欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

使用asp.net mvc,boostrap及knockout.js开发微信自定义菜单编辑工具(推荐)

程序员文章站 2023-11-12 18:35:10
前言   微信的接口调试工具可以编辑自定义菜单,不过是提交json格式数据创建菜单,非常的不方便还容易出错。网上的工具不好用,所以就自己写了一个。 正文   先用bo...

前言

  微信的接口调试工具可以编辑自定义菜单,不过是提交json格式数据创建菜单,非常的不方便还容易出错。网上的工具不好用,所以就自己写了一个。

正文

  先用bootstrap排个页面框架出来,调用自定义菜单接口需要用到accesstoken,放个输入框输入accesstoken。也不排除想直接输入appid和appsecret来获取accesstoken的用户,所以还需要下拉菜单来选择是输入accesstoken还是直接获取accesstoken。为了兼顾微信企业号应用创建菜单还需要agentid,corpid,套件永久授权码,suiteid,suitesecret,suiteticket,参数的输入框大致就是这些。

  使用knockout定义好observables监控属性。并绑定到输入框上。

使用asp.net mvc,boostrap及knockout.js开发微信自定义菜单编辑工具(推荐)

  使用asp.net mvc,boostrap及knockout.js开发微信自定义菜单编辑工具(推荐) 

   定义菜单展示及菜单编辑模块,排版为微信公众号菜单三个大菜单,每个大菜单下面可以配五个子菜单。大致思路如下,页面排版为六行三列,三个大菜单未配置满时在右侧显示增加菜单按钮,

每个父级菜单的子菜单未配置满时在上方显示增加菜单按钮。未配置满时以空白div占位。

  定义个函数生成自定义长度数组

使用asp.net mvc,boostrap及knockout.js开发微信自定义菜单编辑工具(推荐)

  使用knockout定义好菜单监控属性,格式为

{
 "button": [
  {
   "name": "父级菜单1",
   "sub_button": [
    {
     "type": "view",
     "name": "子菜单1",
     "url": ""
    }
   ]
  },
  {
   "name": "父级菜单1",
   "sub_button": [
    {
     "type": "view",
     "name": "子菜单2",
     "url": ""
    },
    {
     "type": "view",
     "name": "子菜单1",
     "url": ""
    }
   ]
  }
 ]
}

   定义添加,编辑,删除菜单函数,定义添加编辑菜单时临时监控属性,定义当前编辑菜单索引的监控属性。

使用asp.net mvc,boostrap及knockout.js开发微信自定义菜单编辑工具(推荐)

  一个一个编辑菜单还不是很方便,所以还要定义菜单的 上 下 左 右 的移动,及复制粘贴功能。

function menuformvalidate() {
   $("#menuform").validate({
    rules: {
     name: {
      required: true
     },
     value: {
      required: false
     }
    },
    messages: {
     name: {
      required: "请输入名称"
     },
     value: {
      required: $("#txtmenubuttonvalue").attr("placeholder")
     }
    }
   });
  }
          menusreset:function () {
     var menus = json.stringify(model.menus());
     model.menus(undefined);
     model.menus(json.parse(menus));//刷新菜单对象
     menuformvalidate();//重新绑定验证方法
    },
