epic-005-travel-service-core.md 40 KB

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,businesstravelMode=carpool,charter

界面修改任务:

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

API修改任务:

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

API查询参数设计:

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

US005-05: 乘客信息查看(管理后台)

作为 系统管理员 我希望 能够查看所有用户的乘客信息 以便 了解用户乘车人情况和进行数据统计

验收标准:

  • 支持查看所有乘客信息列表
  • 支持按用户筛选乘客信息
  • 显示乘客基本信息(姓名、证件类型、证件号码、手机号)
  • 支持导出乘客数据

管理后台页面任务:

  • 乘客信息管理页面 - 查看所有乘客信息

US005-06: 乘客信息管理

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

验收标准:

  • 支持添加、编辑、删除乘客信息
  • 支持设置默认乘客
  • 验证乘客信息完整性(姓名、证件类型、证件号码、手机号)
  • 支持多种证件类型(身份证、港澳通行证、护照等)

页面迁移任务:

  • 迁移添加乘客页面 (add-passenger/add-passenger) - 乘客信息管理页面

US005-07: 订单信息查看(管理后台)

作为 系统管理员 我希望 能够查看所有订单信息和状态 以便 监控订单流程和处理异常订单

验收标准:

  • 支持查看所有订单列表
  • 支持按订单状态筛选(待支付、待出发、行程中、已完成、已取消)
  • 显示订单详细信息(用户信息、路线信息、乘客信息、金额、状态)
  • 支持订单状态统计和报表

管理后台页面任务:

  • 订单管理页面 - 查看所有订单信息

US005-08: 订单创建和支付

作为 出行用户 我希望 能够创建订单并完成支付 以便 确认出行安排

验收标准:

  • 选择路线和乘客后创建订单
  • 计算订单总金额
  • 集成微信支付完成支付流程
  • 支付成功后更新订单状态
  • 保存订单快照信息(路线快照、乘客快照)

页面迁移任务:

  • 迁移下单页面 (order/order) - 订单创建页面
  • 迁移支付成功页面 (pay-success/pay-success) - 支付结果页面

US005-09: 订单状态管理

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

验收标准:

  • 查看订单列表(待支付、待出发、行程中、已完成、已取消)
  • 查看订单详情信息
  • 支持取消订单(在允许的时间范围内)
  • 订单状态自动更新(待出发→行程中→已完成)

页面迁移任务:

  • 迁移订单列表页面 (orders/orders) - 订单管理页面
  • 迁移订单详情页面 (order-detail/order-detail) - 订单详情查看页面

US005-10: 个人中心管理

作为 出行用户 我希望 能够查看和管理我的个人信息 以便 方便地管理我的出行服务

验收标准:

  • 查看个人基本信息(头像、用户名、邮箱、注册时间)
  • 头像上传和更新功能
  • 快速访问基础功能(编辑资料、乘客管理、设置)
  • 退出登录功能
  • 账号信息展示(用户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: 支付集成

作为 系统 我希望 集成微信支付功能 以便 支持用户完成订单支付

验收标准:

  • 实现微信支付JSAPI集成 - 已使用 wechatpay-node-v3 SDK 完整实现
  • 处理支付回调通知 - 已实现签名验证、数据解密和状态更新
  • 支付状态与订单状态同步 - 已实现完整的订单状态流转机制
  • 支付异常处理(超时、失败、重复支付) - 已实现错误处理和状态管理
  • 支付安全验证 - 已实现签名验证、金额一致性检查、防重放攻击
  • 支付状态查询 - 已提供支付状态查询接口
  • 前端微信支付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 字段
  • 状态管理: 订单页面显示手机号获取状态和验证状态

前端实现细节:

// 订单确认页面手机号获取逻辑
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设计:

// 手机号解密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 以便 便捷使用出行服务,无需手动输入账号密码

验收标准:

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

技术实现方案:

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

前端实现细节:

// 微信小程序登录页面登录逻辑
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设计:

// 小程序自动登录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错误、网络错误、用户创建失败等

用户实体扩展:

// 在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参数支持大量数据查询

前端实现细节(基于实际代码结构):

// 订单导出功能实现 - 基于实际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格式)
  • 筛选支持: 支持订单状态、支付状态筛选
  • 数据关联: 已包含 userroute 关联数据
  • 分页能力: 支持大pageSize查询(最大10000条)

管理后台页面任务:

  • 在订单管理页面添加导出按钮(位于搜索区域)
  • 实现导出功能组件(集成到现有Orders.tsx中)
  • 添加导出进度显示和状态管理
  • 支持按当前筛选条件导出
  • 优化大量数据导出性能

技术实现任务:

  • xlsx库依赖: 已安装(web/package.json:118行)
  • 实现订单数据导出组件
  • 后端API: 已支持大量数据查询
  • 权限验证: 已通过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设计示例:

// 获取省份列表
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设计示例:

// 查询地点(支持省市区筛选)
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