Procházet zdrojové kódy

部件修改合并

rui.jiang před 11 měsíci
rodič
revize
3fb9c1696e
49 změnil soubory, kde provedl 1347 přidání a 587 odebrání
  1. binární
      src/assets/analyse/exitFullScreen.png
  2. binární
      src/assets/analyse/fullScreen.png
  3. binární
      src/assets/analyse/mark.png
  4. 52 52
      src/assets/js/constants/color.js
  5. 8 5
      src/assets/js/constants/echarts-config/Heatmap.js
  6. 11 0
      src/assets/js/constants/echarts-config/bar.js
  7. 9 0
      src/assets/js/constants/echarts-config/line.js
  8. 5 5
      src/assets/js/constants/echarts-config/scatter.js
  9. 18 28
      src/store/dragChart.js
  10. 1 1
      src/store/index.js
  11. 5 1
      src/styles/global.scss
  12. 0 7
      src/utils/indexedDb.js
  13. 198 68
      src/utils/vuexIndexedDBPlugin.js
  14. 494 0
      src/views/dataAdministration/laser/index.vue
  15. 3 3
      src/views/dataAdministration/vibration/index.vue
  16. 1 3
      src/views/health/vibration.vue
  17. 2 2
      src/views/laserRangeFinder/components/CylinderOfTower.vue
  18. 64 73
      src/views/laserRangeFinder/components/PlotOfFit.vue
  19. 8 8
      src/views/laserRangeFinder/components/initCharts.vue
  20. 0 1
      src/views/laserRangeFinder/index.vue
  21. 1 0
      src/views/ledger/component/windsiteup.vue
  22. 4 3
      src/views/performance/assetssDetail.vue
  23. 1 0
      src/views/performance/components/DetailCharts.vue
  24. 3 2
      src/views/performance/components/EditAnalysis.vue
  25. 2 1
      src/views/performance/components/JsonMarkerCharts.vue
  26. 1 0
      src/views/performance/components/abnormalDetail.vue
  27. 2 1
      src/views/performance/components/analysisEvent.vue
  28. 2 2
      src/views/performance/components/custonAsCom/AssociatedFields.vue
  29. 3 2
      src/views/performance/components/custonAsCom/DatabaseTable.vue
  30. 111 11
      src/views/performance/components/custonAsCom/dataTable.vue
  31. 3 1
      src/views/performance/components/custonAsCom/dragChart/components/chart/index.vue
  32. 3 1
      src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/Heatmap.js
  33. 3 1
      src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/boxPlot.js
  34. 2 0
      src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/cp.js
  35. 3 1
      src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/pareto.js
  36. 3 1
      src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/pie.js
  37. 3 1
      src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/radar.js
  38. 3 1
      src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/roseChart.js
  39. 3 1
      src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/sankeyDiagram.js
  40. 70 181
      src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/scatter.js
  41. 3 1
      src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/stackedBar.js
  42. 2 2
      src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartTitle.vue
  43. 13 2
      src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/configFn.js
  44. 2 2
      src/views/performance/components/custonAsCom/dragChart/components/chartsContent.vue
  45. 40 2
      src/views/performance/components/custonAsCom/dragChart/components/chartsData.vue
  46. 52 45
      src/views/performance/components/custonAsCom/luckySheet.vue
  47. 1 0
      src/views/performance/components/map.vue
  48. 128 64
      src/views/performance/customAnalysis.vue
  49. 1 1
      vue.config.js

binární
src/assets/analyse/exitFullScreen.png


binární
src/assets/analyse/fullScreen.png


binární
src/assets/analyse/mark.png


+ 52 - 52
src/assets/js/constants/color.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-27 14:40:15
- * @LastEditTime: 2024-12-10 09:58:45
+ * @LastEditTime: 2024-12-17 09:51:33
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/assets/js/constants/color.js
@@ -299,56 +299,56 @@
 //   "#7FA348",
 //   "#B3B72E",
 // ];
-//蓝色-青色
+//蓝色-青色 正常色系
 export const colorPalette = [
-  "#6296E2",
-  "#69C5C8",
-  "#4A90E2",
-  "#1D3C73",
-  "#2F6BB8",
-  "#3F8DAB",
-  "#5C9FBB",
-  "#1A6A84",
-  "#6A8EAE",
-  "#3C7C92",
-  "#1D5479",
-  "#4896D1",
-  "#3B9CB5",
-  "#51A8D2",
-  "#287DAC",
-  "#5F8A99",
-  "#3D84A4",
-  "#67C4D7",
-  "#4F9FC8",
-  "#6B94BD",
-  "#2C7E9A",
-  "#64A9CC",
-  "#3A86B1",
-  "#478F9B",
-  "#5C88B9",
-  "#367F9E",
-  "#4C89B2",
-  "#61A2D5",
-  "#5698B5",
-  "#82B9D5",
-  "#5B7E92",
-  "#6C8E9B",
-  "#4395C0",
-  "#67C1B9",
-  "#5B87A8",
-  "#5189D1",
-  "#5C7B92",
-  "#4E9DB4",
-  "#63A7C3",
-  "#55739A",
-  "#6D88A2",
-  "#3B7CA2",
-  "#6289BD",
-  "#4779A8",
-  "#5B9EBC",
-  "#4C7E9B",
-  "#6B7D98",
-  "#587C9B",
-  "#466690",
-  "#8B94B8",
+  "#D7EFB7",
+  "#9CD9BD",
+  "#7ACCC1",
+  "#5DBFC4",
+  "#46AFC5",
+  "#379CC2",
+  "#3286BB",
+  "#406DAB",
+  "#3856A0",
+  "#314291",
+  "#28357A",
+  "#1A285E",
 ];
+//蓝色-青色 正常色系
+// export const colorPalette = [
+//   // "#FFFFDF",
+//   "#DFEDC1",
+//   // "#EBF6C1",
+//   "#DBEEBC",
+//   "#A8D7BE",
+//   "#8ECAC1",
+//   "#77BDC2",
+//   "#64ADC2",
+//   "#559ABE",
+//   "#4884B7",
+//   "#406DAB",
+//   "#3856A0",
+//   "#314291",
+//   "#28357A",
+//   "#1A285E",
+// ];
+//涉及到温度的 图表
+// export const colorPalette = [
+//   "#F96F4A",
+//   "#F78F4F",
+//   "#FCB06C",
+//   "#FFC475",
+//   "#FFE286",
+//   "#FDF1A9",
+//   "#FBFFBE",
+//   "#EEF9A7",
+//   "#E4F39E",
+//   "#CFEE9E",
+//   "#A8DCA2",
+//   "#85D0AE",
+//   "#60C5A3",
+//   "#52A3AE",
+//   "#4FA4B5",
+//   "#3586BF",
+//   "#476CB9",
+// ];

