Browse Source

Merge branch 'refs/heads/master' into master_fixflow

lanceJiang 9 months ago
parent
commit
72c4daed23

+ 128 - 0
.ai-commit.json

@@ -0,0 +1,128 @@
+{
+    "commit_options": [
+        "--edit"
+    ],
+    "diff_options": [
+        ":!*-lock.json",
+        ":!*.lock",
+        ":!*.sum"
+    ],
+    "http_options": {
+        "verify": false,
+        "connect_timeout": 30,
+        "timeout": 120
+    },
+    "retry": {
+        "times": 3,
+        "sleep": 200
+    },
+    "diff_mark": "<diff>",
+    "type_mark": "<type>",
+    "type_prompt_mark": "<type-prompt>",
+    "type_prompt": "- Use commit type `%s`.",
+    "types": {
+        "auto": "Automatically generate commit type",
+        "feat": "A new feature",
+        "fix": "A bug fix",
+        "docs": "Documentation only changes",
+        "style": "Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)",
+        "refactor": "A code change that neither fixes a bug nor adds a feature",
+        "perf": "A code change that improves performance",
+        "test": "Adding missing tests or correcting existing tests",
+        "build": "Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)",
+        "ci": "Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)",
+        "chore": "Other changes that don't modify src or test files",
+        "revert": "Reverts a previous commit"
+    },
+    "no_edit": false,
+    "no_verify": false,
+    "prompt": "conventional",
+    "generator": "moonshot",
+    "generators": {
+        "bito_cli": {
+            "driver": "bito_cli",
+            "path": "bito",
+            "prompt_filename": "bito.prompt",
+            "parameters": {
+                "cwd": null,
+                "env": null,
+                "input": null,
+                "timeout": 120
+            }
+        },
+        "ernie_bot": {
+            "driver": "ernie_bot",
+            "api_key": "...",
+            "secret_key": "...",
+            "parameters": {
+                "temperature": 0.95,
+                "top_p": 0.8,
+                "penalty_score": 1,
+                "stream": true
+            }
+        },
+        "ernie_bot_turbo": {
+            "driver": "ernie_bot_turbo",
+            "api_key": "...",
+            "secret_key": "...",
+            "parameters": {
+                "temperature": 0.95,
+                "top_p": 0.8,
+                "penalty_score": 1,
+                "stream": true
+            }
+        },
+        "moonshot": {
+            "driver": "moonshot",
+            "api_key": "sk-SYN427v6luITEeMt8l3ZZR1KFaMQrrfVclRJBjgeY68QKZmi",
+            "parameters": {
+                "model": "moonshot-v1-8k",
+                "max_tokens": 600,
+                "temperature": 0,
+                "top_p": 1,
+                "n": 1,
+                "stream": true,
+                "stop": null,
+                "presence_penalty": 0,
+                "frequency_penalty": 0
+            }
+        },
+        "openai": {
+            "driver": "openai",
+            "api_key": "sk-SYN427v6luITEeMt8l3ZZR1KFaMQrrfVclRJBjgeY68QKZmi",
+            "parameters": {
+                "model": "text-davinci-003",
+                "suffix": null,
+                "max_tokens": 600,
+                "temperature": 0,
+                "top_p": 1,
+                "n": 1,
+                "stream": true,
+                "logprobs": null,
+                "echo": false,
+                "stop": null,
+                "presence_penalty": 0,
+                "frequency_penalty": 0,
+                "best_of": 1
+            }
+        },
+        "openai_chat": {
+            "driver": "openai_chat",
+            "api_key": "sk-SYN427v6luITEeMt8l3ZZR1KFaMQrrfVclRJBjgeY68QKZmi",
+            "parameters": {
+                "model": "gpt-3.5-turbo",
+                "max_tokens": 600,
+                "temperature": 0,
+                "top_p": 1,
+                "n": 1,
+                "stream": true,
+                "stop": null,
+                "presence_penalty": 0,
+                "frequency_penalty": 0
+            }
+        }
+    },
+    "prompts": {
+        "conventional": "Here are some best practices for writing commit messages:\n- Write clear, concise, and descriptive messages that explain the changes made in the commit.\n- Use the present tense and active voice in the message, for example, \"Fix bug\" instead of \"Fixed bug.\"\n- Use the imperative mood, which gives the message a sense of command, e.g. \"Add feature\" instead of \"Added feature\"\n- Limit the subject line to 72 characters or less.\n- Capitalize the subject line.\n- Do not end the subject line with a period.\n- Limit the body of the message to 256 characters or less.\n- Use a blank line between the subject and the body of the message.\n- Use the body of the message to provide additional context or explain the reasoning behind the changes.\n- Avoid using general terms like \"update\" or \"change\" in the subject line, be specific about what was updated or changed.\n- Explain, What was done at a glance in the subject line, and provide additional context in the body of the message.\n- Why the change was necessary in the body of the message.\n- The details about what was done in the body of the message.\n- Any useful details concerning the change in the body of the message.\n- Use a hyphen (-) for the bullet points in the body of the message.\n<type-prompt>\nWrite 1 commit messages that accurately summarizes the changes made in the given `git diff` output, following the best practices listed above and the conventional commit format in chinese.\nPlease provide a response in the form of a valid JSON object and do not include \"Output:\", \"Response:\" or anything similar to those two before it, in the following format:\n{\n    \"subject\": \"<type>(<scope>): <subject>\",\n    \"body\": \"<BODY (bullet points)>\"\n}\n\nHere is the output of the `git diff`:\n<diff>"
+    }
+}

