添加个人信息编辑

This commit is contained in:
zk
2026-03-19 21:30:15 +08:00
parent 7c10fba95a
commit dc2e241151
28 changed files with 974 additions and 39 deletions
@@ -0,0 +1,153 @@
package org.jiayunet.controller;
import lombok.AllArgsConstructor;
import org.jiayunet.pojo.dto.userProfile.*;
import org.jiayunet.pojo.param.userProfile.*;
import org.jiayunet.pojo.po.*;
import org.jiayunet.service.UserProfileService;
import org.springframework.beans.BeanUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.util.stream.Collectors;
/**
* 用户个人资料控制类
*
* @author zk
*/
@RestController
@RequestMapping("/user/profile")
@AllArgsConstructor
@Validated
public class UserProfileController {
private UserProfileService userProfileService;
// ==================== 主表 ====================
@GetMapping
public UserProfileDto getProfile() {
UserProfile po = userProfileService.getProfile();
if (po == null) {
return null;
}
UserProfileDto dto = new UserProfileDto();
BeanUtils.copyProperties(po, dto);
return dto;
}
@PostMapping
public void saveProfile(@Validated @RequestBody UserProfileParam param) {
UserProfile po = new UserProfile();
BeanUtils.copyProperties(param, po);
userProfileService.saveProfile(po);
}
// ==================== 教育经历 ====================
@GetMapping("/education")
public List<UserProfileEducationDto> listEducation() {
return userProfileService.listEducation().stream().map(po -> {
UserProfileEducationDto dto = new UserProfileEducationDto();
BeanUtils.copyProperties(po, dto);
return dto;
}).collect(Collectors.toList());
}
@PostMapping("/education")
public void saveEducation(@Validated @RequestBody List<@Valid UserProfileEducationParam> params) {
List<UserProfileEducation> list = params.stream().map(p -> {
UserProfileEducation po = new UserProfileEducation();
BeanUtils.copyProperties(p, po);
return po;
}).collect(Collectors.toList());
userProfileService.saveEducationList(list);
}
// ==================== 工作经历 ====================
@GetMapping("/work")
public List<UserProfileWorkDto> listWork() {
return userProfileService.listWork().stream().map(po -> {
UserProfileWorkDto dto = new UserProfileWorkDto();
BeanUtils.copyProperties(po, dto);
return dto;
}).collect(Collectors.toList());
}
@PostMapping("/work")
public void saveWork(@Validated @RequestBody List<@Valid UserProfileWorkParam> params) {
List<UserProfileWork> list = params.stream().map(p -> {
UserProfileWork po = new UserProfileWork();
BeanUtils.copyProperties(p, po);
return po;
}).collect(Collectors.toList());
userProfileService.saveWorkList(list);
}
// ==================== 实习经历 ====================
@GetMapping("/internship")
public List<UserProfileInternshipDto> listInternship() {
return userProfileService.listInternship().stream().map(po -> {
UserProfileInternshipDto dto = new UserProfileInternshipDto();
BeanUtils.copyProperties(po, dto);
return dto;
}).collect(Collectors.toList());
}
@PostMapping("/internship")
public void saveInternship(@Validated @RequestBody List<@Valid UserProfileInternshipParam> params) {
List<UserProfileInternship> list = params.stream().map(p -> {
UserProfileInternship po = new UserProfileInternship();
BeanUtils.copyProperties(p, po);
return po;
}).collect(Collectors.toList());
userProfileService.saveInternshipList(list);
}
// ==================== 项目经历 ====================
@GetMapping("/project")
public List<UserProfileProjectDto> listProject() {
return userProfileService.listProject().stream().map(po -> {
UserProfileProjectDto dto = new UserProfileProjectDto();
BeanUtils.copyProperties(po, dto);
return dto;
}).collect(Collectors.toList());
}
@PostMapping("/project")
public void saveProject(@Validated @RequestBody List<@Valid UserProfileProjectParam> params) {
List<UserProfileProject> list = params.stream().map(p -> {
UserProfileProject po = new UserProfileProject();
BeanUtils.copyProperties(p, po);
return po;
}).collect(Collectors.toList());
userProfileService.saveProjectList(list);
}
// ==================== 竞赛经历 ====================
@GetMapping("/competition")
public List<UserProfileCompetitionDto> listCompetition() {
return userProfileService.listCompetition().stream().map(po -> {
UserProfileCompetitionDto dto = new UserProfileCompetitionDto();
BeanUtils.copyProperties(po, dto);
return dto;
}).collect(Collectors.toList());
}
@PostMapping("/competition")
public void saveCompetition(@Validated @RequestBody List<@Valid UserProfileCompetitionParam> params) {
List<UserProfileCompetition> list = params.stream().map(p -> {
UserProfileCompetition po = new UserProfileCompetition();
BeanUtils.copyProperties(p, po);
return po;
}).collect(Collectors.toList());
userProfileService.saveCompetitionList(list);
}
}
@@ -0,0 +1,29 @@
package org.jiayunet.pojo.dto.userProfile;
import lombok.Data;
import org.jiayunet.pojo.vo.DescriptionParagraph;
import java.util.List;
/**
* 竞赛经历返回
*
* @author zk
*/
@Data
public class UserProfileCompetitionDto {
private Long id;
/** 竞赛名称 */
private String competitionName;
/** 获奖情况 */
private String award;
/** 获奖时间 */
private String awardDate;
/** 描述段落 */
private List<DescriptionParagraph> description;
}
@@ -0,0 +1,49 @@
package org.jiayunet.pojo.dto.userProfile;
import lombok.Data;
import java.util.List;
/**
* 个人资料主表返回
*
* @author zk
*/
@Data
public class UserProfileDto {
private Long id;
/** 真实姓名 */
private String name;
/** 邮箱 */
private String email;
/** 手机号码 */
private String mobileNumber;
/** 身份证号 */
private String idCard;
/** 所在城市编码 */
private String regionCode;
/** 微信号 */
private String wechatNumber;
/** 作品集链接 */
private String portfolioUrl;
/** 工作年限 */
private Integer workYears;
/** 拥有经验的行业ID列表 */
private List<Long> experienceIndustryIds;
/** 技能标签列表 */
private List<String> skills;
/** 证书标签列表 */
private List<String> certificates;
}
@@ -0,0 +1,38 @@
package org.jiayunet.pojo.dto.userProfile;
import lombok.Data;
import org.jiayunet.pojo.vo.DescriptionParagraph;
import java.util.List;
/**
* 教育经历返回
*
* @author zk
*/
@Data
public class UserProfileEducationDto {
private Long id;
/** 学校名称 */
private String school;
/** 专业 */
private String major;
/** 学历 1=大专 2=本科 3=硕士 4=博士 */
private Integer degree;
/** 学习形式 0=全日制 1=非全日制 */
private Integer studyType;
/** 入学年份 */
private Integer startYear;
/** 毕业年份 */
private Integer endYear;
/** 描述段落 */
private List<DescriptionParagraph> description;
}
@@ -0,0 +1,32 @@
package org.jiayunet.pojo.dto.userProfile;
import lombok.Data;
import org.jiayunet.pojo.vo.DescriptionParagraph;
import java.util.List;
/**
* 实习经历返回
*
* @author zk
*/
@Data
public class UserProfileInternshipDto {
private Long id;
/** 公司名称 */
private String companyName;
/** 职位 */
private String position;
/** 开始时间 */
private String startDate;
/** 结束时间 */
private String endDate;
/** 描述段落 */
private List<DescriptionParagraph> description;
}
@@ -0,0 +1,35 @@
package org.jiayunet.pojo.dto.userProfile;
import lombok.Data;
import org.jiayunet.pojo.vo.DescriptionParagraph;
import java.util.List;
/**
* 项目经历返回
*
* @author zk
*/
@Data
public class UserProfileProjectDto {
private Long id;
/** 所属公司 */
private String companyName;
/** 项目名称 */
private String projectName;
/** 担任角色 */
private String role;
/** 开始时间 */
private String startDate;
/** 结束时间 */
private String endDate;
/** 描述段落 */
private List<DescriptionParagraph> description;
}
@@ -0,0 +1,32 @@
package org.jiayunet.pojo.dto.userProfile;
import lombok.Data;
import org.jiayunet.pojo.vo.DescriptionParagraph;
import java.util.List;
/**
* 工作经历返回
*
* @author zk
*/
@Data
public class UserProfileWorkDto {
private Long id;
/** 公司名称 */
private String companyName;
/** 职位 */
private String position;
/** 开始时间 */
private String startDate;
/** 结束时间 */
private String endDate;
/** 描述段落 */
private List<DescriptionParagraph> description;
}
@@ -0,0 +1,29 @@
package org.jiayunet.pojo.param.userProfile;
import lombok.Data;
import org.jiayunet.pojo.vo.DescriptionParagraph;
import javax.validation.constraints.NotBlank;
import java.util.List;
/**
* 竞赛经历保存入参
*
* @author zk
*/
@Data
public class UserProfileCompetitionParam {
/** 竞赛名称 */
@NotBlank(message = "竞赛名称不能为空")
private String competitionName;
/** 获奖情况,如全国二等奖 */
private String award;
/** 获奖时间,格式:2023.07 */
private String awardDate;
/** 描述段落 */
private List<DescriptionParagraph> description;
}
@@ -0,0 +1,40 @@
package org.jiayunet.pojo.param.userProfile;
import lombok.Data;
import org.jiayunet.pojo.vo.DescriptionParagraph;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List;
/**
* 教育经历保存入参
*
* @author zk
*/
@Data
public class UserProfileEducationParam {
/** 学校名称 */
@NotBlank(message = "学校名称不能为空")
private String school;
/** 专业 */
private String major;
/** 学历 1=大专 2=本科 3=硕士 4=博士 */
@NotNull(message = "学历不能为空")
private Integer degree;
/** 学习形式 0=全日制 1=非全日制 */
private Integer studyType;
/** 入学年份 */
private Integer startYear;
/** 毕业年份 */
private Integer endYear;
/** 描述段落 */
private List<DescriptionParagraph> description;
}
@@ -0,0 +1,34 @@
package org.jiayunet.pojo.param.userProfile;
import lombok.Data;
import org.jiayunet.pojo.vo.DescriptionParagraph;
import javax.validation.constraints.NotBlank;
import java.util.List;
/**
* 实习经历保存入参
*
* @author zk
*/
@Data
public class UserProfileInternshipParam {
/** 公司名称 */
@NotBlank(message = "公司名称不能为空")
private String companyName;
/** 职位 */
@NotBlank(message = "职位不能为空")
private String position;
/** 开始时间,格式:2023.06 */
@NotBlank(message = "开始时间不能为空")
private String startDate;
/** 结束时间,格式:2023.09,至今则为空 */
private String endDate;
/** 描述段落 */
private List<DescriptionParagraph> description;
}
@@ -0,0 +1,49 @@
package org.jiayunet.pojo.param.userProfile;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.util.List;
/**
* 个人资料主表保存入参
*
* @author zk
*/
@Data
public class UserProfileParam {
/** 真实姓名 */
private String name;
/** 邮箱 */
private String email;
/** 手机号码 */
private String mobileNumber;
/** 身份证号 */
private String idCard;
/** 所在城市编码 */
@NotBlank(message = "所在城市不能为空")
private String regionCode;
/** 微信号 */
private String wechatNumber;
/** 作品集链接 */
private String portfolioUrl;
/** 工作年限 */
private Integer workYears;
/** 拥有经验的行业ID列表 */
private List<Long> experienceIndustryIds;
/** 技能标签列表 */
private List<String> skills;
/** 证书标签列表 */
private List<String> certificates;
}
@@ -0,0 +1,36 @@
package org.jiayunet.pojo.param.userProfile;
import lombok.Data;
import org.jiayunet.pojo.vo.DescriptionParagraph;
import javax.validation.constraints.NotBlank;
import java.util.List;
/**
* 项目经历保存入参
*
* @author zk
*/
@Data
public class UserProfileProjectParam {
/** 所属公司 */
private String companyName;
/** 项目名称 */
@NotBlank(message = "项目名称不能为空")
private String projectName;
/** 担任角色 */
private String role;
/** 开始时间,格式:2023.06 */
@NotBlank(message = "开始时间不能为空")
private String startDate;
/** 结束时间,格式:2023.09,至今则为空 */
private String endDate;
/** 描述段落 */
private List<DescriptionParagraph> description;
}
@@ -0,0 +1,34 @@
package org.jiayunet.pojo.param.userProfile;
import lombok.Data;
import org.jiayunet.pojo.vo.DescriptionParagraph;
import javax.validation.constraints.NotBlank;
import java.util.List;
/**
* 工作经历保存入参
*
* @author zk
*/
@Data
public class UserProfileWorkParam {
/** 公司名称 */
@NotBlank(message = "公司名称不能为空")
private String companyName;
/** 职位 */
@NotBlank(message = "职位不能为空")
private String position;
/** 开始时间,格式:2023.06 */
@NotBlank(message = "开始时间不能为空")
private String startDate;
/** 结束时间,格式:2023.09,至今则为空 */
private String endDate;
/** 描述段落 */
private List<DescriptionParagraph> description;
}
@@ -0,0 +1,279 @@
package org.jiayunet.service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.jiayunet.mapper.*;
import org.jiayunet.pojo.po.*;
import org.jiayunet.tool.UserSecurityTool;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.Instant;
import java.util.List;
import java.util.stream.IntStream;
/**
* 用户个人资料服务
* <p>依赖:无</p>
* <p>使用表:bg_user_profile(主表CRUD)、bg_user_profile_education(教育经历)、
* bg_user_profile_work(工作经历)、bg_user_profile_internship(实习经历)、
* bg_user_profile_project(项目经历)、bg_user_profile_competition(竞赛经历)</p>
*
* @author zk
*/
@Service
@Slf4j
public class UserProfileService {
@Autowired
private UserProfileMapper userProfileMapper;
@Autowired
private UserProfileEducationMapper educationMapper;
@Autowired
private UserProfileWorkMapper workMapper;
@Autowired
private UserProfileInternshipMapper internshipMapper;
@Autowired
private UserProfileProjectMapper projectMapper;
@Autowired
private UserProfileCompetitionMapper competitionMapper;
// ==================== 主表 ====================
/** 查询当前用户个人资料 */
public UserProfile getProfile() {
Long userId = UserSecurityTool.getUserId();
return userProfileMapper.selectOne(
new LambdaQueryWrapper<UserProfile>().eq(UserProfile::getUserId, userId));
}
/**
* 保存个人资料主表(upsert)
* <p>1. 按userId查询是否存在 2. 存在则更新,不存在则插入</p>
*/
@Transactional(rollbackFor = Exception.class)
public void saveProfile(UserProfile profile) {
Long userId = UserSecurityTool.getUserId();
UserProfile existing = userProfileMapper.selectOne(
new LambdaQueryWrapper<UserProfile>().eq(UserProfile::getUserId, userId));
Instant now = Instant.now();
if (existing != null) {
profile.setId(existing.getId());
profile.setUserId(userId);
profile.setCreateTime(existing.getCreateTime());
profile.setUpdateTime(now);
userProfileMapper.updateById(profile);
} else {
profile.setUserId(userId);
profile.setCreateTime(now);
profile.setUpdateTime(now);
userProfileMapper.insert(profile);
}
}
// ==================== 教育经历 ====================
/** 查询教育经历列表 */
public List<UserProfileEducation> listEducation() {
Long userId = UserSecurityTool.getUserId();
return educationMapper.selectList(
new LambdaQueryWrapper<UserProfileEducation>()
.eq(UserProfileEducation::getUserId, userId)
.orderByAsc(UserProfileEducation::getSortOrder));
}
/**
* 保存教育经历列表(先删后插)
* <p>1. 删除该用户所有教育经历 2. 批量插入新数据,自动填充userId/profileId/sortOrder/时间</p>
*/
@Transactional(rollbackFor = Exception.class)
public void saveEducationList(List<UserProfileEducation> list) {
Long userId = UserSecurityTool.getUserId();
Long profileId = getOrCreateProfileId(userId);
educationMapper.delete(new LambdaQueryWrapper<UserProfileEducation>().eq(UserProfileEducation::getUserId, userId));
if (list.isEmpty()) {
return;
}
Instant now = Instant.now();
IntStream.range(0, list.size()).forEach(i -> {
UserProfileEducation item = list.get(i);
item.setUserId(userId);
item.setProfileId(profileId);
item.setSortOrder(i);
item.setCreateTime(now);
item.setUpdateTime(now);
});
educationMapper.batchInsert(list);
}
// ==================== 工作经历 ====================
/** 查询工作经历列表 */
public List<UserProfileWork> listWork() {
Long userId = UserSecurityTool.getUserId();
return workMapper.selectList(
new LambdaQueryWrapper<UserProfileWork>()
.eq(UserProfileWork::getUserId, userId)
.orderByAsc(UserProfileWork::getSortOrder));
}
/**
* 保存工作经历列表(先删后插)
* <p>1. 删除该用户所有工作经历 2. 批量插入新数据</p>
*/
@Transactional(rollbackFor = Exception.class)
public void saveWorkList(List<UserProfileWork> list) {
Long userId = UserSecurityTool.getUserId();
Long profileId = getOrCreateProfileId(userId);
workMapper.delete(
new LambdaQueryWrapper<UserProfileWork>().eq(UserProfileWork::getUserId, userId));
if (list.isEmpty()) {
return;
}
Instant now = Instant.now();
IntStream.range(0, list.size()).forEach(i -> {
UserProfileWork item = list.get(i);
item.setUserId(userId);
item.setProfileId(profileId);
item.setSortOrder(i);
item.setCreateTime(now);
item.setUpdateTime(now);
});
workMapper.batchInsert(list);
}
// ==================== 实习经历 ====================
/** 查询实习经历列表 */
public List<UserProfileInternship> listInternship() {
Long userId = UserSecurityTool.getUserId();
return internshipMapper.selectList(
new LambdaQueryWrapper<UserProfileInternship>()
.eq(UserProfileInternship::getUserId, userId)
.orderByAsc(UserProfileInternship::getSortOrder));
}
/**
* 保存实习经历列表(先删后插)
* <p>1. 删除该用户所有实习经历 2. 批量插入新数据</p>
*/
@Transactional(rollbackFor = Exception.class)
public void saveInternshipList(List<UserProfileInternship> list) {
Long userId = UserSecurityTool.getUserId();
Long profileId = getOrCreateProfileId(userId);
internshipMapper.delete(
new LambdaQueryWrapper<UserProfileInternship>().eq(UserProfileInternship::getUserId, userId));
if (list.isEmpty()) {
return;
}
Instant now = Instant.now();
IntStream.range(0, list.size()).forEach(i -> {
UserProfileInternship item = list.get(i);
item.setUserId(userId);
item.setProfileId(profileId);
item.setSortOrder(i);
item.setCreateTime(now);
item.setUpdateTime(now);
});
internshipMapper.batchInsert(list);
}
// ==================== 项目经历 ====================
/** 查询项目经历列表 */
public List<UserProfileProject> listProject() {
Long userId = UserSecurityTool.getUserId();
return projectMapper.selectList(
new LambdaQueryWrapper<UserProfileProject>()
.eq(UserProfileProject::getUserId, userId)
.orderByAsc(UserProfileProject::getSortOrder));
}
/**
* 保存项目经历列表(先删后插)
* <p>1. 删除该用户所有项目经历 2. 批量插入新数据</p>
*/
@Transactional(rollbackFor = Exception.class)
public void saveProjectList(List<UserProfileProject> list) {
Long userId = UserSecurityTool.getUserId();
Long profileId = getOrCreateProfileId(userId);
projectMapper.delete(
new LambdaQueryWrapper<UserProfileProject>().eq(UserProfileProject::getUserId, userId));
if (list.isEmpty()) {
return;
}
Instant now = Instant.now();
IntStream.range(0, list.size()).forEach(i -> {
UserProfileProject item = list.get(i);
item.setUserId(userId);
item.setProfileId(profileId);
item.setSortOrder(i);
item.setCreateTime(now);
item.setUpdateTime(now);
});
projectMapper.batchInsert(list);
}
// ==================== 竞赛经历 ====================
/** 查询竞赛经历列表 */
public List<UserProfileCompetition> listCompetition() {
Long userId = UserSecurityTool.getUserId();
return competitionMapper.selectList(
new LambdaQueryWrapper<UserProfileCompetition>()
.eq(UserProfileCompetition::getUserId, userId)
.orderByAsc(UserProfileCompetition::getSortOrder));
}
/**
* 保存竞赛经历列表(先删后插)
* <p>1. 删除该用户所有竞赛经历 2. 批量插入新数据</p>
*/
@Transactional(rollbackFor = Exception.class)
public void saveCompetitionList(List<UserProfileCompetition> list) {
Long userId = UserSecurityTool.getUserId();
Long profileId = getOrCreateProfileId(userId);
competitionMapper.delete(
new LambdaQueryWrapper<UserProfileCompetition>().eq(UserProfileCompetition::getUserId, userId));
if (list.isEmpty()) {
return;
}
Instant now = Instant.now();
IntStream.range(0, list.size()).forEach(i -> {
UserProfileCompetition item = list.get(i);
item.setUserId(userId);
item.setProfileId(profileId);
item.setSortOrder(i);
item.setCreateTime(now);
item.setUpdateTime(now);
});
competitionMapper.batchInsert(list);
}
// ==================== 内部方法 ====================
/**
* 获取用户的profileId,不存在则自动创建空主表记录
* <p>子表保存时需要profileId,如果用户还没创建过主表,先插入一条空记录</p>
*/
private Long getOrCreateProfileId(Long userId) {
UserProfile profile = userProfileMapper.selectOne(
new LambdaQueryWrapper<UserProfile>().eq(UserProfile::getUserId, userId));
if (profile != null) {
return profile.getId();
}
profile = new UserProfile();
profile.setUserId(userId);
Instant now = Instant.now();
profile.setCreateTime(now);
profile.setUpdateTime(now);
userProfileMapper.insert(profile);
return profile.getId();
}
}