@microi.net/cli 5.5.9 → 5.6.1

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 (161) 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/assets/build-meta.json +5 -5
  7. package/cordis.patch.yml +1 -1
  8. package/package.json +1 -1
  9. package/scripts/mcp-server.js +99 -99
  10. package/scripts/microi-cli.js +39 -36
  11. package/scripts/microi-skills.meta.json +341 -338
  12. package/skills/.microi-skills-version.json +2 -2
  13. package/skills/.progressive-disclosure-manifest.json +3566 -3566
  14. package/skills/README.md +4 -4
  15. package/skills/ai-engine/SKILL.md +45 -45
  16. package/skills/ai-platform-governance/SKILL.md +177 -177
  17. package/skills/ai-platform-governance/references/progressive-01-/345/212/237/350/203/275/345/274/200/345/205/263.md +190 -190
  18. package/skills/app-store/SKILL.md +21 -4
  19. package/skills/business-blueprint/SKILL.md +85 -85
  20. package/skills/datasource-engine/SKILL.md +91 -91
  21. package/skills/dos-orm/SKILL.md +15 -0
  22. package/skills/dos-orm/references/api-reference.md +229 -229
  23. package/skills/email-engine/SKILL.md +80 -80
  24. package/skills/email-engine/references/v8-email.md +34 -34
  25. package/skills/job-engine/SKILL.md +154 -154
  26. package/skills/message-notification/SKILL.md +27 -1
  27. package/skills/message-notification/agents/openai.yaml +5 -5
  28. package/skills/message-notification/references/contracts.md +102 -102
  29. package/skills/microi-ai-app-auth.js +652 -652
  30. package/skills/microi-ai-application/SKILL.md +102 -102
  31. package/skills/microi-ai-application/agents/openai.yaml +4 -4
  32. package/skills/microi-ai-application/references/frontend-baseline.md +164 -164
  33. package/skills/microi-client-frontend/SKILL.md +47 -41
  34. 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 +4 -4
  35. 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 +30 -30
  36. 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 +58 -58
  37. package/skills/microi-codex/SKILL.md +2 -0
  38. package/skills/microi-codex-installer/SKILL.md +216 -216
  39. package/skills/microi-codex-installer/agents/openai.yaml +7 -7
  40. package/skills/microi-datasource-mapping/SKILL.md +67 -67
  41. package/skills/microi-db-schema/SKILL.md +6 -6
  42. package/skills/microi-db-schema/references/core-tables.md +18 -18
  43. package/skills/microi-db-schema/references/form-component-options.md +256 -256
  44. package/skills/microi-db-schema/references/schema-overview.md +11 -11
  45. package/skills/microi-db-schema/references/schema.md +46 -46
  46. package/skills/microi-db-schema/references/table-catalog.md +57 -57
  47. package/skills/microi-deployment/SKILL.md +18 -1
  48. package/skills/microi-deployment/references/deployment-matrix.md +101 -101
  49. package/skills/microi-docs-coverage/SKILL.md +10 -0
  50. package/skills/microi-docs-coverage/references/capability-map.md +3 -2
  51. package/skills/microi-docs-coverage/scripts/audit-doc-skill-coverage.mjs +894 -894
  52. package/skills/microi-form-engine/SKILL.md +27 -3
  53. package/skills/microi-form-engine/references/component-catalog.md +218 -218
  54. package/skills/microi-form-engine/references/data-source-events.md +124 -124
  55. package/skills/microi-form-layout/SKILL.md +13 -13
  56. 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
  57. package/skills/microi-frontend-sdk/SKILL.md +4 -4
  58. 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 +175 -175
  59. package/skills/microi-left-right-layout/SKILL.md +141 -141
  60. package/skills/microi-microservice/SKILL.md +2 -1
  61. package/skills/microi-microservice/references/runtime-delivery.md +278 -278
  62. 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
  63. package/skills/microi-solution-quotation/SKILL.md +78 -78
  64. package/skills/microi-solution-quotation/agents/openai.yaml +4 -4
  65. package/skills/microi-solution-quotation/scripts/build_solution_quote.py +296 -296
  66. package/skills/microi-sso/SKILL.md +6 -0
  67. package/skills/microi-sso/references/acceptance.md +49 -49
  68. package/skills/microi-sso/references/configuration-and-security.md +53 -53
  69. package/skills/microi-sso/references/inbound.md +53 -53
  70. package/skills/microi-sso/references/outbound.md +39 -39
  71. package/skills/microi-system-delivery/SKILL.md +5 -4
  72. 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 +7 -2
  73. package/skills/microi-ui/SKILL.md +7 -2
  74. package/skills/microi-uniapp-frontend/SKILL.md +134 -134
  75. 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 +136 -136
  76. 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 +124 -124
  77. package/skills/module-engine/SKILL.md +30 -14
  78. package/skills/ocr-engine/SKILL.md +2 -2
  79. package/skills/ocr-engine/agents/openai.yaml +1 -1
  80. package/skills/page-engine/SKILL.md +28 -28
  81. 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 +126 -126
  82. 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 +42 -42
  83. package/skills/performance-testing/SKILL.md +120 -120
  84. package/skills/playwright-e2e/SKILL.md +84 -84
  85. 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 +68 -68
  86. 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 +64 -64
  87. package/skills/playwright-e2e/references/progressive-03-microi-helper-/346/250/241/346/235/277.md +20 -20
  88. package/skills/playwright-e2e/references/progressive-04-ci-/345/273/272/350/256/256.md +69 -69
  89. package/skills/print-engine/SKILL.md +11 -3
  90. package/skills/production-readonly-audit/SKILL.md +41 -41
  91. package/skills/report-engine/SKILL.md +71 -71
  92. package/skills/scripts/optimize-progressive-disclosure.mjs +204 -204
  93. package/skills/scripts/refresh-progressive-disclosure.mjs +64 -64
  94. package/skills/scripts/sync-embedded-skills.mjs +46 -0
  95. package/skills/scripts/validate-progressive-disclosure.mjs +8 -3
  96. package/skills/search-engine/SKILL.md +75 -75
  97. package/skills/spider-engine/SKILL.md +190 -190
  98. package/skills/system-observability/SKILL.md +169 -157
  99. package/skills/system-observability/references/memory-incident-triage.md +73 -73
  100. package/skills/translate-engine/SKILL.md +1 -1
  101. package/skills/ui-design/SKILL.md +3 -1
  102. package/skills/uniapp-mall-assets/SKILL.md +170 -170
  103. package/skills/unity-integration/SKILL.md +155 -155
  104. package/skills/unity-integration/agents/openai.yaml +4 -4
  105. package/skills/unity-integration/references/ai-app-delivery.md +103 -103
  106. package/skills/unity-integration/references/sdk-api.md +82 -82
  107. package/skills/unity-integration/references/toolbox-migration.md +66 -66
  108. package/skills/unity-integration/references/webgl-hosting.md +57 -57
  109. package/skills/v8-api-config/SKILL.md +4 -0
  110. package/skills/v8-cache-pattern/SKILL.md +306 -306
  111. package/skills/v8-crud-api/SKILL.md +29 -29
  112. 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 +56 -56
  113. package/skills/v8-debugging/SKILL.md +143 -143
  114. package/skills/v8-explorer-tree/SKILL.md +64 -64
  115. 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 +201 -201
  116. package/skills/v8-export-import/references/progressive-02-powerpoint-/345/257/274/345/207/272.md +118 -118
  117. 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 +32 -32
  118. package/skills/v8-file-upload/SKILL.md +5 -2
  119. 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 +2 -2
  120. 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 +138 -138
  121. package/skills/v8-formengine-http/SKILL.md +126 -108
  122. package/skills/v8-frontend-events/SKILL.md +22 -22
  123. package/skills/v8-frontend-events/references/bluetooth-print-api.md +135 -135
  124. package/skills/v8-frontend-events/references/bluetooth-print.md +247 -247
  125. package/skills/v8-frontend-events/references/progressive-01-/345/210/227/350/241/250/344/272/213/344/273/266.md +50 -50
  126. package/skills/v8-http-integration/SKILL.md +106 -106
  127. package/skills/v8-http-integration/references/progressive-01-get-/350/257/267/346/261/202.md +31 -31
  128. 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 +5 -5
  129. package/skills/v8-image-processing/SKILL.md +190 -190
  130. package/skills/v8-image-processing/agents/openai.yaml +4 -4
  131. package/skills/v8-image-processing/references/api-reference.md +623 -623
  132. package/skills/v8-menu-buttons/SKILL.md +103 -103
  133. package/skills/v8-menu-buttons/references/progressive-01-2-/346/214/211/351/222/256/345/257/271/350/261/241-schema.md +145 -145
  134. 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
  135. 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 +43 -43
  136. package/skills/v8-mongodb/SKILL.md +65 -65
  137. package/skills/v8-mq-mqtt/SKILL.md +175 -175
  138. package/skills/v8-mq-mqtt/references/mqtt-production.md +342 -342
  139. package/skills/v8-mq-mqtt/references/progressive-01-v8-mqtt-iot-/347/211/251/350/201/224/347/275/221.md +137 -137
  140. package/skills/v8-mq-mqtt/scripts/check-mqtt-skill-coverage.mjs +203 -203
  141. package/skills/v8-saas-multi-tenant/SKILL.md +223 -223
  142. package/skills/v8-security/SKILL.md +1 -1
  143. package/skills/v8-security/references/progressive-01-2-/346/235/203/351/231/220/346/240/241/351/252/214.md +122 -122
  144. package/skills/v8-sql-query/SKILL.md +7 -5
  145. package/skills/v8-table-event/SKILL.md +9 -2
  146. 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 +1 -1
  147. 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 +15 -15
  148. package/skills/v8-tcp-integration/SKILL.md +1 -1
  149. package/skills/v8-tcp-integration/agents/openai.yaml +4 -4
  150. package/skills/v8-template-engine/SKILL.md +59 -59
  151. package/skills/v8-utilities/SKILL.md +92 -92
  152. package/skills/v8-utilities/references/client-api-index.md +143 -143
  153. package/skills/v8-utilities/references/platform-http-routes.md +83 -83
  154. package/skills/v8-utilities/references/server-api-index.md +74 -74
  155. package/skills/v8-workflow/SKILL.md +13 -4
  156. package/skills/vision-engine/SKILL.md +19 -19
  157. package/skills/vision-engine/references/architecture-and-acceptance.md +34 -34
  158. package/skills/workspace-conventions/SKILL.md +35 -12
  159. 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 +2 -2
  160. 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 +179 -179
  161. 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 +21 -21
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: microi-client-frontend
3
- description: Microi.Client 源码架构指南。用于修改 Microi.Client Vue 前端代码,尤其是本地 ApiBase/OsClient URL 切换、浏览器租户隔离、表单引擎、diy-table、diy-form-full、工作流面板、sys_menu 按钮、前端 V8 事件、路由、微服务宿主 keep-alive/TagsView 缓存/白屏恢复,以及页面、弹窗和抽屉行为。
3
+ description: Microi.Client 源码架构指南。用于修改 Microi.Client Vue 前端代码,尤其是本地 ApiBase/OsClient URL 切换、浏览器租户隔离、表单引擎、diy-table、diy-form-full、工作流面板、sys_menu 按钮、前端 V8 事件、路由、微服务宿主 keep-alive/TagsView 缓存/白屏恢复,以及页面、弹窗和抽屉行为。
4
4
  ---
5
5
 
6
6
  > **Codex 非阻塞自动更新:** 当前宿主为 Codex 时,吾码 CLI、Codex 插件与工作区 AI/MCP 由后台自动更新;需要诊断时读取 `../microi-codex-installer/SKILL.md`。更新失败、等待空闲或尚未重载均不得阻断当前、正在进行或新建任务。非 Codex 宿主跳过此项。
@@ -44,15 +44,15 @@ description: Microi.Client 源码架构指南。用于修改 Microi.Client Vue
44
44
  ---
45
45
 
46
46
  <!-- /microi-progressive:chunk -->
47
- <!-- microi-progressive:chunk id=microi-client-frontend-002 sha256=ca442fa8a4990040aa7172dd37b49437bc6de0c9b1f88d889a30f5e936321aa1 -->
47
+ <!-- microi-progressive:chunk id=microi-client-frontend-002 sha256=9fae6ea3c3b238d5d830f308599d7512d1ed6364cb495d432278ada8680f769e -->
48
48
  ## 2. 表单引擎三层结构
49
49
 
50
50
  ### 模块级跨端视图
51
51
 
52
- - Detail/Edit/List/Card 视图属于 `sys_menu`,使用物理字段 `EnableViewSchema`、`ViewSchemaVersion`、`ViewConfigVersion`、`ViewSchema`。其中 `EnableViewSchema` 只控制 Detail/Edit 自定义表单视图,List/Card 有有效配置时始终生效;两个版本字段可空,默认按 `1.0/1` 处理。
53
- - 顶层 PC `diy-table` 即使没有 List ViewSchema,也默认显示约 40 至 52px 的紧凑模块标题。`selectModuleView()` 只能对 List/Card 绕过 `EnableViewSchema`;Detail/Edit 必须继续显式启用,不能被列表 fallback 误接管。
54
- - 存量模块没有 Hero 配置时,PC/移动端从真实 `StatisticsFields`、`DataCount/PageCount`、当前页数值求和或当前页真实状态分布生成兜底指标;当前页口径必须写进标签,严禁随机值或伪造全表汇总。
55
- - `Layout.List.Columns[].MinWidth` 优先于普通 `diy_field.TableWidth` 和末列自适应;缺少持久宽度时按标题/地址、日期/编码、数值、状态等字段语义稳定推断。
52
+ - Detail/Edit/List/Card 视图属于 `sys_menu`,使用物理字段 `EnableViewSchema`、`ViewSchemaVersion`、`ViewConfigVersion`、`ViewSchema`。其中 `EnableViewSchema` 只控制 Detail/Edit 自定义表单视图,List/Card 有有效配置时始终生效;两个版本字段可空,默认按 `1.0/1` 处理。
53
+ - 顶层 PC `diy-table` 即使没有 List ViewSchema,也默认显示约 40 至 52px 的紧凑模块标题。`selectModuleView()` 只能对 List/Card 绕过 `EnableViewSchema`;Detail/Edit 必须继续显式启用,不能被列表 fallback 误接管。
54
+ - 存量模块没有 Hero 配置时,PC/移动端从真实 `StatisticsFields`、`DataCount/PageCount`、当前页数值求和或当前页真实状态分布生成兜底指标;当前页口径必须写进标签,严禁随机值或伪造全表汇总。
55
+ - `Layout.List.Columns[].MinWidth` 优先于普通 `diy_field.TableWidth` 和末列自适应;缺少持久宽度时按标题/地址、日期/编码、数值、状态等字段语义稳定推断。
56
56
  - `diy_table.DiyConfig`、`diy_field.DiyConfig`、`sys_menu.DiyConfig` 均为废弃兼容字段;禁止向其中写入任何新功能配置。
57
57
  - Text、Select、ImgUpload、Map 等数据控件继续放在 `diy-field-component`。
58
58
  - EntityHero、MetricStrip、ActionGrid、ResponsiveSection 是独立展示区块,放在 `form-view-blocks`,禁止用虚拟字段或 DevComponent 模拟。
@@ -130,21 +130,21 @@ description: Microi.Client 源码架构指南。用于修改 Microi.Client Vue
130
130
 
131
131
  标准前端 V8 会挂载 `FormEngine`、`ApiEngine`、`DataSourceEngine`、`Http`、`Base64` 等能力;虽然 `DiyCommon.ModuleEngine` 有底层实现,标准全局 V8 当前并未挂载 `V8.ModuleEngine`,文档和编辑器提示不得把它当作可用 API。
132
132
 
133
- `V8.SysConfig` 是面向浏览器的脱敏公开配置投影,不得依赖其中出现数据库连接串、对象存储密钥、短信/邮件密码或其它 SaaS 私密字段。
134
-
135
- ### 框架来源标识与水印(强制)
136
-
137
- - 微服务和定制组件的来源标识必须由 Microi.Client 宿主统一渲染,子应用不得各自实现。来源标识是框架内置的常驻可发现能力,不得再创建 `RenderSourceBadgeMode`、自动收起、全局关闭等租户配置。
138
- - `V8.OpenAppDialog` / Drawer 等标准弹层的来源标识放在标题文字之后,始终显示且不提供关闭按钮;菜单/整页微服务由 `micro-app/host.vue` 在内容区右上角直接渲染,必须提供只作用于当前页面实例的手动关闭按钮,切换实例后恢复显示。不得依赖外围路由组件猜测菜单微服务,避免动态路由元数据不同步导致漏标。
139
- - 来源标识必须使用可点击的 `button` 语义与 `cursor:pointer`。点击后用可拖动、居中、亮/暗色适配的大圆角 Element Plus 弹层展示 AppKey、PageKey、应用内/框架路由、版本、源码定位、运行入口、发布/挂载状态和租户坐标,并生成可复制的 MCP 修改指令;公开详情不得包含 DiyToken、访问密钥、私有配置或用户敏感字段。
140
- - 框架水印覆盖 `100vw × 100vh` 且固定 `pointer-events:none`。开启后内容空值默认 `$SysTitle$ - $UserName$`(用户名为空回退账号)、方向默认 `DiagonalUp`、密度默认 `Comfortable`、字号空值/0 默认 14,透明度空值/0 默认 30;亮色、深色、弹层、键盘和减少动态效果模式都要验收。
141
-
142
- ### 用户级界面偏好(强制)
143
-
144
- - 主题色、浅色/深色、菜单子级展开方式等需要“换设备仍生效”的选择必须保存到当前 DiyToken 用户的 `sys_user` 白名单字段;`localStorage` 只作为未安装新字段租户和匿名启动阶段的兼容回退,不能作为跨设备事实源。
145
- - 已安装用户偏好字段时优先级固定为“当前用户显式值 → 租户 `sys_config` → 平台安全默认”;个人菜单值 `System` 表示继承租户配置。不得让上一位用户的浏览器本地主题覆盖下一位已登录用户。
146
- - 自助保存优先使用官方 `Managed` 接口引擎,由 `V8.CurrentUser.Id` 与 `V8.OsClient` 推导用户和租户,并在服务端构造固定白名单更新对象;接口参数禁止决定目标 Id/OsClient,也禁止写入 Account、Phone、Tenant、Dept、Role、Level、State、Pwd、认证因子和登录审计字段。只有缺少可复用可信原子能力时才新增 C# DTO/端点。保存成功后调用 `V8.Method.RefreshLoginUser` 刷新登录缓存,并让微服务宿主重新同步 `CurrentUser`。
147
- - 右上角即时切换可以乐观应用并短防抖保存;远端保存失败时保留当前设备效果并明确提示。个人中心和右上角必须调用同一个应用包交付的白名单接口引擎(当前为 `platform-user-update-preferences`),不能分别形成两套字段、枚举或优先级。
133
+ `V8.SysConfig` 是面向浏览器的脱敏公开配置投影,不得依赖其中出现数据库连接串、对象存储密钥、短信/邮件密码或其它 SaaS 私密字段。
134
+
135
+ ### 框架来源标识与水印(强制)
136
+
137
+ - 微服务和定制组件的来源标识必须由 Microi.Client 宿主统一渲染,子应用不得各自实现。来源标识是框架内置的常驻可发现能力,不得再创建 `RenderSourceBadgeMode`、自动收起、全局关闭等租户配置。
138
+ - `V8.OpenAppDialog` / Drawer 等标准弹层的来源标识放在标题文字之后,始终显示且不提供关闭按钮;菜单/整页微服务由 `micro-app/host.vue` 在内容区右上角直接渲染,必须提供只作用于当前页面实例的手动关闭按钮,切换实例后恢复显示。不得依赖外围路由组件猜测菜单微服务,避免动态路由元数据不同步导致漏标。
139
+ - 来源标识必须使用可点击的 `button` 语义与 `cursor:pointer`。点击后用可拖动、居中、亮/暗色适配的大圆角 Element Plus 弹层展示 AppKey、PageKey、应用内/框架路由、版本、源码定位、运行入口、发布/挂载状态和租户坐标,并生成可复制的 MCP 修改指令;公开详情不得包含 DiyToken、访问密钥、私有配置或用户敏感字段。
140
+ - 框架水印覆盖 `100vw × 100vh` 且固定 `pointer-events:none`。开启后内容空值默认 `$SysTitle$ - $UserName$`(用户名为空回退账号)、方向默认 `DiagonalUp`、密度默认 `Comfortable`、字号空值/0 默认 14,透明度空值/0 默认 30;亮色、深色、弹层、键盘和减少动态效果模式都要验收。
141
+
142
+ ### 用户级界面偏好(强制)
143
+
144
+ - 主题色、浅色/深色、菜单子级展开方式等需要“换设备仍生效”的选择必须保存到当前 DiyToken 用户的 `sys_user` 白名单字段;`localStorage` 只作为未安装新字段租户和匿名启动阶段的兼容回退,不能作为跨设备事实源。
145
+ - 已安装用户偏好字段时优先级固定为“当前用户显式值 → 租户 `sys_config` → 平台安全默认”;个人菜单值 `System` 表示继承租户配置。不得让上一位用户的浏览器本地主题覆盖下一位已登录用户。
146
+ - 自助保存优先使用官方 `Managed` 接口引擎,由 `V8.CurrentUser.Id` 与 `V8.OsClient` 推导用户和租户,并在服务端构造固定白名单更新对象;接口参数禁止决定目标 Id/OsClient,也禁止写入 Account、Phone、Tenant、Dept、Role、Level、State、Pwd、认证因子和登录审计字段。只有缺少可复用可信原子能力时才新增 C# DTO/端点。保存成功后调用 `V8.Method.RefreshLoginUser` 刷新登录缓存,并让微服务宿主重新同步 `CurrentUser`。
147
+ - 右上角即时切换可以乐观应用并短防抖保存;远端保存失败时保留当前设备效果并明确提示。个人中心和右上角必须调用同一个应用包交付的白名单接口引擎(当前为 `platform-user-update-preferences`),不能分别形成两套字段、枚举或优先级。
148
148
 
