@microi.net/cli 5.9.0 → 5.9.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 (19) 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 +3 -3
  7. package/cordis.patch.yml +1 -1
  8. package/package.json +1 -1
  9. package/scripts/microi-skills.meta.json +204 -204
  10. package/skills/.microi-skills-version.json +2 -2
  11. package/skills/.progressive-disclosure-manifest.json +73 -73
  12. package/skills/microi-mobile-app-quality/SKILL.md +20 -8
  13. 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 +22 -11
  14. 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 +4 -4
  15. package/skills/microi-uniapp-frontend/SKILL.md +18 -12
  16. 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 +103 -67
  17. 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 +10 -10
  18. package/skills/workspace-conventions/SKILL.md +4 -2
  19. 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 +9 -1
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 按需读取;本文件由 SKILL.md 的原章节无损拆分。
4
4
 
5
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-008 sha256=765335189d85b558ad29ba73c04d1cf078101ee94819f969195b50440a82106f -->
5
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-008 sha256=8cc961b2ba44763893f3cc09fbfca36668061b6bd75fc8f066904a04622948ff -->
6
6
  ## 4. 重要按钮必须带图标
7
7
 
8
8
  醒目的主操作必须使用打磨过的图标加文字按钮。
@@ -23,7 +23,7 @@
23
23
  - 确认主操作有图标、合适的加载文案和按下反馈。
24
24
 
25
25
  <!-- /microi-progressive:chunk -->
26
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-009 sha256=e3c66bd92ca059235a7a3b0ece2fdfa598a41eaa149d0ee3a0d24d0d822a9f58 -->
26
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-009 sha256=47248f77c0a41a7fd64f6a255d8c9af356b6768e5167c73a48d60b86f1ab9899 -->
27
27
  ## 4.1 模块列表优先使用声明式业务卡片
28
28
 
29
29
  Microi.Client 的标准模块移动端不应把 PC 表格字段机械纵向堆叠。优先在
@@ -53,7 +53,7 @@ Microi.Client 的标准模块移动端不应把 PC 表格字段机械纵向堆
53
53
  - 批量选择后出现底部操作条;取消选择、执行按钮、更多菜单均可单手点击。
54
54
 
55
55
  <!-- /microi-progressive:chunk -->
56
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-010 sha256=2ddd560cf3620f8fb7f3cf64d62566206430ee14e6ac380a3023c5b9047b4f46 -->
56
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-010 sha256=979733873bd74cd95b0c84988a8d3709f673a813dc212076e4f02e8b376fb492 -->
57
57
  ## 5. 首屏文字和浮层不得重叠
58
58
 
59
59
  移动端首屏常组合大首屏区域和悬浮快捷面板。这个布局必须视觉检查,因为过大的中文标题和激进的负边距容易造成难看的换行或遮挡主按钮。
@@ -74,7 +74,7 @@ Microi.Client 的标准模块移动端不应把 PC 表格字段机械纵向堆
74
74
  - 检查首屏标题、主/次按钮和后续悬浮面板是否裁切或重叠。
75
75
 
76
76
  <!-- /microi-progressive:chunk -->
77
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-011 sha256=b599e047e6b7a3688e4264a4d4b334e220e9798cbc13326e85a06f52bf20ce12 -->
77
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-011 sha256=47a21d62bc04740ed19eea3f7c2c816e4c73b9054de63beb16df12468c6a4363 -->
78
78
  ## 5.1 未登录/授权提示必须在可用内容区居中
79
79
 
80
80
  未登录、未授权、无权限等提示模块不能贴在页面顶部。页面上方有 hero/header,下方有 tabBar 或固定底栏时,提示卡片和“立即登录/去授权”按钮必须在剩余可用内容区上下左右居中。
@@ -94,7 +94,7 @@ Microi.Client 的标准模块移动端不应把 PC 表格字段机械纵向堆
94
94
  - 375px、430px、iOS 刘海屏/灵动岛和 Android 状态栏场景均不得出现贴顶或按钮文字偏移。
95
95
 
96
96
  <!-- /microi-progressive:chunk -->
97
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-012 sha256=a363aaead9b632f3533e2f046f39cf7b579a91b92ef4e33d42f848d5a7538515 -->
97
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-012 sha256=fb7a9bfb6e8be41d472df82edf6238b9d09e6aeabd54eb71bce2a255a50c6326 -->
98
98
  ## 5.2 自定义导航页面必须通过安全区与微信胶囊门禁
99
99
 
100
100
  `navigationStyle: custom` 代表应用接管了系统导航区域,页面壳必须同时负责状态栏、刘海/灵动岛、微信右上角胶囊和底部手势区,不能把这一责任留给业务页面自行估算。
@@ -104,7 +104,7 @@ Microi.Client 的标准模块移动端不应把 PC 表格字段机械纵向堆
104
104
  - CSS `env(safe-area-inset-*)` 只能作为 H5 兜底,不能作为微信小程序唯一实现。真实值应注入 `--mci-safe-top`、`--mci-safe-bottom` 等共享变量。
105
105
  - 微信小程序必须读取 `getMenuButtonBoundingClientRect()` 并为顶部栏预留胶囊右侧宽度;标题、登录、分享、状态按钮与返回按钮都不能和胶囊相交。
106
106
  - 全屏弹层或工作台的多按钮头部必须纳入同一门禁。若按钮组不能完整放在胶囊左侧,标题和按钮组整体布局到胶囊底边以下;不得让关闭按钮被原生“更多/关闭”覆盖。
107
- - 底部导航、fixed 提交栏、底部弹层和正文滚动区必须消费同一个底部安全变量,正文还要预留完整固定栏高度。
107
+ - 底部导航、fixed 提交栏、底部弹层和正文滚动区使用同一个底部安全变量,并明确空间所有者。流内导航已经占高度时正文不再加整条栏占位;覆盖式栏才由共享布局预留一次实测总高度,安全区包含在该高度内,不能再叠一份。
108
108
  - 审计 `pages.json` 的全部页面:每一个自定义导航路由都必须使用统一安全页面壳。首页通过不代表详情页、表单页、管理页已经通过。
109
109
 
110
110
  自动化验收:
@@ -112,8 +112,19 @@ Microi.Client 的标准模块移动端不应把 PC 表格字段机械纵向堆
112
112
  - 断言首个可交互元素位于状态栏下方,逐个读取顶部按钮与胶囊的矩形并确认不相交,底部导航/按钮位于手势条上方,最后一条滚动内容可完整显示。
113
113
  - 发现任意页面被遮挡时,必须修复共享页面壳并重跑全路由;禁止只给当前截图页面增加固定 padding。
114
114
 
115
+ ### 5.2.1 底部空白、滚动和键盘必须测量
116
+
117
+ - 安全区来源单独回读:H5 使用 CSS 环境安全区,禁止将 `screenHeight - windowHeight` 当作底部 inset。App/小程序按各端权威接口取值,`0` 必须原样保留;不得以 `inset || guessedFallback` 触发估算。用非最大化桌面窗口、浏览器缩放和地址栏收展重测,不能仅用 `screen === viewport` 的固定截图通过门禁。
118
+
119
+ - 矩形断言以实际页面内屏为边界:桌面使用手机壳内屏,移动端使用当前可见视口;导航底边与该边界的差应在事先约定的舍入容差内(示例 `2 CSS px`)。壳外阴影、边框和桌面留边不算导航下方空白。
120
+ - 同时量导航外框和内部菜单触摸区。外框贴底但高度几百像素、菜单挤在其顶部仍算失败;内部菜单下方剩余高度只能等于真实安全区加设计底间距,不能把多余区域都解释成“安全区”。
121
+ - 至少选三个主 Tab,在初始、滚动中、滚动到底、切回短内容/空态后重复测量;导航位置应稳定,最后一项不能被导航遮挡。普通单列页只允许一个主体滚动 owner,桌面 body 不应跟随正文滚动。
122
+ - 覆盖桌面正常与矮屏、375px/430px 手机、预览断点两侧、手机横屏和旋转后恢复。`rpx` 换算要在 768px、960px 和 4K 外窗下检查实际导航高度,不能只看源码写了 `430px` 壳宽。
123
+ - 输入框获得焦点、软键盘打开、关闭和返回后重新验证可见区域与导航。H5 结合 `visualViewport` 的尺寸/偏移判断真实可见范围,原生端遵守其键盘模式;缩小浏览器视口只证明 resize 响应,不能证明 iOS/Android 真键盘行为。
124
+ - 取 `fullPage:false` 的真实视口截图并核对导航下方区域。长页 `fullPage` 图中导航可能位于图中部,不能据此判定贴底,也不能仅凭长图或图标存在宣称布局通过。
125
+
115
126
  <!-- /microi-progressive:chunk -->
