@@ -5,25 +5,37 @@ import cn.hutool.json.JSONUtil;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport ;
import com.jeelowcode.core.framework.controller.BaseController ;
import com.jeelowcode.core.framework.service.IFormService ;
import com.jeelowcode.core.framework.service.IFrameSqlService ;
import com.jeelowcode.framework.exception.JeeLowCodeException ;
import com.jeelowcode.framework.global.JeeLowCodeBaseConstant ;
import com.jeelowcode.framework.plus.SqlHelper ;
import com.jeelowcode.framework.plus.build.buildmodel.wrapper.SqlInfoQueryWrapper ;
import com.jeelowcode.framework.tenant.annotation.JeeLowCodeTenantIgnore ;
import com.jeelowcode.framework.utils.model.ResultDataModel ;
import com.jeelowcode.framework.utils.tool.CollectionUtil ;
import com.jeelowcode.service.infra.service.IFileService ;
import com.jeelowcode.tool.framework.common.pojo.CommonResult ;
import com.jeelowcode.tool.framework.common.util.io.FileUtil ;
import com.jeelowcode.tool.framework.security.core.LoginUser ;
import com.jeelowcode.tool.framework.security.core.util.SecurityFrameworkUtils ;
import io.swagger.v3.oas.annotations.Operation ;
import io.swagger.v3.oas.annotations.tags.Tag ;
import lombok.AllArgsConstructor ;
import lombok.extern.slf4j.Slf4j ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.web.bind.annotation.GetMapping ;
import org.springframework.web.bind.annotation.RequestMapping ;
import org.springframework.web.bind.annotation.RestController ;
import org.springframework.web.bind.annotation.* ;
import javax.annotation.Resource ;
import java.io.File ;
import java.io.FileNotFoundException ;
import java.io.IOException ;
import java.time.LocalDateTime ;
import java.time.format.DateTimeFormatter ;
import java.util.* ;
import java.util.regex.Pattern ;
import static com.jeelowcode.tool.framework.common.pojo.CommonResult.success ;
@Slf4j
@JeeLowCodeTenantIgnore
@Tag ( name = " 低代码框架 - 自定义外协人员接口 " )
@RestController
@@ -34,6 +46,12 @@ public class OutSidePersonController extends BaseController {
@Autowired
private IFormService dbFormService ;
@Autowired
private IFileService fileService ;
@Autowired
private IFrameSqlService sqlService ;
@GetMapping ( { " /importOutside " } )
@ApiOperationSupport ( order = 5 )
@Operation ( summary = " 引入外协人员 " )
@@ -71,4 +89,351 @@ public class OutSidePersonController extends BaseController {
super . addJsonData ( Long . valueOf ( tableId ) , licenses ) ;
return success ( " 引入成功 " ) ;
}
public Map < String , Object > getOutSideByCardNo ( String cardNo ) {
SqlInfoQueryWrapper . Wrapper wrapper = SqlHelper . getQueryWrapper ( ) ;
wrapper . setTableName ( " lc_outside_person " ) ;
wrapper . setWhere ( where - > {
where . eq ( " cardNo " , cardNo ) ;
} ) ;
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
Long tenantId = - 1L ;
Long userId = - 1L ;
LoginUser loginUser = SecurityFrameworkUtils . getLoginUser ( ) ;
if ( loginUser ! = null ) {
tenantId = loginUser . getTenantId ( ) ;
userId = loginUser . getId ( ) ;
}
//每个文件放一个文件夹,防止乱码后找不到正确文件
LocalDateTime now = LocalDateTime . now ( ) ;
DateTimeFormatter formatter = DateTimeFormatter . ofPattern ( " HHmmssSSS " ) ;
String timeString = now . format ( formatter ) ;
String publicPath = " upload/ " + tenantId + " / " + userId + " / " + timeString + " / " ;
String path = publicPath + fileName ;
fileName = fileService . getUniqueFileName ( fileName , path ) ;
// 解决信创环境下文件名中文乱码导致附件错乱的问题
//path = publicPath + IdUtil.simpleUUID() + (StrUtil.isEmpty(FileUtil.extName(fileName)) ? "" : ("." + FileUtil.extName(fileName)));
String fileUrl = fileService . createFile ( fileName , path , FileUtil . toByteArray ( file ) ) ;
return fileUrl ;
}
/**
* 根据压缩文件地址下载、解压文件,并根据文件名(身份证号)更新数据库
*
* 功能说明:
* 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异常
*/
@PutMapping ( { " /batchAttachments " } )
@ApiOperationSupport ( order = 5 )
@Operation ( summary = " 批量上传附件 " )
public int batchAttachments ( @RequestBody JSONObject jsonObject ) throws IOException {
String commitmentFileUrl = jsonObject . get ( " commitmentAttchment " ) ! = null ?
jsonObject . get ( " commitmentAttchment " ) . toString ( ) : " " ;
String secretFileUrl = jsonObject . get ( " secretAttchment " ) ! = null ?
jsonObject . get ( " secretAttchment " ) . toString ( ) : " " ;
if ( commitmentFileUrl . isEmpty ( ) & & secretFileUrl . isEmpty ( ) ) {
return 0 ;
}
int successCount = 0 ;
String tableName = " lc_outside_person " ;
Long detailFormId = dbFormService . getDbFormIdByTableName ( tableName ) ;
// 用于存储所有需要更新的数据, key为身份证号, value为需要更新的字段
Map < String , JSONObject > updateDataMap = new HashMap < > ( ) ;
// 处理 commitmentAttchment 压缩包
if ( ! commitmentFileUrl . isEmpty ( ) ) {
processCompressedFile ( commitmentFileUrl , " commitmentAttchment " , updateDataMap ) ;
}
// 处理 secretAttchment 压缩包
if ( ! secretFileUrl . isEmpty ( ) ) {
processCompressedFile ( secretFileUrl , " secretAttchment " , updateDataMap ) ;
}
// 将Map转换为List, 用于批量更新
List < JSONObject > editDataList = new ArrayList < > ( updateDataMap . values ( ) ) ;
if ( ! editDataList . isEmpty ( ) ) {
// 更新数据
super . editJsonData ( detailFormId , editDataList ) ;
successCount = editDataList . size ( ) ;
}
return successCount ;
}
/**
* 处理压缩文件的通用方法
* @param fileUrl 压缩文件地址
* @param fieldName 要更新的字段名( commitmentAttchment 或 secretAttchment)
* @param updateDataMap 用于存储更新数据的Map, key为身份证号
*/
private void processCompressedFile ( String fileUrl , String fieldName ,
Map < String , JSONObject > updateDataMap ) {
File tempZipFile = null ;
File tempDir = null ;
try {
// 1. 下载文件( 如果是URL) 或直接使用本地文件
if ( fileUrl . startsWith ( " http:// " ) | | fileUrl . startsWith ( " https:// " ) ) {
// 从URL下载文件
tempZipFile = FileUtil . downloadFileFromUrl ( fileUrl ) ;
} else {
// 本地文件路径
tempZipFile = new File ( fileUrl ) ;
if ( ! tempZipFile . exists ( ) ) {
log . warn ( " 文件不存在: {} " , fileUrl ) ;
return ;
}
}
// 2. 创建临时解压目录
String tempDirPath = System . getProperty ( " java.io.tmpdir " ) + File . separator +
" unzip_ " + System . currentTimeMillis ( ) + " _ " + fieldName ;
tempDir = new File ( tempDirPath ) ;
if ( ! tempDir . exists ( ) ) {
tempDir . mkdirs ( ) ;
}
// 3. 解压缩文件
List < File > fileList = FileUtil . unzipFile ( tempZipFile , tempDir ) ;
log . info ( " 解压文件成功 [{}],共 {} 个文件 " , fieldName , fileList . size ( ) ) ;
// 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 ) ;
// 4.4 更新或添加到更新数据Map中
String cardIdKey = cardId ;
JSONObject updateData = updateDataMap . get ( cardIdKey ) ;
if ( updateData = = null ) {
// 如果Map中还没有这个身份证号的记录, 创建新记录
updateData = JSONUtil . parseObj ( entity ) ;
updateDataMap . put ( cardIdKey , updateData ) ;
}
// 更新对应的字段
updateData . put ( fieldName , uploadPath ) ;
log . info ( " 处理成功 [{}] - 身份证号: {}, 文件: {} " , fieldName , cardId , uploadPath ) ;
} catch ( Exception e ) {
log . error ( " 处理文件失败 [{}]: {} " , fieldName , file . getName ( ) , e ) ;
}
}
} catch ( Exception e ) {
log . error ( " 处理压缩文件失败 [{}]: {} " , fieldName , fileUrl , e ) ;
} finally {
// 清理临时文件
if ( tempZipFile ! = null & & tempZipFile . exists ( ) & &
( fileUrl . startsWith ( " http:// " ) | | fileUrl . startsWith ( " https:// " ) ) ) {
tempZipFile . delete ( ) ;
}
if ( tempDir ! = null & & tempDir . exists ( ) ) {
FileUtil . deleteDirectory ( tempDir ) ;
}
}
}
}