Commit f0bbbb7f authored by fangxinjiang's avatar fangxinjiang

Merge remote-tracking branch 'origin/MVP1.7.18' into MVP1.7.18

parents 5d9b622e cd63095b
......@@ -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/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/app-max-request-size: "600" # 明确指定应用请求大小
dapr.io/http-max-request-size: "600" #增加http和grpc服务器请求正文参数的最大大小,单位为MB,以处理大文件的上传。 默认值为 4 MB
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
......
......@@ -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列表
......
......@@ -34,10 +34,11 @@ public interface ElectronicArchiveImportService {
/**
* 第三步:异步处理上传
*
* @param taskId 任务ID
* @return 处理结果
* @param taskId 任务ID
* @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);
......
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]));
YifuUser user = SecurityUtils.getUser();
attaInfo.setCreateBy(user.getId());
attaInfo.setCreateName(user.getNickname());
// 优先使用传入的用户信息(支持异步场景)
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());
......
......@@ -207,10 +207,10 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
*/
@Override
public void batchDownloadArchives(List<ArchiveBatchDownloadRequestVO> requestList, HttpServletResponse response) {
// 反馈列表
List<ArchiveDownloadFeedbackVO> feedbackList = new ArrayList<>();
// 用于存储需要下载的档案及其附件
Map<String, ArchiveDownloadInfo> downloadMap = new LinkedHashMap<>();
......@@ -220,26 +220,29 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
List<Long> roleList = user.getClientRoleMap().get(ClientNameConstants.CLIENT_MVP);
if (CommonConstants.ZERO_STRING.equals(user.getSystemFlag()) || (Common.isNotNull(roleList)
&& (roleList.stream().anyMatch(role -> role == 1569585030423158786L)
|| roleList.stream().anyMatch(role -> role == 2003347621962379266L)))) {
|| roleList.stream().anyMatch(role -> role == 2003347621962379266L)))) {
isCheck = false;
}
if (Common.isNotNull(user) && isCheck) {
deptNoList = getDeptNoList(user.getId());
}
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("处理下载请求失败,姓名:{},身份证:{},项目编码:{}",
log.error("处理下载请求失败,姓名:{},身份证:{},项目编码:{}",
request.getEmpName(), request.getEmpIdcard(), request.getDeptNo(), e);
feedbackList.add(createFeedbackVO(request, "系统异常:" + e.getMessage(),null));
}
}
// 2. 校验文件总大小是否超过500MB
long totalSize = calculateTotalFileSize(downloadMap);
long maxSize = 500 * 1024 * 1024L; // 500MB
......@@ -247,39 +250,39 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
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\"}",
String errorMsg = String.format("{\"code\":1,\"msg\":\"下载文件总大小超过限制,当前总大小:%.2fMB,最大允许:500MB\"}",
totalSize / 1024.0 / 1024.0);
response.getWriter().write(errorMsg);
return;
}
// 3. 设置响应头
String fileName = "电子档案批量下载_" +
String fileName = "电子档案批量下载_" +
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) + ".zip";
response.setContentType("application/zip");
response.setCharacterEncoding("UTF-8");
response.setHeader(CommonConstants.CONTENT_DISPOSITION,
"attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
// 4. 创建ZIP输出流
try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
// 5. 下载并打包档案文件
for (Map.Entry<String, ArchiveDownloadInfo> entry : downloadMap.entrySet()) {
String folderName = entry.getKey();
ArchiveDownloadInfo downloadInfo = entry.getValue();
try {
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()) &&
(materialTypes.contains(feedback.getMaterialType()) || "全部资料类型".equals(feedback.getMaterialType()))) {
feedback.getEmpIdcard().equals(downloadInfo.getDetail().getEmpIdcard()) &&
feedback.getDeptNo().equals(downloadInfo.getDetail().getDeptNo()) &&
(materialTypes.contains(feedback.getMaterialType()) || "全部资料类型".equals(feedback.getMaterialType()))) {
feedback.setDownloadStatus("成功");
feedback.setFailReason("");
}
......@@ -290,22 +293,22 @@ public class TElectronicArchiveDetailServiceImpl extends ServiceImpl<TElectronic
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()) &&
(materialTypes.contains(feedback.getMaterialType()) || "全部资料类型".equals(feedback.getMaterialType()))) {
feedback.getEmpIdcard().equals(downloadInfo.getDetail().getEmpIdcard()) &&
feedback.getDeptNo().equals(downloadInfo.getDetail().getDeptNo()) &&
(materialTypes.contains(feedback.getMaterialType()) || "全部资料类型".equals(feedback.getMaterialType()))) {
feedback.setDownloadStatus("失败");
feedback.setFailReason("下载文件失败:" + e.getMessage());
}
}
}
}
// 6. 生成并添加反馈Excel表
addFeedbackExcel(zipOut, feedbackList);
zipOut.finish();
}
} catch (Exception e) {
log.error("批量下载电子档案失败", e);
}
......@@ -345,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()
......@@ -362,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));
......
......@@ -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();
......
......@@ -241,37 +241,37 @@ public class OSSUtil {
log.error("oss客户端获取错误,无此客户端",clientIndex);
}else{
OSSObject ossObject = null;
for(OSSObjectBean key:srcList){
// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
ossObject = client.getObject(bucketName, key.getKey());
if(null != ossObject){
// 读取文件内容。
log.info("Object content:");
inputStream = ossObject.getObjectContent();
//添加到zip
zip.putNextEntry(new ZipEntry(key.getName()));
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) != -1){
zip.write(buf, 0, len);
}
}
// 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
IoUtil.close(inputStream);
zip.closeEntry();
}
}
// 关闭OSSClient。
} catch (OSSException oe) {
ossexceptionlog(oe);
} catch (ClientException ce) {
clientExceptionLog(ce);
} catch (IOException e) {
e.printStackTrace();
} finally {
IoUtil.close(inputStream);
}
}
for(OSSObjectBean key:srcList){
// ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
ossObject = client.getObject(bucketName, key.getKey());
if(null != ossObject){
// 读取文件内容。
log.info("Object content:");
inputStream = ossObject.getObjectContent();
//添加到zip
zip.putNextEntry(new ZipEntry(key.getName()));
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) != -1){
zip.write(buf, 0, len);
}
}
// 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
IoUtil.close(inputStream);
zip.closeEntry();
}
}
// 关闭OSSClient。
} catch (OSSException oe) {
ossexceptionlog(oe);
} catch (ClientException ce) {
clientExceptionLog(ce);
} catch (IOException e) {
e.printStackTrace();
} finally {
IoUtil.close(inputStream);
}
}
/**
* @author fang
......
......@@ -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);
......
......@@ -1295,7 +1295,7 @@
<!-- 派增(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'">
<if test="type != null and type = '1'">
and d.create_name not like '自动化%'
</if>
</select>
......
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