+ 1 - 0
package.json

@@ -44,6 +44,7 @@
     "dayjs": "^1.11.7",
     "echarts": "^5.4.2",
     "element-plus": "2.3.4",
+    "event-source-polyfill": "^1.0.31",
     "everright-filter": "^1.1.1",
     "html2canvas": "^1.4.1",
     "js-md5": "^0.7.3",

+ 19 - 1
src/api/system/message.ts

@@ -20,6 +20,14 @@ function getMessageInfo(data: any): AxiosPromise {
 	})
 }
 
+function getMessageMyInfoApi(data: any): AxiosPromise {
+	return request({
+		url: '/sys/message/page-my',
+		method: 'post',
+		data
+	})
+}
+
 function getMessageInfoById(id: any): AxiosPromise {
 	return request({
 		url: '/sys/message/get?id=' + id,
@@ -27,6 +35,14 @@ function getMessageInfoById(id: any): AxiosPromise {
 	})
 }
 
+function readMessageApi(data: any): AxiosPromise {
+	return request({
+		url: '/sys/message/read',
+		method: 'post',
+		data
+	})
+}
+
 /**
  * 扩展配置 - 删除
  */
@@ -41,5 +57,7 @@ export default {
 	getMessage,
 	getMessageInfo,
 	getMessageInfoById,
-	messageDeleteApi
+	messageDeleteApi,
+	getMessageMyInfoApi,
+	readMessageApi
 }

+ 6 - 7
src/components/Chart.vue

@@ -430,6 +430,12 @@ export const colorBase2 = [
 		}
 
 		.overlay {
+			position: absolute;
+			left: 0;
+			top: 0;
+			bottom: 0;
+			right: 0;
+			pointer-events: none;
 			&.overlayTopLevel {
 				pointer-events: unset;
 			}
@@ -447,13 +453,6 @@ export const colorBase2 = [
 					background: #fff;
 				}
 			}
-
-			position: absolute;
-			left: 0;
-			top: 0;
-			bottom: 0;
-			right: 0;
-			pointer-events: none;
 		}
 	}
 }

+ 1 - 1
src/components/packages/theme/formEditor/ConfigTypeComponent.scss

@@ -26,6 +26,7 @@
         }
       }
       @include when(Selected) {
+		    border-color: $primary-color;
         .ER-icon {
           color: $primary-color;
           //path.1{}
@@ -34,7 +35,6 @@
             fill: #BAE3FF;
           }
         }
-        border-color: $primary-color;
       }
       @include when(Disabled) {
         background: #F2F2F2;

+ 13 - 13
src/components/packages/theme/formEditor/Fields.scss

@@ -21,19 +21,6 @@
     justify-content: space-between;
     flex-wrap: wrap;
     li {
-      @include when(new) {
-        &::after {
-          content: 'new';
-          position: absolute;
-          top: -6px;
-          right: 0;
-          color: #fff;
-          background-color: #f00;
-          font-size: 12px;
-          padding: 0 6px;
-          border-radius: 10px;
-        }
-      }
       position: relative;
       border-radius: 4px;
       margin: 4px;
@@ -61,6 +48,19 @@
       &[draggable="true"] {
         cursor: grabbing;
       }
+			@include when(new) {
+				&::after {
+					content: 'new';
+					position: absolute;
+					top: -6px;
+					right: 0;
+					color: #fff;
+					background-color: #f00;
+					font-size: 12px;
+					padding: 0 6px;
+					border-radius: 10px;
+				}
+			}
     }
   }
 }

