소스 검색

docs(story): 创建故事015.006 - 就业状态API空数据处理优化

新增故事解决用户无就业记录时返回404错误的问题:
- 当前就业状态API在无记录时返回404"用户不存在",误导用户
- 实际上用户存在,只是还没被分配到订单(正常业务状态)
- 修改为返回200+null,前端显示友好的"未就业"状态

同时更新史诗015文档:
- 添加故事015-006到故事列表
- 修正故事编号(保持015-013为手机号登录支持)
- 更新史诗进度和最近更新记录

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

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
yourname 3 주 전
부모
커밋
3fd27142f1
2개의 변경된 파일289개의 추가작업 그리고 25개의 파일을 삭제
  1. 77 25
      docs/prd/epic-015-talent-mini-program-api-support.md
  2. 212 0
      docs/stories/015.006.story.md

+ 77 - 25
docs/prd/epic-015-talent-mini-program-api-support.md

@@ -76,7 +76,7 @@
 遵循与用人方小程序相同的设计原则,人才小程序API以查询功能为主。所有数据修改操作(个人信息更新、银行卡管理、证件照片管理、打卡记录等)由管理员在管理后台统一处理。人才用户仅有的写入操作包括:登录认证、通知标记已读。
 
 **故事概览:**
-本史诗包含12个故事,其中8个为核心故事(015-01到015-03、015-05到015-07、015-09、015-10),3个延期故事(015-04、015-08、015-11),1个冗余故事(015-12)。故事015-04、015-08因打卡功能前端模拟实现而延期
+本史诗包含13个故事,其中9个为核心故事(015-01到015-03、015-05到015-08、015-10、015-11),3个延期故事(015-04、015-09、015-12),1个新增故事(015-06)。故事015-04、015-09因打卡功能前端模拟实现而延期。故事015-06为就业状态API空数据处理优化,修复用户体验问题。故事015-13为人才用户手机号登录支持(已完成)
 
 ### 故事015-01:数据库schema扩展
 **背景:** 现有数据库表结构缺少支持人才小程序完整功能的关键字段,需要在不影响现有数据的前提下扩展schema。
@@ -217,7 +217,58 @@
 
 **状态:** ✅ 完成 (2025-12-28)
 
-### 故事015-06:帮助与支持API
+### 故事015-06:就业状态API空数据处理优化 🆕
+**状态**: Draft
+**优先级**: P1 - 用户体验修复
+
+**背景:** 当前就业状态API在用户无就业记录时返回404错误,导致前端显示错误提示。实际上用户存在,只是还没被分配到订单(无就业记录),这是正常业务状态,不应视为错误。
+
+**问题分析:**
+- `GET /api/v1/rencai/employment/status` 接口在用户无就业记录时返回 **404 "用户不存在"**
+- 前端因此显示错误Toast,用户体验不佳
+- 实际上用户是存在的(JWT认证已通过),只是该残疾人还没有被分配到任何订单
+
+**用户价值:**
+- 避免显示误导性的错误提示
+- 清晰展示"未就业"状态,而非报错
+- 提升用户体验,减少用户焦虑
+
+**技术方案:**
+- **后端**: 返回200状态码 + null(而非404)
+- **前端**: 显示友好的"未就业"状态(而非错误提示)
+- **测试**: 更新集成测试验证新行为
+
+**任务列表:**
+1. **修改后端就业状态API响应逻辑** (talent-employment.routes.ts):
+   - 移除无就业记录时的404响应
+   - 返回200状态码,数据为null
+   - 更新Schema支持空数据响应
+
+2. **优化前端就业信息页空状态显示** (rencai-employment-ui):
+   - CurrentEmploymentStatus组件显示"未就业"空状态
+   - 移除针对404错误的Toast提示
+   - 设计友好的空状态UI(图标+提示文字)
+
+3. **更新测试**:
+   - 更新后端集成测试,验证无就业记录场景返回200
+   - 更新前端测试,验证"未就业"状态正确显示
+   - 运行完整测试套件确保无回归
+
+4. **保持一致性**:
+   - 确保薪资记录和就业历史接口保持一致性(无记录时返回空数组)
+
+**验收标准:**
+- [ ] 当用户无就业记录时,返回 **200 状态码** 而非 404
+- [ ] 返回数据明确表示"未就业"状态(null值)
+- [ ] 前端就业信息页显示友好的"未就业"提示
+- [ ] 不显示错误Toast
+- [ ] 后端集成测试验证无就业记录场景返回200
+- [ ] 前端测试验证"未就业"状态正确显示
+- [ ] 已有就业记录的用户功能不受影响
+
+**详细设计文档**: [docs/stories/015.006.story.md](../stories/015.006.story.md)
+
+### 故事015-07:帮助与支持API
 **背景:** 人才用户需要查看帮助文档、用户协议、隐私政策等内容。所有账号安全设置和个人信息修改由管理员在管理后台统一维护。
 
 **任务列表:**
@@ -240,7 +291,7 @@
 - [ ] 登录日志查询接口返回个人的登录日志记录
 - [ ] 所有接口通过单元测试和集成测试
 
-### 故事015-07:通知与消息API
+### 故事015-08:通知与消息API
 **背景:** 人才用户需要接收系统通知和消息,包括薪资发放通知、考勤异常通知、系统公告等。
 
 **任务列表:**
@@ -273,7 +324,7 @@
 - [ ] 消息推送集成,重要通知实时推送到小程序
 - [ ] 所有接口通过单元测试和集成测试
 
-### 故事015-08:打卡状态查询API(P2 - 延期,打卡功能前端模拟)
+### 故事015-09:打卡状态查询API(P2 - 延期,打卡功能前端模拟)
 **背景:** 人才用户需要查询当天的打卡状态和历史打卡记录。当前打卡功能为前端模拟实现,待后续确定真实打卡接口逻辑后再实现后端API。
 
 **任务列表:**
@@ -298,7 +349,7 @@
 - [ ] 打卡提醒查询接口返回打卡提醒设置信息
 - [ ] 所有接口通过单元测试和集成测试
 
-### 故事015-09:数据统计与报表API
+### 故事015-10:数据统计与报表API
 **背景:** 人才用户需要查看个人数据统计和报表,包括薪资统计、工作统计等。出勤统计依赖打卡数据,当前打卡功能为前端模拟实现,出勤统计相关API可延期实现。
 
 **任务列表:**
@@ -331,7 +382,7 @@
 - [ ] 统计报表导出接口支持导出Excel和PDF格式报表
 - [ ] 所有接口通过单元测试和集成测试
 
-### 故事015-10:路由路径规范与API客户端
+### 故事015-11:路由路径规范与API客户端
 **背景:** 确保所有人才小程序API遵循统一的路径规范,并为前端提供完整的TypeScript API客户端。
 
 **任务列表:**
@@ -365,7 +416,7 @@
 - [ ] OpenAPI文档完整,包含所有接口的文档注释
 - [ ] 集成测试通过,验证路由路径和API客户端正确性
 
-### 故事015-11:高级功能与优化(P2 - 后期优化)
+### 故事015-12:高级功能与优化(P2 - 后期优化)
 **背景:** 人才小程序的高级功能,包括生物识别登录、智能打卡提醒、数据分析洞察等,不是当前MVP必需功能,可延期到后期优化阶段实现。
 
 **优先级说明:** P2优先级,非当前MVP必需功能。可在基本功能稳定后,根据用户反馈逐步添加高级功能。
@@ -384,7 +435,7 @@
 - [ ] (延期)社交功能体验良好
 - [ ] (延期)职业发展功能实用
 
-### 故事015-12:API文档与测试完善(冗余 - 基础设施已覆盖)
+### 故事015-13:API文档与测试完善(冗余 - 基础设施已覆盖)
 **背景:** 项目使用`@hono/zod-openapi`实现OpenAPI文档自动生成,在路由定义时通过Zod Schema添加OpenAPI元数据,文档在server包中自动聚合。各故事已包含测试要求(单元测试≥80%,集成测试≥60%),无需专门的故事进行文档和测试完善。
 
 **冗余说明:**
@@ -396,7 +447,7 @@
 
 **建议:** 此故事作为基础设施任务已由各故事分别覆盖,无需单独实现。保持各故事的文档和测试要求即可。
 
-### 故事015-13:人才用户手机号登录支持 🆕
+### 故事015-13:人才用户手机号登录支持 
 **状态**: ✅ Ready for Review
 **优先级**: P1 - 用户体验改进(强烈建议)
 
@@ -472,19 +523,19 @@ WHERE u.person_id = dp.id
 - [x] **故事015-03**:个人信息管理API - **已完成** ✅
 - [ ] **故事015-04**:考勤记录API - **P2 - 延期**(打卡功能前端模拟)
 - [x] **故事015-05**:就业信息API - **已完成** ✅
