import { View, Text, Image, Input } from '@tarojs/components' import { useState } from 'react' import Taro, { useDidShow } from '@tarojs/taro' import { clearToken, getToken } from '@/services/auth' import { BindingListItem, clearSelectedBindingDeviceId, loadCurrentChildBindingContext, setSelectedBindingDeviceId, 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 { icon: string iconBgClass: string name: string value: string arrow?: boolean disabled?: boolean } export default function Sleep() { const systemBanner = useSystemBanner() const [loading, setLoading] = useState(true) const [children, setChildren] = useState([]) const [bindings, setBindings] = useState([]) const [binding, setBinding] = useState(null) const [currentChild, setCurrentChild] = useState(null) const [firmwareStatus, setFirmwareStatus] = useState(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') const [childName, setChildName] = useState('') const [editingChildId, setEditingChildId] = useState(null) const [parentInfo, setParentInfo] = useState<{ nickname?: string; avatar_url?: string }>({}) useDidShow(() => { void loadData() }) const loadData = async () => { if (!getToken()) { Taro.reLaunch({ url: '/pages/login/index' }) return } 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(nextBinding) setParentInfo(Taro.getStorageSync('userInfo') || {}) void loadFirmwareStatus(nextBinding?.device_id) } catch (error: any) { console.error('[manage] load failed:', error) Taro.showToast({ title: error?.message || '加载失败,请稍后重试', icon: 'none', }) } finally { setLoading(false) } } 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 || '') setEditingChildId(child?.child_id || null) setShowModal(true) } const handleCloseModal = () => { setShowModal(false) setChildName('') setEditingChildId(null) } const handleSelectChild = (child: Child) => { setSelectedChildId(child.child_id) const nextBinding = bindings.find((item) => item.child_id === child.child_id) || null if (nextBinding?.device_id) { setSelectedBindingDeviceId(nextBinding.device_id) } else { clearSelectedBindingDeviceId() } setCurrentChild(child) setBinding(nextBinding) void loadFirmwareStatus(nextBinding?.device_id) setShowChildModal(false) Taro.showToast({ title: '已切换当前孩子', icon: 'success', }) } const handleOpenAddChildFromSwitch = () => { setShowChildModal(false) handleOpenModal('add') } const handleSubmitModal = async () => { const normalizedName = childName.trim() if (!normalizedName) { Taro.showToast({ title: '请输入儿童昵称', icon: 'none' }) return } try { if (modalType === 'add') { const createdChild = await createChild({ child_name: normalizedName }) setSelectedChildId(createdChild.child_id) Taro.showToast({ title: '创建成功', icon: 'success' }) } else if (editingChildId) { await updateChild(editingChildId, { child_name: normalizedName }) Taro.showToast({ title: '修改成功', icon: 'success' }) } handleCloseModal() await loadData() } catch (error: any) { console.error('[manage] save child failed:', error) Taro.showToast({ title: error?.message || '保存失败,请重试', icon: 'none', }) } } 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 Taro.showModal({ title: '解除设备绑定', content: `确定要解除 ${currentChildName} 当前绑定的设备吗?`, confirmColor: '#FF8C42', success: async (result) => { if (!result.confirm) return try { await unbindDevice(binding.device_id) clearSelectedBindingDeviceId() Taro.showToast({ title: '已解绑', icon: 'success' }) await loadData() } catch (error: any) { Taro.showToast({ title: error?.message || '解绑失败,请重试', icon: 'none', }) } }, }) } const handleLogout = () => { Taro.showModal({ title: '退出登录', content: '确定要退出当前账号吗?', confirmColor: '#FF8C42', success: (result) => { if (!result.confirm) return clearToken() clearSelectedBindingDeviceId() clearSelectedChildId() Taro.removeStorageSync('userInfo') Taro.reLaunch({ url: '/pages/login/index' }) }, }) } const handleMenuClick = (item: MenuItem) => { if (item.disabled) return if (item.name === '当前孩子') { setShowChildModal(true) return } if (item.name === '编辑当前孩子') { if (currentChild) { handleOpenModal('edit', currentChild) } else { handleOpenModal('add') } return } if (item.name === '新增孩子') { handleOpenModal('add') return } if (item.name === '绑定设备') { if (!currentChild) { handleOpenModal('add') Taro.showToast({ title: '请先添加儿童资料', icon: 'none', }) return } Taro.navigateTo({ url: '/pages/bind/index' }) return } if (item.name === '解除设备绑定') { handleUnbind() } } if (loading) { return ( 加载中... {systemBanner} ) } 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'), iconBgClass: 'orange', name: '当前孩子', value: currentChildName, arrow: true, }, { icon: require('../../assets/tab-icons/orange-robot.png'), iconBgClass: 'orange', name: '新增孩子', value: '', arrow: true, }, { icon: require('../../assets/tab-icons/orange-robot.png'), iconBgClass: 'orange', name: '编辑当前孩子', value: '', arrow: true, }, { icon: require('../../assets/tab-icons/rings.png'), iconBgClass: 'green', name: '绑定设备', value: binding?.device_id ? `当前: ${binding.device_id}` : '未绑定', arrow: true, }, { icon: require('../../assets/tab-icons/broken-rings.png'), iconBgClass: 'red', name: '解除设备绑定', value: binding?.device_id ? `当前: ${binding.device_id}` : '', arrow: true, disabled: !binding, }, ] return ( 设置与管理 {parentInfo.avatar_url ? ( ) : ( 👤 )} {parentDisplayName} {currentChild ? '已选择当前孩子' : '未选择孩子'} 儿童资料数 {children.length} 个 当前儿童 {currentChildName} 当前设备 {binding?.device_id || '未绑定'} 系统更新 {firmwareSubtitle} {firmwareActionText} 当前设备 {binding?.device_id || '未绑定'} 当前版本 {currentFirmwareLabel} 最新版本 {latestFirmwareLabel} {menuItems.map((item, index) => ( handleMenuClick(item)}> {item.name} {item.value && {item.value}} {item.arrow && } {index < menuItems.length - 1 && } ))} 退出登录 伴伴 Companion V1.1.0 {showChildModal && ( setShowChildModal(false)}> { event.stopPropagation() }} > 切换当前孩子 {children.length === 0 ? ( 当前还没有儿童资料 ) : ( {children.map((item) => { const isActive = currentChild?.child_id === item.child_id const itemBinding = bindings.find((bindingItem) => bindingItem.child_id === item.child_id) || null return ( handleSelectChild(item)} > {item.child_name} {isActive && 当前} {itemBinding?.device_id || '未绑定设备'} ) })} )} + 新增孩子 setShowChildModal(false)}> 关闭 )} {showModal && ( {modalType === 'add' ? '新建儿童资料' : '修改儿童昵称'} setChildName(event.detail.value)} /> 取消 确认 )} {systemBanner} ) }