Handle unassigned device after child deletion
This commit is contained in:
@@ -126,6 +126,7 @@ function getAlarmLocationHint(alarm: DeviceAlarmItem | null): string {
|
|||||||
export default function Device() {
|
export default function Device() {
|
||||||
const systemBanner = useSystemBanner()
|
const systemBanner = useSystemBanner()
|
||||||
const [binding, setBinding] = useState<Binding | null>(null)
|
const [binding, setBinding] = useState<Binding | null>(null)
|
||||||
|
const [pendingBinding, setPendingBinding] = useState<Binding | null>(null)
|
||||||
const [child, setChild] = useState<Child | null>(null)
|
const [child, setChild] = useState<Child | null>(null)
|
||||||
const [deviceStatus, setDeviceStatus] = useState<DeviceStatus | null>(null)
|
const [deviceStatus, setDeviceStatus] = useState<DeviceStatus | null>(null)
|
||||||
const [deviceAlarms, setDeviceAlarms] = useState<DeviceAlarmItem[]>([])
|
const [deviceAlarms, setDeviceAlarms] = useState<DeviceAlarmItem[]>([])
|
||||||
@@ -144,6 +145,7 @@ export default function Device() {
|
|||||||
const loadDeviceInfo = async () => {
|
const loadDeviceInfo = async () => {
|
||||||
if (!getToken()) {
|
if (!getToken()) {
|
||||||
setBinding(null)
|
setBinding(null)
|
||||||
|
setPendingBinding(null)
|
||||||
setChild(null)
|
setChild(null)
|
||||||
setDeviceStatus(null)
|
setDeviceStatus(null)
|
||||||
setDeviceAlarms([])
|
setDeviceAlarms([])
|
||||||
@@ -159,6 +161,7 @@ export default function Device() {
|
|||||||
const context = await loadCurrentChildBindingContext()
|
const context = await loadCurrentChildBindingContext()
|
||||||
setChild(context.currentChild)
|
setChild(context.currentChild)
|
||||||
setBinding(context.currentBinding)
|
setBinding(context.currentBinding)
|
||||||
|
setPendingBinding(context.pendingBinding)
|
||||||
|
|
||||||
if (context.currentBinding?.device_id) {
|
if (context.currentBinding?.device_id) {
|
||||||
const [nextStatus, nextAlarms] = await Promise.all([
|
const [nextStatus, nextAlarms] = await Promise.all([
|
||||||
@@ -324,6 +327,7 @@ export default function Device() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!child) {
|
if (!child) {
|
||||||
|
const hasPendingDevice = Boolean(pendingBinding?.device_id)
|
||||||
return (
|
return (
|
||||||
<View className='device-page'>
|
<View className='device-page'>
|
||||||
<View className='page-header'>
|
<View className='page-header'>
|
||||||
@@ -334,10 +338,14 @@ export default function Device() {
|
|||||||
<View className='empty-robot'>
|
<View className='empty-robot'>
|
||||||
<Image className='robot-img' src={require('../../assets/tab-icons/robot.png')} mode='aspectFit' />
|
<Image className='robot-img' src={require('../../assets/tab-icons/robot.png')} mode='aspectFit' />
|
||||||
</View>
|
</View>
|
||||||
<Text className='empty-title'>先绑定一台伴伴设备</Text>
|
<Text className='empty-title'>{hasPendingDevice ? '设备已绑定,待关联孩子' : '先绑定一台伴伴设备'}</Text>
|
||||||
<Text className='empty-subtitle'>绑定时可以选择已有孩子,或直接新建孩子昵称</Text>
|
<Text className='empty-subtitle'>
|
||||||
<View className='empty-btn' onClick={() => Taro.navigateTo({ url: '/pages/bind/index' })}>
|
{hasPendingDevice
|
||||||
<Text className='empty-btn-text'>添加设备</Text>
|
? '这台设备还没有关联孩子,关联后即可查看定位、聊天和设备状态'
|
||||||
|
: '绑定时可以选择已有孩子,或直接新建孩子昵称'}
|
||||||
|
</Text>
|
||||||
|
<View className='empty-btn' onClick={() => Taro.navigateTo({ url: hasPendingDevice ? '/pages/bind/index?mode=assign' : '/pages/bind/index' })}>
|
||||||
|
<Text className='empty-btn-text'>{hasPendingDevice ? '关联孩子' : '添加设备'}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{systemBanner}
|
{systemBanner}
|
||||||
@@ -346,6 +354,7 @@ export default function Device() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!binding) {
|
if (!binding) {
|
||||||
|
const hasPendingDevice = Boolean(pendingBinding?.device_id)
|
||||||
return (
|
return (
|
||||||
<View className='device-page'>
|
<View className='device-page'>
|
||||||
<View className='page-header'>
|
<View className='page-header'>
|
||||||
@@ -366,10 +375,14 @@ export default function Device() {
|
|||||||
<View className='empty-robot'>
|
<View className='empty-robot'>
|
||||||
<Image className='robot-img' src={require('../../assets/tab-icons/robot.png')} mode='aspectFit' />
|
<Image className='robot-img' src={require('../../assets/tab-icons/robot.png')} mode='aspectFit' />
|
||||||
</View>
|
</View>
|
||||||
<Text className='empty-title'>给当前孩子绑定一台设备</Text>
|
<Text className='empty-title'>{hasPendingDevice ? '有设备待关联' : '给当前孩子绑定一台设备'}</Text>
|
||||||
<Text className='empty-subtitle'>绑定后,这个孩子的聊天记录、定位和设备状态都会显示在首页</Text>
|
<Text className='empty-subtitle'>
|
||||||
<View className='empty-btn' onClick={() => Taro.navigateTo({ url: '/pages/bind/index' })}>
|
{hasPendingDevice
|
||||||
<Text className='empty-btn-text'>去绑定设备</Text>
|
? `设备 ${pendingBinding?.device_id} 还没有关联孩子,可以关联到当前孩子`
|
||||||
|
: '绑定后,这个孩子的聊天记录、定位和设备状态都会显示在首页'}
|
||||||
|
</Text>
|
||||||
|
<View className='empty-btn' onClick={() => Taro.navigateTo({ url: hasPendingDevice ? '/pages/bind/index?mode=assign' : '/pages/bind/index' })}>
|
||||||
|
<Text className='empty-btn-text'>{hasPendingDevice ? '关联到当前孩子' : '去绑定设备'}</Text>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
{systemBanner}
|
{systemBanner}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ export interface BindingCardGroupListResponse {
|
|||||||
export interface BindingChildContext {
|
export interface BindingChildContext {
|
||||||
currentChild: Child | null
|
currentChild: Child | null
|
||||||
currentBinding: Binding | null
|
currentBinding: Binding | null
|
||||||
|
pendingBinding: Binding | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DirectBindPayload {
|
export interface DirectBindPayload {
|
||||||
@@ -253,9 +254,23 @@ export function resolveBindingForChild<T extends { child_id: number | null }>(
|
|||||||
return childBindings[0] || null
|
return childBindings[0] || null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function resolveUnassignedBinding<T extends { child_id: number | null; device_id: string }>(items: T[]): T | null {
|
||||||
|
const unassignedBindings = items.filter((item) => item.device_id && item.child_id === null)
|
||||||
|
if (unassignedBindings.length === 0) return null
|
||||||
|
|
||||||
|
const selectedDeviceId = getSelectedBindingDeviceId()
|
||||||
|
if (selectedDeviceId) {
|
||||||
|
const selectedBinding = unassignedBindings.find((item) => item.device_id === selectedDeviceId) || null
|
||||||
|
if (selectedBinding) return selectedBinding
|
||||||
|
}
|
||||||
|
|
||||||
|
return unassignedBindings[0] || null
|
||||||
|
}
|
||||||
|
|
||||||
export function syncChildAndBindingSelection(children: Child[], bindings: Binding[]): BindingChildContext {
|
export function syncChildAndBindingSelection(children: Child[], bindings: Binding[]): BindingChildContext {
|
||||||
const currentChild = resolveChildSelection(children)
|
const currentChild = resolveChildSelection(children)
|
||||||
const currentBinding = currentChild ? resolveBindingForChild(bindings, currentChild.child_id) : null
|
const childBinding = currentChild ? resolveBindingForChild(bindings, currentChild.child_id) : null
|
||||||
|
const unassignedBinding = resolveUnassignedBinding(bindings)
|
||||||
|
|
||||||
if (currentChild) {
|
if (currentChild) {
|
||||||
setSelectedChildId(currentChild.child_id)
|
setSelectedChildId(currentChild.child_id)
|
||||||
@@ -263,15 +278,18 @@ export function syncChildAndBindingSelection(children: Child[], bindings: Bindin
|
|||||||
clearSelectedChildId()
|
clearSelectedChildId()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentBinding?.device_id) {
|
if (childBinding?.device_id) {
|
||||||
setSelectedBindingDeviceId(currentBinding.device_id)
|
setSelectedBindingDeviceId(childBinding.device_id)
|
||||||
|
} else if (unassignedBinding?.device_id) {
|
||||||
|
setSelectedBindingDeviceId(unassignedBinding.device_id)
|
||||||
} else {
|
} else {
|
||||||
clearSelectedBindingDeviceId()
|
clearSelectedBindingDeviceId()
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
currentChild,
|
currentChild,
|
||||||
currentBinding,
|
currentBinding: childBinding,
|
||||||
|
pendingBinding: unassignedBinding,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,16 +298,18 @@ export async function loadCurrentChildBindingContext(): Promise<{
|
|||||||
bindings: Binding[]
|
bindings: Binding[]
|
||||||
currentChild: Child | null
|
currentChild: Child | null
|
||||||
currentBinding: Binding | null
|
currentBinding: Binding | null
|
||||||
|
pendingBinding: Binding | null
|
||||||
}> {
|
}> {
|
||||||
const [childResponse, bindingResponse] = await Promise.all([getChildren(undefined, 100), getBindings(undefined, 100)])
|
const [childResponse, bindingResponse] = await Promise.all([getChildren(undefined, 100), getBindings(undefined, 100)])
|
||||||
const children = childResponse.items || []
|
const children = childResponse.items || []
|
||||||
const bindings = bindingResponse.items || []
|
const bindings = bindingResponse.items || []
|
||||||
const { currentChild, currentBinding } = syncChildAndBindingSelection(children, bindings)
|
const { currentChild, currentBinding, pendingBinding } = syncChildAndBindingSelection(children, bindings)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
children,
|
children,
|
||||||
bindings,
|
bindings,
|
||||||
currentChild,
|
currentChild,
|
||||||
currentBinding,
|
currentBinding,
|
||||||
|
pendingBinding,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user