2024-11-13 11:26:59 +08:00
|
|
|
|
<template>
|
|
|
|
|
<div class="page-container">
|
|
|
|
|
<Header :title="currentTitle"></Header>
|
|
|
|
|
<van-pull-refresh v-model="loading" success-text="刷新成功" @refresh="onRefresh">
|
|
|
|
|
<div class="content">
|
|
|
|
|
<!-- gateway -->
|
|
|
|
|
<div class="item">
|
|
|
|
|
<van-cell-group inset>
|
|
|
|
|
<div class="header">
|
|
|
|
|
<p class="title">网关卡</p>
|
|
|
|
|
<p :class="getStatusClass(gatewaystatus)" class="state">{{ gatewaystatus }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<van-divider :style="{ color: 'black' }" />
|
|
|
|
|
<van-field label="版本号:" :model-value="gatwayVision" readonly />
|
|
|
|
|
<van-field label="编译时间:" :model-value="gatewayTime" readonly />
|
|
|
|
|
</van-cell-group>
|
|
|
|
|
</div>
|
|
|
|
|
<!-- LED Screen -->
|
|
|
|
|
<div class="item">
|
|
|
|
|
<van-cell-group inset>
|
|
|
|
|
<div class="header">
|
|
|
|
|
<p class="title">双色LED屏驱动板</p>
|
|
|
|
|
<p :class="getStatusClass(ledStatus)" class="state">{{ ledStatus }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<van-divider :style="{ color: 'black' }" />
|
|
|
|
|
<van-field label="版本号:" :model-value="ledVision" readonly />
|
|
|
|
|
<van-field label="编译时间:" :model-value="ledTime" readonly />
|
|
|
|
|
</van-cell-group>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- Car Recognition -->
|
|
|
|
|
<div class="item">
|
|
|
|
|
<van-cell-group inset>
|
|
|
|
|
<div class="header">
|
|
|
|
|
<p class="title">摄像头控制卡</p>
|
|
|
|
|
<p :class="getStatusClass(carStatus)" class="state">{{ carStatus }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<van-divider :style="{ color: 'black' }" />
|
|
|
|
|
<van-field label="版本号:" :model-value="carVision" readonly />
|
|
|
|
|
<van-field label="编译时间:" :model-value="carTime" readonly />
|
|
|
|
|
</van-cell-group>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 4G Sound Card -->
|
|
|
|
|
<div class="item">
|
|
|
|
|
<van-cell-group inset>
|
|
|
|
|
<div class="header">
|
|
|
|
|
<p class="title">音频控制卡</p>
|
|
|
|
|
<p :class="getStatusClass(g4Status)" class="state">{{ g4Status }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<van-divider :style="{ color: 'black' }" />
|
|
|
|
|
<van-field label="版本号:" :model-value="g4Vision" readonly />
|
|
|
|
|
<van-field label="编译时间:" :model-value="g4Time" readonly />
|
|
|
|
|
</van-cell-group>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- LoRa -->
|
|
|
|
|
<div class="item">
|
|
|
|
|
<van-cell-group inset>
|
|
|
|
|
<div class="header">
|
|
|
|
|
<p class="title">LoRa预警板</p>
|
|
|
|
|
<p :class="getStatusClass(loraStatus)" class="state">{{ loraStatus }}</p>
|
|
|
|
|
</div>
|
|
|
|
|
<van-divider :style="{ color: 'black' }" />
|
|
|
|
|
<van-field label="版本号:" :model-value="loraVision" readonly />
|
|
|
|
|
<van-field label="编译时间:" :model-value="loraTime" readonly />
|
|
|
|
|
</van-cell-group>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</van-pull-refresh>
|
|
|
|
|
<Footer></Footer>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
|
|
|
|
import Header from "../../components/Header.vue";
|
|
|
|
|
import Footer from "../../components/Footer.vue";
|
|
|
|
|
import axios from 'axios';
|
|
|
|
|
// import * as mqtt from 'mqtt/dist/mqtt.min';
|
|
|
|
|
import '@vant/touch-emulator';
|
|
|
|
|
export default {
|
|
|
|
|
components: {
|
|
|
|
|
Header,
|
|
|
|
|
Footer
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
setup() {
|
|
|
|
|
const currentTitle = ref('系统信息');
|
|
|
|
|
const loading = ref(false);
|
|
|
|
|
|
|
|
|
|
// 定义绑定字段
|
|
|
|
|
const gatwayVision = ref('');
|
|
|
|
|
const gatewayTime = ref('');
|
|
|
|
|
const gatewaystatus = ref('离线');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const ledVision = ref('');
|
|
|
|
|
const ledTime = ref('');
|
|
|
|
|
const ledStatus = ref('离线');
|
|
|
|
|
const carVision = ref('');
|
|
|
|
|
const carTime = ref('');
|
|
|
|
|
const carStatus = ref('离线');
|
|
|
|
|
const g4Vision = ref('');
|
|
|
|
|
const g4Time = ref('');
|
|
|
|
|
const g4Status = ref('离线');
|
|
|
|
|
const loraTime = ref('');
|
|
|
|
|
const loraVision = ref('');
|
|
|
|
|
const loraStatus = ref('离线');
|
|
|
|
|
let jsonId = ref(1);
|
|
|
|
|
let data; // 将 data 定义在函数外部,使其可以在函数外部访问
|
|
|
|
|
|
|
|
|
|
// 检查环境是否为本地
|
|
|
|
|
const isLocal = window.location.hostname === '192.168.4.1';
|
2025-05-30 16:25:17 +08:00
|
|
|
|
// const MQTT_send = (send_string) => {
|
|
|
|
|
// console.log(" 向父页面发送消息:", JSON.stringify(send_string));
|
|
|
|
|
// // 使用 postMessage 发送数据给父页面
|
|
|
|
|
// window.parent.postMessage(
|
|
|
|
|
// {
|
|
|
|
|
// data: send_string
|
|
|
|
|
// },
|
|
|
|
|
// '*' // 目标 origin,生产环境应替换为具体的父页面域名
|
|
|
|
|
// );
|
|
|
|
|
// };
|
|
|
|
|
|
2025-05-27 15:23:19 +08:00
|
|
|
|
const MQTT_send = (send_string) => {
|
2025-05-30 16:25:17 +08:00
|
|
|
|
console.log("向父页面发送消息:", JSON.stringify(send_string));
|
|
|
|
|
|
|
|
|
|
// 统一的消息发送方法,兼容各平台
|
|
|
|
|
if (typeof uni !== 'undefined' && uni.postMessage) {
|
|
|
|
|
// 小程序/APP环境下使用uni.postMessage
|
|
|
|
|
uni.postMessage({
|
|
|
|
|
data: {
|
|
|
|
|
type: 'mqtt_data',
|
|
|
|
|
payload: send_string,
|
|
|
|
|
timestamp: Date.now()
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// H5环境下使用window.parent.postMessage
|
|
|
|
|
window.parent.postMessage(
|
|
|
|
|
{
|
|
|
|
|
data: send_string
|
|
|
|
|
},
|
|
|
|
|
'*' // 目标 origin,生产环境应替换为具体的父页面域名
|
|
|
|
|
);
|
|
|
|
|
}
|
2025-05-27 15:23:19 +08:00
|
|
|
|
};
|
2024-11-13 11:26:59 +08:00
|
|
|
|
|
2025-05-30 16:25:17 +08:00
|
|
|
|
|
|
|
|
|
|
2024-11-13 11:26:59 +08:00
|
|
|
|
const handleMQTTMessage = (string) => {
|
2025-05-30 16:25:17 +08:00
|
|
|
|
// console.log("MQTT 接收:" + string);
|
2024-11-13 11:26:59 +08:00
|
|
|
|
const data = JSON.parse(string);
|
|
|
|
|
// console.log("MQTT 接收:", JSON.stringify(data, null, 2)); // 格式化打印 JSON 对象
|
|
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
try {
|
|
|
|
|
if (data.led_protocol && data.led_protocol.info) {
|
|
|
|
|
const info = data.led_protocol.info;
|
|
|
|
|
ledVision.value = info.versions;
|
|
|
|
|
ledTime.value = info.compile_time;
|
|
|
|
|
ledStatus.value = '在线';
|
|
|
|
|
resolve(data);
|
|
|
|
|
} else if (data.LPR_card && data.LPR_card.info) {
|
|
|
|
|
const info = data.LPR_card.info;
|
|
|
|
|
carVision.value = info.versions;
|
|
|
|
|
carTime.value = info.compile_time;
|
|
|
|
|
carStatus.value = '在线';
|
|
|
|
|
resolve(data);
|
|
|
|
|
} else if (data.sound_card && data.sound_card.info) {
|
|
|
|
|
const info = data.sound_card.info;
|
|
|
|
|
g4Vision.value = info.versions;
|
|
|
|
|
g4Time.value = info.compile_time;
|
|
|
|
|
g4Status.value = '在线';
|
|
|
|
|
resolve(data);
|
|
|
|
|
} else if (data.LoRa_card && data.LoRa_card.info) {
|
|
|
|
|
const info = data.LoRa_card.info;
|
|
|
|
|
loraVision.value = info.versions;
|
|
|
|
|
loraTime.value = info.compile_time;
|
|
|
|
|
loraStatus.value = '在线';
|
|
|
|
|
resolve(data);
|
|
|
|
|
} else if (data.gateway && data.gateway.info) {
|
|
|
|
|
const info = data.gateway.info;
|
|
|
|
|
gatwayVision.value = info.versions;
|
|
|
|
|
gatewayTime.value = info.compile_time;
|
|
|
|
|
gatewaystatus.value = '在线';
|
|
|
|
|
resolve(data);
|
|
|
|
|
} else {
|
|
|
|
|
resolve(data);
|
|
|
|
|
}
|
|
|
|
|
} catch (error) {
|
|
|
|
|
reject(error);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 发送请求的函数
|
|
|
|
|
const sendRequest = async (requestData, requestType) => {
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
|
const timeout = setTimeout(() => {
|
|
|
|
|
console.warn('请求超时,跳过该请求');
|
|
|
|
|
resolve({ skipped: true });
|
|
|
|
|
}, 5000); // 设置超时时间为5秒
|
|
|
|
|
|
|
|
|
|
if (requestType === 'mqtt') {
|
|
|
|
|
MQTT_send(requestData);
|
|
|
|
|
// 不需要在这里再添加事件监听器,使用全局的 handleMessage 即可
|
|
|
|
|
} else if (requestType === 'axios') {
|
|
|
|
|
axios.post('/communication', requestData, {
|
|
|
|
|
headers: {
|
|
|
|
|
"content-type": "application/json"
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
.then(response => {
|
|
|
|
|
clearTimeout(timeout); // 在收到响应后清除超时
|
|
|
|
|
const data = response.data;
|
|
|
|
|
console.log('收到 Axios 响应:', data);
|
|
|
|
|
if (data.led_protocol && data.led_protocol.info) {
|
|
|
|
|
const info = data.led_protocol.info;
|
|
|
|
|
ledVision.value = info.versions;
|
|
|
|
|
ledTime.value = info.compile_time;
|
|
|
|
|
ledStatus.value = '在线';
|
|
|
|
|
resolve(data);
|
|
|
|
|
} else if (data.LPR_card && data.LPR_card.info) {
|
|
|
|
|
const info = data.LPR_card.info;
|
|
|
|
|
carVision.value = info.versions;
|
|
|
|
|
carTime.value = info.compile_time;
|
|
|
|
|
carStatus.value = '在线';
|
|
|
|
|
resolve(data);
|
|
|
|
|
} else if (data.sound_card && data.sound_card.info) {
|
|
|
|
|
const info = data.sound_card.info;
|
|
|
|
|
g4Vision.value = info.versions;
|
|
|
|
|
g4Time.value = info.compile_time;
|
|
|
|
|
g4Status.value = '在线';
|
|
|
|
|
resolve(data);
|
|
|
|
|
} else if (data.LoRa_card && data.LoRa_card.info) {
|
|
|
|
|
const info = data.LoRa_card.info;
|
|
|
|
|
loraVision.value = info.versions;
|
|
|
|
|
loraTime.value = info.compile_time;
|
|
|
|
|
loraStatus.value = '在线';
|
|
|
|
|
resolve(data);
|
|
|
|
|
} else if (data.gateway && data.gateway.info) {
|
|
|
|
|
const info = data.gateway.info;
|
|
|
|
|
gatwayVision.value = info.versions;
|
|
|
|
|
gatewayTime.value = info.compile_time;
|
|
|
|
|
gatewaystatus.value = '在线';
|
|
|
|
|
resolve(data);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
resolve(data);
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
.catch(error => {
|
|
|
|
|
clearTimeout(timeout); // 在捕获错误后清除超时
|
|
|
|
|
if (error.response && error.response.status === 500) {
|
|
|
|
|
console.error('收到 500 错误码,跳过该请求');
|
|
|
|
|
resolve({ skipped: true });
|
|
|
|
|
} else {
|
|
|
|
|
console.error('Axios 请求错误:', error);
|
|
|
|
|
reject(error);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// MQTT 接收函数
|
|
|
|
|
const MQTT_recv = (string) => {
|
2025-05-27 15:23:19 +08:00
|
|
|
|
// console.log("MQTT 接收的json:" + string);
|
|
|
|
|
// 先解析一次字符串化的 JSON
|
|
|
|
|
const parsedString = JSON.parse(string);
|
|
|
|
|
// 如果解析后的结果仍然是字符串,需要再次解析
|
|
|
|
|
const data = typeof parsedString === 'string' ? JSON.parse(parsedString) : parsedString;
|
2025-05-30 16:25:17 +08:00
|
|
|
|
// console.log("MQTTRECV 接收的json:" + JSON.stringify(data));
|
2025-05-27 15:23:19 +08:00
|
|
|
|
handleMQTTMessage(JSON.stringify(data));
|
2024-11-13 11:26:59 +08:00
|
|
|
|
};
|
|
|
|
|
// 下拉刷新事件处理函数
|
|
|
|
|
const onRefresh = async () => {
|
|
|
|
|
loading.value = true; // 开始刷新时设置 loading 为 true
|
|
|
|
|
|
|
|
|
|
const requests = [
|
|
|
|
|
{ type: isLocal ? 'axios' : 'mqtt', data: { "JSON_id": jsonId.value++, "board_id": 1, "gateway": { "get_info": 1 } } },
|
|
|
|
|
{ type: isLocal ? 'axios' : 'mqtt', data: { "JSON_id": jsonId.value++, "board_id": 102, "led_protocol": { "get_info": 1 } } },
|
|
|
|
|
{ type: isLocal ? 'axios' : 'mqtt', data: { "JSON_id": jsonId.value++, "board_id": 104, "LPR_card": { "get_info": 1 } } },
|
|
|
|
|
{ type: isLocal ? 'axios' : 'mqtt', data: { "JSON_id": jsonId.value++, "board_id": 103, "sound_card": { "get_info": 1 } } },
|
|
|
|
|
{ type: isLocal ? 'axios' : 'mqtt', data: { "JSON_id": jsonId.value++, "board_id": 105, "LoRa_card": { "get_info": 1 } } },
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
for (const request of requests) {
|
|
|
|
|
await sendRequest(request.data, request.type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
loading.value = false; // 完成所有请求后停止 loading
|
|
|
|
|
|
|
|
|
|
// 如果没有收到某个设备的信息,设置其状态为离线
|
|
|
|
|
if (!ledVision.value) ledStatus.value = '离线';
|
|
|
|
|
if (!carVision.value) carStatus.value = '离线';
|
|
|
|
|
if (!g4Vision.value) g4Status.value = '离线';
|
|
|
|
|
if (!loraVision.value) loraStatus.value = '离线';
|
|
|
|
|
if (!gatwayVision.value) gatewaystatus.value = '离线';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 在组件挂载时建立 MQTT 连接
|
|
|
|
|
onMounted(() => {
|
|
|
|
|
console.log(isLocal);
|
2025-05-27 15:23:19 +08:00
|
|
|
|
const messageHandler = function (event) {
|
|
|
|
|
console.log("111接受的原始数据", JSON.stringify(event.data))
|
2025-05-22 15:34:21 +08:00
|
|
|
|
if (event.data) {
|
|
|
|
|
MQTT_recv(JSON.stringify(event.data)); // 保持与原 MQTT_recv 兼容
|
|
|
|
|
}
|
2025-05-27 15:23:19 +08:00
|
|
|
|
};
|
|
|
|
|
window.addEventListener('message', messageHandler);
|
|
|
|
|
// onRefresh();
|
|
|
|
|
|
|
|
|
|
// 在组件卸载时移除事件监听器
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
window.removeEventListener('message', messageHandler);
|
|
|
|
|
console.log('移除事件监听器');
|
|
|
|
|
|
2025-05-22 15:34:21 +08:00
|
|
|
|
});
|
2024-11-13 11:26:59 +08:00
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
onBeforeUnmount(() => {
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// 获取状态对应的类
|
|
|
|
|
const getStatusClass = (status) => {
|
|
|
|
|
return status === '在线' ? 'state online' : 'state offline';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
currentTitle,
|
|
|
|
|
loading,
|
|
|
|
|
onRefresh,
|
|
|
|
|
ledVision,
|
|
|
|
|
ledTime,
|
|
|
|
|
carVision,
|
|
|
|
|
carTime,
|
|
|
|
|
g4Vision,
|
|
|
|
|
g4Time,
|
|
|
|
|
loraTime,
|
|
|
|
|
loraVision,
|
|
|
|
|
ledStatus,
|
|
|
|
|
g4Status,
|
|
|
|
|
carStatus,
|
|
|
|
|
loraStatus,
|
|
|
|
|
getStatusClass,
|
|
|
|
|
gatwayVision,
|
|
|
|
|
gatewayTime,
|
|
|
|
|
gatewaystatus,
|
|
|
|
|
MQTT_send,
|
|
|
|
|
MQTT_recv,
|
|
|
|
|
handleMQTTMessage,
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
<style scoped>
|
|
|
|
|
.page-container {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
position: relative;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.state {
|
|
|
|
|
text-align: right;
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.online {
|
|
|
|
|
color: green;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.offline {
|
|
|
|
|
color: gray;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.content {
|
|
|
|
|
flex: 1;
|
|
|
|
|
overflow-y: auto;
|
|
|
|
|
padding: 20px;
|
|
|
|
|
border-radius: 20px !important;
|
|
|
|
|
margin-top: 80px;
|
|
|
|
|
margin-bottom: 100px;
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.item {
|
|
|
|
|
border: 2px solid #0668fc;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
display: flex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.title {
|
|
|
|
|
text-align: center;
|
|
|
|
|
font-size: 30px;
|
|
|
|
|
}
|
|
|
|
|
</style>
|