304 lines
10 KiB
TypeScript
304 lines
10 KiB
TypeScript
import { get, del } from '../../utils/request/index'
|
||
import { leFuService } from '../../lefu/index'
|
||
import type { UserInfo } from '../../api/index'
|
||
|
||
/** 体重设备(对应 /weighingScale/list/device 返回的 result 元素) */
|
||
interface ScaleDevice {
|
||
/** 记录 ID */
|
||
id: string
|
||
/** 设备 SN */
|
||
scaleDeviceId: string
|
||
/** 连接设备信息(JSON 字符串,含 name、deviceId) */
|
||
connectDeviceInfo: string
|
||
/** 用户数量 */
|
||
userNum: number
|
||
/** 状态 */
|
||
status: false
|
||
}
|
||
|
||
/** 获取体重设备列表(运维模式走 ops/listDevice,普通模式走 v6/list/device) */
|
||
const getDeviceList = () =>
|
||
get<ScaleDevice[]>(
|
||
getApp<IAppOption>().globalData.operationsEngineer
|
||
? 'weighingScale/ops/listDevice'
|
||
: 'weighingScale/v6/list/device',
|
||
)
|
||
|
||
/** 取消配对:id 不传则解除所有设备绑定(运维模式走 ops/deleteUser,普通模式走 v6/unbind) */
|
||
const unbindDevice = (id?: string) => {
|
||
const url = getApp<IAppOption>().globalData.operationsEngineer
|
||
? 'weighingScale/ops/deleteUser'
|
||
: 'weighingScale/v6/unbind'
|
||
return del(`${url}${id ? `?id=${id}` : ''}`, {}, { loading: false })
|
||
}
|
||
|
||
/** 展示用设备项 */
|
||
interface DeviceItem {
|
||
id: string
|
||
name: string
|
||
status: boolean
|
||
deviceId: string
|
||
sn: string
|
||
userNum: number
|
||
connectDeviceInfo: string
|
||
}
|
||
|
||
let unsubDevicesList: (() => void) | null = null
|
||
let unsubConnect: (() => void) | null = null
|
||
let unsubDisconnected: (() => void) | null = null
|
||
let scanTimer: number | null = null
|
||
|
||
Page({
|
||
data: {
|
||
operationsEngineer: false,
|
||
devices: [] as DeviceItem[],
|
||
loadingShow: false,
|
||
loadingTitle: '正在连接设备',
|
||
loadingContent: '请确保设备处于开启状态\n请勿离开...'
|
||
},
|
||
|
||
onShow() {
|
||
this.setData({ operationsEngineer: getApp<IAppOption>().globalData.operationsEngineer ?? false })
|
||
this.loadDevices()
|
||
this._subscribeDisconnected()
|
||
},
|
||
|
||
onHide() {
|
||
leFuService.stopScan()
|
||
unsubDisconnected?.()
|
||
unsubDisconnected = null
|
||
},
|
||
|
||
onUnload() {
|
||
leFuService.stopScan()
|
||
unsubDisconnected?.()
|
||
unsubDisconnected = null
|
||
unsubDevicesList?.()
|
||
unsubDevicesList = null
|
||
unsubConnect?.()
|
||
unsubConnect = null
|
||
if (scanTimer !== null) { clearTimeout(scanTimer); scanTimer = null }
|
||
},
|
||
|
||
/** 订阅断开事件:设备长时间未操作或意外断开时,同步页面状态为未连接 */
|
||
_subscribeDisconnected() {
|
||
unsubDisconnected?.()
|
||
unsubDisconnected = leFuService.onDisconnected(() => {
|
||
this.setData({
|
||
devices: this.data.devices.map(d => ({ ...d, status: false })),
|
||
})
|
||
})
|
||
},
|
||
|
||
/** 拉取体重设备列表 */
|
||
async loadDevices() {
|
||
const raw = wx.getStorageSync('userInfo') as UserInfo | null
|
||
if (!raw?.userId) return
|
||
try {
|
||
const res = await getDeviceList()
|
||
this.setData({
|
||
devices: res.result.map(item => {
|
||
let info: Record<string, any> = {}
|
||
try {
|
||
info = JSON.parse(item.connectDeviceInfo || '{}')
|
||
} catch {}
|
||
return {
|
||
id: item.id,
|
||
name: info.name ?? '',
|
||
status: leFuService.isConnected && leFuService.lastRawDevice?.deviceId === info.deviceId,
|
||
deviceId: info.deviceId ?? '',
|
||
sn: item.scaleDeviceId,
|
||
userNum: item.userNum ?? 0,
|
||
connectDeviceInfo: item.connectDeviceInfo ?? '',
|
||
}
|
||
}),
|
||
})
|
||
} catch {
|
||
// 请求失败已由 request 层统一 toast
|
||
}
|
||
},
|
||
|
||
/** 取消配对:解除指定设备绑定 */
|
||
onTapUnpair(e: WechatMiniprogram.TouchEvent) {
|
||
const item = e.currentTarget.dataset.item as DeviceItem
|
||
wx.showModal({
|
||
title: '取消配对',
|
||
content: '是否确认取消配对当前设备?',
|
||
cancelText: '取消',
|
||
confirmText: '确定',
|
||
confirmColor: '#F24439',
|
||
success: (res) => {
|
||
if (!res.confirm) return
|
||
unbindDevice(item.id)
|
||
.then(() => {
|
||
const cached = wx.getStorageSync('connectDeviceInfo') as Record<string, any> | null
|
||
if (cached?.deviceId === item.deviceId) {
|
||
wx.removeStorageSync('connectDeviceInfo')
|
||
}
|
||
wx.showToast({ title: '已取消配对', icon: 'success' })
|
||
this.loadDevices()
|
||
})
|
||
.catch(() => {})
|
||
},
|
||
})
|
||
},
|
||
|
||
/** 点击设备状态:已连接则断开,未连接则扫描连接 */
|
||
onTapStatus(e: WechatMiniprogram.TouchEvent) {
|
||
const item = e.currentTarget.dataset.item as DeviceItem
|
||
if (item.status) {
|
||
leFuService.disconnect()
|
||
this._updateStatus(item.deviceId, false)
|
||
return
|
||
}
|
||
this._connectDevice(item)
|
||
},
|
||
|
||
/** 扫描蓝牙,找到 deviceId 匹配的设备后连接 */
|
||
_connectDevice(item: DeviceItem) {
|
||
const targetDeviceId = item.deviceId
|
||
if (!targetDeviceId) return
|
||
if (leFuService.isConnected) {
|
||
leFuService.disconnect()
|
||
// 断开后全部置未连接,等新设备连上再标回
|
||
this.setData({
|
||
devices: this.data.devices.map(d => ({ ...d, status: false })),
|
||
})
|
||
}
|
||
|
||
// 清理上一次连接流程的订阅与定时器,避免重复订阅累积
|
||
unsubDevicesList?.()
|
||
unsubDevicesList = null
|
||
unsubConnect?.()
|
||
unsubConnect = null
|
||
if (scanTimer !== null) { clearTimeout(scanTimer); scanTimer = null }
|
||
|
||
wx.showLoading({ title: '连接中...', mask: true })
|
||
wx.openBluetoothAdapter({
|
||
success: () => {
|
||
scanTimer = setTimeout(() => {
|
||
unsubDevicesList?.()
|
||
unsubDevicesList = null
|
||
wx.hideLoading()
|
||
wx.showToast({ title: '未找到设备', icon: 'none' })
|
||
}, 15000)
|
||
|
||
unsubDevicesList = leFuService.onDevicesList((devices) => {
|
||
const matched = devices.find(d => d.raw.deviceId === targetDeviceId)
|
||
if (!matched) return
|
||
if (scanTimer !== null) { clearTimeout(scanTimer); scanTimer = null }
|
||
unsubDevicesList?.()
|
||
unsubDevicesList = null
|
||
leFuService.stopScan()
|
||
leFuService.connect(matched.raw)
|
||
unsubConnect = leFuService.onDeviceConnect(() => {
|
||
unsubConnect?.()
|
||
unsubConnect = null
|
||
wx.hideLoading()
|
||
wx.setStorageSync('connectDeviceInfo', matched.raw)
|
||
this._updateStatus(targetDeviceId, true)
|
||
})
|
||
})
|
||
leFuService.startScan()
|
||
},
|
||
fail: () => {
|
||
wx.hideLoading()
|
||
wx.showToast({ title: '蓝牙未开启', icon: 'none' })
|
||
},
|
||
})
|
||
},
|
||
|
||
_updateStatus(deviceId: string, status: boolean) {
|
||
this.setData({
|
||
devices: this.data.devices.map(item =>
|
||
item.deviceId === deviceId ? { ...item, status } : item
|
||
),
|
||
})
|
||
},
|
||
|
||
/** 底部操作:数据补传 / 设备连接 弹 loading */
|
||
onTapAction(e: WechatMiniprogram.TouchEvent) {
|
||
const action = e.currentTarget.dataset.action as string
|
||
if (action === '数据补传') {
|
||
this.setData({
|
||
loadingShow: true,
|
||
loadingTitle: '正在获取设备本地未上传数据',
|
||
loadingContent: '请稍等...'
|
||
})
|
||
} else if (action === '设备连接') {
|
||
this.setData({
|
||
loadingShow: true,
|
||
loadingTitle: '正在连接设备',
|
||
loadingContent: '请确保设备处于开启状态\n请勿离开...'
|
||
})
|
||
}
|
||
},
|
||
|
||
onCloseLoading() {
|
||
this.setData({ loadingShow: false })
|
||
},
|
||
|
||
/** 用户管理 */
|
||
onTapUser(e: WechatMiniprogram.TouchEvent) {
|
||
const item = e.currentTarget.dataset.item as DeviceItem
|
||
wx.navigateTo({
|
||
url: `/pages/userManagement/userManagement?sn=${encodeURIComponent(item.sn)}&deviceId=${encodeURIComponent(item.deviceId)}&name=${encodeURIComponent(item.name)}&status=${item.status}&connectDeviceInfo=${encodeURIComponent(item.connectDeviceInfo)}`,
|
||
})
|
||
},
|
||
|
||
/** 跳转设备 WiFi 配网页 */
|
||
onTapWifi() {
|
||
wx.navigateTo({ url: '/pages/connectedWifi/connectedWifi' })
|
||
},
|
||
|
||
/** 数据补传:读取设备端 userId 列表(调试用) */
|
||
onTapDataRetransfer() {
|
||
leFuService.fetchDeviceUserIds()
|
||
.then((list) => {
|
||
console.log('[数据补传] userId 列表:', list)
|
||
})
|
||
.catch(() => {
|
||
wx.showToast({ title: '请先连接设备', icon: 'none' })
|
||
})
|
||
},
|
||
|
||
onTapAdd() {
|
||
wx.navigateTo({ url: '/pages/connectedDevice/connectedDevice' })
|
||
},
|
||
|
||
/** 长按 banner 打开运维模式 */
|
||
onLongPressBanner() {
|
||
getApp<IAppOption>().globalData.operationsEngineer = true
|
||
this.setData({ operationsEngineer: true })
|
||
this.loadDevices()
|
||
},
|
||
|
||
/** 关闭运维模式 */
|
||
onCloseOps() {
|
||
getApp<IAppOption>().globalData.operationsEngineer = false
|
||
this.setData({ operationsEngineer: false })
|
||
this.loadDevices()
|
||
},
|
||
|
||
/** 取消全部配对:解除所有设备绑定 */
|
||
onUnpairAll() {
|
||
wx.showModal({
|
||
title: '取消全部配对',
|
||
content: '是否确认取消全部设备的配对?',
|
||
cancelText: '取消',
|
||
confirmText: '确定',
|
||
confirmColor: '#F24439',
|
||
success: (res) => {
|
||
if (!res.confirm) return
|
||
unbindDevice()
|
||
.then(() => {
|
||
wx.removeStorageSync('connectDeviceInfo')
|
||
wx.showToast({ title: '已取消全部配对', icon: 'success' })
|
||
this.loadDevices()
|
||
})
|
||
.catch(() => {})
|
||
},
|
||
})
|
||
}
|
||
})
|