116
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-013 sha256=207765d0398738f24566763a2481469f4fc63e8a0b5f00abd292fe8a1cdd225a -->
127
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-013 sha256=f4e1f01f3dde22120ecba9131b5c738118c0e4aa8131ea83978f3e1d6b4db289 -->
117
128
  ## 5.3 全屏工具页必须遵守返回状态栈
118
129
 
119
130
  - AI 助手、扫码工作台、全屏预览等独占视口功能需要手机侧滑返回时,优先使用独立路由承载;普通 `position:fixed` 蒙层不能冒充页面历史。
@@ -122,7 +133,7 @@ Microi.Client 的标准模块移动端不应把 PC 表格字段机械纵向堆
122
133
  - 自动化至少覆盖关闭按钮、Android 返回键/`onBackPress`、微信侧滑返回三条路径,并验证返回后原页面和滚动状态仍然可用。
123
134
 
124
135
  <!-- /microi-progressive:chunk -->
125
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-014 sha256=1451e6ffbb0c0d29d8362e400540e3fa4f9f38a2402a9faf93de4cce7b1c9b4c -->
136
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-014 sha256=eaf8ac0e9edadf382a08951d6c43b9ab561dd2a8ee02fc80048fc843e4656033 -->
126
137
  ## 5.4 微信浮动入口必须通过真实事件桥门禁
127
138
 
128
139
  - UniApp 自定义组件中的浮动按钮、拖拽助手和悬浮客服不得只做 H5 点击测试。必须在微信运行时找到真实组件节点,派发 `touchstart/touchend`,并断言页面栈、弹层状态或业务动作确实变化。
@@ -131,7 +142,7 @@ Microi.Client 的标准模块移动端不应把 PC 表格字段机械纵向堆
131
142
  - 自动化需增加对照按钮:同页普通按钮可点击、浮动入口也可点击,才能确认不是自动化连接或页面整体失效。
132
143
 
133
144
  <!-- /microi-progressive:chunk -->
134
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-015 sha256=8377f92a7456bd68e83867e893f1c9e8eec9edf0bba2a3f434c5bce75a9e2d00 -->
145
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-015 sha256=3a65e2da022d493b7d950450a10186d33652ec4225c359d9b3800ef431458525 -->
135
146
  ## 6. 后台菜单必须规划为至少两级
136
147
 
137
148
  真实业务系统的后台菜单不能简单堆成一批一级菜单。
@@ -159,7 +170,7 @@ Microi.Client 的标准模块移动端不应把 PC 表格字段机械纵向堆
159
170
  - 最终回复必须说明通过 MCP 写入的真实菜单树,以及执行过的权限刷新。
160
171
 
161
172
  <!-- /microi-progressive:chunk -->
162
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-016 sha256=0c1632d28f986156f8d70b2710dc0219de4643b4b9c61771ac544a18f4c355ac -->
173
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-016 sha256=808d3a4d3e7736566e1dd23c287a9316ea851c3ca212ffe283f49e565a7e0a3d -->
163
174
  ## 7. 移动端页面需要动效,但动效必须有用
164
175
 
165
176
  移动端产品不应像静态后台表单。
@@ -181,7 +192,7 @@ Microi.Client 的标准模块移动端不应把 PC 表格字段机械纵向堆
181
192
  - 没有动画导致横向溢出、文字裁切或固定栏抖动。
182
193
 
183
194
  <!-- /microi-progressive:chunk -->
184
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-017 sha256=2dcca5305da25f543181ae23550547cb3e3761aebae2843c5fc60e7848153176 -->
195
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-017 sha256=15d415351b8e3a7700d56cab2b39079494b06265b7d648636d1e511db1892161 -->
185
196
  ## 8. 登录页必须是直接登录界面
186
197
 
187
198
  登录页不能强迫用户先在两个身份标签之间切换才能登录。
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 按需读取;本文件由 SKILL.md 的原章节无损拆分。
4
4
 
5
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-018 sha256=b6e3138b7f398fad5b03253d07c1eb30e26da5c3df8ff1975117e5a3a282fd58 -->
5
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-018 sha256=28b7c339cbf546a91f4f35fce2bc146f052283fad2b6c54d7a8971acde21740a -->
6
6
  ## 9. 主题切换必须真实且全局生效
7
7
 
8
8
  当客户要求增加另一种视觉风格时,除非用户明确要求删除,否则要把当前已认可设计保留为一个命名主题,而不是直接覆盖。
@@ -39,7 +39,7 @@
39
39
  - 报告详情页必须逐主题截图,检查 `INSPECTION REPORT`、状态胶囊、封面标题、摘要卡、报告正文和富文本在当前主题下都有足够对比度。
40
40
 
41
41
  <!-- /microi-progressive:chunk -->
42
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-019 sha256=f2ca99aebb70273d991f5142e88bd1e02ff42782df5a8e7e180de297fba0faac -->
42
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-019 sha256=406cf4edff553e80567a6462a68b872d98275358b89ff196df0873f78a2c30a9 -->
43
43
  ## 10. 报告/列表详情必须保留用户身份
44
44
 
45
45
  从列表进入详情时必须保留调用者身份模型。即使打开的是同一个视觉报告详情页,员工、客户和公开/分享路线也可能需要不同接口。
@@ -60,7 +60,7 @@
60
60
  - 确认点击可见卡片后不会发生意外登录跳转。
61
61
 
62
62
  <!-- /microi-progressive:chunk -->
63
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-020 sha256=95487284aa5f9b1b3a0fb557845b3400af0355e4b2ebf6abebbef461e8ec8485 -->
63
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-020 sha256=c11ddf69390b21893b0bbb7de62592b8af6e9ecee5eb046bbeff99f3782e7493 -->
64
64
  ## 11. 角色与权限必须基于 sys_user.RoleIds 建模
65
65
 
66
66
  移动端和后台不能只区分“已登录/未登录”。企业应用通常至少有内部员工、售后师傅、客服、客户账号等角色,必须在建模阶段明确角色、菜单权限和数据权限。
@@ -93,7 +93,7 @@
93
93
  - 用未绑定的小程序手机号账号登录,截图确认“我的”页出现申请绑定身份入口;提交申请后后台能看到待审核记录;通过审核前数据权限不提前开放,通过审核后对应客户数据或内部工作台能力才出现。
94
94
 
95
95
  <!-- /microi-progressive:chunk -->
96
- <!-- microi-progressive:chunk id=microi-mobile-app-quality-021 sha256=13405c8ce231e9db8920cd8e1c4e0db26a32c1b5ac967113abee1391985ebfcd -->
96
+ <!-- microi-progressive:chunk id=microi-mobile-app-quality-021 sha256=e177d9cc3a9c28603129f42b598d2af72ecf305e934a982ed9801ca0d5a9e73c -->
97
97
  ## 审核后的会话与角色同步(强制)
98
98
 
99
99
  - 审核通过后的数据库角色、服务端 DiyToken 身份投影、SDK 用户缓存、页面 capability 和申请状态必须一致,禁止以“退出重登后正常”作为验收成功。
