@microi.net/cli 6.1.8 → 6.1.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.
- package/.codebuddy-plugin/marketplace.json +2 -2
- package/.codebuddy-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +43 -43
- package/.mcp.json +1 -1
- package/.workbuddy-plugin/marketplace.json +2 -2
- package/.workbuddy-plugin/plugin.json +1 -1
- package/assets/build-meta.json +4 -4
- package/cordis.patch.yml +1 -1
- package/package.json +82 -82
- package/scripts/codex-marketplace.json +20 -20
- package/scripts/mcp-codex-stdio-adapter.js +189 -189
- package/scripts/mcp-server.js +100 -96
- package/scripts/mcp-trae-windows-launcher.cmd +21 -21
- package/scripts/microi-cli-mcp.js +7 -7
- package/scripts/microi-skills.meta.json +247 -235
- package/skills/.microi-skills-version.json +2 -2
- package/skills/.progressive-disclosure-manifest.json +72 -66
- package/skills/ai-engine/SKILL.md +303 -293
- package/skills/app-store/SKILL.md +2 -1
- package/skills/microi-client-frontend/SKILL.md +260 -252
- package/skills/microi-datasource-mapping/SKILL.md +4 -0
- package/skills/microi-deployment/SKILL.md +63 -5
- package/skills/microi-deployment/references/deployment-matrix.md +27 -0
- package/skills/microi-deployment/references/offline-installer.md +64 -0
- package/skills/microi-docs-coverage/references/capability-map.md +3 -3
- package/skills/microi-form-engine/SKILL.md +13 -0
- package/skills/microi-form-engine/references/component-catalog.md +1 -1
- package/skills/microi-microservice/SKILL.md +17 -0
- package/skills/microi-system-delivery/SKILL.md +8 -6
- package/skills/microi-system-delivery/references/delivery-pitfalls.md +50 -0
- package/skills/microi-system-delivery/references/progressive-01-/346/240/207/345/207/206/345/267/245/344/275/234/346/265/201.md +11 -9
- package/skills/microi-uniapp-frontend/SKILL.md +18 -3
- package/skills/module-engine/SKILL.md +4 -5
- package/skills/page-engine/SKILL.md +233 -215
- package/skills/print-engine/SKILL.md +5 -0
- package/skills/report-engine/SKILL.md +9 -0
- package/skills/report-engine/scripts/check-demo-coverage.mjs +88 -0
- package/skills/report-engine/scripts/check-demo-coverage.test.mjs +52 -0
- package/skills/scripts/sync-embedded-skills.mjs +4 -1
- package/skills/ui-design/SKILL.md +1 -1
- package/skills/uniapp-mall-assets/SKILL.md +5 -0
- package/skills/v8-file-upload/SKILL.md +18 -4
- package/skills/v8-file-upload/references/hotspot-offload-operations.md +16 -1
- package/skills/v8-saas-multi-tenant/SKILL.md +17 -4
- package/skills/v8-security/SKILL.md +20 -5
- package/skills/vision-engine/SKILL.md +114 -3
- package/skills/vision-engine/references/architecture-and-acceptance.md +8 -0
- package/skills/workspace-conventions/SKILL.md +9 -3
- 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 +4 -4
- package/skills/workspace-conventions/references/progressive-04-/345/267/245/344/275/234/345/214/272/344/270/216/345/271/263/345/217/260/344/270/223/351/241/271/344/277/235/351/232/234.md +22 -1
|
@@ -1,260 +1,268 @@
|
|
|
1
|
-
---
|
|
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 缓存/白屏恢复,以及页面、弹窗和抽屉行为。
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
> **Microi吾码基础规范(强制):** 任何 AI 模型与宿主每次新建或接续吾码任务,先完整读取 `../workspace-conventions/SKILL.md`,必须执行版本播报、`@microi.net/cli` 后台自动升级、Skills/MCP 同步和进度播报。安装与诊断读取 `../microi-codex-installer/SKILL.md`;更新失败延后重试,不阻断当前工作。
|
|
7
|
-
|
|
8
|
-
# Microi.Client 前台源码架构说明
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
1
|
+
---
|
|
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 缓存/白屏恢复,以及页面、弹窗和抽屉行为。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
> **Microi吾码基础规范(强制):** 任何 AI 模型与宿主每次新建或接续吾码任务,先完整读取 `../workspace-conventions/SKILL.md`,必须执行版本播报、`@microi.net/cli` 后台自动升级、Skills/MCP 同步和进度播报。安装与诊断读取 `../microi-codex-installer/SKILL.md`;更新失败延后重试,不阻断当前工作。
|
|
7
|
+
|
|
8
|
+
# Microi.Client 前台源码架构说明
|
|
9
|
+
|
|
10
|
+
## 登录回跳与 iframe 地址编码
|
|
11
|
+
|
|
12
|
+
- 退出、强制退出与登录回跳必须使用路由对象 `{path:'/login',query:{redirect:fullPath}}`,不能把 `fullPath` 拼接到 query 字符串。iframe 地址中的内层 `?`、`&`、`%` 属于目标地址,不能变成登录页或宿主的参数。
|
|
13
|
+
- `src/utils/iframe-route.js` 统一规范 `/iframe/<encoded URL>`,已由 Vue Router 解码的 `params.Url` 不再二次解码。修复历史 raw iframe 链接时仍保存内层百分号语义,不修改目标业务参数;普通站内路由和外部跳转拒绝规则继续有效。
|
|
14
|
+
- 真实回归覆盖编码地址打开、退出重登、直接刷新、历史 raw 链接、内层编码的 `&`/`/`/非ASCII与非法转义;同时确认页签标题、iframe真实src和内容可见,不能仅断言URL字符串相同。
|
|
15
|
+
|
|
16
|
+
表单设计保存请求必须使用 `DiyCommon.GetOsClient()`,不能将导入表定义残留的 `OsClient`
|
|
17
|
+
作为传输租户;元数据来源与当前会话租户是不同概念。回归应覆盖从另一租户迁入的表定义,
|
|
18
|
+
验证表和字段保存成功且会话保持有效,不通过放宽后端租户鉴权修复。
|
|
19
|
+
右上角授权类型优先读取公开启动配置 `SysConfig.PlatformEdition`,兼容旧版会话查询;
|
|
20
|
+
`SysConfig.HideSystemLicenseVersion` 缺省关闭,标签可点击跳转 `/license`,不能因一次请求失败永久消失。
|
|
21
|
+
|
|
16
22
|
<!-- microi-progressive:begin -->
|
|
17
|
-
<!-- microi-progressive:chunk id=microi-client-frontend-000 sha256=
|
|
18
|
-
## 单行文本插槽按钮约定
|
|
19
|
-
|
|
20
|
-
- `diy-input.vue` 的插槽按钮行为存储在 `diy_field.Config.SlotButtonV8Code`。
|
|
21
|
-
- 点击事件通过 `CallbackRunV8Code` 进入 `diy-form.vue` 的统一前端 V8 上下文,事件名为 `FieldSlotButtonClick`。
|
|
22
|
-
- 禁止再新增或依赖 `OpenTableId` 一类硬编码目标;打开表格、表单、微服务或调用接口均由 V8 代码决定。
|
|
23
|
-
- 历史键 `ReadOnlyButton` 继续兼容,设计器显示为【禁用插槽按钮】。
|
|
24
|
-
|
|
25
|
-
> 适用于修改 `Microi.Client/` 前台源码。新 AI 对话在动 `Microi.Client/src/views/form-engine` 前,应先阅读本 Skill,避免把分散在 SFC、mixins、utils、路由和低代码配置里的逻辑误判成不存在。
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
23
|
+
<!-- microi-progressive:chunk id=microi-client-frontend-000 sha256=ea9cdd10772c42cc8202aa50ed3f8bec0a41588b16539b2968f256c7ee05cd3a -->
|
|
24
|
+
## 单行文本插槽按钮约定
|
|
25
|
+
|
|
26
|
+
- `diy-input.vue` 的插槽按钮行为存储在 `diy_field.Config.SlotButtonV8Code`。
|
|
27
|
+
- 点击事件通过 `CallbackRunV8Code` 进入 `diy-form.vue` 的统一前端 V8 上下文,事件名为 `FieldSlotButtonClick`。
|
|
28
|
+
- 禁止再新增或依赖 `OpenTableId` 一类硬编码目标;打开表格、表单、微服务或调用接口均由 V8 代码决定。
|
|
29
|
+
- 历史键 `ReadOnlyButton` 继续兼容,设计器显示为【禁用插槽按钮】。
|
|
30
|
+
|
|
31
|
+
> 适用于修改 `Microi.Client/` 前台源码。新 AI 对话在动 `Microi.Client/src/views/form-engine` 前,应先阅读本 Skill,避免把分散在 SFC、mixins、utils、路由和低代码配置里的逻辑误判成不存在。
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
29
35
|
<!-- /microi-progressive:chunk -->
|
|
30
|
-
<!-- microi-progressive:chunk id=microi-client-frontend-001 sha256=
|
|
31
|
-
## 1. 技术栈和源码入口
|
|
32
|
-
|
|
33
|
-
### 详情评论、日志与版本的按需读取
|
|
34
|
-
|
|
35
|
-
- 评论用 `/api/FormEngine/AddFormComment`,只传 `ParentFormEngineKey/ParentTableRowId/_SysMenuId/Content/ParentCommentId/RequestId`。服务端固定作者、父表及回复上下文;同一提交重试必须复用 RequestId,兼容 GUID 与平台 `DiyCommon.NewGuid()` 实际生成的 ULID。
|
|
36
|
-
- 评论归属为 `diy_comment.ParentTableId + TableRowId`,新表字段与复合索引通过表单引擎应用交付,主库回读保证写后可见。已有 TableId 绑定兼容,空归属历史评论禁止仅按记录 Id 自动猜测或后台回填。
|
|
37
|
-
- `/api/FormEngine/GetFormRelatedData` 的日志和版本列表只含元信息;`HistoryContentMode=OnDemand` 时,点击动作再传 `LogId/VersionId` 读取一条,并要求返回 `Authorized`。不要预取全部正文或将版本 Data 装入列表长期缓存。
|
|
38
|
-
- 历史正文单独复核当前主库有效管理员、父菜单/表/记录,普通用户与 AccessKey 会话不能仅凭当前行可读获得历史原文。代码继续使用代码字段白名单,普通数据使用当前元数据和正常 Client 读取前后未改变的字段交集;字段被任意 DataFilter、文件/模块权限隐藏、删除或改写时,不开放其历史值。密码控件、加密列、嵌套凭据及连接等敏感配置继续排除;SaaS 配置历史只允许明确安全字段白名单。
|
|
39
|
-
- 历史读取观察既有父记录管线,不重新执行历史 V8,不新读业务原行、不触发业务写入。局部版本比较/加载只涉及可读快照字段,保存继续走正常表单鉴权和事件。
|
|
40
|
-
- 表、记录、菜单、ApiBase/OsClient 或表单代次变化时同步清空列表、计数、评论/回复与历史弹窗,并作废旧响应。头像解析和按需正文 Promise 恢复后再次核归属;同一记录重新打开也要生成新代次,不能用列表非空代替当前记录已加载。
|
|
41
|
-
- 不得为了修复右栏恢复调度器通用 FormEngine 状态写回、启动历史回填或无变化版本写入。必须同时运行评论归属/去重、按需读取以及 ScheduleRuntimeTimeWriter、V8CodeVersionService 的性能回归。
|
|
42
|
-
|
|
43
|
-
- Vue 3 + Options API + mixins,构建工具是 Vite。
|
|
44
|
-
- UI 主要使用 Element Plus、FontAwesome、项目内 `dynamic-icon`。
|
|
45
|
-
- 状态入口:`src/pinia`,常用 `useDiyStore()` 读取 `GetCurrentUser`、`OsClient`、终端类型等。
|
|
46
|
-
- 低代码主入口集中在 `src/views/form-engine/`,不要只看一个 `.vue` 文件就下结论。
|
|
47
|
-
|
|
48
|
-
常见入口:
|
|
49
|
-
|
|
50
|
-
| 场景 | 关键文件 |
|
|
51
|
-
|------|----------|
|
|
52
|
-
| 列表页 | `diy-table.vue` + `mixins/diy-table-*.mixin.js` |
|
|
53
|
-
| 表单容器 | `diy-form-full.vue` + `mixins/diy-form-full-*.mixin.js` |
|
|
54
|
-
| 表单字段渲染 | `diy-form.vue` + `mixins/diy-form-*.mixin.js` |
|
|
55
|
-
| 字段组件 | `diy-field-component/*.vue` |
|
|
56
|
-
| 工作流右侧面板 | `form-right-panel.vue`、`workflow/wf-work-handler.vue` |
|
|
57
|
-
| 表单设计器 | `diy-design.vue`、`diy-components/*` |
|
|
58
|
-
| 通用 V8/低代码工具 | `src/utils/diy.common.js`、`src/utils/v8-*.js` |
|
|
59
|
-
|
|
60
|
-
---
|
|
61
|
-
|
|
36
|
+
<!-- microi-progressive:chunk id=microi-client-frontend-001 sha256=60265fdc9842dcc4f032f80e1a93b88dd5f47f1261d0fa7334c2a7eac8d31c4c -->
|
|
37
|
+
## 1. 技术栈和源码入口
|
|
38
|
+
|
|
39
|
+
### 详情评论、日志与版本的按需读取
|
|
40
|
+
|
|
41
|
+
- 评论用 `/api/FormEngine/AddFormComment`,只传 `ParentFormEngineKey/ParentTableRowId/_SysMenuId/Content/ParentCommentId/RequestId`。服务端固定作者、父表及回复上下文;同一提交重试必须复用 RequestId,兼容 GUID 与平台 `DiyCommon.NewGuid()` 实际生成的 ULID。
|
|
42
|
+
- 评论归属为 `diy_comment.ParentTableId + TableRowId`,新表字段与复合索引通过表单引擎应用交付,主库回读保证写后可见。已有 TableId 绑定兼容,空归属历史评论禁止仅按记录 Id 自动猜测或后台回填。
|
|
43
|
+
- `/api/FormEngine/GetFormRelatedData` 的日志和版本列表只含元信息;`HistoryContentMode=OnDemand` 时,点击动作再传 `LogId/VersionId` 读取一条,并要求返回 `Authorized`。不要预取全部正文或将版本 Data 装入列表长期缓存。
|
|
44
|
+
- 历史正文单独复核当前主库有效管理员、父菜单/表/记录,普通用户与 AccessKey 会话不能仅凭当前行可读获得历史原文。代码继续使用代码字段白名单,普通数据使用当前元数据和正常 Client 读取前后未改变的字段交集;字段被任意 DataFilter、文件/模块权限隐藏、删除或改写时,不开放其历史值。密码控件、加密列、嵌套凭据及连接等敏感配置继续排除;SaaS 配置历史只允许明确安全字段白名单。
|
|
45
|
+
- 历史读取观察既有父记录管线,不重新执行历史 V8,不新读业务原行、不触发业务写入。局部版本比较/加载只涉及可读快照字段,保存继续走正常表单鉴权和事件。
|
|
46
|
+
- 表、记录、菜单、ApiBase/OsClient 或表单代次变化时同步清空列表、计数、评论/回复与历史弹窗,并作废旧响应。头像解析和按需正文 Promise 恢复后再次核归属;同一记录重新打开也要生成新代次,不能用列表非空代替当前记录已加载。
|
|
47
|
+
- 不得为了修复右栏恢复调度器通用 FormEngine 状态写回、启动历史回填或无变化版本写入。必须同时运行评论归属/去重、按需读取以及 ScheduleRuntimeTimeWriter、V8CodeVersionService 的性能回归。
|
|
48
|
+
|
|
49
|
+
- Vue 3 + Options API + mixins,构建工具是 Vite。
|
|
50
|
+
- UI 主要使用 Element Plus、FontAwesome、项目内 `dynamic-icon`。
|
|
51
|
+
- 状态入口:`src/pinia`,常用 `useDiyStore()` 读取 `GetCurrentUser`、`OsClient`、终端类型等。
|
|
52
|
+
- 低代码主入口集中在 `src/views/form-engine/`,不要只看一个 `.vue` 文件就下结论。
|
|
53
|
+
|
|
54
|
+
常见入口:
|
|
55
|
+
|
|
56
|
+
| 场景 | 关键文件 |
|
|
57
|
+
|------|----------|
|
|
58
|
+
| 列表页 | `diy-table.vue` + `mixins/diy-table-*.mixin.js` |
|
|
59
|
+
| 表单容器 | `diy-form-full.vue` + `mixins/diy-form-full-*.mixin.js` |
|
|
60
|
+
| 表单字段渲染 | `diy-form.vue` + `mixins/diy-form-*.mixin.js` |
|
|
61
|
+
| 字段组件 | `diy-field-component/*.vue` |
|
|
62
|
+
| 工作流右侧面板 | `form-right-panel.vue`、`workflow/wf-work-handler.vue` |
|
|
63
|
+
| 表单设计器 | `diy-design.vue`、`diy-components/*` |
|
|
64
|
+
| 通用 V8/低代码工具 | `src/utils/diy.common.js`、`src/utils/v8-*.js` |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
62
68
|
<!-- /microi-progressive:chunk -->
|
|
63
|
-
<!-- microi-progressive:chunk id=microi-client-frontend-002 sha256=
|
|
64
|
-
## 2. 表单引擎三层结构
|
|
65
|
-
|
|
66
|
-
### 模块级跨端视图
|
|
67
|
-
|
|
68
|
-
- Detail/Edit/List/Card 视图属于 `sys_menu`,使用物理字段 `EnableViewSchema`、`ViewSchemaVersion`、`ViewConfigVersion`、`ViewSchema`。其中 `EnableViewSchema` 只控制 Detail/Edit 自定义表单视图,List/Card 有有效配置时始终生效;两个版本字段可空,默认按 `1.0/1` 处理。
|
|
69
|
-
- 顶层 PC `diy-table` 即使没有 List ViewSchema,也默认显示约 40 至 52px 的紧凑模块标题。`selectModuleView()` 只能对 List/Card 绕过 `EnableViewSchema`;Detail/Edit 必须继续显式启用,不能被列表 fallback 误接管。
|
|
70
|
-
- 存量模块没有 Hero 配置时,PC/移动端从真实 `StatisticsFields`、`DataCount/PageCount`、当前页数值求和或当前页真实状态分布生成兜底指标;当前页口径必须写进标签,严禁随机值或伪造全表汇总。
|
|
71
|
-
- `Layout.List.Columns[].MinWidth` 优先于普通 `diy_field.TableWidth` 和末列自适应;缺少持久宽度时按标题/地址、日期/编码、数值、状态等字段语义稳定推断。
|
|
72
|
-
- `diy_table.DiyConfig`、`diy_field.DiyConfig`、`sys_menu.DiyConfig` 均为废弃兼容字段;禁止向其中写入任何新功能配置。
|
|
73
|
-
- Text、Select、ImgUpload、Map 等数据控件继续放在 `diy-field-component`。
|
|
74
|
-
- EntityHero、MetricStrip、ActionGrid、ResponsiveSection 是独立展示区块,放在 `form-view-blocks`,禁止用虚拟字段或 DevComponent 模拟。
|
|
75
|
-
- PC 详情使用只读视图渲染器,编辑继续复用完整 `DiyForm`。未被视图区块引用的字段必须有兜底分组,不能因移动端视图精简而丢失 PC 字段。
|
|
76
|
-
- 小程序只执行白名单 ActionSchema,不执行任意前端 V8。复杂业务统一调用接口引擎,重要提交校验放在后端表单事件。
|
|
77
|
-
- 新视图缺失、禁用或解析失败时必须回退到现有模块/表单,禁止白屏。
|
|
78
|
-
|
|
79
|
-
### `diy-table.vue`
|
|
80
|
-
|
|
81
|
-
列表页/模块页容器,负责:
|
|
82
|
-
|
|
83
|
-
- 读取 `sys_menu` 得到 `SysMenuModel`。
|
|
84
|
-
- 读取 `diy_table` / `diy_field` 得到表结构和字段列表。
|
|
85
|
-
- 渲染搜索、表格、卡片、行按钮、批量按钮、页面按钮、PageTabs。
|
|
86
|
-
- 打开表单:通过 `refDiyTable_DiyFormDialog.Init({...})` 调用 `diy-form-full.vue`。
|
|
87
|
-
- 权限:`SysMenuId`、`GetCurrentUser._RoleLimits`、`Permission` 控制增删改查和动态按钮。
|
|
88
|
-
|
|
89
|
-
定制页嵌入标准列表时,优先复用 `diy-table` 的运行时 props,不要复制表格实现:
|
|
90
|
-
|
|
91
|
-
- `PropsSelectApi`、`PropsRequestParams`:覆盖列表接口并追加业务参数;禁止透传 Token/Authorization。
|
|
92
|
-
- `PropsVirtualFields`、`PropsSelectFields`、`PropsSearchFields`:补充接口虚拟字段并精确控制列和搜索项。
|
|
93
|
-
- `PropsMenuModelPatch`:仅在当前实例覆盖 `MoreBtns`、`BatchSelectMoreBtns`、`PageTabs`、显隐代码等,不写回 `sys_menu`。
|
|
94
|
-
- `PropsHideImportExport`、`PropsHideMoreFunctions`、`PropsHideAdminDesign`:嵌入页需要保持原业务工具边界时隐藏标准辅助工具。
|
|
95
|
-
- 业务动作仍由 `ParentV8` 暴露给按钮/模板 V8;`diy-table` 只负责通用渲染、权限和分页。
|
|
96
|
-
|
|
97
|
-
### `diy-form-full.vue`
|
|
98
|
-
|
|
99
|
-
- TableChild 详情的菜单元数据和关联数据请求都要携带完整 `_TableChildAuth`,嵌套子表保留 `Parent` 链;后端 `FormRelatedDataService` 的父记录授权参数也必须转交。不能以隐藏子菜单普遍授予 Read 代替父模块权限、父行范围、配置绑定和子行归属校验。
|
|
100
|
-
|
|
101
|
-
- 同次打开按服务器、租户、菜单、表、完整授权上下文和打开代次合并菜单请求;初始化失败后的记录回调不重复请求/提示,但主动重试、重开和切记录仍可重试。关闭或切记录后旧响应不得覆盖新状态。
|
|
102
|
-
|
|
103
|
-
- 关联 Counts 等真实表元数据与记录回调完成再调度;日志、评论、代码版本全部关闭时跳过。相同上下文在途读取可合并,菜单与 Counts 的错误提示按各自分支判断。修改时运行 `tests/tablechild-detail-context.spec.mjs`,并用只有父模块 Read 的真实账号验证正常详情、嵌套、重开、重试及伪造/跨父记录拒绝。
|
|
104
|
-
|
|
105
|
-
表单外壳,不直接渲染字段。它负责:
|
|
106
|
-
|
|
107
|
-
- Page/Dialog/Drawer 三种打开方式。
|
|
108
|
-
- 顶部保存、编辑、关闭、删除、`sys_menu.FormBtns` 动态按钮。
|
|
109
|
-
- 移动端 FAB 菜单。
|
|
110
|
-
- 右侧数据日志、评论、工作流面板。
|
|
111
|
-
- 调用内部 `DiyForm` 并接收 `CallbackSetFormData`、`CallbackSetDiyTableModel`。
|
|
112
|
-
- 自身根据 `SysMenuId` 拉取 `sys_menu`,再执行 `HandlerBtns/HandlerBtnsAsync` 计算 `FormBtns` 显隐。
|
|
113
|
-
|
|
114
|
-
注意:`diy-form-full.vue` 的方法大量来自 mixins:
|
|
115
|
-
|
|
116
|
-
| mixin | 职责 |
|
|
117
|
-
|-------|------|
|
|
118
|
-
| `diy-form-full-state.mixin.js` | data/computed、路由 Page 模式、mounted/activated/deactivated |
|
|
119
|
-
| `diy-form-full-dialog.mixin.js` | OpenDetail、Dialog/Drawer/Page 初始化、关闭和重载 |
|
|
120
|
-
| `diy-form-full-data.mixin.js` | 保存、删除、刷新表单/子表等数据操作 |
|
|
121
|
-
| `diy-form-full-workflow.mixin.js` | StartWork/SendWork 与表单提交整合 |
|
|
122
|
-
| `diy-form-full-mobile.mixin.js` | 移动端 FAB、手势返回、位置保存 |
|
|
123
|
-
| `diy-form-full-permission.mixin.js` | 权限判断 |
|
|
124
|
-
| `diy-form-full-cleanup.mixin.js` | 清理 watcher、全局事件、引用 |
|
|
125
|
-
|
|
126
|
-
### `diy-form.vue`
|
|
127
|
-
|
|
128
|
-
真正的字段表单,负责:
|
|
129
|
-
|
|
130
|
-
- 根据 `diy_field` 分组/Tab/布局渲染字段组件。
|
|
131
|
-
- 执行字段前端 V8、表单前端 V8、模板 V8。
|
|
132
|
-
- 维护 `FormDiyTableModel`、`OldForm`、`DiyFieldList`。
|
|
133
|
-
- 对外 emit `CallbackSetFormData` 和 `CallbackSetDiyTableModel` 给 `diy-form-full.vue`。
|
|
134
|
-
|
|
135
|
-
### 前端 V8 上下文不是固定 DTO
|
|
136
|
-
|
|
137
|
-
`DiyCommon.SetV8DefaultValue()` 只创建基础能力,`diy-table.vue`、`diy-form.vue`、`diy-form-full.vue` 和各 mixin 会按事件再挂载动态属性。新增 API 或修正文档时必须同时核对这些入口,不能只看一个 `V8` 对象字面量。
|
|
138
|
-
|
|
139
|
-
常见上下文差异:
|
|
140
|
-
|
|
141
|
-
| 场景 | 可靠上下文 |
|
|
142
|
-
|------|------------|
|
|
143
|
-
| 表单字段值变化 | `V8.Form`、`V8.ThisValue`、`V8.EventName='FieldValueChange'` |
|
|
144
|
-
| 普通 `diy-form` 字段变化 | 不保证存在 `V8.OldValue`;需要旧值时应由业务代码自己保存 |
|
|
145
|
-
| 列表行内编辑 | `V8.Row`、`V8.RowIndex`、`V8.ThisValue`、`V8.OldValue` |
|
|
146
|
-
| 表单字段键盘事件 | `V8.EventName='FieldOnKeyup'`、`V8.KeyCode` |
|
|
147
|
-
| 列表字段键盘事件 | `V8.EventName='TableFieldOnKeyup'`、`V8.KeyCode` |
|
|
148
|
-
| 字段插槽按钮 | `V8.EventName='FieldSlotButtonClick'`、`V8.Event` |
|
|
149
|
-
| 列表按钮/批量按钮 | `V8.Row` 或 `V8.Rows`、`V8.TableRowSelected`、`V8.SysMenuId` |
|
|
150
|
-
|
|
151
|
-
`V8.FormSet()` 在普通 `diy-form` 中可能继续触发目标字段 V8;在 `diy-table` 行/模板上下文中通常只更新当前行或模板数据。需要静默赋值时直接修改当前上下文模型,并防止字段事件递归。
|
|
152
|
-
|
|
153
|
-
标准前端 V8 会挂载 `FormEngine`、`ApiEngine`、`DataSourceEngine`、`Http`、`Base64` 等能力;虽然 `DiyCommon.ModuleEngine` 有底层实现,标准全局 V8 当前并未挂载 `V8.ModuleEngine`,文档和编辑器提示不得把它当作可用 API。
|
|
154
|
-
|
|
155
|
-
`V8.SysConfig` 是面向浏览器的脱敏公开配置投影,不得依赖其中出现数据库连接串、对象存储密钥、短信/邮件密码或其它 SaaS 私密字段。
|
|
156
|
-
|
|
157
|
-
### 框架来源标识与水印(强制)
|
|
158
|
-
|
|
159
|
-
- 微服务和定制组件的来源标识必须由 Microi.Client 宿主统一渲染,子应用不得各自实现。微服务来源入口只向当前登录用户 `Level >= 9999` 展示,普通用户、未知或非法等级、受限访问密钥会话不显示标签、关闭按钮及源码详情;不从账号名称、`_IsAdmin` 或子应用元数据推断权限。定制组件的原有来源展示保持兼容,不新增 `RenderSourceBadgeMode`、自动收起或全局关闭配置。
|
|
160
|
-
- `V8.OpenAppDialog` / Drawer 等标准弹层的来源标识放在标题文字之后,不提供关闭按钮;菜单/整页微服务由 `micro-app/host.vue` 在内容区右上角直接渲染,管理员可手动关闭当前页面实例的标识,切换实例或账号后恢复。当前用户等级降低后立即隐藏入口并关闭已展开详情;这只控制来源辅助工具,不能改变业务菜单、关闭 Tab、弹层或后端源码/MCP 鉴权。不得依赖外围路由组件猜测菜单微服务。修改时运行 `tests/microservice-source-badge-permission.spec.mjs` 与既有来源及宿主契约回归。
|
|
161
|
-
-
|
|
162
|
-
- 框架水印覆盖 `100vw × 100vh` 且固定 `pointer-events:none`。开启后内容空值默认 `$SysTitle$ - $UserName$`(用户名为空回退账号)、方向默认 `DiagonalUp`、密度默认 `Comfortable`、字号空值/0 默认 14,透明度空值/0 默认 30;亮色、深色、弹层、键盘和减少动态效果模式都要验收。
|
|
163
|
-
|
|
164
|
-
### 用户级界面偏好(强制)
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
-
|
|
171
|
-
-
|
|
172
|
-
-
|
|
173
|
-
-
|
|
174
|
-
-
|
|
175
|
-
-
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
- `
|
|
181
|
-
- `
|
|
182
|
-
-
|
|
183
|
-
-
|
|
184
|
-
-
|
|
185
|
-
-
|
|
186
|
-
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
69
|
+
<!-- microi-progressive:chunk id=microi-client-frontend-002 sha256=e3952f5ff503da3ddb350f01feb9a4da153ba36c8a49e69cc1f52a660c458caa -->
|
|
70
|
+
## 2. 表单引擎三层结构
|
|
71
|
+
|
|
72
|
+
### 模块级跨端视图
|
|
73
|
+
|
|
74
|
+
- Detail/Edit/List/Card 视图属于 `sys_menu`,使用物理字段 `EnableViewSchema`、`ViewSchemaVersion`、`ViewConfigVersion`、`ViewSchema`。其中 `EnableViewSchema` 只控制 Detail/Edit 自定义表单视图,List/Card 有有效配置时始终生效;两个版本字段可空,默认按 `1.0/1` 处理。
|
|
75
|
+
- 顶层 PC `diy-table` 即使没有 List ViewSchema,也默认显示约 40 至 52px 的紧凑模块标题。`selectModuleView()` 只能对 List/Card 绕过 `EnableViewSchema`;Detail/Edit 必须继续显式启用,不能被列表 fallback 误接管。
|
|
76
|
+
- 存量模块没有 Hero 配置时,PC/移动端从真实 `StatisticsFields`、`DataCount/PageCount`、当前页数值求和或当前页真实状态分布生成兜底指标;当前页口径必须写进标签,严禁随机值或伪造全表汇总。
|
|
77
|
+
- `Layout.List.Columns[].MinWidth` 优先于普通 `diy_field.TableWidth` 和末列自适应;缺少持久宽度时按标题/地址、日期/编码、数值、状态等字段语义稳定推断。
|
|
78
|
+
- `diy_table.DiyConfig`、`diy_field.DiyConfig`、`sys_menu.DiyConfig` 均为废弃兼容字段;禁止向其中写入任何新功能配置。
|
|
79
|
+
- Text、Select、ImgUpload、Map 等数据控件继续放在 `diy-field-component`。
|
|
80
|
+
- EntityHero、MetricStrip、ActionGrid、ResponsiveSection 是独立展示区块,放在 `form-view-blocks`,禁止用虚拟字段或 DevComponent 模拟。
|
|
81
|
+
- PC 详情使用只读视图渲染器,编辑继续复用完整 `DiyForm`。未被视图区块引用的字段必须有兜底分组,不能因移动端视图精简而丢失 PC 字段。
|
|
82
|
+
- 小程序只执行白名单 ActionSchema,不执行任意前端 V8。复杂业务统一调用接口引擎,重要提交校验放在后端表单事件。
|
|
83
|
+
- 新视图缺失、禁用或解析失败时必须回退到现有模块/表单,禁止白屏。
|
|
84
|
+
|
|
85
|
+
### `diy-table.vue`
|
|
86
|
+
|
|
87
|
+
列表页/模块页容器,负责:
|
|
88
|
+
|
|
89
|
+
- 读取 `sys_menu` 得到 `SysMenuModel`。
|
|
90
|
+
- 读取 `diy_table` / `diy_field` 得到表结构和字段列表。
|
|
91
|
+
- 渲染搜索、表格、卡片、行按钮、批量按钮、页面按钮、PageTabs。
|
|
92
|
+
- 打开表单:通过 `refDiyTable_DiyFormDialog.Init({...})` 调用 `diy-form-full.vue`。
|
|
93
|
+
- 权限:`SysMenuId`、`GetCurrentUser._RoleLimits`、`Permission` 控制增删改查和动态按钮。
|
|
94
|
+
|
|
95
|
+
定制页嵌入标准列表时,优先复用 `diy-table` 的运行时 props,不要复制表格实现:
|
|
96
|
+
|
|
97
|
+
- `PropsSelectApi`、`PropsRequestParams`:覆盖列表接口并追加业务参数;禁止透传 Token/Authorization。
|
|
98
|
+
- `PropsVirtualFields`、`PropsSelectFields`、`PropsSearchFields`:补充接口虚拟字段并精确控制列和搜索项。
|
|
99
|
+
- `PropsMenuModelPatch`:仅在当前实例覆盖 `MoreBtns`、`BatchSelectMoreBtns`、`PageTabs`、显隐代码等,不写回 `sys_menu`。
|
|
100
|
+
- `PropsHideImportExport`、`PropsHideMoreFunctions`、`PropsHideAdminDesign`:嵌入页需要保持原业务工具边界时隐藏标准辅助工具。
|
|
101
|
+
- 业务动作仍由 `ParentV8` 暴露给按钮/模板 V8;`diy-table` 只负责通用渲染、权限和分页。
|
|
102
|
+
|
|
103
|
+
### `diy-form-full.vue`
|
|
104
|
+
|
|
105
|
+
- TableChild 详情的菜单元数据和关联数据请求都要携带完整 `_TableChildAuth`,嵌套子表保留 `Parent` 链;后端 `FormRelatedDataService` 的父记录授权参数也必须转交。不能以隐藏子菜单普遍授予 Read 代替父模块权限、父行范围、配置绑定和子行归属校验。
|
|
106
|
+
|
|
107
|
+
- 同次打开按服务器、租户、菜单、表、完整授权上下文和打开代次合并菜单请求;初始化失败后的记录回调不重复请求/提示,但主动重试、重开和切记录仍可重试。关闭或切记录后旧响应不得覆盖新状态。
|
|
108
|
+
|
|
109
|
+
- 关联 Counts 等真实表元数据与记录回调完成再调度;日志、评论、代码版本全部关闭时跳过。相同上下文在途读取可合并,菜单与 Counts 的错误提示按各自分支判断。修改时运行 `tests/tablechild-detail-context.spec.mjs`,并用只有父模块 Read 的真实账号验证正常详情、嵌套、重开、重试及伪造/跨父记录拒绝。
|
|
110
|
+
|
|
111
|
+
表单外壳,不直接渲染字段。它负责:
|
|
112
|
+
|
|
113
|
+
- Page/Dialog/Drawer 三种打开方式。
|
|
114
|
+
- 顶部保存、编辑、关闭、删除、`sys_menu.FormBtns` 动态按钮。
|
|
115
|
+
- 移动端 FAB 菜单。
|
|
116
|
+
- 右侧数据日志、评论、工作流面板。
|
|
117
|
+
- 调用内部 `DiyForm` 并接收 `CallbackSetFormData`、`CallbackSetDiyTableModel`。
|
|
118
|
+
- 自身根据 `SysMenuId` 拉取 `sys_menu`,再执行 `HandlerBtns/HandlerBtnsAsync` 计算 `FormBtns` 显隐。
|
|
119
|
+
|
|
120
|
+
注意:`diy-form-full.vue` 的方法大量来自 mixins:
|
|
121
|
+
|
|
122
|
+
| mixin | 职责 |
|
|
123
|
+
|-------|------|
|
|
124
|
+
| `diy-form-full-state.mixin.js` | data/computed、路由 Page 模式、mounted/activated/deactivated |
|
|
125
|
+
| `diy-form-full-dialog.mixin.js` | OpenDetail、Dialog/Drawer/Page 初始化、关闭和重载 |
|
|
126
|
+
| `diy-form-full-data.mixin.js` | 保存、删除、刷新表单/子表等数据操作 |
|
|
127
|
+
| `diy-form-full-workflow.mixin.js` | StartWork/SendWork 与表单提交整合 |
|
|
128
|
+
| `diy-form-full-mobile.mixin.js` | 移动端 FAB、手势返回、位置保存 |
|
|
129
|
+
| `diy-form-full-permission.mixin.js` | 权限判断 |
|
|
130
|
+
| `diy-form-full-cleanup.mixin.js` | 清理 watcher、全局事件、引用 |
|
|
131
|
+
|
|
132
|
+
### `diy-form.vue`
|
|
133
|
+
|
|
134
|
+
真正的字段表单,负责:
|
|
135
|
+
|
|
136
|
+
- 根据 `diy_field` 分组/Tab/布局渲染字段组件。
|
|
137
|
+
- 执行字段前端 V8、表单前端 V8、模板 V8。
|
|
138
|
+
- 维护 `FormDiyTableModel`、`OldForm`、`DiyFieldList`。
|
|
139
|
+
- 对外 emit `CallbackSetFormData` 和 `CallbackSetDiyTableModel` 给 `diy-form-full.vue`。
|
|
140
|
+
|
|
141
|
+
### 前端 V8 上下文不是固定 DTO
|
|
142
|
+
|
|
143
|
+
`DiyCommon.SetV8DefaultValue()` 只创建基础能力,`diy-table.vue`、`diy-form.vue`、`diy-form-full.vue` 和各 mixin 会按事件再挂载动态属性。新增 API 或修正文档时必须同时核对这些入口,不能只看一个 `V8` 对象字面量。
|
|
144
|
+
|
|
145
|
+
常见上下文差异:
|
|
146
|
+
|
|
147
|
+
| 场景 | 可靠上下文 |
|
|
148
|
+
|------|------------|
|
|
149
|
+
| 表单字段值变化 | `V8.Form`、`V8.ThisValue`、`V8.EventName='FieldValueChange'` |
|
|
150
|
+
| 普通 `diy-form` 字段变化 | 不保证存在 `V8.OldValue`;需要旧值时应由业务代码自己保存 |
|
|
151
|
+
| 列表行内编辑 | `V8.Row`、`V8.RowIndex`、`V8.ThisValue`、`V8.OldValue` |
|
|
152
|
+
| 表单字段键盘事件 | `V8.EventName='FieldOnKeyup'`、`V8.KeyCode` |
|
|
153
|
+
| 列表字段键盘事件 | `V8.EventName='TableFieldOnKeyup'`、`V8.KeyCode` |
|
|
154
|
+
| 字段插槽按钮 | `V8.EventName='FieldSlotButtonClick'`、`V8.Event` |
|
|
155
|
+
| 列表按钮/批量按钮 | `V8.Row` 或 `V8.Rows`、`V8.TableRowSelected`、`V8.SysMenuId` |
|
|
156
|
+
|
|
157
|
+
`V8.FormSet()` 在普通 `diy-form` 中可能继续触发目标字段 V8;在 `diy-table` 行/模板上下文中通常只更新当前行或模板数据。需要静默赋值时直接修改当前上下文模型,并防止字段事件递归。
|
|
158
|
+
|
|
159
|
+
标准前端 V8 会挂载 `FormEngine`、`ApiEngine`、`DataSourceEngine`、`Http`、`Base64` 等能力;虽然 `DiyCommon.ModuleEngine` 有底层实现,标准全局 V8 当前并未挂载 `V8.ModuleEngine`,文档和编辑器提示不得把它当作可用 API。
|
|
160
|
+
|
|
161
|
+
`V8.SysConfig` 是面向浏览器的脱敏公开配置投影,不得依赖其中出现数据库连接串、对象存储密钥、短信/邮件密码或其它 SaaS 私密字段。
|
|
162
|
+
|
|
163
|
+
### 框架来源标识与水印(强制)
|
|
164
|
+
|
|
165
|
+
- 微服务和定制组件的来源标识必须由 Microi.Client 宿主统一渲染,子应用不得各自实现。微服务来源入口只向当前登录用户 `Level >= 9999` 展示,普通用户、未知或非法等级、受限访问密钥会话不显示标签、关闭按钮及源码详情;不从账号名称、`_IsAdmin` 或子应用元数据推断权限。定制组件的原有来源展示保持兼容,不新增 `RenderSourceBadgeMode`、自动收起或全局关闭配置。
|
|
166
|
+
- `V8.OpenAppDialog` / Drawer 等标准弹层的来源标识放在标题文字之后,不提供关闭按钮;菜单/整页微服务由 `micro-app/host.vue` 在内容区右上角直接渲染,管理员可手动关闭当前页面实例的标识,切换实例或账号后恢复。当前用户等级降低后立即隐藏入口并关闭已展开详情;这只控制来源辅助工具,不能改变业务菜单、关闭 Tab、弹层或后端源码/MCP 鉴权。不得依赖外围路由组件猜测菜单微服务。修改时运行 `tests/microservice-source-badge-permission.spec.mjs` 与既有来源及宿主契约回归。
|
|
167
|
+
- 来源标识使用可点击的 `button` 语义,普通按钮为 `cursor:pointer`,可拖动菜单胶囊使用 `grab/grabbing`;拖动阈值、边界和 Tab 右键详情遵守 `microi-microservice`。点击后用可拖动、居中、亮/暗色适配的大圆角 Element Plus 弹层展示 AppKey、PageKey、应用内/框架路由、版本、源码定位、运行入口、发布/挂载状态和租户坐标,并生成可复制的 MCP 修改指令;公开详情不得包含 DiyToken、访问密钥、私有配置或用户敏感字段。
|
|
168
|
+
- 框架水印覆盖 `100vw × 100vh` 且固定 `pointer-events:none`。开启后内容空值默认 `$SysTitle$ - $UserName$`(用户名为空回退账号)、方向默认 `DiagonalUp`、密度默认 `Comfortable`、字号空值/0 默认 14,透明度空值/0 默认 30;亮色、深色、弹层、键盘和减少动态效果模式都要验收。
|
|
169
|
+
|
|
170
|
+
### 用户级界面偏好(强制)
|
|
171
|
+
|
|
172
|
+
- 菜单前景独立于按钮前景与页面显示模式。主题设置在自定义颜色旁提供 `MenuTextColor=Auto/Light/Dark`(跟随主题/浅色/深色),默认按实际菜单背景选择。普通、选中、悬停、顶部与侧边弹出菜单必须使用同一前景契约;模式切换和主题重应用保留显式选择。沿当前账号偏好队列保存到 `sys_user.MenuTextColor`,个人中心同步回显;空值继承 `sys_config.MenuTextColor`,全局缺省 Auto。重置清空个人值。旧租户仅使用身份隔离的设备回退,禁止新增全局 localStorage 偏好。密度仅保留现有“小/标准/大”滑杆,不再增加同步的预设按钮组。修改时执行 `menu-text-color.spec.mjs`、偏好接口白名单与真实浏览器刷新恢复回归。
|
|
173
|
+
|
|
174
|
+
右上角主题设置的边角风格默认圆角;已安装 `sys_user.CornerStyle` 时从账号偏好恢复,旧租户才使用浏览器本地兼容值。根元素 `data-mci-corner-style` 控制全局角半径,覆盖动态挂载的 Element Plus 弹层。顶栏入口统一使用 40px 触控区域和 20px 图标,AI 入口使用图标组件,不使用图片。模块 `HideTableBanner`、`HideFormBanner` 只在值明确为 `1/true` 时隐藏对应 Banner,并跳过其专属统计请求;未安装开关字段的旧菜单继续显示。
|
|
175
|
+
|
|
176
|
+
- 边角风格先读取当前用户 `CornerStyle`:`round/square` 显式覆盖;空值或 `System` 继承租户 `sys_config.CornerStyle`,租户空值默认为圆角。不得把空个人值提前归一为 `round`,否则会阻断租户直角设置。
|
|
177
|
+
- 桌面经典布局使用 `NavigationLayout=Side/Top/TopSide`,个人空值或 `System` 继承租户,租户空值为侧边导航。`TopSide` 将一级放顶部,当前一级的二级及更深菜单复用原侧栏;单个子菜单仍留在侧栏,无可见子菜单时隐藏侧栏并释放内容宽度。侧栏仍支持收起及 `MenuChildExpandMode=System/Down/Right`。顶部导航复用当前权限路由、角标与外链,空间不足收纳到更多菜单;移动端仍采用底部导航。当前路由与一级归属由 `hybrid-navigation.js` 统一投影,禁止修改共享权限树。
|
|
178
|
+
- 侧栏与角色管理组织树共用 `MciResizablePane`:右边缘拖拽、可访问分隔条、方向键/Shift/Home/End 和收起按钮必须同样可用。`sys_user.SidebarWidth/RoleTreeWidth` 为 nullable 整数像素(160–600),`SidebarCollapsed/RoleTreeCollapsed` 为 nullable 0/1;使用当前账号的 Managed 偏好白名单保存。拖拽中仅预览,松开提交,取消或卸载释放指针。视口夹紧保留主内容宽度,不能把夹紧值覆盖长期偏好;窄屏禁拖,旧租户仅用账号/租户/API 隔离的设备回退。侧栏空宽度沿用 `sys_config.MenuWidth` 后回退240px,角色树默认240px。
|
|
179
|
+
- 顶部主导航与工作区 Tabs 是不同层级:`Top/TopSide` 的当前一级使用独立短底线,hover/focus 前景显式跟随可读主题,禁止继承 Element 的低对比品牌色。长弹出菜单使用独立主题表面、无异色顶边和内部滚动,嵌套层仍 Teleport;顶部菜单标题与品牌不显示 title/alt/Tooltip 类提示浮层,保留完整 aria-label 无障碍名称;顶栏整条背景色带须贴合视口或所属壳层左右边界,不能把内部 padding 当成全宽验收,内容区留白独立处理。窄视口“更多”菜单也遵守同一契约。
|
|
180
|
+
- 顶部导航整行(含功能图标和账号姓名)使用主题运行时的 `--sidebar-*` 可读表面与前景;主题面板和业务弹层保留自身语义表面。主题入口为齿轮,界面密度在同一主题面板调整,已安装 `sys_user.UiDensityScale` 时保存当前账号、个人空值继承 `sys_config.UiDensityScale`,旧租户才使用按租户/账号隔离的设备回退;AI 入口使用圆圈内 AI 字母 SVG,不能回退魔法棒或图片。
|
|
181
|
+
- 头像菜单【修改密码】使用标准 `DiyCustomDialog + MicroAppDialog` 打开现有平台服务 `/personal-settings`,仅传 `Data.Action=ChangePassword` 选择密码展示模式;不能用宿主输入决定目标账号/租户,不新建密码旁路。当前密码校验、Passkey/TOTP/严格人脸一次性票据与提交继续复用个人中心,成功或卸载清除密码输入。定向回归使用 `hybrid-navigation.spec.mjs`、`password-dialog.spec.mjs` 和个人偏好资源测试。
|
|
182
|
+
- 桌面壳层使用视口高度与可收缩的 flex 内容区,只有路由内容滚动,导航和 Tab 不随页面滚动;移动端仍保留文档滚动。用户入口含头像与姓名,不能使用纯图标的固定 flex 宽度;异步图表须在真实 DOM 挂载后观察尺寸变化,避免侧边/顶部导航切换后撑破卡片。
|
|
183
|
+
- 主题色、浅色/深色、菜单子级展开方式等需要“换设备仍生效”的选择必须保存到当前 DiyToken 用户的 `sys_user` 白名单字段;`localStorage` 只作为未安装新字段租户和匿名启动阶段的兼容回退,不能作为跨设备事实源。
|
|
184
|
+
- 已安装用户偏好字段时优先级固定为“当前用户显式值 → 租户 `sys_config` → 平台安全默认”;个人菜单值 `System` 表示继承租户配置。不得让上一位用户的浏览器本地主题覆盖下一位已登录用户。
|
|
185
|
+
- 主题面板的主题色、亮暗模式、边角、导航、菜单展开、密度、三个装饰开关及登录风格均有同名系统全局默认,不新建重复字段。`framework-appearance.js` 统一应用运行状态;渲染继承值不能写成个人选择。`UiDensityScale` 安全范围为 90~110、步长 5,覆盖表单标签/普通控件、系统设置表单、侧栏、表格、Tab 与 Teleport 弹层;富文本、代码、地图和子表保持内容高度,触屏最小目标仍为 44px。
|
|
186
|
+
- 密度覆盖不能只改字号和单元格 padding:父菜单底圈、图标、菜单行间距与普通表格 `.cell` 的历史38/40px行高都必须采用同一密度 token。多行内容保持自然高度,不能设置固定行高裁切。直角样式需按真实选择器优先级覆盖 `.el-message-box.mci-unified-message-box` 等双class的 important 壳,并验退出确认 Teleport 首帧。
|
|
187
|
+
- 【恢复默认】沿原保存队列把 `ThemeMode/ThemeColor` 清空、`CornerStyle/NavigationLayout/MenuChildExpandMode/LoginStyle` 写 `System`、`UiDensityScale/DisableGradient/DisableShadow/DisableButtonIcon` 写 `null`,只作用当前用户。同时清旧设备回退与本身份缓存;不能修改 `sys_config` 或把平台默认值写成个人覆盖。开关 `0` 与 `null` 语义不同:`0` 可覆盖全局 `1`,`null` 继承全局。
|
|
188
|
+
- `DisableGradient/DisableShadow/DisableButtonIcon` 同时支持个人与租户默认,根标识分别为 `data-mci-disable-gradient/shadow/button-icon`。去装饰仍保留输入边界、键盘焦点、加载指示与纯图标操作。登录样式 `LoginStyle=Original/Minimal/Split/Console` 复用一套业务 mixin 与表单,不复制验证码、SSO、强认证、协议及回跳逻辑;匿名读取当前租户默认或本匿名上下文明确预览,不能读取上一账号的个人值。
|
|
189
|
+
- `sys_config.HideFrameworkFunctions` 只控制顶栏入口,固定 Key 为 `Chat/BackgroundTasks/Search/Language/Theme/AI/Bluetooth/SystemStyle/FullScreen`,账号头像姓名始终保留。它与控制移动端等范围的原 AI 禁用开关独立,也不能代替功能权限。所有入口提供 `data-framework-function` 便于验收,未知 Key 忽略。
|
|
190
|
+
- 新增全局开关 CSS 必须检查编译后选择器;scoped 中 `:global(html[attr]) .child` 会丢失后代范围,禁止用它隐藏装饰。使用独立非 scoped 且有完整登录/框架作用域的样式,或将完整选择器放进 `:global(...)`;必须断言开启全部开关时根 html、body、框架与弹层仍可见。
|
|
191
|
+
- 自助保存优先使用官方 `Managed` 接口引擎,由 `V8.CurrentUser.Id` 与 `V8.OsClient` 推导用户和租户,并在服务端构造固定白名单更新对象;接口参数禁止决定目标 Id/OsClient,也禁止写入 Account、Phone、Tenant、Dept、Role、Level、State、Pwd、认证因子和登录审计字段。只有缺少可复用可信原子能力时才新增 C# DTO/端点。保存成功后调用 `V8.Method.RefreshLoginUser` 刷新登录缓存,并让微服务宿主重新同步 `CurrentUser`。
|
|
192
|
+
- 右上角即时切换可以乐观应用并短防抖保存;远端保存失败时保留当前设备效果并明确提示。个人中心和右上角必须调用同一个应用包交付的白名单接口引擎(当前为 `platform-user-update-preferences`),不能分别形成两套字段、枚举或优先级。
|
|
193
|
+
- 导航切入或退出 `TopSide` 会重建顶栏组件;卸载前必须发送尚未保存的偏好,在途请求与后续选择共用按 store、API 地址、租户、账号和登录会话隔离的运行时队列。新顶栏继承失败状态和重试数据,旧响应不能覆盖更新的选择或跨账号合并队列;标准续签保留 `MicroiSessionId` 时也保留最终待保存选择,计算属性显式依赖 Pinia.Token。JWT 解码仅用于本地队列归属,服务端仍通过标准 DiyToken 验证授权;不得将会话凭据写入偏好存储、日志或响应。使用真实 Vue computed 和组件生命周期回归 `theme-select-autosave-lifecycle.spec.mjs` 验证卸载、在途合并、失败重试、续签及账号/租户/会话切换。
|
|
194
|
+
- 主题回归同时执行 `framework-appearance.spec.mjs`、`ui-density-runtime.spec.mjs` 与 `theme-select-autosave-lifecycle.spec.mjs`;真实浏览器默认使用一个常规桌面 CSS 视口(优先用户实际视口,否则 1920×1080),验证系统设置与左菜单在 90/110 两档的尺寸变化、全局/个人继承与恢复、全部顶栏隐藏后账号仍在,以及装饰关闭后的亮暗和焦点可见性。只有用户明确要求或缺陷涉及超宽屏时才追加 4K,不把截图文件像素尺寸当作浏览器 CSS 视口。
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
190
198
|
<!-- /microi-progressive:chunk -->
|
|
191
|
-
<!-- microi-progressive:chunk id=microi-client-frontend-003 sha256=
|
|
192
|
-
## 4. 工作流与表单提交
|
|
193
|
-
|
|
194
|
-
工作流相关文件:
|
|
195
|
-
|
|
196
|
-
| 文件 | 说明 |
|
|
197
|
-
|------|------|
|
|
198
|
-
| `form-right-panel.vue` | 右侧 Tab 容器,展示日志/评论/工作流 |
|
|
199
|
-
| `workflow/wf-work-handler.vue` | StartWork/SendWork UI 与提交参数构建 |
|
|
200
|
-
| `mixins/diy-form-full-workflow.mixin.js` | 把工作流提交接到 `diy-form-full` 的保存链路 |
|
|
201
|
-
| `diy-components/diy-workflow-line-condition.vue` | 条件路线图形配置与 V8 marker 生成 |
|
|
202
|
-
|
|
203
|
-
关键规则:
|
|
204
|
-
|
|
205
|
-
- 首次发起流程时,前端可能已经生成 `Id`,但业务表还没有行;必须走 `Add` 或传 `_NoLineForAdd=true`。
|
|
206
|
-
- `StartWorkWithForm` 用于“保存表单 + 发起流程”原子化提交。
|
|
207
|
-
- 工作流路线标题是拓扑关系 `{起点节点} 到 {终点节点}`,条件名称不能覆盖 `wf_line.LineName`。
|
|
208
|
-
- 条件 V8 推荐设置 `V8.NextNodeId`,兼容 `V8.LineValue`。
|
|
209
|
-
|
|
210
|
-
---
|
|
211
|
-
|
|
199
|
+
<!-- microi-progressive:chunk id=microi-client-frontend-003 sha256=301f766dc1ab1c6b021aa861a76b44844905d432393ab407472f58f00d6283cd -->
|
|
200
|
+
## 4. 工作流与表单提交
|
|
201
|
+
|
|
202
|
+
工作流相关文件:
|
|
203
|
+
|
|
204
|
+
| 文件 | 说明 |
|
|
205
|
+
|------|------|
|
|
206
|
+
| `form-right-panel.vue` | 右侧 Tab 容器,展示日志/评论/工作流 |
|
|
207
|
+
| `workflow/wf-work-handler.vue` | StartWork/SendWork UI 与提交参数构建 |
|
|
208
|
+
| `mixins/diy-form-full-workflow.mixin.js` | 把工作流提交接到 `diy-form-full` 的保存链路 |
|
|
209
|
+
| `diy-components/diy-workflow-line-condition.vue` | 条件路线图形配置与 V8 marker 生成 |
|
|
210
|
+
|
|
211
|
+
关键规则:
|
|
212
|
+
|
|
213
|
+
- 首次发起流程时,前端可能已经生成 `Id`,但业务表还没有行;必须走 `Add` 或传 `_NoLineForAdd=true`。
|
|
214
|
+
- `StartWorkWithForm` 用于“保存表单 + 发起流程”原子化提交。
|
|
215
|
+
- 工作流路线标题是拓扑关系 `{起点节点} 到 {终点节点}`,条件名称不能覆盖 `wf_line.LineName`。
|
|
216
|
+
- 条件 V8 推荐设置 `V8.NextNodeId`,兼容 `V8.LineValue`。
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
212
220
|
<!-- /microi-progressive:chunk -->
|
|
213
|
-
<!-- microi-progressive:chunk id=microi-client-frontend-004 sha256=
|
|
214
|
-
## 7. 验证建议
|
|
215
|
-
|
|
216
|
-
### 本地 ApiBase 与 OsClient 解析(强制)
|
|
217
|
-
|
|
218
|
-
WebOS 直链容器不能只等旧版 `CallbackSysMenuModel` / `CallbackCurrentDiyTableModel`:标准页面可能不再发送这些事件,标题与图标必须回退当前权限路由的 `meta.title/icon`。路由切换时清空旧模型,回调绑定来源路由并拒绝迟到事件;嵌入窗通知、桌面和手机标题共用同一响应式结果。修改时运行 `tests/webos-page-title.spec.mjs`,并验收直链、刷新、前进后退、桌面窗口和经典界面。
|
|
219
|
-
|
|
220
|
-
- 域名发现先于租户确定,固定 `platform-os-client-by-domain` 请求不能自动注入默认或缓存租户,也不能携带旧 Token;显式调用租户仍保持。没有 URL/index.html 租户时,每次冷启动重新发现域名,成功后更新缓存,失败立即停止,不写入 `iTdos` 继续请求配置。配置业务失败不是连接故障,健康检查成功不能触发循环重载;只有确认连接故障后的恢复才重载失败启动页。回归覆盖无缓存、错误缓存、显式租户及失败不重载,使用 `domain-tenant-bootstrap.spec.mjs`。
|
|
221
|
-
- 登录回跳使用 Vue Router 解析完整深链接后合并 query/hash;对象式 `push({path, query})` 的 query 会覆盖 path 中原有参数,不能直接传空对象导致记录 Id 丢失。使用 `login-deep-link-query.spec.mjs` 验证编号、编码参数、重复参数和锚点。
|
|
222
|
-
|
|
223
|
-
- `app.use(router)` 会立即触发首个路由守卫。守卫中的 SSO、认证、菜单请求必须等待 `initApp()` 完成真实租户和系统配置初始化;初始化失败时取消导航并保留启动错误界面。释放初始化等待必须早于 `router.isReady()`,避免彼此等待;禁止将缓存尚未建立时的 `GetOsClient()` 默认值 `iTdos` 发给客户服务器。
|
|
224
|
-
|
|
225
|
-
- 身份和菜单只读初始化的短暂失败最多读取三次,间隔 300/1000ms;认证失效立即回登录页并保留原深链接,HTTP 403 和已耗尽的菜单依赖重试不得继续重试。重试期间退出登录应停止后续读取,不得用清空 Token、伪造角色或放行保护路由掩盖错误。持续失败用 `next(error)` 保留身份/菜单阶段和原始原因,禁止用 `next(false)` 把它替换为 `Navigation aborted`;启动界面不能据此断言后端断网。当前用户请求的传输失败必须 reject,不能留下永久 pending 的 Promise。修改这条链路时运行 `route-bootstrap-recovery.spec.mjs`,并用真实路由验证健康登录、短暂失败恢复、持续失败提示和过期会话跳转。
|
|
226
|
-
|
|
227
|
-
- `ApiServiceUnavailable` 确认连接故障后,每轮探测结束 5 秒后继续请求固定匿名健康接口;单次请求超时 5 秒,自动与手动检测共用在途请求。后端返回有效健康正文后停止轮询,启动失败的页面只重载一次原 URL,已经就绪的业务页面原地撤掉异常层并保留输入,禁止重放失败的业务写入。旧版健康接口也必须返回有效的 Healthy 正文,不能把反向代理 HTML/404 当作恢复。安全拦截继续按后端解除时间检查,不用连接故障轮询缩短封禁。定向回归使用 `api-service-recovery.spec.mjs` 与 `api-service-status.spec.mjs`,浏览器必须验证断连到自动恢复全过程。
|
|
228
|
-
|
|
229
|
-
- `src/config.json.ApiBaseDev` 是本地默认 API;URL 中 `#` 之前的 `ApiBase`、`OsClient` 必须同时
|
|
230
|
-
高于 `index.html`、config、Pinia 与 localStorage。解析统一走
|
|
231
|
-
`src/utils/runtime-endpoint-query.js`,禁止在新入口另写正则形成不同优先级。
|
|
232
|
-
- URL 只允许有效的 HTTP(S) ApiBase 和安全 OsClient。页面初始化后通过不含 Token 的
|
|
233
|
-
`window.__MICROI_RUNTIME_ENDPOINT__` 暴露实际值,便于 AI/自动化确认没有误连配置文件中的服务器。
|
|
234
|
-
- 页面已解析的租户必须进入真实 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`。
|
|
235
|
-
- 首次身份读取的业务/传输失败交给路由守卫处理,`getInfo` 不调用带全局通知副作用的 `DiyCommon.Result`,同时抑制请求层通知和抢先登录跳转;`App.PageInit` 等待首次导航成功后再启动续签/用户刷新,导航失败时结束。既要验证干净会话,也要验证旧登录缓存和失败后重复刷新,不能以隔离浏览器成功代替用户当前会话验收。
|
|
236
|
-
- 同源浏览器窗口仍共享 Token、CurrentUser 等持久化状态。不同 `ApiBase + OsClient` 并行测试必须
|
|
237
|
-
使用独立 browser context/profile;URL 最高优先级不等于登录态隔离。
|
|
238
|
-
- 修改该链路时运行 `node --test tests/runtime-endpoint-query.spec.mjs`,再使用两个独立
|
|
239
|
-
`browser.newContext()` 验证两组运行目标互不串号。
|
|
240
|
-
|
|
241
|
-
### 菜单微服务缓存与恢复(强制)
|
|
242
|
-
|
|
243
|
-
- 首次挂载分开检查资源下载与渲染:下载最多 60 秒,`beforemount` 资源齐备后才开始原有 12 秒渲染期限;不得在资源正常下载时提前销毁沙箱。成功仍要求真实可见 DOM,保留一次自愈与旧实例保护。回归覆盖超过 12 秒的真实下载、下载停滞、渲染停滞和陈旧实例事件。
|
|
244
|
-
|
|
245
|
-
- 动态菜单宿主的 Vue 路由保持 `keepAlive:false`,由 `<micro-app keep-alive>` 独占运行时状态;契约固定为 `runtime-keep-alive`,禁止 Vue `KeepAlive` 和 micro-app 双层缓存。
|
|
246
|
-
- 每个顶部 Tab 按完整路由生成稳定实例身份,最多保留 5 个隐藏实例并按 LRU 淘汰。关闭 Tab、退出登录、Token/角色变化以及版本或入口变化时必须精确销毁对应运行时。
|
|
247
|
-
- 恢复时强制同步宿主上下文并检查真实可见 DOM;子应用监听 `appstate-change`,在 `afterhidden` 幂等暂停轮询、WebSocket 和观察器,在 `aftershow` 幂等恢复并重新测量布局,同时保留用户输入、筛选、滚动和内部路由。
|
|
248
|
-
- 修改宿主、TagsView 或权限路由时,必须同时读取 [Vue3 前端微服务宿主规则](references/progressive-03-vue3-前端微服务宿主规则.md) 并运行微服务缓存契约测试。
|
|
249
|
-
|
|
250
|
-
- 修改 Vue/JS 后先跑 VS Code Problems 或 `get_errors`。
|
|
251
|
-
- 宿主按钮重置只作用于 `button:not(:focus-visible)`,不能用全局 `outline:none !important` 覆盖组件或微应用的键盘焦点。微应用保留自己的边框形状,焦点色使用已适配明暗表面的 `--mci-text-link`(缺省回退正文语义色),不能直接用浅品牌色。真实 Tab/Shift+Tab 回归须核对 `:focus-visible`、实际 `outline-style`、宽度、颜色与至少 3:1 对比度;`outline-style:none` 即使宽度非零也不可见。使用阴影焦点时另验实际 `box-shadow`,不能只看焦点状态。平台样式组件回归归 Full,应用自身按钮继续在真实业务页面验收。
|
|
252
|
-
- 影响核心前端时跑 `Microi.Client` 的 `npm run build`。
|
|
253
|
-
- 如果改了工作流、表单保存、按钮 V8,建议用实际 `sys_menu` 配置测试:
|
|
254
|
-
- `FormBtns` 是否出现在表单右上角/FAB。
|
|
255
|
-
|
|
256
|
-
---
|
|
257
|
-
|
|
221
|
+
<!-- microi-progressive:chunk id=microi-client-frontend-004 sha256=c122ac25dd00abc7af5751c6db50fe5f9fed29a9979f454ba9a23209d25dbaca -->
|
|
222
|
+
## 7. 验证建议
|
|
223
|
+
|
|
224
|
+
### 本地 ApiBase 与 OsClient 解析(强制)
|
|
225
|
+
|
|
226
|
+
WebOS 直链容器不能只等旧版 `CallbackSysMenuModel` / `CallbackCurrentDiyTableModel`:标准页面可能不再发送这些事件,标题与图标必须回退当前权限路由的 `meta.title/icon`。路由切换时清空旧模型,回调绑定来源路由并拒绝迟到事件;嵌入窗通知、桌面和手机标题共用同一响应式结果。修改时运行 `tests/webos-page-title.spec.mjs`,并验收直链、刷新、前进后退、桌面窗口和经典界面。
|
|
227
|
+
|
|
228
|
+
- 域名发现先于租户确定,固定 `platform-os-client-by-domain` 请求不能自动注入默认或缓存租户,也不能携带旧 Token;显式调用租户仍保持。没有 URL/index.html 租户时,每次冷启动重新发现域名,成功后更新缓存,失败立即停止,不写入 `iTdos` 继续请求配置。配置业务失败不是连接故障,健康检查成功不能触发循环重载;只有确认连接故障后的恢复才重载失败启动页。回归覆盖无缓存、错误缓存、显式租户及失败不重载,使用 `domain-tenant-bootstrap.spec.mjs`。
|
|
229
|
+
- 登录回跳使用 Vue Router 解析完整深链接后合并 query/hash;对象式 `push({path, query})` 的 query 会覆盖 path 中原有参数,不能直接传空对象导致记录 Id 丢失。使用 `login-deep-link-query.spec.mjs` 验证编号、编码参数、重复参数和锚点。
|
|
230
|
+
|
|
231
|
+
- `app.use(router)` 会立即触发首个路由守卫。守卫中的 SSO、认证、菜单请求必须等待 `initApp()` 完成真实租户和系统配置初始化;初始化失败时取消导航并保留启动错误界面。释放初始化等待必须早于 `router.isReady()`,避免彼此等待;禁止将缓存尚未建立时的 `GetOsClient()` 默认值 `iTdos` 发给客户服务器。
|
|
232
|
+
|
|
233
|
+
- 身份和菜单只读初始化的短暂失败最多读取三次,间隔 300/1000ms;认证失效立即回登录页并保留原深链接,HTTP 403 和已耗尽的菜单依赖重试不得继续重试。重试期间退出登录应停止后续读取,不得用清空 Token、伪造角色或放行保护路由掩盖错误。持续失败用 `next(error)` 保留身份/菜单阶段和原始原因,禁止用 `next(false)` 把它替换为 `Navigation aborted`;启动界面不能据此断言后端断网。当前用户请求的传输失败必须 reject,不能留下永久 pending 的 Promise。修改这条链路时运行 `route-bootstrap-recovery.spec.mjs`,并用真实路由验证健康登录、短暂失败恢复、持续失败提示和过期会话跳转。
|
|
234
|
+
|
|
235
|
+
- `ApiServiceUnavailable` 确认连接故障后,每轮探测结束 5 秒后继续请求固定匿名健康接口;单次请求超时 5 秒,自动与手动检测共用在途请求。后端返回有效健康正文后停止轮询,启动失败的页面只重载一次原 URL,已经就绪的业务页面原地撤掉异常层并保留输入,禁止重放失败的业务写入。旧版健康接口也必须返回有效的 Healthy 正文,不能把反向代理 HTML/404 当作恢复。安全拦截继续按后端解除时间检查,不用连接故障轮询缩短封禁。定向回归使用 `api-service-recovery.spec.mjs` 与 `api-service-status.spec.mjs`,浏览器必须验证断连到自动恢复全过程。
|
|
236
|
+
|
|
237
|
+
- `src/config.json.ApiBaseDev` 是本地默认 API;URL 中 `#` 之前的 `ApiBase`、`OsClient` 必须同时
|
|
238
|
+
高于 `index.html`、config、Pinia 与 localStorage。解析统一走
|
|
239
|
+
`src/utils/runtime-endpoint-query.js`,禁止在新入口另写正则形成不同优先级。
|
|
240
|
+
- URL 只允许有效的 HTTP(S) ApiBase 和安全 OsClient。页面初始化后通过不含 Token 的
|
|
241
|
+
`window.__MICROI_RUNTIME_ENDPOINT__` 暴露实际值,便于 AI/自动化确认没有误连配置文件中的服务器。
|
|
242
|
+
- 页面已解析的租户必须进入真实 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`。
|
|
243
|
+
- 首次身份读取的业务/传输失败交给路由守卫处理,`getInfo` 不调用带全局通知副作用的 `DiyCommon.Result`,同时抑制请求层通知和抢先登录跳转;`App.PageInit` 等待首次导航成功后再启动续签/用户刷新,导航失败时结束。既要验证干净会话,也要验证旧登录缓存和失败后重复刷新,不能以隔离浏览器成功代替用户当前会话验收。
|
|
244
|
+
- 同源浏览器窗口仍共享 Token、CurrentUser 等持久化状态。不同 `ApiBase + OsClient` 并行测试必须
|
|
245
|
+
使用独立 browser context/profile;URL 最高优先级不等于登录态隔离。
|
|
246
|
+
- 修改该链路时运行 `node --test tests/runtime-endpoint-query.spec.mjs`,再使用两个独立
|
|
247
|
+
`browser.newContext()` 验证两组运行目标互不串号。
|
|
248
|
+
|
|
249
|
+
### 菜单微服务缓存与恢复(强制)
|
|
250
|
+
|
|
251
|
+
- 首次挂载分开检查资源下载与渲染:下载最多 60 秒,`beforemount` 资源齐备后才开始原有 12 秒渲染期限;不得在资源正常下载时提前销毁沙箱。成功仍要求真实可见 DOM,保留一次自愈与旧实例保护。回归覆盖超过 12 秒的真实下载、下载停滞、渲染停滞和陈旧实例事件。
|
|
252
|
+
|
|
253
|
+
- 动态菜单宿主的 Vue 路由保持 `keepAlive:false`,由 `<micro-app keep-alive>` 独占运行时状态;契约固定为 `runtime-keep-alive`,禁止 Vue `KeepAlive` 和 micro-app 双层缓存。
|
|
254
|
+
- 每个顶部 Tab 按完整路由生成稳定实例身份,最多保留 5 个隐藏实例并按 LRU 淘汰。关闭 Tab、退出登录、Token/角色变化以及版本或入口变化时必须精确销毁对应运行时。
|
|
255
|
+
- 恢复时强制同步宿主上下文并检查真实可见 DOM;子应用监听 `appstate-change`,在 `afterhidden` 幂等暂停轮询、WebSocket 和观察器,在 `aftershow` 幂等恢复并重新测量布局,同时保留用户输入、筛选、滚动和内部路由。
|
|
256
|
+
- 修改宿主、TagsView 或权限路由时,必须同时读取 [Vue3 前端微服务宿主规则](references/progressive-03-vue3-前端微服务宿主规则.md) 并运行微服务缓存契约测试。
|
|
257
|
+
|
|
258
|
+
- 修改 Vue/JS 后先跑 VS Code Problems 或 `get_errors`。
|
|
259
|
+
- 宿主按钮重置只作用于 `button:not(:focus-visible)`,不能用全局 `outline:none !important` 覆盖组件或微应用的键盘焦点。微应用保留自己的边框形状,焦点色使用已适配明暗表面的 `--mci-text-link`(缺省回退正文语义色),不能直接用浅品牌色。真实 Tab/Shift+Tab 回归须核对 `:focus-visible`、实际 `outline-style`、宽度、颜色与至少 3:1 对比度;`outline-style:none` 即使宽度非零也不可见。使用阴影焦点时另验实际 `box-shadow`,不能只看焦点状态。平台样式组件回归归 Full,应用自身按钮继续在真实业务页面验收。
|
|
260
|
+
- 影响核心前端时跑 `Microi.Client` 的 `npm run build`。
|
|
261
|
+
- 如果改了工作流、表单保存、按钮 V8,建议用实际 `sys_menu` 配置测试:
|
|
262
|
+
- `FormBtns` 是否出现在表单右上角/FAB。
|
|
263
|
+
|
|
264
|
+
---
|
|
265
|
+
|
|
258
266
|
<!-- /microi-progressive:chunk -->
|
|
259
267
|
## 详细参考路由(渐进披露)
|
|
260
268
|
|