# Epic 005: 出行服务核心功能 (MVP优先)

## 版本信息
| 版本 | 日期 | 描述 | 作者 |
|------|------|------|------|
| 2.5 | 2025-10-25 | 根据代码核对更新订单导出功能故事US005-14，完善技术实现细节 | John (PM) |
| 2.4 | 2025-10-25 | 添加管理后台订单数据导出功能故事US005-14，顺延原有故事编号 | John (PM) |
| 2.3 | 2025-10-25 | 添加微信小程序环境自动登录获取openid故事US005-13，顺延原有故事编号 | John (PM) |
| 2.2 | 2025-10-25 | 添加小程序手机号获取集成故事US005-12，顺延原有故事编号 | John (PM) |
| 2.1 | 2025-10-20 | 添加车型和路线配置增强故事US005-04，顺延原有故事编号 | John (PM) |
| 2.0 | 2025-10-19 | 添加样式迁移合规性修复故事US005-03，顺延原有故事编号 | John (PM) |
| 1.9 | 2025-10-17 | 添加省市区实体设计方案，支持标准化行政区划数据管理 | John (PM) |
| 1.8 | 2025-10-17 | 采用地点实体方案，统一管理地点信息，支持省市区查询 | John (PM) |
| 1.7 | 2025-10-17 | 优化查询逻辑，明确通过路线查询活动的实现方式 | John (PM) |
| 1.6 | 2025-10-17 | 优化活动实体设计，添加举办地点字段，去程/返程动态判断 | John (PM) |
| 1.5 | 2025-10-16 | 为乘客、订单、用户添加管理后台查看故事 | John (PM) |
| 1.4 | 2025-10-16 | 修正数据模型，移除班次实体，与架构文档保持一致 | Bob (Scrum Master) |
| 1.3 | 2025-10-16 | 添加管理后台故事US005-01，确保故事闭环 | John (PM) |
| 1.2 | 2025-10-15 | 添加我的页面到MVP迁移范围 | John (PM) |
| 1.1 | 2025-10-15 | 重构页面迁移为用户故事任务 | John (PM) |
| 1.0 | 2025-10-15 | 基于实际项目状态创建Epic 005 | John (PM) |

## Epic概述

### Epic目标
实现出行服务的核心功能，包括路线查询、活动筛选、订单管理、乘客管理、支付集成等，将mini-demo的核心页面功能迁移到真实的后端系统。

### 成功标准
- 用户能够完成从查询路线到支付完成的完整出行流程
- 订单数据正确存储到PostgreSQL数据库
- 核心业务逻辑完整实现
- MVP相关页面功能正常

## 当前项目状态分析

### 现有基础
- ✅ **后端框架**: Hono + TypeORM + PostgreSQL 已就绪
- ✅ **用户管理**: 完整的用户认证和权限系统已实现
- ✅ **文件管理**: MinIO对象存储集成已完成
- ✅ **前端基础**: Taro + React 框架已搭建
- ⚠️ **业务数据**: 缺少出行服务相关数据模型
- ⚠️ **前端页面**: 只有基础页面，缺少出行服务页面

### mini-demo页面分析
mini-demo包含14个页面，Epic 005将页面迁移作为用户故事的具体任务进行拆分：
- **核心流程页面** (9个): 首页、活动选择、班次列表、下单页面、添加乘客、支付成功、订单列表、订单详情、我的页面
- **辅助功能页面** (5个): 积分商城、积分历史、优惠券管理等（MVP阶段暂不迁移）

## 用户故事

### US005-01: 基础数据管理（管理后台）
**作为** 系统管理员
**我希望** 能够配置活动、路线等基础数据
**以便** 用户能够查询和使用出行服务

**验收标准**:
- [ ] 支持创建和管理活动信息（活动名称、描述、举办地点、时间范围）
- [ ] 支持配置路线信息（出发地、目的地、上车点、下车点、出发时间、车型、价格、座位数）
- [ ] 支持设置活动关联的路线
- [ ] 支持启用/禁用活动、路线
- [ ] 路线自动识别为去程或返程（目的地=活动地点为去程，出发地=活动地点为返程）

**管理后台页面任务**:
- [ ] 活动管理页面 - 活动类型配置和管理
- [ ] 路线管理页面 - 路线信息配置和管理

### US005-02: 路线查询和活动筛选
**作为** 出行用户
**我希望** 能够查询出行路线和筛选活动类型
**以便** 快速找到适合的出行方案

**验收标准**:
- [ ] 支持按出发地、目的地、日期查询路线
- [ ] 支持筛选去程路线/返程路线
- [ ] 显示路线详细信息（上车点、下车点、出发时间、车型、价格）
- [ ] 支持按价格、出发时间排序
- [ ] 路线类型自动识别（去程：目的地=活动地点，返程：出发地=活动地点）
- [ ] 支持通过路线查询关联的活动信息

**页面迁移任务**:
- [ ] 迁移首页 (home/home) - 路线查询入口页面
- [ ] 迁移活动选择页面 (select-activity/select-activity) - 活动筛选页面
- [ ] 迁移班次列表页面 (schedule-list/schedule-list) - 路线列表展示

### US005-03: 样式迁移合规性修复
**作为** 产品经理
**我希望** 确保所有迁移页面严格遵守样式迁移规范
**以便** 保持用户体验一致性和设计系统完整性

