feat:Roaming CDR自定义导出功能
This commit is contained in:
@@ -22,6 +22,8 @@ import saveAs from 'file-saver';
|
||||
import { useClipboard } from '@vueuse/core';
|
||||
import dayjs, { type Dayjs } from 'dayjs';
|
||||
import { dayjsRanges } from '@/hooks/useRangePicker';
|
||||
import ExportCustomModal from '@/components/ExportCustomModal/index.vue';
|
||||
import * as XLSX from 'xlsx';
|
||||
const { copy } = useClipboard({ legacy: true });
|
||||
const { t } = useI18n();
|
||||
const ws = new WS();
|
||||
@@ -397,9 +399,243 @@ function fnExportList() {
|
||||
});
|
||||
}
|
||||
|
||||
/**自定义导出 - 先获取后端数据来确定可用列 */
|
||||
function fnExportCustom() {
|
||||
if (modalState.confirmLoading || tablePagination.total === 0) return;
|
||||
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
|
||||
// 先获取后端标准格式的完整数据
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageNum = 1;
|
||||
querys.pageSize = Math.min(tablePagination.total, 10); // 只获取前10条用于分析列结构
|
||||
querys.startTime = Number(querys.startTime);
|
||||
querys.endTime = Number(querys.endTime);
|
||||
|
||||
exportSGWCDataCDR(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
// 解析后端Excel文件,获取可用的列
|
||||
parseExcelColumns(res.data);
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Export error:', error);
|
||||
message.error({
|
||||
content: t('common.operateError'),
|
||||
duration: 3,
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**解析Excel获取可用的列信息 */
|
||||
function parseExcelColumns(excelBlob: Blob) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
try {
|
||||
const data = new Uint8Array(e.target?.result as ArrayBuffer);
|
||||
const workbook = XLSX.read(data, { type: 'array' });
|
||||
|
||||
// 获取第一个工作表
|
||||
const firstSheetName = workbook.SheetNames[0];
|
||||
const worksheet = workbook.Sheets[firstSheetName];
|
||||
|
||||
// 将工作表转换为JSON格式
|
||||
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
|
||||
|
||||
if (jsonData.length === 0) {
|
||||
message.error(t('common.noData'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取表头(第一行)
|
||||
const headers = jsonData[0] as string[];
|
||||
const dataRows = jsonData.slice(1, 4); // 取前3行作为示例数据
|
||||
|
||||
// 构建可用列配置
|
||||
const availableColumns = headers.map((header, index) => ({
|
||||
key: `col_${index}`,
|
||||
title: header,
|
||||
originalTitle: header,
|
||||
dataIndex: `col_${index}`,
|
||||
columnIndex: index,
|
||||
visible: true
|
||||
}));
|
||||
|
||||
exportAvailableColumns.value = availableColumns;
|
||||
|
||||
// 构建示例数据
|
||||
const sampleData = dataRows.map((row: any) => {
|
||||
const obj: any = { id: Math.random() };
|
||||
headers.forEach((header, index) => {
|
||||
obj[`col_${index}`] = row[index] || '';
|
||||
});
|
||||
return obj;
|
||||
});
|
||||
|
||||
exportSampleData.value = sampleData;
|
||||
|
||||
// 打开自定义导出对话框
|
||||
exportCustomVisible.value = true;
|
||||
|
||||
} catch (error) {
|
||||
console.error('Parse Excel error:', error);
|
||||
message.error(t('common.operateError'));
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsArrayBuffer(excelBlob);
|
||||
}
|
||||
|
||||
/**处理自定义导出确认 */
|
||||
function handleExportCustomConfirm(config: any[]) {
|
||||
exportCustomConfig.value = config;
|
||||
modalState.confirmLoading = true;
|
||||
const hide = message.loading(t('common.loading'), 0);
|
||||
|
||||
// 先获取后端标准格式的完整数据
|
||||
const querys = toRaw(queryParams);
|
||||
querys.pageNum = 1;
|
||||
querys.pageSize = tablePagination.total;
|
||||
querys.startTime = Number(querys.startTime);
|
||||
querys.endTime = Number(querys.endTime);
|
||||
|
||||
exportSGWCDataCDR(querys)
|
||||
.then(res => {
|
||||
if (res.code === RESULT_CODE_SUCCESS) {
|
||||
// 后端返回标准格式数据后,在前端进行自定义处理
|
||||
processCustomExport(res.data, config);
|
||||
message.success({
|
||||
content: t('common.operateOk'),
|
||||
duration: 3,
|
||||
});
|
||||
} else {
|
||||
message.error({
|
||||
content: `${res.msg}`,
|
||||
duration: 3,
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Export error:', error);
|
||||
message.error({
|
||||
content: t('common.operateError'),
|
||||
duration: 3,
|
||||
});
|
||||
})
|
||||
.finally(() => {
|
||||
hide();
|
||||
modalState.confirmLoading = false;
|
||||
});
|
||||
}
|
||||
|
||||
/**处理自定义导出 - 基于后端数据在前端自定义处理 */
|
||||
function processCustomExport(excelBlob: Blob, config: any[]) {
|
||||
// 读取后端返回的Excel文件
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
try {
|
||||
const data = new Uint8Array(e.target?.result as ArrayBuffer);
|
||||
const workbook = XLSX.read(data, { type: 'array' });
|
||||
|
||||
// 获取第一个工作表
|
||||
const firstSheetName = workbook.SheetNames[0];
|
||||
const worksheet = workbook.Sheets[firstSheetName];
|
||||
|
||||
// 将工作表转换为JSON格式
|
||||
const jsonData = XLSX.utils.sheet_to_json(worksheet, { header: 1 });
|
||||
|
||||
if (jsonData.length === 0) {
|
||||
message.error(t('common.noData'));
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取表头(第一行)
|
||||
const originalHeaders = jsonData[0] as string[];
|
||||
const dataRows = jsonData.slice(1);
|
||||
|
||||
// 根据配置处理数据
|
||||
const processedData = processDataWithConfig(originalHeaders, dataRows, config);
|
||||
|
||||
// 生成新的Excel文件
|
||||
generateCustomExcelFile(processedData);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Process custom export error:', error);
|
||||
message.error(t('common.operateError'));
|
||||
}
|
||||
};
|
||||
|
||||
reader.readAsArrayBuffer(excelBlob);
|
||||
}
|
||||
|
||||
/**根据配置处理数据 */
|
||||
function processDataWithConfig(originalHeaders: string[], dataRows: any[], config: any[]) {
|
||||
// 获取可见的列配置
|
||||
const visibleColumns = config.filter(col => col.visible);
|
||||
|
||||
// 处理表头
|
||||
const newHeaders = visibleColumns.map(col => col.title);
|
||||
|
||||
// 处理数据行 - 使用columnIndex直接访问
|
||||
const newDataRows = dataRows.map(row => {
|
||||
return visibleColumns.map(col => {
|
||||
// 使用columnIndex字段直接访问对应列的数据
|
||||
const columnIndex = col.columnIndex;
|
||||
return columnIndex !== undefined ? (row[columnIndex] || '') : '';
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
headers: newHeaders,
|
||||
data: newDataRows
|
||||
};
|
||||
}
|
||||
|
||||
/**生成自定义Excel文件 */
|
||||
function generateCustomExcelFile(processedData: { headers: string[], data: any[] }) {
|
||||
// 创建工作簿
|
||||
const wb = XLSX.utils.book_new();
|
||||
|
||||
// 准备Excel数据
|
||||
const excelData = [processedData.headers, ...processedData.data];
|
||||
|
||||
// 创建工作表
|
||||
const ws = XLSX.utils.aoa_to_sheet(excelData);
|
||||
|
||||
// 设置列宽
|
||||
const colWidths = processedData.headers.map(() => ({ wch: 20 }));
|
||||
ws['!cols'] = colWidths;
|
||||
|
||||
// 添加工作表到工作簿
|
||||
XLSX.utils.book_append_sheet(wb, ws, 'SGWC CDR');
|
||||
|
||||
// 生成Excel文件并下载
|
||||
const excelBuffer = XLSX.write(wb, { bookType: 'xlsx', type: 'array' });
|
||||
const blob = new Blob([excelBuffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
||||
|
||||
saveAs(blob, `sgwc_cdr_custom_export_${Date.now()}.xlsx`);
|
||||
}
|
||||
|
||||
/**实时数据开关 */
|
||||
const realTimeData = ref<boolean>(false);
|
||||
|
||||
/**自定义导出配置 */
|
||||
const exportCustomVisible = ref<boolean>(false);
|
||||
const exportCustomConfig = ref<any[]>([]);
|
||||
const exportAvailableColumns = ref<any[]>([]);
|
||||
const exportSampleData = ref<any[]>([]);
|
||||
|
||||
/**
|
||||
* 实时数据
|
||||
*/
|
||||
@@ -619,10 +855,25 @@ onBeforeUnmount(() => {
|
||||
{{ t('common.deleteText') }}
|
||||
</a-button>
|
||||
|
||||
<a-button type="dashed" @click.prevent="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
</a-button>
|
||||
<a-dropdown trigger="click" placement="bottomRight">
|
||||
<a-button type="dashed">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.export') }}
|
||||
<DownOutlined />
|
||||
</a-button>
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="export-default" @click="fnExportList()">
|
||||
<template #icon><ExportOutlined /></template>
|
||||
{{ t('common.exportDefault') }}
|
||||
</a-menu-item>
|
||||
<a-menu-item key="export-custom" @click="fnExportCustom()">
|
||||
<template #icon><SettingOutlined /></template>
|
||||
{{ t('common.exportCustom') }}
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
</a-dropdown>
|
||||
</a-space>
|
||||
</template>
|
||||
|
||||
@@ -830,6 +1081,14 @@ onBeforeUnmount(() => {
|
||||
</template>
|
||||
</a-table>
|
||||
</a-card>
|
||||
|
||||
<!-- 自定义导出配置模态框 -->
|
||||
<ExportCustomModal
|
||||
v-model:open="exportCustomVisible"
|
||||
:original-columns="exportAvailableColumns"
|
||||
:sample-data="exportSampleData"
|
||||
@confirm="handleExportCustomConfirm"
|
||||
/>
|
||||
</PageContainer>
|
||||
</template>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user