【v3.8.3】企业微信通知采用卡片

pull/8786/merge
JEECG 2025-09-14 10:44:08 +08:00
parent 700318e1c1
commit d383f7458d
2 changed files with 200 additions and 18 deletions

View File

@ -9,6 +9,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.base.Joiner;
import com.jeecg.dingtalk.api.core.response.Response;
@ -20,9 +21,11 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.dto.AiragFlowDTO;
import org.jeecg.common.api.dto.DataLogDTO;
import org.jeecg.common.api.dto.OnlineAuthDTO;
import org.jeecg.common.api.dto.message.*;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.UrlMatchEnum;
import org.jeecg.common.constant.*;
import org.jeecg.common.constant.enums.*;
@ -32,12 +35,13 @@ import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.query.QueryCondition;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.query.QueryRuleEnum;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.system.vo.*;
import org.jeecg.common.util.*;
import org.jeecg.common.util.dynamic.db.FreemarkerParseFactory;
import org.jeecg.config.firewall.SqlInjection.IDictTableWhiteListHandler;
import org.jeecg.config.mybatis.MybatisPlusSaasConfig;
import org.jeecg.modules.airag.flow.service.IAiragFlowService;
import org.jeecg.modules.airag.flow.vo.api.FlowRunParams;
import org.jeecg.modules.message.entity.SysMessageTemplate;
import org.jeecg.modules.message.handle.impl.DdSendMsgHandle;
import org.jeecg.modules.message.handle.impl.EmailSendMsgHandle;
@ -139,6 +143,9 @@ public class SysBaseApiImpl implements ISysBaseAPI {
@Autowired
private ISysAnnouncementService sysAnnouncementService;
@Autowired
IAiragFlowService airagFlowService;
@Override
//@SensitiveDecode
public LoginUser getUserByName(String username) {
@ -441,7 +448,8 @@ public class SysBaseApiImpl implements ISysBaseAPI {
message.getContent(),
message.getCategory(),
message.getBusType(),
message.getBusId());
message.getBusId(),
message.getNoticeType());
try {
// 同步发送第三方APP消息
wechatEnterpriseService.sendMessage(message, true);
@ -521,7 +529,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
try {
// 同步企业微信、钉钉的消息通知
dingtalkService.sendActionCardMessage(announcement, mobileOpenUrl, true);
wechatEnterpriseService.sendTextCardMessage(announcement, true);
wechatEnterpriseService.sendTextCardMessage(announcement, mobileOpenUrl, true);
} catch (Exception e) {
log.error("同步发送第三方APP消息失败", e);
}
@ -575,6 +583,16 @@ public class SysBaseApiImpl implements ISysBaseAPI {
mobileOpenUrl = tmplateParam.get(CommonConstant.MSG_HREF_URL);
}
// 如果传递扩展json说明是个性化业务有意见remark则设置为通知内容
if(oConvertUtils.isJson(announcement.getMsgAbstract())) {
// 获取announcement.getMsgAbstract()的字段remark
JSONObject jsonObject = JSON.parseObject(announcement.getMsgAbstract());
String remark = jsonObject.containsKey("remark")? jsonObject.getString("remark"): null;
if(oConvertUtils.isNotEmpty(remark)){
announcement.setMsgContent(remark);
}
}
announcement.setMsgCategory(CommonConstant.MSG_CATEGORY_2);
announcement.setDelFlag(String.valueOf(CommonConstant.DEL_FLAG_0));
announcement.setBusId(busId);
@ -609,7 +627,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
// 钉钉的消息通知
dingtalkService.sendActionCardMessage(announcement, mobileOpenUrl, true);
// 企业微信通知
wechatEnterpriseService.sendTextCardMessage(announcement, true);
wechatEnterpriseService.sendTextCardMessage(announcement, mobileOpenUrl, true);
} catch (Exception e) {
log.error("同步发送第三方APP消息失败", e);
}
@ -763,7 +781,6 @@ public class SysBaseApiImpl implements ISysBaseAPI {
return json;
}
@Override
public List<ComboModel> queryAllRole() {
List<ComboModel> list = new ArrayList<ComboModel>();
List<SysRole> roleList = roleMapper.selectList(new QueryWrapper<SysRole>());
@ -1357,8 +1374,9 @@ public class SysBaseApiImpl implements ISysBaseAPI {
* @param setMsgCategory
* @param busType
* @param busId
* @param noticeType ,for [JHHB-136]vue3
*/
private void sendBusAnnouncement(String fromUser, String toUser, String title, String msgContent, String setMsgCategory, String busType, String busId) {
private void sendBusAnnouncement(String fromUser, String toUser, String title, String msgContent, String setMsgCategory, String busType, String busId, String noticeType) {
SysAnnouncement announcement = new SysAnnouncement();
announcement.setTitile(title);
announcement.setMsgContent(msgContent);
@ -1373,7 +1391,12 @@ public class SysBaseApiImpl implements ISysBaseAPI {
announcement.setBusType(busType);
announcement.setOpenType(SysAnnmentTypeEnum.getByType(busType).getOpenType());
announcement.setOpenPage(SysAnnmentTypeEnum.getByType(busType).getOpenPage());
announcement.setNoticeType(NoticeTypeEnum.NOTICE_TYPE_FLOW.getValue());
//update-begin---author:chenrui ---date:20250807 for[JHHB-136]【vue3】协同工作系统消息需要添加一个类型------------
if(oConvertUtils.isEmpty(noticeType)){
noticeType = NoticeTypeEnum.NOTICE_TYPE_FLOW.getValue();
}
announcement.setNoticeType(noticeType);
//update-end---author:chenrui ---date:20250807 for[JHHB-136]【vue3】协同工作系统消息需要添加一个类型------------
//update-begin-author:liusq---date:2025-07-01--for: [QQYUN-12999]系统通知,系统通知时间更新,但是排到下面了
announcement.setIzTop(CommonConstant.IZ_TOP_0);
//update-end-author:liusq---date:2025-07-01--for: [QQYUN-12999]系统通知,系统通知时间更新,但是排到下面了
@ -1765,7 +1788,22 @@ public class SysBaseApiImpl implements ISysBaseAPI {
return sysUserDepartService.listObjs(queryWrapper,e->e.toString());
}
@Override
@Override
public List<String> queryUserIdsByCascadeDeptIds(List<String> deptIds) {
Set<String> userIds = new HashSet<>();
List<SysDepart> departs = sysDepartService.list(Wrappers.lambdaQuery(SysDepart.class)
.select(SysDepart::getOrgCode)
.in(SysDepart::getId, deptIds));
departs.forEach(depart -> {
List<SysUser> sysUsers = sysUserDepartService.queryUserByDepCode(depart.getOrgCode(), null);
if(oConvertUtils.isObjectNotEmpty(sysUsers)){
userIds.addAll(sysUsers.stream().map(SysUser::getId).collect(Collectors.toSet()));
}
});
return new ArrayList<>(userIds);
}
@Override
public List<String> queryUserAccountsByDeptIds(List<String> deptIds) {
return departMapper.queryUserAccountByDepartIds(deptIds);
}
@ -1920,7 +1958,7 @@ public class SysBaseApiImpl implements ISysBaseAPI {
try {
// 同步企业微信、钉钉的消息通知
Response<String> dtResponse = dingtalkService.sendActionCardMessage(sysAnnouncement, null, true);
wechatEnterpriseService.sendTextCardMessage(sysAnnouncement, true);
wechatEnterpriseService.sendTextCardMessage(sysAnnouncement, null,true);
if (dtResponse != null && dtResponse.isSuccess()) {
String taskId = dtResponse.getResult();
@ -1933,4 +1971,129 @@ public class SysBaseApiImpl implements ISysBaseAPI {
}
}
@Override
public SysDepartModel queryCompByOrgCode(String orgCode) {
AssertUtils.assertNotEmpty("请输入部门编码",orgCode);
SysDepart comp = sysDepartService.queryCompByOrgCode(orgCode);
if(comp == null) {
log.error("未查询到对应的公司信息");
return null;
}
SysDepartModel respData = new SysDepartModel();
BeanUtils.copyProperties(comp, respData);
return respData;
}
/**
*
*
* @param orgCode
* @param level 1 1
* @return
*/
@Override
public SysDepartModel queryCompByOrgCodeAndLevel(String orgCode, Integer level) {
if (null == level || 0 == level) {
level = 1;
}
int codeNum = YouBianCodeUtil.ZHANWEI_LENGTH;
//先判断父级code
String parendCode = "";
if (orgCode.length() > codeNum) {
parendCode = orgCode.substring(0, codeNum);
} else {
return null;
}
//根据部门编码查询公司和子公司的数据
List<String> categoryList = new ArrayList<>();
categoryList.add(DepartCategoryEnum.DEPART_CATEGORY_COMPANY.getValue());
categoryList.add(DepartCategoryEnum.DEPART_CATEGORY_SUB_COMPANY.getValue());
LambdaQueryWrapper<SysDepart> query = new LambdaQueryWrapper<>();
query.like(SysDepart::getOrgCode, parendCode);
query.in(SysDepart::getOrgCategory, categoryList);
query.orderByAsc(SysDepart::getOrgType);
List<SysDepart> sysDepartList = sysDepartService.list(query);
if (!CollectionUtils.isEmpty(sysDepartList)) {
//获取上级公司
SysDepart depart = getParentCompanyByOrgCode(orgCode, sysDepartList, level, 1);
if(depart == null){
depart = sysDepartList.get(0);
}
SysDepartModel respData = new SysDepartModel();
BeanUtils.copyProperties(depart, respData);
return respData;
}
return null;
}
@Override
public Object runAiragFlow(AiragFlowDTO airagFlowDTO) {
if(oConvertUtils.isEmpty(airagFlowDTO.getFlowId())) {
throw new JeecgBootException("流程ID不能为空");
}
FlowRunParams params = new FlowRunParams();
params.setFlowId(airagFlowDTO.getFlowId());
params.setInputParams(airagFlowDTO.getInputParams());
params.setResponseMode("blocking");
Result<Object> o = (Result<Object>)airagFlowService.runFlow(params);
return o.getResult();
}
/**
* orgCode
*
* @param orgCode
* @param sysDepartList
* @param level
* @param nowLevel
* @return
*/
public SysDepart getParentCompanyByOrgCode(String orgCode,List<SysDepart> sysDepartList, int level, int nowLevel) {
//获取上一级公司的编码
String code = this.getPrefix(orgCode);
if(oConvertUtils.isEmpty(code)) {
return null;
}
List<SysDepart> list = sysDepartList.stream().filter(sysDepart -> sysDepart.getOrgCode().equals(code)).toList();
//判断去上级的级别
if(!CollectionUtils.isEmpty(list) && nowLevel == level) {
return list.get(0);
} else {
if(!CollectionUtils.isEmpty(list)) {
nowLevel++;
}
return getParentCompanyByOrgCode(code, sysDepartList, level, nowLevel);
}
}
/**
* YouBianCodeUtil.ZHANWEI_LENGTH
*
* @param fullCode "A01A01A01"
* @return "A01A01"
*/
private String getPrefix(String fullCode) {
if(fullCode.length() < YouBianCodeUtil.ZHANWEI_LENGTH){
return "";
}
// 计算总层级数,根据ZHANWEI_LENGTH
int totalLevels = fullCode.length() / YouBianCodeUtil.ZHANWEI_LENGTH;
int keepLevels = totalLevels - 1;
// 计算需要截取的长度(保留层级数 × YouBianCodeUtil.ZHANWEI_LENGTH
int prefixLength = keepLevels * YouBianCodeUtil.ZHANWEI_LENGTH;
return prefixLength == 0 ? "" : fullCode.substring(0, prefixLength);
}
/**
* codeid()
*
* @param orgCode
* @param depId id
* @return String
*/
@Override
public String getDepartPathNameByOrgCode(String orgCode, String depId) {
return sysDepartService.getDepartPathNameByOrgCode(orgCode, depId);
}
}

View File

@ -1,6 +1,7 @@
package org.jeecg.modules.system.service.impl;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -846,7 +847,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
* @param verifyConfig APP
* @return
*/
public JSONObject sendTextCardMessage(SysAnnouncement announcement, boolean verifyConfig) {
public JSONObject sendTextCardMessage(SysAnnouncement announcement,String mobileOpenUrl, boolean verifyConfig) {
SysThirdAppConfig config = this.getWeChatThirdAppConfig();
if (verifyConfig && null == config) {
return null;
@ -882,9 +883,30 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
textCard.setTouser(this.getTouser(usernameString, isToAll));
TextCardEntity entity = new TextCardEntity();
entity.setTitle(announcement.getTitile());
entity.setDescription(oConvertUtils.getString(announcement.getMsgAbstract(),"空"));
String baseUrl = null;
//update-begin---author:scott ---date:2025-08-05 for【QQYUN-13257】【h5】催办、抄送消息在企业微信中显示json乱码---
// 判断announcement.getMsgAbstract()值是json格式
if(oConvertUtils.isJson(announcement.getMsgAbstract()) && oConvertUtils.isNotEmpty(mobileOpenUrl)){
entity.setDescription(announcement.getMsgContent());
entity.setUrl(mobileOpenUrl);
}else{
entity.setDescription(oConvertUtils.getString(announcement.getMsgAbstract(),"空"));
entity.setUrl(geQywxtAnnouncementUrl(announcement));
}
//update-end---author:scott ---date::2025-08-05 for【QQYUN-13257】【h5】催办、抄送消息在企业微信中显示json乱码---
textCard.setTextcard(entity);
return JwMessageAPI.sendTextCardMessage(textCard, accessToken);
}
/**
*
*
* @return
*/
private String geQywxtAnnouncementUrl(SysAnnouncement announcement){
String baseUrl = null;
//优先通过请求获取basepath获取不到读取 jeecg.domainUrl.pc
try {
baseUrl = RestUtil.getBaseUrl();
@ -893,10 +915,7 @@ public class ThirdAppWechatEnterpriseServiceImpl implements IThirdAppService {
baseUrl = jeecgBaseConfig.getDomainUrl().getPc();
//e.printStackTrace();
}
entity.setUrl(baseUrl + "/sys/annountCement/show/" + announcement.getId());
textCard.setTextcard(entity);
return JwMessageAPI.sendTextCardMessage(textCard, accessToken);
return baseUrl + "/sys/annountCement/show/" + announcement.getId();
}
private String getTouser(String origin, boolean toAll) {