**验收标准**:
- [ ] 更新Tailwind配置，添加迁移指导规范中定义的设计系统
- [ ] 修复首页样式，使用正确的设计系统类名
- [ ] 实现包车主题，为不同出行方式提供不同的视觉主题
- [ ] 验证活动选择页面和班次列表页面的样式合规性
- [ ] 确保所有样式转换符合精确迁移要求

**技术实现任务**:
- [ ] 扩展Tailwind配置（颜色系统、圆角系统、阴影系统）
- [ ] 修复首页样式合规性（轮播图、出行方式选择器、出行选择区域）
- [ ] 验证活动选择页面样式（头部信息区域、行程区域、活动卡片）
- [ ] 验证班次列表页面样式（包车卡片、预订按钮、排序工具栏）
- [ ] 编写样式合规性测试

### US005-04: 车型和出行方式配置增强
**作为** 系统管理员
**我希望** 能够配置完整的车型枚举和独立的出行方式字段
**以便** 支持更灵活的出行服务组合查询

**组合查询逻辑**:
- **大巴拼车** → 大巴 + 拼车
- **商务车** → 商务车 + 拼车/包车
- **包车** → 大巴/商务车 + 包车

**具体实现要求**:
- **首页**：保持现有三种查询选项，但查询逻辑需要调整为组合查询
- **活动选择页面**：根据组合查询条件筛选相关活动
- **班次列表页面**：根据组合查询条件显示匹配的路线
- **API查询**：支持根据车型和出行方式的组合条件进行筛选

**组合查询API参数映射**:
- **大巴拼车**：`vehicleType=bus&travelMode=carpool`
- **商务车**：`vehicleType=business&travelMode=carpool,charter`（支持两种出行方式）
- **包车**：`vehicleType=bus,business&travelMode=charter`（支持两种车型）

**验收标准**:
- [ ] 车型枚举包含完整选项：大巴、中巴、小车、商务车
- [ ] 路线配置支持独立的出行方式选择（拼车/包车）
- [ ] 支持组合查询逻辑：大巴拼车、商务车、包车三种查询方式
- [ ] 不同组合支持不同的价格策略和座位配置
- [ ] 前端页面正确显示组合查询选项
- [ ] 小程序和管理后台界面支持组合查询方式
- [ ] 查询API支持组合查询逻辑
- [ ] 活动选择页面支持组合查询逻辑
- [ ] 班次列表页面正确显示组合查询结果

**技术实现任务**:
- [ ] 更新VehicleType枚举，添加商务车选项
- [ ] 创建TravelMode枚举，定义拼车和包车出行方式
- [ ] 在路线实体中添加travelMode字段
- [ ] 更新管理后台路线配置页面，支持车型和出行方式独立选择
- [ ] 更新小程序首页出行方式选择器的查询逻辑，支持组合查询
- [ ] 更新活动选择页面查询逻辑，支持组合查询
- [ ] 更新班次列表页面查询逻辑，支持组合查询
- [ ] 更新班次列表页面显示逻辑，正确显示车型和出行方式的组合信息
- [ ] 更新路线查询API，支持组合查询逻辑
- [ ] 更新订单详情页面，显示完整的车型和出行方式信息
- [ ] 验证前端页面正确显示组合查询选项

**查询逻辑实现细节**:
- **首页查询逻辑**：将三种组合选项映射为对应的API查询参数
- **活动选择页面查询逻辑**：根据组合条件查询关联的活动，支持多条件筛选
- **班次列表页面查询逻辑**：根据组合条件查询匹配的路线，支持车型和出行方式的组合筛选
- **API查询逻辑**：支持多值参数查询，如`vehicleType=bus,business`和`travelMode=carpool,charter`

**界面修改任务**:
- [ ] **管理后台路线配置页面**：添加出行方式选择器，与车型选择器并列
- [ ] **小程序首页**：保持现有组合查询选项显示，更新查询逻辑
- [ ] **班次列表页面**：更新路线卡片，同时显示车型和出行方式
- [ ] **订单详情页面**：更新订单信息显示，包含车型和出行方式

**API修改任务**:
- [ ] 更新路线创建和更新API，支持travelMode字段
- [ ] 更新路线查询API，支持组合查询逻辑
- [ ] 更新路线列表API响应，包含travelMode字段
- [ ] 更新活动查询API，支持组合查询逻辑
- [ ] 更新订单相关API，确保travelMode信息正确传递
- [ ] 更新管理后台路线管理API，支持车型和出行方式筛选

**API查询参数设计**:
- **路线查询API**：支持多值参数
  - `vehicleType`: 支持逗号分隔的多个车型（如`bus,business`）
  - `travelMode`: 支持逗号分隔的多个出行方式（如`carpool,charter`）
  - 组合查询逻辑：`vehicleType`和`travelMode`参数同时存在时进行组合筛选
- **活动查询API**：根据路线组合条件查询关联的活动
  - 支持通过路线查询参数间接筛选活动
  - 返回去重后的活动列表

### US005-05: 乘客信息查看（管理后台）
**作为** 系统管理员
**我希望** 能够查看所有用户的乘客信息
**以便** 了解用户乘车人情况和进行数据统计

**验收标准**:
- [ ] 支持查看所有乘客信息列表
- [ ] 支持按用户筛选乘客信息
- [ ] 显示乘客基本信息（姓名、证件类型、证件号码、手机号）
- [ ] 支持导出乘客数据

**管理后台页面任务**:
- [ ] 乘客信息管理页面 - 查看所有乘客信息

