From 0397547b199b2d5e3291329cee48029e5a65581d Mon Sep 17 00:00:00 2001 From: hongqiwei <1143662660@qq.com> Date: Thu, 12 Nov 2026 09:39:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=93=E6=A3=80=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dependency-reduced-pom.xml | 2 +- .../app/sys/controller/SysHomeController.java | 9 +- .../sys/services/SysHomeActivityService.java | 8 + .../impl/SysHomeActivityServiceImpl.java | 18 + .../HealthCheckupCampusController.java | 64 +- .../HealthCheckupListController.java | 344 +++---- ...ckupPersonConfirmStatisticsController.java | 44 + .../HealthCheckupProjectMangeController.java | 132 +-- .../HealthCheckupSingleController.java | 312 +----- .../H5HealthCheckupController.java | 198 ++-- .../model/HealthCheckupActualStatistics.java | 36 + .../model/HealthCheckupFeedback.java | 52 + .../model/HealthCheckupProject.java | 33 +- .../HealthCheckupProjectSubjectMoney.java | 6 + .../model/HealthCheckupUser.java | 55 + .../HealthCheckupFilterUserPageForm.java | 61 ++ .../H5HealthCheckupApplicationService.java | 396 ++++++++ ...HealthCheckupCampusApplicationService.java | 108 ++ .../service/HealthCheckupFeedbackService.java | 27 + .../HealthCheckupListApplicationService.java | 835 +++++++++++++++ ...CheckupPersonConfirmStatisticsService.java | 26 + ...CheckupProjectMangeApplicationService.java | 224 +++++ .../service/HealthCheckupProjectService.java | 7 + ...HealthCheckupSingleApplicationService.java | 550 ++++++++++ .../service/HealthCheckupSingleService.java | 15 + .../HealthCheckupFeedbackServiceImpl.java | 129 +++ ...kupPersonConfirmStatisticsServiceImpl.java | 60 ++ .../impl/HealthCheckupProjectServiceImpl.java | 73 +- .../impl/HealthCheckupSingleServiceImpl.java | 259 +++-- .../template/HealthCheckupImportTemp.java | 6 + .../platform/js/mixin/initTableMixins.js | 6 +- .../assets/platform/js/util/h5PopupHistory.js | 126 +++ .../resources/views/layouts/platform_h5.html | 1 + src/main/resources/views/layouts/v4/home.html | 2 +- .../resources/views/layouts/v4/home/act.js | 2 +- .../healthCheckup/campus/index.html | 170 ++-- .../common/ConditionStructure.js | 171 ++-- .../healthCheckup/feedbackQuery/index.html | 201 ++++ .../healthCheckup/listMange/addUser.js | 91 ++ .../healthCheckup/listMange/index.html | 850 +++++++++++++--- .../healthCheckup/personconfirm/index.html | 150 +++ .../healthCheckup/projectMange/index.html | 950 +++++++++++------- .../healthCheckup/statisticsSingle/index.html | 915 +++++++++++------ .../healthCheckup/list/index.html | 170 ++-- .../healthCheckup/listParticulars/index.html | 116 +++ .../healthCheckup/mine/index.html | 180 ++-- .../physicalExaminationList/index.html | 531 ++++++++++ .../projectManageForm/index.html | 688 +++++++------ .../healthCheckup/userBaseMessage/index.html | 182 ++++ 49 files changed, 7304 insertions(+), 2287 deletions(-) create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupPersonConfirmStatisticsController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupActualStatistics.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupFeedback.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/param/HealthCheckupFilterUserPageForm.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/H5HealthCheckupApplicationService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupCampusApplicationService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupFeedbackService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupListApplicationService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupPersonConfirmStatisticsService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupProjectMangeApplicationService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupSingleApplicationService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupFeedbackServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupPersonConfirmStatisticsServiceImpl.java create mode 100644 src/main/resources/static/assets/platform/js/util/h5PopupHistory.js create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/feedbackQuery/index.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/listMange/addUser.js create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/personconfirm/index.html create mode 100644 src/main/resources/views/platform/zhghh5/dayofficework/healthCheckup/listParticulars/index.html create mode 100644 src/main/resources/views/platform/zhghh5/dayofficework/healthCheckup/physicalExaminationList/index.html create mode 100644 src/main/resources/views/platform/zhghh5/dayofficework/healthCheckup/userBaseMessage/index.html diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml index a2cc18c4..5d8c5636 100644 --- a/dependency-reduced-pom.xml +++ b/dependency-reduced-pom.xml @@ -182,8 +182,8 @@ 4.5.0 1.15.3 - 9.0.121 8.0.28 + 9.0.121 1.25.0 1.6.2 4.0.0 diff --git a/src/main/java/com/budwk/app/sys/controller/SysHomeController.java b/src/main/java/com/budwk/app/sys/controller/SysHomeController.java index 36a4d77f..06b26788 100644 --- a/src/main/java/com/budwk/app/sys/controller/SysHomeController.java +++ b/src/main/java/com/budwk/app/sys/controller/SysHomeController.java @@ -10,6 +10,7 @@ import com.budwk.app.base.result.Result; import com.budwk.app.sys.models.Sys_home_activity; import com.budwk.app.sys.models.Sys_menu; import com.budwk.app.sys.services.SysMenuService; +import com.budwk.app.sys.services.SysHomeActivityService; import com.budwk.app.sys.services.SysUserService; import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope; @@ -57,6 +58,8 @@ public class SysHomeController { @Inject private SysUserService sysUserService; @Inject + private SysHomeActivityService sysHomeActivityService; + @Inject private RedisService redisService; @At("") @@ -195,9 +198,9 @@ public class SysHomeController { @SaCheckLogin @ApiOperation("首页推送活动") @Ok("json") - public Result listHomeActivity() { - FieldFilter fieldFilter = FieldFilter.locked(Sys_home_activity.class, "classPath"); - List list = Daos.ext(dao, fieldFilter).query(Sys_home_activity.class, Cnd.where("enable", "=", 1).desc("top")); + public Result listHomeActivity(String platform) { + // platform=PC 仅过滤电脑首页;手机端未传此参数时保持原范围,返回 Result.data 活动列表。 + List list = sysHomeActivityService.listHomeCandidates(platform); String userId = SecurityUtil.getUserId(); List allowActivityList = new ArrayList<>(); // 今天的时间 diff --git a/src/main/java/com/budwk/app/sys/services/SysHomeActivityService.java b/src/main/java/com/budwk/app/sys/services/SysHomeActivityService.java index 5341ac7d..c282a205 100644 --- a/src/main/java/com/budwk/app/sys/services/SysHomeActivityService.java +++ b/src/main/java/com/budwk/app/sys/services/SysHomeActivityService.java @@ -3,5 +3,13 @@ package com.budwk.app.sys.services; import com.budwk.app.base.service.BaseService; import com.budwk.app.sys.models.Sys_home_activity; +import java.util.List; + public interface SysHomeActivityService extends BaseService { + /** + * 查询首页启用活动,PC 端排除仅在手机端报名的体检项目。 + * @param platform PC 表示电脑首页;其他值保留原活动范围 + * @return 按置顶顺序排列的候选活动,人员范围和时间仍由原流程判断 + */ + List listHomeCandidates(String platform); } diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysHomeActivityServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysHomeActivityServiceImpl.java index 9553fd5b..5ffa31a3 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysHomeActivityServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysHomeActivityServiceImpl.java @@ -4,6 +4,11 @@ import com.budwk.app.base.service.impl.BaseServiceImpl; import com.budwk.app.sys.models.Sys_home_activity; import com.budwk.app.sys.services.SysHomeActivityService; import org.nutz.dao.Dao; +import org.nutz.dao.Cnd; +import org.nutz.dao.FieldFilter; +import org.nutz.dao.util.Daos; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupProject; +import java.util.List; import org.nutz.ioc.loader.annotation.IocBean; @IocBean(args = {"refer:dao"}) @@ -12,4 +17,17 @@ public class SysHomeActivityServiceImpl extends BaseServiceImpl listHomeCandidates(String platform) { + Cnd condition = Cnd.where("enable", "=", 1); + if ("PC".equalsIgnoreCase(platform)) { + // 保留未绑定业务类的手工活动,仅排除体检项目生成的首页活动。 + condition.and(Cnd.exps("classPath", "is", null) + .or("classPath", "!=", HealthCheckupProject.class.getName())); + } + condition.desc("top"); + return Daos.ext(dao(), FieldFilter.locked(Sys_home_activity.class, "classPath")) + .query(Sys_home_activity.class, condition); + } } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupCampusController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupCampusController.java index ef5695a6..820e9246 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupCampusController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupCampusController.java @@ -1,25 +1,21 @@ package com.budwk.app.zhgh.dayofficework.healthCheckup.controller; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupCampusApplicationService; import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.annotation.SaCheckPermission; import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; -import com.budwk.app.base.service.BaseService; import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupCampus; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; -import org.nutz.dao.Cnd; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Param; -import java.util.List; /** * @ClassName HealthCheckupCampusController @@ -36,9 +32,10 @@ import java.util.List; public class HealthCheckupCampusController { @Inject - private BaseService baseService; + private HealthCheckupCampusApplicationService applicationService; - @At("") + +@At("") @Ok("beetl:/platform/zhgh/dayofficework/healthCheckup/campus/index.html") @SaCheckPermission("healthCheckup.campus") public void index() { @@ -48,51 +45,25 @@ public class HealthCheckupCampusController { @ApiOperation("分页查询") @SaCheckPermission("healthCheckup.campus") public Result pageData(PageForm pageForm, @Param(value = "campusName") String campusName) { - Cnd cnd = Cnd.NEW(); - Sql sql = Sqls.create("select * from health_checkup_campus $condition"); - cnd.and(Cnd.likeEX("campusName", campusName)); - cnd.asc("campusCode"); - sql.setCondition(cnd); - return Result.success(baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql)); + return applicationService.pageData(pageForm, campusName); } @At @ApiOperation("添加院区") @SLog(type = "healthCheckup", tag = "体检管理", msg = "添加院区") @SaCheckPermission("healthCheckup.campus") + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) public Result doAdd(HealthCheckupCampus campus) { - try { - int count = baseService.dao().count(HealthCheckupCampus.class, Cnd.where(HealthCheckupCampus::getCampusCode, "=", campus.getCampusCode())); - if (count > 0) { - return Result.error("编码重复"); - } - baseService.dao().insert(campus); - return Result.success(); - } catch (Exception e) { - e.printStackTrace(); - return Result.error(); - } - + return applicationService.doAdd(campus); } @At @ApiOperation("编辑院区") @SLog(type = "healthCheckup", tag = "体检管理", msg = "编辑院区") @SaCheckPermission("healthCheckup.campus") + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) public Result doEdit(HealthCheckupCampus campus) { - try { - int count = baseService.dao().count(HealthCheckupCampus.class, - Cnd.where(HealthCheckupCampus::getCampusCode, "=", campus.getCampusCode()) - .and(HealthCheckupCampus::getId, "!=", campus.getId())); - if (count > 0) { - return Result.error("编码重复"); - } - baseService.dao().update(campus); - return Result.success(); - } catch (Exception e) { - e.printStackTrace(); - return Result.error(); - } + return applicationService.doEdit(campus); } @@ -100,26 +71,15 @@ public class HealthCheckupCampusController { @ApiOperation("编辑院区") @SLog(type = "healthCheckup", tag = "体检管理", msg = "删除院区") @SaCheckPermission("healthCheckup.campus") + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) public Result doDelete(String id) { - try { - baseService.dao().clear(HealthCheckupCampus.class, Cnd.where(HealthCheckupCampus::getId, "=", id)); - return Result.success(); - } catch (Exception e) { - e.printStackTrace(); - return Result.error(); - } + return applicationService.doDelete(id); } @At @ApiOperation("查询所有院区") @SaCheckLogin public Result queryCampus() { - try { - List campusList = baseService.dao().query(HealthCheckupCampus.class, Cnd.NEW().asc("campusCode")); - return Result.success(campusList); - } catch (Exception e) { - e.printStackTrace(); - return Result.error(); - } + return applicationService.queryCampus(); } } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupListController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupListController.java index ccfc6645..ea5fc828 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupListController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupListController.java @@ -1,45 +1,21 @@ package com.budwk.app.zhgh.dayofficework.healthCheckup.controller; -import cn.afterturn.easypoi.excel.ExcelExportUtil; -import cn.afterturn.easypoi.excel.entity.ExportParams; -import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupListApplicationService; +import com.budwk.app.zhgh.dayofficework.healthCheckup.param.HealthCheckupFilterUserPageForm; +import javax.validation.Valid; import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.StrUtil; -import cn.hutool.json.JSONUtil; import com.budwk.app.base.annotation.SLog; -import com.budwk.app.base.constant.RoleConstant; -import com.budwk.app.base.model.ExcelImportRes; -import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; -import com.budwk.app.base.utils.CommonDownloadUtil; -import com.budwk.app.base.utils.easyexcel.EasyExcelUtil; -import com.budwk.app.sys.views.View_user; -import com.budwk.app.web.commons.auth.utils.AuthUtil; -import com.budwk.app.web.commons.auth.utils.SecurityUtil; -import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope; import com.budwk.app.zhgh.dayofficework.healthCheckup.model.*; import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupProjectService; -import com.budwk.app.zhgh.dayofficework.healthCheckup.template.HealthCheckupImportTemp; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; -import org.apache.poi.ss.formula.functions.T; -import org.apache.poi.ss.usermodel.Workbook; 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.dao.Sqls; -import org.nutz.dao.sql.Sql; -import org.nutz.dao.util.cri.SqlExpressionGroup; 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.lang.util.NutMap; import org.nutz.mvc.annotation.AdaptBy; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; @@ -47,11 +23,7 @@ import org.nutz.mvc.upload.TempFile; import org.nutz.mvc.upload.UploadAdaptor; import javax.servlet.http.HttpServletResponse; -import java.util.ArrayList; -import java.util.Collections; import java.util.Date; -import java.util.List; -import java.util.stream.Collectors; /** * @ClassName HealthCheckupListController @@ -67,88 +39,53 @@ import java.util.stream.Collectors; public class HealthCheckupListController { @Inject - private Dao dao; + private HealthCheckupListApplicationService applicationService; - @Inject + +@Inject private HealthCheckupProjectService healthCheckupProjectService; - @At("") +@At("") @Ok("beetl:/platform/zhgh/dayofficework/healthCheckup/listMange/index.html") @SaCheckPermission("healthCheckup.list.mange") public void index() { } + @At("/feedback/query") + @Ok("beetl:/platform/zhgh/dayofficework/healthCheckup/feedbackQuery/index.html") + @SaCheckPermission("healthCheckup.list.mange.feedback") + public void feedbackQueryIndex() { + } + + /** + * @param pageForm 当前项目 ID、人员筛选及分页排序参数;空筛选项表示不限。 + * @return Result,code=0 时 data.list 为候选人员,data.totalCount 为总人数。 + */ + @At + @SaCheckPermission("healthCheckup.list.import") + @Ok("json:{dateFormat:'yyyy-MM-dd'}") + public Result candidatePageData(@Valid HealthCheckupFilterUserPageForm pageForm) { + return applicationService.candidatePageData(pageForm); + } + + /** + * @param pageForm 当前项目 ID 和人员筛选条件;添加全部匹配人员,不受分页限制。 + * @return Result,code=0 表示成功,msg 说明实际新增人数。 + */ + @At + @SaCheckPermission("healthCheckup.list.import") + @Aop(TransAop.READ_COMMITTED) + @SLog(type = "healthCheckup", tag = "体检管理", msg = "管理员添加体检人员") + public Result addUsers(@Valid HealthCheckupFilterUserPageForm pageForm) { + return applicationService.addUsers(pageForm); + } + @At @ApiOperation("分页查询") @SaCheckPermission("healthCheckup.list.mange") - public Result pageData(PageForm pageForm, - String projectId, - String unionId, - String unitId) { - List confirms = dao.query(HealthCheckupUnionConfirm.class, Cnd.where("projectId", "=", projectId)); - - HealthCheckupProject project = healthCheckupProjectService.findOne(projectId); - Cnd cnd = Cnd.NEW(); - Sql sql = Sqls.create(""" - SELECT - hcu.userId AS id, - hcu.loginName, - hcu.userName, - hcu.sex, - hcu.unionId, - hcu.unionName, - hcu.unitName, - hcus.selectTime, - hcus.campus, - hcus.subjectId, - hcus.bz, - hcus.receiveAddress, - ca.campusName - FROM - health_checkup_user hcu - LEFT JOIN health_checkup_user_selection hcus ON hcu.userId = hcus.selectUserId - AND hcus.projectId=@projectId - LEFT JOIN health_checkup_campus ca on ca.id=hcus.campus - $condition - """).setParam("projectId", projectId); - sql.setCondition(cnd); - cnd.andEX("hcu.projectId", "=", projectId); - cnd.andEX("hcu.unionId", "=", unionId); - cnd.andEX("hcu.unitId", "=", unitId); - - if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { - cnd.andEX("hcu.unionId", "=", SecurityUtil.getUnionId()); - } - - if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { - SqlExpressionGroup group = new SqlExpressionGroup(); - group.orLike("hcu.userName", pageForm.getSearchKeyword()); - group.orLike("hcu.loginName", pageForm.getSearchKeyword()); - cnd.and(group); - } - cnd.groupBy("hcu.userId"); - if (StrUtil.isNotBlank(pageForm.getPageOrderName()) && Strings.isNotBlank(pageForm.getPageOrderBy())) { - cnd.orderBy(pageForm.getPageOrderName(), "ascending".equalsIgnoreCase(pageForm.getPageOrderBy()) ? "ASC" : "DESC"); - } else { - cnd.desc("hcus.selectTime").asc("hcu.unitId"); - } - Pagination pagination = healthCheckupProjectService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); - List paginationList = pagination.getList(); - - paginationList.forEach(v -> { - if (StrUtil.isNotBlank(v.getString("subjectId"))) { - List subjects = project.getHealthCheckupProjectSubjects(); - HealthCheckupProjectSubject subject = subjects.stream().filter(s -> s.getId().equals(v.getString("subjectId"))).findFirst().orElse(null); - v.setv("optionName", subject.getOptionName()); - } - - if (StrUtil.isNotBlank(v.getString("unionId"))) { - HealthCheckupUnionConfirm confirm = confirms.stream().filter(o -> o.getUnionId().equals(v.getString("unionId"))).findFirst().orElse(null); - v.setv("isAudit", confirm != null ? confirm.getIsAudit() : ""); - v.setv("auditTime", confirm != null ? confirm.getAuditTime() : ""); - } - }); - return Result.success(pagination); + public Result pageData(PageForm pageForm, String projectId, String subjectId, + String unionId, String unitId, String physicalExaminationStatus, String isAudit) { + return applicationService.pageData(pageForm, projectId, subjectId, unionId, unitId, physicalExaminationStatus, isAudit); } @At @@ -159,21 +96,7 @@ public class HealthCheckupListController { public Result doAuditUser(String projectId, String unionId, Boolean flag) { - if (StrUtil.isBlank(unionId)) { - unionId = SecurityUtil.getUnionId(); - } - if (flag) { - dao.update(HealthCheckupUnionConfirm.class, Chain.make("isAudit", true) - .add("auditTime", DateUtil.date()) - .add("auditUser", SecurityUtil.getUserId()), - Cnd.where("projectId", "=", projectId).and("unionId", "=", unionId)); - } else { - dao.update(HealthCheckupUnionConfirm.class, Chain.make("isAudit", null) - .add("auditTime", null) - .add("auditUser", null), - Cnd.where("projectId", "=", projectId).and("unionId", "=", unionId)); - } - return Result.success(); + return applicationService.doAuditUser(projectId, unionId, flag); } @@ -181,93 +104,20 @@ public class HealthCheckupListController { @ApiOperation("体检名单管理员编辑选择记录") @SLog(type = "healthCheckup", tag = "体检管理", msg = "管理员编辑了一条选择记录") @SaCheckPermission("healthCheckup.list.mange") + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) public Result doEditHealthCheckupData(String subjectId, String campus, String projectId, String userId, String bz) { - - //查询用户有没有选择过套餐 - HealthCheckupUserSelection userSelection = healthCheckupProjectService.dao().fetch(HealthCheckupUserSelection.class, - Cnd.where("projectId", "=", projectId).and("selectUserId", "=", userId)); - //如果选择过套餐就修改选择的套餐id - if (Lang.isNotEmpty(userSelection)) { - userSelection.setSubjectId(subjectId); - userSelection.setCampus(campus); - userSelection.setBz(bz); - healthCheckupProjectService.update(userSelection); - } else { - //如果没有选择过套餐添加一条记录 - HealthCheckupUserSelection checkupUserSelection = new HealthCheckupUserSelection(); - checkupUserSelection.setSelectUserId(userId); - checkupUserSelection.setProjectId(projectId); - checkupUserSelection.setSubjectId(subjectId); - checkupUserSelection.setCampus(campus); - checkupUserSelection.setSelectTime(new Date()); - checkupUserSelection.setBz(bz); - healthCheckupProjectService.insert(checkupUserSelection); - } - return Result.success(); + return applicationService.doEditHealthCheckupData(subjectId, campus, projectId, userId, bz); } @At @ApiOperation("体检名单导入名单") @SLog(type = "healthCheckup", tag = "体检管理", msg = "管理员导入了体检名单") - @SaCheckPermission("healthCheckup.list.mange") + @SaCheckPermission("healthCheckup.list.import") @Aop(TransAop.READ_COMMITTED) @AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"}) public Result healthImport(TempFile file, String healthProjectId) { - // 读取数据 - List ts = EasyExcelUtil.syncReadModel(file.getFile(), HealthCheckupImportTemp.class, 0, 1); - List healthCheckupImportTemps = JSONUtil.parseArray(JSONUtil.toJsonStr(ts)).toList(HealthCheckupImportTemp.class); - List loginNames = healthCheckupImportTemps.stream().filter(v -> Strings.isNotBlank(v.getLoginName())).map(v -> v.getLoginName()).collect(Collectors.toList()); - //全部的体检名单 - List healthCheckupUserList = dao.query(HealthCheckupUser.class, Cnd.where(HealthCheckupUser::getProjectId, "=", healthProjectId)); - - - List userList = dao.query(View_user.class, Cnd.where(View_user::getLoginname, "in", loginNames)); - - HealthCheckupProject checkupProject = dao.fetch(HealthCheckupProject.class, healthProjectId); - ActivityUserScope userScope = dao.fetch(ActivityUserScope.class, Cnd.where("groupId", "=", checkupProject.getActivityGroupId())); - List userScopeList = new ArrayList<>(); - for (int i = 0; i < healthCheckupImportTemps.size(); i++) { - HealthCheckupImportTemp excel = healthCheckupImportTemps.get(i); - if (StrUtil.isBlank(excel.getLoginName())) { - excel.setErrInfo("工号为空", i + 1); - continue; - } - - // 不能在excel里重复 - if (healthCheckupImportTemps.stream().filter(s -> s.getLoginName().equals(excel.getLoginName())).count() > 1) { - excel.setErrInfo("重复数据", i + 1); - } - - View_user user = userList.stream().filter(s -> s.getLoginname().equals(excel.getLoginName())).findFirst().orElse(null); - if (user == null) { - excel.setErrInfo("无此用户", i + 1); - continue; - } - - if (healthCheckupUserList.stream().anyMatch(s -> s.getUserId().equals(user.getId()))) { - excel.setErrInfo("该用户已加入体检名单", i + 1); - continue; - } - - ActivityUserScope s = new ActivityUserScope(); - s.setGroupId(userScope.getGroupId()); - s.setGroupName(userScope.getGroupName()); - s.setUserId(user.getId()); - s.setCreator(SecurityUtil.getUserId()); - userScopeList.add(s); - } - ; - - dao.insert(userScopeList); - // 创建结果集 - ExcelImportRes excelImportRes = new ExcelImportRes<>(); - excelImportRes.setTotalRecords(healthCheckupImportTemps.size()); - // 添加错误记录 - excelImportRes.setErrorDetails(healthCheckupImportTemps.stream().filter(s -> StrUtil.isNotBlank(s.getErrMsg())).collect(Collectors.toList())); - excelImportRes.setFailedCount(excelImportRes.getErrorDetails().size()); - - return Result.success(excelImportRes); + return applicationService.healthImport(file, healthProjectId); } @At @@ -275,12 +125,106 @@ public class HealthCheckupListController { @ApiOperation("下载体检参加人员导入模版") @SaCheckPermission("healthCheckup.list.mange") public void downloadTem(HttpServletResponse response) { - List entities = new ArrayList<>(); - entities.add(new ExcelExportEntity("工号", "loginName", 20)); - entities.add(new ExcelExportEntity("姓名", "userName", 20)); - ExportParams exportParams = new ExportParams(); - Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, Collections.emptyList()); - CommonDownloadUtil.download("参加人员导入模版.xlsx", workbook, response); + applicationService.downloadTem(response); + } + + @At + @ApiOperation("体检名单删除") + @SaCheckPermission("healthCheckup.list.delete") + @Aop(TransAop.READ_COMMITTED) + public Result doDelete(String id) { + return applicationService.doDelete(id); + } + + @At + @Ok("void") + @ApiOperation("下载体检报告导入模版") + @SaCheckPermission("healthCheckup.list.mange") + public void downloadTemMedicalExaminationReport(HttpServletResponse response) { + applicationService.downloadTemMedicalExaminationReport(response); + } + + @At + @ApiOperation("体检名单导入名单") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "管理员导入了体检名单") + @SaCheckPermission("healthCheckup.list.import.medicalExamination") + @Aop(TransAop.READ_COMMITTED) + @AdaptBy(type = UploadAdaptor.class, args = {"ioc:fileUpload"}) + public Result healthImportMedicalExaminationReport(TempFile file, String healthProjectId) { + return applicationService.healthImportMedicalExaminationReport(file, healthProjectId); + } + + @At + @ApiOperation("套餐选择器查询") + @SaCheckPermission("healthCheckup.list.mange") + public Result listSubjects(String projectId){ + return applicationService.listSubjects(projectId); + } + + @At + @ApiOperation("体检反馈列表") + @SaCheckPermission("healthCheckup.list.mange") + public Result feedbackList(String year, String projectId, String unionId) { + return applicationService.feedbackList(year, projectId, unionId); + } + + @At + @ApiOperation("保存体检反馈") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "新增体检反馈") + @SaCheckPermission("healthCheckup.list.mange") + @Aop(TransAop.READ_COMMITTED) + public Result saveFeedback(String year, String projectId, String unionId, String feedbackInfo) { + return applicationService.saveFeedback(year, projectId, unionId, feedbackInfo); + } + + @At + @ApiOperation("删除体检反馈") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "删除体检反馈") + @SaCheckPermission("healthCheckup.list.mange") + @Aop(TransAop.READ_COMMITTED) + public Result deleteFeedback(String id) { + return applicationService.deleteFeedback(id); + } + + @At + @ApiOperation("批量删除体检反馈") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "批量删除体检反馈") + @SaCheckPermission("healthCheckup.list.mange") + @Aop(TransAop.READ_COMMITTED) + public Result deleteFeedbackBatch(String ids) { + return applicationService.deleteFeedbackBatch(ids); + } + + @At("/feedback/query/pageData") + @ApiOperation("问题反馈列表分页") + @SaCheckPermission("healthCheckup.list.mange") + public Result feedbackQueryPageData(PageForm pageForm, String year, String projectId, String unionId) { + return applicationService.feedbackQueryPageData(pageForm, year, projectId, unionId); + } + + @At + @ApiOperation("体检名单编辑备注") + @SLog(type = "healthCheckup", tag = "体检管理", msg = "编辑备注") + @SaCheckPermission("healthCheckup.list.mange") + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doEditRemarks(String userId, String projectId,String remarks) { + return applicationService.doEditRemarks(userId, projectId, remarks); + } + + @At + @Ok("void") + @ApiOperation("导出") + @SaCheckPermission("healthCheckup.list.mange") + public void exportHealthUser(String projectId, + String unionId, + String searchKeyword, + String subjectId, + String unitId, + String physicalExaminationStatus, + String pageOrderName, + String pageOrderBy, + HttpServletResponse response) { + applicationService.exportHealthUser(projectId, unionId, searchKeyword, subjectId, unitId, physicalExaminationStatus, pageOrderName, pageOrderBy, response); } } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupPersonConfirmStatisticsController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupPersonConfirmStatisticsController.java new file mode 100644 index 00000000..13bebfb2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupPersonConfirmStatisticsController.java @@ -0,0 +1,44 @@ +package com.budwk.app.zhgh.dayofficework.healthCheckup.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupPersonConfirmStatisticsService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; + +/** + * @ClassName HealthCheckupPersonConfirmStatisticsController + * @Description 工会确认情况统计 + * @Author Codex + * @Date 2026/4/28 + */ +@IocBean +@Ok("json:full") +@Api(tags = "体检人员确认情况统计") +@At("/platform/healthCheckup/statistics/personconfirm") +public class HealthCheckupPersonConfirmStatisticsController { + + @Inject + private HealthCheckupPersonConfirmStatisticsService healthCheckupPersonConfirmStatisticsService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/healthCheckup/personconfirm/index.html") + @SaCheckPermission("healthCheckup.personconfirm") + public void index() { + } + + @At + @ApiOperation("工会确认情况分页统计") + @SaCheckPermission("healthCheckup.personconfirm") + public Result pageData(PageForm pageForm, Integer year, String projectId, String unionId) { + // 统计报表按年度、体检项目查询,工会条件选填,统一返回分页结果供前端表格展示。 + Pagination statistics = healthCheckupPersonConfirmStatisticsService.personConfirmPageData(pageForm.getPageNumber(), pageForm.getPageSize(), year, projectId, unionId); + return Result.success(statistics); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupProjectMangeController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupProjectMangeController.java index 47fa6bab..f3a48811 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupProjectMangeController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupProjectMangeController.java @@ -1,33 +1,22 @@ package com.budwk.app.zhgh.dayofficework.healthCheckup.controller; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupProjectMangeApplicationService; import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.hutool.core.date.DateUtil; -import cn.hutool.core.util.StrUtil; import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; -import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.zhgh.activity.culture.service.ActivityCultureService; import com.budwk.app.zhgh.dayofficework.healthCheckup.model.*; -import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupProjectService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.nutz.aop.interceptor.ioc.TransAop; -import org.nutz.dao.Cnd; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; -import org.nutz.dao.util.Daos; 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.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Param; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; /** * @ClassName HealthCheckupProjectMangeController @@ -42,7 +31,11 @@ import java.util.stream.Collectors; public class HealthCheckupProjectMangeController { @Inject - private HealthCheckupProjectService healthCheckupProjectService; + private HealthCheckupProjectMangeApplicationService applicationService; + + +@Inject + private ActivityCultureService activityCultureService; @At("") @@ -58,102 +51,25 @@ public class HealthCheckupProjectMangeController { public Result pageData(PageForm pageForm, Integer year, String name) { - Sql sql = Sqls.create(""" - SELECT - hcp.id, - hcp.`year`, - hcp.`name`, - hcp.choiceTimeStart, - hcp.choiceTimeEnd, - hcp.activityGroupId, - hcp.cover, - hcp.activityGroupName, - hcp.healthCheckupType, - IF((select count(userId) from health_checkup_user hcu where hcu.projectId = hcp.id) > 0,true,false) AS isHasUserList, - IF(NOW() > hcp.choiceTimeStart AND NOW() < hcp.choiceTimeEnd, true, false) AS isWithinChoiceTime, - IF(NOW() < hcp.choiceTimeStart, true, false) AS canCreated - FROM - health_checkup_project hcp - $condition - """); - Cnd cnd = Cnd.NEW(); - cnd.andEX("hcp.`year`", "=", year); - cnd.andEX("hcp.`name`", "=", name); - cnd.desc("hcp.choiceTimeStart"); - sql.setCondition(cnd); - return Result.success(healthCheckupProjectService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql)); + return applicationService.pageData(pageForm, year, name); } @At - @ApiOperation("体检名单确认") + @ApiOperation("体检项目确认") @Aop(TransAop.READ_COMMITTED) @SaCheckPermission("healthCheckup.projectMange") @SLog(type = "healthCheckup", tag = "体检管理", msg = "提交体检项目") public Result doAdd(HealthCheckupProject healthCheckupProject, @Param(value = "deleteRowIds") String[] deleteRowIds, @Param(value = "deleteSubjectIds") String[] deleteSubjectIds) { - - - String projectId; - //如果是保存 - if (StrUtil.isBlank(healthCheckupProject.getId())) { - healthCheckupProject.setYear(DateUtil.thisYear()); - HealthCheckupProject checkupProject = healthCheckupProjectService.insertWith(healthCheckupProject, "healthCheckupProjectSubjects"); - healthCheckupProject.getHealthCheckupProjectSubjects().forEach(v -> { - v.getSubjectMoneys().forEach(m -> { - m.setProjectId(checkupProject.getId()); - m.setSubjectId(v.getId()); - }); - if (Lang.isNotEmpty(v.getSubjectMoneys())) { - healthCheckupProjectService.insert(v.getSubjectMoneys()); - } - }); - projectId = checkupProject.getId(); - } else { - projectId = healthCheckupProject.getId(); - //如果删除了医院 - if (Lang.isNotEmpty(deleteSubjectIds)) { - healthCheckupProjectService.dao().clear(HealthCheckupProjectSubject.class, Cnd.where("id", "in", deleteSubjectIds)); - healthCheckupProjectService.dao().clear(HealthCheckupProjectSubjectMoney.class, Cnd.where("subjectId", "in", deleteSubjectIds)); - } - //如果删除了项目 - if (Lang.isNotEmpty(deleteRowIds)) { - healthCheckupProjectService.dao().clear(HealthCheckupProjectSubjectMoney.class, Cnd.where("id", "in", deleteRowIds)); - } - healthCheckupProjectService.dao().insertOrUpdate(healthCheckupProject.getHealthCheckupProjectSubjects()); - healthCheckupProject.getHealthCheckupProjectSubjects().forEach(v -> { - v.setProjectId(projectId); - v.getSubjectMoneys().forEach(m -> { - m.setProjectId(projectId); - m.setSubjectId(v.getId()); - }); - if (Lang.isNotEmpty(v.getSubjectMoneys())) { - healthCheckupProjectService.insertOrUpdate(v.getSubjectMoneys()); - } - }); - healthCheckupProjectService.dao().insertOrUpdate(healthCheckupProject.getHealthCheckupProjectSubjects()); - healthCheckupProjectService.update(healthCheckupProject); - } - - healthCheckupProjectService.dao().clear(HealthCheckupUnionConfirm.class, Cnd.where("projectId", "=", projectId)); - List unionList = healthCheckupProjectService.dao().query(Sys_union.class, Cnd.NEW()); - List confirmList = new ArrayList<>(); - unionList.forEach(item -> { - HealthCheckupUnionConfirm c = new HealthCheckupUnionConfirm(); - c.setProjectId(projectId); - c.setUnionId(item.getId()); - c.setIsAudit(false); - confirmList.add(c); - }); - healthCheckupProjectService.dao().insert(confirmList); - return Result.success(); + return applicationService.doAdd(healthCheckupProject, deleteRowIds, deleteSubjectIds); } @At @ApiOperation("查询体检项目内容") @SLog(type = "healthCheckup", tag = "体检管理", msg = "查询体检项目内容") public Result findOne(String id) { - return Result.success(healthCheckupProjectService.findOne(id)); + return applicationService.findOne(id); } @At @@ -162,18 +78,14 @@ public class HealthCheckupProjectMangeController { @SaCheckPermission("healthCheckup.projectMange") @SLog(type = "healthCheckup", tag = "体检管理", msg = "删除了一条体检项目") public Result doDelete(String id) { - healthCheckupProjectService.delete(id); - healthCheckupProjectService.dao().clear(HealthCheckupProjectSubject.class, Cnd.where("projectId", "=", id)); - healthCheckupProjectService.dao().clear(HealthCheckupProjectSubjectMoney.class, Cnd.where("projectId", "=", id)); - return Result.success(); + return applicationService.doDelete(id); } @At @ApiOperation("按年份获取体检项目") @SLog(type = "healthCheckup", tag = "体检管理", msg = "查询了所有的体检项目") public Result getHealthCheckupProject(Integer year) { - List projectList = healthCheckupProjectService.query(Cnd.NEW().andEX("year", "=", year).desc("choiceTimeStart")); - return Result.success(projectList); + return applicationService.getHealthCheckupProject(year); } @@ -189,8 +101,7 @@ public class HealthCheckupProjectMangeController { @SaCheckPermission("healthCheckup.projectMange") @SLog(type = "healthCheckup", tag = "体检管理", msg = "创建体检名单") public Result createUserList(HealthCheckupProject healthCheckupProject) { - healthCheckupProjectService.addHealthCheckupUser(healthCheckupProject); - return Result.success(); + return applicationService.createUserList(healthCheckupProject); } @@ -206,8 +117,7 @@ public class HealthCheckupProjectMangeController { @SaCheckPermission("healthCheckup.projectMange") @SLog(type = "healthCheckup", tag = "体检管理", msg = "更新体检名单") public Result renewUserList(HealthCheckupProject healthCheckupProject) { - healthCheckupProjectService.renewHealthCheckupUser(healthCheckupProject); - return Result.success(); + return applicationService.renewUserList(healthCheckupProject); } @@ -223,16 +133,6 @@ public class HealthCheckupProjectMangeController { @SaCheckPermission("healthCheckup.projectMange") @SLog(type = "healthCheckup", tag = "体检管理", msg = "重置体检名单") public Result resetUserList(HealthCheckupProject healthCheckupProject) { - //重置名单,清空已选择的用户记录 - Sql sql = Sqls.create("select id,selectUserId from health_checkup_user_selection where projectId = @projectId").setParam("projectId", healthCheckupProject.getId()); - List list = (List) Daos.query(healthCheckupProjectService.dao(), sql.toString(), Sqls.callback.maps()); - List userSelectionIds = list.stream().map(v -> v.getString("id")).collect(Collectors.toList()); - List userIds = list.stream().map(v -> v.getString("selectUserId")).collect(Collectors.toList()); - - healthCheckupProjectService.dao().clear(HealthCheckupUserSelection.class, Cnd.where("selectUserId", "in", userIds)); - healthCheckupProjectService.dao().clear(HealthCheckupUserCompanion.class, Cnd.where("userSelectionId", "in", userSelectionIds)); - healthCheckupProjectService.dao().clear(HealthCheckupUser.class, Cnd.where("projectId", "=", healthCheckupProject.getId())); - healthCheckupProjectService.addHealthCheckupUser(healthCheckupProject); - return Result.success(); + return applicationService.resetUserList(healthCheckupProject); } } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupSingleController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupSingleController.java index a91705d5..d3d90e6d 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupSingleController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/controller/HealthCheckupSingleController.java @@ -1,46 +1,22 @@ package com.budwk.app.zhgh.dayofficework.healthCheckup.controller; -import cn.afterturn.easypoi.excel.ExcelExportUtil; -import cn.afterturn.easypoi.excel.entity.ExportParams; -import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; -import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupSingleApplicationService; import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.hutool.core.date.DateUtil; import com.budwk.app.base.annotation.SLog; -import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; -import com.budwk.app.base.utils.CommonDownloadUtil; -import com.budwk.app.base.utils.ConditionGroupUtil; -import com.budwk.app.base.utils.ManyAddOrRenewUtil; -import com.budwk.app.sys.views.View_user; -import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupProject; -import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupProjectSubject; -import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupProjectSubjectMoney; -import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupUserSelection; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupProjectService; import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupSingleService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; -import org.apache.poi.ss.usermodel.Workbook; -import org.nutz.dao.Cnd; -import org.nutz.dao.Dao; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.lang.Strings; -import org.nutz.lang.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; import javax.servlet.http.HttpServletResponse; import javax.validation.Valid; -import java.math.BigDecimal; -import java.util.ArrayList; -import java.util.Calendar; import java.util.Date; -import java.util.List; -import java.util.stream.Collectors; /** * @ClassName HealthCheckupSingleController @@ -54,11 +30,14 @@ import java.util.stream.Collectors; @At("/platform/healthCheckup/statistics/single") public class HealthCheckupSingleController { + @Inject + private HealthCheckupSingleApplicationService applicationService; - @Inject + +@Inject private HealthCheckupSingleService healthCheckupSingleService; - @Inject - private ManyAddOrRenewUtil manyAddOrRenewUtil; +@Inject + private HealthCheckupProjectService healthCheckupProjectService; @At("") @Ok("beetl:/platform/zhgh/dayofficework/healthCheckup/statisticsSingle/index.html") @@ -66,14 +45,32 @@ public class HealthCheckupSingleController { public void index() { } - @At @ApiOperation("首页查询") @SaCheckPermission("healthCheckup.statisticsSingle") public Result pageData(String projectId, String unionId) { - NutMap nutMap = healthCheckupSingleService.pageData(projectId, unionId); - return Result.success(nutMap); + return applicationService.pageData(projectId, unionId); + } + + /** + * projectId传体检项目ID;返回Result.data为人数映射,__total__为总人数,其余键为医院ID。 + */ + @At + @SaCheckPermission("healthCheckup.statisticsSingle") + public Result actualStatistics(String projectId) { + return applicationService.actualStatistics(projectId); + } + + /** + * projectId传体检项目ID,counts传整行人数JSON(__total__及医院ID映射非负整数)。 + * 返回Result,data为已保存人数映射;非零code表示校验或权限失败,msg说明原因。 + */ + @At + @SaCheckPermission("healthCheckup.statisticsSingle") + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result saveActualStatistics(String projectId, String counts) { + return applicationService.saveActualStatistics(projectId, counts); } /** @@ -91,12 +88,22 @@ public class HealthCheckupSingleController { public Result receivePageData(PageForm page, String isSelected, String projectId, String unionId) { - List labelList = healthCheckupSingleService.receivePageDataColumns(projectId); - Pagination list = healthCheckupSingleService.receivePageData(page.getPageNumber(), page.getPageSize(), page.getSearchName(), page.getSearchKeyword(), projectId, unionId, isSelected); - return Result.success(NutMap.NEW().addv("list", list).addv("label", labelList)); + return applicationService.receivePageData(page, isSelected, projectId, unionId); } + /** + * @param projectId 当前教职工体检项目ID;不接收分工会筛选,权限在service中校验 + * @param response 返回ZIP附件,其中每个xlsx为一家医院的已选名单,不返回JSON + */ + @At + @Ok("void") + @ApiOperation("按医院导出已选名单ZIP") + @SaCheckPermission("healthCheckup.statisticsSingle") + public void exportSelectedZip(String projectId, HttpServletResponse response) { + applicationService.exportSelectedZip(projectId, response); + } + /** * 导出已选/未选人员名单 * @@ -114,48 +121,7 @@ public class HealthCheckupSingleController { String unionId, Integer year, boolean flag, HttpServletResponse response) { - - List entityList = new ArrayList<>() {{ - add(new ExcelExportEntity("职工号", "loginName", 20)); - add(new ExcelExportEntity("姓名", "userName", 20)); - add(new ExcelExportEntity("性别", "sex", 20)); -// add(new ExcelExportEntity("出生年月", "birthday", 20)); - add(new ExcelExportEntity("年龄", "age", 20)); - add(new ExcelExportEntity("婚姻状况", "marriage", 20)); - add(new ExcelExportEntity("身份证号", "idCard", 20)); - add(new ExcelExportEntity("部门", "unitName", 20)); -// add(new ExcelExportEntity("部门编码", "unitCode", 20)); - add(new ExcelExportEntity("医院", "subjectName", 20)); - add(new ExcelExportEntity("邮寄地址", "receiveAddress", 50)); - }}; - - List list; - if (flag) { - //已选人员 - list = healthCheckupSingleService.receivePageData(projectId, unionId, "0"); - } else { - //未选人员 - list = healthCheckupSingleService.receivePageData(projectId, unionId, "1"); - } - //获取当前年 - Calendar calendar = Calendar.getInstance(); - int thisYear = calendar.get(Calendar.YEAR); - list.forEach(v -> { - int substring = 0; - if (Strings.isNotBlank(v.getString("birthday"))) { - substring = Integer.parseInt(v.getString("birthday").substring(0, 4)); - } else if (Strings.isNotBlank(v.getString("idCard")) && v.getString("idCard").length() >= 10) { - substring = Integer.parseInt(v.getString("idCard").substring(6, 10)); - } - v.put("age", thisYear - substring); - }); - - List list2 = list.stream().filter(v -> Strings.isNotBlank(v.getString("unionName"))).collect(Collectors.toList()); - ExportParams exportParams = new ExportParams(); - exportParams.setType(ExcelType.XSSF); - exportParams.setSheetName(year + "年教职工体检项目及地点统计表"); - Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, list2); - CommonDownloadUtil.download((flag ? year + "年教职工体检项目及地点统计表" : "未选名单") + ".xlsx", workbook, response); + applicationService.exportReceiveDetail(projectId, unionId, year, flag, response); } @@ -166,69 +132,7 @@ public class HealthCheckupSingleController { public void exportUserCompanion(String projectId, String unionId, Integer year, HttpServletResponse response) { - Sql sql = Sqls.create(""" - SELECT - u.username, - u.unitname unitName, - u.mobile, - hcuc.userName familyName, - hcuc.sex, - hcuc.marry isMarried, - hcuc.idCard, - hcc.campusName, - ( - SELECT - GROUP_CONCAT( hcps.optionName ) - FROM - health_checkup_user_selection hcus - LEFT JOIN `health_checkup_project_subject` hcps ON hcps.id = hcus.subjectId - WHERE - hcus.projectId = @projectId - AND hcus.selectUserId = u.id - ) optionName - FROM - `health_checkup_user_companion` hcuc - LEFT JOIN `health_checkup_user_selection` hcus ON hcus.id = hcuc.userSelectionId - LEFT JOIN `health_checkup_campus` hcc ON hcc.id = hcus.campus - LEFT JOIN `vw_user` u ON u.id = hcus.selectUserId - LEFT JOIN `health_checkup_project` hcp ON hcp.id = hcus.projectId - $condition - """).setParam("projectId", projectId); - Cnd cnd = Cnd.NEW(); - cnd.andEX("hcus.projectId", "=", projectId); - cnd.andEX("u.unionid", "=", unionId); - cnd.andEX("hcp.year", "=", year); - cnd.asc("u.unioncode"); - sql.setCondition(cnd); - //家属信息表 - List companionList = healthCheckupSingleService.listMap(sql); - - for (int i = 0; i < companionList.size(); i++) { - companionList.get(i).put("index", i + 1); - } - - List entityList = new ArrayList<>() {{ - add(new ExcelExportEntity("序号", "index", 20)); - add(new ExcelExportEntity("教职工姓名", "username", 20)); - add(new ExcelExportEntity("学院(部门)", "unitName", 20)); - add(new ExcelExportEntity("手机", "mobile", 20)); - add(new ExcelExportEntity("体检人姓名", "familyName", 20)); - add(new ExcelExportEntity("性别", "sex", 20)); - add(new ExcelExportEntity("婚否", "isMarried", 20)); - add(new ExcelExportEntity("体检人身份证号", "idCard", 50)); - add(new ExcelExportEntity("自选项目", "optionName", 50)); - add(new ExcelExportEntity("自选院区", "campusName", 50)); - }}; - - try { - ExportParams exportParams = new ExportParams(); - exportParams.setType(ExcelType.XSSF); - exportParams.setTitle(year + "教职工家属体检登记表"); - Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, companionList); - CommonDownloadUtil.download(year + "教职工家属体检登记表.xlsx", workbook, response); - } catch (Exception e) { - e.printStackTrace(); - } + applicationService.exportUserCompanion(projectId, unionId, year, response); } @@ -237,132 +141,20 @@ public class HealthCheckupSingleController { @Ok("json:full") @SaCheckPermission("healthCheckup.statisticsSingle") @SLog(type = "healthCheckup", tag = "体检管理", msg = "管理员一键代选") + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) public Result doSelectByAdmin(String projectId, String optionId, String campus) { - Dao dao = healthCheckupSingleService.dao(); - HealthCheckupProject project = dao.fetch(HealthCheckupProject.class, projectId); - - Cnd cnd = Cnd.NEW(); - Sql sql = Sqls.create(""" - SELECT - u.id, - u.loginname loginName, - u.username userName, - u.sex, - u.birthday, - u.unitname unitName, - u.unionname unionName, - u.idcard idCard, - u.mobile - FROM - `activity_user_scope` aus - LEFT JOIN `vw_user` u ON u.id = aus.userId - $projectCnd $condition - """); - - cnd.and("aus.groupId", "=", project.getActivityGroupId()); - sql.setVar("projectCnd", "AND u.id NOT IN ( SELECT selectUserId FROM `health_checkup_user_selection` WHERE projectId = '" + projectId + "' AND selectUserId IS NOT NULL )"); - cnd.groupBy("u.loginname"); - sql.setCondition(cnd); - List mapList = healthCheckupSingleService.listMap(sql); - - List userIds = mapList.stream().map(v -> v.getString("id")).collect(Collectors.toList()); - //题目id - List selections = userIds.stream().map(v -> { - HealthCheckupUserSelection selection = new HealthCheckupUserSelection(); - selection.setProjectId(projectId); - selection.setSelectUserId(v); - selection.setCampus(campus); - selection.setSubjectId(optionId); - selection.setSelectTime(new Date()); - return selection; - }).collect(Collectors.toList()); - manyAddOrRenewUtil.asyncExecuteFastInsert(selections, null); - return Result.success(); + return applicationService.doSelectByAdmin(projectId, optionId, campus); } @At - @ApiOperation("管理员一键选择去年数据") + @ApiOperation("按上年补齐未选人员") @Ok("json:full") @SaCheckPermission("healthCheckup.statisticsSingle") @SLog(type = "healthCheckup", tag = "体检管理", msg = "管理员给没选的人统一选择去年的数据") - public Result selectOptionByLastYear(String projectId) { - - Dao dao = healthCheckupSingleService.dao(); - //获取去年项目 - HealthCheckupProject lastYearProject = dao.fetch(HealthCheckupProject.class, Cnd.where("YEAR(year)", "=", DateUtil.thisYear() - 1)); - if (lastYearProject == null) { - return Result.error("请先创建去年的体检项目"); - } - Cnd cnd = Cnd.NEW(); - Sql sql = Sqls.create(""" - SELECT - u.id - FROM - health_checkup_user hcu - LEFT JOIN `vw_user` u ON u.id = hcu.userId - $projectCnd $condition - """); - cnd.and("hcu.projectId", "=", projectId); - sql.setVar("projectCnd", "AND u.id NOT IN ( SELECT selectUserId FROM `health_checkup_user_selection` WHERE projectId = '" + projectId + "' AND selectUserId IS NOT NULL )"); - cnd.groupBy("u.loginname"); - sql.setCondition(cnd); - List mapList = healthCheckupSingleService.listMap(sql); - - List userIds = mapList.stream().map(v -> v.getString("id")).toList(); - - //去年项目的人 - List lastYearSelectionList = dao.query(HealthCheckupUserSelection.class, Cnd.where(HealthCheckupUserSelection::getProjectId, "=", lastYearProject.getId()) - .and(HealthCheckupUserSelection::getSelectUserId, "in", userIds)); - - //去年项目下的医院 - List lastYearSubjectList = dao.query(HealthCheckupProjectSubject.class, - Cnd.where(HealthCheckupProjectSubject::getProjectId, "=", lastYearProject.getId())); - - //今年项目下的医院 - List thisYearSubjectList = dao.query(HealthCheckupProjectSubject.class, - Cnd.where(HealthCheckupProjectSubject::getProjectId, "=", projectId)); - - List selections = new ArrayList<>(); - userIds.forEach(v -> { - //获取去年这个人选择的记录 - HealthCheckupUserSelection userSelection = lastYearSelectionList.stream().filter(item -> item.getSelectUserId().equals(v)).findFirst().orElse(null); - //去年这个人选择的选项是什么 - HealthCheckupProjectSubject lastYearSubject = lastYearSubjectList.stream().filter(last -> last.getId().equals(userSelection.getSubjectId())).findFirst().orElse(null); - //今年项目下的选项 - HealthCheckupProjectSubject thisYearSubject = thisYearSubjectList.stream().filter(thisYear -> thisYear.getOptionName().equals(lastYearSubject.getOptionName())).findFirst().orElse(null); - if (userSelection != null && thisYearSubject != null) { - //获取今年这个选项的收费 - List list = dao.query(HealthCheckupProjectSubjectMoney.class, - Cnd.where(HealthCheckupProjectSubjectMoney::getSubjectId, "=", thisYearSubject.getId())); - BigDecimal money = BigDecimal.valueOf(0.00); - String subjectMoneyId = null; - for (HealthCheckupProjectSubjectMoney subject : list) { - //找出这个人符合哪个项目 - Cnd cndUser = Cnd.where("id", "=", v); - ConditionGroupUtil.applyConditionGroup(cndUser, subject.getMatchCnd()); - int count = dao.count(View_user.class, cndUser); - if (count > 0) { - money = subject.getMoney(); - subjectMoneyId = subject.getId(); - break; - } - } - //如果有符合的就添加 - if (subjectMoneyId != null) { - HealthCheckupUserSelection selection = new HealthCheckupUserSelection(); - selection.setProjectId(projectId); - selection.setSelectUserId(v); - selection.setSubjectId(thisYearSubject.getId()); - selection.setSubjectMoneyId(subjectMoneyId); - selection.setMoney(money); - selection.setSelectTime(new Date()); - selections.add(selection); - } - - } - }); - return Result.success(); + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result selectOptionByLastYear(String projectId, String lastYearProjectId) { + return applicationService.selectOptionByLastYear(projectId, lastYearProjectId); } @@ -372,7 +164,7 @@ public class HealthCheckupSingleController { @SaCheckPermission("healthCheckup.statisticsSingle") @SLog(type = "healthCheckup", tag = "体检管理", msg = "管理员给未选的人发送提醒") public Result msgNotSelect(@Valid String projectId) { - List userList = healthCheckupSingleService.receivePageData(projectId, null, "1"); - return Result.success("暂未开启消息!"); + return applicationService.msgNotSelect(projectId); } + } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/h5controller/H5HealthCheckupController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/h5controller/H5HealthCheckupController.java index be0c21cd..189aae53 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/h5controller/H5HealthCheckupController.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/h5controller/H5HealthCheckupController.java @@ -1,41 +1,23 @@ package com.budwk.app.zhgh.dayofficework.healthCheckup.h5controller; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.H5HealthCheckupApplicationService; import cn.dev33.satoken.annotation.SaCheckPermission; import cn.dev33.satoken.annotation.SaMode; -import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.StrUtil; -import com.budwk.app.base.page.Pagination; import com.budwk.app.base.param.PageForm; import com.budwk.app.base.result.Result; import com.budwk.app.base.service.BaseService; -import com.budwk.app.base.utils.ConditionGroupUtil; -import com.budwk.app.sys.views.View_user; -import com.budwk.app.web.commons.auth.utils.SecurityUtil; -import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupCampus; -import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupProject; -import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupProjectSubjectMoney; -import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupUserSelection; -import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupProjectService; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.*; import io.swagger.annotations.ApiOperation; import org.nutz.aop.interceptor.ioc.TransAop; -import org.nutz.dao.Cnd; -import org.nutz.dao.Dao; -import org.nutz.dao.Sqls; -import org.nutz.dao.sql.Sql; -import org.nutz.dao.util.cri.Static; 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.util.NutMap; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Param; -import java.math.BigDecimal; -import java.util.Date; -import java.util.List; -import java.util.Map; /** * @author : hongqiwei @@ -49,14 +31,13 @@ import java.util.Map; public class H5HealthCheckupController { @Inject - private Dao dao; - @Inject + private H5HealthCheckupApplicationService applicationService; + + +@Inject private BaseService baseService; - @Inject - private HealthCheckupProjectService healthCheckupProjectService; - - @At("/list") +@At("/list") @Ok("beetl:/platform/zhghh5/dayofficework/healthCheckup/list/index.html") @SaCheckPermission("h5.healthCheckup.list") public void list() { @@ -81,125 +62,42 @@ public class H5HealthCheckupController { public Object pageData(PageForm pageForm, String status, String name) { - Sql sql = Sqls.create(""" - select - *, - (select count(*) from health_checkup_user_selection s where s.projectId=p.id and s.selectUserId=@userId) as selectCount - from - health_checkup_project p - $condition - """); - sql.setParam("userId", SecurityUtil.getUserId()); - Cnd cnd = Cnd.NEW(); - // 根据 status 参数筛选进行中或已结束的项目 - if ("ongoing".equals(status)) { - // 进行中的项目:结束时间大于等于当前时间 - cnd.and("p.choiceTimeEnd", ">=", DateUtil.now()); - } else if ("finished".equals(status)) { - // 已结束的项目:结束时间小于当前时间 - cnd.and("p.choiceTimeEnd", "<", DateUtil.now()); - } - cnd.and(new Static("(select count(*) from health_checkup_user where projectId=p.id and userId='%s')>0".formatted(SecurityUtil.getUserId()))); - - - // 只有当name参数不为空时才添加名称查询条件 - if (StrUtil.isNotBlank(name)) { - cnd.and("p.name", "like", "%" + name + "%"); - } - cnd.asc("selectCount"); - sql.setCondition(cnd); - return Result.success(healthCheckupProjectService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql)); + return applicationService.pageData(pageForm, status, name); } @At @SaCheckPermission(value = {"h5.healthCheckup.list", "h5.healthCheckup.mine"}, mode = SaMode.OR) - public Object mineData(PageForm pageForm, String status) { - Sql sql = Sqls.create(""" - SELECT - us.*, - p.name, - p.choiceTimeStart, - p.choiceTimeEnd, - p.cover, - sub.optionName - FROM - health_checkup_user_selection us - LEFT JOIN health_checkup_project p ON us.projectId = p.id - LEFT JOIN health_checkup_project_subject sub on sub.id=us.subjectId - $condition - """); - Cnd cnd = Cnd.NEW(); - cnd.and("us.selectUserId", "=", SecurityUtil.getUserId()); - // 根据 status 参数筛选进行中或已结束的项目 - if ("ongoing".equals(status)) { - // 进行中的项目:结束时间大于等于当前时间 - cnd.and("p.choiceTimeEnd", ">=", DateUtil.now()); - } else if ("finished".equals(status)) { - // 已结束的项目:结束时间小于当前时间 - cnd.and("p.choiceTimeEnd", "<", DateUtil.now()); - } - sql.setCondition(cnd); - Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); - return Result.success(pagination); + public Object mineData(PageForm pageForm, String status, String projectId) { + return applicationService.mineData(pageForm, status, projectId); } @At @Aop(TransAop.READ_COMMITTED) @SaCheckPermission(value = {"h5.healthCheckup.list", "h5.healthCheckup.mine"}, mode = SaMode.OR) - public Result doSubmit(@Param("userSelection") HealthCheckupUserSelection userSelection) { - BigDecimal money = userSelection.getMoney(); - if (money.compareTo(BigDecimal.ZERO) <= 0) { // 小于等于0 - return Result.error("金额必须大于0,当前医院没有符合您的选项!"); - } - if (StrUtil.isNotBlank(userSelection.getId())) { - baseService.dao().clearLinks(userSelection, "companionList"); - baseService.dao().delete(HealthCheckupUserSelection.class, userSelection.getId()); - userSelection.setId(null); - } - userSelection.setSelectUserId(SecurityUtil.getUserId()); - userSelection.setSelectTime(new Date()); - baseService.dao().insertWith(userSelection, "companionList"); - return Result.success("提交成功"); + public Result doSubmit(@Param("userSelection") HealthCheckupUserSelection userSelection, + @Param("baseInfo") HealthCheckupUser baseInfo) { + // userSelection 为医院选择JSON,baseInfo 为可选个人信息JSON;返回 Result 表示整体保存结果。 + return applicationService.submitWithBaseInfo(userSelection, baseInfo); } @At @Aop(TransAop.READ_COMMITTED) @SaCheckPermission(value = {"h5.healthCheckup.list", "h5.healthCheckup.mine"}, mode = SaMode.OR) public Result cancel(String id, String projectId) { - HealthCheckupProject checkupProject = baseService.dao().fetch(HealthCheckupProject.class, projectId); - if (DateUtil.compare(new Date(), checkupProject.getChoiceTimeEnd()) > 0) { - return Result.error("抱歉,当前时间已经不能取消"); - } - HealthCheckupUserSelection userSelection = baseService.dao().fetch(HealthCheckupUserSelection.class, id); - baseService.dao().clearLinks(userSelection, "companionList"); - baseService.dao().delete(HealthCheckupUserSelection.class, userSelection.getId()); - return Result.success("取消成功"); + return applicationService.cancel(id, projectId); } @At @SaCheckPermission(value = {"h5.healthCheckup.list", "h5.healthCheckup.mine"}, mode = SaMode.OR) public Object getCampus() { - return Result.success(baseService.dao().query(HealthCheckupCampus.class, Cnd.NEW().asc("campusCode"))); + return applicationService.getCampus(); } @At @SaCheckPermission(value = {"h5.healthCheckup.list", "h5.healthCheckup.mine"}, mode = SaMode.OR) public Object selectInfo(String projectId) { - HealthCheckupUserSelection userSelection = healthCheckupProjectService.dao().fetch(HealthCheckupUserSelection.class, - Cnd.where("projectId", "=", projectId).and("selectUserId", "=", SecurityUtil.getUserId())); - if (userSelection != null) { - baseService.dao().fetchLinks(userSelection, "companionList"); - NutMap nutMap = Lang.obj2map(userSelection, NutMap.class); - if (userSelection.getCompanionList().size() > 0) { - nutMap.put("isFamily", "是"); - } else { - nutMap.put("isFamily", "否"); - } - - return Result.success(nutMap); - } - return Result.success(); + return applicationService.selectInfo(projectId); } // @At @@ -217,25 +115,53 @@ public class H5HealthCheckupController { @At @SaCheckPermission(value = {"h5.healthCheckup.list", "h5.healthCheckup.mine"}, mode = SaMode.OR) - public Result getSubjectMoney(String id, String marriage) { - List list = healthCheckupProjectService.dao().query(HealthCheckupProjectSubjectMoney.class, Cnd.where(HealthCheckupProjectSubjectMoney::getSubjectId, "=", id)); - BigDecimal money = BigDecimal.valueOf(0.00); - String subjectMoneyId = ""; - for (HealthCheckupProjectSubjectMoney subject : list) { - // 是否满足条件 - Cnd cnd = Cnd.where("id", "=", SecurityUtil.getUserId()); - ConditionGroupUtil.applyConditionGroup(cnd, subject.getMatchCnd()); - int count = dao.count(View_user.class, cnd); - if (count > 0) { - money = subject.getMoney(); - subjectMoneyId = subject.getId(); - break; - } - } + public Result getSubjectMoney(String id, String marriage, Integer age) { + // id 为医院选项ID,age/marriage 为当前表单值;返回 data.money 和 data.subjectMoneyId,仅用于预览。 + return applicationService.getSubjectMoney(id, marriage, age); + } - return Result.success().addData(Map.of("money", money, "subjectMoneyId", subjectMoneyId)); + @At("/listParticulars") + @Ok("beetl:/platform/zhghh5/dayofficework/healthCheckup/listParticulars/index.html") + @SaCheckPermission("h5.healthCheckup.list") + @ApiOperation("体检项目报名详情页面") + public void listParticulars(){} + + @At("/userBaseMessage") + @Ok("beetl:/platform/zhghh5/dayofficework/healthCheckup/userBaseMessage/index.html") + @SaCheckPermission("h5.healthCheckup.list") + @ApiOperation("基础信息确认") + public void userBaseMessage(){} + + @At + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("h5.healthCheckup.list") + @ApiOperation("获取基础信息数据") + public Result findUserBaseMessageData(HealthCheckupUser checkupUser) { + return applicationService.findUserBaseMessageData(checkupUser); + } + + @At + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("h5.healthCheckup.list") + @ApiOperation("基础信息提交") + public Result doSubmitUserBaseMessage(HealthCheckupUser checkupUser) { + return applicationService.doSubmitUserBaseMessage(checkupUser); + } + + + @At + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("h5.healthCheckup.list") + @ApiOperation("上年度体检医院") + public Result findLastYearHospital(HealthCheckupUserSelection checkupUserSelection) { + return applicationService.findLastYearHospital(checkupUserSelection); + } + + @At("/physicalExaminationList") + @Ok("beetl:/platform/zhghh5/dayofficework/healthCheckup/physicalExaminationList/index.html") + @SaCheckPermission("h5.healthCheckup.list") + public void physicalExaminationList() { } } - diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupActualStatistics.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupActualStatistics.java new file mode 100644 index 00000000..caff0cd2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupActualStatistics.java @@ -0,0 +1,36 @@ +package com.budwk.app.zhgh.dayofficework.healthCheckup.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** 项目级实际体检统计,与教职工选择记录独立保存。 */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("health_checkup_actual_statistics") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@TableIndexes({@Index(name = "IDX_CHECKUP_ACTUAL_ITEM", fields = {"projectId", "subjectId"}, unique = true)}) +@Comment("实际体检人数统计") +public class HealthCheckupActualStatistics extends BaseModel { + @Name + @PrevInsert(uu32 = true) + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("主键") + private String id; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("体检项目ID") + private String projectId; + + @Column + @ColDefine(type = ColType.VARCHAR, width = 32) + @Comment("医院选项ID;__total__表示本次体检总人数") + private String subjectId; + + @Column + @Comment("人工录入的实际体检人数,非负整数") + private Integer actualCount; +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupFeedback.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupFeedback.java new file mode 100644 index 00000000..d0ab25df --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupFeedback.java @@ -0,0 +1,52 @@ +package com.budwk.app.zhgh.dayofficework.healthCheckup.model; +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.ColDefine; +import org.nutz.dao.entity.annotation.ColType; +import org.nutz.dao.entity.annotation.Column; +import org.nutz.dao.entity.annotation.Comment; +import org.nutz.dao.entity.annotation.Name; +import org.nutz.dao.entity.annotation.Table; +import org.nutz.dao.entity.annotation.TableMeta; +import org.nutz.dao.interceptor.annotation.PrevInsert; +import java.io.Serializable; +/** + * Health checkup feedback record. + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("health_checkup_feedback") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("health checkup feedback") +public class HealthCheckupFeedback extends BaseModel implements Serializable { + @Name + @Comment("id") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + @Column + @Comment("year") + @ColDefine(type = ColType.VARCHAR, width = 4) + private String year; + @Column + @Comment("project id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String projectId; + @Column + @Comment("project name") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String projectName; + @Column + @Comment("union id") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + @Column + @Comment("union name") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String unionName; + @Column + @Comment("feedback info") + @ColDefine(type = ColType.TEXT) + private String feedbackInfo; +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupProject.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupProject.java index e73b3c2d..92cc6de0 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupProject.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupProject.java @@ -2,10 +2,13 @@ package com.budwk.app.zhgh.dayofficework.healthCheckup.model; import cn.hutool.json.JSONObject; import com.budwk.app.base.model.BaseModel; +import com.budwk.app.sys.models.Sys_home_activity; +import com.budwk.app.sys.services.SysHomeConvert; import lombok.Data; import lombok.EqualsAndHashCode; import org.nutz.dao.entity.annotation.*; import org.nutz.dao.interceptor.annotation.PrevInsert; +import org.nutz.lang.Lang; import java.io.Serializable; import java.util.Date; @@ -22,7 +25,7 @@ import java.util.List; @Table("health_checkup_project") @TableMeta("{'mysql-charset':'utf8mb4'}") @Comment("体检项目表") -public class HealthCheckupProject extends BaseModel implements Serializable { +public class HealthCheckupProject extends BaseModel implements Serializable, SysHomeConvert { @Column @Name @@ -72,11 +75,33 @@ public class HealthCheckupProject extends BaseModel implements Serializable { @ColDefine(type = ColType.VARCHAR, width = 200) private String cover; - - - + @Column + @Comment("温馨提示") + @ColDefine(type = ColType.TEXT) + private String friendlyReminderText; @Many(field = "projectId") private List healthCheckupProjectSubjects; + @Column + @Comment("短信信息") + @ColDefine(type = ColType.TEXT) + private String smsMessage; + + @Override + public Sys_home_activity covertToSysHomeActivity() { + Sys_home_activity sysHomeActivity = new Sys_home_activity(); + sysHomeActivity.setId(this.getId()); + sysHomeActivity.setName(this.getName()); + sysHomeActivity.setCover(this.getCover()); + sysHomeActivity.setH5Url("/platform/healthCheckup/h5/list?id=" + this.getId()); + if (Lang.isNotEmpty(this.getChoiceTimeStart())) { + sysHomeActivity.setStartDate(this.getChoiceTimeStart()); + sysHomeActivity.setEndDate(this.getChoiceTimeEnd()); + } + sysHomeActivity.setEnable(true); + sysHomeActivity.setAllowUserSql("select userId from health_checkup_user where projectId = '" + this.getId() + "' and userId = @userId"); + sysHomeActivity.setClassPath(HealthCheckupProject.class.getName()); + return sysHomeActivity; + } } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupProjectSubjectMoney.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupProjectSubjectMoney.java index 75654488..e3d4d5bd 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupProjectSubjectMoney.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupProjectSubjectMoney.java @@ -62,4 +62,10 @@ public class HealthCheckupProjectSubjectMoney extends BaseModel implements Seria @Comment("选项排序") @ColDefine(type = ColType.VARCHAR, width = 50) private String sort; + + @Column + @Comment("序号") + @ColDefine(type = ColType.INT) + private Integer serialNumber; + } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupUser.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupUser.java index 0905efb2..b83cfc2f 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupUser.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/model/HealthCheckupUser.java @@ -1,6 +1,7 @@ package com.budwk.app.zhgh.dayofficework.healthCheckup.model; import com.budwk.app.base.model.BaseModel; +import com.budwk.app.sys.annotation.DataCenterColumn; import lombok.Data; import lombok.EqualsAndHashCode; import org.nutz.dao.entity.annotation.*; @@ -78,4 +79,58 @@ public class HealthCheckupUser extends BaseModel implements Serializable { @ColDefine(type = ColType.VARCHAR, width = 30) private String userState; + @Column + @Comment("手机号码") + @ColDefine(type = ColType.VARCHAR, width = 11) + private String phone; + + /** 本项目本人填写的年龄;未填写时从系统出生日期计算。 */ + @Column + @Comment("体检年龄") + @ColDefine(type = ColType.INT) + private Integer age; + + @Column + @Comment("身份证号") + @ColDefine(type = ColType.VARCHAR, width = 18) + private String card; + + @Column + @Comment("婚姻状况") + @ColDefine(type = ColType.VARCHAR, width = 20) + @DataCenterColumn(name = "婚姻状况", key = "hyztm", dict = "USER_MARRIAGE") + private String marriage; + + @Column + @Comment("教职工类别") + @ColDefine(type = ColType.VARCHAR) + private String personType; + + @Column + @Comment("确认状态(用户选择体检医院确认)") + // 确认状态保存单字符值,显式限定长度,避免自动迁移生成 CHAR(0) 导致默认值无效。 + @ColDefine(type = ColType.CHAR, width = 1) + @Default("0") + private String confirmStatus; + + @Column + @Comment("体检报告") + @ColDefine(type = ColType.TEXT) + private String medicalExamination; + + @Column + @Comment("是否自聘") + @ColDefine(type = ColType.VARCHAR, width = 10) + @Default("否") + private String isEmployed; + + @Column + @Comment("备注") + @ColDefine(type = ColType.TEXT) + private String bz; + + @Column + @Comment("是否确认") + @ColDefine(type = ColType.BOOLEAN) + private Boolean isAudit; } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/param/HealthCheckupFilterUserPageForm.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/param/HealthCheckupFilterUserPageForm.java new file mode 100644 index 00000000..b7cf2630 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/param/HealthCheckupFilterUserPageForm.java @@ -0,0 +1,61 @@ +package com.budwk.app.zhgh.dayofficework.healthCheckup.param; + +import com.budwk.app.base.param.PageForm; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.Date; + +@EqualsAndHashCode(callSuper = true) +@Data +@ApiModel("用户生成体检名单分页查询参数") +public class HealthCheckupFilterUserPageForm extends PageForm { + + @ApiModelProperty("体检项目id") + private String projectId; + + @ApiModelProperty("姓名") + private String userName; + + @ApiModelProperty("工号") + private String loginName; + + @ApiModelProperty("性别") + private String sex; + + @ApiModelProperty("出生日期") + private Date birthday; + + @ApiModelProperty("出生月份") + private String[] birthMonths; + + @ApiModelProperty("工会id") + private String unionId; + + @ApiModelProperty("工会名称") + private String unionName; + + @ApiModelProperty("单位id") + private String[] unitIds; + + @ApiModelProperty("单位名称") + private String unitName; + + @ApiModelProperty("人员类型") + private String[] personTypes; + + @ApiModelProperty("聘用方式") + private String[] preparedBys; + + @ApiModelProperty("在职状态") + private String[] userStates; + + @ApiModelProperty("是否会员") + private Boolean isMember; + + @ApiModelProperty("是否缴费会员") + private Boolean memberFeePaid; + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/H5HealthCheckupApplicationService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/H5HealthCheckupApplicationService.java new file mode 100644 index 00000000..eca0e3ec --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/H5HealthCheckupApplicationService.java @@ -0,0 +1,396 @@ +package com.budwk.app.zhgh.dayofficework.healthCheckup.service; + + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.base.utils.ConditionGroupUtil; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.sys.services.SysUserService; +import org.nutz.dao.Chain; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.*; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupProjectService; +import org.apache.commons.lang3.StringUtils; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.dao.util.cri.Static; +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.util.NutMap; +import java.math.BigDecimal; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** 体检接口业务服务;HTTP 路由和权限校验保留在 controller。 */ +@IocBean +public class H5HealthCheckupApplicationService { + @Inject + private Dao dao; + @Inject + private BaseService baseService; + @Inject + private HealthCheckupProjectService healthCheckupProjectService; + @Inject + private SysUserService sysUserService; + + /** + * 获取项目列表;业务筛选、数据读写和结果组装在本服务内完成。 + * @param pageForm 分页、搜索及排序参数 + * @param status 进行中 ongoing 或已结束 finished + * @param name 体检项目名称筛选值 + * @return Object;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Object pageData(PageForm pageForm, + String status, + String name) { + Sql sql = Sqls.create(""" + select + *, + (select count(*) from health_checkup_user_selection s where s.projectId=p.id and s.selectUserId=@userId) as selectCount + from + health_checkup_project p + $condition + """); + sql.setParam("userId", SecurityUtil.getUserId()); + Cnd cnd = Cnd.NEW(); + // 根据 status 参数筛选进行中或已结束的项目 + if ("ongoing".equals(status)) { + // 进行中的项目:结束时间大于等于当前时间 + SqlExpressionGroup group = Cnd.NEW().where(); + group.and("p.choiceTimeStart", "<=", DateUtil.now()); + group.and("p.choiceTimeEnd", ">=", DateUtil.now()); + cnd.and(group); + } else if ("finished".equals(status)) { + // 已结束的项目:结束时间小于当前时间 + cnd.and("p.choiceTimeEnd", "<", DateUtil.now()); + } + cnd.and(new Static("(select count(*) from health_checkup_user where projectId=p.id and userId='%s')>0".formatted(SecurityUtil.getUserId()))); + + + // 只有当name参数不为空时才添加名称查询条件 + if (StrUtil.isNotBlank(name)) { + cnd.and("p.name", "like", "%" + name + "%"); + } + cnd.asc("selectCount"); + sql.setCondition(cnd); + return Result.success(healthCheckupProjectService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql)); + } + + /** + * 读取体检业务数据;业务筛选、数据读写和结果组装在本服务内完成。 + * @param pageForm 分页、搜索及排序参数 + * @param status 进行中 ongoing 或已结束 finished + * @param projectId 当前体检项目主键 + * @return Object;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Object mineData(PageForm pageForm, String status, String projectId) { + Sql sql = Sqls.create(""" + SELECT + us.*, + p.name, + p.choiceTimeStart, + p.choiceTimeEnd, + p.cover, + sub.optionName + FROM + health_checkup_user_selection us + LEFT JOIN health_checkup_project p ON us.projectId = p.id + LEFT JOIN health_checkup_project_subject sub on sub.id=us.subjectId + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("us.selectUserId", "=", SecurityUtil.getUserId()); + cnd.andEX("us.projectId", "=", projectId); + cnd.orderBy("us.selectTime","desc"); + // 根据 status 参数筛选进行中或已结束的项目 +// if ("ongoing".equals(status)) { +// // 进行中的项目:结束时间大于等于当前时间 +// cnd.and("p.choiceTimeEnd", ">=", DateUtil.now()); +// } else if ("finished".equals(status)) { +// // 已结束的项目:结束时间小于当前时间 +// cnd.and("p.choiceTimeEnd", "<", DateUtil.now()); +// } + sql.setCondition(cnd); + Pagination pagination = baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + /** + * 提交本人的体检医院及家属选择;业务筛选、数据读写和结果组装在本服务内完成。 + * @param userSelection 本人选择的医院、套餐及家属信息 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doSubmit(HealthCheckupUserSelection userSelection) { + // 手机端只允许操作本人在当前项目的选择;时间窗口和金额不能仅依赖页面校验。 + HealthCheckupProject project = dao.fetch(HealthCheckupProject.class, userSelection.getProjectId()); + Date now = new Date(); + if (project == null || project.getChoiceTimeStart() == null || project.getChoiceTimeEnd() == null + || now.before(project.getChoiceTimeStart()) || now.after(project.getChoiceTimeEnd())) { + return Result.error("当前项目不在报名时间内"); + } + HealthCheckupProjectSubject selectedSubject = dao.fetch(HealthCheckupProjectSubject.class, userSelection.getSubjectId()); + if (selectedSubject == null || !project.getId().equals(selectedSubject.getProjectId())) { + return Result.error("请选择当前项目的医院"); + } + BigDecimal money = BigDecimal.ZERO; + for (HealthCheckupProjectSubjectMoney option : dao.query(HealthCheckupProjectSubjectMoney.class, + Cnd.where("subjectId", "=", selectedSubject.getId()).asc("serialNumber"))) { + Cnd eligible = Cnd.where("id", "=", SecurityUtil.getUserId()); + ConditionGroupUtil.applyConditionGroup(eligible, option.getMatchCnd()); + if (matchesSubject(userSelection.getProjectId(), option)) { + money = option.getMoney(); + userSelection.setSubjectMoneyId(option.getId()); + userSelection.setMoney(money); + break; + } + } + if (money == null || money.compareTo(BigDecimal.ZERO) <= 0) { // 小于等于0 + return Result.error("金额必须大于0,当前医院没有符合您的选项!"); + } + HealthCheckupUser healthCheckupUser = baseService.dao().fetch(HealthCheckupUser.class, + Cnd.NEW().and("projectId", "=", userSelection.getProjectId()) + .and("userId", "=", SecurityUtil.getUserId())); + if (ObjectUtil.isEmpty(healthCheckupUser)) { + return Result.error("请确认您的身份信息是否无误!"); + } else { + if (StringUtils.isBlank(healthCheckupUser.getPhone())) { + return Result.error("基础信息中,\"手机号\" 不能为空!"); + } else if (StringUtils.isBlank(healthCheckupUser.getCard())) { + return Result.error("基础信息中,\"身份证号码\" 不能为空!"); + } + } + HealthCheckupUserSelection existing = dao.fetch(HealthCheckupUserSelection.class, + Cnd.where("projectId", "=", project.getId()).and("selectUserId", "=", SecurityUtil.getUserId())); + if (StrUtil.isNotBlank(userSelection.getId()) && (existing == null || !existing.getId().equals(userSelection.getId()))) { + return Result.error("选择记录不属于当前用户"); + } + userSelection.setId(existing == null ? null : existing.getId()); + if (StrUtil.isNotBlank(userSelection.getId())) { + baseService.dao().clearLinks(userSelection, "companionList"); + baseService.dao().delete(HealthCheckupUserSelection.class, userSelection.getId()); + userSelection.setId(null); + } + userSelection.setSelectUserId(SecurityUtil.getUserId()); + userSelection.setSelectTime(new Date()); + baseService.dao().insertWith(userSelection, "companionList"); + return Result.success("提交成功"); + } + + /** + * 在同一事务内保存个人信息、同步档案并提交医院选择。 + * @param userSelection 当前项目及医院、家属信息 + * @param baseInfo 可选个人信息,仅 age、phone、card、marriage 生效;项目归属取选择记录 + * @return Result,code=0 表示全部保存成功;失败抛异常回滚,避免部分保存 + */ + @Aop(TransAop.READ_COMMITTED) + public Result submitWithBaseInfo(HealthCheckupUserSelection userSelection, HealthCheckupUser baseInfo) { + if (baseInfo != null) { + baseInfo.setProjectId(userSelection.getProjectId()); + Result saved = doSubmitUserBaseMessage(baseInfo); + if (!saved.isSuccess()) throw new com.budwk.app.base.exception.BaseException(saved.getMsg()); + } + Result submitted = doSubmit(userSelection); + if (!submitted.isSuccess()) throw new com.budwk.app.base.exception.BaseException(submitted.getMsg()); + return submitted; + } + + /** + * 取消本人当前项目的体检选择;业务筛选、数据读写和结果组装在本服务内完成。 + * @param id 当前业务记录主键 + * @param projectId 当前体检项目主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result cancel(String id, String projectId) { + HealthCheckupProject checkupProject = baseService.dao().fetch(HealthCheckupProject.class, projectId); + if (checkupProject == null || checkupProject.getChoiceTimeEnd() == null || DateUtil.compare(new Date(), checkupProject.getChoiceTimeEnd()) > 0) { + return Result.error("抱歉,当前时间已经不能取消"); + } + HealthCheckupUserSelection userSelection = baseService.dao().fetch(HealthCheckupUserSelection.class, id); + if (userSelection == null || !SecurityUtil.getUserId().equals(userSelection.getSelectUserId()) + || !projectId.equals(userSelection.getProjectId())) { + return Result.error("选择记录不存在或不属于当前用户"); + } + baseService.dao().clearLinks(userSelection, "companionList"); + baseService.dao().delete(HealthCheckupUserSelection.class, userSelection.getId()); + return Result.success("取消成功"); + } + + /** + * 读取可选体检院区;业务筛选、数据读写和结果组装在本服务内完成。 + * @return Object;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Object getCampus() { + return Result.success(baseService.dao().query(HealthCheckupCampus.class, Cnd.NEW().asc("campusCode"))); + } + + /** + * 读取本人当前项目的选择记录和家属明细;业务筛选、数据读写和结果组装在本服务内完成。 + * @param projectId 当前体检项目主键 + * @return Object;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Object selectInfo(String projectId) { + HealthCheckupUserSelection userSelection = healthCheckupProjectService.dao().fetch(HealthCheckupUserSelection.class, + Cnd.where("projectId", "=", projectId).and("selectUserId", "=", SecurityUtil.getUserId())); + if (userSelection != null) { + baseService.dao().fetchLinks(userSelection, "companionList"); + NutMap nutMap = Lang.obj2map(userSelection, NutMap.class); + if (userSelection.getCompanionList().size() > 0) { + nutMap.put("isFamily", "是"); + } else { + nutMap.put("isFamily", "否"); + } + + return Result.success(nutMap); + } + return Result.success(); + } + + /** + * 按本人档案条件匹配医院套餐额度;业务筛选、数据读写和结果组装在本服务内完成。 + * @param id 当前业务记录主键 + * @param marriage 当前表单婚姻状态;为空时使用已保存值 + * @param age 当前表单年龄;为空时使用已保存值,仅预览不写入数据库 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result getSubjectMoney(String id, String marriage, Integer age) { + if (age != null && (age < 0 || age > 120)) return Result.error("请输入0至120的整数年龄"); + HealthCheckupProjectSubject hospital = dao.fetch(HealthCheckupProjectSubject.class, id); + if (hospital == null) return Result.error("请选择体检医院"); + List list = healthCheckupProjectService.dao().query(HealthCheckupProjectSubjectMoney.class, Cnd.where(HealthCheckupProjectSubjectMoney::getSubjectId, "=", id).asc("serialNumber")); + BigDecimal money = BigDecimal.valueOf(0.00); + String subjectMoneyId = ""; + for (HealthCheckupProjectSubjectMoney subject : list) { + // 是否满足条件 + Cnd cnd = Cnd.where("id", "=", SecurityUtil.getUserId()); + ConditionGroupUtil.applyConditionGroup(cnd, subject.getMatchCnd()); + int count = matchesSubject(hospital.getProjectId(), subject, age, marriage) ? 1 : 0; + if (count > 0) { + money = subject.getMoney(); + subjectMoneyId = subject.getId(); + break; + } + } + + return Result.success().addData(Map.of("money", money, "subjectMoneyId", subjectMoneyId)); + } + + /** + * 获取基础信息数据;业务筛选、数据读写和结果组装在本服务内完成。 + * @param checkupUser 体检人员基本信息 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result findUserBaseMessageData(HealthCheckupUser checkupUser) { + checkupUser.setUserId(SecurityUtil.getUserId()); + if(StringUtils.isNotBlank(checkupUser.getProjectId()) && StringUtils.isNotBlank(checkupUser.getUserId())){ + Sql sql = Sqls.create(""" + select cu.id,cu.projectId,cu.userId,cu.userName,cu.sex, + cu.loginName,cu.phone,cu.card,cu.marriage, + cu.personType, COALESCE(cu.age, TIMESTAMPDIFF(YEAR,u.birthday,CURDATE())) AS age + from health_checkup_user cu + left join sys_user u on cu.userId=u.id + $condition + """); + Cnd cnd = Cnd.NEW().and("cu.projectId", "=", checkupUser.getProjectId()) + .and("cu.userId", "=", checkupUser.getUserId()); + sql.setCondition(cnd); + NutMap nutMap = baseService.fetchMap(sql); + return Result.success(nutMap); + } + return Result.success(); + } + + /** + * 保存本人体检信息并同步系统档案;两处更新由同一事务提交。 + * @param checkupUser projectId 为当前项目;age 为手填体检年龄,phone 为手机号, + * card 为身份证号,marriage 为已婚或未婚;其余客户端字段不用于更新 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doSubmitUserBaseMessage(HealthCheckupUser checkupUser) { + // 以登录身份定位本人记录,不使用客户端传入的用户ID或记录ID。 + HealthCheckupUser own = dao.fetch(HealthCheckupUser.class, + Cnd.where("projectId", "=", checkupUser.getProjectId()).and("userId", "=", SecurityUtil.getUserId())); + if (own == null) return Result.error("当前项目中没有您的体检记录"); + // 仅接受本人当前项目的四个可编辑字段,禁止覆盖姓名、性别、人员类别和归属。 + if (checkupUser.getAge() == null || checkupUser.getAge() < 0 || checkupUser.getAge() > 120) + return Result.error("请输入0至120的整数年龄"); + String phone = StrUtil.trim(checkupUser.getPhone()); + String card = StrUtil.upperFirst(StrUtil.trim(checkupUser.getCard())); + if (phone == null || !phone.matches("1[0-9]{10}")) return Result.error("请输入正确的手机号码"); + if (card == null || !cn.hutool.core.util.IdcardUtil.isValidCard(card)) return Result.error("请输入正确的身份证号"); + if (!"已婚".equals(checkupUser.getMarriage()) && !"未婚".equals(checkupUser.getMarriage())) + return Result.error("请选择婚姻状态"); + if (sysUserService.fetch(SecurityUtil.getUserId()) == null) + return Result.error("当前用户档案不存在"); + own.setAge(checkupUser.getAge()); + own.setPhone(phone); + own.setCard(card.toUpperCase(java.util.Locale.ROOT)); + own.setMarriage(checkupUser.getMarriage()); + own.setConfirmStatus("1"); + dao.update(own); + // 系统年龄由出生日期计算,使用身份证解析日期,不以手填年龄反推生日。 + // 仅同步允许修改的档案列,保留姓名、性别、人员类型及其他系统字段。 + sysUserService.update(Chain.make("mobile", phone) + .add("idCard", own.getCard()) + .add("marriage", own.getMarriage()) + .add("birthday", cn.hutool.core.util.IdcardUtil.getBirthDate(own.getCard())), + Cnd.where("id", "=", SecurityUtil.getUserId())); + sysUserService.deleteCache(SecurityUtil.getUserId()); + return Result.success(); + } + + /** + * 上年度体检医院;业务筛选、数据读写和结果组装在本服务内完成。 + * @param checkupUserSelection 查询上一年度医院的人员条件 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result findLastYearHospital(HealthCheckupUserSelection checkupUserSelection) { + checkupUserSelection.setSelectUserId(SecurityUtil.getUserId()); + return Result.success("成功",healthCheckupProjectService.findLastYearHospital(checkupUserSelection)); + } + /** + * 用当前项目本人信息匹配套餐条件,未填写年龄时沿用系统出生日期。 + * @param projectId 体检项目ID + * @param option 当前医院套餐金额选项及条件组 + * @return true 表示本人满足该选项条件;名单不存在时为 false + */ + private boolean matchesSubject(String projectId, HealthCheckupProjectSubjectMoney option) { + return matchesSubject(projectId, option, null, null); + } + + /** 用表单年龄和婚姻状态预览匹配;仅这两个字段可覆盖,其余信息取本人档案。 */ + private boolean matchesSubject(String projectId, HealthCheckupProjectSubjectMoney option, Integer age, String marriage) { + Sql sql = Sqls.create(""" + SELECT COUNT(*) AS matched FROM ( + SELECT u.id, cu.userName AS username, cu.loginName AS loginname, cu.sex, + COALESCE(@age,cu.age,TIMESTAMPDIFF(YEAR,u.birthday,CURDATE())) AS age, + COALESCE(@marriage,cu.marriage) AS marriage, u.userState, u.preparedBy, cu.personType + FROM health_checkup_user cu JOIN vw_user u ON u.id=cu.userId + WHERE cu.projectId=@projectId AND cu.userId=@userId + ) candidate $condition + """); + sql.setParam("age", age); + sql.setParam("marriage", StrUtil.blankToDefault(marriage, null)); + sql.setParam("projectId", projectId); + sql.setParam("userId", SecurityUtil.getUserId()); + Cnd condition = Cnd.NEW(); + ConditionGroupUtil.applyConditionGroup(condition, option.getMatchCnd()); + sql.setCondition(condition); + return baseService.fetchMap(sql).getInt("matched") > 0; + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupCampusApplicationService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupCampusApplicationService.java new file mode 100644 index 00000000..625f40f1 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupCampusApplicationService.java @@ -0,0 +1,108 @@ +package com.budwk.app.zhgh.dayofficework.healthCheckup.service; + + +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupCampus; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import java.util.List; + +/** 体检接口业务服务;HTTP 路由和权限校验保留在 controller。 */ +@IocBean +public class HealthCheckupCampusApplicationService { + @Inject + private BaseService baseService; + + /** + * 分页查询;业务筛选、数据读写和结果组装在本服务内完成。 + * @param pageForm 分页、搜索及排序参数 + * @param campusName 院区名称筛选值 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result pageData(PageForm pageForm, String campusName) { + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create("select * from health_checkup_campus $condition"); + cnd.and(Cnd.likeEX("campusName", campusName)); + cnd.asc("campusCode"); + sql.setCondition(cnd); + return Result.success(baseService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql)); + } + + /** + * 添加院区;业务筛选、数据读写和结果组装在本服务内完成。 + * @param campus 体检院区主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doAdd(HealthCheckupCampus campus) { + try { + int count = baseService.dao().count(HealthCheckupCampus.class, Cnd.where(HealthCheckupCampus::getCampusCode, "=", campus.getCampusCode())); + if (count > 0) { + return Result.error("编码重复"); + } + baseService.dao().insert(campus); + return Result.success(); + } catch (Exception e) { + e.printStackTrace(); + return Result.error(); + } + + } + + /** + * 编辑院区;业务筛选、数据读写和结果组装在本服务内完成。 + * @param campus 体检院区主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doEdit(HealthCheckupCampus campus) { + try { + int count = baseService.dao().count(HealthCheckupCampus.class, + Cnd.where(HealthCheckupCampus::getCampusCode, "=", campus.getCampusCode()) + .and(HealthCheckupCampus::getId, "!=", campus.getId())); + if (count > 0) { + return Result.error("编码重复"); + } + baseService.dao().update(campus); + return Result.success(); + } catch (Exception e) { + e.printStackTrace(); + return Result.error(); + } + } + + /** + * 编辑院区;业务筛选、数据读写和结果组装在本服务内完成。 + * @param id 当前业务记录主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doDelete(String id) { + try { + baseService.dao().clear(HealthCheckupCampus.class, Cnd.where(HealthCheckupCampus::getId, "=", id)); + return Result.success(); + } catch (Exception e) { + e.printStackTrace(); + return Result.error(); + } + } + + /** + * 查询所有院区;业务筛选、数据读写和结果组装在本服务内完成。 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result queryCampus() { + try { + List campusList = baseService.dao().query(HealthCheckupCampus.class, Cnd.NEW().asc("campusCode")); + return Result.success(campusList); + } catch (Exception e) { + e.printStackTrace(); + return Result.error(); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupFeedbackService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupFeedbackService.java new file mode 100644 index 00000000..d81b1dca --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupFeedbackService.java @@ -0,0 +1,27 @@ +package com.budwk.app.zhgh.dayofficework.healthCheckup.service; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupFeedback; +import org.nutz.lang.util.NutMap; +import java.util.List; +public interface HealthCheckupFeedbackService extends BaseService { + /** + * Query feedback records by the selected filters on the list page. + */ + List listFeedback(String year, String projectId, String unionId); + /** + * Save a feedback record and bind it to the selected year, project and union. + */ + NutMap saveFeedback(String year, String projectId, String unionId, String feedbackInfo); + + /** + * 删除单条体检反馈。 + */ + NutMap deleteFeedback(String id); + NutMap deleteFeedbackBatch(String[] ids); + + /** + * 查询问题反馈列表页数据。 + */ + Pagination listFeedbackPage(Integer pageNumber, Integer pageSize, String year, String projectId, String unionId); +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupListApplicationService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupListApplicationService.java new file mode 100644 index 00000000..061977b2 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupListApplicationService.java @@ -0,0 +1,835 @@ +package com.budwk.app.zhgh.dayofficework.healthCheckup.service; + + +import cn.afterturn.easypoi.excel.ExcelExportUtil; +import cn.afterturn.easypoi.excel.entity.ExportParams; +import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; +import cn.afterturn.easypoi.excel.entity.params.ExcelExportEntity; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.model.ExcelImportRes; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.base.utils.ConditionGroupUtil; +import com.budwk.app.base.utils.easyexcel.EasyExcelUtil; +import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.*; +import com.budwk.app.zhgh.dayofficework.healthCheckup.param.HealthCheckupFilterUserPageForm; +import java.util.Set; +import java.util.HashSet; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupFeedbackService; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupProjectService; +import com.budwk.app.zhgh.dayofficework.healthCheckup.template.HealthCheckupImportTemp; +import org.apache.commons.lang3.StringUtils; +import org.apache.poi.ss.formula.functions.T; +import org.apache.poi.ss.usermodel.Workbook; +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.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +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.lang.util.NutMap; +import org.nutz.mvc.upload.TempFile; +import javax.servlet.http.HttpServletResponse; +import java.math.BigDecimal; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +/** 体检接口业务服务;HTTP 路由和权限校验保留在 controller。 */ +@IocBean +public class HealthCheckupListApplicationService { + @Inject + private Dao dao; + @Inject + private HealthCheckupProjectService healthCheckupProjectService; + @Inject + private HealthCheckupFeedbackService healthCheckupFeedbackService; + + /** + * 查询尚未加入当前体检项目的人员;查询与提交共用筛选条件。 + * @param pageForm 项目 ID、姓名/工号、人员属性、工会单位和分页排序参数,空筛选项表示不限 + * @return Result,code=0 时 data.list 为人员列表,data.totalCount 为匹配总人数 + */ + public Result candidatePageData(HealthCheckupFilterUserPageForm pageForm) { + Result invalid = validateAddUsers(pageForm); + if (invalid != null) return invalid; + return Result.success(healthCheckupProjectService.listPageMap( + pageForm.getPageNumber(), pageForm.getPageSize(), candidateSql(pageForm))); + } + + /** + * 将全部匹配人员加入体检名单,并补齐项目参与范围;两个写入操作必须一起提交。 + * @param pageForm 项目 ID 和人员筛选条件,分页参数仅用于预览,不限制实际添加数量 + * @return Result,code=0 表示成功,msg 返回实际新增人数;已有名单和范围均不重复插入 + */ + @Aop(TransAop.READ_COMMITTED) + public Result addUsers(HealthCheckupFilterUserPageForm pageForm) { + Result invalid = validateAddUsers(pageForm); + if (invalid != null) return invalid; + HealthCheckupProject project = dao.fetch(HealthCheckupProject.class, pageForm.getProjectId()); + // 同一范围的添加请求锁定相同范围记录,避免并发重复写入名单及范围。 + ActivityUserScope group = dao.fetch(ActivityUserScope.class, + Cnd.where("groupId", "=", project.getActivityGroupId()).asc("id")); + if (group == null) return Result.error("参与人员范围已变更,请刷新后重试"); + List locked = healthCheckupProjectService.listMap(Sqls.create( + "select id from activity_user_scope where id=@id for update").setParam("id", group.getId())); + if (locked.isEmpty()) return Result.error("参与人员范围已变更,请刷新后重试"); + List users = healthCheckupProjectService.listMap(candidateSql(pageForm)); + Set scopeUserIds = dao.query(ActivityUserScope.class, + Cnd.where("groupId", "=", project.getActivityGroupId())).stream() + .map(ActivityUserScope::getUserId).collect(Collectors.toSet()); + Set added = new HashSet<>(); + for (NutMap user : users) { + String userId = user.getString("id"); + if (!added.add(userId)) continue; + HealthCheckupUser entry = new HealthCheckupUser(); + entry.setProjectId(project.getId()); + entry.setUserId(userId); + entry.setLoginName(user.getString("loginname")); + entry.setUserName(user.getString("username")); + entry.setSex(user.getString("sex")); + entry.setPhone(user.getString("mobile")); + entry.setCard(user.getString("idCard")); + entry.setMarriage(user.getString("marriage")); + entry.setPersonType(user.getString("personType")); + entry.setUserState(user.getString("userState")); + entry.setUnionId(user.getString("unionId")); + entry.setUnionName(user.getString("unionName")); + entry.setUnitId(user.getString("unitId")); + entry.setUnitName(user.getString("unitName")); + dao.insert(entry); + // 范围已有人时只加名单;缺失时补入,避免后续更新名单将新增人员移除。 + if (scopeUserIds.add(userId)) { + ActivityUserScope scope = new ActivityUserScope(); + scope.setGroupId(group.getGroupId()); + scope.setGroupName(group.getGroupName()); + scope.setUserId(userId); + scope.setCreator(SecurityUtil.getUserId()); + dao.insert(scope); + } + } + return Result.success("成功添加" + added.size() + "人,参与人员范围已同步"); + } + + /** 校验导入名单同等角色、目标项目和实际存在的参与范围;返回 null 表示通过。 */ + private Result validateAddUsers(HealthCheckupFilterUserPageForm pageForm) { + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name(), + RoleConstant.SCHOOL_UNION_CHAIRMAN.name())) { + return Result.error("您没有【添加人员】的权限"); + } + if (pageForm == null || StrUtil.isBlank(pageForm.getProjectId())) return Result.error("请先选择体检项目"); + HealthCheckupProject project = dao.fetch(HealthCheckupProject.class, pageForm.getProjectId()); + if (project == null) return Result.error("体检项目不存在"); + if (project.getActivityGroupId() == null || dao.count(ActivityUserScope.class, + Cnd.where("groupId", "=", project.getActivityGroupId()).and("groupName", "is not", null)) == 0) { + return Result.error("项目未关联有效参与人员范围,请先设置参与人员范围"); + } + return null; + } + + /** 统一预览与提交的候选条件;项目限定和名单排除不能随可选筛选项省略。 */ + private Sql candidateSql(HealthCheckupFilterUserPageForm form) { + Sql sql = Sqls.create(""" + select u.* from vw_user u + left join sys_user su on su.id=u.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("u.id", "not in", Sqls.create( + "select userId from health_checkup_user where projectId=@projectId and userId is not null") + .setParam("projectId", form.getProjectId())); + if (StrUtil.isNotBlank(form.getSearchKeyword())) { + SqlExpressionGroup search = new SqlExpressionGroup(); + search.orLike("u.username", form.getSearchKeyword()); + search.orLike("u.loginname", form.getSearchKeyword()); + cnd.and(search); + } + cnd.andEX("u.sex", "=", form.getSex()); + cnd.andEX("u.birthday", "=", form.getBirthday()); + cnd.andEX("MONTH(u.birthday)", "in", form.getBirthMonths()); + cnd.andEX("u.unionId", "=", form.getUnionId()); + cnd.andEX("u.unitId", "in", form.getUnitIds()); + cnd.andEX("u.personType", "in", form.getPersonTypes()); + cnd.andEX("u.preparedBy", "in", form.getPreparedBys()); + cnd.andEX("u.userState", "in", form.getUserStates()); + cnd.andEX("u.member", "=", form.getIsMember()); + cnd.andEX("IFNULL(su.memberFeePaid, 0)", "=", form.getMemberFeePaid()); + // 排序字段仅接受弹窗展示列,禁止将客户端任意表达式拼入 SQL。 + Set sortFields = Set.of("loginname", "username", "sex", "birthday", "personType", + "preparedBy", "userState", "unionName", "unitName"); + if (form.getPageOrderName() != null && sortFields.contains(form.getPageOrderName())) { + cnd.orderBy("u." + form.getPageOrderName(), "ascending".equals(form.getPageOrderBy()) ? "ASC" : "DESC"); + } else { + cnd.asc("u.unionCode").asc("u.unitCode"); + } + cnd.asc("u.id"); + sql.setCondition(cnd); + return sql; + } + + /** + * 分页查询;业务筛选、数据读写和结果组装在本服务内完成。 + * @param pageForm 分页、搜索及排序参数 + * @param projectId 当前体检项目主键 + * @param subjectId 体检医院选项主键 + * @param unionId 所属分工会主键,可空时按接口范围处理 + * @param unitId 所属单位主键筛选值 + * @param physicalExaminationStatus 1 已选、0 未选、2 全部 + * @param isAudit 确认状态:1 已确认,0 未确认 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result pageData(PageForm pageForm, String projectId, String subjectId, + String unionId, String unitId, String physicalExaminationStatus, String isAudit) { + List confirms = dao.query(HealthCheckupUnionConfirm.class, Cnd.where("projectId", "=", projectId)); + + HealthCheckupProject project = healthCheckupProjectService.findOne(projectId); + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + SELECT + hcu.id AS headId, + hcu.userId AS id, + hcu.loginName, + hcu.userName, + hcu.sex, + hcu.unionId, + hcu.unionName, + hcu.unitName, + hcus.selectTime, + hcus.campus, + hcus.subjectId, + hcu.bz, + hcu.isAudit, + hcus.receiveAddress, + ca.campusName + FROM + health_checkup_user hcu + LEFT JOIN health_checkup_user_selection hcus ON hcu.userId = hcus.selectUserId + AND hcus.projectId=@projectId + LEFT JOIN health_checkup_campus ca on ca.id=hcus.campus + $condition + """).setParam("projectId", projectId); + sql.setCondition(cnd); + cnd.andEX("hcu.projectId", "=", projectId); + cnd.andEX("hcu.unionId", "=", unionId); + cnd.andEX("hcu.unitId", "=", unitId); + cnd.andEX("hcus.subjectId", "=", subjectId); + if(StringUtils.isNotBlank(isAudit)){ + if(isAudit.equals("1")){ + cnd.and("hcu.isAudit", "=", "1"); + } else if(isAudit.equals("0")){ + SqlExpressionGroup group = Cnd.NEW().where(); + group.andEX("hcu.isAudit", "=", "0"); + group.orIsNull("hcu.isAudit"); + cnd.and(group); + } + } + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.andEX("hcu.unionId", "=", SecurityUtil.getUnionId()); + } + //体检状态 + if(StringUtils.isNotBlank(physicalExaminationStatus) && !physicalExaminationStatus.equals("2")){ + if(physicalExaminationStatus.equals("1")) cnd.where().andNotIsNull("hcus.selectTime"); + if(physicalExaminationStatus.equals("0")) cnd.where().andIsNull("hcus.selectTime"); + } + + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup group = new SqlExpressionGroup(); + group.orLike("hcu.userName", pageForm.getSearchKeyword()); + group.orLike("hcu.loginName", pageForm.getSearchKeyword()); + cnd.and(group); + } + cnd.groupBy("hcu.userId"); + if (StrUtil.isNotBlank(pageForm.getPageOrderName()) && Strings.isNotBlank(pageForm.getPageOrderBy())) { + cnd.orderBy(pageForm.getPageOrderName(), "ascending".equalsIgnoreCase(pageForm.getPageOrderBy()) ? "ASC" : "DESC"); + } else { + cnd.desc("hcus.selectTime").asc("hcu.unitId"); + } + cnd.desc("hcu.id"); + Pagination pagination = healthCheckupProjectService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + List paginationList = pagination.getList(); + + paginationList.forEach(v -> { + if (StrUtil.isNotBlank(v.getString("subjectId"))) { + List subjects = project.getHealthCheckupProjectSubjects(); + HealthCheckupProjectSubject subject = subjects.stream().filter(s -> s.getId().equals(v.getString("subjectId"))).findFirst().orElse(null); + v.setv("optionName", subject.getOptionName()); + } + + if (StrUtil.isNotBlank(v.getString("unionId")) && ObjectUtil.isNotEmpty(v.getBoolean("isAudit")) && v.getBoolean("isAudit")) { + HealthCheckupUnionConfirm confirm = confirms.stream() + .filter(o -> o.getUnionId().equals(v.getString("unionId"))) + .findFirst() + .orElse(null); +// v.setv("isAudit", confirm != null ? confirm.getIsAudit() : ""); + v.setv("auditTime", confirm != null ? confirm.getAuditTime() : ""); + } + }); + return Result.success(pagination); + } + + /** + * 体检名单确认;业务筛选、数据读写和结果组装在本服务内完成。 + * @param projectId 当前体检项目主键 + * @param unionId 所属分工会主键,可空时按接口范围处理 + * @param flag 确认或取消、已选或未选的业务标志 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doAuditUser(String projectId, + String unionId, + Boolean flag) { + if (StrUtil.isBlank(unionId)) { + unionId = SecurityUtil.getUnionId(); + } + if (flag) { + dao.update(HealthCheckupUnionConfirm.class, Chain.make("isAudit", true) + .add("auditTime", DateUtil.date()) + .add("auditUser", SecurityUtil.getUserId()), + Cnd.where("projectId", "=", projectId).and("unionId", "=", unionId)); + + dao.update(HealthCheckupUser.class, Chain.make("isAudit", true), + Cnd.where("projectId", "=", projectId).and("unionId", "=", unionId)); + } else { + dao.update(HealthCheckupUnionConfirm.class, Chain.make("isAudit", null) + .add("auditTime", null) + .add("auditUser", null), + Cnd.where("projectId", "=", projectId).and("unionId", "=", unionId)); + + dao.update(HealthCheckupUser.class, Chain.make("isAudit", null), + Cnd.where("projectId", "=", projectId).and("unionId", "=", unionId)); + } + return Result.success(); + } + + /** + * 体检名单管理员编辑选择记录;业务筛选、数据读写和结果组装在本服务内完成。 + * @param subjectId 体检医院选项主键 + * @param campus 体检院区主键 + * @param projectId 当前体检项目主键 + * @param userId 教职工主键 + * @param bz 选择记录备注 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doEditHealthCheckupData(String subjectId, String campus, String projectId, String userId, String bz) { + if(!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(),"HEALTH_ADMIN")) { + return Result.error("您没有操作此按钮的权限"); + } + //查询用户符合哪个套餐 + List list = healthCheckupProjectService.dao().query(HealthCheckupProjectSubjectMoney.class, + Cnd.where(HealthCheckupProjectSubjectMoney::getSubjectId, "=", subjectId)); + BigDecimal money = BigDecimal.valueOf(0.00); + String subjectMoneyId = ""; + for (HealthCheckupProjectSubjectMoney subject : list) { + // 是否满足条件 + Cnd cnd = Cnd.where("id", "=", userId); + ConditionGroupUtil.applyConditionGroup(cnd, subject.getMatchCnd()); + int count = dao.count(View_user.class, cnd); + if (count > 0) { + money = subject.getMoney(); + subjectMoneyId = subject.getId(); + break; + } + } + + //查询用户有没有选择过套餐 + HealthCheckupUserSelection userSelection = healthCheckupProjectService.dao().fetch(HealthCheckupUserSelection.class, + Cnd.where("projectId", "=", projectId) + .and("selectUserId", "=", userId)); + //如果选择过套餐就修改选择的套餐id + if (Lang.isNotEmpty(userSelection)) { + userSelection.setSubjectId(subjectId); + userSelection.setCampus(campus); + userSelection.setBz(bz); + userSelection.setSubjectMoneyId(subjectMoneyId); + userSelection.setMoney(money); + healthCheckupProjectService.update(userSelection); + } else { + //如果没有选择过套餐添加一条记录 + HealthCheckupUserSelection checkupUserSelection = new HealthCheckupUserSelection(); + checkupUserSelection.setSelectUserId(userId); + checkupUserSelection.setProjectId(projectId); + checkupUserSelection.setSubjectId(subjectId); + checkupUserSelection.setCampus(campus); + checkupUserSelection.setSelectTime(new Date()); + checkupUserSelection.setBz(bz); + checkupUserSelection.setSubjectMoneyId(subjectMoneyId); + checkupUserSelection.setMoney(money); + healthCheckupProjectService.insert(checkupUserSelection); + } + return Result.success(); + } + + /** + * 体检名单导入名单;业务筛选、数据读写和结果组装在本服务内完成。 + * @param file 上传的 Excel 临时文件 + * @param healthProjectId 导入目标体检项目主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result healthImport(TempFile file, String healthProjectId) { + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), + RoleConstant.SCHOOL_UNION_ADMIN.name(), + RoleConstant.SCHOOL_UNION_CHAIRMAN.name())) { + return Result.error("您没有【导入名单】的权限"); + } else { + // 读取数据 + List ts = EasyExcelUtil.syncReadModel(file.getFile(), HealthCheckupImportTemp.class, 0, 1); + List healthCheckupImportTemps = JSONUtil.parseArray(JSONUtil.toJsonStr(ts)).toList(HealthCheckupImportTemp.class); + List loginNames = healthCheckupImportTemps.stream().filter(v -> Strings.isNotBlank(v.getLoginName())).map(v -> v.getLoginName()).collect(Collectors.toList()); + //全部的体检名单 + List healthCheckupUserList = dao.query(HealthCheckupUser.class, Cnd.where(HealthCheckupUser::getProjectId, "=", healthProjectId)); + + + List userList = dao.query(View_user.class, Cnd.where(View_user::getLoginname, "in", loginNames)); + + HealthCheckupProject checkupProject = dao.fetch(HealthCheckupProject.class, healthProjectId); + ActivityUserScope userScope = dao.fetch(ActivityUserScope.class, Cnd.where("groupId", "=", checkupProject.getActivityGroupId())); + List userScopeList = new ArrayList<>(); + List healthCheckupUsersToAdd = new ArrayList<>(); + int successCount = 0; + for (int i = 0; i < healthCheckupImportTemps.size(); i++) { + HealthCheckupImportTemp excel = healthCheckupImportTemps.get(i); + if (StrUtil.isBlank(excel.getLoginName())) { + excel.setErrInfo("工号为空", i + 1); + continue; + } + + // 不能在excel里重复 + if (healthCheckupImportTemps.stream().filter(s -> s.getLoginName().equals(excel.getLoginName())).count() > 1) { + excel.setErrInfo("重复数据", i + 1); + continue; + } + + View_user user = userList.stream().filter(s -> s.getLoginname().equals(excel.getLoginName())).findFirst().orElse(null); + if (user == null) { + excel.setErrInfo("无此用户:" + excel.getLoginName(), i + 1); + continue; + } + String projectName = checkupProject.getName(); + if(projectName.contains("在职教职工")) { + projectName = "在职教职工"; + } + if(projectName.contains("校聘高知")) { + projectName = "校聘高知"; + } + if (healthCheckupUserList.stream().anyMatch(s -> s.getUserId().equals(user.getId()))) { + Chain chain = Chain.make("personType", projectName); + if(StringUtils.isNotBlank(excel.getPhone())){ + chain.add("phone", excel.getPhone()); + } + dao.update( + HealthCheckupUser.class,chain, + Cnd.NEW().and(HealthCheckupUser::getUserId, "=", user.getId()) + .and(HealthCheckupUser::getProjectId, "=", healthProjectId) + ); + } else { + ActivityUserScope s = new ActivityUserScope(); + s.setGroupId(userScope.getGroupId()); + s.setGroupName(userScope.getGroupName()); + s.setUserId(user.getId()); + s.setCreator(SecurityUtil.getUserId()); + userScopeList.add(s); + + HealthCheckupUser newHealthUser = new HealthCheckupUser(); + newHealthUser.setProjectId(healthProjectId); + newHealthUser.setUserId(user.getId()); + newHealthUser.setUserName(user.getUsername()); + newHealthUser.setSex(user.getSex()); + newHealthUser.setLoginName(user.getLoginname()); + newHealthUser.setUnionName(user.getUnionName()); + newHealthUser.setUnionId(user.getUnionId()); + newHealthUser.setUnitName(user.getUnitName()); + newHealthUser.setCard(user.getIdCard()); + newHealthUser.setPhone(excel.getPhone()); + newHealthUser.setMarriage(user.getMarriage()); + newHealthUser.setPersonType(projectName); + healthCheckupUsersToAdd.add(newHealthUser); + successCount++; + } + } + + + dao.insert(userScopeList); + dao.insert(healthCheckupUsersToAdd); + // 创建结果集 + ExcelImportRes excelImportRes = new ExcelImportRes<>(); + excelImportRes.setTotalRecords(healthCheckupImportTemps.size()); + // 添加错误记录 + excelImportRes.setErrorDetails(healthCheckupImportTemps.stream().filter(s -> StrUtil.isNotBlank(s.getErrMsg())).collect(Collectors.toList())); + excelImportRes.setFailedCount(excelImportRes.getErrorDetails().size()); + excelImportRes.setSuccessCount(successCount); + + return Result.success(excelImportRes); + } + } + + /** + * 下载体检参加人员导入模版;业务筛选、数据读写和结果组装在本服务内完成。 + * @param response 接收 Excel 文件流的 HTTP 响应 + * 文件内容直接写入 response,不返回 JSON。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public void downloadTem(HttpServletResponse response) { + List entities = new ArrayList<>(); + entities.add(new ExcelExportEntity("工号", "loginName", 20)); + entities.add(new ExcelExportEntity("姓名", "userName", 20)); + entities.add(new ExcelExportEntity("手机号", "phone", 20)); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, Collections.emptyList()); + CommonDownloadUtil.download("参加人员导入模版.xlsx", workbook, response); + } + + /** + * 体检名单删除;业务筛选、数据读写和结果组装在本服务内完成。 + * @param id 当前业务记录主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doDelete(String id) { + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), + RoleConstant.SCHOOL_UNION_ADMIN.name(), + RoleConstant.SCHOOL_UNION_CHAIRMAN.name(), + RoleConstant.BRANCH_UNION_ADMIN.name(), + RoleConstant.BRANCH_UNION_CHAIRMAN.name())) { + return Result.error("您没有【删除】的权限"); + } else { + HealthCheckupUser fetch = dao.fetch(HealthCheckupUser.class, Cnd.where(HealthCheckupUser::getId, "=", id)); + Cnd and = Cnd.NEW().and(HealthCheckupUserSelection::getProjectId, "=", fetch.getProjectId()) + .and(HealthCheckupUserSelection::getSelectUserId, "=", fetch.getUserId()); + dao.clear(HealthCheckupUserSelection.class, and); + dao.clear(HealthCheckupUser.class, Cnd.where(HealthCheckupUser::getId, "=", id)); + return Result.success(); + } + } + + /** + * 下载体检报告导入模版;业务筛选、数据读写和结果组装在本服务内完成。 + * @param response 接收 Excel 文件流的 HTTP 响应 + * 文件内容直接写入 response,不返回 JSON。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public void downloadTemMedicalExaminationReport(HttpServletResponse response) { + List entities = new ArrayList<>(); + entities.add(new ExcelExportEntity("工号", "loginName", 20)); + entities.add(new ExcelExportEntity("体检报告", "medicalExamination", 20)); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entities, Collections.emptyList()); + CommonDownloadUtil.download("体检报告导入模版.xlsx", workbook, response); + } + + /** + * 体检名单导入名单;业务筛选、数据读写和结果组装在本服务内完成。 + * @param file 上传的 Excel 临时文件 + * @param healthProjectId 导入目标体检项目主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result healthImportMedicalExaminationReport(TempFile file, String healthProjectId) { + // 读取数据 + List ts = EasyExcelUtil.syncReadModel(file.getFile(), HealthCheckupImportTemp.class, 0, 1); + List healthCheckupImportTemps = JSONUtil.parseArray(JSONUtil.toJsonStr(ts)).toList(HealthCheckupImportTemp.class); + List loginNames = healthCheckupImportTemps.stream().filter(v -> Strings.isNotBlank(v.getLoginName())).map(v -> v.getLoginName()).collect(Collectors.toList()); + + List userList = dao.query(View_user.class, Cnd.where(View_user::getLoginname, "in", loginNames)); + int successCount = 0; + for (int i = 0; i < healthCheckupImportTemps.size(); i++) { + HealthCheckupImportTemp excel = healthCheckupImportTemps.get(i); + if (StrUtil.isBlank(excel.getLoginName())) { + excel.setErrInfo("工号为空", i + 1); + continue; + } + // 不能在excel里重复 + if (healthCheckupImportTemps.stream().filter(s -> s.getLoginName().equals(excel.getLoginName())).count() > 1) { + excel.setErrInfo("重复数据", i + 1); + } + View_user user = userList.stream().filter(s -> s.getLoginname().equals(excel.getLoginName())).findFirst().orElse(null); + if (user == null) { + excel.setErrInfo("无此用户", i + 1); + continue; + } + + dao.update(HealthCheckupUser.class, + Chain.make("medicalExamination", excel.getMedicalExamination()), + Cnd.where("loginName", "=", excel.getLoginName()).and("projectId", "=", healthProjectId)); + successCount++; + } + + // 创建结果集 + ExcelImportRes excelImportRes = new ExcelImportRes<>(); + excelImportRes.setTotalRecords(healthCheckupImportTemps.size()); + // 添加错误记录 + excelImportRes.setErrorDetails(healthCheckupImportTemps.stream().filter(s -> StrUtil.isNotBlank(s.getErrMsg())).collect(Collectors.toList())); + excelImportRes.setFailedCount(excelImportRes.getErrorDetails().size()); + excelImportRes.setSuccessCount(successCount); + + return Result.success(excelImportRes); + } + + /** + * 套餐选择器查询;业务筛选、数据读写和结果组装在本服务内完成。 + * @param projectId 当前体检项目主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result listSubjects(String projectId) { + return Result.success( + dao.query(HealthCheckupProjectSubject.class, + Cnd.NEW().and("projectId","=",projectId)) + ); + } + + /** + * 体检反馈列表;业务筛选、数据读写和结果组装在本服务内完成。 + * @param year 四位体检年度 + * @param projectId 当前体检项目主键 + * @param unionId 所属分工会主键,可空时按接口范围处理 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result feedbackList(String year, String projectId, String unionId) { + if (StrUtil.isBlank(unionId)) { + unionId = SecurityUtil.getUnionId(); + } + if (StrUtil.hasBlank(year, projectId, unionId)) { + return Result.error("请选择年度、体检项目、分工会后再查看反馈"); + } + return Result.success(healthCheckupFeedbackService.listFeedback(year, projectId, unionId)); + } + + /** + * 保存体检反馈;业务筛选、数据读写和结果组装在本服务内完成。 + * @param year 四位体检年度 + * @param projectId 当前体检项目主键 + * @param unionId 所属分工会主键,可空时按接口范围处理 + * @param feedbackInfo 反馈正文 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result saveFeedback(String year, String projectId, String unionId, String feedbackInfo) { + if (StrUtil.isBlank(unionId)) { + unionId = SecurityUtil.getUnionId(); + } + NutMap result = healthCheckupFeedbackService.saveFeedback(year, projectId, unionId, feedbackInfo); + if (result.getInt("code") == 0) { + return Result.success(result.getString("msg")); + } + return Result.error(result.getString("msg")); + } + + /** + * 删除体检反馈;业务筛选、数据读写和结果组装在本服务内完成。 + * @param id 当前业务记录主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result deleteFeedback(String id) { + NutMap result = healthCheckupFeedbackService.deleteFeedback(id); + if (result.getInt("code") == 0) { + return Result.success(result.getString("msg")); + } + return Result.error(result.getString("msg")); + } + + /** + * 批量删除体检反馈;业务筛选、数据读写和结果组装在本服务内完成。 + * @param ids 逗号分隔或 JSON 数组形式的记录主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result deleteFeedbackBatch(String ids) { + String[] idArray = null; + if (StrUtil.isNotBlank(ids)) { + // 兼容前端传逗号分隔字符串和JSON数组字符串两种格式。 + if (ids.trim().startsWith("[")) { + idArray = JSONUtil.parseArray(ids).toList(String.class).toArray(new String[0]); + } else { + idArray = ids.split(","); + } + } + NutMap result = healthCheckupFeedbackService.deleteFeedbackBatch(idArray); + if (result.getInt("code") == 0) { + return Result.success(result.getString("msg")); + } + return Result.error(result.getString("msg")); + } + + /** + * 问题反馈列表分页;业务筛选、数据读写和结果组装在本服务内完成。 + * @param pageForm 分页、搜索及排序参数 + * @param year 四位体检年度 + * @param projectId 当前体检项目主键 + * @param unionId 所属分工会主键,可空时按接口范围处理 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result feedbackQueryPageData(PageForm pageForm, String year, String projectId, String unionId) { + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name()) && StrUtil.isBlank(unionId)) { + unionId = SecurityUtil.getUnionId(); + } + return Result.success(healthCheckupFeedbackService.listFeedbackPage( + pageForm.getPageNumber(), + pageForm.getPageSize(), + year, + projectId, + unionId + )); + } + + /** + * 体检名单编辑备注;业务筛选、数据读写和结果组装在本服务内完成。 + * @param userId 教职工主键 + * @param projectId 当前体检项目主键 + * @param remarks 人员备注内容 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doEditRemarks(String userId, String projectId,String remarks) { + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.BRANCH_UNION_ADMIN.name(), RoleConstant.BRANCH_UNION_CHAIRMAN.name())) { + return Result.error("您没有操作此按钮的权限"); + } + dao.update(HealthCheckupUser.class, + Chain.make("bz", remarks), + Cnd.where("userId", "=", userId) + .and("projectId", "=", projectId)); + return Result.success(); + } + + /** + * 导出;业务筛选、数据读写和结果组装在本服务内完成。 + * @param projectId 当前体检项目主键 + * @param unionId 所属分工会主键,可空时按接口范围处理 + * @param searchKeyword 姓名或工号搜索文本 + * @param subjectId 体检医院选项主键 + * @param unitId 所属单位主键筛选值 + * @param physicalExaminationStatus 1 已选、0 未选、2 全部 + * @param pageOrderName 排序字段名 + * @param pageOrderBy ascending 升序,否则降序 + * @param response 接收 Excel 文件流的 HTTP 响应 + * 文件内容直接写入 response,不返回 JSON。 + */ + public void exportHealthUser(String projectId, + String unionId, + String searchKeyword, + String subjectId, + String unitId, + String physicalExaminationStatus, + String pageOrderName, + String pageOrderBy, + HttpServletResponse response) { + List confirms = dao.query(HealthCheckupUnionConfirm.class, Cnd.where("projectId", "=", projectId)); + HealthCheckupProject project = healthCheckupProjectService.findOne(projectId); + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + SELECT + hcu.id AS headId, + hcu.userId AS id, + hcu.loginName, + hcu.userName, + hcu.sex, + hcu.unionId, + hcu.unionName, + hcu.unitName, + hcus.selectTime, + hcus.campus, + hcus.subjectId, + hcu.bz, + hcus.receiveAddress, + ca.campusName + FROM health_checkup_user hcu + LEFT JOIN health_checkup_user_selection hcus ON hcu.userId = hcus.selectUserId + AND hcus.projectId=@projectId + LEFT JOIN health_checkup_campus ca on ca.id=hcus.campus + $condition + """).setParam("projectId", projectId); + sql.setCondition(cnd); + cnd.andEX("hcu.projectId", "=", projectId); + cnd.andEX("hcu.unionId", "=", unionId); + cnd.andEX("hcu.unitId", "=", unitId); + cnd.andEX("hcus.subjectId", "=", subjectId); + + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.andEX("hcu.unionId", "=", SecurityUtil.getUnionId()); + } + //体检状态 + if(StringUtils.isNotBlank(physicalExaminationStatus) && !physicalExaminationStatus.equals("2")){ + if(physicalExaminationStatus.equals("1")) cnd.where().andNotIsNull("hcus.selectTime"); + if(physicalExaminationStatus.equals("0")) cnd.where().andIsNull("hcus.selectTime"); + } + + if (StrUtil.isNotBlank(searchKeyword)) { + SqlExpressionGroup group = new SqlExpressionGroup(); + group.orLike("hcu.userName", searchKeyword); + group.orLike("hcu.loginName", searchKeyword); + cnd.and(group); + } + cnd.groupBy("hcu.userId"); + if (StrUtil.isNotBlank(pageOrderName) && Strings.isNotBlank(pageOrderBy)) { + cnd.orderBy(pageOrderName, "ascending".equalsIgnoreCase(pageOrderBy) ? "ASC" : "DESC"); + } else { + cnd.desc("hcus.selectTime").asc("hcu.unitId"); + } + sql.setCondition(cnd); + + List paginationList = healthCheckupProjectService.listMap(sql); + paginationList.forEach(v -> { + if (StrUtil.isNotBlank(v.getString("subjectId"))) { + List subjects = project.getHealthCheckupProjectSubjects(); + HealthCheckupProjectSubject subject = subjects.stream().filter(s -> s.getId().equals(v.getString("subjectId"))).findFirst().orElse(null); + v.setv("optionName", subject.getOptionName()); + } + + if (StrUtil.isNotBlank(v.getString("unionId"))) { + HealthCheckupUnionConfirm confirm = confirms.stream().filter(o -> o.getUnionId().equals(v.getString("unionId"))).findFirst().orElse(null); + v.setv("isAudit", confirm != null && confirm.getIsAudit() ? "已确认" : "未确认"); + v.setv("auditTime", confirm != null && ObjectUtil.isNotEmpty(confirm.getAuditTime() ) + ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(confirm.getAuditTime()) : ""); + } + }); + for (int i = 0; i < paginationList.size(); i++) { + paginationList.get(i).put("index", i + 1); + } + + List entityList = new ArrayList<>() {{ + add(new ExcelExportEntity("序号", "index", 20)); + add(new ExcelExportEntity("工号", "loginName", 20)); + add(new ExcelExportEntity("姓名", "userName", 20)); + add(new ExcelExportEntity("性别", "sex", 20)); + add(new ExcelExportEntity("所属工会", "unionName", 20)); + add(new ExcelExportEntity("所属单位", "unitName", 20)); + add(new ExcelExportEntity("所选套餐", "optionName", 20)); + add(new ExcelExportEntity("选择时间", "selectTime", 50)); + add(new ExcelExportEntity("是否确认", "isAudit", 50)); + add(new ExcelExportEntity("确认时间", "auditTime", 50)); + add(new ExcelExportEntity("备注", "bz", 50)); + }}; + + try { + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + exportParams.setTitle("体检名单数据导出"); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, paginationList); + CommonDownloadUtil.download("体检名单数据导出.xlsx", workbook, response); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupPersonConfirmStatisticsService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupPersonConfirmStatisticsService.java new file mode 100644 index 00000000..5cf0a979 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupPersonConfirmStatisticsService.java @@ -0,0 +1,26 @@ +package com.budwk.app.zhgh.dayofficework.healthCheckup.service; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupUser; + +/** + * @ClassName HealthCheckupPersonConfirmStatisticsService + * @Description 工会人员确认情况统计 + * @Author Codex + * @Date 2026/4/28 + */ +public interface HealthCheckupPersonConfirmStatisticsService extends BaseService { + + /** + * 工会确认情况分页统计 + * + * @param pageNumber 页码 + * @param pageSize 页大小 + * @param year 年度 + * @param projectId 体检项目 + * @param unionId 工会 + * @return 统计分页结果 + */ + Pagination personConfirmPageData(Integer pageNumber, Integer pageSize, Integer year, String projectId, String unionId); +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupProjectMangeApplicationService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupProjectMangeApplicationService.java new file mode 100644 index 00000000..82c432b1 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupProjectMangeApplicationService.java @@ -0,0 +1,224 @@ +package com.budwk.app.zhgh.dayofficework.healthCheckup.service; + + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_home_activity; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.zhgh.activity.culture.service.ActivityCultureService; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.*; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupProjectService; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.Daos; +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.util.NutMap; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** 体检接口业务服务;HTTP 路由和权限校验保留在 controller。 */ +@IocBean +public class HealthCheckupProjectMangeApplicationService { + @Inject + private HealthCheckupProjectService healthCheckupProjectService; + @Inject + private ActivityCultureService activityCultureService; + + /** + * 分页查询;业务筛选、数据读写和结果组装在本服务内完成。 + * @param pageForm 分页、搜索及排序参数 + * @param year 四位体检年度 + * @param name 体检项目名称筛选值 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result pageData(PageForm pageForm, + Integer year, + String name) { + Sql sql = Sqls.create(""" + SELECT + hcp.id, + hcp.`year`, + hcp.`name`, + hcp.choiceTimeStart, + hcp.choiceTimeEnd, + hcp.activityGroupId, + hcp.cover, + hcp.activityGroupName, + hcp.healthCheckupType, + IF((select count(userId) from health_checkup_user hcu where hcu.projectId = hcp.id) > 0,true,false) AS isHasUserList, + IF(NOW() > hcp.choiceTimeStart AND NOW() < hcp.choiceTimeEnd, true, false) AS isWithinChoiceTime, + IF(NOW() < hcp.choiceTimeStart, true, false) AS canCreated + FROM + health_checkup_project hcp + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("hcp.`year`", "=", year); + cnd.andEX("hcp.`name`", "=", name); + cnd.desc("hcp.choiceTimeStart"); + sql.setCondition(cnd); + return Result.success(healthCheckupProjectService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql)); + } + + /** + * 体检项目确认;业务筛选、数据读写和结果组装在本服务内完成。 + * @param healthCheckupProject 体检项目及医院套餐明细 + * @param deleteRowIds 待删除的套餐金额记录主键数组 + * @param deleteSubjectIds 待删除的医院选项主键数组 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doAdd(HealthCheckupProject healthCheckupProject, + String[] deleteRowIds, + String[] deleteSubjectIds) { + + + String projectId; + //如果是保存 + if (StrUtil.isBlank(healthCheckupProject.getId())) { + healthCheckupProject.setYear(DateUtil.thisYear()); + HealthCheckupProject checkupProject = healthCheckupProjectService.insertWith(healthCheckupProject, "healthCheckupProjectSubjects"); + healthCheckupProject.getHealthCheckupProjectSubjects().forEach(v -> { + v.getSubjectMoneys().forEach(m -> { + m.setProjectId(checkupProject.getId()); + m.setSubjectId(v.getId()); + }); + if (Lang.isNotEmpty(v.getSubjectMoneys())) { + healthCheckupProjectService.insert(v.getSubjectMoneys()); + } + }); + projectId = checkupProject.getId(); + } else { + projectId = healthCheckupProject.getId(); + //如果删除了医院 + if (Lang.isNotEmpty(deleteSubjectIds)) { + healthCheckupProjectService.dao().clear(HealthCheckupProjectSubject.class, Cnd.where("id", "in", deleteSubjectIds)); + healthCheckupProjectService.dao().clear(HealthCheckupProjectSubjectMoney.class, Cnd.where("subjectId", "in", deleteSubjectIds)); + } + //如果删除了项目 + if (Lang.isNotEmpty(deleteRowIds)) { + healthCheckupProjectService.dao().clear(HealthCheckupProjectSubjectMoney.class, Cnd.where("id", "in", deleteRowIds)); + } + healthCheckupProjectService.dao().insertOrUpdate(healthCheckupProject.getHealthCheckupProjectSubjects()); + healthCheckupProject.getHealthCheckupProjectSubjects().forEach(v -> { + v.setProjectId(projectId); + v.getSubjectMoneys().forEach(m -> { + m.setProjectId(projectId); + m.setSubjectId(v.getId()); + }); + if (Lang.isNotEmpty(v.getSubjectMoneys())) { + healthCheckupProjectService.insertOrUpdate(v.getSubjectMoneys()); + } + }); + healthCheckupProjectService.dao().insertOrUpdate(healthCheckupProject.getHealthCheckupProjectSubjects()); + + healthCheckupProjectService.update(healthCheckupProject); + } + +// healthCheckupProjectService.dao().clear(HealthCheckupUnionConfirm.class, Cnd.where("projectId", "=", projectId)); +// List unionList = healthCheckupProjectService.dao().query(Sys_union.class, Cnd.NEW()); +// List confirmList = new ArrayList<>(); +// unionList.forEach(item -> { +// HealthCheckupUnionConfirm c = new HealthCheckupUnionConfirm(); +// c.setProjectId(projectId); +// c.setUnionId(item.getId()); +// c.setIsAudit(false); +// confirmList.add(c); +// }); +// healthCheckupProjectService.dao().insert(confirmList); + + Sys_home_activity sysHomeActivity = activityCultureService.dao().fetch(Sys_home_activity.class, Cnd.where("id", "=", healthCheckupProject.getId())); + if(ObjectUtil.isNotEmpty(sysHomeActivity)){ + activityCultureService.dao().clear(Sys_home_activity.class, Cnd.where(Sys_home_activity::getId, "=", sysHomeActivity.getId())); + } + + activityCultureService.insertOrUpdate(healthCheckupProject.covertToSysHomeActivity()); + return Result.success(); + } + + /** + * 查询体检项目内容;业务筛选、数据读写和结果组装在本服务内完成。 + * @param id 当前业务记录主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result findOne(String id) { + return Result.success(healthCheckupProjectService.findOne(id)); + } + + /** + * 删除体检项目;业务筛选、数据读写和结果组装在本服务内完成。 + * @param id 当前业务记录主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doDelete(String id) { + healthCheckupProjectService.delete(id); + healthCheckupProjectService.dao().clear(HealthCheckupProjectSubject.class, Cnd.where("projectId", "=", id)); + healthCheckupProjectService.dao().clear(HealthCheckupProjectSubjectMoney.class, Cnd.where("projectId", "=", id)); + activityCultureService.dao().clear(Sys_home_activity.class, Cnd.where(Sys_home_activity::getId, "=", id)); + return Result.success(); + } + + /** + * 按年份获取体检项目;业务筛选、数据读写和结果组装在本服务内完成。 + * @param year 四位体检年度 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result getHealthCheckupProject(Integer year) { + List projectList = healthCheckupProjectService.query(Cnd.NEW().andEX("year", "=", year).desc("choiceTimeStart")); + return Result.success(projectList); + } + + /** + * 创建体检名单;业务筛选、数据读写和结果组装在本服务内完成。 + * @param healthCheckupProject 体检项目及医院套餐明细 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result createUserList(HealthCheckupProject healthCheckupProject) { + healthCheckupProjectService.addHealthCheckupUser(healthCheckupProject); + return Result.success(); + } + + /** + * 更新体检名单;业务筛选、数据读写和结果组装在本服务内完成。 + * @param healthCheckupProject 体检项目及医院套餐明细 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result renewUserList(HealthCheckupProject healthCheckupProject) { + healthCheckupProjectService.renewHealthCheckupUser(healthCheckupProject); + return Result.success(); + } + + /** + * 重置体检名单;业务筛选、数据读写和结果组装在本服务内完成。 + * @param healthCheckupProject 体检项目及医院套餐明细 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result resetUserList(HealthCheckupProject healthCheckupProject) { + //重置名单,清空已选择的用户记录 + Sql sql = Sqls.create("select id,selectUserId from health_checkup_user_selection where projectId = @projectId").setParam("projectId", healthCheckupProject.getId()); + List list = (List) Daos.query(healthCheckupProjectService.dao(), sql.toString(), Sqls.callback.maps()); + List userSelectionIds = list.stream().map(v -> v.getString("id")).collect(Collectors.toList()); + List userIds = list.stream().map(v -> v.getString("selectUserId")).collect(Collectors.toList()); + + healthCheckupProjectService.dao().clear(HealthCheckupUserSelection.class, + Cnd.NEW().and("selectUserId", "in", userIds) + .and("projectId", "=", healthCheckupProject.getId())); + healthCheckupProjectService.dao().clear(HealthCheckupUserCompanion.class, Cnd.where("userSelectionId", "in", userSelectionIds)); + healthCheckupProjectService.dao().clear(HealthCheckupUser.class, Cnd.where("projectId", "=", healthCheckupProject.getId())); + healthCheckupProjectService.addHealthCheckupUser(healthCheckupProject); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupProjectService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupProjectService.java index ddb2bb59..12f26f3b 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupProjectService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupProjectService.java @@ -2,6 +2,7 @@ package com.budwk.app.zhgh.dayofficework.healthCheckup.service; import com.budwk.app.base.service.BaseService; import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupProject; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupUserSelection; public interface HealthCheckupProjectService extends BaseService { @@ -20,4 +21,10 @@ public interface HealthCheckupProjectService extends BaseService labelList = healthCheckupSingleService.receivePageDataColumns(projectId); + Pagination list = healthCheckupSingleService.receivePageData(page.getPageNumber(), page.getPageSize(), page.getSearchName(), page.getSearchKeyword(), projectId, unionId, isSelected); + return Result.success(NutMap.NEW().addv("list", list).addv("label", labelList)); + } + + /** + * 按医院导出当前项目全部已选教职工;不受页面分工会筛选影响。 + * @param projectId 当前教职工体检项目ID + * @param response 输出ZIP附件,每个有报名人员的医院对应一个xlsx文件;无JSON返回值 + */ + public void exportSelectedZip(String projectId, HttpServletResponse response) { + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + throw new BaseException("仅系统管理员或校工会管理员可导出全部已选名单"); + } + if (Strings.isBlank(projectId)) throw new BaseException("请选择体检项目"); + HealthCheckupProject project = healthCheckupProjectService.fetch(projectId); + if (project == null || !"jzg".equals(project.getHealthCheckupType())) { + throw new BaseException("请选择教职工体检项目"); + } + // 以已选记录为查询起点,不包含尚未报名人员,也不因分工会为空而丢失报名记录。 + Sql sql = Sqls.create(""" + SELECT s.subjectId, h.optionName AS subjectName, + c.loginName, c.userName, c.sex, + COALESCE(c.age,TIMESTAMPDIFF(YEAR,u.birthday,CURDATE())) AS age, + c.phone AS mobile, c.card AS idCard, + COALESCE(d.name,c.personType) AS personType, + c.marriage, s.money, m.settlementMoney, + c.unitName, c.unionName, s.receiveAddress, c.isEmployed + FROM health_checkup_user_selection s + JOIN health_checkup_project_subject h ON h.id=s.subjectId AND h.projectId=s.projectId + LEFT JOIN health_checkup_user c ON c.projectId=s.projectId AND c.userId=s.selectUserId + LEFT JOIN sys_user u ON u.id=s.selectUserId + LEFT JOIN health_checkup_project_subject_money m ON m.id=s.subjectMoneyId AND m.subjectId=s.subjectId + LEFT JOIN sys_dict p ON p.code='USER_PERSON_TYPE' + LEFT JOIN sys_dict d ON d.parentId=p.id AND d.code=c.personType + WHERE s.projectId=@projectId + ORDER BY h.optionSort,h.id,c.unionName,c.unitName,c.loginName,s.id + """); + sql.setParam("projectId", projectId); + List rows = healthCheckupSingleService.listMap(sql); + if (rows.isEmpty()) throw new BaseException("当前项目暂无已选名单"); + Map> hospitals = new LinkedHashMap<>(); + rows.forEach(row -> hospitals.computeIfAbsent(row.getString("subjectId"), key -> new ArrayList<>()).add(row)); + List columns = new ArrayList<>(); + columns.add(new ExcelExportEntity("工号", "loginName", 20)); + columns.add(new ExcelExportEntity("姓名", "userName", 20)); + columns.add(new ExcelExportEntity("性别", "sex", 20)); + columns.add(new ExcelExportEntity("年龄", "age", 20)); + columns.add(new ExcelExportEntity("手机号码", "mobile", 20)); + columns.add(new ExcelExportEntity("身份证号", "idCard", 20)); + columns.add(new ExcelExportEntity("人员类别", "personType", 20)); + columns.add(new ExcelExportEntity("婚姻状况", "marriage", 20)); + columns.add(new ExcelExportEntity("医院", "subjectName", 20)); + columns.add(new ExcelExportEntity("套餐金额", "money", 20)); + columns.add(new ExcelExportEntity("结算金额", "settlementMoney", 20)); + columns.add(new ExcelExportEntity("部门", "unitName", 20)); + columns.add(new ExcelExportEntity("分工会", "unionName", 20)); + columns.add(new ExcelExportEntity("邮寄地址", "receiveAddress", 20)); + columns.add(new ExcelExportEntity("是否自聘", "isEmployed", 20)); + // 先完整生成压缩包再写响应,生成失败时不返回半截附件;各医院使用独立工作簿。 + try (ByteArrayOutputStream bytes = new ByteArrayOutputStream()) { + try (ZipOutputStream zip = new ZipOutputStream(bytes, StandardCharsets.UTF_8)) { + int index = 1; + for (List hospitalRows : hospitals.values()) { + String hospital = hospitalRows.get(0).getString("subjectName"); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + exportParams.setSheetName("已选名单"); + exportParams.setTitle(hospital + "已选名单"); + // 序号避免同名医院产生重复ZIP条目;替换路径分隔符及文件名非法字符。 + String safeName = Strings.sNull(hospital).replaceAll("[\\\\/:*?\"<>|\\p{Cntrl}]", "_"); + if (safeName.length() > 80) safeName = safeName.substring(0, 80); + zip.putNextEntry(new ZipEntry((index++) + "_" + safeName + ".xlsx")); + try (Workbook workbook = ExcelExportUtil.exportExcel(exportParams, columns, hospitalRows)) { + workbook.write(zip); + } + zip.closeEntry(); + } + } + CommonDownloadUtil.download(project.getName() + "_已选名单.zip", bytes.toByteArray(), response); + } catch (IOException e) { + throw new BaseException("已选名单ZIP生成失败,请重试"); + } + } + + /** + * 导出已选/未选人员名单;业务筛选、数据读写和结果组装在本服务内完成。 + * @param projectId 当前体检项目主键 + * @param unionId 所属分工会主键,可空时按接口范围处理 + * @param year 四位体检年度 + * @param flag 确认或取消、已选或未选的业务标志 + * @param response 接收 Excel 文件流的 HTTP 响应 + * 文件内容直接写入 response,不返回 JSON。 + */ + public void exportReceiveDetail(String projectId, + String unionId, + Integer year, + boolean flag, HttpServletResponse response) { + + List entityList = new ArrayList<>() {{ + add(new ExcelExportEntity("工号", "loginName", 20)); + add(new ExcelExportEntity("姓名", "userName", 20)); + add(new ExcelExportEntity("性别", "sex", 20)); + add(new ExcelExportEntity("年龄", "age", 20)); + add(new ExcelExportEntity("手机号码", "mobile", 20)); + add(new ExcelExportEntity("身份证号", "idCard", 20)); + add(new ExcelExportEntity("用户类型", "personType", 20)); + add(new ExcelExportEntity("婚姻状况", "marriage", 20)); + add(new ExcelExportEntity("医院", "subjectName", 20)); + add(new ExcelExportEntity("套餐金额", "money", 20)); + add(new ExcelExportEntity("结算金额", "settlementMoney", 20)); + add(new ExcelExportEntity("部门", "unitName", 20)); + add(new ExcelExportEntity("分工会", "unionName", 20)); + add(new ExcelExportEntity("邮寄地址", "receiveAddress", 50)); + add(new ExcelExportEntity("是否自聘", "isEmployed", 50)); + }}; + + List list; + if (flag) { + //已选人员 + list = healthCheckupSingleService.receivePageData(projectId, unionId, "0"); + } else { + //未选人员 + list = healthCheckupSingleService.receivePageData(projectId, unionId, "1"); + } + //获取当前年 + Calendar calendar = Calendar.getInstance(); + int thisYear = calendar.get(Calendar.YEAR); + list.forEach(v -> { + int substring = 0; + if (Strings.isNotBlank(v.getString("birthday"))) { + substring = Integer.parseInt(v.getString("birthday").substring(0, 4)); + } else if (Strings.isNotBlank(v.getString("idCard")) && v.getString("idCard").length() >= 10) { + substring = Integer.parseInt(v.getString("idCard").substring(6, 10)); + } + v.put("age", thisYear - substring); + if(v.getString("projectName").contains("在职教职工")){ + v.put("personType", "在职教职工"); + } else if(v.getString("projectName").contains("校聘高知")){ + v.put("personType", "校聘高知保健对象"); + } + }); + + List list2 = list.stream().filter(v -> Strings.isNotBlank(v.getString("unionName"))).collect(Collectors.toList()); + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + exportParams.setSheetName(year + "年教职工体检项目及地点统计表"); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, list2); + CommonDownloadUtil.download((flag ? year + "年教职工体检项目及地点统计表" : "未选名单") + ".xlsx", workbook, response); + } + + /** + * 导出教职工家属体检登记表;业务筛选、数据读写和结果组装在本服务内完成。 + * @param projectId 当前体检项目主键 + * @param unionId 所属分工会主键,可空时按接口范围处理 + * @param year 四位体检年度 + * @param response 接收 Excel 文件流的 HTTP 响应 + * 文件内容直接写入 response,不返回 JSON。 + */ + public void exportUserCompanion(String projectId, + String unionId, + Integer year, HttpServletResponse response) { + Sql sql = Sqls.create(""" + SELECT + u.username, + u.unitname unitName, + u.mobile, + hcuc.userName familyName, + hcuc.sex, + hcuc.marry isMarried, + hcuc.idCard, + hcc.campusName, + ( + SELECT + GROUP_CONCAT( hcps.optionName ) + FROM + health_checkup_user_selection hcus + LEFT JOIN `health_checkup_project_subject` hcps ON hcps.id = hcus.subjectId + WHERE + hcus.projectId = @projectId + AND hcus.selectUserId = u.id + ) optionName + FROM + `health_checkup_user_companion` hcuc + LEFT JOIN `health_checkup_user_selection` hcus ON hcus.id = hcuc.userSelectionId + LEFT JOIN `health_checkup_campus` hcc ON hcc.id = hcus.campus + LEFT JOIN `vw_user` u ON u.id = hcus.selectUserId + LEFT JOIN `health_checkup_project` hcp ON hcp.id = hcus.projectId + $condition + """).setParam("projectId", projectId); + Cnd cnd = Cnd.NEW(); + cnd.andEX("hcus.projectId", "=", projectId); + cnd.andEX("u.unionid", "=", unionId); + cnd.andEX("hcp.year", "=", year); + cnd.asc("u.unioncode"); + sql.setCondition(cnd); + //家属信息表 + List companionList = healthCheckupSingleService.listMap(sql); + + for (int i = 0; i < companionList.size(); i++) { + companionList.get(i).put("index", i + 1); + } + + List entityList = new ArrayList<>() {{ + add(new ExcelExportEntity("序号", "index", 20)); + add(new ExcelExportEntity("教职工姓名", "username", 20)); + add(new ExcelExportEntity("学院(部门)", "unitName", 20)); + add(new ExcelExportEntity("手机", "mobile", 20)); + add(new ExcelExportEntity("体检人姓名", "familyName", 20)); + add(new ExcelExportEntity("性别", "sex", 20)); + add(new ExcelExportEntity("婚否", "isMarried", 20)); + add(new ExcelExportEntity("体检人身份证号", "idCard", 50)); + add(new ExcelExportEntity("自选项目", "optionName", 50)); + add(new ExcelExportEntity("自选院区", "campusName", 50)); + }}; + + try { + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + exportParams.setTitle(year + "教职工家属体检登记表"); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, entityList, companionList); + CommonDownloadUtil.download(year + "教职工家属体检登记表.xlsx", workbook, response); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 管理员一键代选;业务筛选、数据读写和结果组装在本服务内完成。 + * @param projectId 当前体检项目主键 + * @param optionId 代选的医院选项主键 + * @param campus 体检院区主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result doSelectByAdmin(String projectId, String optionId, String campus) { + Dao dao = healthCheckupSingleService.dao(); + HealthCheckupProject project = dao.fetch(HealthCheckupProject.class, projectId); + + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + SELECT + u.id, + u.loginname loginName, + u.username userName, + u.sex, + u.birthday, + u.unitname unitName, + u.unionname unionName, + u.idcard idCard, + u.mobile + FROM + `activity_user_scope` aus + LEFT JOIN `vw_user` u ON u.id = aus.userId + $projectCnd $condition + """); + + cnd.and("aus.groupId", "=", project.getActivityGroupId()); + sql.setVar("projectCnd", "AND u.id NOT IN ( SELECT selectUserId FROM `health_checkup_user_selection` WHERE projectId = '" + projectId + "' AND selectUserId IS NOT NULL )"); + cnd.groupBy("u.loginname"); + sql.setCondition(cnd); + List mapList = healthCheckupSingleService.listMap(sql); + + List userIds = mapList.stream().map(v -> v.getString("id")).collect(Collectors.toList()); + //题目id + List selections = userIds.stream().map(v -> { + HealthCheckupUserSelection selection = new HealthCheckupUserSelection(); + selection.setProjectId(projectId); + selection.setSelectUserId(v); + selection.setCampus(campus); + selection.setSubjectId(optionId); + selection.setSelectTime(new Date()); + return selection; + }).collect(Collectors.toList()); + manyAddOrRenewUtil.asyncExecuteFastInsert(selections, null); + return Result.success(); + } + + /** + * 按上年补齐未选人员;业务筛选、数据读写和结果组装在本服务内完成。 + * @param projectId 当前体检项目主键 + * @param lastYearProjectId 上一年度体检项目主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public Result selectOptionByLastYear(String projectId, String lastYearProjectId) { + + Dao dao = healthCheckupSingleService.dao(); + //获取去年项目 + HealthCheckupProject lastYearProject = dao.fetch(HealthCheckupProject.class, Cnd.where("id", "=", lastYearProjectId)); + if (lastYearProject == null) { + return Result.error("请先创建去年的体检项目"); + } + Cnd cnd = Cnd.NEW(); + Sql sql = Sqls.create(""" + SELECT + u.id + FROM + health_checkup_user hcu + LEFT JOIN `vw_user` u ON u.id = hcu.userId + $projectCnd $condition + """); + cnd.and("hcu.projectId", "=", projectId); + + sql.setVar("projectCnd", + "AND u.id NOT IN ( SELECT selectUserId FROM `health_checkup_user_selection` WHERE projectId = '" + projectId + "' AND selectUserId IS NOT NULL )"); + cnd.groupBy("u.loginname"); + sql.setCondition(cnd); + List mapList = healthCheckupSingleService.listMap(sql); + if(CollectionUtil.isEmpty(mapList)) return Result.success(); + + List userIds = mapList.stream().map(v -> v.getString("id")).filter(Strings::isNotBlank).toList(); + + //去年项目的人 + Cnd aNew = Cnd.NEW(); + aNew.and(HealthCheckupUserSelection::getProjectId, "=", lastYearProject.getId()) + .and(HealthCheckupUserSelection::getSelectUserId, "in", userIds); + List lastYearSelectionList = dao.query(HealthCheckupUserSelection.class, aNew); + + //去年项目下的医院 + List lastYearSubjectList = dao.query(HealthCheckupProjectSubject.class, + Cnd.where(HealthCheckupProjectSubject::getProjectId, "=", lastYearProject.getId())); + + //今年项目下的医院 + List thisYearSubjectList = dao.query(HealthCheckupProjectSubject.class, + Cnd.where(HealthCheckupProjectSubject::getProjectId, "=", projectId)); + List thisYearSubjectMoneyList = dao.query(HealthCheckupProjectSubjectMoney.class, + Cnd.where(HealthCheckupProjectSubject::getProjectId, "=", projectId)); + + List selections = new ArrayList<>(); + userIds.forEach(v -> { + //获取去年这个人选择的记录 + HealthCheckupUserSelection userSelection = lastYearSelectionList.stream().filter(item -> item.getSelectUserId().equals(v)).findFirst().orElse(null); + if(ObjectUtil.isNotEmpty(userSelection)){ + //去年这个人选择的选项是什么 + HealthCheckupProjectSubject lastYearSubject = lastYearSubjectList.stream().filter(last -> last.getId().equals(userSelection.getSubjectId())).findFirst().orElse(null); + //今年项目下的选项 + HealthCheckupProjectSubject thisYearSubject = thisYearSubjectList.stream().filter(thisYear -> thisYear.getOptionName().equals(lastYearSubject.getOptionName())).findFirst().orElse(null); + if (userSelection != null && thisYearSubject != null) { + //获取今年这个选项的收费 + List list = dao.query(HealthCheckupProjectSubjectMoney.class, + Cnd.where(HealthCheckupProjectSubjectMoney::getSubjectId, "=", thisYearSubject.getId())); + BigDecimal money = BigDecimal.valueOf(0.00); + String subjectMoneyId = null; + for (HealthCheckupProjectSubjectMoney subject : list) { + //找出这个人符合哪个项目 + Cnd cndUser = Cnd.where("id", "=", v); + ConditionGroupUtil.applyConditionGroup(cndUser, subject.getMatchCnd()); + int count = dao.count(View_user.class, cndUser); + if (count > 0) { + money = subject.getMoney(); + subjectMoneyId = subject.getId(); + break; + } + } + //如果有符合的就添加 + if (subjectMoneyId != null) { + HealthCheckupUserSelection selection = new HealthCheckupUserSelection(); + selection.setProjectId(projectId); + selection.setSelectUserId(v); + selection.setSubjectId(thisYearSubject.getId()); + selection.setSubjectMoneyId(subjectMoneyId); + selection.setMoney(money); + selection.setSelectTime(new Date()); + selections.add(selection); + } + } + } else { + //若去年未体检,则去本年校医院体检 + HealthCheckupProjectSubject thisYearProjectSubject = thisYearSubjectList.stream() + .filter(e -> e.getOptionName().contains("校医院")) + .findFirst() + .orElse(null); + if(ObjectUtil.isNotEmpty(thisYearProjectSubject)) { + List healthCheckupProjectSubjectMonies = thisYearSubjectMoneyList.stream() + .filter(e -> e.getSubjectId().equals(thisYearProjectSubject.getId())) + .collect(Collectors.toList()); + if(CollectionUtil.isNotEmpty(healthCheckupProjectSubjectMonies)){ + BigDecimal money = BigDecimal.valueOf(0.00); + String subjectMoneyId = null; + for (HealthCheckupProjectSubjectMoney subject : healthCheckupProjectSubjectMonies) { + //找出这个人符合哪个项目 + Cnd cndUser = Cnd.where("id", "=", v); + ConditionGroupUtil.applyConditionGroup(cndUser, subject.getMatchCnd()); + int count = dao.count(View_user.class, cndUser); + if (count > 0) { + money = subject.getMoney(); + subjectMoneyId = subject.getId(); + break; + } + } + //如果有符合的就添加 + if (subjectMoneyId != null) { + HealthCheckupUserSelection selection = new HealthCheckupUserSelection(); + selection.setProjectId(projectId); + selection.setSelectUserId(v); + selection.setSubjectId(thisYearProjectSubject.getId()); + selection.setSubjectMoneyId(subjectMoneyId); + selection.setMoney(money); + selection.setSelectTime(new Date()); + selections.add(selection); + } + } + } + } + }); + dao.insert(selections); + return Result.success(); + } + + /** + * 给未选的人发送提醒;业务筛选、数据读写和结果组装在本服务内完成。 + * @param projectId 当前体检项目主键 + * @return Result;Result 的 code 为 0 表示成功,msg 为说明,data 为本接口业务数据。 + */ + public Result msgNotSelect(String projectId) { + + List userList = healthCheckupSingleService.receivePageData(projectId, null, "1"); + if(CollectionUtil.isNotEmpty(userList)){ + HealthCheckupProject project = healthCheckupProjectService.dao().fetch(HealthCheckupProject.class, Cnd.where("id", "=", projectId)); + String smsMessage = StringUtils.defaultIfBlank( + project.getSmsMessage(), + "系统显示您本年度体检医院信息尚未维护,请尽快登录小程序完成体检医院选择及个人信息确认,以免影响正常体检安排。"); + List loginNameList = userList.stream() + .map(e -> e.getString("loginName")) + .collect(Collectors.toList()); + // 使用当前项目的消息服务,保留项目标题、提醒正文和手机端入口。 + smsService.massSend(loginNameList, project.getName(), smsMessage, + Globals.AppDomain + "/platform/healthCheckup/h5/list"); + return Result.success("提醒成功"); + } else { + return Result.success("不存在未体检人员"); + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupSingleService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupSingleService.java index 001316b8..1e679e55 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupSingleService.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/HealthCheckupSingleService.java @@ -9,6 +9,21 @@ import java.util.List; public interface HealthCheckupSingleService extends BaseService { + /** + * 查询项目实际人数,不按工会筛选。 + * @param projectId 体检项目ID + * @return NutMap:__total__为本次体检人数,其他键为医院选项ID,值为人数;未录入项不返回 + */ + NutMap actualStatistics(String projectId); + + /** + * 保存当前项目整行实际人数。 + * @param projectId 体检项目ID + * @param counts JSON对象,__total__及当前项目全部医院ID为键,非负整数为值 + * @return 保存后的实际人数映射 + */ + NutMap saveActualStatistics(String projectId, String counts); + /** * 分页查询 * diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupFeedbackServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupFeedbackServiceImpl.java new file mode 100644 index 00000000..77be1e5b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupFeedbackServiceImpl.java @@ -0,0 +1,129 @@ +package com.budwk.app.zhgh.dayofficework.healthCheckup.service.impl; + +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.sys.models.Sys_union; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupFeedback; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupProject; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupFeedbackService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.util.NutMap; + +import java.util.ArrayList; +import java.util.List; + +@IocBean(args = {"refer:dao"}) +public class HealthCheckupFeedbackServiceImpl extends BaseServiceImpl implements HealthCheckupFeedbackService { + + public HealthCheckupFeedbackServiceImpl(Dao dao) { + super(dao); + } + + @Override + public List listFeedback(String year, String projectId, String unionId) { + Cnd cnd = Cnd.NEW(); + cnd.and("year", "=", year) + .and("projectId", "=", projectId) + .and("unionId", "=", unionId) + .desc("createdAt"); + List feedbackList = query(cnd); + List result = new ArrayList<>(); + for (HealthCheckupFeedback feedback : feedbackList) { + result.add(NutMap.NEW() + .addv("id", feedback.getId()) + .addv("year", feedback.getYear()) + .addv("projectName", feedback.getProjectName()) + .addv("unionName", feedback.getUnionName()) + .addv("feedbackInfo", feedback.getFeedbackInfo()) + .addv("createdBy", feedback.getCreatedBy()) + .addv("createdAt", feedback.getCreatedAt())); + } + return result; + } + + @Override + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public NutMap saveFeedback(String year, String projectId, String unionId, String feedbackInfo) { + if (StrUtil.isBlank(year) || StrUtil.isBlank(projectId) || StrUtil.isBlank(unionId)) { + return NutMap.NEW().addv("code", 1).addv("msg", "请选择年度、体检项目、分工会后再录入反馈"); + } + if (StrUtil.isBlank(feedbackInfo)) { + return NutMap.NEW().addv("code", 1).addv("msg", "请输入反馈信息"); + } + + // 保存前先根据页面选中的条件反查项目和分工会,确保反馈和主列表条件强关联。 + HealthCheckupProject project = dao().fetch(HealthCheckupProject.class, projectId); + if (project == null) { + return NutMap.NEW().addv("code", 1).addv("msg", "当前体检项目不存在,请重新选择"); + } + Sys_union union = dao().fetch(Sys_union.class, unionId); + if (union == null) { + return NutMap.NEW().addv("code", 1).addv("msg", "当前分工会不存在,请重新选择"); + } + + HealthCheckupFeedback feedback = new HealthCheckupFeedback(); + feedback.setYear(year); + feedback.setProjectId(projectId); + feedback.setProjectName(project.getName()); + feedback.setUnionId(unionId); + feedback.setUnionName(union.getName()); + feedback.setFeedbackInfo(feedbackInfo); + insert(feedback); + return NutMap.NEW().addv("code", 0).addv("msg", "保存成功"); + } + + @Override + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public NutMap deleteFeedback(String id) { + if (StrUtil.isBlank(id)) { + return NutMap.NEW().addv("code", 1).addv("msg", "反馈ID不能为空"); + } + HealthCheckupFeedback feedback = fetch(id); + if (feedback == null) { + return NutMap.NEW().addv("code", 1).addv("msg", "反馈记录不存在"); + } + delete(id); + return NutMap.NEW().addv("code", 0).addv("msg", "删除成功"); + } + + @Override + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) + public NutMap deleteFeedbackBatch(String[] ids) { + if (ids == null || ids.length == 0) { + return NutMap.NEW().addv("code", 1).addv("msg", "请选择需要删除的反馈"); + } + Cnd cnd = Cnd.NEW(); + cnd.and("id", "in", ids); + clear(cnd); + return NutMap.NEW().addv("code", 0).addv("msg", "批量删除成功"); + } + + @Override + public Pagination listFeedbackPage(Integer pageNumber, Integer pageSize, String year, String projectId, String unionId) { + Cnd cnd = Cnd.NEW(); + cnd.andEX("hcf.year", "=", year); + cnd.andEX("hcf.projectId", "=", projectId); + cnd.andEX("hcf.unionId", "=", unionId); + cnd.desc("hcf.createdAt"); + Sql sql = Sqls.create(""" + SELECT + hcf.id, + hcf.year, + hcf.projectName, + hcf.unionName, + hcf.feedbackInfo, + hcf.createdAt, + su.username AS createdByName + FROM health_checkup_feedback hcf + LEFT JOIN sys_user su ON su.id = hcf.createdBy + $condition + """); + sql.setCondition(cnd); + return listPageMap(pageNumber, pageSize, sql); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupPersonConfirmStatisticsServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupPersonConfirmStatisticsServiceImpl.java new file mode 100644 index 00000000..5d11af6f --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupPersonConfirmStatisticsServiceImpl.java @@ -0,0 +1,60 @@ +package com.budwk.app.zhgh.dayofficework.healthCheckup.service.impl; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupUser; +import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupPersonConfirmStatisticsService; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.Sqls; +import org.nutz.dao.sql.Sql; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @ClassName HealthCheckupPersonConfirmStatisticsServiceImpl + * @Description 工会人员确认情况统计实现 + * @Author Codex + * @Date 2026/4/28 + */ +@IocBean(args = {"refer:dao"}) +public class HealthCheckupPersonConfirmStatisticsServiceImpl extends BaseServiceImpl implements HealthCheckupPersonConfirmStatisticsService { + + public HealthCheckupPersonConfirmStatisticsServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Pagination personConfirmPageData(Integer pageNumber, Integer pageSize, Integer year, String projectId, String unionId) { + // 统计以系统工会为主表,保证未报名的工会也会显示在列表中。 + Sql sql = Sqls.create(""" + SELECT + su.id AS unionId, + su.name AS unionName, + COUNT(CASE WHEN hcp.id IS NOT NULL THEN hcu.id END) AS totalCount, + SUM(CASE WHEN hcp.id IS NOT NULL AND hcu.isAudit = '1' THEN 1 ELSE 0 END) AS confirmedCount, + SUM(CASE WHEN hcp.id IS NOT NULL AND hcu.id IS NOT NULL AND (hcu.isAudit IS NULL OR hcu.isAudit <> '1') THEN 1 ELSE 0 END) AS unconfirmedCount, + CASE + WHEN COUNT(CASE WHEN hcp.id IS NOT NULL THEN hcu.id END) > 0 + AND COUNT(CASE WHEN hcp.id IS NOT NULL THEN hcu.id END) = SUM(CASE WHEN hcp.id IS NOT NULL AND hcu.isAudit = '1' THEN 1 ELSE 0 END) THEN '已完成' + ELSE '未完成' + END AS completeStatus + FROM sys_union su + LEFT JOIN health_checkup_user hcu ON hcu.unionId = su.id + AND hcu.delFlag = 0 + AND hcu.projectId = @projectId + LEFT JOIN health_checkup_project hcp ON hcp.id = hcu.projectId + AND hcp.delFlag = 0 + AND hcp.year = @year + $condition + """).setParam("projectId", projectId).setParam("year", year); + Cnd cnd = Cnd.NEW(); + cnd.andEX("su.id", "=", unionId); + cnd.groupBy("su.id,su.name"); + cnd.asc("completeStatus"); + cnd.asc("su.unionCode"); + sql.setCondition(cnd); + // isAudit 存在于 health_checkup_user 中,只要还有未确认人员,该工会状态就显示未完成。 + // 排序按报名总人数倒序,人数相同时再按工会编码升序,保证列表顺序稳定。 + return listPageMap(pageNumber, pageSize, sql); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupProjectServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupProjectServiceImpl.java index dfc809a2..dabb5597 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupProjectServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupProjectServiceImpl.java @@ -1,8 +1,12 @@ package com.budwk.app.zhgh.dayofficework.healthCheckup.service.impl; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.ObjectUtil; import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.base.utils.ConditionGroupUtil; import com.budwk.app.base.utils.ManyAddOrRenewUtil; import com.budwk.app.sys.views.View_user; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; import com.budwk.app.zhgh.activity.basic.models.ActivityUserScope; import com.budwk.app.zhgh.dayofficework.healthCheckup.model.*; import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupProjectService; @@ -12,6 +16,7 @@ import org.nutz.dao.Dao; import org.nutz.dao.Sqls; import org.nutz.dao.sql.Sql; import org.nutz.dao.util.Daos; +import org.nutz.dao.util.cri.SqlExpressionGroup; import org.nutz.ioc.aop.Aop; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; @@ -19,8 +24,8 @@ import org.nutz.lang.Strings; import org.nutz.lang.random.R; import org.nutz.lang.util.NutMap; -import java.util.List; -import java.util.Set; +import java.time.LocalDate; +import java.util.*; import java.util.stream.Collectors; /** @@ -47,13 +52,14 @@ public class HealthCheckupProjectServiceImpl extends BaseServiceImpl { - v.setSubjectMoneys(dao().query(HealthCheckupProjectSubjectMoney.class, Cnd.where("subjectId", "=", v.getId()))); + v.setSubjectMoneys(dao().query(HealthCheckupProjectSubjectMoney.class, Cnd.where("subjectId", "=", v.getId()).asc("serialNumber"))); }); return project; } @Override + @org.nutz.ioc.aop.Aop(org.nutz.aop.interceptor.ioc.TransAop.READ_COMMITTED) public void addHealthCheckupUser(HealthCheckupProject healthCheckupProject) { List needAddUsers = getHealthCheckupUserListByProject(healthCheckupProject); manyAddOrRenewUtil.asyncExecuteFastInsert(needAddUsers, null); @@ -86,12 +92,29 @@ public class HealthCheckupProjectServiceImpl extends BaseServiceImpl !sourceSelectionUserIds.contains(v.getUserId())) .collect(Collectors.toList()); - List userSelectionIds = userList.stream().filter(needDeleteUserIds::contains).map(HealthCheckupUser::getId).collect(Collectors.toList()); - dao().clear(HealthCheckupUser.class, Cnd.where("userId", "in", needDeleteUserIds)); - dao().clear(HealthCheckupUserSelection.class, Cnd.where("selectUserId", "in", needDeleteUserIds)); - dao().clear(HealthCheckupUserCompanion.class, Cnd.where("userSelectionId", "in", userSelectionIds)); + // 更新名单仅清理当前项目,并使用真实选择记录主键清理家属,不能影响其他年度。 + if (!needDeleteUserIds.isEmpty()) { + List removed = dao().query(HealthCheckupUserSelection.class, + Cnd.where("projectId", "=", healthCheckupProject.getId()).and("selectUserId", "in", needDeleteUserIds)); + List selectionIds = removed.stream().map(HealthCheckupUserSelection::getId).collect(Collectors.toList()); + if (!selectionIds.isEmpty()) { + dao().clear(HealthCheckupUserCompanion.class, Cnd.where("userSelectionId", "in", selectionIds)); + } + dao().clear(HealthCheckupUserSelection.class, Cnd.where("projectId", "=", healthCheckupProject.getId()).and("selectUserId", "in", needDeleteUserIds)); + dao().clear(HealthCheckupUser.class, Cnd.where("projectId", "=", healthCheckupProject.getId()).and("userId", "in", needDeleteUserIds)); + } manyAddOrRenewUtil.asyncExecuteFastInsert(needInsertSelectionUsers, null); +// Sql updateSql = Sqls.create(""" +// update health_checkup_user cu +// left join health_checkup_project p on cu.projectId=p.id +// left join sys_user u on cu.userId=u.id +// set cu.phone=if(cu.phone is null,u.mobile,cu.phone),cu.card=u.idCard,cu.marriage=u.marriage +// ,cu.personType=(case when p.name like '%在职教职工%' then '在职教职工' when p.name like '%校聘高知%' then '校聘高知保健对象' else '' end) +// where cu.projectId=@projectId2 and cu.confirmStatus!='1' +// """); +// updateSql.setParam("projectId2", healthCheckupProject.getId()); +// dao().execute(updateSql); } @@ -108,6 +131,11 @@ public class HealthCheckupProjectServiceImpl extends BaseServiceImpl=", start.toString()).and("selectTime", "<=", end.toString()); + lastYearCndSelection.where().andNotIsNull("selectTime"); + lastYearCndSelection.desc("selectTime"); + List lastYearSelections = dao().query(HealthCheckupUserSelection.class, lastYearCndSelection); + if(CollectionUtil.isNotEmpty(lastYearSelections)) { + Cnd cnd = Cnd.NEW(); + cnd.and("id","=",lastYearSelections.get(0).getSubjectId()); + HealthCheckupProjectSubject projectSubject = dao().fetch(HealthCheckupProjectSubject.class, cnd); + if(ObjectUtil.isNotEmpty(projectSubject)) { + return projectSubject.getOptionName(); + } + } + } + return null; + } } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupSingleServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupSingleServiceImpl.java index 57e911ad..89c14457 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupSingleServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/healthCheckup/service/impl/HealthCheckupSingleServiceImpl.java @@ -1,11 +1,21 @@ package com.budwk.app.zhgh.dayofficework.healthCheckup.service.impl; import com.budwk.app.base.page.Pagination; +import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupActualStatistics; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.base.constant.RoleConstant; +import org.nutz.ioc.aop.Aop; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.json.Json; +import java.util.LinkedHashSet; +import java.util.Set; import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.base.utils.StringUtil; import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupProject; import com.budwk.app.zhgh.dayofficework.healthCheckup.model.HealthCheckupProjectSubject; import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupProjectService; import com.budwk.app.zhgh.dayofficework.healthCheckup.service.HealthCheckupSingleService; +import org.apache.commons.lang3.StringUtils; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; import org.nutz.dao.Sqls; @@ -29,17 +39,92 @@ public class HealthCheckupSingleServiceImpl extends BaseServiceImpl keys = new LinkedHashSet<>(); + keys.add("__total__"); + dao().query(HealthCheckupProjectSubject.class, Cnd.where("projectId", "=", projectId)) + .forEach(subject -> keys.add(subject.getId())); + // 要求整行提交且医院仍属于当前项目,防止跨项目写入或医院变更后漏存。 + if (values == null || !keys.equals(values.keySet())) { + throw new IllegalArgumentException("医院选项已变化或人数未填全,请刷新后重新录入"); + } + for (String key : keys) { + Object value = values.get(key); + if (value == null || !value.toString().matches("[0-9]+")) { + throw new IllegalArgumentException("人数必须为非负整数"); + } + try { + values.put(key, Integer.valueOf(value.toString())); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("人数超出允许范围"); + } + } + // 在任何写入之前校验医院合计;用long累加,避免多个合法整数相加溢出。 + long hospitalTotal = 0L; + for (String key : keys) { + if (!"__total__".equals(key)) { + hospitalTotal += values.getInt(key); + } + } + if (hospitalTotal > values.getInt("__total__")) { + throw new IllegalArgumentException("各医院人数合计不能大于本次体检人数"); + } + // 校验整行通过后统一保存,总人数允许大于医院合计。 + + for (String key : keys) { + HealthCheckupActualStatistics item = dao().fetch(HealthCheckupActualStatistics.class, + Cnd.where("projectId", "=", projectId).and("subjectId", "=", key)); + if (item == null) { + item = new HealthCheckupActualStatistics(); + item.setProjectId(projectId); + item.setSubjectId(key); + item.setActualCount(values.getInt(key)); + dao().insert(item); + } else { + item.setActualCount(values.getInt(key)); + dao().update(item); + } + } + return values; + } + @Override public NutMap pageData(String projectId, String unionId) { HealthCheckupProject project = healthCheckupProjectService.findOne(projectId); Sql sql = Sqls.create(""" SELECT su.id, - su.name unionName, - (SELECT count( 1 ) FROM `health_checkup_user` hcu WHERE hcu.projectId=@projectId and hcu.unionId = su.id ) sumCount + su.name unionName, + (SELECT count( 1 ) FROM `health_checkup_user` hcu WHERE hcu.projectId=@projectId and hcu.unionId = su.id ) sumCount FROM - sys_union su - $condition + sys_union su + $condition """).setParam("projectId", projectId); Cnd cnd = Cnd.NEW(); cnd.andEX("su.id", "=", unionId); @@ -47,6 +132,7 @@ public class HealthCheckupSingleServiceImpl extends BaseServiceImpl healthCheckupList = listMap(sql); + //该体检项目下的套餐 List subjectList = project.getHealthCheckupProjectSubjects(); @@ -54,20 +140,23 @@ public class HealthCheckupSingleServiceImpl extends BaseServiceImpl userSelectList = this.getUserSelectionByProjectId(projectId); for (NutMap healthCheckup : healthCheckupList) { - List thisUnionSelectList = userSelectList.stream().filter(x -> - x.getString("unionId").equals(healthCheckup.getString("id")) && - x.getString("projectId").equals(projectId)).collect(Collectors.toList()); + List thisUnionSelectList = userSelectList.stream() + .filter(x -> + x.getString("unionId").equals(healthCheckup.getString("id")) + && x.getString("projectId").equals(projectId) + ) + .collect(Collectors.toList()); subjectList.forEach(o -> { //每一项选择的人数 Cnd optionCountCnd = Cnd.NEW(); Sql optionCountSql = Sqls.create(""" SELECT - COUNT(*) + COUNT(*) FROM - `health_checkup_user_selection` hs - LEFT JOIN health_checkup_user hcu ON hcu.userId = hs.selectUserId - AND hcu.projectId = @projectId + `health_checkup_user_selection` hs + LEFT JOIN health_checkup_user hcu ON hcu.userId = hs.selectUserId + AND hcu.projectId = @projectId $condition """).setParam("projectId", projectId); optionCountCnd.andEX("hcu.unionId", "=", healthCheckup.getString("id")); @@ -107,11 +196,11 @@ public class HealthCheckupSingleServiceImpl extends BaseServiceImpl receivePageDataColumns(String projectId) { List labelList = new ArrayList<>(); @@ -145,19 +233,19 @@ public class HealthCheckupSingleServiceImpl extends BaseServiceImpl { - this.tableLoading = false + return this.$axios.post(address, data ? data : this.pageForm).then((res) => { if (res.code === 0) { this.tableData = res.data.list this.pageForm.totalCount = res.data.totalCount } + }).finally(() => { + // 查询失败也释放表格遮罩,供体检等复用此 mixin 的页面统一处理。 + this.tableLoading = false }) }, notifySuccess(msg) { diff --git a/src/main/resources/static/assets/platform/js/util/h5PopupHistory.js b/src/main/resources/static/assets/platform/js/util/h5PopupHistory.js new file mode 100644 index 00000000..baaaa66f --- /dev/null +++ b/src/main/resources/static/assets/platform/js/util/h5PopupHistory.js @@ -0,0 +1,126 @@ +/** + * H5 弹框历史管理:一层可见弹框对应一条历史;关闭和跳转均等待历史回退完成。 + * 页面通过 healthCheckupHistory 显式接入,其他业务页保持现有导航行为。 + */ +(() => { + const entries = []; + let pending = null; + let root = null; + let sequence = 0; + let syncing = false; + const marker = '__h5Overlay'; + const session = Date.now() + '-' + Math.random(); + const closeEntries = (depth) => { + syncing = true; + while (entries.length > depth) { + const entry = entries.pop(); + entry.close(); + } + syncing = false; + }; + const backTo = (depth) => { + if (pending) return pending.promise.then(() => backTo(depth)); + const count = entries.length - depth; + if (count <= 0) return Promise.resolve(); + let resolve; + const promise = new Promise(done => { resolve = done; }); + pending = {promise, resolve}; + window.history.go(-count); + return promise; + }; + const manager = { + // key 标识具体弹框;close 同步关闭其 UI;返回 Promise 在历史状态稳定后结束。 + open(key, close) { + if (pending) return pending.promise.then(() => manager.open(key, close)); + if (entries.some(entry => entry.key === key)) return Promise.resolve(); + entries.push({key, close}); + const state = Object.assign({}, window.history.state || {}); + state[marker] = {session, depth: entries.length}; + window.history.pushState(state, '', window.location.href); + return Promise.resolve(); + }, + close(key) { + if (syncing) return Promise.resolve(); + const index = entries.findIndex(entry => entry.key === key); + // 下层弹框主动关闭时一并清理其上方弹框,防止留下孤立历史。 + return index < 0 ? Promise.resolve() : backTo(index); + }, + clear() { return backTo(0); }, + back() { + return entries.length ? backTo(entries.length - 1) : Promise.resolve().then(() => historyBack()); + } + }; + window.H5PopupHistory = manager; + // 捕获阶段消费弹框历史,避免 jquery.pjax 把同页历史当成业务页面跳转。 + window.addEventListener('popstate', event => { + const state = event.state && event.state[marker]; + if (!entries.length && !pending && !state) return; + event.stopImmediatePropagation(); + const depth = state && state.session === session ? Math.min(state.depth, entries.length) : 0; + closeEntries(depth); + const waiting = pending; + pending = null; + if (waiting) waiting.resolve(); + // 前进到已关闭弹框的历史时不重新打开;去掉旧标记,保持页面状态一致。 + if (state && !entries.length) { + const clean = Object.assign({}, event.state); + delete clean[marker]; + window.history.replaceState(clean, '', window.location.href); + } + }, true); + Vue.mixin({ + created() { + if (this.$options.healthCheckupHistory) root = this; + if (!this.$root.$options.healthCheckupHistory) return; + const name = (this.$options.name || '').toLowerCase().replace(/-/g, ''); + if (!['vanpopup', 'vandialog'].includes(name)) return; + // 只登记最外层弹框,避免 Dialog 内部的 Popup 重复增加历史。 + let parent = this.$parent; + while (parent && parent !== this.$root) { + const parentName = (parent.$options.name || '').toLowerCase().replace(/-/g, ''); + if (['vanpopup', 'vandialog'].includes(parentName)) return; + parent = parent.$parent; + } + const key = 'component-' + (++sequence); + this._overlayKey = key; + this._unwatchOverlay = this.$watch('value', value => { + if (value) { + manager.open(key, () => this.$emit('input', false)).then(() => { + if (!this.value || this._isDestroyed) manager.close(key); + }); + } else manager.close(key); + }, {immediate: true}); + }, + beforeDestroy() { + if (this._unwatchOverlay) this._unwatchOverlay(); + if (this._overlayKey) manager.close(this._overlayKey); + if (root === this) { + root = null; + manager.clear(); + } + } + }); + // PJAX 替换 DOM 不会自动销毁 Vue 实例;主动注销页面及其弹框监听。 + $(document).on('pjax:beforeReplace.healthCheckupHistory', () => { + if (root && !root._isDestroyed) root.$destroy(); + }); + window.healthCheckupHistoryMixin = { + methods: { + historyBack() { return manager.back(); }, + navigateHealthCheckup(url, data = null) { + return manager.clear().then(() => pjaxReplace(url, data)); + }, + // options 是 Vant 确认框配置;只在用户确认且弹框历史已清理后 resolve。 + $healthConfirm(options) { + const key = 'confirm-' + (++sequence); + return manager.open(key, () => vant.Dialog.close()).then(() => { + return vant.Dialog.confirm(options).then(value => { + return manager.close(key).then(() => value); + }, error => { + return manager.close(key).then(() => Promise.reject(error)); + }); + }); + } + } + }; +})(); diff --git a/src/main/resources/views/layouts/platform_h5.html b/src/main/resources/views/layouts/platform_h5.html index 3b723f12..9031b193 100644 --- a/src/main/resources/views/layouts/platform_h5.html +++ b/src/main/resources/views/layouts/platform_h5.html @@ -76,6 +76,7 @@ > + +
+ + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/listMange/addUser.js b/src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/listMange/addUser.js new file mode 100644 index 00000000..636ffd23 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/listMange/addUser.js @@ -0,0 +1,91 @@ +const addHealthCheckupUser = { + template: "#health-checkup-add-user-template", + mixins: [initTableMixins], + data() { + return { + visible: false, + pageDataUrl: "/platform/healthCheckup/list/mange/candidatePageData", + pageForm: { + searchKeyword: null, + sex: null, + birthday: null, + birthMonths: [], + unionId: null, + unitIds: [], + personTypes: [], + preparedBys: [], + userStates: [], + isMember: null, + memberFeePaid: null + }, + sexOptions: ["男", "女"], + unionOptions: [], + unitOptions: [], + tableColumns: [ + { prop: "loginname", label: "工号" }, + { prop: "username", label: "姓名" }, + { prop: "sex", label: "性别", sortable: true, checked: 0 }, + { prop: "birthday", label: "出生日期", sortable: true, checked: 0 }, + { prop: "personType", label: "人员类型", sortable: true }, + { prop: "preparedBy", label: "编制类别", sortable: true }, + { prop: "userState", label: "在职状态", sortable: true }, + { prop: "unionName", label: "所属工会", sortable: true }, + { prop: "unitName", label: "所属单位", sortable: true } + ] + } + }, + methods: { + onCancel() { + // 关闭新增人员弹框,保留现有提交中禁用取消按钮的规则。 + this.$set(this, "visible", false); + }, + // 每次打开绑定目标项目并清空业务筛选,查询和分页由 mixin 负责。 + onOpen(id) { + if (!id) { + this.notifyWarning("请先选择体检项目"); + return; + } + this.$set(this, "visible", true); + this.$set(this, "tableData", []); + const defaults = addHealthCheckupUser.data().pageForm; + Object.keys(defaults).forEach(key => this.$set(this.pageForm, key, defaults[key])); + this.$set(this.pageForm, "projectId", id); + this.$businessTool.listUnion().then(rows => { this.unionOptions = rows; }); + this.unionIdChange(null); + this.doSearch(); + }, + // 工会切换后清空旧单位,防止保留不属于当前工会的筛选条件。 + unionIdChange(id) { + this.$set(this.pageForm, "unitIds", []); + return this.$businessTool.listUnit(id).then(rows => { this.unitOptions = rows; }); + }, + onSubmit() { + if (this.formLoading || this.tableLoading) return; + this.formLoading = true; + // 先按最新输入刷新预览,冻结本次筛选,确认后添加全部匹配人员而非当前页。 + const params = JSON.parse(JSON.stringify(this.pageForm)); + this.$set(this.pageForm, "totalCount", 0); + return this.pageData(params).then(() => { + if (!this.pageForm.totalCount) { + this.notifyWarning("当前筛选没有可添加人员"); + return; + } + return this.$confirm("当前筛选出" + this.pageForm.totalCount + "人,确认全部添加到体检名单并补入参与人员范围吗?", "提示", { + confirmButtonText: "确定", cancelButtonText: "取消", type: "warning" + }).then(() => { + return this.$axios.post("/platform/healthCheckup/list/mange/addUsers", params).then(res => { + if (res.code === 0) { + this.notifySuccess(res.msg); + this.$set(this, "visible", false); + this.$emit("refresh"); + } else { + this.notifyError(res.msg); + } + }); + }); + }).catch(error => { + if (error !== "cancel" && error !== "close") this.notifyError("添加未完成,请刷新后重试"); + }).finally(() => { this.formLoading = false; }); + } + } +}; diff --git a/src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/listMange/index.html b/src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/listMange/index.html index eb8cabd7..818ee88f 100644 --- a/src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/listMange/index.html +++ b/src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/listMange/index.html @@ -1,7 +1,12 @@ - - +
@@ -20,6 +25,9 @@ layout("/layouts/platform.html"){ value-format="yyyy"> + + + - - + + + + + + + + + + - 导入名单 + + 全部 + 已选择 + 未选择 + + 问题反馈 + 添加人员 + + 导入名单 + + 导入体检报告 + + 导出 确认名单 @@ -68,6 +112,12 @@ layout("/layouts/platform.html"){ 取消确认 + @@ -106,13 +156,24 @@ layout("/layouts/platform.html"){ @@ -126,10 +187,10 @@ layout("/layouts/platform.html"){ :close-on-click-modal="false"> - + - + --> - 取消 + 取消 确定 + + + + + + + + 取消 + 确定 + + + + + + + + + + 取消 + 保存 + + + + + + + + + + + + +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/projectMange/index.html b/src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/projectMange/index.html index 1283eaae..cff814ff 100644 --- a/src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/projectMange/index.html +++ b/src/main/resources/views/platform/zhgh/dayofficework/healthCheckup/projectMange/index.html @@ -1,8 +1,6 @@ - -