From b330e57051e54789eb83d10dc58c4d9d10c608e1 Mon Sep 17 00:00:00 2001 From: feiyu02 <risaku@163.com> Date: 星期三, 17 九月 2025 09:55:19 +0800 Subject: [PATCH] 2025.9.17 数据产品模块(待完成) --- 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