From a915d709f4dc92a593803fe902022104cb83d342 Mon Sep 17 00:00:00 2001 From: zk Date: Thu, 2 Jul 2026 14:12:45 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=84=E7=90=86=E7=AE=80=E5=8E=86=E4=B8=8D?= =?UTF-8?q?=E5=9C=A8=E9=99=90=E5=88=B6=E9=9D=9E=E7=A9=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../param/resume/ResumeCompetitionParam.java | 6 +- .../param/resume/ResumeEducationParam.java | 9 +- .../param/resume/ResumeInternshipParam.java | 9 +- .../pojo/param/resume/ResumeParam.java | 10 ++ .../pojo/param/resume/ResumeProjectParam.java | 9 +- .../pojo/param/resume/ResumeWorkParam.java | 9 +- .../jiayunet/service/UserProfileService.java | 21 ++-- .../jiayunet/service/UserResumeService.java | 104 +++++++++++------- 8 files changed, 115 insertions(+), 62 deletions(-) diff --git a/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeCompetitionParam.java b/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeCompetitionParam.java index e4ccfc2..2a79947 100644 --- a/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeCompetitionParam.java +++ b/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeCompetitionParam.java @@ -3,7 +3,7 @@ package org.jiayunet.pojo.param.resume; import lombok.Data; import org.jiayunet.pojo.vo.DescriptionParagraph; -import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; import java.util.List; /** @@ -15,13 +15,15 @@ import java.util.List; public class ResumeCompetitionParam { /** 竞赛名称 */ - @NotBlank(message = "竞赛名称不能为空") + @Size(max = 200, message = "竞赛名称长度不能超过200") private String competitionName; /** 获奖情况,如全国二等奖 */ + @Size(max = 200, message = "获奖情况长度不能超过200") private String award; /** 获奖时间,格式:2023.07 */ + @Size(max = 10, message = "获奖时间长度不能超过10") private String awardDate; /** 描述段落 */ diff --git a/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeEducationParam.java b/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeEducationParam.java index 5bdbb0a..0cade71 100644 --- a/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeEducationParam.java +++ b/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeEducationParam.java @@ -3,7 +3,7 @@ package org.jiayunet.pojo.param.resume; import lombok.Data; import org.jiayunet.pojo.vo.DescriptionParagraph; -import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; import java.util.List; /** @@ -15,22 +15,27 @@ import java.util.List; public class ResumeEducationParam { /** 学校名称 */ - @NotBlank(message = "学校名称不能为空") + @Size(max = 100, message = "学校名称长度不能超过100") private String school; /** 专业 */ + @Size(max = 100, message = "专业长度不能超过100") private String major; /** 学历:大专/本科/硕士/博士 */ + @Size(max = 20, message = "学历长度不能超过20") private String degree; /** 学习形式:全日制/非全日制 */ + @Size(max = 20, message = "学习形式长度不能超过20") private String studyType; /** 开始时间,格式:2023.09 */ + @Size(max = 10, message = "开始时间长度不能超过10") private String startDate; /** 结束时间,格式:2024.06 */ + @Size(max = 10, message = "结束时间长度不能超过10") private String endDate; /** 描述段落 */ diff --git a/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeInternshipParam.java b/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeInternshipParam.java index 4ff4332..8c2b644 100644 --- a/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeInternshipParam.java +++ b/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeInternshipParam.java @@ -3,7 +3,7 @@ package org.jiayunet.pojo.param.resume; import lombok.Data; import org.jiayunet.pojo.vo.DescriptionParagraph; -import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; import java.util.List; /** @@ -15,18 +15,19 @@ import java.util.List; public class ResumeInternshipParam { /** 公司名称 */ - @NotBlank(message = "公司名称不能为空") + @Size(max = 200, message = "公司名称长度不能超过200") private String companyName; /** 职位 */ - @NotBlank(message = "职位不能为空") + @Size(max = 100, message = "职位长度不能超过100") private String position; /** 开始时间,格式:2023.06 */ - @NotBlank(message = "开始时间不能为空") + @Size(max = 10, message = "开始时间长度不能超过10") private String startDate; /** 结束时间,格式:2023.09,至今则为空 */ + @Size(max = 10, message = "结束时间长度不能超过10") private String endDate; /** 描述段落 */ diff --git a/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeParam.java b/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeParam.java index 485d3a8..8232cd3 100644 --- a/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeParam.java +++ b/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeParam.java @@ -2,6 +2,7 @@ package org.jiayunet.pojo.param.resume; import lombok.Data; +import javax.validation.constraints.Size; import java.util.List; /** @@ -16,30 +17,39 @@ public class ResumeParam { private Long resumeId; /** 简历名称 */ + @Size(max = 100, message = "简历名称长度不能超过100") private String resumeName; /** 目标岗位 */ + @Size(max = 100, message = "目标岗位长度不能超过100") private String targetPosition; /** 头像URL */ + @Size(max = 500, message = "头像URL长度不能超过500") private String avatarUrl; /** 真实姓名 */ + @Size(max = 50, message = "真实姓名长度不能超过50") private String name; /** 邮箱 */ + @Size(max = 100, message = "邮箱长度不能超过100") private String email; /** 手机号码 */ + @Size(max = 20, message = "手机号码长度不能超过20") private String mobileNumber; /** 所在城市 */ + @Size(max = 50, message = "所在城市长度不能超过50") private String city; /** 微信号 */ + @Size(max = 50, message = "微信号长度不能超过50") private String wechatNumber; /** 作品集链接 */ + @Size(max = 500, message = "作品集链接长度不能超过500") private String portfolioUrl; /** 技能标签列表 */ diff --git a/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeProjectParam.java b/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeProjectParam.java index 9c61807..be89a1a 100644 --- a/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeProjectParam.java +++ b/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeProjectParam.java @@ -3,7 +3,7 @@ package org.jiayunet.pojo.param.resume; import lombok.Data; import org.jiayunet.pojo.vo.DescriptionParagraph; -import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; import java.util.List; /** @@ -15,20 +15,23 @@ import java.util.List; public class ResumeProjectParam { /** 所属公司 */ + @Size(max = 200, message = "所属公司长度不能超过200") private String companyName; /** 项目名称 */ - @NotBlank(message = "项目名称不能为空") + @Size(max = 200, message = "项目名称长度不能超过200") private String projectName; /** 担任角色 */ + @Size(max = 100, message = "担任角色长度不能超过100") private String role; /** 开始时间,格式:2023.06 */ - @NotBlank(message = "开始时间不能为空") + @Size(max = 10, message = "开始时间长度不能超过10") private String startDate; /** 结束时间,格式:2023.09,至今则为空 */ + @Size(max = 10, message = "结束时间长度不能超过10") private String endDate; /** 描述段落 */ diff --git a/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeWorkParam.java b/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeWorkParam.java index cf6d9b1..d7b8efa 100644 --- a/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeWorkParam.java +++ b/client-api/src/main/java/org/jiayunet/pojo/param/resume/ResumeWorkParam.java @@ -3,7 +3,7 @@ package org.jiayunet.pojo.param.resume; import lombok.Data; import org.jiayunet.pojo.vo.DescriptionParagraph; -import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Size; import java.util.List; /** @@ -15,18 +15,19 @@ import java.util.List; public class ResumeWorkParam { /** 公司名称 */ - @NotBlank(message = "公司名称不能为空") + @Size(max = 200, message = "公司名称长度不能超过200") private String companyName; /** 职位 */ - @NotBlank(message = "职位不能为空") + @Size(max = 100, message = "职位长度不能超过100") private String position; /** 开始时间,格式:2023.06 */ - @NotBlank(message = "开始时间不能为空") + @Size(max = 10, message = "开始时间长度不能超过10") private String startDate; /** 结束时间,格式:2023.09,至今则为空 */ + @Size(max = 10, message = "结束时间长度不能超过10") private String endDate; /** 描述段落 */ diff --git a/client-api/src/main/java/org/jiayunet/service/UserProfileService.java b/client-api/src/main/java/org/jiayunet/service/UserProfileService.java index 0b21a4e..22fbf91 100644 --- a/client-api/src/main/java/org/jiayunet/service/UserProfileService.java +++ b/client-api/src/main/java/org/jiayunet/service/UserProfileService.java @@ -341,15 +341,18 @@ public class UserProfileService { Long profileId; if (existing != null) { profileId = existing.getId(); - existing.setName(resume.getName()); - existing.setEmail(resume.getEmail()); - existing.setMobileNumber(resume.getMobileNumber()); - existing.setWechatNumber(resume.getWechatNumber()); - existing.setPortfolioUrl(resume.getPortfolioUrl()); - existing.setSkills(resume.getSkills()); - existing.setCertificates(resume.getCertificates()); - existing.setUpdateTime(now); - userProfileMapper.updateById(existing); + // A语义:严格镜像简历共有字段(含清空为null),与子表先删后插的镜像行为一致; + // idCard/regionCode及AI派生字段(schoolRank/majorIds等)为个人资料独有,不在同步范围 + userProfileMapper.update(null, new com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper() + .eq(UserProfile::getId, profileId) + .set(UserProfile::getName, resume.getName()) + .set(UserProfile::getEmail, resume.getEmail()) + .set(UserProfile::getMobileNumber, resume.getMobileNumber()) + .set(UserProfile::getWechatNumber, resume.getWechatNumber()) + .set(UserProfile::getPortfolioUrl, resume.getPortfolioUrl()) + .set(UserProfile::getSkills, resume.getSkills(), JSON_TYPE_HANDLER) + .set(UserProfile::getCertificates, resume.getCertificates(), JSON_TYPE_HANDLER) + .set(UserProfile::getUpdateTime, now)); } else { UserProfile profile = new UserProfile(); profile.setUserId(userId); diff --git a/client-api/src/main/java/org/jiayunet/service/UserResumeService.java b/client-api/src/main/java/org/jiayunet/service/UserResumeService.java index 471ae98..c1915ec 100644 --- a/client-api/src/main/java/org/jiayunet/service/UserResumeService.java +++ b/client-api/src/main/java/org/jiayunet/service/UserResumeService.java @@ -40,6 +40,9 @@ public class UserResumeService { @Value("${app.resume.max-count:5}") private int maxResumeCount; + /** JSON字段的TypeHandler,UpdateWrapper显式set时需指定,否则JSON字段不会正确序列化 */ + private static final String JSON_TYPE_HANDLER = "typeHandler=com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"; + @Autowired private UserResumeEducationMapper educationMapper; @@ -115,16 +118,24 @@ public class UserResumeService { userResumeMapper.insert(resume); return resume.getId(); } - // 更新已有简历 + // 更新已有简历(用户可编辑字段用LambdaUpdateWrapper显式set,允许清空为null,绕过全局update-strategy=not_null) UserResume existing = userResumeMapper.selectById(resumeId); checkOwnership(existing); - resume.setId(resumeId); - resume.setUserId(userId); - resume.setCreateTime(existing.getCreateTime()); - resume.setUpdateTime(now); - resume.setIsDefault(existing.getIsDefault()); - resume.setSortOrder(existing.getSortOrder()); - userResumeMapper.updateById(resume); + userResumeMapper.update(null, new LambdaUpdateWrapper() + .eq(UserResume::getId, resumeId) + .set(UserResume::getResumeName, resume.getResumeName()) + .set(UserResume::getTargetPosition, resume.getTargetPosition()) + .set(UserResume::getAvatarUrl, resume.getAvatarUrl()) + .set(UserResume::getName, resume.getName()) + .set(UserResume::getEmail, resume.getEmail()) + .set(UserResume::getMobileNumber, resume.getMobileNumber()) + .set(UserResume::getCity, resume.getCity()) + .set(UserResume::getWechatNumber, resume.getWechatNumber()) + .set(UserResume::getPortfolioUrl, resume.getPortfolioUrl()) + .set(UserResume::getSkills, resume.getSkills(), JSON_TYPE_HANDLER) + .set(UserResume::getCertificates, resume.getCertificates(), JSON_TYPE_HANDLER) + .set(UserResume::getSummary, resume.getSummary()) + .set(UserResume::getUpdateTime, now)); return resumeId; } @@ -491,12 +502,17 @@ public class UserResumeService { UserResumeEducation existing = educationMapper.selectById(po.getId()); Assert.notNull(existing, "教育经历不存在"); checkResumeOwnership(existing.getResumeId()); - po.setResumeId(existing.getResumeId()); - po.setUserId(existing.getUserId()); - po.setSortOrder(existing.getSortOrder()); - po.setCreateTime(existing.getCreateTime()); - po.setUpdateTime(Instant.now()); - educationMapper.updateById(po); + // 显式set用户可编辑字段(允许清空为null);resumeId/userId/sortOrder/createTime保留原值 + educationMapper.update(null, new LambdaUpdateWrapper() + .eq(UserResumeEducation::getId, po.getId()) + .set(UserResumeEducation::getSchool, po.getSchool()) + .set(UserResumeEducation::getMajor, po.getMajor()) + .set(UserResumeEducation::getDegree, po.getDegree()) + .set(UserResumeEducation::getStudyType, po.getStudyType()) + .set(UserResumeEducation::getStartDate, po.getStartDate()) + .set(UserResumeEducation::getEndDate, po.getEndDate()) + .set(UserResumeEducation::getDescription, po.getDescription(), JSON_TYPE_HANDLER) + .set(UserResumeEducation::getUpdateTime, Instant.now())); touchResumeUpdateTime(existing.getResumeId()); } @@ -509,12 +525,15 @@ public class UserResumeService { UserResumeWork existing = workMapper.selectById(po.getId()); Assert.notNull(existing, "工作经历不存在"); checkResumeOwnership(existing.getResumeId()); - po.setResumeId(existing.getResumeId()); - po.setUserId(existing.getUserId()); - po.setSortOrder(existing.getSortOrder()); - po.setCreateTime(existing.getCreateTime()); - po.setUpdateTime(Instant.now()); - workMapper.updateById(po); + // 显式set用户可编辑字段(允许清空为null);resumeId/userId/sortOrder/createTime保留原值 + workMapper.update(null, new LambdaUpdateWrapper() + .eq(UserResumeWork::getId, po.getId()) + .set(UserResumeWork::getCompanyName, po.getCompanyName()) + .set(UserResumeWork::getPosition, po.getPosition()) + .set(UserResumeWork::getStartDate, po.getStartDate()) + .set(UserResumeWork::getEndDate, po.getEndDate()) + .set(UserResumeWork::getDescription, po.getDescription(), JSON_TYPE_HANDLER) + .set(UserResumeWork::getUpdateTime, Instant.now())); touchResumeUpdateTime(existing.getResumeId()); } @@ -527,12 +546,15 @@ public class UserResumeService { UserResumeInternship existing = internshipMapper.selectById(po.getId()); Assert.notNull(existing, "实习经历不存在"); checkResumeOwnership(existing.getResumeId()); - po.setResumeId(existing.getResumeId()); - po.setUserId(existing.getUserId()); - po.setSortOrder(existing.getSortOrder()); - po.setCreateTime(existing.getCreateTime()); - po.setUpdateTime(Instant.now()); - internshipMapper.updateById(po); + // 显式set用户可编辑字段(允许清空为null);resumeId/userId/sortOrder/createTime保留原值 + internshipMapper.update(null, new LambdaUpdateWrapper() + .eq(UserResumeInternship::getId, po.getId()) + .set(UserResumeInternship::getCompanyName, po.getCompanyName()) + .set(UserResumeInternship::getPosition, po.getPosition()) + .set(UserResumeInternship::getStartDate, po.getStartDate()) + .set(UserResumeInternship::getEndDate, po.getEndDate()) + .set(UserResumeInternship::getDescription, po.getDescription(), JSON_TYPE_HANDLER) + .set(UserResumeInternship::getUpdateTime, Instant.now())); touchResumeUpdateTime(existing.getResumeId()); } @@ -545,12 +567,16 @@ public class UserResumeService { UserResumeProject existing = projectMapper.selectById(po.getId()); Assert.notNull(existing, "项目经历不存在"); checkResumeOwnership(existing.getResumeId()); - po.setResumeId(existing.getResumeId()); - po.setUserId(existing.getUserId()); - po.setSortOrder(existing.getSortOrder()); - po.setCreateTime(existing.getCreateTime()); - po.setUpdateTime(Instant.now()); - projectMapper.updateById(po); + // 显式set用户可编辑字段(允许清空为null);resumeId/userId/sortOrder/createTime保留原值 + projectMapper.update(null, new LambdaUpdateWrapper() + .eq(UserResumeProject::getId, po.getId()) + .set(UserResumeProject::getCompanyName, po.getCompanyName()) + .set(UserResumeProject::getProjectName, po.getProjectName()) + .set(UserResumeProject::getRole, po.getRole()) + .set(UserResumeProject::getStartDate, po.getStartDate()) + .set(UserResumeProject::getEndDate, po.getEndDate()) + .set(UserResumeProject::getDescription, po.getDescription(), JSON_TYPE_HANDLER) + .set(UserResumeProject::getUpdateTime, Instant.now())); touchResumeUpdateTime(existing.getResumeId()); } @@ -563,12 +589,14 @@ public class UserResumeService { UserResumeCompetition existing = competitionMapper.selectById(po.getId()); Assert.notNull(existing, "竞赛经历不存在"); checkResumeOwnership(existing.getResumeId()); - po.setResumeId(existing.getResumeId()); - po.setUserId(existing.getUserId()); - po.setSortOrder(existing.getSortOrder()); - po.setCreateTime(existing.getCreateTime()); - po.setUpdateTime(Instant.now()); - competitionMapper.updateById(po); + // 显式set用户可编辑字段(允许清空为null);resumeId/userId/sortOrder/createTime保留原值 + competitionMapper.update(null, new LambdaUpdateWrapper() + .eq(UserResumeCompetition::getId, po.getId()) + .set(UserResumeCompetition::getCompetitionName, po.getCompetitionName()) + .set(UserResumeCompetition::getAward, po.getAward()) + .set(UserResumeCompetition::getAwardDate, po.getAwardDate()) + .set(UserResumeCompetition::getDescription, po.getDescription(), JSON_TYPE_HANDLER) + .set(UserResumeCompetition::getUpdateTime, Instant.now())); touchResumeUpdateTime(existing.getResumeId()); }