<?php /** * 【积分抽奖-手机端】立即抽奖 * * @author: heyuelong * @date: 2018年3月26日11:18:11 */ namespace Api\Controller\Activity; use Common\Common\Constant; use Common\Common\Integral; use Common\Service\ActivityService; use Common\Service\PrizeService; use Common\Service\RecordService; use Common\Service\RightService; use Think\Log; use VcySDK\Config; use VcySDK\Service; class DrawController extends \Api\Controller\AbstractController { /** @var ActivityService */ protected $_activity_service; /** @var RightService */ protected $_right_service; /** @var PrizeService */ protected $_prize_service; /** @var RecordService */ protected $_record_service; public function before_action($action = '') { if (!parent::before_action($action)) { return false; } // 实例化活动 $this->_activity_service = new ActivityService(); // 实例化权限表 $this->_right_service = new RightService(); // 实例化商品表 $this->_prize_service = new PrizeService(); // 实例抽奖记录表 $this->_record_service = new RecordService(); return true; } /** * @return bool */ public function Index_get() { $ac_id = I('get.ac_id', 0); // 验证 $info = $this->validator($ac_id); $prize_info = $this->get_draw_good_info($ac_id); // 初始化记录信息 $data = [ 'ac_id' => $ac_id, 'lp_id' => $prize_info['lp_id'], 'lp_name' => $prize_info['name'], 'is_prize' => $prize_info['is_prize'], 'cover_id' => $prize_info['cover_id'], 'uid' => $this->uid, 'username' => $this->_login->user['memUsername'], 'dp_name' => implode(',', array_column($this->_login->user['dpName'], 'dpName')), 'job' => strval($this->_login->user['memJob']), 'role' => strval($this->_login->user['memRole']), 'mobile' => strval($this->_login->user['memMobile']) ]; try { $this->_record_service->start_trans(); $lr_id = $this->_record_service->insert($data); $uid_list = $this->_record_service->list_by_conds(['ac_id' => $ac_id], null, [], 'uid'); $uids = array_unique(array_column($uid_list, 'uid')); // 查询中奖次数 $won_total = $this->_record_service->count_by_conds(['ac_id' => $ac_id, 'is_prize' => Constant::HAVE_PRIZE]); // 如果已中奖且库存大于0则更新库存 if (Constant::HAVE_PRIZE == $prize_info['is_prize'] && $prize_info['stock_num'] > 0) { // 更新库存 $prize_total = $this->_prize_service->update_by_conds(['lp_id' => $prize_info['lp_id']], ['stock_num=stock_num - ?' => 1]); if (!$prize_total) { $this->_record_service->rollback(); E('_ERR_ACTIVITY_LOTTERY'); return false; } } // 更新已参与人数 $update_total = $this->_activity_service->update($ac_id, [ 'join_people' => count($uids), 'already_num' => count($uid_list), 'won_num' => $won_total, ]); if (!$update_total || !$lr_id) { $this->_record_service->rollback(); E('_ERR_ACTIVITY_LOTTERY'); return false; } $this->_record_service->commit(); } catch (\Exception $e) { \Think\Log::record($e); $this->_record_service->rollback(); E('_ERR_ACTIVITY_LOTTERY'); return false; } $change_params = [ // 用户id 'memUid' => $this->uid, // 积分类型 (默认mi_type0) 'miType' => 'mi_type0', // 积分策略key,integral不为空时,传业务自己的积分规则key 'irKey' => 'lottery', // 积分变更说明 'remark' => '积分抽奖-' . $info['title'], // 变更的积分值 'integral' => !empty($info['integral']) ? -intval($info['integral']) : 0, // 应用标识(消息推送必要) 'msgIdentifier' => Config::instance()->pluginIdentifier, 'businessKey' => 'integral_center', 'businessAct' => 'lottery', ]; try { $result = Integral::instance()->asynUpdateIntegral($change_params); } catch (\Exception $e) { Log::record('trigger integral strategy fail: ' . $e->getMessage(), Log::ERR); } // 获取当前用户积分 $sdk = new \VcySDK\Integral(Service::instance()); $integral_info = $sdk->detail(['memUid' => $this->uid]); // 格式化详情数据 $this->_result = [ 'available' => $integral_info['available'], 'lr_id' => $lr_id, 'lp_id' => $prize_info['lp_id'], 'name' => $prize_info['name'], 'is_prize' => $prize_info['is_prize'], 'img_url' => imgUrl($prize_info['cover_id']) ]; return true; } /** * 获取抽中的奖品详情 * @param int $ac_id 活动ID * @return mixed */ protected function get_draw_good_info($ac_id = 0) { // 需要查询的字段 $fields = 'lp_id,name,cover_id,num,percent,lottery_max,lottery_min,is_prize,stock_num'; // 获取奖品列表 $prize_list = $this->_prize_service->get_prize_list(['ac_id' => $ac_id], $fields); $prize_list = array_combine_by_key($prize_list, 'lp_id'); // 奖品数组 $data = []; $argc = 0; // 不是中奖奖品的IDS集合 $ids = []; foreach ($prize_list as $v) { // 如果是有库存的中奖奖品且有概率 if ($v['stock_num'] > 0 && Constant::HAVE_PRIZE == $v['is_prize'] && $v['percent']) { $max = $argc + $v['percent'] * 100; $data[$v['lp_id']] = [ 'min' => $argc + 1, 'max' => $max, ]; $argc = $max; } else if (Constant::NO_PRIZE == $v['is_prize']) { $ids[] = $v['lp_id']; } } // 奖品记录ID $prize_id = 0; $num = rand(1, 10000); foreach ($data as $key => $item) { if ($num >= $item['min'] && $num <= $item['max']) { $prize_id = $key; break; } } if (!empty($prize_id)) { // 奖品详情 $prize_info = $this->_prize_service->get($prize_id); // 获取当前用户已抽中该奖项次数 $total = $this->_record_service->count_by_conds(['ac_id' => $ac_id, 'uid' => $this->uid, 'lp_id' => $prize_id]); // 获取此活动总的抽奖次数 $lottery_total = $this->_record_service->count_by_conds(['ac_id' => $ac_id]); // 如果超过该奖品的最大中奖次数则设置为不中奖 || 小于最小抽奖次数抽中该奖品则设置为不中奖 || 没有奖品了则显示未中奖 if ((!empty($prize_info['lottery_max']) && $prize_info['lottery_max'] <= $total) || (!empty($prize_info['lottery_min']) && $prize_info['lottery_min'] > $lottery_total) || ($prize_info['stock_num'] == 0) ) { $prize_key = array_rand($ids, 1); $prize_id = $ids[$prize_key]; } } else { $prize_key = array_rand($ids, 1); $prize_id = $ids[$prize_key]; } return $prize_list[$prize_id]; } /** * 活动抽奖验证 * @param int $ac_id 活动ID * @return mixed */ protected function validator($ac_id = 0) { if (empty($ac_id)) { // 验证参数 E('_EMPTY_ACTIVITY_ID'); } // 获取活动详细内容 $info = $this->_activity_service->get_by_conds( [ 'ac_id' => $ac_id, 'activity_status > ?' => 0 ] ); if (empty($info)) { // 数据不存在时抛错 E('_ERR_DATA_NOT_EXIST'); } // 如果不是全公司 if (Constant::IS_ALL_FALSE == $info['is_all']) { // 获取用户权限ID $ids = $this->_right_service->getUserRight($this->_login->user); sort($ids); // 统计用户是否有权限 $total = $this->_right_service->count_by_conds(['ac_id' => $ac_id, 'obj_id' => $ids]); // 如果没有权限 if (empty($total)) { E('_ERR_ACTIVITY_NOT_AUTH'); } } // 活动状态 $status = $this->_prize_service->activity_status($info['activity_status'], $info['start_time'], $info['end_time']); // 活动未开始不能抽奖 if (Constant::STATUS_NOT_START == $status) { E('_ERR_ACTIVITY_STATUS_NOT_START'); } // 活动已结束不能抽奖 if (Constant::STATUS_END == $status) { E('_ERR_ACTIVITY_STATUS_END'); } // 活动已终止不能抽奖 if (Constant::STATUS_STOP == $status) { E('_ERR_ACTIVITY_STATUS_STOP'); } // 获取当前用户积分 $sdk = new \VcySDK\Integral(Service::instance()); $integral_info = $sdk->detail(['memUid' => $this->uid]); // 如果积分不足则不能抽奖 if ($info['integral'] > $integral_info['available']) { E('_ERR_LACK_OF_INTEGRAL'); } if (Constant::DAY_LOTTERY_TYPE == $info['limit_type'] && $info['num_limit'] > 0) { // 每天限制抽奖类型 $start_time = rstrtotime(rgmdate((string)NOW_TIME, 'Y-m-d 0:0:0'), 1); $end_time = rstrtotime(rgmdate((string)NOW_TIME, 'Y-m-d 23:59:59'), 1); $conds = [ 'ac_id' => $ac_id, 'created >=?' => $start_time, 'created <=?' => $end_time, 'uid' => $this->uid ]; $total = $this->_record_service->count_by_conds($conds); if ($total >= $info['num_limit']) { E('当天抽奖次数已用完(' . $info['num_limit'] . '次),请明天继续参与!', '4201001'); } } else if (Constant::TOTAL_LOTTERY_TYPE == $info['limit_type'] && $info['num_limit'] > 0) { // 总体限制抽奖类型 $total = $this->_record_service->count_by_conds(['ac_id' => $ac_id, 'uid' => $this->uid]); if ($total >= $info['num_limit']) { E('该活动抽奖次数已用完(' . $info['num_limit'] . '次),无法继续参与抽奖!', '4201002'); } } return $info; } }