Просмотр исходного кода

📝 docs(story): 更新故事005.002文档,集成故事5.1已实现功能

- 更新验收标准,从固定活动类型改为动态路线类型判断
- 添加省市区三级联动和地点搜索支持
- 集成故事5.1已实现的用户端路线查询API
- 添加前端组件开发任务:AreaCascader、LocationSearch、RouteFilter
- 完善测试策略,添加省市区三级联动和路线类型动态判断测试

🤖 Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 3 месяцев назад
Родитель
Сommit
51a461d602
1 измененных файлов с 118 добавлено и 53 удалено
  1. 118 53
      docs/stories/005.002.story.md

+ 118 - 53
docs/stories/005.002.story.md

@@ -10,9 +10,11 @@ Draft
 
 ## Acceptance Criteria
 1. 支持按出发地、目的地、日期查询路线
-2. 支持筛选去程活动/返程活动
+2. 支持筛选去程路线/返程路线(基于路线与活动地点的关系动态判断)
 3. 显示路线详细信息(上车点、下车点、出发时间、车型、价格)
 4. 支持按价格、出发时间排序
+5. 支持省市区三级联动选择出发地和目的地
+6. 通过路线查询关联的活动信息,展示去重后的活动列表
 
 ## 页面迁移任务 (从mini-demo迁移)
 - [ ] 迁移首页 (mini-demo/pages/home/home) - 路线查询入口页面
@@ -32,29 +34,46 @@ Draft
   - [ ] **注意:MVP阶段不实现司机当前位置显示**
 
 ## Tasks / Subtasks
-- [ ] 实现路线查询API使用通用CRUD (AC: 1, 3, 4)
-  - [ ] 在 `src/server/api/routes/index.ts` 使用 `createCrudRoutes` 创建通用CRUD路由
-  - [ ] 配置搜索字段:startPoint, endPoint, vehicleType
-  - [ ] 配置排序字段:price, departureTime
-  - [ ] 使用filters参数支持日期范围查询
-- [ ] 实现活动查询API使用通用CRUD (AC: 2)
-  - [ ] 在 `src/server/api/activities/index.ts` 使用 `createCrudRoutes` 创建通用CRUD路由
-  - [ ] 配置搜索字段:name, description
-  - [ ] 配置筛选字段:type (去程活动/返程活动)
-- [ ] 实现前端页面迁移 (从mini-demo迁移) (AC: 1, 2, 3, 4)
+- [ ] 集成用户端路线查询API (AC: 1, 2, 3, 4, 6)
+  - [ ] 使用故事5.1已实现的用户端路线查询API:`GET /api/v1/routes/search`
+  - [ ] 支持查询参数:startLocationId, endLocationId, date, routeType, sortBy, sortOrder
+  - [ ] 返回包含关联活动信息的路线列表
+  - [ ] 支持去程/返程路线动态筛选(基于路线与活动地点的关系)
+- [ ] 实现省市区三级联动组件 (AC: 5)
+  - [ ] 在 `mini/src/components/` 创建 `AreaCascader.tsx` 组件
+  - [ ] 集成故事5.1已实现的省市区API:`/api/v1/areas/provinces`, `/api/v1/areas/cities`, `/api/v1/areas/districts`
+  - [ ] 支持省市区三级联动选择
+  - [ ] 在首页出发地/目的地选择器中集成省市区组件
+- [ ] 实现地点搜索组件 (AC: 1, 5)
+  - [ ] 在 `mini/src/components/` 创建 `LocationSearch.tsx` 组件
+  - [ ] 集成故事5.1已实现的地点查询API:`GET /api/v1/locations`
+  - [ ] 支持按省市区筛选地点
+  - [ ] 支持地点名称模糊搜索
+- [ ] 实现前端页面迁移 (从mini-demo迁移) (AC: 1, 2, 3, 4, 5, 6)
   - [ ] 迁移首页 - 基于 `mini-demo/pages/home/home` 在 `mini/src/pages/home/` 创建 `HomePage.tsx`
+    - [ ] 集成省市区三级联动选择出发地和目的地
+    - [ ] 集成地点搜索组件选择具体地点
+    - [ ] 日期选择器
+    - [ ] 查询表单提交
   - [ ] 迁移活动选择页面 - 基于 `mini-demo/pages/select-activity/select-activity` 在 `mini/src/pages/select-activity/` 创建 `ActivitySelectPage.tsx`
