congming_huose-apk/common/mixins/deviceUserWs.js

194 lines
6.2 KiB
JavaScript
Raw Normal View History

/**
* 设备详情页仅监听全局长连接推送并合入展示不在此页 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))
}
},
},
}