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