Sfoglia il codice sorgente

📝 docs(stories): 更新故事006.015状态为已批准

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 1 mese fa
parent
commit
0f32d4b87d
1 ha cambiato i file con 190 aggiunte e 0 eliminazioni
  1. 190 0
      docs/stories/006.015.parent-goods-list-filter.story.md

+ 190 - 0
docs/stories/006.015.parent-goods-list-filter.story.md

@@ -0,0 +1,190 @@
+# Story 006.015: 商品管理列表父子商品筛选优化
+
+## Status
+Approved
+
+## Story
+**As a** 系统管理员,
+**I want** 在商品管理列表中默认只显示父商品,并能通过筛选器切换查看所有商品,
+**so that** 商品列表保持整洁,避免子商品(只有规格信息)造成的混乱
+
+## Acceptance Criteria
+1. 商品管理UI的商品列表默认加载时只显示父商品(spuId=0)
+2. 在商品列表搜索区域添加一个筛选器选项:"显示所有商品"和"只显示父商品"
+3. 筛选器默认选中"只显示父商品"
+4. 切换筛选器时实时刷新商品列表
+5. **验收标准**:管理员能方便地在完整视图和父商品视图之间切换,默认视图整洁有序
+
+## Tasks / Subtasks
+- [ ] **分析现有商品管理UI结构和API支持** (AC: 1, 2, 3, 4, 5)
+  - [ ] 检查GoodsManagement组件中的商品列表查询逻辑
+  - [ ] 确认shared-crud的filters参数使用方式
+  - [ ] 分析现有搜索表单结构,确定筛选器添加位置
+  - [ ] 确定筛选器组件类型(RadioGroup最合适)
+
+- [ ] **实现默认过滤逻辑** (AC: 1)
+  - [ ] 修改商品列表查询,默认传递`filters: '{"spuId": 0}'`
+  - [ ] 确保默认过滤不影响其他查询参数(搜索、分页等)
+  - [ ] 验证默认过滤的正确性:只显示父商品(spuId=0)和单规格商品
+
+- [ ] **实现父商品筛选器组件** (AC: 2, 3)
+  - [ ] 在商品列表搜索区域添加筛选器UI组件
+  - [ ] 筛选器选项:"显示所有商品"、"只显示父商品"
+  - [ ] 默认选中"只显示父商品"
+  - [ ] 使用RadioGroup组件实现单选按钮
+  - [ ] 添加筛选器标签和说明文字
+
+- [ ] **实现筛选状态管理和列表刷新** (AC: 4)
+  - [ ] 将筛选器状态添加到searchParams状态中(filter字段)
+  - [ ] 修改商品列表查询逻辑,filter为'parent'时传递`filters: '{"spuId": 0}'`,filter为'all'时不传递filters参数
+  - [ ] 实现筛选器切换时实时刷新商品列表
+  - [ ] 确保筛选器与其他搜索参数协同工作
+
+- [ ] **更新商品列表显示优化** (AC: 5)
+  - [ ] 在商品列表中添加父子关系标识(如徽章、图标)
+  - [ ] 父商品显示子商品数量信息
+  - [ ] 子商品(当显示所有商品时)显示父商品名称
+  - [ ] 优化商品列表表格列,使其更清晰
+
+- [ ] **更新现有集成测试** (AC: 1, 2, 3, 4, 5)
+  - [ ] 在现有商品管理集成测试中添加筛选器功能测试用例
+  - [ ] 测试默认过滤逻辑:默认只显示父商品
+  - [ ] 测试筛选器状态管理和列表刷新
+  - [ ] 测试父子商品标识显示
+
+## Dev Notes
+
+### 技术栈信息 [Source: architecture/tech-stack.md]
+- **运行时**: Node.js 20.18.3
+- **框架**: Hono 4.8.5 (Web框架和API路由,RPC类型安全)
+- **前端框架**: React 19.1.0 (用户界面构建)
+- **数据库**: PostgreSQL 17 (通过TypeORM进行数据持久化存储)
+- **ORM**: TypeORM 0.3.25 (数据库操作抽象,实体管理)
+- **样式**: Tailwind CSS 4.1.11 (原子化CSS框架)
+- **状态管理**: React Query 5.83.0 (服务端状态管理)
+- **测试框架**: Vitest 2.x (单元测试框架,更好的TypeORM支持)
+- **API测试**: hono/testing (内置,API端点测试,更好的类型安全)
+
+### 项目结构信息 [Source: architecture/source-tree.md]
+- **包管理**: 使用pnpm workspace管理多包依赖关系
+- **多租户架构**: 所有操作必须包含tenantId过滤,父子商品必须在同一租户下
+- **商品管理UI包**: `packages/goods-management-ui-mt/` (`@d8d/goods-management-ui-mt`)
+- **主要组件**: `src/components/GoodsManagement.tsx`
+- **API客户端**: `packages/goods-management-ui-mt/src/api/goodsClient.ts`
+- **共享UI组件**: `@d8d/shared-ui-components` (shadcn/ui组件库,46+基础组件)
+
+### 现有代码分析
+1. **商品管理组件**: `packages/goods-management-ui-mt/src/components/GoodsManagement.tsx`
+   - 使用React Query进行数据获取(第81-94行)
+   - 搜索参数状态:`searchParams`包含page、limit、search(第38行)
+   - API调用:`goodsClientManager.get().index.$get`(第84-90行)
+   - 搜索表单:第290-305行,包含搜索输入框和搜索按钮
+
+2. **管理员商品API**: `packages/goods-module-mt/src/routes/admin-goods-routes.mt.ts`
+   - 使用shared-crud创建路由,`listFilters: {}`(第34行)
+   - 根据故事4(006.004)的实现,API已支持spuId查询参数过滤
+   - 管理员API默认不过滤,但支持通过查询参数过滤
+
+3. **shared-crud筛选参数**:
+   - **filters参数**: JSON字符串格式,支持精确匹配、范围查询等
+   - **特殊处理**: 如果用户显式传入`spuId: null`,则移除spuId过滤(可以显示所有商品)
+   - **优先级**: 用户传入的filters会覆盖默认的listFilters
+   - **实现位置**: `packages/shared-crud/src/routes/generic-crud.routes.ts`第286-305行
+
+4. **父子商品状态定义**:
+   - `spuId = 0`: 父商品或单规格商品
+   - `spuId > 0`: 子商品,值为父商品的ID
+   - 默认过滤条件:`spuId = 0`
+
+### 技术约束
+- **租户隔离**: 所有查询必须包含tenantId过滤
+- **API兼容性**: 保持现有API行为不变,仅通过查询参数扩展功能
+- **性能考虑**: 商品列表查询已添加spuId字段索引(故事4中已实现)
+- **简化实现**: 不需要状态持久化,不需要修改现有API接口
+
+### 实现方案
+1. **利用现有filters参数**: shared-crud已支持`filters`查询参数(JSON字符串格式)
+2. **筛选器状态映射**:
+   - "只显示父商品" → `filters: '{"spuId": 0}'`(过滤只显示父商品)
+   - "显示所有商品" → 不传递filters参数(显示所有商品,包括父子商品)
+3. **筛选器组件**: 使用简单的RadioGroup提供两个选项
+   - 选项1: "显示所有商品"(值: "all")
+   - 选项2: "只显示父商品"(值: "parent",默认)
+4. **状态管理**: 扩展`searchParams`状态,添加filter字段('parent' | 'all')
+5. **API调用修改**:
+   ```typescript
+   const query = {
+     page: searchParams.page,
+     pageSize: searchParams.limit,
+     keyword: searchParams.search,
+     // 根据筛选器状态决定是否传递filters参数
+     ...(searchParams.filter === 'parent' && { filters: '{"spuId": 0}' })
+   }
+   ```
+6. **无需修改接口**: 完全利用现有shared-crud功能,无需后端修改
+7. **简化优势**: 管理员API的`listFilters: {}`为空,不传递filters参数即可显示所有商品
+
+### 测试策略
+- **集成测试**: 在现有商品管理集成测试中添加筛选器功能测试用例
+- **测试重点**: 验证默认过滤逻辑、筛选器状态切换、父子商品标识显示
+- **边界测试**: 测试空列表、网络错误等场景
+
+### 集成点
+1. **商品模块集成**: 使用现有的商品API和spuId查询参数支持
+2. **UI组件集成**: 使用shadcn/ui的RadioGroup、Label等组件
+3. **状态管理集成**: 与现有React Query状态管理集成
+4. **租户上下文集成**: 确保所有查询包含租户过滤
+
+## Testing
+### 测试标准 [Source: architecture/testing-strategy.md]
+- **测试文件位置**: `packages/goods-management-ui-mt/tests/` 目录下
+- **单元测试位置**: `tests/unit/**/*.test.{ts,tsx}`
+- **集成测试位置**: `tests/integration/**/*.test.{ts,tsx}`
+- **测试框架**: Vitest + Testing Library + hono/testing + shared-test-util
+- **测试要求**: 在现有集成测试中添加筛选器功能测试用例
+- **测试模式**: 使用测试数据工厂模式,避免硬编码测试数据
+
+### 测试策略要求
+- **集成测试**: 在现有商品管理集成测试中添加筛选器功能测试
+- **测试重点**: 验证默认过滤只显示父商品、筛选器切换功能、父子商品标识显示
+- **边界测试**: 测试空结果、网络错误等场景
+
+## Change Log
+| Date | Version | Description | Author |
+|------|---------|-------------|--------|
+| 2025-12-15 | 1.0 | 初始故事创建 | John (Product Manager) |
+| 2025-12-15 | 1.0 | 状态更新为已批准 | James |
+
+## Dev Agent Record
+*此部分由开发代理在实现过程中填写*
+
+### Agent Model Used
+Claude Code
+
+### Debug Log References
+- 待实现
+
+### Completion Notes List
+1. 待实现
+
+### File List
+**预计修改的文件:**
+1. `packages/goods-management-ui-mt/src/components/GoodsManagement.tsx` - 添加筛选器组件,修改查询逻辑
+2. `packages/goods-management-ui-mt/tests/unit/GoodsManagement.test.tsx` - 添加筛选器功能测试
+3. `packages/goods-management-ui-mt/tests/integration/goods-management.integration.test.tsx` - 添加筛选器集成测试
+
+**可能新增的文件:**
+1. `packages/goods-management-ui-mt/src/components/GoodsListFilter.tsx` - 筛选器组件(如果复杂度高)
+
+## Status
+✅ Approved
+
+### 完成状态
+- [ ] 所有功能实现完成
+- [ ] 所有单元测试通过
+- [ ] 所有集成测试通过
+- [ ] 代码已提交并推送到远程仓库
+- [ ] 故事验收标准全部满足
+
+## QA Results
+*此部分由QA代理在审查完成后填写*