feat(mini): align companion pages and show OTA progress

This commit is contained in:
stu2not
2026-09-15 11:25:11 +08:00
parent 9f3a4e966f
commit fce6cd1cc1
51 changed files with 537 additions and 115 deletions
+15
View File
@@ -383,3 +383,18 @@
}
}
}
.bind-result { padding: 24px 48px 60px; text-align: center; }
.bind-result-title { display: block; color: #895731; font-size: 46px; font-weight: 700; line-height: 1.35; }
.bind-result-art { display: block; width: 310px; height: 290px; margin: 12px auto 20px; }
.bind-result-description { display: block; margin-top: 18px; color: #a68d74; font-size: 27px; line-height: 1.65; word-break: break-word; }
.bind-countdown-ring { width: 220px; height: 220px; border: 12px solid #f9d96c; border-top-color: #ffa24f; border-radius: 50%; margin: 44px auto; display: flex; flex-direction: column; align-items: center; justify-content: center; background: #fffdf7; }
.bind-countdown-value { font-size: 62px; font-weight: 700; color: #ec913e; }
.bind-countdown-label { margin-top: 12px; font-size: 22px; color: #aa8154; }
.bind-instruction { padding: 28px; border: 2px solid #d2b48c; border-radius: 46px; background: #fffdf7; }
.bind-instruction-title { font-size: 34px; font-weight: 600; color: #895731; }
.bind-result-button { min-height: 92px; margin-top: 28px; border-radius: 46px; display: flex; align-items: center; justify-content: center; font-size: 30px; font-weight: 600; box-sizing: border-box; }
.bind-result-button::after { display: none; }
.bind-result-button.primary { background: linear-gradient(#ffce8d, #efa05a); border: 2px solid #cf935a; color: #895731; }
.bind-result-button.secondary { background: #fffdf7; border: 2px solid #cf935a; color: #ad8054; }
.bind-result-button.waiting { background: linear-gradient(#eeede9, #c9c7c1); border: 2px solid #aaa69c; color: #777168; }
+65 -19
View File
@@ -1,3 +1,4 @@
import { getPageStyle } from '@/utils/page-style'
import { View, Text, Image, Input, Button } from '@tarojs/components'
import { useEffect, useRef, useState } from 'react'
import Taro, { useDidShow, useDidHide, useRouter } from '@tarojs/taro'
@@ -175,6 +176,7 @@ export default function Bind() {
const [bindStatus, setBindStatus] = useState<number | null>(null)
const [cardUUID, setCardUUID] = useState('')
const [bindHint, setBindHint] = useState('')
const [bindResultDestination, setBindResultDestination] = useState('/pages/device/index')
const [bindExpiresAt, setBindExpiresAt] = useState('')
const [remainingBindSeconds, setRemainingBindSeconds] = useState(0)
const pollingRef = useRef<ReturnType<typeof setTimeout> | null>(null)
@@ -370,13 +372,7 @@ export default function Bind() {
: session.card_uuid ? `绑定完成,卡号 ${session.card_uuid},稍后可关联宝贝` : '绑定完成,稍后可关联宝贝'
)
Taro.showToast({ title: isAddingCard ? '新卡添加成功' : '设备绑定成功', icon: 'success' })
setTimeout(() => {
if (isAddingCard || session.child_id) {
goDevicePage()
} else {
goManagePage()
}
}, 500)
setBindResultDestination(isAddingCard || session.child_id ? '/pages/device/index' : '/pages/sleep/index')
return
}
@@ -568,7 +564,7 @@ export default function Bind() {
if (loading) {
return (
<View className='bind-page'>
<View className='bind-page' style={getPageStyle(true)}>
<View className='loading'>
<Text>加载中...</Text>
</View>
@@ -577,8 +573,68 @@ export default function Bind() {
)
}
const sessionVisible = bindStatus !== null && [
SESSION_STATUS_PENDING, SESSION_STATUS_COMPLETED, SESSION_STATUS_EXPIRED,
SESSION_STATUS_FAILED, SESSION_STATUS_CANCELLED,
].includes(bindStatus)
if (sessionVisible) {
const completed = bindStatus === SESSION_STATUS_COMPLETED
const pending = bindStatus === SESSION_STATUS_PENDING
const title = pending ? '请在设备上贴卡' : completed
? isAddingCard ? '新卡添加完成' : '设备绑定成功'
: isExpiredBind ? '贴卡时间已过' : '贴卡未完成'
return (
<View className='bind-page bind-state-page' style={getPageStyle(true)}>
<View className='bind-header'>
<View className='back-btn' onClick={handleBack}>
<Image className='back-icon' src={require('../../assets/tab-icons/arrow-left.png')} mode='aspectFit' />
<Text className='back-text'>返回</Text>
</View>
</View>
<View className='bind-result'>
{pending ? (
<>
<Text className='bind-result-title'>{title}</Text>
<View className='bind-countdown-ring'>
<Text className='bind-countdown-value'>{formatRemainingTime(remainingBindSeconds)}</Text>
<Text className='bind-countdown-label'>剩余贴卡时间</Text>
</View>
<View className='bind-instruction'>
<Text className='bind-instruction-title'>{isAddingCard ? '加卡指令已发送' : '绑卡指令已发送'}</Text>
<Text className='bind-result-description'>{bindHint}</Text>
</View>
<Button className='bind-result-button waiting' disabled>等待设备确认</Button>
</>
) : (
<>
<Image className='bind-result-art' mode='aspectFit'
src={completed ? require('../../assets/ui/dog-success.png') : require('../../assets/ui/dog-failure.png')} />
<Text className='bind-result-title'>{title}</Text>
<Text className='bind-result-description'>{bindHint}</Text>
{completed ? (
<Button className='bind-result-button primary' onClick={() => Taro.reLaunch({ url: bindResultDestination })}>
{bindResultDestination.includes('/sleep/') ? '去关联宝贝' : '返回首页'}
</Button>
) : (
<>
<Button className='bind-result-button primary' onClick={() => {
resetBindSessionState()
if (isExpiredBind && !isAddingCard) handleScanCode()
}}>重新开始</Button>
<Button className='bind-result-button secondary' onClick={goDevicePage}>返回首页</Button>
</>
)}
</>
)}
</View>
{systemBanner}
</View>
)
}
return (
<View className='bind-page'>
<View className='bind-page' style={getPageStyle(true)}>
<View className='bind-header'>
<View className='back-btn' onClick={handleBack}>
<Image className='back-icon' src={require('../../assets/tab-icons/arrow-left.png')} mode='aspectFit' />
@@ -587,16 +643,6 @@ export default function Bind() {
<Text className='title'>{pageTitle}</Text>
</View>
{bindStatus === SESSION_STATUS_PENDING && (
<Image className='bind-state-mascot pending' src={require('../../assets/ui/dog-running.png')} mode='aspectFit' />
)}
{bindStatus === SESSION_STATUS_COMPLETED && (
<Image className='bind-state-mascot success' src={require('../../assets/ui/dog-success.png')} mode='aspectFit' />
)}
{(bindStatus === SESSION_STATUS_EXPIRED || bindStatus === SESSION_STATUS_FAILED || bindStatus === SESSION_STATUS_CANCELLED) && (
<Image className='bind-state-mascot failure' src={require('../../assets/ui/dog-failure.png')} mode='aspectFit' />
)}
{isAddingCard ? (
<View className='pending-device-card'>
<View className='icon-bg orange'>