更改批量设置mealcard逻辑、导入数据加密、数据映射

This commit is contained in:
Qi 2025-06-05 21:23:07 +08:00
parent 2770ff5cf9
commit 49dddc4aaf
5 changed files with 221 additions and 41 deletions

View File

@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.*; import java.util.*;
import java.util.function.Function;
/** /**
* @Description: Controller基类 * @Description: Controller基类
@ -292,36 +293,142 @@ public class JeecgController<T, S extends IService<T>> {
* @param response * @param response
* @return * @return
*/ */
// protected Result<?> importExcel(HttpServletRequest request, HttpServletResponse response, Class<T> clazz) {
// MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
// Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
// for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
// // 获取上传文件对象
// MultipartFile file = entity.getValue();
// ImportParams params = new ImportParams();
// params.setTitleRows(2);
// params.setHeadRows(1);
// params.setNeedSave(true);
// try {
// List<T> list = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params);
// //update-begin-author:taoyan date:20190528 for:批量插入数据
// long start = System.currentTimeMillis();
// service.saveBatch(list);
// //400条 saveBatch消耗时间1592毫秒 循环插入消耗时间1947毫秒
// //1200条 saveBatch消耗时间3687毫秒 循环插入消耗时间5212毫秒
// log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
// //update-end-author:taoyan date:20190528 for:批量插入数据
// return Result.ok("文件导入成功!数据行数:" + list.size());
// } catch (Exception e) {
// //update-begin-author:taoyan date:20211124 for: 导入数据重复增加提示
// String msg = e.getMessage();
// log.error(msg, e);
// if(msg!=null && msg.indexOf("Duplicate entry")>=0){
// return Result.error("文件导入失败:有重复数据!");
// }else{
// return Result.error("文件导入失败:" + e.getMessage());
// }
// //update-end-author:taoyan date:20211124 for: 导入数据重复增加提示
// } finally {
// try {
// file.getInputStream().close();
// } catch (IOException e) {
// e.printStackTrace();
// }
// }
// }
// return Result.error("文件导入失败!");
// }
protected Result<?> importExcel(HttpServletRequest request, HttpServletResponse response, Class<T> clazz) { protected Result<?> importExcel(HttpServletRequest request, HttpServletResponse response, Class<T> clazz) {
MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multipartRequest.getFileMap(); Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) { for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
// 获取上传文件对象
MultipartFile file = entity.getValue(); MultipartFile file = entity.getValue();
ImportParams params = new ImportParams(); ImportParams params = new ImportParams();
params.setTitleRows(2); params.setTitleRows(2);
params.setHeadRows(1); params.setHeadRows(1);
params.setNeedSave(true); params.setNeedSave(true);
try { try {
List<T> list = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params); List<T> list = ExcelImportUtil.importExcel(file.getInputStream(), clazz, params);
//update-begin-author:taoyan date:20190528 for:批量插入数据
// === 加密敏感字段 ===
for (T item : list) {
try {
// 银行卡字段加密
Field pyCardField = null;
try {
pyCardField = item.getClass().getDeclaredField("pyCard");
} catch (NoSuchFieldException ignored) {}
if (pyCardField != null) {
pyCardField.setAccessible(true);
String value = (String) pyCardField.get(item);
if (value != null && !value.isEmpty()) {
String encryptedValue = JasyptUtil.encrypt(value, "bigdata");
pyCardField.set(item, encryptedValue);
}
}
// 身份证字段加密
Field identityIdField = null;
try {
identityIdField = item.getClass().getDeclaredField("identityId");
} catch (NoSuchFieldException ignored) {}
if (identityIdField != null) {
identityIdField.setAccessible(true);
String value = (String) identityIdField.get(item);
if (value != null && !value.isEmpty()) {
String encryptedValue = JasyptUtil.encrypt(value, "bigdata");
identityIdField.set(item, encryptedValue);
}
}
// ===== 状态描述反向映射 =====
// 性别反向映射
applyReverseMapping(item, "sexDescription", "sex", StatusMappingUtil::reverseMapSex);
// 车辆状态反向映射
applyReverseMapping(item, "carStatusDescription", "carStatus", StatusMappingUtil::reverseMapCarStatus);
// 住宿状态反向映射
applyReverseMapping(item, "dormitoryStatusDescription", "dormitoryStatus", StatusMappingUtil::reverseMapDormitoryStatus);
// 一般状态反向映射
applyReverseMapping(item, "statusDescription", "status", StatusMappingUtil::reverseMapStatus);
// 宿舍名称反查 ID
// Field dormNameField = getField(item, "dormitoryName");
// Field dormIdField = getField(item, "dormitoryId");
// if (dormNameField != null && dormIdField != null) {
// String dormName = (String) dormNameField.get(item);
// if (dormName != null && !dormName.isEmpty()) {
// dormIdField.set(item, nameResolverService.getDormitoryId(dormName));
// }
// }
//
// // 组名称反查 ID
// Field groupNameField = getField(item, "groupName");
// Field groupIdField = getField(item, "groupId");
// if (groupNameField != null && groupIdField != null) {
// String groupName = (String) groupNameField.get(item);
// if (groupName != null && !groupName.isEmpty()) {
// groupIdField.set(item, nameResolverService.getGroupId(groupName));
// }
// }
} catch (IllegalAccessException e) {
throw new RuntimeException("加密字段处理失败", e);
}
}
long start = System.currentTimeMillis(); long start = System.currentTimeMillis();
service.saveBatch(list); service.saveBatch(list);
//400条 saveBatch消耗时间1592毫秒 循环插入消耗时间1947毫秒
//1200条 saveBatch消耗时间3687毫秒 循环插入消耗时间5212毫秒
log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒"); log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
//update-end-author:taoyan date:20190528 for:批量插入数据
return Result.ok("文件导入成功!数据行数:" + list.size()); return Result.ok("文件导入成功!数据行数:" + list.size());
} catch (Exception e) { } catch (Exception e) {
//update-begin-author:taoyan date:20211124 for: 导入数据重复增加提示
String msg = e.getMessage(); String msg = e.getMessage();
log.error(msg, e); log.error(msg, e);
if(msg!=null && msg.indexOf("Duplicate entry")>=0){ if (msg != null && msg.contains("Duplicate entry")) {
return Result.error("文件导入失败:有重复数据!"); return Result.error("文件导入失败:有重复数据!");
}else{ } else {
return Result.error("文件导入失败:" + e.getMessage()); return Result.error("文件导入失败:" + msg);
} }
//update-end-author:taoyan date:20211124 for: 导入数据重复增加提示
} finally { } finally {
try { try {
file.getInputStream().close(); file.getInputStream().close();
@ -332,4 +439,28 @@ public class JeecgController<T, S extends IService<T>> {
} }
return Result.error("文件导入失败!"); return Result.error("文件导入失败!");
} }
private Field getField(Object obj, String fieldName) {
try {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (NoSuchFieldException e) {
return null;
}
}
private void applyReverseMapping(Object item, String descFieldName, String codeFieldName, Function<String, Integer> mapper) throws IllegalAccessException {
Field descField = getField(item, descFieldName);
Field codeField = getField(item, codeFieldName);
if (descField != null && codeField != null) {
String desc = (String) descField.get(item);
if (desc != null && !desc.isEmpty()) {
Integer code = mapper.apply(desc);
codeField.set(item, code);
}
}
}
} }

View File

@ -3,4 +3,8 @@ package org.jeecg.common.system.base.service;
public interface NameResolverService { public interface NameResolverService {
String getDormitoryName(String dormitoryId); String getDormitoryName(String dormitoryId);
String getGroupName(String groupId); String getGroupName(String groupId);
Object getDormitoryId(String dormName);
Object getGroupId(String groupName);
} }

View File

@ -24,4 +24,30 @@ public class StatusMappingUtil {
if (status == null) return ""; if (status == null) return "";
return status == 0 ? "已报到" : "未报到"; return status == 0 ? "已报到" : "未报到";
} }
// ===== 反向映射 =====
public static Integer reverseMapSex(String desc) {
if ("".equals(desc)) return 0;
if ("".equals(desc)) return 1;
return null;
}
public static Integer reverseMapCarStatus(String desc) {
if ("".equals(desc)) return 1;
if ("".equals(desc)) return 0;
return null;
}
public static Integer reverseMapDormitoryStatus(String desc) {
if ("".equals(desc)) return 1;
if ("".equals(desc)) return 0;
return null;
}
public static Integer reverseMapStatus(String desc) {
if ("已报到".equals(desc)) return 0;
if ("未报到".equals(desc)) return 1;
return null;
}
} }

