功能描述:跟踪候选人在招聘各阶段的进展
数据来源:需要新建 RecruitmentProcess 表
新建表:RecruitmentProcess
RecruitmentProcess {
resume: Pointer<Resume> // 关联简历
candidate: {
name: string
phone: string
email: string
},
jobPosition: string // 应聘职位
department: Pointer<Department> // 部门
currentStage: string // 当前阶段
stages: Array<{
id: string
name: string // 简历筛选/初试/复试/终试/发offer
status: 'completed' | 'active' | 'pending' | 'blocked'
completedDate: Date
responsible: Pointer<Profile>
notes: string
evaluationResults: Array<{
evaluator: string
result: 'pass' | 'fail' | 'pending'
score: number
comments: string
}>
}>,
status: 'in_progress' | 'passed' | 'rejected' | 'withdrawn'
finalDecision: {
result: string
decisionDate: Date
decisionMaker: Pointer<Profile>
reason: string
}
}
实现方案:
async loadRecruitmentProcesses() {
const query = new Parse.Query('RecruitmentProcess');
query.equalTo('status', 'in_progress');
query.include('resume');
query.include('department');
query.descending('createdAt');
query.limit(50);
const processes = await query.find();
// 统计各阶段人数
const stageStats = {
'简历筛选': 0,
'初试': 0,
'复试': 0,
'终试': 0,
'发offer': 0
};
processes.forEach(process => {
const currentStage = process.get('currentStage');
if (stageStats[currentStage] !== undefined) {
stageStats[currentStage]++;
}
});
return {
processes: processes.map(p => this.formatProcessData(p)),
statistics: stageStats
};
}
// 推进候选人到下一阶段
async advanceToNextStage(processId: string, stageId: string, evaluation: any) {
const process = await new Parse.Query('RecruitmentProcess').get(processId);
const stages = process.get('stages');
// 更新当前阶段
const currentStage = stages.find(s => s.id === stageId);
currentStage.status = 'completed';
currentStage.completedDate = new Date();
currentStage.evaluationResults.push(evaluation);
// 激活下一阶段
const currentIndex = stages.findIndex(s => s.id === stageId);
if (currentIndex < stages.length - 1) {
stages[currentIndex + 1].status = 'active';
process.set('currentStage', stages[currentIndex + 1].name);
}
process.set('stages', stages);
await process.save();
}
功能描述:横向对比员工、部门或项目的绩效
数据来源:复用 Project 表 + 新建 PerformanceRecord 表
新建表:PerformanceRecord
PerformanceRecord {
profile: Pointer<Profile> // 关联员工
department: Pointer<Department> // 部门
period: {
year: number
month: number
quarter: number
},
// 项目相关绩效
projectMetrics: {
totalProjects: number // 负责项目总数
completedProjects: number // 完成项目数
excellentProjects: number // 优秀项目数
overdueProjects: number // 延期项目数
averageQuality: number // 平均质量评分
averageSatisfaction: number // 平均客户满意度
},
// 个人能力评估
capabilities: {
design: number // 设计能力 (0-100)
communication: number // 沟通能力
execution: number // 执行能力
innovation: number // 创新能力
teamwork: number // 团队协作
growth: number // 成长潜力
},
// 综合评分
overallScore: number,
rank: string, // 排名
level: 'excellent' | 'good' | 'average' | 'below_average'
}
实现方案:
async loadPerformanceComparison(comparisonType: 'employee' | 'department' | 'project') {
const currentPeriod = {
year: new Date().getFullYear(),
month: new Date().getMonth() + 1,
quarter: Math.ceil((new Date().getMonth() + 1) / 3)
};
const query = new Parse.Query('PerformanceRecord');
query.equalTo('period.year', currentPeriod.year);
query.equalTo('period.month', currentPeriod.month);
query.include('profile');
query.include('department');
query.descending('overallScore');
query.limit(20);
const records = await query.find();
if (comparisonType === 'employee') {
return this.formatEmployeeComparison(records);
} else if (comparisonType === 'department') {
return this.aggregateDepartmentPerformance(records);
} else {
return this.aggregateProjectPerformance(records);
}
}
// 自动生成绩效记录(定时任务)
async generateMonthlyPerformanceRecords() {
const profiles = await this.getActiveDesigners();
const lastMonth = this.getLastMonthPeriod();
await Promise.all(profiles.map(async profile => {
// 查询该员工上月的项目数据
const projectQuery = new Parse.Query('Project');
projectQuery.equalTo('assignee', profile);
projectQuery.greaterThanOrEqualTo('createdAt', lastMonth.startDate);
projectQuery.lessThanOrEqualTo('createdAt', lastMonth.endDate);
const projects = await projectQuery.find();
// 计算项目指标
const metrics = this.calculateProjectMetrics(projects);
// 计算能力评估(从项目反馈和评价中提取)
const capabilities = await this.calculateCapabilities(profile, projects);
// 计算综合评分
const overallScore = this.calculateOverallScore(metrics, capabilities);
// 保存绩效记录
const PerformanceRecordClass = Parse.Object.extend('PerformanceRecord');
const record = new PerformanceRecordClass();
record.set('profile', profile);
record.set('department', profile.get('department'));
record.set('period', lastMonth.period);
record.set('projectMetrics', metrics);
record.set('capabilities', capabilities);
record.set('overallScore', overallScore);
record.set('level', this.getPerformanceLevel(overallScore));
await record.save();
}));
}
功能描述:按部门、职位、时间段筛选绩效数据
实现方案:
async filterPerformanceRecords(filters: {
department?: string,
position?: string,
startDate?: Date,
endDate?: Date,
level?: string
}) {
const query = new Parse.Query('PerformanceRecord');
if (filters.department) {
const deptQuery = new Parse.Query('Department');
deptQuery.equalTo('name', filters.department);
const dept = await deptQuery.first();
query.equalTo('department', dept);
}
if (filters.position) {
const profileQuery = new Parse.Query('Profile');
profileQuery.equalTo('roleName', filters.position);
query.matchesQuery('profile', profileQuery);
}
if (filters.startDate && filters.endDate) {
query.greaterThanOrEqualTo('createdAt', filters.startDate);
query.lessThanOrEqualTo('createdAt', filters.endDate);
}
if (filters.level) {
query.equalTo('level', filters.level);
}
query.include('profile');
query.include('department');
query.descending('overallScore');
return await query.find();
}
功能描述:展示所有试用期员工的信息
数据来源:复用 Profile 表
查询逻辑:
async loadNewbieList() {
const query = new Parse.Query('Profile');
query.equalTo('isActivated', true);
query.notEqualTo('isDeleted', true);
// 筛选试用期员工
query.equalTo('data.hrData.employmentStatus', 'probation');
query.include('department');
query.ascending('createdAt');
const profiles = await query.find();
return profiles.map(profile => ({
id: profile.id,
name: profile.get('data')?.realname || profile.get('name'),
department: profile.get('department')?.get('name'),
position: profile.get('roleName'),
hireDate: profile.get('data')?.hrData?.hireDate,
daysInCompany: this.calculateDaysInCompany(profile.get('createdAt')),
mentor: profile.get('data')?.hrData?.mentor, // 导师
status: this.getOnboardingStatus(profile)
}));
}
getOnboardingStatus(profile: any) {
const daysInCompany = this.calculateDaysInCompany(profile.get('createdAt'));
if (daysInCompany <= 7) return { text: '第一周', color: 'green' };
if (daysInCompany <= 30) return { text: '第一个月', color: 'blue' };
if (daysInCompany <= 60) return { text: '第二个月', color: 'orange' };
if (daysInCompany <= 90) return { text: '第三个月', color: 'red' };
return { text: '即将转正', color: 'purple' };
}
功能描述:管理新人入职各阶段的跟进任务
数据来源:新建 OnboardingCheckpoint 表
新建表:OnboardingCheckpoint
OnboardingCheckpoint {
profile: Pointer<Profile> // 关联新人
title: string // 检查点标题
description: string // 描述
type: 'week1' | 'week2' | 'month1' | 'month2' | 'month3' // 阶段
dueDate: Date // 截止日期
completed: boolean // 是否完成
completedDate: Date // 完成日期
responsible: Pointer<Profile> // 负责人(导师/HR)
interviewTemplate: Array<{
question: string
answer: string
}>, // 访谈问题和答案
feedback: {
newbieFeedback: string // 新人反馈
mentorFeedback: string // 导师反馈
hrFeedback: string // HR反馈
},
issues: Array<{
description: string
severity: 'high' | 'medium' | 'low'
resolved: boolean
resolution: string
}>
}
实现方案:
// 自动为新人创建检查点(入职时触发)
async createOnboardingCheckpoints(profileId: string) {
const profile = await new Parse.Query('Profile').get(profileId);
const hireDate = profile.get('data')?.hrData?.hireDate || new Date();
const checkpointTemplates = [
{
type: 'week1',
title: '第一周访谈',
description: '了解新人适应情况,解答疑问',
daysFromHire: 7,
questions: [
'工作环境是否适应?',
'团队成员是否友好?',
'是否遇到困难?',
'对公司的第一印象如何?'
]
},
{
type: 'month1',
title: '第一个月评估',
description: '评估工作表现,提供改进建议',
daysFromHire: 30,
questions: [
'是否熟悉工作流程?',
'完成了哪些工作任务?',
'遇到的主要挑战是什么?',
'需要哪些培训和支持?'
]
},
{
type: 'month2',
title: '第二个月中期评估',
description: '检查进步情况',
daysFromHire: 60,
questions: [
'技能提升了多少?',
'能否独立完成任务?',
'与团队协作如何?',
'职业发展规划是什么?'
]
},
{
type: 'month3',
title: '转正前评估',
description: '决定是否转正',
daysFromHire: 85,
questions: [
'整体工作表现如何?',
'达到转正标准了吗?',
'长期发展意向如何?',
'对公司的建议?'
]
}
];
const OnboardingCheckpointClass = Parse.Object.extend('OnboardingCheckpoint');
await Promise.all(checkpointTemplates.map(async template => {
const checkpoint = new OnboardingCheckpointClass();
checkpoint.set('profile', profile);
checkpoint.set('title', template.title);
checkpoint.set('description', template.description);
checkpoint.set('type', template.type);
const dueDate = new Date(hireDate);
dueDate.setDate(dueDate.getDate() + template.daysFromHire);
checkpoint.set('dueDate', dueDate);
checkpoint.set('completed', false);
checkpoint.set('interviewTemplate', template.questions.map(q => ({
question: q,
answer: ''
})));
await checkpoint.save();
}));
}
// 加载某个新人的所有检查点
async loadNewbieCheckpoints(profileId: string) {
const query = new Parse.Query('OnboardingCheckpoint');
const profilePtr = new Parse.Object('Profile');
profilePtr.id = profileId;
query.equalTo('profile', profilePtr);
query.ascending('dueDate');
return await query.find();
}
// 完成检查点
async completeCheckpoint(checkpointId: string, data: {
interviewAnswers: Array<{ question: string, answer: string }>,
feedback: any,
issues?: any[]
}) {
const checkpoint = await new Parse.Query('OnboardingCheckpoint').get(checkpointId);
checkpoint.set('completed', true);
checkpoint.set('completedDate', new Date());
checkpoint.set('interviewTemplate', data.interviewAnswers);
checkpoint.set('feedback', data.feedback);
if (data.issues && data.issues.length > 0) {
checkpoint.set('issues', data.issues);
}
await checkpoint.save();
}
Profile - 员工信息 ✅
Project - 项目信息 ✅
Department - 部门信息 ✅
ResignationRecord - 离职记录 🆕
Resume - 简历信息 🆕
ResumeAnalysis - 简历AI分析结果 🆕
RecruitmentProcess - 招聘流程 🆕
PerformanceRecord - 绩效记录 🆕
OnboardingCheckpoint - 入职检查点 🆕
可复用:
Profile 表的员工数据可复用:
Project 表的项目数据可复用:
Department 表待续第3部分:实施步骤和优先级...