feat: 消息推送
This commit is contained in:
@@ -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