From e5a7b49bc1f334ec6b4c88ca9f30deeca20d3460 Mon Sep 17 00:00:00 2001 From: zhangrui Date: Mon, 29 Jun 2026 11:01:59 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8D=97=E5=A4=A7=E4=B8=89=E5=8D=81=E5=B9=B4?= =?UTF-8?q?=E6=95=99=E8=81=8C=E5=B7=A5=E7=96=97=E4=BC=91=E5=85=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../base/sms/impl/ncu/SmsNcuServiceImpl.java | 6 +- .../app/sys/controller/SysHomeController.java | 2 +- ...achTourBranchUserAssignmentController.java | 36 ++++-- .../ThirtyTeachTourLedgerController.java | 68 ++++++++--- .../ThirtyTeachTourMySignupController.java | 4 +- ...achTourSchoolUserAssignmentController.java | 33 ++++-- .../ThirtyTeachTourSignupController.java | 6 +- .../models/ThirtyTeachTourLedger.java | 7 +- .../models/ThirtyTeachTourUserAssignment.java | 7 +- .../ThirtyTeachTourUserAssignmentService.java | 34 ++++-- ...rtyTeachTourUserAssignmentServiceImpl.java | 92 +++++++++++---- .../thirty_teach_tour_add_photo_files.sql | 6 +- .../thirty_teach_tour_ledger_create.sql | 3 +- ...irty_teach_tour_user_assignment_create.sql | 3 +- .../branchUserAssignment/index.html | 101 ++++++++++++---- .../schoolUserAssignment/index.html | 109 +++++++++++++----- 16 files changed, 388 insertions(+), 129 deletions(-) diff --git a/src/main/java/com/budwk/app/base/sms/impl/ncu/SmsNcuServiceImpl.java b/src/main/java/com/budwk/app/base/sms/impl/ncu/SmsNcuServiceImpl.java index d50b92ec..5ccaebf4 100644 --- a/src/main/java/com/budwk/app/base/sms/impl/ncu/SmsNcuServiceImpl.java +++ b/src/main/java/com/budwk/app/base/sms/impl/ncu/SmsNcuServiceImpl.java @@ -40,9 +40,9 @@ public class SmsNcuServiceImpl implements SmsService { @Inject private Dao dao; - private static final String SEND_MSG_URL = ""; - private static final String APP_ID = ""; - private static final String TEMPLATE_ID = ""; + private static final String SEND_MSG_URL = "https://poa.ncu.edu.cn/apis/messagecenter/v1/poaMessage/messageSend"; + private static final String APP_ID = "72e34a101d3011f1a74cbae5193504f4"; + private static final String TEMPLATE_ID = "MT1773223005000"; @Override public void sendSingleMessage(String loginName, String content) { diff --git a/src/main/java/com/budwk/app/sys/controller/SysHomeController.java b/src/main/java/com/budwk/app/sys/controller/SysHomeController.java index a4579827..21a79ead 100644 --- a/src/main/java/com/budwk/app/sys/controller/SysHomeController.java +++ b/src/main/java/com/budwk/app/sys/controller/SysHomeController.java @@ -329,7 +329,7 @@ public class SysHomeController { rows.add(NutMap.NEW() .addv("id", "thirtyTeachTour-" + setting.getId()) .addv("year", setting.getYear()) - .addv("title", setting.getYear() + "30年教龄疗休养") + .addv("title", setting.getYear() + "服务南大三十年") .addv("imageUrl", imageUrl) .addv("href", "/platform/thirtyTeachTour/signup") .addv("startCorner", "rightTop") diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourBranchUserAssignmentController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourBranchUserAssignmentController.java index c480ff0a..10d45d5a 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourBranchUserAssignmentController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourBranchUserAssignmentController.java @@ -79,9 +79,11 @@ public class ThirtyTeachTourBranchUserAssignmentController { @At @SaCheckPermission("thirtyTeachTour.branchUserAssignment.assign") public Result candidatePageData(PageForm pageForm, String settingId, String keyword, @Param("userIds") String userIds, - Boolean retiringSoon) { + String retiringSoon) { + // 候选人员筛选下拉清空时应视为不筛选,避免空值在参数绑定中被误转换为 false。 + Boolean normalizedRetiringSoon = normalizeBooleanFilter(retiringSoon); return Result.success(tourUserAssignmentService.branchCandidatePage(pageForm, settingId, keyword, - parseUserIds(userIds), retiringSoon)); + parseUserIds(userIds), normalizedRetiringSoon)); } /** @@ -137,7 +139,7 @@ public class ThirtyTeachTourBranchUserAssignmentController { @SaCheckPermission("thirtyTeachTour.branchUserAssignment.assign") @SLog(type = "tour", tag = "疗休养分工会人员分配", msg = "保存分工会人员分配") public Result doAssign(String settingId, String matterId, String periodId, String personType, - @Param("userIds") String userIds, String photoFiles, + @Param("userIds") String userIds, String photoFiles, String currentPeriodPhotoFiles, @Param("assignItems") String assignItems) { if (StrUtil.isNotBlank(assignItems)) { List parsedItems; @@ -160,7 +162,7 @@ public class ThirtyTeachTourBranchUserAssignmentController { } try { return Result.success(tourUserAssignmentService.assignBranchUsers(settingId, matterId, periodId, personType, - buildAssignItems(parsedUserIds, photoFiles))); + buildAssignItems(parsedUserIds, photoFiles, currentPeriodPhotoFiles))); } catch (IllegalArgumentException e) { return Result.error(e.getMessage()); } @@ -188,9 +190,10 @@ public class ThirtyTeachTourBranchUserAssignmentController { @Aop(TransAop.READ_COMMITTED) @SaCheckPermission("thirtyTeachTour.branchUserAssignment.selectMatter") @SLog(type = "tour", tag = "疗休养分工会人员分配", msg = "选择分工会分配事项") - public Result selectMatter(String id, String matterId, String photoFiles) { + public Result selectMatter(String id, String matterId, String photoFiles, String currentPeriodPhotoFiles) { try { - return Result.success(tourUserAssignmentService.selectCurrentBranchAssignmentMatter(id, matterId, photoFiles)); + return Result.success(tourUserAssignmentService.selectCurrentBranchAssignmentMatter(id, matterId, + photoFiles, currentPeriodPhotoFiles)); } catch (IllegalArgumentException e) { return Result.error(e.getMessage()); } @@ -203,9 +206,9 @@ public class ThirtyTeachTourBranchUserAssignmentController { @Aop(TransAop.READ_COMMITTED) @SaCheckPermission("thirtyTeachTour.branchUserAssignment.assign") @SLog(type = "tour", tag = "疗休养分工会人员分配", msg = "上传分工会人员分配图片") - public Result updatePhotoFiles(String id, String photoFiles) { + public Result updatePhotoFiles(String id, String photoFiles, String currentPeriodPhotoFiles) { try { - tourUserAssignmentService.updateCurrentBranchAssignmentPhotoFiles(id, photoFiles); + tourUserAssignmentService.updateCurrentBranchAssignmentPhotoFiles(id, photoFiles, currentPeriodPhotoFiles); return Result.success(); } catch (IllegalArgumentException e) { return Result.error(e.getMessage()); @@ -278,15 +281,28 @@ public class ThirtyTeachTourBranchUserAssignmentController { return Lang.isEmpty(list) ? Collections.emptyList() : list; } + /** + * 候选人员布尔筛选兜底;true/false 转成布尔值,空字符串和 null 表示不追加查询条件。 + */ + private Boolean normalizeBooleanFilter(String value) { + if (StrUtil.isBlank(value)) { + return null; + } + return Boolean.parseBoolean(value); + } + /** * 兼容旧的 userIds 入参,把公共图片材料转换成按人员明细的统一 service 入参。 */ - private List buildAssignItems(List userIds, String photoFiles) { + private List buildAssignItems(List userIds, String photoFiles, String currentPeriodPhotoFiles) { if (Lang.isEmpty(userIds)) { return Collections.emptyList(); } List list = new ArrayList<>(); - userIds.forEach(userId -> list.add(NutMap.NEW().addv("userId", userId).addv("photoFiles", photoFiles))); + userIds.forEach(userId -> list.add(NutMap.NEW() + .addv("userId", userId) + .addv("photoFiles", photoFiles) + .addv("currentPeriodPhotoFiles", currentPeriodPhotoFiles))); return list; } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourLedgerController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourLedgerController.java index 372d229d..f3c8066e 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourLedgerController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourLedgerController.java @@ -392,11 +392,17 @@ public class ThirtyTeachTourLedgerController { List rows = queryLedgerExportRows(startYear, endYear, keyword, unionId, lineId, travelPeriod, lineType, directFamilyOnly, overCostOnly); int imageColumnStartIndex = entities.size(); - int maxPhotoCount = maxPhotoCount(rows); - log.info("三十年教龄疗休养台账导出图片列准备:rows={}, maxPhotoCount={}, appDomain={}", - rows.size(), maxPhotoCount, Globals.AppDomain); + int maxPhotoCount = maxPhotoCount(rows, "photoFiles"); + int maxCurrentPeriodPhotoCount = maxPhotoCount(rows, "currentPeriodPhotoFiles"); + int totalImageColumnCount = maxPhotoCount + maxCurrentPeriodPhotoCount; + log.info("三十年教龄疗休养台账导出图片列准备:rows={}, beforePhotoMax={}, currentPeriodPhotoMax={}, appDomain={}", + rows.size(), maxPhotoCount, maxCurrentPeriodPhotoCount, Globals.AppDomain); for (int i = 1; i <= maxPhotoCount; i++) { - ExcelExportEntity imageEntity = new ExcelExportEntity("图片" + i, "photoCell" + i, 18); + ExcelExportEntity imageEntity = new ExcelExportEntity("30年前图片" + i, "photoCell" + i, 18); + entities.add(imageEntity); + } + for (int i = 1; i <= maxCurrentPeriodPhotoCount; i++) { + ExcelExportEntity imageEntity = new ExcelExportEntity("当前时间段图片" + i, "photoCell" + (maxPhotoCount + i), 18); entities.add(imageEntity); } rows.forEach(row -> { @@ -404,7 +410,7 @@ public class ThirtyTeachTourLedgerController { row.put("familyCountText", (familyCount == null ? 0 : familyCount) + "人"); row.put("joinedText", Boolean.TRUE.equals(row.getBoolean("joined")) ? "是" : "否"); row.put("overCostReimbursedText", Boolean.TRUE.equals(row.getBoolean("overCostReimbursed")) ? "是" : "否"); - fillLedgerPhotoRowImages(row, maxPhotoCount); + fillLedgerPhotoRowImages(row, maxPhotoCount, maxCurrentPeriodPhotoCount); }); List> rowImages = snapshotLedgerRowImages(rows); @@ -412,7 +418,7 @@ public class ThirtyTeachTourLedgerController { exportParams.setSheetName("疗休养台账"); exportParams.setType(ExcelType.XSSF); Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, rows); - resizeLedgerPhotoRows(workbook, rowImages.size(), imageColumnStartIndex, maxPhotoCount); + resizeLedgerPhotoRows(workbook, rowImages.size(), imageColumnStartIndex, totalImageColumnCount); int insertedPictureCount = insertLedgerPhotoImages(workbook, rowImages, imageColumnStartIndex); log.info("三十年教龄疗休养台账导出Excel图片写入完成:insertedPictureCount={}, workbookPictureCount={}", insertedPictureCount, workbook.getAllPictures().size()); @@ -422,10 +428,10 @@ public class ThirtyTeachTourLedgerController { /** * 统计本次导出台账中最大的图片数量,用于动态生成图片1、图片2等横向列。 */ - private int maxPhotoCount(List rows) { + private int maxPhotoCount(List rows, String fieldName) { int maxPhotoCount = 0; for (NutMap row : rows) { - maxPhotoCount = Math.max(maxPhotoCount, splitPhotoFiles(row.getString("photoFiles", "")).size()); + maxPhotoCount = Math.max(maxPhotoCount, splitPhotoFiles(row.getString(fieldName, "")).size()); } return maxPhotoCount; } @@ -433,14 +439,23 @@ public class ThirtyTeachTourLedgerController { /** * 将每条台账的图片材料解析为可写入 Excel 的图片对象,图片列文本保持为空,后续由 POI 手动插入图片。 */ - private void fillLedgerPhotoRowImages(NutMap row, int maxPhotoCount) { + private void fillLedgerPhotoRowImages(NutMap row, int maxPhotoCount, int maxCurrentPeriodPhotoCount) { List photoFiles = splitPhotoFiles(row.getString("photoFiles", "")); + List currentPeriodPhotoFiles = splitPhotoFiles(row.getString("currentPeriodPhotoFiles", "")); if (!photoFiles.isEmpty()) { - log.info("三十年教龄疗休养台账图片字段读取:jobNo={}, userName={}, photoCount={}, photoFiles={}", + log.info("三十年教龄疗休养台账30年前图片字段读取:jobNo={}, userName={}, photoCount={}, photoFiles={}", row.getString("jobNo", ""), row.getString("userName", ""), photoFiles.size(), row.getString("photoFiles", "")); } - row.put("photoImages", resolveLedgerImages(row.getString("photoFiles", ""))); - for (int i = 1; i <= maxPhotoCount; i++) { + if (!currentPeriodPhotoFiles.isEmpty()) { + log.info("三十年教龄疗休养台账当前时间段图片字段读取:jobNo={}, userName={}, photoCount={}, photoFiles={}", + row.getString("jobNo", ""), row.getString("userName", ""), currentPeriodPhotoFiles.size(), row.getString("currentPeriodPhotoFiles", "")); + } + // 图片对象按导出列顺序组装:先 30 年前图片,再当前时间段图片,确保同一教职工图片仍在同一行。 + List photoImages = new ArrayList<>(); + photoImages.addAll(resolveLedgerImages(row.getString("photoFiles", ""), 0)); + photoImages.addAll(resolveLedgerImages(row.getString("currentPeriodPhotoFiles", ""), maxPhotoCount)); + row.put("photoImages", photoImages); + for (int i = 1; i <= maxPhotoCount + maxCurrentPeriodPhotoCount; i++) { row.put("photoCell" + i, ""); } } @@ -508,16 +523,17 @@ public class ThirtyTeachTourLedgerController { List images = rowImages.get(rowIndex); for (int photoIndex = 0; photoIndex < images.size(); photoIndex++) { LedgerExportImage image = images.get(photoIndex); + int imageColumnIndex = imageColumnStartIndex + image.columnOffset; int pictureIndex = workbook.addPicture(image.bytes, image.pictureType); ClientAnchor anchor = creationHelper.createClientAnchor(); - anchor.setCol1(imageColumnStartIndex + photoIndex); + anchor.setCol1(imageColumnIndex); anchor.setRow1(excelRowIndex); - anchor.setCol2(imageColumnStartIndex + photoIndex + 1); + anchor.setCol2(imageColumnIndex + 1); anchor.setRow2(excelRowIndex + 1); drawing.createPicture(anchor, pictureIndex); insertedPictureCount++; - log.info("三十年教龄疗休养台账图片写入Excel成功:rowIndex={}, photoIndex={}, fileId={}, bytes={}, pictureType={}", - excelRowIndex, photoIndex + 1, image.fileId, image.bytes.length, image.pictureType); + log.info("三十年教龄疗休养台账图片写入Excel成功:rowIndex={}, columnOffset={}, fileId={}, bytes={}, pictureType={}", + excelRowIndex, image.columnOffset, image.fileId, image.bytes.length, image.pictureType); } } return insertedPictureCount; @@ -527,13 +543,20 @@ public class ThirtyTeachTourLedgerController { * 将台账图片字段解析成可插入 Excel 的图片对象,当前优先支持系统文件下载路径。 */ private List resolveLedgerImages(String photoFiles) { + return resolveLedgerImages(photoFiles, 0); + } + + /** + * 将台账图片字段解析成可插入 Excel 的图片对象,并记录图片列偏移,支持多组图片列分区写入。 + */ + private List resolveLedgerImages(String photoFiles, int columnOffsetStart) { List images = new ArrayList<>(); List photoPaths = splitPhotoFiles(photoFiles); for (int photoIndex = 0; photoIndex < photoPaths.size(); photoIndex++) { String originalPath = photoPaths.get(photoIndex); LedgerExportImage image = resolveLedgerImage(originalPath); if (image != null) { - images.add(image); + images.add(image.withColumnOffset(columnOffsetStart + photoIndex)); } else { log.warn("三十年教龄疗休养台账图片解析失败:photoIndex={}, originalPath={}", photoIndex + 1, originalPath); } @@ -707,12 +730,22 @@ public class ThirtyTeachTourLedgerController { private final String originalPath; private final byte[] bytes; private final int pictureType; + private final int columnOffset; private LedgerExportImage(String fileId, String originalPath, byte[] bytes, int pictureType) { + this(fileId, originalPath, bytes, pictureType, 0); + } + + private LedgerExportImage(String fileId, String originalPath, byte[] bytes, int pictureType, int columnOffset) { this.fileId = fileId; this.originalPath = originalPath; this.bytes = bytes; this.pictureType = pictureType; + this.columnOffset = columnOffset; + } + + private LedgerExportImage withColumnOffset(int columnOffset) { + return new LedgerExportImage(fileId, originalPath, bytes, pictureType, columnOffset); } } @@ -739,6 +772,7 @@ public class ThirtyTeachTourLedgerController { t.lineType, t.signupTime, t.photoFiles, + t.currentPeriodPhotoFiles, IFNULL(f.familyCount, 0) AS familyCount, t.joined, t.overCostReimbursed diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourMySignupController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourMySignupController.java index d6e2dcf1..b5dc5670 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourMySignupController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourMySignupController.java @@ -508,12 +508,14 @@ public class ThirtyTeachTourMySignupController { ledger.setJoined(oldLedger.getJoined()); ledger.setReimbursed(oldLedger.getReimbursed()); ledger.setSignupTime(defaultIfBlank(oldLedger.getSignupTime(), ledger.getSignupTime())); + // 修改报名表单未必提交当前时间段图片,保留旧台账字段,避免回填人员分配时误清空。 + ledger.setCurrentPeriodPhotoFiles(defaultIfBlank(ledger.getCurrentPeriodPhotoFiles(), oldLedger.getCurrentPeriodPhotoFiles())); fillStaffInfo(ledger); tourLedgerService.updateIgnoreNull(ledger); // 报名台账更新后,仅回填已存在的人员分配记录事项信息,不新增记录、不改变分配来源。 tourUserAssignmentService.backfillExistingAssignmentAfterSignup(matter.getSettingId(), matter.getId(), SecurityUtil.getUserId(), - ledger.getBoardingPlace(), ledger.getPhotoFiles()); + ledger.getBoardingPlace(), ledger.getPhotoFiles(), ledger.getCurrentPeriodPhotoFiles()); tourLedgerFamilyService.clear(Cnd.where(ThirtyTeachTourLedgerFamily::getLedgerId, "=", ledger.getId())); tourLedgerDirectRelativeService.clear(Cnd.where(ThirtyTeachTourLedgerDirectRelative::getLedgerId, "=", ledger.getId())); if (Lang.isNotEmpty(familyList)) { diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourSchoolUserAssignmentController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourSchoolUserAssignmentController.java index 8c060682..a4f4b1b7 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourSchoolUserAssignmentController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourSchoolUserAssignmentController.java @@ -103,9 +103,13 @@ public class ThirtyTeachTourSchoolUserAssignmentController { @At @SaCheckPermission("thirtyTeachTour.schoolUserAssignment") public Result candidatePageData(PageForm pageForm, String settingId, String unionId, String keyword, @Param("userIds") String userIds, - Boolean summerJoined, Boolean lastThirtyJoined, Boolean retiringSoon) { + String summerJoined, String lastThirtyJoined, String retiringSoon) { + // 候选人员筛选下拉清空时应视为不筛选,避免空值在参数绑定中被误转换为 false。 + Boolean normalizedSummerJoined = normalizeBooleanFilter(summerJoined); + Boolean normalizedLastThirtyJoined = normalizeBooleanFilter(lastThirtyJoined); + Boolean normalizedRetiringSoon = normalizeBooleanFilter(retiringSoon); return Result.success(tourUserAssignmentService.schoolCandidatePage(pageForm, settingId, unionId, keyword, - parseUserIds(userIds), summerJoined, lastThirtyJoined, retiringSoon)); + parseUserIds(userIds), normalizedSummerJoined, normalizedLastThirtyJoined, normalizedRetiringSoon)); } /** @@ -151,7 +155,8 @@ public class ThirtyTeachTourSchoolUserAssignmentController { @Aop(TransAop.READ_COMMITTED) @SaCheckPermission("thirtyTeachTour.schoolUserAssignment") @SLog(type = "tour", tag = "疗休养校工会人员分配", msg = "保存校工会人员分配") - public Result doAssign(String settingId, String matterId, String personType, @Param("userIds") String userIds, String photoFiles) { + public Result doAssign(String settingId, String matterId, String personType, @Param("userIds") String userIds, + String photoFiles, String currentPeriodPhotoFiles) { List parsedUserIds; try { parsedUserIds = parseUserIds(userIds); @@ -159,7 +164,8 @@ public class ThirtyTeachTourSchoolUserAssignmentController { return Result.error("人员参数错误"); } try { - return Result.success(tourUserAssignmentService.assignSchoolUsers(settingId, matterId, personType, parsedUserIds, photoFiles)); + return Result.success(tourUserAssignmentService.assignSchoolUsers(settingId, matterId, personType, + parsedUserIds, photoFiles, currentPeriodPhotoFiles)); } catch (IllegalArgumentException e) { return Result.error(e.getMessage()); } @@ -193,9 +199,10 @@ public class ThirtyTeachTourSchoolUserAssignmentController { @Aop(TransAop.READ_COMMITTED) @SaCheckPermission("thirtyTeachTour.schoolUserAssignment") @SLog(type = "tour", tag = "疗休养校工会人员分配", msg = "选择校工会分配事项") - public Result selectMatter(String id, String matterId, String photoFiles) { + public Result selectMatter(String id, String matterId, String photoFiles, String currentPeriodPhotoFiles) { try { - return Result.success(tourUserAssignmentService.selectSchoolAssignmentMatter(id, matterId, photoFiles)); + return Result.success(tourUserAssignmentService.selectSchoolAssignmentMatter(id, matterId, + photoFiles, currentPeriodPhotoFiles)); } catch (IllegalArgumentException e) { return Result.error(e.getMessage()); } @@ -208,9 +215,9 @@ public class ThirtyTeachTourSchoolUserAssignmentController { @Aop(TransAop.READ_COMMITTED) @SaCheckPermission("thirtyTeachTour.schoolUserAssignment") @SLog(type = "tour", tag = "疗休养校工会人员分配", msg = "上传校工会人员分配图片") - public Result updatePhotoFiles(String id, String photoFiles) { + public Result updatePhotoFiles(String id, String photoFiles, String currentPeriodPhotoFiles) { try { - tourUserAssignmentService.updateSchoolAssignmentPhotoFiles(id, photoFiles); + tourUserAssignmentService.updateSchoolAssignmentPhotoFiles(id, photoFiles, currentPeriodPhotoFiles); return Result.success(); } catch (IllegalArgumentException e) { return Result.error(e.getMessage()); @@ -280,6 +287,16 @@ public class ThirtyTeachTourSchoolUserAssignmentController { return Lang.isEmpty(list) ? Collections.emptyList() : list; } + /** + * 候选人员布尔筛选兜底;true/false 转成布尔值,空字符串和 null 表示不追加查询条件。 + */ + private Boolean normalizeBooleanFilter(String value) { + if (StrUtil.isBlank(value)) { + return null; + } + return Boolean.parseBoolean(value); + } + /** * 定义人员分配导出字段,保持与页面列表核心字段一致并补充人员基础信息。 */ diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourSignupController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourSignupController.java index acf2caf3..f2307e97 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourSignupController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/controller/ThirtyTeachTourSignupController.java @@ -906,6 +906,8 @@ public class ThirtyTeachTourSignupController { ledger.setJoined(oldLedger.getJoined()); ledger.setReimbursed(oldLedger.getReimbursed()); ledger.setSignupTime(defaultIfBlank(oldLedger.getSignupTime(), ledger.getSignupTime())); + // 修改报名时前端可能未提交当前时间段图片,沿用旧台账值,避免非图片字段修改导致材料丢失。 + ledger.setCurrentPeriodPhotoFiles(defaultIfBlank(ledger.getCurrentPeriodPhotoFiles(), oldLedger.getCurrentPeriodPhotoFiles())); } ledger.setOverCostReimbursed(Boolean.TRUE.equals(ledger.getOverCostReimbursed())); fillStaffInfo(ledger); @@ -920,7 +922,7 @@ public class ThirtyTeachTourSignupController { } // 报名台账落库后,仅回填已存在的人员分配记录事项信息,不新增记录、不改变分配来源。 tourUserAssignmentService.backfillExistingAssignmentAfterSignup(matter.getSettingId(), matter.getId(), SecurityUtil.getUserId(), - ledger.getBoardingPlace(), ledger.getPhotoFiles()); + ledger.getBoardingPlace(), ledger.getPhotoFiles(), ledger.getCurrentPeriodPhotoFiles()); if (Lang.isNotEmpty(familyList)) { familyList.forEach(item -> { item.setLedgerId(ledger.getId()); @@ -1740,6 +1742,8 @@ public class ThirtyTeachTourSignupController { ledger.setUnitName(defaultIfBlank(assignment.getString("unitName", ""), ledger.getUnitName())); ledger.setUnionId(defaultIfBlank(assignment.getString("unionId", ""), ledger.getUnionId())); ledger.setUnionName(defaultIfBlank(assignment.getString("unionName", ""), ledger.getUnionName())); + // 当前时间段图片只来源于人员分配快照;报名提交时同步进台账,避免台账图片材料缺一类。 + ledger.setCurrentPeriodPhotoFiles(defaultIfBlank(assignment.getString("currentPeriodPhotoFiles", ""), ledger.getCurrentPeriodPhotoFiles())); } private void fillLedgerContactFallback(ThirtyTeachTourLedger ledger, NutMap staff) { diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/models/ThirtyTeachTourLedger.java b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/models/ThirtyTeachTourLedger.java index 6d9d7a89..346a4998 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/models/ThirtyTeachTourLedger.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/models/ThirtyTeachTourLedger.java @@ -127,10 +127,15 @@ public class ThirtyTeachTourLedger extends BaseModel implements Serializable { private String boardingPlace; @Column - @Comment("报名图片材料") + @Comment("30年前图片材料") @ColDefine(type = ColType.TEXT) private String photoFiles; + @Column + @Comment("当前时间段图片材料") + @ColDefine(type = ColType.TEXT) + private String currentPeriodPhotoFiles; + @Column @Comment("是否携带家属") @ColDefine(type = ColType.BOOLEAN) diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/models/ThirtyTeachTourUserAssignment.java b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/models/ThirtyTeachTourUserAssignment.java index cfd54e69..87ce45b1 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/models/ThirtyTeachTourUserAssignment.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/models/ThirtyTeachTourUserAssignment.java @@ -78,10 +78,15 @@ public class ThirtyTeachTourUserAssignment extends BaseModel implements Serializ private String boardingPlace; @Column - @Comment("报名图片材料") + @Comment("30年前图片材料") @ColDefine(type = ColType.TEXT) private String photoFiles; + @Column + @Comment("当前时间段图片材料") + @ColDefine(type = ColType.TEXT) + private String currentPeriodPhotoFiles; + @Column @Comment("出行时间段ID") @ColDefine(type = ColType.VARCHAR, width = 32) diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/service/ThirtyTeachTourUserAssignmentService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/service/ThirtyTeachTourUserAssignmentService.java index 854d835b..ab842784 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/service/ThirtyTeachTourUserAssignmentService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/thirtyTeachTour/service/ThirtyTeachTourUserAssignmentService.java @@ -163,11 +163,11 @@ public interface ThirtyTeachTourUserAssignmentService extends BaseService userIds, String photoFiles); + NutMap assignSchoolUsers(String settingId, String matterId, String personType, List userIds, String photoFiles, String currentPeriodPhotoFiles); /** * 保存校工会人员分配,支持每个候选人员单独选择分配线路。 - * assignItems 中每项包含 userId、matterId、photoFiles;matterId 为空时只保存人员分配,不写台账。 + * assignItems 中每项包含 userId、matterId、photoFiles、currentPeriodPhotoFiles;matterId 为空时只保存人员分配,不写台账。 * * @param settingId 疗休养配置ID * @param assignItems 人员和分配线路明细 @@ -183,7 +183,7 @@ public interface ThirtyTeachTourUserAssignmentService extends BaseService assignItems); @@ -289,6 +289,20 @@ public interface ThirtyTeachTourUserAssignmentService extends BaseService userIds, String photoFiles) { + public NutMap assignSchoolUsers(String settingId, String matterId, String personType, List userIds, + String photoFiles, String currentPeriodPhotoFiles) { List distinctUserIds = normalizeUserIds(userIds); if (StrUtil.isBlank(settingId) || Lang.isEmpty(distinctUserIds)) { throw new IllegalArgumentException("请选择疗休养配置和分配人员"); @@ -378,7 +379,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl candidateUsers = listMap(userSql); - fillCandidatePhotoFiles(candidateUsers, normalizePhotoFiles(photoFiles)); + fillCandidatePhotoFiles(candidateUsers, normalizePhotoFiles(photoFiles), normalizePhotoFiles(currentPeriodPhotoFiles)); List assignments = candidateUsers.stream() .map(user -> buildSchoolAssignment(settingId, matterInfo, normalizedPersonType, user)) .collect(Collectors.toList()); @@ -408,6 +409,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl matterByUserId = new HashMap<>(); Map photoFilesByUserId = new HashMap<>(); + Map currentPeriodPhotoFilesByUserId = new HashMap<>(); List userIds = assignItems.stream() .map(item -> item == null ? "" : item.getString("userId", "")) .filter(StrUtil::isNotBlank) @@ -423,6 +425,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl candidateUsers = listMap(userSql); - candidateUsers.forEach(user -> user.put("photoFiles", photoFilesByUserId.get(user.getString("userId", "")))); + candidateUsers.forEach(user -> { + String userId = user.getString("userId", ""); + user.put("photoFiles", photoFilesByUserId.get(userId)); + user.put("currentPeriodPhotoFiles", currentPeriodPhotoFilesByUserId.get(userId)); + }); List assignments = candidateUsers.stream() .map(user -> { @@ -474,7 +481,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl users = Collections.singletonList(fetchAssignmentUserSnapshot(assignment)); checkProxySignupMaxGroupPeople(matterInfo, users); - updateAssignmentMatterSnapshot(id, matterInfo, ThirtyTeachTourUserAssignment.ASSIGN_SOURCE_BRANCH_UNION, photoFiles); + updateAssignmentMatterSnapshot(id, matterInfo, ThirtyTeachTourUserAssignment.ASSIGN_SOURCE_BRANCH_UNION, + photoFiles, currentPeriodPhotoFiles); int ledgerCount = insertProxySignupLedgers(matterInfo, users); return NutMap.NEW().addv("ledgerCount", ledgerCount); } @@ -542,6 +553,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl photoFilesByUserId = new HashMap<>(); + Map currentPeriodPhotoFilesByUserId = new HashMap<>(); List distinctUserIds = assignItems.stream() .map(item -> item == null ? "" : item.getString("userId", "")) .filter(StrUtil::isNotBlank) @@ -557,6 +569,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl candidateUsers = listMap(userSql); - candidateUsers.forEach(user -> user.put("photoFiles", photoFilesByUserId.get(user.getString("userId", "")))); + candidateUsers.forEach(user -> { + String userId = user.getString("userId", ""); + user.put("photoFiles", photoFilesByUserId.get(userId)); + user.put("currentPeriodPhotoFiles", currentPeriodPhotoFilesByUserId.get(userId)); + }); if (candidateUsers.size() > remainingQuota) { throw new IllegalArgumentException("选择人数超过当前分工会剩余名额"); } @@ -888,6 +905,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl candidateUsers, String photoFiles) { + private void fillCandidatePhotoFiles(List candidateUsers, String photoFiles, String currentPeriodPhotoFiles) { if (Lang.isEmpty(candidateUsers)) { return; } - candidateUsers.forEach(user -> user.put("photoFiles", photoFiles)); + candidateUsers.forEach(user -> { + user.put("photoFiles", photoFiles); + user.put("currentPeriodPhotoFiles", currentPeriodPhotoFiles); + }); } private Pagination emptyPagination(PageForm pageForm) { diff --git a/src/main/resources/db/thirtyTeachTour/thirty_teach_tour_add_photo_files.sql b/src/main/resources/db/thirtyTeachTour/thirty_teach_tour_add_photo_files.sql index 97673cae..f58ae698 100644 --- a/src/main/resources/db/thirtyTeachTour/thirty_teach_tour_add_photo_files.sql +++ b/src/main/resources/db/thirtyTeachTour/thirty_teach_tour_add_photo_files.sql @@ -1,7 +1,7 @@ --- 30年教龄疗休养报名图片材料字段。 +-- 30年教龄疗休养30年前图片材料字段。 -- PC端选择线路、移动端提交报名上传的多张图片统一保存为逗号分隔路径。 ALTER TABLE `thirty_teach_tour_user_assignment` - ADD COLUMN `photoFiles` text DEFAULT NULL COMMENT '报名图片材料' AFTER `boardingPlace`; + ADD COLUMN `photoFiles` text DEFAULT NULL COMMENT '30年前图片材料' AFTER `boardingPlace`; ALTER TABLE `thirty_teach_tour_ledger` - ADD COLUMN `photoFiles` text DEFAULT NULL COMMENT '报名图片材料' AFTER `boardingPlace`; + ADD COLUMN `photoFiles` text DEFAULT NULL COMMENT '30年前图片材料' AFTER `boardingPlace`; diff --git a/src/main/resources/db/thirtyTeachTour/thirty_teach_tour_ledger_create.sql b/src/main/resources/db/thirtyTeachTour/thirty_teach_tour_ledger_create.sql index 4d603d19..515a1017 100644 --- a/src/main/resources/db/thirtyTeachTour/thirty_teach_tour_ledger_create.sql +++ b/src/main/resources/db/thirtyTeachTour/thirty_teach_tour_ledger_create.sql @@ -22,7 +22,8 @@ CREATE TABLE IF NOT EXISTS `thirty_teach_tour_ledger` ( `travelAgencyId` varchar(32) DEFAULT NULL COMMENT '旅行社ID', `travelAgencyName` varchar(100) DEFAULT NULL COMMENT '旅行社', `boardingPlace` varchar(100) DEFAULT NULL COMMENT '乘车地点', - `photoFiles` text DEFAULT NULL COMMENT '报名图片材料', + `photoFiles` text DEFAULT NULL COMMENT '30年前图片材料', + `currentPeriodPhotoFiles` text DEFAULT NULL COMMENT '当前时间段图片材料', `hasFamily` tinyint(1) DEFAULT 0 COMMENT '是否携带家属', `intendedRoommate` varchar(100) DEFAULT NULL COMMENT '意向拼床人', `bedType` varchar(50) DEFAULT NULL COMMENT '床型', diff --git a/src/main/resources/db/thirtyTeachTour/thirty_teach_tour_user_assignment_create.sql b/src/main/resources/db/thirtyTeachTour/thirty_teach_tour_user_assignment_create.sql index da4d71bc..0a29960f 100644 --- a/src/main/resources/db/thirtyTeachTour/thirty_teach_tour_user_assignment_create.sql +++ b/src/main/resources/db/thirtyTeachTour/thirty_teach_tour_user_assignment_create.sql @@ -9,7 +9,8 @@ CREATE TABLE IF NOT EXISTS `thirty_teach_tour_user_assignment` ( `lineId` varchar(32) DEFAULT NULL COMMENT '线路ID', `lineName` varchar(100) DEFAULT NULL COMMENT '线路名称', `boardingPlace` varchar(100) DEFAULT NULL COMMENT '乘车地点', - `photoFiles` text DEFAULT NULL COMMENT '报名图片材料', + `photoFiles` text DEFAULT NULL COMMENT '30年前图片材料', + `currentPeriodPhotoFiles` text DEFAULT NULL COMMENT '当前时间段图片材料', `periodId` varchar(32) DEFAULT NULL COMMENT '出行时间段ID', `periodName` varchar(50) DEFAULT NULL COMMENT '出行时间段名称', `userId` varchar(32) DEFAULT NULL COMMENT '人员ID', diff --git a/src/main/resources/views/platform/zhgh/dayofficework/ThirtyTeachTour/branchUserAssignment/index.html b/src/main/resources/views/platform/zhgh/dayofficework/ThirtyTeachTour/branchUserAssignment/index.html index fddd90f7..c68bb1c7 100644 --- a/src/main/resources/views/platform/zhgh/dayofficework/ThirtyTeachTour/branchUserAssignment/index.html +++ b/src/main/resources/views/platform/zhgh/dayofficework/ThirtyTeachTour/branchUserAssignment/index.html @@ -95,7 +95,7 @@ layout("/layouts/platform.html"){