diff --git a/src/main/java/com/budwk/app/flow/handler/FlowRecipientUnitSchoolLeaderHandler.java b/src/main/java/com/budwk/app/flow/handler/FlowRecipientUnitSchoolLeaderHandler.java index 4dab4bd..dd0bb2b 100644 --- a/src/main/java/com/budwk/app/flow/handler/FlowRecipientUnitSchoolLeaderHandler.java +++ b/src/main/java/com/budwk/app/flow/handler/FlowRecipientUnitSchoolLeaderHandler.java @@ -41,6 +41,11 @@ public class FlowRecipientUnitSchoolLeaderHandler implements AssignmentHandler { throw new BaseException("未找到申请记录。"); } unitId = condolence.getHelpUnitId(); + } else if ("TSWW".equals(processName)) { + com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence info = dao.fetch( + com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence.class, businessNo); + if (info == null) throw new BaseException("未找到申请记录。"); + unitId = info.getHelpUnitId(); } else { throw new BaseException("当前流程不支持获取受助人所在单位分管校领导。"); } diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpApprovalController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpApprovalController.java index 5c921ee..d82575b 100644 --- a/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpApprovalController.java +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/difficulthelp/controller/DifficultHelpApprovalController.java @@ -55,8 +55,12 @@ public class DifficultHelpApprovalController { if (StrUtil.isBlank(args.getStr("tf_opinion"))) throw new BaseException("请填写审批意见"); String level = args.getStr("level"); - Double money = amountApproval ? args.getDouble("money") : null; - if (amountApproval) { + Integer submitType = args.getInt(FlowConst.SUBMIT_TYPE); + boolean skipAmount = "36ebafda-44c2-4bd3-bd7f-10839a575a0d".equals(task.getTaskName()) + && (ProcessSubmitTypeEnum.REJECT.getCode().equals(submitType) + || ProcessSubmitTypeEnum.ROLLBACK_TO_OPERATOR.getCode().equals(submitType)); + Double money = amountApproval && !skipAmount ? args.getDouble("money") : null; + if (amountApproval && !skipAmount) { if (StrUtil.isBlank(level) || money == null || !Double.isFinite(money) || money < 0) { throw new BaseException("请填写完整的级别和帮扶金额"); } diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceApplyController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceApplyController.java new file mode 100644 index 0000000..dfe97fd --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceApplyController.java @@ -0,0 +1,251 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.dev33.satoken.annotation.SaCheckRole; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.result.Result; +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.engine.FlowEngine; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.flow.entity.ProcessTask; +import com.budwk.app.flow.enums.ProcessSubmitTypeEnum; +import com.budwk.app.flow.service.FlowCommonService; +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.democratic.suggestionBox.models.SuggestionBox; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService; +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.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.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import java.util.List; + +/** + * @ClassName SpecialCondolenceApplyController + * @Author JyuHsin + * @Date 2025/8/20 15:40 + * @Version 1.0 + * @Description TODO + */ +@SaCheckRole("BRANCH_UNION_CHAIRMAN") +@IocBean +@At("/platform/special_condolence/apply") +@Api("特殊慰问申请") +@Ok("json:full") +public class SpecialCondolenceApplyController { + + @Inject + private Dao dao; + @Inject + private FlowEngine flowEngine; + @Inject + private SpecialCondolenceService specialcondolenceService; + @Inject + private FlowCommonService flowCommonService; + + @At("/") + @Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/apply/index.html") + @SaCheckPermission("special_condolence.apply") + public void index() {} + + @At("/h5") + @Ok("beetl:/platform/zhghh5/staffbenefit/specialcondolence/apply/index.html") + @SaCheckPermission("h5.special_condolence.apply") + public void h5Index() {} + + @At + @ApiOperation("保存申请") + @SaCheckPermission(value = {"special_condolence.apply", "h5.special_condolence.apply"}, mode = SaMode.OR) + @SLog(tag = "特殊慰问系统-慰问申请", msg = "保存申请") + public Result save(@Param("data") SpecialCondolence specialcondolence) { + if(StrUtil.isBlank(specialcondolence.getId())) specialcondolence.setCreateTime(DateUtil.now()); + prepareApplication(specialcondolence); + specialcondolenceService.saveApplication(specialcondolence); + return Result.success(); + } + + @At + @ApiOperation("提交申请") + @SaCheckPermission(value = {"special_condolence.apply", "h5.special_condolence.apply"}, mode = SaMode.OR) + @SLog(tag = "特殊慰问系统-慰问申请", msg = "提交申请") + @Aop(TransAop.READ_COMMITTED) + public Result submit(@Param("data") SpecialCondolence specialcondolence) { + if (StrUtil.isBlank(specialcondolence.getRemark()) || specialcondolence.getRemark().trim().length() > 500) throw new com.budwk.app.base.exception.BaseException("请填写500字以内的申请事由"); + if (StrUtil.isBlank(specialcondolence.getSignature())) throw new com.budwk.app.base.exception.BaseException("请完成申请人签字"); + if(StrUtil.isBlank(specialcondolence.getId())) specialcondolence.setCreateTime(DateUtil.now()); + prepareApplication(specialcondolence); + specialcondolenceService.saveApplication(specialcondolence); + // 开启流程实例 + Dict args = Dict.create(); + args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.APPLY.getCode()); + args.set(FlowConst.FORM_DATA, specialcondolence); + ProcessInstance instance = flowEngine.startProcessInstanceByKey("TSWW", specialcondolence.getId(), SecurityUtil.getUserId(), args); + + // 自动完成第一个申请任务 + List doingTaskList = flowEngine.processTaskService().getDoingTaskList(instance.getId(), null); + for (ProcessTask task : doingTaskList) { + flowEngine.executeProcessTask(task.getId(), SecurityUtil.getUserId(), args); + } + return Result.success(); + } + + @At + @ApiOperation("重新提交申请") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission(value = {"special_condolence.apply", "h5.special_condolence.apply"}, mode = SaMode.OR) + public Result submitAgain(@Param("data") SpecialCondolence specialcondolence, @Param("taskId") Long taskId) { + if (StrUtil.isBlank(specialcondolence.getRemark()) || specialcondolence.getRemark().trim().length() > 500) throw new com.budwk.app.base.exception.BaseException("请填写500字以内的申请事由"); + if (StrUtil.isBlank(specialcondolence.getSignature())) throw new com.budwk.app.base.exception.BaseException("请完成申请人签字"); + ProcessTask task = taskId == null ? null : dao.fetch(ProcessTask.class, taskId); + ProcessInstance instance = task == null ? null : dao.fetch(ProcessInstance.class, task.getProcessInstanceId()); + if (instance == null || !StrUtil.equals(instance.getBusinessNo(), specialcondolence.getId()) + || !"startTask".equals(task.getTaskName()) || !SecurityUtil.getUserId().equals(instance.getOperator())) { + throw new com.budwk.app.base.exception.BaseException("申请任务不匹配"); + } + prepareApplication(specialcondolence); + specialcondolenceService.saveApplication(specialcondolence); + + Dict dict = Dict.create(); + dict.set(FlowConst.PROCESS_TASK_ID_KEY, taskId); + dict.set(FlowConst.FORM_DATA, specialcondolence); + dict.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.RE_APPLY.getCode()); + flowCommonService.executeTask(dict); + return Result.success(); + } + + @At + @ApiOperation("查询用户") + @SaCheckPermission(value = {"special_condolence.apply", "h5.special_condolence.apply"}, mode = SaMode.OR) + public Object listUser(String keyword) { + Sql sql = Sqls.create(""" + select + u.id, + u.idCard, + u.personType, + bank.bankOfDeposit, + bank.bankUserName, + bank.bankCardNumber, + username as userName, + loginname as loginName, + sex, + mobile, + technicalTitle, + IFNULL(unitname, '暂无') as unitName, + unitid as unitId, + unionid as unionId, + unionname as unionName + from + vw_user u + LEFT JOIN ( + SELECT idCard, bankOfDeposit, bankUserName, bankCardNumber, + ROW_NUMBER() OVER (PARTITION BY idCard ORDER BY createdAt DESC, id DESC) rn + FROM special_condolence_recipient WHERE delFlag = false + ) bank ON bank.idCard = u.idCard AND bank.rn = 1 AND u.idCard <> '' + $condition + """); + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(keyword)) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or(View_user::getLoginname, "like", "%" + keyword + "%"); + seg.or(View_user::getUsername, "like", "%" + keyword + "%"); + cnd.and(seg); + } + if (StrUtil.isBlank(SecurityUtil.getUnionId())) throw new com.budwk.app.base.exception.BaseException("申请人未关联分工会"); + cnd.and("u.unionId", "=", SecurityUtil.getUnionId()); + sql.setCondition(cnd); + Pagination pagination = specialcondolenceService.listPageMap(1, 50, sql); + return Result.success(pagination.getList()); + } + + @At + @Ok("void") + @SaCheckPermission(value = {"special_condolence.apply", "h5.special_condolence.apply"}, mode = SaMode.OR) + public void importTemplate(javax.servlet.http.HttpServletResponse response) throws Exception { + try (java.io.InputStream input = getClass().getResourceAsStream("/templates/special_condolence/special_condolence_import.xlsx")) { + if (input == null) throw new com.budwk.app.base.exception.BaseException("导入模板不存在"); + com.budwk.app.base.utils.CommonDownloadUtil.download("特殊慰问导入模板.xlsx", input.readAllBytes(), response); + } + } + + @At + @SaCheckPermission(value = {"special_condolence.apply", "h5.special_condolence.apply"}, mode = SaMode.OR) + @org.nutz.mvc.annotation.AdaptBy(type = org.nutz.mvc.upload.UploadAdaptor.class, args = {"ioc:fileUpload"}) + public Result importRecipients(@Param("file") org.nutz.mvc.upload.TempFile file) throws Exception { + if (file == null) throw new com.budwk.app.base.exception.BaseException("请选择Excel文件"); + if (!file.getSubmittedFileName().toLowerCase(java.util.Locale.ROOT).matches(".*\\.(xlsx|xls)$")) throw new com.budwk.app.base.exception.BaseException("仅支持xlsx、xls文件"); + String[] headers = {"慰问对象", "工号", "身份证号码", "开户行", "户名", "收款账户"}; + String[] fields = {"helpUserName", "helpLoginName", "idCard", "bankOfDeposit", "bankUserName", "bankCardNumber"}; + java.util.List result = new java.util.ArrayList<>(); + try (java.io.InputStream input = new java.io.FileInputStream(file.getFile()); + org.apache.poi.ss.usermodel.Workbook workbook = org.apache.poi.ss.usermodel.WorkbookFactory.create(input)) { + if (workbook.getNumberOfSheets() == 0) throw new com.budwk.app.base.exception.BaseException("Excel中没有工作表"); + org.apache.poi.ss.usermodel.Sheet sheet = workbook.getSheetAt(0); + org.apache.poi.ss.usermodel.DataFormatter formatter = new org.apache.poi.ss.usermodel.DataFormatter(); + org.apache.poi.ss.usermodel.Row header = sheet.getRow(0); + for (int c = 0; c < headers.length; c++) { + if (header == null || !headers[c].equals(formatter.formatCellValue(header.getCell(c)).trim())) throw new com.budwk.app.base.exception.BaseException("表头不正确,请下载导入模板"); + } + if (sheet.getLastRowNum() > 1000) throw new com.budwk.app.base.exception.BaseException("最多导入1000行"); + for (int r = 1; r <= sheet.getLastRowNum(); r++) { + org.apache.poi.ss.usermodel.Row excelRow = sheet.getRow(r); + if (excelRow == null) continue; + cn.hutool.json.JSONObject row = new cn.hutool.json.JSONObject(); + boolean empty = true; + for (int c = 0; c < fields.length; c++) { + org.apache.poi.ss.usermodel.Cell cell = excelRow.getCell(c); + String value = formatter.formatCellValue(cell).trim(); + if (c != 1 && cell != null && cell.getCellType() == org.apache.poi.ss.usermodel.CellType.FORMULA) throw new com.budwk.app.base.exception.BaseException("第" + (r + 1) + "行不支持公式,请填写实际值"); + if ((c == 2 || c == 5) && cell != null && cell.getCellType() == org.apache.poi.ss.usermodel.CellType.NUMERIC) throw new com.budwk.app.base.exception.BaseException("第" + (r + 1) + "行工号、身份证和收款账户请使用文本格式,避免数字失真"); + row.set(fields[c], value); + empty = empty && value.isEmpty(); + } + if (empty) continue; + for (int c = 0; c < fields.length; c++) { + if (c != 1 && row.getStr(fields[c]).isEmpty()) throw new com.budwk.app.base.exception.BaseException("第" + (r + 1) + "行:请填写" + headers[c]); + } + if (!com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceRecipients.validIdCard(row.getStr("idCard"))) throw new com.budwk.app.base.exception.BaseException("第" + (r + 1) + "行身份证号码格式不正确"); + if (!row.getStr("bankCardNumber").matches("[0-9]{6,30}")) throw new com.budwk.app.base.exception.BaseException("第" + (r + 1) + "行收款账户格式不正确"); + com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceRecipients.resolveUser(row, dao, "第" + (r + 1) + "行:"); + result.add(row); + } + } + if (result.isEmpty()) throw new com.budwk.app.base.exception.BaseException("没有可导入的数据"); + return Result.success(result); + } + + private void prepareApplication(SpecialCondolence info) { + if (StrUtil.isNotBlank(info.getId())) { + SpecialCondolence existing = dao.fetch(SpecialCondolence.class, info.getId()); + if (existing == null || !SecurityUtil.getUserId().equals(existing.getCreatedBy())) { + throw new com.budwk.app.base.exception.BaseException("只能修改本人申请"); + } + info.setCreatedBy(existing.getCreatedBy()); + } + info.setApplyUserId(SecurityUtil.getUserId()); + info.setApplyUserName(SecurityUtil.getUserUsername()); + info.setApplyLoginName(SecurityUtil.getUserLoginname()); + info.setApplyUnionId(SecurityUtil.getUnionId()); + info.setApplyUnitId(SecurityUtil.getUnitId()); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceApprovalController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceApprovalController.java new file mode 100644 index 0000000..85e9f63 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceApprovalController.java @@ -0,0 +1,60 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.exception.BaseException; +import com.budwk.app.base.result.Result; +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.flow.entity.ProcessTask; +import com.budwk.app.flow.service.FlowCommonService; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Dao; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.json.Json; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +@IocBean +@Ok("json") +@At("/platform/special_condolence/approval") +public class SpecialCondolenceApprovalController { + + @Inject + private Dao dao; + @Inject + private FlowCommonService flowCommonService; + + @At + @SaCheckLogin + @Aop(TransAop.READ_COMMITTED) + public Result executeTask(@Param("data") String data) { + Dict args = Json.fromJson(Dict.class, data); + if (args == null || args.getLong(FlowConst.PROCESS_TASK_ID_KEY) == null) { + throw new BaseException("审批任务不能为空"); + } + ProcessTask task = dao.fetch(ProcessTask.class, args.getLong(FlowConst.PROCESS_TASK_ID_KEY)); + if (task == null) throw new BaseException("审批任务不存在"); + if (!"c438972e-2f67-4907-b229-cb7aa17da147".equals(task.getTaskName()) + && !"7f560675-aeea-4254-a57e-957d03d6b786".equals(task.getTaskName()) + && !"af363a4e-fc56-42a0-9906-8c7a2814006b".equals(task.getTaskName())) { + throw new BaseException("当前任务不是特殊慰问审批任务"); + } + ProcessInstance instance = dao.fetch(ProcessInstance.class, task.getProcessInstanceId()); + com.budwk.app.flow.entity.ProcessDefine define = instance == null ? null : dao.fetch(com.budwk.app.flow.entity.ProcessDefine.class, instance.getProcessDefineId()); + SpecialCondolence info = define == null || !"TSWW".equals(define.getName()) ? null : dao.fetch(SpecialCondolence.class, instance.getBusinessNo()); + if (info == null) throw new BaseException("特殊慰问申请不存在"); + if (StrUtil.isBlank(args.getStr("tf_sign"))) throw new BaseException("请完成审批签字"); + if (StrUtil.isBlank(args.getStr("tf_opinion"))) throw new BaseException("请填写审批意见"); + + // 参与者权限由流程引擎校验,业务入口不接受客户端指定管理员代办。 + args.remove(FlowConst.EXT_ENABLE_OPERATOR); + flowCommonService.executeTask(args); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceFourthApprovalController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceFourthApprovalController.java new file mode 100644 index 0000000..17d7c20 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceFourthApprovalController.java @@ -0,0 +1,161 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.constant.RoleConstant; +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.PageUtil; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +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.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +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.List; + +/** + * @ClassName SpecialCondolenceFourthApprovalController + * @Author JyuHsin + * @Date 2025/7/29 16:23 + * @Version 1.0 + * @Description TODO + */ +@IocBean +@At("/platform/special_condolence/fourthApproval") +@Api("特殊慰问四级审核") +@Ok("json:full") +public class SpecialCondolenceFourthApprovalController { + + @Inject + private Dao dao; + @Inject + private SpecialCondolenceService specialcondolenceService; + + @At("/") + @Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/fourthApproval/index.html") + @SaCheckPermission("special_condolence.fourthApproval") + public void index() {} + + @At("/h5") + @Ok("beetl:/platform/zhghh5/staffbenefit/specialcondolence/fourthApproval/index.html") + @SaCheckPermission("h5.special_condolence.fourthApproval") + public void h5Index() {} + + @At + @ApiOperation("分页查询") + @SaCheckPermission(value = {"special_condolence.fourthApproval", "h5.special_condolence.fourthApproval"}, mode = SaMode.OR) + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "type") String type, + @Param(value = "unionId") String unionId, + @Param(value = "unitId") String unitId, + @Param(value = "approval") Boolean approval) { + Sql sql = Sqls.create(""" + SELECT + info.*, + type.name as typeName, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariable, + ins.processDefineId instanceProcessDefineId, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariable, + IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName, + IF(rt.id IS NOT NULL, 1, 0) AS canRevoke + FROM + wf_process_task t + LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId + LEFT JOIN special_condolence info ON info.id = ins.businessNo + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + LEFT JOIN special_condolence_type type ON info.type = type.id + LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10 + LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10 + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("info.id", "is not", null); + cnd.and(new Static(""" + NOT EXISTS ( + SELECT 1 FROM wf_process_task newer + WHERE newer.processInstanceId = t.processInstanceId + AND newer.taskName = t.taskName + AND newer.id > t.id + ) + """)); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or(SpecialCondolence::getHelpUserName, "like", "%" + pageForm.getSearchKeyword() + "%"); + seg.or(SpecialCondolence::getHelpLoginName, "like", "%" + pageForm.getSearchKeyword() + "%"); + cnd.and(seg); + } + cnd.andEX("info.type", "=", type); + cnd.andEX("YEAR(info.createTime)", "=", year); + cnd.andEX("info.applyUnionId", "=", unionId); + cnd.andEX("info.applyUnitId", "=", unitId); + + cnd.and("t.taskName", "=", "af363a4e-fc56-42a0-9906-8c7a2814006b"); + if (!"superadmin".equals(SecurityUtil.getUserLoginname()) && !AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name())) { + Sql unitSql = Sqls.queryString(""" + SELECT DISTINCT ur.unitId + FROM sys_user_role ur + INNER JOIN sys_role r ON r.id = ur.roleId + WHERE ur.userId = @userId + AND ur.enable = true + AND r.disabled = false + AND r.code = @roleCode + AND ur.unitId IS NOT NULL + AND ur.unitId <> '' + """); + unitSql.setParam("userId", SecurityUtil.getUserId()); + unitSql.setParam("roleCode", RoleConstant.UNIT_SCHOOL_LEADER.name()); + dao.execute(unitSql); + List managedUnitIds = unitSql.getList(String.class); + if (managedUnitIds.isEmpty()) { + cnd.and(new Static("1 = 0")); + } else { + cnd.and("info.applyUnitId", "in", managedUnitIds); + } + } + + if (approval) { + cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode())); + } else { + cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode()); + } + + if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.desc("info.createTime"); + } else { + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + cnd.groupBy("t.id"); + sql.setCondition(cnd); + Pagination pageVO = specialcondolenceService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pageVO); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceMineController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceMineController.java new file mode 100644 index 0000000..34d5316 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceMineController.java @@ -0,0 +1,296 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.constant.RoleConstant; +import com.budwk.app.base.exception.BaseException; +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.sms.SmsService; +import com.budwk.app.base.utils.PageUtil; +import com.budwk.app.base.utils.CommonDownloadUtil; +import com.budwk.app.base.utils.SysOfficeTemplateUtil; +import com.budwk.app.flow.engine.FlowEngine; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.flow.entity.ProcessTask; +import com.budwk.app.flow.enums.ProcessInstanceStateEnum; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.flow.vo.ProcessTaskVO; +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.staffbenefit.specialcondolence.model.SpecialCondolence; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolenceType; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService; +import com.deepoove.poi.data.PictureRenderData; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +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.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.util.NutMap; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.servlet.http.HttpServletResponse; +import java.io.InputStream; +import java.util.List; + +/** + * @ClassName SpecialCondolenceApplyController + * @Author JyuHsin + * @Date 2025/7/28 11:06 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@At("/platform/special_condolence/mine") +@Api("特殊慰问我的") +@Ok("json:full") +public class SpecialCondolenceMineController { + + @Inject + private SpecialCondolenceService specialcondolenceService; + @Inject + private FlowEngine flowEngine; + @Inject + private SysOfficeTemplateUtil sysOfficeTemplateUtil; + + @At("/") + @Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/mine/index.html") + @SaCheckPermission("special_condolence.mine") + public void index() {} + + @At("/h5") + @Ok("beetl:/platform/zhghh5/staffbenefit/specialcondolence/mine/index.html") + @SaCheckPermission("h5.special_condolence.mine") + public void h5Index() {} + + @At + @ApiOperation("分页查询") + @SaCheckPermission(value = {"special_condolence.mine", "h5.special_condolence.mine"}, mode = SaMode.OR) + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "type") String type) { + Sql sql = Sqls.create(""" + SELECT + info.*, + type.name as typeName, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariable, + ins.processDefineId instanceProcessDefineId, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariable, + IF((SELECT taskName FROM wf_process_task tt WHERE tt.id = t.taskParentId) = 'startTask', 1, 0) canRevoke, + (select MAX(id) from wf_process_task where processInstanceId = ins.id and taskName = 'startTask') AS startTaskId + FROM + special_condolence info + LEFT JOIN special_condolence_type type ON info.type = type.id + LEFT JOIN `wf_process_instance` ins ON ins.businessNo = info.id + LEFT JOIN ( + SELECT + id, + processInstanceId, + taskName, + displayName, + taskType, + performType, + taskState, + finishTime, + taskParentId, + variable, + ROW_NUMBER() OVER (PARTITION BY processInstanceId ORDER BY createdAt DESC, id DESC) AS rn + FROM wf_process_task + WHERE taskState = 10 + ) t ON t.processInstanceId = ins.id AND t.rn = 1 + $condition + """); + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or(SpecialCondolence::getHelpUserName, "like", "%" + pageForm.getSearchKeyword() + "%"); + seg.or(SpecialCondolence::getHelpLoginName, "like", "%" + pageForm.getSearchKeyword() + "%"); + cnd.and(seg); + } + cnd.andEX("year(info.createTime)", "=", year); + cnd.andEX("info.type", "=", type); + cnd.and("info.createdBy", "=", SecurityUtil.getUserId()); + + if (StrUtil.isNotBlank(pageForm.getPageOrderName()) && StrUtil.isNotBlank(pageForm.getPageOrderBy())) { + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } else { + cnd.desc("info.createTime"); + } + + sql.setCondition(cnd); + Pagination pagination = specialcondolenceService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pagination); + } + + @At + @Ok("void") + @ApiOperation("导出特殊慰问申请表") + @SaCheckPermission("special_condolence.mine") + public void doExportApply(String id, HttpServletResponse response, Boolean print) throws Exception { + log.info("[特殊慰问导出] 开始,applyId={}, userId={}, format={}", id, SecurityUtil.getUserId(), Boolean.TRUE.equals(print) ? "PDF" : "Word"); + SpecialCondolence specialcondolence = specialcondolenceService.loadApplication(id); + if (specialcondolence == null) throw new BaseException("该条记录不存在"); + if (!SecurityUtil.getUserId().equals(specialcondolence.getCreatedBy())) { + throw new BaseException("只能导出本人提交的申请"); + } + ProcessInstance instance = specialcondolenceService.dao().fetch(ProcessInstance.class, + Cnd.where("businessNo", "=", id).desc("id")); + if (instance == null || !ProcessInstanceStateEnum.FINISHED.getCode().equals(instance.getState())) { + throw new BaseException("只能导出已完成的申请"); + } + log.info("[特殊慰问导出] 流程已完成,applyId={}, instanceId={}, state={}, applicantSignPresent={}", id, instance.getId(), instance.getState(), StrUtil.isNotBlank(specialcondolence.getSignature())); + NutMap docData = Lang.obj2nutmap(specialcondolence); + docData.put("payUserName", StrUtil.nullToEmpty(specialcondolence.getBankUserName())); + SpecialCondolenceType type = specialcondolenceService.dao().fetch(SpecialCondolenceType.class, specialcondolence.getType()); + docData.put("typeName", type == null ? "" : type.getName()); + docData.put("signature", null); + if (StrUtil.isNotBlank(specialcondolence.getSignature())) { + PictureRenderData signature = sysOfficeTemplateUtil.createPictureRenderData(90, 40, specialcondolence.getSignature()); + if (signature == null) throw new BaseException("申请人签字图片读取失败"); + docData.put("signature", signature); + } + fillApplyApprovals(docData, instance); + for (String field : List.of("signature", "secondApprovalSign", "thirdApprovalSign", "fourthApprovalSign")) { + Object value = docData.get(field); + log.info("[特殊慰问导出] 渲染前图片字段,applyId={}, instanceId={}, field={}, valueType={}", id, instance.getId(), field, value == null ? "null" : value.getClass().getName()); + } + String fileName = "重庆工贸职业技术学院特殊慰问申请表_" + StrUtil.nullToEmpty(specialcondolence.getHelpUserName()); + try (InputStream input = getClass().getResourceAsStream("/templates/condolence/重庆工贸职业技术学院职工慰问申请表.doc")) { + if (input == null) throw new BaseException("特殊慰问申请表模板不存在"); + boolean pdf = Boolean.TRUE.equals(print); + com.aspose.words.Document template = new com.aspose.words.Document(input); + template.getRange().replace("职工慰问", "特殊慰问", new com.aspose.words.FindReplaceOptions()); + com.aspose.words.NodeCollection rows = template.getChildNodes(com.aspose.words.NodeType.ROW, true); + for (int i = rows.getCount() - 1; i >= 0; i--) { + com.aspose.words.Node row = rows.get(i); + if (row.getText().contains("firstApproval") || row.getText().contains("分工会主席")) row.remove(); + } + java.io.ByteArrayOutputStream templateOutput = new java.io.ByteArrayOutputStream(); + template.save(templateOutput, com.aspose.words.SaveFormat.DOCX); + byte[] bytes; + if (specialcondolence.getRecipients() != null && !specialcondolence.getRecipients().isEmpty()) { + com.aspose.words.Document combined = null; + for (cn.hutool.json.JSONObject person : specialcondolence.getRecipients()) { + NutMap personData = new NutMap(); + personData.putAll(docData); + personData.putAll(person); + personData.put("payUserName", person.getStr("bankUserName")); + byte[] rendered = sysOfficeTemplateUtil.renderTemplate(new java.io.ByteArrayInputStream(templateOutput.toByteArray()), personData, null, false, "specialcondolence:" + id); + com.aspose.words.Document part = new com.aspose.words.Document(new java.io.ByteArrayInputStream(rendered)); + if (combined == null) combined = part; + else combined.appendDocument(part, com.aspose.words.ImportFormatMode.KEEP_SOURCE_FORMATTING); + } + java.io.ByteArrayOutputStream output = new java.io.ByteArrayOutputStream(); + combined.save(output, pdf ? com.aspose.words.SaveFormat.PDF : com.aspose.words.SaveFormat.DOCX); + bytes = output.toByteArray(); + } else { + bytes = sysOfficeTemplateUtil.renderTemplate(new java.io.ByteArrayInputStream(templateOutput.toByteArray()), docData, null, pdf, "specialcondolence:" + id); + } + log.info("[特殊慰问导出] 渲染完成,applyId={}, format={}, outputBytes={}", id, pdf ? "PDF" : "Word", bytes.length); + CommonDownloadUtil.download(fileName + (pdf ? ".pdf" : ".docx"), bytes, response); + } catch (Exception e) { + log.error("[特殊慰问导出] 模板渲染或文件输出失败,applyId={}, instanceId={}, format={}", id, instance.getId(), Boolean.TRUE.equals(print) ? "PDF" : "Word", e); + throw e; + } + } + + private void fillApplyApprovals(NutMap docData, ProcessInstance instance) { + String[] taskKeys = {"c438972e-2f67-4907-b229-cb7aa17da147", + "7f560675-aeea-4254-a57e-957d03d6b786", "af363a4e-fc56-42a0-9906-8c7a2814006b"}; + String[] fields = {"secondApproval", "thirdApproval", "fourthApproval"}; + List suffixes = List.of("Opinion", "Sign", "Year", "Month", "Day"); + for (String field : fields) { + for (String suffix : suffixes) docData.put(field + suffix, "Sign".equals(suffix) ? null : ""); + } + List tasks = specialcondolenceService.dao().query(ProcessTask.class, + Cnd.where("processInstanceId", "=", instance.getId()).asc("id")); + log.info("[特殊慰问导出] 查询审批记录,applyId={}, instanceId={}, taskCount={}, expectedTaskKeys={}", instance.getBusinessNo(), instance.getId(), tasks.size(), List.of(taskKeys)); + for (ProcessTask task : tasks) { + ProcessTaskVO taskVO = flowEngine.processTaskService().findById(task.getId()); + log.info("[特殊慰问导出] 审批记录,instanceId={}, taskId={}, taskKey={}, displayName={}, state={}, finishTime={}, isFirstTaskNode={}, matchedApproval={}", instance.getId(), task.getId(), task.getTaskName(), task.getDisplayName(), task.getTaskState(), task.getFinishTime(), taskVO.getExt() == null ? null : taskVO.getExt().get("isFirstTaskNode"), List.of(taskKeys).contains(task.getTaskName())); + if ("startTask".equals(task.getTaskName()) || (!List.of(taskKeys).contains(task.getTaskName()) + && taskVO.getExt() != null && Boolean.TRUE.equals(taskVO.getExt().getBool("isFirstTaskNode")))) { + log.info("[特殊慰问导出] 申请节点重置本轮审批字段,instanceId={}, taskId={}, taskKey={}", instance.getId(), task.getId(), task.getTaskName()); + // 重新申请后,仅导出本轮审批记录。 + for (String field : fields) { + for (String suffix : suffixes) docData.put(field + suffix, "Sign".equals(suffix) ? null : ""); + } + continue; + } + for (int i = 0; i < taskKeys.length; i++) { + if (!taskKeys[i].equals(task.getTaskName())) continue; + for (String suffix : suffixes) docData.put(fields[i] + suffix, "Sign".equals(suffix) ? null : ""); + if (!ProcessTaskStateEnum.FINISHED.getCode().equals(task.getTaskState())) { + log.info("[特殊慰问导出] 跳过未完成审批,instanceId={}, taskId={}, field={}, state={}", instance.getId(), task.getId(), fields[i], task.getTaskState()); + continue; + } + Dict data = taskVO.getExt() == null ? Dict.create() : taskVO.getTaskFormData(); + log.info("[特殊慰问导出] 读取审批表单,instanceId={}, taskId={}, field={}, formKeys={}, signPresent={}, signReferenceLength={}", instance.getId(), task.getId(), fields[i], data.keySet(), StrUtil.isNotBlank(data.getStr("sign")), StrUtil.nullToEmpty(data.getStr("sign")).length()); + if (StrUtil.isBlank(data.getStr("sign"))) log.warn("[特殊慰问导出] 已完成审批缺少签名字段,instanceId={}, taskId={}, field={}", instance.getId(), task.getId(), fields[i]); + docData.put(fields[i] + "Opinion", StrUtil.nullToEmpty(data.getStr("opinion"))); + if (StrUtil.isNotBlank(data.getStr("sign"))) { + PictureRenderData signature = sysOfficeTemplateUtil.createPictureRenderData(90, 40, data.getStr("sign")); + if (signature == null) throw new BaseException("审批签字图片读取失败"); + docData.put(fields[i] + "Sign", signature); + log.info("[特殊慰问导出] 审批签名填充完成,instanceId={}, taskId={}, field={}", instance.getId(), task.getId(), fields[i] + "Sign"); + } + docData.put(fields[i] + "Year", task.getFinishTime() == null ? "" : DateUtil.format(task.getFinishTime(), "yyyy")); + docData.put(fields[i] + "Month", task.getFinishTime() == null ? "" : DateUtil.format(task.getFinishTime(), "M")); + docData.put(fields[i] + "Day", task.getFinishTime() == null ? "" : DateUtil.format(task.getFinishTime(), "d")); + } + } + } + + @At + @ApiOperation("删除") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission(value = {"special_condolence.mine", "h5.special_condolence.mine"}, mode = SaMode.OR) + @SLog(tag = "特殊慰问系统-我的申请", msg = "删除特殊慰问") + public Result delete(@Param("id") String id) { + specialcondolenceService.deleteApplication(id); + flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id); + return Result.success(); + } + + @At + @ApiOperation("查询单个慰问申请信息") + @SaCheckPermission(value = {"special_condolence", "h5.special_condolence"}, mode = SaMode.OR) + public Result info(String id) { + SpecialCondolence specialcondolence = specialcondolenceService.loadApplication(id); + SpecialCondolenceType type = specialcondolenceService.dao().fetch(SpecialCondolenceType.class, Cnd.where(SpecialCondolenceType::getId, "=", specialcondolence.getType())); + NutMap nutMap = Lang.obj2nutmap(specialcondolence); + nutMap.put("typeName", type == null ? "" : type.getName()); + return Result.success(nutMap); + } + @Inject + private SmsService smsService; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceReadController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceReadController.java new file mode 100644 index 0000000..8bc164d --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceReadController.java @@ -0,0 +1,177 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.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 cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.base.constant.RoleConstant; +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.PageUtil; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.sys.param.SysMsgSummaryPageForm; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +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.dao.util.cri.SqlExpressionGroup; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +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 javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.ArrayList; +import java.util.List; + +/** + * @ClassName SpecialCondolenceReadController + * @Author JyuHsin + * @Date 2025/7/29 16:25 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "特殊慰问阅览") +@At("/platform/special_condolence/read") +public class SpecialCondolenceReadController { + + @Inject + private SpecialCondolenceService specialcondolenceService; + + @At("") + @SaCheckPermission("special_condolence.read") + @Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/read/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("special_condolence.read") + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "type") String type, + @Param(value = "unionId") String unionId, + @Param(value = "unitId") String unitId) { + Sql sql = Sqls.create(""" + SELECT + info.*, + ins.id AS instanceId, + type.name as typeName, + ins.state instanceState, + ins.processDefineId instanceProcessDefineId, + t.displayName taskName + FROM + special_condolence info + LEFT JOIN wf_process_instance ins ON ins.businessNo = info.id + LEFT JOIN ( + SELECT + processInstanceId, + displayName, + createdAt, + ROW_NUMBER() OVER (PARTITION BY processInstanceId ORDER BY createdAt DESC) AS rn + FROM wf_process_task + ) t ON t.processInstanceId = ins.id AND t.rn = 1 + LEFT JOIN special_condolence_type type ON info.type = type.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("info.type", "=", type); + cnd.andEX("YEAR(info.createTime)", "=", year); + cnd.andEX("info.applyUnionId", "=", unionId); + cnd.andEX("info.applyUnitId", "=", unitId); + + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or("info.helpUserName", "like", "%" + pageForm.getSearchKeyword() + "%"); + seg.or("info.helpLoginName", "like", "%" + pageForm.getSearchKeyword() + "%"); + cnd.and(seg); + } + + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_CHAIRMAN.name())) { + cnd.and("info.applyUnionId", "=", SecurityUtil.getUnionId()); + } + + if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.desc("info.createTime"); + } else { + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + sql.setCondition(cnd); + Pagination pageVO = specialcondolenceService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pageVO); + } + + @At + @Ok("void") + @SaCheckPermission("special_condolence.read") + @ApiOperation("导出特殊慰问汇总表") + public void onExport(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "type") String type, + @Param(value = "unionId") String unionId, + @Param(value = "unitId") String unitId, + HttpServletResponse response) { + //查询审核通过的数据 + Sql sql = Sqls.create(""" + select + con.*, + type.name as typeName + from + special_condolence con + left join wf_process_instance ins on ins.businessNo = con.id + left join special_condolence_type type on type.id = con.type + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and(ProcessInstance::getState, "=", ProcessTaskStateEnum.FINISHED.getCode()); + cnd.andEX("con.type", "=", type); + cnd.andEX("YEAR(info.createTime)", "=", year); + cnd.andEX("con.applyUnionId", "=", unionId); + cnd.andEX("con.applyUnitId", "=", unitId); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or("info.helpUserName", "like", "%" + pageForm.getSearchKeyword() + "%"); + seg.or("info.helpLoginName", "like", "%" + pageForm.getSearchKeyword() + "%"); + cnd.and(seg); + } + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_CHAIRMAN.name())) { + cnd.and("con.applyUnionId", "=", SecurityUtil.getUnionId()); + } + sql.setCondition(cnd); + List list = specialcondolenceService.listMap(sql); + + List exportEntities = new ArrayList<>(); + exportEntities.add(new ExcelExportEntity("慰问对象", "helpUserName", 20)); + exportEntities.add(new ExcelExportEntity("慰问对象工号", "helpLoginName", 20)); + exportEntities.add(new ExcelExportEntity("申请人", "applyUserName", 20)); + exportEntities.add(new ExcelExportEntity("所在工会", "helpUnionName", 20)); + exportEntities.add(new ExcelExportEntity("所在单位", "helpUnitName", 20)); + exportEntities.add(new ExcelExportEntity("慰问类型", "typeName", 20)); + exportEntities.add(new ExcelExportEntity("拟补贴金额", "money", 20)); + exportEntities.add(new ExcelExportEntity("申请理由", "remark", 20)); + + ExportParams exportParams = new ExportParams(); + exportParams.setType(ExcelType.XSSF); + Workbook workbook = ExcelExportUtil.exportExcel(exportParams, exportEntities, list); + CommonDownloadUtil.download("申报人汇总.xlsx", workbook, response); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceSecondApprovalController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceSecondApprovalController.java new file mode 100644 index 0000000..1fd221a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceSecondApprovalController.java @@ -0,0 +1,133 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +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.utils.PageUtil; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +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.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +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.List; + +/** + * @author zhf + * @date 2025/12/23 14:13 + * @description 校工会预审 + */ +@IocBean +@At("/platform/special_condolence/schoolPrincipalApproval") +@Api("特殊慰问二级审核") +@Ok("json:full") +public class SpecialCondolenceSecondApprovalController { + + @Inject + private SpecialCondolenceService specialcondolenceService; + + @At("/") + @Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/schoolPrincipalApproval/index.html") + @SaCheckPermission("special_condolence.secondApproval") + public void index() {} + + @At("/h5") + @Ok("beetl:/platform/zhghh5/staffbenefit/specialcondolence/schoolPrincipalApproval/index.html") + @SaCheckPermission("h5.special_condolence.secondApproval") + public void h5Index() {} + + @At + @ApiOperation("分页查询") + @SaCheckPermission(value = {"special_condolence.secondApproval", "h5.special_condolence.secondApproval"}, mode = SaMode.OR) + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "type") String type, + @Param(value = "unionId") String unionId, + @Param(value = "unitId") String unitId, + @Param(value = "approval") Boolean approval) { + Sql sql = Sqls.create(""" + SELECT + info.*, + type.name as typeName, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariable, + ins.processDefineId instanceProcessDefineId, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariable, + IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName, + IF(rt.id IS NOT NULL, 1, 0) AS canRevoke + FROM + wf_process_task t + LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId + LEFT JOIN special_condolence info ON info.id = ins.businessNo + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + LEFT JOIN special_condolence_type type ON info.type = type.id + LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10 + LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10 + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("info.id", "is not", null); + cnd.and(new Static(""" + NOT EXISTS ( + SELECT 1 FROM wf_process_task newer + WHERE newer.processInstanceId = t.processInstanceId + AND newer.taskName = t.taskName + AND newer.id > t.id + ) + """)); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or(SpecialCondolence::getHelpUserName, "like", "%" + pageForm.getSearchKeyword() + "%"); + seg.or(SpecialCondolence::getHelpLoginName, "like", "%" + pageForm.getSearchKeyword() + "%"); + cnd.and(seg); + } + cnd.andEX("info.type", "=", type); + cnd.andEX("YEAR(info.createTime)", "=", year); + cnd.andEX("info.applyUnionId", "=", unionId); + cnd.andEX("info.applyUnitId", "=", unitId); + + cnd.and("t.taskName", "=", "c438972e-2f67-4907-b229-cb7aa17da147"); +// cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId())); + + if (approval) { + cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode())); + } else { + cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode()); + } + + if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.desc("info.createTime"); + } else { + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + cnd.groupBy("t.id"); + sql.setCondition(cnd); + Pagination pageVO = specialcondolenceService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pageVO); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceThirdApprovalController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceThirdApprovalController.java new file mode 100644 index 0000000..38f4c84 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceThirdApprovalController.java @@ -0,0 +1,137 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaMode; +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.utils.PageUtil; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.nutz.dao.Cnd; +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.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +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.List; + +/** + * @ClassName SpecialCondolenceThirdApprovalController + * @Author JyuHsin + * @Date 2025/7/29 16:23 + * @Version 1.0 + * @Description TODO + */ +@IocBean +@At("/platform/special_condolence/schoolUnionApproval") +@Api("特殊慰问三级审核") +@Ok("json:full") +public class SpecialCondolenceThirdApprovalController { + + @Inject + private SpecialCondolenceService specialcondolenceService; + + @At("/") + @Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/schoolUnionApproval/index.html") + @SaCheckPermission("special_condolence.thirdApproval") + public void index() {} + + @At("/h5") + @Ok("beetl:/platform/zhghh5/staffbenefit/specialcondolence/schoolUnionApproval/index.html") + @SaCheckPermission("h5.special_condolence.thirdApproval") + public void h5Index() {} + + @At + @ApiOperation("分页查询") + @SaCheckPermission(value = {"special_condolence.thirdApproval", "h5.special_condolence.thirdApproval"}, mode = SaMode.OR) + public Result pageData(PageForm pageForm, + @Param(value = "year") Integer year, + @Param(value = "type") String type, + @Param(value = "unionId") String unionId, + @Param(value = "unitId") String unitId, + @Param(value = "approval") Boolean approval) { + Sql sql = Sqls.create(""" + SELECT + info.*, + type.name as typeName, + ins.id AS instanceId, + ins.businessNo, + ins.state instanceState, + ins.variable instanceVariable, + ins.processDefineId instanceProcessDefineId, + t.id taskId, + t.taskName AS taskKey, + t.displayName taskName, + t.taskType, + t.performType taskPerformType, + t.taskState, + t.finishTime, + t.taskParentId, + t.variable taskVariable, + IFNULL(GROUP_CONCAT(DISTINCT nt.displayName),'结束') curTaskName, + IF(rt.id IS NOT NULL, 1, 0) AS canRevoke + FROM + wf_process_task t + LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId + LEFT JOIN special_condolence info ON info.id = ins.businessNo + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.id + LEFT JOIN special_condolence_type type ON info.type = type.id + LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10 + LEFT JOIN wf_process_task rt ON rt.processInstanceId = ins.id AND rt.taskParentId = t.id AND rt.taskState = 10 + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("info.id", "is not", null); + cnd.and(new Static(""" + NOT EXISTS ( + SELECT 1 FROM wf_process_task newer + WHERE newer.processInstanceId = t.processInstanceId + AND newer.taskName = t.taskName + AND newer.id > t.id + ) + """)); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or(SpecialCondolence::getHelpUserName, "like", "%" + pageForm.getSearchKeyword() + "%"); + seg.or(SpecialCondolence::getHelpLoginName, "like", "%" + pageForm.getSearchKeyword() + "%"); + cnd.and(seg); + } + cnd.andEX("info.type", "=", type); + cnd.andEX("YEAR(info.createTime)", "=", year); + cnd.andEX("info.applyUnionId", "=", unionId); + cnd.andEX("info.applyUnitId", "=", unitId); + + cnd.and("t.taskName", "=", "7f560675-aeea-4254-a57e-957d03d6b786"); + if (!"superadmin".equals(SecurityUtil.getUserLoginname())) { + cnd.and("ta.actorId", "in", List.of(SecurityUtil.getUserId())); + } + + if (approval) { + cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode())); + } else { + cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode()); + } + + if (StrUtil.isAllBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.desc("info.createTime"); + } else { + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } + cnd.groupBy("t.id"); + sql.setCondition(cnd); + Pagination pageVO = specialcondolenceService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + return Result.success(pageVO); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceTypeController.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceTypeController.java new file mode 100644 index 0000000..cd0a029 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/controller/SpecialCondolenceTypeController.java @@ -0,0 +1,91 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.controller; + +import cn.dev33.satoken.annotation.SaCheckLogin; +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.util.StrUtil; +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.zhgh.staffbenefit.specialcondolence.model.SpecialCondolenceType; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceTypeService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.dao.util.cri.SqlExpressionGroup; +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 java.util.List; + +/** + * @ClassName SpecialCondolenceTypeController + * @Author JyuHsin + * @Date 2025/7/29 10:00 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +@Ok("json:full") +@Api(tags = "特殊慰问类型") +@At("/platform/special_condolence/type") +public class SpecialCondolenceTypeController { + + @Inject + private Dao dao; + @Inject + private SpecialCondolenceTypeService typeService; + + @At("") + @SaCheckPermission("special_condolence.type") + @Ok("beetl:/platform/zhgh/staffbenefit/specialcondolence/type/index.html") + public void index() { + } + + @At + @ApiOperation("分页查询") + @SaCheckPermission("special_condolence.type") + public Result pageData(PageForm pageForm) { + Cnd cnd = Cnd.NEW(); + if (StrUtil.isNotBlank(pageForm.getSearchKeyword())) { + SqlExpressionGroup seg = new SqlExpressionGroup(); + seg.or(SpecialCondolenceType::getName, "like", "%" + pageForm.getSearchKeyword() + "%"); + seg.or(SpecialCondolenceType::getCode, "like", "%" + pageForm.getSearchKeyword() + "%"); + cnd.and(seg); + } + cnd.asc("code"); + Pagination pagination = typeService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), cnd); + return Result.success(pagination); + } + + @At + @ApiOperation("新增/修改特殊慰问类型") + @SaCheckPermission("special_condolence.type") + @SLog(tag = "特殊慰问系统-慰问类型", msg = "新增/修改特殊慰问类型") + public Object onSubmit(SpecialCondolenceType type) { + typeService.insertOrUpdate(type); + return Result.success(); + } + + @At + @ApiOperation("删除特殊慰问类型") + @SaCheckPermission("special_condolence.type") + @SLog(tag = "特殊慰问系统-慰问类型", msg = "删除特殊慰问类型") + public Object onDelete(String id) { + typeService.delete(id); + return Result.success(); + } + + @At + @ApiOperation("查询特殊慰问类型") + @SaCheckLogin + public Result querySpecialCondolenceType() { + List list = typeService.query(Cnd.where(SpecialCondolenceType::getEnable, "=", true).asc(SpecialCondolenceType::getCode)); + return Result.success(list); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/interceptor/SpecialCondolenceSaveInterceptor.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/interceptor/SpecialCondolenceSaveInterceptor.java new file mode 100644 index 0000000..44c415a --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/interceptor/SpecialCondolenceSaveInterceptor.java @@ -0,0 +1,46 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.interceptor; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import com.budwk.app.flow.constant.FlowConst; +import com.budwk.app.flow.engine.FlowInterceptor; +import com.budwk.app.flow.engine.core.Execution; +import com.budwk.app.flow.engine.core.ServiceContext; +import com.budwk.app.flow.entity.ProcessInstance; +import com.budwk.app.zhgh.dayofficework.article.models.Article; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence; +import org.nutz.dao.Chain; +import org.nutz.dao.Cnd; +import org.nutz.dao.Dao; +import org.nutz.json.Json; + +/** + * @ClassName SpecialCondolenceSaveInterceptor + * @Author JyuHsin + * @Date 2025/7/28 11:01 + * @Version 1.0 + * @Description TODO + */ +public class SpecialCondolenceSaveInterceptor implements FlowInterceptor { + + @Override + public void intercept(Execution execution) { + if (!com.budwk.app.web.commons.auth.utils.AuthUtil.hasRoleOr("BRANCH_UNION_CHAIRMAN")) { + throw new com.budwk.app.base.exception.BaseException("仅分工会主席可发起特殊慰问申请"); + } + String formDataStr = execution.getArgs().getStr(FlowConst.FORM_DATA); + SpecialCondolence specialcondolence = Json.fromJson(SpecialCondolence.class, formDataStr); + + if(StrUtil.isBlank(specialcondolence.getId())) specialcondolence.setCreateTime(DateUtil.now()); + + Dao dao = ServiceContext.find(Dao.class); + ServiceContext.find(com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService.class).saveApplication(specialcondolence); + + // 设置流程变量 + execution.getArgs().set("origin", specialcondolence.getOrigin()); + + int instanceId = execution.getArgs().getInt(FlowConst.PROCESS_INSTANCE_ID_KEY); + dao.update(ProcessInstance.class, Chain.make("businessNo", specialcondolence.getId()), Cnd.where(ProcessInstance::getId, "=", instanceId)); + + } +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/model/SpecialCondolence.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/model/SpecialCondolence.java new file mode 100644 index 0000000..d7b7f31 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/model/SpecialCondolence.java @@ -0,0 +1,304 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.model; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.model.BaseModel; +import com.budwk.app.sys.models.Sys_file; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +import java.util.List; + +/** + * @ClassName SpecialCondolence + * @Author JyuHsin + * @Date 2025/7/28 11:03 + * @Version 1.0 + * @Description TODO + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("special_condolence") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("特殊慰问") +public class SpecialCondolence extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("申请人ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String applyUserId; + + @Column + @Comment("申请人姓名") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String applyUserName; + + @Column + @Comment("申请人工号") + @ColDefine(type = ColType.VARCHAR, width = 120) + private String applyLoginName; + + @Column + @Comment("申请人分工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String applyUnionId; + + @Column + @Comment("申请人分工会") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String applyUnionName; + + @Column + @Comment("申请人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String applyUnitId; + + @Column + @Comment("申请人单位") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String applyUnitName; + + @Column + @Comment("补助人ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String helpUserId; + + @Column + @Comment("补助人姓名") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String helpUserName; + + @Column + @Comment("补助人工号") + @ColDefine(type = ColType.VARCHAR, width = 120) + private String helpLoginName; + + @Column + @Comment("补助人分工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String helpUnionId; + + @Column + @Comment("补助人分工会") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String helpUnionName; + + @Column + @Comment("补助人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String helpUnitId; + + @Column + @Comment("补助人单位") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String helpUnitName; + + @Column + @Comment("类型") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String origin; + + @Column + @Comment("收款人") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String payUserId; + + @Column + @Comment("收款人姓名") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String payUserName; + + @Column + @Comment("收款人工号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String payLoginName; + + @Column + @Comment("慰问类型") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String type; + + @Column + @Comment("慰问编码") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String typeCode; + + @Column + @Comment("慰问方式") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String way; + + @Column + @Comment("统一每人慰问金额") + @ColDefine(customType = "decimal(10,2)") + private java.math.BigDecimal perMoney; + + @Column + @Comment("慰问金额") + @ColDefine(type = ColType.FLOAT, width = 10, precision = 2) + private Double money; + + @Column + @Comment("发生时间") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String occurTime; + + @Column + @Comment("生育几孩(孩次)") + @ColDefine(type = ColType.VARCHAR, width = 10) + private String child; + + @Column + @Comment("所在医院") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String hospital; + + @Column + @Comment("病房床号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String hospitalHouseNum; + + @Column + @Comment("病房床号") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String hospitalHouseBedNum; + + @Column + @Comment("住院病由") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String hospitalBy; + + @Column + @Comment("备注") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String remark; + + @Column + @Comment("附件") + @ColDefine(type = ColType.MYSQL_JSON) + private List files; + + @Comment("签字") + @ColDefine(type = ColType.VARCHAR, width = 255) + @Column(hump = true) + private String signature; + + @Column + @Comment("申请时间") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String createTime; + + + + + @Column + @Comment("户名") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String bankUserName; + + @Column + @Comment("银行账号") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String bankCardNumber; + + @Column + @Comment("开户行") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String bankOfDeposit; + + @Column + @Comment("证明人ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String certifierUserId; + + @Column + @Comment("证明人姓名") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String certifierUserName; + + @Column + @Comment("证明人工号") + @ColDefine(type = ColType.VARCHAR, width = 120) + private String certifierLoginName; + + @Column + @Comment("证明人分工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String certifierUnionId; + + @Column + @Comment("证明人分工会") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String certifierUnionName; + + @Column + @Comment("证明人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String certifierUnitId; + + @Column + @Comment("证明人单位") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String certifierUnitName; + + @Column + @Comment("经办人ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String handlerUserId; + + @Column + @Comment("经办人姓名") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String handlerUserName; + + @Column + @Comment("经办人工号") + @ColDefine(type = ColType.VARCHAR, width = 120) + private String handlerLoginName; + + @Column + @Comment("经办人分工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String handlerUnionId; + + @Column + @Comment("经办人分工会") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String handlerUnionName; + + @Column + @Comment("经办人单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String handlerUnitId; + + @Column + @Comment("经办人单位") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String handlerUnitName; + + @Column + @Comment("入院时间") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String hospitalizationTime; + + @Column + @Comment("出院时间") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String leaveHospitalTime; + + @Column + @Comment("当年第几次住院") + @ColDefine(type = ColType.INT) + private Integer thisYearHospitalizationNum; + + @Comment("慰问对象明细,由明细表加载") + private List recipients; + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/model/SpecialCondolenceRecipient.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/model/SpecialCondolenceRecipient.java new file mode 100644 index 0000000..672b09d --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/model/SpecialCondolenceRecipient.java @@ -0,0 +1,100 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.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("special_condolence_recipient") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@TableIndexes({@Index(name = "idx_special_condolence_recipient_apply", fields = {"applyId"}, unique = false)}) +@Comment("特殊慰问被申请人明细") +public class SpecialCondolenceRecipient extends BaseModel { + @Name + @PrevInsert(uu32 = true) + @ColDefine(type = ColType.VARCHAR, width = 32) + private String id; + + @Column + @Comment("申请ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String applyId; + + @Column + @Comment("慰问对象用户ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String helpUserId; + + @Column + @Comment("人员类型") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String personType; + + @Column + @Comment("慰问对象工号") + @ColDefine(type = ColType.VARCHAR, width = 120) + private String helpLoginName; + + @Column + @Comment("慰问对象") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String helpUserName; + + @Column + @Comment("慰问类型ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String type; + + @Column + @Comment("慰问类型名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String typeName; + + @Column + @Comment("慰问类型编码") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String typeCode; + + @Column + @Comment("慰问方式") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String way; + + @Column + @Comment("身份证号码") + @ColDefine(type = ColType.VARCHAR, width = 18) + private String idCard; + + @Column + @Comment("开户行") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String bankOfDeposit; + + @Column + @Comment("户名") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String bankUserName; + + @Column + @Comment("收款账户") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String bankCardNumber; + + @Column + @Comment("慰问金额") + @ColDefine(customType = "decimal(10,2)") + private java.math.BigDecimal money; + + @Column + @Comment("慰问时间") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String occurTime; + + @Column + @Comment("行序号") + @ColDefine(type = ColType.INT) + private Integer sortNum; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/model/SpecialCondolenceType.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/model/SpecialCondolenceType.java new file mode 100644 index 0000000..3097fc8 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/model/SpecialCondolenceType.java @@ -0,0 +1,84 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.model; + +import com.budwk.app.base.model.BaseModel; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.nutz.dao.DB; +import org.nutz.dao.entity.annotation.*; +import org.nutz.dao.interceptor.annotation.PrevInsert; + +/** + * @ClassName SpecialCondolenceType + * @Author JyuHsin + * @Date 2025/7/29 9:59 + * @Version 1.0 + * @Description TODO + */ +@Data +@EqualsAndHashCode(callSuper = true) +@Table("special_condolence_type") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@Comment("特殊慰问类型") +public class SpecialCondolenceType extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("编码") + @ColDefine(type = ColType.VARCHAR, width = 30) + private String code; + + @Column + @Comment("名称") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String name; + + @Column + @Comment("费用") + @ColDefine(type = ColType.FLOAT, width = 10, precision = 2) + private Double money; + + @Column + @Comment("慰问方式") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String way; + + @Column + @Comment("是否启用") + @ColDefine(type = ColType.BOOLEAN) + @Default("1") + private Boolean enable; + + @Column + @Comment("是否上传附件") + @ColDefine(type = ColType.BOOLEAN) + private Boolean isUploadFile; + + @Column + @Comment("上传附件说明") + @ColDefine(type = ColType.VARCHAR,width = 50) + private String uploadFileDesc; + + @Column + @Comment("排序字段") + @Prev({ + @SQL(db = DB.MYSQL, value = "SELECT IFNULL(MAX(location),0)+1 FROM special_condolence_type"), + @SQL(db = DB.ORACLE, value = "SELECT COALESCE(MAX(location),0)+1 FROM special_condolence_type") + }) + private Integer location; + + @Column + @Comment("排序") + @ColDefine(type = ColType.INT) + private int sortNum; + + @Column + @Comment("上传会议纪要") + @Default("0") + @ColDefine(type = ColType.BOOLEAN) + private Boolean uploadMeetingRecord; +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/SpecialCondolenceRecipients.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/SpecialCondolenceRecipients.java new file mode 100644 index 0000000..bafcd7b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/SpecialCondolenceRecipients.java @@ -0,0 +1,117 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.service; + +import cn.hutool.json.JSONObject; +import com.budwk.app.base.exception.BaseException; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolenceType; +import org.nutz.dao.Dao; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; + +public final class SpecialCondolenceRecipients { + private SpecialCondolenceRecipients() {} + + public static void prepare(SpecialCondolence info, Dao dao) { + List rows = info.getRecipients(); + if (rows == null || rows.isEmpty()) throw new BaseException("请添加慰问对象"); + if (rows.size() > 1000) throw new BaseException("每次申请最多1000人"); + if (info.getFiles() != null && info.getFiles().size() > 5) throw new BaseException("最多上传5个附件"); + if (info.getRemark() != null && info.getRemark().trim().length() > 500) throw new BaseException("申请事由最多500字"); + if (info.getPerMoney() == null || info.getPerMoney().signum() <= 0 || info.getPerMoney().compareTo(new BigDecimal("10000")) > 0 || info.getPerMoney().scale() > 2) throw new BaseException("每人慰问金额须大于0且不超过10000元,最多两位小数"); + try { LocalDate.parse(info.getOccurTime()); } + catch (Exception e) { throw new BaseException("请选择有效的统一慰问时间"); } + BigDecimal total = BigDecimal.ZERO; + for (int i = 0; i < rows.size(); i++) { + JSONObject row = rows.get(i); + String prefix = "第" + (i + 1) + "行:"; + if (row == null) throw new BaseException(prefix + "明细不能为空"); + row.set("type", info.getType()); + row.set("money", info.getPerMoney().toPlainString()); + row.set("occurTime", info.getOccurTime()); + resolveUser(row, dao, prefix); + String[] fields = {"helpUserName", "type", "idCard", "bankOfDeposit", "bankUserName", "bankCardNumber", "money", "occurTime"}; + for (String field : fields) { + String value = row.getStr(field); + if (value == null || value.trim().isEmpty()) throw new BaseException(prefix + "请填写完整的慰问对象信息"); + row.set(field, value.trim()); + } + if (!validIdCard(row.getStr("idCard"))) throw new BaseException(prefix + "身份证号码不正确"); + if (!row.getStr("bankCardNumber").matches("[0-9]{6,30}")) throw new BaseException(prefix + "收款账户须为6至30位数字"); + if (row.getStr("helpUserName").length() > 100 || row.getStr("bankOfDeposit").length() > 100 || row.getStr("bankUserName").length() > 100) throw new BaseException(prefix + "姓名、开户行、户名不能超过100字"); + if (!row.getStr("money").matches("[0-9]+(\\.[0-9]{1,2})?")) throw new BaseException(prefix + "金额最多两位小数"); + BigDecimal money = new BigDecimal(row.getStr("money")); + if (money.signum() <= 0 || money.compareTo(new BigDecimal("10000")) > 0) throw new BaseException(prefix + "金额须大于0且不超过10000元"); + try { LocalDate.parse(row.getStr("occurTime")); } + catch (Exception e) { throw new BaseException(prefix + "慰问时间格式须为yyyy-MM-dd"); } + SpecialCondolenceType type = dao.fetch(SpecialCondolenceType.class, row.getStr("type")); + if (type == null || !Boolean.TRUE.equals(type.getEnable())) throw new BaseException(prefix + "慰问类型不存在或已停用"); + row.set("typeName", type.getName()); + row.set("typeCode", type.getCode()); + row.set("way", type.getWay()); + if (Boolean.TRUE.equals(type.getIsUploadFile()) && (info.getFiles() == null || info.getFiles().isEmpty())) throw new BaseException(prefix + "该慰问类型需要上传附件"); + total = total.add(money); + } + JSONObject first = rows.get(0); + String name = first.getStr("helpUserName"); + info.setHelpUserName((rows.size() > 1 && name.length() > 90 ? name.substring(0, 90) : name) + (rows.size() > 1 ? "等" + rows.size() + "人" : "")); + info.setHelpUnitId(info.getApplyUnitId()); + info.setHelpUnitName(info.getApplyUnitName()); + info.setHelpUnionId(info.getApplyUnionId()); + info.setHelpUnionName(info.getApplyUnionName()); + info.setType(first.getStr("type")); + info.setTypeCode(first.getStr("typeCode")); + info.setWay(first.getStr("way")); + info.setOccurTime(first.getStr("occurTime")); + info.setMoney(total.doubleValue()); + info.setBankOfDeposit(first.getStr("bankOfDeposit")); + info.setBankUserName(first.getStr("bankUserName")); + info.setBankCardNumber(first.getStr("bankCardNumber")); + } + + public static void resolveUser(JSONObject row, Dao dao, String prefix) { + String userId = row.getStr("helpUserId"); + com.budwk.app.sys.views.View_user user; + String unionId = com.budwk.app.web.commons.auth.utils.SecurityUtil.getUnionId(); + if (cn.hutool.core.util.StrUtil.isBlank(unionId)) throw new BaseException(prefix + "申请人未关联分工会"); + if (cn.hutool.core.util.StrUtil.isNotBlank(userId)) { + user = dao.fetch(com.budwk.app.sys.views.View_user.class, org.nutz.dao.Cnd.where("id", "=", userId)); + } else { + org.nutz.dao.Cnd identity = org.nutz.dao.Cnd.where("unionId", "=", unionId) + .and("idCard", "=", row.getStr("idCard")).and("username", "=", row.getStr("helpUserName")); + java.util.List dispatched = dao.query(com.budwk.app.sys.views.View_user.class, + identity.and("personType", "=", "劳务派遣人员")); + if (dispatched.size() > 1) throw new BaseException(prefix + "劳务派遣人员身份重复,请核对档案"); + if (dispatched.size() == 1) { + user = dispatched.get(0); + } else { + if (cn.hutool.core.util.StrUtil.isBlank(row.getStr("helpLoginName"))) throw new BaseException(prefix + "普通人员必须填写工号"); + java.util.List users = dao.query(com.budwk.app.sys.views.View_user.class, + org.nutz.dao.Cnd.where("unionId", "=", unionId).and("loginname", "=", row.getStr("helpLoginName")) + .and("username", "=", row.getStr("helpUserName")).and("idCard", "=", row.getStr("idCard"))); + if (users.size() != 1) throw new BaseException(prefix + "工号、姓名、身份证不匹配或不属于申请人本工会"); + user = users.get(0); + } + } + if (user == null) throw new BaseException(prefix + "慰问对象不存在"); + if (!java.util.Objects.equals(user.getUnionId(), unionId)) throw new BaseException(prefix + "只能选择申请人本工会人员"); + if (!"劳务派遣人员".equals(user.getPersonType()) && (cn.hutool.core.util.StrUtil.isBlank(row.getStr("helpLoginName")) || !java.util.Objects.equals(user.getLoginname(), row.getStr("helpLoginName")))) throw new BaseException(prefix + "工号与慰问对象不一致"); + if (cn.hutool.core.util.StrUtil.isNotBlank(user.getIdCard()) && !user.getIdCard().equalsIgnoreCase(row.getStr("idCard"))) throw new BaseException(prefix + "身份证号码与所选人员不一致"); + row.set("helpUserId", user.getId()); + row.set("helpLoginName", user.getLoginname()); + row.set("personType", user.getPersonType()); + row.set("helpUserName", user.getUsername()); + } + + public static boolean validIdCard(String value) { + if (value == null || !value.matches("[1-9][0-9]{16}[0-9Xx]")) return false; + try { LocalDate.parse(value.substring(6, 14), java.time.format.DateTimeFormatter.BASIC_ISO_DATE); } + catch (Exception e) { return false; } + int[] weights = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; + int sum = 0; + for (int i = 0; i < weights.length; i++) sum += (value.charAt(i) - '0') * weights[i]; + return "10X98765432".charAt(sum % 11) == Character.toUpperCase(value.charAt(17)); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/SpecialCondolenceService.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/SpecialCondolenceService.java new file mode 100644 index 0000000..8c6eb97 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/SpecialCondolenceService.java @@ -0,0 +1,17 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence; + +/** + * @ClassName SpecialCondolenceService + * @Author JyuHsin + * @Date 2025/7/29 11:21 + * @Version 1.0 + * @Description TODO + */ +public interface SpecialCondolenceService extends BaseService { + void saveApplication(SpecialCondolence info); + SpecialCondolence loadApplication(String id); + void deleteApplication(String id); +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/SpecialCondolenceTypeService.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/SpecialCondolenceTypeService.java new file mode 100644 index 0000000..0409361 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/SpecialCondolenceTypeService.java @@ -0,0 +1,14 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.service; + +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolenceType; + +/** + * @ClassName SpecialCondolenceTypeService + * @Author JyuHsin + * @Date 2025/7/29 10:03 + * @Version 1.0 + * @Description TODO + */ +public interface SpecialCondolenceTypeService extends BaseService { +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/impl/SpecialCondolenceServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/impl/SpecialCondolenceServiceImpl.java new file mode 100644 index 0000000..50898ea --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/impl/SpecialCondolenceServiceImpl.java @@ -0,0 +1,87 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolenceRecipient; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceRecipients; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import org.nutz.ioc.aop.Aop; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.Cnd; +import java.math.BigDecimal; +import java.util.List; +import java.util.ArrayList; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolence; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @ClassName SpecialCondolenceServiceImpl + * @Author JyuHsin + * @Date 2025/7/29 11:22 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean(args = {"refer:dao"}) +public class SpecialCondolenceServiceImpl extends BaseServiceImpl implements SpecialCondolenceService { + + public SpecialCondolenceServiceImpl(Dao dao) { + super(dao); + } + @Override + @Aop(TransAop.READ_COMMITTED) + public void saveApplication(SpecialCondolence info) { + SpecialCondolenceRecipients.prepare(info, dao()); + dao().insertOrUpdate(info); + dao().clear(SpecialCondolenceRecipient.class, + Cnd.where("applyId", "=", info.getId())); + int sort = 0; + for (JSONObject row : info.getRecipients()) { + SpecialCondolenceRecipient person = new SpecialCondolenceRecipient(); + person.setApplyId(info.getId()); + person.setHelpUserName(row.getStr("helpUserName")); + person.setHelpUserId(row.getStr("helpUserId")); + person.setHelpLoginName(row.getStr("helpLoginName")); + person.setPersonType(row.getStr("personType")); + person.setType(row.getStr("type")); + person.setTypeName(row.getStr("typeName")); + person.setTypeCode(row.getStr("typeCode")); + person.setWay(row.getStr("way")); + person.setIdCard(row.getStr("idCard")); + person.setBankOfDeposit(row.getStr("bankOfDeposit")); + person.setBankUserName(row.getStr("bankUserName")); + person.setBankCardNumber(row.getStr("bankCardNumber")); + person.setMoney(new BigDecimal(row.getStr("money"))); + person.setOccurTime(row.getStr("occurTime")); + person.setSortNum(sort++); + dao().insert(person); + } + } + + @Override + public SpecialCondolence loadApplication(String id) { + SpecialCondolence info = fetch(id); + if (info != null) { + List rows = new ArrayList<>(); + for (SpecialCondolenceRecipient person : dao().query( + SpecialCondolenceRecipient.class, + Cnd.where("applyId", "=", id).asc("sortNum").asc("id"))) { + rows.add(JSONUtil.parseObj(person)); + } + info.setRecipients(rows); + } + return info; + } + + @Override + @Aop(TransAop.READ_COMMITTED) + public void deleteApplication(String id) { + dao().clear(SpecialCondolenceRecipient.class, + Cnd.where("applyId", "=", id)); + delete(id); + } + +} diff --git a/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/impl/SpecialCondolenceTypeServiceImpl.java b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/impl/SpecialCondolenceTypeServiceImpl.java new file mode 100644 index 0000000..0c6dee0 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/staffbenefit/specialcondolence/service/impl/SpecialCondolenceTypeServiceImpl.java @@ -0,0 +1,24 @@ +package com.budwk.app.zhgh.staffbenefit.specialcondolence.service.impl; + +import com.budwk.app.base.service.impl.BaseServiceImpl; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.model.SpecialCondolenceType; +import com.budwk.app.zhgh.staffbenefit.specialcondolence.service.SpecialCondolenceTypeService; +import lombok.extern.slf4j.Slf4j; +import org.nutz.dao.Dao; +import org.nutz.ioc.loader.annotation.IocBean; + +/** + * @ClassName SpecialCondolenceTypeServiceImpl + * @Author JyuHsin + * @Date 2025/7/29 10:03 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean(args = {"refer:dao"}) +public class SpecialCondolenceTypeServiceImpl extends BaseServiceImpl implements SpecialCondolenceTypeService { + + public SpecialCondolenceTypeServiceImpl(Dao dao) { + super(dao); + } +} diff --git a/src/main/resources/db/script/20261030/特殊慰问_模块菜单及流程.sql b/src/main/resources/db/script/20261030/特殊慰问_模块菜单及流程.sql new file mode 100644 index 0000000..1b37976 --- /dev/null +++ b/src/main/resources/db/script/20261030/特殊慰问_模块菜单及流程.sql @@ -0,0 +1,223 @@ +-- 全量初始化:完整定义特殊慰问申请主表、被申请人明细表和慰问类型表。 +-- 表已存在时不执行本文件中的建表语句;本文件不复制数据、不配置角色授权和工作流。 +CREATE TABLE `special_condolence` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `applyUserId` varchar(32) DEFAULT NULL COMMENT '申请人ID', + `applyUserName` varchar(100) DEFAULT NULL COMMENT '申请人姓名', + `applyLoginName` varchar(120) DEFAULT NULL COMMENT '申请人工号', + `applyUnionId` varchar(32) DEFAULT NULL COMMENT '申请人分工会ID', + `applyUnionName` varchar(100) DEFAULT NULL COMMENT '申请人分工会', + `applyUnitId` varchar(32) DEFAULT NULL COMMENT '申请人单位ID', + `applyUnitName` varchar(100) DEFAULT NULL COMMENT '申请人单位', + `helpUserId` varchar(32) DEFAULT NULL COMMENT '补助人ID', + `helpUserName` varchar(100) DEFAULT NULL COMMENT '补助人姓名', + `helpLoginName` varchar(120) DEFAULT NULL COMMENT '补助人工号', + `helpUnionId` varchar(32) DEFAULT NULL COMMENT '补助人分工会ID', + `helpUnionName` varchar(100) DEFAULT NULL COMMENT '补助人分工会', + `helpUnitId` varchar(32) DEFAULT NULL COMMENT '补助人单位ID', + `helpUnitName` varchar(100) DEFAULT NULL COMMENT '补助人单位', + `origin` varchar(20) DEFAULT NULL COMMENT '类型', + `payUserId` varchar(32) DEFAULT NULL COMMENT '收款人', + `payUserName` varchar(30) DEFAULT NULL COMMENT '收款人姓名', + `payLoginName` varchar(20) DEFAULT NULL COMMENT '收款人工号', + `type` varchar(32) DEFAULT NULL COMMENT '慰问类型', + `typeCode` varchar(32) DEFAULT NULL COMMENT '慰问编码', + `way` varchar(20) DEFAULT NULL COMMENT '慰问方式', + `perMoney` decimal(10,2) DEFAULT NULL COMMENT '统一每人慰问金额', + `money` float(10,2) DEFAULT NULL COMMENT '慰问金额', + `occurTime` varchar(30) DEFAULT NULL COMMENT '发生时间', + `child` varchar(10) DEFAULT NULL COMMENT '生育几孩(孩次)', + `hospital` varchar(50) DEFAULT NULL COMMENT '所在医院', + `hospitalHouseNum` varchar(20) DEFAULT NULL COMMENT '病房床号', + `hospitalHouseBedNum` varchar(20) DEFAULT NULL COMMENT '病房床号', + `hospitalBy` varchar(100) DEFAULT NULL COMMENT '住院病由', + `remark` varchar(500) DEFAULT NULL COMMENT '备注', + `files` json DEFAULT NULL COMMENT '附件', + `signature` varchar(255) DEFAULT NULL COMMENT '签字', + `createTime` varchar(30) DEFAULT NULL COMMENT '申请时间', + `bankUserName` varchar(100) DEFAULT NULL COMMENT '户名', + `bankCardNumber` varchar(100) DEFAULT NULL COMMENT '银行账号', + `bankOfDeposit` varchar(100) DEFAULT NULL COMMENT '开户行', + `certifierUserId` varchar(32) DEFAULT NULL COMMENT '证明人ID', + `certifierUserName` varchar(100) DEFAULT NULL COMMENT '证明人姓名', + `certifierLoginName` varchar(120) DEFAULT NULL COMMENT '证明人工号', + `certifierUnionId` varchar(32) DEFAULT NULL COMMENT '证明人分工会ID', + `certifierUnionName` varchar(100) DEFAULT NULL COMMENT '证明人分工会', + `certifierUnitId` varchar(32) DEFAULT NULL COMMENT '证明人单位ID', + `certifierUnitName` varchar(100) DEFAULT NULL COMMENT '证明人单位', + `handlerUserId` varchar(32) DEFAULT NULL COMMENT '经办人ID', + `handlerUserName` varchar(100) DEFAULT NULL COMMENT '经办人姓名', + `handlerLoginName` varchar(120) DEFAULT NULL COMMENT '经办人工号', + `handlerUnionId` varchar(32) DEFAULT NULL COMMENT '经办人分工会ID', + `handlerUnionName` varchar(100) DEFAULT NULL COMMENT '经办人分工会', + `handlerUnitId` varchar(32) DEFAULT NULL COMMENT '经办人单位ID', + `handlerUnitName` varchar(100) DEFAULT NULL COMMENT '经办人单位', + `hospitalizationTime` varchar(30) DEFAULT NULL COMMENT '入院时间', + `leaveHospitalTime` varchar(30) DEFAULT NULL COMMENT '出院时间', + `thisYearHospitalizationNum` int DEFAULT NULL COMMENT '当年第几次住院', + `createdBy` varchar(32) DEFAULT NULL COMMENT '创建人', + `createdAt` bigint DEFAULT NULL COMMENT '创建时间(毫秒时间戳)', + `updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人', + `updatedAt` bigint DEFAULT NULL COMMENT '修改时间(毫秒时间戳)', + `delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='特殊慰问申请'; + +CREATE TABLE `special_condolence_type` ( + `id` varchar(32) NOT NULL COMMENT 'ID', + `code` varchar(30) DEFAULT NULL COMMENT '编码', + `name` varchar(50) DEFAULT NULL COMMENT '名称', + `money` float(10,2) DEFAULT NULL COMMENT '费用', + `way` varchar(20) DEFAULT NULL COMMENT '慰问方式', + `enable` tinyint(1) DEFAULT 1 COMMENT '是否启用', + `isUploadFile` tinyint(1) DEFAULT NULL COMMENT '是否上传附件', + `uploadFileDesc` varchar(50) DEFAULT NULL COMMENT '上传附件说明', + `location` int DEFAULT NULL COMMENT '排序字段', + `sortNum` int NOT NULL DEFAULT 0 COMMENT '排序', + `uploadMeetingRecord` tinyint(1) DEFAULT 0 COMMENT '上传会议纪要', + `createdBy` varchar(32) DEFAULT NULL COMMENT '创建人', + `createdAt` bigint DEFAULT NULL COMMENT '创建时间(毫秒时间戳)', + `updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人', + `updatedAt` bigint DEFAULT NULL COMMENT '修改时间(毫秒时间戳)', + `delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记', + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='特殊慰问类型'; + +-- 一份申请对应一个流程实例;多名被申请人通过 applyId 关联同一份申请。 +CREATE TABLE `special_condolence_recipient` ( + `id` varchar(32) NOT NULL COMMENT '明细ID', + `applyId` varchar(32) NOT NULL COMMENT '申请主表ID', + `helpUserId` varchar(32) NOT NULL COMMENT '慰问对象用户ID', + `helpLoginName` varchar(120) DEFAULT NULL COMMENT '慰问对象工号', + `personType` varchar(50) DEFAULT NULL COMMENT '人员类型', + `helpUserName` varchar(100) NOT NULL COMMENT '慰问对象', + `type` varchar(32) NOT NULL COMMENT '慰问类型ID', + `typeName` varchar(50) DEFAULT NULL COMMENT '慰问类型名称', + `typeCode` varchar(32) DEFAULT NULL COMMENT '慰问类型编码', + `way` varchar(20) DEFAULT NULL COMMENT '慰问方式', + `idCard` varchar(18) NOT NULL COMMENT '身份证号码', + `bankOfDeposit` varchar(100) NOT NULL COMMENT '开户行', + `bankUserName` varchar(100) NOT NULL COMMENT '户名', + `bankCardNumber` varchar(30) NOT NULL COMMENT '收款账户', + `money` decimal(10,2) NOT NULL COMMENT '慰问金额', + `occurTime` varchar(30) NOT NULL COMMENT '慰问时间', + `sortNum` int NOT NULL DEFAULT 0 COMMENT '行序号', + `createdBy` varchar(32) DEFAULT NULL COMMENT '创建人', + `createdAt` bigint DEFAULT NULL COMMENT '创建时间(毫秒时间戳)', + `updatedBy` varchar(32) DEFAULT NULL COMMENT '修改人', + `updatedAt` bigint DEFAULT NULL COMMENT '修改时间(毫秒时间戳)', + `delFlag` tinyint(1) DEFAULT 0 COMMENT '删除标记', + PRIMARY KEY (`id`), + KEY `idx_special_condolence_recipient_apply` (`applyId`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='特殊慰问被申请人明细'; + +-- 主表保留原有摘要字段兼容现有列表,money 为整份申请的金额合计。 +-- 被申请人的完整信息保存在 special_condolence_recipient 中,不在主表使用 JSON 存储。 + +-- 新增 PC、H5 菜单,角色授权由管理员另行配置。 +START TRANSACTION; +CREATE TEMPORARY TABLE special_condolence_menu_map AS +SELECT id oldId, MD5(CONCAT('special_condolence:', id)) newId +FROM sys_menu +WHERE id IN ('3b49290f7db44130b9f6394a8212321f', '024811fd168e44948e6ab84911fc26bb') + OR (href LIKE '/platform/condolence/%' AND href NOT LIKE '%/branchUnionApproval%'); +CREATE TEMPORARY TABLE special_condolence_parent_map ( + oldId varchar(32) NOT NULL COMMENT '原父菜单ID', + newId varchar(32) NOT NULL COMMENT '特殊慰问父菜单ID', + PRIMARY KEY (oldId) +); +INSERT INTO special_condolence_parent_map (oldId, newId) +SELECT oldId, newId FROM special_condolence_menu_map; + +INSERT INTO sys_menu + (id, parentId, path, name, aliasName, type, href, target, icon, showit, disabled, + permission, note, location, hasChildren, createdBy, createdAt, updatedBy, updatedAt, + delFlag, processKey, platform, moduleId, isQuickEntry, picIcon, initialPinyinName, + isRecommendApp, isRecommendService) +SELECT map.newId, COALESCE(parent.newId, m.parentId), + CONCAT('T', SUBSTRING(map.newId, 1, 7)), REPLACE(m.name, '职工慰问', '特殊慰问'), + m.aliasName, m.type, REPLACE(m.href, '/condolence/', '/special_condolence/'), m.target, + m.icon, m.showit, m.disabled, + CASE m.id WHEN '3b49290f7db44130b9f6394a8212321f' THEN 'special_condolence' + WHEN '024811fd168e44948e6ab84911fc26bb' THEN 'h5.special_condolence' + ELSE REPLACE(m.permission, 'condolence', 'special_condolence') END, + REPLACE(m.note, '职工慰问', '特殊慰问'), m.location, m.hasChildren, + m.createdBy, UNIX_TIMESTAMP()*1000, m.updatedBy, UNIX_TIMESTAMP()*1000, m.delFlag, + REPLACE(m.processKey, 'ZGWW', 'TSWW'), m.platform, m.moduleId, m.isQuickEntry, + m.picIcon, IF(m.name = '职工慰问', 't', m.initialPinyinName), m.isRecommendApp, m.isRecommendService +FROM sys_menu m JOIN special_condolence_menu_map map ON map.oldId = m.id +LEFT JOIN special_condolence_parent_map parent ON parent.oldId = m.parentId +WHERE NOT EXISTS (SELECT 1 FROM sys_menu existing WHERE existing.id = map.newId); + +-- 父子菜单路径保持树形前缀关系。 +UPDATE sys_menu child JOIN sys_menu parent ON parent.id = child.parentId +JOIN special_condolence_menu_map map ON map.newId = child.id +SET child.path = CONCAT(parent.path, RIGHT(child.id, 4)); + +DROP TEMPORARY TABLE special_condolence_menu_map; +DROP TEMPORARY TABLE special_condolence_parent_map; + +-- 权限部分,不要删除 +-- SYSADMIN +-- 特殊慰问 web +INSERT INTO sys_role_menu (roleId, menuId) VALUES ('7f4a820d5a394bb8a0a92d6699afe7c8', '4c46696d75ff0eddf5cb57fac3e5d06d'); +INSERT INTO sys_role_menu (roleId, menuId) +VALUES ('7f4a820d5a394bb8a0a92d6699afe7c8', '3e97a91e7aa9566cdae94850038a6212'), + ('7f4a820d5a394bb8a0a92d6699afe7c8', '6c5be59ffb8d7c524ec72f2a02d6c6d2'), + ('7f4a820d5a394bb8a0a92d6699afe7c8', '7f66eb63b6ebd81c5eee9c5c2de2ed98'), + ('7f4a820d5a394bb8a0a92d6699afe7c8', '8d5ebaa091eee01abb33e89e3dcc92f8'), + ('7f4a820d5a394bb8a0a92d6699afe7c8', '9c37242f50c5fb4a9c1b2b9b9dd0e2fd'), + ('7f4a820d5a394bb8a0a92d6699afe7c8', '9f4f850904fe751db1cd13977374f99b'), + ('7f4a820d5a394bb8a0a92d6699afe7c8', 'b24a5bef9ccbf7241c5bb85e80352f8f'); + +-- 特殊慰问 h5 +INSERT INTO sys_role_menu (roleId, menuId) VALUES ('7f4a820d5a394bb8a0a92d6699afe7c8', '2145812145ee6548552504b4f5a55ff7'); +INSERT INTO sys_role_menu (roleId, menuId) +VALUES ('7f4a820d5a394bb8a0a92d6699afe7c8', '42b4b5f54593cf023961ad1c9ce36f53'), + ('7f4a820d5a394bb8a0a92d6699afe7c8', '4f3212a13a54fbb2a082ee77651c9a73'), + ('7f4a820d5a394bb8a0a92d6699afe7c8', '739f64c71fe776dc3520ebb2977c2d68'), + ('7f4a820d5a394bb8a0a92d6699afe7c8', 'b6c725beaf3bfe9f2b29f46855c45a24'), + ('7f4a820d5a394bb8a0a92d6699afe7c8', 'eb3d1b27d51b84df1cebf24e1278e26c'); + + +-- 校工会办公室主任 +-- 特殊慰问 web +INSERT INTO sys_role_menu (roleId, menuId) +VALUES + ('494ac71eb8b44d0e99e19b7fde6bd469', '4c46696d75ff0eddf5cb57fac3e5d06d'), + ('494ac71eb8b44d0e99e19b7fde6bd469', '7f66eb63b6ebd81c5eee9c5c2de2ed98'); + +-- 特殊慰问 h5 +INSERT INTO sys_role_menu (roleId, menuId) +VALUES + ('494ac71eb8b44d0e99e19b7fde6bd469', '2145812145ee6548552504b4f5a55ff7'), + ('494ac71eb8b44d0e99e19b7fde6bd469', '42b4b5f54593cf023961ad1c9ce36f53'); + +-- 校工会主席 +-- 特殊慰问 web +INSERT INTO sys_role_menu (roleId, menuId) +VALUES + ('6aece46b946e4fb9ac4cb15c0cd8c3e6', '4c46696d75ff0eddf5cb57fac3e5d06d'), + ('6aece46b946e4fb9ac4cb15c0cd8c3e6', 'b24a5bef9ccbf7241c5bb85e80352f8f'); + +-- 特殊慰问 h5 +INSERT INTO sys_role_menu (roleId, menuId) +VALUES + ('6aece46b946e4fb9ac4cb15c0cd8c3e6', '2145812145ee6548552504b4f5a55ff7'), + ('6aece46b946e4fb9ac4cb15c0cd8c3e6', 'b6c725beaf3bfe9f2b29f46855c45a24'); + +-- 校工会主席 +-- 特殊慰问 web +INSERT INTO sys_role_menu (roleId, menuId) +VALUES + ('b3854469e6f44901b22bb791cb538431', '4c46696d75ff0eddf5cb57fac3e5d06d'), + ('b3854469e6f44901b22bb791cb538431', '9c37242f50c5fb4a9c1b2b9b9dd0e2fd'); + +-- 特殊慰问 h5 +INSERT INTO sys_role_menu (roleId, menuId) +VALUES + ('b3854469e6f44901b22bb791cb538431', '2145812145ee6548552504b4f5a55ff7'), + ('b3854469e6f44901b22bb791cb538431', '739f64c71fe776dc3520ebb2977c2d68'); + + +COMMIT; diff --git a/src/main/resources/templates/special_condolence/special_condolence_import.xlsx b/src/main/resources/templates/special_condolence/special_condolence_import.xlsx new file mode 100644 index 0000000..6e219ae Binary files /dev/null and b/src/main/resources/templates/special_condolence/special_condolence_import.xlsx differ diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/apply/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/apply/index.html index c0df35c..494836f 100644 --- a/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/apply/index.html +++ b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/apply/index.html @@ -1,8 +1,9 @@ -
- +
+ + @@ -318,6 +319,7 @@ layout("/layouts/platform.html"){ bizId: GetQueryString("bizId"), taskId: GetQueryString("taskId"), isShow: false, + pageLoading: true, time: '', blockMessage: '', formData: { @@ -453,10 +455,12 @@ layout("/layouts/platform.html"){ }) }, findOne(id) { - this.$axios.post('/platform/difficultHelp/mine/findOne', { id }).then(res => { + return this.$axios.post('/platform/difficultHelp/mine/findOne', { id }).then(res => { if (res.code === 0) { this.formData = res.data this.queryRecipients(res.data.loginName) + } else { + throw new Error(res.msg || '申请信息加载失败,请刷新页面重试') } }) }, @@ -617,7 +621,7 @@ layout("/layouts/platform.html"){ return { status: 200, msg: "卡号有效。" }; }, async getIsCanPlay() { - this.$axios.post('/platform/difficultHelp/apply/getIsCanPlay').then(res => { + return this.$axios.post('/platform/difficultHelp/apply/getIsCanPlay').then(res => { if (res.code === 0) { // 新增申请进入页面时,优先校验当前登录人本年度是否已经申请过,已申请则直接拦截新增。 if (!this.bizId && res.data.hasCurrentYearApply && !this.$auth.hasRoleOr('BRANCH_UNION_CHAIRMAN')) { @@ -631,16 +635,25 @@ layout("/layouts/platform.html"){ if (res.data.applyCount !== null && res.data.applyCount !== undefined && res.data.applyCount !== 0) { this.$set(this.formData, 'applyCount', res.data.applyCount) } + } else { + throw new Error(res.msg || '申请资格加载失败,请刷新页面重试') } }) } }, async created() { - await this.getIsCanPlay(); - if (this.bizId) { - this.findOne(this.bizId) - } else { - this.modeChange("1") + try { + await this.getIsCanPlay(); + if (this.bizId) { + await this.findOne(this.bizId) + } else { + this.modeChange("1") + } + } catch (error) { + this.isShow = false + this.blockMessage = error.message || '申请信息加载失败,请刷新页面重试' + } finally { + this.pageLoading = false } } }) diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/index.html index 805cfa4..f061f61 100644 --- a/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/index.html +++ b/src/main/resources/views/platform/zhgh/staffbenefit/difficulthelp/branchunionapproval/index.html @@ -305,7 +305,16 @@ layout("/layouts/platform.html"){ async handleTaskAction(val) { try { - const valid = await this.$refs.formRef.validate() + let valid + if (val === 2 || val === 6) { + this.$refs.formRef.clearValidate(['level', 'money']) + const results = await Promise.all(['tf_opinion', 'tf_sign'].map(prop => new Promise(resolve => { + this.$refs.formRef.validateField(prop, error => resolve(!error)) + }))) + valid = results.every(result => result) + } else { + valid = await this.$refs.formRef.validate() + } if (!valid) return } catch (error) { return diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/apply/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/apply/index.html new file mode 100644 index 0000000..e0021af --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/apply/index.html @@ -0,0 +1,301 @@ + + + +
+ + + +
申请人信息
+ + {{formData.applyUserName}} + {{formData.applyLoginName}} + {{formData.applyUnitName}} + {{formData.applyUnionName}} + + + +
申请说明与签字
+ + + + + + + + + + + + + + + + + + + + +
+ + 保存申请 + 提交申请 + 提交申请 + +
+
+ + + + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/apply/recipients.css b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/apply/recipients.css new file mode 100644 index 0000000..3fc7dba --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/apply/recipients.css @@ -0,0 +1,63 @@ +.special-condolence-apply .el-card__body { padding: 24px; } +.special-condolence-apply .special-condolence-section-title { display: flex; align-items: center; gap: 10px; margin: 24px 0 14px; color: #303133; font-size: 15px; font-weight: 600; line-height: 24px; } +.special-condolence-apply .el-descriptions__table { table-layout: fixed; } +.special-condolence-apply .flow-task-form > .special-condolence-section-title:first-child { margin-top: 0; } +.special-condolence-apply .el-descriptions { font-size: 14px; } +.special-condolence-apply .el-descriptions .el-descriptions-item__cell { height: 50px; padding: 8px 12px; box-sizing: border-box; font-size: 14px; line-height: 32px; vertical-align: middle; } +.special-condolence-apply .el-descriptions-item__label.is-bordered-label { width: 130px; min-width: 130px; max-width: 130px; font-weight: 400; } +.special-condolence-apply .el-descriptions-item__content { font-weight: 400; } +.special-condolence-apply .el-descriptions .el-form-item__content { line-height: 32px; } +.special-condolence-apply .el-descriptions .el-input__inner { height: 32px; line-height: 32px; font-size: 14px; } +.special-condolence-apply .el-descriptions .el-input__icon { line-height: 32px; } +.special-condolence-apply .el-descriptions .el-textarea__inner { font-size: 14px; line-height: 22px; } + +.special-condolence-apply .el-descriptions-item__label { width: 130px; color: #606266; background: #f7f9fc; } +.special-condolence-apply .special-condolence-recipients { margin: 28px 0; border: 1px solid #e4e7ed; border-radius: 6px; overflow: hidden; } +.special-condolence-apply .special-condolence-toolbar { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 14px; padding: 18px 20px; } +.special-condolence-apply .special-condolence-toolbar .special-condolence-section-title { margin: 0 0 4px; } +.special-condolence-hint { color: #606266; font-size: 12px; line-height: 20px; } +.special-condolence-apply .special-condolence-toolbar-buttons { display: flex; flex-wrap: wrap; gap: 8px; } +.special-condolence-apply .special-condolence-toolbar-buttons .el-button { margin: 0; } +.special-condolence-apply .special-condolence-table-item { margin: 0; } +.special-condolence-apply .special-condolence-table-item > .el-form-item__content { line-height: normal; } +.special-condolence-apply .special-condolence-table-item .el-form-item__error { position: static; padding: 8px 20px; } +.special-condolence-apply .special-condolence-table-item .el-table th { background: #f5f7fa; color: #606266; font-weight: 600; } +.special-condolence-apply .special-condolence-table-item .el-table .cell { padding: 0 8px; } +.special-condolence-apply .special-condolence-table-item .el-select, +.special-condolence-apply .special-condolence-table-item .el-input-number, +.special-condolence-apply .special-condolence-table-item .el-date-editor { width: 100%; } +.special-condolence-apply .special-condolence-table-item .el-input-number .el-input__inner { text-align: right; } +.special-condolence-apply .special-condolence-delete { color: #d64040; } +.special-condolence-apply .special-condolence-table-footer { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 10px; padding: 10px 20px; background: #fafbfd; } +.special-condolence-apply .special-condolence-total { display: flex; align-items: baseline; gap: 6px; color: #606266; font-size: 13px; font-variant-numeric: tabular-nums; } +.special-condolence-apply .special-condolence-total > span { margin-left: 18px; } +.special-condolence-apply .special-condolence-total-amount { color: #303133; font-size: 20px; } +.special-condolence-apply .special-condolence-actions { gap: 12px; margin-top: 24px; padding-top: 20px; border-top: 1px solid #ebeef5; } +.special-condolence-apply .special-condolence-actions .el-button { margin: 0; min-width: 108px; } +.special-condolence-dialog { max-width: calc(100vw - 32px); border-radius: 8px; } +.special-condolence-dialog .el-dialog__header { padding: 22px 24px 16px; border-bottom: 1px solid #ebeef5; } +.special-condolence-dialog .el-dialog__body { padding: 24px; } +.special-condolence-dialog .el-dialog__footer { padding: 16px 24px; border-top: 1px solid #ebeef5; } +.special-condolence-dialog .special-condolence-template { display: flex; align-items: center; flex-wrap: wrap; gap: 12px; padding: 16px; border: 1px solid #dce6f3; border-radius: 6px; background: #f6f9fe; } +.special-condolence-dialog .special-condolence-template > i { color: #409eff; font-size: 28px; } +.special-condolence-dialog .special-condolence-template > div { flex: 1; min-width: 180px; } +.special-condolence-dialog .special-condolence-template p { margin: 5px 0 0; color: #606266; font-size: 12px; line-height: 18px; } +.special-condolence-dialog .special-condolence-upload-title { margin: 22px 0 12px; font-weight: 600; } +.special-condolence-dialog .special-condolence-upload .el-upload, +.special-condolence-dialog .special-condolence-upload .el-upload-dragger { width: 100%; } +.special-condolence-dialog .special-condolence-upload .el-upload-dragger { height: auto; min-height: 150px; padding: 22px 12px; } +.special-condolence-dialog .special-condolence-upload .el-icon-upload, +.special-condolence-dialog .special-condolence-upload .el-icon-loading { display: block; margin: 0 0 16px; color: #909399; font-size: 44px; line-height: 48px; } +.special-condolence-dialog .el-upload__tip { margin-bottom: 16px; line-height: 20px; } +.special-condolence-dialog .special-condolence-batch-note { margin-bottom: 24px; padding: 12px 16px; background: #f5f7fa; border-radius: 4px; line-height: 22px; } +.special-condolence-dialog .special-condolence-batch-form .el-select, +.special-condolence-dialog .special-condolence-batch-form .el-input-number, +.special-condolence-dialog .special-condolence-batch-form .el-date-editor { width: 100%; } +@media (max-width: 768px) { + .special-condolence-apply .el-card__body { padding: 16px; } + .special-condolence-apply .special-condolence-toolbar { padding: 14px; } + .special-condolence-apply .special-condolence-total > span { margin-left: 8px; } +} + +.special-condolence-apply .special-condolence-table-item .el-table .el-form-item { margin: 8px 0 20px; } +.special-condolence-apply .special-condolence-table-item .el-table .el-form-item__error { position: absolute; padding: 4px 0 0; font-size: 11px; line-height: 14px; white-space: normal; } diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/apply/recipients.html b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/apply/recipients.html new file mode 100644 index 0000000..ad8c2f6 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/apply/recipients.html @@ -0,0 +1,63 @@ +
统一慰问配置
+ + + + + + + + + + + + + + + + + + + +
+
+
+
慰问对象明细 {{ recipientCount }} 人
+
一行填写一位慰问对象,所有人员随本申请统一审批。
+
+
+ Excel 导入 + 新增慰问对象 +
+
+ + + + + + + + + + + + + +
+ +
+ +
第一步:下载并填写模板

按模板表头填写,一行对应一位慰问对象。

+ 下载模板 +
+
第二步:上传填写好的文件
+ + +
{{ importLoading ? '正在导入,请稍候…' : '将 Excel 文件拖到此处,或点击选择文件' }}
+
支持 .xlsx、.xls 格式,单次最多 1000 行。导入的数据将追加到当前表格。
+
+ + 关闭 +
diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/apply/recipients.js b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/apply/recipients.js new file mode 100644 index 0000000..603b46b --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/apply/recipients.js @@ -0,0 +1,88 @@ +const specialCondolenceRecipients = { + data() { + return { recipientRules: this.createRecipientRules(), importVisible: false, importLoading: false } + }, + computed: { + recipientCount() { + return (this.formData.recipients || []).length + }, + recipientTotal() { + const money = Number(this.formData.perMoney) + const cents = (Number.isFinite(money) && money > 0 ? Math.round(money * 100) : 0) * this.recipientCount + return (cents / 100).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + } + }, + watch: { + typeOptions() { this.chooseType = this.typeOptions.find(t => t.id === this.formData.type) || {} }, + 'formData.type'(value) { this.chooseType = this.typeOptions.find(t => t.id === value) || {} } + }, + methods: { + createRecipientRules() { + const required = label => ({ required: true, whitespace: true, message: '请填写' + label, trigger: ['blur', 'change'] }) + return { + helpUserId: [{ required: true, message: '请选择慰问对象', trigger: 'change' }], + type: [{ required: true, message: '请选择慰问类型', trigger: 'change' }], + idCard: [required('身份证号码'), { validator: (rule, value, cb) => cb(this.validRecipientIdCard(value) ? undefined : new Error('身份证号码不正确')), trigger: ['blur', 'change'] }], + bankOfDeposit: [required('开户行'), { max: 100, message: '开户行最多100字', trigger: 'blur' }], + bankUserName: [required('户名'), { max: 100, message: '户名最多100字', trigger: 'blur' }], + bankCardNumber: [required('收款账户'), { pattern: /^[0-9]{6,30}$/, message: '请输入6至30位数字账户', trigger: ['blur', 'change'] }], + money: [{ validator: (rule, value, cb) => cb(/^(0|[1-9][0-9]*)(\.[0-9]{1,2})?$/.test(String(value)) && Number(value) > 0 && Number(value) <= 10000 ? undefined : new Error('金额须大于0且不超过10000元,最多两位小数')), trigger: ['blur', 'change'] }], + occurTime: [{ validator: (rule, value, cb) => cb(this.$moment(value, 'YYYY-MM-DD', true).isValid() ? undefined : new Error('请选择有效慰问时间')), trigger: ['blur', 'change'] }] + } + }, + validRecipientIdCard(value) { + const card = String(value || '').toUpperCase() + if (!/^[1-9][0-9]{16}[0-9X]$/.test(card) || !this.$moment(card.substring(6, 14), 'YYYYMMDD', true).isValid()) return false + const weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] + return '10X98765432'[weights.reduce((sum, weight, index) => sum + weight * Number(card[index]), 0) % 11] === card[17] + }, + recipientOptions(row) { + return row.helpUserId ? [{ id: row.helpUserId, userName: row.helpUserName, loginName: row.helpLoginName }] : [] + }, + seedRecipientOptions(row, index) { + const component = this.$refs['recipientUser' + index] + if (component && row.helpUserId) component.options = this.recipientOptions(row) + }, + recipientUserChange(row, index, id) { + const component = this.$refs['recipientUser' + index] + const user = component && component.options.find(item => item.id === id) + this.$set(row, 'helpUserId', user ? user.id : '') + this.$set(row, 'helpUserName', user ? user.userName : '') + this.$set(row, 'helpLoginName', user ? user.loginName : '') + this.$set(row, 'personType', user ? user.personType : '') + this.$set(row, 'idCard', user ? user.idCard || '' : '') + this.$set(row, 'bankOfDeposit', user ? user.bankOfDeposit || '' : '') + this.$set(row, 'bankUserName', user ? user.bankUserName || user.userName : '') + this.$set(row, 'bankCardNumber', user ? user.bankCardNumber || '' : '') + this.$nextTick(() => this.$refs.formRef.validateField('recipients.' + index + '.helpUserId')) + }, + + newRecipient() { + return { helpUserId: '', helpLoginName: '', personType: '', helpUserName: '', idCard: '', bankOfDeposit: '', bankUserName: '', bankCardNumber: '' } + }, + initRecipients() { + if (this.formData.perMoney == null && this.formData.recipients && this.formData.recipients.length) this.$set(this.formData, 'perMoney', Number(this.formData.recipients[0].money)) + if (!this.formData.recipients || !this.formData.recipients.length) { + this.$set(this.formData, 'recipients', this.formData.helpUserName ? [Object.assign(this.newRecipient(), this.formData, { recipients: undefined })] : [this.newRecipient()]) + } + }, + async importRecipients(request) { + this.importLoading = true + try { + const data = new FormData() + data.append('file', request.file) + const result = await this.$axios.post('/platform/special_condolence/apply/importRecipients', data) + if (result.code === 0) { + const rows = this.formData.recipients.filter(r => r.helpUserName || r.type || r.idCard || r.bankCardNumber || r.bankUserName || r.bankOfDeposit || r.money) + this.$set(this.formData, 'recipients', rows.concat(result.data)) + this.importVisible = false + this.$message.success('导入成功,共' + result.data.length + '人') + } else this.$message.error(result.msg || '导入失败') + } catch (error) { + this.$message.error('导入失败,请检查文件内容后重试') + } finally { + this.importLoading = false + } + } + } +} diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/common/info.js b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/common/info.js new file mode 100644 index 0000000..23ccd0f --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/common/info.js @@ -0,0 +1,157 @@ +const specialcondolenceInfo = { + template: /*language=HTML*/ ` +
+
+ 申请信息 + 点击查看流程图 +
+ + {{ viewData.applyUserName }} + {{ viewData.applyLoginName }} + {{ viewData.applyUnitName }} + {{ viewData.applyUnionName }} + + + +
{{ viewData.remark }}
+
+ + + 暂无附件 + + + + 暂无签字 + +
+ +
+ 慰问对象明细 {{ viewData.recipients.length }} 人 + 慰问金额合计:¥ {{ detailTotal }} +
+ + + + + + + + + + + + +
+ `, + store, + dicts: ["PROCESS_TASK_SUBMIT_TYPE"], + data() { + return { + visible: false, + viewData: {}, + doneTasks: [], + row: null + } + }, + computed: { + detailTotal() { + const cents = (this.viewData.recipients || []).reduce((sum, row) => { + const money = Number(row.money) + return sum + (Number.isFinite(money) ? Math.round(money * 100) : 0) + }, 0) + return (cents / 100).toLocaleString('zh-CN', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + } + }, + methods: { + onOpen(row) { + this.row = row + this.visible = true + this.getInfo() + this.getDoneTasks() + }, + getInfo() { + this.$axios.post('/platform/special_condolence/mine/info', {id: this.row.id}).then((res) => { + if (res.code === 0) { + this.viewData = res.data + } + }) + }, + // 获取已办任务审批记录 + getDoneTasks() { + this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => { + if (res.code === 0) { + this.doneTasks = res.data + } + }) + }, + // 查看流程图 + openChart(){ + this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId, this.row.instanceId) + } + }, + style: /*language=CSS*/ ` + .el-descriptions-item__label { + width: 200px; + min-width: 200px; + max-width: 200px; + } + .el-tabs__header { + margin: 0; + } + ` +} diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/fourthApproval/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/fourthApproval/index.html new file mode 100644 index 0000000..2b4cd75 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/fourthApproval/index.html @@ -0,0 +1,229 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 已审核 + 未审核 + + + + + + + + + + + + + + + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/mine/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/mine/index.html new file mode 100644 index 0000000..6aebbd1 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/mine/index.html @@ -0,0 +1,170 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + 新增申请 + + + + + + + + + + + + + + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/read/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/read/index.html new file mode 100644 index 0000000..a58a6b9 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/read/index.html @@ -0,0 +1,162 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 导出 + + + + + + + + + + + + + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/schoolPrincipalApproval/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/schoolPrincipalApproval/index.html new file mode 100644 index 0000000..2b4cd75 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/schoolPrincipalApproval/index.html @@ -0,0 +1,229 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 已审核 + 未审核 + + + + + + + + + + + + + + + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/schoolUnionApproval/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/schoolUnionApproval/index.html new file mode 100644 index 0000000..2b4cd75 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/schoolUnionApproval/index.html @@ -0,0 +1,229 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 已审核 + 未审核 + + + + + + + + + + + + + + + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/type/basicForm.js b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/type/basicForm.js new file mode 100644 index 0000000..38c7132 --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/type/basicForm.js @@ -0,0 +1,101 @@ +const basicForm = { + template: /*language=HTML*/ ` +
+ + + + + + + + + + + + + 慰问金 (A) + 提货券 (B) + 慰问品 (C) + + + + + + + + + + 是 + 否 + + + + + + + + 取消 + 提交 + +
+ `, + data() { + return { + formData: { isUploadFile: false }, + formRules: { + name: [{required: true, message: '必填', trigger: ['blur', 'change']}], + money: [{required: true, message: '必填', trigger: ['blur', 'change']}], + way: [{required: true, message: '必填', trigger: ['blur', 'change']}], + code: [{required: true, message: '必填', trigger: ['blur', 'change']}], + isUploadFile: [{required: true, message: '必填', trigger: ['blur', 'change']}], + }, + } + }, + methods: { + onOpen(row) { + if(row && row.id) { + this.formData = clone(row) + } else { + this.formData = { isUploadFile: false } + } + }, + onSubmit() { + this.$refs.formRef.validate((valid) => { + if (valid) { + this.$confirm("您确定要提交吗?", "提示", { + confirmButtonText: "确定", + cancelButtonText: "取消", + type: "warning" + }).then(async () => { + const resp = await this.$axios.post("/platform/special_condolence/type/onSubmit", this.formData) + if (resp.code === 0) { + this.$message.success(resp.msg) + this.$emit('refresh') + } else { + this.$message.warning(resp.msg) + } + }) + } + }) + }, + }, + style: /*language=CSS*/ ` + .el-input-number .el-input__inner { + text-align: left; + } + ` +} diff --git a/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/type/index.html b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/type/index.html new file mode 100644 index 0000000..2e3f29a --- /dev/null +++ b/src/main/resources/views/platform/zhgh/staffbenefit/specialcondolence/type/index.html @@ -0,0 +1,148 @@ + + + + +
+ + + + + + + +
+ + diff --git a/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/apply/index.html b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/apply/index.html new file mode 100644 index 0000000..a11456e --- /dev/null +++ b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/apply/index.html @@ -0,0 +1,513 @@ + + + + +
+ + + + + + + +
+

基本信息

+ + + + + + + + + +
+ 删除 + + + + + + +
+ 增加一行 + +
+
+ +
+

附件材料

+
+ {{ '附件说明:' + chooseType.uploadFileDesc }} +
+ + + + + +
+ +
+

签字确认

+ + + + + +
+ + +
+ 保存申请 + 提交申请 + 提交申请 +
+
+
+ + + + diff --git a/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/common/info.css b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/common/info.css new file mode 100644 index 0000000..389aa4c --- /dev/null +++ b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/common/info.css @@ -0,0 +1,201 @@ +.specialcondolence-full-popup { + --color-primary: #1989fa; + width: 100%; + height: 100%; + overflow: hidden; + background: #f3f7fc; +} + +.specialcondolence-full-popup__page { + display: flex; + height: 100%; + padding-top: 46px; + overflow: hidden; + box-sizing: border-box; + flex-direction: column; +} + +.specialcondolence-full-popup__page > .van-nav-bar { + z-index: 20; + background: #fff; +} + +.specialcondolence-full-popup__page > .van-nav-bar .van-icon, +.specialcondolence-full-popup__page > .van-nav-bar .van-nav-bar__text { + color: #1989fa; +} + +.specialcondolence-full-popup__scroll { + min-height: 0; + overflow-y: auto; + flex: 1; + -webkit-overflow-scrolling: touch; +} + +.specialcondolence-info-main { + padding: 12px 15px calc(18px + env(safe-area-inset-bottom)); +} + +.specialcondolence-info-card { + margin-bottom: 11px; + overflow: hidden; + border: 1px solid #e9eff7; + border-radius: 10px; + background: #fff; + box-shadow: 0 3px 11px rgba(51, 87, 126, .08); +} + +.specialcondolence-info-card__title { + position: relative; + margin: 0; + padding: 12px 14px 8px 21px; + color: #354255; + font-size: 15px; + font-weight: 600; + line-height: 22px; +} + +.specialcondolence-info-card__title::before { + position: absolute; + top: 15px; + bottom: 11px; + left: 12px; + width: 2px; + border-radius: 2px; + background: #1989fa; + content: ""; +} + +/* 审核意见复用详情 Card 标题,并与提案 delegation 审核输入区保持一致。 */ +.specialcondolence-audit-card__required { + margin-left: 4px; + color: #ee0a24; + font-size: 14px; +} + +.specialcondolence-info-card .van-field.specialcondolence-audit-field { + width: calc(100% - 28px); + margin: 0 14px 14px; + padding: 12px; + box-sizing: border-box; + border: 1px solid #c9d5e5; + border-radius: 10px; + background: #f7f9fd; +} + +.specialcondolence-info-card .van-field.specialcondolence-audit-field .van-field__control { + min-height: 150px; + color: #253247; + line-height: 22px; +} + +.specialcondolence-info-card .van-field.specialcondolence-audit-field .van-field__control::placeholder { + color: #9aa7b8; +} + +.specialcondolence-info-card .van-field.specialcondolence-audit-field .van-field__word-limit { + color: #718096; +} + +.specialcondolence-info-card .van-field.specialcondolence-audit-field::after { + display: none; +} + +.specialcondolence-popup-actions { + display: flex; + padding: 10px 12px calc(12px + env(safe-area-inset-bottom)); + justify-content: space-between; + column-gap: 10px; + background: transparent; +} + +.specialcondolence-popup-actions .van-button { + border-radius: 14px; +} + +.specialcondolence-popup-actions .specialcondolence-action-primary { + border-color: #1989fa; + background: #1989fa; +} + +.specialcondolence-popup-actions .specialcondolence-action-danger { + border-color: #ff4d4f; + background: #ff4d4f; +} + +.specialcondolence-info-card .van-cell-group { + margin: 0; + background: transparent; +} + +.specialcondolence-info-card .van-cell { + min-height: 44px; + padding: 10px 14px; + background: transparent; +} + +.specialcondolence-info-card .van-cell:not(:last-child)::after { + right: 14px; + left: 14px; + border-color: #eef2f7; +} + +.specialcondolence-info-card .van-cell__title { + width: 102px; + color: #596779; + font-size: 12px; + line-height: 24px; + flex: 0 0 102px; +} + +.specialcondolence-info-card .van-cell__value { + min-width: 0; + color: #4f5d70; + font-size: 12px; + line-height: 24px; + text-align: left; + overflow-wrap: anywhere; +} + +.specialcondolence-info-long-cell { + display: flex; + align-items: flex-start; +} + +.specialcondolence-info-card .specialcondolence-attachments .empty-container { + height: auto; + justify-content: flex-start; + color: inherit; +} + +.specialcondolence-info-card .specialcondolence-attachments .empty-text { + font-size: inherit; + line-height: inherit; +} + +.specialcondolence-info-opinion > :first-child { + margin-top: 0; +} + +.specialcondolence-info-opinion > :last-child { + margin-bottom: 0; +} + +.specialcondolence-signature-image, +.specialcondolence-approval-signature-image { + display: block; + width: 100%; + max-width: 100%; + height: 80px; +} + +.specialcondolence-signature-image .van-image__img, +.specialcondolence-approval-signature-image { + object-fit: contain; + object-position: left center; +} + +.specialcondolence-info-opinion img { + max-width: 100%; + height: auto; +} diff --git a/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/common/info.js b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/common/info.js new file mode 100644 index 0000000..81cd59f --- /dev/null +++ b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/common/info.js @@ -0,0 +1,193 @@ +const specialcondolenceInfo = { + template: /*language=HTML*/ ` + +
+ +
+
+
+

基本信息

+ + {{ viewData.applyUserName || '--' }} + {{ viewData.applyLoginName || '--' }} + {{ viewData.applyUnitName || '--' }} + {{ viewData.applyUnionName || '--' }} + + + + + + + + + 暂无签字 + + +
+ +
+

{{ task.displayName || '办理记录' }}

+ + + {{ task.ext.initiatorName || '--' }}({{ task.ext.initiatorAccount || '--' }}) + + {{ task.finishTime || '--' }} + + + + + + + {{ task.taskFormData && task.taskFormData.userName || '--' }}({{ task.taskFormData && task.taskFormData.loginName || '--' }}) + + {{ task.finishTime || '--' }} + + + + + + + +
+
+
+
+ + +
+
+
+
+ `, + dicts: ["PROCESS_TASK_SUBMIT_TYPE"], + props: { + pageKey: { + type: String, + required: true + } + }, + data() { + return { + visible: false, + popupTitle: "慰问详情", + viewData: {}, + doneTasks: [], + row: null, + historyLayerUnsubscribe: null + } + }, + methods: { + // 浏览器历史变化时,只同步当前慰问详情弹框的显示状态。 + syncHistoryLayerStack(stack) { + this.$set(this, "visible", stack.includes("specialcondolence-detail")) + }, + + /** + * 打开慰问详情或审核弹框。 + * row 传列表当前行,title 传顶部导航标题;无返回值。 + */ + onOpen(row, title = "慰问详情") { + this.$set(this, "row", row) + this.$set(this, "popupTitle", title) + this.$set(this, "viewData", {}) + this.$set(this, "doneTasks", []) + this.getInfo() + this.getDoneTasks() + if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.open("specialcondolence-detail")) return + this.$set(this, "visible", true) + }, + + // 顶部返回按钮与业务主动关闭统一回退弹框对应的浏览器历史。 + onClose(afterClose = null) { + if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.close("specialcondolence-detail", afterClose)) return + this.$set(this, "visible", false) + if (typeof afterClose === "function") afterClose() + }, + + getInfo() { + this.$axios.post("/platform/special_condolence/mine/info", {id: this.row.id}).then((res) => { + if (res.code === 0) { + this.$set(this, "viewData", res.data || {}) + } + }) + }, + + getDoneTasks() { + this.$axios.post("/flow/common/doneTasks", {bizId: this.row.id}).then((res) => { + if (res.code === 0) { + this.$set(this, "doneTasks", res.data || []) + } + }) + } + }, + created() { + if (!window.h5HistoryLayerManager) return + window.h5HistoryLayerManager.ensureRegistered(this.pageKey) + this.$set(this, "historyLayerUnsubscribe", window.h5HistoryLayerManager.subscribe((stack) => { + this.syncHistoryLayerStack(stack) + })) + }, + beforeDestroy() { + if (typeof this.historyLayerUnsubscribe === "function") this.historyLayerUnsubscribe() + if (window.h5HistoryLayerManager && window.h5HistoryLayerManager.pageKey === this.pageKey) { + window.h5HistoryLayerManager.unregister(this.pageKey) + } + } +} diff --git a/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/fourthApproval/index.html b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/fourthApproval/index.html new file mode 100644 index 0000000..813b7ff --- /dev/null +++ b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/fourthApproval/index.html @@ -0,0 +1,367 @@ + + + + + + +
+
+ + + +
+ + + + + + +
+
+ +
+
+
+ +
+
+ + + + + + +
+ + +
+
+

+ 审批意见* +

+ + +

+ 审批签字* +

+ + + +
+
+
+ 退回 + 不同意 + 同意 +
+
+
+ +
+
+ + + + diff --git a/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/mine/index.html b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/mine/index.html new file mode 100644 index 0000000..e18f98b --- /dev/null +++ b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/mine/index.html @@ -0,0 +1,475 @@ + + + + + + +
+
+ + + +
+ + + + + +
+
+ +
+
+
+ +
+
+ + + + + + +
+ + +
+
+ + + + diff --git a/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/schoolPrincipalApproval/index.html b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/schoolPrincipalApproval/index.html new file mode 100644 index 0000000..74fc295 --- /dev/null +++ b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/schoolPrincipalApproval/index.html @@ -0,0 +1,350 @@ + + + + + + +
+
+ + + +
+ + + + + + +
+
+ +
+
+
+ +
+
+ + + + + + +
+ + +
+
+

+ 审批意见* +

+ + +

+ 审批签字* +

+ + + +
+
+
+ 退回 + 不同意 + 同意 +
+
+
+ +
+
+ + + + diff --git a/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/schoolUnionApproval/index.html b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/schoolUnionApproval/index.html new file mode 100644 index 0000000..a6e658f --- /dev/null +++ b/src/main/resources/views/platform/zhghh5/staffbenefit/specialcondolence/schoolUnionApproval/index.html @@ -0,0 +1,350 @@ + + + + + + +
+
+ + + +
+ + + + + + +
+
+ +
+
+
+ +
+
+ + + + + + +
+ + +
+
+

+ 审批意见* +

+ + +

+ 审批签字* +

+ + + +
+
+
+ 退回 + 不同意 + 同意 +
+
+
+ +
+
+ + + +