### US005-06: 乘客信息管理
**作为** 出行用户
**我希望** 能够管理我的乘客信息
**以便** 快速选择乘车人

**验收标准**:
- [ ] 支持添加、编辑、删除乘客信息
- [ ] 支持设置默认乘客
- [ ] 验证乘客信息完整性（姓名、证件类型、证件号码、手机号）
- [ ] 支持多种证件类型（身份证、港澳通行证、护照等）

**页面迁移任务**:
- [ ] 迁移添加乘客页面 (add-passenger/add-passenger) - 乘客信息管理页面

### US005-07: 订单信息查看（管理后台）
**作为** 系统管理员
**我希望** 能够查看所有订单信息和状态
**以便** 监控订单流程和处理异常订单

**验收标准**:
- [ ] 支持查看所有订单列表
- [ ] 支持按订单状态筛选（待支付、待出发、行程中、已完成、已取消）
- [ ] 显示订单详细信息（用户信息、路线信息、乘客信息、金额、状态）
- [ ] 支持订单状态统计和报表

**管理后台页面任务**:
- [ ] 订单管理页面 - 查看所有订单信息

### US005-08: 订单创建和支付
**作为** 出行用户
**我希望** 能够创建订单并完成支付
**以便** 确认出行安排

**验收标准**:
- [ ] 选择路线和乘客后创建订单
- [ ] 计算订单总金额
- [ ] 集成微信支付完成支付流程
- [ ] 支付成功后更新订单状态
- [ ] 保存订单快照信息（路线快照、乘客快照）

**页面迁移任务**:
- [ ] 迁移下单页面 (order/order) - 订单创建页面
- [ ] 迁移支付成功页面 (pay-success/pay-success) - 支付结果页面


### US005-09: 订单状态管理
**作为** 出行用户
**我希望** 能够查看和管理我的订单状态
**以便** 了解出行安排进度

**验收标准**:
- [x] 查看订单列表（待支付、待出发、行程中、已完成、已取消）
- [x] 查看订单详情信息
- [x] 支持取消订单（在允许的时间范围内）
- [ ] 订单状态自动更新（待出发→行程中→已完成）

**页面迁移任务**:
- [x] 迁移订单列表页面 (orders/orders) - 订单管理页面
- [x] 迁移订单详情页面 (order-detail/order-detail) - 订单详情查看页面


### US005-10: 个人中心管理
**作为** 出行用户
**我希望** 能够查看和管理我的个人信息
**以便** 方便地管理我的出行服务

**验收标准**:
- [x] 查看个人基本信息（头像、用户名、邮箱、注册时间）
- [ ] 头像上传和更新功能
- [x] 快速访问基础功能（编辑资料、乘客管理、设置）
- [x] 退出登录功能
- [ ] 账号信息展示（用户ID、最近登录时间）
- [ ] 按照 mini-demo 样式规范重构页面

**MVP已实现功能**:
- ✅ 用户信息展示区域
- ✅ 头像上传组件（已集成）
- ✅ 基础功能菜单
- ✅ 退出登录流程
- ✅ 账号信息展示

**待完善功能**:
- 🔄 按照 mini-demo 样式规范重构页面
- 🔄 头像上传API集成
- 🔄 编辑资料功能
- 🔄 设置页面功能
- 🔄 乘客管理页面跳转

**技术状态**:
- 页面已迁移完成，使用React + TypeScript + Tailwind CSS
- 基础UI组件已实现，需要按照 mini-demo 样式规范重构
- 需要后端API集成完成功能

**样式迁移要求**:
- 用户信息区域使用渐变背景：`linear-gradient(135deg, #4A90C2 0%, #357ABD 100%)`
- 会员卡片使用紫色渐变：`linear-gradient(135deg, #667eea 0%, #764ba2 100%)`
- 功能菜单使用卡片布局，带阴影和边框
- 精确匹配 mini-demo 的间距、圆角和字体系统

### US005-11: 支付集成
**作为** 系统
**我希望** 集成微信支付功能
**以便** 支持用户完成订单支付

**验收标准**:
- [x] 实现微信支付JSAPI集成 - 已使用 `wechatpay-node-v3` SDK 完整实现
- [x] 处理支付回调通知 - 已实现签名验证、数据解密和状态更新
- [x] 支付状态与订单状态同步 - 已实现完整的订单状态流转机制
- [x] 支付异常处理（超时、失败、重复支付） - 已实现错误处理和状态管理
- [x] 支付安全验证 - 已实现签名验证、金额一致性检查、防重放攻击
- [x] 支付状态查询 - 已提供支付状态查询接口
- [ ] 前端微信支付SDK调用 - 前端代码有TODO注释待实现

**备注**: 退款功能MVP已标记为不需要，当前仅支持支付功能

**技术实现详情**:
- **后端支付服务**: `packages/server/src/modules/payment/payment.service.ts`
- **支付API**: `packages/server/src/api/payment/create.ts`
- **订单状态管理**: 支持 `待支付` → `支付中` → `已支付`/`支付失败` 状态流转
- **安全机制**: 签名验证、AES-256-GCM数据加密、防重放攻击
- **测试覆盖**: 完整的集成测试和单元测试

### US005-12: 小程序手机号获取集成
**作为** 出行用户
**我希望** 能够通过微信小程序一键获取我的手机号
**以便** 快速完成订单联系信息填写

**验收标准**:
- [ ] 支持微信小程序 `getPhoneNumber` 功能调用
- [ ] 实现手机号解密API接口，接收小程序加密数据
- [ ] 将获取的手机号保存到用户信息中
- [ ] 订单确认页面显示已获取的手机号状态
- [ ] 支持手机号获取失败的重试机制
- [ ] 确保手机号数据安全性和隐私保护
- [ ] 手机号获取成功后自动填充到订单联系信息
- [ ] 支持手机号验证状态显示

**技术实现方案**:
- **前端实现**: 使用微信小程序 `getPhoneNumber` 组件
- **后端解密**: 使用微信官方SDK解密手机号加密数据
- **数据存储**: 将手机号保存到用户实体的 `phone` 字段
- **状态管理**: 订单页面显示手机号获取状态和验证状态

**前端实现细节**:
```typescript
// 订单确认页面手机号获取逻辑
const handleGetPhoneNumber = async (e: any) => {
  if (e.detail.errMsg === 'getPhoneNumber:ok') {
    // 调用后端手机号解密API
    const phoneData = await authClient.phone.$post({
      json: {
        code: e.detail.code,
        encryptedData: e.detail.encryptedData,
        iv: e.detail.iv
      }
    });

    // 更新用户信息和页面状态
    setPhoneNumber(phoneData.phoneNumber);
    setHasPhoneNumber(true);
  }
}
```

**后端实现细节**:
- **服务位置**: `packages/server/src/modules/auth/mini-auth.service.ts`
- **新增方法**: `decryptPhoneNumber(code: string, encryptedData: string, iv: string)`
- **解密流程**:
  1. 使用session_key解密手机号数据
  2. 验证用户身份和会话有效性
  3. 将手机号保存到用户实体
  4. 返回解密后的手机号信息

**API设计**:
```typescript
// 手机号解密API
POST /api/v1/auth/phone
{
  "code": "微信小程序获取的code",
  "encryptedData": "加密数据",
  "iv": "加密算法的初始向量"
}

// 响应
{
  "phoneNumber": "13812345678",
  "countryCode": "86",
  "purePhoneNumber": "13812345678"
}
```

**API路由位置**:
- **文件路径**: `packages/server/src/api/auth/phone/post.ts`
- **路由注册**: 在 `packages/server/src/api/auth/index.ts` 中添加
- **认证中间件**: 需要用户登录状态验证
- **错误处理**: 支持微信API错误、解密错误、网络错误等

**安全考虑**:
- 使用微信官方SDK进行数据解密
- 验证用户身份和会话有效性
- 防止重复获取和滥用
- 符合微信小程序隐私政策要求
- 手机号数据加密存储
- 访问权限控制

**依赖关系**:
- **前置依赖**: US005-10 个人中心管理（用户信息展示）
- **并行开发**: US005-08 订单创建和支付（订单确认页面）
- **技术依赖**: 微信小程序SDK、微信开放平台配置

**测试策略**:
- 单元测试：手机号解密逻辑测试
- 集成测试：微信API调用测试
- E2E测试：完整手机号获取流程测试
- 安全测试：数据加密和权限验证测试

### US005-13: 微信小程序环境自动登录获取openid
**作为** 微信小程序用户
**我希望** 在微信小程序环境中能够通过微信一键登录并获取我的openid
**以便** 便捷使用出行服务，无需手动输入账号密码

**验收标准**:
- [x] 支持微信小程序 `wx.login` 获取code
- [x] 实现openid获取API接口，接收小程序code
- [x] 自动创建或关联用户账号
- [x] 支持用户信息自动同步
- [ ] 实现静默登录机制，用户无感知（应用启动时自动登录）
- [x] 支持登录状态持久化
- [x] 确保登录流程的安全性和可靠性
- [x] 支持登录失败的重试机制
- [x] 兼容现有用户认证系统

**技术实现方案**:
- **前端实现**: 微信小程序登录页面调用 `wx.login` API获取code，支持用户信息授权
- **后端认证**: 使用微信官方SDK通过code获取openid和session_key
- **用户管理**: 自动创建或关联用户账号，支持openid绑定
- **会话管理**: session_key存储在Redis，JWT token用于认证

**前端实现细节**:
```typescript
// 微信小程序登录页面登录逻辑
const handleWechatLogin = async () => {
  try {
    // 1. 获取用户信息授权
    const userProfile = await Taro.getUserProfile({
      desc: '用于完善用户资料'
    });

    // 2. 获取登录code
    const loginRes = await Taro.login();

    if (!loginRes.code) {
      throw new Error('获取登录凭证失败');
    }

    // 3. 使用RPC client调用后端小程序登录API
    const response = await authClient['mini-login'].$post({
      json: {
        code: loginRes.code,
        userInfo: userProfile.userInfo
      }
    });

    if (response.status === 200) {
      const { token, user, isNewUser } = await response.json();

      // 4. 保存token和用户信息
      Taro.setStorageSync('userInfo', user);
      Taro.setStorageSync('mini_token', token);

      Taro.showToast({
        title: isNewUser ? '注册成功' : '登录成功',
        icon: 'success',
        duration: 1500
      });

      // 跳转到首页
      setTimeout(() => {
        Taro.switchTab({ url: '/pages/home/index' });
      }, 1500);
    } else {
      const errorData = await response.json();
      throw new Error(errorData.message || '登录失败');
    }
  } catch (error) {
    // 错误处理逻辑
  }
}

// 应用启动时调用
App({
  onLaunch() {
    autoLogin();
  }
});
```

