From 53a56e46b54dda7a1de8f4391e6d01af405c3e1c Mon Sep 17 00:00:00 2001 From: "@jyuhsin" <729757837@qq.com> Date: Mon, 16 Mar 2026 15:18:47 +0800 Subject: [PATCH] commit --- .../com/budwk/app/base/sms/SmsService.java | 33 +--- .../app/base/sms/impl/SmsWhcpServiceImpl.java | 73 +++++++++ .../sms/impl/jshvc/SmsJshvcServiceImpl.java | 150 ------------------ .../flow/controller/FlowCommonController.java | 14 +- .../ProcessTaskStartEventListener.java | 5 +- .../impl/SysDataUserAllUpdateServiceImpl.java | 25 +++ .../app/task/job/SysUserAllRenewJob.java | 2 +- .../app/web/commons/proc/CspProcessor.java | 4 +- .../strategy/impl/SmsMessageSendStrategy.java | 54 +------ .../views/platform/flow/define/preview.html | 47 +++--- 10 files changed, 149 insertions(+), 258 deletions(-) create mode 100644 src/main/java/com/budwk/app/base/sms/impl/SmsWhcpServiceImpl.java delete mode 100644 src/main/java/com/budwk/app/base/sms/impl/jshvc/SmsJshvcServiceImpl.java diff --git a/src/main/java/com/budwk/app/base/sms/SmsService.java b/src/main/java/com/budwk/app/base/sms/SmsService.java index df7cd4d..8f874c1 100644 --- a/src/main/java/com/budwk/app/base/sms/SmsService.java +++ b/src/main/java/com/budwk/app/base/sms/SmsService.java @@ -4,36 +4,7 @@ import java.util.List; public interface SmsService { - /** - * 单发 - * @param loginName 工号 - * @param content 内容 - */ - void send(String loginName, String content); + void send(String mobile, String content); - /** - * 单发 - * @param loginName 工号 - * @param title 标题 - * @param content 内容 - */ - void send(String loginName, String title, String content); - - /** - * 单发 - * @param loginName 工号 - * @param title 标题 - * @param content 内容 - * @param link 链接 - */ - void send(String loginName, String title, String content, String link); - - /** - * 群发 多人接收内容相同时使用该方法 - * @param loginNames 工号 - * @param title 标题 - * @param content 内容 - * @param link 链接 - */ - void massSend(List loginNames, String title, String content, String link); + void massSend(List mobile, String content); } diff --git a/src/main/java/com/budwk/app/base/sms/impl/SmsWhcpServiceImpl.java b/src/main/java/com/budwk/app/base/sms/impl/SmsWhcpServiceImpl.java new file mode 100644 index 0000000..d32ad96 --- /dev/null +++ b/src/main/java/com/budwk/app/base/sms/impl/SmsWhcpServiceImpl.java @@ -0,0 +1,73 @@ +package com.budwk.app.base.sms.impl; + +import cn.hutool.crypto.SecureUtil; +import cn.hutool.http.HttpRequest; +import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSONObject; +import com.budwk.app.base.sms.SmsService; +import com.budwk.app.web.commons.base.Globals; +import com.google.common.net.MediaType; +import lombok.extern.slf4j.Slf4j; +import org.nutz.ioc.loader.annotation.IocBean; +import org.nutz.json.Json; +import org.nutz.lang.Lang; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @ClassName SmsWhcpServiceImpl + * @Author JyuHsin + * @Date 2026/3/16 14:08 + * @Version 1.0 + * @Description TODO + */ +@Slf4j +@IocBean +public class SmsWhcpServiceImpl implements SmsService { + + @Override + public void send(String mobile, String content) { + this.doSend(mobile, content); + } + + @Override + public void massSend(List mobiles, String content) { + if (Lang.isEmpty(mobiles)) { + return; + } + String formatMobile = String.join(",", mobiles); + this.doSend(formatMobile, content); + } + + private void doSend(String mobile, String content) { + if (!Globals.sso) { + log.info("【log】本地开发环境,不允许调用短信消息接口"); + return; + } + + String urls = "https://api-shss.zthysms.com/v2/sendSms"; + + long tKey = System.currentTimeMillis() / 1000; + JSONObject json = new JSONObject(); + json.put("username", "whszyxy"); + json.put("password", SecureUtil.md5(SecureUtil.md5("Whszyxy123") + tKey)); + json.put("tKey", tKey + ""); + json.put("mobile", mobile); + json.put("content", "【智慧工会】" + content); + + log.info("【log】调用短信消息接口,请求参数:{}", Json.toJson(json)); + String result = HttpRequest.post(urls) + .header("Content-Type", "application/json") + .timeout(60000) + .body(json.toJSONString()).execute().body(); + log.info("【log】调用短信消息接口,接口响应数据:{}", result); + + JSONObject resultJsonBody = JSONObject.parseObject(result); + if (resultJsonBody.getInteger("code") == 200) { + log.info("【log】调用短信消息接口成功"); + } else { + log.info("【log】调用短信消息接口失败:{}", resultJsonBody.getString("msg")); + } + } +} diff --git a/src/main/java/com/budwk/app/base/sms/impl/jshvc/SmsJshvcServiceImpl.java b/src/main/java/com/budwk/app/base/sms/impl/jshvc/SmsJshvcServiceImpl.java deleted file mode 100644 index 9eeb4bb..0000000 --- a/src/main/java/com/budwk/app/base/sms/impl/jshvc/SmsJshvcServiceImpl.java +++ /dev/null @@ -1,150 +0,0 @@ -package com.budwk.app.base.sms.impl.jshvc; - -import cn.hutool.core.util.StrUtil; -import cn.hutool.crypto.digest.DigestUtil; -import cn.hutool.http.HttpRequest; -import cn.hutool.http.HttpResponse; -import com.budwk.app.base.sms.SmsService; -import lombok.extern.slf4j.Slf4j; -import org.nutz.integration.jedis.RedisService; -import org.nutz.ioc.loader.annotation.Inject; -import org.nutz.ioc.loader.annotation.IocBean; -import org.nutz.json.Json; -import org.nutz.lang.Lang; -import org.nutz.lang.util.NutMap; - -import java.util.List; -import java.util.Map; - -/** - * @ClassName SmsJshvcServiceImpl - * @Author JyuHsin - * @Date 2025/11/26 19:32 - * @Version 1.0 - * @Description TODO - */ -@Slf4j -@IocBean -public class SmsJshvcServiceImpl implements SmsService { - - private static final String APPID = "1430576717768122368"; - private static final String APP_SECRET = "19A0ACB03FBQHL4R4XQD"; - private static final String TOKEN_URL = "https://gateway.jshvc.edu.cn/token/gateway/accessToken"; - private static final String MSG_URL = "https://gateway.jshvc.edu.cn/mp/restful/v2/message/send"; - private static final String REDIS_KEY_MSG_ACCESS_TOKEN = "msg:token:"; - - @Inject - private RedisService redisService; - - @Override - public void send(String loginName, String content) { -// send(loginName, "智慧工会", content); - } - - @Override - public void send(String loginName, String title, String content) { - send(loginName, "智慧工会", content, null); - } - - @Override - public void send(String loginName, String title, String content, String link) { -// Map paramMap = Map.of("userId", loginName); -// doSend(title, content, List.of(paramMap), link); - } - - @Override - public void massSend(List loginNames, String title, String content, String link) { -// List> receivers = loginNames.stream() -// .map(name -> Map.of("userId", name)) -// .toList(); -// doSend(title, content, receivers, link); - } - - /** - * sign: 请求签名:(accessToken + 第一个receivers 的userID )的32位小写的MD5加密值,其中如果相应部分没有则忽略 - * msgType: 0: 普通消息(默认) 1: 必读消息 2: 验证码(为验证码时消息一定不入收件箱) - * expiredTime: 当msgType 为1必读消息 ,该字段为必填字段 格式:yyyy-MM-dd HH:mm:ss - * sendType: 1.只发送PC门户 2.只发送移动校园 3.邮件 4.短信 5.微信企业号 6.钉钉企业内部应用工作通知 7.微信服务号 8.welink - * wxSendType: 当发送类型为5时此字段才会生效:text(文本消息)、textcard(文本卡片)、nes(图文卡片,如果图文,则qyWeChatImgUrl必填)、button(按钮卡片详见示例),不传默认为text - * receiverType: 1:用户 2:用户组 3:部门,默认为1 - * - * @param title - * @param content - * @param receivers - */ - private void doSend(String title, String content, List> receivers, String link) { - - if (Lang.isEmpty(receivers)) { - log.error("send fail by receivers is null"); - return; - } - - // 获取token - String accessToken = buildAccessToken(); - // 获取第一个接收人的userID - String firstUserId = receivers.get(0).get("userId"); - // md5小写加密生成签名 - String sign = DigestUtil.md5Hex(accessToken + firstUserId); - - NutMap paramsMap = new NutMap(); - paramsMap.put("sign", sign); - paramsMap.put("msgType", "0"); - paramsMap.put("subject", title); - paramsMap.put("content", content); - paramsMap.put("sendType", "5"); - paramsMap.put("receivers", receivers); - if (StrUtil.isBlank(link)) { - paramsMap.put("wxSendType", "text"); - } else { - paramsMap.put("wxSendType", "textcard"); - paramsMap.put("mobileUrl", link); - // 这是图文卡片,后面用到再对接吧 - // paramsMap.put("qyWeChatImgUrl", ""); - } - - log.debug("send params: {}", Json.toJson(paramsMap)); - - HttpRequest request = HttpRequest.post(MSG_URL) - .header("appId", APPID) - .header("accessToken", accessToken) - .body(Json.toJson(paramsMap)); - - try { - HttpResponse response = request.execute(); - log.info("send response body: {}", response.body()); - - NutMap bodyMap = Json.fromJson(NutMap.class, response.body()); - if (bodyMap.getInt("status") == 200) { - log.info("send success code: {}, msg: {}", bodyMap.getInt("status"), bodyMap.getString("msg")); - } else { - log.error("send error code: {}, msg: {}", bodyMap.getInt("status"), bodyMap.getString("msg")); - } - } catch (Exception e) { - log.error("Failed to send: {}", e.getMessage(), e); - } - } - - private String buildAccessToken() { - String token = redisService.get(REDIS_KEY_MSG_ACCESS_TOKEN); - if (StrUtil.isNotBlank(token)) { - return token; - } - HttpRequest request = HttpRequest.get(TOKEN_URL); - request.header("appId", APPID); - request.header("appSecret", APP_SECRET); - - HttpResponse response = request.execute(); - - log.info("accessToken response: {}", Json.toJson(response.body())); - - NutMap bodyMap = Json.fromJson(NutMap.class, response.body()); - if (bodyMap.getInt("errcode") == 0) { - log.info("accessToken status: {}", bodyMap.getInt("errorcode")); - redisService.setex(REDIS_KEY_MSG_ACCESS_TOKEN, 60 * 120, bodyMap.getString("data")); - return bodyMap.getString("data"); - } else { - log.error("accessToken status: {}", bodyMap.getInt("errorcode")); - } - return ""; - } -} diff --git a/src/main/java/com/budwk/app/flow/controller/FlowCommonController.java b/src/main/java/com/budwk/app/flow/controller/FlowCommonController.java index c5031ca..1437fa1 100644 --- a/src/main/java/com/budwk/app/flow/controller/FlowCommonController.java +++ b/src/main/java/com/budwk/app/flow/controller/FlowCommonController.java @@ -4,6 +4,8 @@ import cn.dev33.satoken.annotation.SaCheckLogin; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.lang.Dict; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import com.budwk.app.base.result.Result; import com.budwk.app.base.vo.LabelValueVO; import com.budwk.app.flow.constant.FlowConst; @@ -12,10 +14,7 @@ import com.budwk.app.flow.engine.event.ProcessEvent; import com.budwk.app.flow.engine.event.ProcessPublisher; import com.budwk.app.flow.engine.model.ProcessModel; import com.budwk.app.flow.engine.model.TaskModel; -import com.budwk.app.flow.entity.Candidate; -import com.budwk.app.flow.entity.ProcessDefine; -import com.budwk.app.flow.entity.ProcessInstance; -import com.budwk.app.flow.entity.ProcessTask; +import com.budwk.app.flow.entity.*; import com.budwk.app.flow.enums.ProcessEventTypeEnum; import com.budwk.app.flow.enums.ProcessInstanceStateEnum; import com.budwk.app.flow.enums.ProcessTaskPerformTypeEnum; @@ -147,7 +146,7 @@ public class FlowCommonController { @ApiOperation("获取流程定义的审批记录") public Result approvalRecord(Long instanceId) { List processTaskList = dao.query(ProcessTask.class, Cnd.where(ProcessTask::getProcessInstanceId, "=", instanceId) - .and(ProcessTask::getTaskState, "not in", List.of(ProcessTaskStateEnum.DOING, ProcessTaskStateEnum.WITHDRAW, ProcessTaskStateEnum.ABANDON)) + .and(ProcessTask::getTaskState, "not in", List.of(ProcessTaskStateEnum.WITHDRAW, ProcessTaskStateEnum.ABANDON)) .asc(ProcessTask::getUpdatedAt)); List res = new ArrayList<>(); processTaskList.forEach(processTask -> { @@ -155,6 +154,11 @@ public class FlowCommonController { if (vo.getTaskState().equals(ProcessTaskStateEnum.FINISHED.getCode()) && StrUtil.isNotBlank(vo.getOperator())) { } + if(vo.getTaskState().equals(ProcessTaskStateEnum.DOING.getCode())) { + List taskActorList = dao.query(ProcessTaskActor.class, Cnd.where(ProcessTaskActor::getProcessTaskId, "=", processTask.getId())); + List list = JSONUtil.toList(JSONUtil.toJsonStr(taskActorList), JSONObject.class); + vo.setTaskActorList(list); + } res.add(vo); }); diff --git a/src/main/java/com/budwk/app/flow/listenter/ProcessTaskStartEventListener.java b/src/main/java/com/budwk/app/flow/listenter/ProcessTaskStartEventListener.java index d030783..fecf2eb 100644 --- a/src/main/java/com/budwk/app/flow/listenter/ProcessTaskStartEventListener.java +++ b/src/main/java/com/budwk/app/flow/listenter/ProcessTaskStartEventListener.java @@ -59,12 +59,9 @@ public class ProcessTaskStartEventListener implements ProcessEventListener { for (ProcessTaskActor taskActor : taskActors) { // 模拟发送消息 - String message = StrUtil.format("您有一条待办任务,实例:{},处理环节:{}", taskActor.getActorName(), instanceName, taskDisplayName); + String message = StrUtil.format("您有一条待办任务,实例:{},处理环节:{}", instanceName, taskDisplayName); log.info(message); globalMessageSendService.sendMessage(taskDisplayName, message, 2, List.of(taskActor.getActorId()), null); } - - } - } diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java index ed607d1..d4177ac 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.http.HtmlUtil; import com.budwk.app.base.constant.RoleConstant; import com.budwk.app.base.event.role.RoleEventMsg; @@ -22,6 +23,7 @@ import com.budwk.app.sys.services.SysUserService; import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig; import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin; import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType; +import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Chain; @@ -380,6 +382,29 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService RoleEventPublisher.broadcast(new RoleEventMsg(unitId, RoleConstant.PROPOSAL_BRANCH_SCHOOL_LEADER.name(), RoleEventMsg.RENEW_ROLE)); } + Set sourceSet = sources.stream().map(Sys_user_source::getLoginname).filter(StrUtil::isNotBlank).collect(Collectors.toSet()); + Set userSet = userMap.keySet(); + Set notExist = Sets.difference(userSet, sourceSet).immutableCopy(); + if (Lang.isNotEmpty(notExist)) { + executorService.execute(() -> { + try { + log.info("用户表中有数据,但数据源没有数据: {} 个", notExist.size()); + // 批量处理,避免IN子句过长 + List> batches = ListUtil.split(notExist.stream().toList(), 500); + for (List batch : batches) { + try { + dao.update(Sys_user.class, Chain.make("userState", "退休").add("member", false), Cnd.where("id", "in", batch)); + dao.clear(Sys_user_role.class, Cnd.where("userId", "in", batch).and("roleId", "=", memberRole.getId())); + } catch (Exception e) { + log.error("设置退休异常(用户表中有数据,但数据源没有数据)", e); + } + } + } catch (Exception e) { + log.error("设置退休异常(用户表中有数据,但数据源没有数据)", e); + } + }); + } + long endTime = System.currentTimeMillis(); log.info("全量更新用户数据完成,耗时: {} 毫秒", (endTime - startTime)); diff --git a/src/main/java/com/budwk/app/task/job/SysUserAllRenewJob.java b/src/main/java/com/budwk/app/task/job/SysUserAllRenewJob.java index 6d20f36..4ca0a98 100644 --- a/src/main/java/com/budwk/app/task/job/SysUserAllRenewJob.java +++ b/src/main/java/com/budwk/app/task/job/SysUserAllRenewJob.java @@ -57,6 +57,6 @@ public class SysUserAllRenewJob implements Job { param.setUpdateMode(SysDataUpdateMode.ALL.name()); param.setConditionGroup(conditionGroup); - // sysDataUserUpdateService.update(param); + sysDataUserUpdateService.update(param); } } diff --git a/src/main/java/com/budwk/app/web/commons/proc/CspProcessor.java b/src/main/java/com/budwk/app/web/commons/proc/CspProcessor.java index 02534db..40051d1 100644 --- a/src/main/java/com/budwk/app/web/commons/proc/CspProcessor.java +++ b/src/main/java/com/budwk/app/web/commons/proc/CspProcessor.java @@ -15,7 +15,7 @@ import java.util.Base64; public class CspProcessor extends AbstractProcessor { public void process(ActionContext ac) throws Throwable { - // 1. 生成 nonce + /*// 1. 生成 nonce String nonce = Base64.getEncoder().encodeToString( java.security.SecureRandom.getInstanceStrong().generateSeed(16) ); @@ -34,7 +34,7 @@ public class CspProcessor extends AbstractProcessor { "frame-ancestors 'self'; " + "object-src 'self';"; - ac.getResponse().setHeader("Content-Security-Policy", csp); + ac.getResponse().setHeader("Content-Security-Policy", csp);*/ doNext(ac); } diff --git a/src/main/java/com/budwk/app/zhgh/dayofficework/message/strategy/impl/SmsMessageSendStrategy.java b/src/main/java/com/budwk/app/zhgh/dayofficework/message/strategy/impl/SmsMessageSendStrategy.java index 78e3834..98aea8f 100644 --- a/src/main/java/com/budwk/app/zhgh/dayofficework/message/strategy/impl/SmsMessageSendStrategy.java +++ b/src/main/java/com/budwk/app/zhgh/dayofficework/message/strategy/impl/SmsMessageSendStrategy.java @@ -1,6 +1,7 @@ package com.budwk.app.zhgh.dayofficework.message.strategy.impl; import cn.hutool.json.JSONObject; +import com.budwk.app.base.sms.SmsService; import com.budwk.app.sys.models.Sys_user; import com.budwk.app.zhgh.dayofficework.message.enums.GlobalMessageChannel; import com.budwk.app.zhgh.dayofficework.message.strategy.GlobalMessageSendStrategy; @@ -21,6 +22,8 @@ public class SmsMessageSendStrategy implements GlobalMessageSendStrategy { @Inject private Dao dao; + @Inject + private SmsService smsService; @Override public GlobalMessageChannel getChannel() { @@ -32,10 +35,10 @@ public class SmsMessageSendStrategy implements GlobalMessageSendStrategy { return true; // 短信发送支持异步 } -// @Override -// public boolean isEnabled() { -// return true; -// } + @Override + public boolean isEnabled() { + return true; + } @Override public void send(String title, String content, Integer type, List receiverIds, JSONObject config) { @@ -80,51 +83,10 @@ public class SmsMessageSendStrategy implements GlobalMessageSendStrategy { log.warn("用户{}没有手机号,跳过短信发送", user.getUsername()); continue; } - - // 构建短信内容 - String smsContent = buildSmsContent(title, content, type); - - // 执行发送 - - boolean success = true; - - if (success) { - log.info("短信发送成功:用户{},手机号:{}", user.getUsername(), mobile); - } else { - log.warn("短信发送失败:用户{},手机号:{}", user.getUsername(), mobile); - } + smsService.send(mobile, content); } catch (Exception e) { log.error("发送短信给用户{}时出错:{}", user.getUsername(), e.getMessage(), e); } } } - - /** - * 构建短信内容 - */ - private String buildSmsContent(String title, String content, Integer type) { - StringBuilder sb = new StringBuilder(); - - // 根据消息类型添加前缀 - if (type != null && type == 2) { - sb.append("【待办通知】"); - } else { - sb.append("【系统通知】"); - } - - // 添加标题和内容 - sb.append(title); - if (content != null && !content.trim().isEmpty()) { - sb.append(":").append(content); - } - - // 限制短信长度(一般短信限制70个字符) - String smsContent = sb.toString(); - if (smsContent.length() > 67) { - smsContent = smsContent.substring(0, 67) + "..."; - } - - return smsContent; - } - } diff --git a/src/main/resources/views/platform/flow/define/preview.html b/src/main/resources/views/platform/flow/define/preview.html index b5bdbf7..029f105 100644 --- a/src/main/resources/views/platform/flow/define/preview.html +++ b/src/main/resources/views/platform/flow/define/preview.html @@ -141,18 +141,18 @@
记录{{index + 1}}
@@ -187,6 +187,9 @@ {{approvalInfo.ext?.initiatorName}}({{approvalInfo.ext?.initiatorAccount}}) + + {{ approvalInfo.taskActorList.map(u => u.actorName + '(' + u.actorAccount + ')').join('、') }} + {{approvalInfo.taskFormData.userName}}({{approvalInfo.taskFormData?.loginName}})
@@ -196,23 +199,29 @@
提交结果: - {{getSubmitTypeText(approvalInfo.ext.submitType)}} + + {{getSubmitTypeText(approvalInfo.ext.submitType)}} + + + 暂未处理 +
提交意见: - {{approvalInfo.taskFormData.opinion}} + {{approvalInfo.taskFormData.opinion}} + 暂未处理
提交时间: - {{approvalInfo.finishTime}} + {{approvalInfo.finishTime || '暂未处理'}}
-