194 lines
6.2 KiB
JavaScript
194 lines
6.2 KiB
JavaScript
/**
|
||
* 设备详情页:仅监听全局长连接推送并合入展示;不在此页 subscribe / unsubscribe。
|
||
* 列表侧(DeviceTab)在设备 Tab 内保持订阅,从列表进详情不会触发列表退订。
|
||
*/
|
||
import { connectIfLoggedIn } from '@/common/utils/appUserWs.js'
|
||
|
||
function normalizeMac(m) {
|
||
if (m === undefined || m === null) return ''
|
||
return String(m).replace(/:/g, '').trim().toUpperCase()
|
||
}
|
||
|
||
function pickDeviceRecord(vm) {
|
||
if (vm.xqobj && typeof vm.xqobj === 'object' && Object.keys(vm.xqobj).length) {
|
||
return vm.xqobj
|
||
}
|
||
if (vm.sbobj && typeof vm.sbobj === 'object' && Object.keys(vm.sbobj).length) {
|
||
return vm.sbobj
|
||
}
|
||
return null
|
||
}
|
||
|
||
function mergeIotDataPoint(ov, nv) {
|
||
if (nv === null) return null
|
||
if (typeof nv !== 'object' || Array.isArray(nv)) {
|
||
return nv
|
||
}
|
||
if (!ov || typeof ov !== 'object' || Array.isArray(ov)) {
|
||
return { ...nv }
|
||
}
|
||
const merged = { ...ov, ...nv }
|
||
// 长连接 patch 里若带 value: undefined 或缺省,不要冲掉 HTTP 里已有 value/desc
|
||
if (Object.prototype.hasOwnProperty.call(nv, 'value') && nv.value === undefined) {
|
||
if (Object.prototype.hasOwnProperty.call(ov, 'value') && ov.value !== undefined) {
|
||
merged.value = ov.value
|
||
}
|
||
}
|
||
if (!Object.prototype.hasOwnProperty.call(nv, 'desc') || nv.desc === undefined || nv.desc === '') {
|
||
if (Object.prototype.hasOwnProperty.call(ov, 'desc') && ov.desc !== undefined && ov.desc !== '') {
|
||
merged.desc = ov.desc
|
||
}
|
||
}
|
||
return merged
|
||
}
|
||
|
||
export default {
|
||
data() {
|
||
return {
|
||
deviceUserWsPageActive: false,
|
||
_deviceWsIotPartials: {},
|
||
}
|
||
},
|
||
onLoad() {
|
||
this._deviceWsIotPartials = {}
|
||
},
|
||
computed: {
|
||
_deviceMacForWs() {
|
||
const r = pickDeviceRecord(this)
|
||
const m = r && r.mac
|
||
return m ? String(m).trim() : ''
|
||
},
|
||
},
|
||
onShow() {
|
||
this.deviceUserWsPageActive = true
|
||
connectIfLoggedIn()
|
||
uni.$off('appWs:deviceData', this._onAppWsDeviceData)
|
||
uni.$off('appWs:deviceOnlineStatus', this._onAppWsDeviceOnlineStatus)
|
||
uni.$on('appWs:deviceData', this._onAppWsDeviceData)
|
||
uni.$on('appWs:deviceOnlineStatus', this._onAppWsDeviceOnlineStatus)
|
||
},
|
||
onHide() {
|
||
uni.$off('appWs:deviceData', this._onAppWsDeviceData)
|
||
uni.$off('appWs:deviceOnlineStatus', this._onAppWsDeviceOnlineStatus)
|
||
this._leaveDeviceUserWs()
|
||
},
|
||
onUnload() {
|
||
uni.$off('appWs:deviceData', this._onAppWsDeviceData)
|
||
uni.$off('appWs:deviceOnlineStatus', this._onAppWsDeviceOnlineStatus)
|
||
this._leaveDeviceUserWs()
|
||
},
|
||
onBeforeUnmount() {
|
||
uni.$off('appWs:deviceData', this._onAppWsDeviceData)
|
||
uni.$off('appWs:deviceOnlineStatus', this._onAppWsDeviceOnlineStatus)
|
||
this._leaveDeviceUserWs()
|
||
},
|
||
methods: {
|
||
_onAppWsDeviceData(msg) {
|
||
if (!this.deviceUserWsPageActive) return
|
||
if (!msg || msg.event !== 'device_data') return
|
||
const outer = msg.data
|
||
if (!outer || typeof outer !== 'object') return
|
||
const myMac = normalizeMac(this._deviceMacForWs)
|
||
if (!myMac) return
|
||
const inner = outer.data
|
||
if (!inner || typeof inner !== 'object') return
|
||
const payloadMac = normalizeMac(inner.mac != null ? inner.mac : outer.mac)
|
||
if (payloadMac && payloadMac !== myMac) return
|
||
const patch = inner.data !== undefined ? inner.data : inner
|
||
if (!patch || typeof patch !== 'object') return
|
||
this._applyDeviceDataPatch(patch)
|
||
},
|
||
_onAppWsDeviceOnlineStatus(msg) {
|
||
if (!this.deviceUserWsPageActive) return
|
||
if (!msg || msg.event !== 'device_online_status') return
|
||
const outer = msg.data
|
||
if (!outer || typeof outer !== 'object') return
|
||
const myMac = normalizeMac(this._deviceMacForWs)
|
||
if (!myMac) return
|
||
const inner = outer.data
|
||
if (!inner || typeof inner !== 'object') return
|
||
const payloadMac = normalizeMac(inner.mac != null ? inner.mac : outer.mac)
|
||
if (payloadMac && payloadMac !== myMac) return
|
||
const statusPayload =
|
||
inner.data !== undefined && typeof inner.data === 'object' ? inner.data : inner
|
||
this._applyDeviceOnlinePatch(statusPayload)
|
||
},
|
||
_applyDeviceDataPatch(patch) {
|
||
const rec = pickDeviceRecord(this)
|
||
if (!rec) return
|
||
if (!rec.iotData) {
|
||
this.$set(rec, 'iotData', {})
|
||
}
|
||
const keys = Object.keys(patch).filter((k) => k !== 'mac')
|
||
let any = false
|
||
for (const k of keys) {
|
||
const nv = patch[k]
|
||
const ov = rec.iotData[k]
|
||
const prevP = this._deviceWsIotPartials[k]
|
||
const pMerged =
|
||
typeof nv === 'object' && nv !== null && !Array.isArray(nv)
|
||
? mergeIotDataPoint(prevP || null, nv)
|
||
: mergeIotDataPoint(prevP || null, { value: nv })
|
||
this.$set(this._deviceWsIotPartials, k, pMerged)
|
||
const nextVal =
|
||
nv !== null && typeof nv === 'object' && !Array.isArray(nv)
|
||
? mergeIotDataPoint(ov, nv)
|
||
: nv
|
||
if (JSON.stringify(ov) === JSON.stringify(nextVal)) continue
|
||
this.$set(rec.iotData, k, nextVal)
|
||
any = true
|
||
}
|
||
if (any && typeof this._afterDeviceUserWsData === 'function') {
|
||
this._afterDeviceUserWsData()
|
||
}
|
||
},
|
||
_applyDeviceOnlinePatch(inner) {
|
||
const rec = pickDeviceRecord(this)
|
||
if (!rec) return
|
||
const os = inner.onlineStatus
|
||
const lot = inner.lastOnlineTime
|
||
let changed = false
|
||
if (os !== undefined && os !== null && os !== '') {
|
||
const n = Number(os)
|
||
if (!Number.isNaN(n) && rec.onlineStatus !== n) {
|
||
this.$set(rec, 'onlineStatus', n)
|
||
changed = true
|
||
}
|
||
}
|
||
if (lot !== undefined && lot !== null && rec.lastOnlineTime !== lot) {
|
||
this.$set(rec, 'lastOnlineTime', lot)
|
||
changed = true
|
||
}
|
||
if (!rec.iotOnlineData) {
|
||
this.$set(rec, 'iotOnlineData', {})
|
||
}
|
||
if (os !== undefined && os !== null && os !== '') {
|
||
const s = String(os)
|
||
if (rec.iotOnlineData.onlineStatus !== s) {
|
||
this.$set(rec.iotOnlineData, 'onlineStatus', s)
|
||
changed = true
|
||
}
|
||
}
|
||
if (changed && typeof this._afterDeviceUserWsData === 'function') {
|
||
this._afterDeviceUserWsData()
|
||
}
|
||
},
|
||
_leaveDeviceUserWs() {
|
||
this.deviceUserWsPageActive = false
|
||
},
|
||
reapplyDeviceWsIotToHttpIotData() {
|
||
const rec = pickDeviceRecord(this)
|
||
if (!rec || !this._deviceWsIotPartials) return
|
||
const pkeys = Object.keys(this._deviceWsIotPartials)
|
||
if (!pkeys.length) return
|
||
if (!rec.iotData) this.$set(rec, 'iotData', {})
|
||
for (const k of pkeys) {
|
||
const p = this._deviceWsIotPartials[k]
|
||
if (p === null || p === undefined) continue
|
||
const base = rec.iotData[k]
|
||
this.$set(rec.iotData, k, mergeIotDataPoint(base, p))
|
||
}
|
||
},
|
||
},
|
||
}
|