+ 6 - 6
src/components/packages/theme/formEditor/Main.scss

@@ -17,16 +17,16 @@
     position: relative;
     z-index: 3;
     .ER-icon {
+			border-radius: 4px;
+			width: 24px;
+			height: 24px;
+			display: inline-flex;
+			justify-content: center;
+			align-items: center;
       &:hover {
         color: $primary-color;
         background: #ECF6FF;
       }
-      border-radius: 4px;
-      width: 24px;
-      height: 24px;
-      display: inline-flex;
-      justify-content: center;
-      align-items: center;
     }
   }
   @include e(container) {

+ 9 - 8
src/layout/LayoutLeftMix/index.scss

@@ -31,6 +31,14 @@
         flex: 1;
         .split-item {
 					--el-menu-base-level-padding: 4px;
+					display: flex;
+					flex-direction: column;
+					align-items: center;
+					justify-content: center;
+					height: 70px;
+					line-height: unset;
+					cursor: pointer;
+					transition: all 0.3s ease;
 					&::before {
 						left: 2px;
 						right: 2px;
@@ -41,14 +49,7 @@
 							background-color: inherit;
 						}
 					}
-          display: flex;
-          flex-direction: column;
-          align-items: center;
-          justify-content: center;
-          height: 70px;
-					line-height: unset;
-          cursor: pointer;
-          transition: all 0.3s ease;
+
 					.#{$prefix}pick-icon {
 						//font-size: 18px;
 						margin-right: 0;

+ 58 - 1
src/layout/components/Header/components/Message.vue

@@ -38,9 +38,17 @@
 </template>
 
 <script setup lang="ts">
-import { ref, reactive } from 'vue'
+import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'
 import message from '@/api/system/message'
 import router from '@/router'
+import { EventSourcePolyfill } from 'event-source-polyfill'
+import { ls } from '@/utils'
+import { ElNotification } from 'element-plus'
+const token = ls.get('token')
+const { VITE_APP_BASE_API } = import.meta.env
+const serviceUrlApi = ref(`${VITE_APP_BASE_API}/sys/sse/connect`)
+let eventSource: EventSourcePolyfill | null = null
+
 // noticeList  通知     messageList   消息     todoList   待办
 const tabsConfig = reactive({
 	noticeList: {
@@ -81,6 +89,55 @@ const jumpMessageInfo = () => {
 const jumpMessageDetail = (id: any) => {
 	router.push('/message/list?id=' + id)
 }
+
+onMounted(() => {
+	eventSource = new EventSourcePolyfill(serviceUrlApi.value, {
+		headers: { accessToken: token }
+	})
+
+	eventSource.onmessage = (event: MessageEvent) => {
+		// const data = JSON.parse()
+		console.log('Received message-----:', event)
+
+		const eventType = event.type
+		const notificationTitles: { [key: string]: string } = {
+			message: '消息',
+			notice: '通知',
+			remind: '待办'
+		}
+		const notificationTitle = notificationTitles[eventType] || '您有一条新消息'
+		console.log('Received message:', event.data)
+		// 处理接收到的消息
+		ElNotification({
+			title: notificationTitle,
+			message: event.data,
+			type: 'success',
+			duration: 10000
+		})
+	}
+
+	eventSource.addEventListener('remind', (event: MessageEvent) => {
+		const data = JSON.parse(event.data)
+		console.log('Received remind event:', event)
+		// 处理接收到的提醒消息
+		ElNotification({
+			title: data.title,
+			message: data.content,
+			type: 'success',
+			duration: 10000
+		})
+	})
+
+	eventSource.onerror = (error: any) => {
+		console.error('EventSource failed:', error)
+	}
+})
+
+// onBeforeUnmount(() => {
+// 	if (eventSource) {
+// 		eventSource.close()
+// 	}
+// })
 </script>
 
 <style scoped lang="scss">

+ 70 - 0
src/layout/components/Header/components/Message1.vue

@@ -0,0 +1,70 @@
+<template>
+	<el-popover placement="bottom" :width="310" trigger="click">
+		<template #reference>
+			<div class="menu--message-trigger">
+				<el-tooltip :content="$t('le.message.txt')" effect="dark" placement="bottom">
+					<div class="menu--message menu-item le-hover-effect--bg">
+						<el-badge :value="90" :max="99">
+							<i class="le-iconfont le-notice"></i>
+						</el-badge>
+					</div>
+				</el-tooltip>
+			</div>
+		</template>
+		<ul>
+			<li v-for="(item, idx) in receivedData" :key="idx">{{ item }}</li>
+		</ul>
+	</el-popover>
+</template>
+<script setup>
+import { onMounted, ref, onBeforeUnmount } from 'vue'
+import { ls } from '@/utils'
+const token = ls.get('token')
+const { VITE_APP_BASE_API } = import.meta.env
+// const serviceUrlApi = ref(`${VITE_APP_BASE_API}/sys/sse/connect`);
+const serviceUrlApi = ref(`http://localhost:3000/events`)
+let sseService = ref(null)
+let receivedData = ref([])
+
+// 创建一个新的 EventSource,但首先使用 fetch API 发送带有 Authorization 头的请求
+function connectSSEWithHeaders(url, headers = {}) {
+	return fetch(url, {
+		method: 'GET',
+		headers: headers,
+		cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached
+		mode: 'cors', // no-cors, cors, *same-origin
+		credentials: 'same-origin', // include, *same-origin, omit
+		redirect: 'follow', // manual, *follow, error
+		referrerPolicy: 'no-referrer' // no-referrer, *client
+	})
+		.then(response => {
+			if (!response.ok) {
+				throw new Error('Network response was not ok')
+			}
+			return new EventSource(url)
+		})
+		.catch(error => {
+			console.error('There was a problem with your fetch operation:', error)
+		})
+}
+
+onMounted(() => {
+	connectSSEWithHeaders(serviceUrlApi.value, { accessToken: token }).then(eventSource => {
+		sseService.value = eventSource
+		eventSource.onmessage = function (e) {
+			console.log('后端返回的数据:', e.data)
+			receivedData.value.push(e.data)
+		}
+		eventSource.onerror = function (err) {
+			console.error('EventSource failed:', err)
+		}
+	})
+})
+
+onBeforeUnmount(() => {
+	if (sseService.value) {
+		sseService.value.close()
+		sseService.value = null
+	}
+})
+</script>

+ 145 - 0
src/layout/components/Header/components/Message2.vue

@@ -0,0 +1,145 @@
+<template>
+	<el-popover placement="bottom" :width="310" trigger="click">
+		<template #reference>
+			<div class="menu--message-trigger">
+				<el-tooltip :content="$t('le.message.txt')" effect="dark" placement="bottom">
+					<div class="menu--message menu-item le-hover-effect--bg">
+						<el-badge :value="total" :max="99">
+							<i class="le-iconfont le-notice"></i>
+						</el-badge>
+					</div>
+				</el-tooltip>
+			</div>
+		</template>
+		<el-tabs class="message-tabs" v-model="activeTab">
+			<el-tab-pane v-for="v of tabsConfig" :key="v.name" :name="v.name">
+				<template #label> {{ v.label }}({{ v.list.length }}) </template>
+				<template v-if="v.list.length">
+					<div class="message-list">
+						<div v-for="item of v.list" :key="item.id" class="message-item" @click="jumpMessageDetail(item.id)">
+							<!--<img src="" alt="" class="message-icon" />-->
+							<div class="message-content">
+								<div class="message-title">
+									<span class="txt text-overflow_ellipsis" :title="item.title">{{ item.title }}</span>
+									<span class="message-date">{{ item.createTime }}</span>
+								</div>
+								<span class="message-txt">{{ item.content }}</span>
+							</div>
+						</div>
+						<div class="message-fix-item" @click="jumpMessageInfo">查看更多</div>
+					</div>
+				</template>
+				<template v-else>
+					<LeNoData />
+				</template>
+			</el-tab-pane>
+		</el-tabs>
+	</el-popover>
+</template>
+
+<script setup lang="ts">
+import { ref, reactive } from 'vue'
+import message from '@/api/system/message'
+import router from '@/router'
+// noticeList  通知     messageList   消息     todoList   待办
+const tabsConfig = reactive({
+	noticeList: {
+		name: 'noticeList',
+		label: '通知',
+		list: []
+	},
+	messageList: {
+		name: 'messageList',
+		label: '消息',
+		list: []
+	},
+	todoList: {
+		name: 'todoList',
+		label: '待办',
+		list: []
+	}
+})
+const activeTab = ref('noticeList')
+const total = ref(0)
+message.getMessage().then(res => {
+	let _total = 0
+	Object.keys(tabsConfig).map(key => {
+		if (res[key]) {
+			tabsConfig[key].list = res[key]
+			_total += res[key].length
+		} else {
+			res[key].list = []
+		}
+	})
+	total.value = _total
+})
+
+const jumpMessageInfo = () => {
+	router.push('/message/list')
+}
+
+const jumpMessageDetail = (id: any) => {
+	router.push('/message/list?id=' + id)
+}
+</script>
+
+<style scoped lang="scss">
+.message-list {
+	display: flex;
+	flex-direction: column;
+	max-height: 390px;
+	overflow-y: auto;
+	.message-item {
+		display: flex;
+		align-items: center;
+		padding: 8px 0;
+		border-bottom: 1px solid var(--el-border-color-light);
+		cursor: pointer;
+		&:last-child {
+			border: none;
+		}
+		.message-content {
+			display: flex;
+			flex-direction: column;
+			width: 100%;
+			.message-title {
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				margin-bottom: 5px;
+				font-weight: 600;
+				color: var(--el-text-color-primary);
+			}
+			.message-date {
+				font-size: 12px;
+				color: var(--el-text-color-secondary);
+				margin-left: 10px;
+				font-weight: 400;
+				flex-shrink: 0;
+			}
+			.message-txt {
+				//margin-bottom: 5px;
+				color: var(--el-text-color-regular);
+			}
+		}
+	}
+	.message-fix-item {
+		// flex 居中
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		height: 40px;
+		cursor: pointer;
+	}
+}
+.menu--message-trigger {
+	height: 100%;
+}
+.menu--message {
+	width: 40px;
+	justify-content: center;
+	//.le-notice {
+	//.le-iconfont {
+	//}
+}
+</style>

+ 21 - 29
src/layout/components/Tabs/index.vue

@@ -393,6 +393,9 @@ $transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), border 0s, color 0.1
 							padding: 0 20px;
 							//padding: 0 !important;
 							border: 0;
+							&:hover {
+								color: var(--el-color-primary);
+							}
 
 							.le-tabs__item {
 								height: 100%;
@@ -426,10 +429,6 @@ $transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), border 0s, color 0.1
 								}
 							}
 
-							&:hover {
-								color: var(--el-color-primary);
-							}
-
 							&.is-active {
 								color: var(--el-color-primary) !important;
 								background: var(--el-color-primary-light-9);
@@ -456,6 +455,14 @@ $transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), border 0s, color 0.1
 						.el-tabs__nav {
 							.el-tabs__item {
 								margin-left: -12px;
+								margin-top: 6px;
+								//height: 36px;
+								height: calc(var(--el-tabs-header-height) - 6px);
+								mask: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANoAAAAkCAYAAADvhSSyAAAACXBIWXMAAAsTAAALEwEAmpwYAAABbUlEQVR4nO3d4U3CUBSG4beJA9QNcAJhAtnAOoGOwCaOoBvoCDgBOIHdQDbAH7cJMaHtxcJB6/skJ6Thptw/H+cSktOCn5kCc+AWKJtraaxqYA28A8/N9cktgE9ga1n/tBYcqDhw/QtQHfoh0gitgdkpbrzg/N8klvWbKruz5Xa0CbAi/R6TtDMjdbdOF5k3qzBk0j4VRwzazbC9SKN1nbMo9+j4QTo+SvpuA1z2LcoN2nbYXqRR681R7tFR0gAGTQpg0KQABk0KYNCkAAZNCmDQpAAGTQpg0KQABk0KYNCkAAZNCmDQpAAGTQpg0KQABk0KYNCkAAZNGq4kjTRolRM0x31L3Sb0TMLKCZqTiaVu9/QErW+oyAQHp0p9NqRBqnXbgq6glcATdjQpRw1ctb3ZFrQSeAQejr8fabRegbvcxXPScfHcDxCwrL9YK/Y0qILdgwSnpNHfHhWl4ZbAW/O6LEgplHRC/mEtBfgClkhxraFbr7gAAAAASUVORK5CYII=);
+								//mask-size: 100% 100%;
+								mask-size: 100% calc(100% + 1px);
+								mask-repeat: no-repeat;
+								//mask-position: bottom;
 								/*border-bottom: 0;
                 &::before {
                   display: none;
@@ -470,15 +477,6 @@ $transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), border 0s, color 0.1
 									color: var(--el-color-primary-light-3);
 								}
 
-								margin-top: 6px;
-								//height: 36px;
-								height: calc(var(--el-tabs-header-height) - 6px);
-								mask: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANoAAAAkCAYAAADvhSSyAAAACXBIWXMAAAsTAAALEwEAmpwYAAABbUlEQVR4nO3d4U3CUBSG4beJA9QNcAJhAtnAOoGOwCaOoBvoCDgBOIHdQDbAH7cJMaHtxcJB6/skJ6Thptw/H+cSktOCn5kCc+AWKJtraaxqYA28A8/N9cktgE9ga1n/tBYcqDhw/QtQHfoh0gitgdkpbrzg/N8klvWbKruz5Xa0CbAi/R6TtDMjdbdOF5k3qzBk0j4VRwzazbC9SKN1nbMo9+j4QTo+SvpuA1z2LcoN2nbYXqRR681R7tFR0gAGTQpg0KQABk0KYNCkAAZNCmDQpAAGTQpg0KQABk0KYNCkAAZNCmDQpAAGTQpg0KQABk0KYNCkAAZNGq4kjTRolRM0x31L3Sb0TMLKCZqTiaVu9/QErW+oyAQHp0p9NqRBqnXbgq6glcATdjQpRw1ctb3ZFrQSeAQejr8fabRegbvcxXPScfHcDxCwrL9YK/Y0qILdgwSnpNHfHhWl4ZbAW/O6LEgplHRC/mEtBfgClkhxraFbr7gAAAAASUVORK5CYII=);
-								//mask-size: 100% 100%;
-								mask-size: 100% calc(100% + 1px);
-								mask-repeat: no-repeat;
-								//mask-position: bottom;
-
 								&.is-active {
 									background: var(--el-color-primary-light-9);
 
@@ -503,7 +501,10 @@ $transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), border 0s, color 0.1
 								border: 1px solid var(--el-border-color);
 								border-radius: 4px;
 								margin-left: 4px;
-
+								margin-top: 6px;
+								//height: 36px;
+								height: calc(var(--el-tabs-header-height) - 12px);
+								padding: 0 4px;
 								&:first-child {
 									margin-left: 0;
 								}
@@ -513,24 +514,18 @@ $transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), border 0s, color 0.1
 									border-color: var(--el-color-primary-light-7);
 								}
 
-								margin-top: 6px;
-								//height: 36px;
-								height: calc(var(--el-tabs-header-height) - 12px);
-								padding: 0 4px;
 								/*.le-tabs__item {
                   padding: 0 4px;
                 }*/
 								&.is-active {
 									background-color: var(--el-color-primary-light-9);
-
+									color: var(--el-color-primary);
+									border-color: var(--el-color-primary-light-5);
 									.is-icon-close {
 										&:hover {
 											background-color: var(--el-color-primary);
 										}
 									}
-
-									color: var(--el-color-primary);
-									border-color: var(--el-color-primary-light-5);
 								}
 							}
 						}
@@ -564,19 +559,18 @@ $transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), border 0s, color 0.1
 								}
 
 								&:hover {
+									//background: var(--el-color-primary-light-9);
+									background: var(--el-border-color-light);
+									//color: var(--el-color-primary-light-3);
 									&::before {
 										width: 100%;
 										transition: $transition;
 									}
-
-									//background: var(--el-color-primary-light-9);
-									background: var(--el-border-color-light);
-									//color: var(--el-color-primary-light-3);
 								}
 
 								&.is-active {
 									background: var(--el-color-primary-light-9);
-
+									color: var(--el-color-primary);
 									&::before {
 										width: 100%;
 										border-bottom-color: var(--el-color-primary);
@@ -587,8 +581,6 @@ $transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1), border 0s, color 0.1
 											background-color: var(--el-color-primary);
 										}
 									}
