connectUserId != $user_id) { $database = get_db_connect($this->table, $user_id); $this->setTable($database['table']); $this->connect($database); $this->connectUserId = $user_id; } return $this; } public function getTypeList() { return ['1' => __('书币充值'),'2' => __('VIP充值'),'3' => __('系统操作'),'4' => __('系统操作'),'5' => __('签到')]; } public function getEditTypeList() { return ['1' => __('活动奖励'),'2' => __('系统操作')]; } public function getTypeTextAttr($value, $data) { $value = $value ? $value : $data['type']; $list = $this->getTypeList(); return isset($list[$value]) ? $list[$value] : ''; } public function getFreeEndtimeTextAttr($value, $data) { $value = $value ? $value : $data['free_endtime']; return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value; } public function getEditTypeTextAttr($value, $data) { $value = $value ? $value : $data['edit_type']; $list = $this->getEditTypeList(); return isset($list[$value]) ? $list[$value] : ''; } protected function setFreeEndtimeAttr($value) { return $value && !is_numeric($value) ? strtotime($value) : $value; } /** * 可用免费书币查询 结果集按倒序排列 * @param int $id user_id; */ public function getFreeKandian($id){ $res = $this->setConnect($id)->where('user_id',$id)->where('remain_free_kandian','>',0)->where('free_endtime','>',time())->order('free_endtime','desc')->select(); if($res){ $redis = Redis::instance(); $zresult = $redis->zrangebyscore('ZR:' . $id, time(), '+inf'); //得到未过期免费书币记录 $redis->del('ZR:' . $id); if (!empty($zresult)) { foreach ($zresult as $val) { $redis->del($val); } } foreach($res as $key=>$val){ $rData = []; $rData['id'] = $val->id; $rData['remain_free_kandian'] = $val->remain_free_kandian; $rData['free_endtime'] = $val->free_endtime; $redis->setex('UR:'.$id.':'.$val->id,$val->free_endtime,json_encode($rData,JSON_UNESCAPED_UNICODE)); $redis->zadd('ZR:'.$id,$val->free_endtime,'UR:'.$id.':'.$val->id); } $redis->expire('ZR:'.$id,86400*5); return is_array($res)?$res:$res->toArray(); }else{ return false; } } /** * 查询某个人最近的一条有效免费书币记录(返回一维数组) * @param int $id 用户id */ public function getLastFreeRecord($id){ $redis = Redis::instance(); $redisKey = 'ZR:'.$id; if(!$redis->exists($redisKey)){ $res = $this->getFreeKandian($id); $rechargeEnd = empty($res)?null:$res[0]; }else{ $zresult = $redis->zrevrangebyscore($redisKey, '+inf', time(), array('limit' => array(0, 1))); if($zresult){ $strKey = $zresult[0]; $rechargeEnd = $this->getUserFreeKandianFromCache($strKey); }else{ $rechargeEnd = null; } } return $rechargeEnd; } /** * @param int $uid 用户id * 递归减少免费书币 * return [] err 0成功,1失败 kandian:永久书币还需要扣除多少书币 */ public function reduceFreeKandian($uid,$free_kandian,$rid){ $redis = Redis::instance(); $redisKey = 'ZR:'.$uid; if($redis->exists($redisKey)){ $zresult = $redis->zrangebyscore($redisKey, time(),'+inf', array('limit' => array(0, 1))); //得到该扣费的那条记录 if($zresult){ if($redis->get($zresult[0])){ $recharge = $this->getUserFreeKandianFromCache($zresult[0]); }else{ $returnArr = $this->getFreeKandian($uid); if($returnArr){ $this->reduceFreeKandian($uid,$free_kandian,$rid); }else{ return ['err'=>0,'kandian'=>$free_kandian]; } } } }else{ $result = $this->getFreeKandian($uid); if($result){ $recharge = $result[count($result)-1]; }else{ return ['err'=>0,'kandian'=>$free_kandian]; } } if(empty($recharge)){ return ['err'=>0,'kandian'=>$free_kandian]; }else{ $userKey = 'UR:'.$uid.':'.$recharge['id']; if($recharge['remain_free_kandian']>=$free_kandian){ //如果此条记录够扣 $remain = $recharge['remain_free_kandian'] - $free_kandian; $res = $this->setConnect($uid)->update(['remain_free_kandian'=>$remain],['id'=>$recharge['id']]); if($remain>0){ $rData = []; $rData['id'] = $recharge['id']; $rData['remain_free_kandian'] = $remain; $rData['free_endtime'] = $recharge['free_endtime']; $redis->del($userKey); $redis->setex($userKey,$recharge['free_endtime']-time(),json_encode($rData,JSON_UNESCAPED_UNICODE)); }else{ $redis->del($userKey); $redis->zrem($redisKey,$userKey); } if($res){ return ['err'=>0,'kandian'=>0]; }else{ return ['err'=>1]; } }else{ if($recharge['id'] == $rid){ $redis->del($userKey); $redis->zrem($redisKey,$userKey); return ['err'=>0,'kandian'=>$free_kandian-$recharge['remain_free_kandian']]; }else{ $res = $this->setConnect($uid)->update(['remain_free_kandian'=>0],['id'=>$recharge['id']]); if($res){ $redis->del($userKey); $redis->zrem($redisKey,$userKey); return $this->reduceFreeKandian($uid,$free_kandian-$recharge['remain_free_kandian'],$rid); }else{ return ['err'=>1]; } } } } } /** * 得到用户总共的免费书币数 * @param int $uid * @return int */ public function getTotalFreeKandian($uid){ $totalKandian = 0; $redis = Redis::instance(); $redisKey = 'ZR:'.$uid; if($redis->exists($redisKey)) { $zresult = $redis->zrangebyscore($redisKey, time(), '+inf'); //得到未过期免费书币记录 if (!empty($zresult)) { foreach ($zresult as $val) { $data = $this->getUserFreeKandianFromCache($val); $totalKandian += $data['remain_free_kandian']; } } }else{ $result = $this->setConnect($uid)->where('free_endtime','>',time())->where('user_id',$uid)->select(); if($result){ foreach($result as $val){ $json = []; $json['id'] = $val->id; $json['remain_free_kandian'] = $val->remain_free_kandian; $json['free_endtime'] = $val->free_endtime; $redis->zadd($redisKey,$val->free_endtime,'UR:'.$uid.':'.$val->id); $redis->setex('UR:'.$uid.':'.$val->id, $val->free_endtime-time(), json_encode($json,JSON_UNESCAPED_UNICODE)); $totalKandian += $val->remain_free_kandian; } $redis->expire($redisKey,86400*5); } } return $totalKandian; } /** * 处理自增ID * * @param $data */ protected function autoId($data) { if (!isset($data['id'])) { // 获取redis自增id $redisAuto = Redis::instanceAuto(); $newRechargeId = $redisAuto->incr('URID'); //redis自增返回新的recharge_id if (!$newRechargeId) { Log::error('充值记录自增ID获取失败!data:' . json_encode($data)); throw new HttpException(500, '充值记录自增ID获取失败!'); } $data['id'] = $newRechargeId; } return $data; } /** * 插入记录 * @access public * @param mixed $data 数据 * @param boolean $replace 是否replace * @param boolean $getLastInsID 返回自增主键 * @param string $sequence 自增序列名 * @return integer|string */ public function insert(array $data = [], $replace = false, $getLastInsID = false, $sequence = null) { $data = $this->autoId($data); $res = parent::insert($data, $replace, false, $sequence); if ($res) { $this->lastId = $data['id']; if ($getLastInsID) { return $this->lastId; } } return $res; } /** * 插入记录并获取自增ID * @access public * @param mixed $data 数据 * @param boolean $replace 是否replace * @param string $sequence 自增序列名 * @return integer|string */ public function insertGetId(array $data, $replace = false, $sequence = null) { $data = $this->autoId($data); if (parent::insert($data, $replace, false, $sequence)) { $this->lastId = $data['id']; return $this->lastId; } else { return 0; } } /** * 获取最近插入的ID * @access public * @param string $sequence 自增序列名 * @return string */ public function getLastInsID($sequence = null) { return $this->lastId; } public function getVipStartTime($userid) { $result = $this->setConnect($userid) ->where('user_id',$userid) ->whereIn('type',UserConstants::CHANNEL_VIP_TYPE) ->order('id','desc') ->limit(0,1) ->find(); if($result){ // 如果存在记录 $data = $result->data; $vipTime = intval($data['day']) * 86400 + intval($data['hour']) * 60 * 60; if(($data['vip_starttime'] + $vipTime) > time()){ $vip_starttime = $data['vip_starttime'] + $vipTime; } else{ $vip_starttime = time(); } }else{ $vip_starttime = time(); } return $vip_starttime; } /** * 获取充值缓存 * @param $cacheKey * @return array|false|mixed|\PDOStatement|string|Model */ public function getUserFreeKandianFromCache($cacheKey) { $data = Redis::instance()->get($cacheKey); if (!$data) { $cacheParam = explode(':', $cacheKey); $userId = $cacheParam[1]; $rechargeId = $cacheParam[2]; $recharge = $this->setConnect($userId)->where('id', $rechargeId)->find(); $json = []; $json['id'] = $recharge->id; $json['remain_free_kandian'] = $recharge->remain_free_kandian; $json['free_endtime'] = $recharge->free_endtime; Redis::instance()->zadd('ZR:' . $userId, $recharge->free_endtime, 'UR:' . $userId . ':' . $recharge->id); Redis::instance()->setex('UR:' . $userId . ':' . $recharge->id, $recharge->free_endtime - time(), json_encode($json, JSON_UNESCAPED_UNICODE)); } else { $recharge = json_decode($data, true); } return $recharge; } /** * 获取 渠道商vip_starttime * @param $userid * @return float|int */ public function getChannelVipStartTime($userid) { $result = $this->setConnect($userid) ->where('user_id',$userid) ->where('dd', '=', '0') ->whereIn('type',UserConstants::CHANNEL_VIP_TYPE) ->order('id','desc') ->limit(0,1) ->find(); if($result){ // 如果存在记录 $data = $result->data; $vipTime = intval($data['day']) * 86400 + intval($data['hour']) * 60 * 60; if(($data['channel_vip_starttime'] + $vipTime) > time()){ $vip_starttime = $data['channel_vip_starttime'] + $vipTime; } else{ $vip_starttime = time(); } }else{ $vip_starttime = time(); } return $vip_starttime; } }