个人案例
- 基于小程序·云开发的HTTPAPI实现图片上传功能
基于HTTPAPI实现内容管理的图片上传功能 目前基于小程序·云开发可以快速的实现无服务器的小程序快速开发。但是小程序开发工具自带的管理工具,并不方便进行内容管理。因此为了更高效的管理小程序,需要开发后台管理工具,以方便在电脑端进行内容管理。基于此,会陆续连载更新基于小程序·云开发HTTPAPI进行后台管理工具相关开发的一些经验文章。 前端:elment-admin 后端:node.js koa 前端使用elment-ui el-upload组件实现上传功能 对于elment-admin以及elment-ui不熟悉的请自行去官网学习。 elment-admin是基于elment-ui组件构建的后台管理系统UI,功能强大,方便快速构建后台管理系统。 elment-admin:https://github.com/PanJiaChen/vue-element-admin elment-ui:https://element.eleme.io/#/zh-CN/guide/design [代码]<template> <div class="dashboard-container"> <div> <el-upload class="upload-demo" action="http://localhost:3000/upload/imgs" :before-upload="beforeUploadFile" > <el-button size="small" type="primary">点击上传</el-button> <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div> </el-upload> </div> </div> </template> [代码] 后端基于node koa的后端图片上传功能代码: 学习技术的最好方法就是官方文档,因此要想熟练的使用httpapi构建小程序的后端管理系统,就必须先熟悉官方文档。 小程序官方文档链接:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html 要想使用Httpapi去实现图片上传功能,我们需要先获取访问请求中的参数access_token。access_token获取的官方文档内容: [图片] 通过官方文档可知,传递参数appid和secret,发送请求到文档中的地址,可以获取access_token数据。 access_token获取,存储以及定时更新的相关代码如下: [代码]const rp = require('request-promise') const fs = require('fs') //引用文件操作函数 const path = require('path') //引入文件路径函数 //获取文件的绝对路径 const filePath = path.resolve(__dirname, './access_token.json') //小程序的APPID和Secret const APPID = '小程序的APPID' const Secret = '小程序的Secret' //获取Token的URL const URL = `https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=${APPID}&secret=${Secret}` //从小程序端获取Token函数 const updateAccessToken = async () => { const resStr = await rp(URL) //将字符串类型转为对象 const res = JSON.parse(resStr) if (res.access_token) { //写入文件 fs.writeFileSync(filePath, JSON.stringify({ access_token: res.access_token, //从小程序服务器获取的token createTime: new Date() //获取token时,对应的时间 })) } else { //如果文件不存在,则重新调用获取token函数,重新执行写入 await updateAccessToken() } } //查询Token函数返回给响应的函数去调用云函数 const getAccessToken = async () => { try { //读取文件 const readRes = fs.readFileSync(filePath, 'utf8') const readObj = JSON.parse(readRes) //获取access_token.json中的createtime的时间 const createTime = new Date(readObj.createTime).getTime() //获取当前时间 const nowTime = new Date().getTime() //判断Token的失效是否大于2小时,如果大于2小时则需要重新获取Token,然后在读取Token数据 if ((nowTime - createTime) / 1000 / 60 / 60 >= 2) { await updateAccessToken() await getAccessToken() } //返回Token数据 return readObj.access_token } catch (error) { //如果access_token文件不存在,则读取报错,此时需要重新从服务器获取token数据,再读取token数据 await updateAccessToken() await getAccessToken() } } //定时更新Token setInterval(async () => { await updateAccessToken() }, (7200 - 300) * 1000) module.exports = getAccessToken; [代码] 获取文件上传链接 从官方文档可知,传递access_token和env参数,访问文档中的请求地址,获取上传文件所需的参数数据。 [图片] 从官方文档可知,返回的上传数据中包含如下内容: authorization字段 token字段 cos_file_id字段 url字段 上传文件到云存储。 按照官方文档,访问返回的url字段的链接,并传递相关参数,将图片上传到云存储。 [图片] 图片上传功能的代码如下: [代码]const rp = require('request-promise') const fs = require('fs') //引用文件操作函数 const getAccessToken = require('./getAccessToken') const cloudStorage = { // 1、请求地址 async upload(ctx){ console.log(1,ctx) const ACCESS_TOKEN = await getAccessToken() const file = ctx.request.files.file const path = `test/${Date.now()}-${Math.random()}-${file.name}` var options = { method: 'POST', uri: `https://api.weixin.qq.com/tcb/uploadfile?access_token=${ACCESS_TOKEN}`, body: { env: 'miniprogram-dev-y7a0a', path, }, json: true // Automatically stringifies the body to JSON }; //请求返回的参数 const info = await rp(options) .then(res => { // POST succeeded... return res }) .catch(err => { // POST failed... console.log(err) }); // 2、上传文件到云存储 const params ={ method: 'POST', uri:info.url, header:{ 'content-type':'multipart/form-data' }, formData:{ key:path, Signature:info.authorization, 'x-cos-security-token':info.token, 'x-cos-meta-fileid':info.cos_file_id, file:fs.createReadStream(file.path) }, json: true // Automatically stringifies the body to JSON } await rp(params) return info.file_id } } module.exports=cloudStorage; [代码] 后续会陆续更新相关技术文章,来帮助大家快速熟悉和使用小程序·云开发实现小程序的快速开发,以及基于HTTPAPI实现小程序后端管理系统的开发。
2019-10-11 - 拎包哥回归之作,wifi打印机对接 [拎包入住,即抄即用]
[图片] 距离上一次冒泡已经是两个月前了,上一篇文章还是挂人的水帖,这次拎包哥带来的是市面上已经成熟存在的wifi打印机。 我浏览了一遍社区,但却没啥教程,为啥大家都藏着掖着,难道。。。这里有啥大咪咪? 其实不然,代码真的很简单(看上去有点长),大家耐心走个流程(粘贴)就完事儿了。 ------------------------------------------------------------------------------------ 0.首先,买部飞鹅云的wifi打印机(没广告费),大概300RMB左右(不清楚wifi打印机对比蓝牙打印机优势的可以先百度一下) [图片] 这里吐槽一下智联云wifi打印机 不要被他们的噱头:“多送10卷纸”所蒙蔽了双眼(这就是我踩过的坑哈哈)。服务态度。。。真的一言难尽,每次打服务热线过去都是播完一整首的广场舞歌曲后,机器人告诉我无人接听做结束。下载api发现也不能ctrl c+ ctrl v(菜)直接使用,然后我进QQ群去咨询,半天也没人鸟我。综上所述我才退的货去买的飞鹅云,粘贴api代码,机器立马(一两天)就跑起来了。 1.打开网址:http://admin.feieyun.com/,注册,然后添加打印机 [图片] [图片] 填入这两个信息(在打印机底部)就够了 [图片][图片] 2.在飞鹅开放平台注册开发者账号(放心,不要钱的) 打开个人中心,进行个人实名认证(不需要企业认证) [图片] 认证成功后你会得到自己的开发者信息 [图片] 3.粘贴官方的api到自己的小程序(我直接粘贴过来了,方便讲解) 要改的只有这几个地方: 3.1认证通过后得到的开发者信息 + 打印机底部的SN编号 var USER = "xxxxxxxxxxxxxxxxx"; //必填,飞鹅云 http://admin.feieyun.com/ 管理后台注册的账号名 var UKEY = "xxxxxxxxxxxxxxxxx"; //必填,这个不是填打印机的key,是在飞鹅云后台注册账号后生成的UKEY var SN = 'xxxxxxxxxxxxxxxxx'; //必填,打印机编号,打印机必须要在管理后台先添加 USER和UKEY在这里 [图片] SN在这里(密钥不用管) [图片] 3.2 去掉注释 这里的1代表一次打印1张,如此类推。。。 // print_r(SN,orderInfo,1); 3.3 修改orderInfo里的数据到自己想要的格式 ps. 记得勾选这个 [图片] 官方算法 或者你可以直接跑起来先爽一下,但自己的数据还是要有算法来适应打印纸。 var orderInfo; orderInfo = '小程序测试打印'; orderInfo += '名称 单价 数量 金额'; orderInfo += '--------------------------------'; orderInfo += '饭 10.0 10 10.0'; orderInfo += '炒饭 10.0 10 10.0'; orderInfo += '蛋炒饭 10.0 100 100.0'; orderInfo += '鸡蛋炒饭 100.0 100 100.0'; orderInfo += '西红柿炒饭 1000.0 1 100.0'; orderInfo += '西红柿蛋炒饭 100.0 100 100.0'; orderInfo += '西红柿鸡蛋炒饭 15.0 1 15.0'; orderInfo += '备注:加辣'; orderInfo += '--------------------------------'; 我的算法 orderInfo += '名称 单价 数量 金额';orderInfo += '--------------------------------';for (var i in list) { if (list[i].name.length < 15) { aLength = list[i].name.match(reg).length * 2 a = list[i].name.concat(' '.repeat(15 - aLength)) } if (list[i].price.toString().length < 6) { b = list[i].price.toString().concat(' '.repeat(6 - list[i].price.toString().length)) } if (list[i].num.toString().length < 5) { c = list[i].num.toString().concat(' '.repeat(5 - list[i].num.toString().length)) } if (list[i].sinTtlPrice.toString().length < 5) { d = list[i].sinTtlPrice.toString().concat(' '.repeat(5 - list[i].sinTtlPrice.toString().length)) } orderInfo += a + b + c + d + ''} 完整官方小程序api 只是一个方法,不用node xx包,我等手残党福音! [图片] [图片] //微信小程序https请求实例,根据自己的需求条件触发函数,推送订单打印test(e) { //USER和UKEY在飞鹅云( http://admin.feieyun.com/ )管理后台的个人中心可以查看 var USER = "xxxxxxxxxxxxxxxxx"; //必填,飞鹅云 http://admin.feieyun.com/ 管理后台注册的账号名 var UKEY = "xxxxxxxxxxxxxxxxx"; //必填,这个不是填打印机的key,是在飞鹅云后台注册账号后生成的UKEY var SN = 'xxxxxxxxxxxxxxxxx'; //必填,打印机编号,打印机必须要在管理后台先添加 //以下URL参数不需要修改 var HOST = "api.feieyun.cn"; //域名 var PATH = "/Api/Open/"; //接口路径 var STIME = new Date().getTime();//请求时间,当前时间的秒数 var SIG = hex_sha1(USER + UKEY + STIME);//获取签名 //标签说明: //单标签: //"<BR>"为换行,"<CUT>"为切刀指令(主动切纸,仅限切刀打印机使用才有效果) //"<LOGO>"为打印LOGO指令(前提是预先在机器内置LOGO图片),"<PLUGIN>"为钱箱或者外置音响指令 //成对标签: //"<CB></CB>"为居中放大一倍,"<B></B>"为放大一倍,"<C></C>"为居中,<L></L>字体变高一倍 //<W></W>字体变宽一倍,"<QR></QR>"为二维码,"<BOLD></BOLD>"为字体加粗,"<RIGHT></RIGHT>"为右对齐 //拼凑订单内容时可参考如下格式 //根据打印纸张的宽度,自行调整内容的格式,可参考下面的样例格式 var orderInfo; orderInfo = '<CB>小程序测试打印</CB><BR>'; orderInfo += '名称 单价 数量 金额<BR>'; orderInfo += '--------------------------------<BR>'; orderInfo += '饭 10.0 10 10.0<BR>'; orderInfo += '炒饭 10.0 10 10.0<BR>'; orderInfo += '蛋炒饭 10.0 100 100.0<BR>'; orderInfo += '鸡蛋炒饭 100.0 100 100.0<BR>'; orderInfo += '西红柿炒饭 1000.0 1 100.0<BR>'; orderInfo += '西红柿蛋炒饭 100.0 100 100.0<BR>'; orderInfo += '西红柿鸡蛋炒饭 15.0 1 15.0<BR>'; orderInfo += '备注:加辣<BR>'; orderInfo += '--------------------------------<BR>'; orderInfo += '合计:xx.0元<BR>'; orderInfo += '送货地点:广州市南沙区xx路xx号<BR>'; orderInfo += '联系电话:13888888888888<BR>'; orderInfo += '订餐时间:2014-08-08 08:08:08<BR>'; orderInfo += '<QR>http://www.dzist.com</QR>';//把二维码字符串用标签套上即可自动生成二维码 // ***接口返回值说明*** //正确例子:{"msg":"ok","ret":0,"data":"123456789_20160823165104_1853029628","serverExecutedTime":6} //错误:{"msg":"错误信息.","ret":非零错误码,"data":null,"serverExecutedTime":5} // console.log(orderInfo); //打开注释可测试 // print_r(SN,orderInfo,1); var hexcase = 0; var chrsz = 8; function hex_sha1(s) { return binb2hex(core_sha1(AlignSHA1(s))); } function core_sha1(blockArray) { var x = blockArray; var w = Array(80); var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; var e = -1009589776; for (var i = 0; i < x.length; i += 16) { var olda = a; var oldb = b; var oldc = c; var oldd = d; var olde = e; for (var j = 0; j < 80; j++) { if (j < 16) w[j] = x[i + j]; else w[j] = rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1); var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j))); e = d; d = c; c = rol(b, 30); b = a; a = t; } a = safe_add(a, olda); b = safe_add(b, oldb); c = safe_add(c, oldc); d = safe_add(d, oldd); e = safe_add(e, olde); } return new Array(a, b, c, d, e); } function sha1_ft(t, b, c, d) { if (t < 20) return (b & c) | ((~b) & d); if (t < 40) return b ^ c ^ d; if (t < 60) return (b & c) | (b & d) | (c & d); return b ^ c ^ d; } function sha1_kt(t) { return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : (t < 60) ? -1894007588 : -899497514; } function safe_add(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } function rol(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)); } function AlignSHA1(str) { var nblk = ((str.length + 8) >> 6) + 1, blks = new Array(nblk * 16); for (var i = 0; i < nblk * 16; i++) blks[i] = 0; for (i = 0; i < str.length; i++) blks[i >> 2] |= str.charCodeAt(i) << (24 - (i & 3) * 8); blks[i >> 2] |= 0x80 << (24 - (i & 3) * 8); blks[nblk * 16 - 1] = str.length * 8; return blks; } function binb2hex(binarray) { var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var str = ""; for (var i = 0; i < binarray.length * 4; i++) { str += hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8 + 4)) & 0xF) + hex_tab.charAt((binarray[i >> 2] >> ((3 - i % 4) * 8)) & 0xF); } return str; } // 打印订单方法:Open_printMsg function print_r(SN, orderInfo, TIMES) { wx.request({ url: 'https://' + HOST + PATH, data: { user: USER,//账号 stime: STIME,//当前时间的秒数,请求时间 sig: SIG,//签名 apiname: "Open_printMsg",//不需要修改 sn: SN,//打印机编号 content: orderInfo,//打印内容 times: TIMES,//打印联数,默认为1 }, method: "POST", header: { "content-type": "application/x-www-form-urlencoded" }, success: function (res) { console.log(res.data) } }) }} 好了,大咪咪披露完了。可能还有什么纰漏,没关系,评论里见吧! [图片] -=====================成果图========================= 应大家要求放上成果,图有点歪,当是治治大家的颈椎病吧。 [图片] [图片] ================更新于2020/7/22=========================
2022-03-10 - 小程序应该如何实现在普通打印机上打印信息?
现在小程序,如何将小程序里应该如何链接普通的打印机,将相关的信息打印出来。 看样例,有直接使用蓝牙接口,将数据打印出来。 但普通的打印机小程序是不支持的,能不能生成文件然后打印呢,如果可以应该生成什么格式的文件呢。 或者还有其它别的方法可以实现。
2022-11-03 - 获取今日0点/24点时间戳、今日剩余毫秒
// 获取今日0点时间戳 new Date().setHours(0, 0, 0, 0) // 获取今日24点时间戳 new Date().setHours(24, 0, 0, 0) // 今日剩余毫秒 // 使用场景,UI组件库倒计时组件,今日剩余时间会使用到 new Date().setHours(24, 0, 0, 0) - Date.now() /** * 返回当天或前后多少天的0点时间戳 * @param {number} num - 可传入前后天数 * @returns {number} */ function timestamp(num = 0) { return new Date().setHours(0, 0, 0, 0) - 86400000 * num; } console.log(timestamp()); // 当天0点时间戳 console.log(timestamp(2)); // 2天后的0点时间戳 console.log(timestamp(-3)); // 3天前的0点时间戳
2023-02-08 - 腾讯cos上传文件一直提示403
[图片] 按照https://github.com/tencentyun/wecos-ugc-upload-demo上面的操作来的 鉴权服务器应该是没有问题的,我用web试过可以成功上传文件 // upload.js var REGION = 'ap-shanghai' var APPID = 'xxx' var BUCKET_NAME = 'xx' var cosUrl = "https://" + REGION + ".file.myqcloud.com/files/v2/" + APPID + "/" + BUCKET_NAME //填写自己的鉴权服务器地址 var cosSignatureUrl = 'xxx' /** * 上传方法 * filePath: 上传的文件路径 * fileName: 上传到cos后的文件名 */ function upload(filePath, fileName) { // 鉴权获取签名 wx.request({ url: cosSignatureUrl, success: function (cosRes) { // 签名 var signature = cosRes.data // 头部带上签名,上传文件至COS wx.uploadFile({ url: cosUrl + '/' + fileName, filePath: filePath, header: { 'Authorization': signature }, name: 'filecontent', formData: { op: 'upload' }, success: function (uploadRes) { var data = uploadRes.data console.log('uploadRes', uploadRes) }, fail: function (e) { console.log('e', e) } }) } }) } //index.js sendImageMessage: function () { var that = this wx.chooseImage({ count: 1, // 默认9 sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 success: function (res) { var filePath = res.tempFilePaths[0]; // 获取文件名 var fileName = 'chat.jpg' // 文件上传cos uploadFn(filePath, fileName) }, fail: function (res) { console.log("fail...") }, complete: function (res) { console.log("完成...") } }) }
2018-01-15 - 图片上传到cos?
[图片]调用sdk进行图片上传到cos时,[图片]怎么将这个方法写入到生命周期里啊?
2020-05-06 - 小程序上传图片到腾讯云对象存储COS的简单代码
const fs = require('fs') const COS = require('cos-nodejs-sdk-v5') const cos = new COS({ SecretId: 'SecretId', SecretKey: 'SecretKey', }) module.exports = async (ctx) => { const image = ctx.request.files.image //这里获得小程序wx.uploadFile上传的文件,文件标识名为image if(!image) return let ext = image.type.split('/')[1] let path = image.path let key = `image-${Date.now()}.${ext}`;//保存在cos的文件名 let TaskId; function p() { return new Promise((resolve, reject) => { cos.putObject({ Bucket: 'Bucket-1251490133', /* 必须 */ Region: 'cn-north', Key: key, /* 必须 */ Body: fs.createReadStream(path), ContentLength: fs.statSync(path).size }, function (err, data) { console.log(err || data); if (err) { reject(); } else { resolve("url/" + key); } fs.unlinkSync(path); }); }); } try{ ctx.body = await p() }catch (err){ console.log(err) } } [图片]
2020-10-20 - geoNear经纬度排序报错geoNear(...).get is not a function?
调试基础库2.8.1 const db = wx.cloud.database() const pxgps = db.command db.collection('shops').where({location: pxgps.geoNear({geometry: db.Geo.Point(this.data.longitude, this.data.latitude),minDistance: 0,maxDistance: 5000,}).get({ success: res => { let new_data = res.data let old_data = this.data.products console.log("old_data:" + old_data) this.setData({ products: old_data.concat(new_data), page: page }) }, }) 在官方文档上面发现通过使用geoNear可以对以用户为中心的周边商户经纬度距离进行排序,然而实际上该方法一直报错,数据库中已经将location保存商家经纬度的字段设置了地理索引,但依然不行,在网上查了好几天,发现有问过这个问题的人,但一直都没有得到解决,已经重复检查了很多遍了,代码以及数据库索引应该都是没问题的,请问这到底是个BUG还是有其他要设置的地方?以下为报错信息 VM2208:1 thirdScriptError pxgps.geoNear(...).skip is not a function; [Component] Event Handler Error @ pages/index/index#bound shopslist TypeError: pxgps.geoNear(...).skip is not a function at ye.shopslist (http://127.0.0.1:24671/appservice/pages/index/index.js:196:14) at Object.r.safeCallback (WAService.js:1:1125173) at WAService.js:1:1317978 at r (WAService.js:1:1249680) at WAService.js:1:1249802 at WAService.js:1:420977 at n (http://127.0.0.1:24671/appservice/__dev__/asdebug.js:1:27852) at e.exports.(http://127.0.0.1:24671/appservice/__dev__/asdebug.js:1:28221) at http://127.0.0.1:24671/appservice/__dev__/asdebug.js:1:1968 at Array.forEach (<anonymous>) 关于SKIP,不论我加不加都是一样还是会报错的,因此目前的报错与SKIP无关。希望能得到解决,谢谢
2019-11-24 - 小程序纯前端将数据导出为excel表格
网上有许多文章是讲述小程序将数据导出为excel表格的,但大多需要经过请求服务端,再加上云存储。那一套逻辑之前做后端的时候就玩过了。很多时候,我们浏览页面时数据已经从服务端获取到本地了,直接将之导出即可,再走服务端,实为多此一举。为了减轻服务端压力,于是便有了这篇文章。本文章介绍如何在小程序使用纯前端技术将以获取到的数据导出为excel表格。文末有代码片段 xlsx插件文档 sheetjs插件文档 [代码]const XLSX = require('../utils/excel.js') Page({ data: { }, onLoad() { }, exportData() { // 数据源 const data = [{ code: 1, name: 'A', }, { code: 2, name: 'B', }, { code: 3, name: 'C', }, { code: 4, name: 'D', }] // 构建一个表的数据 let sheet = [] let title = ['序号', '姓名'] sheet.push(title) data.forEach(item => { let rowcontent = [] rowcontent.push(item.code) rowcontent.push(item.name) sheet.push(rowcontent) }) // XLSX插件使用 var ws = XLSX.utils.aoa_to_sheet(sheet); var wb = XLSX.utils.book_new(); XLSX.utils.book_append_sheet(wb, ws, "用户表"); var fileData = XLSX.write(wb, { bookType: "xlsx", type: 'base64' }); let filePath = `${wx.env.USER_DATA_PATH}/用户表.xlsx` // 写文件 const fs = wx.getFileSystemManager() fs.writeFile({ filePath: filePath, data: fileData, encoding: 'base64', bookSST: true, success(res) { console.log(res) const sysInfo = wx.getSystemInfoSync() // 导出 if (sysInfo.platform.toLowerCase().indexOf('windows') >= 0) { // 电脑PC端导出 wx.saveFileToDisk({ filePath: filePath, success(res) { console.log(res) }, fail(res) { console.error(res) util.tips("导出失败") } }) } else { // 手机端导出 // 打开文档 wx.openDocument({ filePath: filePath, showMenu: true, success: function (res) { console.log('打开文档成功') }, fail: console.error }) } }, fail(res) { console.error(res) if (res.errMsg.indexOf('locked')) { wx.showModal({ title: '提示', content: '文档已打开,请先关闭', }) } } }) } }) [代码] 导出效果如下,如需高级设置请参照xlsx插件文档 sheetjs插件文档 [图片] 代码片段 -完-
2023-08-11 - 蚂蚁树林
来蚂蚁树林,和好友一起种树,收取能量把! 蚂蚁树林能量球有4种颜色【青、绿、黄、红】,代表能量球成长的过程。青色和绿色阶段的能量球不可采摘,黄色和红色阶段的能量球可以采摘,就像一个苹果一样,只有成熟了才可以采摘。 能量球每隔24小时会改变到下一种颜色的状态。如果能量球变成红色后会显示24小时的倒计时采摘时间。没有采摘的能量球会自动消失。 [图片][图片] [图片][图片][图片][图片][图片][图片] 我们的服务 APP、小程序定制开发、网站建设、公众号运营、网络营销推广! [图片]
2023-07-24 - 云函数获取开放数据(手机号码、微信步数)
目标:通过简单几行代码,获取手机号码、微信步数。 1. 创建云函数getOpenData,并按如下修改上传部署。 // 云函数 index.js const cloud = require('wx-server-sdk') cloud.init() exports.main = async (event, context) => { return event; } 2. 页面wxml代码 <!-- index.wxml --> <button open-type="getPhoneNumber" bindgetphonenumber="getPhoneNumber">获取手机号码</button> <button bindtap="getWeRunData">获取微信步数</button> 3.页面js代码 // index.js Page({ async getPhoneNumber(e) { const { cloudID } = e.detail; if (cloudID) { let { result } = await this.getOpenData(cloudID); console.log(result); } }, async getWeRunData() { let { cloudID } = await wx.getWeRunData().catch((error) => error); if (cloudID) { let { result } = await this.getOpenData(cloudID); console.log(result); } }, async getOpenData(cloudID) { return wx.cloud.callFunction({ name: "getOpenData", data: { openData: wx.cloud.CloudID(cloudID), }, }); }, }); 4.备注:需要先初始化云函数wx.cloud.init({}),以及勾选将JS编译成ES5。 5. 可以在result获取对应的手机号码或微信步数了。
2021-08-12 - 蛇王传说
《蛇王传说》游戏案例 开局一条蛇,精彩全靠拼! 《蛇王传说》是一款完全免费的休闲竞技游戏,它不仅比拼手速,更考验玩家的策略。在蛇王传说的世界中,每个人都化身为一条小蛇,可以通过不断获取地图上的食物后生长的越来越长,越来越粗。蛇在游走的过程中一定要注意不能碰到墙壁和其它蛇的身体。否则,蛇会死亡,游戏结束。 [图片] 《蛇王传说》已上架微信/抖音平台,扫码体验! [图片] [图片] 同城配送行业解决方案 大力士同城配送小程序是一款同城配送小程序。 客户打开小程序,发货地点自动定位到客户当前位置。客户只用选择要使用的车型后,打开地图,选择要送货的目的地,系统会自动规划起止线路、计算两点距离并显示预估价格(此价格参数由物流服务公司在后台设定)。客户只用点击提交订单完成下单操作。 后台物流服务公司会收到订单信息,客服人员根据客户下单的位置分配订单给最近的司机,客户可以在我的账户中查看订单状态和本次服务的司机信息。 [图片][图片] 直播招聘小程序解决方案 介绍工作拿佣金,Boss直播现真身。 做为直播招聘的新平台,让求职和招聘变得更简单!企业发布招聘视频,展现公司环境与实力,开通会员可以直播招聘、在线面试功能;求职者刷视频可以刷到工作,加入会员,发布自己的才艺视频,优先推荐给企业。我们希望Boss亲自面试,求职者也省去来回奔波。你只需简单的转发,不但为朋友推荐工作,还能拿佣金,可谓一举两得。 [图片][图片] [图片][图片] 我们的客户 专业团队、定制开发、源码交付 [图片] 我们的服务 APP、小程序定制开发、网站建设、公众号运营、网络营销推广! [图片]
07-12 - 万客分销
万客分销商城通过微信分享奖励机制,把粉丝转化为客户,把客户转化为分销商,通过爆炸式裂变用户口碑营销,提高商品销售成功率。 分销奖励策略: 微信授权登录成功后你就会免费升级为【普通会员】,你通过专属小程序二维码把小程序分享到朋友圈或好友,也可以直接转发小程序到朋友圈或好友。只要好友是通过你转发的链接授权登录本平台,他在本平台发生的任何消费行为,你都可以得到销售利润5%的分销提成,如果他升级会员你可以获得5%的拉新奖励。你转发小程序到好友或朋友圈后如果产生收益,佣金直接到账你的账户。 代理等级越高,奖励越丰厚(代理具体奖励策略可在小程序账户设置中查看)。【普通会员】升级为代理后,不但可以获得自己直推的分销提成和拉新奖励,还可以获得推荐下线的二级、三级分销提成和拉新奖励。 如何把小程序推荐给朋友获得奖励? 把小程序推荐给朋友有以下三种方式: 1.打开小程序,点击 我的->我的专属推广码,稍等片刻就可以生成你的专属推广海报。保存图片后把图片转发到微信朋友圈。 2.打开小程序首页,单击右上角三点,在显示的菜单可以转发朋友圈和好友。 3.点击任意商品,在商品详情页有 分享 按钮可实现一键转发。 通过以上三种方式转发朋友圈和好友,也可让朋友打开微信扫你的专属推广码,你就可以锁定客户。以后只要客户消费和升级为代理,你都可以坐享佣金分成。 [图片][图片][图片][图片] [图片][图片] [图片][图片] 我们的服务 APP、小程序定制开发、网站建设、公众号运营、网络营销推广! [图片]
2023-06-24 - 小程序如何自动转账给用户?
公司要做一个类似的推荐好友功能,推荐注册人数到一定数量,立刻返现给该用户,并有入账通知。 翻了一会文档,好像没找到对应的api,求告知 [图片]
2020-09-07 - 云开发短信跳小程序(自定义开发版)教程
写在前面如果你想要自主开发,但没有云开发相关经验,可以采用演示视频来学习本教程: [视频] 一、能力介绍境内非个人主体的认证的小程序,开通静态网站后,可以免鉴权下发支持跳转到相应小程序的短信。短信中会包含支持在微信内或微信外打开的静态网站链接,用户打开页面后可一键跳转至你的小程序。 这个链接的网页在外部浏览器是通过 URL Scheme 的方式来拉起微信打开主体小程序的。 总之,短信跳转能力的实现分为两个步骤,「配置拉起网页」和「发送短信」。本教程将介绍如何执行操作完成短信跳转小程序的能力。 如果你想要无需写代码就能完成短信跳转小程序的能力,可以参照无代码版教程进行逐步实现。 二、操作指引1、网页创建首先我们需要构建一个基础的网页应用,在任何代码编辑器创建一个 html 文件,在教程这里命名为 index.html 在这个 html 文件中输入如下代码,并根据注释提示更换自己的信息: window.onload = function(){ window.web2weapp.init({ appId: 'wx999999', //替换为自己小程序的AppID gh_ID: 'gh_999999',//替换为自己小程序的原始ID env_ID: 'tcb-env',//替换小程序底下云开发环境ID function: { name:'openMini',//提供UrlScheme服务的云函数名称 data:{} //向这个云函数中传入的自定义参数 }, path: 'pages/index/index.html' //打开小程序时的路径 }) } 以上引入的 web2weapp.js 文件是教程封装的有关拉起微信小程序的极简应用,我们直接引用即可轻松使用。 如果你想进一步学习和修改其中的一些WEB展示信息,可以前往 github 获取源码并做修改。 有关于网页拉起小程序的更多信息可以访问官方文档 如果你只想体验短信跳转功能,在执行完上述文件创建操作后,继续以下步骤。 2、创建服务云函数在上面创建网页的过程中,需要填写一个UrlScheme服务云函数。这个云函数主要用来调用微信服务端能力,获取对应的Scheme信息返回给调用前端。 我们在示例中填写的是 openMini 这个命名的云函数。 我们前往微信开发者工具,定位对应的云开发环境,创建一个云函数,名称叫做 openMini 。 在云函数目录中 index.js 文件替换输入以下代码: const cloud = require('wx-server-sdk') cloud.init() exports.main = async (event, context) => { return cloud.openapi.urlscheme.generate({ jumpWxa: { path: '', // 打开小程序时访问路径,为空则会进入主页 query: '',// 可以使用 event 传入的数据制作特定参数,无需求则为空 }, isExpire: true, //是否到期失效,如果为true需要填写到期时间,默认false expire_time: Math.round(new Date().getTime()/1000) + 3600 //我们设置为当前时间3600秒后,也就是1小时后失效 //无需求可以去掉这两个参数(isExpire,expire_time) }) } 保存代码后,在 index.js 右键,选择增量更新文件即可更新成功。 接下来,我们需要开启云函数的未登录访问权限。进入小程序云开发控制台,转到设置-权限设置,找到下方未登录,选择上几步我们统一操作的那个云开发环境(注意:第一步配置的云开发环境和云函数所在的环境,还有此步操作的环境要一致),勾选打开未登录 [图片] 接下来,前往云函数控制台,点击云函数权限,安全规则最后的修改,在弹出框中按如下配置: [图片] 3、本地测试我们在本地浏览器打开第一步创建的 index.html ;唤出控制台,如果效果如下图则证明成功! 需要注意,此处本地打开需要时HTTP协议,建议使用live server等扩展打开。不要直接在资源管理器打开到浏览器,会有跨域的问题! [图片] 4、上传本地创建好的 index.html 至静态网站托管将本地创建好的 index.html 上传至静态网站托管,在这里静态托管需要是小程序本身的云开发环境里的静态托管。 如果你上传至其他静态托管或者是服务器,你仍然可以使用外部浏览器拉起小程序的能力,但会丧失在微信浏览器用开放标签拉起小程序的功能,也不会享受到云开发短信发送跳转链接的能力。 如果你的目标小程序底下有多个云开发环境,则不需要保证云函数和静态托管在一个环境中,无所谓。 比如你有A、B两个环境,A部署了上述的云函数,但是把 index.html 部署到B的环境静态托管中了,这个是没问题的,符合各项能力要求。只需要保证第一步 index.html 网页中的云开发环境配置是云函数所在环境即可。 部署成功后,你便可以访问静态托管的所在地址了,可以通过手机外部浏览器以及微信内部浏览器测试打开小程序的能力了。 5、短信发送云函数的配置在上面创建 openMini 云函数的环境中再来一个云函数,名字叫 sendsms 。 在此云函数 index.js 中配置如下代码: const cloud = require('wx-server-sdk') cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV, }) exports.main = async (event, context) => { try { const config = { env: event.env, content: event.content ? event.content : '发布了短信跳转小程序的新能力', path: event.path, phoneNumberList: event.number } const result = await cloud.openapi.cloudbase.sendSms(config) return result } catch (err) { return err } } 保存代码后,在 index.js 右键,选择增量更新文件即可更新成功。 6、测试短信发送能力在小程序代码中,在 app.js 初始化云开发后,调用云函数,示例代码如下: App({ onLaunch: function () { wx.cloud.init({ env:"tcb-env", //短信云函数所在环境ID traceUser: true }) wx.cloud.callFunction({ name:'sendsms', data:{ "env": "tcb-env",//网页上传的静态托管的环境ID "path":"/index.html",//上传的网页相对根目录的地址,如果是根目录则为/index.html "number":[ "+8616599997777" //你要发送短信的目标手机,前面需要添加「+86」 ] },success(res){ console.log(res) } }) } }) 重新编译运行后,在控制台中看到如下输出,即为测试成功: [图片] 你会在发送的目标手机中收到短信,因为短信中包含「退订回复T」字段,可能会触发手机的自动拦截机制,需要手动在拦截短信中查看。 需要注意:你可以把短信云函数和URLScheme云函数分别放置在不同云开发环境中,但必须保证所放置的云开发环境属于你操作的小程序 另外,出于防止滥用考虑,短信发送的云调用能力需要真实小程序用户访问才可以生效,你不能使用云端测试、云开发JS-SDK以及其他非wx.cloud调用方式(微信侧WEB-SDK除外),会提示如下错误: [图片] 如果你想在其他处使用此能力,可以使用服务端API来做正常HTTP调用,具体访问官方文档 7、查看短信监控图表进入 云开发控制台 > 运营分析 > 监控图表 > 短信监控,即可查看短信监控曲线图、短信发送记录。 [图片] 三、总结短信跳转小程序核心是静态网站中配置的可跳转网页,外部浏览器通过URL Scheme 来实现的,这个方式不适用于微信浏览器,需要使用开放标签才可以URL Scheme的生成是云调用能力,需要是目标小程序的云开发环境的云函数中使用才可以。并且生成的URL Scheme只能是自己小程序的打开链接,不能是任意小程序(和开放标签的任意不一致)短信发送能力的体验是每个有免费配额的环境首月100条,如有超过额度的需求可前往开发者工具-云开发控制台-对应按量付费环境-资源包-短信资源包,进行购买。如当前资源包无法满足需求也可通过云开发 工单 提交申请[图片]短信发送也是云调用能力,需要真实小程序用户调用才可以正常触发,其他方式均报错返回参数错误,出于防止滥用考虑云函数和网页的放置可以不在同一个环境中,只需要保证所属小程序一致即可。(需要保证对应环境ID都能接通)如果你不需要短信能力,可以忽略最后两个步骤CMS配置渠道投放、数据统计可参考官方文档
2021-04-07