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