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))
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
},
|
|||
|
|
}
|