外协人员excel导入优化
This commit is contained in:
203
SQL/202512/20251218/lc_outside_batch_approval.sql
Normal file
203
SQL/202512/20251218/lc_outside_batch_approval.sql
Normal file
File diff suppressed because one or more lines are too long
938
SQL/202512/20251218/lc_outside_person.sql
Normal file
938
SQL/202512/20251218/lc_outside_person.sql
Normal file
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
|
||||
package com.jeelowcode.core.framework.service;
|
||||
|
||||
import com.jeelowcode.core.framework.service.impl.PersonInfoServiceImpl;
|
||||
import com.jeelowcode.framework.utils.tool.spring.SpringUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@@ -8,7 +9,8 @@ public class ExcelExtendFactory {
|
||||
|
||||
public IExcelImportService getExcelImportService(String tableName) {
|
||||
if(tableName.toLowerCase().equals("lc_outside_person")){
|
||||
return new PersonInfoServiceImpl();
|
||||
// 从Spring容器中获取实例,确保依赖注入正常
|
||||
return SpringUtils.getBean(PersonInfoServiceImpl.class);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
|
||||
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.ExcelTemplateModel;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
@@ -34,4 +35,6 @@ public interface IExcelService {
|
||||
* 处理临时库
|
||||
*/
|
||||
void handleTempTable(ServletRequestAttributes sra,Long dbFormId, Long fieldId);
|
||||
|
||||
ExcelImportDataDictModel formatExcelImportDataList(Long dbformId);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
//字典集合
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.jeelowcode.framework.utils.model.ResultDataModel;
|
||||
import com.jeelowcode.framework.utils.tool.spring.SpringUtils;
|
||||
import com.jeelowcode.framework.utils.utils.FuncBase;
|
||||
import com.jeelowcode.framework.utils.utils.JeeLowCodeUtils;
|
||||
import com.jeelowcode.tool.framework.datapermission.core.annotation.DataPermission;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.sf.jsqlparser.JSQLParserException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -685,6 +686,7 @@ public class FrameServiceImpl implements IFrameService {
|
||||
}
|
||||
|
||||
//保存导入数据
|
||||
@DataPermission(enable = false) // 关闭数据权限,避免只查看自己时,查询不到部门。
|
||||
@Override
|
||||
public ExecuteEnhanceModel saveImportData(Long dbFormId, Map<String, Object> params) {
|
||||
String duplicateType = FuncBase.getMap2Str(params, JeeLowCodeConstant.IMPORT_DUPLICATE_TYPE);
|
||||
|
||||
@@ -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.entity.ExcelFileDataEntity;
|
||||
import com.jeelowcode.core.framework.entity.FormEntity;
|
||||
import com.jeelowcode.core.framework.service.IExcelFileDataService;
|
||||
import com.jeelowcode.core.framework.service.IExcelImportService;
|
||||
import com.jeelowcode.core.framework.service.IFormService;
|
||||
import com.jeelowcode.core.framework.service.IFrameService;
|
||||
import com.jeelowcode.core.framework.entity.FormFieldEntity;
|
||||
import com.jeelowcode.core.framework.params.model.ExcelImportDataDictModel;
|
||||
import com.jeelowcode.core.framework.service.*;
|
||||
import com.jeelowcode.framework.utils.enums.JeeLowCodeFieldTypeEnum;
|
||||
import com.jeelowcode.core.framework.utils.Func;
|
||||
import com.jeelowcode.core.framework.utils.FuncWeb;
|
||||
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.stereotype.Service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -32,45 +36,311 @@ public class PersonInfoServiceImpl implements IExcelImportService {
|
||||
@Autowired
|
||||
private IFrameService frameService;
|
||||
|
||||
@Autowired
|
||||
private IExcelService excelService;
|
||||
|
||||
@Autowired
|
||||
private IFormService formService;
|
||||
|
||||
@Override
|
||||
public void importExcelCheck(ButtonParamImport buttonParam) {
|
||||
|
||||
Map<String, Object> params =new HashMap<>();
|
||||
params.put(ParamEnum.PAGE_NO.getCode(),1);
|
||||
params.put(ParamEnum.PAGE_SIZE.getCode(),1000);
|
||||
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
|
||||
public void importExcelDataUpdate(ButtonParamImport buttonParam) {
|
||||
// Map<String, Object> params =new HashMap<>();
|
||||
// params.put(ParamEnum.PAGE_NO.getCode(),1);
|
||||
// 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> map : buttonParam.getDataMapList()){
|
||||
// if(map.containsKey("supplierName")){
|
||||
// Map<String, Object> depMap = model.getRecords().stream().filter(t->t.get("full_name").equals(map.get("supplierName"))).findFirst().orElse(null);
|
||||
// if(Objects.nonNull(depMap)){
|
||||
// map.put("supplierId",depMap.get("id"));
|
||||
// }else {
|
||||
// throw new JeeLowCodeException("供应商:"+map.get("supplierName") + "不存在");
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// 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)){
|
||||
// map.put("demandId",depMap.get("id"));
|
||||
// }else {
|
||||
// throw new JeeLowCodeException("用人单位:"+map.get("demandName") + "不存在");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if(CollectionUtil.isEmpty(buttonParam.getDataMapList())){
|
||||
return;
|
||||
}
|
||||
|
||||
// 遍历数据列表,提取身份证信息
|
||||
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();
|
||||
// 提取身份证信息
|
||||
IdCardInfo idCardInfo = extractIdCardInfo(cardNo);
|
||||
if(idCardInfo != null){
|
||||
// 设置出生日期
|
||||
if(idCardInfo.getBirthDate() != null){
|
||||
dataMap.put("birthday", idCardInfo.getBirthDate());
|
||||
}
|
||||
// 设置年龄
|
||||
if(idCardInfo.getAge() != null){
|
||||
dataMap.put("personAge", idCardInfo.getAge());
|
||||
}
|
||||
// 设置性别("男"或"女")
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +45,19 @@ public class CustomSheetWriteHandler implements SheetWriteHandler {
|
||||
}
|
||||
|
||||
for (Map.Entry<Integer, List<String>> entry : dropDownData.entrySet()){
|
||||
if(entry.getValue().size()>=10){
|
||||
String[] selectValues = entry.getValue().toArray(new String[entry.getValue().size()]);
|
||||
List<String> values = entry.getValue();
|
||||
// 计算下拉框所有选项的字符总数(包括分隔符逗号)
|
||||
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 = writeWorkbookHolder.getWorkbook();
|
||||
|
||||
@@ -110,15 +110,25 @@ public class RowFormatSetTextHandler implements CellWriteHandler {
|
||||
|
||||
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);
|
||||
if (dropdownOptionsArray.length < 10) {
|
||||
DataValidationConstraint constraint;
|
||||
// 如果字符总数超过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);
|
||||
} else {
|
||||
// 联动到另外一个 sheet
|
||||
//这里如果识别到大于等于10行不管数据量有多少
|
||||
constraint = helper.createFormulaListConstraint("hidden"+firstCol+"!$A$1:$A$"+dropdownOptionList.size());
|
||||
}
|
||||
|
||||
// 设置下拉列表应用的单元格区域,例如第2行到最后一行的第2列
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,6 @@ import com.jeelowcode.service.bpm.controller.vo.instance.BpmProcessInstanceRespV
|
||||
import com.jeelowcode.service.bpm.service.IBpmProcessInstanceService;
|
||||
import com.jeelowcode.tool.framework.datapermission.core.annotation.DataPermission;
|
||||
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 javax.annotation.Resource;
|
||||
@@ -25,10 +23,7 @@ public class BillApproveStatusService {
|
||||
@Resource
|
||||
private IDbformDataService dbformDataService;
|
||||
|
||||
|
||||
public void afterSubmit(String processInstanceId){
|
||||
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
//流程实例id
|
||||
BpmProcessInstanceRespVO vo = SpringUtils.getBean(IBpmProcessInstanceService.class).getProcessInstanceVO(processInstanceId);
|
||||
//获取到的自定义表单数据id
|
||||
@@ -42,12 +37,15 @@ public class BillApproveStatusService {
|
||||
json.put(ApproveStatusEnum.nameField, ApproveStatusEnum.APPROVING.getDesc());
|
||||
json.put("ProcessInstanceId", processInstanceId);
|
||||
dbformDataService.update(formEntity.getTableName(),id,json);
|
||||
|
||||
// 如果是批量审批表,同步更新外协人员状态
|
||||
if ("lc_outside_batch_approval".equals(formEntity.getTableName())) {
|
||||
updateOutsidePersonStatusSafely(formEntity.getTableName(), id, json);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void afterApproved(String processInstanceId){
|
||||
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
//流程实例id
|
||||
BpmProcessInstanceRespVO vo = SpringUtils.getBean(IBpmProcessInstanceService.class).getProcessInstanceVO(processInstanceId);
|
||||
//获取到的自定义表单数据id
|
||||
@@ -60,12 +58,15 @@ public class BillApproveStatusService {
|
||||
json.put(ApproveStatusEnum.codeField, ApproveStatusEnum.APPROVED.getCode());
|
||||
json.put(ApproveStatusEnum.nameField, ApproveStatusEnum.APPROVED.getDesc());
|
||||
dbformDataService.update(formEntity.getTableName(),id,json);
|
||||
|
||||
// 如果是批量审批表,同步更新外协人员状态
|
||||
if ("lc_outside_batch_approval".equals(formEntity.getTableName())) {
|
||||
updateOutsidePersonStatusSafely(formEntity.getTableName(), id, json);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void afterRejected(String processInstanceId){
|
||||
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
//流程实例id
|
||||
BpmProcessInstanceRespVO vo = SpringUtils.getBean(IBpmProcessInstanceService.class).getProcessInstanceVO(processInstanceId);
|
||||
//获取到的自定义表单数据id
|
||||
@@ -78,13 +79,16 @@ public class BillApproveStatusService {
|
||||
json.put(ApproveStatusEnum.codeField, ApproveStatusEnum.REJECTED.getCode());
|
||||
json.put(ApproveStatusEnum.nameField, ApproveStatusEnum.REJECTED.getDesc());
|
||||
dbformDataService.update(formEntity.getTableName(),id,json);
|
||||
|
||||
// 如果是批量审批表,同步更新外协人员状态
|
||||
if ("lc_outside_batch_approval".equals(formEntity.getTableName())) {
|
||||
updateOutsidePersonStatusSafely(formEntity.getTableName(), id, json);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void afterCancel(String processInstanceId){
|
||||
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
//流程实例id
|
||||
BpmProcessInstanceRespVO vo = SpringUtils.getBean(IBpmProcessInstanceService.class).getProcessInstanceVO(processInstanceId);
|
||||
//获取到的自定义表单数据id
|
||||
@@ -97,6 +101,42 @@ public class BillApproveStatusService {
|
||||
json.put(ApproveStatusEnum.codeField, ApproveStatusEnum.UNAPPROVED.getCode());
|
||||
json.put(ApproveStatusEnum.nameField, ApproveStatusEnum.UNAPPROVED.getDesc());
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user