@cfmm/umi-plugins-ui-v2 0.0.25 → 0.0.27
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/dist/cjs/components/CrudTable.tpl +28 -9
- package/dist/cjs/components/DataChangeTips.less +12 -0
- package/dist/cjs/components/DataChangeTips.tpl +44 -0
- package/dist/cjs/components/GlobalHeader.tpl +5 -0
- package/dist/cjs/components/MyFooterToolbar.tpl +12 -13
- package/dist/cjs/locales/en-US.d.ts +3 -0
- package/dist/cjs/locales/enUS/DataChangeTips.d.ts +6 -0
- package/dist/cjs/locales/enUS/DataChangeTips.js +11 -0
- package/dist/cjs/locales/enUS/index.d.ts +3 -0
- package/dist/cjs/locales/enUS/index.js +2 -1
- package/dist/cjs/locales/th-TH.d.ts +3 -0
- package/dist/cjs/locales/zh-CN.d.ts +3 -0
- package/dist/cjs/locales/zh-TW.d.ts +3 -0
- package/dist/cjs/locales/zhCN/DataChangeTips.d.ts +6 -0
- package/dist/cjs/locales/zhCN/DataChangeTips.js +11 -0
- package/dist/cjs/locales/zhCN/index.d.ts +3 -0
- package/dist/cjs/locales/zhCN/index.js +2 -1
- package/dist/cjs/locales/zhTW/DataChangeTips.d.ts +6 -0
- package/dist/cjs/locales/zhTW/DataChangeTips.js +11 -0
- package/dist/cjs/locales/zhTW/index.d.ts +3 -0
- package/dist/cjs/locales/zhTW/index.js +2 -1
- package/dist/cjs/types/CrudTableTypes.d.ts +1 -1
- package/dist/cjs/types/CrudTableTypes.js +1 -1
- package/dist/cjs/utils/excelHelper.tpl +302 -24
- package/dist/cjs/writeTmpFile/writeIndex.js +2 -2
- package/dist/esm/components/CrudTable.tpl +28 -9
- package/dist/esm/components/DataChangeTips.less +12 -0
- package/dist/esm/components/DataChangeTips.tpl +44 -0
- package/dist/esm/components/GlobalHeader.tpl +5 -0
- package/dist/esm/components/MyFooterToolbar.tpl +12 -13
- package/dist/esm/locales/en-US.d.ts +3 -0
- package/dist/esm/locales/enUS/DataChangeTips.d.ts +6 -0
- package/dist/esm/locales/enUS/DataChangeTips.js +5 -0
- package/dist/esm/locales/enUS/index.d.ts +3 -0
- package/dist/esm/locales/enUS/index.js +2 -1
- package/dist/esm/locales/th-TH.d.ts +3 -0
- package/dist/esm/locales/zh-CN.d.ts +3 -0
- package/dist/esm/locales/zh-TW.d.ts +3 -0
- package/dist/esm/locales/zhCN/DataChangeTips.d.ts +6 -0
- package/dist/esm/locales/zhCN/DataChangeTips.js +5 -0
- package/dist/esm/locales/zhCN/index.d.ts +3 -0
- package/dist/esm/locales/zhCN/index.js +2 -1
- package/dist/esm/locales/zhTW/DataChangeTips.d.ts +6 -0
- package/dist/esm/locales/zhTW/DataChangeTips.js +5 -0
- package/dist/esm/locales/zhTW/index.d.ts +3 -0
- package/dist/esm/locales/zhTW/index.js +2 -1
- package/dist/esm/types/CrudTableTypes.d.ts +1 -1
- package/dist/esm/types/CrudTableTypes.js +1 -1
- package/dist/esm/utils/excelHelper.tpl +302 -24
- package/dist/esm/writeTmpFile/writeIndex.js +2 -2
- package/package.json +1 -1
|
@@ -188,6 +188,66 @@ type RowStyleType = {
|
|
|
188
188
|
bgColor?: string;
|
|
189
189
|
};
|
|
190
190
|
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* 数据区单元格样式(仅作用于「数据行」,不包含标题行、注意事项、编号行、表头行)
|
|
194
|
+
*
|
|
195
|
+
* 合并优先级(后者覆盖前者):{@link ExcelExportOptions.dataCellStyle}
|
|
196
|
+
* → {@link ExcelExportOptions.columnDataStyles}
|
|
197
|
+
* → {@link ExcelExportOptions.rowDataStyles}(仅单元格字段,不含 {@link ExcelDataRowStyle.height})
|
|
198
|
+
* → {@link ExcelExportOptions.cellDataStyles}
|
|
199
|
+
*/
|
|
200
|
+
export interface ExcelDataCellStyle {
|
|
201
|
+
/** 是否绘制四边边框,默认 true(与历史行为一致) */
|
|
202
|
+
border?: boolean;
|
|
203
|
+
/** 四边统一的边框线型,默认 thin */
|
|
204
|
+
borderStyle?: ExcelJS.BorderStyle;
|
|
205
|
+
alignment?: Partial<ExcelJS.Alignment>;
|
|
206
|
+
font?: Partial<ExcelJS.Font>;
|
|
207
|
+
fill?: ExcelJS.Fill;
|
|
208
|
+
numFmt?: string;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** 列级配置:在整列数据单元格上应用 {@link ExcelDataCellStyle},并可单独设列宽(会合并进工作表列定义) */
|
|
212
|
+
export type ExcelDataColumnStyle = Partial<ExcelDataCellStyle> & {
|
|
213
|
+
/** 列宽(Excel 字符宽度近似值),覆盖 {@link ExcelExportOptions.worksheetColumns} 中同列下标的 width */
|
|
214
|
+
width?: number;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
/** 数据行级配置:在整行数据单元格上应用 {@link ExcelDataCellStyle},并可单独设行高 */
|
|
218
|
+
export type ExcelDataRowStyle = Partial<ExcelDataCellStyle> & {
|
|
219
|
+
/** 覆盖全局 {@link ExcelExportOptions.dataRowHeight} */
|
|
220
|
+
height?: number;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* 生成 {@link ExcelExportOptions.cellDataStyles} 的键:数据行下标、列下标均为从 0 开始
|
|
225
|
+
* @example excelDataCellKey(0, 2) // 第 1 条数据第 3 列 -> '0,2'
|
|
226
|
+
*/
|
|
227
|
+
export function excelDataCellKey(dataRowIndex: number, colIndex: number): string {
|
|
228
|
+
return `${dataRowIndex},${colIndex}`;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* 单列下拉验证配置
|
|
233
|
+
*/
|
|
234
|
+
export interface ColumnValidationConfig {
|
|
235
|
+
/** 目标列索引,0-based(与 headerColumns 对齐) */
|
|
236
|
+
colIndex: number;
|
|
237
|
+
/**
|
|
238
|
+
* 下拉选项值数组。
|
|
239
|
+
* - 总字符数 ≤ 230 时走内联模式:`"v1,v2,v3"`
|
|
240
|
+
* - 超出时自动在 workbook 内创建隐藏辅助 Sheet,通过单元格引用实现长列表
|
|
241
|
+
*/
|
|
242
|
+
formulaList: string[];
|
|
243
|
+
/** 下拉为空时是否允许,默认 true */
|
|
244
|
+
allowBlank?: boolean;
|
|
245
|
+
/** 错误弹窗标题,默认"请从列表中选择" */
|
|
246
|
+
errorTitle?: string;
|
|
247
|
+
/** 错误弹窗内容,默认"该值不在允许的选项中" */
|
|
248
|
+
error?: string;
|
|
249
|
+
}
|
|
250
|
+
|
|
191
251
|
/**
|
|
192
252
|
* Excel导出统一配置选项
|
|
193
253
|
*/
|
|
@@ -214,18 +274,222 @@ export interface ExcelExportOptions {
|
|
|
214
274
|
mergeCells?: string[];
|
|
215
275
|
/** 数据行高度,默认 22 */
|
|
216
276
|
dataRowHeight?: number;
|
|
277
|
+
/**
|
|
278
|
+
* 数据行统一单元格样式(对齐、字体、填充、数字格式、边框等)。
|
|
279
|
+
* 仅作用于数据行,不包含标题/注意事项/编号行/表头。
|
|
280
|
+
*/
|
|
281
|
+
dataCellStyle?: ExcelDataCellStyle;
|
|
282
|
+
/**
|
|
283
|
+
* 数据行按「列」覆盖样式,key 为从 0 开始的列索引。
|
|
284
|
+
* 在 {@link dataCellStyle} 之上合并,优先级低于行、单元格。
|
|
285
|
+
* `width` 会写入工作表列宽(与 {@link worksheetColumns} 同列合并时,此处优先)。
|
|
286
|
+
*/
|
|
287
|
+
columnDataStyles?: Record<number, ExcelDataColumnStyle>;
|
|
288
|
+
/**
|
|
289
|
+
* 数据行按「行」覆盖样式,key 为从 0 开始的数据行索引(第 1 条数据为 0)。
|
|
290
|
+
* 可设置 {@link ExcelDataRowStyle.height} 控制该行高度;其余字段作用于该行所有数据列单元格。
|
|
291
|
+
*/
|
|
292
|
+
rowDataStyles?: Record<number, ExcelDataRowStyle>;
|
|
293
|
+
/**
|
|
294
|
+
* 数据行按「单元格」覆盖样式,key 为 `数据行索引,列索引`(均为 0 起),建议使用 {@link excelDataCellKey}。
|
|
295
|
+
* 优先级最高。
|
|
296
|
+
*/
|
|
297
|
+
cellDataStyles?: Record<string, Partial<ExcelDataCellStyle>>;
|
|
298
|
+
/**
|
|
299
|
+
* 列下拉验证配置,对数据填写行生效。
|
|
300
|
+
* 例如:[{ colIndex: 0, formulaList: ['选项A', '选项B'] }]
|
|
301
|
+
*/
|
|
302
|
+
columnValidations?: ColumnValidationConfig[];
|
|
303
|
+
/**
|
|
304
|
+
* 应用下拉验证的最大数据行数(即预留多少行可供填写),默认 500。
|
|
305
|
+
* 值越大文件越大,按实际场景调整。
|
|
306
|
+
*/
|
|
307
|
+
maxDataRows?: number;
|
|
217
308
|
}
|
|
218
309
|
|
|
219
310
|
// 兼容旧版本的类型别名
|
|
220
311
|
export type ExcelHeaderOptions = ExcelExportOptions;
|
|
221
312
|
|
|
313
|
+
const DEFAULT_DATA_ALIGNMENT: Partial<ExcelJS.Alignment> = {
|
|
314
|
+
horizontal: 'center',
|
|
315
|
+
vertical: 'middle',
|
|
316
|
+
};
|
|
317
|
+
|
|
222
318
|
/**
|
|
223
|
-
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
* @param
|
|
319
|
+
* 为指定列的数据填写行批量写入 Excel 下拉验证。
|
|
320
|
+
*
|
|
321
|
+
* 短列表(选项拼接后 ≤ 230 字符)直接写内联 formulae,超出则在 workbook 内新建
|
|
322
|
+
* 隐藏辅助 Sheet 并通过单元格范围引用,以突破 Excel 255 字符限制。
|
|
323
|
+
*
|
|
324
|
+
* @param workBook 当前 workbook(用于创建辅助 Sheet)
|
|
325
|
+
* @param workSheet 目标工作表
|
|
326
|
+
* @param validations 下拉验证配置列表
|
|
327
|
+
* @param headerRowCount 表头占用的行数(数据行从 headerRowCount+1 开始)
|
|
328
|
+
* @param maxDataRows 预留的数据填写行数
|
|
329
|
+
*/
|
|
330
|
+
const applyColumnValidations = (
|
|
331
|
+
workBook: ExcelJS.Workbook,
|
|
332
|
+
workSheet: ExcelJS.Worksheet,
|
|
333
|
+
validations: ColumnValidationConfig[],
|
|
334
|
+
headerRowCount: number,
|
|
335
|
+
maxDataRows: number,
|
|
336
|
+
) => {
|
|
337
|
+
validations.forEach((validation, idx) => {
|
|
338
|
+
const {
|
|
339
|
+
colIndex,
|
|
340
|
+
formulaList,
|
|
341
|
+
allowBlank = true,
|
|
342
|
+
errorTitle = '请从列表中选择',
|
|
343
|
+
error = '该值不在允许的选项中',
|
|
344
|
+
} = validation;
|
|
345
|
+
|
|
346
|
+
if (!formulaList.length) return;
|
|
347
|
+
|
|
348
|
+
const colLetter = convertNumberToCellName(colIndex);
|
|
349
|
+
|
|
350
|
+
// 超过 230 字符时使用隐藏辅助 Sheet 规避 Excel 内联列表长度限制
|
|
351
|
+
const inlineStr = formulaList.join(',');
|
|
352
|
+
let formulae: string[];
|
|
353
|
+
|
|
354
|
+
if (inlineStr.length <= 230) {
|
|
355
|
+
formulae = [`"${inlineStr}"`];
|
|
356
|
+
} else {
|
|
357
|
+
// 辅助 Sheet 名称唯一化,避免多列验证时冲突
|
|
358
|
+
const helperSheetName = `_VL_${idx}_${colIndex}`;
|
|
359
|
+
const helperSheet = workBook.addWorksheet(helperSheetName);
|
|
360
|
+
formulaList.forEach((val, i) => {
|
|
361
|
+
helperSheet.getCell(`A${i + 1}`).value = val;
|
|
362
|
+
});
|
|
363
|
+
// 隐藏辅助 Sheet,不暴露给用户
|
|
364
|
+
helperSheet.state = 'hidden';
|
|
365
|
+
formulae = [`'${helperSheetName}'!$A$1:$A$${formulaList.length}`];
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// 对数据填写区每行写入验证,仅预留 maxDataRows 行
|
|
369
|
+
const startRow = headerRowCount + 1;
|
|
370
|
+
const endRow = startRow + maxDataRows - 1;
|
|
371
|
+
for (let row = startRow; row <= endRow; row++) {
|
|
372
|
+
workSheet.getCell(`${colLetter}${row}`).dataValidation = {
|
|
373
|
+
type: 'list',
|
|
374
|
+
allowBlank,
|
|
375
|
+
formulae,
|
|
376
|
+
showErrorMessage: true,
|
|
377
|
+
errorStyle: 'stop',
|
|
378
|
+
errorTitle,
|
|
379
|
+
error,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
};
|
|
384
|
+
|
|
385
|
+
function buildDataCellBorder(style: ExcelJS.BorderStyle): ExcelJS.Borders {
|
|
386
|
+
const side = { style } as ExcelJS.Border;
|
|
387
|
+
return {
|
|
388
|
+
top: side,
|
|
389
|
+
left: side,
|
|
390
|
+
bottom: side,
|
|
391
|
+
right: side,
|
|
392
|
+
} as ExcelJS.Borders;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* 对「数据区」的单个单元格写入显示样式(边框、对齐、字体、填充、数字格式)。
|
|
397
|
+
*
|
|
398
|
+
* 【作用范围】仅应在 {@link genExcelAdvanced} 写入每条数据行时调用;标题行、注意事项、编号行、
|
|
399
|
+
* 表头行由 `genExcelAdvanced` 单独写样式,不走本函数。
|
|
400
|
+
*
|
|
401
|
+
* 【样式来源与优先级】自低至高:`dataCellStyle`(全局默认)→ `columnDataStyles` → `rowDataStyles`
|
|
402
|
+
* → `cellDataStyles`;同一属性后者覆盖前者。`columnDataStyles` 中的 `width` 不在此处理,由工作表列定义合并。
|
|
403
|
+
*
|
|
404
|
+
* @param cell ExcelJS 单元格实例
|
|
405
|
+
* @param dataRowIndex 数据行在业务数据中的下标(第 1 条为 0),非工作表物理行号
|
|
406
|
+
* @param colIndex 列下标(第 1 列为 0)
|
|
407
|
+
* @param options 导出选项
|
|
408
|
+
*/
|
|
409
|
+
function applyDataCellAppearance(
|
|
410
|
+
cell: ExcelJS.Cell,
|
|
411
|
+
dataRowIndex: number,
|
|
412
|
+
colIndex: number,
|
|
413
|
+
options?: ExcelExportOptions,
|
|
414
|
+
): void {
|
|
415
|
+
// 取出四层覆盖:全局列、行、单元格(键为 "行,列")
|
|
416
|
+
const unified = options?.dataCellStyle;
|
|
417
|
+
const colOv = options?.columnDataStyles?.[colIndex];
|
|
418
|
+
const rowOv = options?.rowDataStyles?.[dataRowIndex];
|
|
419
|
+
const cellOv = options?.cellDataStyles?.[excelDataCellKey(dataRowIndex, colIndex)];
|
|
420
|
+
|
|
421
|
+
// 是否画四边线及线型(自最细粒度向全局回落,缺省为画 thin 边框)
|
|
422
|
+
const drawBorder =
|
|
423
|
+
cellOv?.border ?? rowOv?.border ?? colOv?.border ?? unified?.border ?? true;
|
|
424
|
+
|
|
425
|
+
const borderStyle =
|
|
426
|
+
cellOv?.borderStyle ??
|
|
427
|
+
rowOv?.borderStyle ??
|
|
428
|
+
colOv?.borderStyle ??
|
|
429
|
+
unified?.borderStyle ??
|
|
430
|
+
'thin';
|
|
431
|
+
|
|
432
|
+
if (drawBorder) {
|
|
433
|
+
cell.border = buildDataCellBorder(borderStyle);
|
|
434
|
+
} else {
|
|
435
|
+
delete (cell as { border?: ExcelJS.Borders }).border;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// 对齐:先默认居中,再逐层叠加深覆盖
|
|
439
|
+
cell.alignment = {
|
|
440
|
+
...DEFAULT_DATA_ALIGNMENT,
|
|
441
|
+
...(unified?.alignment ?? {}),
|
|
442
|
+
...(colOv?.alignment ?? {}),
|
|
443
|
+
...(rowOv?.alignment ?? {}),
|
|
444
|
+
...(cellOv?.alignment ?? {}),
|
|
445
|
+
};
|
|
446
|
+
|
|
447
|
+
// 字体:浅合并四层;有任一字段时再赋值,避免清空 Excel 默认字体
|
|
448
|
+
const mergedFont = {
|
|
449
|
+
...(unified?.font ?? {}),
|
|
450
|
+
...(colOv?.font ?? {}),
|
|
451
|
+
...(rowOv?.font ?? {}),
|
|
452
|
+
...(cellOv?.font ?? {}),
|
|
453
|
+
};
|
|
454
|
+
if (Object.keys(mergedFont).length > 0) {
|
|
455
|
+
cell.font = { ...cell.font, ...mergedFont };
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// 填充:取最先命中的高优先级非空 fill
|
|
459
|
+
const fill = cellOv?.fill ?? rowOv?.fill ?? colOv?.fill ?? unified?.fill;
|
|
460
|
+
if (fill) {
|
|
461
|
+
cell.fill = fill;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// 数字/文本格式(如 '0.00'、'@')
|
|
465
|
+
const numFmt = cellOv?.numFmt ?? rowOv?.numFmt ?? colOv?.numFmt ?? unified?.numFmt;
|
|
466
|
+
if (numFmt !== undefined && numFmt !== '') {
|
|
467
|
+
cell.numFmt = numFmt;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* 通用 Excel 导出:用 ExcelJS 构建工作簿,按固定顺序拼装版式后写出 xlsx 并触发浏览器下载。
|
|
473
|
+
*
|
|
474
|
+
* 【整体流程概要】
|
|
475
|
+
* 1. 创建工作簿与工作表,根据表头确定列数;
|
|
476
|
+
* 2. 合并列宽:`worksheetColumns` 与 `columnDataStyles[].width` 按列下标合并;
|
|
477
|
+
* 3. 自上而下追加可选区块:标题行 → 注意事项 → 隐藏编号行 → 单级或多级表头;
|
|
478
|
+
* 4. 按需执行 `mergeCells`(A1 记法,对应此时工作表中的行号);
|
|
479
|
+
* 5. 拉取 `data`(同步数组或异步函数),逐行 `addRow`,对数据区内每个单元格调用
|
|
480
|
+
* {@link applyDataCellAppearance},并按 `rowDataStyles` / `dataRowHeight` 设行高;
|
|
481
|
+
* 6. 若存在表头锁定或锁定列则 `workSheet.protect`;
|
|
482
|
+
* 7. `writeBuffer` + {@link fileDownloadFromBlob}。
|
|
483
|
+
*
|
|
484
|
+
* 【与样式相关的约定】
|
|
485
|
+
* - 标题、注意事项、表头等使用 `options` 中专有字段写死样式,**不参与** `dataCellStyle` 等数据区配置;
|
|
486
|
+
* - 数据行下标 `dataRowIndex` 从 0 起,与 Excel 中「第几行」无关(前面区块会占掉若干行)。
|
|
487
|
+
*
|
|
488
|
+
* @param fileName 下载文件名(含扩展名,如 `.xlsx`)
|
|
489
|
+
* @param workSheetName 工作表名称
|
|
490
|
+
* @param headerColumns 表头:一维为单级表头,二维为多级表头(末行决定列数)
|
|
491
|
+
* @param data 数据行二维数组,或返回该数组的同步/异步函数(便于分页拉取)
|
|
492
|
+
* @param options 标题、表头区样式、列宽、数据区样式、合并、保护密码等
|
|
229
493
|
*/
|
|
230
494
|
export const genExcelAdvanced = async (
|
|
231
495
|
fileName: string,
|
|
@@ -234,12 +498,13 @@ export const genExcelAdvanced = async (
|
|
|
234
498
|
data: any[] | (() => Promise<any[]>) | (() => any[]),
|
|
235
499
|
options?: ExcelExportOptions,
|
|
236
500
|
): Promise<void> => {
|
|
237
|
-
//
|
|
501
|
+
// 缺少文件名、表名或表头时无法建表,直接返回
|
|
238
502
|
if (!fileName || !workSheetName || !headerColumns.length) {
|
|
239
503
|
console.error('genExcelAdvanced: 缺少必要参数');
|
|
240
504
|
return;
|
|
241
505
|
}
|
|
242
506
|
|
|
507
|
+
// 新建工作簿并打时间戳元数据(部分客户端会显示/使用)
|
|
243
508
|
const workBook = new ExcelJS.Workbook();
|
|
244
509
|
workBook.created = new Date();
|
|
245
510
|
workBook.modified = new Date();
|
|
@@ -257,11 +522,23 @@ export const genExcelAdvanced = async (
|
|
|
257
522
|
: (headerColumns as string[]);
|
|
258
523
|
const colCount = lastHeaderRow.length;
|
|
259
524
|
|
|
260
|
-
//
|
|
261
|
-
|
|
525
|
+
// 列宽:worksheetColumns 为基底,columnDataStyles[colIndex].width 逐项覆盖(仅列级属性,不在单元格里设置)
|
|
526
|
+
const defaultColWidth = 20;
|
|
527
|
+
const wsCols = options?.worksheetColumns;
|
|
528
|
+
const mergedColumns: NonNullable<Worksheet['columns']> = [];
|
|
529
|
+
for (let c = 0; c < colCount; c++) {
|
|
530
|
+
const fromWs = wsCols?.[c] as NonNullable<Worksheet['columns']>[number] | undefined;
|
|
531
|
+
const widthFromStyle = options?.columnDataStyles?.[c]?.width;
|
|
532
|
+
mergedColumns.push({
|
|
533
|
+
...fromWs,
|
|
534
|
+
width: widthFromStyle ?? fromWs?.width ?? defaultColWidth,
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
workSheet.columns = mergedColumns;
|
|
262
538
|
|
|
263
539
|
// 是否锁定基础行(默认为 true)
|
|
264
540
|
const lockHeaderRows = options?.lockHeaderRows !== false;
|
|
541
|
+
// 物理行号:追加行时递增,用于 mergeCells 与「第几行」对应
|
|
265
542
|
let currentRowIndex = 0;
|
|
266
543
|
|
|
267
544
|
// ========== 第一行:标题(可选) ==========
|
|
@@ -413,36 +690,37 @@ export const genExcelAdvanced = async (
|
|
|
413
690
|
});
|
|
414
691
|
}
|
|
415
692
|
|
|
416
|
-
// ==========
|
|
693
|
+
// ========== 锁定列:仅作用于数据行单元格的 protection,需与 workSheet.protect 配合 ==========
|
|
417
694
|
const lockedColumns = options?.lockedColumns ?? [];
|
|
418
695
|
const hasLockedColumns = lockedColumns.length > 0;
|
|
419
696
|
|
|
420
|
-
// ==========
|
|
697
|
+
// ========== 数据:支持传入数组或异步工厂(如大数据分批 resolve) ==========
|
|
421
698
|
const rows = typeof data === 'function' ? await data() : data;
|
|
422
699
|
|
|
423
|
-
// ==========
|
|
700
|
+
// ========== 数据行:每格套用 applyDataCellAppearance;行高来自 rowDataStyles 或全局 dataRowHeight ==========
|
|
424
701
|
if (rows?.length > 0) {
|
|
425
|
-
rows.forEach((row) => {
|
|
702
|
+
rows.forEach((row, dataRowIndex) => {
|
|
426
703
|
const dataRow = workSheet.addRow(row);
|
|
704
|
+
const rowStyle = options?.rowDataStyles?.[dataRowIndex];
|
|
427
705
|
dataRow.eachCell({ includeEmpty: true }, (cell, colNumber) => {
|
|
428
706
|
if (colNumber <= colCount) {
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
left: { style: 'thin' },
|
|
432
|
-
bottom: { style: 'thin' },
|
|
433
|
-
right: { style: 'thin' },
|
|
434
|
-
};
|
|
435
|
-
cell.alignment = { horizontal: 'center', vertical: 'middle' };
|
|
707
|
+
const colIndex = colNumber - 1;
|
|
708
|
+
applyDataCellAppearance(cell, dataRowIndex, colIndex, options);
|
|
436
709
|
if (hasLockedColumns) {
|
|
437
|
-
cell.protection = { locked: lockedColumns.includes(
|
|
710
|
+
cell.protection = { locked: lockedColumns.includes(colIndex) };
|
|
438
711
|
}
|
|
439
712
|
}
|
|
440
713
|
});
|
|
441
|
-
dataRow.height = options?.dataRowHeight ?? 22;
|
|
714
|
+
dataRow.height = rowStyle?.height ?? options?.dataRowHeight ?? 22;
|
|
442
715
|
});
|
|
443
716
|
}
|
|
444
717
|
|
|
445
|
-
// ==========
|
|
718
|
+
// ========== 列下拉验证 ==========
|
|
719
|
+
if (options?.columnValidations?.length) {
|
|
720
|
+
applyColumnValidations(workBook, workSheet, options.columnValidations, currentRowIndex, options.maxDataRows ?? 500);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
// ========== 工作表保护:锁定表头区或部分列时启用(密码可选) ==========
|
|
446
724
|
if (lockHeaderRows || hasLockedColumns) {
|
|
447
725
|
workSheet.protect(options?.sheetPassword ?? '', {
|
|
448
726
|
selectLockedCells: true,
|
|
@@ -454,7 +732,7 @@ export const genExcelAdvanced = async (
|
|
|
454
732
|
});
|
|
455
733
|
}
|
|
456
734
|
|
|
457
|
-
// ==========
|
|
735
|
+
// ========== 序列化为 xlsx 二进制并触发本地下载 ==========
|
|
458
736
|
try {
|
|
459
737
|
const buffer = await workBook.xlsx.writeBuffer();
|
|
460
738
|
fileDownloadFromBlob(fileName, buffer as unknown as Blob);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export default {
|
|
2
|
-
path:
|
|
3
|
-
content: "\n // \u5BFC\u5165\u7EC4\u4EF6\n import QrCodeModal from \"./components/QrCodeModal\";\n import CreateForm from \"./components/AddDrawerForm\";\n import MyFooterToolbar from \"./components/MyFooterToolbar\";\n import DropdownButton from \"./components/DropdownButton\";\n import DynamicIcon, { getAntdIconList } from \"./components/DynamicIcon\";\n import DynamicIconModal from \"./components/DynamicIconModal\";\n import HighlightStr from \"./components/HighlightStr\";\n import EditMultiLangForm from \"./components/EditMultiLangForm\";\n import MyColorPicker from \"./components/MyColorPicker\";\n import MySelect from \"./components/MySelect\";\n import MySelectLang from \"./components/MySelectLang\";\n import PermissionSelect from \"./components/PermissionSelect\";\n import DataPermissionSelect from \"./components/DataPermissionSelect\";\n import UTCDatePicker from \"./components/UTCDatePicker\";\n import ProFormUTCDatePicker from \"./components/ProFormUTCDatePicker\";\n import UTCRangePicker from \"./components/UTCRangePicker\";\n import ProFormUTCRangePicker from \"./components/ProFormUTCRangePicker\";\n import RandomAvatar from \"./components/RandomAvatar\";\n import RefDrawerForm from \"./components/RefDrawerForm\";\n import UpdateForm from \"./components/UpdateForm\";\n import ViewTableItemDrawer from \"./components/ViewTableItemDrawer\";\n import WangEditor from \"./components/WangEditor\";\n import WangEditorView from \"./components/WangEditorView\";\n import MyUpload from \"./components/MyUpload\";\n import CopyButton from \"./components/CopyButton\";\n import ImportExecl from \"./components/ImportExecl\";\n import MyPageContainer from \"./components/MyPageContainer\";\n import MyReactEcharts from \"./components/MyReactEcharts\";\n import MyTagList from \"./components/MyTagList\";\n import VolumeFormItem from \"./components/VolumeFormItem\";\n import ReportTable from \"./components/ReportTable\";\n import DicDropDownList from \"./components/DicDropDownList\";\n import ActionLogDrawer from \"./components/ActionLogDrawer\";\n import DndTabs from \"./components/DndTabs\";\n import DndTag from \"./components/DndTag\";\n import TimeTypeSelect from \"./components/TimeTypeSelect\";\n import ImportDataUpload from \"./components/ImportDataUpload\";\n import PDFWrapper from \"./components/PDFWrapper\";\n import ExportPageWrapper from \"./components/ExportPageWrapper\";\n import { PageExporter } from \"./utils/exportPage\";\n import MySetps from \"./components/MySetps\";\n import CrudTable from \"./components/CrudTable\";\n\n import MenuFooter from \"./components/MenuFooter\";\n import GlobalHeader from \"./components/GlobalHeader\";\n import GlobalFooter from \"./components/GlobalFooter\";\n import AvatarDropdown from \"./components/AvatarDropdown\";\n import HeaderSearch from \"./components/HeaderSearch\";\n import ThemeSwitch from \"./components/ThemeSwitch\";\n import KeepAliveTabs from \"./components/KeepAliveTabs\";\n import KeepAliveDndTabs from \"./components/KeepAliveDndTabs\";\n\n import Authorized from \"./components/Authorized\";\n import AuthorizedRoute from \"./components/AuthorizedRoute\";\n import AuthorizeRender from \"./components/AuthorizeRender\";\n import CheckPermissions from \"./components/CheckPermissions\";\n import PromiseRender from \"./components/PromiseRender\";\n import Secured from \"./components/Secured\";\n import renderAuthorize from \"./components/renderAuthorize\";\n import { getAuthorityFunction } from \"./utils/authorityFunction\";\n\n import LoadingSvg from \"./components/LoadingSvg\";\n import PageLoading from \"./components/PageLoading\";\n import NoFoundPage from \"./components/NoFoundPage\";\n import UserDisable from \"./components/UserDisable\";\n import UserNoPermission from \"./components/UserNoPermission\";\n import UserNoPagePermission from \"./components/UserNoPagePermission\";\n\n import useAction from \"./hooks/useAction\";\n import useFormatLocale from \"./hooks/useFormatLocale\";\n import useActionLocales from \"./hooks/useActionLocales\";\n import useQueryTableList from \"./hooks/useQueryTableList\";\n import useAuthority from \"./hooks/useAuthority\";\n import useColumnTitle, { useBatchColumnTitles } from \"./hooks/useColumnTitle\";\n import useMemoizedFn from \"./hooks/useMemoizedFn\";\n import { useKeepAliveTabs } from \"./hooks/useKeepAliveTabs\";\n import { usePageExport } from \"./hooks/usePageExport\";\n import { useRouteAuth } from \"./hooks/useRouteAuth\";\n import { useFetchList } from \"./hooks/useFetchList\";\n\n // \u5BFC\u51FAhooks\n export {\n useAction,\n useFormatLocale,\n useActionLocales,\n useQueryTableList,\n useAuthority,\n useColumnTitle,\n useBatchColumnTitles,\n useMemoizedFn,\n useKeepAliveTabs,\n usePageExport,\n useRouteAuth,\n useFetchList,\n }\n\n // \u5BFC\u51FA\u7EC4\u4EF6\n export { \n QrCodeModal, \n CreateForm, \n MyFooterToolbar,\n DropdownButton,\n DynamicIcon,\n DynamicIconModal,\n HighlightStr,\n getAntdIconList,\n EditMultiLangForm,\n MyColorPicker,\n MySelect,\n MySelectLang,\n PermissionSelect,\n DataPermissionSelect,\n UTCDatePicker,\n ProFormUTCDatePicker,\n UTCRangePicker,\n ProFormUTCRangePicker,\n RandomAvatar,\n RefDrawerForm,\n UpdateForm,\n ViewTableItemDrawer,\n WangEditor,\n WangEditorView,\n MyUpload,\n CopyButton,\n ImportExecl,\n MyPageContainer,\n MyReactEcharts,\n MyTagList,\n VolumeFormItem,\n ReportTable,\n DicDropDownList,\n ActionLogDrawer,\n DndTabs,\n DndTag,\n TimeTypeSelect,\n ImportDataUpload,\n PDFWrapper,\n ExportPageWrapper,\n PageExporter,\n MySetps,\n CrudTable,\n\n MenuFooter,\n GlobalHeader,\n GlobalFooter,\n AvatarDropdown,\n HeaderSearch,\n ThemeSwitch,\n KeepAliveTabs,\n KeepAliveDndTabs,\n \n Authorized,\n AuthorizedRoute,\n AuthorizeRender,\n CheckPermissions,\n PromiseRender,\n Secured,\n renderAuthorize,\n getAuthorityFunction,\n\n PageLoading,\n LoadingSvg,\n NoFoundPage,\n UserDisable,\n UserNoPermission,\n UserNoPagePermission,\n };\n "
|
|
2
|
+
path: 'index.tsx',
|
|
3
|
+
content: "\n // \u5BFC\u5165\u7EC4\u4EF6\n import QrCodeModal from \"./components/QrCodeModal\";\n import CreateForm from \"./components/AddDrawerForm\";\n import MyFooterToolbar from \"./components/MyFooterToolbar\";\n import DropdownButton from \"./components/DropdownButton\";\n import DynamicIcon, { getAntdIconList } from \"./components/DynamicIcon\";\n import DynamicIconModal from \"./components/DynamicIconModal\";\n import HighlightStr from \"./components/HighlightStr\";\n import EditMultiLangForm from \"./components/EditMultiLangForm\";\n import MyColorPicker from \"./components/MyColorPicker\";\n import MySelect from \"./components/MySelect\";\n import MySelectLang from \"./components/MySelectLang\";\n import PermissionSelect from \"./components/PermissionSelect\";\n import DataPermissionSelect from \"./components/DataPermissionSelect\";\n import UTCDatePicker from \"./components/UTCDatePicker\";\n import ProFormUTCDatePicker from \"./components/ProFormUTCDatePicker\";\n import UTCRangePicker from \"./components/UTCRangePicker\";\n import ProFormUTCRangePicker from \"./components/ProFormUTCRangePicker\";\n import RandomAvatar from \"./components/RandomAvatar\";\n import RefDrawerForm from \"./components/RefDrawerForm\";\n import UpdateForm from \"./components/UpdateForm\";\n import ViewTableItemDrawer from \"./components/ViewTableItemDrawer\";\n import WangEditor from \"./components/WangEditor\";\n import WangEditorView from \"./components/WangEditorView\";\n import MyUpload from \"./components/MyUpload\";\n import CopyButton from \"./components/CopyButton\";\n import ImportExecl from \"./components/ImportExecl\";\n import MyPageContainer from \"./components/MyPageContainer\";\n import MyReactEcharts from \"./components/MyReactEcharts\";\n import MyTagList from \"./components/MyTagList\";\n import VolumeFormItem from \"./components/VolumeFormItem\";\n import ReportTable from \"./components/ReportTable\";\n import DicDropDownList from \"./components/DicDropDownList\";\n import ActionLogDrawer from \"./components/ActionLogDrawer\";\n import DndTabs from \"./components/DndTabs\";\n import DndTag from \"./components/DndTag\";\n import TimeTypeSelect from \"./components/TimeTypeSelect\";\n import ImportDataUpload from \"./components/ImportDataUpload\";\n import PDFWrapper from \"./components/PDFWrapper\";\n import ExportPageWrapper from \"./components/ExportPageWrapper\";\n import { PageExporter } from \"./utils/exportPage\";\n import MySetps from \"./components/MySetps\";\n import CrudTable from \"./components/CrudTable\";\n import DataChangeTips from \"./components/DataChangeTips\";\n\n import MenuFooter from \"./components/MenuFooter\";\n import GlobalHeader from \"./components/GlobalHeader\";\n import GlobalFooter from \"./components/GlobalFooter\";\n import AvatarDropdown from \"./components/AvatarDropdown\";\n import HeaderSearch from \"./components/HeaderSearch\";\n import ThemeSwitch from \"./components/ThemeSwitch\";\n import KeepAliveTabs from \"./components/KeepAliveTabs\";\n import KeepAliveDndTabs from \"./components/KeepAliveDndTabs\";\n\n import Authorized from \"./components/Authorized\";\n import AuthorizedRoute from \"./components/AuthorizedRoute\";\n import AuthorizeRender from \"./components/AuthorizeRender\";\n import CheckPermissions from \"./components/CheckPermissions\";\n import PromiseRender from \"./components/PromiseRender\";\n import Secured from \"./components/Secured\";\n import renderAuthorize from \"./components/renderAuthorize\";\n import { getAuthorityFunction } from \"./utils/authorityFunction\";\n\n import LoadingSvg from \"./components/LoadingSvg\";\n import PageLoading from \"./components/PageLoading\";\n import NoFoundPage from \"./components/NoFoundPage\";\n import UserDisable from \"./components/UserDisable\";\n import UserNoPermission from \"./components/UserNoPermission\";\n import UserNoPagePermission from \"./components/UserNoPagePermission\";\n\n import useAction from \"./hooks/useAction\";\n import useFormatLocale from \"./hooks/useFormatLocale\";\n import useActionLocales from \"./hooks/useActionLocales\";\n import useQueryTableList from \"./hooks/useQueryTableList\";\n import useAuthority from \"./hooks/useAuthority\";\n import useColumnTitle, { useBatchColumnTitles } from \"./hooks/useColumnTitle\";\n import useMemoizedFn from \"./hooks/useMemoizedFn\";\n import { useKeepAliveTabs } from \"./hooks/useKeepAliveTabs\";\n import { usePageExport } from \"./hooks/usePageExport\";\n import { useRouteAuth } from \"./hooks/useRouteAuth\";\n import { useFetchList } from \"./hooks/useFetchList\";\n\n // \u5BFC\u51FAhooks\n export {\n useAction,\n useFormatLocale,\n useActionLocales,\n useQueryTableList,\n useAuthority,\n useColumnTitle,\n useBatchColumnTitles,\n useMemoizedFn,\n useKeepAliveTabs,\n usePageExport,\n useRouteAuth,\n useFetchList,\n }\n\n // \u5BFC\u51FA\u7EC4\u4EF6\n export { \n QrCodeModal, \n CreateForm, \n MyFooterToolbar,\n DropdownButton,\n DynamicIcon,\n DynamicIconModal,\n HighlightStr,\n getAntdIconList,\n EditMultiLangForm,\n MyColorPicker,\n MySelect,\n MySelectLang,\n PermissionSelect,\n DataPermissionSelect,\n UTCDatePicker,\n ProFormUTCDatePicker,\n UTCRangePicker,\n ProFormUTCRangePicker,\n RandomAvatar,\n RefDrawerForm,\n UpdateForm,\n ViewTableItemDrawer,\n WangEditor,\n WangEditorView,\n MyUpload,\n CopyButton,\n ImportExecl,\n MyPageContainer,\n MyReactEcharts,\n MyTagList,\n VolumeFormItem,\n ReportTable,\n DicDropDownList,\n ActionLogDrawer,\n DndTabs,\n DndTag,\n TimeTypeSelect,\n ImportDataUpload,\n PDFWrapper,\n ExportPageWrapper,\n PageExporter,\n MySetps,\n CrudTable,\n DataChangeTips,\n\n MenuFooter,\n GlobalHeader,\n GlobalFooter,\n AvatarDropdown,\n HeaderSearch,\n ThemeSwitch,\n KeepAliveTabs,\n KeepAliveDndTabs,\n \n Authorized,\n AuthorizedRoute,\n AuthorizeRender,\n CheckPermissions,\n PromiseRender,\n Secured,\n renderAuthorize,\n getAuthorityFunction,\n\n PageLoading,\n LoadingSvg,\n NoFoundPage,\n UserDisable,\n UserNoPermission,\n UserNoPagePermission,\n };\n "
|
|
4
4
|
};
|