@@ -20,13 +20,13 @@ UniApp/H5/小程序必须通过项目统一 `microi.v8.js` 的 `V8.uploadFile` /
20
20
  登录页默认不得展示 ApiBase、OsClient 或调试配置;但用户明确要求、且安装包由 Microi 平台方作为多租户聚合客户端发布时,允许仅在 `APP-PLUS` 登录页提供通用连接器。协议必须使用固定 `https://` / `http://` 下拉框,地址框禁止重复输入协议,HTTPS 默认,HTTP 显示明文风险并二次确认;H5、小程序和客户专属包不得因此自动开放。候选地址先匿名读取 `GetSysConfig`,验证成功后再持久化。真正切换时必须清除旧 DiyToken、用户、SignalR、菜单/元数据/页面缓存,按 `ApiBase + OsClient` 隔离记住的账号及 RSA 密文,并用端点代次拒绝切换前的迟到响应。支持任意 HTTP 时,最终 IPA 必须显式包含 ATS 例外,Android 安装包必须显式包含 cleartext 例外;不需要任意 HTTP 的正式包应保持平台默认安全策略,iOS ATS 例外还必须在 App Store 审核中说明。
21
21
 
22
22
  <!-- microi-progressive:begin -->
23
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-000 sha256=ecb0fc85b5c3b15ac79c9049ca86de8c586d4ce3a6c975255464069d89f87ac4 -->
23
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-000 sha256=980d63128f930daa224319aece06ee9a407563f722831790a381b100b44bddeb -->
24
24
  ## 移动端质量门禁必须先读
25
25
 
26
26
  创建、重构或修复任何 Microi 移动端项目前,必须同时应用 `microi.skills/microi-mobile-app-quality/SKILL.md`。该 Skill 中的底部导航真实图标、重要按钮图标化、登录 API 校验、微信手机号快捷登录、后台二级菜单和页面动效要求,属于交付验收条件,不是可选优化。
27
27
 
28
28
  <!-- /microi-progressive:chunk -->
29
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-001 sha256=b195b92de6175b7f184257a0ba3b53b94b8a6aaee7ab42fbb05fe1f5338ba097 -->
29
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-001 sha256=51e5f609e93cf164acb9af45f83a8d713f28fba3d68b22d4331a86e5f5248fc5 -->
30
30
  ## 标准产品、视图协议与租户扩展
31
31
 
32
32
  动态表单的组织/树字段优先复用原生 `mci-native-field` 树形下拉与 `native-tree-options.mjs`,无需为小程序把后台 `Department` 改为普通 Select。读取 `Config.<Component>.Multiple/EmitPath`:组织单选叶值保存 Id,多选叶值保存 Id 数组,路径模式保存完整路径/路径数组,数组统一 JSON 序列化。支持祖先展开、搜索、清空、禁用、重试和只读回显;数据源旧模板不能代替当前授权组织树。业务字段联动放租户扩展,不执行任意前端 V8;验收覆盖保存格式、旧数据回显、失败/迟到响应及最近公司祖先联动。
@@ -50,16 +50,22 @@ Microi 标准小程序必须采用“平台内核 + 版本化元数据 + Profile
50
50
  仓库必须提供 AI 与人工协作约束文件、租户脚手架、Profile 构建/同步命令和架构检查。平台层改动至少同时构建标准 Profile 与默认交付 Profile;租户视觉改动还要执行多视口截图回归。这样其他同事使用 Codex、Claude、Copilot、Cursor 等工具继续开发时,会先读取相同规则,而不是依赖某次对话记忆。
51
51
 
52
52
  <!-- /microi-progressive:chunk -->
53
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-002 sha256=76ebf3985d21fbbc5d86093b95bdf348e526e3670da9bb6827b5e1a7184e617b -->
53
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-002 sha256=b82feb8b7144966aa1223a2087fbf2e3cb59943b3af51d92395646029a1f5343 -->
54
54
  ## H5 预览壳与底部导航强制规则
55
55
 
56
+ - H5 的底部安全区采用 CSS `env(safe-area-inset-bottom)` 等浏览器权威值,不能使用 `screenHeight - windowHeight` 或 `screen.height - innerHeight` 推算。App/小程序只读取平台权威 inset;零值正常,禁止用 `inset || guessedFallback` 换成猜测值。验收必须覆盖物理屏幕与浏览器视口不同、非最大化桌面、缩放和移动浏览器工具栏收展。
57
+
56
58
  - 桌面浏览器允许使用 `Microi UniApp H5 Preview` 手机壳帮助用户理解移动端比例。
57
- - 真机、窄屏浏览器以及 PC DevTools 移动设备仿真(视口宽度小于等于 `767px`)必须自动去掉手机壳标题、外边距、圆角、边框和阴影,内容铺满 `100vw × 100vh`;不得在手机屏幕里再套一层模拟手机。
59
+ - 真机、窄屏浏览器以及 PC DevTools 移动设备仿真必须自动去掉手机壳标题、外边距、圆角、边框和阴影,内容铺满当前可见视口。`767px` 是常用宽度断点,不是手机身份判断;手机横屏/旋转不能因宽度超过它就重新套壳。H5 优先使用动态视口高度并保留旧浏览器兜底,键盘与浏览器栏变化要重新核对可见区域。
60
+ - 桌面手机壳必须约束高度,不能只用 `min-height:100vh` 让内容继续撑长。导航底边贴齐手机壳**内屏**底边,不是浏览器窗口底边;头部和导航不收缩,正文及路由中间包装层使用 `flex:1; min-height:0; min-width:0`。
61
+ - 普通单列壳只有一个正文滚动 owner;流内底栏已占高度,不再给正文叠加整条 tabBar 占位。覆盖式固定底栏由共享布局预留一次实测总高度,包含真实安全区;禁止根容器、正文、占位元素与导航分别重复累加底部间距。双栏列表仅允许明确设计的两块独立滚动区。
62
+ - 桌面宽度限制不能阻止 `rpx` 按外窗宽度放大。把 `rpxCalcMaxDeviceWidth / rpxCalcBaseDeviceWidth` 与壳宽、断点统一,并从实际产物核验导航/图标高度;填满容器使用 `%` 或 flex,不使用 `750rpx`。
58
63
  - AI 应用预览编译器必须为每个底部菜单渲染真实 SVG/本地图标和文字,不能只输出文字、单汉字、emoji 或空白占位。原生 uni-app `tabBar` 仍使用纳入版本管理的本地 PNG `iconPath / selectedIconPath`。
