ソースを参照

feat(dashboard): 在看板页顶部集成navbar组件

- 从@d8d/mini-shared-ui-components导入Navbar组件
- 添加白色背景导航栏,标题为"企业仪表板"
- 隐藏左侧返回按钮,防止误触返回操作
- 调整ScrollView布局:移除顶部内边距(pt-0),保留左右和底部内边距
- 确保navbar占位元素正确提供间距,fixed定位固定在视口顶部

🤖 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 4 週間 前
コミット
900db8ca7e

+ 150 - 0
docs/stories/012.013.story.md

@@ -0,0 +1,150 @@
+# 故事 012.013:工作状态统一优化 - 基于order_person.work_status的长期方案
+
+## 状态
+Draft
+
+## 故事
+**作为**企业用户,
+**我希望**人才列表和详情API使用`order_person.work_status`作为统一工作状态源,
+**以便**能够精确筛选"在职"、"待入职"、"离职"状态,解决当前状态映射不准确的问题。
+
+## 验收标准
+从史诗文件复制的验收标准编号列表
+
+1. [ ] 人才列表API的"在职"筛选精确返回`work_status='working'`的人员
+2. [ ] 人才列表API的"待入职"筛选精确返回`work_status='pre_working'`的人员
+3. [ ] 人才列表API的"离职"筛选精确返回`work_status='resigned'`的人员
+4. [ ] 人才详情页工作状态显示准确,基于最新的`order_person.work_status`
+5. [ ] 状态映射完整:前端中文状态、Schema验证、数据库枚举值保持一致
+6. [ ] 查询性能优化,添加必要的数据库索引,响应时间<200ms
+7. [ ] 集成测试全面覆盖所有状态场景,测试覆盖率≥60%
+8. [ ] API文档更新,包含完整的状态映射说明
+9. [ ] 现有功能不受影响,企业统计等依赖工作状态的功能仍能正常工作
+
+## 任务 / 子任务
+将故事分解为实施所需的具体任务和子任务。
+在相关处引用适用的验收标准编号。
+
+- [ ] 任务1:查询逻辑重构(disability-module扩展)(AC: 1, 2, 3, 4, 5)
+  - [ ] 在`disabled-person.service.ts`的`findAllForCompany`方法中,修改查询逻辑:使用`order_person.work_status`而不是`disabled_person.job_status`作为工作状态源
+  - [ ] 获取人员最新的`order_person`记录(按`join_date`降序)来确定当前工作状态
+  - [ ] 在SELECT语句中添加`MAX(op.work_status)`或通过子查询获取最新状态
+  - [ ] 更新结果映射逻辑,将`WorkStatus`枚举值转换为中文状态:'working'→"在职"、'pre_working'→"待入职"、'resigned'→"离职"、'not_working'→"未就业"(后备)
+
+- [ ] 任务2:筛选条件优化(AC: 1, 2, 3, 5)
+  - [ ] 修改`jobStatus`筛选逻辑,直接使用`order_person.work_status`进行过滤
+  - [ ] 支持前端中文状态到`WorkStatus`枚举值的映射:"在职"→'working'、"待入职"→'pre_working'、"离职"→'resigned'
+  - [ ] 更新Schema验证(`CompanyPersonListQuerySchema`),明确状态映射关系
+
+- [ ] 任务3:人才详情API统一(AC: 4, 5)
+  - [ ] 在`findOneForCompany`方法中,同样使用`order_person.work_status`作为工作状态源
+  - [ ] 获取人员最新的订单关联记录,确定当前工作状态
+  - [ ] 保持与人才列表API一致的状态转换逻辑
+
+- [ ] 任务4:数据库性能优化(AC: 6)
+  - [ ] 分析现有索引:`order_person`表已有`['personId', 'workStatus']`、`['joinDate']`等索引
+  - [ ] 考虑添加复合索引优化最新状态查询:`['personId', 'joinDate', 'workStatus']`
+  - [ ] 验证查询性能,确保响应时间<200ms
+
+- [ ] 任务5:Schema和类型更新(AC: 5, 8)
+  - [ ] 更新`CompanyPersonListQuerySchema`,明确状态筛选选项和映射关系
+  - [ ] 更新`CompanyPersonListSchema`和`CompanyPersonDetailSchema`,使用一致的枚举类型
+  - [ ] 生成准确的TypeScript类型定义,确保前端类型安全
+
+- [ ] 任务6:前端状态显示统一(AC: 5)
+  - [ ] 更新人才管理UI包中的状态显示逻辑,使用新的状态值
+  - [ ] 确保人才列表页、人才详情页的状态标签显示一致
+  - [ ] 更新状态筛选组件的选项说明
+
+- [ ] 任务7:集成测试全面覆盖(AC: 7)
+  - [ ] 在`person-extension.integration.test.ts`中新增测试用例,覆盖所有状态场景
+  - [ ] 测试状态筛选的精确性:"待入职"和"离职"筛选应返回不同结果
+  - [ ] 测试边界条件:无订单关联的人员状态(显示"未就业"或空值)
+  - [ ] 测试性能:大数据量下的状态查询性能
+  - [ ] 确保测试覆盖率≥60%
+
+- [ ] 任务8:兼容性保障(AC: 9)
+  - [ ] 验证现有数据迁移:所有已有关联订单的人员应有正确的`work_status`值
+  - [ ] 对于无订单关联的人员,提供合理的默认状态(空值或'not_working')
+  - [ ] 确保企业统计中的在职状态分布统计仍能正常工作
+
+## 开发笔记
+仅填充从docs文件夹中的实际工件提取的相关信息,与此故事相关:
+
+### 先前故事洞察
+故事012.011(企业专用人才管理API)已完成的变更:
+- 企业专用人才列表和详情API已在`disabled-person.service.ts`中实现`findAllForCompany`和`findOneForCompany`方法[来源:docs/stories/012.011.story.md]
+- `person-extension.route.ts`文件已包含企业专用人才路由[来源:docs/stories/012.011.story.md]
+- 企业用户认证中间件`enterpriseAuthMiddleware`已实现(故事012.002)[来源:docs/stories/012.002.story.md]
+
+### 数据模型
+基于现有实体定义和架构文档:
+
+**残疾人实体**(`allin-packages/disability-module/src/entities/disabled-person.entity.ts`):
+- 表名:`disabled_person`(@Entity('disabled_person'))
+- 主键:`id`(映射到`person_id`列)
+- 字段:`name`、`gender`、`idCard`、`disabilityId`、`disabilityType`、`disabilityLevel`、`birthDate`、`phone`、`jobStatus`等[来源:docs/stories/012.011.story.md#数据模型]
+
+**订单人员实体**(`allin-packages/order-module/src/entities/order-person.entity.ts`):
+- 表名:`order_person`(@Entity('order_person'))
+- 主键:`id`(映射到`op_id`列)
+- 字段:`orderId`、`personId`、`joinDate`、`salaryDetail`、`workStatus`等[来源:docs/stories/012.011.story.md#数据模型]
+- 关联:`personId`关联DisabledPerson,`orderId`关联EmploymentOrder
+
+**工作状态枚举**(`@d8d/allin-enums`包):
+- `WorkStatus`枚举包含:'not_working'、'pre_working'、'working'、'resigned'[来源:docs/prd/epic-012-api-supplement-for-employer-mini-program.md#故事012-13]
+
+### API规范
+**API路径约定**(来自史诗012):
+- 所有用人方小程序的API路径统一使用 `api/v1/yongren` 前缀[来源:docs/prd/epic-012-api-supplement-for-employer-mini-program.md#api路径约定]
+- 企业专用人才API路径:`GET /api/v1/yongren/disability-person`(列表)、`GET /api/v1/yongren/disability-person/{id}`(详情)[来源:docs/stories/012.011.story.md#api规范]
+
+**验证系统规范**(来自架构文档):
+- 使用Zod Schema进行请求验证和响应类型定义[来源:docs/architecture/backend-module-package-standards.md#验证系统规范]
+- 枚举验证使用`z.nativeEnum(WorkStatus)`[来源:docs/architecture/backend-module-package-standards.md#枚举验证]
+- Schema定义位置:`allin-packages/disability-module/src/schemas/person-extension.schema.ts`[来源:项目结构]
+
+### 文件位置
+基于项目结构指南:
+- 服务文件:`allin-packages/disability-module/src/services/disabled-person.service.ts`[来源:docs/architecture/source-tree.md]
+- 路由文件:`allin-packages/disability-module/src/routes/person-extension.route.ts`[来源:项目结构验证]
+- Schema文件:`allin-packages/disability-module/src/schemas/person-extension.schema.ts`[来源:项目结构验证]
+- 集成测试文件:`allin-packages/disability-module/tests/integration/person-extension.integration.test.ts`[来源:项目结构验证]
+
+### 技术栈约束
+- 运行时:Node.js 20.18.3[来源:docs/architecture/tech-stack.md]
+- 框架:Hono 4.8.5(Web框架和API路由)[来源:docs/architecture/tech-stack.md]
+- ORM:TypeORM 0.3.25(数据库操作抽象)[来源:docs/architecture/tech-stack.md]
+- 数据库:PostgreSQL 17[来源:docs/architecture/tech-stack.md]
+- 测试框架:Vitest[来源:docs/architecture/tech-stack.md]
+
+### 测试要求
+**测试策略**(来自架构文档):
+- 单元测试覆盖率目标:≥ 80%[来源:docs/architecture/testing-strategy.md#单元测试]
+- 集成测试覆盖率目标:≥ 60%[来源:docs/architecture/testing-strategy.md#集成测试]
+- 测试文件位置:`tests/integration/`文件夹与源码并列[来源:docs/architecture/testing-strategy.md#集成测试]
+- 测试框架:Vitest + hono/testing[来源:docs/architecture/testing-strategy.md#集成测试]
+- 集成测试应验证完整的用户流程,而不仅仅是单个操作[来源:docs/architecture/testing-strategy.md#验证完整的用户流程]
+
+**测试数据管理**:
+- 集成测试使用专用测试数据库,事务回滚[来源:docs/architecture/testing-strategy.md#数据库测试策略]
+- 使用测试数据工厂模式创建测试数据[来源:docs/architecture/testing-strategy.md#测试数据工厂模式]
+
+### 编码标准
+- 代码风格:TypeScript严格模式,一致的缩进和命名[来源:docs/architecture/coding-standards.md#现有标准合规性]
+- linting规则:已配置ESLint,支持TypeScript和React[来源:docs/architecture/coding-standards.md#现有标准合规性]
+- 实体设计规范:主键使用`id`作为属性名(映射到数据库列如`person_id`)[来源:docs/architecture/backend-module-package-standards.md#主键命名]
+- 字段命名转换:数据库下划线命名 → TypeScript驼峰命名[来源:docs/architecture/backend-module-package-standards.md#字段命名转换]
+
+### 项目结构注意事项
+- 模块包结构遵循`allin-packages/{module-name}-module/`模式[来源:docs/architecture/backend-module-package-standards.md#包结构规范]
+- 服务层应继承`GenericCrudService`或扩展其功能[来源:docs/architecture/backend-module-package-standards.md#genericcrudservice继承]
+- 路由聚合模式:主路由文件聚合自定义路由和CRUD路由[来源:docs/architecture/backend-module-package-standards.md#路由聚合模式]
+
+## 变更日志
+| 日期 | 版本 | 描述 | 作者 |
+|------|------|------|------|
+| 2025-12-20 | 1.0 | 初始故事创建 | Bob (Scrum Master) |
+
+## Dev Agent Record
+*此部分由开发代理在实施期间填写*

+ 14 - 1
mini-ui-packages/yongren-dashboard-ui/src/pages/Dashboard/Dashboard.tsx

@@ -3,6 +3,7 @@ import { View, Text, ScrollView } from '@tarojs/components'
 import Taro from '@tarojs/taro'
 import { useQuery, useQueryClient } from '@tanstack/react-query'
 import { YongrenTabBarLayout } from '@d8d/yongren-shared-ui/components/YongrenTabBarLayout'
+import { Navbar } from '@d8d/mini-shared-ui-components/components/navbar'
 import { enterpriseCompanyClient } from '../../api'
 import { useAuth, useRequireAuth } from '@d8d/mini-enterprise-auth-ui/hooks'
 // import './Dashboard.css'
@@ -128,12 +129,24 @@ const Dashboard: React.FC = () => {
   return (
     <YongrenTabBarLayout activeKey="dashboard">
       <ScrollView
-        className="h-[calc(100%-60px)] overflow-y-auto p-4"
+        className="h-[calc(100%-60px)] overflow-y-auto px-4 pb-4 pt-0"
         scrollY
         refresherEnabled
         refresherTriggered={refreshing}
         onRefresherRefresh={onRefresh}
       >
+        {/* 导航栏 */}
+        <Navbar
+          title="企业仪表板"
+          leftIcon={undefined}
+          leftText={undefined}
+          onClickLeft={() => {}}
+          backgroundColor="bg-white"
+          border={true}
+          fixed={true}
+          placeholder={true}
+        />
+
         {/* 顶部信息栏 - 对照原型第276-300行 */}
         <View className="bg-gradient-to-r from-blue-500 to-purple-600 text-white rounded-2xl p-5 mb-4">
           <View className="flex justify-between items-center">