chore: flatten web project structure

This commit is contained in:
duanshuwen
2026-05-26 12:14:31 +08:00
parent 30b9100b4a
commit aff380dad9
569 changed files with 1081 additions and 74985 deletions

View File

@@ -1,194 +0,0 @@
# 业务功能迁移验收清单
## 文档状态
- 状态:阶段 0 盘点产物
- 日期2026-05-25
- 目标:按业务闭环跟踪 Vue3 Web 迁移进度
## 状态说明
| 状态 | 含义 |
| --- | --- |
| Not Started | 未开始 |
| Inventory | 已完成盘点,等待迁移 |
| In Progress | 正在迁移 |
| Web Ready | Web 版本可验收 |
| Deferred | 延后迁移 |
| Dropped | 明确废弃 |
## 模块总览
| 优先级 | 模块 | 当前源码 | Web 目标目录 | 状态 | 主要风险 |
| --- | --- | --- | --- | --- | --- |
| P0 | 应用基座 | `src/main.js``src/App.vue``vite.config.js` | `web/src/app` | Not Started | 启动、环境、网络恢复逻辑 |
| P0 | 平台适配层 | `uni.*` 分散调用 | `web/src/services` | Not Started | 替换不完整会造成隐性缺陷 |
| P0 | 配置和 Store | `src/constant``src/store` | `web/src/constants``web/src/stores` | Not Started | 持久化和客户端配置 |
| P0 | 请求和登录 | `src/request``src/manager``src/hooks` | `web/src/services/http``web/src/features/auth` | Not Started | token、424、微信授权 |
| P0 | AI 聊天 | `src/pages/ChatMain``src/pages/ChatModule``src/utils/WebSocketManager.js` | `web/src/features/chat` | Not Started | WebSocket、流式响应、滚动键盘 |
| P1 | 首页和发现 | `src/pages/index``src/pages/Discovery` | `web/src/features/chat``web/src/features/discovery` | Not Started | 首页发现与聊天联动 |
| P1 | 商品详情 | `src/pages/goods``src/components/GoodDetail` | `web/src/features/goods` | Not Started | 图片、日期、地图 |
| P1 | 预订 | `src/pages-booking` | `web/src/features/booking` | Not Started | 表单、金额、支付参数 |
| P1 | 订单 | `src/pages-order` | `web/src/features/order` | Not Started | 支付、退款、二维码 |
| P2 | 工单服务 | `src/pages-service``src/components/CreateServiceOrder` | `web/src/features/service` | Not Started | 图片上传、电话、反馈 |
| P2 | 快捷入口 | `src/pages-quick` | `web/src/features/quick` | Not Started | 与聊天指令联动 |
| P2 | WebView 桥接 | `src/pages/webview``src/pages-bridge` | `web/src/features/bridge` | Not Started | iframe、postMessage、外部页面兼容 |
| P2 | 通用组件 | `src/components` | `web/src/components` | Not Started | uni 标签、弹窗、滚动、canvas |
| P3 | 测试页和 demo | `src/pages/test`、各组件 demo | `web/src/features/dev` | Deferred | 非核心路径 |
## 阶段 0盘点和基线冻结
- [x] 输出总体迁移计划:`docs/MIGRATION_PLAN.md`
- [x] 输出路由映射:`docs/ROUTE_MIGRATION_MAP.md`
- [x] 输出 uni API 替换矩阵:`docs/UNI_API_REPLACEMENT_MATRIX.md`
- [x] 输出业务功能迁移验收清单:`docs/FEATURE_MIGRATION_CHECKLIST.md`
- [ ] 录制或截图旧版本核心流程,作为视觉和行为基线。
- [ ] 明确目标 Web 运行环境:普通 H5、微信公众号、企业微信、内嵌 WebView 或多环境。
- [ ] 明确登录和支付在 Web 端的目标方案。
## 阶段 1Vue3 Web 工程骨架
验收项:
- [x] 新建 `web/` 工程。
- [x] 配置 Vue3、TypeScript、Vite、Pinia、Vue Router、Tailwind CSS。
- [x] 配置 `@/` 路径别名。
- [x] 新增移动端基础布局和 CSS reset。
- [x] 新增健康页、404 页和最小路由。
- [x] 新工程不依赖 `@dcloudio/*`
- [x] `web` 工程可以启动和构建。
## 阶段 2平台适配层
验收项:
- [ ] `services/router` 支持 `push``replace``back``reLaunch`
- [ ] `services/storage` 支持 token 和普通持久化。
- [ ] `services/event-bus` 支持 typed `emit/on/off`
- [ ] `services/feedback` 支持 toast、modal、loading。
- [ ] `services/http` 支持 baseUrl、clientId、token、位置请求头、424 登出。
- [ ] `services/browser` 支持图片选择、下载、定位、电话、分享的基础封装或降级。
- [ ] 新 Web 业务代码不直接调用 `uni.*``wx.*`
## 阶段 3配置、Store 和 API
验收项:
- [ ] 客户端配置迁移,能读取当前 `zhinian` 配置。
- [ ] 服务地址配置迁移,支持测试/生产切换。
- [ ] token key 和 refresh token 逻辑迁移。
- [ ] `app` store 迁移。
- [ ] `location` store 迁移。
- [ ] `picture` store 迁移。
- [ ] `selectedDate` store 迁移。
- [ ] 登录 API 迁移并补基础类型。
- [ ] 首页、会话、商品、订单、工单、反馈 API 迁移。
## 阶段 4AI 聊天主链路
验收项:
- [ ] 首页聊天页面可打开。
- [ ] 聊天消息模型 TypeScript 化。
- [ ] WebSocket 连接、心跳、重连、队列发送可用。
- [ ] 流式响应 parser 可解析服务端数据。
- [ ] 文本消息发送可用。
- [ ] AI 流式回复可展示。
- [ ] `toolCall.componentName` 能分发到对应卡片。
- [ ] 至少支持快捷预订卡、发现卡、反馈卡、商品图文卡中的一类。
- [ ] 长文本卡详情页可打开。
- [ ] 停止生成可用。
- [ ] 超时、失败、断线有反馈。
- [ ] 移动端滚动到底和输入区键盘适配通过手工验收。
## 阶段 5首页和发现
验收项:
- [ ] 首页顶部导航迁移。
- [ ] 欢迎区和背景图迁移。
- [ ] 发现页内容流可加载。
- [ ] 快捷问题可触发聊天发送。
- [ ] 发现页定位能力有授权失败降级。
- [ ] 轮播和 tabs 在移动端可用。
- [ ] 首页和聊天 tab 切换状态稳定。
## 阶段 6商品、预订和订单
验收项:
- [ ] 商品详情可通过 `/goods/:commodityId` 打开。
- [ ] 商品图片相册可预览。
- [ ] 酒店商品日期选择可用。
- [ ] 套餐、设施、位置展示可用。
- [ ] 预订确认页表单可填写。
- [ ] 金额计算和预订参数正确。
- [ ] 下单接口调用可用。
- [ ] 支付方案可用或有明确降级。
- [ ] 订单列表可加载。
- [ ] 订单详情可打开。
- [ ] 退款/取消/状态刷新可用。
- [ ] 二维码或券码展示可用。
## 阶段 7工单、反馈、快捷入口和桥接
验收项:
- [ ] 工单列表可加载。
- [ ] 工单卡片信息完整。
- [ ] 服务呼叫表单可提交。
- [ ] 图片选择和上传可用。
- [ ] 反馈表单可提交。
- [ ] 快捷入口列表可打开。
- [ ] 快捷入口可触发聊天指令或跳转。
- [ ] WebView 改为 iframe 或外链跳转。
- [ ] 外部页面能通过 `postMessage` 与主应用通信。
- [ ] 保存图片/下载能力有浏览器兼容提示。
## 阶段 8Tailwind 和 UI 收敛
验收项:
- [ ] 主题色迁移到 Tailwind config 和 CSS variables。
- [ ] 基础间距、字体、颜色工具类映射完成。
- [ ] 新 Web 页面主要使用 Tailwind。
- [ ] 不再新增旧 SCSS 工具类依赖。
- [ ] 底部输入区、安全区、弹窗、抽屉形成统一实现。
- [ ] 移动端常见 viewport 无明显遮挡和溢出。
## 阶段 9测试、灰度和旧栈下线
验收项:
- [ ] 请求层单元测试。
- [ ] 事件总线单元测试。
- [ ] 流式 parser 单元测试。
- [ ] WebSocket 管理器单元测试或集成测试。
- [ ] 聊天核心流程 E2E。
- [ ] 商品预订订单流程 E2E。
- [ ] 登录失效和 424 登出 E2E。
- [ ] 新旧版本核心路径对照验收。
- [ ] 旧 uni-app 代码零活跃依赖后再删除。
## Web 端待确认问题
这些问题在阶段 1 之前需要产品或后端确认:
- [ ] 新 Web 应用运行在哪些容器普通浏览器、微信公众号、企业微信、App WebView、PC 浏览器?
- [ ] 微信登录是否继续使用 openId/code 换 token还是改为手机号/验证码/静默登录?
- [ ] 支付使用 JS-SDK、H5 支付、中间页跳转,还是仅保留下单不支付?
- [ ] 外部 H5 页面是否必须兼容旧 `url + token query` 桥接方式?
- [ ] 地图打开使用哪个地图服务:腾讯地图、高德地图、浏览器地图 URL
- [ ] 保存图片在 Web 端是否接受“下载文件/长按保存”降级?
## 每个业务切片的完成定义
一个模块只有同时满足以下条件,才能标记为 `Web Ready`
- [ ] 对应 Vue Router 路由已接入。
- [ ] 依赖 API 已通过新请求层调用。
- [ ] 页面不直接依赖 `uni.*``wx.*`
- [ ] 关键状态进入 Pinia 或局部 composable职责清晰。
- [ ] 移动端布局通过手工验收。
- [ ] 错误、空数据、加载态、登录失效有处理。
- [ ] 有构建、单元测试或手工验收记录。

