From 4f238e1ff525b6aa1f8c9981f044d606a89734ce Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期四, 24 十月 2024 08:27:19 +0800
Subject: [PATCH] 1. 新增完成展示下载的excel文件功能

---
 src/views/fysp/data-product/components/BaseDataProduct.vue |  216 ++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 192 insertions(+), 24 deletions(-)

diff --git a/src/views/fysp/data-product/components/BaseDataProduct.vue b/src/views/fysp/data-product/components/BaseDataProduct.vue
index 9030b38..b53953e 100644
--- a/src/views/fysp/data-product/components/BaseDataProduct.vue
+++ b/src/views/fysp/data-product/components/BaseDataProduct.vue
@@ -34,7 +34,7 @@
   <el-form ref="expandRef" :inline="true">
     <CompQuickSet @quick-set="setOptions"></CompQuickSet>
   </el-form>
-  <el-space>
+  <el-space ref="segmentedRef">
     <el-segmented
       :model-value="activeSheet"
       :options="sheetNames"
@@ -43,32 +43,69 @@
   </el-space>
   <el-table
     ref="tableRef"
-    :data="excelData"
+    :data="activeExcelData.data"
     v-loading="loading"
-    table-layout="fixed"
+    table-layout="auto"
     size="small"
     :height="tableHeight"
+    fit
+    flexible
+    stripe
     border
   >
-    <template v-if="excelData">
+    <template v-if="activeExcelData.head">
       <el-table-column
-        v-for="(value, key, index) in excelData[0]"
+        v-for="(item, index) in activeExcelData.head"
         :key="index"
-        :prop="key"
-        :label="key"
+        :prop="item.name"
+        :label="item.name"
       >
+        <template v-if="item.children" #default="{ row }">
+          <span v-html="row[item.name]"></span>
+          <el-table-column
+            v-for="(item1, index1) in item.children"
+            :key="index1"
+            :prop="item1.name"
+            :label="item1.name"
+          >
+            <template v-if="item1.children" #default="{ row1 }">
+              <span v-html="row1[item1.name]"></span>
+              <el-table-column
+                v-for="(item2, index2) in item1.children"
+                :key="index2"
+                :prop="item2.name"
+                :label="item2.name"
+              >
+                <template v-if="item2.children" #default="{ row2 }">
+                  <span v-html="row2[item2.name]"></span>
+                </template>
+              </el-table-column>
+            </template>
+          </el-table-column>
+        </template>
       </el-table-column>
     </template>
   </el-table>
-  <div v-if="excelHtml" v-html="excelHtml"></div>
+  <!-- <vue-office-excel
+    :src="excel"
+    :style="'height: ' + tableHeight"
+    @rendered="renderedHandler"
+    @error="errorHandler"
+  /> -->
 </template>
 <script setup>
 /**
  * 闂鍔ㄦ�佽窡韪�
  */
+//寮曞叆VueOfficeExcel缁勪欢
+import VueOfficeExcel from '@vue-office/excel';
+//寮曞叆鐩稿叧鏍峰紡
+import '@vue-office/excel/lib/index.css';
+
 import { ref, onMounted } from 'vue';
 import dayjs from 'dayjs';
 import * as XLSX from 'xlsx';
+import * as ExcelJS from 'exceljs';
 import dataproductApi from '@/api/fysp/dataproductApi';
 import CompReportDownloadDialog from './CompReportDownloadDialog.vue';
 
@@ -100,12 +137,14 @@
 const tableHeight = ref('500');
 let workbook;
 const sheetNames = ref();
+const excelDatas = ref(new Map());
 const activeSheet = ref();
-const excelData = ref();
-const excelHtml = ref();
+const activeExcelData = ref({});
+const excel = ref('');
 
 const searchRef = ref(null);
 const expandRef = ref(null);
+const segmentedRef = ref(null);
 
 function setOptions(param) {
   formSearch.value.locations = param.locations;
@@ -134,28 +173,66 @@
     scensetypeid: scenetype.value
   };
 
+  excelDatas.value.clear();
   loading.value = true;
   dataproductApi
     .downloadProduct(area, props.productType, forceUpdate ? forceUpdate : false)