View File

@ -412,18 +412,18 @@ public class CeesWaiTeacherServiceImpl extends ServiceImpl<CeesWaiTeacherMapper,
throw new IllegalArgumentException("max 参数类型错误"); throw new IllegalArgumentException("max 参数类型错误");
} }
// 获取所有已有的 mealCard构建占用集合 // 获取所有已有的 mealCard 数据
List<CeesWaiTeacher> allTeachers = ceesWaiTeacherMapper.selectList(null); List<CeesWaiTeacher> allTeachers = ceesWaiTeacherMapper.selectList(null);
Set<String> usedCards = allTeachers.stream() Map<String, String> teacherIdToCard = allTeachers.stream()
.map(CeesWaiTeacher::getMealCard)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
// 获取已存在 mealCard 的用户 ID
Set<String> alreadyHasCardIds = allTeachers.stream()
.filter(t -> t.getMealCard() != null && !t.getMealCard().trim().isEmpty()) .filter(t -> t.getMealCard() != null && !t.getMealCard().trim().isEmpty())
.map(CeesWaiTeacher::getId) .collect(Collectors.toMap(CeesWaiTeacher::getId, CeesWaiTeacher::getMealCard));
.collect(Collectors.toSet());
// 卡号 -> 人员ID 的映射方便夺卡
Map<String, String> cardToTeacherId = allTeachers.stream()
.filter(t -> t.getMealCard() != null && !t.getMealCard().trim().isEmpty())
.collect(Collectors.toMap(CeesWaiTeacher::getMealCard, CeesWaiTeacher::getId));
Set<String> usedCards = new HashSet<>(cardToTeacherId.keySet());
int totalUpdatedLocal = 0; int totalUpdatedLocal = 0;
List<String> failedIdsLocal = new ArrayList<>(); List<String> failedIdsLocal = new ArrayList<>();
@ -432,35 +432,44 @@ public class CeesWaiTeacherServiceImpl extends ServiceImpl<CeesWaiTeacherMapper,
int currentCard = min; int currentCard = min;
for (String id : ids) { for (String id : ids) {
// 如果用户已有 mealCard跳过
if (alreadyHasCardIds.contains(id)) {
continue;
}
boolean assigned = false; boolean assigned = false;
// 查找下一个未被占用的卡号
while (currentCard <= max) { while (currentCard <= max) {
String formattedCard = String.format("%03d", currentCard); String formattedCard = String.format("%03d", currentCard);
if (!usedCards.contains(formattedCard)) {
try {
LambdaUpdateWrapper<CeesWaiTeacher> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(CeesWaiTeacher::getId, id)
.set(CeesWaiTeacher::getMealCard, formattedCard);
int affectedRows = ceesWaiTeacherMapper.update(null, updateWrapper); // 如果已被占用则从原用户手中夺取
if (affectedRows > 0) { if (usedCards.contains(formattedCard)) {
totalUpdatedLocal++; String previousHolderId = cardToTeacherId.get(formattedCard);
usedCards.add(formattedCard); if (!Objects.equals(previousHolderId, id)) {
assigned = true; // 夺卡逻辑把旧用户的卡号置空
} LambdaUpdateWrapper<CeesWaiTeacher> clearWrapper = new LambdaUpdateWrapper<>();
} catch (Exception e) { clearWrapper.eq(CeesWaiTeacher::getId, previousHolderId)
// 忽略异常进入失败处理 .set(CeesWaiTeacher::getMealCard, null);
ceesWaiTeacherMapper.update(null, clearWrapper);
usedCards.remove(formattedCard);
cardToTeacherId.remove(formattedCard);
} }
currentCard++;
break;
} }
try {
// 分配卡号给当前用户无论其是否已有
LambdaUpdateWrapper<CeesWaiTeacher> updateWrapper = new LambdaUpdateWrapper<>();
updateWrapper.eq(CeesWaiTeacher::getId, id)
.set(CeesWaiTeacher::getMealCard, formattedCard);
int affectedRows = ceesWaiTeacherMapper.update(null, updateWrapper);
if (affectedRows > 0) {
totalUpdatedLocal++;
usedCards.add(formattedCard);
cardToTeacherId.put(formattedCard, id);
assigned = true;
}
} catch (Exception e) {
// 异常处理
}
currentCard++; currentCard++;
break; // 成功或失败后跳出当前循环
} }
if (!assigned) { if (!assigned) {

View File

@ -32,4 +32,14 @@ public class NameResolverImpl implements NameResolverService {
CeesGroup group = groupService.getById(groupId); CeesGroup group = groupService.getById(groupId);
return group != null ? group.getName() : ""; return group != null ? group.getName() : "";
} }
@Override
public Object getDormitoryId(String dormName) {
return null;
}
@Override
public Object getGroupId(String groupName) {
return null;
}
} }