dongyukun
2025-04-24 5eda9aff304ddc16077cb6e48a9e89a1a695146d
src/views/model/pre/analysis/index.vue
@@ -1,87 +1,104 @@
<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 :inline="true" :model="formData" label-width="70px">
        <el-form-item label="开始时间">
          <el-date-picker
              size="mini"
              v-model="formData.startTime"
              type="datetime"
              placeholder="选择日期时间"/>
            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
              size="mini"
              v-model="formData.endTime"
              type="datetime"
              placeholder="选择日期时间"/>
            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 label="预测时间">
          <el-date-picker
              size="mini"
              v-model="formData.predictTime"
              type="datetime"
              placeholder="选择日期时间"/>
            v-model="formData.predictTime"
            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-input-number size="mini" v-model="formData.predictFreq" controls-position="right" :min="1"
          <el-input-number v-model="formData.predictFreq" controls-position="right"
                           :min="1"
                           :max="10"/>
        </el-form-item>
        <el-form-item>
          <el-button-group>
            <el-button size="mini" type="primary" plain :icon="ArrowLeft"
                       v-loading="loading1" @click="leftSearchDataByRange()"/>
            <el-button size="mini" type="primary" plain :icon="Search"
                       v-loading="loading1" @click="getList()">查询</el-button>
            <el-button size="mini" type="primary" plain :icon="ArrowRight"
                       v-loading="loading1" @click="rightSearchDataByRange()"/>
            <el-button type="primary" plain :icon="DArrowLeft"
                       :loading="loading1" @click="leftSearchDataByRange()"/>
            <el-button type="primary" plain :icon="Search"
                       :loading="loading1" @click="getList()">查询
            </el-button>
            <el-button type="primary" plain :icon="DArrowRight"
                       :loading="loading1" @click="rightSearchDataByRange()"/>
          </el-button-group>
        </el-form-item>
        <el-form-item>
          <el-button-group>
            <el-button type="primary" plain :icon="CaretLeft"
                       @click="playChart(true)"/>
            <el-button type="primary" plain :icon="VideoPlay" v-if="!isPlay"
                       @click="playHandle('play')"/>
            <el-button type="primary" plain :icon="VideoPause" v-if="isPlay"
                       @click="playHandle('pause')"/>
            <el-button type="primary" plain :icon="CaretRight"
                       @click="playChart(false)"/>
          </el-button-group>
        </el-form-item>
        <div class="his-body">
          <div class="his-body-left">
            <div class="his-body-tree">
              <el-input
                v-model="filterText"
                class="mb-2"
                placeholder="Filter"
              />
              <el-tree
                  :data="treeData"
                  show-checkbox
                  node-key="id"
                  ref="tree"
                  highlight-current
                  :props="defaultProps"
                  @check="onCheckTree"/>
                :data="treeData"
                show-checkbox
                node-key="id"
                ref="treeRef"
                highlight-current
                check-strictly
                :filter-node-method="filterNode"
                @check="onCheckTree"/>
            </div>
          </div>
          <div class="his-body-right">
            <div class="his-body-chart">
              <el-form :inline="true" :model="calRateForm" :rules="formRules" ref="calRateForm" label-width="108px">
              <el-form :inline="true" :model="calRateForm" :rules="formRules" ref="calRateFormRef"
                       label-width="108px">
                <el-row>
                  <el-col :span="6" >
                    <el-form-item label="预测项" prop="calItem" style="width: 90%">
                      <el-select v-model="calRateForm.calItem" @change="calItemBaseVale" placeholder="请选择">
                        <el-option
                            v-for="item in formData.checkedItemData"
                            :key="item.id"
                            :label="item.label"
                            :value="item.id"/>
                      </el-select>
                    </el-form-item>
                  </el-col>
                  <el-col :span="6">
<!--                  <el-col :span="6" style="display: flex;align-items: center;justify-content: center">-->
<!--                    <span>预测项:{{formData.checkedItemData?.label || ''}}</span>-->
<!--                  </el-col>-->
                  <el-col :span="8">
                    <el-form-item label="精准度偏差" prop="IN_DEVIATION">
                      <el-input-number size="mini" v-model="calRateForm.IN_DEVIATION" controls-position="right" :min="1"
                                       :max="10"/>
                      <el-input-number size="small" v-model="calRateForm.IN_DEVIATION"
                                       controls-position="right" :min="0"/>
                    </el-form-item>
                  </el-col>
                  <el-col :span="6">
                  <el-col :span="8">
                    <el-form-item label="不可信率偏差" prop="OUT_DEVIATION">
                      <el-input-number size="mini" v-model="calRateForm.OUT_DEVIATION" controls-position="right"
                                       :min="1"
                                       :max="20"/>
                      <el-input-number size="small" v-model="calRateForm.OUT_DEVIATION"
                                       controls-position="right"
                                       :min="1"/>
                    </el-form-item>
                  </el-col>
                  <el-col :span="4">
                  <el-col :span="8">
                    <el-form-item>
                      <el-button size="mini" type="primary" plain :loading="loading2" @click="calAccuracyRate">计算精准度
                      <el-button size="small" type="primary" plain :loading="loading2"
                                 @click="calAccuracyRate">计算精准度
                      </el-button>
                    </el-form-item>
                  </el-col>
