# 故事017.005: 就业信息功能实现 ## 元信息 - **史诗**: 017 - 人才小程序功能实现 - **优先级**: P1 - 核心功能 - **状态**: Ready for Review - **创建日期**: 2025-12-28 - **负责人**: 开发团队 ## 故事描述 **作为** 人才小程序开发者, **我想要** 实现就业信息页面功能, **以便** 人才用户能够查看当前就业状态、薪资记录和就业历史。 ### 背景 **现有系统状态:** - 故事017.001已完成rencai mini ui包基础框架搭建 - 故事017.002已完成登录与首页实现 - 故事017.003已完成个人信息功能实现 - 故事017.004已完成考勤记录功能实现 - `@d8d/rencai-employment-ui`包基础框架已就绪 - API客户端文件已创建(`src/api/index.ts`) - mini-talent项目路由结构已配置完成(就业信息页从首页跳转) **原型设计参考:** - `docs/小程序原型/rencai.html` 提供了就业信息页面的完整原型设计 - 就业信息页 (原型行630-768): 当前就业状态、薪资记录、就业历史 **技术集成模式:** - 参照`yongren-employment-ui`的实现模式(如果存在) - 就业信息页使用`@d8d/rencai-employment-ui`包 - API调用逻辑封装在页面组件内部 - **非TabBar页面**:使用Navbar带返回按钮(参照故事017.012规范) **依赖API (史诗015):** - ✅ 当前就业状态查询API (GET /api/v1/rencai/employment/status) - 已完成 - ✅ 薪资记录查询API (GET /api/v1/rencai/employment/salary-records) - 已完成 - ✅ 就业历史查询API (GET /api/v1/rencai/employment/history) - 已完成 - ✅ 薪资视频查询API (GET /api/v1/rencai/employment/salary-videos) - 已完成 - ✅ 故事015.005已完成 (2025-12-28) - 📋 前端可直接使用真实API,无需模拟数据 **依赖故事完成状态:** - ✅ 故事017.001: rencai mini ui包基础框架搭建完成 - ✅ 故事017.002: 登录与首页实现完成 - ✅ 故事017.003: 个人信息功能实现完成 - ✅ 故事017.004: 考勤记录功能实现完成 - ✅ 故事017.012: 统一Navbar导航栏组件规范完成 ## 验收标准 ### 当前就业状态展示 - [ ] 当前就业状态查询接口返回正确的当前工作信息(企业名称、岗位名称、入职日期、工作状态、订单编号、薪资水平) - [ ] 企业图标使用圆形头像样式(蓝色背景 + Heroicons building图标) - [ ] 工作状态使用彩色标签显示(在职-绿色、离职-灰色) ### 薪资记录展示 - [ ] 薪资记录查询接口返回历史薪资记录,支持按月查询 - [ ] 薪资记录显示月份、发放日期、薪资金额 - [ ] 支持"查看全部"按钮,跳转到完整薪资记录列表 - [ ] 默认显示最近3条薪资记录 ### 就业历史展示 - [ ] 就业历史查询接口返回个人的就业历史记录 - [ ] 就业历史时间线视图展示完整,按时间倒序排列 - [ ] 时间线使用圆点+连线样式(当前工作-蓝色、历史工作-灰色) - [ ] 显示企业名称、岗位名称、工作时间范围 ### 页面设计与布局 - [ ] 页面设计符合原型标准,移动端体验良好 - [ ] 已集成Navbar导航栏组件(**非TabBar页面**,带返回按钮) - [ ] 页面布局包含:当前就业状态卡片、薪资记录卡片、就业历史时间线 ### 前端模拟数据规范 - [ ] 前端模拟数据结构符合后续API接口规范 - [ ] 就业状态数据结构包含:companyName、positionName、hireDate、workStatus、orderNumber、salaryLevel - [ ] 薪资记录数据结构包含:month、paymentDate、amount - [ ] 就业历史数据结构包含:companyName、positionName、startDate、endDate - [ ] 数据结构便于后续替换为真实API ### 集成与兼容性 - [ ] 与前置故事(017.001-017.004)无缝集成 - [ ] 现有mini-talent项目功能不受影响 ## 任务列表 ### 任务1: 创建就业信息页面组件 (AC: 当前就业状态展示) - [ ] 1.1 在`@d8d/rencai-employment-ui`中实现`EmploymentPage`页面组件 (`src/pages/EmploymentPage/EmploymentPage.tsx`) - [ ] 1.2 创建当前就业状态卡片组件 (`src/components/CurrentEmploymentStatus.tsx`) - 显示企业图标(圆形背景 + Heroicons building图标) - 显示企业名称和岗位名称 - 显示入职日期、工作状态、订单编号、薪资水平(2列网格布局) - 工作状态使用彩色标签(在职-绿色、离职-灰色) - [ ] 1.3 创建前端模拟数据 (`src/utils/mockEmploymentData.ts`) - 当前就业状态数据 - 薪资记录数据(按月份倒序) - 就业历史数据(按时间倒序) - [ ] 1.4 实现数据加载状态(Loading状态) - [ ] 1.5 实现错误处理(数据加载失败时显示错误提示) ### 任务2: 实现薪资记录模块 (AC: 薪资记录展示) - [ ] 2.1 创建薪资记录卡片组件 (`src/components/SalaryRecords.tsx`) - 显示标题"薪资记录"和"查看全部"按钮 - 显示薪资记录列表(默认最近3条) - [ ] 2.2 创建薪资记录项组件 (`src/components/SalaryRecordItem.tsx`) - 显示月份(如:2023年11月) - 显示发放日期(如:发放日期: 2023-12-05) - 显示薪资金额(大号字体、加粗) - [ ] 2.3 创建薪资记录类型定义 (`src/types/employment.ts`) - SalaryRecord接口 - [ ] 2.4 集成前端模拟薪资记录数据 - [ ] 2.5 实现"查看全部"按钮交互(预留跳转接口) ### 任务3: 实现就业历史模块 (AC: 就业历史展示) - [ ] 3.1 创建就业历史卡片组件 (`src/components/EmploymentHistory.tsx`) - 显示标题"就业历史" - 显示时间线视图 - [ ] 3.2 创建就业历史项组件 (`src/components/EmploymentHistoryItem.tsx`) - 时间线圆点(当前工作-蓝色、历史工作-灰色) - 时间线连线(垂直线) - 显示企业名称 - 显示岗位名称 - 显示工作时间范围(如:2023-08-15 至今) - [ ] 3.3 创建就业历史类型定义 (`src/types/employment.ts`) - EmploymentHistoryItem接口 - EmploymentStatus枚举类型 - [ ] 3.4 集成前端模拟就业历史数据 - [ ] 3.5 实现时间线样式(圆点+连线) ### 任务4: 集成Navbar导航栏组件 (AC: 页面设计与布局) - [ ] 4.1 导入Navbar组件: `import { Navbar } from '@d8d/mini-shared-ui-components/components/navbar'` - [ ] 4.2 在页面顶部添加Navbar,配置为**非TabBar页面**(带返回按钮) - [ ] 4.3 Navbar配置: `leftIcon="i-heroicons-chevron-left-20-solid" leftText="返回" onClickLeft={() => Taro.navigateBack()}` - [ ] 4.4 使用Navbar的`placeholder`属性占位,移除手动空白占位 - [ ] 4.5 确保Navbar固定在顶部 (`fixed=true`) ### 任务5: 更新mini-talent页面集成 (AC: 集成与兼容性) - [ ] 5.1 更新`mini-talent/src/pages/employment/index.tsx`: - 从`@d8d/rencai-employment-ui/pages/EmploymentPage/EmploymentPage`导入EmploymentPage组件 - 用AuthProvider包装页面 - 添加认证检查(未登录跳转到登录页) - 导出EmploymentPage组件 - [ ] 5.2 验证页面路由配置(已在故事017.001中配置完成) - [ ] 5.3 验证从首页"薪资查询"入口能正确跳转到就业信息页 ### 任务6: 实现页面样式和移动端适配 (AC: 页面设计与布局) - [ ] 6.1 参照原型设计实现就业信息页样式(原型行630-768) - 当前就业状态卡片样式(企业图标圆形背景、2列网格布局) - 薪资记录卡片样式(白色卡片、列表项分隔) - 就业历史时间线样式(圆点+连线) - [ ] 6.2 确保页面设计符合移动端规范: - 宽度参考: 375px - 圆角规范: 12px (卡片) - 颜色主题: 蓝色渐变 (#3b82f6 → #1e40af) - 字体规范: 标题18-24px, 正文14px, 小字12px - 状态颜色: 在职-绿色、离职-灰色 - [ ] 6.3 使用正确的组件:就业信息页使用**非TabBar页面**(带返回按钮的Navbar) ### 任务7: 编写测试 (AC: 集成与兼容性) - [ ] 7.1 为EmploymentPage编写组件测试 (`tests/pages/EmploymentPage/EmploymentPage.test.tsx`) - 测试组件渲染 - 测试当前就业状态展示(Mock数据) - 测试薪资记录展示(Mock数据) - 测试就业历史展示(Mock数据) - [ ] 7.2 为子组件编写单元测试: - CurrentEmploymentStatus.test.tsx - SalaryRecords.test.tsx - SalaryRecordItem.test.tsx - EmploymentHistory.test.tsx - EmploymentHistoryItem.test.tsx - [ ] 7.3 编写集成测试验证现有功能不受影响 - [ ] 7.4 运行`pnpm typecheck`确保类型检查通过 ## 开发者笔记 ### 前置故事见解 **故事017.001完成状态:** - ✅ rencai系列7个UI包基础结构已创建 - ✅ `@d8d/rencai-employment-ui`包基础框架已就绪 - ✅ API客户端文件已创建(`src/api/index.ts`) - ✅ mini-talent项目路由结构已配置完成 - ✅ package.json的exports字段已配置 - ✅ Jest测试框架已配置(`jest.config.cjs`) **故事017.002完成状态:** - ✅ 登录页面功能完整,支持人才用户身份证号/残疾证号/手机号密码登录 - ✅ 首页/个人主页页面展示个人概览数据 - ✅ 认证状态管理正常,token存储和验证可靠 - ✅ AuthContext提供登录状态、用户信息和登出方法 **故事017.003完成状态:** - ✅ 个人信息页面功能完整 - ✅ 数据脱敏工具函数实现(`maskUtils.ts`) - ✅ 证件照片预览功能实现 - ✅ 测试框架选择确认:**mini项目使用Jest**(不是Vitest) **故事017.004完成状态:** - ✅ 考勤记录页面功能完整 - ✅ 前端模拟数据规范实现 - ✅ Taro布局规范确认(使用`flex flex-col`实现垂直布局) - ✅ Navbar导航栏集成规范确认 **故事017.012完成状态:** - ✅ 统一Navbar导航栏组件规范 - ✅ TabBar页面使用Navbar无返回按钮(leftIcon="" leftText="") - ✅ **非TabBar页面使用Navbar带返回按钮**(本故事适用) - ✅ Navbar样式与用人方小程序保持一致 **关键实现经验:** 1. API客户端导入路径修正:从相应的后端模块包导入,而不是`@d8d/server` 2. 页面文件简化设计:采用"薄包装层",仅导入并导出组件 3. 复用现有共享组件:StatusBar、PageContainer、Navbar使用`@d8d/mini-shared-ui-components`中的实现 4. 测试框架选择:**mini项目使用Jest**(不是Vitest) 5. 前端模拟数据规范:数据结构必须符合后续API接口规范,便于后续替换为真实API 6. **本故事是二级页面**:需要使用Navbar带返回按钮 ### 技术栈要求 **来源**: [architecture/tech-stack.md](../architecture/tech-stack.md) **运行时和框架:** - **Node.js**: 20.18.3 - **Hono**: 4.8.5 (RPC客户端) - **React**: 19.1.0 (UI组件) - **Taro**: 4.1.4 (小程序框架) - **Tailwind CSS**: 4.1.11 (样式) **测试框架:** - **Jest**: 30.2.0 (mini项目使用Jest,不是Vitest!) - **ts-jest**: 29.4.5 (TypeScript预处理器) - **@testing-library/react**: 16.3.0 (React组件测试) - **@d8d/mini-testing-utils**: workspace包 (Taro小程序测试工具) **重要**: **mini项目使用Jest测试框架**,与web应用使用的Vitest不同。 ### UI包开发规范 **来源**: - [architecture/mini-ui-package-standards.md](../architecture/mini-ui-package-standards.md) - **Mini UI包专用规范(本文档必须遵循)** **关键规范要求:** #### 1. UI包内部导入规范 **重要**: UI包内部导入必须使用相对路径,不要使用别名。 **正确示例**: ```typescript // ✅ 正确: 使用相对路径导入同一包内的模块 import { mockEmploymentData } from '../../utils/mockEmploymentData' import { CurrentEmploymentStatus } from '../components/CurrentEmploymentStatus' ``` **错误示例**: ```typescript // ❌ 错误: 不要使用别名导入UI包内部的模块 import { mockEmploymentData } from '@/utils/mockEmploymentData' import { CurrentEmploymentStatus } from '@/components/CurrentEmploymentStatus' ``` #### 2. package.json exports配置规范 ```json { "exports": { ".": { "types": "./dist/src/index.d.ts", "import": "./dist/src/index.js", "require": "./dist/src/index.js" }, "./api": { "types": "./src/api/index.ts", "import": "./src/api/index.ts", "require": "./src/api/index.ts" }, "./pages/EmploymentPage/EmploymentPage": { "types": "./dist/src/pages/EmploymentPage/EmploymentPage.d.ts", "import": "./dist/src/pages/EmploymentPage/EmploymentPage.js", "require": "./dist/src/pages/EmploymentPage/EmploymentPage.js" } } } ``` #### 3. 前端模拟数据规范 **重要**: 本故事使用前端模拟数据,数据结构必须符合后续API接口规范。 **模拟数据文件位置**: `src/utils/mockEmploymentData.ts` **数据结构示例**: ```typescript // 当前就业状态(符合后续API接口规范) export interface CurrentEmploymentStatus { companyName: string // 企业名称(如:阿里巴巴集团) positionName: string // 岗位名称(如:数据标注员) hireDate: string // 入职日期(如:2023-08-15) workStatus: EmploymentStatus // 工作状态 orderNumber: string // 订单编号(如:AL20230815001) salaryLevel: string // 薪资水平(如:¥4,800/月) } // 薪资记录数据(符合后续API接口规范) export interface SalaryRecord { month: string // 月份(如:2023年11月) paymentDate: string // 发放日期(如:2023-12-05) amount: number // 薪资金额(如:4800) } // 就业历史数据(符合后续API接口规范) export interface EmploymentHistoryItem { companyName: string // 企业名称 positionName: string // 岗位名称 startDate: string // 开始日期(如:2023-08-15) endDate: string | null // 结束日期(null表示至今,如:2023-07-31) } export enum EmploymentStatus { ACTIVE = 'active', // 在职 INACTIVE = 'inactive' // 离职 } // 模拟数据导出 export const mockCurrentEmploymentStatus: CurrentEmploymentStatus = { companyName: '阿里巴巴集团', positionName: '数据标注员', hireDate: '2023-08-15', workStatus: EmploymentStatus.ACTIVE, orderNumber: 'AL20230815001', salaryLevel: '¥4,800/月' } export const mockSalaryRecords: SalaryRecord[] = [ { month: '2023年11月', paymentDate: '2023-12-05', amount: 4800 }, // ... 更多记录 ] export const mockEmploymentHistory: EmploymentHistoryItem[] = [ { companyName: '阿里巴巴集团', positionName: '数据标注员', startDate: '2023-08-15', endDate: null // 至今 }, // ... 更多记录 ] ``` **后续API集成预留**: - 类型定义使用RPC推断类型预留接口 - 模拟数据导出函数名称与API客户端方法保持一致 - 便于后续替换为真实API调用 #### 4. Jest配置规范 每个UI包必须创建`jest.config.cjs`配置文件,参照`rencai-personal-info-ui/jest.config.cjs`: ```javascript module.exports = { preset: 'ts-jest', testEnvironment: 'jsdom', setupFilesAfterEnv: ['@d8d/mini-testing-utils/setup'], moduleNameMapper: { '^@/(.*)$': '/src/$1', '^~/(.*)$': '/tests/$1', '^@tarojs/taro$': '@d8d/mini-testing-utils/testing/taro-api-mock.ts', '\\.(css|less|scss|sass)$': '@d8d/mini-testing-utils/testing/style-mock.js', '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': '@d8d/mini-testing-utils/testing/file-mock.js' }, testMatch: [ '/tests/**/*.spec.{ts,tsx}', '/tests/**/*.test.{ts,tsx}' ], collectCoverageFrom: [ 'src/**/*.{ts,tsx}', '!src/**/*.d.ts', '!src/**/index.{ts,tsx}', '!src/**/*.stories.{ts,tsx}' ], coverageDirectory: 'coverage', coverageReporters: ['text', 'lcov', 'html'], testPathIgnorePatterns: [ '/node_modules/', '/dist/', '/coverage/' ], transform: { '^.+\\.(ts|tsx)$': 'ts-jest', '^.+\\.(js|jsx)$': 'babel-jest' }, transformIgnorePatterns: [ '/node_modules/(?!(swiper|@tarojs)/)' ], moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'] } ``` ### 原型设计参考 **来源**: [docs/小程序原型/rencai.html](../小程序原型/rencai.html) **就业信息页** (原型行630-768): #### 1. 当前就业状态卡片 ```html

当前就业状态

阿里巴巴集团

数据标注员

入职日期

2023-08-15

工作状态

在职

订单编号

AL20230815001

薪资水平

¥4,800/月

``` **移动端设计规范**: - 白色卡片背景:`bg-white` - 圆角:12px (`rounded-lg`) - 内边距:16px (`p-4`) - 卡片间距:16px (`mb-4`) - 企业图标:圆形背景 48x48px,蓝色背景 (`bg-blue-100`) - 企业图标:Heroicons `building-office-2-20-solid`(替代fas fa-building) - 信息布局:2列网格 (`grid grid-cols-2 gap-3`) - 工作状态标签:圆角胶囊 (`rounded-full`) - 在职状态:绿色 (`bg-green-100 text-green-800`) - 离职状态:灰色 (`bg-gray-100 text-gray-800`) #### 2. 薪资记录卡片 ```html

薪资记录

2023年11月

发放日期: 2023-12-05

¥4,800

``` **移动端设计规范**: - 白色卡片背景:`bg-white` - 圆角:12px (`rounded-lg`) - 列表项间距:12px (`space-y-3`) - 月份字体大小:14px (`text-sm`) - 发放日期字体大小:12px (`text-xs`) - 薪资金额字体大小:18px (`text-lg`),加粗 (`font-bold`) #### 3. 就业历史时间线 ```html

