1313 >
1414 <v-card-text >
1515 <div class =" urgent-title mb-6" >
16- {{ notification ?.content?.message || "无内容" }}
16+ {{ currentNotification ?.content?.message || "无内容" }}
1717 </div >
1818
1919 <!-- 发送者信息(使用 Vuetify Card) -->
4545 size =" small"
4646 >
4747 <v-icon left size =" 16" > mdi-clock </v-icon >
48- {{ formatTime(notification ?.timestamp) }}
48+ {{ formatTime(currentNotification ?.timestamp) }}
4949 </v-chip >
5050 </v-card-text >
5151 </v-card >
5252
53+ <!-- 多通知导航 -->
54+ <div v-if =" hasMultipleNotifications" class =" navigation-controls mt-6" >
55+ <v-card variant =" flat" color =" rgba(255,255,255,0.1)" >
56+ <v-card-text class =" text-center" >
57+ <div class =" notification-counter mb-3" >
58+ <v-chip color =" white" variant =" flat" size =" small" >
59+ {{ notificationCountText }}
60+ </v-chip >
61+ </div >
62+ <div class =" navigation-buttons" >
63+ <v-btn
64+ :disabled =" currentIndex === 0"
65+ color =" white"
66+ variant =" outlined"
67+ size =" small"
68+ @click =" previousNotification"
69+ >
70+ <v-icon > mdi-chevron-left </v-icon >
71+ 上一个
72+ </v-btn >
73+ <v-btn
74+ :disabled =" currentIndex === notificationQueue.length - 1"
75+ color =" white"
76+ variant =" outlined"
77+ size =" small"
78+ class =" ml-2"
79+ @click =" nextNotification"
80+ >
81+ 下一个
82+ <v-icon > mdi-chevron-right </v-icon >
83+ </v-btn >
84+ </div >
85+ </v-card-text >
86+ </v-card >
87+ </div >
88+
5389 <!-- 操作按钮 -->
5490 <div class =" mt-8" >
5591 <v-btn color =" white" size =" large" variant =" flat" @click =" close" >
@@ -76,14 +112,32 @@ export default {
76112 data () {
77113 return {
78114 visible: false ,
79- notification: null ,
115+ notificationQueue: [], // 通知队列
116+ currentIndex: 0 , // 当前显示的通知索引
80117 autoCloseTimer: null ,
81118 urgentSoundTimer: null ,
82119 };
83120 },
84121 computed: {
122+ // 当前显示的通知
123+ currentNotification () {
124+ return this .notificationQueue [this .currentIndex ] || null ;
125+ },
126+ // 队列中是否有通知
127+ hasNotifications () {
128+ return this .notificationQueue .length > 0 ;
129+ },
130+ // 是否有多个通知
131+ hasMultipleNotifications () {
132+ return this .notificationQueue .length > 1 ;
133+ },
134+ // 通知计数文本
135+ notificationCountText () {
136+ if (! this .hasMultipleNotifications ) return " " ;
137+ return ` ${ this .currentIndex + 1 } / ${ this .notificationQueue .length } ` ;
138+ },
85139 isUrgent () {
86- return this .notification ? .content ? .isUrgent || false ;
140+ return this .currentNotification ? .content ? .isUrgent || false ;
87141 },
88142 urgencyColor () {
89143 return this .isUrgent ? " red darken-2" : " blue darken-2" ;
@@ -101,18 +155,20 @@ export default {
101155 },
102156 senderName () {
103157 const senderInfo =
104- this .notification ? .senderInfo || this .notification ? .content ? .senderInfo ;
158+ this .currentNotification ? .senderInfo ||
159+ this .currentNotification ? .content ? .senderInfo ;
105160 if (! senderInfo) return " 未知发送者" ;
106161
107162 return senderInfo .deviceName || senderInfo .deviceType || " 未知设备" ;
108163 },
109164 deviceType () {
110165 const senderInfo =
111- this .notification ? .senderInfo || this .notification ? .content ? .senderInfo ;
166+ this .currentNotification ? .senderInfo ||
167+ this .currentNotification ? .content ? .senderInfo ;
112168 return senderInfo? .deviceType || " 未知类型" ;
113169 },
114170 targetDevices () {
115- return this .notification ? .content ? .targetDevices || [];
171+ return this .currentNotification ? .content ? .targetDevices || [];
116172 },
117173 },
118174 beforeUnmount () {
@@ -125,23 +181,39 @@ export default {
125181 },
126182 methods: {
127183 show (notificationData ) {
128- this . notification = notificationData;
129- this . visible = true ;
130-
131- // 发送显示回执
132- this . sendDisplayedReceipt ( );
133-
134- // 清除之前的自动关闭定时器
135- if ( this . autoCloseTimer ) {
136- clearTimeout ( this . autoCloseTimer ) ;
184+ // 检查是否已存在相同的通知(避免重复)
185+ const existingIndex = this . notificationQueue . findIndex (
186+ ( n ) =>
187+ n . content ? . notificationId === notificationData . content ? . notificationId
188+ );
189+
190+ if (existingIndex !== - 1 ) {
191+ console . log ( " 通知已存在,跳过添加 " );
192+ return ;
137193 }
138194
139- // 播放统一的提示音
140- this .playNotificationSound ( );
195+ // 添加到队列
196+ this .notificationQueue . push (notificationData );
141197
142- // 如果是加急通知,启动定时音效
143- if (this .isUrgent ) {
144- this .startUrgentSound ();
198+ // 如果当前没有显示通知,显示第一个
199+ if (! this .visible ) {
200+ this .currentIndex = this .notificationQueue .length - 1 ; // 显示最新的通知
201+ this .visible = true ;
202+ this .sendDisplayedReceipt ();
203+ this .playNotificationSound ();
204+
205+ // 如果是加急通知,启动定时音效
206+ if (this .isUrgent ) {
207+ this .startUrgentSound ();
208+ }
209+ } else {
210+ // 如果已经有通知在显示,新通知是紧急的话优先显示
211+ if (notificationData .content ? .isUrgent && ! this .isUrgent ) {
212+ this .currentIndex = this .notificationQueue .length - 1 ;
213+ this .sendDisplayedReceipt ();
214+ this .playNotificationSound ();
215+ this .startUrgentSound ();
216+ }
145217 }
146218 },
147219 close () {
@@ -153,24 +225,58 @@ export default {
153225 console .warn (" 发送已读回执失败:" , error);
154226 }
155227
156- this .closeWithoutRead ();
228+ // 显示已读消息提示,便于设备端重新查看
229+ if (this .currentNotification ? .content ? .message ) {
230+ const notificationType = this .isUrgent ? " 紧急通知" : " 通知" ;
231+ if (this .isUrgent ) {
232+ this .$message ? .error (
233+ notificationType,
234+ ` ${ this .currentNotification .content .message } `
235+ );
236+ } else {
237+ this .$message ? .info (
238+ notificationType,
239+ ` ${ this .currentNotification .content .message } `
240+ );
241+ }
242+ }
243+
244+ // 从队列中移除当前通知
245+ if (this .notificationQueue .length > 0 ) {
246+ this .notificationQueue .splice (this .currentIndex , 1 );
247+
248+ // 调整当前索引
249+ if (this .currentIndex >= this .notificationQueue .length ) {
250+ this .currentIndex = Math .max (0 , this .notificationQueue .length - 1 );
251+ }
252+
253+ // 如果还有通知,显示下一个;否则关闭
254+ if (this .notificationQueue .length > 0 ) {
255+ this .sendDisplayedReceipt ();
256+ // 如果新的当前通知是紧急的,启动音效
257+ if (this .isUrgent ) {
258+ this .startUrgentSound ();
259+ } else {
260+ this .stopUrgentSound ();
261+ }
262+ } else {
263+ this .closeWithoutRead ();
264+ }
265+ }
157266 },
158267 // 关闭通知但不发送已读回执(用于程序异常或强制关闭)
159268 closeWithoutRead () {
160269 // 立即关闭弹框
161270 this .visible = false ;
162- this .notification = null ;
271+ this .notificationQueue = [];
272+ this .currentIndex = 0 ;
163273
164274 if (this .autoCloseTimer ) {
165275 clearTimeout (this .autoCloseTimer );
166276 this .autoCloseTimer = null ;
167277 }
168278
169- // 停止加急音效定时器
170- if (this .urgentSoundTimer ) {
171- clearInterval (this .urgentSoundTimer );
172- this .urgentSoundTimer = null ;
173- }
279+ this .stopUrgentSound ();
174280 },
175281 formatTime (timestamp ) {
176282 if (! timestamp) return " " ;
@@ -230,12 +336,12 @@ export default {
230336 // 发送显示回执
231337 sendDisplayedReceipt () {
232338 try {
233- if (this .$refs .eventSender && this .notification ? .eventId ) {
339+ if (this .$refs .eventSender && this .currentNotification ? .eventId ) {
234340 this .$refs .eventSender .sendDisplayedReceipt (
235341 {},
236- this .notification .content .notificationId
342+ this .currentNotification .content .notificationId
237343 );
238- console .log (" 已发送显示回执:" , this .notification .eventId );
344+ console .log (" 已发送显示回执:" , this .currentNotification .eventId );
239345 }
240346 } catch (error) {
241347 console .warn (" 发送显示回执失败:" , error);
@@ -244,35 +350,65 @@ export default {
244350 // 发送已读回执
245351 sendReadReceipt () {
246352 try {
247- if (this .$refs .eventSender && this .notification ? .eventId ) {
353+ if (this .$refs .eventSender && this .currentNotification ? .eventId ) {
248354 this .$refs .eventSender .sendReadReceipt (
249355 {},
250- this .notification .content .notificationId
356+ this .currentNotification .content .notificationId
251357 );
252- console .log (" 已发送已读回执:" , this .notification .eventId );
358+ console .log (" 已发送已读回执:" , this .currentNotification .eventId );
253359 }
254360 } catch (error) {
255361 console .warn (" 发送已读回执失败:" , error);
256362 }
257363 },
364+ // 导航到上一个通知
365+ previousNotification () {
366+ if (this .currentIndex > 0 ) {
367+ this .currentIndex -- ;
368+ this .sendDisplayedReceipt ();
369+
370+ // 根据新通知的紧急程度调整音效
371+ if (this .isUrgent ) {
372+ this .startUrgentSound ();
373+ } else {
374+ this .stopUrgentSound ();
375+ }
376+ }
377+ },
378+ // 导航到下一个通知
379+ nextNotification () {
380+ if (this .currentIndex < this .notificationQueue .length - 1 ) {
381+ this .currentIndex ++ ;
382+ this .sendDisplayedReceipt ();
383+
384+ // 根据新通知的紧急程度调整音效
385+ if (this .isUrgent ) {
386+ this .startUrgentSound ();
387+ } else {
388+ this .stopUrgentSound ();
389+ }
390+ }
391+ },
258392 // 启动加急通知的定时音效
259393 startUrgentSound () {
260- // 清除之前的定时器
261- if (this .urgentSoundTimer ) {
262- clearInterval (this .urgentSoundTimer );
263- }
394+ this .stopUrgentSound (); // 先清除之前的定时器
264395
265396 // 每秒播放一次提示音
266397 this .urgentSoundTimer = setInterval (() => {
267398 if (this .visible && this .isUrgent ) {
268399 this .playNotificationSound ();
269400 } else {
270- // 如果弹框已关闭或不再是加急状态,停止音效
271- clearInterval (this .urgentSoundTimer );
272- this .urgentSoundTimer = null ;
401+ this .stopUrgentSound ();
273402 }
274403 }, 1000 );
275404 },
405+ // 停止加急音效
406+ stopUrgentSound () {
407+ if (this .urgentSoundTimer ) {
408+ clearInterval (this .urgentSoundTimer );
409+ this .urgentSoundTimer = null ;
410+ }
411+ },
276412 },
277413};
278414< / script>
@@ -341,6 +477,21 @@ export default {
341477 gap: 16px ;
342478}
343479
480+ .navigation - controls {
481+ backdrop- filter: blur (10px );
482+ }
483+
484+ .notification - counter {
485+ color: white;
486+ font- weight: 600 ;
487+ }
488+
489+ .navigation - buttons {
490+ display: flex;
491+ justify- content: center;
492+ gap: 8px ;
493+ }
494+
344495/* 动画效果 */
345496@keyframes urgentPulse {
346497 0 % ,
0 commit comments