-
-									color: var(--el-color-primary);
 								}
 							}
 						}

+ 3 - 3
src/styles/element-plus.scss

@@ -51,10 +51,10 @@
 	display: table-cell !important;
 }
 .el-table {
+	//--el-table-header-bg-color: #f6faff;
+	background-color: var(--el-bg-color);
 	&.el-table--enable-row-transition .el-table__body td.el-table__cell {
 		//background-color: var(--el-bg-color);
 		transition: unset;
 	}
-	//--el-table-header-bg-color: #f6faff;
-	background-color: var(--el-bg-color);
-}
+}

+ 1 - 1
src/styles/lance-element-ui.scss

@@ -71,10 +71,10 @@
 		&.is-disabled {
 			.el-input-number__decrease,
 			.el-input-number__increase {
+				color: $le-color_5;
 				&:hover {
 					color: $le-color_5;
 				}
-				color: $le-color_5;
 			}
 		}
 		.el-input-number__decrease,

+ 6 - 5
src/styles/lance-element/draggableNest.scss

@@ -1,5 +1,8 @@
 @import "../variables.scss";
 .#{$prefix}draggable-nest {
+	flex: 1;
+	width: 100%;
+	overflow-y: auto;
 	.flip-list {
 		transition: all 0.3s ease-in-out;
 	}
