vue开发微信公众号可视化配置菜单

其实一开始我也是懵逼的,我搞不懂微信公众号后台其实已经很好用了,为什么还需要开发一个模仿微信公众号后台的系统呢?而且微信公众号可以绑定多个运营者,都可以和管理员一样可以通过扫码登录来修改微信菜单配置,唯一想明白的就是如果有什么特殊功能需要开启第三方服务(开发者配置)的时候,才需要开发自定义菜单和自动回复。既然有如此需求,那么我们就来看看vue是如何实现微信公众号的可视化配置菜单的。菜单数据使用mock.js模拟,安装命令是,前端框架采用vue + element

npm install mockjs --save-dev

一、效果图:

二、采用的是vue-cli 2.0版本,菜单目录结构如图所示:

三、对应文件分别写入

1、views目录下menu的index.vue,我这边使用的是scss,css根据个人需要调整,图片路径也自己更改,所使用的图片地址是:

http://pri3p9w51.bkt.clouddn.com/iphone_backImg.png

<template><div class="public-account-management clearfix"><!--左边配置菜单--><div class="left"><div class="menu clearfix"><div v-for="(item, i) of menu.button" :key="i" class="menu_bottom"><!-- 一级菜单 --><div :class="{'active': isActive == i}" class="menu_item" @click="menuFun(i,item)">{{ item.name }}</div><!--以下为二级菜单--><div v-if="isSubMenuFlag == i" class="submenu"><div v-for="(subItem, k) in item.sub_button" :key="k" class="subtitle"><div :class="{'active': isSubMenuActive == i + '' + k}" class="menu_subItem" @click="subMenuFun(item, subItem, i, k)">{{ subItem.name }}</div></div><!--二级菜单加号, 当长度 小于  5 才显示二级菜单的加号  --><div v-if="item.sub_button.length < 5" class="menu_bottom menu_addicon" @click="addSubMenu(item)"><i class="el-icon-plus"></i></div></div></div><!-- 一级菜单加号 --><div v-if="menuKeyLength < 3" class="menu_bottom menu_addicon" @click="addMenu"><i class="el-icon-plus"></i></div></div><el-button class="save_btn" type="success" @click="saveFun">保存并发布至菜单</el-button></div><!--右边配置--><div v-if="!showRightFlag" class="right"><div class="configure_page"><div class="delete_btn"><el-button size="mini" type="danger" icon="el-icon-delete" @click="deleteMenu(tempObj)">删除当前菜单</el-button></div><div><span>菜单名称:</span><el-input v-model="tempObj.name" class="input_width" placeholder="请输入菜单名称" clearable style="margin-top: 12px;"></el-input></div><div><div class="menu_content"><span>菜单内容:</span><el-radio-group v-model="tempObj.type"><el-radio :label="'media_id'">发送素材</el-radio><el-radio :label="'view'">跳转链接</el-radio><el-radio :label="'click'">发送关键词</el-radio><el-radio :label="'miniprogram'">小程序</el-radio></el-radio-group></div><div class="configur_content"><div v-if="tempObj.type == 'media_id'" class="material"><span>素材内容:</span><el-input v-model="tempObj.media_id" :disabled="true" class="input_width" placeholder="素材名称"></el-input><!--下面点击“选择素材”按钮,弹框框--><el-popoverv-model="visible2"placement="top"><el-table:data="tableData"style="width: 100%"><el-table-columnlabel="文件名"width="600"><template slot-scope="scope"><el-popover trigger="hover" placement="top"><p>文件名: {{ scope.row.name }}</p><div slot="reference" class="name-wrapper"><el-tag size="medium">{{ scope.row.name }}</el-tag></div></el-popover></template></el-table-column><el-table-column label="操作"><template slot-scope="scope"><el-buttonsize="mini"@click="handleEdit(scope.$index, scope.row)">选择</el-button></template></el-table-column></el-table><el-button slot="reference" type="success">选择素材</el-button></el-popover><p class="blue">tips:需要调后台获取到内容,弹框出来,然后选择,把名字赋值上去!</p></div><div v-if="tempObj.type == 'view'"><span>跳转链接:</span><el-input v-model="tempObj.url" class="input_width" placeholder="请输入链接" clearable></el-input></div><div v-if="tempObj.type == 'click'"><div><span>关键词:</span><el-input v-model="tempObj.key" class="input_width" placeholder="请输入关键词" clearable></el-input></div><p class="blue">tips:这里需要配合关键词推送消息一起使用</p></div><div v-if="tempObj.type == 'miniprogram'"><div class="applet"><span>小程序的appid:</span><el-input v-model="tempObj.appid" class="input_width" placeholder="请输入小程序的appid" clearable></el-input></div><div><span>小程序的页面路径:</span><el-input v-model="tempObj.pagepath" class="input_width" placeholder="请输入小程序的页面路径,如:pages/index" clearable></el-input></div><p class="blue">tips:需要和公众号进行关联才可以把小程序绑定带微信菜单上哟!</p></div></div></div></div><div>menu对象值:{{ menu }}</div></div><!--一进页面就显示的默认页面,当点击左边按钮的时候,就不显示了--><div v-if="showRightFlag" class="right"><p>请选择菜单配置</p></div></div>
</template>
<script>
/***时间:2018/08/26*作者: spirtis*功能:* 公众号管理页面(基于vue-cli + elementUI + mockjs)* 如果想迁移到其他UI框架,里面更改的地方,就是:* 1、+ 加号 按钮* 2、el-  开头的组件: 输入框,按钮,弹出框 基本就这三种类型* @参数:**  1、自定义菜单配置文档,需要根据微信公众号要求配置,下面的链接*   https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141013**  2、tempObj.type:以下这4个类型的type值一定是这样,不能改变。*   media_id:发送素材;  view:跳转链接;  click:发送关键词 ; miniprogram:小程序**  3、素材内容这些都得调后台接口,读取微信配置,我本地没有,就用mock模拟**  4、自定义菜单最多包括3个一级菜单,每个一级菜单最多包含5个二级菜单。*    一级菜单最多4个汉字,二级菜单最多7个汉字,多出来的部分将会以“...”代替。*    (PS:输入框这些没有做限制,也没有做验证)**  5、menu 对象必须严格按照微信公众号文档说明的一样**  6、提交的时候,整个menu提交,type值是什么,后台获取的也是对应的内容,如果同个菜单*  的其他内容也填写了,也不妨碍。*/
export default {components: {},data() {return {showRightFlag: true, // 右边配置显示默认详情还是配置详情menu: {// 一级菜单button: [// {//   type: 'click',//   name: '菜单1',//   // key: 'menu1',关键词//   url: '', // 跳转链接//   media_id: '', // 素材名称--图文消息//   sub_button: [//     {//       type: '', // media_id:素材内容; view:跳转链接//       name: '子菜单1',//       url: '', // 跳转链接//       media_id: '' // 素材名称--图文消息//     }//   ]// }]}, // 横向菜单isActive: -1, // 一级菜单点中样式isSubMenuActive: -1, // 一级菜单点中样式isSubMenuFlag: -1, // 二级菜单显示标志tempObj: {// type: "view",// media_id: 素材内容// view: 跳转链接// name: "",//菜单名称// material: "",//素材名称// link: "",//跳转链接}, // 右边临时变量,作为中间值牵引关系tempSelfObj: {// 一些临时值放在这里进行判断,如果放在tempObj,由于引用关系,menu也会多了多余的参数// grand:"" 1:表示一级菜单; 2:表示二级菜单// index:"" 表示一级菜单索引// secondIndex:"" 表示二级菜单索引},visible2: false, // 素材内容  "选择素材"按钮弹框显示隐藏tableData: [] // 素材内容弹框数据}},created() {this.mockMediaFun() // 模拟获取素材this.mockMenuFun() // 模拟调取菜单数据// this.getWxMenu()},/* eslint-disable */methods: {// 模拟调取菜单数据getWxMenu() {this.$http.get('/CustomMenu/get').then(response => {if(response.data.errcode == null) {this.menu.button = response.data.menu.button} else if (response.data.errcode == 46003) {this.menu.button = [{type: 'click',name: '菜单1',// key: 'menu1',关键词url: '', // 跳转链接media_id: '', // 素材名称--图文消息sub_button: [{type: '', // media_id:素材内容; view:跳转链接name: '子菜单1',url: '', // 跳转链接media_id: '' // 素材名称--图文消息}]}]}}).catch(error => {this.$message({showClose: true,message: '获取微信公众号菜单异常{' + error + '}',type: 'error'})})},mockMenuFun(){this.$http({url:"/api/menu",method:'get'}).then((res)=>{this.menu.button = res.data.button})},// 调用素材内容 “选择素材”的弹框数据,模拟从微信返回的数据mockMediaFun(){this.$http({url:"/api/data",method:'get'}).then((res)=>{this.tableData = res.data;})},// 素材内容弹框的选择按钮函数handleEdit(index, row) {this.visible2 = false;this.tempObj.media_id = row.name;},saveFun(){this.$http.post('/CustomMenu/add', this.menu, {headers: {'content-type': 'application/json'}}).then(response => {if(response.data.errcode == 0) {this.$message({showClose: true,message: '保存并发布成功!',type: 'success'})} else {this.$message({showClose: true,message: '' + response.data.errmsg + '',type: 'warning'})}}).catch(error => {this.$message({showClose: true,message: '保存并发布菜单异常{' + error + '}',type: 'error'})})},// 一级菜单点击事件menuFun(i, item){this.showRightFlag = false //右边菜单隐藏// console.log(i)this.tempObj = item //这个如果放在顶部,flag会没有。因为重新赋值了。this.tempSelfObj.grand = "1" //表示一级菜单this.tempSelfObj.index = i //表示一级菜单索引this.isActive = i //一级菜单选中样式this.isSubMenuFlag = i //二级菜单显示标志this.isSubMenuActive = -1 //二级菜单去除选中样式},// 二级菜单点击事件subMenuFun(item, subItem, index, k){this.showRightFlag = false;//右边菜单隐藏this.tempObj = subItem;//将点击的数据放到临时变量,对象有引用作用this.tempSelfObj.grand = "2";//表示二级菜单this.tempSelfObj.index = index;//表示一级菜单索引this.tempSelfObj.secondIndex = k;//表示二级菜单索引this.isSubMenuActive = index + "" + k; //二级菜单选中样式this.isActive = -1;//一级菜单去除样式},// 添加横向一级菜单addMenu(){// 先判断1,再判断2,对象增加,会进行往下计算,所以必须先判断2,再判断1if(this.menuKeyLength == 2){this.$set(this.menu.button,"2",{// type: "",name: "菜单3",// url: "",//跳转链接// media_id:"",//素材名称--图文消息sub_button: []})}if(this.menuKeyLength == 1){this.$set(this.menu.button, "1",{// type: "",name: "菜单2",// url: "",//跳转链接// media_id:"",//素材名称--图文消息sub_button: []})}},// 添加横向二级菜单addSubMenu(item){let subMenuKeyLength = item.sub_button.length;//获取二级菜单key长度if(subMenuKeyLength == 4){this.$set(item.sub_button,"4",{// type: "",name: "子菜单5",// url: "",//跳转链接// media_id:"",//素材名称--图文消息});}if(subMenuKeyLength == 3){this.$set(item.sub_button,"3",{// type: "",name: "子菜单4",// url: "",//跳转链接// media_id:"",//素材名称--图文消息});}if(subMenuKeyLength == 2){this.$set(item.sub_button,"2",{// type: "",name: "子菜单3",// url: "",//跳转链接// media_id:"",//素材名称--图文消息})}if(subMenuKeyLength == 1){this.$set(item.sub_button,"1",{// type: "",name: "子菜单2",// url: "",//跳转链接// media_id:"",//素材名称--图文消息})}if(subMenuKeyLength == 0){this.$set(item.sub_button,"0",{// type: "",name: "子菜单1",// url: "",//跳转链接// media_id:"",//素材名称--图文消息})}},//删除当前菜单deleteMenu(obj){var _this = thisthis.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {_this.deleteData() // 删除菜单数据}).catch(() => {})},// 删除菜单数据deleteData(){// 一级菜单的删除方法if (this.tempSelfObj.grand == "1") {this.menu.button.splice(this.tempSelfObj.index,1)}// 二级菜单的删除方法if (this.tempSelfObj.grand == "2") {this.menu.button[this.tempSelfObj.index].sub_button.splice(this.tempSelfObj.secondIndex, 1)}this.$message({type: 'success',message: '删除成功!'})}},computed:{// menuObj的长度,当长度 小于 3 才显示一级菜单的加号menuKeyLength:function(){return this.menu.button.length;}}/* eslint-disable */
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
@import 'src/styles/variables.scss';
/* 公共颜色变量 */
.clearfix{*zoom:1;}
.clearfix::after{content: "";display: table; clear: both;}
div{text-align: left;
}
.public-account-management{padding: 20px;min-width: 1200px;width: 1200px;margin: 0 auto;.left{font-family: 'Times New Roman', Times, serif;float: left;display: inline-block;width: 301px;background: url("../../../assets/img/wxmenu/iphone_backImg.png") no-repeat;background-size: 100% auto;padding: 490px 25px 88px;position: relative;box-sizing: border-box;/*第一级菜单*/.menu{.menu_bottom{position: relative;float: left;display: inline-block;box-sizing: border-box;width: 83px;/*height: 44px;*//*line-height: 44px;*/text-align: center;background-color: #e2e2e2;border: 1px solid #ebedee;cursor: pointer;&.menu_addicon{height: 46px;line-height: 46px;}.menu_item{height: 44px;line-height: 44px;/*padding: 14px 0;*/text-align: center;box-sizing: border-box;&.active{border: 1px solid #2bb673;}}.menu_subItem{height: 44px;line-height: 44px;text-align: center;box-sizing: border-box;/*padding: 14px 0;*/&.active{border: 1px solid #2bb673;}}}i{color:#2bb673;}/*第二级菜单*/.submenu{position: absolute;width: 83px;bottom: 45px;.subtitle{background-color: #e8e7e7;box-sizing: border-box;margin-bottom: 2px;}}}.save_btn{position: relative;margin-top: 100px;left: 45px;}}/*右边菜单内容*/.right{font-family: 'Times New Roman', Times, serif;float: left;width: 70%;background-color: #e8e7e7;padding: 25px 10px 0px 20px;min-height: 610px;margin-left: 20px;-webkit-box-sizing: border-box;box-sizing: border-box;p {font-size: 16px;margin-top: -10px;font-weight: bold;}.configure_page{.delete_btn{text-align: right;margin-bottom: 15px;}.menu_content{margin-top: 20px;}.configur_content{margin-top: 20px;}.blue{color:#29b6f6;margin-top: 10px;}.applet{margin-bottom: 20px;span{margin-right: 18px;}}.material{.input_width{width: 30%;}.el-textarea{width: 80%}}}}
}
</style>

2、wxmenu.js放置与根目录mock下

import Mock from 'mockjs';// 素材内容
export var tableData = Mock.mock('/api/data',[{name: 'Vue',}, {name: 'angular',},{name: 'react',},]);// 配置菜单
export var menu = Mock.mock('/api/menu',{// 一级菜单button:[{type: "click",name: "菜单1",key: "menu1", // 关键词url: "", // 跳转链接media_id:"", // 素材名称--图文消息sub_button: [{//type: "",//media_id:素材内容; view:跳转链接name: "子菜单1",// url: "",//跳转链接// media_id:"",//素材名称--图文消息},]}]
}
);

3、main.js中写入

require('../mock/wxmenu')

至此,恭喜您,可视化菜单就ok了

vue开发微信公众号可视化配置菜单相关推荐

  1. vue开发微信公众号订阅消息踩坑记录

    今天做了一个微信公众号的网页开发, 使用的是vue做的开发,没错,就是微信公众号的开发,这都2021年了, 还有人有开发微信公众号的需求,我也是晕了, 微信公众号是我开发中感觉,最难调试的开发工作,没 ...

  2. wechatpy开发微信公众号(实现自定义菜单,翻译)

    今天来学习通过wechatpy 来开发微信公众号. 准备工作: 1.申请一个微信公众号 2.pip install wechatpy 如是自己没有服务器,下载ngrok :ngrok 是一个反向代理, ...

  3. Vue开发微信公众号网页跳转小程序

    需求描述:Vue开发的公众号网页,点击图标跳转小程序 公众号中跳转小程序,一般是配置菜单栏跳转即可,但是我们需要在页面中跳转,就需要微信的开放标签了 微信开放标签说明文档 此文档面向网页开发者,介绍微 ...

  4. vue开发微信公众号之文件下载

    开发微信公众号实现文件下载的时候问题就出现了,一般网站做法就用不了,因为微信内置浏览器不支持下载文件,这就需要你用外部浏览器了(一般都是用手机自带的浏览器). 这边你需要新建一个中转页面,提醒用户要通 ...

  5. 微信开发--微信公众号相关配置--添加子管理员

    微信公众号一般由客户申请,客户方会有一位微信公众号的超级管理员管理公众号: 为了方便开发,开发者最好成为微信公众号的子管理员,下面将说明如何添加微信公众号子管理员 首先从客户那里获取到所开发微信公众号 ...

  6. Vue开发微信公众号调用微信JS-SDK的分享接口(实现微信公众号分享功能)

    描述 使用微信提供的分享功能,其实就是JSSDK使用,使用它提供的接口功能. 可以先看下微信公众号开发文档,上面介绍的很详细.提供了那些功能,怎么去使用. https://developers.wei ...

  7. vue开发微信公众号调用相机和相册(上传到自己的服务器)

    第一步: 下载weixin-js-sdk npm install weixin-js-sdk 第二步: 在需要使用的页面引入sdk import wx from "weixin-js-sdk ...

  8. 微信公众号后台配置菜单代码

    导入jar包 首先是 菜单项的基类,所有一级菜单.二级菜单都共有一个相同的属性,那就是name.菜单项基类的封装代码如下: package com.souvc.weixin.menu;/** * 类名 ...

  9. 用vue开发微信公众号H5移动端页面

    第一步:搭建项目结构 其中涉及到路由的配置: 我是这样的routes: [{path: '/',name: 'base-home',redirect: '/main',component: '',ch ...

最新文章

  1. 为什么把事情拖到最后做效率特别高?
  2. Jquery属性选择器(同时匹配多个条件,与或非)(附样例)
  3. Nginx reload的时候出现的问题/usr/local/nginx/logs/nginx.pid
  4. class ts 扩展方法_如使用Typescript撸Vue(Vue2 + TS +TSX+CSS module)
  5. MOSS2010单点登录
  6. 图灵社区 和 大家网
  7. commons-lang3-RandomUtils
  8. MVC中如何使用语音识别功能实现输入
  9. SpringBoot 入门知识点详解
  10. 怎么调用anaconda安装的pip_对于学python的小伙伴来到底该不该安装andconda
  11. ldDWR出现“例外被抛出且未被接住 解决方法
  12. 从Excel中随机取出几行
  13. PFC_颗粒流软件_喷射混凝土模拟
  14. 背景图页面缩小会变形_HTML中怎么让背景图片跟着浏览器窗口变大变小?
  15. 【BUG】【已解决】VS2019:应用程序无法正常启动(0x000007b)
  16. GCD Expectation ZOJ - 3868 (容斥)
  17. 50欧姆线设计 高频pcb_pcb 50欧姆阻抗匹配设计技巧
  18. 数组逆时针旋转 90 度
  19. 美女主动搭讪?小心数学陷阱
  20. IT是未来大趋势,有学计算机专业的同学会后悔和转行原因在哪?

热门文章

  1. 互联网大数据公司排名_互联网上最好的数据科学课程,按照您的评论排名
  2. GitLab-双因子认证
  3. 终于拿到了阿里技术专家分享的552页大型网站架构实战
  4. DevOps 读书雷达 - 企业数字化转型的读书清单
  5. 原 LT、LE、EQ、NE、GE、GT 符号的含义
  6. PR 多项目/多序列编辑
  7. 输出15W 9V 1.5A的TYPE-C口升压充电电路同步开关
  8. Deque与Queue方法总结
  9. c语言之分析输出实数时的有效数位
  10. 新疆大学地理学考研资料