|
|
@@ -0,0 +1,208 @@
|
|
|
+<template>
|
|
|
+ <div class="notification-template-manage">
|
|
|
+ <el-card shadow="never">
|
|
|
+ <div slot="header" class="clearfix">
|
|
|
+ <span>通知模板管理</span>
|
|
|
+ <el-button type="primary" size="small" style="float: right" @click="handleAdd">新增模板</el-button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 模板列表 -->
|
|
|
+ <el-table :data="list" border v-loading="loading">
|
|
|
+ <el-table-column prop="type" label="类型" width="160">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-tag size="small">{{ row.type }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="title" label="标题" min-width="200" show-overflow-tooltip></el-table-column>
|
|
|
+ <el-table-column prop="content" label="内容模板" min-width="280" show-overflow-tooltip></el-table-column>
|
|
|
+ <el-table-column prop="channels" label="推送通道" width="220">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-tag v-for="ch in channelLabels(row.channels)" :key="ch.value" :type="ch.type" size="mini"
|
|
|
+ style="margin-right: 4px">{{ ch.label }}</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="status" label="状态" width="90">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-tag :type="row.status === 1 ? 'success' : 'info'" size="small">
|
|
|
+ {{ row.status === 1 ? '启用' : '停用' }}
|
|
|
+ </el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column prop="updatedAt" label="更新时间" width="170"></el-table-column>
|
|
|
+ <el-table-column label="操作" width="140" fixed="right">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-button size="mini" type="primary" @click="handleEdit(row)">编辑</el-button>
|
|
|
+ <el-button size="mini" type="danger" @click="handleDelete(row)">删除</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-card>
|
|
|
+
|
|
|
+ <!-- 编辑弹窗 -->
|
|
|
+ <el-dialog :title="form.id ? '编辑通知模板' : '新增通知模板'" :visible.sync="dialogVisible" width="600px">
|
|
|
+ <el-form :model="form" label-width="110px">
|
|
|
+ <el-form-item label="类型" required>
|
|
|
+ <el-select v-model="form.type" placeholder="请选择类型" filterable allow-create
|
|
|
+ style="width: 100%">
|
|
|
+ <el-option label="report_ready - 报告完成" value="report_ready"></el-option>
|
|
|
+ <el-option label="reward_granted - 奖励到账" value="reward_granted"></el-option>
|
|
|
+ <el-option label="system - 系统通知" value="system"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="标题" required>
|
|
|
+ <el-input v-model="form.title" placeholder="通知标题,如:健康报告已完成分析"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="内容模板" required>
|
|
|
+ <el-input type="textarea" v-model="form.content" :rows="4"
|
|
|
+ placeholder="支持占位符:{domainName} 问题域名称、{reward} 奖励CF值"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="推送通道">
|
|
|
+ <el-checkbox-group v-model="form.channelList">
|
|
|
+ <el-checkbox label="in_app">小程序内</el-checkbox>
|
|
|
+ <el-checkbox label="sms">短信</el-checkbox>
|
|
|
+ <el-checkbox label="wechat">微信</el-checkbox>
|
|
|
+ <el-checkbox label="phone">电话</el-checkbox>
|
|
|
+ </el-checkbox-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="状态">
|
|
|
+ <el-switch v-model="form.status" :active-value="1" :inactive-value="0"></el-switch>
|
|
|
+ <span style="margin-left: 10px; color: #999">停用后系统将使用默认文案</span>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer">
|
|
|
+ <el-button @click="dialogVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="handleSave" :loading="saving">保存</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import {
|
|
|
+ getNotificationTemplateList,
|
|
|
+ saveNotificationTemplate,
|
|
|
+ deleteNotificationTemplate
|
|
|
+} from '@/api/notificationTemplate'
|
|
|
+
|
|
|
+const CHANNEL_MAP = {
|
|
|
+ in_app: { label: '小程序内', type: 'primary' },
|
|
|
+ sms: { label: '短信', type: 'warning' },
|
|
|
+ wechat: { label: '微信', type: 'success' },
|
|
|
+ phone: { label: '电话', type: 'danger' }
|
|
|
+}
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'NotificationTemplateManage',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ list: [],
|
|
|
+ loading: false,
|
|
|
+ saving: false,
|
|
|
+ dialogVisible: false,
|
|
|
+ form: {
|
|
|
+ id: null,
|
|
|
+ type: '',
|
|
|
+ title: '',
|
|
|
+ content: '',
|
|
|
+ channels: 'in_app',
|
|
|
+ channelList: ['in_app'],
|
|
|
+ status: 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.loadData()
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async loadData() {
|
|
|
+ this.loading = true
|
|
|
+ try {
|
|
|
+ const res = await getNotificationTemplateList()
|
|
|
+ if (res.code === 0 || res.code === 200) {
|
|
|
+ this.list = res.data || []
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.message || '加载失败')
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ this.loading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ channelLabels(channels) {
|
|
|
+ if (!channels) return []
|
|
|
+ return channels.split(',').filter(c => CHANNEL_MAP[c]).map(c => CHANNEL_MAP[c])
|
|
|
+ },
|
|
|
+ handleAdd() {
|
|
|
+ this.form = {
|
|
|
+ id: null,
|
|
|
+ type: '',
|
|
|
+ title: '',
|
|
|
+ content: '',
|
|
|
+ channels: 'in_app',
|
|
|
+ channelList: ['in_app'],
|
|
|
+ status: 1
|
|
|
+ }
|
|
|
+ this.dialogVisible = true
|
|
|
+ },
|
|
|
+ handleEdit(row) {
|
|
|
+ this.form = {
|
|
|
+ id: row.id,
|
|
|
+ type: row.type,
|
|
|
+ title: row.title,
|
|
|
+ content: row.content,
|
|
|
+ channels: row.channels || 'in_app',
|
|
|
+ channelList: (row.channels || 'in_app').split(',').filter(Boolean),
|
|
|
+ status: row.status === 0 ? 0 : 1
|
|
|
+ }
|
|
|
+ this.dialogVisible = true
|
|
|
+ },
|
|
|
+ async handleSave() {
|
|
|
+ if (!this.form.type || !this.form.type.trim()) {
|
|
|
+ this.$message.warning('请填写类型')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!this.form.title || !this.form.title.trim()) {
|
|
|
+ this.$message.warning('请填写标题')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!this.form.content || !this.form.content.trim()) {
|
|
|
+ this.$message.warning('请填写内容模板')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.saving = true
|
|
|
+ try {
|
|
|
+ const data = {
|
|
|
+ ...this.form,
|
|
|
+ channels: (this.form.channelList || []).join(',') || 'in_app'
|
|
|
+ }
|
|
|
+ const res = await saveNotificationTemplate(data)
|
|
|
+ if (res.code === 0 || res.code === 200) {
|
|
|
+ this.$message.success('保存成功')
|
|
|
+ this.dialogVisible = false
|
|
|
+ this.loadData()
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.message || '保存失败')
|
|
|
+ }
|
|
|
+ } finally {
|
|
|
+ this.saving = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ handleDelete(row) {
|
|
|
+ this.$confirm(`确定删除模板「${row.type}」吗?`, '提示', { type: 'warning' }).then(async () => {
|
|
|
+ const res = await deleteNotificationTemplate({ id: row.id })
|
|
|
+ if (res.code === 0 || res.code === 200) {
|
|
|
+ this.$message.success('删除成功')
|
|
|
+ this.loadData()
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.message || '删除失败')
|
|
|
+ }
|
|
|
+ }).catch(() => {})
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.notification-template-manage {
|
|
|
+ padding: 16px;
|
|
|
+}
|
|
|
+</style>
|