@veltra/sheet 2.3.3 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/components/report/binding-badge.js +23 -5
  2. package/dist/components/report/designer/drill-dialog.js +258 -0
  3. package/dist/components/report/designer/float-panel.js +26 -14
  4. package/dist/components/report/print.js +39 -0
  5. package/dist/components/report/report-designer.js +56 -21
  6. package/dist/components/report/report-viewer.js +173 -44
  7. package/dist/components/report/style2.css +91 -0
  8. package/dist/components/report/use-report-designer.js +2 -1
  9. package/dist/components/report/use-report-viewer.js +88 -3
  10. package/dist/components/sheet/insert-image.js +1 -1
  11. package/dist/components/sheet/popups/import.worker.js +2 -3
  12. package/dist/components/sheet/use-sheet-state.js +2 -2
  13. package/dist/index.d.ts +5 -3
  14. package/dist/index.js +4 -2
  15. package/dist/report/drill.d.ts +48 -0
  16. package/dist/report/drill.js +78 -0
  17. package/dist/report/export-xlsx.d.ts +3 -7
  18. package/dist/report/export-xlsx.js +6 -85
  19. package/dist/report/index.d.ts +5 -3
  20. package/dist/report/print.d.ts +23 -0
  21. package/dist/report/print.js +197 -0
  22. package/dist/report/render/aggregate.js +25 -1
  23. package/dist/report/types.d.ts +19 -1
  24. package/dist/tools/download.js +2 -2
  25. package/dist/types/report-designer.d.ts +13 -0
  26. package/dist/types/report-viewer.d.ts +19 -0
  27. package/package.json +6 -9
  28. package/src/components/report/__test__/binding-badge.test.ts +92 -0
  29. package/src/components/report/__test__/report-designer.test.ts +98 -3
  30. package/src/components/report/__test__/report-drill.test.ts +692 -0
  31. package/src/components/report/__test__/report-viewer.test.ts +43 -0
  32. package/src/components/report/__test__/use-report-designer.test.ts +108 -1
  33. package/src/components/report/binding-badge.ts +35 -5
  34. package/src/components/report/designer/drill-dialog.vue +245 -0
  35. package/src/components/report/designer/float-panel.vue +12 -0
  36. package/src/components/report/print.ts +44 -0
  37. package/src/components/report/report-designer.vue +35 -2
  38. package/src/components/report/report-viewer.vue +171 -18
  39. package/src/components/report/style-designer.scss +66 -0
  40. package/src/components/report/style-viewer.scss +40 -0
  41. package/src/components/report/use-report-designer.ts +8 -1
  42. package/src/components/report/use-report-viewer.ts +150 -11
  43. package/src/components/sheet/insert-image.ts +1 -1
  44. package/src/components/sheet/popups/export-popup.vue +1 -1
  45. package/src/components/sheet/popups/import.worker.ts +7 -10
  46. package/src/components/sheet/use-sheet-state.ts +2 -2
  47. package/src/report/__test__/drill.test.ts +194 -0
  48. package/src/report/__test__/export-xlsx.test.ts +3 -25
  49. package/src/report/__test__/print.test.ts +170 -0
  50. package/src/report/__test__/render.test.ts +26 -0
  51. package/src/report/drill.ts +112 -0
  52. package/src/report/export-xlsx.ts +5 -103
  53. package/src/report/index.ts +4 -1
  54. package/src/report/print.ts +234 -0
  55. package/src/report/render/aggregate.ts +28 -0
  56. package/src/report/types.ts +20 -0
  57. package/src/tools/__test__/builtin.test.ts +1 -1
  58. package/src/tools/download.ts +2 -2
  59. package/src/tools/export.worker.ts +2 -2
  60. package/src/types/report-designer.ts +18 -1
  61. package/src/types/report-viewer.ts +18 -1
@@ -1,22 +1,34 @@
1
+ import { buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams } from "../../report/drill.js";
1
2
  import { renderReport, resolveFilledColWidths } from "../../report/render/index.js";
2
3
  import { fetchTemplateRecords, resolveParamDefaults, resolveTemplateParams } from "../../report/template.js";
3
4
  import { computed, ref, shallowRef, watch } from "vue";
5
+ import { cellKey } from "@veltra/sheet-core";
4
6
  //#region src/components/report/use-report-viewer.ts
5
7
  /**
6
8
  * UReportViewer 的 headless 编排:参数提取 → 取数 → renderReport 展开。
7
9
  * 不持有 DOM / 网格引用;填充快照经 `filledSnapshot` 交给组件壳应用。
10
+ * 下钻:openMode 'switch' 栈式切换当前层;'dialog' 由组件壳解析目标后嵌套独立查看器。
11
+ * 导出 / 打印始终作用于当前可见层。
8
12
  */
