Compare commits
2 Commits
cd32d4e64c
...
aea7a3fe42
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aea7a3fe42 | ||
|
|
57bafb003d |
@@ -68,6 +68,41 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.pending-device-card {
|
||||
margin: 0 48px 48px;
|
||||
background: #FFFFFF;
|
||||
border-radius: 24px;
|
||||
padding: 48px 40px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.pending-device-title {
|
||||
font-size: 34px;
|
||||
font-weight: 700;
|
||||
color: #1A1A1A;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.pending-device-id {
|
||||
max-width: 100%;
|
||||
font-size: 28px;
|
||||
color: #FF8C42;
|
||||
font-weight: 600;
|
||||
word-break: break-all;
|
||||
text-align: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.pending-device-desc {
|
||||
font-size: 26px;
|
||||
color: #666666;
|
||||
text-align: center;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.scan-frame {
|
||||
background: #FFFFFF;
|
||||
border-radius: 24px;
|
||||
|
||||
@@ -350,26 +350,37 @@ export default function Bind() {
|
||||
<Text className='title'>{isPendingBinding ? '补全绑定' : '扫码贴卡绑定设备'}</Text>
|
||||
</View>
|
||||
|
||||
<View className='scan-area'>
|
||||
<View className='scan-frame' onClick={handleScanCode}>
|
||||
{isPendingBinding ? (
|
||||
<View className='pending-device-card'>
|
||||
<View className='icon-bg orange'>
|
||||
<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 ? '先选儿童,再扫设备二维码' : '扫描设备二维码或条码'}
|
||||
</Text>
|
||||
<Text className='pending-device-title'>关联现有设备</Text>
|
||||
<Text className='pending-device-id'>{pendingDeviceId}</Text>
|
||||
<Text className='pending-device-desc'>选择已有孩子,或新建孩子后完成关联</Text>
|
||||
</View>
|
||||
) : (
|
||||
<View className='scan-area'>
|
||||
<View className='scan-frame' onClick={handleScanCode}>
|
||||
<View className='icon-bg orange'>
|
||||
<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 ? '先选儿童,再扫设备二维码' : '扫描设备二维码或条码'}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View className='scan-corners'>
|
||||
<View className='corner top-left'></View>
|
||||
<View className='corner top-right'></View>
|
||||
<View className='corner bottom-left'></View>
|
||||
<View className='corner bottom-right'></View>
|
||||
<View className='scan-corners'>
|
||||
<View className='corner top-left'></View>
|
||||
<View className='corner top-right'></View>
|
||||
<View className='corner bottom-left'></View>
|
||||
<View className='corner bottom-right'></View>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
<View className='bind-form'>
|
||||
<View className='form-card'>
|
||||
@@ -413,12 +424,17 @@ export default function Bind() {
|
||||
</View>
|
||||
|
||||
<Text className='field-hint'>
|
||||
{children.length > 0
|
||||
? '可以选已有儿童,也可以在这里新建一个儿童后再绑定设备'
|
||||
: '当前还没有儿童资料,请先创建一个儿童资料'}
|
||||
{isPendingBinding
|
||||
? children.length > 0
|
||||
? '可以选已有儿童,也可以新建一个儿童后关联当前设备'
|
||||
: '当前还没有儿童资料,请先创建一个儿童资料后关联设备'
|
||||
: children.length > 0
|
||||
? '可以选已有儿童,也可以在这里新建一个儿童后再绑定设备'
|
||||
: '当前还没有儿童资料,请先创建一个儿童资料'}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{!isPendingBinding && (
|
||||
<View className='form-card'>
|
||||
<Text className='form-title'>设备信息</Text>
|
||||
|
||||
@@ -457,6 +473,7 @@ export default function Bind() {
|
||||
</View>
|
||||
)}
|
||||
</View>
|
||||
)}
|
||||
|
||||
<Button
|
||||
className='submit-btn'
|
||||
@@ -476,11 +493,11 @@ export default function Bind() {
|
||||
</View>
|
||||
<View className='tip-item'>
|
||||
<Text className='tip-number'>2</Text>
|
||||
<Text className='tip-text'>扫描设备二维码,确认设备号和序列号正确</Text>
|
||||
<Text className='tip-text'>{isPendingBinding ? '确认当前待关联设备,再选择要关联的孩子' : '扫描设备二维码,确认设备号和序列号正确'}</Text>
|
||||
</View>
|
||||
<View className='tip-item'>
|
||||
<Text className='tip-number'>3</Text>
|
||||
<Text className='tip-text'>点击发送绑卡指令,然后去设备上贴自己的卡完成确认</Text>
|
||||
<Text className='tip-text'>{isPendingBinding ? '点击完成儿童关联,设备会出现在该孩子下面' : '点击发送绑卡指令,然后去设备上贴自己的卡完成确认'}</Text>
|
||||
</View>
|
||||
</View>
|
||||
{systemBanner}
|
||||
|
||||
@@ -41,6 +41,14 @@ function getSignalLabel(value?: number | null): string {
|
||||
return '弱'
|
||||
}
|
||||
|
||||
function formatBatteryDisplay(value?: number | null): { text: string; showPercent: boolean } {
|
||||
if (value === null || value === undefined) return { text: '--', showPercent: false }
|
||||
const normalized = Number(value)
|
||||
if (!Number.isFinite(normalized)) return { text: '--', showPercent: false }
|
||||
if (normalized === 0) return { text: '*', showPercent: false }
|
||||
return { text: String(normalized), showPercent: true }
|
||||
}
|
||||
|
||||
function formatSleepRange(status: DeviceStatus | null): string {
|
||||
const start = status?.disable_time_start?.trim()
|
||||
const end = status?.disable_time_end?.trim()
|
||||
@@ -284,7 +292,7 @@ export default function Device() {
|
||||
const childName = child.child_name || '未设置'
|
||||
const pageTitle = `${childName} 的伴伴`
|
||||
const batteryValue = deviceStatus?.power ?? deviceStatus?.battery_pct ?? null
|
||||
const batteryDisplay = batteryValue === null || batteryValue === undefined ? '--' : String(batteryValue)
|
||||
const batteryDisplay = formatBatteryDisplay(batteryValue)
|
||||
const signalLabel = getSignalLabel(deviceStatus?.signal)
|
||||
const versionLabel = deviceStatus?.version || '--'
|
||||
const coordinateLabel = formatCoordinates(deviceStatus)
|
||||
@@ -307,8 +315,8 @@ export default function Device() {
|
||||
</View>
|
||||
<View className='battery-section'>
|
||||
<Text className='battery-percent'>
|
||||
{batteryDisplay}
|
||||
{batteryDisplay !== '--' && <Text className='percent'>%</Text>}
|
||||
{batteryDisplay.text}
|
||||
{batteryDisplay.showPercent && <Text className='percent'>%</Text>}
|
||||
</Text>
|
||||
<Text className='battery-label'>当前电量</Text>
|
||||
</View>
|
||||
|
||||
@@ -68,6 +68,7 @@ export default function Sleep() {
|
||||
const [showDeleteChildModal, setShowDeleteChildModal] = useState(false)
|
||||
const [showRoleModal, setShowRoleModal] = useState(false)
|
||||
const [showFamilyModal, setShowFamilyModal] = useState(false)
|
||||
const [showAssignDeviceModal, setShowAssignDeviceModal] = useState(false)
|
||||
const [modalType, setModalType] = useState<'add' | 'edit'>('add')
|
||||
const [childName, setChildName] = useState('')
|
||||
const [editingChildId, setEditingChildId] = useState<number | null>(null)
|
||||
@@ -334,9 +335,17 @@ export default function Sleep() {
|
||||
|
||||
const handleOpenAddChildFromSwitch = () => {
|
||||
setShowChildModal(false)
|
||||
setShowAssignDeviceModal(false)
|
||||
handleOpenModal('add')
|
||||
}
|
||||
|
||||
const handleAssignExistingDevice = (targetBinding: BindingListItem) => {
|
||||
if (!targetBinding?.device_id) return
|
||||
setSelectedBindingDeviceId(targetBinding.device_id)
|
||||
setShowAssignDeviceModal(false)
|
||||
Taro.navigateTo({ url: '/pages/bind/index' })
|
||||
}
|
||||
|
||||
const handleSubmitModal = async () => {
|
||||
const normalizedName = childName.trim()
|
||||
if (!normalizedName) {
|
||||
@@ -544,6 +553,11 @@ export default function Sleep() {
|
||||
return
|
||||
}
|
||||
|
||||
if (item.name === '关联现有设备') {
|
||||
setShowAssignDeviceModal(true)
|
||||
return
|
||||
}
|
||||
|
||||
if (item.name === '绑定设备') {
|
||||
if (!currentChild) {
|
||||
handleOpenModal('add')
|
||||
@@ -584,6 +598,7 @@ export default function Sleep() {
|
||||
}
|
||||
|
||||
const parentDisplayName = parentInfo.nickname?.trim() || '家长'
|
||||
const unassignedBindings = bindings.filter((item) => item.device_id && item.child_id === null)
|
||||
const currentFirmwareLabel = firmwareStatus?.current_version || '--'
|
||||
const latestFirmwareLabel = firmwareStatus?.latest_version || '--'
|
||||
const currentUserId = getCurrentUserId()
|
||||
@@ -637,6 +652,15 @@ export default function Sleep() {
|
||||
arrow: true,
|
||||
disabled: children.length === 0,
|
||||
},
|
||||
...(unassignedBindings.length > 0
|
||||
? [{
|
||||
icon: require('../../assets/tab-icons/rings.png'),
|
||||
iconBgClass: 'green',
|
||||
name: '关联现有设备',
|
||||
value: `${unassignedBindings.length} 台待关联`,
|
||||
arrow: true,
|
||||
}]
|
||||
: []),
|
||||
{
|
||||
icon: require('../../assets/tab-icons/rings.png'),
|
||||
iconBgClass: 'green',
|
||||
@@ -856,6 +880,48 @@ export default function Sleep() {
|
||||
</View>
|
||||
)}
|
||||
|
||||
{showAssignDeviceModal && (
|
||||
<View className='modal-mask' onClick={() => setShowAssignDeviceModal(false)}>
|
||||
<View
|
||||
className='modal-card device-switch-card'
|
||||
onClick={(event) => {
|
||||
event.stopPropagation()
|
||||
}}
|
||||
>
|
||||
<Text className='modal-title'>关联现有设备</Text>
|
||||
{unassignedBindings.length === 0 ? (
|
||||
<Text className='device-switch-empty'>当前没有待关联设备</Text>
|
||||
) : (
|
||||
<View className='device-switch-list'>
|
||||
{unassignedBindings.map((item) => (
|
||||
<View
|
||||
key={item.device_id}
|
||||
className='device-switch-item'
|
||||
onClick={() => handleAssignExistingDevice(item)}
|
||||
>
|
||||
<View className='device-switch-head'>
|
||||
<Text className='device-switch-id'>{item.device_id}</Text>
|
||||
<Text className='device-switch-tag'>待关联</Text>
|
||||
</View>
|
||||
<Text className='device-switch-name'>未关联孩子</Text>
|
||||
</View>
|
||||
))}
|
||||
</View>
|
||||
)}
|
||||
<View className='device-switch-footer'>
|
||||
<Text className='device-switch-add' onClick={handleOpenAddChildFromSwitch}>
|
||||
+ 新增孩子
|
||||
</Text>
|
||||
</View>
|
||||
<View className='modal-actions'>
|
||||
<Text className='modal-action cancel' onClick={() => setShowAssignDeviceModal(false)}>
|
||||
关闭
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)}
|
||||
|
||||
{showModal && (
|
||||
<View className='modal-mask'>
|
||||
<View className='modal-card'>
|
||||
|
||||
Reference in New Issue
Block a user