|
|
|
@ -1,14 +1,22 @@
|
|
|
|
|
<template>
|
|
|
|
|
<el-dialog :title="!dataForm.id ? '新增' : '修改'" :close-on-click-modal="false" :visible.sync="visible" >
|
|
|
|
|
<!-- el-dialog组件用于弹出对话框,根据dataForm中是否有id来设置标题为“新增”或“修改”,点击模态框背景不关闭对话框,通过visible属性双向绑定控制显示隐藏 -->
|
|
|
|
|
<el-dialog :title="!dataForm.id? '新增' : '修改'" :close-on-click-modal="false" :visible.sync="visible" >
|
|
|
|
|
<!-- el-form组件定义表单,绑定dataForm数据模型,应用dataRule验证规则,设置标签宽度为80px -->
|
|
|
|
|
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" label-width="80px">
|
|
|
|
|
<!-- 规则名称的表单项,对应dataForm中的ruleName属性,设置了必填验证 -->
|
|
|
|
|
<el-form-item label="规则名称" prop="ruleName">
|
|
|
|
|
<!-- el-input组件实现输入框,双向绑定dataForm.ruleName,有占位提示文字 -->
|
|
|
|
|
<el-input v-model="dataForm.ruleName" placeholder="规则名称"></el-input>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<!-- 匹配词的表单项,使用自定义的tags-editor组件,双向绑定dataForm.matchValue,用于输入或编辑匹配词(可能是多个,类似标签形式) -->
|
|
|
|
|
<el-form-item label="匹配词" prop="matchValue">
|
|
|
|
|
<tags-editor v-model="dataForm.matchValue"></tags-editor>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<!-- 第一行布局,使用el-row包裹 -->
|
|
|
|
|
<el-row>
|
|
|
|
|
<!-- 占12列,用于放置作用范围相关的表单元素 -->
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<!-- 作用范围的表单项,对应dataForm中的appid属性,通过下拉选择框选择,有全部公众号和当前公众号两个选项 -->
|
|
|
|
|
<el-form-item label="作用范围" prop="appid">
|
|
|
|
|
<el-select v-model="dataForm.appid" placeholder="作用范围">
|
|
|
|
|
<el-option label="全部公众号" value=""></el-option>
|
|
|
|
@ -16,71 +24,91 @@
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<!-- 同样占12列,用于放置精确匹配相关的表单元素,使用el-switch组件实现开关切换功能,双向绑定dataForm.exactMatch -->
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-form-item label="精确匹配" prop="exactMatch">
|
|
|
|
|
<el-switch v-model="dataForm.exactMatch" :active-value="true" :inactive-value="false"></el-switch>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<!-- 第二行布局 -->
|
|
|
|
|
<el-row>
|
|
|
|
|
<!-- 占12列,用于放置回复类型相关的表单元素 -->
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<!-- 回复类型的表单项,对应dataForm中的replyType属性,通过下拉选择框选择,选项通过循环KefuMsgType生成,选择改变时触发onReplyTypeChange方法 -->
|
|
|
|
|
<el-form-item label="回复类型" prop="replyType">
|
|
|
|
|
<el-select v-model="dataForm.replyType" @change="onReplyTypeChange">
|
|
|
|
|
<el-option v-for="(name,key) in KefuMsgType" :key="key" :value="key" :label="name"></el-option>
|
|
|
|
|
</el-select>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<!-- 占12列,用于放置是否启用相关的表单元素,使用el-switch组件实现开关切换功能,双向绑定dataForm.status -->
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-form-item label="是否启用" prop="status">
|
|
|
|
|
<el-switch v-model="dataForm.status" :active-value="true" :inactive-value="false"></el-switch>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<!-- 第三行布局 -->
|
|
|
|
|
<el-row>
|
|
|
|
|
<!-- 占12列,用于放置生效时间相关的表单元素,使用el-time-picker组件实现时间选择功能,绑定dataForm.effectTimeStart,设置时间格式 -->
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-form-item label="生效时间" prop="effectTimeStart">
|
|
|
|
|
<el-time-picker v-model="dataForm.effectTimeStart" value-format="HH:mm:ss"></el-time-picker>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
<!-- 占12列,用于放置失效时间相关的表单元素,使用el-time-picker组件实现时间选择功能,绑定dataForm.effectTimeEnd,设置时间格式 -->
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-form-item label="失效时间" prop="effectTimeEnd">
|
|
|
|
|
<el-time-picker v-model="dataForm.effectTimeEnd" value-format="HH:mm:ss"></el-time-picker>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
<!-- 回复内容的表单项,对应dataForm中的replyContent属性,使用el-input组件实现文本域输入框,双向绑定dataForm.replyContent,有行数设置和占位提示文字 -->
|
|
|
|
|
<el-form-item label="回复内容" prop="replyContent">
|
|
|
|
|
<el-input v-model="dataForm.replyContent" type="textarea" :rows="5" placeholder="文本、图文ID、media_id、json配置"></el-input>
|
|
|
|
|
<!-- 当回复类型为文本时显示插入链接按钮,点击调用addLink方法在回复内容中添加链接 -->
|
|
|
|
|
<el-button type="text" v-show="'text'==dataForm.replyType" @click="addLink">插入链接</el-button>
|
|
|
|
|
<!-- 根据assetsType的值决定是否显示按钮,点击打开素材选择器(通过控制assetsSelectorVisible属性),按钮文字根据回复类型有所不同 -->
|
|
|
|
|
<el-button type="text" v-show="assetsType" @click="assetsSelectorVisible=true">
|
|
|
|
|
从素材库中选择<span v-if="'miniprogrampage'==dataForm.replyType || 'music'==dataForm.replyType">缩略图</span>
|
|
|
|
|
</el-button>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
<!-- 备注说明的表单项,对应dataForm中的desc属性,使用el-input组件实现输入框,双向绑定dataForm.desc,有占位提示文字 -->
|
|
|
|
|
<el-form-item label="备注说明" prop="desc">
|
|
|
|
|
<el-input v-model="dataForm.desc" placeholder="备注说明"></el-input>
|
|
|
|
|
</el-form-item>
|
|
|
|
|
</el-form>
|
|
|
|
|
<!-- 对话框底部的按钮区域,通过插槽定义 -->
|
|
|
|
|
<span slot="footer" class="dialog-footer">
|
|
|
|
|
<!-- 取消按钮,点击时设置visible为false关闭对话框 -->
|
|
|
|
|
<el-button @click="visible = false">取消</el-button>
|
|
|
|
|
<!-- 确定按钮,类型为主要按钮,点击时调用dataFormSubmit方法进行表单提交 -->
|
|
|
|
|
<el-button type="primary" @click="dataFormSubmit()">确定</el-button>
|
|
|
|
|
</span>
|
|
|
|
|
<!-- 素材选择器组件,根据条件控制显示,通过属性和事件与当前组件进行交互,用于选择素材相关操作 -->
|
|
|
|
|
<assets-selector v-if="assetsSelectorVisible && assetsType" :visible="assetsSelectorVisible" :selectType="assetsType" @selected="onAssetsSelect" @onClose="assetsSelectorVisible=false"></assets-selector>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
// 引入Vuex的mapState辅助函数,用于将Vuex中的状态映射到组件的计算属性中
|
|
|
|
|
import { mapState } from 'vuex'
|
|
|
|
|
export default {
|
|
|
|
|
components: {
|
|
|
|
|
// 异步加载tags-editor组件,用于编辑匹配词相关功能
|
|
|
|
|
tagsEditor: () => import('@/components/tags-editor'),
|
|
|
|
|
AssetsSelector:()=>import('./assets/assets-selector')
|
|
|
|
|
// 异步加载AssetsSelector组件,用于选择素材相关功能
|
|
|
|
|
AssetsSelector: () => import('./assets/assets-selector')
|
|
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
visible: false,
|
|
|
|
|
assetsSelectorVisible:false,
|
|
|
|
|
assetsSelectorVisible: false,
|
|
|
|
|
dataForm: {
|
|
|
|
|
// 规则ID,初始化为0
|
|
|
|
|
ruleId: 0,
|
|
|
|
|
appid:'',
|
|
|
|
|
appid: '',
|
|
|
|
|
ruleName: "",
|
|
|
|
|
exactMatch: false,
|
|
|
|
|
matchValue: "",
|
|
|
|
@ -92,24 +120,31 @@ export default {
|
|
|
|
|
effectTimeEnd: "23:59:59"
|
|
|
|
|
},
|
|
|
|
|
dataRule: {
|
|
|
|
|
// 规则名称的验证规则,必填,触发验证的时机是失去焦点(blur)
|
|
|
|
|
ruleName: [
|
|
|
|
|
{ required: true, message: "规则名称不能为空", trigger: "blur" }
|
|
|
|
|
],
|
|
|
|
|
// 匹配词的验证规则,必填,触发验证的时机是失去焦点
|
|
|
|
|
matchValue: [
|
|
|
|
|
{ required: true, message: "匹配的关键词、事件等不能为空", trigger: "blur" }
|
|
|
|
|
],
|
|
|
|
|
// 回复类型的验证规则,必填,触发验证的时机是失去焦点
|
|
|
|
|
replyType: [
|
|
|
|
|
{ required: true, message: "回复类型(1:文本2:图文3媒体)不能为空", trigger: "blur" }
|
|
|
|
|
],
|
|
|
|
|
// 回复内容的验证规则,必填,触发验证的时机是失去焦点
|
|
|
|
|
replyContent: [
|
|
|
|
|
{ required: true, message: "回复内容不能为空", trigger: "blur" }
|
|
|
|
|
],
|
|
|
|
|
// 是否启用的验证规则,必填,触发验证的时机是失去焦点
|
|
|
|
|
status: [
|
|
|
|
|
{ required: true, message: "是否有效不能为空", trigger: "blur" }
|
|
|
|
|
],
|
|
|
|
|
// 生效起始时间的验证规则,必填,触发验证的时机是失去焦点
|
|
|
|
|
effectTimeStart: [
|
|
|
|
|
{ required: true, message: "生效起始时间不能为空", trigger: "blur" }
|
|
|
|
|
],
|
|
|
|
|
// 生效结束时间的验证规则,必填,触发验证的时机是失去焦点
|
|
|
|
|
effectTimeEnd: [
|
|
|
|
|
{ required: true, message: "生效结束时间不能为空", trigger: "blur" }
|
|
|
|
|
]
|
|
|
|
@ -117,49 +152,60 @@ export default {
|
|
|
|
|
};
|
|
|
|
|
},
|
|
|
|
|
computed: mapState({
|
|
|
|
|
KefuMsgType: state=>state.message.KefuMsgType,
|
|
|
|
|
selectedAppid:state=>state.wxAccount.selectedAppid,
|
|
|
|
|
assetsType(){
|
|
|
|
|
const config={//消息类型与选择素材类型对应关系
|
|
|
|
|
'image':'image',
|
|
|
|
|
'voice':'voice',
|
|
|
|
|
'video':'video',
|
|
|
|
|
'mpnews':'news',
|
|
|
|
|
'miniprogrampage':'image',//小程序需选择卡片图
|
|
|
|
|
'music':'image'
|
|
|
|
|
}
|
|
|
|
|
return config[this.dataForm.replyType] || ''
|
|
|
|
|
// 从Vuex的state中获取message模块下的KefuMsgType状态,映射到组件的计算属性中,用于回复类型下拉框的选项数据
|
|
|
|
|
KefuMsgType: state => state.message.KefuMsgType,
|
|
|
|
|
// 从Vuex的state中获取wxAccount模块下的selectedAppid状态,映射到组件的计算属性中,用于作用范围下拉框中当前公众号选项的值
|
|
|
|
|
selectedAppid: state => state.wxAccount.selectedAppid,
|
|
|
|
|
assetsType() {
|
|
|
|
|
const config = {
|
|
|
|
|
// 定义消息类型与选择素材类型的对应关系,用于根据回复类型确定在素材库中选择的素材类型
|
|
|
|
|
'image': 'image',
|
|
|
|
|
'voice': 'voice',
|
|
|
|
|
'video': 'video',
|
|
|
|
|
'mpnews': 'news',
|
|
|
|
|
'miniprogrampage': 'image', // 小程序需选择卡片图
|
|
|
|
|
'music': 'image'
|
|
|
|
|
};
|
|
|
|
|
return config[this.dataForm.replyType] || '';
|
|
|
|
|
}
|
|
|
|
|
}),
|
|
|
|
|
methods: {
|
|
|
|
|
init(id) {
|
|
|
|
|
// 初始化时设置dataForm的ruleId属性,传入的id为空则设置为0
|
|
|
|
|
this.dataForm.ruleId = id || 0;
|
|
|
|
|
// 设置对话框显示状态为true,即打开对话框
|
|
|
|
|
this.visible = true;
|
|
|
|
|
this.$nextTick(() => {
|
|
|
|
|
// 表单DOM更新后,重置表单所有字段的值
|
|
|
|
|
this.$refs["dataForm"].resetFields();
|
|
|
|
|
if (this.dataForm.ruleId) {
|
|
|
|
|
// 如果ruleId有值,表示是修改操作,发起HTTP请求获取规则详情信息
|
|
|
|
|
this.$http({
|
|
|
|
|
url: this.$http.adornUrl( `/manage/msgReplyRule/info/${this.dataForm.ruleId}` ),
|
|
|
|
|
url: this.$http.adornUrl(`/manage/msgReplyRule/info/${this.dataForm.ruleId}`),
|
|
|
|
|
method: "get",
|
|
|
|
|
params: this.$http.adornParams()
|
|
|
|
|
}).then(({ data }) => {
|
|
|
|
|
if (data && data.code === 200) {
|
|
|
|
|
// 如果请求成功,将返回的规则数据赋值给dataForm
|
|
|
|
|
this.dataForm = data.msgReplyRule;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
// 表单提交
|
|
|
|
|
// 表单提交方法
|
|
|
|
|
dataFormSubmit() {
|
|
|
|
|
// 对表单进行验证,验证结果通过回调函数的参数valid返回
|
|
|
|
|
this.$refs["dataForm"].validate(valid => {
|
|
|
|
|
if (valid) {
|
|
|
|
|
// 如果表单验证通过,发起HTTP请求保存或更新规则数据(根据ruleId是否有值判断是新增还是更新操作)
|
|
|
|
|
this.$http({
|
|
|
|
|
url: this.$http.adornUrl(`/manage/msgReplyRule/${!this.dataForm.ruleId ? "save" : "update"}`),
|
|
|
|
|
url: this.$http.adornUrl(`/manage/msgReplyRule/${!this.dataForm.ruleId? "save" : "update"}`),
|
|
|
|
|
method: "post",
|
|
|
|
|
data: this.$http.adornData(this.dataForm)
|
|
|
|
|
}).then(({ data }) => {
|
|
|
|
|
if (data && data.code === 200) {
|
|
|
|
|
// 如果操作成功,弹出成功提示信息,提示框关闭后设置对话框隐藏,并通过$emit触发父组件的refreshDataList事件
|
|
|
|
|
this.$message({
|
|
|
|
|
message: "操作成功",
|
|
|
|
|
type: "success",
|
|
|
|
@ -170,6 +216,7 @@ export default {
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
// 如果操作失败,弹出错误提示信息
|
|
|
|
|
this.$message.error(data.msg);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
@ -177,9 +224,11 @@ export default {
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
addLink() {
|
|
|
|
|
// 插入链接的方法,在回复内容中添加一个简单的链接示例文本(实际应用中可能需要更灵活的处理方式来确定链接地址和文字等)
|
|
|
|
|
this.dataForm.replyContent += '<a href="链接地址">链接文字</a>'
|
|
|
|
|
},
|
|
|
|
|
onReplyTypeChange(value) {
|
|
|
|
|
// 根据回复类型改变时的不同值,设置不同的回复内容默认值(以JSON格式字符串表示,方便后续解析和使用)
|
|
|
|
|
if ("miniprogrampage" == value) {
|
|
|
|
|
let demo = { title: "标题", appid: "小程序APPID", pagepath: "页面地址", thumb_media_id: "缩略图media_id" };
|
|
|
|
|
this.dataForm.replyContent = JSON.stringify(demo, null, 4)
|
|
|
|
@ -190,21 +239,22 @@ export default {
|
|
|
|
|
let demo = { head_content: "开头文字", list: [{ id: "菜单1ID", content: "菜单2内容" }, { id: "菜单2ID", content: "菜单2内容" }, { id: "菜单nID", content: "菜单n内容" }], tail_content: "结尾文字" }
|
|
|
|
|
this.dataForm.replyContent = JSON.stringify(demo, null, 4)
|
|
|
|
|
} else if ("news" == value) {
|
|
|
|
|
let demo={title:"文章标题",description:"文章简介",url:"链接URL",picUrl:"缩略图URL"}
|
|
|
|
|
let demo = { title: "文章标题", description: "文章简介", url: "链接URL", picUrl: "缩略图URL" }
|
|
|
|
|
this.dataForm.replyContent = JSON.stringify(demo, null, 4)
|
|
|
|
|
} else {
|
|
|
|
|
this.dataForm.replyContent = '媒体素材media_id'
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
onAssetsSelect(assetsInfo){
|
|
|
|
|
if(this.dataForm.replyType=='miniprogrampage' || this.dataForm.replyType=='music'){
|
|
|
|
|
let data = JSON.parse(this.dataForm.replyContent)
|
|
|
|
|
if(data && data.thumb_media_id)data.thumb_media_id=assetsInfo.mediaId
|
|
|
|
|
this.dataForm.replyContent = JSON.stringify(data, null, 4)
|
|
|
|
|
}else{
|
|
|
|
|
this.dataForm.replyContent = assetsInfo.mediaId
|
|
|
|
|
onAssetsSelect(assetsInfo) {
|
|
|
|
|
// 素材选择后的处理方法,根据回复类型判断如何更新回复内容,若是小程序页面或音乐类型,更新对应的缩略图media_id,否则直接赋值为所选素材的mediaId
|
|
|
|
|
if (this.dataForm.replyType =='miniprogrampage' || this.dataForm.replyType =='music') {
|
|
|
|
|
let data = JSON.parse(this.dataForm.replyContent);
|
|
|
|
|
if (data && data.thumb_media_id) data.thumb_media_id = assetsInfo.mediaId;
|
|
|
|
|
this.dataForm.replyContent = JSON.stringify(data, null, 4);
|
|
|
|
|
} else {
|
|
|
|
|
this.dataForm.replyContent = assetsInfo.mediaId;
|
|
|
|
|
}
|
|
|
|
|
this.assetsSelectorVisible=false
|
|
|
|
|
this.assetsSelectorVisible = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|