就业历史

阿里巴巴集团

数据标注员

2023-08-15 至今

``` **移动端设计规范**: - 时间线圆点:3x3px圆形 (`rounded-full`) - 当前工作圆点:蓝色 (`bg-blue-500`) - 历史工作圆点:灰色 (`bg-gray-400`) - 时间线连线:2px宽垂直线 (`w-0.5`),灰色 (`bg-gray-200`) - 企业名称:字体加粗 (`font-medium`) - 岗位名称:14px (`text-sm`) - 时间范围:12px (`text-xs`) ### Navbar导航栏集成规范 **来源**: [docs/stories/017.012.story.md](../stories/017.012.story.md) **非TabBar页面规范(就业信息页属于此类):** - 使用`leftIcon="i-heroicons-chevron-left-20-solid"`和`leftText="返回"` - 参照yongren-order-management-ui:580-589 - Navbar组件来源: `@d8d/mini-shared-ui-components/components/navbar` **Navbar集成示例**: ```typescript import Taro from '@tarojs/taro' import { Navbar } from '@d8d/mini-shared-ui-components/components/navbar' import { View, ScrollView } from '@tarojs/components' export function EmploymentPage() { return ( {/* Navbar导航栏 - 非TabBar页面带返回按钮 */} Taro.navigateBack()} placeholder fixed /> {/* 页面内容 */} {/* 页面内容 */} ) } ``` **关键配置**: - `leftIcon="i-heroicons-chevron-left-20-solid"`: 显示返回按钮图标 - `leftText="返回"`: 显示返回按钮文字 - `onClickLeft={() => Taro.navigateBack()}`: 返回功能 - `placeholder`: 添加占位空间,避免内容被Navbar遮挡 - `fixed`: 固定在顶部 ### 项目结构指南 **来源**: [architecture/source-tree.md](../architecture/source-tree.md) **mini-talent项目结构**: ``` mini-talent/ # 人才小程序项目 ├── src/ │ ├── app.tsx # 小程序入口 │ ├── app.config.ts # 小程序配置 │ ├── app.css # 全局样式 │ ├── pages/ # 页面目录 │ │ ├── login/ # 登录页 │ │ ├── index/ # 首页/个人主页 │ │ ├── attendance/ # 考勤记录页 │ │ ├── personal-info/ # 个人信息页 │ │ ├── employment/ # 就业信息页 (从首页跳转) - 本故事 │ │ │ └── index.tsx │ │ └── settings/ # 设置页 ├── package.json ├── jest.config.js └── tsconfig.json ``` **mini-ui-packages目录结构**: ``` mini-ui-packages/ ├── rencai-employment-ui/ # 人才就业信息UI包 │ ├── src/ │ │ ├── api/ │ │ │ ├── employmentClient.ts │ │ │ └── index.ts │ │ ├── pages/ │ │ │ └── EmploymentPage/ │ │ │ ├── EmploymentPage.tsx │ │ │ └── index.ts (可选) │ │ ├── components/ # UI组件 │ │ │ ├── CurrentEmploymentStatus.tsx # 当前就业状态 │ │ │ ├── SalaryRecords.tsx # 薪资记录 │ │ │ ├── SalaryRecordItem.tsx # 薪资记录项 │ │ │ ├── EmploymentHistory.tsx # 就业历史 │ │ │ └── EmploymentHistoryItem.tsx # 就业历史项 │ │ ├── types/ │ │ │ └── employment.ts # 类型定义 │ │ ├── utils/ │ │ │ └── mockEmploymentData.ts # 前端模拟数据 │ │ └── index.ts │ ├── package.json │ ├── jest.config.cjs │ └── tsconfig.json └── mini-shared-ui-components/ # 通用小程序UI组件 ├── src/ │ └── components/ │ ├── status-bar.tsx │ ├── page-container.tsx │ ├── navbar.tsx │ └── tab-bar.tsx └── ... ``` **mini-talent页面导入方式**: ```typescript // mini-talent/src/pages/employment/index.tsx import EmploymentPage from '@d8d/rencai-employment-ui/pages/EmploymentPage/EmploymentPage' import { AuthContextProvider, useAuth } from '@d8d/rencai-auth-ui/utils' function Employment() { const { isLoggedIn } = useAuth() // 未登录跳转到登录页 if (!isLoggedIn) { Taro.navigateTo({ url: '/pages/login/index' }) return null } return } export default function EmploymentIndex() { return ( ) } ``` ### Taro小程序布局规范 **重要**: 在Taro小程序中,`` 组件内的子元素默认是**横向布局**(`flex-row`),需要显式添加 `flex flex-col` 类才能实现**垂直布局**。 **正确示例**: ```typescript // ✅ 正确: 使用 flex flex-col 实现垂直布局 企业名称: 阿里巴巴集团 岗位名称: 数据标注员 入职日期: 2023-08-15 // ❌ 错误: 缺少 flex flex-col,子元素会横向排列 企业名称: 阿里巴巴集团 岗位名称: 数据标注员 入职日期: 2023-08-15 ``` **当前就业状态卡片示例**: ```typescript import { View, Text } from '@tarojs/components' export function CurrentEmploymentStatus({ status }: { status: CurrentEmploymentStatus }) { return ( 当前就业状态 {/* 企业图标和名称 - 水平布局 */} {/* 企业图标 - Heroicons building */} {status.companyName} {status.positionName} {/* 2列网格信息 - 水平布局 */} {/* 入职日期 */} 入职日期 {status.hireDate} {/* 工作状态 */} 工作状态 {status.workStatus === EmploymentStatus.ACTIVE ? '在职' : '离职'} {/* 订单编号 */} 订单编号 {status.orderNumber} {/* 薪资水平 */} 薪资水平 {status.salaryLevel} ) } ``` **关键点**: 1. **企业图标和名称**使用水平布局(`flex items-center`) 2. **2列网格信息**使用水平布局(`grid grid-cols-2`) 3. **每个信息项**内部使用垂直布局(`flex flex-col`)显示标签和值 4. **重要**: 记住在所有需要垂直排列的 View 上添加 `flex flex-col` ### 图标使用规范 **来源**: [architecture/mini-ui-package-standards.md](../architecture/mini-ui-package-standards.md#图标使用规范) **重要**: **不要使用emoji**,必须使用Heroicons图标类。 **图标类命名格式**: `i-heroicons-{图标名称}-{尺寸}-{样式}` **本故事需要的图标**: - `building-office-2-20-solid` - 企业图标(替代fas fa-building) - `chevron-left-20-solid` - 左箭头(返回按钮) **正确示例**: ```typescript // ✅ 正确: 使用Heroicons图标类 // ❌ 错误: 使用emoji 🏢 ``` **企业图标示例**: ```typescript import { View } from '@tarojs/components' export function CompanyIcon() { return ( ) } ``` ### 前端模拟数据最佳实践 **数据工厂模式**: ```typescript // src/utils/mockEmploymentData.ts /** * 生成模拟就业信息数据 * @returns 就业状态、薪资记录、就业历史 */ export function generateMockEmploymentData(): { currentStatus: CurrentEmploymentStatus salaryRecords: SalaryRecord[] employmentHistory: EmploymentHistoryItem[] } { // 当前就业状态 const currentStatus: CurrentEmploymentStatus = { companyName: '阿里巴巴集团', positionName: '数据标注员', hireDate: '2023-08-15', workStatus: EmploymentStatus.ACTIVE, orderNumber: 'AL20230815001', salaryLevel: '¥4,800/月' } // 薪资记录(按月份倒序) const salaryRecords: SalaryRecord[] = [ { month: '2023年11月', paymentDate: '2023-12-05', amount: 4800 }, { month: '2023年10月', paymentDate: '2023-11-05', amount: 4800 }, { month: '2023年9月', paymentDate: '2023-10-08', amount: 4650 } ] // 就业历史(按时间倒序) const employmentHistory: EmploymentHistoryItem[] = [ { companyName: '阿里巴巴集团', positionName: '数据标注员', startDate: '2023-08-15', endDate: null // 至今 }, { companyName: '腾讯科技', positionName: '内容审核员', startDate: '2023-03-10', endDate: '2023-07-31' }, { companyName: '字节跳动', positionName: '数据录入员', startDate: '2022-09-01', endDate: '2023-02-28' } ] return { currentStatus, salaryRecords, employmentHistory } } ``` ### 测试策略 **来源**: [architecture/testing-strategy.md](../architecture/testing-strategy.md) **测试框架:** - **Jest**: 30.2.0 (mini项目使用Jest,不是Vitest!) - **ts-jest**: 29.4.5 (TypeScript预处理器) - **@testing-library/react**: 16.3.0 (React组件测试) - **@d8d/mini-testing-utils**: workspace包 (Taro小程序测试工具) **测试文件位置**: ``` mini-ui-packages// └── tests/ ├── unit/ # 单元测试 │ └── components/ │ ├── CurrentEmploymentStatus.test.tsx │ ├── SalaryRecords.test.tsx │ ├── SalaryRecordItem.test.tsx │ ├── EmploymentHistory.test.tsx │ └── EmploymentHistoryItem.test.tsx └── pages/ # 页面组件测试 └── EmploymentPage/ └── EmploymentPage.test.tsx ``` **测试要求:** 1. 为每个页面组件编写Jest测试 2. 测试前端模拟数据的正确性 3. 测试当前就业状态展示 4. 测试薪资记录列表显示 5. 测试就业历史时间线展示 6. 验证mini-talent项目现有功能不受影响 7. 运行`pnpm typecheck`确保类型检查通过 **Mock响应示例**: ```typescript const mockCurrentEmploymentStatus: CurrentEmploymentStatus = { companyName: '阿里巴巴集团', positionName: '数据标注员', hireDate: '2023-08-15', workStatus: EmploymentStatus.ACTIVE, orderNumber: 'AL20230815001', salaryLevel: '¥4,800/月' } const mockSalaryRecords: SalaryRecord[] = [ { month: '2023年11月', paymentDate: '2023-12-05', amount: 4800 } ] const mockEmploymentHistory: EmploymentHistoryItem[] = [ { companyName: '阿里巴巴集团', positionName: '数据标注员', startDate: '2023-08-15', endDate: null } ] ``` ### 编码标准 **来源**: [architecture/coding-standards.md](../architecture/coding-standards.md) **关键编码规范:** #### 1. 必须遵循Mini UI包开发规范 开发Mini UI包时,**必须**参考并遵循[Mini UI包开发规范](../architecture/mini-ui-package-standards.md),该规范基于史诗011和017的经验总结。 #### 2. 关键检查点 (基于史诗011和017经验) - **Taro布局规范**: View容器默认横向布局,必须添加`flex flex-col`实现垂直布局 - **图标使用规范**: 必须使用Heroicons图标类,不要使用emoji - **测试框架选择**: **mini项目使用Jest**(不是Vitest) - **Navbar集成**: 非TabBar页面使用Navbar带返回按钮 #### 3. 常见错误避免 - ❌ 不要忘记添加 `flex flex-col` 实现垂直布局 - ❌ 不要使用emoji代替Heroicons图标 - ❌ 不要忘记为图标添加尺寸类(`w-5 h-5`、`text-lg`等) - ❌ 不要在Mini UI包内部导入中使用别名 (`@/`、`~/`等),必须使用相对路径 - ❌ 不要忘记为非TabBar页面添加返回按钮 - ❌ 不要使用Vitest作为Mini项目的测试框架(应使用Jest) **路径使用示例**: ```typescript // ✅ 正确: UI包内部使用相对路径 import { mockEmploymentData } from '../../utils/mockEmploymentData' import { CurrentEmploymentStatus } from '../components/CurrentEmploymentStatus' // ✅ 正确: 跨包导入使用workspace包名 import { SharedComponent } from '@d8d/mini-shared-ui-components' // ❌ 错误: UI包内部使用别名 import { mockEmploymentData } from '@/utils/mockEmploymentData' import { CurrentEmploymentStatus } from '@/components/CurrentEmploymentStatus' ``` #### 4. 参考实现 - **用人方就业UI包**: `mini-ui-packages/yongren-employment-ui` (如果存在) - **人才个人信息UI包**: `mini-ui-packages/rencai-personal-info-ui` - 组件结构和测试参考 - 前端模拟数据实现参考 ### 技术约束 1. **向后兼容**: 不影响现有mini-talent项目功能 2. **类型安全**: 使用TypeScript严格模式,所有数据结构必须有类型定义 3. **模块独立性**: 每个UI包独立管理自己的类型定义和模拟数据 4. **测试覆盖**: 所有新增代码必须有测试覆盖 5. **代码规范**: 遵循项目编码标准和Mini UI包开发规范 6. **数据规范**: 前端模拟数据结构符合后续API接口规范,便于后续替换为真实API ### 风险和缓解措施 **主要风险:** 1. **API延期风险**: 史诗015的就业信息API为P2延期功能,使用前端模拟数据 2. **时间线组件复杂度**: 时间线视图实现可能较为复杂,需要处理圆点和连线样式 3. **数据结构变更**: 前端模拟数据结构与后续API接口可能存在差异 4. **UI组件复用风险**: rencai系列UI包可能与现有yongren系列UI包存在差异 **缓解措施:** 1. **前端模拟数据规范**: 严格按照后续API接口规范设计数据结构,便于后续替换 2. **分阶段实现**: 先实现当前就业状态,再实现薪资记录,最后实现就业历史时间线 3. **参考现有模式**: 参照yongren系列UI包的实现模式和架构 4. **类型安全**: 使用TypeScript接口定义数据结构,确保类型一致性 5. **测试驱动**: 编写完整的测试,确保功能正确性 6. **数据工厂模式**: 使用数据工厂模式生成模拟数据,便于后续替换为真实API ## 测试 ### 测试框架和模式 **来源**: [architecture/testing-strategy.md](../architecture/testing-strategy.md) **测试框架:** - **Jest**: 30.2.0 (mini项目使用Jest,不是Vitest!) - **ts-jest**: 29.4.5 (TypeScript预处理器) - **@testing-library/react**: 16.3.0 (React组件测试) - **@d8d/mini-testing-utils**: workspace包 (Taro小程序测试工具) **测试文件位置:** ``` mini-ui-packages// └── tests/ ├── unit/ # 单元测试 │ └── components/ │ ├── CurrentEmploymentStatus.test.tsx │ ├── SalaryRecords.test.tsx │ ├── SalaryRecordItem.test.tsx │ ├── EmploymentHistory.test.tsx │ └── EmploymentHistoryItem.test.tsx └── pages/ # 页面组件测试 └── EmploymentPage/ └── EmploymentPage.test.tsx ``` ### 测试要求 1. **组件测试**: - 测试组件渲染正确 - 测试前端模拟数据集成 - 测试错误处理 2. **当前就业状态测试**: - 测试企业图标和名称显示 - 测试工作状态标签的颜色(在职-绿色、离职-灰色) - 测试2列网格信息的正确显示 3. **薪资记录测试**: - 测试薪资记录列表的正确渲染 - 测试薪资金额的格式化显示 - 测试"查看全部"按钮 4. **就业历史测试**: - 测试时间线的正确渲染 - 测试圆点颜色(当前-蓝色、历史-灰色) - 测试时间范围显示 5. **集成测试**: - 测试就业信息页面的三个模块数据加载 - 测试Navbar导航栏的正确显示 - 测试返回按钮功能 6. **回归测试**: - 验证mini-talent项目现有功能不受影响 - 运行`pnpm typecheck`确保类型检查通过 ### 测试执行 ```bash # 运行所有测试 cd mini-ui-packages/rencai-employment-ui && pnpm test # 运行特定测试 pnpm test --testNamePattern="EmploymentPage" # 生成覆盖率报告 pnpm test:coverage ``` ## 变更日志 | 日期 | 版本 | 描述 | 作者 | |------|------|------|------| | 2025-12-28 | 1.0 | 创建故事文档 | Bob (Scrum Master) | | 2025-12-28 | 1.1 | 更新API状态(故事015.005已完成,可直接使用真实API) | Bob (Scrum Master) | | 2025-12-28 | 1.2 | 状态更新为Approved | Bob (Scrum Master) | | 2025-12-28 | 1.3 | 开发完成 - 实现就业信息页面功能 | James (Claude Code) | ## 开发者记录 *此部分由开发代理在实施过程中填写* ### 使用的代理模型 claude-sonnet-4-5-20251101 ### 调试日志引用 无 ### 完成说明列表 1. ✅ 创建就业信息页面组件和当前就业状态卡片 - 实现了`CurrentEmploymentStatus`组件,显示企业信息、工作状态、入职日期等 - 使用Heroicons `building-office-2-20-solid`图标 - 工作状态使用彩色标签(在职-绿色、离职-灰色) 2. ✅ 实现薪资记录模块 - 实现了`SalaryRecords`和`SalaryRecordItem`组件 - 显示薪资记录列表,默认显示最近3条 - 支持"查看全部"按钮(预留跳转接口) 3. ✅ 实现就业历史模块 - 实现了`EmploymentHistory`和`EmploymentHistoryItemComponent`组件 - 时间线视图使用圆点+连线样式 - 当前工作-蓝色、历史工作-灰色 4. ✅ 创建就业信息主页面组件 - 集成Navbar导航栏(非TabBar页面,带返回按钮) - 集成真实API(talentEmploymentClient) - 支持下拉刷新 5. ✅ 更新mini-talent页面集成 - mini-talent/src/pages/employment/index.tsx已正确配置 6. ✅ 运行类型检查 - `pnpm typecheck`通过 7. ✅ 编写测试 - 5个测试套件(4个组件测试 + 1个页面测试),27个测试用例全部通过 - 符合Mini UI包测试规范(使用Jest、mini-testing-utils共享mock、真实React Query) - 组件测试:CurrentEmploymentStatus、SalaryRecordItem、SalaryRecords、EmploymentHistory - 页面测试:使用真实React Query的集成测试,验证加载状态、数据显示、Navbar集成、认证检查 **技术实现改进**: - 使用React Query (`useQuery`) 管理服务端状态,符合项目技术栈要求 - 三个独立的query获取就业状态、薪资记录、就业历史 - 使用`QueryClientProvider`进行测试,验证RPC类型推断 ### 文件列表 **新增文件:** - `mini-ui-packages/rencai-employment-ui/src/types/employment.ts` - 类型定义 - `mini-ui-packages/rencai-employment-ui/src/components/CurrentEmploymentStatus.tsx` - 当前就业状态卡片 - `mini-ui-packages/rencai-employment-ui/src/components/SalaryRecordItem.tsx` - 薪资记录项 - `mini-ui-packages/rencai-employment-ui/src/components/SalaryRecords.tsx` - 薪资记录列表 - `mini-ui-packages/rencai-employment-ui/src/components/EmploymentHistoryItem.tsx` - 就业历史项 - `mini-ui-packages/rencai-employment-ui/src/components/EmploymentHistory.tsx` - 就业历史列表 - `mini-ui-packages/rencai-employment-ui/tests/unit/components/CurrentEmploymentStatus.test.tsx` - 测试 - `mini-ui-packages/rencai-employment-ui/tests/unit/components/SalaryRecordItem.test.tsx` - 测试 - `mini-ui-packages/rencai-employment-ui/tests/unit/components/SalaryRecords.test.tsx` - 测试 - `mini-ui-packages/rencai-employment-ui/tests/unit/components/EmploymentHistory.test.tsx` - 测试 - `mini-ui-packages/rencai-employment-ui/tests/pages/EmploymentPage/EmploymentPage.test.tsx` - 页面集成测试(使用真实React Query) **修改文件:** - `mini-ui-packages/rencai-employment-ui/src/pages/EmploymentPage/EmploymentPage.tsx` - 使用React Query重构,符合项目技术栈 - `mini-ui-packages/rencai-employment-ui/jest.config.cjs` - 按照Mini UI测试规范简化配置 ## QA结果 *此部分由QA代理在审查完成后填写*