mirror of https://github.com/jeecgboot/jeecg-boot
【v3.8.3】企业微信通知采用卡片
parent
700318e1c1
commit
d383f7458d
|
@ -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,6 +1788,21 @@ public class SysBaseApiImpl implements ISysBaseAPI {
|
|||
return sysUserDepartService.listObjs(queryWrapper,e->e.toString());
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据部门code或部门id获取部门名称(当前和上级部门)
|
||||
*
|
||||
* @param orgCode 部门编码
|
||||
* @param depId 部门id
|
||||
* @return String 部门名称
|
||||
*/
|
||||
@Override
|
||||
public String getDepartPathNameByOrgCode(String orgCode, String depId) {
|
||||
return sysDepartService.getDepartPathNameByOrgCode(orgCode, depId);
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue