这篇文章主要介绍了使用asp.net mvc,boostrap及knockout.js开发微信自定义菜单编辑工具,非常不错,具有参考借鉴价值,需要的朋友可以参考下
前言
微信的接口调试工具可以编辑自定义菜单,不过是提交json格式数据创建菜单,非常的不方便还容易出错。网上的工具不好用,所以就自己写了一个。
正文
先用bootstrap排个页面框架出来,调用自定义菜单接口需要用到accesstoken,放个输入框输入accesstoken。也不排除想直接输入appid和appsecret来获取accesstoken的用户,所以还需要下拉菜单来选择是输入accesstoken还是直接获取accesstoken。为了兼顾微信企业号应用创建菜单还需要agentid,corpid,套件永久授权码,suiteid,suitesecret,suiteticket,参数的输入框大致就是这些。
使用knockout定义好observables监控属性。并绑定到输入框上。
定义菜单展示及菜单编辑模块,排版为微信公众号菜单三个大菜单,每个大菜单下面可以配五个子菜单。大致思路如下,页面排版为六行三列,三个大菜单未配置满时在右侧显示增加菜单按钮,
每个父级菜单的子菜单未配置满时在上方显示增加菜单按钮。未配置满时以空白p占位。
定义个函数生成自定义长度数组
使用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": ""
}
]
}
]
}
定义添加,编辑,删除菜单函数,定义添加编辑菜单时临时监控属性,定义当前编辑菜单索引的监控属性。
一个一个编辑菜单还不是很方便,所以还要定义菜单的 上 下 左 右 的移动,及复制粘贴功能。
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();
},
绑定好监控属性,生成菜单排版
<p class="panel-body" data-bind="with:menus" id="pmenu" style="display: none;">
<p style="height: 200px;" data-bind="foreach:newarray(3)">
<p 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)) -->
<p class="list-group-item bn"></p>
<!--/ko-->
<!--ko if:$parent.button[$index()].sub_button.length<5 -->
<p class="list-group-item" data-bind="click:function (){$root.addmenu($index())}"><i class="fa fa-plus"></i>
</p>
<!--/ko-->
<!--ko foreach:($parent.button[$index()].sub_button) -->
<p class="list-group-item" data-bind="text:name,attr:{'bottonindex':$parent.value,'subbottonindex':$index()},click:function (){$root.editmenu($data,$parent.value,$index())}"></p>
<!--/ko-->
<!--/ko -->
<!--ko if: $parent.button[$index()]!=undefined && $parent.button[$index()].sub_button==undefined -->
<p class="list-group-item bn"></p>
<p class="list-group-item bn"></p>
<p class="list-group-item bn"></p>
<p class="list-group-item bn"></p>
<p class="list-group-item" data-bind="click:function (){$root.addmenu($index())}"><i class="fa fa-plus"></i>
</p>
<!--/ko-->
<!--ko if: $parent.button[$index()]==undefined -->
<p class="list-group-item bn"></p>
<p class="list-group-item bn"></p>
<p class="list-group-item bn"></p>
<p class="list-group-item bn"></p>
<p class="list-group-item bn"></p>
<!--/ko-->
</p>
</p>
<!--ko foreach:button -->
<p 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)}"></p>
<!--/ko-->
<!--ko if:button.length < 3 -->
<p class="col-xs-4 list-group-item" data-bind="click:function (){$root.addmenu();}"><i class="fa fa-plus"></i>
</p>
<!--/ko-->
<p class="clearfix"></p>
<p 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;">
<p class="form-group col-xs-4">
<input type="text" class="form-control" name="name" placeholder="请输入名称" data-bind="value:name">
</p>
<p 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>
</p>
<p class="form-group col-xs-8">
<input type="text" id="txtmenubuttonvalue" name="value" class="form-control" placeholder="请输入url" data-bind="value:value">
</p>
<p 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>
</p>
</form>
</p>
<p class="clearfix"></p>
</p>
最后增加菜单的查询函数及发布函数。因为编辑菜单方便,菜单对象和微信自定义菜单接口所需要的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);
}
});
}
最终效果如下
【相关推荐】
1. asp.net免费视频教程
2. asp.net教程
3. 极客学院asp.net视频教程
4. 什么是asp.net mvc ?总结asp.net mvc
5. 详细介绍asp.net mvc--控制器(controller)
6. 详细介绍asp.net mvc--视图
7. 详细介绍asp.net mvc--路由
8. 深入了解asp.net mvc与webform的区别
以上就是通过asp.net mvc开发微信自定义菜单编辑工具的代码示例的详细内容。