扫码红包系统php-支付宝扫码红包在哪里
作者
PHP实现连续签到的功能在很多网站无处不见扫码红包系统php,有一些是实现心情签到扫码红包系统php,发表心情。有一些是实现连续签到领取积分或者礼品之类的,根据业务的需求改变而改变,今天要来给大家讲解的是如何实现签到领取积分,连续签到领取礼品之类的功能如图所示,签到之前
签到之后的页面显示
这里给大家贴各种实现的核心代码,学习php主要是大家能借鉴,看懂思路,而不是各种复制黏贴哈扫码红包系统php!需求的需要,本功能实现需要用到三张表:
签到奖励设置表
CREATE TABLE `le_sign_in` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '递增主键', `name` varchar(100) NOT NULL COMMENT '签到名称', `icon` varchar(100) NOT NULL COMMENT '签到图标', `type` tinyint(3) unsigned NOT NULL DEFAULT '2' COMMENT '1. 常规 2. 额外', `keep_sign_in` tinyint(3) unsigned NOT NULL COMMENT '保持签到', `reward_rule` varchar(255) NOT NULL COMMENT '签到奖励规则:[ {reward_type:奖励类型1.积分 2.红包 reward_min:奖励最小值,reward_max:奖励最大值}]', `reward_sort` tinyint(3) unsigned NOT NULL DEFAULT '100' COMMENT '奖励排序', `admin_id` int(10) unsigned NOT NULL COMMENT '管理员用户ID', `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, `deleted_at` datetime DEFAULT NULL COMMENT '是否删除', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8 COMMENT='签到奖励设置表';日志表
CREATE TABLE `le_sign_in_log` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `user_id` int(10) unsigned NOT NULL COMMENT '用户ID', `created_at` datetime DEFAULT NULL COMMENT '签到时间', PRIMARY KEY (`id`), KEY `u_user_and_time` (`user_id`,`created_at`) USING BTREE) ENGINE=InnoDB AUTO_INCREMENT=245 DEFAULT CHARSET=utf8 COMMENT='用户签到日志表';签到奖励日志表
CREATE TABLE `zmq_sign_in_reward_log` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'v', `sign_in_log_id` int(10) unsigned NOT NULL COMMENT 'sign_id_log表id', `sign_in_id` int(10) NOT NULL COMMENT '签到ID', `reward_type` tinyint(3) unsigned NOT NULL COMMENT '奖励类型(1.积分 2.红包 )', `reward_quantity` decimal(10,2) unsigned NOT NULL COMMENT '奖励数量', `is_get` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '是否收到, 0未收到 1已收到', `get_time` datetime DEFAULT NULL COMMENT '收到时间', `type` tinyint(4) NOT NULL COMMENT '对应sign_in表中的type=2', `max_sign_in` *** allint(5) unsigned NOT NULL COMMENT '最大连续签到', `keep_sign_in` *** allint(5) unsigned NOT NULL COMMENT '保持签到次数', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=224 DEFAULT CHARSET=utf8 COMMENT='签到奖励日志表';前端模板文件,这里主要是用vue页面实现
<p id="sign_in" v-cloak> <p class="sign_in_box"> <p class="sign_in_record"> <p class="active_box"> <p>连续签到</p> <p class="number">{{ keepSignIn }}<em>天</em></p> </p> <p class="slash_bg"></p> <p class="history_box"> <p>最高连续记录</p> <p class="number">{{ maxSignIn }}<em>天</em></p> </p> </p> <p v-if="!signIn" class="sign_in_btn" @click="sign_in">签到</p> <p v-else class="sign_in_btn">已签到,获得{{ signReward }}</p> <a href="/mobile/signIn/log" class="sign_in_entrance">签到记录</a> </p> <p class="sign_in_hint" v-show="nextRewardDay">再坚持连续签到{{ nextRewardDay }}天,就可以获得额外奖励哦~</p> <p class="calendars_box"> <p class="today_title">{{currentYear}}年{{currentMonth}}月{{currentDay}}日</p> <ul class="week_box"> <li>日</li> <li>一</li> <li>二</li> <li>三</li> <li>四</li> <li>五</li> <li>六</li> </ul> <ul class="calendars_list"> <li v-for="i in last_month"></li> <li v-for="(item,index) in signInData" @click="showRewardList(item)" :class="{'active':item.isActive == 1, 'today':index == currentDay-1}"> <p v-if="item.is_get == 1" class="prize_price"><p>{{ item.reward_type_zh }}</p><p>{{ parseFloat(item.reward_quantity) }}</p></p> <p v-else >{{ index+1 }}</p> <!--有奖励并且没有领取则显示图片, 并且只有当天有额外奖励才显示--> <p v-if="item.has_reward == 1 && item.is_get == 0" class="signIn_prize"><img :src="item.icon"></p> <!-- 当天已签到,并且有奖励,还没有领取的则显示提示 --> <p v-if="item.isActive == 1 && item.has_reward == 1 && item.is_get == 0 && (index) == (currentDay-1)" class="item_hint"></p> </li> </ul> </p> <p class="signIn_banner" v-if="ad"><a :href="ad.link"><img :src="ad.pic"></a></p> <p v-show="signIn_pop" @click="signIn_pop = !signIn_pop" class="mark_bg2"></p> <p v-show="signIn_pop" class="signIn_pop"> <p v-if="!continue_signIn" class="top_bg"></p> <p v-else class="top_bg2"></p> <p v-if="signIn_pop_style==1" class="pop_title">{{ reward }}</p> <p v-if="signIn_pop_style==2" class="pop_title">请选择扫码红包系统php你的奖励!</p> <p v-if="signIn_pop_style==3" class="pop_title">{{ reward }}</p> <p v-if="signIn_pop_style==1||signIn_pop_style==3" class="odd_goods" :class="{ 'active':signIn_pop_style == 3}"><img :src="`/static/mobile/images/new/sign_in_type_${signInRewrdType}.png`"></p> <ul v-if="signIn_pop_style==2" class="even_goods"> <li v-for="(type, index) in currentReward.reward_type" @click="select_prize(index)" v-if="rewardNum >= index" :class="{'active':selectPrize == index}"> <img :src="`/static/mobile/images/new/sign_in_type_${type}.png`"> <p v-if="type==1">积分</p> <p v-if="type==2">现金红包</p> </li> </ul> <a @click="signIn_pop = !signIn_pop" v-if="signIn_pop_style==1||signIn_pop_style==3" class="close_pop" href="javascript:;">我知道了</a> </p></p>vue实现的代码,主要是与php后端代码的交互,与如何渲染到模板
new Vue({ el: '#sign_in', data: { ad:undefined, //广告 signIn:false,//是否已经签到 signInData:[], today:'', currentYear: 1970, // 年份 currentMonth: 1, // 月份 currentDay: 1, // 日期 currentWeek: 1, // 星期 last_month:'',//上个月剩余多少天 signIn_pop:false,//签到弹窗 continue_signIn:true,//是否持续签到 signIn_pop_style:3,//1.2.3分别是1领取单个2领取两个3领取后 selectPrize:-1,//两种奖品选择 keepSignIn:0,//连续签到 maxSignIn:0,//最大签到 reward:"", //弹出显示的奖励(用于签到和额外奖励) signReward:"", //签到显示的奖励(仅用于签到) nextRewardDay:0, // 下一次签到奖励 rewardNum:1, // 额外奖励可选数量 currentReward:0, // 现在额外奖励 signInRewrdType:0, }, created () { layer.open({type: 2, shadeClose: false}) var that = this; this.$http.post('/mobile/signIn', {}, {emulateJSON:true}).then(function (res) { if (res.body.status == 1) { var data = res.data.data that.signInData = data.calendars; that.maxSignIn = data.max_sign_in; that.keepSignIn = data.keep_sign_in; if (data.today_sign_in) { that.signReward = that.format_sign_in(data.today_sign_in) that.reward = that.format_reward(data.today_sign_in) that.signIn = true } else { that.signIn = data.today_sign_in } layer.closeAll() this.nextRewardTips() } }) this.$http.get('/mobile/index/ads?ad_type=12').then(function(res) { if (res.body.status == 1) { if (res.body.data[12]) this.ad = res.body.data[12][0] } }) this.initData(null) }, methods: { format_sign_in: function (reward) { if (!reward) return switch (parseInt(reward.reward_type)) { case 1: return ` ${reward.reward_quantity} 积分`; case 2: return ` ${reward.reward_quantity} 元`; } }, format_reward: function (reward) { if (!reward) return switch (parseInt(reward.reward_type)) { case 1: return `恭喜你,获得积分奖励 ${reward.reward_quantity} 积分`; case 2: return `恭喜你,获得红包奖励 ${reward.reward_quantity} 元`; default: console.log(reward.reward_type) } }, select_prize:function(e){ layer.open({type: 2, shadeClose: false}) this.selectPrize = e; var data = {log_id: this.currentReward.log_id, select: e} this.$http.post('/mobile/signIn/getReward', data, {emulateJSON:true}).then(function (res) { layer.closeAll() if (res.body.status == 1 && res.body.data) { var data = res.body.data this.reward = this.format_reward(data) this.currentReward.is_get = 1 this.currentReward.reward_type = data.reward_type this.currentReward.reward_type_zh = data.reward_type_zh this.currentReward.reward_quantity = parseFloat(data.reward_quantity) this.signInRewrdType = data.reward_type this.showPopStyle(1) } else { layer.open({ content: res.body.message, skin: 'msg', time: 2 //2秒后自动关闭 }); } }) }, // 用户激活签到 sign_in:function(){ this.$http.post('/mobile/signIn/active', {}, {emulateJSON:true}).then(function (res) { if (res.body.status == 1) { var data = res.body.data this.signReward = this.format_sign_in(data) this.reward = this.format_reward(data) this.signInRewrdType = data.reward_type this.signIn=true; this.signInData[this.currentDay-1].isActive = true; this.signInData[this.currentDay-1].log_id = data.log_id this.showPopStyle(1) if (this.keepSignIn == this.maxSignIn) { this.maxSignIn++ } this.keepSignIn++ this.nextRewardTips() } }) }, // 下一次签到奖励 nextRewardTips: function () { for (var index in this.signInData) { if (index >= this.currentDay) { if (this.signInData[index].icon) { this.nextRewardDay = index - this.currentDay + 1 break; } } } }, //格式化日期 formatDate: function (year, month, day) { const y = year let m = month if (m < 10) m = `0${m}` let d = day if (d < 10) d = `0${d}` return `${y}-${m}-${d}` }, initData: function (cur) { let date = '' if (cur) { date = new Date(cur) } else { date = new Date() } this.currentDay = date.getDate() // 今日日期 几号 this.currentYear = date.getFullYear() // 当前年份 this.currentMonth = date.getMonth() + 1 // 当前月份 this.currentWeek = date.getDay() // 1...6,0 // 今天是星期几 //当前月的第一天是星期几 date.setDate(1); this.firstWeek = date.getDay(); this.last_month=this.firstWeek; }, // 显示额外奖励列表 showRewardList: function (item) { if (item.isActive == 1 && item.has_reward == 1 && item.is_get == 0) { this.rewardNum = item.reward_num; this.currentReward = item // 额外奖励只有一个,直接领取 if (this.rewardNum == 1) { this.select_prize(0) } else { this.showPopStyle(2) } } if (item.is_get) { this.reward = this.format_reward(item) this.signInRewrdType = item.reward_type this.showPopStyle(1) } }, // 显示弹出框类型 showPopStyle: function (i) { this.signIn_pop_style = i this.signIn_pop=true; } }, mounted: function () { }, computed: { rewardNumZh: function () { if (this.rewardNum == 1) { return "一"; } if (this.rewardNum == 2) { return "二"; } } } })前端的代码基本就是那样,接下来看看后端实现的核心代码
用户签到,首先要获取签到的日历,处理过去和未来可能签到的奖励
/** * 获取签到日历 * @param $uid int 用户ID * @param $containPast bool 是否包含过去签到奖励 * @return array */public function getCalendars($uid, $containPast=true){ $signIns = $this->fetchPaginate(['return_model'=>1]); $calendars = $this->getCalendarsArray(); // 处理过去已获得的签到奖励 $past = function () use (&$calendars, &$uid) { $thisMonths = $this->log->fetchThisMonths($uid); $thisMonths->load(['extraReward.signIn'=>ToolModel::withSelect(['id','icon', 'reward_rule'])]); foreach ($thisMonths as $item) { $day = $item->day-1; $calendars[$day]['isActive'] = 1; if (isset($item->extraReward)) { $calendars[$day]['icon'] = $item->extraReward->signIn->icon; $calendars[$day]['has_reward'] = 1; $calendars[$day]['log_id'] = $item->id; $calendars[$day]['is_get'] = $item->extraReward->is_get; if ($item->extraReward->is_get == 0) { $calendars[$day]['reward_num'] = count($item->extraReward->signIn->reward_rule); $calendars[$day]['reward_type'] = array_column($item->extraReward->signIn->reward_rule, 'reward_type'); } else { $calendars[$day]['reward_quantity'] = $item->extraReward->reward_quantity; $calendars[$day]['reward_type'] =$item->extraReward->reward_type; $calendars[$day]['reward_type_zh'] = $item->extraReward->reward_type_zh; } } } }; // 处理未来可能有的签到奖励 $future = function () use (&$calendars, &$signIns, &$uid) { if (empty($signIns))return; $user = $this->userSignIn->findByUserId($uid); $signInLen = count($signIns); $monthNum = count($calendars); $toDay = (date('d')-1); // 是否已签到,如果未签到则-1 if ($this->isActive($uid)) { $start = $toDay - $user->keep_sign_in; } else { $start = $toDay - $user->keep_sign_in-1; } while ($start < $monthNum) { for ($i=0; $i<$signInLen; $i++) { $start += $signIns[$i]->keep_sign_in; if ($start >= $monthNum) { return; } if (0 > $start) { continue; } $calendars[$start]['icon'] = $signIns[$i]['icon']; $calendars[$start]['has_reward'] = 1; $calendars[$start]['reward_num'] = count($signIns[$i]->reward_rule); if ($calendars[$start]['is_get'] == 0) { $calendars[$start]['reward_type'] = array_column($signIns[$i]->reward_rule, 'reward_type'); } // 设置今天的签到奖励 if ($start == $toDay) { $this->toDayExtraSignReward = $signIns[$i]; } } } }; if ($containPast) $past(); $future(); return $calendars;}签到成功后,获取奖励,
/** * 获取今天的签到奖励 * @return array */public function getToDayReward($uid){ $log = $this->log->findByToDay($uid); if (empty($log)) return false; $log->load(['defaultReward']); return ['reward_quantity'=> $log->defaultReward->reward_quantity, 'log_id' => $log->id, 'reward_type'=>$log->defaultReward->reward_type, 'reward_type_zh'=>$log->defaultReward->reward_type_zh, ];}添加用户奖励
/** * 添加用户签到奖励 * @param UserSignBaseModel $userSign 用户签到 * @param SignInLogBaseModel $signInLog 用户签到日志 * @param SignBaseModel $defaultReward 用户签到默认奖励 * @param SignBaseModel $extraReward 用户签到额外奖励 */public function store($userSign, $signInLog, $defaultReward, $extraReward = null){ $data = []; // 默认奖品立刻发放 if (isset($defaultReward)) { foreach ($defaultReward->reward_rule as $rule) { $quantity = $this->getRewardQuantity($rule); $data[] = [ 'sign_in_log_id' => $signInLog->id, 'sign_in_id' => $defaultReward->id, 'reward_type' => $rule['reward_type'], 'reward_quantity' => $quantity, 'is_get' => 1, 'type' => 1, 'get_time' => date('Y-m-d H:i:s'), 'max_sign_in' => $userSign->max_sign_in, 'keep_sign_in' => $userSign->keep_sign_in, ]; $this->sendReward($signInLog->user_id, $rule['reward_type'], $quantity, ['signInLog'=>$signInLog]); } } // 额外签到奖品 if (isset($extraReward)) { $data[] = [ 'sign_in_log_id' => $signInLog->id, 'sign_in_id' => $extraReward->id, 'reward_type' => 0, 'reward_quantity' => 0, 'is_get' => 0, 'type' => 2, 'get_time' => null, 'max_sign_in' => $userSign->max_sign_in, 'keep_sign_in' => $userSign->keep_sign_in, ]; } SignInRewardLogBaseModel::insert($data);}获取额外的奖励以及发放奖励,比如今天你是连续签到的7天的,那你除了获取到积分外,还可以获取到系统设置的红包奖励等。
/** * 发放签到奖励 * @param $uid int 用户ID * @param $type int 类型 * @param $quantity float 数量 * @param $extra array 额外参数 */public function sendReward($uid, $type, $quantity, $extra=[]){ $related_id = empty($extra['signInLog']) ? 0 : $extra['signInLog']->id; // 奖励类型(1.积分 2.红包 3.桶装水 4.5100) switch ($type) { case 1: $params = [ 'user_id' => $uid, 'change_quantity' => $quantity, 'related_type' => 25, 'related_id' => $related_id, 'remark' => '签到奖励' ]; Recharge::sendOf("PointsRecharge", $params); break; case 2: $openid = WeixinUserBaseModel::where('user_id', $uid) ->where('weixin_config_id', config('common.weixin_config_id.zmqcenter'))->first(); if (empty($openid)) { $id = config('common.weixin_config_id.zmqcenter'); throw new Exception("无法找OPENID,user_id={$$uid},weixin_config_id={$id}"); } $params = [ 'weixin_config_id' => config('common.weixin_config_id.zmqcenter'), 'amount' => $quantity, 'openid' => $openid->wxid, 'desc' => '签到奖励红包:'.$quantity.'元', 'trade_no'=> 'qiandao'.$related_id.substr(uniqid(time()), 0, 8), ]; Recharge::sendOf("RedEnvelopeRecharge", $params); break; case 3: $params = [ 'user_id' => $uid, 'goods_id' => config('goods.goods_water_id'), 'change_quantity' => $quantity, 'related_type' => 101, 'related_id' => $related_id, ]; Recharge::sendOf("AccumulativeWaterReward", $params); break; case 4: $params = [ 'user_id' => $uid, 'goods_id' => config('goods.goods_5100_water_id'), 'change_quantity' => $quantity, 'related_type' => 101, 'related_id' => $related_id, ]; Recharge::sendOf("AccumulativeWaterReward", $params); break; }}至此,基本所有的核心代码都已贴出,根据需求来实现,主要还是要设计到数据表,这样才能做到事半功倍!
以上是本文的全部内容,希望对大家的学习有帮助,也希望大家多多支持 php自学中心 感谢阅读!
目录
推荐阅读
0 条评论
本站已关闭游客评论,请登录或者注册后再评论吧~