View File

@@ -44,24 +44,24 @@
### 高风险 uni 能力
| 当前能力 | 使用场景 | Web 改造方向 | 风险 |
| --- | --- | --- | --- |
| `uni.navigateTo/reLaunch/navigateBack` | 页面跳转 | Vue Router 服务封装 | 中 |
| `uni.request/uploadFile` | HTTP 请求、文件上传 | `fetch` 或 Axios + 上传封装 | 中 |
| `uni.$emit/$on/$off` | 跨组件事件 | `mitt` 或 typed event bus | 中 |
| `uni.showToast/showModal/showLoading` | 用户反馈 | UI 组件库或自研反馈服务 | 低 |
| `uni.connectSocket` | AI 聊天实时通信 | 浏览器原生 `WebSocket` | 高 |
| `uni.request enableChunked` | AI 流式回复 | `fetch + ReadableStream` 或 SSE | 高 |
| `uni.login` | 微信登录 | 微信 Web 授权或后端 H5 登录方案 | 高 |
| `uni.requestPayment` | 支付 | 微信 JS-SDK/H5 支付/后端支付跳转 | 高 |
| `uni.chooseImage` | 图片选择上传 | `<input type="file">` + 上传服务 | 中 |
| `uni.saveImageToPhotosAlbum` | 保存图片 | 浏览器下载能力,移动端受限 | 中 |
| `uni.getLocation/openLocation` | 定位和地图 | Geolocation API + 地图 URL/SDK | 中 |
| `uni.createSelectorQuery` | 尺寸测量 | DOM API、ResizeObserver | 中 |
| `uni.onKeyboardHeightChange` | 输入框键盘适配 | 视口监听、CSS env、安全区适配 | 高 |
| `<view>/<text>/<image>/<scroll-view>` | 页面模板 | HTML 标签或基础组件替换 | 中 |
| `<web-view>` | 内嵌页面 | `iframe` + `postMessage` 协议 | 中 |
| `<canvas>` + uni canvas API | 二维码/图片 | 浏览器 Canvas 或第三方库 | 中 |
| 当前能力 | 使用场景 | Web 改造方向 | 风险 |
| -------------------------------------- | ------------------- | -------------------------------- | ---- |
| `uni.navigateTo/reLaunch/navigateBack` | 页面跳转 | Vue Router 服务封装 | 中 |
| `uni.request/uploadFile` | HTTP 请求、文件上传 | `fetch` 或 Axios + 上传封装 | 中 |
| `uni.$emit/$on/$off` | 跨组件事件 | `mitt` 或 typed event bus | 中 |
| `uni.showToast/showModal/showLoading` | 用户反馈 | UI 组件库或自研反馈服务 | 低 |
| `uni.connectSocket` | AI 聊天实时通信 | 浏览器原生 `WebSocket` | 高 |
| `uni.request enableChunked` | AI 流式回复 | `fetch + ReadableStream` 或 SSE | 高 |
| `uni.login` | 微信登录 | 微信 Web 授权或后端 H5 登录方案 | 高 |
| `uni.requestPayment` | 支付 | 微信 JS-SDK/H5 支付/后端支付跳转 | 高 |
| `uni.chooseImage` | 图片选择上传 | `<input type="file">` + 上传服务 | 中 |
| `uni.saveImageToPhotosAlbum` | 保存图片 | 浏览器下载能力,移动端受限 | 中 |
| `uni.getLocation/openLocation` | 定位和地图 | Geolocation API + 地图 URL/SDK | 中 |
| `uni.createSelectorQuery` | 尺寸测量 | DOM API、ResizeObserver | 中 |
| `uni.onKeyboardHeightChange` | 输入框键盘适配 | 视口监听、CSS env、安全区适配 | 高 |
| `<view>/<text>/<image>/<scroll-view>` | 页面模板 | HTML 标签或基础组件替换 | 中 |
| `<web-view>` | 内嵌页面 | `iframe` + `postMessage` 协议 | 中 |
| `<canvas>` + uni canvas API | 二维码/图片 | 浏览器 Canvas 或第三方库 | 中 |
## 目标架构
@@ -104,20 +104,20 @@ web/
### 基础技术选型
| 能力 | 建议方案 |
| --- | --- |
| 框架 | Vue 3 + Composition API |
| 类型 | TypeScript严格模式分阶段开启 |
| 状态管理 | Pinia |
| 能力 | 建议方案 |
| ---------- | --------------------------------------------------- |
| 框架 | Vue 3 + Composition API |
| 类型 | TypeScript严格模式分阶段开启 |
| 状态管理 | Pinia |
| 状态持久化 | `pinia-plugin-persistedstate` 或自研 storage plugin |
| 路由 | Vue Router |
| 样式 | Tailwind CSS + 少量全局 CSS 变量 |
| 请求 | Axios 或标准 `fetch` 封装,二选一后统一使用 |
| 事件总线 | `mitt`,建议加类型约束 |
| WebSocket | 浏览器原生 `WebSocket` |
| 流式响应 | `fetch + ReadableStream`,必要时兼容 SSE |
| 构建 | Vite |
| 测试 | Vitest + Vue Test Utils关键流程补 Playwright |
| 路由 | Vue Router |
| 样式 | Tailwind CSS + 少量全局 CSS 变量 |
| 请求 | Axios 或标准 `fetch` 封装,二选一后统一使用 |
| 事件总线 | `mitt`,建议加类型约束 |
| WebSocket | 浏览器原生 `WebSocket` |
| 流式响应 | `fetch + ReadableStream`,必要时兼容 SSE |
| 构建 | Vite |
| 测试 | Vitest + Vue Test Utils关键流程补 Playwright |
## 分阶段改造计划
@@ -188,8 +188,6 @@ web/
- 迁移 `client-configs.json` 和当前客户端配置读取逻辑。
- 迁移 Pinia store`app``location``picture``selectedDate`
- 替换 `pinia-plugin-unistorage` 为 Web 持久化方案。
- 迁移 `src/request/api/`,统一改用新 `http` 服务。
- 为主要 API 响应定义基础类型,优先覆盖登录、首页、会话、商品、订单。
验收标准:
@@ -319,38 +317,38 @@ web/
## 建议迁移优先级
| 优先级 | 模块 | 原因 |
| --- | --- | --- |
| P0 | 平台适配层、配置、请求、token | 所有业务依赖,必须先稳定 |
| P0 | AI 聊天主链路 | 产品核心价值,风险最高 |
| P1 | 首页、发现、快捷问题 | 用户入口和聊天联动 |
| P1 | 商品详情、预订、订单 | 核心商业闭环 |
| P2 | 工单、反馈、快捷入口 | 重要但可后续分批迁移 |
| P2 | WebView 桥接、图片保存 | 依赖外部页面和浏览器兼容 |
| P3 | 非核心 demo、README 示例、废弃组件 | 最后清理 |
| 优先级 | 模块 | 原因 |
| ------ | ---------------------------------- | ------------------------ |
| P0 | 平台适配层、配置、请求、token | 所有业务依赖,必须先稳定 |
| P0 | AI 聊天主链路 | 产品核心价值,风险最高 |
| P1 | 首页、发现、快捷问题 | 用户入口和聊天联动 |
| P1 | 商品详情、预订、订单 | 核心商业闭环 |
| P2 | 工单、反馈、快捷入口 | 重要但可后续分批迁移 |
| P2 | WebView 桥接、图片保存 | 依赖外部页面和浏览器兼容 |
| P3 | 非核心 demo、README 示例、废弃组件 | 最后清理 |
## 路由迁移初稿
| uni-app 路由 | Vue Router 建议路由 | 说明 |
| --- | --- | --- |
| `/pages/index/index` | `/` | 首页和聊天主入口 |
| `/pages/login/index` | `/login` | 登录页 |
| `/pages/goods/index` | `/goods/:commodityId?` | 商品/房型详情 |
| `/pages/goods/album/index` | `/goods/album` | 商品相册 |
| `/pages/webview/index` | `/bridge/webview` | iframe 或外链桥接 |
| `/pages/ChatMain/ChatLongAnswer/index` | `/chat/long-answer` | 长回答页 |
| `/pages/ChatModule/LongTextGuideCardPreview/guide` | `/chat/guide/guide` | 长文本 guide 详情 |
| `/pages/ChatModule/LongTextGuideCardPreview/poi` | `/chat/guide/poi` | 长文本 poi 详情 |
| `/pages/ChatModule/LongTextGuideCardPreview/route` | `/chat/guide/route` | 长文本 route 详情 |
| `/pages/ChatModule/LongTextGuideCardPreview/photo` | `/chat/guide/photo` | 长文本 photo 详情 |
| `/pages/ChatMain/NoticeMessage/detail` | `/notice/:id?` | 通知详情 |
| `/pages-order/order/list` | `/orders` | 订单列表 |
| `/pages-order/order/detail` | `/orders/:orderId` | 订单详情 |
| `/pages-service/order/list` | `/service-orders` | 工单列表 |
| `/pages-quick/list` | `/quick` | 快捷入口 |
| `/pages-booking/index` | `/booking` | 预订确认 |
| `/pages-bridge/UploadImage` | `/bridge/upload-image` | 图片上传桥接,可被新协议替代 |
| `/pages-bridge/SaveImage` | `/bridge/save-image` | 保存图片桥接,可被下载能力替代 |
| uni-app 路由 | Vue Router 建议路由 | 说明 |
| -------------------------------------------------- | ---------------------- | ------------------------------ |
| `/pages/index/index` | `/` | 首页和聊天主入口 |
| `/pages/login/index` | `/login` | 登录页 |
| `/pages/goods/index` | `/goods/:commodityId?` | 商品/房型详情 |
| `/pages/goods/album/index` | `/goods/album` | 商品相册 |
| `/pages/webview/index` | `/bridge/webview` | iframe 或外链桥接 |
| `/pages/ChatMain/ChatLongAnswer/index` | `/chat/long-answer` | 长回答页 |
| `/pages/ChatModule/LongTextGuideCardPreview/guide` | `/chat/guide/guide` | 长文本 guide 详情 |
| `/pages/ChatModule/LongTextGuideCardPreview/poi` | `/chat/guide/poi` | 长文本 poi 详情 |
| `/pages/ChatModule/LongTextGuideCardPreview/route` | `/chat/guide/route` | 长文本 route 详情 |
| `/pages/ChatModule/LongTextGuideCardPreview/photo` | `/chat/guide/photo` | 长文本 photo 详情 |
| `/pages/ChatMain/NoticeMessage/detail` | `/notice/:id?` | 通知详情 |
| `/pages-order/order/list` | `/orders` | 订单列表 |
| `/pages-order/order/detail` | `/orders/:orderId` | 订单详情 |
| `/pages-service/order/list` | `/service-orders` | 工单列表 |
| `/pages-quick/list` | `/quick` | 快捷入口 |
| `/pages-booking/index` | `/booking` | 预订确认 |
| `/pages-bridge/UploadImage` | `/bridge/upload-image` | 图片上传桥接,可被新协议替代 |
| `/pages-bridge/SaveImage` | `/bridge/save-image` | 保存图片桥接,可被下载能力替代 |
## 关键验收清单
@@ -396,16 +394,16 @@ web/
## 风险和缓解措施
| 风险 | 影响 | 缓解措施 |
| --- | --- | --- |
| 一次性替换导致功能缺失 | 高 | 新旧并行,按业务闭环迁移 |
| 聊天流式协议在 Web 不兼容 | 高 | 优先做流式原型,确认后端支持 `ReadableStream` 或 SSE |
| 微信登录/支付无法等价迁移 | 高 | 提前确认目标是 H5、公众号、企业微信还是普通浏览器 |
| 键盘和滚动体验退化 | 高 | 聊天页单独验收移动端视口和输入行为 |
| Tailwind 全量替换成本过高 | 中 | 页面迁移时渐进替换,不做纯样式大爆炸 |
| 旧 SCSS 工具类和 Tailwind 混用混乱 | 中 | 建立映射规则和废弃清单 |
| JS 改 TS 产生大量类型债 | 中 | 按模块补类型,优先 API、store、消息模型 |
| 外部 H5 桥接协议变化影响存量页面 | 中 | 保留兼容层,先支持旧 query/token 方式 |
| 风险 | 影响 | 缓解措施 |
| ---------------------------------- | ---- | ---------------------------------------------------- |
| 一次性替换导致功能缺失 | 高 | 新旧并行,按业务闭环迁移 |
| 聊天流式协议在 Web 不兼容 | 高 | 优先做流式原型,确认后端支持 `ReadableStream` 或 SSE |
| 微信登录/支付无法等价迁移 | 高 | 提前确认目标是 H5、公众号、企业微信还是普通浏览器 |
| 键盘和滚动体验退化 | 高 | 聊天页单独验收移动端视口和输入行为 |
| Tailwind 全量替换成本过高 | 中 | 页面迁移时渐进替换,不做纯样式大爆炸 |
| 旧 SCSS 工具类和 Tailwind 混用混乱 | 中 | 建立映射规则和废弃清单 |
| JS 改 TS 产生大量类型债 | 中 | 按模块补类型,优先 API、store、消息模型 |
| 外部 H5 桥接协议变化影响存量页面 | 中 | 保留兼容层,先支持旧 query/token 方式 |
## 不建议的做法

