提交小程序合入代码
This commit is contained in:
@@ -194,6 +194,104 @@
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.system-update-card {
|
||||
margin: 0 24px 24px;
|
||||
border-radius: 20px;
|
||||
background: #FFFFFF;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.04);
|
||||
overflow: hidden;
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.72;
|
||||
}
|
||||
}
|
||||
|
||||
.system-update-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 20px;
|
||||
padding: 24px;
|
||||
background: #F0FDF4;
|
||||
}
|
||||
|
||||
.system-update-heading {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.system-update-title {
|
||||
display: block;
|
||||
font-size: 30px;
|
||||
font-weight: 700;
|
||||
color: #14532D;
|
||||
}
|
||||
|
||||
.system-update-subtitle {
|
||||
display: block;
|
||||
margin-top: 8px;
|
||||
font-size: 24px;
|
||||
line-height: 1.5;
|
||||
color: #15803D;
|
||||
}
|
||||
|
||||
.system-update-action {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
min-width: 132px;
|
||||
height: 64px;
|
||||
padding: 0 24px;
|
||||
border-radius: 16px;
|
||||
background: #16A34A;
|
||||
|
||||
&.disabled {
|
||||
background: #CBD5E1;
|
||||
}
|
||||
}
|
||||
|
||||
.system-update-action-text {
|
||||
font-size: 26px;
|
||||
font-weight: 700;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.system-update-body {
|
||||
padding: 6px 24px 20px;
|
||||
}
|
||||
|
||||
.system-update-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 24px;
|
||||
padding: 18px 0;
|
||||
border-bottom: 1px solid #F3F4F6;
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.system-update-label {
|
||||
flex-shrink: 0;
|
||||
font-size: 26px;
|
||||
color: #6B7280;
|
||||
}
|
||||
|
||||
.system-update-value {
|
||||
min-width: 0;
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
text-align: right;
|
||||
word-break: break-all;
|
||||
color: #1F2937;
|
||||
|
||||
&.highlight {
|
||||
color: #15803D;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-item.disabled {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import {
|
||||
unbindDevice,
|
||||
} from '@/services/binding'
|
||||
import { Child, clearSelectedChildId, createChild, setSelectedChildId, updateChild } from '@/services/child'
|
||||
import { DeviceFirmwareStatus, getDeviceFirmwareStatus, startDeviceFirmwareUpdate } from '@/services/device'
|
||||
import { useSystemBanner } from '@/components/system-banner/use-system-banner'
|
||||
import './index.scss'
|
||||
|
||||
interface MenuItem {
|
||||
@@ -22,11 +24,15 @@ interface MenuItem {
|
||||
}
|
||||
|
||||
export default function Sleep() {
|
||||
const systemBanner = useSystemBanner()
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [children, setChildren] = useState<Child[]>([])
|
||||
const [bindings, setBindings] = useState<BindingListItem[]>([])
|
||||
const [binding, setBinding] = useState<BindingListItem | null>(null)
|
||||
const [currentChild, setCurrentChild] = useState<Child | null>(null)
|
||||
const [firmwareStatus, setFirmwareStatus] = useState<DeviceFirmwareStatus | null>(null)
|
||||
const [isLoadingFirmware, setIsLoadingFirmware] = useState(false)
|
||||
const [isUpdatingFirmware, setIsUpdatingFirmware] = useState(false)
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
const [showChildModal, setShowChildModal] = useState(false)
|
||||
const [modalType, setModalType] = useState<'add' | 'edit'>('add')
|
||||
@@ -47,11 +53,13 @@ export default function Sleep() {
|
||||
setLoading(true)
|
||||
try {
|
||||
const context = await loadCurrentChildBindingContext()
|
||||
const nextBinding = (context.currentBinding as BindingListItem | null) || null
|
||||
setChildren(context.children)
|
||||
setBindings(context.bindings as BindingListItem[])
|
||||
setCurrentChild(context.currentChild)
|
||||
setBinding((context.currentBinding as BindingListItem | null) || null)
|
||||
setBinding(nextBinding)
|
||||
setParentInfo(Taro.getStorageSync('userInfo') || {})
|
||||
void loadFirmwareStatus(nextBinding?.device_id)
|
||||
} catch (error: any) {
|
||||
console.error('[manage] load failed:', error)
|
||||
Taro.showToast({
|
||||
@@ -65,6 +73,30 @@ export default function Sleep() {
|
||||
|
||||
const currentChildName = currentChild?.child_name || '未设置'
|
||||
|
||||
const loadFirmwareStatus = async (deviceId?: string | null) => {
|
||||
const normalizedDeviceId = String(deviceId || '').trim()
|
||||
if (!normalizedDeviceId) {
|
||||
setFirmwareStatus(null)
|
||||
setIsLoadingFirmware(false)
|
||||
return
|
||||
}
|
||||
|
||||
setIsLoadingFirmware(true)
|
||||
try {
|
||||
const nextFirmwareStatus = await getDeviceFirmwareStatus(normalizedDeviceId)
|
||||
setFirmwareStatus(nextFirmwareStatus)
|
||||
} catch (error: any) {
|
||||
console.error('[manage] firmware load failed:', error)
|
||||
setFirmwareStatus(null)
|
||||
Taro.showToast({
|
||||
title: error?.message || '系统更新状态加载失败',
|
||||
icon: 'none',
|
||||
})
|
||||
} finally {
|
||||
setIsLoadingFirmware(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleOpenModal = (type: 'add' | 'edit', child?: Child) => {
|
||||
setModalType(type)
|
||||
setChildName(child?.child_name || '')
|
||||
@@ -88,6 +120,7 @@ export default function Sleep() {
|
||||
}
|
||||
setCurrentChild(child)
|
||||
setBinding(nextBinding)
|
||||
void loadFirmwareStatus(nextBinding?.device_id)
|
||||
setShowChildModal(false)
|
||||
Taro.showToast({
|
||||
title: '已切换当前孩子',
|
||||
@@ -128,6 +161,37 @@ export default function Sleep() {
|
||||
}
|
||||
}
|
||||
|
||||
const handleStartFirmwareUpdate = () => {
|
||||
if (!binding?.device_id || !firmwareStatus?.can_update || isLoadingFirmware || isUpdatingFirmware) return
|
||||
|
||||
Taro.showModal({
|
||||
title: '系统更新',
|
||||
content: `确定要更新当前设备 ${binding.device_id} 吗?`,
|
||||
confirmText: '更新',
|
||||
confirmColor: '#16A34A',
|
||||
success: async (result) => {
|
||||
if (!result.confirm || !binding?.device_id) return
|
||||
|
||||
setIsUpdatingFirmware(true)
|
||||
try {
|
||||
const nextFirmwareStatus = await startDeviceFirmwareUpdate(binding.device_id)
|
||||
setFirmwareStatus(nextFirmwareStatus)
|
||||
Taro.showToast({
|
||||
title: '更新指令已发送',
|
||||
icon: 'success',
|
||||
})
|
||||
} catch (error: any) {
|
||||
Taro.showToast({
|
||||
title: error?.message || '更新失败,请重试',
|
||||
icon: 'none',
|
||||
})
|
||||
} finally {
|
||||
setIsUpdatingFirmware(false)
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const handleUnbind = () => {
|
||||
if (!binding) return
|
||||
|
||||
@@ -215,11 +279,23 @@ export default function Sleep() {
|
||||
<View className='loading'>
|
||||
<Text>加载中...</Text>
|
||||
</View>
|
||||
{systemBanner}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const parentDisplayName = parentInfo.nickname?.trim() || '家长'
|
||||
const currentFirmwareLabel = firmwareStatus?.current_version || '--'
|
||||
const latestFirmwareLabel = firmwareStatus?.latest_version || '--'
|
||||
const canUpdateFirmware = Boolean(binding?.device_id && firmwareStatus?.can_update && !isLoadingFirmware && !isUpdatingFirmware)
|
||||
const firmwareActionText = isLoadingFirmware ? '查询中' : isUpdatingFirmware ? '发送中' : '更新'
|
||||
const firmwareSubtitle = !binding?.device_id
|
||||
? '绑定设备后可查看系统版本'
|
||||
: isLoadingFirmware
|
||||
? '正在查询当前设备版本'
|
||||
: firmwareStatus?.update_available
|
||||
? '发现可更新版本'
|
||||
: '当前设备版本状态'
|
||||
const menuItems: MenuItem[] = [
|
||||
{
|
||||
icon: require('../../assets/tab-icons/orange-robot.png'),
|
||||
@@ -296,6 +372,35 @@ export default function Sleep() {
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className={`system-update-card ${binding?.device_id ? '' : 'disabled'}`}>
|
||||
<View className='system-update-header'>
|
||||
<View className='system-update-heading'>
|
||||
<Text className='system-update-title'>系统更新</Text>
|
||||
<Text className='system-update-subtitle'>{firmwareSubtitle}</Text>
|
||||
</View>
|
||||
<View
|
||||
className={`system-update-action ${canUpdateFirmware ? '' : 'disabled'}`}
|
||||
onClick={canUpdateFirmware ? handleStartFirmwareUpdate : undefined}
|
||||
>
|
||||
<Text className='system-update-action-text'>{firmwareActionText}</Text>
|
||||
</View>
|
||||
</View>
|
||||
<View className='system-update-body'>
|
||||
<View className='system-update-row'>
|
||||
<Text className='system-update-label'>当前设备</Text>
|
||||
<Text className='system-update-value'>{binding?.device_id || '未绑定'}</Text>
|
||||
</View>
|
||||
<View className='system-update-row'>
|
||||
<Text className='system-update-label'>当前版本</Text>
|
||||
<Text className='system-update-value'>{currentFirmwareLabel}</Text>
|
||||
</View>
|
||||
<View className='system-update-row'>
|
||||
<Text className='system-update-label'>最新版本</Text>
|
||||
<Text className='system-update-value highlight'>{latestFirmwareLabel}</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View className='menu-card'>
|
||||
{menuItems.map((item, index) => (
|
||||
<View key={index}>
|
||||
@@ -396,6 +501,7 @@ export default function Sleep() {
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
{systemBanner}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user