@gct-paas/word 0.1.45 → 0.1.46-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +32 -5
  2. package/dist/capabilities/panel/schema/registry.d.ts +1 -1
  3. package/dist/core/cursor/CursorController.d.ts +9 -4
  4. package/dist/core/cursor/composables/useCursorSelection.d.ts +6 -0
  5. package/dist/core/cursor/hit/types.d.ts +2 -0
  6. package/dist/core/cursor/layout/baseMeta.d.ts +2 -0
  7. package/dist/core/cursor/logic/index.d.ts +1 -0
  8. package/dist/core/cursor/logic/resolveCursorState.d.ts +24 -0
  9. package/dist/core/cursor/types/cursor.d.ts +4 -2
  10. package/dist/core/data/DataManager.d.ts +46 -3
  11. package/dist/core/data/data-path-suffix.d.ts +2 -0
  12. package/dist/core/data/enrichers/build-field-enrichers.d.ts +4 -3
  13. package/dist/core/data/enrichers/hyperlink-enricher.d.ts +8 -0
  14. package/dist/core/index.d.ts +2 -1
  15. package/dist/core/layout/handlers/RunHandlerBase.d.ts +13 -0
  16. package/dist/core/layout/handlers/TextHandler.d.ts +2 -6
  17. package/dist/core/layout/handlers/fields/FieldBaseHandler.d.ts +9 -7
  18. package/dist/core/layout/handlers/pageWidgets/TimeDiffHandler.d.ts +17 -0
  19. package/dist/core/layout/handlers/pageWidgets/WidgetBaseHandler.d.ts +6 -15
  20. package/dist/core/layout/handlers/pageWidgets/index.d.ts +1 -0
  21. package/dist/core/view/base/LayoutNode.d.ts +0 -2
  22. package/dist/core/view/runs/ImageWidget.d.ts +4 -9
  23. package/dist/core/view/runs/TextRun.d.ts +3 -2
  24. package/dist/core/view/runs/TextWidget.d.ts +6 -11
  25. package/dist/core/view/types/index.d.ts +9 -0
  26. package/dist/core/widget/field-hyperlink.d.ts +12 -0
  27. package/dist/core/widget/widget-state.d.ts +27 -1
  28. package/dist/domain/constants/enum.d.ts +22 -0
  29. package/dist/domain/field/field-props-schema-type.d.ts +7 -0
  30. package/dist/domain/field/field-type.d.ts +8 -0
  31. package/dist/domain/paper-widget/paper-widget-props-schema-type.d.ts +1 -1
  32. package/dist/domain/paper-widget/paper-widget-type.d.ts +3 -1
  33. package/dist/domain/widget/component-type.d.ts +1 -1
  34. package/dist/index.es.js +3169 -3300
  35. package/dist/runtime/_register_/composables/panel/useActivePanel.d.ts +1 -1
  36. package/dist/runtime/interface/render.d.ts +2 -0
  37. package/dist/runtime/renderer/dropdowns/components/tables/composables/useTableDropdown.d.ts +1 -0
  38. package/dist/runtime/renderer/dropdowns/components/tables/strategy/selectStrategy.d.ts +2 -0
  39. package/dist/sdk/doc-runtime/device-link/resolve-field-focus-context.d.ts +15 -0
  40. package/dist/sdk/doc-runtime/device-link/useDeviceFieldFocusBridge.d.ts +7 -0
  41. package/dist/sdk/doc-runtime/device-link/useFormTmplAndModelInit.d.ts +15 -0
  42. package/dist/sdk/doc-runtime/device-link/useFormTmplConfig.d.ts +10 -0
  43. package/dist/sdk/doc-runtime/factories/document-initializer.d.ts +16 -0
  44. package/dist/sdk/doc-runtime/factories/useDocumentFactory.d.ts +2 -0
  45. package/dist/sdk/doc-runtime/useWord.d.ts +11 -5
  46. package/dist/sdk/engine/index.d.ts +1 -0
  47. package/dist/sdk/plugins/index.d.ts +2 -1
  48. package/dist/sdk/plugins/register-panel-schemas.d.ts +9 -0
  49. package/dist/sdk/types/form-tmpl-config.types.d.ts +123 -0
  50. package/dist/sdk/types/index.d.ts +12 -4
  51. package/dist/sdk/vue/layouts/doc-design-layout.vue.d.ts +2 -5
  52. package/dist/suites/edhr/field-manifest/trace/order-no-manifest.d.ts +2 -0
  53. package/dist/suites/edhr/field-manifest/trace/related-lot-no-manifest.d.ts +2 -0
  54. package/dist/suites/edhr/panel-schema/index.d.ts +0 -5
  55. package/dist/suites/edhr/paper-widget-manifest/basic/timediff-manifest.d.ts +2 -0
  56. package/dist/utils/TriggerUtil.d.ts +1 -1
  57. package/dist/utils/func/core.d.ts +9 -0
  58. package/dist/utils/func/render.d.ts +2 -0
  59. package/dist/word.css +104 -415
  60. package/package.json +1 -1
  61. package/dist/sdk/vue/layouts/doc-design-layout.d.ts +0 -7
  62. package/dist/suites/edhr/panel-schema/data-load/DataLoadPanel.vue.d.ts +0 -2
  63. package/dist/suites/edhr/panel-schema/data-load/ai-tmpl/ai-tmpl-editor.vue.d.ts +0 -6
  64. package/dist/suites/edhr/panel-schema/data-load/ai-tmpl/identify-param-card.vue.d.ts +0 -14
  65. package/dist/suites/edhr/panel-schema/data-load/common/add-tmpl-btn.vue.d.ts +0 -16
  66. package/dist/suites/edhr/panel-schema/data-load/common/decimal-slider.vue.d.ts +0 -21
  67. package/dist/suites/edhr/panel-schema/data-load/common/form-field-select.vue.d.ts +0 -19
  68. package/dist/suites/edhr/panel-schema/data-load/common/icon-tooltip.vue.d.ts +0 -10
  69. package/dist/suites/edhr/panel-schema/data-load/common/remove-icon.vue.d.ts +0 -7
  70. package/dist/suites/edhr/panel-schema/data-load/common/tmpl-card.vue.d.ts +0 -25
  71. package/dist/suites/edhr/panel-schema/data-load/data-load.basic.d.ts +0 -5
  72. package/dist/suites/edhr/panel-schema/data-load/device-tmpl/device-field-status.vue.d.ts +0 -9
  73. package/dist/suites/edhr/panel-schema/data-load/device-tmpl/device-tmpl-editor.vue.d.ts +0 -6
  74. package/dist/suites/edhr/panel-schema/data-load/device-tmpl/params-item-card.vue.d.ts +0 -30
  75. package/dist/suites/edhr/panel-schema/data-load/hooks/device-link/constant.d.ts +0 -44
  76. package/dist/suites/edhr/panel-schema/data-load/hooks/device-link/controller.d.ts +0 -38
  77. package/dist/suites/edhr/panel-schema/data-load/hooks/device-link/index.d.ts +0 -3
  78. package/dist/suites/edhr/panel-schema/data-load/hooks/device-link/types.d.ts +0 -157
  79. package/dist/suites/edhr/panel-schema/data-load/hooks/form-tmpl-config/form-tmpl-config-controller.d.ts +0 -67
  80. package/dist/suites/edhr/panel-schema/data-load/hooks/form-tmpl-config/index.d.ts +0 -2
  81. package/dist/suites/edhr/panel-schema/data-load/hooks/form-tmpl-config/use-form-tmpl-config.d.ts +0 -10
