@canvas-components/react-list-table 0.3.42 → 0.3.44

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/index.cjs CHANGED
@@ -3,6 +3,7 @@
3
3
  var react = require('react');
4
4
  var reactDom = require('react-dom');
5
5
  var reactComponents = require('@canvas-components/react-components');
6
+ var print = require('@canvas-components/print');
6
7
  var listTable = require('@canvas-components/list-table');
7
8
  var jsxRuntime = require('react/jsx-runtime');
8
9
  var chart = require('@canvas-components/chart');
@@ -1049,6 +1050,30 @@ function ReactTableContextMenuView(props) {
1049
1050
  }
1050
1051
  ),
1051
1052
  /* @__PURE__ */ jsxRuntime.jsx(MenuAction, { label: "\u67E5\u627E", onClick: request.onOpenSearch }),
1053
+ /* @__PURE__ */ jsxRuntime.jsx(
1054
+ MenuSubmenu,
1055
+ {
1056
+ label: "\u6253\u5370",
1057
+ items: [
1058
+ {
1059
+ key: "print-direct",
1060
+ label: "\u76F4\u63A5\u6253\u5370",
1061
+ onClick: request.onGetPrintData ? () => {
1062
+ setMenuOpen(false);
1063
+ props.onDirectPrint?.();
1064
+ } : void 0
1065
+ },
1066
+ {
1067
+ key: "print-configure",
1068
+ label: "\u6253\u5370\u914D\u7F6E",
1069
+ onClick: request.onGetPrintData ? () => {
1070
+ setMenuOpen(false);
1071
+ props.onPrint?.();
1072
+ } : void 0
1073
+ }
1074
+ ]
1075
+ }
1076
+ ),
1052
1077
  /* @__PURE__ */ jsxRuntime.jsx(
1053
1078
  MenuAction,
1054
1079
  {
@@ -3947,6 +3972,1582 @@ function fitExportDialogColumns(columns, availableWidth) {
3947
3972
  return fit(columns);
3948
3973
  }
3949
3974
 
3975
+ // src/features/print/print-settings.ts
3976
+ function createPrintColumns(columns, summaryColumns = []) {
3977
+ const choices = new Map(summaryColumns.map((column) => [column.key, column]));
3978
+ return columns.map((column) => {
3979
+ const choice = choices.get(column.key);
3980
+ return {
3981
+ ...column,
3982
+ align: column.align ?? "left",
3983
+ overflow: column.overflow ?? "wrap",
3984
+ summaryType: choice?.summary.type ?? "none",
3985
+ showTypePrefix: choice?.summary.showTypePrefix ? "yes" : "no",
3986
+ precision: choice?.summary.precision,
3987
+ roundingMode: choice?.summary.roundingMode ?? "round",
3988
+ preserveTrailingZeros: choice?.summary.preserveTrailingZeros ? "yes" : "no",
3989
+ summaryTitle: choice?.summaryTitle
3990
+ };
3991
+ });
3992
+ }
3993
+ function readPrintSettings(storageKey) {
3994
+ if (!storageKey) return null;
3995
+ try {
3996
+ const value = JSON.parse(
3997
+ localStorage.getItem(`canvas-table-print:${storageKey}`) ?? "null"
3998
+ );
3999
+ if (!value || typeof value !== "object") return null;
4000
+ const settings = value;
4001
+ if (settings.version !== 2 || settings.presetName !== void 0 && typeof settings.presetName !== "string" || !Array.isArray(settings.columns) || !settings.columns.every(
4002
+ (column) => column && typeof column.key === "string" && Number.isFinite(column.width) && column.width >= 10
4003
+ ) || !Array.isArray(settings.selectedKeys) || !settings.selectedKeys.every((key) => typeof key === "string") || !Number.isInteger(settings.rowsPerPage) || settings.rowsPerPage < 1)
4004
+ return null;
4005
+ return settings;
4006
+ } catch {
4007
+ return null;
4008
+ }
4009
+ }
4010
+ function writePrintSettings(storageKey, settings) {
4011
+ if (!storageKey) return;
4012
+ try {
4013
+ const key = `canvas-table-print:${storageKey}`;
4014
+ if (settings) localStorage.setItem(key, JSON.stringify(settings));
4015
+ else localStorage.removeItem(key);
4016
+ } catch {
4017
+ }
4018
+ }
4019
+ function restorePrintColumns(columns, settings) {
4020
+ const current = new Map(columns.map((column) => [column.key, column]));
4021
+ const restored = [];
4022
+ settings?.columns?.forEach((saved) => {
4023
+ const column = current.get(saved.key);
4024
+ if (!column) return;
4025
+ restored.push({ ...column, ...saved, title: column.title });
4026
+ current.delete(saved.key);
4027
+ });
4028
+ return [...restored, ...current.values()];
4029
+ }
4030
+ function resolvePrintSelectedKeys(sourceColumns, presetConfig, cached) {
4031
+ const cachedColumnKeys = new Set(cached?.columns.map((column) => column.key));
4032
+ const presetKeys = presetConfig?.selectedKeys ? new Set(presetConfig.selectedKeys) : null;
4033
+ return sourceColumns.filter((column) => {
4034
+ if (cached) {
4035
+ return cachedColumnKeys.has(column.key) ? cached.selectedKeys.includes(column.key) : true;
4036
+ }
4037
+ if (presetKeys) return presetKeys.has(column.key);
4038
+ return true;
4039
+ }).map((column) => column.key);
4040
+ }
4041
+ function createCachedPrintTableOptions(source, storageKey, printPresets = []) {
4042
+ const cached = readPrintSettings(storageKey);
4043
+ const selectedPreset = cached?.presetName ? printPresets.find((preset) => preset.name === cached.presetName) : cached ? void 0 : printPresets[0];
4044
+ const config = selectedPreset?.config;
4045
+ const settings = { ...config, ...cached };
4046
+ const columns = restorePrintColumns(
4047
+ restorePrintColumns(
4048
+ createPrintColumns(source.columns, source.summaryColumns),
4049
+ config?.columns ? { columns: config.columns } : null
4050
+ ),
4051
+ cached
4052
+ );
4053
+ const selectedKeys = resolvePrintSelectedKeys(source.columns, config, cached);
4054
+ return configurePrintTable(
4055
+ source,
4056
+ columns,
4057
+ selectedKeys,
4058
+ settings.rowsPerPage ?? 30,
4059
+ {
4060
+ includeSummary: settings.includeSummary ?? Boolean(
4061
+ source.summaryRow || source.summaryColumns?.some(
4062
+ (column) => column.summary.type !== "none"
4063
+ )
4064
+ ),
4065
+ rowHeight: settings.rowHeight ?? 8,
4066
+ title: settings.title ?? "\u8868\u683C\u6253\u5370",
4067
+ subtitle: settings.subtitle ?? "",
4068
+ titleFontSize: settings.titleFontSize ?? 18,
4069
+ subtitleFontSize: settings.subtitleFontSize ?? 12,
4070
+ summaryPosition: settings.summaryPosition ?? "last-page",
4071
+ showPageNumbers: settings.showPageNumbers ?? false,
4072
+ pageNumberPosition: settings.pageNumberPosition ?? "right",
4073
+ showPrintTime: settings.showPrintTime ?? false,
4074
+ printTimePosition: settings.printTimePosition ?? "left",
4075
+ pageMargins: settings.pageMargins ?? {
4076
+ top: 12,
4077
+ right: 12,
4078
+ bottom: 12,
4079
+ left: 12
4080
+ },
4081
+ paperSize: settings.paperSize ?? "a4",
4082
+ orientation: settings.orientation ?? "portrait",
4083
+ useCellBorders: settings.useCellBorders ?? true,
4084
+ borderColor: settings.borderColor ?? "#000000",
4085
+ textColor: settings.textColor ?? "#000000",
4086
+ headerBackgroundColor: settings.headerBackgroundColor ?? "#f2f5f8",
4087
+ summaryBackgroundColor: settings.summaryBackgroundColor ?? "#f2f5f8"
4088
+ }
4089
+ );
4090
+ }
4091
+ async function configurePrintTable(source, columns, selectedKeys, rowsPerPage, settings = {}) {
4092
+ const selected = new Set(selectedKeys);
4093
+ const activeColumns = columns.filter((column) => selected.has(column.key));
4094
+ const sourceIndexes = new Map(
4095
+ source.columns.map((column, index) => [column.key, index])
4096
+ );
4097
+ const summaries = Object.fromEntries(
4098
+ activeColumns.map((column) => [
4099
+ column.key,
4100
+ {
4101
+ type: column.summaryType ?? "none",
4102
+ showTypePrefix: column.showTypePrefix === "yes",
4103
+ precision: column.precision,
4104
+ roundingMode: column.roundingMode ?? "round",
4105
+ preserveTrailingZeros: column.preserveTrailingZeros === "yes"
4106
+ }
4107
+ ])
4108
+ );
4109
+ const summaryRow = settings.includeSummary ? source.getSummaryRow ? await source.getSummaryRow({
4110
+ columnKeys: activeColumns.map((column) => column.key),
4111
+ sortState: [],
4112
+ summaries,
4113
+ includeSummary: true
4114
+ }) : source.summaryRow ? activeColumns.map(
4115
+ (column) => source.summaryRow?.[sourceIndexes.get(column.key) ?? -1] ?? ""
4116
+ ) : void 0 : void 0;
4117
+ return {
4118
+ title: settings.title ?? "\u8868\u683C\u6253\u5370",
4119
+ ...settings.subtitle ? { subtitle: settings.subtitle } : {},
4120
+ titleFontSize: settings.titleFontSize ?? 18,
4121
+ subtitleFontSize: settings.subtitleFontSize ?? 12,
4122
+ columns: activeColumns.map(({ key, title, width, align, overflow }) => ({
4123
+ key,
4124
+ title,
4125
+ width,
4126
+ ...align ? { align } : {},
4127
+ ...overflow ? { overflow } : {}
4128
+ })),
4129
+ rows: source.rows.map(
4130
+ (row) => activeColumns.map(
4131
+ (column) => row[sourceIndexes.get(column.key) ?? -1] ?? ""
4132
+ )
4133
+ ),
4134
+ rowsPerPage,
4135
+ rowHeight: settings.rowHeight ?? 8,
4136
+ ...settings.includeSummary && summaryRow ? {
4137
+ summaryRow: activeColumns.map(
4138
+ (_column, index) => summaryRow[index] ?? ""
4139
+ ),
4140
+ summaryPosition: settings.summaryPosition ?? "last-page"
4141
+ } : {},
4142
+ showPageNumbers: settings.showPageNumbers ?? false,
4143
+ pageNumberPosition: settings.pageNumberPosition ?? "right",
4144
+ showPrintTime: settings.showPrintTime ?? false,
4145
+ printTimePosition: settings.printTimePosition ?? "left",
4146
+ pageMargins: settings.pageMargins ?? {
4147
+ top: 12,
4148
+ right: 12,
4149
+ bottom: 12,
4150
+ left: 12
4151
+ },
4152
+ paperSize: settings.paperSize ?? "a4",
4153
+ orientation: settings.orientation ?? "portrait",
4154
+ useCellBorders: settings.useCellBorders ?? true,
4155
+ borderColor: settings.borderColor ?? "#000000",
4156
+ textColor: settings.textColor ?? "#000000",
4157
+ headerBackgroundColor: settings.headerBackgroundColor ?? "#f2f5f8",
4158
+ summaryBackgroundColor: settings.summaryBackgroundColor ?? "#f2f5f8"
4159
+ };
4160
+ }
4161
+ var summaryOptions2 = [
4162
+ { value: "original", label: "\u539F\u6C47\u603B" },
4163
+ { value: "none", label: "\u65E0\u6C47\u603B" },
4164
+ { value: "title", label: "\u6807\u9898" },
4165
+ { value: "sum", label: "\u6C42\u548C" },
4166
+ { value: "avg", label: "\u5E73\u5747\u503C" },
4167
+ { value: "count", label: "\u8BA1\u6570" },
4168
+ { value: "unionCount", label: "\u53BB\u91CD\u8BA1\u6570" },
4169
+ { value: "rowCount", label: "\u884C\u6570" },
4170
+ { value: "mergedRowCount", label: "\u5408\u5E76\u884C\u6570" },
4171
+ { value: "min", label: "\u6700\u5C0F\u503C" },
4172
+ { value: "max", label: "\u6700\u5927\u503C" }
4173
+ ];
4174
+ var roundingOptions2 = [
4175
+ { value: "round", label: "\u56DB\u820D\u4E94\u5165" },
4176
+ { value: "floor", label: "\u5411\u4E0B\u53D6\u6574" },
4177
+ { value: "ceil", label: "\u5411\u4E0A\u53D6\u6574" },
4178
+ { value: "truncate", label: "\u622A\u65AD" }
4179
+ ];
4180
+ var booleanOptions2 = [
4181
+ { value: "yes", label: "\u662F" },
4182
+ { value: "no", label: "\u5426" }
4183
+ ];
4184
+ function ReactListTablePrintDialog(props) {
4185
+ const tableId = react.useId();
4186
+ const [cached] = react.useState(() => readPrintSettings(props.storageKey));
4187
+ const initialPreset = cached?.presetName ? props.printPresets?.find((preset) => preset.name === cached.presetName) : cached ? void 0 : props.printPresets?.[0];
4188
+ const initialConfig = initialPreset?.config;
4189
+ const [columns, setColumns] = react.useState(
4190
+ () => restorePrintColumns(
4191
+ restorePrintColumns(
4192
+ createPrintColumns(props.source.columns, props.source.summaryColumns),
4193
+ initialConfig?.columns ? { columns: initialConfig.columns } : null
4194
+ ),
4195
+ cached
4196
+ )
4197
+ );
4198
+ const [selectedKeys, setSelectedKeys] = react.useState(
4199
+ () => resolvePrintSelectedKeys(props.source.columns, initialConfig, cached)
4200
+ );
4201
+ const [rowsPerPage, setRowsPerPage] = react.useState(
4202
+ cached?.rowsPerPage ?? initialConfig?.rowsPerPage ?? 30
4203
+ );
4204
+ const [rowHeight, setRowHeight] = react.useState(
4205
+ cached?.rowHeight ?? initialConfig?.rowHeight ?? 8
4206
+ );
4207
+ const [autoCalculateRows, setAutoCalculateRows] = react.useState(
4208
+ cached?.autoCalculateRowsPerPage ?? initialConfig?.autoCalculateRowsPerPage ?? false
4209
+ );
4210
+ const [title, setTitle] = react.useState(
4211
+ cached?.title ?? initialConfig?.title ?? "\u8868\u683C\u6253\u5370"
4212
+ );
4213
+ const [subtitle, setSubtitle] = react.useState(
4214
+ cached?.subtitle ?? initialConfig?.subtitle ?? ""
4215
+ );
4216
+ const [titleFontSize, setTitleFontSize] = react.useState(
4217
+ cached?.titleFontSize ?? initialConfig?.titleFontSize ?? 18
4218
+ );
4219
+ const [subtitleFontSize, setSubtitleFontSize] = react.useState(
4220
+ cached?.subtitleFontSize ?? initialConfig?.subtitleFontSize ?? 12
4221
+ );
4222
+ const [includeSummary, setIncludeSummary] = react.useState(
4223
+ () => cached?.includeSummary ?? initialConfig?.includeSummary ?? Boolean(
4224
+ props.source.summaryRow || props.source.summaryColumns?.some(
4225
+ (column) => column.summary.type !== "none"
4226
+ )
4227
+ )
4228
+ );
4229
+ const [summaryPosition, setSummaryPosition] = react.useState(cached?.summaryPosition ?? initialConfig?.summaryPosition ?? "last-page");
4230
+ const [showPageNumbers, setShowPageNumbers] = react.useState(
4231
+ cached?.showPageNumbers ?? initialConfig?.showPageNumbers ?? false
4232
+ );
4233
+ const [pageNumberPosition, setPageNumberPosition] = react.useState(cached?.pageNumberPosition ?? initialConfig?.pageNumberPosition ?? "right");
4234
+ const [showPrintTime, setShowPrintTime] = react.useState(
4235
+ cached?.showPrintTime ?? initialConfig?.showPrintTime ?? false
4236
+ );
4237
+ const [printTimePosition, setPrintTimePosition] = react.useState(cached?.printTimePosition ?? initialConfig?.printTimePosition ?? "left");
4238
+ const [pageMargins, setPageMargins] = react.useState(
4239
+ cached?.pageMargins ?? initialConfig?.pageMargins ?? {
4240
+ top: 12,
4241
+ right: 12,
4242
+ bottom: 12,
4243
+ left: 12
4244
+ }
4245
+ );
4246
+ const [paperSize, setPaperSize] = react.useState(cached?.paperSize ?? initialConfig?.paperSize ?? "a4");
4247
+ const [orientation, setOrientation] = react.useState(
4248
+ cached?.orientation ?? initialConfig?.orientation ?? "portrait"
4249
+ );
4250
+ const [useCellBorders, setUseCellBorders] = react.useState(
4251
+ cached?.useCellBorders ?? initialConfig?.useCellBorders ?? true
4252
+ );
4253
+ const [borderColor, setBorderColor] = react.useState(
4254
+ cached?.borderColor ?? initialConfig?.borderColor ?? "#000000"
4255
+ );
4256
+ const [textColor, setTextColor] = react.useState(
4257
+ cached?.textColor ?? initialConfig?.textColor ?? "#000000"
4258
+ );
4259
+ const [headerBackgroundColor, setHeaderBackgroundColor] = react.useState(
4260
+ cached?.headerBackgroundColor ?? initialConfig?.headerBackgroundColor ?? "#f2f5f8"
4261
+ );
4262
+ const [summaryBackgroundColor, setSummaryBackgroundColor] = react.useState(
4263
+ cached?.summaryBackgroundColor ?? initialConfig?.summaryBackgroundColor ?? "#f2f5f8"
4264
+ );
4265
+ const [selectedPresetName, setSelectedPresetName] = react.useState(
4266
+ initialPreset?.name ?? ""
4267
+ );
4268
+ const [showSectionDividers, setShowSectionDividers] = react.useState(
4269
+ cached?.showSectionDividers ?? initialConfig?.showSectionDividers ?? true
4270
+ );
4271
+ const [sectionDividerTopSpacing, setSectionDividerTopSpacing] = react.useState(
4272
+ cached?.sectionDividerTopSpacing ?? initialConfig?.sectionDividerTopSpacing ?? 4
4273
+ );
4274
+ const [sectionDividerBottomSpacing, setSectionDividerBottomSpacing] = react.useState(
4275
+ cached?.sectionDividerBottomSpacing ?? initialConfig?.sectionDividerBottomSpacing ?? 4
4276
+ );
4277
+ const [formItemSpacing, setFormItemSpacing] = react.useState(
4278
+ cached?.formItemSpacing ?? initialConfig?.formItemSpacing ?? 4
4279
+ );
4280
+ const [cacheEnabled, setCacheEnabled] = react.useState(Boolean(props.storageKey));
4281
+ const [error, setError] = react.useState("");
4282
+ const [previewHtml, setPreviewHtml] = react.useState("");
4283
+ const [previewOpen, setPreviewOpen] = react.useState(false);
4284
+ const [printFullscreen, setPrintFullscreen] = react.useState(false);
4285
+ const [previewFullscreen, setPreviewFullscreen] = react.useState(false);
4286
+ const [previewMode, setPreviewMode] = react.useState("render");
4287
+ const [previewViewport, setPreviewViewport] = react.useState(() => ({
4288
+ width: typeof window === "undefined" ? 1280 : window.innerWidth,
4289
+ height: typeof window === "undefined" ? 900 : window.innerHeight
4290
+ }));
4291
+ const selectedColumnKeys = new Set(selectedKeys.map(String));
4292
+ const layoutWarning = print.getBrowserPrintLayoutWarning({
4293
+ columns: columns.filter((column) => selectedColumnKeys.has(column.key)),
4294
+ pageMargins,
4295
+ paperSize,
4296
+ orientation
4297
+ });
4298
+ const rowLayoutWarning = print.getBrowserPrintRowLayoutWarning({
4299
+ pageMargins,
4300
+ paperSize,
4301
+ orientation,
4302
+ rowsPerPage,
4303
+ rowHeight,
4304
+ includeSummary,
4305
+ summaryPosition,
4306
+ showPageNumbers,
4307
+ showPrintTime,
4308
+ titleFontSize,
4309
+ subtitleFontSize,
4310
+ subtitle
4311
+ });
4312
+ const printLayoutWarning = [layoutWarning, rowLayoutWarning].filter(Boolean).join("\uFF1B");
4313
+ const [paperWidth, paperHeight] = print.BROWSER_PRINT_PAPER_SIZES[paperSize];
4314
+ const previewPaperWidth = orientation === "portrait" ? paperWidth : paperHeight;
4315
+ const previewPaperHeight = orientation === "portrait" ? paperHeight : paperWidth;
4316
+ const previewListHeight = Math.max(
4317
+ 240,
4318
+ previewFullscreen ? previewViewport.height - 168 : Math.min(previewViewport.height - 260, 900)
4319
+ );
4320
+ const previewListWidth = Math.max(
4321
+ 320,
4322
+ (previewFullscreen ? previewViewport.width : Math.min(previewViewport.width * 0.96, 1280)) - 48
4323
+ );
4324
+ const pageWidthPixels = previewPaperWidth * 96 / 25.4;
4325
+ const pageHeightPixels = previewPaperHeight * 96 / 25.4;
4326
+ const previewScale = Math.min(
4327
+ 1,
4328
+ (previewListWidth - 24) / pageWidthPixels,
4329
+ (previewListHeight - 24) / pageHeightPixels
4330
+ );
4331
+ const previewItemHeight = Math.ceil(pageHeightPixels * previewScale + 24);
4332
+ const previewPages = react.useMemo(() => {
4333
+ if (!previewHtml || typeof DOMParser === "undefined") return [];
4334
+ const parsed = new DOMParser().parseFromString(previewHtml, "text/html");
4335
+ const styles = Array.from(parsed.head.querySelectorAll("style")).map((style) => style.outerHTML).join("");
4336
+ const pages = Array.from(parsed.body.children).filter(
4337
+ (element) => element.classList.contains("page")
4338
+ );
4339
+ const pageStyles = `<style>html,body{box-sizing:border-box;width:${pageWidthPixels}px;height:${pageHeightPixels}px;max-width:none;max-height:none;margin:0;padding:0;overflow:hidden;background:#fff}body{display:block}.page{box-sizing:border-box;flex:0 0 auto;width:${previewPaperWidth}mm;max-width:none;height:${previewPaperHeight}mm;margin:0;overflow:hidden}</style>`;
4340
+ return pages.map((page, index) => ({
4341
+ index,
4342
+ srcDoc: `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8">${styles}${pageStyles}</head><body>${page.outerHTML}</body></html>`
4343
+ }));
4344
+ }, [
4345
+ pageHeightPixels,
4346
+ pageWidthPixels,
4347
+ previewHtml,
4348
+ previewPaperHeight,
4349
+ previewPaperWidth
4350
+ ]);
4351
+ react.useEffect(() => {
4352
+ const updateViewport = () => {
4353
+ setPreviewViewport({
4354
+ width: window.innerWidth,
4355
+ height: window.innerHeight
4356
+ });
4357
+ };
4358
+ window.addEventListener("resize", updateViewport);
4359
+ return () => window.removeEventListener("resize", updateViewport);
4360
+ }, []);
4361
+ const autoCalculateColumnWidths = () => {
4362
+ const selectedColumnSet = new Set(selectedKeys.map(String));
4363
+ const selectedColumns = columns.filter(
4364
+ (column) => selectedColumnSet.has(column.key)
4365
+ );
4366
+ const calculated = print.calculateBrowserPrintColumnWidths(selectedColumns, {
4367
+ pageMargins,
4368
+ paperSize,
4369
+ orientation
4370
+ });
4371
+ if (!calculated) {
4372
+ setError("\u5F53\u524D\u7EB8\u5F20\u53EF\u7528\u5BBD\u5EA6\u4E0D\u8DB3\u4EE5\u5BB9\u7EB3\u6240\u9009\u5217\uFF08\u6BCF\u5217\u81F3\u5C11 10mm\uFF09");
4373
+ return;
4374
+ }
4375
+ const widths = new Map(calculated.map(({ key, width }) => [key, width]));
4376
+ setColumns(
4377
+ (current) => current.map(
4378
+ (column) => widths.has(column.key) ? { ...column, width: widths.get(column.key) } : column
4379
+ )
4380
+ );
4381
+ setError("");
4382
+ };
4383
+ const autoCalculateRowsPerPage = () => {
4384
+ const calculated = print.calculateBrowserPrintRowsPerPage({
4385
+ pageMargins,
4386
+ paperSize,
4387
+ orientation,
4388
+ rowHeight,
4389
+ includeSummary,
4390
+ summaryPosition,
4391
+ showPageNumbers,
4392
+ showPrintTime,
4393
+ titleFontSize,
4394
+ subtitleFontSize,
4395
+ subtitle
4396
+ });
4397
+ if (!calculated) {
4398
+ setError("\u5F53\u524D\u7EB8\u5F20\u53EF\u7528\u9AD8\u5EA6\u4E0D\u8DB3\u4EE5\u5BB9\u7EB3\u4E00\u884C");
4399
+ return;
4400
+ }
4401
+ setRowsPerPage(calculated);
4402
+ setError("");
4403
+ };
4404
+ react.useEffect(() => {
4405
+ if (autoCalculateRows) autoCalculateRowsPerPage();
4406
+ }, [
4407
+ autoCalculateRows,
4408
+ rowHeight,
4409
+ includeSummary,
4410
+ summaryPosition,
4411
+ showPageNumbers,
4412
+ showPrintTime,
4413
+ titleFontSize,
4414
+ subtitleFontSize,
4415
+ subtitle,
4416
+ paperSize,
4417
+ orientation,
4418
+ pageMargins
4419
+ ]);
4420
+ react.useEffect(() => {
4421
+ if (showPageNumbers && showPrintTime && pageNumberPosition === printTimePosition) {
4422
+ setPrintTimePosition(pageNumberPosition === "left" ? "center" : "left");
4423
+ }
4424
+ }, [showPageNumbers, showPrintTime, pageNumberPosition, printTimePosition]);
4425
+ const createCurrentPrintOptions = () => configurePrintTable(
4426
+ props.source,
4427
+ columns,
4428
+ selectedKeys.map(String),
4429
+ rowsPerPage,
4430
+ {
4431
+ includeSummary,
4432
+ rowHeight,
4433
+ title,
4434
+ subtitle,
4435
+ titleFontSize,
4436
+ subtitleFontSize,
4437
+ summaryPosition,
4438
+ showPageNumbers,
4439
+ pageNumberPosition,
4440
+ showPrintTime,
4441
+ printTimePosition,
4442
+ pageMargins,
4443
+ paperSize,
4444
+ orientation,
4445
+ useCellBorders,
4446
+ borderColor,
4447
+ textColor,
4448
+ headerBackgroundColor,
4449
+ summaryBackgroundColor
4450
+ }
4451
+ );
4452
+ const applyPrintPreset = (name) => {
4453
+ setSelectedPresetName(name);
4454
+ setError("");
4455
+ if (!name) {
4456
+ const defaultColumns = createPrintColumns(
4457
+ props.source.columns,
4458
+ props.source.summaryColumns
4459
+ );
4460
+ setColumns(defaultColumns);
4461
+ setSelectedKeys(
4462
+ resolvePrintSelectedKeys(props.source.columns, void 0, null)
4463
+ );
4464
+ setRowsPerPage(30);
4465
+ setRowHeight(8);
4466
+ setAutoCalculateRows(false);
4467
+ setTitle("\u8868\u683C\u6253\u5370");
4468
+ setSubtitle("");
4469
+ setTitleFontSize(18);
4470
+ setSubtitleFontSize(12);
4471
+ setIncludeSummary(
4472
+ Boolean(
4473
+ props.source.summaryRow || props.source.summaryColumns?.some(
4474
+ (column) => column.summary.type !== "none"
4475
+ )
4476
+ )
4477
+ );
4478
+ setSummaryPosition("last-page");
4479
+ setShowPageNumbers(false);
4480
+ setPageNumberPosition("right");
4481
+ setShowPrintTime(false);
4482
+ setPrintTimePosition("left");
4483
+ setPageMargins({ top: 12, right: 12, bottom: 12, left: 12 });
4484
+ setPaperSize("a4");
4485
+ setOrientation("portrait");
4486
+ setUseCellBorders(true);
4487
+ setBorderColor("#000000");
4488
+ setTextColor("#000000");
4489
+ setHeaderBackgroundColor("#f2f5f8");
4490
+ setSummaryBackgroundColor("#f2f5f8");
4491
+ setShowSectionDividers(true);
4492
+ setSectionDividerTopSpacing(4);
4493
+ setSectionDividerBottomSpacing(4);
4494
+ setFormItemSpacing(4);
4495
+ return;
4496
+ }
4497
+ const preset = props.printPresets?.find((item) => item.name === name);
4498
+ if (!preset) return;
4499
+ const config = preset.config;
4500
+ const baseColumns = createPrintColumns(
4501
+ props.source.columns,
4502
+ props.source.summaryColumns
4503
+ );
4504
+ setColumns(
4505
+ restorePrintColumns(
4506
+ baseColumns,
4507
+ config.columns ? { columns: config.columns } : null
4508
+ )
4509
+ );
4510
+ setSelectedKeys(
4511
+ resolvePrintSelectedKeys(props.source.columns, config, null)
4512
+ );
4513
+ setRowsPerPage(config.rowsPerPage ?? 30);
4514
+ setRowHeight(config.rowHeight ?? 8);
4515
+ setAutoCalculateRows(config.autoCalculateRowsPerPage ?? false);
4516
+ setTitle(config.title ?? "\u8868\u683C\u6253\u5370");
4517
+ setSubtitle(config.subtitle ?? "");
4518
+ setTitleFontSize(config.titleFontSize ?? 18);
4519
+ setSubtitleFontSize(config.subtitleFontSize ?? 12);
4520
+ setIncludeSummary(
4521
+ config.includeSummary ?? Boolean(
4522
+ props.source.summaryRow || props.source.summaryColumns?.some(
4523
+ (column) => column.summary.type !== "none"
4524
+ )
4525
+ )
4526
+ );
4527
+ setSummaryPosition(config.summaryPosition ?? "last-page");
4528
+ setShowPageNumbers(config.showPageNumbers ?? false);
4529
+ setPageNumberPosition(config.pageNumberPosition ?? "right");
4530
+ setShowPrintTime(config.showPrintTime ?? false);
4531
+ setPrintTimePosition(config.printTimePosition ?? "left");
4532
+ setPageMargins(
4533
+ config.pageMargins ?? { top: 12, right: 12, bottom: 12, left: 12 }
4534
+ );
4535
+ setPaperSize(config.paperSize ?? "a4");
4536
+ setOrientation(config.orientation ?? "portrait");
4537
+ setUseCellBorders(config.useCellBorders ?? true);
4538
+ setBorderColor(config.borderColor ?? "#000000");
4539
+ setTextColor(config.textColor ?? "#000000");
4540
+ setHeaderBackgroundColor(config.headerBackgroundColor ?? "#f2f5f8");
4541
+ setSummaryBackgroundColor(config.summaryBackgroundColor ?? "#f2f5f8");
4542
+ setShowSectionDividers(config.showSectionDividers ?? true);
4543
+ setSectionDividerTopSpacing(config.sectionDividerTopSpacing ?? 4);
4544
+ setSectionDividerBottomSpacing(config.sectionDividerBottomSpacing ?? 4);
4545
+ setFormItemSpacing(config.formItemSpacing ?? 4);
4546
+ };
4547
+ const previewPrintHtml = async () => {
4548
+ if (!selectedKeys.length) {
4549
+ setError("\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u5217");
4550
+ return;
4551
+ }
4552
+ if (!Number.isInteger(rowsPerPage) || rowsPerPage < 1) {
4553
+ setError("\u6BCF\u9875\u884C\u6570\u5FC5\u987B\u662F\u6B63\u6574\u6570");
4554
+ return;
4555
+ }
4556
+ if (!Number.isFinite(rowHeight) || rowHeight <= 0) {
4557
+ setError("\u884C\u9AD8\u5FC5\u987B\u662F\u6B63\u6570");
4558
+ return;
4559
+ }
4560
+ try {
4561
+ const options = await createCurrentPrintOptions();
4562
+ setPreviewHtml(print.createBrowserPrintPreviewHtml(options));
4563
+ setPreviewMode("render");
4564
+ setPreviewOpen(true);
4565
+ setError("");
4566
+ } catch (cause) {
4567
+ setError(cause instanceof Error ? cause.message : "\u751F\u6210\u6253\u5370\u9884\u89C8\u5931\u8D25");
4568
+ }
4569
+ };
4570
+ const confirm = async () => {
4571
+ const selected = selectedKeys.map(String);
4572
+ if (!selected.length) return setError("\u8BF7\u81F3\u5C11\u9009\u62E9\u4E00\u5217");
4573
+ if (!Number.isInteger(rowsPerPage) || rowsPerPage < 1)
4574
+ return setError("\u6BCF\u9875\u884C\u6570\u5FC5\u987B\u662F\u6B63\u6574\u6570");
4575
+ if (!Number.isFinite(rowHeight) || rowHeight <= 0)
4576
+ return setError("\u884C\u9AD8\u5FC5\u987B\u662F\u6B63\u6570");
4577
+ if (Object.values(pageMargins).some(
4578
+ (margin) => !Number.isFinite(margin) || margin < 0
4579
+ )) {
4580
+ return setError("\u6253\u5370\u8FB9\u8DDD\u5FC5\u987B\u662F\u975E\u8D1F\u6570");
4581
+ }
4582
+ if (columns.some(
4583
+ (column) => !Number.isFinite(column.width) || column.width < 10
4584
+ )) {
4585
+ return setError("\u5217\u5BBD\u4E0D\u80FD\u5C0F\u4E8E 10 \u6BEB\u7C73");
4586
+ }
4587
+ const options = await createCurrentPrintOptions();
4588
+ if (!print.printBrowserTable(options))
4589
+ return setError("\u6D4F\u89C8\u5668\u963B\u6B62\u4E86\u6253\u5370\u7A97\u53E3\uFF0C\u8BF7\u5141\u8BB8\u6B64\u9875\u9762\u6253\u5F00\u5F39\u7A97");
4590
+ if (cacheEnabled) {
4591
+ writePrintSettings(props.storageKey, {
4592
+ version: 2,
4593
+ columns,
4594
+ selectedKeys: selected,
4595
+ rowsPerPage,
4596
+ presetName: selectedPresetName || void 0,
4597
+ rowHeight,
4598
+ autoCalculateRowsPerPage: autoCalculateRows,
4599
+ title,
4600
+ subtitle,
4601
+ titleFontSize,
4602
+ subtitleFontSize,
4603
+ includeSummary,
4604
+ summaryPosition,
4605
+ showPageNumbers,
4606
+ pageNumberPosition,
4607
+ showPrintTime,
4608
+ printTimePosition,
4609
+ pageMargins,
4610
+ paperSize,
4611
+ orientation,
4612
+ useCellBorders,
4613
+ borderColor,
4614
+ textColor,
4615
+ headerBackgroundColor,
4616
+ summaryBackgroundColor,
4617
+ showSectionDividers,
4618
+ sectionDividerTopSpacing,
4619
+ sectionDividerBottomSpacing,
4620
+ formItemSpacing
4621
+ });
4622
+ }
4623
+ props.onClose();
4624
+ };
4625
+ const tableColumns = [
4626
+ listTable.ROW_SELECTION_COLUMN,
4627
+ { key: "title", dataIndex: "title", title: "\u6253\u5370\u5217", width: 260 },
4628
+ {
4629
+ key: "width",
4630
+ dataIndex: "width",
4631
+ title: "\u5217\u5BBD\uFF08mm\uFF09",
4632
+ width: 110,
4633
+ editable: true,
4634
+ formItemProps: { valueType: "number", clickCount: 1, min: 10 }
4635
+ },
4636
+ {
4637
+ key: "align",
4638
+ dataIndex: "align",
4639
+ title: "\u5BF9\u9F50\u65B9\u5F0F",
4640
+ width: 100,
4641
+ editable: true,
4642
+ formItemProps: {
4643
+ valueType: "select",
4644
+ clickCount: 1,
4645
+ options: [
4646
+ { value: "left", label: "\u5DE6\u5BF9\u9F50" },
4647
+ { value: "center", label: "\u5C45\u4E2D" },
4648
+ { value: "right", label: "\u53F3\u5BF9\u9F50" }
4649
+ ]
4650
+ },
4651
+ render: (value) => value === "center" ? "\u5C45\u4E2D" : value === "right" ? "\u53F3\u5BF9\u9F50" : "\u5DE6\u5BF9\u9F50"
4652
+ },
4653
+ {
4654
+ key: "overflow",
4655
+ dataIndex: "overflow",
4656
+ title: "\u8D85\u5BBD\u5904\u7406",
4657
+ width: 105,
4658
+ editable: true,
4659
+ formItemProps: {
4660
+ valueType: "select",
4661
+ clickCount: 1,
4662
+ options: [
4663
+ { value: "ellipsis", label: "\u7701\u7565\u53F7" },
4664
+ { value: "clip", label: "\u88C1\u5207" },
4665
+ { value: "wrap", label: "\u6362\u884C" }
4666
+ ]
4667
+ },
4668
+ render: (value) => value === "ellipsis" ? "\u7701\u7565\u53F7" : value === "clip" ? "\u88C1\u5207" : "\u6362\u884C"
4669
+ },
4670
+ ...includeSummary ? [
4671
+ {
4672
+ key: "summary-group",
4673
+ dataIndex: "summaryType",
4674
+ title: "\u6C47\u603B",
4675
+ children: [
4676
+ {
4677
+ key: "summaryType",
4678
+ dataIndex: "summaryType",
4679
+ title: "\u6C47\u603B\u65B9\u5F0F",
4680
+ width: 110,
4681
+ editable: true,
4682
+ formItemProps: {
4683
+ valueType: "select",
4684
+ clickCount: 1,
4685
+ options: summaryOptions2.filter(
4686
+ (option) => option.value !== "original" || props.source.summaryColumns?.some(
4687
+ (column) => column.summary.type === "original"
4688
+ )
4689
+ )
4690
+ },
4691
+ render: (value) => summaryOptions2.find((option) => option.value === value)?.label ?? "\u65E0\u6C47\u603B"
4692
+ },
4693
+ {
4694
+ key: "showTypePrefix",
4695
+ dataIndex: "showTypePrefix",
4696
+ title: "\u6C47\u603B\u524D\u7F00",
4697
+ width: 90,
4698
+ editable: true,
4699
+ formItemProps: {
4700
+ valueType: "select",
4701
+ clickCount: 1,
4702
+ options: booleanOptions2
4703
+ },
4704
+ render: (value) => value === "yes" ? "\u662F" : "\u5426"
4705
+ },
4706
+ {
4707
+ key: "precision",
4708
+ dataIndex: "precision",
4709
+ title: "\u5C0F\u6570\u4F4D\u6570",
4710
+ width: 90,
4711
+ editable: true,
4712
+ formItemProps: {
4713
+ valueType: "number",
4714
+ clickCount: 1,
4715
+ min: 0,
4716
+ max: 20
4717
+ }
4718
+ },
4719
+ {
4720
+ key: "roundingMode",
4721
+ dataIndex: "roundingMode",
4722
+ title: "\u53D6\u6574\u65B9\u5F0F",
4723
+ width: 100,
4724
+ editable: true,
4725
+ formItemProps: {
4726
+ valueType: "select",
4727
+ clickCount: 1,
4728
+ options: roundingOptions2
4729
+ },
4730
+ render: (value) => roundingOptions2.find((option) => option.value === value)?.label ?? "\u56DB\u820D\u4E94\u5165"
4731
+ },
4732
+ {
4733
+ key: "preserveTrailingZeros",
4734
+ dataIndex: "preserveTrailingZeros",
4735
+ title: "\u4FDD\u7559\u65E0\u6548\u96F6",
4736
+ width: 100,
4737
+ editable: true,
4738
+ formItemProps: {
4739
+ valueType: "select",
4740
+ clickCount: 1,
4741
+ options: booleanOptions2
4742
+ },
4743
+ render: (value) => value === "yes" ? "\u662F" : "\u5426"
4744
+ }
4745
+ ]
4746
+ }
4747
+ ] : []
4748
+ ];
4749
+ const sectionDivider = showSectionDividers ? /* @__PURE__ */ jsxRuntime.jsx(
4750
+ "div",
4751
+ {
4752
+ "aria-hidden": "true",
4753
+ style: {
4754
+ height: 1,
4755
+ marginTop: sectionDividerTopSpacing,
4756
+ marginBottom: sectionDividerBottomSpacing,
4757
+ background: "#e2e8f0"
4758
+ }
4759
+ }
4760
+ ) : null;
4761
+ return /* @__PURE__ */ jsxRuntime.jsxs(
4762
+ reactComponents.ReactModal,
4763
+ {
4764
+ open: true,
4765
+ title: /* @__PURE__ */ jsxRuntime.jsxs(
4766
+ "span",
4767
+ {
4768
+ style: {
4769
+ display: "flex",
4770
+ alignItems: "baseline",
4771
+ gap: 12,
4772
+ minWidth: 0
4773
+ },
4774
+ children: [
4775
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u6253\u5370\u8868\u683C\u914D\u7F6E" }),
4776
+ printLayoutWarning ? /* @__PURE__ */ jsxRuntime.jsxs(
4777
+ "span",
4778
+ {
4779
+ role: "status",
4780
+ title: `${printLayoutWarning}\uFF0C\u4ECD\u53EF\u7EE7\u7EED\u6253\u5370\uFF1B\u6253\u5370\u7ED3\u679C\u53EF\u80FD\u88AB\u88C1\u5207\u6216\u5206\u9875\u5F02\u5E38\u3002`,
4781
+ style: {
4782
+ color: "#b45309",
4783
+ fontSize: 12,
4784
+ fontWeight: 400,
4785
+ whiteSpace: "nowrap",
4786
+ overflow: "hidden",
4787
+ textOverflow: "ellipsis",
4788
+ minWidth: 0
4789
+ },
4790
+ children: [
4791
+ printLayoutWarning,
4792
+ "\uFF0C\u4ECD\u53EF\u7EE7\u7EED\u6253\u5370"
4793
+ ]
4794
+ }
4795
+ ) : null
4796
+ ]
4797
+ }
4798
+ ),
4799
+ width: "min(98vw, 1680px)",
4800
+ fullscreenable: true,
4801
+ fullscreen: printFullscreen,
4802
+ onFullscreenChange: setPrintFullscreen,
4803
+ bodyStyle: { display: "flex", minHeight: 0 },
4804
+ okText: "\u6253\u5370",
4805
+ cancelText: "\u53D6\u6D88",
4806
+ onCancel: props.onClose,
4807
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(
4808
+ "div",
4809
+ {
4810
+ style: {
4811
+ display: "flex",
4812
+ justifyContent: "flex-end",
4813
+ alignItems: "center",
4814
+ gap: 8,
4815
+ width: "100%"
4816
+ },
4817
+ children: [
4818
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactButton, { type: "default", onClick: props.onClose, children: "\u53D6\u6D88" }),
4819
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactButton, { type: "default", onClick: previewPrintHtml, children: "\u6253\u5370\u9884\u89C8" }),
4820
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactButton, { type: "primary", onClick: confirm, children: "\u6253\u5370" })
4821
+ ]
4822
+ }
4823
+ ),
4824
+ children: [
4825
+ /* @__PURE__ */ jsxRuntime.jsx(
4826
+ "div",
4827
+ {
4828
+ style: {
4829
+ display: "flex",
4830
+ flex: "1 1 auto",
4831
+ minHeight: 0,
4832
+ flexDirection: "column"
4833
+ },
4834
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
4835
+ "div",
4836
+ {
4837
+ style: {
4838
+ display: "grid",
4839
+ flex: "1 1 auto",
4840
+ minHeight: 0,
4841
+ gridTemplateColumns: "minmax(340px, 380px) minmax(0, 1fr)",
4842
+ gap: 20,
4843
+ alignItems: "stretch"
4844
+ },
4845
+ children: [
4846
+ /* @__PURE__ */ jsxRuntime.jsx(
4847
+ "div",
4848
+ {
4849
+ style: {
4850
+ display: "grid",
4851
+ gap: 0,
4852
+ padding: "4px 4px 0 0",
4853
+ minHeight: 0,
4854
+ overflowY: "auto"
4855
+ },
4856
+ children: /* @__PURE__ */ jsxRuntime.jsxs(
4857
+ reactComponents.ReactForm,
4858
+ {
4859
+ layout: "horizontal",
4860
+ noWrap: true,
4861
+ itemSpacing: `${formItemSpacing}px`,
4862
+ labelWidth: 88,
4863
+ labelAlign: "left",
4864
+ style: { display: "contents" },
4865
+ children: [
4866
+ props.printPresets?.length ? /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u6253\u5370\u914D\u7F6E", children: /* @__PURE__ */ jsxRuntime.jsx(
4867
+ reactComponents.ReactSelect,
4868
+ {
4869
+ value: selectedPresetName,
4870
+ "aria-label": "\u6253\u5370\u914D\u7F6E\u9884\u8BBE",
4871
+ options: [
4872
+ { value: "", label: "\u9ED8\u8BA4\u914D\u7F6E" },
4873
+ ...props.printPresets.map((preset) => ({
4874
+ value: preset.name,
4875
+ label: preset.name
4876
+ }))
4877
+ ],
4878
+ onChange: (value) => applyPrintPreset(String(value ?? "")),
4879
+ style: { width: "100%" }
4880
+ }
4881
+ ) }) : null,
4882
+ props.storageKey ? /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u7F13\u5B58\u5230\u672C\u5730", children: /* @__PURE__ */ jsxRuntime.jsx(
4883
+ reactComponents.ReactCheckbox,
4884
+ {
4885
+ checked: cacheEnabled,
4886
+ "aria-label": "\u7F13\u5B58\u6253\u5370\u914D\u7F6E\u5230\u672C\u5730",
4887
+ onChange: (event) => {
4888
+ setCacheEnabled(event.target.checked);
4889
+ if (!event.target.checked)
4890
+ writePrintSettings(props.storageKey, null);
4891
+ }
4892
+ }
4893
+ ) }) : null,
4894
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u5206\u9694\u7EBF\u5360\u4F4D", children: /* @__PURE__ */ jsxRuntime.jsx(
4895
+ reactComponents.ReactCheckbox,
4896
+ {
4897
+ checked: showSectionDividers,
4898
+ "aria-label": "\u663E\u793A\u5206\u7EC4\u5206\u9694\u7EBF",
4899
+ onChange: (event) => setShowSectionDividers(event.target.checked)
4900
+ }
4901
+ ) }),
4902
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u884C\u95F4\u8DDD\uFF08px\uFF09", children: /* @__PURE__ */ jsxRuntime.jsx(
4903
+ reactComponents.ReactNumberInput,
4904
+ {
4905
+ min: 0,
4906
+ max: 40,
4907
+ step: 1,
4908
+ value: formItemSpacing,
4909
+ "aria-label": "\u8868\u5355\u884C\u95F4\u8DDD",
4910
+ onChange: (value) => setFormItemSpacing(value ?? 0),
4911
+ style: { width: "100%" }
4912
+ }
4913
+ ) }),
4914
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u5206\u9694\u7EBF\u4E0A\u4E0B\u95F4\u8DDD\uFF08px\uFF09", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
4915
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u4E0A" }),
4916
+ /* @__PURE__ */ jsxRuntime.jsx(
4917
+ reactComponents.ReactNumberInput,
4918
+ {
4919
+ min: 0,
4920
+ max: 40,
4921
+ step: 1,
4922
+ value: sectionDividerTopSpacing,
4923
+ "aria-label": "\u5206\u9694\u7EBF\u4E0A\u95F4\u8DDD",
4924
+ onChange: (value) => setSectionDividerTopSpacing(value ?? 0),
4925
+ style: { width: 64 }
4926
+ }
4927
+ ),
4928
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: "\u4E0B" }),
4929
+ /* @__PURE__ */ jsxRuntime.jsx(
4930
+ reactComponents.ReactNumberInput,
4931
+ {
4932
+ min: 0,
4933
+ max: 40,
4934
+ step: 1,
4935
+ value: sectionDividerBottomSpacing,
4936
+ "aria-label": "\u5206\u9694\u7EBF\u4E0B\u95F4\u8DDD",
4937
+ onChange: (value) => setSectionDividerBottomSpacing(value ?? 0),
4938
+ style: { width: 64 }
4939
+ }
4940
+ )
4941
+ ] }) }),
4942
+ sectionDivider,
4943
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u6807\u9898", children: /* @__PURE__ */ jsxRuntime.jsx(
4944
+ reactComponents.ReactInput,
4945
+ {
4946
+ value: title,
4947
+ "aria-label": "\u6253\u5370\u6807\u9898",
4948
+ allowClear: true,
4949
+ onChange: (event) => setTitle(event.target.value),
4950
+ style: { width: "100%", minWidth: 0 }
4951
+ }
4952
+ ) }),
4953
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u5B50\u6807\u9898", children: /* @__PURE__ */ jsxRuntime.jsx(
4954
+ reactComponents.ReactInput,
4955
+ {
4956
+ value: subtitle,
4957
+ "aria-label": "\u6253\u5370\u5B50\u6807\u9898",
4958
+ allowClear: true,
4959
+ onChange: (event) => setSubtitle(event.target.value),
4960
+ style: { width: "100%", minWidth: 0 }
4961
+ }
4962
+ ) }),
4963
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u6807\u9898\u5B57\u53F7", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 8, minWidth: 0 }, children: [
4964
+ /* @__PURE__ */ jsxRuntime.jsx(
4965
+ reactComponents.ReactNumberInput,
4966
+ {
4967
+ min: 1,
4968
+ step: 1,
4969
+ value: titleFontSize,
4970
+ "aria-label": "\u6807\u9898\u5B57\u53F7",
4971
+ onChange: (value) => setTitleFontSize(value ?? 18),
4972
+ style: { flex: "1 1 0", minWidth: 0 }
4973
+ }
4974
+ ),
4975
+ /* @__PURE__ */ jsxRuntime.jsx(
4976
+ reactComponents.ReactNumberInput,
4977
+ {
4978
+ min: 1,
4979
+ step: 1,
4980
+ value: subtitleFontSize,
4981
+ "aria-label": "\u5B50\u6807\u9898\u5B57\u53F7",
4982
+ onChange: (value) => setSubtitleFontSize(value ?? 12),
4983
+ style: { flex: "1 1 0", minWidth: 0 }
4984
+ }
4985
+ )
4986
+ ] }) }),
4987
+ sectionDivider,
4988
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u7EB8\u5F20", children: /* @__PURE__ */ jsxRuntime.jsx(
4989
+ reactComponents.ReactSelect,
4990
+ {
4991
+ value: paperSize,
4992
+ options: [
4993
+ { value: "a0", label: "A0" },
4994
+ { value: "a1", label: "A1" },
4995
+ { value: "a2", label: "A2" },
4996
+ { value: "a3", label: "A3" },
4997
+ { value: "a4", label: "A4" },
4998
+ { value: "a5", label: "A5" },
4999
+ { value: "a6", label: "A6" },
5000
+ { value: "b4", label: "B4" },
5001
+ { value: "b5", label: "B5" },
5002
+ { value: "letter", label: "Letter" },
5003
+ { value: "legal", label: "Legal" },
5004
+ { value: "tabloid", label: "Tabloid" },
5005
+ { value: "executive", label: "Executive" },
5006
+ { value: "folio", label: "Folio" }
5007
+ ],
5008
+ onChange: (value) => setPaperSize(value),
5009
+ style: { width: "100%" }
5010
+ }
5011
+ ) }),
5012
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u6253\u5370\u65B9\u5411", children: /* @__PURE__ */ jsxRuntime.jsxs(
5013
+ reactComponents.ReactRadio.Group,
5014
+ {
5015
+ value: orientation,
5016
+ "aria-label": "\u6253\u5370\u65B9\u5411",
5017
+ onChange: (event) => setOrientation(event.target.value),
5018
+ style: { display: "flex", gap: 10, flexWrap: "nowrap" },
5019
+ children: [
5020
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactRadio, { value: "portrait", children: "\u7EB5\u5411" }),
5021
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactRadio, { value: "landscape", children: "\u6A2A\u5411" })
5022
+ ]
5023
+ }
5024
+ ) }),
5025
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u6253\u5370\u8FB9\u8DDD\uFF08mm\uFF09", children: /* @__PURE__ */ jsxRuntime.jsx(
5026
+ "div",
5027
+ {
5028
+ style: {
5029
+ display: "grid",
5030
+ gridTemplateColumns: "repeat(4, minmax(0, 1fr))",
5031
+ gap: 8
5032
+ },
5033
+ children: [
5034
+ ["top", "\u4E0A"],
5035
+ ["right", "\u53F3"],
5036
+ ["bottom", "\u4E0B"],
5037
+ ["left", "\u5DE6"]
5038
+ ].map(([side, label]) => /* @__PURE__ */ jsxRuntime.jsxs(
5039
+ "div",
5040
+ {
5041
+ style: {
5042
+ display: "grid",
5043
+ gridTemplateColumns: "20px minmax(0, 1fr)",
5044
+ gap: 4,
5045
+ alignItems: "center"
5046
+ },
5047
+ children: [
5048
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: label }),
5049
+ /* @__PURE__ */ jsxRuntime.jsx(
5050
+ reactComponents.ReactNumberInput,
5051
+ {
5052
+ min: 0,
5053
+ step: 1,
5054
+ value: pageMargins[side],
5055
+ onChange: (value) => setPageMargins((current) => ({
5056
+ ...current,
5057
+ [side]: value ?? 0
5058
+ })),
5059
+ style: { width: "100%" }
5060
+ }
5061
+ )
5062
+ ]
5063
+ },
5064
+ side
5065
+ ))
5066
+ }
5067
+ ) }),
5068
+ sectionDivider,
5069
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u5355\u5143\u683C\u8FB9\u6846", children: /* @__PURE__ */ jsxRuntime.jsx(
5070
+ reactComponents.ReactCheckbox,
5071
+ {
5072
+ checked: useCellBorders,
5073
+ "aria-label": "\u5355\u5143\u683C\u8FB9\u6846",
5074
+ onChange: (event) => setUseCellBorders(event.target.checked)
5075
+ }
5076
+ ) }),
5077
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u8FB9\u6846\u989C\u8272", children: /* @__PURE__ */ jsxRuntime.jsx(
5078
+ reactComponents.ReactColorPicker,
5079
+ {
5080
+ value: borderColor,
5081
+ disabled: !useCellBorders,
5082
+ onChange: setBorderColor,
5083
+ style: { width: "100%" }
5084
+ }
5085
+ ) }),
5086
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u6587\u5B57\u989C\u8272", children: /* @__PURE__ */ jsxRuntime.jsx(
5087
+ reactComponents.ReactColorPicker,
5088
+ {
5089
+ value: textColor,
5090
+ onChange: setTextColor,
5091
+ style: { width: "100%" }
5092
+ }
5093
+ ) }),
5094
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u8868\u5934\u80CC\u666F\u8272", children: /* @__PURE__ */ jsxRuntime.jsx(
5095
+ reactComponents.ReactColorPicker,
5096
+ {
5097
+ value: headerBackgroundColor,
5098
+ onChange: setHeaderBackgroundColor,
5099
+ style: { width: "100%" }
5100
+ }
5101
+ ) }),
5102
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u6C47\u603B\u884C\u80CC\u666F\u8272", children: /* @__PURE__ */ jsxRuntime.jsx(
5103
+ reactComponents.ReactColorPicker,
5104
+ {
5105
+ value: summaryBackgroundColor,
5106
+ onChange: setSummaryBackgroundColor,
5107
+ style: { width: "100%" }
5108
+ }
5109
+ ) }),
5110
+ sectionDivider,
5111
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u6253\u5370\u6C47\u603B\u884C", children: /* @__PURE__ */ jsxRuntime.jsx(
5112
+ reactComponents.ReactCheckbox,
5113
+ {
5114
+ checked: includeSummary,
5115
+ "aria-label": "\u6253\u5370\u6C47\u603B\u884C",
5116
+ onChange: (event) => setIncludeSummary(event.target.checked)
5117
+ }
5118
+ ) }),
5119
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u6C47\u603B\u4F4D\u7F6E", children: /* @__PURE__ */ jsxRuntime.jsxs(
5120
+ reactComponents.ReactRadio.Group,
5121
+ {
5122
+ value: summaryPosition,
5123
+ "aria-label": "\u6C47\u603B\u4F4D\u7F6E",
5124
+ onChange: (event) => setSummaryPosition(
5125
+ event.target.value
5126
+ ),
5127
+ style: { display: "flex", gap: 10, flexWrap: "nowrap" },
5128
+ children: [
5129
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactRadio, { value: "every-page", disabled: !includeSummary, children: "\u6BCF\u9875" }),
5130
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactRadio, { value: "last-page", disabled: !includeSummary, children: "\u6700\u540E\u4E00\u9875" })
5131
+ ]
5132
+ }
5133
+ ) }),
5134
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u6253\u5370\u65F6\u95F4", children: /* @__PURE__ */ jsxRuntime.jsxs(
5135
+ "span",
5136
+ {
5137
+ style: {
5138
+ display: "flex",
5139
+ alignItems: "center",
5140
+ gap: 8,
5141
+ minWidth: 0,
5142
+ whiteSpace: "nowrap"
5143
+ },
5144
+ children: [
5145
+ /* @__PURE__ */ jsxRuntime.jsx(
5146
+ reactComponents.ReactCheckbox,
5147
+ {
5148
+ checked: showPrintTime,
5149
+ "aria-label": "\u663E\u793A\u6253\u5370\u65F6\u95F4",
5150
+ onChange: (event) => {
5151
+ const checked = event.target.checked;
5152
+ setShowPrintTime(checked);
5153
+ if (checked && showPageNumbers && pageNumberPosition === printTimePosition) {
5154
+ setPrintTimePosition(
5155
+ pageNumberPosition === "left" ? "center" : "left"
5156
+ );
5157
+ }
5158
+ }
5159
+ }
5160
+ ),
5161
+ "\u663E\u793A"
5162
+ ]
5163
+ }
5164
+ ) }),
5165
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u65F6\u95F4\u4F4D\u7F6E", children: /* @__PURE__ */ jsxRuntime.jsxs(
5166
+ reactComponents.ReactRadio.Group,
5167
+ {
5168
+ value: printTimePosition,
5169
+ "aria-label": "\u6253\u5370\u65F6\u95F4\u4F4D\u7F6E",
5170
+ onChange: (event) => {
5171
+ const next = event.target.value;
5172
+ if (showPageNumbers && next === pageNumberPosition) return;
5173
+ setPrintTimePosition(next);
5174
+ },
5175
+ style: { display: "flex", gap: 10, flexWrap: "nowrap" },
5176
+ children: [
5177
+ /* @__PURE__ */ jsxRuntime.jsx(
5178
+ reactComponents.ReactRadio,
5179
+ {
5180
+ value: "left",
5181
+ disabled: !showPrintTime || showPageNumbers && pageNumberPosition === "left",
5182
+ children: "\u5DE6\u4FA7"
5183
+ }
5184
+ ),
5185
+ /* @__PURE__ */ jsxRuntime.jsx(
5186
+ reactComponents.ReactRadio,
5187
+ {
5188
+ value: "center",
5189
+ disabled: !showPrintTime || showPageNumbers && pageNumberPosition === "center",
5190
+ children: "\u4E2D\u95F4"
5191
+ }
5192
+ ),
5193
+ /* @__PURE__ */ jsxRuntime.jsx(
5194
+ reactComponents.ReactRadio,
5195
+ {
5196
+ value: "right",
5197
+ disabled: !showPrintTime || showPageNumbers && pageNumberPosition === "right",
5198
+ children: "\u53F3\u4FA7"
5199
+ }
5200
+ )
5201
+ ]
5202
+ }
5203
+ ) }),
5204
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u5206\u9875\u4FE1\u606F", children: /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
5205
+ /* @__PURE__ */ jsxRuntime.jsx(
5206
+ reactComponents.ReactCheckbox,
5207
+ {
5208
+ checked: showPageNumbers,
5209
+ "aria-label": "\u663E\u793A\u5206\u9875\u4FE1\u606F",
5210
+ onChange: (event) => setShowPageNumbers(event.target.checked)
5211
+ }
5212
+ ),
5213
+ "\u663E\u793A"
5214
+ ] }) }),
5215
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u5206\u9875\u4F4D\u7F6E", children: /* @__PURE__ */ jsxRuntime.jsxs(
5216
+ reactComponents.ReactRadio.Group,
5217
+ {
5218
+ value: pageNumberPosition,
5219
+ "aria-label": "\u5206\u9875\u4FE1\u606F\u4F4D\u7F6E",
5220
+ onChange: (event) => (() => {
5221
+ const next = event.target.value;
5222
+ setPageNumberPosition(next);
5223
+ if (showPrintTime && next === printTimePosition) {
5224
+ setPrintTimePosition(
5225
+ next === "left" ? "center" : "left"
5226
+ );
5227
+ }
5228
+ })(),
5229
+ style: { display: "flex", gap: 10, flexWrap: "nowrap" },
5230
+ children: [
5231
+ /* @__PURE__ */ jsxRuntime.jsx(
5232
+ reactComponents.ReactRadio,
5233
+ {
5234
+ value: "left",
5235
+ disabled: !showPageNumbers || showPrintTime && printTimePosition === "left",
5236
+ children: "\u5DE6\u4FA7"
5237
+ }
5238
+ ),
5239
+ /* @__PURE__ */ jsxRuntime.jsx(
5240
+ reactComponents.ReactRadio,
5241
+ {
5242
+ value: "center",
5243
+ disabled: !showPageNumbers || showPrintTime && printTimePosition === "center",
5244
+ children: "\u4E2D\u95F4"
5245
+ }
5246
+ ),
5247
+ /* @__PURE__ */ jsxRuntime.jsx(
5248
+ reactComponents.ReactRadio,
5249
+ {
5250
+ value: "right",
5251
+ disabled: !showPageNumbers || showPrintTime && printTimePosition === "right",
5252
+ children: "\u53F3\u4FA7"
5253
+ }
5254
+ )
5255
+ ]
5256
+ }
5257
+ ) }),
5258
+ sectionDivider,
5259
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u884C\u9AD8\uFF08mm\uFF09", children: /* @__PURE__ */ jsxRuntime.jsx(
5260
+ reactComponents.ReactNumberInput,
5261
+ {
5262
+ min: 1,
5263
+ step: 1,
5264
+ value: rowHeight,
5265
+ onChange: (value) => {
5266
+ setRowHeight(value ?? 0);
5267
+ setError("");
5268
+ },
5269
+ style: { width: "100%" }
5270
+ }
5271
+ ) }),
5272
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactForm.Item, { label: "\u6BCF\u9875\u884C\u6570", children: /* @__PURE__ */ jsxRuntime.jsxs(
5273
+ "span",
5274
+ {
5275
+ style: {
5276
+ display: "flex",
5277
+ alignItems: "center",
5278
+ gap: 8,
5279
+ whiteSpace: "nowrap"
5280
+ },
5281
+ children: [
5282
+ /* @__PURE__ */ jsxRuntime.jsx(
5283
+ reactComponents.ReactNumberInput,
5284
+ {
5285
+ min: 1,
5286
+ step: 1,
5287
+ value: rowsPerPage,
5288
+ onChange: (value) => {
5289
+ setRowsPerPage(value ?? 0);
5290
+ setError("");
5291
+ },
5292
+ style: { flex: "1 1 auto", minWidth: 0 }
5293
+ }
5294
+ ),
5295
+ /* @__PURE__ */ jsxRuntime.jsx(
5296
+ reactComponents.ReactCheckbox,
5297
+ {
5298
+ checked: autoCalculateRows,
5299
+ "aria-label": "\u81EA\u52A8\u8BA1\u7B97\u6BCF\u9875\u884C\u6570",
5300
+ onChange: (event) => setAutoCalculateRows(event.target.checked)
5301
+ }
5302
+ ),
5303
+ "\u81EA\u52A8\u8BA1\u7B97"
5304
+ ]
5305
+ }
5306
+ ) })
5307
+ ]
5308
+ }
5309
+ )
5310
+ }
5311
+ ),
5312
+ /* @__PURE__ */ jsxRuntime.jsxs(
5313
+ "div",
5314
+ {
5315
+ style: {
5316
+ minWidth: 0,
5317
+ minHeight: 0,
5318
+ display: "flex",
5319
+ flexDirection: "column"
5320
+ },
5321
+ children: [
5322
+ /* @__PURE__ */ jsxRuntime.jsx(
5323
+ "div",
5324
+ {
5325
+ style: {
5326
+ display: "flex",
5327
+ justifyContent: "flex-end",
5328
+ marginBottom: 8
5329
+ },
5330
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5331
+ reactComponents.ReactButton,
5332
+ {
5333
+ type: "default",
5334
+ onClick: autoCalculateColumnWidths,
5335
+ disabled: selectedKeys.length === 0,
5336
+ children: "\u81EA\u52A8\u8BA1\u7B97\u5217\u5BBD"
5337
+ }
5338
+ )
5339
+ }
5340
+ ),
5341
+ /* @__PURE__ */ jsxRuntime.jsx(
5342
+ "div",
5343
+ {
5344
+ style: {
5345
+ flex: "1 1 auto",
5346
+ minHeight: 280,
5347
+ height: printFullscreen ? "100%" : "min(58vh, 560px)"
5348
+ },
5349
+ children: props.renderTable({
5350
+ tableId,
5351
+ columns: tableColumns,
5352
+ dataSource: columns,
5353
+ rowKey: "key",
5354
+ rowHeight: 40,
5355
+ headerRowHeight: 38,
5356
+ toolbar: false,
5357
+ contextMenu: false,
5358
+ pagination: false,
5359
+ draggable: true,
5360
+ rowSelection: {
5361
+ type: "checkbox",
5362
+ selectedRowKeys: selectedKeys,
5363
+ selectRowByClick: false,
5364
+ onChange: (keys) => {
5365
+ setSelectedKeys(keys);
5366
+ setError("");
5367
+ }
5368
+ },
5369
+ rowDrag: {
5370
+ enabled: true,
5371
+ droppable: true,
5372
+ allowSelfDrop: true,
5373
+ mode: "move",
5374
+ onDrop: ({ rows: moved, insertIndex, source }) => {
5375
+ if (source.tableId !== tableId || insertIndex == null)
5376
+ return;
5377
+ const keys = new Set(moved.map((row) => row.key));
5378
+ setColumns((current) => {
5379
+ const remaining = current.filter(
5380
+ (row) => !keys.has(row.key)
5381
+ );
5382
+ const preceding = current.slice(0, insertIndex).filter((row) => !keys.has(row.key)).length;
5383
+ remaining.splice(
5384
+ preceding,
5385
+ 0,
5386
+ ...current.filter((row) => keys.has(row.key))
5387
+ );
5388
+ return remaining;
5389
+ });
5390
+ }
5391
+ },
5392
+ style: { width: "100%", height: "100%" }
5393
+ })
5394
+ }
5395
+ )
5396
+ ]
5397
+ }
5398
+ )
5399
+ ]
5400
+ }
5401
+ )
5402
+ }
5403
+ ),
5404
+ error ? /* @__PURE__ */ jsxRuntime.jsx("div", { role: "alert", style: { color: "#c2410c", marginTop: 8 }, children: error }) : null,
5405
+ /* @__PURE__ */ jsxRuntime.jsx(
5406
+ reactComponents.ReactModal,
5407
+ {
5408
+ open: previewOpen,
5409
+ title: "\u6253\u5370\u9884\u89C8",
5410
+ width: "min(96vw, 1280px)",
5411
+ fullscreenable: true,
5412
+ fullscreen: previewFullscreen,
5413
+ onFullscreenChange: setPreviewFullscreen,
5414
+ bodyStyle: { display: "flex", minHeight: 0 },
5415
+ footer: /* @__PURE__ */ jsxRuntime.jsxs(
5416
+ "div",
5417
+ {
5418
+ style: {
5419
+ display: "flex",
5420
+ justifyContent: "flex-end",
5421
+ alignItems: "center",
5422
+ gap: 8,
5423
+ width: "100%"
5424
+ },
5425
+ children: [
5426
+ /* @__PURE__ */ jsxRuntime.jsx(
5427
+ reactComponents.ReactButton,
5428
+ {
5429
+ type: previewMode === "render" ? "primary" : "default",
5430
+ onClick: () => setPreviewMode("render"),
5431
+ children: "\u6548\u679C"
5432
+ }
5433
+ ),
5434
+ /* @__PURE__ */ jsxRuntime.jsx(
5435
+ reactComponents.ReactButton,
5436
+ {
5437
+ type: previewMode === "source" ? "primary" : "default",
5438
+ onClick: () => setPreviewMode("source"),
5439
+ children: "HTML"
5440
+ }
5441
+ ),
5442
+ /* @__PURE__ */ jsxRuntime.jsx(reactComponents.ReactButton, { type: "default", onClick: previewPrintHtml, children: "\u5237\u65B0\u9884\u89C8" })
5443
+ ]
5444
+ }
5445
+ ),
5446
+ onCancel: () => setPreviewOpen(false),
5447
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5448
+ "div",
5449
+ {
5450
+ style: {
5451
+ display: "flex",
5452
+ flex: 1,
5453
+ minHeight: 0,
5454
+ width: "100%",
5455
+ justifyContent: "center"
5456
+ },
5457
+ children: previewMode === "render" ? /* @__PURE__ */ jsxRuntime.jsx(
5458
+ reactComponents.ReactVirtualList,
5459
+ {
5460
+ items: previewPages,
5461
+ height: previewListHeight,
5462
+ itemHeight: previewItemHeight,
5463
+ itemKey: (page) => page.index,
5464
+ overscan: 1,
5465
+ style: {
5466
+ width: "100%",
5467
+ maxWidth: previewListWidth,
5468
+ overflowX: "hidden"
5469
+ },
5470
+ renderItem: (page, _index, meta) => /* @__PURE__ */ jsxRuntime.jsx(
5471
+ "div",
5472
+ {
5473
+ style: {
5474
+ ...meta.style,
5475
+ display: "flex",
5476
+ justifyContent: "center",
5477
+ alignItems: "flex-start",
5478
+ height: previewItemHeight,
5479
+ padding: 12,
5480
+ boxSizing: "border-box",
5481
+ overflow: "hidden"
5482
+ },
5483
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5484
+ "div",
5485
+ {
5486
+ style: {
5487
+ width: pageWidthPixels * previewScale,
5488
+ height: pageHeightPixels * previewScale,
5489
+ border: "1px solid #cbd5e1",
5490
+ position: "relative",
5491
+ overflow: "hidden",
5492
+ background: "white"
5493
+ },
5494
+ children: /* @__PURE__ */ jsxRuntime.jsx(
5495
+ "iframe",
5496
+ {
5497
+ title: `\u6253\u5370\u6548\u679C\u9884\u89C8\u7B2C ${page.index + 1} \u9875`,
5498
+ srcDoc: page.srcDoc,
5499
+ sandbox: "",
5500
+ style: {
5501
+ display: "block",
5502
+ position: "absolute",
5503
+ left: 0,
5504
+ top: 0,
5505
+ width: pageWidthPixels,
5506
+ height: pageHeightPixels,
5507
+ transform: `scale(${previewScale})`,
5508
+ transformOrigin: "top left",
5509
+ border: 0,
5510
+ overflow: "hidden",
5511
+ background: "white"
5512
+ }
5513
+ }
5514
+ )
5515
+ }
5516
+ )
5517
+ }
5518
+ )
5519
+ }
5520
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
5521
+ "pre",
5522
+ {
5523
+ "aria-label": "\u751F\u6210\u7684\u6253\u5370 HTML",
5524
+ style: {
5525
+ boxSizing: "border-box",
5526
+ width: "100%",
5527
+ height: previewFullscreen ? "100%" : "min(72vh, 900px)",
5528
+ minHeight: 0,
5529
+ overflow: "auto",
5530
+ margin: 0,
5531
+ padding: 12,
5532
+ border: "1px solid #cbd5e1",
5533
+ background: "#f8fafc",
5534
+ color: "#1f2937",
5535
+ font: "12px/1.5 ui-monospace, SFMono-Regular, monospace",
5536
+ whiteSpace: "pre-wrap",
5537
+ overflowWrap: "anywhere"
5538
+ },
5539
+ children: previewHtml
5540
+ }
5541
+ )
5542
+ }
5543
+ )
5544
+ }
5545
+ )
5546
+ ]
5547
+ }
5548
+ );
5549
+ }
5550
+
3950
5551
  // src/features/editor/utils.ts
