|
|
|
@ -4,6 +4,7 @@
|
|
|
|
<template #header>
|
|
|
|
<template #header>
|
|
|
|
<div class="card-header">
|
|
|
|
<div class="card-header">
|
|
|
|
<span class="header-title">追溯结构</span>
|
|
|
|
<span class="header-title">追溯结构</span>
|
|
|
|
|
|
|
|
<el-button type="primary" link icon="ArrowLeft" @click="goBack">返回列表</el-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
</template>
|
|
|
|
<el-tree
|
|
|
|
<el-tree
|
|
|
|
@ -182,7 +183,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
<script setup lang="ts" name="MixTraceBackward2">
|
|
|
|
<script setup lang="ts" name="MixTraceBackward2">
|
|
|
|
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
|
|
|
|
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
|
|
|
|
import { useRoute } from 'vue-router';
|
|
|
|
import { useRoute, useRouter } from 'vue-router';
|
|
|
|
import { ArrowRight, Document, Folder } from '@element-plus/icons-vue';
|
|
|
|
import { ArrowRight, Document, Folder } from '@element-plus/icons-vue';
|
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
|
import { ElMessage } from 'element-plus';
|
|
|
|
import * as echarts from 'echarts';
|
|
|
|
import * as echarts from 'echarts';
|
|
|
|
@ -191,6 +192,7 @@ import backwardData from './data/backward2.json';
|
|
|
|
type BarcodeType = '1' | '2' | '3' | '4';
|
|
|
|
type BarcodeType = '1' | '2' | '3' | '4';
|
|
|
|
|
|
|
|
|
|
|
|
const route = useRoute();
|
|
|
|
const route = useRoute();
|
|
|
|
|
|
|
|
const router = useRouter();
|
|
|
|
const detailMap = (backwardData as any).detailMap || {};
|
|
|
|
const detailMap = (backwardData as any).detailMap || {};
|
|
|
|
const detailKeys = Object.keys(detailMap);
|
|
|
|
const detailKeys = Object.keys(detailMap);
|
|
|
|
|
|
|
|
|
|
|
|
@ -208,6 +210,14 @@ const treeRef = ref();
|
|
|
|
const chartRef = ref<HTMLDivElement>();
|
|
|
|
const chartRef = ref<HTMLDivElement>();
|
|
|
|
let chartInstance: echarts.ECharts | null = null;
|
|
|
|
let chartInstance: echarts.ECharts | null = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const goBack = () => {
|
|
|
|
|
|
|
|
if (window.history.length > 1) {
|
|
|
|
|
|
|
|
router.back();
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
router.push('/mes/mixTrace/show/backward1');
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const productionInfo = computed(() => {
|
|
|
|
const productionInfo = computed(() => {
|
|
|
|
return detailMap[detailId.value]?.production || {};
|
|
|
|
return detailMap[detailId.value]?.production || {};
|
|
|
|
});
|
|
|
|
});
|
|
|
|
@ -258,7 +268,86 @@ const loadData = () => {
|
|
|
|
const initChart = () => {
|
|
|
|
const initChart = () => {
|
|
|
|
if (!chartRef.value) return;
|
|
|
|
if (!chartRef.value) return;
|
|
|
|
const cd = curveDataSource.value;
|
|
|
|
const cd = curveDataSource.value;
|
|
|
|
const xAxisData = cd.mixingTime || [];
|
|
|
|
const mixingRows = Array.isArray(mixingProcessData.value) ? mixingProcessData.value : [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const toNumberOrNull = (value: any): number | null => {
|
|
|
|
|
|
|
|
const num = Number(value);
|
|
|
|
|
|
|
|
return Number.isFinite(num) ? num : null;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const listLength = (value: any): number => {
|
|
|
|
|
|
|
|
return Array.isArray(value) ? value.length : 0;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const buildPositionFromAction = (row: any): number | null => {
|
|
|
|
|
|
|
|
const actionText = String(row?.action || row?.condition || '');
|
|
|
|
|
|
|
|
if (actionText.includes('压上顶栓')) return 1;
|
|
|
|
|
|
|
|
if (actionText.includes('升上顶栓')) return 0;
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let xAxisData: Array<string | number> = [];
|
|
|
|
|
|
|
|
let temperatureData: Array<number | null> = [];
|
|
|
|
|
|
|
|
let powerData: Array<number | null> = [];
|
|
|
|
|
|
|
|
let energyData: Array<number | null> = [];
|
|
|
|
|
|
|
|
let pressureData: Array<number | null> = [];
|
|
|
|
|
|
|
|
let speedData: Array<number | null> = [];
|
|
|
|
|
|
|
|
let positionData: Array<number | null> = [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (mixingRows.length > 0) {
|
|
|
|
|
|
|
|
xAxisData = mixingRows.map((row: any, idx: number) => row.step ?? idx + 1);
|
|
|
|
|
|
|
|
temperatureData = mixingRows.map((row: any) => toNumberOrNull(row.temperature));
|
|
|
|
|
|
|
|
powerData = mixingRows.map((row: any) => toNumberOrNull(row.power));
|
|
|
|
|
|
|
|
energyData = mixingRows.map((row: any) => toNumberOrNull(row.energy));
|
|
|
|
|
|
|
|
pressureData = mixingRows.map((row: any) => toNumberOrNull(row.pressure));
|
|
|
|
|
|
|
|
speedData = mixingRows.map((row: any) => toNumberOrNull(row.rpm));
|
|
|
|
|
|
|
|
positionData = mixingRows.map((row: any) => buildPositionFromAction(row));
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
const maxLen = Math.max(
|
|
|
|
|
|
|
|
listLength(cd.mixingTime),
|
|
|
|
|
|
|
|
listLength(cd.temperature),
|
|
|
|
|
|
|
|
listLength(cd.power),
|
|
|
|
|
|
|
|
listLength(cd.energy),
|
|
|
|
|
|
|
|
listLength(cd.pressure),
|
|
|
|
|
|
|
|
listLength(cd.speed),
|
|
|
|
|
|
|
|
listLength(cd.position)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
xAxisData =
|
|
|
|
|
|
|
|
Array.isArray(cd.mixingTime) && cd.mixingTime.length > 0
|
|
|
|
|
|
|
|
? cd.mixingTime.map((v: any, i: number) => {
|
|
|
|
|
|
|
|
const num = Number(v);
|
|
|
|
|
|
|
|
return Number.isFinite(num) ? num : i + 1;
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
: Array.from({ length: maxLen }, (_, i) => i + 1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const buildSeriesData = (source: any): Array<number | null> => {
|
|
|
|
|
|
|
|
const arr = Array.isArray(source) ? source : [];
|
|
|
|
|
|
|
|
return xAxisData.map((_, idx) => toNumberOrNull(arr[idx]));
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
temperatureData = buildSeriesData(cd.temperature);
|
|
|
|
|
|
|
|
powerData = buildSeriesData(cd.power);
|
|
|
|
|
|
|
|
energyData = buildSeriesData(cd.energy);
|
|
|
|
|
|
|
|
pressureData = buildSeriesData(cd.pressure);
|
|
|
|
|
|
|
|
speedData = buildSeriesData(cd.speed);
|
|
|
|
|
|
|
|
positionData = buildSeriesData(cd.position);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const calcRange = (arr: Array<number | null>) => {
|
|
|
|
|
|
|
|
const nums = arr.filter((n): n is number => typeof n === 'number');
|
|
|
|
|
|
|
|
if (!nums.length) return {};
|
|
|
|
|
|
|
|
const min = Math.min(...nums);
|
|
|
|
|
|
|
|
const max = Math.max(...nums);
|
|
|
|
|
|
|
|
const pad = min === max ? Math.max(Math.abs(min) * 0.1, 1) : (max - min) * 0.1;
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
|
|
|
min: Number((min - pad).toFixed(2)),
|
|
|
|
|
|
|
|
max: Number((max + pad).toFixed(2))
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const leftAxisRange = calcRange(temperatureData);
|
|
|
|
|
|
|
|
const rightAxisRange = calcRange([...powerData, ...energyData, ...pressureData, ...speedData, ...positionData]);
|
|
|
|
|
|
|
|
|
|
|
|
if (chartInstance) {
|
|
|
|
if (chartInstance) {
|
|
|
|
chartInstance.dispose();
|
|
|
|
chartInstance.dispose();
|
|
|
|
@ -266,26 +355,47 @@ const initChart = () => {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
chartInstance = echarts.init(chartRef.value);
|
|
|
|
chartInstance = echarts.init(chartRef.value);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (xAxisData.length === 0) {
|
|
|
|
|
|
|
|
chartInstance.setOption({
|
|
|
|
|
|
|
|
graphic: {
|
|
|
|
|
|
|
|
type: 'text',
|
|
|
|
|
|
|
|
left: 'center',
|
|
|
|
|
|
|
|
top: 'middle',
|
|
|
|
|
|
|
|
style: { text: '暂无曲线数据', fill: '#909399', fontSize: 14 }
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
chartInstance.setOption({
|
|
|
|
chartInstance.setOption({
|
|
|
|
|
|
|
|
animation: false,
|
|
|
|
grid: { left: '5%', right: '5%', top: '10%', bottom: '10%', containLabel: true },
|
|
|
|
grid: { left: '5%', right: '5%', top: '10%', bottom: '10%', containLabel: true },
|
|
|
|
tooltip: { trigger: 'axis' },
|
|
|
|
tooltip: { trigger: 'axis' },
|
|
|
|
xAxis: { type: 'category', data: xAxisData, boundaryGap: false, name: '时间(s)' },
|
|
|
|
xAxis: {
|
|
|
|
|
|
|
|
type: 'category',
|
|
|
|
|
|
|
|
data: xAxisData,
|
|
|
|
|
|
|
|
boundaryGap: false,
|
|
|
|
|
|
|
|
name: mixingRows.length > 0 ? '混炼步骤' : '时间(s)'
|
|
|
|
|
|
|
|
},
|
|
|
|
yAxis: [
|
|
|
|
yAxis: [
|
|
|
|
{ type: 'value', name: '温度(℃)', position: 'left', axisLine: { show: true } },
|
|
|
|
{ type: 'value', name: '温度(℃)', position: 'left', axisLine: { show: true }, ...leftAxisRange },
|
|
|
|
{ type: 'value', name: '其他参数', position: 'right', axisLine: { show: true } }
|
|
|
|
{ type: 'value', name: '其他参数', position: 'right', axisLine: { show: true }, ...rightAxisRange }
|
|
|
|
],
|
|
|
|
],
|
|
|
|
series: [
|
|
|
|
series: [
|
|
|
|
{ name: '温度', type: 'line', yAxisIndex: 0, data: cd.temperature || [], smooth: true, itemStyle: { color: '#ff4d4f' } },
|
|
|
|
{ name: '温度', type: 'line', yAxisIndex: 0, data: temperatureData, smooth: false, connectNulls: false, showSymbol: true, itemStyle: { color: '#ff4d4f' } },
|
|
|
|
{ name: '功率', type: 'line', yAxisIndex: 1, data: cd.power || [], smooth: true, itemStyle: { color: '#40a9ff' } },
|
|
|
|
{ name: '功率', type: 'line', yAxisIndex: 1, data: powerData, smooth: false, connectNulls: false, showSymbol: true, itemStyle: { color: '#40a9ff' } },
|
|
|
|
{ name: '能量', type: 'line', yAxisIndex: 1, data: cd.energy || [], smooth: true, itemStyle: { color: '#36cfc9' } },
|
|
|
|
{ name: '能量', type: 'line', yAxisIndex: 1, data: energyData, smooth: false, connectNulls: false, showSymbol: true, itemStyle: { color: '#36cfc9' } },
|
|
|
|
{ name: '压力', type: 'line', yAxisIndex: 1, data: cd.pressure || [], smooth: true, itemStyle: { color: '#95de64' } },
|
|
|
|
{ name: '压力', type: 'line', yAxisIndex: 1, data: pressureData, smooth: false, connectNulls: false, showSymbol: true, itemStyle: { color: '#95de64' } },
|
|
|
|
{ name: '转速', type: 'line', yAxisIndex: 1, data: cd.speed || [], smooth: true, itemStyle: { color: '#f7d13d' } },
|
|
|
|
{ name: '转速', type: 'line', yAxisIndex: 1, data: speedData, smooth: false, connectNulls: false, showSymbol: true, itemStyle: { color: '#f7d13d' } },
|
|
|
|
{
|
|
|
|
{
|
|
|
|
name: '上顶栓',
|
|
|
|
name: '上顶栓',
|
|
|
|
type: 'line',
|
|
|
|
type: 'line',
|
|
|
|
yAxisIndex: 1,
|
|
|
|
yAxisIndex: 1,
|
|
|
|
data: cd.position || [],
|
|
|
|
data: positionData,
|
|
|
|
smooth: false,
|
|
|
|
smooth: false,
|
|
|
|
|
|
|
|
connectNulls: false,
|
|
|
|
|
|
|
|
showSymbol: true,
|
|
|
|
lineStyle: { type: 'dashed' },
|
|
|
|
lineStyle: { type: 'dashed' },
|
|
|
|
itemStyle: { color: '#ffa07a' }
|
|
|
|
itemStyle: { color: '#ffa07a' }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|