wxml:
wxml: <view>商品秒杀页面</view> <view wx:if="{{goods.stime<goods.time}}">秒杀已开始</view> <view wx:else="{{goods.stime > goods.time}}">秒杀未开始</view> <l-countdown time-type="second" time="{{expire_time}}" bind:linend="changeBtn" /> <l-card type="primary" full="{{true}}" image="{{goods.goods.goods_img}}" title="{{goods.goods.goods_name}}"> <view> 价格:{{goods.goods.goods_price}} </view> <view> <!-- <button disabled="true" bindtap="buyGoods" >抢购</button> --> <l-button disabled="{{ btn_disable }}" bind:lintap="buyGoods" type="error" data-goods_id="{{ goods.goods.id }}">立即秒杀</l-button> </view> </l-card>
js:
js: import tool from "../../pages/tool/tool.js"; Page({ /** * 页面的初始数据 */ data: { goods:{}, expire_time:0, btn_disable:false, win_scrollTop:0, }, /** * 生命周期函数--监听页面加载 */ onl oad: function (options) { //商品id let goods_id = options.goods_id; console.log(goods_id) this.getGoodsDetail(goods_id) }, //获取商品详情 getGoodsDetail(goods_id){ wx.request({ url: 'http://www.skill.com/api/detail?goods_id='+goods_id, header: { token:wx.getStorageSync('token') }, success: res => { //当前的时间戳 let now_time = Math.round(new Date().getTime() / 1000).toString(); let expire_time = res.data.data.start_time-now_time; this.setData({ goods:res.data.data, expire_time }) if(expire_time > 0){ this.setData({ btn_disable:true }) } console.log(this.data.goods) } }) }, //立即抢购 buyGoods: tool.debounce(function(e) { var token = wx.getStorageSync('token') if(token==''){ wx.showToast({ title: '请先登录', }) // wx.navigateTo({ // url: '/pages/login/login', // }) return } let goods_id = e[0].currentTarget.dataset.goods_id wx.request({ url: 'http://www.skill.com/api/skill', header: { token:wx.getStorageSync('token') }, method:"POST", data:{ goods_id }, success: res => { let code = res.statusCode.toString() if (!code.startsWith('2')){ wx.showToast({ title: '异常!', icon:1 }) } if(res.data.errorCode == 0){ wx.showToast({ title: res.data.msg, }) // wx.navigateTo({ // url: '/pages/order/order', // }) }else{ wx.showToast({ title: res.data.msg, }) } console.log(res.data) } }) }), changeBtn(){ this.setData({ btn_disable:false }) }, })
json:
json: { "navigationBarTitleText": "商品详情", "usingComponents": { "l-countdown":"/miniprogram_npm/lin-ui/countdown", "l-card":"/miniprogram_npm/lin-ui/card", "l-button":"/miniprogram_npm/lin-ui/button" } }
php:
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use App\Jobs\OrderJob; use App\Models\Goods; use App\Models\Order; use App\Models\Skill; use App\Models\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\Redis; class GoodsController extends Controller { /** * 商品秒杀列表 * @return \Illuminate\Http\JsonResponse */ public function activityList() { $result = Skill::with(['goods']) ->get(); return response()->json(['errorCode' => 0, 'data' => $result, 'msg' => '查询成功']); } //商品秒杀详情 public function goodsDetail(Request $request) { $goods_id = $request->get('goods_id'); $result = Skill::with(['goods']) ->where('goods_id',$goods_id) ->first(); $time = time(); $result['time'] = $time; return response()->json(['errorCode' => 0, 'data' => $result, 'msg' => '查询成功']); } //同步库存 public function syncStock(request $request) { //查看队列的长度 // $count = Redis::llen('activity_goods_1'); // echo $count; // die; //查出所有参与秒杀活动列表 $page = $request->get('page')?$request->get('page'):1; $limit = $request->get('limit')?$request->get('limit'):5; $size = ($page-1)*$limit; $result = Skill::with(['goods']) ->offset($size) ->limit($limit) ->get(); $data = json_decode($result,true); //进行把参与秒杀的商品写入到数据库 foreach ($data as $val){ //生成对应商品库存队列 $goods = "activity_goods_".$val['goods_id']; for ($i=0; $i < $val['skill_num']; $i++) { Redis::lpush($goods, 1); } } return response()->json(['errorCode' => 0, 'data' => $result, 'msg' => '查询成功']); } //校验库存 /** * 秒杀接口 * @param Request $request * @return \Illuminate\Http\JsonResponse */ public function checkStock(Request $request) { //抢购用户id $openid =$request['uid']; $user = User::where('openid',$openid)->first(); $userID = $user['id']; //商品id $goodsID = $request->input("goods_id"); //对应商品库存队列 $goods = "activity_goods_".$goodsID; //对应商品抢购成功用户集合 {1,3,4} $robSuccessUser = "success_user".$goodsID; //进行判断当前用户是否在抢成功的队列里面 $result = Redis::sismember($robSuccessUser,$userID); //如果你在这里面,就抢完了 if ($result) { //如果抢购成功 返回状态码,进行下单 return response()->json(['errorCode' => 20000, 'data' => '', 'msg' => '已经抢购过了']); } //减库存,把队列里面的数据从左边 头 $count = Redis::lpop($goods); if (!$count) { //如果抢购成功 返回状态码,进行下单 return response()->json(['errorCode' => 20001, 'data' => '', 'msg' => '已经抢光了哦']); } //把当前这个秒杀的uid存储到中奖的队列里set $success = Redis::sadd($robSuccessUser, $userID); if(!$success){ //已经在成功队列里了,加回库存,防止的是同个用户并发请求 Redis::lpush($goods, 1); //如果抢购成功 返回状态码,进行下单 return response()->json(['errorCode' => 20002, 'data' => '', 'msg' => '已经抢购过了']); } //如果抢购成功 返回状态码,进行下单 return response()->json(['errorCode' => 0, 'data' => '', 'msg' => '秒杀成功']); } }