@@ -25,9 +28,7 @@
 		//box-shadow: 1px 1px 5px 2px rgba(0,0,0,.15);
 		box-shadow: inset 0 0 6px -2px rgba(0, 0, 0, 0.15);
 	}
-	flex: 1;
-	width: 100%;
-	overflow-y: auto;
+
 	&-item {
 		padding-left: 12px;
 		&:hover {
@@ -48,14 +49,14 @@
 			&.disabled {
 				color: var(--el-text-color-disabled);
 				cursor: not-allowed;
+				opacity: unset;
+				box-shadow: none;
 				&.ghost {
 					background: unset;
 				}
 				& > .dragEl {
 					cursor: not-allowed;
 				}
-				opacity: unset;
-				box-shadow: none;
 				.disabled_fixed {
 					width: 28px;
 					margin-left: auto;

+ 7 - 7
src/styles/lance-element/noData.scss

@@ -1,6 +1,11 @@
 @import "../variables.scss";
 // NoData 样式
 .#{$prefix}no-data {
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+	padding: 20px 0;
   &.small {
 		.#{$prefix}no-data__img {
 			//width: 108px;
@@ -14,17 +19,12 @@
 			font-size: 120px;
     }
   }
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  align-items: center;
+
   &--full {
     width: 100%;
     height: 100%;
   }
 
-  padding: 20px 0;
-
   &__img {
     font-size: 80px;
     pointer-events: none;
@@ -35,4 +35,4 @@
     line-height: initial;
 		font-size: 12px;
   }
-}
+}

+ 3 - 3
src/styles/lance-element/text.scss

@@ -1,6 +1,9 @@
 @import "../variables.scss";
 // Text 样式
 .#{$prefix}text {
+	//font-size: 14px;
+	font-size: var(--el-font-size-base);
+	display: inline-flex;
 	&-wrap {
 	}
 	/*.is-line-clamp {
@@ -8,9 +11,6 @@
 		-webkit-box-orient: vertical;
 		overflow: hidden;
 	}*/
-	//font-size: 14px;
-	font-size: var(--el-font-size-base);
-	display: inline-flex;
 	.action-icon {
 		margin-left: 2px;
 		padding-top: 4px;

+ 1 - 1
src/views/approve/components/approvedContent.vue

@@ -619,7 +619,7 @@ watch(
 		display: flex;
 		flex-direction: column;
 		position: relative;
-		z-index: 0;
+		//z-index: 0;
 		height: 100%;
 		overflow: hidden;
 	}

+ 2 - 2
src/views/dashboard/index.vue

@@ -505,13 +505,13 @@ const tableOpts = ref({
 	}
 }
 :deep(.info-wrap) {
+	min-height: 120px;
+	background: var(--el-bg-color) linear-gradient(120deg, var(--el-color-primary-light-9) 10%, var(--el-bg-color)) no-repeat;
 	.el-card__body {
 		display: flex;
 		align-items: center;
 		justify-content: center;
 	}
-	min-height: 120px;
-	background: var(--el-bg-color) linear-gradient(120deg, var(--el-color-primary-light-9) 10%, var(--el-bg-color)) no-repeat;
 	.header {
 		//font-size: var(--el-font-size-bigger);
 		font-size: 18px;

+ 50 - 9
src/views/message/list/my.vue

@@ -14,8 +14,8 @@
 				:columns="activeColumns"
 			>
 				<template #toolLeft>
-					<el-button plain type="primary">全部标记已读</el-button>
-					<el-button plain :icon="Delete" :disabled="curSelectionRows.length === 0" @click="batch_del" type="danger">删除</el-button>
+					<el-button plain type="primary" @click="readAll">一键已读</el-button>
+					<el-button plain :icon="Delete" :disabled="curSelectionRows.length === 0" type="danger" @click="batch_del">删除</el-button>
 				</template>
 
 				<template #categorySlot="scope">
@@ -24,6 +24,17 @@
 					<el-tag v-if="scope.row.category === 2" size="small" type="warning" effect="plain">待办通知</el-tag>
 				</template>
 
+				<template #viewedSlot="scope">
+					<el-tag
+						v-if="scope.row.viewed !== undefined && scope.row.viewed !== null"
+						:type="getViewedType(scope.row.viewed)"
+						size="small"
+						effect="plain"
+					>
+						{{ getViewedLabel(scope.row.viewed) }}
+					</el-tag>
+				</template>
+
 				<template #actionSlot="{ row }">
 					<div class="flex flex-align-pack-center">
 						<LeIcon class="text-lg text-icon-color cursor-pointer" icon-class="icon-processInfo-icons--view-light" @click="openDetail(row)" />
@@ -34,7 +45,7 @@
 			</LeTable>
 		</div>
 
-		<message-detail v-if="visibleDetail" v-model="visibleDetail" :message-id="currentId" @closed="visibleDetail = false"></message-detail>
+		<message-detail v-if="visibleDetail" v-model="visibleDetail" :message-id="currentId" @closed="queryList"></message-detail>
 	</div>
 </template>
 <script lang="tsx" setup>
@@ -48,15 +59,15 @@ import { ElMessage, ElMessageBox } from 'element-plus'
 
 const route = useRoute()
 const visibleDetail = ref(false) // 权限设置弹窗显示隐藏
-const currentId = ref(null)
+const currentId = ref('')
 
 // 表格搜索条件
 const forms = ref([
 	{
 		prop: 'title',
-		label: '标题:',
+		label: '消息标题:',
 		itemType: 'input',
-		placeholder: '请输入标题'
+		placeholder: '请输入消息标题'
 	},
 	{
 		prop: 'createBy',
@@ -71,7 +82,7 @@ const queryList = async () => {
 	const { options, searchParams } = tableOpts
 	options.loading = true
 	try {
-		const { records: list, total } = await message.getMessageInfo(searchParams)
+		const { records: list, total } = await message.getMessageMyInfoApi(searchParams)
 		tableOpts.total = total
 		tableOpts.list = list
 	} catch {
@@ -88,7 +99,7 @@ const queryList = async () => {
 const columns = [
 	{
 		prop: 'title',
-		label: '标题',
+		label: '消息标题',
 		minWidth: 80
 	},
 	{
@@ -104,6 +115,13 @@ const columns = [
 		label: '发布人',
 		minWidth: 100
 	},
+	{
+		prop: 'viewed',
+		label: '查看状态',
+		slots: {
+			default: 'viewedSlot'
+		}
+	},
 	{
 		prop: 'createTime',
 		label: '发布时间',
@@ -174,12 +192,35 @@ const batch_del = () => {
 		deleteItem(ids)
 	})
 }
+const markAsRead = async (id: string | undefined) => {
+	await message.readMessageApi({ id })
+}
 
-const openDetail = (row: any) => {
+const openDetail = async (row: any) => {
+	if (Number(row.viewed) === 0) {
+		await markAsRead(row.id)
+	}
 	currentId.value = row.id
 	visibleDetail.value = true
 }
 
+const readAll = async () => {
+	try {
+		await markAsRead(undefined)
+		queryList()
+	} catch (error) {
+		console.error('Error marking all messages as read:', error)
+	}
+}
+
+const getViewedType = viewed => {
+	return Number(viewed) === 0 ? 'warning' : 'success'
+}
+
+const getViewedLabel = viewed => {
+	return Number(viewed) === 0 ? '未查看' : '已查看'
+}
+
 nextTick(() => {
 	queryList()
 })