CampaignService.php 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. <?php
  2. namespace app\common\service;
  3. use app\common\library\Redis;
  4. use app\common\model\CampaignMatch;
  5. use app\main\constants\PayConstants;
  6. use app\main\constants\CampaignConstants;
  7. use app\main\service\FinancialService;
  8. use app\main\service\UserDdFlushService;
  9. use app\main\service\UserService;
  10. use app\common\model\CampaignUserMatch;
  11. use app\main\service\MyScene;
  12. use think\Collection;
  13. use think\Config;
  14. use think\Cookie;
  15. use think\Log;
  16. use think\Request;
  17. use think\Db;
  18. use think\Cache;
  19. /**
  20. * Class CampaignService
  21. * @package app\common\service
  22. * wudd
  23. * 消耗活动 作废 迁移到 recharge
  24. * 20191029
  25. */
  26. class CampaignService
  27. {
  28. public static $self;
  29. /**
  30. * @return CampaignService
  31. */
  32. public static function instance()
  33. {
  34. if(self::$self == NULL){
  35. self::$self = new self();
  36. }
  37. return self::$self;
  38. }
  39. public function getCampaignReadModel()
  40. {
  41. return model('CampaignRead');
  42. }
  43. public function getCampaignMatchModel()
  44. {
  45. return model('CampaignMatch');
  46. }
  47. public function getUserMatchModel( $userId ){
  48. return model('CampaignUserMatch')->setConnect($userId);
  49. }
  50. public function getCampaignConsumeModel( $userId ){
  51. return model('CampaignConsume')->setConnect($userId);
  52. }
  53. /**
  54. * 记录当天打卡人数
  55. * @param $kandian
  56. */
  57. public function setSignNumToday( $matchId ){
  58. $rediskey = CampaignConstants::getMatchSignNumToday($matchId);
  59. $num = Redis::instance()->incr($rediskey);
  60. if ($num == 1){
  61. Redis::instance()->expire($rediskey, 3600*24);
  62. }
  63. return $num;
  64. }
  65. /**
  66. * 获取一个场次
  67. * wud
  68. */
  69. public function getMatchByTime( $matchDate, $kandian=50 ){
  70. $redisKey = CampaignConstants::getCampaignMatchRedisKey($matchDate,$kandian);
  71. $campaign = Redis::instance()->hGetAll($redisKey);//'active_id'=>$active
  72. if ( $campaign==false ){
  73. $campaign = $this->getCampaignMatchModel()
  74. ->where(['match_date'=>$matchDate,'kandian'=>$kandian])
  75. ->find();
  76. if ( !empty($campaign) ){
  77. $campaign = is_array($campaign) ? $campaign : $campaign->toArray();
  78. Redis::instance()->hmSet($redisKey, $campaign );
  79. Redis::instance()->expire($redisKey,3600*24);
  80. }
  81. }
  82. return $campaign;
  83. }
  84. /**
  85. * wudd
  86. * 报名成功更新活动场次表人数
  87. */
  88. public function updateMatchById( $matchId, $matchDate, $kandian=50 ){
  89. $redisKey = CampaignConstants::getCampaignMatchRedisKey($matchDate,$kandian);
  90. $update = [
  91. 'participator_num'=>['exp','participator_num+1'],
  92. ];
  93. $res = $this->getCampaignMatchModel()
  94. ->where(['id'=>$matchId])
  95. ->update($update);
  96. if ( $res && Redis::instance()->exists($redisKey) ){
  97. Redis::instance()->HINCRBY( $redisKey, 'participator_num', 1 );
  98. }
  99. return $res;
  100. }
  101. /**
  102. * 获取用户打卡记录
  103. */
  104. public function getUserMatch( $userId, $toDb=false ){
  105. $redisKey = CampaignConstants::getUserMatchKey($userId);
  106. if ( !$toDb ){
  107. $userMatch = Redis::instance()->hGetAll( $redisKey );
  108. if ( empty($userMatch) ){
  109. $toDb = true;
  110. }
  111. }
  112. if ( $toDb ){
  113. $userMatch = $this->getUserMatchModel($userId)
  114. ->where(['user_id'=>$userId])
  115. ->order('id desc')
  116. ->find();
  117. if (empty($userMatch)){
  118. $userMatch['noSign'] = 1;
  119. }else{
  120. $userMatch = $userMatch->toArray();
  121. }
  122. Redis::instance()->hmSet( $redisKey,$userMatch);
  123. Redis::instance()->expire($redisKey,3600*24);
  124. }
  125. if ( count($userMatch) < 2 ){
  126. $userMatch = [];
  127. }
  128. return $userMatch;
  129. }
  130. /**
  131. * @param $userId
  132. * @param $id
  133. * @param $status
  134. */
  135. public function updateUserMatch( $userId, $id, $status ){
  136. $this->getUserMatchModel($userId)->where(['id'=>$id])
  137. ->update(['status'=>$status,'updatetime'=>time()] );
  138. Redis::instance()->del(CampaignConstants::getUserMatchKey($userId));
  139. }
  140. /**
  141. * test
  142. */
  143. public function updateUserMatchTest( $args ){
  144. $update = [];
  145. if ( $args['status'] ){
  146. $update['status'] = $args['status'];
  147. }
  148. if ( $args['num'] ){
  149. $update['num'] = $args['num'];
  150. }
  151. if ( $args['is_again'] ){
  152. $update['is_again'] = $args['is_again'];
  153. }
  154. if ( $args['match_date'] ){
  155. $update['match_date'] = $args['match_date'];
  156. $update['updatetime'] = strtotime($args['match_date']);
  157. }
  158. if ( $args['match_id'] ){
  159. $update['match_id'] = $args['match_id'];
  160. }
  161. if ( $args['kandian'] ){
  162. $update['kandian'] = $args['kandian'];
  163. }
  164. $res = $this->getUserMatchModel($args['user_id'])->where(['id'=>$args['id']])
  165. ->update($update);
  166. Redis::instance()->del(CampaignConstants::getUserMatchKey($args['user_id']));
  167. Redis::instance()->del(CampaignConstants::getCampaignMatchRedisKey($args['match_date'],$args['kandian']));
  168. return $res;
  169. }
  170. /**
  171. *充值完成后自动报名
  172. */
  173. public function autoCheckIn( $userInfo, $matchInfo ){
  174. if ( !empty($matchInfo['campaign']) ){
  175. $args['nickname'] = $userInfo['nickname'];
  176. $args['avatar'] = $userInfo['avatar'];
  177. $args['openid'] = $userInfo['openid'];
  178. $args['channel_id'] = $userInfo['channel_id'];
  179. $args['kandian'] = $matchInfo['campaign']['kandian'];
  180. $args['matchDate'] = $matchInfo['campaign']['match_date'];
  181. try{
  182. $res = $this->checkIn( $userInfo['id'], $args );
  183. if ( $res['code'] != 200 ){
  184. LogService::info('autoCheckInError002'.json_encode($res));
  185. }else{
  186. Redis::instance()->set(CampaignConstants::getUserMatchFirstLogin($userInfo['id']),1,3600*4);//进入报名页弹窗标识
  187. LogService::info('autoCheckInSuccess');
  188. }
  189. }catch ( \Throwable $th ){
  190. LogService::info( 'autoCheckInError001'.$th->getMessage());
  191. }
  192. }else{
  193. LogService::info('autoCheckInError003'.json_encode($matchInfo).json_encode($userInfo));
  194. }
  195. return;
  196. }
  197. /**
  198. * @param $userId
  199. * @param $args
  200. * @return array
  201. * 报名 wud
  202. */
  203. public function checkIn( $userId, $args ){
  204. $res = ['code'=>201,'msg'=>'报名失败','return'=>[]];
  205. $match = $this->getMatchByTime($args['matchDate'], $args['kandian']);
  206. if ( !empty($match) && $match['match_date'] == date('Ymd',time() )){
  207. $userMatch = $this->getUserMatch( $userId );
  208. $active = $this->getCampaignById($match['campaign_id']);
  209. if ( empty($userMatch) || $userMatch['match_date'] != $match['match_date'] ){
  210. // 报名前刷新remainkandian
  211. LogService::info('autoCheckIn1'.json_encode($userMatch));
  212. UserDdFlushService::instance()->checkUserFlushState($userId);
  213. $insert = [
  214. 'active_id'=>$match['campaign_id'],
  215. 'user_id'=>$userId,
  216. 'match_id'=> $match['id'],
  217. 'match_date'=>$match['match_date'],
  218. 'period'=>$match['period'],
  219. 'kandian'=>$match['kandian'],
  220. 'openid'=>$args['openid'],
  221. 'channel_id'=>$args['channel_id'],
  222. 'endtime'=>time()+3600*24*10,
  223. 'num'=>0,
  224. 'status'=>1,
  225. 'updatetime'=>time(),
  226. 'createtime'=>time()
  227. ];
  228. //扣除书币
  229. $match['realKandian'] = $match['kandian'];
  230. $match['activeName'] = $active['name'];
  231. $isPay = FinancialService::instance()->reduceKandianCampaign( $userId, $match);
  232. if ( $isPay->code == 0 ){
  233. //更新场次人数
  234. $this->updateMatchById( $match['id'],$args['matchDate'], $args['kandian'] );
  235. //新增用户报名记录
  236. $isInsert = $this->getUserMatchModel($userId)->insert($insert);
  237. //插入报名弹幕 集合
  238. $this->insertBarrage($args['nickname'],$args['avatar'],$args['kandian']);
  239. //新增失败返回书币
  240. if ( !$isInsert ){
  241. //退回书币
  242. FinancialService::instance()->modifyUserKandian( $userId, 1, 3,$match['kandian']);
  243. return $res;
  244. }
  245. //删除 用户报名信息的缓存
  246. Redis::instance()->del(CampaignConstants::getUserMatchKey($userId));
  247. $res=['code'=>200, 'msg'=>'报名成功','return'=>[
  248. 'kandian'=>$args['kandian'],
  249. 'matchDate'=>$args['matchDate'],
  250. 'readNumber'=>$active['read_number'],
  251. ]];
  252. return $res;
  253. }
  254. LogService::info('activeMatcherror'.json_encode($isPay));
  255. $res['return'] = json_encode($isPay);
  256. return $res;
  257. }else{
  258. LogService::info('autoCheckIn'.json_encode($userMatch));
  259. $res['msg'] = '您已经报名成功,请刷新页面';
  260. }
  261. }
  262. return $res;
  263. }
  264. /**
  265. * wud 领奖
  266. * @param $userId
  267. * @param $matchId
  268. * @return array
  269. * @throws \think\Exception
  270. * @throws \think\exception\PDOException
  271. */
  272. public function getReward( $userId, $args ){
  273. $res = ['code'=>201,'msg'=>'奖励未发放,请稍后'];
  274. $match = $this->getMatchByTime($args['matchDate'], $args['kandian']);
  275. if ( !empty($match) ){
  276. //查看挑战是否完成
  277. $data = $this->getUserMatch( $userId );
  278. if ( !empty($data) && $data['match_date']==$match['match_date'] && $data['status'] == 3 ){
  279. $days = intval( ( time()-strtotime($data['match_date']) )/(3600*24) );
  280. if ( $days == 0 ){
  281. $res['msg'] = '奖励明日发放';
  282. return $res;
  283. }
  284. if ( $days-$match['period'] > CampaignConstants::CAMPAIGN_PERIOD_DAY){// 领奖超时 为失败
  285. $res['msg'] = '超过领奖时间';
  286. $this->updateUserMatch($userId,$data['id'],5);
  287. return $res;
  288. }
  289. //查看奖励是否发放 打卡完成后的2天 0点1分 计算 ,计算规则 $this->getAward
  290. if ( $match['award'] == false ){
  291. $res['msg'] = '系统正在计算,请稍后';
  292. return $res;
  293. }
  294. //计算奖励
  295. //$reward = $match['success_num'] ? ( $match['participator_num'] * $match['kandian'] + $match['subsidy_need'] )/$match['success_num'] : 0;
  296. //更新 场次表和打卡日志表
  297. $this->getCampaignMatchModel()->where(['id'=>$match['id']])->update(['award_amount'=>['exp','award_amount+'.$match['award']]]);
  298. $success = $this->getUserMatchModel($userId)
  299. ->where(['id'=>$data['id']])
  300. ->update(['status'=>4, 'reward'=>$match['award'],'updatetime'=>time()] );
  301. //删除用户打卡日志缓存 更新场次缓存
  302. Redis::instance()->del(CampaignConstants::getUserMatchKey($userId));
  303. $this->updateMatchById( $match['id'], $args['matchDate'], $args['kandian'] );
  304. if ( $success ){
  305. //增加书币
  306. FinancialService::instance()->modifyUserKandian( $userId, 1, 1,0,$match['award'],'活动赠送书币',2);
  307. $res['code'] = 200;
  308. $res['data'] = $match['award'];
  309. $res['msg'] = '领取成功';
  310. return $res;
  311. }
  312. }
  313. $res['msg'] = '操作异常';
  314. return $res;
  315. }
  316. return $res;
  317. }
  318. /**
  319. * @return mixed
  320. * 用户第一次进入页面 标记 n
  321. */
  322. public function setUserMatchFirstLogin($userId){
  323. $key = CampaignConstants::getUserMatchFirstLogin($userId);
  324. if( Redis::instance()->setnx($key,1) ){
  325. Redis::instance()->expire($key,3600);
  326. return true;
  327. }
  328. return false;
  329. }
  330. /**
  331. * 我的挑战记录
  332. */
  333. public function getUserRecharge( $userId ){
  334. // $data = Cache::get('LIST'.$userId);
  335. // if( $data == false ){
  336. $data = $this->getUserMatchModel($userId)->where(['user_id'=>$userId])->order(['id desc'])->select();
  337. Cache::set('LIST'.$userId,$data,60);
  338. // }
  339. return $data;
  340. }
  341. /**
  342. * 活动信息
  343. * wudd
  344. */
  345. public function getActivityById( $activeId, $toDb=false ){
  346. $redisKey = CampaignConstants::getCampaignRedisKey($activeId);
  347. if ( !$toDb ){
  348. $activiy = Redis::instance()->hGetAll($redisKey);
  349. $toDb = empty($activiy) ? true : false;
  350. }
  351. if ( $toDb ){
  352. $activiy = $this->getCampaignReadModel()
  353. ->where([
  354. 'id'=>$activeId
  355. ])
  356. ->find();
  357. $activiy = is_array($activiy) ? $activiy : $activiy->toArray();
  358. redis::instance()->hmSet($redisKey, $activiy);
  359. Redis::instance()->expire($redisKey,3600*24);
  360. }
  361. return $activiy;
  362. }
  363. /**
  364. * wudd
  365. * 批量获取场次数据
  366. */
  367. public function getMatchBatch( $matchLevel, $dates ){
  368. $campaignRedis = [];
  369. foreach ($matchLevel as $kandian) {
  370. foreach ( $dates as $date ){
  371. $campaignRedis[] = $this->getMatchByTime($date, $kandian);
  372. }
  373. }
  374. return $campaignRedis;
  375. // $campaign = $pipe->exec();
  376. // $isExists = [];
  377. // $campaignRedis = [];
  378. // if( !empty($campaign) )foreach ($campaign as $k =>$v){
  379. // if (!empty($v)){
  380. // $isExists[] = $v['id'];
  381. // $campaignRedis[] = $v;
  382. // }
  383. // }
  384. // if ( count($isExists) < count($matchLevel) ){
  385. // $isExists[] = -1;
  386. // $campaignDb = $this->getCampaignMatchModel()
  387. // ->where(['id'=>['not in', $isExists], 'match_date'=>['in', $dates]])
  388. // ->select();
  389. // if ( $campaignDb ){
  390. // $pipe = Redis::instance()->multi(\Redis::PIPELINE);
  391. // foreach ($campaignDb as $vv) {
  392. // if ( is_object($vv) ){
  393. // $vv = $vv->toArray();
  394. // }
  395. // $campaignRedis[] = $vv;
  396. // $pipe->hMSet(CampaignConstants::getCampaignMatchRedisKey( $vv['match_date'],$vv['kandian'] ), $vv);
  397. // $pipe->expire(CampaignConstants::getCampaignMatchRedisKey( $vv['match_date'],$vv['kandian'] ), 3600*24);
  398. // }
  399. // $pipe->exec();
  400. // }
  401. // }
  402. // unset($campaignDb);
  403. // unset($campaign);
  404. // return $campaignRedis;
  405. }
  406. /**
  407. * 计算奖励
  408. */
  409. public function awardInit( $date = 0 ){
  410. $awardDay = CampaignConstants::CAMPAIGN_PERIOD_DAY;
  411. if ( !$date ){
  412. $date = date( 'Ymd', time()-3600*24*(7+$awardDay) );
  413. }
  414. $data = $this->getCampaignMatchModel()->where([
  415. 'match_date' => $date,
  416. ])->select();
  417. if ( !empty($data) ){
  418. $activeId = $data[0]->campaign_id;
  419. $active = $this->getActivityById($activeId);
  420. //每个场次的基数
  421. $baseNum =$active['elementary_num']*$active['elementary_need']+$active['intermediate_num']*$active['intermediate_need']+$active['advanced_num']*$active['advanced_need'];
  422. //实际报名和成功的人数
  423. $signNum = 0;
  424. $successNum = 0;
  425. foreach ($data as $k =>$v){
  426. $signNum += $v['kandian']*$v['participator_num'];
  427. $successNum += $v['kandian']*$v['success_num'];
  428. }
  429. //官方补贴+基数+实际报名人数
  430. $signNum += $baseNum+$active['subsidy_need'];
  431. //基数+实际成功的人数
  432. $successNum += $baseNum;
  433. //升值倍数
  434. $awardPercent = !empty($successNum) ?round($signNum/$successNum,2) : 1;
  435. foreach ($data as $k=>$v) {
  436. $update[$k]['id'] = $v['id'];
  437. $update[$k]['award'] = intval($v['kandian']*$awardPercent);
  438. }
  439. $this->getCampaignMatchModel()->isUpdate()->saveAll($update);
  440. }
  441. return;
  442. }
  443. /**
  444. * 弹幕
  445. * @param $matchLevel
  446. * @return array
  447. */
  448. public function getBarrage10( $matchLevel ){
  449. $key = CampaignConstants::MATCH_SIGN_USER_INFO;
  450. $data = Cache::get($key);
  451. if ( $data == false ){
  452. $data = [
  453. 'name'=>[],
  454. 'avatar'=>[]
  455. ];
  456. $nameInit = ['果果吧','我本善良','Bear.zheng','书友','幸福','可乐要加冰块','金芳','有些梦,忘了追','杨洪旭'];
  457. $len = Redis::instance()->sCard(CampaignConstants::MATCH_SIGN_USER_INFO);
  458. if ( $len >= 20 ){
  459. $res = Redis::instance()->spop($key, 10);
  460. }else{
  461. $res = Redis::instance()->SRANDMEMBER($key, 10);
  462. }
  463. if ( !empty($res) ){
  464. foreach ( $res as $k=>$v ){
  465. $res[$k] = json_decode( $v );
  466. }
  467. $data['name'] = array_column($res, 'name');
  468. $data['avatar'] = array_column( $res, 'avatar');
  469. }
  470. unset($res);
  471. //不够十个填充
  472. $diff = 10 - count($data['name']);
  473. while ( $diff ){
  474. $data['name'][] = array_pop($nameInit).'参加了'.$matchLevel[rand(0,2)].'看点挑战赛';
  475. $data['avatar'][] ="/assets/img/frontend/campaign/default_people.png";
  476. $diff--;
  477. }
  478. Cache::set( $key, $data, 6 );
  479. }
  480. return $data;
  481. }
  482. /**
  483. * @param $nickname
  484. * @param $avatar
  485. * @param $kandian
  486. * 插入弹幕 集合
  487. */
  488. private function insertBarrage( $nickname, $avatar, $kandian ){
  489. $data['name'] = $nickname.' 报名了'.$kandian.'书币挑战赛';
  490. $data['avatar'] = $avatar;
  491. if ( Redis::instance()->scard(CampaignConstants::MATCH_SIGN_USER_INFO) < 20 ){
  492. Redis::instance()->sadd(CampaignConstants::MATCH_SIGN_USER_INFO, json_encode( $data ) );
  493. }
  494. return;
  495. }
  496. /**
  497. * @param $userId
  498. * @return array
  499. */
  500. public function getActiveByUser( $userId ){
  501. //检查活动是否开启
  502. $isOpen = $this->checkCampaignOpen();
  503. if ($isOpen != 1){
  504. return [];
  505. }
  506. $userMatch = $this->getUserMatch( $userId );
  507. $res = [];
  508. if ( !empty ($userMatch) && isset($userMatch['active_id']) ){
  509. $res = $this->getActivityById( $userMatch['active_id'] );
  510. }
  511. return $res;
  512. }
  513. /**
  514. * 计算本期的报名人数 总奖池 和预期奖励
  515. * 奖励=奖励系数*报名书币
  516. * 奖励系数=官方补贴+初级报名人数*初级书币+中级报名人数*中级书币+高级报名人数*高级书币/(初级完成人数*初级书币+中级完成人数*中级书币+高级完成人数*高级书币)
  517. */
  518. public function getAward( $dateMatch, $active){
  519. //报名人数基数
  520. $signNum = $active['base_number'];
  521. //基础奖励
  522. $awardNum =$active['elementary_num']*$active['elementary_need']+$active['intermediate_num']*$active['intermediate_need']+$active['advanced_num']*$active['advanced_need'];
  523. foreach ($dateMatch as $k =>$v){
  524. $signNum+=$v['participator_num'];
  525. $awardNum +=$v['kandian']*$v['participator_num'];
  526. }
  527. $totalAward = $awardNum+$active['subsidy_need'];
  528. $awardPercent = !empty($awardNum) ?round($totalAward/$awardNum,2) : 1;
  529. $res = [
  530. 'signNum'=>$signNum,
  531. 'totalAward'=>$totalAward,
  532. 'awardPercent'=>$awardPercent
  533. ];
  534. return $res;
  535. }
  536. /**
  537. * 获取最近一次结束得场次
  538. */
  539. public function lastTimeMatch()
  540. {
  541. $key = CampaignConstants::getLastAwardMatch();
  542. $res = Redis::instance()->hGetAll($key);
  543. if ( empty($res) ){
  544. $data = $this->getCampaignMatchModel()->where('award','>', 0)->order('id desc')->limit(3)->select();
  545. if ( empty($data) ){
  546. $res['nodata'] = 1;
  547. }else{
  548. foreach($data as $k =>$v ){
  549. $res[$v['kandian']] = $v['award'];
  550. }
  551. }
  552. Redis::instance()->hMSet($key, $res);
  553. Redis::instance()->expire($key, 3600*23);
  554. }
  555. if ( isset($res['nodata']) ){
  556. $res = [];
  557. }
  558. return $res;
  559. }
  560. /**
  561. * 充值后 如果没有参加活动 发推送
  562. */
  563. public function checkActive($userId){
  564. //检查活动是否开启
  565. $isOpen = $this->checkCampaignOpen();
  566. if ($isOpen != 1){
  567. return 0;
  568. }
  569. $res = $this->getUserMatch($userId);
  570. if ( empty($res) ){
  571. $res = $this->getLatestReadInfo();
  572. if ( !empty($res) ){
  573. return $res['id'];//有进行得活动进行推送
  574. }
  575. }
  576. return 0;
  577. }
  578. /**
  579. * 查看消耗活动是否开启 :1 开启 2 是关闭
  580. * @return int
  581. */
  582. public function checkCampaignOpen()
  583. {
  584. $redisKey = CampaignConstants::CAMPAIGN_IS_OPEN;
  585. $isOpen = Redis::instance()->get($redisKey);
  586. if ( !$isOpen ){
  587. $lastDate = model('CampaignMatch')->field('match_date,period')->order('id desc')->limit(1)->find();
  588. if ( !empty($lastDate) && isset($lastDate->match_date) ){
  589. //判断最后一个场次 是不是已经结束
  590. $day = ( time()-date($lastDate->match_date) )/(3600*24);
  591. $day-=$lastDate->period;
  592. if( ($day-$lastDate->match_date) > 4 ){
  593. $lastDate = [];
  594. }
  595. }
  596. $isOpen = empty($lastDate) ? 2 : 1;
  597. Redis::instance()->set($redisKey,$isOpen,3600*24);
  598. }
  599. return (int)$isOpen;
  600. }
  601. /**
  602. * 维护活动场次数据
  603. * @param $campaign_id
  604. * @param $campaign_data
  605. */
  606. public function maintainMacth($campaign_id, $campaign_data)
  607. {
  608. $start_time = strtotime($campaign_data['start_time']);
  609. $end_time = strtotime($campaign_data['end_time']);
  610. if($end_time >= $start_time) {
  611. for ($i = 0; ($start_time + $i * 86400) <= $end_time; $i++) {
  612. $match_date = date('Ymd', $start_time + $i * 86400);
  613. $mdata_elementary = [
  614. 'campaign_id' => $campaign_id,
  615. 'subsidy_need' => $campaign_data['subsidy_need'],
  616. 'match_date' => $match_date,
  617. 'period' => $campaign_data['period'],
  618. 'kandian' => $campaign_data['elementary_need'],
  619. 'goods_id' => $campaign_data['elementary_goods_id'],
  620. 'level'=> 0,
  621. 'createtime' => time(),
  622. 'updatetime' => time()
  623. ];
  624. $mdata_intermediate = [
  625. 'campaign_id' => $campaign_id,
  626. 'subsidy_need' => $campaign_data['subsidy_need'],
  627. 'match_date' => $match_date,
  628. 'period' => $campaign_data['period'],
  629. 'kandian' => $campaign_data['intermediate_need'],
  630. 'goods_id' => $campaign_data['intermediate_goods_id'],
  631. 'level'=> 1,
  632. 'createtime' => time(),
  633. 'updatetime' => time()
  634. ];
  635. $mdata_advanced = [
  636. 'campaign_id' => $campaign_id,
  637. 'subsidy_need' => $campaign_data['subsidy_need'],
  638. 'match_date' => $match_date,
  639. 'period' => $campaign_data['period'],
  640. 'kandian' => $campaign_data['advanced_need'],
  641. 'goods_id' => $campaign_data['advanced_goods_id'],
  642. 'level'=> 2,
  643. 'createtime' => time(),
  644. 'updatetime' => time()
  645. ];
  646. $this->getCampaignMatchModel()->insert($mdata_elementary);
  647. $this->getCampaignMatchModel()->insert($mdata_intermediate);
  648. $this->getCampaignMatchModel()->insert($mdata_advanced);
  649. }
  650. }
  651. }
  652. /**
  653. * 根据活动ID,删除Match表中数据
  654. * @param $campaign_id
  655. */
  656. public function delMatch($campaign_id)
  657. {
  658. $rst = $this->getCampaignMatchModel()->where('campaign_id', $campaign_id)->select();
  659. if ($rst) {
  660. $pipe = Redis::instance()->multi(\Redis::PIPELINE);
  661. foreach ($rst as $k=>$v){
  662. $redis_key = CampaignConstants::USER_MATCH_KEY_PREFIX.$v->match_date.$v->kandian;
  663. $pipe->del($redis_key);
  664. }
  665. $pipe->exec();
  666. }
  667. $this->getCampaignMatchModel()->where('campaign_id', $campaign_id)->delete();
  668. }
  669. /**
  670. * 获取最新有效活动(有Banner 或者 弹窗图 或者 智能推送图)
  671. * @param $channel_id
  672. * @param $user_id
  673. * @return array
  674. */
  675. public function getLatestCampaign($userInfo)
  676. {
  677. //检查是不是新用户
  678. $user_id = $userInfo->id;
  679. $channel_id = $userInfo->channel_id;
  680. $createDate = date('Ymd',$userInfo->createtime);
  681. if ($createDate == date('Ymd',time())) {//新用户不弹出
  682. return [];
  683. }
  684. //检查活动是否开启
  685. $isOpen = $this->checkCampaignOpen();
  686. if ($isOpen != 1){
  687. return [];
  688. }
  689. // 获取用户参与活动的信息
  690. $userMatchInfo = $this->getUserMatch($user_id);
  691. $registration_time = $userMatchInfo['createtime'] ?? 0;
  692. //$active_end_time = $registration_time + ($userMatchInfo['period'] + CampaignConstants::CAMPAIGN_PERIOD_DAY) * 86400;
  693. $arward_flag = true;
  694. if ($userMatchInfo) {
  695. $diff_day = (time() - $registration_time) / 86400 - $userMatchInfo['num'];
  696. $arward_flag = (in_array($userMatchInfo['status'], ['1', '2']) && $diff_day <= 2) || ($userMatchInfo['status'] == 3 && $diff_day <= 3);
  697. }
  698. if ($userMatchInfo && $userMatchInfo['active_id'] && $arward_flag) {
  699. $data = $this->getCampaignById($userMatchInfo['active_id']);
  700. } else {
  701. //黑名单改为白名单
  702. //$forbidden_channels = explode(',', str_replace(',', ',', Config::get('site.campaign_forbidden_channels')));
  703. $isWrite = model('ChannelSpecialManage')->isWhite('campaign', $channel_id);
  704. if(!$isWrite){
  705. $data = [];
  706. }else{
  707. $data = $this->getLatestReadInfo();
  708. if ($data && $data['end_time'] < time()) {
  709. $data = [];
  710. }
  711. }
  712. }
  713. return $data;
  714. }
  715. /**
  716. * 按时间取出最新的一条挑战赛活动信息
  717. */
  718. public function getLatestReadInfo()
  719. {
  720. $redisKey = CampaignConstants::CAMPAIGN_READ_LAST_KEY;
  721. $rst_arr = Redis::instance()->hGetAll($redisKey);
  722. if (empty($rst_arr)) {
  723. $rst = $this->getCampaignReadModel()
  724. ->where('status', 'eq', 'normal')
  725. ->where('start_time', '<=', time())
  726. ->where('end_time', '>=', time())
  727. ->where(function ($query) {
  728. $query->where('banner_img', 'neq', '')
  729. ->whereor('popup_img', 'neq', '');
  730. })
  731. ->order('id', 'desc')
  732. ->find();
  733. $ttl = strtotime(date('Y-m-d 23:59:59', time())) - time();
  734. if ($rst) {
  735. $rst_arr = $rst->toArray();
  736. $rst_arr['banner_img'] = !empty($rst_arr['banner_img']) ? cdnurl($rst_arr['banner_img']) : '';
  737. $rst_arr['popup_img'] = !empty($rst_arr['popup_img']) ? cdnurl($rst_arr['popup_img']) : '';
  738. } else {
  739. $rst_arr = [
  740. 'id' => 0,
  741. 'end_time' => 0
  742. ];
  743. }
  744. Redis::instance()->hMSet($redisKey, $rst_arr);
  745. Redis::instance()->expire($redisKey, $ttl);
  746. }
  747. return $rst_arr;
  748. }
  749. /**
  750. * 通过ID获取信息
  751. * @param $id
  752. * @return array
  753. */
  754. public function getCampaignById($id)
  755. {
  756. $redisKey = CampaignConstants::CAMPAIGN_READ_KEY . $id;
  757. if (Redis::instance()->hGetAll($redisKey)) {
  758. return Redis::instance()->hGetAll($redisKey);
  759. } else {
  760. $rst = $this->getCampaignReadModel()
  761. ->where('id', '=', $id)
  762. ->find();
  763. $ttl = strtotime(date('Y-m-d 23:59:59', time())) - time();
  764. if ($rst) {
  765. $rst_arr = $rst->toArray();
  766. $rst_arr['banner_img'] = !empty($rst_arr['banner_img']) ? cdnurl($rst_arr['banner_img']) : '';
  767. $rst_arr['popup_img'] = !empty($rst_arr['popup_img']) ? cdnurl($rst_arr['popup_img']) : '';
  768. } else {
  769. $rst_arr = [];
  770. }
  771. Redis::instance()->hMSet($redisKey, $rst_arr);
  772. Redis::instance()->expire($redisKey, $ttl);
  773. return $rst_arr;
  774. }
  775. }
  776. /**
  777. * 删除Redis中最新的活动信息
  778. */
  779. public function delLatestCampaignRedis()
  780. {
  781. Redis::instance()->del(CampaignConstants::CAMPAIGN_READ_LAST_KEY);
  782. }
  783. /**
  784. * 删除活动缓存
  785. * @param $activeId
  786. */
  787. public function delReadRedisById($activeId)
  788. {
  789. $redisKey = CampaignConstants::getCampaignRedisKey($activeId);
  790. Redis::instance()->del($redisKey);
  791. }
  792. /**
  793. * 获取消费活动商品
  794. */
  795. public function getCampaignGoods()
  796. {
  797. $list = model('Goods')->getGoodsList(PayConstants::BUSINESS_WECHAT,PayConstants::GOODS_CATEGORY_CAMPAIGN,PayConstants::GOODS_TYPE_KD);
  798. return $list;
  799. }
  800. }