项羽的博客

自己选择的路,跪着也要走下去...

小程序地址选择仿美团(附源码)

2019-03-22T07:16:15.png

代码很简单

var city = require('../../utils/city.js');
var app = getApp()
Page({
  data: {
    searchLetter: [],
    showLetter: "",
    winHeight: 0,
    // tHeight: 0,
    // bHeight: 0,
    cityList: [],
    isShowLetter: false,
    scrollTop: 0,//置顶高度
    scrollTopId: '',//置顶id
    city: "上海市",
    hotcityList: [{ cityCode: 110000, city: '北京市' }, { cityCode: 310000, city: '上海市' }, { cityCode: 440100, city: '广州市' }, { cityCode: 440300, city: '深圳市' }, { cityCode: 330100, city: '杭州市' }, { cityCode: 320100, city: '南京市' }, { cityCode: 420100, city: '武汉市' }, { cityCode: 410100, city: '郑州市' }, { cityCode: 120000, city: '天津市' }, { cityCode: 610100, city: '西安市' }, { cityCode: 510100, city: '成都市' }, { cityCode: 500000, city: '重庆市' }]
  },
  onLoad: function () {
    // 生命周期函数--监听页面加载
    var searchLetter = city.searchLetter;
    var cityList = city.cityList();
    var sysInfo = wx.getSystemInfoSync();
    var winHeight = sysInfo.windowHeight;
    var itemH = winHeight / searchLetter.length;
    var tempObj = [];
    for (var i = 0; i < searchLetter.length; i++) {
      var temp = {};
      temp.name = searchLetter[i];
      temp.tHeight = i * itemH;
      temp.bHeight = (i + 1) * itemH;
      tempObj.push(temp)
    }
    this.setData({
      winHeight: winHeight,
      itemH: itemH,
      searchLetter: tempObj,
      cityList: cityList
    })

  },
  onReady: function () {
    // 生命周期函数--监听页面初次渲染完成

  },
  onShow: function () {
    // 生命周期函数--监听页面显示

  },
  onHide: function () {
    // 生命周期函数--监听页面隐藏

  },
  onUnload: function () {
    // 生命周期函数--监听页面卸载

  },
  onPullDownRefresh: function () {
    // 页面相关事件处理函数--监听用户下拉动作

  },
  onReachBottom: function () {
    // 页面上拉触底事件的处理函数

  },
  clickLetter: function (e) {
    console.log(e.currentTarget.dataset.letter)
    var showLetter = e.currentTarget.dataset.letter;
    this.setData({
      showLetter: showLetter,
      isShowLetter: true,
      scrollTopId: showLetter,
    })
    var that = this;
    setTimeout(function () {
      that.setData({
        isShowLetter: false
      })
    }, 1000)
  },
  //选择城市
  bindCity: function (e) {
    console.log("bindCity")
    this.setData({ city: e.currentTarget.dataset.city })
  },
  //选择热门城市
  bindHotCity: function (e) {
    console.log("bindHotCity")
    this.setData({
      city: e.currentTarget.dataset.city
    })
  },
  //点击热门城市回到顶部
  hotCity: function () {
    this.setData({
      scrollTop: 0,
    })
  }
})

Git源码下载

阅读全文

Javascript控制页面物理返回事件处理

点击物理返回键.关闭窗口

pushHistory();
window.addEventListener("popstate", function(e) {
    //alert("我监听到了浏览器的返回按钮事件啦");//根据自己的需求实现自己的功能
    //alert('guanbi');
    WeixinJSBridge.call('closeWindow');
    if (typeof(WeixinJSBridge) != "undefined") {
        WeixinJSBridge.call('closeWindow');
    } else {
        if (navigator.userAgent.indexOf("MSIE") > 0) {
            if (navigator.userAgent.indexOf("MSIE 6.0") > 0) {
                window.opener = null;
                window.close();
            } else {
                window.open('', '_top');
                window.top.close();
            }
        } else if (navigator.userAgent.indexOf("Firefox") > 0) {
            window.location.href = 'about:blank ';
            //window.history.go(-2);  
        } else {
            window.opener = null;
            window.open('', '_self', '');
            window.close();
        }
    }
}, false);
window.onbeforeunload = function() {
    return;
}
function pushHistory() {
    var state = {
        title: "title",
        url: ""
    };
    window.history.pushState(state, "title", "");
}