package/README.md CHANGED
@@ -169,7 +169,7 @@ Vue 运行时注册函数。建议在 `createApp` 后、`mount` 前调用。
169
169
 
170
170
  `controller.value` 可用后,主要分为 4 类能力:
171
171
 
172
- 1) 状态字段(响应式):
172
+ 1. 状态字段(响应式):
173
173
 
174
174
  - `id: string`:当前文档实例 id
175
175
  - `mode`:当前渲染模式
@@ -178,12 +178,12 @@ Vue 运行时注册函数。建议在 `createApp` 后、`mount` 前调用。
178
178
  - `pages`:当前页面数组
179
179
  - `docRuntimeMeta`:运行时元信息(接口返回 + 业务拼接)
180
180
 
181
- 2) 查询 API(只读):
181
+ 2. 查询 API(只读):
182
182
 
183
183
  - `query.getWidgetByModelId(modelId)`:按模型字段 id 定位组件节点
184
184
  - `query.getPaperBySecRefId(id)`:按分节 refId 定位页面
185
185
 
186
- 3) 编辑/控制 API:
186
+ 3. 编辑/控制 API:
187
187
 
188
188
  - `execute(command, payload?)`:执行内置命令(高级)
189
189
  - `undo()` / `redo()`:撤销与重做
@@ -192,7 +192,7 @@ Vue 运行时注册函数。建议在 `createApp` 后、`mount` 前调用。
192
192
  - `rawData()`:获取原始填报数据
193
193
  - `reload()`:手动触发文档重载
194
194
 
195
- 4) 数据处理 API:
195
+ 4. 数据处理 API:
196
196
 
197
197
  - `validate()`:校验字段,返回错误映射或 `null`
198
198
  - `exportModel()`:导出 XmlJson 模型数据
