feat: allow binding device without child
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { View, Text, Image, Input, Button } from '@tarojs/components'
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
import Taro, { useDidShow, useDidHide } from '@tarojs/taro'
|
||||
import Taro, { useDidShow, useDidHide, useRouter } from '@tarojs/taro'
|
||||
|
||||
import { getToken } from '@/services/auth'
|
||||
import {
|
||||
@@ -83,6 +83,8 @@ function parseBindingPayload(rawValue: string): { deviceId: string; serialNumber
|
||||
}
|
||||
|
||||
export default function Bind() {
|
||||
const router = useRouter()
|
||||
const isAssignMode = String(router.params?.mode || '').trim() === 'assign'
|
||||
const systemBanner = useSystemBanner()
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [submitting, setSubmitting] = useState(false)
|
||||
@@ -112,12 +114,17 @@ export default function Bind() {
|
||||
const hasSelectedOrNewChild = selectedChildId !== null || Boolean(newChildName.trim())
|
||||
const isPendingBinding = Boolean(pendingDeviceId)
|
||||
const isPollingBind = bindStatus === SESSION_STATUS_PENDING && Boolean(bindToken)
|
||||
const canEditDeviceFields = hasSelectedOrNewChild && !isPollingBind
|
||||
const canEditDeviceFields = !isPendingBinding && !isPollingBind
|
||||
const canSubmit = isPendingBinding ? hasSelectedOrNewChild : !isPollingBind
|
||||
|
||||
const goDevicePage = () => {
|
||||
Taro.reLaunch({ url: '/pages/device/index' })
|
||||
}
|
||||
|
||||
const goManagePage = () => {
|
||||
Taro.switchTab({ url: '/pages/sleep/index' })
|
||||
}
|
||||
|
||||
const handleBack = () => {
|
||||
if (getCurrentPages().length > 1) {
|
||||
Taro.navigateBack()
|
||||
@@ -167,10 +174,18 @@ export default function Bind() {
|
||||
|
||||
if (session.status === SESSION_STATUS_COMPLETED) {
|
||||
setSelectedBindingDeviceId(session.device_id)
|
||||
setBindHint(session.card_uuid ? `绑定完成,卡号 ${session.card_uuid}` : '绑定完成')
|
||||
setBindHint(
|
||||
session.child_id
|
||||
? session.card_uuid ? `绑定完成,卡号 ${session.card_uuid}` : '绑定完成'
|
||||
: session.card_uuid ? `绑定完成,卡号 ${session.card_uuid},稍后可关联孩子` : '绑定完成,稍后可关联孩子'
|
||||
)
|
||||
Taro.showToast({ title: '设备绑定成功', icon: 'success' })
|
||||
setTimeout(() => {
|
||||
goDevicePage()
|
||||
if (session.child_id) {
|
||||
goDevicePage()
|
||||
} else {
|
||||
goManagePage()
|
||||
}
|
||||
}, 500)
|
||||
return
|
||||
}
|
||||
@@ -209,7 +224,7 @@ export default function Bind() {
|
||||
setChildren(currentChildren)
|
||||
setSelectedChildId(currentChild?.child_id || null)
|
||||
|
||||
if (activeBinding?.device_id && !activeBinding.child_id) {
|
||||
if (isAssignMode && activeBinding?.device_id && !activeBinding.child_id) {
|
||||
setPendingDeviceId(activeBinding.device_id)
|
||||
setDeviceId(activeBinding.device_id)
|
||||
} else {
|
||||
@@ -243,7 +258,7 @@ export default function Bind() {
|
||||
const handleScanCode = () => {
|
||||
if (!canEditDeviceFields) {
|
||||
Taro.showToast({
|
||||
title: '请先选择或新建儿童资料',
|
||||
title: isPollingBind ? '绑定确认中,请稍候' : '当前不能扫码',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
@@ -283,11 +298,11 @@ export default function Bind() {
|
||||
|
||||
try {
|
||||
const childId = await ensureChildId()
|
||||
if (!childId) {
|
||||
throw new Error('请先选择儿童或填写新的儿童昵称')
|
||||
}
|
||||
|
||||
if (isPendingBinding) {
|
||||
if (!childId) {
|
||||
throw new Error('请先选择儿童或填写新的儿童昵称')
|
||||
}
|
||||
await setBindingChild(pendingDeviceId!, { child_id: childId })
|
||||
setSelectedBindingDeviceId(pendingDeviceId)
|
||||
Taro.showToast({ title: '关联完成', icon: 'success' })
|
||||
@@ -305,15 +320,15 @@ export default function Bind() {
|
||||
}
|
||||
|
||||
resetBindSessionState()
|
||||
const session = await startNFCBind({
|
||||
const bindPayload = {
|
||||
device_id: deviceId.trim(),
|
||||
serial_number: serialNumber.trim(),
|
||||
child_id: childId,
|
||||
})
|
||||
}
|
||||
const session = await startNFCBind(childId ? { ...bindPayload, child_id: childId } : bindPayload)
|
||||
|
||||
setBindToken(session.bind_token)
|
||||
setBindStatus(session.status)
|
||||
setBindHint('已发送绑卡指令,请去设备上贴自己的卡')
|
||||
setBindHint(childId ? '已发送绑卡指令,请去设备上贴自己的卡' : '已发送绑卡指令,贴卡后设备会先进入待关联状态')
|
||||
schedulePoll(session.bind_token)
|
||||
Taro.showToast({ title: '请去设备上贴卡', icon: 'none' })
|
||||
} catch (error: any) {
|
||||
@@ -366,11 +381,9 @@ export default function Bind() {
|
||||
<Image className='control-icon-img' src={require('../../assets/tab-icons/rings.png')} mode='aspectFit' />
|
||||
</View>
|
||||
<Text className='scan-text'>
|
||||
{!canEditDeviceFields ? '请先完成儿童资料' : isScanning ? '正在扫码...' : '点击扫码'}
|
||||
</Text>
|
||||
<Text className='scan-hint'>
|
||||
{!canEditDeviceFields ? '先选儿童,再扫设备二维码' : '扫描设备二维码或条码'}
|
||||
{isScanning ? '正在扫码...' : '点击扫码'}
|
||||
</Text>
|
||||
<Text className='scan-hint'>扫描设备二维码或条码</Text>
|
||||
</View>
|
||||
|
||||
<View className='scan-corners'>
|
||||
@@ -388,6 +401,18 @@ export default function Bind() {
|
||||
|
||||
{children.length > 0 && (
|
||||
<View className='child-list'>
|
||||
{!isPendingBinding && (
|
||||
<View
|
||||
className={`child-item ${!hasSelectedOrNewChild ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setSelectedChildId(null)
|
||||
setStoredSelectedChildId(null)
|
||||
setNewChildName('')
|
||||
}}
|
||||
>
|
||||
<Text className='child-item-text'>暂不关联孩子</Text>
|
||||
</View>
|
||||
)}
|
||||
{children.map((child) => (
|
||||
<View
|
||||
key={child.child_id}
|
||||
@@ -408,11 +433,15 @@ export default function Bind() {
|
||||
)}
|
||||
|
||||
<View className='field-item'>
|
||||
<Text className='field-label'>新建儿童昵称</Text>
|
||||
<Text className='field-label'>{isPendingBinding ? '新建儿童昵称' : '新建儿童昵称(可选)'}</Text>
|
||||
<Input
|
||||
className='field-input'
|
||||
value={newChildName}
|
||||
placeholder={children.length > 0 ? '不选已有儿童时,可填写新昵称' : '请输入儿童昵称'}
|
||||
placeholder={
|
||||
isPendingBinding
|
||||
? children.length > 0 ? '不选已有儿童时,可填写新昵称' : '请输入儿童昵称'
|
||||
: children.length > 0 ? '不选已有儿童时,可填写新昵称' : '可不填,稍后再关联孩子'
|
||||
}
|
||||
onInput={(event) => {
|
||||
setNewChildName(event.detail.value)
|
||||
if (event.detail.value) {
|
||||
@@ -429,8 +458,8 @@ export default function Bind() {
|
||||
? '可以选已有儿童,也可以新建一个儿童后关联当前设备'
|
||||
: '当前还没有儿童资料,请先创建一个儿童资料后关联设备'
|
||||
: children.length > 0
|
||||
? '可以选已有儿童,也可以在这里新建一个儿童后再绑定设备'
|
||||
: '当前还没有儿童资料,请先创建一个儿童资料'}
|
||||
? '儿童资料可选;不选择时,设备会先绑定到账号,稍后可关联孩子'
|
||||
: '也可以先不创建儿童,直接绑定设备,稍后再关联孩子'}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
@@ -444,7 +473,7 @@ export default function Bind() {
|
||||
className='field-input'
|
||||
value={deviceId}
|
||||
disabled={!canEditDeviceFields || isPendingBinding}
|
||||
placeholder={canEditDeviceFields ? '请输入设备号' : '请先选择儿童资料'}
|
||||
placeholder={canEditDeviceFields ? '请输入设备号' : '绑定确认中'}
|
||||
onInput={(event) => setDeviceId(event.detail.value)}
|
||||
/>
|
||||
</View>
|
||||
@@ -455,7 +484,7 @@ export default function Bind() {
|
||||
className='field-input'
|
||||
value={serialNumber}
|
||||
disabled={!canEditDeviceFields || isPendingBinding}
|
||||
placeholder={canEditDeviceFields ? '请输入设备序列号' : '请先选择儿童资料'}
|
||||
placeholder={canEditDeviceFields ? '请输入设备序列号' : '绑定确认中'}
|
||||
onInput={(event) => setSerialNumber(event.detail.value)}
|
||||
/>
|
||||
</View>
|
||||
@@ -478,7 +507,7 @@ export default function Bind() {
|
||||
<Button
|
||||
className='submit-btn'
|
||||
loading={submitting}
|
||||
disabled={submitting || !hasSelectedOrNewChild || isPollingBind}
|
||||
disabled={submitting || !canSubmit}
|
||||
onClick={handleSubmit}
|
||||
>
|
||||
{isPendingBinding ? '完成儿童关联' : isPollingBind ? '等待贴卡确认' : '发送绑卡指令'}
|
||||
@@ -489,7 +518,7 @@ export default function Bind() {
|
||||
<Text className='tips-title'>绑定帮助</Text>
|
||||
<View className='tip-item'>
|
||||
<Text className='tip-number'>1</Text>
|
||||
<Text className='tip-text'>先选择已有儿童,或者在本页新建一个儿童</Text>
|
||||
<Text className='tip-text'>{isPendingBinding ? '先选择已有儿童,或者在本页新建一个儿童' : '儿童资料可选,不选择时设备会先进入待关联状态'}</Text>
|
||||
</View>
|
||||
<View className='tip-item'>
|
||||
<Text className='tip-number'>2</Text>
|
||||
|
||||
@@ -343,7 +343,7 @@ export default function Sleep() {
|
||||
if (!targetBinding?.device_id) return
|
||||
setSelectedBindingDeviceId(targetBinding.device_id)
|
||||
setShowAssignDeviceModal(false)
|
||||
Taro.navigateTo({ url: '/pages/bind/index' })
|
||||
Taro.navigateTo({ url: '/pages/bind/index?mode=assign' })
|
||||
}
|
||||
|
||||
const handleSubmitModal = async () => {
|
||||
@@ -559,14 +559,6 @@ export default function Sleep() {
|
||||
}
|
||||
|
||||
if (item.name === '绑定设备') {
|
||||
if (!currentChild) {
|
||||
handleOpenModal('add')
|
||||
Taro.showToast({
|
||||
title: '请先添加儿童资料',
|
||||
icon: 'none',
|
||||
})
|
||||
return
|
||||
}
|
||||
Taro.navigateTo({ url: '/pages/bind/index' })
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user