前言
微信的接口調試工具可以編輯自定義菜單,不過是提交json格式數據創建菜單,非常的不方便還容易出錯。網上的工具不好用,所以就自己寫了一個。
正文
先用bootstrap排個頁面框架出來,調用自定義菜單接口需要用到AccessToken,放個輸入框輸入AccessToken。也不排除想直接輸入AppId和AppSecret來獲取AccessToken的用戶,所以還需要下拉菜單來選擇是輸入AccessToken還是直接獲取AccessToken。為了兼顧微信企業號應用創建菜單還需要AgentId,CorpId,套件永久授權碼,SuiteId,SuiteSecret,SuiteTicket,參數的輸入框大致就是這些。
使用knockout定義好observables監控屬性。并綁定到輸入框上。
定義菜單展示及菜單編輯模塊,排版為微信公眾號菜單三個大菜單,每個大菜單下面可以配五個子菜單。大致思路如下,頁面排版為六行三列,三個大菜單未配置滿時在右側顯示增加菜單按鈕,
每個父級菜單的子菜單未配置滿時在上方顯示增加菜單按鈕。未配置滿時以空白div占位。
定義個函數生成自定義長度數組
使用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" : "" } ] } ] } |
定義添加,編輯,刪除菜單函數,定義添加編輯菜單時臨時監控屬性,定義當前編輯菜單索引的監控屬性。
一個一個編輯菜單還不是很方便,所以還要定義菜單的 上 下 左 右 的移動,及復制粘貼功能。
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開發微信自定義菜單編輯工具,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:http://www.cnblogs.com/jiept/archive/2017/05/03/6802287.html