feat: 消息推送
This commit is contained in:
+104
@@ -0,0 +1,104 @@
|
||||
package com.budwk.app.zhgh.pointsmall.message.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.annotation.SLog;
|
||||
import com.budwk.app.base.result.Result;
|
||||
import com.budwk.app.zhgh.pointsmall.message.models.PointsMallMessageTemplate;
|
||||
import com.budwk.app.zhgh.pointsmall.message.param.PointsMallMessagePageParam;
|
||||
import com.budwk.app.zhgh.pointsmall.message.param.PointsMallMessageTemplatePageParam;
|
||||
import com.budwk.app.zhgh.pointsmall.message.service.PointsMallMessageService;
|
||||
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 java.util.List;
|
||||
|
||||
@IocBean
|
||||
@Ok("json:full")
|
||||
@At("/platform/zhgh/points-mall/message")
|
||||
public class PointsMallMessageController {
|
||||
|
||||
@Inject
|
||||
private PointsMallMessageService pointsMallMessageService;
|
||||
|
||||
@At("")
|
||||
@Ok("beetl:/platform/zhgh/points-mall/message/index.html")
|
||||
@SaCheckPermission("points.mall.message")
|
||||
public void index() {
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("points.mall.message")
|
||||
public Result pageData(PointsMallMessageTemplatePageParam param) {
|
||||
return Result.success(pointsMallMessageService.templatePage(param));
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("points.mall.message")
|
||||
public Result list() {
|
||||
return Result.success(pointsMallMessageService.templateList());
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("points.mall.message")
|
||||
public Result get(@Param("id") String id) {
|
||||
return Result.success(pointsMallMessageService.fetch(id));
|
||||
}
|
||||
|
||||
@At
|
||||
@SLog(tag = "消息推送", msg = "保存消息模板")
|
||||
@SaCheckPermission("points.mall.message")
|
||||
public Result doSave(PointsMallMessageTemplate template) {
|
||||
try {
|
||||
pointsMallMessageService.saveTemplate(template);
|
||||
return Result.success();
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@At
|
||||
@SLog(tag = "消息推送", msg = "删除消息模板")
|
||||
@SaCheckPermission("points.mall.message")
|
||||
public Result doDelete(@Param("ids") String ids) {
|
||||
List<String> idList = StrUtil.split(ids, ',');
|
||||
if (idList.isEmpty()) {
|
||||
return Result.error("请选择需要删除的数据");
|
||||
}
|
||||
try {
|
||||
return Result.success(pointsMallMessageService.deleteTemplate(idList));
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@At
|
||||
@SaCheckPermission("points.mall.message")
|
||||
public Result recordPage(PointsMallMessagePageParam param) {
|
||||
return Result.success(pointsMallMessageService.messagePage(param));
|
||||
}
|
||||
|
||||
@At
|
||||
@SLog(tag = "消息推送", msg = "重新推送消息")
|
||||
@SaCheckPermission("points.mall.message")
|
||||
public Result resend(@Param("ids") String ids) {
|
||||
List<String> idList = StrUtil.split(ids, ',');
|
||||
try {
|
||||
pointsMallMessageService.resend(idList);
|
||||
return Result.success();
|
||||
} catch (IllegalArgumentException e) {
|
||||
return Result.error(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@At
|
||||
@SLog(tag = "消息推送", msg = "一键推送消息")
|
||||
@SaCheckPermission("points.mall.message")
|
||||
public Result resendAll(PointsMallMessagePageParam param) {
|
||||
pointsMallMessageService.resendAll(param);
|
||||
return Result.success();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package com.budwk.app.zhgh.pointsmall.message.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.ColDefine;
|
||||
import org.nutz.dao.entity.annotation.ColType;
|
||||
import org.nutz.dao.entity.annotation.Column;
|
||||
import org.nutz.dao.entity.annotation.Comment;
|
||||
import org.nutz.dao.entity.annotation.Name;
|
||||
import org.nutz.dao.entity.annotation.Table;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("points_mall_message")
|
||||
@Comment("积分商城消息记录")
|
||||
public class PointsMallMessage extends BaseModel implements Serializable {
|
||||
|
||||
@Name
|
||||
@Column
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("业务唯一号")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 128)
|
||||
private String uniqueNo;
|
||||
|
||||
@Column
|
||||
@Comment("推送类型")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 50)
|
||||
private String pushType;
|
||||
|
||||
@Column
|
||||
@Comment("模板ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
private String templateId;
|
||||
|
||||
@Column
|
||||
@Comment("目标用户")
|
||||
@ColDefine(type = ColType.VARCHAR, customType = "mediumtext")
|
||||
private String touser;
|
||||
|
||||
@Column
|
||||
@Comment("目标部门")
|
||||
@ColDefine(type = ColType.VARCHAR, customType = "mediumtext")
|
||||
private String toparty;
|
||||
|
||||
@Column
|
||||
@Comment("目标标签")
|
||||
@ColDefine(type = ColType.VARCHAR, customType = "mediumtext")
|
||||
private String totag;
|
||||
|
||||
@Column
|
||||
@Comment("推送内容")
|
||||
@ColDefine(type = ColType.VARCHAR, customType = "mediumtext")
|
||||
private String content;
|
||||
|
||||
@Column
|
||||
@Comment("内容链接")
|
||||
@ColDefine(type = ColType.VARCHAR, customType = "mediumtext")
|
||||
private String contentLink;
|
||||
|
||||
@Column
|
||||
@Comment("计划推送时间")
|
||||
private Date planPushTime;
|
||||
|
||||
@Column
|
||||
@Comment("状态")
|
||||
private Integer status;
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
package com.budwk.app.zhgh.pointsmall.message.models;
|
||||
|
||||
import com.budwk.app.base.model.BaseModel;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import org.nutz.dao.entity.annotation.ColDefine;
|
||||
import org.nutz.dao.entity.annotation.ColType;
|
||||
import org.nutz.dao.entity.annotation.Column;
|
||||
import org.nutz.dao.entity.annotation.Comment;
|
||||
import org.nutz.dao.entity.annotation.Default;
|
||||
import org.nutz.dao.entity.annotation.Name;
|
||||
import org.nutz.dao.entity.annotation.Table;
|
||||
import org.nutz.dao.interceptor.annotation.PrevInsert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Table("points_mall_message_template")
|
||||
@Comment("积分商城消息模板")
|
||||
public class PointsMallMessageTemplate extends BaseModel implements Serializable {
|
||||
|
||||
@Name
|
||||
@Column
|
||||
@Comment("ID")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 32)
|
||||
@PrevInsert(uu32 = true)
|
||||
private String id;
|
||||
|
||||
@Column
|
||||
@Comment("模板名称")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String name;
|
||||
|
||||
@Column
|
||||
@Comment("模板类型")
|
||||
private Integer type;
|
||||
|
||||
@Column
|
||||
@Comment("内容模板")
|
||||
@ColDefine(type = ColType.VARCHAR, customType = "mediumtext")
|
||||
private String content;
|
||||
|
||||
@Column
|
||||
@Comment("内容链接")
|
||||
@ColDefine(type = ColType.VARCHAR, customType = "mediumtext")
|
||||
private String contentLink;
|
||||
|
||||
@Column
|
||||
@Comment("状态:0禁用,1启用")
|
||||
@Default("1")
|
||||
private Integer status;
|
||||
|
||||
@Column
|
||||
@Comment("扩展参数")
|
||||
@ColDefine(type = ColType.VARCHAR, customType = "mediumtext")
|
||||
private String extParam;
|
||||
|
||||
@Column
|
||||
@Comment("是否发放积分")
|
||||
@Default("0")
|
||||
private Integer isSendPoints;
|
||||
|
||||
@Column
|
||||
@Comment("发放积分")
|
||||
@Default("0")
|
||||
@ColDefine(customType = "decimal(18,2)")
|
||||
private BigDecimal sendPoints;
|
||||
|
||||
@Column
|
||||
@Comment("目标机构列表")
|
||||
@ColDefine(type = ColType.VARCHAR, customType = "mediumtext")
|
||||
private String deptIdList;
|
||||
|
||||
@Column
|
||||
@Comment("目标工会列表")
|
||||
@ColDefine(type = ColType.VARCHAR, customType = "mediumtext")
|
||||
private String unionIdList;
|
||||
|
||||
@Column
|
||||
@Comment("节日日期")
|
||||
@ColDefine(type = ColType.VARCHAR, width = 100)
|
||||
private String festivalDate;
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.budwk.app.zhgh.pointsmall.message.param;
|
||||
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PointsMallMessagePageParam extends PageForm {
|
||||
|
||||
private String templateId;
|
||||
private String touser;
|
||||
private String statuses;
|
||||
private String createTimeStart;
|
||||
private String createTimeEnd;
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
package com.budwk.app.zhgh.pointsmall.message.param;
|
||||
|
||||
import com.budwk.app.base.param.PageForm;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class PointsMallMessageTemplatePageParam extends PageForm {
|
||||
|
||||
private String name;
|
||||
private Integer type;
|
||||
private Integer status;
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
package com.budwk.app.zhgh.pointsmall.message.service;
|
||||
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.service.BaseService;
|
||||
import com.budwk.app.zhgh.pointsmall.message.models.PointsMallMessage;
|
||||
import com.budwk.app.zhgh.pointsmall.message.models.PointsMallMessageTemplate;
|
||||
import com.budwk.app.zhgh.pointsmall.message.param.PointsMallMessagePageParam;
|
||||
import com.budwk.app.zhgh.pointsmall.message.param.PointsMallMessageTemplatePageParam;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface PointsMallMessageService extends BaseService<PointsMallMessageTemplate> {
|
||||
|
||||
Pagination<PointsMallMessageTemplate> templatePage(PointsMallMessageTemplatePageParam param);
|
||||
|
||||
List<PointsMallMessageTemplate> templateList();
|
||||
|
||||
void saveTemplate(PointsMallMessageTemplate template);
|
||||
|
||||
int deleteTemplate(List<String> ids);
|
||||
|
||||
Pagination<PointsMallMessage> messagePage(PointsMallMessagePageParam param);
|
||||
|
||||
void resend(List<String> ids);
|
||||
|
||||
void resendAll(PointsMallMessagePageParam param);
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
package com.budwk.app.zhgh.pointsmall.message.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.budwk.app.base.page.Pagination;
|
||||
import com.budwk.app.base.service.impl.BaseServiceImpl;
|
||||
import com.budwk.app.zhgh.pointsmall.message.models.PointsMallMessage;
|
||||
import com.budwk.app.zhgh.pointsmall.message.models.PointsMallMessageTemplate;
|
||||
import com.budwk.app.zhgh.pointsmall.message.param.PointsMallMessagePageParam;
|
||||
import com.budwk.app.zhgh.pointsmall.message.param.PointsMallMessageTemplatePageParam;
|
||||
import com.budwk.app.zhgh.pointsmall.message.service.PointsMallMessageService;
|
||||
import org.nutz.dao.Chain;
|
||||
import org.nutz.dao.Cnd;
|
||||
import org.nutz.dao.Dao;
|
||||
import org.nutz.ioc.loader.annotation.IocBean;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@IocBean(args = {"refer:dao"})
|
||||
public class PointsMallMessageServiceImpl extends BaseServiceImpl<PointsMallMessageTemplate> implements PointsMallMessageService {
|
||||
|
||||
public PointsMallMessageServiceImpl(Dao dao) {
|
||||
super(dao);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pagination<PointsMallMessageTemplate> templatePage(PointsMallMessageTemplatePageParam param) {
|
||||
Cnd cnd = templateCnd(param);
|
||||
cnd.desc("createdAt");
|
||||
return listPage(param.getPageNumber(), param.getPageSize(), PointsMallMessageTemplate.class, cnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PointsMallMessageTemplate> templateList() {
|
||||
return query(Cnd.where("delFlag", "=", false).and("status", "=", 1).desc("createdAt"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveTemplate(PointsMallMessageTemplate template) {
|
||||
checkTemplate(template);
|
||||
if (template.getStatus() == null) {
|
||||
template.setStatus(1);
|
||||
}
|
||||
if (template.getIsSendPoints() == null) {
|
||||
template.setIsSendPoints(0);
|
||||
}
|
||||
if (StrUtil.isBlank(template.getId())) {
|
||||
insert(template);
|
||||
} else {
|
||||
updateIgnoreNull(template);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteTemplate(List<String> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
return 0;
|
||||
}
|
||||
List<String> canDelete = ids.stream()
|
||||
.filter(id -> dao().count("points_mall_message_schedule", Cnd.where("templateId", "=", id).and("delFlag", "=", false)) == 0)
|
||||
.filter(id -> {
|
||||
PointsMallMessageTemplate template = fetch(id);
|
||||
return template != null && !Integer.valueOf(5).equals(template.getType());
|
||||
})
|
||||
.toList();
|
||||
if (canDelete.isEmpty()) {
|
||||
throw new IllegalArgumentException("模板正在使用中或为业务消息,无法删除");
|
||||
}
|
||||
dao().update(PointsMallMessageTemplate.class, Chain.make("delFlag", true), Cnd.where("id", "in", canDelete));
|
||||
return canDelete.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pagination<PointsMallMessage> messagePage(PointsMallMessagePageParam param) {
|
||||
Cnd cnd = Cnd.where("delFlag", "=", false);
|
||||
if (StrUtil.isNotBlank(param.getTemplateId())) {
|
||||
cnd.and("templateId", "=", param.getTemplateId());
|
||||
}
|
||||
if (StrUtil.isNotBlank(param.getTouser())) {
|
||||
cnd.and("touser", "like", "%" + param.getTouser() + "%");
|
||||
}
|
||||
List<Integer> statuses = splitStatuses(param.getStatuses());
|
||||
if (CollUtil.isNotEmpty(statuses)) {
|
||||
cnd.and("status", "in", statuses);
|
||||
}
|
||||
if (StrUtil.isNotBlank(param.getCreateTimeStart())) {
|
||||
cnd.and("createdAt", ">=", DateUtil.parse(param.getCreateTimeStart()).getTime());
|
||||
}
|
||||
if (StrUtil.isNotBlank(param.getCreateTimeEnd())) {
|
||||
cnd.and("createdAt", "<=", DateUtil.parse(param.getCreateTimeEnd()).getTime());
|
||||
}
|
||||
cnd.desc("createdAt");
|
||||
return listPage(param.getPageNumber(), param.getPageSize(), PointsMallMessage.class, cnd);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resend(List<String> ids) {
|
||||
if (CollUtil.isEmpty(ids)) {
|
||||
throw new IllegalArgumentException("请选择消息记录");
|
||||
}
|
||||
dao().update(PointsMallMessage.class, Chain.make("status", 2), Cnd.where("id", "in", ids).and("status", "in", Arrays.asList(0, 3)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resendAll(PointsMallMessagePageParam param) {
|
||||
Cnd cnd = Cnd.where("delFlag", "=", false).and("status", "in", Arrays.asList(0, 3));
|
||||
if (StrUtil.isNotBlank(param.getTemplateId())) {
|
||||
cnd.and("templateId", "=", param.getTemplateId());
|
||||
}
|
||||
if (StrUtil.isNotBlank(param.getTouser())) {
|
||||
cnd.and("touser", "like", "%" + param.getTouser() + "%");
|
||||
}
|
||||
dao().update(PointsMallMessage.class, Chain.make("status", 2), cnd);
|
||||
}
|
||||
|
||||
private Cnd templateCnd(PointsMallMessageTemplatePageParam param) {
|
||||
Cnd cnd = Cnd.where("delFlag", "=", false);
|
||||
if (StrUtil.isNotBlank(param.getName())) {
|
||||
cnd.and("name", "like", "%" + param.getName() + "%");
|
||||
}
|
||||
if (param.getType() != null) {
|
||||
cnd.and("type", "=", param.getType());
|
||||
}
|
||||
if (param.getStatus() != null) {
|
||||
cnd.and("status", "=", param.getStatus());
|
||||
}
|
||||
return cnd;
|
||||
}
|
||||
|
||||
private void checkTemplate(PointsMallMessageTemplate template) {
|
||||
if (template == null) {
|
||||
throw new IllegalArgumentException("模板信息不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(template.getName())) {
|
||||
throw new IllegalArgumentException("模板名称不能为空");
|
||||
}
|
||||
if (template.getType() == null) {
|
||||
throw new IllegalArgumentException("模板类型不能为空");
|
||||
}
|
||||
if (StrUtil.isBlank(template.getContent())) {
|
||||
throw new IllegalArgumentException("模板内容不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Integer> splitStatuses(String statuses) {
|
||||
if (StrUtil.isBlank(statuses)) {
|
||||
return List.of();
|
||||
}
|
||||
return Arrays.stream(statuses.split(","))
|
||||
.map(String::trim)
|
||||
.filter(StrUtil::isNotBlank)
|
||||
.map(Integer::valueOf)
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,345 @@
|
||||
<!--#
|
||||
layout("/layouts/platform.html"){
|
||||
#-->
|
||||
<div id="app" v-cloak>
|
||||
<el-card shadow="never">
|
||||
<search @search="doSearch">
|
||||
<search-item label="模板名称">
|
||||
<el-input clearable placeholder="请输入模板名称" v-model="pageForm.name"></el-input>
|
||||
</search-item>
|
||||
<search-item label="模板类型">
|
||||
<el-select clearable placeholder="请选择模板类型" v-model="pageForm.type">
|
||||
<el-option :value="1" label="节日消息"></el-option>
|
||||
<el-option :value="2" label="提醒消息(用户-商城)"></el-option>
|
||||
<el-option :value="3" label="提醒消息(管理员-商城)"></el-option>
|
||||
<el-option :value="4" label="生日消息"></el-option>
|
||||
<el-option :value="5" label="业务消息"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
<search-item label="状态">
|
||||
<el-select clearable placeholder="请选择状态" v-model="pageForm.status">
|
||||
<el-option :value="1" label="启用"></el-option>
|
||||
<el-option :value="0" label="禁用"></el-option>
|
||||
</el-select>
|
||||
</search-item>
|
||||
</search>
|
||||
</el-card>
|
||||
|
||||
<el-card class="mt10" shadow="never">
|
||||
<table-tool label="消息推送">
|
||||
<el-button @click="openAdd" icon="el-icon-plus" size="small" type="primary">新增</el-button>
|
||||
<el-button @click="deleteSelected" icon="el-icon-delete" size="small" type="danger">删除</el-button>
|
||||
</table-tool>
|
||||
<el-table :data="tableData" @selection-change="handleSelectionChange" border size="small" style="width:100%" v-loading="tableLoading">
|
||||
<el-table-column type="selection" width="50"></el-table-column>
|
||||
<el-table-column :index="indexMethod" align="center" label="序号" type="index" width="70"></el-table-column>
|
||||
<el-table-column align="center" label="模板名称" min-width="150" prop="name" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column align="center" label="模板类型" width="170">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag size="small">{{ typeName(row.type) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="模板内容" min-width="250" prop="content" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column align="center" label="状态" width="90">
|
||||
<template slot-scope="{row}">
|
||||
<el-switch :active-value="1" :inactive-value="0" @change="changeStatus(row)" v-model="row.status"></el-switch>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="创建时间" width="170">
|
||||
<template slot-scope="{row}">{{ formatTime(row.createdAt) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" fixed="right" label="操作" width="190">
|
||||
<template slot-scope="{row}">
|
||||
<el-button @click="openEdit(row)" size="mini" type="text">编辑</el-button>
|
||||
<el-button @click="openRecords(row)" size="mini" type="text">消息记录</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination :current-page="pageForm.pageNumber" :page-size="pageForm.pageSize" :page-sizes="[10,20,30,50]" :total="pageForm.totalCount" @current-change="pageChange" @size-change="sizeChange" layout="total, sizes, prev, pager, next" style="margin-top:16px;text-align:right"></el-pagination>
|
||||
</el-card>
|
||||
|
||||
<el-dialog :close-on-click-modal="false" :title="formData.id ? '修改消息模板' : '新增消息模板'" :visible.sync="editDialogVisible" width="900px">
|
||||
<el-form :model="formData" :rules="rules" label-width="120px" ref="form">
|
||||
<el-form-item label="模板名称" prop="name">
|
||||
<el-input clearable placeholder="请输入模板名称" v-model="formData.name"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板类型" prop="type">
|
||||
<el-select placeholder="请选择模板类型" style="width:100%" v-model="formData.type">
|
||||
<el-option :value="1" label="节日消息"></el-option>
|
||||
<el-option :value="2" label="提醒消息(用户-商城)"></el-option>
|
||||
<el-option :value="3" label="提醒消息(管理员-商城)"></el-option>
|
||||
<el-option :value="4" label="生日消息"></el-option>
|
||||
<el-option :value="5" label="业务消息"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="formData.type === 1" label="节日日期">
|
||||
<el-date-picker placeholder="请选择节日日期" style="width:100%" type="date" value-format="yyyy-MM-dd" v-model="formData.festivalDate"></el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否发放积分">
|
||||
<el-radio-group v-model="formData.isSendPoints">
|
||||
<el-radio :label="1">发放</el-radio>
|
||||
<el-radio :label="0">不发放</el-radio>
|
||||
</el-radio-group>
|
||||
<el-input-number v-if="formData.isSendPoints === 1" :min="0" :precision="2" controls-position="right" style="margin-left:16px;width:180px" v-model="formData.sendPoints"></el-input-number>
|
||||
</el-form-item>
|
||||
<el-form-item label="目标机构列表">
|
||||
<el-input clearable placeholder="多个机构ID用英文逗号分隔" v-model="formData.deptIdList"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="目标工会列表">
|
||||
<el-input clearable placeholder="多个工会ID用英文逗号分隔" v-model="formData.unionIdList"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="内容链接">
|
||||
<el-input :rows="3" placeholder="请输入内容链接JSON或文本" type="textarea" v-model="formData.contentLink"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="模板内容" prop="content">
|
||||
<el-input :rows="6" placeholder="请输入模板内容" type="textarea" v-model="formData.content"></el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span slot="footer">
|
||||
<el-button @click="editDialogVisible=false">取消</el-button>
|
||||
<el-button :loading="submitLoading" @click="submitForm" type="primary">保存</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog :title="recordTitle" :visible.sync="recordDialogVisible" width="1050px">
|
||||
<el-form inline @submit.native.prevent>
|
||||
<el-form-item label="用户工号">
|
||||
<el-input clearable placeholder="请输入用户工号" v-model="recordForm.touser"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="状态">
|
||||
<el-select clearable multiple placeholder="请选择状态" style="width:180px" v-model="recordStatuses">
|
||||
<el-option :value="0" label="未推送"></el-option>
|
||||
<el-option :value="2" label="推送中"></el-option>
|
||||
<el-option :value="1" label="已推送"></el-option>
|
||||
<el-option :value="3" label="推送失败"></el-option>
|
||||
<el-option :value="-1" label="不推送"></el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="recordSearch" type="primary">查询</el-button>
|
||||
<el-button @click="recordReset">重置</el-button>
|
||||
<el-button @click="resendSelected" type="primary">确认推送</el-button>
|
||||
<el-button @click="resendAll" type="primary">一键全部推送</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-table :data="recordData" @selection-change="handleRecordSelectionChange" border size="small" v-loading="recordLoading">
|
||||
<el-table-column type="selection" width="50"></el-table-column>
|
||||
<el-table-column :index="recordIndexMethod" align="center" label="序号" type="index" width="70"></el-table-column>
|
||||
<el-table-column align="center" label="用户工号" prop="touser" width="130"></el-table-column>
|
||||
<el-table-column align="center" label="推送内容" min-width="260" prop="content" show-overflow-tooltip></el-table-column>
|
||||
<el-table-column align="center" label="状态" width="110">
|
||||
<template slot-scope="{row}">
|
||||
<el-tag :type="messageStatusTag(row.status)" size="small">{{ messageStatusName(row.status) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="计划推送时间" prop="planPushTime" width="170"></el-table-column>
|
||||
<el-table-column align="center" label="创建时间" width="170">
|
||||
<template slot-scope="{row}">{{ formatTime(row.createdAt) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" fixed="right" label="操作" width="100">
|
||||
<template slot-scope="{row}">
|
||||
<el-button :disabled="row.status !== 0 && row.status !== 3" @click="resendRow(row)" size="mini" type="text">重新推送</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-pagination :current-page="recordForm.pageNumber" :page-size="recordForm.pageSize" :total="recordForm.totalCount" @current-change="recordPageChange" layout="total, prev, pager, next" style="margin-top:16px;text-align:right"></el-pagination>
|
||||
</el-dialog>
|
||||
</div>
|
||||
|
||||
<script nonce="${cspNonce!}">
|
||||
new Vue({
|
||||
el: "#app",
|
||||
data() {
|
||||
return {
|
||||
tableData: [],
|
||||
tableLoading: false,
|
||||
submitLoading: false,
|
||||
multipleSelection: [],
|
||||
editDialogVisible: false,
|
||||
pageForm: {pageNumber: 1, pageSize: 10, totalCount: 0, name: "", type: null, status: null},
|
||||
formData: {},
|
||||
rules: {
|
||||
name: [{required: true, message: "请输入模板名称", trigger: "blur"}],
|
||||
type: [{required: true, message: "请选择模板类型", trigger: "change"}],
|
||||
content: [{required: true, message: "请输入模板内容", trigger: "blur"}]
|
||||
},
|
||||
recordDialogVisible: false,
|
||||
recordTitle: "消息记录",
|
||||
recordData: [],
|
||||
recordLoading: false,
|
||||
recordSelection: [],
|
||||
recordStatuses: [],
|
||||
recordForm: {pageNumber: 1, pageSize: 10, totalCount: 0, templateId: "", touser: "", statuses: ""}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
indexMethod(index) { return index + 1 + (this.pageForm.pageNumber - 1) * this.pageForm.pageSize },
|
||||
recordIndexMethod(index) { return index + 1 + (this.recordForm.pageNumber - 1) * this.recordForm.pageSize },
|
||||
formatTime(value) { return value ? new Date(value).toLocaleString() : "" },
|
||||
typeName(type) {
|
||||
return {1: "节日消息", 2: "提醒消息(用户-商城)", 3: "提醒消息(管理员-商城)", 4: "生日消息", 5: "业务消息"}[type] || "-"
|
||||
},
|
||||
messageStatusName(status) {
|
||||
return {0: "未推送", 1: "已推送", 2: "推送中", 3: "推送失败", "-1": "不推送"}[status] || "-"
|
||||
},
|
||||
messageStatusTag(status) {
|
||||
if (status === 1) return "success"
|
||||
if (status === 2) return "warning"
|
||||
if (status === 3 || status === -1) return "danger"
|
||||
return "info"
|
||||
},
|
||||
doSearch() { this.pageForm.pageNumber = 1; this.pageData() },
|
||||
async pageData() {
|
||||
this.tableLoading = true
|
||||
const res = await this.$axios.post("/platform/zhgh/points-mall/message/pageData", this.pageForm)
|
||||
this.tableLoading = false
|
||||
if (res.code === 0) {
|
||||
this.tableData = res.data.list || []
|
||||
this.pageForm.totalCount = res.data.totalCount || 0
|
||||
} else {
|
||||
this.$message.warning(res.msg)
|
||||
}
|
||||
},
|
||||
pageChange(value) { this.pageForm.pageNumber = value; this.pageData() },
|
||||
sizeChange(value) { this.pageForm.pageSize = value; this.pageForm.pageNumber = 1; this.pageData() },
|
||||
handleSelectionChange(value) { this.multipleSelection = value },
|
||||
openAdd() {
|
||||
this.formData = {name: "", type: 1, content: "", contentLink: "", status: 1, extParam: "", isSendPoints: 0, sendPoints: 0, deptIdList: "", unionIdList: "", festivalDate: ""}
|
||||
this.editDialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
},
|
||||
openEdit(row) {
|
||||
this.formData = Object.assign({}, row)
|
||||
this.editDialogVisible = true
|
||||
this.$nextTick(() => this.$refs.form && this.$refs.form.clearValidate())
|
||||
},
|
||||
async submitForm() {
|
||||
this.$refs.form.validate(async valid => {
|
||||
if (!valid) return
|
||||
this.submitLoading = true
|
||||
const res = await this.$axios.post("/platform/zhgh/points-mall/message/doSave", this.formData)
|
||||
this.submitLoading = false
|
||||
if (res.code === 0) {
|
||||
this.$message.success(res.msg)
|
||||
this.editDialogVisible = false
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg)
|
||||
}
|
||||
})
|
||||
},
|
||||
async changeStatus(row) {
|
||||
const res = await this.$axios.post("/platform/zhgh/points-mall/message/doSave", row)
|
||||
if (res.code === 0) {
|
||||
this.$message.success("修改成功")
|
||||
} else {
|
||||
row.status = row.status === 1 ? 0 : 1
|
||||
this.$message.warning(res.msg)
|
||||
}
|
||||
},
|
||||
deleteSelected() {
|
||||
if (!this.multipleSelection.length) {
|
||||
this.$message.warning("请至少选择一条数据")
|
||||
return
|
||||
}
|
||||
if (this.multipleSelection.some(item => item.type === 5)) {
|
||||
this.$message.warning("业务消息不允许删除")
|
||||
return
|
||||
}
|
||||
this.$confirm("确定删除选中模板吗?", "提示", {
|
||||
type: "warning",
|
||||
callback: async action => {
|
||||
if (action === "confirm") {
|
||||
const res = await this.$axios.post("/platform/zhgh/points-mall/message/doDelete", {ids: this.multipleSelection.map(item => item.id).join(",")})
|
||||
if (res.code === 0) {
|
||||
this.$message.success("删除成功")
|
||||
this.pageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
openRecords(row) {
|
||||
this.recordTitle = "消息记录 - " + row.name
|
||||
this.recordStatuses = []
|
||||
this.recordForm = {pageNumber: 1, pageSize: 10, totalCount: 0, templateId: row.id, touser: "", statuses: ""}
|
||||
this.recordDialogVisible = true
|
||||
this.recordPageData()
|
||||
},
|
||||
handleRecordSelectionChange(value) { this.recordSelection = value },
|
||||
recordSearch() {
|
||||
this.recordForm.pageNumber = 1
|
||||
this.recordForm.statuses = this.recordStatuses.join(",")
|
||||
this.recordPageData()
|
||||
},
|
||||
recordReset() {
|
||||
this.recordStatuses = []
|
||||
this.recordForm.touser = ""
|
||||
this.recordSearch()
|
||||
},
|
||||
async recordPageData() {
|
||||
this.recordLoading = true
|
||||
const res = await this.$axios.post("/platform/zhgh/points-mall/message/recordPage", this.recordForm)
|
||||
this.recordLoading = false
|
||||
if (res.code === 0) {
|
||||
this.recordData = res.data.list || []
|
||||
this.recordForm.totalCount = res.data.totalCount || 0
|
||||
} else {
|
||||
this.$message.warning(res.msg)
|
||||
}
|
||||
},
|
||||
recordPageChange(value) { this.recordForm.pageNumber = value; this.recordPageData() },
|
||||
resendRow(row) { this.resend([row]) },
|
||||
resendSelected() {
|
||||
if (!this.recordSelection.length) {
|
||||
this.$message.warning("请至少选择一条消息记录")
|
||||
return
|
||||
}
|
||||
this.resend(this.recordSelection)
|
||||
},
|
||||
resend(rows) {
|
||||
const allowed = rows.filter(row => row.status === 0 || row.status === 3)
|
||||
if (!allowed.length) {
|
||||
this.$message.warning("请选择未推送或推送失败的消息")
|
||||
return
|
||||
}
|
||||
this.$confirm("确定重新推送选中消息吗?", "提示", {
|
||||
type: "warning",
|
||||
callback: async action => {
|
||||
if (action === "confirm") {
|
||||
const res = await this.$axios.post("/platform/zhgh/points-mall/message/resend", {ids: allowed.map(item => item.id).join(",")})
|
||||
if (res.code === 0) {
|
||||
this.$message.success("推送已触发")
|
||||
this.recordPageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
resendAll() {
|
||||
this.$confirm("确定按当前条件推送全部未推送/失败消息吗?", "提示", {
|
||||
type: "warning",
|
||||
callback: async action => {
|
||||
if (action === "confirm") {
|
||||
const res = await this.$axios.post("/platform/zhgh/points-mall/message/resendAll", this.recordForm)
|
||||
if (res.code === 0) {
|
||||
this.$message.success("推送已触发")
|
||||
this.recordPageData()
|
||||
} else {
|
||||
this.$message.warning(res.msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
created() { this.pageData() }
|
||||
})
|
||||
</script>
|
||||
<!--#
|
||||
}
|
||||
#-->
|
||||
Reference in New Issue
Block a user