menuindex: ko.observable(), //父级菜单索引
    iseditmenu: ko.observable(false), //是否是编辑菜单
    bottonindex: ko.observable(-1), //编辑菜单的父级菜单索引
    subbottonindex: ko.observable(-1), //编辑菜单的子菜单索引
    menu: ko.observable(),//编辑菜单时临时监控属性
    copymenu: ko.observable(),//复制的菜单对象
    copy: function () { //复制
     if (model.menu() != undefined) {
      var menu = json.stringify(model.menu());
      model.copymenu(json.parse(menu));
      model.menu(undefined);
     }
    },
    paste: function () {//粘贴
     if (model.copymenu() != undefined) {
      var menu = json.parse(json.stringify(model.copymenu()));
      if (model.subbottonindex() !== -1 && menu.sub_button != undefined || (!model.iseditmenu() && model.menuindex() != undefined)) {
       delete menu.sub_button;
      }
      model.menu(menu);
      menuformvalidate();
     }
    },
    up: function () {//向上移动
     var bottonindex = model.bottonindex();
     var subbottonindex = model.subbottonindex();
     var newsubbottonindex = subbottonindex - 1;
     model.menus().button[bottonindex].sub_button[subbottonindex] = model.menus().button[bottonindex].sub_button[newsubbottonindex];
     model.menus().button[bottonindex].sub_button[newsubbottonindex] = model.menu();
     model.menusreset();
     model.subbottonindex(newsubbottonindex);
    },
    down: function () {//向下移动
     var bottonindex = model.bottonindex();
     var subbottonindex = model.subbottonindex();
     var newsubbottonindex = subbottonindex + 1;
     model.menus().button[bottonindex].sub_button[subbottonindex] = model.menus().button[bottonindex].sub_button[newsubbottonindex];
     model.menus().button[bottonindex].sub_button[newsubbottonindex] = model.menu();
     model.menusreset();
     model.subbottonindex(newsubbottonindex);
    },
    left: function () {//向左移动
     var bottonindex = model.bottonindex();
     var subbottonindex = model.subbottonindex();
     if (subbottonindex === -1) {
      var newbottonindex = bottonindex - 1;
      model.menus().button[bottonindex] = model.menus().button[newbottonindex];
      model.menus().button[newbottonindex] = model.menu();
      model.menusreset();
      model.bottonindex(newbottonindex);
     }
    },
    right: function () {//向右移动
     var bottonindex = model.bottonindex();
     var subbottonindex = model.subbottonindex();
     if (subbottonindex === -1) {
      var newbottonindex = bottonindex + 1;
      model.menus().button[bottonindex] = model.menus().button[newbottonindex];
      model.menus().button[newbottonindex] = model.menu();
      model.menusreset();
      model.bottonindex(newbottonindex);
     }
    },
    editmenu: function (obj, bottonindex, subbottonindex) {//编辑菜单
     model.bottonindex(bottonindex);
     model.subbottonindex(subbottonindex);
     model.iseditmenu(true);
     var data = json.stringify(obj);
     model.menu(json.parse(data));
     menuformvalidate();
    },
    addmenu: function (index) {//添加菜单
     model.bottonindex(-1);
     model.subbottonindex(-1);
     model.iseditmenu(false);
     model.menuindex(index);
     var menu = { type: "view", name: "", value: "" };
     model.menu(menu);
     menuformvalidate();
    },
    deletemenu: function () {//删除菜单
     $(model.menus().button).each(function (index, item) {
      if (index === model.bottonindex() && model.subbottonindex() === -1) {
       model.menus().button.splice(index, 1);
      }
      if (item.sub_button instanceof array) {
       $(item.sub_button).each(function (index1) {
        if (index === model.bottonindex() && index1 === model.subbottonindex()) {
         item.sub_button.splice(index1, 1);
        }
       });
      }
     });
     model.menu(undefined);
     model.menuindex(undefined);
     model.bottonindex(-1);
     model.subbottonindex(-1);
     model.menusreset();
    },
    cancelmenusave: function () {//取消编辑,重置参数
     model.menu(undefined);
     model.menuindex(undefined);
     model.bottonindex(-1);
     model.subbottonindex(-1);
    },
    menusave: function () {//保存编辑的菜单
     if (!$("#menuform").data("validator").form()) {
      return;
     }
     if (model.iseditmenu()) {
      var menuindex = model.bottonindex();
      var submenuindex = model.subbottonindex();
      if (submenuindex === -1) {
       model.menus().button[menuindex] = model.menu();
      } else {
       model.menus().button[menuindex].sub_button[submenuindex] = model.menu();
      }
     } else {
      if (model.menuindex() != undefined) {
       if (model.menus().button[model.menuindex()].sub_button == undefined) {
        model.menus().button[model.menuindex()].sub_button = new array();
       }
       model.menus().button[model.menuindex()].sub_button.unshift(model.menu());
      } else {
       model.menus().button.push(model.menu());
      }
     }
     model.menu(undefined);
     model.menuindex(undefined);
     model.bottonindex(-1);
     model.subbottonindex(-1);
     model.menusreset();
    },

