对比新文件 |
| | |
| | | <template> |
| | | <el-card shadow="never" class="aui-card--fill"> |
| | | <div class="mod-his__index"> |
| | | <el-form :inline="true" :model="formData" label-width="80px"> |
| | | <el-form-item label="开始时间"> |
| | | <el-date-picker |
| | | v-model="formData.startTime" |
| | | type="datetime" |
| | | format="YYYY-MM-DD HH:mm:00" |
| | | value-format="YYYY-MM-DD HH:mm:00" |
| | | placeholder="选择日期时间"/> |
| | | </el-form-item> |
| | | <el-form-item label="结束时间"> |
| | | <el-date-picker |
| | | v-model="formData.endTime" |
| | | type="datetime" |
| | | format="YYYY-MM-DD HH:mm:00" |
| | | value-format="YYYY-MM-DD HH:mm:00" |
| | | placeholder="选择日期时间"/> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button-group> |
| | | <el-button type="primary" plain :icon="ArrowLeft" |
| | | :loading="loading1" @click="leftSearchDataByRange()"/> |
| | | <el-button type="primary" plain :icon="Search" |
| | | :loading="loading1" @click="getList()">查询 |
| | | </el-button> |
| | | <el-button type="primary" plain :icon="ArrowRight" |
| | | :loading="loading1" @click="rightSearchDataByRange()"/> |
| | | </el-button-group> |
| | | </el-form-item> |
| | | |
| | | <div class="his-body"> |
| | | <div class="his-body-left"> |
| | | <div class="his-body-tree"> |
| | | <el-tree |
| | | :data="treeData" |
| | | show-checkbox |
| | | node-key="id" |
| | | ref="tree" |
| | | highlight-current |
| | | :props="defaultProps" |
| | | @check="onCheckTree"/> |
| | | </div> |
| | | </div> |
| | | <div class="his-body-middle"> |
| | | <div class="his-body-chart"> |
| | | <el-form :inline="true" :model="formData" label-width="100px"> |
| | | <el-row> |
| | | <el-col> |
| | | <el-form-item label="数据类型"> |
| | | <el-checkbox-group v-model="formData.chartCheck" @change="changeChartCheck"> |
| | | <el-checkbox v-for="item in formData.chartOptions" :label="item" |
| | | :key="item">{{ item }} |
| | | </el-checkbox> |
| | | </el-checkbox-group> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | </el-form> |
| | | <div ref="dataAnalysisChart" style="height: 500px;"></div> |
| | | </div> |
| | | </div> |
| | | <div class="his-body-right"> |
| | | <ContentWrap> |
| | | <el-table v-loading="loading" :data="list"> |
| | | <el-table-column label="编号" align="center" min-width="100" prop="itemno"/> |
| | | <el-table-column label="名称" header-align="center" align="left" min-width="200" |
| | | prop="resultName"/> |
| | | <el-table-column label="开始时间" header-align="center" align="left" min-width="200" |
| | | prop="startTime"/> |
| | | <el-table-column label="结束时间" header-align="center" align="left" min-width="200" |
| | | prop="endTime"/> |
| | | <el-table-column label="丢失时间(min)" header-align="center" align="left" min-width="100" |
| | | prop="gap"/> |
| | | <el-table-column label="随机偏差" header-align="center" align="left" min-width="200" |
| | | prop="random"> |
| | | <el-input-number |
| | | v-model="scope.row.random" |
| | | :min="0" |
| | | placeholder="请输入随机偏差" |
| | | /> |
| | | </el-table-column> |
| | | <el-table-column label="操作" align="center" min-width="120" fixed="right"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | link |
| | | type="primary" |
| | | @click="repair(scope.row)" |
| | | > |
| | | 修复 |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- 分页 --> |
| | | <Pagination |
| | | :total="total" |
| | | v-model:page="queryParams.pageNo" |
| | | v-model:limit="queryParams.pageSize" |
| | | @pagination="getList" |
| | | /> |
| | | </ContentWrap> |
| | | </div> |
| | | </div> |
| | | </el-form> |
| | | </div> |
| | | </el-card> |
| | | </template> |
| | | <script lang="ts" setup> |
| | | import {getYMDHMS} from "@/utils/dateUtil" |
| | | import * as McsApi from '@/api/model/mcs' |
| | | import * as echarts from "echarts"; |
| | | import {Search, ArrowLeft, ArrowRight,} from '@element-plus/icons-vue' |
| | | |
| | | defineOptions({name: 'RepairformData'}) |
| | | |
| | | const dataAnalysisChart = ref(null); |
| | | const loading1 = ref(false) // 列表的加载中 |
| | | const treeData = ref([]) |
| | | const itemDataObject = ref() |
| | | const timer = ref() |
| | | const list = ref() |
| | | let myChart = null; |
| | | const queryParams = reactive({ |
| | | pageNo: 1, |
| | | pageSize: 10, |
| | | }) |
| | | |
| | | const formData = ref({ |
| | | startTime: '', |
| | | endTime: '', |
| | | predictTime: '', |
| | | chartCheck: ['T+L', '真实值'], |
| | | chartOptions: ['T+N', 'T+L', '真实值'], |
| | | checkedItemData: [], |
| | | isMultipleYRadio: '单坐标轴', |
| | | isMultipleY: false, |
| | | }) |
| | | |
| | | const repair = async (rows) => { |
| | | const params = reactive({ |
| | | outIds: rows.outIds, |
| | | startTime: rows.startTime, |
| | | endTime: rows.endTime, |
| | | random: rows.random, |
| | | }) |
| | | |
| | | const result = await McsApi.repair(params); |
| | | if (result.code === 0) { |
| | | this.$alert('数据修复成功', '提示', { |
| | | confirmButtonText: '确定', |
| | | callback: () => { |
| | | this.getList(); |
| | | } |
| | | }); |
| | | } else { |
| | | this.$message.error(`数据修复失败`); |
| | | } |
| | | } |
| | | /** 查询列表 */ |
| | | const getList = async () => { |
| | | loading1.value = true |
| | | try { |
| | | if (!formData.value.chartCheck) { |
| | | formData.value.chartCheck = ['真实值'] |
| | | } |
| | | let chartCheckArray = formData.value.chartCheck; |
| | | if (!formData.value.checkedItemData || formData.value.checkedItemData.length == 0) { |
| | | return; |
| | | } |
| | | let outIds = formData.value.checkedItemData.map(item => { |
| | | return item.id |
| | | }) |
| | | const params = reactive({ |
| | | outIds: outIds, |
| | | predictTime: formData.value.predictTime, |
| | | startTime: formData.value.startTime, |
| | | endTime: formData.value.endTime |
| | | }) |
| | | const data = await McsApi.getPreDataCharts(params) |
| | | const list = await McsApi.getPreDataMissDataList(params) |
| | | this.list = list |
| | | formData.value.predictTime = data.predictTime; |
| | | formData.value.startTime = data.startTime |
| | | formData.value.endTime = data.endTime |
| | | |
| | | let xAxisData = data.categories; |
| | | let yAxisData = []; |
| | | let offset = 0; |
| | | let yAxisIndex = 0; |
| | | let legendData = []; |
| | | let yMaxArr = []; |
| | | let seriesData = []; |
| | | seriesData.push({ |
| | | name: '', |
| | | data: [null], |
| | | type: 'line', |
| | | smooth: true, |
| | | color: 'green', |
| | | markLine: { |
| | | silent: true, |
| | | lineStyle: { |
| | | color: '#32a487', |
| | | width: 2 |
| | | }, |
| | | data: [{ |
| | | xAxis: formData.value.predictTime |
| | | }], |
| | | label: { |
| | | normal: { |
| | | formatter: formData.value.predictTime |
| | | } |
| | | }, |
| | | symbol: ['circle', 'none'], |
| | | }, |
| | | }); |
| | | itemDataObject.value = {} |
| | | for (let i = 0; i < data.dataViewList.length; i++) { |
| | | let dataView = data.dataViewList[i] |
| | | itemDataObject.value[dataView.outId] = dataView; |
| | | let maxValue = dataView.maxValue; |
| | | let minValue = dataView.minValue; |
| | | yAxisIndex = formData.value.isMultipleY ? i : 0; |
| | | let yMax = maxValue; |
| | | if (maxValue < 0) { |
| | | maxValue = 1; |
| | | } else if (maxValue < 10) { |
| | | yMax = (Math.ceil(maxValue * 11) / 10).toFixed(1); |
| | | } else if (maxValue < 100) { |
| | | yMax = (Math.ceil(maxValue * 1.1 / 5) * 5); |
| | | } else { |
| | | yMax = (Math.ceil(maxValue * 1.1 / 10) * 10); |
| | | } |
| | | yMaxArr.push(yMax); |
| | | let yMin = minValue; |
| | | if (minValue >= 0) { |
| | | yMin = 0; |
| | | } else if (minValue > -10) { |
| | | yMin = (Math.floor(minValue * 11) / 10).toFixed(1); |
| | | } else if (minValue > -100) { |
| | | yMin = (Math.floor(minValue * 1.1 / 5) * 5); |
| | | } else { |
| | | yMin = (Math.floor(minValue * 1.1 / 10) * 10); |
| | | } |
| | | yAxisData.push({ |
| | | type: 'value', |
| | | name: "", |
| | | min: yMin, |
| | | max: yMax, |
| | | position: 'left', |
| | | offset: offset, |
| | | splitLine: { |
| | | show: false |
| | | }, |
| | | axisLine: { |
| | | show: true, |
| | | lineStyle: {} |
| | | }, |
| | | axisLabel: { |
| | | formatter: '{value}' |
| | | } |
| | | }) |
| | | offset = offset + 40 |
| | | if (chartCheckArray.indexOf('真实值') !== -1) { |
| | | let legendName = dataView.resultName + '(真实)'; |
| | | legendData.push(legendName); |
| | | seriesData.push({ |
| | | name: legendName, |
| | | data: dataView.realData || [], |
| | | type: 'line', |
| | | yAxisIndex: yAxisIndex, |
| | | showSymbol: false, |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 2 |
| | | } |
| | | }); |
| | | } |
| | | if (chartCheckArray.indexOf('T+N') !== -1) { |
| | | let legendName = dataView.resultName + '(T+N)'; |
| | | seriesData.push({ |
| | | name: legendName, |
| | | data: dataView.preDataN || [], |
| | | type: 'line', |
| | | yAxisIndex: yAxisIndex, |
| | | showSymbol: false, |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 2 |
| | | } |
| | | }); |
| | | } |
| | | if (chartCheckArray.indexOf('T+L') !== -1) { |
| | | let legendName = dataView.resultName + '(T+L)'; |
| | | legendData.push(legendName); |
| | | seriesData.push({ |
| | | name: legendName, |
| | | data: dataView.preDataL || [], |
| | | type: 'line', |
| | | showSymbol: false, |
| | | connectNulls: true, |
| | | yAxisIndex: yAxisIndex, |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 2 |
| | | } |
| | | }); |
| | | } |
| | | if (chartCheckArray.indexOf('当时') !== -1) { |
| | | let legendName = dataView.resultName + '(当时)'; |
| | | legendData.push(legendName); |
| | | seriesData.push({ |
| | | name: legendName, |
| | | data: dataView.curData || [], |
| | | type: 'line', |
| | | yAxisIndex: yAxisIndex, |
| | | showSymbol: false, |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 2 |
| | | } |
| | | }); |
| | | } |
| | | if (chartCheckArray.indexOf('调整值') !== -1) { |
| | | let legendName = dataView.resultName + '(调整值)'; |
| | | legendData.push(legendName); |
| | | seriesData.push({ |
| | | name: legendName, |
| | | data: dataView.adjData || [], |
| | | type: 'line', |
| | | yAxisIndex: yAxisIndex, |
| | | showSymbol: false, |
| | | connectNulls: true, |
| | | smooth: true, |
| | | lineStyle: { |
| | | width: 2, |
| | | type: 'dashed' |
| | | } |
| | | }); |
| | | } |
| | | } |
| | | //如果最大值相差不大,改成一致大小 |
| | | if (yMaxArr.length > 1) { |
| | | let max = Math.max.apply(null, yMaxArr); |
| | | let min = Math.min.apply(null, yMaxArr); |
| | | if (Math.abs((max - min) / max) <= 0.2) { |
| | | for (let i = 0; i < yAxisData.length; i++) { |
| | | yAxisData[i].max = max; |
| | | } |
| | | } |
| | | } |
| | | myChart = echarts.init(dataAnalysisChart.value); |
| | | let option = { |
| | | title: { |
| | | text: '' |
| | | }, |
| | | tooltip: { |
| | | trigger: 'axis' |
| | | }, |
| | | legend: { |
| | | show: true, |
| | | data: legendData, |
| | | top: 10 |
| | | }, |
| | | grid: { |
| | | top: '20%', |
| | | left: '3%', |
| | | right: '6%', |
| | | bottom: '3%', |
| | | containLabel: true |
| | | }, |
| | | xAxis: { |
| | | type: 'category', |
| | | boundaryGap: false, |
| | | data: xAxisData |
| | | }, |
| | | yAxis: formData.value.isMultipleY ? yAxisData : { |
| | | type: 'value', |
| | | splitLine: {show: false}, |
| | | axisLine: {show: true} |
| | | }, |
| | | dataZoom: [ |
| | | { |
| | | type: 'inside', |
| | | start: 0, |
| | | end: 100 |
| | | }, |
| | | { |
| | | start: 0, |
| | | end: 10 |
| | | } |
| | | ], |
| | | series: seriesData |
| | | } |
| | | myChart.clear() |
| | | myChart.setOption(option) |
| | | } finally { |
| | | loading1.value = false |
| | | } |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getPreItemTree() |
| | | }) |
| | | |
| | | async function getPreItemTree() { |
| | | treeData.value = await McsApi.getPredictItemTree() |
| | | } |
| | | |
| | | function leftSearchDataByRange() { |
| | | let mins = getRangeMins(); |
| | | let startTime = formData.value.startTime; |
| | | let endTime = formData.value.endTime; |
| | | let predictTime = formData.value.predictTime; |
| | | if (predictTime) { |
| | | predictTime = getYMDHMS(new Date(predictTime) - 1000 * 60 * mins); |
| | | formData.value.predictTime = predictTime; |
| | | } |
| | | if (startTime) { |
| | | startTime = getYMDHMS(new Date(startTime) - 1000 * 60 * mins); |
| | | formData.value.startTime = startTime; |
| | | } |
| | | if (endTime) { |
| | | endTime = getYMDHMS(new Date(endTime) - 1000 * 60 * mins); |
| | | formData.value.endTime = endTime; |
| | | } |
| | | getList(); |
| | | } |
| | | |
| | | function getRangeMins() { |
| | | let result: string | number = 0; |
| | | if (formData.value.startTime && formData.value.endTime) { |
| | | let startStamp = new Date(formData.value.startTime).getTime(); |
| | | let endStamp = new Date(formData.value.endTime).getTime(); |
| | | let queryStep = ((endStamp - startStamp) / (1000 * 60)).toFixed(0); |
| | | result = queryStep >= 0 ? queryStep : 0; |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | function onCheckTree(data, checked, indeterminate) { |
| | | formData.value.checkedItemData = []; |
| | | if (checked.checkedNodes) { |
| | | formData.value.checkedItemData = [...checked.checkedNodes] |
| | | } |
| | | debounce(getList, 1000); |
| | | } |
| | | |
| | | function debounce(func, wait) { |
| | | let args = []; |
| | | if (timer.value) { |
| | | clearTimeout(timer.value); |
| | | } |
| | | timer.value = setTimeout(() => { |
| | | func.apply(this, args); |
| | | timer.value = null; |
| | | }, wait) |
| | | } |
| | | |
| | | function rightSearchDataByRange() { |
| | | let mins = getRangeMins(); |
| | | let startTime = formData.value.startTime; |
| | | let endTime = formData.value.endTime; |
| | | let predictTime = formData.value.predictTime; |
| | | if (predictTime) { |
| | | predictTime = getYMDHMS(new Date(predictTime) - 0 + 1000 * 60 * mins); |
| | | formData.value.predictTime = predictTime; |
| | | } |
| | | if (startTime) { |
| | | startTime = getYMDHMS(new Date(startTime) - 0 + 1000 * 60 * mins); |
| | | formData.value.startTime = startTime; |
| | | } |
| | | if (endTime) { |
| | | endTime = getYMDHMS(new Date(endTime) - 0 + 1000 * 60 * mins); |
| | | formData.value.endTime = endTime; |
| | | } |
| | | getList(); |
| | | } |
| | | </script> |
| | | <style scoped> |
| | | .el-form-item { |
| | | margin-bottom: 0 !important; |
| | | } |
| | | |
| | | .his-body-chart { |
| | | height: 100%; |
| | | border: 1px solid lightgray; |
| | | padding: 10px; |
| | | } |
| | | |
| | | .his-body-tree { |
| | | height: 100%; |
| | | border: 1px solid lightgray; |
| | | padding: 10px; |
| | | } |
| | | |
| | | .his-body-middle{ |
| | | width: 40%; |
| | | height: 100%; |
| | | padding: 10px 10px 0 0; |
| | | } |
| | | .his-body-right { |
| | | width: 40%; |
| | | height: 100%; |
| | | padding-top: 10px; |
| | | } |
| | | .his-body-left { |
| | | width: 20%; |
| | | height: 100%; |
| | | padding: 10px 10px 0 0; |
| | | } |
| | | |
| | | .his-body { |
| | | width: 100%; |
| | | height: calc(calc(100vh - 68px - 38px - 160px)); |
| | | display: flex; |
| | | flex-direction: row; |
| | | justify-content: flex-start; |
| | | align-content: flex-start; |
| | | } |
| | | </style> |