外协人员excel导入优化

This commit is contained in:
2025-12-18 09:27:45 +08:00
parent 235b95a653
commit 4b45b69291
12 changed files with 1697 additions and 53 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,7 @@
package com.jeelowcode.core.framework.service; package com.jeelowcode.core.framework.service;
import com.jeelowcode.core.framework.service.impl.PersonInfoServiceImpl; import com.jeelowcode.core.framework.service.impl.PersonInfoServiceImpl;
import com.jeelowcode.framework.utils.tool.spring.SpringUtils;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
@@ -8,7 +9,8 @@ public class ExcelExtendFactory {
public IExcelImportService getExcelImportService(String tableName) { public IExcelImportService getExcelImportService(String tableName) {
if(tableName.toLowerCase().equals("lc_outside_person")){ if(tableName.toLowerCase().equals("lc_outside_person")){
return new PersonInfoServiceImpl(); // 从Spring容器中获取实例确保依赖注入正常
return SpringUtils.getBean(PersonInfoServiceImpl.class);
} }
return null; return null;
} }

View File

@@ -1,6 +1,7 @@
package com.jeelowcode.core.framework.service; package com.jeelowcode.core.framework.service;
import com.jeelowcode.core.framework.params.model.ExcelImportDataDictModel;
import com.jeelowcode.core.framework.params.model.ExcelModel; import com.jeelowcode.core.framework.params.model.ExcelModel;
import com.jeelowcode.core.framework.params.model.ExcelTemplateModel; import com.jeelowcode.core.framework.params.model.ExcelTemplateModel;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
@@ -34,4 +35,6 @@ public interface IExcelService {
* 处理临时库 * 处理临时库
*/ */
void handleTempTable(ServletRequestAttributes sra,Long dbFormId, Long fieldId); void handleTempTable(ServletRequestAttributes sra,Long dbFormId, Long fieldId);
ExcelImportDataDictModel formatExcelImportDataList(Long dbformId);
} }

View File

@@ -219,7 +219,8 @@ public class ExcelServiceImpl implements IExcelService {
//获取字典 //获取字典
private ExcelImportDataDictModel formatExcelImportDataList(Long dbformId) { @Override
public ExcelImportDataDictModel formatExcelImportDataList(Long dbformId) {
List<FormFieldEntity> fieldList = formService.getDbFieldList(dbformId); List<FormFieldEntity> fieldList = formService.getDbFieldList(dbformId);
//字典集合 //字典集合

View File

@@ -40,6 +40,7 @@ import com.jeelowcode.framework.utils.model.ResultDataModel;
import com.jeelowcode.framework.utils.tool.spring.SpringUtils; import com.jeelowcode.framework.utils.tool.spring.SpringUtils;
import com.jeelowcode.framework.utils.utils.FuncBase; import com.jeelowcode.framework.utils.utils.FuncBase;
import com.jeelowcode.framework.utils.utils.JeeLowCodeUtils; import com.jeelowcode.framework.utils.utils.JeeLowCodeUtils;
import com.jeelowcode.tool.framework.datapermission.core.annotation.DataPermission;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.JSQLParserException;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -685,6 +686,7 @@ public class FrameServiceImpl implements IFrameService {
} }
//保存导入数据 //保存导入数据
@DataPermission(enable = false) // 关闭数据权限,避免只查看自己时,查询不到部门。
@Override @Override
public ExecuteEnhanceModel saveImportData(Long dbFormId, Map<String, Object> params) { public ExecuteEnhanceModel saveImportData(Long dbFormId, Map<String, Object> params) {
String duplicateType = FuncBase.getMap2Str(params, JeeLowCodeConstant.IMPORT_DUPLICATE_TYPE); String duplicateType = FuncBase.getMap2Str(params, JeeLowCodeConstant.IMPORT_DUPLICATE_TYPE);

View File

@@ -6,10 +6,10 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeelowcode.core.framework.config.btncommand.param.ButtonParamImport; import com.jeelowcode.core.framework.config.btncommand.param.ButtonParamImport;
import com.jeelowcode.core.framework.entity.ExcelFileDataEntity; import com.jeelowcode.core.framework.entity.ExcelFileDataEntity;
import com.jeelowcode.core.framework.entity.FormEntity; import com.jeelowcode.core.framework.entity.FormEntity;
import com.jeelowcode.core.framework.service.IExcelFileDataService; import com.jeelowcode.core.framework.entity.FormFieldEntity;
import com.jeelowcode.core.framework.service.IExcelImportService; import com.jeelowcode.core.framework.params.model.ExcelImportDataDictModel;
import com.jeelowcode.core.framework.service.IFormService; import com.jeelowcode.core.framework.service.*;
import com.jeelowcode.core.framework.service.IFrameService; import com.jeelowcode.framework.utils.enums.JeeLowCodeFieldTypeEnum;
import com.jeelowcode.core.framework.utils.Func; import com.jeelowcode.core.framework.utils.Func;
import com.jeelowcode.core.framework.utils.FuncWeb; import com.jeelowcode.core.framework.utils.FuncWeb;
import com.jeelowcode.framework.exception.JeeLowCodeException; import com.jeelowcode.framework.exception.JeeLowCodeException;
@@ -22,7 +22,11 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@@ -32,45 +36,311 @@ public class PersonInfoServiceImpl implements IExcelImportService {
@Autowired @Autowired
private IFrameService frameService; private IFrameService frameService;
@Autowired
private IExcelService excelService;
@Autowired
private IFormService formService;
@Override @Override
public void importExcelCheck(ButtonParamImport buttonParam) { public void importExcelCheck(ButtonParamImport buttonParam) {
Map<String, Object> params =new HashMap<>(); Map<String, Object> params =new HashMap<>();
params.put(ParamEnum.PAGE_NO.getCode(),1); params.put(ParamEnum.PAGE_NO.getCode(),1);
params.put(ParamEnum.PAGE_SIZE.getCode(),1000); params.put(ParamEnum.PAGE_SIZE.getCode(),1000);
IFrameService proxyService = SpringUtils.getBean(IFrameService.class); IFrameService proxyService = SpringUtils.getBean(IFrameService.class);
ResultDataModel model = proxyService.getDataList(NumberUtil.toLong("1964207990401785857"), params);
//获取字典 - 使用SpringUtils获取避免注入为null的问题
IExcelService excelServiceBean = excelService != null ? excelService : SpringUtils.getBean(IExcelService.class);
ExcelImportDataDictModel dictModel = excelServiceBean.formatExcelImportDataList(buttonParam.getDbFormId());
Map<String, Map<String, String>> dictMaps = dictModel != null ? dictModel.getDictMaps() : null;
// 如果字典为空或数据列表为空,直接返回
if(dictMaps == null || dictMaps.isEmpty() || CollectionUtil.isEmpty(buttonParam.getDataMapList())){
return;
}
// 以遍历dictMaps为起点检查每个字典字段
for(Map.Entry<String, Map<String, String>> dictEntry : dictMaps.entrySet()){
String fieldCode = dictEntry.getKey(); // 字段名,如 supplierId、demandId
Map<String, String> dictMap = dictEntry.getValue(); // 该字段对应的字典映射
// 遍历导入数据列表,查找是否有匹配的字段
for(Map<String, Object> dataMap : buttonParam.getDataMapList()){
// 检查数据中是否包含该字段
if(dataMap.containsKey(fieldCode)){
Object fieldValue = dataMap.get(fieldCode);
// 如果字段有值
if(fieldValue != null && !fieldValue.toString().trim().isEmpty()){
String valueStr = fieldValue.toString();
// 检查该值在对应的字典中是否存在
if(dictMap == null || !dictMap.containsKey(valueStr)){
throw new JeeLowCodeException("字段[" + fieldCode + "]的值[" + valueStr + "]在字典中不存在");
}
}
}
}
}
// 校验身份证格式
if(CollectionUtil.isNotEmpty(buttonParam.getDataMapList())){
for(Map<String, Object> dataMap : buttonParam.getDataMapList()){
if(dataMap.containsKey("cardNo")){
Object cardNoValue = dataMap.get("cardNo");
if(cardNoValue != null && !cardNoValue.toString().trim().isEmpty()){
String cardNo = cardNoValue.toString().trim();
if(!isValidIdCard(cardNo)){
throw new JeeLowCodeException("身份证号[" + cardNo + "]格式不正确");
}
}
}
}
}
// 校验日期类型字段格式
validateDateFields(buttonParam);
}
/**
* 校验日期类型字段格式
*/
private void validateDateFields(ButtonParamImport buttonParam) {
if(CollectionUtil.isEmpty(buttonParam.getDataMapList())){
return;
}
// 获取字段列表
List<FormFieldEntity> fieldList = formService.getDbFieldList(buttonParam.getDbFormId());
if(CollectionUtil.isEmpty(fieldList)){
return;
}
// 找出所有日期类型字段Date 和 DateTime
Map<String, JeeLowCodeFieldTypeEnum> dateFieldMap = new HashMap<>();
for(FormFieldEntity field : fieldList){
String fieldType = field.getFieldType();
JeeLowCodeFieldTypeEnum fieldTypeEnum = JeeLowCodeFieldTypeEnum.getByFieldType(fieldType);
if(fieldTypeEnum == JeeLowCodeFieldTypeEnum.DATE || fieldTypeEnum == JeeLowCodeFieldTypeEnum.DATETIME){
dateFieldMap.put(field.getFieldCode(), fieldTypeEnum);
}
}
if(dateFieldMap.isEmpty()){
return;
}
// 遍历数据,校验日期字段格式
for(Map<String, Object> dataMap : buttonParam.getDataMapList()){
for(Map.Entry<String, JeeLowCodeFieldTypeEnum> dateFieldEntry : dateFieldMap.entrySet()){
String fieldCode = dateFieldEntry.getKey();
JeeLowCodeFieldTypeEnum fieldTypeEnum = dateFieldEntry.getValue();
if(dataMap.containsKey(fieldCode)){
Object fieldValue = dataMap.get(fieldCode);
if(fieldValue != null && !fieldValue.toString().trim().isEmpty()){
String valueStr = fieldValue.toString().trim();
if(!isValidDate(valueStr, fieldTypeEnum)){
String expectedFormat = fieldTypeEnum == JeeLowCodeFieldTypeEnum.DATE
? "yyyy-MM-dd"
: "yyyy-MM-dd HH:mm:ss";
throw new JeeLowCodeException("字段[" + fieldCode + "]的值[" + valueStr + "]日期格式不正确,期望格式:" + expectedFormat);
}
}
}
}
}
}
/**
* 校验日期格式是否正确
* @param dateStr 日期字符串
* @param fieldTypeEnum 字段类型枚举DATE 或 DATETIME
* @return true-格式正确false-格式错误
*/
private boolean isValidDate(String dateStr, JeeLowCodeFieldTypeEnum fieldTypeEnum) {
if(dateStr == null || dateStr.trim().isEmpty()){
return false;
}
dateStr = dateStr.trim();
try {
if(fieldTypeEnum == JeeLowCodeFieldTypeEnum.DATE){
// 日期格式yyyy-MM-dd
LocalDate.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
return true;
} else if(fieldTypeEnum == JeeLowCodeFieldTypeEnum.DATETIME){
// 日期时间格式yyyy-MM-dd HH:mm:ss
java.time.LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
return true;
}
} catch (Exception e) {
// 解析失败,格式不正确
return false;
}
return false;
}
/**
* 校验身份证格式
* @param cardNo 身份证号
* @return true-格式正确false-格式错误
*/
private boolean isValidIdCard(String cardNo) {
if(cardNo == null || cardNo.trim().isEmpty()){
return false;
}
cardNo = cardNo.trim();
// 18位身份证前17位必须是数字最后一位可以是数字或X大小写都可以
if(cardNo.length() == 18){
// 前17位必须是数字
String first17 = cardNo.substring(0, 17);
if(!first17.matches("\\d{17}")){
return false;
}
// 最后一位可以是数字或X大小写都可以
char lastChar = cardNo.charAt(17);
return Character.isDigit(lastChar) || lastChar == 'X' || lastChar == 'x';
}
// 15位身份证旧版全部15位都是数字
if(cardNo.length() == 15){
return cardNo.matches("\\d{15}");
}
// 其他长度都不符合
return false;
} }
@Override @Override
public void importExcelDataUpdate(ButtonParamImport buttonParam) { public void importExcelDataUpdate(ButtonParamImport buttonParam) {
// Map<String, Object> params =new HashMap<>(); if(CollectionUtil.isEmpty(buttonParam.getDataMapList())){
// params.put(ParamEnum.PAGE_NO.getCode(),1); return;
// params.put(ParamEnum.PAGE_SIZE.getCode(),1000); }
// IFrameService proxyService = SpringUtils.getBean(IFrameService.class);
// ResultDataModel model = proxyService.getDataList(NumberUtil.toLong("1964207990401785857"), params); // 遍历数据列表,提取身份证信息
// if(CollectionUtil.isNotEmpty(buttonParam.getDataMapList())){ for(Map<String, Object> dataMap : buttonParam.getDataMapList()){
// for(Map<String, Object> map : buttonParam.getDataMapList()){ if(dataMap.containsKey("cardNo")){
// if(map.containsKey("supplierName")){ Object cardNoValue = dataMap.get("cardNo");
// Map<String, Object> depMap = model.getRecords().stream().filter(t->t.get("full_name").equals(map.get("supplierName"))).findFirst().orElse(null); if(cardNoValue != null && !cardNoValue.toString().trim().isEmpty()){
// if(Objects.nonNull(depMap)){ String cardNo = cardNoValue.toString().trim();
// map.put("supplierId",depMap.get("id")); // 提取身份证信息
// }else { IdCardInfo idCardInfo = extractIdCardInfo(cardNo);
// throw new JeeLowCodeException("供应商:"+map.get("supplierName") + "不存在"); if(idCardInfo != null){
// } // 设置出生日期
// } if(idCardInfo.getBirthDate() != null){
// dataMap.put("birthday", idCardInfo.getBirthDate());
// if(map.containsKey("demandName")){ }
// Map<String, Object> depMap = model.getRecords().stream().filter(t->t.get("full_name").equals(map.get("demandName"))).findFirst().orElse(null); // 设置年龄
// if(Objects.nonNull(depMap)){ if(idCardInfo.getAge() != null){
// map.put("demandId",depMap.get("id")); dataMap.put("personAge", idCardInfo.getAge());
// }else { }
// throw new JeeLowCodeException("用人单位:"+map.get("demandName") + "不存在"); // 设置性别("男"或"女"
// } if(idCardInfo.getGender() != null){
// } dataMap.put("personSex", idCardInfo.getGender());
// } }
// } }
}
}
}
}
/**
* 身份证信息类
*/
private static class IdCardInfo {
private String birthDate; // 出生日期格式yyyy-MM-dd
private Integer age; // 年龄
private String gender; // 性别:"男"或"女"
public String getBirthDate() {
return birthDate;
}
public void setBirthDate(String birthDate) {
this.birthDate = birthDate;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
}
/**
* 从身份证号提取信息(出生日期、年龄、性别)
* @param cardNo 身份证号
* @return 身份证信息如果格式不正确返回null
*/
private IdCardInfo extractIdCardInfo(String cardNo) {
if(cardNo == null || cardNo.trim().isEmpty()){
return null;
}
cardNo = cardNo.trim();
IdCardInfo info = new IdCardInfo();
String birthDateStr = null;
LocalDate birthDate = null;
// 18位身份证
if(cardNo.length() == 18){
// 提取出生日期第7-14位YYYYMMDD格式
String yearMonthDay = cardNo.substring(6, 14);
try {
birthDate = LocalDate.parse(yearMonthDay, DateTimeFormatter.ofPattern("yyyyMMdd"));
birthDateStr = birthDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
} catch (Exception e) {
// 日期解析失败返回null
return null;
}
// 提取性别第17位奇数为男偶数为女
int genderCode = Character.getNumericValue(cardNo.charAt(16));
info.setGender(genderCode % 2 == 1 ? "" : "");
}
// 15位身份证旧版
else if(cardNo.length() == 15){
// 提取出生日期第7-12位YYMMDD格式
try {
int year = Integer.parseInt(cardNo.substring(6, 8));
int month = Integer.parseInt(cardNo.substring(8, 10));
int day = Integer.parseInt(cardNo.substring(10, 12));
// 年份需要加1900
birthDate = LocalDate.of(1900 + year, month, day);
birthDateStr = birthDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
} catch (Exception e) {
// 日期解析失败返回null
return null;
}
// 提取性别第15位奇数为男偶数为女
int genderCode = Character.getNumericValue(cardNo.charAt(14));
info.setGender(genderCode % 2 == 1 ? "" : "");
}
else {
// 长度不符合返回null
return null;
}
// 计算年龄
if(birthDate != null){
LocalDate now = LocalDate.now();
long age = ChronoUnit.YEARS.between(birthDate, now);
info.setAge((int) age);
info.setBirthDate(birthDateStr);
}
return info;
} }
} }

View File

@@ -45,8 +45,19 @@ public class CustomSheetWriteHandler implements SheetWriteHandler {
} }
for (Map.Entry<Integer, List<String>> entry : dropDownData.entrySet()){ for (Map.Entry<Integer, List<String>> entry : dropDownData.entrySet()){
if(entry.getValue().size()>=10){ List<String> values = entry.getValue();
String[] selectValues = entry.getValue().toArray(new String[entry.getValue().size()]); // 计算下拉框所有选项的字符总数(包括分隔符逗号)
int totalLength = 0;
for (String value : values) {
totalLength += value != null ? value.length() : 0;
}
// 加上分隔符逗号的长度如果有n个选项需要n-1个逗号
if (values.size() > 1) {
totalLength += values.size() - 1;
}
// 如果字符总数超过255或者选项数量>=10创建隐藏sheet用于sheet引用
if (totalLength > 255 || values.size() >= 10) {
String[] selectValues = values.toArray(new String[values.size()]);
/* 解决办法从这里开始 */ /* 解决办法从这里开始 */
//获取一个workbook //获取一个workbook
Workbook workbook = writeWorkbookHolder.getWorkbook(); Workbook workbook = writeWorkbookHolder.getWorkbook();

View File

@@ -110,15 +110,25 @@ public class RowFormatSetTextHandler implements CellWriteHandler {
String[] dropdownOptionsArray = dropdownOptionList.toArray(new String[0]); String[] dropdownOptionsArray = dropdownOptionList.toArray(new String[0]);
// 计算下拉框所有选项的字符总数(包括分隔符逗号)
int totalLength = 0;
for (String value : dropdownOptionList) {
totalLength += value != null ? value.length() : 0;
}
// 加上分隔符逗号的长度如果有n个选项需要n-1个逗号
if (dropdownOptionList.size() > 1) {
totalLength += dropdownOptionList.size() - 1;
}
// 创建下拉列表的约束 // 创建下拉列表的约束
DataValidationConstraint constraint;//= helper.createExplicitListConstraint(dropdownOptionsArray); DataValidationConstraint constraint;
if (dropdownOptionsArray.length < 10) { // 如果字符总数超过255或者选项数量>=10使用sheet引用方式
if (totalLength > 255 || dropdownOptionsArray.length >= 10) {
// 联动到另外一个 sheet
constraint = helper.createFormulaListConstraint("hidden"+firstCol+"!$A$1:$A$"+dropdownOptionList.size());
} else {
// 直接设置下拉选 // 直接设置下拉选
constraint = helper.createExplicitListConstraint(dropdownOptionsArray); constraint = helper.createExplicitListConstraint(dropdownOptionsArray);
} else {
// 联动到另外一个 sheet
//这里如果识别到大于等于10行不管数据量有多少
constraint = helper.createFormulaListConstraint("hidden"+firstCol+"!$A$1:$A$"+dropdownOptionList.size());
} }
// 设置下拉列表应用的单元格区域例如第2行到最后一行的第2列 // 设置下拉列表应用的单元格区域例如第2行到最后一行的第2列

View File

@@ -0,0 +1,8 @@
package com.jeelowcode.module.biz.service;
import java.util.Map;
public interface IOutsideBatchApprovalService {
void updateOutsidePersonStatus(String tableName, String id, Map<String,Object> dataMap);
}

View File

@@ -0,0 +1,156 @@
package com.jeelowcode.module.biz.service.impl;
import cn.hutool.json.JSONObject;
import com.jeelowcode.core.framework.controller.BaseController;
import com.jeelowcode.core.framework.enums.ApproveStatusEnum;
import com.jeelowcode.core.framework.service.IFormService;
import com.jeelowcode.core.framework.service.IFrameService;
import com.jeelowcode.framework.utils.model.ResultDataModel;
import com.jeelowcode.framework.utils.tool.CollectionUtil;
import com.jeelowcode.framework.utils.tool.NumberUtil;
import com.jeelowcode.module.biz.service.IOutsideBatchApprovalService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* 批量审批服务实现
* 根据lc_outside_batch_approval的审批状态同步更新lc_outside_person表的审批状态和流程实例ID
*/
@Slf4j
@Service
public class OutsideBatchApprovalService extends BaseController implements IOutsideBatchApprovalService {
@Autowired
private IFormService dbFormService;
@Autowired
private IFrameService frameService;
@Override
public void updateOutsidePersonStatus(String tableName, String id, Map<String, Object> dataMap) {
// 只处理批量审批表
if (!"lc_outside_batch_approval".equals(tableName)) {
log.debug("表名 {} 不是批量审批表,跳过处理", tableName);
return;
}
if (id == null || id.trim().isEmpty()) {
log.warn("批量审批记录ID为空跳过同步");
return;
}
Long dataId = NumberUtil.toLong(id);
if (dataId == null) {
log.warn("批量审批记录ID {} 无法转换为Long类型跳过同步", id);
return;
}
Long personFormId = dbFormService.getDbFormIdByTableName("lc_outside_person");
Long batchFormId = dbFormService.getDbFormIdByTableName("lc_outside_batch_approval");
// 获取批量审批记录详情
ResultDataModel resultDataModel = frameService.getDataDetail(batchFormId, dataId, new HashMap<>());
if (CollectionUtil.isEmpty(resultDataModel.getRecords())) {
log.warn("批量审批记录 {} 不存在,跳过同步", dataId);
return;
}
if (!resultDataModel.getRecords().get(0).containsKey("jeelowcode_subtable_data")) {
log.warn("批量审批记录 {} 没有子表数据,跳过同步", dataId);
return;
}
HashMap<String, Object> details = (HashMap<String, Object>) resultDataModel.getRecords().get(0).get("jeelowcode_subtable_data");
if (!details.containsKey("lc_outside_batch_approval_detail")) {
log.warn("批量审批记录 {} 没有明细数据,跳过同步", dataId);
return;
}
List<HashMap<String, Object>> detailList = (List<HashMap<String, Object>>) details.get("lc_outside_batch_approval_detail");
// 从dataMap中获取审批状态和流程实例ID
// 尝试多种可能的字段名(框架可能返回不同的大小写格式)
Object approveStatusObj = dataMap.get(ApproveStatusEnum.codeField);
if (approveStatusObj == null) {
approveStatusObj = dataMap.get("approveStatus");
}
Object processInstanceIdObj = dataMap.get("processInstanceId");
if (processInstanceIdObj == null) {
processInstanceIdObj = dataMap.get("ProcessInstanceId");
}
if (approveStatusObj == null) {
log.warn("批量审批记录 {} 的审批状态为空,跳过同步", dataId);
return;
}
Integer approveStatus = NumberUtil.toInt(approveStatusObj.toString());
String processInstanceId = processInstanceIdObj != null ? processInstanceIdObj.toString() : null;
// 根据审批状态获取对应的描述
String approveStatusName = getApproveStatusName(approveStatus);
if (CollectionUtil.isEmpty(detailList)) {
log.warn("批量审批记录 {} 没有关联的明细数据,跳过同步", dataId);
return;
}
// 收集需要更新的外协人员ID
List<Long> outsideIdList = new ArrayList<>();
for (Map<String, Object> detail : detailList) {
Object outsideIdObj = detail.get("outsideId");
if (outsideIdObj != null) {
Long outsideId = NumberUtil.toLong(outsideIdObj.toString());
if (outsideId != null) {
outsideIdList.add(outsideId);
}
}
}
if (CollectionUtil.isEmpty(outsideIdList)) {
log.warn("批量审批记录 {} 没有有效的外协人员ID跳过同步", dataId);
return;
}
// 批量更新外协人员表的审批状态和流程实例ID
List<JSONObject> updateList = new ArrayList<>();
for (Long outsideId : outsideIdList) {
JSONObject updateData = new JSONObject();
updateData.put("id", outsideId);
updateData.put(ApproveStatusEnum.codeField, approveStatus);
updateData.put(ApproveStatusEnum.nameField, approveStatusName);
if (processInstanceId != null) {
updateData.put("processInstanceId", processInstanceId);
}
updateList.add(updateData);
}
// 执行批量更新
if (CollectionUtil.isNotEmpty(updateList)) {
super.editJsonData(personFormId, updateList);
log.info("批量审批记录 {} 同步更新了 {} 条外协人员记录的审批状态", dataId, updateList.size());
}
}
/**
* 根据审批状态码获取对应的描述
*/
private String getApproveStatusName(Integer approveStatus) {
if (approveStatus == null) {
return ApproveStatusEnum.UNAPPROVED.getDesc();
}
for (ApproveStatusEnum statusEnum : ApproveStatusEnum.values()) {
if (statusEnum.getCode() == approveStatus) {
return statusEnum.getDesc();
}
}
return ApproveStatusEnum.UNAPPROVED.getDesc();
}
}

View File

@@ -9,8 +9,6 @@ import com.jeelowcode.service.bpm.controller.vo.instance.BpmProcessInstanceRespV
import com.jeelowcode.service.bpm.service.IBpmProcessInstanceService; import com.jeelowcode.service.bpm.service.IBpmProcessInstanceService;
import com.jeelowcode.tool.framework.datapermission.core.annotation.DataPermission; import com.jeelowcode.tool.framework.datapermission.core.annotation.DataPermission;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.impl.persistence.entity.ExecutionEntityImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.annotation.Resource; import javax.annotation.Resource;
@@ -25,10 +23,7 @@ public class BillApproveStatusService {
@Resource @Resource
private IDbformDataService dbformDataService; private IDbformDataService dbformDataService;
public void afterSubmit(String processInstanceId){ public void afterSubmit(String processInstanceId){
Map<String,Object> map = new HashMap<>();
//流程实例id //流程实例id
BpmProcessInstanceRespVO vo = SpringUtils.getBean(IBpmProcessInstanceService.class).getProcessInstanceVO(processInstanceId); BpmProcessInstanceRespVO vo = SpringUtils.getBean(IBpmProcessInstanceService.class).getProcessInstanceVO(processInstanceId);
//获取到的自定义表单数据id //获取到的自定义表单数据id
@@ -43,11 +38,14 @@ public class BillApproveStatusService {
json.put("ProcessInstanceId", processInstanceId); json.put("ProcessInstanceId", processInstanceId);
dbformDataService.update(formEntity.getTableName(),id,json); dbformDataService.update(formEntity.getTableName(),id,json);
// 如果是批量审批表,同步更新外协人员状态
if ("lc_outside_batch_approval".equals(formEntity.getTableName())) {
updateOutsidePersonStatusSafely(formEntity.getTableName(), id, json);
}
} }
public void afterApproved(String processInstanceId){ public void afterApproved(String processInstanceId){
Map<String,Object> map = new HashMap<>();
//流程实例id //流程实例id
BpmProcessInstanceRespVO vo = SpringUtils.getBean(IBpmProcessInstanceService.class).getProcessInstanceVO(processInstanceId); BpmProcessInstanceRespVO vo = SpringUtils.getBean(IBpmProcessInstanceService.class).getProcessInstanceVO(processInstanceId);
//获取到的自定义表单数据id //获取到的自定义表单数据id
@@ -61,11 +59,14 @@ public class BillApproveStatusService {
json.put(ApproveStatusEnum.nameField, ApproveStatusEnum.APPROVED.getDesc()); json.put(ApproveStatusEnum.nameField, ApproveStatusEnum.APPROVED.getDesc());
dbformDataService.update(formEntity.getTableName(),id,json); dbformDataService.update(formEntity.getTableName(),id,json);
// 如果是批量审批表,同步更新外协人员状态
if ("lc_outside_batch_approval".equals(formEntity.getTableName())) {
updateOutsidePersonStatusSafely(formEntity.getTableName(), id, json);
}
} }
public void afterRejected(String processInstanceId){ public void afterRejected(String processInstanceId){
Map<String,Object> map = new HashMap<>();
//流程实例id //流程实例id
BpmProcessInstanceRespVO vo = SpringUtils.getBean(IBpmProcessInstanceService.class).getProcessInstanceVO(processInstanceId); BpmProcessInstanceRespVO vo = SpringUtils.getBean(IBpmProcessInstanceService.class).getProcessInstanceVO(processInstanceId);
//获取到的自定义表单数据id //获取到的自定义表单数据id
@@ -79,12 +80,15 @@ public class BillApproveStatusService {
json.put(ApproveStatusEnum.nameField, ApproveStatusEnum.REJECTED.getDesc()); json.put(ApproveStatusEnum.nameField, ApproveStatusEnum.REJECTED.getDesc());
dbformDataService.update(formEntity.getTableName(),id,json); dbformDataService.update(formEntity.getTableName(),id,json);
// 如果是批量审批表,同步更新外协人员状态
if ("lc_outside_batch_approval".equals(formEntity.getTableName())) {
updateOutsidePersonStatusSafely(formEntity.getTableName(), id, json);
}
} }
public void afterCancel(String processInstanceId){ public void afterCancel(String processInstanceId){
Map<String,Object> map = new HashMap<>();
//流程实例id //流程实例id
BpmProcessInstanceRespVO vo = SpringUtils.getBean(IBpmProcessInstanceService.class).getProcessInstanceVO(processInstanceId); BpmProcessInstanceRespVO vo = SpringUtils.getBean(IBpmProcessInstanceService.class).getProcessInstanceVO(processInstanceId);
//获取到的自定义表单数据id //获取到的自定义表单数据id
@@ -98,5 +102,41 @@ public class BillApproveStatusService {
json.put(ApproveStatusEnum.nameField, ApproveStatusEnum.UNAPPROVED.getDesc()); json.put(ApproveStatusEnum.nameField, ApproveStatusEnum.UNAPPROVED.getDesc());
dbformDataService.update(formEntity.getTableName(),id,json); dbformDataService.update(formEntity.getTableName(),id,json);
// 如果是批量审批表,同步更新外协人员状态
if ("lc_outside_batch_approval".equals(formEntity.getTableName())) {
updateOutsidePersonStatusSafely(formEntity.getTableName(), id, json);
}
}
/**
* 安全地调用 IOutsideBatchApprovalService 的方法,避免循环依赖
* 使用反射和 SpringUtils 延迟获取 Bean避免编译时依赖
*/
private void updateOutsidePersonStatusSafely(String tableName, String id, Map<String, Object> dataMap) {
try {
// 使用反射获取接口类,避免编译时依赖
Class<?> serviceClass = Class.forName("com.jeelowcode.module.biz.service.IOutsideBatchApprovalService");
// 通过 SpringUtils 获取 Bean使用 Bean 名称,默认是类名首字母小写)
Object service = SpringUtils.getBean("outsideBatchApprovalService");
if (service == null) {
// 如果通过名称获取不到,尝试通过类获取
service = SpringUtils.getBean(serviceClass);
}
if (service != null) {
// 反射调用方法
java.lang.reflect.Method method = serviceClass.getMethod("updateOutsidePersonStatus", String.class, String.class, Map.class);
method.invoke(service, tableName, id, dataMap);
log.debug("成功调用 IOutsideBatchApprovalService.updateOutsidePersonStatus");
} else {
log.warn("未找到 IOutsideBatchApprovalService Bean跳过同步外协人员状态");
}
} catch (ClassNotFoundException e) {
log.debug("IOutsideBatchApprovalService 类不存在,可能未加载该模块,跳过同步外协人员状态");
} catch (NoSuchMethodException e) {
log.warn("IOutsideBatchApprovalService.updateOutsidePersonStatus 方法不存在", e);
} catch (Exception e) {
log.error("调用 IOutsideBatchApprovalService.updateOutsidePersonStatus 失败", e);
}
} }
} }