|
@@ -173,6 +173,62 @@
|
|
|
opacity: 0.8;
|
|
opacity: 0.8;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+.signal-info-card {
|
|
|
|
|
+ margin-top: 8px;
|
|
|
|
|
+ padding: 12px 16px;
|
|
|
|
|
+ background: #f5f7fa;
|
|
|
|
|
+ border-radius: 8px;
|
|
|
|
|
+
|
|
|
|
|
+ .signal-title {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ margin-bottom: 10px;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .signal-grid {
|
|
|
|
|
+ display: grid;
|
|
|
|
|
+ grid-template-columns: repeat(2, 1fr);
|
|
|
|
|
+ gap: 6px 24px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .signal-item {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ font-size: 13px;
|
|
|
|
|
+ padding: 5px 0;
|
|
|
|
|
+ border-bottom: 1px dashed #e4e7ed;
|
|
|
|
|
+
|
|
|
|
|
+ .signal-label {
|
|
|
|
|
+ color: #909399;
|
|
|
|
|
+ flex-shrink: 0;
|
|
|
|
|
+ margin-right: 12px;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .signal-value {
|
|
|
|
|
+ color: #303133;
|
|
|
|
|
+ font-weight: 600;
|
|
|
|
|
+ word-break: break-all;
|
|
|
|
|
+ text-align: right;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .signal-value.chip-id {
|
|
|
|
|
+ font-size: 12px;
|
|
|
|
|
+ max-width: 220px;
|
|
|
|
|
+ overflow: hidden;
|
|
|
|
|
+ text-overflow: ellipsis;
|
|
|
|
|
+ white-space: nowrap;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .signal-good { color: #67c23a; }
|
|
|
|
|
+ .signal-mid { color: #e6a23c; }
|
|
|
|
|
+ .signal-bad { color: #f56c6c; }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
</style>
|
|
</style>
|
|
|
|
|
|
|
|
<template>
|
|
<template>
|
|
@@ -224,6 +280,9 @@
|
|
|
<el-button class="action-btn" type="primary" plain @click="handleReadConfig" :loading="state.loading">
|
|
<el-button class="action-btn" type="primary" plain @click="handleReadConfig" :loading="state.loading">
|
|
|
<el-icon><Reading /></el-icon> 读取配置
|
|
<el-icon><Reading /></el-icon> 读取配置
|
|
|
</el-button>
|
|
</el-button>
|
|
|
|
|
+ <el-button class="action-btn" type="info" plain @click="handleReadHardwareInfo" :loading="state.loading">
|
|
|
|
|
+ <el-icon><Odometer /></el-icon> 读取信号值
|
|
|
|
|
+ </el-button>
|
|
|
<el-button class="action-btn" type="warning" plain @click="handleShowMsgbox" :loading="state.loading">
|
|
<el-button class="action-btn" type="warning" plain @click="handleShowMsgbox" :loading="state.loading">
|
|
|
<el-icon><ChatDotSquare /></el-icon> 屏幕消息
|
|
<el-icon><ChatDotSquare /></el-icon> 屏幕消息
|
|
|
</el-button>
|
|
</el-button>
|
|
@@ -249,6 +308,48 @@
|
|
|
</div>
|
|
</div>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+ <!-- 信号值信息(点击「读取信号值」后显示) -->
|
|
|
|
|
+ <div class="signal-info-card" v-if="state.hardwareInfo">
|
|
|
|
|
+ <div class="signal-title">
|
|
|
|
|
+ <span>设备信号值</span>
|
|
|
|
|
+ <el-button size="small" text type="primary" @click="state.hardwareInfo = null">收起</el-button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="signal-grid">
|
|
|
|
|
+ <div class="signal-item">
|
|
|
|
|
+ <span class="signal-label">网络类型</span>
|
|
|
|
|
+ <span class="signal-value">{{ state.hardwareInfo.network?.type || '--' }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="signal-item">
|
|
|
|
|
+ <span class="signal-label">信号质量(RSSI)</span>
|
|
|
|
|
+ <span class="signal-value" :class="rssiLevel">{{ state.hardwareInfo.network?.rssi ?? '--' }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="signal-item">
|
|
|
|
|
+ <span class="signal-label">误码率(BER)</span>
|
|
|
|
|
+ <span class="signal-value">{{ state.hardwareInfo.network?.ber ?? '--' }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="signal-item">
|
|
|
|
|
+ <span class="signal-label">IMEI</span>
|
|
|
|
|
+ <span class="signal-value">{{ state.hardwareInfo.network?.imei || '--' }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="signal-item">
|
|
|
|
|
+ <span class="signal-label">硬件版本</span>
|
|
|
|
|
+ <span class="signal-value">{{ state.hardwareInfo.board?.hard_version || '--' }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="signal-item">
|
|
|
|
|
+ <span class="signal-label">固件版本</span>
|
|
|
|
|
+ <span class="signal-value">{{ state.hardwareInfo.board?.firmware_version || '--' }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="signal-item">
|
|
|
|
|
+ <span class="signal-label">编译时间</span>
|
|
|
|
|
+ <span class="signal-value">{{ state.hardwareInfo.board?.build_time || '--' }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="signal-item">
|
|
|
|
|
+ <span class="signal-label">芯片ID</span>
|
|
|
|
|
+ <span class="signal-value chip-id">{{ state.hardwareInfo.board?.chip_id || '--' }}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+
|
|
|
<!-- 配置编辑区 -->
|
|
<!-- 配置编辑区 -->
|
|
|
<div class="config-editor" v-if="state.showConfigEditor">
|
|
<div class="config-editor" v-if="state.showConfigEditor">
|
|
|
<div class="config-title">设备配置编辑</div>
|
|
<div class="config-title">设备配置编辑</div>
|
|
@@ -359,7 +460,7 @@ import {Msg} from "/@/utils/message";
|
|
|
import {$body} from "/@/utils/request";
|
|
import {$body} from "/@/utils/request";
|
|
|
import u from '/@/utils/u';
|
|
import u from '/@/utils/u';
|
|
|
import {ElMessage} from 'element-plus';
|
|
import {ElMessage} from 'element-plus';
|
|
|
-import {Refresh, Reading, ChatDotSquare, CloseBold, SwitchButton, Loading} from '@element-plus/icons-vue';
|
|
|
|
|
|
|
+import {Refresh, Reading, ChatDotSquare, CloseBold, SwitchButton, Loading, Odometer} from '@element-plus/icons-vue';
|
|
|
|
|
|
|
|
const emit = defineEmits(['refresh']);
|
|
const emit = defineEmits(['refresh']);
|
|
|
|
|
|
|
@@ -371,6 +472,7 @@ const initState = () => ({
|
|
|
uptimeMs: '',
|
|
uptimeMs: '',
|
|
|
hasPa: false,
|
|
hasPa: false,
|
|
|
orderInfo: null as any,
|
|
orderInfo: null as any,
|
|
|
|
|
+ hardwareInfo: null as any,
|
|
|
showConfigEditor: false,
|
|
showConfigEditor: false,
|
|
|
configForm: {} as any,
|
|
configForm: {} as any,
|
|
|
priceDialog: {
|
|
priceDialog: {
|
|
@@ -430,6 +532,15 @@ const temperatureDisplay = computed(() => {
|
|
|
return state.temperatureChip != null ? `${state.temperatureChip}°C` : '--';
|
|
return state.temperatureChip != null ? `${state.temperatureChip}°C` : '--';
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+// 信号质量等级(rssi 越大信号越好)
|
|
|
|
|
+const rssiLevel = computed(() => {
|
|
|
|
|
+ const rssi = state.hardwareInfo?.network?.rssi;
|
|
|
|
|
+ if (rssi == null) return '';
|
|
|
|
|
+ if (rssi >= 20) return 'signal-good';
|
|
|
|
|
+ if (rssi >= 10) return 'signal-mid';
|
|
|
|
|
+ return 'signal-bad';
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
const open = (row: any) => {
|
|
const open = (row: any) => {
|
|
|
productKey = row.productKey;
|
|
productKey = row.productKey;
|
|
|
deviceName = row.deviceName;
|
|
deviceName = row.deviceName;
|
|
@@ -513,6 +624,19 @@ const handleWriteConfig = async () => {
|
|
|
}
|
|
}
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+const handleReadHardwareInfo = async () => {
|
|
|
|
|
+ state.loading = true;
|
|
|
|
|
+ try {
|
|
|
|
|
+ const res: any = await api('queryHardwareInfo');
|
|
|
|
|
+ state.hardwareInfo = res || null;
|
|
|
|
|
+ Msg.message('信号值读取成功', 'success');
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ Msg.message('读取信号值失败', 'error');
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ state.loading = false;
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
const editPrice = (fn: any) => {
|
|
const editPrice = (fn: any) => {
|
|
|
if (fn.price == null) {
|
|
if (fn.price == null) {
|
|
|
Msg.message('配置加载失败,无法修改价格,请点击「读取配置」重试', 'warning');
|
|
Msg.message('配置加载失败,无法修改价格,请点击「读取配置」重试', 'warning');
|