|
|
@@ -0,0 +1,789 @@
|
|
|
+<template>
|
|
|
+ <div class="app-container">
|
|
|
+ <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px" style="text-align: center;">
|
|
|
+ <el-form-item style="width: 208px; display: inline-block;">
|
|
|
+ <div style="display: flex; align-items: center; justify-content: center;">
|
|
|
+ <el-button icon="ArrowLeft" @click="navigateDay(-1)" size="small" style="margin-right: 15px;"></el-button>
|
|
|
+ <el-date-picker clearable
|
|
|
+ v-model="queryParams.dataDate"
|
|
|
+ type="date"
|
|
|
+ value-format="YYYY-MM-DD"
|
|
|
+ placeholder="请选择日期"
|
|
|
+ style="width: 130px"
|
|
|
+ @change="handleQuery">
|
|
|
+ </el-date-picker>
|
|
|
+ <el-button icon="ArrowRight" @click="navigateDay(1)" size="small" style="margin-left: 15px;"></el-button>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <!-- 产线选择 -->
|
|
|
+ <el-row :gutter="20" style="margin-bottom: 20px;">
|
|
|
+ <el-col :span="24">
|
|
|
+ <el-card>
|
|
|
+ <!-- Added equipment type and parameter selectors on the same line -->
|
|
|
+ <div style="display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 10px;">
|
|
|
+ <span>设备类型:</span>
|
|
|
+ <el-select v-model="selectedEquipmentType" placeholder="请选择设备类型" size="small" @change="handleEquipmentTypeChange" clearable style="width: 150px;">
|
|
|
+ <el-option
|
|
|
+ v-for="item in equipmentTypeOptions"
|
|
|
+ :key="item.typeId"
|
|
|
+ :label="item.typeName"
|
|
|
+ :value="item.typeId">
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+
|
|
|
+ <span style="margin-left: 30px;">设备参数:</span>
|
|
|
+ <el-select v-model="selectedEquipmentParam" placeholder="请选择设备参数" size="small" @change="handleEquipmentParamChange(v)" clearable style="width: 150px;">
|
|
|
+ <el-option
|
|
|
+ v-for="item in equipmentParamOptions"
|
|
|
+ :key="item.paraCode"
|
|
|
+ :label="item.paraName"
|
|
|
+ :value="item.paraCode">
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div style="display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 10px;">
|
|
|
+ <span>选择产线进行对比:</span>
|
|
|
+ <el-checkbox-group v-model="selectedLines" @change="getDeviceList(v)" style="padding-left: 10px;">
|
|
|
+ <el-checkbox v-for="line in allLines" :key="line" :value="line" :label="`${line}#`">
|
|
|
+ <div v-if="selectedLines.includes(line)" style="display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin-bottom: 0px;">
|
|
|
+ <span>{{line}}# 设备:</span>
|
|
|
+ <el-select v-model="selectedMetrics[line]" placeholder="请选择设备" size="small" @change="updateQueryData" style="width: 150px;">
|
|
|
+ <el-option
|
|
|
+ v-for="item in equipmentList[line]"
|
|
|
+ :key="item.id"
|
|
|
+ :label="item.name"
|
|
|
+ :value="item.id">
|
|
|
+ </el-option>
|
|
|
+ </el-select>
|
|
|
+ </div>
|
|
|
+ <div v-else>{{ line }}#</div>
|
|
|
+ </el-checkbox>
|
|
|
+ </el-checkbox-group>
|
|
|
+ </div>
|
|
|
+ </el-card>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 折线图和表格左右布局 -->
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <!-- 左侧折线图 -->
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-card style="margin-bottom: 20px;">
|
|
|
+ <div ref="chartRef0" style="width: 100%; height: 320px;"></div>
|
|
|
+ </el-card>
|
|
|
+ <el-card style="margin-bottom: 20px;">
|
|
|
+ <el-table :data="rzLineList" height="320" :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: 20px;">
|
|
|
+ <div ref="chartRef1" style="width: 100%; height: 320px;"></div>
|
|
|
+ </el-card>
|
|
|
+ <el-card style="margin-bottom: 20px;">
|
|
|
+ <el-table :data="rzLineList1" height="320" :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>
|
|
|
+ </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 } 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 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() {
|
|
|
+ selectedLines.value = [];
|
|
|
+ // 先获取设备类型列表
|
|
|
+ listDeviceTypes({pageSize: 10000}).then(response => {
|
|
|
+ equipmentTypeList.value = response.rows;
|
|
|
+ // 提取设备类型选项
|
|
|
+ equipmentTypeOptions.value = response.rows.map(item => {
|
|
|
+ return {
|
|
|
+ typeId: item.typeId,
|
|
|
+ typeName: item.typeName
|
|
|
+ };
|
|
|
+ });
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function difference(arr1, arr2) {
|
|
|
+ const set2 = new Set(arr2);
|
|
|
+ return arr1.filter(item => !set2.has(item));
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 获取设备列表
|
|
|
+ * @returns {void}
|
|
|
+ */
|
|
|
+function getDeviceList(v){
|
|
|
+ // 检查是否选择了产线
|
|
|
+ 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);
|
|
|
+ console.log("取消了产线:",tmp[0])
|
|
|
+ selectedMetrics.value[tmp[0]] = '';
|
|
|
+ updateQueryData();
|
|
|
+ }
|
|
|
+
|
|
|
+ let currentLine = 0;
|
|
|
+ if (selectedLines.value.length == 1) {
|
|
|
+ currentLine = selectedLines.value[0];
|
|
|
+ }else{
|
|
|
+ let tmp = difference(selectedLines.value,oldSelectLines.value);
|
|
|
+ if (tmp.length == 1){
|
|
|
+ currentLine = tmp[0];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(currentLine == 0){
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if(selectedEquipmentType.value.length == 0){
|
|
|
+ proxy.$modal.msgError("请先选择设备类型");
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if(selectedEquipmentParam.value.length == 0){
|
|
|
+ proxy.$modal.msgError("请先选择设备参数");
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ oldSelectLines.value = JSON.parse(JSON.stringify(selectedLines.value));
|
|
|
+ listDevice({pageSize: 10000,pageNum:1,paraCode:selectedEquipmentParam.value,typeId:selectedEquipmentType.value,line:currentLine}).then(response => {
|
|
|
+ // 提取设备参数选项
|
|
|
+ equipmentList.value[currentLine] = response.rows.map(item => {
|
|
|
+ return {
|
|
|
+ id: item.deviceId,
|
|
|
+ name: item.deviceName
|
|
|
+ };
|
|
|
+ });
|
|
|
+ });
|
|
|
+}
|
|
|
+
|
|
|
+function updateQueryData() {
|
|
|
+ initChart();
|
|
|
+ rzLineList.value=[];
|
|
|
+ rzLineList1.value=[];
|
|
|
+ let queryPara = {
|
|
|
+ paraCode: selectedEquipmentParam.value,
|
|
|
+ typeId: selectedEquipmentType.value,
|
|
|
+ dataDate: queryParams.value.dataDate,
|
|
|
+ pageSize:10000,
|
|
|
+ pageNum:1,
|
|
|
+ };
|
|
|
+ if(selectedLines.value.length==1){
|
|
|
+ queryPara['line'] = selectedLines.value[0];
|
|
|
+ queryPara['deviceId'] = selectedMetrics.value[selectedLines.value[0]];
|
|
|
+ listHour(queryPara).then(res=>{
|
|
|
+ rzLineList.value = res.rows;
|
|
|
+ updateChart();
|
|
|
+ })
|
|
|
+ }
|
|
|
+ if(selectedLines.value.length==2){
|
|
|
+ queryPara['line'] = selectedLines.value[0];
|
|
|
+ queryPara['deviceId'] = selectedMetrics.value[selectedLines.value[0]];
|
|
|
+ listHour(queryPara).then(res=>{
|
|
|
+ rzLineList.value = res.rows;
|
|
|
+ updateChart();
|
|
|
+ })
|
|
|
+ queryPara['line'] = selectedLines.value[1];
|
|
|
+ queryPara['deviceId'] = selectedMetrics.value[selectedLines.value[1]];
|
|
|
+ listHour(queryPara).then(res=>{
|
|
|
+ rzLineList1.value = res.rows;
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 更新图表
|
|
|
+function updateChart() {
|
|
|
+ if (!chartInstance0 || !rzLineList.value.length) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+/*
|
|
|
+ {
|
|
|
+ "dataDate": "2025-11-04 00:00:00",
|
|
|
+ "hour": 3,
|
|
|
+ "deviceId": 15,
|
|
|
+ "deviceName": "两棍刷毛机_6线_前整_5号",
|
|
|
+ "paraCode": "ENG_energy",
|
|
|
+ "paraName": "电量",
|
|
|
+ "paraValue": 2.830000,
|
|
|
+ "paraMValue": "[{\"time\":\"1\",\"value\":0.04},{\"time\":\"2\",\"value\":0.06},{\"time\":\"3\",\"value\":0.03},{\"time\":\"4\",\"value\":0.05},{\"time\":\"5\",\"value\":0.06},{\"time\":\"6\",\"value\":0.06},{\"time\":\"7\",\"value\":0.06},{\"time\":\"8\",\"value\":0.05},{\"time\":\"9\",\"value\":0.06},{\"time\":\"10\",\"value\":0.03},{\"time\":\"11\",\"value\":0.06},{\"time\":\"12\",\"value\":0.05},{\"time\":\"13\",\"value\":0.06},{\"time\":\"14\",\"value\":0.06},{\"time\":\"15\",\"value\":0.05},{\"time\":\"16\",\"value\":0.03},{\"time\":\"17\",\"value\":0.06},{\"time\":\"18\",\"value\":0.06},{\"time\":\"19\",\"value\":0.06},{\"time\":\"20\",\"value\":0.06},{\"time\":\"21\",\"value\":0.03},{\"time\":\"22\",\"value\":0.06},{\"time\":\"23\",\"value\":0.05},{\"time\":\"24\",\"value\":0.05},{\"time\":\"25\",\"value\":0},{\"time\":\"26\",\"value\":0.01},{\"time\":\"27\",\"value\":0},{\"time\":\"28\",\"value\":0.01},{\"time\":\"29\",\"value\":0},{\"time\":\"30\",\"value\":0.01},{\"time\":\"31\",\"value\":0.02},{\"time\":\"32\",\"value\":0.03},{\"time\":\"33\",\"value\":0.06},{\"time\":\"34\",\"value\":0.06},{\"time\":\"35\",\"value\":0.06},{\"time\":\"36\",\"value\":0.07},{\"time\":\"37\",\"value\":0.06},{\"time\":\"38\",\"value\":0.03},{\"time\":\"39\",\"value\":0.06},{\"time\":\"40\",\"value\":0.06},{\"time\":\"41\",\"value\":0.05},{\"time\":\"42\",\"value\":0.06},{\"time\":\"43\",\"value\":0.08},{\"time\":\"44\",\"value\":0.03},{\"time\":\"45\",\"value\":0.06},{\"time\":\"46\",\"value\":0.05},{\"time\":\"47\",\"value\":0.06},{\"time\":\"48\",\"value\":0.06},{\"time\":\"49\",\"value\":0.03},{\"time\":\"50\",\"value\":0.05},{\"time\":\"51\",\"value\":0.06},{\"time\":\"52\",\"value\":0.04},{\"time\":\"53\",\"value\":0.05},{\"time\":\"54\",\"value\":0.06},{\"time\":\"55\",\"value\":0.05},{\"time\":\"56\",\"value\":0.03},{\"time\":\"57\",\"value\":0.06},{\"time\":\"58\",\"value\":0.06},{\"time\":\"59\",\"value\":0.05},{\"time\":\"0\",\"value\":0.06}]",
|
|
|
+ }
|
|
|
+*/
|
|
|
+ let line = rzLineList.value[0]['deviceName'];
|
|
|
+ let selectedEquipmentParamName=rzLineList.value[0]['paraName'];
|
|
|
+
|
|
|
+ // 获取所有唯一的时间点
|
|
|
+ const allTimePoints = [...new Set(rzLineList.value.map(item =>
|
|
|
+ `${item.hour.toString().padStart(2, '0')}`))].sort();
|
|
|
+
|
|
|
+ // 准备图表数据
|
|
|
+ const series = [];
|
|
|
+ const legendData = [];
|
|
|
+
|
|
|
+ // 为每个产线生成选定指标的数据系列
|
|
|
+ const dataMap = new Map();
|
|
|
+ rzLineList.value.forEach(item => {
|
|
|
+ const timePoint = `${item.hour.toString().padStart(2, '0')}`;
|
|
|
+ dataMap.set(timePoint, item);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 基于统一时间轴生成数据
|
|
|
+ const openRateData = allTimePoints.map(timePoint => {
|
|
|
+ const item = dataMap.get(timePoint);
|
|
|
+ return item && item.paraValue !== null ? parseFloat(item.paraValue) : null;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 添加产线+指标的数据系列
|
|
|
+ series.push({
|
|
|
+ name: `${line}-${selectedEquipmentParamName}`,
|
|
|
+ type: 'line',
|
|
|
+ data: openRateData,
|
|
|
+ smooth: true,
|
|
|
+ showSymbol: false
|
|
|
+ });
|
|
|
+
|
|
|
+ const option = {
|
|
|
+ title: {
|
|
|
+ text: '前整车间'+line+' '+selectedEquipmentParamName+'对比',
|
|
|
+ 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: allTimePoints
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ name: ''
|
|
|
+ },
|
|
|
+ series: series
|
|
|
+ };
|
|
|
+
|
|
|
+ chartInstance0.setOption(option, true);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+function updateChart1() {
|
|
|
+ if (!chartInstance1 || !rzLineList1.value.length) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+/*
|
|
|
+ {
|
|
|
+ "dataDate": "2025-11-04 00:00:00",
|
|
|
+ "hour": 3,
|
|
|
+ "deviceId": 15,
|
|
|
+ "deviceName": "两棍刷毛机_6线_前整_5号",
|
|
|
+ "paraCode": "ENG_energy",
|
|
|
+ "paraName": "电量",
|
|
|
+ "paraValue": 2.830000,
|
|
|
+ "paraMValue": "[{\"time\":\"1\",\"value\":0.04},{\"time\":\"2\",\"value\":0.06},{\"time\":\"3\",\"value\":0.03},{\"time\":\"4\",\"value\":0.05},{\"time\":\"5\",\"value\":0.06},{\"time\":\"6\",\"value\":0.06},{\"time\":\"7\",\"value\":0.06},{\"time\":\"8\",\"value\":0.05},{\"time\":\"9\",\"value\":0.06},{\"time\":\"10\",\"value\":0.03},{\"time\":\"11\",\"value\":0.06},{\"time\":\"12\",\"value\":0.05},{\"time\":\"13\",\"value\":0.06},{\"time\":\"14\",\"value\":0.06},{\"time\":\"15\",\"value\":0.05},{\"time\":\"16\",\"value\":0.03},{\"time\":\"17\",\"value\":0.06},{\"time\":\"18\",\"value\":0.06},{\"time\":\"19\",\"value\":0.06},{\"time\":\"20\",\"value\":0.06},{\"time\":\"21\",\"value\":0.03},{\"time\":\"22\",\"value\":0.06},{\"time\":\"23\",\"value\":0.05},{\"time\":\"24\",\"value\":0.05},{\"time\":\"25\",\"value\":0},{\"time\":\"26\",\"value\":0.01},{\"time\":\"27\",\"value\":0},{\"time\":\"28\",\"value\":0.01},{\"time\":\"29\",\"value\":0},{\"time\":\"30\",\"value\":0.01},{\"time\":\"31\",\"value\":0.02},{\"time\":\"32\",\"value\":0.03},{\"time\":\"33\",\"value\":0.06},{\"time\":\"34\",\"value\":0.06},{\"time\":\"35\",\"value\":0.06},{\"time\":\"36\",\"value\":0.07},{\"time\":\"37\",\"value\":0.06},{\"time\":\"38\",\"value\":0.03},{\"time\":\"39\",\"value\":0.06},{\"time\":\"40\",\"value\":0.06},{\"time\":\"41\",\"value\":0.05},{\"time\":\"42\",\"value\":0.06},{\"time\":\"43\",\"value\":0.08},{\"time\":\"44\",\"value\":0.03},{\"time\":\"45\",\"value\":0.06},{\"time\":\"46\",\"value\":0.05},{\"time\":\"47\",\"value\":0.06},{\"time\":\"48\",\"value\":0.06},{\"time\":\"49\",\"value\":0.03},{\"time\":\"50\",\"value\":0.05},{\"time\":\"51\",\"value\":0.06},{\"time\":\"52\",\"value\":0.04},{\"time\":\"53\",\"value\":0.05},{\"time\":\"54\",\"value\":0.06},{\"time\":\"55\",\"value\":0.05},{\"time\":\"56\",\"value\":0.03},{\"time\":\"57\",\"value\":0.06},{\"time\":\"58\",\"value\":0.06},{\"time\":\"59\",\"value\":0.05},{\"time\":\"0\",\"value\":0.06}]",
|
|
|
+ }
|
|
|
+*/
|
|
|
+ let line = rzLineList1.value[0]['deviceName'];
|
|
|
+ let selectedEquipmentParamName=rzLineList1.value[0]['paraName'];
|
|
|
+
|
|
|
+ // 获取所有唯一的时间点
|
|
|
+ const allTimePoints = [...new Set(rzLineList1.value.map(item =>
|
|
|
+ `${item.hour.toString().padStart(2, '0')}`))].sort();
|
|
|
+
|
|
|
+ // 准备图表数据
|
|
|
+ const series = [];
|
|
|
+ const legendData = [];
|
|
|
+
|
|
|
+ // 为每个产线生成选定指标的数据系列
|
|
|
+ const dataMap = new Map();
|
|
|
+ rzLineList1.value.forEach(item => {
|
|
|
+ const timePoint = `${item.hour.toString().padStart(2, '0')}`;
|
|
|
+ dataMap.set(timePoint, item);
|
|
|
+ });
|
|
|
+
|
|
|
+ // 基于统一时间轴生成数据
|
|
|
+ const openRateData = allTimePoints.map(timePoint => {
|
|
|
+ const item = dataMap.get(timePoint);
|
|
|
+ return item && item.paraValue !== null ? parseFloat(item.paraValue) : null;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 添加产线+指标的数据系列
|
|
|
+ series.push({
|
|
|
+ name: `${line}-${selectedEquipmentParamName}`,
|
|
|
+ type: 'line',
|
|
|
+ data: openRateData,
|
|
|
+ smooth: true,
|
|
|
+ showSymbol: false
|
|
|
+ });
|
|
|
+
|
|
|
+ const option = {
|
|
|
+ title: {
|
|
|
+ text: '前整车间'+line+' '+selectedEquipmentParamName+'对比',
|
|
|
+ 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: allTimePoints
|
|
|
+ },
|
|
|
+ yAxis: {
|
|
|
+ type: 'value',
|
|
|
+ name: ''
|
|
|
+ },
|
|
|
+ series: series
|
|
|
+ };
|
|
|
+
|
|
|
+ chartInstance1.setOption(option, true);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+// 窗口大小改变时重置图表大小
|
|
|
+function resizeChart() {
|
|
|
+ if (chartInstance0) {
|
|
|
+ chartInstance0.resize();
|
|
|
+ }
|
|
|
+ if (chartInstance1) {
|
|
|
+ chartInstance1.resize();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ initChart();
|
|
|
+ window.addEventListener('resize', resizeChart);
|
|
|
+
|
|
|
+ // 默认选择所有产线
|
|
|
+ //selectedLines.value = [...allLines.value];
|
|
|
+
|
|
|
+ // 初始加载数据
|
|
|
+ getList();
|
|
|
+});
|
|
|
+
|
|
|
+onUnmounted(() => {
|
|
|
+ window.removeEventListener('resize', resizeChart);
|
|
|
+ if (chartInstance0) {
|
|
|
+ chartInstance0.dispose();
|
|
|
+ }
|
|
|
+ if (chartInstance1) {
|
|
|
+ chartInstance1.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;
|
|
|
+ }
|
|
|
+ getList();
|
|
|
+}
|
|
|
+
|
|
|
+/** 重置按钮操作 */
|
|
|
+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 = [...allLines.value];
|
|
|
+
|
|
|
+ handleQuery();
|
|
|
+}
|
|
|
+
|
|
|
+// 全选产线
|
|
|
+function selectAllLines() {
|
|
|
+ selectedLines.value = [...allLines.value];
|
|
|
+ getList();
|
|
|
+}
|
|
|
+
|
|
|
+// 反选产线
|
|
|
+function invertSelection() {
|
|
|
+ const newSelectedLines = [];
|
|
|
+ allLines.value.forEach(line => {
|
|
|
+ if (!selectedLines.value.includes(line)) {
|
|
|
+ newSelectedLines.push(line);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ selectedLines.value = newSelectedLines;
|
|
|
+ getList();
|
|
|
+}
|
|
|
+
|
|
|
+// 全选指标
|
|
|
+function selectAllMetrics() {
|
|
|
+ selectedMetrics.value = ['开机率', '温度', '速度', '电量', '电流'];
|
|
|
+ updateChart();
|
|
|
+}
|
|
|
+
|
|
|
+// 反选指标
|
|
|
+function invertMetrics() {
|
|
|
+ const allMetrics = ['开机率', '温度', '速度', '电量', '电流'];
|
|
|
+ const newSelectedMetrics = [];
|
|
|
+ allMetrics.forEach(metric => {
|
|
|
+ if (!selectedMetrics.value.includes(metric)) {
|
|
|
+ newSelectedMetrics.push(metric);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ selectedMetrics.value = newSelectedMetrics;
|
|
|
+ updateChart();
|
|
|
+}
|
|
|
+
|
|
|
+// 处理设备类型变化
|
|
|
+function handleEquipmentTypeChange(val) {
|
|
|
+ console.log('设备类型变化:', 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
|
|
|
+ };
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ equipmentParamOptions.value = [];
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 如果没有选择设备类型,清空设备参数选项
|
|
|
+ equipmentParamOptions.value = [];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 处理设备参数变化
|
|
|
+function handleEquipmentParamChange() {
|
|
|
+ // 可以在这里添加设备参数变化时的处理逻辑
|
|
|
+ //let lst = equipmentParamOptions.value.filter(item => item.paraCode ==selectedEquipmentParam.value);
|
|
|
+ //console.log(lst);
|
|
|
+ getDeviceList();
|
|
|
+}
|
|
|
+
|
|
|
+// 多选框选中数据
|
|
|
+function handleSelectionChange(selection) {
|
|
|
+ ids.value = selection.map(item => item.id);
|
|
|
+ single.value = selection.length != 1;
|
|
|
+ multiple.value = !selection.length;
|
|
|
+}
|
|
|
+
|
|
|
+/** 新增按钮操作 */
|
|
|
+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>
|