openyida 2026.9.19 → 2026.9.21

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 (195) hide show
  1. package/README.md +4 -4
  2. package/lib/app/application-style.js +69 -0
  3. package/lib/app/create-form/args.js +37 -12
  4. package/lib/app/create-form/batch.js +32 -5
  5. package/lib/app/create-form.js +94 -57
  6. package/lib/app/form-field-validator.js +0 -36
  7. package/lib/app/services/form-compiler.js +0 -2
  8. package/lib/app/theme-from-design.js +40 -14
  9. package/lib/app/update-app.js +63 -13
  10. package/lib/core/command-manifest.js +81 -25
  11. package/lib/core/locales/en.js +20 -3
  12. package/lib/core/locales/zh.js +20 -3
  13. package/lib/core/sample.js +36 -14
  14. package/lib/design/document.js +1 -0
  15. package/lib/design-plan/confirmation.js +13 -0
  16. package/lib/design-plan/design-plan.js +44 -2
  17. package/lib/design-plan/entry-navigation.js +10 -2
  18. package/lib/design-plan/init.js +16 -9
  19. package/lib/design-plan/materialize.js +85 -45
  20. package/lib/design-plan/normalize.js +13 -14
  21. package/lib/design-plan/parallel.js +62 -13
  22. package/lib/design-plan/patch.js +21 -7
  23. package/lib/design-plan/rebase.js +60 -0
  24. package/lib/design-plan/themes.js +16 -1
  25. package/lib/design-plan/validate.js +16 -1
  26. package/lib/design-plan/visual-policy.js +29 -4
  27. package/lib/samples/openyida-scaffold/canvas-form-drawer.canvas.jsx +3 -3
  28. package/lib/samples/openyida-scaffold/canvas-nav/mixed.jsx +6 -4
  29. package/lib/samples/openyida-scaffold/canvas-nav/shared.jsx +5 -5
  30. package/lib/samples/openyida-scaffold/canvas-nav/side.jsx +1 -2
  31. package/lib/samples/openyida-scaffold/canvas-nav/sidebar.jsx +1 -1
  32. package/lib/samples/openyida-scaffold/canvas-nav/top.jsx +5 -4
  33. package/package.json +1 -1
  34. package/yida-skills/SKILL.md +2 -2
  35. package/yida-skills/references/official-example-schema-patterns.md +1 -1
  36. package/yida-skills/references/yida-api.md +4 -0
  37. package/yida-skills/skills/yida-app/SKILL.md +15 -4
  38. package/yida-skills/skills/yida-app/references/entry-navigation.md +11 -9
  39. package/yida-skills/skills/yida-app/workflow/plan/step-4-deliver.md +1 -1
  40. package/yida-skills/skills/yida-app/workflow/plan/workflow.md +11 -4
  41. package/yida-skills/skills/yida-app/workflow/step-2-design.md +3 -3
  42. package/yida-skills/skills/yida-app/workflow/step-3-create-or-reuse-app.md +2 -2
  43. package/yida-skills/skills/yida-app/workflow/step-8-publish-navigation.md +3 -3
  44. package/yida-skills/skills/yida-app/workflow/step-9-output-finish.md +3 -2
  45. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +2 -2
  46. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-style-implementation-guide.md +1 -1
  47. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-theme-provider.md +1 -1
  48. package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +140 -1
  49. package/yida-skills/skills/yida-canvas-custom-page/references/navigation-and-entry-guide.md +1 -1
  50. package/yida-skills/skills/yida-canvas-custom-page/scripts/canvas-theme-provider.template.jsx +1 -1
  51. package/yida-skills/skills/yida-canvas-data-binding/SKILL.md +7 -0
  52. package/yida-skills/skills/yida-create-form-page/SKILL.md +34 -43
  53. package/yida-skills/skills/yida-create-form-page/references/advanced-form-modes.md +5 -5
  54. package/yida-skills/skills/yida-create-form-page/references/association-form-field.md +4 -4
  55. package/yida-skills/skills/yida-create-form-page/references/batch-forms.md +2 -2
  56. package/yida-skills/skills/yida-create-form-page/references/field-definition-guide.md +4 -16
  57. package/yida-skills/skills/yida-create-form-page/references/form-field-properties.md +14 -37
  58. package/yida-skills/skills/yida-design/SKILL.md +7 -5
  59. package/yida-skills/skills/yida-design/references/application-style-library.md +93 -0
  60. package/yida-skills/skills/yida-design/references/application-theme-consistency.md +48 -7
  61. package/yida-skills/skills/yida-design/references/ask-human-interaction-contract.md +1 -1
  62. package/yida-skills/skills/yida-design/references/native-form-styles.md +208 -0
  63. package/yida-skills/skills/yida-design/references/navigation-decision.md +6 -4
  64. package/yida-skills/skills/yida-design/references/theme/app-custom-theme-template.css +110 -1
  65. package/yida-skills/skills/yida-design/references/theme/application-style-recipes.css +58 -0
  66. package/yida-skills/skills/yida-design/references/theme-selection.md +12 -11
  67. package/yida-skills/skills/yida-design/references/visual-decision-engine.md +1 -1
  68. package/yida-skills/skills/yida-design/scripts/validate_design_themes.py +49 -6
  69. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/SKILL.md +13 -3
  70. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-compact-schema.md +6 -2
  71. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-schema.md +5 -3
  72. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-design.md +3 -1
  73. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-theme-selection.md +22 -23
  74. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/render_build_plan.py +2 -0
  75. package/yida-skills/skills/yida-design/templates/application-styles.json +398 -0
  76. package/yida-skills/skills/yida-design/templates/design-themes/README.md +15 -10
  77. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/app_theme.css +748 -0
  78. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/design.md +274 -0
  79. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/form-layout.json +15 -0
  80. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/app_theme.css +748 -0
  81. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/design.md +274 -0
  82. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/form-layout.json +14 -0
  83. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/app_theme.css +748 -0
  84. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/design.md +274 -0
  85. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/form-layout.json +13 -0
  86. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/app_theme.css +748 -0
  87. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/design.md +274 -0
  88. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/form-layout.json +14 -0
  89. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/app_theme.css +748 -0
  90. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/design.md +274 -0
  91. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/form-layout.json +14 -0
  92. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/app_theme.css +748 -0
  93. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/design.md +274 -0
  94. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/form-layout.json +14 -0
  95. package/yida-skills/skills/yida-design/templates/design-themes/app-line/app_theme.css +748 -0
  96. package/yida-skills/skills/yida-design/templates/design-themes/app-line/design.md +274 -0
  97. package/yida-skills/skills/yida-design/templates/design-themes/app-line/form-layout.json +13 -0
  98. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/app_theme.css +748 -0
  99. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/design.md +274 -0
  100. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/form-layout.json +14 -0
  101. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/app_theme.css +754 -0
  102. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/design.md +279 -0
  103. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/form-layout.json +13 -0
  104. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/app_theme.css +748 -0
  105. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/design.md +274 -0
  106. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/form-layout.json +13 -0
  107. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/app_theme.css +748 -0
  108. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/design.md +274 -0
  109. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/form-layout.json +14 -0
  110. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/app_theme.css +748 -0
  111. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/design.md +274 -0
  112. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/form-layout.json +14 -0
  113. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/app_theme.css +758 -0
  114. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/design.md +281 -0
  115. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/form-layout.json +14 -0
  116. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/app_theme.css +748 -0
  117. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/design.md +274 -0
  118. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/form-layout.json +14 -0
  119. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/app_theme.css +748 -0
  120. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/design.md +274 -0
  121. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/form-layout.json +14 -0
  122. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/app_theme.css +754 -0
  123. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/design.md +279 -0
  124. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/form-layout.json +14 -0
  125. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/app_theme.css +752 -0
  126. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/design.md +278 -0
  127. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/form-layout.json +13 -0
  128. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/app_theme.css +748 -0
  129. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/design.md +274 -0
  130. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/form-layout.json +14 -0
  131. package/yida-skills/skills/yida-design/templates/design-themes/basic-tokens.json +2 -1
  132. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/app_theme.css +690 -0
  133. package/yida-skills/skills/yida-design/templates/design-themes/{dark-inset-hairline.md → dark-inset-hairline/design.md} +107 -58
  134. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/form-layout.json +13 -0
  135. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/app_theme.css +691 -0
  136. package/yida-skills/skills/yida-design/templates/design-themes/{dark-rail-fine-lines.md → dark-rail-fine-lines/design.md} +106 -50
  137. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/form-layout.json +13 -0
  138. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/app_theme.css +696 -0
  139. package/yida-skills/skills/yida-design/templates/design-themes/{dark-rail-signal-panels.md → dark-rail-signal-panels/design.md} +66 -12
  140. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/form-layout.json +13 -0
  141. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/app_theme.css +689 -0
  142. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/design.md +238 -0
  143. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/form-layout.json +13 -0
  144. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/app_theme.css +692 -0
  145. package/yida-skills/skills/yida-design/templates/design-themes/{graphite-bevel-grid.md → graphite-bevel-grid/design.md} +64 -10
  146. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/form-layout.json +13 -0
  147. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/app_theme.css +691 -0
  148. package/yida-skills/skills/yida-design/templates/design-themes/{hairline-shared-bands.md → hairline-shared-bands/design.md} +66 -12
  149. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/form-layout.json +13 -0
  150. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/app_theme.css +691 -0
  151. package/yida-skills/skills/yida-design/templates/design-themes/{hairline-soft-blocks.md → hairline-soft-blocks/design.md} +61 -9
  152. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/form-layout.json +13 -0
  153. package/yida-skills/skills/yida-design/templates/design-themes/index.json +399 -31
  154. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/app_theme.css +701 -0
  155. package/yida-skills/skills/yida-design/templates/design-themes/{ink-glow-soft-panels.md → ink-glow-soft-panels/design.md} +62 -8
  156. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/form-layout.json +13 -0
  157. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/app_theme.css +691 -0
  158. package/yida-skills/skills/yida-design/templates/design-themes/{inset-frame-pixel-rhythm.md → inset-frame-pixel-rhythm/design.md} +63 -9
  159. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/form-layout.json +13 -0
  160. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/app_theme.css +698 -0
  161. package/yida-skills/skills/yida-design/templates/design-themes/{outlined-texture-duotone.md → outlined-texture-duotone/design.md} +66 -12
  162. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/form-layout.json +13 -0
  163. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/app_theme.css +691 -0
  164. package/yida-skills/skills/yida-design/templates/design-themes/{soft-inset-surfaces.md → soft-inset-surfaces/design.md} +63 -11
  165. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/form-layout.json +13 -0
  166. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/app_theme.css +690 -0
  167. package/yida-skills/skills/yida-design/templates/design-themes/{soft-outline-rhythm.md → soft-outline-rhythm/design.md} +64 -26
  168. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/form-layout.json +13 -0
  169. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/app_theme.css +698 -0
  170. package/yida-skills/skills/yida-design/templates/design-themes/{soft-rail-bold-band.md → soft-rail-bold-band/design.md} +103 -49
  171. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/form-layout.json +13 -0
  172. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/app_theme.css +692 -0
  173. package/yida-skills/skills/yida-design/templates/design-themes/{soft-spectral-panels.md → soft-spectral-panels/design.md} +67 -13
  174. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/form-layout.json +13 -0
  175. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/app_theme.css +711 -0
  176. package/yida-skills/skills/yida-design/templates/design-themes/{warm-canvas-contrast-panels.md → warm-canvas-contrast-panels/design.md} +64 -10
  177. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/form-layout.json +13 -0
  178. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/app_theme.css +692 -0
  179. package/yida-skills/skills/yida-design/templates/design-themes/{warm-rail-muted-panels.md → warm-rail-muted-panels/design.md} +102 -50
  180. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/form-layout.json +13 -0
  181. package/yida-skills/skills/yida-design/templates/navigation-styles.json +769 -0
  182. package/yida-skills/skills/yida-design/workflow/output-design.md +9 -6
  183. package/yida-skills/skills/yida-design/workflow/step-2-theme-system.md +12 -4
  184. package/yida-skills/skills/yida-design/workflow/step-6-handoff.md +1 -1
  185. package/yida-skills/skills/yida-form-permission/SKILL.md +6 -0
  186. package/yida-skills/skills/yida-nav-shell/SKILL.md +1 -1
  187. package/yida-skills/skills/yida-nav-shell/references/nav-shell-patterns.md +6 -0
  188. package/yida-skills/skills/yida-page-config/SKILL.md +9 -0
  189. package/yida-skills/skills/yida-prd/SKILL.md +1 -0
  190. package/yida-skills/skills/yida-prd/workflow/output-prd.md +2 -2
  191. package/yida-skills/skills/yida-prd/workflow/step-2-information-architecture.md +1 -1
  192. package/yida-skills/skills/yida-requirement-analysis/references/experience-groups.md +45 -9
  193. package/yida-skills/skills/yida-requirement-analysis/references/handoff.md +5 -5
  194. package/yida-skills/skills/yida-requirement-analysis/workflow/prepare-brief.md +17 -4
  195. package/yida-skills/skills-index.json +2 -2