@@ -89,111 +106,1177 @@
                <el-row>
                  <el-col :span="4">
                    <el-form-item label="精准度:">
                      {{calRateForm.IN_ACCURACY_RATE}}%
                      {{ calRateForm.IN_ACCURACY_RATE }}%
                    </el-form-item>
                  </el-col>
                  <el-col :span="4">
                    <el-form-item label="预测平均值:">
                      {{calRateForm.itemPreAvg}}
                      {{ calRateForm.itemPreAvg }}
                    </el-form-item>
                  </el-col>
                  <el-col :span="4">
                    <el-form-item label="预测最大值:">
                      {{calRateForm.itemPreMax}}
                      {{ calRateForm.itemPreMax }}
                    </el-form-item>
                  </el-col>
                  <el-col :span="4">
                    <el-form-item label="预测最小值:">
                      {{calRateForm.itemPreMin}}
                      {{ calRateForm.itemPreMin }}
                    </el-form-item>
                  </el-col>
                  <el-col :span="4">
                    <el-form-item label="预测累积量:">
                      {{calRateForm.preCumulant}}
                      {{ calRateForm.preCumulant }}
                    </el-form-item>
                  </el-col>
                  <el-col :span="4">
                    <el-form-item label="平均绝对误差:" label-width="110px">
                      {{ calRateForm.deviation }}
                    </el-form-item>
                  </el-col>
                </el-row>
                <el-row>
                  <el-col :span="4">
                    <el-form-item label="不可信率:">
                      {{calRateForm.OUT_ACCURACY_RATE}}%
                      {{ calRateForm.OUT_ACCURACY_RATE }}%
                    </el-form-item>
                  </el-col>
                  <el-col :span="4">
                    <el-form-item label="真实平均值:">
                      {{calRateForm.itemAvg}}
                      {{ calRateForm.itemAvg }}
                    </el-form-item>
                  </el-col>
                  <el-col :span="4">
                    <el-form-item label="真实最大值:">
                      {{calRateForm.itemMax}}
                      {{ calRateForm.itemMax }}
                    </el-form-item>
                  </el-col>
                  <el-col :span="4">
                    <el-form-item label="真实最小值:">
                      {{calRateForm.itemMin}}
                      {{ calRateForm.itemMin }}
                    </el-form-item>
                  </el-col>
                  <el-col :span="4">
                    <el-form-item label="真实累积量:">
                      {{calRateForm.realCumulant}}
                      {{ calRateForm.realCumulant }}
                    </el-form-item>
                  </el-col>
                  <el-col :span="4">
                    <el-form-item label="累积量平均绝对误差:" label-width="152px">
                      {{ calRateForm.deviationCumulant }}
                    </el-form-item>
                  </el-col>
                </el-row>
              </el-form>
              <el-form :inline="true" :model="formData" label-width="100px">
                <el-row>
                  <el-col :span="12">
                  <el-col :span="18">
                    <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 v-for="item in formData.chartOptions" :label="item"
                                     :key="item">{{ item }}
                        </el-checkbox>
                      </el-checkbox-group>
                    </el-form-item>
                  </el-col>
                  <el-col :span="6">
                    <el-form-item>
                      <el-radio v-model="formData.isMultipleY" :label="false" @input="onChangeMultipleY">单坐标轴</el-radio>
                      <el-radio v-model="formData.isMultipleY" :label="true" @input="onChangeMultipleY">多坐标轴</el-radio>
                      <el-radio v-model="formData.isMultipleY" :label="false"
                                @input="onChangeMultipleY">单坐标轴
                      </el-radio>
                      <el-radio v-model="formData.isMultipleY" :label="true"
                                @input="onChangeMultipleY">多坐标轴
                      </el-radio>
                    </el-form-item>
                  </el-col>
                </el-row>
              </el-form>
              <div id="data-analysis" style="height: 500px;"></div>
              <div style="width: 100%;height: 700px;display: flex;flex-direction: row;">
                <div style="height: 100%;width: 80%">
                  <div ref="dataAnalysisChart" style="height: 50%;width: 100%"></div>
                  <div ref="influenceFactorChart" style="height: 50%;width: 100%"></div>
                </div>
                <div style="width: 20%;height: 100%;">
                  <div style="display: flex;flex-direction: row;align-items: center;margin-bottom: 4px;">
                    <div style="font-weight: bold;font-size: 14px">影响因素:</div>
                    <div style="width: calc(100% - 80px);">
                      <el-select v-model="influenceFactor" placeholder="请选择" size="small" @change="changeInfluenceFactor">
                        <el-option
                          v-for="(influenceFactor,index) in influenceFactorList"
                          :key="index"
                          :label="influenceFactor.factorOutputName"
                          :value="influenceFactor.factorOutputId"
                        />
                      </el-select>
                    </div>
                  </div>
                  <div class="chart-foot-table p-2" style="width: 100%;height: calc(100% - 20px);overflow-x: hidden;overflow-y: auto;">
                    <div style="display: flex;flex-direction: column;align-items: center;margin-bottom: 4px;">
                      <span>影响时间</span>
                      <span style="font-size: 16px;font-weight: bold">{{influenceFactorResultTime}}</span>
                    </div>
                    <div v-for="(result, index) in influenceFactorResult" :key="index" style="display: flex;flex-direction: row">
                      <span>{{result.factorOutputName}}:</span>
                      <span>{{result.value}}</span>
                    </div>
                  </div>
                </div>
              </div>
              <div class="chart-foot">
                <div class="chart-foot-content">
                  <h3 class="chart-foot-title">预警信息</h3>
                  <div class="chart-foot-table">
                    <el-table :data="alarmList" style="width: 100%" v-loading="loadingAlarm" height="100px">
                      <el-table-column prop="content" header-align="center" align="left" label="消息内容" min-width="240" />
                      <el-table-column prop="alarmType" label="预警类型" header-align="center" align="left" min-width="150"/>
                      <el-table-column prop="alarmTime" label="预警时间" header-align="center" align="left" min-width="150"/>
                    </el-table>
                  </div>
                </div>
                <div class="chart-foot-content">
                  <h3 class="chart-foot-title">调度建议</h3>
                  <div class="chart-foot-table">
                    <el-table :data="suggestList" style="width: 100%" v-loading="loadingAdjust" height="100px">
                      <el-table-column
                        prop="scheduleTime"
                        label="调度时间"
                        header-align="center"
                        align="left"
                        min-width="160"
                      />
                      <el-table-column
                        prop="content"
                        label="内容"
                        min-width="300"
                        header-align="center" align="left"
                      />
                      <el-table-column
                        prop="adjustValue"
                        label="调整值"
                        header-align="center"
                        align="center"
                        min-width="100"
                      />
                    </el-table>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </el-form>
    </div>
  </el-card>