绑定好监控属性,生成菜单排版

<div class="panel-body" data-bind="with:menus" id="divmenu" style="display: none;">
  <div style="height: 200px;" data-bind="foreach:newarray(3)">
   <div class="list-group col-xs-4 clearfill bn">
    <!--ko if:($parent.button.length>0 && $parent.button[$index()]!=undefined && $parent.button[$index()].sub_button!=undefined ) -->
    <!--ko foreach:newarray((4-$parent.button[$index()].sub_button.length)) -->
    <div class="list-group-item bn"></div>
    <!--/ko-->
    <!--ko if:$parent.button[$index()].sub_button.length<5 -->
    <div class="list-group-item" data-bind="click:function (){$root.addmenu($index())}"><i class="fa fa-plus"></i>
    </div>
    <!--/ko-->
    <!--ko foreach:($parent.button[$index()].sub_button) -->
    <div class="list-group-item" data-bind="text:name,attr:{'bottonindex':$parent.value,'subbottonindex':$index()},click:function (){$root.editmenu($data,$parent.value,$index())}"></div>
    <!--/ko-->
    <!--/ko -->
    <!--ko if: $parent.button[$index()]!=undefined && $parent.button[$index()].sub_button==undefined -->
    <div class="list-group-item bn"></div>
    <div class="list-group-item bn"></div>
    <div class="list-group-item bn"></div>
    <div class="list-group-item bn"></div>
    <div class="list-group-item" data-bind="click:function (){$root.addmenu($index())}"><i class="fa fa-plus"></i>
    </div>
    <!--/ko-->
    <!--ko if: $parent.button[$index()]==undefined -->
    <div class="list-group-item bn"></div>
    <div class="list-group-item bn"></div>
    <div class="list-group-item bn"></div>
    <div class="list-group-item bn"></div>
    <div class="list-group-item bn"></div>
    <!--/ko-->
   </div>
  </div>
  <!--ko foreach:button -->
  <div class="col-xs-4 list-group-item list-group-item-danger" data-bind="text:name,attr:{'bottonindex':$index()},click:function (){$root.editmenu($data,$index(),-1)}"></div>
  <!--/ko-->
  <!--ko if:button.length < 3 -->
  <div class="col-xs-4 list-group-item" data-bind="click:function (){$root.addmenu();}"><i class="fa fa-plus"></i>
  </div>
  <!--/ko-->
  <div class="clearfix"></div>
  <div class="col-xs-12" style="border: 1px solid #eeeeee; padding-top: 15px; margin-top: 15px;" data-bind="with:$root.menu,visible:($root.menu()!=undefined)">
   <form id="menuform" onsubmit="return false;">
    <div class="form-group col-xs-4">
     <input type="text" class="form-control" name="name" placeholder="请输入名称" data-bind="value:name">
    </div>
    <div class="form-group col-xs-4">
     <select class="form-control" onchange="$('#txtmenubuttonvalue')
 .attr('placeholder', $(this).find('option:selected').attr('pl'))" data-bind="value:type">
      <option value="view" pl="请输入url">跳转url</option>
      <option value="click" pl="请输入key">点击推事件</option>
      <option value="scancode_push" pl="请输入key">扫码推事件</option>
      <option value="scancode_waitmsg" pl="请输入key">扫码推事件且弹出“消息接收中”提示框</option>
      <option value="pic_sysphoto" pl="请输入key">弹出系统拍照发图</option>
      <option value="pic_photo_or_album" pl="请输入key">弹出拍照或者相册发图</option>
      <option value="pic_weixin" pl="请输入key"> 弹出微信相册发图器</option>
      <option value="location_select" pl="请输入key">弹出地理位置选择器</option>
     </select>
    </div>
    <div class="form-group col-xs-8">
     <input type="text" id="txtmenubuttonvalue" name="value" class="form-control" placeholder="请输入url" data-bind="value:value">
    </div>
    <div class="form-group col-xs-12">
     <button type="submit" class="btn btn-primary" data-bind="click:$root.menusave">确定</button>
     <button type="submit" class="btn btn-danger" data-bind="visible:$root.iseditmenu,click:$root.deletemenu">删除</button>
     <button type="button" class="btn btn-default" title="上移" data-bind="visible:$root.iseditmenu(),disable:!$root.isup(),click:$root.up"><i class="fa fa-chevron-circle-up" aria-hidden="true"></i></button>
     <button type="button" class="btn btn-default" title="下移" data-bind="visible:$root.iseditmenu(),disable:!$root.isdown(),click:$root.down"><i class="fa fa-chevron-circle-down" aria-hidden="true"></i></button>
     <button type="button" class="btn btn-default" title="左移" data-bind="visible:$root.iseditmenu(),disable:!$root.isleft(),click:$root.left"><i class="fa fa-chevron-circle-left" aria-hidden="true"></i></button>
     <button type="button" class="btn btn-default" title="右移" data-bind="visible:$root.iseditmenu(),disable:!$root.isright(),click:$root.right"><i class="fa fa-chevron-circle-right" aria-hidden="true"></i></button>
     <button type="button" class="btn btn-default" title="复制菜单" data-bind="visible:$root.iseditmenu(),click:$root.copy">复制</button>
     <button type="button" class="btn btn-default" title="粘贴菜单" data-bind="click:$root.paste">粘贴</button>
     <button type="submit" class="btn btn-default" data-bind="click:$root.cancelmenusave">关闭</button>
    </div>
   </form>
  </div>
  <div class="clearfix"></div>
 </div>

最后增加菜单的查询函数及发布函数。因为编辑菜单方便,菜单对象和微信自定义菜单接口所需要的json格式不对应,所以在查询现有菜单和发布菜单时,需要对json数据进行一下格式变化。,             

 editmenus: function (isquery) {
     if (isquery == undefined) {
      var menu = {};
      menu.button = new array();
      model.menus(menu);
     } else {
      var appid = model.appid();
      var appsecret = model.appsecret();
      var accesstoken = model.accesstoken();
      var type = model.type();
      var tokentype = model.tokentype();
      var corpid = model.corpid();
      var permanentcode = model.permanentcode();
      var agentid = model.agentid();
      var suiteid = model.suiteid();
      var suitesecret = model.suitesecret();
      var suiteticket = model.suiteticket();
      if (type === "1" && tokentype === "2") {
       if (appid == undefined || $.trim(appid).length === 0) {
        alert("请输入appid");
        return;
       }
       if (appsecret == undefined || $.trim(appsecret).length === 0) {
        alert("请输入appsecret");
        return;
       }
      } else if (type === "2" && tokentype === "2") {
       if (corpid == undefined || $.trim(corpid).length === 0) {
        alert("请输入corpid");
        return;
       }
       if (permanentcode == undefined || $.trim(permanentcode).length === 0) {
        alert("请输入永久授权码");
        return;
       }
       if (agentid == undefined || $.trim(agentid).length === 0) {
        alert("请输入agentid");
        return;
       }
       if (suiteid == undefined || $.trim(suiteid).length === 0) {
        alert("请输入suiteid");
        return;
       }
       if (suitesecret == undefined || $.trim(suitesecret).length === 0) {
        alert("请输入suitesecret");
        return;
       }
       if (suiteticket == undefined || $.trim(suiteticket).length === 0) {
        alert("请输入suiteticket");
        return;
       }
      } else if (tokentype === "1") {
       if (accesstoken == undefined || $.trim(accesstoken).length === 0) {
        alert("请输入accesstoken");
        return;
       }
      }
      $("#btnquerymenu").button("查询中...");
      $.ajax({
       url: "",
       datatype: "json",
       type: "post",
       async: true,
       data: json.stringify({
        appid: appid, appsecret: appsecret, accesstoken: accesstoken, type: type, tokentype: tokentype, corpid: corpid, permanentcode: permanentcode, agentid: agentid,
        suiteid: suiteid, suitesecret: suitesecret, suiteticket: suiteticket
       }),
       contenttype: "application/json; charset=utf-8",
       success: function (obj) {
        $("#btnquerymenu").button("reset");
        if (obj.success) {
         var data = obj.data;
         var menus = json.parse(data).menu;
         $(menus.button).each(function (index, item) {
          if (item.type === "view") {
           item.value = item.url;
           delete item.url;
          } else {
           item.value = item.key;
           delete item.key;
          }
          if (item.type == undefined) {
           item.type = "view";
           item.value = "";
          }
          if (item.sub_button instanceof array) {
           $(item.sub_button).each(function (index1, item2) {
            if (item2.type === "view") {
             item2.value = item2.url;
             delete item2.url;
            } else {
             item2.value = item2.key;
             delete item2.key;
            }
           });
          }
         });
         model.menu(undefined);
         model.menuindex(undefined);
         model.bottonindex(-1);
         model.subbottonindex(-1);
         model.menus(undefined);
         model.menus(menus);
        } else {
         alert(obj.messages);
        }
       },
       error: function (xmlhttprequest, textstatus, errorthrown) {
        $("#btnquerymenu").button("reset");
        console.error(errorthrown);
       }
      });
     }
    },
    savemenus: function () {
     var menus = json.parse(json.stringify(model.menus()));
     $(menus.button).each(function (index, item) {
      if (item.type === "view") {
       item.url = item.value;
       delete item.value;
      } else {
       item.key = item.value;
       delete item.value;
      }
      if (item.sub_button instanceof array) {
       $(item.sub_button).each(function (index1, item2) {
        if (item2.type === "view") {
         item2.url = item2.value;
         delete item2.value;
        } else {
         item2.key = item2.value;
         delete item2.value;
        }
       });
       if (item.sub_button.length > 0) {
        delete item.key;
        delete item.url;
        delete item.type;
       } else {
        delete item.sub_button;
       }
      }
     });
     console.log(json.stringify(menus));
     var appid = model.appid();
     var appsecret = model.appsecret();
     var accesstoken = model.accesstoken();
     var type = model.type();
     var tokentype = model.tokentype();
     var agentid = model.agentid();
     var suiteid = model.suiteid();
     var suitesecret = model.suitesecret();
     var suiteticket = model.suiteticket();
     if (type === "1" && tokentype === "2") {
      if (appid == undefined || $.trim(appid).length === 0) {
       alert("请输入appid");
       return;
      }
      if (appsecret == undefined || $.trim(appsecret).length === 0) {
       alert("请输入appsecret");
       return;
      }
     } else if (type === "2" && tokentype === "2") {
      if (agentid == undefined || $.trim(agentid).length === 0) {
       alert("请输入agentid");
       return;
      }
      if (suiteid == undefined || $.trim(suiteid).length === 0) {
       alert("请输入suiteid");
       return;
      }
      if (suitesecret == undefined || $.trim(suitesecret).length === 0) {
       alert("请输入suitesecret");
       return;
      }
      if (suiteticket == undefined || $.trim(suiteticket).length === 0) {
       alert("请输入suiteticket");
       return;
      }
     } else if (tokentype === "1") {
      if (accesstoken == undefined || $.trim(accesstoken).length === 0) {
       alert("请输入accesstoken");
       return;
      }
     }
     $("#btnsubmitmenu").button("发布中...");
     $.ajax({
      url: "",
      datatype: "json",
      type: "post",
      async: true,
      data: json.stringify({
       appid: appid, appsecret: appsecret, accesstoken: accesstoken, type: type, tokentype: tokentype, agentid: agentid,
       suiteid: suiteid, suitesecret: suitesecret, suiteticket: suiteticket, menu: json.stringify(menus)
      }),
      contenttype: "application/json; charset=utf-8",
      success: function (obj) {
       $("#btnsubmitmenu").button("reset");
       if (obj.success) {
        alert("发布成功");
       } else {
        alert(obj.messages);
       }
      },
      error: function (xmlhttprequest, textstatus, errorthrown) {
       $("#btnsubmitmenu").button("reset");
       console.error(errorthrown);
      }
     });
    }

 最终效果如下

使用asp.net mvc,boostrap及knockout.js开发微信自定义菜单编辑工具(推荐)

以上所述是小编给大家介绍的使用asp.net mvc,boostrap及knockout.js开发微信自定义菜单编辑工具,希望对大家有所帮助