@microi.net/cli 5.7.7 → 5.7.9

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 (191) 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/.workbuddy-plugin/marketplace.json +2 -2
  5. package/.workbuddy-plugin/plugin.json +1 -1
  6. package/LICENSE +21 -21
  7. package/README.md +71 -71
  8. package/assets/build-meta.json +6 -6
  9. package/assets/feature-matrix.json +138 -138
  10. package/assets/logo.svg +4 -4
  11. package/cordis.patch.yml +1 -1
  12. package/package.json +1 -1
  13. package/scripts/mcp-codex-stdio-adapter.js +0 -0
  14. package/scripts/mcp-server.js +102 -101
  15. package/scripts/microi-cli.js +57 -57
  16. package/scripts/microi-codex-broker.js +450 -450
  17. package/scripts/microi-codex-router.js +0 -0
  18. package/scripts/microi-skills.meta.json +366 -366
  19. package/skills/.microi-skills-version.json +2 -2
  20. package/skills/.progressive-disclosure-manifest.json +27 -27
  21. package/skills/README.md +286 -286
  22. package/skills/ai-engine/SKILL.md +265 -265
  23. package/skills/ai-engine/agents/openai.yaml +4 -4
  24. package/skills/ai-platform-governance/SKILL.md +177 -177
  25. package/skills/ai-platform-governance/references/progressive-01-/345/212/237/350/203/275/345/274/200/345/205/263.md +190 -190
  26. package/skills/app-store/SKILL.md +392 -396
  27. package/skills/app-store/agents/openai.yaml +4 -4
  28. package/skills/business-blueprint/SKILL.md +193 -193
  29. package/skills/datasource-engine/SKILL.md +90 -90
  30. package/skills/datasource-engine/agents/openai.yaml +4 -4
  31. package/skills/dos-orm/references/api-reference.md +229 -229
  32. package/skills/email-engine/SKILL.md +78 -78
  33. package/skills/email-engine/references/v8-email.md +34 -34
  34. package/skills/job-engine/SKILL.md +171 -172
  35. package/skills/job-engine/agents/openai.yaml +4 -4
  36. package/skills/message-notification/SKILL.md +155 -156
  37. package/skills/message-notification/agents/openai.yaml +5 -5
  38. package/skills/message-notification/references/contracts.md +102 -102
  39. package/skills/microi-ai-app-auth.js +652 -652
  40. package/skills/microi-ai-application/SKILL.md +102 -106
  41. package/skills/microi-ai-application/agents/openai.yaml +4 -4
  42. package/skills/microi-ai-application/references/frontend-baseline.md +164 -164
  43. package/skills/microi-client-frontend/SKILL.md +235 -240
  44. 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
  45. 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
  46. 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
  47. package/skills/microi-codex/SKILL.md +75 -75
  48. package/skills/microi-codex-installer/SKILL.md +225 -223
  49. package/skills/microi-codex-installer/agents/openai.yaml +7 -7
  50. package/skills/microi-datasource-mapping/SKILL.md +107 -111
  51. package/skills/microi-db-schema/SKILL.md +175 -175
  52. package/skills/microi-db-schema/agents/openai.yaml +4 -4
  53. package/skills/microi-db-schema/references/core-tables.md +695 -695
  54. package/skills/microi-db-schema/references/form-component-options.md +256 -256
  55. package/skills/microi-db-schema/references/schema-overview.md +202 -202
  56. package/skills/microi-db-schema/references/schema.md +646 -646
  57. package/skills/microi-db-schema/references/table-catalog.md +1599 -1599
  58. package/skills/microi-deployment/references/deployment-matrix.md +101 -101
  59. package/skills/microi-docs-coverage/references/capability-map.md +0 -1
  60. package/skills/microi-docs-coverage/scripts/audit-doc-skill-coverage.mjs +894 -894
  61. package/skills/microi-form-engine/SKILL.md +226 -226
  62. package/skills/microi-form-engine/references/component-catalog.md +216 -216
  63. package/skills/microi-form-engine/references/data-source-events.md +124 -124
  64. package/skills/microi-form-layout/SKILL.md +205 -205
  65. 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
  66. package/skills/microi-frontend-sdk/SKILL.md +188 -188
  67. 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
  68. package/skills/microi-left-right-layout/SKILL.md +141 -141
  69. package/skills/microi-microservice/SKILL.md +322 -323
  70. package/skills/microi-microservice/references/runtime-delivery.md +278 -278
  71. package/skills/microi-mobile-app-quality/SKILL.md +181 -181
  72. 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
  73. 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
  74. package/skills/microi-solution-quotation/SKILL.md +78 -78
  75. package/skills/microi-solution-quotation/agents/openai.yaml +4 -4
  76. package/skills/microi-solution-quotation/scripts/build_solution_quote.py +296 -296
  77. package/skills/microi-sso/references/acceptance.md +49 -49
  78. package/skills/microi-sso/references/configuration-and-security.md +53 -53
  79. package/skills/microi-sso/references/inbound.md +53 -53
  80. package/skills/microi-sso/references/outbound.md +39 -39
  81. package/skills/microi-system-delivery/SKILL.md +134 -134
  82. 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
  83. 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 +189 -189
  84. package/skills/microi-ui/SKILL.md +174 -174
  85. 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
  86. package/skills/microi-uniapp-frontend/SKILL.md +193 -193
  87. 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
  88. 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
  89. package/skills/microi.v8.js +1921 -1921
  90. package/skills/module-engine/SKILL.md +237 -250
  91. package/skills/module-engine/references/module-config.md +204 -204
  92. package/skills/ocr-engine/SKILL.md +113 -113
  93. package/skills/ocr-engine/agents/openai.yaml +4 -4
  94. package/skills/page-engine/SKILL.md +180 -191
  95. 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
  96. 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
  97. package/skills/performance-testing/SKILL.md +221 -221
  98. package/skills/playwright-e2e/SKILL.md +197 -197
  99. 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
  100. 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
  101. package/skills/playwright-e2e/references/progressive-03-microi-helper-/346/250/241/346/235/277.md +221 -221
  102. package/skills/playwright-e2e/references/progressive-04-ci-/345/273/272/350/256/256.md +115 -115
  103. package/skills/print-engine/SKILL.md +259 -259
  104. package/skills/production-readonly-audit/SKILL.md +41 -41
  105. package/skills/report-engine/SKILL.md +71 -71
  106. package/skills/report-engine/agents/openai.yaml +4 -4
  107. package/skills/scripts/optimize-progressive-disclosure.mjs +204 -204
  108. package/skills/scripts/refresh-progressive-disclosure.mjs +64 -64
  109. package/skills/search-engine/SKILL.md +75 -75
  110. package/skills/search-engine/agents/openai.yaml +4 -4
  111. package/skills/spider-engine/SKILL.md +190 -190
  112. package/skills/system-observability/SKILL.md +238 -238
  113. package/skills/system-observability/references/memory-incident-triage.md +70 -70
  114. package/skills/translate-engine/SKILL.md +140 -140
  115. package/skills/translate-engine/agents/openai.yaml +4 -4
  116. package/skills/ui-design/SKILL.md +191 -191
  117. package/skills/ui-design/assets/templates/MCI-DESIGN.md +198 -198
  118. package/skills/ui-design/references/design-pattern-library.md +184 -184
  119. package/skills/ui-design/references/mci-design-contract.md +163 -163
  120. 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
  121. package/skills/ui-design/references/progressive-02-/345/255/227/344/275/223.md +137 -137
  122. 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
  123. 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
  124. 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
  125. 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
  126. 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
  127. 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 +117 -117
  128. package/skills/uniapp-mall-assets/SKILL.md +176 -176
  129. package/skills/unity-integration/SKILL.md +155 -155
  130. package/skills/unity-integration/agents/openai.yaml +4 -4
  131. package/skills/unity-integration/references/ai-app-delivery.md +103 -103
  132. package/skills/unity-integration/references/sdk-api.md +82 -82
  133. package/skills/unity-integration/references/toolbox-migration.md +66 -66
  134. package/skills/unity-integration/references/webgl-hosting.md +57 -57
  135. package/skills/v8-cache-pattern/SKILL.md +306 -306
  136. package/skills/v8-crud-api/SKILL.md +175 -175
  137. 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
  138. 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
  139. package/skills/v8-debugging/SKILL.md +284 -284
  140. package/skills/v8-explorer-tree/SKILL.md +228 -228
  141. package/skills/v8-export-import/SKILL.md +209 -209
  142. 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
  143. package/skills/v8-export-import/references/progressive-02-powerpoint-/345/257/274/345/207/272.md +202 -202
  144. 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
  145. package/skills/v8-file-upload/SKILL.md +256 -263
  146. 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 +101 -101
  147. 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 +150 -150
  148. package/skills/v8-formengine-http/SKILL.md +219 -219
  149. package/skills/v8-frontend-events/SKILL.md +178 -178
  150. package/skills/v8-frontend-events/references/bluetooth-print-api.md +135 -135
  151. package/skills/v8-frontend-events/references/bluetooth-print.md +246 -246
  152. package/skills/v8-frontend-events/references/progressive-01-/345/210/227/350/241/250/344/272/213/344/273/266.md +219 -219
  153. package/skills/v8-http-integration/SKILL.md +182 -182
  154. package/skills/v8-http-integration/references/progressive-01-get-/350/257/267/346/261/202.md +220 -220
  155. 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
  156. package/skills/v8-image-processing/SKILL.md +190 -190
  157. package/skills/v8-image-processing/agents/openai.yaml +4 -4
  158. package/skills/v8-image-processing/references/api-reference.md +623 -623
  159. package/skills/v8-menu-buttons/SKILL.md +180 -180
  160. 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
  161. 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
  162. 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
  163. package/skills/v8-mongodb/SKILL.md +192 -192
  164. package/skills/v8-mq-mqtt/SKILL.md +175 -176
  165. package/skills/v8-mq-mqtt/references/mqtt-production.md +342 -342
  166. package/skills/v8-mq-mqtt/references/progressive-01-v8-mqtt-iot-/347/211/251/350/201/224/347/275/221.md +181 -181
  167. package/skills/v8-mq-mqtt/scripts/check-mqtt-skill-coverage.mjs +203 -203
  168. package/skills/v8-saas-multi-tenant/SKILL.md +219 -219
  169. package/skills/v8-security/SKILL.md +168 -168
  170. package/skills/v8-security/references/progressive-01-2-/346/235/203/351/231/220/346/240/241/351/252/214.md +198 -198
  171. package/skills/v8-security/references/progressive-02-7-/346/227/245/345/277/227/350/256/260/345/275/225.md +158 -158
  172. package/skills/v8-sql-query/SKILL.md +302 -302
  173. package/skills/v8-table-event/SKILL.md +144 -144
  174. 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 +197 -197
  175. 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
  176. package/skills/v8-tcp-integration/SKILL.md +147 -147
  177. package/skills/v8-tcp-integration/agents/openai.yaml +4 -4
  178. package/skills/v8-template-engine/SKILL.md +167 -167
  179. package/skills/v8-utilities/SKILL.md +90 -90
  180. package/skills/v8-utilities/references/client-api-index.md +143 -143
  181. package/skills/v8-utilities/references/platform-http-routes.md +83 -83
  182. package/skills/v8-utilities/references/server-api-index.md +188 -188
  183. package/skills/v8-workflow/SKILL.md +216 -243
  184. 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
  185. package/skills/vision-engine/SKILL.md +159 -159
  186. package/skills/vision-engine/agents/openai.yaml +4 -4
  187. package/skills/vision-engine/references/architecture-and-acceptance.md +194 -194
  188. package/skills/workspace-conventions/SKILL.md +261 -261
  189. 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 +208 -208
  190. 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 +216 -216
  191. 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,228 +1,228 @@
