微信自定义菜单

页面效果是如此这般的
微信自定义菜单
特别说明:实习方式仿站乐享微信 但又不完全依照!!!
 
首先介绍下环境配置
wamp环境 + thinkphp框架实现的!
 
核心:自定义菜单生成到微信端:从数据库取出数据——>生产微信自定义菜单。
 
这里有三个难点:
1. 数据库的设计:一个表实现(用PID来识别主菜单及子菜单的区别)。
数据库如下(MYSQL):
 
当然表绝对不止这些内容 但是主要说明一下微信自定义菜单表对应的关系就可以了
--
-- 表的结构 `wx_custom_menu`
--

CREATE TABLE IF NOT EXISTS `wx_custom_menu` (
  `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
  `parentid` mediumint(8) unsigned NOT NULL COMMENT ‘一级菜单ID‘,
  `title` char(10) NOT NULL COMMENT ‘菜单名称‘,
  `key` varchar(200) NOT NULL COMMENT ‘此关键字字段可URL或关键词,如百度地图链接比够长,需添加200‘,
  `isshow` tinyint(1) unsigned NOT NULL COMMENT ‘是否显示菜单‘,
  `listsort` tinyint(3) unsigned NOT NULL COMMENT ‘一级菜单ID‘,
  PRIMARY KEY (`id`),
  KEY `idx_wxid_userid` (`wxid`,`userid`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=110 ;
 
首先说明下:wxid,userid这两个字段可不用 但是我这原本是微信开发用来识别微信公众号以及用户的ID。最后也做了个索引!
 
2. 页面的输出:
Thinkphp框架的写法:
 
class CustomMenuAction extends UserAction{
    
    public function index() {
        $arr = $this->selectDb();
        $this->assign(‘arr‘,$arr);
        $this->display();
    }
  //从数据库中查找数据并重组数组
    public function selectDb(){
  //从表中根据isshow是否显示这个条件查询出数据
        $menu=M(‘custom_menu‘)->where(array(‘isshow‘=>1))->select();
        $arr = array();
  //这里是重组数据
        foreach ($menu as $value){
            if($value[‘parentid‘] == 0){
                $arr[$value[‘id‘]]=$value;
            }else{
                $arr[$value[‘parentid‘]][‘sub‘][$value[‘id‘]]=$value;
            }
        }
  //调用排序 使结果逆向排序
        $arr = $this->array_sort($arr,‘listsort‘);
        foreach ($arr as $key=>$row){
            foreach ($row as $r)
            if(is_array($r)){
                $arr[$key][‘sub‘] = $this->array_sort($r,‘listsort‘);
             }
        }
        return $arr;
    }
 
  /* 二维数组按指定的键值排序
  * $array 数组
  * $key排序键值
  * $type排序方式
  */
  function array_sort($arr, $keys, $type = ‘desc‘) {
      $keysvalue = $new_array = array();
      foreach ($arr as $k => $v) {
          $keysvalue[$k] = $v[$keys];
      }
      if ($type == ‘asc‘) {
          asort($keysvalue);
      } else {
          arsort($keysvalue);
      }
      reset($keysvalue);
      foreach ($keysvalue as $k => $v) {
          $new_array[$k] = $arr[$k];
      }
      return $new_array;
  }
}
 
必要说明:后续的代码都是写进上面的类。
具体结果格式应该呈现这样的:
微信自定义菜单
 
 
好了 到这里class就写好了
那么问题来了!
html怎么搞呢
 
3. 页面JS 其实JQuery更方便 这里我直接拉取乐享的,然后修改了一下。
 
页面还有一个增加子菜单的效果,这个用JS解决!
代码直接贴上不多说了 唯一的重点就是一个地方,增加子菜单这里
  //替换parentid的value值为主菜单ID
        for(var i = 0; i <= typedata.length - 1; i++) {
        var cell = row.insertCell(i);
        cell.colSpan = typedata[i][0];
        var tmp = typedata[i][1];
        if(typedata[i][2]) {
            cell.className = typedata[i][2];
        }
        //替换parentid的value值为主菜单ID
        tmp = tmp.replace(/\{(n)\}/g, function($1) {return addrowkey;});  
        tmp = tmp.replace(/\{[0-9]+\}/g, function($1, $2) {return val});    
        cell.innerHTML = tmp;        
    }    
这最后3行代码尤其重要!用正则替换掉增加的节点名称 <input type="hidden" name="new[parentid][]" value="{1}" />这个value="{1}"替换成主菜单ID,
这步非常重要 如果不成功则增删改都会出问题
详细代码如下:
 
<script type="text/JavaScript">   
var rowtypedata = [
[
    [1,‘<input name="new[listsort][]" value="" style=" width:90%" size="3" type="text" class="px" >‘,
 ‘td25‘],
    [1, ‘<input name="new[title][]" value="" size="15" style=" width:90%" type="text" class="px" >‘],
    [1, ‘<input name="new[key][]" value="" size="15" type="text" class="px" style=" width:90%"  > <input type="hidden" name="new[parentid][]" value="0" />‘],
    [1,‘<input class="checkbox" type="checkbox" name="new[isshow][]"  checked="checked"   value="1"  >‘,‘‘],
    [1,‘‘,‘‘]
],
[
    [1,‘<input name="new[listsrot][]" value="" size="3" style=" width:90%"  type="text" class="px" >‘, ‘td25‘],
    [1, ‘<div class=\"board\"><input name="new[title][]" value="" size="15" style=" width:90%"  type="text" class="px" ></div>‘],
    [1, ‘<input name="new[key][]" value="" size="15" style=" width:90%" type="text" class="px" >  <input type="hidden" name="new[parentid][]" value="{1}" />‘] ,
    [1,‘<input class="checkbox" type="checkbox"   checked="checked"  name="new[isshow][]" value="1" >‘,‘‘],
    [1,‘‘,‘‘]
]
];

var addrowdirect = 0;
var addrowkey = 0;
function addrow(obj, type ,val) {
    var table = obj.parentNode.parentNode.parentNode.parentNode.parentNode;
    if(!addrowdirect) {
        var row = table.insertRow(obj.parentNode.parentNode.parentNode.rowIndex);
    } else {
        var row = table.insertRow(obj.parentNode.parentNode.parentNode.rowIndex + 1);
    }
    var typedata = rowtypedata[type];
    for(var i = 0; i <= typedata.length - 1; i++) {
        var cell = row.insertCell(i);
        cell.colSpan = typedata[i][0];
        var tmp = typedata[i][1];
        if(typedata[i][2]) {
            cell.className = typedata[i][2];
        }
        //替换parentid的value值为主菜单ID
        tmp = tmp.replace(/\{(n)\}/g, function($1) {return addrowkey;});
        
        tmp = tmp.replace(/\{[0-9]+\}/g, function($1, $2) {return val});    
        cell.innerHTML = tmp;        
    }
    addrowkey ++;
    addrowdirect = 0;
}

function deleterow(obj) {
    var table = obj.parentNode.parentNode.parentNode.parentNode.parentNode;
    var tr = obj.parentNode.parentNode.parentNode;
    table.deleteRow(tr.rowIndex);
}
function dropmenu(obj){
    showMenu({‘ctrlid‘:obj.id, ‘menuid‘:obj.id + ‘child‘, ‘evt‘:‘mouseover‘});
    $(obj.id + ‘child‘).style.top = (parseInt($(obj.id + ‘child‘).style.top) - Math.max(document.body.scrollTop, document.documentElement.scrollTop)) + ‘px‘;
    if(BROWSER.ie > 6 || !BROWSER.ie) {
        $(obj.id + ‘child‘).style.left = (parseInt($(obj.id + ‘child‘).style.left) - Math.max(document.body.scrollLeft, document.documentElement.scrollLeft)) + ‘px‘;
    }
}
</script>
 
4. 增删改管理
  直接贴代码
  /**
     * 添加主菜单到数据库
     * title     主菜单名称
     * isshow    是否显示
     * key       关键字/URL
     * parentid  是否是一级菜单--0为主菜单
    */        
    public function addMenuToDb(){    
        
        $wx_menu_db = M(‘custom_menu‘);
        $array= array();
        //添加新的数据 -- 重新组合数组
        foreach ($this->_post(‘new‘) as $value){
            foreach ($value as $key=>$val){
                $array[$key][]=$val;
            }
        }
        
        foreach ($array as $v){
            //分别赋值,对应表里的5个字段位
            $data[‘wxid‘]     = $this->wxid;
            $data[‘userid‘]   = $this->userid;
            $data[‘listsort‘] = $v[0];
            $data[‘title‘]    = $v[1];
            $data[‘key‘]      = $v[2];
            $data[‘parentid‘] = $v[3];
            $data[‘isshow‘]   = $v[4];
            if(!empty($data[‘title‘]) && !empty($data[‘key‘])){
                $add = $wx_menu_db->data($data)->add();
            }
        }    
        
        $save = array();
        //更新旧数据
        foreach ($this->_post(‘ps‘) as $ps){
            $temp[‘wxid‘]     = $this->wxid;
            $temp[‘userid‘]   = $this->userid;
            $temp[‘id‘]       = $ps[‘id‘];
            $temp[‘listsort‘] = $ps[‘listsort‘];
            $temp[‘title‘]    = $ps[‘title‘];
            $temp[‘key‘]      = $ps[‘key‘];
            $temp[‘parentid‘] = $ps[‘parentid‘];
            $temp[‘isshow‘]   = $ps[‘isshow‘];
            $save[] = $wx_menu_db->where(array(‘id‘=>$temp[‘id‘]))->data($temp)->save();
        }
        //判断是否有修改过
        foreach($save as $s){
            if($s){
                $a=1;
            }
        }
        if($add || $a){
            $this->success(‘操作成功,正在返回...‘,U(‘CustomMenu/custommenu‘,array(‘wxid‘=>$this->wxid)));
        }else{
            $this->error(‘操作无影响!‘,U(‘CustomMenu/custommenu‘,array(‘wxid‘=>$this->wxid)));
        }
    }
 
这里主要对新增的,编辑过得一次性处理
 
5. 生成微信自定义菜单
说明:运用cURL生成微信自定义菜单
  //从数据库中取出数据    
        $array = $this->selectDb();    
        $arr = array();
        //重组数组
        foreach($array as $val){
            $arr[$val[‘id‘]][‘name‘] = $val[‘title‘];
            $arr[$val[‘id‘]][‘key‘]  = $val[‘key‘];
            if($val[‘sub‘]){
                foreach($val as $v){
                    if(is_array($v)){
                        foreach($v as $k){
                            $arr[$val[‘id‘]][‘sub‘][‘name‘]= $k[‘title‘];
                            $arr[$val[‘id‘]][‘sub‘][‘key‘] = $k[‘key‘];
                        }
                    }
                }
            }
        }
        
        //编写Json数据串
        $js=‘{"button":[‘;
        foreach($arr as $a){
            if(!is_array($a[‘sub‘])){
                $js.=‘{"type":"click",‘;
                $js.=‘"name":"‘.$a[‘name‘].‘",‘;
                $js.=‘"key":"‘.$a[‘key‘].‘"},‘;
            }else{
                $js1.=‘{"name":"‘.$a[‘name‘].‘",‘;
                $js1.=‘"sub_button":[‘;
                foreach($a as $vo){
                    foreach($vo as $o){
                        $js2.=‘{"type":"view",‘;
                        $js2.=‘"name":"‘.$vo[‘name‘].‘",‘;
                        $js2.=‘"url":"‘.$vo[‘key‘].‘"},‘;
                    }
                }
                $js1.=$js2;
            }
        }
        $js.=$js1;
        $js.=‘]}]}‘;
    $url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=".$access_token;
        //发送到微信,接受返回的结果
        $result = $this->httpsRequest($url,$js);
        $r = json_decode($result,trues);
        if($r[‘errcode‘]==0){
            $this->success(‘添加成功!‘,U(‘CustomMenu/custommenu‘,array(‘wxid‘=>$this->wxid)));
        }
        else{
            $this->error(‘添加失败‘);
        }
 
  public function httpsRequest($url,$data = null){
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
         }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }
 
至此微信自定义菜单功能已实现!

微信自定义菜单

上一篇:【Android UI设计与开发】第14期:顶部标题栏(五)两种方式实现仿微信标题栏弹窗效果


下一篇:vue3 axios 前端跨域 调试