riku
2024-10-24 4f238e1ff525b6aa1f8c9981f044d606a89734ce
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);
    .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) {
  if (!excelDatas.value.has(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);
    // 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()