**后端实现细节**:
- **服务位置**: `packages/server/src/modules/auth/mini-auth.service.ts`
- **核心方法**: `miniLogin(code: string)`
- **登录流程**:
  1. 使用code调用微信 `jscode2session` API获取openid和session_key
  2. 根据openid查找或创建用户账号
  3. 生成JWT token并返回给前端
  4. 保存session_key到Redis用于后续数据解密
  5. 支持用户信息更新（昵称、头像）

**API设计**:
```typescript
// 小程序自动登录API
POST /api/v1/auth/mini-login
{
  "code": "微信小程序登录获取的code",
  "userInfo": {
    "nickName": "用户昵称",
    "avatarUrl": "头像URL"
  }
}

// 响应
{
  "token": "JWT认证token",
  "user": {
    "id": "用户ID",
    "username": "用户名",
    "nickname": "昵称",
    "phone": "手机号",
    "email": "邮箱",
    "avatarFileId": "头像文件ID",
    "registrationSource": "注册来源"
  },
  "isNewUser": true
}
```

**API路由位置**:
- **文件路径**: `packages/server/src/api/auth/mini-login/post.ts`
- **路由注册**: 已在 `packages/server/src/api/auth/index.ts` 中注册
- **认证中间件**: 无需登录状态验证（用于首次登录）
- **错误处理**: 支持微信API错误、网络错误、用户创建失败等

**用户实体扩展**:
```typescript
// 在User实体中已添加微信相关字段
@Entity('users')
export class UserEntity {
  // 现有字段...

  @Column({ name: 'openid', type: 'varchar', length: 255, nullable: true, unique: true })
  openid!: string | null;

  @Column({ name: 'unionid', type: 'varchar', length: 255, nullable: true })
  unionid!: string | null;

  @Column({ name: 'registration_source', type: 'varchar', length: 20, default: 'web' })
  registrationSource!: string;
}
```

**安全考虑**:
- 使用微信官方SDK进行openid获取
- session_key安全存储在Redis，不返回给前端
- JWT token设置合理过期时间
- 防止重复登录和会话劫持
- 符合微信小程序安全规范
- 用户隐私数据保护
- 登录频率限制和防刷机制
- 支持用户信息授权，符合微信隐私政策

**依赖关系**:
- **前置依赖**: US005-02 用户管理基础框架 ✅
- **并行开发**: US005-12 小程序手机号获取集成 ✅
- **技术依赖**: 微信小程序SDK、微信开放平台配置、JWT认证 ✅

**测试策略**:
- 单元测试：openid获取和用户关联逻辑测试
- 集成测试：微信API调用和JWT生成测试
- E2E测试：完整微信登录流程测试
- 安全测试：会话管理和防刷机制测试
- 兼容性测试：与现有用户系统的兼容性

**实现状态总结**:
- ✅ **后端API**: 完整实现，支持openid获取、用户自动创建、JWT认证
- ✅ **前端页面**: 完整实现微信登录页面，支持用户信息授权
- ✅ **数据模型**: 用户实体已扩展支持openid、unionid等字段
- ✅ **会话管理**: session_key存储在Redis，支持后续数据解密
- 🔄 **静默登录**: 应用启动时自动登录功能待实现
- ✅ **安全机制**: 完整的错误处理、防刷机制和隐私保护

### US005-14: 管理后台订单数据导出功能
**作为** 系统管理员
**我希望** 能够在管理后台的订单管理页面导出订单数据为xlsx格式
**以便** 进行数据分析和报表制作

**验收标准**:
- [ ] 在订单管理页面添加"导出Excel"按钮
- [ ] 支持按当前筛选条件导出订单数据
- [ ] 导出的xlsx文件包含完整的订单信息
- [ ] 支持批量导出所有订单数据
- [ ] 导出的文件格式规范，包含表头和格式
- [ ] 支持导出进度显示和下载提示
- [ ] 处理大量数据时的性能优化
- [ ] 导出文件命名规范，包含时间戳

**实际可导出数据字段**（基于代码核对）:
- **订单编号**: `id`
- **用户信息**: `user.username`, `user.phone`
- **路线信息**: `route.name`, `route.description`
- **乘客数量**: `passengerCount`
- **订单金额**: `totalAmount`
- **订单状态**: `status` (待支付、待出发、行程中、已完成、已取消)
- **支付状态**: `paymentStatus` (待支付、支付中、已支付、支付失败、已退款、已关闭)
- **创建时间**: `createdAt`
- **更新时间**: `updatedAt`
- **乘客快照信息**: `passengerSnapshots` (包含姓名、证件类型、证件号码等)

**技术实现方案**（基于实际代码架构）:
- **前端实现**: 使用已安装的 `xlsx` 库生成Excel文件
- **后端支持**: 利用现有的通用CRUD API，支持JSON格式筛选条件
- **文件生成**: 前端生成Excel文件，避免服务器压力
- **性能优化**: 使用现有API的`pageSize`参数支持大量数据查询