@@ -86,7 +86,7 @@ body.pod-premium.page-type-workbench .vc-page-yida-pure-container:has(> .vc-root
86
86
  背景职责统一:Shell 的 `--pod-shell-bg-color-light/white/gray/dark` 承载外层氛围;原生页面与自定义页面的基础底色统一消费 `--pod-page-bg-color`;卡片、表格外壳和面板消费 `--pod-card-bg-color`,回退 `--color-white`。渐变、纹理和图片作为页面局部装饰层叠加,不另设应用基础背景变量。
87
87
 
88
88
  应用根背景已提供 `--pod-app-root-bg-color` 和 `--pod-app-root-bg-image`,后者可表达图片或 CSS 渐变。它们只影响实际消费这些变量的根容器;不透明页面和卡片仍显示各自底色。全应用背景由主题 CSS 配置,单页渐变在本页根容器用 `background-image` 实现;颜色变量不放渐变,页面代码不向父页面 body 注入样式。Fast 与 Plan 共用这套规则,详见 [背景作用范围](../../yida-design/workflow/output-design.md#背景颜色渐变与图片)。
89
- 抽屉整体背景默认使用 `--pod-shell-theme-bg-color`,回退 `--color-white`;标题栏、正文容器透明承接外壳,不铺 `--pod-card-bg-color`。抽屉内独立业务卡片才使用卡片 token。
89
+ 抽屉外壳背景默认使用 `--pod-shell-theme-bg-color`,回退 `--color-white`;标题栏、正文容器透明承接外壳,不铺 `--pod-card-bg-color`。抽屉内独立业务卡片才使用卡片 token。
90
90
 
91
91
  导航布局和页面底色分别配置。隐藏应用导航不自动把 Canvas 改为透明;深色或明确的应用底色在 `design.md` 的平台 token 中定义,生成 `app-theme.css` 后统一生效。页面局部视觉不能通过修改应用 token 影响其他页面。
92
92
 
@@ -77,7 +77,7 @@ Provider 上下文的 `controls` 返回同一组 surface/text/selectedBg/selecte
77
77
  - antd 主按钮使用 `type="primary"`,链接使用 `type="link"` 或 Typography.Link;Tabs 保留默认主题交互色。调整内层 ConfigProvider 时只覆盖所需尺寸、圆角,颜色读取上下文解析值。`token.colorPrimary/colorLink`、Tabs 的 inkBarColor/itemSelectedColor 等不要填固定品牌色,也不要直接填未解析的 `var(...)`。
78
78
  - 自绘按钮、链接及 Tab 的 normal/hover/active/selected/focus/disabled 都消费应用 CSS 变量;优先提取 `canvas-nav-tabs` 作为受控 Tab 片段。选中逻辑与颜色分开,不能仅初始态跟随主题、点击后切成固定蓝色或 Tailwind 的 `bg-blue-*`。状态色与装饰色仍按业务语义使用。
79
79
  - 页面背景使用 `--pod-page-bg-color`,卡片使用 `--pod-card-bg-color`。Provider 已提供根节点背景和最小高度,业务内容负责布局、卡片和装饰。
80
- - Drawer 的组件级背景单独读取 `--pod-shell-theme-bg-color`,回退 `--color-white`,跟随主题更新;不沿用卡片或通用浮层的底色。
80
+ - Drawer 的组件级背景单独读取 `--pod-shell-theme-bg-color`,回退 `--color-white`;外壳文字读取 `--pod-page-header-text-color`,回退 `--color-text1-4`。外壳跟随应用框架更新,内部 iframe 继续使用平台页面主题;卡片和通用浮层保留各自底色。
81
81
  - Provider 内置表格和 Spin 加载遮罩的防闪边样式:边框固定为零,只对透明度做过渡,避免整页刷新时延迟加载的基础样式触发黑边动画。保留这段样式,不要改回 `transition: all`。旧页面需更新 Provider 并重新发布,修改主题 CSS 不会自动更新页面里的 Provider。
82
82
  - antd 自动接收主色、表面、文字、填充和边框色,并应用上述控件状态默认值。成功、警告和错误使用 antd 默认色;尺寸、圆角、字体和图表色组按 design.md 设置。
83
83
  - 图表在 PageContent 内调用 `useCanvasThemeContext()` 获取解析后的 token。
@@ -11,8 +11,9 @@
11
11
  | 宜搭开放 API(OpenAPI,`appKey`/`appSecret` 签名) | 服务端 / 平台连接器 | 需服务端签名;浏览器直连会泄露 secret。由后端或已鉴权的平台连接器调用。 |
12
12
  | 平台已配置连接器 `window.__OPENYIDA_CONNECTOR_API__` | **第三方 API 默认** | 页面只保存 `Http_*` `connectorName`、`operationId`、`connectionId` 和业务输入,由固定的同源运行时桥调用;鉴权与密钥留在平台侧。 |
13
13
  | 内部表单数据端点(同源、依赖登录 cookie + CSRF) | 降级可用 | 仅在 yida JS-API 桥不存在时使用;必须使用同源相对路径、`credentials: 'include'` 和运行态 CSRF token。 |
14
+ | 公开访问网关 `window.pageConfig[...]`(同源、匿名态) | **匿名页仅此可用** | 仅当页面运行在 `/o/...` 公开链接(`FREELOGIN`、`loginUser.userId === 'FREEUSER'`)时使用;提交 URL 从 `window.pageConfig.RECEIPT_SAVE_FORM_DATA` 取值,为 origin 相对路径;CSRF 优先从 `window.g_config._csrf_token` 取,兼容 `pageConfig` 等运行态配置,**作为请求参数**(不是 header)传递;必须设置 `X-Requested-With: XMLHttpRequest` 头;`credentials: 'same-origin'`。仅当显示页和目标表单都已开启公开访问(`isOpen === 'y'`)且目标表单权限包含 `FREE_LOGIN` 数据规则时平台才会放行。 |
14
15
 
15
- 选路原则:读本应用或本轮创建的宜搭表单,默认走 yida JS-API 桥;读第三方或复杂后端数据,走平台连接器桥;只有桥不存在且必须读表单时,才同源直连内部端点。Cookie、CSRF、AK/SK 和签名由平台上下文、连接器或后端服务提供,页面不能接收或保存密钥。
16
+ 选路原则:读本应用或本轮创建的宜搭表单,默认走 yida JS-API 桥;读第三方或复杂后端数据,走平台连接器桥;只有桥不存在且必须读表单时,才同源直连内部端点。页面运行在公开链接 `/o/...` 时即使能读到 `window.__OPENYIDA_YIDA_API__`,其登录态 `saveFormData` 也会失败;匿名提交必须优先走公开访问网关,且显示页和目标表单都已开启公开访问、目标表单权限包含 `FREE_LOGIN`。Cookie、CSRF、AK/SK 和签名由平台上下文、连接器或后端服务提供,页面不能接收或保存密钥。
16
17
 
17
18
  ## 推荐:先写 dataBinding,再实现数据桥
18
19
 
@@ -380,10 +381,146 @@ function fetchFormData(appType, formUuid, signal) {
380
381
  function fieldOf(row, fieldId) { return (row.formData || row)[fieldId]; }
381
382
  ```
382
383
 
384
+ ## 公开访问(匿名态)提交
385
+
386
+ 页面运行在公开链接 `/o/...` 时,`this.utils.yida.saveFormData` 不可用于匿名提交;页面上即使存在 `window.__OPENYIDA_YIDA_API__` 桥对象,其登录态 `saveFormData` 也会返回 `LOGIN FAILED`。平台在 `window.pageConfig` 里注入的公开访问 API 网关映射,是匿名页写入表单数据的**唯一可行通道**。
387
+
388
+ 前置条件(缺一不可,缺任一都不承诺匿名提交):
389
+
390
+ - **显示页已开启公开访问**:`openyida get-page-config <appType> <显示页formUuid>` 返回 `isOpen === 'y'`。
391
+ - **目标表单(receipt)也已开启公开访问**:`openyida get-page-config <appType> <目标formUuid>` 返回 `isOpen === 'y'`。显示页和目标表单的 `isOpen` 缺一不可。
392
+ - **目标表单权限包含 FREE_LOGIN 规则**:`openyida get-permission <appType> <目标formUuid>` 的 DEFAULT 权限组 `dataPermit.rule` 包含 `{"type":"FREE_LOGIN","value":"y"}`。缺少此条会得到 `TIANSHU_160001 没有权限`。
393
+ - 页面确实运行在匿名态:`String(window.pageConfig && window.pageConfig.FREELOGIN) === 'true'` 或 `(window.loginUser || {}).userId === 'FREEUSER'`。
394
+ - `window.pageConfig.RECEIPT_SAVE_FORM_DATA` 非空(值形如 `/o/<hash>`)。
395
+
396
+ 网关请求契约:
397
+
398
+ - **URL**:`window.location.origin + window.pageConfig.RECEIPT_SAVE_FORM_DATA`,与租户命名空间无关,不要硬编码 `/dingtalk/web` 或 `/alibaba/web`。
399
+ - **方法与编码**:`POST` + `Content-Type: application/x-www-form-urlencoded`。
400
+ - **必须的请求头**:`X-Requested-With: XMLHttpRequest`(缺少此头会导致 302 重定向而非 JSON 响应)。
401
+ - **CSRF**:优先从 `window.g_config._csrf_token` 取,兼容 `pageConfig`、`YIDA_CONFIG`、`__YIDA__` 等运行态配置,**作为请求参数** `_csrf_token` 传递;`credentials: 'same-origin'`。
402
+ - **body 参数**:`formUuid`、`appType`、`_csrf_token`、`value`(`JSON.stringify(字段数组)`)。`_schemaVersion` 不必填。
403
+ - **`value` 字段数组格式**:每项固定为 `{componentName, fieldId, fieldData: {value}}`:
404
+ ```json
405
+ [
406
+ {
407
+ "componentName": "TextField",
408
+ "fieldId": "textField_xxx",
409
+ "fieldData": { "value": "文本值" }
410
+ }
411
+ ]
412
+ ```
413
+ `componentName` 必须取目标表单 `openyida get-schema <appType> <formUuid> --field-map-json` 返回的真实值,不得根据 `fieldId` 前缀猜测;标准组件名称见[字段定义 JSON 指南](../../yida-create-form-page/references/field-definition-guide.md#支持的字段类型)。`fieldData.value` 沿用表单保存值结构,文本、数字、单选、多选和日期等格式统一引用[数据格式指南](../../yida-data-management/references/data-format-guide.md#常见字段值格式),不在本技能复制第二份映射表。该引用只说明值结构,不代表所有字段都支持公开匿名提交;仍需遵守下方匿名能力边界,并按返回实例 ID 回读目标字段。
414
+ 把字段 ID 放进 `fieldData` 会得到 `success: true` 和 `formInstId`,但实际创建的是空记录,不能据此判定提交成功。
415
+ - **响应**:`success: true` 时读 `content.formInstId`。
416
+
417
+ 自适应提交 helper(页面直接复制;登录态走既有桥,匿名态走公开网关;两态失败都返回可读原因):
418
+
419
+ ```jsx
420
+ function isFreeLoginPage() {
421
+ try {
422
+ var cfg = window.pageConfig || {};
423
+ if (String(cfg.FREELOGIN) === 'true') { return true; }
424
+ } catch (err) {}
425
+ try { return (window.loginUser || {}).userId === 'FREEUSER'; } catch (err) {}
426
+ return false;
427
+ }
428
+
429
+ function publicEndpoint(key) {
430
+ var cfg = (typeof window !== 'undefined' && window.pageConfig) || {};
431
+ var p = cfg[key];
432
+ if (!p) { return ''; }
433
+ return p.charAt(0) === '/' ? window.location.origin + p : p;
434
+ }
435
+
436
+ function getCsrfToken() {
437
+ var yida = window.__YIDA__ || {};
438
+ var sources = [
439
+ window.g_config,
440
+ window.pageConfig,
441
+ window.YIDA_CONFIG,
442
+ yida,
443
+ yida.config,
444
+ yida.pageConfig,
445
+ yida.runtimeConfig,
446
+ ];
447
+ var keys = ['_csrf_token', 'csrfToken', 'csrf_token', 'global_csrf_token'];
448
+ for (var i = 0; i < sources.length; i += 1) {
449
+ var source = sources[i] || {};
450
+ for (var j = 0; j < keys.length; j += 1) {
451
+ if (source[keys[j]]) { return source[keys[j]]; }
452
+ }
453
+ }
454
+ return '';
455
+ }
456
+
457
+ function submitViaPublicGateway(appType, formUuid, fieldArray) {
458
+ var url = publicEndpoint('RECEIPT_SAVE_FORM_DATA');
459
+ if (!url) {
460
+ return Promise.reject(new Error('当前页面未开启公开访问,无法匿名提交'));
461
+ }
462
+ var csrf = getCsrfToken();
463
+ if (!csrf) {
464
+ return Promise.reject(new Error('当前公开页面缺少提交凭证,请刷新后重试'));
465
+ }
466
+ var body = new URLSearchParams();
467
+ body.set('formUuid', formUuid);
468
+ body.set('appType', appType);
469
+ body.set('value', JSON.stringify(fieldArray));
470
+ body.set('_csrf_token', csrf);
471
+ return fetch(url, {
472
+ method: 'POST',
473
+ credentials: 'same-origin',
474
+ headers: {
475
+ 'Content-Type': 'application/x-www-form-urlencoded',
476
+ 'X-Requested-With': 'XMLHttpRequest',
477
+ },
478
+ body: body.toString(),
479
+ }).then(function (r) { return r.json(); }).then(function (json) {
480
+ if (!json || json.success === false) {
481
+ var msg = (json && (json.errorMsg || json.errorCode)) || '匿名提交失败';
482
+ throw new Error(msg);
483
+ }
484
+ return json.content || json;
485
+ });
486
+ }
487
+
488
+ function submitFormData(appType, formUuid, fields, fieldComponents) {
489
+ if (isFreeLoginPage()) {
490
+ var fieldArray = Object.keys(fields).map(function (fieldId) {
491
+ var componentName = fieldComponents && fieldComponents[fieldId];
492
+ if (!componentName) {
493
+ throw new Error('字段 ' + fieldId + ' 缺少真实 componentName,请先回读表单 Schema');
494
+ }
495
+ return {
496
+ componentName: componentName,
497
+ fieldId: fieldId,
498
+ fieldData: { value: fields[fieldId] },
499
+ };
500
+ });
501
+ return submitViaPublicGateway(appType, formUuid, fieldArray);
502
+ }
503
+ return window.__OPENYIDA_YIDA_API__.saveFormData({
504
+ appType: appType, formUuid: formUuid,
505
+ formDataJson: JSON.stringify(fields),
506
+ });
507
+ }
508
+ ```
509
+
510
+ 匿名态能力边界(不要在这些场景里承诺免登能力):
511
+
512
+ - **不能发起流程**:`window.pageConfig.START_INSTANCE` 为空字符串,匿名态无法调用 `startProcessInstance`;流程页必须走登录态。
513
+ - **不能读取跨组织附件**:匿名会话看不到组织内附件,附件字段默认不支持组织外访问。
514
+ - **不支持成员/部门/关联表单/关联查询/行业组件/自定义组件**:这些字段在公开访问表单中被平台限制。
515
+ - **唯一性校验不可用**:唯一约束不会在匿名提交时生效,业务侧要另外做去重。
516
+ - **提交人恒为匿名**:审计需要真实身份时不要走匿名通道,改为登录页 + 表单公开访问关闭。
517
+ - **匿名态开启后**:不再支持从该表单发送卡片消息给个人/群聊。
518
+
383
519
  ## 数据接入验收清单
384
520
 
385
521
  - 已确认 appType、formUuid 和字段 ID 来自真实表单 Schema。
386
522
  - 页面首屏接口返回后,统计总数与数据管理页 / `openyida data query form` 的总数一致。
523
+ - 匿名提交不能只检查 `success` / `formInstId` 或总数增长;必须按返回的 `formInstId` 回读记录,确认代表性字段值真实落库。
387
524
  - 真实接口异常时显示错误原因和重试入口。
388
525
  - 提交、点赞等写操作成功后调用 silent reload,只更新统计和列表。
389
526
  - 轮询 `setInterval` 有 cleanup,页面隐藏时暂停请求。
@@ -394,3 +531,5 @@ function fieldOf(row, fieldId) { return (row.formData || row)[fieldId]; }
394
531
  - **幂等**:提交按钮加 loading 锁与去重键,拦截重复写入。
395
532
  - **权限**:写操作是否允许由平台权限决定;失败按后端返回的 `errorMsg` 提示。
396
533
  - **密钥位置**:任何 `appSecret` / 签名逻辑都留在服务端 / 连接器,页面源码里只出现同源相对路径与业务参数。
534
+ - **匿名态分流**:页面运行在 `/o/...` 公开链接时,即使存在 `window.__OPENYIDA_YIDA_API__` 桥对象,其 `saveFormData` 仍会返回 `LOGIN FAILED`;必须先识别 `FREELOGIN` / `FREEUSER`,再按上文"公开访问(匿名态)提交"章节走 `window.pageConfig.RECEIPT_SAVE_FORM_DATA`,且 CSRF 走请求参数、`credentials: 'same-origin'`。
535
+ - **匿名态限制**:匿名提交不能发起流程(`START_INSTANCE` 为空),唯一性校验不生效,成员/部门/关联表单/关联查询/行业组件/自定义组件不支持,提交人恒为匿名。审计需要真实身份、或需要唯一约束时不走匿名通道。
@@ -181,7 +181,7 @@ YidaCodeCanvas 推荐使用 antd `Drawer`。`FormOpenContainer` 只负责打开
181
181
 
182
182
  抽屉 header 的工具操作统一使用图标按钮:新窗口打开用 `ExternalLink`,全屏/退出全屏用 `Maximize2` / `Minimize2`,关闭用 `X`。表单抽屉三个操作必须齐全,不得替换为“在新窗口打开”“关闭”等可见文字链接,也不得省略全屏。每个按钮提供对应的 `title`、`aria-label` 和可见键盘焦点;全屏按钮同时更新图标、提示和 `aria-pressed`。按钮默认使用中性色,hover、focus 跟随主题。发布前逐一验证三个按钮的实际行为,不以按钮已渲染代替验收。
183
183
 
184
- 抽屉外壳默认使用 `var(--pod-shell-theme-bg-color, var(--color-white, #fff))`,标题栏与正文容器透明承接同一底色,不使用 `--pod-card-bg-color` 铺满抽屉。CanvasThemeProvider 同步设置 antd Drawer 的组件级背景;其他卡片、弹窗保留各自表面。只有明确的设计覆盖才传 CanvasDrawer.background 或 openForm 的 background,不主动生成卡片色覆盖。iframe 内页面继续使用平台主题。
184
+ 抽屉外壳默认使用 `var(--pod-shell-theme-bg-color, var(--color-white, #fff))`,标题栏与正文容器透明承接同一底色,不使用 `--pod-card-bg-color` 铺满抽屉。CanvasThemeProvider 同步设置 antd Drawer 的组件级背景;其他卡片、弹窗保留各自表面。只有明确的设计覆盖才传 CanvasDrawer.background 或 openForm 的 background,不主动生成卡片色覆盖。抽屉外壳的标题、正文和标题栏按钮默认使用 `--pod-page-header-text-color`,回退到 `--color-text1-4`,显式的 drawer 颜色变量仍可覆盖对应角色。外壳背景跟随应用框架,内部 iframe 独立呈现表单或详情页。传入 `background` 时同时检查标题、按钮和正文的可读性。iframe 内页面继续使用平台主题。
185
185
 
186
186
  提交页和详情页统一由 `FormOpenContainer` 使用 `contentMode="iframe"`:iframe 直接填满标题栏下方的剩余空间,外层不加 `oy-drawer-card`、卡片底色、圆角或 padding,也不设置外层滚动。`oy-drawer-frame` 仅负责尺寸定位和裁切;滚动由 iframe 内页面负责。不要恢复 `calc(100vh - 56px)` 等猜测高度的兜底。
187
187
 
@@ -105,7 +105,7 @@ function CanvasThemeProvider({ children, preview = false, getPopupContainer }) {
105
105
  try {
106
106
  const token = resolveCanvasTheme(root);
107
107
  const controls = resolveCanvasControls(token);
108
- const components = { ...resolveCanvasControlComponents(token, controls), Drawer: resolveCanvasTheme(root, { colorBgElevated: ['--pod-shell-theme-bg-color', '--color-white'] }) };
108
+ const components = { ...resolveCanvasControlComponents(token, controls), Drawer: resolveCanvasTheme(root, { colorBgElevated: ['--pod-shell-theme-bg-color', '--color-white'], colorText: ['--pod-page-header-text-color', '--color-text1-4'], colorTextHeading: ['--pod-page-header-text-color', '--color-text1-4'] }) };
109
109
  next = { token, components, controls, status: token.colorPrimary ? (preview ? 'preview' : 'ready') : 'missing' };
110
110
  } catch (_error) {
111
111
  next = { token: {}, components: {}, controls: null, status: 'error' };
@@ -18,6 +18,8 @@ description: 自定义页面真实数据接入技能。用于在使用 `YidaCode
18
18
  - `YidaCodeCanvas` 组件只透传 `code / runtimeCode / importedModules / pageType`。
19
19
  - 组件内没有 `this` 上下文,也没有 `dataSourceMap`。
20
20
  - `this.utils.yida.*`、`didMount()`、`_customState` 等普通页面契约在 `YidaComp` 内不可直接使用;发布使用 `YidaCodeCanvas` 组件实现的页面时,外层普通页面的 `didMount` 必须自动把 `this.utils.yida.*` 封装到 `window.__OPENYIDA_YIDA_API__`,并把 `this.utils.toast/dialog/router.push/openPage/isMobile` 等根级工具封装到 `window.__OPENYIDA_UTILS__`,组件内部只能消费这些 window 桥。
21
+ - 桥对象存在只代表发布层已注入能力,不代表当前访客具有登录态。公开页 `/o/...` 中桥可能存在,但匿名用户调用其 `saveFormData` 仍会返回 `LOGIN FAILED`;写入前必须先按 `pageConfig.FREELOGIN === 'true'` 或 `loginUser.userId === 'FREEUSER'` 分流。
22
+ - 登录态表单写入继续使用 `window.__OPENYIDA_YIDA_API__.saveFormData`;匿名态只能按[公开访问(匿名态)提交](../yida-canvas-custom-page/references/data-bridge-guide.md#公开访问匿名态提交)走 `window.pageConfig.RECEIPT_SAVE_FORM_DATA`,不得在桥失败后盲目重试。
21
23
  - `YidaCodeCanvas` 组件没有官方 `useDataBinding` hook,不得从任何包 `import { useDataBinding }`;真实表单数据绑定用页面内本地 `useYidaData(binding)`、`DataBridge` 和 yida JS-API 桥实现。
22
24
  - Cookie 由浏览器同源请求自动携带,前端代码不能硬编码 Cookie、appSecret、accessKey 或外部密钥。
23
25
  - `mode=form` 读取宜搭表单数据时,默认调用 `window.__OPENYIDA_YIDA_API__.searchFormDatas(params)`,它底层来自官方 `this.utils.yida.searchFormDatas(params)`。发布层同一个桥也同步 `this.utils.yida` 的表单、流程、表单设计与运行态方法,例如 `saveFormData`、`updateFormData`、`startProcessInstance`、`getProcessInstances`、`request`、`searchUserList`。参数至少包含 `formUuid`、`currentPage`、`pageSize` 和 `searchFieldJson`,`pageSize` 一般显式写 `50`,字段 ID 必须来自真实 schema。
@@ -202,6 +204,9 @@ var payload = await bridge.searchFormDatas({
202
204
  - 接口异常时页面有明确错误态,不用 demo seed 伪装成成功态。
203
205
  - 发布后回读页面,确认 `YidaCodeCanvas` 组件的 `runtimeCode` 非空。
204
206
  - 在已登录浏览器中确认页面退出 loading、无数据加载错误,并显示至少一条已 query 确认的记录。
207
+ - 公开页匿名提交前,已回读显示页和目标表单的 `isOpen === 'y'`,并确认目标表单 DEFAULT 权限包含 `FREE_LOGIN`。
208
+ - 匿名字段数组使用 `{ componentName, fieldId, fieldData: { value } }`,CSRF 优先来自 `window.g_config._csrf_token`。
209
+ - 匿名提交不能只检查 HTTP 200、`success`、`formInstId` 或总数增长;必须按返回的实例 ID 回读代表性字段值。
205
210
 
206
211
  验收命令:
207
212
 
@@ -217,5 +222,7 @@ openyida get-schema <appType> <formUuid> > .cache/openyida/dashboard-schema.json
217
222
  | 页面显示 0 条,但数据管理里有数据 | 先检查外层页面是否注入 `window.__OPENYIDA_YIDA_API__`,再检查返回体包裹层和字段映射;触发 `totalCount` 保护 |
218
223
  | 首屏后每 5 秒闪白 | 轮询改成 silent refresh,保留旧数据直到新数据返回 |
219
224
  | 登录态存在但接口 403 | 优先改回 yida JS-API 桥;只有降级直连时才检查同源路径、CSRF 参数和 `global_csrf_token` 头 |
225
+ | 公开页提交返回 `LOGIN FAILED` | 不以桥对象存在判断登录态;先识别 `FREELOGIN` / `FREEUSER`,匿名态改走 `RECEIPT_SAVE_FORM_DATA` |
226
+ | 匿名网关返回成功但字段为空 | 把每项改为 `{ componentName, fieldId, fieldData: { value } }`,再按 `formInstId` 回读字段值 |
220
227
  | 接口失败后仍显示漂亮 demo 数据 | 改成错误态 + seed 标识,不能伪装真实成功 |
221
228
  | 字段值全为空 | 回读 schema 校验字段 ID,确认字段映射没有使用 label |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: yida-create-form-page
3
- description: 表单页面创建与更新;支持 19 种业务字段和 Divider、ColumnContainer 等表单展示布局组件,PageSection/GroupContainer 仅少量特殊场景使用;支持联动规则和数据源绑定。
3
+ description: 表单页面创建与更新;可创建 19 种业务字段、Divider 与 ColumnContainer,更新组件树时保留已有的 Tab、按钮组、图片和状态区;支持联动规则和数据源绑定。
4
4
  ---
5
5
 
6
6
  # 表单页面创建与更新
@@ -20,23 +20,20 @@ description: 表单页面创建与更新;支持 19 种业务字段和 Divider
20
20
  ## 严格禁止 (NEVER DO)
21
21
 
22
22
  - 不要编造 formUuid,必须从命令返回的 JSON 中提取
23
- - 不要猜测 fieldId。字段级命令优先用字段 `label`、必要时用已知 `fieldId` 或 `tableLabel + label`;CLI 内部读 schema/定位并返回 compact evidence。只有字段解析失败/歧义、patch 底层路径或页面/公式/流程等确实需要多字段映射时,才用 `yida-get-schema` 一次性取证。
23
+ - 不要猜测 fieldId。字段级命令优先用字段 `label`,必要时用已知 `fieldId` 或 `tableLabel + label`;CLI 会读取当前表单、定位字段并返回 compact evidence。只有字段解析失败或歧义、patch 底层路径或页面/公式/流程确实需要多字段映射时,才用 `yida-get-schema` 一次性取证。
24
24
  - 不要用此命令操作数据记录(增删改查),应使用 `yida-data-management`
25
25
  - 不要用 shell heredoc、`cat`/`echo`/`printf`/`tee` 或重定向生成字段、变更、补丁、规则、数据源 JSON 文件
26
26
  - OpenYida CLI 不要加 `2>/dev/null`;失败时保留 stdout/stderr 诊断,遇到 DENIED 或重复失败必须换策略
27
27
  - 多表单 batch 契约已在本技能给出时,不要再调用 `create-form batch --help`、`create-form batch --check`,也不要搜索 CLI 安装目录或源码来探测格式;这些调用同样占用本轮唯一一次 batch 调用名额
28
- - 已有目标表单且用户是改字段/联动/属性时,不要创建新表单;必须走 update/patch/rule/bind-datasource。
29
- - 不要用 `GroupContainer` / `PageSection` 承载普通业务分组;普通分组必须优先用 `Divider`
30
- - 严禁为原生表单或 `formDetail` 生成、注入 CSS、JS、HTML 或主题代码;详情页由平台渲染。
31
28
 
32
29
  ## 严格要求 (MUST DO)
33
30
 
34
31
  - 拿到或确认真实 `formUuid` 后,用于后续字段更新、数据绑定和页面入口配置。
35
32
  - create 成功后,将 formUuid 记录到 `.cache/<项目名>-schema.json`
36
- - 完整应用生成场景中,create 成功并记录 formUuid 后,把核心普通表单交给 `yida-data-management` 默认写入 1-3 条业务化示例记录;不要在本技能里直接操作数据记录。
37
- - update / add-option / bind-datasource / validation / rule 等字段级操作不要求先执行外部 `get-schema`;直接提交 compact JSON 或字段 label/fieldId,CLI 会内部读取 schema、定位字段,并在成功 JSON 中输出 compact `resolved`/`updatedProps` evidence。字段解析失败/歧义时按 `diagnostics[].candidates` 补 `tableLabel`、修正 label 或再执行一次 compact `get-schema`。
33
+ - 完整应用生成场景中,create 成功并记录 formUuid 后,把核心普通表单交给 `yida-data-management` 默认写入 1-3 条业务化示例记录。
34
+ - update / add-option / bind-datasource / validation / rule 等字段级操作不要求先执行外部 `get-schema`;直接提交 compact JSON 或字段 label/fieldId,CLI 会读取当前表单、定位字段,并在成功 JSON 中输出 compact `resolved`/`updatedProps` evidence。字段解析失败或歧义时,按 `diagnostics[].candidates` 补 `tableLabel`、修正 label,或再执行一次 compact `get-schema`。
38
35
  - 字段定义或变更定义需要落盘时,必须使用 agent 的结构化文件写入工具创建到 `<projectRoot>/.cache/openyida/<项目名或任务名>/`,例如 `<projectRoot>/.cache/openyida/pm/pm-fields-team.json`
39
- - 普通表单分组必须优先使用 `Divider`,多列排版必须通过字段 JSON 中的 `ColumnContainer` 局部表达
36
+ - 创建或更新表单结构时,按[布局决策规则](#布局决策规则)规划组件树;编辑已有表单时保留原组件树
40
37
  - **重复结构化记录默认使用 `TableField`**:用户未指定具体字段类型时,凡一个业务字段承载多条同构记录,且每条记录由一组固定子字段组成,必须用 `TableField + children` 建模,不以字段名称或业务领域作为判断依据;用户明确指定具体字段类型时按用户要求执行,不将模型推断、跨会话记忆或历史兼容性说法视为用户指定。未在当前应用、当前提交链路验证的限制不能作为字段改型依据。
41
38
  - **本技能不读写 memory**:formUuid 等信息输出到 stdout,通过 `.cache/<项目名>-schema.json` 持久化,不依赖跨会话的 memory 状态
42
39
 
@@ -60,9 +57,9 @@ description: 表单页面创建与更新;支持 19 种业务字段和 Divider
60
57
 
61
58
  ## 多表单创建
62
59
 
63
- 同一轮需要新建两个及以上普通表单时,必须按 [并行创建表单](references/batch-forms.md) 把全部表单写入同一个 `forms.json`,并且只调用一次 `openyida create-form batch <appType> <任务文件> --json`。独立表单和关联表单放在同一任务文件中,依赖通过 `dependsOn` / `$form` 表达,由 CLI 在一次 batch 内部完成分组、真实 `formUuid/fieldId` 回读和依赖调度;不要手工拆成多次 batch,也不要逐个调用 `create-form create`。调用前先确认 CLI 的实际项目根目录,并让 Write 创建的绝对路径与 Bash 使用的任务文件指向同一个物理文件:常见 `<workspace>/project` 布局中应写入 `<workspace>/project/.cache/openyida/<项目名>/forms.json`,再从该项目根传 `.cache/openyida/<项目名>/forms.json`。先用 Read 确认任务文件存在,不要通过试跑 batch 探测路径。batch 返回 background pending 时等待运行时投递完成结果,不得再次调用 batch。只有修改已有表单、恢复已有 `formUuid`,或当前 batch 契约无法表达依赖时,才走明确的非 batch 路径并说明原因。
60
+ 同一轮需要新建两个及以上普通表单时,必须按 [并行创建表单](references/batch-forms.md) 把全部表单写入同一个 `forms.json`,并且只调用一次 `openyida create-form batch <appType> <任务文件> --json`。独立表单和关联表单放在同一任务文件中,依赖通过 `dependsOn` / `$form` 表达,由 CLI 在一次 batch 内部完成分组、真实 `formUuid/fieldId` 回读和依赖调度;不要手工拆成多次 batch,也不要逐个调用 `create-form create`。调用前先确认 CLI 的实际项目根目录,并让 Write 创建的绝对路径与 Bash 使用的任务文件指向同一个物理文件:常见 `<workspace>/project` 布局中应写入 `<workspace>/project/.cache/openyida/<项目名>/forms.json`,再从该项目根传 `.cache/openyida/<项目名>/forms.json`。先用 Read 确认任务文件存在。batch 返回 background pending 时等待运行时投递完成结果,不得再次调用 batch。只有修改已有表单、恢复已有 `formUuid`,或当前 batch 契约无法表达依赖时,才走明确的非 batch 路径并说明原因。
64
61
 
65
- 主技能内的最小任务文件契约如下,执行普通批量创建无需再查 help、sample 或 CLI 源码:
62
+ 主技能内的最小任务文件契约如下:
66
63
 
67
64
  ```json
68
65
  {
@@ -90,7 +87,7 @@ description: 表单页面创建与更新;支持 19 种业务字段和 Divider
90
87
  }
91
88
  ```
92
89
 
93
- `fieldsFile` 也可替代内联 `fields`,其路径相对 `forms.json` 所在目录;已有完整表单可提供 `formUuid` 回读复用。普通搭建的 batch 项必须省略 `icon`,由 CLI 按标题和字段语义自动选择;只有用户明确给出 `openyida create-form icons --json` 目录中的表单图标名时才设置,应用图标 `xian-*` 绝不是表单图标。`locale` 同样只在用户明确指定时设置。普通多表单创建的执行顺序固定为:确认 `projectRoot` → Write 一个任务文件 → Read 确认文件 → 唯一一次真实 batch → 使用 batch 结果和必要的 compact `get-schema` 回读。
90
+ `fieldsFile` 也可替代内联 `fields`,其路径相对 `forms.json` 所在目录;已有完整表单可提供 `formUuid` 回读复用。batch 项的 `icon` 与 `locale` 遵循 [create 模式](#create-模式)的同名参数规则。普通多表单创建的执行顺序固定为:确认 `projectRoot` → Write 一个任务文件 → Read 确认文件 → 唯一一次真实 batch → 使用 batch 结果和必要的 compact `get-schema` 回读。
94
91
 
95
92
  最小 `forms.json` 结构如下;`fieldsFile` 相对 `forms.json` 所在目录解析:
96
93
 
@@ -108,7 +105,7 @@ description: 表单页面创建与更新;支持 19 种业务字段和 Divider
108
105
  }
109
106
  ```
110
107
 
111
- 关联字段必须把引用放在 `associationForm` 内。推荐使用紧凑写法 `"associationForm": { "$form": "customer", "field": "客户名称" }`;batch 会将其规范化为 `associationForm.formUuid` 和 `associationForm.mainFieldId`。完整写法则分别在 `formUuid` 使用 `{ "$form": "customer" }`、在 `mainFieldId` 使用 `{ "$form": "customer", "field": "客户名称" }`。不要把 `$form` 放在 `AssociationFormField` 顶层,也不要用 `batch --help`、空参数或临时计划探索格式;技能中的结构就是正式契约。
108
+ 关联字段的引用放在 `associationForm` 内。推荐使用紧凑写法 `"associationForm": { "$form": "customer", "field": "客户名称" }`;batch 会将其规范化为 `associationForm.formUuid` 和 `associationForm.mainFieldId`。完整写法则分别在 `formUuid` 使用 `{ "$form": "customer" }`、在 `mainFieldId` 使用 `{ "$form": "customer", "field": "客户名称" }`。
112
109
 
113
110
  Batch 以任务文件指纹和 `<forms.json>.state.json` 共同标识一次批量操作,恢复动作由结果中的 `recoveryAction` 唯一决定:
114
111
 
@@ -133,48 +130,39 @@ CLI 在同一次 batch 内对已取得真实 `formUuid` 的空壳表单执行一
133
130
 
134
131
  ## 布局决策规则
135
132
 
136
- 默认表单是单列,使用 `Divider` / `ColumnContainer` / 标准字段表达业务结构。严禁为了“更高级”默认把整表改成双列;严禁用 `GroupContainer` / `PageSection` 做普通分组。
133
+ 原生表单支持组件化布局。按任务规划顶部、左侧、主体、右侧和字段间区域,再将组件与字段放入对应区域。
137
134
 
138
- - 默认单列:字段较少、流程表单、移动端优先、长文本、说明、附件、地址、子表、审批意见、需要逐项认真填写的字段。
139
- - 局部多列:短字段且天然成对或成组时使用 `ColumnContainer`,例如开始/结束日期、姓名/工号、部门/岗位、金额/币种、联系人/电话。
140
- - 全局 `--layout double`:只有用户明确要求“整个表单双列”时才使用;一般更推荐在字段 JSON 内用 `ColumnContainer` 做局部多列。
141
- - 语义分组:按业务含义分段,不按字段数量平均分。常见分组包括“基本信息”“业务信息”“时间计划”“补充材料”“审批信息”。
142
- - Divider 样式:按页面业务、字段密度和主题,从 [23 个可见样式](references/form-field-properties.md#divider) 中选择并显式填写 `dividerType`;不要套用固定推荐顺序。
143
- - 字段 JSON 和表单 Schema JS 只承载表单结构与业务动作。
144
-
145
- 推荐结构:
146
-
147
- ```text
148
- Divider > ColumnContainer > Field
149
- Divider > Field
150
- ```
135
+ - 区域设计:先写清每个区域的组件、作用和响应式规则,再安排字段。
136
+ - 字段排布:长文本、附件、地址和子表通常整行;短字段可按业务关系放入 `ColumnContainer`。可采用单列、局部多列、主次分栏或多区域布局。
137
+ - 组件选用:业务字段负责数据采集,Tab/切换负责导航,按钮组/操作入口执行业务动作,图片或图形建立视觉焦点,状态区提供反馈,标题与 `Divider` 组织层级和节奏,`ColumnContainer` 组织横向字段。编辑已有表单时保留现有组件。
138
+ - 分组规则:普通业务分组和章节分隔使用 `Divider`;横向字段组合使用 `ColumnContainer`。
139
+ - Divider 样式:按页面业务、字段密度和主题,从 [23 个可见样式](references/form-field-properties.md#divider) 中选择并显式填写 `dividerType`。同页同层级使用一致样式;编辑已有页面时沿用原样式,不同业务页面按各自设计选择。
151
140
 
152
141
  ## 企业级表单质量规则
153
142
 
154
143
  生成企业级表单时按以下规则执行:
155
144
 
156
145
  - 字段必须先覆盖 PRD 明确要求,再按真实业务补充少量必要字段,避免堆砌冗余字段。
157
- - 字段较多时必须用 `Divider` 做语义分组;每个分组开头都要有 `Divider`,包括第一个分组;`Divider` 不放在字段列表末尾。
158
- - 同页同层级的 `Divider` 尽量使用同一个 `dividerType`;不同业务页面优先选择不同且合适的样式;场景不明确或候选同样合适时,按页面随机轮换,并把选定值写入 `dividerType`,同页不逐组随机。标题概括组内字段,已有页面局部修改沿用原样式。
146
+ - 内容较多时,按[布局决策规则](#布局决策规则)为各区域选择组件。
159
147
  - 完整业务应用包含多张表单时,表单之间应有业务关联;涉及数据流转的主表建议有文本型业务编号/名称字段,涉及时间、金额、数量的业务应使用日期/数值字段表达。
160
148
  - 复杂业务表单应自然使用多种字段类型,例如文本、数值、日期、选择、成员/部门、附件、子表、关联表单;字段类型多样性服务于业务语义。
161
149
  - `TableField` 必须提供 `children` 子字段,`AssociationFormField` 必须提供关联表单信息。
162
150
  - 审批人、审批状态、审批节点等流程运行字段由流程能力承载;表单只收集业务数据。
163
- - 表单标题、字段 label/title、选项、提示语、校验文案、动作源码、字段 JSON 常量和字段 JSON 文件路径都禁止 emoji;`create-form` / schema compiler 报 emoji 错误时必须改字段 JSON 或路径,不能重复 create 或用同义命令绕过。
151
+ - 表单标题、字段 label/title、选项、提示语、校验文案、动作源码、字段 JSON 常量和字段 JSON 文件路径都禁止 emoji;`create-form` 报 emoji 错误时必须修改字段 JSON 或路径,不能重复 create 或用同义命令绕过。
164
152
 
165
153
  ## 表单布局样式
166
154
 
167
- - 普通业务分组使用 `Divider`,下面直接接字段或 `ColumnContainer`
168
- - 局部多列容器保持背景克制,避免给每个列容器单独上色
169
- - 流程表单更偏单列和清晰分段,颜色只用于章节识别
170
- - 用户明确指定颜色时才写 `colorType: "custom"` 和具体色值
155
+ - 提交、编辑和记录详情与导航、应用框架、自定义页面共用 `design.md` 的整体风格。按 [表单样式与提交页背景](../yida-design/references/native-form-styles.md) 将字体、控件、状态、背景与底栏规则写入同一份应用主题 CSS。
156
+ - 布局结构按[布局决策规则](#布局决策规则)执行,并在 `design.md` 记录列宽、标签位置、分组间距与响应式安排。
157
+ - `--theme default|compact|comfortable` 配置页面密度;应用主题 token 配置完整视觉风格。美化已有表单时保留现有 `formUuid` 和字段结构,只更新布局与主题。
158
+ - 局部多列容器使用统一、克制的背景。
159
+ - 流程表单优先采用单列和清晰分段,颜色用于章节识别。
160
+ - 用户明确指定颜色时,写入 `colorType: "custom"` 和具体色值。
171
161
 
172
162
  ## create 模式
173
163
 
174
- 仅当目标表单缺失且用户意图允许新增数据收集入口时使用。已有 `formUuid` / 表单 URL / bound form 时禁止使用 create 模式。
175
-
176
164
  ```bash
177
- openyida create-form create <appType> <formTitle> <fieldsJsonOrFile> [--layout double|card] [--theme compact|comfortable] [--label-align top|left]
165
+ openyida create-form create <appType> <formTitle> <fieldsJsonOrFile> [--layout single|double|card|section] [--theme default|compact|comfortable] [--label-align top|left|right] [--icon auto|<iconName>] [--locale zh_CN|en_US|ja_JP] [--open|--no-open]
178
166
  # 文件路径示例:.cache/openyida/<项目名或任务名>/<表单名>-fields.json
179
167
  ```
180
168
 
@@ -210,7 +198,7 @@ create 命令失败后,不要立刻重复同一条 create:
210
198
 
211
199
  ## update 模式
212
200
 
213
- 已有 `formUuid` / 表单 URL / bound form 时优先使用本模式。简单字段属性更新直接写 compact changes,不需要模型先 `get-schema --field-map-json`;CLI 会内部读取当前 schema,按 `label`、`fieldId` 或 `tableLabel + label` 定位字段,成功 JSON 会返回 `changes[].resolved` 和 `changes[].updatedProps`。
201
+ 已有 `formUuid` / 表单 URL / bound form 时优先使用本模式。简单字段属性更新直接写 compact changes,不需要模型先 `get-schema --field-map-json`;CLI 会读取当前表单,按 `label`、`fieldId` 或 `tableLabel + label` 定位字段,成功 JSON 会返回 `changes[].resolved` 和 `changes[].updatedProps`。
214
202
 
215
203
  ```bash
216
204
  openyida create-form update <appType> <formUuid> <changesJsonOrFile>
@@ -250,7 +238,7 @@ openyida create-form rule <appType> <formUuid> <rulesJsonOrFile>
250
238
 
251
239
  ## 半成功 create 恢复
252
240
 
253
- create 已返回真实 `formUuid`、但后续 schema 保存或回读失败时,使用保守恢复命令:
241
+ create 已返回真实 `formUuid`、但后续保存或回读失败时,使用保守恢复命令:
254
242
 
255
243
  ```bash
256
244
  openyida create-form resume <appType> <formUuid> <fieldsJsonOrFile> --json
@@ -276,7 +264,7 @@ openyida create-form resume <appType> <formUuid> <fieldsJsonOrFile> --json
276
264
 
277
265
  | 模式 | 命令 | 何时使用 |
278
266
  |------|------|------|
279
- | `patch` | `openyida create-form patch <appType> <formUuid> <patchJsonOrFile>` | 受控修改底层 Schema;字段事件动作必须用 `field-action` 并确认 `designerBindingFound: true`、`readbackVerified: true` |
267
+ | `patch` | `openyida create-form patch <appType> <formUuid> <patchJsonOrFile>` | 受控修改表单底层配置;字段事件动作必须用 `field-action` 并确认 `designerBindingFound: true`、`readbackVerified: true` |
280
268
  | `rule` | `openyida create-form rule <appType> <formUuid> <rulesJsonOrFile>` | 字段显示隐藏、只读、自动赋值、onChange 带出 |
281
269
  | `validation` | `openyida create-form validation <appType> <formUuid> <validationsJsonOrFile>` | 字段校验规则,优先用内置校验,复杂场景再用 customValidate |
282
270
  | `bind-datasource` | `openyida create-form bind-datasource <appType> <formUuid> <fieldLabelOrId> <dataSourceJsonOrFile>` | 选项字段绑定远程搜索数据源;成功输出 `resolved` |
@@ -284,7 +272,7 @@ openyida create-form resume <appType> <formUuid> <fieldsJsonOrFile> --json
284
272
 
285
273
  ## 字段定义 JSON 高频范式
286
274
 
287
- 字段 JSON 详细属性、布局组件、update changes 和完整字段类型表见 [field-definition-guide.md](references/field-definition-guide.md)。
275
+ 字段 JSON 详细属性、`Divider` / `ColumnContainer` 结构、update changes 和完整字段类型表见 [field-definition-guide.md](references/field-definition-guide.md)。
288
276
 
289
277
  常用结构:
290
278
 
@@ -337,7 +325,7 @@ openyida create-form resume <appType> <formUuid> <fieldsJsonOrFile> --json
337
325
 
338
326
  | 文档 | 何时读取 |
339
327
  |------|------|
340
- | [field-definition-guide.md](references/field-definition-guide.md) | 需要完整字段属性、布局组件、update changes 或字段类型表时 |
328
+ | [field-definition-guide.md](references/field-definition-guide.md) | 需要完整字段属性、`Divider` / `ColumnContainer` 结构、update changes 或字段类型表时 |
341
329
  | [advanced-form-modes.md](references/advanced-form-modes.md) | 使用 patch / rule / validation / bind-datasource 高级模式前必须读取 |
342
330
  | [form-field-properties.md](references/form-field-properties.md) | 需要字段属性细节或平台属性映射时 |
343
331
  | [employee-field.md](references/employee-field.md) | 成员字段配置 |
@@ -348,7 +336,7 @@ openyida create-form resume <appType> <formUuid> <fieldsJsonOrFile> --json
348
336
 
349
337
  - `appType` 必须来自已创建应用或用户提供
350
338
  - 字段类型必须使用标准组件名,如 `TextField`、`SelectField`
351
- - 电话字段固定使用 `TextField` 加正则自定义校验;读取已有 Schema 时可以识别历史 `PhoneField`,但不得把它作为新建或 patch 能力。
339
+ - 电话字段固定使用 `TextField` 加正则自定义校验;读取已有表单时可以识别历史 `PhoneField`,但不得把它作为新建或 patch 能力。
352
340
  - `SelectField`、`MultiSelectField`、`RadioField`、`CheckboxField` 固定选项必须提供 `dataSource`;远程选项字段必须提供 `remoteDataSource` 或通过 `bind-datasource` 配置,不要生成无选项源的字段 JSON。
353
341
  - `TableField` 必须提供 `children`,且子表不能嵌套子表
354
342
  - `AssociationFormField` 必须提供 `associationForm`
@@ -360,6 +348,9 @@ openyida create-form resume <appType> <formUuid> <fieldsJsonOrFile> --json
360
348
  |---------|----------|
361
349
  | create 返回失败 | 检查 appType 是否正确,确认登录态有效 |
362
350
  | 字段级命令找不到字段 | 先看命令 JSON 的 `diagnostics[].candidates` 修正 label、补 `tableLabel` 或改用已知 `fieldId`;仍不明确时再用 `openyida get-schema --compact --resolve-fields` |
363
- | 字段类型不支持 | 检查字段类型是否在支持的 19 种业务字段或已验证展示布局组件列表中 |
351
+ | 字段类型不支持 | 使用 `create-form` 支持的 19 种业务字段、`Divider` 或 `ColumnContainer` |
364
352
  | 子表字段创建失败 | 确认 `children` 数组格式正确,子表字段不能嵌套子表 |
365
353
  | 返回 JSON 中无 formUuid | 不要猜测 formUuid,重新执行命令获取 |
354
+
355
+
356
+ 应用整体设计可使用[应用风格模板或自由创意](../yida-design/references/application-style-library.md)。导航、自定义页面、表单与详情继承同一设计语言;自由创意从业务推演。模板中的原生布局 JSON 用于建立结构,使用时填入真实字段并核对间距和响应式。表单组件树按[布局决策规则](#布局决策规则)创建。
@@ -1,8 +1,8 @@
1
1
  # 高级表单模式:patch / rule / bind-datasource
2
2
 
3
- ## patch 模式(设计器 Schema 补丁)
3
+ ## patch 模式(表单配置补丁)
4
4
 
5
- 当宜搭后台已有配置项,但 OpenYida 还没有高阶 DSL 时,使用 patch 模式对表单 V5 Schema 做受控修改:
5
+ 当宜搭后台已有配置项,但 OpenYida 还没有高阶 DSL 时,使用 patch 模式受控修改表单配置:
6
6
 
7
7
  ```bash
8
8
  openyida create-form patch <appType> <formUuid> <patchJsonOrFile>
@@ -15,9 +15,9 @@ openyida create-form patch <appType> <formUuid> <patchJsonOrFile>
15
15
  |------|------|
16
16
  | `field-props` | 按 `fieldId` / `field` / `label` 合并字段 `props`,适合补字段状态、提交策略、设计器属性 |
17
17
  | `form-props` | 合并 `FormContainer.props` |
18
- | `add` / `replace` / `remove` | JSON Pointer 形式的底层 Schema Patch |
18
+ | `add` / `replace` / `remove` | 按 JSON Pointer 路径添加、替换或删除表单配置 |
19
19
  | `merge` | 对指定 JSON Pointer 路径做对象深合并 |
20
- | `actions-module` | 写入页面动作模块 `source` / `compiled`,`source` 会自动编译 |
20
+ | `actions-module` | 写入表单业务动作模块 `source` / `compiled`,`source` 会自动编译 |
21
21
  | `bind-field-action` | 给字段事件(如 `onChange`)绑定动作引用 |
22
22
  | `field-action` | 原子写入动作函数、注册动作并绑定字段事件;字段自定义事件默认使用此操作 |
23
23
  | `bind-datasource` | 给选项类字段绑定远程搜索数据源(高阶入口优先用 bind-datasource 模式) |
@@ -103,7 +103,7 @@ openyida create-form patch <appType> <formUuid> <patchJsonOrFile>
103
103
 
104
104
  ## rule 模式(字段联动与自动赋值)
105
105
 
106
- 常见字段联动不要直接写底层 Schema Patch,优先使用 rule 模式:
106
+ 常见字段联动不要直接修改表单底层配置,优先使用 rule 模式:
107
107
 
108
108
  ```bash
109
109
  openyida create-form rule <appType> <formUuid> <rulesJsonOrFile>
@@ -116,7 +116,7 @@
116
116
  1. `source` 和 `target` 的 fieldId 是否正确(可通过 get-schema 技能查看)
117
117
  2. `sourceType` 和 `targetType` 是否与字段类型一致
118
118
  3. `dataFillingRules` 是否被正确设置到 `props.dataFillingRules`(而非只写在 `associationForm` 对象内)
119
- 4. 关联表单字段的 Schema 节点**顶层**是否有 `fieldId` 属性(宜搭回填引擎依赖顶层 `fieldId` 识别字段,仅在 `props` 内有 `fieldId` 不生效)
119
+ 4. 关联表单字段节点的**顶层**是否有 `fieldId` 属性(宜搭回填引擎依赖顶层 `fieldId` 识别字段,仅在 `props` 内有 `fieldId` 不生效)
120
120
 
121
121
  **子表填充子表(tableRules)格式**:
122
122
 
@@ -164,7 +164,7 @@
164
164
 
165
165
  **注意事项**:
166
166
  - `tableRules` 用于实现"选择关联表单记录后,将其子表数据自动填充到当前表单的子表中"
167
- - **`tableId` 必须填写被关联表单(源表)的子表 fieldId**,宜搭通过它在源表 Schema 中定位子表数据;填写当前表单的子表 fieldId 会导致 `getInstMultiSubTableDatas` 接口报 500 错误
167
+ - **`tableId` 必须填写被关联表单(源表)的子表 fieldId**,宜搭通过它在源表中定位子表数据;填写当前表单的子表 fieldId 会导致 `getInstMultiSubTableDatas` 接口报 500 错误
168
168
  - 每个 `tableRule` 对应源表的一个子表,可以配置多个子表的回填规则
169
169
  - 子表内的 `target` 同样支持 `@label:字段标签` 语法,脚本会自动解析为 fieldId
170
170
  - 确保 `rules[].source` 是源表子表内的字段 fieldId,`rules[].target` 是当前表单子表内的字段 fieldId
@@ -372,7 +372,7 @@
372
372
  ```
373
373
 
374
374
  **关键点说明**:
375
- 1. `tableRules` 中的 `tableId` 填写的是**被关联表单(商品表)的子表 fieldId**(即「规格明细」子表的 fieldId),而非当前表单(订单表)的子表 fieldId。宜搭通过此 fieldId 在源表 Schema 中定位子表数据,填错会导致 `getInstMultiSubTableDatas` 接口报 500 错误
375
+ 1. `tableRules` 中的 `tableId` 填写的是**被关联表单(商品表)的子表 fieldId**(即「规格明细」子表的 fieldId),而非当前表单(订单表)的子表 fieldId。宜搭通过此 fieldId 在源表中定位子表数据,填错会导致 `getInstMultiSubTableDatas` 接口报 500 错误
376
376
  2. `tableRules` 中的每个 `rule.target` 支持 `@label:字段标签` 语法,用于定位当前表单子表内的字段
377
377
  3. 选择商品后,商品表的「规格明细」子表数据会自动填充到订单表的「订单明细」子表中
378
378
  4. 可以配置多个 `tableRule` 来实现多子表的数据回填
@@ -385,7 +385,7 @@
385
385
  - 检查 `sourceType` 和 `targetType` 是否与字段类型一致
386
386
  - 确认 `props.supportDataFilling` 是否为 `true`
387
387
  - 确认每条规则同时包含 `sourceFieldId/targetFieldId/source/sourceType/target/targetType` 6 个字段(缺少任意一个不生效)
388
- - 确认关联表单字段的 Schema 节点**顶层**有 `fieldId` 属性(宜搭回填引擎依赖顶层 `fieldId`,仅在 `props` 内有 `fieldId` 不生效)
388
+ - 确认关联表单字段节点的**顶层**有 `fieldId` 属性(宜搭回填引擎依赖顶层 `fieldId`,仅在 `props` 内有 `fieldId` 不生效)
389
389
 
390
390
  **问题 2:子表填充子表不生效**
391
391
  - 检查 `tableRules` 是否为数组且非空
@@ -13,14 +13,14 @@ openyida create-form batch <appType> .cache/openyida/<项目名>/forms.json --js
13
13
  ```json
14
14
  {
15
15
  "forms": [
16
- { "key": "customer", "title": "客户", "fieldsFile": "customer-fields.json" },
16
+ { "key": "customer", "title": "客户", "fieldsFile": "customer-fields.json", "layout": "section", "theme": "comfortable", "labelAlign": "left" },
17
17
  { "key": "product", "title": "商品", "fieldsFile": "product-fields.json" },
18
18
  { "key": "order", "title": "订单", "fieldsFile": "order-fields.json", "dependsOn": ["customer", "product"] }
19
19
  ]
20
20
  }
21
21
  ```
22
22
 
23
- `fieldsFile` 相对任务文件所在目录,也可使用 `fields` 直接填写字段定义。普通 batch 项省略 `icon`,由 CLI 自动选择;只有用户明确给出表单图标目录中的合法名称时才设置,禁止写应用图标 `xian-*`。`locale` 也只在用户明确指定时设置。已有完整表单填写 `formUuid`,CLI 回读并复用。
23
+ `fieldsFile` 相对任务文件所在目录,也可使用 `fields` 直接填写字段定义。每个表单可按业务设置 `layout: single|double|card|section`、`theme: default|compact|comfortable`、`labelAlign: top|left|right`;它们分别控制整表布局起点、密度和 PC 标签位置,不能代替完整组件树设计。普通 batch 项省略 `icon`,由 CLI 自动选择;只有用户明确给出表单图标目录中的合法名称时才设置,禁止写应用图标 `xian-*`。`locale` 也只在用户明确指定时设置。已有完整表单填写 `formUuid`,CLI 回读并复用。
24
24
 
25
25
  客户和商品同时创建。订单的前置表单完成后开始创建;其他独立任务继续执行。依赖环、未知依赖、重复 key 和无效字段会在创建前报错。
26
26
 
@@ -39,12 +39,12 @@
39
39
  | `dataSource` | Array | 条件必填 | 选项类字段必填 |
40
40
  | `multiple` | Boolean | 否 | 是否多选 |
41
41
  | `remoteDataSource` | Object | 否 | 选项类字段远程搜索数据源配置 |
42
- | `children` | Object[] | 条件必填 | `TableField` / 展示布局组件必填 |
42
+ | `children` | Object[] | 条件必填 | `TableField` / `ColumnContainer` 必填 |
43
43
  | `associationForm` | Object | 条件必填 | `AssociationFormField` 必填 |
44
44
 
45
45
  选项类字段包括 `SelectField`、`MultiSelectField`、`RadioField`、`CheckboxField`。固定选项必须在字段 JSON 中提供非空 `dataSource`;不要省略选项源,也不要只写旧式 `options`。
46
46
 
47
- ## 展示/布局组件
47
+ ## Divider 与 ColumnContainer
48
48
 
49
49
  ### Divider
50
50
 
@@ -73,20 +73,9 @@
73
73
  }
74
74
  ```
75
75
 
76
- ### GroupContainer / PageSection
76
+ ### 分组组件
77
77
 
78
- 只在特殊场景使用,不要承载普通业务分组:
79
-
80
- ```json
81
- {
82
- "type": "PageSection",
83
- "title": "高级配置",
84
- "showHeadDivider": true,
85
- "children": [
86
- { "type": "TextField", "label": "配置说明" }
87
- ]
88
- }
89
- ```
78
+ 普通业务分组和章节分隔使用 `Divider`,需要局部多列时组合 `Divider` 与 `ColumnContainer`。
90
79
 
91
80
  ## update changes
92
81
 
@@ -129,4 +118,3 @@
129
118
  | `SerialNumberField` | 流水号 | 自动生成 |
130
119
  | `Divider` | 分割线 | `title`、`dividerType`、`showTitle` |
131
120
  | `ColumnContainer` | 分栏布局,映射 `ColumnsLayout` | `layout`、`columnGap`、`rowGap`、二维 `children` |
132
- | `GroupContainer` / `PageSection` | 特殊分组容器,映射 `PageSection` | `label`/`title`、`showHeadDivider`、`children` |