# 页面路由

<cite>
**本文引用的文件**
- [pages.json](file://my-uniapp-vue3/src/pages.json)
- [main.ts](file://my-uniapp-vue3/src/main.ts)
- [App.vue](file://my-uniapp-vue3/src/App.vue)
- [manifest.json](file://my-uniapp-vue3/src/manifest.json)
- [user.ts](file://my-uniapp-vue3/src/store/user.ts)
- [request.ts](file://my-uniapp-vue3/src/utils/request.ts)
- [storage.ts](file://my-uniapp-vue3/src/utils/storage.ts)
- [index.vue（首页）](file://my-uniapp-vue3/src/pages/index/index.vue)
- [login.vue（登录页）](file://my-uniapp-vue3/src/pages/login/index.vue)
- [mine.vue（我的页）](file://my-uniapp-vue3/src/pages/mine/index.vue)
- [vite.config.ts](file://my-uniapp-vue3/vite.config.ts)
</cite>

## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)

## 简介
本文件面向“AI有声书生成平台”的前端路由体系，围绕 UniApp 的页面路由配置与运行时行为进行系统化梳理。重点覆盖以下方面：
- pages.json 的页面声明、窗口样式与 TabBar 配置
- 路由守卫机制与页面生命周期管理
- 页面间通信方式与权限控制
- 与 Vue Router 的差异及在 UniApp 中的特殊处理
- 动态路由、嵌套路由、懒加载与 SEO 优化建议
- 实战最佳实践与常见问题排查

## 项目结构
本项目采用 UniApp + Vue 3 + Vite 的技术栈，路由配置集中在 pages.json，页面通过 uni-app 的导航 API 进行跳转，全局状态通过 Pinia 管理。

```mermaid
graph TB
subgraph "应用入口"
A["App.vue<br/>应用生命周期(onLaunch/onShow/onHide)"]
B["main.ts<br/>创建应用实例/初始化用户状态"]
C["manifest.json<br/>应用元信息/平台能力"]
end
subgraph "路由与页面"
D["pages.json<br/>页面清单/窗口样式/TabBar"]
E["各页面组件<br/>如 pages/index/index.vue 等"]
end
subgraph "状态与网络"
F["store/user.ts<br/>用户状态/Pinia"]
G["utils/request.ts<br/>统一请求/鉴权/重试/缓存"]
H["utils/storage.ts<br/>跨端存储封装"]
end
subgraph "开发与构建"
I["vite.config.ts<br/>代理/插件"]
end
A --> B
B --> F
B --> G
D --> E
F --> E
G --> E
I --> D
```

图表来源
- [App.vue:1-134](file://my-uniapp-vue3/src/App.vue#L1-L134)
- [main.ts:1-32](file://my-uniapp-vue3/src/main.ts#L1-L32)
- [manifest.json:1-52](file://my-uniapp-vue3/src/manifest.json#L1-L52)
- [pages.json:1-211](file://my-uniapp-vue3/src/pages.json#L1-L211)
- [user.ts:1-107](file://my-uniapp-vue3/src/store/user.ts#L1-L107)
- [request.ts:1-207](file://my-uniapp-vue3/src/utils/request.ts#L1-L207)
- [storage.ts:1-63](file://my-uniapp-vue3/src/utils/storage.ts#L1-L63)
- [vite.config.ts:1-24](file://my-uniapp-vue3/vite.config.ts#L1-L24)

章节来源
- [pages.json:1-211](file://my-uniapp-vue3/src/pages.json#L1-L211)
- [main.ts:1-32](file://my-uniapp-vue3/src/main.ts#L1-L32)
- [App.vue:1-134](file://my-uniapp-vue3/src/App.vue#L1-L134)
- [manifest.json:1-52](file://my-uniapp-vue3/src/manifest.json#L1-L52)
- [vite.config.ts:1-24](file://my-uniapp-vue3/vite.config.ts#L1-L24)

## 核心组件
- 页面清单与窗口样式
  - pages.json 中的 pages 数组定义每个页面的 path 与 style（导航栏标题、自定义导航等）
  - globalStyle 定义全局导航栏与背景色
  - tabBar 定义底部标签页及其对应页面
- 应用生命周期与初始化
  - App.vue 在 onLaunch 中初始化用户状态并应用夜间模式
  - main.ts 创建应用实例并注入 Pinia，初始化用户状态
- 状态与权限
  - store/user.ts 管理 token、用户信息、会员状态与登录登出流程
  - utils/request.ts 在请求头中携带 Authorization，并在 401 时触发自动跳转登录
- 导航与跳转
  - 页面内通过 uni.navigateTo/switchTab/reLaunch 等 API 实现页面跳转
  - 登录页在登录成功后根据当前页面栈决定 navigateBack 或 switchTab

章节来源
- [pages.json:1-211](file://my-uniapp-vue3/src/pages.json#L1-L211)
- [App.vue:1-134](file://my-uniapp-vue3/src/App.vue#L1-L134)
- [main.ts:1-32](file://my-uniapp-vue3/src/main.ts#L1-L32)
- [user.ts:1-107](file://my-uniapp-vue3/src/store/user.ts#L1-L107)
- [request.ts:1-207](file://my-uniapp-vue3/src/utils/request.ts#L1-L207)

## 架构总览
UniApp 的路由体系由“配置驱动 + 运行时导航 API”构成。pages.json 决定页面清单与 TabBar，运行时通过 uni-app 的导航 API 控制页面栈与跳转行为；全局状态与网络层负责权限校验与数据获取。

```mermaid
sequenceDiagram
participant U as "用户"
participant P as "页面组件"
participant R as "路由导航API"
participant S as "用户状态(Pinia)"
participant N as "网络层(request)"
participant B as "后端"
U->>P : 触发跳转/进入页面
P->>R : uni.navigateTo/switchTab/reLaunch
R-->>P : 页面栈变化/页面显示
P->>S : 读取登录状态/会员状态
alt 未登录
P->>N : 调用登录接口
N-->>P : 成功后写入token/用户信息
P->>R : reLaunch/switchTab 跳转首页
else 已登录
P->>N : 拉取业务数据
N->>B : 发起带Authorization的请求
B-->>N : 返回数据/401
alt 401
N->>R : reLaunch 跳转登录页
end
end
```

图表来源
- [index.vue（首页）:231-262](file://my-uniapp-vue3/src/pages/index/index.vue#L231-L262)
- [login.vue（登录页）:101-134](file://my-uniapp-vue3/src/pages/login/index.vue#L101-L134)
- [mine.vue（我的页）:264-274](file://my-uniapp-vue3/src/pages/mine/index.vue#L264-L274)
- [request.ts:135-146](file://my-uniapp-vue3/src/utils/request.ts#L135-L146)
- [user.ts:32-46](file://my-uniapp-vue3/src/store/user.ts#L32-L46)

## 详细组件分析

### pages.json 配置详解
- 页面路径与窗口样式
  - 每个页面以 path 指向相对路径，style 中可设置 navigationBarTitleText、navigationStyle（custom 表示自定义导航栏）
  - 适用于首页、创建页、历史页、我的页、播放页、登录页、收藏页、搜索页、专辑/合辑页、书籍生成功能、视频生成功能、设置、订单、发布、歌单、草稿、webview、支付结果/确认、支付宝二维码等
- 全局样式
  - globalStyle 控制全局导航栏文字颜色、标题、背景色与页面背景色
- TabBar
  - tabBar.list 中的 pagePath 指向底部标签页对应的页面
  - 文案 text 显示在 TabBar 上

章节来源
- [pages.json:1-211](file://my-uniapp-vue3/src/pages.json#L1-L211)

### 路由守卫机制与页面生命周期
- 生命周期
  - App.vue 的 onLaunch 在应用启动时执行，用于初始化用户状态与夜间模式
  - 页面组件可通过 onShow/onHide/onLoad 等生命周期钩子感知页面显示/隐藏
- 权限守卫
  - 登录页在登录成功后根据当前页面栈决定返回上一页或跳转 Tab 页
  - 我的页 onShow 中若检测到未登录则跳转登录页
  - 网络层在收到 401 时清除 token 并跳转登录页

```mermaid
flowchart TD
Start(["页面显示"]) --> CheckLogin["检查登录状态"]
CheckLogin --> |未登录| GoLogin["跳转登录页"]
CheckLogin --> |已登录| FetchData["拉取业务数据"]
FetchData --> Resp{"请求结果"}
Resp --> |401| ClearToken["清除token并跳转登录"]
Resp --> |其他| Done(["渲染完成"])
GoLogin --> Done
ClearToken --> Done
```

图表来源
- [login.vue（登录页）:118-125](file://my-uniapp-vue3/src/pages/login/index.vue#L118-L125)
- [mine.vue（我的页）:264-274](file://my-uniapp-vue3/src/pages/mine/index.vue#L264-L274)
- [request.ts:135-146](file://my-uniapp-vue3/src/utils/request.ts#L135-L146)

章节来源
- [App.vue:10-25](file://my-uniapp-vue3/src/App.vue#L10-L25)
- [login.vue（登录页）:101-134](file://my-uniapp-vue3/src/pages/login/index.vue#L101-L134)
- [mine.vue（我的页）:264-274](file://my-uniapp-vue3/src/pages/mine/index.vue#L264-L274)
- [request.ts:135-146](file://my-uniapp-vue3/src/utils/request.ts#L135-L146)

### 页面间通信方式
- 参数传递
  - 通过 uni.navigateTo 等 API 的 url 参数携带查询字符串或路径参数
  - 示例：首页跳转播放页、专辑详情页均通过查询参数传入 id
- 全局状态共享
  - 使用 Pinia store 在页面间共享用户信息、会员状态等
- 事件与消息
  - 可通过 uni.$emit/$off/$once 或自定义事件总线在页面间传递消息（本项目未显式使用）

章节来源
- [index.vue（首页）:231-262](file://my-uniapp-vue3/src/pages/index/index.vue#L231-L262)

### uniapp 路由与 Vue Router 的区别与特殊处理
- 不同点
  - uniapp 路由由 pages.json 声明式配置驱动，运行时通过 uni-app API 控制页面栈
  - Vue Router 是前端 SPA 路由，基于浏览器 History/Hash 模式
- 特殊处理
  - 自定义导航栏：pages.json 中 navigationStyle: "custom"，页面内自行实现导航栏
  - TabBar：通过 tabBar.list 指定底部标签页，使用 uni.switchTab 切换
  - 页面栈：uni-app 有原生页面栈概念，navigateTo/redirectTo/switchTab/redirectTo/reLaunch 影响页面栈结构

章节来源
- [pages.json:5-8](file://my-uniapp-vue3/src/pages.json#L5-L8)
- [pages.json:191-208](file://my-uniapp-vue3/src/pages.json#L191-L208)

### 动态路由与嵌套路由
- 动态路由
  - 通过在 pages.json 中定义带占位符的 path，结合 uni.navigateTo 的参数传递实现动态路由
  - 示例：专辑详情页通过 id 参数区分不同专辑
- 嵌套路由
  - uniapp 不支持传统 Web 的嵌套路由，但可通过 TabBar 子页面组合实现类似效果（如“我的”下的多个子页面）

章节来源
- [index.vue（首页）:244-247](file://my-uniapp-vue3/src/pages/index/index.vue#L244-L247)

### 懒加载策略
- 页面级懒加载
  - 通过按需引入页面组件或拆分页面，减少首屏加载体积
- 资源懒加载
  - 图片懒加载、骨架屏占位、滚动触底加载更多
- 网络懒加载
  - 首屏仅请求必要数据，后续滚动或交互再请求更多数据

章节来源
- [index.vue（首页）:9-31](file://my-uniapp-vue3/src/pages/index/index.vue#L9-L31)
- [index.vue（首页）:184-207](file://my-uniapp-vue3/src/pages/index/index.vue#L184-L207)

### SEO 优化方案
- 页面标题与描述
  - 在 pages.json 的 style.navigationBarTitleText 设置页面标题
  - 全局标题可在 globalStyle.navigationBarTitleText 设置
- 结构化数据
  - 对于公开内容页面，可在页面内输出结构化数据（如 JSON-LD），提升搜索引擎识别度
- 静态资源优化
  - 使用 CDN、压缩与缓存策略，提升页面加载速度

章节来源
- [pages.json:5-7](file://my-uniapp-vue3/src/pages.json#L5-L7)
- [pages.json:180-184](file://my-uniapp-vue3/src/pages.json#L180-L184)

## 依赖关系分析
- 配置依赖
  - pages.json 决定页面清单与 TabBar，直接影响导航与页面栈
- 运行时依赖
  - App.vue 与 main.ts 负责应用初始化与用户状态注入
  - store/user.ts 与 utils/request.ts 共同实现权限校验与自动跳转
- 构建与代理
  - vite.config.ts 提供 /api、/uploads、/videos 代理，便于开发联调

```mermaid
graph LR
P["pages.json"] --> T["TabBar/页面清单"]
M["main.ts"] --> U["App.vue"]
U --> S["store/user.ts"]
S --> R["utils/request.ts"]
R --> B["后端API"]
V["vite.config.ts"] --> R
```

图表来源
- [pages.json:1-211](file://my-uniapp-vue3/src/pages.json#L1-L211)
- [main.ts:1-32](file://my-uniapp-vue3/src/main.ts#L1-L32)
- [App.vue:1-134](file://my-uniapp-vue3/src/App.vue#L1-L134)
- [user.ts:1-107](file://my-uniapp-vue3/src/store/user.ts#L1-L107)
- [request.ts:1-207](file://my-uniapp-vue3/src/utils/request.ts#L1-L207)
- [vite.config.ts:1-24](file://my-uniapp-vue3/vite.config.ts#L1-L24)

章节来源
- [pages.json:1-211](file://my-uniapp-vue3/src/pages.json#L1-L211)
- [main.ts:1-32](file://my-uniapp-vue3/src/main.ts#L1-L32)
- [App.vue:1-134](file://my-uniapp-vue3/src/App.vue#L1-L134)
- [user.ts:1-107](file://my-uniapp-vue3/src/store/user.ts#L1-L107)
- [request.ts:1-207](file://my-uniapp-vue3/src/utils/request.ts#L1-L207)
- [vite.config.ts:1-24](file://my-uniapp-vue3/vite.config.ts#L1-L24)

## 性能考量
- 页面栈管理
  - 合理使用 uni.switchTab 与 uni.navigateTo，避免过深页面栈导致内存压力
- 数据缓存
  - request.ts 提供请求缓存（GET + TTL），减少重复请求
- 骨架屏与懒加载
  - 首屏使用骨架屏，滚动触底加载更多，降低白屏时间
- 构建优化
  - vite.config.ts 配置代理，减少跨域与联调成本；生产环境启用压缩与缓存

章节来源
- [request.ts:20-55](file://my-uniapp-vue3/src/utils/request.ts#L20-L55)
- [index.vue（首页）:9-31](file://my-uniapp-vue3/src/pages/index/index.vue#L9-L31)
- [vite.config.ts:7-22](file://my-uniapp-vue3/vite.config.ts#L7-L22)

## 故障排查指南
- 登录态异常
  - 现象：访问受保护接口返回 401
  - 排查：检查 token 是否存在、是否过期；确认 request.ts 是否正确注入 Authorization；确认网络层是否触发 reLaunch
- 页面跳转异常
  - 现象：跳转后页面栈混乱
  - 排查：确认使用 uni.switchTab/uni.navigateTo/uni.reLaunch 的场景是否正确；避免在 Tab 页中使用非 Tab 跳转
- 夜间模式不生效
  - 现象：切换夜间模式后页面颜色未更新
  - 排查：确认 App.vue 是否正确应用夜间模式类名；确认页面样式是否包含夜间模式分支
- 开发联调失败
  - 现象：/api /uploads /videos 请求失败
  - 排查：确认 vite.config.ts 代理配置是否正确；确认后端服务是否启动

章节来源
- [request.ts:135-146](file://my-uniapp-vue3/src/utils/request.ts#L135-L146)
- [App.vue:28-37](file://my-uniapp-vue3/src/App.vue#L28-L37)
- [vite.config.ts:7-22](file://my-uniapp-vue3/vite.config.ts#L7-L22)

## 结论
本项目的路由体系以 pages.json 为配置核心，结合 uni-app 导航 API 与 Pinia 状态管理，实现了清晰的页面组织、完善的权限控制与良好的用户体验。通过合理的生命周期管理、请求缓存与懒加载策略，能够在多端环境中保持稳定的性能表现。未来可在动态路由参数校验、SEO 结构化数据与更细粒度的页面懒加载方面进一步优化。

## 附录
- 最佳实践清单
  - 使用 pages.json 统一声明页面与 TabBar
  - 在 App.vue 与 main.ts 中集中初始化用户状态
  - 在 store/user.ts 中集中处理登录/登出/会员状态
  - 在 utils/request.ts 中统一处理鉴权、重试与缓存
  - 使用骨架屏与懒加载优化首屏体验
  - 使用 vite.config.ts 的代理提升开发联调效率