2025-06-06 06:31:05 +08:00

423 lines
14 KiB
Vue
Raw 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>
<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';
// const MQTT_send = (send_string) => {
// console.log(" 向父页面发送消息:", JSON.stringify(send_string));
// // 使用 postMessage 发送数据给父页面
// window.parent.postMessage(
// {
// data: send_string
// },
// '*' // 目标 origin生产环境应替换为具体的父页面域名
// );
// };
// const MQTT_send = (send_string) => {
// 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生产环境应替换为具体的父页面域名
// );
// }
// };
const MQTT_send = (send_string) => {
console.log("向父页面发送消息:", JSON.stringify(send_string));
// 统一使用uni.postMessage方法发送消息
uni.postMessage({
data: {
type: 'mqtt_data',
payload: send_string,
timestamp: Date.now()
}
});
};
const handleMQTTMessage = (string) => {
// console.log("MQTT 接收:" + string);
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) => {
// console.log("MQTT 接收的json:" + string);
// 先解析一次字符串化的 JSON
const parsedString = JSON.parse(string);
// 如果解析后的结果仍然是字符串,需要再次解析
const data = typeof parsedString === 'string' ? JSON.parse(parsedString) : parsedString;
// console.log("MQTTRECV 接收的json:" + JSON.stringify(data));
handleMQTTMessage(JSON.stringify(data));
};
// 下拉刷新事件处理函数
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);
const messageHandler = function (event) {
console.log("111接受的原始数据", JSON.stringify(event.data))
if (event.data) {
MQTT_recv(JSON.stringify(event.data)); // 保持与原 MQTT_recv 兼容
}
};
window.addEventListener('message', messageHandler);
// onRefresh();
// 在组件卸载时移除事件监听器
onBeforeUnmount(() => {
window.removeEventListener('message', messageHandler);
console.log('移除事件监听器');
});
});
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>