-- [ ] **故事015-06**:帮助与支持API - **待实现**
-- [ ] **故事015-07**:通知与消息API - **待实现**
-- [ ] **故事015-08**:打卡状态查询API - **P2 - 延期**(打卡功能前端模拟)
-- [ ] **故事015-09**:数据统计与报表API - **待实现**(出勤统计可选
-- [ ] **故事015-10**:路由路径规范与API客户端 - **待实现**
-- [ ] **故事015-11**:高级功能与优化 - **P2 - 延期**(后期优化)
-- [ ] **故事015-12**:API文档与测试完善 - **冗余**(基础设施已覆盖
+- [ ] **故事015-06**:就业状态API空数据处理优化 - **待实现** 🆕
+- [ ] **故事015-07**:帮助与支持API - **待实现**
+- [ ] **故事015-08**:通知与消息API - **待实现**
+- [ ] **故事015-09**:打卡状态查询API - **P2 - 延期**(打卡功能前端模拟
+- [ ] **故事015-10**:数据统计与报表API - **待实现**(出勤统计可选)
+- [ ] **故事015-11**:路由路径规范与API客户端 - **待实现**
+- [ ] **故事015-12**:高级功能与优化 - **P2 - 延期**(后期优化
 - [x] **故事015-13**:人才用户手机号登录支持 - **已完成** ✅
 
 **总体进度:** 5/13 故事完成(38%)
-**MVP进度:** 5/9 核心故事完成(56%,排除015-04、015-08、015-11延期和015-12冗余
+**MVP进度:** 5/9 核心故事完成(56%,排除015-04、015-09、015-12延期
 
-**最近更新:** 2025-12-28 - 故事015.005已完成:就业信息API实现,包含当前就业状态查询、薪资记录查询、就业历史查询、薪资视频查询4个API接口,所有12个集成测试通过。2025-12-26 - 故事015.013已完成:人才用户手机号登录支持,扩展UserService.getTalentUserByIdentifier方法支持手机号优先查找,更新API文档和错误提示,18个集成测试全部通过。2025-12-26 - 故事015.013已创建:人才用户手机号登录支持,允许人才用户使用手机号/身份证号/残疾证号登录,提升用户体验。2025-12-25 - 故事015-03已完成:个人信息查询API、银行卡信息查询API(卡号脱敏)、证件照片查询API、所有11个集成测试通过。2025-12-25 - 故事015-02已完成:人才用户认证API、JWT登录、退出登录、获取用户信息、认证中间件、所有16个测试通过。2025-12-24 - 故事015-01已完成:UserType枚举扩展、personId字段添加、TypeORM实体和Schema更新、测试通过。
+**最近更新:** 2025-12-28 - 故事015.006已创建:就业状态API空数据处理优化,修复无就业记录时返回404错误的问题,改为返回200+null,前端显示友好的"未就业"状态。2025-12-28 - 故事015.005已完成:就业信息API实现,包含当前就业状态查询、薪资记录查询、就业历史查询、薪资视频查询4个API接口,所有12个集成测试通过。2025-12-26 - 故事015.013已完成:人才用户手机号登录支持,扩展UserService.getTalentUserByIdentifier方法支持手机号优先查找,更新API文档和错误提示,18个集成测试全部通过。2025-12-26 - 故事015.013已创建:人才用户手机号登录支持,允许人才用户使用手机号/身份证号/残疾证号登录,提升用户体验。2025-12-25 - 故事015-03已完成:个人信息查询API、银行卡信息查询API(卡号脱敏)、证件照片查询API、所有11个集成测试通过。2025-12-25 - 故事015-02已完成:人才用户认证API、JWT登录、退出登录、获取用户信息、认证中间件、所有16个测试通过。2025-12-24 - 故事015-01已完成:UserType枚举扩展、personId字段添加、TypeORM实体和Schema更新、测试通过。
 
 ---
 
@@ -564,13 +615,14 @@ WHERE u.person_id = dp.id
 2. **然后完成故事015-02**:人才用户认证API扩展,提供登录基础
 3. **故事015-03**:个人信息管理API,提供基本信息查询
 4. **故事015-05**:就业信息API,核心功能实现
-5. **故事015-06和015-07**:帮助与支持API和通知与消息API,完善用户体验
-6. **故事015-09**:数据统计与报表API(出勤统计可选),增强功能
-7. **故事015-10**:路由路径规范与API客户端,确保架构规范
-8. **故事015-04、015-08**:考勤记录API和打卡状态查询API(P2延期,打卡功能前端模拟)
-9. **故事015-11**:高级功能与优化(P2优先级,后期优化)
-10. **故事015-12**:API文档与测试完善(冗余,基础设施已覆盖)
-11. **按模块分组**:同一模块的扩展建议由同一开发者完成,确保一致性
+5. **故事015-06**:就业状态API空数据处理优化,修复用户体验问题(建议优先实现)🆕
+6. **故事015-07和015-08**:帮助与支持API和通知与消息API,完善用户体验
+7. **故事015-10**:数据统计与报表API(出勤统计可选),增强功能
+8. **故事015-11**:路由路径规范与API客户端,确保架构规范
+9. **故事015-04、015-09**:考勤记录API和打卡状态查询API(P2延期,打卡功能前端模拟)
+10. **故事015-12**:高级功能与优化(P2优先级,后期优化)
+11. **故事015-13**:人才用户手机号登录支持(已完成)✅
+12. **按模块分组**:同一模块的扩展建议由同一开发者完成,确保一致性
 
 ---
 

+ 212 - 0
docs/stories/015.006.story.md

@@ -0,0 +1,212 @@
+# Story 015.006: 就业状态API空数据处理优化
+
+## Status
+Approved
+
+## Story
+**作为** 人才小程序用户,
+**我想要** 当我没有就业记录时,页面显示友好的"未就业"状态而不是错误提示,
+**以便** 我能够清楚了解当前的就业状态,避免产生混淆和焦虑
+
+## Background
+
+**问题描述**:
+当前 `GET /api/v1/rencai/employment/status` 接口在用户没有就业记录时返回 **404 状态码**和"用户不存在"消息。这导致前端显示错误提示,但实际上:
+1. 用户是存在的(JWT认证已通过)
+2. 该残疾人只是**还没有被分配到任何订单**(无就业记录)
+3. 这是一种正常的业务状态,不应被视为错误
+
+**当前行为** (talent-employment.routes.ts:196-200):
+```typescript
+if (!employmentStatus) {
+  return c.json({
+    code: 404,
+    message: '用户不存在'
+  }, 404);
+}
+```
+
+**期望行为**:
+- 返回 **200 状态码**
+- 数据为空或表示"未就业"状态
+- 前端显示友好的"未就业"提示
+
+**影响范围**:
+- 史诗015.005: 就业信息API (已完成)
+- 史诗017.005: 就业信息功能实现 (已完成)
+
+## Acceptance Criteria
+
+1. **后端API修改**:
+   - [ ] 当用户无就业记录时,返回 **200 状态码** 而非 404
+   - [ ] 返回数据明确表示"未就业"状态
+   - [ ] Schema 支持空数据响应
+
+2. **前端页面优化**:
+   - [ ] 就业信息页显示友好的"未就业"提示
+   - [ ] 不显示错误Toast
+   - [ ] 薪资记录和就业历史正确处理空数据
+
+3. **测试覆盖**:
+   - [ ] 后端集成测试验证无就业记录场景返回200
+   - [ ] 前端测试验证"未就业"状态正确显示
+
+4. **向后兼容**:
+   - [ ] 已有就业记录的用户功能不受影响
+   - [ ] 其他就业接口(薪资记录、就业历史)保持一致性
+
+## Tasks / Subtasks
+
+### 任务1: 修改后端就业状态API响应逻辑 (AC: 1)
+- [ ] 1.1 修改 `talent-employment.routes.ts` 中的 `/employment/status` 路由
+  - 移除无就业记录时的404响应
+  - 返回200状态码,数据为null或表示"未就业"的对象
+- [ ] 1.2 更新 `EmploymentStatusResponseSchema` 支持空数据
+  - 考虑使用可选字段或null值
+- [ ] 1.3 确保薪资记录和就业历史接口保持一致性
+  - 无记录时返回空数组,而非404
+
+### 任务2: 优化前端就业信息页空状态显示 (AC: 2)
+- [ ] 2.1 修改 `CurrentEmploymentStatus` 组件
+  - 当 `status` 为 null 或 undefined 时显示"未就业"状态
+  - 设计友好的空状态UI (图标 + 提示文字)
+- [ ] 2.2 修改 `EmploymentPage` 页面
+  - 移除针对404错误的Toast提示
+  - 正确处理200状态但数据为空的情况
+- [ ] 2.3 修改 `SalaryRecords` 和 `EmploymentHistory` 组件
+  - 确保空数组时显示友好提示
+
+### 任务3: 更新测试 (AC: 3)
+- [ ] 3.1 更新后端集成测试
+  - 修改无就业记录场景的断言,验证返回200而非404
+  - 文件: `allin-packages/order-module/tests/integration/talent-employment.integration.test.ts`
+- [ ] 3.2 更新前端组件测试
+  - 添加"未就业"状态的测试用例
+  - 验证空状态UI正确显示
+- [ ] 3.3 运行完整测试套件确保无回归
+
+### 任务4: 更新文档 (AC: 4)
+- [ ] 4.1 更新故事015.005的Dev Notes,记录API行为变更
+- [ ] 4.2 更新故事017.005的Dev Notes,记录前端处理变更
+
+## Dev Notes
+
+### 当前API行为分析
+
+**来源**: 史诗015.005就业信息API
+
+**当前接口**:
+- `GET /api/v1/rencai/employment/status` - 当前就业状态
+- `GET /api/v1/rencai/employment/salary-records` - 薪资记录
+- `GET /api/v1/rencai/employment/history` - 就业历史
+
+**问题代码位置**:
+`allin-packages/order-module/src/routes/talent-employment.routes.ts:196-200`
+
+```typescript
+// 当前代码 - 返回404
+if (!employmentStatus) {
+  return c.json({
+    code: 404,
+    message: '用户不存在'
+  }, 404);
+}
+```
+
+### 建议的修改方案
+
+**方案1: 返回null值** (推荐)
+```typescript
+// 返回200 + null
+if (!employmentStatus) {
+  return c.json(null, 200);
+}
+```
+- 前端判断: `status === null` 时显示"未就业"
+- 优点: 语义清晰,前端易于判断
+
+**方案2: 返回空对象**
+```typescript
+// 返回200 + 空对象
+return c.json({
+  companyName: null,
+  positionName: null,
+  workStatus: 'not_working'
+}, 200);
+```
+- 前端判断: 根据 `workStatus` 字段显示对应状态
+- 优点: 数据结构一致
+
+**推荐使用方案1**,因为:
+1. 更简洁明了
+2. 前端可以通过null快速判断
+3. 与薪资记录(空数组)保持一致的"无数据"语义
+
+### 前端处理建议
+
+**CurrentEmploymentStatus 组件**:
+```typescript
+interface Props {
+  status: CurrentEmploymentStatusType | null
+  loading: boolean
+}
+
+export function CurrentEmploymentStatus({ status, loading }: Props) {
+  if (loading) return <LoadingSpinner />
+  if (!status) return <EmptyState />  // 显示"未就业"状态
+
+  return (
+    // 正常显示就业信息
+  )
+}
+```
+
+**EmptyState 组件设计**:
+- 图标: Heroicons `briefcase` 或 `user`
+- 提示文字: "暂无就业信息"
+- 说明文字: "您还没有被分配到任何订单"
+- 颜色: 灰色主题
+
+### 技术栈要求
+- **后端**: Hono 4.8.5, TypeORM 0.3.20
+- **前端**: Taro 4.1.4, React 19.1.0
+- **测试**: Vitest (后端), Jest (前端)
+
+### 相关文件
+**需要修改的文件**:
+- `allin-packages/order-module/src/routes/talent-employment.routes.ts` - 后端路由
+- `mini-ui-packages/rencai-employment-ui/src/components/CurrentEmploymentStatus.tsx` - 前端组件
+- `mini-ui-packages/rencai-employment-ui/src/pages/EmploymentPage/EmploymentPage.tsx` - 前端页面
+- `allin-packages/order-module/tests/integration/talent-employment.integration.test.ts` - 后端测试
+- `mini-ui-packages/rencai-employment-ui/tests/unit/components/CurrentEmploymentStatus.test.tsx` - 前端测试
+
+### 参考实现
+- **参考**: 故事015.005中薪资记录接口的处理方式
+  - 薪资记录无数据时返回 `data: []`
+  - 就业状态应采用类似逻辑,返回null或空对象
+
+## Change Log
+| Date | Version | Description | Author |
+|------|---------|-------------|--------|
+| 2025-12-28 | 1.0 | 初始故事创建 | James (Claude Code) |
+
+## Dev Agent Record
+*此部分由开发代理在实施过程中填写*
+
+### Agent Model Used
+(待填写)
+
+### Debug Log References
+(待填写)
+
+### Completion Notes List
+(待填写)
+
+### Known Issues
+(待填写)
+
+### File List
+(待填写)
+
+## QA Results
+*此部分由QA代理在审查完成后填写*