Ver código fonte

修改原试图初始展示比例

liujiejie 3 meses atrás
pai
commit
ef186a7d00

Diferenças do arquivo suprimidas por serem muito extensas
+ 27289 - 20
package-lock.json


+ 5 - 1
package.json

@@ -13,6 +13,11 @@
   "dependencies": {
     "@jiaminghi/data-view": "^2.10.0",
     "@riophae/vue-treeselect": "^0.4.0",
+    "@univerjs/core": "^0.10.6",
+    "@univerjs/preset-sheets-core": "^0.10.6",
+    "@univerjs/presets": "^0.10.6",
+    "@univerjs/sheets": "^0.10.6",
+    "@univerjs/ui": "^0.10.6",
     "@wangeditor/editor": "^5.1.23",
     "@wangeditor/editor-for-vue": "^1.0.2",
     "axios": "^1.6.8",
@@ -27,7 +32,6 @@
     "flatted": "^3.3.2",
     "happypack": "^5.0.1",
     "jszip": "^3.10.1",
-    "luckysheet": "^2.1.13",
     "ol": "^9.2.3",
     "p-limit": "^6.2.0",
     "pako": "^2.1.0",

+ 46 - 114
src/views/home/components/Menu.vue

@@ -10,12 +10,13 @@
       background-color="#eff1f3"
       text-color="#000"
       :active-text-color="activeTextColor"
-      :router="true"
+      :router="false"
       :default-active="defaultActive"
       :collapse="isCollapse"
       :default-openeds="openMenus"
     >
       <template v-for="item in routerList">
+        <!-- 有子菜单 -->
         <el-submenu
           v-if="
             item.children && item.children.length && item.meta?.hidden === false
@@ -30,6 +31,8 @@
             </i>
             <span>{{ item.name }}</span>
           </template>
+
+          <!-- 子菜单项 -->
           <el-menu-item
             v-for="child in item.children"
             v-if="child.meta?.hidden === false"
@@ -44,6 +47,8 @@
             <span>{{ child.name }}</span>
           </el-menu-item>
         </el-submenu>
+
+        <!-- 没有子菜单 -->
         <el-tooltip
           v-else-if="item.meta?.hidden === false"
           class="box-item"
@@ -75,6 +80,7 @@
       </template>
     </el-menu>
 
+    <!-- 展开/收起 -->
     <div class="foldBox flexCenter">
       <span
         v-show="isCollapse"
@@ -86,9 +92,7 @@
         v-show="!isCollapse"
         :value="isExpanded"
         @change="toggleAllMenus"
-      >
-        <!-- :inactive-text="isExpanded ? '收起全部菜单' : '展开全部菜单'" -->
-      </el-switch>
+      />
       <span
         v-show="!isCollapse"
         class="el-icon-s-fold icon"
@@ -101,17 +105,14 @@
 
 <script>
 import { mapActions, mapState } from "vuex";
-import { orgList } from "./mockData";
 import Vue from "vue";
 
 export default {
   data() {
     return {
-      isExpanded: false, // 控制是否展开所有子菜单
-      openMenus: [], // 用来存储展开的菜单
+      isExpanded: false,
+      openMenus: [],
       isCollapse: true,
-      orgList: orgList,
-      searchInputValue: "",
       defaultActive: this.$route.fullPath,
       activeIndex: false,
       keyObject: {},
@@ -122,20 +123,7 @@ export default {
           path: "/home/cockpitManage",
           name: "首页",
           iconName: "gps",
-          meta: {
-            hidden: false,
-          },
-          // children: [
-          //   {
-          //     id: 11,
-          //     iconName: "",
-          //     meta: {
-          //       hidden: false,
-          //     },
-          //     path: "electronic-map",
-          //     name: "电子地图",
-          //   },
-          // ],
+          meta: { hidden: false },
         },
       ],
     };
@@ -150,116 +138,60 @@ export default {
     ...mapState({
       currentMenuIndex: (state) => state.breadStore?.currentUrl?.routeUrl,
     }),
-    // 获取所有父级菜单的 index
     allMenuIndexes() {
-      return this.routerList.map((item) => {
-        if (
-          item.children &&
-          item.children.length &&
-          item.meta?.hidden === false
-        ) {
-          return item.path;
-        } else {
-          return `${item.path}?id=${item.id}`;
-        }
-      });
+      return this.routerList.map((item) =>
+        item.children && item.children.length && item.meta?.hidden === false
+          ? item.path
+          : `${item.path}?id=${item.id}`
+      );
     },
   },
   watch: {
-    currentMenuIndex: {
-      deep: true,
-      handler(newVale, oldVal) {
-        if (newVale) {
-          this.$refs.menu.close(newVale);
-        }
-      },
-    },
-    keyObject: {
-      deep: true,
-      handler(newVale) {
-        if (newVale && newVale.key === this.defaultActive) {
-          this.getBreadcrumbList(newVale.keyPath);
-        }
-      },
+    currentMenuIndex(newVal) {
+      if (newVal) {
+        this.$refs.menu.close(newVal);
+      }
     },
   },
   methods: {
     ...mapActions("menuTag", ["addTag"]),
-    // 切换展开/收起所有菜单
     toggleAllMenus() {
       this.isExpanded = !this.isExpanded;
-
-      if (this.isExpanded) {
-        // 展开所有子菜单
-        this.openMenus = this.routerList
-          .filter((item) => item.children && item.children.length)
-          .map((item) => item.path);
-      } else {
-        // 收起所有子菜单
-        this.openMenus = [];
-      }
+      this.openMenus = this.isExpanded
+        ? this.routerList
+            .filter((item) => item.children && item.children.length)
+            .map((item) => item.path)
+        : [];
     },
-    handleChangeMenuUrl(item, path) {
-      this.defaultActive = path;
-      this.$router.push(path); // 跳转到指定的路由
+    // 修复后的跳转方法
+    handleChangeMenuUrl(item, key) {
+      if (!key.startsWith("/")) {
+        key = "/" + key;
+      }
+      this.defaultActive = key;
+
+      const tag = { path: key, name: item.name, label: item.name };
+      this.addTag(tag);
+
+      // 用 nextTick 兼容 Firefox
+      this.$nextTick(() => {
+        this.$router.push(key).catch((err) => {
+          if (err.name !== "NavigationDuplicated") {
+            console.error("路由跳转失败:", err);
+          }
+        });
+      });
     },
     isElPrefix(str) {
-      const regex = /^el-/;
-      return regex.test(str);
-    },
-    getBreadcrumbList(keyPath) {
-      const urls = keyPath;
-      const result = urls.map((url, index) => {
-        const params = new URLSearchParams(url.split("?")[1]);
-        const id = params.get("id");
-        const name = params.get("name");
-        const routeUrl = url;
-        if (index === urls.length - 1) {
-          return { id, name, routeUrl, currentPage: true };
-        }
-        return { id, name, routeUrl };
-      });
-      this.$store.commit("breadStore/ADD_BREAD", result);
-      return result;
+      return /^el-/.test(str);
     },
     handleOpen(key, keyPath) {
       this.activeIndex = false;
-      this.keyObject = {
-        key,
-        keyPath,
-      };
+      this.keyObject = { key, keyPath };
     },
     handleClose(key, keyPath) {
       this.activeIndex = false;
-      this.keyObject = {
-        key,
-        keyPath,
-      };
-    },
-    shrinkTree() {
-      this.$refs.menu.close(`/orgsPage?id=${orgList.id}&name=${orgList.name}`);
-    },
-    handleChangeRouter() {
-      this.activeIndex = true;
-      this.defaultActive = "";
-      this.$store.commit("breadStore/ADD_BREAD", []);
-      this.$refs.menu.close(`/orgsPage?id=${orgList.id}&name=${orgList.name}`);
-      this.$router.push("/");
-    },
-    handleChangeMenuUrl(item, key) {
-      this.defaultActive = key;
-      if (item) {
-        item.activeIndex = true;
-      }
-      const tag = {
-        path: key,
-        name: item.name,
-        label: item.name,
-      };
-      this.addTag(tag);
-      this.$router.push({
-        path: key,
-      });
+      this.keyObject = { key, keyPath };
     },
   },
 };

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

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2024-05-29 09:13:51
- * @LastEditTime: 2025-07-01 16:02:54
+ * @LastEditTime: 2025-09-04 17:07:30
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/analysisEvent.vue
@@ -522,7 +522,7 @@ export default {
         .then((res) => {
           if (res.data.code === 200) {
             this.timeRanges = res.data.datas;
-            // this.formData = { ...res.data.datas };
+            this.formData = { ...res.data.datas };
           }
         })
         .catch((error) => {});
@@ -742,6 +742,7 @@ export default {
         this.$router.push("/home/performance/assetssMag");
       }
     },
+
     handleCheckAllChange(val) {
       this.checkedCities = val
         ? [...this.cities, "数据源过滤", "图像设置"]

+ 0 - 22
src/views/performance/components/custonAsCom/UniverSheet.vue

@@ -1,22 +0,0 @@
-<!--
- * @Author: your name
- * @Date: 2025-08-07 10:36:41
- * @LastEditTime: 2025-08-07 11:03:12
- * @LastEditors: bogon
- * @Description: In User Settings Edit
- * @FilePath: /performance-test/src/views/performance/components/custonAsCom/UniverSheet.vue
--->
-<template>
-  <div>UniverSheet</div>
-</template>
-<script>
-export default {
-  props: {},
-  data() {
-    return {};
-  },
-  mounted() {},
-  methods: {},
-};
-</script>
-<style scoped lang="scss"></style>

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

@@ -1,7 +1,7 @@
 <!--
  * @Author: your name
  * @Date: 2024-10-28 16:46:38
- * @LastEditTime: 2025-04-11 16:56:28
+ * @LastEditTime: 2025-09-01 10:26:56
  * @LastEditors: bogon
  * @Description: In User Settings Edit
  * @FilePath: /performance-test/src/views/performance/components/custonAsCom/dataTable.vue
@@ -122,7 +122,6 @@ export default {
     removeTab(targetName) {
       // 1. 在 tabData 中删除对应的 tab
       const index = this.tabData.findIndex((tab) => tab.fileId === targetName);
-
       if (index !== -1) {
         this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
           confirmButtonText: "确定",

+ 268 - 152
src/views/performance/components/custonAsCom/luckySheet.vue

@@ -1,6 +1,6 @@
 <template>
   <div>
-    <!-- <input style="font-size: 16px" type="file" @change="uploadExcel" /> -->
+    <!-- UniverSheet -->
     <el-row type="flex" class="row-bg" justify="space-between">
       <el-col>
         <el-button
@@ -18,187 +18,309 @@
         </el-button>
       </el-col>
     </el-row>
-
-    <div id="luckysheet" style="width: 100%; height: 88vh"></div>
-    <!-- 显示获取的数据 -->
+    <!-- Univer 表格容器 -->
+    <div id="univer-sheet" style="width: 100%; height: 88vh"></div>
   </div>
 </template>
 
 <script>
-import luckysheet from "luckysheet";
+import { createUniver, LocaleType, mergeLocales } from "@univerjs/presets";
+import { UniverSheetsCorePreset } from "@univerjs/preset-sheets-core";
+import zhCN from "@univerjs/preset-sheets-core/locales/zh-CN";
+import "@univerjs/preset-sheets-core/lib/index.css";
+
 import {
   getDataFromIndexedDB,
   storeSetData,
   initDatabase,
 } from "@/utils/indexedDb";
 import { format } from "date-fns";
+
 export default {
-  name: "LuckySheetDemo",
+  name: "UniverSheetDemo",
   data() {
     return {
-      sheetData: null, // 用于存储表格数据
+      univer: null,
+      univerAPI: null,
+      workbook: null,
       sheetName: "",
     };
   },
-  mounted() {
-    this.initSheetData();
+  async mounted() {
+    await this.initSheetData();
   },
+  beforeDestroy() {
+    if (this.univer) {
+      this.univer.dispose();
+    }
+  },
+
   methods: {
+    /** 初始化表格数据 */
     async initSheetData() {
       const jsonData = await getDataFromIndexedDB();
-
-      if (jsonData && jsonData.length > 0) {
-        this.sheetName = [...jsonData].filter(
-          (item) => item.fileId == this.$route.query.id
-        )[0]?.fileOldName;
-
-        // 1. 动态提取表头
-        const headers = Object.keys(
-          [...jsonData].filter((item) => item.fileId == this.$route.query.id)[0]
-            .fileData[0]
-        );
-        // 2. 将 JSON 数据转换为二维数组格式
-        const formattedData = [...jsonData]
-          .filter((item) => item.fileId == this.$route.query.id)[0]
-          .fileData.map((item) => headers.map((header) => item[header]));
-        // 3. 将表头插入到数据的第一行
-        formattedData.unshift(headers);
-        //4.  将 JSON 数据转换为 Luckysheet 格式
-        this.initLuckySheet(formattedData);
-      } else {
+      if (!jsonData || jsonData.length === 0) {
         this.$message.warning("暂无数据,请先进行数据导入");
         this.$router.push("/home/performance/customAnalysis");
+        return;
+      }
+
+      const targetFile = jsonData.find(
+        (item) => item.fileId == this.$route.query.id
+      );
+      if (!targetFile) {
+        this.$message.warning("未找到对应的数据文件");
+        this.$router.push("/home/performance/customAnalysis");
+        return;
       }
+
+      this.sheetName = await this.truncateString(targetFile.fileOldName);
+
+      const headers = Object.keys(targetFile.fileData[0]);
+      const formattedData = targetFile.fileData.map((row) =>
+        headers.map((h) => row[h])
+      );
+      formattedData.unshift(headers);
+
+      this.initUniverSheet(formattedData);
     },
-    async initLuckySheet(formattedData) {
-      const options = {
-        container: "luckysheet",
-        showReturnIcon: false, // 假设有这个选项
-        data: [
-          {
-            name: await this.truncateString(this.sheetName), //工作表名称
-            index: 0, //工作表索引
-            status: 1, //激活状态
-            order: 0, //工作表的下标
-            hide: 0, //是否隐藏
-            row: 36, //行数
-            column: 18, //列数
-            defaultRowHeight: 19, //自定义行高
-            defaultColWidth: 73, //自定义列宽
-            celldata: formattedData
-              .map((row, rowIndex) =>
-                row.map((cell, colIndex) => ({
-                  r: rowIndex,
-                  c: colIndex,
-                  v: {
-                    m: cell, // 显示的内容
-                    ct: {
-                      fa: "General", // 格式(通用)
-                      t: "g", // 类型(general)
-                    },
-                    v: cell, // 实际值
-                  },
-                }))
-              )
-              .flat(),
-            //初始化使用的单元格数据
-            config: {
-              merge: {}, //合并单元格
-              rowlen: {}, //表格行高
-              columnlen: {}, //表格列宽
-              rowhidden: {}, //隐藏行
-              colhidden: {}, //隐藏列
-              borderInfo: {}, //边框
-              authority: {}, //工作表保护
-            },
-            scrollLeft: 0, //左右滚动条位置
-            scrollTop: 315, //上下滚动条位置
-            luckysheet_select_save: [], //选中的区域
-            calcChain: [], //公式链
-            isPivotTable: false, //是否数据透视表
-            pivotTable: {}, //数据透视表设置
-            filter_select: {}, //筛选范围
-            filter: null, //筛选配置
-            luckysheet_alternateformat_save: [], //交替颜色
-            luckysheet_alternateformat_save_modelCustom: [], //自定义交替颜色
-            luckysheet_conditionformat_save: {}, //条件格式
-            frozen: {}, //冻结行列配置
-            // chart: [], //图表配置
-            zoomRatio: 1, // 缩放比例
-            image: [], //图片
-            showGridLines: 1, //是否显示网格线
-            dataVerification: {}, //数据验证配置
-          },
-        ],
-        title: "LuckySheet示例", // 表格标题
-        lang: "zh", // 语言设置
-        showtoolbar: true, // 是否显示工具栏
-        chart: {
-          //
-          // 配置图表
-          enable: false, // 启用图表功能
-        },
-        showtoolbarConfig: {
-          chart: false, // 隐藏图表工具按钮
+
+    /** 初始化 UniverSheet */
+    initUniverSheet(formattedData) {
+      // 1. 创建 Univer 实例(返回 univer + univerAPI)
+      const { univer, univerAPI } = createUniver({
+        locale: LocaleType.ZH_CN,
+        locales: {
+          [LocaleType.ZH_CN]: mergeLocales(zhCN),
         },
-      };
-      luckysheet.create(options);
+        presets: [
+          UniverSheetsCorePreset({
+            container: "univer-sheet",
+          }),
+        ],
+      });
+
+      this.univer = univer;
+      this.univerAPI = univerAPI;
+
+      // 2. 创建 Workbook(新版 API)
+      const fWorkbook = univerAPI.createWorkbook({
+        name: this.sheetName || "数据表",
+      });
+      this.workbook = fWorkbook;
+
+      // 3. 获取当前工作表
+      const fSheet = fWorkbook.getActiveSheet();
+
+      // 4. 写入数据
+      const rows = formattedData.length;
+      const cols = formattedData[0]?.length || 0;
+      if (rows && cols) {
+        fSheet.getRange(0, 0, rows, cols).setValues(formattedData);
+      }
+      // 直接设置名字(Facade API 提供的方法)
+      if (fSheet && typeof fSheet.setName === "function") {
+        fSheet.setName(this.sheetName);
+      }
+
+      console.log("✅ Univer 初始化完成,数据已填充");
+    },
+    // 剪掉底部和右侧全空的行/列
+    trimEmptyRowsCols(values) {
+      if (!Array.isArray(values) || values.length === 0) return [];
+
+      // 去掉底部全空行
+      let lastRow = values.length - 1;
+      while (lastRow >= 0) {
+        const row = values[lastRow] || [];
+        if (row.some((v) => v !== "" && v != null)) break;
+        lastRow--;
+      }
+      if (lastRow < 0) return [];
+
+      values = values.slice(0, lastRow + 1);
+
+      // 找到最后一列索引
+      let lastCol = 0;
+      for (let r = 0; r < values.length; r++) {
+        const row = values[r] || [];
+        for (let c = row.length - 1; c >= 0; c--) {
+          if (row[c] !== "" && row[c] != null) {
+            if (c > lastCol) lastCol = c;
+            break;
+          }
+        }
+      }
+
+      // 切每行到 lastCol
+      const trimmed = values.map((row) => (row || []).slice(0, lastCol + 1));
+      return trimmed;
     },
+
     async saveData() {
-      // 获取所有工作表
-      const sheets = luckysheet.getAllSheets();
+      // 检查 workbook(你之前通过 univerAPI.createWorkbook 得到的 fWorkbook)
+      if (!this.workbook) {
+        this.$message.error("表格未初始化");
+        return;
+      }
+
       const allFileData = [];
-      sheets.forEach((sheet, ind) => {
-        const data = sheet.data; // 获取当前工作表的数据
-        const formattedData = [];
-        const headers = data[0].map((cell) => (cell && cell.v ? cell.v : "")); // 表头内容
-
-        // 遍历数据行,从第二行开始
-        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;
+
+      // 获取 Facade sheets 列表(多数版本支持 getSheets())
+      const fSheets =
+        typeof this.workbook.getSheets === "function"
+          ? this.workbook.getSheets()
+          : Array.isArray(this.workbook.sheets)
+          ? this.workbook.sheets
+          : [];
+
+      for (let index = 0; index < fSheets.length; index++) {
+        const fSheet = fSheets[index];
+        // 1) 获取 sheet 名(多种回退)
+        let name = "";
+        try {
+          if (fSheet && typeof fSheet.getName === "function") {
+            name = fSheet.getName();
+          } else if (fSheet && typeof fSheet.getSheet === "function") {
+            const coreSheet = fSheet.getSheet();
+            if (coreSheet) {
+              if (typeof coreSheet.getName === "function") {
+                name = coreSheet.getName();
+              } else if (typeof coreSheet.getConfig === "function") {
+                const cfg = coreSheet.getConfig() || {};
+                name = cfg.name || cfg.sheetName || "";
+              } else if (coreSheet.name) {
+                name = coreSheet.name;
+              }
             }
+          } else if (fSheet && fSheet.getConfig) {
+            const cfg = fSheet.getConfig() || {};
+            name = cfg.name || "";
+          } else if (fSheet && fSheet.name) {
+            name = fSheet.name;
           }
-          // 如果行数据不为空,加入到结果数组中
-          if (Object.keys(rowData).length) {
-            formattedData.push(rowData);
+        } catch (e) {
+          console.warn("取 sheet 名出错,使用默认名", e);
+        }
+        if (!name) name = `Sheet${index}`;
+
+        // 2) 获取行列数(优先使用 core snapshot)
+        let rowCount = 0;
+        let colCount = 0;
+        try {
+          const coreSheet =
+            fSheet && typeof fSheet.getSheet === "function"
+              ? fSheet.getSheet()
+              : null;
+          if (coreSheet && typeof coreSheet.getSnapshot === "function") {
+            const snap = coreSheet.getSnapshot() || {};
+            rowCount = snap.rowCount || 0;
+            colCount = snap.columnCount || 0;
+          } else if (
+            fSheet &&
+            typeof fSheet.getRange === "function" &&
+            typeof fSheet.getRange().getValues === "function"
+          ) {
+            // 无 snapshot 的情况下无法精确知道行列,后面会尝试读取默认区域
           }
+        } catch (e) {
+          console.warn("取 snapshot 失败,稍后使用回退读取。", e);
         }
-        // 生成唯一的 fileData
+
+        // 3) 读取值(优先用精确 rowCount/colCount,否则回退到安全的区域)
+        let values = [];
+        try {
+          if (
+            rowCount > 0 &&
+            colCount > 0 &&
+            typeof fSheet.getRange === "function"
+          ) {
+            values = fSheet.getRange(0, 0, rowCount, colCount).getValues();
+          } else if (typeof fSheet.getRange === "function") {
+            // 回退:读取一个合理的上限区域(可根据数据量调整)
+            const tryRows = 1000; // 你可以根据实际场景调大或调小
+            const tryCols = 200;
+            values = fSheet.getRange(0, 0, tryRows, tryCols).getValues();
+          } else {
+            // 如果 fSheet 没有 getRange,则尝试从 coreSheet 读取(某些版本差别)
+            const coreSheet =
+              fSheet && typeof fSheet.getSheet === "function"
+                ? fSheet.getSheet()
+                : null;
+            if (coreSheet && typeof coreSheet.getSnapshot === "function") {
+              const snap = coreSheet.getSnapshot();
+              rowCount = rowCount || snap.rowCount || 0;
+              colCount = colCount || snap.columnCount || 0;
+              if (
+                rowCount > 0 &&
+                colCount > 0 &&
+                typeof fSheet.getRange === "function"
+              ) {
+                values = fSheet.getRange(0, 0, rowCount, colCount).getValues();
+              }
+            }
+          }
+        } catch (e) {
+          console.warn("读取表格值失败,返回空数组作为回退", e);
+          values = [];
+        }
+
+        // 4) 裁剪空行空列并按你的格式转成对象数组
+        const trimmed = this.trimEmptyRowsCols(values);
+        if (!trimmed || trimmed.length <= 1) {
+          // 没有数据或只有表头
+          continue;
+        }
+        const headers = trimmed[0];
+        const formatted = trimmed
+          .slice(1)
+          .filter((row) => row && row.some((v) => v !== "" && v != null))
+          .map((row) => {
+            const obj = {};
+            headers.forEach((h, i) => {
+              if (h !== undefined && h !== null && h !== "") {
+                obj[h] = row[i] ?? "";
+              }
+            });
+            return obj;
+          });
+
+        if (!formatted.length) continue;
+
         const fileData = {
           filename:
-            format(new Date(), "yyyyMMdd-HH:mm:ss") + "_" + ind + sheet.name,
-          fileData: formattedData,
-          fileOldName: sheet.name + "_" + ind,
-          fileId: new Date().getTime() + "_" + ind,
+            format(new Date(), "yyyyMMdd-HH:mm:ss") + "_" + index + name,
+          fileData: formatted,
+          fileOldName: name + "_" + index,
+          fileId: new Date().getTime() + "_" + index,
         };
-        allFileData.push(fileData); // 将当前工作表的文件数据加入到数组中
-      });
 
-      // 批量存储到数据库
-      await initDatabase()
-        .then((database) => {
-          allFileData.forEach((fileData) => {
-            if (fileData && fileData.fileData.length > 0) {
-              storeSetData(database, "files", "fileDataArray", fileData, () => {
-                console.log("数据存储成功:", fileData.filename);
-              });
-            }
-          });
-          // 跳转到分析页面
-          this.$router.push("/home/performance/customAnalysis");
-        })
-        .catch((error) => {
-          console.error("数据库初始化失败,无法继续存储数据。", error);
+        allFileData.push(fileData);
+      } // for sheets
+
+      // 存 DB
+      try {
+        const db = await initDatabase();
+        allFileData.forEach((fileData) => {
+          if (fileData && fileData.fileData && fileData.fileData.length > 0) {
+            storeSetData(db, "files", "fileDataArray", fileData, () => {
+              console.log("数据存储成功:", fileData.filename);
+            });
+          }
         });
+      } catch (e) {
+        console.error("保存到 IndexedDB 失败", e);
+        this.$message.error("保存失败,请检查控制台错误");
+        return;
+      }
+
+      this.$router.push("/home/performance/customAnalysis");
     },
+    // /** 保存数据 */
+
+    // /** 截断 Sheet 名称 */
     truncateString(str) {
-      return new Promise((resolve, reject) => {
-        // 如果字符串长度超过30
+      return new Promise((resolve) => {
         if (str.length > 30) {
           this.$confirm(
             "sheet页名长度已超过31个字符,可能会影响后续对函数的使用,是否需要进行自动截取?",
@@ -212,14 +334,10 @@ export default {
             .then(() => {
               const suffixes = [".csv", ".xlsx", ".xls"];
               let truncatedFilename = str;
-
-              // 查找文件名中的后缀位置并进行截取
+              console.log(str, "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;
@@ -228,15 +346,13 @@ export default {
               resolve(truncatedFilename);
             })
             .catch(() => {
-              // 用户取消时返回原始的str
               this.$message({
                 type: "info",
-                message: "已取消删除",
+                message: "已取消自动截取",
               });
               resolve(str);
             });
         } else {
-          // 字符串长度不超过30,直接返回原字符串
           resolve(str);
         }
       });
@@ -246,7 +362,7 @@ export default {
 </script>
 
 <style scoped lang="scss">
-/* 可以添加一些自定义样式 */
+/* 隐藏返回按钮 */
 ::v-deep .luckysheet_info_detail div.luckysheet_info_detail_back {
   display: none;
 }

+ 245 - 0
src/views/performance/components/custonAsCom/luckySheet1.vue

@@ -0,0 +1,245 @@
+<template>
+  <div>
+    <el-row type="flex" class="row-bg" justify="space-between">
+      <el-col>
+        <el-button
+          type="text"
+          style="font-size: 20px"
+          icon="el-icon-arrow-left"
+          @click="() => $router.push('/home/performance/customAnalysis')"
+        >
+          返回
+        </el-button>
+      </el-col>
+      <el-col style="display: flex; justify-content: end">
+        <el-button type="primary" @click="saveData" size="small">
+          保存数据
+        </el-button>
+      </el-col>
+    </el-row>
+    <div id="luckysheet" style="width: 100%; height: 88vh"></div>
+    <!-- 显示获取的数据 -->
+  </div>
+</template>
+
+<script>
+// import luckysheet from "luckysheet";
+// import {
+//   getDataFromIndexedDB,
+//   storeSetData,
+//   initDatabase,
+// } from "@/utils/indexedDb";
+// import { format } from "date-fns";
+export default {
+  name: "LuckySheetDemo",
+  data() {
+    return {
+      sheetData: null, // 用于存储表格数据
+      sheetName: "",
+    };
+  },
+  mounted() {
+    // this.initSheetData();
+  },
+  methods: {
+    // async initSheetData() {
+    //   const jsonData = await getDataFromIndexedDB();
+    //   if (jsonData && jsonData.length > 0) {
+    //     this.sheetName = [...jsonData].filter(
+    //       (item) => item.fileId == this.$route.query.id
+    //     )[0]?.fileOldName;
+    //     // 1. 动态提取表头
+    //     const headers = Object.keys(
+    //       [...jsonData].filter((item) => item.fileId == this.$route.query.id)[0]
+    //         .fileData[0]
+    //     );
+    //     // 2. 将 JSON 数据转换为二维数组格式
+    //     const formattedData = [...jsonData]
+    //       .filter((item) => item.fileId == this.$route.query.id)[0]
+    //       .fileData.map((item) => headers.map((header) => item[header]));
+    //     // 3. 将表头插入到数据的第一行
+    //     formattedData.unshift(headers);
+    //     //4.  将 JSON 数据转换为 Luckysheet 格式
+    //     this.initLuckySheet(formattedData);
+    //   } else {
+    //     this.$message.warning("暂无数据,请先进行数据导入");
+    //     this.$router.push("/home/performance/customAnalysis");
+    //   }
+    // },
+    // async initLuckySheet(formattedData) {
+    //   const options = {
+    //     container: "luckysheet",
+    //     showReturnIcon: false, // 假设有这个选项
+    //     data: [
+    //       {
+    //         name: await this.truncateString(this.sheetName), //工作表名称
+    //         index: 0, //工作表索引
+    //         status: 1, //激活状态
+    //         order: 0, //工作表的下标
+    //         hide: 0, //是否隐藏
+    //         row: 36, //行数
+    //         column: 18, //列数
+    //         defaultRowHeight: 19, //自定义行高
+    //         defaultColWidth: 73, //自定义列宽
+    //         celldata: formattedData
+    //           .map((row, rowIndex) =>
+    //             row.map((cell, colIndex) => ({
+    //               r: rowIndex,
+    //               c: colIndex,
+    //               v: {
+    //                 m: cell, // 显示的内容
+    //                 ct: {
+    //                   fa: "General", // 格式(通用)
+    //                   t: "g", // 类型(general)
+    //                 },
+    //                 v: cell, // 实际值
+    //               },
+    //             }))
+    //           )
+    //           .flat(),
+    //         //初始化使用的单元格数据
+    //         config: {
+    //           merge: {}, //合并单元格
+    //           rowlen: {}, //表格行高
+    //           columnlen: {}, //表格列宽
+    //           rowhidden: {}, //隐藏行
+    //           colhidden: {}, //隐藏列
+    //           borderInfo: {}, //边框
+    //           authority: {}, //工作表保护
+    //         },
+    //         scrollLeft: 0, //左右滚动条位置
+    //         scrollTop: 315, //上下滚动条位置
+    //         luckysheet_select_save: [], //选中的区域
+    //         calcChain: [], //公式链
+    //         isPivotTable: false, //是否数据透视表
+    //         pivotTable: {}, //数据透视表设置
+    //         filter_select: {}, //筛选范围
+    //         filter: null, //筛选配置
+    //         luckysheet_alternateformat_save: [], //交替颜色
+    //         luckysheet_alternateformat_save_modelCustom: [], //自定义交替颜色
+    //         luckysheet_conditionformat_save: {}, //条件格式
+    //         frozen: {}, //冻结行列配置
+    //         // chart: [], //图表配置
+    //         zoomRatio: 1, // 缩放比例
+    //         image: [], //图片
+    //         showGridLines: 1, //是否显示网格线
+    //         dataVerification: {}, //数据验证配置
+    //       },
+    //     ],
+    //     title: "LuckySheet示例", // 表格标题
+    //     lang: "zh", // 语言设置
+    //     showtoolbar: true, // 是否显示工具栏
+    //     chart: {
+    //       //
+    //       // 配置图表
+    //       enable: false, // 启用图表功能
+    //     },
+    //     showtoolbarConfig: {
+    //       chart: false, // 隐藏图表工具按钮
+    //     },
+    //   };
+    //   luckysheet.create(options);
+    // },
+    // async saveData() {
+    //   // 获取所有工作表
+    //   const sheets = luckysheet.getAllSheets();
+    //   const allFileData = [];
+    //   sheets.forEach((sheet, ind) => {
+    //     const data = sheet.data; // 获取当前工作表的数据
+    //     const formattedData = [];
+    //     const headers = data[0].map((cell) => (cell && cell.v ? cell.v : "")); // 表头内容
+    //     // 遍历数据行,从第二行开始
+    //     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);
+    //       }
+    //     }
+    //     // 生成唯一的 fileData
+    //     const fileData = {
+    //       filename:
+    //         format(new Date(), "yyyyMMdd-HH:mm:ss") + "_" + ind + sheet.name,
+    //       fileData: formattedData,
+    //       fileOldName: sheet.name + "_" + ind,
+    //       fileId: new Date().getTime() + "_" + ind,
+    //     };
+    //     allFileData.push(fileData); // 将当前工作表的文件数据加入到数组中
+    //   });
+    //   // 批量存储到数据库
+    //   await initDatabase()
+    //     .then((database) => {
+    //       allFileData.forEach((fileData) => {
+    //         if (fileData && fileData.fileData.length > 0) {
+    //           storeSetData(database, "files", "fileDataArray", fileData, () => {
+    //             console.log("数据存储成功:", fileData.filename);
+    //           });
+    //         }
+    //       });
+    //       // 跳转到分析页面
+    //       this.$router.push("/home/performance/customAnalysis");
+    //     })
+    //     .catch((error) => {
+    //       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>
+
+<style scoped lang="scss">
+/* 可以添加一些自定义样式 */
+::v-deep .luckysheet_info_detail div.luckysheet_info_detail_back {
+  display: none;
+}
+</style>

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff