文件问题
This commit is contained in:
@@ -29,6 +29,9 @@ public class ContractLaunchFileDto implements Serializable {
|
||||
/** 文件路径(上传到法务系统后返回的 path,或本系统存储路径) */
|
||||
private String filePath;
|
||||
|
||||
/** 法务系统可用的附件路径(上传法务后缓存) */
|
||||
private String legalFileUrl;
|
||||
|
||||
/** 文件类型(docx/pdf 等) */
|
||||
private String fileType;
|
||||
|
||||
|
||||
@@ -78,6 +78,11 @@ public interface ContractLaunchMapper {
|
||||
@Param("fileCategory") String fileCategory,
|
||||
@Param("updateBy") String updateBy);
|
||||
|
||||
/** 回写法务附件路径缓存 */
|
||||
int updateFileLegalUrl(@Param("id") Long id,
|
||||
@Param("legalFileUrl") String legalFileUrl,
|
||||
@Param("updateBy") String updateBy);
|
||||
|
||||
/** 删除合同下的所有履行计划(逻辑删除) */
|
||||
int deletePlanByContractId(@Param("contractId") Long contractId,
|
||||
@Param("updateBy") String updateBy);
|
||||
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
package com.nbport.zgwl.contractlaunch.service;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchFileDto;
|
||||
import com.nbport.zgwl.contractlaunch.mapper.ContractLaunchMapper;
|
||||
import com.nbport.zgwl.contractpush.service.DataCollectionPushService;
|
||||
import com.nbport.zgwl.exception.ServiceException;
|
||||
import com.nbport.zgwl.service.LocalFileService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ContractLaunchLegalFileBridgeService {
|
||||
|
||||
private final DataCollectionPushService dataCollectionPushService;
|
||||
private final LocalFileService localFileService;
|
||||
private final ContractLaunchMapper contractLaunchMapper;
|
||||
|
||||
public String ensureLegalFilePath(ContractLaunchFileDto fileDto) {
|
||||
if (fileDto == null) {
|
||||
return null;
|
||||
}
|
||||
String cachedLegalPath = StrUtil.trim(fileDto.getLegalFileUrl());
|
||||
if (StrUtil.isNotBlank(cachedLegalPath)) {
|
||||
return cachedLegalPath;
|
||||
}
|
||||
String filePath = StrUtil.trim(fileDto.getFilePath());
|
||||
if (StrUtil.isBlank(filePath)) {
|
||||
return null;
|
||||
}
|
||||
if (isLegalRemotePath(filePath)) {
|
||||
return filePath;
|
||||
}
|
||||
byte[] bytes = localFileService.readFileBytes(filePath);
|
||||
Map<String, Object> uploadResult = dataCollectionPushService.upload(bytes, resolveFileName(fileDto), null);
|
||||
String legalPath = extractUploadedPath(uploadResult);
|
||||
if (StrUtil.isBlank(legalPath)) {
|
||||
throw new ServiceException("法务附件上传成功但未返回文件路径");
|
||||
}
|
||||
fileDto.setLegalFileUrl(legalPath);
|
||||
if (fileDto.getId() != null) {
|
||||
contractLaunchMapper.updateFileLegalUrl(fileDto.getId(), legalPath, "system");
|
||||
}
|
||||
return legalPath;
|
||||
}
|
||||
|
||||
public Map<String, Object> buildSettlementPayload(ContractLaunchFileDto fileDto) {
|
||||
String legalPath = ensureLegalFilePath(fileDto);
|
||||
if (StrUtil.isBlank(legalPath)) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("fileName", resolveFileName(fileDto));
|
||||
map.put("filePath", legalPath);
|
||||
map.put("fileSize", fileDto.getFileSize());
|
||||
map.put("fileType", resolveSuffix(fileDto));
|
||||
return map;
|
||||
}
|
||||
|
||||
public Map<String, Object> buildCollectionPayload(ContractLaunchFileDto fileDto) {
|
||||
String legalPath = ensureLegalFilePath(fileDto);
|
||||
if (StrUtil.isBlank(legalPath)) {
|
||||
return null;
|
||||
}
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("size", fileDto.getFileSize() == null ? "" : String.valueOf(fileDto.getFileSize()));
|
||||
map.put("name", resolveFileName(fileDto));
|
||||
map.put("suffix", resolveSuffix(fileDto));
|
||||
map.put("path", legalPath);
|
||||
return map;
|
||||
}
|
||||
|
||||
private String resolveFileName(ContractLaunchFileDto fileDto) {
|
||||
String fileName = StrUtil.trim(fileDto.getFileName());
|
||||
if (StrUtil.isNotBlank(fileName)) {
|
||||
return fileName;
|
||||
}
|
||||
throw new ServiceException("附件文件名不能为空");
|
||||
}
|
||||
|
||||
private String resolveSuffix(ContractLaunchFileDto fileDto) {
|
||||
String fileType = StrUtil.trim(fileDto.getFileType());
|
||||
if (StrUtil.isNotBlank(fileType)) {
|
||||
return fileType.startsWith(".") ? fileType.substring(1) : fileType;
|
||||
}
|
||||
String fileName = resolveFileName(fileDto);
|
||||
int index = fileName.lastIndexOf('.');
|
||||
return index >= 0 && index < fileName.length() - 1 ? fileName.substring(index + 1) : "";
|
||||
}
|
||||
|
||||
private boolean isLegalRemotePath(String filePath) {
|
||||
return filePath.startsWith("/cj/")
|
||||
|| filePath.startsWith("http://")
|
||||
|| filePath.startsWith("https://");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private String extractUploadedPath(Map<String, Object> uploadResult) {
|
||||
if (uploadResult == null || uploadResult.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
Object directData = uploadResult.get("data");
|
||||
if (directData instanceof String && StrUtil.isNotBlank((String) directData)) {
|
||||
return (String) directData;
|
||||
}
|
||||
if (directData instanceof Map) {
|
||||
Object nested = ((Map<String, Object>) directData).get("data");
|
||||
if (nested instanceof String && StrUtil.isNotBlank((String) nested)) {
|
||||
return (String) nested;
|
||||
}
|
||||
Object path = ((Map<String, Object>) directData).get("path");
|
||||
if (path instanceof String && StrUtil.isNotBlank((String) path)) {
|
||||
return (String) path;
|
||||
}
|
||||
}
|
||||
Object result = uploadResult.get("result");
|
||||
if (result instanceof String && StrUtil.isNotBlank((String) result)) {
|
||||
return (String) result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+37
-12
@@ -12,6 +12,7 @@ import com.nbport.zgwl.contractlaunch.dto.ContractLaunchPartyDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchPlanDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchQueryDto;
|
||||
import com.nbport.zgwl.contractlaunch.dto.ContractLaunchSealDto;
|
||||
import com.nbport.zgwl.contractlaunch.service.ContractLaunchLegalFileBridgeService;
|
||||
import com.nbport.zgwl.contractlaunch.mapper.ContractLaunchMapper;
|
||||
import com.nbport.zgwl.contractlaunch.utils.ContractLaunchCodeUtils;
|
||||
import com.nbport.zgwl.contractlaunch.utils.ContractLaunchConstants;
|
||||
@@ -50,6 +51,7 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
private final AdminSecurityManage adminSecurityManage;
|
||||
private final SettlementPushService settlementPushService;
|
||||
private final DataCollectionPushService dataCollectionPushService;
|
||||
private final ContractLaunchLegalFileBridgeService legalFileBridgeService;
|
||||
|
||||
/** 分页查询,附带合同方/文件/履行计划(列表页不查日志) */
|
||||
@Override
|
||||
@@ -1088,9 +1090,9 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
map.put("planSubjectName", plan.getPlanSubjectName());
|
||||
return map;
|
||||
}).collect(Collectors.toList()));
|
||||
payload.put("contractText", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_BODY));
|
||||
payload.put("otherAttach", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_OTHER));
|
||||
payload.put("contractGistFile", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_GIST));
|
||||
payload.put("contractText", buildSettlementFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_BODY));
|
||||
payload.put("otherAttach", buildSettlementFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_OTHER));
|
||||
payload.put("contractGistFile", buildSettlementFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_GIST));
|
||||
return payload;
|
||||
}
|
||||
|
||||
@@ -1122,9 +1124,9 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
payload.put("c_creator", contract.getInitiator());
|
||||
payload.put("c_creatorPhone", contract.getCreatorPhone());
|
||||
payload.put("c_createDept", contract.getInitiatorDept());
|
||||
payload.put("c_zw", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_BODY));
|
||||
payload.put("c_attachs", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_OTHER));
|
||||
payload.put("c_signAttachs", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_SIGNED));
|
||||
payload.put("c_zw", buildCollectionFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_BODY));
|
||||
payload.put("c_attachs", buildCollectionFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_OTHER));
|
||||
payload.put("c_signAttachs", buildCollectionFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_GIST));
|
||||
payload.put("c_lxPlan", contract.getPerformancePlans());
|
||||
Map<String, Object> seal = new LinkedHashMap<>();
|
||||
seal.put("seal_isSeal", "1");
|
||||
@@ -1136,7 +1138,7 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
sign.put("sign_isSign", "1");
|
||||
sign.put("sign_date", contract.getSignDate());
|
||||
sign.put("sign_activeDate", contract.getActiveDate());
|
||||
sign.put("sign_attachs", buildFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_SIGNED));
|
||||
sign.put("sign_attachs", buildCollectionFilePayloadList(contract, ContractLaunchConstants.FILE_CATEGORY_SIGNED));
|
||||
sign.put("sign_executor", contract.getExecutorAccount());
|
||||
payload.put("c_sign", sign);
|
||||
return payload;
|
||||
@@ -1151,22 +1153,45 @@ public class ContractLaunchServiceImpl implements ContractLaunchService {
|
||||
payload.put("KeeperUnit", archiveDto == null ? null : archiveDto.getArchiveKeeperUnit());
|
||||
payload.put("KeeperUnitCode", archiveDto == null ? null : archiveDto.getArchiveKeeperUnitCode());
|
||||
payload.put("archivePapers", List.of());
|
||||
payload.put("archiveEles", (archiveDto == null || archiveDto.getArchiveFiles() == null) ? List.of() : archiveDto.getArchiveFiles());
|
||||
payload.put("archiveEles", buildSettlementArchiveEleList(archiveDto));
|
||||
return payload;
|
||||
}
|
||||
|
||||
/** 按 fileCategory 提取文件列表,转为法务接口要求的附件格式 */
|
||||
private List<Map<String, Object>> buildFilePayloadList(ContractLaunchDto contract, String fileCategory) {
|
||||
private List<Map<String, Object>> buildSettlementFilePayloadList(ContractLaunchDto contract, String fileCategory) {
|
||||
return contract.getFileList().stream()
|
||||
.filter(item -> fileCategory.equals(item.getFileCategory()))
|
||||
.map(item -> {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("fileName", item.getFileName());
|
||||
map.put("filePath", item.getFilePath());
|
||||
map.put("filePath", legalFileBridgeService.ensureLegalFilePath(item));
|
||||
map.put("fileSize", item.getFileSize());
|
||||
map.put("fileType", item.getFileType());
|
||||
return map;
|
||||
}).collect(Collectors.toList());
|
||||
})
|
||||
.filter(item -> item.get("filePath") != null)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> buildCollectionFilePayloadList(ContractLaunchDto contract, String fileCategory) {
|
||||
return contract.getFileList().stream()
|
||||
.filter(item -> fileCategory.equals(item.getFileCategory()))
|
||||
.map(item -> legalFileBridgeService.buildCollectionPayload(item))
|
||||
.filter(item -> item != null && item.get("path") != null)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> buildSettlementArchiveEleList(ContractLaunchArchiveDto archiveDto) {
|
||||
if (archiveDto == null || archiveDto.getArchiveFiles() == null || archiveDto.getArchiveFiles().isEmpty()) {
|
||||
return List.of();
|
||||
}
|
||||
return archiveDto.getArchiveFiles().stream()
|
||||
.map(item -> {
|
||||
Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("archivesName", item.getFileName());
|
||||
map.put("approvalAttachs", List.of(legalFileBridgeService.buildSettlementPayload(item)));
|
||||
return map;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private String trim(String value) {
|
||||
|
||||
@@ -60,6 +60,15 @@ public class DataCollectionPushService {
|
||||
return httpUtils.postMultipart(properties.getDataCollection().getUploadUrl(), file, headers);
|
||||
}
|
||||
|
||||
public Map<String, Object> upload(byte[] bytes, String originalFileName, String token) {
|
||||
Map<String, String> headers = requestHandler.buildDataCollectionHeaders(
|
||||
resolveCollectionToken(token),
|
||||
properties.getDataCollection().getSystemKey(),
|
||||
true
|
||||
);
|
||||
return httpUtils.postMultipart(properties.getDataCollection().getUploadUrl(), bytes, originalFileName, headers);
|
||||
}
|
||||
|
||||
/** 相对方信息采集:将相对方信息推送给法务系统 */
|
||||
public Map<String, Object> collectOpposites(PushPayloadDTO requestDTO) {
|
||||
return postCollectionJson(properties.getDataCollection().getCollectOppositesUrl(), requestDTO, false);
|
||||
|
||||
@@ -68,6 +68,26 @@ public class ContractPushHttpUtils {
|
||||
return parseResponse(response.getBody());
|
||||
}
|
||||
|
||||
public Map<String, Object> postMultipart(String url, byte[] fileBytes, String originalFilename, Map<String, String> headers) {
|
||||
if (fileBytes == null || fileBytes.length == 0) {
|
||||
throw new ServiceException("上传文件不能为空");
|
||||
}
|
||||
if (originalFilename == null || originalFilename.trim().isEmpty()) {
|
||||
throw new ServiceException("上传文件名不能为空");
|
||||
}
|
||||
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
|
||||
addHeaders(httpHeaders, headers);
|
||||
|
||||
MultiValueMap<String, Object> formData = new LinkedMultiValueMap<>();
|
||||
formData.add("file", toByteArrayResource(fileBytes, originalFilename));
|
||||
|
||||
HttpEntity<MultiValueMap<String, Object>> entity = new HttpEntity<>(formData, httpHeaders);
|
||||
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, entity, String.class);
|
||||
return parseResponse(response.getBody());
|
||||
}
|
||||
|
||||
/** 将 MultipartFile 转为 ByteArrayResource(保留原始文件名) */
|
||||
private ByteArrayResource toByteArrayResource(MultipartFile file) {
|
||||
try {
|
||||
@@ -82,6 +102,15 @@ public class ContractPushHttpUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private ByteArrayResource toByteArrayResource(byte[] bytes, String originalFilename) {
|
||||
return new ByteArrayResource(bytes) {
|
||||
@Override
|
||||
public String getFilename() {
|
||||
return originalFilename;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void addHeaders(HttpHeaders httpHeaders, Map<String, String> headers) {
|
||||
if (headers == null || headers.isEmpty()) {
|
||||
return;
|
||||
|
||||
@@ -78,4 +78,18 @@ public class LocalFileService {
|
||||
throw new ServiceException("文件下载失败");
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] readFileBytes(String fileName) {
|
||||
try {
|
||||
Path rootPath = Paths.get(localPath).toAbsolutePath().normalize();
|
||||
Path filePath = FileStorageUtils.resolveFilePath(rootPath, fileName);
|
||||
if (!Files.exists(filePath) || Files.isDirectory(filePath)) {
|
||||
throw new ServiceException(ServiceErrorCodeRange.FILE_NOT_FOUND, "文件不存在");
|
||||
}
|
||||
return Files.readAllBytes(filePath);
|
||||
} catch (IOException e) {
|
||||
log.error("文件读取失败", e);
|
||||
throw new ServiceException("文件读取失败");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@
|
||||
<result property="fileCategory" column="FILE_CATEGORY"/>
|
||||
<result property="fileName" column="FILE_NAME"/>
|
||||
<result property="filePath" column="FILE_PATH"/>
|
||||
<result property="legalFileUrl" column="LEGAL_FILE_URL"/>
|
||||
<result property="fileType" column="FILE_TYPE"/>
|
||||
<result property="fileSize" column="FILE_SIZE"/>
|
||||
<result property="sortOrder" column="SORT_ORDER"/>
|
||||
@@ -411,10 +412,10 @@
|
||||
INSERT ALL
|
||||
<foreach collection="list" item="item">
|
||||
INTO SEAL_CONTRACT_LAUNCH_FILE (
|
||||
ID, CONTRACT_ID, FILE_CATEGORY, FILE_NAME, FILE_PATH, FILE_TYPE, FILE_SIZE,
|
||||
ID, CONTRACT_ID, FILE_CATEGORY, FILE_NAME, FILE_PATH, LEGAL_FILE_URL, FILE_TYPE, FILE_SIZE,
|
||||
SORT_ORDER, CREATE_BY, CREATE_TIME, UPDATE_BY, UPDATE_TIME, IS_DELETED, REMARK
|
||||
) VALUES (
|
||||
#{item.id}, #{item.contractId}, #{item.fileCategory}, #{item.fileName}, #{item.filePath}, #{item.fileType}, #{item.fileSize},
|
||||
#{item.id}, #{item.contractId}, #{item.fileCategory}, #{item.fileName}, #{item.filePath}, #{item.legalFileUrl}, #{item.fileType}, #{item.fileSize},
|
||||
#{item.sortOrder}, #{createBy}, SYSDATE, #{updateBy}, SYSDATE, 'N', #{item.remark}
|
||||
)
|
||||
</foreach>
|
||||
@@ -471,7 +472,16 @@
|
||||
UPDATE_BY = #{updateBy},
|
||||
UPDATE_TIME = SYSDATE
|
||||
where CONTRACT_ID = #{contractId}
|
||||
and FILE_CATEGORY = #{fileCategory}
|
||||
and FILE_CATEGORY = #{fileCategory}
|
||||
and IS_DELETED = 'N'
|
||||
</update>
|
||||
|
||||
<update id="updateFileLegalUrl">
|
||||
update SEAL_CONTRACT_LAUNCH_FILE
|
||||
set LEGAL_FILE_URL = #{legalFileUrl},
|
||||
UPDATE_BY = #{updateBy},
|
||||
UPDATE_TIME = SYSDATE
|
||||
where ID = #{id}
|
||||
and IS_DELETED = 'N'
|
||||
</update>
|
||||
|
||||
@@ -500,7 +510,7 @@
|
||||
</select>
|
||||
|
||||
<select id="selectFileByContractIds" resultMap="FileResult">
|
||||
select ID, CONTRACT_ID, FILE_CATEGORY, FILE_NAME, FILE_PATH, FILE_TYPE, FILE_SIZE, SORT_ORDER, REMARK
|
||||
select ID, CONTRACT_ID, FILE_CATEGORY, FILE_NAME, FILE_PATH, LEGAL_FILE_URL, FILE_TYPE, FILE_SIZE, SORT_ORDER, REMARK
|
||||
from SEAL_CONTRACT_LAUNCH_FILE
|
||||
where IS_DELETED = 'N'
|
||||
and CONTRACT_ID in
|
||||
|
||||
Reference in New Issue
Block a user