From b8f758793f0a1f3aecc8b3de57fb6de5985f001a Mon Sep 17 00:00:00 2001
From: dongyukun <1208714201@qq.com>
Date: 星期一, 26 五月 2025 18:25:28 +0800
Subject: [PATCH] 调度建议快照

---
 src/views/model/sche/suggest/suggestOperationRecord.vue |   21 ++++
 src/views/model/sche/snapshotConf/det/index.vue         |    3 
 src/views/model/sche/suggest/suggestSnapshot.vue        |  219 +++++++++++++++++++++++++++++++++++++++++++
 src/api/model/sche/suggest/suggestSnapshotRecord.ts     |   16 +++
 src/views/model/sche/snapshotConf/det/configDetForm.vue |   28 +++--
 5 files changed, 276 insertions(+), 11 deletions(-)

diff --git a/src/api/model/sche/suggest/suggestSnapshotRecord.ts b/src/api/model/sche/suggest/suggestSnapshotRecord.ts
new file mode 100644
index 0000000..009734d
--- /dev/null
+++ b/src/api/model/sche/suggest/suggestSnapshotRecord.ts
@@ -0,0 +1,16 @@
+// 建议快照记录
+import request from "@/config/axios";
+
+export interface ChartListReqVO extends PageParam {
+  chooseDataList: []
+}
+
+// 列表
+export const getList = (id) => {
+  return request.get({ url: '/model/suggest/snapshot/record/list?operationId=' + id })
+}
+
+// 图表
+export const getChartList = (params: ChartListReqVO) => {
+  return request.get({ url: '/model/suggest/snapshot/record/chartList' , params})
+}
diff --git a/src/views/model/sche/snapshotConf/det/configDetForm.vue b/src/views/model/sche/snapshotConf/det/configDetForm.vue
index ee9ab76..470a342 100644
--- a/src/views/model/sche/snapshotConf/det/configDetForm.vue
+++ b/src/views/model/sche/snapshotConf/det/configDetForm.vue
@@ -7,67 +7,73 @@
       :rules="formRules"
       label-width="80px"
     >
-      <el-row :gutter="20">
+      <el-row :gutter="24">
         <el-col :span="12">
           <el-form-item label="数据类型" prop="dataType">
             <el-input v-model="formData.dataType" placeholder=""/>
           </el-form-item>
         </el-col>
         <el-col :span="12">
-          <el-form-item label="数据编号" prop="dataNo">
-            <el-input v-model="formData.dataNo" placeholder=""/>
+          <el-form-item label="数据名称" prop="dataName">
+            <el-input v-model="formData.dataName" placeholder=""/>
           </el-form-item>
         </el-col>
       </el-row>
       <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="数据编号" prop="dataNo">
+            <el-input v-model="formData.dataNo" placeholder=""/>
+          </el-form-item>
+        </el-col>
         <el-col :span="12">
           <el-form-item label="左侧长度" prop="leftLength">
             <el-input v-model="formData.leftLength" placeholder=""/>
           </el-form-item>
         </el-col>
+      </el-row>
+      <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item label="右侧长度" prop="rightLength">
             <el-input v-model="formData.rightLength" placeholder=""/>
           </el-form-item>
         </el-col>
-      </el-row>
-      <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item label="排序" prop="sort">
             <el-input v-model="formData.sort" placeholder=""/>
           </el-form-item>
         </el-col>
+      </el-row>
+      <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item label="拓展字段1" prop="ext1">
             <el-input v-model="formData.ext1" placeholder=""/>
           </el-form-item>
         </el-col>
-      </el-row>
-      <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item label="拓展字段2" prop="ext2">
             <el-input v-model="formData.ext2" placeholder=""/>
           </el-form-item>
         </el-col>
+      </el-row>
+      <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item label="拓展字段3" prop="ext3">
             <el-input v-model="formData.ext3" placeholder=""/>
           </el-form-item>
         </el-col>
-      </el-row>
-      <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item label="拓展字段4" prop="ext4">
             <el-input v-model="formData.ext4" placeholder=""/>
           </el-form-item>
         </el-col>
+      </el-row>
+      <el-row :gutter="20">
         <el-col :span="12">
           <el-form-item label="拓展字段5" prop="ext5">
             <el-input v-model="formData.ext5" placeholder=""/>
           </el-form-item>
         </el-col>
       </el-row>
-
     </el-form>
     <template #footer>
       <el-button :disabled="formLoading" type="primary" @click="submitForm">确 定</el-button>
@@ -92,6 +98,7 @@
   id: undefined,
   confId: undefined,
   dataType: undefined,
+  dataName: undefined,
   dataNo: undefined,
   leftLength: undefined,
   rightLength: undefined,
@@ -104,6 +111,7 @@
 })
 const formRules = reactive({
   dataType: [{ required: true, message: '不能为空', trigger: 'blur' }],
+  dataName: [{ required: true, message: '不能为空', trigger: 'blur' }],
   dataNo: [{ required: true, message: '不能为空', trigger: 'blur' }],
 })
 const formRef = ref() // 表单 Ref
diff --git a/src/views/model/sche/snapshotConf/det/index.vue b/src/views/model/sche/snapshotConf/det/index.vue
index 0fad67a..36fd064 100644
--- a/src/views/model/sche/snapshotConf/det/index.vue
+++ b/src/views/model/sche/snapshotConf/det/index.vue
@@ -1,7 +1,7 @@
 <template>
   <el-drawer
     v-model="drawer"
-    size="40%"
+    size="60%"
     title="参数列表"
     direction="rtl"
     :before-close="handleClose"
@@ -61,6 +61,7 @@
         row-key="id"
       >
         <el-table-column prop="dataType" label="数据类型"/>
+        <el-table-column prop="dataName" label="数据名称"/>
         <el-table-column prop="dataNo" label="数据编号"/>
         <el-table-column prop="leftLength" label="左侧长度(min)"/>
         <el-table-column prop="rightLength" label="右侧侧长度(min)"/>
diff --git a/src/views/model/sche/suggest/suggestOperationRecord.vue b/src/views/model/sche/suggest/suggestOperationRecord.vue
index 2fd69eb..e666add 100644
--- a/src/views/model/sche/suggest/suggestOperationRecord.vue
+++ b/src/views/model/sche/suggest/suggestOperationRecord.vue
@@ -50,6 +50,18 @@
           align="center"
           min-width="150"
         />
+        <el-table-column label="快照" align="center" min-width="100" fixed="right">
+          <template #default="scope">
+            <el-button
+              link
+              type="primary"
+              @click="openSnapshot(scope.row.id)"
+              v-if="scope.row.operate=='采纳建议'"
+            >
+              快照
+            </el-button>
+          </template>
+        </el-table-column>
       </el-table>
       <!-- 分页 -->
       <Pagination
@@ -60,10 +72,13 @@
       />
     </ContentWrap>
   </el-drawer>
+  <!-- 快照弹窗 -->
+  <SuggestSnapshot ref="suggestSnapshotRef" @success="getList" />
 </template>
 <script lang="ts" setup>
   import type {DrawerProps} from 'element-plus'
   import { getSuggestOperationRecordPage } from '@/api/model/sche/suggest/suggestOperationRecord';
+  import SuggestSnapshot from './suggestSnapshot.vue'
   import {ref} from "vue";
 
   defineOptions({name: 'SuggestOperationRecord'})
@@ -103,6 +118,12 @@
     getList()
   }
 
