@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,161 +1,161 @@
1
- # v8-file-upload 详细参考 2
2
-
3
- > 按需读取;本文件由 SKILL.md 的原章节无损拆分。
4
-
5
- <!-- microi-progressive:chunk id=v8-file-upload-008 sha256=5dacdb706cc408a76a576da55c497756cd974819863162c6a50ad36504738051 -->
6
- ## Office 文件在线编辑版本号规则
7
-
8
- ### 文件柜 Office 版本
9
-
10
- 文件柜对象没有表单字段 JSON。`Microi.Client/src/views/file-manage/` 打开 Office 文件时传当前文件柜菜单、原始对象键和桶类型到 `/online-office`;后端 `GetFileCabinetOfficeMeta`、`SaveFileCabinetOfficeDocument` 每次重新校验管理员 DiyToken、权威文件柜菜单及原对象存在,绝不相信前端传来的版本路径或 `canEdit`。公有桶和私有桶都可编辑,历史快照及索引始终放在当前租户私有桶的 `.microi-office-history/<按桶及原键生成的摘要>/` 下,文件柜列表隐藏该内部目录。
11
-
12
- 文件柜初始版本为 `v1.0.0`;每次手动保存前先把当前字节归档为上一版本,再覆盖原对象键并持久化版本索引,版本依次递增。原对象键始终是最新版本,历史版本只读。用共享 Redis 租约串行保存并比较 `ExpectedVersion`;索引写入失败须恢复原对象,不能把未持久化索引的响应视为成功。历史版本预览用 `ResourceKind=FileManagerObject`、`ResourceId=历史快照键`、权威 `SysMenuId` 重新签发私有审计代理地址。修改文件柜对象移动/重命名/删除语义时,必须同时处理其版本索引与历史快照,防止索引失联或残留。
13
-
14
- MCP 只读发现使用 `microi_list_file_cabinet_objects(path, limit)` 与 `microi_get_file_cabinet_office_meta(filePathName, sysMenuId, limit)`;后者必须使用权威文件柜菜单 Id,普通用户和访问密钥无权调用。它们不下载文件字节,也不代表已发布新版本。整文件夹移动/重命名和跨平台文件同步不能视为 Office 历史迁移;迁移存储时需连同私有桶历史前缀一起处理,并回读原对象和历史版本。
15
-
16
- OnlyOffice 前端组件 npm 包不能替代 Docs 文档服务。`DocsAPI.DocEditor` 的同一存储版本必须使用稳定文档 key,避免每位用户生成不同 key 后失去协同;版本更新后 key 才应变化。Univer 开源包并不包含与现有链路等价的 Office 文件转换、协同服务和历史版本,不能直接加一个系统设置选项就声称切换完成。
17
-
18
- 当文件上传控件开启【Office 在线预览】、【允许在线编辑】和【开启 Office 文件版本号】时,前后端必须遵循统一版本规则:
19
-
20
- - 新上传的 Office 文件(`pdf/doc/docx/xls/xlsx/ppt/pptx`)要立即写入初始版本 `v1.0.0`,字段 JSON 的 `Path` 指向该原始文件,`Version` 为 `v1.0.0`,`Versions[0]` 保存同一份原始文件路径。
21
- - 用户进入 OnlyOffice 在线编辑页后,每次手动点击【保存文件】才生成新版本;第一次保存生成 `v1.0.1`,之后依次生成 `v1.0.2`、`v1.0.3`。
22
- - 未开启版本号时,保存文件直接覆盖当前 `Path` 对应的 HDFS/OSS 源文件。
23
- - 开启版本号时,保存文件必须生成带版本号后缀的新文件,例如 `contract_v1.0.1.docx`,字段 JSON 的 `Path` 指向最新版本,`Versions` 保留历史版本路径。
24
- - 在线 Office 路由和文件上传字段都要能读取 `Versions`,用于右上角切换历史版本预览/编辑。
25
-
26
- ### OnlyOffice 服务端取文件与匿名预览规则
27
-
28
- - OnlyOffice 文档服务器会在服务端再次下载文件。浏览器可以下载但 OnlyOffice 提示“下载失败”时,优先检查生成地址是否为 `localhost/127.0.0.1/内网域名`。
29
- - OnlyOffice 可能先对文档地址发起 `HEAD` 探测。响应文件接口除了 `GET 200`,还必须让 `HEAD` 返回相同的 `Content-Type/Content-Length/Content-Disposition`,不能返回 `405`。
30
- - 私有文件在线预览调用 `/apiengine/platform-private-file-url` 时传 `ForOfficePreview:true` 和权威资源上下文。审计代理应优先使用租户系统配置的公网 `ApiBase`,但仍把真实对象存储签名地址保存在共享 Redis ticket 中,禁止直接返回真实签名地址;旧 Controller 路由只作兼容转发。
31
- - `/online-office` 可以匿名访问。公有存储模式只允许当前 `OsClient` 目录下的 `filePathName`;接口模式通过 `fileUrl` 接收当前平台正式 `ApiBase`,或由同端口本地后端读取的 loopback `/apiengine/...` 响应文件地址,并要求 URL 显式携带当前 `OsClient`。两种模式都拒绝跨租户、路径穿越和任意第三方 URL;`isPrivate=1` 必须登录。
32
- - 匿名接口引擎预览不要求 V8 代码先上传 HDFS:接口开启【响应文件】和【允许匿名】后,完整地址 URL 编码传给 `fileUrl`,同时传 `fileName/fileType`。页面通过匿名安全中转让当前后端限域读取源文件,并以确定性路径缓存到当前租户公有对象存储;OnlyOffice 只接收公网 `FileServer` 地址。loopback 仅允许同端口本地后端访问,禁止开放任意 URL 代理。
33
- - `canEdit` 只是前端请求参数,不是权限。最终编辑条件必须是“有效登录态 && canEdit=true”;匿名始终只读,不能因 URL 参数放开编辑。
34
- - 匿名预览页隐藏左侧菜单、顶部导航和页签;已登录用户保持原系统布局。
35
- - 匿名导出响应接口应配置频率限制或保证生成逻辑足够轻量,不能让单个公网 URL 无界消耗 CPU/内存;如业务仍需要落盘缓存,缓存事实必须进入共享 Redis/HDFS,不能用进程内变量。
36
-
37
- 字段 JSON 示例:
38
-
39
- ```json
40
- {
41
- "Name": "contract.docx",
42
- "Path": "/tenant_demo/file/20260622/contract_v1.0.1.docx",
43
- "Version": "v1.0.1",
44
- "Versions": [
45
- { "Version": "v1.0.0", "Name": "contract.docx", "Path": "/tenant_demo/file/20260622/contract.docx", "IsLatest": false },
46
- { "Version": "v1.0.1", "Name": "contract_v1.0.1.docx", "Path": "/tenant_demo/file/20260622/contract_v1.0.1.docx", "IsLatest": true }
47
- ]
48
- }
49
- ```
50
-
51
- <!-- /microi-progressive:chunk -->
52
- <!-- microi-progressive:chunk id=v8-file-upload-009 sha256=fa3e980be41d5e1030b516f91ddaf5505917073936f08f919f34cad979b9b054 -->
53
- ## ImgUpload / FileUpload 字段值兼容规则
54
-
55
- `ImgUpload` 不能假设只是一种值结构。PC 表单、移动端、旧数据、单图/多图、公开/私有桶会混合出现以下格式:
56
-
57
- | 场景 | 可能的值 |
58
- |------|----------|
59
- | 空值/占位 | `''`、`null`、`undefined`、`'[]'`、`'null'`、`'正在上传中...'` |
60
- | 旧单图 | `'/upload/xxx/a.png'`、`'https://cdn/a.png'` |
61
- | 新单图 | `{ Path, Name, Size, Id, State }` 或 JSON 字符串 `'{"Path":"..."}'` |
62
- | 多图 | `[{ Path, Name, Id, State }]` 或 JSON 字符串 `'[{"Path":"..."}]'` |
63
- | 其它兼容字段 | `Path`、`FilePathName`、`FullPath`、`Url`、`url`、`src` |
64
-
65
- 任何端(PC、uni-app、H5、小程序)渲染图片前都必须先做“归一化 -> 取 Path -> 转最终 URL”,不要直接 `JSON.parse` 后只处理数组,也不要直接把字段值拼到 `FileServer`。
66
-
67
- 推荐归一化:
68
-
69
- ```javascript
70
- function normalizeUploadValue(value) {
71
- if (value == null || value === '' || value === 'undefined' || value === 'null') return [];
72
- if (value === '正在上传中...' || value === '[]' || value === '[ ]') return [];
73
-
74
- var raw = value;
75
- if (typeof raw === 'string') {
76
- var s = raw.trim();
77
- if ((s.indexOf('{') === 0 || s.indexOf('[') === 0)) {
78
- try { raw = JSON.parse(s); } catch (e) { raw = s; }
79
- } else {
80
- raw = s;
81
- }
82
- }
83
-
84
- if (Array.isArray(raw)) {
85
- return raw.map(normalizeUploadItem).filter(function (it) { return !!it.Path; });
86
- }
87
-
88
- var one = normalizeUploadItem(raw);
89
- return one.Path ? [one] : [];
90
- }
91
-
92
- function normalizeUploadItem(item) {
93
- if (!item) return {};
94
- if (typeof item === 'string') {
95
- return { Path: item, Name: item.split('/').pop() || item, State: 1 };
96
- }
97
- if (typeof item === 'object') {
98
- var path = item.Path || item.FilePathName || item.FullPath || item.Url || item.url || item.src || '';
99
- return {
100
- Id: item.Id || item.id || '',
101
- Name: item.Name || item.FileName || item.name || (path ? String(path).split('/').pop() : ''),
102
- Size: item.Size || item.size || '',
103
- CreateTime: item.CreateTime || item.createTime || '',
104
- State: item.State == null ? 1 : item.State,
105
- Path: path
106
- };
107
- }
108
- return {};
109
- }
110
- ```
111
-
112
- 公开图片 URL 解析原则与 `Microi.Client/src/utils/diy.common.js` 的 `GetServerPath` 一致:
113
-
114
- ```javascript
115
- function publicUploadUrl(path) {
116
- if (!path) return '';
117
- var s = String(path).trim();
118
- if (!s || s === '正在上传中...') return '';
119
- if (s.indexOf('.') === 0) return s; // ./static/img/loading.gif 等本地静态资源
120
- if (/^(https?:|data:|blob:)/i.test(s)) return s; // 已经是最终 URL
121
- if (s.indexOf('{') === 0 || s.indexOf('[') === 0) {
122
- var list = normalizeUploadValue(s);
123
- s = list.length ? list[0].Path : '';
124
- }
125
- if (!s) return '';
126
- return String(V8.SysConfig.FileServer || '').replace(/\/+$/, '') + '/' + s.replace(/^\/+/, '');
127
- }
128
- ```
129
-
130
- 私有桶(`Limit === true`)不要拼 `FileServer`,必须把归一化后的 `Path` 传给 `V8.Method.GetPrivateFileUrl({ FilePathName: path })` 或后端签名接口换临时 URL。
131
-
132
- 跨端保存时保留上传响应的实际 `Limit`(兼容布尔值、`1/0` 与对应字符串),只删除临时签名地址和本地预览状态。历史对象缺少该标记时按字段配置取址;已有私有标记优先于公有字段缺省值。单图字段兼容历史单元素数组,不应在字段值预处理阶段把数组直接清空。
133
-
134
- <!-- /microi-progressive:chunk -->
135
- <!-- microi-progressive:chunk id=v8-file-upload-010 sha256=f34d476435c3a8321df017b481771d757f580c8d75f7648fdd54ee1c624d116c -->
136
- ## 安全注意
137
-
138
- - ❌ 不要让前端任意指定 `Path`(路径穿越风险),只允许后端固定路径
139
- - ❌ 不要不校验文件类型 / 大小:根据 ContentType + 后缀双重校验
140
- - ❌ 不要把持有 Token 当成私有文件授权;普通用户必须证明菜单、记录和字段引用关系
141
- - ❌ 不要向普通角色开放文件列表、移动、重命名、删除、覆盖等管理接口;这些接口仅限 `Level >= 9999`
142
- - ❌ 不要开启 UEditor `catchimage` 远程抓图;默认关闭,确需采集时另建带域名白名单、DNS/IP 校验、禁止跳转、超时和响应上限的受控接口
143
- - ❌ 敏感文件(合同、身份证)必须用私有桶 `Limit: true`
144
- - ✅ 公有桶 URL 可缓存到前端,私有桶临时 URL 每次重新生成
145
- - ✅ 删除数据时同步清理 HDFS 文件(避免存储泄漏)
146
- - ✅ Excel/PDF 等导出文件通过【响应文件】配置返回,不要拼接到 JSON 数据里
147
-
148
- ### 安全升级兼容
149
-
150
- - 旧页面如果只传 `FilePathName` 获取私有地址,升级后普通帐号会失败;必须补齐 `FormEngineKey`、`FormDataId`、`FieldId`、`SysMenuId`,不能改回匿名或放开管理权限。
151
- - 旧自定义上传若依赖普通用户设置 `Limit:false` 或任意多级 `Path`,应改成私有上传;公开资源改走受控发布流程。
152
- - 历史公有文件不会自动变成私有文件。迁移时先复制对象、验证私有读取,再停止旧公有访问;数据库继续保存租户内相对路径,不能持久化临时 URL。
153
- - 上线验收至少覆盖:普通角色跨菜单/跨记录/跨字段读取被拒绝、单文件/单请求/数量限制、帐号与租户配额、Redis 故障失败关闭、多节点并发、公有匿名 `200`、私有匿名 `403`、授权私有访问 `200`。
154
-
155
- ### 复盘:ZIP 发布端与安装端 SHA256 口径不一致
156
-
157
- - 触发场景:应用包已成功生成 ZIP 和摘要,但安装端下载 ZIP 后调用不存在的哈希辅助函数,或尝试通过当前 V8 环境不可用的 `.NET SHA256.Create()` 校验,导致安装中断。
158
- - 根因:发布端实际使用 `V8.EncryptHelper.Sha256Hex(FileByteBase64)`,安装端却按原始字节设计了另一套实现,函数名称、输入数据和运行时能力均未对齐。
159
- - 通用规则:文件摘要必须在包清单中记录算法和输入口径;当前应用 ZIP 统一使用 `SHA256-Base64Text`,发布端与安装端都对同一份 Base64 文本调用 `V8.EncryptHelper.Sha256Hex`。禁止仅凭函数名推测算法,也不要在未验证 V8 互操作能力时直接实例化 `.NET` 加密对象。
160
- - 自动化检查:生成同时包含源码 ZIP、编译 ZIP 的应用包,再从官方地址下载并安装;分别篡改 Base64 文本和摘要,正常包应安装成功,两个篡改包都必须在解压前被拒绝。
161
- <!-- /microi-progressive:chunk -->
1
+ # v8-file-upload 详细参考 2
2
+
3
+ > 按需读取;本文件由 SKILL.md 的原章节无损拆分。
4
+
5
+ <!-- microi-progressive:chunk id=v8-file-upload-008 sha256=5dacdb706cc408a76a576da55c497756cd974819863162c6a50ad36504738051 -->
6
+ ## Office 文件在线编辑版本号规则
7
+
8
+ ### 文件柜 Office 版本
9
+
10
+ 文件柜对象没有表单字段 JSON。`Microi.Client/src/views/file-manage/` 打开 Office 文件时传当前文件柜菜单、原始对象键和桶类型到 `/online-office`;后端 `GetFileCabinetOfficeMeta`、`SaveFileCabinetOfficeDocument` 每次重新校验管理员 DiyToken、权威文件柜菜单及原对象存在,绝不相信前端传来的版本路径或 `canEdit`。公有桶和私有桶都可编辑,历史快照及索引始终放在当前租户私有桶的 `.microi-office-history/<按桶及原键生成的摘要>/` 下,文件柜列表隐藏该内部目录。
11
+
12
+ 文件柜初始版本为 `v1.0.0`;每次手动保存前先把当前字节归档为上一版本,再覆盖原对象键并持久化版本索引,版本依次递增。原对象键始终是最新版本,历史版本只读。用共享 Redis 租约串行保存并比较 `ExpectedVersion`;索引写入失败须恢复原对象,不能把未持久化索引的响应视为成功。历史版本预览用 `ResourceKind=FileManagerObject`、`ResourceId=历史快照键`、权威 `SysMenuId` 重新签发私有审计代理地址。修改文件柜对象移动/重命名/删除语义时,必须同时处理其版本索引与历史快照,防止索引失联或残留。
13
+
14
+ MCP 只读发现使用 `microi_list_file_cabinet_objects(path, limit)` 与 `microi_get_file_cabinet_office_meta(filePathName, sysMenuId, limit)`;后者必须使用权威文件柜菜单 Id,普通用户和访问密钥无权调用。它们不下载文件字节,也不代表已发布新版本。整文件夹移动/重命名和跨平台文件同步不能视为 Office 历史迁移;迁移存储时需连同私有桶历史前缀一起处理,并回读原对象和历史版本。
15
+
16
+ OnlyOffice 前端组件 npm 包不能替代 Docs 文档服务。`DocsAPI.DocEditor` 的同一存储版本必须使用稳定文档 key,避免每位用户生成不同 key 后失去协同;版本更新后 key 才应变化。Univer 开源包并不包含与现有链路等价的 Office 文件转换、协同服务和历史版本,不能直接加一个系统设置选项就声称切换完成。
17
+
18
+ 当文件上传控件开启【Office 在线预览】、【允许在线编辑】和【开启 Office 文件版本号】时,前后端必须遵循统一版本规则:
19
+
20
+ - 新上传的 Office 文件(`pdf/doc/docx/xls/xlsx/ppt/pptx`)要立即写入初始版本 `v1.0.0`,字段 JSON 的 `Path` 指向该原始文件,`Version` 为 `v1.0.0`,`Versions[0]` 保存同一份原始文件路径。
21
+ - 用户进入 OnlyOffice 在线编辑页后,每次手动点击【保存文件】才生成新版本;第一次保存生成 `v1.0.1`,之后依次生成 `v1.0.2`、`v1.0.3`。
22
+ - 未开启版本号时,保存文件直接覆盖当前 `Path` 对应的 HDFS/OSS 源文件。
23
+ - 开启版本号时,保存文件必须生成带版本号后缀的新文件,例如 `contract_v1.0.1.docx`,字段 JSON 的 `Path` 指向最新版本,`Versions` 保留历史版本路径。
24
+ - 在线 Office 路由和文件上传字段都要能读取 `Versions`,用于右上角切换历史版本预览/编辑。
25
+
26
+ ### OnlyOffice 服务端取文件与匿名预览规则
27
+
28
+ - OnlyOffice 文档服务器会在服务端再次下载文件。浏览器可以下载但 OnlyOffice 提示“下载失败”时,优先检查生成地址是否为 `localhost/127.0.0.1/内网域名`。
29
+ - OnlyOffice 可能先对文档地址发起 `HEAD` 探测。响应文件接口除了 `GET 200`,还必须让 `HEAD` 返回相同的 `Content-Type/Content-Length/Content-Disposition`,不能返回 `405`。
30
+ - 私有文件在线预览调用 `/apiengine/platform-private-file-url` 时传 `ForOfficePreview:true` 和权威资源上下文。审计代理应优先使用租户系统配置的公网 `ApiBase`,但仍把真实对象存储签名地址保存在共享 Redis ticket 中,禁止直接返回真实签名地址;旧 Controller 路由只作兼容转发。
31
+ - `/online-office` 可以匿名访问。公有存储模式只允许当前 `OsClient` 目录下的 `filePathName`;接口模式通过 `fileUrl` 接收当前平台正式 `ApiBase`,或由同端口本地后端读取的 loopback `/apiengine/...` 响应文件地址,并要求 URL 显式携带当前 `OsClient`。两种模式都拒绝跨租户、路径穿越和任意第三方 URL;`isPrivate=1` 必须登录。
32
+ - 匿名接口引擎预览不要求 V8 代码先上传 HDFS:接口开启【响应文件】和【允许匿名】后,完整地址 URL 编码传给 `fileUrl`,同时传 `fileName/fileType`。页面通过匿名安全中转让当前后端限域读取源文件,并以确定性路径缓存到当前租户公有对象存储;OnlyOffice 只接收公网 `FileServer` 地址。loopback 仅允许同端口本地后端访问,禁止开放任意 URL 代理。
33
+ - `canEdit` 只是前端请求参数,不是权限。最终编辑条件必须是“有效登录态 && canEdit=true”;匿名始终只读,不能因 URL 参数放开编辑。
34
+ - 匿名预览页隐藏左侧菜单、顶部导航和页签;已登录用户保持原系统布局。
35
+ - 匿名导出响应接口应配置频率限制或保证生成逻辑足够轻量,不能让单个公网 URL 无界消耗 CPU/内存;如业务仍需要落盘缓存,缓存事实必须进入共享 Redis/HDFS,不能用进程内变量。
36
+
37
+ 字段 JSON 示例:
38
+
39
+ ```json
40
+ {
41
+ "Name": "contract.docx",
42
+ "Path": "/tenant_demo/file/20260622/contract_v1.0.1.docx",
43
+ "Version": "v1.0.1",
44
+ "Versions": [
45
+ { "Version": "v1.0.0", "Name": "contract.docx", "Path": "/tenant_demo/file/20260622/contract.docx", "IsLatest": false },
46
+ { "Version": "v1.0.1", "Name": "contract_v1.0.1.docx", "Path": "/tenant_demo/file/20260622/contract_v1.0.1.docx", "IsLatest": true }
47
+ ]
48
+ }
49
+ ```
50
+
51
+ <!-- /microi-progressive:chunk -->
52
+ <!-- microi-progressive:chunk id=v8-file-upload-009 sha256=fa3e980be41d5e1030b516f91ddaf5505917073936f08f919f34cad979b9b054 -->
53
+ ## ImgUpload / FileUpload 字段值兼容规则
54
+
55
+ `ImgUpload` 不能假设只是一种值结构。PC 表单、移动端、旧数据、单图/多图、公开/私有桶会混合出现以下格式:
56
+
57
+ | 场景 | 可能的值 |
58
+ |------|----------|
59
+ | 空值/占位 | `''`、`null`、`undefined`、`'[]'`、`'null'`、`'正在上传中...'` |
60
+ | 旧单图 | `'/upload/xxx/a.png'`、`'https://cdn/a.png'` |
61
+ | 新单图 | `{ Path, Name, Size, Id, State }` 或 JSON 字符串 `'{"Path":"..."}'` |
62
+ | 多图 | `[{ Path, Name, Id, State }]` 或 JSON 字符串 `'[{"Path":"..."}]'` |
63
+ | 其它兼容字段 | `Path`、`FilePathName`、`FullPath`、`Url`、`url`、`src` |
64
+
65
+ 任何端(PC、uni-app、H5、小程序)渲染图片前都必须先做“归一化 -> 取 Path -> 转最终 URL”,不要直接 `JSON.parse` 后只处理数组,也不要直接把字段值拼到 `FileServer`。
66
+
67
+ 推荐归一化:
68
+
69
+ ```javascript
70
+ function normalizeUploadValue(value) {
71
+ if (value == null || value === '' || value === 'undefined' || value === 'null') return [];
72
+ if (value === '正在上传中...' || value === '[]' || value === '[ ]') return [];
73
+
74
+ var raw = value;
75
+ if (typeof raw === 'string') {
76
+ var s = raw.trim();
77
+ if ((s.indexOf('{') === 0 || s.indexOf('[') === 0)) {
78
+ try { raw = JSON.parse(s); } catch (e) { raw = s; }
79
+ } else {
80
+ raw = s;
81
+ }
82
+ }
83
+
84
+ if (Array.isArray(raw)) {
85
+ return raw.map(normalizeUploadItem).filter(function (it) { return !!it.Path; });
86
+ }
87
+
88
+ var one = normalizeUploadItem(raw);
89
+ return one.Path ? [one] : [];
90
+ }
91
+
92
+ function normalizeUploadItem(item) {
93
+ if (!item) return {};
94
+ if (typeof item === 'string') {
95
+ return { Path: item, Name: item.split('/').pop() || item, State: 1 };
96
+ }
97
+ if (typeof item === 'object') {
98
+ var path = item.Path || item.FilePathName || item.FullPath || item.Url || item.url || item.src || '';
99
+ return {
100
+ Id: item.Id || item.id || '',
101
+ Name: item.Name || item.FileName || item.name || (path ? String(path).split('/').pop() : ''),
102
+ Size: item.Size || item.size || '',
103
+ CreateTime: item.CreateTime || item.createTime || '',
104
+ State: item.State == null ? 1 : item.State,
105
+ Path: path
106
+ };
107
+ }
108
+ return {};
109
+ }
110
+ ```
111
+
112
+ 公开图片 URL 解析原则与 `Microi.Client/src/utils/diy.common.js` 的 `GetServerPath` 一致:
113
+
114
+ ```javascript
115
+ function publicUploadUrl(path) {
116
+ if (!path) return '';
117
+ var s = String(path).trim();
118
+ if (!s || s === '正在上传中...') return '';
119
+ if (s.indexOf('.') === 0) return s; // ./static/img/loading.gif 等本地静态资源
120
+ if (/^(https?:|data:|blob:)/i.test(s)) return s; // 已经是最终 URL
121
+ if (s.indexOf('{') === 0 || s.indexOf('[') === 0) {
122
+ var list = normalizeUploadValue(s);
123
+ s = list.length ? list[0].Path : '';
124
+ }
125
+ if (!s) return '';
126
+ return String(V8.SysConfig.FileServer || '').replace(/\/+$/, '') + '/' + s.replace(/^\/+/, '');
127
+ }
128
+ ```
129
+
130
+ 私有桶(`Limit === true`)不要拼 `FileServer`,必须把归一化后的 `Path` 传给 `V8.Method.GetPrivateFileUrl({ FilePathName: path })` 或后端签名接口换临时 URL。
131
+
132
+ 跨端保存时保留上传响应的实际 `Limit`(兼容布尔值、`1/0` 与对应字符串),只删除临时签名地址和本地预览状态。历史对象缺少该标记时按字段配置取址;已有私有标记优先于公有字段缺省值。单图字段兼容历史单元素数组,不应在字段值预处理阶段把数组直接清空。
133
+
134
+ <!-- /microi-progressive:chunk -->
135
+ <!-- microi-progressive:chunk id=v8-file-upload-010 sha256=f34d476435c3a8321df017b481771d757f580c8d75f7648fdd54ee1c624d116c -->
136
+ ## 安全注意
137
+
138
+ - ❌ 不要让前端任意指定 `Path`(路径穿越风险),只允许后端固定路径
139
+ - ❌ 不要不校验文件类型 / 大小:根据 ContentType + 后缀双重校验
140
+ - ❌ 不要把持有 Token 当成私有文件授权;普通用户必须证明菜单、记录和字段引用关系
141
+ - ❌ 不要向普通角色开放文件列表、移动、重命名、删除、覆盖等管理接口;这些接口仅限 `Level >= 9999`
142
+ - ❌ 不要开启 UEditor `catchimage` 远程抓图;默认关闭,确需采集时另建带域名白名单、DNS/IP 校验、禁止跳转、超时和响应上限的受控接口
143
+ - ❌ 敏感文件(合同、身份证)必须用私有桶 `Limit: true`
144
+ - ✅ 公有桶 URL 可缓存到前端,私有桶临时 URL 每次重新生成
145
+ - ✅ 删除数据时同步清理 HDFS 文件(避免存储泄漏)
146
+ - ✅ Excel/PDF 等导出文件通过【响应文件】配置返回,不要拼接到 JSON 数据里
147
+
148
+ ### 安全升级兼容
149
+
150
+ - 旧页面如果只传 `FilePathName` 获取私有地址,升级后普通帐号会失败;必须补齐 `FormEngineKey`、`FormDataId`、`FieldId`、`SysMenuId`,不能改回匿名或放开管理权限。
151
+ - 旧自定义上传若依赖普通用户设置 `Limit:false` 或任意多级 `Path`,应改成私有上传;公开资源改走受控发布流程。
152
+ - 历史公有文件不会自动变成私有文件。迁移时先复制对象、验证私有读取,再停止旧公有访问;数据库继续保存租户内相对路径,不能持久化临时 URL。
153
+ - 上线验收至少覆盖:普通角色跨菜单/跨记录/跨字段读取被拒绝、单文件/单请求/数量限制、帐号与租户配额、Redis 故障失败关闭、多节点并发、公有匿名 `200`、私有匿名 `403`、授权私有访问 `200`。
154
+
155
+ ### 复盘:ZIP 发布端与安装端 SHA256 口径不一致
156
+
157
+ - 触发场景:应用包已成功生成 ZIP 和摘要,但安装端下载 ZIP 后调用不存在的哈希辅助函数,或尝试通过当前 V8 环境不可用的 `.NET SHA256.Create()` 校验,导致安装中断。
158
+ - 根因:发布端实际使用 `V8.EncryptHelper.Sha256Hex(FileByteBase64)`,安装端却按原始字节设计了另一套实现,函数名称、输入数据和运行时能力均未对齐。
159
+ - 通用规则:文件摘要必须在包清单中记录算法和输入口径;当前应用 ZIP 统一使用 `SHA256-Base64Text`,发布端与安装端都对同一份 Base64 文本调用 `V8.EncryptHelper.Sha256Hex`。禁止仅凭函数名推测算法,也不要在未验证 V8 互操作能力时直接实例化 `.NET` 加密对象。
160
+ - 自动化检查:生成同时包含源码 ZIP、编译 ZIP 的应用包,再从官方地址下载并安装;分别篡改 Base64 文本和摘要,正常包应安装成功,两个篡改包都必须在解压前被拒绝。
161
+ <!-- /microi-progressive:chunk -->