当前位置:网站首页>Wechat applet authorization login + mobile phone sending verification code +jwt verification interface (laravel8+php)
Wechat applet authorization login + mobile phone sending verification code +jwt verification interface (laravel8+php)
2022-06-25 06:17:00 【SunNang】
Reference blog The applet authorizes login and laravel7(laravel8) token application - Wang Yue 666 - Blog Garden
Wechat applet sku Commodity specification selector - Simple books
Wechat applet and laravel8 Paging after search load _guanj0623 The blog of -CSDN Blog
https://www.jb51.net/article/207552.htm
.wxml( Authorization login page )
<!-- Foreground page , Decide whether to display login or information through judgment -->
<view wx:if="{
{isHide}}">
<view wx:if="{
{canIUse}}" >
<view class='header'>
<image src='/images/x.jpg'></image>
</view>
<view class='content'>
<view> Request permission to </view>
<text> Get your public information ( nickname , Head etc. )</text>
</view>
<button type="primary" open-type="getUserInfo" bind:tap="login"> Authorized login </button>
</view>
<view wx:else> Please upgrade wechat version </view>
</view>
<view wx:else>
<view> My homepage content </view>
</view>
.wxss( Authorization login page )
.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( Authorized login )
// index.js
// Get application instance
const app = getApp()
Page({
data: {
canIUse: wx.canIUse('button.open-type.getUserInfo'),
// This is what the front desk judges
isHide: true
},
// Wechat Authorization
login(evt){
var that=this;
// wx.getUserProfile Get user information
wx.getUserProfile({
// desc Declare the purpose of obtaining the user's personal information , No more than 30 Characters
desc: 'desc',
success:res=>{
if (res.userInfo) {
/* wx.login Call interface to get login credentials (code). Exchange user login status information through credentials , Include the user's unique identity in the current applet (openid)、 The unique identity of wechat open platform account (unionid, If the current applet has been bound to wechat open platform account ) And the session key of this login (session_key)*/
wx.login({
success:ret=>{
// obtain code
var code=ret.code;
// Get user nickname
var nickName=res.userInfo.nickName;
// Get user photos
var log=res.userInfo.avatarUrl;
// Sent to the php Back end
wx.request({
url: 'http://www.yk.com/api/v1/wxlogin', // Just for the sample , Not a real interface address
data: {
code:code,
nickName:nickName,
log:log
},
method:"POST",
header: {
'content-type': 'application/json' // The default value is
},
// The data returned json Format
success (res) {
// Get the returned token, And will token Save to local buffer
wx.setStorageSync('token', res.data.data.token)
// // Will the user id Stored locally
wx.setStorageSync('userid', res.data.data.id);
wx.reLaunch({
url: '/pages/mine/mine',
})
}
})
}
})
}else{
console.log(' The user refused ');
}
}
})
}
})
controller
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\User;
use App\Service\JwtServer;
use App\Service\Token;
use Illuminate\Http\Request;
class LoginController extends Controller
{
public function loginInfo(Request $request)
{
// Receive the value from the foreground
$params = $request->post();
$code=$request->post('code');
// obtain appid
$appID = "wx1378003a2bdb6c0c";
// Obtained from wechat public platform secret
$appSecret = "37e8b20e2f4bb7e85707c92cc1f4f0e4";
// Send a request in exchange for openid and sessionkey
$url="https://api.weixin.qq.com/sns/jscode2session?appid=".$appID."&secret=".$appSecret."&js_code=".$code."&grant_type=authorization_code";
// Temporary use file_get_contents() Send a request , You can use CURL Extended form implementation , obtain opid and session_key
$res = json_decode(file_get_contents($url), true);
// Define a new array after the call succeeds , Most important session_key and openid Two values
$params['openid'] = $res['openid'];
// to $params Additional session_key
$params['session_key'] = $res['session_key'];
// Check whether there is in the database openid, Modify if you have , Add... If not
$res = User::where('openid', $params['openid'])->first();
// Using the found user information id Generate token
$token=JwtServer::createToken($res['id']);
// take token Send to applet , Applet to buffer token And the user id
$res['token']=$token;
// If yes, modify the user's quota openID
if ($res) {
User::where('openid', $params['openid'])->update($params);
return ['code' => 201, 'meg' => ' Modification successful ', 'data' => $res];
} else {
// Add new users without
$add =User::create($params);
return ['code' => 200, 'meg' => ' Add success ', 'data' => $res];
}
}
}
App\Service newly build Curl.php file
<?php
namespace App\Service;
class Curl
{
public static function getCurl($url)
{
$headerArray =array("Content-type:application/json;","Accept:application/json");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch,CURLOPT_HTTPHEADER,$headerArray);
$output = curl_exec($ch);
curl_close($ch);
$output = json_decode($output,true);
return $output;
}
}
composer download jwt
composer require firebase/php-jwtservice Next build a JwtServer.php, Add the following code

