From 41b370692e283b12b2d66060edfb1668e8dad562 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 1 Jun 2026 15:31:22 +0800 Subject: [PATCH] commit --- .../web/commons/proc/NutShiroProcessor.java | 4 +- .../basic/ActivityBasicScopeController.java | 59 ++++- .../controller/template/UserTemp.java | 18 ++ .../services/ActivityBasicScopeService.java | 25 ++ .../impl/ActivityBasicScopeServiceImpl.java | 123 +++++++++ ...RapyRecuperationBaseManagerController.java | 79 +++++- ...heRapyRecuperationUserQueryController.java | 26 ++ ...erationSchoolUnionUserQueryController.java | 20 +- .../TheRapyRecuperationConfigController.java | 79 ++---- .../TheRapyRecuperationBaseManagement.java | 6 + .../model/TheRapyRecuperationConfig.java | 10 + .../TheRapyRecuperationConfigService.java | 50 ++++ .../TheRapyRecuperationConfigServiceImpl.java | 236 ++++++++++++++++++ .../TheRapyRecuperationEnrollServiceImpl.java | 116 ++++++++- .../static/components/plugins/UserScope.vue | 156 +++++++++++- .../templates/travel/TravelEnrollImport.xlsx | Bin 0 -> 8813 bytes .../therapyRecuperation/baseManagement.html | 12 + .../baseManage/baseManagement.html | 19 +- .../schoolUnionUserQuery/index.html | 101 +++++++- .../theRapyConfig/TheRapyConfig.html | 169 +++++++++---- 20 files changed, 1175 insertions(+), 133 deletions(-) create mode 100644 src/main/java/io/v/nutz/zhgh/activity/controller/template/UserTemp.java create mode 100644 src/main/java/io/v/nutz/zhgh/therapyRecuperation/service/TheRapyRecuperationConfigService.java create mode 100644 src/main/java/io/v/nutz/zhgh/therapyRecuperation/service/impl/TheRapyRecuperationConfigServiceImpl.java create mode 100644 src/main/resources/templates/travel/TravelEnrollImport.xlsx diff --git a/src/main/java/io/v/nutz/web/commons/proc/NutShiroProcessor.java b/src/main/java/io/v/nutz/web/commons/proc/NutShiroProcessor.java index 8f902a3..2eaac3e 100644 --- a/src/main/java/io/v/nutz/web/commons/proc/NutShiroProcessor.java +++ b/src/main/java/io/v/nutz/web/commons/proc/NutShiroProcessor.java @@ -68,11 +68,11 @@ public class NutShiroProcessor extends AbstractProcessor { //不需要认证授权的url String[] authIgnoreUrlArr = Lang.array("/", "/sso/login", -// "/platform/login", + "/platform/login", "/platform/login(/doLogin|/logout|/captcha)", "/platform/qywechat/.*", "/platform/home/(500|403|404|UnknownAccountError|LockedAccountError)", -// "/mobile/login", + "/mobile/login", "/mobile/login/doLogin", "/platform/jsz/login", "/platform/activity/basic/scope/getScopeUser", diff --git a/src/main/java/io/v/nutz/zhgh/activity/controller/basic/ActivityBasicScopeController.java b/src/main/java/io/v/nutz/zhgh/activity/controller/basic/ActivityBasicScopeController.java index d1a570c..7b888ee 100644 --- a/src/main/java/io/v/nutz/zhgh/activity/controller/basic/ActivityBasicScopeController.java +++ b/src/main/java/io/v/nutz/zhgh/activity/controller/basic/ActivityBasicScopeController.java @@ -3,6 +3,7 @@ package io.v.nutz.zhgh.activity.controller.basic; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; import cn.hutool.core.util.StrUtil; import cn.wizzer.framework.base.Result; import io.v.nutz.base.utils.ViTool; @@ -31,9 +32,12 @@ import org.nutz.json.Json; import org.nutz.lang.Lang; import org.nutz.lang.util.NutMap; import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.AdaptBy; import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.POST; import org.nutz.mvc.annotation.Param; +import org.nutz.mvc.upload.TempFile; +import org.nutz.mvc.upload.UploadAdaptor; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @@ -105,7 +109,8 @@ public class ActivityBasicScopeController { @Param(value = "clubId", required = false) String clubId, @Param(value = "reverseSelection") boolean reverseSelection, @Param(value = "activityGroupId", required = false) Integer activityGroupId, - @Param(value = "activityUserCnd", required = false) String activityUserCndStr) { + @Param(value = "activityUserCnd", required = false) String activityUserCndStr, + @Param(value = "existsLoginNameRedisKey", required = false) String existsLoginNameRedisKey) { Sql sql = Sqls.create(""" SELECT DISTINCT(u.id) as id, @@ -127,6 +132,7 @@ public class ActivityBasicScopeController { """); try { Cnd cnd = getCnd(pageForm, unionId, unitId, personTypes, userStates, memberTypes, sexTypes, age, teacherMeetingId, roleIds, userId, clubId, reverseSelection, activityGroupId, activityUserCndStr); + activityBasicScopeService.appendImportUserCnd(cnd, existsLoginNameRedisKey); sql.setCondition(cnd); @@ -169,7 +175,8 @@ public class ActivityBasicScopeController { @Param(value = "userId", required = false) String[] userId, @Param(value = "clubId", required = false) String clubId, @Param(value = "reverseSelection") boolean reverseSelection, - @Param(value = "activityUserCnd", required = false) String activityUserCndStr) { + @Param(value = "activityUserCnd", required = false) String activityUserCndStr, + @Param(value = "existsLoginNameRedisKey", required = false) String existsLoginNameRedisKey) { Sql sql = Sqls.create(""" SELECT DISTINCT ( u.id ) AS userId @@ -180,6 +187,7 @@ public class ActivityBasicScopeController { $condition """); Cnd cnd = getCnd(pageForm, unionId, unitId, personTypes, userStates, memberTypes, sexTypes, age, teacherMeetingId, roleIds, userId, clubId, reverseSelection, activityGroupId, activityUserCndStr); + activityBasicScopeService.appendImportUserCnd(cnd, existsLoginNameRedisKey); sql.setCondition(cnd); sql.setCallback(Sqls.callback.entities()); @@ -322,7 +330,7 @@ public class ActivityBasicScopeController { } @At - @ViReturn + @Ok("void") @RequiresPermissions("activity.basic.scope") public void doExportUser(PageForm pageForm, @Param(value = "props", required = false) String props, @@ -339,7 +347,9 @@ public class ActivityBasicScopeController { @Param(value = "clubId", required = false) String clubId, @Param(value = "reverseSelection") boolean reverseSelection, @Param(value = "activityGroupId", required = false) Integer activityGroupId, - @Param(value = "activityUserCnd", required = false) String activityUserCndStr, HttpServletResponse response) { + @Param(value = "activityUserCnd", required = false) String activityUserCndStr, + @Param(value = "existsLoginNameRedisKey", required = false) String existsLoginNameRedisKey, + HttpServletResponse response) { Sql sql = Sqls.create(""" SELECT @@ -363,6 +373,7 @@ public class ActivityBasicScopeController { try { Cnd cnd = getCnd(pageForm, unionId, unitId, personTypes, userStates, memberTypes, sexTypes, age, teacherMeetingId, roleIds, userId, clubId, reverseSelection, activityGroupId, activityUserCndStr); + activityBasicScopeService.appendImportUserCnd(cnd, existsLoginNameRedisKey); sql.setCondition(cnd); @@ -377,14 +388,50 @@ public class ActivityBasicScopeController { entityList.add(new ExcelExportEntity(v, k, 40)); }); - ViTool.excelResponse(response, "人员名单.xls"); - Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), entityList, map); + ViTool.excelResponse(response, "人员名单.xlsx"); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, map); workbook.write(response.getOutputStream()); } catch (IOException e) { e.printStackTrace(); } } + @At + @Ok("void") + @RequiresPermissions("activity.basic.scope") + public void downloadImport(HttpServletResponse response) { + try { + ViTool.excelResponse(response, "人员导入模板.xlsx"); + List entityList = new ArrayList<>(); + entityList.add(new ExcelExportEntity("工号", "loginname", 20)); + entityList.add(new ExcelExportEntity("姓名", "username", 20)); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, new ArrayList<>()); + workbook.write(response.getOutputStream()); + } catch (IOException e) { + e.printStackTrace(); + } + } + + @At + @ViReturn + @RequiresPermissions("activity.basic.scope") + public Object clearSearchCnd(String existsLoginNameRedisKey) { + activityBasicScopeService.clearImportUserCnd(existsLoginNameRedisKey); + return null; + } + + @At + @ViReturn + @AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"}) + @RequiresPermissions("activity.basic.scope") + public Object doImport(TempFile file) { + return activityBasicScopeService.checkImportUser(file.getFile()); + } + private Cnd getCnd(PageForm pageForm, String unionId, diff --git a/src/main/java/io/v/nutz/zhgh/activity/controller/template/UserTemp.java b/src/main/java/io/v/nutz/zhgh/activity/controller/template/UserTemp.java new file mode 100644 index 0000000..2bf426a --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/activity/controller/template/UserTemp.java @@ -0,0 +1,18 @@ +package io.v.nutz.zhgh.activity.controller.template; + +import cn.afterturn.easypoi.excel.annotation.Excel; +import lombok.Data; + +@Data +public class UserTemp { + + @Excel(name = "工号") + private String loginname; + + @Excel(name = "姓名") + private String username; + + @Excel(name = "备注") + private String remarks; + +} diff --git a/src/main/java/io/v/nutz/zhgh/activity/services/ActivityBasicScopeService.java b/src/main/java/io/v/nutz/zhgh/activity/services/ActivityBasicScopeService.java index 1ed5c2b..1e936f3 100644 --- a/src/main/java/io/v/nutz/zhgh/activity/services/ActivityBasicScopeService.java +++ b/src/main/java/io/v/nutz/zhgh/activity/services/ActivityBasicScopeService.java @@ -4,7 +4,9 @@ import io.v.nutz.zhgh.activity.models.ActivityUserScope; import io.v.nutz.base.service.ViService; import org.nutz.dao.Cnd; import org.nutz.dao.sql.Sql; +import org.nutz.lang.util.NutMap; +import java.io.File; import java.util.List; /** @@ -21,4 +23,27 @@ public interface ActivityBasicScopeService extends ViService */ void largeDataInsert(List list) ; + /** + * 解析人员导入模板,核对系统中存在的工号,并把匹配到的工号暂存为后续查询条件。 + * + * @param file 上传的人员导入 Excel 文件 + * @return 导入总数、成功数、错误数、错误明细和临时查询 key + */ + NutMap checkImportUser(File file); + + /** + * 将导入核对成功的工号追加到当前查询条件中。 + * + * @param cnd 查询条件 + * @param existsLoginNameRedisKey 导入核对成功工号的临时缓存 key + */ + void appendImportUserCnd(Cnd cnd, String existsLoginNameRedisKey); + + /** + * 清理导入人员临时查询条件。 + * + * @param existsLoginNameRedisKey 导入核对成功工号的临时缓存 key + */ + void clearImportUserCnd(String existsLoginNameRedisKey); + } diff --git a/src/main/java/io/v/nutz/zhgh/activity/services/impl/ActivityBasicScopeServiceImpl.java b/src/main/java/io/v/nutz/zhgh/activity/services/impl/ActivityBasicScopeServiceImpl.java index e364afc..93e10d2 100644 --- a/src/main/java/io/v/nutz/zhgh/activity/services/impl/ActivityBasicScopeServiceImpl.java +++ b/src/main/java/io/v/nutz/zhgh/activity/services/impl/ActivityBasicScopeServiceImpl.java @@ -1,24 +1,37 @@ package io.v.nutz.zhgh.activity.services.impl; +import cn.afterturn.easypoi.excel.ExcelImportUtil; +import cn.afterturn.easypoi.excel.entity.ImportParams; import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.StrUtil; import io.v.nutz.zhgh.activity.models.ActivityUserScope; import io.v.nutz.zhgh.activity.services.ActivityBasicScopeService; import io.v.nutz.base.utils.DateUtil; import io.v.nutz.base.service.impl.ViServiceImpl; +import io.v.nutz.zhgh.activity.controller.template.UserTemp; import lombok.extern.slf4j.Slf4j; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; import org.nutz.dao.impl.NutTxDao; +import org.nutz.dao.Sqls; import org.nutz.dao.sql.Sql; +import org.nutz.integration.jedis.RedisService; +import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; +import java.io.File; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; /** * @author zxy @@ -28,6 +41,11 @@ import java.util.concurrent.atomic.AtomicInteger; @IocBean(args = {"refer:dao"}) @Slf4j public class ActivityBasicScopeServiceImpl extends ViServiceImpl implements ActivityBasicScopeService { + private static final String IMPORT_NO_MATCH_LOGIN_NAME = "__activity_scope_import_no_match__"; + + @Inject + private RedisService redisService; + public ActivityBasicScopeServiceImpl(Dao dao) { super(dao); } @@ -79,4 +97,109 @@ public class ActivityBasicScopeServiceImpl extends ViServiceImpl userImportList = ExcelImportUtil.importExcel(file, UserTemp.class, new ImportParams()); + if (userImportList == null) { + userImportList = new ArrayList<>(); + } + Set sysLoginNames = getSysLoginNames(); + List existsLoginNames = new ArrayList<>(); + + for (UserTemp excelUser : userImportList) { + if (excelUser == null || StrUtil.isBlank(excelUser.getLoginname())) { + if (excelUser != null) { + excelUser.setRemarks("工号不能为空"); + } + continue; + } + if (sysLoginNames.contains(excelUser.getLoginname())) { + existsLoginNames.add(excelUser.getLoginname()); + } else { + excelUser.setRemarks("系统查不到此人"); + } + } + + List errorExcelTempUsers = userImportList.stream() + .filter(v -> v != null && StrUtil.isNotBlank(v.getRemarks())) + .collect(Collectors.toList()); + + NutMap nutMap = NutMap.NEW(); + nutMap.setv("totalCount", userImportList.size()); + nutMap.setv("successCount", existsLoginNames.size()); + nutMap.setv("errorCount", errorExcelTempUsers.size()); + nutMap.setv("errorList", errorExcelTempUsers.stream().map(v -> NutMap.NEW() + .addv("工号", v.getLoginname()) + .addv("姓名", v.getUsername()) + .addv("错误原因", v.getRemarks())).collect(Collectors.toList())); + nutMap.setv("existsLoginNameRedisKey", matchUserLoginNamesKey); + + // 没有匹配人员时写入一个不可能存在的工号,避免后续查询误变成全量。 + String[] cacheLoginNames = Lang.isNotEmpty(existsLoginNames) + ? existsLoginNames.toArray(new String[0]) + : new String[]{IMPORT_NO_MATCH_LOGIN_NAME}; + redisService.lpush(matchUserLoginNamesKey, cacheLoginNames); + redisService.expire(matchUserLoginNamesKey, 60 * 60); + + return nutMap; + } + + /** + * 根据导入核对返回的 Redis key,给现有查询条件追加工号范围。 + * + * @param cnd 查询条件 + * @param existsLoginNameRedisKey 导入核对成功工号的临时缓存 key + */ + @Override + public void appendImportUserCnd(Cnd cnd, String existsLoginNameRedisKey) { + if (StrUtil.isBlank(existsLoginNameRedisKey)) { + return; + } + List loginNames = redisService.lrange(existsLoginNameRedisKey, 0, -1); + if (Lang.isEmpty(loginNames)) { + cnd.and("u.loginname", "=", IMPORT_NO_MATCH_LOGIN_NAME); + return; + } + cnd.andEX("u.loginname", "in", loginNames); + } + + /** + * 清理导入核对成功工号的临时缓存。 + * + * @param existsLoginNameRedisKey 导入核对成功工号的临时缓存 key + */ + @Override + public void clearImportUserCnd(String existsLoginNameRedisKey) { + if (StrUtil.isNotBlank(existsLoginNameRedisKey)) { + redisService.del(existsLoginNameRedisKey); + } + } + + private Set getSysLoginNames() { + Sql sql = Sqls.queryString(""" + SELECT + u.loginname + FROM + `user` u + """); + dao().execute(sql); + String[] sysLoginNames = (String[]) sql.getResult(); + Set loginNameSet = new HashSet<>(); + if (sysLoginNames != null) { + for (String loginName : sysLoginNames) { + if (StrUtil.isNotBlank(loginName)) { + loginNameSet.add(loginName); + } + } + } + return loginNameSet; + } } diff --git a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/baseManage/TheRapyRecuperationBaseManagerController.java b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/baseManage/TheRapyRecuperationBaseManagerController.java index f4d332e..14ed660 100644 --- a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/baseManage/TheRapyRecuperationBaseManagerController.java +++ b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/baseManage/TheRapyRecuperationBaseManagerController.java @@ -21,6 +21,7 @@ import io.v.nutz.base.utils.ViTool; import io.v.nutz.sys.models.SysHoliday; import io.v.nutz.sys.models.User; import io.v.nutz.web.commons.utils.ShiroUtil; +import io.v.nutz.zhgh.therapyRecuperation.constant.TheRapyRecuperationState; import io.v.nutz.zhgh.therapyRecuperation.model.*; import io.v.nutz.zhgh.therapyRecuperation.service.baseManage.TheRapyRecuperationBaseManagerService; import org.apache.poi.ss.usermodel.Workbook; @@ -117,6 +118,7 @@ public class TheRapyRecuperationBaseManagerController { tb.activityStartTime, tb.activityEndTime, tb.files, + tb.maxSignCount, tb.baseContactPerson, tb.baseContactNumber, tb.files as fileId, @@ -286,7 +288,11 @@ public class TheRapyRecuperationBaseManagerController { return Result.error("参数错误"); } - TheRapyRecuperationConfig config = dao.fetch(TheRapyRecuperationConfig.class, Cnd.NEW()); + // 手机端日历只使用最新提交配置,保持活动时间和页面展示一致。 + TheRapyRecuperationConfig config = dao.fetch(TheRapyRecuperationConfig.class, Cnd.where("latestConfig", "=", true)); + if (config == null) { + return Result.error("未找到最新疗休养配置,请联系管理员"); + } //获取线路对应的标段 TheRapyRecuperationBaseManagement management = dao.fetch(TheRapyRecuperationBaseManagement.class, id); //TheRapyRecuperationLot lot = dao.fetch(TheRapyRecuperationLot.class, management.getLotId()); @@ -306,6 +312,7 @@ public class TheRapyRecuperationBaseManagerController { }); List weeks = management.getWeekCheckIn(); + Set fullDays = getFullBaseManagementDays(management); // 解析日期 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); @@ -330,6 +337,10 @@ public class TheRapyRecuperationBaseManagerController { currentDate = currentDate.plusDays(1); continue; } + if (fullDays.contains(currentDateString)) { + currentDate = currentDate.plusDays(1); + continue; + } // 检查是否为需要排除的周几 int dayOfWeek = currentDate.getDayOfWeek().getValue() % 7; // 1是周一,7是周日 if (Lang.isNotEmpty(weeks) && !weeks.contains(dayOfWeek)) { @@ -343,11 +354,77 @@ public class TheRapyRecuperationBaseManagerController { return Map.of("days", resultDates, "holidays", holidays, + "fullDays", fullDays, "lotValue", 0, "minDate", DateUtil.formatDate(config.getFragmentPlayStartTime()), "maxDate", DateUtil.formatDate(config.getFragmentPlayEndTime())); } + /** + * 获取指定酒店报名已满的日期,手机端日历用来过滤不可选入住日。 + * + * @param management 酒店信息 + * @return 已达到每日最高报名人数的日期集合 + */ + private Set getFullBaseManagementDays(TheRapyRecuperationBaseManagement management) { + if (management == null || management.getMaxSignCount() == null || management.getMaxSignCount() <= 0) { + return Collections.emptySet(); + } + List enrolls = dao.query(TheRapyRecuperationEnroll.class, + Cnd.where("takePartInBaseManagementId", "=", management.getId()) + .and("specificTime", "is not", null) + .and("isNormal", "=", true) + .and("stateId", "in", Lang.array(TheRapyRecuperationState.UNIT, TheRapyRecuperationState.LINEUNIT, TheRapyRecuperationState.SCHOOL, TheRapyRecuperationState.PASS)) + .and("YEAR(signingUptime)", "=", DateUtil.thisYear())); + Map dayCountMap = new HashMap<>(); + for (TheRapyRecuperationEnroll enroll : enrolls) { + for (String day : parseSpecificTimeDays(enroll.getSpecificTime())) { + dayCountMap.put(day, dayCountMap.getOrDefault(day, 0) + 1); + } + } + return dayCountMap.entrySet().stream() + .filter(entry -> entry.getValue() >= management.getMaxSignCount()) + .map(Map.Entry::getKey) + .collect(Collectors.toSet()); + } + + /** + * 把“06月01日-06月03日”格式的报名时间拆成逐日日期。 + * + * @param specificTime 报名时间段 + * @return 报名时间段覆盖的日期集合,格式 yyyy-MM-dd + */ + private List parseSpecificTimeDays(String specificTime) { + if (StrUtil.isBlank(specificTime) || !specificTime.contains("-")) { + return Collections.emptyList(); + } + String[] times = specificTime.split("-"); + if (times.length != 2 || StrUtil.isBlank(times[0]) || StrUtil.isBlank(times[1])) { + return Collections.emptyList(); + } + DateTimeFormatter sourceFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日"); + DateTimeFormatter targetFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); + LocalDate start; + LocalDate end; + try { + start = LocalDate.parse(DateUtil.thisYear() + "年" + times[0].trim(), sourceFormatter); + end = LocalDate.parse(DateUtil.thisYear() + "年" + times[1].trim(), sourceFormatter); + } catch (Exception e) { + return Collections.emptyList(); + } + if (end.isBefore(start)) { + end = end.plusYears(1); + } + + List days = new ArrayList<>(); + LocalDate current = start; + while (!current.isAfter(end)) { + days.add(current.format(targetFormatter)); + current = current.plusDays(1); + } + return days; + } + /** * 目的地导入模版 diff --git a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/process/TheRapyRecuperationUserQueryController.java b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/process/TheRapyRecuperationUserQueryController.java index dc2ba00..34c7336 100644 --- a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/process/TheRapyRecuperationUserQueryController.java +++ b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/process/TheRapyRecuperationUserQueryController.java @@ -37,10 +37,12 @@ import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.upload.TempFile; import org.nutz.mvc.upload.UploadAdaptor; +import org.apache.commons.io.IOUtils; import org.springframework.util.CollectionUtils; import javax.servlet.http.HttpServletResponse; import java.io.IOException; +import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; @@ -183,6 +185,30 @@ public class TheRapyRecuperationUserQueryController { } + /** + * 下载参加人员导入模板 + * + * @param response 响应 + */ + @At + @Ok("void") + @RequiresAuthentication + public void downloadImportTemplate(HttpServletResponse response) { + String templatePath = "templates/travel/TravelEnrollImport.xlsx"; + try (InputStream inputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(templatePath)) { + if (inputStream == null) { + response.sendError(HttpServletResponse.SC_NOT_FOUND, "模板文件不存在"); + return; + } + response.setContentType("application/octet-stream"); + response.setHeader("Content-Disposition", "attachment;filename=" + new String(("参加人员导入模板.xlsx").getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)); + IOUtils.copy(inputStream, response.getOutputStream()); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + + /** * 参加人员导入 * diff --git a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/query/TheRapyRecuperationSchoolUnionUserQueryController.java b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/query/TheRapyRecuperationSchoolUnionUserQueryController.java index b9b6122..b977f49 100644 --- a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/query/TheRapyRecuperationSchoolUnionUserQueryController.java +++ b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/query/TheRapyRecuperationSchoolUnionUserQueryController.java @@ -94,7 +94,10 @@ public class TheRapyRecuperationSchoolUnionUserQueryController { state.stateColor, line.regionalNature, line.lineName, - agency.travelAgencyName, + COALESCE(agency.travelAgencyName, lineAgency.travelAgencyName) AS travelAgencyName, + lot.lotName, + lot.activityCost, + CASE WHEN lineu.playStartTime IS NULL AND lineu.playEndTime IS NULL THEN '' ELSE CONCAT(IFNULL(DATE_FORMAT(lineu.playStartTime,'%Y-%m-%d'), ''), '至', IFNULL(DATE_FORMAT(lineu.playEndTime,'%Y-%m-%d'), '')) END AS travelTime, ma.baseName, enroll.*, lineu.lineId, @@ -107,6 +110,8 @@ public class TheRapyRecuperationSchoolUnionUserQueryController { LEFT JOIN the_rapy_recuperation_line_union_select lineu ON lineu.id=enroll.takePartInLineId LEFT JOIN the_rapy_recuperation_line line ON line.id = lineu.lineId LEFT JOIN the_rapy_recuperation_travel_agency agency ON agency.id = enroll.takePartInTravelAgencyId + LEFT JOIN the_rapy_recuperation_travel_agency lineAgency ON lineAgency.id = line.travelAgencyId + LEFT JOIN the_rapy_recuperation_lot lot ON lot.id = line.lotId LEFT JOIN the_rapy_recuperation_base_management ma on ma.id = enroll.takePartInBaseManagementId LEFT JOIN audit_state state ON state.stateId = enroll.stateId $condition @@ -293,7 +298,10 @@ public class TheRapyRecuperationSchoolUnionUserQueryController { state.stateColor, line.regionalNature, line.lineName, - agency.travelAgencyName, + COALESCE(agency.travelAgencyName, lineAgency.travelAgencyName) AS travelAgencyName, + lot.lotName, + lot.activityCost, + CASE WHEN lineu.playStartTime IS NULL AND lineu.playEndTime IS NULL THEN '' ELSE CONCAT(IFNULL(DATE_FORMAT(lineu.playStartTime,'%Y-%m-%d'), ''), '至', IFNULL(DATE_FORMAT(lineu.playEndTime,'%Y-%m-%d'), '')) END AS travelTime, ma.baseName, enroll.*, lineu.lineId, @@ -306,6 +314,8 @@ public class TheRapyRecuperationSchoolUnionUserQueryController { LEFT JOIN the_rapy_recuperation_line_union_select lineu ON lineu.id=enroll.takePartInLineId LEFT JOIN the_rapy_recuperation_line line ON line.id = lineu.lineId LEFT JOIN the_rapy_recuperation_travel_agency agency ON agency.id = enroll.takePartInTravelAgencyId + LEFT JOIN the_rapy_recuperation_travel_agency lineAgency ON lineAgency.id = line.travelAgencyId + LEFT JOIN the_rapy_recuperation_lot lot ON lot.id = line.lotId LEFT JOIN the_rapy_recuperation_base_management ma on ma.id = enroll.takePartInBaseManagementId LEFT JOIN audit_state state ON state.stateId = enroll.stateId $condition @@ -378,6 +388,12 @@ public class TheRapyRecuperationSchoolUnionUserQueryController { excelEntities.add(new ExcelExportEntity("工会", "unionName", 20)); excelEntities.add(new ExcelExportEntity("身份证号", "idCard", 30)); excelEntities.add(new ExcelExportEntity("手机号", "mobile", 20)); + // 导出线路关联信息,与列表查询使用同一批筛选条件,确保列表查到什么导出什么。 + excelEntities.add(new ExcelExportEntity("出行时间", "travelTime", 30)); + excelEntities.add(new ExcelExportEntity("标段", "lotName", 20)); + excelEntities.add(new ExcelExportEntity("标段费用", "activityCost", 20)); + excelEntities.add(new ExcelExportEntity("线路", "lineName", 30)); + excelEntities.add(new ExcelExportEntity("旅行社", "travelAgencyName", 30)); if (config.getFamilyInfo() == 2) { excelEntities.add(new ExcelExportEntity("与本人关系", "relation", 10)); excelEntities.add(new ExcelExportEntity("床型", "bedType", 10)); diff --git a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/theRapyConfig/TheRapyRecuperationConfigController.java b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/theRapyConfig/TheRapyRecuperationConfigController.java index c8580d1..cdccb65 100644 --- a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/theRapyConfig/TheRapyRecuperationConfigController.java +++ b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/controller/theRapyConfig/TheRapyRecuperationConfigController.java @@ -1,32 +1,14 @@ package io.v.nutz.zhgh.therapyRecuperation.controller.theRapyConfig; import io.v.nutz.base.annontation.ViReturn; -import io.v.nutz.base.model.msgUser; -import io.v.nutz.base.utils.MsgApi; -import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationBaseManagement; import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationConfig; -import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLine; -import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLot; +import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationConfigService; import org.apache.shiro.authz.annotation.RequiresAuthentication; import org.apache.shiro.authz.annotation.RequiresPermissions; -import org.nutz.aop.interceptor.ioc.TransAop; -import org.nutz.dao.Cnd; -import org.nutz.dao.Dao; -import org.nutz.ioc.aop.Aop; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.Lang; -import org.nutz.lang.Strings; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; -import org.nutz.trans.Trans; -import org.springframework.util.CollectionUtils; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.stream.Collectors; /** * rapy休养配置控制器 @@ -41,9 +23,7 @@ public class TheRapyRecuperationConfigController { @Inject - private Dao dao; - @Inject - private MsgApi msgApi; + private TheRapyRecuperationConfigService configService; @At("") @@ -55,29 +35,23 @@ public class TheRapyRecuperationConfigController { @At @ViReturn @RequiresAuthentication - @Aop(TransAop.READ_COMMITTED) public Object operation(TheRapyRecuperationConfig config, String[] lotDeleteList) { - if (Strings.isNotBlank(config.getId())) { - if (Lang.isNotEmpty(lotDeleteList)) { - dao.clear(TheRapyRecuperationLot.class, Cnd.where("id", "in", lotDeleteList)); - } - dao.updateWith(config, "lots"); - List collect = config.getLots().stream().filter(v -> v.getConfigId() == null).collect(Collectors.toList()); - for (TheRapyRecuperationLot obj : collect) { - obj.setConfigId(config.getId()); - } - dao.insert(collect); - } else { - dao.insertWith(config, "lots"); - } + configService.saveConfig(config, lotDeleteList); return null; } @At @ViReturn @RequiresAuthentication - public Object findOne() { - return dao.fetchLinks(dao.fetch(TheRapyRecuperationConfig.class), "lots",Cnd.NEW().desc("lotValue")); + public Object findOne(Integer year) { + return configService.findByYear(year); + } + + @At + @ViReturn + @RequiresAuthentication + public Object copyLastYear(Integer year) { + return configService.copyLastYear(year); } @@ -90,20 +64,7 @@ public class TheRapyRecuperationConfigController { @ViReturn @RequiresAuthentication public Object getLotsById(String lotId){ - List lineNames = new ArrayList<>(); - List baseNames = new ArrayList<>(); - Map> map = new HashMap<>(); - List lineList = dao.query(TheRapyRecuperationLine.class, Cnd.where("lotId", "=", lotId)); - if (!CollectionUtils.isEmpty(lineList)){ - lineList.forEach(v-> lineNames.add(v.getLineName())); - map.put("line",lineNames); - } - List managementList = dao.query(TheRapyRecuperationBaseManagement.class, Cnd.where("lotId", "=", lotId)); - if (!CollectionUtils.isEmpty(managementList)){ - managementList.forEach(v-> baseNames.add(v.getBaseName())); - map.put("base",baseNames); - } - return map; + return configService.getLotsById(lotId); } @@ -116,19 +77,7 @@ public class TheRapyRecuperationConfigController { @ViReturn @RequiresAuthentication public Object deleteLotById(String lotId){ - Trans.exec(()->{ - dao.clear(TheRapyRecuperationLot.class, Cnd.where("id","=",lotId)); - List lineList = dao.query(TheRapyRecuperationLine.class, Cnd.where("lotId", "=", lotId)); - if (!CollectionUtils.isEmpty(lineList)) { - lineList.forEach(v -> v.setLotId(null)); - dao.update(lineList); - } - List managementList = dao.query(TheRapyRecuperationBaseManagement.class, Cnd.where("lotId", "=", lotId)); - if (!CollectionUtils.isEmpty(managementList)) { - managementList.forEach(v -> v.setLotId(null)); - dao.update(managementList); - } - }); + configService.deleteLotById(lotId); return null; } } diff --git a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/model/TheRapyRecuperationBaseManagement.java b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/model/TheRapyRecuperationBaseManagement.java index e7994cd..c71acaf 100644 --- a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/model/TheRapyRecuperationBaseManagement.java +++ b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/model/TheRapyRecuperationBaseManagement.java @@ -165,6 +165,12 @@ public class TheRapyRecuperationBaseManagement { @Comment("天数") private List allowDay; + @Column + @ColDefine(type = ColType.INT) + @Comment("同一酒店每日最高报名人数") + @Excel(name = "同一酒店每日最高报名人数") + private Integer maxSignCount; + @Column @ColDefine(type = ColType.VARCHAR) @Comment("旅行社地点") diff --git a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/model/TheRapyRecuperationConfig.java b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/model/TheRapyRecuperationConfig.java index 1016d48..654f6e6 100644 --- a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/model/TheRapyRecuperationConfig.java +++ b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/model/TheRapyRecuperationConfig.java @@ -26,6 +26,16 @@ public class TheRapyRecuperationConfig { @Comment("配置名称") private String configName; + @Column + @ColDefine(type = ColType.INT) + @Comment("配置年度") + private Integer configYear; + + @Column + @ColDefine(type = ColType.BOOLEAN) + @Comment("是否最新提交配置") + private Boolean latestConfig; + @Column @ColDefine(type = ColType.INT, width = 32) @Comment("参加人员范围") diff --git a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/service/TheRapyRecuperationConfigService.java b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/service/TheRapyRecuperationConfigService.java new file mode 100644 index 0000000..6d59c27 --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/service/TheRapyRecuperationConfigService.java @@ -0,0 +1,50 @@ +package io.v.nutz.zhgh.therapyRecuperation.service; + +import io.v.nutz.base.service.ViService; +import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationConfig; +import org.nutz.lang.util.NutMap; + +/** + * 疗休养基础配置服务。 + */ +public interface TheRapyRecuperationConfigService extends ViService { + + /** + * 按年度查询基础配置;年度为空时使用当前年度。 + * + * @param configYear 配置年度 + * @return 年度配置 + */ + TheRapyRecuperationConfig findByYear(Integer configYear); + + /** + * 保存年度基础配置,已存在配置时更新,不存在时新增。 + * + * @param config 基础配置 + * @param lotDeleteList 需要删除的标段id + */ + void saveConfig(TheRapyRecuperationConfig config, String[] lotDeleteList); + + /** + * 将上一年度配置复制为当前年度配置。 + * + * @param configYear 当前配置年度 + * @return 复制后的当前年度配置 + */ + TheRapyRecuperationConfig copyLastYear(Integer configYear); + + /** + * 查询使用该标段的线路和目的地。 + * + * @param lotId 标段id + * @return 使用情况 + */ + NutMap getLotsById(String lotId); + + /** + * 强制删除标段,并清空已绑定线路和目的地上的标段。 + * + * @param lotId 标段id + */ + void deleteLotById(String lotId); +} diff --git a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/service/impl/TheRapyRecuperationConfigServiceImpl.java b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/service/impl/TheRapyRecuperationConfigServiceImpl.java new file mode 100644 index 0000000..b820815 --- /dev/null +++ b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/service/impl/TheRapyRecuperationConfigServiceImpl.java @@ -0,0 +1,236 @@ +package io.v.nutz.zhgh.therapyRecuperation.service.impl; + +import cn.hutool.core.date.DateTime; +import io.v.nutz.base.service.impl.ViServiceImpl; +import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationBaseManagement; +import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationConfig; +import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLine; +import io.v.nutz.zhgh.therapyRecuperation.model.TheRapyRecuperationLot; +import io.v.nutz.zhgh.therapyRecuperation.service.TheRapyRecuperationConfigService; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.Strings; +import org.nutz.lang.util.NutMap; +import org.nutz.trans.Trans; +import org.springframework.util.CollectionUtils; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.temporal.ChronoField; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 疗休养基础配置服务实现。 + */ +@IocBean(args = {"refer:dao"}) +public class TheRapyRecuperationConfigServiceImpl extends ViServiceImpl implements TheRapyRecuperationConfigService { + + private static final int DEFAULT_CONFIG_YEAR = 2025; + + public TheRapyRecuperationConfigServiceImpl(Dao dao) { + super(dao); + } + + /** + * 年度为空时统一使用 2025 年,兼容原有无年度的基础配置。 + * + * @param configYear 配置年度 + * @return 有效年度 + */ + private Integer getConfigYear(Integer configYear) { + return configYear == null ? DEFAULT_CONFIG_YEAR : configYear; + } + + @Override + public TheRapyRecuperationConfig findByYear(Integer configYear) { + if (configYear == null) { + return findLatestConfig(); + } + Integer year = getConfigYear(configYear); + TheRapyRecuperationConfig config = fetch(Cnd.where("configYear", "=", year)); + if (config == null && year == DEFAULT_CONFIG_YEAR) { + config = fetch(Cnd.where("configYear", "is", null)); + } + if (config == null) { + return null; + } + return dao().fetchLinks(config, "lots", Cnd.NEW().desc("lotValue")); + } + + /** + * 其他业务页面不传年度时,只使用最新提交的基础配置。 + * + * @return 最新基础配置 + */ + private TheRapyRecuperationConfig findLatestConfig() { + TheRapyRecuperationConfig config = fetch(Cnd.where("latestConfig", "=", true)); + if (config == null) { + return null; + } + return dao().fetchLinks(config, "lots", Cnd.NEW().desc("lotValue")); + } + + @Override + @Aop(TransAop.READ_COMMITTED) + public void saveConfig(TheRapyRecuperationConfig config, String[] lotDeleteList) { + Integer year = getConfigYear(config.getConfigYear()); + config.setConfigYear(year); + config.setLatestConfig(true); + TheRapyRecuperationConfig oldConfig = findByYear(year); + if (Strings.isBlank(config.getId()) && oldConfig != null) { + config.setId(oldConfig.getId()); + } + resetLatestConfig(config.getId()); + if (Strings.isNotBlank(config.getId())) { + if (Lang.isNotEmpty(lotDeleteList)) { + dao().clear(TheRapyRecuperationLot.class, Cnd.where("id", "in", lotDeleteList)); + } + dao().updateWith(config, "lots"); + List lots = config.getLots() == null ? new ArrayList<>() : config.getLots(); + List collect = lots.stream().filter(v -> v.getConfigId() == null).collect(Collectors.toList()); + for (TheRapyRecuperationLot obj : collect) { + obj.setConfigId(config.getId()); + } + if (Lang.isNotEmpty(collect)) { + dao().insert(collect); + } + } else { + dao().insertWith(config, "lots"); + } + } + + /** + * 每次提交年度配置后,仅保留当前配置为最新配置。 + * + * @param currentConfigId 当前配置id + */ + private void resetLatestConfig(String currentConfigId) { + Cnd cnd = Cnd.NEW(); + if (Strings.isNotBlank(currentConfigId)) { + cnd.and("id", "!=", currentConfigId); + } + dao().update(TheRapyRecuperationConfig.class, Chain.make("latestConfig", false), cnd); + } + + @Override + @Aop(TransAop.READ_COMMITTED) + public TheRapyRecuperationConfig copyLastYear(Integer configYear) { + Integer year = getConfigYear(configYear); + TheRapyRecuperationConfig currentConfig = findByYear(year); + TheRapyRecuperationConfig lastConfig = findByYear(year - 1); + if (lastConfig == null) { + return null; + } + lastConfig.setId(currentConfig == null ? null : currentConfig.getId()); + lastConfig.setConfigYear(year); + lastConfig.setLatestConfig(true); + resetConfigTimeYear(lastConfig, year); + resetLatestConfig(null); + if (currentConfig == null) { + copyLotsToNewConfig(lastConfig); + dao().insertWith(lastConfig, "lots"); + } else { + dao().clear(TheRapyRecuperationLot.class, Cnd.where("configId", "=", currentConfig.getId())); + copyLotsToNewConfig(lastConfig); + dao().update(lastConfig); + for (TheRapyRecuperationLot lot : lastConfig.getLots()) { + lot.setConfigId(currentConfig.getId()); + } + if (Lang.isNotEmpty(lastConfig.getLots())) { + dao().insert(lastConfig.getLots()); + } + } + return findByYear(year); + } + + /** + * 沿用上一年度配置时,将所有年度相关时间改为当前配置年度,月日和时分秒保持不变。 + * + * @param config 待复制配置 + * @param year 当前配置年度 + */ + private void resetConfigTimeYear(TheRapyRecuperationConfig config, Integer year) { + config.setCreateLineStartTime(resetDateTimeYear(config.getCreateLineStartTime(), year)); + config.setCreateLineEndTime(resetDateTimeYear(config.getCreateLineEndTime(), year)); + config.setImplodeStartTime(resetDateTimeYear(config.getImplodeStartTime(), year)); + config.setImplodeEndTime(resetDateTimeYear(config.getImplodeEndTime(), year)); + config.setFragmentStartTime(resetDateTimeYear(config.getFragmentStartTime(), year)); + config.setFragmentEndTime(resetDateTimeYear(config.getFragmentEndTime(), year)); + config.setFragmentPlayStartTime(resetDateTimeYear(config.getFragmentPlayStartTime(), year)); + config.setFragmentPlayEndTime(resetDateTimeYear(config.getFragmentPlayEndTime(), year)); + } + + /** + * 替换时间年份;闰年 2 月 29 日复制到平年时,自动落到该年 2 月最后一天。 + * + * @param dateTime 原时间 + * @param year 目标年度 + * @return 替换年份后的时间 + */ + private DateTime resetDateTimeYear(DateTime dateTime, Integer year) { + if (dateTime == null || year == null) { + return dateTime; + } + LocalDateTime sourceTime = LocalDateTime.ofInstant(dateTime.toInstant(), ZoneId.systemDefault()); + int dayOfMonth = (int) Math.min(sourceTime.getDayOfMonth(), sourceTime.withYear(year).range(ChronoField.DAY_OF_MONTH).getMaximum()); + LocalDateTime targetTime = sourceTime.withYear(year).withDayOfMonth(dayOfMonth); + return new DateTime(java.util.Date.from(targetTime.atZone(ZoneId.systemDefault()).toInstant())); + } + + /** + * 复制上一年度标段时清空主键和配置外键,让数据库生成当前年度独立数据。 + * + * @param config 待复制配置 + */ + private void copyLotsToNewConfig(TheRapyRecuperationConfig config) { + if (config.getLots() == null) { + return; + } + for (TheRapyRecuperationLot lot : config.getLots()) { + lot.setId(null); + lot.setConfigId(null); + } + } + + @Override + public NutMap getLotsById(String lotId) { + List lineNames = new ArrayList<>(); + List baseNames = new ArrayList<>(); + NutMap map = new NutMap(); + List lineList = dao().query(TheRapyRecuperationLine.class, Cnd.where("lotId", "=", lotId)); + if (!CollectionUtils.isEmpty(lineList)) { + lineList.forEach(v -> lineNames.add(v.getLineName())); + map.put("line", lineNames); + } + List managementList = dao().query(TheRapyRecuperationBaseManagement.class, Cnd.where("lotId", "=", lotId)); + if (!CollectionUtils.isEmpty(managementList)) { + managementList.forEach(v -> baseNames.add(v.getBaseName())); + map.put("base", baseNames); + } + return map; + } + + @Override + public void deleteLotById(String lotId) { + Trans.exec(() -> { + dao().clear(TheRapyRecuperationLot.class, Cnd.where("id", "=", lotId)); + List lineList = dao().query(TheRapyRecuperationLine.class, Cnd.where("lotId", "=", lotId)); + if (!CollectionUtils.isEmpty(lineList)) { + lineList.forEach(v -> v.setLotId(null)); + dao().update(lineList); + } + List managementList = dao().query(TheRapyRecuperationBaseManagement.class, Cnd.where("lotId", "=", lotId)); + if (!CollectionUtils.isEmpty(managementList)) { + managementList.forEach(v -> v.setLotId(null)); + dao().update(managementList); + } + }); + } +} diff --git a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/service/impl/TheRapyRecuperationEnrollServiceImpl.java b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/service/impl/TheRapyRecuperationEnrollServiceImpl.java index 5c490c2..caec088 100644 --- a/src/main/java/io/v/nutz/zhgh/therapyRecuperation/service/impl/TheRapyRecuperationEnrollServiceImpl.java +++ b/src/main/java/io/v/nutz/zhgh/therapyRecuperation/service/impl/TheRapyRecuperationEnrollServiceImpl.java @@ -35,6 +35,7 @@ import org.nutz.lang.util.NutMap; import java.time.LocalDate; import java.time.Period; +import java.time.format.DateTimeFormatter; import java.util.*; import java.util.stream.Collectors; @@ -543,8 +544,11 @@ public class TheRapyRecuperationEnrollServiceImpl extends ViServiceImpl validSignUpInfo(String loginName, TheRapyRecuperationEnroll enrollInfo) { - //配置信息 - TheRapyRecuperationConfig config = dao().fetch(TheRapyRecuperationConfig.class); + // 配置信息只取当前最新配置,避免报名校验和页面展示使用不同年度配置。 + TheRapyRecuperationConfig config = fetchLatestConfig(); + if (config == null) { + return Map.of(false, "未找到最新疗休养配置,请联系管理员"); + } if (StrUtil.isNotBlank(loginName) && loginName.startsWith("2025")) { return Map.of(false, "抱歉,您是今年新入职,不能报名!"); @@ -710,7 +714,10 @@ public class TheRapyRecuperationEnrollServiceImpl extends ViServiceImpl validSignTime(TheRapyRecuperationEnroll currentEnroll) { - TheRapyRecuperationConfig config = dao().fetch(TheRapyRecuperationConfig.class, Cnd.NEW()); + TheRapyRecuperationConfig config = fetchLatestConfig(); + if (config == null) { + return Map.of(false, "未找到最新疗休养配置,请联系管理员"); + } DateTime signUpStartTime = null; DateTime signUpEndTime = null; if (StrUtil.isNotBlank(currentEnroll.getTakePartInLineId())) { @@ -729,7 +736,21 @@ public class TheRapyRecuperationEnrollServiceImpl extends ViServiceImpl days = new ArrayList<>(); + LocalDate current = start; + while (!current.isAfter(end)) { + days.add(current); + current = current.plusDays(1); + } + return days; + } + //判断一年报几次 public Map validCountThisYear(String loginName, int travelFrequency, Boolean validHotel) { Cnd cnd = Cnd.NEW(); diff --git a/src/main/resources/static/components/plugins/UserScope.vue b/src/main/resources/static/components/plugins/UserScope.vue index 91fc574..a024c3a 100644 --- a/src/main/resources/static/components/plugins/UserScope.vue +++ b/src/main/resources/static/components/plugins/UserScope.vue @@ -279,6 +279,10 @@ @@ -405,6 +460,7 @@ module.exports = { roleIds: [], userId: [], activityUserCnd: '', + existsLoginNameRedisKey: '', reverseSelection: false }, activityUnions: [], @@ -434,7 +490,18 @@ module.exports = { setGroupName: [{required: true, message: '请输入分组名称', trigger: ['blur', 'change']}] }, relatedSessionMenus: ['aca4d14498c145ceb5b24ed70776aae2', '733d7266652740a3aeac9da97ab5eeca', 'fe2d0768e26d4a80beeb159306bb8d01'], - roleData: {} + roleData: {}, + dialogVisible: false, + importLoading: false, + importData: { + fileList: [], + }, + errorInfoData: { + totalCount: 0, + successCount: 0, + errorCount: 0, + errorList: [], + }, } }, computed: { @@ -461,6 +528,88 @@ module.exports = { 'user-cnd': httpVueLoader('/components/plugins/UserCnd.vue'), }, methods: { + exportErrors() { + const data = this.errorInfoData.errorList + const workbook = XLSX.utils.book_new() + const worksheet = XLSX.utils.json_to_sheet(data) + XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1') + const excelBuffer = XLSX.write(workbook, {bookType: 'xlsx', type: 'array'}) + const blob = new Blob([excelBuffer], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'}) + const url = window.URL.createObjectURL(blob) + const link = document.createElement('a') + link.href = url + link.download = '核对记录.xlsx' + document.body.appendChild(link) + link.click() + document.body.removeChild(link) + window.URL.revokeObjectURL(url) + }, + doImportSearch() { + this.doSearch() + this.dialogVisible = false + }, + doImport() { + if (this.importData.fileList.length === 0) { + this.notifyWarning("请选择文件!") + return + } + const data = new FormData() + this.importData.fileList.forEach((val) => { + data.append("file", val.raw, val.raw.name) + }) + + this.importLoading = true + $.ajax({ + url: "/platform/activity/basic/scope/doImport", + type: "post", + data: data, + processData: false, + contentType: false, + success: (data) => { + this.importLoading = false + if (data.code === 0) { + this.notifySuccess("核对成功") + this.errorInfoData = data.data + this.$set(this.pageForm, "existsLoginNameRedisKey", data.data.existsLoginNameRedisKey) + } else { + this.notifyWarning("核对失败") + } + }, + error: () => { + this.notifyWarning("导入失败") + this.importLoading = false + } + }) + }, + clearSearchCnd() { + const existsLoginNameRedisKey = this.pageForm.existsLoginNameRedisKey + this.$set(this.importData, "fileList", []) + this.errorInfoData = { + totalCount: 0, + successCount: 0, + errorCount: 0, + errorList: [], + } + this.$set(this.pageForm, "existsLoginNameRedisKey", "") + this.doSearch() + this.dialogVisible = false + $.get('/platform/activity/basic/scope/clearSearchCnd', {existsLoginNameRedisKey: existsLoginNameRedisKey}).then(res => { + if (res.code === 0) { + this.$message.success(res.msg) + } else { + this.$message.error(res.msg) + } + }) + }, + openImport() { + this.dialogVisible = true + }, + handleImportFileRemove(file, fileList) { + this.$set(this.importData, "fileList", this.fileHandleRemove(file, fileList)) + }, + handleImportFileChange(file, fileList) { + this.$set(this.importData, "fileList", this.fileHandleChange(file, fileList, {type: ['xls', 'xlsx']})) + }, doExportUser() { const { userId, @@ -476,7 +625,8 @@ module.exports = { activityGroupId, age, reverseSelection, - activityUserCnd + activityUserCnd, + existsLoginNameRedisKey } = this.pageForm let props = {} @@ -495,6 +645,7 @@ module.exports = { "&reverseSelection=" + reverseSelection + "&clubId=" + clubId + "&activityGroupId=" + activityGroupId + + "&existsLoginNameRedisKey=" + existsLoginNameRedisKey + "&teacherMeetingId=" + teacherMeetingId + "&unionId=" + unionId + "&unitId=" + unitId @@ -514,6 +665,7 @@ module.exports = { this.pageForm.clubId = '' this.pageForm.activityGroupId = '' this.pageForm.activityUserCnd = '' + this.pageForm.existsLoginNameRedisKey = '' this.pageForm.age = [0, 0] this.pageForm.reverseSelection = false this.doSearch() diff --git a/src/main/resources/templates/travel/TravelEnrollImport.xlsx b/src/main/resources/templates/travel/TravelEnrollImport.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..665e5869c9ef604dd556c09800806c2cfcab1295 GIT binary patch literal 8813 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 Om{16Ja*Cw)pZ*6}6BDWc literal 0 HcmV?d00001 diff --git a/src/main/resources/views/mobile/therapyRecuperation/baseManagement.html b/src/main/resources/views/mobile/therapyRecuperation/baseManagement.html index 2c72a2f..2dde7af 100644 --- a/src/main/resources/views/mobile/therapyRecuperation/baseManagement.html +++ b/src/main/resources/views/mobile/therapyRecuperation/baseManagement.html @@ -527,6 +527,7 @@ layout("/mobile/platform.html"){ minDate: new Date(2010, 0, 1), maxDate: new Date(2010, 0, 31), holidays: [], + fullDays: [], timeVisible: false, active: 0, tarBarActive: 0, @@ -623,6 +624,12 @@ layout("/mobile/platform.html"){ this.$refs.cal.reset(null) break } + if(this.fullDays.includes(afterDateStr)) { + this.$toast(afterDateStr + '报名人数已满,请更换出行时间') + this.chooseDate = [] + this.$refs.cal.reset(null) + break + } this.chooseDate.push(afterDateStr) if(i === (this.lotValue - 1)) { @@ -639,6 +646,10 @@ layout("/mobile/platform.html"){ if(this.timeArray.indexOf(date) === -1) { day.type = 'disabled' } + if(this.fullDays.includes(date)) { + day.type = 'disabled' + day.bottomInfo = '已满' + } if(this.chooseDate.length > 0 && this.chooseDate.includes(date)) { day.className = 'cal_middle' if(date === this.chooseDate[this.chooseDate.length - 1]) { @@ -801,6 +812,7 @@ layout("/mobile/platform.html"){ }) this.timeArray = res.data.days this.holidays = res.data.holidays + this.$set(this, 'fullDays', res.data.fullDays || []) //this.lotValue = Number(res.data.lotValue) this.minDate = new Date(res.data.minDate) this.maxDate = new Date(res.data.maxDate) diff --git a/src/main/resources/views/platform/theRapyRecuperation/baseManage/baseManagement.html b/src/main/resources/views/platform/theRapyRecuperation/baseManage/baseManagement.html index 1fadd06..00fe430 100644 --- a/src/main/resources/views/platform/theRapyRecuperation/baseManage/baseManagement.html +++ b/src/main/resources/views/platform/theRapyRecuperation/baseManage/baseManagement.html @@ -96,6 +96,9 @@ layout("/layouts/platform.html"){ {{item.lotName}} + @@ -202,7 +205,7 @@ layout("/layouts/platform.html"){ - + 省内 @@ -210,7 +213,16 @@ layout("/layouts/platform.html"){ - + + + + + + + + + 不限 @@ -508,6 +520,7 @@ layout("/layouts/platform.html"){ baseContactNumber: '', weekIn: 1, allowDay: [], + maxSignCount: 0, travelAgencyPlace: '', }, tableColumns: [ @@ -515,6 +528,7 @@ layout("/layouts/platform.html"){ {label: '目的地名称', prop: 'baseName', sortable: true}, {label: '承担旅行社', prop: 'travelAgencyName', sortable: true}, //{label: '标段时间', prop: 'lotId', sortable: true}, + {label: '每日最高人数', prop: 'maxSignCount', sortable: true}, {label: '联系人', prop: 'baseContactPerson', sortable: true}, {label: '联系人电话', prop: 'baseContactNumber', sortable: true}, //{label: '活动时间', prop: 'activityTime', sortable: true}, @@ -543,6 +557,7 @@ layout("/layouts/platform.html"){ activityEndTime: [{required: true, validator: validateActivityEndTime, trigger: ['change', 'blur']}], estimatedCost: [{required: true, message: '请输入预计费用', trigger: ['change', 'blur']}], allowDay: [{required: true, message: '请选择天数', trigger: ['change', 'blur']}], + maxSignCount: [{required: false, message: '请输入每日最高人数', trigger: ['change', 'blur']}], travelAgencyPlace: [{required: true, message: '请选择旅行社地点', trigger: ['change', 'blur']}], }, //目的地导入 diff --git a/src/main/resources/views/platform/theRapyRecuperation/schoolUnionUserQuery/index.html b/src/main/resources/views/platform/theRapyRecuperation/schoolUnionUserQuery/index.html index 4e6c154..84d93b7 100644 --- a/src/main/resources/views/platform/theRapyRecuperation/schoolUnionUserQuery/index.html +++ b/src/main/resources/views/platform/theRapyRecuperation/schoolUnionUserQuery/index.html @@ -171,6 +171,8 @@ layout("/layouts/platform.html"){