@cluadwong/form-designer 0.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/LICENSE +21 -0
- package/README.md +261 -0
- package/dist/chunks/designer-ui.js +3092 -0
- package/dist/chunks/renderer-core.js +2635 -0
- package/dist/components/designer/CanvasSurface.vue.d.ts +64 -0
- package/dist/components/designer/CanvasSurface.vue.d.ts.map +1 -0
- package/dist/components/designer/DesignerToolbar.vue.d.ts +49 -0
- package/dist/components/designer/DesignerToolbar.vue.d.ts.map +1 -0
- package/dist/components/designer/FormDesigner.vue.d.ts +25 -0
- package/dist/components/designer/FormDesigner.vue.d.ts.map +1 -0
- package/dist/components/designer/HelpPanel.vue.d.ts +10 -0
- package/dist/components/designer/HelpPanel.vue.d.ts.map +1 -0
- package/dist/components/designer/InspectorPanel.vue.d.ts +48 -0
- package/dist/components/designer/InspectorPanel.vue.d.ts.map +1 -0
- package/dist/components/designer/NodeTreeItem.vue.d.ts +18 -0
- package/dist/components/designer/NodeTreeItem.vue.d.ts.map +1 -0
- package/dist/components/designer/PaletteSidebar.vue.d.ts +29 -0
- package/dist/components/designer/PaletteSidebar.vue.d.ts.map +1 -0
- package/dist/components/designer/StatusBar.vue.d.ts +25 -0
- package/dist/components/designer/StatusBar.vue.d.ts.map +1 -0
- package/dist/components/designer/composables/treeControl.d.ts +65 -0
- package/dist/components/designer/composables/treeControl.d.ts.map +1 -0
- package/dist/components/designer/composables/useFillData.d.ts +34 -0
- package/dist/components/designer/composables/useFillData.d.ts.map +1 -0
- package/dist/components/designer/composables/useNodeSelection.d.ts +56 -0
- package/dist/components/designer/composables/useNodeSelection.d.ts.map +1 -0
- package/dist/components/designer/composables/useSchemaDocument.d.ts +44 -0
- package/dist/components/designer/composables/useSchemaDocument.d.ts.map +1 -0
- package/dist/components/designer/composables/useSchemaEdits.d.ts +111 -0
- package/dist/components/designer/composables/useSchemaEdits.d.ts.map +1 -0
- package/dist/components/designer/config.d.ts +40 -0
- package/dist/components/designer/config.d.ts.map +1 -0
- package/dist/components/designer/export-api.d.ts +81 -0
- package/dist/components/designer/export-api.d.ts.map +1 -0
- package/dist/components/designer/inspectors/CellInspector.vue.d.ts +20 -0
- package/dist/components/designer/inspectors/CellInspector.vue.d.ts.map +1 -0
- package/dist/components/designer/inspectors/FieldPInspector.vue.d.ts +10 -0
- package/dist/components/designer/inspectors/FieldPInspector.vue.d.ts.map +1 -0
- package/dist/components/designer/inspectors/GridInspector.vue.d.ts +10 -0
- package/dist/components/designer/inspectors/GridInspector.vue.d.ts.map +1 -0
- package/dist/components/designer/inspectors/HeaderFooterFields.vue.d.ts +14 -0
- package/dist/components/designer/inspectors/HeaderFooterFields.vue.d.ts.map +1 -0
- package/dist/components/designer/inspectors/HtmlInspector.vue.d.ts +10 -0
- package/dist/components/designer/inspectors/HtmlInspector.vue.d.ts.map +1 -0
- package/dist/components/designer/inspectors/ImageInspector.vue.d.ts +10 -0
- package/dist/components/designer/inspectors/ImageInspector.vue.d.ts.map +1 -0
- package/dist/components/designer/inspectors/IssuesPanel.vue.d.ts +11 -0
- package/dist/components/designer/inspectors/IssuesPanel.vue.d.ts.map +1 -0
- package/dist/components/designer/inspectors/PageInspector.vue.d.ts +27 -0
- package/dist/components/designer/inspectors/PageInspector.vue.d.ts.map +1 -0
- package/dist/components/designer/inspectors/TableInspector.vue.d.ts +10 -0
- package/dist/components/designer/inspectors/TableInspector.vue.d.ts.map +1 -0
- package/dist/components/designer/inspectors/TextInspector.vue.d.ts +10 -0
- package/dist/components/designer/inspectors/TextInspector.vue.d.ts.map +1 -0
- package/dist/components/designer/inspectors/TextStyleFields.vue.d.ts +10 -0
- package/dist/components/designer/inspectors/TextStyleFields.vue.d.ts.map +1 -0
- package/dist/components/renderer-v2/FormRenderer.vue.d.ts +106 -0
- package/dist/components/renderer-v2/FormRenderer.vue.d.ts.map +1 -0
- package/dist/components/renderer-v2/GridFormRenderer.vue.d.ts +49 -0
- package/dist/components/renderer-v2/GridFormRenderer.vue.d.ts.map +1 -0
- package/dist/components/renderer-v2/GridSchemaNode.vue.d.ts +46 -0
- package/dist/components/renderer-v2/GridSchemaNode.vue.d.ts.map +1 -0
- package/dist/components/renderer-v2/HtmlBlock.vue.d.ts +16 -0
- package/dist/components/renderer-v2/HtmlBlock.vue.d.ts.map +1 -0
- package/dist/components/renderer-v2/PaperViewport.vue.d.ts +63 -0
- package/dist/components/renderer-v2/PaperViewport.vue.d.ts.map +1 -0
- package/dist/components/renderer-v2/collectFieldValues.d.ts +29 -0
- package/dist/components/renderer-v2/collectFieldValues.d.ts.map +1 -0
- package/dist/components/renderer-v2/index.d.ts +13 -0
- package/dist/components/renderer-v2/index.d.ts.map +1 -0
- package/dist/components/renderer-v2/measure-rows.d.ts +12 -0
- package/dist/components/renderer-v2/measure-rows.d.ts.map +1 -0
- package/dist/components/renderer-v2/page-size-style.d.ts +28 -0
- package/dist/components/renderer-v2/page-size-style.d.ts.map +1 -0
- package/dist/components/renderer-v2/print-form.d.ts +20 -0
- package/dist/components/renderer-v2/print-form.d.ts.map +1 -0
- package/dist/designer-ui.css +5 -0
- package/dist/designer.d.ts +16 -0
- package/dist/designer.d.ts.map +1 -0
- package/dist/designer.js +16 -0
- package/dist/engine-v2/derivation.d.ts +81 -0
- package/dist/engine-v2/derivation.d.ts.map +1 -0
- package/dist/engine-v2/index.d.ts +3 -0
- package/dist/engine-v2/index.d.ts.map +1 -0
- package/dist/engine-v2/node-address.d.ts +25 -0
- package/dist/engine-v2/node-address.d.ts.map +1 -0
- package/dist/engine-v2/pagination.d.ts +120 -0
- package/dist/engine-v2/pagination.d.ts.map +1 -0
- package/dist/i18n/en.d.ts +7 -0
- package/dist/i18n/en.d.ts.map +1 -0
- package/dist/i18n/index.d.ts +14 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/types.d.ts +5 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/i18n/zh-CN.d.ts +7 -0
- package/dist/i18n/zh-CN.d.ts.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +107 -0
- package/dist/renderer-core.css +1 -0
- package/dist/renderer.d.ts +22 -0
- package/dist/renderer.d.ts.map +1 -0
- package/dist/renderer.js +93 -0
- package/dist/samples/types.d.ts +18 -0
- package/dist/samples/types.d.ts.map +1 -0
- package/dist/ticket-designer.css +5 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/schema-v2-index.d.ts +15 -0
- package/dist/types/schema-v2-index.d.ts.map +1 -0
- package/dist/types/schema-v2-operations.d.ts +124 -0
- package/dist/types/schema-v2-operations.d.ts.map +1 -0
- package/dist/types/schema-v2-serialization.d.ts +30 -0
- package/dist/types/schema-v2-serialization.d.ts.map +1 -0
- package/dist/types/schema-v2-table-rows.d.ts +17 -0
- package/dist/types/schema-v2-table-rows.d.ts.map +1 -0
- package/dist/types/schema-v2-validation.d.ts +10 -0
- package/dist/types/schema-v2-validation.d.ts.map +1 -0
- package/dist/types/schema-v2.d.ts +283 -0
- package/dist/types/schema-v2.d.ts.map +1 -0
- package/dist/utils/date-format.d.ts +34 -0
- package/dist/utils/date-format.d.ts.map +1 -0
- package/package.json +96 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GridFormRenderer.vue.d.ts","sourceRoot":"","sources":["../../../src/components/renderer-v2/GridFormRenderer.vue"],"names":[],"mappings":"AA4ZA,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,UAAU,EAEf,KAAK,iBAAiB,EAGvB,MAAM,SAAS,CAAC;AAejB,KAAK,WAAW,GAAG;IACf,MAAM,EAAE,YAAY,CAAC;IACrB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,2DAA2D;IAC3D,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CACtD,CAAC;;;;;;;;cARW,OAAO;;AA4XtB,wBAQG"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { FormNodeV2, FieldActionTriggerV2, FieldPermissionV2, FormDataV2 } from "../../types";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
node: FormNodeV2;
|
|
4
|
+
baseRowHeight: number;
|
|
5
|
+
/**
|
|
6
|
+
* 渲染模式(A1 / A5):显式声明调用方意图,取代旧版靠 `data != null` 推断三态。
|
|
7
|
+
* - design:设计态,字段 contenteditable 就地占位(不回写 schema),结构可拖拽/选中。
|
|
8
|
+
* - preview:带数据回显,**字段可输入**(消费模板、输入数据以配合流程流转)。
|
|
9
|
+
* 未传时向后兼容:有 `data` → preview,否则 design。
|
|
10
|
+
* ⚠️ `mode` 不决定可编辑性;真正的「不可输入」由 `readonly` 闸门决定(见下)。
|
|
11
|
+
*/
|
|
12
|
+
mode?: "design" | "preview";
|
|
13
|
+
data?: FormDataV2 | null;
|
|
14
|
+
/**
|
|
15
|
+
* 只读闸门:为 `true` 时字段一律不可输入(真·只读回显/打印浏览)。
|
|
16
|
+
* 与 `mode` **正交**——`mode="preview"` + `readonly` 才是消费页的只读回显;
|
|
17
|
+
* `mode="preview"` + 不传 `readonly` 仍可输入(设计器预览态即显式传 `:readonly="false"`)。
|
|
18
|
+
*/
|
|
19
|
+
readonly?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* 相邻 Grid 外框去重(Item 2):当本 Grid 与相邻兄弟 Grid 都配置了外框时,
|
|
22
|
+
* 由父级(页面竖向堆叠 / 单元格横向排布)传入需要隐藏的边框侧,避免重叠成 2px。
|
|
23
|
+
* 仅隐藏「后一个」Grid 的引导侧(页面级 top / 单元格级 left),保留前者的拖尾侧单线。
|
|
24
|
+
*/
|
|
25
|
+
suppressBorders?: {
|
|
26
|
+
top?: boolean;
|
|
27
|
+
right?: boolean;
|
|
28
|
+
bottom?: boolean;
|
|
29
|
+
left?: boolean;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* 字段级运行时权限(P9.2a/P9.2b,与 `data` 同轨经 props 注入,不进 schema):
|
|
33
|
+
* 按字段名映射 READ(只读回显)/ EDIT(可输入,缺省)/ HIDDEN(隐藏但保留占位)。
|
|
34
|
+
* 设计态不注入(undefined)→ 恒为 EDIT,设计交互不受影响。
|
|
35
|
+
*/
|
|
36
|
+
fieldPermissions?: Record<string, FieldPermissionV2>;
|
|
37
|
+
};
|
|
38
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
39
|
+
"field-change": (field: string, value: string) => any;
|
|
40
|
+
"action-trigger": (payload: FieldActionTriggerV2) => any;
|
|
41
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
42
|
+
"onField-change"?: ((field: string, value: string) => any) | undefined;
|
|
43
|
+
"onAction-trigger"?: ((payload: FieldActionTriggerV2) => any) | undefined;
|
|
44
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
45
|
+
export default _default;
|
|
46
|
+
//# sourceMappingURL=GridSchemaNode.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GridSchemaNode.vue.d.ts","sourceRoot":"","sources":["../../../src/components/renderer-v2/GridSchemaNode.vue"],"names":[],"mappings":"AA2jCA,OAAO,KAAK,EACV,UAAU,EACV,oBAAoB,EACpB,iBAAiB,EAQjB,UAAU,EACX,MAAM,SAAS,CAAC;AA2BjB,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAC;IAC5B,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE;QAChB,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,KAAK,CAAC,EAAE,OAAO,CAAC;QAChB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;IACF;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CACtD,CAAC;;;;;;;;AAu3BF,wBAOG"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { FieldPermissionV2, HtmlNodeV2, FormDataV2 } from "../../types";
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
node: HtmlNodeV2;
|
|
4
|
+
data?: FormDataV2 | null;
|
|
5
|
+
/** 只读硬闸门(与 GridSchemaNode 同轨);为 true 时字段一律不可编辑。 */
|
|
6
|
+
readonly?: boolean;
|
|
7
|
+
/** 字段级权限(P9.2d,与 P 字段同轨经 props 注入):READ/HIDDEN 作用于 HTML 内 {{field}}。 */
|
|
8
|
+
fieldPermissions?: Record<string, FieldPermissionV2>;
|
|
9
|
+
};
|
|
10
|
+
declare const _default: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
11
|
+
"field-change": (field: string, value: string) => any;
|
|
12
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
13
|
+
"onField-change"?: ((field: string, value: string) => any) | undefined;
|
|
14
|
+
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
15
|
+
export default _default;
|
|
16
|
+
//# sourceMappingURL=HtmlBlock.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HtmlBlock.vue.d.ts","sourceRoot":"","sources":["../../../src/components/renderer-v2/HtmlBlock.vue"],"names":[],"mappings":"AAqLA,OAAO,KAAK,EAAE,iBAAiB,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAEzE,KAAK,WAAW,GAAG;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CACtD,CAAC;;;;;;AAiMF,wBAOG"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 纸张视口(表面层 · 浏览缩放)
|
|
3
|
+
*
|
|
4
|
+
* 纯「视图/浏览」外壳:把渲染内核(GridFormRenderer)或设计表面层(CanvasSurface)
|
|
5
|
+
* 包进一个可平移 / 缩放的视口,内核与表面层保持纯净(schema + 交互,不含缩放态)。
|
|
6
|
+
*
|
|
7
|
+
* 选型:@panzoom/panzoom(timmywil,v4)——
|
|
8
|
+
* - 拖拽平移 + 滚轮缩放(`zoomWithWheel` 需手动绑定,v4 不自动绑 wheel)+ 触屏双指捏合(`pinch` 内置);
|
|
9
|
+
* - 通过 `excludeClass`(默认 `panzoom-exclude`)排除指定元素上的「平移手势」:被排除元素的指针按下不触发 pan,
|
|
10
|
+
* 从而表单字段可正常编辑/选中、设计态可拖拽节点;其余空白区域照常平移。
|
|
11
|
+
* - 缩放变化(滚轮 / 捏合 / 按钮 / reset)统一经原生事件 `panzoomchange`(`detail.scale`)同步百分比显示。
|
|
12
|
+
*
|
|
13
|
+
* 打印安全:`@media print` 下 `.paper-viewport__scaler { transform: none !important }` 覆盖 panzoom 内联 transform,
|
|
14
|
+
* 配合内核 `@media print`(`grid-form-canvas` 转 `overflow:visible`、纸张 `margin:0`)走真实 mm 出页,缩放被完全忽略。
|
|
15
|
+
*
|
|
16
|
+
* 注意:panzoom 会在 `onMounted` 时给 scaler(`userSelect:none`)与 parent(`.paper-viewport` `overflow:hidden`、
|
|
17
|
+
* `touchAction:none`)写内联样式;本组件在挂载后把 scaler/parent 的 `userSelect` 复位为 `''`(被排除的字段单独设为 text),
|
|
18
|
+
* 否则字段内文本无法选中;打印时由 `!important` 复位 `overflow` / `transform`。
|
|
19
|
+
*/
|
|
20
|
+
type __VLS_Props = {
|
|
21
|
+
/** 初始缩放比例(默认 1 = 100%)。 */
|
|
22
|
+
initialScale?: number;
|
|
23
|
+
/** 挂载后自动适应宽度(窄屏 / 移动端查看场景)。 */
|
|
24
|
+
fitOnMount?: boolean;
|
|
25
|
+
/** 允许的最小缩放(默认 0.2)。 */
|
|
26
|
+
minScale?: number;
|
|
27
|
+
/** 允许的最大缩放(默认 4)。 */
|
|
28
|
+
maxScale?: number;
|
|
29
|
+
};
|
|
30
|
+
declare function zoomIn(): void;
|
|
31
|
+
declare function zoomOut(): void;
|
|
32
|
+
declare function reset(): void;
|
|
33
|
+
/** 适应宽度:按视口可见宽 / 内容自然宽算缩放;jsdom / 未布局时回退初始比例,不抛错。 */
|
|
34
|
+
declare function fitWidth(): void;
|
|
35
|
+
declare function getScaleValue(): number;
|
|
36
|
+
declare var __VLS_1: {};
|
|
37
|
+
type __VLS_Slots = {} & {
|
|
38
|
+
default?: (props: typeof __VLS_1) => any;
|
|
39
|
+
};
|
|
40
|
+
declare const __VLS_component: import("vue").DefineComponent<__VLS_Props, {
|
|
41
|
+
zoomIn: typeof zoomIn;
|
|
42
|
+
zoomOut: typeof zoomOut;
|
|
43
|
+
reset: typeof reset;
|
|
44
|
+
fitWidth: typeof fitWidth;
|
|
45
|
+
getScale: typeof getScaleValue;
|
|
46
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
47
|
+
"scale-change": (scale: number) => any;
|
|
48
|
+
}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
49
|
+
"onScale-change"?: ((scale: number) => any) | undefined;
|
|
50
|
+
}>, {
|
|
51
|
+
initialScale: number;
|
|
52
|
+
fitOnMount: boolean;
|
|
53
|
+
minScale: number;
|
|
54
|
+
maxScale: number;
|
|
55
|
+
}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
56
|
+
declare const _default: __VLS_WithSlots<typeof __VLS_component, __VLS_Slots>;
|
|
57
|
+
export default _default;
|
|
58
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
59
|
+
new (): {
|
|
60
|
+
$slots: S;
|
|
61
|
+
};
|
|
62
|
+
};
|
|
63
|
+
//# sourceMappingURL=PaperViewport.vue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PaperViewport.vue.d.ts","sourceRoot":"","sources":["../../../src/components/renderer-v2/PaperViewport.vue"],"names":[],"mappings":"AAqXA;;;;;;;;;;;;;;;;;;GAkBG;AACH,KAAK,WAAW,GAAG;IACf,2BAA2B;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,uBAAuB;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qBAAqB;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAmHJ,iBAAS,MAAM,IAAI,IAAI,CAGtB;AAED,iBAAS,OAAO,IAAI,IAAI,CAGvB;AAED,iBAAS,KAAK,IAAI,IAAI,CAErB;AAED,qDAAqD;AACrD,iBAAS,QAAQ,IAAI,IAAI,CAWxB;AAED,iBAAS,aAAa,IAAI,MAAM,CAE/B;AA6ID,QAAA,IAAI,OAAO,IAAW,CAAE;AACxB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AA+B/C,QAAA,MAAM,eAAe;;;;;;;;;;;kBAtUF,MAAM;gBAER,OAAO;cAET,MAAM;cAEN,MAAM;6EAyUnB,CAAC;wBACkB,eAAe,CAAC,OAAO,eAAe,EAAE,WAAW,CAAC;AAAzE,wBAA0E;AAa1E,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KAEV,CAAA;CACD,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { FormDataV2 } from "../../types";
|
|
2
|
+
export interface CollectFieldValuesOptions {
|
|
3
|
+
/**
|
|
4
|
+
* 脱敏字段(HIDDEN)的真实值来源(响应式数据侧,如 `previewFormData`):
|
|
5
|
+
* 本机「保存数据」时回源真实数据,保证 保存→读取 循环不丢值。
|
|
6
|
+
*/
|
|
7
|
+
baseData?: FormDataV2 | null;
|
|
8
|
+
/**
|
|
9
|
+
* 脱敏导出口径(P9.2b,用户拍板):为 `true` 时 HIDDEN 字段采集为 `***`
|
|
10
|
+
* (**保持脱敏**,用于「导出数据」外发场景),优先于 `baseData` 回源。
|
|
11
|
+
*/
|
|
12
|
+
maskHidden?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* 通过遍历渲染 DOM 收集字段值(用户需求:预览 / 填写不必逐键回写,改用 DOM 遍历采集)。
|
|
16
|
+
*
|
|
17
|
+
* - 带 `data-field` 的普通文本字段(`<p>` / 复合字段的 `.layout-p__input`)取其文本;
|
|
18
|
+
* - 带 `data-field` 的图片字段(`<img>`)取其 `src`;
|
|
19
|
+
* - 多行(innerBorder 逐行 div)在浏览器中由 `innerText` 还原为带 `\n` 的文本,
|
|
20
|
+
* jsdom 等无 `innerText` 实现时回退 `textContent`(不含换行分隔);
|
|
21
|
+
* - **HIDDEN 脱敏字段**(`.layout-p--hidden`):DOM 中显示的是假值 `***`,按调用方
|
|
22
|
+
* 口径二选一——`maskHidden: true`(「导出数据」外发)→ 采集为 `***` 保持脱敏;
|
|
23
|
+
* 否则从 `baseData` 回源真实数据(本机「保存数据」循环);两者皆无 → 省略该字段
|
|
24
|
+
* (绝不把 DOM 假值当真值采集)。
|
|
25
|
+
*
|
|
26
|
+
* @param root 渲染根容器,如 `.grid-form-canvas` 或 `GridFormRenderer` 的挂载元素。
|
|
27
|
+
*/
|
|
28
|
+
export declare function collectFieldValues(root: ParentNode, options?: CollectFieldValuesOptions): FormDataV2;
|
|
29
|
+
//# sourceMappingURL=collectFieldValues.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collectFieldValues.d.ts","sourceRoot":"","sources":["../../../src/components/renderer-v2/collectFieldValues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,QAAQ,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC7B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,UAAU,EAChB,OAAO,GAAE,yBAA8B,GACtC,UAAU,CAmFZ"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { default as GridFormRenderer } from "./GridFormRenderer.vue";
|
|
2
|
+
export { default as GridSchemaNode } from "./GridSchemaNode.vue";
|
|
3
|
+
export { collectFieldValues } from "./collectFieldValues";
|
|
4
|
+
export type { CollectFieldValuesOptions } from "./collectFieldValues";
|
|
5
|
+
export { setPageSizeStyle, registerPageSizeStyle, currentPageSizeStyle, } from "./page-size-style";
|
|
6
|
+
/**
|
|
7
|
+
* D2:打印触发入口(呈现 + 触发同归渲染内核,宿主不再各自 `window.print()`)。
|
|
8
|
+
* 实现 = vue-print-next 局部打印:只把纸张序列化进同源 iframe,宿主页面其余部分不进打印流。
|
|
9
|
+
* `printForm()` 无参调用会自动找全局第一个内核画布;多实例场景请显式传 `{ root }`。
|
|
10
|
+
*/
|
|
11
|
+
export { printForm, PRINT_PAPER_SELECTOR, PRINT_ROOT_SELECTOR } from "./print-form";
|
|
12
|
+
export type { PrintFormOptions } from "./print-form";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/renderer-v2/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AACrE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EACL,gBAAgB,EAChB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,mBAAmB,CAAC;AAC3B;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACpF,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** CSS px → mm(96dpi)。 */
|
|
2
|
+
export declare const PX_PER_MM: number;
|
|
3
|
+
/**
|
|
4
|
+
* 测量元素真实渲染高度(mm)。
|
|
5
|
+
*
|
|
6
|
+
* ⚠️ **必须用 `offsetHeight`(布局高度),不能用 `getBoundingClientRect().height`**:
|
|
7
|
+
* 后者包含祖先 CSS `transform`,而纸张被 `PaperViewport`(panzoom)以 `transform: scale()`
|
|
8
|
+
* 包裹 —— 缩放 60% 时,10mm 的行会被量成 6mm,分页引擎据此判定「还放得下」,
|
|
9
|
+
* 于是内容溢出纸张却永不换页(内容跑到纸外 / 盖住页脚)。`offsetHeight` 不受 transform 影响。
|
|
10
|
+
*/
|
|
11
|
+
export declare function measureHeightMm(el: HTMLElement): number;
|
|
12
|
+
//# sourceMappingURL=measure-rows.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"measure-rows.d.ts","sourceRoot":"","sources":["../../../src/components/renderer-v2/measure-rows.ts"],"names":[],"mappings":"AAAA,0BAA0B;AAC1B,eAAO,MAAM,SAAS,QAAY,CAAC;AAEnC;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,EAAE,EAAE,WAAW,GAAG,MAAM,CAEvD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 打印纸张尺寸注入(P11-3 修复):把当前 Schema 的纸张尺寸写进全局 `@page` 规则。
|
|
3
|
+
*
|
|
4
|
+
* 背景:`@page` 是**页面级**规则,无法写成组件的 scoped 样式、也无法用 Vue 绑定,
|
|
5
|
+
* 历史上被硬编码在设计器里(`@page { size: A4 }`)——于是屏幕上选 A3 横向
|
|
6
|
+
* (纸张元素 420×297mm)渲染正常,打印却仍按 A4 出页,内容被裁掉。
|
|
7
|
+
*
|
|
8
|
+
* 做法:由渲染内核(`GridFormRenderer`)把 `@page { size: Wmm Hmm; margin: 0 }`
|
|
9
|
+
* 注入到 `document.head` 的单例 `<style>`,纸张切换时更新、最后一个使用者释放后移除。
|
|
10
|
+
* 这样设计器与消费页(`<FormRenderer>`)打印都跟随 Schema,无需各写一遍。
|
|
11
|
+
*
|
|
12
|
+
* 说明:写具体毫米值(`420mm 297mm`)而非 `A3 landscape`——后者在各浏览器
|
|
13
|
+
* 对「关键字 + 方向」的组合支持不一致,指定物理尺寸最稳且与纸张元素完全对齐。
|
|
14
|
+
*/
|
|
15
|
+
/**
|
|
16
|
+
* 设置打印纸张尺寸(幂等,可随纸张切换反复调用)。
|
|
17
|
+
* @param widthMm 纸张宽度(mm),如 A4 纵向 210、A3 横向 420。
|
|
18
|
+
* @param heightMm 纸张高度(mm),如 A4 纵向 297、A3 横向 297。
|
|
19
|
+
*/
|
|
20
|
+
export declare function setPageSizeStyle(widthMm: number, heightMm: number): void;
|
|
21
|
+
/**
|
|
22
|
+
* 登记一个使用者(每个渲染实例在 setup 中调用一次),返回释放函数(交给 `onUnmounted`)。
|
|
23
|
+
* 与 `setPageSizeStyle` 分开,避免「每次更新都计数」导致计数虚高、样式卸不掉。
|
|
24
|
+
*/
|
|
25
|
+
export declare function registerPageSizeStyle(): () => void;
|
|
26
|
+
/** 当前注入的 `@page` 文本(测试 / 调试用);未注入时返回空串。 */
|
|
27
|
+
export declare function currentPageSizeStyle(): string;
|
|
28
|
+
//# sourceMappingURL=page-size-style.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-size-style.d.ts","sourceRoot":"","sources":["../../../src/components/renderer-v2/page-size-style.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAmBH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAIxE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,IAAI,CAUlD;AAED,2CAA2C;AAC3C,wBAAgB,oBAAoB,IAAI,MAAM,CAE7C"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** 物理页元素选择器(内核 `GridFormRenderer` 渲染产物,每张纸一个)。 */
|
|
2
|
+
export declare const PRINT_PAPER_SELECTOR = ".grid-form-paper";
|
|
3
|
+
/** 打印根兜底选择器(`options.root` 未传时用)。 */
|
|
4
|
+
export declare const PRINT_ROOT_SELECTOR = ".grid-form-canvas";
|
|
5
|
+
/** HTML 模块宿主元素选择器(`HtmlBlock.vue` 的根,内容在 Shadow DOM 里)。 */
|
|
6
|
+
export declare const HTML_BLOCK_SELECTOR = ".layout-html";
|
|
7
|
+
export interface PrintFormOptions {
|
|
8
|
+
/** 打印根(含 `.grid-form-paper` 的容器,通常即内核画布)。缺省取全局第一个画布。 */
|
|
9
|
+
root?: HTMLElement | null;
|
|
10
|
+
/** 打印文档标题(浏览器打印框里显示的文档名)。缺省沿用 `document.title`。 */
|
|
11
|
+
title?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* 触发打印当前渲染结果。
|
|
15
|
+
*
|
|
16
|
+
* @param options 见 {@link PrintFormOptions}。无参调用时自动找全局第一个内核画布。
|
|
17
|
+
* @returns 是否真的触发了打印。找不到打印根 / 没有纸张 / 宿主不支持时返回 `false`(不抛错)。
|
|
18
|
+
*/
|
|
19
|
+
export declare function printForm(options?: PrintFormOptions): boolean;
|
|
20
|
+
//# sourceMappingURL=print-form.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"print-form.d.ts","sourceRoot":"","sources":["../../../src/components/renderer-v2/print-form.ts"],"names":[],"mappings":"AAoDA,kDAAkD;AAClD,eAAO,MAAM,oBAAoB,qBAAqB,CAAC;AAEvD,qCAAqC;AACrC,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD,2DAA2D;AAC3D,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAYlD,MAAM,WAAW,gBAAgB;IAC/B,wDAAwD;IACxD,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA0FD;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAqCjE"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/* 以下内容内联自 renderer-core.css:设计器复用渲染内核呈现纸张与版式,必须一并加载 */
|
|
2
|
+
.layout-html[data-v-2c9190b4]{width:100%;min-width:0}.layout-grid[data-v-3f4d7b64]{display:flex;flex-direction:column;width:100%;min-width:0;box-sizing:border-box}.layout-grid__cell--flex[data-v-3f4d7b64]{flex-wrap:wrap}.layout-grid__row[data-v-3f4d7b64]{display:grid;flex:0 0 auto;width:100%;min-width:0;box-sizing:border-box}.layout-grid__cell[data-v-3f4d7b64]{display:flex;min-width:0;min-height:0;box-sizing:border-box;overflow:hidden}.layout-grid__cell--flex>.layout-p[data-v-3f4d7b64],.layout-grid__cell--flex>.layout-text[data-v-3f4d7b64]{flex:0 1 auto;width:auto;min-width:0}.layout-grid--all[data-v-3f4d7b64],.layout-grid--outer[data-v-3f4d7b64]{border:1px solid #111827}.layout-grid--no-top[data-v-3f4d7b64]{border-top:none}.layout-grid--no-right[data-v-3f4d7b64]{border-right:none}.layout-grid--no-bottom[data-v-3f4d7b64]{border-bottom:none}.layout-grid--no-left[data-v-3f4d7b64]{border-left:none}.layout-grid--all>.layout-grid__row:not(:last-child)>.layout-grid__cell[data-v-3f4d7b64],.layout-grid--inner>.layout-grid__row:not(:last-child)>.layout-grid__cell[data-v-3f4d7b64]{border-bottom:1px solid #111827}.layout-grid--all>.layout-grid__row>.layout-grid__cell[data-v-3f4d7b64]:not(:last-child),.layout-grid--inner>.layout-grid__row>.layout-grid__cell[data-v-3f4d7b64]:not(:last-child){border-right:1px solid #111827}.layout-p[data-v-3f4d7b64]{display:flex;flex-wrap:wrap;width:100%;min-width:0;min-height:0;align-self:center;margin:0 1mm;padding:0;align-items:center;box-sizing:border-box;color:#111827;font-size:13px;line-height:1.35;white-space:pre-wrap;overflow-wrap:anywhere;outline:none}.layout-p[data-v-3f4d7b64] div{flex:1 1 100%;width:100%;min-width:0}.layout-p--inner-border[data-v-3f4d7b64] div{border-bottom:1px solid #111827}.layout-text[data-v-3f4d7b64]{display:flex;width:100%;min-width:0;min-height:0;align-self:center;margin:0;padding:0 1mm;align-items:center;box-sizing:border-box;color:#111827;font-size:13px;line-height:1.35;white-space:pre-wrap;overflow-wrap:anywhere;outline:none}.layout-p--field[data-v-3f4d7b64]{cursor:text}.layout-p--composite[data-v-3f4d7b64]{gap:1mm}.layout-p__label[data-v-3f4d7b64]{flex:0 0 auto;white-space:nowrap}.layout-p__input[data-v-3f4d7b64]{display:inline-block;flex:1 1 auto;min-width:12mm;min-height:1.35em;outline:none}.layout-p__value[data-v-3f4d7b64]{flex:1 1 auto;min-width:0;min-height:1.35em;white-space:pre-wrap;overflow-wrap:anywhere}.layout-p__line[data-v-3f4d7b64]{min-height:1.35em;width:100%;text-align:inherit;white-space:pre-wrap;overflow-wrap:anywhere}.layout-p__lines[data-v-3f4d7b64]{display:block;width:100%;outline:none;min-height:1.35em}.layout-p--underline[data-v-3f4d7b64]{border-bottom:1px solid #111827}.layout-table[data-v-3f4d7b64]{display:block;width:100%;min-width:0;box-sizing:border-box;border-collapse:collapse}.layout-table--all[data-v-3f4d7b64],.layout-table--outer[data-v-3f4d7b64]{border:1px solid #111827}.layout-table--all .layout-table__row[data-v-3f4d7b64]:not(:last-child),.layout-table--inner .layout-table__row[data-v-3f4d7b64]:not(:last-child){border-bottom:1px solid #111827}.layout-table--all .layout-table__cell[data-v-3f4d7b64]:not(:last-child),.layout-table--inner .layout-table__cell[data-v-3f4d7b64]:not(:last-child){border-right:1px solid #111827}.layout-table--all .layout-table__header[data-v-3f4d7b64],.layout-table--inner .layout-table__header[data-v-3f4d7b64]{border-bottom:1px solid #111827}.layout-table>thead[data-v-3f4d7b64],.layout-table>tbody[data-v-3f4d7b64]{display:block;width:100%}.layout-table__row[data-v-3f4d7b64]{display:grid;width:100%;min-width:0;flex:0 0 auto}.layout-table__cell[data-v-3f4d7b64]{display:flex;min-width:0;min-height:0;margin:0;padding:0 1mm;align-items:stretch;justify-content:center;box-sizing:border-box}.layout-table__header[data-v-3f4d7b64]{align-items:center;font-weight:600;text-align:center;font-size:16px}.layout-image[data-v-3f4d7b64]{max-width:100%;object-position:center}@media print{.layout-image--blank[data-v-3f4d7b64]{display:none}.layout-p--underline[data-v-3f4d7b64]{border-bottom:none}}.grid-form-canvas[data-v-f3e7b908]{height:100%;overflow:auto;padding:24px;background:#e5e7eb;box-sizing:border-box}.grid-form-canvas--bare[data-v-f3e7b908]{height:auto;padding:0;background:transparent;overflow:visible}.grid-form-paper[data-v-f3e7b908]{margin:0 auto 24px;background:#fff;box-sizing:border-box;box-shadow:0 4px 12px #0f172a24}.grid-form-band[data-v-f3e7b908]{position:absolute;display:grid;grid-template-columns:minmax(0,1fr) auto minmax(0,1fr);align-items:center;box-sizing:border-box;overflow:hidden;font-size:12px;line-height:1.4;color:#111827}.grid-form-band__zone[data-v-f3e7b908]{min-width:0;white-space:nowrap}.grid-form-band__zone--left[data-v-f3e7b908],.grid-form-band__zone--right[data-v-f3e7b908]{overflow:hidden;text-overflow:ellipsis}.grid-form-band__zone--center[data-v-f3e7b908]{text-align:center}.grid-form-band__zone--right[data-v-f3e7b908]{text-align:right}@media print{.grid-form-canvas[data-v-f3e7b908]{height:auto;padding:0;overflow:visible;background:#fff}.grid-form-paper[data-v-f3e7b908]{margin:0;box-shadow:none;break-after:page}.grid-form-paper[data-v-f3e7b908]:last-child{break-after:auto}}.paper-viewport[data-v-2b6e9ef6]{position:relative;width:100%;height:100%;background:#e5e7eb}.paper-viewport__scaler[data-v-2b6e9ef6]{transform-origin:50% 50%;will-change:transform}.paper-viewport.is-space-pan .paper-viewport__scaler[data-v-2b6e9ef6]>*{pointer-events:none}.paper-viewport.is-space-pan[data-v-2b6e9ef6],.paper-viewport.is-space-pan .paper-viewport__scaler[data-v-2b6e9ef6]>*{cursor:grab}.paper-viewport.is-space-pan[data-v-2b6e9ef6]:active{cursor:grabbing}.paper-viewport__bar[data-v-2b6e9ef6]{position:absolute;right:12px;bottom:12px;z-index:20;display:flex;align-items:center;gap:6px;padding:4px 6px;background:#ffffffeb;border:1px solid #cbd5e1;border-radius:8px;box-shadow:0 2px 8px #0f172a1f;font-size:13px;-webkit-user-select:none;user-select:none}.paper-viewport__btn[data-v-2b6e9ef6]{min-width:26px;height:26px;padding:0 6px;border:1px solid #cbd5e1;border-radius:6px;background:#fff;color:#0f172a;cursor:pointer;font-size:14px;line-height:1}.paper-viewport__btn[data-v-2b6e9ef6]:hover{background:#f1f5f9}.paper-viewport__btn--text[data-v-2b6e9ef6]{font-size:12px}.paper-viewport__scale[data-v-2b6e9ef6]{min-width:44px;text-align:center;font-variant-numeric:tabular-nums;color:#334155}@media print{.paper-viewport[data-v-2b6e9ef6]{overflow:visible!important;height:auto!important;background:#fff!important}.paper-viewport__scaler[data-v-2b6e9ef6]{transform:none!important}.paper-viewport__bar[data-v-2b6e9ef6]{display:none!important}}
|
|
3
|
+
|
|
4
|
+
/* ===== 内联自 renderer-core.css 结束 ===== */
|
|
5
|
+
.v2-canvas-surface[data-v-deb3136c]{position:relative;width:100%;height:100%}.v2-canvas-surface--preview[data-v-deb3136c] .grid-form-canvas{padding:24px}.v2-canvas-surface[data-v-deb3136c] .is-design-selected{position:relative;z-index:2;background-color:#2563eb1f!important;box-shadow:inset 0 0 0 2px #2563eb!important}.v2-canvas-surface[data-v-deb3136c] .v2-drop-target{outline:2px dashed #2563eb;outline-offset:-2px;background:#eff6ff}.v2-insertion-line[data-v-deb3136c]{height:2px;background:#2563eb;box-shadow:0 0 0 1px #2563eb66;border-radius:1px;pointer-events:none;z-index:5}@media print{.v2-canvas-surface[data-v-deb3136c] .is-design-selected{background-color:transparent!important;box-shadow:none!important}.v2-canvas-surface[data-v-deb3136c] .v2-drop-target{outline:none!important;background:transparent!important}.v2-canvas-surface .v2-insertion-line[data-v-deb3136c]{display:none!important}}.status-bar[data-v-e5a749ea]{display:flex;align-items:center;justify-content:space-between;padding:0 16px;background:#1f2937;color:#d1d5db;font-size:12px;height:28px}.status-group[data-v-e5a749ea]{display:flex;align-items:center;gap:16px}.status-item[data-v-e5a749ea]{display:inline-flex;align-items:center;gap:4px}.status-item strong[data-v-e5a749ea]{color:#f9fafb}.warning-count.has-warning[data-v-e5a749ea]{color:#fbbf24}.warning-count.has-warning strong[data-v-e5a749ea]{color:#f59e0b}.muted[data-v-e5a749ea]{color:#6b7280}@media print{.status-bar[data-v-e5a749ea]{display:none!important}}.v2-toolbar__dirty[data-v-71ae7003]{padding:1px 8px;border-radius:10px;color:#94a3b8;background:#ffffff14;font-size:11px}.v2-toolbar__dirty--on[data-v-71ae7003]{color:#fde68a;background:#fde68a2e}.v2-toolbar__label[data-v-71ae7003]{align-self:center;margin-right:2px;font-size:12px;color:#9fb3c8}.v2-tree-row[data-v-10a2a207]{display:flex;align-items:center;gap:4px;padding:3px 6px;font-size:12px;line-height:1.5;color:#334155;cursor:pointer;border-radius:3px;-webkit-user-select:none;user-select:none}.v2-tree-row[data-v-10a2a207]:hover{background:#f1f5f9}.v2-tree-row--selected[data-v-10a2a207]{background:#dbeafe;color:#1d4ed8;font-weight:600}.v2-tree-toggle[data-v-10a2a207]{flex:0 0 auto;width:16px;height:16px;padding:0;border:none;background:transparent;color:#64748b;font-size:10px;line-height:16px;cursor:pointer}.v2-tree-dot[data-v-10a2a207]{flex:0 0 auto;width:16px;text-align:center;color:#cbd5e1}.v2-tree-label[data-v-10a2a207]{flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.v2-tree-type[data-v-10a2a207]{flex:0 0 auto;font-size:10px;color:#94a3b8;background:#f8fafc;border:1px solid #e2e8f0;border-radius:3px;padding:0 4px}.v2-sidebar__heading[data-v-91a9dac6]{margin-bottom:14px;color:#334155;font-size:13px;font-weight:700}.v2-sidebar__heading--tree[data-v-91a9dac6]{margin-top:16px;margin-bottom:8px;padding-top:12px;border-top:1px solid #e2e8f0}.v2-tree-head[data-v-91a9dac6]{display:flex;align-items:center;justify-content:space-between}.v2-tree__delete[data-v-91a9dac6]{padding:3px 8px;border:1px solid #fca5a5;border-radius:4px;color:#b91c1c;background:#fff7f7;font-size:12px;font-weight:500;cursor:pointer}.v2-tree__delete[data-v-91a9dac6]:hover:not(:disabled){background:#fee2e2}.v2-tree__delete[data-v-91a9dac6]:disabled{opacity:.45;cursor:not-allowed}.v2-tree__buttons[data-v-91a9dac6]{display:flex;gap:8px;margin-top:8px}.v2-tree__btn[data-v-91a9dac6]{flex:1 1 0;padding:5px 0;border:1px solid #cbd5e1;border-radius:4px;color:#334155;background:#f8fafc;font-size:12px;cursor:pointer}.v2-tree__btn[data-v-91a9dac6]:hover{background:#eef2f7}.v2-tree[data-v-91a9dac6]{max-height:42vh;overflow:auto;border:1px solid #e2e8f0;border-radius:4px;padding:4px 2px;background:#fcfdff}.v2-palette-item[data-v-91a9dac6]{display:block;width:100%;margin-bottom:8px;padding:9px 10px;border:1px solid #d8dee8;border-radius:4px;color:#334155;background:#f8fafc;font-size:12px}.v2-palette-item--button[data-v-91a9dac6]{text-align:left;cursor:pointer}.v2-palette-item--button[data-v-91a9dac6]:disabled{cursor:not-allowed;opacity:.45}.v2-sidebar__group-title[data-v-91a9dac6]{margin:16px 0 8px;padding-left:8px;border-left:3px solid #2563eb;color:#1e293b;font-size:12px;font-weight:700}.v2-sidebar__group-title[data-v-91a9dac6]:first-child{margin-top:0}.v2-col-table[data-v-6aacc8cd]{border:1px solid #e2e8f0;border-radius:6px;overflow:hidden}.v2-col-table__row[data-v-6aacc8cd]{display:grid;grid-template-columns:1fr 1fr 32px;align-items:center;gap:0;border-bottom:1px solid #f1f5f9}.v2-col-table__row[data-v-6aacc8cd]:last-child{border-bottom:none}.v2-col-table__head[data-v-6aacc8cd]{background:#f8fafc;border-bottom:1px solid #e2e8f0!important}.v2-col-table__th[data-v-6aacc8cd]{padding:6px 10px;font-size:11px;font-weight:700;color:#64748b;text-transform:none}.v2-col-table__th--action[data-v-6aacc8cd]{padding:6px 4px}.v2-col-table__input[data-v-6aacc8cd]{width:100%;min-height:32px;padding:4px 8px;border:none;border-right:1px solid #f1f5f9;background:#fff;font-size:12px;color:#1e293b;outline:none;box-sizing:border-box}.v2-col-table__input[data-v-6aacc8cd]:focus{background:#eff6ff;box-shadow:inset 0 0 0 1px #93c5fd}.v2-col-table__input--mono[data-v-6aacc8cd]{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;color:#475569}.v2-inspector__delete[data-v-6aacc8cd]{margin-left:auto;padding:4px 8px;border:1px solid #fca5a5;border-radius:4px;color:#b91c1c;background:#fff7f7;font-size:12px;cursor:pointer}.v2-inspector__delete[data-v-6aacc8cd]:hover:not(:disabled){background:#fee2e2}.v2-inspector__delete[data-v-6aacc8cd]:disabled{opacity:.45;cursor:not-allowed}.v2-inspector__delete--small[data-v-6aacc8cd]{padding:2px 8px;font-size:11px}.v2-add-col[data-v-6aacc8cd]{width:100%;margin-top:8px;border-color:#93c5fd;color:#1d4ed8;background:#eff6ff}.v2-add-col[data-v-6aacc8cd]:hover{background:#dbeafe}.v2-issues[data-v-1f696812]{margin-top:18px;padding:10px;border:1px solid #f0b7b7;border-radius:4px;color:#991b1b;background:#fff5f5;font-size:12px}.v2-issues--ok[data-v-1f696812]{border-color:#b7dfc5;color:#166534;background:#f0fdf4}.v2-issue[data-v-1f696812]{margin-top:6px;line-height:1.45}.v2-issue--selectable[data-v-1f696812]{cursor:pointer}.v2-issue--selectable[data-v-1f696812]:hover{color:#1d4ed8;text-decoration:underline}.v2-sidebar--right[data-v-b0930d9c]{border-right:0;border-left:1px solid #d8dee8}.v2-inspector-row[data-v-b0930d9c]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px;color:#64748b;font-size:12px}.v2-inspector-row--head[data-v-b0930d9c]{position:sticky;top:0;padding-bottom:10px;border-bottom:1px solid #e2e8f0;background:#fff}.v2-inspector-row code[data-v-b0930d9c]{max-width:150px;overflow:hidden;color:#334155;text-overflow:ellipsis;white-space:nowrap}.v2-help[data-v-3f47c5df]{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1000;display:flex;align-items:center;justify-content:center;background:#0f172a73}.v2-help__panel[data-v-3f47c5df]{display:flex;flex-direction:column;width:min(760px,calc(100vw - 48px));max-height:min(86vh,900px);border-radius:8px;background:#fff;box-shadow:0 20px 60px #0f172a40;overflow:hidden}.v2-help__head[data-v-3f47c5df]{display:flex;align-items:center;justify-content:space-between;flex-shrink:0;padding:12px 18px;border-bottom:1px solid #e2e8f0}.v2-help__head h2[data-v-3f47c5df]{margin:0;color:#1e293b;font-size:15px;font-weight:700}.v2-help__close[data-v-3f47c5df]{padding:2px 8px;border:1px solid #cbd5e1;border-radius:4px;color:#475569;background:#f8fafc;font-size:13px;line-height:1.4;cursor:pointer}.v2-help__close[data-v-3f47c5df]:hover{background:#eef2f7}.v2-help__body[data-v-3f47c5df]{padding:6px 18px 18px;overflow-y:auto;color:#334155;font-size:13px;line-height:1.7}.v2-help__body h3[data-v-3f47c5df]{margin:16px 0 6px;padding-left:8px;border-left:3px solid #2563eb;color:#1e293b;font-size:13px;font-weight:700}.v2-help__body p[data-v-3f47c5df]{margin:4px 0}.v2-help__body ul[data-v-3f47c5df],.v2-help__body ol[data-v-3f47c5df]{margin:4px 0;padding-left:20px}.v2-help__body li[data-v-3f47c5df]{margin:2px 0}.v2-help__body table[data-v-3f47c5df]{width:100%;margin:6px 0;border:1px solid #e2e8f0;border-collapse:collapse}.v2-help__body th[data-v-3f47c5df],.v2-help__body td[data-v-3f47c5df]{padding:4px 8px;border:1px solid #e2e8f0;text-align:left;vertical-align:top;font-weight:400}.v2-help__body th[data-v-3f47c5df]{width:34%;color:#1e293b;background:#f8fafc;font-weight:600;white-space:nowrap}.v2-help__tip[data-v-3f47c5df]{margin-top:6px!important;padding:6px 10px;border-radius:4px;background:#eff6ff}@media print{.v2-help[data-v-3f47c5df]{display:none!important}}.v2-toolbar{display:flex;align-items:center;gap:18px;padding:0 18px;color:#f8fafc;background:#172033;overflow-x:auto}.v2-toolbar>*{flex-shrink:0}.v2-toolbar__group{display:flex;gap:6px}.v2-toolbar__group:last-of-type{margin-left:auto}.v2-toolbar__button{height:28px;padding:0 12px;border:1px solid #4c6484;border-radius:4px;color:#f8fafc;background:#263957;cursor:pointer;font-size:12px;white-space:nowrap}.v2-toolbar__button:disabled{cursor:not-allowed;opacity:.4}.v2-toolbar__button--active{border-color:#60a5fa;background:#1d4ed8}.v2-toolbar--row{background:#fff}.v2-sidebar{min-width:0;padding:16px;overflow:auto;background:#fff;border-right:1px solid #d8dee8}.v2-sidebar__subheading{margin:16px 0 8px;color:#64748b;font-size:11px;font-weight:700}.v2-sidebar__hint{margin:18px 2px 0;color:#64748b;font-size:11px;line-height:1.6}.v2-control{display:flex;flex-direction:column;gap:6px;margin:14px 0;color:#475569;font-size:12px}.v2-control input,.v2-control select{width:100%;min-height:30px;padding:0 8px;border:1px solid #cbd5e1;border-radius:4px;box-sizing:border-box;color:#1e293b;background:#fff;font-size:12px}.v2-control input[type=checkbox]{width:16px;min-height:16px;height:16px;margin:0;padding:0;border:none;background:transparent;align-self:flex-start;accent-color:#2563eb;cursor:pointer}.v2-control--inline{flex-direction:column;align-items:stretch;gap:6px;margin:0}.v2-control--toggle{flex-direction:row;align-items:center;gap:6px;margin:14px 0 0}.v2-control--toggle span{color:#475569;font-size:12px}.v2-control--full{grid-column:1 / -1}.v2-grid-dimensions{display:grid;grid-template-columns:1fr 1fr;gap:8px}.v2-grid-dimensions .v2-control{margin:0}.v2-style-grid{display:grid;grid-template-columns:1fr 1fr;gap:8px 12px;margin-bottom:4px}.v2-style-grid .v2-control{margin-bottom:0}.v2-style-grid .v2-control--inline input[type=color]{width:100%;height:26px;padding:0;border:1px solid #cbd5e1;border-radius:3px;background:#fff}.v2-textarea{width:100%;min-height:30px;padding:6px 8px;border:1px solid #cbd5e1;border-radius:4px;box-sizing:border-box;color:#1e293b;background:#fff;font-size:12px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;resize:vertical}.v2-hint{margin:-6px 0 12px;color:#64748b;font-size:11px;line-height:1.6}.v2-hint code{padding:1px 4px;border-radius:3px;background:#f1f5f9;font-size:11px}@media print{.v2-toolbar,.v2-sidebar{display:none!important}}.v2-designer[data-v-c31c7c34]{display:grid;grid-template-rows:48px minmax(0,1fr) 28px;height:var(--v2-designer-height, 100%);min-height:0;overflow:hidden;background:#f3f4f6}.v2-toolbar__file[data-v-c31c7c34]{display:none}.v2-designer__body[data-v-c31c7c34]{display:grid;grid-template-columns:360px minmax(0,1fr) 360px;min-height:0}.v2-canvas[data-v-c31c7c34]{min-width:0;overflow:hidden}@media print{[data-v-c31c7c34] .status-bar{display:none!important}.v2-designer[data-v-c31c7c34],.v2-designer__body[data-v-c31c7c34],.v2-canvas[data-v-c31c7c34]{display:block;height:auto;overflow:visible}}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 设计器入口(模板编排端入口)
|
|
3
|
+
*
|
|
4
|
+
* 需要让用户在宿主系统内编排模板时才引用:`import { FormDesigner } from "@cluadwong/form-designer/designer"`。
|
|
5
|
+
* 会带上设计器全部 UI 与非 scoped 全局样式(styles/designer-ui.css),消费端不要引。
|
|
6
|
+
*
|
|
7
|
+
* 注意:入口文件一律用相对路径 import,理由见 renderer.ts 顶部注释。
|
|
8
|
+
*/
|
|
9
|
+
export { default as FormDesigner } from "./components/designer/FormDesigner.vue";
|
|
10
|
+
export { defaultDesignerUIConfig, resolveDesignerUIConfig, } from "./components/designer/config";
|
|
11
|
+
export type { DesignerUIConfig } from "./components/designer/config";
|
|
12
|
+
export { buildBlankSchema } from "./components/designer/composables/useSchemaDocument";
|
|
13
|
+
export { collectFormData, downloadJsonFile, exportFileName, FILL_DATA_EXPORT_PREFIX, JSON_INDENT, normalizeIncomingSchema, SCHEMA_EXPORT_PREFIX, serializeFormDataJson, serializeSchemaJson, } from "./components/designer/export-api";
|
|
14
|
+
export type { FormDesignerExposed } from "./components/designer/export-api";
|
|
15
|
+
export type { SampleEntry } from "./samples/types";
|
|
16
|
+
//# sourceMappingURL=designer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"designer.d.ts","sourceRoot":"","sources":["../src/designer.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,wCAAwC,CAAC;AAGjF,OAAO,EACL,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAGrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qDAAqD,CAAC;AAIvF,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,uBAAuB,EACvB,WAAW,EACX,uBAAuB,EACvB,oBAAoB,EACpB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,kCAAkC,CAAC;AAC1C,YAAY,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAG5E,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/designer.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { F as s, a as o, J as i, S as n, b as r, c as l, d as m, e as F, f as c, n as g, r as D, s as I, g as t } from "./chunks/designer-ui.js";
|
|
2
|
+
export {
|
|
3
|
+
s as FILL_DATA_EXPORT_PREFIX,
|
|
4
|
+
o as FormDesigner,
|
|
5
|
+
i as JSON_INDENT,
|
|
6
|
+
n as SCHEMA_EXPORT_PREFIX,
|
|
7
|
+
r as buildBlankSchema,
|
|
8
|
+
l as collectFormData,
|
|
9
|
+
m as defaultDesignerUIConfig,
|
|
10
|
+
F as downloadJsonFile,
|
|
11
|
+
c as exportFileName,
|
|
12
|
+
g as normalizeIncomingSchema,
|
|
13
|
+
D as resolveDesignerUIConfig,
|
|
14
|
+
I as serializeFormDataJson,
|
|
15
|
+
t as serializeSchemaJson
|
|
16
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { FieldRuleV2, FormDataV2, FormNodeV2, FormSchemaV2, GridCellV2, GridNodeV2, ImageNodeV2, TableNodeV2 } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* 渲染期领域逻辑(B4 归 engine)。
|
|
4
|
+
*
|
|
5
|
+
* 原本这些"派生 / 布局 / 取值计算"散落在 `../types`(schema-v2-operations /
|
|
6
|
+
* schema-v2-table-rows),导致渲染组件必须 import 类型层才能拿到计算逻辑。
|
|
7
|
+
* 现统一收口到 engine:渲染组件(GridSchemaNode / FormDesigner)只做视图映射,
|
|
8
|
+
* 按 `列key_行号` 派生字段、表格动态行数、字段清单枚举、单元格盒解析均由本模块负责。
|
|
9
|
+
*/
|
|
10
|
+
export interface ResolvedCellBoxV2 {
|
|
11
|
+
padding: number;
|
|
12
|
+
align: "left" | "center" | "right";
|
|
13
|
+
verticalAlign: "top" | "middle" | "bottom";
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 解析图片节点的可显示来源(渲染 / 分页高度估算共用同一真相源)。
|
|
17
|
+
*
|
|
18
|
+
* 取值优先级(与渲染层历史行为一致):
|
|
19
|
+
* 1. 非设计态且配了 `field`、**数据里该字段有值** → 用数据值(可覆盖 `src`);
|
|
20
|
+
* 2. 否则用 `src`;
|
|
21
|
+
* 3. 都没有 → **`null`(无来源)**,渲染层显示占位灰框、分页按 0 高度计。
|
|
22
|
+
*
|
|
23
|
+
* ⚠️ 渲染层与分页估算必须与本函数同口径:屏幕/打印不显示的东西,就不能在分页里占高度,
|
|
24
|
+
* 否则会出现「图片没打印出来却多出一张空白纸」。
|
|
25
|
+
*/
|
|
26
|
+
export declare function resolveImageSourceV2(node: ImageNodeV2, options?: {
|
|
27
|
+
data?: FormDataV2 | null;
|
|
28
|
+
isDesign?: boolean;
|
|
29
|
+
}): string | null;
|
|
30
|
+
/** 解析单元格的内边距 / 对齐:cell 覆盖优先,否则继承 Grid 默认,再否则取引擎常量。 */
|
|
31
|
+
export declare function resolveCellBoxV2(cell: GridCellV2, grid: GridNodeV2): ResolvedCellBoxV2;
|
|
32
|
+
/**
|
|
33
|
+
* 表格列内字段的命名规则:`列key_行号`(行号 1-based)。
|
|
34
|
+
* 例:列 key 为 `工作地点`,第 3 行的字段为 `工作地点_3`。
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildTableRowField(columnKey: string, rowIndex: number): string;
|
|
37
|
+
/**
|
|
38
|
+
* 把表格单元格节点(及其后代 Grid 内的字段 P)的字段绑定到派生名 `列key_行号`。
|
|
39
|
+
* 仅字段 P(`mode: "field"`)被重写;Text / HTML / Image / Table 等保持原样。
|
|
40
|
+
* 嵌套 Grid 内的字段 P 也一并派生(沿用同一 `列key_行号`),保持与表格行一致。
|
|
41
|
+
* 空字符串 field 会被覆盖(派生名非空),故 schema 中手写值无影响。
|
|
42
|
+
*/
|
|
43
|
+
export declare function bindTableRowCell(node: FormNodeV2, columnKey: string, rowIndex: number): FormNodeV2;
|
|
44
|
+
/**
|
|
45
|
+
* 表格运行时行数 = max(配置行数 `minRows`, data 中实际出现过的最大行号)。
|
|
46
|
+
*
|
|
47
|
+
* 表格「可重复 / 动态行」**不是一个 schema 属性**,而是渲染期按 data 推导的行为——
|
|
48
|
+
* 只要 data 里存在超出 `minRows` 的行数据,就要补渲染对应行,保证 data 能被完整看到。
|
|
49
|
+
* 无 data(设计态)、或行模板字段不含有效 `列key_` 前缀时,行数 = `minRows`。
|
|
50
|
+
*/
|
|
51
|
+
export declare function resolveTableRowCount(node: TableNodeV2, data: FormDataV2 | null | undefined): number;
|
|
52
|
+
export interface SchemaFieldInfo {
|
|
53
|
+
key: string;
|
|
54
|
+
kind: "field" | "table-field";
|
|
55
|
+
tableField?: string;
|
|
56
|
+
row?: number;
|
|
57
|
+
label?: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 收集整张 Schema 的完整字段清单(替代 `collectFieldKeys` 仅收手写 field 的局限)。
|
|
61
|
+
*
|
|
62
|
+
* 遍历口径与渲染期 `bindTableRowCell` / `tableTemplate` 完全一致:
|
|
63
|
+
* - 普通字段 P(不在表格内)→ 直接取 `node.field`;
|
|
64
|
+
* - 表格 → 对每列 × `resolveTableRowCount(node, data)` 行,按 `template.columnKey` 配对模板单元格,
|
|
65
|
+
* 生成派生字段 `列key_行号`(kind=table-field);模板内(含嵌套 Grid)的字段 P 同样绑定到该 `列key_行号`;
|
|
66
|
+
* - 嵌套 Grid / 嵌套 Table 递归处理(嵌套 Table 独立派生自身列字段)。
|
|
67
|
+
*/
|
|
68
|
+
export declare function collectSchemaFields(schema: FormSchemaV2, data?: FormDataV2 | null): SchemaFieldInfo[];
|
|
69
|
+
/**
|
|
70
|
+
* 找出当前数据下「值为空」的必填字段(P9.2c 提交校验的引擎侧真相源)。
|
|
71
|
+
*
|
|
72
|
+
* - **规则由消费方经 props 注入**(`FormRenderer` 的 `options.rules`,P9.2c 用户拍板),
|
|
73
|
+
* 与 `data` / `fieldPermissions` 同轨、**不进 schema**——「哪些字段必填」是消费
|
|
74
|
+
* 会话的采集策略,模板不携带。
|
|
75
|
+
* - 空值口径:键缺失 / `undefined` / `""` / 纯空白串都算空。
|
|
76
|
+
* - 只校验 `rules` 里声明了 `required: true` 的键;规则键应为 schema 字段名
|
|
77
|
+
* (指向不存在字段的规则永远校验失败,会让配置错误自然浮出水面)。
|
|
78
|
+
* - 返回字段名数组(按 rules 声明顺序,天然去重——对象键唯一)。
|
|
79
|
+
*/
|
|
80
|
+
export declare function findEmptyRequiredFields(rules: Record<string, FieldRuleV2> | undefined, data: FormDataV2 | null | undefined): string[];
|
|
81
|
+
//# sourceMappingURL=derivation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derivation.d.ts","sourceRoot":"","sources":["../../src/engine-v2/derivation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,UAAU,EACV,YAAY,EACZ,UAAU,EACV,UAAU,EACV,WAAW,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB;;;;;;;GAOG;AAMH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACnC,aAAa,EAAE,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;CAC5C;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,WAAW,EACjB,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GAC7D,MAAM,GAAG,IAAI,CAMf;AAMD,sDAAsD;AACtD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,UAAU,GACf,iBAAiB,CAOnB;AAMD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,UAAU,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,UAAU,CAmBZ;AAYD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,WAAW,EACjB,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GAClC,MAAM,CAWR;AAMD,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,OAAO,GAAG,aAAa,CAAC;IAC9B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,YAAY,EACpB,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,GACvB,eAAe,EAAE,CA6CnB;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,SAAS,EAC9C,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GAClC,MAAM,EAAE,CAQV"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/engine-v2/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 节点地址契约(C2 / A5 分层重构)
|
|
3
|
+
*
|
|
4
|
+
* 渲染内核(renderer-v2)为每个可被设计器交互的节点输出两类定位属性,
|
|
5
|
+
* 设计表面层(designer/CanvasSurface 及 FormDesigner 的拖拽/选中逻辑)据此反查节点与所属格。
|
|
6
|
+
* 内核负责"暴露稳定地址",表面层负责"交互"——这是内核与表面层之间唯一可接受的边界
|
|
7
|
+
* (分层约束见 docs/design.md)。
|
|
8
|
+
*
|
|
9
|
+
* 约定:
|
|
10
|
+
* - `data-node-id`:每个可交互节点的唯一 id(page / grid / row? 否 / cell / p / text / table / html / image)。
|
|
11
|
+
* 注意 row 本身不挂 data-node-id(行是 Grid 的内部布局结构,不可独立选中),但其父 Grid 与子 cell 均挂。
|
|
12
|
+
* - `data-layout-id`:Grid 的 Row 与 Cell、以及 Table 单元格模板的布局定位 id,用于拖拽落点判定
|
|
13
|
+
* (`closest("[data-layout-id]")` 命中目标格 / 行)。
|
|
14
|
+
*
|
|
15
|
+
* 消费方应使用下方常量与选择器辅助函数,避免在多处硬编码属性名字符串导致静默失效。
|
|
16
|
+
*/
|
|
17
|
+
export declare const NODE_ID_ATTR: "data-node-id";
|
|
18
|
+
export declare const LAYOUT_ID_ATTR: "data-layout-id";
|
|
19
|
+
/** 模板面板拖拽到画布时写入 dataTransfer 的 MIME(设计器侧源)。 */
|
|
20
|
+
export declare const PALETTE_DRAG_MIME: "application/x-ticket-node-kind";
|
|
21
|
+
/** 选中某节点的 CSS 选择器,如 `[data-node-id="unit-field"]`。 */
|
|
22
|
+
export declare function nodeIdSelector(id: string): string;
|
|
23
|
+
/** 命中某布局格/行的 CSS 选择器,如 `[data-layout-id="cell-u-l"]`。 */
|
|
24
|
+
export declare function layoutIdSelector(id: string): string;
|
|
25
|
+
//# sourceMappingURL=node-address.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"node-address.d.ts","sourceRoot":"","sources":["../../src/engine-v2/node-address.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,YAAY,EAAG,cAAuB,CAAC;AACpD,eAAO,MAAM,cAAc,EAAG,gBAAyB,CAAC;AACxD,+CAA+C;AAC/C,eAAO,MAAM,iBAAiB,EAAG,gCAAyC,CAAC;AAE3E,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,yDAAyD;AACzD,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema V2 分页引擎(DOM 无关、确定性)。
|
|
3
|
+
*
|
|
4
|
+
* 背景:原 `GridFormRenderer` 用纸张 `min-height` 渲染单个逻辑页,内容超高时只是
|
|
5
|
+
* 在单页内继续向下撑开,看不出「超出纸张高度应换页」的效果。本引擎在** Schema 层**
|
|
6
|
+
* 把每个逻辑 `PageSchemaV2` 的内容流切成若干「物理页」——每页只承载能在纸张正文区
|
|
7
|
+
* (纸张高 − 上/下边距)内放下的节点/网格片段,超高部分流向下一页。
|
|
8
|
+
*
|
|
9
|
+
* 为什么在 Schema 层而不是 DOM 测量层:
|
|
10
|
+
* 固定版式表单里 Grid 的每一行高度是确定性值(`row.height × baseRowHeight` mm,
|
|
11
|
+
* cell.rowHeight 可覆盖所在行高),无需渲染后测量即可得到精确行高。因此本引擎对 Grid
|
|
12
|
+
* 做**精确、可测试**的逐行切分;对 Text/Image/Html/Table 这类内容高度不确定的节点,
|
|
13
|
+
* 用启发式估算(并可注入 DOM 测量回调 `measureNode` 提升精度),整块落页或整体换页。
|
|
14
|
+
*
|
|
15
|
+
* 自动分页(2026-09-03 二十续):纯确定性估算可能误判——多行字段、换行文本、超大图片等
|
|
16
|
+
* 实际渲染高度会高于 `row.height × baseRowHeight` 的估算值,导致引擎认为「放得下」的页
|
|
17
|
+
* 实际却溢出纸张。为此本引擎支持注入**真实测量高度** `measureRow`(逐 Grid 行)与
|
|
18
|
+
* `measureNode`(原子节点),由渲染层在浏览器里测量实际渲染高度后二次校正分页,
|
|
19
|
+
* 保证「内容超高 → 自动换页、永不溢出纸外」(设计态与渲染态共用同一修正通道)。
|
|
20
|
+
*
|
|
21
|
+
* 旧版 v1 引擎(`src/engine`,基于 DOM 测量 + FormSchema/Component 旧模型)已于
|
|
22
|
+
* 2026-09-02 十八续删除;本文件是全项目**唯一**的分页实现。
|
|
23
|
+
*
|
|
24
|
+
* 切分语义:
|
|
25
|
+
* - Grid 可跨页:按行边界切;首个片段保留上边框、末片段保留下边框,中间片段用
|
|
26
|
+
* `suppressBorders` 抑制上/下边框,使多页连起来像一张被「拆开」的连续表格。
|
|
27
|
+
* - 其它节点为原子块:当前页放得下就放,放不下(且本页已有内容)就换页;单个节点比整页还高
|
|
28
|
+
* 则强制放入并产出 warning(渲染层 overflow 兜底)。
|
|
29
|
+
*
|
|
30
|
+
* 输出 `PhysicalPage[]` 直接喂给渲染层:每个物理页对应一个 `<main class="grid-form-paper">`
|
|
31
|
+
* ,其 `children` 是要渲染的节点/网格片段(`FormNodeV2`,片段即裁剪了 rows 的 GridNodeV2)。
|
|
32
|
+
*/
|
|
33
|
+
import type { EdgeInsetsV2, FormDataV2, FormNodeV2, FormSchemaV2, GridNodeV2, GridRowV2, PageSchemaV2 } from "../types";
|
|
34
|
+
/**
|
|
35
|
+
* 单行高度(mm)。行高 = `max(row.height, 该行任意 cell.rowHeight 覆盖值) × baseRowHeight`,
|
|
36
|
+
* 与 `GridSchemaNode.gridRowStyle` 的 `min-height: row.height * baseRowHeight` 以及
|
|
37
|
+
* cell 的 `min-height: cell.rowHeight * baseRowHeight`(行容器按最高单元格撑开)一致。
|
|
38
|
+
*/
|
|
39
|
+
export declare function gridRowHeightMm(baseRowHeight: number, row: GridRowV2, measureRow?: (row: GridRowV2) => number | undefined): number;
|
|
40
|
+
/**
|
|
41
|
+
* 一段连续 Grid 行的渲染高度(mm),含行间距与(未抑制的)外框上下边框。
|
|
42
|
+
* @param rows 该片段包含的行(连续)
|
|
43
|
+
* @param suppressTop 是否抑制上边框(非首片段时连续外观用)
|
|
44
|
+
* @param suppressBottom 是否抑制下边框(非末片段时连续外观用)
|
|
45
|
+
* @param measureRow 可选逐行真实测量高度(mm),优先级高于确定性估算。
|
|
46
|
+
*/
|
|
47
|
+
export declare function gridFragmentHeightMm(baseRowHeight: number, grid: GridNodeV2, rows: GridRowV2[], suppressTop: boolean, suppressBottom: boolean, measureRow?: (row: GridRowV2) => number | undefined): number;
|
|
48
|
+
/** Table 节点估算高度(mm):表头 1 行 + 数据行(minRows 或 data 推导,受 _paginateMaxRows 限制)× baseRowHeight + 外框。 */
|
|
49
|
+
export declare function tableHeightMm(node: Extract<FormNodeV2, {
|
|
50
|
+
type: "table";
|
|
51
|
+
}>, baseRowHeight: number, data: FormDataV2 | null | undefined): number;
|
|
52
|
+
/** 分页上下文(高度计算所需的一切)。 */
|
|
53
|
+
export interface PaginateContext {
|
|
54
|
+
/** 表单基准行高(mm)。 */
|
|
55
|
+
baseRowHeight: number;
|
|
56
|
+
/** 正文内容区宽度(mm)= 纸张宽 − 左/右边距,用于 Text 折行估算。 */
|
|
57
|
+
contentWidthMm: number;
|
|
58
|
+
/** 正文可用高(mm)= 纸张高 − 上/下边距。 */
|
|
59
|
+
bodyHeightMm: number;
|
|
60
|
+
/** 填写数据(Table 行数推导用),缺省为 null。 */
|
|
61
|
+
data?: FormDataV2 | null;
|
|
62
|
+
/** 可选 DOM 测量回调:返回节点精确高度(mm)或 undefined 走启发式。 */
|
|
63
|
+
measureNode?: (node: FormNodeV2) => number | undefined;
|
|
64
|
+
/** 可选逐 Grid 行测量回调:返回该行真实渲染高度(mm)或 undefined 走确定性估算。
|
|
65
|
+
* 用于自动分页——真实行高(多行字段/换行文本)高于估算值时,按真实高度切分,避免溢出纸外。 */
|
|
66
|
+
measureRow?: (row: GridRowV2) => number | undefined;
|
|
67
|
+
}
|
|
68
|
+
/** 物理页中的一个子项(节点,或裁剪了 rows 的 Grid 片段)。 */
|
|
69
|
+
export interface PhysicalPageChild {
|
|
70
|
+
node: FormNodeV2;
|
|
71
|
+
/** 该片段需抑制的边框侧(Grid 跨页连续外观用)。 */
|
|
72
|
+
suppressBorders?: {
|
|
73
|
+
top?: boolean;
|
|
74
|
+
right?: boolean;
|
|
75
|
+
bottom?: boolean;
|
|
76
|
+
left?: boolean;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** 一个物理页(对应渲染层一个 `<main class="grid-form-paper">`)。 */
|
|
80
|
+
export interface PhysicalPage {
|
|
81
|
+
/** 物理页稳定 id(基于来源逻辑页 id + 序号)。 */
|
|
82
|
+
id: string;
|
|
83
|
+
/** 来源逻辑页 id。 */
|
|
84
|
+
sourcePageId: string;
|
|
85
|
+
/** 在来源逻辑页内的序号(0-based)。 */
|
|
86
|
+
sourceIndex: number;
|
|
87
|
+
/** 整篇文档内的全局物理页序号(1-based,由 paginateSchema 回填)。 */
|
|
88
|
+
index: number;
|
|
89
|
+
/** 该物理页使用的页边距(等于来源逻辑页边距)。 */
|
|
90
|
+
margin: EdgeInsetsV2;
|
|
91
|
+
/** 需渲染的节点/片段。 */
|
|
92
|
+
children: PhysicalPageChild[];
|
|
93
|
+
}
|
|
94
|
+
/** 分页告警(内容超高被裁剪等)。 */
|
|
95
|
+
export interface PaginateWarning {
|
|
96
|
+
nodeId: string;
|
|
97
|
+
message: string;
|
|
98
|
+
}
|
|
99
|
+
/** 分页结果。 */
|
|
100
|
+
export interface PaginateResult {
|
|
101
|
+
pages: PhysicalPage[];
|
|
102
|
+
warnings: PaginateWarning[];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* 分页单个逻辑页,得到 0..N 个物理页。
|
|
106
|
+
* @param page 逻辑页
|
|
107
|
+
* @param opts 分页上下文
|
|
108
|
+
*/
|
|
109
|
+
export declare function paginatePage(page: PageSchemaV2, opts: PaginateContext): PaginateResult;
|
|
110
|
+
/**
|
|
111
|
+
* 分页整篇 Schema:逐逻辑页分页后拼接,回填全局物理页序号。
|
|
112
|
+
* @param schema 表单 Schema
|
|
113
|
+
* @param extra 额外上下文(data / measureNode);baseRowHeight 取自 schema
|
|
114
|
+
*/
|
|
115
|
+
export declare function paginateSchema(schema: FormSchemaV2, extra?: {
|
|
116
|
+
data?: FormDataV2 | null;
|
|
117
|
+
measureNode?: PaginateContext["measureNode"];
|
|
118
|
+
measureRow?: PaginateContext["measureRow"];
|
|
119
|
+
}): PaginateResult;
|
|
120
|
+
//# sourceMappingURL=pagination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination.d.ts","sourceRoot":"","sources":["../../src/engine-v2/pagination.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,UAAU,EACV,YAAY,EACZ,UAAU,EACV,SAAS,EACT,YAAY,EAEb,MAAM,SAAS,CAAC;AAYjB;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,EACrB,GAAG,EAAE,SAAS,EACd,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,MAAM,GAAG,SAAS,GAClD,MAAM,CAoBR;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,UAAU,EAChB,IAAI,EAAE,SAAS,EAAE,EACjB,WAAW,EAAE,OAAO,EACpB,cAAc,EAAE,OAAO,EACvB,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,MAAM,GAAG,SAAS,GAClD,MAAM,CAYR;AA2BD,kGAAkG;AAClG,wBAAgB,aAAa,CAC3B,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC,EAC5C,aAAa,EAAE,MAAM,EACrB,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,SAAS,GAClC,MAAM,CASR;AAmCD,wBAAwB;AACxB,MAAM,WAAW,eAAe;IAC9B,kBAAkB;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,6CAA6C;IAC7C,cAAc,EAAE,MAAM,CAAC;IACvB,8BAA8B;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,kCAAkC;IAClC,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,gDAAgD;IAChD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,MAAM,GAAG,SAAS,CAAC;IACvD;wDACoD;IACpD,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,SAAS,KAAK,MAAM,GAAG,SAAS,CAAC;CACrD;AAED,yCAAyC;AACzC,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,UAAU,CAAC;IACjB,gCAAgC;IAChC,eAAe,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CACxF;AAED,uDAAuD;AACvD,MAAM,WAAW,YAAY;IAC3B,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,gBAAgB;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,MAAM,EAAE,YAAY,CAAC;IACrB,iBAAiB;IACjB,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,sBAAsB;AACtB,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,YAAY;AACZ,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,GAAG,cAAc,CA4WtF;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,YAAY,EACpB,KAAK,CAAC,EAAE;IACN,IAAI,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IACzB,WAAW,CAAC,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC;IAC7C,UAAU,CAAC,EAAE,eAAe,CAAC,YAAY,CAAC,CAAC;CAC5C,GACA,cAAc,CAoBhB"}
|