# Main 模块业务逻辑

## 模块职责

Main 模块负责登录后的主界面 Tab 容器，以及当前尚未迁移页面的占位入口。

主界面由 `MainTabsView` 承载：
- 根据 `MainTabBarConfiguration.activeStyle` 选择自定义 TabBar 或系统 `TabView`。
- 默认使用自定义 TabBar；如需切回系统实现，将配置改为 `.system`。
- 自定义和系统两套外壳都展示首页、订单、数据、我的四个 Tab。
- 每个 Tab 内部都包裹独立的 `NavigationStack`，并通过 `TabNavigationStackHost` 复用同一套导航构建逻辑。
- 每个 Tab 的导航路径由 `AppRouter` 单独保存。

## Tab 结构

当前 Tab 来自 `AppTab`：
- `home`：首页
- `orders`：订单
- `statistics`：数据
- `profile`：我的

`HomeRootView` 已接入真实的 `HomeView`，`OrdersRootView` 已接入真实的 `OrdersView`，`StatisticsRootView` 已接入真实的 `StatisticsView`，`ProfileRootView` 已接入真实的 `ProfileView`。

## 导航流程

1. `MainTabsView` 从 Environment 读取 `AppRouter`。
2. `MainTabsView` 根据 `MainTabBarConfiguration.activeStyle` 选择 `CustomMainTabsView` 或 `SystemMainTabsView`。
3. 两套外壳都使用 `appRouter.selectedTab` 作为选中状态。
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` 外壳由 `SystemMainTabsView` 保留。系统模式不显示中间扫码按钮，但订单页内部的扫码核销入口仍然可用。

## 后续迁移规则

迁移新页面时：
- 优先替换对应 Tab 的 RootView。
- 保持每个 Tab 自己的 `NavigationStack`。
- 跨 Tab 跳转通过 `AppRouter.select` 切换 Tab。
- 需要从首页或全局入口进入订单核销时，优先使用 `AppRouter.selectOrders(entry:)` 或 `AppRouter.routeToOrderVerification(scannedCode:)`。
- Tab 内跳转通过当前 Tab 的 `RouterPath.navigate` 或扩展后的 `AppRoute` 处理。
- 普通业务子页面默认隐藏 TabBar；只有确有产品需求时，才在 `AppRoute` 策略中单独放开。
- 不要把业务状态塞进自定义 TabBar 组件；TabBar 只接收绑定、文案和动作回调。
- 真实业务页面接入后，应同步补充该模块文档和单元测试。
