From c2fd0bf273c19874d7f1a4f6f6a304ac723b42e3 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期一, 22 九月 2025 09:50:48 +0800
Subject: [PATCH] 2025.9.22 扬尘月度简报分解数据产品(基础-现场巡查、中间-月度巡查简报)完成

---
 src/views/fysp/data-product/components/BaseDataProduct.vue |  265 +++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 237 insertions(+), 28 deletions(-)

diff --git a/src/views/fysp/data-product/components/BaseDataProduct.vue b/src/views/fysp/data-product/components/BaseDataProduct.vue
index 9030b38..8f462ba 100644
--- a/src/views/fysp/data-product/components/BaseDataProduct.vue
+++ b/src/views/fysp/data-product/components/BaseDataProduct.vue
@@ -23,18 +23,18 @@
     </template>
     <template #buttons>
       <CompReportDownloadDialog
-        name="闂涓庢暣鏀规眹鎬诲垎鏋愪笌鍔ㄦ�佽窡韪竻鍗�"
+        :name="fileName"
         :locations="formSearch.locations"
         :scenetype="formSearch.scenetype"
         :time="formSearch.time"
-        @submit="handleSearch"
+        @submit="(e) => handleSearch(e, true)"
       ></CompReportDownloadDialog>
     </template>
   </FYSearchBar>
   <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,34 +43,75 @@
   </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.prop"
+        :label="item.name"
       >
+        <template v-if="item.children" #default="{ row }">
+          <span v-html="row[item.prop]"></span>
+          <el-table-column
+            v-for="(item1, index1) in item.children"
+            :key="index1"
+            :prop="item1.prop"
+            :label="item1.name"
+          >
+            <template v-if="item1.children" #default="scope1">
+              <span v-html="scope1.row[item1.prop]"></span>
+              <el-table-column
+                v-for="(item2, index2) in item1.children"
+                :key="index2"
+                :prop="item2.prop"
+                :label="item2.name"
+              >
+                <template v-if="item2.children" #default="scope2">
+                  <span v-html="scope2.row[item2.prop]"></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>
 /**
  * 闂鍔ㄦ�佽窡韪�
  */
-import { ref, onMounted } from 'vue';
+//寮曞叆VueOfficeExcel缁勪欢
+import VueOfficeExcel from '@vue-office/excel';
+//寮曞叆鐩稿叧鏍峰紡
+import '@vue-office/excel/lib/index.css';
+
+import { ref, onMounted, computed } 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';
+import { Base64 } from 'js-base64';
+import { useBgtaskStore } from '@/stores/bgtaskStore';
+
+const bgtaskStore = useBgtaskStore();
 
 const emit = defineEmits(['search']);
 
@@ -91,6 +132,19 @@
   }
 });
 
+const fileName = computed(() => {
+  switch (props.productType) {
+    case 1:
+      return '闂涓庢暣鏀规眹鎬诲垎鏋愪笌鍔ㄦ�佽窡韪竻鍗�';
+    case 2:
+      return '瑙勮寖鎬ц瘎浼颁笌鍒嗘瀽娓呭崟';
+    case 3:
+      return '闂涓庢暣鏀瑰垎甯冨垎鏋愭竻鍗�';
+    default:
+      return '鎶ュ憡娓呭崟';
+  }
+});
+
 const formSearch = ref({
   locations: {},
   scenetype: {},
@@ -100,12 +154,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;
@@ -119,7 +175,7 @@
   getTable(activeSheet.value);
 }
 
-function handleSearch(forceUpdate) {
+function handleSearch(forceUpdate, isDownload) {
   const locations = formSearch.value.locations;
   const time = formSearch.value.time;
   const scenetype = formSearch.value.scenetype;
@@ -134,28 +190,87 @@
     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) => {
+      if (res == false) {
+        alert('鎶ュ憡鐢熸垚涓紝鍙湪鍚庡彴浠诲姟鏌ョ湅鐢熸垚杩涘害');
+        bgtaskStore.dialogShow = true;
+        bgtaskStore.fetchTask();
+      } else {
+        if (isDownload) {
+          const name = Base64.decode(res.headers.get('filename'));
+          const url = window.URL.createObjectURL(res.data);
+          const link = document.createElement('a');
+          link.href = url;
+          link.setAttribute('download', name);
+          document.body.appendChild(link);
+          link.click();
+          document.body.removeChild(link);
+          window.URL.revokeObjectURL(url);
+        } else {
+          res.data.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'), '</span><br/><span>');
+        // newTxt = newTxt.replace(new RegExp(/"/, 'g'), '');
+        // tableData = tableData.replace(txt, `<span>${newTxt}</span>`);
+        let newTxt = txt.replace(new RegExp(/\n/, 'g'), '');
+        newTxt = newTxt.replace(new RegExp(/"/, 'g'), '');
+        tableData = tableData.replace(txt, newTxt);
+      });
+    }
+    // console.log(tableData);
+
+    const t = strToTableObj(tableData);
+    // console.log(t);
+    // console.log(head);
+    // console.log(data);
+    excelDatas.value.set(sheetName, t);
+  }
+  activeExcelData.value = excelDatas.value.get(sheetName);
+
+  // activeExcelData.value = props.beforeDataShow(tableData);
 }
 
 // 鏍规嵁琛ㄥご鐨勮鏁帮紝鍚堝苟琛ㄥご
@@ -173,11 +288,105 @@
 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) => {
+        const prop = r == '' ? r : `id-${r}-${y}`;
+        lastHead.push({ name: r, prop });
+        dataKeys.push(prop);
+      });
+    } else {
+      const newHead = [];
+      row.forEach((r, y) => {
+        const prop = `id-${r}-${y}`;
+        if (dataKeys[y] == '') {
+          // lastHead[y] = { name: r, prop };
+          dataKeys[y] = prop;
+        }
+
+        const last = lastHead[y];
+        if (!last) {
+          console.log(last);
+        }
+        if (last.name == '') {
+          newHead.push({ name: r, prop });
+          offset++;
+        } else if (r != '') {
+          newHead.push({
+            name: r,
+            children: [last]
+          });
+          offset = 1;
+        } else {
+          newHead.push({ name: '', prop });
+          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