@microi.net/cli 5.8.5 → 5.8.6

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 (211) hide show
  1. package/.codebuddy-plugin/marketplace.json +2 -2
  2. package/.codebuddy-plugin/plugin.json +1 -1
  3. package/.codex-plugin/plugin.json +1 -1
  4. package/.mcp.json +1 -1
  5. package/.workbuddy-plugin/marketplace.json +2 -2
  6. package/.workbuddy-plugin/plugin.json +1 -1
  7. package/LICENSE +21 -21
  8. package/README.md +71 -71
  9. package/assets/build-meta.json +6 -6
  10. package/assets/feature-matrix.json +138 -138
  11. package/assets/logo.svg +4 -4
  12. package/cordis.patch.yml +1 -1
  13. package/package.json +1 -1
  14. package/scripts/codex-marketplace.json +20 -20
  15. package/scripts/mcp-codex-stdio-adapter.js +189 -189
  16. package/scripts/mcp-trae-windows-launcher.cmd +21 -21
  17. package/scripts/microi-cli-mcp.js +7 -7
  18. package/scripts/microi-cli.js +66 -65
  19. package/scripts/microi-codex-broker.js +450 -450
  20. package/scripts/microi-codex-router.js +618 -618
  21. package/scripts/microi-skills.meta.json +384 -384
  22. package/skills/.microi-skills-version.json +2 -2
  23. package/skills/.progressive-disclosure-manifest.json +3566 -3566
  24. package/skills/README.md +287 -287
  25. package/skills/ai-engine/SKILL.md +269 -265
  26. package/skills/ai-engine/agents/openai.yaml +4 -4
  27. package/skills/ai-engine/references/ai-employees.md +48 -48
  28. package/skills/ai-engine/references/self-hosted-digital-human.md +59 -59
  29. package/skills/ai-platform-governance/SKILL.md +177 -177
  30. package/skills/ai-platform-governance/references/progressive-01-/345/212/237/350/203/275/345/274/200/345/205/263.md +190 -190
  31. package/skills/app-store/SKILL.md +525 -525
  32. package/skills/app-store/agents/openai.yaml +4 -4
  33. package/skills/business-blueprint/SKILL.md +193 -193
  34. package/skills/datasource-engine/SKILL.md +93 -93
  35. package/skills/datasource-engine/agents/openai.yaml +4 -4
  36. package/skills/dos-orm/SKILL.md +97 -97
  37. package/skills/dos-orm/references/api-reference.md +229 -229
  38. package/skills/email-engine/SKILL.md +81 -81
  39. package/skills/email-engine/references/v8-email.md +34 -34
  40. package/skills/job-engine/SKILL.md +176 -176
  41. package/skills/job-engine/agents/openai.yaml +4 -4
  42. package/skills/message-notification/SKILL.md +156 -156
  43. package/skills/message-notification/agents/openai.yaml +5 -5
  44. package/skills/message-notification/references/contracts.md +102 -102
  45. package/skills/microi/SKILL.md +14 -14
  46. package/skills/microi-ai-app-auth.js +652 -652
  47. package/skills/microi-ai-application/SKILL.md +115 -115
  48. package/skills/microi-ai-application/agents/openai.yaml +4 -4
  49. package/skills/microi-ai-application/references/frontend-baseline.md +164 -164
  50. package/skills/microi-client-frontend/SKILL.md +244 -244
  51. package/skills/microi-client-frontend/references/progressive-01-3-/345/212/250/346/200/201/346/214/211/351/222/256/347/263/273/347/273/237.md +144 -144
  52. package/skills/microi-client-frontend/references/progressive-02-8-/350/277/220/350/241/214/346/227/266/351/253/230/351/242/221/345/235/221/345/244/215/347/233/230.md +196 -196
  53. package/skills/microi-client-frontend/references/progressive-03-vue3-/345/211/215/347/253/257/345/276/256/346/234/215/345/212/241/345/256/277/344/270/273/350/247/204/345/210/231.md +167 -167
  54. package/skills/microi-codex/SKILL.md +102 -102
  55. package/skills/microi-codex-installer/SKILL.md +231 -231
  56. package/skills/microi-codex-installer/agents/openai.yaml +7 -7
  57. package/skills/microi-datasource-mapping/SKILL.md +122 -122
  58. package/skills/microi-db-schema/SKILL.md +175 -175
  59. package/skills/microi-db-schema/agents/openai.yaml +4 -4
  60. package/skills/microi-db-schema/references/core-tables.md +695 -695
  61. package/skills/microi-db-schema/references/form-component-options.md +256 -256
  62. package/skills/microi-db-schema/references/schema-overview.md +202 -202
  63. package/skills/microi-db-schema/references/schema.md +646 -646
  64. package/skills/microi-db-schema/references/table-catalog.md +1599 -1599
  65. package/skills/microi-deployment/SKILL.md +221 -221
  66. package/skills/microi-deployment/references/deployment-matrix.md +109 -109
  67. package/skills/microi-docs-coverage/SKILL.md +133 -133
  68. package/skills/microi-docs-coverage/references/capability-map.md +91 -91
  69. package/skills/microi-docs-coverage/scripts/audit-doc-skill-coverage.mjs +894 -894
  70. package/skills/microi-form-engine/SKILL.md +333 -333
  71. package/skills/microi-form-engine/references/component-catalog.md +218 -218
  72. package/skills/microi-form-engine/references/data-source-events.md +124 -124
  73. package/skills/microi-form-layout/SKILL.md +205 -205
  74. package/skills/microi-form-layout/references/progressive-01-3-/344/270/211/347/247/215/345/210/206/347/273/204/347/232/204/345/255/230/345/202/250/344/270/216/351/205/215/347/275/256.md +235 -235
  75. package/skills/microi-frontend-sdk/SKILL.md +194 -194
  76. package/skills/microi-frontend-sdk/references/progressive-01-token-/345/275/223/345/211/215/347/231/273/345/275/225/347/224/250/346/210/267/344/270/216/345/275/223/345/211/215/347/273/210/347/253/257/347/231/273/345/275/225/345/215/217/350/256/256.md +176 -176
  77. package/skills/microi-left-right-layout/SKILL.md +141 -141
  78. package/skills/microi-microservice/SKILL.md +326 -324
  79. package/skills/microi-microservice/references/runtime-delivery.md +278 -278
  80. package/skills/microi-mobile-app-quality/SKILL.md +185 -185
  81. package/skills/microi-mobile-app-quality/references/progressive-01-4-/351/207/215/350/246/201/346/214/211/351/222/256/345/277/205/351/241/273/345/270/246/345/233/276/346/240/207.md +213 -213
  82. package/skills/microi-mobile-app-quality/references/progressive-02-9-/344/270/273/351/242/230/345/210/207/346/215/242/345/277/205/351/241/273/347/234/237/345/256/236/344/270/224/345/205/250/345/261/200/347/224/237/346/225/210.md +128 -128
  83. package/skills/microi-solution-quotation/SKILL.md +78 -78
  84. package/skills/microi-solution-quotation/agents/openai.yaml +4 -4
  85. package/skills/microi-solution-quotation/scripts/build_solution_quote.py +296 -296
  86. package/skills/microi-sso/SKILL.md +92 -92
  87. package/skills/microi-sso/references/acceptance.md +49 -49
  88. package/skills/microi-sso/references/configuration-and-security.md +53 -53
  89. package/skills/microi-sso/references/inbound.md +53 -53
  90. package/skills/microi-sso/references/outbound.md +39 -39
  91. package/skills/microi-system-delivery/SKILL.md +137 -137
  92. package/skills/microi-system-delivery/references/progressive-01-/346/240/207/345/207/206/345/267/245/344/275/234/346/265/201.md +193 -193
  93. package/skills/microi-system-delivery/references/progressive-02-/350/207/252/345/212/250/345/214/226/346/265/213/350/257/225/345/277/205/351/241/273/350/246/206/347/233/226/347/232/204/345/235/221.md +217 -217
  94. package/skills/microi-ui/SKILL.md +192 -192
  95. package/skills/microi-ui/references/progressive-01-/347/247/273/345/212/250/347/253/257/345/234/272/346/231/257/350/223/235/345/233/276.md +183 -183
  96. package/skills/microi-uniapp-frontend/SKILL.md +193 -193
  97. package/skills/microi-uniapp-frontend/references/progressive-01-/347/247/273/345/212/250/347/253/257/345/210/206/347/261/273-/345/217/214/346/240/217/345/210/227/350/241/250/347/213/254/347/253/213/346/273/232/345/212/250.md +225 -225
  98. package/skills/microi-uniapp-frontend/references/progressive-02-/345/205/263/351/224/256/344/270/232/345/212/241/350/265/204/344/272/247/344/270/215/345/276/227/351/273/230/350/256/244/351/200/211/344/270/255.md +154 -154
  99. package/skills/microi.v8.js +1921 -1921
  100. package/skills/module-engine/SKILL.md +255 -255
  101. package/skills/module-engine/references/module-config.md +204 -204
  102. package/skills/ocr-engine/SKILL.md +113 -113
  103. package/skills/ocr-engine/agents/openai.yaml +4 -4
  104. package/skills/page-engine/SKILL.md +206 -206
  105. package/skills/page-engine/examples/compact-dashboard.json +1444 -1444
  106. package/skills/page-engine/references/progressive-01-/346/211/200/346/234/211/347/273/204/344/273/266/347/261/273/345/236/213.md +234 -234
  107. package/skills/page-engine/references/progressive-02-/347/211/210/346/234/254/345/216/206/345/217/262-/345/271/266/345/217/221/344/277/235/345/255/230/344/270/216/345/233/236/346/273/232.md +60 -60
  108. package/skills/performance-testing/SKILL.md +221 -221
  109. package/skills/playwright-e2e/SKILL.md +196 -196
  110. package/skills/playwright-e2e/references/progressive-01-/345/205/250/350/207/252/345/212/250/347/231/273/345/275/225-/345/205/215/351/252/214/350/257/201/347/240/201-/344/275/206/344/270/215/345/205/215/345/257/206/347/240/201-/345/277/205/350/257/273.md +173 -173
  111. package/skills/playwright-e2e/references/progressive-02-/346/226/207/345/255/227/345/257/271/346/257/224/345/272/246/344/270/216/345/217/257/350/257/273/346/200/247/350/207/252/345/212/250/345/214/226/346/243/200/346/237/245-/345/277/205/345/201/232.md +183 -183
  112. package/skills/playwright-e2e/references/progressive-03-microi-helper-/346/250/241/346/235/277.md +221 -221
  113. package/skills/playwright-e2e/references/progressive-04-ci-/345/273/272/350/256/256.md +115 -115
  114. package/skills/print-engine/SKILL.md +259 -259
  115. package/skills/production-readonly-audit/SKILL.md +41 -41
  116. package/skills/report-engine/SKILL.md +71 -71
  117. package/skills/report-engine/agents/openai.yaml +4 -4
  118. package/skills/scripts/optimize-progressive-disclosure.mjs +204 -204
  119. package/skills/scripts/refresh-progressive-disclosure.mjs +64 -64
  120. package/skills/scripts/sync-embedded-skills.mjs +46 -46
  121. package/skills/scripts/validate-progressive-disclosure.mjs +57 -57
  122. package/skills/search-engine/SKILL.md +75 -75
  123. package/skills/search-engine/agents/openai.yaml +4 -4
  124. package/skills/spider-engine/SKILL.md +190 -190
  125. package/skills/system-observability/SKILL.md +248 -248
  126. package/skills/system-observability/references/memory-incident-triage.md +77 -77
  127. package/skills/translate-engine/SKILL.md +140 -140
  128. package/skills/translate-engine/agents/openai.yaml +4 -4
  129. package/skills/ui-design/SKILL.md +223 -223
  130. package/skills/ui-design/assets/pattern-showcase/app.js +54 -54
  131. package/skills/ui-design/assets/pattern-showcase/index.html +163 -163
  132. package/skills/ui-design/assets/pattern-showcase/styles.css +311 -311
  133. package/skills/ui-design/assets/templates/MCI-DESIGN.md +206 -206
  134. package/skills/ui-design/references/design-pattern-library.md +184 -184
  135. package/skills/ui-design/references/mci-design-contract.md +163 -163
  136. package/skills/ui-design/references/motion-and-media.md +78 -78
  137. package/skills/ui-design/references/product-flow-recipes.md +94 -94
  138. package/skills/ui-design/references/progressive-01-/351/242/234/350/211/262/344/275/223/347/263/273-css-variables-/346/224/257/346/214/201/344/270/273/351/242/230/345/210/207/346/215/242.md +218 -218
  139. package/skills/ui-design/references/progressive-02-/345/255/227/344/275/223.md +164 -164
  140. package/skills/ui-design/references/progressive-03-/345/212/250/346/225/210/350/247/204/350/214/203-/344/270/260/345/257/214/344/275/206/344/270/215/345/215/241.md +235 -235
  141. package/skills/ui-design/references/progressive-04-/347/273/204/344/273/266/351/243/216/346/240/274/351/200/237/346/237/245.md +152 -152
  142. package/skills/ui-design/references/progressive-05-/347/247/273/345/212/250/347/253/257/344/270/223/347/224/250/350/247/204/350/214/203.md +238 -238
  143. package/skills/ui-design/references/progressive-06-/344/270/273/351/242/230/345/210/207/346/215/242/345/256/236/347/216/260.md +194 -194
  144. package/skills/ui-design/references/progressive-07-/351/200/237/346/237/245-/344/273/216/345/244/264/346/220/255/345/273/272/344/270/200/344/270/252/347/247/273/345/212/250/347/253/257/351/241/265/351/235/242.md +207 -207
  145. package/skills/ui-design/references/progressive-08-/350/241/250/345/215/225/345/210/206/347/273/204/350/247/204/350/214/203-tabs-vs-collapsegroup-/345/274/272/345/210/266.md +142 -142
  146. package/skills/uniapp-mall-assets/SKILL.md +176 -176
  147. package/skills/unity-integration/SKILL.md +171 -171
  148. package/skills/unity-integration/agents/openai.yaml +4 -4
  149. package/skills/unity-integration/references/ai-app-delivery.md +119 -119
  150. package/skills/unity-integration/references/sdk-api.md +82 -82
  151. package/skills/unity-integration/references/toolbox-migration.md +66 -66
  152. package/skills/unity-integration/references/webgl-hosting.md +57 -57
  153. package/skills/v8-api-config/SKILL.md +388 -388
  154. package/skills/v8-cache-pattern/SKILL.md +312 -312
  155. package/skills/v8-crud-api/SKILL.md +178 -178
  156. package/skills/v8-crud-api/references/progressive-01-/346/237/245/350/257/242/345/210/227/350/241/250-/345/210/206/351/241/265.md +226 -226
  157. package/skills/v8-crud-api/references/progressive-02-where-/346/235/241/344/273/266/350/257/255/346/263/225/351/200/237/346/237/245.md +49 -49
  158. package/skills/v8-debugging/SKILL.md +284 -284
  159. package/skills/v8-explorer-tree/SKILL.md +228 -228
  160. package/skills/v8-export-import/SKILL.md +219 -219
  161. package/skills/v8-export-import/references/progressive-01-excellayout-/351/253/230/347/272/247/350/207/252/347/224/261/345/270/203/345/261/200.md +211 -211
  162. package/skills/v8-export-import/references/progressive-02-powerpoint-/345/257/274/345/207/272.md +202 -202
  163. package/skills/v8-export-import/references/progressive-03-/345/256/211/345/205/250-/346/200/247/350/203/275/346/263/250/346/204/217.md +42 -42
  164. package/skills/v8-file-upload/SKILL.md +284 -284
  165. package/skills/v8-file-upload/references/progressive-01-/345/205/254/346/234/211/346/241/266-vs-/347/247/201/346/234/211/346/241/266.md +263 -263
  166. package/skills/v8-file-upload/references/progressive-02-office-/346/226/207/344/273/266/345/234/250/347/272/277/347/274/226/350/276/221/347/211/210/346/234/254/345/217/267/350/247/204/345/210/231.md +161 -161
  167. package/skills/v8-formengine-http/SKILL.md +238 -238
  168. package/skills/v8-frontend-events/SKILL.md +180 -180
  169. package/skills/v8-frontend-events/references/bluetooth-print-api.md +135 -135
  170. package/skills/v8-frontend-events/references/bluetooth-print.md +258 -258
  171. package/skills/v8-frontend-events/references/progressive-01-/345/210/227/350/241/250/344/272/213/344/273/266.md +219 -219
  172. package/skills/v8-http-integration/SKILL.md +182 -182
  173. package/skills/v8-http-integration/references/progressive-01-get-/350/257/267/346/261/202.md +220 -220
  174. package/skills/v8-http-integration/references/progressive-02-/351/224/231/350/257/257/345/244/204/347/220/206/346/250/241/345/274/217.md +44 -44
  175. package/skills/v8-image-processing/SKILL.md +190 -190
  176. package/skills/v8-image-processing/agents/openai.yaml +4 -4
  177. package/skills/v8-image-processing/references/api-reference.md +623 -623
  178. package/skills/v8-menu-buttons/SKILL.md +186 -186
  179. package/skills/v8-menu-buttons/references/progressive-01-2-/346/214/211/351/222/256/345/257/271/350/261/241-schema.md +222 -222
  180. package/skills/v8-menu-buttons/references/progressive-02-8-/346/250/241/345/274/217-f-/345/220/216/345/217/260/344/273/273/345/212/241/346/214/211/351/222/256-/351/225/277/344/273/273/345/212/241.md +228 -228
  181. package/skills/v8-menu-buttons/references/progressive-03-10-/345/217/215/346/250/241/345/274/217-/351/201/277/345/205/215.md +104 -104
  182. package/skills/v8-mongodb/SKILL.md +200 -200
  183. package/skills/v8-mq-mqtt/SKILL.md +176 -176
  184. package/skills/v8-mq-mqtt/references/mqtt-production.md +342 -342
  185. package/skills/v8-mq-mqtt/references/progressive-01-v8-mqtt-iot-/347/211/251/350/201/224/347/275/221.md +181 -181
  186. package/skills/v8-mq-mqtt/scripts/check-mqtt-skill-coverage.mjs +203 -203
  187. package/skills/v8-saas-multi-tenant/SKILL.md +305 -305
  188. package/skills/v8-security/SKILL.md +210 -210
  189. package/skills/v8-security/references/progressive-01-2-/346/235/203/351/231/220/346/240/241/351/252/214.md +200 -200
  190. package/skills/v8-security/references/progressive-02-7-/346/227/245/345/277/227/350/256/260/345/275/225.md +160 -160
  191. package/skills/v8-sql-query/SKILL.md +302 -302
  192. package/skills/v8-table-event/SKILL.md +176 -176
  193. package/skills/v8-table-event/references/progressive-01-informv8-js-/350/241/250/345/215/225/346/211/223/345/274/200/344/272/213/344/273/266.md +216 -216
  194. package/skills/v8-table-event/references/progressive-02-/345/211/215/347/253/257/344/272/213/344/273/266/345/220/215-v8-eventname-/345/217/257/350/203/275/347/232/204/345/200/274.md +46 -46
  195. package/skills/v8-tcp-integration/SKILL.md +147 -147
  196. package/skills/v8-tcp-integration/agents/openai.yaml +4 -4
  197. package/skills/v8-template-engine/SKILL.md +167 -167
  198. package/skills/v8-utilities/SKILL.md +104 -104
  199. package/skills/v8-utilities/references/client-api-index.md +143 -143
  200. package/skills/v8-utilities/references/platform-http-routes.md +83 -83
  201. package/skills/v8-utilities/references/server-api-index.md +188 -188
  202. package/skills/v8-workflow/SKILL.md +252 -252
  203. package/skills/v8-workflow/references/progressive-01-/350/212/202/347/202/271/345/274/200/345/247/213-v8-/344/272/213/344/273/266.md +180 -180
  204. package/skills/v8-workflow/references/workflow-configuration.md +49 -49
  205. package/skills/vision-engine/SKILL.md +160 -160
  206. package/skills/vision-engine/agents/openai.yaml +4 -4
  207. package/skills/vision-engine/references/architecture-and-acceptance.md +194 -194
  208. package/skills/workspace-conventions/SKILL.md +273 -273
  209. package/skills/workspace-conventions/references/progressive-01-/347/211/210/346/234/254/346/233/264/346/226/260/346/227/245/345/277/227/344/277/235/346/212/244/350/247/204/345/210/231-/345/274/272/345/210/266.md +209 -209
  210. package/skills/workspace-conventions/references/progressive-02-microi-net-api-/346/234/254/345/234/260/345/220/257/345/212/250/347/272/246/345/256/232.md +217 -217
  211. package/skills/workspace-conventions/references/progressive-03-cli-/344/270/216-ide-/346/217/222/344/273/266/351/224/231/347/211/210/345/205/261/345/255/230/347/272/246/345/256/232.md +27 -27