+    - [ ] 展示去重后的活动列表(通过路线查询关联的活动)
+    - [ ] 支持去程/返程路线筛选
+    - [ ] 活动卡片展示(图片、名称、时间、地点、匹配点)
   - [ ] 迁移班次列表页面 - 基于 `mini-demo/pages/schedule-list/schedule-list` 在 `mini/src/pages/schedule-list/` 创建 `ScheduleListPage.tsx`
-  - [ ] 集成查询表单和结果展示
-  - [ ] 使用React Query调用通用CRUD API
-- [ ] 实现前端活动筛选组件 (AC: 2)
-  - [ ] 在 `mini/src/components/` 创建 `ActivityFilter.tsx` 组件
-  - [ ] 支持活动类型筛选
-- [ ] 编写单元测试、集成测试和E2E测试 (AC: 1, 2, 3, 4)
-  - [ ] 为通用CRUD路由编写集成测试 (`tests/integration/server/`)
-  - [ ] 为前端组件编写单元测试 (`tests/unit/client/`)
-  - [ ] 为查询功能编写集成测试 (`tests/integration/client/`)
+    - [ ] 路线列表展示(上车点、下车点、出发时间、车型、价格)
+    - [ ] 排序功能(价格、出发时间)
+    - [ ] 筛选功能
+- [ ] 实现前端路线筛选组件 (AC: 2)
+  - [ ] 在 `mini/src/components/` 创建 `RouteFilter.tsx` 组件
+  - [ ] 支持路线类型筛选(去程/返程)
+  - [ ] 支持车型筛选
+- [ ] 编写单元测试、集成测试和E2E测试 (AC: 1, 2, 3, 4, 5, 6)
+  - [ ] 为前端组件编写单元测试 (`mini/tests/components/`)
+  - [ ] 为查询功能编写集成测试 (`mini/tests/pages/`)
   - [ ] 编写完整出行流程的E2E测试 (`tests/e2e/travel-flow/`)
+    - [ ] 首页查询 → 活动选择 → 班次列表完整流程
+    - [ ] 省市区三级联动功能测试
+    - [ ] 路线类型动态判断逻辑测试
 
 ## Dev Notes
 
@@ -68,25 +87,42 @@ Draft
 - **首页焦点图使用固定静态图** - 轮播图组件保留,但数据使用固定的一张静态图片(不从API获取轮播图数组)
 
 ### 数据模型依赖