149
149
  ---
150
150
 
@@ -171,30 +171,36 @@ description: Microi.Client 源码架构指南。用于修改 Microi.Client Vue
171
171
  ---
172
172
 
173
173
  <!-- /microi-progressive:chunk -->
174
- <!-- microi-progressive:chunk id=microi-client-frontend-004 sha256=5c5669acf2040f87491abe1f8c85f89e9707a128508ca00f82d8f6a73c3ba7bc -->
175
- ## 7. 验证建议
176
-
177
- ### 本地 ApiBase 与 OsClient 解析(强制)
178
-
174
+ <!-- microi-progressive:chunk id=microi-client-frontend-004 sha256=53d475c7c494a5b6e9e2436c986c458ee539807426978fd99a27a1d7eb967881 -->
175
+ ## 7. 验证建议
176
+
177
+ ### 本地 ApiBase 与 OsClient 解析(强制)
178
+
179
179
  - `app.use(router)` 会立即触发首个路由守卫。守卫中的 SSO、认证、菜单请求必须等待 `initApp()` 完成真实租户和系统配置初始化;初始化失败时取消导航并保留启动错误界面。释放初始化等待必须早于 `router.isReady()`,避免彼此等待;禁止将缓存尚未建立时的 `GetOsClient()` 默认值 `iTdos` 发给客户服务器。
180
180
 
181
- - `src/config.json.ApiBaseDev` 是本地默认 API;URL 中 `#` 之前的 `ApiBase`、`OsClient` 必须同时
182
- 高于 `index.html`、config、Pinia 与 localStorage。解析统一走
183
- `src/utils/runtime-endpoint-query.js`,禁止在新入口另写正则形成不同优先级。
181
+ - 身份和菜单只读初始化的短暂失败最多读取三次,间隔 300/1000ms;认证失效立即回登录页并保留原深链接,HTTP 403 和已耗尽的菜单依赖重试不得继续重试。重试期间退出登录应停止后续读取,不得用清空 Token、伪造角色或放行保护路由掩盖错误。持续失败用 `next(error)` 保留身份/菜单阶段和原始原因,禁止用 `next(false)` 把它替换为 `Navigation aborted`;启动界面不能据此断言后端断网。当前用户请求的传输失败必须 reject,不能留下永久 pending 的 Promise。修改这条链路时运行 `route-bootstrap-recovery.spec.mjs`,并用真实路由验证健康登录、短暂失败恢复、持续失败提示和过期会话跳转。
182
+
183
+ - `ApiServiceUnavailable` 确认连接故障后,每轮探测结束 5 秒后继续请求固定匿名健康接口;单次请求超时 5 秒,自动与手动检测共用在途请求。后端返回有效健康正文后停止轮询,启动失败的页面只重载一次原 URL,已经就绪的业务页面原地撤掉异常层并保留输入,禁止重放失败的业务写入。旧版健康接口也必须返回有效的 Healthy 正文,不能把反向代理 HTML/404 当作恢复。安全拦截继续按后端解除时间检查,不用连接故障轮询缩短封禁。定向回归使用 `api-service-recovery.spec.mjs` 与 `api-service-status.spec.mjs`,浏览器必须验证断连到自动恢复全过程。
184
+
185
+ - `src/config.json.ApiBaseDev` 是本地默认 API;URL 中 `#` 之前的 `ApiBase`、`OsClient` 必须同时
186
+ 高于 `index.html`、config、Pinia 与 localStorage。解析统一走
187
+ `src/utils/runtime-endpoint-query.js`,禁止在新入口另写正则形成不同优先级。
184
188
  - URL 只允许有效的 HTTP(S) ApiBase 和安全 OsClient。页面初始化后通过不含 Token 的
185
189
  `window.__MICROI_RUNTIME_ENDPOINT__` 暴露实际值,便于 AI/自动化确认没有误连配置文件中的服务器。
186
- - 同源浏览器窗口仍共享 Token、CurrentUser 等持久化状态。不同 `ApiBase + OsClient` 并行测试必须
187
- 使用独立 browser context/profile;URL 最高优先级不等于登录态隔离。
188
- - 修改该链路时运行 `node --test tests/runtime-endpoint-query.spec.mjs`,再使用两个独立
189
- `browser.newContext()` 验证两组运行目标互不串号。
190
-
191
- ### 菜单微服务缓存与恢复(强制)
192
-
193
- - 动态菜单宿主的 Vue 路由保持 `keepAlive:false`,由 `<micro-app keep-alive>` 独占运行时状态;契约固定为 `runtime-keep-alive`,禁止 Vue `KeepAlive` 和 micro-app 双层缓存。
194
- - 每个顶部 Tab 按完整路由生成稳定实例身份,最多保留 5 个隐藏实例并按 LRU 淘汰。关闭 Tab、退出登录、Token/角色变化以及版本或入口变化时必须精确销毁对应运行时。
195
- - 恢复时强制同步宿主上下文并检查真实可见 DOM;子应用监听 `appstate-change`,在 `afterhidden` 幂等暂停轮询、WebSocket 和观察器,在 `aftershow` 幂等恢复并重新测量布局,同时保留用户输入、筛选、滚动和内部路由。
196
- - 修改宿主、TagsView 或权限路由时,必须同时读取 [Vue3 前端微服务宿主规则](references/progressive-03-vue3-前端微服务宿主规则.md) 并运行微服务缓存契约测试。
197
-
190
+ - 页面已解析的租户必须进入真实 HTTP 请求。`DiyCommon.UseAxios/UseAxiosAll` 与共享 axios 请求层统一通过 `request-tenant-context.js` 补当前 API 的 `osclient` 请求头;保留调用者显式的路径、Query、参数或 Header 租户,不给其它服务器或相邻 API 子路径自动添加页面租户。JSON 正文在动态路由阶段可能尚未读取,不能只依赖正文或旧 Token 选择租户。验收必须增加同源旧 Token 指向其它/不存在租户的真实后端场景:`platform-current-user` 应走页面租户并返回登录失效,保留原深链接进入登录页,不得显示“无法确认接口配置”或让 SSO 发现返回错误租户的 404;定向回归为 `request-tenant-context.spec.mjs`。
191
+ - 首次身份读取的业务/传输失败交给路由守卫处理,`getInfo` 不调用带全局通知副作用的 `DiyCommon.Result`,同时抑制请求层通知和抢先登录跳转;`App.PageInit` 等待首次导航成功后再启动续签/用户刷新,导航失败时结束。既要验证干净会话,也要验证旧登录缓存和失败后重复刷新,不能以隔离浏览器成功代替用户当前会话验收。
192
+ - 同源浏览器窗口仍共享 Token、CurrentUser 等持久化状态。不同 `ApiBase + OsClient` 并行测试必须
193
+ 使用独立 browser context/profile;URL 最高优先级不等于登录态隔离。
194
+ - 修改该链路时运行 `node --test tests/runtime-endpoint-query.spec.mjs`,再使用两个独立
195
+ `browser.newContext()` 验证两组运行目标互不串号。
196
+
197
+ ### 菜单微服务缓存与恢复(强制)
198
+
199
+ - 动态菜单宿主的 Vue 路由保持 `keepAlive:false`,由 `<micro-app keep-alive>` 独占运行时状态;契约固定为 `runtime-keep-alive`,禁止 Vue `KeepAlive` 和 micro-app 双层缓存。
200
+ - 每个顶部 Tab 按完整路由生成稳定实例身份,最多保留 5 个隐藏实例并按 LRU 淘汰。关闭 Tab、退出登录、Token/角色变化以及版本或入口变化时必须精确销毁对应运行时。
201
+ - 恢复时强制同步宿主上下文并检查真实可见 DOM;子应用监听 `appstate-change`,在 `afterhidden` 幂等暂停轮询、WebSocket 和观察器,在 `aftershow` 幂等恢复并重新测量布局,同时保留用户输入、筛选、滚动和内部路由。
202
+ - 修改宿主、TagsView 或权限路由时,必须同时读取 [Vue3 前端微服务宿主规则](references/progressive-03-vue3-前端微服务宿主规则.md) 并运行微服务缓存契约测试。
203
+
198
204
  - 修改 Vue/JS 后先跑 VS Code Problems 或 `get_errors`。
