Commit c3807a12 authored by Cai Wei's avatar Cai Wei

feat(*): 布袋监测连调

parent f61d456b
...@@ -132,6 +132,7 @@ export const getBagMonitoringChartOption = (xData = [], seriesData = []) => ({ ...@@ -132,6 +132,7 @@ export const getBagMonitoringChartOption = (xData = [], seriesData = []) => ({
top: "3%", top: "3%",
containLabel: true, containLabel: true,
}, },
// x轴的文字去除年月日
xAxis: { xAxis: {
type: "category", type: "category",
boundaryGap: false, boundaryGap: false,
...@@ -145,6 +146,9 @@ export const getBagMonitoringChartOption = (xData = [], seriesData = []) => ({ ...@@ -145,6 +146,9 @@ export const getBagMonitoringChartOption = (xData = [], seriesData = []) => ({
fontSize: 12, fontSize: 12,
interval: "auto", interval: "auto",
rotate: 0, rotate: 0,
formatter: function (value) {
return value.split(' ')[1];
}
}, },
axisTick: { axisTick: {
show: false, show: false,
......
...@@ -4,49 +4,69 @@ ...@@ -4,49 +4,69 @@
<div class="select-container"> <div class="select-container">
<span>检测仪器</span> <span>检测仪器</span>
<el-select v-model="selectedDevice" placeholder="1#布袋检测仪"> <el-select v-model="selectedDevice" placeholder="1#布袋检测仪">
<el-option v-for="item in deviceList" :key="item.deviceNo" :label="item.deviceName" :value="item.deviceNo"></el-option> <el-option
v-for="item in deviceList"
:key="item.deviceNo"
:label="item.deviceName"
:value="item.deviceNo"
></el-option>
</el-select> </el-select>
</div> </div>
<div class="title">BME布袋监测</div> <div class="title">BME布袋监测</div>
</div> </div>
<div class="chart-container"> <div class="chart-container">
<div class="chart-wrapper" ref="chartRef" v-if="chartData.xData.length > 0"></div> <div class="chart-wrapper" ref="chartRef"></div>
<div class="chart-wrapper" v-else> <div class="chart-wrapper no-data" v-if="chartData.xData.length === 0">
<div class="no-data-text">暂无数据</div> <div class="no-data-text">暂无数据</div>
</div> </div>
</div>
<div class="data-panel" :class="{ 'collapsed': !isPanelOpen }">
<div class="panel-toggle" :class="{ 'collapsed-icon': !isPanelOpen, 'expanded-icon': isPanelOpen }" @click="togglePanel"> <div class="data-panel" :class="{ collapsed: !isPanelOpen }">
<el-icon v-if="isPanelOpen"><ArrowRightBold /></el-icon> <div
<el-icon v-if="!isPanelOpen"><ArrowLeftBold /></el-icon> class="panel-toggle"
:class="{
'collapsed-icon': !isPanelOpen,
'expanded-icon': isPanelOpen,
}"
@click="togglePanel"
>
<el-icon v-if="isPanelOpen"><ArrowRightBold /></el-icon>
<el-icon v-if="!isPanelOpen"><ArrowLeftBold /></el-icon>
</div>
<div class="data-box">
<div class="data-item">
<div>时间: {{ currentData.time }}</div>
<div>仓室: {{ currentData.compartNo }}</div>
<div>反吹: {{ currentData.blowBack }}</div>
</div> </div>
<div class="data-box">
<div class="data-item"> <div class="data-item">
<div>时间: {{ currentData.time || '-' }}</div> <div>DI3: {{ currentData.di3 }}</div>
<div>仓室: {{ currentData.compartName }}</div>
<div>反吹: {{ currentData.blowBack }}</div>
</div>
<div class="data-item">
<div>排: {{ currentData.row }}</div> <div>排: {{ currentData.row }}</div>
<div>实时值: {{ currentData.realData }}</div> <div>实时值: {{ currentData.realData }}</div>
</div>
<div class="data-item">
<div>基线值: {{ currentData.baseline }}</div> <div>基线值: {{ currentData.baseline }}</div>
<div>Delay: {{ currentData.delay }}</div>
<div>totaltime: {{ currentData.totalTime }}</div>
</div>
<div class="data-item">
<div>next:{{ currentData.next }}</div>
<div>valve:{{ currentData.valveNo }}</div>
<div>DI_TIME={{ currentData.diTime }}</div>
</div> </div>
<div class="data-item"> <div class="data-item">
<!-- <div>峰值R: {{ currentData.peakValueR }}</div>
<div>峰值H: {{ currentData.peakValueH }}</div> -->
<div>peak={{ currentData.peak }}</div> <div>peak={{ currentData.peak }}</div>
</div> </div>
</div> </div>
<!-- <div class="data-box second-box"> <!-- <div class="data-box second-box">
<div>时间:{{ secondaryData.time }}, 仓室: {{ secondaryData.chamber }}, 反吹: {{ secondaryData.backwash }}, 谷值: {{ secondaryData.valleyValue }}, 仓室状态阀门{{ secondaryData.status }}False{{ secondaryData.falseVal }}</div> <div>时间:{{ secondaryData.time }}, 仓室: {{ secondaryData.chamber }}, 反吹: {{ secondaryData.backwash }}, 谷值: {{ secondaryData.valleyValue }}, 仓室状态阀门{{ secondaryData.status }}False{{ secondaryData.falseVal }}</div>
</div> --> </div> -->
</div>
</div> </div>
<div class="data-table">
<div class="data-table">
<div class="time-controls"> <div class="time-controls">
<el-button @click="navigateBackward"> <el-button @click="navigateBackward">
<el-icon><ArrowLeftBold />向前</el-icon> <el-icon><ArrowLeftBold />向前</el-icon>
...@@ -65,415 +85,451 @@ ...@@ -65,415 +85,451 @@
<thead> <thead>
<tr> <tr>
<th>名称</th> <th>名称</th>
<th v-for="(value, index) in tableData" :key="index">{{ value.compartName }}</th> <th v-for="(value, index) in tableData" :key="index">
{{ value.compartName }}
</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td>峰值_R</td> <td>峰值_R</td>
<td v-for="(value, index) in tableData" :key="'r'+index">{{ value.peakValueR || '-' }}</td> <td v-for="(value, index) in tableData" :key="'r' + index">
{{ value.peakValueR || "-" }}
</td>
</tr> </tr>
<tr> <tr>
<td>峰值_H</td> <td>峰值_H</td>
<td v-for="(value, index) in tableData" :key="'h'+index">{{ value.peakValueH || '-' }}</td> <td v-for="(value, index) in tableData" :key="'h' + index">
{{ value.peakValueH || "-" }}
</td>
</tr> </tr>
<tr> <tr>
<td>状态</td> <td>状态</td>
<td v-for="(value, index) in tableData" :key="'s'+index" :class="{ 'error': value.status === 1 }">{{ value.status === 1 ? '故障' : '正常' }}</td> <td
v-for="(value, index) in tableData"
:key="'s' + index"
:class="{ error: value.status === 1 }"
>
{{ value.status === 1 ? "故障" : "正常" }}
</td>
</tr> </tr>
<tr> <tr>
<td>反吹中</td> <td>反吹中</td>
<td v-for="(value, index) in tableData" :key="'b'+index">{{ value.blowBack || '-' }}</td> <td v-for="(value, index) in tableData" :key="'b' + index">
{{ value.blowBack || "-" }}
</td>
</tr> </tr>
<tr> <tr>
<td>谷值</td> <td>谷值</td>
<td v-for="(value, index) in tableData" :key="'v'+index">{{ value.valleyValue || '-' }}</td> <td v-for="(value, index) in tableData" :key="'v' + index">
{{ value.valleyValue || "-" }}
</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted, onBeforeUnmount, watch } from 'vue' import { ref, reactive, onMounted, onBeforeUnmount, watch } from "vue";
import * as echarts from 'echarts' import * as echarts from "echarts";
import moment from 'moment' import moment from "moment";
import { ArrowRightBold, ArrowLeftBold } from '@element-plus/icons-vue' import { ArrowRightBold, ArrowLeftBold } from "@element-plus/icons-vue";
import { getBagMonitoringChartOption } from '@/utils/chart.js' import { getBagMonitoringChartOption } from "@/utils/chart.js";
import { getMonitorToday, getMonitorList, getMonitorRealtime } from '@/request/api/bagMonitor' import {
import { useRoute } from 'vue-router' getMonitorToday,
getMonitorList,
getMonitorRealtime,
} from "@/request/api/bagMonitor";
import { useRoute } from "vue-router";
// 获取路由参数 // 获取路由参数
const route = useRoute() const route = useRoute();
// 设备选择 // 设备选择
const selectedDevice = ref(null) const selectedDevice = ref(null);
const isPanelOpen = ref(true) const isPanelOpen = ref(true);
// 图表相关 // 图表相关
const chartRef = ref(null) const chartRef = ref(null);
let chartInstance = null let chartInstance = null;
let updateTimer = null // 定时器引用 let updateTimer = null; // 定时器引用
let lastTimePoint = null let lastTimePoint = null;
// 控制是否获取实时设备状态数据 // 控制是否获取实时设备状态数据
let showRealtimeDeviceStatus = true let showRealtimeDeviceStatus = true;
// 从路由参数获取dusterNo // 从路由参数获取dusterNo
const dusterNo = ref(route.params.dusterNo || route.query.dusterNo || 'ZH-ZL-1GL-001') // 默认值作为fallback const dusterNo = ref(
route.params.dusterNo || route.query.dusterNo || "ZH-ZL-1GL-001"
); // 默认值作为fallback
// 图表数据 // 图表数据
const chartData = reactive({ const chartData = reactive({
xData: [], xData: [],
seriesData: [] seriesData: [],
}) });
const deviceList = ref([]); const deviceList = ref([]);
const currentTime = ref(null); const currentTime = ref(null);
// 当前数据面板 // 当前数据面板
const currentData = ref({ const currentData = ref({
"date": "", realtime: "",
"realData": "", time: "",
"valveNo": "", compartNo: "",
"baseline": "", blowBack: "",
"peak": "", di3: "",
"time": "", row: "",
"compartName": "", realData: "",
"blowBack": "", baseline: "",
"row": "" delay: "",
}) totalTime: "",
next: "",
valveNo: "",
diTime: "",
peak: "",
});
// 表格数据 // 表格数据
const tableData = ref([{ const tableData = ref([
compartName: '默认', {
peakValueR: 0, compartName: "默认",
peakValueH: 0, peakValueR: 0,
status: 0, peakValueH: 0,
blowBack: 0, status: 0,
valleyValue: 0 blowBack: 0,
}]); valleyValue: 0,
},
]);
// 时间控制 // 时间控制
const timeInterval = ref('10') const timeInterval = ref("10");
const togglePanel = () => { const togglePanel = () => {
isPanelOpen.value = !isPanelOpen.value isPanelOpen.value = !isPanelOpen.value;
} };
// 初始化图表 // 初始化图表
const initChart = () => { const initChart = () => {
if (chartInstance) { if (chartInstance) {
chartInstance.dispose() chartInstance.dispose();
} }
// 初始化图表数据 // 初始化图表数据
initChartData() initChartData();
} };
// 初始化图表数据 // 初始化图表数据
const initChartData = () => { const initChartData = () => {
if (!dusterNo.value || !selectedDevice.value) { if (!dusterNo.value || !selectedDevice.value) {
console.warn('缺少dusterNo或deviceNo,无法获取数据') console.warn("缺少dusterNo或deviceNo,无法获取数据");
return return;
} }
// 获取昨天这个之前的数据 // 获取昨天这个之前的数据
const startTime = moment().subtract(1, 'days').subtract(5, 'minutes').format('YYYY-MM-DD HH:mm:ss') const startTime = moment()
const endTime = moment().subtract(1, 'days').format('YYYY-MM-DD HH:mm:ss') .subtract(5, "minutes")
chartData.xData = [] .format("YYYY-MM-DD HH:mm:ss");
chartData.seriesData = [] const endTime = moment().format("YYYY-MM-DD HH:mm:ss");
chartData.xData = [];
chartData.seriesData = [];
getMonitorToday({ getMonitorToday({
dusterNo: dusterNo.value, dusterNo: dusterNo.value,
deviceNo: selectedDevice.value, deviceNo: selectedDevice.value,
startTime: startTime, startTime: startTime,
endTime: endTime endTime: endTime,
}).then(res => {
// 将data中的date和realData数据添加到chartData中,要求大数据量下速度快
if (res.data && res.data.length > 0) {
res.data.forEach((item) => {
chartData.xData.push(item.date)
chartData.seriesData.push(item.realData)
})
// 当前时间
currentTime.value = res.data[res.data.length-1].date
chartInstance = echarts.init(chartRef.value)
// 启动定时更新
startRealTimeUpdates()
} else {
console.warn('未获取到初始数据')
}
}).catch(err => {
console.error('获取初始数据失败:', err)
}) })
} .then((res) => {
// 将data中的date和realData数据添加到chartData中,要求大数据量下速度快
if (res.data && res.data.length > 0) {
res.data.forEach((item) => {
chartData.xData.push(item.date);
chartData.seriesData.push(item.realData);
});
// 当前时间
currentTime.value = res.data[res.data.length - 1].date;
chartInstance = echarts.init(chartRef.value);
// 启动定时更新
startRealTimeUpdates();
} else {
console.warn("未获取到初始数据");
}
})
.catch((err) => {
console.error("获取初始数据失败:", err);
});
};
// 更新图表 // 更新图表
const updateChart = () => { const updateChart = () => {
if (chartInstance) { if (chartInstance) {
chartInstance.setOption(getBagMonitoringChartOption(chartData.xData, chartData.seriesData)) chartInstance.setOption(
getBagMonitoringChartOption(chartData.xData, chartData.seriesData)
);
} }
} };
// 启动实时更新 // 启动实时更新
const startRealTimeUpdates = () => { const startRealTimeUpdates = () => {
if (updateTimer) { if (updateTimer) {
clearInterval(updateTimer) clearInterval(updateTimer);
} }
updateTimer = setInterval(() => { updateTimer = setInterval(() => {
updateFunction() updateFunction();
}, 1000) }, 1000);
isRealTimeMode = true showRealtimeDeviceStatus = true;
showRealtimeDeviceStatus = true };
}
// 更新函数 // 更新函数
const updateFunction = () => { const updateFunction = () => {
if (!dusterNo.value || !selectedDevice.value) return; if (!dusterNo.value || !selectedDevice.value) return;
// 从API获取实时数据 // 从API获取实时数据
if (showRealtimeDeviceStatus) { if (showRealtimeDeviceStatus) {
getMonitorRealtime({ getMonitorRealtime({
dusterNo: dusterNo.value, dusterNo: dusterNo.value,
deviceNo: selectedDevice.value deviceNo: selectedDevice.value,
}).then(res => {
if (res.data) {
// 更新数据面板
if (res.data.realtimeCompart) {
tableData.value = res.data.realtimeCompart
}
if (res.data.realtimeCurve) {
currentData.value = res.data.realtimeCurve
}
}
}).catch(err => {
console.error('获取实时数据失败:', err)
}) })
.then((res) => {
if (res.data) {
// 更新数据面板
if (res.data.realtimeCompart) {
tableData.value = res.data.realtimeCompart;
}
if (res.data.realtimePanel) {
currentData.value = res.data.realtimePanel;
}
}
})
.catch((err) => {
console.error("获取实时数据失败:", err);
});
} }
// 结束时间往后推一秒 // 结束时间往后推一秒
let endTime = moment(new Date(currentTime.value)).add(1, 'seconds').format('YYYY-MM-DD HH:mm:ss') let endTime = moment(new Date(currentTime.value))
.add(1, "seconds")
.format("YYYY-MM-DD HH:mm:ss");
getMonitorToday({ getMonitorToday({
dusterNo: dusterNo.value, dusterNo: dusterNo.value,
deviceNo: selectedDevice.value, deviceNo: selectedDevice.value,
startTime: currentTime.value, startTime: currentTime.value,
endTime: endTime endTime: endTime,
}).then(res => { }).then((res) => {
if (res.data && res.data.length > 0) { if (res.data && res.data.length > 0) {
const item = res.data[res.data.length-1] const item = res.data[res.data.length - 1];
chartData.xData.push(item.date) chartData.xData.push(item.date);
chartData.seriesData.push(item.realData || 0) chartData.seriesData.push(item.realData || 0);
// 移除最旧的数据点以保持固定长度 // 移除最旧的数据点以保持固定长度
if (chartData.xData.length > 301) { // 保持300秒的数据 if (chartData.xData.length > 301) {
chartData.xData.shift() // 保持300秒的数据
chartData.seriesData.shift() chartData.xData.shift();
} chartData.seriesData.shift();
currentTime.value = endTime; }
// 更新图表 currentTime.value = endTime;
updateChart() // 更新图表
updateChart();
} }
}) });
} };
// 停止实时更新 // 停止实时更新
const stopRealTimeUpdates = () => { const stopRealTimeUpdates = () => {
if (updateTimer) { if (updateTimer) {
clearInterval(updateTimer) clearInterval(updateTimer);
updateTimer = null updateTimer = null;
} }
isRealTimeMode = false showRealtimeDeviceStatus = false;
showRealtimeDeviceStatus = false };
}
// 向前导航(查看更早的数据) // 向前导航(查看更早的数据)
const navigateBackward = () => { const navigateBackward = () => {
// 不完全关闭轮询,只禁用实时设备状态获取 // 不完全关闭轮询,只禁用实时设备状态获取
showRealtimeDeviceStatus = false showRealtimeDeviceStatus = false;
// 获取时间间隔(分钟) // 获取时间间隔(分钟)
const interval = parseInt(timeInterval.value) || 10 const interval = parseInt(timeInterval.value) || 10;
const intervalMs = interval * 60 * 1000 const intervalMs = interval * 60 * 1000;
// 如果是第一次点击,以当前最后一条数据的时间为参考 // 如果是第一次点击,以当前最后一条数据的时间为参考
if (lastTimePoint === null && chartData.xData.length > 0) { if (lastTimePoint === null && chartData.xData.length > 0) {
const lastTimeString = chartData.xData[chartData.xData.length - 1] const lastTimeString = chartData.xData[chartData.xData.length - 1];
lastTimePoint = new Date(lastTimeString) lastTimePoint = new Date(lastTimeString);
} else if (lastTimePoint === null) { } else if (lastTimePoint === null) {
// 如果没有数据,使用当前时间 // 如果没有数据,使用当前时间
lastTimePoint = new Date() lastTimePoint = new Date();
} }
// 计算新的时间范围 // 计算新的时间范围
const endTime = new Date(lastTimePoint.getTime() - intervalMs) const endTime = new Date(lastTimePoint.getTime() - intervalMs);
lastTimePoint = endTime lastTimePoint = endTime;
// 重新生成数据 // 重新生成数据
generateHistoricalData(endTime, interval) generateHistoricalData(endTime, interval);
} };
// 向后导航(查看更近的数据) // 向后导航(查看更近的数据)
const navigateForward = () => { const navigateForward = () => {
// 不完全关闭轮询,只禁用实时设备状态获取 // 不完全关闭轮询,只禁用实时设备状态获取
showRealtimeDeviceStatus = false showRealtimeDeviceStatus = false;
// 获取时间间隔(分钟) // 获取时间间隔(分钟)
const interval = parseInt(timeInterval.value) || 10 const interval = parseInt(timeInterval.value) || 10;
const intervalMs = interval * 60 * 1000 const intervalMs = interval * 60 * 1000;
// 如果是第一次点击,以当前最后一条数据的时间为参考 // 如果是第一次点击,以当前最后一条数据的时间为参考
if (lastTimePoint === null && chartData.xData.length > 0) { if (lastTimePoint === null && chartData.xData.length > 0) {
const lastTimeString = chartData.xData[chartData.xData.length - 1] const lastTimeString = chartData.xData[chartData.xData.length - 1];
lastTimePoint = new Date(lastTimeString) lastTimePoint = new Date(lastTimeString);
} else if (lastTimePoint === null) { } else if (lastTimePoint === null) {
// 如果没有数据,使用当前时间 // 如果没有数据,使用当前时间
lastTimePoint = new Date() lastTimePoint = new Date();
} }
// 计算新的时间范围 // 计算新的时间范围
const endTime = new Date(lastTimePoint.getTime() + intervalMs) const endTime = new Date(lastTimePoint.getTime() + intervalMs);
// 如果新的结束时间超过当前时间,则切换回实时模式 // 如果新的结束时间超过当前时间,则切换回实时模式
const now = moment() const now = moment();
if (endTime > now) { if (endTime > now) {
lastTimePoint = null lastTimePoint = null;
showRealtimeDeviceStatus = true showRealtimeDeviceStatus = true;
return return;
} }
lastTimePoint = endTime lastTimePoint = endTime;
// 重新生成数据 // 重新生成数据
generateHistoricalData(endTime, interval) generateHistoricalData(endTime, interval);
} };
const reset = () => { const reset = () => {
// 清空现有数据 // 清空现有数据
chartData.xData = [] chartData.xData = [];
chartData.seriesData = [] chartData.seriesData = [];
lastTimePoint = null lastTimePoint = null;
// 恢复实时设备状态获取 // 恢复实时设备状态获取
showRealtimeDeviceStatus = true showRealtimeDeviceStatus = true;
// 重新生成当前时间往前300秒的数据 // 重新生成当前时间往前300秒的数据
const now = new Date() const now = new Date();
generateHistoricalData(now, 5);
generateHistoricalData(now, 5)
// 开启实时更新 // 开启实时更新
startRealTimeUpdate() startRealTimeUpdate();
} };
// 开启实时更新(重置用) // 开启实时更新(重置用)
const startRealTimeUpdate = () => { const startRealTimeUpdate = () => {
// 确保之前的定时器已清除 // 确保之前的定时器已清除
stopRealTimeUpdates() stopRealTimeUpdates();
// 初始化实时模式标志
isRealTimeMode = true
// 启动定时更新 // 启动定时更新
updateTimer = setInterval(() => { updateTimer = setInterval(() => {
updateFunction() updateFunction();
}, 1000) }, 1000);
} };
// 生成历史数据 // 生成历史数据
const generateHistoricalData = (endTime, intervalMinutes) => { const generateHistoricalData = (endTime, intervalMinutes) => {
if (!dusterNo.value || !selectedDevice.value) return; if (!dusterNo.value || !selectedDevice.value) return;
// 清空现有数据 // 清空现有数据
chartData.xData = [] chartData.xData = [];
chartData.seriesData = [] chartData.seriesData = [];
const startTime = new Date(endTime.getTime() - intervalMinutes * 60 * 1000) const startTime = new Date(endTime.getTime() - intervalMinutes * 60 * 1000);
const startTimeStr = moment(startTime).format('YYYY-MM-DD HH:mm:ss') const startTimeStr = moment(startTime).format("YYYY-MM-DD HH:mm:ss");
const endTimeStr = moment(endTime).format('YYYY-MM-DD HH:mm:ss') const endTimeStr = moment(endTime).format("YYYY-MM-DD HH:mm:ss");
// 从API获取历史数据 // 从API获取历史数据
getMonitorToday({ getMonitorToday({
dusterNo: dusterNo.value, dusterNo: dusterNo.value,
deviceNo: selectedDevice.value, deviceNo: selectedDevice.value,
startTime: startTimeStr, startTime: startTimeStr,
endTime: endTimeStr endTime: endTimeStr,
}).then(res => {
if (res.data && res.data.length > 0) {
res.data.forEach(item => {
chartData.xData.push(item.date)
chartData.seriesData.push(item.realData)
})
// 更新图表
updateChart()
}
}).catch(err => {
console.error('获取历史数据失败:', err)
}) })
} .then((res) => {
if (res.data && res.data.length > 0) {
res.data.forEach((item) => {
chartData.xData.push(item.date);
chartData.seriesData.push(item.realData);
});
// 更新图表
updateChart();
}
})
.catch((err) => {
console.error("获取历史数据失败:", err);
});
};
// 监听窗口大小变化,调整图表大小 // 监听窗口大小变化,调整图表大小
const handleResize = () => { const handleResize = () => {
if (chartInstance) { if (chartInstance) {
chartInstance.resize() chartInstance.resize();
} }
} };
const getDeviceList = () => { const getDeviceList = () => {
if (!dusterNo.value) return; if (!dusterNo.value) return;
getMonitorList({ getMonitorList({
dusterNo: dusterNo.value dusterNo: dusterNo.value,
}).then(res => { }).then((res) => {
deviceList.value = res.data.devices || []; deviceList.value = res.data.devices || [];
if (deviceList.value.length > 0) { if (deviceList.value.length > 0) {
selectedDevice.value = deviceList.value[0].deviceNo selectedDevice.value = deviceList.value[0].deviceNo;
tableData.value = Array.from({ length: res.data.compartCount }, (item, index) => ({ tableData.value = Array.from(
compartName: `${index+1}仓`, { length: res.data.compartCount },
peakValueR: 0, (item, index) => ({
peakValueH: 0, compartName: `${index + 1}仓`,
status: 0, peakValueR: 0,
blowBack: 0, peakValueH: 0,
})) status: 0,
blowBack: 0,
})
);
} }
initChart() initChart();
}) });
} };
// 监听dusterNo变化 // 监听dusterNo变化
watch(dusterNo, (newVal) => { watch(dusterNo, (newVal) => {
if (newVal) { if (newVal) {
// 重新获取设备列表 // 重新获取设备列表
getDeviceList() getDeviceList();
} }
}) });
onMounted(() => { onMounted(() => {
console.log("dusterNo", route); console.log("dusterNo", route);
if (dusterNo.value) { if (dusterNo.value) {
getDeviceList() getDeviceList();
} }
window.addEventListener('resize', handleResize) window.addEventListener("resize", handleResize);
}) });
onBeforeUnmount(() => { onBeforeUnmount(() => {
window.removeEventListener('resize', handleResize) window.removeEventListener("resize", handleResize);
// 清除定时器 // 清除定时器
if (updateTimer) { if (updateTimer) {
clearInterval(updateTimer) clearInterval(updateTimer);
updateTimer = null updateTimer = null;
} }
// 销毁图表实例 // 销毁图表实例
if (chartInstance) { if (chartInstance) {
chartInstance.dispose() chartInstance.dispose();
chartInstance = null chartInstance = null;
} }
}) });
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
...@@ -481,15 +537,16 @@ onBeforeUnmount(() => { ...@@ -481,15 +537,16 @@ onBeforeUnmount(() => {
width: 100%; width: 100%;
height: calc(100% - 14px); height: calc(100% - 14px);
box-sizing: border-box; box-sizing: border-box;
overflow-x: hidden; // overflow-x: hidden;
position: relative;
.header { .header {
position: relative; position: relative;
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
margin-bottom: 16px; margin-bottom: 16px;
.select-container { .select-container {
position: absolute; position: absolute;
left: 0; left: 0;
...@@ -498,13 +555,13 @@ onBeforeUnmount(() => { ...@@ -498,13 +555,13 @@ onBeforeUnmount(() => {
display: flex; display: flex;
align-items: center; align-items: center;
z-index: 99; z-index: 99;
span { span {
display: block; display: block;
width: 110px; width: 110px;
margin-right: 10px; margin-right: 10px;
} }
.device-number { .device-number {
background: #fcf0c2; background: #fcf0c2;
padding: 2px 8px; padding: 2px 8px;
...@@ -512,14 +569,14 @@ onBeforeUnmount(() => { ...@@ -512,14 +569,14 @@ onBeforeUnmount(() => {
border-radius: 6px; border-radius: 6px;
} }
} }
.title { .title {
font-size: 18px; font-size: 18px;
font-weight: bold; font-weight: bold;
color: #409EFF; color: #409eff;
} }
} }
.chart-container { .chart-container {
width: 100%; width: 100%;
height: calc(100% - 350px); height: calc(100% - 350px);
...@@ -527,7 +584,8 @@ onBeforeUnmount(() => { ...@@ -527,7 +584,8 @@ onBeforeUnmount(() => {
border-radius: 4px; border-radius: 4px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative;
.chart-wrapper { .chart-wrapper {
flex: 1; flex: 1;
width: 100%; width: 100%;
...@@ -543,101 +601,110 @@ onBeforeUnmount(() => { ...@@ -543,101 +601,110 @@ onBeforeUnmount(() => {
border-radius: 4px; border-radius: 4px;
} }
} }
.no-data {
.data-panel {
position: absolute; position: absolute;
top: 110px; top: 0;
right: 25px; left: 0;
width: 320px; width: 100%;
height: 100%;
z-index: 10; z-index: 10;
transition: transform 0.3s ease-in-out; }
}
&.collapsed {
transform: translateX(345px); .data-panel {
} position: absolute;
top: 0px;
.panel-toggle { right: 0px;
position: absolute; width: 320px;
width: 25px; z-index: 100;
height: 30px; transition: transform 0.3s ease-in-out;
background: #fff;
top: 1px; &.collapsed {
transform: translateX(345px);
}
.panel-toggle {
position: absolute;
width: 25px;
height: 30px;
background: #fff;
top: 1px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
border-radius: 4px;
}
.collapsed-icon {
left: -23px;
}
.expanded-icon {
right: -23px;
}
.data-box {
padding: 10px;
background-color: rgba(255, 255, 255, 0.9);
border-radius: 4px;
border: 1px solid #ebeef5;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
margin-bottom: 10px;
.data-item {
display: flex; display: flex;
align-items: center; justify-content: space-between;
justify-content: center; margin-bottom: 5px;
cursor: pointer; font-size: 14px;
border-radius: 4px;
}
.collapsed-icon { div {
left: -23px; flex: 1;
}
.expanded-icon {
right: -23px;
}
.data-box {
padding: 10px;
background-color: rgba(255, 255, 255, 0.9);
border-radius: 4px;
border: 1px solid #ebeef5;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
margin-bottom: 10px;
.data-item {
display: flex;
justify-content: space-between;
margin-bottom: 5px;
font-size: 14px;
div {
flex: 1;
}
} }
} }
}
.second-box {
font-size: 12px; .second-box {
} font-size: 12px;
} }
} }
.data-table { .data-table {
background-color: #fff; background-color: #fff;
border-radius: 4px; border-radius: 4px;
padding: 10px 0; padding: 10px 0;
box-sizing: border-box; box-sizing: border-box;
table { table {
width: 100%; width: 100%;
border-collapse: collapse; border-collapse: collapse;
th, td { th,
border: 1px solid #EBEEF5; td {
border: 1px solid #ebeef5;
text-align: center; text-align: center;
padding: 8px; padding: 8px;
font-size: 14px; font-size: 14px;
} }
th { th {
background-color: #F5F7FA; background-color: #f5f7fa;
color: #606266; color: #606266;
} }
.error { .error {
color: #F56C6C; color: #f56c6c;
} }
.highlight { .highlight {
background-color: #FCF8E3; background-color: #fcf8e3;
position: relative; position: relative;
&::after { &::after {
content: ""; content: "";
position: absolute; position: absolute;
width: 16px; width: 16px;
height: 16px; height: 16px;
background-color: #E6A23C; background-color: #e6a23c;
border-radius: 50%; border-radius: 50%;
top: 50%; top: 50%;
left: 50%; left: 50%;
...@@ -646,17 +713,18 @@ onBeforeUnmount(() => { ...@@ -646,17 +713,18 @@ onBeforeUnmount(() => {
} }
} }
} }
.time-controls { .time-controls {
margin-bottom: 10px; margin-bottom: 10px;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: flex-end; justify-content: flex-end;
.time-label, .time-unit { .time-label,
.time-unit {
margin: 0 5px; margin: 0 5px;
} }
.time-input { .time-input {
width: 60px; width: 60px;
} }
...@@ -664,4 +732,3 @@ onBeforeUnmount(() => { ...@@ -664,4 +732,3 @@ onBeforeUnmount(() => {
} }
} }
</style> </style>
\ No newline at end of file
...@@ -74,6 +74,7 @@ ...@@ -74,6 +74,7 @@
class="point warn" class="point warn"
v-for="item in detailObj.compartHealthList[0]" v-for="item in detailObj.compartHealthList[0]"
:key="item" :key="item"
@click="handleStatusDotClick()"
></div> ></div>
</div> </div>
<div class="part"> <div class="part">
...@@ -117,6 +118,7 @@ ...@@ -117,6 +118,7 @@
</template> </template>
<script setup> <script setup>
import { ref, reactive, onMounted, onUnmounted, watch, computed } from "vue"; import { ref, reactive, onMounted, onUnmounted, watch, computed } from "vue";
import { useRouter } from "vue-router";
import * as echarts from "echarts"; import * as echarts from "echarts";
import { getDataFun } from "@/request/method.js"; import { getDataFun } from "@/request/method.js";
import { useUsersStore } from "@/pinia/user.js"; import { useUsersStore } from "@/pinia/user.js";
...@@ -148,6 +150,7 @@ const option = { ...@@ -148,6 +150,7 @@ const option = {
}, },
], ],
}; };
const router = useRouter();
const chartInstance = reactive({}); const chartInstance = reactive({});
const chartData = reactive([{}, {}, {}]); const chartData = reactive([{}, {}, {}]);
const initChart = (instance, option, domEl) => { const initChart = (instance, option, domEl) => {
...@@ -546,6 +549,14 @@ const dusterName = computed(() => { ...@@ -546,6 +549,14 @@ const dusterName = computed(() => {
return dusterList.value.find((item) => item.dusterNo == form.dusterNo) return dusterList.value.find((item) => item.dusterNo == form.dusterNo)
?.dusterName; ?.dusterName;
}); });
const handleStatusDotClick = () => {
router.push({
path: "/bag-monitor",
query: {
dusterNo: form.dusterNo,
}
});
};
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
$borderColor: #bbbdc391; $borderColor: #bbbdc391;
......
...@@ -362,7 +362,6 @@ const handleValveNumClick = (row) => { ...@@ -362,7 +362,6 @@ const handleValveNumClick = (row) => {
}; };
const handleStatusDotClick = (row, colIndex) => { const handleStatusDotClick = (row, colIndex) => {
console.log("row", row);
router.push({ router.push({
path: "/bag-monitor", path: "/bag-monitor",
query: { query: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment