archive file

dev-tmp1
luotaiqian 2026-08-25 17:46:31 +08:00
parent a8db7ee59c
commit c71b875c4d
4 changed files with 135 additions and 84 deletions

View File

@ -7,7 +7,6 @@ import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil; import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.qinan.safetyeval.app.executor.institution.support.EvalCmdCopy; import org.qinan.safetyeval.app.executor.institution.support.EvalCmdCopy;
import org.qinan.safetyeval.app.executor.institution.support.EvalProjectNodeSupport; import org.qinan.safetyeval.app.executor.institution.support.EvalProjectNodeSupport;
@ -37,9 +36,10 @@ import org.qinan.safetyeval.infrastructure.convertor.EvalProcessControlConvertor
import org.qinan.safetyeval.infrastructure.convertor.EvalProjectMemberDoConvertor; import org.qinan.safetyeval.infrastructure.convertor.EvalProjectMemberDoConvertor;
import org.qinan.safetyeval.infrastructure.dataobject.*; import org.qinan.safetyeval.infrastructure.dataobject.*;
import org.qinan.safetyeval.infrastructure.mapper.*; import org.qinan.safetyeval.infrastructure.mapper.*;
import org.qinan.safetyeval.infrastructure.persistence.domainobject.EvalProjectArchiveFileDO;
import org.qinan.safetyeval.infrastructure.persistence.mapper.EvalProjectArchiveFileMapper;
import org.qinan.safetyeval.infrastructure.persistence.queryservice.*; import org.qinan.safetyeval.infrastructure.persistence.queryservice.*;
import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults; import org.qinan.safetyeval.infrastructure.support.InsertFieldDefaults;
import org.qinan.safetyeval.infrastructure.utils.CommonUtil;
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.util.CollectionUtils; import org.springframework.util.CollectionUtils;
@ -99,12 +99,12 @@ public class EvalProcessControlExecutor implements EvalProcessControlApi {
@Resource @Resource
private EvalProcessControlMapper evalProcessControlMapper; private EvalProcessControlMapper evalProcessControlMapper;
@Resource @Resource
private EvalProjectDocMapper evalProjectDocMapper; private EvalRiskParticipantMapper evalRiskParticipantMapper;
@Resource
private EvalProjectArchiveFileMapper evalProjectArchiveFileMapper;
@Resource @Resource
private EvalSignTaskMapper evalSignTaskMapper; private EvalSignTaskMapper evalSignTaskMapper;
@Resource @Resource
private EvalCustomerMapper evalCustomerMapper;
@Resource
private WpsDocQueryService wpsDocQueryService; private WpsDocQueryService wpsDocQueryService;
@Resource @Resource
private SafetyMessageGateway safetyMessageGateway; private SafetyMessageGateway safetyMessageGateway;
@ -370,7 +370,8 @@ public class EvalProcessControlExecutor implements EvalProcessControlApi {
projectStageSyncService.onArchived(projectId, cmd.getArchiveTransferorName(), cmd.getArchiveArchivistName()); projectStageSyncService.onArchived(projectId, cmd.getArchiveTransferorName(), cmd.getArchiveArchivistName());
// 写入项目预警记录(存在则更新,不存在则新增) // 写入项目预警记录(存在则更新,不存在则新增)
upsertProjectWaring(project); upsertProjectWaring(project);
// 归档项目资料:将所有项目文件以流程自动记录来源存入 eval_project_archive_file
saveAutoArchiveFiles(projectId, project);
projectStageSyncService.onNodeCompleted(projectId, ProjectStageEnum.ARCHIVE.getNode()); projectStageSyncService.onNodeCompleted(projectId, ProjectStageEnum.ARCHIVE.getNode());
return SingleResponse.success(evalProcessControlConvertor.toProcessCO(entity)); return SingleResponse.success(evalProcessControlConvertor.toProcessCO(entity));
} }
@ -381,6 +382,8 @@ public class EvalProcessControlExecutor implements EvalProcessControlApi {
Long orgId = project.getOrgId(); Long orgId = project.getOrgId();
List<EvalProjectFileCO> files = new java.util.ArrayList<>(); List<EvalProjectFileCO> files = new java.util.ArrayList<>();
// 风险分析/项目组-参与人签字eval_risk_participantrisk_id 非空为风险分析,为空为项目组)
files.addAll(listRiskParticipantFiles(projectId));
// 业务合同-合同扫描件 // 业务合同-合同扫描件
files.addAll(evalContractQueryService.listProjectFiles(projectId, orgId)); files.addAll(evalContractQueryService.listProjectFiles(projectId, orgId));
// 现场踏勘-附件 // 现场踏勘-附件
@ -528,63 +531,115 @@ public class EvalProcessControlExecutor implements EvalProcessControlApi {
} }
/** /**
* listProjectFiles ARCHIVED eval_project_doc.project_doc_url * listProjectFiles eval_project_archive_file
* materialType=ARCHIVED * record_source=auto_process_record
*/ */
private void upsertArchivedProjectDocs(Long projectId, EvalProjectEntity project) { private void saveAutoArchiveFiles(Long projectId, EvalProjectEntity project) {
List<EvalProjectFileCO> files = listProjectFiles(projectId).getData(); // 先删除该项目流程自动记录来源的旧档案文件,避免重复归档产生脏数据
// 将每个文件 projectDocUrl 中的 JSON 数组扁平化:数组内每个文件对象拆分为独立的资料条目 evalProjectArchiveFileMapper.delete(new LambdaQueryWrapper<EvalProjectArchiveFileDO>()
List<EvalProjectDocMaterialItemCO> archivedItems = new ArrayList<>(); .eq(EvalProjectArchiveFileDO::getProjectId, String.valueOf(projectId))
if (!CollectionUtils.isEmpty(files)) { .eq(EvalProjectArchiveFileDO::getRecordSource, ProjectArchiveFileSourceEnum.AUTO_PROCESS_RECORD.getCode()));
for (EvalProjectFileCO f : files) {
List<JSONObject> urlObjects = parseFileUrlObjects(f.getProjectDocUrl());
String itemName = f.getItemName();
for (JSONObject obj : urlObjects) {
EvalProjectDocMaterialItemCO item = new EvalProjectDocMaterialItemCO();
String name = obj.getStr("name");
String fName = StringUtils.hasText(name) ? CommonUtil.EMPTY : name;
item.setMaterialName(itemName + fName);
item.setProjectDocUrl(obj.getStr("url"));
item.setMaterialType(MaterialCategory.ARCHIVED.getMsg());
archivedItems.add(item);
}
}
}
EvalProjectDocDO docDO = evalProjectDocMapper.selectOne(new LambdaQueryWrapper<EvalProjectDocDO>() List<EvalProjectFileCO> files = listProjectFiles(projectId).getData();
.select(EvalProjectDocDO::getId, EvalProjectDocDO::getProjectDocUrl) if (CollectionUtils.isEmpty(files)) {
.eq(EvalProjectDocDO::getProjectId, projectId)); return;
if (docDO == null) {
EvalCustomerDO evalCustomerDO = evalCustomerMapper.selectOne(new LambdaQueryWrapper<EvalCustomerDO>()
.select(EvalCustomerDO::getCustomerName)
.eq(EvalCustomerDO::getId, project.getCustomerId()));
docDO = new EvalProjectDocDO();
docDO.setOrgId(project.getOrgId());
docDO.setProjectId(projectId);
docDO.setProjectNo(project.getProjectNo());
docDO.setCustomerName(evalCustomerDO.getCustomerName());
docDO.setProjectName(project.getProjectName());
docDO.setEvalTypeCode(project.getEvalTypeCode());
docDO.setProjectDocUrl(JSON.toJSONString(archivedItems));
docDO.setRemarks(MaterialCategory.ARCHIVED.getMsg());
InsertFieldDefaults.apply(docDO);
evalProjectDocMapper.insert(docDO);
} else {
List<EvalProjectDocMaterialItemCO> existing = new ArrayList<>();
if (StringUtils.hasText(docDO.getProjectDocUrl())) {
List<EvalProjectDocMaterialItemCO> parsed = JSONUtil.toList(docDO.getProjectDocUrl(), EvalProjectDocMaterialItemCO.class);
if (parsed != null) {
existing.addAll(parsed);
}
}
// 先移除原有 ARCHIVED 类型的资料,再追加本次归档的文件
String archivedVal = MaterialCategory.ARCHIVED.getVal();
existing.removeIf(item -> archivedVal.equals(item.getMaterialType()));
existing.addAll(archivedItems);
evalProjectDocMapper.update(new LambdaUpdateWrapper<EvalProjectDocDO>()
.eq(EvalProjectDocDO::getId, docDO.getId())
.set(EvalProjectDocDO::getProjectDocUrl, JSON.toJSONString(existing)));
} }
for (EvalProjectFileCO file : files) {
ProjectStageEnum stage = resolveStageByMsg(file.getProcessName());
for (JSONObject obj : parseFileUrlObjects(file.getProjectDocUrl())) {
if (!StringUtils.hasText(obj.getStr("url"))) {
continue;
}
evalProjectArchiveFileMapper.insert(buildArchiveFileDO(projectId, project, file, stage, obj));
}
}
}
/**
* archiveType ArchiveTypeEnumbusinessNode ProjectStageEnum
*/
private EvalProjectArchiveFileDO buildArchiveFileDO(Long projectId, EvalProjectEntity project,
EvalProjectFileCO file, ProjectStageEnum stage, JSONObject obj) {
String urlName = obj.getStr("name");
EvalProjectArchiveFileDO archiveFileDO = new EvalProjectArchiveFileDO();
archiveFileDO.setOrgId(project.getOrgId());
archiveFileDO.setProjectId(String.valueOf(projectId));
archiveFileDO.setFileUrl(obj.getStr("url"));
archiveFileDO.setFileName(StringUtils.hasText(urlName) ? urlName : file.getItemName());
archiveFileDO.setArchiveType(resolveArchiveType(stage).getCode());
archiveFileDO.setBusinessNode(stage != null ? stage.getVal() : file.getProcessName());
archiveFileDO.setRecordSource(ProjectArchiveFileSourceEnum.AUTO_PROCESS_RECORD.getCode());
InsertFieldDefaults.apply(archiveFileDO);
return archiveFileDO;
}
/**
* ProjectStageEnum.msg / null
*/
private ProjectStageEnum resolveStageByMsg(String processName) {
if (!StringUtils.hasText(processName)) {
return null;
}
for (ProjectStageEnum stage : ProjectStageEnum.values()) {
if (stage.getMsg().equals(processName)) {
return stage;
}
}
return null;
}
/**
*
* /
*
*/
private ArchiveTypeEnum resolveArchiveType(ProjectStageEnum stage) {
if (stage == null) {
return ArchiveTypeEnum.OTHER;
}
switch (stage) {
case RISK_ANALYSIS:
return ArchiveTypeEnum.RISK_ANALYSIS;
case BUSINESS_CONTRACT:
return ArchiveTypeEnum.TECH_SERVICE_CONTRACT;
case PROJECT_GROUP:
return ArchiveTypeEnum.PROJECT_ORG_FILE;
case SITE_SURVEY:
return ArchiveTypeEnum.SITE_SURVEY;
case REPORT_PREPARATION:
return ArchiveTypeEnum.EVALUATION_REPORT;
case INTERNAL_REVIEW:
case TECHNICAL_REVIEW:
return ArchiveTypeEnum.REVIEW_RECORD;
case PROCESS_CONTROL:
return ArchiveTypeEnum.PROCESS_CONTROL;
default:
return ArchiveTypeEnum.OTHER;
}
}
/**
* eval_risk_participant risk_id
*/
private List<EvalProjectFileCO> listRiskParticipantFiles(Long projectId) {
List<EvalProjectFileCO> files = new ArrayList<>();
List<EvalRiskParticipantDO> participants = evalRiskParticipantMapper.selectList(
new LambdaQueryWrapper<EvalRiskParticipantDO>()
.eq(EvalRiskParticipantDO::getProjectId, projectId)
.isNotNull(EvalRiskParticipantDO::getSignFileUrl));
if (CollectionUtils.isEmpty(participants)) {
return files;
}
for (EvalRiskParticipantDO participant : participants) {
ProjectStageEnum stage = participant.getRiskId() != null
? ProjectStageEnum.RISK_ANALYSIS : ProjectStageEnum.PROJECT_GROUP;
EvalProjectFileCO co = new EvalProjectFileCO();
co.setProcessName(stage.getMsg());
co.setItemName(stage.getMsg() + "签字");
co.setProjectDocUrl(participant.getSignFileUrl());
files.add(co);
}
return files;
} }
/** /**

View File

@ -5,6 +5,7 @@ import lombok.Data;
import org.qinan.safetyeval.domain.constant.ArchiveTypeEnum; import org.qinan.safetyeval.domain.constant.ArchiveTypeEnum;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Size;
import java.io.Serializable; import java.io.Serializable;
/** /**
@ -17,47 +18,34 @@ import java.io.Serializable;
public class EvalProjectArchiveFileAddCmd implements Serializable { public class EvalProjectArchiveFileAddCmd implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
/**
* ID
*/
@ApiModelProperty(value = "项目ID", required = true) @ApiModelProperty(value = "项目ID", required = true)
@NotBlank(message = "项目ID不能为空") @NotBlank(message = "项目ID不能为空")
private String projectId; private String projectId;
/**
*
*/
@ApiModelProperty(value = "文件地址", required = true) @ApiModelProperty(value = "文件地址", required = true)
@NotBlank(message = "文件地址不能为空") @NotBlank(message = "文件地址不能为空")
private String fileUrl; private String fileUrl;
/**
*
*/
@ApiModelProperty(value = "文件名称", required = true) @ApiModelProperty(value = "文件名称", required = true)
@NotBlank(message = "文件名称不能为空") @Size(max = 100, message = "文件名称长度不能超过100")
private String fileName; private String fileName;
/**
* ArchiveTypeEnum.REMARKS
*/
@ApiModelProperty(value = ArchiveTypeEnum.REMARKS, required = true) @ApiModelProperty(value = ArchiveTypeEnum.REMARKS, required = true)
@NotBlank(message = ArchiveTypeEnum.REMARKS + "不能为空") @NotBlank(message = ArchiveTypeEnum.REMARKS + "不能为空")
@Size(max = 100, message = "档案类型长度不能超过100")
private String archiveType; private String archiveType;
/**
*
*/
@ApiModelProperty(value = "业务节点", required = true) @ApiModelProperty(value = "业务节点", required = true)
@NotBlank(message = "业务节点不能为空") @NotBlank(message = "业务节点不能为空")
@Size(max = 32, message = "业务节点长度不能超过32")
private String businessNode; private String businessNode;
/**
* auto_process_recordupload_additional_files
*/
@ApiModelProperty(value = "来源 auto_process_record流程自动记录upload_additional_files 补充上传", required = true) @ApiModelProperty(value = "来源 auto_process_record流程自动记录upload_additional_files 补充上传", required = true)
@NotBlank(message = "来源 auto_process_record流程自动记录upload_additional_files 补充上传不能为空") @NotBlank(message = "来源 auto_process_record流程自动记录upload_additional_files 补充上传不能为空")
@Size(max = 32, message = "来源长度不能超过32")
private String recordSource; private String recordSource;
/**
*
*/
@ApiModelProperty(value = "环境")
private String env;
@ApiModelProperty(value = "备注")
@Size(max = 200, message = "备注长度不能超过200")
private String remarks;
} }

View File

@ -7,6 +7,7 @@ import org.qinan.safetyeval.domain.constant.ArchiveTypeEnum;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
import java.io.Serializable; import java.io.Serializable;
/** /**
@ -56,4 +57,8 @@ public class EvalProjectArchiveFileUpdateCmd implements Serializable {
@ApiModelProperty(value = "来源 auto_process_record流程自动记录upload_additional_files 补充上传", required = true) @ApiModelProperty(value = "来源 auto_process_record流程自动记录upload_additional_files 补充上传", required = true)
@NotBlank(message = "来源 auto_process_record流程自动记录upload_additional_files 补充上传不能为空") @NotBlank(message = "来源 auto_process_record流程自动记录upload_additional_files 补充上传不能为空")
private String recordSource; private String recordSource;
@ApiModelProperty(value = "备注")
@Size(max = 200, message = "备注长度不能超过200")
private String remarks;
} }

View File

@ -54,4 +54,7 @@ public class EvalProjectArchiveFileCo extends ClientObject {
@ApiModelProperty(value = "创建人") @ApiModelProperty(value = "创建人")
protected String createName; protected String createName;
@ApiModelProperty(value = "备注")
private String remarks;
} }