@@ -223,7 +223,7 @@ if (!errors) {
223
223
  - 初始化 API:`setupPlatformAdapters`、`setupVueRuntime`
224
224
  - 引擎/类型:`useWord`、`DocModeTypeConst`、`PageSizeEnumConst`、`BuiltinComponentTypeConst`、`WordRuntime`、`DocController` 等
225
225
  - Vue 组件:`DocDesignLayout`、`DocRenderLayout`、`GctLayout`
226
- - 插件能力:`registerSuite`、`WordSuitePlugin`、`edhrSuitePlugin`
226
+ - 插件能力:`registerSuite`、`WordSuitePlugin`、`edhrSuitePlugin`、`registerPanelSchemas`
227
227
 
228
228
  ## 插件扩展
229
229
 
@@ -262,6 +262,33 @@ const customPlugin: WordSuitePlugin = {
262
262
  };
263
263
  ```
264
264
 
265
+ ### 主工程注册属性面板(如数据加载)
266
+
267
+ `edhrSuitePlugin` 不再内置注册 `data-load.basic`,需在 **edhr 插件之后** 由主工程注册:
268
+
269
+ ```ts
270
+ import { edhrSuitePlugin, registerPanelSchemas, type WordSuitePlugin } from '@gct-paas/word';
271
+ import DataLoadPanel from './panels/data-load/DataLoadPanel.vue';
272
+
273
+ const hostPanelPlugin: WordSuitePlugin = {
274
+ key: 'host-panels',
275
+ install() {
276
+ registerPanelSchemas('edhr', {
277
+ 'data-load.basic': {
278
+ key: 'data-load.basic',
279
+ title: '数据加载',
280
+ render: DataLoadPanel,
281
+ },
282
+ });
283
+ },
284
+ };
285
+
286
+ setupPlatformAdapters({
287
+ // ...
288
+ plugins: [edhrSuitePlugin, hostPanelPlugin],
289
+ });
290
+ ```
291
+
265
292
  ## 最佳实践
266
293
 
267
294
  - `setupPlatformAdapters` 只在应用启动时调用一次,避免重复注册全局能力。
@@ -2,6 +2,6 @@ import { BaseRegistry } from '../../base/BaseRegistry';
2
2
  import { PanelSchema, PanelSchemaKey, PanelSchemaMap } from './types';
3
3
  /** 面板组件注册表 */
4
4
  export declare class PanelSchemaRegistry extends BaseRegistry<PanelSchemaKey, PanelSchema> {
5
- register(suiteKey: SuiteKey, components: PanelSchemaMap): void;
5
+ register(suiteKey: SuiteKey, components: PanelSchemaMap, override?: boolean): void;
6
6
  }
7
7
  export declare const panelSchemaRegistry: PanelSchemaRegistry;
@@ -1,3 +1,4 @@
1
+ import { CommandResult } from '../command/types';
1
2
  import { Doc } from '../view/Doc';
2
3
  import { MoveOpts } from '../event/types';
3
4
  import { PointerHitResult } from './hit/types';
@@ -25,10 +26,14 @@ export declare class CursorController {
25
26
  }): void;
26
27
  private flushDragMove;
27
28
  onDragEndAt(_canvasX: number, _canvasY: number, pid: number | null, pos?: Pos): void;
28
- /** 将当前光标重新对齐到指定节点 */
29
- resolveCursorAtNode(data: any): void;
30
- /** 将光标设置为选区对齐到指定节点 */
31
- resolveCursorRange(start: any, end: any): void;
29
+ /** panel / 表单控件正在输入时,避免 layout 后 hidden-input 抢焦点 */
30
+ private isExternalInputFocused;
31
+ /** 将解析结果写入 CursorManager,并按需同步 hidden input */
32
+ private applyResolvedCursorState;
33
+ /** Command 执行后应用目标光标(与 layout 重锚定共用 resolve 逻辑) */
34
+ applyCommandCursorResult(result: CommandResult): void;
35
+ /** layout 重建后,按模式(设计/填报)重锚定光标与 hidden input */
36
+ realignAfterLayout(): void;
32
37
  /** 处理方向键移动 */
33
38
  keydownArrowKey(opts: MoveOpts): void;
34
39
  clearCursor(): void;
@@ -3,6 +3,7 @@ import { ICursorPosition, ISelectionRange } from '../types/cursor';
3
3
  export declare function useCursorSelection(docInstance?: Doc): {
4
4
  cursor: import('vue').Ref<{
5
5
  nodeId: string;
6
+ modelId?: string | undefined;
6
7
  pageId: string;
7
8
  preNodeId: string;
8
9
  preLocation: string;
@@ -14,6 +15,7 @@ export declare function useCursorSelection(docInstance?: Doc): {
14
15
  phase: "preview" | "commit";
15
16
  } | null, ICursorPosition | {
16
17
  nodeId: string;
18
+ modelId?: string | undefined;
17
19
  pageId: string;
18
20
  preNodeId: string;
19
21
  preLocation: string;
@@ -27,6 +29,7 @@ export declare function useCursorSelection(docInstance?: Doc): {
27
29
  selection: import('vue').Ref<{
28
30
  anchor: {
29
31
  nodeId: string;
32
+ modelId?: string | undefined;
30
33
  pageId: string;
31
34
  preNodeId: string;
32
35
  preLocation: string;
@@ -39,6 +42,7 @@ export declare function useCursorSelection(docInstance?: Doc): {
39
42
  };
40
43
  focus: {
41
44
  nodeId: string;
45
+ modelId?: string | undefined;
42
46
  pageId: string;
43
47
  preNodeId: string;
44
48
  preLocation: string;
@@ -52,6 +56,7 @@ export declare function useCursorSelection(docInstance?: Doc): {
52
56
  } | null, ISelectionRange | {
53
57
  anchor: {
54
58
  nodeId: string;
59
+ modelId?: string | undefined;
55
60
  pageId: string;
56
61
  preNodeId: string;
57
62
  preLocation: string;
@@ -64,6 +69,7 @@ export declare function useCursorSelection(docInstance?: Doc): {
64
69
  };
65
70
  focus: {
66
71
  nodeId: string;
72
+ modelId?: string | undefined;
67
73
  pageId: string;
68
74
  preNodeId: string;
69
75
  preLocation: string;
@@ -4,6 +4,8 @@ import { CursorIntent, Side } from '../types/cursor';
4
4
  import { Page } from '../../view/Page';
5
5
  export interface HitResult {
6
6
  id: string;
7
+ /** 对应 model 节点的 modelRef.id */
8
+ modelId?: string;
7
9
  offset: number;
8
10
  side: Side;
9
11
  path: string[];
@@ -5,6 +5,8 @@ import { BaseMetaNode } from '../../layout/types';
5
5
  */
6
6
  export declare function getBaseMetaInfo(node: BaseMetaNode): {
7
7
  isPlaceholder: boolean;
8
+ /** model 侧 run 的 id,布局重建后可用于重锚定 */
9
+ modelId: string | undefined;
8
10
  path: string[];
9
11
  id: string;
10
12
  pathIndex: number[];
@@ -1,6 +1,7 @@
1
1
  import { Doc } from '../../view/Doc';
2
2
  import { HitIntentResult, HitResult } from '../hit/types';
3
3
  import { ICursorPosition } from '../types/cursor';
4
+ export { computeRealignedCursorState, cursorMetaToInput, cursorPositionToInput, resolveCursorPosition, resolveCursorStateFromMeta, resolveSelectionStateFromMeta, type CursorResolveInput, type ResolvedCursorState, } from './resolveCursorState';
4
5
  export { getCursorCoords } from './getCursorCoords';
5
6
  export { getCursorTextRawList } from './getCursorTextRawList';
6
7
  export { getSelectionRects } from './getSelectionRects';
@@ -0,0 +1,24 @@
1
+ import { CursorMeta } from '../../command/types';
2
+ import { Doc } from '../../view/Doc';
3
+ import { ICursorPosition, ISelectionRange } from '../types/cursor';
4
+ /** 统一的光标解析输入(Command meta / 现有光标 / layout 重锚定) */
5
+ export type CursorResolveInput = {
6
+ nodeId?: string;
7
+ modelId?: string;
8
+ offset: number;
9
+ side: 'before' | 'after';
10
+ phase: ICursorPosition['phase'];
11
+ pathIndex?: number[];
12
+ };
13
+ export type ResolvedCursorState = {
14
+ cursor: ICursorPosition | null;
15
+ selection: ISelectionRange | null;
16
+ };
17
+ export declare function cursorPositionToInput(cursor: ICursorPosition): CursorResolveInput;
18
+ export declare function cursorMetaToInput(meta: CursorMeta, phase?: ICursorPosition['phase']): CursorResolveInput;
19
+ /** 统一入口:将 meta / 光标 / layout 重锚定输入解析为 ICursorPosition */
20
+ export declare function resolveCursorPosition(doc: Doc, input: CursorResolveInput): ICursorPosition | null;
21
+ export declare function resolveCursorStateFromMeta(doc: Doc, meta: CursorMeta, phase?: ICursorPosition['phase']): ResolvedCursorState | null;
22
+ export declare function resolveSelectionStateFromMeta(doc: Doc, start: CursorMeta, end: CursorMeta, phase?: ICursorPosition['phase']): ResolvedCursorState | null;
23
+ /** layout 后按当前光标状态重锚定 */
24
+ export declare function computeRealignedCursorState(doc: Doc): ResolvedCursorState | null;
@@ -4,6 +4,8 @@ export type Side = 'before' | 'after';
4
4
  export interface ICursorPosition {
5
5
  /** 节点的唯一key */
6
6
  nodeId: string;
7
+ /** 对应 model 节点的 modelRef.id */
8
+ modelId?: string;
7
9
  /** 纸张id */
8
10
  pageId: string;
9
11
  /** 父节点key */
@@ -14,9 +16,9 @@ export interface ICursorPosition {
14
16
  path: string[];
15
17
  /** 节点索引路径: 每层在父节点数组中的下标 */
16
18
  pathIndex: number[];
17
- /** 偏移量 */
19
+ /** 偏移量(layout run 内的本地字符下标) */
18
20
  offset: number;
19
- /** 特殊原子节点的光标“在前/在后” */
21
+ /** 特殊原子节点的光标"在前/在后" */
20
22
  side: Side;
21
23
  /** 是否是占位符 */
22
24
  isPlaceholder: boolean;
@@ -5,6 +5,14 @@ export type Data = Record<string, any>;
5
5
  export type PartialData = Partial<Data>;
6
6
  type JsonPath = string;
7
7
  type SubscriptionCallback = (newValue: any, oldValue: any) => void;
8
+ /** 组件依赖按 runtime valuePath 写入的运行时配置(子表各行独立) */
9
+ export type FieldRuntimeSpecificConfig = {
10
+ newReadonly?: boolean;
11
+ newRequired?: boolean;
12
+ newDisabled?: boolean;
13
+ /** assignment 策略「始终覆盖」时按行不可输入 */
14
+ cannotInput?: boolean;
15
+ };
8
16
  /**
9
17
  * 数据管理器
10
18
  * 用于保存和操作原始 JSON 数据,支持基于 jsonpath 的读写操作
@@ -17,8 +25,9 @@ export declare class DataManager {
17
25
  private depQueue;
18
26
  private computing;
19
27
  private layoutScheduled;
20
- private emitScheduled;
21
28
  private emitQueue;
29
+ /** 串行化 emit 批处理,供 init/refresh 等待 enrich 写回 _href_ 后再排版 */
30
+ private emitTail;
22
31
  private rawData;
23
32
  private postChangePipeline?;
24
33
  /** 无字段依赖的常量公式(如 true)已执行过的 depKey,防止重复 register 死循环 */
@@ -26,6 +35,11 @@ export declare class DataManager {
26
35
  /** 正在执行「注册时立即跑」的依赖,避免 setMultiple 再次走完整 postChange */
27
36
  private runningImmediateDep;
28
37
  private immediateDepDataTouched;
38
+ /** flushDependencies 期间由 dependency 写回的字段 path(供 enrichers 补跑) */
39
+ private flushingDependencies;
40
+ private dependencyFlushChangedPaths;
41
+ /** 组件依赖回调写入的运行时配置,按 runtime valuePath 隔离(避免子表行共享 widgetMeta) */
42
+ private fieldRuntimeConfigByPath;
29
43
  /**
30
44
  * 默认值 Map
31
45
  * key: jsonpath 路径 (支持 [n] 数组索引)
@@ -40,10 +54,35 @@ export declare class DataManager {
40
54
  * 调度 layout,自动合并同一微任务队列中的多个操作
41
55
  */
42
56
  attachPostChangePipeline(ctx: PostChangePipelineContext): void;
57
+ /** 文档初始化 / 刷新数据后,对已有 value 跑一轮后置 enrich */
58
+ runInitialPostChangeFlush(paths: JsonPath[]): Promise<void>;
59
+ /** 等待已入队的 emit 批处理(含 postChange / enrich 写回)全部完成 */
60
+ whenEmitSettled(): Promise<void>;
61
+ /**
62
+ * 对已注册的组件依赖全量重算(refresh 后 depGraph 已重建,需等 readonly/赋值稳定后再 enrich/layout)
63
+ */
64
+ flushAllFieldDependencies(): Promise<void>;
43
65
  private scheduleLayout;
44
66
  getLabelPath(path: JsonPath): JsonPath;
45
- /** PostChangePipeline 在同一微任务内刷新公式依赖 */
46
- flushDependenciesNow(): Promise<void>;
67
+ getHrefPath(path: JsonPath): JsonPath;
68
+ getFieldRuntimeSpecificConfig(path: JsonPath): FieldRuntimeSpecificConfig | undefined;
69
+ setFieldRuntimeSpecificConfig(path: JsonPath, partial: FieldRuntimeSpecificConfig): void;
70
+ /** 子表插行后:index 及之后的行配置下标 +1 */
71
+ private shiftFieldRuntimeConfigAfterRowInsert;
72
+ /** 子表删行后:移除该行配置,其后行配置下标 -1 */
73
+ private shiftFieldRuntimeConfigAfterRowRemove;
74
+ private parseSubtableFieldPath;
75
+ /** 收集 depGraph 中所有 DepNode(按 key 去重) */
76
+ private collectDepNodes;
77
+ /** 依赖图结构变更后按 node.deps + targetPath 重建索引 */
78
+ private rebuildDepGraphIndex;
79
+ /** 子表插行后同步依赖 targetPath 下标 */
80
+ private shiftDependencyGraphAfterRowInsert;
81
+ /** 子表删行后移除该行依赖,并同步其后行的 targetPath 下标 */
82
+ private shiftDependencyGraphAfterRowRemove;
83
+ /** 供 PostChangePipeline 在同一微任务内刷新公式依赖,并返回联动写回的字段 path */
84
+ flushDependenciesNow(): Promise<JsonPath[]>;
85
+ private trackDependencyFieldChange;
47
86
  /**
48
87
  * 根据 jsonpath 获取原始数据(仅返回 rawData 中的值)
49
88
  * @param path jsonpath 路径 (例如: "document.body.children[0].text" 或 "user.name")
@@ -57,6 +96,8 @@ export declare class DataManager {
57
96
  * @returns 指定路径的标签值或原值,不存在返回 undefined
58
97
  */
59
98
  getLabel<T = any>(path: JsonPath): T | undefined;
99
+ /** 获取与 value 并存的超链接 href;无或不可链时为 null/undefined */
100
+ getHref<T = string>(path: JsonPath): T | null | undefined;
60
101
  /** 子表数组路径下未软删行数 */
61
102
  countActiveSubtableRows(arrayPath: JsonPath): number;
62
103
  /** 版面可见行下标 → rawData 数组实际下标 */
@@ -238,6 +279,8 @@ export declare class DataManager {
238
279
  * 调度 emit 事件,自动合并相同 path 的事件
239
280
  */
240
281
  private emit;
282
+ /** 排空 emit 队列(同批合并 path,期间新入队项会继续处理) */
283
+ private processEmitQueue;
241
284
  /**
242
285
  * 通知订阅者与依赖队列(不触发布局)
243
286
  * 实际执行 emit 逻辑
@@ -2,6 +2,8 @@
2
2
  export declare const LABEL_SUFFIX = "_lb_";
3
3
  /** 与 rawData 并存的外链 href 后缀(超链接字段) */
4
4
  export declare const HREF_SUFFIX = "_href_";
5
+ /** 版面超链接文字颜色 */
6
+ export declare const HYPERLINK_TEXT_COLOR = "#0563c1";
5
7
  export declare function getLabelPath(path: string): string;
6
8
  export declare function getHrefPath(path: string): string;
7
9
  export declare function isDerivedDataPath(path: string): boolean;
@@ -1,6 +1,7 @@
1
+ import { Doc } from '../../view/Doc';
1
2
  import { Wr } from '../../model/document';
2
3
  import { PostChangePipelineContext } from '../post-change-pipeline';
3
4
  import { DataEnricherRegistration } from '../enricher-types';
4
- export declare function buildFieldEnricherRegistrations(instances: Wr[], ctx: PostChangePipelineContext): DataEnricherRegistration[];
5
- /** 收集 init 后需 enrich 的运行时路径(将 [n] 等占位替换为 0) */
6
- export declare function collectInitialEnrichPaths(instances: Wr[]): string[];
5
+ export declare function buildFieldEnricherRegistrations(instances: any[], ctx: PostChangePipelineContext, doc: Doc): DataEnricherRegistration[];
6
+ /** 收集 init 后需 enrich 的运行时路径(按 rawData 实际行数展开) */
7
+ export declare function collectInitialEnrichPaths(instances: Wr[], rawData: Record<string, any>): string[];
@@ -0,0 +1,8 @@
1
+ import { Doc } from '../../view/Doc';
2
+ import { WidgetMeta } from '../../widget/widget-meta';
3
+ import { DataEnricherRegistration } from '../enricher-types';
4
+ export type HyperlinkEnricherOptions = Omit<DataEnricherRegistration, 'enrich'> & {
5
+ doc: Doc;
6
+ widgetMeta: WidgetMeta;
7
+ };
8
+ export declare function createHyperlinkEnricher(reg: HyperlinkEnricherOptions): DataEnricherRegistration;
@@ -3,7 +3,8 @@ export { useDocPubApiContext } from './utils/DocPubApiContext';
3
3
  export { useInteraction } from './interaction/useInteraction';
4
4
  export { formulaUtils } from './utils/calculate-formula';
5
5
  export { TextUtil } from './view/utils/TextUtil';
6
- export { resolveWidgetState } from './widget/widget-state';
6
+ export { resolveWidgetState, resolveFieldSpecificConfig, isWidgetMetaReadonlyDisplay } from './widget/widget-state';
7
+ export { isFieldHyperlinkMarked, hasFieldHyperlinkHref, shouldShowFieldHyperlink, } from './widget/field-hyperlink';
7
8
  export { validateTextWidgetMarker } from './layout/logic/LayoutBuilder';
8
9
  export { CommandType } from './command/types';
9
10
  export { ModelConverter } from './model';
@@ -0,0 +1,13 @@
1
+ import { LayoutContext } from '../LayoutContext';
2
+ import { DataSlotIndex } from '../../view/types';
3
+ /** 子表数据下标解析与 layout modelRef.id 生成 基类 */
4
+ export declare class RunHandlerBase {
5
+ /** 子表展开时当前单元格对应的数据下标(一维 dataIndex,或二维 horizontal/vertical 单轴下标) */
6
+ static getSubTableRunIndex(context: LayoutContext): number | undefined;
7
+ /** 从 subRenderer 生成 Run 上的 dataSlotIndex 快照 */
8
+ static buildDataSlotIndex(context: LayoutContext): DataSlotIndex | undefined;
9
+ /** 根据子表展开 / 页眉页脚上下文生成 layout modelRef.id。 */
10
+ static buildSplitModelRefId(context: LayoutContext, baseId: string): string;
11
+ /** 是否是交叉区域 */
12
+ private static buildCrossZoneModelRefId;
13
+ }
@@ -1,11 +1,7 @@
1
1
  import { WrText } from '../../model/document';
2
2
  import { LayoutContext } from '../LayoutContext';
3
- export declare class TextHandler {
4
- static getId(context: LayoutContext, wr: WrText): string;
5
- static get2DInfo(context: LayoutContext): {
6
- xDataIndex: number | undefined;
7
- yDataIndex: number | undefined;
8
- };
3
+ import { RunHandlerBase } from './RunHandlerBase';
4
+ export declare class TextHandler extends RunHandlerBase {
9
5
  /**
10
6
  * 合并部分run
11
7
  * @param context
@@ -2,22 +2,24 @@ import { WrText } from '../../../model/document';
2
2
  import { LayoutContext } from '../../LayoutContext';
3
3
  import { TextRun } from '../../../view/runs/TextRun';
4
4
  import { TextWidget } from '../../../view/runs/TextWidget';
5
+ import { RunHandlerBase } from '../RunHandlerBase';
5
6
  import { HandlerContext } from '../../types';
7
+ import { DataSlotIndex } from '../../../view/types';
6
8
  type ValueType = string | number | undefined | null;
7
- export declare class FieldBaseHandler {
9
+ export declare class FieldBaseHandler extends RunHandlerBase {
8
10
  static hasValue(value: ValueType): boolean;
9
- static getSubTableRunIndex(context: LayoutContext): number | undefined;
10
- static getId(context: LayoutContext, wr: WrText): string;
11
- static get2DInfo(context: LayoutContext): {
12
- xDataIndex: number | undefined;
13
- yDataIndex: number | undefined;
14
- };
11
+ static getModelRefId(context: LayoutContext, wr: WrText): string;
12
+ static getDataSlotIndex(context: LayoutContext): DataSlotIndex | undefined;
15
13
  static getValue(ctx: HandlerContext, valuePath: string): any;
16
14
  static getLabel(ctx: HandlerContext, valuePath: string): any;
17
15
  static getNoValueLabel(ctx: HandlerContext): {
18
16
  label: string;
19
17
  type: 'placeholder' | 'fieldName' | 'noneLabel' | 'default';
20
18
  };
19
+ /** 存在 href 且(打印态 / 填报只读)时应用超链接排版样式 */
20
+ static shouldApplyHyperlinkLayoutStyle(ctx: HandlerContext, wr: WrText, templateValuePath: string): boolean;
21
+ /** 字段文本排版样式(含 rPr + 超链接样式) */
22
+ static resolveFieldTextLayoutStyle(ctx: HandlerContext, wr: WrText, templateValuePath: string): Partial<TextRun>;
21
23
  static formatFieldValue(ctx: HandlerContext, valuePath: string): any;
22
24
  /**
23
25
  * 渲染组件值 label -> value
@@ -0,0 +1,17 @@
1
+ import { WidgetBaseHandler } from './WidgetBaseHandler';
2
+ export declare class TimeDiffHandler extends WidgetBaseHandler {
3
+ layout(): void;
4
+ private resolveLabel;
5
+ private calcTimeDiffLabel;
6
+ private shouldUsePlaceholder;
7
+ /** 按当前格式生成占位,如 --天--时--分--秒 */
8
+ private formatPlaceholder;
9
+ private resolveTimeMs;
10
+ private buildValuePath;
11
+ /**
12
+ * 解析字段父路径:布局时优先用当前单元格 subRenderer(二维表交叉/横向/纵向、动态表等),
13
+ * 与 InsertField / LayoutContext.getValuePath 行为一致。
14
+ */
15
+ private resolveFieldParentKey;
16
+ private formatDiff;
17
+ }
@@ -1,28 +1,19 @@
1
1
  import { WrText } from '../../../model/document';
2
2
  import { LayoutContext } from '../../LayoutContext';
3
3
  import { TextRun } from '../../../view/runs/TextRun';
4
+ import { RunHandlerBase } from '../RunHandlerBase';
4
5
  import { TableCell } from '../../../view/TableCell';
5
6
  import { HandlerContext } from '../../types';
6
- export declare abstract class WidgetBaseHandler {
7
+ import { DataSlotIndex } from '../../../view/types';
8
+ export declare abstract class WidgetBaseHandler extends RunHandlerBase {
7
9
  context: LayoutContext;
8
10
  wr: WrText;
9
11
  constructor(ctx: HandlerContext);
10
- /**
11
- * 获取所在单元格
12
- * @returns
13
- */
12
+ /** 获取所在单元格 */
14
13
  getCell(): TableCell | null;
15
- /**
16
- * 获取所在子表的数据索引
17
- * @returns
18
- */
19
14
  getDataIndex(init?: 0 | null): number | null;
20
- getPaperIndex(): number | null;
21
- getId(): string;
22
- get2DInfo(): {
23
- xDataIndex: number | undefined;
24
- yDataIndex: number | undefined;
25
- };
15
+ getModelRefId(): string;
16
+ getDataSlotIndex(): DataSlotIndex | undefined;
26
17
  getLayoutStyle(): ReturnType<typeof TextRun.textStyle2LayoutStyle>;
27
18
  abstract layout(): void;
28
19
  }
@@ -6,3 +6,4 @@ export { PageWidgetImageHandler } from './PageWidgetImageHandler';
6
6
  export { DiagonalHandler } from './DiagonalHandler';
7
7
  export { PaginationHandler } from './PaginationHandler';
8
8
  export { LineHandler } from './LineHandler';
9
+ export { TimeDiffHandler } from './TimeDiffHandler';
@@ -7,8 +7,6 @@ type ModelRef = {
7
7
  id: string;
8
8
  start?: number;
9
9
  end?: number;
10
- xDataIndex?: number;
11
- yDataIndex?: number;
12
10
  };
13
11
  /**
14
12
  * 布局节点配置
@@ -1,5 +1,6 @@
1
1
  import { WidgetMeta } from '../../widget/widget-meta';
2
2
  import { ImageRun, IImageRun, ImageRunOptions } from './ImageRun';
3
+ import { DataSlotIndex } from '../types';
3
4
  /**
4
5
  * 图片运行接口
5
6
  */
@@ -10,9 +11,7 @@ export interface IImageWidget extends IImageRun {
10
11
  widgetMeta?: WidgetMeta;
11
12
  signature?: string;
12
13
  pageWidgetMeta?: Record<string, any>;
13
- dataIndex?: number;
14
- xDataIndex?: number;
15
- yDataIndex?: number;
14
+ dataSlotIndex?: DataSlotIndex;
16
15
  }
17
16
  export interface ImageWidgetOptions extends ImageRunOptions {
18
17
  /** 值路径 */
@@ -21,9 +20,7 @@ export interface ImageWidgetOptions extends ImageRunOptions {
21
20
  widgetMeta?: WidgetMeta;
22
21
  signature?: string;
23
22
  pageWidgetMeta?: IImageWidget['pageWidgetMeta'];
24
- dataIndex?: number;
25
- xDataIndex?: number;
26
- yDataIndex?: number;
23
+ dataSlotIndex?: DataSlotIndex;
27
24
  }
28
25
  /**
29
26
  * 图片运行类
@@ -34,8 +31,6 @@ export declare class ImageWidget extends ImageRun implements IImageWidget {
34
31
  widgetMeta?: WidgetMeta;
35
32
  signature?: string;
36
33
  pageWidgetMeta?: IImageWidget['pageWidgetMeta'];
37
- dataIndex?: number;
38
- xDataIndex?: number;
39
- yDataIndex?: number;
34
+ dataSlotIndex?: DataSlotIndex;
40
35
  constructor(options: ImageWidgetOptions);
41
36
  }
@@ -62,8 +62,9 @@ export interface TextRunOptions extends LayoutNodeOptions {
62
62
  valuePath?: string;
63
63
  ascent: number;
64
64
  descent: number;
65
- style?: TextStyle;
66
- charMetrics: CharMetric[];
65
+ /** 版面样式(由 textStyle2LayoutStyle 等产出,构造时合并到 run 上) */
66
+ style?: Partial<TextRun> | TextStyle;
67
+ charMetrics?: CharMetric[];
67
68
  }
68
69
  export declare class TextRun extends LayoutNode implements ITextRun {
69
70
  component: "text";
@@ -1,5 +1,6 @@
1
1
  import { WidgetMeta } from '../../widget/widget-meta';
2
2
  import { TextRun, ITextRun, TextRunOptions } from './TextRun';
3
+ import { DataSlotIndex } from '../types';
3
4
  /**
4
5
  * 文本组件接口
5
6
  */
@@ -24,9 +25,7 @@ export interface ITextWidget extends ITextRun {
24
25
  widgetFieldRightMarker?: boolean;
25
26
  /** 页面组件元数据 */
26
27
  pageWidgetMeta?: WidgetMeta;
27
- dataIndex?: number;
28
- xDataIndex?: number;
29
- yDataIndex?: number;
28
+ dataSlotIndex?: DataSlotIndex;
30
29
  }
31
30
  export interface TextWidgetOptions extends TextRunOptions {
32
31
  /** 组件元数据 */
@@ -41,10 +40,8 @@ export interface TextWidgetOptions extends TextRunOptions {
41
40
  widgetFileItem?: ITextWidget['widgetFileItem'];
42
41
  widgetFieldLeftMarker?: boolean;
43
42
  widgetFieldRightMarker?: boolean;
44
- pageWidgetMeta: ITextWidget['pageWidgetMeta'];
45
- dataIndex?: number;
46
- xDataIndex?: number;
47
- yDataIndex?: number;
43
+ pageWidgetMeta?: ITextWidget['pageWidgetMeta'];
44
+ dataSlotIndex?: DataSlotIndex;
48
45
  }
49
46
  export declare class TextWidget extends TextRun implements ITextWidget {
50
47
  widgetMeta?: WidgetMeta;
@@ -56,9 +53,7 @@ export declare class TextWidget extends TextRun implements ITextWidget {
56
53
  widgetFieldRightMarker?: boolean;
57
54
  widgetOption?: ITextWidget['widgetOption'];
58
55
  widgetFileItem?: ITextWidget['widgetFileItem'];
59
- pageWidgetMeta: ITextWidget['pageWidgetMeta'];
60
- dataIndex?: number;
61
- xDataIndex?: number;
62
- yDataIndex?: number;
56
+ pageWidgetMeta?: ITextWidget['pageWidgetMeta'];
57
+ dataSlotIndex?: DataSlotIndex;
63
58
  constructor(options: TextWidgetOptions);
64
59
  }
@@ -13,5 +13,14 @@ export interface Border {
13
13
  width?: number;
14
14
  style?: 'solid' | 'dashed' | 'dotted';
15
15
  }
16
+ /** 子表展开数据槽下标 */
17
+ export type DataSlotIndex = {
18
+ /** 一维子表 [n] */
19
+ dataIndex?: number;
20
+ /** 二维横向 [n_x] */
21
+ xDataIndex?: number;
22
+ /** 二维纵向 [n_y] */
23
+ yDataIndex?: number;
24
+ };
16
25
  export type { BuiltinComponentToLayoutNode, LayoutNodeForComponent, } from './layout-node-by-component';
17
26
  export { isLayoutInlineImage, isLayoutOverlayLayout, isLayoutPage, isLayoutParagraph, isLayoutTable, isLayoutTableCell, isLayoutTableRow, isLayoutTextRun, isLayoutTextWidget, } from './layout-node-by-component';
@@ -0,0 +1,12 @@
1
+ import { Doc } from '../view/Doc';
2
+ import { WidgetMeta } from './widget-meta';
3
+ /** 静态标记:直接按超链接样式展示,不走 enrich / _href_ */
4
+ export declare function isFieldHyperlinkMarked(widgetMeta: WidgetMeta | undefined | null): boolean;
5
+ /** manifest 规则:依赖 enrich 写入的 path_href_ */
6
+ export declare function hasFieldHyperlinkHref(doc: Doc, runtimePath: string): boolean;
7
+ /**
8
+ * 是否按超链接展示/点击。
9
+ * - newHrefSuffix:有展示值 + 只读/打印即显示链接样式,无需 _href_
10
+ * - manifest hyperlink:需 enrich 写回 _href_ 后
11
+ */
12
+ export declare function shouldShowFieldHyperlink(doc: Doc, widgetMeta: WidgetMeta | undefined | null, runtimePath: string): boolean;