@microi.net/cli 5.8.4 → 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 (212) 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 +7 -7
  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-server.js +5 -0
  17. package/scripts/mcp-trae-windows-launcher.cmd +21 -21
  18. package/scripts/microi-cli-mcp.js +7 -7
  19. package/scripts/microi-cli.js +67 -66
  20. package/scripts/microi-codex-broker.js +450 -450
  21. package/scripts/microi-codex-router.js +618 -582
  22. package/scripts/microi-skills.meta.json +384 -384
  23. package/skills/.microi-skills-version.json +2 -2
  24. package/skills/.progressive-disclosure-manifest.json +3566 -3566
  25. package/skills/README.md +287 -287
  26. package/skills/ai-engine/SKILL.md +269 -265
  27. package/skills/ai-engine/agents/openai.yaml +4 -4
  28. package/skills/ai-engine/references/ai-employees.md +48 -48
  29. package/skills/ai-engine/references/self-hosted-digital-human.md +59 -59
  30. package/skills/ai-platform-governance/SKILL.md +177 -177
  31. package/skills/ai-platform-governance/references/progressive-01-/345/212/237/350/203/275/345/274/200/345/205/263.md +190 -190
  32. package/skills/app-store/SKILL.md +525 -525
  33. package/skills/app-store/agents/openai.yaml +4 -4
  34. package/skills/business-blueprint/SKILL.md +193 -193
  35. package/skills/datasource-engine/SKILL.md +93 -93
  36. package/skills/datasource-engine/agents/openai.yaml +4 -4
  37. package/skills/dos-orm/SKILL.md +97 -97
  38. package/skills/dos-orm/references/api-reference.md +229 -229
  39. package/skills/email-engine/SKILL.md +81 -81
  40. package/skills/email-engine/references/v8-email.md +34 -34
  41. package/skills/job-engine/SKILL.md +176 -176
  42. package/skills/job-engine/agents/openai.yaml +4 -4
  43. package/skills/message-notification/SKILL.md +156 -156
  44. package/skills/message-notification/agents/openai.yaml +5 -5
  45. package/skills/message-notification/references/contracts.md +102 -102
  46. package/skills/microi/SKILL.md +14 -14
  47. package/skills/microi-ai-app-auth.js +652 -652
  48. package/skills/microi-ai-application/SKILL.md +115 -115
  49. package/skills/microi-ai-application/agents/openai.yaml +4 -4
  50. package/skills/microi-ai-application/references/frontend-baseline.md +164 -164
  51. package/skills/microi-client-frontend/SKILL.md +244 -244
  52. 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
  53. 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
  54. 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
  55. package/skills/microi-codex/SKILL.md +102 -100
  56. package/skills/microi-codex-installer/SKILL.md +231 -227
  57. package/skills/microi-codex-installer/agents/openai.yaml +7 -7
  58. package/skills/microi-datasource-mapping/SKILL.md +122 -122
  59. package/skills/microi-db-schema/SKILL.md +175 -175
  60. package/skills/microi-db-schema/agents/openai.yaml +4 -4
  61. package/skills/microi-db-schema/references/core-tables.md +695 -695
  62. package/skills/microi-db-schema/references/form-component-options.md +256 -256
  63. package/skills/microi-db-schema/references/schema-overview.md +202 -202
  64. package/skills/microi-db-schema/references/schema.md +646 -646
  65. package/skills/microi-db-schema/references/table-catalog.md +1599 -1599
  66. package/skills/microi-deployment/SKILL.md +221 -221
  67. package/skills/microi-deployment/references/deployment-matrix.md +109 -109
  68. package/skills/microi-docs-coverage/SKILL.md +133 -133
  69. package/skills/microi-docs-coverage/references/capability-map.md +91 -91
  70. package/skills/microi-docs-coverage/scripts/audit-doc-skill-coverage.mjs +894 -894
  71. package/skills/microi-form-engine/SKILL.md +333 -333
  72. package/skills/microi-form-engine/references/component-catalog.md +218 -218
  73. package/skills/microi-form-engine/references/data-source-events.md +124 -124
  74. package/skills/microi-form-layout/SKILL.md +205 -205
  75. 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
  76. package/skills/microi-frontend-sdk/SKILL.md +194 -194
  77. 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
  78. package/skills/microi-left-right-layout/SKILL.md +141 -141
  79. package/skills/microi-microservice/SKILL.md +326 -324
  80. package/skills/microi-microservice/references/runtime-delivery.md +278 -278
  81. package/skills/microi-mobile-app-quality/SKILL.md +185 -185
  82. 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
  83. 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
  84. package/skills/microi-solution-quotation/SKILL.md +78 -78
  85. package/skills/microi-solution-quotation/agents/openai.yaml +4 -4
  86. package/skills/microi-solution-quotation/scripts/build_solution_quote.py +296 -296
  87. package/skills/microi-sso/SKILL.md +92 -92
  88. package/skills/microi-sso/references/acceptance.md +49 -49
  89. package/skills/microi-sso/references/configuration-and-security.md +53 -53
  90. package/skills/microi-sso/references/inbound.md +53 -53
  91. package/skills/microi-sso/references/outbound.md +39 -39
  92. package/skills/microi-system-delivery/SKILL.md +137 -137
  93. 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
  94. 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
  95. package/skills/microi-ui/SKILL.md +192 -192
  96. 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
  97. package/skills/microi-uniapp-frontend/SKILL.md +193 -193
  98. 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
  99. 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
  100. package/skills/microi.v8.js +1921 -1921
  101. package/skills/module-engine/SKILL.md +255 -255
  102. package/skills/module-engine/references/module-config.md +204 -204
  103. package/skills/ocr-engine/SKILL.md +113 -113
  104. package/skills/ocr-engine/agents/openai.yaml +4 -4
  105. package/skills/page-engine/SKILL.md +206 -206
  106. package/skills/page-engine/examples/compact-dashboard.json +1444 -1444
  107. 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
  108. 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
  109. package/skills/performance-testing/SKILL.md +221 -221
  110. package/skills/playwright-e2e/SKILL.md +196 -196
  111. 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
  112. 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
  113. package/skills/playwright-e2e/references/progressive-03-microi-helper-/346/250/241/346/235/277.md +221 -221
  114. package/skills/playwright-e2e/references/progressive-04-ci-/345/273/272/350/256/256.md +115 -115
  115. package/skills/print-engine/SKILL.md +259 -259
  116. package/skills/production-readonly-audit/SKILL.md +41 -41
  117. package/skills/report-engine/SKILL.md +71 -71
  118. package/skills/report-engine/agents/openai.yaml +4 -4
  119. package/skills/scripts/optimize-progressive-disclosure.mjs +204 -204
  120. package/skills/scripts/refresh-progressive-disclosure.mjs +64 -64
  121. package/skills/scripts/sync-embedded-skills.mjs +46 -46
  122. package/skills/scripts/validate-progressive-disclosure.mjs +57 -57
  123. package/skills/search-engine/SKILL.md +75 -75
  124. package/skills/search-engine/agents/openai.yaml +4 -4
  125. package/skills/spider-engine/SKILL.md +190 -190
  126. package/skills/system-observability/SKILL.md +248 -248
  127. package/skills/system-observability/references/memory-incident-triage.md +77 -77
  128. package/skills/translate-engine/SKILL.md +140 -140
  129. package/skills/translate-engine/agents/openai.yaml +4 -4
  130. package/skills/ui-design/SKILL.md +223 -223
  131. package/skills/ui-design/assets/pattern-showcase/app.js +54 -54
  132. package/skills/ui-design/assets/pattern-showcase/index.html +163 -163
  133. package/skills/ui-design/assets/pattern-showcase/styles.css +311 -311
  134. package/skills/ui-design/assets/templates/MCI-DESIGN.md +206 -206
  135. package/skills/ui-design/references/design-pattern-library.md +184 -184
  136. package/skills/ui-design/references/mci-design-contract.md +163 -163
  137. package/skills/ui-design/references/motion-and-media.md +78 -78
  138. package/skills/ui-design/references/product-flow-recipes.md +94 -94
  139. 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
  140. package/skills/ui-design/references/progressive-02-/345/255/227/344/275/223.md +164 -164
  141. 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
  142. 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
  143. 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
  144. 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
  145. 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
  146. 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
  147. package/skills/uniapp-mall-assets/SKILL.md +176 -176
  148. package/skills/unity-integration/SKILL.md +171 -171
  149. package/skills/unity-integration/agents/openai.yaml +4 -4
  150. package/skills/unity-integration/references/ai-app-delivery.md +119 -119
  151. package/skills/unity-integration/references/sdk-api.md +82 -82
  152. package/skills/unity-integration/references/toolbox-migration.md +66 -66
  153. package/skills/unity-integration/references/webgl-hosting.md +57 -57
  154. package/skills/v8-api-config/SKILL.md +388 -388
  155. package/skills/v8-cache-pattern/SKILL.md +312 -312
  156. package/skills/v8-crud-api/SKILL.md +178 -178
  157. 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
  158. 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
  159. package/skills/v8-debugging/SKILL.md +284 -284
  160. package/skills/v8-explorer-tree/SKILL.md +228 -228
  161. package/skills/v8-export-import/SKILL.md +219 -219
  162. 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
  163. package/skills/v8-export-import/references/progressive-02-powerpoint-/345/257/274/345/207/272.md +202 -202
  164. 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
  165. package/skills/v8-file-upload/SKILL.md +284 -284
  166. 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
  167. 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
  168. package/skills/v8-formengine-http/SKILL.md +238 -238
  169. package/skills/v8-frontend-events/SKILL.md +180 -180
  170. package/skills/v8-frontend-events/references/bluetooth-print-api.md +135 -135
  171. package/skills/v8-frontend-events/references/bluetooth-print.md +258 -258
  172. package/skills/v8-frontend-events/references/progressive-01-/345/210/227/350/241/250/344/272/213/344/273/266.md +219 -219
  173. package/skills/v8-http-integration/SKILL.md +182 -182
  174. package/skills/v8-http-integration/references/progressive-01-get-/350/257/267/346/261/202.md +220 -220
  175. 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
  176. package/skills/v8-image-processing/SKILL.md +190 -190
  177. package/skills/v8-image-processing/agents/openai.yaml +4 -4
  178. package/skills/v8-image-processing/references/api-reference.md +623 -623
  179. package/skills/v8-menu-buttons/SKILL.md +186 -186
  180. 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
  181. 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
  182. 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
  183. package/skills/v8-mongodb/SKILL.md +200 -200
  184. package/skills/v8-mq-mqtt/SKILL.md +176 -176
  185. package/skills/v8-mq-mqtt/references/mqtt-production.md +342 -342
  186. package/skills/v8-mq-mqtt/references/progressive-01-v8-mqtt-iot-/347/211/251/350/201/224/347/275/221.md +181 -181
  187. package/skills/v8-mq-mqtt/scripts/check-mqtt-skill-coverage.mjs +203 -203
  188. package/skills/v8-saas-multi-tenant/SKILL.md +305 -305
  189. package/skills/v8-security/SKILL.md +210 -210
  190. package/skills/v8-security/references/progressive-01-2-/346/235/203/351/231/220/346/240/241/351/252/214.md +200 -200
  191. package/skills/v8-security/references/progressive-02-7-/346/227/245/345/277/227/350/256/260/345/275/225.md +160 -160
  192. package/skills/v8-sql-query/SKILL.md +302 -302
  193. package/skills/v8-table-event/SKILL.md +176 -176
  194. 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
  195. 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
  196. package/skills/v8-tcp-integration/SKILL.md +147 -147
  197. package/skills/v8-tcp-integration/agents/openai.yaml +4 -4
  198. package/skills/v8-template-engine/SKILL.md +167 -167
  199. package/skills/v8-utilities/SKILL.md +104 -104
  200. package/skills/v8-utilities/references/client-api-index.md +143 -143
  201. package/skills/v8-utilities/references/platform-http-routes.md +83 -83
  202. package/skills/v8-utilities/references/server-api-index.md +188 -188
  203. package/skills/v8-workflow/SKILL.md +252 -252
  204. 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
  205. package/skills/v8-workflow/references/workflow-configuration.md +49 -49
  206. package/skills/vision-engine/SKILL.md +160 -160
  207. package/skills/vision-engine/agents/openai.yaml +4 -4
  208. package/skills/vision-engine/references/architecture-and-acceptance.md +194 -194
  209. package/skills/workspace-conventions/SKILL.md +273 -270
  210. 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
  211. 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
  212. 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
- > **Codex 非阻塞自动更新:** 当前宿主为 Codex 时,吾码 CLI、Codex 插件与工作区 AI/MCP 由后台自动更新;需要诊断时读取 `../microi-codex-installer/SKILL.md`。更新失败、等待空闲或尚未重载均不得阻断当前、正在进行或新建任务。非 Codex 宿主跳过此项。
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` 只影响事件语义,不授予任何客户端表权限。