mirror of
https://github.com/ZeroCatDev/Classworks.git
synced 2026-03-21 09:13:10 +00:00
feat: 添加麦克风权限状态提示,优化噪音监测体验
This commit is contained in:
parent
787c95ca18
commit
41dc2c5251
@ -83,6 +83,48 @@
|
|||||||
<v-tabs-window v-model="activeTab">
|
<v-tabs-window v-model="activeTab">
|
||||||
<!-- ==================== 实时监测 ==================== -->
|
<!-- ==================== 实时监测 ==================== -->
|
||||||
<v-tabs-window-item value="realtime">
|
<v-tabs-window-item value="realtime">
|
||||||
|
<!-- 麦克风不可用提示 -->
|
||||||
|
<v-alert
|
||||||
|
v-if="micPermissionState === 'denied'"
|
||||||
|
type="error"
|
||||||
|
variant="tonal"
|
||||||
|
class="ma-4 mb-0"
|
||||||
|
prominent
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<v-icon
|
||||||
|
icon="mdi-microphone-off"
|
||||||
|
size="28"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<div class="text-subtitle-2 font-weight-bold mb-1">
|
||||||
|
麦克风权限被拒绝
|
||||||
|
</div>
|
||||||
|
<div class="text-body-2">
|
||||||
|
浏览器已拒绝麦克风访问,无法进行噪音监测。请在浏览器地址栏左侧的锁图标中重新授予麦克风权限,然后刷新页面。
|
||||||
|
</div>
|
||||||
|
</v-alert>
|
||||||
|
<v-alert
|
||||||
|
v-else-if="micPermissionState === 'unavailable'"
|
||||||
|
type="warning"
|
||||||
|
variant="tonal"
|
||||||
|
class="ma-4 mb-0"
|
||||||
|
prominent
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<v-icon
|
||||||
|
icon="mdi-microphone-question"
|
||||||
|
size="28"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<div class="text-subtitle-2 font-weight-bold mb-1">
|
||||||
|
未检测到麦克风
|
||||||
|
</div>
|
||||||
|
<div class="text-body-2">
|
||||||
|
当前设备未检测到麦克风硬件,无法进行噪音监测。请连接麦克风后刷新页面重试。
|
||||||
|
</div>
|
||||||
|
</v-alert>
|
||||||
|
|
||||||
<!-- 分贝仪表区 -->
|
<!-- 分贝仪表区 -->
|
||||||
<div class="noise-dashboard pa-5">
|
<div class="noise-dashboard pa-5">
|
||||||
<div class="d-flex align-center justify-center">
|
<div class="d-flex align-center justify-center">
|
||||||
@ -344,6 +386,7 @@
|
|||||||
prepend-icon="mdi-play"
|
prepend-icon="mdi-play"
|
||||||
size="large"
|
size="large"
|
||||||
class="px-6"
|
class="px-6"
|
||||||
|
:disabled="micPermissionState === 'denied' || micPermissionState === 'unavailable'"
|
||||||
@click="$emit('start')"
|
@click="$emit('start')"
|
||||||
>
|
>
|
||||||
开始监测
|
开始监测
|
||||||
@ -1006,6 +1049,7 @@ export default {
|
|||||||
lastSlice: { type: Object, default: null },
|
lastSlice: { type: Object, default: null },
|
||||||
history: { type: Array, default: () => [] },
|
history: { type: Array, default: () => [] },
|
||||||
isMonitoring: { type: Boolean, default: false },
|
isMonitoring: { type: Boolean, default: false },
|
||||||
|
micPermissionState: { type: String, default: '' },
|
||||||
sessionActive: { type: Boolean, default: false },
|
sessionActive: { type: Boolean, default: false },
|
||||||
sessionData: { type: Object, default: null },
|
sessionData: { type: Object, default: null },
|
||||||
reportMeta: { type: Object, default: () => ({ dates: {} }) },
|
reportMeta: { type: Object, default: () => ({ dates: {} }) },
|
||||||
|
|||||||
@ -39,28 +39,58 @@
|
|||||||
style="min-width: 80px;"
|
style="min-width: 80px;"
|
||||||
@click.stop="onNoiseClick"
|
@click.stop="onNoiseClick"
|
||||||
>
|
>
|
||||||
|
<!-- 无麦克风权限提示 -->
|
||||||
<div
|
<template v-if="micPermissionState === 'denied'">
|
||||||
class="noise-side-db font-weight-bold"
|
<v-icon
|
||||||
:class="`text-${noiseDbColor}`"
|
color="error"
|
||||||
:style="{ fontSize: `${fontSize * 0.9}px`, lineHeight: 1, fontVariantNumeric: 'tabular-nums' }"
|
size="24"
|
||||||
>
|
>
|
||||||
{{ noiseDisplayDb }}
|
mdi-microphone-off
|
||||||
</div>
|
</v-icon>
|
||||||
<div
|
<div
|
||||||
class="text-caption mt-1"
|
class="text-caption text-error mt-1"
|
||||||
:class="`text-${noiseDbColor}`"
|
style="white-space: nowrap; font-size: 10px;"
|
||||||
style="white-space: nowrap; font-size: 11px;"
|
>
|
||||||
>
|
权限被拒绝
|
||||||
{{ noiseStatusText }}
|
</div>
|
||||||
</div>
|
</template>
|
||||||
<div
|
<template v-else-if="micPermissionState === 'unavailable'">
|
||||||
v-if="!noiseMonitoring"
|
<v-icon
|
||||||
class="text-caption text-medium-emphasis mt-1"
|
color="warning"
|
||||||
style="font-size: 10px; cursor: pointer;"
|
size="24"
|
||||||
>
|
>
|
||||||
点击开启
|
mdi-microphone-question
|
||||||
</div>
|
</v-icon>
|
||||||
|
<div
|
||||||
|
class="text-caption text-warning mt-1"
|
||||||
|
style="white-space: nowrap; font-size: 10px;"
|
||||||
|
>
|
||||||
|
无麦克风
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<div
|
||||||
|
class="noise-side-db font-weight-bold"
|
||||||
|
:class="`text-${noiseDbColor}`"
|
||||||
|
:style="{ fontSize: `${fontSize * 0.9}px`, lineHeight: 1, fontVariantNumeric: 'tabular-nums' }"
|
||||||
|
>
|
||||||
|
{{ noiseDisplayDb }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="text-caption mt-1"
|
||||||
|
:class="`text-${noiseDbColor}`"
|
||||||
|
style="white-space: nowrap; font-size: 11px;"
|
||||||
|
>
|
||||||
|
{{ noiseStatusText }}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="!noiseMonitoring"
|
||||||
|
class="text-caption text-medium-emphasis mt-1"
|
||||||
|
style="font-size: 10px; cursor: pointer;"
|
||||||
|
>
|
||||||
|
点击开启
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
@ -80,6 +110,7 @@
|
|||||||
:last-slice="noiseLastSlice"
|
:last-slice="noiseLastSlice"
|
||||||
:history="noiseHistory"
|
:history="noiseHistory"
|
||||||
:is-monitoring="noiseMonitoring"
|
:is-monitoring="noiseMonitoring"
|
||||||
|
:mic-permission-state="micPermissionState"
|
||||||
:session-active="noiseSessionActive"
|
:session-active="noiseSessionActive"
|
||||||
:session-data="noiseSessionData"
|
:session-data="noiseSessionData"
|
||||||
:report-meta="noiseReportMeta"
|
:report-meta="noiseReportMeta"
|
||||||
@ -749,6 +780,7 @@ export default {
|
|||||||
noiseCurrentDateReports: [], // 当前日期的报告列表
|
noiseCurrentDateReports: [], // 当前日期的报告列表
|
||||||
// 麦克风权限引导
|
// 麦克风权限引导
|
||||||
showMicPermissionDialog: false,
|
showMicPermissionDialog: false,
|
||||||
|
micPermissionState: '', // 'granted' | 'prompt' | 'denied' | 'unavailable'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -925,6 +957,7 @@ export default {
|
|||||||
this.noiseHistory = noiseService.getHistory()
|
this.noiseHistory = noiseService.getHistory()
|
||||||
// 检查麦克风权限状态
|
// 检查麦克风权限状态
|
||||||
const micState = await this.checkMicPermission()
|
const micState = await this.checkMicPermission()
|
||||||
|
this.micPermissionState = micState
|
||||||
if (micState === 'granted') {
|
if (micState === 'granted') {
|
||||||
// 已授权 → 正常流程
|
// 已授权 → 正常流程
|
||||||
this.loadNoiseSessionConfig().then(() => {
|
this.loadNoiseSessionConfig().then(() => {
|
||||||
@ -939,7 +972,7 @@ export default {
|
|||||||
this.showMicPermissionDialog = true
|
this.showMicPermissionDialog = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// denied → 什么也不做
|
// denied / unavailable → 不自动启动,micPermissionState 已记录
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
beforeUnmount() {
|
beforeUnmount() {
|
||||||
@ -1124,7 +1157,13 @@ export default {
|
|||||||
// ===== 麦克风权限引导 =====
|
// ===== 麦克风权限引导 =====
|
||||||
async checkMicPermission() {
|
async checkMicPermission() {
|
||||||
try {
|
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' })
|
const result = await navigator.permissions.query({ name: 'microphone' })
|
||||||
return result.state // 'granted' | 'prompt' | 'denied'
|
return result.state // 'granted' | 'prompt' | 'denied'
|
||||||
} catch {
|
} catch {
|
||||||
@ -1139,6 +1178,8 @@ export default {
|
|||||||
this.startSessionCheck()
|
this.startSessionCheck()
|
||||||
// 调用 startNoise 触发浏览器权限弹框
|
// 调用 startNoise 触发浏览器权限弹框
|
||||||
await this.startNoise()
|
await this.startNoise()
|
||||||
|
// 重新检查状态
|
||||||
|
this.micPermissionState = await this.checkMicPermission()
|
||||||
},
|
},
|
||||||
dismissMicPermission() {
|
dismissMicPermission() {
|
||||||
this.showMicPermissionDialog = false
|
this.showMicPermissionDialog = false
|
||||||
@ -1202,6 +1243,10 @@ export default {
|
|||||||
this.noiseHistory = []
|
this.noiseHistory = []
|
||||||
},
|
},
|
||||||
onNoiseClick() {
|
onNoiseClick() {
|
||||||
|
if (this.micPermissionState === 'denied' || this.micPermissionState === 'unavailable') {
|
||||||
|
this.showNoiseDetail = true
|
||||||
|
return
|
||||||
|
}
|
||||||
if (!this.noiseMonitoring) {
|
if (!this.noiseMonitoring) {
|
||||||
this.startNoise()
|
this.startNoise()
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user