Kaynağa Gözat

feat(components): 重构消息组件

- 移除消息组件中的el-tabs和el-tab-pane标签
- 替换为简单的ul和li标签展示消息列表
- 添加sse连接逻辑,用于实时接收消息
- 移除原有的tabsConfig和activeTab状态
- 移除原有的跳转逻辑和消息列表请求逻辑
- 添加onMounted和onBeforeUnmount生命周期钩子
- 添加connectSSEWithHeaders函数用于创建EventSource连接
luoyali 9 ay önce
ebeveyn
işleme
767ec2429a
1 değiştirilmiş dosya ile 49 ekleme ve 124 silme
  1. 49 124
      src/layout/components/Header/components/Message.vue

+ 49 - 124
src/layout/components/Header/components/Message.vue

@@ -4,142 +4,67 @@
 			<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">
+						<el-badge :value="90" :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>
+		<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([])
 
-<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 = []
-		}
+// 创建一个新的 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
 	})
-	total.value = _total
-})
-
-const jumpMessageInfo = () => {
-	router.push('/message/list')
+		.then(response => {
+			if (!response.ok) {
+				throw new Error('网络响应失败')
+			}
+			return new EventSource(url)
+		})
+		.catch(error => {
+			console.error('There was a problem with your fetch operation:', error)
+		})
 }
 
-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;
+onMounted(() => {
+	connectSSEWithHeaders(serviceUrlApi.value, { accessToken: token }).then(eventSource => {
+		sseService.value = eventSource
+		eventSource.onmessage = function (e) {
+			console.log('后端返回的数据:', e.data)
+			receivedData.value.push(e.data)
 		}
-		.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);
-			}
+		eventSource.onerror = function (err) {
+			console.error('EventSource failed:', err)
 		}
+	})
+})
+
+onBeforeUnmount(() => {
+	if (sseService.value) {
+		sseService.value.close()
+		sseService.value = null
 	}
-	.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>
+})
+</script>