View File

@@ -1,105 +0,0 @@
# YGChatCS 路由迁移映射
## 文档状态
- 状态:阶段 0 盘点产物
- 日期2026-05-25
- 来源:`src/pages.json`
- 目标:将 uni-app 页面和分包路由迁移为 Vue Router 路由
## 迁移原则
1. 保留业务语义,不照搬 uni-app 目录结构到 URL。
2. 旧路由参数通过 Vue Router `params``query` 明确承接。
3. 分包概念在 Web 端取消,改由路由懒加载和业务模块拆包承担。
4. `navigationStyle: "custom"` 对应 Web 端页面自定义顶部栏,不再依赖小程序导航配置。
5. 旧项目路由在迁移期作为兼容入口保留映射表,便于 WebView、外链和历史跳转逐步改造。
## 路由映射总表
| 优先级 | uni-app 路由 | Vue Router 路由 | 目标模块 | 迁移策略 | 备注 |
| --- | --- | --- | --- | --- | --- |
| P0 | `/pages/index/index` | `/` | `features/chat` | 重写页面壳,复用可迁移业务逻辑 | 首页、发现、聊天主入口;旧页面禁用页面滚动 |
| P0 | `/pages/login/index` | `/login` | `features/auth` | 重写 | 登录方式需按 Web/H5 重新确认 |
| P1 | `/pages/goods/index` | `/goods/:commodityId?` | `features/goods` | 迁移并类型化 | 旧默认 `commodityId` 仅可作为开发兜底 |
| P1 | `/pages/goods/album/index` | `/goods/album` | `features/goods` | 迁移 | 图片数据建议通过 store 或 query id 获取 |
| P2 | `/pages/webview/index` | `/bridge/webview` | `features/bridge` | 重建桥接 | `<web-view>` 改为 iframe 或外链跳转 |
| P0 | `/pages/ChatMain/ChatLongAnswer/index` | `/chat/long-answer` | `features/chat` | 迁移并拆分 | 接收 `message``streamId``finished` 等 query |
| P0 | `/pages/ChatModule/LongTextGuideCardPreview/guide` | `/chat/guide/guide` | `features/chat` | 迁移 | 长文本 guide 预览 |
| P0 | `/pages/ChatModule/LongTextGuideCardPreview/poi` | `/chat/guide/poi` | `features/chat` | 迁移 | 长文本 poi 预览 |
| P0 | `/pages/ChatModule/LongTextGuideCardPreview/route` | `/chat/guide/route` | `features/chat` | 迁移 | 长文本 route 预览 |
| P0 | `/pages/ChatModule/LongTextGuideCardPreview/photo` | `/chat/guide/photo` | `features/chat` | 迁移 | 长文本 photo 预览 |
| P1 | `/pages/ChatMain/NoticeMessage/detail` | `/notice/:id?` | `features/notice` | 迁移 | 当前通过 query 传参Web 端建议兼容 query |
| P3 | `/pages/test/index` | `/dev/test` | `features/dev` | 延后或废弃 | 仅开发测试入口,默认不进入首批迁移 |
| P1 | `/pages-order/order/list` | `/orders` | `features/order` | 迁移 | 订单列表,原 pages-order 分包取消 |
| P1 | `/pages-order/order/detail` | `/orders/:orderId` | `features/order` | 迁移 | 兼容 `?orderId=` 历史跳转 |
| P2 | `/pages-service/order/list` | `/service-orders` | `features/service` | 迁移 | 工单/服务订单列表 |
| P2 | `/pages-quick/list` | `/quick` | `features/quick` | 迁移 | 快捷入口列表 |
| P1 | `/pages-booking/index` | `/booking` | `features/booking` | 迁移 | 预订确认;参数来源需从 query/store 明确化 |
| P2 | `/pages-bridge/UploadImage` | `/bridge/upload-image` | `features/bridge` | 兼容后废弃 | 优先改为统一上传服务和 postMessage 回传 |
| P2 | `/pages-bridge/SaveImage` | `/bridge/save-image` | `features/bridge` | 兼容后废弃 | 浏览器保存图片能力受限制 |
## Vue Router 初稿
```ts
export const routes = [
{ path: "/", name: "home", component: () => import("@/features/chat/pages/HomePage.vue") },
{ path: "/login", name: "login", component: () => import("@/features/auth/pages/LoginPage.vue") },
{ path: "/goods/:commodityId?", name: "goods-detail", component: () => import("@/features/goods/pages/GoodsDetailPage.vue") },
{ path: "/goods/album", name: "goods-album", component: () => import("@/features/goods/pages/GoodsAlbumPage.vue") },
{ path: "/booking", name: "booking", component: () => import("@/features/booking/pages/BookingPage.vue") },
{ path: "/orders", name: "orders", component: () => import("@/features/order/pages/OrderListPage.vue") },
{ path: "/orders/:orderId", name: "order-detail", component: () => import("@/features/order/pages/OrderDetailPage.vue") },
{ path: "/service-orders", name: "service-orders", component: () => import("@/features/service/pages/ServiceOrderListPage.vue") },
{ path: "/quick", name: "quick", component: () => import("@/features/quick/pages/QuickListPage.vue") },
{ path: "/notice/:id?", name: "notice-detail", component: () => import("@/features/notice/pages/NoticeDetailPage.vue") },
{ path: "/chat/long-answer", name: "chat-long-answer", component: () => import("@/features/chat/pages/LongAnswerPage.vue") },
{ path: "/chat/guide/:type", name: "chat-guide-preview", component: () => import("@/features/chat/pages/GuidePreviewPage.vue") },
{ path: "/bridge/webview", name: "bridge-webview", component: () => import("@/features/bridge/pages/WebviewBridgePage.vue") },
{ path: "/bridge/upload-image", name: "bridge-upload-image", component: () => import("@/features/bridge/pages/UploadImageBridgePage.vue") },
{ path: "/bridge/save-image", name: "bridge-save-image", component: () => import("@/features/bridge/pages/SaveImageBridgePage.vue") },
{ path: "/dev/test", name: "dev-test", component: () => import("@/features/dev/pages/TestPage.vue") },
]
```
## 旧路由兼容策略
迁移期间建议保留一个旧路由转换函数,用于处理旧代码、外部 H5、历史分享链接中的 uni-app path
| 输入 | 输出 |
| --- | --- |
| `/pages/index/index` | `/` |
| `/pages/goods/index?commodityId=123` | `/goods/123` |
| `/pages-order/order/detail?orderId=123` | `/orders/123` |
| `/pages/webview/index?url=...` | `/bridge/webview?url=...` |
| `/pages/ChatModule/LongTextGuideCardPreview/poi` | `/chat/guide/poi` |
兼容层只在迁移期使用。新 Web 代码应直接使用 Vue Router route name 或封装后的 `routerService`
## 参数迁移规则
| 参数来源 | uni-app 写法 | Web 目标写法 |
| --- | --- | --- |
| 页面参数 | `onLoad((query) => {})` | `useRoute().query``useRoute().params` |
| 商品 id | `commodityId` query | `/goods/:commodityId`,同时兼容 query |
| 订单 id | `orderId` query | `/orders/:orderId`,同时兼容 query |
| WebView URL | `url` query | `/bridge/webview?url=`,进入前校验和编码 |
| 长回答内容 | `message/streamId/finished` query | query 保留,后续可改为 store/session id |
## 迁移顺序
1. 建立 Vue Router 和 `routerService`
2. 添加旧路由到新路由的转换表。
3. 迁移首页、登录、聊天详情等 P0 路由。
4. 迁移商品、预订、订单等 P1 路由。
5. 迁移工单、快捷入口、桥接等 P2 路由。
6. 确认没有旧路由调用后,删除兼容转换表。
## 验收清单
- [ ] Vue Router 中存在所有 P0/P1 路由。
- [ ]`navigateTo` 参数能正确映射到新路由。
- [ ] 页面刷新后能从 URL 恢复必要参数。
- [ ] 登录拦截、424 登出跳转和返回上一页逻辑可用。
- [ ] WebView/iframe URL 参数经过编码和安全校验。
- [ ] 分包页面迁移后不再依赖 uni-app subPackages。

