集成 MJRefresh 并重构主 TabBar 为系统 TabView 样式。
新增 SwiftUI 桥接层与单元测试,更新 Tab 图标资源命名和多倍图,同步调整 UI Test 的 Tab/扫码定位逻辑。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@ -5,11 +5,12 @@
|
||||
Main 模块负责登录后的主界面 Tab 容器,以及当前尚未迁移页面的占位入口。
|
||||
|
||||
主界面由 `MainTabsView` 承载:
|
||||
- 根据 `MainTabBarConfiguration.activeStyle` 选择自定义 TabBar 或系统 `TabView`。
|
||||
- 默认使用自定义 TabBar;如需切回系统实现,将配置改为 `.system`。
|
||||
- 自定义和系统两套外壳都展示首页、订单、数据、我的四个 Tab。
|
||||
- 使用系统 `TabView` 展示登录后的底部导航。
|
||||
- 底部按顺序展示首页、订单、扫码、数据、我的五个入口。
|
||||
- 扫码入口只负责打开扫码页,不属于 `AppTab`,也不持有独立业务导航栈。
|
||||
- 每个 Tab 内部都包裹独立的 `NavigationStack`,并通过 `TabNavigationStackHost` 复用同一套导航构建逻辑。
|
||||
- 每个 Tab 的导航路径由 `AppRouter` 单独保存。
|
||||
- 订单 Tab 角标由 `MainTabBadgeViewModel` 提供,数量为 0 或获取失败时不显示。
|
||||
|
||||
## Tab 结构
|
||||
|
||||
@ -24,27 +25,21 @@ Main 模块负责登录后的主界面 Tab 容器,以及当前尚未迁移页
|
||||
## 导航流程
|
||||
|
||||
1. `MainTabsView` 从 Environment 读取 `AppRouter`。
|
||||
2. `MainTabsView` 根据 `MainTabBarConfiguration.activeStyle` 选择 `CustomMainTabsView` 或 `SystemMainTabsView`。
|
||||
3. 两套外壳都使用 `appRouter.selectedTab` 作为选中状态。
|
||||
4. 每个 Tab 通过 `TabNavigationStackHost` 创建自己的 `NavigationStack(path:)`。
|
||||
2. `TabView` 使用内部 `MainTabSelection` 作为选择值,普通 Tab 映射到 `AppTab`,扫码映射到 `.scanner`。
|
||||
3. 普通 Tab 切换时调用 `AppRouter.select(_:)` 更新当前业务 Tab。
|
||||
4. 每个普通 Tab 通过 `TabNavigationStackHost` 创建自己的 `NavigationStack(path:)`。
|
||||
5. 路径绑定来自 `appRouter.binding(for:)`。
|
||||
6. Tab 内页面需要进入尚未迁移的子页面时,通过当前 Tab 注入的 `RouterPath` push 一个 `AppRoute.placeholder`。
|
||||
7. `navigationDestination` 根据 `AppRoute` 展示详情页。
|
||||
8. 子页面展示时读取 `AppRoute.hidesTabBarWhenPushed`,默认隐藏底部 TabBar。
|
||||
|
||||
## 自定义 TabBar
|
||||
## 扫码入口
|
||||
|
||||
自定义 TabBar 由 `CustomMainTabsView` 和 `CustomMainTabBar` 组成:
|
||||
- `CustomMainTabsView` 负责保留已访问 Tab 页面、刷新订单角标、展示扫码页。
|
||||
- `CustomTabNavigationStackHost` 会把 `CustomMainTabBar` 拼在每个 Tab 的根页面内容下方。
|
||||
- `CustomMainTabBar` 只负责展示 UI,不直接读取账号、订单 API 或业务上下文。
|
||||
- `MainTabBadgeViewModel` 通过 `OrdersAPI.writeOffList` 获取待核销数量,失败时静默清空角标。
|
||||
- 中间扫码按钮使用订单模块已有的 `OrderScannerPage`。
|
||||
- 扫码成功后调用 `AppRouter.routeToOrderVerification(scannedCode:)`,订单页再通过 `consumePendingOrderScanCode()` 一次性消费结果。
|
||||
- 自定义 TabBar 只属于 Tab 根页面内容;当前 Tab 的导航栈 push 到二级页面后,目标页面不包含 TabBar,也不会保留底部占位高度。
|
||||
- 承载根页面和 `CustomMainTabBar` 的容器需要忽略键盘底部安全区,避免订单搜索框等输入控件唤起键盘时把自定义 TabBar 顶起。
|
||||
扫码入口是系统 `TabView` 中的中间入口,只显示 `qrcode.viewfinder` 图标,并通过无障碍标签标记为“扫码核销”。
|
||||
|
||||
系统 `TabView` 外壳由 `SystemMainTabsView` 保留。系统模式不显示中间扫码按钮,但订单页内部的扫码核销入口仍然可用。
|
||||
点击扫码入口时,`MainTabsView` 拦截 `.scanner` 选择并展示订单模块已有的 `OrderScannerPage`,不会修改 `AppRouter.selectedTab`。因此用户关闭扫码页后,仍停留在打开扫码前的 Tab。
|
||||
|
||||
扫码成功后调用 `AppRouter.routeToOrderVerification(scannedCode:)`,订单页再通过 `consumePendingOrderScanCode()` 一次性消费结果。扫码失败时关闭扫码页并展示错误提示。
|
||||
|
||||
## 后续迁移规则
|
||||
|
||||
@ -55,5 +50,5 @@ Main 模块负责登录后的主界面 Tab 容器,以及当前尚未迁移页
|
||||
- 需要从首页或全局入口进入订单核销时,优先使用 `AppRouter.selectOrders(entry:)` 或 `AppRouter.routeToOrderVerification(scannedCode:)`。
|
||||
- Tab 内跳转通过当前 Tab 的 `RouterPath.navigate` 或扩展后的 `AppRoute` 处理。
|
||||
- 普通业务子页面默认隐藏 TabBar;只有确有产品需求时,才在 `AppRoute` 策略中单独放开。
|
||||
- 不要把业务状态塞进自定义 TabBar 组件;TabBar 只接收绑定、文案和动作回调。
|
||||
- 不要把扫码入口加入 `AppTab`;它不是业务 Tab,只是主界面的全局动作入口。
|
||||
- 真实业务页面接入后,应同步补充该模块文档和单元测试。
|
||||
|
||||
Reference in New Issue
Block a user