@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,238 +1,238 @@
1
- ---
2
- name: v8-formengine-http
3
- description: 移动端 / 外部系统通过 HTTP 直接调用 Microi FormEngine(GetTableData / GetFormData / Add / Upt / Del)的 RESTful 路由约定与排错指南
4
- ---
5
-
6
- > **Microi吾码基础规范(强制):** 任何 AI 模型与宿主每次新建或接续吾码任务,先完整读取 `../workspace-conventions/SKILL.md`,必须执行版本播报、`@microi.net/cli` 后台自动升级、Skills/MCP 同步和进度播报。安装与诊断读取 `../microi-codex-installer/SKILL.md`;更新失败延后重试,不阻断当前工作。
7
-
8
- # FormEngine HTTP 路由约定(外部系统调用)
9
-
10
- > 适用于:uni-app H5、原生 App、Postman、第三方系统、Playwright/Cypress 自动化测试等任何**没有进入 V8 引擎**的客户端。
11
- > 不适用于:服务器端 V8 接口引擎内部 — 那种情况请直接 `V8.FormEngine.GetTableData(...)`。
12
-
13
- ## ⚠️ 最常见错误
14
-
15
- ```text
16
- ❌ POST /formengine/{表名}/gettabledata → 404
17
- ❌ POST /api/formengine/{表名}/gettabledata → 404
18
- ✅ POST /api/formengine/gettabledata-{表名} → OK (动态短路由)
19
- ✅ POST /api/formengine/GetTableData body 中带 FormEngineKey → OK (标准路由)
20
- ```
21
-
22
- 平台路由由 `Microi.Server/Microi.net.Api/Handler/DynamicApiEngine.cs` 的 `FormEngineRoutes` 字典决定,**只认上面两种形式**。
23
-
24
- ## 路由总表
25
-
26
- ### 形式一:标准 Controller 路由 — 推荐
27
- 全部为 `POST`,URL 不含表名,`FormEngineKey` 放在 Body 中。
28
-
29
- | URL | 动作 |
30
- | --- | --- |
31
- | `/api/formengine/GetFormData` | 取一条 |
32
- | `/api/formengine/GetTableData` | 取列表(分页) |
33
- | `/api/formengine/AddFormData` | 新增 |
34
- | `/api/formengine/UptFormData` | 按 Id 修改 |
35
- | `/api/formengine/UptFormDataByWhere` | 按 _Where 批量改 |
36
- | `/api/formengine/DelFormData` | 删除(Id / Ids) |
37
- | `/api/formengine/DelFormDataByWhere` | 按 _Where 批量删 |
38
- | `/api/formengine/GetFormDataAnonymous` | 匿名取一条 |
39
- | `/api/formengine/GetTableDataAnonymous` | 匿名取列表 |
40
- | `/api/formengine/AddFormDataAnonymous` | 匿名新增 |
41
-
42
- ### 形式二:动态短路由(表名写进 URL,URL-friendly)
43
- | URL 前缀 | 等价于 |
44
- | --- | --- |
45
- | `/api/formengine/getformdata-{table}` | `/api/formengine/GetFormData` |
46
- | `/api/formengine/get-formdata-{table}` | `/api/formengine/GetFormData` |
47
- | `/api/formengine/gettabledata-{table}` | `/api/formengine/GetTableData` |
48
- | `/api/formengine/get-tabledata-{table}` | `/api/formengine/GetTableData` |
49
- | `/api/formengine/addformdata-{table}` | `/api/formengine/AddFormData` |
50
- | `/api/formengine/add-formdata-{table}` | `/api/formengine/AddFormData` |
51
- | `/api/formengine/uptformdata-{table}` | `/api/formengine/UptFormData` |
52
- | `/api/formengine/upt-formdata-{table}` | `/api/formengine/UptFormData` |
53
- | `/api/formengine/delformdata-{table}` | `/api/formengine/DelFormData` |
54
- | `/api/formengine/del-formdata-{table}` | `/api/formengine/DelFormData` |
55
-
56
- URL 中的表名小写最稳,平台不区分大小写。匿名版本目前**只在形式一上有**(`GetTableDataAnonymous` 等)。
57
-
58
- ## 请求 Header
59
-
60
- | Header | 是否必填 | 说明 |
61
- | --- | --- | --- |
62
- | `Content-Type` | 必填 | `application/json` 推荐 |
63
- | `OsClient` | 必填 | 租户标识;亦可放 querystring `?OsClient=xxx` 或 body |
64
- | `authorization` | 鉴权接口必填 | `Bearer <Token>`;兼容旧客户端的 `Token` Header |
65
- | `did` | 登录及鉴权接口推荐 | 当前终端稳定设备标识;首次生成后持久化,不能每次请求随机变化 |
66
-
67
- 注意:上表是 FormEngine 路由约定。ApiEngine HTTP 复测和移动端 `callEngine` 使用稳定路径 `/apiengine/{key}`,租户通过唯一的 `osclient` Header 传递,JSON/Form Body 可冗余携带 `OsClient`。普通 POST/PUT/PATCH/DELETE 禁止追加 `--OsClient--...--`;特殊路径只用于无法设置 Header/Form/Query 的 GET/HEAD 或第三方回调。
68
-
69
- 平台可能通过响应 Header `authorization`(兼容 `token`)续签或替换 Token。客户端必须立即保存新 Token,并保证并发旧响应不能覆盖已经写入的新 Token。跨域部署还必须在 CORS 中暴露 `authorization`、`token` 等需要读取的响应 Header。Token 属于凭据,禁止写入 URL、日志、错误上报和页面源码。
70
-
71
- ## FormEngine 数据授权边界
72
-
73
- “Token 有效”只代表身份有效,不代表可以访问任意表。客户端 FormEngine CRUD 还会经过表、菜单、角色和行级范围授权:
74
-
75
- 1. 受保护的平台敏感表优先拒绝普通用户;匿名接口也不能绕过。
76
- 2. 标准菜单页应携带真实 `_SysMenuId`,或使用 `ModuleEngineKey`。服务器会严格校验该菜单是否绑定目标表、当前角色是否拥有菜单及对应操作权限;列表、计数、导出追加该菜单的数据范围。
77
- 3. 列表、写入、导入、导出显式传错 `_SysMenuId` / `ModuleEngineKey` 会直接拒绝,不会降级为其它菜单或表权限。单行详情只要当前角色拥有至少一个直接绑定同表的菜单(或精确表级 `Read` 权限)即可读取,不应用菜单 `SqlWhere` / `SqlJoin`;旧客户端携带过期菜单 Id 时也按该规则恢复。
78
- 4. 为兼容历史前端 V8/外部客户端,普通 CRUD 未传菜单上下文时,服务器会从当前用户的版本化授权缓存中查找“当前角色已获授权且直接绑定目标表”的菜单。无菜单列表仍安全合并候选菜单的数据范围,不能靠漏参绕过;详情按同表菜单访问,写入按 `Add/Edit/Del` 动作权限。也可以使用角色的精确表级 `Read/Add/Edit/Del` 授权。`JoinTables` 不是独立访问授权。
79
- 5. 导入、导出必须锚定具体菜单,不能依赖无菜单兼容推断。
80
- 6. `TableChild` 子表委托由标准表单运行时生成 `_TableChildAuth`,服务器重新校验父菜单、父记录、字段绑定、子表和外键,并强制父子范围。它是内部不透明上下文,外部客户端不要手工拼装。
81
- 7. `_InvokeType:'Client'` 只决定是否执行客户端语义的表单事件,不是权限开关。可信服务器调用标记也不能通过 HTTP Body 伪造。
82
-
83
- 因此:
84
-
85
- - 标准模块、详情页和其字段元数据请求优先传真实 `_SysMenuId`,使服务器确定菜单绑定与操作权限;其中只有列表、计数、导出应用菜单查询范围。
86
- - 历史无 `_SysMenuId` 请求可继续工作,但前提是当前用户确实拥有目标表对应的菜单或精确表权限;不能把兼容推断理解为“有 Token 即可查表”。
87
- - 历史单表字段请求可在菜单缺失/过期时回退到当前角色另一个引用同表的已授权菜单;`GetDiyFieldByDiyTables` 批量字段请求按“第一张主表必须授权、后续表逐张授权并过滤”兼容。后续未授权/保护表不会导致主表失败,也不会返回其字段配置;这些规则不授予数据行权限。
88
- - 表单设计器 `/api/DiyField/UptDiyFieldList` 属于 `Level >= 9999` 控制面:外层一次授权、字段归属校验、同事务批量更新、批次末一次缓存/版本刷新。禁止在 100+ 字段循环中逐条调用完整 `UptFormDataAsync("diy_field", ...)`,否则会重复执行授权、V8、日志及 SaaS/Redis 缓存工作。
89
- - 接口引擎内的 `V8.FormEngine.*` 属于服务器端调用,不要求客户端 `_SysMenuId`。但接口引擎本身必须正确限制谁能调用,并在服务端校验业务对象范围,不能把表名和条件原样交给不可信客户端。
90
- - 客户端新增、修改、删除分别校验真实菜单的 `Add`、`Edit`、`Del` 权限。`SqlWhere` / `SqlJoin` 是模块查询过滤,不是行级写权限:不得把它们追加到写入 SQL,也不得因查询包含 Join 拒绝已获授权的主表写入。
91
- - 进入 `SubmitBeforeServerV8` / `SubmitAfterServerV8` 后,事件内 FormEngine/数据库调用与接口引擎一样属于可信服务器执行,可实现当前租户内的跨表事务。需要“只能修改本人数据”等业务约束以及归属字段写入时,应在这里或专用接口引擎中完成。
92
-
93
- ## 原生详情关联数据
94
-
95
- - `POST /api/FormEngine/GetFormRelatedData` 接收父表 `ParentFormEngineKey`、父记录
96
- `ParentTableRowId`、真实 `_SysMenuId`,以及固定 `RelatedType`:
97
- `Counts/DataLog/DataComment/DataVersion`。身份、租户来自 DiyToken,不能透传请求的可信标记。
98
- - `AuthorizeClientTableOperationAsync(..., 'Read')` 仅完成表/菜单授权,不证明父行可读。
99
- 必须再执行 Client `GetFormDataAsync`,让父记录不存在或 `ServerDataV8` 拒绝阻断关联查询。
100
- - 固定辅助表查询使用服务端新构造的 CLR 参数与可信来源;`JObject` 中写
101
- `_InvokeType:'Server'` 仍是非可信参数。不得通过给普通角色开放辅助表权限来修复此类拒绝。
102
- - 日志和版本返回固定元信息,`DataAppend.HistoryContentMode='MetadataOnly'`;
103
- 当前行脱敏不授予历史 `Content/Data` 原文。客户端不能据元信息开放预览、对比、加载。
104
- - 评论必须同时按真实 `TableId + TableRowId` 过滤。缺少 `TableId` 时,Counts 返回
105
- `DataComment=null`,以 `DataAppend.DataCommentUnavailableReason/Message` 显式说明;
106
- 评论详情失败。不能按单键兼容、猜旧数据归属、假报零条或承诺不存在的可用升级包。
107
- - 回归须区分实际 HTTP 与替身组件测试:普通角色父行可读、同菜单另一归属被 DataFilter
108
- 拒绝、父 Id 不存在、同 Id 不同表、伪造租户/类型/可信标记、历史敏感原文不返回都需验收。
109
- 安全评论绑定写入及旧数据处理须独立交付后才能宣称评论完整可用。
110
-
111
- ## Body 结构(POST JSON)
112
-
113
- ```jsonc
114
- {
115
- "OsClient": "demo",
116
- "FormEngineKey": "mall_product", // 形式一必填;形式二可选(已在 URL 中)
117
- "_SysMenuId": "目标菜单Id", // 标准模块推荐;必须是真实绑定目标表且当前角色有权访问的菜单
118
- "_Where": [["Status","=","OnSale"], ["AND","Stock",">",0]],
119
- "_SelectFields": ["Id","Title","CurrentPrice","MainImg"],
120
- "_OrderBy": "SoldCount",
121
- "_OrderByType": "DESC",
122
- "_PageIndex": 1,
123
- "_PageSize": 20
124
- }
125
- ```
126
-
127
- 写操作(Add/Upt)将业务字段平铺到 body:
128
- ```jsonc
129
- { "OsClient":"demo", "FormEngineKey":"biz_order",
130
- "Id":"01ABC...", "Quantity": 2, "Selected": 1 }
131
- ```
132
-
133
- ## 响应 DosResult 标准格式
134
-
135
- ```jsonc
136
- { "Code": 1, "Data": [...], "DataCount": 123, "Msg": "" }
137
- ```
138
- | Code | 含义 |
139
- | --- | --- |
140
- | 1 | 成功 |
141
- | 0 | 业务失败(看 `Msg`) |
142
- | 1001 | 登录身份已过期 / Token 无效 |
143
- | 1002 | 身份验证失败(OsClient 与 Token 不匹配) |
144
-
145
- ## 客户端封装样板(uni-app)
146
-
147
- ```javascript
148
- const BASE = 'https://api.itdos.com';
149
- const OS_CLIENT = runtimeConfig.osClient;
150
- const TOKEN_KEY = 'mall_token';
151
- const DID_KEY = 'mall_did';
152
-
153
- function normalizeToken(value) {
154
- return String(value || '').replace(/^Bearer\s+/i, '').trim();
155
- }
156
- function getToken() {
157
- return normalizeToken(uni.getStorageSync(TOKEN_KEY));
158
- }
159
- function getDid() {
160
- let did = uni.getStorageSync(DID_KEY);
161
- if (!did) {
162
- did = `uni-${Date.now()}-${Math.random().toString(36).slice(2)}`;
163
- uni.setStorageSync(DID_KEY, did);
164
- }
165
- return did;
166
- }
167
- function readHeader(headers, name) {
168
- const key = Object.keys(headers || {}).find(k => k.toLowerCase() === name);
169
- return key ? headers[key] : '';
170
- }
171
- function applyResponseToken(headers, requestToken) {
172
- const responseToken = normalizeToken(
173
- readHeader(headers, 'authorization') || readHeader(headers, 'token')
174
- );
175
- if (!responseToken) return;
176
-
177
- const currentToken = getToken();
178
- // 旧请求若只回显旧 Token,不得覆盖其它请求/标签页已保存的新 Token。
179
- if (currentToken && requestToken && currentToken !== requestToken && responseToken === requestToken) {
180
- return;
181
- }
182
- uni.setStorageSync(TOKEN_KEY, responseToken);
183
- }
184
-
185
- function formEngineRequest(action, table, body = {}) {
186
- return new Promise((resolve, reject) => {
187
- const requestToken = getToken();
188
- uni.request({
189
- url: `${BASE}/api/formengine/${action}-${table}`,
190
- method: 'POST',
191
- header: {
192
- 'Content-Type': 'application/json',
193
- 'OsClient': OS_CLIENT,
194
- 'authorization': requestToken ? `Bearer ${requestToken}` : '',
195
- 'did': getDid()
196
- },
197
- data: { OsClient: OS_CLIENT, FormEngineKey: table, ...body },
198
- success: (res) => {
199
- applyResponseToken(res.header || res.headers, requestToken);
200
- resolve(res.data || {});
201
- },
202
- fail: reject
203
- });
204
- });
205
- }
206
- export const formEngineGet = (t, w) => formEngineRequest('gettabledata', t, w);
207
- export const formEngineGetOne = (t, w) => formEngineRequest('getformdata', t, w);
208
- export const formEngineAdd = (t, d) => formEngineRequest('addformdata', t, d);
209
- export const formEngineUpt = (t, d) => formEngineRequest('uptformdata', t, d);
210
- export const formEngineDel = (t, d) => formEngineRequest('delformdata', t, d);
211
- ```
212
-
213
- ## 排错速查
214
-
215
- | 现象 | 真实原因 |
216
- | --- | --- |
217
- | 404 Not Found | URL 缺 `/api/` 前缀,或表名/动作之间用 `/` 而不是 `-` |
218
- | 405 Method Not Allowed | 用了 GET(FormEngine 全部为 POST) |
219
- | 1001 登录身份已过期 | 没传 Token / Token 过期 / Redis 重启 |
220
- | 1002 身份验证失败 | OsClient 不匹配 |
221
- | `NoAuth` / `您没有权限做此操作` | Token 有效但菜单、表操作权限、表绑定角色、行级范围或敏感表策略不允许 |
222
- | 显式传 `_SysMenuId` 后无权限 | 列表/写入使用错误菜单会严格拒绝;唯一详情在当前角色仍拥有另一个同表菜单时可恢复,不应用菜单查询范围 |
223
- | 无 `_SysMenuId` 仍无权限 | 当前角色没有直接绑定该表的菜单授权,也没有精确表级授权 |
224
- | 并发后提示 TokenReplaced / MissingToken | 客户端没有接收响应新 Token,或旧请求/其它标签页覆盖或清除了共享新 Token |
225
- | Code:0 表不存在 | `FormEngineKey` 在 `diy_table` 不存在 |
226
- | Code:0 字段不存在 | `_Where` / `_SelectFields` 写了表上没有的字段 |
227
- | 返回 `null` 而不是 DosResult | Controller 抛了异常被吞,到后端日志看 `Microi.Core` 报错 |
228
-
229
- ## 与服务器端 V8 的对照
230
-
231
- | 客户端 HTTP 路由 | V8 内等价写法 |
232
- | --- | --- |
233
- | POST `/api/formengine/gettabledata-mall_product` | `V8.FormEngine.GetTableData('mall_product', {...})` |
234
- | POST `/api/formengine/getformdata-mall_member` | `V8.FormEngine.GetFormData('mall_member', {...})` |
235
- | POST `/api/formengine/uptformdata-mall_shopping_cart` | `V8.FormEngine.UptFormData('mall_shopping_cart', {...})` |
236
-
237
- > 客户端 HTTP 调用**会**触发 `SubmitBeforeServerV8`、`SubmitAfterServerV8`、`DataFilterV8` 等服务端事件;
238
- > 而 V8 引擎内调用 `V8.FormEngine.*` 默认**不**触发,除非显式传 `_InvokeType:'Client'`。`_InvokeType` 只影响事件语义,不授予任何客户端表权限。
1
+ ---
2
+ name: v8-formengine-http
3
+ description: 移动端 / 外部系统通过 HTTP 直接调用 Microi FormEngine(GetTableData / GetFormData / Add / Upt / Del)的 RESTful 路由约定与排错指南
4
+ ---
5
+
6
+ > **Microi吾码基础规范(强制):** 任何 AI 模型与宿主每次新建或接续吾码任务,先完整读取 `../workspace-conventions/SKILL.md`,必须执行版本播报、`@microi.net/cli` 后台自动升级、Skills/MCP 同步和进度播报。安装与诊断读取 `../microi-codex-installer/SKILL.md`;更新失败延后重试,不阻断当前工作。
7
+
8
+ # FormEngine HTTP 路由约定(外部系统调用)
9
+
10
+ > 适用于:uni-app H5、原生 App、Postman、第三方系统、Playwright/Cypress 自动化测试等任何**没有进入 V8 引擎**的客户端。
11
+ > 不适用于:服务器端 V8 接口引擎内部 — 那种情况请直接 `V8.FormEngine.GetTableData(...)`。
12
+
13
+ ## ⚠️ 最常见错误
14
+
15
+ ```text
16
+ ❌ POST /formengine/{表名}/gettabledata → 404
17
+ ❌ POST /api/formengine/{表名}/gettabledata → 404
18
+ ✅ POST /api/formengine/gettabledata-{表名} → OK (动态短路由)
19
+ ✅ POST /api/formengine/GetTableData body 中带 FormEngineKey → OK (标准路由)
20
+ ```
21
+
22
+ 平台路由由 `Microi.Server/Microi.net.Api/Handler/DynamicApiEngine.cs` 的 `FormEngineRoutes` 字典决定,**只认上面两种形式**。
23
+
24
+ ## 路由总表
25
+
26
+ ### 形式一:标准 Controller 路由 — 推荐
27
+ 全部为 `POST`,URL 不含表名,`FormEngineKey` 放在 Body 中。
28
+
29
+ | URL | 动作 |
30
+ | --- | --- |
31
+ | `/api/formengine/GetFormData` | 取一条 |
32
+ | `/api/formengine/GetTableData` | 取列表(分页) |
33
+ | `/api/formengine/AddFormData` | 新增 |
34
+ | `/api/formengine/UptFormData` | 按 Id 修改 |
35
+ | `/api/formengine/UptFormDataByWhere` | 按 _Where 批量改 |
36
+ | `/api/formengine/DelFormData` | 删除(Id / Ids) |
37
+ | `/api/formengine/DelFormDataByWhere` | 按 _Where 批量删 |
38
+ | `/api/formengine/GetFormDataAnonymous` | 匿名取一条 |
39
+ | `/api/formengine/GetTableDataAnonymous` | 匿名取列表 |
40
+ | `/api/formengine/AddFormDataAnonymous` | 匿名新增 |
41
+
42
+ ### 形式二:动态短路由(表名写进 URL,URL-friendly)
43
+ | URL 前缀 | 等价于 |
44
+ | --- | --- |
45
+ | `/api/formengine/getformdata-{table}` | `/api/formengine/GetFormData` |
46
+ | `/api/formengine/get-formdata-{table}` | `/api/formengine/GetFormData` |
47
+ | `/api/formengine/gettabledata-{table}` | `/api/formengine/GetTableData` |
48
+ | `/api/formengine/get-tabledata-{table}` | `/api/formengine/GetTableData` |
49
+ | `/api/formengine/addformdata-{table}` | `/api/formengine/AddFormData` |
50
+ | `/api/formengine/add-formdata-{table}` | `/api/formengine/AddFormData` |
51
+ | `/api/formengine/uptformdata-{table}` | `/api/formengine/UptFormData` |
52
+ | `/api/formengine/upt-formdata-{table}` | `/api/formengine/UptFormData` |
53
+ | `/api/formengine/delformdata-{table}` | `/api/formengine/DelFormData` |
54
+ | `/api/formengine/del-formdata-{table}` | `/api/formengine/DelFormData` |
55
+
56
+ URL 中的表名小写最稳,平台不区分大小写。匿名版本目前**只在形式一上有**(`GetTableDataAnonymous` 等)。
57
+
58
+ ## 请求 Header
59
+
60
+ | Header | 是否必填 | 说明 |
61
+ | --- | --- | --- |
62
+ | `Content-Type` | 必填 | `application/json` 推荐 |
63
+ | `OsClient` | 必填 | 租户标识;亦可放 querystring `?OsClient=xxx` 或 body |
64
+ | `authorization` | 鉴权接口必填 | `Bearer <Token>`;兼容旧客户端的 `Token` Header |
65
+ | `did` | 登录及鉴权接口推荐 | 当前终端稳定设备标识;首次生成后持久化,不能每次请求随机变化 |
66
+
67
+ 注意:上表是 FormEngine 路由约定。ApiEngine HTTP 复测和移动端 `callEngine` 使用稳定路径 `/apiengine/{key}`,租户通过唯一的 `osclient` Header 传递,JSON/Form Body 可冗余携带 `OsClient`。普通 POST/PUT/PATCH/DELETE 禁止追加 `--OsClient--...--`;特殊路径只用于无法设置 Header/Form/Query 的 GET/HEAD 或第三方回调。
68
+
69
+ 平台可能通过响应 Header `authorization`(兼容 `token`)续签或替换 Token。客户端必须立即保存新 Token,并保证并发旧响应不能覆盖已经写入的新 Token。跨域部署还必须在 CORS 中暴露 `authorization`、`token` 等需要读取的响应 Header。Token 属于凭据,禁止写入 URL、日志、错误上报和页面源码。
70
+
71
+ ## FormEngine 数据授权边界
72
+
73
+ “Token 有效”只代表身份有效,不代表可以访问任意表。客户端 FormEngine CRUD 还会经过表、菜单、角色和行级范围授权:
74
+
75
+ 1. 受保护的平台敏感表优先拒绝普通用户;匿名接口也不能绕过。
76
+ 2. 标准菜单页应携带真实 `_SysMenuId`,或使用 `ModuleEngineKey`。服务器会严格校验该菜单是否绑定目标表、当前角色是否拥有菜单及对应操作权限;列表、计数、导出追加该菜单的数据范围。
77
+ 3. 列表、写入、导入、导出显式传错 `_SysMenuId` / `ModuleEngineKey` 会直接拒绝,不会降级为其它菜单或表权限。单行详情只要当前角色拥有至少一个直接绑定同表的菜单(或精确表级 `Read` 权限)即可读取,不应用菜单 `SqlWhere` / `SqlJoin`;旧客户端携带过期菜单 Id 时也按该规则恢复。
78
+ 4. 为兼容历史前端 V8/外部客户端,普通 CRUD 未传菜单上下文时,服务器会从当前用户的版本化授权缓存中查找“当前角色已获授权且直接绑定目标表”的菜单。无菜单列表仍安全合并候选菜单的数据范围,不能靠漏参绕过;详情按同表菜单访问,写入按 `Add/Edit/Del` 动作权限。也可以使用角色的精确表级 `Read/Add/Edit/Del` 授权。`JoinTables` 不是独立访问授权。
79
+ 5. 导入、导出必须锚定具体菜单,不能依赖无菜单兼容推断。
80
+ 6. `TableChild` 子表委托由标准表单运行时生成 `_TableChildAuth`,服务器重新校验父菜单、父记录、字段绑定、子表和外键,并强制父子范围。它是内部不透明上下文,外部客户端不要手工拼装。
81
+ 7. `_InvokeType:'Client'` 只决定是否执行客户端语义的表单事件,不是权限开关。可信服务器调用标记也不能通过 HTTP Body 伪造。
82
+
83
+ 因此:
84
+
85
+ - 标准模块、详情页和其字段元数据请求优先传真实 `_SysMenuId`,使服务器确定菜单绑定与操作权限;其中只有列表、计数、导出应用菜单查询范围。
86
+ - 历史无 `_SysMenuId` 请求可继续工作,但前提是当前用户确实拥有目标表对应的菜单或精确表权限;不能把兼容推断理解为“有 Token 即可查表”。
87
+ - 历史单表字段请求可在菜单缺失/过期时回退到当前角色另一个引用同表的已授权菜单;`GetDiyFieldByDiyTables` 批量字段请求按“第一张主表必须授权、后续表逐张授权并过滤”兼容。后续未授权/保护表不会导致主表失败,也不会返回其字段配置;这些规则不授予数据行权限。
88
+ - 表单设计器 `/api/DiyField/UptDiyFieldList` 属于 `Level >= 9999` 控制面:外层一次授权、字段归属校验、同事务批量更新、批次末一次缓存/版本刷新。禁止在 100+ 字段循环中逐条调用完整 `UptFormDataAsync("diy_field", ...)`,否则会重复执行授权、V8、日志及 SaaS/Redis 缓存工作。
89
+ - 接口引擎内的 `V8.FormEngine.*` 属于服务器端调用,不要求客户端 `_SysMenuId`。但接口引擎本身必须正确限制谁能调用,并在服务端校验业务对象范围,不能把表名和条件原样交给不可信客户端。
90
+ - 客户端新增、修改、删除分别校验真实菜单的 `Add`、`Edit`、`Del` 权限。`SqlWhere` / `SqlJoin` 是模块查询过滤,不是行级写权限:不得把它们追加到写入 SQL,也不得因查询包含 Join 拒绝已获授权的主表写入。
91
+ - 进入 `SubmitBeforeServerV8` / `SubmitAfterServerV8` 后,事件内 FormEngine/数据库调用与接口引擎一样属于可信服务器执行,可实现当前租户内的跨表事务。需要“只能修改本人数据”等业务约束以及归属字段写入时,应在这里或专用接口引擎中完成。
92
+
93
+ ## 原生详情关联数据
94
+
95
+ - `POST /api/FormEngine/GetFormRelatedData` 接收父表 `ParentFormEngineKey`、父记录
96
+ `ParentTableRowId`、真实 `_SysMenuId`,以及固定 `RelatedType`:
97
+ `Counts/DataLog/DataComment/DataVersion`。身份、租户来自 DiyToken,不能透传请求的可信标记。
98
+ - `AuthorizeClientTableOperationAsync(..., 'Read')` 仅完成表/菜单授权,不证明父行可读。
99
+ 必须再执行 Client `GetFormDataAsync`,让父记录不存在或 `ServerDataV8` 拒绝阻断关联查询。
100
+ - 固定辅助表查询使用服务端新构造的 CLR 参数与可信来源;`JObject` 中写
101
+ `_InvokeType:'Server'` 仍是非可信参数。不得通过给普通角色开放辅助表权限来修复此类拒绝。
102
+ - 日志和版本返回固定元信息,`DataAppend.HistoryContentMode='MetadataOnly'`;
103
+ 当前行脱敏不授予历史 `Content/Data` 原文。客户端不能据元信息开放预览、对比、加载。
104
+ - 评论必须同时按真实 `TableId + TableRowId` 过滤。缺少 `TableId` 时,Counts 返回
105
+ `DataComment=null`,以 `DataAppend.DataCommentUnavailableReason/Message` 显式说明;
106
+ 评论详情失败。不能按单键兼容、猜旧数据归属、假报零条或承诺不存在的可用升级包。
107
+ - 回归须区分实际 HTTP 与替身组件测试:普通角色父行可读、同菜单另一归属被 DataFilter
108
+ 拒绝、父 Id 不存在、同 Id 不同表、伪造租户/类型/可信标记、历史敏感原文不返回都需验收。
109
+ 安全评论绑定写入及旧数据处理须独立交付后才能宣称评论完整可用。
110
+
111
+ ## Body 结构(POST JSON)
112
+
113
+ ```jsonc
114
+ {
115
+ "OsClient": "demo",
116
+ "FormEngineKey": "mall_product", // 形式一必填;形式二可选(已在 URL 中)
117
+ "_SysMenuId": "目标菜单Id", // 标准模块推荐;必须是真实绑定目标表且当前角色有权访问的菜单
118
+ "_Where": [["Status","=","OnSale"], ["AND","Stock",">",0]],
119
+ "_SelectFields": ["Id","Title","CurrentPrice","MainImg"],
120
+ "_OrderBy": "SoldCount",
121
+ "_OrderByType": "DESC",
122
+ "_PageIndex": 1,
123
+ "_PageSize": 20
124
+ }
125
+ ```
126
+
127
+ 写操作(Add/Upt)将业务字段平铺到 body:
128
+ ```jsonc
129
+ { "OsClient":"demo", "FormEngineKey":"biz_order",
130
+ "Id":"01ABC...", "Quantity": 2, "Selected": 1 }
131
+ ```
132
+
133
+ ## 响应 DosResult 标准格式
134
+
135
+ ```jsonc
136
+ { "Code": 1, "Data": [...], "DataCount": 123, "Msg": "" }
137
+ ```
138
+ | Code | 含义 |
139
+ | --- | --- |
140
+ | 1 | 成功 |
141
+ | 0 | 业务失败(看 `Msg`) |
142
+ | 1001 | 登录身份已过期 / Token 无效 |
143
+ | 1002 | 身份验证失败(OsClient 与 Token 不匹配) |
144
+
145
+ ## 客户端封装样板(uni-app)
146
+
147
+ ```javascript
148
+ const BASE = 'https://api.itdos.com';
149
+ const OS_CLIENT = runtimeConfig.osClient;
150
+ const TOKEN_KEY = 'mall_token';
151
+ const DID_KEY = 'mall_did';
152
+
153
+ function normalizeToken(value) {
154
+ return String(value || '').replace(/^Bearer\s+/i, '').trim();
155
+ }
156
+ function getToken() {
157
+ return normalizeToken(uni.getStorageSync(TOKEN_KEY));
158
+ }
159
+ function getDid() {
160
+ let did = uni.getStorageSync(DID_KEY);
161
+ if (!did) {
162
+ did = `uni-${Date.now()}-${Math.random().toString(36).slice(2)}`;
163
+ uni.setStorageSync(DID_KEY, did);
164
+ }
165
+ return did;
166
+ }
167
+ function readHeader(headers, name) {
168
+ const key = Object.keys(headers || {}).find(k => k.toLowerCase() === name);
169
+ return key ? headers[key] : '';
170
+ }
171
+ function applyResponseToken(headers, requestToken) {
172
+ const responseToken = normalizeToken(
173
+ readHeader(headers, 'authorization') || readHeader(headers, 'token')
174
+ );
175
+ if (!responseToken) return;
176
+
177
+ const currentToken = getToken();
178
+ // 旧请求若只回显旧 Token,不得覆盖其它请求/标签页已保存的新 Token。
179
+ if (currentToken && requestToken && currentToken !== requestToken && responseToken === requestToken) {
180
+ return;
181
+ }
182
+ uni.setStorageSync(TOKEN_KEY, responseToken);
183
+ }
184
+
185
+ function formEngineRequest(action, table, body = {}) {
186
+ return new Promise((resolve, reject) => {
187
+ const requestToken = getToken();
188
+ uni.request({
189
+ url: `${BASE}/api/formengine/${action}-${table}`,
190
+ method: 'POST',
191
+ header: {
192
+ 'Content-Type': 'application/json',
193
+ 'OsClient': OS_CLIENT,
194
+ 'authorization': requestToken ? `Bearer ${requestToken}` : '',
195
+ 'did': getDid()
196
+ },
197
+ data: { OsClient: OS_CLIENT, FormEngineKey: table, ...body },
198
+ success: (res) => {
199
+ applyResponseToken(res.header || res.headers, requestToken);
200
+ resolve(res.data || {});
201
+ },
202
+ fail: reject
203
+ });
204
+ });
205
+ }
206
+ export const formEngineGet = (t, w) => formEngineRequest('gettabledata', t, w);
207
+ export const formEngineGetOne = (t, w) => formEngineRequest('getformdata', t, w);
208
+ export const formEngineAdd = (t, d) => formEngineRequest('addformdata', t, d);
209
+ export const formEngineUpt = (t, d) => formEngineRequest('uptformdata', t, d);
210
+ export const formEngineDel = (t, d) => formEngineRequest('delformdata', t, d);
211
+ ```
212
+
213
+ ## 排错速查
214
+
215
+ | 现象 | 真实原因 |
216
+ | --- | --- |
217
+ | 404 Not Found | URL 缺 `/api/` 前缀,或表名/动作之间用 `/` 而不是 `-` |
218
+ | 405 Method Not Allowed | 用了 GET(FormEngine 全部为 POST) |
219
+ | 1001 登录身份已过期 | 没传 Token / Token 过期 / Redis 重启 |
220
+ | 1002 身份验证失败 | OsClient 不匹配 |
221
+ | `NoAuth` / `您没有权限做此操作` | Token 有效但菜单、表操作权限、表绑定角色、行级范围或敏感表策略不允许 |
222
+ | 显式传 `_SysMenuId` 后无权限 | 列表/写入使用错误菜单会严格拒绝;唯一详情在当前角色仍拥有另一个同表菜单时可恢复,不应用菜单查询范围 |
223
+ | 无 `_SysMenuId` 仍无权限 | 当前角色没有直接绑定该表的菜单授权,也没有精确表级授权 |
224
+ | 并发后提示 TokenReplaced / MissingToken | 客户端没有接收响应新 Token,或旧请求/其它标签页覆盖或清除了共享新 Token |
225
+ | Code:0 表不存在 | `FormEngineKey` 在 `diy_table` 不存在 |
226
+ | Code:0 字段不存在 | `_Where` / `_SelectFields` 写了表上没有的字段 |
227
+ | 返回 `null` 而不是 DosResult | Controller 抛了异常被吞,到后端日志看 `Microi.Core` 报错 |
228
+
229
+ ## 与服务器端 V8 的对照
230
+
231
+ | 客户端 HTTP 路由 | V8 内等价写法 |
232
+ | --- | --- |
233
+ | POST `/api/formengine/gettabledata-mall_product` | `V8.FormEngine.GetTableData('mall_product', {...})` |
234
+ | POST `/api/formengine/getformdata-mall_member` | `V8.FormEngine.GetFormData('mall_member', {...})` |
235
+ | POST `/api/formengine/uptformdata-mall_shopping_cart` | `V8.FormEngine.UptFormData('mall_shopping_cart', {...})` |
236
+
237
+ > 客户端 HTTP 调用**会**触发 `SubmitBeforeServerV8`、`SubmitAfterServerV8`、`DataFilterV8` 等服务端事件;
238
+ > 而 V8 引擎内调用 `V8.FormEngine.*` 默认**不**触发,除非显式传 `_InvokeType:'Client'`。`_InvokeType` 只影响事件语义,不授予任何客户端表权限。