App\Http\Middleware Under the new JwtToken.php file ,toekn middleware
<?php
namespace App\Http\Middleware;
use App\Service\JwtServer;
use Closure;
use Illuminate\Http\Request;
class JwtToken
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$token = $request->header('token');
if(empty($token)){
return response()->json(['code'=>40001,'msg'=>' Please log in first ','data'=>$token]);
}
$userId=JwtServer::decodeToken($token);
if(!is_numeric($userId)){
return response()->json(['code'=>40002,'msg'=>'token Be overdue ','data'=>$userId]);
}
$request['id'] = $userId;
return $next($request);
}
}
middleware kernel.php Under the document
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
// middleware
'jwt'=>JwtToken::class
];Definition api route , Be careful api Route writing format , Default api Prefix
Route::group(['prefix'=>'v1','namespace'=>'Api'],function (){
// Applet login
Route::any('wxlogin','[email protected]');
});
Route::group(['middleware'=>'jwt','prefix'=>'v2','namespace'=>'Api'],function (){
// Get mobile phone verification code
Route::get('phone','[email protected]');
// Bind the phone
Route::get('bound','[email protected]');
// Query product list
Route::get('goods','[email protected]');
// Get product details
Route::get('detail','[email protected]');
// Get the product specification attribute value
Route::get('specs','[email protected]');
// Add order
Route::post('orders','[email protected]');
// Get order details
Route::get('order','[email protected]');
// Payment interface
Route::post('pay','[email protected]');
});
Mobile phone sends verification code
.wxss( Mobile phone sends verification code )
<!--pages/logins/logins.wxml-->
<view class="container">
<view class="title"> Bind cell phone number </view>
<form catchsubmit="login">
<view class="inputView">
<input class="inputText" placeholder=" Please enter your mobile number " name="phone" bindinput="phone" />
</view>
<view class="inputView">
<input class="inputText" placeholder=" Please enter the verification code " name="code" />
<button class="line" size="mini" bindtap="sendcode">{
{codebtn}}</button>
</view>
<view class="loginBtnView">
<button class="loginBtn" type="primary" formType="submit"> binding </button>
</view>
</form>
</view>
.wxss
.container {
display: flex;
flex-direction: column;
padding: 0;
}
.inputView {
line-height: 45px;
border-bottom:1px solid #999999;
}
.title{
width: 80%;
font-weight: bold;
font-size: 30px;
}
.inputText {
display: inline-block;
line-height: 45px;
padding-left: 10px;
margin-top: 11px;
color: #cccccc;
font-size: 14px;
}
.line {
border: 1px solid #ccc;
border-radius: 20px;
float: right;
margin-top: 9px;
color: #cccccc;
}
.loginBtn {
margin-top: 40px;
border-radius:10px;
}
.js
// pages/logins/logins.js
Page({
/**
* Initial data of the page
*/
data: {
phone:'',
code: '',
codebtn:' Send verification code ',
disabled:false,
},
/**
* Life cycle function -- Monitor page loading
*/
onLoad: function (options) {
},
// Get input account
phone: function (e) {
let phone = e.detail.value;
this.setData({
phone: e.detail.value
})
},
// Send verification code
sendcode:function(){
let that=this;
let phone =this.data.phone;
let token=wx.getStorageSync('token');
// console.log(token)
wx.request({
url: 'http://www.yk.com/api/v2/phone', // Just for the sample , Not a real interface address
data: {phone},
header: {token},
method:"GET",
success (res) {
console.log(res.data)
that.setData({
code:res.data
})
}
})
},
// Binding processing
login: function (evt) {
// console.log(evt);
var that = this;
// console.log(this.data.code)
var userid=wx.getStorageSync('userid')
var token=wx.getStorageSync('token');
wx.request({
url: 'http://www.yk.com/api/v2/bound', // Just for the sample , Not a real interface address
method: 'get',
data: {
phone: that.data.phone,
code:that.data.code,
userid:userid
},
header: {
token
},
success(res) {
if (res.data.code == "10000") {
wx.reLaunch({
url: '/pages/home/home',
})
} else {
wx.showToast({
title: res.data.msg,
icon: 'none',
duration: 2000
})
}
}
})
}
})
controller
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Cache;
class PhoneController extends Controller
{
/**
* Get the verification code method
* Request $request Parameters
* $getphone cell-phone number $code Verification Code
*/
public function PhoneCode(Request $request){
// Receive mobile phone number
$getPhone=$request->get('phone');
// Generate a random four bit random number
$code=mt_rand(1111,9999);
if(empty($getPhone) || empty($code)){
return ['code'=>0,'data'=>'','msg'=>' The parameter cannot be null '];
}
Cache::set($getPhone,$code,5000);
//
// $statusStr = array(
// "0" => " Message sent successfully ",
// "-1" => " Incomplete parameters ",
// "-2" => " Server space does not support , Please confirm support curl perhaps fsocket, Contact your space provider to solve or replace the space !",
// "30" => " Wrong password ",
// "40" => " Account does not exist ",
// "41" => " Lack of balance ",
// "42" => " The account has expired ",
// "43" => "IP Address restrictions ",
// "50" => " The content contains sensitive words "
// );
// $smsapi = "http://api.smsbao.com/";
// $user = "tannanping"; // SMS platform account
// $pass = md5(""); // SMS platform password
// $content=" Content of short message ".$code;// The text message to send
// $phone = $getPhone;// Mobile phone number to send SMS
// $sendurl = $smsapi."sms?u=".$user."&p=".$pass."&m=".$phone."&c=".urlencode($content);
// $result =file_get_contents($sendurl) ;
// echo $statusStr[$result];
return $code;
}
/**
* Login method
* Parameters Request $request
*/
public function bound(Request $request){
$phone=$request->get('phone');
$code=$request->get('code');
// Take out the verification code in the cache
$oldCode=Cache::get($phone);
if($code!=$oldCode){
return ['code'=>10001,'data'=>'','msg'=>' The verification code is incorrect '];
}else{
$model=new User();
$res=$model->where('phone',$phone)->first();
if(empty($res)){
return ['code'=>10002,'data'=>'','msg'=>' Account does not exist '];
}else{
return ['code'=>10000,'data'=>$res,'msg'=>' Binding success '];
}
}
}
}
app.js( First verify whether you are logged in Judge token Whether there is )
//app.js
App({
onLaunch: function () {
// Demonstrate local storage capabilities
var logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
var token=wx.getStorageSync('token');
if(token!=""){
wx.reLaunch({
url: '/pages/mine/mine',
})
}else{
wx.reLaunch({
url: '/pages/index/index',
})
}
// Sign in
wx.login({
success: res => {
// send out res.code Go backstage to exchange openId, sessionKey, unionId
}
})
// Get user information
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// Has authorized , Can be called directly getUserInfo Get head nickname , Can't pop the frame
wx.getUserInfo({
success: res => {
// Can be res Send it to the background and decode it out unionId
this.globalData.userInfo = res.userInfo
// because getUserInfo It's a network request , May be in Page.onLoad And then come back
// So add here callback To prevent this
if (this.userInfoReadyCallback) {
this.userInfoReadyCallback(res)
}
}
})
}
}
})
},
globalData: {
userInfo: null
}
})Control the product shopping process
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\Goods;
use App\Models\Goodspecs;
use App\Models\Orders;
use App\Models\User;
use Illuminate\Http\Request;
class IndexController extends Controller
{
// Display item list data
public function index(Request $request){
// $keyword = $request->input('keyword');
$data = Goods::paginate(5);
return ['status'=>200,'msg'=>'success','data'=>$data];
}
public function detail(Request $request){
$id=$request->get('id');
$model=new Goods();
$res=$model->where('gid',$id)->first();
return ['status'=>200,'msg'=>'success','data'=>$res];
}
public function specs(Request $request){
$id=$request->get('id');
$model=new Goods();
$res=$model->where('gid',$id)->with(['specs','goodspecs'])->get();
return ['status'=>200,'msg'=>'success','data'=>$res];
}
// Add order
public function orders(Request $request){
$param=$request->post();
// goods id
$id=$request->post('g_id');
// Query the inventory of this commodity
$good=new Goodspecs();
$ku=$good->where('g_id',$id)->first();
$number=$ku['num'];
// Judge whether the stock of goods is enough
if($number<$param['num']){
return ['status'=>0,'msg'=>' Insufficient inventory of goods ','data'=>$number];
}
$model=new Orders();
$res=$model->create($param);
if(!$res){
return ['status'=>0,'msg'=>'error','data'=>$res];
}else{
return ['status'=>200,'msg'=>'success','data'=>$res];
}
}
// Get order details
public function order(Request $request){
$oid=$request->get('oid');
$model=new Orders();
$res=$model->where('oid',$oid)->with(['user','goods'])->get();
return ['status'=>200,'msg'=>'success','data'=>$res];
}
// Execute payment
public function pay(Request $request){
$oid=$request->post('oid');
$uid=$request->post('uid');
$model=new Orders();
$oldprice=$model->where('oid',$oid)->first();
$user=new User();
$zh=$user->where('id',$uid)->first();
if($zh['price']<$oldprice['price']){
return ['status'=>0,'msg'=>' Lack of balance ','data'=>$zh];
}else{
// Product property sheet
$goods=new Goodspecs();
// Get the original inventory
$kc=$goods->where('g_id',$oldprice['g_id'])->first();
// Current stock = Original inventory - Purchase quantity
$newnumber=$kc['num']-$oldprice['num'];
// Successful payment Modify inventory
$res=$goods->where('g_id',$oldprice['g_id'])->update(['num'=>$newnumber]);
}
}
}
List of goods
.wxml( List of goods )
<view>
<view>
<view>
<form bindsubmit="dopost">
<view class="weui-search-bar">
<view class="weui-search-bar__form">
<!-- Search box -->
<view class="weui-search-bar__box">
<icon class="weui-icon-search_in-box" type="search" size="14"></icon>
<input type="text" name="keyword" value="{
{keyword}}" class="weui-search-bar__input" placeholder=" Please enter the search content " />
</view>
</view>
<!-- Search button , Call the search query method -->
<button size="mini" class="weui-search-bar__cancel-btn" form-type="submit"> Search for </button>
</view>
</form>
</view>
</view>
<view class="page-section-spacing">
<scroll-view scroll-y="true" class="page-scroll-style" bindscrolltolower="scroll">
<block wx:for="{
{activity}}" wx:key="activity">
<view class="scroll-view-content">
<image src="{
{item.image}}" class="scroll-view-image" bindtap=""></image>
<view class="scroll-view-text" bindtap="detail" data-id="{
{item.gid}}">
{
{item.name}}
</view>
<view class="scroll-view-name">
{
{item.price}}
</view>
</view>
</block>
</scroll-view>
</view>
</view>
.wxss
/**index.wxss**/
.weui-search-bar {
position: relative;
padding: 8px 10px;
display: -webkit-box;
display: -webkit-flex;
display: flex;
box-sizing: border-box;
background-color: #EFEFF4;
border-top: 1rpx solid #D7D6DC;
border-bottom: 1rpx solid #D7D6DC;
}
.weui-icon-search_in-box {
position: absolute;
left: 10px;
top: 7px;
}
.weui-search-bar__form {
position: relative;
-webkit-box-flex: 1;
-webkit-flex: auto;
flex: auto;
border-radius: 5px;
background: #FFFFFF;
border: 1rpx solid #E6E6EA;
}
.weui-search-bar__box {
position: relative;
padding-left: 30px;
padding-right: 30px;
width: 100%;
box-sizing: border-box;
z-index: 1;
}
.weui-search-bar__input {
height: 28px;
line-height: 28px;
font-size: 14px;
}
.weui-search-bar__cancel-btn {
margin-left: 10px;
line-height: 28px;
color: #09BB07;
white-space: nowrap;
}
.swp{
height: 500rpx;
}
.page-section-spacing{
margin-top: 60rpx;
}
.page-scroll-style{
height: 1000rpx;
background: aliceblue;
}
.scroll-view-content{
height: 230rpx;
margin: auto 10rpx;
background: white;
border: 1px solid gray;
}
.scroll-view-image{
width: 200rpx;
height: 200rpx;
margin-top: 15rpx;
margin-left: 20rpx;
float: left;
}
.scroll-view-text{
width: 400rpx;
float: left;
font-weight: 800;
margin-top: 15rpx;
margin-left: 20rpx;
}
.scroll-view-name{
float: left;
font-size: 30rpx;
color: gray;
margin-top: 20rpx;
margin-left: 20rpx;
}
.scroll-view_H{
white-space: nowrap;
}
.scroll-view-item{
height: 300rpx;
}
.scroll-view-item_H{
display: inline-block;
width: 100%;
height: 300rpx;
}
.js
Page({
/**
* Initial data of the page
*/
data: {
activity:{},
page:1,
last_page : 0,
keyword:''
},
detail:function(evn){
let id=evn.target.dataset.id;
wx.reLaunch({
url: '/pages/detail/detail?id='+id,
})
},
// load
scroll(e){
let that = this;
let page = that.data.page+1;
let keyword = that.data.keyword
that.setData({
page:page
})
let last_page = that.data.last_page
if(page > last_page){
wx.showToast({
title: ' Whether the ',
})
return ;
}
wx.showLoading({
title: ' Loading ',
})
let token=wx.getStorageSync('token');
wx.request({
url: 'http://www.yk.com/api/v2/goods',
data:{page,keyword},
header: {
token
},
success (res) {
console.log(res.data)
let activity = res.data.data.data
that.setData({
activity:that.data.activity.concat(activity),
})
wx.hideLoading()
}
})
},
/**
* Life cycle function -- Monitor page loading
*/
onLoad: function (options) {
var that = this;
let token=wx.getStorageSync('token');
wx.request({
url: 'http://www.yk.com/api/v2/goods',
header: {
token
},
success (res) {
// console.log(res.data)
let activity = res.data.data.data
that.setData({
activity:activity,
last_page:res.data.data.last_page,
page:res.data.data.current_page
})
}
})
},
// Search for
dopost:function(e){
console.log(e);
let formData = e.detail.value;
wx.request({
url: 'http://www.week2.skill.com/api/activity/index',
data:formData,
method:"GET",
success:res=>{
console.log(res);
if(res.data.status==200){
this.setData({
activity:res.data.data.data,
keyword:formData.keyword,
last_page:res.data.data.last_page,
page:res.data.data.current_page
})
}
},
fail(e){
wx.showToast({
title: ' request was aborted ',
icon:"error"
})
}
})
},
})
Goods details
.wxml
<!-- banner -->
<swiper indicator-dots="{
{indicatorDots}}" autoplay="{
{autoplay}}" interval="{
{interval}}" duration="{
{duration}}">
<block>
<swiper-item>
<image src="{
{activity.image}}" data-src="{
{item}}" bindtap="previewImage"></image>
</swiper-item>
</block>
</swiper>
<scroll-view scroll-y="true">
<view class="detail">
<text class="title">{
{activity.name}}</text>
<text class="price">¥{
{activity.price}}</text>
</view>
<view class="separate"></view>
<!-- sku choice -->
<text bindtap="toggleDialog"> Please choose the purchase quantity </text>
<view class="separate"></view>
<text> Product evaluation </text>
<text class="text-remark"> Things are OK , Praise ~</text>
<view class="separate"></view>
<text> Goods details </text>
<block wx:for-items="{
{detailImg}}" wx:key="name">
<image class="image_detail" src="{
{item}}" />
</block>
<view class="temp"></view>
</scroll-view>
<!-- Bottom suspension bar
<view class="detail-nav">
<image bindtap="toCar"/>
<view class="line_nav"></view>
<image bindtap="addLike"/>
<button class="button-green" bindtap="addCar" formType="submit"> Add to cart </button>
<button class="button-red" bindtap="immeBuy" formType="submit"> Buy now </button>
</view> -->
<!--pages/demo/demo.wxml-->
<view class="container">
<view class="footer-box" hover-class="btn-hover" bindtap="buy" data-id="{
{activity.gid}}">
Buy now
</view>
<view class="mark" hidden='{
{selHidden}}' bindtap='hiddenSel'></view>
<view class="detail-box" animation="{
{animationDataSel}}" wx:for="{
{activ}}">
<view class="goods-img-box">
<image src="{
{item.image}}" class="goods-img"></image>
<view class='right-side'>
<view class='price'>¥{
{item.price}}</view>
<view class='type'> Selected :{
{selTypeList}}</view>
<view class='inventory'> stock :{
{activ.num}}</view>
</view>
<view class="sel-box">
<view class="sel-list" wx:for="{
{item.specs}}">
<text class="{
{indexArr[childIndex] == index ? 'active':''}}" bindtap="choice" data-fid="{
{childIndex}}" data-id="{
{index}}">
{
{item.name}}
</text>
</view>
<view class="sel-list" wx:for="{
{item.specs}}">
<text class="{
{indexArr[childIndex] == index ? 'active':''}}" bindtap="choice" data-fid="{
{childIndex}}" data-id="{
{index}}">
{
{item.name}}
</text>
</view>
</view>
</view>
<view class="number-box" style="margin-top: 200px;">
<view class="control {
{plusBan}}" bindtap='plus'>+</view>
<view class="control num">{
{selNum}}</view>
<view class="control {
{minusBan}}" bindtap='minus'>-</view>
</view>
<view class="confirm-btn {
{btnType}}" bindtap='confirm' data-id="{
{activity.gid}}" data-price="{
{activity.price}}"> confirm </view>
</view>
</view>
.wxss
page {
display: flex;
flex-direction: column;
height: 100%;
}
/* Set up directly swiper attribute */
swiper {
height: 500rpx;
}
swiper-item image {
width: 100%;
height: 100%;
}
.detail {
display: flex;
flex-direction: column;
margin-top: 15rpx;
margin-bottom: 0rpx;
}
.detail .title {
font-size: 40rpx;
margin: 10rpx;
color: black;
text-align: justify;
}
.detail .price {
color: red;
font-size: 40rpx;
margin: 10rpx;
}
.line_flag {
width: 80rpx;
height: 1rpx;
display: inline-block;
margin: 20rpx auto;
background-color: gainsboro;
text-align: center;
}
.line {
width: 100%;
height: 2rpx;
display: inline-block;
margin: 20rpx 0rpx;
background-color: gainsboro;
text-align: center;
}
.detail-nav {
display: flex;
flex-direction: row;
align-items: center;
float: left;
background-color: #fff;
position: fixed;
bottom: 0;
right: 0;
z-index: 1;
width: 100%;
height: 100rpx;
}
.button-green {
background-color: #4caf50; /* Green */
}
.button-red {
background-color: #f44336; /* Red */
}
.image_detail {
width: 100%;
}
button {
color: white;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 30rpx;
border-radius: 0rpx;
width: 50%;
height: 100%;
line-height: 100rpx;
}
.detail-nav image {
width: 70rpx;
height: 50rpx;
margin: 20rpx 40rpx;
}
.line_nav {
width: 5rpx;
height: 100%;
background-color: gainsboro;
}
/* placeholder */
.temp {
height: 100rpx;
}
text {
display: block;
height: 60rpx;
line-height: 60rpx;
font-size: 30rpx;
margin: 10rpx;
}
.text-remark {
display: block;
font-size: 25rpx;
margin: 10rpx;
}
/* pages/demo/demo.wxss */
.container .footer-box{
position: fixed;
bottom: 0rpx;
margin: auto;
height: 100rpx;
width:100%;
background-color: #E40112;
text-align: center;
line-height: 100rpx;
color: #fff;
font-size: 32rpx;
}
.container .btn-hover{
opacity: 0.8;
}
.container .mark{
position: fixed;
z-index: 10;
height: 100%;
width: 100%;
background-color: rgba(0, 0, 0, 0.75)
}
.container .detail-box{
position: fixed;
z-index: 10;
bottom: -980rpx;
height: 980rpx;
width: 100%;
background-color: #fff;
}
.container .detail-box .goods-img-box{
height: 240rpx;
box-sizing: border-box;
padding: 24rpx;
border-bottom: solid 1rpx #e3e3e3;
}
.container .detail-box .goods-img-box .goods-img{
height: 192rpx;
width: 192rpx;
float: left;
}
.container .detail-box .goods-img-box .right-side{
float: left;
padding-top: 10rpx;
}
.container .detail-box .goods-img-box .right-side .price{
font-size: 32rpx;
color: #E40112;
font-weight: bold;
}
.container .detail-box .goods-img-box .right-side .type{
font-size: 24rpx;
color: #333;
margin-top: 8rpx;
margin-bottom: 8rpx;
overflow : hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.container .detail-box .goods-img-box .right-side .inventory{
font-size: 24rpx;
color: #999;
}
.container .detail-box .sel-box{
height: 560rpx;
width: 100%;
box-sizing: border-box;
padding-bottom: 24rpx;
overflow-y: auto;
}
.container .detail-box .sel-box .sel-list .sel-title{
font-size: 28rpx;
color: #333;
line-height: 60rpx;
padding-left: 24rpx;
}
.container .detail-box .sel-box .sel-list .type-list{
padding-left: 24rpx;
}
.container .detail-box .sel-box .sel-list .type-list {
overflow: hidden;
}
.container .detail-box .sel-box .sel-list .type-list .type-item{
display: inline-block;
height: 50rpx;
line-height: 48rpx;
border: solid 1rpx #999;
padding-left: 15rpx;
padding-right: 15rpx;
font-size: 24rpx;
color: #666;
border-radius: 5rpx;
margin-right: 24rpx;
margin-bottom: 24rpx;
}
.container .detail-box .sel-box .sel-list .type-list .sel{
border: solid 1rpx #f63636;
color: #f63636;
}
.container .detail-box .sel-box .sel-list .type-list .ban{
background-color: #f5f5f5;
border: solid 1rpx #f5f5f5;
}
.container .detail-box .confirm-btn{
height: 100rpx;
background-color: #E40112;
text-align: center;
line-height: 100rpx;
color: #fff;
font-size: 30rpx;
}
.container .detail-box .buy-ban{
background-color: #ddd;
}
.container .detail-box .number-box{
padding-left: 24rpx;
padding-right: 24rpx;
height: 80rpx;
box-sizing: border-box;
border-top: solid 1rpx #e3e3e3;
}
.container .detail-box .number-box .control{
margin-top: 14rpx;
float: right;
height: 52rpx;
width: 52rpx;
background-color: #e3e3e3;
text-align: center;
line-height: 52rpx;
color: #666;
font-size: 36rpx;
border-radius: 5rpx;
margin-left: 4rpx;
}
.container .detail-box .number-box .ban{
background-color: #F0F0F0;
}
.container .detail-box .number-box .num{
width: 100rpx;
font-size: 26rpx;
background-color: #f0f0f0;
font-family: Arial, Helvetica, sans-serif;
}
.js
Page({
data: {
shopping:[],
selNum:1,// Quantity to buy
},
minus:function(){
// Reduce the number of purchases
let that=this;
if (that.data.minusBan=="ban"){
return;
}else{
that.setData({
selNum: that.data.selNum-1
})
if (that.data.selNum==1){
that.setData({
minusBan:"ban"
})
}
}
if (that.data.selNum == that.data.selStock) {
that.setData({
plusBan: "ban"
})
}else{
that.setData({
plusBan: ""
})
}
},
plus:function(){
// Increase the number of purchases
let that = this;
if (that.data.plusBan == "ban"){
return;
}else{
that.setData({
selNum: that.data.selNum + 1
})
if (that.data.selNum == that.data.selStock) {
that.setData({
plusBan: "ban"
})
}
if (that.data.selNum == 1) {
that.setData({
minusBan: "ban"
})
}else{
that.setData({
minusBan: ""
})
}
}
},
confirm:function(evn){
// Pop up confirmation button triggers
let num=this.data.selNum;
let u_id=wx.getStorageSync('userid');
let g_id=evn.target.dataset.id;
let oldprice=evn.target.dataset.price;
// Total price = Total quantity * The unit price
let price=num*oldprice;
let token=wx.getStorageSync('token');
wx.request({
url: 'http://www.yk.com/api/v2/orders',
method:'post',
data:{u_id,g_id,num,price},
header: {
token
},
success (res) {
// Get order id
let id=res.data.data.id;
wx.reLaunch({
url: '/pages/order/order?id='+id,
})
}
})
},
onLoad: function (options) {
// goods id
let id=options.id;
var that = this;
let token=wx.getStorageSync('token');
wx.request({
url: 'http://www.yk.com/api/v2/detail',
method:'GET',
data:{id},
header: {
token
},
success (res) {
// console.log(res.data)
let activity = res.data.data
that.setData({
activity:activity,
})
}
})
},
buy:function(evn){
// console.log(evn.target.dataset.id);
// goods id
let id=evn.target.dataset.id;
// The buy now button triggers
this.showSelBox();
let that = this;
let token=wx.getStorageSync('token');
wx.request({
url: 'http://www.yk.com/api/v2/specs',
method:'GET',
data:{id},
header: {
token
},
success (res) {
console.log(res.data.data)
let activ = res.data.data;
that.setData({
activ:activ,
})
}
})
},
onReady: function () {
let that = this
that.animation = wx.createAnimation({ // Animation
duration: 300, // Animation duration
timingFunction: 'linear', // The effect of animation The speed of animation is the same from beginning to end
transformOrigin: "50% 50% 0",
})
},
showSelBox: function (e) {// Display options
let that = this;
let systemInfo = wx.getSystemInfoSync();
let px = 980 / 750 * systemInfo.windowWidth;
this.animation.translateY(-px).step() // stay Y Axis offset tx, Company px
this.setData({
animationDataSel: that.animation.export(),
selHidden: false,
})
},
})
Order page
.wxml
<view wx:for="{
{order}}" wx:key="order">
<view wx:for="{
{item.user}}">
<view>{
{item.nickName}}</view>
<view>{
{item.phone}}</view>
</view>
<view style="margin-top: 100;" wx:for="{
{item.goods}}">
<view>{
{item.name}}</view>
<image src="{
{item.image}}"></image>
<view> The unit price {
{item.price}}</view>
</view>
<view style="margin-top: 100;">
<view> Number :{
{item.num}}</view>
<view> The total price :{
{item.price}}</view>
<button bindtap="pay" data-id="{
{item.oid}}"> To pay </button>
</view>
</view>
.js
// pages/order/order.js
Page({
/**
* Initial data of the page
*/
data: {
},
pay:function(evn){
let oid=evn.target.dataset.id;
let uid=wx.getStorageSync('userid');
let token=wx.getStorageSync('token');
wx.request({
url: 'http://www.yk.com/api/v2/pay',
method:'post',
data:{oid,uid},
header: {
token
},
success (res) {
// Get order id
console.log(res)
// let order=res.data.data;
// console.log(order)
// that.setData({
// order:order
// })
// wx.reLaunch({
// url: '/pages/order/order?id='+id,
// })
}
})
},
/**
* Life cycle function -- Monitor page loading
*/
onLoad: function (options) {
let that=this;
// console.log(options.id);
let oid=options.id;
let token=wx.getStorageSync('token');
wx.request({
url: 'http://www.yk.com/api/v2/order',
method:'get',
data:{oid},
header: {
token
},
success (res) {
// Get order id
// console.log(res)
let order=res.data.data;
console.log(order)
that.setData({
order:order
})
// wx.reLaunch({
// url: '/pages/order/order?id='+id,
// })
}
})
},
/**
* Life cycle function -- Listening page first rendering completed
*/
onReady: function () {
},
/**
* Life cycle function -- Monitor page display
*/
onShow: function () {
},
/**
* Life cycle function -- Monitor page hidden
*/
onHide: function () {
},
/**
* Life cycle function -- Monitor page uninstall
*/
onUnload: function () {
},
/**
* Page related event handler -- Monitor user pull-down action
*/
onPullDownRefresh: function () {
},
/**
* Handling function of page pull bottom event
*/
onReachBottom: function () {
},
/**
* Users click the upper right corner to share
*/
onShareAppMessage: function () {
}
})app.json
{
"pages": [
"pages/mine/mine",
"pages/index/index",
"pages/home/home",
"pages/detail/detail",
"pages/order/order"
],
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#f0145a",
"navigationBarTitleText": " Wechat mall ",
"backgroundColor": "#f0145a"
},
"tabBar": {
"color": "#858585",
"selectedColor": "#f0145a",
"backgroundColor": "#ffffff",
"borderStyle": "white",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "images/home.png",
"selectedIconPath": "images/home_select.png",
"text": " home page "
},
{
"pagePath": "pages/home/home",
"iconPath": "images/classify.png",
"selectedIconPath": "images/classify_select.png",
"text": " classification "
},
{
"pagePath": "pages/detail/detail",
"iconPath": "images/classify.png",
"selectedIconPath": "images/classify_select.png",
"text": " details "
},
{
"pagePath": "pages/mine/mine",
"iconPath": "images/mine.png",
"selectedIconPath": "images/mine_select.png",
"text": " my "
}
]
},
"sitemapLocation": "sitemap.json"
}边栏推荐
- Aiot project that is an introduction to the basics of the Internet of things and can be implemented in practice
- Technology Review: Interpretation of cloud native architecture trend in 2022
- Interview experience - list of questions
- Handling skills of SQL optimization (2)
- Methods for obtaining some information of equipment
- 2022-02-19: fence installation. In a two-dimensional garden, there are some trees represented by (x, y) coordinates. As the installation cost is very expensive, your task is to enclose all the trees w
- Folding mobile phones are expected to explode, or help Samsung compete with apple and Chinese mobile phones
- The locally developed SAP ui5 application is deployed to the ABAP server to perform error analysis
- SAP ui5 date type sap ui. model. type. Analysis of date parsing format
- Day22 send request and parameterization using JMeter
猜你喜欢