</template>
<script lang="ts" setup>
  import {getYMDHMS} from "@/utils/dateUtil"
  import * as CategoryApi from "@/api/data/ind/category";
  import * as DmModule from '@/api/model/pre/dm'
  import * as ItemApi from "@/api/data/ind/item/item";
  import * as MmPredictItem from '@/api/model/pre/predict'
  import * as echarts from "echarts";
  import { onMounted, ref } from 'vue';
  import { Search, ArrowLeft, ArrowRight,} from '@element-plus/icons-vue'
import {getYMDHMS,formatToDateTime} from "@/utils/dateUtil"
import * as McsApi from '@/api/model/mcs'
import * as influenceFactorApi from '@/api/model/pre/influenceFactor/influenceFactorApi'
import * as AlarmMessageApi from '@/api/model/pre/alarm/message'
import * as ScheSuggestApi from '@/api/model/sche/suggest'
import * as echarts from "echarts";
import {Search, DArrowLeft, DArrowRight, VideoPlay, VideoPause, CaretLeft, CaretRight} from '@element-plus/icons-vue'
import {lighten} from "@/utils/color";
  defineOptions({name: 'AnalysisformData'})
defineOptions({name: 'AnalysisformData'})
  const message = useMessage() // 消息弹窗
  const { t } = useI18n() // 国际化
  const dataCategoryList = ref([] as CategoryApi.IndItemCategoryVO[])
  const loading1 = ref(false) // 列表的加载中
  const loading2 = ref(false) // 列表的加载中
  const total = ref(0) // 列表的总页数
  const list = ref([]) // 字典表格数据
  const queryParams = reactive({
    pageNo: 1,
    pageSize: 10,
    itemno: '',
    itemname: '',
const message = useMessage() // 消息弹窗
const {t} = useI18n() // 国际化
const loading1 = ref(false) // 列表的加载中
const loading2 = ref(false) // 列表的加载中
const total = ref(0) // 列表的总页数
const list = ref([]) // 字典表格数据
let formData = ref({
  rangeDate: '',
  startTime: '',
  endTime: '',
  predictTime: '',
  predictTimeStr: '',
  startTimeStr: '',
  endTimeStr: '',
  predictTimeStamp: 0,
  startTimeStamp: 0,
  endTimeStamp: 0,
  currentStamp: '',
  currentStamp60: '',
  predictStamp: '',
  chartCheck: ['T+L', '真实值'],
  chartOptions: ['T+N', 'T+L','T+L(未调整)', '当时', '真实值', '调整值', '预测累计', '真实累计'],
  checkedItemData: undefined,
  backItem: '',
  backValue: 0,
  backCoe: 1,
  preCumulant: 0,
  realCumulant: 0,
  queryStep: 2,
  isMultipleYRadio: '单坐标轴',
  isMultipleY: false,
  predictFreq: 2,
})
const calRateFormRef = ref()
const calRateForm = ref({
  calItem: undefined,
  IN_DEVIATION: 10,
  OUT_DEVIATION: 50,
  IN_ACCURACY_RATE: 0,
  OUT_ACCURACY_RATE: 0,
  itemAvg: 0,
  itemMax: 0,
  itemMin: 0,
  itemPreAvg: 0,
  itemPreMax: 0,
  itemPreMin: 0,
  preCumulant: 0,
  realCumulant: 0,
  deviation: 0, //平均绝对误差
  deviationCumulant: 0, //累积量平均绝对误差
})
let itemData = ref({
  currentTreeList: [],
  chart: {},
  option: {}
})
const treeData = ref([])
const itemDataObject = ref()
const timer = ref()
const isPlay = ref(false)
const alarmList = ref([])
const suggestList = ref([])
const loadingAlarm = ref(false)
const loadingAdjust = ref(false)
// 影响因素结果列表
const influenceFactorResultList = ref([])
// 影响因素列表
const influenceFactorList = ref([])
// 选中影响因素
const influenceFactor = ref()
const formRules = reactive({
  IN_DEVIATION: [{required: true, message: '精准度偏差不能为空', trigger: 'blur'}],
  OUT_DEVIATION: [{required: true, message: '不可信率偏差不能为空', trigger: 'blur'}],
})
// 树形过滤
const filterText = ref('')
const treeRef = ref()
watch(filterText, (val) => {
  treeRef.value!.filter(val)
})
const filterNode = (value: string, data) => {
  if (!value) return true
  return data.label.includes(value)
}
let xAxisData = []
/** 查询列表 */
const getList = async (isClear = true) => {
  loading1.value = true
  try {
    if (!formData.value.chartCheck) {
      formData.value.chartCheck = ['真实值']
    }
    let chartCheckArray = formData.value.chartCheck;
    if (!formData.value.checkedItemData) {
      itemData.value.option = {};
      return;
    }
    let outIds = [formData.value.checkedItemData.id]
    const params = reactive({
      outIds: outIds,
      predictTime: formData.value.predictTime,
      startTime: formData.value.startTime,
      endTime: formData.value.endTime
    })
    const data = await McsApi.getPreDataCharts(params)
    formData.value.predictTime = data.predictTime;
    formData.value.startTime = data.startTime
    formData.value.endTime = data.endTime
    // 默认影响时间
    changeInfluenceFactorTime(data.predictTime);
    // 获取影响因素结果列表
    influenceFactorResultList.value = await influenceFactorApi.getResultList({
      outIds: outIds,
      startTime: data.startTime,
      endTime: data.endTime
    })
    // 获取影响因素结果列表
    influenceFactorList.value = await influenceFactorApi.getListByOutId(formData.value.checkedItemData.id)
    if (influenceFactorList.value && influenceFactorList.value.length > 0) {
      // 根据factorOutputId去重,因为不同的统计规则会有重复的影响因素
      influenceFactorList.value = Array.from(new Map(influenceFactorList.value.map(item => [item.factorOutputId, item])).values());
      // 默认选中第一个影响因素
      influenceFactor.value = influenceFactorList.value?.[0]?.factorOutputId
      getInfluenceFactorChart(influenceFactorList.value?.[0]?.factorOutputId)
    }
    const paramsAlarm = reactive({
      outIds: outIds,
      predictTime: formData.value.predictTime
    })
    loadingAlarm.value = true
    alarmList.value = await AlarmMessageApi.getListByOut(paramsAlarm)
    loadingAlarm.value = false
    loadingAdjust.value = true
    suggestList.value = await ScheSuggestApi.getListByOut(paramsAlarm)
    loadingAdjust.value = false
    xAxisData = data.categories;
    let defaultYAxis = [
      {
        type: 'value',
        name: "累计值",
        splitLine: {show: false},
        axisLine: {show: true},
        position: 'right'
      },
      {
        type: 'value',
        name: "",
        splitLine: {show: false},
        axisLine: {show: true},
        position: 'left'
      }
    ];
    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 = {}
    yAxisData.push({
      type: 'value',
      name: "累计值",
      position: 'right',
      splitLine: {
        show: false
      },
      axisLine: {
        show: true,
        lineStyle: {}
      },
      axisLabel: {
        formatter: '{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) + 1;
      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: false,
          lineStyle: {
            width: 2
          }
        });
      }
      if (chartCheckArray.indexOf('T+N') !== -1) {
        let legendName = dataView.resultName + '(T+N)';
        legendData.push(legendName);
        seriesData.push({
          name: legendName,
          data: dataView.preDataN || [],
          type: 'line',
          yAxisIndex: yAxisIndex,
          showSymbol: false,
          smooth: false,
          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: false,
          lineStyle: {
            width: 2
          }
        });
      }
      if (chartCheckArray.indexOf('T+L(未调整)') !== -1) {
        let legendName = dataView.resultName + '(T+L(未调整))';
        legendData.push(legendName);
        seriesData.push({
          name: legendName,
          data: dataView.preDataLOriginal
            || [],
          type: 'line',
          showSymbol: false,
          connectNulls: true,
          yAxisIndex: yAxisIndex,
          smooth: false,
          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: true,
          smooth: false,
          lineStyle: {
            width: 3
          }
        });
      }
      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: false,
          lineStyle: {
            width: 2,
            type: 'dashed'
          }
        });
      }
      if (chartCheckArray.indexOf('预测累计') !== -1) {
        let legendName = dataView.resultName + '(预测累计)';
        legendData.push(legendName);
        let seriesLeiJiData = []
        if (dataView.cumulantPreData) {
          seriesLeiJiData = dataView.cumulantPreData
        }
        seriesData.push({
          name: legendName,
          data: seriesLeiJiData,
          type: 'line',
          yAxisIndex: 0,
          showSymbol: false,
          connectNulls: true,
          smooth: false,
          lineStyle: {
            width: 2,
            type: 'dashed'
          }
        });
      }
      if (chartCheckArray.indexOf('真实累计') !== -1) {
        let legendName = dataView.resultName + '(真实累计)';
        legendData.push(legendName);
        let seriesLeiJiData = []
        if (dataView.cumulantRealData) {
          seriesLeiJiData = dataView.cumulantRealData
        }
        seriesData.push({
          name: legendName,
          data: seriesLeiJiData,
          type: 'line',
          yAxisIndex: 0,
          showSymbol: false,
          connectNulls: true,
          smooth: false,
          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;
        }
      }
    }
    let option = {
      title: {
        text: ''
      },
      tooltip: {
        trigger: 'axis'
      },
      toolbox: {
        show: true,
        feature: {
          saveAsImage: {}
        }
      },
      legend: {
        show: true,
        data: legendData,
        top: 10
      },
      grid: {
        top: '20%',
        left: '5%',
        right: '5%',
        bottom: '3%',
        containLabel: true
      },
      xAxis: {
        type: 'category',
        boundaryGap: false,
        data: xAxisData
      },
      yAxis: formData.value.isMultipleY ? yAxisData : defaultYAxis,
      dataZoom: [
        {
          type: 'inside',
          start: 0,
          end: 100
        },
        {
          start: 0,
          end: 10
        }
      ],
      series: seriesData
    }
    if (isClear) {
      myChart.clear()
    }
    myChart.setOption(option)
  } finally {
    loading1.value = false
  }
  calItemBaseVale()
}
// 查询影响因素chart
const getInfluenceFactorChart = async (outId) => {
  loading1.value = true
  try {
    let outIds = [outId]
    const params = reactive({
      outIds: outIds,
      predictTime: formData.value.predictTime,
      startTime: formData.value.startTime,
      endTime: formData.value.endTime
    })
    const data = await McsApi.getPreDataCharts(params)
    if (!data?.dataViewList || data.dataViewList.length === 0) {
      myInfluenceFactorChart.clear()
      return
    }
    xAxisData = data.categories;
    let defaultYAxis = [
      {
        type: 'value',
        name: "累计值",
        splitLine: {show: false},
        axisLine: {show: true},
        position: 'right'
      },
      {
        type: 'value',
        name: "",
        splitLine: {show: false},
        axisLine: {show: true},
        position: 'left'
      }
    ];
    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 = {}
    yAxisData.push({
      type: 'value',
      name: "累计值",
      position: 'right',
      splitLine: {
        show: false
      },
      axisLine: {
        show: true,
        lineStyle: {}
      },
      axisLabel: {
        formatter: '{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) + 1;
      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
      //真实值
      legendData.push(dataView.resultName + '(真实)');
      seriesData.push({
        name: dataView.resultName + '(真实)',
        data: dataView.realData || [],
        type: 'line',
        yAxisIndex: yAxisIndex,
        showSymbol: false,
        smooth: false,
        lineStyle: {
          width: 2
        }
      });
      //T+L
      legendData.push(dataView.resultName + '(T+L)');
      seriesData.push({
        name: dataView.resultName + '(T+L)',
        data: dataView.preDataL || [],
        type: 'line',
        showSymbol: false,
        connectNulls: true,
        yAxisIndex: yAxisIndex,
        smooth: false,
        lineStyle: {
          width: 2
        }
      });
      // 当时
      legendData.push(dataView.resultName + '(当时)');
      seriesData.push({
        name: dataView.resultName + '(当时)',
        data: dataView.curData || [],
        type: 'line',
        yAxisIndex: yAxisIndex,
        showSymbol: true,
        smooth: false,
        lineStyle: {
          width: 3
        }
      });
      //预测累计
      legendData.push(dataView.resultName + '(预测累计)');
      seriesData.push({
        name: dataView.resultName + '(预测累计)',
        data: dataView.cumulantPreData || [],
        type: 'line',
        yAxisIndex: 0,
        showSymbol: false,
        connectNulls: true,
        smooth: false,
        lineStyle: {
          width: 2,
          type: 'dashed'
        }
      });
      // 真实累计
      legendData.push(dataView.resultName + '(真实累计)');
      seriesData.push({
        name: dataView.resultName + '(真实累计)',
        data: dataView.cumulantRealData || [],
        type: 'line',
        yAxisIndex: 0,
        showSymbol: false,
        connectNulls: true,
        smooth: false,
        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;
        }
      }
    }
    let option = {
      title: {
        text: ''
      },
      tooltip: {
        trigger: 'axis'
      },
      toolbox: {
        show: true,
        feature: {
          saveAsImage: {}
        }
      },
      legend: {
        show: true,
        data: legendData,
        top: 10
      },
      grid: {
        top: '20%',
        left: '5%',
        right: '5%',
        bottom: '3%',
        containLabel: true
      },
      xAxis: {
        type: 'category',
        boundaryGap: false,
        data: xAxisData
      },
      yAxis: formData.value.isMultipleY ? yAxisData : defaultYAxis,
      dataZoom: [
        {
          type: 'inside',
          start: 0,
          end: 100
        },
        {
          start: 0,
          end: 10
        }
      ],
      series: seriesData
    }
    myInfluenceFactorChart.clear()
    myInfluenceFactorChart.setOption(option)
  } finally {
    loading1.value = false
  }
}
onMounted(() => {
  initChart()
  resetForm()
  getPreItemTree()
})
const dataAnalysisChart = ref();
const influenceFactorChart = ref();
let myChart = ref({});
let myInfluenceFactorChart = ref({});
function initChart() {
  myChart = echarts.init(dataAnalysisChart.value)
  myInfluenceFactorChart = echarts.init(influenceFactorChart.value)
  // 监听点击事件
  myChart.getZr().on('click', 'series.line',function (params) {
    var pointInPixel = [params.offsetX, params.offsetY];
    var pointInData = myChart.convertFromPixel('grid', pointInPixel);
    const time = xAxisData[pointInData[0]];
    changeInfluenceFactorTime(time)
  });
}
let influenceFactorResult = ref([])
let influenceFactorResultTime = ref('')
// 影响因素时间改变
function changeInfluenceFactorTime(time) {
  if (time && new Date(time)?.getTime()) {
    influenceFactorResultTime.value = time
    influenceFactorResult.value = influenceFactorResultList.value?.[formData.value.checkedItemData?.id]?.filter(e => e.time === new Date(time).getTime()).sort((a, b) => b.value - a.value) || [];
  }
}// 选择影响因素
function changeInfluenceFactor(value) {
  getInfluenceFactorChart(value)
}
async function getPreItemTree() {
  treeData.value = await McsApi.getPredictItemTree()
}
function changeChartCheck(value) {
  getList(true)
}
function onChangeMultipleY() {
  getList(true)
}
function playChart(isBack = false) {
  let mins = isBack ? formData.value.predictFreq * -1 : formData.value.predictFreq
  let startTime = formData.value.startTime;
  let endTime = formData.value.endTime;
  let predictTime = formData.value.predictTime;
  if (predictTime) {
    predictTime = getYMDHMS(new Date(predictTime).getTime() + 1000 * 60 * mins);
    formData.value.predictTime = predictTime;
  }
  if (startTime) {
    startTime = getYMDHMS(new Date(startTime).getTime() + 1000 * 60 * mins);
    formData.value.startTime = startTime;
  }
  if (endTime) {
    endTime = getYMDHMS(new Date(endTime).getTime() + 1000 * 60 * mins);
    formData.value.endTime = endTime;
  }
  getList(false);
}
function playHandle(type) {
  isPlay.value = 'play' === type
  let doPlay = setInterval(function () {
    if (isPlay.value) {
      playChart()
    } else {
      clearInterval(doPlay);
    }
    if (new Date().getTime() - new Date(formData.value.predictTime).getTime() < 1000 * 60 ) {
      isPlay.value = false
      clearInterval(doPlay);
    }
  }, 1000)
}
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).getTime() - 1000 * 60 * mins);
    formData.value.predictTime = predictTime;
  }
  if (startTime) {
    startTime = getYMDHMS(new Date(startTime).getTime() - 1000 * 60 * mins);
    formData.value.startTime = startTime;
  }
  if (endTime) {
    endTime = getYMDHMS(new Date(endTime).getTime() - 1000 * 60 * mins);
    formData.value.endTime = endTime;
  }
  getList(false);
}
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) {
  // 单选
  treeRef.value.setCheckedKeys([])
  treeRef.value.setCheckedNodes([data])
  formData.value.checkedItemData = data
  calRateForm.value.calItem = data.id
  // if (checked.checkedNodes) {
  //   let cns = [...checked.checkedNodes]
  //   for (let i = 0; i < cns.length; i++) {
  //     if (cns[i].id.indexOf('-') !== -1) {
  //       continue
  //     }
  //     formData.value.checkedItemData.push(cns[i])
  //   }
  // }
  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 calItemBaseVale() {
  if (!calRateForm.value.calItem) {
    calRateForm.value.itemPreMax = 0;
    calRateForm.value.itemPreMin = 0;
    calRateForm.value.itemPreAvg = 0;
    calRateForm.value.preCumulant = 0;
    calRateForm.value.itemMax = 0;
    calRateForm.value.itemMin = 0;
    calRateForm.value.itemAvg = 0;
    calRateForm.value.realCumulant = 0;
  } else {
    let dataView = itemDataObject.value[calRateForm.value.calItem]
    calRateForm.value.itemPreMax = dataView.preMax;
    calRateForm.value.itemPreMin = dataView.preMin;
    calRateForm.value.itemPreAvg = dataView.preAvg;
    calRateForm.value.preCumulant = dataView.preCumulant;
    calRateForm.value.itemMax = dataView.hisMax;
    calRateForm.value.itemMin = dataView.hisMin;
    calRateForm.value.itemAvg = dataView.hisAvg;
    calRateForm.value.realCumulant = dataView.hisCumulant;
    calDeviation(dataView.realData,dataView.preDataL,'deviation')
    calDeviation(dataView.cumulantRealData,dataView.cumulantPreData,'deviationCumulant')
    calAccuracyRate()
  }
}
function calAccuracyRate() {
  const valid = calRateFormRef.value.validate()
  if (!valid) return
  let dataView = itemDataObject.value[calRateForm.value.calItem]
  let seriesReaData = dataView.realData;
  let seriesPreData = dataView.preDataL;
  if (seriesReaData == null || seriesPreData == null ||
    seriesReaData.length === 0 || seriesPreData.length === 0) {
    loading2.value = false;
    return;
  }
  let predictValueMap = {};
  seriesPreData.forEach(function (item) {
    predictValueMap[item[0]] = item[1];
  })
  let formData = ref({
  let pointValueMap = {};
  seriesReaData.forEach(function (item) {
    pointValueMap[item[0]] = item[1];
  })
  let inDeviation = Number(calRateForm.value.IN_DEVIATION);
  let outDeviation = Number(calRateForm.value.OUT_DEVIATION);
  if (inDeviation === 0 && outDeviation === 0) {
    loading2.value = false;
    return;
  }
  let inDeviationCount = 0;
  let outDeviationCount = 0;
  let totalCount = 0;
  for (let key in predictValueMap) {
    let predictValue = predictValueMap[key];
    let pointValue = pointValueMap[key];
    if (pointValue == null || "" === pointValue || predictValue == null || "" === predictValue) {
      continue;
    }
    let deviationAbs = (predictValue - pointValue) >= 0 ? (predictValue - pointValue) : (predictValue - pointValue) * -1;
    if (deviationAbs < inDeviation) {
      inDeviationCount = inDeviationCount + 1;
    }
    if (deviationAbs > outDeviation) {
      outDeviationCount = outDeviationCount + 1;
    }
    totalCount = totalCount + 1;
  }
  let rateIn = (inDeviationCount / totalCount * 100).toFixed(2);
  let rateOut = (outDeviationCount / totalCount * 100).toFixed(2);
  calRateForm.value.IN_ACCURACY_RATE = Number(rateIn);
  calRateForm.value.OUT_ACCURACY_RATE = Number(rateOut);
  loading2.value = false;
}
function calDeviation(realData,preDataL,key) {
  if (realData == null || preDataL == null || realData.length === 0 || preDataL.length === 0) {
    return;
  }
  const realObj = {}
  realData.map(e => realObj[e[0]] = e[1])
  let sum = 0;
  let index = 0;
  preDataL.forEach(e => {
    if (realObj[e[0]] != undefined) {
      sum += Math.abs(e[1] - realObj[e[0]])
      index++
    }
  })
  calRateForm.value[key] = Number((sum / index).toFixed(2))
}
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).getTime() + 1000 * 60 * mins);
    formData.value.predictTime = predictTime;
  }
  if (startTime) {
    startTime = getYMDHMS(new Date(startTime).getTime() + 1000 * 60 * mins);
    formData.value.startTime = startTime;
  }
  if (endTime) {
    endTime = getYMDHMS(new Date(endTime).getTime() + 1000 * 60 * mins);
    formData.value.endTime = endTime;
  }
  getList(false);
}
/** 重置表单 */
const resetForm = () => {
  formData.value = {
    rangeDate: '',
    startTime: '',
    endTime: '',
@@ -208,8 +1291,8 @@
    currentStamp60: '',
    predictStamp: '',
    chartCheck: ['T+L', '真实值'],
    chartOptions: ['T+N', 'T+L', '当时', '真实值', '调整值'],
    checkedItemData: [],
    chartOptions: ['T+N', 'T+L','T+L(未调整)', '当时', '真实值', '调整值', '预测累计', '真实累计'],
    checkedItemData: undefined,
    backItem: '',
    backValue: 0,
    backCoe: 1,
@@ -218,12 +1301,12 @@
    queryStep: 2,
    isMultipleYRadio: '单坐标轴',
    isMultipleY: false,
    predictFreq: 3,
  })
  let calRateForm = ref({
    calItem: '',
    IN_DEVIATION: 0,
    OUT_DEVIATION: 0,
    predictFreq: 2,
  }
  calRateForm.value = {
    calItem: undefined,
    IN_DEVIATION: 10,
    OUT_DEVIATION: 50,
    IN_ACCURACY_RATE: 0,
    OUT_ACCURACY_RATE: 0,
    itemAvg: 0,
@@ -232,462 +1315,69 @@
    itemPreAvg: 0,
    itemPreMax: 0,
    itemPreMin: 0,
    preCumulant:0,
    realCumulant:0
  })
  let itemData = ref({
    currentTreeList: [],
    chart: {},
    option: {}
  })
  const chartContainer = ref(null);
  const treeData = ref([])
  const itemDataObject = ref()
  const timer = ref()
  const formRules = reactive({
    calItem: [{required: true, message: '预测项不能为空', trigger: 'blur'}],
    IN_DEVIATION: [{required: true, message: '精准度偏差不能为空', trigger: 'blur'}],
    OUT_DEVIATION: [{required: true, message: '不可信率偏差不能为空', trigger: 'blur'}],
  })
  //const myChart = echarts.init(document.getElementById("data-analysis"));
  /** 查询列表 */
  const getList = async () => {
    loading1.value = true
    try {
      const data = formData.value
      if (!formData.value.chartCheck) {
        formData.value.chartCheck = ['真实值']
      }
      let chartCheckArray = formData.value.chartCheck;
      if (!formData.value.checkedItemData || formData.value.checkedItemData.length == 0) {
        itemData.value.option = {};
        return;
      }
      let itemIdList = formData.value.checkedItemData.map(item => {
        return item.id
      })
      const params = ref({
        itemIds: itemIdList.join(','),
        predictTime: formData.value.predictTime,
        startTime: formData.value.startTime,
        endTime: formData.value.endTime
      })
      const res = await MmPredictItem.getViewCharts(params)
      if (res.code !== 0) {
        return message.error(res.msg)
      }
      formData.value.predictTime = res.data.predictTime;
      formData.value.startTime = res.data.startTime
      formData.value.endTime = res.data.endTime
      let xAxisData = res.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 < res.data.dataViewList.length; i++) {
        let dataView = res.data.dataViewList[i]
        itemDataObject.value.dataView.itemId = 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.itemName + '(真实)';
          legendData.push(legendName);
          seriesData.push({
            name: legendName,
            data: dataView.realData || [],
            type: 'line',
            yAxisIndex: yAxisIndex,
            showSymbol: false,
            smooth: true,
            lineStyle: {
              width: 3
            }
          });
        }
        if (chartCheckArray.indexOf('T+N') !== -1) {
          let legendName = dataView.itemName + '(T+N)';
          seriesData.push({
            name: legendName,
            data: dataView.preDataN || [],
            type: 'line',
            yAxisIndex: yAxisIndex,
            showSymbol: false,
            smooth: true,
            lineStyle: {
              width: 3
            }
          });
        }
        if (chartCheckArray.indexOf('T+L') !== -1) {
          let legendName = dataView.itemName + '(T+L)';
          legendData.push(legendName);
          seriesData.push({
            name: legendName,
            data: dataView.preDataL || [],
            type: 'line',
            showSymbol: false,
            connectNulls: true,
            yAxisIndex: yAxisIndex,
            smooth: true,
            lineStyle: {
              width: 3
            }
          });
        }
        if (chartCheckArray.indexOf('当时') !== -1) {
          let legendName = dataView.itemName + '(当时)';
          legendData.push(legendName);
          seriesData.push({
            name: legendName,
            data: dataView.curData || [],
            type: 'line',
            yAxisIndex: yAxisIndex,
            showSymbol: false,
            smooth: true,
            lineStyle: {
              width: 3
            }
          });
        }
        if (chartCheckArray.indexOf('调整值') !== -1) {
          let legendName = dataView.itemName + '(调整值)';
          legendData.push(legendName);
          seriesData.push({
            name: legendName,
            data: dataView.adjData || [],
            type: 'line',
            yAxisIndex: yAxisIndex,
            showSymbol: false,
            connectNulls: true,
            smooth: true,
            lineStyle: {
              width: 3,
              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;
          }
        }
      }
      let option = {
        title: {
          text: ''
        },
        tooltip: {
          trigger: 'axis'
        },
        legend: {
          show: true,
          data: legendData,
          top: 10
        },
        grid: {
          top: 50,
          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
      }
      //chart.setOption(option)
    } finally {
      loading1.value = false
    }
    preCumulant: 0,
    realCumulant: 0,
    deviation: 0, //平均绝对误差
    deviationCumulant: 0, //累积量平均绝对误差
  }
  onMounted(() => {
    getPreItemTree()
    getList()
  })
  async function getPreItemTree() {
    treeData.value = await MmPredictItem.getMmPredictItemTree()
  }
  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]
    }
    //myChart.clear()
    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 calItemBaseVale() {
    if (!calRateForm.value.calItem) {
      calRateForm.value.itemPreMax = 0;
      calRateForm.value.itemPreMin = 0;
      calRateForm.value.itemPreAvg = 0;
      calRateForm.value.preCumulant = 0;
      calRateForm.value.itemMax = 0;
      calRateForm.value.itemMin = 0;
      calRateForm.value.itemAvg = 0;
      calRateForm.value.realCumulant = 0;
      return
    } else {
      let dataView = itemDataObject[calRateForm.value.calItem]
      calRateForm.value.itemPreMax = dataView.preMax;
      calRateForm.value.itemPreMin = dataView.preMin;
      calRateForm.value.itemPreAvg = dataView.preAvg;
      calRateForm.value.preCumulant = dataView.preCumulant;
      calRateForm.value.itemMax = dataView.hisMax;
      calRateForm.value.itemMin = dataView.hisMin;
      calRateForm.value.itemAvg = dataView.hisAvg;
      calRateForm.value.realCumulant = dataView.hisCumulant;
    }
  }
  function calAccuracyRate() {
    this.$refs['calRateForm'].validate((valid) => {
      if (!valid) {
        return false
      }
      let dataView = itemDataObject[calRateForm.value.calItem]
      let seriesReaData = dataView.realData;
      let seriesPreData = dataView.preDataL;
      if (seriesReaData == null || seriesPreData == null ||
        seriesReaData.length === 0 || seriesPreData.length === 0) {
        loading2.value = false;
        return;
      }
      let predictValueMap = {};
      seriesPreData.forEach(function (item) {
        predictValueMap[item[0]] = item[1];
      })
      let pointValueMap = {};
      seriesReaData.forEach(function (item) {
        pointValueMap[item[0]] = item[1];
      })
      let inDeviation = Number(calRateForm.value.IN_DEVIATION);
      let outDeviation = Number(calRateForm.value.OUT_DEVIATION);
      if (inDeviation === 0 && outDeviation === 0) {
        loading2.value = false;
        return;
      }
      let inDeviationCount = 0;
      let outDeviationCount = 0;
      let totalCount = 0;
      for (let key in predictValueMap) {
        let predictValue = predictValueMap[key];
        let pointValue = pointValueMap[key];
        if (pointValue == null || "" === pointValue || predictValue == null || "" === predictValue) {
          continue;
        }
        let deviationAbs = (predictValue - pointValue) >= 0 ? (predictValue - pointValue) : (predictValue - pointValue) * -1;
        if (deviationAbs < inDeviation) {
          inDeviationCount = inDeviationCount + 1;
        }
        if (deviationAbs > outDeviation) {
          outDeviationCount = outDeviationCount + 1;
        }
        totalCount = totalCount + 1;
      }
      let rateIn = (inDeviationCount / totalCount * 100).toFixed(2);
      let rateOut = (outDeviationCount / totalCount * 100).toFixed(2);
      calRateForm.value.IN_ACCURACY_RATE = Number(rateIn);
      calRateForm.value.OUT_ACCURACY_RATE = Number(rateOut);
      loading2.value = false;
    })
  }
  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();
  }
  calRateFormRef.value?.resetFields()
}
</script>
<style scoped>
  .el-form-item {
    margin-bottom: 0 !important;
  }
