openyida 2026.9.20 → 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 (162) hide show
  1. package/README.md +1 -1
  2. package/lib/app/application-style.js +3 -1
  3. package/lib/app/theme-from-design.js +38 -13
  4. package/lib/app/update-app.js +63 -13
  5. package/lib/core/command-manifest.js +32 -20
  6. package/lib/core/locales/en.js +17 -0
  7. package/lib/core/locales/zh.js +17 -0
  8. package/lib/core/sample.js +17 -14
  9. package/lib/design-plan/confirmation.js +13 -0
  10. package/lib/design-plan/design-plan.js +44 -2
  11. package/lib/design-plan/entry-navigation.js +10 -2
  12. package/lib/design-plan/init.js +11 -7
  13. package/lib/design-plan/materialize.js +62 -43
  14. package/lib/design-plan/normalize.js +13 -14
  15. package/lib/design-plan/parallel.js +62 -13
  16. package/lib/design-plan/patch.js +21 -7
  17. package/lib/design-plan/rebase.js +60 -0
  18. package/lib/design-plan/themes.js +16 -1
  19. package/lib/design-plan/validate.js +6 -1
  20. package/lib/design-plan/visual-policy.js +18 -4
  21. package/lib/samples/openyida-scaffold/canvas-form-drawer.canvas.jsx +3 -3
  22. package/lib/samples/openyida-scaffold/canvas-nav/mixed.jsx +6 -4
  23. package/lib/samples/openyida-scaffold/canvas-nav/shared.jsx +5 -5
  24. package/lib/samples/openyida-scaffold/canvas-nav/side.jsx +1 -2
  25. package/lib/samples/openyida-scaffold/canvas-nav/sidebar.jsx +1 -1
  26. package/lib/samples/openyida-scaffold/canvas-nav/top.jsx +5 -4
  27. package/package.json +1 -1
  28. package/yida-skills/SKILL.md +2 -2
  29. package/yida-skills/references/yida-api.md +4 -0
  30. package/yida-skills/skills/yida-app/SKILL.md +12 -4
  31. package/yida-skills/skills/yida-app/references/entry-navigation.md +11 -9
  32. package/yida-skills/skills/yida-app/workflow/plan/step-4-deliver.md +1 -1
  33. package/yida-skills/skills/yida-app/workflow/plan/workflow.md +11 -4
  34. package/yida-skills/skills/yida-app/workflow/step-2-design.md +3 -3
  35. package/yida-skills/skills/yida-app/workflow/step-3-create-or-reuse-app.md +2 -2
  36. package/yida-skills/skills/yida-app/workflow/step-8-publish-navigation.md +3 -3
  37. package/yida-skills/skills/yida-app/workflow/step-9-output-finish.md +3 -2
  38. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +2 -2
  39. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-style-implementation-guide.md +1 -1
  40. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-theme-provider.md +1 -1
  41. package/yida-skills/skills/yida-canvas-custom-page/references/data-bridge-guide.md +140 -1
  42. package/yida-skills/skills/yida-canvas-custom-page/references/navigation-and-entry-guide.md +1 -1
  43. package/yida-skills/skills/yida-canvas-custom-page/scripts/canvas-theme-provider.template.jsx +1 -1
  44. package/yida-skills/skills/yida-canvas-data-binding/SKILL.md +7 -0
  45. package/yida-skills/skills/yida-create-form-page/SKILL.md +1 -1
  46. package/yida-skills/skills/yida-design/SKILL.md +5 -3
  47. package/yida-skills/skills/yida-design/references/application-style-library.md +22 -7
  48. package/yida-skills/skills/yida-design/references/application-theme-consistency.md +45 -5
  49. package/yida-skills/skills/yida-design/references/ask-human-interaction-contract.md +1 -1
  50. package/yida-skills/skills/yida-design/references/native-form-styles.md +1 -1
  51. package/yida-skills/skills/yida-design/references/navigation-decision.md +6 -4
  52. package/yida-skills/skills/yida-design/references/theme/app-custom-theme-template.css +62 -0
  53. package/yida-skills/skills/yida-design/references/theme-selection.md +10 -9
  54. package/yida-skills/skills/yida-design/references/visual-decision-engine.md +1 -1
  55. package/yida-skills/skills/yida-design/scripts/validate_design_themes.py +35 -9
  56. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/SKILL.md +13 -3
  57. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-compact-schema.md +4 -2
  58. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/build-plan-schema.md +4 -2
  59. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-design.md +3 -1
  60. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/references/visual-theme-selection.md +15 -17
  61. package/yida-skills/skills/yida-design/sub_skill/yida-design-plan/scripts/render_build_plan.py +2 -0
  62. package/yida-skills/skills/yida-design/templates/design-themes/README.md +15 -10
  63. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/app_theme.css +224 -83
  64. package/yida-skills/skills/yida-design/templates/design-themes/app-amber/design.md +69 -14
  65. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/app_theme.css +224 -83
  66. package/yida-skills/skills/yida-design/templates/design-themes/app-editorial/design.md +69 -14
  67. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/app_theme.css +244 -103
  68. package/yida-skills/skills/yida-design/templates/design-themes/app-executive/design.md +68 -13
  69. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/app_theme.css +223 -82
  70. package/yida-skills/skills/yida-design/templates/design-themes/app-finance/design.md +68 -13
  71. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/app_theme.css +225 -84
  72. package/yida-skills/skills/yida-design/templates/design-themes/app-glass/design.md +69 -14
  73. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/app_theme.css +244 -103
  74. package/yida-skills/skills/yida-design/templates/design-themes/app-graphite/design.md +68 -13
  75. package/yida-skills/skills/yida-design/templates/design-themes/app-line/app_theme.css +224 -83
  76. package/yida-skills/skills/yida-design/templates/design-themes/app-line/design.md +69 -14
  77. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/app_theme.css +244 -103
  78. package/yida-skills/skills/yida-design/templates/design-themes/app-neon/design.md +68 -13
  79. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/app_theme.css +236 -89
  80. package/yida-skills/skills/yida-design/templates/design-themes/app-nordic/design.md +74 -14
  81. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/app_theme.css +224 -83
  82. package/yida-skills/skills/yida-design/templates/design-themes/app-paper/design.md +68 -13
  83. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/app_theme.css +223 -82
  84. package/yida-skills/skills/yida-design/templates/design-themes/app-platinum/design.md +68 -13
  85. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/app_theme.css +224 -83
  86. package/yida-skills/skills/yida-design/templates/design-themes/app-plum/design.md +68 -13
  87. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/app_theme.css +240 -89
  88. package/yida-skills/skills/yida-design/templates/design-themes/app-pop/design.md +76 -14
  89. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/app_theme.css +224 -83
  90. package/yida-skills/skills/yida-design/templates/design-themes/app-sage/design.md +69 -14
  91. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/app_theme.css +224 -83
  92. package/yida-skills/skills/yida-design/templates/design-themes/app-teal/design.md +68 -13
  93. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/app_theme.css +254 -107
  94. package/yida-skills/skills/yida-design/templates/design-themes/app-terminal/design.md +74 -14
  95. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/app_theme.css +233 -88
  96. package/yida-skills/skills/yida-design/templates/design-themes/app-ticket/design.md +73 -14
  97. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/app_theme.css +224 -83
  98. package/yida-skills/skills/yida-design/templates/design-themes/app-wire/design.md +69 -14
  99. package/yida-skills/skills/yida-design/templates/design-themes/basic-tokens.json +2 -1
  100. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/app_theme.css +690 -0
  101. package/yida-skills/skills/yida-design/templates/design-themes/{dark-inset-hairline.md → dark-inset-hairline/design.md} +103 -58
  102. package/yida-skills/skills/yida-design/templates/design-themes/dark-inset-hairline/form-layout.json +13 -0
  103. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/app_theme.css +691 -0
  104. package/yida-skills/skills/yida-design/templates/design-themes/{dark-rail-fine-lines.md → dark-rail-fine-lines/design.md} +102 -50
  105. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-fine-lines/form-layout.json +13 -0
  106. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/app_theme.css +696 -0
  107. package/yida-skills/skills/yida-design/templates/design-themes/{dark-rail-signal-panels.md → dark-rail-signal-panels/design.md} +62 -12
  108. package/yida-skills/skills/yida-design/templates/design-themes/dark-rail-signal-panels/form-layout.json +13 -0
  109. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/app_theme.css +278 -115
  110. package/yida-skills/skills/yida-design/templates/design-themes/free-creative/design.md +57 -10
  111. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/app_theme.css +692 -0
  112. package/yida-skills/skills/yida-design/templates/design-themes/{graphite-bevel-grid.md → graphite-bevel-grid/design.md} +60 -10
  113. package/yida-skills/skills/yida-design/templates/design-themes/graphite-bevel-grid/form-layout.json +13 -0
  114. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/app_theme.css +691 -0
  115. package/yida-skills/skills/yida-design/templates/design-themes/{hairline-shared-bands.md → hairline-shared-bands/design.md} +62 -12
  116. package/yida-skills/skills/yida-design/templates/design-themes/hairline-shared-bands/form-layout.json +13 -0
  117. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/app_theme.css +691 -0
  118. package/yida-skills/skills/yida-design/templates/design-themes/{hairline-soft-blocks.md → hairline-soft-blocks/design.md} +57 -9
  119. package/yida-skills/skills/yida-design/templates/design-themes/hairline-soft-blocks/form-layout.json +13 -0
  120. package/yida-skills/skills/yida-design/templates/design-themes/index.json +141 -48
  121. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/app_theme.css +701 -0
  122. package/yida-skills/skills/yida-design/templates/design-themes/{ink-glow-soft-panels.md → ink-glow-soft-panels/design.md} +58 -8
  123. package/yida-skills/skills/yida-design/templates/design-themes/ink-glow-soft-panels/form-layout.json +13 -0
  124. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/app_theme.css +691 -0
  125. package/yida-skills/skills/yida-design/templates/design-themes/{inset-frame-pixel-rhythm.md → inset-frame-pixel-rhythm/design.md} +59 -9
  126. package/yida-skills/skills/yida-design/templates/design-themes/inset-frame-pixel-rhythm/form-layout.json +13 -0
  127. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/app_theme.css +698 -0
  128. package/yida-skills/skills/yida-design/templates/design-themes/{outlined-texture-duotone.md → outlined-texture-duotone/design.md} +62 -12
  129. package/yida-skills/skills/yida-design/templates/design-themes/outlined-texture-duotone/form-layout.json +13 -0
  130. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/app_theme.css +691 -0
  131. package/yida-skills/skills/yida-design/templates/design-themes/{soft-inset-surfaces.md → soft-inset-surfaces/design.md} +59 -11
  132. package/yida-skills/skills/yida-design/templates/design-themes/soft-inset-surfaces/form-layout.json +13 -0
  133. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/app_theme.css +690 -0
  134. package/yida-skills/skills/yida-design/templates/design-themes/{soft-outline-rhythm.md → soft-outline-rhythm/design.md} +60 -26
  135. package/yida-skills/skills/yida-design/templates/design-themes/soft-outline-rhythm/form-layout.json +13 -0
  136. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/app_theme.css +698 -0
  137. package/yida-skills/skills/yida-design/templates/design-themes/{soft-rail-bold-band.md → soft-rail-bold-band/design.md} +99 -49
  138. package/yida-skills/skills/yida-design/templates/design-themes/soft-rail-bold-band/form-layout.json +13 -0
  139. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/app_theme.css +692 -0
  140. package/yida-skills/skills/yida-design/templates/design-themes/{soft-spectral-panels.md → soft-spectral-panels/design.md} +63 -13
  141. package/yida-skills/skills/yida-design/templates/design-themes/soft-spectral-panels/form-layout.json +13 -0
  142. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/app_theme.css +711 -0
  143. package/yida-skills/skills/yida-design/templates/design-themes/{warm-canvas-contrast-panels.md → warm-canvas-contrast-panels/design.md} +60 -10
  144. package/yida-skills/skills/yida-design/templates/design-themes/warm-canvas-contrast-panels/form-layout.json +13 -0
  145. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/app_theme.css +692 -0
  146. package/yida-skills/skills/yida-design/templates/design-themes/{warm-rail-muted-panels.md → warm-rail-muted-panels/design.md} +98 -50
  147. package/yida-skills/skills/yida-design/templates/design-themes/warm-rail-muted-panels/form-layout.json +13 -0
  148. package/yida-skills/skills/yida-design/templates/navigation-styles.json +769 -0
  149. package/yida-skills/skills/yida-design/workflow/output-design.md +5 -5
  150. package/yida-skills/skills/yida-design/workflow/step-2-theme-system.md +5 -3
  151. package/yida-skills/skills/yida-design/workflow/step-6-handoff.md +1 -1
  152. package/yida-skills/skills/yida-form-permission/SKILL.md +6 -0
  153. package/yida-skills/skills/yida-nav-shell/SKILL.md +1 -1
  154. package/yida-skills/skills/yida-nav-shell/references/nav-shell-patterns.md +6 -0
  155. package/yida-skills/skills/yida-page-config/SKILL.md +9 -0
  156. package/yida-skills/skills/yida-prd/SKILL.md +1 -0
  157. package/yida-skills/skills/yida-prd/workflow/output-prd.md +2 -2
  158. package/yida-skills/skills/yida-prd/workflow/step-2-information-architecture.md +1 -1
  159. package/yida-skills/skills/yida-requirement-analysis/references/experience-groups.md +45 -9
  160. package/yida-skills/skills/yida-requirement-analysis/references/handoff.md +5 -5
  161. package/yida-skills/skills/yida-requirement-analysis/workflow/prepare-brief.md +17 -4
  162. package/yida-skills/skills-index.json +2 -2
@@ -1,12 +1,12 @@
1
1
  # 前台、管理端的菜单与权限
2
2
 
3
- 本说明用于前台、业务管理端和共用工作区的入口规划,无论本次只交付一端还是多个入口。这里的“管理端”用于处理业务数据,不是开发者修改应用的后台。
3
+ 本说明用于用户使用系统时的页面入口、菜单和权限规划。先按[判断是否分前后台](../../yida-requirement-analysis/references/experience-groups.md)确定“只有访问后台”“只有访问前台”“分前后台”或“不分前后台”。这里的前台和业务后台都是访问态页面;开发者修改应用配置的后台另行交付。
4
4
 
5
5
  例如报修应用:访客使用“我要报修、我的报修”,管理者使用“待处理工单、全部工单”。两端共享报修数据,但菜单名称、数量、顺序和打开后首先显示的内容可以不同。管理端可直接打开待处理列表,无需另建首页,也不必把访客首页放进管理菜单。
6
6
 
7
7
  ## 先确定这四件事
8
8
 
9
- 1. **谁来用**:只有一类用户共用工作区,还是分别提供访客入口和管理入口?
9
+ 1. **谁来用**:哪些人使用同一套业务页面,哪些人需要分别进入前台和后台?多种角色也可以不分前后台,按职责配置菜单和权限。
10
10
  2. **各自做什么**:逐项列出菜单任务,并按 [首页按任务选择](../../yida-requirement-analysis/references/experience-groups.md#首页按任务选择) 确定默认落点;管理端不自动使用驾驶舱。
11
11
  3. **在哪里做**:访客端通常在一个自定义页面内完成任务;管理端按需要使用宜搭原生列表、表单或自定义页面。
12
12
  4. **能看和能改哪些数据**:分别写清本人、本部门或其他明确范围,以及查看、提交、编辑等操作。
@@ -17,7 +17,7 @@ Fast(直接搭建)与 Plan(先确认方案)使用同一份入口规划
17
17
 
18
18
  ## 每个入口都确定首页与菜单顺序
19
19
 
20
- 前台、后台、共用工作区都要完成入口排序。逐入口确定以下内容,写入已有 `menu`、`defaultMenuKey` 和需求依据,不新增另一份顺序清单:
20
+ 无论是否分前后台,每个入口都要完成菜单排序。逐入口确定以下内容,写入已有 `menu`、`defaultMenuKey` 和需求依据,不新增另一份顺序清单:
21
21
 
22
22
  - **默认打开什么**:依据该角色进入应用后的首要任务选择页面或业务视图;写清真实资源、视图与入口链接。用户已指定首页时沿用,不因页面名称、创建先后或是否为自定义页面改选。
23
23
  - **菜单怎么排**:`menu[]` 及 `children[]` 的数组顺序就是展示顺序。按任务优先级、使用频率和业务流程组织;详情、填写、配置等是否成为顶级入口取决于实际用途,不把所有创建出的资源平铺进菜单。
@@ -61,7 +61,7 @@ Fast(直接搭建)与 Plan(先确认方案)使用同一份入口规划
61
61
 
62
62
  ### 整理管理菜单
63
63
 
64
- 有独立入口规划时,从管理端或共用工作区的菜单生成平台导航顺序:默认任务在前,同一资源只排一次。访客菜单不自动加入。
64
+ 有独立入口规划时,从业务后台或不分前后台的系统菜单生成平台导航顺序:默认任务在前,同一资源只排一次。访客菜单不自动加入。
65
65
 
66
66
  - 已有 `navigationOrder` 与入口规划冲突时,先修正规划,再生成产物。
67
67
  - 整个应用使用自定义导航或只交付前台时,仍按本入口的 `menu` 顺序和 `defaultMenuKey` 实现、发布并验收自定义导航;跳过的是平台排序命令。只改指定资源时保留无关入口的已有顺序。
@@ -110,7 +110,7 @@ Fast(直接搭建)与 Plan(先确认方案)使用同一份入口规划
110
110
 
111
111
  分别用访客、业务管理者、同时拥有两种身份的用户检查:
112
112
 
113
- - 分别从前台、后台或共用工作区的实际入口首次打开,核对默认页面、具体视图和首屏任务;菜单及分组顺序与规划一致。排序回读只证明资源顺序,不能替代实际首页验证。
113
+ - 从本轮交付的每个业务入口首次打开,核对默认页面、具体视图和首屏任务;菜单及分组顺序与规划一致。排序回读只证明资源顺序,不能替代实际首页验证。
114
114
  - 同一表单的填写、本人记录、管理视图分别遵守对应权限。
115
115
  - 无权限用户直接打开链接也不能访问;本人数据范围确实生效。
116
116
  - 刷新、直接打开子页面、浏览器前进后退后,菜单与内容仍然一致。
@@ -127,9 +127,9 @@ Fast(直接搭建)与 Plan(先确认方案)使用同一份入口规划
127
127
 
128
128
  | 字段 | 含义和要求 |
129
129
  | --- | --- |
130
- | `mode` | `unified`:共用工作区;`service-management`:访客端与管理端分开;`frontend-only`:只交付前台。实施前必须选定,不能为 `undetermined` |
131
- | `entries[]` | 每个入口填写 `key/name/role/menu/defaultMenuKey`;访客入口或包含 `local` 菜单的任意入口还需 `sceneKey` |
132
- | `role` | `service`:访客;`management`:业务管理者;`workspace`:共用工作区 |
130
+ | `mode` | `unified`:不分前后台;`service-management`:分前后台;`frontend-only`:只有访问前台;`backend-only`:只有访问后台。实施前必须选定,不能为 `undetermined`;旧 unified 计划保留原字段、值和角色,不自动改分类 |
131
+ | `entries[]` | backend-only 的每个入口 role 必须为 management;新建 unified 入口通常使用 workspace。每个入口填写 `key/name/role/menu/defaultMenuKey`;访客入口或包含 `local` 菜单的任意入口还需 `sceneKey` |
132
+ | `role` | `service`:前台使用者,如客户或报修员工,不表示匿名访问;`management`:业务处理人员;`workspace`:不分前后台时的使用者。实际数据和操作按权限配置 |
133
133
  | `sceneKey` | 关联唯一承载页面的顶层 `sceneKey`;service 入口必须关联 `entryMode=standalone`;management/workspace 含 local 菜单时也必须填写 |
134
134
  | `menu[]` | 数组及 children 的先后就是本入口展示顺序;分组用 `{key,label,children}`;可点击菜单用 `{key,label,resource,targetType,viewUuid?,viewKey?,access}` |
135
135
  | `resource` | 规划中的资源名称;实施时创建或查询资源,换成真实 ID |
@@ -157,6 +157,8 @@ Fast(直接搭建)与 Plan(先确认方案)使用同一份入口规划
157
157
 
158
158
  上述资源必须在计划中真实存在,页面需实现 `orders` 视图;其订单数据另列真实数据资源权限。管理端直接打开原生业务页面时使用 `page`,填写时使用 `submission`,这两种情况不要求为入口新增自定义承载页面。
159
159
 
160
+ `entryModeSummary` 是 CLI 根据 mode 生成的交接说明,供 PRD 和预览使用,不写入 build-plan.json。只有访问前台且提交后需要处理时,按需求分析记录的承接方式核验,不额外补建业务后台。
161
+
160
162
  ### 传入入口规划
161
163
 
162
164
  可以通过需求 JSON、Plan JSON,或以下命令更新:
@@ -181,7 +183,7 @@ openyida update-form-config <appType> <formUuid> <true|false|keep> "<页面标
181
183
 
182
184
  ### 接入页面权限查询
183
185
 
184
- 页面函数的 `mode=local|platform|independent` 表示菜单过滤方式,与规划字段 mode 的三种入口方案不同。
186
+ 页面函数的 `mode=local|platform|independent` 表示菜单过滤方式,与规划字段 mode 的四种入口方案不同。
185
187
 
186
188
  `resolveAccess({appType,requirements,signal})` 接收当前应用、权限要求和取消请求信号:
187
189
 
@@ -42,7 +42,7 @@ HTML 使用预置模板,保留需求总览、数据模型、业务流程、页
42
42
  {"question":"请确认当前搭建方案","options":[{"label":"确认并开始搭建","value":"confirm_build"},{"label":"继续调整","value":"continue_editing"}],"submitLabel":"提交选择","attachments":[{"name":"build-plan.html","path":"<outputs.html>"}],"revision":"<revision>"}
43
43
  ```
44
44
 
45
- 把 `<outputs.html>` 和 `<revision>` 替换为本次 materialize 的实际结果,不另造值。确认前不创建业务资源。
45
+ 优先将本次 materialize 或 patch --materialize 返回的 `confirmation` 对象原样传给 ask_human,它已经绑定同调用附件、revision 和固定选项。旧 CLI 没有该字段时,才按上例用实际 `<outputs.html>` 和 `<revision>` 填写,禁止另造值或省略 options/attachments/revision。确认前不创建业务资源。
46
46
 
47
47
  3. 结构化交互成功创建后将 `meta.planState.presentedRevision=meta.revision` 写回源 JSON,仅保存展示事实,不重新物化。询问“确认并开始搭建”或“继续调整”,提交时由宿主原样回传 revision,将确认结果绑定到本次展示版本。用户可见标题、摘要、附件名称与确认问题统一使用“搭建方案”或“当前方案”,不展示修订序号。内部 revision、展示记录和确认失效机制照常维护。
48
48
 
@@ -25,16 +25,17 @@
25
25
  ## 执行顺序
26
26
 
27
27
  1. 直接复用已确认的 `requirement-brief.json`;若尚未完成 Step 2 的规划准备,先按 [交接契约](../../../yida-requirement-analysis/references/handoff.md#规划阶段补齐) 补齐页面承载、导航与主题,AI 建议保留来源,不重新询问业务或导航;本文件已经包含规划入口,不再额外读取 `step-1-understand.md` 或 `step-2-confirm.md`。
28
- 2. 主题映射未确定时,执行一次 `openyida design-plan catalog --json`,从返回的 `themes` 选择 themeId,并复用 `pagePatterns`。已有合法主题 ID 时直接初始化。初始化计划草稿,CLI 返回编写契约与当前主题的精简上下文:
28
+ 2. 用户未给出明确完整视觉风格时,先执行 [Plan 视觉分支](../../../yida-design/sub_skill/yida-design-plan/SKILL.md):按 Fast / Plan 共用规则生成恰好三套候选,并通过 `ask_human` 获得用户选择。不得因用户未主动要求比较而跳过。获得选择或已有明确完整风格后,再继续主题映射和初始化。
29
+ 3. 主题映射未确定时,执行一次 `openyida design-plan catalog --json`,从返回的 `themes` 选择 themeId,并复用 `pagePatterns`。已有合法主题 ID 时直接初始化。初始化计划草稿,CLI 返回编写契约与当前主题的精简上下文:
29
30
 
30
31
  ```bash
31
32
  openyida design-plan init .cache/openyida/<项目名>/requirement-brief.json --theme-id <已选主题> --json
32
33
  ```
33
34
  `requirement-brief.json` 必须复用 `yida-requirement-analysis` 的输出结构,不要自行发明字段层级;`projectName` 位于 JSON 根级,`businessGoals` 等集合字段保持数组,命令第一次就传入 `visualSelection.themeId`。若 CLI 返回字段路径诊断,按 `expectedPath` 集中修正原文件后最多重试一次,不要通过反复更换项目名规避结构错误。
34
35
 
35
- 3. 按 init 返回的 `parallelTasks` 和 `dependsOn` 完成待补内容。CLI 预填业务骨架与已选主题;自定义页仍须补齐焦点、布局、主操作、响应式和验收,写入 `visual.json`。业务页面确定后完成视觉任务,可在同一轮中顺序填写两个文件。纯原生资源且两个片段均已就绪时,直接生成方案。
36
- 4. init 已创建并预填 `business.json` 骨架;读取该文件及 `context` 中的类型示例,按 `authoring.pendingFields` 的文件和字段路径补齐内容,保留 `base` 与已有事实。复核需求覆盖后,将已完成片段设为 `ready=true`。`business.json` 的 facts 填写 overview、dataModels、businessFlows、pages 和可选 execution;`visual.json` 的 facts 填写 visualStyle。同一次补齐所有普通表单的 sampleDataPlan(窄范围不造数时写 skipReason)及所有自定义页面的 permissionSummary,然后直接执行 init 返回的 `materialize.command`,只物化一次。标准首版禁止先试 `--from-preview`、`preview`、`--check` 或无参数 materialize;成功 JSON 已返回 HTML 路径和 revision,不再用 Glob、Read 或帮助命令检查产物。只有存在品牌稿、参考图、页面级特殊风格或用户明确要求精修时,才执行 `optionalTasks.visual-refinement` 后再物化。
37
- 5. 读取精确路径 `workflow/plan/step-4-deliver.md`,按其中契约直接展示并确认当前方案。超大需求需要展示中间进展或用户明确要求边生成边查看时,才使用 [按模块更新方案](../incremental-preview.md);普通首版不逐模块预览和重复渲染。
36
+ 4. 按 init 返回的 `parallelTasks` 和 `dependsOn` 完成待补内容。CLI 预填业务骨架与已选主题;自定义页仍须补齐焦点、布局、主操作、响应式和验收,写入 `visual.json`。业务页面确定后完成视觉任务,可在同一轮中顺序填写两个文件。纯原生资源且两个片段均已就绪时,直接生成方案。
37
+ 5. init 已创建并预填 `business.json` 骨架;读取该文件及 `context` 中的类型示例,按 `authoring.pendingFields` 的文件和字段路径补齐内容,保留 `base` 与已有事实。复核需求覆盖后,将已完成片段设为 `ready=true`。`business.json` 的 facts 填写 overview、dataModels、businessFlows、pages 和可选 execution;`visual.json` 的 facts 填写 visualStyle。同一次补齐所有普通表单的 sampleDataPlan(窄范围不造数时写 skipReason)及所有自定义页面的 permissionSummary,然后直接执行 init 返回的 `materialize.command`,只物化一次。标准首版禁止先试 `--from-preview`、`preview`、`--check` 或无参数 materialize;成功 JSON 已返回 HTML 路径和 revision,不再用 Glob、Read 或帮助命令检查产物。只有存在品牌稿、参考图、页面级特殊风格或用户明确要求精修时,才执行 `optionalTasks.visual-refinement` 后再物化。
38
+ 6. 读取精确路径 `workflow/plan/step-4-deliver.md`,按其中契约直接展示并确认当前方案。超大需求需要展示中间进展或用户明确要求边生成边查看时,才使用 [按模块更新方案](../incremental-preview.md);普通首版不逐模块预览和重复渲染。
38
39
 
39
40
  明确范围的方案以 `explicitScope` 作为完整执行清单。确认后的每个写操作都对应清单中的一个资源或交付项;清单资源全部回读且真实链接完成交付时,本轮达到完成态。
40
41
 
@@ -57,3 +58,9 @@ build-plan.json(业务和视觉的源事实)
57
58
  草稿按已确定的模块更新,最终校验后统一保存三份文档和主题 CSS。后续业务或视觉调整按 [局部调整](step-4-deliver.md#4-处理调整) 更新并确认;素材进度同步沿用已有确认。
58
59
 
59
60
  用户交互按 [可见表达契约](../../../yida-design/references/ask-human-interaction-contract.md) 执行。当前展示版本确认后,先按物化返回的 `assetTasks` 启动素材任务,再将 `prd.md`、`design.md` 和 `outputs.theme` 交给主流程 Step 3;搜索与创建应用同时推进。仅完整应用同步主题设置;`explicitScope.allowInferredResources=false` 时忽略主题和导航交接,只创建范围内资源并交付,不重复物化计划。
61
+
62
+ ## 加载失败与内容修复
63
+
64
+ 技能加载失败、限流或换模型后,先成功读取本工作流和当前步骤,再沿用已确认需求继续;未加载成功不得凭记忆生成 HTML 或确认参数。首次物化前只修 business.json/visual.json 对应 facts(菜单与执行规划在 business.facts.execution),不要直接修初始化主计划。字段错误按具体路径修正后重试。
65
+
66
+ 如果已经改动主计划并出现 DESIGN_PLAN_STALE_PART,在原 materialize 命令增加 --rebase-parts。CLI 使用 init 保存的 .build-plan-base.json 做三方核对,保留已完成 facts;冲突按 details.conflicts 明确选择后重试。基线缺失或无法核实时告知阻塞并恢复可信文件,不手填 digest、不删除重建、不重新 init。已物化后调整走 patch --materialize,不继续复用初始化片段。
@@ -20,7 +20,7 @@
20
20
  2. 按 [模式路由](../../yida-design/references/design-mode.md) 确定执行方式,沿用用户最后一次明确选择。
21
21
  3. AI 根据有效功能、`userTasks` 与 `entryRecommendation`,按 [导航决策](../../yida-design/references/navigation-decision.md) 规划各入口的页面和菜单,补齐稳定 `pageScenes` 与主题映射。新增建议标记来源,范围遵守 explicitScope。
22
22
 
23
- Fast / Plan 的主题与配色统一按[设计方向比较](../../yida-design/references/theme-selection.md#设计方向比较)在本轮规划中选定,结果写回 brief,后续直接复用。
23
+ Fast / Plan 的主题与配色统一按[设计方向比较](../../yida-design/references/theme-selection.md#设计方向比较)在本轮规划中选定,结果写回 brief,后续直接复用。两种模式使用同一组三方向生成规则:Fast 内部选一套;Plan 在用户未给出明确完整风格时,先由 `yida-design-plan` 生成恰好三套候选并调用 `ask_human`,获得选择后才能继续 Plan 初始化。
24
24
 
25
25
  进入 2.1 前校验规划字段完整性和 `intake.designMode`。页面、导航、主题等建议随整体搭建方案展示。
26
26
 
@@ -48,7 +48,7 @@ Plan 分支从已加载 `yida-app` 的 Available Files 读取精确路径 `workf
48
48
  | 内容 | 负责技能 | 输出 | 完成条件 |
49
49
  | --- | --- | --- | --- |
50
50
  | Product PRD | `yida-prd` | `prd/<项目名>/prd.md` | 资源蓝图、资源创建顺序、页面实现交付顺序、导航顺序、页面 handoff 和验收标准完整 |
51
- | Visual Design | `yida-design` | `prd/<项目名>/design.md` | 主题 token、视觉特征、布局、材质、圆角、密度、组件、状态、响应式和页面场景引用完整 |
51
+ | Visual Design | `yida-design` | `prd/<项目名>/design.md` | 导航、应用框架、表单、详情与自定义页面共用完整主题 token;布局、材质、形状、密度、组件、状态、响应式和页面场景引用完整 |
52
52
 
53
53
  两个技能读取同一份已确认需求,业务规划与基础视觉同时准备;页面任务、区块和 sceneKey 确定后补齐逐页视觉绑定。各自维护职责内的文件。某一份生成失败时只重跑对应技能,不覆盖已经完成的另一份。
54
54
 
@@ -76,7 +76,7 @@ Fast 设计就绪后按 [素材调度](parallel-work.md#素材与页面同时推
76
76
 
77
77
  ## 主题文件实现指令
78
78
 
79
- 在设计中确定配色、导航明暗和布局。未禁止 `theme-file` 时,Plan 使用 CLI 返回的 `outputs.theme`,Fast 按 [主题文件生成与更新](../../yida-design/workflow/output-design.md#cli-token-契约fast--plan-共用) 准备主题 CSS;用户确认计划或主题后即可启动 CSS 生成,不等待表单或页面开发。Plan 已生成当前版本的 CSS 时直接复用。拿到真实 appType 后,在应用级配置同一份主题文件,与表单创建和页面开发并行;页面组件按已确认契约消费主题 token。若 `theme-file` 被禁止,跳过生成、复制、修改和上传,沿用现有平台主题并在交付中说明未更改主题。详见 [主题与业务资源的依赖](parallel-work.md#主题与业务资源的依赖)。
79
+ 在设计中同时确定导航、应用框架、表单、详情与自定义页面的整体风格。命名模板提供完整导航 token 与派生的导航明暗,自由创意明确填写;布局沿用业务规划。未禁止 `theme-file` 时,Plan 使用 CLI 返回的 `outputs.theme`,Fast 按 [主题文件生成与更新](../../yida-design/workflow/output-design.md#cli-token-契约fast--plan-共用) 准备主题 CSS;用户确认计划或主题后即可启动 CSS 生成,不等待表单或页面开发。Plan 已生成当前版本的 CSS 时直接复用。拿到真实 appType 后,在应用级配置同一份主题文件,与表单创建和页面开发并行;页面组件按已确认契约消费主题 token。若 `theme-file` 被禁止,跳过生成、复制、修改和上传,沿用现有平台主题并在交付中说明未更改主题。详见 [主题与业务资源的依赖](parallel-work.md#主题与业务资源的依赖)。
80
80
 
81
81
  ## 产出
82
82
 
@@ -56,13 +56,13 @@
56
56
 
57
57
  例如,仅将已有应用切换为平台顶部导航:`openyida update-app <appType> --layout top --show-app-nav`。联合更新主题时,将这两个参数合并到同一次 `update-app --theme-file` 调用。
58
58
 
59
- Agent 必须显式传入场景选择对应的布局,不依赖 CLI 默认值。`navigationType=platform-top` 是计划内部标识,不能作为 `--layout` 的值;也不能用旧 Shell 的 `navType`、`hoz/ver/slide` 或 `top_fold/top_side/side_only` 代替上述参数。`navTheme` 只控制导航配色,不控制布局。自定义导航的 `variant=top/side/mixed/dock` 描述页面内菜单,不用于设置平台布局;自定义导航仍使用 `--hide-app-nav`。
59
+ Agent 必须显式传入场景选择对应的布局,不依赖 CLI 默认值。`navigationType=platform-top` 是计划内部标识,不能作为 `--layout` 的值;也不能用旧 Shell 的 `navType`、`hoz/ver/slide` 或 `top_fold/top_side/side_only` 代替上述参数。`navTheme` 选择导航明暗模式,完整导航 token 决定实际配色、边界、形状、文字和间距;圆角、三种状态边框和选中阴影先写入设计,再按 [命令与参数](../../yida-design/references/application-style-library.md#命令与参数) 重新生成 CSS 并上传;布局仍由 `--layout` 设置。自定义导航的 `variant=top/side/mixed/dock` 描述页面内菜单,不用于设置平台布局;自定义导航仍使用 `--hide-app-nav`。
60
60
 
61
61
  `navType` 是兼容字段:CLI 查询应用后将已有值原样带回;缺失时不补造,也不根据新布局改写。没有 `--nav-type` 参数。未传 `--layout` 时,CLI 保留原布局:现代 `side/top/l_shape` 优先;旧 `hoz + top_side` 为 L 型,其他 `hoz` 为顶部,`ver` 为侧边;布局缺失时用 `navType=top_fold/top_side` 分别恢复顶部/L 型,其余回退侧边。
62
62
 
63
63
  Shell 渲染阶段才把顶部、侧边、L 型转换为 `top_fold`、`side_only`、`top_side`。详情/提交页的 `top_fold` 强制顶部、`none` 保持无导航属于页面运行态规则,不能反向写入应用配置。
64
64
 
65
- 保存后核对应用详情中的 `layoutDirection` 与 `hideAppNav` 是否等于目标值,可通过应用设置页或 `/<appType>/query/app/getAppIncludingAecpInfo.json` 回读。CLI 输出的 `updatedFields` 是提交值,`themeVerification` 只验证主题资源,两者都不能单独证明导航配置已生效。发布后再刷新应用,检查实际布局;未完成回读时明确标记未验证。
65
+ 保存后读取 CLI 的 `navigationVerification`:`verified=true` 且其中本次请求的 `navTheme`、`layoutDirection`、`hideAppNav`、`logoSource` 与目标一致,表示导航设置回读通过。旧布局字段由 CLI 归一化后比较;缺少回读证据时保持未验证。CLI 最多重试三次只读查询,失败返回 `APP_NAVIGATION_NOT_PERSISTED`,按返回的期望值、实际值和查询错误核实应用设置。`updatedFields` 仍是提交值,`themeVerification` 仍只验证主题资源。发布后刷新应用,检查实际导航、内容布局与状态;设置回读通过与页面视觉验收分别记录。
66
66
 
67
67
  ## 产出
68
68
 
@@ -12,7 +12,7 @@
12
12
 
13
13
  ## 自定义导航分支
14
14
 
15
- 前台、后台及共用工作区的自定义导航均按 [首页与菜单顺序](../references/entry-navigation.md#每个入口都确定首页与菜单顺序) 实施:发布前核对每个入口菜单数组及分组顺序、`defaultMenuKey` 对应的页面/视图,发布后从实际入口验证首屏。`frontend-only` 不调用平台排序命令,但必须完成上述排序和验收。
15
+ 无论是否分前后台,自定义导航均按 [首页与菜单顺序](../references/entry-navigation.md#每个入口都确定首页与菜单顺序) 实施:发布前核对每个入口菜单数组及分组顺序、`defaultMenuKey` 对应的页面/视图,发布后从实际入口验证首屏。`frontend-only` 不调用平台排序命令,但必须完成上述排序和验收。
16
16
 
17
17
  PRD 的应用工作区导航 `execution.appConfig.navigationType=custom` 时,页面导航已在 Step 4 / Step 6 创建或复用页面后按 [导航壳必做配置](../../yida-nav-shell/SKILL.md#必做配置) 隐藏并回读,与源码开发并行。本步骤发布并检查本轮全部自定义页面,再回读核对 `renderNav=false`;缺失或被发布改变时才补写修复,不把首次隐藏推迟到发布后。导航顺序由自定义导航实现;汇总 Step 4 / Step 6 的配置结果与发布后回读结果,覆盖 PRD 全部页面后进入 Step 9。下方平台导航排序仅适用于三种平台导航类型。
18
18
 
@@ -49,7 +49,7 @@ openyida nav-group auto-order <appType>
49
49
 
50
50
  4. 同一搭建 Run 不得同时执行显式排序与自动排序,不生成逐项 `move` 的 Bash/Python 循环。
51
51
  5. 逐入口落实任务顺序与默认页:平台菜单消费 entryRecommendation 派生的 navigationOrder;自定义菜单消费该入口的 menu 和 defaultMenuKey。前台首页不自动进入后台,frontend-only 仍需完成前台菜单排序。
52
- 6. 分别从本轮交付的前台、后台与共用工作区入口检查实际菜单顺序、默认页面、具体视图和首屏内容。平台排序 `readbackVerified=true` 不证明首页已正确;根入口仍打开错误任务时,继续处理平台支持的默认页配置,能力未验证时交付明确任务链接并标记根入口待验证。平台导航管理页只保留一套跨模块导航,重复时修正页面源码。
52
+ 6. 从本轮交付的每个业务入口检查实际菜单顺序、默认页面、具体视图和首屏内容。平台排序 `readbackVerified=true` 不证明首页已正确;根入口仍打开错误任务时,继续处理平台支持的默认页配置,能力未验证时交付明确任务链接并标记根入口待验证。平台导航管理页只保留一套跨模块导航,重复时修正页面源码。
53
53
  7. 本步骤配置宜搭平台导航,不要求页面源码实现侧边栏或顶部应用导航;只有 PRD 已规划该入口自己的菜单时才实现,不因平台排序再回头补导航壳。
54
54
  7. 本轮任一页面 `entryMode=standalone` 时,Step 6 已在取得页面 ID 后隐藏页面导航;发布和健康检查通过后执行 `openyida get-form-config <appType> <displayPageFormUuid> --json` 核对。配置缺失或变化时才执行 `openyida update-form-config <appType> <displayPageFormUuid> false "<页面标题>"` 并再次回读。只有回读明确为 `renderNav=false` 时,才把干净的 `{base_url}/{appType}/custom/{displayPageFormUuid}` 交给 Step 9 作为独立业务入口;写入或回读失败时只保留工作台入口,不用 `?isRenderNav=false` 猜测成功。
55
55
  8. 主页面 `entryMode=platform-shell` 或缺失时,不修改页面导航配置,也不输出独立业务入口。
@@ -76,7 +76,7 @@ openyida nav-group auto-order <appType>
76
76
  - [ ] 发布目标是已解析的 display 页面;
77
77
  - [ ] Canvas 发布结果为 `publishMode=canvas`,且 `healthCheck.ok=true`、`healthCheck.readback.hasYidaCodeCanvas=true`、`runtimeCodeBytes>0`;
78
78
  - [ ] 已获得可访问 URL;
79
- - [ ] 本轮每个前台、后台或共用工作区入口都已核对默认页面、菜单及分组顺序和首屏任务;自定义导航没有因跳过平台排序命令而漏验;
79
+ - [ ] 本轮每个业务入口都已核对默认页面、菜单及分组顺序和首屏任务;自定义导航没有因跳过平台排序命令而漏验;
80
80
  - [ ] 自定义导航业务工作区切换后的 main 和 iframe 撑满剩余空间;连续展示页的首屏背景覆盖导航背后,滚动进入第二屏及窄屏展开菜单仍可读;检查短/长内容、窗口高度变化和底部操作可达性,无双滚动、背景断带或意外边距变化;
81
81
  - [ ] 按 [页面与导航连续性](../../yida-design/references/page-continuity.md) 验证菜单往返、直接链接、刷新、前进后退、重复/快速点击及加载失败;保留约定的筛选、分页、位置和未保存输入,URL、选中态与内容一致;
82
82
  - [ ] 使用自定义导航时逐项点击,导航仍可见、可操作,选中项与主内容一致且能返回工作台;刷新、前进后退恢复任务,无双导航和双滚动条,不能仅以目标页打开成功验收;
@@ -110,10 +110,11 @@
110
110
  - 用户或调用方明确要求资源清单、资源 UUID/ID、发布状态或测试数据摘要时,终态 artifact 的 `description` 包含简洁的“交付清单”。清单是本轮真实返回值和只读 readback 的投影,覆盖已创建或发布资源的名称、类型、ID、主页面发布状态及 seed records 写入/抽查摘要;未知信息标记为未核验。
111
111
  - 业务总结中的资源数量、seed records 数量和完成状态与逐资源真实返回值/readback 一一对应;证据不完整的资源标记为未核验。
112
112
  - 新增、修改或发布单个具体页面时,交付当前页面并保持单页范围。
113
- - 完整应用的入口组按有效范围交付:统一工作区或前后台双入口包含经验证的“业务管理入口”:根 `{base_url}/{appType}/workbench` 或上述指定任务/视图链接;明确仅前台时不追加业务后台,但仍提供开发者管理后台。
113
+ - 完整应用的入口组按有效范围交付:不分前后台时提供经验证的“系统入口”,分前后台或只有访问后台时提供经验证的“业务后台入口”:根 `{base_url}/{appType}/workbench` 或上述指定任务/视图链接;明确仅前台时不追加业务后台,但仍提供开发者管理后台。
114
+ - 只有访问后台时核验业务处理人员的入口、数据范围和操作,不追加前台;只有访问前台且提交后需要处理时,核验已有系统、人员入口或自动流程如何承接,未核验的部分明确说明。
114
115
  - 前台页面在 PRD 中为 `entryMode=standalone`,且 Step 8 回读确认 `renderNav=false` 时,入口组包含“前台” `{base_url}/{appType}/custom/{formUuid}`;否则不得输出。
115
116
  - 完整应用默认交付“开发者管理后台” `{base_url}/{appType}/admin`,使用 `create-app` 或 `app-list` 成功结果中的 `adminUrl`。`application_entry_policy.entries.admin=include` 不受云端/本地宿主或登录态注入方式影响;不要沿用旧版本云端省略 admin 的规则。地址生成不代表已验证收件人的管理权限,实际访问仍由平台鉴权。
116
- - 完整应用一般为 2–3 个地址:有前后台时为“前台、业务后台、开发者管理后台”;仅前台时为“前台、开发者管理后台”;统一工作区时为“应用工作台、开发者管理后台”。同一业务入口不重复凑数,不为补链接创建额外业务后台。用户明确排除开发者入口时遵从;单页任务保持单页交付范围。
117
+ - 完整应用一般为 2–3 个地址:有前后台时为“前台、业务后台、开发者管理后台”;仅前台时为“前台、开发者管理后台”;仅业务后台时为“业务后台、开发者管理后台”;不分前后台时为“系统入口、开发者管理后台”。同一业务入口不重复凑数,不为补链接创建额外业务后台。用户明确排除开发者入口时遵从;单页任务保持单页交付范围。
117
118
  - 若历史创建结果缺少 `adminUrl`,分页查询 `app-list` 并匹配真实 `appType`(名称仅辅助识别),保留其 `adminUrl`;不要自行猜租户域名或资源 ID。无法取得时明确标记开发者入口待补齐,不得静默省略或声明交付完成。
118
119
  - 三个入口属于同一个应用入口组,不得各自连同业务资源再生成多组交付。
119
120
  - 不把 `g.alicdn.com` 的 `index.css`、`index.js`、`index.html`、`locales/*.json`、构建产物 URL、CDN 资源 URL 或中间文件链接当成最终结果展示。
@@ -114,7 +114,7 @@ function setNavigationTitle(title) {
114
114
  2. **组件增强可降级**:门户、成员、部门、上传组件都做 feature detect 和 fallback;组件缺失时页面仍展示自绘基线。
115
115
  3. **值先归一化**:成员、部门、文件的原始返回值保留到 `raw` 用于检查,业务 payload 使用统一结构。
116
116
  4. **UI 改造保持功能契约**:页面美感提升、页面重构和局部美化只调整颜色、布局、密度、间距、视觉层级、素材和图标表达;已有数据源、字段映射、按钮动作、筛选逻辑、提交 URL、权限和业务状态按原有实现保留。
117
- 5. **页面跟随应用主题**:应用设置使用 `app-theme.css`;页面通过 `--color-brand1-*`、`--color-group` 和 `--pod-*` 取色。页面底色使用 `--pod-page-bg-color`,卡片使用 `--pod-card-bg-color`,抽屉整体背景使用 `--pod-shell-theme-bg-color`,正文容器保持透明;自绘导航页按 `design.md` 设置内部画布背景。样式限定在 `YidaComp` 内,应用主题通过 `update-app --theme-file` 更新。根节点使用 `display:flow-root` 或 flex/grid,将导航间距留在根节点内部。宿主背景和局部画布规则见 [样式指南](references/canvas-style-implementation-guide.md)。
117
+ 5. **页面跟随应用主题**:应用设置使用 `app-theme.css`;页面通过 `--color-brand1-*`、`--color-group` 和 `--pod-*` 取色。页面底色使用 `--pod-page-bg-color`,卡片使用 `--pod-card-bg-color`,抽屉外壳背景使用 `--pod-shell-theme-bg-color`,正文容器保持透明;自绘导航页按 `design.md` 设置内部画布背景。样式限定在 `YidaComp` 内,应用主题通过 `update-app --theme-file` 更新。根节点使用 `display:flow-root` 或 flex/grid,将导航间距留在根节点内部。宿主背景和局部画布规则见 [样式指南](references/canvas-style-implementation-guide.md)。
118
118
  6. **先验证再扩展业务**:原生组件、上传、组织搜索、弹层类能力先做 smoke 页面,确认 PC/移动端都可用后再进入复杂业务页面。
119
119
  7. **按设计编写 UI,示例按需参考**:新建 `.canvas.jsx` / `.canvas.tsx` 时,直接按 PRD、`design.md`、真实数据和页面交互实现,允许从空文件编写。需要参考完整表单交互时,可执行 `openyida sample openyida-page-template canvas-form-drawer --output .cache/samples/form-drawer.canvas.jsx --var APP_TYPE=<appType> --var FORM_UUID=<formUuid>`;整页示例按需参考;含表单打开入口时,必须按下方“表单打开入口统一容器”整体合并抽屉片段,不能裁剪交互能力。页面其余布局、材质、留白、圆角和选中态按设计实现。未改写的示例不得直接发布;页面 UI、业务文案、交付说明和 final 中不出现内部示例名、生成过程或实现代号。使用示例时,发布前删除 `@openyida-page-template-base`、`SAMPLE_ROWS`、`{{APP_TYPE}}` / `{{FORM_UUID}}`、示例数据和占位文案。
120
120
  8. **用文件编辑工具维护源码**:业务源码使用 Write/Edit/patch 编写,已有 JSX/CSS/JSON 源码只做定点 Edit。主题代码使用 `sample` 提取,或由 `scripts/build-canvas-theme.js` 插入标记处并输出独立文件。修改业务时编辑原始文件,再重新运行主题脚本。
@@ -126,7 +126,7 @@ function setNavigationTitle(title) {
126
126
  13. **页面产物使用纯文本业务文案**:`.canvas.jsx` 源码、`page-spec.json` 中会渲染到页面的文案、JS 注释、数据常量和产物文件路径都使用无 emoji 文本。页面生成、`compileCanvasLocal` 或 `publish` 报 emoji 错误时,先改 spec/源码/路径,再重新校验发布。若 emoji 原本承担图标含义,必须按 `design.md.iconSystem` 改成 `lucide-react` 或 `@ant-design/icons` 的具体组件,默认 `lucide-react`;不得用 CSS 绘制图形、单字母、首字母、标点符号、Unicode 符号或临时 SVG 冒充图标。
127
127
  14. **JSX 文案只能是文本或字符串**:JSX 文案只能写成纯文本 `所有级别` 或带引号字符串 `{'所有级别'}`;筛选项、按钮、状态、空态和表格列名等中文业务文案都按此规则书写。花括号里只能放真实 JS 变量/表达式,不能把中文文案写成 `{所有级别}`、`{处理中}`;Unicode escape 被工具解码后也必须保留字符串引号。
128
128
  15. **先区分应用导航与入口菜单**:按 PRD 应用 navigationType 和当前页 pageSpecHandoff.entryMode/navigation 执行。普通页默认保留平台导航,页面内 tab 不触发应用级隐藏;独立前台可有自己的顶部、侧边或底部菜单,执行 `use_skill("yida-nav-shell")` 的页面级分支,只配置当前页。仅整个应用采用自定义导航时才执行 `openyida update-app <appType> --hide-app-nav`;不得因前台 custom 隐藏后台应用菜单。
129
- 16. **表单提交必须接入提供的抽屉模板**:前台、后台、Fast、Plan 的页面内新增、报名、申请、预约等普通表单提交,以及表单详情入口,统一使用 `FormOpenContainer`;不能因为页面是全码开发就自绘填写表单并直接调用提交 API,也不能由 AI 自行改成普通链接、新窗口或简化弹层。先执行 `openyida sample openyida-page-template form-open-container --output .cache/samples/form-open-container.jsx`,整体合并 `CanvasDrawer` / `FormOpenContainer` / `useYidaFormOpen` 及其 import 和辅助函数。业务按钮调用 `openForm`,页面 JSX 必须渲染 `formOpenContainer`,接入真实表单、实例 ID 和刷新函数。保留三个标题栏图标操作、拖拽调宽、关闭刷新和 iframe 自适应高度;移动端打开方式由模板处理。只能通过主题变量和现有 props 调整外观,不重写外壳。搜索筛选不是表单提交;已明确的表格批量录入沿用专用技能。应用级导航已确定在主内容区嵌入原生提交页时按 [入口用途](../yida-nav-shell/references/nav-shell-patterns.md#入口用途与嵌入页面) 执行;不能以此绕过页面内按钮的抽屉要求。接入步骤见 [标准容器](references/navigation-and-entry-guide.md#接入示例)。
129
+ 16. **表单提交必须接入提供的抽屉模板(登录态默认,匿名态窄例外)**:前台、后台、Fast、Plan 的页面内新增、报名、申请、预约等普通登录态表单提交,以及表单详情入口,统一使用 `FormOpenContainer`;不能因为页面是全码开发就自绘填写表单并直接调用登录态提交 API,也不能由 AI 自行改成普通链接、新窗口或简化弹层。先执行 `openyida sample openyida-page-template form-open-container --output .cache/samples/form-open-container.jsx`,整体合并 `CanvasDrawer` / `FormOpenContainer` / `useYidaFormOpen` 及其 import 和辅助函数。业务按钮调用 `openForm`,页面 JSX 必须渲染 `formOpenContainer`,接入真实表单、实例 ID 和刷新函数。保留三个标题栏图标操作、拖拽调宽、关闭刷新和 iframe 自适应高度;移动端打开方式由模板处理。只能通过主题变量和现有 props 调整外观,不重写外壳。搜索筛选不是表单提交;已明确的表格批量录入沿用专用技能。应用级导航已确定在主内容区嵌入原生提交页时按 [入口用途](../yida-nav-shell/references/nav-shell-patterns.md#入口用途与嵌入页面) 执行;不能以此绕过页面内按钮的抽屉要求。接入步骤见 [标准容器](references/navigation-and-entry-guide.md#接入示例)。唯一窄例外是用户明确要求 `/o/...` 公开页面匿名采集,且显示页、目标普通表单公开状态和目标表单 `FREE_LOGIN` 权限三项门禁均已回读通过;此时加载 `yida-canvas-data-binding`,按[公开访问(匿名态)提交](references/data-bridge-guide.md#公开访问匿名态提交)自绘受控字段并走 `RECEIPT_SAVE_FORM_DATA`,发布后必须按返回的实例 ID 回读字段值。任一门禁不满足、需要流程或需要真实身份时仍使用登录态方案,不适用该例外。
130
130
  17. **图标资源固定为可加载库**:页面图标只使用 `lucide-react` 或 `@ant-design/icons`,默认使用 `lucide-react` named import。只有页面已经采用 Ant Design 图标语言、或 antd 组件语境需要 Outlined 图标时,才使用 `@ant-design/icons`。快捷入口、按钮、状态、导航和空态图标在写源码前先建立 `actionIconMap` / `statusIconMap`,按业务语义映射到具体组件,例如 `Plus`、`Upload`、`Download`、`Eye`、`Building2`、`AlertCircle`、`Check`。图标外层可以用 CSS 控制尺寸、颜色、圆角、背景和 hover,但图标本体必须来自上述两类组件,不能用 CSS 形状、字母或 emoji 替代。包名可用不代表任意图标都存在;以宜搭运行时导出为准,不照搬最新版官网名称。`OPENYIDA_CANVAS_ICON_EXPORT_UNAVAILABLE` 必须修正具体 import 后重新编译;动态名称使用显式组件映射并提供可用图标兜底,详见 [运行时图标校验](references/component-library-guide.md#运行时图标校验)。
131
131
 
132
132
  18. **对话框统一消费主题 token**:新增或改造对话框时,执行 `openyida sample openyida-page-template canvas-dialog --output .cache/samples/canvas-dialog.jsx`,将 `CanvasDialog` 合并到当前页面并接入业务状态,见 [对话框](references/dialog-guide.md)。标题、正文、背景、页脚、关闭按钮和操作按钮均消费应用 token;整体暗色适配与导航明暗分别判断。
@@ -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 |
@@ -152,7 +152,7 @@ CLI 在同一次 batch 内对已取得真实 `formUuid` 的空壳表单执行一
152
152
 
153
153
  ## 表单布局样式
154
154
 
155
- - 表单和详情延续 `design.md` 中已确定的应用风格。按 [表单样式与提交页背景](../yida-design/references/native-form-styles.md) 将字体、控件、状态、背景与底栏规则写入同一份应用主题 CSS。
155
+ - 提交、编辑和记录详情与导航、应用框架、自定义页面共用 `design.md` 的整体风格。按 [表单样式与提交页背景](../yida-design/references/native-form-styles.md) 将字体、控件、状态、背景与底栏规则写入同一份应用主题 CSS。
156
156
  - 布局结构按[布局决策规则](#布局决策规则)执行,并在 `design.md` 记录列宽、标签位置、分组间距与响应式安排。
157
157
  - `--theme default|compact|comfortable` 配置页面密度;应用主题 token 配置完整视觉风格。美化已有表单时保留现有 `formUuid` 和字段结构,只更新布局与主题。
158
158
  - 局部多列容器使用统一、克制的背景。
@@ -3,7 +3,7 @@ name: yida-design
3
3
  description: >
4
4
  当用户要做完整应用视觉设计、单页 UI 改造、主页面视觉设计、应用主题色或全局换肤时使用。
5
5
  完整应用读取共享需求:Fast 并行输出 design.md,Plan 维护视觉事实后由 CLI 生成 design.md。
6
- design.md 写主题 token、布局、材质、圆角、密度、呼吸感、组件和状态规则。
6
+ 将导航、应用框架、表单、记录详情和自定义页面一起设计,在 design.md 写入统一的主题 token、布局、材质、形状、间距与状态规则。
7
7
  ---
8
8
 
9
9
  # yida-design
@@ -12,6 +12,8 @@ description: >
12
12
 
13
13
  宜搭平台基础变量是平台提供的应用主题基础变量框架。项目主题在这套基础变量上按需扩展材质、布局、字体、动效和组件状态变量。先确定设计效果,再写入对应变量和消费位置;见 [主题扩展规则](references/application-theme-consistency.md#平台基础变量是应用主题基础框架)。
14
14
 
15
+ 设计导航时,把菜单圆角、三态边框、选中阴影、项高、内距和间距一起写入主题,并在访问态的数据管理页与业务页面检查效果,见 [导航形状与密度的案例经验](references/application-theme-consistency.md#导航形状与密度的案例经验)。
16
+
15
17
  确定风格前,按[设计方向比较](references/theme-selection.md#设计方向比较)以第一直觉为参照,发展两个更有表现力的方向,在当前规划轮次内选定。已有明确视觉要求时,在其范围内完善设计。
16
18
 
17
19
  向用户说明设计时,写风格和适用场景:“设计主题风格为轻盈媒体栅格,适合产品展示型品牌官网。”风格名称与场景按当前项目填写;建议阶段使用“建议采用……风格”。
@@ -64,7 +66,7 @@ Fast、Plan 和单页设计使用相同的 UI 设计规则、主题变量和质
64
66
  3. **默认保留平台应用导航**:普通自定义页、页面内 tab、分段、筛选和快捷入口都不触发 `yida-nav-shell`。PRD 的应用工作区选择自定义导航,或用户明确要求自绘应用级导航、隐藏应用导航时,写 `appBlueprint.hideAppNav: 'y'` 并交给 `yida-nav-shell`。独立前台选择自己的菜单时,同样进入 `yida-nav-shell`,但只配置该页独立展示,保留后台应用导航。用户只说全屏、无导航或 `isRenderNav=false` 时,只写页面级隐藏配置。
65
67
  4. **同应用页面入口归导航**:同应用页面优先放入平台导航或导航分组;自定义页内容区放当前页动作、原生表单新建/查看、外部链接和跨应用资源。
66
68
  5. **表单入口响应式**:新增/提交页 URL 默认使用页面级隐藏导航的 `submission/{formUuid}?isRenderNav=false`;详情页 URL 默认使用 `formDetail/{formUuid}?formInstId={formInstId}&navConfig.layout=1180&isRenderNav=false`,且 `formInstId` 必须来自真实数据记录并优先取 `row.formInstId`;PC 端默认在侧边抽屉中用 iframe 承载宜搭原生表单,抽屉默认半屏 `50vw`,提交页和详情页使用同一宽度规则;移动端整页或新页打开。
67
- 6. **主题文件**:Plan 使用 CLI 返回的 `outputs.theme`;Fast 和已有主题调整按 [主题文件生成与更新](workflow/output-design.md#cli-token-契约fast--plan-共用) 执行。按 [共用主题规则](references/application-theme-consistency.md) 将已选风格落实为 token,并核对生成的 CSS。修改变量要回到设计源后重新生成、上传;仅 CLI 未覆盖且已核实选择器的样式覆盖可在 CSS 末尾小范围追加,不另写脚本生成或重写主题文件。
69
+ 6. **主题文件**:主题目录统一包含设计、CSS、表单布局三个文件,导出和生成参数见 [命令与参数](references/application-style-library.md#命令与参数)。Plan 使用 CLI 返回的 `outputs.theme`;Fast 和已有主题调整按 [主题文件生成与更新](workflow/output-design.md#cli-token-契约fast--plan-共用) 执行。按 [共用主题规则](references/application-theme-consistency.md) 将已选风格落实为 token,并核对生成的 CSS。修改变量要回到设计源后重新生成、上传;仅 CLI 未覆盖且已核实选择器的样式覆盖可在 CSS 末尾小范围追加,不另写脚本生成或重写主题文件。
68
70
  7. **默认主题先做业务判断**:工作台、门户、列表、详情、普通看板和数据大屏默认都是浅底 / light 模式,但主色不固定为 `podBlue` 或 #1677ff;先根据行业、品牌、业务情绪和视觉目标做创意色彩判断,主题色可以是任意合法 CSS 颜色。只有用户明确说暗色/深色/夜间/高对比时才用深色沉浸。
69
71
  8. **页面布局要到可实现粒度**:每个页面至少写清顶部/左侧/主体/右侧/底部区域、核心组件、信息密度、主操作位置、PC/移动端差异和空/载/错态。
70
72
  9. **页面丰富度建议**:工作台、首页、门户、看板、展示页和业务入口页推荐规划 8-10 个有业务目的的区块以上,例如上下文标题、状态摘要、主操作、筛选、任务列表、最近记录、动态流、洞察、提醒、空态行动、右侧上下文和底部辅助信息。区块数量不是硬门槛,窄场景、单任务页面或用户明确要求精简时可以更少,但要写清每个区块的业务目的和取舍原因。计数按“区块组”算,不按子项算:`KPI 卡片: 学生总数, 课程总数, 出勤率, 平均分` 只能算 1 个状态摘要区块,`快捷入口: 录入学生/登记成绩/记录考勤/管理课程` 只能算 1 个动作区块;不能用重复 KPI 卡、重复快捷入口或大空白卡凑数量。
@@ -72,7 +74,7 @@ Fast、Plan 和单页设计使用相同的 UI 设计规则、主题变量和质
72
74
  11. **按主题保持形状、密度与呼吸感**:`design.md` 正文写清圆角、密度与呼吸节奏的具体消费方式和必要数值,优先采用选中主题的容器/控件形状与内距、组间距、列表行高。通用业务页参考值只补主题未定义项,不能用固定大圆角、padding 或 gap 覆盖主题。呼吸感来自对齐、分组、层级和节奏,不来自超宽空 KPI 框或空白卡。
73
75
  12. **背景与内容层次清晰**:正文说明主题如何用色差、细边界、共容器、留白或材质区分内容。同色画布与面板可通过明确边界和分组成立;渐变、玻璃、阴影按主题规则启用,不强制添加。
74
76
  13. **模板与自由创意并列**:始终支持[自由创意](references/application-style-library.md),根据业务独立推演,不要求从模板选择。使用模板时,先按业务任务、信息拓扑选择风格,再按用户确认的色彩氛围协调页面、卡片、导航、填充、边界和交互。布局、圆角与材质可保留,模板固定灰阶和品牌色面积限制不能覆盖用户要求。“自然绿意”等整体风格不能缩减成只有按钮和 logo 变绿;明确只改强调色或忠实中性参考时才保持原画布。文字保留可读的中性层级,状态保留独立语义。
75
- 14. **应用主题统一**:`app-theme.css` 是应用全局样式,作用于应用框架、表单、详情页和自定义页面等。`YidaCodeCanvas` 页面只在 `YidaComp` 内消费 `--color-brand1-*`、`--color-group` 和 `--pod-*`;严禁页面代码修改或向上层注入主题变量。应用包含表单或详情页时,读取 [表单风格规则](references/native-form-styles.md),将组件布局和只读详情样式写入 `design.md`;视觉值写入应用主题 CSS,结构写入表单配置。
77
+ 14. **应用主题统一**:按 [整体主题规则](references/application-theme-consistency.md#导航与应用框架) 一起设计导航、应用框架、提交/编辑表单、记录详情和自定义页面。`app-theme.css` 保存完整主题变量与消费样式。`YidaCodeCanvas` 页面只在 `YidaComp` 内消费 `--color-brand1-*`、`--color-group` 和 `--pod-*`;严禁页面代码修改或向上层注入主题变量。应用包含表单或详情页时,读取 [表单风格规则](references/native-form-styles.md),将组件布局和只读详情样式写入 `design.md`;视觉值写入应用主题 CSS,结构写入表单配置。
76
78
  15. **参考转成可执行选择**:参考 Dribbble / 优秀案例时,落到主色、背景素材、首屏构图、信息密度、动线、区块数量和反默认点。
77
79
  16. **页面文案和图标使用专业表达**:渲染文案使用纯文本;图标只使用 `lucide-react` 或 `@ant-design/icons` 的具体组件,默认选择 `lucide-react`,并在 `design.md` 的 `iconSystem` 中写清业务动作、状态、导航和空态到图标组件的映射。emoji 不能改成 CSS 形状、字母占位、Unicode 符号或临时 SVG;如果需要图标,必须映射到上述两类库的具体组件。
78
80
  17. **实现交接明确**:设计产物只定义页面结构、视觉系统和验收标准;常规业务图表使用 `yida-rechart`;ECharts 例外只用于用户明确要求复杂 ECharts option 或维护旧图表。