What happens when redis runs out of memory

Add the author watermark plugin v1.4 update to the posts of elegant grass discuz plugin - some forums post errors and bugs have been fixed
SAP ui5 date type sap ui. model. type. Analysis of date parsing format

MySQL tuning --01--- optimization steps and system performance parameters
Some common errors and solutions of using SAP ui5 to consume OData services

Day22 send request and parameterization using JMeter
![[road of system analyst] collection of wrong questions in the chapters of Applied Mathematics and economic management](/img/62/dab2ac0526795f2040394acd9efdd3.jpg)
[road of system analyst] collection of wrong questions in the chapters of Applied Mathematics and economic management

Folding mobile phones are expected to explode, or help Samsung compete with apple and Chinese mobile phones
![[hand torn STL] Stack & queue](/img/db/d05c52f8e3fb0aade51460e86cf623.jpg)
[hand torn STL] Stack & queue
Linus' speech recordings, which were lost in 1994, were made public
随机推荐
JS to realize the encapsulation of the function of obtaining the mouse click position
[network security] sharing of experience and ideas of an emergency battle
Advantages and disadvantages of using SNMP and WMI polling
Fdisk command – disk partition
Lesson 8: FTP server setup and loading
Mount command - file system mount
Socket, network model notes
cacacahe
Jz-066- motion range of robot
【LeetCode】40. Combined summation II (2 strokes of wrong questions)
Soft exam information system project manager_ Information system security management - Senior Information System Project Manager of soft test 026
Part 33 of SAP ui5 application development tutorial - trial version of responsiveness of SAP ui5 applications
Do you know what a three-tier architecture is?
How SAP ui5 device type detection device API works
Research Report on global and Chinese vaccine market profit forecast and the 14th five year plan development strategy 2022-2028
Asemi fast recovery diode us1m parameters, us1m recovery time, us1m voltage drop
C simple operation mongodb
Copying DNA
Laravel8 fill data
SAP Fiori tools and corresponding cli (command line interface)