+  /** 快照 */
+  const suggestSnapshotRef = ref()
+  const openSnapshot = (id?: string) => {
+    suggestSnapshotRef.value.openSnapshot(id)
+  }
+
   /** 打开弹窗 */
   const open = async (modelId?: string, scheduleTime?: string) => {
     drawer.value = true
diff --git a/src/views/model/sche/suggest/suggestSnapshot.vue b/src/views/model/sche/suggest/suggestSnapshot.vue
new file mode 100644
index 0000000..31ea85d
--- /dev/null
+++ b/src/views/model/sche/suggest/suggestSnapshot.vue
@@ -0,0 +1,219 @@
+<template>
+  <el-dialog
+    title="历史值"
+    :close-on-click-modal="false"
+    width="80%"
+    v-model="visible"
+  >
+    <div class="flex-container">
+        <el-tag
+          v-for="item in dataList"
+          :key="item.dataCode"
+          class="data-tag"
+          :type="selectedData.includes(item.dataCode) ? '' : 'info'"
+          @click="toggleDataSelection(item)"
+        >
+          {{ item.dataName }}
+        </el-tag>
+      </div>
+      <div class="right-panel">
+        <div
+          v-for="chart in charts"
+          :key="chart.id"
+          class="chart-container"
+          ref="chartDom"
+          v-loading="loading"
+        ></div>
+      </div>
+  </el-dialog>
+</template>
+
+<script lang="ts" setup>
+  import { ref, reactive, nextTick } from 'vue'
+  import * as echarts from 'echarts'
+  import * as suggestSnapshotApi from '@/api/model/sche/suggest/suggestSnapshotRecord';
+
+  const message = useMessage()
+  const visible = ref(false)
+  const dataList = ref([])
+  const selectedData = ref([])
+  const charts = ref([])
+  const chartInstances = ref([])
+  const loading = ref(false)
+
+  const dataForm = reactive({
+    id: "",
+  })
+
+  /** 打开弹窗 */
+  const open = async (id: string) => {
+    visible.value = true
+    dataForm.id = id
+    await getDataList()
+  }
+
+  defineExpose({ open })
+
+  /** 获取数据列表 */
+  const getDataList = async () => {
+    try {
+      const res = await suggestSnapshotApi.getList(dataForm.id)
+      dataList.value = res
+    } catch (error) {
+      console.error(error)
+      message.error('获取数据列表失败')
+    }
+  }
+
+  /** 切换数据选择 */
+  const toggleDataSelection = (item) => {
+    const index = selectedData.value.indexOf(item.dataCode)
+    if (index === -1) {
+      selectedData.value.push(item.dataCode)
+    } else {
+      selectedData.value.splice(index, 1)
+    }
+    refreshCharts()
+  }
+
+  /** 刷新图表 */
+  const refreshCharts = async () => {
+    if (selectedData.value.length === 0) {
+      charts.value = []
+      return
+    }
+
+    loading.value = true
+    try {
+      const params = {
+        chooseDataList: selectedData.value,
+      }
+      const chartData = await suggestSnapshotApi.getChartList(params)
+
+      // 销毁之前的图表实例
+      chartInstances.value.forEach(instance => instance.dispose())
+      chartInstances.value = []
+
+      // 准备新的图表数据
+      charts.value = selectedData.value.map((code, index) => {
+        const item = dataList.value.find(d => d.dataCode === code)
+        return {
+          id: `chart-${index}`,
+          name: item?.dataName || code,
+          data: chartData[index] // 假设返回数据是按顺序对应的
+        }
+      })
+
+      // 渲染新图表
+      await nextTick()
+      renderCharts()
+    } catch (error) {
+      console.error(error)
+      message.error('获取图表数据失败')
+    } finally {
+      loading.value = false
+    }
+  }
+
+  /** 渲染所有图表 */
+  const renderCharts = () => {
+    const chartContainers = document.querySelectorAll('.chart-container')
+
+    chartContainers.forEach((container, index) => {
+      const chart = echarts.init(container)
+      const chartInfo = charts.value[index]
+
+      const option = {
+        title: {
+          text: chartInfo.name,
+          top: 0,
+          left: "1%",
+          textStyle: {
+            fontSize: 14,
+          },
+        },
+        tooltip: {
+          trigger: "axis",
+          axisPointer: {
+            type: "line",
+            lineStyle: {
+              color: "#cccccc",
+              width: "1",
+              type: "dashed",
+            },
+          },
+        },
+        legend: {
+          show: false,
+          top: 10,
+        },
+        grid: {
+          top: 30,
+          left: "3%",
+          right: "5%",
+          bottom: 10,
+          containLabel: true,
+        },
+        xAxis: {
+          type: "category",
+          boundaryGap: false,
+          data: chartInfo.data.categories,
+        },
+        yAxis: {
+          type: "value",
+        },
+        dataZoom: [
+          {
+            type: "inside",
+          },
+        ],
+        series: [{
+          name: chartInfo.name,
+          type: "line",
+          data: chartInfo.data.series[0].data,
+          showSymbol: true,
+          smooth: false,
+          lineStyle: {
+            normal: {
+              color: "#5B8FF9",
+              width: 1,
+            },
+          },
+        }],
+      }
+
+      chart.setOption(option)
+      chartInstances.value.push(chart)
+    })
+  }
+</script>
+
+<style scoped>
+  .flex-container {
+    display: flex;
+    height: 600px;
+  }
+
+  .left-panel {
+    width: 250px;
+    padding-right: 20px;
+    border-right: 1px solid #eee;
+    overflow-y: auto;
+  }
+
+  .right-panel {
+    flex: 1;
+    padding-left: 20px;
+    overflow-y: auto;
+  }
+
+  .data-tag {
+    margin: 5px;
+    cursor: pointer;
+  }
+
+  .chart-container {
+    height: 300px;
+    margin-bottom: 20px;
+  }
+</style>

--
Gitblit v1.9.3