111
This commit is contained in:
@@ -219,14 +219,6 @@ export type HomeAssistantLightTransition = {
|
|||||||
message: string
|
message: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HomeAssistantSpeakerDemo = {
|
|
||||||
audioUrl: string
|
|
||||||
speakerOnline: boolean
|
|
||||||
directPlaybackSupported: boolean
|
|
||||||
commandAccepted: boolean
|
|
||||||
message: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type HomeAssistantStatus = {
|
export type HomeAssistantStatus = {
|
||||||
connected: boolean
|
connected: boolean
|
||||||
message: string
|
message: string
|
||||||
@@ -299,10 +291,6 @@ export const healthApi = {
|
|||||||
http.post<never, HomeAssistantLightTransition>('/api/health/home-assistant/lights/wake'),
|
http.post<never, HomeAssistantLightTransition>('/api/health/home-assistant/lights/wake'),
|
||||||
stopLightTransition: () =>
|
stopLightTransition: () =>
|
||||||
http.post<never, HomeAssistantLightTransition>('/api/health/home-assistant/lights/stop'),
|
http.post<never, HomeAssistantLightTransition>('/api/health/home-assistant/lights/stop'),
|
||||||
speakerDemoStatus: () =>
|
|
||||||
http.get<never, HomeAssistantSpeakerDemo>('/api/health/home-assistant/speaker/demo'),
|
|
||||||
playSpeakerDemo: () =>
|
|
||||||
http.post<never, HomeAssistantSpeakerDemo>('/api/health/home-assistant/speaker/play-demo'),
|
|
||||||
executeSleepScene: () =>
|
executeSleepScene: () =>
|
||||||
http.post<never, HomeAssistantSceneResult>('/api/health/home-assistant/scenes/sleep', undefined, { timeout: 90000 }),
|
http.post<never, HomeAssistantSceneResult>('/api/health/home-assistant/scenes/sleep', undefined, { timeout: 90000 }),
|
||||||
executeAllOffScene: () =>
|
executeAllOffScene: () =>
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ onMounted(load)
|
|||||||
</div>
|
</div>
|
||||||
<div class="startup-param-badge">
|
<div class="startup-param-badge">
|
||||||
<span class="lbl">8H 床垫</span>
|
<span class="lbl">8H 床垫</span>
|
||||||
<strong>左右加热 {{ dashboard?.mattressComfort?.heatingLevel ?? 0 }} 档 · 软硬度{{ dashboard?.mattressComfort?.firmness || '待填写 BMI' }}</strong>
|
<strong>左右加热 {{ dashboard?.mattressComfort?.heatingLevel ?? 0 }} 档 · 软硬度{{ dashboard?.mattressComfort?.firmness || '待填写 BMI' }} · 右侧全身轻柔按摩</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="startup-param-badge" v-if="dashboard?.sceneConfig?.enableUv">
|
<div class="startup-param-badge" v-if="dashboard?.sceneConfig?.enableUv">
|
||||||
<span class="lbl">除湿消杀</span>
|
<span class="lbl">除湿消杀</span>
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import {
|
|||||||
healthApi,
|
healthApi,
|
||||||
type HomeAssistantDiscoveredDevice,
|
type HomeAssistantDiscoveredDevice,
|
||||||
type HomeAssistantLightTransition,
|
type HomeAssistantLightTransition,
|
||||||
type HomeAssistantSpeakerDemo,
|
|
||||||
type HomeAssistantStatus,
|
type HomeAssistantStatus,
|
||||||
type MattressComfort,
|
type MattressComfort,
|
||||||
type TcmAssessmentResult
|
type TcmAssessmentResult
|
||||||
@@ -31,8 +30,6 @@ const lastUpdatedAt = ref('')
|
|||||||
const actionFeedback = ref<{ type: 'success' | 'fail'; message: string }>()
|
const actionFeedback = ref<{ type: 'success' | 'fail'; message: string }>()
|
||||||
const lightTransition = ref<HomeAssistantLightTransition>()
|
const lightTransition = ref<HomeAssistantLightTransition>()
|
||||||
const lightActionBusy = ref(false)
|
const lightActionBusy = ref(false)
|
||||||
const speakerDemo = ref<HomeAssistantSpeakerDemo>()
|
|
||||||
const speakerDemoBusy = ref(false)
|
|
||||||
let lightProgressTimer: ReturnType<typeof setInterval> | undefined
|
let lightProgressTimer: ReturnType<typeof setInterval> | undefined
|
||||||
let lightPolling = false
|
let lightPolling = false
|
||||||
|
|
||||||
@@ -73,11 +70,10 @@ function setFeedback(type: 'success' | 'fail', message: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const operationBusy = computed(() =>
|
const operationBusy = computed(() =>
|
||||||
loading.value || lightActionBusy.value || speakerDemoBusy.value || Boolean(sceneRunning.value) || Boolean(settingParam.value) || Boolean(switchingDeviceId.value)
|
loading.value || lightActionBusy.value || Boolean(sceneRunning.value) || Boolean(settingParam.value) || Boolean(switchingDeviceId.value)
|
||||||
)
|
)
|
||||||
|
|
||||||
const currentOperationText = computed(() => {
|
const currentOperationText = computed(() => {
|
||||||
if (speakerDemoBusy.value) return '正在尝试播放示例音频…'
|
|
||||||
if (lightActionBusy.value) return '正在切换灯光渐变模式…'
|
if (lightActionBusy.value) return '正在切换灯光渐变模式…'
|
||||||
if (sceneRunning.value === 'sleep') return '正在启动全屋舒睡模式…'
|
if (sceneRunning.value === 'sleep') return '正在启动全屋舒睡模式…'
|
||||||
if (sceneRunning.value === 'all-off') return '正在关闭场景设备…'
|
if (sceneRunning.value === 'all-off') return '正在关闭场景设备…'
|
||||||
@@ -188,14 +184,6 @@ async function loadStatus(notify = false) {
|
|||||||
if (controls.mattress_massage_right_part?.state) localParams.mattressMassageRightPart = controls.mattress_massage_right_part.state
|
if (controls.mattress_massage_right_part?.state) localParams.mattressMassageRightPart = controls.mattress_massage_right_part.state
|
||||||
if (controls.mattress_massage_level?.state) localParams.mattressMassageLevel = controls.mattress_massage_level.state
|
if (controls.mattress_massage_level?.state) localParams.mattressMassageLevel = controls.mattress_massage_level.state
|
||||||
await syncLightTransitionStatus()
|
await syncLightTransitionStatus()
|
||||||
try {
|
|
||||||
speakerDemo.value = await healthApi.speakerDemoStatus()
|
|
||||||
} catch (err) {
|
|
||||||
speakerDemo.value = {
|
|
||||||
audioUrl: '', speakerOnline: false, directPlaybackSupported: false, commandAccepted: false,
|
|
||||||
message: err instanceof Error ? err.message : '音箱能力检测失败'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastUpdatedAt.value = new Intl.DateTimeFormat('zh-CN', {
|
lastUpdatedAt.value = new Intl.DateTimeFormat('zh-CN', {
|
||||||
hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false
|
hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false
|
||||||
}).format(new Date())
|
}).format(new Date())
|
||||||
@@ -271,26 +259,6 @@ async function controlLightTransition(action: 'sleep' | 'wake' | 'stop') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function tryPlaySpeakerDemo() {
|
|
||||||
if (!speakerDemo.value?.directPlaybackSupported || operationBusy.value) return
|
|
||||||
speakerDemoBusy.value = true
|
|
||||||
const loadingToast = showLoadingToast({ message: '正在尝试投放到音箱…', forbidClick: true, duration: 0 })
|
|
||||||
try {
|
|
||||||
const result = await healthApi.playSpeakerDemo()
|
|
||||||
speakerDemo.value = result
|
|
||||||
if (!result.commandAccepted) throw new Error(result.message)
|
|
||||||
setFeedback('success', result.message)
|
|
||||||
showSuccessToast('指令已发送,请确认音箱实际出声')
|
|
||||||
} catch (err) {
|
|
||||||
const message = err instanceof Error ? err.message : '投放失败'
|
|
||||||
setFeedback('fail', message)
|
|
||||||
showFailToast(message)
|
|
||||||
} finally {
|
|
||||||
loadingToast.close()
|
|
||||||
speakerDemoBusy.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 查找具体设备
|
// 查找具体设备
|
||||||
const dehumidifierDevice = computed(() =>
|
const dehumidifierDevice = computed(() =>
|
||||||
haStatus.value?.devices.find(d => d.category === 'EnvironmentControl')
|
haStatus.value?.devices.find(d => d.category === 'EnvironmentControl')
|
||||||
@@ -777,17 +745,6 @@ onUnmounted(() => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="params-body">
|
<div class="params-body">
|
||||||
<div class="speaker-demo-panel">
|
|
||||||
<strong>OSS 音频播放 Demo</strong>
|
|
||||||
<small>先在手机试听,再检测能否投放到 Sound Pro。</small>
|
|
||||||
<audio v-if="speakerDemo?.audioUrl" controls preload="none" :src="speakerDemo.audioUrl">
|
|
||||||
当前浏览器不支持播放音频
|
|
||||||
</audio>
|
|
||||||
<p>{{ speakerDemo?.message || '正在检测音箱播放能力…' }}</p>
|
|
||||||
<button type="button" :disabled="operationBusy || !speakerDemo?.directPlaybackSupported" @click="tryPlaySpeakerDemo">
|
|
||||||
{{ speakerDemo?.directPlaybackSupported ? '尝试音箱播放' : '当前音箱集成暂不支持投放' }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<!-- 音量滑块 -->
|
<!-- 音量滑块 -->
|
||||||
<div class="param-row">
|
<div class="param-row">
|
||||||
<div class="param-header">
|
<div class="param-header">
|
||||||
@@ -1544,29 +1501,6 @@ onUnmounted(() => {
|
|||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
.speaker-demo-panel {
|
|
||||||
padding: 13px;
|
|
||||||
border-radius: 12px;
|
|
||||||
background: #f3f8f7;
|
|
||||||
border: 1px solid #d9e9e5;
|
|
||||||
}
|
|
||||||
|
|
||||||
.speaker-demo-panel strong,
|
|
||||||
.speaker-demo-panel small,
|
|
||||||
.speaker-demo-panel audio {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.speaker-demo-panel strong { font-size: 13px; color: #174d44; }
|
|
||||||
.speaker-demo-panel small { margin-top: 4px; color: #647b75; font-size: 11px; }
|
|
||||||
.speaker-demo-panel audio { width: 100%; margin-top: 10px; height: 38px; }
|
|
||||||
.speaker-demo-panel p { margin: 10px 0; color: #526a64; font-size: 11px; line-height: 1.5; }
|
|
||||||
.speaker-demo-panel button {
|
|
||||||
width: 100%; padding: 9px 10px; border: 0; border-radius: 9px;
|
|
||||||
background: #0c5045; color: #fff; font-size: 12px; font-weight: 600;
|
|
||||||
}
|
|
||||||
.speaker-demo-panel button:disabled { background: #b8c5c1; }
|
|
||||||
|
|
||||||
/* 滑块样式:左右各预留 10px 间距,使滑块在 0% 和 100% 端点时,外凸的圆形按钮完整居中且不被裁剪 */
|
/* 滑块样式:左右各预留 10px 间距,使滑块在 0% 和 100% 端点时,外凸的圆形按钮完整居中且不被裁剪 */
|
||||||
.param-row :deep(.van-slider) {
|
.param-row :deep(.van-slider) {
|
||||||
margin: 10px 10px 14px 10px;
|
margin: 10px 10px 14px 10px;
|
||||||
|
|||||||
Reference in New Issue
Block a user