点击物理返回键,返回到指定页面

window.addEventListener("popstate", function(e) {
    window.location.href="{:url('sdns/index/index')}";
}, false);
function pushHistory() { 
    var state = { 
        title: "title", 
        url: "#"
    }; 
    window.history.pushState(null,null, "#"); 
}

禁用物理返回键

XBack = {};
(function(XBack) {
    XBack.STATE = 'x - back';
    XBack.element;
    XBack.onPopState = function(event) {
        event.state === XBack.STATE && XBack.fire();
        XBack.record(XBack.STATE); //初始化事件时,push一下
    };
    XBack.record = function(state) {
        history.pushState(state, null, location.href);
    };
    XBack.fire = function() {
        var event = document.createEvent('Events');
        event.initEvent(XBack.STATE, false, false);
        XBack.element.dispatchEvent(event);
    };
    XBack.listen = function(listener) {
        XBack.element.addEventListener(XBack.STATE, listener, false);
    };
    XBack.init = function() {
        XBack.element = document.createElement('span');
        window.addEventListener('popstate', XBack.onPopState);
        XBack.record(XBack.STATE);
    };
})(XBack); // 引入这段js文件
XBack.init();
XBack.listen(function() {});

禁止返回并给个提示

pushHistory(); 
window.addEventListener("popstate", function(e) { 
    popTip("禁止返回");
    XBack = {};
    (function(XBack) {
        XBack.STATE = 'x - back';
        XBack.element;
        XBack.onPopState = function(event) {
            event.state === XBack.STATE && XBack.fire();
            XBack.record(XBack.STATE); //初始化事件时,push一下
        };
        XBack.record = function(state) {
            history.pushState(state, null, location.href);
        };
        XBack.fire = function() {
            var event = document.createEvent('Events');
            event.initEvent(XBack.STATE, false, false);
            XBack.element.dispatchEvent(event);
        };
        XBack.listen = function(listener) {
            XBack.element.addEventListener(XBack.STATE, listener, false);
        };
        XBack.init = function() {
            XBack.element = document.createElement('span');
            window.addEventListener('popstate', XBack.onPopState);
            XBack.record(XBack.STATE);
        };
    })(XBack); // 引入这段js文件
    XBack.init();
    XBack.listen(function() {});
}, false);
function pushHistory() { 
    var state = { 
        title: "title", 
        url: "#"
    }; 
    window.history.pushState(null,null, "#"); 
}
阅读全文

VisualSVN项目管理技巧

第一步:找一台电脑,内存足够大,用来搭建局域网svn主机

安装VisualSVN教程:
https://jingyan.baidu.com/article/870c6fc36a31d0b03fe4be3f.html

汉化版svn下载
http://www.mycodes.net/70/1544.htm

2019-03-18T06:29:18.png

第二步:在VisualSVN里面选择Users创建所有开发人员的账号密码,用文本记录好
第三步:创建对应的项目分组,比如说我要创建一个电商的项目分组,可以直接创建对应的电商名称简写,勾选相关开发人员到对应的分组即可。
第四步:点击Reositories 创建对应的项目名称,可以用中文命名,创建项目的时候就可以直接勾选项目权限分组,切记千万别允许所有人访问。
1)第一步
2019-03-18T06:29:28.png
2)第二步:
2019-03-18T06:29:34.png
3)第三步:
2019-03-18T06:29:39.png
4)第四步:
2019-03-18T06:29:46.png
5)第五步:
2019-03-18T06:36:01.png
6)第六步:
2019-03-18T06:34:51.png

在每个项目下面分别有trunk跟tags两个目录。
Trunk目录为开发目录,tags目录为稳定的项目版本目录。下面分别对这两个目录的格式做一下规范。