**前端实现细节**（基于实际代码结构）:
```typescript
// 订单导出功能实现 - 基于实际Orders.tsx页面结构
const handleExportOrders = async () => {
  try {
    // 1. 显示导出进度
    setExporting(true);

    // 2. 获取当前页面筛选条件（基于现有filters和searchParams）
    const exportFilters = {
      status: filters.status,
      paymentStatus: filters.paymentStatus,
      search: searchParams.search,
      pageSize: 10000 // 使用大pageSize获取所有数据
    };

    // 3. 调用现有订单API获取数据
    const response = await orderClient.$get({
      query: {
        page: 1,
        pageSize: 10000,
        keyword: searchParams.search,
        filters: JSON.stringify({
          status: filters.status,
          paymentStatus: filters.paymentStatus
        })
      }
    });

    if (response.status !== 200) {
      throw new Error('获取订单数据失败');
    }

    const ordersData = await response.json();
    const orders = ordersData.data || [];

    // 4. 生成Excel文件
    const workbook = XLSX.utils.book_new();
    const worksheet = XLSX.utils.json_to_sheet(orders.map(order => ({
      '订单编号': `#${order.id}`,
      '用户名': order.user?.username || '未知用户',
      '手机号': order.user?.phone || '未知',
      '路线名称': order.route?.name || '未知路线',
      '路线描述': order.route?.description || '无描述',
      '乘客数量': order.passengerCount,
      '订单金额': `¥${order.totalAmount}`,
      '订单状态': order.status,
      '支付状态': order.paymentStatus,
      '创建时间': format(new Date(order.createdAt), 'yyyy-MM-dd HH:mm:ss'),
      '更新时间': format(new Date(order.updatedAt), 'yyyy-MM-dd HH:mm:ss'),
      '乘客信息': order.passengerSnapshots?.map((p: any, index: number) =>
        `乘客${index + 1}: ${p.name || '未知'} (${p.idType || '未知'}: ${p.idNumber || '未知'})`
      ).join('; ') || '无乘客信息'
    })));

    // 5. 设置表头样式
    XLSX.utils.book_append_sheet(workbook, worksheet, '订单数据');

    // 6. 生成文件并下载
    const fileName = `订单数据_${dayjs().format('YYYYMMDD_HHmmss')}.xlsx`;
    XLSX.writeFile(workbook, fileName);

    // 7. 显示成功提示
    message.success(`订单数据导出成功，共导出 ${orders.length} 条记录`);
  } catch (error) {
    console.error('导出失败:', error);
    message.error('导出失败，请重试');
  } finally {
    setExporting(false);
  }
};
```

**后端API现状**（基于代码核对）:
- ✅ **API端点**: `GET /api/v1/admin/orders` 已存在
- ✅ **查询参数**: 支持 `page`, `pageSize`, `keyword`, `filters` (JSON格式)
- ✅ **筛选支持**: 支持订单状态、支付状态筛选
- ✅ **数据关联**: 已包含 `user` 和 `route` 关联数据
- ✅ **分页能力**: 支持大pageSize查询（最大10000条）

**管理后台页面任务**:
- [ ] 在订单管理页面添加导出按钮（位于搜索区域）
- [ ] 实现导出功能组件（集成到现有Orders.tsx中）
- [ ] 添加导出进度显示和状态管理
- [ ] 支持按当前筛选条件导出
- [ ] 优化大量数据导出性能

**技术实现任务**:
- [x] **xlsx库依赖**: 已安装（web/package.json:118行）
- [ ] 实现订单数据导出组件
- [x] **后端API**: 已支持大量数据查询
- [x] **权限验证**: 已通过adminMiddleware实现
- [ ] 实现导出文件命名规范
- [ ] 添加导出错误处理和重试机制

**性能优化策略**:
- **现有API利用**: 使用现有通用CRUD API的`pageSize`参数
- **进度显示**: 在导出过程中显示进度状态
- **错误处理**: 处理网络超时和API错误
- **内存管理**: 及时释放内存资源

**安全考虑**:
- ✅ **权限验证**: 已通过adminMiddleware确保仅管理员可访问
- ✅ **数据安全**: 现有API已包含权限验证
- **数据脱敏**: 保护用户隐私信息
- **导出频率**: 可考虑添加频率限制

**依赖关系**:
- ✅ **前置依赖**: US005-07 订单信息查看（管理后台）已实现
- ✅ **技术依赖**: xlsx库已安装，订单查询API已存在
- ✅ **并行开发**: 可与现有订单管理页面集成

**实现状态总结**:
- ✅ **技术基础**: xlsx库已安装，后端API已就绪
- ✅ **数据模型**: 订单实体包含完整导出字段
- ✅ **权限控制**: 管理员权限验证已实现
- 🔄 **前端集成**: 需要在Orders.tsx中添加导出功能
- 🔄 **用户体验**: 需要添加导出进度和状态显示

## 技术实现方案

### 后端数据模型
基于架构文档设计，需要实现以下实体：
- **Order实体**: 订单管理
- **Passenger实体**: 乘客信息管理
- **Route实体**: 路线管理（包含出发时间、车型、价格、座位数等）
- **Activity实体**: 活动管理（包含举办地点信息，去程/返程通过路线与活动地点的关系动态判断）

### 活动实体设计优化
基于对现有设计的分析，活动实体需要进行以下优化：

**问题识别**:
- 当前活动实体缺少举办地点字段
- 去程/返程逻辑不够清晰，存在数据冗余
- 每个活动都需要创建对应的去程和返程活动，导致重复数据
- 地点信息缺乏结构化，无法支持省市区查询和地理功能

**优化方案**:
- **创建独立的地点实体(LocationEntity)**: 统一管理所有地点信息，包含省市区、经纬度等
- **Activity实体关联地点**: 通过venueLocation字段关联活动举办地点
- **Route实体关联地点**: 通过startLocation和endLocation字段关联路线起止地点
- **去程/返程动态判断**:
  - 去程路线: 目的地 = 活动举办地点
  - 返程路线: 出发地 = 活动举办地点
- **简化数据模型**: 每个活动只需创建一次，路线根据与活动地点的关系自动识别类型

**数据模型示例**:
```
地点 (Location)
├── 名称 (name)
├── 省份 (province)
├── 城市 (city)
├── 区县 (district)
├── 详细地址 (address)
├── 纬度 (latitude)
└── 经度 (longitude)