59
- - 自动化验收必须同时使用桌面视口与移动视口截图:桌面端断言手机壳存在,移动端断言 `.phone-status` 隐藏且 `.phone` 无圆角、无边框、宽高铺满;每个底部菜单的图标元素和文字都必须可见、可点击。
64
+ - 自动化验收不能只断言手机壳或图标节点存在。至少覆盖三个主 Tab 的真实内屏/导航/触摸区矩形、导航下方剩余高度、滚动 owner 和末条内容可达;覆盖桌面矮屏、断点、手机横竖屏、键盘打开与关闭后恢复。使用视口截图,桌面 body 不产生第二条竖向滚动条;真实键盘/安全区另做渠道或真机验收。
65
+ - 完整实现与门禁示例见 [H5 手机壳和几何验收](references/progressive-01-移动端分类-双栏列表独立滚动.md#h5-在-pc-浏览器必须自动模拟移动端)。修改共享壳后重跑所有 Tab 与路由,不能只给当前页面补 padding。
60
66
 
61
67
  <!-- /microi-progressive:chunk -->
62
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-003 sha256=5cedd05cb29746019a92db56a21123718fde23d5d9df4b8064dfc260bc89ee05 -->
68
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-003 sha256=cf398596130bfa85683b358683631d5056bb3c48a4049214d00a9b26e3a61ec4 -->
63
69
  ## 登录页与手机号快捷登录
64
70
 
65
71
  - 登录页必须是直接登录面,不要默认做“员工登录 / 客户登录”身份 Tab 切换,除非用户明确要求。默认展示系统账号密码登录,同时提供客户手机号快捷登录入口。
@@ -77,7 +83,7 @@ Microi 标准小程序必须采用“平台内核 + 版本化元数据 + Profile
77
83
  - 微信小程序构建后必须扫描登录页源码以及 `dist/build/mp-weixin/pages/login/` 产物,并截图核对手机号快速验证前置页;命中上述混淆文案、官方图形或近似元素时必须阻止上传和提审,不能只检查按钮主文案而漏掉说明文字、错误弹窗或分享标题。
78
84
 
79
85
  <!-- /microi-progressive:chunk -->
80
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-004 sha256=cc25e3d896e6f7349a7a7e93b8025ee797bf9810e60214eb95e41d75aa083422 -->
86
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-004 sha256=c0e95b3c0fef84be2526e4b902a7c0d980d98217139b0d0b5b5b6fca7145641d -->
81
87
  ## 微信小程序全页面分享
82
88
 
83
89
  - 创建或维护 UniApp 微信小程序时,默认把好友转发与朋友圈分享视为页面基础能力;按 `pages.json` 全量路由逐页接入,不等待用户额外提出。
@@ -88,7 +94,7 @@ Microi 标准小程序必须采用“平台内核 + 版本化元数据 + Profile
88
94
  - 验收不能只看首页右上角。用脚本比较 `pages.json` 路由数量与源码/微信构建产物中的两种分享生命周期数量,并在体验版抽测公开页、登录页和受保护详情页。
89
95
 
90
96
  <!-- /microi-progressive:chunk -->
91
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-005 sha256=d6f78d95dc0b0b042f0d0c525a9cb5295a0324f1c70d6f480c93f2e03d315cec -->
97
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-005 sha256=7e002241f968def653a6ddb7934b3a4f185a0cf5fc845dd31d16f2a47d5cd598 -->
92
98
  ## 首屏 Hero 与浮动面板验收
93
99
 
94
100
  - 移动端首屏 Hero 标题必须按真实中文文案调字号和行高,不能为了“震撼”把业务入口标题做得过大,导致一行半、孤字换行或压住按钮。
@@ -96,7 +102,7 @@ Microi 标准小程序必须采用“平台内核 + 版本化元数据 + Profile
96
102
  - 交付前至少检查 375px 与 430px 宽度首屏截图,确认标题、主按钮、次按钮、浮动面板、第二块内容没有重叠、裁切或不美观换行。
97
103
 
98
104
  <!-- /microi-progressive:chunk -->
99
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-006 sha256=a39f7e4fb42c6d290463a9e40eed03235e4afe063d60208b5a3e73a170fbc39f -->
105
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-006 sha256=4ddf2899af481528fd518842ec98aa31ada5e5c0b5dc585c27098b5413b2dd5a -->
100
106
  ## 资源 URL 必须集中解析
101
107
 
102
108
  数据库中的图片、附件、头像、Logo、卡面图、单据图片等字段常见保存形式:
@@ -120,7 +126,7 @@ Microi 标准小程序必须采用“平台内核 + 版本化元数据 + Profile
120
126
  - 第三方占位图、已失效临时地址、空字符串统一清理为空,交给 UI 占位态。
121
127
 
122
128
  <!-- /microi-progressive:chunk -->
123
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-007 sha256=3894454672b6bde6f4a7b329103c9418804f4594b7e3505617590ebea5f136ab -->
129
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-007 sha256=bc13da83759030866897991a5192831ee28bb24ad0ff5a5ad9e5c57917520f0d -->
124
130
  ## 移动端大资源优先使用租户 HDFS/CDN
125
131
 
126
132
  定制 UniApp/H5/小程序中的大图、视频、音频、字体和大型第三方静态文件,默认不要塞进主包。应先确认目标 `OsClient`,通过该租户 MCP/HDFS 上传,再以 `sys_config.FileServer + Path` 的 CDN/公有桶地址引用;合同、证件等敏感资源仍必须使用私有桶和临时签名 URL。
@@ -136,7 +142,7 @@ Microi 标准小程序必须采用“平台内核 + 版本化元数据 + Profile
136
142
  - 原始高清图、视频母版、设计源文件不得继续放在会被 UniApp 收集的 `src/static`、分包目录或其它构建入口中;应移到项目资料/设计源目录。主包仅保留小于门禁的轻量失败占位图和离线关键图标。
137
143
 
138
144
  <!-- /microi-progressive:chunk -->
139
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-008 sha256=d7b2b5c8ffe5c1dd8f51eb7d5e8368dba6813c2fa25d39dd3fb8f6659922b5b9 -->
145
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-008 sha256=d52c69b1f93de27639f47c25916cb6c479465ff0db9e5ef3db81073dd50ebebb -->
140
146
  ## 头像必须异步统一解析
141
147
 
142
148
  头像字段比普通图片更容易混合出现上传 JSON、私有路径、相对路径、历史字段名和脏数据。列表页、详情页、业务记录、审批记录、团队/会员卡片、聊天/消息等头像场景都必须走同一个头像解析入口。
@@ -157,7 +163,7 @@ row.OwnerAvatarUrl = await resolveAvatarUrl(rawAvatar);
157
163
  禁止在模板中临时拼接文件服务器,禁止每个页面各写一套头像解析,禁止只在能查到关联用户时才解析接口已经返回的头像字段。
158
164
 
159
165
  <!-- /microi-progressive:chunk -->
160
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-009 sha256=0270fbc5a2ee0d20a4d1d2f2a9c7fc7304e18402d282e1efcf860bd31db9fcb0 -->
166
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-009 sha256=20cfb0b95ea827e9cbca1272b27a57a080976fc1fd8db3b4586e0dc5ed13d903 -->
161
167
  ## 移动端富文本图文排版
162
168
 
163
169
  商品详情、公告详情、活动说明、文章正文、协议说明等富文本在移动端渲染时,图片和文字不能使用同一套留白规则。
@@ -2,13 +2,13 @@
2
2
 
3
3
  > 按需读取;本文件由 SKILL.md 的原章节无损拆分。
4
4
 
5
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-010 sha256=2820c6dbc7641b03cb2d3af98f80ca654162fdac7995993be5cb7e25b8e5bdea -->
5
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-010 sha256=81d5dbf6cae493337a5289d66ef39bb6d6a64a3e3f64c98e228dc77853810986 -->
6
6
  ## 移动端分类/双栏列表独立滚动
7
7
 
8
8
  商品分类、知识库分类、通讯录分组、资产分类等“左侧分类 + 右侧列表”的移动端页面,根节点必须固定在一个视口内,不能让整页和内部列表同时滚动。
9
9
 
10
- - 根页面使用 `height:100vh; overflow:hidden; display:flex; flex-direction:column;`。
11
- - 分类主体使用 `flex:1; min-height:0; display:flex;`,并给底部 tabBar 预留 `padding-bottom: calc(tabBarHeight + env(safe-area-inset-bottom));`。
10
+ - 根页面使用有界视口高度、`overflow:hidden; display:flex; flex-direction:column;`;H5 使用 `100dvh` 或共享可见高度变量,保留 `100vh` 旧端兜底。
11
+ - 分类主体使用 `flex:1; min-height:0; display:flex;`。导航在根 flex 流内时不再加 tabBar 占位;导航覆盖正文时,才由共享壳预留一次实测总高度(已经包含安全区)。
12
12
  - 左侧分类和右侧列表分别用 `scroll-view scroll-y`,高度来自父级 `height:100%` / `flex:1; min-height:0`,不要用整页滚动承载右侧商品列表。
13
13
  - 右侧分页必须绑定 `@scrolltolower`,设置合理 `lower-threshold`,并维护 `pageIndex/pageSize/loading/finished`,第一页重置列表,后续页追加列表。
14
14
  - 切换左侧分类或顶部专区时,必须重置分页状态并重新加载第一页;不能沿用旧分类的 `finished` 或 `pageIndex`。
@@ -27,14 +27,16 @@
27
27
  ```
28
28
 
29
29
  ```scss
30
- .page-category { height: 100vh; overflow: hidden; display: flex; flex-direction: column; }
31
- .cat-body { flex: 1; min-height: 0; display: flex; padding-bottom: calc(104rpx + env(safe-area-inset-bottom)); }
30
+ .page-category { height: 100vh; height: var(--mci-visible-height, 100dvh); overflow: hidden; display: flex; flex-direction: column; }
31
+ .cat-body { flex: 1; min-height: 0; display: flex; }
32
32
  .cat-side { width: 176rpx; height: 100%; }
33
33
  .cat-content { flex: 1; min-width: 0; height: 100%; }
34
+ // 本示例采用流内导航,导航自己占高度并消费安全区;覆盖式导航另由共享壳预留实测高度。
35
+ .category-nav { flex-shrink: 0; padding-bottom: var(--mci-safe-bottom, env(safe-area-inset-bottom)); }
34
36
  ```
35
37
 
36
38
  <!-- /microi-progressive:chunk -->
37
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-011 sha256=a28fba298274b738ef9039c6bd6a1707468687e2ae9644a819736374586749e9 -->
39
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-011 sha256=fcf60104a95a27645f4b519b19bde6aab55d41f38388c442179533dd4ed8a35a -->
38
40
  ## 数据页必须使用骨架屏 Loading
39
41
 
40
42
  任何依赖接口/数据库返回数据的移动端页面,都必须区分 `loading`、`data`、`empty`,并且首屏加载态必须使用骨架屏(Skeleton Screen)。接口请求结束前不能提前显示“暂无数据/暂无明细/空空如也”,也不能只用“图标 + 数据加载中...”或单独 spinner 作为页面级 loading。
@@ -72,27 +74,28 @@ async function load() {
72
74
  ```
73
75
 
74
76
  <!-- /microi-progressive:chunk -->
75
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-012 sha256=5554c817702cc491937fb2b32f5ba2ce76554a35ef0a2189979ff1d60789ab30 -->
77
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-012 sha256=affb88f7856aa410c7d8dd4efa9a5b804be4721efda013e2319203e490d58f54 -->
76
78
  ## 移动端安全区必须兼容 iOS 与 Android
77
79
 
78
80
  任何 UniApp/H5 移动端页面都必须同时适配 iPhone 刘海屏/Dynamic Island/Home Indicator、Android 状态栏/虚拟导航栏/手势条、微信/浏览器/WebView 容器差异。不要用固定 `20px/44px/64px` 直接硬编码顶部或底部间距。
79
81
 
80
82
  - `manifest.json` / H5 模板必须确保 viewport 含 `viewport-fit=cover`,否则 iOS 的 `env(safe-area-inset-*)` 不会完整生效。
81
- - 页面根节点使用 `min-height:100vh` 或固定视口布局时,顶部内容、底部固定栏和内部滚动容器必须一起考虑安全区,不能只给根节点加 padding。
83
+ - 页面根节点使用最小高度或固定视口布局时,顶部内容、底部固定栏和内部滚动容器必须一起考虑安全区,不能只给根节点加 padding;有界 H5 壳优先动态可见高度,不能用 `min-height:100vh` 代替高度上限。
82
84
  - 顶部自定义导航栏应结合 `uni.getSystemInfoSync().statusBarHeight` 和 CSS `env(safe-area-inset-top)`:状态栏占位负责不同系统高度,导航按钮和标题整体下移,返回按钮触摸区不能压到刘海/状态栏。
83
85
  - 不能只依赖 `env(safe-area-inset-*)`。微信小程序、部分 Android WebView 或开发者工具中该值可能为 `0`;项目必须通过 `uni.getWindowInfo()`(旧端回退 `uni.getSystemInfoSync()`)读取 `statusBarHeight`、`safeArea` / `safeAreaInsets`,注入统一的 `--mci-safe-top`、`--mci-safe-bottom` 等页面壳变量。
84
86
  - 微信小程序使用 `navigationStyle: custom` 时,必须读取 `uni.getMenuButtonBoundingClientRect()`(必要时回退 `wx.getMenuButtonBoundingClientRect()`),给顶部栏右侧预留 `windowWidth - capsule.left + gap`。登录、分享、状态角标、更多操作等任何按钮都不能进入右上角胶囊区域。
85
87
  - 全屏弹层/工作台如果包含历史、新建、关闭等多个头部操作,必须先计算整组宽度;胶囊左侧不足时将整组放到胶囊底边以下,不得通过缩小触摸区、覆盖胶囊或截断标题硬塞。自动化测试应读取元素与胶囊 `boundingClientRect` 并断言不相交。
86
88
  - 安全区实现必须集中在 `MciPage`、页面壳 composable/runtime 或全局布局中;禁止每页各自猜测 `20px/44px`。`pages.json` 中每个 `navigationStyle: custom` 页面都必须接入同一个页面壳,新增路由时同步纳入检查。
87
- - 底部 `tabBar`、购买栏、提交栏、批量操作栏等 fixed 元素必须使用 `padding-bottom: env(safe-area-inset-bottom)`,主体内容必须额外预留底部高度,避免最后一条数据被按钮或 tabBar 遮挡。
89
+ - 底部 `tabBar`、购买栏、提交栏、批量操作栏应在栏内消费统一的真实安全区。流内栏已经占据布局高度,正文不得再加整条栏占位;覆盖式 fixed 栏才预留一次栏的实测总高度,确保最后一条数据可见。
88
90
  - 底部 fixed 元素应优先使用运行时 `--mci-safe-bottom`,以 CSS `env(safe-area-inset-bottom)` 作为 H5 兜底;底部导航、提交栏、弹出层和滚动容器必须引用同一变量,不能各算一套。
89
- - 双栏分类页、聊天页、详情页带底部按钮时,内部 `scroll-view` 要用 `flex:1; min-height:0` 承载滚动,并在滚动容器底部预留 `calc(fixedBarHeight + env(safe-area-inset-bottom))`。
91
+ - 双栏分类页、聊天页、详情页带底部按钮时,内部 `scroll-view` 要用 `flex:1; min-height:0` 承载滚动。`fixedBarHeight` 若已经包含安全区,不再加一份 `env`;禁止根 padding、原生占位、正文 padding 和栏 padding 共同重复预留。
90
92
  - H5 在 PC 手机壳模式下,fixed 顶栏/底栏仍要限制在手机壳宽度内;不能铺满整个桌面浏览器。
93
+ - 桌面预览没有真实手机手势区时底部安全区为 `0`;不能为了模仿手机外观硬塞 `34px/80rpx` 等假安全区。边框、阴影、装饰 Home Indicator 与系统安全区要分别处理。
91
94
  - 验收必须至少覆盖一个 iPhone 刘海/灵动岛尺寸、一个 Android 高状态栏或虚拟导航栏尺寸、一个微信开发者工具真机模拟尺寸、一个 PC H5 手机壳尺寸;逐项截图检查顶部不被状态栏/胶囊遮挡、底部按钮不贴边、列表最后一项可见。不能只截图首页,必须按 `pages.json` 路由清单覆盖登录、Tab 页、详情、表单、弹层和管理页。
92
95
  - 独占屏幕且需要支持手机侧滑返回的功能应使用独立页面路由。`onBackPress`/页面返回先消费当前页内部的键盘、对话框和抽屉状态;内部状态清空后才弹出当前页,不能让一次返回直接退出小程序或越过底层业务页。
93
96
 
94
97
  <!-- /microi-progressive:chunk -->
95
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-013 sha256=591a8e5a3e33cfcdb102abf56ebc6eeb5c5896d621442c30e734f455d625842c -->
98
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-013 sha256=b6074ef264327e9cc630a9c4136989d6355ed33ba4902098e8ae025661a207ed -->
96
99
  ## 微信自定义组件的点击与拖动事件必须真机链路验收
97
100
 
98
101
  - UniApp 可拖动浮动入口等自定义组件,不要给 `touchstart/touchmove/touchend/tap` 整组无差别添加 `.stop/.prevent`。这些修饰符会生成微信 `catchtouch* / catchtap`,部分 UniApp 自定义组件中可能吞掉事件桥,出现节点可见但点击和触摸方法完全不执行。
@@ -121,7 +124,7 @@ async function load() {
121
124
  ```
122
125
 
123
126
  <!-- /microi-progressive:chunk -->
124
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-014 sha256=62f20b920f2365d9f2f5062218b10b17aa181ccb3ae5d2260f795e086355f678 -->
127
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-014 sha256=201c7dd1b1e923a62319f1402088fa696bb96aa8ca58a8c7f9817a6ecce36e12 -->
125
128
  ## 列表型资料页必须提供完整管理动作
126
129
 
127
130
  地址、联系人、收款方式、发票抬头、车辆、设备、证照、银行卡等用户维护型资料页,不能只展示简略列表。除非业务明确只读,移动端必须提供:
@@ -135,7 +138,7 @@ async function load() {
135
138
  - 空态行动:没有数据时给出新增入口,但仍要遵守上面的加载态规则。
136
139
 
137
140
  <!-- /microi-progressive:chunk -->
138
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-015 sha256=d8e9280b5127d7dafd4dcb83b22bdb379fef39eac1e2e1b2e37f1c064cfe7fc6 -->
141
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-015 sha256=287d085d3651e0eb20b97fadf0ba616e9f4aea9447efda6824612b64309efd27 -->
139
142
  ## 移动端资产/奖励流水展示
140
143
 
141
144
  收益明细、积分明细、奖励明细、充值记录、订单流水等页面要面向用户展示“发生了什么”和“是否到账”,不要直接暴露后台调试字段。
@@ -147,79 +150,112 @@ async function load() {
147
150
  - 后端接口应先把 `TypeLabel`、`SettleStatusLabel`、`DisplayTime`、`ContributorName`、`CardNo` 等字段整理好,前端只做轻展示,避免多个页面各自拼接导致重复或口径不一致。
148
151
 
149
152
  <!-- /microi-progressive:chunk -->
150
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-016 sha256=610b00696fd8a1548842974b5551e0e55bc276a3605459947251f508b4ef2ad3 -->
153
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-016 sha256=f1c583f99234a5a82a7c1557658c3ba036020b39d5524466eca0e2b1cdb85988 -->
151
154
  ## H5 在 PC 浏览器必须自动模拟移动端
152
155
 
153
156
  移动端 UniApp H5 被 PC 浏览器访问时,不能按桌面宽屏铺满。必须在全局样式里用媒体查询生成手机预览壳。
154
157
 
155
158
  基础要求:
156
159
 
157
- - `@media screen and (min-width: 768px)` 下把 `uni-app` 居中并限制到常见手机宽度,例如 `430px`。
160
+ - 桌面预览把内屏居中并限制到常见手机宽度,例如 `430px`;预览条件综合宽度、输入能力或项目运行时设备标记,不能仅按 `min-width:768px` 把手机横屏当桌面。下面媒体查询是精细指针桌面示例,项目还需验证移动设备仿真和真实设备判断。
158
161
  - `html, body` 使用克制的桌面背景,`uni-app` 内保持移动端页面本身背景。
159
162
  - 如果项目或主题给 `body.theme-light`、`body.theme-dark` 写了背景色,PC 媒体查询必须显式覆盖,避免手机壳外侧仍显示暗色或项目内装饰背景。
160
- - 同步约束 `uni-page`、`uni-page-wrapper`、`uni-page-body` 的宽度。
161
- - `uni-page-body` 给底部菜单和安全区预留 padding,避免内容或底部操作栏压住 tabBar。
162
- - 所有 `position: fixed` 底部操作栏按同一手机壳宽度居中。
163
- - 原生 `uni-tabbar` 和 `.uni-tabbar` 必须显式设置 `position: fixed`、`bottom: 0`、同宽居中和足够的 `z-index`,否则主体像手机壳但底部菜单可能丢失或铺满 PC 宽屏。
163
+ - 同步约束页面壳及 `uni-page / uni-page-wrapper / uni-page-body` 中实际参与布局的包装层:`min-height:0; min-width:0`。头部和导航不收缩,剩余高度留给正文;不能把 `uni-page-body` 写成整屏高后再追加导航。
164
+ - 先确定导航是流内还是覆盖式。流内栏使用 `flex-shrink:0`,正文不加整栏占位;覆盖式栏的宽、高、底边和唯一占位由共享壳负责。原生 `uni-tabbar` 的平台占位存在时不能再叠自定义占位。
165
+ - 有桌面外边距或矮屏壳时,栏必须贴壳内屏底边,不是外窗 `bottom:0`。为覆盖式栏建立属于内屏的定位包含块,或根据其真实矩形定位;不要同时给原生 tabBar 外层和内层重复 `fixed`。
166
+ - `rpx` 按设备宽度计算,不自动跟随 CSS 手机壳宽度。`pages.json.globalStyle` 的最大换算宽度和基准宽度应与预览策略一致,例如 767/430;检查 768、960 和 4K 外窗的实际换算结果。全宽使用 `100%` 或 flex,不能用 `750rpx`。参见 [DCloud 宽屏适配](https://uniapp.dcloud.io/tutorial/adapt.html)。
164
167
  - 页面内 `position: fixed` 的装饰背景(如 aurora、粒子、全屏渐变)在 PC 壳模式下必须收回到 `uni-app/uni-page-body` 内,不能覆盖整块桌面背景。
165
168
 
166
- 参考样式:
169
+ 自定义流内导航参考结构(选择该模式后,不再并列渲染原生导航):
167
170
 
168
- ```scss
169
- @media screen and (min-width: 768px) {
170
- html,
171
- body {
172
- min-height: 100%;
173
- background:
174
- linear-gradient(135deg, rgba(255,255,255,.78), rgba(244,246,250,.92) 44%, rgba(236,239,245,.98)),
175
- radial-gradient(circle at 18% 16%, rgba(181,18,32,.07), transparent 32%),
176
- radial-gradient(circle at 84% 10%, rgba(216,162,58,.08), transparent 28%),
177
- #F3F5F9;
178
- }
171
+ ```html
172
+ <main class="mci-h5-viewport" data-app-viewport>
173
+ <header class="mci-preview-header">移动端预览</header>
174
+ <section class="mci-page-scroll" data-page-scroll>页面内容</section>
175
+ <nav class="mci-bottom-nav" data-bottom-nav>图标与菜单触摸区</nav>
176
+ </main>
177
+ ```
179
178
 
180
- body { margin: 0; }
179
+ 参考样式:
181
180
 
182
- uni-app {
183
- position: relative;
184
- display: block;
185
- width: min(430px, 100vw);
186
- min-height: 100vh;
187
- margin: 0 auto;
188
- overflow-x: hidden;
189
- background: var(--app-bg-base, #F7F8FB);
181
+ ```scss
182
+ html, body { margin: 0; height: 100%; overflow: hidden; }
183
+ .mci-h5-viewport {
184
+ box-sizing: border-box;
185
+ width: 100%; height: 100vh;
186
+ height: var(--mci-visible-height, 100dvh);
187
+ min-height: 0;
188
+ display: flex; flex-direction: column; overflow: hidden;
189
+ background: var(--app-bg-base, #F7F8FB);
190
+ }
191
+ .mci-preview-header { display: none; flex-shrink: 0; }
192
+ .mci-page-scroll { flex: 1; min-height: 0; min-width: 0; overflow-y: auto; }
193
+ .mci-bottom-nav {
194
+ flex-shrink: 0; box-sizing: border-box;
195
+ padding-bottom: var(--mci-safe-bottom, env(safe-area-inset-bottom, 0px));
196
+ }
197
+ @media screen and (min-width: 768px) and (hover: hover) and (pointer: fine) {
198
+ body { display: grid; place-items: center; background: #F3F5F9; }
199
+ .mci-h5-viewport {
200
+ --mci-safe-bottom: 0px; // 桌面预览没有手机系统手势区,不伪造安全区。
201
+ width: 430px;
202
+ height: calc(100vh - 32px); height: calc(100dvh - 32px);
203
+ max-height: 900px;
204
+ border-radius: 24px;
190
205
  box-shadow: 0 18px 54px rgba(28, 36, 52, .16);
191
206
  }
207
+ .mci-preview-header { display: block; }
208
+ }
209
+ ```
192
210
 
193
- uni-page,
194
- uni-page-wrapper,
195
- uni-page-body {
196
- width: 100% !important;
197
- max-width: 430px;
198
- margin: 0 auto;
199
- }
211
+ 真实 UniApp 页面还应检查框架包装层高度和原生 tabBar 占位。这个结构示例不授权业务页覆盖所有 `uni-*` 标签,也不适用于必须使用文档滚动的页面;文档滚动模式必须另行证明根滚动是唯一 owner、导航跟随可见视口且尾部占位仅一份。
200
212
 
201
- uni-page-body {
202
- padding-bottom: calc(64px + env(safe-area-inset-bottom));
203
- }
213
+ ### 导航贴底与剩余空间的真实断言
204
214
 
205
- .bottom-bar {
206
- left: 50% !important;
207
- right: auto !important;
208
- width: calc(min(430px, 100vw) - 24px);
209
- transform: translateX(-50%);
210
- }
215
+ H5 安全区必须来自 CSS `env(safe-area-inset-bottom)` 等浏览器权威来源。`screenHeight - windowHeight` 与 `screen.height - innerHeight` 包含外窗、工具栏和缩放差异,禁止转换为安全区 padding。App/小程序的权威 inset 可以为 `0`,只能在值缺失时按明确平台契约处理,不能用 `inset || guessedFallback` 将零替换。桌面非最大化窗口和缩放必须纳入验收,物理屏幕与视口不同也应保持导航内栏高度有界。
211
216
 
212
- uni-tabbar,
213
- uni-tabbar .uni-tabbar {
214
- position: fixed !important;
215
- left: 50% !important;
216
- right: auto !important;
217
- bottom: 0 !important;
218
- width: min(430px, 100vw) !important;
219
- transform: translateX(-50%);
220
- z-index: 99 !important;
221
- }
222
- }
217
+ 下列例子测量自定义流内导航;选择器按项目真实结构替换,目标边界必须是**内屏**而不是带边框的装饰壳。设计值在测试开始前固定,不能根据异常画面扩大阈值:
218
+
219
+ ```js
220
+ const geometry = await page.evaluate(() => {
221
+ const rect = node => {
222
+ const r = node.getBoundingClientRect();
223
+ return { top: r.top, bottom: r.bottom, left: r.left, right: r.right, height: r.height };
224
+ };
225
+ const screen = document.querySelector('[data-app-viewport]');
226
+ const nav = document.querySelector('[data-bottom-nav]');
227
+ const scroll = document.querySelector('[data-page-scroll]');
228
+ if (!screen || !nav || !scroll) throw new Error('页面结构缺失');
229
+ const items = [...nav.querySelectorAll('[data-nav-item]')];
230
+ if (!items.length) throw new Error('导航菜单缺失');
231
+ return {
232
+ screen: rect(screen), nav: rect(nav), scroll: rect(scroll), items: items.map(rect),
233
+ safeBottom: parseFloat(getComputedStyle(nav).paddingBottom) || 0,
234
+ rootOverflow: document.scrollingElement.scrollHeight - document.scrollingElement.clientHeight
235
+ };
236
+ });
237
+ expect(Math.abs(geometry.nav.bottom - geometry.screen.bottom)).toBeLessThanOrEqual(2);
238
+ expect(geometry.nav.left).toBeGreaterThanOrEqual(geometry.screen.left - 2);
239
+ expect(geometry.nav.right).toBeLessThanOrEqual(geometry.screen.right + 2);
240
+ expect(geometry.scroll.bottom).toBeLessThanOrEqual(geometry.nav.top + 2);
241
+ expect(geometry.rootOverflow).toBeLessThanOrEqual(2);
242
+ expect(geometry.nav.height).toBeLessThanOrEqual(designNavContentHeight + geometry.safeBottom + 2);
243
+ const lastItemBottom = Math.max(...geometry.items.map(item => item.bottom));
244
+ expect(geometry.nav.bottom - lastItemBottom)
245
+ .toBeLessThanOrEqual(geometry.safeBottom + designNavInnerBottomGap + 2);
246
+ await page.screenshot({ path: screenshotPath, fullPage: false });
223
247
  ```
224
248
 
249
+ `safeBottom` 在此示例是 CSS 计算结果,不代表系统安全区来源已经可信。测试仍须核对运行时安全值、同一个值的唯一消费位置和桌面为零;不能用一个错误的巨大 padding 放宽几何门禁。短内容允许正文留白,禁止的是**导航下方**无业务依据的大块剩余区域。
250
+
251
+ | 场景 | 必须断言 |
252
+ |---|---|
253
+ | 三个主 Tab、短内容/空态 | 导航底边贴内屏,内栏高度有界,图标文字可见且触摸区可点 |
254
+ | 长内容滚动中/到底、切回 Tab | 导航位置不漂移,最后一项可达且未遮挡,壳外根滚动不变化 |
255
+ | 桌面 1024×600 / 1366×768 / 1920×1080 / 4K | 内屏在视口内,导航贴壳底;rpx 不随外窗放大,正文只有一个 owner |
256
+ | 手机 375×812 / 430×932、767/768 断点、横屏与旋转 | 移动模式去壳,内屏铺满可见区域;旋转后重测安全区和底边 |
257
+ | 键盘打开/关闭、浏览器栏展开/收起 | 焦点与操作可见,关闭后恢复底边,无残留占位或第二条滚动条 |
258
+
259
+ H5 键盘可能改变 visual viewport 而不改变 layout viewport;`100dvh` 不是所有键盘模式的保证。共享壳按目标浏览器处理 `visualViewport` 尺寸/偏移与 resize/恢复,原生端按配置的键盘模式测量;真机 iOS/Android 另验。缩小 Playwright 视口只证明 resize 分支,不等于软键盘实测。参考 [W3C Viewport 交互部件规则](https://www.w3.org/TR/css-viewport-1/#interactive-widget-section)。
260
+
225
261
  <!-- /microi-progressive:chunk -->
@@ -2,7 +2,7 @@
2
2
 
3
3
  > 按需读取;本文件由 SKILL.md 的原章节无损拆分。
4
4
 
5
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-017 sha256=f4c3bd827f3349b65dd40c894a51299d32ba7d75ba58a3a81d04aaba6b1733f2 -->
5
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-017 sha256=9ef6eaa852b4b29ee01b51a4353685ee97ee219ff5d6da881f3de6371654861f -->
6
6
  ## 关键业务资产不得默认选中
7
7
 
8
8
  凡是会扣减、消耗、转移、提交审批或触发财务后果的业务资产,都不能默认选中第一条。例如资产卡、余额账户、积分账户、优惠券、库存批次、付款账户、审批对象、设备工单等。
@@ -15,7 +15,7 @@
15
15
  - 规则同时写在 UI 状态和提交前校验中。
16
16
 
17
17
  <!-- /microi-progressive:chunk -->
18
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-018 sha256=35f9826cc82000f9cedd3ccaffd8e7718b0efbec75cf12665145f1de4f8a6d23 -->
18
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-018 sha256=c55461eba07b7763cb7810818574d4660fbaeed65f95e894e0f859aa96b4bbd2 -->
19
19
  ## 账号角色与会话状态
20
20
 
21
21
  - Microi 企业移动端默认要从 `sys_user.RoleIds`、`_Roles`、`Roles`、`RoleName`、`Level` 解析内部账号角色,不要只用“是否登录”控制界面。
@@ -31,7 +31,7 @@
31
31
  - 收到 `Code=1001/1002` 时用可完整阅读的模态框展示后端 `Msg`,包括过期分钟/小时/天或租户不匹配信息,确认后再跳登录;不能先覆盖成固定 Toast。
32
32
 
33
33
  <!-- /microi-progressive:chunk -->
34
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-019 sha256=72621b385229c3308cbe98dbfa0fb29de95e88d675dad31d9fbe4543b441fdbb -->
34
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-019 sha256=7a258af0c36dd3e82d7f9444043d3b0b9d3bc99f329ff85a167b91594b1a54b1 -->
35
35
  ## 数字、主题、上传与消息
36
36
 
37
37
  - 资产金额、积分、余额、库存值、累计充值、收益等数字要按空间自适应格式化。金额很大时显示为 `1.23万`、`123万`、`1.2亿` 等,不能撑破卡片。
@@ -46,7 +46,7 @@
46
46
  - 私有图片、身份证照片、支付凭证等禁止匿名访问的文件,前端必须先换取临时 URL;不能直接把私有路径给 `<image>`。
47
47
 
48
48
  <!-- /microi-progressive:chunk -->
49
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-020 sha256=6f5c05a725b3325feb889fbb4c97621e247ca9d6eb89970bf9f8602a81177524 -->
49
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-020 sha256=2ae732a49279cc7604169a302987d5428ab3b9e8a108ec442813bbd0aea735a0 -->
50
50
  ## 图片上传必须支持替换与预览
51
51
 
52
52
  头像、支付凭证、实名认证、收款码、证照、商品图、富文本图片等移动端图片上传场景,选择图片后不能把入口锁死。所有上传入口必须统一做到:
@@ -60,7 +60,7 @@
60
60
  - 自动化或手工验收至少覆盖支付凭证、头像/实名认证/收款码中一个私有图场景,确认可替换、可预览、不会丢表单字段。
61
61
 
62
62
  <!-- /microi-progressive:chunk -->
63
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-021 sha256=ad8b543f8e0cd7a20464adb88d456bc21e0451e3f216b1419fa572631543cd49 -->
63
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-021 sha256=68367fcd8e3fae5c2e7da8a956fd803b712ea7bdddbc5a595b16c35b4f7c9fd8 -->
64
64
  ## 组件复用与页面去重
65
65
 
66
66
  同一类 UniApp/H5 UI 在两个及以上页面出现时,必须抽成 `Mci*` 或项目级 `mci-*` 组件,不要复制模板和 scoped 样式到多个业务页面。常见必须复用的结构包括:未登录/授权提示、空态、错误态、骨架屏、列表卡片、商品卡、消息卡、筛选栏、Tab、底部操作栏、按钮组、头像/角标。
@@ -73,7 +73,7 @@
73
73
  - 对复用组件补充自动化检查:静态检查至少确认业务页使用同一个组件;视觉检查至少覆盖两个不同业务页实例。
74
74
 
75
75
  <!-- /microi-progressive:chunk -->
76
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-022 sha256=79b92cb4a1e0b37d786b148a98848fbae3f4424b4d07febc96adbf62ef389431 -->
76
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-022 sha256=bf2b295c18b0e848bffb9dd16a3c8fa2c1d022e7f9a344dd100a2305c5e14de1 -->
77
77
  ## 验收要求
78
78
 
79
79
  每次改动 UniApp/H5 前端后,至少做以下验证:
@@ -90,7 +90,7 @@
90
90
  - 未登录/未授权态必须额外截图确认:提示卡片位于 header 与 tabBar/底栏之间的可用区域中心,不能只横向居中但纵向贴顶。
91
91
 
92
92
  <!-- /microi-progressive:chunk -->
93
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-023 sha256=bdd657712c4a6a12698c619d22c58b43648c3a3ab32ded54f09c3dc7331ad8ab -->
93
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-023 sha256=07c9a59b5b1c165d75648a618039d9627560398a4849da78ea6d1cfa71c4c0de -->
94
94
  ## Microi 前端 SDK 必须接入
95
95
 
96
96
  任何 Microi UniApp/H5 Vue3 项目都必须优先使用 `microi.skills/microi.v8.js` 作为统一前端 SDK,并参考 `microi.skills/microi-frontend-sdk/SKILL.md`。新项目不得再手写分散的 `uni.request`、Token 存储、上传、私有文件 URL、头像解析、`ApiEngine` 或 `FormEngine` 包装。
@@ -103,7 +103,7 @@
103
103
  - SDK 不绑定任何 UI 库;页面 UI 仍遵守本 Skill 的骨架屏、安全区、移动端富文本和资源展示规范。
104
104
 
105
105
  <!-- /microi-progressive:chunk -->
106
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-024 sha256=b2b9b1ea707ab4bd114db5838eda185b7b7e375435cdca21effd7be24f996a27 -->
106
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-024 sha256=c206d390961681ac6dec722beb96c598efa97a97112744c9fabc6f7eee79e43c -->
107
107
  ## MCI-UI Mobile 必须优先使用
108
108
 
109
109
  新的 Microi UniApp/H5 Vue3 项目必须默认基于 `Microi.UI/src/uniapp` 建立页面基础组件,至少包括页面壳、导航栏、按钮、卡片、分段标签、指标卡、底部安全区操作栏、头像、商品卡、骨架屏、数据状态、富文本。用户未主动指定 UI 风格时,AI 必须自动采用 Microi吾码UI。项目可以使用 `uni-ui`、`uView`、`FirstUI` 等第三方组件,但应封装在 MCI-UI 或项目级 `mci-*` 组件后面,不要让业务页面直接散落多套视觉风格。
@@ -117,7 +117,7 @@
117
117
  5. 商品详情、公告、协议等富文本使用 `MciRichText` 或遵循同等结构。
118
118
 
119
119
  <!-- /microi-progressive:chunk -->
120
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-025 sha256=c472359f2f16b287398c0781cb66cbfb98fea99accddbfa078e9f1e9356aa30d -->
120
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-025 sha256=88463d70885f5a2e0718cbd08acfcbe0fa6f60dc4101f9016af575f9932f3783 -->
121
121
  ## 登录、图标与主题补充规范
122
122
 
123
123
  - 登录页不要同时铺开两套完整登录系统。H5/App 默认只做一个“账号/手机号 + 密码”表单;微信小程序默认展示 `<button open-type="getPhoneNumber">` 手机号授权登录,账号密码只能作为次级折叠/备用入口。
@@ -136,7 +136,7 @@
136
136
  - 列表进入详情必须保持身份路径:员工列表点报告详情走员工 token/FormEngine 权限,客户列表点报告详情走 CustomerToken,分享链接走 ShareToken;禁止员工点击可见报告后因为传空 CustomerToken 被跳回登录。
137
137
 
138
138
  <!-- /microi-progressive:chunk -->
139
- <!-- microi-progressive:chunk id=microi-uniapp-frontend-026 sha256=67c8816c77d24e6aef77f1706a72330c7a103b58c623178c056a71203e2b43d3 -->
139
+ <!-- microi-progressive:chunk id=microi-uniapp-frontend-026 sha256=12cab2ca3839d0eee4bebc69648f63b172a793ddeade2c6b0a1108fcad0adc4a -->
140
140
  ## UniApp 上传路径与 Header 规则
141
141
 
142
142
  任何移动端图片、头像、身份认证、付款凭证、富文本图片、收款码上传,都必须走项目统一的 `uploadFile` 包装,并最终委托 `microi.v8.js` 的 `V8.uploadFile`。页面里不得直接调用 `/api/HDFS/UniappUpload`,不得临时手写 `uni.uploadFile`。