UNIAPP实战项目笔记57 发送手机验证码 接入短信SDK
UNIAPP实战项目笔记57 发送手机验证码 接入短信SDK
注册时候需要发送验证
通过验阿里云或腾讯云等短信sdk供应商
实际案例图片

后端接口文件 index.js
var express = require('express');
var router = express.Router();
var connection = require('../db/sql.js');
var user = require('../db/UserSql.js');//设置跨域访问(设置在所有的请求前面即可)
router.all("*", function (req, res, next) {//设置允许跨域的域名,*代表允许任意域名跨域res.header("Access-Control-Allow-Origin", "*");//允许的header类型res.header("Access-Control-Allow-Headers", "content-type");//跨域允许的请求方式 res.header("Access-Control-Allow-Methods", "DELETE,PUT,POST,GET,OPTIONS");if (req.method == 'OPTIONS')res.sendStatus(200); //让options尝试请求快速结束elsenext();
});/* GET home page. */
router.get('/', function(req, res, next) {res.render('index', { title: 'Express' });
});/* 发送验证码 */
router.post('/api/code', function(req, res, next) {// 前端给后端的数据let params = {userName : req.body.userName}// 短信SDK 可以使用阿里云或腾讯云的,具体接入方式以官方NodeJS代码案例// ....// 阿里云 官方代码 https://help.aliyun.com/document_detail/112185.html// 腾讯云 官方代码 https://cloud.tencent.com/developer/article/1987501// ....// ....var paramss = [ Math.floor( Math.random()*(9999-1000)+1000 ) ] // 要发送的验证码// 模拟成功返回验证码res.send({data:{success:true,code : paramss[0]}})
})/* 注册验证手机号是否存在 */
router.post('/api/registered', function(req, res, next) {// 前端给后端的数据let params = {userName : req.body.phone}// 查询手机号是否存在connection.query(user.queryUserName(params),function(error,results,fields){if(results.length > 0){res.send({data:{success:false,msg:"手机号已经存在!"}});}else{res.send({data:{success:true}});}})});/* 用户登录 */
router.post('/api/login', function(req, res, next) {// 前端给后端的数据let params = {userName : req.body.userName,userPwd : req.body.userPwd}// 查询用户名或手机号是否存在connection.query(user.queryUserName(params),function(error,results,fields){if(results.length > 0){connection.query(user.queryUserPwd(params),function(erro,result){if(result.length > 0){res.send({data:{success:true,msg:"登录成功!",data:result[0]}});}else{res.send({data:{success:false,msg:"密码不正确!"}});}})}else{res.send({data:{success:false,msg:"用户名或手机号不存在!"}});}})});/* GET databases goods Detail. */
router.get('/api/goods/id', function(req, res, next) {let id = req.query.id;connection.query("select * from goods_search where id='"+id+"'",function(error,result,fields){if(error) throw error;res.send({code:"0",data:result})})
});/* GET List Page */
router.get('/api/goods/list', function(req, res, next) {res.send({code:0,name:"家居家纺",data:[{id:1,name:"家纺",data:[{name:"家纺",list:[{id:1,name:"毛巾/浴巾",imgUrl:"/static/logo.png"},{id:2,name:"枕头",imgUrl:"/static/logo.png"}]},{name:"生活用品",list:[{id:1,name:"浴室用品",imgUrl:"/static/logo.png"},{id:2,name:"洗晒",imgUrl:"/static/logo.png"}]}]},{id:2,name:"女装",data:[{name:"裙装",list:[{id:1,name:"连衣裙",imgUrl:"/static/logo.png"},{id:2,name:"半身裙",imgUrl:"/static/logo.png"}]},{name:"上衣",list:[{id:1,name:"T恤",imgUrl:"/static/logo.png"},{id:2,name:"衬衫",imgUrl:"/static/logo.png"}]}]}]});
});/* GET databases goods. */
router.get('/api/goods/search', function(req, res, next) {/* desc 降序 asc 升序 */// 获取对象的keylet [goodsName,orderName] = Object.keys(req.query);// name参数的值let name = req.query.name;// orderName的key值let order = req.query[orderName];let sql = "select * from goods_search";if(!(name == undefined || orderName == undefined || order == undefined)){sql = "select * from goods_search where name like '%"+name+"%' order by "+orderName+" "+order;}connection.query(sql,function(error,results,fields){res.send({code:"0",data:results});})
});/* 首页第一次触底的数据 */
router.get('/api/index_list/1/data/2', function(req, res, next) {res.send({code:"0",data:[ {type:"commodityList",data:[{id:1,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:2,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:3,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:4,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},]},]});
});/* 运动户外第二次触底的数据 */
router.get('/api/index_list/2/data/3', function(req, res, next) {res.send({code:"0",data:[ {type:"commodityList",data:[{id:1,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:2,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:3,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:4,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},]},]});
});/* 运动户外第一次触底的数据 */
router.get('/api/index_list/2/data/2', function(req, res, next) {res.send({code:"0",data:[ {type:"commodityList",data:[{id:1,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:2,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:3,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:4,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},]},]});
});/* 运动户外第一次加载的数据 */
router.get('/api/index_list/2/data/1', function(req, res, next) {res.send({code:"0",data:[ {type:"bannerList",imgUrl:"../../static/img/b3.jpg",},{type:"iconsList",data:[{imgUrl:"../../static/logo.png",name:"运动户外"},{imgUrl:"../../static/logo.png",name:"运动户外"},{imgUrl:"../../static/logo.png",name:"运动户外"},{imgUrl:"../../static/logo.png",name:"运动户外"},{imgUrl:"../../static/logo.png",name:"运动户外"},{imgUrl:"../../static/logo.png",name:"运动户外"},{imgUrl:"../../static/logo.png",name:"运动户外"},{imgUrl:"../../static/logo.png",name:"运动户外"}]},{type:"hotList",data:[{id:1,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:2,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:3,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"}]},{type:"shopList",data:[{bigUrl:"../../static/img/b3.jpg",data:[{id:1,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:2,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:3,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:4,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"}]}],},{type:"commodityList",data:[{id:1,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:2,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:3,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:4,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},]},]});
});/* 服饰内衣第一次加载的数据 */
router.get('/api/index_list/3/data/1', function(req, res, next) {res.send({code:"0",data:[ {type:"bannerList",imgUrl:"../../static/img/b3.jpg",},{type:"iconsList",data:[{imgUrl:"../../static/logo.png",name:"服饰内衣"},{imgUrl:"../../static/logo.png",name:"服饰内衣"},{imgUrl:"../../static/logo.png",name:"服饰内衣"},{imgUrl:"../../static/logo.png",name:"服饰内衣"},{imgUrl:"../../static/logo.png",name:"服饰内衣"},{imgUrl:"../../static/logo.png",name:"服饰内衣"},{imgUrl:"../../static/logo.png",name:"服饰内衣"},{imgUrl:"../../static/logo.png",name:"服饰内衣"}]},{type:"hotList",data:[{id:1,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:2,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:3,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"}]},{type:"shopList",data:[{bigUrl:"../../static/img/b3.jpg",data:[{id:1,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:2,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:3,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:4,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"}]}],},{type:"commodityList",data:[{id:1,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:2,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:3,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:4,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},]},]});
});/* 首页推荐数据 */
router.get('/api/index_list/data', function(req, res, next) {res.send({"code":0,"data":{topBar:[{id:1,name:'推荐'},{id:2,name:'运动户外'},{id:3,name:'服饰内衣'},{id:4,name:'鞋靴箱包'},{id:5,name:'美妆个护'},{id:6,name:'家居数码'},{id:7,name:'食品母婴'}],data:[{type:"swiperList",data:[{imgUrl:'/static/img/b3.jpg'},{imgUrl:'/static/img/b3.jpg'},{imgUrl:'/static/img/b3.jpg'}]},{type:"recommendList",data:[{bigUrl:"../../static/img/b3.jpg",data:[{imgUrl:'../../static/logo.png'},{imgUrl:'../../static/logo.png'},{imgUrl:'../../static/logo.png'}]},{bigUrl:"../../static/img/b3.jpg",data:[{imgUrl:'../../static/logo.png'},{imgUrl:'../../static/logo.png'},{imgUrl:'../../static/logo.png'}]}]},{type:"commodityList",data:[{id:1,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:2,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:3,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},{id:4,imgUrl:"../../static/logo.png",name:"迪奥绒毛大衣,今年必抢,错过瞬时不爽了,爆款疯狂销售",pprice:"299",oprice:"659",discount:"5.2"},]},]}})
});module.exports = router;
验证码接口文档
五 发送验证码接口文档
1.1 接口功能
发送验证码
1.2 URL
地址 /api/code
1.3 支持格式
JSON
1.4 HTTP请求方式
POST
1.5 请求参数
| 参数 | 必选 | 类型 | 说明 |
|---|---|---|---|
| userName | 是 | string | 手机号 |
1.6 返回字段
| 返回字段 | 字段类型 | 说明 |
|---|---|---|
| code | string | 返回结果状态 0:正常 1:错误 |
| data | object | 商品分类数据 |
1.7 接口示例
{"code":'0',"data":[{success:true,code:6585}
}
获取验证码页面 login-code.vue
<template><view><Lines></Lines><view class="login-tel"><view class="tel-main"><view class="login-from"><view class="login-user"><text class="user-text">验证码</text><input type="text" focus="true" v-model="userCode" placeholder="请输入验证码"><button plain="true" size="mini" :disabled="disabled" @tap="sendCode">{{codeMsg}}</button></view></view><view class="tel" @click="getNextIndex">下一步</view></view></view></view>
</template><script>import $http from '@/common/api/request.js'import Lines from '@/components/common/Lines.vue'export default {data() {return {//用户输入的验证码userCode:"",// 倒计时时间codeNum:60,// 显示的文本codeMsg:"",// 按钮是否禁用disabled:false,// 手机号phone:'',};},components:{Lines},onReady() {this.codeMsg = '重新发送('+this.codeNum+')';this.sendCode();},onLoad(e) {this.phone = e.phone;},methods:{sendCode(){// 请求接口返回验证码$http.request({url:'/code',method:"POST",data:{userName: this.phone}}).then((res)=>{console.log(res.code);}).catch(()=>{uni.showToast({title:'请求失败',icon:'none'})})this.disabled = true;let timer = setInterval(()=>{--this.codeNum;this.codeMsg = '重新发送('+this.codeNum+')';},1000);setTimeout(()=>{clearInterval(timer);this.codeNum = 60;this.disabled = false;this.codeMsg = '重新发送';},60000)},// 点击下一步getNextIndex(){uni.switchTab({url:'/pages/index/index'})}},}
</script><style lang="scss">
.login-tel{width: 100vw;height: 100vh;
}
.tel-main{padding: 0 20rpx;
}
.login-from{padding: 30rpx 0;
}
.tel{width: 100%;height: 80rpx;line-height: 80rpx;text-align: center;color: #fff;background-color: #40bde8;border-radius: 40rpx;
}
.login-user{font-size: 40rpx;padding: 10rpx 0 ;display: flex;align-items: center;border-bottom: 2rpx solid #f7f7f7;
}
.user-text{padding-right: 10rpx;
}
</style>
手机登录页面 login.vue
<template><view class="login"><swiper vertical="true" style="height: 100vh;"><swiper-item><scroll-view><view class="login-tel"><view class="tel-main"><view class="close" @tap="goBack"><image class="close-img" src="../../static/img/close-bold.png" mode=""></image></view><view class="logo"><image class="logo-img" src="../../static/logo.png" mode=""></image></view><view class="tel" @tap="goLoginTel">手机号注册</view><LoginOther></LoginOther><view class="login-go"><view class="">已有账号,去登录</view><image src="../../static/img/arrow-down.png" mode=""></image></view></view></view></scroll-view></swiper-item><swiper-item><scroll-view><view class="login-tel"><view class="tel-main"><view class="close close-center"><view class="" @tap="goBack"><image class="close-img" src="../../static/img/close-bold.png" mode=""></image></view><view class="login-go"><image class="close-img" src="../../static/img/up.png" mode=""></image><view class="">没账号,去注册</view></view><view class=""></view></view><view class="login-form"><view class="login-user"><text class='user-text'>账号</text><input type="text" v-model="userName" value="" placeholder="请输入手机号/昵称"/></view><view class="login-user"><text class='user-text'>密码</text><input type="safe-password" v-model="userPwd" value="" placeholder="6-16位字符"/></view></view><view class="login-quick"><view class="">忘记密码</view><view class="">免密登录</view></view><view class="tel" @tap="submit">登录</view><view class="reminder">温馨提示,您可以选择免密登录,更加方便</view><LoginOther></LoginOther></view></view></scroll-view></swiper-item></swiper></view>
</template><script>import $http from '@/common/api/request.js'import LoginOther from '@/components/login/login-other.vue'import {mapMutations} from 'vuex'export default {data() {return {userName:"",userPwd:"",rules:{userName:{rule:/\S/,msg:"账号不能为空 "},userPwd:{rule:/^[0-9a-zA-Z]{6,16}$/,msg:"密码应该为6-16位字符"}}};},components:{LoginOther},methods:{...mapMutations(['login']),goBack(){uni.navigateBack();},submit(){if( !this.validate('userName') ) return ;if( !this.validate('userPwd') ) return ;uni.showLoading({title:"登录中..."});// setTimeout(()=>{// uni.hideLoading();// uni.navigateBack();// },2000)$http.request({url:'/login',method:"POST",data:{userName: this.userName,userPwd : this.userPwd}}).then((res)=>{// 保存用户信息this.login(res.data);console.log(res.data);uni.showToast({title:res.msg,icon:"none"})// console.log(res);uni.hideLoading();if(res.success){uni.navigateBack();}}).catch(()=>{uni.showToast({title:'请求失败',icon:'none'})})},// 判断验证是否符合要求validate(key){let bool = true;if( !this.rules[key].rule.test(this[key]) ){uni.showToast({title:this.rules[key].msg,icon:'none'});bool = false;return false;}return bool;},// 进入手机号注册页面goLoginTel(){uni.navigateTo({url:"/pages/login-tel/login-tel"})}}}
</script><style lang="scss">
.login-tel{width: 100vw;height: 100vh;
}
.tel-main{padding: 0 20rpx;
}
.close{padding: 120rpx 0;
}
.close-img{width: 60rpx;height: 60rpx;
}
.logo{padding: 0 100rpx;padding-bottom: 100rpx;display: flex;justify-content: center;}
.logo-img{width: 200rpx;height: 200rpx;
}
.tel{width: 100%;height: 80rpx;line-height: 80rpx;text-align: center;color: #fff;background-color: #40bde8;border-radius: 40rpx;
}.login-go{display: flex;flex-direction: column;justify-content: center;align-items: center;
}
.login-go image{width: 60rpx;height: 60rpx;
}// 第二屏
.close-center{display: flex;
}
.close-center >view{flex: 1;
}
.login-form{padding-top: 100rpx;
}
.login-user{font-size: 40rpx;padding: 10rpx 0 ;display: flex;align-items: center;border-bottom: 2rpx solid #f7f7f7;
}
.user-text{padding-right: 10rpx;
}
.login-quick{display: flex;padding: 20rpx 0;justify-content: space-between;
}
.reminder{color: #ccc;font-size: 32rpx;padding: 20rpx 0;text-align: center;
}
</style>
目录结构
前端目录结构
-
manifest.json 配置文件: appid、logo…
-
pages.json 配置文件: 导航、 tabbar、 路由
-
main.js vue初始化入口文件
-
App.vue 全局配置:样式、全局监视
-
static 静态资源:图片、字体图标
-
page 页面
- index
- index.vue
- list
- list.vue
- my
- my.vue
- my-config
- my-config.vue
- my-config
- my-config.vue
- my-add-path
- my-add-path.vue
- my-path-list
- my-path-list.vue
- search
- search.vue
- search-list
- search-list.vue
- shopcart
- shopcart.vue
- details
- details.vue
- my-order
- my-order.vue
- confirm-order
- confirm-order.vue
- payment
- payment.vue
- payment-success
- payment-success.vue
- login
- login.vue
- login-tel
login-tel.vue
- login-code
login-code.vue
- index
-
components 组件
- index
- Banner.vue
- Hot.vue
- Icons.vue
- indexSwiper.vue
- Recommend.vue
- Shop.vue
Tabbar.vue
- common
- Card.vue
- Commondity.vue
- CommondityList.vue
- Line.vue
- ShopList.vue
- order
- order-list.vue
- uni
- uni-number-box
- uni-number-box.vue
- uni-icons
- uni-icons.vue
- uni-nav-bar
- uni-nav-bar.vue
- mpvue-citypicker
- mpvueCityPicker.vue
- uni-number-box
- index
-
common 公共文件:全局css文件 || 全局js文件
- api
- request.js
- common.css
- uni.css
- api
-
store vuex状态机文件
- modules
- cart.js
- path.js
- user.js
- index.js
- modules
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
