|
|
@@ -0,0 +1,1077 @@
|
|
|
+# 故事017.005: 就业信息功能实现
|
|
|
+
|
|
|
+## 元信息
|
|
|
+- **史诗**: 017 - 人才小程序功能实现
|
|
|
+- **优先级**: P1 - 核心功能
|
|
|
+- **状态**: Draft
|
|
|
+- **创建日期**: 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: {
|
|
|
+ '^@/(.*)$': '<rootDir>/src/$1',
|
|
|
+ '^~/(.*)$': '<rootDir>/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: [
|
|
|
+ '<rootDir>/tests/**/*.spec.{ts,tsx}',
|
|
|
+ '<rootDir>/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
|
|
|
+<!-- 当前就业状态 -->
|
|
|
+<div class="card bg-white p-4 mb-4">
|
|
|
+ <h3 class="font-semibold text-gray-700 mb-3">当前就业状态</h3>
|
|
|
+
|
|
|
+ <!-- 企业图标和名称 -->
|
|
|
+ <div class="flex items-center mb-4">
|
|
|
+ <div class="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center mr-3">
|
|
|
+ <i class="fas fa-building text-blue-500"></i>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <p class="font-medium text-gray-800">阿里巴巴集团</p>
|
|
|
+ <p class="text-sm text-gray-500">数据标注员</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 2列网格信息 -->
|
|
|
+ <div class="grid grid-cols-2 gap-3 text-sm">
|
|
|
+ <div>
|
|
|
+ <p class="text-gray-500">入职日期</p>
|
|
|
+ <p class="text-gray-800">2023-08-15</p>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <p class="text-gray-500">工作状态</p>
|
|
|
+ <span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded-full">在职</span>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <p class="text-gray-500">订单编号</p>
|
|
|
+ <p class="text-gray-800">AL20230815001</p>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <p class="text-gray-500">薪资水平</p>
|
|
|
+ <p class="text-gray-800">¥4,800/月</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</div>
|
|
|
+```
|
|
|
+
|
|
|
+**移动端设计规范**:
|
|
|
+- 白色卡片背景:`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
|
|
|
+<!-- 薪资记录 -->
|
|
|
+<div class="card bg-white p-4 mb-4">
|
|
|
+ <div class="flex justify-between items-center mb-3">
|
|
|
+ <h3 class="font-semibold text-gray-700">薪资记录</h3>
|
|
|
+ <button class="text-blue-500 text-sm">查看全部</button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="space-y-3">
|
|
|
+ <!-- 薪资记录1 -->
|
|
|
+ <div class="flex justify-between items-center p-3 border border-gray-100 rounded-lg">
|
|
|
+ <div>
|
|
|
+ <p class="text-sm font-medium text-gray-800">2023年11月</p>
|
|
|
+ <p class="text-xs text-gray-500">发放日期: 2023-12-05</p>
|
|
|
+ </div>
|
|
|
+ <p class="text-lg font-bold text-gray-800">¥4,800</p>
|
|
|
+ </div>
|
|
|
+ <!-- ... 更多记录 -->
|
|
|
+ </div>
|
|
|
+</div>
|
|
|
+```
|
|
|
+
|
|
|
+**移动端设计规范**:
|
|
|
+- 白色卡片背景:`bg-white`
|
|
|
+- 圆角:12px (`rounded-lg`)
|
|
|
+- 列表项间距:12px (`space-y-3`)
|
|
|
+- 月份字体大小:14px (`text-sm`)
|
|
|
+- 发放日期字体大小:12px (`text-xs`)
|
|
|
+- 薪资金额字体大小:18px (`text-lg`),加粗 (`font-bold`)
|
|
|
+
|
|
|
+#### 3. 就业历史时间线
|
|
|
+```html
|
|
|
+<!-- 就业历史 -->
|
|
|
+<div class="card bg-white p-4">
|
|
|
+ <h3 class="font-semibold text-gray-700 mb-3">就业历史</h3>
|
|
|
+
|
|
|
+ <div class="space-y-4">
|
|
|
+ <!-- 就业记录1 -->
|
|
|
+ <div class="flex">
|
|
|
+ <!-- 时间线圆点+连线 -->
|
|
|
+ <div class="flex flex-col items-center mr-3">
|
|
|
+ <div class="w-3 h-3 rounded-full bg-blue-500"></div>
|
|
|
+ <div class="w-0.5 h-full bg-gray-200 mt-1"></div>
|
|
|
+ </div>
|
|
|
+ <!-- 内容 -->
|
|
|
+ <div class="flex-1 pb-4">
|
|
|
+ <p class="font-medium text-gray-800">阿里巴巴集团</p>
|
|
|
+ <p class="text-sm text-gray-500 mb-1">数据标注员</p>
|
|
|
+ <p class="text-xs text-gray-500">2023-08-15 至今</p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- ... 更多记录 -->
|
|
|
+ </div>
|
|
|
+</div>
|
|
|
+```
|
|
|
+
|
|
|
+**移动端设计规范**:
|
|
|
+- 时间线圆点: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 (
|
|
|
+ <View className="h-screen bg-gray-100">
|
|
|
+ {/* Navbar导航栏 - 非TabBar页面带返回按钮 */}
|
|
|
+ <Navbar
|
|
|
+ title="就业信息"
|
|
|
+ leftIcon="i-heroicons-chevron-left-20-solid"
|
|
|
+ leftText="返回"
|
|
|
+ onClickLeft={() => Taro.navigateBack()}
|
|
|
+ placeholder
|
|
|
+ fixed
|
|
|
+ />
|
|
|
+
|
|
|
+ {/* 页面内容 */}
|
|
|
+ <ScrollView scrollY className="h-full">
|
|
|
+ {/* 页面内容 */}
|
|
|
+ </ScrollView>
|
|
|
+ </View>
|
|
|
+ )
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**关键配置**:
|
|
|
+- `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 <EmploymentPage />
|
|
|
+}
|
|
|
+
|
|
|
+export default function EmploymentIndex() {
|
|
|
+ return (
|
|
|
+ <AuthContextProvider>
|
|
|
+ <Employment />
|
|
|
+ </AuthContextProvider>
|
|
|
+ )
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### Taro小程序布局规范
|
|
|
+
|
|
|
+**重要**: 在Taro小程序中,`<View>` 组件内的子元素默认是**横向布局**(`flex-row`),需要显式添加 `flex flex-col` 类才能实现**垂直布局**。
|
|
|
+
|
|
|
+**正确示例**:
|
|
|
+```typescript
|
|
|
+// ✅ 正确: 使用 flex flex-col 实现垂直布局
|
|
|
+<View className="flex flex-col">
|
|
|
+ <Text>企业名称: 阿里巴巴集团</Text>
|
|
|
+ <Text>岗位名称: 数据标注员</Text>
|
|
|
+ <Text>入职日期: 2023-08-15</Text>
|
|
|
+</View>
|
|
|
+
|
|
|
+// ❌ 错误: 缺少 flex flex-col,子元素会横向排列
|
|
|
+<View>
|
|
|
+ <Text>企业名称: 阿里巴巴集团</Text>
|
|
|
+ <Text>岗位名称: 数据标注员</Text>
|
|
|
+ <Text>入职日期: 2023-08-15</Text>
|
|
|
+</View>
|
|
|
+```
|
|
|
+
|
|
|
+**当前就业状态卡片示例**:
|
|
|
+```typescript
|
|
|
+import { View, Text } from '@tarojs/components'
|
|
|
+
|
|
|
+export function CurrentEmploymentStatus({ status }: { status: CurrentEmploymentStatus }) {
|
|
|
+ return (
|
|
|
+ <View className="bg-white rounded-lg p-4 mb-4">
|
|
|
+ <Text className="font-semibold text-gray-700 mb-3">当前就业状态</Text>
|
|
|
+
|
|
|
+ {/* 企业图标和名称 - 水平布局 */}
|
|
|
+ <View className="flex items-center mb-4">
|
|
|
+ {/* 企业图标 - Heroicons building */}
|
|
|
+ <View className="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center mr-3">
|
|
|
+ <View className="i-heroicons-building-office-2-20-solid text-blue-500 w-6 h-6" />
|
|
|
+ </View>
|
|
|
+ <View>
|
|
|
+ <Text className="font-medium text-gray-800">{status.companyName}</Text>
|
|
|
+ <Text className="text-sm text-gray-500">{status.positionName}</Text>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ {/* 2列网格信息 - 水平布局 */}
|
|
|
+ <View className="grid grid-cols-2 gap-3 text-sm">
|
|
|
+ {/* 入职日期 */}
|
|
|
+ <View className="flex flex-col">
|
|
|
+ <Text className="text-gray-500">入职日期</Text>
|
|
|
+ <Text className="text-gray-800">{status.hireDate}</Text>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ {/* 工作状态 */}
|
|
|
+ <View className="flex flex-col">
|
|
|
+ <Text className="text-gray-500">工作状态</Text>
|
|
|
+ <View className={`text-xs px-2 py-1 rounded-full ${
|
|
|
+ status.workStatus === EmploymentStatus.ACTIVE
|
|
|
+ ? 'bg-green-100 text-green-800'
|
|
|
+ : 'bg-gray-100 text-gray-800'
|
|
|
+ }`}>
|
|
|
+ <Text>{status.workStatus === EmploymentStatus.ACTIVE ? '在职' : '离职'}</Text>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ {/* 订单编号 */}
|
|
|
+ <View className="flex flex-col">
|
|
|
+ <Text className="text-gray-500">订单编号</Text>
|
|
|
+ <Text className="text-gray-800">{status.orderNumber}</Text>
|
|
|
+ </View>
|
|
|
+
|
|
|
+ {/* 薪资水平 */}
|
|
|
+ <View className="flex flex-col">
|
|
|
+ <Text className="text-gray-500">薪资水平</Text>
|
|
|
+ <Text className="text-gray-800">{status.salaryLevel}</Text>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ </View>
|
|
|
+ )
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+**关键点**:
|
|
|
+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图标类
|
|
|
+<View className="i-heroicons-building-office-2-20-solid w-6 h-6 text-blue-500" />
|
|
|
+
|
|
|
+// ❌ 错误: 使用emoji
|
|
|
+<Text>🏢</Text>
|
|
|
+```
|
|
|
+
|
|
|
+**企业图标示例**:
|
|
|
+```typescript
|
|
|
+import { View } from '@tarojs/components'
|
|
|
+
|
|
|
+export function CompanyIcon() {
|
|
|
+ return (
|
|
|
+ <View className="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center">
|
|
|
+ <View className="i-heroicons-building-office-2-20-solid text-blue-500 w-6 h-6" />
|
|
|
+ </View>
|
|
|
+ )
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 前端模拟数据最佳实践
|
|
|
+
|
|
|
+**数据工厂模式**:
|
|
|
+```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/<package-name>/
|
|
|
+└── 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/<package-name>/
|
|
|
+└── 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) |
|
|
|
+
|
|
|
+## 开发者记录
|
|
|
+
|
|
|
+*此部分由开发代理在实施过程中填写*
|
|
|
+
|
|
|
+### 使用的代理模型
|
|
|
+
|
|
|
+待填写
|
|
|
+
|
|
|
+### 调试日志引用
|
|
|
+
|
|
|
+待填写
|
|
|
+
|
|
|
+### 完成说明列表
|
|
|
+
|
|
|
+待填写
|
|
|
+
|
|
|
+### 文件列表
|
|
|
+
|
|
|
+待填写
|
|
|
+
|
|
|
+## QA结果
|
|
|
+
|
|
|
+*此部分由QA代理在审查完成后填写*
|