-    .then((res) => {
-      const data = new Uint8Array(res);
-      workbook = XLSX.read(data, { type: 'array' });
-      sheetNames.value = workbook.SheetNames;
-      activeSheet.value = sheetNames.value[0];
-      getTable(activeSheet.value);
+    .then(async (res) => {
+      // const data = new Uint8Array(res);
+      res.arrayBuffer().then((data) => {
+        workbook = XLSX.read(data, { type: 'array' });
+        sheetNames.value = workbook.SheetNames;
+        activeSheet.value = sheetNames.value[0];
+        getTable(activeSheet.value);
+      });
+
+      // const workbook = new ExcelJS.Workbook();
+      // await workbook.xlsx.load(res);
+      // workbook.eachSheet(function (worksheet, sheetId) {
+      //   console.log(worksheet.name);
+      // });
+      // const sheet1 = workbook.worksheets[0]
+      // const row = sheet1.getRow(1)
+      // console.log(row);
+
+      // console.log(res);
+      // console.log(new ArrayBuffer(res));
+      // res.arrayBuffer().then(r=>{
+      //   excel.value = r
+      // })
+
+      // excel.value = new ArrayBuffer(res)
     })
     .finally(() => (loading.value = false));
 }
 
 function getTable(sheetName) {
-  const worksheet = workbook.Sheets[sheetName];
-  const tableData = XLSX.utils.sheet_to_json(worksheet, { header: 3 });
-  // const tableData = XLSX.utils.sheet_to_csv(worksheet);
-  console.log(tableData);
-  console.log(tableData[0]);
-  combineTableHead(tableData);
+  if (!excelDatas.value.has(sheetName)) {
+    const worksheet = workbook.Sheets[sheetName];
+    // const tableData = XLSX.utils.sheet_to_json(worksheet, { header: 3 });
+    let tableData = XLSX.utils.sheet_to_txt(worksheet);
+    // console.log(tableData);
 
-  excelData.value = props.beforeDataShow(tableData);
+    const regx = new RegExp(/"([^"]|\n)+"/, 'g');
+    let matchTxt = tableData.match(regx);
+
+    if (matchTxt) {
+      matchTxt.forEach((txt) => {
+        let newTxt = txt.replace(new RegExp(/\n/, 'g'), '<br />');
+        newTxt = newTxt.replace(new RegExp(/"/, 'g'), '');
+        tableData = tableData.replace(txt, newTxt);
+      });
+      // console.log(tableData);
+    }
+
+    const t = strToTableObj(tableData);
+    // console.log(head);
+    // console.log(data);
+    excelDatas.value.set(sheetName, t);
+  }
+  activeExcelData.value = excelDatas.value.get(sheetName);
+
+  // activeExcelData.value = props.beforeDataShow(tableData);
 }
 
 // 鏍规嵁琛ㄥご鐨勮鏁帮紝鍚堝苟琛ㄥご
@@ -173,11 +250,102 @@
 function calcTableHeight() {
   const h1 = searchRef.value.$el.offsetHeight;
   const h2 = expandRef.value.$el.offsetHeight;
+  const h3 = segmentedRef.value.$el.offsetHeight;
 
-  const h = h1 + h2;
+  const h = h1 + h2 + h3;
   return `calc(100vh - ${h}px - 60px - var(--el-main-padding) * 2)`;
 }
 
+function renderedHandler() {
+  console.log('娓叉煋瀹屾垚');
+}
+function errorHandler(e) {
+  console.log('娓叉煋澶辫触', e);
+}
+
+function strToTableObj(data, headNum) {
+  const rows = data.split('\n').map((r) => r.split('\t'));
+  if (rows.length == 0) return;
+
+  let header = 1;
+  for (let i = 1; i < rows.length; i++) {
+    const row = rows[i];
+    if (row.length == 0) {
+      break;
+    }
+    if (row[0] == '') {
+      header++;
+    } else {
+      break;
+    }
+  }
+
+  if (rows.length < header) {
+    throw new Error(`鏂囦欢琛屾暟灏忎簬${header}`);
+  }
+  // 琛ㄥご
+  let lastHead = [];
+  // 灞炴�у悕
+  const dataKeys = [];
+  let offset = 1;
+  for (let i = header - 1; i >= 0; i--) {
+    const row = rows[i];
+    if (lastHead.length == 0) {
+      row.forEach((r, y) => {
+        lastHead.push({ name: r });
+        dataKeys.push(r);
+      });
+    } else {
+      const newHead = [];
+      row.forEach((r, y) => {
+        if (dataKeys[y] == '') {
+          dataKeys[y] = r;
+        }
+
+        const last = lastHead[y];
+        if (!last) {
+          console.log(last);
+        }
+        if (last.name == '') {
+          newHead.push({ name: r });
+          offset++;
+        } else if (r != '') {
+          newHead.push({
+            name: r,
+            children: [last]
+          });
+          offset = 1;
+        } else {
+          newHead.push({ name: '' });
+          let _index = newHead.length - 1 - offset;
+          _index = _index >= 0 ? _index : 0;
+          newHead[_index].children.push(last);
+          offset++;
+        }
+      });
+      lastHead = newHead;
+    }
+  }
+  const heads = [];
+  lastHead.forEach((h) => {
+    if (h && h.name != '') {
+      heads.push(h);
+    }
+  });
+
+  const tableData = [];
+  for (let i = header; i < rows.length; i++) {
+    const row = rows[i];
+    const data = {};
+    row.forEach((r, y) => {
+      data[dataKeys[y]] = r;
+    });
+    tableData.push(data);
+  }
+
+  return { head: heads, data: tableData };
+}
+
 onMounted(() => {
   tableHeight.value = calcTableHeight();
   // handleSearch()

--
Gitblit v1.9.3