Files
ERP/oa-backend/src/main/java/com/kaidi/oa/seed/HrRecruitSeeder.java
T
Qiufeng 1affcd9a5e
Signed Release / release (push) Failing after 5m1s
feat: add PostgreSQL web installation wizard
2026-08-04 07:42:20 +08:00

336 lines
17 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package com.kaidi.oa.seed;
import com.kaidi.oa.domain.HrAiDocDraft;
import com.kaidi.oa.domain.HrInterviewQuestion;
import com.kaidi.oa.domain.HrRecruitCandidate;
import com.kaidi.oa.domain.HrRecruitJob;
import com.kaidi.oa.repository.HrAiDocDraftRepository;
import com.kaidi.oa.repository.HrInterviewQuestionRepository;
import com.kaidi.oa.repository.HrRecruitCandidateRepository;
import com.kaidi.oa.repository.HrRecruitJobRepository;
import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import java.time.Instant;
import java.time.LocalDate;
/**
* 行政·综合部——招聘与人才管理 + AI文档初稿 演示种子。
*
* 幂等:各表已有数据则跳过。
* 覆盖:
* - HrRecruitJob 3 条岗位(招聘中/面试中/已录用)
* - HrRecruitCandidate 6 条候选人(多状态,含 AI 评分)
* - HrInterviewQuestion 5 条面试题(AI 生成标记)
* - HrAiDocDraft 4 条 AI 生成文档(入职资料/岗位说明/员工手册/转正考核,多状态)
*/
@DemoSeed
@Order(203)
public class HrRecruitSeeder implements CommandLineRunner {
private final HrRecruitJobRepository jobRepo;
private final HrRecruitCandidateRepository candidateRepo;
private final HrInterviewQuestionRepository questionRepo;
private final HrAiDocDraftRepository aiDocRepo;
public HrRecruitSeeder(HrRecruitJobRepository jobRepo,
HrRecruitCandidateRepository candidateRepo,
HrInterviewQuestionRepository questionRepo,
HrAiDocDraftRepository aiDocRepo) {
this.jobRepo = jobRepo;
this.candidateRepo = candidateRepo;
this.questionRepo = questionRepo;
this.aiDocRepo = aiDocRepo;
}
@Override
public void run(String... args) {
seedJobs();
seedAiDocs();
}
// ============ 岗位 + 候选人 ============
private void seedJobs() {
if (jobRepo.count() > 0) return;
// Job 1:高级工程师(招聘中)
HrRecruitJob j1 = new HrRecruitJob();
j1.setPosition("高级结构工程师");
j1.setDept("工程技术部");
j1.setHeadcount(2);
j1.setChannel("猎聘");
j1.setRequirement("注册结构工程师,BIM,超高层,地下工程,CAD,10年以上");
j1.setSalaryRange("25k-40k");
j1.setTargetDate(LocalDate.now().plusMonths(1).toString());
j1.setStatus("招聘中");
j1.setHrOwner("王芳");
j1.setRemark("紧急招募,优先有超高层经验");
j1.setCreatedAt(Instant.now().minusSeconds(86400 * 20));
j1.setUpdatedAt(Instant.now().minusSeconds(86400 * 5));
j1 = jobRepo.save(j1);
// Job 2:项目经理(面试中)
HrRecruitJob j2 = new HrRecruitJob();
j2.setPosition("项目经理(EPC");
j2.setDept("项目管理部");
j2.setHeadcount(1);
j2.setChannel("BOSS直聘");
j2.setRequirement("一级建造师,EPC总承包,项目全周期管理,甲方协调,8年以上");
j2.setSalaryRange("30k-45k");
j2.setTargetDate(LocalDate.now().plusWeeks(3).toString());
j2.setStatus("面试中");
j2.setHrOwner("李娜");
j2.setRemark("要求有大型市政工程经验");
j2.setCreatedAt(Instant.now().minusSeconds(86400 * 30));
j2.setUpdatedAt(Instant.now().minusSeconds(86400 * 3));
j2 = jobRepo.save(j2);
// Job 3:财务主管(已录用)
HrRecruitJob j3 = new HrRecruitJob();
j3.setPosition("财务主管");
j3.setDept("财务中心");
j3.setHeadcount(1);
j3.setChannel("内部推荐");
j3.setRequirement("注册会计师,ERP系统,财务分析,税务筹划,5年以上");
j3.setSalaryRange("18k-25k");
j3.setTargetDate(LocalDate.now().minusWeeks(1).toString());
j3.setStatus("已录用");
j3.setHrOwner("王芳");
j3.setRemark("已完成录用,等待入职");
j3.setCreatedAt(Instant.now().minusSeconds(86400 * 45));
j3.setUpdatedAt(Instant.now().minusSeconds(86400 * 7));
j3 = jobRepo.save(j3);
// 候选人 for Job 1
addCandidate(j1.getId(), "张明远", "138****5201", "硕士", 12,
"注册结构工程师,超高层钢结构,BIM建模,CAD,地下工程,设计院15年",
75, "推荐(评分:75)。学历:硕士;工作年限:12年。", "初筛通过", "35k", "2026-06-25 10:00", "技术背景强,建议安排技术面试");
addCandidate(j1.getId(), "刘雪梅", "139****6302", "本科", 8,
"结构工程,CAD,AutoCAD,工程设计,住宅项目",
62, "推荐(评分:62)。学历:本科;工作年限:8年。", "面试安排", "28k", "2026-06-28 14:00", "");
addCandidate(j1.getId(), "赵国强", "136****4403", "大专", 5,
"辅助设计,AutoCAD,钢筋翻样",
51, "不推荐(评分:51)。学历:大专;工作年限:5年。", "已淘汰", "20k", null, "学历和经验不满足要求");
// 候选人 for Job 2
addCandidate(j2.getId(), "陈志远", "137****7504", "本科", 10,
"一级建造师,EPC总承包,项目全周期,市政工程,甲方协调,合同管理",
88, "强烈推荐(评分:88)。学历:本科;工作年限:10年。", "面试通过", "40k", "2026-06-20 09:00", "各项能力突出,建议发Offer");
addCandidate(j2.getId(), "孙丽华", "135****8605", "硕士", 7,
"项目管理,EPC,一建,工程合同,进度管理",
80, "强烈推荐(评分:80)。学历:硕士;工作年限:7年。", "offer发出", "38k", "2026-06-18 14:00", "综合素质优秀");
// 候选人 for Job 3(已入职)
addCandidate(j3.getId(), "吴美玲", "132****9706", "本科", 6,
"注册会计师,ERP财务模块,财务分析,税务筹划,预算管理",
90, "强烈推荐(评分:90)。学历:本科;工作年限:6年。", "已入职", "22k", "2026-06-10 10:00", "已正式入职,表现优异");
// 面试题(for Job 1AI生成)
if (questionRepo.count() == 0) {
addQuestion(j1.getId(), "高级结构工程师", "技能考察",
"请描述您在超高层建筑钢结构设计中遇到的最大技术挑战,以及您的解决方案。",
"考察实际技术经验;期望看到:抗风抗震计算、复杂节点处理、BIM协同经验。",
"高级");
addQuestion(j1.getId(), "高级结构工程师", "面试话术",
"请介绍您主导过的最大单体项目,包括规模、难点和您的贡献。",
"关注项目规模、复杂度与个人贡献比重;是否有超过5万平方米单体。",
"中级");
addQuestion(j2.getId(), "项目经理(EPC", "情景题",
"假设EPC项目在施工过程中甲方提出重大变更,可能导致工期延误3个月,您如何应对?",
"考察变更管理和谈判能力;期望看到:书面确认→工期/费用影响评估→变更谈判→合同签署。",
"高级");
addQuestion(j2.getId(), "项目经理(EPC", "综合素质",
"您如何处理团队内部成员工作风格冲突的问题?请举例说明。",
"考察领导力与团队管理;期望看到积极沟通、明确责任、结果导向。",
"中级");
addQuestion(j3.getId(), "财务主管", "笔试题",
"请说明税务筹划与逃税的本质区别,并举例说明合法的增值税筹划方法。",
"考察税务专业知识合规意识;期望看到清晰区分合规边界,举例一般纳税人优惠政策。",
"高级");
}
}
private void addCandidate(Long jobId, String name, String phone, String edu, int years,
String summary, int score, String aiReport,
String status, String salary, String interviewTime, String note) {
HrRecruitCandidate c = new HrRecruitCandidate();
c.setJobId(jobId);
c.setName(name);
c.setPhone(phone);
c.setEducation(edu);
c.setWorkYears(years);
c.setResumeSummary(summary);
c.setAiScore(score);
c.setAiReport(aiReport);
c.setStatus(status);
c.setExpectedSalary(salary);
c.setInterviewTime(interviewTime);
c.setInterviewNote(note);
c.setCreatedAt(Instant.now().minusSeconds(86400 * (long)(Math.random() * 15 + 1)));
c.setUpdatedAt(Instant.now().minusSeconds(3600));
candidateRepo.save(c);
}
private void addQuestion(Long jobId, String position, String qType,
String content, String refAnswer, String difficulty) {
HrInterviewQuestion q = new HrInterviewQuestion();
q.setJobId(jobId);
q.setPosition(position);
q.setQuestionType(qType);
q.setContent(content);
q.setReferenceAnswer(refAnswer);
q.setAiGenerated(true);
q.setDifficulty(difficulty);
q.setStatus("启用");
q.setCreator("AI系统");
q.setCreatedAt(Instant.now().minusSeconds(86400 * 10));
questionRepo.save(q);
}
// ============ AI 文档初稿 ============
private void seedAiDocs() {
if (aiDocRepo.count() > 0) return;
// 1. 入职资料(已发布)
HrAiDocDraft d1 = new HrAiDocDraft();
d1.setDocType("入职资料");
d1.setRelatedPosition(null);
d1.setRelatedDept("工程技术部");
d1.setTitle("工程技术部 新员工入职资料包(AI初稿)");
d1.setContent("# 工程技术部 新员工入职资料包\n\n"
+ "> AI生成初稿,已经HR审核。\n\n"
+ "## 一、欢迎信\n\n"
+ "亲爱的新同事,\n\n热烈欢迎您加入凯迪科技工程技术部大家庭!\n\n"
+ "## 二、报到须知\n\n"
+ "**报到时间**:请于入职通知书上注明的日期 09:00 前到达人力资源部。\n\n"
+ "**携带材料**:身份证、学历证书、学位证书、离职证明、近期照片 2 张、银行卡。\n\n"
+ "## 三、专属材料\n\n"
+ "技术部员工还需提供:职业资格证书(建造师/结构工程师等)原件复印件。\n\n"
+ "## 四、入职第一周\n\n"
+ "- Day1:行政手续 + 系统开通\n- Day2:公司文化宣贯\n"
+ "- Day3-4:技术规范学习 + 导师结对\n- Day5:与主管沟通试用期目标\n\n"
+ "---\n*由 AI 辅助生成,HR 已审核。*");
d1.setGenContext("类型=入职资料 岗位= 部门=工程技术部 背景=职业资格证书");
d1.setAiGenerated(true);
d1.setStatus("已发布");
d1.setReviewNote("内容准确,补充了专业证书要求,审核通过");
d1.setOperator("HR-王芳");
d1.setCreatedAt(Instant.now().minusSeconds(86400 * 30));
d1.setUpdatedAt(Instant.now().minusSeconds(86400 * 25));
aiDocRepo.save(d1);
// 2. 岗位说明(已审核)
HrAiDocDraft d2 = new HrAiDocDraft();
d2.setDocType("岗位说明");
d2.setRelatedPosition("高级结构工程师");
d2.setRelatedDept("工程技术部");
d2.setTitle("高级结构工程师 岗位说明书(AI初稿)");
d2.setContent("# 高级结构工程师 岗位说明书\n\n"
+ "> AI生成初稿,已审核待发布。\n\n"
+ "## 一、基本信息\n\n"
+ "| 项目 | 内容 |\n| ---- | ---- |\n"
+ "| 岗位名称 | 高级结构工程师 |\n"
+ "| 所属部门 | 工程技术部 |\n"
+ "| 直接上级 | 技术总工 |\n"
+ "| 岗位类别 | 专业技术类 |\n"
+ "| 编制人数 | 2 |\n\n"
+ "## 二、岗位职责\n\n"
+ "1. 负责大型建筑结构设计、审核与优化\n"
+ "2. 参与超高层/复杂结构的技术攻关\n"
+ "3. 指导初中级工程师完成设计任务\n"
+ "4. 负责结构设计图纸的质量把控\n"
+ "5. 参与投标技术方案编写\n\n"
+ "## 三、任职资格\n\n"
+ "**学历**:本科及以上,土木/结构工程专业\n\n"
+ "**证书**:注册结构工程师(一级)优先\n\n"
+ "**经验**:10年以上相关经验,有超高层项目经验\n\n"
+ "**技能**BIM、CAD、SAP2000/PKPM、Revit\n\n"
+ "---\n*由 AI 辅助生成,已审核待签发。*");
d2.setGenContext("类型=岗位说明 岗位=高级结构工程师 部门=工程技术部 背景=注册结构工程师,BIM,超高层");
d2.setAiGenerated(true);
d2.setStatus("已审核");
d2.setReviewNote("内容基本准确,已补充证书要求,待部门负责人签发");
d2.setOperator("HR-李娜");
d2.setCreatedAt(Instant.now().minusSeconds(86400 * 15));
d2.setUpdatedAt(Instant.now().minusSeconds(86400 * 10));
aiDocRepo.save(d2);
// 3. 员工手册(草稿)
HrAiDocDraft d3 = new HrAiDocDraft();
d3.setDocType("员工手册");
d3.setRelatedPosition(null);
d3.setRelatedDept("凯迪科技有限公司");
d3.setTitle("凯迪科技有限公司 员工手册(AI初稿·2026版)");
d3.setContent("# 凯迪科技有限公司 员工手册\n\n"
+ "> AI生成草稿,待法务及HR审核。\n\n"
+ "## 第一章 公司简介\n\n"
+ "凯迪科技有限公司是一家专业从事工程技术、建设管理及 ERP 系统集成的企业,"
+ "秉承「诚信、专业、创新」的核心价值观。\n\n"
+ "## 第二章 行为规范\n\n"
+ "- 诚实守信,不弄虚作假\n"
+ "- 尊重同事,维护良好工作氛围\n"
+ "- 保守公司机密,不泄露商业信息\n\n"
+ "## 第三章 考勤制度\n\n"
+ "- 工作时间:周一至周五 09:00-18:00\n"
+ "- 打卡方式:APP/指纹识别\n"
+ "- 迟到:15分钟以上计考勤异常\n\n"
+ "## 第四章 假期\n\n"
+ "| 假期 | 时长 |\n| ---- | ---- |\n"
+ "| 年假 | 5-15天 |\n| 病假 | 按医院证明 |\n| 婚假 | 3天 |\n"
+ "| 产假 | 按国家规定 |\n\n"
+ "## 第五章 薪酬福利\n\n"
+ "每月15日发薪;五险一金按规定缴纳;节日发放礼品/礼金。\n\n"
+ "---\n*由 AI 辅助生成,待法务审核。*");
d3.setGenContext("类型=员工手册 部门=凯迪科技有限公司");
d3.setAiGenerated(true);
d3.setStatus("草稿");
d3.setReviewNote(null);
d3.setOperator("HR-王芳");
d3.setCreatedAt(Instant.now().minusSeconds(86400 * 5));
d3.setUpdatedAt(Instant.now().minusSeconds(86400 * 5));
aiDocRepo.save(d3);
// 4. 转正考核(草稿)
HrAiDocDraft d4 = new HrAiDocDraft();
d4.setDocType("转正考核");
d4.setRelatedPosition("财务主管");
d4.setRelatedDept("财务中心");
d4.setTitle("财务主管 转正考核表(AI初稿)");
d4.setContent("# 财务主管 转正考核表\n\n"
+ "> AI生成草稿,请直属主管填写评分。\n\n"
+ "## 基本信息\n\n"
+ "| 项目 | 内容 |\n| ---- | ---- |\n"
+ "| 员工姓名 | 吴美玲 |\n"
+ "| 岗位 | 财务主管 |\n"
+ "| 入职日期 | 2026-06-10 |\n"
+ "| 试用期截止 | 2026-09-10 |\n"
+ "| 直属主管 | 财务总监 |\n\n"
+ "## 试用期目标\n\n"
+ "| 目标 | 计划完成 | 实际完成 | 完成率 |\n"
+ "| ---- | ---- | ---- | ---- |\n"
+ "| 完成岗位培训 | 入职第1周 | | |\n"
+ "| 接管月度账务 | 入职第1月 | | |\n"
+ "| 独立完成税务申报 | 入职第2月 | | |\n"
+ "| 完成半年财务分析 | 试用期末 | | |\n\n"
+ "## 综合评分\n\n"
+ "| 维度 | 权重 | 得分 |\n"
+ "| ---- | ---- | ---- |\n"
+ "| 专业能力 | 40% | |\n"
+ "| 工作态度 | 20% | |\n"
+ "| 团队协作 | 20% | |\n"
+ "| 执行力 | 20% | |\n\n"
+ "**转正建议**[ ] 正式转正 [ ] 延长 [ ] 不予转正\n\n"
+ "---\n*由 AI 辅助生成,待主管填写。*");
d4.setGenContext("类型=转正考核 岗位=财务主管 部门=财务中心");
d4.setAiGenerated(true);
d4.setStatus("草稿");
d4.setReviewNote(null);
d4.setOperator("HR-李娜");
d4.setCreatedAt(Instant.now().minusSeconds(86400 * 3));
d4.setUpdatedAt(Instant.now().minusSeconds(86400 * 3));
aiDocRepo.save(d4);
}
}