<template> <div class="container"> <el-row :gutter="20"> <el-col :span="5"> <el-tree :data="data" :props="defaultProps" accordion @node-click="handleNodeClick" :empty-text="$t('main.sData.noData')" ></el-tree> </el-col> <el-col :span="19"> <el-row> <el-col :span="24"> <el-table :empty-text="$t('main.sData.noData')" ref="table" :data="tableData" max-height="800" style="width: 100%" border stripe > <el-table-column prop="code" :label="$t('main.sData.platformCode')" width="120" ></el-table-column> <el-table-column prop="name" :label="$t('main.sData.platformName')" width="150" ></el-table-column> <el-table-column prop="outputProperty" :label="$t('main.sData.extractedAttribute')" width="100" :formatter="formatOutputProperty" > </el-table-column> <el-table-column prop="autoStatus" :label="$t('main.sData.automaticState')" width="100" :formatter="formatAutoStatus" ></el-table-column> <el-table-column prop="barcode" :label="$t('main.sData.barCode')" width="120" ></el-table-column> <el-table-column prop="requestMessage" :label="$t('main.sData.PLC_requestMessage')" width="120" ></el-table-column> <el-table-column prop="requestLoadStatus" :label="$t('main.sData.PLC_requestToLoad')" width="120" ></el-table-column> <el-table-column prop="requestNumber" :label="$t('main.sData.PLC_requestCodeReader')" width="130" ></el-table-column> <el-table-column prop="requestBarcode" :label="$t('main.sData.PLC_requestBarcode')" width="120" ></el-table-column> <el-table-column prop="requestWeight" :label="$t('main.sData.PLC_requestWeight')" width="120" ></el-table-column> <el-table-column prop="requestLength" :label="$t('main.sData.PLC_requestLength')" width="120" ></el-table-column> <el-table-column prop="requestWidth" :label="$t('main.sData.PLC_requestWidth')" width="120" ></el-table-column> <el-table-column prop="requestHeight" :label="$t('main.sData.PLC_requestHeight')" width="120" ></el-table-column> <el-table-column prop="wcsReplyMessage" :label="$t('main.sData.WCS_requestMessage')" width="120" ></el-table-column> <el-table-column prop="wcsReplyLoadStatus" :label="$t('main.sData.WCS_requestToLoad')" width="120" ></el-table-column> <el-table-column prop="wcsReplyNumber" :label="$t('main.sData.WCS_requestCodeReader')" width="130" ></el-table-column> <el-table-column prop="wcsReplyBarcode" :label="$t('main.sData.WCS_requestBarcode')" width="120" ></el-table-column> <el-table-column prop="wcsReplyWeight" :label="$t('main.sData.WCS_requestWeight')" width="120" ></el-table-column> <el-table-column prop="wcsReplyLength" :label="$t('main.sData.WCS_requestLength')" width="120" ></el-table-column> <el-table-column prop="wcsReplyWidth" :label="$t('main.sData.WCS_requestWidth')" width="120" ></el-table-column> <el-table-column prop="wcsReplyHeight" :label="$t('main.sData.WCS_requestHeight')" width="120" ></el-table-column> <el-table-column prop="wcsReplyAddress" :label="$t('main.sData.WCS_targetAddress')" width="120" ></el-table-column> <el-table-column prop="arriveMessage" :label="$t('main.sData.PLC_arrivalMessage')" width="120" ></el-table-column> <el-table-column prop="arriveResult" :label="$t('main.sData.PLC_arrivalResult')" width="120" ></el-table-column> <el-table-column prop="arriveAllocationAddress" :label="$t('main.sData.PLC_arrivalAssignAddress')" width="140" ></el-table-column> <el-table-column prop="arriveBarcode" :label="$t('main.sData.PLC_arrivalBarcode')" width="120" ></el-table-column> <el-table-column prop="wcsAddressACKMessage" :label="$t('main.sData.WCS_arrivalMessage')" width="120" ></el-table-column> <el-table-column prop="wcsAddressACKLoadStatus" :label="$t('main.sData.WCS_arrivalToLoad')" width="120" ></el-table-column> <el-table-column prop="code" :label="$t('main.sData.WCS_platformCode')" width="120" ></el-table-column> </el-table> </el-col> <el-col :span="24" v-if="currentDetail"> <div class="detail-panel" style="display: flex; flex-direction: column; height: 100%" > <el-row :gutter="20" style="flex: 1; display: flex"> <!-- PLC地址请求 --> <el-col :span="12" style="height: 100%"> <el-card class="box-card" style="height: 100%"> <div slot="header" class="clearfix"> <span>{{ $t("main.sData.PLC_addressRequest") }}</span> </div> <el-descriptions :column="2" size="medium" border> <el-descriptions-item :label="$t('main.sData.requestMessage')">{{ currentDetail.requestMessage }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.load')">{{ currentDetail.requestLoadStatus }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.codeReader')">{{ currentDetail.requestNumber }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.barCode')">{{ currentDetail.requestBarcode }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.weight')">{{ currentDetail.requestWeight }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.length')">{{ currentDetail.requestLength }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.width')">{{ currentDetail.requestWidth }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.height')">{{ currentDetail.requestHeight }}</el-descriptions-item> </el-descriptions> </el-card> </el-col> <!-- PLC位置到达 --> <el-col :span="12" style="height: 100%"> <el-card class="box-card" style="height: 100%"> <div slot="header" class="clearfix"> <span>{{ $t("main.sData.PLC_positionArrived") }}</span> </div> <el-descriptions :column="2" size="medium" border> <el-descriptions-item :label="$t('main.sData.arrivalMessage')">{{ currentDetail.arriveMessage }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.result')">{{ currentDetail.arriveResult }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.codeReader')">{{ currentDetail.arriveRealAddress }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.assignAddress')">{{ currentDetail.arriveAllocationAddress }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.arrivalBarcode')">{{ currentDetail.arriveBarcode }}</el-descriptions-item> </el-descriptions> </el-card> </el-col> </el-row> <!-- WCS地址请求 --> <el-row :gutter="20" style="flex: 1; display: flex; margin-top: 0" > <el-col :span="12" style="height: 100%"> <el-card class="box-card" style="height: 100%"> <div slot="header" class="clearfix"> <span>{{ $t("main.sData.WCS_addressRequestReply") }}</span> </div> <el-descriptions :column="2" size="medium" border> <el-descriptions-item :label="$t('main.sData.requestMessage')">{{ currentDetail.wcsReplyMessage }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.load')">{{ currentDetail.wcsReplyLoadStatus }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.codeReader')">{{ currentDetail.wcsReplyNumber }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.barCode')">{{ currentDetail.wcsReplyBarcode }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.weight')">{{ currentDetail.wcsReplyWeight }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.length')">{{ currentDetail.wcsReplyLength }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.width')">{{ currentDetail.wcsReplyWidth }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.height')" >{{ currentDetail.wcsReplyHeight }} </el-descriptions-item> <el-descriptions-item :label="$t('main.sData.targetAddress')" >{{ currentDetail.wcsReplyAddress }} </el-descriptions-item> </el-descriptions> </el-card> </el-col> <!-- WCS位置到达 --> <el-col :span="12" style="height: 100%"> <el-card class="box-card" style="height: 100%"> <div slot="header" class="clearfix"> <span>{{ $t("main.sData.WCS_locationArrivedReply") }}</span> </div> <el-descriptions :column="2" size="medium" border> <el-descriptions-item :label="$t('main.sData.arrivalMessage')">{{ currentDetail.wcsAddressACKMessage }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.load')">{{ currentDetail.wcsAddressACKLoadStatus }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.codeReader')">{{ currentDetail.wcsAddressACKNumber }}</el-descriptions-item> <el-descriptions-item :label="$t('main.sData.arrivalBarcode')">{{ currentDetail.wcsAddressACKBarcode }}</el-descriptions-item> </el-descriptions> </el-card> </el-col> </el-row> </div> </el-col> </el-row> </el-col> </el-row> </div> </template> <script> import { GetSRMInfo, GetStationInfo, GetStationMonitorInfo } from "@/api/main"; export default { data() { return { data: [], defaultProps: { children: "children", label: "label", }, tableData: [], currentDetail: null, zhantai: null, GetSRMInfo: null, zhantaibaowen: null, isLoading: false, isCurrentTab: false, isOpenServer: false, lastProcessedData: null, // 新增数据比对变量 lastRawData: null, // 存储原始API数据用于比较 }; }, props: { // 定义接收的 startDeal 变量 startDeal: { type: Boolean, default: false, }, }, watch: { // 监听 startDeal 变量的变化 startDeal(newValue, oldValue) { // console.log('处理状态发生变化:', newValue); this.isOpenServer = newValue; if (this.isCurrentTab) { if (newValue) { this.start(); } else { this.stop(); } } }, }, created() { // this.handleNodeClick(this.data[0]); // 默认选择第一个节点 }, beforeDestroy() { clearInterval(this.timer); }, methods: { formatOutputProperty(row, column) { console.log("formatOutputProperty", row, column); if (row.outputProperty === "True") return this.$t("main.msg.canBeReleased"); if (row.outputProperty === "False") return this.$t("main.msg.cannotBeReleased"); return ""; }, formatAutoStatus(row, column, cellValue) { return cellValue === 1 ? this.$t("main.msg.automatic") : this.$t("main.msg.NonAutomatic"); }, // 添加深度比对方法 isDataChanged(newData) { if (!this.lastProcessedData) return true; return JSON.stringify(newData) !== JSON.stringify(this.lastProcessedData); }, start() { this.isCurrentTab = true; if (!this.isOpenServer) { return; } // console.log("start方法被调用"); if (this.timer) { return; } this.isLoading = true; this.loadAllData(); this.timer = setInterval(() => { this.loadAllData(); }, 3000); }, stop() { this.isCurrentTab = false; clearInterval(this.timer); this.timer = null; this.isLoading = false; this.data = []; this.tableData = []; this.currentDetail = null; this.zhantai = null; this.GetSRMInfo = null; this.zhantaibaowen = null; this.lastProcessedData = null; this.lastRawData = null; }, async loadAllData() { this.isLoading = true; try { const [stationRes, srmRes, monitorRes] = await Promise.all([ GetStationInfo(), GetSRMInfo(), GetStationMonitorInfo(), ]); if ( stationRes.code === "Success" && srmRes.code === "Success" && monitorRes.code === "Success" ) { // 创建原始数据对象用于比较 const rawData = { station: stationRes.data, srm: srmRes.data, monitor: monitorRes.data, }; // 只有当原始数据变化时才处理 if ( !this.lastRawData || JSON.stringify(rawData) !== JSON.stringify(this.lastRawData) ) { this.zhantai = stationRes.data; this.GetSRMInfo = srmRes.data; this.zhantaibaowen = monitorRes.data; this.lastRawData = rawData; // 存储原始数据副本 this.GetStationInfoData(); } // console.log( // "站台主要数据:", // stationRes, // "堆垛机:", // srmRes, // "站台监控:", // monitorRes // ); } } catch (error) { console.error(this.$t("main.msg.dataLoadingFailed"), error); } finally { this.isLoading = false; } }, // initGetStationInfo() { // GetStationInfo().then((res) => { // console.log("站台请求", res); // if (res.code == "Success") { // this.zhantai = res.data; // } // }); // }, // initGetSRMInfo() { // GetSRMInfo().then((res) => { // if (res.code != "Success") { // return; // } // console.log("堆垛机", res); // this.GetSRMInfo = res.data; // }); // }, // initGetStationMonitorInfo() { // GetStationMonitorInfo().then((res) => { // if (res.code != "Success") { // return; // } // console.log("站台监控", res); // this.zhantaibaowen = res.data; // }); // }, GetStationInfoData() { // let zhantai = window.zhajtaiData; // let GetSRMInfo = window.GetSRMInfoData; // let zhantaibaowenData = window.zhantaibaowen; // 处理SRM信息映射 const GetSRMInfolist = this.GetSRMInfo.map((item) => { return { ...item, extraProps: item.extraProps.map((prop) => { if (prop.key?.includes("Station")) { prop.key = prop.key.replace("Station", ""); } return prop; }), }; }); // 处理站台属性映射 this.zhantai = this.zhantai.map((item) => { item.outputProperty = ""; const srmInfo = GetSRMInfolist.find( (srm) => srm.destinationArea === item.destinationArea ); if (srmInfo) { const matchingProp = srmInfo.extraProps.find( (prop) => prop.key == item.stationIndex ); if (matchingProp) item.outputProperty = matchingProp.value; } return item; }); // 合并监控数据 this.zhantai.forEach((zhantaiItem) => { const newCode = "StationMonitor" + zhantaiItem.code; const matchingMonitor = this.zhantaibaowen.find( (monitorItem) => monitorItem.code == newCode ); if (matchingMonitor) { zhantaiItem.autoStatus = matchingMonitor.stationMonitorAutomation; zhantaiItem.barcode = matchingMonitor.stationMonitorBarcode; } }); const validGroups = [ ...new Set( this.zhantai .map((item) => item.stationGroup) .filter((group) => group && group.trim() !== "") ), ]; const hasEmptyGroup = this.zhantai.some( (item) => !item.stationGroup || item.stationGroup.trim() === "" ); const stationGroups = [...validGroups]; if (hasEmptyGroup) stationGroups.push(this.$t("main.msg.otherPlatforms")); // 构建树形数据但不立即赋值 const processedData = stationGroups.map((group) => ({ label: group, children: this.zhantai .filter((item) => { if (group === this.$t("main.msg.otherPlatforms")) { return !item.stationGroup || item.stationGroup.trim() === ""; } return item.stationGroup === group; }) .map((item) => { // 新增条码字段处理逻辑 const processBarcode = (value) => { return value && value.includes("\u0001") ? "" : value; }; return { label: item.code, name: item.stationIndex ? `${item.name}this.$t("main.msg.index")${item.stationIndex}` : item.name, code: item.code, outputProperty: item.outputProperty, autoStatus: item.autoStatus, barcode: item.barcode, // PLC地址请求 requestMessage: item.requestMessage, requestLoadStatus: item.requestLoadStatus, RequestNumber: item.RequestNumber, requestBarcode: processBarcode(item.requestBarcode), requestWeight: item.requestWeight, requestLength: item.requestLength, requestWidth: item.requestWidth, requestHeight: item.requestHeight, // PLC位置到达 arriveMessage: item.arriveMessage, arriveResult: item.arriveResult, arriveRealAddress: item.arriveRealAddress, arriveAllocationAddress: item.arriveAllocationAddress, arriveBarcode: processBarcode(item.arriveBarcode), // WCS地址请求 wcsReplyMessage: item.wcsReplyMessage, wcsReplyLoadStatus: item.wcsReplyLoadStatus, wcsReplyNumber: item.wcsReplyNumber, wcsReplyBarcode: processBarcode(item.wcsReplyBarcode), wcsReplyWeight: item.wcsReplyWeight, wcsReplyLength: item.wcsReplyLength, wcsReplyWidth: item.wcsReplyWidth, wcsReplyHeight: item.wcsReplyHeight, wcsReplyAddress: item.wcsReplyAddress, // WCS位置到达 wcsAddressACKMessage: item.wcsAddressACKMessage, wcsAddressACKLoadStatus: item.wcsAddressACKLoadStatus, wcsAddressACKNumber: item.wcsAddressACKNumber, wcsAddressACKBarcode: processBarcode(item.wcsAddressACKBarcode), }; }), })); // 仅当数据变化时更新 if (this.isDataChanged(processedData)) { this.data = processedData; this.lastProcessedData = JSON.parse(JSON.stringify(processedData)); } }, handleNodeClick(data) { if (data.children) { this.tableData = data.children; this.currentDetail = null; } else { this.tableData = [data]; this.currentDetail = data; } }, }, }; </script> <style scoped> .container { /* padding: 20px; */ } ::v-deep .el-table__body-wrapper::-webkit-scrollbar { width: 8px; height: 8px; } ::v-deep .el-table__body-wrapper::-webkit-scrollbar-thumb { background-color: #777f87; border-radius: 4px; } ::v-deep .el-table__body-wrapper::-webkit-scrollbar-track { background-color: #f5f5f5; } .el-tree { border: 1px solid #ebeef5; padding: 10px; border-radius: 4px; } ::v-deep .el-descriptions-item__label { width: 5vw !important; } .el-table { margin-top: 0; } .detail-panel { border-radius: 4px; padding: 10px 0 10px 0; height: calc(100vh - 360px) !important; box-sizing: border-box; /* 确保内边距不影响总高度 */ } ::v-deep.el-table thead { color: #101010; font-weight: 600; } </style>