上面就是一个完整项目的所有步骤,以及目录结构,每一个目录都可以单独设置权限,只有tags目录有最高管理权限,开发人员只有trunk目录的权限,项目经理或者项目负责人才有tags的权限,一旦项目结束,删除对应的开发人员的目录权限。
Db目录放置的是可以直接执行的sql文件,如果项目sql文件过大,需要另附上说明文档讲明导入方案。
Doc目录是项目相关的所有文件,包括线上线下项目安装运行的的详细步骤,以及psd图,项目确认函,功能表文档。
Html 静态html文件目录
Project 源码目录
MiniProgram 小程序源码目录

Tags里面的目录结构也是一样的,含义也是一样的。最外层包了一个版本号,主要是方便项目回退以及代码版本管理。

做这个的目的也是为了提高项目质量,严格做好codereview工作。

阅读全文

TP5使用js+jquery实现无限极联动

今天工作需要写树形的联动,于是写了个可扩展的无限极联动下拉选项

代码写的比较凌乱 先mark有空再整理

2019-03-09T14:13:33.png
2019-03-09T14:13:53.png
页面代码 用的SMARTY

<div id="select" >
    <select name="category_1" id="category_1" onChange="change('category_1');">
        <option>请选择分类</option>
        <!-- {foreach from=$galleryCategory item=category} -->
            <option value="{$category.id}">{$category.category_name}</option>
        <!-- {/foreach} -->    
    </select>
</div>

$galleryCategory 去数据的PHP代码为

$sql = " select * from yl_gallery_category where pid = 0"; 
$galleryCategory = $db->query($sql); 
$smarty->assign("galleryCategory",$galleryCategory); 

用的原生态代码 还是比较容易理解的
然后就是关键的 JS代码了

function change(val) {
    var str = val; //select的id
    var num; //当前级数
    var id; // 分类id
    num = str.substr(9, 10);
    //alert(num);
    var nownum = parseInt(num) + 1; // 将字符串转换为数字
    id = $("#" + str + "").val();
    var r = /^[1-9]+[0-9]*]*$/;  //正整数
    if (!r.test(id)) {
        //清空过时的选项
        $("select").each(function(index) {
            if (index + 1 > num) {
                $(this).remove();
            }
        })

        return false;
    }
    var url = 'gallery.php?act=category&pid=' + id;
    $.ajax({
        type: "POST",
        cache: false,
        url: url,
        datatype: 'json',
        timeout: 3000,
        success: function(result) {
            if (result != 0) {
                var html = "<select name=category_" + nownum + "     id=category_" + nownum + "  onChange=change('category_" + nownum + "'); >";
                html += "<option>请选择分类 </option>";
                var datas = eval(result);
                $.each(datas,
                function(i, val) {
                    html += "<option value='" + val.id + "' >" + val.category_name + "</option>";
                });
                html += "</select>";

                //清空过时的选项
                $("select").each(function(index) {
                    if (index + 1 > num) {
                        $(this).remove();
                    }
                })

                $("#select").append(html);
            } else {           //清空过时的选项
                $("select").each(function(index) {
                    if (index + 1 > num) {
                        $(this).remove();
                    }
                })       
            }

        },
        error: false
    });

}

AJAX 取数据的PHP代码

$sql = " select * from yl_gallery_category where pid = " .$pid; 
    $res = $db->query($sql); 
    if (empty($res)) { 
        $res = 0; 
    } 
    echo json_encode($res); 
阅读全文
none

小程序推广分享带参数二维码生成

一、二维码生成类库

<?php
/**
 * Created by PhpStorm.
 * User: 项羽
 * Date: 2019/1/22
 * Time: 22:55
 * 生成小程序码接口地址    https://developers.weixin.qq.com/miniprogram/dev/api/getWXACodeUnlimit.html
 */

namespace app\api\controller;

