congming_huose-apk/subpackage/device/devicexq.vue

764 lines
27 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="device-detail">
<!-- 自定义导航栏 -->
<view class="tabback">
<view class="rtjt" @click="btnback"></view>
<view class="name">{{ $i18n.t('deviceDetail') }}</view>
<view style="width: 36rpx;"></view>
</view>
<scroll-view style="height: 90vh;" scroll-y refresher-enabled @refresherrefresh="onRefresh" :refresher-triggered="isRefreshing" refresher-default-style="black">
<!-- 头像和扫码按钮悬浮 -->
<view class="avatar-box">
<image class="avatar" :src="xqobj.productPicture || 'https://api.ccttiot.com/smartmeter/img/static/uZiAQwh3lTliRkGXV3R0'" mode="aspectFill"></image>
<view class="scan-btn" @click="btnrdit">
<image src="https://api.ccttiot.com/smartmeter/img/static/uZiAQwh3lTliRkGXV3R0" mode="aspectFill"></image>
</view>
</view>
<!-- 信息列表卡片 -->
<view class="info-card">
<!-- 蜂窝信号 -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/u28z8kmu23FHKOMs5OoT" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('cellularSignal') }}</view>
<view class="info-status-row">
<view class="signal-bar three-level">
<view
v-for="n in 3"
:key="n"
class="signal-block"
:class="{active: (Number(n) + 1) <= Math.min(cellularSignalLevel, 3)}"
></view>
</view>
<text class="info-status signal-label">
{{ getRssiDisplay('HW1.lte_rssi') }}
</text>
</view>
</view>
<!-- <image v-if="cellularSignalValueClass == 'red'" style="width: 60rpx;height: 60rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uw31nuDEs8OOlS36kYE3" mode=""></image> -->
<view class="divider"></view>
</view>
<!-- WiFi信号 -->
<!-- <view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/uutwguH4unzWw2r9Zpde" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('wifiSignal') }}</view>
<view class="info-status-row">
<text class="info-status" :class="wifiSignalValueClass">{{ wifiSignalValue }}</text>
</view>
</view>
<image v-if="wifiSignalValueClass == 'red'" style="width: 60rpx;height: 60rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uw31nuDEs8OOlS36kYE3" mode=""></image>
<view class="divider"></view>
</view> -->
<!-- 网络状态 -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/uRFwK1gJXCpUJJk3wDG4" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('networkStatus') }}</view>
<view class="info-status-row">
<text class="info-status" style="color: #e74c3c;" v-if="xqobj.onlineStatus == 0">离线</text>
<text class="info-status" style="color: #4cd964;" v-if="xqobj.onlineStatus == 1">在线</text>
<text class="info-status" v-if="xqobj.onlineStatus == undefined || xqobj.onlineStatus == null">--</text>
</view>
</view>
<image v-if="xqobj.onlineStatus == 0" style="width: 60rpx;height: 60rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uw31nuDEs8OOlS36kYE3" mode=""></image>
<view class="divider"></view>
</view>
<!-- 电池电量 -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/uAlkslDfDJ7MJtYkLXAd" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('batteryLevel') }}</view>
<view class="info-status-row">
<text class="info-status" :class="(Number(getIotValue('HW1.battery_pct', 'NaN')) <= 20) ? 'red' : ''">{{ getIotValue('HW1.battery_pct') !== '--' ? getIotValue('HW1.battery_pct') + '%' : '--' }}</text>
</view>
</view>
<view class="divider"></view>
</view>
<!-- 设备覆盖 -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/uRAWgDGlM9ySANCb5m7S" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('deviceCover') }}</view>
<view class="info-status-row">
<text class="info-status" :class="(String(getIotValue('HW1.case_opened')) === '1') ? 'red' : ''">{{ getIotValue('HW1.case_opened') !== '--' ? (String(getIotValue('HW1.case_opened')) === '1' ? 'Open' : 'Close') : '--' }}</text>
</view>
</view>
<view class="divider"></view>
</view>
<!-- 外部电源 -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/u934hpF8vWqaGF1soiPH" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('externalPower') }}</view>
<view class="info-status-row">
<text class="info-status" :class="(getIotValue('HW1.power_src') === 'battery') ? '' : ''">{{ getIotValue('HW1.power_src') }}</text>
</view>
</view>
<view class="divider"></view>
</view>
<!-- 蜂窝设备 -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/u28z8kmu23FHKOMs5OoT" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('cellularDevice') }}</view>
<view class="info-status-row">
<text class="info-status" :class="(String(getIotValue('HW1.cellular_ok')) === '0') ? 'red' : 'green'">{{ getIotValue('HW1.cellular_ok') !== '--' ? (String(getIotValue('HW1.cellular_ok')) === '1' ? 'On' : 'Off') : '--' }}</text>
</view>
</view>
<image v-if="String(getIotValue('HW1.cellular_ok')) === '0'" style="width: 60rpx;height: 60rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uw31nuDEs8OOlS36kYE3" mode=""></image>
<view class="divider"></view>
</view>
<!-- WiFi -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/uutwguH4unzWw2r9Zpde" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('wifi') }}</view>
<view class="info-status-row">
<text class="info-status" :class="(String(getIotValue('HW1.wifi_ok')) === '0') ? 'red' : 'green'">{{ getIotValue('HW1.wifi_ok') !== '--' ? (String(getIotValue('HW1.wifi_ok')) === '1' ? 'On' : 'Off') : '--' }}</text>
</view>
</view>
<image v-if="String(getIotValue('HW1.wifi_ok')) === '0'" style="width: 60rpx;height: 60rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uw31nuDEs8OOlS36kYE3" mode=""></image>
<view class="divider"></view>
</view>
<!-- 以太网 -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/upnqWy06k5L0xtanObM7" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('ethernet') }}</view>
<view class="info-status-row">
<text class="info-status" :class="(String(getIotValue('HW1.eth_ok')) === '0') ? '' : ''">{{ getIotValue('HW1.eth_ok') !== '--' ? (String(getIotValue('HW1.eth_ok')) === '1' ? 'SIM2' : 'SIM1') : '--' }}</text>
</view>
</view>
<!-- <image v-if="xqobj.iotData && xqobj.iotData['HW1.eth_ok'] && String(xqobj.iotData['HW1.eth_ok'].value) === '0'" style="width: 60rpx;height: 60rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uw31nuDEs8OOlS36kYE3" mode=""></image> -->
<view class="divider"></view>
</view>
<!-- SIM1 -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/uvq4fvbXLx8LMdAJVunM" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('sim1') }}</view>
<view class="info-status-row">
<text class="info-status" :class="(String(getIotValue('HW2.imei1')) === 'N/A') ? 'red' : ''">{{ getIotValue('HW2.imei1') }}</text>
</view>
</view>
<image v-if="String(getIotValue('HW2.imei1')) === 'N/A'" style="width: 60rpx;height: 60rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uw31nuDEs8OOlS36kYE3" mode=""></image>
<view class="divider"></view>
</view>
<!-- SIM2 -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/uvq4fvbXLx8LMdAJVunM" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('sim2') }}</view>
<view class="info-status-row">
<text class="info-status" :class="(String(getIotValue('HW2.imei2')) === 'N/A') ? 'red' : ''">{{ getIotValue('HW2.imei2') }}</text>
</view>
</view>
<image v-if="String(getIotValue('HW2.imei2')) === 'N/A'" style="width: 60rpx;height: 60rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uw31nuDEs8OOlS36kYE3" mode=""></image>
<view class="divider"></view>
</view>
<!-- 平均SNR -->
<!-- <view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/udon2SOIwspVLoxX6G6q" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('avgSnr') }}</view>
<view class="info-status-row">
<text class="info-status" :class="(xqobj.iotData && xqobj.iotData['HW2.lora_rssi'] && String(xqobj.iotData['HW2.lora_rssi'].value) !== '0') ? '' : 'red'">{{ (xqobj.iotData && xqobj.iotData['HW2.lora_rssi'] && xqobj.iotData['HW2.lora_rssi'].value !== undefined && xqobj.iotData['HW2.lora_snr'] && xqobj.iotData['HW2.lora_snr'].value !== undefined && xqobj.iotData['HW2.lora_level'] && xqobj.iotData['HW2.lora_level'].value !== undefined) ? (xqobj.iotData['HW2.lora_rssi'].value + ' / ' + xqobj.iotData['HW2.lora_level'].value + ' / ' + xqobj.iotData['HW2.lora_snr'].value) : '--' }}</text>
</view>
</view>
<image v-if="xqobj.iotData && xqobj.iotData['HW2.lora_rssi'] && String(xqobj.iotData['HW2.lora_rssi'].value) === '0'" style="width: 60rpx;height: 60rpx;" src="https://api.ccttiot.com/smartmeter/img/static/uw31nuDEs8OOlS36kYE3" mode=""></image>
<view class="divider"></view>
</view> -->
<!-- LORA -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/uhM8UxrlR0qKJ50Xlx3L" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">LORA</view>
<view class="info-status-row">
<view class="signal-bar three-level">
<view
v-for="n in 3"
:key="n"
class="signal-block"
:class="{ active: n <= getLoraBleBarCount('HW2.lora_rssi') }"
></view>
</view>
<text
class="info-status signal-label"
:class="getLoraBleBarCount('HW2.lora_rssi') === 0 ? '' : ''"
>
{{ getRssiDisplay('HW2.lora_rssi') }}
</text>
</view>
</view>
<view class="divider"></view>
</view>
<!-- BLE -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/udon2SOIwspVLoxX6G6q" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">BLE</view>
<view class="info-status-row">
<view class="signal-bar three-level">
<view
v-for="n in 3"
:key="n"
class="signal-block"
:class="{ active: n <= getLoraBleBarCount('HW2.ble_rssi') }"
></view>
</view>
<text
class="info-status signal-label"
:class="getLoraBleBarCount('HW2.ble_rssi') === 0 ? 'red' : ''">
{{ getRssiDisplay('HW2.ble_rssi') }}
</text>
</view>
</view>
<view class="divider"></view>
</view>
<!-- 安全公司 -->
<view class="info-item">
<image class="iconfont info-icon" src="https://api.ccttiot.com/smartmeter/img/static/uTlg5irZwTYkGGnIxFRY" mode="aspectFill"></image>
<view class="info-content">
<view class="info-title">{{ $i18n.t('securityCompany') }}</view>
<view class="info-status-row">
<text class="info-status" :class="securityCompanyValueClass">{{ securityCompanyValue }}</text>
</view>
</view>
</view>
</view>
<!-- 底部摘要 -->
<view class="device-summary">
<view v-for="item in detailSummaryList" :key="item.key">{{ item.label }}{{ item.value }}</view>
</view>
</scroll-view>
</view>
</template>
<script>
export default {
data() {
return {
// 蜂窝信号
cellularSignalLevel: 3,
cellularSignalValueClass: '',
// WiFi信号
wifiSignalValue: this.$i18n.t('noData'),
wifiSignalValueClass: '',
// 电池电量
batteryLevelValue: this.$i18n.t('noData'),
batteryLevelValueClass: '',
// 设备覆盖
deviceCoverValue: this.$i18n.t('noData'),
deviceCoverValueClass: 'red',
// 外部电源
externalPowerValue: this.$i18n.t('noData'),
externalPowerValueClass: '',
// 蜂窝设备
cellularDeviceValue: this.$i18n.t('offline'),
cellularDeviceValueClass: '',
// WiFi
wifiValue: this.$i18n.t('offline'),
wifiValueClass: 'red',
// 以太网
ethernetValue: this.$i18n.t('offline'),
ethernetValueClass: '',
// SIM1
sim1Value: this.$i18n.t('unknownNumber'),
sim1ValueClass: '',
// SIM2
sim2Value: this.$i18n.t('unknownNumber'),
sim2ValueClass: '',
// 平均SNR
avgSnrValue: this.$i18n.t('noData') + ' / ' + this.$i18n.t('noData') + ' / ' + this.$i18n.t('noData'),
avgSnrValueClass: '',
// LORA/BLE
loraBleValue: this.$i18n.t('noData') + ' / ' + this.$i18n.t('noData') + ' / ' + this.$i18n.t('noData'),
loraBleValueClass: '',
// 安全公司
securityCompanyValue: this.$i18n.t('noData') + ' / ' + this.$i18n.t('noData') + ' / ' + this.$i18n.t('noData'),
securityCompanyValueClass: '',
id:'',
xqobj:{},
isRefreshing:false,
}
},
onLoad(option) {
this.id = option.id
this.getxq()
},
computed: {
detailSummaryList() {
return [
// { key: 'model', label: '机器型号:', value: this.getIotValue('HW2.model') },
{ key: 'hw_ver', label: '硬件版本:', value: this.getIotValue('HW2.hw_ver') },
{ key: 'sw_ver', label: '软件版本:', value: this.getIotValue('HW2.sw_ver') },
{ key: 'serial_no', label: '流水号:', value: this.getIotValue('HW2.serial_no') },
// { key: 'sim_slot', label: '手机卡槽:', value: this.getSimSlotText() },
// { key: 'net_type', label: '网络类型:', value: this.getIotValue('HW2.net_type') },
// { key: 'server_ok', label: '服务器:', value: this.getBooleanText('HW1.server_ok', '已连接', '未连接') },
// { key: 'ble_count', label: 'BLE接机数', value: this.getIotValue('HW1.ble_count') },
// { key: 'battery_mv', label: '电池电压:', value: this.getBatteryMvText() },
// { key: 'imei1', label: 'IMEI1', value: this.getIotValue('HW2.imei1') },
// { key: 'imei2', label: 'IMEI2', value: this.getIotValue('HW2.imei2') },
{ key: 'mac', label: '设备MAC', value: this.xqobj.mac || '--' },
]
}
},
methods: {
// 下拉刷新
onRefresh() {
this.isRefreshing = true
setTimeout(()=>{
this.isRefreshing = false
this.getxq()
},1000)
},
// 点击进行设备修改
btnrdit(){
uni.navigateTo({
url:'/pages/device/hubedit?id=' + this.id
})
},
// 进行设备详情请求
getxq(){
this.$http.get(`/bst/device/detail?id=${this.id}`).then(res => {
if(res.code == 200){
this.xqobj = res.data
const rssi = this.getIotValue('HW1.lte_rssi')
this.cellularSignalLevel = this.getCellularSignalLevel(rssi)
console.log(this.cellularSignalLevel,'this.cellularSignalLevelthis.cellularSignalLevelthis.cellularSignalLevel');
this.cellularSignalValueClass = this.cellularSignalLevel <= 1 ? 'red' : 'green'
}
})
},
/**
* 将 HW1/HW2 的 valueJSON 字符串或多次包裹的字符串)解析为对象
*/
parseHwValueToObject(val) {
if (val === undefined || val === null || val === '') {
return {}
}
if (typeof val === 'object' && val !== null && !Array.isArray(val)) {
return val
}
let cur = val
for (let depth = 0; depth < 10; depth++) {
if (typeof cur === 'object' && cur !== null && !Array.isArray(cur)) {
return cur
}
const s = typeof cur === 'string' ? cur.trim() : String(cur)
if (!s) {
return {}
}
try {
cur = JSON.parse(s)
} catch (e) {
const next = this.stripQuotes(s)
if (next === s) {
return {}
}
cur = next
}
}
return typeof cur === 'object' && cur !== null && !Array.isArray(cur) ? cur : {}
},
/** 是否为新版聚合点iotData.HW1 / HW2 带 value 字段 */
isHwAggregateBlock(hwId) {
const data = this.xqobj && this.xqobj.iotData ? this.xqobj.iotData : {}
const block = data[hwId]
return !!(
block &&
typeof block === 'object' &&
!Array.isArray(block) &&
Object.prototype.hasOwnProperty.call(block, 'value')
)
},
/**
* 当 HW*.value 整段是 JSON 字符串/数字(如 "N/A"、3而非对象时取出标量用于展示。
* 若解析得到普通对象则返回 null应走 getHwPayload 字段读取)。
*/
parseHwTopLevelScalar(val) {
let cur = val
for (let i = 0; i < 10; i++) {
if (cur === undefined || cur === null || cur === '') {
return null
}
if (typeof cur === 'object') {
if (Array.isArray(cur)) return null
return null
}
if (typeof cur === 'boolean' || typeof cur === 'number') {
return cur
}
if (typeof cur === 'string') {
const t = cur.trim()
if (!t) return null
try {
cur = JSON.parse(t)
continue
} catch (e) {
return t
}
}
return null
}
return null
},
hwScalarToDisplay(v) {
if (v === undefined || v === null || v === '') {
return '--'
}
if (typeof v === 'number' || typeof v === 'boolean') {
return String(v)
}
return this.stripQuotes(v)
},
/** 读取聚合后的 HW1 / HW2 块iotData.HW1.value 内为 JSON */
getHwPayload(hwId) {
const data = this.xqobj && this.xqobj.iotData ? this.xqobj.iotData : {}
const block = data[hwId]
if (!block || typeof block !== 'object' || Array.isArray(block)) {
return {}
}
if (Object.prototype.hasOwnProperty.call(block, 'value')) {
return this.parseHwValueToObject(block.value)
}
return {}
},
getIotValue(key, fallback = '--') {
const data = this.xqobj && this.xqobj.iotData ? this.xqobj.iotData : {}
const m = /^HW([12])\.(.+)$/.exec(key)
if (m) {
const hwId = 'HW' + m[1]
const field = m[2]
const aggregate = this.isHwAggregateBlock(hwId)
const payload = this.getHwPayload(hwId)
if (Object.prototype.hasOwnProperty.call(payload, field)) {
const v = payload[field]
if (v === undefined || v === null || v === '') {
return fallback
}
if (typeof v === 'number' || typeof v === 'boolean') {
return String(v)
}
return this.stripQuotes(v)
}
// 聚合块存在但 JSON 里没有 imei 字段:整段 value 可能是标量(如 "N/A"),原样展示
if (aggregate && (field === 'imei1' || field === 'imei2')) {
const block = data[hwId]
const scalar = this.parseHwTopLevelScalar(block && block.value)
if (scalar !== null && scalar !== undefined && scalar !== '') {
return this.hwScalarToDisplay(scalar)
}
}
// 已是 HW1/HW2 聚合模式时,禁止回退到旧的扁平键 HW2.imei1避免读到过期错误数据如显示成 3
if (aggregate) {
return fallback
}
}
const item = data[key]
if (item === undefined || item === null) {
return fallback
}
// 避免 data[key] 为数字 0 时 !item 为 true 被当成无数据
if (typeof item === 'number' || typeof item === 'string' || typeof item === 'boolean') {
if (item === '') return fallback
return this.stripQuotes(item)
}
if (typeof item === 'object') {
if (item.value === undefined || item.value === null || item.value === '') {
return fallback
}
return this.stripQuotes(item.value)
}
return fallback
},
stripQuotes(value) {
if (value === undefined || value === null) {
return '--'
}
let text = String(value)
while (text.length >= 2 && text.startsWith('"') && text.endsWith('"')) {
text = text.slice(1, -1)
}
return text
},
getBooleanText(key, trueText, falseText) {
const value = String(this.getIotValue(key, '')).trim()
if (value === '1') {
return trueText
}
if (value === '0') {
return falseText
}
return '--'
},
getSimSlotText() {
const value = String(this.getIotValue('HW2.sim_slot', '')).trim()
if (value === '0') {
return 'SIM1'
}
if (value === '1') {
return 'SIM2'
}
return value || '--'
},
getBatteryMvText() {
const value = this.getIotValue('HW1.battery_mv')
return value === '--' ? '--' : `${value} mV`
},
getCellularSignalLevel(rssiValue) {
const rssi = Number(rssiValue)
if (Number.isNaN(rssi) || rssi === 0) {
return 1
}
// 按你的规则分 4 档:越小越强
if (rssi < -50) {
return 4
}
if (rssi < -20) {
return 3
}
if (rssi < -10) {
return 2
}
return 1
},
/**
* LORA/BLE 信号条:依据 HW2.lora_rssi / HW2.ble_rssi
* 0 → 三格全灰0 格点亮)
* 小于 -40 → 三格
* -40 ~ -20含边界→ 两格
* -20 ~ -1不含 -20、含 -1→ 一格
*/
/** 读取 LORA/BLE rssi 数值0、字符串 0、(-1,0) 内异常小数均视为无信号 */
getLoraBleRssiNumber(key) {
const data = this.xqobj && this.xqobj.iotData ? this.xqobj.iotData : {}
const m = /^HW([12])\.(.+)$/.exec(key)
let v
if (m) {
const payload = this.getHwPayload('HW' + m[1])
const field = m[2]
if (Object.prototype.hasOwnProperty.call(payload, field)) {
v = payload[field]
} else {
return null
}
} else {
const item = data[key]
if (item && typeof item === 'object' && !Array.isArray(item) && Object.prototype.hasOwnProperty.call(item, 'value')) {
v = item.value
} else if (typeof item === 'number' || typeof item === 'string') {
v = item
} else {
return null
}
}
if (v === '' || v === null || v === undefined) return null
const s = String(v).trim()
if (s === '') return null
if (/^-?0+(\.0+)?$/.test(s) || s === '+0') return 0
const n = Number(s)
if (!Number.isFinite(n)) return null
if (n === 0 || Object.is(n, -0)) return 0
// 接口可能返回 -0.00x,界面四舍五入成 0仍应无格
if (n > -1 && n < 0) return 0
return n
},
getLoraBleBarCount(key) {
const n = this.getLoraBleRssiNumber(key)
if (n === null || n === undefined || n === 0) return 0
if (n < -40) return 3
if (n <= -20) return 2
if (n <= -1) return 1
return 0
},
getLoraBleBarLabel(key) {
const c = this.getLoraBleBarCount(key)
const raw = this.getIotValue(key, '')
if (raw === '--' || raw === '' || String(raw).trim() === '0') return '无信号'
if (c === 3) return '三格'
if (c === 2) return '两格'
if (c === 1) return '一格'
return '无信号'
},
getRssiDisplay(key) {
const raw = this.getIotValue(key, '--')
if (raw === '--') {
return ''
}
return ` (${raw} dBm)`
},
// 点击返回上一级
btnback(){
uni.navigateBack()
},
}
}
</script>
<style scoped lang="less">
.tabback {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
height: 160rpx;
padding: 0 20rpx;
padding-top: 80rpx;
box-sizing: border-box;
position: fixed;
top: 0;
left: 0;
z-index: 999 !important;
background-color: #fff;
.rtjt {
font-size: 36rpx;
}
}
.device-detail {
padding-top: 150rpx;
background-color: #F3F5F6;
}
.avatar-box {
position: relative;
display: flex;
justify-content: center;
margin-top: 60rpx;
padding-bottom: 74rpx;
border-bottom: 1rpx solid #f2f2f2;
.avatar {
width: 278rpx;
height: 278rpx;
background: #e0e0e0;
border-radius: 24rpx;
box-shadow: 0 2rpx 8rpx #eee;
}
.scan-btn {
image{
width: 48rpx;
height: 48rpx;
}
position: absolute;
right: 26rpx;
top: -36rpx;
width: 48rpx;
height: 48rpx;
background: #fff;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
box-shadow: 0 2rpx 8rpx #eee;
border: 1rpx solid #eee;
}
}
.info-card {
background: #fff;
.info-item {
display: flex;
align-items: flex-start;
padding: 0 24rpx 0 32rpx;
position: relative;
min-height: 80rpx;
image{
width: 50rpx;
height: 50rpx;
margin-top: 30rpx;
}
.info-icon {
font-family: 'iconfont' !important;
font-size: 32rpx;
margin-right: 18rpx;
color: #222;
line-height: 80rpx;
}
.info-content {
flex: 1;
padding: 18rpx 0;
.info-title {
font-size: 28rpx;
color: #333;
font-weight: 500;
}
.info-status-row {
display: flex;
align-items: center;
margin-top: 6rpx;
min-height: 32rpx;
.info-status {
font-size: 26rpx;
color: #666;
&.red {
color: #e74c3c;
}
&.green {
color: #27ae60;
}
}
.signal-bar {
display: flex;
align-items: center;
margin-right: 16rpx;
.signal-block {
width: 62rpx;
height: 6rpx;
margin-right: 6rpx;
border-radius: 2rpx;
background: #e0e0e0;
&.active {
background: #4cd964;
}
}
}
.signal-bar.three-level {
.signal-block {
width: 40rpx;
}
}
.signal-label {
margin-left: 4rpx;
}
}
}
.divider {
position: absolute;
left: 0;
right: 0;
bottom: 0;
height: 1rpx;
background: #f2f2f2;
}
}
}
.device-summary {
background: #f7f7f7;
text-align: center;
color: #888;
font-size: 24rpx;
line-height: 1.8;
border-radius: 0 0 20rpx 20rpx;
padding-top: 40rpx;
box-sizing: border-box;
padding-bottom: 30rpx;
}
</style>