|
@@ -1,12 +1,506 @@
|
|
|
<template>
|
|
<template>
|
|
|
- 这是历史曲线
|
|
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <div class="realtimeCurve-content">
|
|
|
|
|
+ <div>
|
|
|
|
|
+ <base-search :isShowDate="true" :dateValue="date.arr" :isShowExport="false"
|
|
|
|
|
+ @on-search="search" @reset="reset"></base-search>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div v-loading="loading" :style="{ height: height }" class="echarts-content">
|
|
|
|
|
+ <div v-if="allData.length != 0 && historyItems.length != 0" ref="chartRef"></div>
|
|
|
|
|
+ <div v-if="allData.length === 0 || historyItems.length === 0" class="el-table-empty">
|
|
|
|
|
+ <el-image :src="emptybg"></el-image>
|
|
|
|
|
+ <span>当前无数据</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
|
|
+</template>
|
|
|
|
|
|
|
|
- </template>
|
|
|
|
|
-
|
|
|
|
|
- <script setup lang="ts">
|
|
|
|
|
|
|
+<script setup lang="ts">
|
|
|
|
|
+import { ref, reactive, onMounted, onUnmounted, nextTick } from 'vue';
|
|
|
|
|
+import * as echarts from 'echarts';
|
|
|
|
|
+import dayjs from 'dayjs';
|
|
|
|
|
+import emptybgUrl from '@/assets/images/empty-bg.png';
|
|
|
|
|
+import type { ECharts, EChartsOption } from 'echarts';
|
|
|
|
|
+import BizVarDictAPI, { BizVarDictTable, BizVarDictPageQuery } from '@/api/module_business/vardict';
|
|
|
|
|
+import { formatToDateTime } from "@/utils/dateUtil";
|
|
|
|
|
+// 移除MQTT相关导入
|
|
|
|
|
+const emptybg = ref(emptybgUrl)
|
|
|
|
|
|
|
|
- </script>
|
|
|
|
|
-
|
|
|
|
|
- <style lang="less" scoped>
|
|
|
|
|
|
|
+// 起重机信息
|
|
|
|
|
+const craneInfo = JSON.parse(localStorage.getItem('craneInfo') || '{}');
|
|
|
|
|
+const loading = ref(true);
|
|
|
|
|
+const height = ref('calc(100vh - 70px - 5px - 50px - 10px - 44px - 50px)')
|
|
|
|
|
+// ========== 新增:时间选择相关 ==========
|
|
|
|
|
+const timeDialogVisible = ref(false);
|
|
|
|
|
|
|
|
- </style>
|
|
|
|
|
|
|
+const date = reactive({
|
|
|
|
|
+ arr: [dayjs(dayjs().subtract(1, 'hour')).format('YYYY-MM-DD HH:mm:ss'), dayjs().format('YYYY-MM-DD HH:mm:ss')]
|
|
|
|
|
+})
|
|
|
|
|
+
|
|
|
|
|
+// 查询参数:修改created_time为数组类型(适配时间范围查询)
|
|
|
|
|
+const queryFormVarDictData = reactive<BizVarDictPageQuery>({
|
|
|
|
|
+ page_no: 1,
|
|
|
|
|
+ page_size: 1000,
|
|
|
|
|
+ crane_no: craneInfo.crane_no,
|
|
|
|
|
+ var_code: undefined,
|
|
|
|
|
+ var_name: undefined,
|
|
|
|
|
+ mec_type: undefined,
|
|
|
|
|
+ switch_type: undefined,
|
|
|
|
|
+ gateway_id: undefined,
|
|
|
|
|
+ var_group: undefined,
|
|
|
|
|
+ var_category: undefined,
|
|
|
|
|
+ is_top_show: undefined,
|
|
|
|
|
+ is_save: undefined,
|
|
|
|
|
+ is_overview_top_show: undefined,
|
|
|
|
|
+ is_home_page_show: undefined,
|
|
|
|
|
+ status: undefined,
|
|
|
|
|
+ created_time: undefined,
|
|
|
|
|
+ updated_time: undefined,
|
|
|
|
|
+ created_id: undefined,
|
|
|
|
|
+ updated_id: undefined,
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+// 变量数据存储
|
|
|
|
|
+const allData = ref<BizVarDictTable[]>([]);
|
|
|
|
|
+const historyItems = ref<any[]>([]);
|
|
|
|
|
+
|
|
|
|
|
+// ========== ECharts核心配置(样式不变) ==========
|
|
|
|
|
+const chartRef = ref<HTMLDivElement | null>(null);
|
|
|
|
|
+let chartInstance: ECharts | null = null;
|
|
|
|
|
+const gridHeight = 150; // 每组Grid高度(px)
|
|
|
|
|
+const gridGap = 50; // 组间间距
|
|
|
|
|
+const gridTopBase = 80; // 顶部基础间距
|
|
|
|
|
+
|
|
|
|
|
+// 单条曲线数据结构
|
|
|
|
|
+interface SeriesDataItem {
|
|
|
|
|
+ name: string; // 变量名(var_name)
|
|
|
|
|
+ code: string; // 变量编码
|
|
|
|
|
+ data: [number, number][]; // 时间戳+值
|
|
|
|
|
+}
|
|
|
|
|
+const seriesData = ref<SeriesDataItem[]>([]);
|
|
|
|
|
+
|
|
|
|
|
+const search = (v:any) => {
|
|
|
|
|
+ date.arr = v.dateValue
|
|
|
|
|
+ getData();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+const reset = () => {
|
|
|
|
|
+ date.arr = [dayjs(dayjs().subtract(1, 'hour')).format('YYYY-MM-DD HH:mm:ss'), dayjs().format('YYYY-MM-DD HH:mm:ss')]
|
|
|
|
|
+ getData();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+// ========== 数据加载:先加载变量列表,再加载历史数据 ==========
|
|
|
|
|
+const getData = async () => {
|
|
|
|
|
+ loading.value = true;
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 1. 加载变量列表(原有逻辑不变)
|
|
|
|
|
+ const varResponse = await BizVarDictAPI.listBizVarDictAnalog(queryFormVarDictData);
|
|
|
|
|
+ allData.value = varResponse.data.data || [];
|
|
|
|
|
+
|
|
|
|
|
+ if (allData.value.length === 0) {
|
|
|
|
|
+ loading.value = false;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 初始化曲线结构
|
|
|
|
|
+ initMultiGridSeries();
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 加载历史数据
|
|
|
|
|
+ await loadHistoryData();
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('数据加载失败:', error);
|
|
|
|
|
+ loading.value = false;
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// ========== 加载历史数据(核心改造) ==========
|
|
|
|
|
+const loadHistoryData = async () => {
|
|
|
|
|
+ if (allData.value.length === 0) return;
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ // 请求历史数据接口
|
|
|
|
|
+ queryFormVarDictData.created_time = [formatToDateTime(date.arr[0]), formatToDateTime(date.arr[1])]
|
|
|
|
|
+ const historyResponse = await BizVarDictAPI.historyData(queryFormVarDictData);
|
|
|
|
|
+ historyItems.value = historyResponse.data.data.items || [];
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化所有变量的历史数据为空
|
|
|
|
|
+ seriesData.value.forEach(item => {
|
|
|
|
|
+ item.data = [];
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 遍历历史数据,按var_code匹配填充
|
|
|
|
|
+ historyItems.value.forEach((item: any) => {
|
|
|
|
|
+ const { var_name, var_code, val, ts } = item;
|
|
|
|
|
+ if (!var_code || ts === undefined || val === undefined) return;
|
|
|
|
|
+
|
|
|
|
|
+ const targetSeries = seriesData.value.find(series => series.code === var_code);
|
|
|
|
|
+ if (targetSeries) {
|
|
|
|
|
+ const timeStamp = dayjs(ts).valueOf();
|
|
|
|
|
+ targetSeries.data.push([timeStamp, Number(val)]);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化ECharts并渲染
|
|
|
|
|
+ nextTick(() => {
|
|
|
|
|
+ initEchartsWithMultiGrid();
|
|
|
|
|
+ });
|
|
|
|
|
+ } catch (error) {
|
|
|
|
|
+ console.error('历史数据加载失败:', error);
|
|
|
|
|
+ } finally {
|
|
|
|
|
+ loading.value = false;
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// ========== 多Grid初始化(样式逻辑不变) ==========
|
|
|
|
|
+const initMultiGridSeries = () => {
|
|
|
|
|
+ if (allData.value.length === 0) {
|
|
|
|
|
+ console.warn('无变量数据,无法生成曲线');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 为每个变量初始化曲线数据结构
|
|
|
|
|
+ seriesData.value = allData.value.map(item => ({
|
|
|
|
|
+ name: item.var_name || '未知变量',
|
|
|
|
|
+ code: item.var_code || '',
|
|
|
|
|
+ data: [],
|
|
|
|
|
+ }));
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// ========== ECharts初始化(样式逻辑不变,移除MQTT相关) ==========
|
|
|
|
|
+const initEchartsWithMultiGrid = () => {
|
|
|
|
|
+ if (!chartRef.value || !seriesData.value.length) return;
|
|
|
|
|
+
|
|
|
|
|
+ // 销毁旧实例
|
|
|
|
|
+ if (chartInstance) {
|
|
|
|
|
+ chartInstance.dispose();
|
|
|
|
|
+ chartInstance = null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 创建ECharts实例
|
|
|
|
|
+ chartInstance = echarts.init(chartRef.value);
|
|
|
|
|
+
|
|
|
|
|
+ // 计算Grid数量和总高度
|
|
|
|
|
+ const gridCount = seriesData.value.length;
|
|
|
|
|
+ const totalChartHeight = gridTopBase + gridCount * (gridHeight + gridGap);
|
|
|
|
|
+
|
|
|
|
|
+ // 1. 构建多Grid配置
|
|
|
|
|
+ const grids = seriesData.value.map((_, index) => ({
|
|
|
|
|
+ id: `grid_${index}`,
|
|
|
|
|
+ left: '0%',
|
|
|
|
|
+ right: '2%',
|
|
|
|
|
+ top: gridTopBase + index * (gridHeight + gridGap),
|
|
|
|
|
+ height: gridHeight,
|
|
|
|
|
+ width: '98%',
|
|
|
|
|
+ containLabel: true,
|
|
|
|
|
+ padding: [10, 20, 20, 20],
|
|
|
|
|
+ show: true
|
|
|
|
|
+ }));
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 构建多X轴配置
|
|
|
|
|
+ const xAxes: any[] = seriesData.value.map((_, index) => ({
|
|
|
|
|
+ gridIndex: index,
|
|
|
|
|
+ type: 'time',
|
|
|
|
|
+ show: true,
|
|
|
|
|
+ axisLabel: {
|
|
|
|
|
+ interval: 'auto',
|
|
|
|
|
+ formatter: (value: number) => dayjs(value).format('YYYY/MM/DD HH:mm:ss'),
|
|
|
|
|
+ fontSize: 12,
|
|
|
|
|
+ color: '#506388',
|
|
|
|
|
+ margin: 10
|
|
|
|
|
+ },
|
|
|
|
|
+ splitLine: { show: false },
|
|
|
|
|
+ alignTicks: true
|
|
|
|
|
+ }));
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 构建多Y轴配置
|
|
|
|
|
+ const yAxes: any[] = seriesData.value.map((item, index) => ({
|
|
|
|
|
+ gridIndex: index,
|
|
|
|
|
+ type: 'value',
|
|
|
|
|
+ show: true,
|
|
|
|
|
+ name: item.name,
|
|
|
|
|
+ nameTextStyle: {
|
|
|
|
|
+ fontSize: 14,
|
|
|
|
|
+ color: '#fff'
|
|
|
|
|
+ },
|
|
|
|
|
+ nameGap: 20,
|
|
|
|
|
+ axisLabel: {
|
|
|
|
|
+ formatter: (value: any) => `{fixedWidth|${value}}`,
|
|
|
|
|
+ rich: {
|
|
|
|
|
+ fixedWidth: {
|
|
|
|
|
+ width: 80,
|
|
|
|
|
+ textAlign: 'right',
|
|
|
|
|
+ backgroundColor: 'transparent',
|
|
|
|
|
+ fontSize: 14,
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ color: '#506388',
|
|
|
|
|
+ margin: 20,
|
|
|
|
|
+ overflow: 'hidden',
|
|
|
|
|
+ textOverflow: 'ellipsis'
|
|
|
|
|
+ },
|
|
|
|
|
+ splitLine: {
|
|
|
|
|
+ show: true,
|
|
|
|
|
+ lineStyle: {
|
|
|
|
|
+ color: '#3E5487',
|
|
|
|
|
+ width: 1
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ position: 'left'
|
|
|
|
|
+ }));
|
|
|
|
|
+
|
|
|
|
|
+ // 4. 构建多Series配置
|
|
|
|
|
+ const series: any[] = seriesData.value.map((item, index) => {
|
|
|
|
|
+ const curveColor = getColor(index);
|
|
|
|
|
+ return {
|
|
|
|
|
+ name: item.name,
|
|
|
|
|
+ type: 'line',
|
|
|
|
|
+ smooth: true,
|
|
|
|
|
+ symbol: 'none',
|
|
|
|
|
+ gridIndex: index,
|
|
|
|
|
+ xAxisIndex: index,
|
|
|
|
|
+ yAxisIndex: index,
|
|
|
|
|
+ data: item.data,
|
|
|
|
|
+ color: curveColor,
|
|
|
|
|
+ lineStyle: { color: curveColor, width: 2 },
|
|
|
|
|
+ itemStyle: { color: curveColor },
|
|
|
|
|
+ areaStyle: {
|
|
|
|
|
+ color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
|
|
|
|
+ { offset: 0, color: curveColor + 'cc' },
|
|
|
|
|
+ { offset: 1, color: curveColor + '11' }
|
|
|
|
|
+ ])
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // ECharts最终配置
|
|
|
|
|
+ const option: EChartsOption = {
|
|
|
|
|
+ alignTicks: true,
|
|
|
|
|
+ legend: {
|
|
|
|
|
+ show: true,
|
|
|
|
|
+ top: 20,
|
|
|
|
|
+ left: 'center',
|
|
|
|
|
+ data: seriesData.value.map(item => item.name),
|
|
|
|
|
+ textStyle: {
|
|
|
|
|
+ fontSize: 14,
|
|
|
|
|
+ color: '#fff'
|
|
|
|
|
+ },
|
|
|
|
|
+ itemWidth: 12,
|
|
|
|
|
+ itemHeight: 12,
|
|
|
|
|
+ padding: [0, 20],
|
|
|
|
|
+ formatter: (name) => {
|
|
|
|
|
+ return name.length > 10 ? name.substring(0, 10) + '...' : name;
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ tooltip: {
|
|
|
|
|
+ trigger: 'axis',
|
|
|
|
|
+ triggerOn: 'mousemove',
|
|
|
|
|
+ formatter: function (params: any) {
|
|
|
|
|
+ if (!params || params.length === 0) return '';
|
|
|
|
|
+
|
|
|
|
|
+ const targetTime = params[0].data[0];
|
|
|
|
|
+ const timeStr = formatToDateTime(targetTime);
|
|
|
|
|
+ let tooltipHtml = `<div style="font-weight: bold; margin-bottom: 8px;font-size: 12px">时间:${timeStr}</div>`;
|
|
|
|
|
+
|
|
|
|
|
+ seriesData.value.forEach((seriesItem, idx) => {
|
|
|
|
|
+ const closestData = seriesItem.data.find(d => d[0] === targetTime);
|
|
|
|
|
+ const value = closestData ? closestData[1] : '-';
|
|
|
|
|
+ tooltipHtml += `
|
|
|
|
|
+ <div style="display: flex; align-items: center; margin: 4px 0;">
|
|
|
|
|
+ <span style="display: inline-block; width: 8px; height: 8px; background: ${getColor(idx)}; margin-right: 8px; border-radius: 50%;"></span>
|
|
|
|
|
+ <span style="font-size: 12px" >${seriesItem.name}:</span>
|
|
|
|
|
+ <span style="margin-left: 8px;font-size: 12px">${value}</span>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ `;
|
|
|
|
|
+ });
|
|
|
|
|
+ return tooltipHtml;
|
|
|
|
|
+ },
|
|
|
|
|
+ backgroundColor: 'rgba(255,255,255,0.95)',
|
|
|
|
|
+ borderColor: '#e6e6e6',
|
|
|
|
|
+ borderWidth: 1,
|
|
|
|
|
+ padding: 12,
|
|
|
|
|
+ textStyle: { fontSize: 12 },
|
|
|
|
|
+ },
|
|
|
|
|
+ height: totalChartHeight,
|
|
|
|
|
+ grid: grids,
|
|
|
|
|
+ xAxis: xAxes,
|
|
|
|
|
+ yAxis: yAxes,
|
|
|
|
|
+ series: series,
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ chartInstance.setOption(option);
|
|
|
|
|
+
|
|
|
|
|
+ // 图例勾选事件(原有逻辑保留)
|
|
|
|
|
+ chartInstance.off('legendselectchanged');
|
|
|
|
|
+ chartInstance.on('legendselectchanged', (params: any) => {
|
|
|
|
|
+ if (!params || !params.selected) return;
|
|
|
|
|
+
|
|
|
|
|
+ const selectedLegend = params.selected;
|
|
|
|
|
+ const showSeriesNames = Object.entries(selectedLegend)
|
|
|
|
|
+ .filter(([_, isSelected]) => isSelected)
|
|
|
|
|
+ .map(([name]) => name);
|
|
|
|
|
+ const showIndices = seriesData.value
|
|
|
|
|
+ .map((item, index) => ({ name: item.name, index }))
|
|
|
|
|
+ .filter((item) => showSeriesNames.includes(item.name))
|
|
|
|
|
+ .map((item) => item.index);
|
|
|
|
|
+
|
|
|
|
|
+ const updatedGrids = grids.map((grid, index) => {
|
|
|
|
|
+ const seriesName = seriesData.value[index].name;
|
|
|
|
|
+ const isShow = selectedLegend[seriesName] || false;
|
|
|
|
|
+
|
|
|
|
|
+ if (!isShow) {
|
|
|
|
|
+ return { ...grid, show: false };
|
|
|
|
|
+ } else {
|
|
|
|
|
+ const showSortIndex = showIndices.findIndex(showIndex => showIndex === index);
|
|
|
|
|
+ const newTop = gridTopBase + showSortIndex * (gridHeight + gridGap);
|
|
|
|
|
+ return { ...grid, show: true, top: newTop };
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const updatedXAxes = xAxes.map((xAxis, index) => {
|
|
|
|
|
+ const seriesName = seriesData.value[index].name;
|
|
|
|
|
+ return {
|
|
|
|
|
+ ...xAxis,
|
|
|
|
|
+ show: selectedLegend[seriesName] || false,
|
|
|
|
|
+ axisLine: { onZero: false },
|
|
|
|
|
+ scale: false
|
|
|
|
|
+ };
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const updatedYAxes = yAxes.map((yAxis, index) => {
|
|
|
|
|
+ const seriesName = seriesData.value[index].name;
|
|
|
|
|
+ return { ...yAxis, show: selectedLegend[seriesName] || false };
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ const showGridCount = showIndices.length;
|
|
|
|
|
+ const newTotalChartHeight = gridTopBase + showGridCount * (gridHeight + gridGap);
|
|
|
|
|
+
|
|
|
|
|
+ chartInstance?.setOption({
|
|
|
|
|
+ grid: updatedGrids,
|
|
|
|
|
+ xAxis: updatedXAxes,
|
|
|
|
|
+ yAxis: updatedYAxes,
|
|
|
|
|
+ height: newTotalChartHeight
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ chartInstance?.resize({
|
|
|
|
|
+ width: 'auto',
|
|
|
|
|
+ height: newTotalChartHeight
|
|
|
|
|
+ });
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 调整图表尺寸
|
|
|
|
|
+ chartInstance.resize({
|
|
|
|
|
+ width: 'auto',
|
|
|
|
|
+ height: totalChartHeight,
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 窗口自适应
|
|
|
|
|
+ const resizeHandler = () => {
|
|
|
|
|
+ if (chartInstance) {
|
|
|
|
|
+ chartInstance.resize({
|
|
|
|
|
+ width: 'auto',
|
|
|
|
|
+ height: 'auto',
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+ window.addEventListener('resize', resizeHandler);
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// ========== 新增:时间选择弹窗逻辑 ==========
|
|
|
|
|
+// 打开时间选择弹窗
|
|
|
|
|
+const openTimeDialog = () => {
|
|
|
|
|
+ timeDialogVisible.value = true;
|
|
|
|
|
+ // 弹窗打开时重置为当前选中的时间范围
|
|
|
|
|
+ if(queryFormVarDictData.created_time){
|
|
|
|
|
+ date.arr = queryFormVarDictData.created_time;
|
|
|
|
|
+ }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// 确认时间选择并查询
|
|
|
|
|
+const handleTimeConfirm = () => {
|
|
|
|
|
+ if (!date.arr || date.arr.length !== 2) {
|
|
|
|
|
+ ElMessage.warning('请选择有效的时间范围');
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 更新查询参数的时间范围
|
|
|
|
|
+ queryFormVarDictData.created_time = date.arr;
|
|
|
|
|
+ // 重新加载数据
|
|
|
|
|
+ getData();
|
|
|
|
|
+ // 关闭弹窗
|
|
|
|
|
+ timeDialogVisible.value = false;
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// ========== 颜色生成函数(原有逻辑保留) ==========
|
|
|
|
|
+const getColor = (index: number) => {
|
|
|
|
|
+ const extendedColors = [
|
|
|
|
|
+ '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FECA57',
|
|
|
|
|
+ '#FF9FF3', '#54A0FF', '#8E44AD', '#E74C3C', '#3498DB',
|
|
|
|
|
+ '#2ECC71', '#F1C40F', '#9B59B6', '#1ABC9C', '#E67E22',
|
|
|
|
|
+ '#34495E', '#FF7675', '#74B9FF', '#00B894', '#FDCB6E'
|
|
|
|
|
+ ];
|
|
|
|
|
+ return extendedColors[index % extendedColors.length];
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+// ========== 生命周期(移除MQTT相关) ==========
|
|
|
|
|
+onMounted(async () => {
|
|
|
|
|
+ await getData();
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+onUnmounted(() => {
|
|
|
|
|
+ // 销毁ECharts实例
|
|
|
|
|
+ if (chartInstance) {
|
|
|
|
|
+ chartInstance.dispose();
|
|
|
|
|
+ chartInstance = null;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 移除resize监听
|
|
|
|
|
+ window.removeEventListener('resize', () => chartInstance?.resize());
|
|
|
|
|
+});
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+</script>
|
|
|
|
|
+
|
|
|
|
|
+<style lang="less" scoped>
|
|
|
|
|
+.realtimeCurve-content {
|
|
|
|
|
+ :deep(.el-loading-parent--relative) {
|
|
|
|
|
+ --el-mask-color: rgba(255, 255, 255, 0.1);
|
|
|
|
|
+ }
|
|
|
|
|
+ padding: 20px;
|
|
|
|
|
+ background: linear-gradient(to bottom, rgba(20, 66, 140, 0.8) 0%, rgba(18, 31, 52, 1) 15%);
|
|
|
|
|
+ border: 2px solid rgba(40, 73, 136, 1);
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.echarts-content {
|
|
|
|
|
+ overflow-x: hidden;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+.el-table-empty {
|
|
|
|
|
+ width: 100%;
|
|
|
|
|
+ height: 100%;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ flex-direction: column;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ color: #8ECAFF;
|
|
|
|
|
+
|
|
|
|
|
+ img {
|
|
|
|
|
+ width: 200px;
|
|
|
|
|
+ height: auto;
|
|
|
|
|
+ margin-bottom: 20px;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+::-webkit-scrollbar {
|
|
|
|
|
+ width: 5px;
|
|
|
|
|
+ height: 5px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+::-webkit-scrollbar-track {
|
|
|
|
|
+ border-radius: 10px;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+::-webkit-scrollbar-thumb {
|
|
|
|
|
+ border-radius: 7px;
|
|
|
|
|
+ background-color: #798DAE;
|
|
|
|
|
+}
|
|
|
|
|
+</style>
|