mp:增加【自动回复】的前端实现

This commit is contained in:
YunaiV 2023-01-17 00:01:07 +08:00
parent ab41c96641
commit 1e402d8063
9 changed files with 239 additions and 112 deletions

View File

@ -8,11 +8,13 @@ import cn.iocoder.yudao.module.mp.convert.message.MpAutoReplyConvert;
import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpAutoReplyDO; import cn.iocoder.yudao.module.mp.dal.dataobject.message.MpAutoReplyDO;
import cn.iocoder.yudao.module.mp.service.message.MpAutoReplyService; import cn.iocoder.yudao.module.mp.service.message.MpAutoReplyService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource; import javax.annotation.Resource;
@ -37,4 +39,13 @@ public class MpAutoReplyController {
return success(MpAutoReplyConvert.INSTANCE.convertPage(pageResult)); return success(MpAutoReplyConvert.INSTANCE.convertPage(pageResult));
} }
@GetMapping("/get")
@ApiOperation("获得公众号自动回复")
@ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('mp:auto-reply:query')")
public CommonResult<MpAutoReplyRespVO> getAutoReply(@RequestParam("id") Long id) {
MpAutoReplyDO autoReply = mpAutoReplyService.getAutoReply(id);
return success(MpAutoReplyConvert.INSTANCE.convert(autoReply));
}
} }

View File

@ -30,7 +30,7 @@ public class MpAutoReplyBaseVO {
@ApiModelProperty(value = "请求的关键字", example = "关键字", notes = "当 type 为 MpAutoReplyTypeEnum#KEYWORD 时,必填") @ApiModelProperty(value = "请求的关键字", example = "关键字", notes = "当 type 为 MpAutoReplyTypeEnum#KEYWORD 时,必填")
private String requestKeyword; private String requestKeyword;
@ApiModelProperty(value = "请求的关键字", example = "关键字", notes = "当 type 为 MpAutoReplyTypeEnum#KEYWORD 时,必填") @ApiModelProperty(value = "请求的匹配方式", example = "1", notes = "当 type 为 MpAutoReplyTypeEnum#KEYWORD 时,必填")
private Integer requestMatch; private Integer requestMatch;
@ApiModelProperty(value = "请求的消息类型", example = "text", notes = "当 type 为 MpAutoReplyTypeEnum#MESSAGE 时,必填") @ApiModelProperty(value = "请求的消息类型", example = "text", notes = "当 type 为 MpAutoReplyTypeEnum#MESSAGE 时,必填")

View File

@ -6,6 +6,8 @@ import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString; import lombok.ToString;
import java.util.Date;
@ApiModel("管理后台 - 公众号自动回复 Response VO") @ApiModel("管理后台 - 公众号自动回复 Response VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ -20,4 +22,7 @@ public class MpAutoReplyRespVO extends MpAutoReplyBaseVO {
@ApiModelProperty(value = "微信公众号 appid", required = true, example = "wx1234567890") @ApiModelProperty(value = "微信公众号 appid", required = true, example = "wx1234567890")
private String appId; private String appId;
@ApiModelProperty(value = "创建时间", required = true)
private Date createTime;
} }

View File

@ -27,4 +27,6 @@ public interface MpAutoReplyConvert {
PageResult<MpAutoReplyRespVO> convertPage(PageResult<MpAutoReplyDO> page); PageResult<MpAutoReplyRespVO> convertPage(PageResult<MpAutoReplyDO> page);
MpAutoReplyRespVO convert(MpAutoReplyDO bean);
} }

View File

@ -21,6 +21,14 @@ public interface MpAutoReplyService {
*/ */
PageResult<MpAutoReplyDO> getAutoReplyPage(MpMessagePageReqVO pageVO); PageResult<MpAutoReplyDO> getAutoReplyPage(MpMessagePageReqVO pageVO);
/**
* 获得公众号自动回复
*
* @param id 编号
* @return 自动回复
*/
MpAutoReplyDO getAutoReply(Long id);
/** /**
* 当收到消息时自动回复 * 当收到消息时自动回复
* *

View File

@ -44,6 +44,11 @@ public class MpAutoReplyServiceImpl implements MpAutoReplyService {
return mpAutoReplyMapper.selectPage(pageVO); return mpAutoReplyMapper.selectPage(pageVO);
} }
@Override
public MpAutoReplyDO getAutoReply(Long id) {
return mpAutoReplyMapper.selectById(id);
}
@Override @Override
public WxMpXmlOutMessage replyForMessage(String appId, WxMpXmlMessage wxMessage) { public WxMpXmlOutMessage replyForMessage(String appId, WxMpXmlMessage wxMessage) {
// 第一步匹配自动回复 // 第一步匹配自动回复

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 创建公众号的自动回复
export function createAutoReply(data) {
return request({
url: '/mp/auto-reply/create',
method: 'post',
data: data
})
}
// 更新公众号的自动回复
export function updateAutoReply(data) {
return request({
url: '/mp/auto-reply/update',
method: 'put',
data: data
})
}
// 删除公众号的自动回复
export function deleteAutoReply(id) {
return request({
url: '/mp/auto-reply/delete?id=' + id,
method: 'delete'
})
}
// 获得公众号的自动回复
export function getAutoReply(id) {
return request({
url: '/mp/auto-reply/get?id=' + id,
method: 'get'
})
}
// 获得公众号的自动回复分页
export function getAutoReplyPage(query) {
return request({
url: '/mp/auto-reply/page',
method: 'get',
params: query
})
}

View File

@ -58,6 +58,9 @@ export const DICT_TYPE = {
PAY_REFUND_ORDER_STATUS: 'pay_refund_order_status', // 退款订单状态 PAY_REFUND_ORDER_STATUS: 'pay_refund_order_status', // 退款订单状态
PAY_REFUND_ORDER_TYPE: 'pay_refund_order_type', // 退款订单类别 PAY_REFUND_ORDER_TYPE: 'pay_refund_order_type', // 退款订单类别
// ========== MP 模块 ==========
MP_AUTO_REPLY_REQUEST_MATCH: 'mp_auto_reply_request_match', // 自动回复请求匹配类型
// ========== MALL - PRODUCT 模块 ========== // ========== MALL - PRODUCT 模块 ==========
PRODUCT_SPU_STATUS: 'product_spu_status', // 商品 SPU 状态 PRODUCT_SPU_STATUS: 'product_spu_status', // 商品 SPU 状态

View File

@ -22,6 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
芋道源码 芋道源码
移除 avue 框架使用 element-ui 重写 移除 avue 框架使用 element-ui 重写
重写代码保持和现有项目保持一致
--> -->
<template> <template>
<div class="app-container"> <div class="app-container">
@ -44,10 +45,10 @@ SOFTWARE.
<el-row :gutter="10" class="mb8"> <el-row :gutter="10" class="mb8">
<el-col :span="1.5"> <el-col :span="1.5">
<el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
v-hasPermi="['mp:auto-reply:create']" v-if="list.length <= 0">新增 v-hasPermi="['mp:auto-reply:create']" v-if="type !== '1' || list.length <= 0">新增
</el-button> </el-button>
</el-col> </el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList" />
</el-row> </el-row>
<!-- 列表 --> <!-- 列表 -->
<el-tab-pane name="1"> <el-tab-pane name="1">
@ -97,7 +98,11 @@ SOFTWARE.
<span slot="label"><i class="el-icon-news"></i> 关键词回复</span> <span slot="label"><i class="el-icon-news"></i> 关键词回复</span>
<el-table v-loading="loading" :data="list"> <el-table v-loading="loading" :data="list">
<el-table-column label="关键词" align="center" prop="requestKeyword"/> <el-table-column label="关键词" align="center" prop="requestKeyword"/>
<el-table-column label="匹配类型" align="center" prop="requestMatch"/> <el-table-column label="匹配类型" align="center" prop="requestMatch">
<template v-slot="scope">
<dict-tag :type="DICT_TYPE.MP_AUTO_REPLY_REQUEST_MATCH" :value="scope.row.requestMatch"/>
</template>
</el-table-column>
<el-table-column label="回复消息类型" align="center" prop="responseMessageType"/> <el-table-column label="回复消息类型" align="center" prop="responseMessageType"/>
<el-table-column label="创建时间" align="center" prop="createTime" width="180"> <el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope"> <template slot-scope="scope">
@ -118,39 +123,31 @@ SOFTWARE.
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
<el-dialog :title="handleType === 'add' ? '新增回复消息' : '修改回复消息'" :visible.sync="dialog1Visible" width="50%"> <!-- 添加或修改自动回复的对话框 -->
<el-form label-width="100px"> <el-dialog :title="title" :visible.sync="open" width="800px" append-to-body>
<el-form-item label="请求消息类型" v-if="type == '2'"> <el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-select v-model="objData.reqType" placeholder="请选择"> <el-form-item label="消息类型" prop="requestMessageType" v-if="type === '2'">
<el-option <el-select v-model="form.requestMessageType" placeholder="请选择">
v-for="item in dictData.get('wx_req_type')" <el-option v-for="item in dictData.get('wx_req_type')" :key="item.value" :label="item.label"
:key="item.value" :value="item.value" :disabled="item.disabled" v-if="item.value !== 'event'">
:label="item.label"
:value="item.value"
:disabled="item.disabled"
v-if="item.value !== 'event'">
</el-option> </el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="匹配类型" v-if="type === '3'"> <el-form-item label="匹配类型" prop="requestMatch" v-if="type === '3'">
<el-select v-model="objData.repMate" placeholder="请选择" style="width: 100px"> <el-select v-model="form.requestMatch" placeholder="请选择匹配类型" clearable size="small">
<el-option <el-option v-for="dict in this.getDictDatas(DICT_TYPE.MP_AUTO_REPLY_REQUEST_MATCH)"
v-for="item in dictData.get('wx_rep_mate')" :key="dict.value" :label="dict.label" :value="parseInt(dict.value)"/>
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="关键词" v-if="type === '3'"> <el-form-item label="关键词" prop="requestKeyword" v-if="type === '3'">
<el-input placeholder="请输入内容" v-model="objData.reqKey" clearable> </el-input> <el-input v-model="form.requestKeyword" placeholder="请输入内容" clearable />
</el-form-item> </el-form-item>
<el-form-item label="回复消息"> <el-form-item label="回复消息">
<WxReplySelect :objData="objData" v-if="hackResetWxReplySelect"></WxReplySelect> <wx-reply-select :objData="objData" v-if="hackResetWxReplySelect" />
</el-form-item> </el-form-item>
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="dialog1Visible = false"> </el-button> <el-button @click="cancel"> </el-button>
<el-button type="primary" @click="handleSubmit"> </el-button> <el-button type="primary" @click="handleSubmit"> </el-button>
</span> </span>
</el-dialog> </el-dialog>
@ -158,11 +155,9 @@ SOFTWARE.
</template> </template>
<script> <script>
// import { getPage, getObj, addObj, putObj, delObj } from '@/api/wxmp/wxautoreply'
// import { tableOption1, tableOption2, tableOption3 } from '@/const/crud/wxmp/wxautoreply'
import WxReplySelect from '@/views/mp/components/wx-reply/main.vue' import WxReplySelect from '@/views/mp/components/wx-reply/main.vue'
import { getSimpleAccounts } from "@/api/mp/account"; import { getSimpleAccounts } from "@/api/mp/account";
import { getTagPage } from "@/api/mp/tag"; import { createAutoReply, deleteAutoReply, getAutoReply, getAutoReplyPage, updateAutoReply } from "@/api/mp/autoReply";
export default { export default {
name: 'mpAutoReply', name: 'mpAutoReply',
@ -188,13 +183,24 @@ export default {
accountId: undefined, accountId: undefined,
}, },
dialog1Visible:false, //
objData:{ title: "",
repType : 'text' //
open: false,
//
form: {},
//
objData: {
type : 'text'
}, },
handleType: null, //
rules: {
requestKeyword: [{ required: true, message: "请求的关键字不能为空", trigger: "blur" }],
requestMatch: [{ required: true, message: "请求的关键字的匹配不能为空", trigger: "blur" }],
},
hackResetWxReplySelect: false, // WxReplySelect
dictData: new Map(), dictData: new Map(),
hackResetWxReplySelect: false,
// //
accounts: [] accounts: []
@ -211,14 +217,7 @@ export default {
this.getList(); this.getList();
}) })
// this.getPage(this.page) // TODO
this.dictData.set('wx_rep_mate',[{
value: '1',
label: '全匹配'
},{
value: '2',
label: '半匹配'
}])
this.dictData.set('wx_req_type',[{ this.dictData.set('wx_req_type',[{
value: 'text', value: 'text',
label: '文本' label: '文本'
@ -250,15 +249,18 @@ export default {
getList() { getList() {
// //
if (!this.queryParams.accountId) { if (!this.queryParams.accountId) {
this.$message.error('未选中公众号,无法查询标签') this.$message.error('未选中公众号,无法查询自动回复')
return false return false
} }
this.loading = false this.loading = false
// //
let params = {...this.queryParams} let params = {
...this.queryParams,
type: this.type
}
// //
getTagPage(params).then(response => { getAutoReplyPage(params).then(response => {
this.list = response.data.list this.list = response.data.list
this.total = response.data.total this.total = response.data.total
this.loading = false this.loading = false
@ -278,75 +280,122 @@ export default {
} }
this.handleQuery() this.handleQuery()
}, },
handleClick(tab, event) {
handleAdd(){
this.hackResetWxReplySelect = false//
this.$nextTick(() => {
this.hackResetWxReplySelect = true//
})
this.handleType = 'add'
this.dialog1Visible = true
this.objData = {
repType : 'text'
}
},
handleEdit(row){
this.hackResetWxReplySelect = false//
this.$nextTick(() => {
this.hackResetWxReplySelect = true//
})
this.handleType = 'edit'
this.dialog1Visible = true
this.objData = Object.assign({}, row)
},
handleClick(tab, event){
this.tableData = []
this.page.currentPage = 1
this.type = tab.name this.type = tab.name
this.getPage(this.page) this.handleQuery()
}, },
handleDel: function(row, index) {
var _this = this /** 新增按钮操作 */
this.$confirm('是否确认删除此数据', '提示', { handleAdd(){
confirmButtonText: '确定', this.reset();
cancelButtonText: '取消', this.resetEditor();
type: 'warning' //
}).then(function() { this.open = true
return delObj(row.id) this.title = '新增自动回复';
}).then(data => { this.objData = {
_this.$message({ type : 'text'
showClose: true, }
message: '删除成功',
type: 'success'
})
this.getPage(this.page)
}).catch(function(err) { })
}, },
handleSubmit(row){ /** 修改按钮操作 */
if(this.handleType === 'add'){ handleUpdate(row) {
addObj(Object.assign({ this.reset();
type:this.type this.resetEditor();
}, this.objData)).then(data => { const id = row.id;
this.$message({ getAutoReply(id).then(response => {
showClose: true, //
message: '添加成功', this.form = {...response.data}
type: 'success' this.$delete(this.form, 'responseMessageType');
}) this.$delete(this.form, 'responseContent');
this.getPage(this.page) this.$delete(this.form, 'responseMediaId');
this.dialog1Visible = false this.$delete(this.form, 'responseMediaUrl');
}) this.$delete(this.form, 'responseDescription');
} this.$delete(this.form, 'responseArticles');
if(this.handleType === 'edit'){ this.objData = {
putObj(this.objData).then(data => { type: response.data.responseMessageType,
this.$message({ accountId: this.queryParams.accountId,
showClose: true, content: response.data.responseContent,
message: '修改成功', mediaId: response.data.responseMediaId,
type: 'success' url: response.data.responseMediaUrl,
}) title: response.data.responseTitle,
this.getPage(this.page) description: response.data.responseDescription,
this.dialog1Visible = false thumbMediaId: response.data.responseThumbMediaId,
}) thumbMediaUrl: response.data.responseThumbMediaUrl,
} articles: response.data.responseArticles,
musicUrl: response.data.responseMusicUrl,
hqMusicUrl: response.data.responseHqMusicUrl,
}
//
this.open = true
this.title = '修改自动回复';
})
},
handleSubmit() {
this.$refs["form"].validate(valid => {
if (!valid) {
return;
}
//
const form = {...this.form};
form.responseMessageType = this.objData.type;
form.responseContent = this.objData.content;
form.responseMediaId = this.objData.mediaId;
form.responseMediaUrl = this.objData.url;
form.responseTitle = this.objData.title;
form.responseDescription = this.objData.description;
form.responseThumbMediaId = this.objData.thumbMediaId;
form.responseThumbMediaUrl = this.objData.thumbMediaUrl;
form.responseArticles = this.objData.articles;
form.responseMusicUrl = this.objData.musicUrl;
form.responseHqMusicUrl = this.objData.hqMusicUrl;
if (this.form.id !== undefined) {
updateAutoReply(form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
createAutoReply(form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
});
},
//
reset() {
this.form = {
id: undefined,
accountId: this.queryParams.accountId,
type: this.type,
requestKeyword: undefined,
requestMatch: this.type === '3' ? 1 : undefined,
requestMessageType: undefined,
};
this.resetForm("form");
},
//
cancel() {
this.open = false;
this.reset();
},
// Editor
resetEditor() {
this.hackResetWxReplySelect = false //
this.$nextTick(() => {
this.hackResetWxReplySelect = true //
})
},
handleDelete: function(row) {
const ids = row.id;
this.$modal.confirm('是否确认删除此数据?').then(function() {
return deleteAutoReply(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
}, },
} }
} }