服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服务器之家 - 编程语言 - ASP.NET教程 - 使用asp.net mvc,boostrap及knockout.js开发微信自定义菜单编辑工具(推荐)

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

2020-05-04 15:38zhuzhijie ASP.NET教程

这篇文章主要介绍了使用asp.net mvc,boostrap及knockout.js开发微信自定义菜单编辑工具,非常不错,具有参考借鉴价值,需要的朋友可以参考下

前言

  微信的接口调试工具可以编辑自定义菜单,不过是提交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定义好菜单监控属性,格式为

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
 "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开发微信自定义菜单编辑工具(推荐)

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
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();
    },

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<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数据进行一下格式变化。,             

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
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开发微信自定义菜单编辑工具,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!

原文链接:http://www.cnblogs.com/jiept/archive/2017/05/03/6802287.html

延伸 · 阅读

精彩推荐