1
- # v8-menu-buttons 详细参考 2
2
-
3
- > 按需读取;本文件由 SKILL.md 的原章节无损拆分。
4
-
5
- <!-- microi-progressive:chunk id=v8-menu-buttons-008 sha256=8109ed4c7386f8cd1c89db1a8629962b26a448f68082abbb81c75277d5aa1843 -->
6
- ## 8. 模式 F:后台任务按钮(长任务)
7
-
8
- 应用安装、初始化多语言、批量导入、批量修复、跨系统同步等可能超过浏览器或网关等待时间的操作,必须优先设计为后台任务。判断阈值:预计超过 2 分钟、500 条以上、1000 个以上扇出子操作、100 次以上外部调用,或总量未知且可能持续运行。前端按钮只负责提交任务,后台任务列表通过 WebSocket/SignalR 推送并以轮询兜底。
9
-
10
- 少量数据也可能因为单次 V8 根执行的累计分配量过大而需要拆分。如果业务天然支持“每片独立事务提交、失败后按剩余量安全恢复”,按钮可以在前端发起多个独立 HTTP 请求,并声明客户端分片协议:
11
-
12
- ```jsonc
13
- {
14
- "Name": "批量生成主构件码",
15
- "Workload": {
16
- "ExecutionMode": "ClientChunked",
17
- "MaxItemsPerChunk": 40,
18
- "Resumable": true,
19
- "ExpectedItems": 200
20
- },
21
- "V8Code": "// 按 MaxItemsPerChunk 构造切片,并逐片 await V8.ApiEngine.Run(...)"
22
- }
23
- ```
24
-
25
- 逐条独立调用可使用 `ExecutionMode: "ClientSequential"` 和 `MaxItemsPerChunk: 1`。该声明必须与真实代码一致,且每片是新的 HTTP 请求;在同一次接口引擎调用中仅把大数组切成多个循环,不会重置 Jint 累计内存。缺少明确单片上限、不能恢复、预计总耗时超过 2 分钟或总量未知时,仍应使用后台任务和持久化检查点。
26
-
27
- 推荐直接使用按钮字段:
28
-
29
- ```jsonc
30
- {
31
- "Name": "安装",
32
- "BtnStyle": "primary",
33
- "ShowRow": true,
34
- "RunBackground": true,
35
- "ApiEngineKey": "import-microi-store-package",
36
- "Workload": { "ExpectedItems": 2000, "FanOutOperations": 10000, "ExpectedSeconds": 3000 },
37
- "BackgroundTaskOptions": {
38
- "IdempotencyKeyFields": ["Id", "Version"],
39
- "ConcurrencyKey": "microi-store-install",
40
- "BusinessTable": "sys_microistore",
41
- "BusinessStatusField": "TaskStatus",
42
- "BusinessTaskIdField": "BackgroundTaskId",
43
- "BusinessProgressField": "TaskProgress",
44
- "BusinessEtaField": "EstimatedEndTime"
45
- },
46
- "V8Code": "return { Package: V8.Form, _BackgroundTaskTitle: '安装应用:' + (V8.Form.Name || '') };"
47
- }
48
- ```
49
-
50
- 也可以在 V8Code 中显式调用:
51
-
52
- ```js
53
- V8.ApiEngine.RunBackground('import-microi-store-package', {
54
- Package: V8.Form
55
- }, '安装应用:' + (V8.Form.Name || ''), {
56
- IdempotencyKey: 'install:' + V8.Form.Id + ':' + (V8.Form.Version || ''),
57
- ConcurrencyKey: 'microi-store-install',
58
- BusinessTable: 'sys_microistore',
59
- BusinessId: V8.Form.Id,
60
- BusinessStatusField: 'TaskStatus',
61
- BusinessTaskIdField: 'BackgroundTaskId',
62
- BusinessProgressField: 'TaskProgress',
63
- BusinessEtaField: 'EstimatedEndTime'
64
- });
65
- ```
66
-
67
- `Business*` 字段用于业务关联与受权限保护的状态标记。按钮提交成功后,前端使用当前用户的 `V8.FormEngine` 权限写入“后台处理中”和任务 Id;通用后台服务不会信任客户端传来的任意表名/字段名去绕过权限。接口引擎应在成功、失败和取消补偿路径用固定业务表/字段更新最终状态,任务 Id 始终保留用于打开通知中心详情。
68
-
69
- 接口引擎中必须上报真实进度。平台创建后台任务时会自动把 `_BackgroundTaskId` 注入 `V8.Param`,V8 代码不要自己生成任务 Id,也不要只在结束时写一个固定百分比。
70
-
71
- ```js
72
- var backgroundTaskId = V8.Param._BackgroundTaskId || V8.Param.BackgroundTaskId || V8.Param.TaskId || '';
73
- var backgroundTask = V8.Param._BackgroundTask || {};
74
- if (backgroundTask.BusinessTable && backgroundTask.BusinessId) {
75
- var taskPatch = { Id: backgroundTask.BusinessId };
76
- taskPatch[backgroundTask.BusinessStatusField] = '后台处理中';
77
- taskPatch[backgroundTask.BusinessTaskIdField] = backgroundTaskId;
78
- V8.FormEngine.UptFormData(backgroundTask.BusinessTable, taskPatch);
79
- }
80
- var reportProgress = function(current, total, msg) {
81
- if (!backgroundTaskId || !V8.Method || !V8.Method.UpdateBackgroundTask) return;
82
- V8.Method.UpdateBackgroundTask({
83
- _BackgroundTaskId: backgroundTaskId,
84
- Current: current,
85
- Total: total,
86
- Msg: msg,
87
- Message: msg
88
- });
89
- };
90
-
91
- reportProgress(1, 5, '正在读取数据');
92
- // ...执行第 1 阶段
93
- reportProgress(2, 5, '正在写入表结构');
94
- // ...执行第 2 阶段
95
- ```
96
-
97
- 推荐用“已提交条数 / 总条数”上报 `Current/Total`,平台以共享数据库为事实源,Redis/SignalR 仅作缓存和推送,并根据真实吞吐估算结束时间。总量未知时只上报 `Current + Msg`,通知中心显示“计算进度中”,不要填写假的 `Total=100`。耗时循环中每提交一批数据调用一次,例如每 50 或 100 条更新;不能用计时器匀速增加百分比。
98
-
99
- 后台任务不能隐藏真实失败。失败时返回 `Code:0` 和清晰 `Msg`,并把关键阶段写入任务进度或系统日志。只有最终成功才显示 100%;失败/取消保留最后真实进度。
100
-
101
- 预计超过 10 分钟的任务必须分页/分片。每片只处理可在较短事务内提交的一批,仍有后续时返回 `Data.BackgroundTask.HasMore=true + Checkpoint + Current/Total`,平台持久化检查点并重新入队;最后一片返回普通 `Code:1`。重试副作用必须用稳定幂等键、数据库唯一约束和 `_BackgroundTaskFencingToken` 条件写入,不能依赖锁本身。
102
-
103
- 后台接口同时启用 `LockKey` 时,平台可信持久后台上下文会把接口 `Timeout` 作为单次 Redis 租期并按唯一持有者令牌自动续租;当前默认最长续租边界为 12 小时,显式配置得更长的单次租期不会被缩短。客户端自行传入 `_BackgroundTaskId`、`_TrustedServerInvocation` 或用户对象不能取得该能力。自动续租只防止正常长任务因短 TTL 自然过期,不能取消本节的检查点、幂等和 fencing token 要求。
104
-
105
- 持有者令牌不匹配、锁已过期、Redis 所有权/续租确认失败或达到最长租约时,任务必须失败关闭并保留最后真实进度与原始错误。V8 代码不得捕获“分布式锁租约已丢失”后返回 `Code:1`;旧执行者后续的业务条件写入必须因 `_BackgroundTaskFencingToken` 过期而被拒绝。完整配置语义见 `../../v8-api-config/SKILL.md`。
106
-
107
- ### 复盘:主租户默认值误清空子租户后台任务身份
108
-
109
- - 触发场景:同一套前后端中,独立部署的主租户可正常执行后台安装,挂在平台主库下的子租户却间歇性提示“只有超级管理员才能安装”;数据库中的 admin 实际已经是最高等级。
110
- - 根因:任务提交时虽然已从登录令牌保存可信用户快照,但后台线程脱离 HTTP 请求后再次调用 `GetCurrentToken()`,得到的只是服务默认主租户;普通接口的跨租户保护发现默认租户与任务 `OsClient` 不同,误把可信用户快照清空。线程是否赶在原请求上下文释放前运行还会造成偶发成功、偶发失败。
111
- - 通用规则:后台任务必须在提交阶段由服务端读取并克隆 `CurrentUser + OsClient`,通过不暴露给客户端/V8 的可信执行入口传给接口引擎;客户端参数中的 `_CurrentUser` 必须删除。普通 HTTP 接口继续执行跨租户身份清空,但不得用无真实 Token 的默认租户结果覆盖后台任务可信身份。
112
- - 自动化检查:使用“服务默认租户 A + 子租户 B”的部署配置,以 B 的超级管理员连续提交多次后台接口任务,并在原请求结束后才放行执行;断言每次 V8 的 `CurrentUser.Id/Level` 与提交者一致,同时验证携带 A Token 调用 B 普通接口仍会按匿名处理。
113
-
114
- ---
115
-
116
- <!-- /microi-progressive:chunk -->
117
- <!-- microi-progressive:chunk id=v8-menu-buttons-009 sha256=dc4cda219daf751e6943d1bc518776b67c15963cf7a9a5ebdfecaf6884aa89a0 -->
118
- ## 9. 通过 MCP 创建菜单 + 按钮(一次到位)
119
-
120
- > AI 在 `microi_create_module` 调用时,把按钮 JSON **作为字符串** 传入对应字段。
121
-
122
- ```js
123
- var moreBtns = [
124
- {
125
- Id: "01K...",
126
- Name: "指派",
127
- BtnStyle: "primary",
128
- IsVisible: true,
129
- ShowRow: true,
130
- V8CodeShow: "V8.Result = (V8.Form.Status == '待指派');",
131
- V8Code: `
132
- var assignResult = await V8.ApiEngine.Run({
133
- ApiEngineKey: "aftersale_assign",
134
- Id: V8.Form.Id,
135
- AssigneeId: V8.Form.AssigneeId
136
- });
137
-
138
- V8.Tips(assignResult.Code == 1 ? "指派成功" : assignResult.Msg, assignResult.Code == 1);
139
- V8.RefreshTable({ _PageIndex: 1 });
140
- `
141
- }
142
- ];
143
-
144
- var modulePayload = {
145
- name: "售后任务",
146
- diyTableId: "<TableId>",
147
- icon: "fab fa-first-order",
148
- moreBtns: JSON.stringify(moreBtns),
149
- formBtns: JSON.stringify([]),
150
- pageTabs: JSON.stringify([]),
151
- batchSelectMoreBtns: JSON.stringify([])
152
- };
153
- ```
154
-
155
- > ⚠️ 真实调用 `microi_create_module` 时传 `modulePayload.moreBtns` 这样的 JSON 字符串。不要为了“看起来短”把 `V8Code` 压成一行。
156
-
157
- ---
158
-
159
- <!-- /microi-progressive:chunk -->
160
- <!-- microi-progressive:chunk id=v8-menu-buttons-010 sha256=fd43cbb167733a5a722938f7c8c412b52999aa61ffe7b3016efc09a0e383dd41 -->
161
- ## 前端 FormEngine 权限与兼容
162
-
163
- - 当前按钮所在菜单绑定表会由 scoped facade 自动补真实 `_SysMenuId`,历史按钮不需要逐个修改。
164
- - 按钮跨表调用时不要把当前菜单 Id 传播给目标表;后端按当前用户对目标表的有效菜单权限缓存推断。
165
- - 显式 `_SysMenuId`/`ModuleEngineKey` 会严格校验,伪造或借用其它表菜单不会回退兼容推断。
166
- - 平台敏感表仍对普通客户端硬拒绝;Import/Export 必须走独立端点和专项菜单权限。
167
- - TableChild 的 `_TableChildAuth` 由标准子表自动维护,业务按钮不得构造或跨父记录复用。
168
- - 前端真实批量方法名是 `AddFormDataBatch/UptFormDataBatch/DelFormDataBatch`,没有 `AddTableData/UptTableData/DelTableData`。
169
- - 状态推进、资产、库存、审批、批量副作用等业务动作必须调用 ApiEngine;FormEngine 只适合权限范围内的简单单表 CRUD。
170
-
171
- ---
172
-
173
- <!-- /microi-progressive:chunk -->
174
- <!-- microi-progressive:chunk id=v8-menu-buttons-011 sha256=3e7e5f9faac605ca1c8e8eeb3d5aa8a2a5aabeb4716179955942bd243302c521 -->
175
- ## 10. 与接口引擎配套的工作流
176
-
177
- 业务按钮通常与接口引擎配套:
178
-
179
- 1. **microi_create_engine** 先创建 ApiEngineKey(如 `aftersale_assign`),写好后端事务/校验/通知逻辑
180
- 2. **microi_create_module** 创建菜单时把按钮的 `V8Code` 设为 `V8.ApiEngine.Run({ApiEngineKey:'aftersale_assign',...})`
181
- 3. AI 在生成菜单时**应主动**:
182
- - 识别业务动作(指派/接单/审核/完成/驳回/导出/批量处理/状态推进)
183
- - 为每个动作创建一个接口引擎
184
- - 在 `moreBtns` / `formBtns` 中绑定按钮 → 接口
185
-
186
- ---
187
-
188
- <!-- /microi-progressive:chunk -->
189
- <!-- microi-progressive:chunk id=v8-menu-buttons-012 sha256=4236db974612bd9eeeb35200c7e583a93e3dd17c72736e1674c9fb757698a550 -->
190
- ## 10.1 后台直充/调账类行按钮
191
-
192
- 会员积分、余额、库存、额度等会改动资产的后台行按钮,必须采用“前端按钮只收参数,后端接口负责事务”的模式。
193
-
194
- 规则:
195
- - `MoreBtns` 使用 `ShowRow:true`,按钮只负责 `V8.ConfirmTips` 弹窗、读取金额/备注、调用接口和刷新表格。
196
- - 不要在 `V8Code` 里直接写 `V8.FormEngine.UptFormData` 改余额;余额更新、订单/流水生成、幂等校验都放到 ApiEngine。
197
- - 后端接口必须校验 `MemberId/Amount`,金额必须大于 0,并同时写资产主表和对应流水表;如系统已有订单表参与统计,也要同步生成已完成/已支付订单。
198
- - 资产主表更新、`SELECT ... FOR UPDATE` 和流水写入必须全部使用同一个 `V8.DbTrans`;禁止一部分用 `V8.Db`、另一部分写流水,否则后半段报错时可能留下单边余额变化。
199
- - 备注字段要有默认值,例如 `平台直充积分`,并允许管理员在弹窗中修改。
200
- - 验证时至少做一次小额测试,读回主表余额、订单表和流水表;测试备注要明确标识,方便审计。
201
- - 还必须做一次回滚验收:故意让流水写入失败,回读资产主表确认余额完全未变,再修正输入完成成功验收。
202
-
203
- 按钮 V8Code 骨架。充值包含金额、备注、联动校验,属于可维护业务表单,应使用在线微服务页面,不要在 `ConfirmTips` 中拼接 `<input>/<textarea>`:
204
-
205
- ```js
206
- var row = V8.Form || {};
207
- V8.OpenAppDialog({
208
- AppKey: 'member_asset_admin',
209
- RoutePath: '/recharge',
210
- Title: '后台充值积分',
211
- Width: 'min(720px, calc(100vw - 32px))',
212
- Data: {
213
- MemberId: row.Id,
214
- MemberName: row.NickName || row.Phone || row.Id || ''
215
- },
216
- OnSuccess: function (result) {
217
- V8.Tips((result && result.message) || '充值成功', true);
218
- V8.RefreshTable({ _PageIndex: -1 });
219
- },
220
- OnError: function (error) {
221
- V8.Tips((error && error.message) || '充值失败', false);
222
- }
223
- });
224
- ```
225
-
226
- ---
227
-
228
- <!-- /microi-progressive:chunk -->
1
+ # v8-menu-buttons 详细参考 2
2
+
3
+ > 按需读取;本文件由 SKILL.md 的原章节无损拆分。
4
+
5
+ <!-- microi-progressive:chunk id=v8-menu-buttons-008 sha256=8109ed4c7386f8cd1c89db1a8629962b26a448f68082abbb81c75277d5aa1843 -->
6
+ ## 8. 模式 F:后台任务按钮(长任务)
7
+
8
+ 应用安装、初始化多语言、批量导入、批量修复、跨系统同步等可能超过浏览器或网关等待时间的操作,必须优先设计为后台任务。判断阈值:预计超过 2 分钟、500 条以上、1000 个以上扇出子操作、100 次以上外部调用,或总量未知且可能持续运行。前端按钮只负责提交任务,后台任务列表通过 WebSocket/SignalR 推送并以轮询兜底。
9
+
10
+ 少量数据也可能因为单次 V8 根执行的累计分配量过大而需要拆分。如果业务天然支持“每片独立事务提交、失败后按剩余量安全恢复”,按钮可以在前端发起多个独立 HTTP 请求,并声明客户端分片协议:
11
+
12
+ ```jsonc
13
+ {
14
+ "Name": "批量生成主构件码",
15
+ "Workload": {
16
+ "ExecutionMode": "ClientChunked",
17
+ "MaxItemsPerChunk": 40,
18
+ "Resumable": true,
19
+ "ExpectedItems": 200
20
+ },
21
+ "V8Code": "// 按 MaxItemsPerChunk 构造切片,并逐片 await V8.ApiEngine.Run(...)"
22
+ }
23
+ ```
24
+
25
+ 逐条独立调用可使用 `ExecutionMode: "ClientSequential"` 和 `MaxItemsPerChunk: 1`。该声明必须与真实代码一致,且每片是新的 HTTP 请求;在同一次接口引擎调用中仅把大数组切成多个循环,不会重置 Jint 累计内存。缺少明确单片上限、不能恢复、预计总耗时超过 2 分钟或总量未知时,仍应使用后台任务和持久化检查点。
26
+
27
+ 推荐直接使用按钮字段:
28
+
29
+ ```jsonc
30
+ {
31
+ "Name": "安装",
32
+ "BtnStyle": "primary",
33
+ "ShowRow": true,
34
+ "RunBackground": true,
35
+ "ApiEngineKey": "import-microi-store-package",
36
+ "Workload": { "ExpectedItems": 2000, "FanOutOperations": 10000, "ExpectedSeconds": 3000 },
37
+ "BackgroundTaskOptions": {
38
+ "IdempotencyKeyFields": ["Id", "Version"],
39
+ "ConcurrencyKey": "microi-store-install",
40
+ "BusinessTable": "sys_microistore",
41
+ "BusinessStatusField": "TaskStatus",
42
+ "BusinessTaskIdField": "BackgroundTaskId",
43
+ "BusinessProgressField": "TaskProgress",
44
+ "BusinessEtaField": "EstimatedEndTime"
45
+ },
46
+ "V8Code": "return { Package: V8.Form, _BackgroundTaskTitle: '安装应用:' + (V8.Form.Name || '') };"
47
+ }
48
+ ```
49
+
50
+ 也可以在 V8Code 中显式调用:
51
+
52
+ ```js
53
+ V8.ApiEngine.RunBackground('import-microi-store-package', {
54
+ Package: V8.Form
55
+ }, '安装应用:' + (V8.Form.Name || ''), {
56
+ IdempotencyKey: 'install:' + V8.Form.Id + ':' + (V8.Form.Version || ''),
57
+ ConcurrencyKey: 'microi-store-install',
58
+ BusinessTable: 'sys_microistore',
59
+ BusinessId: V8.Form.Id,
60
+ BusinessStatusField: 'TaskStatus',
61
+ BusinessTaskIdField: 'BackgroundTaskId',
62
+ BusinessProgressField: 'TaskProgress',
63
+ BusinessEtaField: 'EstimatedEndTime'
64
+ });
65
+ ```
66
+
67
+ `Business*` 字段用于业务关联与受权限保护的状态标记。按钮提交成功后,前端使用当前用户的 `V8.FormEngine` 权限写入“后台处理中”和任务 Id;通用后台服务不会信任客户端传来的任意表名/字段名去绕过权限。接口引擎应在成功、失败和取消补偿路径用固定业务表/字段更新最终状态,任务 Id 始终保留用于打开通知中心详情。
68
+
69
+ 接口引擎中必须上报真实进度。平台创建后台任务时会自动把 `_BackgroundTaskId` 注入 `V8.Param`,V8 代码不要自己生成任务 Id,也不要只在结束时写一个固定百分比。
70
+
71
+ ```js
72
+ var backgroundTaskId = V8.Param._BackgroundTaskId || V8.Param.BackgroundTaskId || V8.Param.TaskId || '';
73
+ var backgroundTask = V8.Param._BackgroundTask || {};
74
+ if (backgroundTask.BusinessTable && backgroundTask.BusinessId) {
75
+ var taskPatch = { Id: backgroundTask.BusinessId };
76
+ taskPatch[backgroundTask.BusinessStatusField] = '后台处理中';
77
+ taskPatch[backgroundTask.BusinessTaskIdField] = backgroundTaskId;
78
+ V8.FormEngine.UptFormData(backgroundTask.BusinessTable, taskPatch);
79
+ }
80
+ var reportProgress = function(current, total, msg) {
81
+ if (!backgroundTaskId || !V8.Method || !V8.Method.UpdateBackgroundTask) return;
82
+ V8.Method.UpdateBackgroundTask({
83
+ _BackgroundTaskId: backgroundTaskId,
84
+ Current: current,
85
+ Total: total,
86
+ Msg: msg,
87
+ Message: msg
88
+ });
89
+ };
90
+
91
+ reportProgress(1, 5, '正在读取数据');
92
+ // ...执行第 1 阶段
93
+ reportProgress(2, 5, '正在写入表结构');
94
+ // ...执行第 2 阶段
95
+ ```
96
+
97
+ 推荐用“已提交条数 / 总条数”上报 `Current/Total`,平台以共享数据库为事实源,Redis/SignalR 仅作缓存和推送,并根据真实吞吐估算结束时间。总量未知时只上报 `Current + Msg`,通知中心显示“计算进度中”,不要填写假的 `Total=100`。耗时循环中每提交一批数据调用一次,例如每 50 或 100 条更新;不能用计时器匀速增加百分比。
98
+
99
+ 后台任务不能隐藏真实失败。失败时返回 `Code:0` 和清晰 `Msg`,并把关键阶段写入任务进度或系统日志。只有最终成功才显示 100%;失败/取消保留最后真实进度。
100
+
101
+ 预计超过 10 分钟的任务必须分页/分片。每片只处理可在较短事务内提交的一批,仍有后续时返回 `Data.BackgroundTask.HasMore=true + Checkpoint + Current/Total`,平台持久化检查点并重新入队;最后一片返回普通 `Code:1`。重试副作用必须用稳定幂等键、数据库唯一约束和 `_BackgroundTaskFencingToken` 条件写入,不能依赖锁本身。
102
+
103
+ 后台接口同时启用 `LockKey` 时,平台可信持久后台上下文会把接口 `Timeout` 作为单次 Redis 租期并按唯一持有者令牌自动续租;当前默认最长续租边界为 12 小时,显式配置得更长的单次租期不会被缩短。客户端自行传入 `_BackgroundTaskId`、`_TrustedServerInvocation` 或用户对象不能取得该能力。自动续租只防止正常长任务因短 TTL 自然过期,不能取消本节的检查点、幂等和 fencing token 要求。
104
+
105
+ 持有者令牌不匹配、锁已过期、Redis 所有权/续租确认失败或达到最长租约时,任务必须失败关闭并保留最后真实进度与原始错误。V8 代码不得捕获“分布式锁租约已丢失”后返回 `Code:1`;旧执行者后续的业务条件写入必须因 `_BackgroundTaskFencingToken` 过期而被拒绝。完整配置语义见 `../../v8-api-config/SKILL.md`。
106
+
107
+ ### 复盘:主租户默认值误清空子租户后台任务身份
108
+
109
+ - 触发场景:同一套前后端中,独立部署的主租户可正常执行后台安装,挂在平台主库下的子租户却间歇性提示“只有超级管理员才能安装”;数据库中的 admin 实际已经是最高等级。
110
+ - 根因:任务提交时虽然已从登录令牌保存可信用户快照,但后台线程脱离 HTTP 请求后再次调用 `GetCurrentToken()`,得到的只是服务默认主租户;普通接口的跨租户保护发现默认租户与任务 `OsClient` 不同,误把可信用户快照清空。线程是否赶在原请求上下文释放前运行还会造成偶发成功、偶发失败。
111
+ - 通用规则:后台任务必须在提交阶段由服务端读取并克隆 `CurrentUser + OsClient`,通过不暴露给客户端/V8 的可信执行入口传给接口引擎;客户端参数中的 `_CurrentUser` 必须删除。普通 HTTP 接口继续执行跨租户身份清空,但不得用无真实 Token 的默认租户结果覆盖后台任务可信身份。
112
+ - 自动化检查:使用“服务默认租户 A + 子租户 B”的部署配置,以 B 的超级管理员连续提交多次后台接口任务,并在原请求结束后才放行执行;断言每次 V8 的 `CurrentUser.Id/Level` 与提交者一致,同时验证携带 A Token 调用 B 普通接口仍会按匿名处理。
113
+
114
+ ---
115
+
116
+ <!-- /microi-progressive:chunk -->
117
+ <!-- microi-progressive:chunk id=v8-menu-buttons-009 sha256=dc4cda219daf751e6943d1bc518776b67c15963cf7a9a5ebdfecaf6884aa89a0 -->
118
+ ## 9. 通过 MCP 创建菜单 + 按钮(一次到位)
119
+
120
+ > AI 在 `microi_create_module` 调用时,把按钮 JSON **作为字符串** 传入对应字段。
121
+
122
+ ```js
123
+ var moreBtns = [
124
+ {
125
+ Id: "01K...",
126
+ Name: "指派",
127
+ BtnStyle: "primary",
128
+ IsVisible: true,
129
+ ShowRow: true,
130
+ V8CodeShow: "V8.Result = (V8.Form.Status == '待指派');",
131
+ V8Code: `
132
+ var assignResult = await V8.ApiEngine.Run({
133
+ ApiEngineKey: "aftersale_assign",
134
+ Id: V8.Form.Id,
135
+ AssigneeId: V8.Form.AssigneeId
136
+ });
137
+
138
+ V8.Tips(assignResult.Code == 1 ? "指派成功" : assignResult.Msg, assignResult.Code == 1);
139
+ V8.RefreshTable({ _PageIndex: 1 });
140
+ `
141
+ }
142
+ ];
143
+
144
+ var modulePayload = {
145
+ name: "售后任务",
146
+ diyTableId: "<TableId>",
147
+ icon: "fab fa-first-order",
148
+ moreBtns: JSON.stringify(moreBtns),
149
+ formBtns: JSON.stringify([]),
150
+ pageTabs: JSON.stringify([]),
151
+ batchSelectMoreBtns: JSON.stringify([])
152
+ };
153
+ ```
154
+
155
+ > ⚠️ 真实调用 `microi_create_module` 时传 `modulePayload.moreBtns` 这样的 JSON 字符串。不要为了“看起来短”把 `V8Code` 压成一行。
156
+
157
+ ---
158
+
159
+ <!-- /microi-progressive:chunk -->
160
+ <!-- microi-progressive:chunk id=v8-menu-buttons-010 sha256=fd43cbb167733a5a722938f7c8c412b52999aa61ffe7b3016efc09a0e383dd41 -->
161
+ ## 前端 FormEngine 权限与兼容
162
+
163
+ - 当前按钮所在菜单绑定表会由 scoped facade 自动补真实 `_SysMenuId`,历史按钮不需要逐个修改。
164
+ - 按钮跨表调用时不要把当前菜单 Id 传播给目标表;后端按当前用户对目标表的有效菜单权限缓存推断。
165
+ - 显式 `_SysMenuId`/`ModuleEngineKey` 会严格校验,伪造或借用其它表菜单不会回退兼容推断。
166
+ - 平台敏感表仍对普通客户端硬拒绝;Import/Export 必须走独立端点和专项菜单权限。
167
+ - TableChild 的 `_TableChildAuth` 由标准子表自动维护,业务按钮不得构造或跨父记录复用。
168
+ - 前端真实批量方法名是 `AddFormDataBatch/UptFormDataBatch/DelFormDataBatch`,没有 `AddTableData/UptTableData/DelTableData`。
169
+ - 状态推进、资产、库存、审批、批量副作用等业务动作必须调用 ApiEngine;FormEngine 只适合权限范围内的简单单表 CRUD。
170
+
171
+ ---
172
+
173
+ <!-- /microi-progressive:chunk -->
174
+ <!-- microi-progressive:chunk id=v8-menu-buttons-011 sha256=3e7e5f9faac605ca1c8e8eeb3d5aa8a2a5aabeb4716179955942bd243302c521 -->
175
+ ## 10. 与接口引擎配套的工作流
176
+
177
+ 业务按钮通常与接口引擎配套:
178
+
179
+ 1. **microi_create_engine** 先创建 ApiEngineKey(如 `aftersale_assign`),写好后端事务/校验/通知逻辑
180
+ 2. **microi_create_module** 创建菜单时把按钮的 `V8Code` 设为 `V8.ApiEngine.Run({ApiEngineKey:'aftersale_assign',...})`
181
+ 3. AI 在生成菜单时**应主动**:
182
+ - 识别业务动作(指派/接单/审核/完成/驳回/导出/批量处理/状态推进)
183
+ - 为每个动作创建一个接口引擎
184
+ - 在 `moreBtns` / `formBtns` 中绑定按钮 → 接口
185
+
186
+ ---
187
+
188
+ <!-- /microi-progressive:chunk -->
189
+ <!-- microi-progressive:chunk id=v8-menu-buttons-012 sha256=4236db974612bd9eeeb35200c7e583a93e3dd17c72736e1674c9fb757698a550 -->
190
+ ## 10.1 后台直充/调账类行按钮
191
+
192
+ 会员积分、余额、库存、额度等会改动资产的后台行按钮,必须采用“前端按钮只收参数,后端接口负责事务”的模式。
193
+
194
+ 规则:
195
+ - `MoreBtns` 使用 `ShowRow:true`,按钮只负责 `V8.ConfirmTips` 弹窗、读取金额/备注、调用接口和刷新表格。
196
+ - 不要在 `V8Code` 里直接写 `V8.FormEngine.UptFormData` 改余额;余额更新、订单/流水生成、幂等校验都放到 ApiEngine。
197
+ - 后端接口必须校验 `MemberId/Amount`,金额必须大于 0,并同时写资产主表和对应流水表;如系统已有订单表参与统计,也要同步生成已完成/已支付订单。
198
+ - 资产主表更新、`SELECT ... FOR UPDATE` 和流水写入必须全部使用同一个 `V8.DbTrans`;禁止一部分用 `V8.Db`、另一部分写流水,否则后半段报错时可能留下单边余额变化。
199
+ - 备注字段要有默认值,例如 `平台直充积分`,并允许管理员在弹窗中修改。
200
+ - 验证时至少做一次小额测试,读回主表余额、订单表和流水表;测试备注要明确标识,方便审计。
201
+ - 还必须做一次回滚验收:故意让流水写入失败,回读资产主表确认余额完全未变,再修正输入完成成功验收。
202
+
203
+ 按钮 V8Code 骨架。充值包含金额、备注、联动校验,属于可维护业务表单,应使用在线微服务页面,不要在 `ConfirmTips` 中拼接 `<input>/<textarea>`:
204
+
205
+ ```js
206
+ var row = V8.Form || {};
207
+ V8.OpenAppDialog({
208
+ AppKey: 'member_asset_admin',
209
+ RoutePath: '/recharge',
210
+ Title: '后台充值积分',
211
+ Width: 'min(720px, calc(100vw - 32px))',
212
+ Data: {
213
+ MemberId: row.Id,
214
+ MemberName: row.NickName || row.Phone || row.Id || ''
215
+ },
216
+ OnSuccess: function (result) {
217
+ V8.Tips((result && result.message) || '充值成功', true);
218
+ V8.RefreshTable({ _PageIndex: -1 });
219
+ },
220
+ OnError: function (error) {
221
+ V8.Tips((error && error.message) || '充值失败', false);
222
+ }
223
+ });
224
+ ```
225
+
226
+ ---
227
+
228
+ <!-- /microi-progressive:chunk -->