9
13
  function useReportViewer(props) {
10
14
  const loading = ref(false);
11
15
  const error = shallowRef(null);
12
16
  const filledSnapshot = shallowRef(null);
13
17
  const filledColWidths = shallowRef(void 0);
14
- const params = computed(() => resolveTemplateParams(props.template));
18
+ const drillStack = shallowRef(null);
19
+ const drillHits = shallowRef(/* @__PURE__ */ new Map());
20
+ const currentTemplate = computed(() => {
21
+ const stack = drillStack.value;
22
+ return stack ? currentDrillLayer(stack).template : props.template;
23
+ });
24
+ const drillDepth = computed(() => (drillStack.value?.length ?? 1) - 1);
25
+ const canDrillBack = computed(() => drillDepth.value > 0);
26
+ const params = computed(() => resolveTemplateParams(currentTemplate.value));
15
27
  const values = shallowRef({});
16
28
  let fetchSeq = 0;
17
29
  async function refresh() {
18
30
  const current = ++fetchSeq;
19
- const template = props.template;
31
+ const template = currentTemplate.value;
20
32
  loading.value = true;
21
33
  error.value = null;
22
34
  const result = await fetchTemplateRecords(props.connector, template, values.value);
@@ -29,15 +41,81 @@ function useReportViewer(props) {
29
41
  }
30
42
  filledSnapshot.value = renderReport(template, result.data);
31
43
  filledColWidths.value = template.colWidths?.length ? resolveFilledColWidths(template, result.data, template.colWidths) : void 0;
44
+ drillHits.value = props.resolveTemplate ? buildDrillHitMap(template, result.data) : /* @__PURE__ */ new Map();
45
+ }
46
+ /** 切层共有收尾:清填充结果与命中索引,写入新层参数并重新取数 */
47
+ function transitionTo(layerParams) {
48
+ filledSnapshot.value = null;
49
+ filledColWidths.value = void 0;
50
+ drillHits.value = /* @__PURE__ */ new Map();
51
+ values.value = layerParams;
52
+ return refresh();
53
+ }
54
+ async function resolveDrillTarget(config, record) {
55
+ const resolve = props.resolveTemplate;
56
+ if (!resolve) return null;
57
+ let target;
58
+ try {
59
+ target = await resolve(config.target);
60
+ } catch (err) {
61
+ error.value = {
62
+ code: "DRILL_RESOLVE_FAILED",
63
+ message: err instanceof Error ? err.message : String(err)
64
+ };
65
+ return null;
66
+ }
67
+ if (!target) {
68
+ error.value = {
69
+ code: "DRILL_RESOLVE_FAILED",
70
+ message: `下钻目标模板解析失败:${config.target}`
71
+ };
72
+ return null;
73
+ }
74
+ error.value = null;
75
+ return {
76
+ template: target,
77
+ params: {
78
+ ...resolveParamDefaults(resolveTemplateParams(target)),
79
+ ...resolveDrillParams(config, record)
80
+ }
81
+ };
82
+ }
83
+ async function drillInto(config, record) {
84
+ const next = await resolveDrillTarget(config, record);
85
+ if (!next) return;
86
+ const base = drillStack.value ?? createDrillStack({
87
+ template: props.template,
88
+ params: values.value
89
+ });
90
+ drillStack.value = pushDrillLayer(base, {
91
+ template: next.template,
92
+ params: next.params
93
+ }, values.value);
94
+ await transitionTo(next.params);
95
+ }
96
+ async function drillBack() {
97
+ const stack = drillStack.value;
98
+ if (!stack || stack.length <= 1) return;
99
+ const next = popDrillLayer(stack);
100
+ drillStack.value = next;
101
+ await transitionTo({ ...currentDrillLayer(next).params });
102
+ }
103
+ function resolveDrillHit(addr) {
104
+ return drillHits.value.get(cellKey(addr)) ?? null;
32
105
  }
33
106
  function setValues(next) {
34
107
  values.value = next;
35
108
  refresh();
36
109
  }
37
110
  watch(() => props.template, () => {
111
+ drillStack.value = null;
112
+ drillHits.value = /* @__PURE__ */ new Map();
38
113
  filledSnapshot.value = null;
39
114
  filledColWidths.value = void 0;
40
- values.value = resolveParamDefaults(params.value);
115
+ values.value = {
116
+ ...resolveParamDefaults(params.value),
117
+ ...props.initialValues
118
+ };
41
119
  refresh();
42
120
  }, { immediate: true });
43
121
  return {
@@ -47,6 +125,13 @@ function useReportViewer(props) {
47
125
  error,
48
126
  filledSnapshot,
49
127
  filledColWidths,
128
+ currentTemplate,
129
+ drillDepth,
130
+ canDrillBack,
131
+ resolveDrillHit,
132
+ resolveDrillTarget,
133
+ drillInto,
134
+ drillBack,
50
135
  refresh,
51
136
  setValues
52
137
  };
@@ -18,7 +18,7 @@ const EXT_TO_TYPE = {
18
18
  svg: "svg",
19
19
  webp: "webp"
20
20
  };
21
- /** MIME → hucre 图片类型;MIME 为空时回落扩展名 */
21
+ /** MIME → sheet-core 图片类型(core/image 的 SheetImageType);MIME 为空时回落扩展名 */
22
22
  function resolveImageType(file) {
23
23
  const mime = file.type.trim().toLowerCase();
24
24
  if (mime && MIME_TO_TYPE[mime]) return MIME_TO_TYPE[mime];
@@ -3,10 +3,9 @@ self.onmessage = (e) => {
3
3
  const { buffer } = e.data;
4
4
  (async () => {
5
5
  try {
6
- const [{ readXlsx }, { buildWorkbookFromHucre, XLSX_READ_OPTIONS }] = await Promise.all([import("hucre/xlsx"), import("@veltra/sheet-core/core/io/import")]);
7
- const hucreWb = await readXlsx(new Uint8Array(buffer), XLSX_READ_OPTIONS);
6
+ const { importXlsx } = await import("@veltra/sheet-core/core/io/import");
8
7
  let lastPercent = -1;
9
- const wb = buildWorkbookFromHucre(hucreWb, (done, total) => {
8
+ const wb = await importXlsx(new Uint8Array(buffer), (done, total) => {
10
9
  const percent = total > 0 ? Math.floor(done / total * 10) : 10;
11
10
  if (percent !== lastPercent || done === total) {
12
11
  lastPercent = percent;
@@ -78,8 +78,8 @@ function useSheetState(props, emit, hooks) {
78
78
  ];
79
79
  }
80
80
  /**
81
- * 工作簿内容被结构性替换后同步(如导入 xlsx 的 replaceWorkbook):
82
- * replaceWorkbook 未必触发 active-sheet-change(同 index),需显式同步 tabs、
81
+ * 工作簿内容被结构性替换后同步(如导入 xlsx 的 replaceWorkbookWithSnapshots):
82
+ * 整簿替换未必触发 active-sheet-change(同 index),需显式同步 tabs、
83
83
  * 重绑 sheet 事件并重建网格。
84
84
  */
85
85
  function syncFromWorkbook() {
package/dist/index.d.ts CHANGED
@@ -4,18 +4,20 @@ import _sfc_main from "./components/report/report-designer.js";
4
4
  import { SheetContext, createSheetContext } from "./tools/context.js";
5
5
  import { SheetTool, SheetToolGroup, SheetToolPopupType, defaultToolRegistry, registerTool, unregisterTool } from "./tools/registry.js";
6
6
  import { SheetEmits, SheetExposed, SheetProps, _SheetExposed } from "./types/sheet.js";
7
- import { ConditionalOperator, ConditionalRule, DatasetCatalogItem, DatasetField, DatasetRecords, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, ReportAggregate, ReportBinding, ReportExpand, ReportPreset, ReportSort } from "./report/types.js";
7
+ import { ConditionalOperator, ConditionalRule, DatasetCatalogItem, DatasetField, DatasetRecords, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, ReportAggregate, ReportBinding, ReportDrillConfig, ReportExpand, ReportPreset, ReportSort, ReportTemplateListItem } from "./report/types.js";
8
8
  import { InferParentOptions, ListParentCandidateOptions, REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, parseCellAddress, prefersGroupParent, presetBindingPatch, presetStillApplies, setBindingCatalog } from "./report/binding.js";
9
9
  import { ConditionalEvalContext, evaluateCondition, evaluateConditionalStyle, resolveRuleCompareValue, toComparableNumber } from "./report/rules/evaluate.js";
10
10
  import { buildParamDefs, extractParamIds, resolveBoundDatasetParams } from "./report/params.js";
11
- import { ReportColWidthEntry, buildColumnDefs, exportFilledReportXlsx, pxToExcelColWidth } from "./report/export-xlsx.js";
11
+ import { ReportColWidthEntry, exportFilledReportXlsx } from "./report/export-xlsx.js";
12
12
  import { mapFilledColWidths } from "./report/render/builder.js";
13
13
  import { renderReport, resolveFilledColWidths } from "./report/render/index.js";
14
14
  import { ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, QueryResult, Result, createHttpConnector, resolvePortOnTypeChange } from "./report/connector.js";
15
15
  import { IncompatibleTemplateVersionError, REPORT_TEMPLATE_VERSION, ReportDatasetDef, ReportTemplate, assertCompatibleTemplateVersion, createReportTemplate, fetchTemplateRecords, getBoundDatasetIds, getTemplateDatasets, resolveParamDefaults, resolveTemplateParams } from "./report/template.js";
16
16
  import { parseDateRangeValue, patchParamValues, resolveNumberParamValue } from "./report/filter-bar.js";
17
+ import { DrillHit, DrillStack, DrillStackLayer, ResolveReportTemplate, buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams } from "./report/drill.js";
18
+ import { ReportPrintOptions, buildFilledReportPrintHtml } from "./report/print.js";
17
19
  import "./report/index.js";
18
20
  import { ReportViewerExposed, ReportViewerProps, _ReportViewerExposed } from "./types/report-viewer.js";
19
21
  import { ReportDesignerEmits, ReportDesignerExposed, ReportDesignerProps, _ReportDesignerExposed } from "./types/report-designer.js";
20
22
  import "./types/index.js";
21
- export { type ConditionalEvalContext, ConditionalOperator, ConditionalRule, ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, DatasetCatalogItem, DatasetField, DatasetRecords, IncompatibleTemplateVersionError, InferParentOptions, ListParentCandidateOptions, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, QueryResult, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, ReportAggregate, ReportBinding, ReportColWidthEntry, ReportDatasetDef, type ReportDesignerEmits, type ReportDesignerExposed, type ReportDesignerProps, ReportExpand, ReportPreset, ReportSort, ReportTemplate, type ReportViewerExposed, type ReportViewerProps, Result, type SheetContext, type SheetEmits, type SheetExposed, type SheetProps, type SheetTool, type SheetToolGroup, type SheetToolPopupType, _sfc_main as UReportDesigner, _sfc_main$1 as UReportViewer, _sfc_main$2 as USheet, type _ReportDesignerExposed, type _ReportViewerExposed, type _SheetExposed, applyReportPreset, assertCompatibleTemplateVersion, buildColumnDefs, buildParamDefs, createHttpConnector, createReportBinding, createReportTemplate, createSheetContext, defaultToolRegistry, evaluateCondition, evaluateConditionalStyle, exportFilledReportXlsx, extractParamIds, fetchTemplateRecords, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, prefersGroupParent, presetBindingPatch, presetStillApplies, pxToExcelColWidth, registerTool, renderReport, resolveBoundDatasetParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber, unregisterTool };
23
+ export { type ConditionalEvalContext, ConditionalOperator, ConditionalRule, ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, DatasetCatalogItem, DatasetField, DatasetRecords, DrillHit, DrillStack, DrillStackLayer, IncompatibleTemplateVersionError, InferParentOptions, ListParentCandidateOptions, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, QueryResult, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, ReportAggregate, ReportBinding, ReportColWidthEntry, ReportDatasetDef, type ReportDesignerEmits, type ReportDesignerExposed, type ReportDesignerProps, ReportDrillConfig, ReportExpand, ReportPreset, ReportPrintOptions, ReportSort, ReportTemplate, ReportTemplateListItem, type ReportViewerExposed, type ReportViewerProps, ResolveReportTemplate, Result, type SheetContext, type SheetEmits, type SheetExposed, type SheetProps, type SheetTool, type SheetToolGroup, type SheetToolPopupType, _sfc_main as UReportDesigner, _sfc_main$1 as UReportViewer, _sfc_main$2 as USheet, type _ReportDesignerExposed, type _ReportViewerExposed, type _SheetExposed, applyReportPreset, assertCompatibleTemplateVersion, buildDrillHitMap, buildFilledReportPrintHtml, buildParamDefs, createDrillStack, createHttpConnector, createReportBinding, createReportTemplate, createSheetContext, currentDrillLayer, defaultToolRegistry, evaluateCondition, evaluateConditionalStyle, exportFilledReportXlsx, extractParamIds, fetchTemplateRecords, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, popDrillLayer, prefersGroupParent, presetBindingPatch, presetStillApplies, pushDrillLayer, registerTool, renderReport, resolveBoundDatasetParams, resolveDrillParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber, unregisterTool };
package/dist/index.js CHANGED
@@ -2,9 +2,11 @@ import { defaultToolRegistry, registerTool, unregisterTool } from "./tools/regis
2
2
  import "./tools/builtin.js";
3
3
  import { createSheetContext } from "./tools/context.js";
4
4
  import _sfc_main$2 from "./components/sheet/sheet.js";
5
- import { buildColumnDefs, exportFilledReportXlsx, pxToExcelColWidth } from "./report/export-xlsx.js";
5
+ import { exportFilledReportXlsx } from "./report/export-xlsx.js";
6
+ import { buildFilledReportPrintHtml } from "./report/print.js";
6
7
  import { parseDateRangeValue, patchParamValues, resolveNumberParamValue } from "./report/filter-bar.js";
7
8
  import { REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, parseCellAddress, prefersGroupParent, presetBindingPatch, presetStillApplies, setBindingCatalog } from "./report/binding.js";
9
+ import { buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams } from "./report/drill.js";
8
10
  import { evaluateCondition, evaluateConditionalStyle, resolveRuleCompareValue, toComparableNumber } from "./report/rules/evaluate.js";
9
11
  import { mapFilledColWidths } from "./report/render/builder.js";
10
12
  import { renderReport, resolveFilledColWidths } from "./report/render/index.js";
@@ -13,4 +15,4 @@ import { IncompatibleTemplateVersionError, REPORT_TEMPLATE_VERSION, assertCompat
13
15
  import _sfc_main$1 from "./components/report/report-viewer.js";
14
16
  import { DEFAULT_CONNECTION_PORTS, createHttpConnector, resolvePortOnTypeChange } from "./report/connector.js";
15
17
  import _sfc_main from "./components/report/report-designer.js";
16
- export { DEFAULT_CONNECTION_PORTS, IncompatibleTemplateVersionError, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, _sfc_main as UReportDesigner, _sfc_main$1 as UReportViewer, _sfc_main$2 as USheet, applyReportPreset, assertCompatibleTemplateVersion, buildColumnDefs, buildParamDefs, createHttpConnector, createReportBinding, createReportTemplate, createSheetContext, defaultToolRegistry, evaluateCondition, evaluateConditionalStyle, exportFilledReportXlsx, extractParamIds, fetchTemplateRecords, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, prefersGroupParent, presetBindingPatch, presetStillApplies, pxToExcelColWidth, registerTool, renderReport, resolveBoundDatasetParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber, unregisterTool };
18
+ export { DEFAULT_CONNECTION_PORTS, IncompatibleTemplateVersionError, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, _sfc_main as UReportDesigner, _sfc_main$1 as UReportViewer, _sfc_main$2 as USheet, applyReportPreset, assertCompatibleTemplateVersion, buildDrillHitMap, buildFilledReportPrintHtml, buildParamDefs, createDrillStack, createHttpConnector, createReportBinding, createReportTemplate, createSheetContext, currentDrillLayer, defaultToolRegistry, evaluateCondition, evaluateConditionalStyle, exportFilledReportXlsx, extractParamIds, fetchTemplateRecords, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, popDrillLayer, prefersGroupParent, presetBindingPatch, presetStillApplies, pushDrillLayer, registerTool, renderReport, resolveBoundDatasetParams, resolveDrillParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber, unregisterTool };
@@ -0,0 +1,48 @@
1
+ import { DatasetRecords, ParamValues, ReportDrillConfig } from "./types.js";
2
+ import { ReportTemplate } from "./template.js";
3
+ import { SheetSnapshot } from "@veltra/sheet-core";
4
+ //#region src/report/drill.d.ts
5
+ /**
6
+ * 宿主模板解析契约:按下钻 target 引用取回目标模板(允许同步/异步)。
7
+ * 失败抛错——查看器提示可读错误并停留当前报;设计器配置对话框据此解析目标模板查询参数。
8
+ */
9
+ type ResolveReportTemplate = (ref: string) => ReportTemplate | Promise<ReportTemplate>;
10
+ /**
11
+ * 按下钻映射从该格对应记录取值,生成详情报 Filter Bar 参数值。
12
+ * 记录缺字段(值为 `undefined`)时跳过对应参数,由详情报回退默认值;空映射返回空参数。
13
+ */
14
+ declare function resolveDrillParams(config: ReportDrillConfig, record: Record<string, unknown>): ParamValues;
15
+ /** 下钻栈层:一张报表模板 + 当时 Filter Bar 参数值(回退时据此恢复并重新取数) */
16
+ interface DrillStackLayer {
17
+ template: ReportTemplate;
18
+ params: ParamValues;
19
+ }
20
+ /**
21
+ * 下钻栈:自根(初始报表)到顶的层序列,至少一层。
22
+ * 只经下方纯函数做不可变更新(返回新栈),便于组件层直接挂响应式。
23
+ */
24
+ type DrillStack = DrillStackLayer[];
25
+ /** 以初始报表为根层创建下钻栈 */
26
+ declare function createDrillStack(root: DrillStackLayer): DrillStack;
27
+ /**
28
+ * 压入详情报新层并使其成为当前层;`currentParams` 把当前层参数定格为离开时的值
29
+ * (缺省保留原值)。指向自身或成环不做检测,照常压栈,靠 pop 逐级退出。
30
+ */
31
+ declare function pushDrillLayer(stack: DrillStack, next: DrillStackLayer, currentParams?: ParamValues): DrillStack;
32
+ /** 弹出当前层返回上一层;仅剩根层时原样返回(查看器始终保留一张报表) */
33
+ declare function popDrillLayer(stack: DrillStack): DrillStack;
34
+ /** 当前层(栈顶) */
35
+ declare function currentDrillLayer(stack: DrillStack): DrillStackLayer;
36
+ /** 下钻命中:物理格对应的下钻配置与该格记录 */
37
+ interface DrillHit {
38
+ config: ReportDrillConfig;
39
+ record: Record<string, unknown>;
40
+ }
41
+ /**
42
+ * 构建填充报表的物理格 → 下钻命中索引(每次成功取数后重建)。
43
+ * 仅含配了下钻的绑定格落点(含分组/汇总格与展开后的实例格,合并跨度内每格都命中);
44
+ * 记录由 `resolvePlacementContext` 解析:list 明细取源数据行,分组/汇总取分组上下文。
45
+ */
46
+ declare function buildDrillHitMap(template: SheetSnapshot, data: DatasetRecords): Map<number, DrillHit>;
47
+ //#endregion
48
+ export { DrillHit, DrillStack, DrillStackLayer, ResolveReportTemplate, buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams };
@@ -0,0 +1,78 @@
1
+ import { buildTemplateIndex } from "./render/template-index.js";
2
+ import { computeExpansionLayout } from "./render/coordinate.js";
3
+ import { AggregateIndex, resolvePlacementContext } from "./render/aggregate.js";
4
+ import { cellKey } from "@veltra/sheet-core";
5
+ //#region src/report/drill.ts
6
+ /**
7
+ * 按下钻映射从该格对应记录取值,生成详情报 Filter Bar 参数值。
8
+ * 记录缺字段(值为 `undefined`)时跳过对应参数,由详情报回退默认值;空映射返回空参数。
9
+ */
10
+ function resolveDrillParams(config, record) {
11
+ const values = {};
12
+ for (const [field, paramId] of Object.entries(config.mapping)) {
13
+ const value = record[field];
14
+ if (value === void 0) continue;
15
+ values[paramId] = value;
16
+ }
17
+ return values;
18
+ }
19
+ /** 以初始报表为根层创建下钻栈 */
20
+ function createDrillStack(root) {
21
+ return [{
22
+ template: root.template,
23
+ params: { ...root.params }
24
+ }];
25
+ }
26
+ /**
27
+ * 压入详情报新层并使其成为当前层;`currentParams` 把当前层参数定格为离开时的值
28
+ * (缺省保留原值)。指向自身或成环不做检测,照常压栈,靠 pop 逐级退出。
29
+ */
30
+ function pushDrillLayer(stack, next, currentParams) {
31
+ const top = stack[stack.length - 1];
32
+ const layers = currentParams ? [...stack.slice(0, -1), {
33
+ template: top.template,
34
+ params: { ...currentParams }
35
+ }] : [...stack];
36
+ layers.push({
37
+ template: next.template,
38
+ params: { ...next.params }
39
+ });
40
+ return layers;
41
+ }
42
+ /** 弹出当前层返回上一层;仅剩根层时原样返回(查看器始终保留一张报表) */
43
+ function popDrillLayer(stack) {
44
+ if (stack.length <= 1) return stack;
45
+ return stack.slice(0, -1);
46
+ }
47
+ /** 当前层(栈顶) */
48
+ function currentDrillLayer(stack) {
49
+ return stack[stack.length - 1];
50
+ }
51
+ /**
52
+ * 构建填充报表的物理格 → 下钻命中索引(每次成功取数后重建)。
53
+ * 仅含配了下钻的绑定格落点(含分组/汇总格与展开后的实例格,合并跨度内每格都命中);
54
+ * 记录由 `resolvePlacementContext` 解析:list 明细取源数据行,分组/汇总取分组上下文。
55
+ */
56
+ function buildDrillHitMap(template, data) {
57
+ const hits = /* @__PURE__ */ new Map();
58
+ const index = buildTemplateIndex(template);
59
+ const layout = computeExpansionLayout(index, data);
60
+ const aggregateIndex = new AggregateIndex(data);
61
+ for (const placement of layout.placements) {
62
+ const config = placement.binding?.drill;
63
+ if (!config) continue;
64
+ const record = resolvePlacementContext(placement, index, data, aggregateIndex);
65
+ if (!record) continue;
66
+ const hit = {
67
+ config,
68
+ record
69
+ };
70
+ for (let row = placement.physical.start.row; row <= placement.physical.end.row; row++) for (let col = placement.physical.start.col; col <= placement.physical.end.col; col++) hits.set(cellKey({
71
+ row,
72
+ col
73
+ }), hit);
74
+ }
75
+ return hits;
76
+ }
77
+ //#endregion
78
+ export { buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams };
@@ -1,17 +1,13 @@
1
1
  import { Sheet } from "@veltra/sheet-core";
2
- import { ColumnDef } from "hucre";
3
2
  //#region src/report/export-xlsx.d.ts
4
3
  /** 列宽条目:模型列索引 → 像素宽(与 SheetSnapshot.colWidths 同构) */
5
4
  type ReportColWidthEntry = readonly [number, number];
6
- /** VTable 像素列宽 → Excel 字符宽度(近似换算) */
7
- declare function pxToExcelColWidth(px: number): number;
8
- /** 从列宽条目构建 hucre ColumnDef */
9
- declare function buildColumnDefs(colWidths: ReadonlyArray<ReportColWidthEntry>): ColumnDef[];
10
5
  /**
11
- * 将已填充的 Sheet(Filled Report)导出为保真 XLSX(合并 / 样式 / 行高 / 列宽)。
6
+ * 将已填充的 Sheet(Filled Report)导出为保真 XLSX(合并 / 样式 / 行高 / 列宽 / 浮动图)。
7
+ * 组装与序列化委托 sheet-core `exportSheetXlsx`(与 `exportWorkbookXlsx` 同一套单表逻辑);
12
8
  * 条件样式颜色已在 renderReport 展开阶段打平进 StylePool(ADR-0001 决策 2)。
13
9
  * 列宽取自 sheet 模型(`getColWidths`)。
14
10
  */
15
11
  declare function exportFilledReportXlsx(sheet: Sheet): Promise<Uint8Array>;
16
12
  //#endregion
17
- export { ReportColWidthEntry, buildColumnDefs, exportFilledReportXlsx, pxToExcelColWidth };
13
+ export { ReportColWidthEntry, exportFilledReportXlsx };
@@ -1,92 +1,13 @@
1
- import { rangeToHucre, styleToHucre } from "@veltra/sheet-core/core/io/export";
2
- import { writeXlsx } from "hucre/xlsx";
1
+ import { exportSheetXlsx } from "@veltra/sheet-core/core/io/export";
3
2
  //#region src/report/export-xlsx.ts
4
- /** 像素 → Excel points */
5
- function pxToPt(px) {
6
- return px * .75;
7
- }
8
- /** VTable 像素列宽 → Excel 字符宽度(近似换算) */
9
- function pxToExcelColWidth(px) {
10
- return Math.max(1, Math.round((px - 5) / 7));
11
- }
12
- /** 从列宽条目构建 hucre ColumnDef */
13
- function buildColumnDefs(colWidths) {
14
- if (colWidths.length === 0) return [];
15
- const maxCol = Math.max(...colWidths.map(([col]) => col));
16
- const columns = Array.from({ length: maxCol + 1 }, () => ({}));
17
- for (const [col, width] of colWidths) columns[col] = { width: pxToExcelColWidth(width) };
18
- return columns;
19
- }
20
3
  /**
21
- * 将已填充的 Sheet(Filled Report)导出为保真 XLSX(合并 / 样式 / 行高 / 列宽)。
4
+ * 将已填充的 Sheet(Filled Report)导出为保真 XLSX(合并 / 样式 / 行高 / 列宽 / 浮动图)。
5
+ * 组装与序列化委托 sheet-core `exportSheetXlsx`(与 `exportWorkbookXlsx` 同一套单表逻辑);
22
6
  * 条件样式颜色已在 renderReport 展开阶段打平进 StylePool(ADR-0001 决策 2)。
23
7
  * 列宽取自 sheet 模型(`getColWidths`)。
24
8
  */
25
- async function exportFilledReportXlsx(sheet) {
26
- const widths = [...sheet.getColWidths()];
27
- let maxRow = -1;
28
- let maxCol = -1;
29
- for (const [addr] of sheet.store.entries()) {
30
- if (addr.row > maxRow) maxRow = addr.row;
31
- if (addr.col > maxCol) maxCol = addr.col;
32
- }
33
- for (const [row] of sheet.getRowHeights()) if (row > maxRow) maxRow = row;
34
- for (const [col] of widths) if (col > maxCol) maxCol = col;
35
- const rows = maxRow < 0 ? [] : Array.from({ length: maxRow + 1 }, () => Array.from({ length: maxCol + 1 }, () => null));
36
- const cells = /* @__PURE__ */ new Map();
37
- for (const [addr, data] of sheet.store.entries()) {
38
- const row = rows[addr.row];
39
- const key = `${addr.row},${addr.col}`;
40
- const cell = {};
41
- const style = sheet.getEffectiveStyle(addr);
42
- if (style) cell.style = styleToHucre(style);
43
- if (data.f != null && data.f !== "") {
44
- cell.formula = data.f;
45
- if (data.v != null) cell.formulaResult = data.v;
46
- row[addr.col] = data.v ?? null;
47
- cells.set(key, cell);
48
- continue;
49
- }
50
- if (data.t === "e") {
51
- cell.value = data.v;
52
- cell.type = "error";
53
- row[addr.col] = null;
54
- cells.set(key, cell);
55
- continue;
56
- }
57
- if (data.t === "d") {
58
- cell.value = data.v;
59
- cell.type = "number";
60
- cell.style = {
61
- ...cell.style,
62
- numFmt: "yyyy-mm-dd"
63
- };
64
- row[addr.col] = null;
65
- cells.set(key, cell);
66
- continue;
67
- }
68
- row[addr.col] = data.v ?? null;
69
- if (Object.keys(cell).length > 0) cells.set(key, cell);
70
- }
71
- const writeSheet = {
72
- name: sheet.name || "报表",
73
- rows,
74
- ...cells.size > 0 ? { cells } : {},
75
- ...sheet.merges.size > 0 ? { merges: sheet.merges.getMerges().map((range) => rangeToHucre(range)) } : {},
76
- ...widths.length > 0 ? { columns: buildColumnDefs(widths) } : {}
77
- };
78
- const frozen = sheet.frozen;
79
- if (frozen.rows > 0 || frozen.cols > 0) writeSheet.freezePane = {
80
- rows: frozen.rows,
81
- columns: frozen.cols
82
- };
83
- const rowDefs = /* @__PURE__ */ new Map();
84
- for (const [row, height] of sheet.getRowHeights()) rowDefs.set(row, { height: pxToPt(height) });
85
- if (rowDefs.size > 0) writeSheet.rowDefs = rowDefs;
86
- return writeXlsx({
87
- sheets: [writeSheet],
88
- activeSheet: 0
89
- });
9
+ function exportFilledReportXlsx(sheet) {
10
+ return exportSheetXlsx(sheet, { fallbackName: "报表" });
90
11
  }
91
12
  //#endregion
92
- export { buildColumnDefs, exportFilledReportXlsx, pxToExcelColWidth };
13
+ export { exportFilledReportXlsx };
@@ -1,12 +1,14 @@
1
- import { ConditionalOperator, ConditionalRule, DatasetCatalogItem, DatasetField, DatasetRecords, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, ReportAggregate, ReportBinding, ReportExpand, ReportPreset, ReportSort } from "./types.js";
1
+ import { ConditionalOperator, ConditionalRule, DatasetCatalogItem, DatasetField, DatasetRecords, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, ReportAggregate, ReportBinding, ReportDrillConfig, ReportExpand, ReportPreset, ReportSort, ReportTemplateListItem } from "./types.js";
2
2
  import { InferParentOptions, ListParentCandidateOptions, REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, parseCellAddress, prefersGroupParent, presetBindingPatch, presetStillApplies, setBindingCatalog } from "./binding.js";
3
3
  import { ConditionalEvalContext, evaluateCondition, evaluateConditionalStyle, resolveRuleCompareValue, toComparableNumber } from "./rules/evaluate.js";
4
4
  import "./rules/index.js";
5
5
  import { buildParamDefs, extractParamIds, resolveBoundDatasetParams } from "./params.js";
6
- import { ReportColWidthEntry, buildColumnDefs, exportFilledReportXlsx, pxToExcelColWidth } from "./export-xlsx.js";
6
+ import { ReportColWidthEntry, exportFilledReportXlsx } from "./export-xlsx.js";
7
7
  import { mapFilledColWidths } from "./render/builder.js";
8
8
  import { renderReport, resolveFilledColWidths } from "./render/index.js";
9
9
  import { ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, QueryResult, Result, createHttpConnector, resolvePortOnTypeChange } from "./connector.js";
10
10
  import { IncompatibleTemplateVersionError, REPORT_TEMPLATE_VERSION, ReportDatasetDef, ReportTemplate, assertCompatibleTemplateVersion, createReportTemplate, fetchTemplateRecords, getBoundDatasetIds, getTemplateDatasets, resolveParamDefaults, resolveTemplateParams } from "./template.js";
11
11
  import { parseDateRangeValue, patchParamValues, resolveNumberParamValue } from "./filter-bar.js";
12
- export { type ConditionalEvalContext, ConditionalOperator, ConditionalRule, ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, DatasetCatalogItem, DatasetField, DatasetRecords, IncompatibleTemplateVersionError, InferParentOptions, ListParentCandidateOptions, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, QueryResult, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, ReportAggregate, ReportBinding, ReportColWidthEntry, ReportDatasetDef, ReportExpand, ReportPreset, ReportSort, ReportTemplate, Result, applyReportPreset, assertCompatibleTemplateVersion, buildColumnDefs, buildParamDefs, createHttpConnector, createReportBinding, createReportTemplate, evaluateCondition, evaluateConditionalStyle, exportFilledReportXlsx, extractParamIds, fetchTemplateRecords, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, prefersGroupParent, presetBindingPatch, presetStillApplies, pxToExcelColWidth, renderReport, resolveBoundDatasetParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber };
12
+ import { DrillHit, DrillStack, DrillStackLayer, ResolveReportTemplate, buildDrillHitMap, createDrillStack, currentDrillLayer, popDrillLayer, pushDrillLayer, resolveDrillParams } from "./drill.js";
13
+ import { ReportPrintOptions, buildFilledReportPrintHtml } from "./print.js";
14
+ export { type ConditionalEvalContext, ConditionalOperator, ConditionalRule, ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, DatasetCatalogItem, DatasetField, DatasetRecords, DrillHit, DrillStack, DrillStackLayer, IncompatibleTemplateVersionError, InferParentOptions, ListParentCandidateOptions, ParamValues, QueryParamDef, QueryParamOption, QueryParamType, QueryResult, REPORT_META_NAMESPACE, REPORT_TEMPLATE_VERSION, ReportAggregate, ReportBinding, ReportColWidthEntry, ReportDatasetDef, ReportDrillConfig, ReportExpand, ReportPreset, ReportPrintOptions, ReportSort, ReportTemplate, ReportTemplateListItem, ResolveReportTemplate, Result, applyReportPreset, assertCompatibleTemplateVersion, buildDrillHitMap, buildFilledReportPrintHtml, buildParamDefs, createDrillStack, createHttpConnector, createReportBinding, createReportTemplate, currentDrillLayer, evaluateCondition, evaluateConditionalStyle, exportFilledReportXlsx, extractParamIds, fetchTemplateRecords, formatBindingPlaceholder, formatBindingPlaceholderParts, formatCellAddress, formatParentCandidateLabel, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferParentsForPreset, inferReportPreset, inferRowParentCandidate, isColGroupBinding, isExpansionBandCol, isExpansionBandRow, isHorizontalExpandBinding, isReductionAggregate, isRowGroupBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, popDrillLayer, prefersGroupParent, presetBindingPatch, presetStillApplies, pushDrillLayer, renderReport, resolveBoundDatasetParams, resolveDrillParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber };
@@ -0,0 +1,23 @@
1
+ import { Sheet } from "@veltra/sheet-core";
2
+ //#region src/report/print.d.ts
3
+ /** 报表打印选项 */
4
+ interface ReportPrintOptions {
5
+ /** 打印文档标题(打印对话框标题 / 另存 PDF 文件名);缺省取 sheet 名,再回落「报表」 */
6
+ title?: string;
7
+ /** 纸张方向(@page size),默认 portrait */
8
+ orientation?: 'portrait' | 'landscape';
9
+ }
10
+ /**
11
+ * 将已填充的 Sheet(Filled Report)构建为打印专用 HTML 文档(纯 TS、headless、无 DOM)。
12
+ *
13
+ * 路线说明:网格渲染层是 canvas + 虚拟滚动(视口外不绘制),无法直接 window.print;
14
+ * 这里从模型单一事实源(与 exportFilledReportXlsx 同一读取路径)重建 `<table>`——
15
+ * 矢量文字清晰、浏览器原生分页、合并格天然映射 rowspan/colspan。
16
+ *
17
+ * 保真范围:值 / 合并 / 有效样式(fill + border + font + align/wrap,条件样式已在
18
+ * 展开阶段打平进 StylePool)/ 行高 / 列宽 / 浮动图(data URL 内嵌,跨页被裁剪属预期)。
19
+ * 与 Excel 默认一致:不打印屏幕网格线(仅模型显式边框)。
20
+ */
21
+ declare function buildFilledReportPrintHtml(sheet: Sheet, options?: ReportPrintOptions): string;
22
+ //#endregion
23
+ export { ReportPrintOptions, buildFilledReportPrintHtml };