@canvas-components/react-list-table 0.3.43 → 0.3.45

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