- 解决正则的插件 非常好用
小程序正则插件 粘贴下面如下 /** * 表单验证 * * @param {Object} rules 验证字段的规则 * @param {Object} messages 验证字段的提示信息 * */ class wxValidate { constructor(rules = {}, messages = {}) { Object.assign(this, { rules, messages, }) this.__init() } /** * __init */ __init() { this.__initMethods() this.__initDefaults() this.__initData() } /** * 初始化数据 */ __initData() { this.form = {} this.errorList = [] } /** * 初始化默认提示信息 */ __initDefaults() { this.defaults = { messages: { required: '这是必填字段。', email: '请输入有效的电子邮件地址。', tel: '请输入11位的手机号码。', url: '请输入有效的网址。', date: '请输入有效的日期。', dateISO: '请输入有效的日期(ISO),例如:2009-06-23,1998/01/22。', number: '请输入有效的数字。', digits: '只能输入数字。', idcard: '请输入18位的有效身份证。', equalTo: this.formatTpl('输入值必须和 {0} 相同。'), contains: this.formatTpl('输入值必须包含 {0}。'), minlength: this.formatTpl('最少要输入 {0} 个字符。'), maxlength: this.formatTpl('最多可以输入 {0} 个字符。'), rangelength: this.formatTpl('请输入长度在 {0} 到 {1} 之间的字符。'), min: this.formatTpl('请输入不小于 {0} 的数值。'), max: this.formatTpl('请输入不大于 {0} 的数值。'), range: this.formatTpl('请输入范围在 {0} 到 {1} 之间的数值。'), } } } /** * 初始化默认验证方法 */ __initMethods() { const that = this that.methods = { /** * 验证必填元素 */ required(value, param) { if (!that.depend(param)) { return 'dependency-mismatch' } else if (typeof value === 'number') { value = value.toString() } else if (typeof value === 'boolean') { return !0 } return value.length > 0 }, /** * 验证电子邮箱格式 */ email(value) { return that.optional(value) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(value) }, /** * 验证手机格式 */ tel(value) { return that.optional(value) || /^1[34578]\d{9}$/.test(value) }, /** * 验证URL格式 */ url(value) { return that.optional(value) || /^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(value) }, /** * 验证日期格式 */ date(value) { return that.optional(value) || !/Invalid|NaN/.test(new Date(value).toString()) }, /** * 验证ISO类型的日期格式 */ dateISO(value) { return that.optional(value) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test(value) }, /** * 验证十进制数字 */ number(value) { return that.optional(value) || /^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(value) }, /** * 验证整数 */ digits(value) { return that.optional(value) || /^\d+$/.test(value) }, /** * 验证身份证号码 */ idcard(value) { return that.optional(value) || /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$/.test(value) }, /** * 验证两个输入框的内容是否相同 */ equalTo(value, param) { return that.optional(value) || value === that.scope.detail.value[param] }, /** * 验证是否包含某个值 */ contains(value, param) { return that.optional(value) || value.indexOf(param) >= 0 }, /** * 验证最小长度 */ minlength(value, param) { return that.optional(value) || value.length >= param }, /** * 验证最大长度 */ maxlength(value, param) { return that.optional(value) || value.length <= param }, /** * 验证一个长度范围[min, max] */ rangelength(value, param) { return that.optional(value) || (value.length >= param[0] && value.length <= param[1]) }, /** * 验证最小值 */ min(value, param) { return that.optional(value) || value >= param }, /** * 验证最大值 */ max(value, param) { return that.optional(value) || value <= param }, /** * 验证一个值范围[min, max] */ range(value, param) { return that.optional(value) || (value >= param[0] && value <= param[1]) }, } } /** * 添加自定义验证方法 * @param {String} name 方法名 * @param {Function} method 函数体,接收两个参数(value, param),value表示元素的值,param表示参数 * @param {String} message 提示信息 */ addMethod(name, method, message) { this.methods[name] = method this.defaults.messages[name] = message !== undefined ? message : this.defaults.messages[name] } /** * 判断验证方法是否存在 */ isValidMethod(value) { let methods = [] for (let method in this.methods) { if (method && typeof this.methods[method] === 'function') { methods.push(method) } } return methods.indexOf(value) !== -1 } /** * 格式化提示信息模板 */ formatTpl(source, params) { const that = this if (arguments.length === 1) { return function () { let args = Array.from(arguments) args.unshift(source) return that.formatTpl.apply(this, args) } } if (params === undefined) { return source } if (arguments.length > 2 && params.constructor !== Array) { params = Array.from(arguments).slice(1) } if (params.constructor !== Array) { params = [params] } params.forEach(function (n, i) { source = source.replace(new RegExp("\\{" + i + "\\}", "g"), function () { return n }) }) return source } /** * 判断规则依赖是否存在 */ depend(param) { switch (typeof param) { case 'boolean': param = param break case 'string': param = !!param.length break case 'function': param = param() default: param = !0 } return param } /** * 判断输入值是否为空 */ optional(value) { return !this.methods.required(value) && 'dependency-mismatch' } /** * 获取自定义字段的提示信息 * @param {String} param 字段名 * @param {Object} rule 规则 */ customMessage(param, rule) { const params = this.messages[param] const isObject = typeof params === 'object' if (params && isObject) return params[rule.method] } /** * 获取某个指定字段的提示信息 * @param {String} param 字段名 * @param {Object} rule 规则 */ defaultMessage(param, rule) { let message = this.customMessage(param, rule) || this.defaults.messages[rule.method] let type = typeof message if (type === 'undefined') { message = `Warning: No message defined for ${rule.method}.` } else if (type === 'function') { message = message.call(this, rule.parameters) } return message } /** * 缓存错误信息 * @param {String} param 字段名 * @param {Object} rule 规则 * @param {String} value 元素的值 */ formatTplAndAdd(param, rule, value) { let msg = this.defaultMessage(param, rule) this.errorList.push({ param: param, msg: msg, value: value, }) } /** * 验证某个指定字段的规则 * @param {String} param 字段名 * @param {Object} rules 规则 * @param {Object} event 表单数据对象 */ checkParam(param, rules, event) { // 缓存表单数据对象 this.scope = event // 缓存字段对应的值 const data = event.detail.value const value = data[param] || '' // 遍历某个指定字段的所有规则,依次验证规则,否则缓存错误信息 for (let method in rules) { // 判断验证方法是否存在 if (this.isValidMethod(method)) { // 缓存规则的属性及值 const rule = { method: method, parameters: rules[method] } // 调用验证方法 const result = this.methods[method](value, rule.parameters) // 若result返回值为dependency-mismatch,则说明该字段的值为空或非必填字段 if (result === 'dependency-mismatch') { continue } this.setValue(param, method, result, value) // 判断是否通过验证,否则缓存错误信息,跳出循环 if (!result) { this.formatTplAndAdd(param, rule, value) break } } } } /** * 设置字段的默认验证值 * @param {String} param 字段名 */ setView(param) { this.form[param] = { $name: param, $valid: true, $invalid: false, $error: {}, $success: {}, $viewValue: ``, } } /** * 设置字段的验证值 * @param {String} param 字段名 * @param {String} method 字段的方法 * @param {Boolean} result 是否通过验证 * @param {String} value 字段的值 */ setValue(param, method, result, value) { const params = this.form[param] params.$valid = result params.$invalid = !result params.$error[method] = !result params.$success[method] = result params.$viewValue = value } /** * 验证所有字段的规则,返回验证是否通过 * @param {Object} event 表单数据对象 */ checkForm(event) { this.__initData() for (let param in this.rules) { this.setView(param) this.checkParam(param, this.rules[param], event) } return this.valid() } /** * 返回验证是否通过 */ valid() { return this.size() === 0 } /** * 返回错误信息的个数 */ size() { return this.errorList.length } /** * 返回所有错误信息 */ validationErrors() { return this.errorList } } export default wxValidate 引入到app.js import wxValidate from 'utils/wxValidate.js'; App({ wxValidate: (rules, messages) => new wxValidate(rules, messages), }) var app=getApp() js文件如下 onload({ // 正则 this.wxValidate = app.wxValidate( { name: { required: true, name: true }, post:{ required: true, post: true, }, phone:{ required: true, tel: true, }, site:{ required: true, site: true, }, mailbox:{ required: true, email:true }, companyid:{ required:true, companyid:true } } , { name: { required: "请输入名字" }, post: { required: "请输入职位" }, phone:{ required: "请输入正确电话" }, site: { required: "请输入地址" }, mailbox:{ required: "请输入邮箱" }, companyid:{ required:"请输入公司名字" } } ) }) formSubmit:function(e){ if (!this.wxValidate.checkForm(e)) { const error = this.wxValidate.errorList[0] var error_text = `${error.msg}`; that.setData({ error_text: error_text }) wx.showToast({ title: error_text, icon:"none" }) return false } wxml <form bindsubmit='formSubmit'> <view class='list'> <view class='name'> <view> <image src='../../images/tx.png'></image> </view> <view> 姓名: </view> <input placeholder='请输入姓名' name="name" value='{{user[0].name}}'></input> </view> <view class='name'> <view> <image src='../../images/company.png'></image> </view> <view> 公司: </view> <input placeholder='请输入公司名字' name="companyid" value='{{user[0].gs}}'></input> </view> <view class='name'> <view> <image src='../../images/position.png'></image> </view> <view> 职位: </view> <input placeholder='请输入职位' name="post" value='{{user[0].zhiwei}}'></input> </view> <view class='name'> <view> <image src='../../images/phone.png'></image> </view> <view> 电话: </view> <input placeholder='请输入电话' type='number' name="phone" value='{{user[0].tel}}'></input> </view> <view class='name'> <view> <image src='../../images/yx.png'></image> </view> <view> 邮箱: </view> <input placeholder='请输入邮箱' class='mailbox' name="mailbox" value='{{user[0].email}}'></input> </view> <view class='name'> <view> <image src='../../images/address.png'></image> </view> <view> 地址: </view> <input placeholder='请输入地址' class='site' name="site" value='{{user[0].address}}'></input> </view> </view> <button form-type='submit' class='sbmit'>保存</button> </form> </view> 这样就可以了 有不明白的可以来骚扰啊 不用谢 [图片]
2018-09-15 - 微信小程序评论/留言功能,附:前端+后端代码+视频讲解!
前端界面:[图片] [图片] [代码]<!-- 表单 -->[代码][代码]<[代码][代码]form[代码] [代码]bindsubmit[代码][代码]=[代码][代码]"formSubmit"[代码][代码]>[代码][代码]<[代码][代码]input[代码] [代码]type[代码][代码]=[代码][代码]"text"[代码] [代码]name[代码][代码]=[代码][代码]"liuyantext"[代码] [代码]placeholder[代码][代码]=[代码][代码]'输入留言内容'[代码] [代码]class[代码][代码]=[代码][代码]"input-style"[代码][代码]/>[代码][代码]<[代码][代码]button[代码] [代码]formType[代码][代码]=[代码][代码]"submit"[代码] [代码]class[代码][代码]=[代码][代码]"btn"[代码] [代码]wx:if[代码][代码]=[代码][代码]"{{nickName == empty}}"[代码] [代码]open-type[代码][代码]=[代码][代码]"getUserInfo"[代码] [代码]bindgetuserinfo[代码][代码]=[代码][代码]"bindGetUserInfo"[代码] [代码]bindtap[代码][代码]=[代码][代码]'login'[代码][代码]>授权登录</[代码][代码]button[代码][代码]>[代码][代码]<[代码][代码]button[代码] [代码]formType[代码][代码]=[代码][代码]"submit"[代码] [代码]class[代码][代码]=[代码][代码]"btn"[代码] [代码]wx:else>留言</[代码][代码]button[代码][代码]>[代码][代码]<[代码][代码]input[代码] [代码]type[代码][代码]=[代码][代码]"text"[代码] [代码]name[代码][代码]=[代码][代码]"nickname"[代码] [代码]value[代码][代码]=[代码][代码]'{{nickName}}'[代码] [代码]style[代码][代码]=[代码][代码]"display:none;"[代码][代码]/>[代码][代码]<[代码][代码]input[代码] [代码]type[代码][代码]=[代码][代码]"text"[代码] [代码]name[代码][代码]=[代码][代码]"headimg"[代码] [代码]value[代码][代码]=[代码][代码]'{{avatarUrl}}'[代码] [代码]style[代码][代码]=[代码][代码]"display:none;"[代码][代码]/>[代码][代码]</[代码][代码]form[代码][代码]>[代码] [代码]<[代码][代码]view[代码] [代码]wx:for[代码][代码]=[代码][代码]"{{re}}"[代码] [代码]wx:key[代码][代码]=[代码][代码]"re"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]view[代码] [代码]class[代码][代码]=[代码][代码]"result"[代码][代码]>{{item.result}}</[代码][代码]view[代码][代码]>[代码][代码]</[代码][代码]view[代码][代码]>[代码][代码]<[代码][代码]view[代码] [代码]style[代码][代码]=[代码][代码]"text-align:center;font-size:14px;color:#ccc;margin-top:20px;"[代码][代码]>以下是留言内容</[代码][代码]view[代码][代码]>[代码][代码]<[代码][代码]view[代码] [代码]wx:for[代码][代码]=[代码][代码]"{{liuyanlist}}"[代码] [代码]wx:key[代码][代码]=[代码][代码]"liuyanlist"[代码] [代码]class[代码][代码]=[代码][代码]"liuyanview"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]view[代码] [代码]class[代码][代码]=[代码][代码]"headimg"[代码][代码]><[代码][代码]image[代码] [代码]src[代码][代码]=[代码][代码]"{{item.headimg}}"[代码][代码]></[代码][代码]image[代码][代码]></[代码][代码]view[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]view[代码] [代码]class[代码][代码]=[代码][代码]"nickname_liuyantext"[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]view[代码] [代码]class[代码][代码]=[代码][代码]"nickname"[代码][代码]>{{item.nickname}} <[代码][代码]view[代码] [代码]class[代码][代码]=[代码][代码]"time"[代码][代码]>{{item.lytime}}</[代码][代码]view[代码][代码]></[代码][代码]view[代码][代码]>[代码][代码] [代码][代码]<[代码][代码]view[代码] [代码]class[代码][代码]=[代码][代码]"text"[代码][代码]>{{item.liuyantext}}</[代码][代码]view[代码][代码]>[代码][代码] [代码][代码]</[代码][代码]view[代码][代码]>[代码][代码] [代码][代码]<!-- 占位符 -->[代码][代码] [代码][代码]<[代码][代码]view[代码] [代码]style[代码][代码]=[代码][代码]"width:100%;height:10px;"[代码][代码]></[代码][代码]view[代码][代码]>[代码][代码]</[代码][代码]view[代码][代码]>[代码] [代码]//index.js[代码][代码]//获取应用实例[代码][代码]const app = getApp()[代码][代码]Page({[代码][代码] [代码][代码]/**[代码][代码] [代码][代码]* 页面的初始数据[代码][代码] [代码][代码]*/[代码][代码] [代码][代码]data: {[代码][代码] [代码] [代码] [代码][代码]},[代码] [代码] [代码][代码]//授权登录[代码][代码] [代码][代码]login: [代码][代码]function[代码] [代码]() {[代码][代码] [代码][代码]var[代码] [代码]that = [代码][代码]this[代码][代码];[代码][代码] [代码][代码]// 查看是否授权[代码][代码] [代码][代码]wx.getSetting({[代码][代码] [代码][代码]success(res) {[代码][代码] [代码][代码]if[代码] [代码](res.authSetting[[代码][代码]'scope.userInfo'[代码][代码]]) {[代码][代码] [代码][代码]// 已经授权,可以直接调用 getUserInfo 获取头像昵称[代码][代码] [代码][代码]wx.getUserInfo({[代码][代码] [代码][代码]success: [代码][代码]function[代码] [代码](res) {[代码][代码] [代码][代码]console.log(res.userInfo),[代码][代码] [代码][代码]that.setData({[代码][代码] [代码][代码]nickName: res.userInfo.nickName,[代码][代码] [代码][代码]avatarUrl: res.userInfo.avatarUrl,[代码][代码] [代码][代码]})[代码][代码] [代码][代码]}[代码][代码] [代码][代码]})[代码][代码] [代码][代码]}[代码][代码] [代码][代码]}[代码][代码] [代码][代码]})[代码][代码] [代码][代码]},[代码][代码] [代码][代码]bindGetUserInfo(e) {[代码][代码] [代码][代码]console.log(e.detail.userInfo)[代码][代码] [代码][代码]},[代码] [代码] [代码][代码]formSubmit: [代码][代码]function[代码] [代码](e) {[代码][代码] [代码][代码]wx.showToast({[代码][代码] [代码][代码]title: [代码][代码]'已留言'[代码][代码],[代码][代码] [代码][代码]icon: [代码][代码]'success'[代码][代码] [代码][代码]})[代码][代码] [代码][代码]var[代码] [代码]that = [代码][代码]this[代码][代码];[代码][代码] [代码][代码]var[代码] [代码]liuyantext = e.detail.value.liuyantext; [代码][代码]//获取表单所有name=liuyantext的值 [代码][代码] [代码][代码]var[代码] [代码]nickName = e.detail.value.nickname; [代码][代码]//获取表单所有name=nickName的值 [代码][代码] [代码][代码]var[代码] [代码]headimg = e.detail.value.headimg; [代码][代码]//获取表单所有name=headimg的值 [代码][代码] [代码][代码]wx.request({[代码][代码] [代码][代码]url: [代码][代码]'http://localhost/liuyanserver/liuyan.php?liuyantext='[代码] [代码]+ liuyantext + [代码][代码]'&nickname='[代码] [代码]+ nickName + [代码][代码]'&headimg='[代码] [代码]+ headimg,[代码][代码] [代码][代码]data: {[代码][代码] [代码][代码]liuyantext,[代码][代码] [代码][代码]nickName,[代码][代码] [代码][代码]headimg[代码][代码] [代码][代码]},[代码][代码] [代码][代码]header: { [代码][代码]'Content-Type'[代码][代码]: [代码][代码]'application/json'[代码] [代码]},[代码][代码] [代码][代码]success: [代码][代码]function[代码] [代码](res) {[代码][代码] [代码][代码]console.log(res.data)[代码][代码] [代码][代码]that.setData({[代码][代码] [代码][代码]re: res.data,[代码][代码] [代码][代码]})[代码][代码] [代码][代码]wx.hideToast();[代码][代码] [代码][代码]}[代码][代码] [代码][代码]})[代码][代码] [代码][代码]},[代码] [代码] [代码][代码]onPullDownRefresh: [代码][代码]function[代码] [代码]() {[代码][代码] [代码][代码]wx.showNavigationBarLoading();[代码][代码] [代码][代码]var[代码] [代码]that = [代码][代码]this[代码][代码] [代码][代码]wx.request({[代码][代码] [代码][代码]url: [代码][代码]'http://localhost/liuyanserver/loadliuyan.php'[代码][代码],[代码][代码] [代码][代码]headers: {[代码][代码] [代码][代码]'Content-Type'[代码][代码]: [代码][代码]'application/json'[代码][代码] [代码][代码]},[代码][代码] [代码][代码]success: [代码][代码]function[代码] [代码](res) {[代码][代码] [代码][代码]//将获取到的json数据,存在名字叫list的这个数组中[代码][代码] [代码][代码]that.setData({[代码][代码] [代码][代码]liuyanlist: res.data,[代码][代码] [代码][代码]//res代表success函数的事件对,data是固定的,liuyanlist是数组[代码][代码] [代码][代码]})[代码][代码] [代码][代码]// 隐藏导航栏加载框[代码][代码] [代码][代码]wx.hideNavigationBarLoading();[代码][代码] [代码][代码]// 停止下拉动作[代码][代码] [代码][代码]wx.stopPullDownRefresh();[代码][代码] [代码][代码]}[代码][代码] [代码][代码]})[代码][代码] [代码][代码]},[代码] [代码] [代码][代码]//加载最新数据[代码][代码] [代码][代码]onLoad: [代码][代码]function[代码] [代码]() {[代码][代码] [代码][代码]var[代码] [代码]that = [代码][代码]this[代码][代码] [代码][代码]wx.request({[代码][代码] [代码][代码]url: [代码][代码]'http://localhost/liuyanserver/loadliuyan.php'[代码][代码],[代码][代码] [代码][代码]headers: {[代码][代码] [代码][代码]'Content-Type'[代码][代码]: [代码][代码]'application/json'[代码][代码] [代码][代码]},[代码][代码] [代码][代码]success: [代码][代码]function[代码] [代码](res) {[代码][代码] [代码][代码]//将获取到的json数据,存在名字叫list的这个数组中[代码][代码] [代码][代码]that.setData({[代码][代码] [代码][代码]liuyanlist: res.data,[代码][代码] [代码][代码]//res代表success函数的事件对,data是固定的,liuyanlist是数组[代码][代码] [代码][代码]})[代码][代码] [代码][代码]}[代码][代码] [代码][代码]})[代码][代码] [代码][代码]}[代码][代码]})[代码] [代码]/**index.wxss**/[代码][代码].input-style{[代码][代码] [代码][代码]width[代码][代码]: [代码][代码]90%[代码][代码];[代码][代码] [代码][代码]height[代码][代码]: [代码][代码]50px[代码][代码];[代码][代码] [代码][代码]border[代码][代码]:[代码][代码]1px[代码] [代码]solid[代码] [代码]#ccc[代码][代码];[代码][代码] [代码][代码]margin[代码][代码]:[代码][代码]10px[代码] [代码]auto[代码][代码];[代码][代码]}[代码] [代码].btn{[代码][代码] [代码][代码]width[代码][代码]: [代码][代码]88%[代码][代码];[代码][代码] [代码][代码]margin[代码][代码]:[代码][代码]5px[代码] [代码]auto[代码][代码];[代码][代码]}[代码] [代码].liuyanview{[代码][代码] [代码][代码]width[代码][代码]: [代码][代码]90%[代码][代码];[代码][代码] [代码][代码]margin[代码][代码]: [代码][代码]10px[代码] [代码]auto[代码][代码];[代码][代码]}[代码] [代码].result{[代码][代码] [代码][代码]text-align[代码][代码]: [代码][代码]center[代码][代码];[代码][代码] [代码][代码]font-size[代码][代码]: [代码][代码]14px[代码][代码];[代码][代码] [代码][代码]color[代码][代码]: [代码][代码]#f00[代码][代码];[代码][代码] [代码][代码]margin-top[代码][代码]: [代码][代码]20px[代码][代码];[代码][代码]}[代码] [代码].headimg{[代码][代码] [代码][代码]width[代码][代码]: [代码][代码]45px[代码][代码];[代码][代码] [代码][代码]height[代码][代码]: [代码][代码]45px[代码][代码];[代码][代码] [代码][代码]border-radius: [代码][代码]100%[代码][代码];[代码][代码]}[代码] [代码].headimg image{[代码][代码] [代码][代码]width[代码][代码]: [代码][代码]45px[代码][代码];[代码][代码] [代码][代码]height[代码][代码]: [代码][代码]45px[代码][代码];[代码][代码] [代码][代码]border-radius: [代码][代码]100%[代码][代码];[代码][代码]}[代码] [代码].nickname_liuyantext{[代码][代码] [代码][代码]width[代码][代码]: calc([代码][代码]100%[代码] [代码]- [代码][代码]55px[代码][代码]);[代码][代码] [代码][代码]float[代码][代码]: [代码][代码]right[代码][代码];[代码][代码] [代码][代码]margin-top[代码][代码]:[代码][代码]-45px[代码][代码];[代码][代码]}[代码] [代码].nickname_liuyantext .nickname{[代码][代码] [代码][代码]font-size[代码][代码]: [代码][代码]15px[代码][代码];[代码][代码] [代码][代码]color[代码][代码]: [代码][代码]#999[代码][代码];[代码][代码]}[代码] [代码].nickname_liuyantext .nickname .time{[代码][代码] [代码][代码]font-size[代码][代码]: [代码][代码]11px[代码][代码];[代码][代码] [代码][代码]color[代码][代码]: [代码][代码]#999[代码][代码];[代码][代码] [代码][代码]float[代码][代码]: [代码][代码]right[代码][代码];[代码][代码]}[代码] [代码].nickname_liuyantext .text{[代码][代码] [代码][代码]font-size[代码][代码]: [代码][代码]16px[代码][代码];[代码][代码] [代码][代码]color[代码][代码]: [代码][代码]#666[代码][代码];[代码][代码]}[代码] 以上是前端部分 后端有两个文件。 点击下载后端,后端需要修改自己的数据库配置! 视频:https://www.lanzous.com/i1w1deb 后端:https://www.lanzous.com/i1w19pi
2018-09-16 - 借助小程序云开发获取小程序用户openid
openid作为小程序用户的唯一标示,就相当于用户在微信里的身份证一样,我们做小程序开发时,获取用户的openid是很重要的。我们之前获取用户的openid,如下图官方文档说明,是通过该wx.login先获取临时凭证,然后再用临时凭证去换取用户的openid,这样做无可厚非,但是小程序出了云开发之后,再用这种方法获取用户openid就显得有些麻烦了,因为通过云开发获取用户openid特别方便,并且可靠。 [图片] image.png 下面就来带领大家借助云开发愉快的获取用户openid。 使用云开发之前需要简单了解下云开发,下面链接是官方学习文档。https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html 一,开启云开发[图片] 开启云开发 开启云开发只需要在开发者工具里点击上面红色框里的云开发按钮即可,创建成功后如下图 [图片] image.png 二,创建云函数1,创建云函数所需文件夹 [图片] 创建云函数所需文件夹 2,右键点击functions,点击同步云函数列表 [图片] image.png 3,右键点击functions,点击新建node.js云函数 [图片] 创建云函数 4,创建名为getOpenid的云函数 [图片] 云函数创建成功 5,编写获取openid的代码 [图片] 云函数代码 [代码]// 云函数入口文件const cloud = require('wx-server-sdk') cloud.init()//获取用户的openidexports.main = async(event, context) => { return event.userInfo; //返回用户信息}[代码]6,右键点击getOpenid,上传并部署云函数。 [图片] image.png 三,使用getOpenid云函数获取用户openid1,在app.js里初始化云开发 [代码]//app.jsApp({ onLaunch: function() { //云开发初始化 wx.cloud.init({ env: 'prod-8aa9a5', traceUser: true }) } })[代码]2,在首页使用云函数获取openid [代码]//home.jsPage({ data: { openid: '', }, onLoad: function () { this.getOpenid(); }, // 获取用户openid getOpenid() { let that = this; wx.cloud.callFunction({ name: 'getOpenid', complete: res => { console.log('云函数获取到的openid: ', res.result.openId) var openid = res.result.openId; that.setData({ openid: openid }) } }) } })[代码]获取结果如下 [图片] 获取到openid 到此我们就轻松的借助云开发云函数获取到了用户的openid了 有小程序相关的问题,可以加我微信2501902696(备注小程序)
2018-10-11 - 云市场短信接口之云函数调用
云市场短信接口介绍本云函数使用的接口是我们上架到云市场里面的接口:https://market.cloud.tencent.com/products/7303 各个小程序引用本插件后可以快速的实现短信发送功能,直接在腾讯云市场购买短信服务后即可调用插件接口发送短信。 本接口最大的优点是,接口调用对接方便,在腾讯云市场购买短信后直接报备短信模板即可使用。而且价格优惠不限制购买金额,可以根据自己网站的需要用多少购买多少。 欢迎各类小程序应用接入,接口简单,对接方便,审核快速,价格优惠,服务周到。联系QQ:320266360(微信同号)平台已经入驻腾讯云市场,量大优惠价格全网最低,欢迎推荐,推荐返点! 云函数使用流程1.登录微信web开发者工具新建云开发快速启动模板,如果你的上面没有这个选项,请更新微信web开发者工具。 [图片] 2.先点云开发按钮,按照流程开通云开发环境,否则无法使用云函数功能。 [图片] 3.右键点击cloudfunctions,选择新建云函数输入qcloudsms,确定安装依赖(需要本地先安装配置好nodejs和npm)。 [图片] [图片] 4.到腾讯云市场 https://market.cloud.tencent.com/products/7303 购买短信服务,如果短信套餐使用完了腾讯云会提醒,然后再次购买即可。 [图片] 5.登录腾讯云到已购产品与服务 https://console.cloud.tencent.com/servicemarket/services 点管理查看SecretId和SecretKey。 [图片] [图片] 6.复制下面云函数代码到刚创建的云函数qcloudsms里面的index.js文件中,注意修改secretid和secretkey为你自己在腾讯云市场购买服务的SecretId和SecretKey。(这个云函数代码的作用是调用云市场短信接口)。 [代码]// 云函数入口文件[代码][代码]const cloud = require([代码][代码]'wx-server-sdk'[代码][代码])[代码] [代码]cloud.init()[代码] [代码]// 云函数入口函数[代码][代码]exports.main = async (event, context) => {[代码][代码] [代码][代码]console.log(event)[代码][代码] [代码][代码]console.log(context)[代码] [代码] [代码][代码]return[代码] [代码]new[代码] [代码]Promise((resolve, reject) => {[代码][代码] [代码][代码]secretid = [代码][代码]'你的secretid'[代码][代码] [代码][代码]secretkey = [代码][代码]'你的secretkey'[代码][代码] [代码][代码]mobile = event.mobile[代码][代码] [代码][代码]content = event.content[代码] [代码] [代码][代码]var[代码] [代码]url = [代码][代码]'https://api.chanyoo.net/qcloudsms?appid='[代码] [代码]+ event.userInfo.appId + [代码][代码]'&secretid='[代码] [代码]+ secretid + [代码][代码]'&secretkey='[代码] [代码]+ secretkey + [代码][代码]'&mobile='[代码] [代码]+ mobile + [代码][代码]'&content='[代码] [代码]+ encodeURIComponent(content)[代码][代码] [代码][代码]//console.log(url)[代码] [代码] [代码][代码]var[代码] [代码]https = require([代码][代码]'https'[代码][代码]);[代码][代码] [代码][代码]https.get(url, [代码][代码]function[代码] [代码](res) {[代码][代码] [代码][代码]var[代码] [代码]size = 0;[代码][代码] [代码][代码]var[代码] [代码]chunks = [];[代码][代码] [代码][代码]res.on([代码][代码]'data'[代码][代码], [代码][代码]function[代码] [代码](chunk) {[代码][代码] [代码][代码]size += chunk.length;[代码][代码] [代码][代码]chunks.push(chunk);[代码][代码] [代码][代码]});[代码][代码] [代码][代码]res.on([代码][代码]'end'[代码][代码], [代码][代码]function[代码] [代码]() {[代码][代码] [代码][代码]var[代码] [代码]data = Buffer.concat(chunks, size).toString();[代码][代码] [代码][代码]console.log(data)[代码][代码] [代码][代码]resolve(JSON.parse(data))[代码][代码] [代码][代码]});[代码][代码] [代码][代码]}).on([代码][代码]'error'[代码][代码], (e) => {[代码][代码] [代码][代码]console.log(`url:${url} error: ${e.message}`);[代码][代码] [代码][代码]});[代码][代码] [代码][代码]})[代码][代码]}[代码] [图片] 7.找到快速新建云函数页面代码addFunction.js文件,注释默认的云函数sum的调用代码,复制粘贴下面云函数qcloudsms的调用代码并保存。 [代码]wx.cloud.callFunction({[代码][代码] [代码][代码]name: [代码][代码]'qcloudsms'[代码][代码],[代码][代码] [代码][代码]data: {[代码][代码] [代码][代码]mobile: [代码][代码]'13333333333'[代码][代码],[代码][代码] [代码][代码]content: [代码][代码]'您的手机号:13333333333,验证码:110426,请及时完成验证,如不是本人操作请忽略。【腾讯云市场】'[代码][代码] [代码][代码]},[代码][代码] [代码][代码]success: res => {[代码][代码] [代码][代码]wx.showToast({[代码][代码] [代码][代码]title: [代码][代码]'调用成功'[代码][代码],[代码][代码] [代码][代码]})[代码][代码] [代码][代码]this[代码][代码].setData({[代码][代码] [代码][代码]result: JSON.stringify(res.result)[代码][代码] [代码][代码]})[代码][代码] [代码][代码]},[代码][代码] [代码][代码]fail: err => {[代码][代码] [代码][代码]wx.showToast({[代码][代码] [代码][代码]icon: [代码][代码]'none'[代码][代码],[代码][代码] [代码][代码]title: [代码][代码]'调用失败'[代码][代码],[代码][代码] [代码][代码]})[代码][代码] [代码][代码]console.error([代码][代码]'[云函数] [qcloudsms] 调用失败:'[代码][代码], err)[代码][代码] [代码][代码]}[代码][代码] [代码][代码]})[代码] [图片] 8.右键点击刚刚创建的云函数qcloudsms选择上传并部署等待提示上传成功。 [图片] [图片] 9.到快速新建云函数页面点击按钮测试云函数,提示调用成功并输出调用结果表示云函数qcloudsms调用成功。 [图片] 10.如需发送正式短信内容请到模板报备地址:https://api.chanyoo.net/qcloud/template.html 报备您的模板。 代码片段:wechatide://minicode/2bD9Qcmm7I3h 调试代码片段请先登录自己的微信web开发者工具开通云开发,然后导入这个代码片段链接,存放选择一个空目录,输入刚才开通云开发的AppID。如果不这样操作就无法调试成功,因为微信小程序调用云函数需要使用到你自己创建的云开发环境,如果没有开通云开发是无法调用云函数的。 云开发教程:https://developers.weixin.qq.com/miniprogram/dev/wxcloud/basis/getting-started.html [图片] 微信小程序添加并引用本短信插件可以快速实现短信发送功能,大大提高小程序的开发效率,如有任何问题可以联系QQ:320266360(微信同号)协助您解决相关问题! [图片]
2019-01-06 - 个人微信号绑定的开发/体验者权限数量不够了,该怎么办?
近期有童鞋反映,个人微信号在绑定新的小程序账号的管理员/开发者/体验者时,因个人微信号绑定的小程序账号满额导致无法绑定成功,该怎么办?如果员工离职,原员工微信号与小程序账号没有解绑,那么会浪费小程序账号与员工微信号双方绑定账号数量的名额,对于双方来讲不是一件好事。 方法一:原小程序账号的管理员,登录微信公众平台 - 小程序后台 - 用户身份 找到该开发/体验者微信号的头像昵称可以删除其开发或体验权限,此时,小程序账号又多预留了以为可绑定名额,微信号也一样。 那么问题来了,个人微信号怎么知道自己绑定了多少个小程序账号?如果每个小程序账号的解绑,该微信号的使用者都要一一麻烦管理员去操作,是不是太繁琐? 方法二:搜索微信公众号:公众平台安全助手 ,关注公众号,必须要关注公众号。进入公众号对话的主界面,左下角找到 <绑定查询> 可以根据手机号、身份证号以及微信号的方式查询,这里要用根据 微信号绑定账号 的方式查询。点击进入后,会看到:公众号、小程序、开放平台。因为我们的目的是微信开发者/体验者自主发起解绑小程序账号,所以选择的是小程序,可以看到你目前作为管理员和作为项目成员分别下面有那些小程序账号,在这个页面可以看到每个小程序的头像、名称、原始ID以及是否授权第三方(作为管理员可查看)。 这里要注意,作为管理员下面绑定的小程序账号如果显示已经授权第三方,可以查看第三方的基本信息,其他情况下点击无效。作为项目成员下面绑定的小程序账号均可点击,点击后会提示“解除绑定”,当你点击解除绑定的时候,该小程序账号信息会从该列表消失,此时你的微信号多了一个可绑定小程序账号名额,而你此时无法访问已解绑小程序账号的开发版和体验版,在小程序“小程序开发助手”中也看不到原先解绑的小程序信息。 如果作为管理员下面的小程序不属于你负责的账号,那么这种情况需要管理员登录微信公众平台 - 小程序后台 - 用户身份 修改管理员,即将修改为管理员的微信号必须有可绑定小程序管理员名额且绑定了银行卡经过微信实名认证,具体不做展开,有疑问评论区留言。 关于个人微信号和小程序账号绑定的名额相关估计很多人有疑问,接下来总结梳理一下。 成员管理人数限制,每个小程序帐号可添加一定数量的项目成员,不区分成员身份,具体限制如下: 个人类型小程序账号:15个 未认证、未发布组织类型:30个 已认证未发布/未认证已发布组织类型:60个 已认证已发布组织类型:90个 补充说明 管理员及其他项目成员均可变更。 管理员及其他项目成员绑定帐号数不占用公众号绑定数量限制。 每个微信号可以成为50个小程序的项目成员。 一个微信号最多可以成为5个小程序账号的管理员。 成员权限说明 开发者权限:可使用小程序开发者工具及开发版小程序进行开发 体验者权限:可使用体验版小程序 登录:可登录小程序管理后台,无需管理员确认 数据分析:使用小程序数据分析功能查看小程序数据 开发管理:小程序提交审核、发布、回退 开发设置:设置小程序服务器域名、消息推送及扫描普通链接二维码打开小程序 暂停服务设置:暂停小程序线上服务 疑问:为什么经过 公众平台安全助手 公众号的查询,微信号已经绑定了那么多小程序账号,我尽全然无知? 在微信小程序刚推出的时候,每一次绑定关联开发者/体验者的时候,都需要管理员扫码登录、扫码授权、发送关联邀请、微信用户确认关联等一系列操作才能完成,其实是一个繁琐的过程。 后来在小程序账号绑定微信号做了简化,当管理员在小程序后台输入某个微信用户的ID,并确认点击添加的时候,无需微信用户确认即可完成绑定操作。 上面说了好处,目前这种操作有个不好的地方就是,当管理员如果没经过微信用户同意,也可以随意添加项目成员,这样,微信用户会在神不知鬼不觉的情况下,成为了某个小程序的项目成员。随着小程序账号的增多,参与小程序项目增加,微信号中默默绑定数量增加了,确实不太好。 这里建议官方,当管理员主动发起绑定项目成员和解除项目成员当时候,给微信用户推送一条消息提醒(之前有,现在不知道为何没有了)。
2018-10-18