首页
免费后端云服务
关于
推荐
免费图床源码
Search
1
小程序后端入门系列视频教程【一-微信开发工具介绍】
9,715 阅读
2
微信小程序三级联动之多列选择器
9,598 阅读
3
小程序开发免费后端之神秘利器分享
9,526 阅读
4
Golang-开发企业级资源权限管理【第一步表设计】-1
9,075 阅读
5
学会微信服务端开发第一步
8,972 阅读
日常记录
日常
随笔
Bmob后端云
从零开始学物联网
Serverless实战驾校小程序
心邮
Serverless
向量数据库
登录
Search
Magic
累计撰写
120
篇文章
累计收到
21
条评论
首页
栏目
日常记录
日常
随笔
Bmob后端云
从零开始学物联网
Serverless实战驾校小程序
心邮
Serverless
向量数据库
页面
免费后端云服务
关于
推荐
免费图床源码
搜索到
118
篇与
的结果
2016-10-29
微信心邮小程序开发实战(2)-信箱功能
回顾上一篇文章讲了微信小程序准备工作,并建立了小程序信箱数据表第一步:在微信小程序开发工具Pages建立信箱文件mail/ ├── mail.js ├── mail.json ├── mail.wxml └── mail.wxss 1. mail.js页面显示时查询数据把查询的数据setData到模版页面//index.js //获取应用实例 var common = require('../template/getCode.js') var Bmob = require("../../utils/bmob.js"); var that; var molist; var app = getApp() Page({ data: { moodList: [], limit: 6, loading: false, windowHeight1: 0, windowWidth1: 0, scrollTop: { scroll_top1: 0, goTop_show: false } }, onLoad: function (e) { that = this; that.setData({ loading: false }) }, //页面显示时执行 onShow: function () { molist = new Array(); var myInterval = setInterval(getReturn, 500);//半秒定时查询 //获取服务端数据 function getReturn() { wx.getStorage({ key: 'user_id', success: function (ress) {//根据User_id查询 if (ress.data) { clearInterval(myInterval)//清楚定时查询 var Diary = Bmob.Object.extend("Diary"); var query = new Bmob.Query(Diary); query.equalTo("is_hide", "1"); query.descending("createdAt"); query.include("publisher"); // 查询所有数据 query.find({ success: function (results) {//数据查询成功 that.setData({ loading: true }); //数据重新初始化 for (var i = 0; i < results.length; i++) { var publisherId = results[i].get("publisher").id; var title = results[i].get("title"); var content = results[i].get("content"); var id = results[i].id; var createdAt = results[i].createdAt; var _url; var likeNum = results[i].get("likeNum"); var commentNum = results[i].get("commentNum"); var pic = results[i].get("pic"); if (pic) { _url = results[i].get("pic")._url; } else { _url = null; } var name = results[i].get("publisher").get("nickname"); var userPic = results[i].get("publisher").get("userPic"); var liker = results[i].get("liker"); var isLike = 0; for (var j = 0; j < liker.length; j++) { if (liker[j] == ress.data) { isLike = 1; break; } } var jsonA; if (pic) { jsonA = '{"title":"' + title + '","content":"' + content + '","id":"' + id + '","avatar":"' + userPic + '","created_at":"' + createdAt + '","attachment":"' + _url + '","likes":"' + likeNum + '","comments":"' + commentNum + '","is_liked":"' + isLike + '","username":"' + name + '"}' } else { jsonA = '{"title":"' + title + '","content":"' + content + '","id":"' + id + '","avatar":"' + userPic + '","created_at":"' + createdAt + '","likes":"' + likeNum + '","comments":"' + commentNum + '","is_liked":"' + isLike + '","username":"' + name + '"}'; } var jsonB = JSON.parse(jsonA); //每条数据重新写入到数组 molist.push(jsonB) that.setData({ moodList: molist, loading: true }) } }, error: function (error) { common.dataLoading(error, "loading"); that.setData({ loading: true }) console.log(error) } }); } }, fail: function (error) { console.log("失败") } }) } }, //分享页面 onShareAppMessage: function () { return { title: '心邮', desc: '倾诉烦恼,邮寄心情,分享快乐', path: '/pages/index/index' } }, onPullDownRefresh: function () { wx.stopPullDownRefresh() }, scrollTopFun: function (e) { if (e.detail.scrollTop > 300) { this.setData({ 'scrollTop.goTop_show': true }); } else { this.setData({ 'scrollTop.goTop_show': false }); } }, goTopFun: function (e) { var _top = this.data.scrollTop.scroll_top1;//发现设置scroll-top值不能和上一次的值一样,否则无效,所以这里加了个判断 if (_top == 1) { _top = 0; } else { _top = 1; } this.setData({ 'scrollTop.scroll_top1': _top }); this.onShow(); } }) 2. mail.wxml写入循环输出数据wx:for-items="{{moodList}}"<loading hidden="{{loading}}"> 加载中... </loading> <import src="../template/list.wxml" /> <!--<scroll-view lower-threshold="800" bindscrolltolower="pullUpLoad" upper-threshold="0" scroll-y="true" style="height: {{windowHeight1}}px; width: {{windowWidth1}}px; " scroll-top="{{scrollTop.scroll_top1}}" bindscroll="scrollTopFun">--> <view class="index_list"> <navigator url="../listDetail/listDetail?moodId={{item.id}}" hover-class="navigator-hover" wx:for-items="{{moodList}}" wx:key="moodListId" wx:if="{{item.id}}"> <template is="listHeader" data="{{userPic:item.avatar,userNick:item.username,publishTime:item.created_at}}" /> <template is="listTemp" data="{{listPic:item.attachment,listTitle:item.title,listContent:item.content}}" /> <view class="list_footer"> <view class="agreeNum agree_{{item.is_liked}}">{{item.likes}}</view> <view class="commNum">{{item.comments}}</view> </view> </navigator> </view> <!--</scroll-view>--> <view class="bord"></view> <view class="returnTop" wx:if="{{scrollTop.goTop_show}}" catchtap="goTopFun"> </view>第二步:在微信小程序开发工具更改配置文件 app.json第三步:在管理后台数据库添加一些数据至此微信小程序信箱功能已经完成我们可以看到这里主要的代码就是页面显示查询出数据,写在onshow里面。模版页面无非是展示出来,下面贴一段查询数据的源码。 var Diary = Bmob.Object.extend("表名称"); var query = new Bmob.Query(Diary); query.get("4edc3f6ee9", { success: function(result) { // The object was retrieved successfully. console.log("该日记标题为"+result.get("title")); }, error: function(result, error) { console.log("查询失败"); } });
2016年10月29日
3,359 阅读
0 评论
16 点赞
2016-08-09
Bmob云-Serverless-开发公众号邀请返利
Bmob后端云 公众号邀请返利开发APP里有个注册页面,希望互相转发微信,邀请返利。 为了方便传播,注册页面单独用H5页面实现。 为了提高邀请用户质量,提高邀请用户的有效性,我们强制要求微信里面打开才能注册。所以基于公众号开发。 为了快速开发,这里使用Bmob云Serverless 里的Faas服务与文件CDN存储服务。1.准备材料公众号Bmob云Serverless如果想用自己域名,备案好的域名2.设置公众号一、设置AppSecret值开发者ID(AppID)开发者密码(AppSecret)二、设置白名单IP白名单三、设置授权域名接口权限,登陆,找到网页授权域名四、设置调试微信开发者开发者工具-》web开发者工具 【这个跟小程序一样的工具】,添加微信到开发者,最多可以绑定50个3.开发过程一、注册Bmob账号二、创建一个应用三、点击进入云函数编写微信获取用户昵称代码四、新建云函数云函数getOpenId 获取用户openid,拿到openid调用getUserInfo获取用户信息云函数function onRequest (request, response, modules) { var code = request.body.code ? request.body.code : '011jOWiN0vmFa42ynziN0B6bjN0jOWir' //获取数据库对象 var db = modules.oData; var functions = modules.oFunctions; //http请求方式: GET var appid = ''; var secret = ''; var url = 'https://api.weixin.qq.com/sns/oauth2/access_token?appid=' + appid + '&secret=' + secret + '&code=' + code + '&grant_type=authorization_code'; //获取Http模块 var http = modules.oHttp; //发起Get请求 http(url, function (error, res, body) { if (!error && res.statusCode == 200) { //写入数据库 var resultObject = JSON.parse(body); //如果返回错误则打印 if (resultObject.errcode) { response.send(resultObject); } functions.run({ "name": "getUserInfo", "data": { "openid": resultObject.openid, "access_token": resultObject.access_token } }, function (err, data) { //回调函数 response.send(data); }); } }); } getUserInfo云函数function onRequest (request, response, modules) { var db = modules.oData; var openid = request.body.openid || 'ol2Ey0tePs0fdFdVRZKqzu50_83c'; var access_token = request.body.access_token || 'xxxx'; getUserInfoMp(openid, access_token); function getUserInfoMp (openid, access_token) { var http = modules.oHttp; http('https://api.weixin.qq.com/sns/userinfo?access_token=' + access_token + '&openid=' + openid + '&lang=zh_CN', function (error, res, body) { if (!error && res.statusCode == 200) { var at = JSON.parse(body); response.send(body); } response.send(body); }); } } 五.运行流程介绍用户打开一个url,这个url打开后会提示用户是否授权,同意后跳转到自己的网址,并带上code。(URL地址)https://open.weixin.qq.com/connect/oauth2/authorize?appid=wxbafdda995607cc&redirect_uri=https%3a%2f%2fgoldenage.xxxxx.com%2f&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirectredirect_uri参数关键:指定统一授权后打开的网址,接下来就1步,通过code拿到openid。上面函数getOpenId就可以拿到openid,如果需要昵称头像,可以调用第二个云函数getUserInfohttps://mp.weixin.qq.com/wiki?action=doc&id=mp1421140842&t=0.35600785609885244#3)六.如何调用https://cloud.bmob.cn/19b475f87c366db2/getOpenId 方法:post 参数:code: 微信code 返回: {"openid":"ol2Ey0tePs0fdFdVRZKqzu50_83c","nickname":"magic","sex":1,"language":"zh_CN","city":"广州","province":"广东","country":"中国","headimgurl":"http:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/DYAIOgq83epySXbnQqg4MialjffKNKbxj42prvL2aIaIFbs3pj7svlT4gbQeQPbricZNBGYWfv1zcOo86fjwc99Q\/132","privilege":[]}}总结:相比自己服务器开发优势,成本低,速度快。 基于Serverless,的Faas 只需要一个函数,即可实现用户openid功能。如果熟悉,整个微信开发不需要10分钟。这里有个用户点击授权的页面是HTML的,这个HTML我们可以用CDN云存储,把静态html页面保存到文件里面,支持绑定自己域名,让用户访问。 整个开发,不需要购买服务器,ip,环境,微信设置好,一个函数,暴露接口就可以实现。前端网页调用效果截图:
2016年08月09日
2,709 阅读
0 评论
1 点赞
2016-07-17
mongodb运维(3)-db-currentOp与db-killOp命令
好久没更新mongo运维这块知识了,这次介绍 db.currentOp与db.killOp命令数据库优化方法有很多,但所有数据库优化都离不开慢查询优化。mysql、mongodb都可以开启慢查询,来对数据库查询进行分析。开启慢查询日志,对性能会有一定的影响。mongoDB 有时我们只想临时看下慢查询日志,应该如何处理。这时,我们可以用到mongdb的db.currentOp命令 ,他可以列出当前真正跑的op相关信息。1.查看目前正在执行的所有查询语句db.currentOp();2.查询所有操作xxx集合并且执行时间已超过3s的请求db.currentOp( { "active" : true, "secs_running" : { "$gt" : 3 }, "ns" : /^xxx\./ } )3. 当然,如果我当前db集群有非常多的集合,我也可以不限制xxx集合db.currentOp( { "active" : true, "secs_running" : { "$gt" : 3 } } )currentOp的过滤条件包括请求操作类型,insert、update、delete…请求对应的connectionId,threadId请求是否正在等待锁请求执行时间请求操作的DB或collection请求query的内容…等等返回结果如下{ "desc" : "conn44266", "threadId" : "140419266524928", "connectionId" : 44266, "client" : "10.10.68.209", "active" : true, "opid" : 4495651, "secs_running" : 25, "microsecs_running" : NumberLong(25459008), "op" : "command", "ns" : "xxxxx", "query" : { "count" : "c74dc2de71", "query" : { "video" : { "$exists" : true }, "_isdel" : 0, "deleted" : { "$ne" : true }, "verify" : { "$ne" : false } } }, "planSummary" : "IXSCAN { video: 1 }", "numYields" : 189, "locks" : { "Global" : "r", "Database" : "r", "Collection" : "r" }, "waitingForLock" : false, "lockStats" : { "Global" : { "acquireCount" : { "r" : NumberLong(380) } }, "Database" : { "acquireCount" : { "r" : NumberLong(190) } }, "Collection" : { "acquireCount" : { "r" : NumberLong(190) } } } }当我们知道某条语句是锁库的罪魁祸首的时候,我们就可以通过另一条语句,干掉对应的请求。killOp 停止正在执行的查询用法:db.killOp(opid)目前Mongodb手册,还未有一次清掉当前所有查询,文档地址:https://docs.mongodb.com/manual/reference/method/db.killOp/执行后返回{ "info" : "attempting to kill op", "ok" : 1 }db.killOp(opid)的实现原理如下每个连接对应的服务线程存储了一个killPending的字段,当发送killOp时,会将该字段置1;请求在执行过程中,可以通过不断的调用OperationContext::checkForInterrupt()来检查killPending是否被设置,如果被设置,则线程退出。一个请求要支持killOp,必须在请求的处理逻辑里加上checkForInterrupt()检查点才行,否则即使发送了killOp,也只能等待请求完全处理完毕线程才会退出。比如createIndex的处理逻辑里包含了类似如下的代码,在createIndex的循环过程中,一旦killPending被置1了,createIndex的执行可以在当前循环结束时退出。while (!createIndexFinished) { createIndexForOneElement(); checkForInterupt(); }所以发送killOp后,请求要执行到下一个『检查点』线程才会退出,MongoDB在很多可能耗时长的请求中,都加入了checkForInterrupt()检查点,如创建索引,repair database,mapreduce、aggregation等。批量一次清楚当前慢查询上面说还未有一次清掉当前所有查询, 不过我们可以通过手动写脚本实现。此脚本由diggzhang大神贡献。文章链接:http://yangcongchufang.com/kill-mongo-ops.html实现功能:传入自己的IP地址,强制关停自己的异常查询。打开家目录下的.mongorc.js拷贝下面的killMyRunningOps函数进去,重新打开mongoshell即可加载这个函数(mongoshell启动时会预读这个文件)。➜ ~ cat ~/.mongorc.jskillMyRunningOps = function (clientIp) { var currOp = db.currentOp(); for (op in currOp.inprog) { if (clientIp == currOp.inprog[op].client.split(":")[0]) { db.killOp(currentOp.inprog[op].opid) } } }用法很简单,知道自己IP后,调用这个函数:> killMyRunningOps("12.23.32.21")
2016年07月17日
7,443 阅读
0 评论
12 点赞
2016-06-06
Shadow socks 配置
(1) 安装Shadowsocks和Chrome brew install shadowsocks-libev brew cask install google-chrome (2) 安装Chrome插件Proxy SwitchySharp https://chrome.google.com/webstore/detail/proxy-switchysharp/dpplabbmogkhghncfbfdeeokoefdjegm (3) 配置 emacs /usr/local/etc/shadowsocks-libev.json 修改下面的配置 { "server":"", "server_port":, "local_port":, "password":"", "timeout":600, "method":"aes-256-cfb" } 服务器请到https://get发邮件获取,配置完成后是如下: { "server":"hongxchen.github.io", "server_port":1080, "local_port":8104, "password":"abc", "timeout":600, "method":"aes-256-cfb" } 注意:method字段一定要小写 (4) 配置Proxy SwitchySharp 1. 添加新的的配置New Profile 2. Profile Name:Shadowsocks 3. 选择Manual Configuration 4. 在SOCKS Host中填入127.0.0.1和shadowsocks-libev.json中设置的local_port,如8104。HTTP Proxy,HTTPS Proxy,FTP Proxy空着不填。 5. 选择SOCKS v5 6. 切换到 Switch Rules 7. 勾选Enable Switch Rules 8. 勾选Online Rule List,在Rule List URL中填入**list.googlecode.com/svn/trunk/**list.txt,Proxy Profile选择Shadowsocks 9. 勾选AutoProxy Compatible List (5) 测试 终端执行 /usr/local/opt/shadowsocks-libev/bin/ss-local -c /usr/local/etc/shadowsocks-libev.json 打开Chrome,Proxy SwitchySharp选择Auto Switch Mode 打开www.youtube.com等被墙网站,如果不能打开则https://get发邮件获取其他服务的的配置 (6) 开机启动 Ctrl+C关闭在终端中打开执行的ss-local 制作/usr/local/opt/shadowsocks-libev/homebrew.mxcl.shadowsocks-libev.plist文件的软连接到~/Library/LaunchAgents % ln -s /usr/local/opt/shadowsocks-libev/homebrew.mxcl.shadowsocks-libev.plist ~/Library/LaunchAgents/homebrew.mxcl.shadowsocks-libev.plist (7) 加载配置文件 launchctl load ~/Library/LaunchAgents/homebrew.mxcl.shadowsocks-libev.plist ** 卸载为launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.shadowsocks-libev.plist (8) 完成 到此配置完成,以后开机打开Chrome就能够翻出墙外,.shadowsocks.net/get提供的服务器在一段时间后可能不能连接,只需关闭服务在shadowsocks-libev.json文件中写入新的配置项,重新启动服务就行了。 launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.shadowsocks-libev.plist emacs /usr/local/etc/shadowsocks-libev.json launchctl load ~/Library/LaunchAgents/homebrew.mxcl.shadowsocks-libev.plist 转:
2016年06月06日
4 阅读
0 评论
0 点赞
2016-05-24
Serverless实战驾校小程序考题练习三
Serverless实战驾校小程序【考题练习】三 介绍 上一节我们讲了,实现了分类、题目显示、进度条显示等功能,这节我们继续完善答题功能。由于开发时间比较紧,这里主要写实习思路,与核心代码。 这一节做顺序练习与模拟考试。都属于答题详细页面功能 这次进度条可以根据答题进度,显示进度。 这个也用了iview的一个插件, 目前样式没调整, 这个后面再说。这一节主要实现了一些逻辑计算逻辑一:记录学习题目进度 记录的核心代码,在提交保存的时候调用。当然,也可以在练习离开的时候触发,这里给了个按钮,点击保存即可保存学习记录const AddLearning = ({ num, result, type = 1 }) => { let current = wx.Bmob.User.current() return new Promise((resolve, reject) => { const query = wx.Bmob.Query('learning'); query.set('bSubjects', '1') query.set('bModels', '1') query.set('num', num) query.set('result', result) query.set('type', type) query.set('uid', current.objectId) query.save().then(res => { resolve(res) }).catch(err => { console.error(err) reject(err) }) }); }逻辑二:记录题目回答的对错 上面的变量result记录,格式请看上一节数据库格式说明,是题目的对错。这里点击一个选择就记录一次,我在页面data里面增加了一个items变量来保存。选择答案执行以下代码,今天先实现单选,我们单选与多选,判断事件分开来做,这样便于逻辑管理// 单选题 handleFruitChange ({ detail = {}, target = {} }) { let questionInfo = this.data.questionInfo // 判断单选是否正确 if (target.dataset.id) { console.log('ok') questionInfo.isOk = 1 } this.setData({ questionInfo: questionInfo, current: detail.value }); // 单选自动跳到下一题 this.statistical() // 显示第几道题 this.setThisData(this.data.index) this.setData({ index: this.data.index + 1, current: '' }); },逻辑三:答题相关统计 逻辑二讲了,记录对错,这里有一些统计需要拿出来计算,先做单选题,点击选择,判断是否正确, 如果正确,记录到结果对象 [{" id ":" XXX ', '0'}, {" id ":" XXX ", "1"}] ,0代表回答错误,1正确例如错题个数、对题个数,页面提示,进度条进一步statistical () { // 统计错题个数 let questionErr = this.data.questionErr //错题个数 let questionOk = this.data.questionOk //错题个数 let questionInfo = this.data.questionInfo let items = this.data.items let arr = { "id": questionInfo.objectId, "o": 0 } let t = 'error', m = '回答错误' if (questionInfo.isOk === 1) { // o 0代表失败,1代表成功 arr.o = 1 questionOk = questionOk + 1 t = 'success' m = '回答正确' } else { // 错误数+1 questionErr = questionErr + 1 } items.push(arr) // 提示 $Message({ content: m, type: t, duration: 2 }); //进度条 let totalW = this.data.index / this.data.total totalW = (totalW * 100).toFixed(2); totalW = totalW < 1 ? 1 : totalW this.setData({ items: items, questionErr: questionErr, questionOk: questionOk, totalW: totalW, }); },逻辑四:上一题下一题的实现 页面显示第几个题目,我们用数组的下面来记录,单电机下一题,我们记录回答对错,并且数组下标+1// 翻页 handlePageChange ({ detail }) { const type = detail.type; const current = this.data.current if (current == "") { console.log('空') $Toast({ content: '请选择答案!', type: 'warning' }); return; } this.statistical() if (type === 'next') { this.setThisData(this.data.index) this.setData({ index: this.data.index + 1, current: '' }); } else if (type === 'prev') { this.setData({ index: this.data.index - 1, current: '' }); this.setThisData(this.data.index) } },逻辑五:引入模式概念 因为答题页面逻辑非常多,今天写这么多也没写完一般, 除了学习模式,后面还有模拟考试模式,这里不单独使用另外的页面来开发,统一在一个页面。 所以,我们在页面data里加入model变量,代表模式。/** * 这里有个模式, 练习模式,与模拟考试模式 * model 1.练习模式 2.模拟考试考试 * 练习模式查询出所有数据练习 * 模拟考试 随机100题 计算打分 */总结 今天练习模式里面的单项选择逻辑基本已经做好,明天将实现模拟考试,计算考试成绩等等功能大家想学习更多的云服务开发, 可以加入Bmob的交流群:群号:273080081
2016年05月24日
3 阅读
0 评论
0 点赞
1
...
13
14
15
...
24