|
|
@@ -0,0 +1,1268 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+ <!-- 头部操作区域 -->
|
|
|
+ <el-card style="margin-bottom: 15px;">
|
|
|
+ <el-row :gutter="15" align="middle">
|
|
|
+ <!-- 时间选择 -->
|
|
|
+ <el-col :span="8">
|
|
|
+ <div style="display: flex; align-items: center; justify-content: center;">
|
|
|
+ <el-button icon="ArrowLeft" @click="navigateDay(-1)" size="small" style="margin-right: 10px;"></el-button>
|
|
|
+ <el-date-picker clearable
|
|
|
+ v-model="queryParams.dataDate"
|
|
|
+ type="date"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ placeholder="请选择日期"
|
|
|
+ style="width: 120px"
|
|
|
+ size="small"
|
|
|
+ @change="handleQuery">
|
|
|
+ </el-date-picker>
|
|
|
+ <el-button icon="ArrowRight" @click="navigateDay(1)" size="small" style="margin-left: 10px;"></el-button>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 设备类型和参数选择 -->
|
|
|
+ <el-col :span="10">
|
|
|
+ <div style="display: flex; align-items: center; flex-wrap: nowrap; gap: 10px;">
|
|
|
+ <span style="white-space: nowrap;">设备类型:</span>
|
|
|
+ <el-select v-model="selectedEquipmentType" placeholder="设备类型" size="small" @change="handleEquipmentTypeChange" clearable style="flex: 1; min-width: 100px;">
|
|
|
+ <el-option
|
|
|
+ v-for="item in equipmentTypeOptions"
|
|
|
+ :key="item.typeId"
|
|
|
+ :label="item.typeName"
|
|
|
+ :value="item.typeId">
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+
|
|
|
+ <span style="white-space: nowrap; margin-left: 10px;">参数:</span>
|
|
|
+ <el-select v-model="selectedEquipmentParam" placeholder="设备参数" size="small" @change="handleEquipmentParamChange" clearable style="flex: 1; min-width: 100px;">
|
|
|
+ <el-option
|
|
|
+ v-for="item in equipmentParamOptions"
|
|
|
+ :key="item.paraCode"
|
|
|
+ :label="item.paraName"
|
|
|
+ :value="item.paraCode">
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 产线选择 -->
|
|
|
+ <el-col :span="6">
|
|
|
+ <div style="display: flex; align-items: center;">
|
|
|
+ <span style="white-space: nowrap; margin-right: 10px;">产线:</span>
|
|
|
+ <el-select
|
|
|
+ v-model="selectedLines"
|
|
|
+ multiple
|
|
|
+ collapse-tags
|
|
|
+ collapse-tags-tooltip
|
|
|
+ placeholder="请选择产线"
|
|
|
+ size="small"
|
|
|
+ @change="handleLineSelectionChange"
|
|
|
+ style="flex: 1;">
|
|
|
+ <el-option
|
|
|
+ v-for="line in allLines"
|
|
|
+ :key="line"
|
|
|
+ :label="line + '#产线'"
|
|
|
+ :value="line">
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-card>
|
|
|
+
|
|
|
+ <!-- 产线和设备选择详情区域 -->
|
|
|
+ <el-card style="margin-bottom: 15px;" v-if="selectedLines.length > 0">
|
|
|
+ <!-- 同产线设备对比(选择一条产线时) -->
|
|
|
+ <div v-if="selectedLines.length === 1" style="display: flex; align-items: center; flex-wrap: wrap; gap: 15px; padding: 10px;">
|
|
|
+ <span style="font-weight: bold;">同产线设备对比:</span>
|
|
|
+ <span>{{ selectedLines[0] }}#产线</span>
|
|
|
+ <el-select
|
|
|
+ v-model="selectedMetrics[selectedLines[0] + '_0']"
|
|
|
+ placeholder="设备1"
|
|
|
+ size="small"
|
|
|
+ @change="updateQueryData"
|
|
|
+ style="width: 180px;"
|
|
|
+ clearable>
|
|
|
+ <el-option
|
|
|
+ v-for="item in equipmentList[selectedLines[0]]"
|
|
|
+ :key="item.id"
|
|
|
+ :label="item.name"
|
|
|
+ :value="item.id">
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ <span>VS</span>
|
|
|
+ <el-select
|
|
|
+ v-model="selectedMetrics[selectedLines[0] + '_1']"
|
|
|
+ placeholder="设备2"
|
|
|
+ size="small"
|
|
|
+ @change="updateQueryData"
|
|
|
+ style="width: 180px;"
|
|
|
+ clearable>
|
|
|
+ <el-option
|
|
|
+ v-for="item in equipmentList[selectedLines[0]]"
|
|
|
+ :key="item.id"
|
|
|
+ :label="item.name"
|
|
|
+ :value="item.id">
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 跨产线设备对比(选择两条产线时) -->
|
|
|
+ <div v-if="selectedLines.length === 2" style="display: flex; align-items: center; flex-wrap: wrap; gap: 15px; padding: 10px;">
|
|
|
+ <template v-for="(line, index) in selectedLines" :key="line">
|
|
|
+ <div v-if="index > 0" style="width: 1px; height: 24px; background-color: #dcdfe6; margin: 0 10px;"></div>
|
|
|
+ <span style="font-weight: bold;">{{ index === 0 ? '产线A' : '产线B' }}:</span>
|
|
|
+ <span>{{ line }}#产线</span>
|
|
|
+ <el-select
|
|
|
+ v-model="selectedMetrics[line]"
|
|
|
+ placeholder="请选择设备"
|
|
|
+ size="small"
|
|
|
+ @change="updateQueryData"
|
|
|
+ style="width: 180px;"
|
|
|
+ clearable>
|
|
|
+ <el-option
|
|
|
+ v-for="item in equipmentList[line]"
|
|
|
+ :key="item.id"
|
|
|
+ :label="item.name"
|
|
|
+ :value="item.id">
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </template>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+
|
|
|
+ <!-- 折线图和表格左右布局 -->
|
|
|
+ <el-row :gutter="15">
|
|
|
+ <!-- 左侧折线图 -->
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-card style="margin-bottom: 15px;">
|
|
|
+ <div ref="chartRef0" style="width: 100%; height: 400px;"></div>
|
|
|
+ </el-card>
|
|
|
+ <el-card style="margin-bottom: 15px;">
|
|
|
+ <el-table :data="rzLineList" height="400" :span-method="spanMethod">
|
|
|
+ <el-table-column label="小时" align="center" prop="hour" width="60" />
|
|
|
+ <el-table-column label="设备" align="center" prop="deviceName" width="360" />
|
|
|
+ <el-table-column :label="rzLineList.length>0 ? rzLineList[0].paraName : ''" align="center" >
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.paraValue }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 右侧表格 -->
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-card style="margin-bottom: 15px;">
|
|
|
+ <div ref="chartRef1" style="width: 100%; height: 400px;"></div>
|
|
|
+ </el-card>
|
|
|
+ <el-card style="margin-bottom: 15px;">
|
|
|
+ <el-table :data="rzLineList1" height="400" :span-method="spanMethod">
|
|
|
+ <el-table-column label="小时" align="center" prop="hour" width="60" />
|
|
|
+ <el-table-column label="设备" align="center" prop="deviceName" width="360" />
|
|
|
+ <el-table-column :label="rzLineList.length>0 ? rzLineList[0].paraName : ''" align="center" >
|
|
|
+ <template #default="scope">
|
|
|
+ {{ scope.row.paraValue }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 分钟级数据弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ :title="minuteDialogTitle"
|
|
|
+ v-model="minuteDialogVisible"
|
|
|
+ width="80%"
|
|
|
+ :before-close="handleMinuteDialogClose"
|
|
|
+ append-to-body
|
|
|
+ >
|
|
|
+ <el-row :gutter="15">
|
|
|
+ <!-- 左侧分钟级折线图 -->
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-card style="margin-bottom: 15px;">
|
|
|
+ <div ref="minuteChartRef0" style="width: 100%; height: 400px;"></div>
|
|
|
+ </el-card>
|
|
|
+ <el-card style="margin-bottom: 15px;">
|
|
|
+ <el-table :data="minuteTableData0" height="400">
|
|
|
+ <el-table-column prop="time" label="分钟" width="100" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="value" :label="minuteDataLabel0" align="center"></el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+
|
|
|
+ <!-- 右侧分钟级折线图 -->
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-card style="margin-bottom: 15px;">
|
|
|
+ <div ref="minuteChartRef1" style="width: 100%; height: 400px;"></div>
|
|
|
+ </el-card>
|
|
|
+ <el-card style="margin-bottom: 15px;">
|
|
|
+ <el-table :data="minuteTableData1" height="400">
|
|
|
+ <el-table-column prop="time" label="分钟" width="100" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="value" :label="minuteDataLabel1" align="center"></el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup name="gyfx">
|
|
|
+import * as echarts from 'echarts';
|
|
|
+import { listRzLine, getRzLine, delRzLine, addRzLine, updateRzLine } from "@/api/dyeing/rzLine";
|
|
|
+import { listDeviceTypes } from "@/api/dyeing/gyfx"; // 添加导入listDeviceTypes接口
|
|
|
+import { listDevice } from "@/api/dye/device";
|
|
|
+import {listHour} from "@/api/dye/hour.js";
|
|
|
+import { ref, nextTick } from 'vue';
|
|
|
+
|
|
|
+const { proxy } = getCurrentInstance();
|
|
|
+
|
|
|
+const rzLineList = ref([]);
|
|
|
+const rzLineList1 = ref([]);
|
|
|
+const open = ref(false);
|
|
|
+const loading = ref(true);
|
|
|
+const showSearch = ref(true);
|
|
|
+const ids = ref([]);
|
|
|
+const single = ref(true);
|
|
|
+const multiple = ref(true);
|
|
|
+const total = ref(0);
|
|
|
+const title = ref("");
|
|
|
+const chartRef0 = ref(null);
|
|
|
+const chartRef1 = ref(null);
|
|
|
+let chartInstance0 = null;
|
|
|
+let chartInstance1 = null;
|
|
|
+
|
|
|
+// 分钟级数据相关变量
|
|
|
+const minuteDialogVisible = ref(false);
|
|
|
+const minuteDialogTitle = ref('');
|
|
|
+// 左侧分钟级数据
|
|
|
+const minuteChartRef0 = ref(null);
|
|
|
+let minuteChartInstance0 = null;
|
|
|
+const minuteTableData0 = ref([]);
|
|
|
+const minuteDataLabel0 = ref('');
|
|
|
+// 右侧分钟级数据
|
|
|
+const minuteChartRef1 = ref(null);
|
|
|
+let minuteChartInstance1 = null;
|
|
|
+const minuteTableData1 = ref([]);
|
|
|
+const minuteDataLabel1 = ref('');
|
|
|
+
|
|
|
+const data = reactive({
|
|
|
+ form: {},
|
|
|
+ queryParams: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10000,
|
|
|
+ dataDate: new Date(new Date().getTime() - 24 * 60 * 60 * 1000).Format('yyyy-MM-dd'),
|
|
|
+ hour: null,
|
|
|
+ lines: null,
|
|
|
+ openRate: null,
|
|
|
+ length: null,
|
|
|
+ tmp: null,
|
|
|
+ speed: null,
|
|
|
+ energy: null,
|
|
|
+ amp: null,
|
|
|
+ createdBy: null,
|
|
|
+ createdTime: null,
|
|
|
+ updatedBy: null,
|
|
|
+ updatedTime: null,
|
|
|
+ remark: null
|
|
|
+ },
|
|
|
+ rules: {
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+const selectedEquipmentType = ref('');
|
|
|
+const selectedEquipmentParam = ref('');
|
|
|
+const selectedMetrics = ref({});
|
|
|
+const selectedLines = ref([]); // 多条产线选择
|
|
|
+const equipmentList = ref({});
|
|
|
+const equipmentTypeList = ref([]);
|
|
|
+const equipmentParamOptions = ref([]);
|
|
|
+const equipmentTypeOptions = ref([]);
|
|
|
+const allLines = ref(['1', '2', '3', '4', '5', '6', '7', '8']);
|
|
|
+const oldSelectLines = ref([]);
|
|
|
+
|
|
|
+const { queryParams, form, rules } = toRefs(data);
|
|
|
+
|
|
|
+// 按产线分组的数据
|
|
|
+const groupedRzLineList = computed(() => {
|
|
|
+ const grouped = {};
|
|
|
+ rzLineList.value.forEach(item => {
|
|
|
+ if (!grouped[item.line]) {
|
|
|
+ grouped[item.line] = [];
|
|
|
+ }
|
|
|
+ grouped[item.line].push(item);
|
|
|
+ });
|
|
|
+ // 按产线编号排序
|
|
|
+ const sortedGrouped = {};
|
|
|
+ Object.keys(grouped).sort().forEach(key => {
|
|
|
+ sortedGrouped[key] = grouped[key];
|
|
|
+ });
|
|
|
+ return sortedGrouped;
|
|
|
+});
|
|
|
+
|
|
|
+// 合并单元格处理函数
|
|
|
+const spanMethod = ({ row, column, rowIndex, columnIndex }) => {
|
|
|
+ if (columnIndex === 0) { // 小时列
|
|
|
+ // 获取当前行小时值
|
|
|
+ const currentHour = row.hour;
|
|
|
+
|
|
|
+ // 计算当前小时值第一次出现的位置
|
|
|
+ let firstIndex = -1;
|
|
|
+ for (let i = 0; i < rzLineList.value.length; i++) {
|
|
|
+ if (rzLineList.value[i].hour === currentHour) {
|
|
|
+ firstIndex = i;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果当前行是该小时值第一次出现的位置
|
|
|
+ if (firstIndex === rowIndex) {
|
|
|
+ // 计算该小时值连续出现的次数
|
|
|
+ let spanCount = 0;
|
|
|
+ for (let i = firstIndex; i < rzLineList.value.length; i++) {
|
|
|
+ if (rzLineList.value[i].hour === currentHour) {
|
|
|
+ spanCount++;
|
|
|
+ } else {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return [spanCount, 1];
|
|
|
+ } else {
|
|
|
+ // 如果不是第一次出现,隐藏该单元格
|
|
|
+ return [0, 0];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return [1, 1]; // 其他列不合并
|
|
|
+};
|
|
|
+function navigateDay(offset) {
|
|
|
+ const currentDate = new Date(queryParams.value.dataDate);
|
|
|
+ currentDate.setDate(currentDate.getDate() + offset);
|
|
|
+ queryParams.value.dataDate = currentDate.toISOString().split('T')[0];
|
|
|
+ handleQuery();
|
|
|
+}
|
|
|
+/** 查询染整线产线小时统计数据列表 */
|
|
|
+function getList() {
|
|
|
+ // 先获取设备类型列表
|
|
|
+ listDeviceTypes({pageSize: 10000}).then(response => {
|
|
|
+ equipmentTypeList.value = response.rows;
|
|
|
+ // 提取设备类型选项
|
|
|
+ equipmentTypeOptions.value = response.rows.map(item => {
|
|
|
+ return {
|
|
|
+ typeId: item.typeId,
|
|
|
+ typeName: item.typeName
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ // 默认选择第一条设备类型
|
|
|
+ if (response.rows.length > 0 && !selectedEquipmentType.value) {
|
|
|
+ selectedEquipmentType.value = response.rows[0].typeId;
|
|
|
+ // 触发设备类型变化事件,加载对应的参数
|
|
|
+ handleEquipmentTypeChange(selectedEquipmentType.value);
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function difference(arr1, arr2) {
|
|
|
+ const set2 = new Set(arr2);
|
|
|
+ return arr1.filter(item => !set2.has(item));
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取设备列表
|
|
|
+ * @returns {void}
|
|
|
+ */
|
|
|
+function getDeviceList(){
|
|
|
+ // 检查是否选择了产线
|
|
|
+ if (selectedLines.value.length === 0) {
|
|
|
+ proxy.$modal.msgWarning("请至少选择一条产线进行对比");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (selectedLines.value.length > 2) {
|
|
|
+ let tmp = difference(selectedLines.value, oldSelectLines.value);
|
|
|
+ selectedLines.value = selectedLines.value.filter(item => !tmp.includes(item));
|
|
|
+ oldSelectLines.value = JSON.parse(JSON.stringify(selectedLines.value));
|
|
|
+ proxy.$modal.msgWarning("最多只能选择两条产线进行对比");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理取消选择产线的情况
|
|
|
+ if (selectedLines.value.length < oldSelectLines.value.length) {
|
|
|
+ // 取消了一条产线
|
|
|
+ let tmp = difference(oldSelectLines.value, selectedLines.value);
|
|
|
+ // 清除取消产线的相关设备选择
|
|
|
+ if (selectedMetrics.value[tmp[0]]) {
|
|
|
+ selectedMetrics.value[tmp[0]] = '';
|
|
|
+ }
|
|
|
+ // 如果是单一产线情况,清除相关的设备选择
|
|
|
+ if (selectedMetrics.value[tmp[0] + '_0']) selectedMetrics.value[tmp[0] + '_0'] = '';
|
|
|
+ if (selectedMetrics.value[tmp[0] + '_1']) selectedMetrics.value[tmp[0] + '_1'] = '';
|
|
|
+ updateQueryData();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查是否选择了设备类型和参数
|
|
|
+ if (!selectedEquipmentType.value) {
|
|
|
+ proxy.$modal.msgError("请先选择设备类型");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!selectedEquipmentParam.value) {
|
|
|
+ proxy.$modal.msgError("请先选择设备参数");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 为所有选中的产线获取设备列表
|
|
|
+ selectedLines.value.forEach(line => {
|
|
|
+ listDevice({
|
|
|
+ pageSize: 10000,
|
|
|
+ pageNum: 1,
|
|
|
+ paraCode: selectedEquipmentParam.value,
|
|
|
+ typeId: selectedEquipmentType.value,
|
|
|
+ line: line
|
|
|
+ }).then(response => {
|
|
|
+ // 提取设备参数选项
|
|
|
+ equipmentList.value[line] = response.rows.map(item => {
|
|
|
+ return {
|
|
|
+ id: item.deviceId,
|
|
|
+ name: item.deviceName
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ // 默认选中第一台设备
|
|
|
+ let needUpdateData = false;
|
|
|
+ if (response.rows.length > 0) {
|
|
|
+ // 如果是单条产线情况,设置同产线设备对比的第一台设备
|
|
|
+ if (selectedLines.value.length === 1) {
|
|
|
+ const lineKey = selectedLines.value[0];
|
|
|
+ if (!selectedMetrics.value[lineKey + '_0']) {
|
|
|
+ selectedMetrics.value[lineKey + '_0'] = response.rows[0].deviceId;
|
|
|
+ needUpdateData = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 如果是两条产线情况,设置对应产线的第一台设备
|
|
|
+ else if (selectedLines.value.length === 2) {
|
|
|
+ if (!selectedMetrics.value[line]) {
|
|
|
+ selectedMetrics.value[line] = response.rows[0].deviceId;
|
|
|
+ needUpdateData = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果设置了默认设备,则更新数据
|
|
|
+ if (needUpdateData) {
|
|
|
+ updateQueryData();
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ oldSelectLines.value = JSON.parse(JSON.stringify(selectedLines.value));
|
|
|
+ // 如果选择了产线,更新图表
|
|
|
+ if (selectedLines.value.length >= 1 && Object.keys(selectedMetrics.value).length > 0) {
|
|
|
+ // 检查是否所有产线都已设置设备,如果是则更新数据
|
|
|
+ let allLinesHaveDevices = true;
|
|
|
+ if (selectedLines.value.length === 1) {
|
|
|
+ const lineKey = selectedLines.value[0];
|
|
|
+ if (!selectedMetrics.value[lineKey + '_0']) {
|
|
|
+ allLinesHaveDevices = false;
|
|
|
+ }
|
|
|
+ } else if (selectedLines.value.length === 2) {
|
|
|
+ for (const line of selectedLines.value) {
|
|
|
+ if (!selectedMetrics.value[line]) {
|
|
|
+ allLinesHaveDevices = false;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (allLinesHaveDevices) {
|
|
|
+ updateQueryData();
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function updateQueryData() {
|
|
|
+ initChart();
|
|
|
+ rzLineList.value = [];
|
|
|
+ rzLineList1.value = [];
|
|
|
+
|
|
|
+ let queryPara = {
|
|
|
+ paraCode: selectedEquipmentParam.value,
|
|
|
+ typeId: selectedEquipmentType.value,
|
|
|
+ dataDate: queryParams.value.dataDate,
|
|
|
+ pageSize: 10000,
|
|
|
+ pageNum: 1,
|
|
|
+ };
|
|
|
+
|
|
|
+ // 情况1:选择了一条产线,需要比较该产线下的两个设备
|
|
|
+ if (selectedLines.value.length == 1) {
|
|
|
+ const line = selectedLines.value[0];
|
|
|
+ // 检查是否选择了两个设备进行对比
|
|
|
+ if (selectedMetrics.value[line + '_0'] && selectedMetrics.value[line + '_1']) {
|
|
|
+ // 查询第一个设备的数据
|
|
|
+ queryPara['line'] = line;
|
|
|
+ queryPara['deviceId'] = selectedMetrics.value[line + '_0'];
|
|
|
+ listHour(queryPara).then(res => {
|
|
|
+ rzLineList.value = res.rows;
|
|
|
+ nextTick(() => {
|
|
|
+ updateChart();
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ // 查询第二个设备的数据
|
|
|
+ queryPara['deviceId'] = selectedMetrics.value[line + '_1'];
|
|
|
+ listHour(queryPara).then(res => {
|
|
|
+ rzLineList1.value = res.rows;
|
|
|
+ nextTick(() => {
|
|
|
+ updateChart1();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 情况2:选择了两条产线,每条产线选择一个设备进行对比
|
|
|
+ else if (selectedLines.value.length == 2) {
|
|
|
+ // 查询第一条产线设备的数据
|
|
|
+ if (selectedMetrics.value[selectedLines.value[0]]) {
|
|
|
+ queryPara['line'] = selectedLines.value[0];
|
|
|
+ queryPara['deviceId'] = selectedMetrics.value[selectedLines.value[0]];
|
|
|
+ listHour(queryPara).then(res => {
|
|
|
+ rzLineList.value = res.rows;
|
|
|
+ nextTick(() => {
|
|
|
+ updateChart();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询第二条产线设备的数据
|
|
|
+ if (selectedMetrics.value[selectedLines.value[1]]) {
|
|
|
+ queryPara['line'] = selectedLines.value[1];
|
|
|
+ queryPara['deviceId'] = selectedMetrics.value[selectedLines.value[1]];
|
|
|
+ listHour(queryPara).then(res => {
|
|
|
+ rzLineList1.value = res.rows;
|
|
|
+ nextTick(() => {
|
|
|
+ updateChart1();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 初始化图表
|
|
|
+function initChart() {
|
|
|
+ if (chartInstance0) {
|
|
|
+ chartInstance0.dispose();
|
|
|
+ }
|
|
|
+ if (chartInstance1) {
|
|
|
+ chartInstance1.dispose();
|
|
|
+ }
|
|
|
+ if (chartRef0.value) {
|
|
|
+ chartInstance0 = echarts.init(chartRef0.value);
|
|
|
+ }
|
|
|
+ if (chartRef1.value) {
|
|
|
+ chartInstance1 = echarts.init(chartRef1.value);
|
|
|
+ }
|
|
|
+ //建立图表联动
|
|
|
+ if (chartInstance0 && chartInstance1) {
|
|
|
+ echarts.connect([
|
|
|
+ chartInstance0,
|
|
|
+ chartInstance1,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 初始化分钟级数据图表
|
|
|
+function initMinuteChart0(minuteData, targetData) {
|
|
|
+ if (minuteChartInstance0) {
|
|
|
+ minuteChartInstance0.dispose();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (minuteChartRef0.value) {
|
|
|
+ minuteChartInstance0 = echarts.init(minuteChartRef0.value);
|
|
|
+
|
|
|
+ // 准备分钟级数据
|
|
|
+ const timePoints = minuteData.map(item => item.time);
|
|
|
+ const values = minuteData.map(item => item.value);
|
|
|
+
|
|
|
+ const option = {
|
|
|
+ title: {
|
|
|
+ text: targetData.deviceName + ' ' + targetData.paraName,
|
|
|
+ left: 'center'
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ formatter: function (params) {
|
|
|
+ let result = params[0].axisValue + '分<br/>';
|
|
|
+ params.forEach(param => {
|
|
|
+ let valueText = '';
|
|
|
+ valueText = param.value !== null ? param.value : '无数据';
|
|
|
+ result += `<div style="display:flex;align-items:center;">
|
|
|
+ <span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${param.color};"></span>
|
|
|
+ ${param.seriesName}: ${valueText}
|
|
|
+ </div>`;
|
|
|
+ });
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ legend:{
|
|
|
+ top: 40 ,
|
|
|
+ left: 'center',
|
|
|
+ textStyle: {
|
|
|
+ fontSize: 10
|
|
|
+ },
|
|
|
+ itemWidth: 10,
|
|
|
+ itemHeight: 10
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '3%',
|
|
|
+ right: '4%',
|
|
|
+ top: '25%',
|
|
|
+ bottom: 20,
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ boundaryGap: false,
|
|
|
+ data: timePoints
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ name: targetData.paraName
|
|
|
+ },
|
|
|
+ series: [{
|
|
|
+ name: targetData.deviceName + '-' + targetData.paraName,
|
|
|
+ type: 'line',
|
|
|
+ data: values,
|
|
|
+ smooth: true,
|
|
|
+ showSymbol: false
|
|
|
+ }]
|
|
|
+ };
|
|
|
+
|
|
|
+ minuteChartInstance0.setOption(option);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 初始化分钟级数据图表1
|
|
|
+function initMinuteChart1(minuteData, targetData) {
|
|
|
+ if (minuteChartInstance1) {
|
|
|
+ minuteChartInstance1.dispose();
|
|
|
+ }
|
|
|
+
|
|
|
+ if (minuteChartRef1.value) {
|
|
|
+ minuteChartInstance1 = echarts.init(minuteChartRef1.value);
|
|
|
+
|
|
|
+ // 准备分钟级数据
|
|
|
+ const timePoints = minuteData.map(item => item.time);
|
|
|
+ const values = minuteData.map(item => item.value);
|
|
|
+
|
|
|
+ const option = {
|
|
|
+ title: {
|
|
|
+ text: targetData.deviceName + ' ' + targetData.paraName,
|
|
|
+ left: 'center'
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ formatter: function (params) {
|
|
|
+ let result = params[0].axisValue + '分<br/>';
|
|
|
+ params.forEach(param => {
|
|
|
+ let valueText = '';
|
|
|
+ valueText = param.value !== null ? param.value : '无数据';
|
|
|
+ result += `<div style="display:flex;align-items:center;">
|
|
|
+ <span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${param.color};"></span>
|
|
|
+ ${param.seriesName}: ${valueText}
|
|
|
+ </div>`;
|
|
|
+ });
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ legend:{
|
|
|
+ top: 40 ,
|
|
|
+ left: 'center',
|
|
|
+ textStyle: {
|
|
|
+ fontSize: 10
|
|
|
+ },
|
|
|
+ itemWidth: 10,
|
|
|
+ itemHeight: 10
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '3%',
|
|
|
+ right: '4%',
|
|
|
+ top: '25%',
|
|
|
+ bottom: 20,
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ boundaryGap: false,
|
|
|
+ data: timePoints
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ name: targetData.paraName
|
|
|
+ },
|
|
|
+ series: [{
|
|
|
+ name: targetData.deviceName + '-' + targetData.paraName,
|
|
|
+ type: 'line',
|
|
|
+ data: values,
|
|
|
+ smooth: true,
|
|
|
+ showSymbol: false
|
|
|
+ }]
|
|
|
+ };
|
|
|
+
|
|
|
+ minuteChartInstance1.setOption(option);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 更新图表0
|
|
|
+function updateChart() {
|
|
|
+ if (chartInstance0 && rzLineList.value.length > 0) {
|
|
|
+ const hours = rzLineList.value.map(item => item.hour.toString().padStart(2, '0') + ':00');
|
|
|
+ const values = rzLineList.value.map(item => item.paraValue);
|
|
|
+
|
|
|
+ const option = {
|
|
|
+ title: {
|
|
|
+ text: rzLineList.value[0].deviceName + ' ' + rzLineList.value[0].paraName,
|
|
|
+ left: 'center'
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ formatter: function (params) {
|
|
|
+ let result = params[0].axisValue + '<br/>';
|
|
|
+ params.forEach(param => {
|
|
|
+ let valueText = '';
|
|
|
+ valueText = param.value !== null ? param.value : '无数据';
|
|
|
+ result += `<div style="display:flex;align-items:center;">
|
|
|
+ <span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${param.color};"></span>
|
|
|
+ ${param.seriesName}: ${valueText}
|
|
|
+ </div>`;
|
|
|
+ });
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ legend:{
|
|
|
+ top: 40 ,
|
|
|
+ left: 'center',
|
|
|
+ textStyle: {
|
|
|
+ fontSize: 10
|
|
|
+ },
|
|
|
+ itemWidth: 10,
|
|
|
+ itemHeight: 10
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '3%',
|
|
|
+ right: '4%',
|
|
|
+ top: '25%',
|
|
|
+ bottom: 20,
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ boundaryGap: false,
|
|
|
+ data: hours
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ name: rzLineList.value[0].paraName
|
|
|
+ },
|
|
|
+ series: [{
|
|
|
+ name: rzLineList.value[0].deviceName,
|
|
|
+ type: 'line',
|
|
|
+ data: values,
|
|
|
+ smooth: true,
|
|
|
+ showSymbol: false
|
|
|
+ }]
|
|
|
+ };
|
|
|
+
|
|
|
+ chartInstance0.setOption(option);
|
|
|
+
|
|
|
+ // 先移除之前的点击事件监听,避免重复绑定
|
|
|
+ chartInstance0.off('click');
|
|
|
+ // 添加点击事件监听
|
|
|
+ chartInstance0.on('click', (params) => {
|
|
|
+ handleChartClick(params, 'chart0');
|
|
|
+ });
|
|
|
+ } else if (chartInstance0) {
|
|
|
+ // 如果没有数据,清空图表
|
|
|
+ chartInstance0.setOption({
|
|
|
+ title: {
|
|
|
+ text: '暂无数据',
|
|
|
+ left: 'center',
|
|
|
+ top: 'center'
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: []
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value'
|
|
|
+ },
|
|
|
+ series: []
|
|
|
+ });
|
|
|
+
|
|
|
+ // 移除点击事件监听
|
|
|
+ chartInstance0.off('click');
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 更新图表1
|
|
|
+function updateChart1() {
|
|
|
+ if (chartInstance1 && rzLineList1.value.length > 0) {
|
|
|
+ const hours = rzLineList1.value.map(item => item.hour.toString().padStart(2, '0') + ':00');
|
|
|
+ const values = rzLineList1.value.map(item => item.paraValue);
|
|
|
+
|
|
|
+ const option = {
|
|
|
+ title: {
|
|
|
+ text: rzLineList1.value[0].deviceName + ' ' + rzLineList1.value[0].paraName,
|
|
|
+ left: 'center'
|
|
|
+ },
|
|
|
+ tooltip: {
|
|
|
+ trigger: 'axis',
|
|
|
+ formatter: function (params) {
|
|
|
+ let result = params[0].axisValue + '<br/>';
|
|
|
+ params.forEach(param => {
|
|
|
+ let valueText = '';
|
|
|
+ valueText = param.value !== null ? param.value : '无数据';
|
|
|
+ result += `<div style="display:flex;align-items:center;">
|
|
|
+ <span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${param.color};"></span>
|
|
|
+ ${param.seriesName}: ${valueText}
|
|
|
+ </div>`;
|
|
|
+ });
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ legend:{
|
|
|
+ top: 40 ,
|
|
|
+ left: 'center',
|
|
|
+ textStyle: {
|
|
|
+ fontSize: 10
|
|
|
+ },
|
|
|
+ itemWidth: 10,
|
|
|
+ itemHeight: 10
|
|
|
+ },
|
|
|
+ grid: {
|
|
|
+ left: '3%',
|
|
|
+ right: '4%',
|
|
|
+ top: '25%',
|
|
|
+ bottom: 20,
|
|
|
+ containLabel: true
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ boundaryGap: false,
|
|
|
+ data: hours
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ name: rzLineList1.value[0].paraName
|
|
|
+ },
|
|
|
+ series: [{
|
|
|
+ name: rzLineList1.value[0].deviceName,
|
|
|
+ type: 'line',
|
|
|
+ data: values,
|
|
|
+ smooth: true,
|
|
|
+ showSymbol: false
|
|
|
+ }]
|
|
|
+ };
|
|
|
+
|
|
|
+ chartInstance1.setOption(option);
|
|
|
+
|
|
|
+ // 先移除之前的点击事件监听,避免重复绑定
|
|
|
+ chartInstance1.off('click');
|
|
|
+ // 添加点击事件监听
|
|
|
+ chartInstance1.on('click', (params) => {
|
|
|
+ handleChartClick(params, 'chart1');
|
|
|
+ });
|
|
|
+ } else if (chartInstance1) {
|
|
|
+ // 如果没有数据,清空图表
|
|
|
+ chartInstance1.setOption({
|
|
|
+ title: {
|
|
|
+ text: '暂无数据',
|
|
|
+ left: 'center',
|
|
|
+ top: 'center'
|
|
|
+ },
|
|
|
+ xAxis: {
|
|
|
+ type: 'category',
|
|
|
+ data: []
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value'
|
|
|
+ },
|
|
|
+ series: []
|
|
|
+ });
|
|
|
+
|
|
|
+ // 移除点击事件监听
|
|
|
+ chartInstance1.off('click');
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 图表点击事件处理函数
|
|
|
+function handleChartClick(params, chartType) {
|
|
|
+ // 获取点击的小时
|
|
|
+ const hour = params.name;
|
|
|
+
|
|
|
+ // 查找对应小时的数据(无论点击的是哪个图表,都要显示两个设备的数据)
|
|
|
+ // 尝试多种匹配方式来查找数据
|
|
|
+ let targetData0 = null;
|
|
|
+ let targetData1 = null;
|
|
|
+
|
|
|
+ // 对于第一个数据集
|
|
|
+ for (let i = 0; i < rzLineList.value.length; i++) {
|
|
|
+ const item = rzLineList.value[i];
|
|
|
+ const itemHour = item.hour.toString().padStart(2, '0');
|
|
|
+ const clickedHour = hour.replace(':00', ''); // 去掉可能的 ':00' 后缀
|
|
|
+
|
|
|
+ if (itemHour === clickedHour) {
|
|
|
+ targetData0 = item;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 对于第二个数据集
|
|
|
+ for (let i = 0; i < rzLineList1.value.length; i++) {
|
|
|
+ const item = rzLineList1.value[i];
|
|
|
+ const itemHour = item.hour.toString().padStart(2, '0');
|
|
|
+ const clickedHour = hour.replace(':00', ''); // 去掉可能的 ':00' 后缀
|
|
|
+
|
|
|
+ if (itemHour === clickedHour) {
|
|
|
+ targetData1 = item;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查两个设备是否都有对应小时的数据
|
|
|
+ if ((targetData0 && targetData0.paraMValue) || (targetData1 && targetData1.paraMValue)) {
|
|
|
+ try {
|
|
|
+ // 设置对话框标题
|
|
|
+ minuteDialogTitle.value = `小时 ${hour} 的分钟级数据对比`;
|
|
|
+
|
|
|
+ // 处理左侧设备的分钟级数据
|
|
|
+ if (targetData0 && targetData0.paraMValue) {
|
|
|
+ let minuteData0;
|
|
|
+ try {
|
|
|
+ minuteData0 = typeof targetData0.paraMValue === 'string'
|
|
|
+ ? JSON.parse(targetData0.paraMValue)
|
|
|
+ : targetData0.paraMValue;
|
|
|
+ } catch (e) {
|
|
|
+ // 尝试其他格式
|
|
|
+ if (Array.isArray(targetData0.paraMValue)) {
|
|
|
+ minuteData0 = targetData0.paraMValue;
|
|
|
+ } else {
|
|
|
+ minuteData0 = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置左侧分钟级数据
|
|
|
+ minuteTableData0.value = minuteData0.map(item => ({
|
|
|
+ time: item.time,
|
|
|
+ value: item.value
|
|
|
+ }));
|
|
|
+ minuteDataLabel0.value = targetData0.paraName;
|
|
|
+
|
|
|
+ // 初始化左侧分钟级图表
|
|
|
+ nextTick(() => {
|
|
|
+ initMinuteChart0(minuteData0, targetData0);
|
|
|
+ // 建立分钟级图表联动
|
|
|
+ if (minuteChartInstance0 && minuteChartInstance1) {
|
|
|
+ echarts.connect([minuteChartInstance0, minuteChartInstance1]);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 如果没有数据,清空左侧内容
|
|
|
+ minuteTableData0.value = [];
|
|
|
+ minuteDataLabel0.value = '';
|
|
|
+ if (minuteChartInstance0) {
|
|
|
+ minuteChartInstance0.dispose();
|
|
|
+ minuteChartInstance0 = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 处理右侧设备的分钟级数据
|
|
|
+ if (targetData1 && targetData1.paraMValue) {
|
|
|
+ let minuteData1;
|
|
|
+ try {
|
|
|
+ minuteData1 = typeof targetData1.paraMValue === 'string'
|
|
|
+ ? JSON.parse(targetData1.paraMValue)
|
|
|
+ : targetData1.paraMValue;
|
|
|
+ } catch (e) {
|
|
|
+ // 尝试其他格式
|
|
|
+ if (Array.isArray(targetData1.paraMValue)) {
|
|
|
+ minuteData1 = targetData1.paraMValue;
|
|
|
+ } else {
|
|
|
+ minuteData1 = [];
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置右侧分钟级数据
|
|
|
+ minuteTableData1.value = minuteData1.map(item => ({
|
|
|
+ time: item.time,
|
|
|
+ value: item.value
|
|
|
+ }));
|
|
|
+ minuteDataLabel1.value = targetData1.paraName;
|
|
|
+
|
|
|
+ // 初始化右侧分钟级图表
|
|
|
+ nextTick(() => {
|
|
|
+ initMinuteChart1(minuteData1, targetData1);
|
|
|
+ // 建立分钟级图表联动
|
|
|
+ if (minuteChartInstance0 && minuteChartInstance1) {
|
|
|
+ echarts.connect([minuteChartInstance0, minuteChartInstance1]);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // 如果没有数据,清空右侧内容
|
|
|
+ minuteTableData1.value = [];
|
|
|
+ minuteDataLabel1.value = '';
|
|
|
+ if (minuteChartInstance1) {
|
|
|
+ minuteChartInstance1.dispose();
|
|
|
+ minuteChartInstance1 = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 显示对话框
|
|
|
+ showMinuteDialog();
|
|
|
+ } catch (error) {
|
|
|
+ proxy.$modal.msgError("数据解析失败");
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 显示提示信息
|
|
|
+ proxy.$modal.msgWarning("该小时没有分钟级数据");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 窗口大小改变时重置图表大小
|
|
|
+function resizeChart() {
|
|
|
+ if (chartInstance0) {
|
|
|
+ chartInstance0.resize();
|
|
|
+ }
|
|
|
+ if (chartInstance1) {
|
|
|
+ chartInstance1.resize();
|
|
|
+ }
|
|
|
+ if (minuteChartInstance0) {
|
|
|
+ minuteChartInstance0.resize();
|
|
|
+ }
|
|
|
+ if (minuteChartInstance1) {
|
|
|
+ minuteChartInstance1.resize();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 关闭分钟级数据弹窗
|
|
|
+function handleMinuteDialogClose() {
|
|
|
+ minuteDialogVisible.value = false;
|
|
|
+}
|
|
|
+
|
|
|
+// 显示分钟级数据弹窗
|
|
|
+function showMinuteDialog() {
|
|
|
+ minuteDialogVisible.value = true;
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ initChart();
|
|
|
+ window.addEventListener('resize', resizeChart);
|
|
|
+
|
|
|
+ // 默认选择所有产线
|
|
|
+ //selectedLines.value = [...allLines.value];
|
|
|
+
|
|
|
+ // 初始加载数据
|
|
|
+ getList();
|
|
|
+
|
|
|
+ // 添加一个微任务确保图表正确初始化
|
|
|
+ nextTick(() => {
|
|
|
+ if (!chartInstance0 && chartRef0.value) {
|
|
|
+ chartInstance0 = echarts.init(chartRef0.value);
|
|
|
+ }
|
|
|
+ if (!chartInstance1 && chartRef1.value) {
|
|
|
+ chartInstance1 = echarts.init(chartRef1.value);
|
|
|
+ }
|
|
|
+ });
|
|
|
+});
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ window.removeEventListener('resize', resizeChart);
|
|
|
+ if (chartInstance0) {
|
|
|
+ chartInstance0.dispose();
|
|
|
+ }
|
|
|
+ if (chartInstance1) {
|
|
|
+ chartInstance1.dispose();
|
|
|
+ }
|
|
|
+ if (minuteChartInstance0) {
|
|
|
+ minuteChartInstance0.dispose();
|
|
|
+ }
|
|
|
+ if (minuteChartInstance1) {
|
|
|
+ minuteChartInstance1.dispose();
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+onActivated(() => {
|
|
|
+ resizeChart();
|
|
|
+});
|
|
|
+
|
|
|
+// 取消按钮
|
|
|
+function cancel() {
|
|
|
+ open.value = false;
|
|
|
+ reset();
|
|
|
+}
|
|
|
+
|
|
|
+// 表单重置
|
|
|
+function reset() {
|
|
|
+ form.value = {
|
|
|
+ id: null,
|
|
|
+ dataDate: null,
|
|
|
+ hour: null,
|
|
|
+ line: null,
|
|
|
+ openRate: null,
|
|
|
+ length: null,
|
|
|
+ tmp: null,
|
|
|
+ speed: null,
|
|
|
+ energy: null,
|
|
|
+ amp: null,
|
|
|
+ createdBy: null,
|
|
|
+ createdTime: null,
|
|
|
+ updatedBy: null,
|
|
|
+ updatedTime: null,
|
|
|
+ remark: null
|
|
|
+ };
|
|
|
+ proxy.resetForm("rzLineRef");
|
|
|
+}
|
|
|
+
|
|
|
+/** 搜索按钮操作 */
|
|
|
+function handleQuery() {
|
|
|
+ queryParams.value.pageNum = 1;
|
|
|
+ // 检查查询条件
|
|
|
+ if (!queryParams.value.dataDate) {
|
|
|
+ proxy.$modal.msgWarning("请选择日期");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 不要重置已选择的产线和设备,仅更新数据
|
|
|
+ updateQueryData();
|
|
|
+}
|
|
|
+
|
|
|
+/** 重置按钮操作 */
|
|
|
+function resetQuery() {
|
|
|
+ proxy.resetForm("queryRef");
|
|
|
+ // 设置默认日期为当前日期
|
|
|
+ const now = new Date();
|
|
|
+ const year = now.getFullYear();
|
|
|
+ const month = (now.getMonth() + 1).toString().padStart(2, '0');
|
|
|
+ const day = now.getDate().toString().padStart(2, '0');
|
|
|
+ queryParams.value.dataDate = `${year}-${month}-${day}`;
|
|
|
+
|
|
|
+ // 重置产线和设备选择
|
|
|
+ selectedLines.value = [];
|
|
|
+ selectedMetrics.value = {};
|
|
|
+ equipmentList.value = {};
|
|
|
+
|
|
|
+ handleQuery();
|
|
|
+}
|
|
|
+// 处理设备类型变化
|
|
|
+function handleEquipmentTypeChange(val) {
|
|
|
+ // 清空已选的设备参数
|
|
|
+ selectedEquipmentParam.value = '';
|
|
|
+
|
|
|
+ // 如果有选择设备类型,则更新设备参数选项
|
|
|
+ if (val) {
|
|
|
+ // 在设备类型列表中找到当前选中的设备类型
|
|
|
+ const selectedType = equipmentTypeList.value.find(item => item.typeId === val);
|
|
|
+ if (selectedType && selectedType.dyeTypeParaList) {
|
|
|
+ // 提取设备参数选项
|
|
|
+ equipmentParamOptions.value = selectedType.dyeTypeParaList.map(item => {
|
|
|
+ return {
|
|
|
+ paraCode: item.paraCode,
|
|
|
+ paraName: item.paraName
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ // 默认选择第一条设备参数
|
|
|
+ if (selectedType.dyeTypeParaList.length > 0 && !selectedEquipmentParam.value) {
|
|
|
+ selectedEquipmentParam.value = selectedType.dyeTypeParaList[0].paraCode;
|
|
|
+ // 触发设备参数变化事件
|
|
|
+ handleEquipmentParamChange();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ equipmentParamOptions.value = [];
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 如果没有选择设备类型,清空设备参数选项
|
|
|
+ equipmentParamOptions.value = [];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 处理设备参数变化
|
|
|
+function handleEquipmentParamChange() {
|
|
|
+ // 清空设备列表和已选择的设备
|
|
|
+ equipmentList.value = {};
|
|
|
+ selectedMetrics.value = {};
|
|
|
+
|
|
|
+ // 获取新设备列表
|
|
|
+ getDeviceList();
|
|
|
+}
|
|
|
+
|
|
|
+// 处理产线选择变化
|
|
|
+function handleLineSelectionChange(val) {
|
|
|
+ if (val.length > 2) {
|
|
|
+ // 限制最多选择两条产线
|
|
|
+ selectedLines.value = val.slice(0, 2);
|
|
|
+ proxy.$modal.msgWarning("最多只能选择两条产线进行对比");
|
|
|
+ }
|
|
|
+ // 当取消选择所有产线时,清空相关设备选择
|
|
|
+ if (val.length === 0) {
|
|
|
+ selectedMetrics.value = {};
|
|
|
+ }
|
|
|
+ getDeviceList();
|
|
|
+}
|
|
|
+
|
|
|
+/** 新增按钮操作 */
|
|
|
+function handleAdd() {
|
|
|
+ reset();
|
|
|
+ open.value = true;
|
|
|
+ title.value = "添加染整线产线小时统计数据";
|
|
|
+}
|
|
|
+
|
|
|
+/** 修改按钮操作 */
|
|
|
+function handleUpdate(row) {
|
|
|
+ reset();
|
|
|
+ const _id = row.id || ids.value
|
|
|
+ getRzLine(_id).then(response => {
|
|
|
+ form.value = response.data;
|
|
|
+ open.value = true;
|
|
|
+ title.value = "修改染整线产线小时统计数据";
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/** 提交按钮 */
|
|
|
+function submitForm() {
|
|
|
+ proxy.$refs["rzLineRef"].validate(valid => {
|
|
|
+ if (valid) {
|
|
|
+ if (form.value.id != null) {
|
|
|
+ updateRzLine(form.value).then(response => {
|
|
|
+ proxy.$modal.msgSuccess("修改成功");
|
|
|
+ open.value = false;
|
|
|
+ getList();
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ addRzLine(form.value).then(response => {
|
|
|
+ proxy.$modal.msgSuccess("新增成功");
|
|
|
+ open.value = false;
|
|
|
+ getList();
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+/** 删除按钮操作 */
|
|
|
+function handleDelete(row) {
|
|
|
+ const _ids = row.id || ids.value;
|
|
|
+ proxy.$modal.confirm('是否确认删除染整线产线小时统计数据编号为"' + _ids + '"的数据项?').then(function() {
|
|
|
+ return delRzLine(_ids);
|
|
|
+ }).then(() => {
|
|
|
+ getList();
|
|
|
+ proxy.$modal.msgSuccess("删除成功");
|
|
|
+ }).catch(() => {});
|
|
|
+}
|
|
|
+
|
|
|
+/** 导出按钮操作 */
|
|
|
+function handleExport() {
|
|
|
+ proxy.download('dyeing/rzLine/export', {
|
|
|
+ ...queryParams.value
|
|
|
+ }, `rzLine_${new Date().getTime()}.xlsx`)
|
|
|
+}
|
|
|
+
|
|
|
+getList();
|
|
|
+</script>
|