2025-12-04 优化改造

This commit is contained in:
2025-12-04 17:00:07 +08:00
parent be56324763
commit 4282a126ef
22 changed files with 5660 additions and 98 deletions

View File

@@ -78,7 +78,10 @@ public class ExamIssusController extends BaseController {
detail = new ArrayList<HashMap<String, Object>>();
}
for (JeeLowCodeUser dbuser : userPage.getRecords()) {
HashMap<String, Object> user = CollectionUtil.isEmpty(detail) ? null : detail.stream().filter(t -> t.containsKey("userId") && t.get("userId").toString().equals(dbuser.getUserId())).findFirst().orElse(null);
HashMap<String, Object> user = CollectionUtil.isEmpty(detail) ? null
: detail.stream().filter(t ->
t.containsKey("userId") && t.get("userId").toString().equals(dbuser.getUserId()))
.findFirst().orElse(null);
if (Objects.isNull(user)) {
HashMap<String, Object> newUser = new HashMap<>();
newUser.put("chargeId", dbuser.getUserId());

View File

@@ -0,0 +1,218 @@
package com.jeelowcode.module.biz.controller;
import cn.hutool.json.JSONObject;
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.common.util.string.StrUtils;
import com.jeelowcode.tool.framework.datapermission.core.annotation.DataPermission;
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.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;
import static com.jeelowcode.tool.framework.common.pojo.CommonResult.success;
@Slf4j
@JeeLowCodeTenantIgnore
@Tag(name = "低代码框架 - 自定义外协人员持证接口")
@RestController
@AllArgsConstructor
@RequestMapping(JeeLowCodeBaseConstant.REQUEST_URL_START + "/outsideLicense")
@DataPermission(enable=false)
public class OutSideLicenseController extends BaseController {
@Autowired
private IFormService dbFormService;
@Autowired
private IFileService fileService;
@Autowired
private IFrameSqlService sqlService;
public Map<String, Object> getOutSideBypersonNo(String personNo) {
SqlInfoQueryWrapper.Wrapper wrapper = SqlHelper.getQueryWrapper();
wrapper.setTableName("lc_outside_license");
wrapper.setWhere(where -> {
where.eq("personNo", personNo);
where.eq("is_deleted", 0);
});
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字段为文件地址
* @param jsonObject 压缩文件的地址可以是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 attachmentFileUrl = jsonObject.get("attachment") != null ?
jsonObject.get("attachment").toString() : "";
if (attachmentFileUrl.isEmpty()) {
return 0;
}
int successCount = 0;
String tableName = "lc_outside_license";
Long detailFormId = dbFormService.getDbFormIdByTableName(tableName);
// 用于存储所有需要更新的数据key为身份证号value为需要更新的字段
Map<String, JSONObject> updateDataMap = new HashMap<>();
processCompressedFile(attachmentFileUrl, "attachment", 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 要更新的字段名attachment
* @param updateDataMap 用于存储更新数据的Mapkey为身份证号
*/
private void processCompressedFile(String fileUrl, String fieldName,
Map<String, JSONObject> updateDataMap) {
File tempZipFile = null;
File tempDir = null;
Long tenantId = -1L;
Long userId = -1L;
try {
// 1. 下载文件如果是URL或直接使用本地文件
if (fileUrl.startsWith("http://") || fileUrl.startsWith("https://")) {
// 从URL下载文件先编码路径避免中文/特殊字符导致 400
String encodedUrl = StrUtils.encodeUrl(fileUrl);
tempZipFile = FileUtil.downloadFileFromUrl(encodedUrl);
} else {
// 本地文件路径
tempZipFile = new File(fileUrl);
if (!tempZipFile.exists()) {
log.warn("文件不存在: {}", fileUrl);
return;
}
}
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
if (loginUser != null) {
tenantId = loginUser.getTenantId();
userId = loginUser.getId();
}
// 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 = getOutSideBypersonNo(cardId);
if (entity.isEmpty()) {
log.warn("未找到身份证号对应的记录: {}", cardId);
continue;
}
// 4.3 上传文件到服务器
String uploadPath = fileService.uploadFile(file,tenantId,userId);
// 4.4 更新或添加到更新数据Map中
String cardIdKey = cardId;
JSONObject updateData = updateDataMap.get(cardIdKey);
if (updateData == null) {
// 如果Map中还没有这个身份证号的记录创建新记录
updateData = JSONUtil.parseObj(entity);
updateDataMap.put(cardIdKey, updateData);
}
// 更新对应的字段(追加路径)
String targetFieldKey = StrUtils.getCaseInsensitiveKey(updateData, fieldName);
String existPath = updateData.getStr(targetFieldKey);
if (existPath == null || existPath.isEmpty()) {
updateData.put(fieldName, uploadPath);
} else {
updateData.put(fieldName, existPath + "," + 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);
}
}
}
}

View File

@@ -16,6 +16,7 @@ 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.common.util.string.StrUtils;
import com.jeelowcode.tool.framework.datapermission.core.annotation.DataPermission;
import com.jeelowcode.tool.framework.security.core.LoginUser;
import com.jeelowcode.tool.framework.security.core.util.SecurityFrameworkUtils;
@@ -26,14 +27,8 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
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.*;
import java.util.regex.Pattern;
@@ -100,36 +95,11 @@ public class OutSidePersonController extends BaseController {
wrapper.setTableName("lc_outside_person");
wrapper.setWhere(where -> {
where.eq("cardNo", cardNo);
where.eq("is_deleted", 0);
});
return sqlService.getDataOneByPlus(wrapper);
}
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;
}
/**
* 根据压缩文件地址下载、解压文件,并根据文件名(身份证号)更新数据库
*
@@ -140,37 +110,7 @@ public class OutSidePersonController extends BaseController {
* 4. 根据身份证号查询lc_risk_hazard_manage表的cardID字段
* 5. 如果匹配到数据,将文件上传到服务器指定目录
* 6. 更新lc_risk_hazard_manage表的actual_corrective_Attachment字段为文件地址
*
* 使用示例:
* <pre>
* // 方式1使用MyBatis Mapper
* &#64;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() {
* &#64;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"
* @param jsonObject 压缩文件的地址可以是URL如"http://example.com/file.zip"或本地路径如"/path/to/file.zip"
* @return 处理结果:成功处理的文件数量
* @throws IOException IO异常
*/
@@ -234,12 +174,13 @@ public class OutSidePersonController extends BaseController {
Map<String, JSONObject> updateDataMap) {
File tempZipFile = null;
File tempDir = null;
Long tenantId = -1L;
Long userId = -1L;
try {
// 1. 下载文件如果是URL或直接使用本地文件
if (fileUrl.startsWith("http://") || fileUrl.startsWith("https://")) {
// 从URL下载文件先编码路径避免中文/特殊字符导致 400
String encodedUrl = encodeUrl(fileUrl);
String encodedUrl = StrUtils.encodeUrl(fileUrl);
tempZipFile = FileUtil.downloadFileFromUrl(encodedUrl);
} else {
// 本地文件路径
@@ -250,6 +191,12 @@ public class OutSidePersonController extends BaseController {
}
}
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
if (loginUser != null) {
tenantId = loginUser.getTenantId();
userId = loginUser.getId();
}
// 2. 创建临时解压目录
String tempDirPath = System.getProperty("java.io.tmpdir") + File.separator +
"unzip_" + System.currentTimeMillis() + "_" + fieldName;
@@ -282,7 +229,7 @@ public class OutSidePersonController extends BaseController {
}
// 4.3 上传文件到服务器
String uploadPath = uploadFile(file);
String uploadPath = fileService.uploadFile(file,tenantId,userId);
// 4.4 更新或添加到更新数据Map中
String cardIdKey = cardId;
@@ -295,7 +242,7 @@ public class OutSidePersonController extends BaseController {
}
// 更新对应的字段(追加路径)
String targetFieldKey = getCaseInsensitiveKey(updateData, fieldName);
String targetFieldKey = StrUtils.getCaseInsensitiveKey(updateData, fieldName);
String existPath = updateData.getStr(targetFieldKey);
if (existPath == null || existPath.isEmpty()) {
updateData.put(fieldName, uploadPath);
@@ -328,28 +275,5 @@ 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;
}
}

View File

@@ -80,7 +80,7 @@ public class PlanIssusController extends BaseController {
for (JeeLowCodeUser dbuser : userPage.getRecords()) {
HashMap<String, Object> user = CollectionUtil.isEmpty(detail) ? null
: detail.stream().filter(t ->
t.containsKey("dept_id") && t.get("dept_id").toString().equals(dbuser.getDeptId())).
t.containsKey("charge_id") && t.get("charge_id").toString().equals(dbuser.getUserId())).
findFirst().orElse(null);
if (Objects.isNull(user)) {
HashMap<String, Object> newUser = new HashMap<>();

View File

@@ -5,6 +5,7 @@ import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.jeelowcode.core.framework.controller.BaseController;
import com.jeelowcode.core.framework.service.IFormService;
import com.jeelowcode.framework.exception.JeeLowCodeException;
import com.jeelowcode.framework.global.JeeLowCodeBaseConstant;
import com.jeelowcode.framework.tenant.annotation.JeeLowCodeTenantIgnore;
@@ -21,6 +22,7 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jodd.util.ArraysUtil;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.*;
@@ -38,6 +40,9 @@ public class TrainingController extends BaseController {
private final IJeeLowCodeAdapter jeeLowCodeAdapter;
@Autowired
private IFormService dbFormService;
@GetMapping({"/sendDept"})
@ApiOperationSupport(order = 5)
@Operation(summary = "下发计划给使用部门")
@@ -48,22 +53,29 @@ public class TrainingController extends BaseController {
throw new JeeLowCodeException("缺少必要参数");
}
String tableName="lc_training_record";
Long dbFormId = dbFormService.getDbFormIdByTableName(tableName);
List<Long> userIdList = Arrays.stream(userIdArr).map(Long::parseLong).collect(Collectors.toList());
IPage<JeeLowCodeUser> userPage = (IPage<JeeLowCodeUser>) jeeLowCodeAdapter.getUserPageByUserIds(1, 10000, userIdList);
if (CollectionUtil.isNotEmpty(userPage.getRecords())) {
for (int i = 0; i < idArr.length; i++) {
ResultDataModel resultDataModel = super.getDataDetail(Long.parseLong(tableId), Long.valueOf(idArr[i]), new HashMap<String, Object>());
if (CollectionUtil.isNotEmpty(resultDataModel.getRecords())) {
// resultDataModel.getRecords().get(0).get("jeelowcode_subtable_data") lc_training_plan_area
if (resultDataModel.getRecords().get(0).containsKey("jeelowcode_subtable_data")) {
HashMap<String, Object> details = (HashMap<String, Object>) resultDataModel.getRecords().get(0).get("jeelowcode_subtable_data");
Map<String, Object> trainingPlan=resultDataModel.getRecords().get(0);
if (trainingPlan.containsKey("jeelowcode_subtable_data")) {
HashMap<String, Object> details = (HashMap<String, Object>) trainingPlan.get("jeelowcode_subtable_data");
List<JSONObject> records = new ArrayList<JSONObject>();
if (details.containsKey("lc_training_plan_area")) {
List<HashMap<String, Object>> detail = (List<HashMap<String, Object>>) details.get("lc_training_plan_area");
if(Objects.isNull(detail)) {
detail = new ArrayList<HashMap<String, Object>>();
}
for (JeeLowCodeUser dbuser : userPage.getRecords()) {
HashMap<String, Object> user = CollectionUtil.isEmpty(detail) ? null : detail.stream().filter(t -> t.containsKey("userId") && t.get("userId").toString().equals(dbuser.getUserId())).findFirst().orElse(null);
HashMap<String, Object> user = CollectionUtil.isEmpty(detail) ? null
: detail.stream().filter(t ->
t.containsKey("userId") && t.get("userId").toString().equals(dbuser.getUserId()))
.findFirst().orElse(null);
if (Objects.isNull(user)) {
HashMap<String, Object> newUser = new HashMap<>();
newUser.put("userId", dbuser.getUserId());
@@ -72,10 +84,27 @@ public class TrainingController extends BaseController {
newUser.put("deptName", dbuser.getDeptName());
newUser.put("planId", Long.valueOf(idArr[i]));
detail.add(newUser);
// 组装培训记录
HashMap<String, Object> newRecord = new HashMap<>();
newRecord.put("deptName", dbuser.getDeptName());
newRecord.put("deptId", dbuser.getDeptId());
newRecord.put("planName", trainingPlan.get("planname"));
newRecord.put("planId", trainingPlan.get("id"));
newRecord.put("billNo", "PXJL" + System.currentTimeMillis());
records.add(JSONUtil.parseObj(newRecord));
}
}
resultDataModel.getRecords().get(0).put("lc_training_plan_area", detail);
super.editJsonData(Long.valueOf(tableId), JSONUtil.parseObj(resultDataModel.getRecords().get(0)));
super.addJsonData(dbFormId, records);
}
}
}

View File

@@ -71,7 +71,8 @@ public class AfterDrillPlanListEnhance extends BaseController implements AfterAd
// 遍历allTask 如果有一个逾期,设置计划为逾期状态
if (CollectionUtil.isNotEmpty(allTask.getRecords())) {
for (Map<String, Object> task : allTask.getRecords()) {
if (!task.get("task_status").equals("3")) {
if (!"3".equals(task.get("task_status"))) {
// 对比当前日期和任务日期
LocalDate eDate = LocalDate.parse(task.get("eDate").toString(), formatter);
// 比较日期并更新状态

View File

@@ -0,0 +1,73 @@
package com.jeelowcode.module.biz.enhance;
import com.jeelowcode.core.framework.config.aspect.enhance.model.EnhanceContext;
import com.jeelowcode.core.framework.config.aspect.enhance.plugin.BeforeAdvicePlugin;
import com.jeelowcode.core.framework.controller.BaseController;
import com.jeelowcode.core.framework.service.IFormService;
import com.jeelowcode.core.framework.utils.Func;
import com.jeelowcode.framework.utils.tool.NumberUtil;
import com.jeelowcode.module.biz.service.IDrillPlanService;
import com.jeelowcode.service.system.entity.AdminUserDO;
import com.jeelowcode.service.system.service.IAdminUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Map;
import java.util.Objects;
/**
* 演练任务数据导入前
*/
@Slf4j
@Component("beforeDrillTaskExportEnhance")
public class BeforeDrillTaskExportEnhance extends BaseController implements BeforeAdvicePlugin {
@Autowired
private IFormService dbFormService;
@Autowired
private IAdminUserService userService;
@Autowired
private IDrillPlanService iDrillPlanService;
private static BeforeDrillTaskExportEnhance ADTE;
@PostConstruct
public void init(){
ADTE = this;
}
@Override
public void execute(EnhanceContext enhanceContext) {
Map<String, Object> params = enhanceContext.getParam().getParams();
params.put("billNo","RW" + System.currentTimeMillis());
params.put("task_status", 3);
params.put("isIssus", 0);
//责任人
if(params.containsKey("drill_plan_id")) {
Long planId = NumberUtil.toLong(params.get("drill_plan_id").toString());
Map<String, Object> currentPlan=ADTE.iDrillPlanService.getDrillPlanById(planId);
if(!Objects.isNull(currentPlan)) {
params.put("emergency_plan_name", currentPlan.get("emergency_plan_name"));
params.put("emergency_plan_id", currentPlan.get("emergency_plan_id"));
}
}
//责任人
if(params.containsKey("charge_name")) {
String deptChargerName = Func.getMap2Str(params, "charge_name");
AdminUserDO user = ADTE.userService.selectByNickname(deptChargerName);
if (user != null) {
params.put("charge_id", user.getId());
}
}
}
}