.chart-foot-table {
  border: 1px solid #bababa;
}
.chart-foot-title {
  font-size: 14px;
}
.chart-foot-content {
  height: 100%;
  width: 50%;
  padding: 5px;
}
.chart-foot {
  height: 120px;
  width: 100%;
  display: flex;
  flex-direction: row;
}
.el-form-item {
  margin-bottom: 0 !important;
}
  .his-body-chart {
    height: 100%;
    border: 1px solid lightgray;
    padding: 10px;
  }
.his-body-chart {
  height: 100%;
  border: 1px solid lightgray;
  padding: 10px;
  overflow-y: auto;
  overflow-x: hidden;
}
  .his-body-tree {
    height: 100%;
    border: 1px solid lightgray;
    padding: 10px;
  }
.his-body-tree {
  height: 100%;
  border: 1px solid lightgray;
  padding: 10px 10px 20px 10px;
  overflow-y: auto;
}
  .his-body-right {
    width: 80%;
    height: 100%;
    padding-top: 10px;
  }
.his-body-right {
  width: 80%;
  height: 100%;
  padding-top: 10px;
}
  .his-body-left {
    width: 20%;
    height: 100%;
    padding: 10px 10px 0 0;
  }
.his-body-left {
  width: 20%;
  height: 100%;
  padding: 10px 10px 0 0;
}
  .his-body {
    width: 100%;
    height: calc(calc(100vh - 48px - 38px - 130px));
    display: flex;
    flex-direction: row;
    justify-content: flex-start;
    align-content: flex-start;
  }
.his-body {
  width: 100%;
  height: calc(calc(100vh - 68px - 38px - 60px));
  display: flex;
  flex-direction: row;
  justify-content: flex-start;
  align-content: flex-start;
}
</style>