View File

@@ -1,136 +0,0 @@
# uni-app API 替换矩阵
## 文档状态
- 状态:阶段 0 盘点产物
- 日期2026-05-25
- 来源:`rg` 扫描 `src`,排除 `src/uni_modules`
- 目标:为 Vue3 Web 改造建立 uni 运行时替换账本
## 扫描摘要
高频 `uni.*` 使用统计:
| API | 次数 | 主要风险 |
| --- | ---: | --- |
| `uni.showToast` | 74 | 用户反馈入口分散 |
| `uni.navigateTo` | 26 | 路由跳转分散 |
| `uni.$emit` | 26 | 跨组件事件耦合 |
| `uni.hideLoading` | 19 | loading 状态分散 |
| `uni.$on` | 13 | 事件监听生命周期需重建 |
| `uni.createSelectorQuery` | 12 | DOM 测量方式不同 |
| `uni.navigateBack` | 9 | 返回逻辑需路由服务承接 |
| `uni.$off` | 9 | 事件清理需统一 |
| `uni.connectSocket` | 8 | 聊天实时链路高风险 |
| `uni.showModal` | 7 | Modal 交互需统一 |
| `uni.showLoading` | 6 | loading 交互需统一 |
| `uni.getSystemInfoSync` | 6 | 系统信息和安全区需 Web 替代 |
| `uni.hideKeyboard` | 5 | 键盘行为 Web 不等价 |
| `uni.request` | 4 | 请求层需替换 |
| `uni.getLocation/openLocation` | 6 | 浏览器定位和地图打开需授权/降级 |
| `uni.requestPayment` | 2 | 支付方案需重新确认 |
| `uni.login` | 2 | 微信登录不能直接迁移 |
| `uni.chooseImage` | 2 | 图片选择上传需 Web 化 |
| `uni.saveImageToPhotosAlbum` | 2 | 浏览器保存相册不可等价 |
微信原生 `wx.*` 使用:
| API | 次数 | 文件 |
| --- | ---: | --- |
| `wx.getPrivacySetting` | 1 | `src/components/Privacy/index.vue` |
| `wx.openPrivacyContract` | 1 | `src/components/Privacy/index.vue` |
uni 页面生命周期使用集中在:
- `src/App.vue`
- `src/pages/index/index.vue`
- `src/pages/login/index.vue`
- `src/pages/goods/index.vue`
- `src/pages/goods/album/index.vue`
- `src/pages-booking/index.vue`
- `src/pages-order/order/detail.vue`
- `src/pages/ChatMain/ChatMainList/index.vue`
- `src/pages/ChatMain/ChatLongAnswer/index.vue`
- `src/pages/ChatMain/NoticeMessage/detail.vue`
- `src/pages-bridge/UploadImage.vue`
- `src/components/Privacy/index.vue`
## 替换矩阵
| 分类 | 当前 API/能力 | 代表文件 | Web 替代方案 | 目标封装 | 阶段 | 风险 |
| --- | --- | --- | --- | --- | --- | --- |
| 路由 | `uni.navigateTo``uni.navigateBack``uni.reLaunch` | `src/router/index.js``src/hooks/useGoLogin.js`、多页面 | Vue Router `push/back/replace` | `services/router` | 2 | 中 |
| 请求 | `uni.request` | `src/request/base/request.js``src/request/api/AgentChatStream.js` | Axios 或 `fetch` | `services/http``services/stream` | 2/4 | 高 |
| 上传 | `uni.uploadFile` | `src/request/api/UpdateFile.js` | `FormData` + `fetch/axios` | `services/http/upload` | 2/7 | 中 |
| 下载 | `uni.downloadFile` | `src/pages/webview/bridge.js` | `fetch blob` + object URL | `services/browser/download` | 7 | 中 |
| 存储 | `uni.setStorageSync``uni.getStorageSync``uni.removeStorageSync` | `src/constant/token.js` | `localStorage/sessionStorage` | `services/storage` | 2/3 | 低 |
| 事件 | `uni.$emit``uni.$on``uni.$off` | 聊天、发现、登录、通知 | `mitt` typed event bus | `services/event-bus` | 2 | 中 |
| 反馈 | `uni.showToast``uni.showModal``uni.showLoading``uni.hideLoading` | 多页面和组件 | 统一 Toast/Modal/Loading 组件 | `services/feedback` | 2 | 低 |
| 生命周期 | `onLoad``onShow``onHide``onUnload``onReady` | 页面组件 | Vue `onMounted/onUnmounted` + Router hooks | 页面组合式函数 | 4-7 | 中 |
| 应用启动 | `onLaunch``uni.onNetworkStatusChange``uni.getNetworkType` | `src/App.vue` | App bootstrap + `online/offline` 事件 | `app/bootstrap` | 2/3 | 中 |
| 系统信息 | `uni.getSystemInfoSync``uni.getWindowInfo` | 导航栏、登录、卡片 | `window.innerWidth`、CSS env、ResizeObserver | `services/browser/viewport` | 2/8 | 中 |
| DOM 测量 | `uni.createSelectorQuery` | Tabs、发现 tabs、长回答 | DOM API、`getBoundingClientRect`、ResizeObserver | 局部 composable | 5/6 | 中 |
| 键盘 | `uni.onKeyboardHeightChange``uni.hideKeyboard` | `src/pages/ChatMain/ChatInputArea/index.vue` | VisualViewport API、blur、CSS 视口适配 | `features/chat/composables` | 4 | 高 |
| WebSocket | `uni.connectSocket` | `src/utils/WebSocketManager.js` | 浏览器原生 `WebSocket` | `services/websocket` | 4 | 高 |
| 流式响应 | `enableChunked``uni.arrayBufferToBase64` | `src/request/api/AgentChatStream.js` | `fetch + ReadableStream`、TextDecoder、SSE parser | `services/stream` | 4 | 高 |
| 登录 | `uni.login` | `src/manager/LoginManager.js` | 微信 Web 授权、H5 登录或后端 token 方案 | `services/auth` | 3 | 高 |
| 支付 | `uni.requestPayment` | `src/pages-booking/index.vue``FooterSection` | 微信 JS-SDK/H5 支付/后端支付跳转 | `features/payment` | 6 | 高 |
| 图片选择 | `uni.chooseImage` | `CreateServiceOrder``webview/bridge.js` | `<input type="file">` | `services/browser/file-picker` | 7 | 中 |
| 保存图片 | `uni.saveImageToPhotosAlbum` | `Qrcode``webview/bridge.js` | 下载链接、长按保存提示 | `services/browser/download` | 7 | 中 |
| 图片预览 | `uni.previewImage` | 图片组件 | 弹窗预览组件 | `components/ImagePreview` | 5/6 | 低 |
| Canvas | `uni.createCanvasContext``uni.canvasToTempFilePath``uni.upx2px` | `src/components/Qrcode` | 浏览器 Canvas、二维码库 | `components/Qrcode` | 6/7 | 中 |
| 定位地图 | `uni.getLocation``uni.openLocation` | `LocationCard``LocationInfo``Discovery` | Geolocation API、地图 URL/SDK | `services/browser/location` | 5/6 | 中 |
| 电话 | `uni.makePhoneCall` | `LocationCard`、订单卡片 | `tel:` 链接 | `services/browser/phone` | 6/7 | 低 |
| 小程序隐私 | `wx.getPrivacySetting``wx.openPrivacyContract``uni.getPrivacySetting` | `src/components/Privacy/index.vue` | Web 隐私协议弹窗/链接 | `features/auth/privacy` | 3/7 | 中 |
| 分享 | `uni.showShareMenu``utils/share.js` | `src/main.js``src/utils/share.js` | Web Share API 或自定义分享 | `services/browser/share` | 7 | 中 |
| 更新 | `uni.getUpdateManager` | `src/utils/UpdateManager.js` | Web 无等价PWA 时另做 | 待定 | 9 | 低 |
## 模板标签替换摘要
高频 uni/小程序标签:
| 标签 | 次数 | Web 替代 |
| --- | ---: | --- |
| `<view>` | 997 | `div` 或布局组件 |
| `<text>` | 292 | `span``p` |
| `<image>` | 65 | `img` 或图片组件 |
| `<button>` | 20 | `button` |
| `<scroll-view>` | 18 | `div` + CSS overflow |
| `<input>` | 9 | `input` |
| `<uni-popup>` | 7 | Modal/Drawer 组件 |
| `<swiper>``<swiper-item>` | 6 | 轮播组件或 CSS scroll snap |
| `<textarea>` | 3 | `textarea` |
| `<z-paging>` | 3 | 列表分页/虚拟列表组件 |
| `<zero-markdown-view>` | 3 | Markdown 渲染库 |
| `<canvas>` | 2 | 浏览器 `canvas` |
替换策略:
1. 迁移页面时同步替换标签,不做全仓机械替换。
2. 高频基础标签可在早期建立轻量基础组件,但不要复刻 uni 组件完整语义。
3. `scroll-view``swiper``canvas``web-view` 必须按业务场景单独验证。
## 约束规则
- 新 Web 代码不得直接调用 `uni.*``wx.*`
- 新业务页面不得直接散落 `fetch``localStorage``window.location` 等浏览器 API必须通过服务封装进入。
- 新路由跳转优先使用 route name 或 `routerService`,避免字符串拼接旧路径。
- 事件名可以沿用 `src/constant/constant.js`,但事件 payload 应在 TypeScript 中补类型。
- 小程序专属能力先保留旧项目Web 端必须有明确替代、降级或暂不支持说明。
## 第一批替换任务建议
1. `services/storage` 替代 token storage。
2. `services/event-bus` 替代登录、聊天、发现联动事件。
3. `services/router` 替代跳转语义。
4. `services/feedback` 替代 toast/loading/modal。
5. `services/http` 替代普通 API 请求。
6. `services/websocket``services/stream` 单独做聊天链路原型。
## 验收清单
- [ ] 新 Web 工程中没有新增 `uni.*``wx.*` 调用。
- [ ] 所有平台能力都有唯一封装入口。
- [ ] 聊天 WebSocket 和流式响应先做原型验证。
- [ ] 支付、登录、隐私协议有目标平台方案确认。
- [ ] 页面迁移时每个 `scroll-view``swiper``canvas` 都有对应验收项。