微信小程序+php 授权登陆查看，完整代码
先来看效果图实现流程：1、授权登陆按钮和正文信息放到了同一个页面，未授权的时候显示登陆按钮，已授权的时候隐藏登陆按钮，显示正文信息，当然也可以授权和正文分开成两个页面，在授权页面的onload里判断是否已授权，若已授权就直接跳转正文的页面。这里只说授权按钮和正文在同一页面的情况。2、在onload里先判断是否已授权，如果已授权，就隐藏授权登陆按钮，显示正文信息，如果没有授权，显示授权登陆按钮。3、前端使用button的open-type="getUserInfo"来操作，点击授权按钮之后，“e”中会携带userInfo，用户的基本信息（和使用wx.getUserInfo接口获取的数据一样，所以我是在"e"里面直接取的，没有调用wx.getUserInfo接口）4、使用wx.login接口获取登陆凭证code，使用code去后解密换取openid，传输code的时候带上第3步获取的用户信息一块发送给后台解密（也可以不携带，携带的目的是为了验证签名，这样安全一些，不验证也可以）5、后台解密使用的是“auth.code2Session”接口，解密用到的SDK下载地址“https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/signature.html”。5、后台解密之后（后台语言用的是php），会返回openid等敏感信息，就还可以把这些信息存起来了。6、获取授权成功之后，再隐藏授权登陆按钮，显示正文信息。7、如果用户点击拒绝授权，提示引导用户再次授权。注意，要考虑到授权失败的情况以下是详细代码wxml<view wx:if="{{isHide}}"> <view wx:if="{{canIUse}}" > <view class='header'> <image src='/images/icon/wx_login.png'></image> </view> <view class='content'> <view>申请获取以下权限</view> <text>获得你的公开信息(昵称，头像等)</text> </view> 授权登录 </view> <view wx:else>请升级微信版本</view> </view> <view wx:else> <view>我的首页内容</view> </view>wxss.header { margin: 90rpx 0 90rpx 50rpx; border-bottom: 1px solid #ccc; text-align: center; width: 650rpx; height: 300rpx; line-height: 450rpx; } .header image { width: 200rpx; height: 200rpx; } .content { margin-left: 50rpx; margin-bottom: 90rpx; } .content text { display: block; color: #9d9d9d; margin-top: 40rpx; } .bottom { border-radius: 80rpx; margin: 70rpx 50rpx; font-size: 35rpx; }js// pages/test1/test1.js var app = getApp(); Page({ /** * 页面的初始数据 */ data: { //判断小程序的API，回调，参数，组件等是否在当前版本可用。 canIUse: wx.canIUse('button.open-type.getUserInfo'), isHide: false }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { var that = this; // 查看是否授权 wx.getSetting({ success: function (res) { if (!res.authSetting['scope.userInfo']) { // 还未授权，显示授权按钮 that.setData({ isHide: true }); } else { // 已授权，隐藏授权按钮，显示正文 that.setData({ isHide: false }); } } }) }, //授权登陆按钮 bindGetUserInfo: function (e) { var that = this; console.log(e) if (e.detail.userInfo) { //用户授权登陆，并跳转首页 // that.getOpenid() wx.login({ success: function (res) { // 请求自己后台获取用户openid wx.request({ url: app.domain + 'teacherapi/Wx_Decode/WxDecode', method: 'POST', header: { 'content-type': 'application/x-www-form-urlencoded' }, data: { encryptedData: e.detail.encryptedData, signature: e.detail.signature, rawData: e.detail.rawData, iv: e.detail.iv, code: res.code }, success: function (res_user) { if (res_user.data.status == 0) { var data = JSON.parse(res_user.data.msg) //json转对象 //授权成功返回的数据，根据自己需求操作 console.log(data) //授权成功后，隐藏授权按钮，显示正文 that.setData({ isHide: false }); } }, fail: function () { that.showModal('获取授权信息失败') } }) } }) } else { //用户按了拒绝授权按钮，提示引导授权 that.showModal('请授权后使用小程序') } }, //未授权弹窗 showModal: function (e) { wx.showModal({ title: '提示', content: e, showCancel: false, confirmText: '返回授权', success: function (res) { if (res.confirm) { console.log('用户点击了“返回授权”') } } }) }, })PHP<?php namespace app\teacherapi\controller; use think\Controller; /** * @date: 2018-12 * 微信操作类 */ class WxDecode extends Controller { public function httpGet($url) { $curl = curl_init(); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_TIMEOUT, 500); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); curl_setopt($curl, CURLOPT_URL, $url); $res = curl_exec($curl); curl_close($curl); return $res; } /** * @author: zxf * @date: 2018-12-08 * @description: 解密微信用户敏感数据 * @return array */ public function WxDecode() { // 接收参数 $data = request() -> param(); // 引入解密文件 在微信小程序开发文档下载 vendor('wx.WXBizDataCrypt'); vendor('wx.ErrorCode'); $appid = config('TESTPPID'); $appsecret = config('TESTSECREET'); $grant_type = "authorization_code"; //授权（必填） $code = $data['code']; //有效期5分钟 登录会话 $encryptedData=$data['encryptedData']; $iv = $data['iv']; $signature = $data['signature']; $rawData = $data['rawData']; // 拼接url $url = "https://api.weixin.qq.com/sns/jscode2session?"."appid=".$appid."&secret=".$appsecret."&js_code=".$code."&grant_type=".$grant_type; $res = json_decode($this->httpGet($url),true); $sessionKey = $res['session_key']; //取出json里对应的值 $signature2 = sha1(htmlspecialchars_decode($rawData).$sessionKey); // 验证签名 if ($signature2 !== $signature){ return json("验签失败"); } // 获取解密后的数据 $pc = new \WXBizDataCrypt($appid, $sessionKey); $errCode = $pc->decryptData($encryptedData, $iv, $data ); if ($errCode == 0) { return return_succ($data); } else { return return_error($errCode); } } }
微信小程序搜索功能(附：小程序前端+PHP后端)
这篇文章主要介绍了微信小程序搜索功能(附：小程序前端+PHP后端)，小编觉得挺不错的，现在分享给大家，也给大家做个参考。一起跟随小编过来看看吧开发需求微信小程序已经是非常火了，而且学习也比较容易，但是对于初学者来说还是一件比较伤脑筋的事，接下来给大家分享一下小程序搜索的思路。流程1、表单（输入框、提交按钮、提交的name值)2、接收表单数据（js获取表单name=keyword的值）3、通过wx.request向服务器后端发起请求查询数据库4、返回JSON格式的数据给小程序，js解析渲染到小程序前端展示界面代码index.wxml <view class="title">小程序搜索</view> <view class="search_con"> 搜索 </view> <view wx:for="{{re}}" wx:key="re" class="search_result"> <view class="empty">{{item.empty}}</view> <view class="resname">{{item.resname}}</view> <view class="noresult">{{item.noresult}}</view> </view>index.js其中里面的http://localhost/search.php?keyword=是服务器后端接口，用于接收小程序传过去的关键词的，下面会有这个后端PHP文件。const app = getApp() Page({ data: {}, //执行点击事件 formSubmit: function (e) { //声明当天执行的 var that = this; //获取表单所有name=keyword的值 var formData = e.detail.value.keyword; //显示搜索中的提示 wx.showLoading({ title: '搜索中', icon: 'loading' }) //向搜索后端服务器发起请求 wx.request({ //URL url: 'http://localhost/search.php?keyword=' + formData, //发送的数据 data: formData, //请求的数据时JSON格式 header: { 'Content-Type':'application/json' }, //请求成功 success: function (res) { //控制台打印（开发调试用） console.log(res.data) //把所有结果存进一个名为re的数组 that.setData({ re: res.data, }) //搜索成功后，隐藏搜索中的提示 wx.hideLoading(); } }) }, })index.wxss/* 搜索样式 */ .title{ text-align: center; font-size: 20px; font-weight: bold; } .search_con{ width: 80%; margin:20px auto; } .search_con .search_input{ border: 1px solid rgb(214, 211, 211); height: 45px; border-radius: 100px; font-size: 17px; padding-left: 15px;/*此处要用padding-left才可以把光标往右移动15像素，不可以用text-indent*/ color: #333; } .search_con .search_btn{ margin-top: 15px; width: 100%; height: 45px; background: #56b273; color: #fff; border-radius: 100px; } .search_result{ width: 80%; margin:10px auto; } .search_result .empty{ text-align: center; color: #f00; font-size: 15px; } .search_result .noresult{ text-align: center; color: #666; font-size: 15px; } .search_result .resname{ text-align: left; color: #333; font-size: 15px; }服务端search.php<?php header('Content-Type:application/json'); //获取表单数据 $keyword1 = $_GET["keyword"]; //过滤表单空格 $keyword2 = trim($keyword1); //当表单提交空白数据时 if(empty($keyword2)){ //构建数组 $arr = array( "empty" => "表单不能为空" ); //把数组转换为json $data = json_encode($arr); echo "[$data]"; }else{ //过滤表单特殊字符 $replace = array('!','@','#','$','%','^','&','*','(',')','_','-','+','=','{','}','[',']',';',':','"','<','>','?','/','|'); $keyword3 = str_replace($replace, '', $keyword2); // 连接数据库 $con = mysql_connect("数据库地址","数据库账号","数据库密码"); if (!$con){die('Could not connect: ' . mysql_error());} mysql_select_db("数据库名", $con); mysql_query("SET NAMES UTF8"); //查询数据库 $result = mysql_query("SELECT * FROM 表名 WHERE 需要查询的字段 like '%$keyword3%' ORDER BY ID DESC"); $results = array(); //查询数据库是否存在这条记录 $exist = mysql_num_rows($result); if ($exist) { //遍历输出 while ($row = mysql_fetch_assoc($result)){ $results[] = $row; } //输出JSON echo json_encode($results); //当查询无结果的时候 }else{ //构建数组 $arr = array( "noresult" => "暂无结果" ); //把数组转换为json $data = json_encode($arr); echo "[$data]"; } //断开数据库连接 mysql_close($con); } ?>服务端也是非常简单的，大家自己把服务端写好一点，毕竟安全和效率是很重要的。演示
微信小程序开发搜索功能实现(前端+后端+数据库)
这篇文章主要介绍了微信小程序开发搜索功能实现，文中通过示例代码介绍的非常详细，对大家的学习或者工作具有一定的参考学习价值，需要的朋友们下面随着小编来一起学习学习吧界面比较丑，主要实现逻辑...超级简单的界面，表单，提交按钮，搜索结果展示区域...下面是index.wxml 搜索 <view>搜索结果</view> <view wx:for="{{re}}" wx:key="re"> <view style='color:#f00;'>{{item.result}}</view> <view style='color:green;'>{{item.title}}</view> </view>跟前端差不多，form表单要加一个bindsubmit="formSubmit"接着就是index.js//index.js //获取应用实例 const app = getApp() Page({ /** * 页面的初始数据 */ data: { result:'', state:'' }, formSubmit: function (e) { var that = this; var formData = e.detail.value.id; //获取表单所有name=id的值 wx.request({ url: 'http://localhost/2018-5-24/search.php?id=' + formData, data: formData, header: { 'Content-Type': 'application/json' }, success: function (res) { console.log(res.data) that.setData({ re: res.data, }) wx.showToast({ title: '已提交', icon: 'success', duration: 2000 }) } }) }, })这个很容易理解var that = this; var formData = e.detail.value.id; 先把表单name=id的值获得，然后赋给formData这个变量 然后，在url进行拼接，用+号拼接这个变量即可...然后，提交到接口，后端进行处理即可，后端处理后返回json格式的数据，然后通过that.setData({ re: res.data, })进行打印在控制台，你也可以渲染在index.wxml为了方便大家研究，我把后端的php源码也贴出来。search.php<?php header("Content-type:text/json;charset=utf8"); //定义参数 $id = $_GET["id"]; //表单验证 if(empty($id)){ echo "[{\"result\":\"表单为空...\"}]"; }else{ //连接数据库 $con = mysql_connect("数据库链接","账号","密码"); //设置数据库字符集 mysql_query("SET NAMES UTF8"); //查询数据库 mysql_select_db("数据库名", $con); $result = mysql_query("SELECT * FROM test WHERE id like '%$id%'"); $results = array(); while($row = mysql_fetch_assoc($result)) { $results[] = $row; // 将数组转成json格式 echo json_encode($results); } //关闭数据库连接 mysql_close($con); } ?>数据库表名为test,里面一共有两个字段，一个是id，一个是title所以index.wxml里面有两个值<view wx:for="{{re}}" wx:key="re"> <view style='color:#f00;'>{{item.result}}</view> <view style='color:green;'>{{item.title}}</view> </view>wx:for="{{re}}"指的是循环数组，在js代码中，我们把所有服务端取得的数据，存进了re的数组然后，{{item.result}}指的是服务端返回表单为空的结果。{{item.title}}返回的是搜索结果，这个结合你的数据库吧，你想展示什么结果，你就把title改成你数据库的相关字段。到此这篇关于微信小程序开发搜索功能实现的文章就介绍到这了,更多相关小程序搜索功能内容请搜索轩宇网以前的文章或继续浏览下面的相关文章希望大家以后多多支持轩宇网！
微信小程序实现slideUp、slideDown滑动效果及点击空白隐藏功能示例
这篇文章主要介绍了微信小程序实现slideUp、slideDown滑动效果及点击空白隐藏功能,涉及微信小程序事件响应、页面元素属性动态操作实现滑动与蒙层功能相关技巧与注意事项,需要的朋友可以参考下本文实例讲述了微信小程序实现slideUp、slideDown滑动效果及点击空白隐藏功能。分享给大家供大家参考，具体如下：怎样实现jq中的slideUp或者slideDown这种动画效果呢，我的思路是用css3的transform: translateY() 属性，给需要动画的元素添加上一个动画class。先上效果图：1.蒙层的结构： <view class='list-fix' wx:if="{{mengShow}}" bindtap='outbtn'> <view class='in-list {{aniStyle?"slideup":"slidedown"}}' catchtap='inbtn'> <view class='in-content'> <text>已选商品（1）</text> <text class='iconfont icon-6'>清空购物车</text> </view> <view class='cho-list' wx:for="{{chooseList}}" wx:key=""> <view class='listName'>{{item.Cname}}</view> <view class='listPrice'>￥{{item.Cprice}}</view> <view class='opBtn'> <view class='com-btn cuts' >-</view> <view class='com-num'>{{item.Cnum}}</view> <view class='com-btn add' >+</view> </view> </view> </view> </view>注意：三元运算符里的slideup和slidedown一定要加上引号2.蒙层的其它样式自己写。最主要的是slideup和slidedown的动画效果的样式：@keyframes slidedown { from { transform: translateY(0); } to { transform: translateY(100%); } } .slidedown { animation: slidedown 0.5s linear ; } .slideup { animation: slideup 0.5s linear ; } @keyframes slideup { from { transform: translateY(100%); } to { transform: translateY(0); } }其它的样式：list-fix是fixed定位，而in-list是absolute定位。需要注意的一点是：做的时候，是从Y轴100%的位置处即最底部开始运动或是从0到100%，所以要设置z-index，才能实现在底部运动起来的时候或者回到100%即底部的时候，蒙层浮在“确认下单”这整个结构的下面。即“确认下单”这整个结构的z-index要大于蒙层的z-index。3.jspage({ data: { mengShow:false,//蒙层的显示与否 aniStyle:true, //动画效果，默认slideup }, //蒙层的显示 showMeng:function(e){ //这是“确认下单”这整个购物车导航栏的点击事件 this.setData({ mengShow:true, //蒙层显示 aniStyle:true//设置动画效果为slideup }) }, outbtn:function(e){ //这是list-fix的点击事件，给它绑定事件，是为了实现点击其它地方隐藏蒙层的效果 var that=this; this.setData({ aniStyle:false//设置动画效果为slidedown }) setTimeout(function(){ //延时设置蒙层的隐藏，这个定时器的时间，就是slidedown在css动画里设置的时间，这样就能实现slidedown动画完成后，蒙层才消失的效果。不设置定时器会导致动画效果看不见 that.setData({ mengShow: false }) },500) }, inbtn:function(e){ //这个事件必须有，就算不做什么事情也要写上去，因为这个事件是为了防止事件冒泡，导致点击in-list这里面的元素时，点击事件冒泡到list-fix触发它的slidedown事件。 console.log("in") }, })这样就能实现slidedown和slideup，点击其它地方隐藏某元素的功能了。总结：1.防止冒泡的点击事件：catchtap=""2.点击父元素除子元素以外的其它地方隐藏父元素的方法：父元素绑定一个点击隐藏事件，然后子元素绑定catchtap这种能阻止冒泡的事件3.巧用定时器设置属性值，可达到类似上面执行一个动画之后再执行另外一个动画的方法。希望本文所述对大家微信小程序开发有所帮助，也希望大家继续支持轩宇网。
这篇文章主要为大家详细介绍了微信小程序实现订单倒计时，具有一定的参考价值，感兴趣的小伙伴们可以参考一下本文实例为大家分享了微信小程序实现订单倒计时的具体代码，供大家参考，具体内容如下之前在做一个有拼团功能项目的时候遇到过倒计时的问题，由于当时技术不熟在这方面耽搁了好些时间，所以这里整理出来希望能为后来人提供些许启发。1.实现思路求出发起拼团时间与拼团结束时间的时间差再将时间差格式化得到我们想要的格式如：时间每秒递减使用了 setTimeout(this.setTimeCount,1000);这个函数，让这个函数每隔一秒执行一次。效果图：2.实现中的难点若是要实现单个倒计时如60s发送验证码倒不是很难，难的是多条倒计时。不同的订单下单时间是不一样的时间差time也就不一样，所以当初在这卡了很久，后来想通一切才觉得原来如此。实现方法1：是后台计算出时间前端直接获取时间差，当时为了不影响项目进度我们用的就是这个方法，真是苦了那个些后台的兄弟还得迁就我这个菜鸟。获取这个时间差time后我们就可以将它处理后放入数组循环。这样做的好处是前端不用将time作为一个属性添加到原数组中。index.wxml<view class="item">单条倒计时:{{time}}</view> <view class="item">多条倒计时</view> <view class='no'>暂无任何记录</view> <view class="content"> <block wx:for="{{listData}}"wx:key="idx" wx:for-item="item" wx:for-index="{{idx}}"> <view class="tip {{item.time<=0?'isShow':''}}"> <view class="dis"> <view class='dis_time left'>剩余时间：{{item.countDown}}</view> </view> </view> </block> </view>index.wxsspage{ height:100%; background: #fff; position: relative; } .item{ height:4%; background: #fff; text-align: center; } .content{ border:1px solid rgb(167, 159, 159); background: #F6F8F8; margin-bottom:300rpx; border-bottom: none; } .no{ text-align: center; position: absolute; top:8%; z-index: -11; } .tip{ position: relative; background: #fff; width:100%; height:100rpx; margin-bottom: 5rpx; padding:20rpx 0; border-bottom: 1px solid gainsboro; } .isShow{ display:none; } .dis{ width:100%; font-size: 35rpx; color:#009FE5; box-sizing: border-box; } .dis_time{ width:50%; }index.jsPage({ /** * 页面的初始数据 */ data: { pingData: [ { "id": "1", "icon": "../../images/image2.jpg", "number": "20", "pingTime": "2019-3-28 23:30:00", "time": "55267", "showList": "false", }, { "id": "2", "icon": "../../images/image3.jpg", "number": "4566", "pingTime": "2019-3-28 12:30:00", "time": "58934", "showList": "false", }, { "id": "3", "icon": "../../images/image2.jpg", "number": "20", "pingTime": "2019-3-28 08:30:00", "time": "555234", "showList": "false", } ], time:"30" }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { var that = this that.setData({ listData: that.data.pingData }) that.setCountDown(); that.setTimeCount(); }, /** * 60s倒计时 */ setTimeCount:function(){ let time=this.data.time time--; if (time <= 0) { time = 0; } this.setData({ time:time }) setTimeout(this.setTimeCount,1000); }, /** * 倒计时 */ setCountDown: function () { let time = 1000; let { listData } = this.data; let list = listData.map((v, i) => { if (v.time <= 0) { v.time = 0; } let formatTime = this.getFormat(v.time); v.time -= time; v.countDown = `${formatTime.hh}:${formatTime.mm}:${formatTime.ss}`; return v; }) this.setData({ listData: list }); setTimeout(this.setCountDown, time); }, /** * 格式化时间 */ getFormat: function (msec) { let ss = parseInt(msec / 1000); let ms = parseInt(msec % 1000); let mm = 0; let hh = 0; if (ss > 60) { mm = parseInt(ss / 60); ss = parseInt(ss % 60); if (mm > 60) { hh = parseInt(mm / 60); mm = parseInt(mm % 60); } } ss = ss > 9 ? ss : `0${ss}`; mm = mm > 9 ? mm : `0${mm}`; hh = hh > 9 ? hh : `0${hh}`; return { ss, mm, hh }; } })实现方法2：本着不想做菜鸟的心情，我在项目完成后由研究了下当初未完成的方法，即前端计算出时间差并将时间差数组作为原数组的属性加入循环遍历。当初一直不知如何在原数组中再添加一个数组作为它的一个属性。在之前的基础上将time时间差作为一个属性放到原数组中关键代码如下：var pinData = that.data.pingData for (var i = 0; i < pinData.length;i++){ console.log("计算出长度为" + pinData.length) var endtime = that.data.pingData[i].pingTime console.log("计算出长度为" + endtime) that.queryTime(endtime) var time ="pingData["+i+"].time" that.setData({ [time]:that.queryTime(endtime), listData:pinData }) }新增计算时间差的方法：queryTime:function(pintime){ var start_date = new Date(); var end_date = new Date(pintime.replace(/-/g, "/")); var days = end_date.getTime() - start_date.getTime(); console.log("获取到时间差" + days) return days; }之前困惑我的地方就是如何将时间差这个数组添加到原来的数组中，现在想想思路清晰，曾经的难题也不过尔尔。index.js方法二修改后的代码Page({ /** * 页面的初始数据 */ data: { pingData: [ { "id": "1", "icon": "../../images/image2.jpg", "number": "20", "pingTime": "2019-4-15 23:30:00", "time": "55267", "showList": "false", }, { "id": "2", "icon": "../../images/image3.jpg", "number": "4566", "pingTime": "2019-4-13 12:30:00", "time": "58934", "showList": "false", }, { "id": "3", "icon": "../../images/image2.jpg", "number": "20", "pingTime": "2019-4-13 08:30:00", "time": "555234", "showList": "false", } ], time:"60" }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { var that = this var pinData = that.data.pingData for (var i = 0; i < pinData.length;i++){ console.log("计算出长度为" + pinData.length) var endtime = that.data.pingData[i].pingTime console.log("计算出长度为" + endtime) that.queryTime(endtime) var time ="pingData["+i+"].time" that.setData({ [time]:that.queryTime(endtime), listData:pinData }) } that.setCountDown(); that.setTimeCount(); }, /** * 60s倒计时 */ setTimeCount:function(){ let time=this.data.time time--; if (time <= 0) { time = 0; } this.setData({ time:time }) setTimeout(this.setTimeCount,1000); }, /** * 倒计时 */ setCountDown: function () { let time = 1000; let { listData } = this.data; let list = listData.map((v, i) => { if (v.time <= 0) { v.time = 0; } let formatTime = this.getFormat(v.time); v.time -= time; v.countDown = `${formatTime.hh}:${formatTime.mm}:${formatTime.ss}`; return v; }) this.setData({ listData: list }); setTimeout(this.setCountDown, time); }, /** * 格式化时间 */ getFormat: function (msec) { let ss = parseInt(msec / 1000); let ms = parseInt(msec % 1000); let mm = 0; let hh = 0; if (ss > 60) { mm = parseInt(ss / 60); ss = parseInt(ss % 60); if (mm > 60) { hh = parseInt(mm / 60); mm = parseInt(mm % 60); } } ss = ss > 9 ? ss : `0${ss}`; mm = mm > 9 ? mm : `0${mm}`; hh = hh > 9 ? hh : `0${hh}`; return { ss, mm, hh }; }, queryTime:function(pintime){ var start_date = new Date(); var end_date = new Date(pintime.replace(/-/g, "/")); var days = end_date.getTime() - start_date.getTime(); console.log("获取到时间差" + days) return days; } })以上就是本文的全部内容，希望对大家的学习有所帮助，也希望大家多多支持轩宇网。原文链接：https://blog.csdn.net/JY185445/article/details/89267461
微信小程序发布新版本时自动提示用户更新的方法
这篇文章主要介绍了微信小程序发布新版本时自动提示用户更新的方法，文中通过示例代码介绍的非常详细，对大家学习或者使用小程序具有一定的参考学习价值，需要的朋友们下面来一起学习学习吧如图，当小程序发布新的版本后，用户如果之前访问过该小程序，通过已打开的小程序进入（未手动删除），则会弹出这个提示，提醒用户更新新的版本。用户点击确定就可以自动重启更新，点击取消则关闭弹窗，不再更新。官方给的示例代码：const updateManager = wx.getUpdateManager() updateManager.onCheckForUpdate(function (res) { // 请求完新版本信息的回调 console.log(res.hasUpdate) }) updateManager.onUpdateReady(function () { wx.showModal({ title: '更新提示', content: '新版本已经准备好，是否重启应用？', success(res) { if (res.confirm) { // 新的版本已经下载好，调用 applyUpdate 应用新版本并重启 updateManager.applyUpdate() } } }) }) updateManager.onUpdateFailed(function () { // 新版本下载失败 })官方提供的demo中，只有最基本的更新提示，并未做异常处理。而且官方也说了这个功能基础库 1.9.90 开始支持，低版本需做兼容处理，那么就需要对着端代码进行改进了。另一方面，如果当前版本更新有重大调整，一定需要用户更新，那么可以在用户点击取消的回调中给出提示，并重新进入版本提示流程。如下图，在上边的更新提示中，用户点击取消，则弹出下面提示弹窗，用户点击确定，则更新版本，点击取消，则重新调用上边的更新提示。总之，用户只有更新了，才能正常访问小程序（如非必须，建议慎用）。改善后的代码：//app.js App({ onLaunch: function(options) { this.autoUpdate() }, autoUpdate:function(){ console.log(new Date()) var self=this // 获取小程序更新机制兼容 if (wx.canIUse('getUpdateManager')) { const updateManager = wx.getUpdateManager() //1. 检查小程序是否有新版本发布 updateManager.onCheckForUpdate(function (res) { // 请求完新版本信息的回调 if (res.hasUpdate) { //2. 小程序有新版本，则静默下载新版本，做好更新准备 updateManager.onUpdateReady(function () { console.log(new Date()) wx.showModal({ title: '更新提示', content: '新版本已经准备好，是否重启应用？', success: function (res) { if (res.confirm) { //3. 新的版本已经下载好，调用 applyUpdate 应用新版本并重启 updateManager.applyUpdate() } else if (res.cancel) { //如果需要强制更新，则给出二次弹窗，如果不需要，则这里的代码都可以删掉了 wx.showModal({ title: '温馨提示~', content: '本次版本更新涉及到新的功能添加，旧版本无法正常访问的哦~', success: function (res) { self.autoUpdate() return; //第二次提示后，强制更新 if (res.confirm) { // 新的版本已经下载好，调用 applyUpdate 应用新版本并重启 updateManager.applyUpdate() } else if (res.cancel) { //重新回到版本更新提示 self.autoUpdate() } } }) } } }) }) updateManager.onUpdateFailed(function () { // 新的版本下载失败 wx.showModal({ title: '已经有新版本了哟~', content: '新版本已经上线啦~，请您删除当前小程序，重新搜索打开哟~', }) }) } }) } else { // 如果希望用户在最新版本的客户端上体验您的小程序，可以这样子提示 wx.showModal({ title: '提示', content: '当前微信版本过低，无法使用该功能，请升级到最新微信版本后重试。' }) } } })更新版本的模拟测试：微信开发者工具上可以通过「编译模式」下的「下次编译模拟更新」开关来调试；小程序开发版/体验版没有「版本」概念，所以无法在开发版/体验版上测试更版本更新情况；对于开发者工具，可以这样验证测试：点击编译模式设置下拉列表，然后点击“添加编译模式”，在自定义编译条件弹窗界面，点击下次编译时模拟更新，然后点击确定，重新编译就OK了。需要注意的是，这种方式模拟更新一次之后就失效了，后边再测试仍需要对这种编译模式进行重新设置才可以。更新提示有延迟？在开发者工具上测试验证的时候，更新提示弹窗在小程序界面加载出来五六秒之后才弹出来，这是由于小程序在检测到有新版本之后，调用UpdateManager.onUpdateReady(function callback)进行版本更新监听，此时客户端主动触发下载（无需开发者触发），下载成功后回调。也就是说我们上边的更新提示弹窗是在小程序检测到新版本并完成新版本下载之后弹出的，所以就有了这几秒的时间差。这样的话就很有必要进行再次改善了，至少应该在小程序编译时检测到有新版本就应该先给出更新提示，至于新版本下载的准备工作，可以在用户点击确认按钮之后进行，代码改造如下：App({ onLaunch: function(options) { this.autoUpdate() }, autoUpdate: function() { var self = this // 获取小程序更新机制兼容 if (wx.canIUse('getUpdateManager')) { const updateManager = wx.getUpdateManager() //1. 检查小程序是否有新版本发布 updateManager.onCheckForUpdate(function(res) { // 请求完新版本信息的回调 if (res.hasUpdate) { //检测到新版本，需要更新，给出提示 wx.showModal({ title: '更新提示', content: '检测到新版本，是否下载新版本并重启小程序？', success: function(res) { if (res.confirm) { //2. 用户确定下载更新小程序，小程序下载及更新静默进行 self.downLoadAndUpdate(updateManager) } else if (res.cancel) { //用户点击取消按钮的处理，如果需要强制更新，则给出二次弹窗，如果不需要，则这里的代码都可以删掉了 wx.showModal({ title: '温馨提示~', content: '本次版本更新涉及到新的功能添加，旧版本无法正常访问的哦~', showCancel:false,//隐藏取消按钮 confirmText:"确定更新",//只保留确定更新按钮 success: function(res) { if (res.confirm) { //下载新版本，并重新应用 self.downLoadAndUpdate(updateManager) } } }) } } }) } }) } else { // 如果希望用户在最新版本的客户端上体验您的小程序，可以这样子提示 wx.showModal({ title: '提示', content: '当前微信版本过低，无法使用该功能，请升级到最新微信版本后重试。' }) } }, /** * 下载小程序新版本并重启应用 */ downLoadAndUpdate: function (updateManager){ var self=this wx.showLoading(); //静默下载更新小程序新版本 updateManager.onUpdateReady(function () { wx.hideLoading() //新的版本已经下载好，调用 applyUpdate 应用新版本并重启 updateManager.applyUpdate() }) updateManager.onUpdateFailed(function () { // 新的版本下载失败 wx.showModal({ title: '已经有新版本了哟~', content: '新版本已经上线啦~，请您删除当前小程序，重新搜索打开哟~', }) }) } })如上，在检测到小程序有新版本之后，就给出弹窗提示用户下载新版并重启小程序，用户点击确定按钮后进行小程序新版本的下载和更新。也为了调用方便，将新版本下载及小程序的重启应用单独封装起来。这样，从小程序加载到弹出版本更新弹窗只需要耗费调用新版本检测API并返回结果的时间（开发者工具测试有2~3秒），虽说还是有一点延迟，但目前也只能这样了。总结：综上，无论如何，使用小程序版本更新检测功能都是需要一定时间的（一两秒的时间已经不算短了哈），如果在检测这一两秒中内用户进行了操作，那么更新提示弹窗则会打断用户的操作。但毕竟不是频繁更新版本，所以这方面还是可以接受的。另外，下载新的版本包的时候建议loading，这样用户就知道是在下载，然后下载完成自动重启，这样整个流程就顺畅多了。梳理了下，整了份思维导图，可以辅助理解：其他注意事项：基础库最低版本设置：如果不想做API支持判断，那么可以给小程序设置最低版本支持。打开小程序管理后台-设置-基础库最低版本设置，根据现有小程序的访问情况或者小程序官方提供的数据，设置一个比较大众化的基础库版本就好了，这样就能进了尽量减少API兼容性判断，也能促使用户更新微信版本，以支持小程序正常运行，体验小程序一些高级功能。以上就是这篇文章的全部内容了，希望本文的内容对大家的学习或者工作具有一定的参考学习价值，谢谢大家对轩宇网的支持。
这篇文章主要介为大家详细绍了微信小程序实现打卡日历功能，具有一定的参考价值，感兴趣的小伙伴们可以参考一下生活中有各种可以打卡的app，例如背单词打卡什么的，本人觉得很有意思，于是本人在大二时做了一款诚信状打卡的微信小程序，这里讲述一下编写的过程。先说一下开发环境：用的是微信web开发工具开发的，后台采用了Bmob后台，比较方便。先展示一下成果：话不多说，直接上代码，里面也有挺多的注释，以防自己忘记，当然各位如果直接复制过去肯定不能有当前的效果，注意后台数据的交互，不过做一个界面还是没有问题的。Calendar.wxml 页面文件 页面上显示出来的东西，布局上主要是一个年月栏、上一个月和下一个月的按钮；然后是星期栏，就是日一二三四五六，然后就是每个月的日期，注意每个月的前面可能有空的地方。这里面用wx:if标签来区分当前日期有无打卡的情况。 <view class='all'> <view class="bar"> <view class="previous" bindtap="handleCalendar" data-handle="prev"> <image src='../../images/pre.png'></image> </view> <view class="date"> 年 月</view> <view class="next" bindtap="handleCalendar" data-handle="next"> <image src='../../images/next.png'></image> </view> </view> <view class="week"> <view wx:for="{{weeks_ch}}" wx:key="{{index}}" data-idx="{{index}}">{{item}}</view> </view> <view class='days'> <view class="columns" wx:for="{{days.length/7}}" wx:for-index="i" wx:key="i"> <view wx:for="{{days}}" wx:for-index="j" wx:key="j"> <view class="rows" wx:if="{{j/7 == i}}"> <view class="rows" wx:for="{{7}}" wx:for-index="k" wx:key="k"> <view class='cell' wx:if="{{days[j+k].date == null}}"> <text decode="{{true}}"> </text> </view> <view class='cell' wx:else> <view wx:if="{{days[j+k].isSign == true}}" style='background-color:#83C75D' class='cell'> <text>{{days[j+k].date}}</text> </view> <view wx:else> <text>{{days[j+k].date}}</text> </view> </view> </view> </view> </view> </view> </view> <view class='count'> <text>截至目前，你已坚持打卡</text> <view class='daynumber'> <text class='number'>{{count}}</text> <text class='day'>天</text> </view> <text>请再接再厉，继续努力</text> </view> </view>Calendar.wxss 样式文件 这个就是让页面显示得更好看一点了，里面有些属性更改之后可能会导致整个页面的格式变得很乱，说明自己的功夫还是不到家。/* pages/Calendar/Calendar.wxss */ /* 打卡日历 */ .all{ margin-top: 20rpx; } .all .bar{ display: flex; flex-direction: row; justify-content: space-between; margin: 30rpx 20rpx; padding: 10rpx; } .all .bar image{ width: 50rpx; height: 50rpx; } .all .week{ display: flex; flex-direction: row; justify-content: space-between; padding: 20rpx; padding-left: 40rpx; padding-right: 40rpx; margin: 20rpx; border-radius: 10px; background-color: #acd; } .all .days{ margin: 20rpx; padding: 10rpx; border-radius: 10px; background-color: #acd; } .all .columns{ display: flex; flex-direction: column; justify-content: space-between; } .all .columns .rows{ display: flex; flex-direction: row; justify-content: space-between; } .all .columns .rows .cell{ width: 84rpx; height: 88rpx; margin: 3rpx; text-align: center; border-radius: 50%; display: flex; flex-direction: column; justify-content: center; } .count .daynumber{ display: flex; flex-direction: row; justify-content: center; } .count .daynumber .day{ margin-top: 50rpx; } .count{ margin: 20rpx; padding: 30rpx; display: flex; text-align: center; border-radius: 10px; flex-direction: column; justify-content: center; background-color: #acd; align-items: center; } .count .number{ color: red; font-size: 60rpx; background-color: #fff; width: 100rpx; height: 100rpx; border-radius: 50%; display: flex; flex-direction: column; justify-content: center; margin: 20rpx; } .count text{ margin: 10rpx; }Calendar.js JavaScript文件 js文件里面涉及到Bmob的操作，这里就不多说Bmob的操作了，感兴趣的同学可以去参考它的官方文档。 然后里面主要是对上一个月、下一个月的点击函数进行处理，以及对某年某月的每个日期进行初始化（尤其是每个月前的可能有的几个空格进行了处理），然后就是判断某个日期在后台数据中是否有打卡。// pages/Calendar/Calendar.js //打卡日历页面 var util = require('../../utils/util.js'); var Bmob = require('../../utils/bmob.js'); Page({ /** * 页面的初始数据 */ data: { objectId:'', days:[], signUp:[], cur_year:0, cur_month:0, count:0 }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { this.setData({objectId : options.objectId}); //获取当前年月 const date = new Date(); const cur_year = date.getFullYear(); const cur_month = date.getMonth() + 1; const weeks_ch = ['日', '一', '二', '三', '四', '五', '六']; this.calculateEmptyGrids(cur_year, cur_month); this.calculateDays(cur_year, cur_month); //获取当前用户当前任务的签到状态 this.onGetSignUp(); this.setData({ cur_year, cur_month, weeks_ch }) }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function () { }, /** * 生命周期函数--监听页面显示 */ onShow: function () { }, /** * 生命周期函数--监听页面隐藏 */ onHide: function () { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function () { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function () { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function () { }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { }, // 获取当月共多少天 getThisMonthDays:function(year, month){ return new Date(year, month, 0).getDate() }, // 获取当月第一天星期几 getFirstDayOfWeek:function(year, month) { return new Date(Date.UTC(year, month - 1, 1)).getDay(); }, // 计算当月1号前空了几个格子，把它填充在days数组的前面 calculateEmptyGrids:function(year, month) { var that = this; //计算每个月时要清零 that.setData({days:[]}); const firstDayOfWeek = this.getFirstDayOfWeek(year, month); if (firstDayOfWeek > 0) { for (let i = 0; i < firstDayOfWeek; i++) { var obj = { date:null, isSign:false } that.data.days.push(obj); } this.setData({ days:that.data.days }); //清空 } else { this.setData({ days: [] }); } }, // 绘制当月天数占的格子，并把它放到days数组中 calculateDays:function(year, month) { var that = this; const thisMonthDays = this.getThisMonthDays(year, month); for (let i = 1; i <= thisMonthDays; i++) { var obj = { date: i, isSign: false } that.data.days.push(obj); } this.setData({ days:that.data.days }); }, //匹配判断当月与当月哪些日子签到打卡 onJudgeSign:function(){ var that = this; var signs = that.data.signUp; var daysArr = that.data.days; for (var i=0; i < signs.length;i++){ var current = new Date(signs[i].date.replace(/-/g, "/")); var year = current.getFullYear(); var month = current.getMonth()+1; var day = current.getDate(); day = parseInt(day); for (var j = 0; j < daysArr.length;j++){ //年月日相同并且已打卡 if (year == that.data.cur_year && month == that.data.cur_month && daysArr[j].date == day && signs[i].isSign == "今日已打卡"){ daysArr[j].isSign = true; } } } that.setData({days:daysArr}); }, // 切换控制年月，上一个月，下一个月 handleCalendar:function(e) { const handle = e.currentTarget.dataset.handle; const cur_year = this.data.cur_year; const cur_month = this.data.cur_month; if (handle === 'prev') { let newMonth = cur_month - 1; let newYear = cur_year; if (newMonth < 1) { newYear = cur_year - 1; newMonth = 12; } this.calculateEmptyGrids(newYear, newMonth); this.calculateDays(newYear, newMonth); this.onGetSignUp(); this.setData({ cur_year: newYear, cur_month: newMonth }) } else { let newMonth = cur_month + 1; let newYear = cur_year; if (newMonth > 12) { newYear = cur_year + 1; newMonth = 1; } this.calculateEmptyGrids(newYear, newMonth); this.calculateDays(newYear, newMonth); this.onGetSignUp(); this.setData({ cur_year: newYear, cur_month: newMonth }) } }, //获取当前用户该任务的签到数组 onGetSignUp:function(){ var that = this; var Task_User = Bmob.Object.extend("task_user"); var q = new Bmob.Query(Task_User); q.get(that.data.objectId, { success: function (result) { that.setData({ signUp : result.get("signUp"), count : result.get("score") }); //获取后就判断签到情况 that.onJudgeSign(); }, error: function (object, error) { } }); } })Calendar.json json文件 这里仅仅是改变了导航栏上的标题文字{ "navigationBarTitleText": "打卡日历" }其中bmob.js的具体代码如下：! function(e, t) { "object" == typeof exports && "object" == typeof module ? module.exports = t() : "function" == typeof define && define.amd ? define([], t) : "object" == typeof exports ? exports.Bmob = t() : e.Bmob = t() }("undefined" != typeof self ? self : this, function() { return function(e) { var t = {}; function n(r) { if (t[r]) return t[r].exports; var o = t[r] = { i: r, l: !1, exports: {} }; return e[r].call(o.exports, o, o.exports, n), o.l = !0, o.exports } return n.m = e, n.c = t, n.d = function(e, t, r) { n.o(e, t) || Object.defineProperty(e, t, { configurable: !1, enumerable: !0, get: r }) }, n.n = function(e) { var t = e && e.__esModule ? function() { return e.default } : function() { return e }; return n.d(t, "a", t), t }, n.o = function(e, t) { return Object.prototype.hasOwnProperty.call(e, t) }, n.p = "", n(n.s = 17) }([function(e, t, n) { (function(t) { const r = n(5), o = t.Bmob || {}; o.utils = r, o._config = r.getConfig(), o.initialize = ((e, t, n) => { o._config.applicationId = e, o._config.applicationKey = t, o._config.applicationMasterKey = n }), e.exports = o }).call(t, n(6)) }, function(e, t, n) { "use strict"; var r = n(11), o = n(24), s = Object.prototype.toString; function i(e) { return "[object Array]" === s.call(e) } function a(e) { return null !== e && "object" == typeof e } function c(e) { return "[object Function]" === s.call(e) } function u(e, t) { if (null !== e && void 0 !== e) if ("object" != typeof e && (e = [e]), i(e)) for (var n = 0, r = e.length; n < r; n++) t.call(null, e[n], n, e); else for (var o in e) Object.prototype.hasOwnProperty.call(e, o) && t.call(null, e[o], o, e) } e.exports = { isArray: i, isArrayBuffer: function(e) { return "[object ArrayBuffer]" === s.call(e) }, isBuffer: o, isFormData: function(e) { return "undefined" != typeof FormData && e instanceof FormData }, isArrayBufferView: function(e) { return "undefined" != typeof ArrayBuffer && ArrayBuffer.isView ? ArrayBuffer.isView(e) : e && e.buffer && e.buffer instanceof ArrayBuffer }, isString: function(e) { return "string" == typeof e }, isNumber: function(e) { return "number" == typeof e }, isObject: a, isUndefined: function(e) { return void 0 === e }, isDate: function(e) { return "[object Date]" === s.call(e) }, isFile: function(e) { return "[object File]" === s.call(e) }, isBlob: function(e) { return "[object Blob]" === s.call(e) }, isFunction: c, isStream: function(e) { return a(e) && c(e.pipe) }, isURLSearchParams: function(e) { return "undefined" != typeof URLSearchParams && e instanceof URLSearchParams }, isStandardBrowserEnv: function() { return ("undefined" == typeof navigator || "ReactNative" !== navigator.product) && "undefined" != typeof window && "undefined" != typeof document }, forEach: u, merge: function e() { var t = {}; function n(n, r) { "object" == typeof t[r] && "object" == typeof n ? t[r] = e(t[r], n) : t[r] = n } for (var r = 0, o = arguments.length; r < o; r++) u(arguments[r], n); return t }, extend: function(e, t, n) { return u(t, function(t, o) { e[o] = n && "function" == typeof t ? r(t, n) : t }), e }, trim: function(e) { return e.replace(/^\s*/, "").replace(/\s*$/, "") } } }, function(e, t) { e.exports = { isObject: e => "[object Object]" === Object.prototype.toString.call(e), isNumber: e => "[object Number]" === Object.prototype.toString.call(e), isString: e => "[object String]" === Object.prototype.toString.call(e), isUndefined: e => "[object Undefined]" === Object.prototype.toString.call(e), isBoolean: e => "[object Boolean]" === Object.prototype.toString.call(e), isArray: e => "[object Array]" === Object.prototype.toString.call(e), isFunction: e => "[object Function]" === Object.prototype.toString.call(e) } }, function(e, t) { e.exports = class { constructor(e, t) { let n = new Error; return n.code = e, n.message = t ? `Bmob.Error:{code:${e}, message:${t}}` : `Bmob.Error:{code:${e}, message:${this.errorMsg(e)}}`, n } errorMsg(e) { switch (e) { case 415: return "incorrect parameter type."; case 416: return "Parameter is null."; case 417: return "There is no upload content."; case 418: return "Log in failure."; case 419: return "Bmob.GeoPoint location error."; default: return "unknown error" } } } }, function(e, t, n) { let r; const o = n(5).getAppType(); "h5" === o ? r = n(10) : "wx" === o ? r = n(41) : "hap" === o ? r = n(42) : "nodejs" === o && (r = n(10)), e.exports = r }, function(e, t, n) { (function(t, r) { let o; try { o = n(18) } catch (e) { o = n(20) } const s = () => o; e.exports = { getConfig: s, getAppType: () => { const e = s(); let n; return n = "undefined" != typeof wx ? "wx" : "undefined" != typeof window ? "h5" : t === r.process ? "nodejs" : 3 === e.type ? "hap" : "h5" } } }).call(t, n(7), n(6)) }, function(e, t) { var n; n = function() { return this }(); try { n = n || Function("return this")() || (0, eval)("this") } catch (e) { "object" == typeof window && (n = window) } e.exports = n }, function(e, t) { var n, r, o = e.exports = {}; function s() { throw new Error("setTimeout has not been defined") } function i() { throw new Error("clearTimeout has not been defined") } function a(e) { if (n === setTimeout) return setTimeout(e, 0); if ((n === s || !n) && setTimeout) return n = setTimeout, setTimeout(e, 0); try { return n(e, 0) } catch (t) { try { return n.call(null, e, 0) } catch (t) { return n.call(this, e, 0) } } }! function() { try { n = "function" == typeof setTimeout ? setTimeout : s } catch (e) { n = s } try { r = "function" == typeof clearTimeout ? clearTimeout : i } catch (e) { r = i } }(); var c, u = [], l = !1, p = -1; function f() { l && c && (l = !1, c.length ? u = c.concat(u) : p = -1, u.length && h()) } function h() { if (!l) { var e = a(f); l = !0; for (var t = u.length; t;) { for (c = u, u = []; ++p < t;) c && c[p].run(); p = -1, t = u.length } c = null, l = !1, function(e) { if (r === clearTimeout) return clearTimeout(e); if ((r === i || !r) && clearTimeout) return r = clearTimeout, clearTimeout(e); try { r(e) } catch (t) { try { return r.call(null, e) } catch (t) { return r.call(this, e) } } }(e) } } function d(e, t) { this.fun = e, this.array = t } function m() {} o.nextTick = function(e) { var t = new Array(arguments.length - 1); if (arguments.length > 1) for (var n = 1; n < arguments.length; n++) t[n - 1] = arguments[n]; u.push(new d(e, t)), 1 !== u.length || l || a(h) }, d.prototype.run = function() { this.fun.apply(null, this.array) }, o.title = "browser", o.browser = !0, o.env = {}, o.argv = [], o.version = "", o.versions = {}, o.on = m, o.addListener = m, o.once = m, o.off = m, o.removeListener = m, o.removeAllListeners = m, o.emit = m, o.prependListener = m, o.prependOnceListener = m, o.listeners = function(e) { return [] }, o.binding = function(e) { throw new Error("process.binding is not supported") }, o.cwd = function() { return "/" }, o.chdir = function(e) { throw new Error("process.chdir is not supported") }, o.umask = function() { return 0 } }, function(e, t, n) { "use strict"; (function(t) { var r = n(1), o = n(26), s = { "Content-Type": "application/x-www-form-urlencoded" }; function i(e, t) { !r.isUndefined(e) && r.isUndefined(e["Content-Type"]) && (e["Content-Type"] = t) } var a = { adapter: function() { var e; return "undefined" != typeof XMLHttpRequest ? e = n(12) : void 0 !== t && (e = n(12)), e }(), transformRequest: [function(e, t) { return o(t, "Content-Type"), r.isFormData(e) || r.isArrayBuffer(e) || r.isBuffer(e) || r.isStream(e) || r.isFile(e) || r.isBlob(e) ? e : r.isArrayBufferView(e) ? e.buffer : r.isURLSearchParams(e) ? (i(t, "application/x-www-form-urlencoded;charset=utf-8"), e.toString()) : r.isObject(e) ? (i(t, "application/json;charset=utf-8"), JSON.stringify(e)) : e }], transformResponse: [function(e) { if ("string" == typeof e) try { e = JSON.parse(e) } catch (e) {} return e }], timeout: 0, xsrfCookieName: "XSRF-TOKEN", xsrfHeaderName: "X-XSRF-TOKEN", maxContentLength: -1, validateStatus: function(e) { return e >= 200 && e < 300 }, headers: { common: { Accept: "application/json, text/plain, */*" } } }; r.forEach(["delete", "get", "head"], function(e) { a.headers[e] = {} }), r.forEach(["post", "put", "patch"], function(e) { a.headers[e] = r.merge(s) }), e.exports = a }).call(t, n(7)) }, function(e, t, n) { let r = n(0); const o = n(4), { isObject: s, isString: i, isNumber: a, isUndefined: c, isArray: u } = n(2), l = n(3), p = n(16); function f(e, t, n) { let r = {}, o = {}; o[t] = n, r[e] = o; let s = r; return Object.keys(this.queryData).length ? c(this.queryData.$and) ? this.queryData = { $and: [this.queryData, s] } : this.queryData.$and.push(s) : this.queryData = s, s } e.exports = class { constructor(e) { this.tableName = `${r._config.parameters.QUERY}/${e}`, this.className = e, this.init(), this.addArray = {}, this.setData = {} } init() { this.queryData = {}, this.location = {}, this.andData = {}, this.orData = {}, this.stat = {}, this.limitNum = 100, this.skipNum = 0, this.includes = "", this.queryReilation = {}, this.orders = null, this.keys = null } get(e) { if (!i(e)) throw new l(415); let t = {}; const n = {}, r = {}, s = {}, f = (e, t) => { if (!i(e) || !u(t)) throw new l(415); s[e] = { __op: "Add", objects: t } }, h = (e, t) => { if (!i(e) || !u(t)) throw new l(415); s[e] = { __op: "AddUnique", objects: t } }, d = (e, t) => { if (!i(e) || !u(t)) throw new l(415); s[e] = { __op: "Remove", objects: t } }, m = (e, t = 1) => { if (!i(e) || !a(t)) throw new l(415); n[e] = { __op: "Increment", amount: t } }, w = t => { if (!i(e)) throw new l(415); r[t] = { __op: "Delete" } }, g = (e, n) => { if (!i(e) || c(n)) throw new l(415); const { filename: r, cdn: o, url: s } = n; c(r) || c(o) || c(s) ? t[e] = n : t[e] = { __type: "File", group: o, filename: r, url: s } }, y = () => { const i = Object.assign(r, t, n, s); return "_User" === this.className ? new Promise((t, n) => { o(`${this.tableName}/${e}`, "put", i).then(e => { const n = this.current(); let r = Object.assign(n, i); p.save("bmob", r), t(e) }).catch(e => { n(e) }) }) : o(`${this.tableName}/${e}`, "put", i) }, b = {}; return "" !== this.includes && (b.include = this.includes), new Promise((t, n) => { o(`${this.tableName}/${e}`, "get", b).then(n => { Object.defineProperty(n, "set", { value: g }), Object.defineProperty(n, "unset", { value: w }), Object.defineProperty(n, "save", { value: y }), Object.defineProperty(n, "increment", { value: m }), Object.defineProperty(n, "add", { value: f }), Object.defineProperty(n, "remove", { value: d }), Object.defineProperty(n, "addUnique", { value: h }), Object.defineProperty(n, "destroy", { value: () => this.destroy(e) }), t(n) }).catch(e => { n(e) }) }) } destroy(e) { if (!i(e)) throw new l(415); return o(`${this.tableName}/${e}`, "delete") } set(e, t) { if (!i(e) || c(t)) throw new l(415, `${e}字段参数,类型不正确`); const { filename: n, cdn: r, url: o } = t; c(n) || c(r) || c(o) ? this.setData[e] = t : this.setData[e] = { __type: "File", group: r, filename: n, url: o } } add(e, t) { if (!i(e) || !u(t)) throw new l(415); this.addArray[e] = { __op: "Add", objects: t } } addUnique(e, t) { if (!i(e) || !u(t)) throw new l(415); this.addArray[e] = { __op: "AddUnique", objects: t } } current() { if ("hap" !== r.type) { const e = p.fetch("bmob"); return "object" == typeof e ? e : JSON.parse(e) } return new Promise((e, t) => p.fetch("bmob").then(t => { e(t) }).catch(e => { t(e) })) } updateStorage(e) { if (!i(e)) throw new l(415); return new Promise((t, n) => { const r = this.current(); if (!r) throw new l(415); this.get(e).then(e => { let n = Object.assign(r, e); p.save("bmob", n), t(e) }).catch(e => { console.log(e), n(e) }) }) } save(e = {}) { if (!s(e)) throw new l(415); let t = this.setData.id ? "PUT" : "POST", n = this.setData.id ? this.setData.id : ""; delete this.setData.id; let r = Object.assign(e, this.setData, this.addArray); return new Promise((e, s) => { o(`${this.tableName}/${n}`, t, r).then(t => { if (this.addArray = {}, this.setData = {}, "_User" === this.className) { const e = this.current(); let t = Object.assign(e, r); p.save("bmob", t) } e(t) }).catch(e => { s(e) }) }) } saveAll(e) { if (!u(e)) throw new l(415); if (e.length < 1) throw new l(416); let t, n, s = "put", i = []; e.map(e => ("/undefined" === (t = `/${e.objectId}`) && (t = "", s = "post"), n = { method: s, path: `${this.tableName}${t}`, body: e.setData }, i.push(n), e)); let a = { requests: i }, c = r._config.parameters.BATCH; return o(c, "POST", a) } withinKilometers(e, { latitude: t, longitude: n }, r = 100) { let o = {}; return o[e] = { $nearSphere: { __type: "GeoPoint", latitude: t, longitude: n }, $maxDistanceInKilometers: r }, this.location = o, o } withinGeoBox(e, { latitude: t, longitude: n }, r) { let o = {}; return o[e] = { $within: { $box: [{ __type: "GeoPoint", latitude: t, longitude: n }, { __type: "GeoPoint", latitude: r.latitude, longitude: r.longitude }] } }, this.location = o, o } statTo(e, t) { if (!i(e)) throw new l(415); return this.stat[e] = t, this.stat } equalTo(e, t, n) { if (!i(e)) throw new l(415); const r = ((e, t, n) => { let r = {}, o = null; switch (o = "createdAt" === e || "updateAt" === e ? { __type: "Date", iso: n } : n, t) { case "==": case "===": r[e] = o; break; case "!=": r[e] = { $ne: o }; break; case "<": r[e] = { $lt: o }; break; case "<=": r[e] = { $lte: o }; break; case ">": r[e] = { $gt: o }; break; case ">=": r[e] = { $gte: o }; break; default: throw new l(415) } return r })(e, t, n); return Object.keys(this.queryData).length ? c(this.queryData.$and) ? this.queryData = { $and: [this.queryData, r] } : this.queryData.$and.push(r) : this.queryData = r, r } containedIn(e, t) { if (!i(e) || !u(t)) throw new l(415); return f.call(this, e, "$in", t) } notContainedIn(e, t) { if (!i(e) || !u(t)) throw new l(415); return f.call(this, e, "$nin", t) } exists(e) { if (!i(e)) throw new l(415); return f.call(this, e, "$exists", !0) } doesNotExist(e) { if (!i(e)) throw new l(415); return f.call(this, e, "$exists", !1) } or(...e) { e.map((e, t) => { if (!s(e)) throw new l(415) }); const t = this.queryData.$and; if (!c(t)) { for (let n = 0; n < t.length; n++) for (let r = 0; r < e.length; r++) JSON.stringify(t[n]) === JSON.stringify(e[r]) && this.queryData.$and.splice(n, 1); t.length || delete this.queryData.$and } this.orData = { $or: e } } and(...e) { e.map((e, t) => { if (!s(e)) throw new l(415) }), this.andData = { $and: e } } limit(e) { if (!a(e)) throw new l(415); e > 1e3 && (e = 1e3), this.limitNum = e } skip(e) { if (!a(e)) throw new l(415); this.skipNum = e } order(...e) { e.map(e => { if (!i(e)) throw new l(415) }), this.orders = e.join(",") } include(...e) { e.map(e => { if (!i(e)) throw new l(415) }), this.includes = e.join(",") } select(...e) { e.map(e => { if (!i(e)) throw new l(415) }), this.keys = e.join(",") } field(e, t) { if (!i(e) || !i(t)) throw new l(415); this.queryReilation.where = { $relatedTo: { object: { __type: "Pointer", className: this.className, objectId: t }, key: e } } } relation(e) { if (!i(e)) throw new l(415); e = "_User" === e ? "users" : `classes/${e}`, this.queryReilation.count = 1; let t = Object.assign(this.getParams(), this.queryReilation); return new Promise((n, r) => { o(`/1/${e}`, "get", t).then(e => { n(e) }).catch(e => { r(e) }) }) } getParams() { let e = {}; Object.keys(this.queryData).length && (e.where = this.queryData), Object.keys(this.location).length && (e.where = Object.assign(this.location, this.queryData)), Object.keys(this.andData).length && (e.where = Object.assign(this.andData, this.queryData)), Object.keys(this.orData).length && (e.where = Object.assign(this.orData, this.queryData)), e.limit = this.limitNum, e.skip = this.skipNum, e.include = this.includes, e.order = this.orders, e.keys = this.keys, Object.keys(this.stat).length && (e = Object.assign(e, this.stat)); for (const t in e)(e.hasOwnProperty(t) && null === e[t] || 0 === e[t] || "" === e[t]) && delete e[t]; return e } find() { let e = {}, t = {}; const n = this.getParams(), s = (t, n) => { if (!t || c(n)) throw new l(415); e[t] = n }, i = (n = "updata") => { if (console.log(n), t.length < 1) throw new l(416); let s, i, a = "put", c = []; t.map(t => ("/undefined" === (s = `/${t.objectId}`) && (s = "", a = "post"), i = { method: a, path: `${this.tableName}${s}`, body: e }, "delete" === n && (i = { method: "DELETE", path: `${this.tableName}${s}` }), c.push(i), t)); let u = { requests: c }, p = r._config.parameters.BATCH; return o(p, "POST", u) }; return new Promise((e, r) => { o(`${this.tableName}`, "get", n).then(r => { let o = r.results; n.hasOwnProperty("count") && (o = r), this.init(), Object.defineProperty(o, "set", { value: s }), Object.defineProperty(o, "saveAll", { value: () => i() }), Object.defineProperty(o, "destroyAll", { value: () => i("delete") }), t = o, e(o) }).catch(e => { r(e) }) }) } count(e = 0) { const t = {}; return Object.keys(this.queryData).length && (t.where = this.queryData), Object.keys(this.andData).length && (t.where = Object.assign(this.andData, this.queryData)), Object.keys(this.orData).length && (t.where = Object.assign(this.orData, this.queryData)), t.count = 1, t.limit = e, new Promise((e, n) => { o(`${this.tableName}`, "get", t).then(({ count: t }) => { e(t) }).catch(e => { n(e) }) }) } } }, function(e, t, n) { const r = n(23); let o = n(0); e.exports = ((e, t = "get", s = {}) => new Promise((i, a) => { void 0 === o.User && (o = n(0)); const c = (e => { let t = "wechatApp"; "nodejs" === o.type && (t = "cloudcode"); let n = { "content-type": "application/json", "X-Bmob-SDK-Type": t, "X-Bmob-Application-Id": e.applicationId, "X-Bmob-REST-API-Key": e.applicationKey }; return e.applicationMasterKey && (n["X-Bmob-Master-Key"] = e.applicationMasterKey), n })(o._config); var u = o.User.current(); u && (c["X-Bmob-Session-Token"] = u.sessionToken); const l = r.create({ baseURL: o._config.host, headers: c, validateStatus: e => e < 500 }), p = { url: e, method: t }; "get" === p.method ? p.params = s : p.data = s, l(p).then(({ data: e }) => { (e.code && e.error || e.error) && a(e), i(e) }).catch(e => { a(e) }) })) }, function(e, t, n) { "use strict"; e.exports = function(e, t) { return function() { for (var n = new Array(arguments.length), r = 0; r < n.length; r++) n[r] = arguments[r]; return e.apply(t, n) } } }, function(e, t, n) { "use strict"; (function(t) { var r = n(1), o = n(27), s = n(29), i = n(30), a = n(31), c = n(13), u = "undefined" != typeof window && window.btoa && window.btoa.bind(window) || n(32); e.exports = function(e) { return new Promise(function(l, p) { var f = e.data, h = e.headers; r.isFormData(f) && delete h["Content-Type"]; var d = new XMLHttpRequest, m = "onreadystatechange", w = !1; if ("test" === t.env.NODE_ENV || "undefined" == typeof window || !window.XDomainRequest || "withCredentials" in d || a(e.url) || (d = new window.XDomainRequest, m = "onload", w = !0, d.onprogress = function() {}, d.ontimeout = function() {}), e.auth) { var g = e.auth.username || "", y = e.auth.password || ""; h.Authorization = "Basic " + u(g + ":" + y) } if (d.open(e.method.toUpperCase(), s(e.url, e.params, e.paramsSerializer), !0), d.timeout = e.timeout, d[m] = function() { if (d && (4 === d.readyState || w) && (0 !== d.status || d.responseURL && 0 === d.responseURL.indexOf("file:"))) { var t = "getAllResponseHeaders" in d ? i(d.getAllResponseHeaders()) : null, n = { data: e.responseType && "text" !== e.responseType ? d.response : d.responseText, status: 1223 === d.status ? 204 : d.status, statusText: 1223 === d.status ? "No Content" : d.statusText, headers: t, config: e, request: d }; o(l, p, n), d = null } }, d.onerror = function() { p(c("Network Error", e, null, d)), d = null }, d.ontimeout = function() { p(c("timeout of " + e.timeout + "ms exceeded", e, "ECONNABORTED", d)), d = null }, r.isStandardBrowserEnv()) { var b = n(33), S = (e.withCredentials || a(e.url)) && e.xsrfCookieName ? b.read(e.xsrfCookieName) : void 0; S && (h[e.xsrfHeaderName] = S) } if ("setRequestHeader" in d && r.forEach(h, function(e, t) { void 0 === f && "content-type" === t.toLowerCase() ? delete h[t] : d.setRequestHeader(t, e) }), e.withCredentials && (d.withCredentials = !0), e.responseType) try { d.responseType = e.responseType } catch (t) { if ("json" !== e.responseType) throw t } "function" == typeof e.onDownloadProgress && d.addEventListener("progress", e.onDownloadProgress), "function" == typeof e.onUploadProgress && d.upload && d.upload.addEventListener("progress", e.onUploadProgress), e.cancelToken && e.cancelToken.promise.then(function(e) { d && (d.abort(), p(e), d = null) }), void 0 === f && (f = null), d.send(f) }) } }).call(t, n(7)) }, function(e, t, n) { "use strict"; var r = n(28); e.exports = function(e, t, n, o, s) { var i = new Error(e); return r(i, t, n, o, s) } }, function(e, t, n) { "use strict"; e.exports = function(e) { return !(!e || !e.__CANCEL__) } }, function(e, t, n) { "use strict"; function r(e) { this.message = e } r.prototype.toString = function() { return "Cancel" + (this.message ? ": " + this.message : "") }, r.prototype.__CANCEL__ = !0, e.exports = r }, function(e, t, n) { let r; const o = n(5).getAppType(); "h5" === o ? r = n(43) : "wx" === o ? r = n(44) : "hap" === o ? r = n(45) : "nodejs" === o && (r = n(46)), e.exports = r }, function(e, t, n) { (function(t) { const r = n(0), o = n(21), s = n(22), i = n(9), a = n(47), c = n(48), u = n(49), l = n(50), { generateCode: p, sendMessage: f, getAccessToken: h, sendWeAppMessage: d, refund: m, notifyMsg: w, functions: g, timestamp: y, requestPasswordReset: b, resetPasswordBySmsCode: S, updateUserPassword: E, geoPoint: v, checkMsg: T, push: _ } = n(51), { requestSmsCode: D, verifySmsCode: j } = n(52); r.GeoPoint = v, r.generateCode = p, r.sendMessage = f, r.getAccessToken = h, r.sendWeAppMessage = d, r.refund = m, r.checkMsg = T, r.notifyMsg = w, r.requestSmsCode = D, r.verifySmsCode = j, r.run = r.functions = g, r.timestamp = y, r.requestPasswordReset = b, r.resetPasswordBySmsCode = S, r.updateUserPassword = E, r.push = _, r.Pay = new u, r.User = new a, r.Socket = (() => new l), r.Query = (e => new i(e)), r.File = ((e, t) => new c(e, t)), r.request = n(4), r.type = r.utils.getAppType(), r.Pointer = (e => new o(e)), r.Relation = (e => new s(e)), "wx" === r.type ? wx.Bmob = r : "h5" === r.type ? window.Bmob = r : "hap" === r.type ? t.Bmob = r : "nodejs" === r.type && (t.Bmob = r), e.exports = r }).call(t, n(6)) }, function(e, t, n) { const r = `v${n(19).version}`; e.exports = { host: "https://api.bmobcloud.com", applicationId: "", applicationKey: "", applicationMasterKey: "", parameters: { GENERATECODE: "/1/wechatApp/qr/generatecode", GETACCESSTOKEN: "/1/wechatApp/getAccessToken", SENDWEAPPMESSAGE: "/1/wechatApp/SendWeAppMessage", NOTIFYMSG: "/1/wechatApp/notifyMsg", REFUND: "/1/pay/refund", REQUESTSMSCODE: "/1/requestSmsCode", VERIFYSMSCODE: "/1/verifySmsCode", FUNCTIONS: "/1/functions", REQUESTPASSWORDRESET: "/1/requestPasswordReset", RESETPASSWORDBYSMSCODE: "/1/resetPasswordBySmsCode", UPDATEUSERPASSWORD: "/1/updateUserPassword", PUSH: "/1/push", FILES: "/2/files", DELFILES: "/2/cdnBatchDelete", TIMESTAMP: "/1/timestamp", LOGIN: "/1/login", REGISTER: "/1/users", REQUEST_EMAIL_VERIFY: "/1/requestEmailVerify", USERS: "/1/users", PAY: "/1/pay", WECHAT_APP: "/1/wechatApp/", BATCH: "/1/batch", CHECK_MSG: "/1/wechatApp/checkMsg", DECRYPTION: "/1/wechatApp/decryption", QUERY: "/1/classes" }, version: r, type: 3 } }, function(e, t) { e.exports = { name: "hydrogen-js-sdk", version: "1.6.7", description: "Bmob SDK", main: "./src/lib/app.js", scripts: { test: 'echo "Error: no test specified" && exit 1', build: "webpack --config config/prod.env.js", watch: "webpack --watch --config config/prod.env.js", dev: "webpack-dev-server --config config/dev.env.js" }, repository: { type: "git", url: "git+https://github.com/bmob/hydrogen-js-sdk.git" }, author: "Bmob", license: "ISC", bugs: { url: "https://github.com/bmob/hydrogen-js-sdk/issues" }, homepage: "https://github.com/bmob/hydrogen-js-sdk#readme", dependencies: { "node.extend": "^2.0.0", webpack: "^3.12.0" }, devDependencies: { "clean-webpack-plugin": "^0.1.19", eslint: "^4.19.1", "eslint-config-standard": "^11.0.0", "eslint-friendly-formatter": "^4.0.1", "eslint-loader": "^2.0.0", "eslint-plugin-import": "^2.12.0", "eslint-plugin-node": "^6.0.1", "eslint-plugin-promise": "^3.7.0", "eslint-plugin-standard": "^3.1.0", "html-webpack-plugin": "^2.30.1", "uglifyjs-webpack-plugin": "^1.2.5", "webpack-dev-server": "^2.11.2" }, directories: { doc: "docs" }, keywords: ["Bmob"] } }, function(e, t) { e.exports = { host: "https://api.bmobcloud.com", applicationId: "", applicationKey: "", parameters: { GENERATECODE: "/1/wechatApp/qr/generatecode", GETACCESSTOKEN: "/1/wechatApp/getAccessToken", SENDWEAPPMESSAGE: "/1/wechatApp/SendWeAppMessage", NOTIFYMSG: "/1/wechatApp/notifyMsg", REFUND: "/1/pay/refund", REQUESTSMSCODE: "/1/requestSmsCode", VERIFYSMSCODE: "/1/verifySmsCode", FUNCTIONS: "/1/functions", REQUESTPASSWORDRESET: "/1/requestPasswordReset", RESETPASSWORDBYSMSCODE: "/1/resetPasswordBySmsCode", UPDATEUSERPASSWORD: "/1/updateUserPassword", PUSH: "/1/push", FILES: "/2/files", DELFILES: "/2/cdnBatchDelete", TIMESTAMP: "/1/timestamp", LOGIN: "/1/login", REGISTER: "/1/users", REQUEST_EMAIL_VERIFY: "/1/requestEmailVerify", USERS: "/1/users", PAY: "/1/pay", WECHAT_APP: "/1/wechatApp/", BATCH: "/1/batch", CHECK_MSG: "/1/wechatApp/checkMsg", DECRYPTION: "/1/wechatApp/decryption", QUERY: "/1/classes" }, version: 1, type: 1 } }, function(e, t, n) { const { isString: r } = n(2), o = n(3); e.exports = class { constructor(e) { if (!r(e)) throw new o(415); this.tableName = e } set(e) { if (!r(e)) throw new o(415); return { __type: "Pointer", className: this.tableName, objectId: e } } } }, function(e, t, n) { const { isString: r, isArray: o } = n(2), s = n(3); function i(e, t) { if (r(e)) return { __op: t, objects: [{ __type: "Pointer", className: this.tableName, objectId: e }] }; if (o(e)) { const n = []; return e.map(e => { if (!r(e)) throw new s(415); n.push({ __type: "Pointer", className: this.tableName, objectId: e }) }), { __op: t, objects: n } } throw new s(415) } e.exports = class { constructor(e) { if (!r(e)) throw new s(415); this.tableName = e } add(e) { return i.call(this, e, "AddRelation") } remove(e) { return i.call(this, e, "RemoveRelation") } } }, function(e, t, n) { "use strict"; var r = n(1), o = n(11), s = n(25), i = n(8); function a(e) { var t = new s(e), n = o(s.prototype.request, t); return r.extend(n, s.prototype, t), r.extend(n, t), n } var c = a(i); c.Axios = s, c.create = function(e) { return a(r.merge(i, e)) }, c.Cancel = n(15), c.CancelToken = n(39), c.isCancel = n(14), c.all = function(e) { return Promise.all(e) }, c.spread = n(40), e.exports = c, e.exports.default = c }, function(e, t) { function n(e) { return !!e.constructor && "function" == typeof e.constructor.isBuffer && e.constructor.isBuffer(e) } /*! * Determine if an object is a Buffer * * @author Feross Aboukhadijeh <https://feross.org> * @license MIT */ e.exports = function(e) { return null != e && (n(e) || function(e) { return "function" == typeof e.readFloatLE && "function" == typeof e.slice && n(e.slice(0, 0)) }(e) || !!e._isBuffer) } }, function(e, t, n) { "use strict"; var r = n(8), o = n(1), s = n(34), i = n(35); function a(e) { this.defaults = e, this.interceptors = { request: new s, response: new s } } a.prototype.request = function(e) { "string" == typeof e && (e = o.merge({ url: arguments[0] }, arguments[1])), (e = o.merge(r, { method: "get" }, this.defaults, e)).method = e.method.toLowerCase(); var t = [i, void 0], n = Promise.resolve(e); for (this.interceptors.request.forEach(function(e) { t.unshift(e.fulfilled, e.rejected) }), this.interceptors.response.forEach(function(e) { t.push(e.fulfilled, e.rejected) }); t.length;) n = n.then(t.shift(), t.shift()); return n }, o.forEach(["delete", "get", "head", "options"], function(e) { a.prototype[e] = function(t, n) { return this.request(o.merge(n || {}, { method: e, url: t })) } }), o.forEach(["post", "put", "patch"], function(e) { a.prototype[e] = function(t, n, r) { return this.request(o.merge(r || {}, { method: e, url: t, data: n })) } }), e.exports = a }, function(e, t, n) { "use strict"; var r = n(1); e.exports = function(e, t) { r.forEach(e, function(n, r) { r !== t && r.toUpperCase() === t.toUpperCase() && (e[t] = n, delete e[r]) }) } }, function(e, t, n) { "use strict"; var r = n(13); e.exports = function(e, t, n) { var o = n.config.validateStatus; n.status && o && !o(n.status) ? t(r("Request failed with status code " + n.status, n.config, null, n.request, n)) : e(n) } }, function(e, t, n) { "use strict"; e.exports = function(e, t, n, r, o) { return e.config = t, n && (e.code = n), e.request = r, e.response = o, e } }, function(e, t, n) { "use strict"; var r = n(1); function o(e) { return encodeURIComponent(e).replace(/%40/gi, "@").replace(/%3A/gi, ":").replace(/%24/g, "$").replace(/%2C/gi, ",").replace(/%20/g, "+").replace(/%5B/gi, "[").replace(/%5D/gi, "]") } e.exports = function(e, t, n) { if (!t) return e; var s; if (n) s = n(t); else if (r.isURLSearchParams(t)) s = t.toString(); else { var i = []; r.forEach(t, function(e, t) { null !== e && void 0 !== e && (r.isArray(e) ? t += "[]" : e = [e], r.forEach(e, function(e) { r.isDate(e) ? e = e.toISOString() : r.isObject(e) && (e = JSON.stringify(e)), i.push(o(t) + "=" + o(e)) })) }), s = i.join("&") } return s && (e += (-1 === e.indexOf("?") ? "?" : "&") + s), e } }, function(e, t, n) { "use strict"; var r = n(1), o = ["age", "authorization", "content-length", "content-type", "etag", "expires", "from", "host", "if-modified-since", "if-unmodified-since", "last-modified", "location", "max-forwards", "proxy-authorization", "referer", "retry-after", "user-agent"]; e.exports = function(e) { var t, n, s, i = {}; return e ? (r.forEach(e.split("\n"), function(e) { if (s = e.indexOf(":"), t = r.trim(e.substr(0, s)).toLowerCase(), n = r.trim(e.substr(s + 1)), t) { if (i[t] && o.indexOf(t) >= 0) return; i[t] = "set-cookie" === t ? (i[t] ? i[t] : []).concat([n]) : i[t] ? i[t] + ", " + n : n } }), i) : i } }, function(e, t, n) { "use strict"; var r = n(1); e.exports = r.isStandardBrowserEnv() ? function() { var e, t = /(msie|trident)/i.test(navigator.userAgent), n = document.createElement("a"); function o(e) { var r = e; return t && (n.setAttribute("href", r), r = n.href), n.setAttribute("href", r), { href: n.href, protocol: n.protocol ? n.protocol.replace(/:$/, "") : "", host: n.host, search: n.search ? n.search.replace(/^\?/, "") : "", hash: n.hash ? n.hash.replace(/^#/, "") : "", hostname: n.hostname, port: n.port, pathname: "/" === n.pathname.charAt(0) ? n.pathname : "/" + n.pathname } } return e = o(window.location.href), function(t) { var n = r.isString(t) ? o(t) : t; return n.protocol === e.protocol && n.host === e.host } }() : function() { return !0 } }, function(e, t, n) { "use strict"; var r = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; function o() { this.message = "String contains an invalid character" } o.prototype = new Error, o.prototype.code = 5, o.prototype.name = "InvalidCharacterError", e.exports = function(e) { for (var t, n, s = String(e), i = "", a = 0, c = r; s.charAt(0 | a) || (c = "=", a % 1); i += c.charAt(63 & t >> 8 - a % 1 * 8)) { if ((n = s.charCodeAt(a += .75)) > 255) throw new o; t = t << 8 | n } return i } }, function(e, t, n) { "use strict"; var r = n(1); e.exports = r.isStandardBrowserEnv() ? { write: function(e, t, n, o, s, i) { var a = []; a.push(e + "=" + encodeURIComponent(t)), r.isNumber(n) && a.push("expires=" + new Date(n).toGMTString()), r.isString(o) && a.push("path=" + o), r.isString(s) && a.push("domain=" + s), !0 === i && a.push("secure"), document.cookie = a.join("; ") }, read: function(e) { var t = document.cookie.match(new RegExp("(^|;\\s*)(" + e + ")=([^;]*)")); return t ? decodeURIComponent(t[3]) : null }, remove: function(e) { this.write(e, "", Date.now() - 864e5) } } : { write: function() {}, read: function() { return null }, remove: function() {} } }, function(e, t, n) { "use strict"; var r = n(1); function o() { this.handlers = [] } o.prototype.use = function(e, t) { return this.handlers.push({ fulfilled: e, rejected: t }), this.handlers.length - 1 }, o.prototype.eject = function(e) { this.handlers[e] && (this.handlers[e] = null) }, o.prototype.forEach = function(e) { r.forEach(this.handlers, function(t) { null !== t && e(t) }) }, e.exports = o }, function(e, t, n) { "use strict"; var r = n(1), o = n(36), s = n(14), i = n(8), a = n(37), c = n(38); function u(e) { e.cancelToken && e.cancelToken.throwIfRequested() } e.exports = function(e) { return u(e), e.baseURL && !a(e.url) && (e.url = c(e.baseURL, e.url)), e.headers = e.headers || {}, e.data = o(e.data, e.headers, e.transformRequest), e.headers = r.merge(e.headers.common || {}, e.headers[e.method] || {}, e.headers || {}), r.forEach(["delete", "get", "head", "post", "put", "patch", "common"], function(t) { delete e.headers[t] }), (e.adapter || i.adapter)(e).then(function(t) { return u(e), t.data = o(t.data, t.headers, e.transformResponse), t }, function(t) { return s(t) || (u(e), t && t.response && (t.response.data = o(t.response.data, t.response.headers, e.transformResponse))), Promise.reject(t) }) } }, function(e, t, n) { "use strict"; var r = n(1); e.exports = function(e, t, n) { return r.forEach(n, function(n) { e = n(e, t) }), e } }, function(e, t, n) { "use strict"; e.exports = function(e) { return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(e) } }, function(e, t, n) { "use strict"; e.exports = function(e, t) { return t ? e.replace(/\/+$/, "") + "/" + t.replace(/^\/+/, "") : e } }, function(e, t, n) { "use strict"; var r = n(15); function o(e) { if ("function" != typeof e) throw new TypeError("executor must be a function."); var t; this.promise = new Promise(function(e) { t = e }); var n = this; e(function(e) { n.reason || (n.reason = new r(e), t(n.reason)) }) } o.prototype.throwIfRequested = function() { if (this.reason) throw this.reason }, o.source = function() { var e; return { token: new o(function(t) { e = t }), cancel: e } }, e.exports = o }, function(e, t, n) { "use strict"; e.exports = function(e) { return function(t) { return e.apply(null, t) } } }, function(e, t, n) { let r = n(0); e.exports = ((e, t = "get", o = {}) => new Promise((s, i) => { const a = (e => { let t = { "content-type": "application/json", "X-Bmob-SDK-Type": "wechatApp", "X-Bmob-Application-Id": e.applicationId, "X-Bmob-REST-API-Key": e.applicationKey }; return e.applicationMasterKey && (t["X-Bmob-Master-Key"] = e.applicationMasterKey), t })(r._config); void 0 === r.User && (r = n(0)); var c = r.User.current(); c && (a["X-Bmob-Session-Token"] = c.sessionToken), wx.request({ url: r._config.host + e, method: t, data: o, header: a, success: e => { (e.data.code && e.data.error || e.data.error) && i(e.data), s(e.data) }, fail: e => { console.log(e), i(e) } }) })) }, function(e, t, n) { let r = n(0); e.exports = ((e, t = "get", o = {}) => new Promise((s, i) => { const a = (e => { let t = { "content-type": "application/json", "X-Bmob-SDK-Type": "wechatApp", "X-Bmob-Application-Id": e.applicationId, "X-Bmob-REST-API-Key": e.applicationKey }; return e.applicationMasterKey && (t["X-Bmob-Master-Key"] = e.applicationMasterKey), t })(r._config); void 0 === r.User && (r = n(0)); var c = r.User.current(); c && (a["X-Bmob-Session-Token"] = c.sessionToken), "object" == typeof o && (o = JSON.stringify(o)), "require('@system.fetch')".fetch({ url: r._config.host + e, header: a, method: t, data: o, success: function(e) { const t = JSON.parse(e.data); t.code && i(t), s(t) }, fail: function(e, t) { console.log(`handling fail, code = ${t}`), i(e) } }) })) }, function(e, t, n) { const { isString: r } = n(2); let o; o = "undefined" != typeof cc ? cc.sys.localStorage : localStorage; const s = { save(e, t) { if (!r(e) || !t) throw new Error(415); o.setItem(e, JSON.stringify(t)) }, fetch(e) { if (!r(e)) throw new Error(415); return JSON.parse(o.getItem(e)) || null }, remove(e) { if (!r(e)) throw new Error(415); o.removeItem(e) }, clear() { o.clear() } }; e.exports = s }, function(e, t, n) { const { isString: r, isObject: o } = n(2), s = { save(e, t) { if (!r(e) || !t) throw new Error(415); return t = o(t) ? JSON.stringify(t) : t, wx.setStorageSync(e, t) }, fetch(e) { if (!r(e)) throw new Error(415); return wx.getStorageSync(e) || null }, remove(e) { if (!r(e)) throw new Error(415); return wx.removeStorageSync(e) }, clear: () => wx.clearStorageSync() }; e.exports = s }, function(e, t, n) { const { isString: r } = n(2), o = "xxrequire('@system.storage')xx", s = { save(e, t) { if (!r(e) || !t) throw new Error(415); o.set({ key: e, value: JSON.stringify(t), success: function(e) { return console.log("handling success"), e }, fail: function(e, t) { console.log(`handling fail, code = ${t}`) } }) }, fetch(e) { if (!r(e)) throw new Error(415); return new Promise((t, n) => o.get({ key: e, success: function(e) { t(e || null) }, fail: function(e, t) { console.log(`handling fail, code = ${t}`), n(e) } })) }, remove(e) { if (!r(e)) throw new Error(415); o.delete({ key: e, success: function(e) { console.log("handling success") }, fail: function(e, t) { console.log(`handling fail, code = ${t}`) } }) }, clear() { o.clear({ success: function(e) { console.log("handling success") }, fail: function(e, t) { console.log(`handling fail, code = ${t}`) } }) } }; e.exports = s }, function(e, t) { const n = { save(e, t) {}, fetch: e => null, remove(e) {}, clear() {} }; e.exports = n }, function(e, t, n) { const r = n(4), o = n(16), s = n(9), i = n(0), a = n(3), { isObject: c, isString: u, isNumber: l } = n(2); e.exports = class extends s { constructor() { super("_User") } set(e, t = "") { u(e) && (this.setData[e] = t) } requestEmailVerify(e) { if (!u(e)) throw new a(415); this.setData = Object.assign({}, { email: e }), console.log(this.setData); const t = i._config.parameters.REQUEST_EMAIL_VERIFY; return r(t, "post", this.setData) } register(e) { if (!c(e)) throw new a(415); this.setData = Object.assign({}, e); const t = i._config.parameters.REGISTER; return r(t, "post", this.setData) } login(e, t) { if (!u(e) || !u(t)) throw new a(415); this.setData = Object.assign({}, { username: e, password: t }); const n = i._config.parameters.LOGIN; return new Promise((e, t) => { r(n, "get", this.setData).then(t => { o.save("bmob", t), e(t) }).catch(e => { t(e) }) }) } logout() { o.clear() } users() { const e = i._config.parameters.USERS; return r(e, "get") } decryption(e) { let t = this; return new Promise((n, o) => { const s = e.iv ? e.iv : e.detail.iv, a = e.encryptedData ? e.encryptedData : e.detail.encryptedData, c = { sessionKey: t.current().authData.weapp.session_key, encryptedData: a, iv: s }, u = i._config.parameters.DECRYPTION; r(u, "POST", c).then(e => { n(e) }).catch(e => { o(e) }) }) } signOrLoginByMobilePhone(e, t) { if (!l(e) || !l(t)) throw new a(415); this.setData = Object.assign({}, { mobilePhoneNumber: e, smsCode: t }); const n = i._config.parameters.LOGIN; return r(n, "get", this.setData) } requestOpenId(e) { const t = i._config.parameters.WECHAT_APP; return r(t + e, "POST", {}) } linkWith(e) { let t = { authData: e }; const n = i._config.parameters.USERS; return r(n, "POST", t) } loginWithWeapp(e) { return new Promise((t, n) => { this.requestOpenId(e).then(e => { const n = { weapp: e }, r = this.linkWith(n); t(r) }).catch(e => { n(e) }) }) } upInfo(e) { return new Promise((t, n) => { var r = e.nickName, s = e.avatarUrl, i = this.current(); if (!i) throw new a(415); var c = o.fetch("openid"); this.get(i.objectId).then(e => { e.set("nickName", r), e.set("userPic", s), e.set("openid", c), e.save().then(e => { t(e) }).catch(e => { console.log(e), n(e) }) }).catch(e => { console.log(e), n(e) }) }) } auth() { var e = this; return new Promise((t, n) => { const r = () => { wx.login({ success: r => { e.loginWithWeapp(r.code).then(e => { if (e.error) throw new a(415); var n = e.authData.weapp.openid; o.save("openid", n), o.save("bmob", e), t(e) }, function(e) { n(e) }) } }) }; wx.checkSession({ success: function() { let o = e.current(); null === o && n("登陆错误，请在Bmob后台填写小程序AppSecret。"), t(o), r() }, fail: () => { r() } }) }) } } }, function(e, t, n) { const r = n(4); let o = n(0); const s = n(3), i = n(5), a = "xxrequire('@system.request')xx", { isString: c, isArray: u } = n(2); let l = []; e.exports = class { constructor(e, t) { if (e && t) { if (!c(e)) throw new s(415); l.push({ name: e, route: `${o._config.parameters.FILES}/${e}`, data: t }) } } save() { if (!l.length) throw new s(417); let e; const t = i.getAppType(); return "h5" === t || "nodejs" === t ? e = new Promise((e, t) => { const n = []; for (let o of l) r(o.route, "post", o.data).then(r => { n.push(r), n.length === l.length && (l = [], e(n), t(n)) }).catch(e => { n.push(e) }) }) : "wx" === t ? e = new Promise((e, t) => { void 0 === o.User && (o = n(0)); let r = "bmob"; var s = o.User.current(); s && (r = s.sessionToken); const i = [], a = { _ApplicationId: o._config.applicationId, _RestKey: o._config.applicationKey, _SessionToken: r }, c = Object.assign({ _ContentType: "text/plain", mime_type: "text/plain", category: "wechatApp", _ClientVersion: "js3.6.1", _InstallationId: "bmob" }, a); for (let n of l) wx.uploadFile({ url: o._config.host + n.route, filePath: n.data, name: "file", header: { "X-Bmob-SDK-Type": "wechatApp" }, formData: c, success: function(n) { var r = JSON.parse(n.data); i.push(r), i.length === l.length && (l = [], e(i), t(i)) }, fail: function(e) { i.push(e) } }) }) : "hap" === t && (e = new Promise((e, t) => { void 0 === o.User && (o = n(0)); var r = o.User.current(); const s = [], i = { _ApplicationId: o._config.applicationId, _RestKey: o._config.applicationKey, _SessionToken: r.sessionToken }, c = Object.assign({ _ContentType: "text/plain", mime_type: "text/plain", category: "wechatApp", _ClientVersion: "js3.6.1", _InstallationId: "bmob" }, i); for (let n of l) a.upload({ url: o._config.host + n.route, files: [{ uri: n.data, name: "file", filename: n.name }], header: { "X-Bmob-SDK-Type": "wechatApp" }, data: c, success: function(n) { console.log("handling success" + s); var r = n.data; s.push(r), s.length === l.length && (l = [], e(s), t(s)) }, fail: function(e, t) { console.log(`handling fail, code = ${t}`) } }) })), e } destroy(e) { if (c(e)) return r(`${o._config.parameters.FILES}/upyun/${e.split(".com/")[1]}`, "delete"); if (u(e)) { const t = []; return e.map(e => { t.push(e.split(".com/")[1]) }), r(o._config.parameters.DELFILES, "post", { upyun: t }) } throw new s(415) } } }, function(e, t, n) { const r = n(4), o = n(0), s = n(3); e.exports = class { weApp(e, t, n) { var i = wx.getStorageSync("openid"); if (!(e && t && n && i)) throw new s(416); var a = { order_price: e, product_name: t, body: n, open_id: i, pay_type: 4 }; let c = o._config.parameters.PAY; return r(c, "post", a) } } }, function(t, n, r) { const o = r(0), s = r(3), i = { setup(e) { let t = []; Object.assign(e, { on(e, n) { "function" == typeof n && t.push([e, n]) }, emit(e, ...n) { t.forEach(([t, r]) => e === t && r(...n)) }, removeAllListeners() { t = [] } }) } }; t.exports = class { constructor() { if (!o._config.applicationId) throw new s(415); this.config = { host: "wss.bmobcloud.com" }, i.setup(this.emitter = {}), this.applicationId = o._config.applicationId, this.initialize() } handshake() { var t = "https://" + this.config.host + "/socket.io/1/?t=" + (new Date).getTime(), n = JSON.stringify({}); return new Promise((r, o) => { wx.request({ method: "GET", url: t, data: n, header: { "content-type": "text/plain" }, success: function(t) { return t.data && t.data.statusCode ? r("request error", e) : 200 !== t.statusCode ? r("request error", e) : r(function(e) { if (!(e instanceof s)) return e.split(":")[0]; self.connecting = !1, self.onError(e.message) }(t.data)) }, fail: function(e) { return r("request error", e) } }) }) } initialize() { return this.handshake().then(e => { try { this.connect(`wss://${this.config.host}/socket.io/1/websocket/` + e, {}) } catch (e) { throw console.error({ connectError: e }), e } }), this.on("close", () => { console.log("连接已中断") }), new Promise((e, t) => { this.on("server_pub", e => { switch (e.action) { case "updateTable": this.onUpdateTable(e.tableName, e.data); break; case "updateRow": this.onUpdateRow(e.tableName, e.objectId, e.data); break; case "deleteTable": this.onDeleteTable(e.tableName, e.data); break; case "deleteRow": this.onDeleteRow(e.tableName, e.objectId, e.data) } }), this.on("client_send_data", e => { this.onInitListen() }) }) } onInitListen() {} connect(e, t) { const n = Object.keys(t).map(e => `${e}=${encodeURIComponent(t[e])}`).join("&"), r = e.indexOf("?") > -1 ? "&" : "?"; return e = [e, n].join(r), new Promise((n, r) => { wx.onSocketOpen(n), wx.onSocketError(r), wx.onSocketMessage(e => { try { let t = function(e) { const { name: t, args: n } = JSON.parse(e); return { name: t, args: n } }, n = e.data; if ("2:::" === n.slice(0, 4) && this.emit(!1, !0), null === (n = n.slice(4)) || "" === n) return; const { name: r, args: o } = t(n); let s = null == o ? "" : JSON.parse(o[0]); this.emitter.emit(r, s) } catch (t) { console.log("Handle packet failed: " + e.data, t) } }), wx.onSocketClose(() => this.emitter.emit("close")), wx.connectSocket({ url: e, header: t }) }) } on(e, t) { this.emitter.on(e, t) } emit(e, t) { t = void 0 === t ? "5:::" : "2:::", e = e ? JSON.stringify(e) : "", wx.sendSocketMessage({ data: t + e }) } emitData(e, t) { return { name: e, args: [t = JSON.stringify(t)] } } updateTable(e) { var t = { appKey: this.applicationId, tableName: e, objectId: "", action: "updateTable" }; t = this.emitData("client_sub", t), this.emit(t) } unsubUpdateTable(e) { var t = { appKey: this.applicationId, tableName: e, objectId: "", action: "unsub_updateTable" }; t = this.emitData("client_sub", t), this.emit(t) } updateRow(e, t) { var n = { appKey: this.applicationId, tableName: e, objectId: t, action: "updateRow" }; n = this.emitData("client_sub", n), this.emit(n) } unsubUpdateRow(e, t) { var n = { appKey: this.applicationId, tableName: e, objectId: t, action: "unsub_updateRow" }; n = this.emitData("client_sub", n), this.emit(n) } deleteTable(e) { var t = { appKey: this.applicationId, tableName: e, objectId: "", action: "deleteTable" }; t = this.emitData("client_sub", t), this.emit(t) } unsubDeleteTable(e) { var t = { appKey: this.applicationId, tableName: e, objectId: "", action: "unsub_deleteTable" }; t = this.emitData("client_sub", t), this.emit(t) } deleteRow(e, t) { var n = { appKey: this.applicationId, tableName: e, objectId: t, action: "deleteRow" }; n = this.emitData("client_sub", n), this.emit(n) } unsubDeleteRow(e, t) { var n = { appKey: this.applicationId, tableName: e, objectId: t, action: "unsub_deleteRow" }; n = this.emitData("client_sub", n), this.emit(n) } onUpdateTable(e, t) {} onUpdateRow(e, t, n) {} onDeleteTable(e, t) {} onDeleteRow(e, t, n) {} } }, function(e, t, n) { const r = n(4), o = n(0), s = n(3), { isObject: i, isString: a } = n(2); e.exports = { generateCode: e => { if (!i(e)) throw new s(415); let t = o._config.parameters.GENERATECODE; return r(t, "post", e) }, sendMessage: e => 1, getAccessToken: e => { let t = o._config.parameters.GETACCESSTOKEN; return r(t, "get") }, sendWeAppMessage: e => { if (!i(e)) throw new s(415); let t = o._config.parameters.SENDWEAPPMESSAGE; return r(t, "post", e) }, refund: e => { if (!i(e)) throw new s(415); let t = o._config.parameters.REFUND; return r(t, "post", e) }, notifyMsg: e => { if (!i(e)) throw new s(415); let t = o._config.parameters.NOTIFYMSG; return r(t, "post", e) }, functions: (e, t) => { if (t || (t = {}), !a(e)) throw new s(415); const n = `${o._config.parameters.FUNCTIONS}/${e}`; return new Promise((e, o) => { r(n, "post", t).then(({ result: t }) => { try { e(JSON.parse(t)) } catch (n) { e(t) } }).catch(e => { o(e) }) }) }, timestamp: () => { let e = o._config.parameters.TIMESTAMP; return r(e, "get") }, requestPasswordReset: e => { if (!i(e)) throw new s(415); let t = o._config.parameters.REQUESTPASSWORDRESET; return r(t, "post", e) }, resetPasswordBySmsCode: (e, t) => { if (!a(e)) throw new s(415); let n = `${o._config.parameters.RESETPASSWORDBYSMSCODE}/${e}`; return r(n, "put", t) }, updateUserPassword: (e, t) => { if (!i(t) || !a(e)) throw new s(415); let n = `${o._config.parameters.UPDATEUSERPASSWORD}/${e}`; return r(n, "put", t) }, geoPoint: ({ latitude: e, longitude: t }) => { return ((e, t) => { if (e < -90) throw new s(419); if (e > 90) throw new s(419); if (t < -180) throw new s(419); if (t > 180) throw new s(419) })(e, t), { __type: "GeoPoint", latitude: e, longitude: t } }, checkMsg: e => { if (!a(e)) throw new s(415); let t = `${o._config.parameters.CHECK_MSG}`; return r(t, "post", { content: e }) }, push: e => { if (!i(e)) throw new s(415); let t = o._config.parameters.PUSH; return r(t, "post", e) } } }, function(e, t, n) { const r = n(4), o = n(0), s = n(3), { isObject: i, isString: a } = n(2); e.exports = { requestSmsCode: (e, t) => { if (!i(e)) throw new s(415); let n = o._config.parameters.REQUESTSMSCODE; return r(n, "post", e) }, verifySmsCode: (e, t, n) => { if (!a(e)) throw new s(415); if (!i(t)) throw new s(415); let c = `${o._config.parameters.VERIFYSMSCODE}/${e}`; return r(c, "post", t) } } }]) });以上就是本文的全部内容，希望对大家的学习有所帮助，也希望大家多多支持轩宇网。
微信小程序自定义带价格显示日历效果
这篇文章主要为大家详细介绍了微信小程序自定义带价格显示日历效果，具有一定的参考价值，感兴趣的小伙伴们可以参考一下本文实例为大家分享了微信小程序自定义日历效果的具体代码，供大家参考，具体内容如下JS代码：var Moment = require("../../utils/moment.js"); var DATE_YEAR = new Date().getFullYear(); var DATE_MONTH = new Date().getMonth() + 1; var DATE_DAY = new Date().getDate(); Page({ data: { year: '', month: '', day: '', days: {}, systemInfo: {}, weekStr: ['日', '一', '二', '三', '四', '五', '六'], checkDate:[] }, onLoad: function(options) { var _this = this; let now = new Date(); let year = now.getFullYear(); let month = now.getMonth() + 1; // 页面初始化 options为页面跳转所带来的参数 this.createDateListData(); this.setData({ year: year, month: month }) wx.getSystemInfo({ success: function(res) { _this.setData({ systemInfo: res, }); } }) }, onReady: function() { // 页面渲染完成 }, onShow: function() { }, /**创建日历数据 */ createDateListData: function(setYear, setMonth) { //全部时间的月份都是按0~11基准，显示月份才+1 let dateArr = []; //需要遍历的日历数组数据 let arrLen = 0; //dateArr的数组长度 let now = setYear ? new Date(setYear, setMonth) : new Date(); let year = setYear || now.getFullYear(); let nextYear = 0; let month = setMonth || now.getMonth(); //没有+1方便后面计算当月总天数 let nextMonth = (month + 1) > 11 ? 1 : (month + 1); console.log("当前选中月nextMonth：" + nextMonth); //目标月1号对应的星期 let startWeek = this.getWeek(year, nextMonth, 1); //new Date(year + ',' + (month + 1) + ',' + 1).getDay(); console.log("目标月1号对应的星期startWeek:" + startWeek); //获取目标月有多少天 let dayNums = this.getTotalDayByMonth(year, nextMonth); //new Date(year, nextMonth, 0).getDate(); console.log("获取目标月有多少天dayNums:" + dayNums); let obj = {}; let num = 0; if (month + 1 > 11) { nextYear = year + 1; dayNums = new Date(nextYear, nextMonth, 0).getDate(); } for (var j = -startWeek + 1; j <= dayNums; j++) { var tempWeek = -1; if (j > 0) { tempWeek = this.getWeek(year, nextMonth, j); //console.log(year + "年" + month + "月" + j + "日" + "星期" + tempWeek); } var clazz = ''; if (tempWeek == 0 || tempWeek == 6) clazz = 'week' if (j < DATE_DAY && year == DATE_YEAR && nextMonth == DATE_MONTH) //当天之前的日期不可用 clazz = 'unavailable ' + clazz; else clazz = '' + clazz /**如果当前日期已经选中，则变色 */ var date = year + "-" + nextMonth + "-" + j; var index = this.checkItemExist(this.data.checkDate, date); if (index != -1) { clazz = clazz + ' active'; } dateArr.push({ day: j, class: clazz, amount:'￥99.8' }) } this.setData({ days: dateArr }) }, /** * 上个月 */ lastMonthEvent:function(){ //全部时间的月份都是按0~11基准，显示月份才+1 let year = this.data.month - 2 < 0 ? this.data.year - 1 : this.data.year; let month = this.data.month - 2 < 0 ? 11 : this.data.month - 2; this.setData({ year: year, month: (month + 1) }) this.createDateListData(year, month); }, /** * 下个月 */ nextMonthEvent:function(){ //全部时间的月份都是按0~11基准，显示月份才+1 let year = this.data.month > 11 ? this.data.year + 1 : this.data.year; let month = this.data.month > 11 ? 0 : this.data.month; this.setData({ year: year, month: (month + 1) }) this.createDateListData(year, month); }, /* * 获取月的总天数 */ getTotalDayByMonth: function(year, month) { month = parseInt(month, 10); var d = new Date(year, month, 0); return d.getDate(); }, /* * 获取月的第一天是星期几 */ getWeek: function(year, month, day) { var d = new Date(year, month - 1, day); return d.getDay(); }, /** * 点击日期事件 */ onPressDateEvent: function(e) { var { year, month, day, amount } = e.currentTarget.dataset; console.log("当前点击的日期：" + year + "-" + month + "-" + day); //当前选择的日期为同一个月并小于今天，或者点击了空白处（即day<0），不执行 if ((day < DATE_DAY && month == DATE_MONTH) || day <= 0) return; this.renderPressStyle(year, month, day, amount); }, renderPressStyle: function (year, month, day, amount) { var days = this.data.days; //渲染点击样式 for (var j = 0; j < days.length; j++) { var tempDay = days[j].day; if (tempDay == day) { var date = year + "-" + month + "-" + day; var obj = { day: date, amount: amount }; var checkDateJson = this.data.checkDate; var index = this.checkItemExist(checkDateJson, date); if (index == -1) { checkDateJson.push(obj); days[j].class = days[j].class + ' active'; } else { checkDateJson.splice(index, 1); days[j].class = days[j].class.replace('active',' '); } this.setData({ checkDate: checkDateJson }) console.log(JSON.stringify(this.data.checkDate)); break; } } this.setData({ days: days }); }, /**检查数组中是否存在该元素 */ checkItemExist: function (arr,value){ for (var i = 0; i < arr.length; i++) { if (value === arr[i].day) { return i; } } return -1; } })WXML代码：<view class="date-year-month"><image bindtap='lastMonthEvent' src='../../image/left.png'></image>{{year}}年{{month}}月<image src='../../image/right.png' bindtap='nextMonthEvent' ></image></view> <view ></view> <view> <view style="background:#F5F5F5;font-size: 30rpx; "> <view class="layout-flex row" style="background-color: #F5F5F5;"> <text class="date-week" style="width:{{systemInfo.windowWidth/7-10}}px;height:20px" wx:for="{{weekStr}}" wx:key="{{index}}"> <text wx:if="{{item !=='日' && item !=='六'}}">{{item}}</text> <text wx:if="" class="week">{{item}}</text> </text> </view> </view> <view class="layout-flex row" style="flex-wrap: wrap;margin-top:30rpx;"> <view class="date-day {{item.day<=0?'bgwhite':item.class}}" style="width:{{systemInfo.windowWidth/7-10}}px;height:{{systemInfo.windowWidth/7}}px;" data-year="{{year}}" data-month="{{month}}" data-day="{{item.day}}" data-amount="{{item.amount}}"bindtap="onPressDateEvent" wx:for="{{days}}" wx:key="{{index}}"> <view class='item-days'> <text>{{item.day>0?(item.daytext?item.daytext:item.day):''}}</text> <text class='amount' wx:if='{{item.day>0}}'>{{item.amount}}</text> </view> </view> </view> </view>WXSS代码/* pages/dateSelect/dateSelect.wxss */ .date-day { display: flex; padding: 5px; text-align: center; justify-content: center; align-items: center; flex-direction: column; } .date-day.bgitem { background-color: #d8ecf9; } .date-day.active { background: #099fde; color: #fff; } .date-day.unavailable { color: #aaa; } .date-week { display: flex; justify-content: center; align-content: center; margin: 5px; } .week { color: #099fde; } .row { display: flex; flex-direction: row; } .item-days { display: flex; flex-direction: column; justify-content: center; align-items: center; font-size: 35rpx; } .amount{ font-size: 30rpx; } .bgwhite { background-color: #fff; } .date-year-month { text-align: center; font-size: 35rpx; height: 100rpx; line-height: 100rpx; display: flex; justify-content: center; align-items: center; } .date-year-month image{ height: 50rpx; width: 50rpx; margin: 0 30rpx; }moment.jsvar Moment = function (date) { var date; if (date) this.date = new Date(date); else this.date = new Date(); return this; }; /** * 对Date的扩展，将 Date 转化为指定格式的String * 月(M)、日(d)、12小时(h)、24小时(H)、分(m)、秒(s)、周(E)、季度(q) 可以用 1-2 个占位符 * 年(y)可以用 1-4 个占位符，毫秒(S)只能用 1 个占位符(是 1-3 位的数字) * eg: * "yyyy-MM-dd hh:mm:ss.S" ==> 2006-07-02 08:09:04.423 * "yyyy-M-d h:m:s.S" ==> 2006-7-2 8:9:4.18 * "yyyy-MM-dd E HH:mm:ss" ==> 2009-03-10 二 20:09:04 * "yyyy-MM-dd EE hh:mm:ss" ==> 2009-03-10 周二 08:09:04 * "yyyy-MM-dd EEE hh:mm:ss" ==> 2009-03-10 星期二 08:09:04 */ Moment.prototype.format = function (format) { var date = this.date; /* var r= /^(\d{4})-(\d{1,2})-(\d{1,2})$/; //正则表达式 匹配出生日期(简单匹配) r.exec('1985-10-15'); s1=RegExp.$1;s2=RegExp.$2;s3=RegExp.$3;//结果为1985 10 15 */ if (typeof date === 'string') date = this.parse(date); var o = { "M+": date.getMonth() + 1, //月份 "(d+|D+)": date.getDate(), //日 "(h+|H+)": date.getHours(), //小时 "m+": date.getMinutes(), //分 "s+": date.getSeconds(), //秒 "q+": Math.floor((date.getMonth() + 3) / 3), //季度 "S": date.getMilliseconds() //毫秒 }; var week = { "0": "/u65e5", "1": "/u4e00", "2": "/u4e8c", "3": "/u4e09", "4": "/u56db", "5": "/u4e94", "6": "/u516d" }; if (/(y+|Y+)/.test(format)) format = format.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length)); if (/(E+)/.test(format)) format = format.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "/u661f/u671f" : "/u5468") : "") + week[date.getDay() + ""]); for (var k in o) { if (new RegExp("(" + k + ")").test(format)) format = format.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); } return format; } Moment.prototype.parse = function () { return this.date; } /** * 计算两个日期差差 * return day */ Moment.prototype.differ = function (date) { var time1 = this.date.getTime(); if (typeof date === 'string') date = new Date(date); var time1 = this.date.getTime(); var time2 = date.getTime(); var differ = Math.ceil((time1 - time2) / (1000 * 3600 * 24));//除不尽时,向上取整 return differ; } Moment.prototype.add = function (num, optionType) { var date = this.date; if ('day' === optionType) { date.setDate(date.getDate() + num); } if ('month' === optionType) { date.setMonth(date.getMonth() + num); } if ('year' === optionType) { date.setFullYear(date.getFullYear() + num); } this.date = date; return this; } Moment.prototype.before = function (date) { return this.date.getTime() < new Date(date).getTime() } Moment.prototype.after = function (date) { return this.date.getTime() > date.getTime() } module.exports = function (date) { return new Moment(date); }以上就是本文的全部内容，希望对大家的学习有所帮助，也希望大家多多支持轩宇网。
微信小程序日历弹窗选择器代码实例
这篇文章主要介绍了微信小程序日历弹窗选择器，文中通过示例代码介绍的非常详细，对大家的学习或者工作具有一定的参考学习价值，需要的朋友们下面随着小编来一起学习学习吧应项目需求，写了一个弹窗日历选择器，感觉用着还不错，封装了一下，分享给大家，希望大家有什么意见可以指出来相互交流共同改进！先上一个效果图：（当天日期为2019-05-10）直接上代码：wxml:<view class="weui-cells weui-cells_after-title" style='margin-top:100rpx;'> <view class="weui-cell weui-cell_access" hover-class="weui-cell_active" catchtap='showModalBtn'> <view class="weui-cell__bd">选择时间</view> <view class="weui-cell__ft weui-cell__ft_in-access">{{chooseDate}}</view> </view> </view> <view class="modal-mask" bindtap="hideModal" catchtouchmove="preventTouchMove" hidden="{{showModal}}"></view> <view class="modal-dialog" hidden="{{showModal}}"> <view class='modalBox'> <view class='box'> <view class='calendarBox'> <view class='calendarTitle'> 当前月份: <text style='font-size:46rpx;'>{{thisMonth}}</text> 月 </view> <block wx:for="{{week}}" wx:key="item"> <view class="week">{{week[index]}}</view> </block> <block wx:for="{{weekNum}}" wx:key="item"> <view class="week" style="border-bottom:0;color:transparent">0</view> </block> <block wx:for="{{dayList}}" wx:key="item"> <view class='week' style="border-bottom:0;background-color:{{dayIndex>index?'#f1f1f1':(tapThis==index?'#1296db':'')}};color:{{tapThis==index?'white':''}}" catchtap="chooseDate" data-index="{{index}}" data-value="{{item}}">{{item}}</view> </block> </view> </view> </view> </view>wxss:.modalBox{ width: 100%; font-size: 32rpx; } .box{ margin: 0 auto; width: 630rpx; } .calendarTitle{ /* margin: 0 auto; width: 630rpx; */ width: 100%; height: 80rpx; line-height: 80rpx; text-align: center; border-bottom: 1rpx solid #ddd; } .calendarBox{ /* width: 630rpx; */ width:100%; margin: 0 auto; border:1rpx solid #ddd; } .week{ display: inline-block; width:90rpx; height: 80rpx; text-align: center; line-height: 80rpx; border-bottom: 1rpx solid #ddd; } .dateBtn{ width:100%; height: 80rpx; display: flex; justify-content: space-between; margin-top: 20rpx; } .dateBtn>button{ width: 45%; height: 100%; display:flex; justify-content: center; align-items: center; margin: 0; font-size: 36rpx; } /* 模态框 */ .modal-mask { width: 100%; height: 100%; position: fixed; top: 0; left: 0; background: #000; opacity: 0.5; overflow: hidden; z-index: 9000; } .modal-dialog { width: 85%; padding: 100rpx 30rpx 30rpx 30rpx; overflow: hidden; position: fixed; top: 20%; left: 0; right: 0; margin: 0 auto; z-index: 9999; background: rgba(255, 255, 255, 1); border-radius: 5rpx; } js:Page({ /** * 页面的初始数据 */ data: { showModal:true, weekLength:7, week:["日","一","二","三","四","五","六"], dayList:[], weekNum:0, tapThis:0, thisMonth:0, thisYear:0, dayIndex:0, chooseDate:"", }, getWeek(year,month,day){ var that = this; var d = new Date(); d.setFullYear(year); d.setMonth(month-1); d.setDate(1); var n = d.getDay(); var arr =[]; var Index=0; var dayN=1; for(var i = 0; i<day; i++){ arr.push(dayN++); } var now = new Date(); var nowYear = now.getFullYear(); var nowMonth = now.getMonth()+1; var nowDay = now.getDate(); var val = 1; if(year==nowYear){ if(month==nowMonth){ Index=arr.indexOf(nowDay); console.log(Index); val = nowDay; } } that.setData({ weekNum:n, dayList:arr, dayIndex:Index, tapThis:Index, thisMonth:month, thisYear:year, chooseDate:year+"-"+month+"-"+val, }) }, chooseDate(e){ var that = this; var n = e.currentTarget.dataset.index; var val = e.currentTarget.dataset.value; console.log(n); if(n>=that.data.dayIndex){ that.setData({ tapThis:n, chooseDate:that.data.thisYear+"-"+that.data.thisMonth+"-"+val, showModal:true, }) } }, /** * 弹出框蒙层截断touchmove事件 */ preventTouchMove: function () { }, /** * 隐藏模态对话框 */ hideModal() { var that = this; that.setData({ showModal: true, }) }, showModalBtn(){ var that = this; that.setData({ showModal:false }) }, /** * 生命周期函数--监听页面加载 */ onLoad: function (e) { var that = this; that.getWeek("2018","04","31"); //使用方法： 在此函数内传入年、月、日(此月的天数)即可。 } })代码设计思路：1、此代码是符合我们公司实际情况定制的，选择哪个月份，需要传递哪个月份的参数，比如我要2018-04的日历选择器，那么我需要在 getWeek() 中传递年，月，日（此月的总天数）作为参数，代码会自动计算出当月的一号是星期几并且排版好！如果不知道此月的天数 ，这里还提供如下代码方便各位码友计算出各个月份的天数getDayNum(year,month){ //传入参数年份 和 要计算的月份， 可以为字符串，也可以为数字。 var that = this; var d = new Date(); d.setFullYear(year); d.setMonth(month); d.setDate(0); console.log(d.getDate()); //d.getDate() 即为此月的总天数！ },2、具体思路就是：根据传递的参数计算出当月的第一天为星期几，然后从星期几开始排列，通过循环{{总天数}}次，让日期循环出来。然后再获取当前日期，判断日历弹窗与当前月份是否吻合，如果吻合，就要将在当前日期之前的日期都设置为不可点击状态。然后就是点击获取值，整个日历流程完毕。为了美观大家记得引入weui.wxss只需要在app.wxss中加入@import 'weui.wxss';以上所述是小编给大家介绍的微信小程序日历弹窗选择器详解整合，希望对大家有所帮助，如果大家有任何疑问请给我留言，小编会及时回复大家的。在此也非常感谢大家对轩宇网的支持！
这篇文章主要为大家详细介绍了微信小程序实现左右列表联动，具有一定的参考价值，感兴趣的小伙伴们可以参考一下本文实例为大家分享了微信小程序实现左右列表联动的具体代码，供大家参考，具体内容如下效果图：直接上代码：wxml界面:<view class='header'> <text class='headerClass'>分类</text> <text class='headerPin'>/品牌</text> <view class="search"> <image src='/images/搜索.png'></image> <text>搜索商品</text> </view> </view> <view class='main'> <view class='left'> <scroll-view scroll-y="true" style="height: 1100rpx" scroll-into-view="true" scroll-with-animation="true"> <block wx:for="{{leftText}}" wx:for-list="item"> <view class="{{classfiySelect == item.id?'active':''}}" data-id='{{item.id}}' bindtap='left_list'> <text>{{item.text1}}</text> </view> </block> </scroll-view> </view> <view class='right'> <scroll-view scroll-y="true" style="height: 1100rpx" bindscroll="scroll" scroll-top="{{scrollTop}}" scroll-into-view="{{'inToview'+rigId}}" scroll-with-animation="true"> <block wx:for="{{rightData}}" wx:for-list="item"> <view class='itemTitle' id="{{'inToview'+item.id}}">{{item.title}}</view> <view bindtap='particulars' class='listItem' data-id='{{item.id}}'> <block wx:for="{{item.frist}}"> <view class='listItem2' data-text="{{}}"> <view class='img'> <image src='{{item.url}}'></image> </view> <view class='listText'> <text>{{item.text}}</text> <text class='money'>¥{{item.money}}</text> <view> <text>已售{{item.sum}}</text> 立即抢购 </view> </view> </view> </block> </view> </block> </scroll-view> </view> </view>js核心代码： // pages/class/class.js Page({ /** * 页面的初始数据 */ data: { classfiySelect: "", leftText: [{ id: "01", text1: "美妆专区", }, { id: "02", text1: "面部清洁", }, { id: "03", text1: "洗护专区", }, { id: "04", text1: "面膜", }, { id: "05", text1: "口红", }, { id: "06", text1: "美妆专区", }, { id: "07", text1: "面部清洁", }, { id: "08", text1: "洗护专区", }, { id: "09", text1: "面膜", }, { id: "010", text1: "口红", }, { id: "011", text1: "美妆专区", }, { id: "012", text1: "面部清洁", }, { id: "013", text1: "洗护专区", }, { id: "014", text1: "面膜", }, { id: "015", text1: "口红", }, { text1: "美妆专区", }, { text1: "面部清洁", }, { text1: "洗护专区", }, { text1: "面膜", }, { text1: "口红", }, ], rightData: [{ id: "01", title: "美妆专区", frist: [{ url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, id:1, }, { url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, id: 2, }, { url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, ], }, { id: "02", title: "面部清洁", frist: [{ url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, { url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, { url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, ], }, { id: "03", title: "洗护专区", frist: [{ url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, { url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, { url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, ], }, { id: "04", title: "面膜", frist: [{ url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, { url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, { url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, ], }, { id: "05", title: "口红", frist: [{ url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, { url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, { url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, ], }, { id: "06", title: "美妆专区", frist: [{ url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, { url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, { url: "/images/85309.jpg", text: "卡姿兰补水套装", money: 200, sum: 20, }, ], }, ], }, /** * 生命周期函数--监听页面加载 */ onLoad: function(options) { this.setData({ classfiySelect: this.data.leftText[0].id }) }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady: function() { }, /** * 生命周期函数--监听页面显示 */ onShow: function() { }, /** * 生命周期函数--监听页面隐藏 */ onHide: function() { }, /** * 生命周期函数--监听页面卸载 */ onUnload: function() { }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh: function() { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom: function() { }, /** * 用户点击右上角分享 */ onShareAppMessage: function() { }, //滚动触发 scroll: function(e) { var scrollTop = e.detail.scrollTop, h = 0, classfiySelect; var that = this; that.data.leftText.forEach(function(clssfiy, i) { var _h =26 + that.length(clssfiy['id'])*102; if (scrollTop >= h){ classfiySelect = clssfiy['id']; } h +=_h; console.log(h); }) that.setData({ classfiySelect: classfiySelect, }) }, //求每一栏高度 length: function(e) { var that = this; var rightData = that.data.rightData; for (var i = 0; i < rightData.length; i++) { if(rightData[i]['id']==e){ return rightData[i]['frist'].length; } } }, //点击左边事件 left_list: function(e) { var that = this; var l_id = e.currentTarget.dataset.id; that.setData({ rigId: l_id, }) }, //跳转详情界面 particulars:function(e){ } }) wxss界面：.header{ display: flex; background-color: rgba(219, 219, 221, 0.884); align-items: center; height: 60rpx; } .active{ color: red; } .header .headerClass{ color: red; margin-left: 20rpx; } .header .headerClass, .header .headerPin{ font-size: 28rpx; } .search{ display: flex; height: 46rpx; border-radius: 20rpx; margin-left: 30rpx; background-color:white; width: 70%; } .search text{ color: gainsboro; font-family: monospace; font-size: 30rpx; line-height: 46rpx; } .search image{ padding-left:50rpx; width: 46rpx; height: 46rpx; } .main{ display: flex; } .left{ width: 25% } .left view{ padding-top: 30rpx; text-align: center; } .right{ width: 75%; } .listItem2{ display: flex; } .listItem .img{ width: 200rpx; height: 200rpx; text-align: center; padding-top: 10rpx; } .listItem .img image{ width: 80%; height: 80% } .itemTitle{ font-size: 32rpx; padding-left: 20rpx; padding-top: 10rpx; color:gray; } .listItem .listText{ display: flex; flex-direction: column; margin-top: 6rpx; } .listItem .listText view{ display: flex; align-items: flex-end; } .listItem .listText text{ font-size: 34rpx; margin-top: 10rpx; } .listItem .listText .money{ color: red; } .listItem .listText view text{ font-size: 28rpx; color :silver; margin-right: 60rpx; } .listItem .listText view button{ background-color: red; color: white; padding-right: 8px; padding-left: 8px; padding-top: 0px; } ::-webkit-scrollbar { width: 6px; height: 6px; background-color: #ffffff; } ::-webkit-scrollbar-track{ height: 20rpx; color: black; }以上就是本文的全部内容，希望对大家的学习有所帮助，也希望大家多多支持轩宇网。