外协人员批量上传附件优化
This commit is contained in:
576
SQL/202511/20251121/lc_confined_space_operation.sql
Normal file
576
SQL/202511/20251121/lc_confined_space_operation.sql
Normal file
File diff suppressed because one or more lines are too long
631
SQL/202511/20251121/lc_high_operation.sql
Normal file
631
SQL/202511/20251121/lc_high_operation.sql
Normal file
File diff suppressed because one or more lines are too long
291
SQL/202511/20251121/lc_item_result.sql
Normal file
291
SQL/202511/20251121/lc_item_result.sql
Normal file
File diff suppressed because one or more lines are too long
510
SQL/202511/20251121/lc_land_operation.sql
Normal file
510
SQL/202511/20251121/lc_land_operation.sql
Normal file
File diff suppressed because one or more lines are too long
543
SQL/202511/20251121/lc_lifting_operation.sql
Normal file
543
SQL/202511/20251121/lc_lifting_operation.sql
Normal file
File diff suppressed because one or more lines are too long
858
SQL/202511/20251121/lc_outside_person.sql
Normal file
858
SQL/202511/20251121/lc_outside_person.sql
Normal file
File diff suppressed because one or more lines are too long
532
SQL/202511/20251121/lc_temporary_power_operation.sql
Normal file
532
SQL/202511/20251121/lc_temporary_power_operation.sql
Normal file
File diff suppressed because one or more lines are too long
@@ -29,6 +29,8 @@ import javax.annotation.Resource;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
@@ -100,138 +102,6 @@ public class OutSidePersonController extends BaseController {
|
||||
return sqlService.getDataOneByPlus(wrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据压缩文件地址下载、解压文件,并根据文件名(身份证号)更新数据库
|
||||
*
|
||||
* 功能说明:
|
||||
* 1. 根据文件地址(支持URL或本地路径)下载/读取压缩文件
|
||||
* 2. 解压缩文件(支持zip、rar、7z格式),得到文件列表
|
||||
* 3. 遍历文件列表,每个文件的文件名作为身份证号
|
||||
* 4. 根据身份证号查询lc_risk_hazard_manage表的cardID字段
|
||||
* 5. 如果匹配到数据,将文件上传到服务器指定目录
|
||||
* 6. 更新lc_risk_hazard_manage表的actual_corrective_Attachment字段为文件地址
|
||||
*
|
||||
* 使用示例:
|
||||
* <pre>
|
||||
* // 方式1:使用MyBatis Mapper
|
||||
* @Autowired
|
||||
* private RiskHazardManageMapper mapper;
|
||||
*
|
||||
* String fileUrl = "http://example.com/files.zip";
|
||||
* String uploadPath = "/data/uploads";
|
||||
* int count = FileUtil.processCompressedFileByCardId(fileUrl, uploadPath, mapper);
|
||||
*
|
||||
* // 方式2:使用JPA Repository(需要实现接口)
|
||||
* RiskHazardManageMapper mapper = new RiskHazardManageMapper() {
|
||||
* @Autowired
|
||||
* private RiskHazardManageRepository repository;
|
||||
*
|
||||
* public RiskHazardManage findByCardId(String cardId) {
|
||||
* return repository.findByCardId(cardId);
|
||||
* }
|
||||
*
|
||||
* public void updateActualCorrectiveAttachment(String cardId, String fileUrl) {
|
||||
* RiskHazardManage entity = repository.findByCardId(cardId);
|
||||
* if (entity != null) {
|
||||
* entity.setActualCorrectiveAttachment(fileUrl);
|
||||
* repository.save(entity);
|
||||
* }
|
||||
* }
|
||||
* };
|
||||
* </pre>
|
||||
*
|
||||
* @param fileUrl 压缩文件的地址(可以是URL如"http://example.com/file.zip"或本地路径如"/path/to/file.zip")
|
||||
* @return 处理结果:成功处理的文件数量
|
||||
* @throws IOException IO异常
|
||||
*/
|
||||
public int processCompressedFileByCardId( @RequestBody JSONObject jsonObject) throws IOException {
|
||||
String fileUrl=jsonObject.get("commitmentAttchment").toString();
|
||||
if(fileUrl.isEmpty()){
|
||||
return 0;
|
||||
}
|
||||
|
||||
int successCount = 0;
|
||||
File tempZipFile = null;
|
||||
File tempDir = null;
|
||||
|
||||
String tableName = "lc_outside_person";
|
||||
Long detailFormId = dbFormService.getDbFormIdByTableName(tableName);
|
||||
|
||||
try {
|
||||
// 1. 下载文件(如果是URL)或直接使用本地文件
|
||||
if (fileUrl.startsWith("http://") || fileUrl.startsWith("https://")) {
|
||||
// 从URL下载文件
|
||||
tempZipFile = FileUtil.downloadFileFromUrl(fileUrl);
|
||||
} else {
|
||||
// 本地文件路径
|
||||
tempZipFile = new File(fileUrl);
|
||||
if (!tempZipFile.exists()) {
|
||||
throw new FileNotFoundException("文件不存在: " + fileUrl);
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 创建临时解压目录
|
||||
String tempDirPath = System.getProperty("java.io.tmpdir") + File.separator +
|
||||
"unzip_" + System.currentTimeMillis();
|
||||
tempDir = new File(tempDirPath);
|
||||
if (!tempDir.exists()) {
|
||||
tempDir.mkdirs();
|
||||
}
|
||||
|
||||
// 3. 解压缩文件
|
||||
List<File> fileList = FileUtil.unzipFile(tempZipFile, tempDir);
|
||||
log.info("解压文件成功,共 {} 个文件", fileList.size());
|
||||
|
||||
List<JSONObject> editDataList = new ArrayList<>();
|
||||
// 4. 遍历文件列表,处理每个文件
|
||||
for (File file : fileList) {
|
||||
try {
|
||||
// 4.1 获取文件名(身份证号),去掉扩展名
|
||||
String fileName = file.getName();
|
||||
String cardId = fileName;
|
||||
// 如果文件名包含扩展名,去掉扩展名
|
||||
int lastDotIndex = fileName.lastIndexOf('.');
|
||||
if (lastDotIndex > 0) {
|
||||
cardId = fileName.substring(0, lastDotIndex);
|
||||
}
|
||||
|
||||
// 4.2 根据身份证号查询数据库
|
||||
Map<String, Object> entity = getOutSideByCardNo(cardId);
|
||||
if (entity.isEmpty()) {
|
||||
log.warn("未找到身份证号对应的记录: {}", cardId);
|
||||
continue;
|
||||
}
|
||||
|
||||
// 4.3 上传文件到服务器
|
||||
String uploadPath = uploadFile(file);
|
||||
entity.put("commitmentAttchment", uploadPath);
|
||||
|
||||
editDataList.add(JSONUtil.parseObj(entity));
|
||||
log.info("处理成功 - 身份证号: {}, 文件: {}", cardId, uploadPath);
|
||||
successCount++;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("处理文件失败: {}", file.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新数据
|
||||
super.editJsonData(detailFormId, editDataList);
|
||||
|
||||
} finally {
|
||||
// 清理临时文件
|
||||
if (tempZipFile != null && tempZipFile.exists() &&
|
||||
(fileUrl.startsWith("http://") || fileUrl.startsWith("https://"))) {
|
||||
tempZipFile.delete();
|
||||
}
|
||||
if (tempDir != null && tempDir.exists()) {
|
||||
FileUtil.deleteDirectory(tempDir);
|
||||
}
|
||||
}
|
||||
|
||||
return successCount;
|
||||
}
|
||||
|
||||
public String uploadFile(File file) throws Exception {
|
||||
String fileName = file.getName();
|
||||
//微信图片_20230905094700.png
|
||||
@@ -310,8 +180,10 @@ public class OutSidePersonController extends BaseController {
|
||||
jsonObject.get("commitmentAttchment").toString() : "";
|
||||
String secretFileUrl = jsonObject.get("secretAttchment") != null ?
|
||||
jsonObject.get("secretAttchment").toString() : "";
|
||||
String noCriminalFileUrl = jsonObject.get("noCriminalAttachment") != null ?
|
||||
jsonObject.get("noCriminalAttachment").toString() : "";
|
||||
|
||||
if (commitmentFileUrl.isEmpty() && secretFileUrl.isEmpty()) {
|
||||
if (commitmentFileUrl.isEmpty() && secretFileUrl.isEmpty() && noCriminalFileUrl.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -324,12 +196,17 @@ public class OutSidePersonController extends BaseController {
|
||||
|
||||
// 处理 commitmentAttchment 压缩包
|
||||
if (!commitmentFileUrl.isEmpty()) {
|
||||
processCompressedFile(commitmentFileUrl, "commitmentAttchment", updateDataMap);
|
||||
processCompressedFile(commitmentFileUrl, "commitmentAttchment", "isSignSafe", updateDataMap);
|
||||
}
|
||||
|
||||
// 处理 secretAttchment 压缩包
|
||||
if (!secretFileUrl.isEmpty()) {
|
||||
processCompressedFile(secretFileUrl, "secretAttchment", updateDataMap);
|
||||
processCompressedFile(secretFileUrl, "secretAttchment", "isSignSecret", updateDataMap);
|
||||
}
|
||||
|
||||
// 处理 noCriminalAttachment 压缩包
|
||||
if (!noCriminalFileUrl.isEmpty()) {
|
||||
processCompressedFile(noCriminalFileUrl, "noCriminalAttachment", "isGovExxplain", updateDataMap);
|
||||
}
|
||||
|
||||
// 将Map转换为List,用于批量更新
|
||||
@@ -347,10 +224,11 @@ public class OutSidePersonController extends BaseController {
|
||||
/**
|
||||
* 处理压缩文件的通用方法
|
||||
* @param fileUrl 压缩文件地址
|
||||
* @param fieldName 要更新的字段名(commitmentAttchment 或 secretAttchment)
|
||||
* @param fieldName 要更新的字段名(commitmentAttchment / secretAttchment / noCriminalAttachment)
|
||||
* @param statusFieldName 要同步的状态字段(isSignSafe / isSignSecret / isGovExxplain)
|
||||
* @param updateDataMap 用于存储更新数据的Map,key为身份证号
|
||||
*/
|
||||
private void processCompressedFile(String fileUrl, String fieldName,
|
||||
private void processCompressedFile(String fileUrl, String fieldName, String statusFieldName,
|
||||
Map<String, JSONObject> updateDataMap) {
|
||||
File tempZipFile = null;
|
||||
File tempDir = null;
|
||||
@@ -358,8 +236,9 @@ public class OutSidePersonController extends BaseController {
|
||||
try {
|
||||
// 1. 下载文件(如果是URL)或直接使用本地文件
|
||||
if (fileUrl.startsWith("http://") || fileUrl.startsWith("https://")) {
|
||||
// 从URL下载文件
|
||||
tempZipFile = FileUtil.downloadFileFromUrl(fileUrl);
|
||||
// 从URL下载文件(先编码路径,避免中文/特殊字符导致 400)
|
||||
String encodedUrl = encodeUrl(fileUrl);
|
||||
tempZipFile = FileUtil.downloadFileFromUrl(encodedUrl);
|
||||
} else {
|
||||
// 本地文件路径
|
||||
tempZipFile = new File(fileUrl);
|
||||
@@ -413,8 +292,18 @@ public class OutSidePersonController extends BaseController {
|
||||
updateDataMap.put(cardIdKey, updateData);
|
||||
}
|
||||
|
||||
// 更新对应的字段
|
||||
updateData.put(fieldName, uploadPath);
|
||||
// 更新对应的字段(追加路径)
|
||||
String targetFieldKey = getCaseInsensitiveKey(updateData, fieldName);
|
||||
String existPath = updateData.getStr(targetFieldKey);
|
||||
if (existPath == null || existPath.isEmpty()) {
|
||||
updateData.set(targetFieldKey, uploadPath);
|
||||
} else {
|
||||
updateData.set(targetFieldKey, existPath + "," + uploadPath);
|
||||
}
|
||||
|
||||
if (statusFieldName != null && !statusFieldName.isEmpty()) {
|
||||
updateData.set(statusFieldName, "是");
|
||||
}
|
||||
|
||||
log.info("处理成功 [{}] - 身份证号: {}, 文件: {}", fieldName, cardId, uploadPath);
|
||||
|
||||
@@ -436,4 +325,29 @@ public class OutSidePersonController extends BaseController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String encodeUrl(String rawUrl) {
|
||||
try {
|
||||
URL url = new URL(rawUrl);
|
||||
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(),
|
||||
url.getPath(), url.getQuery(), url.getRef());
|
||||
return uri.toASCIIString();
|
||||
} catch (Exception e) {
|
||||
log.warn("URL 编码失败,使用原始地址: {}", rawUrl, e);
|
||||
return rawUrl;
|
||||
}
|
||||
}
|
||||
|
||||
private String getCaseInsensitiveKey(JSONObject jsonObject, String key) {
|
||||
if (jsonObject.containsKey(key)) {
|
||||
return key;
|
||||
}
|
||||
for (String existingKey : jsonObject.keySet()) {
|
||||
if (existingKey != null && existingKey.equalsIgnoreCase(key)) {
|
||||
return existingKey;
|
||||
}
|
||||
}
|
||||
// 默认返回原 key,保证 put 时能插入
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,14 +65,15 @@ public class RiskHazardController extends BaseController {
|
||||
@GetMapping({"/syncData2RiskHazard"})
|
||||
@ApiOperationSupport(order = 1)
|
||||
@Operation(summary = "同步数据")
|
||||
public void SyncData2RiskHazard()
|
||||
{
|
||||
public void SyncData2RiskHazard() {
|
||||
|
||||
// 报表 code
|
||||
String reportCode="ali_risk_data";
|
||||
String syncTableName="lc_report_data_sync";
|
||||
String syncDetailTableName="lc_report_data_sync_detail";
|
||||
String riskTableName="lc_risk_hazard_manage";
|
||||
String campusTableName="campus_info";
|
||||
String reportCode = "ali_risk_data";
|
||||
String syncTableName = "lc_report_data_sync";
|
||||
String syncDetailTableName = "lc_report_data_sync_detail";
|
||||
String riskTableName = "lc_risk_hazard_manage";
|
||||
String campusTableName = "campus_info";
|
||||
|
||||
Long dbFormId = formService.getDbFormIdByTableName(syncTableName);
|
||||
Long detailFormId = formService.getDbFormIdByTableName(syncDetailTableName);
|
||||
Long riskFormId = formService.getDbFormIdByTableName(riskTableName);
|
||||
@@ -88,45 +89,65 @@ public class RiskHazardController extends BaseController {
|
||||
Map<String, Object> param3 = new HashMap<>();
|
||||
ResultDataModel allCampus = super.getDataPage(campusFormId, param3);
|
||||
|
||||
if (CollectionUtil.isNotEmpty(unSyncs.getRecords()))
|
||||
{
|
||||
List<JSONObject> syncList = new ArrayList<>();
|
||||
List<JSONObject> syncDetailList = new ArrayList<>();
|
||||
// 可选优化:提前把 campus 列表转成 Map<campus_id, campus_name>,避免每次 stream 过滤
|
||||
Map<String, Object> campusMap = new HashMap<>();
|
||||
if (CollectionUtil.isNotEmpty(allCampus.getRecords())) {
|
||||
for (Map<String, Object> campus : allCampus.getRecords()) {
|
||||
Object campusIdObj = campus.get("campus_id");
|
||||
if (campusIdObj != null) {
|
||||
campusMap.put(campusIdObj.toString(), campus.get("campus_name"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CollectionUtil.isNotEmpty(unSyncs.getRecords())) {
|
||||
|
||||
List<JSONObject> syncList = new ArrayList<>(); // 主表需要更新的记录
|
||||
List<JSONObject> syncDetailList = new ArrayList<>(); // 明细表需要更新的记录
|
||||
|
||||
for (Map<String, Object> unSync : unSyncs.getRecords()) {
|
||||
|
||||
// 根据 同步表主表Id 获取所有未同步的明细表数据
|
||||
Map<String, Object> param2 = new HashMap<>();
|
||||
param2.put("syncId", unSync.get("id"));
|
||||
param2.put("isSync", 0);
|
||||
|
||||
ResultDataModel unSyncDetails = super.getDataPage(detailFormId, param2);
|
||||
if(CollectionUtil.isNotEmpty(unSyncDetails.getRecords())) {
|
||||
List<JSONObject> newRisks=new ArrayList<>();
|
||||
|
||||
if (CollectionUtil.isNotEmpty(unSyncDetails.getRecords())) {
|
||||
|
||||
// 新增和更新分开两个 list
|
||||
List<JSONObject> riskInsertList = new ArrayList<>();
|
||||
List<JSONObject> riskUpdateList = new ArrayList<>();
|
||||
|
||||
for (Map<String, Object> data : unSyncDetails.getRecords()) {
|
||||
Object result = data.get("resultData");
|
||||
JSONObject sourceData = result instanceof JSONObject
|
||||
? (JSONObject) result
|
||||
: JSONUtil.parseObj(String.valueOf(result));
|
||||
|
||||
// 取 sourceid 作为唯一标识
|
||||
String sourceId = Func.getMap2Str(sourceData, "sourceid");
|
||||
|
||||
// 生成 风险隐患表数据
|
||||
HashMap<String, Object> newRisk = new HashMap<>();
|
||||
newRisk.put("sync_Id", data.get("id"));
|
||||
newRisk.put("source_Id", sourceData.get("sourceid"));
|
||||
newRisk.put("source_Id", sourceId);
|
||||
newRisk.put("billNo", sourceData.get("work_order_id"));
|
||||
newRisk.put("source", 2); //来源 默认线上
|
||||
newRisk.put("source", 2); // 来源 默认线上
|
||||
newRisk.put("company_name", sourceData.get("company_name"));
|
||||
newRisk.put("company_id", sourceData.get("company_id"));
|
||||
|
||||
|
||||
newRisk.put("parkId", sourceData.get("campus_id"));
|
||||
// 设置 园区名称
|
||||
if(sourceData.containsKey("campus_id")) {
|
||||
|
||||
// 设置 园区名称(使用预构建的 campusMap)
|
||||
if (sourceData.containsKey("campus_id")) {
|
||||
String campusId = Func.getMap2Str(sourceData, "campus_id");
|
||||
// 根据name查找id
|
||||
Map<String, Object> depMap = allCampus.getRecords().stream()
|
||||
.filter(t -> t.get("campus_id").toString()
|
||||
.equals(campusId)).findFirst().orElse(null);
|
||||
if (Objects.nonNull(depMap)) {
|
||||
newRisk.put("parkName", depMap.get("campus_name"));
|
||||
Object campusName = campusMap.get(campusId);
|
||||
if (Objects.nonNull(campusName)) {
|
||||
newRisk.put("parkName", campusName);
|
||||
}
|
||||
}
|
||||
|
||||
//newRisk.put("check_area", sourceData.get("check_area"));
|
||||
//newRisk.put("check_item", sourceData.get("check_item"));
|
||||
newRisk.put("check_content", sourceData.get("item_name"));
|
||||
@@ -140,25 +161,50 @@ public class RiskHazardController extends BaseController {
|
||||
newRisk.put("corrective_confirm_people", sourceData.get("confirm_person_name"));
|
||||
newRisk.put("remarks", sourceData.get("remark"));
|
||||
|
||||
newRisks.add(JSONUtil.parseObj(newRisk));
|
||||
// 更新明细表为已同步
|
||||
// ======= 关键逻辑:根据 source_Id 先查 lc_risk_hazard_manage,存在则更新,不存在则插入 =======
|
||||
|
||||
Map<String, Object> riskQueryParam = new HashMap<>();
|
||||
riskQueryParam.put("source_Id", sourceId);
|
||||
ResultDataModel existRisk = super.getDataPage(riskFormId, riskQueryParam);
|
||||
|
||||
if (CollectionUtil.isNotEmpty(existRisk.getRecords())) {
|
||||
// 已存在记录:取第一条记录的 id,放入 newRisk,加入更新列表
|
||||
Map<String, Object> exist = existRisk.getRecords().get(0);
|
||||
newRisk.put("id", exist.get("id"));
|
||||
riskUpdateList.add(JSONUtil.parseObj(newRisk));
|
||||
} else {
|
||||
// 不存在:加入新增列表
|
||||
riskInsertList.add(JSONUtil.parseObj(newRisk));
|
||||
}
|
||||
|
||||
// ======= 同步明细表状态:置为已同步 =======
|
||||
data.put("isSync", 1);
|
||||
syncDetailList.add(JSONUtil.parseObj(data));
|
||||
}
|
||||
// 插入新的 风险隐患数据
|
||||
super.addJsonData(riskFormId,newRisks);
|
||||
|
||||
// 批量插入新的 风险隐患数据
|
||||
if (CollectionUtil.isNotEmpty(riskInsertList)) {
|
||||
super.addJsonData(riskFormId, riskInsertList);
|
||||
}
|
||||
|
||||
// 批量更新已存在的 风险隐患数据
|
||||
if (CollectionUtil.isNotEmpty(riskUpdateList)) {
|
||||
super.editJsonData(riskFormId, riskUpdateList);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新主表为已同步
|
||||
unSync.put("isSync", 1);
|
||||
syncList.add(JSONUtil.parseObj(unSync));
|
||||
}
|
||||
|
||||
// 更新同步数据表和同步数据明细表
|
||||
// 批量更新同步主表和明细表
|
||||
if (CollectionUtil.isNotEmpty(syncDetailList)) {
|
||||
super.editJsonData(detailFormId, syncDetailList);
|
||||
}
|
||||
// 更新同步数据表和同步数据明细表
|
||||
if (CollectionUtil.isNotEmpty(syncList)) {
|
||||
super.editJsonData(dbFormId, syncList);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
|
||||
package com.jeelowcode.module.biz.service;
|
||||
|
||||
import com.jeelowcode.tool.framework.datapermission.core.annotation.DataPermission;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Demo相关
|
||||
*/
|
||||
|
||||
public interface IWorkItemService {
|
||||
|
||||
Map<String, Object> getWorkItemById(long id);
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.jeelowcode.service.bpm.config.framework.portal.core.dto.ReceiveReques
|
||||
import com.jeelowcode.service.system.api.IApiAdminUserApi;
|
||||
import com.jeelowcode.service.system.dto.AdminUserRespDTO;
|
||||
import com.jeelowcode.tool.framework.common.util.object.BeanUtils;
|
||||
import com.jeelowcode.tool.framework.datapermission.core.annotation.DataPermission;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -33,6 +34,7 @@ import java.util.*;
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@DataPermission(enable=false)
|
||||
public class WorkItemServiceImpl implements IWorkItemService {
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user