فهرست منبع

图表封装、数据关联

liujiejie 7 ماه پیش
والد
کامیت
d84938f268

+ 12 - 1
src/assets/js/class/chart.js

@@ -8,7 +8,16 @@
  * @params {Number} 图表类型 type
  */
 export default class chartClass {
-  constructor({ type, option, x = 0, y = 0, width = 300, height = 300 }) {
+  constructor({
+    type,
+    option,
+    x = 0,
+    y = 0,
+    width = 300,
+    height = 300,
+    Xdata = [],
+    Ydata = [],
+  }) {
     this.id = Math.random();
     this.option = option;
     this.x = x;
@@ -16,5 +25,7 @@ export default class chartClass {
     this.width = width;
     this.height = height;
     this.type = type;
+    this.Xdata = Xdata;
+    this.Ydata = Ydata;
   }
 }

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

@@ -15,7 +15,6 @@ export const option = {
     containLabel: true, // 包含标签在内
   },
   xAxis: {
-    name: "周",
     type: "category",
     data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
     axisTick: {
@@ -24,7 +23,6 @@ export const option = {
   },
 
   yAxis: {
-    name: "个",
     type: "value",
   },
 

+ 21 - 41
src/assets/js/constants/echarts-config/line.js

@@ -1,82 +1,62 @@
 export const option = {
   title: {
-    text: "堆叠区域图",
+    text: "Stacked Line",
   },
   tooltip: {
     trigger: "axis",
-    axisPointer: {
-      type: "cross",
-      label: {
-        backgroundColor: "#6a7985",
-      },
-    },
   },
   legend: {
-    data: ["邮件营销", "联盟广告", "视频广告", "直接访问", "搜索引擎"],
+    data: ["Email", "Union Ads", "Video Ads", "Direct", "Search Engine"],
   },
+
   toolbox: {
     feature: {
       saveAsImage: {},
     },
   },
+  xAxis: {
+    type: "category",
+    boundaryGap: false,
+    data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
+  },
+  yAxis: {
+    type: "value",
+  },
   grid: {
     top: "20%",
     right: "20%",
     bottom: "10%",
     containLabel: true, // 包含标签在内
   },
-  xAxis: [
-    {
-      type: "category",
-      boundaryGap: false,
-      data: ["周一", "周二", "周三", "周四", "周五", "周六", "周日"],
-    },
-  ],
-  yAxis: [
-    {
-      type: "value",
-    },
-  ],
   series: [
     {
-      name: "邮件营销",
+      name: "Email",
       type: "line",
-      stack: "总量",
-      areaStyle: {},
+      stack: "Total",
       data: [120, 132, 101, 134, 90, 230, 210],
     },
     {
-      name: "联盟广告",
+      name: "Union Ads",
       type: "line",
-      stack: "总量",
-      areaStyle: {},
+      stack: "Total",
       data: [220, 182, 191, 234, 290, 330, 310],
     },
     {
-      name: "视频广告",
+      name: "Video Ads",
       type: "line",
-      stack: "总量",
-      areaStyle: {},
+      stack: "Total",
       data: [150, 232, 201, 154, 190, 330, 410],
     },
     {
-      name: "直接访问",
+      name: "Direct",
       type: "line",
-      stack: "总量",
-      areaStyle: {},
+      stack: "Total",
       data: [320, 332, 301, 334, 390, 330, 320],
     },
     {
-      name: "搜索引擎",
+      name: "Search Engine",
       type: "line",
-      stack: "总量",
-      label: {
-        normal: {
-          show: true,
-          position: "top",
-        },
-      },
-      areaStyle: {},
+      stack: "Total",
       data: [820, 932, 901, 934, 1290, 1330, 1320],
     },
   ],

+ 6 - 1
src/main.js

@@ -4,6 +4,7 @@ import router from "./router";
 import { store } from "./store/index.js";
 // import "./assets/style/element-variables.module.scss";
 import "./icons/index"; // icon
+
 import VueRulerTool from "vue-ruler-tool";
 // 引入element ui
 import ElementUI from "element-ui";
@@ -64,7 +65,11 @@ Vue.prototype.$formatDateTWO = function (timestamp) {
   // const seconds = String(date.getSeconds()).padStart(2, "0");:${seconds}
   return `${year}-${month}-${day} ${hours}:${minutes}`;
 };
-
+// 监听页面刷新或关闭事件
+window.addEventListener("beforeunload", () => {
+  // 调用清空 Vuex 仓库的 Action
+  store.commit("dragChart/clearchart");
+});
 new Vue({
   router,
   store,

+ 38 - 3
src/store/dragChart.js

@@ -1,8 +1,8 @@
 /*
  * @Author: your name
  * @Date: 2024-11-04 10:06:23
- * @LastEditTime: 2024-11-07 16:01:46
- * @LastEditors: milo-MacBook-Pro.local
+ * @LastEditTime: 2024-11-14 16:02:22
+ * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/store/dragChart.js
  */
@@ -13,6 +13,9 @@ const _ = require("lodash");
 export default {
   namespaced: true,
   state: {
+    triggerGetData: false,
+    updateTriggerGetData: false,
+    relatedFieldsData: [], //关联字段表
     curEdit: {}, // 当前编辑的图表
     currentChartList: [], // 当前文件的当前数据
     originChartList: [], // 当前文件的原始数据
@@ -20,6 +23,31 @@ export default {
     dataBaseCheckList: {},
   },
   mutations: {
+    setUpdateTriggerGetData(state, value) {
+      state.updateTriggerGetData = value;
+    },
+    setTriggerGetData(state, value) {
+      state.triggerGetData = value;
+    },
+    setRelatedFieldsData(state, data) {
+      console.log(data);
+      state.relatedFieldsData = [...state.relatedFieldsData, { ...data }];
+    },
+    // 清空图表
+    clearchart(state) {
+      const resetState = {
+        curEdit: {},
+        currentChartList: [],
+        originChartList: [],
+        fileList: [],
+        dataBaseCheckList: {},
+      };
+
+      // 遍历重置每个字段
+      Object.keys(resetState).forEach((key) => {
+        state[key] = resetState[key];
+      });
+    },
     // 设置当前编辑的图表
     setCurEdit(state, data) {
       state.curEdit = data;
@@ -27,14 +55,21 @@ export default {
 
     // 当前画布添加图表
     addChart(state, data) {
-      state.currentChartList.push(data);
+      //   console.log("当前画布添加图表", data);
+      if (state.currentChartList.length <= 0) {
+        state.currentChartList.push({ ...data, index: 0 });
+      } else {
+        state.currentChartList.push(data);
+      }
     },
     //更新数据配置当前选中数据
     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],

+ 9 - 5
src/utils/indexedDb.js

@@ -56,20 +56,24 @@ export function checkObjectStoreExists(dbName, storeName) {
 // 获取indexedDB所有数据
 export async function getDataFromIndexedDB() {
   return new Promise((resolve, reject) => {
-    // 不指定版本号以使用现有的最新版本
     const request = indexedDB.open("FileDataDB");
 
     request.onsuccess = (event) => {
       const db = event.target.result;
       const transaction = db.transaction(["files"], "readonly");
       const store = transaction.objectStore("files");
-      const getRequest = store.get("fileDataArray");
 
+      // 使用 getAll() 方法获取全部数据
+      const getRequest = store.getAll();
       getRequest.onsuccess = () => {
-        if (getRequest.result) {
-          resolve(getRequest.result.data); // 返回数组数据
+        if (getRequest.result && getRequest.result.length > 0) {
+          // 假设获取的数据中包含 fileDataArray 数据
+          const fileData = getRequest.result.find(
+            (item) => item.id === "fileDataArray"
+          );
+          resolve(fileData ? fileData.data : []); // 返回文件数据或空数组
         } else {
-          resolve([]); // 若数据库为空,返回空数组
+          resolve([]); // 数据库为空时返回空数组
         }
       };
 

+ 295 - 102
src/views/performance/components/custonAsCom/AssociatedFields.vue

@@ -1,92 +1,135 @@
-<!--
- * @Author: your name
- * @Date: 2024-11-06 14:48:36
- * @LastEditTime: 2024-11-06 16:57:25
- * @LastEditors: bogon
- * @Description: In User Settings Edit
- * @FilePath: /performance-test/src/views/performance/components/custonAsCom/AssociatedFields.vue
--->
 <template>
   <div class="associtedFieldsContent">
     <el-row type="flex" class="row-bg" justify="end">
-      <el-button type="primary" @click="drawer = true">新建关联</el-button>
+      <el-button type="primary" @click="handleDrawer">新建关联</el-button>
     </el-row>
-    <el-table :data="tableData" border style="width: 100%">
-      <el-table-column prop="date" label="关联表1" width="300">
+    <el-table :data="relatedFieldsData || []" border style="width: 100%">
+      <el-table-column prop="tableFileName1" label="关联表1"> </el-table-column>
+      <el-table-column prop="tableFileName2" label="关联表2"> </el-table-column>
+      <el-table-column prop="tableFileName1" label="表1关联字段" align="center">
+        <template slot-scope="scope">
+          <div v-for="(item, ind) in scope.row.relatedFields?.formSelection1">
+            <span style="display: inline-block">{{ item.label }}</span>
+          </div>
+        </template>
       </el-table-column>
-      <el-table-column prop="name" label="关联表2" width="300">
+      <el-table-column prop="address" label="" align="center">
+        <template slot-scope="scope">
+          <i
+            style="font-size: 24px; color: #ffc107"
+            class="el-icon-connection"
+          ></i>
+        </template>
+      </el-table-column>
+      <el-table-column prop="tableFileName2" label="表2关联字段" align="center">
+        <template slot-scope="scope">
+          <div v-for="(item, ind) in scope.row.relatedFields?.formSelection2">
+            <span>{{ item.label }}</span>
+          </div>
+        </template>
       </el-table-column>
-      <el-table-column prop="address" label="关联字段"></el-table-column>
     </el-table>
     <el-drawer
       title="新建关联"
       :visible.sync="drawer"
       direction="rtl"
+      width="50%"
       :before-close="handleClose"
     >
       <el-card class="box-card">
         <div slot="header" class="clearfix">
-          <span>关联图表1</span>
-        </div>
-        <el-select
-          v-model="dataChart1"
-          placeholder="请选择"
-          @change="handleSelectData1"
-        >
-          <el-option
-            v-for="item in options"
-            :key="item.id"
-            :label="item.label"
-            :value="item.id"
+          <el-button
+            type="primary"
+            icon="el-icon-circle-plus-outline"
+            @click="
+              formSelection1.push({ label: '', fileData: [], id: '' });
+              formSelection2.push({ label: '', fileData: [], id: '' });
+            "
+            >添加关联字段</el-button
           >
-          </el-option>
-        </el-select>
-        <el-table
-          ref="multipleTable"
-          :data="tableDataChart1"
-          tooltip-effect="dark"
-          style="width: 100%; margin-top: 20px"
-          @selection-change="handleSelectionChange1"
-        >
-          <el-table-column type="selection" width="55"> </el-table-column>
-          <el-table-column label="字段">
-            <template slot-scope="scope">{{ scope.row.label }}</template>
-          </el-table-column>
-        </el-table>
-      </el-card>
+          <el-form
+            :model="ruleForm"
+            :rules="rules"
+            ref="ruleForm"
+            class="demo-ruleForm"
+            label-position="left"
+          >
+            <el-form-item label="关联表名" prop="name">
+              <el-input v-model="ruleForm.name"></el-input>
+            </el-form-item>
+          </el-form>
+        </div>
 
-      <el-card class="box-card">
-        <div slot="header" class="clearfix">
-          <span>关联图表2</span>
+        <div class="flexs">
+          <div class="flexsCenter">
+            <div style="color: #928c8c; margin: 0 0 10px 0">关联表1</div>
+            <el-select
+              v-model="dataChart1"
+              placeholder="请选择"
+              @change="handleSelectData1"
+            >
+              <el-option
+                v-for="item in options"
+                :key="item.id"
+                :label="item.label"
+                :value="item.id"
+              >
+              </el-option>
+            </el-select>
+            <template v-for="(item, ind) in formSelection1">
+              <el-select
+                style="margin: 5px 0"
+                :key="ind + 'select'"
+                v-model="formSelection1[ind].id"
+                placeholder="请先进行数据配置"
+              >
+                <el-option
+                  v-for="item in tableDataChart1"
+                  :label="item.label"
+                  :value="item.id"
+                  :key="item.id"
+                ></el-option>
+              </el-select>
+            </template>
+          </div>
+          <div class="flexsCenter">
+            <div style="color: #928c8c; margin: 0 0 10px 0">关联表2</div>
+            <el-select
+              v-model="dataChart2"
+              placeholder="请选择"
+              @change="handleSelectData2"
+            >
+              <el-option
+                v-for="item in options"
+                :key="item.id"
+                :label="item.label"
+                :value="item.id"
+              >
+              </el-option>
+            </el-select>
+            <template v-for="(item, ind) in formSelection2">
+              <el-select
+                style="margin: 5px 0"
+                :key="ind + 'select'"
+                v-model="formSelection2[ind].id"
+                placeholder="请先进行数据配置"
+              >
+                <el-option
+                  v-for="item in tableDataChart2"
+                  :label="item.label"
+                  :value="item.id"
+                  :key="item.id"
+                ></el-option>
+              </el-select>
+            </template>
+          </div>
         </div>
-        <el-select
-          v-model="dataChart2"
-          placeholder="请选择"
-          @change="handleSelectData2"
-        >
-          <el-option
-            v-for="item in options"
-            :key="item.id"
-            :label="item.label"
-            :value="item.id"
-          >
-          </el-option>
-        </el-select>
-        <el-table
-          ref="multipleTable"
-          :data="tableDataChart2"
-          tooltip-effect="dark"
-          style="width: 100%; margin-top: 20px"
-          @selection-change="handleSelectionChange"
-        >
-          <el-table-column type="selection" width="55"> </el-table-column>
-          <el-table-column label="字段">
-            <template slot-scope="scope">{{ scope.row.label }}</template>
-          </el-table-column>
-        </el-table>
       </el-card>
       <el-row type="flex" class="row-bg" justify="center">
-        <el-button type="primary" @click="submitAssociated" style="width: 200px"
+        <el-button
+          type="primary"
+          @click="submitAssociated('ruleForm')"
+          style="width: 200px"
           >确定关联</el-button
         >
       </el-row>
@@ -97,60 +140,182 @@
 import {
   getDataFromIndexedDB,
   checkObjectStoreExists,
+  storeSetData,
+  initDatabase,
 } from "@/utils/indexedDb";
+import { mapMutations, mapState } from "vuex";
 export default {
   data() {
     return {
-      tableData: [],
+      ruleForm: {
+        name: "",
+      },
+      rules: {
+        name: [{ required: true, message: "请输入表名称", trigger: "blur" }],
+      },
       drawer: false,
       options: [],
       dataChart1: [],
       dataChart2: [],
+      tableFileName1: "",
+      tableFileName2: "",
+      formSelection1: [{ label: "", fileData: [], id: "" }],
+      formSelection2: [{ label: "", fileData: [], id: "" }],
       tableDataChart1: [],
       tableDataChart2: [],
-      multipleSelection1: [],
-      multipleSelection2: [],
     };
   },
-  async created() {
-    //判断indexedDb中是否存在这个数据表
-    checkObjectStoreExists("FileDataDB", "files")
-      .then((exists) => {
-        if (exists) {
-          console.log("对象存储 'files' 存在!");
-          this.getIndexDbData();
+  async created() {},
+  computed: {
+    ...mapState("dragChart", {
+      relatedFieldsData: "relatedFieldsData",
+    }),
+  },
+  methods: {
+    ...mapMutations("dragChart", [
+      "setRelatedFieldsData",
+      "setTriggerGetData",
+      "setUpdateTriggerGetData",
+    ]),
+    async saveDatas(data) {
+      await initDatabase()
+        .then((database) => {
+          // 调用 storeSetData 方法
+          let fileData = {
+            filename: this.ruleForm.name + "关联表",
+            fileData: data,
+            fileOldName: this.ruleForm.name + "关联表",
+            fileId: new Date().getTime(),
+          };
+          storeSetData(database, "files", "fileDataArray", fileData, () => {
+            this.setRelatedFieldsData({
+              tableFileName1: this.tableFileName1,
+              tableFileName2: this.tableFileName2,
+              relatedFields: {
+                formSelection1: this.formSelection1,
+                formSelection2: this.formSelection2,
+              },
+            });
+            this.setTriggerGetData(true);
+            this.setUpdateTriggerGetData(true);
+            this.ruleForm.name = "";
+            this.formSelection1 = [{ label: "", fileData: [], id: "" }];
+            this.formSelection2 = [{ label: "", fileData: [], id: "" }];
+            this.drawer = false;
+            this.$message({
+              type: "success",
+              message: `关联完成,关联表可在数据表格中查看。`,
+            });
+          });
+        })
+        .catch((error) => {
+          console.error("数据库初始化失败,无法继续存储数据。", error);
+        });
+    },
+    filterDataRecursively(filterNodeData, ind) {
+      if (ind >= this.formSelection2.length) {
+        // 终止条件:当 ind 超过 formSelection2 长度时,返回当前的 filterNodeData
+        return filterNodeData;
+      }
+      const data = [];
+      filterNodeData.forEach((fileData1) => {
+        const result = this.formSelection2[ind].fileData.find((fileData2) => {
+          return (
+            fileData1[this.formSelection1[ind].label] !== undefined &&
+            fileData2[this.formSelection2[ind].label] !== undefined &&
+            fileData1[this.formSelection1[ind].label] + "" ===
+              fileData2[this.formSelection2[ind].label] + ""
+          );
+        });
+        if (result) {
+          data.push({
+            ...fileData1,
+            ...result,
+          });
+        }
+      });
+
+      // 递归调用并返回筛选结果
+      return this.filterDataRecursively(data, ind + 1);
+    },
+    submitAssociated(formName) {
+      this.$refs[formName].validate((valid) => {
+        if (valid) {
+          // 初始化表格数据
+          this.tableDataChart1.forEach((item) => {
+            this.formSelection1.forEach((val) => {
+              if (val.id === item.id) {
+                val.fileData = item.fileData;
+                val.label = item.label;
+              }
+            });
+          });
+          this.tableDataChart2.forEach((item) => {
+            this.formSelection2.forEach((val) => {
+              if (val.id === item.id) {
+                val.fileData = item.fileData;
+                val.label = item.label;
+              }
+            });
+          });
+          if (
+            this.formSelection1[0].fileData.length <= 0 ||
+            this.formSelection2[0].fileData.length <= 0
+          ) {
+            console.log("sssss", this.formSelection1, this.formSelection2);
+            this.$message({
+              type: "warning",
+              message: `至少需要关联1组字段。`,
+            });
+            return;
+          }
+          // 初步过滤数据
+          let filterNodeData = [];
+          this.formSelection1.forEach((fileAttribut1, ind) => {
+            fileAttribut1.fileData.forEach((fileData1) => {
+              if (ind === 0) {
+                const result = this.formSelection2[ind].fileData.find(
+                  (fileData2) => {
+                    return (
+                      fileData1[fileAttribut1.label] !== undefined &&
+                      fileData2[this.formSelection2[ind].label] !== undefined &&
+                      fileData1[fileAttribut1.label] + "" ===
+                        fileData2[this.formSelection2[ind].label] + ""
+                    );
+                  }
+                );
+                if (result) {
+                  filterNodeData.push({
+                    ...fileData1,
+                    ...result,
+                  });
+                }
+              }
+            });
+          });
+          // 递归筛选
+          filterNodeData = this.filterDataRecursively(filterNodeData, 1);
+          this.saveDatas(filterNodeData);
         } else {
-          this.loading = false;
-          console.log("对象存储 'files' 不存在!");
+          console.log("error submit!!");
+          return false;
         }
-      })
-      .catch((error) => {
-        console.error("检查对象存储时出错:", error);
       });
-  },
-  methods: {
-    submitAssociated() {
-      console.log(
-        this.multipleSelection2,
-        this.multipleSelection1,
-        "multipleSelection2"
-      );
+
+      // console.log(filterNodeData, "filterNodeData");
     },
     //select 选择
     handleSelectData1() {
       const obj = this.options.find((item) => item.id === this.dataChart1);
+      this.tableFileName1 = obj.fileOldName;
       this.tableDataChart1 = obj.children;
+      this.formSelection1 = [{ label: "", fileData: [], id: "" }];
     },
     handleSelectData2() {
       const obj = this.options.find((item) => item.id === this.dataChart2);
+      this.tableFileName2 = obj.fileOldName;
       this.tableDataChart2 = obj.children;
-    },
-    //表格选择
-    handleSelectionChange1(val) {
-      this.multipleSelection1 = val;
-    },
-    handleSelectionChange(val) {
-      this.multipleSelection2 = val;
+      this.formSelection2 = [{ label: "", fileData: [], id: "" }];
     },
     handleClose(done) {
       this.$confirm("确认关闭?")
@@ -159,10 +324,8 @@ export default {
         })
         .catch((_) => {});
     },
-
     async getIndexDbData() {
       const jsonData = await getDataFromIndexedDB();
-
       this.options = jsonData.map((item) => {
         return {
           label: item.filename,
@@ -175,7 +338,23 @@ export default {
           })),
         };
       });
-      console.log(jsonData, "this.data");
+    },
+    handleDrawer() {
+      this.drawer = true;
+      //判断indexedDb中是否存在这个数据表
+      checkObjectStoreExists("FileDataDB", "files")
+        .then((exists) => {
+          if (exists) {
+            // console.log("对象存储 'files' 存在!");
+            this.getIndexDbData();
+          } else {
+            this.loading = false;
+            // console.log("对象存储 'files' 不存在!");
+          }
+        })
+        .catch((error) => {
+          console.error("检查对象存储时出错:", error);
+        });
     },
   },
 };
@@ -189,4 +368,18 @@ export default {
   margin: 0 auto;
   margin-bottom: 20px;
 }
+::v-deep .el-drawer {
+  width: 50% !important;
+}
+.flexs {
+  display: flex;
+  justify-content: space-between;
+  .flexsCenter {
+    display: flex;
+    flex-direction: column;
+    ::v-deep .el-input--suffix .el-input__inner {
+      width: 250px;
+    }
+  }
+}
 </style>

+ 23 - 4
src/views/performance/components/custonAsCom/dataTable.vue

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2024-10-28 16:46:38
- * @LastEditTime: 2024-10-31 15:45:24
+ * @LastEditTime: 2024-11-14 15:55:59
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dataTable.vue
@@ -39,6 +39,9 @@
               :key="ind + tabItem.fileData"
             >
               <el-table-column
+                :width="
+                  Object.keys(tabItem.fileData[0]).length > 6 ? 200 : null
+                "
                 v-for="(tableTitle, index) in Object.keys(tabItem.fileData[0])"
                 :key="index + 'title'"
                 :prop="tableTitle"
@@ -59,9 +62,9 @@
 <script>
 import {
   getDataFromIndexedDB,
-  clearAllDataFromIndexedDB,
   checkObjectStoreExists,
 } from "@/utils/indexedDb";
+import { mapMutations, mapState } from "vuex";
 export default {
   data() {
     return {
@@ -71,8 +74,22 @@ export default {
       loading: true,
     };
   },
+  // computed: {
+  //   ...mapState("dragChart", {
+  //     triggerGetData: "triggerGetData",
+  //   }),
+  // },
+  // watch: {
+  //   triggerGetData: function (newVal) {
+  //     if (newVal) {
+  //       console.log(newVal, "newVal dataTable");
+  //       this.setTriggerGetData(false);
+  //       this.getIndexDbData();
+  //       // 重置 triggerGetData 状态为 false
+  //     }
+  //   },
+  // },
   mounted() {
-    // this.getIndexDbData();
     //判断indexedDb中是否存在这个数据表
     checkObjectStoreExists("FileDataDB", "files")
       .then((exists) => {
@@ -89,11 +106,13 @@ export default {
       });
   },
   methods: {
+    ...mapMutations("dragChart", ["setTriggerGetData"]),
     async getIndexDbData() {
       // this.loading = true;
+      console.log("触发了这个事件");
       const jsonData = await getDataFromIndexedDB();
       this.tabData = jsonData;
-      console.log(jsonData, "jsonData");
+      console.log(jsonData, "jsonData dataTable");
       this.activeName =
         jsonData &&
         jsonData[0] &&

+ 34 - 0
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/configFn.js

@@ -0,0 +1,34 @@
+/*
+ * @Author: your name
+ * @Date: 2024-11-12 09:27:50
+ * @LastEditTime: 2024-11-12 17:33:26
+ * @LastEditors: bogon
+ * @Description: In User Settings Edit
+ * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/configFn.js
+ */
+export const getFormattedLabels = (index, lableData) => {
+  let labels = [];
+  //   console.log(lableData, "lableData");
+  // 获取每个项的标签信息
+  lableData.forEach((item) => {
+    if (item.data[index] !== undefined) {
+      const labelValue = item.data[index][item.label];
+      labels.push(`${item.label}: ${labelValue}`);
+    }
+  });
+
+  // 使用换行符分隔每个标签
+  return labels.join("\n");
+};
+
+export const getFormattedSeries = (data, chartType) => {
+  let series = [];
+  data.forEach((item) => {
+    series.push({
+      name: item.label,
+      type: chartType,
+      data: item.data.map((data) => parseFloat(data[item.label]) || 0), // 将数据转换为数值
+    });
+  });
+  return series;
+};

+ 137 - 36
src/views/performance/components/custonAsCom/dragChart/components/chartConfig/form/title.vue

@@ -33,6 +33,7 @@
             v-model="formLabelAlign.Xdata[ind].id"
             placeholder="请先进行数据配置"
             :disabled="disabled"
+            @change="handleXdata"
           >
             <el-option
               v-for="item in selectData"
@@ -42,33 +43,44 @@
             ></el-option>
           </el-select>
         </template>
-        <!-- <el-select
-          style="margin: 5px 0"
-          v-model="formLabelAlign.Ydata"
-          placeholder="请先进行数据配置"
-          :disabled="disabled"
-        >
-          <el-option
-            v-for="item in selectData"
-            :label="item.label"
-            :value="item.id"
-            :key="item.id"
-          ></el-option>
-        </el-select> -->
       </el-form-item>
       <el-form-item label="指标值">
-        <el-select
-          v-model="formLabelAlign.Ydata"
-          placeholder="请先进行数据配置"
-          :disabled="disabled"
+        <div
+          slot="label"
+          style="
+            display: flex;
+            align-items: center;
+            justify-content: space-between;
+          "
         >
-          <el-option
-            v-for="item in selectData"
-            :label="item.label"
-            :value="item.id"
-            :key="item.id"
-          ></el-option>
-        </el-select>
+          <span>指标值</span>
+          <el-tooltip content="添加指标值" placement="bottom-start">
+            <i
+              @click="
+                formLabelAlign.Ydata.push({ lable: '', data: [], id: '' })
+              "
+              class="el-icon-circle-plus-outline"
+              style="font-size: 20px"
+            ></i>
+          </el-tooltip>
+        </div>
+        <template v-for="(item, ind) in formLabelAlign.Ydata">
+          <el-select
+            style="margin: 5px 0"
+            :key="ind + 'select' + 'zhibiao'"
+            v-model="formLabelAlign.Ydata[ind].id"
+            placeholder="请先进行数据配置"
+            :disabled="disabled"
+            @change="handleYdata"
+          >
+            <el-option
+              v-for="item in selectData"
+              :label="item.label"
+              :value="item.id"
+              :key="item.id"
+            ></el-option>
+          </el-select>
+        </template>
       </el-form-item>
       <el-form-item label="标题名称">
         <el-input v-model="formLabelAlign.text"></el-input>
@@ -91,6 +103,7 @@
 
 <script>
 import { mapState, mapMutations } from "vuex";
+import { getFormattedLabels, getFormattedSeries } from "./configFn";
 export default {
   name: "title",
   props: {
@@ -115,13 +128,13 @@ export default {
             id: "",
           },
         ],
-        Ydata: "",
-        // Ydata: [
-        //   {
-        //     label: "",
-        //     data: [],
-        //   },
-        // ],
+        Ydata: [
+          {
+            label: "",
+            data: [],
+            id: "",
+          },
+        ],
         text: "",
         Xlable: "",
         Ylable: "",
@@ -138,12 +151,12 @@ export default {
   },
   watch: {
     curEdit() {
-      console.log(this.curEdit, "curEdit");
+      console.log("title-watch-curEdit");
       this.changeData();
     },
     formLabelAlign: {
       handler(nval) {
-        console.log(nval, "nval");
+        console.log("title-watch-formLabelAlign");
         this.changeChart();
       },
       deep: true,
@@ -162,21 +175,66 @@ export default {
     this.changeData();
   },
   methods: {
-    ...mapMutations("dragChart", ["updateChart"]),
+    ...mapMutations("dragChart", ["updateChart", "setCurEdit"]),
+    //纬度轴
+    handleXdata() {
+      this.formLabelAlign.Xdata = this.updateAxisData(
+        this.formLabelAlign.Xdata
+      );
+    },
+    handleYdata() {
+      this.formLabelAlign.Ydata = this.updateAxisData(
+        this.formLabelAlign.Ydata
+      );
+    },
+    updateAxisData(axisData) {
+      return axisData.map((item) => {
+        const selected = this.selectData.find((val) => val.id === item.id);
+        if (selected) {
+          return {
+            ...item,
+            label: selected.label,
+            data: selected.fileData || [],
+          };
+        }
+        return item;
+      });
+    },
+
     changeData() {
       this.$refs.form.resetFields();
       if (this.curEdit && this.curEdit.option) {
+        console.log(this.curEdit, "title-changeData-this.curEdit");
         this.formLabelAlign = {
-          ...this.formLabelAlign,
+          // ...this.formLabelAlign,
           text: this.curEdit.option.title?.text || "",
           Xlable: this.curEdit.option.xAxis?.name || "",
           Ylable: this.curEdit.option.yAxis?.name || "",
+          Xdata:
+            this.curEdit.Xdata.length > 0
+              ? this.curEdit.Xdata
+              : [
+                  {
+                    label: "",
+                    data: [],
+                    id: "",
+                  },
+                ],
+          Ydata:
+            this.curEdit.Ydata.length > 0
+              ? this.curEdit.Ydata
+              : [
+                  {
+                    label: "",
+                    data: [],
+                    id: "",
+                  },
+                ],
         };
       } else {
         console.log("curEdit.option 不存在", this.curEdit);
       }
     },
-
     changeChart() {
       if (!this.curEdit || !this.curEdit.option) return; // 确保 curEdit 和 option 存在
       const item = JSON.parse(JSON.stringify(this.curEdit));
@@ -184,11 +242,54 @@ export default {
       item.option.title = item.option.title || {};
       // 更新标题和坐标轴名称
       Object.assign(item.option.title, { text: this.formLabelAlign.text });
+      //判断图表类型进行值设置
       if (this.curEdit.type !== "pie" && this.curEdit.type !== "radar") {
         item.option.xAxis = item.option.xAxis || {};
         item.option.yAxis = item.option.yAxis || {};
+        item.Xdata = this.formLabelAlign.Xdata;
+        item.Ydata = this.formLabelAlign.Ydata;
         Object.assign(item.option.xAxis, { name: this.formLabelAlign.Xlable });
         Object.assign(item.option.yAxis, { name: this.formLabelAlign.Ylable });
+        console.log(item, "title-changeChart-this.curEdit");
+        if (item.Ydata[0].data.length > 0) {
+          item.option.series = getFormattedSeries(
+            item.Ydata,
+            this.curEdit.type
+          );
+        }
+        if (item.Xdata[0].data.length > 0) {
+          console.log(item.Xdata, "item.Xdata");
+          item.option.xAxis = {
+            name: item.Xlable,
+            data: item.Xdata[0].data,
+            axisTick: {
+              alignWithLabel: true,
+            },
+            axisLabel: {
+              formatter: (value, index) => {
+                // 格式化标签内容
+                return getFormattedLabels(index, item.Xdata);
+              },
+            },
+          };
+          item.option.tooltip = {
+            trigger: "axis",
+            axisPointer: { type: "shadow" },
+            formatter: (params) => {
+              const index = params[0].dataIndex; // 获取当前数据点的索引
+              // 默认 tooltip 内容
+              let content = params
+                .map((param) => {
+                  return `${param.marker}${param.seriesName}: ${param.value}`;
+                })
+                .join("<br/>");
+              // 获取自定义的标签信息
+              const customLabels = getFormattedLabels(index, item.Xdata);
+              // 合并 tooltip 内容和自定义标签
+              return `${customLabels}<br/>${content}`;
+            },
+          };
+        }
       }
 
       this.updateChart(item); // 更新图表

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

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2024-11-01 10:14:11
- * @LastEditTime: 2024-11-05 14:27:18
+ * @LastEditTime: 2024-11-13 10:17:18
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartsContent.vue
@@ -161,6 +161,7 @@ export default {
   ::v-deep .card {
     height: 100%;
     border-radius: 0 !important;
+    overflow: scroll;
   }
 }
 ::v-deep .el-divider--horizontal {

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

@@ -1,8 +1,8 @@
 <!--
  * @Author: your name
  * @Date: 2024-11-01 10:14:11
- * @LastEditTime: 2024-11-08 10:26:34
- * @LastEditors: milo-MacBook-Pro.local
+ * @LastEditTime: 2024-11-12 15:05:25
+ * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/components/chartsContent.vue
 -->
@@ -172,7 +172,7 @@ export default {
       nodes[index].style.opacity = 0;
     },
     appendChart(type) {
-      console.log("type  修改", type);
+      // console.log("type  修改", type);
       const config = require(`@/assets/js/constants/echarts-config/${type}.js`);
       this.addChart(
         new ChartClass({
@@ -203,7 +203,6 @@ export default {
     },
 
     handleImportConfig(option) {
-      console.log(this.addChartType, "type");
       this.addChart(
         new ChartClass({
           option: new Function("return " + option)() /* eslint-disable-line */,

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

@@ -7,7 +7,6 @@
         class="filter-tree"
         :data="data"
         :props="defaultProps"
-        default-expand-all
         node-key="id"
         :filter-node-method="filterNode"
         ref="tree"
@@ -23,8 +22,7 @@ import {
   getDataFromIndexedDB,
   checkObjectStoreExists,
 } from "@/utils/indexedDb";
-import { mapMutations } from "vuex";
-import { constructNow } from "date-fns";
+import { mapMutations, mapState } from "vuex";
 export default {
   data() {
     return {
@@ -37,40 +35,44 @@ export default {
       selectedNodeId: null, // 存储当前选中的节点 ID
     };
   },
+  computed: {
+    ...mapState("dragChart", {
+      triggerGetData: "triggerGetData",
+    }),
+  },
   watch: {
     filterText(val) {
       this.$refs.tree.filter(val);
     },
+    triggerGetData: function (newVal) {
+      if (newVal) {
+        console.log(newVal, "newVal chartData");
+        this.getAllData();
+        // 重置 triggerGetData 状态为 false
+        this.setTriggerGetData(false);
+      }
+    },
   },
   async created() {
-    checkObjectStoreExists("FileDataDB", "files")
-      .then((exists) => {
-        if (exists) {
-          console.log("对象存储 'files' 存在!");
-          this.getIndexDbData();
-        } else {
-          this.loading = false;
-          console.log("对象存储 'files' 不存在!");
-        }
-      })
-      .catch((error) => {
-        console.error("检查对象存储时出错:", error);
-      });
+    this.getAllData();
   },
   methods: {
-    ...mapMutations("dragChart", ["updateDataBase"]),
+    ...mapMutations("dragChart", ["updateDataBase", "setTriggerGetData"]),
     async getIndexDbData() {
       const jsonData = await getDataFromIndexedDB();
+      console.log(jsonData, "jsonData  chartData");
       this.data = jsonData.map((item) => {
         return {
           label: item.filename,
           fileOldName: item.fileOldName,
           id: item.fileId,
-          children: [...Object.keys(item.fileData[0])].map((val) => ({
-            label: val,
-            id: item.fileId + val,
-            fileData: item.fileData,
-          })),
+          children: item.fileData[0]
+            ? [...Object.keys(item.fileData[0])].map((val) => ({
+                label: val,
+                id: item.fileId + val,
+                fileData: item.fileData,
+              }))
+            : [],
         };
       });
       // 检查选中的节点状态,如果没有选中节点则调用 updateDataBase({})
@@ -78,6 +80,19 @@ export default {
         this.updateDataBase({});
       }
     },
+    getAllData() {
+      checkObjectStoreExists("FileDataDB", "files")
+        .then((exists) => {
+          if (exists) {
+            this.getIndexDbData();
+          } else {
+            this.loading = false;
+          }
+        })
+        .catch((error) => {
+          console.error("检查对象存储时出错:", error);
+        });
+    },
     filterNode(value, data) {
       if (!value) return true;
       return data.label.indexOf(value) !== -1;
@@ -132,6 +147,9 @@ export default {
   ::v-deep .card {
     height: 100%;
     border-radius: 0 !important;
+    // .el-card__body {
+    overflow: scroll;
+    // }
   }
   ::v-deep .el-radio {
     margin: 0;

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

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2024-10-31 16:01:27
- * @LastEditTime: 2024-11-04 15:09:27
+ * @LastEditTime: 2024-11-12 15:05:48
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dragChart/index.vue
@@ -44,7 +44,7 @@ export default {
      * @params {String} 图表类型
      */
     addChart(type) {
-      console.log("添加一个图表", type);
+      // console.log("添加一个图表", type);
       // 如果连续两次添加相同的类型,强制触发更新
       if (this.addChartType === type) {
         this.addChartType = ""; // 先清空

+ 0 - 1
src/views/performance/components/custonAsCom/luckySheet.vue

@@ -26,7 +26,6 @@
 
 <script>
 import luckysheet from "luckysheet";
-import LuckyExcel from "luckyexcel";
 import {
   getDataFromIndexedDB,
   storeSetData,

+ 21 - 9
src/views/performance/customAnalysis.vue

@@ -186,6 +186,7 @@ import Papa from "papaparse";
 import * as XLSX from "xlsx";
 import { storeSetData } from "@/utils/indexedDb";
 import { format } from "date-fns";
+import { mapMutations, mapState } from "vuex";
 export default {
   components: {
     DataTable,
@@ -223,12 +224,28 @@ export default {
       },
     };
   },
+  computed: {
+    ...mapState("dragChart", {
+      updateTriggerGetData: "updateTriggerGetData",
+    }),
+  },
+  watch: {
+    updateTriggerGetData: function (newVal) {
+      if (newVal) {
+        console.log(newVal, "newVal dataTable");
+        this.setUpdateTriggerGetData(false);
+        this.$refs.dataTableRef.getIndexDbData();
+        // 重置 triggerGetData 状态为 false
+      }
+    },
+  },
   methods: {
+    ...mapMutations("dragChart", [
+      "setTriggerGetData",
+      "setUpdateTriggerGetData",
+    ]),
     async initDB() {
       return new Promise((resolve, reject) => {
-        // 尝试删除现有数据库以避免版本冲突
-        // const deleteRequest = indexedDB.deleteDatabase("FileDataDB");
-        // deleteRequest.onsuccess = () => {
         const request = indexedDB.open("FileDataDB", 2); // 使用较高版本
         request.onupgradeneeded = (event) => {
           const db = event.target.result;
@@ -248,15 +265,11 @@ export default {
           console.error("数据库初始化失败:", event.target.error);
           reject(event.target.error);
         };
-        // };
-        // deleteRequest.onerror = (event) => {
-        //   console.error("删除数据库失败:", event.target.error);
-        //   reject(event.target.error);
-        // };
       });
     },
     async storeData(newFileData) {
       await storeSetData(this.db, "files", "fileDataArray", newFileData, () => {
+        this.setTriggerGetData(true);
         this.$refs.dataTableRef.getIndexDbData();
       });
     },
@@ -267,7 +280,6 @@ export default {
         })
         .catch((_) => {});
     },
-
     handleImportClick() {
       // 点击 import 标签时切换 popover 的显示状态
       this.showPopover = !this.showPopover; // 切换显示状态

+ 2 - 2
vue.config.js

@@ -64,9 +64,9 @@ module.exports = {
     proxy: {
       "/api": {
         // target: "http://192.168.5.4:16200", // 石月
-        // target: "http://192.168.50.235:16200", //内网
+        target: "http://192.168.50.235:16200", //内网
         // target: "http://192.168.5.15:16200",
-        target: "http://106.120.102.238:16600", //外网
+        // target: "http://106.120.102.238:16600", //外网
         //  target: "http://10.96.137.5",
         changeOrigin: true,
         pathRewrite: {