小程序 结合 laravel 实现秒杀

参考博客:

https://blog.csdn.net/m0_56487875/article/details/118603439

小程序登录:

https://www.cnblogs.com/xiaoyantongxue/p/15677256.html

小程序授权登录跳转至秒杀列表页

// pages/seckill/seckill.js
Page({

    /**
     * 页面的初始数据
     */
    data: {
        goods: []
    },

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad: function (options) {
        var token=wx.getStorageSync('token')
        wx.request({
            url: 'http://www.yan.com/api/yk/goods', //仅为示例,并非真实的接口地址
            header: {token},
            method: "POST",
            success: res => {
                console.log(res.data);
                this.setData({
                    goods: res.data.data
                })
              
            }
        })


    },
      /**
     * 开始抢购按钮
     */
     start(e){
        var id=e.target.dataset.id
        wx.navigateTo({
          url: '/pages/details/details?id='+id,
        })
      
     




    },
 
  
})

//数据进行渲染:

<!--pages/seckill/seckill.wxml-->
<view>秒杀</view>

<view class="page-section-spacing">
        <scroll-view scroll-y="true" class="page-scroll-style" bindscrolltolower="scroll">
        <block wx:for="{{goods}}" wx:key="goods">
          <view class="scroll-view-content">
            <image src="{{item.goods.goods_image}}" class="scroll-view-image"></image>
            <view class="scroll-view-text">
              {{item.goods.goods_name}}
            </view>
            <view class="scroll-view-name">
               ¥{{item.goods.goods_price}}
            </view>
            <view class="scroll-view-text">
               限量{{item.goods.goods_nums}}
            </view>
            <text bindtap="start" data-id="{{item.id}}">开始抢购</text>
          </view>
        </block>
        </scroll-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;
    color: red;
  }
  .scroll-view_H{
    white-space: nowrap;
  }
  .scroll-view-item{
    height: 300rpx;
  }
  .scroll-view-item_H{
    display: inline-block;
    width: 100%;
    height: 300rpx;
  }

 

 

 

php 后台请求的数据路由:

Route::group(['namespace' => 'YK','middleware'=>'jwt'], function () {
//列表展示
    Route::post('yk/goods','YkController@goods');
//    详情
    Route::post('yk/details','YkController@details');
//    秒杀
    Route::post('yk/checkstock','YkController@checkStock');
//    订单的生成
    Route::post('yk/order','YkController@createOrder');

});

控制器:

<?php

namespace App\Http\Controllers\YK;

use App\Http\Controllers\Controller;
use App\models\Seckill\Goods;
use App\Models\Seckill\SeckillOrder;
use App\Models\Seckill\SeckillTime;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Redis;
use Predis\Client;

class YkController extends Controller
{



    //列表展示
    public function goods()
    {
        $result = SeckillTime::with(['goods'])
            ->get()->toArray();

        //进行把参与秒杀的商品写入到数据库
        foreach ($result as $val) {
            //生成对应商品库存队列
            $goods = "activity_goods_" . $val['goods_id'];
            for ($i = 0; $i < $val['sku_nums']; $i++) {
                Redis::lpush($goods, 1);
            }

            return response()->json(['code' => 200, 'message' => 'success', 'data' => $result]);
        }
    }

//    详情
    public function details(Request $request)
    {
        $id = $request->post('id');
        $res = Goods::where('id', $id)->first();
        if ($res) {
            return response()->json(['code' => 200, 'message' => 'success', 'data' => $res]);
        }
        return response()->json(['code' => 500, 'message' => 'no', 'data' => '']);
    }

//    抢购:
    public function checkStock(Request $request)
    {
//        接受用户id
        $userID=$request->post('userid');
//        商品id
        $goodsID=$request->post('id');
         $goods = "activity_goods_".$goodsID;
        //对应商品抢购成功用户集合 {1,3,4}
        $robSuccessUser = "success_user".$goodsID;
        //进行判断当前用户是否在抢成功的队列里面
        $result = Redis::sismember($robSuccessUser,$userID);
        //如果你在这里面,就抢完了
        if ($result) {
            //如果抢购成功 返回状态码,进行下单
            return response()->json(['code' => 201, 'data' => '', 'msg' => '已经抢购过了']);
        }
        //减库存,把队列里面的数据从左边 头
        $count = Redis::lpop($goods);
        if (!$count) {
            //如果抢购成功 返回状态码,进行下单
            return response()->json(['code' => 202, 'data' => '', 'msg' => '已经抢光了哦']);
        }
        //把当前这个秒杀的uid存储到中奖的队列里set
        $success = Redis::sadd($robSuccessUser, $userID);
        if(!$success){
            //已经在成功队列里了,加回库存,防止的是同个用户并发请求
            Redis::lpush($goods, 1);
            //如果抢购成功 返回状态码,进行下单
            return response()->json(['errorCode' => 203, 'data' => '', 'msg' => '已经抢购过了']);
        }

        //如果抢购成功 返回状态码,进行下单
        return response()->json(['errorCode' => 200, 'data' => '', 'msg' => '秒杀成功']);

    }
订单的生成
    public function createOrder(Request $request)
    {


//接受小程序用户id
        $userID=$request->post('userid');
        //抢购用户id
        //商品id
        $goodsID = $request->post("goods_id");
        //对应商品抢购成功用户集合 {1,3,4}
        $robSuccessUser = "success_user".$goodsID;
        //进行判断当前用户是否在抢成功的队列里面
        $result = Redis::sismember($robSuccessUser,$userID);
        //如果你在这里面,就抢完了
        if (!$result) {
            //如果抢购成功 返回状态码,进行下单
            return response()->json(['code' => 203, 'data' => '', 'msg' => '手慢了!']);
        }

        DB::beginTransaction();
        try{
            //减库存 秒杀的商频库存减去一
            SeckillTime::decrement('sku_nums');
            Goods::decrement('goods_nums');
            //生成订单
            $order_no='YK'.date('YmdHis').sprintf("%'.09d",$goodsID).mt_rand(1000,9999);
//            将订单号和用户id,商品id添加至 订单明细表中
            $data=[];
            $data['user_id']=$userID;
            $data['g_id']=$goodsID;
            $data['order']=$order_no;
            SeckillOrder::insertGetId($data);
            DB::commit();
            //下单成功,跳转支付页面
            return response()->json(['code' => 200, 'data' => $order_no, 'msg' => '下单成功!']);
        }catch (\Exception $e){
            DB::rollBack();
        }

    }

}

 

 

 