class Spreadcode
{
//    获取accesstoken
    public function getAccesstoken(){

        $appid = '';                     /*小程序appid*/
        $srcret = '';      /*小程序秘钥*/

        $tokenUrl="https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$srcret;
        $getArr=array();
        $tokenArr=json_decode($this->send_post($tokenUrl,$getArr,"GET"));

        $access_token=$tokenArr->access_token;

        return $access_token;
    }

    public function send_post($url, $post_data,$method='POST') {
        $postdata = http_build_query($post_data);
        $options = array(
            'http' => array(
                'method' => $method, //or GET
                'header' => 'Content-type:application/x-www-form-urlencoded',
                'content' => $postdata,
                'timeout' => 15 * 60 // 超时时间(单位:s)
            )
        );
        $context = stream_context_create($options);
        $result = file_get_contents($url, false, $context);
        return $result;
    }



    public function api_notice_increment($url, $data){
        $ch = curl_init();
        $header=array('Accept-Language:zh-CN','x-appkey:114816004000028','x-apsignature:933931F9124593865313864503D477035C0F6A0C551804320036A2A1C5DF38297C9A4D30BB1714EC53214BD92112FB31B4A6FAB466EEF245710CC83D840D410A7592D262B09D0A5D0FE3A2295A81F32D4C75EBD65FA846004A42248B096EDE2FEE84EDEBEBEC321C237D99483AB51235FCB900AD501C07A9CAD2F415C36DED82','x-apversion:1.0','Content-Type:application/x-www-form-urlencoded','Accept-Charset: utf-8','Accept:application/json','X-APFormat:json');
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
        curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $tmpInfo = curl_exec($ch);
        //         var_dump($tmpInfo);
        //        exit;
        if (curl_errno($ch)) {
            return false;
        }else{
            // var_dump($tmpInfo);
            return $tmpInfo;
        }
    }

    /*上面生成的是数量限制10万的二维码,下面重写数量不限制的码*/
    /*getWXACodeUnlimit*/
    /*码一,圆形的小程序二维码,数量限制一分钟五千条*/
    /*45009    调用分钟频率受限(目前5000次/分钟,会调整),如需大量小程序码,建议预生成。
    41030    所传page页面不存在,或者小程序没有发布*/
    public function mpcode($page,$cardid){
        //参数
//        $postdata['scene']="nidaodaodao";
        $postdata['scene']=$cardid;
        // 宽度
        $postdata['width']=430;
        // 页面
        $postdata['page']=$page;
//        $postdata['page']="pages/postcard/postcard";
        // 线条颜色
        $postdata['auto_color']=false;
        //auto_color 为 false 时生效
        $postdata['line_color']=['r'=>'0','g'=>'0','b'=>'0'];
        // 是否有底色为true时是透明的
        $postdata['is_hyaline']=true;

        $post_data = json_encode($postdata);
        $access_token=$this->getAccesstoken();
        $url="https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=".$access_token;
        $result=$this->api_notice_increment($url,$post_data);

        $data='image/png;base64,'.base64_encode($result);
        return $data;
//        echo '<img src="data:'.$data.'">';
    }


    /*码二,正方形的二维码,数量限制调用十万条*/
    public function qrcodes(){
        $path="pages/postcard/postcard";
        // 宽度
        $postdata['width']=430;
        // 页面
        $postdata['path']=$path;
        $post_data = json_encode($postdata);

        $access_token=$this->getAccesstoken();
        $url="https://api.weixin.qq.com/cgi-bin/wxaapp/createwxaqrcode?access_token=".$access_token;
        $result=$this->api_notice_increment($url,$post_data);

        $data='image/png;base64,'.base64_encode($result);
        echo '<img src="data:'.$data.'">';
    }


}

二、php调用方法

$page='pages/postcard/postcard';
$cardid="10";
$class = new \app\api\controller\Spreadcode();
$mpcodeimg=$class->mpcode($page,$cardid);
$dataret['mpcodeimg']=$mpcodeimg;
$this->assign('retdata',$dataret);

三、前端页面调用

<img src="data:{$retdata['mpcodeimg']}" />

阅读全文