Commit d2faaa1c by zwb

新增个人简历基本信息管理,工作经历与实习经历切换

parent cf629718
Showing with 425 additions and 55 deletions
......@@ -84,4 +84,43 @@ public class ResumeEnum {
return codeList;
}
}
@AllArgsConstructor
@NoArgsConstructor
@Getter
public enum ResumeBase{
CITY(1, "期望城市", "city", 6),
WECHAT(2, "微信", "wechat", 8),
EMAIL(3, "邮箱", "email", 1),
PHONE(4, "手机号", "phone",2),
SEX(5, "性别", "sex", 3),
JOBINT(6, "求职意向", "jobInt", 4),
AVATAR(7, "头像", "avatar", 5),//获奖信息-荣誉奖项
NAME(8, "姓名", "username", 99),
;
private int code;
private String name;
private String webCode;
private int sort;
public static String getWebCodeByCode(Integer code){
for (ResumeModel thisEnum : EnumSet.allOf(ResumeModel.class)) {
if (thisEnum.code == code){
return thisEnum.webCode;
}
}
return null;
}
public static List<Integer> getResumeModel(){
List<Integer> codeList = new ArrayList<>();
for (ResumeModel model : EnumSet.allOf(ResumeModel.class)) {
if (model != ResumeModel.CUSTOM && model != ResumeModel.BASE){
codeList.add(model.getCode());
}
}
return codeList;
}
}
}
......@@ -33,9 +33,9 @@ public class AiConfigProperties {
//
// public String avatarImages = "https://xzt-dev.jinsehuaqin.com/avatar_images/";
//
public String pdfDownZs;
public String htmlDownZs;
// public String pdfDownZs = "https://xzt-dev.jinsehuaqin.com/pdf_down_zs/";
//
// public String htmlDownZs = "https://xzt-dev.jinsehuaqin.com/html_down_zs/";
//
// public String imagesDownZs = "https://xzt-dev.jinsehuaqin.com/images_down_zs/";
//
......
......@@ -3,10 +3,9 @@ package com.bkty.system.controller;
import cn.hutool.core.collection.CollectionUtil;
import com.bkty.system.api.model.LoginUser;
import com.bkty.system.domain.dto.ModuleOptimizationDto;
import com.bkty.system.domain.dto.ResumeByPdfDto;
import com.bkty.system.domain.dto.ResumeListItemCache;
import com.bkty.system.domain.dto.ResumeMakeDto;
import com.bkty.system.domain.dto.*;
import com.bkty.system.domain.entity.FunctionResumeBaseTag;
import com.bkty.system.domain.vo.ResumeBase;
import com.bkty.system.domain.vo.ResumeByPdfVo;
import com.bkty.system.domain.vo.ResumeModelVo;
import com.bkty.system.domain.vo.ResumeVo;
......@@ -153,9 +152,7 @@ public class NewEditionResumeController {
*/
@PostMapping("/create-resume-pdf")
public R<ResumeByPdfVo> createResumePdf(@RequestBody ResumeByPdfDto dto){
ResumeByPdfVo vo = this.newEditionResumeService.createResumePdf(dto);
return new R<>(vo);
}
......@@ -209,8 +206,50 @@ public class NewEditionResumeController {
throw new JxgException("简历id不能为空");
}
this.newEditionResumeService.resumeModelSort(dto);
//修改缓存模块
this.resumeCacheService.updateModelSort(dto);
return new R<>();
}
/**
* 查询个人简历基本信息标签列表
* @param dto
* @return
*/
@PostMapping(value = "/resume-data-tagList")
@RepeatSubmit
public R<List<String>> resumeDataTagList(@RequestBody ResumeMakeDto dto){
if (null == dto.getResumeId()){
throw new JxgException("简历id不能为空");
}
return R.ok(this.newEditionResumeService.resumeDataTagList(dto.getResumeId()));
}
/**
* 更新个人简历基本信息标签列表
* @param dto
* @return
*/
@PostMapping(value = "/update-resume-tagList")
@RepeatSubmit
public R<List<String>> updateResumeTagList(@RequestBody ResumeBaseTagDto dto){
if (null == dto.getResumeId()){
throw new JxgException("简历id不能为空");
}
return R.ok(this.newEditionResumeService.updateResumeTagList(dto));
}
/**
* 个人简历工作经历与实习经历切换
* @param dto
* @return
*/
@PostMapping(value = "/reversal-experience")
@RepeatSubmit
public R reversalExperience(@RequestBody ResumeExpChangeDto dto) throws Exception {
if (null == dto.getWorkExperience()&&dto.getInternshipExperience()==null){
throw new JxgException("切换经历不能为空");
}
return R.ok(this.newEditionResumeService.reversalExperience(dto));
}
}
package com.bkty.system.domain.dto;
import lombok.Data;
import java.util.List;
/**
* @author Zhang Wenbiao
* @description 个人简历基本信息标签请求类
* @datetime 2025/12/2 17:21
*/
@Data
public class ResumeBaseTagDto {
private String resumeId;
private List<String> resumeNameList;
}
package com.bkty.system.domain.dto;
import lombok.Data;
/**
* @author Zhang Wenbiao
* @description 个人简历经历切换请求类
* @datetime 2025/12/3 9:29
*/
@Data
public class ResumeExpChangeDto {
/**
* 工作经历
*/
private ResumeMakeDto workExperience;
/**
* 实习经历
*/
private ResumeMakeDto internshipExperience;
}
......@@ -57,4 +57,7 @@ public class ResumeMakeDto {
/**模版名称*/
private String templateName;
/**模块名称*/
private String modelName;
}
package com.bkty.system.domain.dto;
import lombok.Data;
import java.util.Map;
/**
* @author Zhang Wenbiao
* @description 个人简历修改请求类
* @datetime 2025/12/3 9:30
*/
@Data
public class ResumeUpdateDto {
/**简历id*/
private String resumeId;
/**模块id*/
private Long modelId;
/**个人简历基本信息*/
private Map<String, Object> bodyData;
/**模块名称*/
private String modelName;
}
package com.bkty.system.domain.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.dromara.common.mybatis.core.domain.BaseEntity;
/**
* @author Zhang Wenbiao
* @description 个人简历基本信息标签
* @datetime 2025/12/2 14:48
*/
@Data
@TableName("function_resume_base_tag")
public class FunctionResumeBaseTag extends BaseEntity {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.ASSIGN_ID)
private Long id;
/**简历id*/
private Long resumeId;
/**标签类型 ResumeEnum.ResumeBase枚举类型*/
private Integer baseTag;
/**标签名称*/
private String tagName;
/**是否展示0.显示 1.不显示*/
private Integer isShow;
/**排序*/
private Integer dataSort;
/**
* 标签英文code
*/
private String baseWebCode;
}
......@@ -14,14 +14,14 @@ public class NewEditionBase {
@Schema(description = "头像URL")
private String avatar;
@Schema(description = "出生日期")
private String birthday;
// @Schema(description = "出生日期")
// private String birthday;
@Schema(description = "电子邮箱")
private String email;
@Schema(description = "民族")
private String ethnic;
// @Schema(description = "民族")
// private String ethnic;
@Schema(description = "求职意向")
private String jobInt;
......@@ -29,8 +29,8 @@ public class NewEditionBase {
@Schema(description = "手机号")
private String phone;
@Schema(description = "政治面貌")
private String polStatus;
// @Schema(description = "政治面貌")
// private String polStatus;
@Schema(description = "简历名称")
private String resumeName;
......@@ -44,9 +44,9 @@ public class NewEditionBase {
@Schema(description = "微信号")
private String wechat;
@Schema(description = "工作状态")
private String workStatus;
@Schema(description = "参加工作时间")
private String workTime;
// @Schema(description = "工作状态")
// private String workStatus;
//
// @Schema(description = "参加工作时间")
// private String workTime;
}
......@@ -10,9 +10,6 @@ import org.dromara.common.core.annotation.JxgInitField;
**/
@Data
public class ResumeBase {
/**生日*/
@JxgInitField("Age")
private String birthday;
/**头像url*/
@JxgInitField("Avatar")
......@@ -22,10 +19,6 @@ public class ResumeBase {
@JxgInitField("City")
private String city;
/**名族*/
@JxgInitField("Ethnic")
private String ethnic;
/**岗位*/
@JxgInitField("JobInt")
private String jobInt;
......@@ -38,35 +31,44 @@ public class ResumeBase {
@JxgInitField("Name")
private String username;
/**薪资*/
@JxgInitField("Pay")
private String pay;
/**手机号*/
@JxgInitField("Phone")
private String phone;
/**政治面貌*/
@JxgInitField("PolStatus")
private String polStatus;
/**性别*/
@JxgInitField("Sex")
private String sex;
/**工作状态*/
@JxgInitField("Status")
private String workStatus;
/**微信号*/
@JxgInitField("Wechat")
private String wechat;
/**参加工作时间*/
@JxgInitField(value = "WorkTime")
private String workTime;
/**简历名称*/
@JxgInitField(value = "ResumeName")
private String resumeName;
// /**生日*/
// @JxgInitField("Age")
// private String birthday;
// /**名族*/
// @JxgInitField("Ethnic")
// private String ethnic;
// /**薪资*/
// @JxgInitField("Pay")
// private String pay;
// /**政治面貌*/
// @JxgInitField("PolStatus")
// private String polStatus;
// /**工作状态*/
// @JxgInitField("Status")
// private String workStatus;
// /**参加工作时间*/
// @JxgInitField(value = "WorkTime")
// private String workTime;
}
package com.bkty.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.bkty.system.domain.entity.FunctionResumeBaseTag;
import org.apache.ibatis.annotations.*;
import java.util.List;
/**
* 个人简历基本数据标签Mapper
*/
@Mapper
public interface FunctionResumeBaseTagMapper extends BaseMapper<FunctionResumeBaseTag> {
@Insert({
"<script>",
"INSERT INTO function_resume_base_tag (id, resume_id, base_tag,base_web_code, tag_name, is_show, data_sort, create_by, create_time, update_by, update_time, is_deleted) ",
"VALUES ",
"<foreach collection='tags' item='item' separator=','>",
"(#{item.id}, #{item.resumeId}, #{item.baseTag} ,#{item.baseWebCode}, #{item.tagName}, #{item.isShow}, #{item.dataSort}, #{item.createBy}, #{item.createTime}, #{item.updateBy}, #{item.updateTime}, #{item.isDeleted})",
"</foreach>",
"</script>"
})
void insertBatch(@Param("tags")List<FunctionResumeBaseTag> tagList);
/**
* 查询简历基本数据标签列表
*
* @param resumeId
* @return
*/
@Select("""
select base_web_code
from function_resume_base_tag ft
where ft.resume_id = #{resumeId}
and ft.is_show = 0
""")
List<String> queryBaseWebCodeList(@Param("resumeId") String resumeId);
@Select("""
select tag_name from function_resume_base_tag ft
where ft.resume_id = #{resumeId}
and ft.is_show = 0""")
List<String> selectTagNameList(String resumeId);
@Update({
"<script>",
"UPDATE function_resume_base_tag",
"SET is_show = CASE",
" WHEN tag_name IN",
" <foreach collection='resumeBaseTagNameList' item='tagName' open='(' separator=',' close=')'>",
" #{tagName}",
" </foreach>",
" THEN 0",
" ELSE 1",
"END,",
" update_time = NOW()",
"WHERE resume_id = #{resumeId}",
" AND is_deleted = 0",
"</script>"
})
void updateResumeTag(@Param("resumeId") String resumeId, @Param("resumeBaseTagNameList") List<String> resumeBaseTagNameList);
}
package com.bkty.system.service.resume;
import com.bkty.system.domain.dto.ModuleOptimizationDto;
import com.bkty.system.domain.dto.ResumeByPdfDto;
import com.bkty.system.domain.dto.ResumeListItemCache;
import com.bkty.system.domain.dto.ResumeMakeDto;
import com.bkty.system.domain.dto.*;
import com.bkty.system.domain.vo.ResumeByPdfVo;
import com.bkty.system.domain.vo.ResumeModelVo;
import com.bkty.system.domain.vo.ResumeVo;
......@@ -100,4 +97,25 @@ public interface NewEditionResumeService {
*/
ResumeByPdfVo createResumePdf(ResumeByPdfDto dto);
/**
* 查询个人简历基本信息标签列表
* @param resumeId
*/
List<String> resumeDataTagList(String resumeId);
/**
* 更新个人简历基本信息标签列表
* @param dto
* @return
*/
List<String> updateResumeTagList(ResumeBaseTagDto dto);
/**
* 个人简历工作经历与实习经历切换
*
* @param dto
* @return
*/
String reversalExperience(ResumeExpChangeDto dto) throws Exception;
}
......@@ -12,10 +12,7 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.bkty.system.api.model.LoginUser;
import com.bkty.system.config.AiConfigProperties;
import com.bkty.system.config.CommonAsyncThreadPool;
import com.bkty.system.domain.dto.ModuleOptimizationDto;
import com.bkty.system.domain.dto.ResumeByPdfDto;
import com.bkty.system.domain.dto.ResumeListItemCache;
import com.bkty.system.domain.dto.ResumeMakeDto;
import com.bkty.system.domain.dto.*;
import com.bkty.system.domain.entity.*;
import com.bkty.system.domain.vo.*;
import com.bkty.system.mapper.*;
......@@ -106,6 +103,8 @@ public class NewEditionResumeServiceImpl implements NewEditionResumeService {
private final AiConfigProperties properties;
private final FunctionResumeBaseTagMapper resumeBaseTagMapper;
@Override
public void insertNewEditionResume(MultipartFile file, String type) {
......@@ -117,7 +116,6 @@ public class NewEditionResumeServiceImpl implements NewEditionResumeService {
UserLoginInfo finalUser = new UserLoginInfo();
BeanUtils.copyProperties(frontUser, finalUser);
FunctionResumeBase resumeBase = new FunctionResumeBase();
resumeBase.setId(SnowFlakeUtil.newId());
resumeBase.setRunType(1);
......@@ -808,8 +806,6 @@ public class NewEditionResumeServiceImpl implements NewEditionResumeService {
.eq("is_deleted", 0)
.set("is_show", 1);
this.resumeModelMapper.update(null, updateWrapper);
//修改模块缓存
this.resumeCacheService.updateModelSort(dto);
} else {
//排序
resumeModelMapper.updateDataSortByIds(dto.getModelSort());
......@@ -830,7 +826,7 @@ public class NewEditionResumeServiceImpl implements NewEditionResumeService {
if (StringUtils.isBlank(templateName)){
templateName = "tpl21.ejs";
}
if (com.alibaba.excel.util.StringUtils.isBlank(dto.getResumeId())){
if (StringUtils.isBlank(dto.getResumeId())){
throw new WarnException("简历ID不能为空");
}
ResumeByPdfVo vo = new ResumeByPdfVo();
......@@ -929,6 +925,44 @@ public class NewEditionResumeServiceImpl implements NewEditionResumeService {
return vo;
}
@Override
public List<String> resumeDataTagList(String resumeId) {
return resumeBaseTagMapper.selectTagNameList(resumeId);
}
@Override
public List<String> updateResumeTagList(ResumeBaseTagDto dto) {
String resumeId = dto.getResumeId();
List<String> resumeBaseTagNameList = dto.getResumeNameList();
// 如果不包含用户姓名,则给定默认展示username"未命名",其他标签都隐藏
if (!resumeBaseTagNameList.contains(ResumeEnum.ResumeBase.NAME.getName())) {
// 创建新的列表,确保包含username
List<String> newWebCodeList = new ArrayList<>();
newWebCodeList.add(ResumeEnum.ResumeBase.NAME.getName());
resumeBaseTagNameList = newWebCodeList;
}
// 调用统一的更新方法
resumeBaseTagMapper.updateResumeTag(resumeId, resumeBaseTagNameList);
// 返回更新后的标签列表
return resumeDataTagList(resumeId);
}
@Override
public String reversalExperience(ResumeExpChangeDto dto) throws Exception {
//修改工作经历
if (dto.getWorkExperience()!=null){
if (StringUtils.isNotBlank(dto.getWorkExperience().getModelName()))
updateModule(dto.getWorkExperience().getModelName(),dto.getWorkExperience());
}
//修改实习经历
if (dto.getInternshipExperience()!=null){
if (StringUtils.isNotBlank(dto.getInternshipExperience().getModelName()))
updateModule(dto.getInternshipExperience().getModelName(),dto.getInternshipExperience());
}
return null;
}
public String sanitizeFileName(String fileName) {
if (fileName == null) return null;
......
package com.bkty.system.utils;
import java.lang.reflect.Field;
import java.util.Date;
import com.google.common.collect.Maps;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
......@@ -12,6 +15,7 @@ import com.bkty.system.mapper.*;
import com.bkty.system.service.resume.ResumeCacheService;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.dromara.common.core.constant.CacheConstants;
import org.dromara.common.core.domain.UserLoginInfo;
import org.dromara.common.core.enums.ResumeEnum;
......@@ -67,6 +71,9 @@ public class NewEditionResumeUtil {
@Autowired
private FunctionResumeModelCustomMapper resumeModelCustomMapper;
@Autowired
private FunctionResumeBaseTagMapper resumeBaseTagMapper;
@PostConstruct
public void beforeInit() {
resume = this;
......@@ -110,6 +117,21 @@ public class NewEditionResumeUtil {
}
}
}
else if (model == ResumeEnum.ResumeModel.BASE){
List<FunctionResumeBaseTag> tagList = new ArrayList<>();
for (ResumeEnum.ResumeBase baseTag : EnumSet.allOf(ResumeEnum.ResumeBase.class)) {
FunctionResumeBaseTag resumeBaseTag = new FunctionResumeBaseTag();
resumeBaseTag.setId(Long.valueOf(SnowFlakeUtil.newIdString()));
resumeBaseTag.setResumeId(resumeBase.getId());
resumeBaseTag.setBaseTag(baseTag.getCode());
resumeBaseTag.setTagName(baseTag.getName());
resumeBaseTag.setBaseWebCode(baseTag.getWebCode());
resumeBaseTag.setIsShow(0);
resumeBaseTag.setDataSort(baseTag.getSort());
tagList.add(resumeBaseTag);
}
resume.resumeBaseTagMapper.insertBatch(tagList);
}
}
resume.resumeModelMapper.insertBatch(addList);
if (resumeMakeDto != null) {
......@@ -372,9 +394,50 @@ public class NewEditionResumeUtil {
resumeBase = resume.functionResumeBaseMapper.selectById(dto.getResumeId());
resume.resumeCacheService.saveResumeModelDataCache(Long.valueOf(dto.getResumeId()), Long.valueOf(dto.getResumeId()), JSON.toJSONString(resumeBase));
}
ResumeBase result = new ResumeBase();
List<String> tagList = resume.resumeBaseTagMapper.queryBaseWebCodeList(dto.getResumeId());
// 如果 tagList 为空或未指定,复制所有属性
if (tagList == null || tagList.isEmpty()) {
ResumeBase base = new ResumeBase();
BeanUtils.copyProperties(resumeBase, base);
base.setUsername("未命名");
return base;
} else {
// 根据 tagList 中的 webCode 复制对应的属性
copyPropertiesSelectively(resumeBase, result, tagList);
}
return result;
}
// 选择性地复制属性
private void copyPropertiesSelectively(FunctionResumeBase source, ResumeBase target, List<String> tagList) {
// 创建要包含的属性名称列表
String[] includedFields = tagList.stream()
.map(tag -> {
// 这里假设 webCode 直接对应字段名
// 如果需要映射,可以使用 ResumeModel 枚举来映射
return tag;
})
.toArray(String[]::new);
// 使用 BeanUtils 复制指定属性
BeanUtils.copyProperties(source, target, getExcludedFields(source, includedFields));
}
// 获取要排除的字段列表
private String[] getExcludedFields(FunctionResumeBase source, String[] includedFields) {
Set<String> includedSet = new HashSet<>(Arrays.asList(includedFields));
List<String> excludedFields = new ArrayList<>();
// 获取所有字段
Field[] fields = source.getClass().getDeclaredFields();
for (Field field : fields) {
if (!includedSet.contains(field.getName())) {
excludedFields.add(field.getName());
}
}
return excludedFields.toArray(new String[0]);
}
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment