AaronBruin 2 hari lalu
induk
melakukan
2b28e71f70
1 mengubah file dengan 87 tambahan dan 14 penghapusan
  1. 87 14
      pages/index/home.vue

+ 87 - 14
pages/index/home.vue

@@ -2,6 +2,7 @@
 	<view class="notice-board">
 		<view class="board-header">
 			<view class="card_logo" @click="linkSet">
+				<!-- <view class="card_logo"> -->
 				<image class="logo_image" src="/static/logo.png" mode=""></image>
 				<view class="logo_title">观山湖区疾控中心</view>
 			</view>
@@ -34,7 +35,7 @@
 					</view>
 					<view class="table-cell time">{{ formatTime(item.createTime) }}</view>
 					<view class="table-cell time">{{ formatTime(item.outTime) }}</view>
-					<view class="table-cell status">
+					<view class="table-cell status" style="padding: 0rpx;">
 						<view class="status-tag" :class="`status-${getClass(item.status)}`">
 							{{ getStatusText(item) }}
 						</view>
@@ -52,7 +53,7 @@
 					</view>
 					<view class="table-cell time">{{ formatTime(item.createTime) }}</view>
 					<view class="table-cell time">{{ formatTime(item.outTime) }}</view>
-					<view class="table-cell status">
+					<view class="table-cell status" style="padding: 0rpx;">
 						<view class="status-tag" :class="`status-${getClass(item.status)}`">
 							{{ getStatusText(item) }}
 						</view>
@@ -157,6 +158,9 @@
 				heartbeatRate: 0,
 				isSend: true,
 				reconnectionNum: 0,
+				TTSSpeech: null,
+				speechQueue: [], // 语音队列
+				isSpeaking: false, // 是否正在播放语音
 			}
 		},
 		computed: {
@@ -221,6 +225,22 @@
 				})
 			}
 		},
+		onLoad() {
+			//#ifdef APP
+			// 引入插件
+			this.TTSSpeech = uni.requireNativePlugin('MT-TTS-Speech');
+			// 初始化TTS引擎
+			this.TTSSpeech.init((status) => { // 👈 同样移除 : number
+				if (status === 0) {
+					console.log('TTS引擎初始化成功');
+				} else {
+					console.error('TTS引擎初始化失败,状态码:', status)
+				}
+			}, 'com.iflytek.speechcloud')
+			this.TTSSpeech.setPitch(50)
+			this.TTSSpeech.setSpeed(50)
+			//#endif
+		},
 		mounted() {
 			this.reconnectionNum = 0
 			// 每秒更新当前时间
@@ -269,6 +289,54 @@
 			}
 		},
 		methods: {
+			// 将文本添加到队列
+			addToSpeechQueue(textValue) {
+				if (textValue && typeof textValue === 'string') {
+					this.speechQueue.push(textValue);
+					// 如果没有正在播放,则开始播放
+					if (!this.isSpeaking) {
+						this.processSpeechQueue();
+					}
+				} else {
+					console.warn('Invalid text value for speech:', textValue);
+				}
+			},
+			// 处理语音队列
+			async processSpeechQueue() {
+				if (this.speechQueue.length === 0) {
+					this.isSpeaking = false;
+					return;
+				}
+				this.isSpeaking = true;
+				const textToSpeak = this.speechQueue.shift(); // 取出队列第一个元素
+				try {
+					// 等待当前语音播放完成 (通过 onDone 回调)
+					await this.speak(textToSpeak);
+				} catch (error) {
+					console.error('TTS speak error for text:', textToSpeak, error);
+					// 即使当前项播放失败,也继续处理队列中的下一个
+				} finally {
+					this.processSpeechQueue();
+				}
+			},
+			// 执行实际的语音播放 (返回 Promise)
+			speak(textValue) {
+				return new Promise((resolve, reject) => {
+					if (!this.TTSSpeech) {
+						reject(new Error('TTS engine not initialized.'));
+						return;
+					}
+					// 监听 TTS 播放结束事件
+					this.TTSSpeech.onDone(() => {
+						resolve(); // 播放完成,Promise 成功
+					});
+					// 尝试启动语音播放
+					const speakOptions = {
+						text: textValue,
+					};
+					this.TTSSpeech.speak(speakOptions);
+				});
+			},
 			keyboardheightchange() {
 				uni.onKeyboardHeightChange(res => {
 					this.keyboardHeight = res.height
@@ -350,7 +418,6 @@
 					}
 					try {
 						const data = JSON.parse(res.data);
-						// console.log('收到消息:', data);
 						this.handleMessage(data);
 					} catch (e) {
 						console.warn('非 JSON 消息,已忽略', res.data);
@@ -617,6 +684,10 @@
 						case 'delete':
 							this.batchRemove(data.data);
 							break;
+						case 'msg':
+							// 使用队列播放语音
+							this.addToSpeechQueue(data.msg)
+							break;
 						default:
 							console.warn('未知操作类型:', action);
 					}
@@ -1128,7 +1199,9 @@
 
 	.table-cell {
 		padding: 24rpx 16rpx;
-		font-size: 50rpx;
+		/* font-size: 50rpx; */
+		font-size: 66rpx;
+		font-weight: bold;
 		text-align: center;
 		color: #333;
 		display: flex;
@@ -1139,7 +1212,8 @@
 
 	.cell {
 		padding: 24rpx 16rpx;
-		font-size: 50rpx;
+		/* font-size: 50rpx; */
+		font-size: 60rpx;
 		text-align: center;
 		color: #333;
 	}
@@ -1215,25 +1289,25 @@
 	.status-observing {
 		background-color: #9dd6ff;
 		color: #007bff;
-		border: 2rpx solid #48a0ff;
+		border: 6rpx solid #007bff;
 	}
 
 	.status-completed {
 		background-color: #e8f5e8;
 		color: #28a745;
-		border: 2rpx solid #8bc34a;
+		border: 6rpx solid #28a745;
 	}
 
 	.status-warning {
 		background-color: #ffebee;
 		color: #ff0000;
-		border: 2rpx solid #ef9a9a;
+		border: 6rpx solid #ff0000;
 	}
 
 	.status-hasleft {
 		background-color: #fff2e8;
 		color: #fa8c16;
-		border: 2rpx solid #ffbb96;
+		border: 6rpx solid #fa8c16;
 	}
 
 	.item-observing {
@@ -1258,11 +1332,10 @@
 		display: flex;
 		align-items: center;
 		justify-content: center;
-		padding: 8rpx 20rpx;
-		border-radius: 32rpx;
-		font-size: 48rpx;
-		font-weight: 500;
-		width: calc(100% - 20rpx);
+		border-radius: 50rpx;
+		font-size: 60rpx;
+		font-weight: bold;
+		width: 80%;
 	}
 
 	.empty-tip {