+ 8 - 5
src/assets/js/constants/echarts-config/Heatmap.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-20 09:13:21
- * @LastEditTime: 2024-12-16 10:20:24
+ * @LastEditTime: 2024-12-17 16:27:13
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/assets/js/constants/echarts-config/Heatmap.js
@@ -42,7 +42,7 @@ export const option = {
     orient: "vertical",
     right: 20,
     top: "center",
-    color: ["#0d59b7", "#bee8ff"],
+    color: ["#1A285E", "#379CC2", "#D7EFB7"],
   },
   series: [
     {
@@ -50,11 +50,14 @@ export const option = {
       type: "heatmap",
       data: [
         [0, 0, 5],
-        [1, 0, 10],
-        [2, 0, 15],
-        [0, 1, 7],
+        [1, 0, 100],
+        [2, 0, 35],
+        [0, 1, 70],
         [1, 1, 8],
         [2, 1, 12],
+        [0, 2, 80],
+        [1, 2, 58],
+        [2, 2, 92],
       ], // [x, y, 风速值]
       emphasis: {
         itemStyle: {

+ 11 - 0
src/assets/js/constants/echarts-config/bar.js

@@ -51,6 +51,17 @@ export const option = {
       type: "bar",
       barWidth: "60%",
       data: [10, 52, 200, 334, 390, 330, 220],
+      progressiveThreshold: 3000, // 当数据量超过3000时启用渐进式渲染
+      progressive: true, // 启用渐进式渲染
+      markPoint: {
+        data: [
+          { type: "max", name: "Max" },
+          { type: "min", name: "Min" },
+        ],
+      },
+      markLine: {
+        data: [{ type: "average", name: "Avg" }],
+      },
     },
   ],
 };

+ 9 - 0
src/assets/js/constants/echarts-config/line.js

@@ -52,6 +52,15 @@ export const option = {
       name: "功率曲线",
       type: "line",
       data: [300, 22, 249, 345, 234, 56, 73], // 风速与功率对应数据
+      markPoint: {
+        data: [
+          { type: "max", name: "Max" },
+          { type: "min", name: "Min" },
+        ],
+      },
+      markLine: {
+        data: [{ type: "average", name: "Avg" }],
+      },
     },
   ],
 };

+ 5 - 5
src/assets/js/constants/echarts-config/scatter.js

@@ -35,11 +35,11 @@ export const option = {
       ], // [风向, 风速, 数据点大小]
       // symbolSize: (data) => data[2], // 根据大小调整气泡尺寸
       renderMode: "webgl", // 启用 WebGL 渲染
-      itemStyle: {
-        shadowBlur: 10,
-        shadowColor: "rgba(25, 100, 150, 0.5)",
-        shadowOffsetY: 5,
-      },
+      // itemStyle: {
+      //   shadowBlur: 10,
+      //   shadowColor: "rgba(25, 100, 150, 0.5)",
+      //   shadowOffsetY: 5,
+      // },
     },
   ],
   tooltip: {

+ 18 - 28
src/store/dragChart.js

@@ -53,8 +53,7 @@ export default {
     },
     //编辑数据筛选字段
     setFormFilterAlignData(state, data) {
-      //将数据存储起来用于回显 数据
-      // 检查是否已经存在相同的 id
+      //将数据存储起来用于回显数据---检查是否已经存在相同的 id
       state.currentChartList?.map((chartItem, ind) => {
         if (chartItem.id === data.id) {
           state.currentChartList[ind].formFilterAlignData = data.data;
@@ -65,7 +64,6 @@ export default {
     setCurEdit(state, data) {
       state.curEdit = data;
     },
-
     // 当前画布添加图表
     addChart(state, data) {
       //   console.log("当前画布添加图表", data);
@@ -77,12 +75,10 @@ export default {
     },
     //更新数据配置当前选中数据
     updateDataBase(state, data) {
-      // console.log("更改了图表数据", data);
       state.dataBaseCheckList = data;
     },
     // 更新图表
     updateChart(state, data) {
-      // console.log("更改了图表组件", data.index, data);
       if (state.currentChartList[data.index]) {
         state.currentChartList[data.index] = Object.assign(
           state.currentChartList[data.index],
@@ -90,28 +86,23 @@ export default {
         );
       }
     },
-
     // 删除图表
     deleteChart(state, index) {
       state.currentChartList.splice(index, 1);
     },
-
     // 设置当前图表列表
     setCurrentChartList(state, list = []) {
       state.currentChartList = list;
     },
-
     // 文件删除
     fileListDelete(state, item) {
       const index = state.fileList.indexOf(item);
       state.fileList.splice(index, 1);
     },
-
     // 文件添加
     fileListAdd(state, item) {
       state.fileList.push(item);
     },
-
     fileListUpdate(state, item) {
       state.fileList = _.cloneDeep(item);
     },
@@ -135,25 +126,24 @@ export default {
         Message.warning("未找到文件!");
       }
     },
-
     // 缩放屏幕
-    scaleScreen(state, isGrow) {
-      if (isGrow) {
-        state.currentChartList.forEach((item) => {
-          item.x = parseInt(item.x * SCALE);
-          item.y = parseInt(item.y * SCALE);
-          item.height = parseInt(item.height * SCALE);
-          item.width = parseInt(item.width * SCALE);
-        });
-      } else {
-        state.currentChartList.forEach((item) => {
-          item.x = parseInt(item.x / SCALE);
-          item.y = parseInt(item.y / SCALE);
-          item.height = parseInt(item.height / SCALE);
-          item.width = parseInt(item.width / SCALE);
-        });
-      }
-    },
+    // scaleScreen(state, isGrow) {
+    //   if (isGrow) {
+    //     state.currentChartList.forEach((item) => {
+    //       item.x = parseInt(item.x * SCALE);
+    //       item.y = parseInt(item.y * SCALE);
+    //       item.height = parseInt(item.height * SCALE);
+    //       item.width = parseInt(item.width * SCALE);
+    //     });
+    //   } else {
+    //     state.currentChartList.forEach((item) => {
+    //       item.x = parseInt(item.x / SCALE);
+    //       item.y = parseInt(item.y / SCALE);
+    //       item.height = parseInt(item.height / SCALE);
+    //       item.width = parseInt(item.width / SCALE);
+    //     });
+    //   }
+    // },
   },
   actions: {},
 };

+ 1 - 1
src/store/index.js

@@ -48,7 +48,7 @@ export const store = new Vuex.Store({
         "auth",
         "settings",
         "themes",
-        "menuTag", // 指定需要存储的模块,排除 dragChart
+        "menuTag", // 指定需要持久化存储的模块,排除 dragChart
       ],
     }),
     vuexIndexedDBPlugin,

+ 5 - 1
src/styles/global.scss

@@ -4,6 +4,9 @@
   border-color: var(--primary-color) !important;
   color: var(--text-color) !important;
 }
+.el-menu-item.is-active {
+  color: var(--primary-color) !important;
+}
 
 .el-dialog__header {
   background-color: var(--primary-color) !important;
@@ -21,6 +24,7 @@
   color: var(--primary-color) !important;
   // color: var(--primary-color) !important;
 }
+
 .el-button--text {
   color: var(--primary-color) !important;
 }
@@ -32,7 +36,7 @@
 }
 
 // 改变振动分析边框色
-.head{
+.head {
   border-top: 5px solid var(--primary-color) !important;
   border-bottom: 5px solid var(--primary-color) !important;
 }

+ 0 - 7
src/utils/indexedDb.js

@@ -97,23 +97,18 @@ export async function getDataFromIndexedDB() {
 export async function clearAllDataFromIndexedDB() {
   return new Promise((resolve, reject) => {
     const versionRequest = indexedDB.open("FileDataDB");
-
     versionRequest.onsuccess = (event) => {
       const db = event.target.result;
-
       // 检查对象存储是否存在
       if (!db.objectStoreNames.contains("files")) {
         console.log("Object store 'files' does not exist. No action needed.");
         db.close();
         return resolve();
       }
-
       const currentVersion = db.version;
       db.close();
-
       // 使用当前版本或更高版本打开数据库
       const request = indexedDB.open("FileDataDB", currentVersion);
-
       request.onsuccess = (event) => {
         const db = event.target.result;
         const transaction = db.transaction(["files"], "readwrite");
@@ -125,7 +120,6 @@ export async function clearAllDataFromIndexedDB() {
           console.log("All data cleared from IndexedDB.");
           resolve();
         };
-
         clearRequest.onerror = (event) => {
           console.error(
             "Failed to clear data from IndexedDB:",
@@ -134,7 +128,6 @@ export async function clearAllDataFromIndexedDB() {
           reject(event.target.error);
         };
       };
-
       request.onerror = (event) => {
         console.error("Failed to open IndexedDB:", event.target.error);
         reject(event.target.error);

+ 198 - 68
src/utils/vuexIndexedDBPlugin.js

@@ -1,31 +1,193 @@
-import { saveData, getData, openDB } from "@/utils/indexedDb";
-import { stringify, parse } from "flatted"; // 用于处理循环引用 压缩数据处理
-import pako from "pako";
+// import { saveData, getData } from "@/utils/indexedDb";
+// import { stringify, parse } from "flatted"; // 用于处理循环引用 压缩数据处理
+// import pako from "pako";
+// import { Message } from "element-ui";
+
+// // 通用分片函数
+// const splitIntoChunks = (data, chunkSize) => {
+//   const chunks = [];
+//   for (let i = 0; i < data.length; i += chunkSize) {
+//     chunks.push(data.slice(i, i + chunkSize));
+//   }
+//   return chunks;
+// };
+
+// // 修改后的 openDB 方法
+// const openDB = (dbName, version) => {
+//   return new Promise((resolve, reject) => {
+//     const request = indexedDB.open(dbName, version);
+
+//     request.onsuccess = () => {
+//       resolve(request.result);
+//     };
+
+//     request.onerror = (error) => {
+//       reject(error);
+//     };
+
+//     request.onupgradeneeded = (event) => {
+//       const db = event.target.result;
+
+//       // 创建对象存储(如果不存在)
+//       if (!db.objectStoreNames.contains("dragChart_chunk_meta")) {
+//         db.createObjectStore("dragChart_chunk_meta");
+//       }
+//       if (!db.objectStoreNames.contains("dragChart_compressed")) {
+//         db.createObjectStore("dragChart_compressed");
+//       }
+//       if (!db.objectStoreNames.contains("myIndexedDB")) {
+//         db.createObjectStore("myIndexedDB");
+//       }
+//     };
+//   });
+// };
+
+// // vuex 插件
+// const vuexIndexedDBPlugin = (store) => {
+//   const dbName = "vuexDB";
+//   const keyName = "vuexState";
+
+//   // 过滤 Vuex 状态,去掉不可序列化的部分
+//   const filterState = (state) => {
+//     const clonedState = JSON.parse(
+//       JSON.stringify(state, (key, value) => {
+//         // 如果是函数或无法克隆的对象,返回 undefined
+//         if (typeof value === "function") return undefined;
+//         return value;
+//       })
+//     );
+//     return clonedState;
+//   };
+//   // 初始化 IndexedDB 并加载状态
+//   openDB(dbName, 1).then(() => {
+//     getData(dbName, keyName).then((savedState) => {
+//       if (savedState) {
+//         store.replaceState({
+//           ...store.state,
+//           ...savedState,
+//         });
+//       }
+//     });
+//   });
+
+//   // 订阅 Vuex mutations,每次状态变更时保存到 IndexedDB
+//   store.subscribe((mutation, state) => {
+//     if (mutation.type.startsWith("dragChart/")) {
+//       const dragChartState = state.dragChart;
+
+//       try {
+//         const cleanedState = JSON.parse(
+//           JSON.stringify(dragChartState, (key, value) => {
+//             if (
+//               typeof value === "function" ||
+//               value instanceof HTMLElement ||
+//               value === undefined
+//             ) {
+//               return undefined;
+//             }
+//             return value;
+//           })
+//         );
+
+//         // 压缩或分片存储
+//         const chunkSize = 500;
+//         if (
+//           cleanedState.currentChartList &&
+//           Array.isArray(cleanedState.currentChartList)
+//         ) {
+//           const chunks = splitIntoChunks(
+//             cleanedState.currentChartList,
+//             chunkSize
+//           );
+//           chunks.forEach((chunk, index) => {
+//             const chunkKey = `dragChart_chunk_${index}`;
+//             saveData("myIndexedDB", chunkKey, chunk)
+//               .then(() => {
+//                 console.log(`Chunk ${index} saved successfully`);
+//               })
+//               .catch((error) =>
+//                 console.error(`Failed to save chunk ${index}:`, error)
+//               );
+//           });
+
+//           saveData("myIndexedDB", "dragChart_chunk_meta", {
+//             totalChunks: chunks.length,
+//           });
+//         }
+
+//         // 存储压缩的元数据
+//         const compressedData = pako.deflate(stringify(cleanedState), {
+//           to: "string",
+//         });
+//         saveData("myIndexedDB", "dragChart_compressed", compressedData)
+//           .then(() => {
+//             //console.log("Compressed metadata saved")
+//           })
+//           .catch((error) =>
+//             console.error("Failed to save compressed metadata:", error)
+//           );
+//       } catch (error) {
+//         console.error("Error processing dragChart state:", error);
+//         Message({
+//           message: "数据存储已满,请刷新页面进行数据清除" + error,
+//           type: "error",
+//         });
+//       }
+//     }
+//   });
+// };
+
+// export default vuexIndexedDBPlugin;
+import { saveData, getData } from "@/utils/indexedDb";
 import { Message } from "element-ui";
-// 通用分片函数
-const splitIntoChunks = (data, chunkSize) => {
-  const chunks = [];
-  for (let i = 0; i < data.length; i += chunkSize) {
-    chunks.push(data.slice(i, i + chunkSize));
-  }
-  return chunks;
+
+// 通用的过滤 Vuex 状态,去掉不可序列化的部分
+const filterState = (state) => {
+  const clonedState = JSON.parse(
+    JSON.stringify(state, (key, value) => {
+      // 如果是函数或无法克隆的对象,返回 undefined
+      if (
+        typeof value === "function" ||
+        value instanceof HTMLElement ||
+        value === undefined
+      ) {
+        return undefined;
+      }
+      return value;
+    })
+  );
+  return clonedState;
 };
+
+// 修改后的 openDB 方法
+const openDB = (dbName, version) => {
+  return new Promise((resolve, reject) => {
+    const request = indexedDB.open(dbName, version);
+
+    request.onsuccess = () => {
+      resolve(request.result);
+    };
+
+    request.onerror = (error) => {
+      reject(error);
+    };
+
+    request.onupgradeneeded = (event) => {
+      const db = event.target.result;
+
+      // 创建对象存储(如果不存在)
+      if (!db.objectStoreNames.contains("myIndexedDB")) {
+        db.createObjectStore("myIndexedDB");
+      }
+    };
+  });
+};
+
+// vuex 插件
 const vuexIndexedDBPlugin = (store) => {
   const dbName = "vuexDB";
   const keyName = "vuexState";
 
-  // 过滤 Vuex 状态,去掉不可序列化的部分
-  const filterState = (state) => {
-    const clonedState = JSON.parse(
-      JSON.stringify(state, (key, value) => {
-        // 如果是函数或无法克隆的对象,返回 undefined
-        if (typeof value === "function") return undefined;
-        return value;
-      })
-    );
-    return clonedState;
-  };
-
   // 初始化 IndexedDB 并加载状态
   openDB(dbName, 1).then(() => {
     getData(dbName, keyName).then((savedState) => {
@@ -34,7 +196,6 @@ const vuexIndexedDBPlugin = (store) => {
           ...store.state,
           ...savedState,
         });
-        console.log("Vuex state loaded from IndexedDB");
       }
     });
   });
@@ -45,56 +206,25 @@ const vuexIndexedDBPlugin = (store) => {
       const dragChartState = state.dragChart;
 
       try {
-        const cleanedState = JSON.parse(
-          JSON.stringify(dragChartState, (key, value) => {
-            if (
-              typeof value === "function" ||
-              value instanceof HTMLElement ||
-              value === undefined
-            ) {
-              return undefined;
-            }
-            return value;
-          })
-        );
-
-        // 压缩或分片存储
-        const chunkSize = 500;
-        if (
-          cleanedState.currentChartList &&
-          Array.isArray(cleanedState.currentChartList)
-        ) {
-          const chunks = splitIntoChunks(
-            cleanedState.currentChartList,
-            chunkSize
-          );
-          chunks.forEach((chunk, index) => {
-            const chunkKey = `dragChart_chunk_${index}`;
-            saveData("myIndexedDB", chunkKey, chunk)
-              .then(() => console.log(`Chunk ${index} saved successfully`))
-              .catch((error) =>
-                console.error(`Failed to save chunk ${index}:`, error)
-              );
-          });
+        // 过滤不需要保存的内容
+        const cleanedState = filterState(dragChartState);
 
-          saveData("myIndexedDB", "dragChart_chunk_meta", {
-            totalChunks: chunks.length,
+        // 直接保存整个状态到 IndexedDB
+        saveData("myIndexedDB", keyName, cleanedState)
+          .then(() => {
+            console.log("State saved successfully");
+          })
+          .catch((error) => {
+            console.error("Failed to save state:", error);
+            Message({
+              message: "数据存储失败:" + error,
+              type: "error",
+            });
           });
-        }
-
-        // 存储压缩的元数据
-        const compressedData = pako.deflate(stringify(cleanedState), {
-          to: "string",
-        });
-        saveData("myIndexedDB", "dragChart_compressed", compressedData)
-          .then(() => console.log("Compressed metadata saved"))
-          .catch((error) =>
-            console.error("Failed to save compressed metadata:", error)
-          );
       } catch (error) {
         console.error("Error processing dragChart state:", error);
         Message({
-          message: "数据存储已满,请刷新页面进行数据清除" + error,
+          message: "数据存储失败,请刷新页面进行数据清除:" + error,
           type: "error",
         });
       }

+ 494 - 0
src/views/dataAdministration/laser/index.vue

@@ -0,0 +1,494 @@
+<!--
+ * @Author: your name
+ * @Date: 2024-12-16 11:30:03
+ * @LastEditTime: 2024-12-17 09:25:42
+ * @LastEditors: bogon
+ * @Description: In User Settings Edit
+ * @FilePath: /performance-test/src/views/dataAdministration/laser/index.vue
+-->
+
+<template>
+  <div class="global-variable" v-loading="loading">
+    <!-- 激光测距仪转换操作页面 -->
+    <div class="condition">
+      <el-form
+        :inline="true"
+        ref="ruleForm"
+        :model="formInline"
+        class="demo-form-inline"
+      >
+        <el-form-item label="风场名称:" prop="fieldName">
+          <el-input
+            size="small"
+            v-model="formInline.fieldName"
+            placeholder="请输入风场名称"
+          ></el-input>
+        </el-form-item>
+        <el-form-item label="状态:">
+          <el-select
+            size="small"
+            v-model="formInline.transferStatus"
+            placeholder="请选择状态"
+            style="width: 100%"
+          >
+            <el-option
+              :label="item.label"
+              v-for="item in StateCodeList"
+              :value="item.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" @click="onSubmit" size="small"
+            >查询</el-button
+          >
+          <el-button @click="reset('ruleForm')" size="small">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
+    <div class="list-page">
+      <div class="newly">
+        <el-button
+          v-hasPermi="['performance:batchMag:add']"
+          type="primary"
+          @click="newnuedialog"
+          size="small"
+          >新增</el-button
+        >
+      </div>
+      <el-table
+        v-loading="loading"
+        class="center-align-table"
+        :data="tableData"
+        border
+        :cell-style="rowStyle"
+      >
+        <el-table-column
+          prop="fieldName"
+          align="center"
+          min-width="100"
+          label="风场名称"
+        >
+        </el-table-column>
+        <el-table-column
+          align="center"
+          min-width="100"
+          label="转换路径"
+          prop="transferAddr"
+        >
+        </el-table-column>
+        <el-table-column
+          align="center"
+          min-width="100"
+          label="进度"
+          prop="transferProgress"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="transferStatus"
+          align="center"
+          label="状态"
+          min-width="100"
+        >
+          <template slot-scope="scope">
+            <span>
+              {{
+                scope.row.transferStatus == 0
+                  ? "转换中"
+                  : scope.row.transferStatus == 1
+                  ? "转换完成"
+                  : scope.row.transferStatus == 2
+                  ? "转换异常"
+                  : scope.row.transferStatus == -1
+                  ? "未转换"
+                  : "/"
+              }}</span
+            >
+          </template>
+        </el-table-column>
+
+        <el-table-column
+          align="center"
+          min-width="100"
+          label="异常信息"
+          prop="errInfo"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="transferStartTime"
+          align="center"
+          min-width="150"
+          label="开始时间"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="transferEndTime"
+          align="center"
+          min-width="150"
+          label="结束时间"
+        >
+        </el-table-column>
+        <el-table-column
+          prop="transition"
+          align="center"
+          fixed="right"
+          label="操作"
+          min-width="200"
+        >
+          <!-- 需要配置按钮权限再加这个自定义指令 -->
+          <!-- v-hasPermi="['dataAdministration:vibration:conversion']" -->
+          <template slot-scope="scope">
+            <el-button
+              v-if="scope.row.transferStatus === -1"
+              @click="conversion(scope.row, 0)"
+              type="text"
+              size="small"
+              >转换</el-button
+            >
+            <!-- v-hasPermi="['dataAdministration:vibration:reconversion']" -->
+            <el-button
+              v-if="
+                scope.row.transferStatus === 0 ||
+                scope.row.transferStatus === 1 ||
+                scope.row.transferStatus === 2
+              "
+              @click="conversion(scope.row, 1)"
+              type="text"
+              size="small"
+              :disabled="scope.row.transferStatus == 0"
+              >重新转换</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+      <div class="pagination-container">
+        <el-pagination
+          @current-change="handleCurrentChange"
+          :current-page.sync="formInline.pageNum"
+          layout="total, prev, pager, next"
+          :page-size="formInline.pageSize"
+          :total="formInline.totalSize"
+        >
+        </el-pagination>
+      </div>
+    </div>
+
+    <!-- 弹出层 -->
+    <!-- 新增 /编辑-->
+    <el-dialog
+      :title="title"
+      :visible.sync="nuedialog"
+      width="500px"
+      :before-close="handleCloses"
+    >
+      <div v-loading="loadingView" class="views">
+        <el-form
+          :model="ruleForm"
+          :rules="addUserRules"
+          ref="addUserForm"
+          label-width="100px"
+          class="demo-ruleForm"
+        >
+          <el-form-item label="风场:" prop="fieldCode">
+            <el-select
+              v-model="ruleForm.fieldCode"
+              placeholder="请选择风场"
+              :disabled="title !== '新增'"
+              style="width: 100%"
+            >
+              <el-option
+                :label="item.fieldName"
+                v-for="item in fieldCodeList"
+                :value="item.codeNumber"
+              ></el-option>
+            </el-select>
+          </el-form-item>
+          <el-form-item label="转换路径" prop="transferAddr">
+            <el-input
+              v-model="ruleForm.transferAddr"
+              placeholder="请输入转换路径"
+            ></el-input>
+          </el-form-item>
+        </el-form>
+        <span slot="footer" class="dialog-footer">
+          <el-button @click="cancel('addUserForm')" size="small"
+            >取 消
+          </el-button>
+          <el-button
+            type="primary"
+            @click="submitForm('addUserForm')"
+            size="small"
+          >
+            确 定
+          </el-button>
+        </span>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { updateFieldBatch, queryCodeNum } from "@/api/performance.js";
+import {
+  getDataTransfer,
+  addDataTransfer,
+  DataTransfer,
+} from "@/api/dataManage.js";
+
+export default {
+  data() {
+    return {
+      loadingView: false,
+      loading: false, //数据加载中
+      fieldCodeList: [],
+      StateCodeList: [
+        {
+          label: "未转换",
+          value: -1,
+        },
+        {
+          label: "转换中",
+          value: 0,
+        },
+        {
+          label: "转换完成",
+          value: 1,
+        },
+        {
+          label: "转换异常",
+          value: 2,
+        },
+      ],
+      formInline: {
+        pageNum: 1,
+        pageSize: 10,
+        transferType: 2,
+        fieldName: "",
+        transferStatus: "",
+      },
+      tableData: [],
+      // 新增编辑表单
+      ruleForm: {
+        fieldCode: null,
+        transferAddr: null,
+      },
+      addUserRules: {
+        fieldCode: {
+          required: true,
+          message: "请选择风场",
+          trigger: "change",
+        },
+        transferAddr: [
+          { required: true, message: "请输入转换路径", trigger: "blur" },
+        ],
+      },
+      nuedialog: false,
+      title: "",
+      id: "",
+    };
+  },
+  created() {
+    this.getTableList();
+    this.getQueryCodeNumList();
+  },
+
+  methods: {
+    //转换重新转换
+    conversion(row, retransfer) {
+      try {
+        // 直接替换整个对象,以确保 Vue 的响应式系统能够检测到变化
+        this.ruleForm = {
+          fieldCode: row.fieldCode,
+          transferAddr: row.transferAddr,
+        };
+        this.id = row.id;
+        this.nuedialog = true;
+        this.title = retransfer === 0 ? "转换" : "重新转换";
+      } catch (error) {
+        this.$message.error("获取用户信息失败");
+      }
+    },
+    handleCloses(done) {
+      this.$confirm("确认关闭?")
+        .then((_) => {
+          done();
+        })
+        .catch((_) => {});
+    },
+
+    //获取风场列表
+    async getQueryCodeNumList() {
+      this.loading = true;
+      try {
+        const result = await queryCodeNum();
+        this.fieldCodeList = result.data.fieldCodeList;
+        this.loading = false;
+      } catch (error) {
+        console.error(error);
+        this.loading = false;
+      }
+    },
+    //分页数据切换
+    handleCurrentChange(val) {
+      this.formInline.pageNum = val;
+      this.getTableList();
+    },
+
+    async getTableList() {
+      try {
+        this.loading = true;
+        const result = await getDataTransfer({
+          ...this.formInline,
+          transferStatus:
+            this.formInline.transferStatus === ""
+              ? undefined
+              : this.formInline.transferStatus,
+          fieldName:
+            this.formInline.fieldName === ""
+              ? undefined
+              : this.formInline.fieldName,
+        });
+        this.tableData = result.data.list;
+        this.formInline.totalSize = result.data.totalSize;
+        this.loading = false;
+      } catch (error) {
+        this.$message({
+          type: "error",
+          message: "请检查是否连接网络",
+        });
+      }
+    },
+
+    rowStyle() {
+      return "text-align:center";
+    },
+    // 查询
+    onSubmit() {
+      this.getTableList();
+    },
+
+    // 新增,编辑确定
+    submitForm(formName) {
+      this.$refs[formName].validate(async (valid) => {
+        if (!valid) return false;
+        this.loadingView = true;
+        // 定义处理逻辑的映射
+        const actionMap = {
+          新增: () => addDataTransfer({ transferType: 2, ...this.ruleForm }),
+          转换: () =>
+            DataTransfer({
+              id: this.id,
+              retransfer: 0,
+              transferAddr: this.ruleForm.transferAddr,
+            }),
+          重新转换: () =>
+            DataTransfer({
+              id: this.id,
+              retransfer: 1,
+              transferAddr: this.ruleForm.transferAddr,
+            }),
+        };
+        try {
+          // 执行对应的操作
+          const response = await actionMap[this.title]?.();
+          if (response) {
+            this.$message({
+              type: "success",
+              message: response.msg,
+            });
+            this.getTableList();
+            this.nuedialog = false;
+          }
+        } catch (error) {
+          console.error("操作失败:", error);
+          this.$message.error(error?.msg || "操作失败,请稍后重试。");
+        } finally {
+          this.loadingView = false;
+        }
+      });
+    },
+
+    //点击取消
+    cancel(formName) {
+      this.$refs[formName] && this.$refs[formName].resetFields();
+      this.ruleForm = {
+        fieldCode: null,
+        transferAddr: null,
+      };
+      this.nuedialog = false;
+      this.loadingView = false;
+    },
+    reset() {
+      this.formInline = {
+        fieldName: "",
+        transferStatus: "",
+      };
+      this.getTableList();
+    },
+    // 新增
+    newnuedialog() {
+      this.cancel("addUserForm");
+      this.ruleForm = {
+        transferAddr: "",
+        fieldCode: "",
+      };
+      this.nuedialog = true;
+      this.title = "新增";
+    },
+  },
+};
+</script>
+
+<style lang="scss" scoped>
+.general {
+  display: flex;
+  flex-wrap: wrap;
+
+  .condition {
+    width: 50%;
+    display: flex;
+
+    p {
+      width: 100px;
+      text-align: right;
+      line-height: 40px;
+    }
+
+    span {
+      line-height: 40px;
+
+      padding-left: 20px;
+    }
+
+    .el-select {
+      width: 100%;
+      margin-bottom: 20px;
+    }
+
+    .el-input {
+      margin-bottom: 20px;
+    }
+  }
+}
+
+.attachment {
+  display: flex;
+  padding-top: 10px;
+
+  p {
+    margin-right: 20px;
+    color: #409eff;
+  }
+}
+
+.addition {
+  display: flex;
+  justify-content: flex-end;
+  margin-bottom: 10px;
+}
+.demo-ruleForm {
+  .el-form-item {
+    margin-bottom: 25px;
+  }
+}
+</style>

+ 3 - 3
src/views/dataAdministration/vibration/index.vue

@@ -1,14 +1,14 @@
 <!--
  * @Author: your name
  * @Date: 2024-11-25 09:28:47
- * @LastEditTime: 2024-12-06 16:12:50
+ * @LastEditTime: 2024-12-17 09:26:01
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/dataAdministration/vibration/index.vue
 -->
 <template>
   <div class="global-variable" v-loading="loading">
-    <!-- 振动数据操作页面 -->
+    <!-- 振动数据转换操作页面 -->
     <div class="condition">
       <el-form
         :inline="true"
@@ -372,7 +372,7 @@ export default {
         this.loadingView = true;
         // 定义处理逻辑的映射
         const actionMap = {
-          新增: () => addDataTransfer({ transferType: "1", ...this.ruleForm }),
+          新增: () => addDataTransfer({ transferType: 1, ...this.ruleForm }),
           转换: () =>
             DataTransfer({
               id: this.id,

+ 1 - 3
src/views/health/vibration.vue

@@ -1,7 +1,6 @@
 <template>
   <div class="global-variable">
     <div class="head">
-    
       <div class="headleft">
         <div @click="generate('1')" class="picture">
           <img src="@/assets/analyse/03.png" alt="" />
@@ -308,7 +307,6 @@ export default {
       }
     },
   },
-
   methods: {
     handleLoading(currentRow, loading, activeIndex, params) {
       if (loading) {
@@ -852,4 +850,4 @@ export default {
 //   color: #088080;
 //   font-weight: 600;
 // }
-</style>
+</style>

+ 2 - 2
src/views/laserRangeFinder/components/CylinderOfTower.vue

@@ -136,9 +136,9 @@ export default {
             sampling: "lttb",
             itemStyle: {
               normal: {
-                color: "#3070B7",
+                color: "#1A285E",
                 lineStyle: {
-                  color: "#3070B7",
+                  color: "#1A285E",
                   width: 1,
                 },
               },

+ 64 - 73
src/views/laserRangeFinder/components/PlotOfFit.vue

@@ -62,8 +62,24 @@ export default {
       currentIndex: 0, // 默认索引
       tableData: [], // 数据
       originalChartStyle: {}, // 用于存储原始样式
+      // 控制标注的显示/隐藏
+      markPointVisible: false,
+      markLineVisible: false,
     };
   },
+  watch: {
+    // 监听标注的显示状态变化
+    markPointVisible(newVal, oldVal) {
+      if (newVal !== oldVal) {
+        this.updateChart(); // 更新图表
+      }
+    },
+    markLineVisible(newVal, oldVal) {
+      if (newVal !== oldVal) {
+        this.updateChart(); // 更新图表
+      }
+    },
+  },
   mounted() {
     this.initializeChart();
     // 监听键盘事件
@@ -78,6 +94,7 @@ export default {
     initializeChart() {
       const chartDom = this.$refs.chart;
       this.chartInstance = echarts.init(chartDom);
+
       const defaultData = [
         Math.floor(Math.random() * 300),
         Math.floor(Math.random() * 300),
@@ -103,70 +120,20 @@ export default {
         (_, index) => `2024/1/${index + 1}`
       );
       const option = {
-        color: ["#9CC5AF", "#C9866B", "#709EA6", "#344453", "#B34138"],
-        // title: [
-        //   {
-        //     text: "",
-        //     left: "center",
-        //     // subtext: '纯属虚构'
-        //   },
-        //   {
-        //     text: "",
-        //     // subtext:'实线',
-        //     textStyle: {
-        //       color: "#c23531",
-        //       // }
-        //     },
-        //     right: 35,
-        //     top: 275,
-        //     // subtext: '纯属虚构'
-        //   },
-        //   {
-        //     text: "",
-        //     right: 3,
-        //     top: 280,
-        //     textStyle: {
-        //       color: "#c23531",
-        //       fontSize: 12,
-        //     },
-        //   },
-
-        //   {
-        //     text: "",
-        //     textStyle: {
-        //       color: "#2f4554",
-        //     },
-        //     right: 35,
-        //     top: 295,
-        //     // subtext: '纯属虚构'
-        //   },
-        //   {
-        //     text: "",
-        //     textStyle: {
-        //       // fontSize:12,
-        //       color: "#d48265",
-        //     },
-        //     right: 0,
-        //     top: 219,
-        //     // subtext: '纯属虚构'
-        //   },
-        //   {
-        //     text: "",
-        //     textStyle: {
-        //       color: "#61a0a8",
-        //     },
-        //     right: 35,
-        //     top: 410,
-        //     // subtext: '纯属虚构'
-        //   },
-        //   {
-        //     top: 510,
-        //     left: 50,
-        //     subtextStyle: {
-        //       fontWeight: "bold",
-        //     },
-        //   },
-        // ],
+        color: [
+          "#D7EFB7",
+          // "#9CD9BD",
+          // "#7ACCC1",
+          // "#5DBFC4",
+          "#46AFC5",
+          // "#379CC2",
+          // "#3286BB",
+          // "#406DAB",
+          "#3856A0",
+          // "#314291",
+          // "#28357A",
+          "#1A285E",
+        ],
         toolbox: {
           feature: {
             dataZoom: { yAxisIndex: "none" },
@@ -186,14 +153,22 @@ export default {
             },
             myCustomTool3: {
               show: true,
+              title: "标注",
+              icon: `image://${require("@/assets/analyse/mark.png")}`,
+              onclick: () => this.WhetherToDisplay(),
+            },
+            myCustomTool4: {
+              show: true,
               title: "全屏",
               icon: `image://${require("@/assets/analyse/fullScreen.png")}`,
+
               onclick: () => this.fullScreen(),
             },
-            myCustomTool4: {
+            myCustomTool5: {
               show: true,
               title: "退出全屏",
               icon: `image://${require("@/assets/analyse/exitFullScreen.png")}`, // 替换为你自己的图标路径
+
               onclick: () => this.exitFullScreen(),
             },
           },
@@ -232,24 +207,16 @@ export default {
             name: "叶片2根部轮廓",
             type: "line",
             showSymbol: false,
-            lineStyle: {
-              //   type: "dashed",
-            },
             data: [
               12.84, 13.03, 13.05, 13.89, 13.72, 12.97, 13.21, 14.02, 14.54,
               15.07, 14.94, 14.55, 13.84, 12.7, 12.06, 11.93, 11.6, 10.84,
               10.26, 10.18, 10.21, 9.86, 10.1, 9.96, 10.25, 11.1, 11.08, 10.7,
             ],
           },
-
           {
             name: "叶片3根部轮廓",
             showSymbol: false,
-            lineStyle: {
-              //   type: "dotted",
-            },
             type: "line",
-
             data: [
               7.38, 7.73, 7.46, 7.85, 7.68, 7.45, 6.94, 6.7, 5.98, 6.25, 6.28,
               5.74, 5.51, 5.35, 5.25, 5.03, 4.83, 4.57, 4.58, 4.33, 4.6, 4.42,
@@ -293,8 +260,32 @@ export default {
           },
         ],
       };
+      // 切换标注的显示状态
+      option.series = option.series.map((serie) => ({
+        ...serie,
+        markPoint: this.markPointVisible
+          ? {
+              data: [
+                { type: "max", name: "Max" },
+                { type: "min", name: "Min" },
+              ],
+            }
+          : { data: [] },
+        markLine: this.markLineVisible
+          ? {
+              data: [{ type: "average", name: "Avg" }],
+            }
+          : { data: [] },
+      }));
+      this.chartInstance.setOption(option, true); // 强制刷新
       this.chartInstance.setOption(option);
     },
+    // 标注是否显示
+    WhetherToDisplay() {
+      // 切换显示状态
+      this.markPointVisible = !this.markPointVisible;
+      this.markLineVisible = !this.markLineVisible;
+    },
     previousRow() {
       let newIndex =
         this.currentIndex > 0

+ 8 - 8
src/views/laserRangeFinder/components/initCharts.vue

@@ -115,20 +115,20 @@ export default {
             sampling: "lttb",
             itemStyle: {
               normal: {
-                color: "#3A84FF",
+                color: "#1A285E",
                 lineStyle: {
-                  color: "#3A84FF",
+                  color: "#1A285E",
                   width: 1,
                 },
                 areaStyle: {
                   color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
                     {
                       offset: 0,
-                      color: "rgba(58,132,255,0)",
+                      color: "rgba(26,40,94,0)",
                     },
                     {
                       offset: 1,
-                      color: "rgba(58,132,255,0.35)",
+                      color: "rgba(26,40,94,0.35)",
                     },
                   ]),
                 },
@@ -145,20 +145,20 @@ export default {
             sampling: "lttb",
             itemStyle: {
               normal: {
-                color: "rgba(255,80,124,1)",
+                color: "#d2e9b4",
                 lineStyle: {
-                  color: "rgba(255,80,124,1)",
+                  color: "#d2e9b4",
                   width: 1,
                 },
                 areaStyle: {
                   color: new echarts.graphic.LinearGradient(0, 1, 0, 0, [
                     {
                       offset: 0,
-                      color: "rgba(255,80,124,0)",
+                      color: "rgba(210,233,180,0)",
                     },
                     {
                       offset: 1,
-                      color: "rgba(255,80,124,0.35)",
+                      color: "rgba(210,233,180,1)",
                     },
                   ]),
                 },

+ 0 - 1
src/views/laserRangeFinder/index.vue

@@ -235,7 +235,6 @@ export default {
           windCode: this.formInline.companyCode,
           windTurbineNumber: this.formInline.unitvalue,
         };
-        console.log(this.formInline, "formInline");
         const res = await axios.post("/WZLapi/laserData/getLaserData", params);
         if (res.data.code === 200) {
           this.tableData = res.data.datas;

+ 1 - 0
src/views/ledger/component/windsiteup.vue

@@ -102,6 +102,7 @@ import {
   saveWindFieldResource,
   getWindEngineMillList,
 } from "@/api/ledger.js";
+
 export default {
   props: {
     uploadingPOP: {

+ 4 - 3
src/views/performance/assetssDetail.vue

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2024-05-27 09:25:45
- * @LastEditTime: 2024-10-09 09:11:01
+ * @LastEditTime: 2024-12-24 10:49:20
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/assetssDetail.vue
@@ -119,6 +119,7 @@
         <el-table-column prop="engine_name" label="风机名称"> </el-table-column>
         <el-table-column prop="yaw_error1" label="误差值"> </el-table-column>
       </el-table>
+      <!-- 需要在这里添加三个分析类型排版布局 ,分析详情中 -->
       <div v-else>
         <el-card class="box-card analysisType" v-if="generalFiles.length > 0">
           <div slot="header" class="clearfix">
@@ -380,7 +381,7 @@ import {
   downloadFile,
 } from "@/api/performance";
 import CreateNewChart from "./createNewChart.vue";
-import DetailCharts from "./components/DetailCharts.vue";
+// import DetailCharts from "./components/DetailCharts.vue";
 import BoxLineCharts from "./components/chartsCom/BoxLineCharts";
 import HeatmapCharts from "./components/chartsCom/HeatmapCharts.vue";
 import WindRoseChart from "./components/chartsCom/WindRoseChart.vue";
@@ -395,7 +396,7 @@ import Papa from "papaparse";
 import axios from "axios";
 export default {
   components: {
-    DetailCharts,
+    // DetailCharts,
     WindRoseChart,
     // JsonMarkerCharts,
     HeatmapCharts,

+ 1 - 0
src/views/performance/components/DetailCharts.vue

@@ -1,5 +1,6 @@
 <template>
   <div>
+    <!-- 废弃页面 -->
     <div id="mainChart"></div>
     <div
       v-for="(engine, index) in data.data"

+ 3 - 2
src/views/performance/components/EditAnalysis.vue

@@ -1,12 +1,13 @@
 <!--
  * @Author: your name
  * @Date: 2024-05-29 09:14:23
- * @LastEditTime: 2024-09-30 16:28:49
- * @LastEditors: milo-MacBook-Pro.local
+ * @LastEditTime: 2024-12-24 10:48:23
+ * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/EditAnalysis.vue
 -->
 <template>
+  <!-- 分析编辑页面 -->
   <div v-loading="loading">
     <el-form ref="form" :model="form" label-width="120px">
       <el-collapse v-model="activeNames">

+ 2 - 1
src/views/performance/components/JsonMarkerCharts.vue

@@ -1,12 +1,13 @@
 <!--
  * @Author: your name
  * @Date: 2024-08-16 16:19:19
- * @LastEditTime: 2024-09-30 09:30:43
+ * @LastEditTime: 2024-12-24 10:47:21
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/JsonMarkerCharts.vue
 -->
 <template>
+  <!-- json 数据渲染plotly散点图  废弃页面-->
   <div>
     <div ref="chart" style="width: 100%; height: 500px"></div>
   </div>

+ 1 - 0
src/views/performance/components/abnormalDetail.vue

@@ -1,5 +1,6 @@
 <template>
   <div v-loading="loading">
+    <!-- 异常描述页面 -->
     <div class="newly">
       <el-button type="primary" @click="addRow" size="small">新增</el-button>
     </div>

+ 2 - 1
src/views/performance/components/analysisEvent.vue

@@ -1,12 +1,13 @@
 <!--
  * @Author: your name
  * @Date: 2024-05-29 09:13:51
- * @LastEditTime: 2024-09-30 16:12:20
+ * @LastEditTime: 2024-12-24 10:49:55
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/analysisEvent.vue
 -->
 <template>
+  <!-- 分析事件页面 -->
   <div v-loading="loading">
     <el-form
       ref="form"

+ 2 - 2
src/views/performance/components/custonAsCom/AssociatedFields.vue

@@ -170,7 +170,6 @@ export default {
       tableDataChart2: [],
     };
   },
-  async created() {},
   computed: {
     ...mapState("dragChart", {
       relatedFieldsData: "relatedFieldsData",
@@ -190,7 +189,8 @@ export default {
             filename: this.ruleForm.name + "关联表",
             fileData: data,
             fileOldName: this.ruleForm.name + "关联表",
-            fileId: new Date().getTime(),
+            fileId:
+              new Date().getTime() + "_" + Math.floor(Math.random() * 1000),
           };
           storeSetData(database, "files", "fileDataArray", fileData, () => {
             this.setRelatedFieldsData({

+ 3 - 2
src/views/performance/components/custonAsCom/DatabaseTable.vue

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2024-10-28 17:43:21
- * @LastEditTime: 2024-12-06 14:11:30
+ * @LastEditTime: 2024-12-26 09:28:12
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/DatabaseTable.vue
@@ -91,6 +91,7 @@
 import axios from "axios";
 import { storeSetData, initDatabase } from "@/utils/indexedDb";
 import { mapMutations, mapState } from "vuex";
+import { format } from "date-fns";
 export default {
   props: {
     dialogVisible: {
@@ -233,7 +234,7 @@ export default {
             fileData: data[key],
             fileId: `${new Date().getTime()}_${key}`, // 添加唯一时间戳和字段标识
             fileOldName: `${key}.xlsx`, // 文件原始名称
-            filename: `${new Date().getTime()}_${key}.xlsx`, // 包含时间戳的文件名
+            filename: `${format(new Date(), "yyyyMMdd-HH:mm:ss")}_${key}.xlsx`, // 包含时间戳的文件名
           }));
         // 初始化数据库
         const database = await initDatabase();

+ 111 - 11
src/views/performance/components/custonAsCom/dataTable.vue

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2024-10-28 16:46:38
- * @LastEditTime: 2024-12-05 15:27:24
+ * @LastEditTime: 2024-12-26 09:13:11
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dataTable.vue
@@ -12,12 +12,14 @@
       v-if="tabData.length > 0"
       v-model="activeName"
       @tab-click="handleClick"
+      closable
+      @tab-remove="removeTab"
       class="tabsBox"
     >
       <template v-for="(tabItem, ind) in tabData">
         <el-tab-pane
           :label="tabItem.filename"
-          :name="String(tabItem.filename + tabItem.fileId)"
+          :name="String(tabItem.fileId)"
           :key="tabItem.fileData + ind + 'tabPane'"
         >
           <el-row
@@ -26,9 +28,9 @@
             justify="end"
             :key="tabItem.filename + ind + 'row'"
           >
-            <el-button type="primary" @click="handleEditTable(tabItem.fileId)"
-              >编辑</el-button
-            >
+            <el-button type="primary" @click="handleEditTable(tabItem.fileId)">
+              编辑
+            </el-button>
           </el-row>
           <template v-if="tabItem.fileData && tabItem.fileData.length > 0">
             <el-table
@@ -106,17 +108,115 @@ export default {
       });
   },
   methods: {
-    ...mapMutations("dragChart", ["setTriggerGetData"]),
+    ...mapMutations("dragChart", [
+      "setTriggerGetData",
+      "setUpdateTriggerGetData",
+    ]),
     async getIndexDbData() {
-      // this.loading = true;
+      this.loading = true;
       const jsonData = await getDataFromIndexedDB();
       this.tabData = jsonData;
-      this.activeName =
-        jsonData &&
-        jsonData[0] &&
-        String(jsonData[0].filename + jsonData[0].fileId);
+      this.activeName = jsonData && jsonData[0] && String(jsonData[0].fileId);
       this.loading = false;
     },
+
+    // 删除 tab 方法
+    removeTab(targetName) {
+      // 1. 在 tabData 中删除对应的 tab
+      const index = this.tabData.findIndex((tab) => tab.fileId === targetName);
+      console.log(this.tabData, targetName, "targetName");
+      if (index !== -1) {
+        this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        })
+          .then(() => {
+            // 删除 tabData 中的对应项
+            const data = this.tabData;
+            const removedTab = data.splice(index, 1)[0]; // 获取被删除的 tab 数据
+            // 2. 更新 IndexedDB
+            this.updateDataInIndexedDB(removedTab);
+
+            // 3. 触发需要更新的状态
+            this.setTriggerGetData(true);
+            this.setUpdateTriggerGetData(true);
+            this.$message({
+              type: "success",
+              message: "删除成功!",
+            });
+          })
+          .catch(() => {
+            this.$message({
+              type: "info",
+              message: "已取消删除",
+            });
+          });
+      }
+    },
+
+    async updateDataInIndexedDB(removedTab) {
+      try {
+        const db = await this.openIndexedDB(); // 打开 IndexedDB
+
+        // 创建事务,指定操作对象存储空间
+        const transaction = db.transaction(["files"], "readwrite");
+        const store = transaction.objectStore("files");
+        // 使用 getAll 获取所有数据
+        const getRequest = store.getAll();
+        getRequest.onsuccess = () => {
+          const data = getRequest.result;
+          console.log(data, "所有数据");
+
+          // 假设文件数据在 data[0].data 中
+          let updatedData = data[0]?.data || [];
+
+          // 从数据中移除被删除的 tab 数据
+          updatedData = updatedData.filter(
+            (item) => item.fileId !== removedTab.fileId
+          );
+
+          // 更新存储的数据(这里假设数据存储在 id 为 "fileDataArray" 的键下)
+          const putRequest = store.put({
+            id: "fileDataArray", // 使用 "fileDataArray" 作为 id
+            data: updatedData,
+          });
+
+          putRequest.onsuccess = () => {
+            console.log("Updated data successfully in IndexedDB");
+          };
+
+          putRequest.onerror = (event) => {
+            console.error(
+              "Error updating data in IndexedDB:",
+              event.target.error
+            );
+          };
+        };
+
+        getRequest.onerror = (event) => {
+          console.error(
+            "Error retrieving data from IndexedDB:",
+            event.target.error
+          );
+        };
+      } catch (error) {
+        console.error("Failed to update data in IndexedDB:", error);
+      }
+    },
+
+    // 打开 IndexedDB 数据库
+    openIndexedDB() {
+      return new Promise((resolve, reject) => {
+        const request = indexedDB.open("FileDataDB");
+        request.onsuccess = (event) => {
+          resolve(event.target.result);
+        };
+        request.onerror = (event) => {
+          reject(event.target.error);
+        };
+      });
+    },
     handleClick(tab, event) {},
     handleEditTable(id) {
       this.$router.push({

+ 3 - 1
src/views/performance/components/custonAsCom/dragChart/components/chart/index.vue

@@ -65,7 +65,9 @@ export default {
   methods: {
     drawChart() {
       if (!this.myChart) {
-        this.myChart = echarts.init(this.$refs.chart, this.theme);
+        this.myChart = echarts.init(this.$refs.chart, this.theme, {
+          renderer: "svg", // 设置渲染方式为SVG
+        });
       }
       this.myChart.setOption(this.option);
     },

+ 3 - 1
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/Heatmap.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-28 10:31:21
- * @LastEditTime: 2024-11-28 13:43:22
+ * @LastEditTime: 2024-12-26 09:56:47
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/Heatmap.js
@@ -115,6 +115,8 @@ export function handleHeatmapPlotChartLogic(
       {
         type: "heatmap",
         data: formattedData,
+        progressiveThreshold: 3000, // 当数据量超过3000时启用渐进式渲染
+        progressive: true, // 启用渐进式渲染
         emphasis: {
           itemStyle: {
             shadowBlur: 10,

+ 3 - 1
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/boxPlot.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-27 15:20:57
- * @LastEditTime: 2024-11-27 17:09:21
+ * @LastEditTime: 2024-12-26 09:56:13
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/boxPlot.js
@@ -110,6 +110,8 @@ export function handleBoxPlotChartLogic(
     // 添加到 series
     item.option.series.push({
       type: "boxplot",
+      progressiveThreshold: 3000, // 当数据量超过3000时启用渐进式渲染
+      progressive: true, // 启用渐进式渲染
       data: boxplotData,
     });
   }

+ 2 - 0
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/cp.js

@@ -9,6 +9,8 @@ function generateSeriesData(dataSource, xData, yData, labelKey) {
       name: item.label,
       type: labelKey, // 'line' 或 'scatter'
       renderMode: "webgl", // 启用 WebGL 渲染
+      progressiveThreshold: 3000, // 当数据量超过3000时启用渐进式渲染
+      progressive: true, // 启用渐进式渲染
       showSymbol: labelKey === "line" ? true : undefined,
       // itemStyle: {
       //   color: colorPalette[ind], // 为风机A的散点设置单独的颜色

+ 3 - 1
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/pareto.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-27 09:59:10
- * @LastEditTime: 2024-11-27 14:32:23
+ * @LastEditTime: 2024-12-26 09:57:24
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/pareto.js
@@ -37,6 +37,8 @@ function generateSeriesData(dataSource, xData, yData, labelKey) {
       name: item.label,
       type: labelKey, // 'line' 或 'bar'
       renderMode: "webgl", // 启用 WebGL 渲染
+      progressiveThreshold: 3000, // 当数据量超过3000时启用渐进式渲染
+      progressive: true, // 启用渐进式渲染
       showBackground: true,
       smooth: labelKey === "line" ? true : undefined,
       lineStyle:

+ 3 - 1
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/pie.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-26 16:33:45
- * @LastEditTime: 2024-11-26 17:31:22
+ * @LastEditTime: 2024-12-26 09:57:53
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/pie.js
@@ -67,6 +67,8 @@ export function handlePieChartLogic(
       name: yItem.label,
       type,
       radius: "60%",
+      progressiveThreshold: 3000, // 当数据量超过3000时启用渐进式渲染
+      progressive: true, // 启用渐进式渲染
       data:
         yItem.data &&
         yItem.data.map((val, valIndex) => {

+ 3 - 1
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/radar.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-21 09:40:55
- * @LastEditTime: 2024-11-22 14:04:16
+ * @LastEditTime: 2024-12-26 09:58:03
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/radar.js
@@ -123,6 +123,8 @@ export function handleRadarChartLogic(
     item.option.series = [
       {
         type: "radar",
+        progressiveThreshold: 3000, // 当数据量超过3000时启用渐进式渲染
+        progressive: true, // 启用渐进式渲染
         data: seriesData,
       },
     ];

+ 3 - 1
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/roseChart.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-26 16:33:38
- * @LastEditTime: 2024-11-26 17:21:35
+ * @LastEditTime: 2024-12-26 09:58:11
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/roseChart.js
@@ -77,6 +77,8 @@ export function handleRoseChartChartLogic(
       name: yitem.label,
       type: "bar",
       coordinateSystem: "polar",
+      progressiveThreshold: 3000, // 当数据量超过3000时启用渐进式渲染
+      progressive: true, // 启用渐进式渲染
       data:
         yitem.data &&
         yitem.data.map((val) => {

+ 3 - 1
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/sankeyDiagram.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-27 17:15:51
- * @LastEditTime: 2024-11-28 10:24:14
+ * @LastEditTime: 2024-12-26 09:58:23
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/sankeyDiagram.js
@@ -109,6 +109,8 @@ export function handleSankeyDiagramPlotChartLogic(
         emphasis: {
           focus: "adjacency",
         },
+        progressiveThreshold: 3000, // 当数据量超过3000时启用渐进式渲染
+        progressive: true, // 启用渐进式渲染
         data: uniqueXData,
         links: sankeyDiagramData,
         lineStyle: {

+ 70 - 181
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/scatter.js

@@ -1,115 +1,6 @@
 //散点图+散点折线图
 import { filterData } from "../dargChartFIlter";
-// export function handleScatterChartLogic(
-//   item, //curEdit编辑项配置
-//   formLabelAlign, //每一项label显示
-//   formFilterAlign, //过滤数据 数据筛选from
-//   isFilter, //是否是过滤
-//   type //图表类型
-// ) {
-//   // 封装柱状图的具体逻辑
-//   if (isFilter === "filter") {
-//     // 数据筛选逻辑
-//     const filterResult = formLabelAlign.Ydata.map((yItem, index) => ({
-//       label: yItem.label,
-//       id: yItem.id,
-//       data: yItem.data.map((val) => {
-//         const filters = formFilterAlign[index]?.filters || [];
-//         return val === null ||
-//           (filters.length > 0 && !filters.includes(val[yItem.label]))
-//           ? null
-//           : val;
-//       }),
-//     }));
-//     // 条件筛选逻辑
-//     const filterList = filterResult.map((filteredItem, index) => {
-//       const filter = formFilterAlign[index];
-//       const { filterType1, filterType2, number1, number2 } = filter;
-//       if (
-//         (number1 === null || number1 === "") &&
-//         (number2 === null || number2 === "")
-//       ) {
-//         return {
-//           label: filteredItem.label,
-//           id: filteredItem.id,
-//           data: filteredItem.data,
-//         };
-//       } else {
-//         const filterDatas = filterData(
-//           filter,
-//           filteredItem.data,
-//           filteredItem.label
-//         );
-//         return {
-//           label: filteredItem.label,
-//           id: filteredItem.id,
-//           data: [...filterDatas],
-//         };
-//       }
-//     });
-//     item.Xdata = formLabelAlign.Xdata;
-//     item.Ydata = filterList;
-//   } else {
-//     item.Xdata = formLabelAlign.Xdata;
-//     item.Ydata = formLabelAlign.Ydata;
-//   }
-//   item.option.xAxis = {
-//     ...item.option.xAxis,
-//     type: "value",
-//     name: formLabelAlign.Xlable,
-//   };
-//   item.option.yAxis = {
-//     ...item.option.yAxis,
 
-//     name: formLabelAlign.Ylable,
-//   };
-
-//   if (item.Ydata[0]?.data?.length > 0 || item.Xdata[0]?.data?.length > 0) {
-//     // console.log(item.Xdata, "item.Xdata", item.Ydata);
-//     item.option.series = (
-//       item.Xdata.length > item.Ydata.length ? item.Xdata : item.Ydata
-//     ).map((val, ind) => {
-//       const xData = item.Xdata[ind]?.data || [];
-//       const yData = item.Ydata[ind]?.data || [];
-
-//       const scatterData = xData
-//         .map((xItem, idx) => {
-//           const yItem = yData[idx];
-//           if (!xItem || !yItem) return null; // 如果对应项不存在,则跳过
-//           return [
-//             Number(
-//               xItem[item.Xdata[ind].label] === undefined
-//                 ? 0
-//                 : xItem[item.Xdata[ind].label]
-//             ) || 0, // 取 X 值
-//             Number(
-//               yItem[item.Ydata[ind].label] === undefined
-//                 ? 0
-//                 : yItem[item.Ydata[ind].label]
-//             ) || 0, // 取 Y 值
-//           ];
-//         })
-//         .filter((point) => point !== null); // 过滤掉无效的点
-
-//       return {
-//         name: `${item.Xdata[ind]?.label || "X"} - ${
-//           item.Ydata[ind]?.label || "Y"
-//         }`,
-//         type: type,
-//         renderMode: "webgl", // 启用 WebGL 渲染
-//         data: scatterData, // 生成的散点图数据
-//         tooltip: {
-//           trigger: "item", // 鼠标悬停触发
-//         },
-//         itemStyle: {
-//           shadowBlur: 3,
-//           shadowColor: "rgba(25, 100, 150, 0.3)",
-//           shadowOffsetY: 1.5,
-//         },
-//       };
-//     });
-//   }
-// }
 export function handleScatterChartLogic(
   item, // curEdit编辑项配置
   formLabelAlign, // 每一项label显示
@@ -130,7 +21,6 @@ export function handleScatterChartLogic(
           : val;
       }),
     }));
-
     const filterList = filterResult.map((filteredItem, index) => {
       const filter = formFilterAlign[index];
       const { filterType1, filterType2, number1, number2 } = filter;
@@ -205,92 +95,91 @@ export function handleScatterChartLogic(
           item.Ydata[ind]?.label || "Y"
         }`,
         type: type,
+        progressiveThreshold: 3000, // 当数据量超过3000时启用渐进式渲染
+        progressive: true, // 启用渐进式渲染
         renderMode: "webgl", // 启用 WebGL 渲染
         data: scatterData, // 生成的散点图数据
         tooltip: {
           trigger: "item", // 鼠标悬停触发
         },
-        itemStyle: {
-          shadowBlur: 3,
-          shadowColor: "rgba(25, 100, 150, 0.3)",
-          shadowOffsetY: 1.5,
-        },
+        // itemStyle: {
+        //   shadowBlur: 3,
+        //   shadowColor: "rgba(25, 100, 150, 0.3)",
+        //   shadowOffsetY: 1.5,
+        // },
       };
     });
 
     // 记录选中的散点
-    const selectedPoints = [];
-
-    // 点击事件的处理函数
-    function handleClick(event) {
-      const selectedIndex = event.dataIndex;
-      const scatterData = item.option.series[0].data;
-
-      // 获取点击点的坐标
-      const xClick = event.data[0];
-      const yClick = event.data[1];
-
-      // 判断该点是否已经被选中
-      const existingIndex = selectedPoints.findIndex(
-        (point) => point.index === selectedIndex
-      );
-
-      if (existingIndex === -1) {
-        // 如果没有选中,则加入
-        selectedPoints.push({
-          index: selectedIndex,
-          x: xClick,
-          y: yClick,
-        });
-      } else {
-        // 如果已经选中,则取消选中
-        selectedPoints.splice(existingIndex, 1);
-      }
-
-      // 更新选中点的样式
-      const newColors = scatterData.map((point, index) => {
-        // 如果该点在 selectedPoints 中,则改变其颜色
-        if (
-          selectedPoints.some((selectedPoint) => selectedPoint.index === index)
-        ) {
-          return "red"; // 选中点为红色
-        }
-        return point[0] && point[1] ? "#000" : "transparent"; // 默认颜色,未选中点为黑色
-      });
-
-      const newSizes = scatterData.map((point, index) => {
-        // 如果该点在 selectedPoints 中,则增大其大小
-        if (
-          selectedPoints.some((selectedPoint) => selectedPoint.index === index)
-        ) {
-          return 10; // 选中点大小为 10
-        }
-        return 5; // 默认大小
-      });
-
-      // 更新图表的颜色和大小
-      item.option.series[0].itemStyle = {
-        color: newColors,
-        size: newSizes,
-      };
-
-      // 通过重新设置 `option` 来更新图表
-      if (item.chartInstance) {
-        item.chartInstance.setOption(item.option);
-      }
-    }
-
+    // const selectedPoints = [];
+    // // 点击事件的处理函数
+    // function handleClick(event) {
+    //   const selectedIndex = event.dataIndex;
+    //   const scatterData = item.option.series[0].data;
+
+    //   // 获取点击点的坐标
+    //   const xClick = event.data[0];
+    //   const yClick = event.data[1];
+
+    //   // 判断该点是否已经被选中
+    //   const existingIndex = selectedPoints.findIndex(
+    //     (point) => point.index === selectedIndex
+    //   );
+
+    //   if (existingIndex === -1) {
+    //     // 如果没有选中,则加入
+    //     selectedPoints.push({
+    //       index: selectedIndex,
+    //       x: xClick,
+    //       y: yClick,
+    //     });
+    //   } else {
+    //     // 如果已经选中,则取消选中
+    //     selectedPoints.splice(existingIndex, 1);
+    //   }
+
+    //   // 更新选中点的样式
+    //   const newColors = scatterData.map((point, index) => {
+    //     // 如果该点在 selectedPoints 中,则改变其颜色
+    //     if (
+    //       selectedPoints.some((selectedPoint) => selectedPoint.index === index)
+    //     ) {
+    //       return "red"; // 选中点为红色
+    //     }
+    //     return point[0] && point[1] ? "#000" : "transparent"; // 默认颜色,未选中点为黑色
+    //   });
+
+    //   const newSizes = scatterData.map((point, index) => {
+    //     // 如果该点在 selectedPoints 中,则增大其大小
+    //     if (
+    //       selectedPoints.some((selectedPoint) => selectedPoint.index === index)
+    //     ) {
+    //       return 10; // 选中点大小为 10
+    //     }
+    //     return 5; // 默认大小
+    //   });
+
+    //   // 更新图表的颜色和大小
+    //   item.option.series[0].itemStyle = {
+    //     color: newColors,
+    //     size: newSizes,
+    //   };
+
+    //   // 通过重新设置 `option` 来更新图表
+    //   if (item.chartInstance) {
+    //     item.chartInstance.setOption(item.option);
+    //   }
+    // }
     // 绑定点击事件
     item.option.series[0].emphasis = {
       itemStyle: {
         color: "red",
       },
     };
-
     // 添加点击事件
-    if (item.chartInstance) {
-      item.chartInstance.off("click"); // 先移除之前的事件
-      item.chartInstance.on("click", handleClick); // 然后绑定新的点击事件
-    }
+    // if (item.chartInstance) {
+    //   item.chartInstance.off("click"); // 先移除之前的事件
+    //   item.chartInstance.on("click", handleClick); // 然后绑定新的点击事件
+    // }
   }
 }

+ 3 - 1
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/stackedBar.js

@@ -1,7 +1,7 @@
 /*
  * @Author: your name
  * @Date: 2024-11-27 09:36:28
- * @LastEditTime: 2024-11-27 17:16:20
+ * @LastEditTime: 2024-12-26 09:59:03
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartLogic/modules/stackedBar.js
@@ -80,6 +80,8 @@ export function handlestackedBarChartLogic(
         name: item.label,
         type: "bar",
         stack: "d",
+        progressiveThreshold: 3000, // 当数据量超过3000时启用渐进式渲染
+        progressive: true, // 启用渐进式渲染
         data: item.data.map(
           (data) => parseFloat(data !== null && data[item.label]) || 0
         ), // 将数据转换为数值

+ 2 - 2
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/chartTitle.vue

@@ -113,7 +113,7 @@
               content="添加指标值"
               placement="bottom-start"
               v-if="
-                curEdit.type !== 'roseChart' &&
+                // curEdit.type !== 'roseChart' &&
                 curEdit.type !== 'pie' &&
                 curEdit.type !== 'sankeyDiagram' &&
                 curEdit.type !== 'Heatmap'
@@ -155,7 +155,7 @@
               </el-select>
               <el-tooltip
                 v-if="
-                  curEdit.type !== 'roseChart' &&
+                  // curEdit.type !== 'roseChart' &&
                   curEdit.type !== 'pie' &&
                   curEdit.type !== 'sankeyDiagram' &&
                   curEdit.type !== 'Heatmap'

+ 13 - 2
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/configFn.js

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2024-11-12 09:27:50
- * @LastEditTime: 2024-11-19 15:30:26
- * @LastEditors: milo-MacBook-Pro.local
+ * @LastEditTime: 2024-12-26 09:55:59
+ * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/configFn.js
  */
@@ -28,9 +28,20 @@ export const getFormattedSeries = (data, chartType) => {
     series.push({
       name: item.label,
       type: chartType,
+      progressiveThreshold: 3000, // 当数据量超过3000时启用渐进式渲染
+      progressive: true, // 启用渐进式渲染
       data: item.data.map(
         (data) => parseFloat(data !== null && data[item.label]) || 0
       ), // 将数据转换为数值
+      markPoint: {
+        data: [
+          { type: "max", name: "Max" },
+          { type: "min", name: "Min" },
+        ],
+      },
+      markLine: {
+        data: [{ type: "average", name: "Avg" }],
+      },
     });
   });
   return series;

+ 2 - 2
src/views/performance/components/custonAsCom/dragChart/components/chartsContent.vue

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2024-11-01 10:14:11
- * @LastEditTime: 2024-11-12 15:05:25
+ * @LastEditTime: 2024-12-24 14:35:12
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartsContent.vue
@@ -122,7 +122,7 @@ export default {
   },
   methods: {
     ...mapMutations("dragChart", [
-      "scaleScreen",
+      // "scaleScreen",
       "setCurrentChartList",
       "addChart",
       "updateChart",

+ 40 - 2
src/views/performance/components/custonAsCom/dragChart/components/chartsData.vue

@@ -70,6 +70,7 @@ export default {
             ? [...Object.keys(item.fileData[0])].map((val) => ({
                 label: val,
                 id: item.fileId + val,
+                parentId: item.fileId,
                 fileData: item.fileData,
               }))
             : [],
@@ -99,8 +100,42 @@ export default {
     },
     handleNodeClick(data) {
       this.selectedNodeId = data.id;
-
-      this.updateDataBase(this.$refs.tree.getCheckedNodes());
+      if (
+        this.$refs.tree.getCheckedNodes() &&
+        this.$refs.tree.getCheckedNodes().length > 0
+      ) {
+        let newDatas = [];
+        this.$refs.tree
+          .getCheckedNodes()
+          .filter((obj) => obj.children === undefined)
+          .map((item) => {
+            const index = newDatas.findIndex(
+              (val) => item.parentId === val.parentId
+            );
+            if (index === -1) {
+              newDatas.push({
+                fileData: item.fileData,
+                fileObj: [
+                  { id: item.id, label: item.label, parentId: item.parentId },
+                ],
+                parentId: item.parentId,
+              });
+            } else {
+              newDatas[index].fileObj.push({
+                id: item.id,
+                label: item.label,
+                parentId: item.parentId,
+              });
+            }
+          });
+        console.log(newDatas, "newDatas");
+        // checkData=[{fileData:[],fileObj:[{}],parentId:''}]
+        this.updateDataBase(
+          this.$refs.tree
+            .getCheckedNodes()
+            .filter((obj) => obj.children === undefined)
+        );
+      }
     },
     // 父节点复选框改变时递归设置子节点状态
     handleParentNodeChange(node, isChecked) {
@@ -166,6 +201,9 @@ export default {
 </script>
 
 <style scoped lang="scss">
+.el-tree {
+  overflow: hidden !important;
+}
 .chartContiner {
   background-color: skyblue;
   width: 300px;

+ 52 - 45
src/views/performance/components/custonAsCom/luckySheet.vue

@@ -46,7 +46,7 @@ export default {
   methods: {
     async initSheetData() {
       const jsonData = await getDataFromIndexedDB();
-      console.log(jsonData, "jsonData");
+
       if (jsonData && jsonData.length > 0) {
         this.sheetName = [...jsonData].filter(
           (item) => item.fileId == this.$route.query.id
@@ -65,15 +65,18 @@ export default {
         formattedData.unshift(headers);
         //4.  将 JSON 数据转换为 Luckysheet 格式
         this.initLuckySheet(formattedData);
+      } else {
+        this.$message.warning("暂无数据,请先进行数据导入");
+        this.$router.push("/home/performance/customAnalysis");
       }
     },
-    initLuckySheet(formattedData) {
+    async initLuckySheet(formattedData) {
       const options = {
         container: "luckysheet",
         showReturnIcon: false, // 假设有这个选项
         data: [
           {
-            name: this.sheetName, //工作表名称
+            name: await this.truncateString(this.sheetName), //工作表名称
             index: 0, //工作表索引
             status: 1, //激活状态
             order: 0, //工作表的下标
@@ -131,6 +134,7 @@ export default {
         lang: "zh", // 语言设置
         showtoolbar: true, // 是否显示工具栏
         chart: {
+          //
           // 配置图表
           enable: false, // 启用图表功能
         },
@@ -140,46 +144,6 @@ export default {
       };
       luckysheet.create(options);
     },
-    // async saveData() {
-    //   // 获取当前表格的数据
-    //   const data = luckysheet.getAllSheets()[0].data; // 目前只需处理第一个工作表的数据
-    //   const formattedData = [];
-    //   // 获取表头 (假设表头在第一行,行索引为0)
-    //   const headers = data[0].map((cell) => (cell && cell.v ? cell.v : "")); // 提取表头内容
-    //   // 遍历数据行,从第二行开始 (行索引为1)
-    //   for (let i = 1; i < data.length; i++) {
-    //     const row = data[i];
-    //     const rowData = {};
-    //     // 遍历每一列,并根据表头动态生成键值对
-    //     for (let j = 0; j < headers.length; j++) {
-    //       if (row[j] && (row[j].v || row[j].v == 0)) {
-    //         rowData[headers[j]] = row[j].v || 0;
-    //       }
-    //     }
-    //     // 如果行数据不为空,加入到结果数组中
-    //     if (Object.keys(rowData).length) {
-    //       formattedData.push(rowData);
-    //     }
-    //   }
-
-    //   this.sheetData = JSON.stringify(formattedData, null, 2);
-    //   await initDatabase()
-    //     .then((database) => {
-    //       // 调用 storeSetData 方法
-    //       let fileData = {
-    //         filename: format(new Date(), "yyyyMMdd-HH:mm:ss") + this.sheetName,
-    //         fileData: JSON.parse(this.sheetData),
-    //         fileOldName: this.sheetName,
-    //         fileId: new Date().getTime(),
-    //       };
-    //       storeSetData(database, "files", "fileDataArray", fileData, () => {
-    //         this.$router.push("/home/performance/customAnalysis");
-    //       });
-    //     })
-    //     .catch((error) => {
-    //       console.error("数据库初始化失败,无法继续存储数据。", error);
-    //     });
-    // },
     async saveData() {
       // 获取所有工作表
       const sheets = luckysheet.getAllSheets();
@@ -204,7 +168,6 @@ export default {
             formattedData.push(rowData);
           }
         }
-
         // 生成唯一的 fileData
         const fileData = {
           filename:
@@ -213,7 +176,6 @@ export default {
           fileOldName: sheet.name + "_" + ind,
           fileId: new Date().getTime() + "_" + ind,
         };
-
         allFileData.push(fileData); // 将当前工作表的文件数据加入到数组中
       });
 
@@ -232,6 +194,51 @@ export default {
           console.error("数据库初始化失败,无法继续存储数据。", error);
         });
     },
+    truncateString(str) {
+      return new Promise((resolve, reject) => {
+        // 如果字符串长度超过30
+        if (str.length > 30) {
+          this.$confirm(
+            "sheet页名长度已超过31个字符,可能会影响后续对函数的使用,是否需要进行自动截取?",
+            "提示",
+            {
+              confirmButtonText: "确定",
+              cancelButtonText: "取消",
+              type: "warning",
+            }
+          )
+            .then(() => {
+              const suffixes = [".csv", ".xlsx", ".xls"];
+              let truncatedFilename = str;
+
+              // 查找文件名中的后缀位置并进行截取
+              for (let suffix of suffixes) {
+                const suffixIndex = str.lastIndexOf(suffix);
+
+                // 如果找到了后缀,进行截取
+                if (suffixIndex !== -1) {
+                  // 截取文件名,确保不超过31个字符
+                  truncatedFilename =
+                    str.slice(0, 31 - suffix.length) + str.slice(suffixIndex);
+                  break;
+                }
+              }
+              resolve(truncatedFilename);
+            })
+            .catch(() => {
+              // 用户取消时返回原始的str
+              this.$message({
+                type: "info",
+                message: "已取消删除",
+              });
+              resolve(str);
+            });
+        } else {
+          // 字符串长度不超过30,直接返回原字符串
+          resolve(str);
+        }
+      });
+    },
   },
 };
 </script>

+ 1 - 0
src/views/performance/components/map.vue

@@ -1,5 +1,6 @@
 <template>
   <div class="map-ditu">
+    <!-- 分析事件中 风场信息展示地图组件 -->
     <Tmap
       ref="map"
       :windEngineGroupByFieldCodeDetail="windEngineGroupByFieldCodeDetail"

+ 128 - 64
src/views/performance/customAnalysis.vue

@@ -1,5 +1,5 @@
 <template>
-  <div class="content" v-loading="loading">
+  <div class="content">
     <el-tabs
       ref="tabs"
       tab-position="left"
@@ -14,6 +14,7 @@
               <el-upload
                 action=""
                 class="upload-demo"
+                multiple
                 :http-request="customUpload"
                 :on-change="validateAndHandleChange"
                 :before-upload="checkFileType"
@@ -102,7 +103,6 @@
             </span>
           </el-tooltip>
         </span>
-        计算器弹出框
       </el-tab-pane>
       <el-tab-pane name="associatedFields">
         <span slot="label" class="iconFont">
@@ -126,7 +126,9 @@
     <el-dialog
       title="数据列表特征计算函数"
       :visible.sync="dialogVisible"
+      element-loading-background="rgba(0, 0, 0, 0.8)"
       width="600px"
+      v-loading="loading"
       :before-close="handleClose"
     >
       <el-form
@@ -293,7 +295,6 @@ export default {
       "setTriggerGetData",
       "setUpdateTriggerGetData",
     ]),
-
     async initDB() {
       return new Promise((resolve, reject) => {
         const request = indexedDB.open("FileDataDB", 2); // 使用较高版本
@@ -333,38 +334,64 @@ export default {
       console.log(this.options, "调用数据");
     },
     async submitComputedFn(formName) {
+      this.loading = true;
       try {
         // 1. 验证表单
-        if (!(await this.validateForm(formName))) return;
+        if (!(await this.validateForm(formName))) {
+          this.loading = false;
+          return;
+        }
         if (Number(this.ruleForm.max) < Number(this.ruleForm.min)) {
           this.$message.error("开始行不可以大于结束行");
+          this.loading = false;
           return;
         }
         // 2. 获取 IndexedDB 数据
         const indexeddbData = await getDataFromIndexedDB();
         const region = this.getRegionData(indexeddbData);
-
         if (!region.length) {
           console.warn("当前选择的列未找到数据");
+          this.loading = false;
           return;
         }
-
+        let newDatas = [];
+        if (region[0].length > 500) {
+          if (!Number(this.ruleForm.min) || !Number(this.ruleForm.max)) {
+            this.$message.warning("每次最多选择范围在500条内。请输入数据范围");
+            this.loading = false;
+            return;
+          }
+          newDatas = region[0].slice(
+            Number(this.ruleForm.min) - 1,
+            Number(this.ruleForm.max) - 1
+          );
+          if (newDatas.length > 500) {
+            this.$message.warning(
+              "由于列数据过长,为了保证页面操作流畅,每次最多选择范围在500条内。请分批次选择。"
+            );
+            this.loading = false;
+            return;
+          }
+        } else {
+          newDatas = region[0];
+          this.loading = false;
+        }
         // 3. 调用算法接口
-        const resData = await this.fetchAlgorithmData(region[0]);
-
+        const resData = await this.fetchAlgorithmData(newDatas);
         // 4. 筛选和处理数据
         const filteredData = this.filterResponseData(resData);
-
         // 5. 构建导出数据
         const resObj = this.buildExportData(indexeddbData, filteredData);
         this.storeData(resObj);
         this.resetForm();
-        console.log(resObj, "resObj");
+        this.loading = false;
+        this.$message.success("成功");
       } catch (error) {
         console.error("提交过程中发生错误:", error);
+        this.$message.error(error);
+        this.loading = false;
       }
     },
-
     async validateForm(formName) {
       try {
         const valid = await this.$refs[formName].validate();
@@ -446,7 +473,7 @@ export default {
       }
       resObj.filename =
         format(new Date(), "yyyyMMdd-HH:mm:ss") + resObj.fileOldName;
-      resObj.fileId = new Date().getTime();
+      resObj.fileId = new Date().getTime() + "";
       resObj.fileData = resData.map((item) => {
         const dynamicKeys = this.ruleForm.type.reduce((acc, label) => {
           const fieldName = this.selectedNames.find(
@@ -466,7 +493,6 @@ export default {
 
       return resObj;
     },
-
     resetForm() {
       this.ruleForm = {
         max: "",
@@ -476,7 +502,6 @@ export default {
       };
       this.dialogVisible = false; // 重置表单状态
     },
-
     async storeData(newFileData) {
       await storeSetData(this.db, "files", "fileDataArray", newFileData, () => {
         this.setTriggerGetData(true);
@@ -508,46 +533,98 @@ export default {
       const formData = new FormData();
       formData.append("file", file);
       // 使用 axios 自定义上传逻辑
+      console.log("自定义上传", file.name);
     },
     // 验证并处理文件变化
-    validateAndHandleChange(file) {
-      if (this.checkFileType(file)) {
-        this.handleChange(file); // 仅当验证通过时调用 handleChange
+    validateAndHandleChange(fileList) {
+      // 判断 fileList 是否为数组(多个文件)还是单个文件
+      if (Array.isArray(fileList)) {
+        // 如果是数组(多个文件),遍历每个文件进行处理
+        fileList.forEach((file) => {
+          if (this.checkFileType(file)) {
+            this.handleChange(file); // 验证通过后逐一处理
+          }
+        });
+      } else {
+        // 如果是单个文件,直接处理
+        if (this.checkFileType(fileList)) {
+          this.handleChange(fileList);
+        }
+      }
+    },
+    // 检查文件类型&多个文件选择,但多个文件总数大小不能超过50KB
+    checkFileType(file) {
+      // 判断文件类型
+      const isValidType =
+        file.type === "text/csv" ||
+        file.name.endsWith(".csv") ||
+        file.type ===
+          "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ||
+        file.name.endsWith(".xlsx") ||
+        file.name.endsWith(".xls");
+
+      if (!isValidType) {
+        this.$message.error("只能上传csv文件或xlsx或xls文件");
+        return false; // 返回false,阻止上传
       }
+      // 判断文件大小(以字节为单位,50KB = 51200字节)
+      const maxSize = 50 * 1024; // 50KB
+      if (file.size > maxSize) {
+        this.$message.error("文件大小不能超过50KB");
+        return false; // 返回false,阻止上传
+      }
+      return true; // 如果验证通过,允许上传
     },
-    // 文件变化时的处理
+
+    // 处理文件
     handleChange(file) {
-      this.checkFileType(file);
-      //csv 本身不支持多个sheet 页 ,所有以这里不需要循环处理
-      if (file && file.name.endsWith(".csv")) {
-        Papa.parse(file.raw, {
-          header: true,
-          complete: (results) => {
-            // 可以进一步处理解析后的数据
-            const fileData = {
-              filename: format(new Date(), "yyyyMMdd-HH:mm:ss") + file.name,
-              fileOldName: file.name,
-              fileData: results.data,
-              fileId: new Date().getTime(),
-            };
-            if (results.data.length > 0) {
-              this.storeData(fileData);
+      // 如果是 CSV 文件
+      if (file.name.endsWith(".csv")) {
+        const reader = new FileReader();
+        reader.onload = (e) => {
+          const encoding = this.detectFileEncoding(e.target.result);
+          const text = new TextDecoder(encoding).decode(
+            new Uint8Array(e.target.result)
+          );
+
+          // 使用 Papa.parse 解析 CSV 数据
+          Papa.parse(text, {
+            header: true, // 第一行作为表头
+            complete: (results) => {
+              const newData = results.data.slice(0, results.data.length - 1);
+              const fileData = {
+                filename: format(new Date(), "yyyyMMdd-HH:mm:ss") + file.name,
+                fileOldName: file.name,
+                fileData: newData,
+                fileId:
+                  new Date().getTime() + "_" + Math.floor(Math.random() * 1000),
+              };
+              if (results.data.length > 0) {
+                this.storeData(fileData);
+                this.loading = false;
+              }
+            },
+            error: (error) => {
+              console.error("Error parsing CSV:", error);
               this.loading = false;
-            }
-          },
-          error: (error) => {
-            console.error("Error parsing CSV:", error);
-            this.loading = false;
-          },
-        });
+            },
+          });
+        };
+        reader.readAsArrayBuffer(file.raw);
       } else {
+        // 如果是 Excel 文件
         const reader = new FileReader();
         reader.onload = (e) => {
           const data = new Uint8Array(e.target.result);
+          // 读取 Excel 文件
           const workbook = XLSX.read(data, { type: "array" });
+
           workbook.SheetNames.forEach((sheetName, ind) => {
             const sheetData = XLSX.utils.sheet_to_json(
-              workbook.Sheets[sheetName]
+              workbook.Sheets[sheetName],
+              {
+                defval: "", // 确保空值不会导致错误
+              }
             );
             const fileData = {
               filename:
@@ -560,34 +637,18 @@ export default {
               this.storeData(fileData);
               this.loading = false;
             }
-            // console.log("Parsed Excel Sheet Data:", sheetData);
-            // 可以进一步处理解析后的数据
           });
         };
         reader.readAsArrayBuffer(file.raw);
       }
     },
-    //判断上传文件类型
-    checkFileType(file) {
-      const isPdf =
-        file.type === "text/csv" ||
-        file.name.endsWith(".csv") ||
-        file.type ===
-          "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ||
-        file.name.endsWith(".xlsx") ||
-        file.name.endsWith(".xls");
-      if (!isPdf) {
-        this.$message.error("只能上传csv文件或xlsx或xls文件");
-        return false;
-      }
-      // 判断文件大小(以字节为单位,100kB = 102400字节)
-      const maxSize = 50 * 1024; // 100kB
-      if (file.size > maxSize) {
-        this.$message.error("文件大小不能超过50kB");
-        return false;
+    // 检测文件编码的方法
+    detectFileEncoding(arrayBuffer) {
+      const text = new TextDecoder("utf-8").decode(new Uint8Array(arrayBuffer));
+      if (text.includes("�")) {
+        return "gbk"; // 如果有乱码字符,可能是 GBK 编码
       }
-      this.loading = true;
-      return true;
+      return "utf-8";
     },
   },
   async mounted() {
@@ -614,8 +675,11 @@ export default {
   .popover-footer {
     text-align: right;
   }
-  .iconFont {
+  ::v-deep .iconFont {
     padding: 0 20px;
+    width: 100% !important;
+    height: 100% !important;
+    display: inline-block;
   }
 
   ::v-deep .el-tabs__content {

+ 1 - 1
vue.config.js

@@ -113,7 +113,7 @@ module.exports = {
       },
       //自定义算法文佳
       "/sAlgorithm": {
-        target: "http://192.168.5.28:8666", // 目标地址
+        target: "http://192.168.50.235:8666", // 目标地址
         changeOrigin: true,
         pathRewrite: {
           "^/sAlgorithm": "", // 如果后端需要 `/api` 前缀