-- **Route实体**: 已在Story 5.1中创建,包含上车点、下车点、出发时间、车型、价格等字段
-- **Activity实体**: 已在Story 5.1中创建,包含活动名称、描述、类型(去程/返程)、开始日期、结束日期等字段
-- **关系**: 一个活动关联多条路线 [Source: architecture/data-model-schema-changes.md#数据关系]
+- **Route实体**: 已在Story 5.1中创建,包含startLocation、endLocation、pickupPoint、dropoffPoint、departureTime、vehicleType、price、seatCount等字段
+- **Activity实体**: 已在Story 5.1中创建,包含name、description、venueLocation、startDate、endDate等字段
+- **Location实体**: 已在Story 5.1中创建,包含name、province、city、district、address、latitude、longitude等字段
+- **Area实体**: 已在Story 5.1中创建,包含name、parentId、level、code等字段,支持省市区三级数据管理
+- **关系**:
+  - 一个活动关联多条路线
+  - 路线动态判断类型:目的地=活动地点为去程,出发地=活动地点为返程
+  - 地点关联省市区实体,支持标准化行政区划管理
 
 ### API规范
-- **通用CRUD路由**: 使用 `createCrudRoutes` 创建标准CRUD API [Source: src/server/utils/generic-crud.routes.ts]
-- **路线查询端点**: `GET /api/v1/routes` 支持查询参数:page, pageSize, keyword, sortBy, sortOrder, filters [Source: src/server/utils/generic-crud.routes.ts#L23]
-- **活动查询端点**: `GET /api/v1/activities` 支持查询参数:page, pageSize, keyword, sortBy, sortOrder, filters [Source: src/server/utils/generic-crud.routes.ts#L23]
+- **用户端路线查询API**: 使用故事5.1已实现的 `GET /api/v1/routes/search`
+  - 查询参数:startLocationId, endLocationId, date, routeType, sortBy, sortOrder
+  - 返回格式:包含路线列表和关联活动信息
+  - 支持去程/返程路线动态筛选
+- **省市区API**: 使用故事5.1已实现的省市区三级联动API
+  - `GET /api/v1/areas/provinces` - 获取省份列表
+  - `GET /api/v1/areas/cities?provinceId=1` - 获取城市列表
+  - `GET /api/v1/areas/districts?cityId=34` - 获取区县列表
+- **地点查询API**: 使用故事5.1已实现的 `GET /api/v1/locations`
+  - 查询参数:provinceId, cityId, districtId, keyword
+  - 支持按省市区筛选和名称模糊搜索
 - **分页响应**: 使用标准分页格式 [Source: architecture/data-model-schema-changes.md#分页响应接口]
-- **通用CRUD服务**: 使用 `ConcreteCrudService` 作为基础服务类 [Source: src/server/utils/concrete-crud.service.ts]
 
 ### 文件位置
-- **API路由**: `src/server/api/routes/index.ts`, `src/server/api/activities/index.ts` [Source: architecture/source-tree.md#实际项目结构]
+- **用户端API路由**: `src/server/api/routes/index.ts` (包含用户端路线查询API) [Source: architecture/source-tree.md#实际项目结构]
+- **省市区API路由**: `src/server/api/areas/index.ts` (故事5.1已实现) [Source: architecture/source-tree.md#实际项目结构]
+- **地点API路由**: `src/server/api/locations/index.ts` (故事5.1已实现) [Source: architecture/source-tree.md#实际项目结构]
 - **前端页面**:
   - `mini/src/pages/home/HomePage.tsx` (首页)
   - `mini/src/pages/select-activity/ActivitySelectPage.tsx` (活动选择页面)
   - `mini/src/pages/schedule-list/ScheduleListPage.tsx` (班次列表页面) [Source: architecture/source-tree.md#实际项目结构]
-- **前端组件**: `mini/src/components/ActivityFilter.tsx` [Source: architecture/source-tree.md#实际项目结构]
-- **共享类型**: `src/share/route.types.ts`, `src/share/activity.types.ts` [Source: architecture/source-tree.md#实际项目结构]
+- **前端组件**:
+  - `mini/src/components/AreaCascader.tsx` (省市区三级联动组件)
+  - `mini/src/components/LocationSearch.tsx` (地点搜索组件)
+  - `mini/src/components/RouteFilter.tsx` (路线筛选组件) [Source: architecture/source-tree.md#实际项目结构]
+- **共享类型**: `src/share/route.types.ts`, `src/share/activity.types.ts`, `src/share/location.types.ts`, `src/share/area.types.ts` [Source: architecture/source-tree.md#实际项目结构]
 
 ### 技术栈要求
 - **后端框架**: Hono + TypeORM [Source: architecture/tech-stack.md#现有技术栈维护]
@@ -99,12 +135,30 @@ Draft
 - **样式开发**: 遵循 [Tailwind CSS样式规范](../architecture/tailwind-css-standards.md)
 - **迁移指导**: 参考 [mini-demo迁移指导规范](../architecture/mini-demo-migration-guide.md)(包含精确样式迁移)
 
-### 通用CRUD使用模式
-- **路由创建**: 使用 `createCrudRoutes` 函数创建标准CRUD路由 [Source: src/server/api/users/index.ts#L9]
-- **搜索配置**: 配置 `searchFields` 支持关键词搜索 [Source: src/server/api/users/index.ts#L15]
-- **关联关系**: 配置 `relations` 字段加载关联数据 [Source: src/server/api/users/index.ts#L16]
-- **认证中间件**: 使用 `authMiddleware` 保护路由 [Source: src/server/api/users/index.ts#L17]
-- **前端调用**: 使用React Query调用通用CRUD API,支持分页、搜索、排序
+### 前端API调用模式
+- **用户端路线查询**: 使用React Query调用用户端路线查询API
+  ```typescript
+  const { data, isLoading } = useQuery({
+    queryKey: ['routes', searchParams],
+    queryFn: async () => {
+      const res = await routeClient.search.$get({
+        query: {
+          startLocationId: searchParams.startLocationId,
+          endLocationId: searchParams.endLocationId,
+          date: searchParams.date,
+          routeType: searchParams.routeType,
+          sortBy: searchParams.sortBy,
+          sortOrder: searchParams.sortOrder
+        }
+      });
+      if (res.status !== 200) throw new Error('查询失败');
+      return await res.json();
+    }
+  });
+  ```
+- **省市区查询**: 使用React Query调用省市区三级联动API
+- **地点搜索**: 使用防抖搜索优化地点查询性能
+- **认证中间件**: 所有用户端API使用 `authMiddleware` 进行认证保护
 
 ### 安全要求
 - **API认证**: 所有路线和活动查询API必须使用 `authMiddleware` 进行认证保护
@@ -147,31 +201,42 @@ Draft
 - **覆盖率目标**: 核心业务逻辑 > 80% [Source: architecture/testing-strategy.md#覆盖率目标]
 
 **具体测试要求**:
-- 路线查询API的单元测试 (`tests/unit/server/routes/`) 和集成测试 (`tests/integration/server/routes/`)
+- **用户端路线查询API测试** (故事5.1已实现,需要验证集成)
   - 正常查询场景:按出发地、目的地、日期查询
-  - 边界条件:空查询结果、日期范围查询、分页查询
+  - 路线类型动态判断:验证去程/返程路线筛选逻辑
+  - 关联活动查询:验证通过路线查询关联的活动信息
   - 排序功能:按价格、出发时间排序
-  - 错误场景:无效参数、认证失败、权限不足
-- 活动查询API的单元测试 (`tests/unit/server/activities/`) 和集成测试 (`tests/integration/server/activities/`)
-  - 正常筛选场景:按活动类型(去程/返程)筛选
-  - 边界条件:无活动数据、活动状态筛选
-  - 关联查询:活动关联的路线数据
-  - 错误场景:无效类型参数、认证失败
-- 前端组件的单元测试 (`mini/tests/components/`)
-  - 组件渲染:首页、活动选择、班次列表页面
-  - 用户交互:查询表单提交、筛选条件变更
-  - 状态管理:查询结果展示、加载状态处理
-- 查询功能的集成测试 (`mini/tests/pages/`)
-  - 完整查询流程:首页查询 → 活动筛选 → 班次列表
+  - 边界条件:空查询结果、日期范围查询
+- **省市区三级联动测试**
+  - 省份列表获取和展示
+  - 城市列表根据省份动态加载
+  - 区县列表根据城市动态加载
+  - 完整省市区选择流程
+- **地点搜索组件测试**
+  - 按省市区筛选地点
+  - 地点名称模糊搜索
+  - 防抖搜索性能优化
+  - 地点选择交互
+- **前端组件单元测试** (`mini/tests/components/`)
+  - AreaCascader组件:省市区三级联动功能
+  - LocationSearch组件:地点搜索和选择功能
+  - RouteFilter组件:路线类型和车型筛选
+  - 页面组件:首页、活动选择、班次列表页面
+- **查询功能集成测试** (`mini/tests/pages/`)
+  - 完整查询流程:首页查询 → 活动选择 → 班次列表
+  - 省市区三级联动与地点搜索集成
+  - 路线类型动态筛选集成
   - 数据一致性:前端展示与后端数据一致
-  - 错误处理:网络错误、API错误处理
-- 完整出行流程的E2E测试 (`tests/e2e/travel-flow/`)
-  - 用户登录 → 路线查询 → 活动筛选 → 查看班次列表
+- **完整出行流程E2E测试** (`tests/e2e/travel-flow/`)
+  - 用户登录 → 省市区选择 → 地点搜索 → 路线查询 → 活动筛选 → 班次列表
+  - 路线类型动态判断逻辑验证
+  - 省市区三级联动功能验证
   - 边界场景:无数据、大量数据、并发查询
 
 ## Change Log
 | Date | Version | Description | Author |
 |------|---------|-------------|--------|
+| 2025-10-18 | 2.0 | 更新数据模型概念,集成故事5.1已实现功能,添加省市区三级联动和动态路线类型判断 | John (PM) |
 | 2025-10-16 | 1.8 | 移除基础数据实体任务,迁移到Story 5.1 | Bob (Scrum Master) |
 | 2025-10-15 | 1.7 | 修正Taro测试位置,统一使用mini/tests/目录 | Winston (Architect) |
 | 2025-10-15 | 1.6 | 修正前端页面路径从src/client到mini/src目录 | Bob (Scrum Master) |