活动 (Activity)
├── 名称 (name)
├── 描述 (description)
├── 举办地点 (venueLocation) → 关联Location
├── 开始时间 (startDate)
└── 结束时间 (endDate)

路线 (Route)
├── 出发地 (startLocation) → 关联Location
├── 目的地 (endLocation) → 关联Location
├── 上车点 (pickupPoint)
├── 下车点 (dropoffPoint)
├── 车型 (vehicleType) → VehicleType枚举（大巴/中巴/小车/商务车）
├── 出行方式 (travelMode) → TravelMode枚举（拼车/包车）
├── 关联活动 (activity)
└── 其他信息...
```

### 省市区实体设计方案
基于发现的省市区数据文件，需要实现标准化的省市区数据管理：

**问题识别**:
- 当前地点实体中的省市区字段为自由文本，缺乏标准化
- 无法支持省市区三级联动选择
- 地点查询时无法按标准行政区划进行精确筛选
- 缺乏完整的省市区数据支持

**优化方案**:
- **创建省市区实体(AreaEntity)**: 标准化管理省市区三级数据
- **Location实体关联Area**: 通过province、city、district字段关联AreaEntity
- **预置完整数据**: 使用现有的省市区CSV文件初始化数据
- **支持三级联动**: 前端组件支持省市区联动选择

**省市区实体设计**:
```
省市区 (Area)
├── ID (id) - 主键
├── 父级ID (parentId) - 关联父级区域，0表示顶级（省/直辖市）
├── 名称 (name) - 区域名称
├── 层级 (level) - 1:省/直辖市, 2:市, 3:区/县
├── 代码 (code) - 行政区划代码
├── 创建时间 (createdAt)
└── 更新时间 (updatedAt)
```

**数据来源和使用**:
- **数据文件**: `scripts/省市区.csv` (包含3282条完整记录)
- **生成脚本**: `scripts/generate-area-sql.mjs` (CSV转SQL导入脚本)
- **初始化**: 通过数据库迁移预置完整的省市区数据
- **更新机制**: 支持后续行政区划变更的增量更新

**地点实体优化**:
```
地点 (Location)
├── 名称 (name)
├── 省份 (province) → 关联AreaEntity (level=1)
├── 城市 (city) → 关联AreaEntity (level=2)
├── 区县 (district) → 关联AreaEntity (level=3)
├── 详细地址 (address)
├── 纬度 (latitude)
└── 经度 (longitude)
```

**省市区查询逻辑设计**:
- **获取省份列表**: 查询level=1的区域
- **获取城市列表**: 根据省份ID查询level=2的子区域
- **获取区县列表**: 根据城市ID查询level=3的子区域
- **地点关联查询**: 通过省市区ID精确关联地点

**API设计示例**:
```typescript
// 获取省份列表
GET /api/v1/areas/provinces

// 获取城市列表
GET /api/v1/areas/cities?provinceId=1

// 获取区县列表
GET /api/v1/areas/districts?cityId=34

// 地点查询（支持省市区筛选）
GET /api/v1/locations?provinceId=1&cityId=34&districtId=36
```

**优势**:
- **数据标准化**: 统一的省市区数据源，避免数据不一致
- **查询优化**: 支持精确的省市区筛选和关联查询
- **用户体验**: 前端组件支持省市区三级联动选择
- **扩展性**: 支持行政区划变更和新增区域
- **维护性**: 集中管理省市区数据，便于更新和维护

### 查询逻辑设计
基于优化的数据模型，查询逻辑需要相应调整：

**地点查询**:
- 支持按省份、城市、区县多维度查询地点
- 支持地点名称模糊搜索
- 支持按地点类型筛选（场馆、车站、地标等）

**路线查询**:
- 通过地点关联查询路线
- 路线类型动态判断：目的地=活动地点为去程，出发地=活动地点为返程
- 支持按省市区范围查询路线
- **组合查询支持**：支持车型和出行方式的组合筛选
  - 大巴拼车：`vehicleType=bus&travelMode=carpool`
  - 商务车：`vehicleType=business&travelMode=carpool,charter`
  - 包车：`vehicleType=bus,business&travelMode=charter`

**活动查询**:
- 通过路线间接查询关联的活动
- 用户选择出发地、目的地、日期时，系统：
  1. 查询匹配的地点
  2. 通过地点找到关联的路线（支持组合查询条件）
  3. 根据路线找到关联的活动
  4. 展示去重后的活动列表
- **组合查询支持**：活动查询基于路线组合条件进行筛选

**API设计示例**:
```typescript
// 查询地点（支持省市区筛选）
GET /api/v1/locations?province=北京市&city=北京市&name=工人体育场

// 查询路线（支持组合查询）
GET /api/v1/routes?startLocationId=123&endLocationId=456&date=2025-10-15&type=departure&vehicleType=bus,business&travelMode=carpool,charter

