From 41dc2c525153dc368c23b35c7973f497a72d48dc Mon Sep 17 00:00:00 2001 From: Sunwuyuan Date: Sat, 7 Mar 2026 14:07:05 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E9=BA=A6=E5=85=8B?= =?UTF-8?q?=E9=A3=8E=E6=9D=83=E9=99=90=E7=8A=B6=E6=80=81=E6=8F=90=E7=A4=BA?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E5=99=AA=E9=9F=B3=E7=9B=91=E6=B5=8B?= =?UTF-8?q?=E4=BD=93=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/NoiseMonitorDetail.vue | 44 +++++++++++++ src/components/TimeCard.vue | 93 ++++++++++++++++++++------- 2 files changed, 113 insertions(+), 24 deletions(-) diff --git a/src/components/NoiseMonitorDetail.vue b/src/components/NoiseMonitorDetail.vue index 3e71251..6858e3d 100644 --- a/src/components/NoiseMonitorDetail.vue +++ b/src/components/NoiseMonitorDetail.vue @@ -83,6 +83,48 @@ + + + +
+ 麦克风权限被拒绝 +
+
+ 浏览器已拒绝麦克风访问,无法进行噪音监测。请在浏览器地址栏左侧的锁图标中重新授予麦克风权限,然后刷新页面。 +
+
+ + +
+ 未检测到麦克风 +
+
+ 当前设备未检测到麦克风硬件,无法进行噪音监测。请连接麦克风后刷新页面重试。 +
+
+
@@ -344,6 +386,7 @@ prepend-icon="mdi-play" size="large" class="px-6" + :disabled="micPermissionState === 'denied' || micPermissionState === 'unavailable'" @click="$emit('start')" > 开始监测 @@ -1006,6 +1049,7 @@ export default { lastSlice: { type: Object, default: null }, history: { type: Array, default: () => [] }, isMonitoring: { type: Boolean, default: false }, + micPermissionState: { type: String, default: '' }, sessionActive: { type: Boolean, default: false }, sessionData: { type: Object, default: null }, reportMeta: { type: Object, default: () => ({ dates: {} }) }, diff --git a/src/components/TimeCard.vue b/src/components/TimeCard.vue index 4243cda..4e875f1 100644 --- a/src/components/TimeCard.vue +++ b/src/components/TimeCard.vue @@ -39,28 +39,58 @@ style="min-width: 80px;" @click.stop="onNoiseClick" > - -
- {{ noiseDisplayDb }} -
-
- {{ noiseStatusText }} -
-
- 点击开启 -
+ + + +
@@ -80,6 +110,7 @@ :last-slice="noiseLastSlice" :history="noiseHistory" :is-monitoring="noiseMonitoring" + :mic-permission-state="micPermissionState" :session-active="noiseSessionActive" :session-data="noiseSessionData" :report-meta="noiseReportMeta" @@ -749,6 +780,7 @@ export default { noiseCurrentDateReports: [], // 当前日期的报告列表 // 麦克风权限引导 showMicPermissionDialog: false, + micPermissionState: '', // 'granted' | 'prompt' | 'denied' | 'unavailable' } }, computed: { @@ -925,6 +957,7 @@ export default { this.noiseHistory = noiseService.getHistory() // 检查麦克风权限状态 const micState = await this.checkMicPermission() + this.micPermissionState = micState if (micState === 'granted') { // 已授权 → 正常流程 this.loadNoiseSessionConfig().then(() => { @@ -939,7 +972,7 @@ export default { this.showMicPermissionDialog = true } } - // denied → 什么也不做 + // denied / unavailable → 不自动启动,micPermissionState 已记录 } }, beforeUnmount() { @@ -1124,7 +1157,13 @@ export default { // ===== 麦克风权限引导 ===== async checkMicPermission() { try { - if (!navigator.permissions || !navigator.permissions.query) return 'granted' // 不支持 Permissions API 时视为已授权 + // 先检查是否有麦克风硬件 + if (navigator.mediaDevices && navigator.mediaDevices.enumerateDevices) { + const devices = await navigator.mediaDevices.enumerateDevices() + const hasMic = devices.some(d => d.kind === 'audioinput') + if (!hasMic) return 'unavailable' + } + if (!navigator.permissions || !navigator.permissions.query) return 'granted' const result = await navigator.permissions.query({ name: 'microphone' }) return result.state // 'granted' | 'prompt' | 'denied' } catch { @@ -1139,6 +1178,8 @@ export default { this.startSessionCheck() // 调用 startNoise 触发浏览器权限弹框 await this.startNoise() + // 重新检查状态 + this.micPermissionState = await this.checkMicPermission() }, dismissMicPermission() { this.showMicPermissionDialog = false @@ -1202,6 +1243,10 @@ export default { this.noiseHistory = [] }, onNoiseClick() { + if (this.micPermissionState === 'denied' || this.micPermissionState === 'unavailable') { + this.showNoiseDetail = true + return + } if (!this.noiseMonitoring) { this.startNoise() } else {