按设备回执确认音量调整完成
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
import { View, Text, Slider, Image } from '@tarojs/components'
|
||||
import { useState } from 'react'
|
||||
import { useRef, useState } from 'react'
|
||||
import Taro, { useDidShow } from '@tarojs/taro'
|
||||
import { getToken } from '@/services/auth'
|
||||
import { DEVICE_UNAVAILABLE_MESSAGE } from '@/services/api'
|
||||
import { Binding, loadCurrentChildBindingContext } from '@/services/binding'
|
||||
import { Child } from '@/services/child'
|
||||
import { DeviceAlarmItem, DeviceStatus, getDeviceAlarms, getDeviceStatus, setDeviceRemoteSleepWake, setDeviceVolume } from '@/services/device'
|
||||
import { DeviceAlarmItem, DeviceStatus, getDeviceAlarms, getDeviceStatus, getDeviceVolumeCommandStatus, setDeviceRemoteSleepWake, setDeviceVolume } from '@/services/device'
|
||||
import { useSystemBanner } from '@/components/system-banner/use-system-banner'
|
||||
import './index.scss'
|
||||
|
||||
@@ -41,6 +41,12 @@ function getSignalLabel(value?: number | null): string {
|
||||
return '弱'
|
||||
}
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(resolve, ms)
|
||||
})
|
||||
}
|
||||
|
||||
function formatBatteryDisplay(value?: number | null): { text: string; showPercent: boolean } {
|
||||
if (value === null || value === undefined) return { text: '--', showPercent: false }
|
||||
const normalized = Number(value)
|
||||
@@ -123,6 +129,7 @@ export default function Device() {
|
||||
const [isSavingVolume, setIsSavingVolume] = useState(false)
|
||||
const [sleepWakePending, setSleepWakePending] = useState<'on' | 'off' | null>(null)
|
||||
const [volumeValue, setVolumeValue] = useState(0)
|
||||
const volumeCommandInFlightRef = useRef(false)
|
||||
|
||||
useDidShow(() => {
|
||||
void loadDeviceInfo()
|
||||
@@ -173,21 +180,42 @@ export default function Device() {
|
||||
}
|
||||
|
||||
const handleVolumeChanging = (e: any) => {
|
||||
if (volumeCommandInFlightRef.current) return
|
||||
setVolumeValue(Number(e.detail?.value || 0))
|
||||
}
|
||||
|
||||
const handleVolumeCommit = async (e: any) => {
|
||||
if (!binding?.device_id) return
|
||||
if (volumeCommandInFlightRef.current) return
|
||||
const nextLevel = Number(e.detail?.value || 0)
|
||||
const fallbackLevel = deviceStatus?.volume ?? volumeValue ?? 0
|
||||
volumeCommandInFlightRef.current = true
|
||||
setVolumeValue(nextLevel)
|
||||
setIsSavingVolume(true)
|
||||
|
||||
try {
|
||||
await setDeviceVolume(nextLevel, binding.device_id)
|
||||
setDeviceStatus((current) => (current ? { ...current, volume: nextLevel } : current))
|
||||
const command = await setDeviceVolume(nextLevel, binding.device_id)
|
||||
let completedLevel: number | null = null
|
||||
let failedMessage = ''
|
||||
for (let attempt = 0; attempt < 13; attempt += 1) {
|
||||
await sleep(800)
|
||||
const status = await getDeviceVolumeCommandStatus(binding.device_id, command.time)
|
||||
if (status.status === 'completed') {
|
||||
completedLevel = status.current_level ?? nextLevel
|
||||
break
|
||||
}
|
||||
if (status.status === 'failed' || status.status === 'timeout') {
|
||||
failedMessage = status.error || (status.status === 'timeout' ? '设备未确认音量调整,请稍后查看设备状态' : '设备音量调整失败')
|
||||
break
|
||||
}
|
||||
}
|
||||
if (completedLevel === null) {
|
||||
throw new Error(failedMessage || '设备未确认音量调整,请稍后查看设备状态')
|
||||
}
|
||||
setVolumeValue(completedLevel)
|
||||
setDeviceStatus((current) => (current ? { ...current, volume: completedLevel } : current))
|
||||
Taro.showToast({
|
||||
title: '音量指令已发送',
|
||||
title: '音量已成功调整',
|
||||
icon: 'success',
|
||||
})
|
||||
} catch (error: any) {
|
||||
@@ -200,6 +228,7 @@ export default function Device() {
|
||||
icon: 'none',
|
||||
})
|
||||
} finally {
|
||||
volumeCommandInFlightRef.current = false
|
||||
setIsSavingVolume(false)
|
||||
}
|
||||
}
|
||||
@@ -402,7 +431,7 @@ export default function Device() {
|
||||
</View>
|
||||
<View className='control-info'>
|
||||
<Text className='control-name'>外放音量</Text>
|
||||
<Text className='control-detail'>{isSavingVolume ? '发送中...' : `当前 ${volumeLabel}`}</Text>
|
||||
<Text className='control-detail'>{isSavingVolume ? '调整中...' : `当前 ${volumeLabel}`}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
@@ -417,6 +446,7 @@ export default function Device() {
|
||||
min={0}
|
||||
max={100}
|
||||
value={volumeValue}
|
||||
disabled={isSavingVolume}
|
||||
onChanging={handleVolumeChanging}
|
||||
onChange={handleVolumeCommit}
|
||||
activeColor='#FF8C42'
|
||||
|
||||
@@ -65,6 +65,19 @@ export interface DeviceVolumeUpdateResponse {
|
||||
device_id: string
|
||||
level: number
|
||||
msg_id: string
|
||||
time: number
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface DeviceVolumeCommandStatusResponse {
|
||||
device_id: string
|
||||
level: number
|
||||
msg_id: string
|
||||
time: number
|
||||
status: 'sent' | 'completed' | 'failed' | string
|
||||
current_level?: number | null
|
||||
response_status?: string | null
|
||||
error?: string | null
|
||||
}
|
||||
|
||||
export interface DeviceSleepScheduleUpdateResponse {
|
||||
@@ -179,6 +192,13 @@ export async function setDeviceVolume(level: number, deviceId?: string): Promise
|
||||
})
|
||||
}
|
||||
|
||||
export async function getDeviceVolumeCommandStatus(
|
||||
deviceId: string,
|
||||
commandTime: number,
|
||||
): Promise<DeviceVolumeCommandStatusResponse> {
|
||||
return request<DeviceVolumeCommandStatusResponse>(`/banban/devices/${deviceId}/volume/${commandTime}`)
|
||||
}
|
||||
|
||||
export async function setDeviceSleepSchedule(
|
||||
start: string,
|
||||
end: string,
|
||||
|
||||
Reference in New Issue
Block a user