aegon-gen 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +12 -0
- package/src/App.vue +3 -0
- package/src/api/index.ts +19 -0
- package/src/api/modules/gen-ai/gen-entry/index.ts +30 -0
- package/src/api/modules/gen-ai/model-manager/index.ts +42 -0
- package/src/api/modules/gen-ai/model-manager/mockApi.ts +33 -0
- package/src/api/modules/index.ts +98 -0
- package/src/api/modules/user/index.ts +4 -0
- package/src/api/request.ts +102 -0
- package/src/assets/sample-access-icon.png +0 -0
- package/src/assets/sample-pie-chart.png +0 -0
- package/src/assets/vue.svg +1 -0
- package/src/components/CapsuleScrollbar.vue +93 -0
- package/src/components/Export/ExcelExport.vue +592 -0
- package/src/components/Export/ExcelExport2.vue +494 -0
- package/src/components/Export/ExcelExport3.vue +342 -0
- package/src/components/Export/ExcelExport4.vue +665 -0
- package/src/components/Export/excelExport.js +547 -0
- package/src/components/Export/excelExport.ts +551 -0
- package/src/components/GEN-AI/index.vue +142 -0
- package/src/components/GEN-AI/index1.vue +456 -0
- package/src/components/GEN-AI/index10.vue +5 -0
- package/src/components/GEN-AI/index2.vue +568 -0
- package/src/components/GEN-AI/index3.vue +623 -0
- package/src/components/GEN-AI/index4.vue +629 -0
- package/src/components/GEN-AI/index5.vue +578 -0
- package/src/components/GEN-AI/index6.vue +656 -0
- package/src/components/GEN-AI/index7.vue +717 -0
- package/src/components/GEN-AI/index8.vue +405 -0
- package/src/components/GEN-AI/index9.vue +1065 -0
- package/src/components/GEN-AI/types.ts +12 -0
- package/src/components/GEN-AI/utils.ts +42 -0
- package/src/components/HelloWorld.vue +41 -0
- package/src/components/PageCard.vue +7 -0
- package/src/components/PageHeader.vue +32 -0
- package/src/components/backup/index5 copy.vue +556 -0
- package/src/components/backup/index5.vue +620 -0
- package/src/components/backup/index9 copy.vue +1029 -0
- package/src/components/backup/index9-pro.vue +1065 -0
- package/src/components/backup/index9.vue +1057 -0
- package/src/components/el-date-picker.vue +64 -0
- package/src/directives/btnLoading.ts +427 -0
- package/src/directives/debounce copy.ts +670 -0
- package/src/directives/debounce.ts +98 -0
- package/src/directives/index.ts +25 -0
- package/src/layouts/MainLayout.vue +101 -0
- package/src/main.ts +85 -0
- package/src/router/index.ts +76 -0
- package/src/router/menus.ts +28 -0
- package/src/style.css +79 -0
- package/src/styles/_variables.scss +24 -0
- package/src/styles/app-button.css +26 -0
- package/src/styles/element-overrides.css +23 -0
- package/src/styles/global.css +44 -0
- package/src/styles/index.scss +1 -0
- package/src/styles/page-card.css +21 -0
- package/src/styles/variables.css +26 -0
- package/src/test/mock.ts +101 -0
- package/src/test/test1.vue +402 -0
- package/src/test/test2.vue +1689 -0
- package/src/types/gen-ai/gen-entry/index.ts +17 -0
- package/src/types/gen-ai/model-manager/index.ts +19 -0
- package/src/utils/docxExport.ts +1610 -0
- package/src/utils/gen-ai-navigation.ts +37 -0
- package/src/utils/gen-ai-scroll.ts +455 -0
- package/src/utils/openDataLoaderWordExport.ts +33 -0
- package/src/utils/pageScrollbar.ts +115 -0
- package/src/utils/randomTranscode.ts +87 -0
- package/src/utils/reportPdfExport.ts +44 -0
- package/src/views/AdminCenter/index.vue +817 -0
- package/src/views/Blank.vue +68 -0
- package/src/views/Home.vue +29 -0
- package/src/views/ReportCenter/index.vue +1380 -0
- package/src/views/TemplateCenter/Knowledge.ts +83 -0
- package/src/views/TemplateCenter/data.d.ts +10 -0
- package/src/views/TemplateCenter/index.vue +1205 -0
- package/src/views/TemplateCenter/service.ts +69 -0
- package/src/views/gen-ai/components/RecentReportsTable.vue +193 -0
- package/src/views/gen-ai/gen-entry/index.vue +309 -0
- package/src/views/gen-ai/gen-entry/mockData.ts +160 -0
- package/src/views/gen-ai/management-center/index.vue +53 -0
- package/src/views/gen-ai/model-manager/ChapterTitleScroll.vue +275 -0
- package/src/views/gen-ai/model-manager/index.vue +1205 -0
- package/src/views/gen-ai/model-manager/mockData.ts +122 -0
- package/src/views/gen-ai/report-center/index.vue +158 -0
- package/src/vite-env.d.ts +38 -0
|
@@ -0,0 +1,494 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="export-container">
|
|
3
|
+
<!-- 导出按钮 -->
|
|
4
|
+
<el-button type="primary" @click="exportExcel"
|
|
5
|
+
>导出Excel(Vue3+TS)</el-button
|
|
6
|
+
>
|
|
7
|
+
<!-- 导出状态提示 -->
|
|
8
|
+
<p v-if="isExporting">正在导出...</p>
|
|
9
|
+
<p v-if="exportSuccess" style="color: green">导出成功!</p>
|
|
10
|
+
<p v-if="exportError" style="color: red">导出失败!</p>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import { ref } from "vue";
|
|
16
|
+
import ExcelJS from "exceljs";
|
|
17
|
+
import type { CellValue, Worksheet, Row, Cell } from "exceljs";
|
|
18
|
+
import { ElMessage } from "element-plus";
|
|
19
|
+
|
|
20
|
+
// 导出状态
|
|
21
|
+
const isExporting = ref(false);
|
|
22
|
+
const exportSuccess = ref(false);
|
|
23
|
+
const exportError = ref(false);
|
|
24
|
+
|
|
25
|
+
// 提取的表格数据(表头+数据行)
|
|
26
|
+
const complexLoanData = [
|
|
27
|
+
// 表头行
|
|
28
|
+
[
|
|
29
|
+
"會計日",
|
|
30
|
+
"控制行號",
|
|
31
|
+
"客戶CIN",
|
|
32
|
+
"客戶經理號",
|
|
33
|
+
"客戶經理名稱",
|
|
34
|
+
"客戶英文名",
|
|
35
|
+
"客戶中文名",
|
|
36
|
+
"帳號",
|
|
37
|
+
"產品(大項)",
|
|
38
|
+
"產品(細項)",
|
|
39
|
+
"餘額(HKD)",
|
|
40
|
+
"額度(HKD)",
|
|
41
|
+
"授信資產風險評級YBD",
|
|
42
|
+
"逾期天數",
|
|
43
|
+
],
|
|
44
|
+
// 数据行1
|
|
45
|
+
[
|
|
46
|
+
"2025-12-12",
|
|
47
|
+
"307",
|
|
48
|
+
"72050XXXXXX",
|
|
49
|
+
"8812345",
|
|
50
|
+
"陳XX",
|
|
51
|
+
"FXXXX LIMITED",
|
|
52
|
+
"朝XXXXXX有限公司",
|
|
53
|
+
"1288740XXXXXX",
|
|
54
|
+
"特定放款計劃",
|
|
55
|
+
"HKMC中小企融資擔保計劃(SFGS)-定放/定押放/循環貸款/租購放款",
|
|
56
|
+
"1,481,082.78",
|
|
57
|
+
"4,000,000.00 S2M",
|
|
58
|
+
"",
|
|
59
|
+
"11",
|
|
60
|
+
],
|
|
61
|
+
// 数据行2
|
|
62
|
+
[
|
|
63
|
+
"2025-12-11",
|
|
64
|
+
"307",
|
|
65
|
+
"72050XXXXXX",
|
|
66
|
+
"8812345",
|
|
67
|
+
"陳XX",
|
|
68
|
+
"FXXXX LIMITED",
|
|
69
|
+
"朝XXXXXX有限公司",
|
|
70
|
+
"1288741XXXXXX",
|
|
71
|
+
"特定放款計劃",
|
|
72
|
+
"HKMC中小企融資擔保計劃(SFGS)-定放/定押放/循環貸款/租購放款",
|
|
73
|
+
"3,481,082.78",
|
|
74
|
+
"6,000,000.00 S2M",
|
|
75
|
+
"",
|
|
76
|
+
"1",
|
|
77
|
+
],
|
|
78
|
+
// 添加更多测试数据(不同日期)
|
|
79
|
+
[
|
|
80
|
+
"2025-12-12",
|
|
81
|
+
"308",
|
|
82
|
+
"72051XXXXXX",
|
|
83
|
+
"8812346",
|
|
84
|
+
"李XX",
|
|
85
|
+
"GXXXX LIMITED",
|
|
86
|
+
"廣XXXXXX有限公司",
|
|
87
|
+
"1288742XXXXXX",
|
|
88
|
+
"特定放款計劃",
|
|
89
|
+
"HKMC中小企融資擔保計劃(SFGS)-定放/定押放/循環貸款/租購放款",
|
|
90
|
+
"2,481,082.78",
|
|
91
|
+
"5,000,000.00 S2M",
|
|
92
|
+
"",
|
|
93
|
+
"5",
|
|
94
|
+
],
|
|
95
|
+
[
|
|
96
|
+
"2025-12-10",
|
|
97
|
+
"309",
|
|
98
|
+
"72052XXXXXX",
|
|
99
|
+
"8812347",
|
|
100
|
+
"王XX",
|
|
101
|
+
"HXXXX LIMITED",
|
|
102
|
+
"華XXXXXX有限公司",
|
|
103
|
+
"1288743XXXXXX",
|
|
104
|
+
"特定放款計劃",
|
|
105
|
+
"HKMC中小企融資擔保計劃(SFGS)-定放/定押放/循環貸款/租購放款",
|
|
106
|
+
"4,481,082.78",
|
|
107
|
+
"7,000,000.00 S2M",
|
|
108
|
+
"",
|
|
109
|
+
"15",
|
|
110
|
+
],
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 工具函数:安全获取单元格值的长度
|
|
115
|
+
* @param cellValue Excel单元格值
|
|
116
|
+
* @returns 单元格值的字符长度(数字转字符串,空值返回0)
|
|
117
|
+
*/
|
|
118
|
+
const getCellValueLength = (
|
|
119
|
+
cellValue: CellValue | undefined | null
|
|
120
|
+
): number => {
|
|
121
|
+
if (cellValue === null || cellValue === undefined) return 0;
|
|
122
|
+
// 处理不同类型的CellValue,统一转为字符串后计算长度
|
|
123
|
+
let strValue = "";
|
|
124
|
+
if (typeof cellValue === "string") {
|
|
125
|
+
strValue = cellValue;
|
|
126
|
+
} else if (typeof cellValue === "number" || typeof cellValue === "boolean") {
|
|
127
|
+
strValue = cellValue.toString();
|
|
128
|
+
} else if (cellValue instanceof Date) {
|
|
129
|
+
strValue = cellValue.toISOString();
|
|
130
|
+
} else {
|
|
131
|
+
// 处理富文本、公式等特殊类型,转为字符串
|
|
132
|
+
strValue = String(cellValue);
|
|
133
|
+
}
|
|
134
|
+
return strValue.length;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* 判断是否为数字的辅助函数
|
|
139
|
+
* @param value 单元格值
|
|
140
|
+
* @returns 是否为数字(包括带小数点的数字字符串)
|
|
141
|
+
*/
|
|
142
|
+
const isNumberValue = (value: any): boolean => {
|
|
143
|
+
if (value === null || value === undefined) return false;
|
|
144
|
+
if (typeof value === "number") return true;
|
|
145
|
+
if (typeof value !== "string") return false;
|
|
146
|
+
|
|
147
|
+
// 移除千分位逗号和货币符号
|
|
148
|
+
const cleanedValue = value.replace(/[,$]/g, "").replace(/\s/g, "");
|
|
149
|
+
|
|
150
|
+
// 检查是否为数字(包括负数、小数、带单位的数字)
|
|
151
|
+
return /^-?\d+(\.\d+)?/.test(cleanedValue);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* 按日期分组数据
|
|
156
|
+
* @param data 原始数据(包含表头)
|
|
157
|
+
* @returns 按日期分组的对象,键为日期,值为该日期的数据数组
|
|
158
|
+
*/
|
|
159
|
+
const groupDataByDate = (data: string[][]): Record<string, string[][]> => {
|
|
160
|
+
if (data.length <= 1) return {}; // 只有表头或空数据
|
|
161
|
+
|
|
162
|
+
const header: string[] = data[0] || [];
|
|
163
|
+
const dateGroups: Record<string, string[][]> = {};
|
|
164
|
+
|
|
165
|
+
// 安全检查:确保header存在
|
|
166
|
+
if (!header || !Array.isArray(header)) {
|
|
167
|
+
dateGroups["全部数据"] = data;
|
|
168
|
+
return dateGroups;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const dateColumnIndex = header.indexOf("會計日"); // 根据实际情况调整列名
|
|
172
|
+
|
|
173
|
+
if (dateColumnIndex === -1) {
|
|
174
|
+
// 如果没有找到日期列,将所有数据放在一个分组中
|
|
175
|
+
dateGroups["全部数据"] = data;
|
|
176
|
+
return dateGroups;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 遍历数据行(跳过表头)
|
|
180
|
+
for (let i = 1; i < data.length; i++) {
|
|
181
|
+
const row: string[] = data[i] || [];
|
|
182
|
+
const date = row[dateColumnIndex];
|
|
183
|
+
|
|
184
|
+
if (!date) continue;
|
|
185
|
+
|
|
186
|
+
if (!dateGroups[date]) {
|
|
187
|
+
// 为新日期创建分组,包含表头
|
|
188
|
+
dateGroups[date] = [header];
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// 添加数据行到对应日期的分组
|
|
192
|
+
dateGroups[date].push(row);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return dateGroups;
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* 配置工作表的样式
|
|
200
|
+
* @param worksheet Excel工作表对象
|
|
201
|
+
* @param header 表头数组
|
|
202
|
+
*/
|
|
203
|
+
const configureWorksheetStyle = (worksheet: Worksheet, header: string[]) => {
|
|
204
|
+
if (!header || !Array.isArray(header)) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 1. 配置表头样式(无特殊颜色和背景,仅加粗)
|
|
209
|
+
const headerRow = worksheet.getRow(1);
|
|
210
|
+
if (headerRow) {
|
|
211
|
+
headerRow.eachCell((cell: Cell) => {
|
|
212
|
+
// 表头字体:仅加粗,无特殊颜色
|
|
213
|
+
cell.font = {
|
|
214
|
+
name: "Calibri",
|
|
215
|
+
size: 11,
|
|
216
|
+
bold: true,
|
|
217
|
+
color: { argb: "FF000000" }, // 黑色文本
|
|
218
|
+
};
|
|
219
|
+
// 表头无特殊背景
|
|
220
|
+
cell.fill = {
|
|
221
|
+
type: "pattern",
|
|
222
|
+
pattern: "solid",
|
|
223
|
+
fgColor: { argb: "FFFFFFFF" }, // 白色背景
|
|
224
|
+
};
|
|
225
|
+
// 表头文本左对齐(垂直居中)
|
|
226
|
+
cell.alignment = {
|
|
227
|
+
vertical: "middle",
|
|
228
|
+
horizontal: "left", // 左对齐
|
|
229
|
+
wrapText: true, // 自动换行
|
|
230
|
+
};
|
|
231
|
+
// 表头黑色边框
|
|
232
|
+
cell.border = {
|
|
233
|
+
top: { style: "thin", color: { argb: "FF000000" } },
|
|
234
|
+
left: { style: "thin", color: { argb: "FF000000" } },
|
|
235
|
+
bottom: { style: "thin", color: { argb: "FF000000" } },
|
|
236
|
+
right: { style: "thin", color: { argb: "FF000000" } },
|
|
237
|
+
};
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// 2. 配置数据行样式
|
|
242
|
+
worksheet.eachRow((row: Row, rowIndex: number) => {
|
|
243
|
+
// 跳过表头行
|
|
244
|
+
if (rowIndex === 1) return;
|
|
245
|
+
|
|
246
|
+
row.eachCell((cell: Cell, cellNumber: number) => {
|
|
247
|
+
// 基础字体设置
|
|
248
|
+
cell.font = {
|
|
249
|
+
name: "Calibri",
|
|
250
|
+
size: 11,
|
|
251
|
+
color: { argb: "FF000000" }, // 黑色文本
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
// 获取列名
|
|
255
|
+
const columnIndex = cellNumber - 1;
|
|
256
|
+
const columnName = columnIndex < header.length ? header[columnIndex] : "";
|
|
257
|
+
|
|
258
|
+
// 数字列处理:右对齐
|
|
259
|
+
const rightAlignedColumns = ["餘額(HKD)", "額度(HKD)", "逾期天數"];
|
|
260
|
+
if (
|
|
261
|
+
(columnName && rightAlignedColumns.includes(columnName)) ||
|
|
262
|
+
isNumberValue(cell.value)
|
|
263
|
+
) {
|
|
264
|
+
cell.alignment = {
|
|
265
|
+
vertical: "middle",
|
|
266
|
+
horizontal: "right", // 右对齐
|
|
267
|
+
wrapText: true,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
// 其他列:左对齐
|
|
271
|
+
else {
|
|
272
|
+
cell.alignment = {
|
|
273
|
+
vertical: "middle",
|
|
274
|
+
horizontal: "left", // 左对齐
|
|
275
|
+
wrapText: true,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// 数据行黑色边框
|
|
280
|
+
cell.border = {
|
|
281
|
+
top: { style: "thin", color: { argb: "FF000000" } },
|
|
282
|
+
left: { style: "thin", color: { argb: "FF000000" } },
|
|
283
|
+
bottom: { style: "thin", color: { argb: "FF000000" } },
|
|
284
|
+
right: { style: "thin", color: { argb: "FF000000" } },
|
|
285
|
+
};
|
|
286
|
+
});
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// 3. 列宽自适应
|
|
290
|
+
worksheet.columns?.forEach((column) => {
|
|
291
|
+
// 初始化默认宽度
|
|
292
|
+
let maxWidth = 10;
|
|
293
|
+
|
|
294
|
+
// 安全处理column.values(空值判断)
|
|
295
|
+
if (column.values && column.values.length > 0) {
|
|
296
|
+
// 明确指定reduce的返回类型为number
|
|
297
|
+
maxWidth = column.values.reduce<number>(
|
|
298
|
+
(w: number, cellValue: CellValue) => {
|
|
299
|
+
// 安全获取单元格值长度(处理所有CellValue类型)
|
|
300
|
+
const cellLength = getCellValueLength(cellValue);
|
|
301
|
+
return Math.max(w, cellLength);
|
|
302
|
+
},
|
|
303
|
+
10
|
|
304
|
+
); // 初始值设为数字10
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// 确保maxWidth是数字后再计算
|
|
308
|
+
column.width = Math.min(maxWidth + 2, 50); // 限制最大宽度为50
|
|
309
|
+
});
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* 行业数据Excel导出函数(支持多工作表,按日期分组)
|
|
314
|
+
* @param worksheetData Excel工作表数据(二维数组)
|
|
315
|
+
* @param excelName 导出文件名(不含.xlsx后缀)
|
|
316
|
+
* @param dateRange 日期范围字符串,可选
|
|
317
|
+
*/
|
|
318
|
+
async function industryExportToExcel(
|
|
319
|
+
worksheetData: string[][],
|
|
320
|
+
excelName: string,
|
|
321
|
+
dateRange?: string
|
|
322
|
+
): Promise<void> {
|
|
323
|
+
const workbook = new ExcelJS.Workbook();
|
|
324
|
+
|
|
325
|
+
// 1. 按日期分组数据
|
|
326
|
+
const dateGroups = groupDataByDate(worksheetData);
|
|
327
|
+
|
|
328
|
+
// 2. 如果没有数据,只创建一个空的工作表
|
|
329
|
+
if (Object.keys(dateGroups).length === 0) {
|
|
330
|
+
const worksheet = workbook.addWorksheet("数据");
|
|
331
|
+
const header = worksheetData[0] || [];
|
|
332
|
+
worksheet.addRows(worksheetData.length > 0 ? worksheetData : [header]);
|
|
333
|
+
configureWorksheetStyle(worksheet, header);
|
|
334
|
+
} else {
|
|
335
|
+
// 3. 为每个日期创建独立的工作表
|
|
336
|
+
Object.keys(dateGroups).forEach((date) => {
|
|
337
|
+
const dateData: string[][] = dateGroups[date] || [];
|
|
338
|
+
|
|
339
|
+
// 创建工作表,工作表名称为日期
|
|
340
|
+
// Excel工作表名称不能包含特定字符,需要处理
|
|
341
|
+
let sheetName = date;
|
|
342
|
+
if (sheetName === "全部数据") {
|
|
343
|
+
sheetName = "汇总";
|
|
344
|
+
} else {
|
|
345
|
+
// 移除可能影响工作表名称的字符
|
|
346
|
+
sheetName = sheetName.replace(/[\/\\\*\?\[\]:]/g, "-");
|
|
347
|
+
// 限制工作表名称长度(Excel限制31个字符)
|
|
348
|
+
if (sheetName.length > 31) {
|
|
349
|
+
sheetName = sheetName.substring(0, 31);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const worksheet = workbook.addWorksheet(sheetName);
|
|
354
|
+
|
|
355
|
+
// 4. 写入数据
|
|
356
|
+
if (dateData.length > 0) {
|
|
357
|
+
worksheet.addRows(dateData);
|
|
358
|
+
|
|
359
|
+
// 5. 配置工作表样式
|
|
360
|
+
const header = dateData[0] || [];
|
|
361
|
+
configureWorksheetStyle(worksheet, header);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// 6. 导出 Excel
|
|
367
|
+
try {
|
|
368
|
+
const buffer = await workbook.xlsx.writeBuffer();
|
|
369
|
+
const blob = new Blob([buffer], {
|
|
370
|
+
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
371
|
+
});
|
|
372
|
+
const url = URL.createObjectURL(blob);
|
|
373
|
+
const a = document.createElement("a");
|
|
374
|
+
|
|
375
|
+
// 构建文件名
|
|
376
|
+
let fileName = excelName;
|
|
377
|
+
if (dateRange) {
|
|
378
|
+
fileName = `${excelName}_${dateRange}`;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
a.href = url;
|
|
382
|
+
a.download = `${fileName}.xlsx`;
|
|
383
|
+
document.body.appendChild(a);
|
|
384
|
+
a.click();
|
|
385
|
+
document.body.removeChild(a);
|
|
386
|
+
URL.revokeObjectURL(url);
|
|
387
|
+
return Promise.resolve();
|
|
388
|
+
} catch (error) {
|
|
389
|
+
return Promise.reject(error);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* 获取日期范围字符串
|
|
395
|
+
* @param data 数据数组
|
|
396
|
+
* @returns 日期范围字符串,如 "2025-12-10~2025-12-12"
|
|
397
|
+
*/
|
|
398
|
+
const getDateRangeString = (data: string[][]): string => {
|
|
399
|
+
if (data.length <= 1) return "";
|
|
400
|
+
|
|
401
|
+
const header: string[] = data[0] || [];
|
|
402
|
+
const dateColumnIndex = header.indexOf("會計日");
|
|
403
|
+
|
|
404
|
+
if (dateColumnIndex === -1) return "";
|
|
405
|
+
|
|
406
|
+
const dates: string[] = [];
|
|
407
|
+
|
|
408
|
+
// 收集所有日期
|
|
409
|
+
for (let i = 1; i < data.length; i++) {
|
|
410
|
+
const row: string[] = data[i] || [];
|
|
411
|
+
const date = row[dateColumnIndex];
|
|
412
|
+
if (date && !dates.includes(date)) {
|
|
413
|
+
dates.push(date);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
if (dates.length === 0) return "";
|
|
418
|
+
|
|
419
|
+
// 排序日期
|
|
420
|
+
dates.sort();
|
|
421
|
+
|
|
422
|
+
if (dates.length === 1) {
|
|
423
|
+
return dates[0] as any;
|
|
424
|
+
} else {
|
|
425
|
+
return `${dates[0]}~${dates[dates.length - 1]}`;
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* 导出Excel主函数
|
|
431
|
+
*/
|
|
432
|
+
const exportExcel = async () => {
|
|
433
|
+
// 重置状态
|
|
434
|
+
exportSuccess.value = false;
|
|
435
|
+
exportError.value = false;
|
|
436
|
+
isExporting.value = true;
|
|
437
|
+
|
|
438
|
+
try {
|
|
439
|
+
// 准备导出数据
|
|
440
|
+
const exportData = complexLoanData;
|
|
441
|
+
|
|
442
|
+
// 获取日期范围
|
|
443
|
+
const dateRange = getDateRangeString(exportData);
|
|
444
|
+
|
|
445
|
+
// 构建文件名
|
|
446
|
+
const excelName = "贷款数据报表";
|
|
447
|
+
|
|
448
|
+
// 调用导出函数
|
|
449
|
+
await industryExportToExcel(exportData, excelName, dateRange);
|
|
450
|
+
|
|
451
|
+
// 导出成功
|
|
452
|
+
exportSuccess.value = true;
|
|
453
|
+
isExporting.value = false;
|
|
454
|
+
|
|
455
|
+
// 显示成功提示
|
|
456
|
+
ElMessage.success("Excel导出成功!");
|
|
457
|
+
|
|
458
|
+
// 3秒后自动清除成功提示
|
|
459
|
+
setTimeout(() => {
|
|
460
|
+
exportSuccess.value = false;
|
|
461
|
+
}, 3000);
|
|
462
|
+
} catch (error) {
|
|
463
|
+
console.error("导出失败:", error);
|
|
464
|
+
|
|
465
|
+
// 导出失败
|
|
466
|
+
exportError.value = true;
|
|
467
|
+
isExporting.value = false;
|
|
468
|
+
|
|
469
|
+
// 显示错误提示
|
|
470
|
+
ElMessage.error("Excel导出失败,请重试!");
|
|
471
|
+
|
|
472
|
+
// 3秒后自动清除错误提示
|
|
473
|
+
setTimeout(() => {
|
|
474
|
+
exportError.value = false;
|
|
475
|
+
}, 3000);
|
|
476
|
+
}
|
|
477
|
+
};
|
|
478
|
+
</script>
|
|
479
|
+
|
|
480
|
+
<style scoped>
|
|
481
|
+
.export-container {
|
|
482
|
+
padding: 20px;
|
|
483
|
+
text-align: center;
|
|
484
|
+
margin-top: 50px;
|
|
485
|
+
}
|
|
486
|
+
.el-button {
|
|
487
|
+
font-size: 16px;
|
|
488
|
+
padding: 10px 20px;
|
|
489
|
+
}
|
|
490
|
+
p {
|
|
491
|
+
margin-top: 20px;
|
|
492
|
+
font-size: 14px;
|
|
493
|
+
}
|
|
494
|
+
</style>
|