3951
5552
  function toNumberValue(value) {
3952
5553
  if (typeof value === "number" && Number.isFinite(value)) {
@@ -5948,6 +7549,32 @@ function applyColumnManagerState(columns, visibility, orders, config, parentKey
5948
7549
  };
5949
7550
  });
5950
7551
  }
7552
+ function normalizeUniqueColumnKeys(columns) {
7553
+ const usedKeys = /* @__PURE__ */ new Set();
7554
+ const reservedKeys = /* @__PURE__ */ new Set();
7555
+ const collectKeys = (items) => {
7556
+ items.forEach((column) => {
7557
+ reservedKeys.add(resolveColumnKey(column));
7558
+ if (column.children) collectKeys(column.children);
7559
+ });
7560
+ };
7561
+ collectKeys(columns);
7562
+ const visit = (items) => items.map((column) => {
7563
+ const baseKey = resolveColumnKey(column);
7564
+ let key = baseKey;
7565
+ let suffix = 2;
7566
+ while (usedKeys.has(key) || key !== baseKey && reservedKeys.has(key)) {
7567
+ key = `${baseKey}#${suffix++}`;
7568
+ }
7569
+ usedKeys.add(key);
7570
+ return {
7571
+ ...column,
7572
+ key,
7573
+ children: column.children ? visit(column.children) : void 0
7574
+ };
7575
+ });
7576
+ return visit(columns);
7577
+ }
5951
7578
  function applyManagedColumnOrder(columns, orderedKeys) {
5952
7579
  const managedKeySet = new Set(orderedKeys);
5953
7580
  const managedSlots = columns.map(
@@ -6053,6 +7680,10 @@ function ReactListTableInner(props, ref) {
6053
7680
  toolbar,
6054
7681
  exportOptions
6055
7682
  } = props;
7683
+ const sourceColumns = react.useMemo(
7684
+ () => normalizeUniqueColumnKeys(columns),
7685
+ [columns]
7686
+ );
6056
7687
  const inheritedDebugEnabled = useReactListTableDebugEnabled();
6057
7688
  const resolvedDebug = react.useMemo(
6058
7689
  () => resolveReactListTableDebugOptions(debug, inheritedDebugEnabled),
@@ -6092,13 +7723,13 @@ function ReactListTableInner(props, ref) {
6092
7723
  const [columnConfigResetRevision, setColumnConfigResetRevision] = react.useState(0);
6093
7724
  const resolvedColumns = react.useMemo(
6094
7725
  () => applyColumnManagerState(
6095
- restoredColumnTree?.sourceColumns === columns && restoredColumnTree.storageKey === storageKey ? restoredColumnTree.columns : columns,
7726
+ restoredColumnTree?.sourceColumns === sourceColumns && restoredColumnTree.storageKey === storageKey ? restoredColumnTree.columns : sourceColumns,
6096
7727
  columnVisibility,
6097
7728
  columnOrders,
6098
7729
  columnConfig
6099
7730
  ),
6100
7731
  [
6101
- columns,
7732
+ sourceColumns,
6102
7733
  storageKey,
6103
7734
  restoredColumnTree,
6104
7735
  columnVisibility,
@@ -6179,10 +7810,10 @@ function ReactListTableInner(props, ref) {
6179
7810
  onColumnSettingsChange: (restoredColumns, source) => {
6180
7811
  const signature = getColumnSettingsSignature(restoredColumns);
6181
7812
  const current = restoredColumnTreeRef.current;
6182
- if (current?.sourceColumns === columns && current.storageKey === storageKey && current.signature === signature)
7813
+ if (current?.sourceColumns === sourceColumns && current.storageKey === storageKey && current.signature === signature)
6183
7814
  return;
6184
7815
  const next = {
6185
- sourceColumns: columns,
7816
+ sourceColumns,
6186
7817
  storageKey,
6187
7818
  columns: restoredColumns,
6188
7819
  signature
@@ -6267,6 +7898,7 @@ function ReactListTableInner(props, ref) {
6267
7898
  closeDangerConfirmRequest
6268
7899
  } = useReactListTableState(options);
6269
7900
  const hasPagination = paginationConfig != null;
7901
+ const [printSource, setPrintSource] = react.useState(null);
6270
7902
  const paginationLayout = resolveReactListTablePaginationLayout(resolvedRowHeight);
6271
7903
  const portalContainer = resolveFullscreenPortalContainer(shellRef.current);
6272
7904
  react.useImperativeHandle(
@@ -6373,7 +8005,7 @@ function ReactListTableInner(props, ref) {
6373
8005
  },
6374
8006
  onResetColumns: () => {
6375
8007
  const initialColumns = applyColumnManagerState(
6376
- columns,
8008
+ sourceColumns,
6377
8009
  /* @__PURE__ */ new Map(),
6378
8010
  /* @__PURE__ */ new Map(),
6379
8011
  /* @__PURE__ */ new Map()
@@ -6448,6 +8080,30 @@ function ReactListTableInner(props, ref) {
6448
8080
  /* @__PURE__ */ jsxRuntime.jsx(
6449
8081
  ReactTableContextMenuView,
6450
8082
  {
8083
+ onPrint: () => {
8084
+ const getPrintData = headerContextMenuRequest?.onGetPrintData;
8085
+ if (!getPrintData) return;
8086
+ void Promise.resolve(getPrintData()).then(
8087
+ (source) => setPrintSource(source)
8088
+ );
8089
+ headerContextMenuRequest?.onClose();
8090
+ },
8091
+ onDirectPrint: () => {
8092
+ const request = headerContextMenuRequest;
8093
+ if (!request?.onGetPrintData) return;
8094
+ request.onClose();
8095
+ void Promise.resolve(request.onGetPrintData()).then(
8096
+ (source) => createCachedPrintTableOptions(
8097
+ source,
8098
+ storageKey ? `list:${storageKey}` : void 0,
8099
+ props.printPresets
8100
+ )
8101
+ ).then((options2) => {
8102
+ print.printBrowserTable(options2);
8103
+ }).catch((error) => {
8104
+ console.error("\u76F4\u63A5\u6253\u5370\u5931\u8D25", error);
8105
+ });
8106
+ },
6451
8107
  request: headerContextMenuRequest ? {
6452
8108
  ...headerContextMenuRequest,
6453
8109
  scrollbar: effectiveScrollbar,
@@ -6468,6 +8124,19 @@ function ReactListTableInner(props, ref) {
6468
8124
  ),
6469
8125
  portalContainer
6470
8126
  ),
8127
+ printSource ? reactDom.createPortal(
8128
+ /* @__PURE__ */ jsxRuntime.jsx(
8129
+ ReactListTablePrintDialog,
8130
+ {
8131
+ source: printSource,
8132
+ printPresets: props.printPresets,
8133
+ storageKey: storageKey ? `list:${storageKey}` : void 0,
8134
+ onClose: () => setPrintSource(null),
8135
+ renderTable: (tableProps) => /* @__PURE__ */ jsxRuntime.jsx(ReactListTable, { ...tableProps })
8136
+ }
8137
+ ),
8138
+ portalContainer
8139
+ ) : null,
6471
8140
  searchRequest ? reactDom.createPortal(
6472
8141
  /* @__PURE__ */ jsxRuntime.jsx(ReactListTableSearchDialog, { request: searchRequest }),
6473
8142
  portalContainer