From 0a2e7b3502cb86101997a76722538dc9d2fa495d Mon Sep 17 00:00:00 2001 From: zhouhefeng Date: Thu, 14 May 2026 10:26:44 +0800 Subject: [PATCH] commit --- .../sys/controller/SysLoginController.java | 2 + .../sys/services/impl/SysMsgServiceImpl.java | 4 - .../app/todo/platform/TodoPlatformConfig.java | 14 +- .../WorkflowMessageAuditController.java | 59 +++ .../controller/WorkflowMessageController.java | 103 +++++ .../models/WorkflowMessage.java | 121 ++++++ .../models/WorkflowMessageReceiver.java | 88 ++++ .../service/WorkflowMessageAuditService.java | 25 ++ .../service/WorkflowMessageService.java | 75 ++++ .../impl/WorkflowMessageAuditServiceImpl.java | 205 +++++++++ .../impl/WorkflowMessageServiceImpl.java | 389 ++++++++++++++++++ .../views/platform/sys/role/index.html | 30 +- .../workflowmessage/apply/index.html | 223 ++++++++++ .../workflowmessage/audit/index.html | 203 +++++++++ .../dayofficework/workflowmessage/info.js | 95 +++++ 15 files changed, 1610 insertions(+), 26 deletions(-) create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/controller/WorkflowMessageAuditController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/controller/WorkflowMessageController.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/models/WorkflowMessage.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/models/WorkflowMessageReceiver.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/WorkflowMessageAuditService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/WorkflowMessageService.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/impl/WorkflowMessageAuditServiceImpl.java create mode 100644 src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/impl/WorkflowMessageServiceImpl.java create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workflowmessage/apply/index.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workflowmessage/audit/index.html create mode 100644 src/main/resources/views/platform/zhgh/dayofficework/workflowmessage/info.js diff --git a/src/main/java/com/budwk/app/sys/controller/SysLoginController.java b/src/main/java/com/budwk/app/sys/controller/SysLoginController.java index 1a95de1..9e1f822 100644 --- a/src/main/java/com/budwk/app/sys/controller/SysLoginController.java +++ b/src/main/java/com/budwk/app/sys/controller/SysLoginController.java @@ -63,6 +63,7 @@ public class SysLoginController { @Inject protected PropertiesProxy conf; +/* @At("") @Ok("re") @ApiOperation("用户本地登录页面") @@ -70,6 +71,7 @@ public class SysLoginController { public String login(HttpServletRequest req, HttpSession session) { return "beetl:/platform/sys/login.html"; } +*/ @At @Ok("re") diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysMsgServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysMsgServiceImpl.java index 998f801..5d426a4 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysMsgServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysMsgServiceImpl.java @@ -103,12 +103,8 @@ public class SysMsgServiceImpl extends BaseServiceImpl implements SysMs }); //发送学校平台消息 -// for (String loginName : loginNames) { -// smsService.send(loginName, sysMsg.getTitle(), sysMsg.getNote()); -// } if(sysMsg.getWechatEnterprise()) { ThreadUtil.execute(() -> { - //smsService.massSend(loginNames, sysMsg.getTitle(), HtmlUtil.cleanHtmlTag(StrUtil.blankToDefault(sysMsg.getNote(),"")), sysMsg.getUrl()); String plainText = SysMsgServiceImpl.htmlToPlainText(StrUtil.blankToDefault(sysMsg.getNote(), "")); smsService.massSendMessage(loginNames, HtmlUtil.cleanHtmlTag(plainText)); }); diff --git a/src/main/java/com/budwk/app/todo/platform/TodoPlatformConfig.java b/src/main/java/com/budwk/app/todo/platform/TodoPlatformConfig.java index 76647ab..13aa988 100644 --- a/src/main/java/com/budwk/app/todo/platform/TodoPlatformConfig.java +++ b/src/main/java/com/budwk/app/todo/platform/TodoPlatformConfig.java @@ -10,20 +10,20 @@ package com.budwk.app.todo.platform; public class TodoPlatformConfig { // token 获取 - public static final String TOKEN_URL = "https://gateway.jshvc.edu.cn/token/gateway/accessToken"; + public static final String TOKEN_URL = "/accessToken"; // 待办平台基础地址 public static final String TODO_PLATFORM_BASE_URL = "https://gateway.jshvc.edu.cn"; // 待办平台新增或者修改 - public static final String TODO_PLATFORM_SAVE_OR_UPDATE_URL = "https://gateway.jshvc.edu.cn/casp-tdc/task/saveOrUpdate"; + public static final String TODO_PLATFORM_SAVE_OR_UPDATE_URL = "/saveOrUpdate"; // 待办平台修改地址 - public static final String TODO_PLATFORM_MODIFY_URL = "https://gateway.jshvc.edu.cn/casp-tdc/task/modifyInfo"; + public static final String TODO_PLATFORM_MODIFY_URL = "/modifyInfo"; // 待办平台删除任务地址 - public static final String TODO_PLATFORM_DELETE_TASK_URL = "https://gateway.jshvc.edu.cn/casp-tdc/task/delete"; + public static final String TODO_PLATFORM_DELETE_TASK_URL = "/delete"; // 待办平台删除实例地址 - public static final String TODO_PLATFORM_DELETE_INSTANCE_URL = "https://gateway.jshvc.edu.cn/casp-tdc/processInstance/realDelete"; + public static final String TODO_PLATFORM_DELETE_INSTANCE_URL = "/realDelete"; - public static final String TODO_APP_ID = "1430576717768122368"; - public static final String TODO_APP_SECRET = "19A0ACB03FBQHL4R4XQD"; + public static final String TODO_APP_ID = "XXXXXXXXXXXXXXXXXXXXXX"; + public static final String TODO_APP_SECRET = "XXXXXXXXXXXXXXXXXXXXXX"; public static final String REDIS_KEY_TODO_ACCESS_TOKEN = "todo:token:"; public static final Long TODO_REQUEST_TIMEOUT = 5000L; diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/controller/WorkflowMessageAuditController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/controller/WorkflowMessageAuditController.java new file mode 100644 index 0000000..209ce9b --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/controller/WorkflowMessageAuditController.java @@ -0,0 +1,59 @@ +package com.budwk.app.zhgh.dayofficework.workflowmessage.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.zhgh.dayofficework.workflowmessage.service.WorkflowMessageAuditService; +import com.budwk.app.zhgh.dayofficework.workflowmessage.service.WorkflowMessageService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.mvc.annotation.At; +import org.nutz.mvc.annotation.Ok; +import org.nutz.mvc.annotation.Param; + +import javax.validation.Valid; + +@IocBean +@At("/platform/dayofficework/workflowmessage/audit") +@Ok("json:full") +@Api(tags = "工作流消息审核") +public class WorkflowMessageAuditController { + + @Inject + private WorkflowMessageAuditService workflowMessageAuditService; + @Inject + private WorkflowMessageService workflowMessageService; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workflowmessage/audit/index.html") + @SaCheckPermission("dayofficework.message.workflow.audit") + @ApiOperation("工作流消息审核页面") + public void index() { + } + + @At + @SaCheckPermission("dayofficework.message.workflow.audit") + @ApiOperation("消息审核列表") + public Result pageData(@Valid PageForm pageForm) { + return Result.success(workflowMessageAuditService.pageData(pageForm)); + } + + @At + @SaCheckPermission("dayofficework.message.workflow.audit") + @ApiOperation("消息申请详情") + public Result info(@Param("id") String id) { + return Result.success(workflowMessageService.info(id)); + } + + @At + @SaCheckPermission("dayofficework.message.workflow.audit") + @ApiOperation("审核消息发送申请") + @SLog(tag = "工作流消息审核", msg = "审核消息发送申请") + public Result audit(@Param("taskId") Long taskId, @Param("opinion") String opinion, @Param("action") Integer action) { + workflowMessageAuditService.audit(taskId, opinion, action); + return Result.success(); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/controller/WorkflowMessageController.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/controller/WorkflowMessageController.java new file mode 100644 index 0000000..729aeaa --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/controller/WorkflowMessageController.java @@ -0,0 +1,103 @@ +package com.budwk.app.zhgh.dayofficework.workflowmessage.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.budwk.app.base.annotation.RepeatSubmit; +import com.budwk.app.base.annotation.SLog; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.result.Result; +import com.budwk.app.sys.models.Sys_role; +import com.budwk.app.zhgh.dayofficework.workflowmessage.models.WorkflowMessage; +import com.budwk.app.zhgh.dayofficework.workflowmessage.service.WorkflowMessageService; +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.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 javax.validation.Valid; + +@IocBean +@At("/platform/dayofficework/workflowmessage") +@Ok("json:full") +@Api(tags = "工作流消息申请") +public class WorkflowMessageController { + + @Inject + private WorkflowMessageService workflowMessageService; + @Inject + private Dao dao; + + @At("") + @Ok("beetl:/platform/zhgh/dayofficework/workflowmessage/apply/index.html") + @SaCheckPermission("dayofficework.message.workflow") + @ApiOperation("工作流消息申请页面") + public void index() { + } + + @At + @SaCheckPermission("dayofficework.message.workflow") + @ApiOperation("消息申请列表") + public Result pageData(@Valid PageForm pageForm) { + return Result.success(workflowMessageService.pageData(pageForm)); + } + + @At + @SaCheckPermission("dayofficework.message.workflow") + @ApiOperation("提交消息发送申请") + @SLog(tag = "工作流消息管理", msg = "提交消息发送申请") + @Aop(TransAop.READ_COMMITTED) + public Result submit(@Param("message") @Valid WorkflowMessage message, @Param("users") String[] users) { + return Result.success(workflowMessageService.submit(message, users)); + } + + @At + @SaCheckPermission("dayofficework.message.workflow") + @ApiOperation("更新并重新提交消息发送申请") + @SLog(tag = "工作流消息管理", msg = "更新并重新提交消息发送申请") + public Result updateSubmit(@Param("message") @Valid WorkflowMessage message, @Param("users") String[] users, @Param("taskId") Long taskId) { + return Result.success(workflowMessageService.updateSubmit(message, users, taskId)); + } + + @At + @SaCheckPermission("dayofficework.message.workflow") + @ApiOperation("消息申请详情") + public Result info(@Param("id") String id) { + return Result.success(workflowMessageService.info(id)); + } + + @At + @SaCheckPermission("dayofficework.message.workflow") + @ApiOperation("消息接收人列表") + public Result receiverList(@Param("messageId") String messageId) { + return Result.success(workflowMessageService.receiverList(messageId)); + } + + @At + @SaCheckPermission("dayofficework.message.workflow") + @ApiOperation("删除消息申请") + @SLog(tag = "工作流消息管理", msg = "删除消息申请") + public Result delete(@Param("id") String id) { + workflowMessageService.deleteApply(id); + return Result.success(); + } + + @At + @SaCheckPermission("dayofficework.message.workflow") + @ApiOperation("可选接收人列表") + public Result userData(@Valid PageForm pageForm, String unionId, String unitId, String roleId, String sex, String clubId) { + return Result.success(workflowMessageService.userPageData(pageForm, unionId, unitId, roleId, sex, clubId)); + } + + @At + @SaCheckPermission("dayofficework.message.workflow") + @ApiOperation("角色列表") + public Result roleList() { + return Result.success(dao.query(Sys_role.class, Cnd.NEW())); + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/models/WorkflowMessage.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/models/WorkflowMessage.java new file mode 100644 index 0000000..d557e92 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/models/WorkflowMessage.java @@ -0,0 +1,121 @@ +package com.budwk.app.zhgh.dayofficework.workflowmessage.models; + +import cn.hutool.json.JSONObject; +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; + +import javax.validation.constraints.NotBlank; +import java.util.List; + +@Data +@EqualsAndHashCode(callSuper = true) +@Table("workflow_message") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@TableIndexes({ + @Index(name = "INDEX_WORKFLOW_MESSAGE_APPLY_STATUS", fields = "applyStatus", unique = false), + @Index(name = "INDEX_WORKFLOW_MESSAGE_PROCESS_INSTANCE", fields = "processInstanceId", unique = false) +}) +@Comment("工作流消息申请") +public class WorkflowMessage extends BaseModel { + + @Name + @Comment("ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + @PrevInsert(uu32 = true) + private String id; + + @Column + @Comment("消息标题") + @ColDefine(type = ColType.VARCHAR, width = 255) + @NotBlank(message = "消息标题不能为空") + private String title; + + @Column + @Comment("消息内容") + @ColDefine(type = ColType.TEXT) + @NotBlank(message = "消息内容不能为空") + private String note; + + @Column + @Comment("消息URL") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String url; + + @Column + @Comment("是否同步企业微信") + @ColDefine(type = ColType.BOOLEAN) + @Default("0") + private Boolean wechatEnterprise; + + @Column + @Comment("是否需要反馈") + @ColDefine(type = ColType.BOOLEAN) + @Default("0") + private Boolean needBack; + + @Column + @Comment("消息附件") + @ColDefine(type = ColType.MYSQL_JSON) + private List files; + + @Column + @Comment("流程实例ID") + private Long processInstanceId; + + @Column + @Comment("申请状态 10待审核 20审核通过 30审核拒绝 40退回发起人") + @ColDefine(type = ColType.INT) + private Integer applyStatus; + + @Column + @Comment("发送状态 0未发送 1已发送 2发送失败") + @ColDefine(type = ColType.INT) + private Integer sendStatus; + + @Column + @Comment("发送时间") + private Long sendAt; + + @Column + @Comment("发送结果") + @ColDefine(type = ColType.VARCHAR, width = 500) + private String sendResult; + + @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 applyUnitId; + + @Column + @Comment("申请人单位") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String applyUnitName; + + @Column + @Comment("申请人分工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String applyUnionId; + + @Column + @Comment("申请人分工会") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String applyUnionName; +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/models/WorkflowMessageReceiver.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/models/WorkflowMessageReceiver.java new file mode 100644 index 0000000..45af555 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/models/WorkflowMessageReceiver.java @@ -0,0 +1,88 @@ +package com.budwk.app.zhgh.dayofficework.workflowmessage.models; + +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("workflow_message_receiver") +@TableMeta("{'mysql-charset':'utf8mb4'}") +@TableIndexes({ + @Index(name = "INDEX_WORKFLOW_MESSAGE_RECEIVER_MSG", fields = "messageId", unique = false), + @Index(name = "INDEX_WORKFLOW_MESSAGE_RECEIVER_LOGIN", fields = "loginName", unique = false) +}) +@Comment("工作流消息接收人") +public class WorkflowMessageReceiver 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 messageId; + + @Column + @Comment("接收人ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String userId; + + @Column + @Comment("接收人工号") + @ColDefine(type = ColType.VARCHAR, width = 120) + private String loginName; + + @Column + @Comment("接收人姓名") + @ColDefine(type = ColType.VARCHAR, width = 120) + private String userName; + + @Column + @Comment("接收人性别") + @ColDefine(type = ColType.VARCHAR, width = 20) + private String sex; + + @Column + @Comment("接收人手机") + @ColDefine(type = ColType.VARCHAR, width = 50) + private String mobile; + + @Column + @Comment("在职状态") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String userState; + + @Column + @Comment("教职工类别") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String personType; + + @Column + @Comment("单位ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unitId; + + @Column + @Comment("单位名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String unitName; + + @Column + @Comment("分工会ID") + @ColDefine(type = ColType.VARCHAR, width = 32) + private String unionId; + + @Column + @Comment("分工会名称") + @ColDefine(type = ColType.VARCHAR, width = 100) + private String unionName; + + @One(target = WorkflowMessage.class, field = "messageId") + private WorkflowMessage message; +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/WorkflowMessageAuditService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/WorkflowMessageAuditService.java new file mode 100644 index 0000000..b9dae69 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/WorkflowMessageAuditService.java @@ -0,0 +1,25 @@ +package com.budwk.app.zhgh.dayofficework.workflowmessage.service; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import org.nutz.lang.util.NutMap; + +public interface WorkflowMessageAuditService { + + /** + * 查询消息审核任务列表。 + * + * @param pageForm 分页参数,audit=true 查询已审核,audit=false 查询待审核 + * @return 分页后的审核任务数据 + */ + Pagination pageData(PageForm pageForm); + + /** + * 执行消息审核任务,流程审核通过并结束后正式发送消息。 + * + * @param taskId 流程任务ID + * @param opinion 审核意见 + * @param action 提交类型,1同意、2拒绝、6退回发起人等 + */ + void audit(Long taskId, String opinion, Integer action); +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/WorkflowMessageService.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/WorkflowMessageService.java new file mode 100644 index 0000000..30a3175 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/WorkflowMessageService.java @@ -0,0 +1,75 @@ +package com.budwk.app.zhgh.dayofficework.workflowmessage.service; + +import com.budwk.app.base.page.Pagination; +import com.budwk.app.base.param.PageForm; +import com.budwk.app.base.service.BaseService; +import com.budwk.app.zhgh.dayofficework.workflowmessage.models.WorkflowMessage; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +public interface WorkflowMessageService extends BaseService { + + /** + * 保存消息申请并启动流程。 + * + * @param message 待审核消息,包含标题、内容、链接、附件和发送选项 + * @param users 接收人工号数组,审核通过后会按这些工号正式发送消息 + * @return 已保存并绑定流程实例的消息申请 + */ + WorkflowMessage submit(WorkflowMessage message, String[] users); + + /** + * 更新撤回后的消息申请并重新提交发起节点。 + * + * @param message 待更新消息,必须包含 id、标题、内容、附件和发送选项 + * @param users 接收人工号数组,会覆盖原接收人快照 + * @param startTaskId 撤回后发起节点任务ID,用于重新提交流程 + * @return 更新后的消息申请 + */ + WorkflowMessage updateSubmit(WorkflowMessage message, String[] users, Long startTaskId); + + /** + * 查询消息申请列表。 + * + * @param pageForm 分页与关键字参数,searchKeyword 用于匹配标题 + * @return 分页后的申请数据 + */ + Pagination pageData(PageForm pageForm); + + /** + * 获取消息申请详情。 + * + * @param id 消息申请ID + * @return 详情数据,包含消息主体和接收人列表 + */ + NutMap info(String id); + + /** + * 删除消息申请、接收人快照及关联流程实例。 + * + * @param id 消息申请ID + */ + void deleteApply(String id); + + /** + * 获取可选接收人列表。 + * + * @param pageForm 查询字段、关键字、分页参数 + * @param unionId 分工会ID + * @param unitId 单位ID + * @param roleId 角色ID + * @param sex 性别 + * @param clubId 协会ID + * @return 分页后的人员数据 + */ + Pagination userPageData(PageForm pageForm, String unionId, String unitId, String roleId, String sex, String clubId); + + /** + * 根据消息ID查询接收人快照。 + * + * @param messageId 消息申请ID + * @return 接收人列表 + */ + List receiverList(String messageId); +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/impl/WorkflowMessageAuditServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/impl/WorkflowMessageAuditServiceImpl.java new file mode 100644 index 0000000..6db101e --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/impl/WorkflowMessageAuditServiceImpl.java @@ -0,0 +1,205 @@ +package com.budwk.app.zhgh.dayofficework.workflowmessage.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.StrUtil; +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.service.impl.BaseServiceImpl; +import com.budwk.app.base.utils.PageUtil; +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.ProcessInstanceStateEnum; +import com.budwk.app.flow.enums.ProcessSubmitTypeEnum; +import com.budwk.app.flow.enums.ProcessTaskStateEnum; +import com.budwk.app.flow.service.FlowCommonService; +import com.budwk.app.sys.models.Sys_msg; +import com.budwk.app.sys.services.SysMsgService; +import com.budwk.app.web.commons.auth.utils.AuthUtil; +import com.budwk.app.web.commons.auth.utils.SecurityUtil; +import com.budwk.app.zhgh.dayofficework.workflowmessage.models.WorkflowMessage; +import com.budwk.app.zhgh.dayofficework.workflowmessage.models.WorkflowMessageReceiver; +import com.budwk.app.zhgh.dayofficework.workflowmessage.service.WorkflowMessageAuditService; +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.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +@IocBean(args = {"refer:dao"}) +public class WorkflowMessageAuditServiceImpl extends BaseServiceImpl implements WorkflowMessageAuditService { + + private static final String PROCESS_DEFINE_KEY = "XXZX"; + private static final int APPLY_STATUS_AUDITING = 10; + private static final int APPLY_STATUS_PASS = 20; + private static final int APPLY_STATUS_REJECT = 30; + private static final int APPLY_STATUS_ROLLBACK = 40; + private static final int SEND_STATUS_SUCCESS = 1; + private static final int SEND_STATUS_FAIL = 2; + + @Inject + private FlowEngine flowEngine; + @Inject + private FlowCommonService flowCommonService; + @Inject + private SysMsgService sysMsgService; + + public WorkflowMessageAuditServiceImpl(Dao dao) { + super(dao); + } + + @Override + public Pagination pageData(PageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + msg.*, + 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, + COUNT(DISTINCT receiver.id) receiverCount + FROM wf_process_task t + LEFT JOIN wf_process_instance ins ON ins.id = t.processInstanceId + LEFT JOIN wf_process_define def ON def.id = ins.processDefineId + LEFT JOIN workflow_message msg ON msg.id = ins.businessNo + LEFT JOIN wf_process_task_actor ta ON ta.processTaskId = t.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 + LEFT JOIN workflow_message_receiver receiver ON receiver.messageId = msg.id + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.and("def.name", "=", PROCESS_DEFINE_KEY); + cnd.and("msg.id", "is not", null); + if (!AuthUtil.hasRole(RoleConstant.SYSADMIN.name())) { + cnd.and("ta.actorId", "=", SecurityUtil.getUserId()); + } + if (Boolean.TRUE.equals(pageForm.getAudit())) { + cnd.and("t.taskState", "in", List.of(ProcessTaskStateEnum.FINISHED.getCode(), ProcessTaskStateEnum.INTERRUPT.getCode(), ProcessTaskStateEnum.WITHDRAW.getCode())); + } else { + cnd.and("t.taskState", "=", ProcessTaskStateEnum.DOING.getCode()); + } + cnd.and(Cnd.likeEX("msg.title", pageForm.getSearchKeyword())); + if (StrUtil.isAllNotBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.orderBy("msg." + pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } else { + cnd.desc("t.createdAt"); + } + cnd.groupBy("t.id"); + sql.setCondition(cnd); + return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + } + + @Override + @Aop(TransAop.READ_COMMITTED) + public void audit(Long taskId, String opinion, Integer action) { + ProcessTask task = flowEngine.processTaskService().fetch(taskId); + if (task == null) { + throw new BaseException("流程任务不存在"); + } + ProcessInstance instance = flowEngine.processInstanceService().fetch(task.getProcessInstanceId()); + if (instance == null) { + throw new BaseException("流程实例不存在"); + } + + // 参数含义:processTaskId 为当前流程任务,submitType 为审核动作,tf_opinion 为审核意见;流程组件会记录办理人和办理结果。 + Dict args = Dict.create(); + args.set(FlowConst.PROCESS_TASK_ID_KEY, taskId); + args.set(FlowConst.SUBMIT_TYPE, action); + args.set("tf_opinion", opinion); + flowCommonService.executeTask(args); + + ProcessInstance currentInstance = flowEngine.processInstanceService().fetch(instance.getId()); + WorkflowMessage message = dao().fetch(WorkflowMessage.class, instance.getBusinessNo()); + if (message == null) { + throw new BaseException("消息申请不存在"); + } + updateApplyStatusByTaskAction(message, action, currentInstance); + if (ProcessSubmitTypeEnum.AGREE.getCode().equals(action) + && ProcessInstanceStateEnum.FINISHED.getCode().equals(currentInstance.getState())) { + publishMessage(message.getId()); + } + } + + private void updateApplyStatusByTaskAction(WorkflowMessage message, Integer action, ProcessInstance instance) { + WorkflowMessage update = new WorkflowMessage(); + update.setId(message.getId()); + if (ProcessSubmitTypeEnum.REJECT.getCode().equals(action) + || ProcessInstanceStateEnum.REJECT.getCode().equals(instance.getState())) { + update.setApplyStatus(APPLY_STATUS_REJECT); + } else if (ProcessSubmitTypeEnum.ROLLBACK_TO_OPERATOR.getCode().equals(action)) { + update.setApplyStatus(APPLY_STATUS_ROLLBACK); + } else if (ProcessInstanceStateEnum.FINISHED.getCode().equals(instance.getState())) { + update.setApplyStatus(APPLY_STATUS_PASS); + } else { + update.setApplyStatus(APPLY_STATUS_AUDITING); + } + dao().updateIgnoreNull(update); + } + + private void publishMessage(String id) { + WorkflowMessage message = dao().fetch(WorkflowMessage.class, id); + if (message == null) { + throw new BaseException("消息申请不存在"); + } + if (Integer.valueOf(SEND_STATUS_SUCCESS).equals(message.getSendStatus())) { + return; + } + List receivers = dao().query(WorkflowMessageReceiver.class, Cnd.where(WorkflowMessageReceiver::getMessageId, "=", id)); + if (Lang.isEmpty(receivers)) { + throw new BaseException("消息接收人为空,无法发送"); + } + try { + Sys_msg sysMsg = new Sys_msg(); + sysMsg.setType("user"); + sysMsg.setTitle(message.getTitle()); + sysMsg.setNote(message.getNote()); + sysMsg.setUrl(message.getUrl()); + sysMsg.setNeedBack(Boolean.TRUE.equals(message.getNeedBack())); + sysMsg.setWechatEnterprise(Boolean.TRUE.equals(message.getWechatEnterprise())); + sysMsg.setFiles(message.getFiles()); + sysMsg.setSendType("show"); + sysMsg.setSendAt(DateUtil.current()); + sysMsg.setCreatedBy(message.getApplyUserId()); + sysMsgService.saveMsg(sysMsg, receivers.stream().map(WorkflowMessageReceiver::getLoginName).toArray(String[]::new), true); + + WorkflowMessage update = new WorkflowMessage(); + update.setId(id); + update.setApplyStatus(APPLY_STATUS_PASS); + update.setSendStatus(SEND_STATUS_SUCCESS); + update.setSendAt(DateUtil.current()); + update.setSendResult("发送成功"); + dao().updateIgnoreNull(update); + } catch (Exception e) { + WorkflowMessage update = new WorkflowMessage(); + update.setId(id); + update.setSendStatus(SEND_STATUS_FAIL); + update.setSendResult(StrUtil.sub(e.getMessage(), 0, 500)); + dao().updateIgnoreNull(update); + throw e; + } + } +} diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/impl/WorkflowMessageServiceImpl.java b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/impl/WorkflowMessageServiceImpl.java new file mode 100644 index 0000000..79acd48 --- /dev/null +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/workflowmessage/service/impl/WorkflowMessageServiceImpl.java @@ -0,0 +1,389 @@ +package com.budwk.app.zhgh.dayofficework.workflowmessage.service.impl; + +import cn.hutool.core.lang.Dict; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +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.service.impl.BaseServiceImpl; +import com.budwk.app.base.utils.PageUtil; +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.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.club.model.ClubUser; +import com.budwk.app.zhgh.club.model.SysClub; +import com.budwk.app.zhgh.club.service.SysClubService; +import com.budwk.app.zhgh.dayofficework.workflowmessage.models.WorkflowMessage; +import com.budwk.app.zhgh.dayofficework.workflowmessage.models.WorkflowMessageReceiver; +import com.budwk.app.zhgh.dayofficework.workflowmessage.service.WorkflowMessageService; +import org.nutz.aop.interceptor.ioc.TransAop; +import org.nutz.dao.*; +import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.SqlExpressionGroup; +import org.nutz.dao.util.cri.Static; +import org.nutz.ioc.aop.Aop; +import org.nutz.ioc.loader.annotation.Inject; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.lang.Lang; +import org.nutz.lang.util.NutMap; + +import java.util.List; + +@IocBean(args = {"refer:dao"}) +public class WorkflowMessageServiceImpl extends BaseServiceImpl implements WorkflowMessageService { + + private static final String PROCESS_DEFINE_KEY = "XXZX"; + private static final int APPLY_STATUS_AUDITING = 10; + private static final int SEND_STATUS_WAIT = 0; + + private static final String MSG_SCOPE_SCHOOL = "dayofficework.message.workflow.school"; + private static final String MSG_SCOPE_UNION = "dayofficework.message.workflow.union"; + private static final String MSG_SCOPE_CLUB = "dayofficework.message.workflow.club"; + + @Inject + private FlowEngine flowEngine; + @Inject + private SysClubService sysClubService; + + public WorkflowMessageServiceImpl(Dao dao) { + super(dao); + } + + @Override + @Aop(TransAop.READ_COMMITTED) + public WorkflowMessage submit(WorkflowMessage message, String[] users) { + if (ObjectUtil.isEmpty(users)) { + throw new BaseException("请选择用户"); + } + if (users.length > 100) { + throw new BaseException("单条消息最多发送100人,请分批次发送。"); + } + + fillApplyUser(message); + message.setApplyStatus(APPLY_STATUS_AUDITING); + message.setSendStatus(SEND_STATUS_WAIT); + message.setSendAt(null); + message.setSendResult(null); + insert(message); + + saveReceivers(message.getId(), users); + startWorkflow(message); + return message; + } + + @Override + public Pagination pageData(PageForm pageForm) { + Sql sql = Sqls.create(""" + SELECT + msg.*, + 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((SELECT taskName FROM wf_process_task tt WHERE tt.id = t.taskParentId) = 'startTask', 1, 0) canRevoke, + (SELECT MAX(st.id) FROM wf_process_task st WHERE st.processInstanceId = ins.id AND st.taskName = 'startTask') startTaskId, + COUNT(DISTINCT receiver.id) receiverCount + FROM workflow_message msg + LEFT JOIN wf_process_instance ins ON ins.id = msg.processInstanceId + LEFT JOIN wf_process_task t ON t.processInstanceId = ins.id AND t.taskState = 10 + LEFT JOIN wf_process_task nt ON nt.processInstanceId = ins.id AND nt.taskState = 10 + LEFT JOIN workflow_message_receiver receiver ON receiver.messageId = msg.id + $condition + """); + Cnd cnd = Cnd.NEW(); + if (!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + cnd.and("msg.applyUserId", "=", SecurityUtil.getUserId()); + } + cnd.and(Cnd.likeEX("msg.title", pageForm.getSearchKeyword())); + if (StrUtil.isAllNotBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.orderBy("msg." + pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } else { + cnd.desc("msg.createdAt"); + } + cnd.groupBy("msg.id"); + sql.setCondition(cnd); + return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + } + + @Override + @Aop(TransAop.READ_COMMITTED) + public WorkflowMessage updateSubmit(WorkflowMessage message, String[] users, Long startTaskId) { + if (StrUtil.isBlank(message.getId())) { + throw new BaseException("消息申请ID不能为空"); + } + if (ObjectUtil.isEmpty(users)) { + throw new BaseException("请选择用户"); + } + if (users.length > 100) { + throw new BaseException("单条消息最多发送100人,请分批次发送。"); + } + + WorkflowMessage oldMessage = fetch(message.getId()); + if (oldMessage == null) { + throw new BaseException("消息申请不存在"); + } + checkApplyOwner(oldMessage); + checkEditable(oldMessage); + + WorkflowMessage update = new WorkflowMessage(); + update.setId(message.getId()); + update.setTitle(message.getTitle()); + update.setNote(message.getNote()); + update.setUrl(message.getUrl()); + update.setWechatEnterprise(message.getWechatEnterprise()); + update.setNeedBack(message.getNeedBack()); + update.setFiles(message.getFiles()); + update.setApplyStatus(APPLY_STATUS_AUDITING); + update.setSendStatus(SEND_STATUS_WAIT); + updateIgnoreNull(update); + + dao().clear(WorkflowMessageReceiver.class, Cnd.where(WorkflowMessageReceiver::getMessageId, "=", message.getId())); + saveReceivers(message.getId(), users); + submitStartTask(message.getId(), startTaskId); + return fetch(message.getId()); + } + + @Override + public NutMap info(String id) { + WorkflowMessage message = fetch(id); + if (message == null) { + throw new BaseException("消息申请不存在"); + } + return NutMap.NEW() + .addv("message", message) + .addv("receivers", receiverList(id)); + } + + @Override + @Aop(TransAop.READ_COMMITTED) + public void deleteApply(String id) { + WorkflowMessage message = fetch(id); + if (message == null) { + throw new BaseException("消息申请不存在"); + } + checkApplyOwner(message); + checkEditable(message); + dao().clear(WorkflowMessageReceiver.class, Cnd.where(WorkflowMessageReceiver::getMessageId, "=", id)); + delete(id); + flowEngine.processInstanceService().deleteProcessInstanceByBusinessKey(id); + } + + @Override + public Pagination userPageData(PageForm pageForm, String unionId, String unitId, String roleId, String sex, String clubId) { + Sql sql = Sqls.create(""" + SELECT + u.id, + u.username, + u.loginname, + u.sex, + u.mobile, + u.unitId unitid, + u.unitName unitname, + u.unionId unionid, + u.unionName unionname, + u.userState, + u.personType, + u.preparedBy + FROM vw_user u + $condition + """); + Cnd cnd = Cnd.NEW(); + cnd.andEX("u.unionId", "=", unionId); + cnd.andEX("u.unitId", "=", unitId); + cnd.andEX("u.sex", "=", sex); + if (StrUtil.isNotBlank(roleId)) { + cnd.and(new Static("u.id in (select userId from sys_user_role where roleId = '%s')".formatted(roleId))); + } + if (StrUtil.isAllNotBlank(pageForm.getSearchName(), pageForm.getSearchKeyword())) { + cnd.and(pageForm.getSearchName(), "like", "%" + pageForm.getSearchKeyword() + "%"); + } + appendSendUserScope(cnd, "u"); + appendClubScope(cnd, clubId, "u"); + if (StrUtil.isAllNotBlank(pageForm.getPageOrderName(), pageForm.getPageOrderBy())) { + cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); + } else { + cnd.desc("u.loginname"); + } + sql.setCondition(cnd); + return listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql); + } + + @Override + public List receiverList(String messageId) { + Sql sql = Sqls.create(""" + SELECT + id, + messageId, + userId, + loginName, + userName, + sex, + mobile, + userState, + personType, + unitName, + unionName + FROM workflow_message_receiver + WHERE messageId = @messageId + ORDER BY loginName DESC + """); + sql.setParam("messageId", messageId); + return listMap(sql); + } + + private void fillApplyUser(WorkflowMessage message) { + View_user user = dao().fetch(View_user.class, Cnd.where(View_user::getId, "=", SecurityUtil.getUserId())); + message.setApplyUserId(SecurityUtil.getUserId()); + message.setApplyUserName(SecurityUtil.getUserUsername()); + message.setApplyLoginName(SecurityUtil.getUserLoginname()); + if (user != null) { + message.setApplyUnitId(user.getUnitId()); + message.setApplyUnitName(user.getUnitName()); + message.setApplyUnionId(user.getUnionId()); + message.setApplyUnionName(user.getUnionName()); + } else { + message.setApplyUnitId(SecurityUtil.getUnitId()); + message.setApplyUnionId(SecurityUtil.getUnionId()); + } + } + + private void saveReceivers(String messageId, String[] users) { + List viewUsers = dao().query(View_user.class, Cnd.where(View_user::getLoginname, "in", users).groupBy("loginname")); + if (Lang.isEmpty(viewUsers)) { + throw new BaseException("未找到有效接收人"); + } + List receivers = viewUsers.stream().map(user -> { + WorkflowMessageReceiver receiver = new WorkflowMessageReceiver(); + receiver.setMessageId(messageId); + receiver.setUserId(user.getId()); + receiver.setLoginName(user.getLoginname()); + receiver.setUserName(user.getUsername()); + receiver.setSex(user.getSex()); + receiver.setMobile(user.getMobile()); + receiver.setUserState(user.getUserState()); + receiver.setPersonType(user.getPersonType()); + receiver.setUnitId(user.getUnitId()); + receiver.setUnitName(user.getUnitName()); + receiver.setUnionId(user.getUnionId()); + receiver.setUnionName(user.getUnionName()); + return receiver; + }).toList(); + dao().insert(receivers); + } + + private void startWorkflow(WorkflowMessage message) { + Dict args = Dict.create(); + args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.APPLY.getCode()); + args.set(FlowConst.FORM_DATA, message); + args.set("title", message.getTitle()); + ProcessInstance instance = flowEngine.startProcessInstanceByKey(PROCESS_DEFINE_KEY, message.getId(), SecurityUtil.getUserId(), args); + List doingTaskList = flowEngine.processTaskService().getDoingTaskList(instance.getId(), null); + for (ProcessTask task : doingTaskList) { + flowEngine.executeProcessTask(task.getId(), SecurityUtil.getUserId(), args); + } + message.setProcessInstanceId(instance.getId()); + updateIgnoreNull(message); + } + + private void submitStartTask(String messageId, Long startTaskId) { + if (startTaskId == null) { + throw new BaseException("流程发起节点任务不存在,无法重新提交"); + } + ProcessTask task = flowEngine.processTaskService().fetch(startTaskId); + if (task == null) { + throw new BaseException("流程发起节点任务不存在,无法重新提交"); + } + if (!StrUtil.equals(task.getTaskName(), "startTask")) { + throw new BaseException("当前流程不在发起节点,无法重新提交"); + } + WorkflowMessage currentMessage = fetch(messageId); + if (!ObjectUtil.equals(currentMessage.getProcessInstanceId(), task.getProcessInstanceId())) { + throw new BaseException("流程任务与消息申请不匹配"); + } + Dict args = Dict.create(); + args.set(FlowConst.SUBMIT_TYPE, ProcessSubmitTypeEnum.APPLY.getCode()); + args.set(FlowConst.FORM_DATA, currentMessage); + args.set("title", currentMessage.getTitle()); + flowEngine.executeProcessTask(startTaskId, SecurityUtil.getUserId(), args); + } + + private void checkApplyOwner(WorkflowMessage message) { + if (AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) { + return; + } + if (!StrUtil.equals(message.getApplyUserId(), SecurityUtil.getUserId())) { + throw new BaseException("只能操作本人提交的消息申请"); + } + } + + private void checkEditable(WorkflowMessage message) { + if (message.getProcessInstanceId() == null) { + return; + } + List doingTaskList = flowEngine.processTaskService().getDoingTaskList(message.getProcessInstanceId(), null); + if (Lang.isEmpty(doingTaskList) || doingTaskList.stream().noneMatch(task -> StrUtil.equals(task.getTaskName(), "startTask"))) { + throw new BaseException("当前流程状态不允许编辑或删除"); + } + } + + private void appendClubScope(Cnd cnd, String clubId, String userAlias) { + if (StrUtil.isBlank(clubId)) { + return; + } + List clubUsers = sysClubService.dao().query(ClubUser.class, Cnd.where(ClubUser::getClubId, "=", clubId)); + if (Lang.isEmpty(clubUsers)) { + cnd.and(new Static("1 = 0")); + return; + } + cnd.and(userAlias + ".id", "in", clubUsers.stream().map(ClubUser::getUserId).distinct().toList()); + } + + private void appendSendUserScope(Cnd cnd, String userAlias) { + // 校级消息权限可选择全校人员。 + if (AuthUtil.hasPermission(MSG_SCOPE_SCHOOL)) { + return; + } + + SqlExpressionGroup scopeGroup = new SqlExpressionGroup(); + // 分工会消息权限只能选择当前登录人所在分工会人员。 + if (AuthUtil.hasPermission(MSG_SCOPE_UNION) && StrUtil.isNotBlank(SecurityUtil.getUnionId())) { + scopeGroup.or(userAlias + ".unionId", "=", SecurityUtil.getUnionId()); + } + + // 协会消息权限只能选择当前登录人管理协会下的会员。 + if (AuthUtil.hasPermission(MSG_SCOPE_CLUB)) { + List myManageClub = sysClubService.getMyManageClub(); + if (Lang.isNotEmpty(myManageClub)) { + List clubIds = myManageClub.stream().map(SysClub::getId).toList(); + List clubUsers = sysClubService.dao().query(ClubUser.class, Cnd.where(ClubUser::getClubId, "in", clubIds)); + if (Lang.isNotEmpty(clubUsers)) { + scopeGroup.or(userAlias + ".id", "in", clubUsers.stream().map(ClubUser::getUserId).distinct().toList()); + } + } + } + + if (scopeGroup.isEmpty()) { + cnd.and(new Static("1 = 0")); + } else { + cnd.and(scopeGroup); + } + } +} diff --git a/src/main/resources/views/platform/sys/role/index.html b/src/main/resources/views/platform/sys/role/index.html index 527fce9..9fdd493 100644 --- a/src/main/resources/views/platform/sys/role/index.html +++ b/src/main/resources/views/platform/sys/role/index.html @@ -237,17 +237,17 @@ layout("/layouts/platform.html"){ - - - - - - - - - - - + + + + + 全选 清空 @@ -664,10 +664,10 @@ layout("/layouts/platform.html"){ }) }, doMenu() { - // if (this.searchText) { - // this.$message.warning('请清空搜索条件后再提交') - // return; - // } + if (this.searchText) { + this.$message.warning('请清空搜索条件后再提交') + return; + } const ids = this.$refs["doMenuTree"].getCheckedKeys() if (!ids || ids.length === 0) { diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workflowmessage/apply/index.html b/src/main/resources/views/platform/zhgh/dayofficework/workflowmessage/apply/index.html new file mode 100644 index 0000000..9faae9e --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workflowmessage/apply/index.html @@ -0,0 +1,223 @@ + + + +
+ + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workflowmessage/audit/index.html b/src/main/resources/views/platform/zhgh/dayofficework/workflowmessage/audit/index.html new file mode 100644 index 0000000..a4ba61e --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workflowmessage/audit/index.html @@ -0,0 +1,203 @@ + + + +
+ + + + +
+ + + + diff --git a/src/main/resources/views/platform/zhgh/dayofficework/workflowmessage/info.js b/src/main/resources/views/platform/zhgh/dayofficework/workflowmessage/info.js new file mode 100644 index 0000000..0fec72b --- /dev/null +++ b/src/main/resources/views/platform/zhgh/dayofficework/workflowmessage/info.js @@ -0,0 +1,95 @@ +const WORKFLOW_MESSAGE_INFO = { + template: /*language=HTML*/ ` +
+
+ 消息申请信息 + 点击查看流程图 +
+ + {{ message.title }} + + {{ message.wechatEnterprise ? "是" : "否" }} + + {{ message.applyUserName }}({{ message.applyLoginName }}) + {{ message.applyUnitName }} + +
+
+ + + +
+
接收人
+ + + + + + + + + + + +
+ `, + dicts: ["PROCESS_TASK_SUBMIT_TYPE"], + data() { + return { + row: null, + message: {}, + receivers: [], + doneTasks: [] + } + }, + methods: { + // 打开消息详情:row 为列表当前行,必须包含 id;组件内部统一拉取消息详情和流程办理记录。 + onOpen(row) { + this.row = row + this.getInfo() + this.getDoneTasks() + }, + // 查询消息详情:参数 id 为工作流消息申请ID;返回 message 详情对象和 receivers 接收人数组。 + getInfo() { + this.$axios.post("/platform/dayofficework/workflowmessage/info", { id: this.row.id }).then((res) => { + if (res.code === 0) { + this.message = res.data.message + this.receivers = res.data.receivers + } else { + this.$message.warning(res.msg) + } + }) + }, + // 查询流程办理记录:参数 bizId 为工作流消息申请ID;返回已办任务数组,用于查看申请和审核流转意见。 + getDoneTasks() { + this.$axios.post("/flow/common/doneTasks", { bizId: this.row.id }).then((res) => { + if (res.code === 0) { + this.doneTasks = res.data + } + }) + }, + // 打开流程图:优先使用列表行中的流程定义ID和流程实例ID,兼容申请列表的 processInstanceId 字段。 + openChart() { + this.$refs.snakerChartRef.onOpenFull(this.row.instanceProcessDefineId, this.row.instanceId || this.row.processInstanceId) + } + } +}