小程序抢购,点击抢购进入详情页面:

 

 

 

详情wxjs的代码:

// pages/details/details.js
// 放抖的引入
import tool from "../../utils/tool.js";
Page({
    /**
     * 页面的初始数据
     */
    data: {
   goods_details:[]
    },

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad: function (options) {
        var token=wx.getStorageSync('token')
        var id=options.id
        wx.request({
            url: 'http://www.yan.com/api/yk/details', //仅为示例,并非真实的接口地址
            header: {token},
            data:{
             id:id
            },
            method: "POST",
            success: res => {
                // console.log(res.data.data);
                this.setData({
                    goods_details: res.data.data
                })
              
            }
        })
        
    },
//秒杀
          buyGoods(e){
        var token=wx.getStorageSync('token')
         var  id=e.target.dataset.id;
        //  获取用户id
        var userid=wx.getStorageSync('userid');
         wx.request({
            url: 'http://www.yan.com/api/yk/checkstock', //仅为示例,并非真实的接口地址
            header: {token},
            data:{
             id:id,
             userid:userid
            },
            method: "POST",
            success: res => {
                console.log(res.data);
                if(res.data.code==201){
                    wx.switchTab({
                        url: '/pages/order/order?gid='+id,
                      })
                    wx.showToast({
                      title: '已经抢购过了,请支付',
                    })
                  

                }
                if(res.data.code==202){
                    wx.showToast({
                      title: '已经抢光了哦',
                    })

                }
                if(res.data.code==203){
                    wx.showToast({
                      title: '已经抢购过了,请支付',
                    })
                    wx.switchTab({
                        url: '/pages/order/order?gid='+id,
                      })

                }
                if(res.data.code==200){
                    wx.showToast({
                      title: '秒杀成功,请支付',
                    })
                    // 跳转至订单页面
                    wx.switchTab({
                        url: '/pages/order/order?gid='+id,
                      })
                }
               
               
            
              
            }
        })
        },
   
})

详情wxml代码:

<!--pages/details/details.wxml-->
<view class="page-section-spacing">
        <scroll-view scroll-y="true" class="page-scroll-style" bindscrolltolower="scroll">
          <view class="scroll-view-content">
            <image src="{{goods_details.goods_image}}" class="scroll-view-image"></image>
            <view class="scroll-view-text">
              {{goods_details.goods_name}}
            </view>
            <view class="scroll-view-name">
               ¥{{goods_details.goods_price}}
            </view>
            <view class="scroll-view-text">
               限量{{goods_details.goods_nums}}
            </view>
            <text bindtap="buyGoods" class="a" data-id="{{goods_details.id}}">开始秒杀</text>
          </view>
 
        </scroll-view>
</view>

抢购完成进入订单页面:

<button type="primary" bindtap="pay">支付</button>
// pages/order/order.js
Page({

    /**
     * 页面的初始数据
     */
    data: {
        goods_id: ''
    },

    /**
     * 生命周期函数--监听页面加载
     */
    onLoad: function (options) {
        // 获取商品id用于订单的生成
        var gid = options.gid;
        this.setData({
            goods_id: gid
        })
    },
    // 支付
    pay(e) {
        //    获取用户id
        var userid = wx.getStorageSync('userid');
        var goods_id = this.data.goods_id,
        var token=wx.getStorageSync('token')
        //  将用户id发送至后台用于生成订单
        wx.request({
            url: 'http://www.yan.com/api/yk/order', //仅为示例,并非真实的接口地址
            data: {
                userid: userid,
                goods_id: goods_id
            },
            header: {token},
            method: "POST",
            success(res) {
                if (res.data.code == 203) {
                    wx.showToast({
                        title: '手慢啦',
                    })
                }
                if (res.data.code == 200) {
                    wx.showToast({
                        title: '下单成功',
                    })
                }

            }
        })



    }

})

 

posted @ 2021-12-30 11:02  王越666  阅读(233)  评论(0编辑  收藏  举报