# 人事板块首页分析与实现方案 - 第4部分:测试与部署 ## 🧪 测试方案 ### 1. P0 功能测试(基础统计) #### 测试1.1:职级分布统计 ```typescript // 测试数据准备 async prepareTestData_RankDistribution() { // 创建测试员工 const profiles = [ { name: '张三', level: 'junior' }, { name: '李四', level: 'junior' }, { name: '王五', level: 'intermediate' }, { name: '赵六', level: 'intermediate' }, { name: '钱七', level: 'intermediate' }, { name: '孙八', level: 'senior' } ]; for (const data of profiles) { const Profile = Parse.Object.extend('Profile'); const profile = new Profile(); profile.set('name', data.name); profile.set('isActivated', true); profile.set('isDeleted', false); profile.set('data', { realname: data.name, hrData: { level: data.level, employmentStatus: 'active' } }); await profile.save(); } } // 测试用例 it('职级分布统计应该正确', async () => { const distribution = await this.loadRankDistribution(); expect(distribution).toEqual([ { level: '初级', count: 2, percentage: '33.3' }, { level: '中级', count: 3, percentage: '50.0' }, { level: '高级', count: 1, percentage: '16.7' } ]); }); ``` #### 测试1.2:入离职趋势统计 ```typescript // 测试数据准备 async prepareTestData_MonthlyTrend() { const months = [ { month: '2025-01', hired: 5, left: 2 }, { month: '2025-02', hired: 3, left: 1 }, { month: '2025-03', hired: 4, left: 3 } ]; for (const data of months) { // 创建入职员工 for (let i = 0; i < data.hired; i++) { const profile = new Parse.Object('Profile'); profile.set('createdAt', new Date(data.month + '-15')); profile.set('name', `入职${i+1}`); await profile.save(); } // 创建离职记录 for (let i = 0; i < data.left; i++) { const profile = new Parse.Object('Profile'); profile.set('data', { hrData: { resignationDate: new Date(data.month + '-20') } }); await profile.save(); } } } // 测试用例 it('入离职趋势应该正确统计', async () => { const trend = await this.loadMonthlyTrend(); expect(trend[0]).toEqual({ month: '2025-01', hired: 5, left: 2 }); }); ``` --- ### 2. P1 功能测试(AI简历分析) #### 测试2.1:简历上传和解析 ```typescript it('应该能够上传简历并提取文本', async () => { const testFile = new File(['测试简历内容'], 'resume.txt'); const result = await this.uploadAndAnalyzeResume(testFile, '设计师'); expect(result.resume).toBeDefined(); expect(result.resume.get('resumeText')).toBe('测试简历内容'); expect(result.resume.get('status')).toBe('analyzed'); }); ``` #### 测试2.2:AI多维度分析 ```typescript it('AI应该能够正确分析简历各维度', async () => { const resumeText = ` 姓名:张三 学历:本科 专业:环境艺术设计 工作经验:5年室内设计经验 技能:熟练使用Photoshop、AutoCAD、3DMax 项目经历: 1. XX住宅项目 - 主设计师 2. XX商业空间 - 设计总监 `; const analysisRequest = { resumeText, jobPosition: '设计师', jobRequirements: [ '本科及以上学历', '3年以上设计经验', '熟练使用设计软件' ] }; const result = await this.doubaoAi .analyzeResume(analysisRequest) .toPromise(); // 验证学历维度 const educationDim = result.matchDimensions.find(d => d.name.includes('学历') ); expect(educationDim.score).toBeGreaterThan(70); // 验证技能维度 const skillsDim = result.matchDimensions.find(d => d.name.includes('技能') ); expect(skillsDim.score).toBeGreaterThan(60); // 验证项目经验维度 const projectDim = result.matchDimensions.find(d => d.name.includes('项目') ); expect(projectDim.level).toBe('high'); // 验证总分 expect(result.overallScore).toBeGreaterThan(75); // 验证推荐结论 expect(result.recommendation.level).toBe('recommend'); }); ``` #### 测试2.3:简历筛选功能 ```typescript it('应该能够根据条件筛选简历', async () => { // 创建多份简历 const resumes = [ { score: 85, education: 'bachelor', status: 'analyzed' }, { score: 65, education: 'college', status: 'analyzed' }, { score: 92, education: 'master', status: 'analyzed' } ]; for (const data of resumes) { const resume = new Parse.Object('Resume'); const analysis = new Parse.Object('ResumeAnalysis'); analysis.set('resume', resume); analysis.set('overallScore', data.score); await resume.save(); await analysis.save(); } // 筛选条件:综合评分 > 80 const filteredResumes = await this.filterResumes({ minScore: 80 }); expect(filteredResumes.length).toBe(2); expect(filteredResumes.every(r => r.score >= 80)).toBe(true); }); ``` --- ### 3. P1 功能测试(绩效分析) #### 测试3.1:绩效记录生成 ```typescript it('应该能够生成月度绩效记录', async () => { // 准备测试数据:创建员工和项目 const designer = await this.createTestDesigner(); const projects = await this.createTestProjects(designer, 5); // 生成绩效记录 await this.generateMonthlyPerformance(); // 验证记录是否创建 const query = new Parse.Query('PerformanceRecord'); query.equalTo('profile', designer); const record = await query.first(); expect(record).toBeDefined(); expect(record.get('projectMetrics').totalProjects).toBe(5); }); ``` #### 测试3.2:绩效对比分析 ```typescript it('绩效对比应该正确排序', async () => { // 创建3个设计师的绩效记录 const records = [ { name: '张三', score: 85 }, { name: '李四', score: 92 }, { name: '王五', score: 78 } ]; for (const data of records) { const profile = await this.createTestProfile(data.name); const performance = new Parse.Object('PerformanceRecord'); performance.set('profile', profile); performance.set('overallScore', data.score); await performance.save(); } // 加载绩效对比 const comparison = await this.loadPerformanceComparison('employee'); // 验证排序(降序) expect(comparison[0].name).toBe('李四'); expect(comparison[1].name).toBe('张三'); expect(comparison[2].name).toBe('王五'); }); ``` --- ## 🚀 部署指南 ### 1. 数据库初始化 #### Step 1: 创建新表 ```bash # 在 Parse Dashboard 中依次创建以下表: 1. Resume(简历) - 权限设置:管理员和HR可读写 - 索引:candidateName, status, jobPosition 2. ResumeAnalysis(简历分析) - 权限设置:管理员和HR可读写 - 索引:resume, analysisDate, overallScore 3. RecruitmentProcess(招聘流程) - 权限设置:管理员和HR可读写 - 索引:resume, status, currentStage 4. PerformanceRecord(绩效记录) - 权限设置:管理员可读写,员工可读自己的 - 索引:profile, period, overallScore 5. ResignationRecord(离职记录) - 权限设置:管理员和HR可读写 - 索引:profile, resignationDate, reasonCategory 6. OnboardingCheckpoint(入职检查点) - 权限设置:管理员和HR可读写 - 索引:profile, type, dueDate, completed ``` #### Step 2: 补充现有表字段 ```bash # Profile 表 添加字段: - data.hrData.mentor (Pointer) - data.hrData.resignationDate (Date) - data.hrData.probationEndDate (Date) - data.hrData.convertedDate (Date) # Project 表 添加字段: - data.quality.score (Number) - data.quality.isExcellent (Boolean) - data.clientSatisfaction (Number) - data.timeline.expectedDate (Date) - data.timeline.actualDate (Date) ``` --- ### 2. 云函数部署 #### 云函数1:定时生成绩效记录 ```javascript // cloud/hr-performance.js Parse.Cloud.define('generateMonthlyPerformance', async (request) => { const { month, year } = request.params; // 查询所有在职设计师 const profileQuery = new Parse.Query('Profile'); profileQuery.equalTo('isActivated', true); profileQuery.notEqualTo('isDeleted', true); profileQuery.equalTo('data.hrData.employmentStatus', 'active'); const profiles = await profileQuery.find({ useMasterKey: true }); const results = []; for (const profile of profiles) { // 查询该月的项目 const startDate = new Date(year, month - 1, 1); const endDate = new Date(year, month, 0); const projectQuery = new Parse.Query('Project'); projectQuery.equalTo('assignee', profile); projectQuery.greaterThanOrEqualTo('createdAt', startDate); projectQuery.lessThan('createdAt', endDate); const projects = await projectQuery.find({ useMasterKey: true }); // 计算绩效指标 const metrics = calculateMetrics(projects); const capabilities = calculateCapabilities(profile, projects); const overallScore = calculateOverallScore(metrics, capabilities); // 保存绩效记录 const Performance = Parse.Object.extend('PerformanceRecord'); const record = new Performance(); record.set('profile', profile); record.set('department', profile.get('department')); record.set('period', { year, month, quarter: Math.ceil(month / 3) }); record.set('projectMetrics', metrics); record.set('capabilities', capabilities); record.set('overallScore', overallScore); await record.save(null, { useMasterKey: true }); results.push({ profileId: profile.id, score: overallScore }); } return { success: true, count: results.length, results }; }); // 辅助函数 function calculateMetrics(projects) { return { totalProjects: projects.length, completedProjects: projects.filter(p => p.get('status') === 'completed').length, excellentProjects: projects.filter(p => p.get('data')?.quality?.isExcellent).length, overdueProjects: projects.filter(p => { const expected = p.get('data')?.timeline?.expectedDate; const actual = p.get('data')?.timeline?.actualDate; return actual && expected && actual > expected; }).length }; } ``` #### 云函数2:自动创建入职检查点 ```javascript // cloud/hr-onboarding.js Parse.Cloud.define('createOnboardingCheckpoints', async (request) => { const { profileId } = request.params; const profile = await new Parse.Query('Profile').get(profileId, { useMasterKey: true }); const hireDate = profile.get('data')?.hrData?.hireDate || new Date(); const checkpointTemplates = [ { type: 'week1', title: '第一周访谈', days: 7 }, { type: 'month1', title: '第一个月评估', days: 30 }, { type: 'month2', title: '第二个月评估', days: 60 }, { type: 'month3', title: '转正前评估', days: 85 } ]; const Checkpoint = Parse.Object.extend('OnboardingCheckpoint'); for (const template of checkpointTemplates) { const checkpoint = new Checkpoint(); const dueDate = new Date(hireDate); dueDate.setDate(dueDate.getDate() + template.days); checkpoint.set('profile', profile); checkpoint.set('title', template.title); checkpoint.set('type', template.type); checkpoint.set('dueDate', dueDate); checkpoint.set('completed', false); await checkpoint.save(null, { useMasterKey: true }); } return { success: true, count: checkpointTemplates.length }; }); ``` #### Step 3: 配置定时任务 ```bash # 在 Parse Dashboard 中配置 Jobs 1. 月度绩效生成 - 任务名称:generateMonthlyPerformance - 执行时间:每月1日 00:00 - 函数:generateMonthlyPerformance 2. 新人检查点提醒 - 任务名称:checkOnboardingDue - 执行时间:每天 09:00 - 函数:checkOnboardingDue ``` --- ### 3. 前端配置 #### Step 1: 环境变量配置 ```typescript // environment.ts export const environment = { production: false, parseConfig: { applicationId: 'your-app-id', serverURL: 'https://your-parse-server.com/parse' }, doubaoAI: { apiKey: 'your-doubao-api-key', modelId: 'ep-20241201234567-abcdef' } }; ``` #### Step 2: 权限配置 ```typescript // hr-dashboard.guard.ts @Injectable() export class HRDashboardGuard implements CanActivate { async canActivate(route: ActivatedRouteSnapshot): Promise { const profile = await this.profileService.getCurrentProfile(); // 只有 HR 和管理员可以访问 const allowedRoles = ['HR', '管理员', 'Admin']; const roleName = profile?.get('roleName'); return allowedRoles.includes(roleName); } } ``` --- ## 📊 上线检查清单 ### 上线前准备 ``` ✅ 数据库表已创建 ✅ 字段权限已配置 ✅ 云函数已部署 ✅ 定时任务已配置 ✅ 测试数据已准备 ✅ 功能测试已通过 ✅ 性能测试已通过 ✅ 权限测试已通过 ``` ### 数据迁移 ``` ✅ 现有员工数据补充 level 字段 ✅ 现有项目数据补充 quality 字段 ✅ 历史离职数据导入 ResignationRecord ✅ 生成最近3个月的绩效记录 ``` ### 监控指标 ``` - API 响应时间 < 2s - AI 分析时间 < 3s - 图表渲染时间 < 1s - 数据库查询时间 < 500ms - 错误率 < 0.1% ``` --- ## 🎯 总结 ### 完成的工作 1. ✅ 分析了人事板块的所有功能模块 2. ✅ 设计了完整的数据库表结构 3. ✅ 提供了详细的实现方案 4. ✅ 编写了测试用例 5. ✅ 制定了部署计划 ### 关键亮点 1. **AI简历分析** - 多维度智能筛选 2. **自动绩效生成** - 基于项目数据自动计算 3. **新人全流程跟进** - 入职检查点管理 4. **数据可视化** - 雷达图、饼图、折线图 5. **复用现有表** - 最大化利用现有数据 ### 下一步计划 1. 实施P0功能(职级分布、入离职趋势) 2. 开发AI简历分析功能 3. 实现绩效自动生成 4. 完善招聘流程跟踪 5. 部署上线并收集反馈 --- **文档版本**:v1.0 **最后更新**:2025-11-20 01:45 **维护人**:Cascade AI Assistant **状态**:✅ 待实施