@veltra/sheet 2.1.1 → 2.2.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.
- package/dist/components/report/binding-badge.js +76 -0
- package/dist/components/report/designer/cell-coords.js +46 -0
- package/dist/components/report/designer/col-widths.js +15 -0
- package/dist/components/report/designer/conditional-rules/helpers.js +139 -0
- package/dist/components/report/designer/drop-highlight-overlay.js +76 -0
- package/dist/components/report/designer/float-panel.js +385 -0
- package/dist/components/report/designer/role.js +17 -0
- package/dist/components/report/designer/rule-preview.js +33 -0
- package/dist/components/report/designer/rule-row.js +269 -0
- package/dist/components/report/designer/rules-dialog.js +135 -0
- package/dist/components/report/designer/topology-overlay.js +122 -0
- package/dist/components/report/designer/topology.js +64 -0
- package/dist/components/report/designer/use-grid-overlay.js +75 -0
- package/dist/components/report/designer-hub.js +177 -0
- package/dist/components/report/field-panel-helpers.js +33 -0
- package/dist/components/report/field-panel.js +132 -0
- package/dist/components/report/filter-bar.js +74 -0
- package/dist/components/report/hub-connection-form.js +145 -0
- package/dist/components/report/hub-dataset-editor.js +394 -0
- package/dist/components/report/report-designer.js +343 -0
- package/dist/components/report/report-viewer.js +111 -0
- package/dist/components/report/style.d.ts +17 -0
- package/dist/components/report/style.js +18 -0
- package/dist/components/report/style2.css +869 -0
- package/dist/components/report/use-report-designer.js +360 -0
- package/dist/components/report/use-report-viewer.js +50 -0
- package/dist/{vue → components/sheet}/formula-bar.js +1 -1
- package/dist/{vue → components/sheet}/formula-suggest-list.js +1 -1
- package/dist/{vue → components/sheet}/import-file.js +1 -1
- package/dist/{vue → components/sheet}/insert-count-menu-item.js +1 -1
- package/dist/{vue → components/sheet}/insert-image.js +1 -1
- package/dist/{vue → components/sheet}/popup-helpers.js +1 -1
- package/dist/{vue → components/sheet}/popups/border-popup.js +1 -1
- package/dist/{vue → components/sheet}/popups/border-preset-glyph.js +1 -1
- package/dist/{vue → components/sheet}/popups/export-popup.js +2 -2
- package/dist/{vue → components/sheet}/popups/fill-color-popup.js +1 -1
- package/dist/{vue → components/sheet}/popups/find-popup.js +1 -1
- package/dist/{vue → components/sheet}/popups/font-color-popup.js +1 -1
- package/dist/{vue → components/sheet}/popups/font-size-popup.js +1 -1
- package/dist/{vue → components/sheet}/popups/import.worker.d.ts +1 -1
- package/dist/{vue → components/sheet}/popups/import.worker.js +1 -1
- package/dist/{vue → components/sheet}/popups/insert-image-popup.js +1 -1
- package/dist/{vue → components/sheet}/sheet-context-menu.js +1 -1
- package/dist/{vue → components/sheet}/sheet-tabs.js +1 -1
- package/dist/{vue → components/sheet}/sheet-toolbar.js +1 -1
- package/dist/{vue → components/sheet}/sheet.js +8 -1
- package/dist/{vue → components/sheet}/use-find-replace.js +1 -1
- package/dist/{vue → components/sheet}/use-formula-ref-select.js +1 -1
- package/dist/{vue → components/sheet}/use-sheet-grid.js +10 -2
- package/dist/{vue → components/sheet}/use-sheet-state.js +3 -3
- package/dist/{vue → components/sheet}/use-sheet-tabs-bar.js +1 -1
- package/dist/{vue → components/sheet}/use-tool-groups.js +2 -2
- package/dist/{vue → components/sheet}/use-tool-popup.js +2 -2
- package/dist/{vue → components/sheet}/use-toolbar-scroll.js +1 -1
- package/dist/index.d.ts +17 -3
- package/dist/index.js +13 -3
- package/dist/report/binding.d.ts +45 -0
- package/dist/report/binding.js +175 -0
- package/dist/report/connector.d.ts +66 -0
- package/dist/report/connector.js +159 -0
- package/dist/report/export-xlsx.d.ts +19 -0
- package/dist/report/export-xlsx.js +95 -0
- package/dist/report/filter-bar.d.ts +10 -0
- package/dist/report/filter-bar.js +31 -0
- package/dist/report/index.d.ts +12 -0
- package/dist/report/params.d.ts +13 -0
- package/dist/report/params.js +61 -0
- package/dist/report/render/aggregate.js +157 -0
- package/dist/report/render/builder.d.ts +12 -0
- package/dist/report/render/builder.js +139 -0
- package/dist/report/render/coordinate.d.ts +25 -0
- package/dist/report/render/coordinate.js +733 -0
- package/dist/report/render/index.d.ts +14 -0
- package/dist/report/render/index.js +21 -0
- package/dist/report/render/style-resolver.js +50 -0
- package/dist/report/render/template-index.d.ts +24 -0
- package/dist/report/render/template-index.js +137 -0
- package/dist/report/rules/evaluate.d.ts +25 -0
- package/dist/report/rules/evaluate.js +82 -0
- package/dist/report/rules/index.d.ts +2 -0
- package/dist/report/template.d.ts +59 -0
- package/dist/report/template.js +80 -0
- package/dist/report/types.d.ts +85 -0
- package/dist/tools/context.d.ts +1 -1
- package/dist/types/index.d.ts +3 -2
- package/dist/types/report-designer.d.ts +36 -0
- package/dist/types/report-viewer.d.ts +38 -0
- package/dist/types/sheet.d.ts +17 -1
- package/package.json +3 -5
- package/src/components/report/__test__/conditional-rules-helpers.test.ts +87 -0
- package/src/components/report/__test__/field-panel-helpers.test.ts +65 -0
- package/src/components/report/__test__/float-panel-position.test.ts +45 -0
- package/src/components/report/__test__/report-designer.test.ts +388 -0
- package/src/components/report/__test__/report-viewer.test.ts +334 -0
- package/src/components/report/__test__/topology.test.ts +143 -0
- package/src/components/report/__test__/use-report-designer.test.ts +565 -0
- package/src/components/report/binding-badge.ts +73 -0
- package/src/components/report/designer/cell-coords.ts +94 -0
- package/src/components/report/designer/col-widths.ts +33 -0
- package/src/components/report/designer/conditional-rules/helpers.ts +186 -0
- package/src/components/report/designer/drop-highlight-overlay.vue +74 -0
- package/src/components/report/designer/float-panel.vue +387 -0
- package/src/components/report/designer/role.ts +32 -0
- package/src/components/report/designer/rule-preview.vue +40 -0
- package/src/components/report/designer/rule-row.vue +252 -0
- package/src/components/report/designer/rules-dialog.vue +126 -0
- package/src/components/report/designer/topology-overlay.vue +127 -0
- package/src/components/report/designer/topology.ts +124 -0
- package/src/components/report/designer/use-grid-overlay.ts +113 -0
- package/src/components/report/designer-hub.vue +198 -0
- package/src/components/report/field-panel-helpers.ts +44 -0
- package/src/components/report/field-panel.vue +136 -0
- package/src/components/report/filter-bar.vue +77 -0
- package/src/components/report/hub-connection-form.vue +124 -0
- package/src/components/report/hub-dataset-editor.vue +369 -0
- package/src/components/report/index.ts +2 -0
- package/src/components/report/report-designer.vue +356 -0
- package/src/components/report/report-viewer.vue +128 -0
- package/src/components/report/style-designer.scss +583 -0
- package/src/components/report/style-hub.scss +292 -0
- package/src/components/report/style-viewer.scss +104 -0
- package/src/components/report/style.scss +3 -0
- package/src/components/report/style.ts +20 -0
- package/src/components/report/use-report-designer.ts +547 -0
- package/src/components/report/use-report-viewer.ts +79 -0
- package/src/{vue → components/sheet}/__test__/formula-bar.test.ts +37 -18
- package/src/{vue → components/sheet}/__test__/insert-image-popup.test.ts +1 -1
- package/src/{vue → components/sheet}/__test__/insert-image.test.ts +1 -1
- package/src/{vue → components/sheet}/__test__/sheet-component.test.ts +40 -3
- package/src/{vue → components/sheet}/__test__/sheet-context-menu.test.ts +1 -1
- package/src/{vue → components/sheet}/formula-bar.vue +1 -1
- package/src/{vue → components/sheet}/insert-image.ts +1 -1
- package/src/{vue → components/sheet}/popup-helpers.ts +1 -1
- package/src/{vue → components/sheet}/popups/border-popup.vue +1 -1
- package/src/{vue → components/sheet}/popups/export-popup.vue +2 -2
- package/src/{vue → components/sheet}/popups/fill-color-popup.vue +1 -1
- package/src/{vue → components/sheet}/popups/find-popup.vue +1 -1
- package/src/{vue → components/sheet}/popups/font-color-popup.vue +1 -1
- package/src/{vue → components/sheet}/popups/font-size-popup.vue +1 -1
- package/src/{vue → components/sheet}/popups/insert-image-popup.vue +1 -1
- package/src/{vue → components/sheet}/sheet-context-menu.ts +2 -2
- package/src/{vue → components/sheet}/sheet-toolbar.vue +2 -2
- package/src/{vue → components/sheet}/sheet.vue +4 -3
- package/src/{vue → components/sheet}/use-find-replace.ts +1 -1
- package/src/{vue → components/sheet}/use-sheet-grid.ts +7 -3
- package/src/{vue → components/sheet}/use-sheet-state.ts +3 -3
- package/src/{vue → components/sheet}/use-tool-groups.ts +2 -2
- package/src/{vue → components/sheet}/use-tool-popup.ts +2 -2
- package/src/index.ts +24 -188
- package/src/report/__test__/binding.test.ts +218 -0
- package/src/report/__test__/connector.test.ts +218 -0
- package/src/report/__test__/export-xlsx.test.ts +118 -0
- package/src/report/__test__/filter-bar.test.ts +58 -0
- package/src/report/__test__/params.test.ts +156 -0
- package/src/report/__test__/render.test.ts +728 -0
- package/src/report/__test__/rules.test.ts +131 -0
- package/src/report/__test__/template.test.ts +355 -0
- package/src/report/binding.ts +243 -0
- package/src/report/connector.ts +205 -0
- package/src/report/export-xlsx.ts +118 -0
- package/src/report/filter-bar.ts +36 -0
- package/src/report/index.ts +13 -0
- package/src/report/params.ts +96 -0
- package/src/report/render/__test__/aggregate.test.ts +16 -0
- package/src/report/render/__test__/coordinate.test.ts +405 -0
- package/src/report/render/aggregate.ts +240 -0
- package/src/report/render/builder.ts +211 -0
- package/src/report/render/coordinate.ts +1239 -0
- package/src/report/render/index.ts +30 -0
- package/src/report/render/style-resolver.ts +68 -0
- package/src/report/render/template-index.ts +200 -0
- package/src/report/rules/evaluate.ts +113 -0
- package/src/report/rules/index.ts +7 -0
- package/src/report/template.ts +141 -0
- package/src/report/types.ts +96 -0
- package/src/tools/builtin.ts +2 -2
- package/src/types/index.ts +2 -6
- package/src/types/report-designer.ts +36 -0
- package/src/types/report-viewer.ts +37 -0
- package/src/types/sheet.ts +22 -1
- /package/dist/{vue → components/sheet}/style.d.ts +0 -0
- /package/dist/{vue → components/sheet}/style.js +0 -0
- /package/dist/{vue → components/sheet}/style2.css +0 -0
- /package/dist/{vue → components/sheet}/use-formula-suggest.js +0 -0
- /package/src/{vue → components/sheet}/__test__/import-file.test.ts +0 -0
- /package/src/{vue → components/sheet}/__test__/insert-count-menu-item.test.ts +0 -0
- /package/src/{vue → components/sheet}/__test__/use-formula-ref-select.test.ts +0 -0
- /package/src/{vue → components/sheet}/__test__/use-formula-suggest.test.ts +0 -0
- /package/src/{vue → components/sheet}/formula-suggest-list.vue +0 -0
- /package/src/{vue → components/sheet}/import-file.ts +0 -0
- /package/src/{vue → components/sheet}/index.ts +0 -0
- /package/src/{vue → components/sheet}/insert-count-menu-item.vue +0 -0
- /package/src/{vue → components/sheet}/parsing.ts +0 -0
- /package/src/{vue → components/sheet}/popups/border-preset-glyph.vue +0 -0
- /package/src/{vue → components/sheet}/popups/import.worker.ts +0 -0
- /package/src/{vue → components/sheet}/sheet-tabs.vue +0 -0
- /package/src/{vue → components/sheet}/style.scss +0 -0
- /package/src/{vue → components/sheet}/style.ts +0 -0
- /package/src/{vue → components/sheet}/use-formula-ref-select.ts +0 -0
- /package/src/{vue → components/sheet}/use-formula-suggest.ts +0 -0
- /package/src/{vue → components/sheet}/use-sheet-tabs-bar.ts +0 -0
- /package/src/{vue → components/sheet}/use-toolbar-scroll.ts +0 -0
|
@@ -2,7 +2,7 @@ import { buildBodyMenus, buildColHeaderMenus, buildRowHeaderMenus, ensureContext
|
|
|
2
2
|
import { onBeforeUnmount, onMounted, watch } from "vue";
|
|
3
3
|
import { contextmenu } from "@veltra/desktop";
|
|
4
4
|
import { SheetGrid } from "@veltra/sheet-core/grid/sheet-grid";
|
|
5
|
-
//#region src/
|
|
5
|
+
//#region src/components/sheet/use-sheet-grid.ts
|
|
6
6
|
/**
|
|
7
7
|
* 缓存容量:最近 N 个 sheet 的 SheetGrid 实例常驻(tab 来回切换零重建)。
|
|
8
8
|
* 大文件多 sheet 场景下切换卡顿的主因是每次重建 VTable(实例创建 + scenegraph
|
|
@@ -62,6 +62,10 @@ function useSheetGrid(options) {
|
|
|
62
62
|
sheet,
|
|
63
63
|
rows: props.rows,
|
|
64
64
|
cols: props.cols,
|
|
65
|
+
readonly: props.readonly,
|
|
66
|
+
resolveDisplayValue: props.resolveDisplayValue,
|
|
67
|
+
resolveCellStyle: props.resolveCellStyle,
|
|
68
|
+
resolveCellRenderer: props.resolveCellRenderer,
|
|
65
69
|
onContextMenu: handleContextMenu,
|
|
66
70
|
onEditStart: (addr) => formulaBarRef.value?.mirrorGridEdit(addr),
|
|
67
71
|
onEditEnd: (addr) => formulaBarRef.value?.exitMirror(addr),
|
|
@@ -165,7 +169,11 @@ function useSheetGrid(options) {
|
|
|
165
169
|
activateGrid();
|
|
166
170
|
}
|
|
167
171
|
onMounted(activateGrid);
|
|
168
|
-
watch(() => [
|
|
172
|
+
watch(() => [
|
|
173
|
+
props.rows,
|
|
174
|
+
props.cols,
|
|
175
|
+
props.readonly
|
|
176
|
+
], rebuildGrid);
|
|
169
177
|
onBeforeUnmount(() => {
|
|
170
178
|
invalidateAll();
|
|
171
179
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { defaultToolRegistry } from "
|
|
2
|
-
import { createSheetContext } from "
|
|
1
|
+
import { defaultToolRegistry } from "../../tools/registry.js";
|
|
2
|
+
import { createSheetContext } from "../../tools/context.js";
|
|
3
3
|
import { computed, onBeforeUnmount, onMounted, ref, shallowRef, watch } from "vue";
|
|
4
4
|
import { Workbook } from "@veltra/sheet-core/core/workbook";
|
|
5
|
-
//#region src/
|
|
5
|
+
//#region src/components/sheet/use-sheet-state.ts
|
|
6
6
|
/**
|
|
7
7
|
* USheet 的状态源(单一数据源,其余状态由此推导):
|
|
8
8
|
* - workbook(外部传入或内部自建单 sheet 工作簿)、sheetList、activeIndex、activeSheet
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { nextTick, onBeforeUnmount, onMounted, shallowRef, watch } from "vue";
|
|
2
2
|
import { applyWheelHorizontalScroll, computeOverflowNavState, scrollElementIntoView, scrollViewportByStep } from "@veltra/utils";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/components/sheet/use-sheet-tabs-bar.ts
|
|
4
4
|
/**
|
|
5
5
|
* Sheet 底部标签栏溢出滚动(滚动几何/滚轮转横滚/元素滚入视野共享
|
|
6
6
|
* @veltra/utils overflow-nav,见 #17;此处保留事件绑定与 watch 差异):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { defaultToolRegistry } from "
|
|
1
|
+
import { defaultToolRegistry } from "../../tools/registry.js";
|
|
2
2
|
import { computed } from "vue";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/components/sheet/use-tool-groups.ts
|
|
4
4
|
/**
|
|
5
5
|
* 内置组稳定顺序:history | cell | text | edit | insert | file。
|
|
6
6
|
* 未列出的自定义组按注册先后排在已知组之后。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { defaultToolRegistry } from "
|
|
1
|
+
import { defaultToolRegistry } from "../../tools/registry.js";
|
|
2
2
|
import { onBeforeUnmount, onMounted, shallowRef } from "vue";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/components/sheet/use-tool-popup.ts
|
|
4
4
|
/**
|
|
5
5
|
* 面板打开期间的写入是否合并为一个 undo 单元(关闭时提交):
|
|
6
6
|
* 填充颜色 / 边框 / 字体颜色 / 字号参与事务;查找(每次替换独立 undo)、
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { onBeforeUnmount, onMounted, shallowRef, watch } from "vue";
|
|
2
2
|
import { applyWheelHorizontalScroll, computeOverflowNavState, scrollViewportByStep } from "@veltra/utils";
|
|
3
|
-
//#region src/
|
|
3
|
+
//#region src/components/sheet/use-toolbar-scroll.ts
|
|
4
4
|
/**
|
|
5
5
|
* 工具栏溢出滚动(滚动几何/滚轮转横滚共享 @veltra/utils overflow-nav,见 #17;
|
|
6
6
|
* 无活动项跟随):
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
|
-
import _sfc_main from "./
|
|
1
|
+
import _sfc_main$2 from "./components/sheet/sheet.js";
|
|
2
|
+
import _sfc_main$1 from "./components/report/report-viewer.js";
|
|
3
|
+
import _sfc_main from "./components/report/report-designer.js";
|
|
2
4
|
import { SheetContext, createSheetContext } from "./tools/context.js";
|
|
3
5
|
import { SheetTool, SheetToolGroup, SheetToolPopupType, defaultToolRegistry, registerTool, unregisterTool } from "./tools/registry.js";
|
|
4
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";
|
|
8
|
+
import { REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatBindingPlaceholder, formatCellAddress, inferColParentCandidate, inferDropPreset, inferReportPreset, inferRowParentCandidate, isExpansionBandRow, isHorizontalExpandBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, parseCellAddress, presetBindingPatch, setBindingCatalog } from "./report/binding.js";
|
|
9
|
+
import { ConditionalEvalContext, evaluateCondition, evaluateConditionalStyle, resolveRuleCompareValue, toComparableNumber } from "./report/rules/evaluate.js";
|
|
10
|
+
import { buildParamDefs, extractParamIds, resolveBoundDatasetParams } from "./report/params.js";
|
|
11
|
+
import { ReportColWidthEntry, buildColumnDefs, exportFilledReportXlsx, pxToExcelColWidth } from "./report/export-xlsx.js";
|
|
12
|
+
import { mapFilledColWidths } from "./report/render/builder.js";
|
|
13
|
+
import { renderReport, resolveFilledColWidths } from "./report/render/index.js";
|
|
14
|
+
import { ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, QueryResult, Result, createHttpConnector, resolvePortOnTypeChange } from "./report/connector.js";
|
|
15
|
+
import { IncompatibleTemplateVersionError, REPORT_TEMPLATE_VERSION, ReportDatasetDef, ReportTemplate, assertCompatibleTemplateVersion, createReportTemplate, fetchTemplateRecords, getBoundDatasetIds, getTemplateDatasets, resolveParamDefaults, resolveTemplateParams } from "./report/template.js";
|
|
16
|
+
import { parseDateRangeValue, patchParamValues, resolveNumberParamValue } from "./report/filter-bar.js";
|
|
17
|
+
import "./report/index.js";
|
|
18
|
+
import { ReportViewerExposed, ReportViewerProps, _ReportViewerExposed } from "./types/report-viewer.js";
|
|
19
|
+
import { ReportDesignerEmits, ReportDesignerExposed, ReportDesignerProps, _ReportDesignerExposed } from "./types/report-designer.js";
|
|
5
20
|
import "./types/index.js";
|
|
6
|
-
|
|
7
|
-
export { ALIGN_STYLE_KEYS, type AstNode, type AstReference, BORDER_EDGE_DEFAULTS, BORDER_SIDES, BORDER_STYLE_WIDTH, type BinaryOperator, type BorderEdge, type BorderLineStyle, type BorderPreset, type BorderPresetItem, type BorderSide, type CellAddress, type CellAlign, type CellData, type CellFont, type CellInfo, type CellPatch, type CellRange, type CellSnapshotItem, CellStore, type CellStyle, type CellStylePatch, type CellType, type CellValue, type Command, type CommandContext, type CommandResult, DependencyGraph, type EvalValue, FONT_STYLE_KEYS, FORMULA_ERROR_CODES, type FillDirection, type FindMatch, type FindOptions, type FormulaDependency, type FormulaError, type FormulaErrorCode, type FormulaEvalContext, type FormulaFunction, type FormulaFunctionMeta, type FormulaNode, type FormulaOperator, FormulaParseError, type FormulaToken, type FrozenState, type GenerateFillOptions, HistoryManager, type HistoryState, type HorizontalAlign, type ImageInput, type ImagePatch, type ImageUpdateFields, InsertCellsCommand, type InsertCellsParams, InsertImageCommand, type InsertImageParams, MergeCellsCommand, type MergeCellsParams, MergeManager, type MergePatch, type MergeResult, type MergedCellKind, type Mutation, NUMERIC_TEXT_RE, type Patch, type PatchDirection, RemoveImageCommand, type RemoveImageParams, type ScalarValue, SelectionModel, type SelectionState, SetCellFormulaCommand, type SetCellFormulaParams, SetCellStyleCommand, type SetCellStyleItem, type SetCellStyleParams, SetCellValueCommand, type SetCellValueItem, type SetCellValueParams, Sheet, type SheetContext, type SheetEmits, type SheetEvents, type SheetExposed, SheetGrid, type SheetGridContextMenuInfo, type SheetGridContextMenuKind, type SheetGridOptions, type SheetImage, type SheetImageAnchor, type SheetImageType, type SheetProps, type SheetSnapshot, type SheetTool, type SheetToolGroup, type SheetToolPopupType, type SnapshotPatch, type StructureChange, type StructurePatch, type StyleId, StylePool, _sfc_main as USheet, UnmergeCellsCommand, type UnmergeCellsParams, UpdateImageCommand, type UpdateImageParams, type VerticalAlign, Workbook, type WorkbookEvents, type _SheetExposed, boundingBox, buildBorderPresetItems, cellDataEqual, cellKey, cloneImageAnchor, cloneSheetImage, coerceToBoolean, coerceToNumber, coerceToText, colIndexToName, colNameToIndex, collectReferences, computeFillTargetRange, createImageId, createRange, createSheetContext, defaultCommandRegistry, defaultToolRegistry, evaluateAst, exportSheetCsv, exportWorkbookXlsx, findAll, findNext, findNextFrom, findPrev, findPrevFrom, formatAddress, formatRange, formulaError, generateFill, importCsv, importXlsx, inferCellType, invokeFormulaFunction, isEmptyCellData, isFormulaError, isFormulaErrorCode, iterateRange, listFormulaFunctions, normalizeInputValue, parseAddress, parseFormula, parseRange, rangeContainsAddress, rangesEqual, rangesIntersect, registerFormulaFunction, registerTool, replaceWorkbook, tokenizeFormula, unregisterTool };
|
|
21
|
+
export { type ConditionalEvalContext, ConditionalOperator, ConditionalRule, ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, DatasetCatalogItem, DatasetField, DatasetRecords, IncompatibleTemplateVersionError, 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, formatCellAddress, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferReportPreset, inferRowParentCandidate, isExpansionBandRow, isHorizontalExpandBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, presetBindingPatch, pxToExcelColWidth, registerTool, renderReport, resolveBoundDatasetParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber, unregisterTool };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { defaultToolRegistry, registerTool, unregisterTool } from "./tools/registry.js";
|
|
2
2
|
import "./tools/builtin.js";
|
|
3
3
|
import { createSheetContext } from "./tools/context.js";
|
|
4
|
-
import _sfc_main from "./
|
|
5
|
-
import {
|
|
6
|
-
|
|
4
|
+
import _sfc_main$2 from "./components/sheet/sheet.js";
|
|
5
|
+
import { buildColumnDefs, exportFilledReportXlsx, pxToExcelColWidth } from "./report/export-xlsx.js";
|
|
6
|
+
import { parseDateRangeValue, patchParamValues, resolveNumberParamValue } from "./report/filter-bar.js";
|
|
7
|
+
import { REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatBindingPlaceholder, formatCellAddress, inferColParentCandidate, inferDropPreset, inferReportPreset, inferRowParentCandidate, isExpansionBandRow, isHorizontalExpandBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, parseCellAddress, presetBindingPatch, setBindingCatalog } from "./report/binding.js";
|
|
8
|
+
import { evaluateCondition, evaluateConditionalStyle, resolveRuleCompareValue, toComparableNumber } from "./report/rules/evaluate.js";
|
|
9
|
+
import { mapFilledColWidths } from "./report/render/builder.js";
|
|
10
|
+
import { renderReport, resolveFilledColWidths } from "./report/render/index.js";
|
|
11
|
+
import { buildParamDefs, extractParamIds, resolveBoundDatasetParams } from "./report/params.js";
|
|
12
|
+
import { IncompatibleTemplateVersionError, REPORT_TEMPLATE_VERSION, assertCompatibleTemplateVersion, createReportTemplate, fetchTemplateRecords, getBoundDatasetIds, getTemplateDatasets, resolveParamDefaults, resolveTemplateParams } from "./report/template.js";
|
|
13
|
+
import _sfc_main$1 from "./components/report/report-viewer.js";
|
|
14
|
+
import { DEFAULT_CONNECTION_PORTS, createHttpConnector, resolvePortOnTypeChange } from "./report/connector.js";
|
|
15
|
+
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, formatCellAddress, getBoundDatasetIds, getTemplateDatasets, inferColParentCandidate, inferDropPreset, inferReportPreset, inferRowParentCandidate, isExpansionBandRow, isHorizontalExpandBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, mapFilledColWidths, parseCellAddress, parseDateRangeValue, patchParamValues, presetBindingPatch, pxToExcelColWidth, registerTool, renderReport, resolveBoundDatasetParams, resolveFilledColWidths, resolveNumberParamValue, resolveParamDefaults, resolvePortOnTypeChange, resolveRuleCompareValue, resolveTemplateParams, setBindingCatalog, toComparableNumber, unregisterTool };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { DatasetCatalogItem, ReportBinding, ReportPreset } from "./types.js";
|
|
2
|
+
import { CellAddress } from "@veltra/sheet-core";
|
|
3
|
+
//#region src/report/binding.d.ts
|
|
4
|
+
declare function setBindingCatalog(catalog: DatasetCatalogItem[]): void;
|
|
5
|
+
declare const REPORT_META_NAMESPACE = "report";
|
|
6
|
+
/** 预设 → 绑定字段补丁(父格除 grandTotal 外均保留推断值) */
|
|
7
|
+
declare function presetBindingPatch(preset: ReportPreset, options?: {
|
|
8
|
+
transpose?: boolean;
|
|
9
|
+
}): Partial<ReportBinding>;
|
|
10
|
+
/** 将预设写入绑定(grandTotal 清空双父格;其余保留既有父格) */
|
|
11
|
+
declare function applyReportPreset(binding: ReportBinding, preset: ReportPreset, options?: {
|
|
12
|
+
transpose?: boolean;
|
|
13
|
+
}): ReportBinding;
|
|
14
|
+
declare function isVerticalExpandBinding(binding: ReportBinding): boolean;
|
|
15
|
+
declare function isHorizontalExpandBinding(binding: ReportBinding): boolean;
|
|
16
|
+
/** 指定模板行是否含纵向扩展绑定(展开带行) */
|
|
17
|
+
declare function isExpansionBandRow(row: number, getBindingAt: (addr: CellAddress) => ReportBinding | undefined, scanCols?: number): boolean;
|
|
18
|
+
/** 落格时推断预设:默认明细;数值字段且位于展开带正下方相邻行 → 小计 */
|
|
19
|
+
declare function inferDropPreset(addr: CellAddress, fieldType: DatasetCatalogItem['fields'][number]['type'], getBindingAt: (addr: CellAddress) => ReportBinding | undefined): ReportPreset;
|
|
20
|
+
/** 同数据集纵向扩展绑定格(行方向父格下拉候选) */
|
|
21
|
+
declare function listRowParentCandidates(binding: ReportBinding, entries: ReadonlyArray<{
|
|
22
|
+
addr: CellAddress;
|
|
23
|
+
binding: ReportBinding;
|
|
24
|
+
}>): CellAddress[];
|
|
25
|
+
/** 同数据集横向扩展绑定格(列方向父格下拉候选) */
|
|
26
|
+
declare function listColParentCandidates(binding: ReportBinding, entries: ReadonlyArray<{
|
|
27
|
+
addr: CellAddress;
|
|
28
|
+
binding: ReportBinding;
|
|
29
|
+
}>): CellAddress[];
|
|
30
|
+
/** 同列向上找最近的纵向扩展绑定,作为 rowParent 候选 */
|
|
31
|
+
declare function inferRowParentCandidate(addr: CellAddress, getBindingAt: (addr: CellAddress) => ReportBinding | undefined): CellAddress | null;
|
|
32
|
+
/** 同行向左找最近的横向扩展绑定,作为 colParent 候选 */
|
|
33
|
+
declare function inferColParentCandidate(addr: CellAddress, getBindingAt: (addr: CellAddress) => ReportBinding | undefined): CellAddress | null;
|
|
34
|
+
/** 从绑定字段推断预设;不匹配任何预设时返回 null(自定义) */
|
|
35
|
+
declare function inferReportPreset(binding: ReportBinding): ReportPreset | null;
|
|
36
|
+
/** 默认明细 + 纵向扩展 */
|
|
37
|
+
declare function createReportBinding(dataset: DatasetCatalogItem, fieldName: string): ReportBinding;
|
|
38
|
+
/** 设计地址 → A1 标签(支持多字母列) */
|
|
39
|
+
declare function formatCellAddress(addr: CellAddress): string;
|
|
40
|
+
/** A1 标签 → 设计地址;非法输入返回 null */
|
|
41
|
+
declare function parseCellAddress(label: string): CellAddress | null;
|
|
42
|
+
/** Binding Placeholder 中文可读文案(如「分组 · 客户」) */
|
|
43
|
+
declare function formatBindingPlaceholder(binding: ReportBinding, resolveLabel?: (datasetId: string, fieldName: string) => string): string;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatBindingPlaceholder, formatCellAddress, inferColParentCandidate, inferDropPreset, inferReportPreset, inferRowParentCandidate, isExpansionBandRow, isHorizontalExpandBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, parseCellAddress, presetBindingPatch, setBindingCatalog };
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { formatAddress, parseAddress } from "@veltra/sheet-core";
|
|
2
|
+
//#region src/report/binding.ts
|
|
3
|
+
/** 字段 label 解析用的 catalog(由宿主注入) */
|
|
4
|
+
let bindingCatalog = [];
|
|
5
|
+
function setBindingCatalog(catalog) {
|
|
6
|
+
bindingCatalog = catalog;
|
|
7
|
+
}
|
|
8
|
+
const REPORT_META_NAMESPACE = "report";
|
|
9
|
+
const AGGREGATE_PLACEHOLDER_TAG = {
|
|
10
|
+
list: "明细",
|
|
11
|
+
group: "分组",
|
|
12
|
+
sum: "求和",
|
|
13
|
+
avg: "平均",
|
|
14
|
+
count: "计数",
|
|
15
|
+
max: "最大",
|
|
16
|
+
min: "最小"
|
|
17
|
+
};
|
|
18
|
+
/** 预设 → 绑定字段补丁(父格除 grandTotal 外均保留推断值) */
|
|
19
|
+
function presetBindingPatch(preset, options) {
|
|
20
|
+
const expand = options?.transpose ? "right" : "down";
|
|
21
|
+
switch (preset) {
|
|
22
|
+
case "groupHeader": return {
|
|
23
|
+
preset,
|
|
24
|
+
expand,
|
|
25
|
+
aggregate: "group"
|
|
26
|
+
};
|
|
27
|
+
case "detail": return {
|
|
28
|
+
preset,
|
|
29
|
+
expand,
|
|
30
|
+
aggregate: "list"
|
|
31
|
+
};
|
|
32
|
+
case "subtotal": return {
|
|
33
|
+
preset,
|
|
34
|
+
expand: "none",
|
|
35
|
+
aggregate: "sum"
|
|
36
|
+
};
|
|
37
|
+
case "grandTotal": return {
|
|
38
|
+
preset,
|
|
39
|
+
expand: "none",
|
|
40
|
+
aggregate: "sum",
|
|
41
|
+
rowParent: void 0,
|
|
42
|
+
colParent: void 0
|
|
43
|
+
};
|
|
44
|
+
case "cross": return {
|
|
45
|
+
preset,
|
|
46
|
+
expand: "none",
|
|
47
|
+
aggregate: "sum"
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/** 将预设写入绑定(grandTotal 清空双父格;其余保留既有父格) */
|
|
52
|
+
function applyReportPreset(binding, preset, options) {
|
|
53
|
+
const patch = presetBindingPatch(preset, options);
|
|
54
|
+
const next = {
|
|
55
|
+
...binding,
|
|
56
|
+
...patch
|
|
57
|
+
};
|
|
58
|
+
if (preset === "grandTotal") {
|
|
59
|
+
delete next.rowParent;
|
|
60
|
+
delete next.colParent;
|
|
61
|
+
}
|
|
62
|
+
return next;
|
|
63
|
+
}
|
|
64
|
+
function isVerticalExpandBinding(binding) {
|
|
65
|
+
return binding.expand === "down" && (binding.aggregate === "group" || binding.aggregate === "list");
|
|
66
|
+
}
|
|
67
|
+
function isHorizontalExpandBinding(binding) {
|
|
68
|
+
return binding.expand === "right" && binding.aggregate === "group";
|
|
69
|
+
}
|
|
70
|
+
/** 指定模板行是否含纵向扩展绑定(展开带行) */
|
|
71
|
+
function isExpansionBandRow(row, getBindingAt, scanCols = 64) {
|
|
72
|
+
for (let col = 0; col < scanCols; col++) {
|
|
73
|
+
const binding = getBindingAt({
|
|
74
|
+
row,
|
|
75
|
+
col
|
|
76
|
+
});
|
|
77
|
+
if (binding && isVerticalExpandBinding(binding)) return true;
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
/** 落格时推断预设:默认明细;数值字段且位于展开带正下方相邻行 → 小计 */
|
|
82
|
+
function inferDropPreset(addr, fieldType, getBindingAt) {
|
|
83
|
+
if (fieldType === "number" && addr.row > 0 && isExpansionBandRow(addr.row - 1, getBindingAt)) return "subtotal";
|
|
84
|
+
return "detail";
|
|
85
|
+
}
|
|
86
|
+
/** 同数据集纵向扩展绑定格(行方向父格下拉候选) */
|
|
87
|
+
function listRowParentCandidates(binding, entries) {
|
|
88
|
+
const candidates = [];
|
|
89
|
+
for (const entry of entries) {
|
|
90
|
+
if (entry.binding.dataset !== binding.dataset) continue;
|
|
91
|
+
if (!isVerticalExpandBinding(entry.binding)) continue;
|
|
92
|
+
candidates.push(entry.addr);
|
|
93
|
+
}
|
|
94
|
+
return candidates;
|
|
95
|
+
}
|
|
96
|
+
/** 同数据集横向扩展绑定格(列方向父格下拉候选) */
|
|
97
|
+
function listColParentCandidates(binding, entries) {
|
|
98
|
+
const candidates = [];
|
|
99
|
+
for (const entry of entries) {
|
|
100
|
+
if (entry.binding.dataset !== binding.dataset) continue;
|
|
101
|
+
if (!isHorizontalExpandBinding(entry.binding)) continue;
|
|
102
|
+
candidates.push(entry.addr);
|
|
103
|
+
}
|
|
104
|
+
return candidates;
|
|
105
|
+
}
|
|
106
|
+
/** 同列向上找最近的纵向扩展绑定,作为 rowParent 候选 */
|
|
107
|
+
function inferRowParentCandidate(addr, getBindingAt) {
|
|
108
|
+
for (let row = addr.row - 1; row >= 0; row--) {
|
|
109
|
+
const binding = getBindingAt({
|
|
110
|
+
row,
|
|
111
|
+
col: addr.col
|
|
112
|
+
});
|
|
113
|
+
if (binding && isVerticalExpandBinding(binding)) return {
|
|
114
|
+
row,
|
|
115
|
+
col: addr.col
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
/** 同行向左找最近的横向扩展绑定,作为 colParent 候选 */
|
|
121
|
+
function inferColParentCandidate(addr, getBindingAt) {
|
|
122
|
+
for (let col = addr.col - 1; col >= 0; col--) {
|
|
123
|
+
const binding = getBindingAt({
|
|
124
|
+
row: addr.row,
|
|
125
|
+
col
|
|
126
|
+
});
|
|
127
|
+
if (binding && isHorizontalExpandBinding(binding)) return {
|
|
128
|
+
row: addr.row,
|
|
129
|
+
col
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
/** 从绑定字段推断预设;不匹配任何预设时返回 null(自定义) */
|
|
135
|
+
function inferReportPreset(binding) {
|
|
136
|
+
if (binding.preset) return binding.preset;
|
|
137
|
+
if (binding.expand === "none" && binding.aggregate === "sum" && binding.rowParent && binding.colParent) return "cross";
|
|
138
|
+
if (binding.expand === "none" && binding.aggregate === "sum" && !binding.rowParent && !binding.colParent) return "grandTotal";
|
|
139
|
+
if (binding.expand === "none" && binding.aggregate === "sum" && binding.rowParent && !binding.colParent) return "subtotal";
|
|
140
|
+
if (binding.aggregate === "group" && (binding.expand === "down" || binding.expand === "right")) return "groupHeader";
|
|
141
|
+
if (binding.aggregate === "list" && (binding.expand === "down" || binding.expand === "right")) return "detail";
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
/** 默认明细 + 纵向扩展 */
|
|
145
|
+
function createReportBinding(dataset, fieldName) {
|
|
146
|
+
return {
|
|
147
|
+
dataset: dataset.id,
|
|
148
|
+
field: fieldName,
|
|
149
|
+
aggregate: "list",
|
|
150
|
+
expand: "down",
|
|
151
|
+
preset: "detail",
|
|
152
|
+
sort: "none",
|
|
153
|
+
conditionalRules: []
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
/** 设计地址 → A1 标签(支持多字母列) */
|
|
157
|
+
function formatCellAddress(addr) {
|
|
158
|
+
return formatAddress(addr);
|
|
159
|
+
}
|
|
160
|
+
/** A1 标签 → 设计地址;非法输入返回 null */
|
|
161
|
+
function parseCellAddress(label) {
|
|
162
|
+
return parseAddress(label);
|
|
163
|
+
}
|
|
164
|
+
/** 解析字段中文标签(找不到时回退字段名);可传入报表配置中的 label */
|
|
165
|
+
function resolveFieldLabel(datasetId, fieldName, resolveLabel) {
|
|
166
|
+
const override = resolveLabel?.(datasetId, fieldName);
|
|
167
|
+
if (override) return override;
|
|
168
|
+
return (bindingCatalog.find((d) => d.id === datasetId)?.fields.find((f) => f.name === fieldName))?.label ?? fieldName;
|
|
169
|
+
}
|
|
170
|
+
/** Binding Placeholder 中文可读文案(如「分组 · 客户」) */
|
|
171
|
+
function formatBindingPlaceholder(binding, resolveLabel) {
|
|
172
|
+
return `${AGGREGATE_PLACEHOLDER_TAG[binding.aggregate]} · ${resolveFieldLabel(binding.dataset, binding.field, resolveLabel)}`;
|
|
173
|
+
}
|
|
174
|
+
//#endregion
|
|
175
|
+
export { REPORT_META_NAMESPACE, applyReportPreset, createReportBinding, formatBindingPlaceholder, formatCellAddress, inferColParentCandidate, inferDropPreset, inferReportPreset, inferRowParentCandidate, isExpansionBandRow, isHorizontalExpandBinding, isVerticalExpandBinding, listColParentCandidates, listRowParentCandidates, parseCellAddress, presetBindingPatch, setBindingCatalog };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { DatasetField, ParamValues } from "./types.js";
|
|
2
|
+
//#region src/report/connector.d.ts
|
|
3
|
+
/** 数据连接类型(ADR-0003 决策 3:收敛为 MySQL / PostgreSQL) */
|
|
4
|
+
type ConnectionType = 'mysql' | 'postgresql';
|
|
5
|
+
/** 各连接类型的默认端口 */
|
|
6
|
+
declare const DEFAULT_CONNECTION_PORTS: Record<ConnectionType, number>;
|
|
7
|
+
/**
|
|
8
|
+
* 切换连接类型时解析端口:若当前端口仍是上一类型的默认值(或 0),则切到新类型默认端口;
|
|
9
|
+
* 用户已自定义的端口保持不变。
|
|
10
|
+
*/
|
|
11
|
+
declare function resolvePortOnTypeChange(prevType: ConnectionType, nextType: ConnectionType, currentPort: number): number;
|
|
12
|
+
/**
|
|
13
|
+
* 数据连接(纯序列化对象,仅驻留内存)。
|
|
14
|
+
* 凭据持久化与安全存储由下游负责(ADR-0003 决策 4)。
|
|
15
|
+
*/
|
|
16
|
+
interface DataConnection {
|
|
17
|
+
id: string;
|
|
18
|
+
label: string;
|
|
19
|
+
type: ConnectionType;
|
|
20
|
+
host: string;
|
|
21
|
+
port: number;
|
|
22
|
+
database: string;
|
|
23
|
+
username: string;
|
|
24
|
+
password: string;
|
|
25
|
+
}
|
|
26
|
+
/** 业务错误(`200 + { ok: false, error }`)或客户端传输层错误 */
|
|
27
|
+
interface ConnectorError {
|
|
28
|
+
code: string;
|
|
29
|
+
message: string;
|
|
30
|
+
}
|
|
31
|
+
/** 统一结果:成功携带 data;失败携带 error(连接器不抛异常,调用方只处理一条错误路径) */
|
|
32
|
+
type Result<T> = {
|
|
33
|
+
ok: true;
|
|
34
|
+
data: T;
|
|
35
|
+
} | {
|
|
36
|
+
ok: false;
|
|
37
|
+
error: ConnectorError;
|
|
38
|
+
};
|
|
39
|
+
/** query 成功结果:字段 schema + 行记录(契约 `{ fields, rows }` 归一化后) */
|
|
40
|
+
interface QueryResult {
|
|
41
|
+
fields: DatasetField[];
|
|
42
|
+
rows: Record<string, unknown>[];
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 数据连接器(词汇表:Data Connector):test / describe / query 三方法镜像 HTTP 契约三端点。
|
|
46
|
+
* 真实数据库访问由下游后端以任意语言实现(BYO)。
|
|
47
|
+
*/
|
|
48
|
+
interface DataConnector {
|
|
49
|
+
test(connection: DataConnection): Promise<Result<void>>;
|
|
50
|
+
describe(connection: DataConnection, sql: string): Promise<Result<DatasetField[]>>;
|
|
51
|
+
query(connection: DataConnection, sql: string, values: ParamValues): Promise<Result<QueryResult>>;
|
|
52
|
+
}
|
|
53
|
+
interface CreateHttpConnectorOptions {
|
|
54
|
+
/** 契约端点前缀,如 `https://api.example.com/report`;三端点 = `{endpoint}/test|describe|query`(无版本段) */
|
|
55
|
+
endpoint: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 创建 HTTP 数据连接器:三方法对应 `POST {endpoint}/test|describe|query`。
|
|
59
|
+
* - 请求体 JSON 序列化,`Content-Type: application/json`;
|
|
60
|
+
* - 网络异常与非 2xx(传输层错误)折叠为 `{ ok: false, error }`,不抛异常;
|
|
61
|
+
* - 业务错误(连接失败 / SQL 报错)由服务端以 `200 + { ok: false, error: { code, message } }` 返回并原样透传;
|
|
62
|
+
* - `describe` / `query` 的 fields 归一化为内核 `DatasetField`(label 回退 name,type 缺省 string)。
|
|
63
|
+
*/
|
|
64
|
+
declare function createHttpConnector({ endpoint }: CreateHttpConnectorOptions): DataConnector;
|
|
65
|
+
//#endregion
|
|
66
|
+
export { ConnectionType, ConnectorError, CreateHttpConnectorOptions, DEFAULT_CONNECTION_PORTS, DataConnection, DataConnector, QueryResult, Result, createHttpConnector, resolvePortOnTypeChange };
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
//#region src/report/connector.ts
|
|
2
|
+
/** 各连接类型的默认端口 */
|
|
3
|
+
const DEFAULT_CONNECTION_PORTS = {
|
|
4
|
+
mysql: 3306,
|
|
5
|
+
postgresql: 5432
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* 切换连接类型时解析端口:若当前端口仍是上一类型的默认值(或 0),则切到新类型默认端口;
|
|
9
|
+
* 用户已自定义的端口保持不变。
|
|
10
|
+
*/
|
|
11
|
+
function resolvePortOnTypeChange(prevType, nextType, currentPort) {
|
|
12
|
+
if (prevType === nextType) return currentPort;
|
|
13
|
+
if (currentPort === DEFAULT_CONNECTION_PORTS[prevType] || currentPort === 0) return DEFAULT_CONNECTION_PORTS[nextType];
|
|
14
|
+
return currentPort;
|
|
15
|
+
}
|
|
16
|
+
/** 客户端错误:网络不可达 / 非 2xx / 响应不可解析(业务错误由服务端 200 透传) */
|
|
17
|
+
function badResponse(message) {
|
|
18
|
+
return {
|
|
19
|
+
ok: false,
|
|
20
|
+
error: {
|
|
21
|
+
code: "BAD_RESPONSE",
|
|
22
|
+
message
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function isRecord(value) {
|
|
27
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28
|
+
}
|
|
29
|
+
function toConnectorError(value) {
|
|
30
|
+
if (isRecord(value)) {
|
|
31
|
+
const { code, message } = value;
|
|
32
|
+
if (typeof code === "string" && typeof message === "string") return {
|
|
33
|
+
code,
|
|
34
|
+
message
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
code: "SERVER_ERROR",
|
|
39
|
+
message: "服务端返回未知错误"
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/** 契约字段 → 内核 DatasetField(label 缺省回退 name,type 缺省 string) */
|
|
43
|
+
function normalizeField(field) {
|
|
44
|
+
return {
|
|
45
|
+
name: field.name,
|
|
46
|
+
label: field.name,
|
|
47
|
+
type: field.type ?? "string"
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** 校验并归一化契约 fields;形状不合法返回 null */
|
|
51
|
+
function normalizeFields(fields) {
|
|
52
|
+
if (!Array.isArray(fields)) return null;
|
|
53
|
+
const normalized = [];
|
|
54
|
+
for (const field of fields) {
|
|
55
|
+
if (!isRecord(field) || typeof field.name !== "string") return null;
|
|
56
|
+
normalized.push(normalizeField(field));
|
|
57
|
+
}
|
|
58
|
+
return normalized;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 创建 HTTP 数据连接器:三方法对应 `POST {endpoint}/test|describe|query`。
|
|
62
|
+
* - 请求体 JSON 序列化,`Content-Type: application/json`;
|
|
63
|
+
* - 网络异常与非 2xx(传输层错误)折叠为 `{ ok: false, error }`,不抛异常;
|
|
64
|
+
* - 业务错误(连接失败 / SQL 报错)由服务端以 `200 + { ok: false, error: { code, message } }` 返回并原样透传;
|
|
65
|
+
* - `describe` / `query` 的 fields 归一化为内核 `DatasetField`(label 回退 name,type 缺省 string)。
|
|
66
|
+
*/
|
|
67
|
+
function createHttpConnector({ endpoint }) {
|
|
68
|
+
async function postJson(path, body) {
|
|
69
|
+
let response;
|
|
70
|
+
try {
|
|
71
|
+
response = await fetch(`${endpoint}${path}`, {
|
|
72
|
+
method: "POST",
|
|
73
|
+
headers: { "Content-Type": "application/json" },
|
|
74
|
+
body: JSON.stringify(body)
|
|
75
|
+
});
|
|
76
|
+
} catch (error) {
|
|
77
|
+
return {
|
|
78
|
+
ok: false,
|
|
79
|
+
error: {
|
|
80
|
+
code: "NETWORK_ERROR",
|
|
81
|
+
message: error instanceof Error ? error.message : String(error)
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
if (!response.ok) return {
|
|
86
|
+
ok: false,
|
|
87
|
+
error: {
|
|
88
|
+
code: `HTTP_${response.status}`,
|
|
89
|
+
message: `请求失败(HTTP ${response.status})`
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
let payload;
|
|
93
|
+
try {
|
|
94
|
+
payload = await response.json();
|
|
95
|
+
} catch {
|
|
96
|
+
return badResponse("响应不是合法 JSON");
|
|
97
|
+
}
|
|
98
|
+
if (!isRecord(payload)) return badResponse("响应不是 JSON 对象");
|
|
99
|
+
return {
|
|
100
|
+
ok: true,
|
|
101
|
+
data: payload
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
async test(connection) {
|
|
106
|
+
const result = await postJson("/test", { connection });
|
|
107
|
+
if (!result.ok) return result;
|
|
108
|
+
if (result.data.ok === true) return {
|
|
109
|
+
ok: true,
|
|
110
|
+
data: void 0
|
|
111
|
+
};
|
|
112
|
+
return {
|
|
113
|
+
ok: false,
|
|
114
|
+
error: toConnectorError(result.data.error)
|
|
115
|
+
};
|
|
116
|
+
},
|
|
117
|
+
async describe(connection, sql) {
|
|
118
|
+
const result = await postJson("/describe", {
|
|
119
|
+
connection,
|
|
120
|
+
sql
|
|
121
|
+
});
|
|
122
|
+
if (!result.ok) return result;
|
|
123
|
+
if (result.data.ok !== true) return {
|
|
124
|
+
ok: false,
|
|
125
|
+
error: toConnectorError(result.data.error)
|
|
126
|
+
};
|
|
127
|
+
const fields = normalizeFields(result.data.fields);
|
|
128
|
+
if (!fields) return badResponse("describe 响应缺少合法的 fields 数组");
|
|
129
|
+
return {
|
|
130
|
+
ok: true,
|
|
131
|
+
data: fields
|
|
132
|
+
};
|
|
133
|
+
},
|
|
134
|
+
async query(connection, sql, values) {
|
|
135
|
+
const result = await postJson("/query", {
|
|
136
|
+
connection,
|
|
137
|
+
sql,
|
|
138
|
+
values
|
|
139
|
+
});
|
|
140
|
+
if (!result.ok) return result;
|
|
141
|
+
if (result.data.ok !== true) return {
|
|
142
|
+
ok: false,
|
|
143
|
+
error: toConnectorError(result.data.error)
|
|
144
|
+
};
|
|
145
|
+
const fields = normalizeFields(result.data.fields);
|
|
146
|
+
if (!fields) return badResponse("query 响应缺少合法的 fields 数组");
|
|
147
|
+
if (!Array.isArray(result.data.rows)) return badResponse("query 响应缺少 rows 数组");
|
|
148
|
+
return {
|
|
149
|
+
ok: true,
|
|
150
|
+
data: {
|
|
151
|
+
fields,
|
|
152
|
+
rows: result.data.rows
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
//#endregion
|
|
159
|
+
export { DEFAULT_CONNECTION_PORTS, createHttpConnector, resolvePortOnTypeChange };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Sheet } from "@veltra/sheet-core";
|
|
2
|
+
import { ColumnDef } from "hucre";
|
|
3
|
+
//#region src/report/export-xlsx.d.ts
|
|
4
|
+
/** 列宽条目:模型列索引 → 像素宽(sheet-core 列宽未进 SheetSnapshot,导出时由调用方显式传入) */
|
|
5
|
+
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
|
+
/**
|
|
11
|
+
* 将已填充的 Sheet(Filled Report)导出为保真 XLSX(合并 / 样式 / 行高 / 列宽)。
|
|
12
|
+
* 条件样式颜色已在 renderReport 展开阶段打平进 StylePool(ADR-0001 决策 2)。
|
|
13
|
+
*
|
|
14
|
+
* 与 `exportWorkbookXlsx`(sheet-core)的差异:列宽未进 SheetSnapshot,
|
|
15
|
+
* 只能经 VTable 运行时读取,故这里接收显式列宽并写入 columns 定义。
|
|
16
|
+
*/
|
|
17
|
+
declare function exportFilledReportXlsx(sheet: Sheet, colWidths: ReadonlyArray<ReportColWidthEntry>): Promise<Uint8Array>;
|
|
18
|
+
//#endregion
|
|
19
|
+
export { ReportColWidthEntry, buildColumnDefs, exportFilledReportXlsx, pxToExcelColWidth };
|