Commit 9f4da5ab authored by hongguangwu's avatar hongguangwu

Merge branch 'develop' into MVP1.7.19

parents 2a410bfc 355fd612
......@@ -33,8 +33,9 @@ spec: # 资源规范字段
#dapr.io/sidecar-memory-limit: "800Mi" #Dapr sidecar可以使用的最大内存量。默认情况下未设置 请参阅 https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/ 的有效值。
#dapr.io/sidecar-cpu-request: 1 #Dapr sidecar要求的 CPU 数量
#dapr.io/sidecar-memory-request #Dapr sidecar 请求的内存数量
dapr.io/app-max-request-size: "600" # 明确指定应用请求大小
dapr.io/http-max-request-size: "600" #增加http和grpc服务器请求正文参数的最大大小,单位为MB,以处理大文件的上传。 默认值为 4 MB
dapr.io/http-read-buffer-size: "200" #Dapr has a default limit of 4KB for the http header read buffer size. When sending http headers that are bigger than the default 4KB, you can increase this value. Otherwise, you may encounter a Too big request header
dapr.io/http-read-buffer-size: "4096" #Dapr has a default limit of 4KB for the http header read buffer size. When sending http headers that are bigger than the default 4KB, you can increase this value. Otherwise, you may encounter a Too big request header
dapr.io/sidecar-listen-addresses: "0.0.0.0"
# 更多dapr配置请参考 https://www.bookstack.cn/read/dapr-1.5-zh/cc77b74e2cc2f4d4.md
......
......@@ -33,8 +33,9 @@ spec: # 资源规范字段
#dapr.io/sidecar-memory-limit: "800Mi" #Dapr sidecar可以使用的最大内存量。默认情况下未设置 请参阅 https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/ 的有效值。
#dapr.io/sidecar-cpu-request: 1 #Dapr sidecar要求的 CPU 数量
#dapr.io/sidecar-memory-request #Dapr sidecar 请求的内存数量
dapr.io/app-max-request-size: "600" # 明确指定应用请求大小
dapr.io/http-max-request-size: "600" #增加http和grpc服务器请求正文参数的最大大小,单位为MB,以处理大文件的上传。 默认值为 4 MB
dapr.io/http-read-buffer-size: "16" #Dapr has a default limit of 4KB for the http header read buffer size. When sending http headers that are bigger than the default 4KB, you can increase this value. Otherwise, you may encounter a Too big request header
dapr.io/http-read-buffer-size: "4096" #Dapr has a default limit of 4KB for the http header read buffer size. When sending http headers that are bigger than the default 4KB, you can increase this value. Otherwise, you may encounter a Too big request header
#dapr.io/sidecar-listen-addresses: "0.0.0.0" 开通外部访问,仅限测试环境
# 更多dapr配置请参考 https://www.bookstack.cn/read/dapr-1.5-zh/cc77b74e2cc2f4d4.md
......
......@@ -751,13 +751,13 @@ public class EmployeeRegistrationPreServiceImpl extends ServiceImpl<EmployeeRegi
.eq(TEmployeeContractInfo::getDeleteFlag, CommonConstants.ZERO_INT)
.last(CommonConstants.LAST_ONE_SQL)) > 0;
if (employeeRegistrationPre.getServerItem().contains("合同")
&& Common.isNotNull(employeeRegistrationPre.getContractUpdateFlag())
&& employeeRegistrationPre.getContractUpdateFlag()) {
//查询老的合同明细
contractOld = contractPreMapper.selectOne(Wrappers.<TEmployeeContractPre>query().lambda()
.eq(TEmployeeContractPre::getRegisterId, employeeRegistrationPre.getId())
.last(CommonConstants.LAST_ONE_SQL));
if (employeeRegistrationPre.getServerItem().contains("合同")
&& Common.isNotNull(employeeRegistrationPre.getContractUpdateFlag())
&& employeeRegistrationPre.getContractUpdateFlag()) {
if (Common.isEmpty(employeeRegistrationPre.getEmployeeContractPre()) && !flag) {
errorTemp.append("未找到流程中或者在用的合同;");
......
......@@ -248,6 +248,7 @@ public class TEmployeePreLogServiceImpl extends ServiceImpl<TEmployeePreLogMappe
SOCIAL_IGNORE_FIELD.add("upperLimit");
SOCIAL_IGNORE_FIELD.add("lowerLimit");
SOCIAL_IGNORE_FIELD.add("fundUpdateFlag");
SOCIAL_IGNORE_FIELD.add("processStatus");
}
......@@ -318,6 +319,8 @@ public class TEmployeePreLogServiceImpl extends ServiceImpl<TEmployeePreLogMappe
List<TEmployeeInsurancePre> saveOrUpdateList = new ArrayList<>();
//加一个禁止编辑的判断
List<TEmployeeInsurancePre> unUpdateList = new ArrayList<>();
//删除的判断
List<TEmployeeInsurancePre> delInsuracneList = new ArrayList<>();
// 是否修改了商险
boolean isModifyInsurance = false;
TEmployeeInsurancePre oldInsurance;
......@@ -341,7 +344,7 @@ public class TEmployeePreLogServiceImpl extends ServiceImpl<TEmployeePreLogMappe
isModifyInsurance = true;
detailList.add(detailInsuranceLog);
}
if (!newInfo.getExitInsuranceInfoList().isEmpty()) {
if (null != newInfo.getExitInsuranceInfoList() && !newInfo.getExitInsuranceInfoList().isEmpty()) {
newInfo.getExitInsuranceInfoList().forEach(insurancePreVo -> insurancePreVo.setRegisterId(empPreId));
}
HttpDaprUtil.invokeMethodPost(daprInsurancesProperties.getAppUrl(), daprInsurancesProperties.getAppId()
......@@ -402,6 +405,7 @@ public class TEmployeePreLogServiceImpl extends ServiceImpl<TEmployeePreLogMappe
this.setLogBaseInfo(empPreId, newInsurance, null, user, differenceInsuranceKey, logId, detailInsuranceLog);
isModifyInsurance = true;
detailList.add(detailInsuranceLog);
delInsuracneList.add(newInsurance);
} else if (CommonConstants.FOUR_STRING.equals(newInsurance.getModelType())) {
// 4:不可编辑
unUpdateList.add(newInsurance);
......@@ -449,7 +453,36 @@ public class TEmployeePreLogServiceImpl extends ServiceImpl<TEmployeePreLogMappe
.in(TEmployeeContractPre::getProcessStatus, Arrays.asList("0","1","3","5","7","10","11"))
.eq(TEmployeeContractPre::getId,contractOld.getId()));
}
if (newInfo.getServerItem().contains("合同") && contractOld != null && employeeContractPre != null) {
//是的场景删除合同待购买数据
if (newInfo.getServerItem().contains("合同") && Common.isNotNull(contractOld)
&& Common.isEmpty(employeeContractPre) && null != newInfo.getContractUpdateFlag()
&& newInfo.getContractUpdateFlag()) {
//记录操作记录
contractOld.setAttaList(null);
detailEmpLog = new TEmployeePreLogDetail();
detailEmpLog.setModelType(CommonConstants.THREE_STRING);
detailEmpLog.setType(CommonConstants.THREE_STRING);
this.setLogBaseInfo(empPreId, contractOld, null, user, differenceContractKey, logId, detailEmpLog);
detailList.add(detailEmpLog);
if (Common.isNotNull(diffTitle)) {
diffTitle += "、合同信息";
} else {
diffTitle = "合同信息";
}
// 创建更新条件构造器
LambdaUpdateWrapper<TAttaInfo> updateWrapperContract = new LambdaUpdateWrapper<>();
// 设置更新条件和新值
updateWrapperContract.eq(TAttaInfo::getDomainId, contractOld.getId())
.set(TAttaInfo::getDomainId, CommonConstants.EMPTY_STRING);
// 执行更新操作,清空附件的关联ID
attaInfoService.update(updateWrapperContract);
//删除历史的合同待签订数据
contractPreService.remove(Wrappers.<TEmployeeContractPre>query().lambda()
.in(TEmployeeContractPre::getProcessStatus, Arrays.asList("0","1","3","5","7","10","11"))
.eq(TEmployeeContractPre::getId,contractOld.getId()));
}
if (newInfo.getServerItem().contains("合同") && contractOld != null && employeeContractPre != null
&& null != newInfo.getContractUpdateFlag() && newInfo.getContractUpdateFlag()) {
//1.9.11 huych 附件类型不比较差异
contractOld.setAttaList(null);
employeeContractPre.setAttaList(null);
......@@ -628,7 +661,8 @@ public class TEmployeePreLogServiceImpl extends ServiceImpl<TEmployeePreLogMappe
}
}
//保存合同待签订数据
if (newInfo.getServerItem().contains("合同") && employeeContractPre != null) {
if (newInfo.getServerItem().contains("合同") && employeeContractPre != null
&& null != newInfo.getContractUpdateFlag() && newInfo.getContractUpdateFlag()) {
TEmployeeContractPreVo preVo = new TEmployeeContractPreVo();
BeanUtils.copyProperties(employeeContractPre,preVo);
if (Common.isNotNull(employeeContractPre.getExpectedCollectionTime()) ) {
......@@ -672,7 +706,7 @@ public class TEmployeePreLogServiceImpl extends ServiceImpl<TEmployeePreLogMappe
HttpDaprUtil.invokeMethodPost(daprInsurancesProperties.getAppUrl(), daprInsurancesProperties.getAppId()
, "/temployeeinsurancepre/inner/saveOrUpdateInsuranceList"
, saveOrUpdateList, Boolean.class, SecurityConstants.FROM_IN);
} else if (unUpdateList.isEmpty()){
} else if (unUpdateList.isEmpty() || !delInsuracneList.isEmpty()){
HttpDaprUtil.invokeMethodPost(daprInsurancesProperties.getAppUrl(), daprInsurancesProperties.getAppId()
, "/temployeeinsurancepre/inner/deleteInsuranceByPreId"
, empPreId, Boolean.class, SecurityConstants.FROM_IN);
......@@ -746,6 +780,30 @@ public class TEmployeePreLogServiceImpl extends ServiceImpl<TEmployeePreLogMappe
.toInstant());
}
}
/**
* @Description: 填充基本信息
* @Author: hgw
* @Date: 2025/4/8 10:49
* @return: void
**/
private void setLogBaseInfo(String empPreId, Object oldInfo, Object newInfo
, YifuUser user, String differenceKey, String logId, TEmployeePreLogDetail detailEmpLog) {
detailEmpLog.setPreId(empPreId);
detailEmpLog.setPreLogId(logId);
detailEmpLog.setDifferenceInfo(differenceKey);
detailEmpLog.setCreateTime(LocalDateTime.now());
if (Common.isNotNull(user)) {
detailEmpLog.setCreateBy(user.getId());
detailEmpLog.setCreateName(user.getNickname());
}
if (Common.isNotNull(oldInfo)) {
detailEmpLog.setOldInfo(JSON.toJSONString(oldInfo, features));
}
if (Common.isNotNull(newInfo)) {
detailEmpLog.setNewInfo(JSON.toJSONString(newInfo, features));
}
}
@Override
public void saveUpdateInsurance(String empPreId, EmployeeRegistrationPre oldInfo
, EmployeeRegistrationPre newInfo, String userId, String nickName, Map<String, TEmployeeInsurancePre> oldMap
......@@ -1030,30 +1088,6 @@ public class TEmployeePreLogServiceImpl extends ServiceImpl<TEmployeePreLogMappe
}
}
/**
* @Description: 填充基本信息
* @Author: hgw
* @Date: 2025/4/8 10:49
* @return: void
**/
private void setLogBaseInfo(String empPreId, Object oldInfo, Object newInfo
, YifuUser user, String differenceKey, String logId, TEmployeePreLogDetail detailEmpLog) {
detailEmpLog.setPreId(empPreId);
detailEmpLog.setPreLogId(logId);
detailEmpLog.setDifferenceInfo(differenceKey);
detailEmpLog.setCreateTime(LocalDateTime.now());
if (Common.isNotNull(user)) {
detailEmpLog.setCreateBy(user.getId());
detailEmpLog.setCreateName(user.getNickname());
}
if (Common.isNotNull(oldInfo)) {
detailEmpLog.setOldInfo(JSON.toJSONString(oldInfo, features));
}
if (Common.isNotNull(newInfo)) {
detailEmpLog.setNewInfo(JSON.toJSONString(newInfo, features));
}
}
/**
* @Description: 填充基本信息
* @Author: huyc
......
......@@ -23,40 +23,41 @@ public class ArchiveImportVO extends RowIndex implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 姓名
*/
@ExcelAttribute(name = "姓名", isNotEmpty = true, errorInfo = "姓名不能为空", maxLength = 32)
@ExcelProperty(value = "姓名")
@NotBlank(message = "姓名不能为空")
@Schema(description = "姓名")
private String empName;
/**
* 身份证号码
*/
@ExcelAttribute(name = "身份证号码", isNotEmpty = true, errorInfo = "身份证号码不能为空", maxLength = 18)
@ExcelProperty(value = "身份证号码", index = 0)
@ExcelProperty(value = "身份证号码")
@NotBlank(message = "身份证号码不能为空")
@Schema(description = "身份证号码")
private String empIdcard;
/**
* 姓名
* 项目名称
*/
@ExcelAttribute(name = "姓名", isNotEmpty = true, errorInfo = "姓名不能为空", maxLength = 32)
@ExcelProperty(value = "姓名", index = 1)
@NotBlank(message = "姓名不能为空")
@Schema(description = "姓名")
private String empName;
@ExcelAttribute(name = "项目名称", isNotEmpty = true, errorInfo = "项目名称不能为空", maxLength = 50)
@ExcelProperty(value = "项目名称")
@NotBlank(message = "项目名称不能为空")
@Schema(description = "项目名称")
private String deptName;
/**
* 项目编码
*/
@ExcelAttribute(name = "项目编码", isNotEmpty = true, errorInfo = "项目编码不能为空", maxLength = 50)
@ExcelProperty(value = "项目编码", index = 2)
@ExcelProperty(value = "项目编码")
@NotBlank(message = "项目编码不能为空")
@Schema(description = "项目编码")
private String deptNo;
/**
* 项目名称
*/
@ExcelAttribute(name = "项目名称", isNotEmpty = true, errorInfo = "项目名称不能为空", maxLength = 50)
@ExcelProperty(value = "项目名称", index = 3)
@NotBlank(message = "项目名称不能为空")
@Schema(description = "项目名称")
private String deptName;
}
......@@ -136,25 +136,6 @@ public class TElectronicArchiveTaskController {
return R.ok(task);
}
/**
* 手动触发异步处理(用于重试)
*
* @param taskId 任务ID
* @return R
*/
@Operation(summary = "手动触发异步处理", description = "手动触发异步处理任务(用于重试失败的任务)")
@PostMapping("/retryProcess/{taskId}")
public R<?> retryProcess(@PathVariable("taskId") String taskId) {
TElectronicArchiveTask task = tElectronicArchiveTaskService.getById(taskId);
if (task == null) {
return R.failed("任务不存在");
}
// 只有生成中或失败的任务才能重试
// 这里可以根据需要增加失败状态
return importService.asyncProcessUpload(taskId);
}
/**
* 单个新增人员附件
* 前端先调用 /fileUpload/uploadArchiveFile 接口上传文件获取附件ID列表
......
......@@ -35,9 +35,10 @@ public interface ElectronicArchiveImportService {
* 第三步:异步处理上传
*
* @param taskId 任务ID
* @return 处理结果
* @param userId 用户ID
* @param userName 用户名
*/
R<?> asyncProcessUpload(String taskId);
void asyncProcessUpload(String taskId, String userId, String userName);
/**
* 生成任务编号
......
......@@ -22,6 +22,21 @@ public interface FileUploadService {
R<TAttaInfo> uploadFileReturnAtta(MultipartFile file, String filePath, String type, String domainId, String taskId) throws IOException;
/**
* 上传文件并返回附件信息(支持传递用户ID,用于异步场景)
*
* @param file 文件
* @param filePath 文件路径
* @param type 类型
* @param domainId 域ID
* @param taskId 任务ID
* @param userId 用户ID
* @param userName 用户名
* @return 附件信息
* @throws IOException IO异常
*/
R<TAttaInfo> uploadFileReturnAtta(MultipartFile file, String filePath, String type, String domainId, String taskId, String userId, String userName) throws IOException;
R<T> uploadAsso(MultipartFile file, String filePath, String type, String domain, String uploadType);
R<T> uploadAsso(MultipartFile file, String filePath, String type, String domain, String uploadType, String taskId);
......
......@@ -33,9 +33,11 @@ import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import com.yifu.cloud.plus.v1.yifu.insurances.constants.InsurancesConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.cache.support.SimpleValueWrapper;
import org.springframework.context.annotation.Lazy;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
......@@ -47,6 +49,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
/**
......@@ -68,14 +72,22 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
private final ArchivesDaprUtil archivesDaprUtil;
private final CacheManager cacheManager;
private final OSSUtil ossUtil;
private final SysConfigLimitMapper configLimitMapper;
/**
* 自注入代理对象,用于解决@Async注解在类内部调用时失效的问题
*
* @Lazy 延迟加载,避免循环依赖
*/
@Autowired
@Lazy
private ElectronicArchiveImportService self;
//初始化zip导入上限值
private int maxLimit = 1;
private AtomicInteger atomicInteger = new AtomicInteger(0);
private final SysConfigLimitMapper configLimitMapper;
/**
* 第一步:导入Excel模板文件
......@@ -161,15 +173,15 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
taskService.save(task);
// 保存任务表附件
saveTaskAttachment(task.getId(), fileName, inputStream, "task_file"+"/" + task.getId() + "_" + fileName);
saveTaskAttachment(task.getId(), fileName, inputStream, "task_file" + "/" + task.getId() + "_" + fileName);
// 上传文件到阿里云OSS根目录
uploadFileToOSS("task_file"+"/" + task.getId() + "_" + fileName, fileBytes);
uploadFileToOSS("task_file" + "/" + task.getId() + "_" + fileName, fileBytes);
// 建立任务和档案详情的关联关系
createTaskArchiveRelations(task.getId(), successList);
return R.ok(task.getId(),"全部校验通过");
return R.ok(task.getId(), "全部校验通过");
} catch (Exception e) {
log.error("导入Excel文件失败", e);
......@@ -186,7 +198,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
TEmployeeInfo empInfo;
TSettleDomainSelectVo settleResult;
R<TEmployeeInfo> empResult;
Map<String,String> map = new HashMap<>();
Map<String, String> map = new HashMap<>();
List<String> deptNoList = new ArrayList<>();
......@@ -208,16 +220,16 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
if (Common.isNotNull(user) && isCheck) {
if (Common.isEmpty(deptNoList) || !deptNoList.contains(data.getDeptNo())) {
ErrorMessage<ArchiveImportVO> errorMessage = new ErrorMessage<>(data.getRowIndex()
,InsurancesConstants.DEPT_NO_NOT_IN_USER_DEPT_LIST,data);
, InsurancesConstants.DEPT_NO_NOT_IN_USER_DEPT_LIST, data);
errorMessageList.add(errorMessage);
continue;
}
}
// 1. 校验表格中一个姓名、身份证只能有一条
String uniqueKey = data.getEmpIdcard() + "_" + data.getEmpName() + "_" + data.getDeptNo();
String uniqueKey = data.getEmpIdcard() + "_" + data.getEmpName();
if (null != map.get(uniqueKey)) {
ErrorMessage<ArchiveImportVO> errorMessage = new ErrorMessage<>(data.getRowIndex()
,"第" + data.getRowIndex() + "行:姓名和身份证信息存在重复数据",data);
, "第" + data.getRowIndex() + "行:姓名和身份证信息存在重复数据", data);
errorMessageList.add(errorMessage);
continue;
} else {
......@@ -226,9 +238,9 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
// 查询项目信息获取客户信息
settleResult = archivesDaprUtil.selectDeptByNo(data.getDeptNo());
if (settleResult == null) {
if (Common.isEmpty(settleResult) || Common.isEmpty(settleResult.getCustomerCode())) {
ErrorMessage<ArchiveImportVO> errorMessage = new ErrorMessage<>(data.getRowIndex()
,"第" + data.getRowIndex() + "行:项目编码[" + data.getDeptNo() + "]信息不存在",data);
, "第" + data.getRowIndex() + "行:项目编码[" + data.getDeptNo() + "]信息不存在", data);
errorMessageList.add(errorMessage);
continue;
}
......@@ -240,7 +252,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
empResult = archivesDaprUtil.getTEmployeeInfoByIdcardAndName(vo);
if (empResult == null || empResult.getData() == null) {
ErrorMessage<ArchiveImportVO> errorMessage = new ErrorMessage<>(data.getRowIndex()
,"第" + data.getRowIndex() + "行:人员档案信息不存在",data);
, "第" + data.getRowIndex() + "行:人员档案信息不存在", data);
errorMessageList.add(errorMessage);
continue;
}
......@@ -262,7 +274,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
detail.setEmpIdcard(data.getEmpIdcard());
detail.setDeptNo(data.getDeptNo());
detail.setDeptId(settleResult.getId());
detail.setDeptName(data.getDeptName());
detail.setDeptName(settleResult.getDepartName());
detail.setCustomerName(settleResult.getCustomerName());
detail.setCustomerCode(settleResult.getCustomerCode());
detail.setMaterialType(""); // 初始为空,第三步处理时填充
......@@ -287,7 +299,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
/**
* 保存任务表附件
*/
private void saveTaskAttachment(String taskId, String fileName, InputStream inputStream,String filePath) {
private void saveTaskAttachment(String taskId, String fileName, InputStream inputStream, String filePath) {
try {
TAttaInfo attaInfo = new TAttaInfo();
attaInfo.setAttaName(fileName);
......@@ -326,22 +338,22 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
/**
* 获取项目权限
*
* @author huych
* @param userId
* @return {@link List< String>}
* @author huych
*/
public List<String> getDeptNoList(String userId){
public List<String> getDeptNoList(String userId) {
List<String> deptList = new ArrayList<>(16);
try{
try {
R<TSettleDomainListVo> settleDomainList = archivesDaprUtil.getSettleDomainIdsByUserId(userId);
if(Common.isNotNull(settleDomainList) && settleDomainList.getCode() == CommonConstants.SUCCESS){
if (Common.isNotNull(settleDomainList) && settleDomainList.getCode() == CommonConstants.SUCCESS) {
TSettleDomainListVo data = settleDomainList.getData();
if (Optional.ofNullable(data).isPresent()){
if (Optional.ofNullable(data).isPresent()) {
deptList = data.getDeptNos();
}
}
}catch (Exception e){
log.error("查询项目信息出错:"+e);
} catch (Exception e) {
log.error("查询项目信息出错:" + e);
}
return deptList;
}
......@@ -418,7 +430,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
// 3. 校验同时上传任务数
maxLimit = configLimitMapper.getSysConfigLimitByKey("UPDOLOAD_MAX_LIMIT");
if (atomicInteger.incrementAndGet() > maxLimit){
if (atomicInteger.incrementAndGet() > maxLimit) {
atomicInteger.decrementAndGet();
return R.failed("有其他客服正在上传中,请5分钟后重试");
}
......@@ -449,8 +461,9 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
zipAtta.setAttaSrc(tempZipFile.getAbsolutePath()); // 临时存储文件路径
attaInfoService.save(zipAtta);
// 调用异步处理
asyncProcessUpload(taskId);
// 调用异步处理(通过self代理对象调用,使@Async生效)
// 传递用户ID和用户名,因为异步线程无法获取用户上下文
self.asyncProcessUpload(taskId, user.getId(), user.getNickname());
return R.ok("ZIP文件提交成功,正在处理中");
......@@ -470,10 +483,14 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
/**
* 第三步:异步处理上传
*
* @param taskId 任务ID
* @param userId 用户ID(用于上传反馈文件)
* @param userName 用户名(用于上传反馈文件)
*/
@Override
@Async
public R<?> asyncProcessUpload(String taskId) {
public void asyncProcessUpload(String taskId, String userId, String userName) {
List<ArchiveFeedbackVO> feedbackList = new ArrayList<>();
File tempDir = null;
......@@ -483,7 +500,8 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
// 查询任务及关联的明细
TElectronicArchiveTask task = taskService.getById(taskId);
if (task == null) {
return R.failed("任务不存在");
log.error("任务不存在,任务ID:{}", taskId);
return;
}
// 查询ZIP附件(从附件导入中获取)
......@@ -493,7 +511,8 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
if (CollUtil.isEmpty(zipAttas)) {
updateTaskStatus(task, ArchiveConstants.TASK_STATUS_NOT_UPLOADED);
return R.failed("ZIP附件不存在");
log.error("ZIP附件不存在,任务ID:{}", taskId);
return;
}
TAttaInfo zipAtta = zipAttas.get(0);
......@@ -501,13 +520,15 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
// 从附件记录中获取ZIP文件路径
if (StrUtil.isBlank(zipAtta.getAttaSrc())) {
updateTaskStatus(task, ArchiveConstants.TASK_STATUS_NOT_UPLOADED);
return R.failed("ZIP文件路径为空");
log.error("ZIP文件路径为空,任务ID:{}", taskId);
return;
}
zipSourceFile = new File(zipAtta.getAttaSrc());
if (!zipSourceFile.exists()) {
updateTaskStatus(task, ArchiveConstants.TASK_STATUS_NOT_UPLOADED);
return R.failed("ZIP文件不存在");
log.error("ZIP文件不存在,任务ID:{},文件路径:{}", taskId, zipAtta.getAttaSrc());
return;
}
// 获取任务关联的明细
......@@ -516,7 +537,8 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
if (CollUtil.isEmpty(relations)) {
updateTaskStatus(task, ArchiveConstants.TASK_STATUS_NOT_UPLOADED);
return R.failed("任务没有关联的明细数据");
log.error("任务没有关联的明细数据,任务ID:{}", taskId);
return;
}
List<String> detailIds = relations.stream()
......@@ -531,7 +553,8 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
tempDir = new File(tempDirPath);
if (!tempDir.exists() && !tempDir.mkdirs()) {
updateTaskStatus(task, ArchiveConstants.TASK_STATUS_NOT_UPLOADED);
return R.failed("创建临时目录失败");
log.error("创建临时目录失败,任务ID:{},目录路径:{}", taskId, tempDirPath);
return;
}
// 解压ZIP文件
......@@ -540,7 +563,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
if (!zipSourceFile.canRead()) {
log.error("ZIP文件不可读,路径:{}", zipSourceFile.getAbsolutePath());
updateTaskStatus(task, ArchiveConstants.TASK_STATUS_NOT_UPLOADED);
return R.failed("ZIP文件不可读");
return;
}
// 使用指定字符集解压(支持中文文件名)
// Windows系统通常使用GBK编码,Linux使用UTF-8
......@@ -554,7 +577,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
log.error("解压ZIP文件失败,任务ID:{},ZIP路径:{},临时目录:{}",
taskId, zipSourceFile.getAbsolutePath(), tempDirPath, e);
updateTaskStatus(task, ArchiveConstants.TASK_STATUS_NOT_UPLOADED);
return R.failed("解压ZIP文件失败:" + e.getMessage() + ",请检查ZIP文件是否完整且格式正确");
return;
}
// 获取ZIP包的根目录(第一级目录,身份证+姓名目录)
......@@ -598,7 +621,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
// 遍历该人员的所有文件夹
for (File personDir : personDirs) {
processPersonDirectoryWithResult(personDir, detail, materialTypes, failReasons, taskId);
processPersonDirectoryWithResult(personDir, detail, materialTypes, failReasons, taskId, userId, userName);
}
personMaterialTypesMap.put(uniqueKey, materialTypes);
......@@ -654,9 +677,9 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
task.setStatus(ArchiveConstants.TASK_STATUS_GENERATED);
taskService.updateById(task);
// 生成反馈表
generateFeedbackExcel(task, feedbackList);
return R.ok("处理完成");
// 生成反馈表(传递用户信息)
generateFeedbackExcel(task, feedbackList, userId, userName);
log.info("异步任务处理完成,任务ID:{}", taskId);
} catch (Exception e) {
log.error("异步处理任务失败,任务ID:{}", taskId, e);
......@@ -665,7 +688,6 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
if (task != null) {
updateTaskStatus(task, ArchiveConstants.TASK_STATUS_NOT_UPLOADED);
}
return R.failed("处理失败:" + e.getMessage());
} finally {
// 清理临时解压目录
if (tempDir != null && tempDir.exists()) {
......@@ -827,9 +849,12 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
* @param materialTypes 成功处理的资料类型列表(输出参数)
* @param failReasons 失败原因列表(输出参数)
* @param taskId 任务ID
* @param userId 用户ID
* @param userName 用户名
*/
private void processPersonDirectoryWithResult(File personDir, TElectronicArchiveDetail detail,
List<String> materialTypes, List<String> failReasons, String taskId) {
List<String> materialTypes, List<String> failReasons, String taskId,
String userId, String userName) {
// 处理第三级目录(资料类型或直接是文件)
File[] subFiles = personDir.listFiles();
if (subFiles == null || subFiles.length == 0) {
......@@ -866,7 +891,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
}
// 按资料类型分组处理目录下的所有文件
String result = processMaterialTypeDirectoryWithResult(subFile, detail, materialType, taskId);
String result = processMaterialTypeDirectoryWithResult(subFile, detail, materialType, taskId, userId, userName);
if ("success".equals(result)) {
materialTypesSet.add(materialType);
} else {
......@@ -880,7 +905,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
// 统一处理所有直接文件(存量类型)
if (!stockFiles.isEmpty()) {
String result = processMaterialTypeFilesWithResult(stockFiles, detail, ArchiveConstants.MATERIAL_TYPE_STOCK, taskId);
String result = processMaterialTypeFilesWithResult(stockFiles, detail, ArchiveConstants.MATERIAL_TYPE_STOCK, taskId, userId, userName);
if ("success".equals(result)) {
materialTypesSet.add(ArchiveConstants.MATERIAL_TYPE_STOCK);
} else {
......@@ -925,10 +950,12 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
* @param detail 电子档案明细
* @param materialType 资料类型
* @param taskId 任务ID
* @param userId 用户ID
* @param userName 用户名
* @return "success" 表示成功,其他表示失败原因
*/
private String processMaterialTypeDirectoryWithResult(File directory, TElectronicArchiveDetail detail,
String materialType, String taskId) {
String materialType, String taskId, String userId, String userName) {
// 收集该资料类型目录下的所有文件(递归收集子目录中的文件)
List<File> allFiles = new ArrayList<>();
collectAllFiles(directory, allFiles);
......@@ -938,7 +965,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
}
// 统一处理该资料类型下的所有文件
return processMaterialTypeFilesWithResult(allFiles, detail, materialType, taskId);
return processMaterialTypeFilesWithResult(allFiles, detail, materialType, taskId, userId, userName);
}
/**
......@@ -1041,10 +1068,12 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
* @param detail 电子档案明细
* @param materialType 资料类型
* @param taskId 任务ID
* @param userId 用户ID
* @param userName 用户名
* @return "success" 表示成功,其他表示失败原因
*/
private String processMaterialTypeFilesWithResult(List<File> files, TElectronicArchiveDetail detail,
String materialType, String taskId) {
String materialType, String taskId, String userId, String userName) {
// 第一步:验证所有文件格式
for (File file : files) {
String fileName = file.getName();
......@@ -1071,12 +1100,15 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
}
// 上传文件到阿里云OSS,uploadFileReturnAtta会自动生成TAttaInfo记录
// 传递用户信息,支持异步场景
R<TAttaInfo> uploadResult = fileUploadService.uploadFileReturnAtta(
multipartFile,
ossDirectory,
CommonConstants.FOUR_STRING,
detail.getId(),
taskId
taskId,
userId,
userName
);
if (!R.isSuccess(uploadResult)) {
......@@ -1184,9 +1216,16 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
/**
* 生成反馈表Excel
*
* @param task 任务信息
* @param feedbackList 反馈列表
* @param userId 用户ID
* @param userName 用户名
*/
private void generateFeedbackExcel(TElectronicArchiveTask task, List<ArchiveFeedbackVO> feedbackList) {
private void generateFeedbackExcel(TElectronicArchiveTask task, List<ArchiveFeedbackVO> feedbackList,
String userId, String userName) {
if (CollUtil.isEmpty(feedbackList)) {
log.warn("反馈列表为空,跳过生成反馈表,任务ID:{}", task.getId());
return;
}
......@@ -1201,28 +1240,35 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
.sheet("处理结果反馈")
.doWrite(feedbackList);
// 上传反馈表到OSS
YifuUser user = SecurityUtils.getUser();
if (user != null) {
log.info("反馈表Excel文件生成成功,文件路径:{},记录数:{}", tempFilePath, feedbackList.size());
// 上传反馈表到OSS(传递用户信息)
if (StrUtil.isNotBlank(userId)) {
R<TAttaInfo> uploadResult = fileUploadService.uploadFileReturnAtta(
fileToMultipartFile(feedbackFile),
"archive/feedback",
ArchiveConstants.ATTA_RELATION_TYPE_FEEDBACK,
task.getId()
task.getId(),
null, // taskId为null
userId,
userName
);
if (R.isSuccess(uploadResult)) {
log.info("反馈表生成成功");
log.info("反馈表上传成功,任务ID:{},附件ID:{}", task.getId(), uploadResult.getData().getId());
} else {
log.error("反馈表上传失败");
log.error("反馈表上传失败,任务ID:{},失败原因:{}", task.getId(), uploadResult.getMsg());
}
} else {
log.error("用户ID为空,无法上传反馈表,任务ID:{}", task.getId());
}
// 删除临时文件
FileUtil.del(feedbackFile);
log.info("临时反馈表文件已删除:{}", tempFilePath);
} catch (Exception e) {
log.error("生成反馈表失败:", e);
log.error("生成反馈表失败,任务ID:{},异常信息:", task.getId(), e);
}
}
......@@ -1232,44 +1278,60 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
*/
private Map<String, String> parseIdCardAndName(String folderName) {
Map<String, String> result = new HashMap<>();
if (folderName == null || folderName.trim().isEmpty()) {
return result;
}
// 统一处理全角和半角横线
folderName = folderName.replace("—", "-");
// 身份证正则表达式:18位,前17位为数字,最后一位可以是数字或X(大小写)
String idCardPattern = "\\d{17}[\\dXx]";
// 尝试用-分隔
if (folderName.contains("-") || folderName.contains("—")) {
String[] parts;
// 情况1:包含分隔符"-"
if (folderName.contains("-")) {
parts = folderName.split("-");
}else {
parts = folderName.split("—");
}
String[] parts = folderName.split("-");
if (parts.length == 2) {
// 判断哪个是身份证号(18位数字)
if (parts[0].matches("\\d{18}")) {
result.put("idCard", parts[0]);
result.put("name", parts[1]);
} else if (parts[1].matches("\\d{18}")) {
result.put("name", parts[0]);
result.put("idCard", parts[1]);
String part1 = parts[0].trim();
String part2 = parts[1].trim();
if (part1.matches(idCardPattern)) {
result.put("idCard", part1.toUpperCase()); // 统一转为大写
result.put("name", part2);
} else if (part2.matches(idCardPattern)) {
result.put("name", part1);
result.put("idCard", part2.toUpperCase());
}
}
} else {
// 尝试提取18位身份证号
int idCardStart = -1;
for (int i = 0; i <= folderName.length() - 18; i++) {
String sub = folderName.substring(i, i + 18);
if (sub.matches("\\d{18}")) {
idCardStart = i;
break;
return result;
}
// 情况2:无分隔符,直接拼接
// 使用正则表达式查找身份证号
Pattern pattern = Pattern.compile(idCardPattern);
Matcher matcher = pattern.matcher(folderName);
if (matcher.find()) {
String idCard = matcher.group().toUpperCase();
int start = matcher.start();
int end = matcher.end();
// 提取姓名部分(身份证前后部分合并)
String name;
if (start == 0) {
// 身份证在开头
name = folderName.substring(end).trim();
} else if (end == folderName.length()) {
// 身份证在结尾
name = folderName.substring(0, start).trim();
} else {
// 身份证在中间(理论上不应该出现,但处理一下)
name = (folderName.substring(0, start) + folderName.substring(end)).trim();
}
if (idCardStart >= 0) {
String idCard = folderName.substring(idCardStart, idCardStart + 18);
String name = folderName.substring(0, idCardStart) +
folderName.substring(idCardStart + 18);
result.put("idCard", idCard);
result.put("name", name);
}
}
return result;
}
......@@ -1356,7 +1418,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
detail.setEmpName(empName);
detail.setEmpIdcard(empIdcard);
detail.setDeptNo(deptNo);
detail.setDeptName(deptName);
detail.setDeptName(settleResult.getDepartName());
detail.setDeptId(settleResult.getId());
detail.setCustomerName(settleResult.getCustomerName());
detail.setCustomerCode(settleResult.getCustomerCode());
......@@ -1509,7 +1571,7 @@ public class ElectronicArchiveImportServiceImpl implements ElectronicArchiveImpo
detail.setEmpName(empName);
detail.setEmpIdcard(empIdcard);
detail.setDeptNo(deptNo);
detail.setDeptName(deptName);
detail.setDeptName(settleResult.getDepartName());
detail.setDeptId(settleResult.getId());
detail.setCustomerName(settleResult.getCustomerName());
detail.setCustomerCode(settleResult.getCustomerCode());
......
package com.yifu.cloud.plus.v1.batch.service.impl;
import cn.hutool.core.util.StrUtil;
import com.yifu.cloud.plus.v1.batch.entity.TAttaInfo;
import com.yifu.cloud.plus.v1.batch.mapper.SysConfigLimitMapper;
import com.yifu.cloud.plus.v1.batch.service.FileUploadService;
......@@ -14,17 +15,12 @@ import com.yifu.cloud.plus.v1.yifu.common.core.vo.YifuUser;
import com.yifu.cloud.plus.v1.yifu.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
@Service
......@@ -49,6 +45,18 @@ public class FileUploadServiceImpl implements FileUploadService {
@Override
public R<TAttaInfo> uploadFileReturnAtta(MultipartFile file, String filePath, String type, String domainId, String taskId) throws IOException {
// 从当前上下文获取用户信息
YifuUser user = SecurityUtils.getUser();
if (user != null) {
return uploadFileReturnAtta(file, filePath, type, domainId, taskId, user.getId(), user.getNickname());
} else {
return uploadFileReturnAtta(file, filePath, type, domainId, taskId, null, null);
}
}
@Override
public R<TAttaInfo> uploadFileReturnAtta(MultipartFile file, String filePath, String type, String domainId,
String taskId, String userId, String userName) throws IOException {
if (null == file) {
return R.failed("文件删除异常,请重新上传!");
}
......@@ -98,12 +106,23 @@ public class FileUploadServiceImpl implements FileUploadService {
attaInfo.setDomainId(domainId);
attaInfo.setTaskId(taskId);
Set<String> dbAuthsSet = new HashSet<>();
Collection<? extends GrantedAuthority> authorities = AuthorityUtils
.createAuthorityList(dbAuthsSet.toArray(new String[0]));
// 优先使用传入的用户信息(支持异步场景)
if (Common.isNotNull(userId) && StrUtil.isNotBlank(userId)) {
attaInfo.setCreateBy(userId);
attaInfo.setCreateName(userName);
} else {
// 从上下文获取(同步场景)
try {
YifuUser user = SecurityUtils.getUser();
if (user != null) {
attaInfo.setCreateBy(user.getId());
attaInfo.setCreateName(user.getNickname());
}
} catch (Exception e) {
log.warn("获取用户上下文失败,附件创建人将为空", e);
}
}
attaInfo = tAttaInfoService.add(attaInfo);
} catch (Exception e) {
log.error("OSS文件上传异常:" + e.getMessage());
......
......@@ -229,10 +229,13 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
}
try {
//重复数据检测
Map<String,String> map = new HashMap<>();
// 1. 校验请求并查询档案信息
for (ArchiveBatchDownloadRequestVO request : requestList) {
try {
validateAndPrepareDownload(request, downloadMap, feedbackList, isCheck, deptNoList);
validateAndPrepareDownload(request, downloadMap, feedbackList, isCheck, deptNoList, map);
} catch (Exception e) {
log.error("处理下载请求失败,姓名:{},身份证:{},项目编码:{}",
request.getEmpName(), request.getEmpIdcard(), request.getDeptNo(), e);
......@@ -240,7 +243,20 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
}
}
// 2. 设置响应头
// 2. 校验文件总大小是否超过500MB
long totalSize = calculateTotalFileSize(downloadMap);
long maxSize = 500 * 1024 * 1024L; // 500MB
if (totalSize > maxSize) {
log.warn("批量下载文件总大小超过限制,总大小:{}MB,限制:500MB", totalSize / 1024 / 1024);
response.setContentType("application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
String errorMsg = String.format("{\"code\":1,\"msg\":\"下载文件总大小超过限制,当前总大小:%.2fMB,最大允许:500MB\"}",
totalSize / 1024.0 / 1024.0);
response.getWriter().write(errorMsg);
return;
}
// 3. 设置响应头
String fileName = "电子档案批量下载_" +
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".zip";
response.setContentType("application/zip");
......@@ -248,10 +264,10 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
response.setHeader(CommonConstants.CONTENT_DISPOSITION,
"attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
// 3. 创建ZIP输出流
// 4. 创建ZIP输出流
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
// 4. 下载并打包档案文件
// 5. 下载并打包档案文件
for (Map.Entry<String, ArchiveDownloadInfo> entry : downloadMap.entrySet()) {
String folderName = entry.getKey();
ArchiveDownloadInfo downloadInfo = entry.getValue();
......@@ -260,11 +276,13 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
downloadArchiveFiles(zipOut, folderName, downloadInfo);
// 更新反馈状态为成功
// 使用materialTypeAttaMap的所有key来匹配,确保所有资料类型的反馈都被更新
Set<String> materialTypes = downloadInfo.getMaterialTypeAttaMap().keySet();
for (ArchiveDownloadFeedbackVO feedback : feedbackList) {
if (feedback.getEmpName().equals(downloadInfo.getDetail().getEmpName()) &&
feedback.getEmpIdcard().equals(downloadInfo.getDetail().getEmpIdcard()) &&
feedback.getDeptNo().equals(downloadInfo.getDetail().getDeptNo()) &&
feedback.getMaterialType().equals(downloadInfo.getMaterialType())) {
(materialTypes.contains(feedback.getMaterialType()) || "全部资料类型".equals(feedback.getMaterialType()))) {
feedback.setDownloadStatus("成功");
feedback.setFailReason("");
}
......@@ -272,11 +290,12 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
} catch (Exception e) {
log.error("下载档案文件失败,文件夹:{}", folderName, e);
// 更新反馈状态为失败
Set<String> materialTypes = downloadInfo.getMaterialTypeAttaMap().keySet();
for (ArchiveDownloadFeedbackVO feedback : feedbackList) {
if (feedback.getEmpName().equals(downloadInfo.getDetail().getEmpName()) &&
feedback.getEmpIdcard().equals(downloadInfo.getDetail().getEmpIdcard()) &&
feedback.getDeptNo().equals(downloadInfo.getDetail().getDeptNo()) &&
feedback.getMaterialType().equals(downloadInfo.getMaterialType())) {
(materialTypes.contains(feedback.getMaterialType()) || "全部资料类型".equals(feedback.getMaterialType()))) {
feedback.setDownloadStatus("失败");
feedback.setFailReason("下载文件失败:" + e.getMessage());
}
......@@ -284,7 +303,7 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
}
}
// 5. 生成并添加反馈Excel表
// 6. 生成并添加反馈Excel表
addFeedbackExcel(zipOut, feedbackList);
zipOut.finish();
......@@ -329,7 +348,8 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
Map<String, ArchiveDownloadInfo> downloadMap,
List<ArchiveDownloadFeedbackVO> feedbackList,
boolean isCheck,
List<String> deptNoList) {
List<String> deptNoList,
Map<String,String> map) {
// 1. 根据姓名、身份证、项目编码、项目名称查询电子档案明细
LambdaQueryWrapper<TElectronicArchiveDetail> wrapper = Wrappers.<TElectronicArchiveDetail>lambdaQuery()
......@@ -346,6 +366,24 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
// 查询档案明细
TElectronicArchiveDetail detail = baseMapper.selectOne(wrapper);
StringBuilder s = new StringBuilder();
s.append(request.getEmpIdcard());
s.append("_");
s.append(request.getDeptNo());
s.append("_");
s.append(request.getDeptName());
s.append("_");
s.append(request.getEmpName());
s.append("_");
s.append(request.getMaterialType());
if (null != map.get(s.toString())) {
feedbackList.add(createFeedbackVO(request, "存在重复的导出人员信息",detail));
return;
}else {
map.put(s.toString(), "1");
}
//项目权限校验
if (isCheck && !deptNoList.contains(request.getDeptNo())) {
feedbackList.add(createFeedbackVO(request, "没有该项目的权限",detail));
......@@ -447,7 +485,7 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
if (!downloadInfo.getMaterialTypeAttaMap().containsKey(request.getMaterialType())) {
downloadInfo.getMaterialTypeAttaMap().put(request.getMaterialType(), attaList);
}
downloadInfo.setMaterialType(request.getMaterialType());
// 不再使用单个materialType字段,而是使用materialTypeAttaMap的所有key
// 添加成功的反馈(状态暂时为"处理中",实际下载完成后更新)
feedbackList.add(createSuccessFeedbackVO(request,detail));
......@@ -803,6 +841,19 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
return;
}
// 2. 校验文件总大小是否超过500MB
long totalSize = calculateTotalFileSize(downloadMap);
long maxSize = 500 * 1024 * 1024L; // 500MB
if (totalSize > maxSize) {
log.warn("批量下载文件总大小超过限制,总大小:{}MB,限制:500MB", totalSize / 1024 / 1024);
response.setContentType("application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
String errorMsg = String.format("{\"code\":1,\"msg\":\"下载文件总大小超过限制,当前总大小:%.2fMB,最大允许:500MB\"}",
totalSize / 1024.0 / 1024.0);
response.getWriter().write(errorMsg);
return;
}
// 3. 设置响应头
String fileName = "电子档案勾选导出_" +
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".zip";
......@@ -1131,6 +1182,19 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
return;
}
// 2. 校验文件总大小是否超过500MB
long totalSize = calculateTotalFileSize(downloadMap);
long maxSize = 500 * 1024 * 1024L; // 500MB
if (totalSize > maxSize) {
log.warn("批量下载文件总大小超过限制,总大小:{}MB,限制:500MB", totalSize / 1024 / 1024);
response.setContentType("application/json;charset=UTF-8");
response.setCharacterEncoding("UTF-8");
String errorMsg = String.format("{\"code\":1,\"msg\":\"下载文件总大小超过限制,当前总大小:%.2fMB,最大允许:500MB\"}",
totalSize / 1024.0 / 1024.0);
response.getWriter().write(errorMsg);
return;
}
// 5. 设置响应头
String fileName = "电子档案条件导出_" +
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".zip";
......@@ -1319,6 +1383,19 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
return R.failed("电子档案明细不存在");
}
List<TTaskArchiveRelation> relationList = relationService.list(Wrappers.<TTaskArchiveRelation>lambdaQuery()
.eq(TTaskArchiveRelation::getArchiveDetailId, id));
if (Common.isNotNull(relationList)) {
for (TTaskArchiveRelation relation: relationList) {
//查找是否存在任务
TElectronicArchiveTask task = taskService.getById(relation.getTaskId());
if (Common.isNotNull(task) && task.getStatus().equals(ArchiveConstants.TASK_STATUS_NOT_UPLOADED)) {
return R.failed("该明细正在被待上传zip文件的任务使用,请先删除任务或者上传对应的zip文件,"
+ "任务编码:" +task.getTaskCode());
}
}
}
// 2. 查询该明细下所有的附件(包括可用和不可用的)
List<TAttaInfo> attachments = attaInfoService.list(Wrappers.<TAttaInfo>lambdaQuery()
.eq(TAttaInfo::getDomainId, id)
......@@ -1373,7 +1450,6 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
}
// 7. 构建返回消息
YifuUser user = SecurityUtils.getUser();
String resultMsg = String.format("删除成功。明细:%s-%s-%s,附件删除成功:%d个",
detail.getDeptNo(), detail.getEmpName(), detail.getEmpIdcard(), attachmentSuccessCount);
......@@ -1388,4 +1464,35 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
return R.failed("删除失败:" + e.getMessage());
}
}
/**
* 计算下载文件总大小
*
* @param downloadMap 下载信息Map
* @return 文件总大小(字节)
*/
private long calculateTotalFileSize(Map<String, ArchiveDownloadInfo> downloadMap) {
long totalSize = 0L;
for (Map.Entry<String, ArchiveDownloadInfo> entry : downloadMap.entrySet()) {
ArchiveDownloadInfo downloadInfo = entry.getValue();
Map<String, List<TAttaInfo>> materialTypeAttaMap = downloadInfo.getMaterialTypeAttaMap();
if (materialTypeAttaMap != null) {
for (Map.Entry<String, List<TAttaInfo>> attaEntry : materialTypeAttaMap.entrySet()) {
List<TAttaInfo> attaList = attaEntry.getValue();
if (CollUtil.isNotEmpty(attaList)) {
for (TAttaInfo atta : attaList) {
if (atta.getAttaSize() != null) {
totalSize += atta.getAttaSize();
}
}
}
}
}
}
log.info("批量下载文件总大小:{}字节({}MB)", totalSize, totalSize / 1024.0 / 1024.0);
return totalSize;
}
}
......@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveDetail;
import com.yifu.cloud.plus.v1.batch.entity.TElectronicArchiveTask;
import com.yifu.cloud.plus.v1.batch.entity.TTaskArchiveRelation;
import com.yifu.cloud.plus.v1.batch.mapper.TElectronicArchiveDetailMapper;
......@@ -67,7 +68,9 @@ public class TElectronicArchiveTaskServiceImpl extends ServiceImpl<TElectronicAr
//删除关联关系表
relationService.removeById(relation.getId());
//删除电子档案明细表
detailMapper.deleteById(relation.getArchiveDetailId());
detailMapper.delete(Wrappers.<TElectronicArchiveDetail>query().lambda()
.eq(TElectronicArchiveDetail::getStatus,CommonConstants.ZERO_STRING)
.eq(TElectronicArchiveDetail::getId,relation.getArchiveDetailId()));
}
}
return R.ok();
......
......@@ -104,7 +104,7 @@
<include refid="Base_Column_List"/>
FROM t_electronic_archive_detail a
<where>
a.DELETE_FLAG = '0'
a.DELETE_FLAG = '0' and a.STATUS = '1'
<include refid="tElectronicArchiveDetail_where"/>
</where>
ORDER BY a.CREATE_TIME DESC
......@@ -116,7 +116,7 @@
<include refid="Base_Column_List"/>
FROM t_electronic_archive_detail a
<where>
a.DELETE_FLAG = '0'
a.DELETE_FLAG = '0' and a.STATUS = '1'
<include refid="tElectronicArchiveDetail_where"/>
</where>
ORDER BY a.CREATE_TIME DESC
......
......@@ -45,5 +45,9 @@
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
......@@ -48,4 +48,6 @@ public interface ChecksConstants {
String ID_NUM="idNum";
String CARD_NO="cardNo";
String ORDER_NO="orderNo";
}
......@@ -79,6 +79,12 @@ public class TCheckMobile extends BaseEntity {
@Schema(description ="检测结果,枚举值:0:空号 1:实号 2:停机 3:库无 4:沉默号 5:风险号 10:配置或接口异常")
private String status;
/**
* 检测结果,枚举值:1 正常 2 空号 3 通话中(此状态失效,不返回) 4 不在网(即空号,可以和状态2合并) 5 关机 7 在网但不可用 13 停机 10 未知 9 服务器异常 12 不存在的号码
*/
@Schema(description ="检测结果,枚举值:0:空号 1:实号 2:停机 3:库无 4:沉默号 5:风险号 10:配置或接口异常")
private String statusNew;
/**
* 响应code码解释
*/
......
......@@ -10,11 +10,11 @@ import com.yifu.cloud.plus.v1.check.entity.TCheckIdCard;
import com.yifu.cloud.plus.v1.check.entity.TCheckMobile;
import com.yifu.cloud.plus.v1.yifu.common.core.constant.CommonConstants;
import com.yifu.cloud.plus.v1.yifu.common.core.util.Common;
import com.yifu.cloud.plus.v1.yifu.common.core.util.DateUtil;
import com.yifu.cloud.plus.v1.yifu.common.core.util.R;
import com.yifu.cloud.plus.v1.yifu.common.core.util.RandomUtil;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* @author hgw2
......@@ -30,6 +30,9 @@ public class ChecksUtil {
private static final String APP_KEY_IDCARD = "s4lW5JRA";
private static final String API_URL = "https://api.253.com/open/idcard/id-card-auth";
private static final String API_URL_MOBILE = "https://api.253.com/open/unn/batch-ucheck";
private static final String API_URL_MOBILE_NEW = "https://api.253.com/open/mobstatus/mobstatus-query-basic";
private static final String API_URL_BANK_NO ="https://api.253.com/open/bankcard/card-auth";
private static final String API_URL_BANK_NO_TWO ="https://api.253.com/open/bankcard/card-two-auth";
private static final String API_URL_BANK_NO_THREE ="https://api.253.com/open/bankcard/card-three-auth";
......@@ -75,6 +78,35 @@ public class ChecksUtil {
return R.ok(resMap);
}
}
/**
* @Author fxj
* @Description 手机号码状态检测--号码实时基础版
* @Date 17:50 2022/6/20
* @param mobiles 检测手机号,多个手机号码用英文半角逗号隔开,仅支持国内号码 一次请求最多五十个号码
**/
public static R<Map<String,TCheckMobile>> checkMobileBasic(String mobiles, boolean canCheck) {
Map<String,TCheckMobile> checkMobiles = new HashMap<>();
if (canCheck) {
// 1.调用手机信息校验api
return checkMobileBasicMethod(mobiles,checkMobiles);
} else {
TCheckMobile checkMobile;
List<String> mobileList = Common.initStrToList(mobiles,CommonConstants.COMMA_STRING);
Map<String,TCheckMobile> resMap = new HashMap<>();
if (Common.isNotNull(mobileList)){
for (String m:mobileList){
checkMobile = new TCheckMobile();
checkMobile.setMobile(m);
checkMobile.setStatus(CommonConstants.ONE_STRING);
checkMobile.setType(CommonConstants.ONE_STRING);
checkMobile.setMessage(ChecksConstants.CHECK_CONFIG_ACCESS);
resMap.put(m,checkMobile);
}
}
return R.ok(resMap);
}
}
/**
* @Author fxj
* @Description 银行卡四要素标准版 校验
......@@ -247,7 +279,78 @@ public class ChecksUtil {
}
return R.ok(checkMobileMap);
}
/**
* @Author fxj
* @Description 手机号码状态检测--号码实时基础版
* 倩倩确定:非2、4、12的都可以进
* 开发api :https://rkzav3pcv4.feishu.cn/wiki/SCt3wBxhEig772kzQxecMGtjnig
* @Date 11:50 2026/1/12
* @Param
* @return
**/
private static R<Map<String,TCheckMobile>> checkMobileBasicMethod(String mobiles, Map<String,TCheckMobile> checkMobileMap) {
if (Common.isEmpty(mobiles)){
return R.failed("手机号码不能为空");
}
List<String> mobileList = new ArrayList<>();
mobileList.addAll(Arrays.asList(mobiles.split(",")));
JsonObject jsonObject;
if (mobileList.size() > CommonConstants.ZERO_INT){
TCheckMobile mobile = null;
for (String mb : mobileList){
jsonObject = ChecksUtil.invokeMobileBasic(mb);
// 2.处理返回结果
if (jsonObject != null) {
//响应code码。200000:成功,其他失败
String code = jsonObject.get(ChecksConstants.CODE).getAsString();
if (ChecksConstants.CODE_200000.equals(code) && jsonObject.get(ChecksConstants.DATA) != null) {
// 调用身份信息校验成功
// 解析结果数据,进行业务处理
// 校验状态码 200000:成功,其他失败
JsonObject mobileJson = jsonObject.get(ChecksConstants.DATA).getAsJsonObject();
String message = jsonObject.get(ChecksConstants.MESSAGE).getAsString();
if (Common.isNotNull(mobileJson)){
mobile = new TCheckMobile();
mobile.setMobile(getJsonElementValue(mobileJson.get(ChecksConstants.MOBILE)));
mobile.setArea(getJsonElementValue(mobileJson.get(ChecksConstants.AREA)));
mobile.setNumbertype(getJsonElementValue(mobileJson.get(ChecksConstants.NUMBER_TYPE)));
mobile.setChargesstatus(getJsonElementValue(mobileJson.get(ChecksConstants.CHARGES_STATUS)));
mobile.setStatus(getJsonElementValue(mobileJson.get(ChecksConstants.STATUS)));
//老检测结果,枚举值:0:空号 1:实号 2:停机 3:库无 4:沉默号 5:风险号 10:配置异常 (1、4、5为号码正常放行)
//新号码状态,1 正常 2 空号 3 通话中(此状态失效,不返回) 4 不在网(即空号,可以和状态2合并) 5 关机 7 在网但不可用 13 停机 10 未知 9 服务器异常 12 不存在的号码
//倩倩确定:新号码状态非2、4、12的都可以进
//转换好旧状态
if ( !CommonConstants.TWO_STRING.equals(mobile.getStatus())
&& !CommonConstants.FOUR_STRING.equals(mobile.getStatus())
&& !CommonConstants.TWELVE_STRING.equals(mobile.getStatus())){
mobile.setStatus(CommonConstants.ONE_STRING);
}else {
if (CommonConstants.TWO_STRING.equals(mobile.getStatus())
|| CommonConstants.FOUR_STRING.equals(mobile.getStatus())){
mobile.setStatus(CommonConstants.ZERO_STRING);
}
if (CommonConstants.TWELVE_STRING.equals(mobile.getStatus())){
mobile.setStatus(CommonConstants.THREE_STRING);
}
}
//保存新状态
mobile.setStatusNew(getJsonElementValue(mobileJson.get(ChecksConstants.STATUS)));
//转换成老的状态
mobile.setMessage(message);
mobile.setType(CommonConstants.ONE_STRING);
checkMobileMap.put(mb,mobile);
}
} else {
// 记录错误日志,正式项目中请换成log打印
return R.failed("手机号校验失败:" + jsonObject.get(ChecksConstants.MESSAGE).getAsString());
}
} else {
return R.failed(ChecksConstants.NO_DATA_RESULT);
}
}
}
return R.ok(checkMobileMap);
}
// 核心调用
private static void checkIdCardMethod(TCheckIdCard checkIdCard) {
final JsonObject jsonObject = ChecksUtil.invokeIdCard(checkIdCard.getName(), checkIdCard.getIdCard());
......@@ -312,6 +415,39 @@ public class ChecksUtil {
}
return null;
}
/**
* @Author fxj
* @Description 手机号码状态检测--实时基础版
* 号码实时基础版status解释
* 1-正常 ----(通话中、正常号码、响应慢 (静音)、忙音) 可以正常打通的号码
* 13-停机--- 停机号码
* 7-在网但不可用 ---、号码小号呼转、手机号码繁忙,无法接听,不在服务区等。
* 4-不在网(空号)--- 空号销号的号码
* 3-通话中 ---号码在通话中、可以放在正常状态里面
* 5-关机-- 当时该手机处于关机或者没电来电提醒的状态
* 2-空号 ---空号、未激活使用的号码
* 9-服务器异常 --运营商异常或系统内部异常,也包含特殊号码无法查询
* 10-未知 ---号码失败次数超频,请隔天再试/运营商返回其他的错误信息、号码管控、号段不支持
* 12-号码不存在--- 号码不支持/运营商返回其他的错误信息
* 倩倩确定:非2、4、12的都可以进
* @Date 11:32 2026/1/12
* @Param
* @return
**/
private static JsonObject invokeMobileBasic(String mobiles) {
Map<String, String> params = new HashMap<>();
params.put(ChecksConstants.APP_ID, APP_ID);
params.put(ChecksConstants.APP_KEY, APP_KEY_IDCARD);
params.put(ChecksConstants.MOBILE, mobiles);
params.put(ChecksConstants.ORDER_NO, new Date().getTime()+ RandomUtil.getSix());
//请求参数 Body 以 multipart/form-data 方式提交
String result = HttpUtils.postMultipart(API_URL_MOBILE_NEW, params);
// 解析json,并返回结果
if (Common.isNotNull(result)){
return jsonParser.parse(result).getAsJsonObject();
}
return null;
}
private static JsonObject invokeBankNo(String name, String idNum, String cardNo, String mobile) {
Map<String, String> params = new HashMap<>();
......
......@@ -5,10 +5,13 @@ import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Map;
......@@ -47,6 +50,15 @@ public class HttpUtils {
return send(RequestBuilder.post(url), paramsMap);
}
/**
* 以 multipart/form-data 方式提交POST请求
* @param url 请求地址
* @param paramsMap 参数map
* @return 响应结果
*/
public static String postMultipart(String url, Map<String, String> paramsMap) {
return sendMultipart(RequestBuilder.post(url), paramsMap);
}
public static String send(RequestBuilder requestBuilder, Map<String, String> paramsMap) {
requestBuilder.setCharset(Charset.forName(ENCODING));
......@@ -80,4 +92,51 @@ public class HttpUtils {
return responseText;
}
/**
* 以 multipart/form-data 方式发送请求
* @param requestBuilder 请求构建器
* @param paramsMap 参数map
* @return 响应结果
*/
public static String sendMultipart(RequestBuilder requestBuilder, Map<String, String> paramsMap) {
String responseText = "";
if (paramsMap != null) {
// 创建 multipart/form-data 实体
MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create();
entityBuilder.setCharset(Charset.forName(ENCODING));
// 添加参数到 multipart 实体
for (Map.Entry<String, String> param : paramsMap.entrySet()) {
try {
entityBuilder.addPart(param.getKey(), new StringBody(param.getValue(), Charset.forName(ENCODING)));
} catch (UnsupportedEncodingException e) {
return null;
}
}
HttpEntity entity = entityBuilder.build();
requestBuilder.setEntity(entity);
CloseableHttpResponse response = null;
try {
response = client.execute(requestBuilder.build());
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity responseEntity = response.getEntity();
if (responseEntity != null) {
responseText = EntityUtils.toString(responseEntity, ENCODING);
}
}
} catch (Exception e) {
e.printStackTrace();//正式项目中请改为log打印
} finally {
try {
response.close();
} catch (Exception e) {
e.printStackTrace();//正式项目中请改为log打印
}
}
}
return responseText;
}
}
\ No newline at end of file
......@@ -18,6 +18,7 @@ package com.yifu.cloud.plus.v1.check.service.impl;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yifu.cloud.plus.v1.check.constant.ChecksConstants;
import com.yifu.cloud.plus.v1.check.entity.TCanCheck;
import com.yifu.cloud.plus.v1.check.entity.TCheckMobile;
import com.yifu.cloud.plus.v1.check.entity.TPreEmpCheckNum;
......@@ -88,7 +89,7 @@ public class TCheckMobileServiceImpl extends ServiceImpl<TCheckMobileMapper, TCh
mobileList.removeAll(existMap.keySet());
//2.从远处端获取数据
if (Common.isNotNull(mobileList)) {
mobileMapR = ChecksUtil.checkMobile(Common.ListToStr(mobileList, CommonConstants.COMMA_STRING), canCheckService.getCanCheck());
mobileMapR = ChecksUtil.checkMobileBasic(Common.ListToStr(mobileList, CommonConstants.COMMA_STRING), canCheckService.getCanCheck());
if (Common.isEmpty(mobileMapR) || Common.isEmpty(mobileMapR.getData())) {
return R.failed(MsgUtils.getMessage(ErrorCodes.CHECKS_MOBILE_REQUEST_ERROR)
+ (Common.isNotNull(mobileMapR) ? mobileMapR.getMsg() : CommonConstants.EMPTY_STRING));
......@@ -150,7 +151,7 @@ public class TCheckMobileServiceImpl extends ServiceImpl<TCheckMobileMapper, TCh
return returnMobile;
} else {
//2.从远处端获取数据
R<Map<String, TCheckMobile>> mobileMapR = ChecksUtil.checkMobile(mobile, canCheckService.getCanCheck());
R<Map<String, TCheckMobile>> mobileMapR = ChecksUtil.checkMobileBasic(mobile, canCheckService.getCanCheck());
if (Common.isEmpty(mobileMapR) || Common.isEmpty(mobileMapR.getData())) {
if (mobileMapR != null) {
returnMobile.setMessage(mobileMapR.getMsg());
......@@ -237,7 +238,7 @@ public class TCheckMobileServiceImpl extends ServiceImpl<TCheckMobileMapper, TCh
}
}
synchronized (this) {
R<Map<String, TCheckMobile>> mobileMapR = ChecksUtil.checkMobile(phone, canCheck);
R<Map<String, TCheckMobile>> mobileMapR = ChecksUtil.checkMobileBasic(phone, canCheck);
if (Common.isNotNull(mobileMapR) && Common.isNotNull(mobileMapR.getData())) {
Map<String, TCheckMobile> result = mobileMapR.getData();
TCheckMobile mo = result.get(phone);
......@@ -249,7 +250,8 @@ public class TCheckMobileServiceImpl extends ServiceImpl<TCheckMobileMapper, TCh
|| CommonConstants.FIVE_STRING.equals(mo.getStatus()))) {
return R.ok();
} else {
return R.failed(Common.isNotNull(mo.getMessage()) ? mo.getMessage() : "校验错误!");
//提示语不正确 特地优化了 fxj 2026-01-15
return R.failed("手机号码不可用!");
}
} else {
return R.failed("校验失败");
......@@ -285,7 +287,7 @@ public class TCheckMobileServiceImpl extends ServiceImpl<TCheckMobileMapper, TCh
List<TCheckMobile> saveList = new ArrayList<>();
if (!noCurlist.isEmpty() && Common.isNotNull(phones)) {
synchronized (this) {
R<Map<String, TCheckMobile>> mobileMapR = ChecksUtil.checkMobile(phones.toString(), canCheckService.getCanCheck());
R<Map<String, TCheckMobile>> mobileMapR = ChecksUtil.checkMobileBasic(phones.toString(), canCheckService.getCanCheck());
if (Common.isNotNull(mobileMapR) && Common.isNotNull(mobileMapR.getData())) {
Map<String, TCheckMobile> result = mobileMapR.getData();
TCheckMobile mo;
......@@ -307,4 +309,61 @@ public class TCheckMobileServiceImpl extends ServiceImpl<TCheckMobileMapper, TCh
}
vo.setCheckMap(backMap);
}
/* * 临时查询本地库的代码,先留存吧
private R<Map<String,TCheckMobile>> checkMobileTemp(String mobiles, boolean canCheck) {
Map<String,TCheckMobile> resMap = new HashMap<>();
TCheckMobile checkMobile;
List<String> mobileList = Common.initStrToList(mobiles,CommonConstants.COMMA_STRING);
if (canCheck) {
Map<String, TCheckMobile> existMap = new HashMap<>();
if (Common.isNotNull(mobiles)) {
if (Common.isNotEmpty(mobileList) && mobileList.size() > CommonConstants.INTEGER_HUNDRED) {
return R.failed(MsgUtils.getMessage(ErrorCodes.CHECKS_MOBILE_REQUEST_LIMIT_HUNDRED));
}
//1.先从本地库获取正常数据
List<TCheckMobile> checkMobiles = baseMapper.selectList(Wrappers.<TCheckMobile>query().lambda()
.in(TCheckMobile::getMobile, mobileList));
if (Common.isNotNull(checkMobiles)) {
for (TCheckMobile c : checkMobiles) {
if (CommonConstants.ONE_STRING.equals(c.getStatus())
|| CommonConstants.FOUR_STRING.equals(c.getStatus())
|| CommonConstants.FIVE_STRING.equals(c.getStatus())) {
c.setStatus(CommonConstants.ONE_STRING);
} else {
c.setStatus(c.getStatus());
}
c.setMessage(c.getMessage());
resMap.put(c.getMobile(), c);
}
existMap = checkMobiles.stream().collect(Collectors.toMap(TCheckMobile::getMobile, TCheckMobile -> TCheckMobile));
}
mobileList.removeAll(existMap.keySet());
if (Common.isNotEmpty(mobileList)) {
for (String mobile : mobileList) {
checkMobile = new TCheckMobile();
checkMobile.setMobile(mobile);
checkMobile.setStatus(CommonConstants.ONE_STRING);
checkMobile.setType(CommonConstants.ONE_STRING);
checkMobile.setMessage(ChecksConstants.CHECK_CONFIG_ACCESS);
resMap.put(mobile, checkMobile);
}
}
}
} else {
resMap = new HashMap<>();
if (Common.isNotNull(mobileList)) {
for (String m : mobileList) {
checkMobile = new TCheckMobile();
checkMobile.setMobile(m);
checkMobile.setStatus(CommonConstants.ONE_STRING);
checkMobile.setType(CommonConstants.ONE_STRING);
checkMobile.setMessage(ChecksConstants.CHECK_CONFIG_ACCESS);
resMap.put(m, checkMobile);
}
}
}
return R.ok(resMap);
}*/
}
......@@ -36,6 +36,7 @@
<result property="numbertype" column="numberType"/>
<result property="chargesstatus" column="chargesStatus"/>
<result property="status" column="status"/>
<result property="statusNew" column="status_new"/>
<result property="message" column="message"/>
</resultMap>
......@@ -44,7 +45,7 @@
SELECT
a.id,
a.mobile,
a.status
a.status,status_new
FROM t_check_mobile a
where a.mobile in
<foreach item="item" index="index" collection="noList" open="(" separator="," close=")">
......
......@@ -902,11 +902,18 @@ public class EmployeeRegistrationServiceImpl extends ServiceImpl<EmployeeRegistr
//当月办次月生效
if (CommonConstants.ONE_STRING.equals(innerVo.getAddHandleRule())){
if (canBeHandle){
if (isBeforeThreshold){
Date today = new Date();
preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
today, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
today, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
}else {
preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
tomorrow, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
tomorrow, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
}
} else {
preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
nextMonthFirstDay, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
......
......@@ -39,7 +39,7 @@ public interface TInsurancePolicyMapper extends BaseMapper<TInsurancePolicy> {
*/
List<TInsurancePolicy> getInsurancePolicyList(@Param("param") InsurancePolicyListParam param);
Page<PolicyListVo> policyPageToAutoSelect(Page page,@Param("param") InsuredParam param);
IPage<PolicyListVo> policyPageToAutoSelect(Page page,@Param("param") InsuredParam param);
}
......
......@@ -75,5 +75,5 @@ public interface TInsurancePolicyService extends IService<TInsurancePolicy> {
R<List<ErrorMessage>> importInsurancePolicy(InputStream inputStream);
Page<PolicyListVo> policyPageToAutoSelect(Page<PolicyListVo> page, InsuredParam param, String mId);
IPage<PolicyListVo> policyPageToAutoSelect(Page<PolicyListVo> page, InsuredParam param, String mId);
}
......@@ -430,7 +430,7 @@ public class TInsurancePolicyServiceImpl extends ServiceImpl<TInsurancePolicyMap
@Override
public Page<PolicyListVo> policyPageToAutoSelect(Page<PolicyListVo> page, InsuredParam param, String mId) {
public IPage<PolicyListVo> policyPageToAutoSelect(Page<PolicyListVo> page, InsuredParam param, String mId) {
// 查保单未过期的数据
String today = LocalDateUtil.getDateSrt(LocalDate.now());
param.setPolicyEnd(today);
......
......@@ -649,11 +649,12 @@
a.INSURANCE_CITY_NAME as insuranceCityName
from
t_insurance_detail a
left join t_employee_insurance_pre b on a.id = b.insurances_id
where
a.DELETE_FLAG = 0
and (a.BUY_HANDLE_STATUS in (1,2) or (a.BUY_HANDLE_STATUS = 3 and a.IS_EFFECT = 0 and a.IS_OVERDUE = 0))
AND EMP_IDCARD_NO = #{empIdCard}
and a.create_name not like '自动化%'
AND EMP_IDCARD_NO = #{empIdCard} and b.id is null
group by a.id
</select>
<!-- ***********************减员办理******************************** -->
......
......@@ -125,7 +125,27 @@ public class SysHouseHoldInfoController {
public R<Boolean> updateById(@RequestBody SysHouseHoldInfo sysHouseHoldInfo) {
return sysHouseHoldInfoService.updateByIdAsso(sysHouseHoldInfo);
}
/**
* 启用禁用
* @param delFlag 户启用禁用 0 启用 1 禁用
* @return R
*/
@Operation(summary = "修改社保户公积金户启用禁用", description = "修改社保户公积金户启用禁用")
@SysLog("修改社保户公积金户启用禁用" )
@PostMapping("/updateDeFlag")
public R updateDeFlag(@RequestParam String id, @RequestParam(required = false) String delFlag ) {
if (Common.isEmpty(delFlag)){
return R.failed("请选择启用禁用状态");
}
SysHouseHoldInfo sysHouseHoldInfo = sysHouseHoldInfoService.getById(id);
if (Common.isNotNull(sysHouseHoldInfo)) {
if (Common.isNotNull(delFlag)){
sysHouseHoldInfo.setDelFlag(delFlag);
}
return sysHouseHoldInfoService.updateStatusById(sysHouseHoldInfo);
}
return R.failed(CommonConstants.NO_DATA_TO_HANDLE);
}
/**
* 修改社保户公积金户自动化配置
* @param autoStatus 户自动化配置启用禁用标识 0 启用 1 禁用
......
......@@ -1007,11 +1007,20 @@ public class TDispatchInfoPreServiceImpl extends ServiceImpl<TDispatchInfoPreMap
//当月办次月生效
if (CommonConstants.ONE_STRING.equals(innerVo.getAddHandleRule())){
if (canBeHandle){
//发起时间不看工作日
if (isBeforeThreshold) {
Date today = new Date();
preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
today, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
today, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
}else {
preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
tomorrow, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
preVo2.setExpectedConfirmTime(DateUtil.parseDate(DateUtil.dateToString(
tomorrow, DateUtil.ISO_EXPANDED_DATE_FORMAT) + confirmTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
}
} else {
preVo2.setExpectedCollectionTime(DateUtil.parseDate(DateUtil.dateToString(
nextMonthFirstDay, DateUtil.ISO_EXPANDED_DATE_FORMAT) + collectionTimeFormat, DateUtil.DATETIME_PATTERN_MINUTE));
......
......@@ -508,8 +508,12 @@ public class THouseHoldLimitServiceImpl extends ServiceImpl<THouseHoldLimitMappe
//当月办次月生效
if (CommonConstants.ONE_STRING.equals(addHandleRule)){
if (canBeHandle){
if (isBeforeThreshold){
Date today = new Date();
return DateUtil.dateToString(today, DateUtil.ISO_EXPANDED_DATE_FORMAT);
}else {
return DateUtil.dateToString(tomorrow, DateUtil.ISO_EXPANDED_DATE_FORMAT);
}
} else {
return DateUtil.dateToString(nextMonthFirstDay, DateUtil.ISO_EXPANDED_DATE_FORMAT);
}
......
......@@ -303,26 +303,29 @@
AND DATE_FORMAT(a.FUND_START_DATE,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.fundTimeEnd}
</if>
<!-- 社保五险起缴日期查询,有一个符合就出现 -->
<if test="tDispatchInfoPre.socialTimeStart != null">
<if test="tDispatchInfoPre.socialTimeStart != null and tDispatchInfoPre.socialTimeEnd != null">
AND (
(a.PENSION_START is not null and DATE_FORMAT(a.PENSION_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart} ) or
(a.MEDICAL_START is not null and DATE_FORMAT(a.MEDICAL_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart} ) or
(a.WORK_INJURY_START is not null and DATE_FORMAT(a.WORK_INJURY_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart} ) or
(a.UNEMPLOY_START is not null and DATE_FORMAT(a.UNEMPLOY_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart} ) or
(a.BIRTH_START is not null and DATE_FORMAT(a.BIRTH_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart} ) or
(a.BIGAILMENT_START is not null and DATE_FORMAT(a.BIGAILMENT_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart} )
(a.PENSION_START is not null and DATE_FORMAT(a.PENSION_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart}
and DATE_FORMAT(a.PENSION_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd}
) or
(a.MEDICAL_START is not null and DATE_FORMAT(a.MEDICAL_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart}
and DATE_FORMAT(a.MEDICAL_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd}
) or
(a.WORK_INJURY_START is not null and DATE_FORMAT(a.WORK_INJURY_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart}
and DATE_FORMAT(a.WORK_INJURY_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd}
) or
(a.UNEMPLOY_START is not null and DATE_FORMAT(a.UNEMPLOY_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart}
and DATE_FORMAT(a.UNEMPLOY_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd}
) or
(a.BIRTH_START is not null and DATE_FORMAT(a.BIRTH_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart}
and DATE_FORMAT(a.BIRTH_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd}
) or
(a.BIGAILMENT_START is not null and DATE_FORMAT(a.BIGAILMENT_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart}
and DATE_FORMAT(a.BIGAILMENT_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd}
)
</if>
<if test="tDispatchInfoPre.socialTimeEnd != null">
AND (
(a.PENSION_START is not null and DATE_FORMAT(a.PENSION_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd} ) or
(a.MEDICAL_START is not null and DATE_FORMAT(a.MEDICAL_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd} ) or
(a.WORK_INJURY_START is not null and DATE_FORMAT(a.WORK_INJURY_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd} ) or
(a.UNEMPLOY_START is not null and DATE_FORMAT(a.UNEMPLOY_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd} ) or
(a.BIRTH_START is not null and DATE_FORMAT(a.BIRTH_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd} ) or
(a.BIGAILMENT_START is not null and DATE_FORMAT(a.BIGAILMENT_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd} )
)
</if>
</if>
</sql>
......@@ -417,24 +420,26 @@
AND DATE_FORMAT(a.FUND_START_DATE,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.fundTimeEnd}
</if>
<!-- 社保五险起缴日期查询,有一个符合就出现 -->
<if test="tDispatchInfoPre.socialTimeStart != null">
<if test="tDispatchInfoPre.socialTimeStart != null and tDispatchInfoPre.socialTimeEnd != null">
AND (
(a.PENSION_START is not null and DATE_FORMAT(a.PENSION_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart} ) or
(a.MEDICAL_START is not null and DATE_FORMAT(a.MEDICAL_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart} ) or
(a.WORK_INJURY_START is not null and DATE_FORMAT(a.WORK_INJURY_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart} ) or
(a.UNEMPLOY_START is not null and DATE_FORMAT(a.UNEMPLOY_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart} ) or
(a.BIRTH_START is not null and DATE_FORMAT(a.BIRTH_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart} ) or
(a.BIGAILMENT_START is not null and DATE_FORMAT(a.BIGAILMENT_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart} )
(a.PENSION_START is not null and DATE_FORMAT(a.PENSION_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart}
and DATE_FORMAT(a.PENSION_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd}
) or
(a.MEDICAL_START is not null and DATE_FORMAT(a.MEDICAL_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart}
and DATE_FORMAT(a.MEDICAL_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd}
) or
(a.WORK_INJURY_START is not null and DATE_FORMAT(a.WORK_INJURY_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart}
and DATE_FORMAT(a.WORK_INJURY_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd}
) or
(a.UNEMPLOY_START is not null and DATE_FORMAT(a.UNEMPLOY_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart}
and DATE_FORMAT(a.UNEMPLOY_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd}
) or
(a.BIRTH_START is not null and DATE_FORMAT(a.BIRTH_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart}
and DATE_FORMAT(a.BIRTH_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd}
) or
(a.BIGAILMENT_START is not null and DATE_FORMAT(a.BIGAILMENT_START,'%Y-%m-%d') <![CDATA[ >= ]]> #{tDispatchInfoPre.socialTimeStart}
and DATE_FORMAT(a.BIGAILMENT_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd}
)
</if>
<if test="tDispatchInfoPre.socialTimeEnd != null">
AND (
(a.PENSION_START is not null and DATE_FORMAT(a.PENSION_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd} ) or
(a.MEDICAL_START is not null and DATE_FORMAT(a.MEDICAL_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd} ) or
(a.WORK_INJURY_START is not null and DATE_FORMAT(a.WORK_INJURY_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd} ) or
(a.UNEMPLOY_START is not null and DATE_FORMAT(a.UNEMPLOY_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd} ) or
(a.BIRTH_START is not null and DATE_FORMAT(a.BIRTH_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd} ) or
(a.BIGAILMENT_START is not null and DATE_FORMAT(a.BIGAILMENT_START,'%Y-%m-%d') <![CDATA[ <= ]]> #{tDispatchInfoPre.socialTimeEnd} )
)
</if>
</if>
......
......@@ -1269,7 +1269,7 @@
<!-- 社保状态:派增(0待审核、1待办理、2办理中 3办理成功、4部分办理失败 5 办理失败 10 审核不通过)、派减(6待审核 7待办理 8办理成功 9 办理失败 11派减办理中 12 派减部分办理失败) -->
and a.social_status in ('0', '1', '2', '3', '4', '6', '7', '9', '11', '12')
<if test="type != null and type = '1'">
and a.create_name not like '自动化%'
and d.create_name not like '自动化%'
</if>
</select>
<!--tSocialFundInfo简单分页查询-->
......@@ -1295,8 +1295,8 @@
<!-- 派增(0待审核、1待办理、3办理成功、4办理失败9 审核不通过)、派减(5待审核 6待办理 7 办理成功 8 办理失败 ) -->
and a.fund_status in ('0', '1', '3', '5', '6', '8')
<if test="type != null and type == '1'">
and a.create_name not like '自动化%'
<if test="type != null and type = '1'">
and d.create_name not like '自动化%'
</if>
</select>
<select id="selectSocialFundInfoCountByEmpIdcard" resultType="java.lang.Long">
......
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