南大三十年教职工疗休养

This commit is contained in:
2026-06-29 11:01:59 +08:00
parent 1b888b4fce
commit e5a7b49bc1
16 changed files with 388 additions and 129 deletions
@@ -40,9 +40,9 @@ public class SmsNcuServiceImpl implements SmsService {
@Inject @Inject
private Dao dao; private Dao dao;
private static final String SEND_MSG_URL = ""; private static final String SEND_MSG_URL = "https://poa.ncu.edu.cn/apis/messagecenter/v1/poaMessage/messageSend";
private static final String APP_ID = ""; private static final String APP_ID = "72e34a101d3011f1a74cbae5193504f4";
private static final String TEMPLATE_ID = ""; private static final String TEMPLATE_ID = "MT1773223005000";
@Override @Override
public void sendSingleMessage(String loginName, String content) { public void sendSingleMessage(String loginName, String content) {
@@ -329,7 +329,7 @@ public class SysHomeController {
rows.add(NutMap.NEW() rows.add(NutMap.NEW()
.addv("id", "thirtyTeachTour-" + setting.getId()) .addv("id", "thirtyTeachTour-" + setting.getId())
.addv("year", setting.getYear()) .addv("year", setting.getYear())
.addv("title", setting.getYear() + "30年教龄疗休养") .addv("title", setting.getYear() + "服务南大三十年")
.addv("imageUrl", imageUrl) .addv("imageUrl", imageUrl)
.addv("href", "/platform/thirtyTeachTour/signup") .addv("href", "/platform/thirtyTeachTour/signup")
.addv("startCorner", "rightTop") .addv("startCorner", "rightTop")
@@ -79,9 +79,11 @@ public class ThirtyTeachTourBranchUserAssignmentController {
@At @At
@SaCheckPermission("thirtyTeachTour.branchUserAssignment.assign") @SaCheckPermission("thirtyTeachTour.branchUserAssignment.assign")
public Result candidatePageData(PageForm pageForm, String settingId, String keyword, @Param("userIds") String userIds, 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, 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") @SaCheckPermission("thirtyTeachTour.branchUserAssignment.assign")
@SLog(type = "tour", tag = "疗休养分工会人员分配", msg = "保存分工会人员分配") @SLog(type = "tour", tag = "疗休养分工会人员分配", msg = "保存分工会人员分配")
public Result doAssign(String settingId, String matterId, String periodId, String personType, 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) { @Param("assignItems") String assignItems) {
if (StrUtil.isNotBlank(assignItems)) { if (StrUtil.isNotBlank(assignItems)) {
List<NutMap> parsedItems; List<NutMap> parsedItems;
@@ -160,7 +162,7 @@ public class ThirtyTeachTourBranchUserAssignmentController {
} }
try { try {
return Result.success(tourUserAssignmentService.assignBranchUsers(settingId, matterId, periodId, personType, return Result.success(tourUserAssignmentService.assignBranchUsers(settingId, matterId, periodId, personType,
buildAssignItems(parsedUserIds, photoFiles))); buildAssignItems(parsedUserIds, photoFiles, currentPeriodPhotoFiles)));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return Result.error(e.getMessage()); return Result.error(e.getMessage());
} }
@@ -188,9 +190,10 @@ public class ThirtyTeachTourBranchUserAssignmentController {
@Aop(TransAop.READ_COMMITTED) @Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("thirtyTeachTour.branchUserAssignment.selectMatter") @SaCheckPermission("thirtyTeachTour.branchUserAssignment.selectMatter")
@SLog(type = "tour", tag = "疗休养分工会人员分配", msg = "选择分工会分配事项") @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 { try {
return Result.success(tourUserAssignmentService.selectCurrentBranchAssignmentMatter(id, matterId, photoFiles)); return Result.success(tourUserAssignmentService.selectCurrentBranchAssignmentMatter(id, matterId,
photoFiles, currentPeriodPhotoFiles));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return Result.error(e.getMessage()); return Result.error(e.getMessage());
} }
@@ -203,9 +206,9 @@ public class ThirtyTeachTourBranchUserAssignmentController {
@Aop(TransAop.READ_COMMITTED) @Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("thirtyTeachTour.branchUserAssignment.assign") @SaCheckPermission("thirtyTeachTour.branchUserAssignment.assign")
@SLog(type = "tour", tag = "疗休养分工会人员分配", msg = "上传分工会人员分配图片") @SLog(type = "tour", tag = "疗休养分工会人员分配", msg = "上传分工会人员分配图片")
public Result updatePhotoFiles(String id, String photoFiles) { public Result updatePhotoFiles(String id, String photoFiles, String currentPeriodPhotoFiles) {
try { try {
tourUserAssignmentService.updateCurrentBranchAssignmentPhotoFiles(id, photoFiles); tourUserAssignmentService.updateCurrentBranchAssignmentPhotoFiles(id, photoFiles, currentPeriodPhotoFiles);
return Result.success(); return Result.success();
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return Result.error(e.getMessage()); return Result.error(e.getMessage());
@@ -278,15 +281,28 @@ public class ThirtyTeachTourBranchUserAssignmentController {
return Lang.isEmpty(list) ? Collections.emptyList() : list; 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 入参。 * 兼容旧的 userIds 入参,把公共图片材料转换成按人员明细的统一 service 入参。
*/ */
private List<NutMap> buildAssignItems(List<String> userIds, String photoFiles) { private List<NutMap> buildAssignItems(List<String> userIds, String photoFiles, String currentPeriodPhotoFiles) {
if (Lang.isEmpty(userIds)) { if (Lang.isEmpty(userIds)) {
return Collections.emptyList(); return Collections.emptyList();
} }
List<NutMap> list = new ArrayList<>(); List<NutMap> 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; return list;
} }
@@ -392,11 +392,17 @@ public class ThirtyTeachTourLedgerController {
List<NutMap> rows = queryLedgerExportRows(startYear, endYear, keyword, unionId, lineId, travelPeriod, List<NutMap> rows = queryLedgerExportRows(startYear, endYear, keyword, unionId, lineId, travelPeriod,
lineType, directFamilyOnly, overCostOnly); lineType, directFamilyOnly, overCostOnly);
int imageColumnStartIndex = entities.size(); int imageColumnStartIndex = entities.size();
int maxPhotoCount = maxPhotoCount(rows); int maxPhotoCount = maxPhotoCount(rows, "photoFiles");
log.info("三十年教龄疗休养台账导出图片列准备:rows={}, maxPhotoCount={}, appDomain={}", int maxCurrentPeriodPhotoCount = maxPhotoCount(rows, "currentPeriodPhotoFiles");
rows.size(), maxPhotoCount, Globals.AppDomain); int totalImageColumnCount = maxPhotoCount + maxCurrentPeriodPhotoCount;
log.info("三十年教龄疗休养台账导出图片列准备:rows={}, beforePhotoMax={}, currentPeriodPhotoMax={}, appDomain={}",
rows.size(), maxPhotoCount, maxCurrentPeriodPhotoCount, Globals.AppDomain);
for (int i = 1; i <= maxPhotoCount; i++) { 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); entities.add(imageEntity);
} }
rows.forEach(row -> { rows.forEach(row -> {
@@ -404,7 +410,7 @@ public class ThirtyTeachTourLedgerController {
row.put("familyCountText", (familyCount == null ? 0 : familyCount) + ""); row.put("familyCountText", (familyCount == null ? 0 : familyCount) + "");
row.put("joinedText", Boolean.TRUE.equals(row.getBoolean("joined")) ? "" : ""); row.put("joinedText", Boolean.TRUE.equals(row.getBoolean("joined")) ? "" : "");
row.put("overCostReimbursedText", Boolean.TRUE.equals(row.getBoolean("overCostReimbursed")) ? "" : ""); row.put("overCostReimbursedText", Boolean.TRUE.equals(row.getBoolean("overCostReimbursed")) ? "" : "");
fillLedgerPhotoRowImages(row, maxPhotoCount); fillLedgerPhotoRowImages(row, maxPhotoCount, maxCurrentPeriodPhotoCount);
}); });
List<List<LedgerExportImage>> rowImages = snapshotLedgerRowImages(rows); List<List<LedgerExportImage>> rowImages = snapshotLedgerRowImages(rows);
@@ -412,7 +418,7 @@ public class ThirtyTeachTourLedgerController {
exportParams.setSheetName("疗休养台账"); exportParams.setSheetName("疗休养台账");
exportParams.setType(ExcelType.XSSF); exportParams.setType(ExcelType.XSSF);
Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, rows); 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); int insertedPictureCount = insertLedgerPhotoImages(workbook, rowImages, imageColumnStartIndex);
log.info("三十年教龄疗休养台账导出Excel图片写入完成:insertedPictureCount={}, workbookPictureCount={}", log.info("三十年教龄疗休养台账导出Excel图片写入完成:insertedPictureCount={}, workbookPictureCount={}",
insertedPictureCount, workbook.getAllPictures().size()); insertedPictureCount, workbook.getAllPictures().size());
@@ -422,10 +428,10 @@ public class ThirtyTeachTourLedgerController {
/** /**
* 统计本次导出台账中最大的图片数量,用于动态生成图片1、图片2等横向列。 * 统计本次导出台账中最大的图片数量,用于动态生成图片1、图片2等横向列。
*/ */
private int maxPhotoCount(List<NutMap> rows) { private int maxPhotoCount(List<NutMap> rows, String fieldName) {
int maxPhotoCount = 0; int maxPhotoCount = 0;
for (NutMap row : rows) { for (NutMap row : rows) {
maxPhotoCount = Math.max(maxPhotoCount, splitPhotoFiles(row.getString("photoFiles", "")).size()); maxPhotoCount = Math.max(maxPhotoCount, splitPhotoFiles(row.getString(fieldName, "")).size());
} }
return maxPhotoCount; return maxPhotoCount;
} }
@@ -433,14 +439,23 @@ public class ThirtyTeachTourLedgerController {
/** /**
* 将每条台账的图片材料解析为可写入 Excel 的图片对象,图片列文本保持为空,后续由 POI 手动插入图片。 * 将每条台账的图片材料解析为可写入 Excel 的图片对象,图片列文本保持为空,后续由 POI 手动插入图片。
*/ */
private void fillLedgerPhotoRowImages(NutMap row, int maxPhotoCount) { private void fillLedgerPhotoRowImages(NutMap row, int maxPhotoCount, int maxCurrentPeriodPhotoCount) {
List<String> photoFiles = splitPhotoFiles(row.getString("photoFiles", "")); List<String> photoFiles = splitPhotoFiles(row.getString("photoFiles", ""));
List<String> currentPeriodPhotoFiles = splitPhotoFiles(row.getString("currentPeriodPhotoFiles", ""));
if (!photoFiles.isEmpty()) { 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.getString("jobNo", ""), row.getString("userName", ""), photoFiles.size(), row.getString("photoFiles", ""));
} }
row.put("photoImages", resolveLedgerImages(row.getString("photoFiles", ""))); if (!currentPeriodPhotoFiles.isEmpty()) {
for (int i = 1; i <= maxPhotoCount; i++) { log.info("三十年教龄疗休养台账当前时间段图片字段读取:jobNo={}, userName={}, photoCount={}, photoFiles={}",
row.getString("jobNo", ""), row.getString("userName", ""), currentPeriodPhotoFiles.size(), row.getString("currentPeriodPhotoFiles", ""));
}
// 图片对象按导出列顺序组装:先 30 年前图片,再当前时间段图片,确保同一教职工图片仍在同一行。
List<LedgerExportImage> 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, ""); row.put("photoCell" + i, "");
} }
} }
@@ -508,16 +523,17 @@ public class ThirtyTeachTourLedgerController {
List<LedgerExportImage> images = rowImages.get(rowIndex); List<LedgerExportImage> images = rowImages.get(rowIndex);
for (int photoIndex = 0; photoIndex < images.size(); photoIndex++) { for (int photoIndex = 0; photoIndex < images.size(); photoIndex++) {
LedgerExportImage image = images.get(photoIndex); LedgerExportImage image = images.get(photoIndex);
int imageColumnIndex = imageColumnStartIndex + image.columnOffset;
int pictureIndex = workbook.addPicture(image.bytes, image.pictureType); int pictureIndex = workbook.addPicture(image.bytes, image.pictureType);
ClientAnchor anchor = creationHelper.createClientAnchor(); ClientAnchor anchor = creationHelper.createClientAnchor();
anchor.setCol1(imageColumnStartIndex + photoIndex); anchor.setCol1(imageColumnIndex);
anchor.setRow1(excelRowIndex); anchor.setRow1(excelRowIndex);
anchor.setCol2(imageColumnStartIndex + photoIndex + 1); anchor.setCol2(imageColumnIndex + 1);
anchor.setRow2(excelRowIndex + 1); anchor.setRow2(excelRowIndex + 1);
drawing.createPicture(anchor, pictureIndex); drawing.createPicture(anchor, pictureIndex);
insertedPictureCount++; insertedPictureCount++;
log.info("三十年教龄疗休养台账图片写入Excel成功:rowIndex={}, photoIndex={}, fileId={}, bytes={}, pictureType={}", log.info("三十年教龄疗休养台账图片写入Excel成功:rowIndex={}, columnOffset={}, fileId={}, bytes={}, pictureType={}",
excelRowIndex, photoIndex + 1, image.fileId, image.bytes.length, image.pictureType); excelRowIndex, image.columnOffset, image.fileId, image.bytes.length, image.pictureType);
} }
} }
return insertedPictureCount; return insertedPictureCount;
@@ -527,13 +543,20 @@ public class ThirtyTeachTourLedgerController {
* 将台账图片字段解析成可插入 Excel 的图片对象,当前优先支持系统文件下载路径。 * 将台账图片字段解析成可插入 Excel 的图片对象,当前优先支持系统文件下载路径。
*/ */
private List<LedgerExportImage> resolveLedgerImages(String photoFiles) { private List<LedgerExportImage> resolveLedgerImages(String photoFiles) {
return resolveLedgerImages(photoFiles, 0);
}
/**
* 将台账图片字段解析成可插入 Excel 的图片对象,并记录图片列偏移,支持多组图片列分区写入。
*/
private List<LedgerExportImage> resolveLedgerImages(String photoFiles, int columnOffsetStart) {
List<LedgerExportImage> images = new ArrayList<>(); List<LedgerExportImage> images = new ArrayList<>();
List<String> photoPaths = splitPhotoFiles(photoFiles); List<String> photoPaths = splitPhotoFiles(photoFiles);
for (int photoIndex = 0; photoIndex < photoPaths.size(); photoIndex++) { for (int photoIndex = 0; photoIndex < photoPaths.size(); photoIndex++) {
String originalPath = photoPaths.get(photoIndex); String originalPath = photoPaths.get(photoIndex);
LedgerExportImage image = resolveLedgerImage(originalPath); LedgerExportImage image = resolveLedgerImage(originalPath);
if (image != null) { if (image != null) {
images.add(image); images.add(image.withColumnOffset(columnOffsetStart + photoIndex));
} else { } else {
log.warn("三十年教龄疗休养台账图片解析失败:photoIndex={}, originalPath={}", photoIndex + 1, originalPath); log.warn("三十年教龄疗休养台账图片解析失败:photoIndex={}, originalPath={}", photoIndex + 1, originalPath);
} }
@@ -707,12 +730,22 @@ public class ThirtyTeachTourLedgerController {
private final String originalPath; private final String originalPath;
private final byte[] bytes; private final byte[] bytes;
private final int pictureType; private final int pictureType;
private final int columnOffset;
private LedgerExportImage(String fileId, String originalPath, byte[] bytes, int pictureType) { 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.fileId = fileId;
this.originalPath = originalPath; this.originalPath = originalPath;
this.bytes = bytes; this.bytes = bytes;
this.pictureType = pictureType; 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.lineType,
t.signupTime, t.signupTime,
t.photoFiles, t.photoFiles,
t.currentPeriodPhotoFiles,
IFNULL(f.familyCount, 0) AS familyCount, IFNULL(f.familyCount, 0) AS familyCount,
t.joined, t.joined,
t.overCostReimbursed t.overCostReimbursed
@@ -508,12 +508,14 @@ public class ThirtyTeachTourMySignupController {
ledger.setJoined(oldLedger.getJoined()); ledger.setJoined(oldLedger.getJoined());
ledger.setReimbursed(oldLedger.getReimbursed()); ledger.setReimbursed(oldLedger.getReimbursed());
ledger.setSignupTime(defaultIfBlank(oldLedger.getSignupTime(), ledger.getSignupTime())); ledger.setSignupTime(defaultIfBlank(oldLedger.getSignupTime(), ledger.getSignupTime()));
// 修改报名表单未必提交当前时间段图片,保留旧台账字段,避免回填人员分配时误清空。
ledger.setCurrentPeriodPhotoFiles(defaultIfBlank(ledger.getCurrentPeriodPhotoFiles(), oldLedger.getCurrentPeriodPhotoFiles()));
fillStaffInfo(ledger); fillStaffInfo(ledger);
tourLedgerService.updateIgnoreNull(ledger); tourLedgerService.updateIgnoreNull(ledger);
// 报名台账更新后,仅回填已存在的人员分配记录事项信息,不新增记录、不改变分配来源。 // 报名台账更新后,仅回填已存在的人员分配记录事项信息,不新增记录、不改变分配来源。
tourUserAssignmentService.backfillExistingAssignmentAfterSignup(matter.getSettingId(), matter.getId(), SecurityUtil.getUserId(), 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())); tourLedgerFamilyService.clear(Cnd.where(ThirtyTeachTourLedgerFamily::getLedgerId, "=", ledger.getId()));
tourLedgerDirectRelativeService.clear(Cnd.where(ThirtyTeachTourLedgerDirectRelative::getLedgerId, "=", ledger.getId())); tourLedgerDirectRelativeService.clear(Cnd.where(ThirtyTeachTourLedgerDirectRelative::getLedgerId, "=", ledger.getId()));
if (Lang.isNotEmpty(familyList)) { if (Lang.isNotEmpty(familyList)) {
@@ -103,9 +103,13 @@ public class ThirtyTeachTourSchoolUserAssignmentController {
@At @At
@SaCheckPermission("thirtyTeachTour.schoolUserAssignment") @SaCheckPermission("thirtyTeachTour.schoolUserAssignment")
public Result candidatePageData(PageForm pageForm, String settingId, String unionId, String keyword, @Param("userIds") String userIds, 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, 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) @Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("thirtyTeachTour.schoolUserAssignment") @SaCheckPermission("thirtyTeachTour.schoolUserAssignment")
@SLog(type = "tour", tag = "疗休养校工会人员分配", msg = "保存校工会人员分配") @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<String> parsedUserIds; List<String> parsedUserIds;
try { try {
parsedUserIds = parseUserIds(userIds); parsedUserIds = parseUserIds(userIds);
@@ -159,7 +164,8 @@ public class ThirtyTeachTourSchoolUserAssignmentController {
return Result.error("人员参数错误"); return Result.error("人员参数错误");
} }
try { 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) { } catch (IllegalArgumentException e) {
return Result.error(e.getMessage()); return Result.error(e.getMessage());
} }
@@ -193,9 +199,10 @@ public class ThirtyTeachTourSchoolUserAssignmentController {
@Aop(TransAop.READ_COMMITTED) @Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("thirtyTeachTour.schoolUserAssignment") @SaCheckPermission("thirtyTeachTour.schoolUserAssignment")
@SLog(type = "tour", tag = "疗休养校工会人员分配", msg = "选择校工会分配事项") @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 { try {
return Result.success(tourUserAssignmentService.selectSchoolAssignmentMatter(id, matterId, photoFiles)); return Result.success(tourUserAssignmentService.selectSchoolAssignmentMatter(id, matterId,
photoFiles, currentPeriodPhotoFiles));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return Result.error(e.getMessage()); return Result.error(e.getMessage());
} }
@@ -208,9 +215,9 @@ public class ThirtyTeachTourSchoolUserAssignmentController {
@Aop(TransAop.READ_COMMITTED) @Aop(TransAop.READ_COMMITTED)
@SaCheckPermission("thirtyTeachTour.schoolUserAssignment") @SaCheckPermission("thirtyTeachTour.schoolUserAssignment")
@SLog(type = "tour", tag = "疗休养校工会人员分配", msg = "上传校工会人员分配图片") @SLog(type = "tour", tag = "疗休养校工会人员分配", msg = "上传校工会人员分配图片")
public Result updatePhotoFiles(String id, String photoFiles) { public Result updatePhotoFiles(String id, String photoFiles, String currentPeriodPhotoFiles) {
try { try {
tourUserAssignmentService.updateSchoolAssignmentPhotoFiles(id, photoFiles); tourUserAssignmentService.updateSchoolAssignmentPhotoFiles(id, photoFiles, currentPeriodPhotoFiles);
return Result.success(); return Result.success();
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
return Result.error(e.getMessage()); return Result.error(e.getMessage());
@@ -280,6 +287,16 @@ public class ThirtyTeachTourSchoolUserAssignmentController {
return Lang.isEmpty(list) ? Collections.emptyList() : list; 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);
}
/** /**
* 定义人员分配导出字段,保持与页面列表核心字段一致并补充人员基础信息。 * 定义人员分配导出字段,保持与页面列表核心字段一致并补充人员基础信息。
*/ */
@@ -906,6 +906,8 @@ public class ThirtyTeachTourSignupController {
ledger.setJoined(oldLedger.getJoined()); ledger.setJoined(oldLedger.getJoined());
ledger.setReimbursed(oldLedger.getReimbursed()); ledger.setReimbursed(oldLedger.getReimbursed());
ledger.setSignupTime(defaultIfBlank(oldLedger.getSignupTime(), ledger.getSignupTime())); ledger.setSignupTime(defaultIfBlank(oldLedger.getSignupTime(), ledger.getSignupTime()));
// 修改报名时前端可能未提交当前时间段图片,沿用旧台账值,避免非图片字段修改导致材料丢失。
ledger.setCurrentPeriodPhotoFiles(defaultIfBlank(ledger.getCurrentPeriodPhotoFiles(), oldLedger.getCurrentPeriodPhotoFiles()));
} }
ledger.setOverCostReimbursed(Boolean.TRUE.equals(ledger.getOverCostReimbursed())); ledger.setOverCostReimbursed(Boolean.TRUE.equals(ledger.getOverCostReimbursed()));
fillStaffInfo(ledger); fillStaffInfo(ledger);
@@ -920,7 +922,7 @@ public class ThirtyTeachTourSignupController {
} }
// 报名台账落库后,仅回填已存在的人员分配记录事项信息,不新增记录、不改变分配来源。 // 报名台账落库后,仅回填已存在的人员分配记录事项信息,不新增记录、不改变分配来源。
tourUserAssignmentService.backfillExistingAssignmentAfterSignup(matter.getSettingId(), matter.getId(), SecurityUtil.getUserId(), tourUserAssignmentService.backfillExistingAssignmentAfterSignup(matter.getSettingId(), matter.getId(), SecurityUtil.getUserId(),
ledger.getBoardingPlace(), ledger.getPhotoFiles()); ledger.getBoardingPlace(), ledger.getPhotoFiles(), ledger.getCurrentPeriodPhotoFiles());
if (Lang.isNotEmpty(familyList)) { if (Lang.isNotEmpty(familyList)) {
familyList.forEach(item -> { familyList.forEach(item -> {
item.setLedgerId(ledger.getId()); item.setLedgerId(ledger.getId());
@@ -1740,6 +1742,8 @@ public class ThirtyTeachTourSignupController {
ledger.setUnitName(defaultIfBlank(assignment.getString("unitName", ""), ledger.getUnitName())); ledger.setUnitName(defaultIfBlank(assignment.getString("unitName", ""), ledger.getUnitName()));
ledger.setUnionId(defaultIfBlank(assignment.getString("unionId", ""), ledger.getUnionId())); ledger.setUnionId(defaultIfBlank(assignment.getString("unionId", ""), ledger.getUnionId()));
ledger.setUnionName(defaultIfBlank(assignment.getString("unionName", ""), ledger.getUnionName())); ledger.setUnionName(defaultIfBlank(assignment.getString("unionName", ""), ledger.getUnionName()));
// 当前时间段图片只来源于人员分配快照;报名提交时同步进台账,避免台账图片材料缺一类。
ledger.setCurrentPeriodPhotoFiles(defaultIfBlank(assignment.getString("currentPeriodPhotoFiles", ""), ledger.getCurrentPeriodPhotoFiles()));
} }
private void fillLedgerContactFallback(ThirtyTeachTourLedger ledger, NutMap staff) { private void fillLedgerContactFallback(ThirtyTeachTourLedger ledger, NutMap staff) {
@@ -127,10 +127,15 @@ public class ThirtyTeachTourLedger extends BaseModel implements Serializable {
private String boardingPlace; private String boardingPlace;
@Column @Column
@Comment("报名图片材料") @Comment("30年前图片材料")
@ColDefine(type = ColType.TEXT) @ColDefine(type = ColType.TEXT)
private String photoFiles; private String photoFiles;
@Column
@Comment("当前时间段图片材料")
@ColDefine(type = ColType.TEXT)
private String currentPeriodPhotoFiles;
@Column @Column
@Comment("是否携带家属") @Comment("是否携带家属")
@ColDefine(type = ColType.BOOLEAN) @ColDefine(type = ColType.BOOLEAN)
@@ -78,10 +78,15 @@ public class ThirtyTeachTourUserAssignment extends BaseModel implements Serializ
private String boardingPlace; private String boardingPlace;
@Column @Column
@Comment("报名图片材料") @Comment("30年前图片材料")
@ColDefine(type = ColType.TEXT) @ColDefine(type = ColType.TEXT)
private String photoFiles; private String photoFiles;
@Column
@Comment("当前时间段图片材料")
@ColDefine(type = ColType.TEXT)
private String currentPeriodPhotoFiles;
@Column @Column
@Comment("出行时间段ID") @Comment("出行时间段ID")
@ColDefine(type = ColType.VARCHAR, width = 32) @ColDefine(type = ColType.VARCHAR, width = 32)
@@ -163,11 +163,11 @@ public interface ThirtyTeachTourUserAssignmentService extends BaseService<Thirty
* @param userIds 待分配人员ID列表 * @param userIds 待分配人员ID列表
* @return 保存结果,包含实际分配数量、跳过数量和代报名台账写入数量 * @return 保存结果,包含实际分配数量、跳过数量和代报名台账写入数量
*/ */
NutMap assignSchoolUsers(String settingId, String matterId, String personType, List<String> userIds, String photoFiles); NutMap assignSchoolUsers(String settingId, String matterId, String personType, List<String> userIds, String photoFiles, String currentPeriodPhotoFiles);
/** /**
* 保存校工会人员分配,支持每个候选人员单独选择分配线路。 * 保存校工会人员分配,支持每个候选人员单独选择分配线路。
* assignItems 中每项包含 userId、matterId、photoFilesmatterId 为空时只保存人员分配,不写台账。 * assignItems 中每项包含 userId、matterId、photoFiles、currentPeriodPhotoFiles;matterId 为空时只保存人员分配,不写台账。
* *
* @param settingId 疗休养配置ID * @param settingId 疗休养配置ID
* @param assignItems 人员和分配线路明细 * @param assignItems 人员和分配线路明细
@@ -183,7 +183,7 @@ public interface ThirtyTeachTourUserAssignmentService extends BaseService<Thirty
* @param matterId 疗休养事项ID * @param matterId 疗休养事项ID
* @return 处理结果,包含台账写入数量 * @return 处理结果,包含台账写入数量
*/ */
NutMap selectSchoolAssignmentMatter(String id, String matterId, String photoFiles); NutMap selectSchoolAssignmentMatter(String id, String matterId, String photoFiles, String currentPeriodPhotoFiles);
/** /**
* 给当前分工会已分配的正式人员补选分配路线,并按代报名写入疗休养台账。 * 给当前分工会已分配的正式人员补选分配路线,并按代报名写入疗休养台账。
@@ -193,7 +193,7 @@ public interface ThirtyTeachTourUserAssignmentService extends BaseService<Thirty
* @param matterId 疗休养事项ID * @param matterId 疗休养事项ID
* @return 处理结果,包含台账写入数量 * @return 处理结果,包含台账写入数量
*/ */
NutMap selectCurrentBranchAssignmentMatter(String id, String matterId, String photoFiles); NutMap selectCurrentBranchAssignmentMatter(String id, String matterId, String photoFiles, String currentPeriodPhotoFiles);
/** /**
* 查询指定配置下已启用的出行时间段,供分工会人员分配弹窗按时间段选择正式名额。 * 查询指定配置下已启用的出行时间段,供分工会人员分配弹窗按时间段选择正式名额。
@@ -221,7 +221,7 @@ public interface ThirtyTeachTourUserAssignmentService extends BaseService<Thirty
* @param matterId 疗休养事项ID,可为空 * @param matterId 疗休养事项ID,可为空
* @param periodId 出行时间段ID,正式人员必填 * @param periodId 出行时间段ID,正式人员必填
* @param personType 人员类型:FORMAL 正式人员,BACKUP 替补人员 * @param personType 人员类型:FORMAL 正式人员,BACKUP 替补人员
* @param assignItems 待分配人员明细,每项包含 userId、photoFiles * @param assignItems 待分配人员明细,每项包含 userId、photoFiles、currentPeriodPhotoFiles
* @return 保存结果,包含实际分配数量、跳过数量、代报名台账写入数量和剩余名额 * @return 保存结果,包含实际分配数量、跳过数量、代报名台账写入数量和剩余名额
*/ */
NutMap assignBranchUsers(String settingId, String matterId, String periodId, String personType, List<NutMap> assignItems); NutMap assignBranchUsers(String settingId, String matterId, String periodId, String personType, List<NutMap> assignItems);
@@ -289,6 +289,20 @@ public interface ThirtyTeachTourUserAssignmentService extends BaseService<Thirty
*/ */
int backfillExistingAssignmentAfterSignup(String settingId, String matterId, String userId, String boardingPlace, String photoFiles); int backfillExistingAssignmentAfterSignup(String settingId, String matterId, String userId, String boardingPlace, String photoFiles);
/**
* 用户报名写入台账后,回填人员分配记录并同步两类图片材料。
*
* @param settingId 疗休养配置ID
* @param matterId 疗休养事项ID
* @param userId 报名用户ID
* @param boardingPlace 用户报名时最终选择的乘车地点
* @param photoFiles 30年前图片材料
* @param currentPeriodPhotoFiles 当前时间段图片材料
* @return 更新记录数
*/
int backfillExistingAssignmentAfterSignup(String settingId, String matterId, String userId, String boardingPlace,
String photoFiles, String currentPeriodPhotoFiles);
/** /**
* 用户取消报名删除台账后,清空该用户在同一疗休养配置下已存在人员分配记录的事项快照。 * 用户取消报名删除台账后,清空该用户在同一疗休养配置下已存在人员分配记录的事项快照。
* 仅清空事项、线路、旅行社字段,不删除记录,不修改 assignSource 和人员类型。 * 仅清空事项、线路、旅行社字段,不删除记录,不修改 assignSource 和人员类型。
@@ -337,17 +351,19 @@ public interface ThirtyTeachTourUserAssignmentService extends BaseService<Thirty
* 更新校工会人员分配记录的图片材料,并同步该人员已存在的报名台账图片。 * 更新校工会人员分配记录的图片材料,并同步该人员已存在的报名台账图片。
* *
* @param id 人员分配记录ID * @param id 人员分配记录ID
* @param photoFiles 图片材料,多个文件以逗号分隔 * @param photoFiles 30年前图片材料,多个文件以逗号分隔
* @param currentPeriodPhotoFiles 当前时间段图片材料,多个文件以逗号分隔
*/ */
void updateSchoolAssignmentPhotoFiles(String id, String photoFiles); void updateSchoolAssignmentPhotoFiles(String id, String photoFiles, String currentPeriodPhotoFiles);
/** /**
* 更新当前分工会人员分配记录的图片材料,并同步该人员已存在的报名台账图片。 * 更新当前分工会人员分配记录的图片材料,并同步该人员已存在的报名台账图片。
* *
* @param id 人员分配记录ID * @param id 人员分配记录ID
* @param photoFiles 图片材料,多个文件以逗号分隔 * @param photoFiles 30年前图片材料,多个文件以逗号分隔
* @param currentPeriodPhotoFiles 当前时间段图片材料,多个文件以逗号分隔
*/ */
void updateCurrentBranchAssignmentPhotoFiles(String id, String photoFiles); void updateCurrentBranchAssignmentPhotoFiles(String id, String photoFiles, String currentPeriodPhotoFiles);
/** /**
* 删除指定来源的人员分配记录,避免校工会页面误删分工会分配的数据。 * 删除指定来源的人员分配记录,避免校工会页面误删分工会分配的数据。
@@ -356,7 +356,8 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
} }
@Override @Override
public NutMap assignSchoolUsers(String settingId, String matterId, String personType, List<String> userIds, String photoFiles) { public NutMap assignSchoolUsers(String settingId, String matterId, String personType, List<String> userIds,
String photoFiles, String currentPeriodPhotoFiles) {
List<String> distinctUserIds = normalizeUserIds(userIds); List<String> distinctUserIds = normalizeUserIds(userIds);
if (StrUtil.isBlank(settingId) || Lang.isEmpty(distinctUserIds)) { if (StrUtil.isBlank(settingId) || Lang.isEmpty(distinctUserIds)) {
throw new IllegalArgumentException("请选择疗休养配置和分配人员"); throw new IllegalArgumentException("请选择疗休养配置和分配人员");
@@ -378,7 +379,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
userCnd.and("u.id", "in", distinctUserIds); userCnd.and("u.id", "in", distinctUserIds);
userSql.setCondition(userCnd); userSql.setCondition(userCnd);
List<NutMap> candidateUsers = listMap(userSql); List<NutMap> candidateUsers = listMap(userSql);
fillCandidatePhotoFiles(candidateUsers, normalizePhotoFiles(photoFiles)); fillCandidatePhotoFiles(candidateUsers, normalizePhotoFiles(photoFiles), normalizePhotoFiles(currentPeriodPhotoFiles));
List<ThirtyTeachTourUserAssignment> assignments = candidateUsers.stream() List<ThirtyTeachTourUserAssignment> assignments = candidateUsers.stream()
.map(user -> buildSchoolAssignment(settingId, matterInfo, normalizedPersonType, user)) .map(user -> buildSchoolAssignment(settingId, matterInfo, normalizedPersonType, user))
.collect(Collectors.toList()); .collect(Collectors.toList());
@@ -408,6 +409,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
Map<String, String> matterByUserId = new HashMap<>(); Map<String, String> matterByUserId = new HashMap<>();
Map<String, String> photoFilesByUserId = new HashMap<>(); Map<String, String> photoFilesByUserId = new HashMap<>();
Map<String, String> currentPeriodPhotoFilesByUserId = new HashMap<>();
List<String> userIds = assignItems.stream() List<String> userIds = assignItems.stream()
.map(item -> item == null ? "" : item.getString("userId", "")) .map(item -> item == null ? "" : item.getString("userId", ""))
.filter(StrUtil::isNotBlank) .filter(StrUtil::isNotBlank)
@@ -423,6 +425,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
} }
matterByUserId.put(userId, item.getString("matterId", "")); matterByUserId.put(userId, item.getString("matterId", ""));
photoFilesByUserId.put(userId, normalizePhotoFiles(item.getString("photoFiles"))); photoFilesByUserId.put(userId, normalizePhotoFiles(item.getString("photoFiles")));
currentPeriodPhotoFilesByUserId.put(userId, normalizePhotoFiles(item.getString("currentPeriodPhotoFiles")));
}); });
if (Lang.isEmpty(userIds)) { if (Lang.isEmpty(userIds)) {
throw new IllegalArgumentException("请选择分配人员"); throw new IllegalArgumentException("请选择分配人员");
@@ -446,7 +449,11 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
userCnd.and("u.id", "in", userIds); userCnd.and("u.id", "in", userIds);
userSql.setCondition(userCnd); userSql.setCondition(userCnd);
List<NutMap> candidateUsers = listMap(userSql); List<NutMap> 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<ThirtyTeachTourUserAssignment> assignments = candidateUsers.stream() List<ThirtyTeachTourUserAssignment> assignments = candidateUsers.stream()
.map(user -> { .map(user -> {
@@ -474,7 +481,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
} }
@Override @Override
public NutMap selectSchoolAssignmentMatter(String id, String matterId, String photoFiles) { public NutMap selectSchoolAssignmentMatter(String id, String matterId, String photoFiles, String currentPeriodPhotoFiles) {
if (StrUtil.isBlank(id) || StrUtil.isBlank(matterId)) { if (StrUtil.isBlank(id) || StrUtil.isBlank(matterId)) {
throw new IllegalArgumentException("请选择人员分配记录和分配线路"); throw new IllegalArgumentException("请选择人员分配记录和分配线路");
} }
@@ -495,14 +502,16 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
if (matterInfo == null) { if (matterInfo == null) {
throw new IllegalArgumentException("分配线路不存在或未配置线路"); throw new IllegalArgumentException("分配线路不存在或未配置线路");
} }
updateAssignmentMatterSnapshot(id, matterInfo, ThirtyTeachTourUserAssignment.ASSIGN_SOURCE_SCHOOL_UNION, photoFiles); updateAssignmentMatterSnapshot(id, matterInfo, ThirtyTeachTourUserAssignment.ASSIGN_SOURCE_SCHOOL_UNION,
photoFiles, currentPeriodPhotoFiles);
assignment.setPhotoFiles(normalizePhotoFiles(photoFiles)); assignment.setPhotoFiles(normalizePhotoFiles(photoFiles));
assignment.setCurrentPeriodPhotoFiles(normalizePhotoFiles(currentPeriodPhotoFiles));
int ledgerCount = insertProxySignupLedgers(matterInfo, Collections.singletonList(fetchAssignmentUserSnapshot(assignment))); int ledgerCount = insertProxySignupLedgers(matterInfo, Collections.singletonList(fetchAssignmentUserSnapshot(assignment)));
return NutMap.NEW().addv("ledgerCount", ledgerCount); return NutMap.NEW().addv("ledgerCount", ledgerCount);
} }
@Override @Override
public NutMap selectCurrentBranchAssignmentMatter(String id, String matterId, String photoFiles) { public NutMap selectCurrentBranchAssignmentMatter(String id, String matterId, String photoFiles, String currentPeriodPhotoFiles) {
if (StrUtil.isBlank(id) || StrUtil.isBlank(matterId)) { if (StrUtil.isBlank(id) || StrUtil.isBlank(matterId)) {
throw new IllegalArgumentException("请选择人员分配记录和分配路线"); throw new IllegalArgumentException("请选择人员分配记录和分配路线");
} }
@@ -525,9 +534,11 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
throw new IllegalArgumentException("当前线路不在报名时间内,不能选择"); throw new IllegalArgumentException("当前线路不在报名时间内,不能选择");
} }
assignment.setPhotoFiles(normalizePhotoFiles(photoFiles)); assignment.setPhotoFiles(normalizePhotoFiles(photoFiles));
assignment.setCurrentPeriodPhotoFiles(normalizePhotoFiles(currentPeriodPhotoFiles));
List<NutMap> users = Collections.singletonList(fetchAssignmentUserSnapshot(assignment)); List<NutMap> users = Collections.singletonList(fetchAssignmentUserSnapshot(assignment));
checkProxySignupMaxGroupPeople(matterInfo, users); 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); int ledgerCount = insertProxySignupLedgers(matterInfo, users);
return NutMap.NEW().addv("ledgerCount", ledgerCount); return NutMap.NEW().addv("ledgerCount", ledgerCount);
} }
@@ -542,6 +553,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
throw new IllegalArgumentException("请选择疗休养配置和分配人员"); throw new IllegalArgumentException("请选择疗休养配置和分配人员");
} }
Map<String, String> photoFilesByUserId = new HashMap<>(); Map<String, String> photoFilesByUserId = new HashMap<>();
Map<String, String> currentPeriodPhotoFilesByUserId = new HashMap<>();
List<String> distinctUserIds = assignItems.stream() List<String> distinctUserIds = assignItems.stream()
.map(item -> item == null ? "" : item.getString("userId", "")) .map(item -> item == null ? "" : item.getString("userId", ""))
.filter(StrUtil::isNotBlank) .filter(StrUtil::isNotBlank)
@@ -557,6 +569,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
} }
// 图片材料来自人员分配弹窗的行级暂存,按人员写入后续分配表和台账。 // 图片材料来自人员分配弹窗的行级暂存,按人员写入后续分配表和台账。
photoFilesByUserId.put(userId, normalizePhotoFiles(item.getString("photoFiles"))); photoFilesByUserId.put(userId, normalizePhotoFiles(item.getString("photoFiles")));
currentPeriodPhotoFilesByUserId.put(userId, normalizePhotoFiles(item.getString("currentPeriodPhotoFiles")));
}); });
if (Lang.isEmpty(distinctUserIds)) { if (Lang.isEmpty(distinctUserIds)) {
throw new IllegalArgumentException("请选择分配人员"); throw new IllegalArgumentException("请选择分配人员");
@@ -604,7 +617,11 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
userCnd.and("u.id", "in", distinctUserIds); userCnd.and("u.id", "in", distinctUserIds);
userSql.setCondition(userCnd); userSql.setCondition(userCnd);
List<NutMap> candidateUsers = listMap(userSql); List<NutMap> 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) { if (candidateUsers.size() > remainingQuota) {
throw new IllegalArgumentException("选择人数超过当前分工会剩余名额"); throw new IllegalArgumentException("选择人数超过当前分工会剩余名额");
} }
@@ -888,6 +905,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
unionName, unionName,
boardingPlace, boardingPlace,
photoFiles, photoFiles,
currentPeriodPhotoFiles,
periodId, periodId,
periodName, periodName,
personType, personType,
@@ -965,6 +983,12 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
@Override @Override
public int backfillExistingAssignmentAfterSignup(String settingId, String matterId, String userId, String boardingPlace, String photoFiles) { public int backfillExistingAssignmentAfterSignup(String settingId, String matterId, String userId, String boardingPlace, String photoFiles) {
return backfillExistingAssignmentAfterSignup(settingId, matterId, userId, boardingPlace, photoFiles, "");
}
@Override
public int backfillExistingAssignmentAfterSignup(String settingId, String matterId, String userId, String boardingPlace,
String photoFiles, String currentPeriodPhotoFiles) {
if (StrUtil.isBlank(settingId) || StrUtil.isBlank(matterId) || StrUtil.isBlank(userId)) { if (StrUtil.isBlank(settingId) || StrUtil.isBlank(matterId) || StrUtil.isBlank(userId)) {
return 0; return 0;
} }
@@ -980,7 +1004,8 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
.add("travelAgencyId", matterInfo.getString("travelAgencyId")) .add("travelAgencyId", matterInfo.getString("travelAgencyId"))
.add("travelAgencyName", matterInfo.getString("travelAgencyName")) .add("travelAgencyName", matterInfo.getString("travelAgencyName"))
.add("boardingPlace", StrUtil.blankToDefault(boardingPlace, matterInfo.getString("defaultBoardingPlace"))) .add("boardingPlace", StrUtil.blankToDefault(boardingPlace, matterInfo.getString("defaultBoardingPlace")))
.add("photoFiles", normalizePhotoFiles(photoFiles)), .add("photoFiles", normalizePhotoFiles(photoFiles))
.add("currentPeriodPhotoFiles", normalizePhotoFiles(currentPeriodPhotoFiles)),
Cnd.where(ThirtyTeachTourUserAssignment::getSettingId, "=", settingId) Cnd.where(ThirtyTeachTourUserAssignment::getSettingId, "=", settingId)
.and(ThirtyTeachTourUserAssignment::getUserId, "=", userId) .and(ThirtyTeachTourUserAssignment::getUserId, "=", userId)
.and(ThirtyTeachTourUserAssignment::getDelFlag, "=", false)); .and(ThirtyTeachTourUserAssignment::getDelFlag, "=", false));
@@ -998,7 +1023,9 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
.add("lineName", null) .add("lineName", null)
.add("travelAgencyId", null) .add("travelAgencyId", null)
.add("travelAgencyName", null) .add("travelAgencyName", null)
.add("boardingPlace", null), .add("boardingPlace", null)
.add("photoFiles", null)
.add("currentPeriodPhotoFiles", null),
Cnd.where(ThirtyTeachTourUserAssignment::getSettingId, "=", settingId) Cnd.where(ThirtyTeachTourUserAssignment::getSettingId, "=", settingId)
.and(ThirtyTeachTourUserAssignment::getUserId, "=", userId) .and(ThirtyTeachTourUserAssignment::getUserId, "=", userId)
.and(ThirtyTeachTourUserAssignment::getDelFlag, "=", false)); .and(ThirtyTeachTourUserAssignment::getDelFlag, "=", false));
@@ -1023,7 +1050,9 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
.add("lineName", null) .add("lineName", null)
.add("travelAgencyId", null) .add("travelAgencyId", null)
.add("travelAgencyName", null) .add("travelAgencyName", null)
.add("boardingPlace", null), .add("boardingPlace", null)
.add("photoFiles", null)
.add("currentPeriodPhotoFiles", null),
cnd); cnd);
} }
@@ -1038,21 +1067,21 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
} }
@Override @Override
public void updateSchoolAssignmentPhotoFiles(String id, String photoFiles) { public void updateSchoolAssignmentPhotoFiles(String id, String photoFiles, String currentPeriodPhotoFiles) {
ThirtyTeachTourUserAssignment assignment = fetchAssignmentBySource(id, ThirtyTeachTourUserAssignment.ASSIGN_SOURCE_SCHOOL_UNION); ThirtyTeachTourUserAssignment assignment = fetchAssignmentBySource(id, ThirtyTeachTourUserAssignment.ASSIGN_SOURCE_SCHOOL_UNION);
if (assignment == null) { if (assignment == null) {
throw new IllegalArgumentException("人员分配记录不存在或无权限操作"); throw new IllegalArgumentException("人员分配记录不存在或无权限操作");
} }
updateAssignmentPhotoFiles(assignment, photoFiles); updateAssignmentPhotoFiles(assignment, photoFiles, currentPeriodPhotoFiles);
} }
@Override @Override
public void updateCurrentBranchAssignmentPhotoFiles(String id, String photoFiles) { public void updateCurrentBranchAssignmentPhotoFiles(String id, String photoFiles, String currentPeriodPhotoFiles) {
ThirtyTeachTourUserAssignment assignment = fetchCurrentBranchAssignment(id); ThirtyTeachTourUserAssignment assignment = fetchCurrentBranchAssignment(id);
if (assignment == null) { if (assignment == null) {
throw new IllegalArgumentException("人员分配记录不存在或无权限操作"); throw new IllegalArgumentException("人员分配记录不存在或无权限操作");
} }
updateAssignmentPhotoFiles(assignment, photoFiles); updateAssignmentPhotoFiles(assignment, photoFiles, currentPeriodPhotoFiles);
} }
@Override @Override
@@ -1373,19 +1402,23 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
* 更新人员分配图片材料,并同步同一事项和工号下已生成的报名台账。 * 更新人员分配图片材料,并同步同一事项和工号下已生成的报名台账。
* 未选择线路或尚未生成台账时,只更新人员分配表,保证主列表上传不会强制产生台账数据。 * 未选择线路或尚未生成台账时,只更新人员分配表,保证主列表上传不会强制产生台账数据。
*/ */
private void updateAssignmentPhotoFiles(ThirtyTeachTourUserAssignment assignment, String photoFiles) { private void updateAssignmentPhotoFiles(ThirtyTeachTourUserAssignment assignment, String photoFiles, String currentPeriodPhotoFiles) {
if (assignment == null || StrUtil.isBlank(assignment.getId())) { if (assignment == null || StrUtil.isBlank(assignment.getId())) {
throw new IllegalArgumentException("人员分配记录不存在或无权限操作"); throw new IllegalArgumentException("人员分配记录不存在或无权限操作");
} }
String normalizedPhotoFiles = normalizePhotoFiles(photoFiles); String normalizedPhotoFiles = normalizePhotoFiles(photoFiles);
update(Chain.make("photoFiles", normalizedPhotoFiles), String normalizedCurrentPeriodPhotoFiles = normalizePhotoFiles(currentPeriodPhotoFiles);
// 两类图片材料属于同一人员分配快照,上传时一起落库并同步已生成的台账。
update(Chain.make("photoFiles", normalizedPhotoFiles)
.add("currentPeriodPhotoFiles", normalizedCurrentPeriodPhotoFiles),
Cnd.where(ThirtyTeachTourUserAssignment::getId, "=", assignment.getId()) Cnd.where(ThirtyTeachTourUserAssignment::getId, "=", assignment.getId())
.and(ThirtyTeachTourUserAssignment::getDelFlag, "=", false)); .and(ThirtyTeachTourUserAssignment::getDelFlag, "=", false));
if (StrUtil.isBlank(assignment.getMatterId()) || StrUtil.isBlank(assignment.getLoginName())) { if (StrUtil.isBlank(assignment.getMatterId()) || StrUtil.isBlank(assignment.getLoginName())) {
return; return;
} }
dao().update(ThirtyTeachTourLedger.class, dao().update(ThirtyTeachTourLedger.class,
Chain.make("photoFiles", normalizedPhotoFiles), Chain.make("photoFiles", normalizedPhotoFiles)
.add("currentPeriodPhotoFiles", normalizedCurrentPeriodPhotoFiles),
Cnd.where(ThirtyTeachTourLedger::getMatterId, "=", assignment.getMatterId()) Cnd.where(ThirtyTeachTourLedger::getMatterId, "=", assignment.getMatterId())
.and(ThirtyTeachTourLedger::getJobNo, "=", assignment.getLoginName()) .and(ThirtyTeachTourLedger::getJobNo, "=", assignment.getLoginName())
.and(ThirtyTeachTourLedger::getDelFlag, "=", false)); .and(ThirtyTeachTourLedger::getDelFlag, "=", false));
@@ -1426,7 +1459,9 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
.add("lineName", null) .add("lineName", null)
.add("travelAgencyId", null) .add("travelAgencyId", null)
.add("travelAgencyName", null) .add("travelAgencyName", null)
.add("boardingPlace", null), .add("boardingPlace", null)
.add("photoFiles", null)
.add("currentPeriodPhotoFiles", null),
Cnd.where(ThirtyTeachTourUserAssignment::getId, "=", assignmentId) Cnd.where(ThirtyTeachTourUserAssignment::getId, "=", assignmentId)
.and(ThirtyTeachTourUserAssignment::getDelFlag, "=", false)); .and(ThirtyTeachTourUserAssignment::getDelFlag, "=", false));
} }
@@ -1641,6 +1676,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
fillMatterSnapshot(assignment, matterInfo); fillMatterSnapshot(assignment, matterInfo);
// 图片材料来自人员分配/报名提交快照,不能放在事项快照方法中读取。 // 图片材料来自人员分配/报名提交快照,不能放在事项快照方法中读取。
assignment.setPhotoFiles(normalizePhotoFiles(user.getString("photoFiles"))); assignment.setPhotoFiles(normalizePhotoFiles(user.getString("photoFiles")));
assignment.setCurrentPeriodPhotoFiles(normalizePhotoFiles(user.getString("currentPeriodPhotoFiles")));
assignment.setUserId(user.getString("userId")); assignment.setUserId(user.getString("userId"));
assignment.setLoginName(user.getString("loginName")); assignment.setLoginName(user.getString("loginName"));
assignment.setUserName(user.getString("userName")); assignment.setUserName(user.getString("userName"));
@@ -1685,7 +1721,8 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
assignment.setPeriodName(period.getPeriodName()); assignment.setPeriodName(period.getPeriodName());
} }
private void updateAssignmentMatterSnapshot(String id, NutMap matterInfo, String assignSource, String photoFiles) { private void updateAssignmentMatterSnapshot(String id, NutMap matterInfo, String assignSource,
String photoFiles, String currentPeriodPhotoFiles) {
// 补选事项时同时回写人员分配表事项快照,后续列表筛选无需再跨表追溯事项信息。 // 补选事项时同时回写人员分配表事项快照,后续列表筛选无需再跨表追溯事项信息。
update(Chain.make("matterId", matterInfo.getString("matterId")) update(Chain.make("matterId", matterInfo.getString("matterId"))
.add("matterName", matterInfo.getString("matterName")) .add("matterName", matterInfo.getString("matterName"))
@@ -1694,7 +1731,8 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
.add("travelAgencyId", matterInfo.getString("travelAgencyId")) .add("travelAgencyId", matterInfo.getString("travelAgencyId"))
.add("travelAgencyName", matterInfo.getString("travelAgencyName")) .add("travelAgencyName", matterInfo.getString("travelAgencyName"))
.add("boardingPlace", matterInfo.getString("defaultBoardingPlace")) .add("boardingPlace", matterInfo.getString("defaultBoardingPlace"))
.add("photoFiles", normalizePhotoFiles(photoFiles)), .add("photoFiles", normalizePhotoFiles(photoFiles))
.add("currentPeriodPhotoFiles", normalizePhotoFiles(currentPeriodPhotoFiles)),
Cnd.where(ThirtyTeachTourUserAssignment::getId, "=", id) Cnd.where(ThirtyTeachTourUserAssignment::getId, "=", id)
.and(ThirtyTeachTourUserAssignment::getAssignSource, "=", assignSource)); .and(ThirtyTeachTourUserAssignment::getAssignSource, "=", assignSource));
} }
@@ -1807,6 +1845,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
if (Lang.isNotEmpty(users)) { if (Lang.isNotEmpty(users)) {
NutMap user = users.get(0); NutMap user = users.get(0);
user.put("photoFiles", assignment.getPhotoFiles()); user.put("photoFiles", assignment.getPhotoFiles());
user.put("currentPeriodPhotoFiles", assignment.getCurrentPeriodPhotoFiles());
return user; return user;
} }
// 视图中找不到人员时使用分配表快照兜底,保证补选事项不会因非关键字段缺失中断。 // 视图中找不到人员时使用分配表快照兜底,保证补选事项不会因非关键字段缺失中断。
@@ -1820,7 +1859,8 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
.addv("unitName", assignment.getUnitName()) .addv("unitName", assignment.getUnitName())
.addv("unionId", assignment.getUnionId()) .addv("unionId", assignment.getUnionId())
.addv("unionName", assignment.getUnionName()) .addv("unionName", assignment.getUnionName())
.addv("photoFiles", assignment.getPhotoFiles()); .addv("photoFiles", assignment.getPhotoFiles())
.addv("currentPeriodPhotoFiles", assignment.getCurrentPeriodPhotoFiles());
} }
private ThirtyTeachTourLedger buildProxySignupLedger(NutMap matterInfo, NutMap user) { private ThirtyTeachTourLedger buildProxySignupLedger(NutMap matterInfo, NutMap user) {
@@ -1843,6 +1883,7 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
ledger.setTravelAgencyName(matterInfo.getString("travelAgencyName")); ledger.setTravelAgencyName(matterInfo.getString("travelAgencyName"));
ledger.setBoardingPlace(matterInfo.getString("defaultBoardingPlace")); ledger.setBoardingPlace(matterInfo.getString("defaultBoardingPlace"));
ledger.setPhotoFiles(normalizePhotoFiles(user.getString("photoFiles"))); ledger.setPhotoFiles(normalizePhotoFiles(user.getString("photoFiles")));
ledger.setCurrentPeriodPhotoFiles(normalizePhotoFiles(user.getString("currentPeriodPhotoFiles")));
ledger.setHasFamily(false); ledger.setHasFamily(false);
ledger.setJoined(false); ledger.setJoined(false);
ledger.setReimbursed(false); ledger.setReimbursed(false);
@@ -1920,11 +1961,14 @@ public class ThirtyTeachTourUserAssignmentServiceImpl extends BaseServiceImpl<Th
/** /**
* 批量人员共用同一组上传图片时,将图片路径写入候选人快照,后续构建分配表和台账时直接读取。 * 批量人员共用同一组上传图片时,将图片路径写入候选人快照,后续构建分配表和台账时直接读取。
*/ */
private void fillCandidatePhotoFiles(List<NutMap> candidateUsers, String photoFiles) { private void fillCandidatePhotoFiles(List<NutMap> candidateUsers, String photoFiles, String currentPeriodPhotoFiles) {
if (Lang.isEmpty(candidateUsers)) { if (Lang.isEmpty(candidateUsers)) {
return; return;
} }
candidateUsers.forEach(user -> user.put("photoFiles", photoFiles)); candidateUsers.forEach(user -> {
user.put("photoFiles", photoFiles);
user.put("currentPeriodPhotoFiles", currentPeriodPhotoFiles);
});
} }
private Pagination<NutMap> emptyPagination(PageForm pageForm) { private Pagination<NutMap> emptyPagination(PageForm pageForm) {
@@ -1,7 +1,7 @@
-- 30年教龄疗休养报名图片材料字段。 -- 30年教龄疗休养30年前图片材料字段。
-- PC端选择线路、移动端提交报名上传的多张图片统一保存为逗号分隔路径。 -- PC端选择线路、移动端提交报名上传的多张图片统一保存为逗号分隔路径。
ALTER TABLE `thirty_teach_tour_user_assignment` 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` 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`;
@@ -22,7 +22,8 @@ CREATE TABLE IF NOT EXISTS `thirty_teach_tour_ledger` (
`travelAgencyId` varchar(32) DEFAULT NULL COMMENT '旅行社ID', `travelAgencyId` varchar(32) DEFAULT NULL COMMENT '旅行社ID',
`travelAgencyName` varchar(100) DEFAULT NULL COMMENT '旅行社', `travelAgencyName` varchar(100) DEFAULT NULL COMMENT '旅行社',
`boardingPlace` 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 '是否携带家属', `hasFamily` tinyint(1) DEFAULT 0 COMMENT '是否携带家属',
`intendedRoommate` varchar(100) DEFAULT NULL COMMENT '意向拼床人', `intendedRoommate` varchar(100) DEFAULT NULL COMMENT '意向拼床人',
`bedType` varchar(50) DEFAULT NULL COMMENT '床型', `bedType` varchar(50) DEFAULT NULL COMMENT '床型',
@@ -9,7 +9,8 @@ CREATE TABLE IF NOT EXISTS `thirty_teach_tour_user_assignment` (
`lineId` varchar(32) DEFAULT NULL COMMENT '线路ID', `lineId` varchar(32) DEFAULT NULL COMMENT '线路ID',
`lineName` varchar(100) DEFAULT NULL COMMENT '线路名称', `lineName` varchar(100) DEFAULT NULL COMMENT '线路名称',
`boardingPlace` 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', `periodId` varchar(32) DEFAULT NULL COMMENT '出行时间段ID',
`periodName` varchar(50) DEFAULT NULL COMMENT '出行时间段名称', `periodName` varchar(50) DEFAULT NULL COMMENT '出行时间段名称',
`userId` varchar(32) DEFAULT NULL COMMENT '人员ID', `userId` varchar(32) DEFAULT NULL COMMENT '人员ID',
@@ -95,7 +95,7 @@ layout("/layouts/platform.html"){
<el-table-column label="操作" width="470" align="center" header-align="center" fixed="right"> <el-table-column label="操作" width="470" align="center" header-align="center" fixed="right">
<template slot-scope="{row}"> <template slot-scope="{row}">
<el-button v-if="!row.matterId && row.personType !== 'BACKUP' && $auth.hasPermission('thirtyTeachTour.branchUserAssignment.selectMatter')" size="mini" type="primary" @click="openSelectMatter(row)">选择路线</el-button> <el-button v-if="!row.matterId && row.personType !== 'BACKUP' && $auth.hasPermission('thirtyTeachTour.branchUserAssignment.selectMatter')" size="mini" type="primary" @click="openSelectMatter(row)">选择路线</el-button>
<el-button v-if="$auth.hasPermission('thirtyTeachTour.branchUserAssignment.assign')" size="mini" type="primary" @click="openListPhotoUpload(row)">{{ row.photoFiles ? "已上传" : "上传图片" }}</el-button> <el-button v-if="$auth.hasPermission('thirtyTeachTour.branchUserAssignment.assign')" size="mini" type="primary" @click="openListPhotoUpload(row)">{{ photoFileCount(row) > 0 ? "已上传" : "上传图片" }}</el-button>
<el-button v-if="$auth.hasPermission('thirtyTeachTour.branchUserAssignment.switchPersonType')" size="mini" type="primary" :loading="personTypeSwitching === row.id" @click="switchPersonType(row, row.personType === 'BACKUP' ? 'FORMAL' : 'BACKUP')">{{ row.personType === 'BACKUP' ? '转为正式' : '转为替补' }}</el-button> <el-button v-if="$auth.hasPermission('thirtyTeachTour.branchUserAssignment.switchPersonType')" size="mini" type="primary" :loading="personTypeSwitching === row.id" @click="switchPersonType(row, row.personType === 'BACKUP' ? 'FORMAL' : 'BACKUP')">{{ row.personType === 'BACKUP' ? '转为正式' : '转为替补' }}</el-button>
<el-button v-if="isCancelled(row) && $auth.hasPermission('thirtyTeachTour.branchUserAssignment.cancelRestore')" size="mini" type="warning" @click="restoreCancel(row)">取消退出</el-button> <el-button v-if="isCancelled(row) && $auth.hasPermission('thirtyTeachTour.branchUserAssignment.cancelRestore')" size="mini" type="warning" @click="restoreCancel(row)">取消退出</el-button>
<el-button v-if="$auth.hasPermission('thirtyTeachTour.branchUserAssignment.delete')" size="mini" type="danger" @click="doDelete(row)">删除</el-button> <el-button v-if="$auth.hasPermission('thirtyTeachTour.branchUserAssignment.delete')" size="mini" type="danger" @click="doDelete(row)">删除</el-button>
@@ -228,7 +228,7 @@ layout("/layouts/platform.html"){
<el-table-column label="材料" width="110" align="center" header-align="center"> <el-table-column label="材料" width="110" align="center" header-align="center">
<template slot-scope="{row}"> <template slot-scope="{row}">
<el-button type="text" size="mini" :disabled="!isCandidateSelected(row)" @click="openPhotoUpload(row)"> <el-button type="text" size="mini" :disabled="!isCandidateSelected(row)" @click="openPhotoUpload(row)">
{{ row.photoFiles ? "已上传" : "上传" }} {{ photoFileCount(row) > 0 ? "已上传" : "上传" }}
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
@@ -261,7 +261,7 @@ layout("/layouts/platform.html"){
<el-form-item label="人员"> <el-form-item label="人员">
<el-input v-model="photoUploadForm.userName" disabled></el-input> <el-input v-model="photoUploadForm.userName" disabled></el-input>
</el-form-item> </el-form-item>
<el-form-item label="图片材料"> <el-form-item label="30年前图片">
<file-upload <file-upload
style="--upload-width: 96px;--upload-height:96px" style="--upload-width: 96px;--upload-height:96px"
:upload_number="9" :upload_number="9"
@@ -273,6 +273,18 @@ layout("/layouts/platform.html"){
upload_result_category="interval"> upload_result_category="interval">
</file-upload> </file-upload>
</el-form-item> </el-form-item>
<el-form-item label="当前时间段图片">
<file-upload
style="--upload-width: 96px;--upload-height:96px"
:upload_number="9"
:upload_size="20971520"
:value.sync="photoUploadForm.currentPeriodPhotoFiles"
accept=".jpg,.jpeg,.png"
complete_result
upload_mode="image"
upload_result_category="interval">
</file-upload>
</el-form-item>
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="photoUploadDialogVisible = false">取消</el-button> <el-button @click="photoUploadDialogVisible = false">取消</el-button>
@@ -290,7 +302,7 @@ layout("/layouts/platform.html"){
<el-form-item label="人员"> <el-form-item label="人员">
<el-input v-model="listPhotoForm.userName" disabled></el-input> <el-input v-model="listPhotoForm.userName" disabled></el-input>
</el-form-item> </el-form-item>
<el-form-item label="图片材料"> <el-form-item label="30年前图片">
<file-upload <file-upload
style="--upload-width: 96px;--upload-height:96px" style="--upload-width: 96px;--upload-height:96px"
:upload_number="9" :upload_number="9"
@@ -302,6 +314,18 @@ layout("/layouts/platform.html"){
upload_result_category="interval"> upload_result_category="interval">
</file-upload> </file-upload>
</el-form-item> </el-form-item>
<el-form-item label="当前时间段图片">
<file-upload
style="--upload-width: 96px;--upload-height:96px"
:upload_number="9"
:upload_size="20971520"
:value.sync="listPhotoForm.currentPeriodPhotoFiles"
accept=".jpg,.jpeg,.png"
complete_result
upload_mode="image"
upload_result_category="interval">
</file-upload>
</el-form-item>
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="listPhotoDialogVisible = false">取消</el-button> <el-button @click="listPhotoDialogVisible = false">取消</el-button>
@@ -324,7 +348,7 @@ layout("/layouts/platform.html"){
<el-option v-for="item in selectMatterOptions" :key="item.matterId" :label="matterOptionLabel(item)" :value="item.matterId"></el-option> <el-option v-for="item in selectMatterOptions" :key="item.matterId" :label="matterOptionLabel(item)" :value="item.matterId"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="图片材料"> <el-form-item label="30年前图片">
<file-upload <file-upload
style="--upload-width: 96px;--upload-height:96px" style="--upload-width: 96px;--upload-height:96px"
:upload_number="9" :upload_number="9"
@@ -336,6 +360,18 @@ layout("/layouts/platform.html"){
upload_result_category="interval"> upload_result_category="interval">
</file-upload> </file-upload>
</el-form-item> </el-form-item>
<el-form-item label="当前时间段图片">
<file-upload
style="--upload-width: 96px;--upload-height:96px"
:upload_number="9"
:upload_size="20971520"
:value.sync="selectMatterForm.currentPeriodPhotoFiles"
accept=".jpg,.jpeg,.png"
complete_result
upload_mode="image"
upload_result_category="interval">
</file-upload>
</el-form-item>
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="selectMatterDialogVisible = false">取消</el-button> <el-button @click="selectMatterDialogVisible = false">取消</el-button>
@@ -464,7 +500,8 @@ layout("/layouts/platform.html"){
photoUploadForm: { photoUploadForm: {
userId: "", userId: "",
userName: "", userName: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
}, },
selectMatterDialogVisible: false, selectMatterDialogVisible: false,
selectMatterSubmitting: false, selectMatterSubmitting: false,
@@ -475,7 +512,8 @@ layout("/layouts/platform.html"){
listPhotoForm: { listPhotoForm: {
id: "", id: "",
userName: "", userName: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
}, },
personTypeSwitching: "", personTypeSwitching: "",
pageForm: { pageForm: {
@@ -510,7 +548,8 @@ layout("/layouts/platform.html"){
settingId: "", settingId: "",
matterId: "", matterId: "",
userName: "", userName: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
}, },
assignRules: { assignRules: {
year: [{required: true, message: "请选择年度", trigger: ["change", "blur"]}], year: [{required: true, message: "请选择年度", trigger: ["change", "blur"]}],
@@ -557,7 +596,8 @@ layout("/layouts/platform.html"){
settingId: "", settingId: "",
matterId: "", matterId: "",
userName: "", userName: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
} }
}, },
resetSearch() { resetSearch() {
@@ -818,14 +858,15 @@ layout("/layouts/platform.html"){
pageNumber: this.candidateForm.pageNumber, pageNumber: this.candidateForm.pageNumber,
pageSize: this.candidateForm.pageSize, pageSize: this.candidateForm.pageSize,
settingId: this.assignForm.settingId, settingId: this.assignForm.settingId,
retiringSoon: this.candidateForm.retiringSoon, retiringSoon: this.normalizeCandidateFilterValue(this.candidateForm.retiringSoon),
keyword: (this.selectedCandidateIds || []).length > 0 ? "" : this.candidateForm.keyword, keyword: (this.selectedCandidateIds || []).length > 0 ? "" : this.candidateForm.keyword,
userIds: JSON.stringify(this.selectedCandidateIds || []) userIds: JSON.stringify(this.selectedCandidateIds || [])
}).then((res) => { }).then((res) => {
if (res.code === 0) { if (res.code === 0) {
const data = res.data || {} const data = res.data || {}
this.candidateData = (data.list || []).map(item => Object.assign({}, item, { this.candidateData = (data.list || []).map(item => Object.assign({}, item, {
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
})) }))
this.candidateForm.totalCount = data.totalCount || 0 this.candidateForm.totalCount = data.totalCount || 0
this.mergeCandidateOptions(this.candidateData) this.mergeCandidateOptions(this.candidateData)
@@ -876,7 +917,7 @@ layout("/layouts/platform.html"){
pageNumber: 1, pageNumber: 1,
pageSize: 20, pageSize: 20,
settingId: this.assignForm.settingId, settingId: this.assignForm.settingId,
retiringSoon: this.candidateForm.retiringSoon, retiringSoon: this.normalizeCandidateFilterValue(this.candidateForm.retiringSoon),
keyword: keyword || "" keyword: keyword || ""
}).then((res) => { }).then((res) => {
if (res.code === 0) { if (res.code === 0) {
@@ -891,6 +932,10 @@ layout("/layouts/platform.html"){
// 人员选择器仅作为查询条件;最终分配人员仍由下方列表勾选决定。 // 人员选择器仅作为查询条件;最终分配人员仍由下方列表勾选决定。
this.selectedCandidateIds = userIds || [] this.selectedCandidateIds = userIds || []
}, },
normalizeCandidateFilterValue(value) {
// 候选人员下拉清空后按“不筛选”处理,避免空字符串被后端转换成 false 后继续追加条件。
return value === "" || value === undefined ? null : value
},
candidateOptionLabel(item) { candidateOptionLabel(item) {
if (!item) { if (!item) {
return "" return ""
@@ -922,13 +967,15 @@ layout("/layouts/platform.html"){
this.photoUploadForm = { this.photoUploadForm = {
userId: row.userId || "", userId: row.userId || "",
userName: row.userName || "", userName: row.userName || "",
photoFiles: row.photoFiles || "" photoFiles: row.photoFiles || "",
currentPeriodPhotoFiles: row.currentPeriodPhotoFiles || ""
} }
this.photoUploadDialogVisible = true this.photoUploadDialogVisible = true
}, },
confirmPhotoUpload() { confirmPhotoUpload() {
if (this.photoUploadRow) { if (this.photoUploadRow) {
this.$set(this.photoUploadRow, "photoFiles", this.photoUploadForm.photoFiles || "") this.$set(this.photoUploadRow, "photoFiles", this.photoUploadForm.photoFiles || "")
this.$set(this.photoUploadRow, "currentPeriodPhotoFiles", this.photoUploadForm.currentPeriodPhotoFiles || "")
} }
this.photoUploadDialogVisible = false this.photoUploadDialogVisible = false
}, },
@@ -937,7 +984,8 @@ layout("/layouts/platform.html"){
this.photoUploadForm = { this.photoUploadForm = {
userId: "", userId: "",
userName: "", userName: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
} }
}, },
openListPhotoUpload(row) { openListPhotoUpload(row) {
@@ -946,7 +994,8 @@ layout("/layouts/platform.html"){
this.listPhotoForm = { this.listPhotoForm = {
id: row.id || "", id: row.id || "",
userName: row.userName || "", userName: row.userName || "",
photoFiles: row.photoFiles || "" photoFiles: row.photoFiles || "",
currentPeriodPhotoFiles: row.currentPeriodPhotoFiles || ""
} }
this.listPhotoDialogVisible = true this.listPhotoDialogVisible = true
}, },
@@ -956,7 +1005,8 @@ layout("/layouts/platform.html"){
this.listPhotoForm = { this.listPhotoForm = {
id: "", id: "",
userName: "", userName: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
} }
}, },
saveListPhotoFiles() { saveListPhotoFiles() {
@@ -967,11 +1017,13 @@ layout("/layouts/platform.html"){
this.listPhotoSubmitting = true this.listPhotoSubmitting = true
this.$axios.post(loc() + "/updatePhotoFiles", { this.$axios.post(loc() + "/updatePhotoFiles", {
id: this.listPhotoForm.id, id: this.listPhotoForm.id,
photoFiles: this.listPhotoForm.photoFiles || "" photoFiles: this.listPhotoForm.photoFiles || "",
currentPeriodPhotoFiles: this.listPhotoForm.currentPeriodPhotoFiles || ""
}).then((res) => { }).then((res) => {
if (res.code === 0) { if (res.code === 0) {
if (this.listPhotoRow) { if (this.listPhotoRow) {
this.$set(this.listPhotoRow, "photoFiles", this.listPhotoForm.photoFiles || "") this.$set(this.listPhotoRow, "photoFiles", this.listPhotoForm.photoFiles || "")
this.$set(this.listPhotoRow, "currentPeriodPhotoFiles", this.listPhotoForm.currentPeriodPhotoFiles || "")
} }
this.$message.success("图片材料保存成功") this.$message.success("图片材料保存成功")
this.listPhotoDialogVisible = false this.listPhotoDialogVisible = false
@@ -1008,7 +1060,8 @@ layout("/layouts/platform.html"){
const assignItems = this.selectedCandidates.map(item => { const assignItems = this.selectedCandidates.map(item => {
return { return {
userId: item.userId, userId: item.userId,
photoFiles: item.photoFiles || "" photoFiles: item.photoFiles || "",
currentPeriodPhotoFiles: item.currentPeriodPhotoFiles || ""
} }
}) })
this.assignSubmitting = true this.assignSubmitting = true
@@ -1055,7 +1108,8 @@ layout("/layouts/platform.html"){
settingId: row.settingId, settingId: row.settingId,
matterId: "", matterId: "",
userName: row.userName || "", userName: row.userName || "",
photoFiles: "" photoFiles: row.photoFiles || "",
currentPeriodPhotoFiles: row.currentPeriodPhotoFiles || ""
} }
this.selectMatterOptions = [] this.selectMatterOptions = []
this.selectMatterDialogVisible = true this.selectMatterDialogVisible = true
@@ -1084,7 +1138,8 @@ layout("/layouts/platform.html"){
this.$axios.post(loc() + "/selectMatter", { this.$axios.post(loc() + "/selectMatter", {
id: this.selectMatterForm.id, id: this.selectMatterForm.id,
matterId: this.selectMatterForm.matterId, matterId: this.selectMatterForm.matterId,
photoFiles: this.selectMatterForm.photoFiles photoFiles: this.selectMatterForm.photoFiles,
currentPeriodPhotoFiles: this.selectMatterForm.currentPeriodPhotoFiles
}).then((res) => { }).then((res) => {
if (res.code === 0) { if (res.code === 0) {
const data = res.data || {} const data = res.data || {}
@@ -1134,10 +1189,12 @@ layout("/layouts/platform.html"){
return row && (row.cancelled === true || row.cancelled === 1) return row && (row.cancelled === true || row.cancelled === 1)
}, },
photoFileCount(row) { photoFileCount(row) {
if (!row || !row.photoFiles) { if (!row) {
return 0 return 0
} }
return String(row.photoFiles).split(",").map(item => item.trim()).filter(item => item).length const photoCount = row.photoFiles ? String(row.photoFiles).split(",").map(item => item.trim()).filter(item => item).length : 0
const currentPhotoCount = row.currentPeriodPhotoFiles ? String(row.currentPeriodPhotoFiles).split(",").map(item => item.trim()).filter(item => item).length : 0
return photoCount + currentPhotoCount
}, },
restoreCancel(row) { restoreCancel(row) {
this.$confirm("确定将【" + row.userName + "】恢复为未退出状态吗?", "提示", { this.$confirm("确定将【" + row.userName + "】恢复为未退出状态吗?", "提示", {
@@ -118,7 +118,7 @@ layout("/layouts/platform.html"){
<el-table-column label="操作" width="410" align="center" header-align="center" fixed="right"> <el-table-column label="操作" width="410" align="center" header-align="center" fixed="right">
<template slot-scope="{row}"> <template slot-scope="{row}">
<el-button v-if="isSchoolUnionAssignment(row) && !row.matterId && row.personType !== 'BACKUP'" size="mini" type="primary" @click="openSelectMatter(row)">选择线路</el-button> <el-button v-if="isSchoolUnionAssignment(row) && !row.matterId && row.personType !== 'BACKUP'" size="mini" type="primary" @click="openSelectMatter(row)">选择线路</el-button>
<el-button v-if="isSchoolUnionAssignment(row)" size="mini" type="primary" @click="openListPhotoUpload(row)">{{ row.photoFiles ? "已上传" : "上传图片" }}</el-button> <el-button v-if="isSchoolUnionAssignment(row)" size="mini" type="primary" @click="openListPhotoUpload(row)">{{ photoFileCount(row) > 0 ? "已上传" : "上传图片" }}</el-button>
<el-button v-if="isSchoolUnionAssignment(row) && isCancelled(row) && $auth.hasPermission('thirtyTeachTour.schoolUserAssignment.cancelRestore')" size="mini" type="warning" @click="restoreCancel(row)">取消退出</el-button> <el-button v-if="isSchoolUnionAssignment(row) && isCancelled(row) && $auth.hasPermission('thirtyTeachTour.schoolUserAssignment.cancelRestore')" size="mini" type="warning" @click="restoreCancel(row)">取消退出</el-button>
<el-button v-if="isSchoolUnionAssignment(row)" size="mini" type="danger" @click="doDelete(row)">删除</el-button> <el-button v-if="isSchoolUnionAssignment(row)" size="mini" type="danger" @click="doDelete(row)">删除</el-button>
</template> </template>
@@ -261,7 +261,7 @@ layout("/layouts/platform.html"){
<el-table-column label="材料" width="110" align="center" header-align="center"> <el-table-column label="材料" width="110" align="center" header-align="center">
<template slot-scope="{row}"> <template slot-scope="{row}">
<el-button type="text" size="mini" :disabled="!isCandidateSelected(row)" @click="openPhotoUpload(row)"> <el-button type="text" size="mini" :disabled="!isCandidateSelected(row)" @click="openPhotoUpload(row)">
{{ row.photoFiles ? "已上传" : "上传" }} {{ photoFileCount(row) > 0 ? "已上传" : "上传" }}
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
@@ -294,7 +294,7 @@ layout("/layouts/platform.html"){
<el-form-item label="人员"> <el-form-item label="人员">
<el-input v-model="photoUploadForm.userName" disabled></el-input> <el-input v-model="photoUploadForm.userName" disabled></el-input>
</el-form-item> </el-form-item>
<el-form-item label="图片材料"> <el-form-item label="30年前图片">
<file-upload <file-upload
style="--upload-width: 96px;--upload-height:96px" style="--upload-width: 96px;--upload-height:96px"
:upload_number="9" :upload_number="9"
@@ -306,6 +306,18 @@ layout("/layouts/platform.html"){
upload_result_category="interval"> upload_result_category="interval">
</file-upload> </file-upload>
</el-form-item> </el-form-item>
<el-form-item label="当前时间段图片">
<file-upload
style="--upload-width: 96px;--upload-height:96px"
:upload_number="9"
:upload_size="20971520"
:value.sync="photoUploadForm.currentPeriodPhotoFiles"
accept=".jpg,.jpeg,.png"
complete_result
upload_mode="image"
upload_result_category="interval">
</file-upload>
</el-form-item>
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="photoUploadDialogVisible = false">取消</el-button> <el-button @click="photoUploadDialogVisible = false">取消</el-button>
@@ -323,7 +335,7 @@ layout("/layouts/platform.html"){
<el-form-item label="人员"> <el-form-item label="人员">
<el-input v-model="listPhotoForm.userName" disabled></el-input> <el-input v-model="listPhotoForm.userName" disabled></el-input>
</el-form-item> </el-form-item>
<el-form-item label="图片材料"> <el-form-item label="30年前图片">
<file-upload <file-upload
style="--upload-width: 96px;--upload-height:96px" style="--upload-width: 96px;--upload-height:96px"
:upload_number="9" :upload_number="9"
@@ -335,6 +347,18 @@ layout("/layouts/platform.html"){
upload_result_category="interval"> upload_result_category="interval">
</file-upload> </file-upload>
</el-form-item> </el-form-item>
<el-form-item label="当前时间段图片">
<file-upload
style="--upload-width: 96px;--upload-height:96px"
:upload_number="9"
:upload_size="20971520"
:value.sync="listPhotoForm.currentPeriodPhotoFiles"
accept=".jpg,.jpeg,.png"
complete_result
upload_mode="image"
upload_result_category="interval">
</file-upload>
</el-form-item>
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="listPhotoDialogVisible = false">取消</el-button> <el-button @click="listPhotoDialogVisible = false">取消</el-button>
@@ -357,7 +381,7 @@ layout("/layouts/platform.html"){
<el-option v-for="item in selectMatterOptions" :key="item.matterId" :label="matterOptionLabel(item)" :value="item.matterId"></el-option> <el-option v-for="item in selectMatterOptions" :key="item.matterId" :label="matterOptionLabel(item)" :value="item.matterId"></el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="图片材料"> <el-form-item label="30年前图片">
<file-upload <file-upload
style="--upload-width: 96px;--upload-height:96px" style="--upload-width: 96px;--upload-height:96px"
:upload_number="9" :upload_number="9"
@@ -369,6 +393,18 @@ layout("/layouts/platform.html"){
upload_result_category="interval"> upload_result_category="interval">
</file-upload> </file-upload>
</el-form-item> </el-form-item>
<el-form-item label="当前时间段图片">
<file-upload
style="--upload-width: 96px;--upload-height:96px"
:upload_number="9"
:upload_size="20971520"
:value.sync="selectMatterForm.currentPeriodPhotoFiles"
accept=".jpg,.jpeg,.png"
complete_result
upload_mode="image"
upload_result_category="interval">
</file-upload>
</el-form-item>
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="selectMatterDialogVisible = false">取消</el-button> <el-button @click="selectMatterDialogVisible = false">取消</el-button>
@@ -453,7 +489,8 @@ layout("/layouts/platform.html"){
photoUploadForm: { photoUploadForm: {
userId: "", userId: "",
userName: "", userName: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
}, },
selectMatterDialogVisible: false, selectMatterDialogVisible: false,
selectMatterSubmitting: false, selectMatterSubmitting: false,
@@ -464,7 +501,8 @@ layout("/layouts/platform.html"){
listPhotoForm: { listPhotoForm: {
id: "", id: "",
userName: "", userName: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
}, },
pageForm: { pageForm: {
pageNumber: 1, pageNumber: 1,
@@ -502,7 +540,8 @@ layout("/layouts/platform.html"){
settingId: "", settingId: "",
matterId: "", matterId: "",
userName: "", userName: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
}, },
remindForm: { remindForm: {
content: "" content: ""
@@ -545,7 +584,8 @@ layout("/layouts/platform.html"){
settingId: "", settingId: "",
matterId: "", matterId: "",
userName: "", userName: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
} }
}, },
defaultRemindForm() { defaultRemindForm() {
@@ -805,9 +845,9 @@ layout("/layouts/platform.html"){
pageSize: this.candidateForm.pageSize, pageSize: this.candidateForm.pageSize,
settingId: this.assignForm.settingId, settingId: this.assignForm.settingId,
unionId: this.candidateForm.unionId, unionId: this.candidateForm.unionId,
retiringSoon: this.candidateForm.retiringSoon, retiringSoon: this.normalizeCandidateFilterValue(this.candidateForm.retiringSoon),
summerJoined: this.candidateForm.summerJoined, summerJoined: this.normalizeCandidateFilterValue(this.candidateForm.summerJoined),
lastThirtyJoined: this.candidateForm.lastThirtyJoined, lastThirtyJoined: this.normalizeCandidateFilterValue(this.candidateForm.lastThirtyJoined),
keyword: (this.selectedCandidateIds || []).length > 0 ? "" : this.candidateForm.keyword, keyword: (this.selectedCandidateIds || []).length > 0 ? "" : this.candidateForm.keyword,
userIds: JSON.stringify(this.selectedCandidateIds || []) userIds: JSON.stringify(this.selectedCandidateIds || [])
}).then((res) => { }).then((res) => {
@@ -815,7 +855,8 @@ layout("/layouts/platform.html"){
const data = res.data || {} const data = res.data || {}
this.candidateData = (data.list || []).map(item => Object.assign({}, item, { this.candidateData = (data.list || []).map(item => Object.assign({}, item, {
assignmentMatterId: "", assignmentMatterId: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
})) }))
this.candidateForm.totalCount = data.totalCount || 0 this.candidateForm.totalCount = data.totalCount || 0
this.mergeCandidateOptions(this.candidateData) this.mergeCandidateOptions(this.candidateData)
@@ -886,9 +927,9 @@ layout("/layouts/platform.html"){
pageSize: 20, pageSize: 20,
settingId: this.assignForm.settingId, settingId: this.assignForm.settingId,
unionId: this.candidateForm.unionId, unionId: this.candidateForm.unionId,
retiringSoon: this.candidateForm.retiringSoon, retiringSoon: this.normalizeCandidateFilterValue(this.candidateForm.retiringSoon),
summerJoined: this.candidateForm.summerJoined, summerJoined: this.normalizeCandidateFilterValue(this.candidateForm.summerJoined),
lastThirtyJoined: this.candidateForm.lastThirtyJoined, lastThirtyJoined: this.normalizeCandidateFilterValue(this.candidateForm.lastThirtyJoined),
keyword: keyword || "" keyword: keyword || ""
}).then((res) => { }).then((res) => {
if (res.code === 0) { if (res.code === 0) {
@@ -903,6 +944,10 @@ layout("/layouts/platform.html"){
// 人员选择器仅作为查询条件;最终分配人员仍由下方列表勾选决定。 // 人员选择器仅作为查询条件;最终分配人员仍由下方列表勾选决定。
this.selectedCandidateIds = userIds || [] this.selectedCandidateIds = userIds || []
}, },
normalizeCandidateFilterValue(value) {
// 候选人员下拉清空后按“不筛选”处理,避免空字符串被后端转换成 false 后继续追加条件。
return value === "" || value === undefined ? null : value
},
candidateOptionLabel(item) { candidateOptionLabel(item) {
if (!item) { if (!item) {
return "" return ""
@@ -934,13 +979,15 @@ layout("/layouts/platform.html"){
this.photoUploadForm = { this.photoUploadForm = {
userId: row.userId || "", userId: row.userId || "",
userName: row.userName || "", userName: row.userName || "",
photoFiles: row.photoFiles || "" photoFiles: row.photoFiles || "",
currentPeriodPhotoFiles: row.currentPeriodPhotoFiles || ""
} }
this.photoUploadDialogVisible = true this.photoUploadDialogVisible = true
}, },
confirmPhotoUpload() { confirmPhotoUpload() {
if (this.photoUploadRow) { if (this.photoUploadRow) {
this.$set(this.photoUploadRow, "photoFiles", this.photoUploadForm.photoFiles || "") this.$set(this.photoUploadRow, "photoFiles", this.photoUploadForm.photoFiles || "")
this.$set(this.photoUploadRow, "currentPeriodPhotoFiles", this.photoUploadForm.currentPeriodPhotoFiles || "")
} }
this.photoUploadDialogVisible = false this.photoUploadDialogVisible = false
}, },
@@ -949,7 +996,8 @@ layout("/layouts/platform.html"){
this.photoUploadForm = { this.photoUploadForm = {
userId: "", userId: "",
userName: "", userName: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
} }
}, },
openListPhotoUpload(row) { openListPhotoUpload(row) {
@@ -958,7 +1006,8 @@ layout("/layouts/platform.html"){
this.listPhotoForm = { this.listPhotoForm = {
id: row.id || "", id: row.id || "",
userName: row.userName || "", userName: row.userName || "",
photoFiles: row.photoFiles || "" photoFiles: row.photoFiles || "",
currentPeriodPhotoFiles: row.currentPeriodPhotoFiles || ""
} }
this.listPhotoDialogVisible = true this.listPhotoDialogVisible = true
}, },
@@ -968,7 +1017,8 @@ layout("/layouts/platform.html"){
this.listPhotoForm = { this.listPhotoForm = {
id: "", id: "",
userName: "", userName: "",
photoFiles: "" photoFiles: "",
currentPeriodPhotoFiles: ""
} }
}, },
saveListPhotoFiles() { saveListPhotoFiles() {
@@ -979,11 +1029,13 @@ layout("/layouts/platform.html"){
this.listPhotoSubmitting = true this.listPhotoSubmitting = true
this.$axios.post(loc() + "/updatePhotoFiles", { this.$axios.post(loc() + "/updatePhotoFiles", {
id: this.listPhotoForm.id, id: this.listPhotoForm.id,
photoFiles: this.listPhotoForm.photoFiles || "" photoFiles: this.listPhotoForm.photoFiles || "",
currentPeriodPhotoFiles: this.listPhotoForm.currentPeriodPhotoFiles || ""
}).then((res) => { }).then((res) => {
if (res.code === 0) { if (res.code === 0) {
if (this.listPhotoRow) { if (this.listPhotoRow) {
this.$set(this.listPhotoRow, "photoFiles", this.listPhotoForm.photoFiles || "") this.$set(this.listPhotoRow, "photoFiles", this.listPhotoForm.photoFiles || "")
this.$set(this.listPhotoRow, "currentPeriodPhotoFiles", this.listPhotoForm.currentPeriodPhotoFiles || "")
} }
this.$message.success("图片材料保存成功") this.$message.success("图片材料保存成功")
this.listPhotoDialogVisible = false this.listPhotoDialogVisible = false
@@ -1017,7 +1069,8 @@ layout("/layouts/platform.html"){
return { return {
userId: item.userId, userId: item.userId,
matterId: item.assignmentMatterId || this.assignForm.matterId || "", matterId: item.assignmentMatterId || this.assignForm.matterId || "",
photoFiles: item.photoFiles || "" photoFiles: item.photoFiles || "",
currentPeriodPhotoFiles: item.currentPeriodPhotoFiles || ""
} }
}) })
this.assignSubmitting = true this.assignSubmitting = true
@@ -1045,7 +1098,8 @@ layout("/layouts/platform.html"){
settingId: row.settingId, settingId: row.settingId,
matterId: "", matterId: "",
userName: row.userName || "", userName: row.userName || "",
photoFiles: "" photoFiles: row.photoFiles || "",
currentPeriodPhotoFiles: row.currentPeriodPhotoFiles || ""
} }
this.selectMatterOptions = [] this.selectMatterOptions = []
this.selectMatterDialogVisible = true this.selectMatterDialogVisible = true
@@ -1074,7 +1128,8 @@ layout("/layouts/platform.html"){
this.$axios.post(loc() + "/selectMatter", { this.$axios.post(loc() + "/selectMatter", {
id: this.selectMatterForm.id, id: this.selectMatterForm.id,
matterId: this.selectMatterForm.matterId, matterId: this.selectMatterForm.matterId,
photoFiles: this.selectMatterForm.photoFiles photoFiles: this.selectMatterForm.photoFiles,
currentPeriodPhotoFiles: this.selectMatterForm.currentPeriodPhotoFiles
}).then((res) => { }).then((res) => {
if (res.code === 0) { if (res.code === 0) {
const data = res.data || {} const data = res.data || {}
@@ -1136,10 +1191,12 @@ layout("/layouts/platform.html"){
return row && (row.cancelled === true || row.cancelled === 1) return row && (row.cancelled === true || row.cancelled === 1)
}, },
photoFileCount(row) { photoFileCount(row) {
if (!row || !row.photoFiles) { if (!row) {
return 0 return 0
} }
return String(row.photoFiles).split(",").map(item => item.trim()).filter(item => item).length const photoCount = row.photoFiles ? String(row.photoFiles).split(",").map(item => item.trim()).filter(item => item).length : 0
const currentPhotoCount = row.currentPeriodPhotoFiles ? String(row.currentPeriodPhotoFiles).split(",").map(item => item.trim()).filter(item => item).length : 0
return photoCount + currentPhotoCount
}, },
restoreCancel(row) { restoreCancel(row) {
this.$confirm("确定将【" + row.userName + "】恢复为未退出状态吗?", "提示", { this.$confirm("确定将【" + row.userName + "】恢复为未退出状态吗?", "提示", {