This commit is contained in:
@jyuhsin
2026-03-06 11:50:29 +08:00
parent f526db3153
commit 33bcdc42e7
7 changed files with 102 additions and 7 deletions
@@ -69,6 +69,14 @@ public interface SmsService {
*/ */
void sendSinglePicTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl, String picUrl); void sendSinglePicTextCard(String loginName, String title, String content, String pcUrl, String mobileUrl, String picUrl);
/**
* 群发普通消息(多人接收相同内容)
* @param loginNames 接收人工号列表(必填,不能为空列表)
* @param content 消息内容(必填)
* @return void
*/
void massSendMessage(List<String> loginNames, String content);
/** /**
* 群发普通消息(多人接收相同内容) * 群发普通消息(多人接收相同内容)
* @param loginNames 接收人工号列表(必填,不能为空列表) * @param loginNames 接收人工号列表(必填,不能为空列表)
@@ -78,6 +86,16 @@ public interface SmsService {
*/ */
void massSendMessage(List<String> loginNames, String title, String content); void massSendMessage(List<String> loginNames, String title, String content);
/**
* 群发短信文本卡片消息
* @param loginNames 接收人工号列表(必填,不能为空列表)
* @param content 卡片内容(必填)
* @param pcUrl PC端跳转链接(必填)
* @param mobileUrl 移动端跳转链接(必填)
* @return
*/
void massSendTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl);
/** /**
* 群发短信文本卡片消息 * 群发短信文本卡片消息
* @param loginNames 接收人工号列表(必填,不能为空列表) * @param loginNames 接收人工号列表(必填,不能为空列表)
@@ -89,6 +107,17 @@ public interface SmsService {
*/ */
void massSendTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl); void massSendTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl);
/**
* 群发图文卡片消息
* @param loginNames 接收人工号列表(必填,不能为空列表)
* @param content 卡片内容(必填)
* @param pcUrl PC端跳转链接(必填)
* @param mobileUrl 移动端跳转链接(必填)
* @param picUrl 图片链接(必填)
* @return
*/
void massSendPicTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl, String picUrl);
/** /**
* 群发图文卡片消息 * 群发图文卡片消息
* @param loginNames 接收人工号列表(必填,不能为空列表) * @param loginNames 接收人工号列表(必填,不能为空列表)
@@ -60,6 +60,11 @@ public class SmsJshvcServiceImpl implements SmsService {
this.massSendPicTextCard(List.of(loginName), title, content, pcUrl, mobileUrl, picUrl); this.massSendPicTextCard(List.of(loginName), title, content, pcUrl, mobileUrl, picUrl);
} }
@Override
public void massSendMessage(List<String> loginNames, String content) {
this.massSendMessage(loginNames, "智慧工会", content);
}
@Override @Override
public void massSendMessage(List<String> loginNames, String title, String content) { public void massSendMessage(List<String> loginNames, String title, String content) {
List<ReceiverDto> list = loginNames.stream().map(loginName -> { List<ReceiverDto> list = loginNames.stream().map(loginName -> {
@@ -70,6 +75,11 @@ public class SmsJshvcServiceImpl implements SmsService {
this.doSend(WxSendType_Constants.TEXT, list, title, content, null, null, null); this.doSend(WxSendType_Constants.TEXT, list, title, content, null, null, null);
} }
@Override
public void massSendTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl) {
this.massSendTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl);
}
@Override @Override
public void massSendTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl) { public void massSendTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl) {
List<ReceiverDto> list = loginNames.stream().map(loginName -> { List<ReceiverDto> list = loginNames.stream().map(loginName -> {
@@ -80,6 +90,11 @@ public class SmsJshvcServiceImpl implements SmsService {
this.doSend(WxSendType_Constants.TEXT_CARD, list, title, content, pcUrl, mobileUrl, null); this.doSend(WxSendType_Constants.TEXT_CARD, list, title, content, pcUrl, mobileUrl, null);
} }
@Override
public void massSendPicTextCard(List<String> loginNames, String content, String pcUrl, String mobileUrl, String picUrl) {
this.massSendPicTextCard(loginNames, "智慧工会", content, pcUrl, mobileUrl, picUrl);
}
@Override @Override
public void massSendPicTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl, String picUrl) { public void massSendPicTextCard(List<String> loginNames, String title, String content, String pcUrl, String mobileUrl, String picUrl) {
List<ReceiverDto> list = loginNames.stream().map(loginName -> { List<ReceiverDto> list = loginNames.stream().map(loginName -> {
@@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import com.budwk.app.base.annotation.RepeatSubmit; import com.budwk.app.base.annotation.RepeatSubmit;
import com.budwk.app.base.annotation.SLog; import com.budwk.app.base.annotation.SLog;
import com.budwk.app.base.constant.RoleConstant;
import com.budwk.app.base.page.Pagination; import com.budwk.app.base.page.Pagination;
import com.budwk.app.base.param.PageForm; import com.budwk.app.base.param.PageForm;
import com.budwk.app.base.result.Result; import com.budwk.app.base.result.Result;
@@ -16,16 +17,23 @@ import com.budwk.app.sys.models.Sys_role;
import com.budwk.app.sys.services.SysMsgService; import com.budwk.app.sys.services.SysMsgService;
import com.budwk.app.sys.services.SysMsgUserService; import com.budwk.app.sys.services.SysMsgUserService;
import com.budwk.app.sys.services.SysUserService; import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil; 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 io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.nutz.dao.Cnd; import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls; import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql; import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.dao.util.cri.Static; import org.nutz.dao.util.cri.Static;
import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings; import org.nutz.lang.Strings;
import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.At;
import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Ok;
@@ -47,6 +55,8 @@ public class SysMsgController {
private SysMsgUserService sysMsgUserService; private SysMsgUserService sysMsgUserService;
@Inject @Inject
private SysUserService sysUserService; private SysUserService sysUserService;
@Inject
private SysClubService sysClubService;
@At({"/", "/list/?"}) @At({"/", "/list/?"})
@Ok("beetl:/platform/sys/msg/index.html") @Ok("beetl:/platform/sys/msg/index.html")
@@ -197,6 +207,28 @@ public class SysMsgController {
if (Strings.isNotBlank(pageForm.getPageOrderName()) && Strings.isNotBlank(pageForm.getPageOrderBy())) { if (Strings.isNotBlank(pageForm.getPageOrderName()) && Strings.isNotBlank(pageForm.getPageOrderBy())) {
cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy())); cnd.orderBy(pageForm.getPageOrderName(), PageUtil.getOrder(pageForm.getPageOrderBy()));
} }
SqlExpressionGroup group = new SqlExpressionGroup();
if(!AuthUtil.hasRoleOr(RoleConstant.SYSADMIN.name(), RoleConstant.SCHOOL_UNION_ADMIN.name())) {
if(AuthUtil.hasRoleOr(RoleConstant.BRANCH_UNION_ADMIN.name(), RoleConstant.BRANCH_UNION_CHAIRMAN.name())) {
group.or("u.unionId", "=", SecurityUtil.getUnionId());
}
if(AuthUtil.hasRoleOr(RoleConstant.CLUB_PRESIDENT.name(), RoleConstant.CLUB_MANAGER.name(),RoleConstant.CLUB_SECRETARY.name())) {
List<SysClub> myManageClub = sysClubService.getMyManageClub();
if(Lang.isNotEmpty(myManageClub)) {
List<String> list = myManageClub.stream().map(SysClub::getId).toList();
List<ClubUser> clubUsers = sysClubService.dao().query(ClubUser.class, Cnd.where(ClubUser::getClubId, "in", list));
if(Lang.isNotEmpty(clubUsers)) {
List<String> clubUserList = clubUsers.stream().map(ClubUser::getUserId).distinct().toList();
group.or("u.id", "in", clubUserList);
}
}
}
}
if(!group.isEmpty()) {
cnd.and(group);
}
sql.setCondition(cnd); sql.setCondition(cnd);
return Result.success().addData(sysUserService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql)); return Result.success().addData(sysUserService.listPageMap(pageForm.getPageNumber(), pageForm.getPageSize(), sql));
} catch (Exception e) { } catch (Exception e) {
@@ -57,6 +57,12 @@ public class Sys_msg extends BaseModel implements Serializable {
@Many(field = "msgId") @Many(field = "msgId")
private List<Sys_msg_user> userList; private List<Sys_msg_user> userList;
@Column
@Comment("同步企业微信")
@ColDefine(type = ColType.BOOLEAN)
@Default("0")
private Boolean wechatEnterprise;
@Column @Column
@Comment("是否需要反馈") @Comment("是否需要反馈")
@ColDefine(type = ColType.BOOLEAN) @ColDefine(type = ColType.BOOLEAN)
@@ -105,10 +105,12 @@ public class SysMsgServiceImpl extends BaseServiceImpl<Sys_msg> implements SysMs
// for (String loginName : loginNames) { // for (String loginName : loginNames) {
// smsService.send(loginName, sysMsg.getTitle(), sysMsg.getNote()); // smsService.send(loginName, sysMsg.getTitle(), sysMsg.getNote());
// } // }
ThreadUtil.execute(() -> { if(sysMsg.getWechatEnterprise()) {
//smsService.massSend(loginNames, sysMsg.getTitle(), HtmlUtil.cleanHtmlTag(StrUtil.blankToDefault(sysMsg.getNote(),"")), sysMsg.getUrl()); ThreadUtil.execute(() -> {
}); //smsService.massSend(loginNames, sysMsg.getTitle(), HtmlUtil.cleanHtmlTag(StrUtil.blankToDefault(sysMsg.getNote(),"")), sysMsg.getUrl());
smsService.massSendMessage(loginNames, HtmlUtil.cleanHtmlTag(StrUtil.blankToDefault(sysMsg.getNote(),"")));
});
}
return sysMsg; return sysMsg;
} }
@@ -7,6 +7,15 @@ const MSG_FORM_TEMPLATE = {
</el-form-item> </el-form-item>
<el-form-item prop="url" label="链接地址"> <el-form-item prop="url" label="链接地址">
<el-input placeholder="请输入链接地址" v-model="formData.url"></el-input> <el-input placeholder="请输入链接地址" v-model="formData.url"></el-input>
</el-form-item>
<el-form-item prop="wechatEnterprise" label="同步企业微信">
<div style="color: grey; font-size: 13px">
(温馨提醒:如选择是,将会同步发送到企业微信,同时“链接地址”、“是否需要反馈”、“消息附件”可无需填写。)
</div>
<el-radio-group v-model="formData.wechatEnterprise" size="small">
<el-radio border :label="true">是</el-radio>
<el-radio border :label="false">否</el-radio>
</el-radio-group>
</el-form-item> </el-form-item>
<el-form-item prop="needBack" label="是否需要反馈"> <el-form-item prop="needBack" label="是否需要反馈">
<el-radio-group v-model="formData.needBack" size="small"> <el-radio-group v-model="formData.needBack" size="small">
@@ -58,7 +67,7 @@ const MSG_FORM_TEMPLATE = {
<el-dialog title="选择用户" :visible.sync="selectDialogVisible" width="65%" append-to-body top="2%"> <el-dialog title="选择用户" :visible.sync="selectDialogVisible" width="65%" append-to-body top="2%">
<div class="btn-group tool-button"> <div class="btn-group tool-button">
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" @keyup.enter.native="doSearch" style="width: 300px"> <el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" @keyup.enter.native="doSearch" style="width: 240px">
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px"> <el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
<el-option label="工号" value="u.loginname"></el-option> <el-option label="工号" value="u.loginname"></el-option>
<el-option label="姓名" value="u.username"></el-option> <el-option label="姓名" value="u.username"></el-option>
@@ -136,6 +145,7 @@ const MSG_FORM_TEMPLATE = {
title: [{ required: true, message: "必填", trigger: ["blur", "change"] }], title: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
note: [{ required: true, message: "必填", trigger: ["blur", "change"] }], note: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
needBack: [{ required: true, message: "必填", trigger: ["blur", "change"] }], needBack: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
wechatEnterprise: [{ required: true, message: "必填", trigger: ["blur", "change"] }],
type: [{ required: true, message: "必填", trigger: ["blur", "change"] }] type: [{ required: true, message: "必填", trigger: ["blur", "change"] }]
}, },
selectDialogVisible: false, selectDialogVisible: false,
@@ -216,7 +226,8 @@ const MSG_FORM_TEMPLATE = {
this.formData = { this.formData = {
id: "", id: "",
type: "user", type: "user",
needBack: false needBack: false,
wechatEnterprise: false,
} }
if (this.$refs["addForm"]) this.$refs["addForm"].resetFields() if (this.$refs["addForm"]) this.$refs["addForm"].resetFields()
}, },
@@ -3,7 +3,7 @@ const VIEW_USER_TEMPLATE = {
<div> <div>
<el-dialog :title="viewUserTitle" :visible.sync="viewDialogVisible" width="65%" top="2%"> <el-dialog :title="viewUserTitle" :visible.sync="viewDialogVisible" width="65%" top="2%">
<div class="btn-group tool-button"> <div class="btn-group tool-button">
<el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" size="small" @keyup.enter.native="doSearch" style="width: 300px"> <el-input placeholder="请输入内容" v-model="pageForm.searchKeyword" size="small" @keyup.enter.native="doSearch" style="width: 240px">
<el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px"> <el-select v-model="pageForm.searchName" slot="prepend" placeholder="查询类型" style="width: 80px">
<el-option label="工号" value="u.loginname"></el-option> <el-option label="工号" value="u.loginname"></el-option>
<el-option label="姓名" value="u.username"></el-option> <el-option label="姓名" value="u.username"></el-option>