199
205
  - 影响核心前端时跑 `Microi.Client` 的 `npm run build`。
200
206
  - 如果改了工作流、表单保存、按钮 V8,建议用实际 `sys_menu` 配置测试:
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 按需读取;本文件由 SKILL.md 的原章节无损拆分。
4
4
 
5
- <!-- microi-progressive:chunk id=microi-client-frontend-005 sha256=0ffafbd99fc0ee478db91200bfc3645c288f20d45120cd7413fb00ac3fbd8952 -->
5
+ <!-- microi-progressive:chunk id=microi-client-frontend-005 sha256=2c4c3f197bcd921d147b892cb64ccd1b77461f67c0219cfc3107ec6c7c268d88 -->
6
6
  ## 3. 动态按钮系统
7
7
 
8
8
  按钮配置来自 `sys_menu`:
@@ -16,7 +16,7 @@
16
16
  | `PageTabs` | 列表页 Tab |
17
17
  | `ExportMoreBtns` | 导出下拉扩展 |
18
18
 
19
- `PageTabs.TargetSysMenuId` 是通用的跨模块页签协议。未配置时继续执行当前模块的页签 V8;配置其它 `sys_menu.Id` 时,`diy-table.vue` 在同一个组件实例内切换模块上下文,按目标 `sys_menu / diy_table / diy_field` 重载数据,同时保留入口路由、面包屑、顶部访问标签、宿主 Hero 和入口 PageTabs,URL 只更新 `Tab` 查询参数。入口模块是唯一 PageTabs 配置源,隐藏目标模块不得复制 PageTabs。不得为应用商城或其它单一模块在 schema/data mixin 中增加专用数据源分支。
19
+ `PageTabs.TargetSysMenuId` 是通用的跨模块页签协议。未配置时继续执行当前模块的页签 V8;配置其它 `sys_menu.Id` 时,`diy-table.vue` 在同一个组件实例内切换模块上下文,按目标 `sys_menu / diy_table / diy_field` 重载数据,同时保留入口路由、面包屑、顶部访问标签、宿主 Hero 和入口 PageTabs,URL 只更新 `Tab` 查询参数。入口模块是唯一 PageTabs 配置源,隐藏目标模块不得复制 PageTabs。不得为应用商城或其它单一模块在 schema/data mixin 中增加专用数据源分支。
20
20
 
21
21
  按钮显隐链路:
22
22
 
@@ -45,7 +45,7 @@ V8.Result = V8.Form.Status == '待审核';
45
45
  ---
46
46
 
47
47
  <!-- /microi-progressive:chunk -->
48
- <!-- microi-progressive:chunk id=microi-client-frontend-006 sha256=f2cb2548a184ceb086733d032e16d9a6870cb037c661671eb8c8a6cf2e694e60 -->
48
+ <!-- microi-progressive:chunk id=microi-client-frontend-006 sha256=e92ec7faad68c55a2175580e301c0b2b6a63b90e8e7edba48b8b0073ae53c807 -->
49
49
  ## 5. 路由与打开方式
50
50
 
51
51
  登录首页支持“用户 > 系统 > 首个可访问菜单”的三级优先级:
@@ -76,7 +76,7 @@ Page 模式要特别注意:
76
76
  - 匿名公有存储场景只允许当前 `OsClient` 目录下的 `filePathName`;接口响应文件场景用 `fileUrl` 接收当前平台正式 `ApiBase`,或由同端口本地后端读取的 loopback `/apiengine/...`,并要求 URL 显式携带当前 `OsClient`。两种场景都拒绝私有文件、跨租户路径、路径穿越和任意第三方域名。
77
77
  - `fileUrl` 路径没有文件扩展名时必须同时传 `fileName` 或 `fileType`。组件先调用 `/api/HDFS/PrepareOfficePreviewFromUrl`,由后端严格校验当前平台、当前 `OsClient` 和单层 `/apiengine/{key}`,再把响应文件透明缓存到当前租户公有对象存储;OnlyOffice 使用返回的公网静态地址。开发环境 loopback 只允许同端口本地后端读取,不能简单替换 origin,也不能把该接口扩展成通用 URL 代理。
78
78
  - `canEdit` 不能直接作为授权结果。最终允许编辑必须同时满足有效登录态;匿名即使传 `canEdit=1` 也强制使用 OnlyOffice `mode:'view'` 和 `permissions.edit=false`。
79
- - 私有文件调用 `/apiengine/platform-private-file-url` 时传 `ForOfficePreview:true` 和权威资源上下文,让远程 OnlyOffice 使用租户公网 `ApiBase` 的审计代理地址,避免 `localhost` 导致“下载失败”。
79
+ - 私有文件调用 `/apiengine/platform-private-file-url` 时传 `ForOfficePreview:true` 和权威资源上下文,让远程 OnlyOffice 使用租户公网 `ApiBase` 的审计代理地址,避免 `localhost` 导致“下载失败”。
80
80
  - `layout/index.vue` 仅在“路由要求隐藏外壳且当前无有效登录用户”时隐藏 Sidebar/Navbar/TagsView;登录用户打开同一路由仍保留正常系统布局。
81
81
  - 不要把匿名路由简单加入全局白名单后跳过组件鉴权;过期 Token 要清理,公有文件校验失败必须停止创建 OnlyOffice 配置。
82
82
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 按需读取;本文件由 SKILL.md 的原章节无损拆分。
4
4
 
5
- <!-- microi-progressive:chunk id=microi-client-frontend-008 sha256=4824b3271515717979847b142c1cad88e468c5904d93b23950c59cc90b90c5a4 -->
5
+ <!-- microi-progressive:chunk id=microi-client-frontend-008 sha256=8c69ef00a2d46086848ea96273bb0d172fa1a2611be6bc5d5d5fe5721abdccaf -->
6
6
  ## 8. 运行时高频坑复盘
7
7
 
8
8
  ### 前端 V8.Http 与后端同构契约
@@ -51,7 +51,7 @@ DiyCommon.FormEngine.AddFormData("table_name", { Field: "value" }, function (res
51
51
  - 当前菜单绑定表会自动补真实 `_SysMenuId`。
52
52
  - 跨表调用不能继承当前菜单 Id,否则会把无关菜单的数据范围错误套到目标表;未显式指定目标菜单时,由后端从当前用户的版本化授权缓存中推断其对目标表的菜单/表级权限。
53
53
  - 传入 `_SysMenuId`、历史 `SysMenuId` 或 `ModuleEngineKey` 表示调用方选择了明确菜单,后端必须按该菜单严格校验,失败时不能回退。
54
- - 平台表由服务端分级:管理员专用表全操作硬保护,只读委托表仅在真实菜单/Table `Read` 授权后查询,`mic_page/mic_print` 按角色 CRUD 权限管理;三类都拒绝匿名。前端角色页必须读取服务端授权策略并失败关闭,不维护第二份硬编码表名清单。`_InvokeType:'Client'` 只控制表单事件触发方式,不是授权绕过参数。
54
+ - 平台表由服务端分级:管理员专用表全操作硬保护,只读委托表仅在真实菜单/Table `Read` 授权后查询,`mic_page/mic_print` 按角色 CRUD 权限管理;三类都拒绝匿名。前端角色页必须读取服务端授权策略并失败关闭,不维护第二份硬编码表名清单。`_InvokeType:'Client'` 只控制表单事件触发方式,不是授权绕过参数。
55
55
  - `TableChild` 使用运行时生成的不透明 `_TableChildAuth`;后端会重新验证父菜单、父记录、字段关系、外键和数据范围。业务代码不得手工伪造。
56
56
  - 导入、导出必须锚定真实菜单;通用 CRUD 的历史无菜单兼容不能扩展到批量数据传输。
57
57
 
@@ -88,7 +88,7 @@ DiyCommon.FormEngine.AddFormData("table_name", { Field: "value" }, function (res
88
88
  - 官方文档:`microi.doc/docs/doc/v8-engine/v8-client.md`。
89
89
  - Skills:`v8-frontend-events`、`v8-table-event`、`v8-menu-buttons`、`v8-template-engine`、`v8-formengine-http` 和本 Skill。
90
90
 
91
- `sys_menu.ViewSchema` 使用 `DiyModulePresentationDesigner` 作为配置入口,聚合 `EnableViewSchema / ViewSchemaVersion / ViewConfigVersion / ViewSchema`。设计器固定提供“模块标题与统计 / PC 复合列 / 移动端卡片 / 自定义表单 / 高级 JSON”五个 Tab;可视化编辑默认 List-PC 与 Card-Mobile 视图,以独立的“自定义表单”JSON 编辑 Detail/Edit,并由高级 JSON 保留完整协议、角色视图和未知字段;运行时的 EntityHero/MetricStrip 等仍是独立展示区块,不由 DevComponent 参与渲染。
91
+ `sys_menu.ViewSchema` 使用 `DiyModulePresentationDesigner` 作为配置入口,聚合 `EnableViewSchema / ViewSchemaVersion / ViewConfigVersion / ViewSchema`。设计器固定提供“模块标题与统计 / PC 复合列 / 移动端卡片 / 自定义表单 / 高级 JSON”五个 Tab;可视化编辑默认 List-PC 与 Card-Mobile 视图,以独立的“自定义表单”JSON 编辑 Detail/Edit,并由高级 JSON 保留完整协议、角色视图和未知字段;运行时的 EntityHero/MetricStrip 等仍是独立展示区块,不由 DevComponent 参与渲染。
92
92
 
93
93
  固定高度的 `diy-form-full` 弹窗只能有一个纵向滚动容器:由弹窗直属 `.el-dialog__body` 承载滚动,Element Plus 的 overlay 和表单顶层 `.el-tabs__content` 必须禁用独立滚动。禁止同时保留 overlay、dialog body、tabs content 三层纵向滚动条;切换表单 Tab 时弹窗外框高度不得变化。
94
94
 
@@ -135,19 +135,19 @@ DiyCommon.FormEngine.AddFormData("table_name", { Field: "value" }, function (res
135
135
  - 标题栏应保持清晰的拖动热区,可给 `.el-dialog__header` 设置 `cursor: move`,但不能遮挡关闭按钮。
136
136
  - 弹窗内部的表格、树、编辑区要设置稳定高度或最大高度,避免内容撑出视口导致默认居中失效。
137
137
  - 修改后验收默认打开态和拖动后状态:弹窗仍在可视区域内,标题/按钮/输入框不被导航、遮罩或浏览器边缘遮挡。
138
- - 对长内容弹窗还要分别滚到顶部、中部和底部触发一次错误反馈/二次确认,断言提示层仍以当前视口为基准居中;静态扫描同时禁止 `window.alert`、`window.confirm`、`window.prompt` 及对应全局别名。
139
-
140
- ### 内容 Loading 统一使用主题骨架
141
-
142
- - `Microi.Client` 的异步内容区统一使用 `v-mci-loading:<variant>`,语义变体为 `table/cards/form/detail/page/stats/list/tree/compact`;菜单异步路由在守卫开始/结束时驱动页面骨架,全屏内容导入使用 `openMciLoading()`。
143
- - 平台主题由 `theme-color.js` 同步生成 `--mci-skeleton-surface/card/header/base/highlight/accent/border`;骨架样式只能消费这些语义令牌,禁止在组件里写亮/暗两套硬编码颜色,禁止新增半透明 `.el-loading-mask`。
144
- - `diy-table` 首屏/筛选重载使用表格或卡片骨架,移动追加使用底部 `compact` 骨架;`diy-form` 把骨架挂在根容器,不能依赖尚未加载完成的 Tabs。请求完成前禁止渲染空态。
145
- - 头像、验证码、私有图片/文件缩略图使用圆形或媒体骨架;旧表单依赖的 `./static/img/loading.gif` 可继续作为内存中的状态哨兵,但渲染前必须拦截,禁止作为 `<img>`、`<el-image>` 或背景图 URL 发起网络请求。
146
- - 保存/提交/登录验证等动作保留按钮 Loading,可信百分比保留真实进度;其余 spinner、转圈图标和“加载中”文案不得充当内容加载态。
147
- - 修改后运行静态门禁,确认源码不存在内容型 `v-loading`、`ElLoading.service`、硬编码黑色 Loading mask 或加载期空态;再用真实浏览器验证菜单、首页、表格、表单详情在亮色、暗色、自定义主题和移动端下的骨架几何、对比度、`aria-busy`、reduced-motion 及请求失败收口。
148
-
149
- <!-- /microi-progressive:chunk -->
150
- <!-- microi-progressive:chunk id=microi-client-frontend-009 sha256=11a3c4fd1667c1309832387d79dd98ca14b64d8c60b5a54c0b8ac4237e22d0e4 -->
138
+ - 对长内容弹窗还要分别滚到顶部、中部和底部触发一次错误反馈/二次确认,断言提示层仍以当前视口为基准居中;静态扫描同时禁止 `window.alert`、`window.confirm`、`window.prompt` 及对应全局别名。
139
+
140
+ ### 内容 Loading 统一使用主题骨架
141
+
142
+ - `Microi.Client` 的异步内容区统一使用 `v-mci-loading:<variant>`,语义变体为 `table/cards/form/detail/page/stats/list/tree/compact`;菜单异步路由在守卫开始/结束时驱动页面骨架,全屏内容导入使用 `openMciLoading()`。
143
+ - 平台主题由 `theme-color.js` 同步生成 `--mci-skeleton-surface/card/header/base/highlight/accent/border`;骨架样式只能消费这些语义令牌,禁止在组件里写亮/暗两套硬编码颜色,禁止新增半透明 `.el-loading-mask`。
144
+ - `diy-table` 首屏/筛选重载使用表格或卡片骨架,移动追加使用底部 `compact` 骨架;`diy-form` 把骨架挂在根容器,不能依赖尚未加载完成的 Tabs。请求完成前禁止渲染空态。
145
+ - 头像、验证码、私有图片/文件缩略图使用圆形或媒体骨架;旧表单依赖的 `./static/img/loading.gif` 可继续作为内存中的状态哨兵,但渲染前必须拦截,禁止作为 `<img>`、`<el-image>` 或背景图 URL 发起网络请求。
146
+ - 保存/提交/登录验证等动作保留按钮 Loading,可信百分比保留真实进度;其余 spinner、转圈图标和“加载中”文案不得充当内容加载态。
147
+ - 修改后运行静态门禁,确认源码不存在内容型 `v-loading`、`ElLoading.service`、硬编码黑色 Loading mask 或加载期空态;再用真实浏览器验证菜单、首页、表格、表单详情在亮色、暗色、自定义主题和移动端下的骨架几何、对比度、`aria-busy`、reduced-motion 及请求失败收口。
148
+
149
+ <!-- /microi-progressive:chunk -->
150
+ <!-- microi-progressive:chunk id=microi-client-frontend-009 sha256=aec6ac1daf1566f4893c86ab0b12a17dcd156b0f46fa81a7ca387ca59f13fe17 -->
151
151
  ## 7.1 登录验证码与 Sys_Config
152
152
 
153
153
  修改 `Microi.Client/src/views/login/index.vue` 或任何 PC 端登录扩展时,必须遵守平台登录验证码契约:
@@ -160,30 +160,30 @@ DiyCommon.FormEngine.AddFormData("table_name", { Field: "value" }, function (res
160
160
 
161
161
  文件同步、跨平台导入等需要登录另一套 Microi API 的前端工具,也必须复用同一验证码契约:
162
162
 
163
- - 用户填写远程 `ApiBase` 和 `OsClient` 后,先请求远程 `/apiengine/platform-sys-config?OsClient=<OsClient>`,并让 Query、`osclient` Header 与 Body 三处租户一致;按 `isEnabledFlag(EnableCaptcha)` 判断是否需要验证码,不能先盲目调用登录接口。
163
+ - 用户填写远程 `ApiBase` 和 `OsClient` 后,先请求远程 `/apiengine/platform-sys-config?OsClient=<OsClient>`,并让 Query、`osclient` Header 与 Body 三处租户一致;按 `isEnabledFlag(EnableCaptcha)` 判断是否需要验证码,不能先盲目调用登录接口。
164
164
  - 需要验证码时,自动请求远程 `/api/Captcha/GetCaptcha?OsClient=<OsClient>`,读取响应头 `captchaid` 并显示验证码图片;用户输入后,远程 `/api/SysUser/login` 必须同时提交 `_CaptchaId/_CaptchaValue`。
165
165
  - 远程地址或租户变化时清空旧验证码和 Token;登录失败时刷新验证码。未开启验证码时不得显示验证码输入,也不得提交空验证码字段。
166
166
  - 远程响应头必须通过 CORS 暴露 `captchaid` 和 `authorization`;前端还应兼容登录响应体中的 Token,避免只依赖响应头。
167
167
 
168
- ### PC/移动自适应 Token 续签
168
+ ### PC/移动自适应 Token 续签
169
169
 
170
170
  - PC 登录传 `_ClientType:'PC'`;`diyStore.IsPhoneView` 的移动自适应登录传 `_ClientType:'Mobile'`。完整协议以 `microi-frontend-sdk/SKILL.md` 为准。
171
171
  - `DiyCommon.getToken()` 是 Microi.Client 请求发送时的 Token 单一事实源;不得先用 Pinia、组件 data 或其它副本判断“是否需要携带 X-Token”,否则持久化恢复或并发续签后会把有效 Token 漏掉。受保护请求收到新 `authorization/token` 后,必须先更新公共存储,再同步 Pinia;登录成功也要在生成动态路由前完成同样的同步。
172
172
  - `TokenExpires` 表示“下次应检查续签的时间”,不能固定成所有终端 15 分钟;应从 JWT `exp` 和 `MicroiTokenIssuedAt` 按 10% 提前量计算,最少 5 分钟、最多 1 天。
173
173
  - `App.vue` 除一分钟维护定时器外,还必须监听 `visibilitychange`、`focus`、`pageshow`。标签页从浏览器休眠恢复时先走 single-flight RefreshToken,再发业务请求。
174
174
  - `Code=1001/1002` 或明确的 `NoLogin / Token签名验证失败` 时展示后端原始 `Msg`。确认失败响应对应的仍是当前 Token 后,必须清理 Token,并携带当前 Hash 用 `location.replace` 完整进入登录页,重建旧页签的动态路由与组件状态,禁止停留在空白页。
175
- - 多 Tab 共享 Token 时,旧请求返回不得覆盖新 Token,也不得因旧 Token 的失效响应清除另一个 Tab 已写入的新 Token。
176
-
177
- ### 复盘:Token 续签的瞬时角色查询失败清空按钮权限
178
-
179
- - 触发场景:管理员已登录且业务页面仍可访问,但列表的新增、编辑等按钮偶发消失;重新登录后立即恢复。
180
- - 根因:旧续签链在角色或角色权限查询异常时,把 `_IsAdmin=false`、`_Roles=[]`、`_RoleLimits=[]` 当作成功结果写回同一用户共享的 Redis 会话。路由守卫随后又把这份坏快照持久化并标记为已初始化,页面不会再主动修复。
181
- - 通用规则:后端权限投影必须从主库完整构建,任一技术性读取失败都保持旧缓存不变,并且在成功投影之后才允许轮换 Token。会话写入须与 Token 轮换共用同一用户锁,锁内重读最新会话且只替换 `CurrentUser`,不得覆盖并发终端的 Token 集合;注销或吊销期间缓存消失、请求 Token 已失活时禁止重建会话。超级管理员由权威 `Level` 判断,不得因普通角色列表为空而降级。
182
- - 通用规则:前端在生成动态路由和设置非空 `roles` 之前,必须验证完整授权快照。技术错误标记或 `Level>=9999 && _IsAdmin!==true` 属于待修复投影;同用户可以临时保留最后一份有效权限用于渲染,但必须携带显式修复标记并强制调用权威刷新接口。干净的普通用户 `false + []` 撤权仍应立即生效,访问密钥裁剪身份不得被自动提升。
183
- - 通用规则:异步刷新结果只能写回与当前 Token 相同的 `UserId + OsClient`;登录切换或租户切换后的迟到响应必须丢弃。权限修复失败时不得提前把路由身份标记为已初始化。
184
- - 自动化检查:单测覆盖失败投影保留最后有效权限、合法撤权、访问密钥、登录切换迟到响应和注销竞态;真实浏览器拦截一次坏的当前用户投影,确认页面无需重新登录即可自动刷新,并连续检查新增、编辑按钮及刷新接口返回的管理员权限始终完整。
185
-
186
- <!-- /microi-progressive:chunk -->
175
+ - 多 Tab 共享 Token 时,旧请求返回不得覆盖新 Token,也不得因旧 Token 的失效响应清除另一个 Tab 已写入的新 Token。
176
+
177
+ ### 复盘:Token 续签的瞬时角色查询失败清空按钮权限
178
+
179
+ - 触发场景:管理员已登录且业务页面仍可访问,但列表的新增、编辑等按钮偶发消失;重新登录后立即恢复。
180
+ - 根因:旧续签链在角色或角色权限查询异常时,把 `_IsAdmin=false`、`_Roles=[]`、`_RoleLimits=[]` 当作成功结果写回同一用户共享的 Redis 会话。路由守卫随后又把这份坏快照持久化并标记为已初始化,页面不会再主动修复。
181
+ - 通用规则:后端权限投影必须从主库完整构建,任一技术性读取失败都保持旧缓存不变,并且在成功投影之后才允许轮换 Token。会话写入须与 Token 轮换共用同一用户锁,锁内重读最新会话且只替换 `CurrentUser`,不得覆盖并发终端的 Token 集合;注销或吊销期间缓存消失、请求 Token 已失活时禁止重建会话。超级管理员由权威 `Level` 判断,不得因普通角色列表为空而降级。
182
+ - 通用规则:前端在生成动态路由和设置非空 `roles` 之前,必须验证完整授权快照。技术错误标记或 `Level>=9999 && _IsAdmin!==true` 属于待修复投影;同用户可以临时保留最后一份有效权限用于渲染,但必须携带显式修复标记并强制调用权威刷新接口。干净的普通用户 `false + []` 撤权仍应立即生效,访问密钥裁剪身份不得被自动提升。
183
+ - 通用规则:异步刷新结果只能写回与当前 Token 相同的 `UserId + OsClient`;登录切换或租户切换后的迟到响应必须丢弃。权限修复失败时不得提前把路由身份标记为已初始化。
184
+ - 自动化检查:单测覆盖失败投影保留最后有效权限、合法撤权、访问密钥、登录切换迟到响应和注销竞态;真实浏览器拦截一次坏的当前用户投影,确认页面无需重新登录即可自动刷新,并连续检查新增、编辑按钮及刷新接口返回的管理员权限始终完整。
185
+
186
+ <!-- /microi-progressive:chunk -->
187
187
  <!-- microi-progressive:chunk id=microi-client-frontend-010 sha256=d89bb60734da788a027790c666287db8b6cda862e8f5fb3806543b07b3cce94c -->
188
188
  ## Microi 前端 SDK 约束
189
189
 
@@ -2,42 +2,42 @@
2
2
 
3
3
  > 按需读取;本文件由 SKILL.md 的原章节无损拆分。
4
4
 
5
- <!-- microi-progressive:chunk id=microi-client-frontend-011 sha256=7f8680e6afd7cae492a0d938e1efc95d0d20b04d0a33b0b956f2d0edb26d25cb -->
5
+ <!-- microi-progressive:chunk id=microi-client-frontend-011 sha256=850ba16e253014a9d022582155cd3e18bf04dff375e82dd2947ea527bac4342a -->
6
6
  ## Vue3 前端微服务宿主规则
7
7
 
8
8
  `sys_menu.OpenType=MicroService` 时,动态路由必须把 `MicroServiceId`、`MicroServicePageId`、`MicroServiceRoutePath` 和真实入口 `MicroAppUrl` 写入 route meta;浏览器侧菜单路由使用 `/#/micro-app/{MsKey}/{RoutePath}`,不要再生成 `/micro-app-host/{menuId}`,否则地址过长且刷新或直接访问菜单路由容易加载空白页。
9
9
 
10
- 同一个编译后的微服务可以绑定多个后台菜单和内部页面。`MicroAppHost` 的 `<micro-app name>` 必须包含菜单 Id、路由路径或其它实例维度,避免多个菜单共享同一个 appKey 时触发 `app name conflict`。入口 URL 中的 `microRoute/routePath` 只用于解析,最终应通过 `data.microRoute` 传给子应用,入口文件 URL 保持稳定。
11
-
12
- 菜单微服务的缓存所有权固定为一层:动态菜单和友好路由都设置 `meta.keepAlive=false`、`meta.microAppHost=true`,`AppMain` 不缓存 Vue 宿主;`host.vue` 的 `<micro-app keep-alive>` 才保存子应用 DOM、路由和状态。`AppMain` 对菜单微服务使用 `$route.fullPath` 作为宿主 key,宿主创建时立即快照 path/fullPath/meta/query,之后不得监听全局 `$route` 去改写即将隐藏的旧宿主。普通 Vue 页面继续使用原有 `KeepAlive`,菜单微服务也不得占用或淘汰 `cachedViews` 槽位。
13
-
14
- 运行时缓存集中维护在 `utils/microAppRuntimeCache.js`:实例名必须由租户、AppKey、fullPath、版本和入口的安全指纹稳定生成,长度受限且不暴露 Token/查询原文。菜单 Id 可能在友好路由首屏之后才随动态菜单元数据补齐,只能进入权限上下文,禁止参与实例身份;否则首次返回同一路由会被误判为新实例。全局最多保留 5 个实例,只淘汰最久未使用的 hidden 实例。TagsView 的关闭当前/其它/全部和访问记录淘汰必须按 fullPath 精确销毁;退出登录、Token 重置、角色切换必须清空全部;同一路由版本/入口变化必须替换旧实例。销毁统一调用 `unmountApp(name,{destroy:true,clearData:true})`,不能只从本地 Map 删除。
15
-
16
- 宿主监听 `beforeshow/aftershow/afterhidden`:恢复时用 `forceSetData` 下发最新 Token、OsClient、权限、主题、路由和视口,并重新执行可见 DOM 健康检查;隐藏时停止宿主看门狗并把实例放入 LRU。`microAppData.cache` 与 `hostCapabilities.lifecycle` 要公开缓存模式、所有者、上限和 `appstate-change` 状态,错误诊断同时显示 cacheMode/cacheState/cacheInstance。可见 DOM 不健康时只自动销毁重建一次,禁止恢复阶段无限重试。
17
-
18
- 菜单型微服务的宿主操作集中维护在 `views/micro-app/host-bridge.js` 和 `host.vue`。
19
- `microAppData.hostCapabilities` 必须下发 `microi.host.v1` 协议、`tab` 模式、请求/结果事件名和动作清单;
20
- 子应用只允许 dispatch `micro-app:host-action`,不能接收父页面函数或直接操作 TagsView/Router。
21
- 标准动作包括 `closeTab/navigate/replaceTab/back/forward/reloadTab/setTabTitle/showMessage`:
22
- 关闭当前 Tab 要复用 `useTagsViewStore` 的当前 `fullPath`,拒绝固定/最后一个 Tab;`navigate`
23
- 保留当前 Tab,`replaceTab` 删除旧 Tab;返回/前进只使用站内 history;右键刷新和 `reloadTab`
24
- 都重新解析并挂载当前微服务。路由输入必须拒绝外部 URL、协议相对地址、反斜杠、登录、访问密钥和
25
- 内部 redirect,并在跳转前用当前 Router 解析,404/未注册动态路由失败关闭。宿主结果用
26
- `micro-app:host-action-result` 尽力回传,但关闭或跳转会卸载子应用,不能承诺结果事件必达。
27
-
28
- `navigate/replaceTab` 只用于主框架级跳转;同一微服务内部菜单必须在子应用内用 Vue Router、
29
- 状态或 iframe Hash 切换,并将异步页面的 `Suspense` 骨架屏限制在内容区域。不得通过改变主框架
30
- `$route.fullPath` 实现内部页面切换,否则 TagsView 会重建整个微服务。宿主根节点与 `<micro-app>`
31
- 元素必须建立 `contain: layout paint`、`isolation:isolate` 的绘制边界;子应用仍必须把主题/reset/
32
- 元素选择器限定在 AppKey 唯一的 `[data-mci-ui-root="{AppKey}"]`,不能只写宿主也会命中的裸属性
33
- 选择器,禁止以 `:root/html/body` 或固定全屏装饰污染主框架。
34
-
35
- `OpenAppDialog` 不暴露 Tab 模式能力;弹窗成功/取消/失败继续使用
36
- `app-dialog:success/cancel/error`。修改桥接时至少运行
37
- `node --test tests/micro-app-host-bridge.spec.mjs tests/micro-app-runtime-contract.spec.mjs`,并同步
38
- `microi.doc/docs/doc/system-engine/micro-app.md` 与 `microi-microservice` Skill。
39
-
40
- 后台配置必须配套维护 `sys_microiservice_page` 路由子表,并在 `sys_microiservice` 表单上用隐藏子模块 + `TableChild` 显示页面/路由。`sys_menu` 选择微服务时要由前端 V8 事件实时加载页面列表,不能完全依赖 SQL 下拉里的表单变量替换。
10
+ 同一个编译后的微服务可以绑定多个后台菜单和内部页面。`MicroAppHost` 的 `<micro-app name>` 必须包含菜单 Id、路由路径或其它实例维度,避免多个菜单共享同一个 appKey 时触发 `app name conflict`。入口 URL 中的 `microRoute/routePath` 只用于解析,最终应通过 `data.microRoute` 传给子应用,入口文件 URL 保持稳定。
11
+
12
+ 菜单微服务的缓存所有权固定为一层:动态菜单和友好路由都设置 `meta.keepAlive=false`、`meta.microAppHost=true`,`AppMain` 不缓存 Vue 宿主;`host.vue` 的 `<micro-app keep-alive>` 才保存子应用 DOM、路由和状态。`AppMain` 对菜单微服务使用 `$route.fullPath` 作为宿主 key,宿主创建时立即快照 path/fullPath/meta/query,之后不得监听全局 `$route` 去改写即将隐藏的旧宿主。普通 Vue 页面继续使用原有 `KeepAlive`,菜单微服务也不得占用或淘汰 `cachedViews` 槽位。
13
+
14
+ 运行时缓存集中维护在 `utils/microAppRuntimeCache.js`:实例名必须由租户、AppKey、fullPath、版本和入口的安全指纹稳定生成,长度受限且不暴露 Token/查询原文。菜单 Id 可能在友好路由首屏之后才随动态菜单元数据补齐,只能进入权限上下文,禁止参与实例身份;否则首次返回同一路由会被误判为新实例。全局最多保留 5 个实例,只淘汰最久未使用的 hidden 实例。TagsView 的关闭当前/其它/全部和访问记录淘汰必须按 fullPath 精确销毁;退出登录、Token 重置、角色切换必须清空全部;同一路由版本/入口变化必须替换旧实例。销毁统一调用 `unmountApp(name,{destroy:true,clearData:true})`,不能只从本地 Map 删除。
15
+
16
+ 宿主监听 `beforeshow/aftershow/afterhidden`:恢复时用 `forceSetData` 下发最新 Token、OsClient、权限、主题、路由和视口,并重新执行可见 DOM 健康检查;隐藏时停止宿主看门狗并把实例放入 LRU。`microAppData.cache` 与 `hostCapabilities.lifecycle` 要公开缓存模式、所有者、上限和 `appstate-change` 状态,错误诊断同时显示 cacheMode/cacheState/cacheInstance。可见 DOM 不健康时只自动销毁重建一次,禁止恢复阶段无限重试。
17
+
18
+ 菜单型微服务的宿主操作集中维护在 `views/micro-app/host-bridge.js` 和 `host.vue`。
19
+ `microAppData.hostCapabilities` 必须下发 `microi.host.v1` 协议、`tab` 模式、请求/结果事件名和动作清单;
20
+ 子应用只允许 dispatch `micro-app:host-action`,不能接收父页面函数或直接操作 TagsView/Router。
21
+ 标准动作包括 `closeTab/navigate/replaceTab/back/forward/reloadTab/setTabTitle/showMessage`:
22
+ 关闭当前 Tab 要复用 `useTagsViewStore` 的当前 `fullPath`,拒绝固定/最后一个 Tab;`navigate`
23
+ 保留当前 Tab,`replaceTab` 删除旧 Tab;返回/前进只使用站内 history;右键刷新和 `reloadTab`
24
+ 都重新解析并挂载当前微服务。路由输入必须拒绝外部 URL、协议相对地址、反斜杠、登录、访问密钥和
25
+ 内部 redirect,并在跳转前用当前 Router 解析,404/未注册动态路由失败关闭。宿主结果用
26
+ `micro-app:host-action-result` 尽力回传,但关闭或跳转会卸载子应用,不能承诺结果事件必达。
27
+
28
+ `navigate/replaceTab` 只用于主框架级跳转;同一微服务内部菜单必须在子应用内用 Vue Router、
29
+ 状态或 iframe Hash 切换,并将异步页面的 `Suspense` 骨架屏限制在内容区域。不得通过改变主框架
30
+ `$route.fullPath` 实现内部页面切换,否则 TagsView 会重建整个微服务。宿主根节点与 `<micro-app>`
31
+ 元素必须建立 `contain: layout paint`、`isolation:isolate` 的绘制边界;子应用仍必须把主题/reset/
32
+ 元素选择器限定在 AppKey 唯一的 `[data-mci-ui-root="{AppKey}"]`,不能只写宿主也会命中的裸属性
33
+ 选择器,禁止以 `:root/html/body` 或固定全屏装饰污染主框架。
34
+
35
+ `OpenAppDialog` 不暴露 Tab 模式能力;弹窗成功/取消/失败继续使用
36
+ `app-dialog:success/cancel/error`。修改桥接时至少运行
37
+ `node --test tests/micro-app-host-bridge.spec.mjs tests/micro-app-runtime-contract.spec.mjs`,并同步
38
+ `microi.doc/docs/doc/system-engine/micro-app.md` 与 `microi-microservice` Skill。
39
+
40
+ 后台配置必须配套维护 `sys_microiservice_page` 路由子表,并在 `sys_microiservice` 表单上用隐藏子模块 + `TableChild` 显示页面/路由。`sys_menu` 选择微服务时要由前端 V8 事件实时加载页面列表,不能完全依赖 SQL 下拉里的表单变量替换。
41
41
 
42
42
  `sys_menu.MicroServiceId` 的字段值变更 V8 必须把 `V8.ThisValue` 传给页面列表加载函数,例如 `window.LoadMicroServicePages(V8, false, V8.ThisValue || V8.Form.MicroServiceId)`;不要只读取 `V8.Form.MicroServiceId`,因为字段变更触发瞬间表单模型可能仍是旧值或显示文本。页面列表加载函数必须支持从选中对象、保存 Id、`名称(MsKey)` 文本中解析服务,并在按 `MicroServiceId` 查询为空时按 `MicroServiceKey` 兜底查询。
43
43
 
@@ -70,30 +70,30 @@ VS Code 插件执行前端微服务构建前必须先安全清理当前项目自
70
70
  - `routes` 是页面源码、`microi.routes.json`、发布路由和菜单绑定的共同事实源;一条路由只生成一个页面文件,必须明确 `path/name/title/sourceFile/isHome`。不能为了提供默认首页额外生成一个未被需求或菜单使用的第三页面。
71
71
  - 脚手架完成后依次执行:`npm install`、本地构建、`microi_create_microservice`、`microi_sync_microservice_source`、`microi_publish_application_directory_stream`。真实编译目录优先流式发布;只有当前服务器尚未部署流式端点且产物很小时,才允许临时使用兼容的 `microi_publish_microservice`,并在交付结论中如实注明。
72
72
  - 发布回读取得 `sys_microiservice.Id` 与每条 `sys_microiservice_page.Id` 后,使用 `microi_create_module` 一次传入 `openType=MicroService`、`microServiceId`、`microServicePageId`、`microServiceRoutePath`、`microServiceKey`。菜单工具必须写后回读这些字段;不得长期依赖“先建普通 URL 菜单,再手工补字段”的两步绕路。
73
- - 最终通过 `microi_get_application_context`、`microi_get_microservice`、`microi_get_module` 和真实登录后的友好菜单路由逐层验收;多个菜单至少往返切换 8 轮,检查标题与子路由不串页、缓存范围内输入/筛选/滚动保持、无 404/5xx/白屏/永久骨架屏/实例冲突。再打开第 6 个实例验证 LRU 冷启动,并关闭 Tab/退出登录验证精确销毁;保存 fullPage 截图后用 `view_image` 复核。
74
-
75
- ### 表单下拉 Data 动态对象选项
76
-
77
- 表单 V8 通过 `V8.FieldSet('字段名', 'Data', objectRows)` 动态写入下拉数据时,如果 `objectRows` 是对象数组,即使 `diy_field.Config.DataSource='Data'`,前端也必须按对象数据源处理,并使用 `SelectLabel/SelectSaveField` 或常见字段兜底生成 label/value。禁止把对象数组按普通字符串 Data 源过滤,否则会出现接口已有数据但下拉显示“无数据”的回归。
78
-
79
- ### 线上微服务到本地宿主的运行目标复现
80
-
81
- AI 收到线上 `/micro-app/{MsKey}/{RoutePath}` 地址并需要用本地 `Microi.Client` 排查时:
82
-
83
- 1. 在一次性隔离 browser context 打开线上地址并等待主框架初始化。
84
- 2. 优先读取 `window.__MICROI_RUNTIME_ENDPOINT__`。旧版没有该对象时,读取 URL、
85
- `window.ApiBase/window.OsClient`、`JSON.parse(localStorage.getItem('microi.net') || '{}')`;
86
- OsClient 仍为空再通过域名解析接口或成功请求确认。
87
- 3. 在新的独立 context 打开
88
- `http://localhost:61500/?OsClient=<encoded>&ApiBase=<encoded>#/micro-app/{MsKey}/{RoutePath}`。
89
- 4. 断言本地 `window.__MICROI_RUNTIME_ENDPOINT__` 与线上识别结果一致,再开始功能回归。若不一致,
90
- 先停止测试,不能把 `config.json` 指向的其它服务器结果当成目标租户证据。
91
-
92
- 同一个普通浏览器 Profile/Playwright context 不能并行承载不同租户;页面间会共享 Token、
93
- CurrentUser、ApiBase 和 OsClient。无痕窗口是人工第二租户的最低要求,但多个无痕窗口可能共享临时
94
- 会话;自动化必须一组运行目标一个 `browser.newContext()`。目标 API 还必须允许 localhost CORS。
95
-
96
- ### 复盘:历史 OpenIframe 打印入口在 Vue3 弹窗中空白
73
+ - 最终通过 `microi_get_application_context`、`microi_get_microservice`、`microi_get_module` 和真实登录后的友好菜单路由逐层验收;多个菜单至少往返切换 8 轮,检查标题与子路由不串页、缓存范围内输入/筛选/滚动保持、无 404/5xx/白屏/永久骨架屏/实例冲突。再打开第 6 个实例验证 LRU 冷启动,并关闭 Tab/退出登录验证精确销毁;保存 fullPage 截图后用 `view_image` 复核。
74
+
75
+ ### 表单下拉 Data 动态对象选项
76
+
77
+ 表单 V8 通过 `V8.FieldSet('字段名', 'Data', objectRows)` 动态写入下拉数据时,如果 `objectRows` 是对象数组,即使 `diy_field.Config.DataSource='Data'`,前端也必须按对象数据源处理,并使用 `SelectLabel/SelectSaveField` 或常见字段兜底生成 label/value。禁止把对象数组按普通字符串 Data 源过滤,否则会出现接口已有数据但下拉显示“无数据”的回归。
78
+
79
+ ### 线上微服务到本地宿主的运行目标复现
80
+
81
+ AI 收到线上 `/micro-app/{MsKey}/{RoutePath}` 地址并需要用本地 `Microi.Client` 排查时:
82
+
83
+ 1. 在一次性隔离 browser context 打开线上地址并等待主框架初始化。
84
+ 2. 优先读取 `window.__MICROI_RUNTIME_ENDPOINT__`。旧版没有该对象时,读取 URL、
85
+ `window.ApiBase/window.OsClient`、`JSON.parse(localStorage.getItem('microi.net') || '{}')`;
86
+ OsClient 仍为空再通过域名解析接口或成功请求确认。
87
+ 3. 在新的独立 context 打开
88
+ `http://localhost:61500/?OsClient=<encoded>&ApiBase=<encoded>#/micro-app/{MsKey}/{RoutePath}`。
89
+ 4. 断言本地 `window.__MICROI_RUNTIME_ENDPOINT__` 与线上识别结果一致,再开始功能回归。若不一致,
90
+ 先停止测试,不能把 `config.json` 指向的其它服务器结果当成目标租户证据。
91
+
92
+ 同一个普通浏览器 Profile/Playwright context 不能并行承载不同租户;页面间会共享 Token、
93
+ CurrentUser、ApiBase 和 OsClient。无痕窗口是人工第二租户的最低要求,但多个无痕窗口可能共享临时
94
+ 会话;自动化必须一组运行目标一个 `browser.newContext()`。目标 API 还必须允许 localhost CORS。
95
+
96
+ ### 复盘:历史 OpenIframe 打印入口在 Vue3 弹窗中空白
97
97
 
98
98
  - 触发场景:同一租户的旧正式版打印正常,最新版列表点击打印只打开空白抽屉;数据库中的当前按钮已改成 `PrintEngineView`,但运行态菜单缓存仍可能返回历史 `ComponentName: 'OpenIframe'`。
99
99
  - 根因:Vue3 全局组件表移除了 Vue2 的 `OpenIframe` 注册,动态组件只能渲染成未知标签;同时历史 `DataApi` 可能带有 `https:/host` 这种单斜杠协议地址。
@@ -149,7 +149,7 @@ Microi 的 AI 应用与应用商城只有一个主数据源:`sys_microistore`
149
149
  - 同一份 ApiKey/Token 摘要在 Overview 与 AI 页面复用同一个组件;Token 额度统一展示“总量/Total”,不要把总量写成“赠送”。复制密钥必须有明确成功或失败提示,并提供 Clipboard API 不可用时的兼容复制。
150
150
 
151
151
  <!-- /microi-progressive:chunk -->
152
- <!-- microi-progressive:chunk id=microi-client-frontend-013 sha256=8f876b46e20dce5020e17f87ac6f9acfb37c908ab27f7c9568d59e9e7a00d3b2 -->
152
+ <!-- microi-progressive:chunk id=microi-client-frontend-013 sha256=c4054f900b1f6af15ae9ffb483e7571570f9d2aa99a0e674ee0bb9a956f06172 -->
153
153
  ## 浏览器访问密钥路由
154
154
 
155
155
  - 固定看板免登录使用常量匿名路由 `/access-login`,密钥使用 `microi_ak_` 前缀,完整链接格式为 `{Microi.Client前端WebBase}/?OsClient={当前租户}#/access-login?access_key={密钥}&redirect={encodeURIComponent后的站内Hash路由}`。例如目标路由 `/mic/data-dashboard/preview/01KK988A0YPHKAM8SF216917HX` 必须生成 `redirect=%2Fmic%2Fdata-dashboard%2Fpreview%2F01KK988A0YPHKAM8SF216917HX`。生成器只复制当前 `OsClient`,不能把其它页面查询参数带进凭据链接,也不能把 API Server 当成前端 WebBase。
@@ -159,7 +159,7 @@ Microi 的 AI 应用与应用商城只有一个主数据源:`sys_microistore`
159
159
  - 兑换通过 `POST /api/SysUserAccessKey/Exchange` 的 JSON Body 完成。响应头中的短期 Token 继续交给平台统一请求层保存和轮换。
160
160
  - 创建界面默认按页面名称勾选,也支持粘贴完整页面网址自动解析;不能要求普通用户手写路由和物理表名。页面/数据均可选择“全部已授权”,内部值为 `*`,含义只是取消密钥层二次白名单,仍与目标帐号实时菜单、表单和行权限取交集。接口引擎与数据源引擎 Key 仍必须准确选择。
161
161
  - `_AccessKeySession=true` 且页面为准确白名单时只允许清单路径;页面范围为 `*` 时才加载目标帐号实时可用的动态路由,以便全部已授权菜单可访问。该前端限制只是体验和泄露面收窄,服务端仍必须校验 API、表和引擎权限。
162
- - 全部页面模式会调用 `/apiengine/platform-sys-menu?Action=GetSysMenuStep`,服务端只能在 `page:open + AllowedRoutes=*` 时放行;准确页面模式不得为了省事请求完整菜单树。页面渲染过程中使用 `FormEngineKey`、`TableId`、`ModuleEngineKey` 或 `_SysMenuId` 的请求都必须能被服务端映射到同一份表范围,不能通过换参数名绕过,也不能把合法的菜单 Id 请求误判为缺少表引用。
162
+ - 全部页面模式会调用 `/apiengine/platform-sys-menu?Action=GetSysMenuStep`,服务端只能在 `page:open + AllowedRoutes=*` 时放行;准确页面模式不得为了省事请求完整菜单树。页面渲染过程中使用 `FormEngineKey`、`TableId`、`ModuleEngineKey` 或 `_SysMenuId` 的请求都必须能被服务端映射到同一份表范围,不能通过换参数名绕过,也不能把合法的菜单 Id 请求误判为缺少表引用。
163
163
  - 列表和表单会把表 Key 或菜单 Id 放进动态友好地址,例如 `/api/FormEngine/GetTableData-{table-key}` 和 `/api/FormEngine/GetFormData-{table-key}`。访问密钥服务端必须先把这些地址归一化为标准 action,再按 `form:read/form:write` 对 URL 后缀与请求体中的表/菜单引用做一致性校验,并把菜单 Id 映射回绑定的 `DiyTableId` 校验数据范围;不能要求前端为了密钥会话退回另一套 URL,也不能对整个 `FormEngine` Controller 无条件放行。
164
164
  - 不要因为底层帐号是管理员而在访问密钥会话展示控制面入口或触发控制面预加载。`_AccessKeySession=true` 时,密码显示、密钥管理、表/字段/菜单设计、缓存/服务器管理、查看或踢出其它终端等功能必须保持不可用;后台任务中心最多读取和管理当前用户自己的任务。
165
165
  - `/access-login` 必须在普通 SSO 发现之前直接放行,兑换最多等待 20 秒并给出明确错误,不能让页面永久停在“正在自动登录”。
@@ -7,6 +7,8 @@ description: 在 Codex 或 DeepSeek Harness 中完成 Microi吾码 VS Code 扩
7
7
 
8
8
  本插件与 `Microi.VSCode`、`@microi.net/cli` 共用配置、Token、MCP Server 和 Microi Skills。不要另写原生 HTTP、SQL 或第二套认证实现。
9
9
 
10
+ 每次 Microi 对话先完整读取工作区 `microi.skills/workspace-conventions/SKILL.md`;工作区尚未初始化时读取本插件同级 `../workspace-conventions/SKILL.md`。按其中首部完成创始人身份识别及平台功能四项同步检查,再进入专项流程;完整规则只维护该基础入口,不复制到本路由。
11
+
10
12
  ## 非阻塞自动更新(强制)
11
13
 
12
14
  Codex Router 启动后会异步调用 bundled CLI 的 `microi update --background`。需要了解完整安装/诊断机制时读取同级 `microi-codex-installer/SKILL.md`;更新检查不得发生在用户工作之前,也不得让任务等待。