// 响应：路线列表，包含完整的地点信息和活动信息
{
  routes: [
    {
      id: 1,
      startLocation: {
        id: 123,
        name: "中关村",
        province: "北京市",
        city: "北京市",
        district: "海淀区"
      },
      endLocation: {
        id: 456,
        name: "工人体育场",
        province: "北京市",
        city: "北京市",
        district: "朝阳区"
      },
      vehicleType: "bus",
      travelMode: "carpool",
      activity: {
        id: 1,
        name: "中超联赛北京国安主场赛事",
        venueLocation: {
          id: 456,
          name: "工人体育场",
          province: "北京市",
          city: "北京市",
          district: "朝阳区"
        }
      }
    }
  ]
}
```

### API接口设计
需要新增以下API端点：

**管理后台API**:
- `GET /api/v1/admin/locations` - 地点管理列表
- `POST /api/v1/admin/locations` - 创建地点
- `PUT /api/v1/admin/locations/:id` - 更新地点
- `DELETE /api/v1/admin/locations/:id` - 删除地点
- `GET /api/v1/admin/activities` - 活动管理列表
- `POST /api/v1/admin/activities` - 创建活动
- `PUT /api/v1/admin/activities/:id` - 更新活动
- `DELETE /api/v1/admin/activities/:id` - 删除活动
- `GET /api/v1/admin/routes` - 路线管理列表
- `POST /api/v1/admin/routes` - 创建路线
- `PUT /api/v1/admin/routes/:id` - 更新路线
- `DELETE /api/v1/admin/routes/:id` - 删除路线

**用户端API**:
- `GET /api/v1/locations` - 地点查询（支持省份、城市、区县、名称等参数）
- `GET /api/v1/routes` - 路线查询（支持出发地、目的地、日期、类型等参数，返回包含活动信息的路线列表）
  - **组合查询参数**：
    - `vehicleType`：车型筛选，支持多值（如`bus,business`）
    - `travelMode`：出行方式筛选，支持多值（如`carpool,charter`）
    - 支持三种组合查询模式：大巴拼车、商务车、包车
- `GET /api/v1/activities` - 活动列表查询（基础信息查询）
- `POST /api/v1/orders` - 创建订单
- `GET /api/v1/orders` - 订单列表
- `GET /api/v1/orders/:id` - 订单详情
- `PUT /api/v1/orders/:id/cancel` - 取消订单
- `POST /api/v1/passengers` - 添加乘客
- `GET /api/v1/passengers` - 乘客列表
- `PUT /api/v1/passengers/:id` - 更新乘客
- `DELETE /api/v1/passengers/:id` - 删除乘客

### 前端页面迁移策略
页面迁移任务已分配到各个用户故事中，确保每个页面迁移与对应的业务功能同步开发：
- **US005-01**: 活动管理页面、路线管理页面、班次管理页面（管理后台）
- **US005-02**: 首页、活动选择、班次列表页面
- **US005-03**: 样式迁移合规性修复（所有迁移页面）
- **US005-04**: 车型和出行方式配置增强（管理后台路线配置页面、小程序首页、班次列表页面、订单详情页面）
- **US005-05**: 乘客信息管理页面（管理后台）
- **US005-06**: 添加乘客页面
- **US005-07**: 订单管理页面（管理后台）
- **US005-08**: 下单页面、支付成功页面
- **US005-09**: 订单列表、订单详情页面
- **US005-10**: 我的页面

## 依赖关系

### 前置依赖
- Epic 001: 测试基础设施 ✅
- Epic 002: 用户管理增强 ✅
- Epic 003: Lint配置 ✅
- Epic 004: API实际请求测试 ✅

### 后续依赖
- Epic 006: 前端页面迁移和基础框架
- Epic 007: 用户认证和基础管理
- Epic 008: 管理后台系统

## 风险评估

### 技术风险
- **微信支付集成**: 需要申请微信支付商户号和配置证书
- **数据迁移**: mini-demo模拟数据需要转换为真实数据
- **性能优化**: 订单状态自动更新需要定时任务支持

### 业务风险
- **支付流程**: 需要确保支付流程的稳定性和安全性
- **用户体验**: 页面迁移可能影响原有用户体验
- **数据一致性**: 订单快照机制需要确保数据完整性

## 测试策略

### 单元测试
- 订单业务逻辑测试
- 支付状态流转测试
- 乘客信息验证测试

### 集成测试
- API端点集成测试
- 微信支付集成测试
- 数据库操作测试

### E2E测试
- 完整出行流程测试（查询→下单→支付→完成）
- 异常场景测试（支付失败、取消订单等）

## 验收标准

### 功能验收
- [ ] 用户能够完成完整的出行服务流程
- [ ] 订单数据正确存储和展示
- [ ] 支付功能正常集成
- [ ] 乘客信息管理功能完整

### 性能验收
- [ ] 页面加载时间 < 2秒
- [ ] API响应时间 < 500ms
- [ ] 支付成功率 > 98%

### 质量验收
- [ ] 核心业务逻辑测试覆盖率 > 80%
- [ ] 无重大安全漏洞
- [ ] 代码符合编码规范

## 下一步行动

1. **立即开始**: 创建出行服务数据模型实体
2. **并行开发**: 后端API开发和前端页面迁移
3. **集成测试**: 微信支付集成和端到端测试
4. **用户验收**: MVP功能演示和用户反馈收集

---

**文档状态**: 已更新
**最后更新**: 2025-10-25
**下次评审**: 2025-11-01