2023-02-11 00:44:00 +08:00
|
|
|
<template>
|
2023-04-09 18:14:58 +08:00
|
|
|
<doc-alert title="自动回复" url="https://doc.iocoder.cn/mp/auto-reply/" />
|
2023-04-09 11:59:15 +08:00
|
|
|
|
2023-04-09 18:14:58 +08:00
|
|
|
<!-- 搜索工作栏 -->
|
|
|
|
<ContentWrap>
|
2023-04-12 13:29:24 +08:00
|
|
|
<el-form class="-mb-15px" :model="queryParams" :inline="true" label-width="68px">
|
|
|
|
<el-form-item label="公众号" prop="accountId">
|
2023-04-14 15:22:23 +08:00
|
|
|
<WxAccountSelect @change="onAccountChanged" />
|
2023-04-12 13:29:24 +08:00
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
2023-04-09 18:14:58 +08:00
|
|
|
</ContentWrap>
|
2023-04-09 11:59:15 +08:00
|
|
|
|
2023-04-09 18:14:58 +08:00
|
|
|
<!-- tab 切换 -->
|
|
|
|
<ContentWrap>
|
2023-04-18 11:19:13 +08:00
|
|
|
<el-tabs v-model="msgType" @tab-change="onTabChange">
|
2023-04-09 18:14:58 +08:00
|
|
|
<!-- 操作工具栏 -->
|
|
|
|
<el-row :gutter="10" class="mb8">
|
|
|
|
<el-col :span="1.5">
|
|
|
|
<el-button
|
|
|
|
type="primary"
|
|
|
|
plain
|
2023-04-18 11:19:13 +08:00
|
|
|
@click="onCreate"
|
2023-04-09 18:14:58 +08:00
|
|
|
v-hasPermi="['mp:auto-reply:create']"
|
2023-04-12 13:29:24 +08:00
|
|
|
v-if="msgType !== MsgType.Follow || list.length <= 0"
|
2023-04-09 18:14:58 +08:00
|
|
|
>
|
|
|
|
<Icon icon="ep:plus" />新增
|
|
|
|
</el-button>
|
|
|
|
</el-col>
|
|
|
|
</el-row>
|
|
|
|
<!-- tab 项 -->
|
2023-04-12 13:29:24 +08:00
|
|
|
<el-tab-pane :name="MsgType.Follow">
|
2023-04-09 18:14:58 +08:00
|
|
|
<template #label>
|
2023-04-18 11:19:13 +08:00
|
|
|
<el-row align="middle"><Icon icon="ep:star" class="mr-2px" /> 关注时回复</el-row>
|
2023-04-09 18:14:58 +08:00
|
|
|
</template>
|
|
|
|
</el-tab-pane>
|
2023-04-12 13:29:24 +08:00
|
|
|
<el-tab-pane :name="MsgType.Message">
|
2023-04-09 18:14:58 +08:00
|
|
|
<template #label>
|
2023-04-18 11:19:13 +08:00
|
|
|
<el-row align="middle"><Icon icon="ep:chat-line-round" class="mr-2px" /> 消息回复</el-row>
|
2023-04-09 18:14:58 +08:00
|
|
|
</template>
|
|
|
|
</el-tab-pane>
|
2023-04-12 13:29:24 +08:00
|
|
|
<el-tab-pane :name="MsgType.Keyword">
|
2023-04-09 18:14:58 +08:00
|
|
|
<template #label>
|
2023-04-18 11:19:13 +08:00
|
|
|
<el-row align="middle"><Icon icon="fa:newspaper-o" class="mr-2px" /> 关键词回复</el-row>
|
2023-04-09 18:14:58 +08:00
|
|
|
</template>
|
|
|
|
</el-tab-pane>
|
|
|
|
</el-tabs>
|
2023-04-09 13:41:14 +08:00
|
|
|
<!-- 列表 -->
|
2023-04-18 11:19:13 +08:00
|
|
|
<ReplyTable
|
|
|
|
:loading="loading"
|
|
|
|
:list="list"
|
|
|
|
:msg-type="msgType"
|
2023-04-19 19:07:45 +08:00
|
|
|
@on-update="onUpdate"
|
|
|
|
@on-delete="onDelete"
|
2023-04-18 11:19:13 +08:00
|
|
|
/>
|
2023-04-09 11:59:15 +08:00
|
|
|
|
2023-04-09 18:14:58 +08:00
|
|
|
<!-- 添加或修改自动回复的对话框 -->
|
2023-04-19 19:07:45 +08:00
|
|
|
<!-- TODO @Dhb52 -->
|
2023-04-18 11:19:13 +08:00
|
|
|
<el-dialog :title="dialogTitle" v-model="showFormDialog" width="800px" destroy-on-close>
|
2023-04-12 13:29:24 +08:00
|
|
|
<el-form ref="formRef" :model="replyForm" :rules="rules" label-width="80px">
|
|
|
|
<el-form-item label="消息类型" prop="requestMessageType" v-if="msgType === MsgType.Message">
|
|
|
|
<el-select v-model="replyForm.requestMessageType" placeholder="请选择">
|
2023-04-09 18:14:58 +08:00
|
|
|
<template v-for="dict in getDictOptions(DICT_TYPE.MP_MESSAGE_TYPE)" :key="dict.value">
|
2023-04-09 11:59:15 +08:00
|
|
|
<el-option
|
2023-04-12 13:29:24 +08:00
|
|
|
v-if="RequestMessageTypes.includes(dict.value)"
|
2023-04-09 11:59:15 +08:00
|
|
|
:label="dict.label"
|
2023-04-09 18:14:58 +08:00
|
|
|
:value="dict.value"
|
2023-04-09 11:59:15 +08:00
|
|
|
/>
|
2023-04-09 18:14:58 +08:00
|
|
|
</template>
|
|
|
|
</el-select>
|
|
|
|
</el-form-item>
|
2023-04-12 13:29:24 +08:00
|
|
|
<el-form-item label="匹配类型" prop="requestMatch" v-if="msgType === MsgType.Keyword">
|
|
|
|
<el-select v-model="replyForm.requestMatch" placeholder="请选择匹配类型" clearable>
|
2023-04-09 18:14:58 +08:00
|
|
|
<el-option
|
2023-04-19 19:07:45 +08:00
|
|
|
v-for="dict in getIntDictOptions(DICT_TYPE.MP_AUTO_REPLY_REQUEST_MATCH)"
|
2023-04-09 18:14:58 +08:00
|
|
|
:key="dict.value"
|
|
|
|
:label="dict.label"
|
|
|
|
:value="dict.value"
|
|
|
|
/>
|
|
|
|
</el-select>
|
|
|
|
</el-form-item>
|
2023-04-12 13:29:24 +08:00
|
|
|
<el-form-item label="关键词" prop="requestKeyword" v-if="msgType === MsgType.Keyword">
|
|
|
|
<el-input v-model="replyForm.requestKeyword" placeholder="请输入内容" clearable />
|
2023-04-09 18:14:58 +08:00
|
|
|
</el-form-item>
|
|
|
|
<el-form-item label="回复消息">
|
2023-04-21 20:22:11 +08:00
|
|
|
<WxReplySelect v-model="reply" />
|
2023-04-09 18:14:58 +08:00
|
|
|
</el-form-item>
|
|
|
|
</el-form>
|
|
|
|
<template #footer>
|
2023-04-09 18:49:54 +08:00
|
|
|
<el-button @click="cancel">取 消</el-button>
|
2023-04-18 11:19:13 +08:00
|
|
|
<el-button type="primary" @click="onSubmit">确 定</el-button>
|
2023-04-09 18:14:58 +08:00
|
|
|
</template>
|
|
|
|
</el-dialog>
|
|
|
|
</ContentWrap>
|
2023-02-11 00:44:00 +08:00
|
|
|
</template>
|
2023-04-12 13:29:24 +08:00
|
|
|
<script setup lang="ts" name="MpAutoReply">
|
2023-04-21 20:22:11 +08:00
|
|
|
import WxReplySelect, { type Reply, ReplyType } from '@/views/mp/components/wx-reply'
|
|
|
|
import WxAccountSelect from '@/views/mp/components/wx-account-select'
|
2023-04-10 01:07:04 +08:00
|
|
|
import * as MpAutoReplyApi from '@/api/mp/autoReply'
|
2023-04-19 19:07:45 +08:00
|
|
|
import { DICT_TYPE, getDictOptions, getIntDictOptions } from '@/utils/dict'
|
2023-04-09 11:59:15 +08:00
|
|
|
import { ContentWrap } from '@/components/ContentWrap'
|
2023-04-21 20:22:11 +08:00
|
|
|
import type { FormInstance, TabPaneName } from 'element-plus'
|
2023-04-18 11:19:13 +08:00
|
|
|
import ReplyTable from './components/ReplyTable.vue'
|
2023-04-21 20:22:11 +08:00
|
|
|
import { MsgType } from './components/types'
|
2023-04-19 19:07:45 +08:00
|
|
|
const message = useMessage() // 消息
|
2023-04-09 11:59:15 +08:00
|
|
|
|
2023-04-22 23:43:35 +08:00
|
|
|
const accountId = ref(-1) // 公众号ID
|
2023-04-19 19:07:45 +08:00
|
|
|
const msgType = ref<MsgType>(MsgType.Keyword) // 消息类型
|
|
|
|
const RequestMessageTypes = ['text', 'image', 'voice', 'video', 'shortvideo', 'location', 'link'] // 允许选择的请求消息类型
|
|
|
|
const loading = ref(true) // 遮罩层
|
|
|
|
const total = ref(0) // 总条数
|
|
|
|
const list = ref<any[]>([]) // 自动回复列表
|
2023-04-21 20:22:11 +08:00
|
|
|
const formRef = ref<FormInstance | null>(null) // 表单 ref
|
2023-04-09 11:59:15 +08:00
|
|
|
// 查询参数
|
2023-04-22 23:43:35 +08:00
|
|
|
const queryParams = reactive({
|
2023-04-09 11:59:15 +08:00
|
|
|
pageNo: 1,
|
|
|
|
pageSize: 10,
|
2023-04-22 23:43:35 +08:00
|
|
|
accountId: accountId
|
2023-04-09 11:59:15 +08:00
|
|
|
})
|
|
|
|
|
2023-04-19 19:07:45 +08:00
|
|
|
const dialogTitle = ref('') // 弹出层标题
|
|
|
|
const showFormDialog = ref(false) // 是否显示弹出层
|
2023-04-21 20:22:11 +08:00
|
|
|
const replyForm = ref<any>({}) // 表单参数
|
2023-04-09 11:59:15 +08:00
|
|
|
// 回复消息
|
2023-04-21 20:22:11 +08:00
|
|
|
const reply = ref<Reply>({
|
|
|
|
type: ReplyType.Text,
|
2023-04-22 23:43:35 +08:00
|
|
|
accountId: -1
|
2023-04-09 11:59:15 +08:00
|
|
|
})
|
|
|
|
// 表单校验
|
|
|
|
const rules = {
|
|
|
|
requestKeyword: [{ required: true, message: '请求的关键字不能为空', trigger: 'blur' }],
|
|
|
|
requestMatch: [{ required: true, message: '请求的关键字的匹配不能为空', trigger: 'blur' }]
|
|
|
|
}
|
|
|
|
|
2023-04-18 11:19:13 +08:00
|
|
|
/** 侦听账号变化 */
|
2023-04-21 20:22:11 +08:00
|
|
|
const onAccountChanged = (id: number) => {
|
2023-04-22 23:43:35 +08:00
|
|
|
accountId.value = id
|
2023-04-21 20:22:11 +08:00
|
|
|
reply.value.accountId = id
|
2023-04-22 23:43:35 +08:00
|
|
|
queryParams.pageNo = 1
|
2023-04-10 01:07:04 +08:00
|
|
|
getList()
|
|
|
|
}
|
2023-04-09 11:59:15 +08:00
|
|
|
|
|
|
|
/** 查询列表 */
|
|
|
|
const getList = async () => {
|
2023-04-18 11:19:13 +08:00
|
|
|
loading.value = true
|
2023-04-10 01:07:04 +08:00
|
|
|
try {
|
|
|
|
const data = await MpAutoReplyApi.getAutoReplyPage({
|
|
|
|
...queryParams,
|
2023-04-12 13:29:24 +08:00
|
|
|
type: msgType.value
|
2023-04-10 01:07:04 +08:00
|
|
|
})
|
2023-04-09 11:59:15 +08:00
|
|
|
list.value = data.list
|
|
|
|
total.value = data.total
|
2023-04-10 01:07:04 +08:00
|
|
|
} finally {
|
2023-04-09 11:59:15 +08:00
|
|
|
loading.value = false
|
2023-04-10 01:07:04 +08:00
|
|
|
}
|
2023-04-09 11:59:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** 搜索按钮操作 */
|
|
|
|
const handleQuery = () => {
|
|
|
|
queryParams.pageNo = 1
|
|
|
|
getList()
|
|
|
|
}
|
|
|
|
|
2023-04-18 11:19:13 +08:00
|
|
|
const onTabChange = (tabName: TabPaneName) => {
|
2023-04-12 13:29:24 +08:00
|
|
|
msgType.value = tabName as MsgType
|
2023-04-09 11:59:15 +08:00
|
|
|
handleQuery()
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 新增按钮操作 */
|
2023-04-18 11:19:13 +08:00
|
|
|
const onCreate = () => {
|
2023-04-09 11:59:15 +08:00
|
|
|
reset()
|
|
|
|
// 打开表单,并设置初始化
|
2023-04-21 20:22:11 +08:00
|
|
|
reply.value = {
|
|
|
|
type: ReplyType.Text,
|
2023-04-09 11:59:15 +08:00
|
|
|
accountId: queryParams.accountId
|
|
|
|
}
|
2023-04-12 13:29:24 +08:00
|
|
|
|
2023-04-18 11:19:13 +08:00
|
|
|
dialogTitle.value = '新增自动回复'
|
|
|
|
showFormDialog.value = true
|
2023-04-09 11:59:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** 修改按钮操作 */
|
2023-04-18 11:19:13 +08:00
|
|
|
const onUpdate = async (id: number) => {
|
2023-04-09 11:59:15 +08:00
|
|
|
reset()
|
|
|
|
|
2023-04-18 11:19:13 +08:00
|
|
|
const data = await MpAutoReplyApi.getAutoReply(id)
|
2023-04-12 13:29:24 +08:00
|
|
|
// 设置属性
|
|
|
|
replyForm.value = { ...data }
|
|
|
|
delete replyForm.value['responseMessageType']
|
|
|
|
delete replyForm.value['responseContent']
|
|
|
|
delete replyForm.value['responseMediaId']
|
|
|
|
delete replyForm.value['responseMediaUrl']
|
|
|
|
delete replyForm.value['responseDescription']
|
|
|
|
delete replyForm.value['responseArticles']
|
2023-04-21 20:22:11 +08:00
|
|
|
reply.value = {
|
2023-04-12 13:29:24 +08:00
|
|
|
type: data.responseMessageType,
|
|
|
|
accountId: queryParams.accountId,
|
|
|
|
content: data.responseContent,
|
|
|
|
mediaId: data.responseMediaId,
|
|
|
|
url: data.responseMediaUrl,
|
|
|
|
title: data.responseTitle,
|
|
|
|
description: data.responseDescription,
|
|
|
|
thumbMediaId: data.responseThumbMediaId,
|
|
|
|
thumbMediaUrl: data.responseThumbMediaUrl,
|
|
|
|
articles: data.responseArticles,
|
|
|
|
musicUrl: data.responseMusicUrl,
|
|
|
|
hqMusicUrl: data.responseHqMusicUrl
|
|
|
|
}
|
2023-04-09 11:59:15 +08:00
|
|
|
|
2023-04-12 13:29:24 +08:00
|
|
|
// 打开表单
|
2023-04-18 11:19:13 +08:00
|
|
|
dialogTitle.value = '修改自动回复'
|
|
|
|
showFormDialog.value = true
|
2023-04-09 11:59:15 +08:00
|
|
|
}
|
|
|
|
|
2023-04-18 11:19:13 +08:00
|
|
|
/** 删除按钮操作 */
|
|
|
|
const onDelete = async (id: number) => {
|
|
|
|
await message.confirm('是否确认删除此数据?')
|
|
|
|
await MpAutoReplyApi.deleteAutoReply(id)
|
|
|
|
await getList()
|
|
|
|
message.success('删除成功')
|
|
|
|
}
|
|
|
|
|
|
|
|
const onSubmit = async () => {
|
2023-04-12 13:29:24 +08:00
|
|
|
const valid = await formRef.value?.validate()
|
|
|
|
if (!valid) return
|
2023-04-09 11:59:15 +08:00
|
|
|
|
2023-04-12 13:29:24 +08:00
|
|
|
// 处理回复消息
|
|
|
|
const submitForm: any = { ...replyForm.value }
|
2023-04-21 20:22:11 +08:00
|
|
|
submitForm.responseMessageType = reply.value.type
|
|
|
|
submitForm.responseContent = reply.value.content
|
|
|
|
submitForm.responseMediaId = reply.value.mediaId
|
|
|
|
submitForm.responseMediaUrl = reply.value.url
|
|
|
|
submitForm.responseTitle = reply.value.title
|
|
|
|
submitForm.responseDescription = reply.value.description
|
|
|
|
submitForm.responseThumbMediaId = reply.value.thumbMediaId
|
|
|
|
submitForm.responseThumbMediaUrl = reply.value.thumbMediaUrl
|
|
|
|
submitForm.responseArticles = reply.value.articles
|
|
|
|
submitForm.responseMusicUrl = reply.value.musicUrl
|
|
|
|
submitForm.responseHqMusicUrl = reply.value.hqMusicUrl
|
2023-04-09 11:59:15 +08:00
|
|
|
|
2023-04-12 13:29:24 +08:00
|
|
|
if (replyForm.value.id !== undefined) {
|
|
|
|
await MpAutoReplyApi.updateAutoReply(submitForm)
|
|
|
|
message.success('修改成功')
|
|
|
|
} else {
|
|
|
|
await MpAutoReplyApi.createAutoReply(submitForm)
|
|
|
|
message.success('新增成功')
|
|
|
|
}
|
|
|
|
|
2023-04-18 11:19:13 +08:00
|
|
|
showFormDialog.value = false
|
2023-04-14 15:08:58 +08:00
|
|
|
await getList()
|
2023-04-09 11:59:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 表单重置
|
|
|
|
const reset = () => {
|
2023-04-12 13:29:24 +08:00
|
|
|
replyForm.value = {
|
2023-04-09 11:59:15 +08:00
|
|
|
id: undefined,
|
|
|
|
accountId: queryParams.accountId,
|
2023-04-12 13:29:24 +08:00
|
|
|
type: msgType.value,
|
2023-04-09 11:59:15 +08:00
|
|
|
requestKeyword: undefined,
|
2023-04-12 13:29:24 +08:00
|
|
|
requestMatch: msgType.value === MsgType.Keyword ? 1 : undefined,
|
2023-04-09 11:59:15 +08:00
|
|
|
requestMessageType: undefined
|
|
|
|
}
|
|
|
|
formRef.value?.resetFields()
|
|
|
|
}
|
|
|
|
|
|
|
|
// 取消按钮
|
|
|
|
const cancel = () => {
|
2023-04-18 11:19:13 +08:00
|
|
|
showFormDialog.value = false
|
2023-04-09 11:59:15 +08:00
|
|
|
reset()
|
|
|
|
}
|
|
|
|
</script>
|