Commit 4bf1304e authored by 刘斌's avatar 刘斌

fix: 修复业务问题

parent b5daf20e
...@@ -64,8 +64,8 @@ ...@@ -64,8 +64,8 @@
<artifactId>maven-compiler-plugin</artifactId> <artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version> <version>${maven-compiler-plugin.version}</version>
<configuration> <configuration>
<source>17</source> <source>21</source>
<target>17</target> <target>21</target>
<encoding>UTF-8</encoding> <encoding>UTF-8</encoding>
</configuration> </configuration>
</plugin> </plugin>
......
...@@ -5,10 +5,12 @@ import org.springframework.boot.SpringApplication; ...@@ -5,10 +5,12 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
@Slf4j @Slf4j
@EnableAsync @EnableAsync
@EnableCaching @EnableCaching
@EnableScheduling
@SpringBootApplication(scanBasePackages = {"top.binfast.daemon.codegen", "top.binfast.app", "com.example"}) @SpringBootApplication(scanBasePackages = {"top.binfast.daemon.codegen", "top.binfast.app", "com.example"})
public class Application { public class Application {
......
package com.example.config;
import com.example.constant.HrCacheConstants;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import top.binfast.app.biz.sysapi.bean.params.sysDept.SysDeptParam;
import top.binfast.common.redis.util.CacheUtils;
/**
* @author 刘斌
* @date 2025/11/12 10:19
*/
@Aspect
@Component
@Slf4j
public class RefreshDeptCacheAspect {
/**
* 定义切入点:Controller包下的方法
*/
@Pointcut("execution(* top.binfast.app.admin.controller.SysDeptCtrl.add(..)) ||" +
" execution(* top.binfast.app.admin.controller.SysDeptCtrl.edit(..)) ||" +
" execution(* top.binfast.app.admin.controller.SysDeptCtrl.deleteOne(..))")
public void deptChangePointcut() {}
/**
* 方法一:基于注解的监听
*/
@AfterReturning(pointcut = "deptChangePointcut()", returning = "result")
public void afterOperation(JoinPoint joinPoint, Object result) {
try {
// 获取方法参数
Object[] args = joinPoint.getArgs();
if (args == null || args.length == 0) {
return;
}
Long deptId = null;
if (args[0] instanceof SysDeptParam param) {
deptId = param.getId();
} else if (args[0] instanceof Long) {
deptId = (Long) args[0];
}
// 清除部门缓存
CacheUtils.evict(HrCacheConstants.DEPT_AND_PARENT_NAME, deptId + "");
} catch (Exception e) {
log.error("清楚部门缓存异常", e);
}
}
}
package com.example.constant;
/**
* @author 刘斌
* @date 2025/11/12 10:30
*/
public interface HrCacheConstants {
/**
* 部门及以下权限
*/
String DEPT_AND_PARENT_NAME = "dept_and_parent_name#30d";
}
...@@ -4,7 +4,6 @@ import cn.dev33.satoken.annotation.SaCheckPermission; ...@@ -4,7 +4,6 @@ import cn.dev33.satoken.annotation.SaCheckPermission;
import com.alibaba.cola.dto.PageResponse; import com.alibaba.cola.dto.PageResponse;
import com.alibaba.cola.dto.Response; import com.alibaba.cola.dto.Response;
import com.alibaba.cola.dto.SingleResponse; import com.alibaba.cola.dto.SingleResponse;
import com.example.domain.EmployeeInfo;
import com.example.domain.params.*; import com.example.domain.params.*;
import com.example.domain.vo.EmployeeInfoImportVo; import com.example.domain.vo.EmployeeInfoImportVo;
import com.example.domain.vo.EmployeeInfoVo; import com.example.domain.vo.EmployeeInfoVo;
...@@ -15,16 +14,13 @@ import jakarta.validation.constraints.NotEmpty; ...@@ -15,16 +14,13 @@ import jakarta.validation.constraints.NotEmpty;
import org.dromara.core.trans.anno.TransMethodResult; import org.dromara.core.trans.anno.TransMethodResult;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import top.binfast.app.biz.sysapi.bean.vo.sysUser.SysUserImportVo; import org.springframework.web.multipart.MultipartFile;
import top.binfast.common.core.constant.BusinessType; import top.binfast.common.core.constant.BusinessType;
import top.binfast.common.core.util.Json;
import top.binfast.common.core.util.MapstructUtils;
import top.binfast.common.core.util.ResponseUtils; import top.binfast.common.core.util.ResponseUtils;
import top.binfast.common.core.validate.AddGroup; import top.binfast.common.core.validate.AddGroup;
import top.binfast.common.core.validate.EditGroup; import top.binfast.common.core.validate.EditGroup;
import top.binfast.common.excel.annotion.ExcelExport; import top.binfast.common.excel.annotion.ExcelExport;
import top.binfast.common.excel.annotion.ExcelStream; import top.binfast.common.excel.annotion.ExcelStream;
import top.binfast.common.excel.core.ExcelDownHandler;
import top.binfast.common.log.annotation.PinSysLog; import top.binfast.common.log.annotation.PinSysLog;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -74,8 +70,8 @@ public class EmployeeInfoCtrl { ...@@ -74,8 +70,8 @@ public class EmployeeInfoCtrl {
@PinSysLog(value = "系统用户", businessType = BusinessType.IMPORT) @PinSysLog(value = "系统用户", businessType = BusinessType.IMPORT)
@SaCheckPermission("employee:info:import") @SaCheckPermission("employee:info:import")
@PostMapping(value = "/excel/import") @PostMapping(value = "/excel/import")
public Response importWithOptions(@ExcelStream(headRowNumber = 2) Stream<EmployeeInfoImportVo> stream) { public Response importWithOptions(@ExcelStream(headRowNumber = 2) Stream<EmployeeInfoImportVo> stream, @RequestPart("file") MultipartFile file) {
return employeeInfoServ.importEmployeeList(stream); return employeeInfoServ.importEmployeeList(stream, file);
} }
/** /**
......
...@@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName; ...@@ -5,7 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.time.LocalDateTime;; import java.time.LocalDateTime;
import java.io.Serial; import java.io.Serial;
......
...@@ -6,7 +6,7 @@ import lombok.Getter; ...@@ -6,7 +6,7 @@ import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate;; import java.time.LocalDate;
import java.io.Serial; import java.io.Serial;
...@@ -45,6 +45,11 @@ public class EmployeeInfo extends BaseModel { ...@@ -45,6 +45,11 @@ public class EmployeeInfo extends BaseModel {
*/ */
private String secondLevelDepartment; private String secondLevelDepartment;
/**
* 部门id
*/
private Long deptId;
/** /**
* 工号 * 工号
*/ */
...@@ -75,6 +80,11 @@ public class EmployeeInfo extends BaseModel { ...@@ -75,6 +80,11 @@ public class EmployeeInfo extends BaseModel {
*/ */
private String gender; private String gender;
/**
* 简历图片
*/
private String resumeImage;
/** /**
* 身份证号码 * 身份证号码
*/ */
......
package com.example.domain.params; package com.example.domain.params;
import cn.idev.excel.annotation.ExcelProperty;
import com.example.domain.EmployeeInfo; import com.example.domain.EmployeeInfo;
import io.github.linpeilie.annotations.AutoMapper; import io.github.linpeilie.annotations.AutoMapper;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
...@@ -52,6 +53,12 @@ public class EmployeeInfoParam { ...@@ -52,6 +53,12 @@ public class EmployeeInfoParam {
@NotBlank(message = "二级部门不能为空", groups = { AddGroup.class, EditGroup.class }) @NotBlank(message = "二级部门不能为空", groups = { AddGroup.class, EditGroup.class })
private String secondLevelDepartment; private String secondLevelDepartment;
/**
* 部门id
*/
@NotNull(message = "部门id不能为空", groups = { AddGroup.class, EditGroup.class })
private Long deptId;
/** /**
* 工号 * 工号
*/ */
...@@ -88,6 +95,12 @@ public class EmployeeInfoParam { ...@@ -88,6 +95,12 @@ public class EmployeeInfoParam {
@NotBlank(message = "性别不能为空", groups = { AddGroup.class, EditGroup.class }) @NotBlank(message = "性别不能为空", groups = { AddGroup.class, EditGroup.class })
private String gender; private String gender;
/**
* 简历图片
*/
@NotBlank(message = "简历图片不能为空", groups = { AddGroup.class, EditGroup.class })
private String resumeImage;
/** /**
* 身份证号码 * 身份证号码
*/ */
......
package com.example.domain.params; package com.example.domain.params;
import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
/** /**
...@@ -18,5 +19,8 @@ public class EmployeeTransferApplyParam { ...@@ -18,5 +19,8 @@ public class EmployeeTransferApplyParam {
@NotBlank(message = "二级部门不能为空") @NotBlank(message = "二级部门不能为空")
private String secondLevelDepartment; private String secondLevelDepartment;
@NotNull(message = "部门id不能为空")
private Long deptId;
private String remark; private String remark;
} }
...@@ -23,7 +23,6 @@ import java.time.LocalDate; ...@@ -23,7 +23,6 @@ import java.time.LocalDate;
* @date 2025/10/29 09:42 * @date 2025/10/29 09:42
*/ */
@Getter @Getter
@Setter
@AutoMappers({ @AutoMappers({
@AutoMapper(target = EmployeeInfo.class, reverseConvertGenerate = false), @AutoMapper(target = EmployeeInfo.class, reverseConvertGenerate = false),
@AutoMapper(target = EmployeeInfoParam.class, reverseConvertGenerate = false) @AutoMapper(target = EmployeeInfoParam.class, reverseConvertGenerate = false)
...@@ -100,6 +99,12 @@ public class EmployeeInfoImportVo extends ExcelBaseEntity implements Serializabl ...@@ -100,6 +99,12 @@ public class EmployeeInfoImportVo extends ExcelBaseEntity implements Serializabl
@ExcelDictFormat(dictType = HrConstant.HR_USER_SEX) @ExcelDictFormat(dictType = HrConstant.HR_USER_SEX)
private String gender; private String gender;
/**
* 简历图片
*/
@ExcelProperty(value = "简历图片")
private String resumeImage;
// /** // /**
// * 性别 // * 性别
// */ // */
...@@ -385,4 +390,202 @@ public class EmployeeInfoImportVo extends ExcelBaseEntity implements Serializabl ...@@ -385,4 +390,202 @@ public class EmployeeInfoImportVo extends ExcelBaseEntity implements Serializabl
*/ */
@ExcelProperty(value = "离职原因") @ExcelProperty(value = "离职原因")
private String resignationReason; private String resignationReason;
public void setPlate(String plate) {
this.plate = plate == null ? null : plate.trim();
}
public void setProject(String project) {
this.project = project == null ? null : project.trim();
}
public void setFirstLevelDepartment(String firstLevelDepartment) {
this.firstLevelDepartment = firstLevelDepartment == null ? null : firstLevelDepartment.trim();
}
public void setSecondLevelDepartment(String secondLevelDepartment) {
this.secondLevelDepartment = secondLevelDepartment == null ? null : secondLevelDepartment.trim();
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId == null ? null : employeeId.trim();
}
public void setJobLevel(String jobLevel) {
this.jobLevel = jobLevel == null ? null : jobLevel.trim();
}
public void setPosition(String position) {
this.position = position == null ? null : position.trim();
}
public void setPost(String post) {
this.post = post == null ? null : post.trim();
}
public void setName(String name) {
this.name = name == null ? null : name.trim();
}
public void setGender(String gender) {
this.gender = gender == null ? null : gender.trim();
}
public void setResumeImage(String resumeImage) {
this.resumeImage = resumeImage == null ? null : resumeImage.trim();
}
public void setIdCardNumber(String idCardNumber) {
this.idCardNumber = idCardNumber == null ? null : idCardNumber.trim();
}
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
public void setAge(Integer age) {
this.age = age;
}
public void setAgeGroup(String ageGroup) {
this.ageGroup = ageGroup == null ? null : ageGroup.trim();
}
public void setNativePlace(String nativePlace) {
this.nativePlace = nativePlace == null ? null : nativePlace.trim();
}
public void setEthnicity(String ethnicity) {
this.ethnicity = ethnicity == null ? null : ethnicity.trim();
}
public void setMaritalStatus(String maritalStatus) {
this.maritalStatus = maritalStatus == null ? null : maritalStatus.trim();
}
public void setPoliticalStatus(String politicalStatus) {
this.politicalStatus = politicalStatus == null ? null : politicalStatus.trim();
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber == null ? null : phoneNumber.trim();
}
public void setEmergencyContact(String emergencyContact) {
this.emergencyContact = emergencyContact == null ? null : emergencyContact.trim();
}
public void setEmergencyContactPhone(String emergencyContactPhone) {
this.emergencyContactPhone = emergencyContactPhone == null ? null : emergencyContactPhone.trim();
}
public void setHomeAddress(String homeAddress) {
this.homeAddress = homeAddress == null ? null : homeAddress.trim();
}
public void setHouseholdRegistrationAddress(String householdRegistrationAddress) {
this.householdRegistrationAddress = householdRegistrationAddress == null ? null : householdRegistrationAddress.trim();
}
public void setWorkStartDate(LocalDate workStartDate) {
this.workStartDate = workStartDate;
}
public void setEntryDate(LocalDate entryDate) {
this.entryDate = entryDate;
}
public void setYearsOfService(String yearsOfService) {
this.yearsOfService = yearsOfService == null ? null : yearsOfService.trim();
}
public void setYearsOfServiceSegment(String yearsOfServiceSegment) {
this.yearsOfServiceSegment = yearsOfServiceSegment == null ? null : yearsOfServiceSegment.trim();
}
public void setEducation(String education) {
this.education = education == null ? null : education.trim();
}
public void setDegree(String degree) {
this.degree = degree == null ? null : degree.trim();
}
public void setGraduationDate(LocalDate graduationDate) {
this.graduationDate = graduationDate;
}
public void setMajor(String major) {
this.major = major == null ? null : major.trim();
}
public void setGraduateSchool(String graduateSchool) {
this.graduateSchool = graduateSchool == null ? null : graduateSchool.trim();
}
public void setEmployeeType(String employeeType) {
this.employeeType = employeeType == null ? null : employeeType.trim();
}
public void setProfessionalTitle(String professionalTitle) {
this.professionalTitle = professionalTitle == null ? null : professionalTitle.trim();
}
public void setResume(String resume) {
this.resume = resume == null ? null : resume.trim();
}
public void setEmploymentForm(String employmentForm) {
this.employmentForm = employmentForm == null ? null : employmentForm.trim();
}
public void setContractTerm(String contractTerm) {
this.contractTerm = contractTerm == null ? null : contractTerm.trim();
}
public void setContractStartDate(LocalDate contractStartDate) {
this.contractStartDate = contractStartDate;
}
public void setContractEndDate(LocalDate contractEndDate) {
this.contractEndDate = contractEndDate;
}
public void setContractExpirationReminder(LocalDate contractExpirationReminder) {
this.contractExpirationReminder = contractExpirationReminder;
}
public void setContractSigningStatus(String contractSigningStatus) {
this.contractSigningStatus = contractSigningStatus == null ? null : contractSigningStatus.trim();
}
public void setContractEntity(String contractEntity) {
this.contractEntity = contractEntity == null ? null : contractEntity.trim();
}
public void setRegularizationDate(LocalDate regularizationDate) {
this.regularizationDate = regularizationDate;
}
public void setTransferStatus(String transferStatus) {
this.transferStatus = transferStatus == null ? null : transferStatus.trim();
}
public void setRewardPunishmentStatus(String rewardPunishmentStatus) {
this.rewardPunishmentStatus = rewardPunishmentStatus == null ? null : rewardPunishmentStatus.trim();
}
public void setRemarks(String remarks) {
this.remarks = remarks == null ? null : remarks.trim();
}
public void setResignationDate(LocalDate resignationDate) {
this.resignationDate = resignationDate;
}
public void setResignationReason(String resignationReason) {
this.resignationReason = resignationReason == null ? null : resignationReason.trim();
}
} }
...@@ -16,6 +16,7 @@ import top.binfast.common.excel.annotion.ExcelDictFormat; ...@@ -16,6 +16,7 @@ import top.binfast.common.excel.annotion.ExcelDictFormat;
import top.binfast.common.excel.converters.ExcelDictConvert; import top.binfast.common.excel.converters.ExcelDictConvert;
import io.github.linpeilie.annotations.AutoMapper; import io.github.linpeilie.annotations.AutoMapper;
import lombok.Data; import lombok.Data;
import top.binfast.common.excel.converters.ExcelUrlImageConverter;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
...@@ -103,6 +104,12 @@ public class EmployeeInfoVo implements TransPojo, Serializable { ...@@ -103,6 +104,12 @@ public class EmployeeInfoVo implements TransPojo, Serializable {
@Trans(type = TransType.DICTIONARY, key = HrConstant.HR_USER_SEX) @Trans(type = TransType.DICTIONARY, key = HrConstant.HR_USER_SEX)
private String gender; private String gender;
/**
* 简历图片
*/
@ExcelProperty(value = "简历图片", converter = ExcelUrlImageConverter.class)
private String resumeImage;
/** /**
* 身份证号码 * 身份证号码
*/ */
......
...@@ -7,6 +7,7 @@ import com.example.domain.EmployeeInfo; ...@@ -7,6 +7,7 @@ import com.example.domain.EmployeeInfo;
import com.example.domain.params.*; import com.example.domain.params.*;
import com.example.domain.vo.EmployeeInfoImportVo; import com.example.domain.vo.EmployeeInfoImportVo;
import com.example.domain.vo.EmployeeInfoVo; import com.example.domain.vo.EmployeeInfoVo;
import org.springframework.web.multipart.MultipartFile;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
...@@ -42,7 +43,7 @@ public interface EmployeeInfoServ extends IService<EmployeeInfo> { ...@@ -42,7 +43,7 @@ public interface EmployeeInfoServ extends IService<EmployeeInfo> {
* @param stream 员工信息列表 * @param stream 员工信息列表
* @return 是否导入成功 * @return 是否导入成功
*/ */
Response importEmployeeList(Stream<EmployeeInfoImportVo> stream); Response importEmployeeList(Stream<EmployeeInfoImportVo> stream, MultipartFile file);
/** /**
* 校验员工名称是否唯一 * 校验员工名称是否唯一
...@@ -50,7 +51,7 @@ public interface EmployeeInfoServ extends IService<EmployeeInfo> { ...@@ -50,7 +51,7 @@ public interface EmployeeInfoServ extends IService<EmployeeInfo> {
* @param param 员工信息 * @param param 员工信息
* @return 是否唯一 * @return 是否唯一
*/ */
Boolean checkEmployeeNameUnique(EmployeeInfoParam param); Boolean checkEmployeeIdCardNumberUnique(EmployeeInfoParam param);
/** /**
* 查询员工信息 * 查询员工信息
* *
......
package com.example.service;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author 刘斌
* @date 2025/11/6 11:27
*/
public interface EmployeeSysDeptServ {
/**
* 根据部门id查询部门名称以及父级部门名称
*
* @param deptId 部门id
*/
List<String> selectDeptNameAncestorsById(Long deptId);
Map<String, Long> selectJoinDeptNames();
}
...@@ -19,23 +19,27 @@ import com.example.domain.params.*; ...@@ -19,23 +19,27 @@ import com.example.domain.params.*;
import com.example.domain.vo.EmployeeInfoImportVo; import com.example.domain.vo.EmployeeInfoImportVo;
import com.example.domain.vo.EmployeeInfoVo; import com.example.domain.vo.EmployeeInfoVo;
import com.example.mapper.EmployeeInfoMapper; import com.example.mapper.EmployeeInfoMapper;
import com.example.service.EmployeeAuditLogServ; import com.example.service.*;
import com.example.service.EmployeeDeptServ;
import com.example.service.EmployeeFlowServ;
import com.example.service.EmployeeInfoServ;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.dromara.trans.service.impl.TransService; import org.dromara.trans.service.impl.TransService;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import top.binfast.common.core.enums.ResultCode; import top.binfast.common.core.enums.ResultCode;
import top.binfast.common.core.util.LambdaUtil; import top.binfast.common.core.util.LambdaUtil;
import top.binfast.common.core.util.MapstructUtils; import top.binfast.common.core.util.MapstructUtils;
import top.binfast.common.excel.core.ExcelContextHolder; import top.binfast.common.excel.core.ExcelContextHolder;
import top.binfast.common.excel.image.CellImageData;
import top.binfast.common.excel.image.ExcelProcessingResult;
import top.binfast.common.excel.image.TempFileExcelImageImporter;
import top.binfast.common.log.model.SysAuditLog; import top.binfast.common.log.model.SysAuditLog;
import top.binfast.common.mybatis.util.QueryUtil; import top.binfast.common.mybatis.util.QueryUtil;
import top.binfast.common.oss.core.OssService;
import top.binfast.common.oss.entity.UploadResult;
import top.binfast.common.satoken.util.SecurityUtils; import top.binfast.common.satoken.util.SecurityUtils;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
...@@ -49,10 +53,11 @@ import java.util.stream.Stream; ...@@ -49,10 +53,11 @@ import java.util.stream.Stream;
public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, EmployeeInfo> implements EmployeeInfoServ { public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, EmployeeInfo> implements EmployeeInfoServ {
private final EmployeeInfoMapper employeeInfoMapper; private final EmployeeInfoMapper employeeInfoMapper;
private final EmployeeDeptServ employeeDeptServ; private final EmployeeSysDeptServ employeeSysDeptServ;
private final EmployeeFlowServ employeeFlowServ; private final EmployeeFlowServ employeeFlowServ;
private final EmployeeAuditLogServ employeeAuditLogServ; private final EmployeeAuditLogServ employeeAuditLogServ;
private final TransService transService; private final TransService transService;
private final OssService ossService;
/** /**
* 分页查询员工信息列表 * 分页查询员工信息列表
...@@ -145,10 +150,16 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ ...@@ -145,10 +150,16 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
* @return 是否导入成功 * @return 是否导入成功
*/ */
@Override @Override
public Response importEmployeeList(Stream<EmployeeInfoImportVo> list) { public Response importEmployeeList(Stream<EmployeeInfoImportVo> list, MultipartFile file) {
List<EmployeeInfoImportVo> errorList = new ArrayList<>(); List<EmployeeInfoImportVo> errorList = new ArrayList<>();
List<EmployeeInfo> successList = new ArrayList<>(); List<EmployeeInfoImportVo> successList = new ArrayList<>();
Set<String> deptNameGroups = new HashSet<>(); CompletableFuture<ExcelProcessingResult> future = CompletableFuture.supplyAsync(() -> {
try {
return TempFileExcelImageImporter.importExcelWithAllImages(file);
} catch (Exception e) {
throw new RuntimeException(e);
}
});
list.forEach(item -> { list.forEach(item -> {
// System.out.println(item.getNickName()); // System.out.println(item.getNickName());
// item.validGroup(AddGroup.class); // item.validGroup(AddGroup.class);
...@@ -158,22 +169,34 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ ...@@ -158,22 +169,34 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
errorList.add(item); errorList.add(item);
return; return;
} }
// transService.unTransOne(item);
EmployeeInfoParam employeeInfoParam = MapstructUtils.convert(item, EmployeeInfoParam.class); EmployeeInfoParam employeeInfoParam = MapstructUtils.convert(item, EmployeeInfoParam.class);
if (!checkEmployeeNameUnique(employeeInfoParam)) { if (!checkEmployeeIdCardNumberUnique(employeeInfoParam)) {
item.addError("姓名已存在"); item.addError("姓名已存在");
errorList.add(item); errorList.add(item);
return; return;
} }
EmployeeInfo employeeInfo = MapstructUtils.convert(employeeInfoParam, EmployeeInfo.class); successList.add(item);
successList.add(employeeInfo);
deptNameGroups.add(employeeInfo.getFirstLevelDepartment() + StrUtil.DASHED + employeeInfo.getSecondLevelDepartment());
}); });
if (CollUtil.isNotEmpty(successList)) { if (CollUtil.isNotEmpty(successList)) {
employeeInfoMapper.insert(successList); Map<String, Long> deptNamesIdMap = employeeSysDeptServ.selectJoinDeptNames();
EmployeeDeptCheckAndSaveParam checkAndSaveParam = ExcelProcessingResult excelProcessingResult = future.join();
new EmployeeDeptCheckAndSaveParam(deptNameGroups, SecurityUtils.getCurrentUserId(), SecurityUtils.getTenantId()); List<EmployeeInfo> insertList = new ArrayList<>(successList.size());
employeeDeptServ.checkAndSaveDept(checkAndSaveParam); for (EmployeeInfoImportVo importVo : successList) {
this.handleImageToUrl(excelProcessingResult, importVo);
Long leafDeptId = deptNamesIdMap.get(buildDeptNameStr(importVo));
if (leafDeptId == null) {
importVo.addError("部门不存在");
errorList.add(importVo);
continue;
}
EmployeeInfo employeeInfo = MapstructUtils.convert(importVo, EmployeeInfo.class);
employeeInfo.setDeptId(leafDeptId);
insertList.add(employeeInfo);
}
employeeInfoMapper.insert(insertList);
// EmployeeDeptCheckAndSaveParam checkAndSaveParam =
// new EmployeeDeptCheckAndSaveParam(deptNameGroups, SecurityUtils.getCurrentUserId(), SecurityUtils.getTenantId());
// employeeDeptServ.checkAndSaveDept(checkAndSaveParam);
} }
StringBuilder message; StringBuilder message;
if (CollUtil.isNotEmpty(errorList)) { if (CollUtil.isNotEmpty(errorList)) {
...@@ -189,10 +212,36 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ ...@@ -189,10 +212,36 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
} }
} }
private void handleImageToUrl(ExcelProcessingResult excelProcessingResult, EmployeeInfoImportVo importVo) {
// 处理图片,保存到OSS,替换成url
List<CellImageData> imageData = null;
if (excelProcessingResult.checkWpsOrOffice(importVo.getResumeImage())) {
imageData = excelProcessingResult.getWpsImageData(importVo.getResumeImage());
} else {
imageData = excelProcessingResult.getOfficeImageData(importVo.getLineNum());
}
if (CollUtil.isNotEmpty(imageData)) {
CellImageData cellImageData = imageData.getFirst();
UploadResult uploadResult = ossService.upload(cellImageData.getImageName(), cellImageData.getImageData());
importVo.setResumeImage(uploadResult.getUrl());
}
}
private String buildDeptNameStr(EmployeeInfoImportVo importVo) {
StringBuilder builder = new StringBuilder(importVo.getPlate() + StrUtil.SLASH + importVo.getProject());
if (StrUtil.isNotBlank(importVo.getFirstLevelDepartment())) {
builder.append(StrUtil.SLASH).append(importVo.getFirstLevelDepartment());
}
if (StrUtil.isNotBlank(importVo.getSecondLevelDepartment())) {
builder.append(StrUtil.SLASH).append(importVo.getSecondLevelDepartment());
}
return builder.toString();
}
@Override @Override
public Boolean checkEmployeeNameUnique(EmployeeInfoParam employee) { public Boolean checkEmployeeIdCardNumberUnique(EmployeeInfoParam employee) {
boolean exist = employeeInfoMapper.exists(new LambdaQueryWrapper<EmployeeInfo>() boolean exist = employeeInfoMapper.exists(new LambdaQueryWrapper<EmployeeInfo>()
.eq(EmployeeInfo::getName, employee.getName()) .eq(EmployeeInfo::getIdCardNumber, employee.getIdCardNumber())
.ne(ObjectUtil.isNotNull(employee.getId()), EmployeeInfo::getId, employee.getId())); .ne(ObjectUtil.isNotNull(employee.getId()), EmployeeInfo::getId, employee.getId()));
return !exist; return !exist;
} }
...@@ -235,9 +284,9 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ ...@@ -235,9 +284,9 @@ public class EmployeeInfoServImpl extends ServiceImpl<EmployeeInfoMapper, Employ
// 检查或增加部门 // 检查或增加部门
Set<String> deptNameGroups = new HashSet<>(); Set<String> deptNameGroups = new HashSet<>();
deptNameGroups.add(employeeInfo.getFirstLevelDepartment() + StrUtil.DASHED + employeeInfo.getSecondLevelDepartment()); deptNameGroups.add(employeeInfo.getFirstLevelDepartment() + StrUtil.DASHED + employeeInfo.getSecondLevelDepartment());
EmployeeDeptCheckAndSaveParam checkAndSaveParam = // EmployeeDeptCheckAndSaveParam checkAndSaveParam =
new EmployeeDeptCheckAndSaveParam(deptNameGroups, SecurityUtils.getCurrentUserId(), SecurityUtils.getTenantId()); // new EmployeeDeptCheckAndSaveParam(deptNameGroups, SecurityUtils.getCurrentUserId(), SecurityUtils.getTenantId());
employeeDeptServ.checkAndSaveDept(checkAndSaveParam); // employeeDeptServ.checkAndSaveDept(checkAndSaveParam);
employeeInfo.setEntryApplyStatus(HrFlowEnum.WAITING.getStatus()); employeeInfo.setEntryApplyStatus(HrFlowEnum.WAITING.getStatus());
return this.save(employeeInfo); return this.save(employeeInfo);
} }
......
package com.example.service.impl;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.example.constant.HrFlowEnum;
import com.example.domain.EmployeeInfo;
import com.example.mapper.EmployeeInfoMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.util.List;
/**
* @author 刘斌
* @date 2025/11/5 17:01
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class EmployeeScheduleService {
private final EmployeeInfoMapper employeeInfoMapper;
/**
* 方式1:使用cron表达式
* 每天凌晨1点执行
*/
@Scheduled(cron = "0 0 1 * * ?")
public void midnightTask() {
executeSafely("刷新员工工龄以及年龄", this::processRefreshInfo);
}
/**
* 刷新员工工龄以及工龄组
*/
private void processRefreshInfo() {
List<EmployeeInfo> employeeInfos = employeeInfoMapper.selectList(new LambdaUpdateWrapper<EmployeeInfo>()
.eq(EmployeeInfo::getEntryApplyStatus, HrFlowEnum.FINISH.getStatus())
.ne(EmployeeInfo::getResignationApplyStatus, HrFlowEnum.FINISH.getStatus()));
for (EmployeeInfo employeeInfo : employeeInfos) {
Period period = LocalDateTimeUtil.betweenPeriod(employeeInfo.getEntryDate(), LocalDate.from(LocalDateTime.now()));
int years = period.getYears();
int months = period.getMonths();
employeeInfo.setYearsOfService(years > 0 ? years + "年" + months + "个月" : months + "个月");
// TODO 更新员工工龄组
precessRefreshAge(employeeInfo);
}
}
private void precessRefreshAge(EmployeeInfo employeeInfo) {
Period period = LocalDateTimeUtil.betweenPeriod(employeeInfo.getBirthDate(), LocalDate.from(LocalDateTime.now()));
if (employeeInfo.getAge() != period.getYears()) {
employeeInfo.setAge(period.getYears());
// TODO 更新员工年龄组
}
}
/**
* 安全执行方法,包含异常处理
*/
private void executeSafely(String taskName, Runnable task) {
log.info("开始执行{}", taskName);
long startTime = System.currentTimeMillis();
try {
task.run();
long cost = System.currentTimeMillis() - startTime;
log.info("{}执行完成,耗时:{}ms", taskName, cost);
} catch (Exception e) {
log.error("{}执行失败", taskName, e);
// 这里可以添加告警逻辑,如发送邮件、短信等
}
}
}
package com.example.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.example.constant.HrCacheConstants;
import com.example.service.EmployeeSysDeptServ;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import top.binfast.app.biz.sysapi.bean.model.auth.SysDept;
import top.binfast.app.biz.sysapi.bean.params.sysDept.SysDeptParam;
import top.binfast.app.biz.sysapi.bean.vo.sysDept.SysDeptDTO;
import top.binfast.app.biz.sysapi.dao.auth.SysDeptMapper;
import top.binfast.app.biz.sysbiz.service.SysDeptServ;
import top.binfast.common.core.bean.dto.TreeDTO;
import top.binfast.common.core.constant.CacheNames;
import top.binfast.common.core.util.LambdaUtil;
import top.binfast.common.core.util.StringUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author 刘斌
* @date 2025/11/6 11:30
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class EmployeeSysDeptServImpl implements EmployeeSysDeptServ {
private final SysDeptMapper sysDeptMapper;
private final SysDeptServ sysDeptServ;
@Cacheable(cacheNames = HrCacheConstants.DEPT_AND_PARENT_NAME, key = "#deptId")
@Override
public List<String> selectDeptNameAncestorsById(Long deptId) {
SysDeptDTO dept = sysDeptServ.selectDeptById(deptId);
List<Long> split = StringUtils.splitTo(dept.getNodePath(), StrUtil.SLASH, Convert::toLong);
if (split.size() <= 2) {
return List.of(dept.getName());
}
List<SysDept> deptNameList = sysDeptMapper.selectByIds(split);
return LambdaUtil.mapToList(deptNameList, SysDept::getName);
}
@Override
public Map<String, Long> selectJoinDeptNames() {
// if (CollUtil.isEmpty(joinNameSet)) {
// return new HashMap<>();
// }
Map<String, Long> result = new HashMap<>();
List<SysDeptDTO> sysDeptDTOS = sysDeptServ.deptTreeForOptions();
traverseDeptTree(sysDeptDTOS, "", result);
// for (String joinName : joinNameSet) {
// List<String> deptNameList = StrUtil.split(joinName, StrUtil.SLASH);
//
// }
return result;
}
// 遍历根节点列表
private <T extends TreeDTO> void traverseDeptTree(List<T> deptList, String parentPath, Map<String, Long> result) {
if (CollUtil.isEmpty(deptList)) {
return;
}
for (TreeDTO dept : deptList) {
String currentPath = StrUtil.isEmpty(parentPath) ? dept.getLabel() : parentPath + StrUtil.SLASH + dept.getLabel();
// 递归处理子节点
if (CollUtil.isNotEmpty(dept.getChildren())) {
traverseDeptTree(dept.getChildren(), currentPath, result);
} else {
result.put(currentPath, dept.getId());
}
}
}
}
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
2. 注意修改 <property name="${log-path}/log.path" value=""/> 的value模块 2. 注意修改 <property name="${log-path}/log.path" value=""/> 的value模块
--> -->
<configuration debug="false" scan="false"> <configuration debug="false" scan="false">
<property name="log.path" value="./logs/${project.artifactId}"/> <property name="log.path" value="./logs"/>
<!-- 日志最大的历史 30天 --> <!-- 日志最大的历史 30天 -->
<property name="log.maxHistory" value="30"/> <property name="log.maxHistory" value="30"/>
<property name="log.level" value="debug"/> <property name="log.level" value="debug"/>
...@@ -126,4 +126,4 @@ ...@@ -126,4 +126,4 @@
<appender-ref ref="info"/> <appender-ref ref="info"/>
<appender-ref ref="error"/> <appender-ref ref="error"/>
</root> </root>
</configuration> </configuration>
\ No newline at end of file
package com.example; package com.example;
import com.example.service.EmployeeSysDeptServ;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import java.util.HashSet;
@SpringBootTest @SpringBootTest
class ApplicationTests { class ApplicationTests {
@Resource
private EmployeeSysDeptServ employeeSysDeptServ;
@Test @Test
void contextLoads() { void contextLoads() {
employeeSysDeptServ.selectJoinDeptNames();
} }
} }
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<properties> <properties>
<java.version>21</java.version> <java.version>21</java.version>
<spring-boot.version>3.5.6</spring-boot.version> <spring-boot.version>3.5.7</spring-boot.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven-jar-plugin.version>3.4.2</maven-jar-plugin.version> <maven-jar-plugin.version>3.4.2</maven-jar-plugin.version>
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
<mapstruct-plus.version>1.4.8</mapstruct-plus.version> <mapstruct-plus.version>1.4.8</mapstruct-plus.version>
<lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version> <lombok-mapstruct-binding.version>0.2.0</lombok-mapstruct-binding.version>
<therapi-javadoc.version>0.15.0</therapi-javadoc.version> <therapi-javadoc.version>0.15.0</therapi-javadoc.version>
<binfast.version>1.2.3</binfast.version> <binfast.version>1.2.5</binfast.version>
<lombok.version>1.18.38</lombok.version> <lombok.version>1.18.38</lombok.version>
</properties> </properties>
......
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 to comment