@@ -1,333 +1,333 @@
1
- ---
2
- name: microi-form-engine
3
- description: Microi 表单引擎设计与控件配置指南。用于创建或修改 diy_table、diy_field、表单组件、字段属性、选项/SQL/数据源引擎数据源、子表、关联表单、定制组件、表单布局和字段事件。
4
- ---
5
-
6
- > **Microi吾码基础规范(强制):** 任何 AI 模型与宿主每次新建或接续吾码任务,先完整读取 `../workspace-conventions/SKILL.md`,必须执行版本播报、`@microi.net/cli` 后台自动升级、Skills/MCP 同步和进度播报。安装与诊断读取 `../microi-codex-installer/SKILL.md`;更新失败延后重试,不阻断当前工作。
7
-
8
- # Microi 表单引擎设计
9
-
10
- ## 表单设计器生成表单代码
11
-
12
- 保留现有 `Diy` 动态渲染;需要每表独立页面时,在保存设计后使用【生成表单代码】。生成器产生 `src/pages/Form_表名.vue`,源码归当前租户 `microi-generated-forms` 微服务私有项目,AI 应用工作台可继续编辑。Vite 构建并发布运行产物后,模块菜单用 `CodeForm`,同时绑定原 `DiyTableId` 与对应微服务路由。生成页经前端 V8 SDK 传 `_SysMenuId` 调用 FormEngine,权限及后端事件继续由服务端校验。
13
-
14
- 基础控件生成独立表单;复杂控件、动态数据源、前端 V8 事件/模板和缺少选项的多选生成平台原表单入口,通过宿主 `openForm` 保留原控件与事件,监听 `micro-app:form-saved` 刷新列表。两种模式读取服务端 `DataAppend.FieldAccess`,隐藏字段不渲染、只读字段不写入;不要只依赖前端身份推断。
15
-
16
- 人工修改过的目标源码仍需停止覆盖并显示原因。设计器再次变更后重新生成草稿,在源码工作台审阅和合并,再构建发布。源码保存不等于微服务已构建、菜单已切换或目标租户已安装。必须验证实际源码保存回读、构建后页面及普通账号写入,不能只验证预览字符串。
17
-
18
- 表单引擎同时驱动数据模型、表单、列表、模块、接口配置和工作流配置。处理“新增字段”
19
- 不能只做物理 `ALTER TABLE`:必须让 `diy_table`、`diy_field`、物理列、组件
20
- Config/Data、菜单查询列与缓存保持一致。
21
-
22
- 平台创建 DIY 表时会自动加入 `DiyCommon.FixedDiyField` 定义的 Id、创建/更新时间、
23
- 创建人、租户等固定字段。业务 Manifest 不重复声明这些字段;读取实时 Schema 或离线快照时也不能
24
- 因为 `_Fields` 只列出可配置字段,就误判物理表缺少固定字段。
25
-
26
- ## 必读参考
27
-
28
- - 控件完整目录、推荐物理类型和选择规则:`references/component-catalog.md`
29
- - 数据源、字段属性、事件与定制组件:`references/data-source-events.md`
30
- - 表单分组与宽度:`../microi-form-layout/SKILL.md`
31
- - 后端表单事件:`../v8-table-event/SKILL.md`
32
- - 前端字段事件:`../v8-frontend-events/SKILL.md`
33
-
34
- ## 标准工作流
35
-
36
- ### 物理字段允许为空(强制)
37
-
38
- 除作为主键的 `Id` 外,通过 MCP、表单设计器、FormEngine、V8 或应用包新增、修改的普通字段,数据库列一律允许 `NULL`。`NotEmpty` 等业务必填要求只作用于表单/服务端校验,不能生成 `NOT NULL`。默认值和是否允许为空是两项独立属性;兼容旧列时只放宽可空约束,保留类型、有效默认值、字符集、排序规则、注释、索引和历史数据,不以补零/空串替代结构修复。
39
-
40
- MySQL 的 `ALTER COLUMN DROP DEFAULT` 会让可空列也在省略字段时报 1364;移除普通标量列的旧默认值应使用 `SET DEFAULT NULL`。`IS_NULLABLE=YES` 和 `COLUMN_DEFAULT=NULL` 不足以证明可省略字段,需要通过 `SELECT DEFAULT(列) FROM 表 LIMIT 0` 验证。TEXT/BLOB 的缺失默认标志应保留完整列定义执行 `MODIFY COLUMN` 修复,不能对它们使用 `ALTER COLUMN SET DEFAULT NULL`。
41
-
42
- 1. 先通过 `microi_get_db_schema` 读取目标租户的真实表、字段和菜单。
43
- 2. 从当前源码
44
- `Microi.Client/src/views/form-engine/diy-field-component/diy-component-list.json`
45
- 核对控件名;官网页面可能含历史控件。
46
- 3. 新表用 `microi_create_table`;字段用 `microi_add_field`,不得直接写
47
- `diy_field` 或执行临时 DDL。
48
- 4. 选项控件同时设置 `data/config`;关联控件明确保存字段和显示字段。
49
- 5. 字段多时设置 `diy_table.Tabs` 与字段 `Tab`;只有整行控件设置
50
- `FormWidth=24`,普通字段省略。`CollapseGroup` 属于整行控件,必须显式保存
51
- `FormWidth=24`,且 `Config.CollapseGroup.ShowFieldCount` 默认补为 `true`。
52
- 6. 绑定菜单后补齐/允许平台推断列表列、搜索列、隐藏列、排序列、移动端列和默认排序。
53
- 7. 回读 `diy_field`、刷新 schema 缓存,再在真实新增/编辑/查看表单中验收。
54
-
55
- ## 原生查询主库策略
56
-
57
- - 对不能接受副本延迟的权限关系等表,显式配置 `diy_table.ReadPrimary=1`;普通表保持
58
- `NULL/0`。只能从可信表元数据选择连接,禁止让查询请求的 `ReadPrimary`、`TableModel`
59
- 或 `DataBaseId` 控制主库/副本。此配置不扩大菜单、表、记录或字段权限。
60
- - 原生 Get、List、Count/CountBatch、SUM 批量与回退、Tree 子计数和 Export 必须共用
61
- 目标表所属数据库的 writer 选择;扩展库不得误回租户基础库。主库不可用或配置非法必须
62
- 失败,不能以副本或0计数伪装成功。直接调用 `V8.DbRead` 的语义不变。
63
- - V8 的 JavaScript Number 经 .NET 互操作可能成为浮点类型;配置解析接受数值精确等于
64
- `0/1` 的表示,仍拒绝小数、NaN、Infinity、布尔值及其它非法值,禁止通过截断或舍入放宽值域。
65
- - 显式 `DbTrans` 保留,不为主库策略跳出事务;父事务旧 RR 快照仍可能看见旧授权关系,
66
- 不能声称仅开启本字段就实现与撤权原子串行。需要实时授权时采用独立受控主库身份读取。
67
- - 标准 `microi_create_table`、`microi_update_table` 和 Manifest `tables[].readPrimary`
68
- 支持 `null/0/1`,省略保持已有配置,显式 `null` 清回缺省。先升级后端并安装正式表单
69
- 引擎字段,再配置;不通过定制 `.NET` 启动迁移或原始 SQL 补字段。
70
- - 元数据冷回源使用主库,写后清表缓存并回读。验收分别证明字段定义、可空物理列、配置值、
71
- 普通身份真实 Rows/Count/SUM/Tree/Export 与撤权边界;离线会话选择测试不能冒充复制延迟
72
- 或七种数据库实机测试。所有新普通表字段保持可空,不把已有表批量设为主库。
73
-
74
- ## 上传字段配置(AI 生成时强制)
75
-
76
- - 需要逐附件角色权限时,在 `Config.FileUpload` 设置 `EnableRolePermission:true` 和 `Limit:true`;
77
- `HideUnauthorizedFiles`(隐藏无权行)、`ShowUnauthorizedFileName`(显示无权名称)、
78
- `DisableRoleInheritance`(关闭角色继承)均为 boolean,默认 false。未启用的旧字段保持兼容。
79
- - 每个文件的 `VisibleRoleIds` 是真实角色 Id 数组;空数组跟随表单权限。标签名称及 `_FileAccess`
80
- 由后端投影,不能作为客户端授权事实。默认真实持有角色的 Level 严格更高即可继承,
81
- 同级不同角色不继承;多选任一角色命中即可,仍须有菜单/表单/记录访问与编辑权限。
82
- - `Config.FileUpload.ConfigurableRoleIds` 是“可配置角色列表”,使用真实角色 Id 数组,默认 `[]` 表示全部。
83
- 非空时,角色目录和后端新增附件授权都只允许该范围;缩小范围保留旧附件已有角色,可移除但不可再添加。
84
- 此范围只限制可选授权角色,不改变 Level 继承规则。先用 `microi_list_roles` 读取当前租户角色,禁止复制其它租户的 Id。
85
- - 无权限附件默认只显示锁定占位、不显示名称;开启隐藏只改变展示,保存时服务端保留原附件,
86
- 篡改无权元数据、复制他人路径及删除含无权附件的整条记录均应失败。条件批量写附件/删除应改为逐条。
87
- - 新附件必须通过当前记录/字段的私有上传取得短期 `_UploadProof`,保存后由服务端移除。
88
- 不能手工拼接他人路径;历史公有文件设置角色前重新私有上传。先部署前后端,再启用字段配置。
89
- - MCP 可复用 `microi_get_field_list`、`microi_update_field`、`microi_refresh_schema_cache`、
90
- `microi_list_roles` 和 `microi_save_role`,先完整回读并合并 Config,禁止覆盖原上传大小、数量和 V8。
91
- 新版 `microi_build_field_config` 支持 `sourceType:"FileUpload"`,自动强制私有存储并校验布尔值;
92
- 旧 MCP 直接传同等 Config JSON 即可,无需另建业务接口。回归必须使用高/中/低角色和直接 HTTP 篡改,
93
- 同时覆盖名称开关、隐藏开关、继承开关、单文件、列表、私有/版本预览和保存后重开。
94
-
95
- - 图片使用 `Config.ImgUpload`,至少明确 `Limit`、`Multiple`、`MaxCount`、`Preview`、
96
- `MaxSize` 和 `Crop`;文件使用 `Config.FileUpload`,至少明确 `Limit`、`Multiple`、
97
- `MaxCount`、`MaxSize`。完整键和值域读取 `references/component-catalog.md`。
98
- - `ImgUpload.Preview` 未配置时默认开启压缩;普通业务图片优先保持开启。裁剪前的原图无论
99
- 展示图配置为公有或私有、是否压缩,都必须保存在 HDFS 私有桶,业务字段不得保存原图路径。
100
- - `ImgUpload.Crop.Enabled` 只控制表单打开时是否默认选中裁剪。运行时的裁剪开关、存储范围、
101
- 单/多图数量、压缩状态和最大体积统一显示在紧凑上传面板中;不得把 `Enabled=false` 误解为
102
- 禁止用户裁剪。`Mode` 只允许 `free/fixed/select`。
103
- - 图片和文件的拖放区都使用同一紧凑配置面板。`Multiple=true` 时必须设置业务合理的
104
- `MaxCount`;`MaxSize` 单位为 MB,字段限制只能收紧租户/平台上限,不能放大。
105
- - 富文本使用 `Config.RichText`:必须明确 `Limit`,并按需配置
106
- `Image.Enabled/MaxSize/MaxCount/Preview/CompressMaxSize/CompressMaxWidth`、
107
- `Video.Enabled/MaxSize/MaxCount`、`File.Enabled/MaxSize/MaxCount/Accept`。公开公告、商品详情
108
- 等匿名正文显式使用 `Limit=false`;内部正文使用 `true`。旧字段缺失配置时安全默认为私有桶,
109
- 图片默认压缩到约 500 KB、最长边 1920 px。
110
- - 私有富文本只能持久化稳定对象标识,禁止把 HDFS 签名 URL、审计代理 Ticket 或 DiyToken 写入
111
- HTML。每次查看/编辑按当前菜单、表、记录和字段权限换取新短效地址;外部匿名页面没有此权限
112
- 上下文,因此不能把私有 RichText 当作公开正文。普通用户通过当前表单新增/编辑授权后,后端
113
- 必须回读 `diy_field.Config.RichText.Limit` 决定公私桶;只改请求 `Limit=false` 不能绕过字段配置。
114
- - 图片、文件和富文本上传必须携带 `FormEngineKey + FieldId + SysMenuId`,编辑记录再带
115
- `FormDataId`,TableChild 再带父子授权上下文。后端不得按用户等级统一覆盖字段的“禁止匿名访问”;
116
- 无法回查字段与动作权限的普通上传才安全降级为私有桶。
117
-
118
- 新建表/模块时,除非用户显式指定或表单达到极重阈值(约 36+ 业务字段、2+ 子表或同等
119
- 重型控件密度),默认保存 `diy_table.FormOpenType=Dialog` 与 `FormOpenWidth=80%`。
120
- Drawer 只服务超长复杂表单,不能作为所有 CRUD 模块的模板默认值。
121
- 若设计器显示而运行态不显示,先检查 `InFormV8`/字段 V8 是否调用
122
- `V8.FieldSet(..., 'Visible', false)`、`hideField` 或传入 `HideFields`,再判断前端源码。
123
-
124
- ## 表单 Banner(所有新业务表必做)
125
-
126
- 标准表单 Banner 默认显示,以当前主题色约 50% 混合强度叠加深蓝灰渐变,并适配浅色、
127
- 深色与移动端。视觉应有层次但保持清爽,标题始终维持安全对比度;统计卡片使用半透明背景
128
- 和柔和阴影分层,避免堆叠边框。它属于表单语义,配置
129
- 必须写入 `diy_table` 的 `FormBannerEnabled`、`FormBannerTitleField`、
130
- `FormBannerSubtitleField`、`FormBannerImageField`、`FormBannerIcon`、
131
- `FormBannerBackgroundField`、`FormBannerTagFields`、`FormBannerMetrics`,禁止写进
132
- `sys_menu`、`DiyConfig` 或项目定制组件。
133
-
134
- - 标题优先业务自动编号/单号/编码,再选名称或标题;副标题优先客户、项目、公司、分类、
135
- 日期等可读字段。
136
- - 左侧图片使用 `ImgUpload`。单图、多图取首图,继续遵循吾码公有/私有文件路径与授权
137
- 规则;图片为空时必须有语义合适的 Font Awesome 图标回退。
138
- - 右侧标签优先 `Select/Radio/Switch/Checkbox/SelectTree/Department` 等选项字段,最多
139
- 选择 3 个有业务意义的状态、类型或等级。显式 `[]` 表示不要自动标签。
140
- - 自动统计最多 3 项,只选择真实金额、合计、数量、成本、余额、评分、比率、进度等具有
141
- 明确业务口径的数值字段;必须排除 Id、排序、启用、状态、版本、分页和本页加载量。
142
- 存在 `TableChild` 时,默认统计必须携带完整父表/父字段/父记录授权上下文,在服务端对全部
143
- 关联子表数据计算行数或业务数值合计,不能只统计当前页。跨表自定义口径使用 `ApiEngineKey +
144
- ValuePath + ParamMap + RefreshSeconds`,相同接口批量返回,禁止 N+1、随机数和固定演示数;
145
- 没有可靠指标时隐藏统计区。显式 `[]` 表示不要自动统计。
146
- - 兼容旧模块 Hero 时仅迁移视觉、`Source=Field` 或显式记录作用域指标;列表总数、分类数量和
147
- 未引用当前 `Form/RecordId` 的全局接口统计不得进入单记录 Banner,缺省时回到当前记录和
148
- 授权 `TableChild` 的语义统计。
149
- - 未配置的存量表由运行时按字段类型智能推断,不能因为物理字段为空而隐藏或展示空壳。
150
- 只有 `FormBannerEnabled=0` 才隐藏。
151
- - 字段绑定须区分省略/`NULL` 与显式空字符串:`titleField/subtitleField/imageField/backgroundField`
152
- 省略或 `NULL` 表示未选择,允许兼容推断;显式 `""` 表示不绑定该字段,不能被推断值或旧别名
153
- 覆盖。取消标题/图片字段后仍保留表单名称/默认图标回退。完整验收须同时使用包含该语义的 MCP
154
- 与平台前端,逐项回读空字符串并验证实际表单;不能只看到写入 `Code=1` 就宣称生效。
155
- - 完整系统 Manifest 使用 `tables[].formBanner`;未提供时 `microi_generate_system` 仍须写入
156
- 类型感知的默认值。逐步创建字段后调用 `microi_configure_form_banner` 并回读验证。
157
- - `microi_generate_system` 的最终验收与 `microi_validate_system` 必须逐表回读 Banner 语义字段;
158
- 写入返回成功、结构验收 `Code=1` 都不能代替已持久化配置,`Data.Passed=false` 仍视为失败。
159
- 旧库缺少 Banner 物理列时先完成平台正式升级,再配置和重新验收,不直接执行 SQL 补列。
160
- - 表单设计器验收必须覆盖有/无图片、有/无统计、子表完整聚合、接口失败回退、浅色、深色、
161
- PC 和窄屏,并检查文字对比度以及不存在技术字段伪统计。
162
-
163
- ## 物理类型底线
164
-
165
- MCP 建模只使用:
166
-
167
- - `varchar(N)`
168
- - `mediumtext` / `longtext`
169
- - `int` / `bigint`
170
- - `decimal(18,N)`
171
-
172
- 日期时间用 `varchar(25)` 保存 `yyyy-MM-dd HH:mm:ss`,组件用 `DateTime`;
173
- 开关用 `int`。不得生成 `datetime/date/timestamp/float/double/boolean/bool/string/text/nvarchar`。
174
- 前端设计器 JSON 中的历史默认类型不能覆盖服务器建模规则。
175
-
176
- ## 选项字段
177
-
178
- `Select`、`MultipleSelect`、`Radio`、`Checkbox` 没有数据源时会显示空选项:
179
-
180
- ```text
181
- 1|启用,0|禁用
182
- ```
183
-
184
- 推荐保存稳定 Key、显示可翻译 Label。修改 `Data/Config/KeyValue` 后必须
185
- `microi_get_field_list` 回读,并执行 `microi_refresh_schema_cache`。
186
-
187
- ## `JoinForm` 与 `TableChild` 硬性判定
188
-
189
- 这两个控件都能在表单内显示另一张表,但数据关系和运行组件完全不同,生成表/字段前
190
- 必须先确定基数,不得因为名称里出现“关联”就默认使用 `JoinForm`。
191
-
192
- | 判断项 | `JoinForm`(关联表单) | `TableChild`(子表) |
193
- |---|---|---|
194
- | 关系 | 当前记录关联**一个**独立目标记录,通常为 N:1 或 1:1 | 一条主表记录拥有 0..N 条明细,标准 1:N |
195
- | 关系存储 | 主表字段保存目标记录 `Id` | **子表物理外键**保存主表 `Id`/指定主键值 |
196
- | 界面 | 嵌入一张 `diy-form`,只展示/编辑一条目标记录 | 嵌入一张 `diy-table`,提供明细列表、分页及行级增删改 |
197
- | 核心配置 | `Config.JoinForm.{TableId,TableName,JoinFieldName,FormMode,Id,_SearchEqual}` | `Config` 根节点的子表/菜单/外键 Id,加 `Config.TableChild` 运行选项 |
198
- | 目标限制 | 目标表必须与当前表不同;相同则组件拒绝渲染 | 子表应是独立明细表,并通过外键限定到当前父记录 |
199
-
200
- ### 决策规则(强制)
201
-
202
- - 需求出现“子表、明细、清单、条目、行项目、多个、若干条、记录列表”,且没有明确说明
203
- “只关联一条已有记录”时,默认建模为 `TableChild`。
204
- - 只要一条父记录可能有 0..N 条目标记录,或需要在父表单内列表、分页、新增、编辑、删除
205
- 多行,就必须用 `TableChild`。
206
- - 只有主表保存一个目标记录 Id、并需要把该独立记录的完整表单嵌入当前表单时,才用
207
- `JoinForm`。选择一条记录但无需嵌入完整表单时,优先 `OpenTable`/`Select`。
208
- - 语义仍不明确时必须在任何 MCP 写入前询问基数;禁止静默退化为 `JoinForm`。
209
- - 禁止把“明细”设计为主表 `XxxId + JoinForm`;禁止让 `JoinForm.TableId/TableName`
210
- 指向当前表;禁止把 1:N 外键放在主表。
211
- - 完整系统 Manifest 中,`JoinForm` / `TableChild` 字段必须声明 `relation.cardinality`;
212
- `microi_plan_system` 与 `microi_generate_system` 会在任何写入前执行本节门禁。直接调用
213
- `microi_add_field` / `microi_update_field` 时,后端仍会校验目标表、主/子外键、隐藏菜单
214
- 和子表索引,不能靠绕过 Manifest 写入未初始化配置。
215
-
216
- 示例:
217
-
218
- - “订单包含多个商品明细” → `order_detail.OrderId` + `TableChild`。
219
- - “访客单包含多件携带物品” → `fk_carry_item.VisitId` + `TableChild`,不能用
220
- `GuestId + JoinForm`,也不能把 `JoinForm` 指回 `fk_carry_item` 自己。
221
- - “工单关联一个客户,并在工单内展开客户档案” → 主表 `CustomerId` + `JoinForm`。
222
-
223
- ### MCP 创建 `TableChild` 的两阶段流程
224
-
225
- 1. 创建主表和独立子表;在子表创建真实外键(如 `VisitId varchar(50)`)。
226
- 2. 在子表为回查创建与物理隔离方式一致的索引:表有 `OsClient` 时通常为
227
- `(OsClient, VisitId)`,独立租户表没有该列时为 `(VisitId)`。索引写入 Manifest
228
- `tables[].indexes`,并以 `microi_get_table_indexes` 回读;物理字段回读失败时停止配置。
229
- 3. 为子表创建绑定其 `diyTableId` 的隐藏 CRUD 菜单:`Display=0`、`AppDisplay=0`、
230
- `HasChild=0`。
231
- 4. 在完整系统 Manifest 的主表字段声明:
232
-
233
- ```json
234
- {
235
- "name": "Items",
236
- "label": "明细",
237
- "component": "TableChild",
238
- "formWidth": 24,
239
- "relation": {
240
- "cardinality": "1:N",
241
- "targetTable": "Biz_OrderItem",
242
- "childForeignKey": "OrderId",
243
- "childModule": "订单明细(隐藏)",
244
- "primaryTableFieldName": "Id"
245
- }
246
- }
247
- ```
248
-
249
- `microi_generate_system` 会先创建全部表与普通字段,再创建隐藏菜单,最后回读并写入
250
- 当前租户真实的 `diy_table.Id` / `sys_menu.Id`。禁止在 Manifest 中编造这些 Id,禁止
251
- 因依赖尚未创建而退化成 `JoinForm`。
252
- 5. `TableChild` 控件字段通常只是表单配置位,关系事实存放在子表外键。至少保存:
253
-
254
- ```json
255
- {
256
- "TableChildTableId": "<子表 diy_table.Id>",
257
- "TableChildSysMenuId": "<子表 sys_menu.Id>",
258
- "TableChildSysMenuName": "携带物品明细",
259
- "TableChildFkFieldName": "VisitId",
260
- "TableChild": {
261
- "PrimaryTableFieldName": "Id",
262
- "Data": [],
263
- "SearchAppend": {},
264
- "ImportAutoFillFk": true,
265
- "FieldRelations": [],
266
- "LastTableId": "",
267
- "LastSysMenuId": "",
268
- "LastSysMenuName": "",
269
- "DisablePagination": false,
270
- "NoneDefaultHeight": false
271
- }
272
- }
273
- ```
274
-
275
- `FieldRelations` 使用紧凑格式 `[["父表字段","子表字段",true?], ...]`。全部关系用于新增回写和导入回填;第三位 `true` 仅标记参与导入反查父表的关系。后端兼容旧三项配置,新版前端会合并去重并在字段下次保存时清除旧键。
276
-
277
- - `TableChild` 的父关联键为空、`null` 或仅空白时必须失败关闭:不得发起子表列表请求,服务端
278
- 收到空关联键也必须返回空集合,不能把空筛选忽略后退化成全表查询。旧客户端无法在请求层保证时,
279
- 应让控件在关联键有效前保持不挂载;`DisablePagination` 必须为 `false`,只作为第二道限流保护。
280
- - `InFormV8`、字段进入事件和抽屉打开回调不得为预生成的父 `Id` 持久化默认子记录;用户取消
281
- 新增不会提交父表,会留下无法回滚的孤儿数据。默认行应保留在前端状态,或在父表保存成功后通过
282
- 幂等的后端事件创建;不需要真实明细时保持 0 行。
283
-
284
- `OpenTable` 用于弹出列表选择数据,固定授权范围用 `V8.OpenTableSetWhere`;`JoinTable`
285
- 用于展示关联集合,不能用前端拼接代替数据权限。
286
-
287
- ### 子表验收与复盘
288
-
289
- - 回读主表字段、子表字段、隐藏子菜单和索引,确认配置中的表 Id、菜单 Id、外键名均真实存在。
290
- - 用父记录 A 新增/编辑/删除多条子记录;打开父记录 B,确认 A 的数据不可见且不可越权操作。
291
- - 新增主表尚无真实 Id 时,不得产生孤儿子记录;保存后重新打开仍能正确回显。
292
- - 若曾误选组件,复盘必须记录:触发用语、误判基数、正确关系、应增加的生成前断言;通用结论
293
- 回写本节,不能只修一张业务表。
294
-
295
- ## 自定义组件边界
296
-
297
- 优先使用现有 44 类标准控件。只有标准控件无法表达交互、且该交互会长期复用时,
298
- 才使用 `DevComponent`:
299
-
300
- - 多租户共用且与主框架强耦合的 Vue 组件,路径必须稳定并纳入 `Microi.Client` 源码/构建。
301
- - 支持 Add/Edit/View、只读、必填、清空、校验、移动端和暗色主题。
302
- - 不在组件内绕过 FormEngine 权限直接访问任意表。
303
- - 复杂但租户独有、需要固定嵌入表单的区域,优先使用 `DevComponent` + MicroService 路由;临时打开的复杂页面使用 `V8.OpenAppDialog`,都避免把客户逻辑打进主前端。
304
- - MicroService 表单嵌入使用 `microi.routes.json` 页面级 `LegacyComponentPaths` 作为稳定别名,字段 `Config.DevComponentPath` 与其匹配。主前端存在同路径 Vue 文件时本地优先;不存在时平台自动加载对应 `sys_microiservice_page.RoutePath`。新别名不得与 `/src/views` 真实文件冲突。
305
- - 组件宿主下发 `componentMode=true`、可序列化 `componentData` 与 `permissionContext`;子应用用 `dev-component:resize` 同步高度,用 `dev-component:event` 回传 `update:modelValue`、`CallbackFormValueChange`、`FormSet` 或 `ParentFormSet`。不传 Vue 实例、函数、循环引用或 `ParentV8`,不直接操作父页面 DOM。
306
- - 表单嵌入验收必须覆盖 Add/Edit/View/只读、初始值与回写、自动高度、窄屏、暗色主题,以及当前菜单 `ModuleEngineKey` 下的有权/无权账号。
307
- - `DevComponent` 配置了非空字段标题时必须正常渲染 Label;只有标题本身为空时才允许隐藏,
308
- 不能按组件类型全局吞掉业务标题。`el-form--label-top` 下的字段级 `Button` 仍保留与其它
309
- 控件等高的不可见 Label 占位,使按钮对齐控件区而不是对齐标题行。
310
- - 字段显式配置 `FormLabelPosition=left/right/top` 时优先于子表、代码编辑器等特殊组件的默认
311
- `top` 布局;移动端仍可统一回落到 `top`。验收时必须在真实设计器保存后回读该字段配置。
312
- - 同一标签行同时显示 `Label` 与 `Description` 时,业务 Label 不允许收缩或省略;说明文字使用
313
- 剩余宽度并以省略号截断,完整说明通过 Element Plus tooltip 提供。自定义组件内部不得再次
314
- 输出与宿主字段相同的标题;需要补充的是说明或安全提示。
315
- - 权限树勾选子菜单时必须补齐全部祖先菜单的 `Read` 权限,祖先不得被动继承子菜单的增删改查;
316
- 这样既保证路由可见,又避免扩大业务操作权限。
317
-
318
- ## 固定审计字段
319
-
320
- - 核心协议迁移也必须遵守普通物理列允许 NULL。流式发布的 SaaS 开关、协议版本、栅栏、门禁代次和审计字段不能在旧迁移补跑时重新设为 NOT NULL;默认值、状态机、身份校验和完整审计由可信程序保证,只有主键 Id 保持数据库非空约束。
321
-
322
- - `Id`、`CreateTime`、`UpdateTime`、`UserId`、`UserName`、`IsDeleted` 是 DIY 表的正常固定字段。物理列存在时必须有对应 `diy_field` 元数据,不能长期出现在“异常字段修复”列表;`diy_table.DisplayDefaultField` 只控制设计器默认是否显示这些字段,不等于删除元数据。
323
- - 统一通过平台修复接口或 MCP `microi_repair_audit_fields` 补齐/恢复元数据。修复必须按 `OsClient` 使用共享租约锁,可重复执行,只处理已存在的固定物理列,不借机执行 DDL,并在成功后清理字段缓存。
324
- - 表格里的创建人、创建时间、修改时间等审计列应与普通字段共用列头高级搜索、权限和格式化逻辑。
325
-
326
- ## 验收
327
-
328
- - 物理列与 `diy_field` 一致,字段缓存已刷新。
329
- - 新增、编辑、查看、列表、搜索、导入/导出至少覆盖适用场景。
330
- - 选项显示 Label、保存 Key,回显和筛选一致。
331
- - 子表新增/编辑/删除与父表外键正确,不能跨父记录串数据。
332
- - PC 与移动端字段顺序、Tabs、整行控件无截断。
333
- - 前端校验只改善体验;绕过前端直接 HTTP 提交时后端事件仍能阻止非法数据。
1
+ ---
2
+ name: microi-form-engine
3
+ description: Microi 表单引擎设计与控件配置指南。用于创建或修改 diy_table、diy_field、表单组件、字段属性、选项/SQL/数据源引擎数据源、子表、关联表单、定制组件、表单布局和字段事件。
4
+ ---
5
+
6
+ > **Microi吾码基础规范(强制):** 任何 AI 模型与宿主每次新建或接续吾码任务,先完整读取 `../workspace-conventions/SKILL.md`,必须执行版本播报、`@microi.net/cli` 后台自动升级、Skills/MCP 同步和进度播报。安装与诊断读取 `../microi-codex-installer/SKILL.md`;更新失败延后重试,不阻断当前工作。
7
+
8
+ # Microi 表单引擎设计
9
+
10
+ ## 表单设计器生成表单代码
11
+
12
+ 保留现有 `Diy` 动态渲染;需要每表独立页面时,在保存设计后使用【生成表单代码】。生成器产生 `src/pages/Form_表名.vue`,源码归当前租户 `microi-generated-forms` 微服务私有项目,AI 应用工作台可继续编辑。Vite 构建并发布运行产物后,模块菜单用 `CodeForm`,同时绑定原 `DiyTableId` 与对应微服务路由。生成页经前端 V8 SDK 传 `_SysMenuId` 调用 FormEngine,权限及后端事件继续由服务端校验。
13
+
14
+ 基础控件生成独立表单;复杂控件、动态数据源、前端 V8 事件/模板和缺少选项的多选生成平台原表单入口,通过宿主 `openForm` 保留原控件与事件,监听 `micro-app:form-saved` 刷新列表。两种模式读取服务端 `DataAppend.FieldAccess`,隐藏字段不渲染、只读字段不写入;不要只依赖前端身份推断。
15
+
16
+ 人工修改过的目标源码仍需停止覆盖并显示原因。设计器再次变更后重新生成草稿,在源码工作台审阅和合并,再构建发布。源码保存不等于微服务已构建、菜单已切换或目标租户已安装。必须验证实际源码保存回读、构建后页面及普通账号写入,不能只验证预览字符串。
17
+
18
+ 表单引擎同时驱动数据模型、表单、列表、模块、接口配置和工作流配置。处理“新增字段”
19
+ 不能只做物理 `ALTER TABLE`:必须让 `diy_table`、`diy_field`、物理列、组件
20
+ Config/Data、菜单查询列与缓存保持一致。
21
+
22
+ 平台创建 DIY 表时会自动加入 `DiyCommon.FixedDiyField` 定义的 Id、创建/更新时间、
23
+ 创建人、租户等固定字段。业务 Manifest 不重复声明这些字段;读取实时 Schema 或离线快照时也不能
24
+ 因为 `_Fields` 只列出可配置字段,就误判物理表缺少固定字段。
25
+
26
+ ## 必读参考
27
+
28
+ - 控件完整目录、推荐物理类型和选择规则:`references/component-catalog.md`
29
+ - 数据源、字段属性、事件与定制组件:`references/data-source-events.md`
30
+ - 表单分组与宽度:`../microi-form-layout/SKILL.md`
31
+ - 后端表单事件:`../v8-table-event/SKILL.md`
32
+ - 前端字段事件:`../v8-frontend-events/SKILL.md`
33
+
34
+ ## 标准工作流
35
+
36
+ ### 物理字段允许为空(强制)
37
+
38
+ 除作为主键的 `Id` 外,通过 MCP、表单设计器、FormEngine、V8 或应用包新增、修改的普通字段,数据库列一律允许 `NULL`。`NotEmpty` 等业务必填要求只作用于表单/服务端校验,不能生成 `NOT NULL`。默认值和是否允许为空是两项独立属性;兼容旧列时只放宽可空约束,保留类型、有效默认值、字符集、排序规则、注释、索引和历史数据,不以补零/空串替代结构修复。
39
+
40
+ MySQL 的 `ALTER COLUMN DROP DEFAULT` 会让可空列也在省略字段时报 1364;移除普通标量列的旧默认值应使用 `SET DEFAULT NULL`。`IS_NULLABLE=YES` 和 `COLUMN_DEFAULT=NULL` 不足以证明可省略字段,需要通过 `SELECT DEFAULT(列) FROM 表 LIMIT 0` 验证。TEXT/BLOB 的缺失默认标志应保留完整列定义执行 `MODIFY COLUMN` 修复,不能对它们使用 `ALTER COLUMN SET DEFAULT NULL`。
41
+
42
+ 1. 先通过 `microi_get_db_schema` 读取目标租户的真实表、字段和菜单。
43
+ 2. 从当前源码
44
+ `Microi.Client/src/views/form-engine/diy-field-component/diy-component-list.json`
45
+ 核对控件名;官网页面可能含历史控件。
46
+ 3. 新表用 `microi_create_table`;字段用 `microi_add_field`,不得直接写
47
+ `diy_field` 或执行临时 DDL。
48
+ 4. 选项控件同时设置 `data/config`;关联控件明确保存字段和显示字段。
49
+ 5. 字段多时设置 `diy_table.Tabs` 与字段 `Tab`;只有整行控件设置
50
+ `FormWidth=24`,普通字段省略。`CollapseGroup` 属于整行控件,必须显式保存
51
+ `FormWidth=24`,且 `Config.CollapseGroup.ShowFieldCount` 默认补为 `true`。
52
+ 6. 绑定菜单后补齐/允许平台推断列表列、搜索列、隐藏列、排序列、移动端列和默认排序。
53
+ 7. 回读 `diy_field`、刷新 schema 缓存,再在真实新增/编辑/查看表单中验收。
54
+
55
+ ## 原生查询主库策略
56
+
57
+ - 对不能接受副本延迟的权限关系等表,显式配置 `diy_table.ReadPrimary=1`;普通表保持
58
+ `NULL/0`。只能从可信表元数据选择连接,禁止让查询请求的 `ReadPrimary`、`TableModel`
59
+ 或 `DataBaseId` 控制主库/副本。此配置不扩大菜单、表、记录或字段权限。
60
+ - 原生 Get、List、Count/CountBatch、SUM 批量与回退、Tree 子计数和 Export 必须共用
61
+ 目标表所属数据库的 writer 选择;扩展库不得误回租户基础库。主库不可用或配置非法必须
62
+ 失败,不能以副本或0计数伪装成功。直接调用 `V8.DbRead` 的语义不变。
63
+ - V8 的 JavaScript Number 经 .NET 互操作可能成为浮点类型;配置解析接受数值精确等于
64
+ `0/1` 的表示,仍拒绝小数、NaN、Infinity、布尔值及其它非法值,禁止通过截断或舍入放宽值域。
65
+ - 显式 `DbTrans` 保留,不为主库策略跳出事务;父事务旧 RR 快照仍可能看见旧授权关系,
66
+ 不能声称仅开启本字段就实现与撤权原子串行。需要实时授权时采用独立受控主库身份读取。
67
+ - 标准 `microi_create_table`、`microi_update_table` 和 Manifest `tables[].readPrimary`
68
+ 支持 `null/0/1`,省略保持已有配置,显式 `null` 清回缺省。先升级后端并安装正式表单
69
+ 引擎字段,再配置;不通过定制 `.NET` 启动迁移或原始 SQL 补字段。
70
+ - 元数据冷回源使用主库,写后清表缓存并回读。验收分别证明字段定义、可空物理列、配置值、
71
+ 普通身份真实 Rows/Count/SUM/Tree/Export 与撤权边界;离线会话选择测试不能冒充复制延迟
72
+ 或七种数据库实机测试。所有新普通表字段保持可空,不把已有表批量设为主库。
73
+
74
+ ## 上传字段配置(AI 生成时强制)
75
+
76
+ - 需要逐附件角色权限时,在 `Config.FileUpload` 设置 `EnableRolePermission:true` 和 `Limit:true`;
77
+ `HideUnauthorizedFiles`(隐藏无权行)、`ShowUnauthorizedFileName`(显示无权名称)、
78
+ `DisableRoleInheritance`(关闭角色继承)均为 boolean,默认 false。未启用的旧字段保持兼容。
79
+ - 每个文件的 `VisibleRoleIds` 是真实角色 Id 数组;空数组跟随表单权限。标签名称及 `_FileAccess`
80
+ 由后端投影,不能作为客户端授权事实。默认真实持有角色的 Level 严格更高即可继承,
81
+ 同级不同角色不继承;多选任一角色命中即可,仍须有菜单/表单/记录访问与编辑权限。
82
+ - `Config.FileUpload.ConfigurableRoleIds` 是“可配置角色列表”,使用真实角色 Id 数组,默认 `[]` 表示全部。
83
+ 非空时,角色目录和后端新增附件授权都只允许该范围;缩小范围保留旧附件已有角色,可移除但不可再添加。
84
+ 此范围只限制可选授权角色,不改变 Level 继承规则。先用 `microi_list_roles` 读取当前租户角色,禁止复制其它租户的 Id。
85
+ - 无权限附件默认只显示锁定占位、不显示名称;开启隐藏只改变展示,保存时服务端保留原附件,
86
+ 篡改无权元数据、复制他人路径及删除含无权附件的整条记录均应失败。条件批量写附件/删除应改为逐条。
87
+ - 新附件必须通过当前记录/字段的私有上传取得短期 `_UploadProof`,保存后由服务端移除。
88
+ 不能手工拼接他人路径;历史公有文件设置角色前重新私有上传。先部署前后端,再启用字段配置。
89
+ - MCP 可复用 `microi_get_field_list`、`microi_update_field`、`microi_refresh_schema_cache`、
90
+ `microi_list_roles` 和 `microi_save_role`,先完整回读并合并 Config,禁止覆盖原上传大小、数量和 V8。
91
+ 新版 `microi_build_field_config` 支持 `sourceType:"FileUpload"`,自动强制私有存储并校验布尔值;
92
+ 旧 MCP 直接传同等 Config JSON 即可,无需另建业务接口。回归必须使用高/中/低角色和直接 HTTP 篡改,
93
+ 同时覆盖名称开关、隐藏开关、继承开关、单文件、列表、私有/版本预览和保存后重开。
94
+
95
+ - 图片使用 `Config.ImgUpload`,至少明确 `Limit`、`Multiple`、`MaxCount`、`Preview`、
96
+ `MaxSize` 和 `Crop`;文件使用 `Config.FileUpload`,至少明确 `Limit`、`Multiple`、
97
+ `MaxCount`、`MaxSize`。完整键和值域读取 `references/component-catalog.md`。
98
+ - `ImgUpload.Preview` 未配置时默认开启压缩;普通业务图片优先保持开启。裁剪前的原图无论
99
+ 展示图配置为公有或私有、是否压缩,都必须保存在 HDFS 私有桶,业务字段不得保存原图路径。
100
+ - `ImgUpload.Crop.Enabled` 只控制表单打开时是否默认选中裁剪。运行时的裁剪开关、存储范围、
101
+ 单/多图数量、压缩状态和最大体积统一显示在紧凑上传面板中;不得把 `Enabled=false` 误解为
102
+ 禁止用户裁剪。`Mode` 只允许 `free/fixed/select`。
103
+ - 图片和文件的拖放区都使用同一紧凑配置面板。`Multiple=true` 时必须设置业务合理的
104
+ `MaxCount`;`MaxSize` 单位为 MB,字段限制只能收紧租户/平台上限,不能放大。
105
+ - 富文本使用 `Config.RichText`:必须明确 `Limit`,并按需配置
106
+ `Image.Enabled/MaxSize/MaxCount/Preview/CompressMaxSize/CompressMaxWidth`、
107
+ `Video.Enabled/MaxSize/MaxCount`、`File.Enabled/MaxSize/MaxCount/Accept`。公开公告、商品详情
108
+ 等匿名正文显式使用 `Limit=false`;内部正文使用 `true`。旧字段缺失配置时安全默认为私有桶,
109
+ 图片默认压缩到约 500 KB、最长边 1920 px。
110
+ - 私有富文本只能持久化稳定对象标识,禁止把 HDFS 签名 URL、审计代理 Ticket 或 DiyToken 写入
111
+ HTML。每次查看/编辑按当前菜单、表、记录和字段权限换取新短效地址;外部匿名页面没有此权限
112
+ 上下文,因此不能把私有 RichText 当作公开正文。普通用户通过当前表单新增/编辑授权后,后端
113
+ 必须回读 `diy_field.Config.RichText.Limit` 决定公私桶;只改请求 `Limit=false` 不能绕过字段配置。
114
+ - 图片、文件和富文本上传必须携带 `FormEngineKey + FieldId + SysMenuId`,编辑记录再带
115
+ `FormDataId`,TableChild 再带父子授权上下文。后端不得按用户等级统一覆盖字段的“禁止匿名访问”;
116
+ 无法回查字段与动作权限的普通上传才安全降级为私有桶。
117
+
118
+ 新建表/模块时,除非用户显式指定或表单达到极重阈值(约 36+ 业务字段、2+ 子表或同等
119
+ 重型控件密度),默认保存 `diy_table.FormOpenType=Dialog` 与 `FormOpenWidth=80%`。
120
+ Drawer 只服务超长复杂表单,不能作为所有 CRUD 模块的模板默认值。
121
+ 若设计器显示而运行态不显示,先检查 `InFormV8`/字段 V8 是否调用
122
+ `V8.FieldSet(..., 'Visible', false)`、`hideField` 或传入 `HideFields`,再判断前端源码。
123
+
124
+ ## 表单 Banner(所有新业务表必做)
125
+
126
+ 标准表单 Banner 默认显示,以当前主题色约 50% 混合强度叠加深蓝灰渐变,并适配浅色、
127
+ 深色与移动端。视觉应有层次但保持清爽,标题始终维持安全对比度;统计卡片使用半透明背景
128
+ 和柔和阴影分层,避免堆叠边框。它属于表单语义,配置
129
+ 必须写入 `diy_table` 的 `FormBannerEnabled`、`FormBannerTitleField`、
130
+ `FormBannerSubtitleField`、`FormBannerImageField`、`FormBannerIcon`、
131
+ `FormBannerBackgroundField`、`FormBannerTagFields`、`FormBannerMetrics`,禁止写进
132
+ `sys_menu`、`DiyConfig` 或项目定制组件。
133
+
134
+ - 标题优先业务自动编号/单号/编码,再选名称或标题;副标题优先客户、项目、公司、分类、
135
+ 日期等可读字段。
136
+ - 左侧图片使用 `ImgUpload`。单图、多图取首图,继续遵循吾码公有/私有文件路径与授权
137
+ 规则;图片为空时必须有语义合适的 Font Awesome 图标回退。
138
+ - 右侧标签优先 `Select/Radio/Switch/Checkbox/SelectTree/Department` 等选项字段,最多
139
+ 选择 3 个有业务意义的状态、类型或等级。显式 `[]` 表示不要自动标签。
140
+ - 自动统计最多 3 项,只选择真实金额、合计、数量、成本、余额、评分、比率、进度等具有
141
+ 明确业务口径的数值字段;必须排除 Id、排序、启用、状态、版本、分页和本页加载量。
142
+ 存在 `TableChild` 时,默认统计必须携带完整父表/父字段/父记录授权上下文,在服务端对全部
143
+ 关联子表数据计算行数或业务数值合计,不能只统计当前页。跨表自定义口径使用 `ApiEngineKey +
144
+ ValuePath + ParamMap + RefreshSeconds`,相同接口批量返回,禁止 N+1、随机数和固定演示数;
145
+ 没有可靠指标时隐藏统计区。显式 `[]` 表示不要自动统计。
146
+ - 兼容旧模块 Hero 时仅迁移视觉、`Source=Field` 或显式记录作用域指标;列表总数、分类数量和
147
+ 未引用当前 `Form/RecordId` 的全局接口统计不得进入单记录 Banner,缺省时回到当前记录和
148
+ 授权 `TableChild` 的语义统计。
149
+ - 未配置的存量表由运行时按字段类型智能推断,不能因为物理字段为空而隐藏或展示空壳。
150
+ 只有 `FormBannerEnabled=0` 才隐藏。
151
+ - 字段绑定须区分省略/`NULL` 与显式空字符串:`titleField/subtitleField/imageField/backgroundField`
152
+ 省略或 `NULL` 表示未选择,允许兼容推断;显式 `""` 表示不绑定该字段,不能被推断值或旧别名
153
+ 覆盖。取消标题/图片字段后仍保留表单名称/默认图标回退。完整验收须同时使用包含该语义的 MCP
154
+ 与平台前端,逐项回读空字符串并验证实际表单;不能只看到写入 `Code=1` 就宣称生效。
155
+ - 完整系统 Manifest 使用 `tables[].formBanner`;未提供时 `microi_generate_system` 仍须写入
156
+ 类型感知的默认值。逐步创建字段后调用 `microi_configure_form_banner` 并回读验证。
157
+ - `microi_generate_system` 的最终验收与 `microi_validate_system` 必须逐表回读 Banner 语义字段;
158
+ 写入返回成功、结构验收 `Code=1` 都不能代替已持久化配置,`Data.Passed=false` 仍视为失败。
159
+ 旧库缺少 Banner 物理列时先完成平台正式升级,再配置和重新验收,不直接执行 SQL 补列。
160
+ - 表单设计器验收必须覆盖有/无图片、有/无统计、子表完整聚合、接口失败回退、浅色、深色、
161
+ PC 和窄屏,并检查文字对比度以及不存在技术字段伪统计。
162
+
163
+ ## 物理类型底线
164
+
165
+ MCP 建模只使用:
166
+
167
+ - `varchar(N)`
168
+ - `mediumtext` / `longtext`
169
+ - `int` / `bigint`
170
+ - `decimal(18,N)`
171
+
172
+ 日期时间用 `varchar(25)` 保存 `yyyy-MM-dd HH:mm:ss`,组件用 `DateTime`;
173
+ 开关用 `int`。不得生成 `datetime/date/timestamp/float/double/boolean/bool/string/text/nvarchar`。
174
+ 前端设计器 JSON 中的历史默认类型不能覆盖服务器建模规则。
175
+
176
+ ## 选项字段
177
+
178
+ `Select`、`MultipleSelect`、`Radio`、`Checkbox` 没有数据源时会显示空选项:
179
+
180
+ ```text
181
+ 1|启用,0|禁用
182
+ ```
183
+
184
+ 推荐保存稳定 Key、显示可翻译 Label。修改 `Data/Config/KeyValue` 后必须
185
+ `microi_get_field_list` 回读,并执行 `microi_refresh_schema_cache`。
186
+
187
+ ## `JoinForm` 与 `TableChild` 硬性判定
188
+
189
+ 这两个控件都能在表单内显示另一张表,但数据关系和运行组件完全不同,生成表/字段前
190
+ 必须先确定基数,不得因为名称里出现“关联”就默认使用 `JoinForm`。
191
+
192
+ | 判断项 | `JoinForm`(关联表单) | `TableChild`(子表) |
193
+ |---|---|---|
194
+ | 关系 | 当前记录关联**一个**独立目标记录,通常为 N:1 或 1:1 | 一条主表记录拥有 0..N 条明细,标准 1:N |
195
+ | 关系存储 | 主表字段保存目标记录 `Id` | **子表物理外键**保存主表 `Id`/指定主键值 |
196
+ | 界面 | 嵌入一张 `diy-form`,只展示/编辑一条目标记录 | 嵌入一张 `diy-table`,提供明细列表、分页及行级增删改 |
197
+ | 核心配置 | `Config.JoinForm.{TableId,TableName,JoinFieldName,FormMode,Id,_SearchEqual}` | `Config` 根节点的子表/菜单/外键 Id,加 `Config.TableChild` 运行选项 |
198
+ | 目标限制 | 目标表必须与当前表不同;相同则组件拒绝渲染 | 子表应是独立明细表,并通过外键限定到当前父记录 |
199
+
200
+ ### 决策规则(强制)
201
+
202
+ - 需求出现“子表、明细、清单、条目、行项目、多个、若干条、记录列表”,且没有明确说明
203
+ “只关联一条已有记录”时,默认建模为 `TableChild`。
204
+ - 只要一条父记录可能有 0..N 条目标记录,或需要在父表单内列表、分页、新增、编辑、删除
205
+ 多行,就必须用 `TableChild`。
206
+ - 只有主表保存一个目标记录 Id、并需要把该独立记录的完整表单嵌入当前表单时,才用
207
+ `JoinForm`。选择一条记录但无需嵌入完整表单时,优先 `OpenTable`/`Select`。
208
+ - 语义仍不明确时必须在任何 MCP 写入前询问基数;禁止静默退化为 `JoinForm`。
209
+ - 禁止把“明细”设计为主表 `XxxId + JoinForm`;禁止让 `JoinForm.TableId/TableName`
210
+ 指向当前表;禁止把 1:N 外键放在主表。
211
+ - 完整系统 Manifest 中,`JoinForm` / `TableChild` 字段必须声明 `relation.cardinality`;
212
+ `microi_plan_system` 与 `microi_generate_system` 会在任何写入前执行本节门禁。直接调用
213
+ `microi_add_field` / `microi_update_field` 时,后端仍会校验目标表、主/子外键、隐藏菜单
214
+ 和子表索引,不能靠绕过 Manifest 写入未初始化配置。
215
+
216
+ 示例:
217
+
218
+ - “订单包含多个商品明细” → `order_detail.OrderId` + `TableChild`。
219
+ - “访客单包含多件携带物品” → `fk_carry_item.VisitId` + `TableChild`,不能用
220
+ `GuestId + JoinForm`,也不能把 `JoinForm` 指回 `fk_carry_item` 自己。
221
+ - “工单关联一个客户,并在工单内展开客户档案” → 主表 `CustomerId` + `JoinForm`。
222
+
223
+ ### MCP 创建 `TableChild` 的两阶段流程
224
+
225
+ 1. 创建主表和独立子表;在子表创建真实外键(如 `VisitId varchar(50)`)。
226
+ 2. 在子表为回查创建与物理隔离方式一致的索引:表有 `OsClient` 时通常为
227
+ `(OsClient, VisitId)`,独立租户表没有该列时为 `(VisitId)`。索引写入 Manifest
228
+ `tables[].indexes`,并以 `microi_get_table_indexes` 回读;物理字段回读失败时停止配置。
229
+ 3. 为子表创建绑定其 `diyTableId` 的隐藏 CRUD 菜单:`Display=0`、`AppDisplay=0`、
230
+ `HasChild=0`。
231
+ 4. 在完整系统 Manifest 的主表字段声明:
232
+
233
+ ```json
234
+ {
235
+ "name": "Items",
236
+ "label": "明细",
237
+ "component": "TableChild",
238
+ "formWidth": 24,
239
+ "relation": {
240
+ "cardinality": "1:N",
241
+ "targetTable": "Biz_OrderItem",
242
+ "childForeignKey": "OrderId",
243
+ "childModule": "订单明细(隐藏)",
244
+ "primaryTableFieldName": "Id"
245
+ }
246
+ }
247
+ ```
248
+
249
+ `microi_generate_system` 会先创建全部表与普通字段,再创建隐藏菜单,最后回读并写入
250
+ 当前租户真实的 `diy_table.Id` / `sys_menu.Id`。禁止在 Manifest 中编造这些 Id,禁止
251
+ 因依赖尚未创建而退化成 `JoinForm`。
252
+ 5. `TableChild` 控件字段通常只是表单配置位,关系事实存放在子表外键。至少保存:
253
+
254
+ ```json
255
+ {
256
+ "TableChildTableId": "<子表 diy_table.Id>",
257
+ "TableChildSysMenuId": "<子表 sys_menu.Id>",
258
+ "TableChildSysMenuName": "携带物品明细",
259
+ "TableChildFkFieldName": "VisitId",
260
+ "TableChild": {
261
+ "PrimaryTableFieldName": "Id",
262
+ "Data": [],
263
+ "SearchAppend": {},
264
+ "ImportAutoFillFk": true,
265
+ "FieldRelations": [],
266
+ "LastTableId": "",
267
+ "LastSysMenuId": "",
268
+ "LastSysMenuName": "",
269
+ "DisablePagination": false,
270
+ "NoneDefaultHeight": false
271
+ }
272
+ }
273
+ ```
274
+
275
+ `FieldRelations` 使用紧凑格式 `[["父表字段","子表字段",true?], ...]`。全部关系用于新增回写和导入回填;第三位 `true` 仅标记参与导入反查父表的关系。后端兼容旧三项配置,新版前端会合并去重并在字段下次保存时清除旧键。
276
+
277
+ - `TableChild` 的父关联键为空、`null` 或仅空白时必须失败关闭:不得发起子表列表请求,服务端
278
+ 收到空关联键也必须返回空集合,不能把空筛选忽略后退化成全表查询。旧客户端无法在请求层保证时,
279
+ 应让控件在关联键有效前保持不挂载;`DisablePagination` 必须为 `false`,只作为第二道限流保护。
280
+ - `InFormV8`、字段进入事件和抽屉打开回调不得为预生成的父 `Id` 持久化默认子记录;用户取消
281
+ 新增不会提交父表,会留下无法回滚的孤儿数据。默认行应保留在前端状态,或在父表保存成功后通过
282
+ 幂等的后端事件创建;不需要真实明细时保持 0 行。
283
+
284
+ `OpenTable` 用于弹出列表选择数据,固定授权范围用 `V8.OpenTableSetWhere`;`JoinTable`
285
+ 用于展示关联集合,不能用前端拼接代替数据权限。
286
+
287
+ ### 子表验收与复盘
288
+
289
+ - 回读主表字段、子表字段、隐藏子菜单和索引,确认配置中的表 Id、菜单 Id、外键名均真实存在。
290
+ - 用父记录 A 新增/编辑/删除多条子记录;打开父记录 B,确认 A 的数据不可见且不可越权操作。
291
+ - 新增主表尚无真实 Id 时,不得产生孤儿子记录;保存后重新打开仍能正确回显。
292
+ - 若曾误选组件,复盘必须记录:触发用语、误判基数、正确关系、应增加的生成前断言;通用结论
293
+ 回写本节,不能只修一张业务表。
294
+
295
+ ## 自定义组件边界
296
+
297
+ 优先使用现有 44 类标准控件。只有标准控件无法表达交互、且该交互会长期复用时,
298
+ 才使用 `DevComponent`:
299
+
300
+ - 多租户共用且与主框架强耦合的 Vue 组件,路径必须稳定并纳入 `Microi.Client` 源码/构建。
301
+ - 支持 Add/Edit/View、只读、必填、清空、校验、移动端和暗色主题。
302
+ - 不在组件内绕过 FormEngine 权限直接访问任意表。
303
+ - 复杂但租户独有、需要固定嵌入表单的区域,优先使用 `DevComponent` + MicroService 路由;临时打开的复杂页面使用 `V8.OpenAppDialog`,都避免把客户逻辑打进主前端。
304
+ - MicroService 表单嵌入使用 `microi.routes.json` 页面级 `LegacyComponentPaths` 作为稳定别名,字段 `Config.DevComponentPath` 与其匹配。主前端存在同路径 Vue 文件时本地优先;不存在时平台自动加载对应 `sys_microiservice_page.RoutePath`。新别名不得与 `/src/views` 真实文件冲突。
305
+ - 组件宿主下发 `componentMode=true`、可序列化 `componentData` 与 `permissionContext`;子应用用 `dev-component:resize` 同步高度,用 `dev-component:event` 回传 `update:modelValue`、`CallbackFormValueChange`、`FormSet` 或 `ParentFormSet`。不传 Vue 实例、函数、循环引用或 `ParentV8`,不直接操作父页面 DOM。
306
+ - 表单嵌入验收必须覆盖 Add/Edit/View/只读、初始值与回写、自动高度、窄屏、暗色主题,以及当前菜单 `ModuleEngineKey` 下的有权/无权账号。
307
+ - `DevComponent` 配置了非空字段标题时必须正常渲染 Label;只有标题本身为空时才允许隐藏,
308
+ 不能按组件类型全局吞掉业务标题。`el-form--label-top` 下的字段级 `Button` 仍保留与其它
309
+ 控件等高的不可见 Label 占位,使按钮对齐控件区而不是对齐标题行。
310
+ - 字段显式配置 `FormLabelPosition=left/right/top` 时优先于子表、代码编辑器等特殊组件的默认
311
+ `top` 布局;移动端仍可统一回落到 `top`。验收时必须在真实设计器保存后回读该字段配置。
312
+ - 同一标签行同时显示 `Label` 与 `Description` 时,业务 Label 不允许收缩或省略;说明文字使用
313
+ 剩余宽度并以省略号截断,完整说明通过 Element Plus tooltip 提供。自定义组件内部不得再次
314
+ 输出与宿主字段相同的标题;需要补充的是说明或安全提示。
315
+ - 权限树勾选子菜单时必须补齐全部祖先菜单的 `Read` 权限,祖先不得被动继承子菜单的增删改查;
316
+ 这样既保证路由可见,又避免扩大业务操作权限。
317
+
318
+ ## 固定审计字段
319
+
320
+ - 核心协议迁移也必须遵守普通物理列允许 NULL。流式发布的 SaaS 开关、协议版本、栅栏、门禁代次和审计字段不能在旧迁移补跑时重新设为 NOT NULL;默认值、状态机、身份校验和完整审计由可信程序保证,只有主键 Id 保持数据库非空约束。
321
+
322
+ - `Id`、`CreateTime`、`UpdateTime`、`UserId`、`UserName`、`IsDeleted` 是 DIY 表的正常固定字段。物理列存在时必须有对应 `diy_field` 元数据,不能长期出现在“异常字段修复”列表;`diy_table.DisplayDefaultField` 只控制设计器默认是否显示这些字段,不等于删除元数据。
323
+ - 统一通过平台修复接口或 MCP `microi_repair_audit_fields` 补齐/恢复元数据。修复必须按 `OsClient` 使用共享租约锁,可重复执行,只处理已存在的固定物理列,不借机执行 DDL,并在成功后清理字段缓存。
324
+ - 表格里的创建人、创建时间、修改时间等审计列应与普通字段共用列头高级搜索、权限和格式化逻辑。
325
+
326
+ ## 验收
327
+
328
+ - 物理列与 `diy_field` 一致,字段缓存已刷新。
329
+ - 新增、编辑、查看、列表、搜索、导入/导出至少覆盖适用场景。
330
+ - 选项显示 Label、保存 Key,回显和筛选一致。
331
+ - 子表新增/编辑/删除与父表外键正确,不能跨父记录串数据。
332
+ - PC 与移动端字段顺序、Tabs、整行控件无截断。
333
+ - 前端校验只改善体验;绕过前端直接 HTTP 提交时后端事件仍能阻止非法数据。