Index.php 37 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096
  1. <?php
  2. namespace app\index\controller;
  3. use think\facade\Db;
  4. use app\middleware\Log;
  5. use think\facade\Cache;
  6. use ReflectionException;
  7. use app\middleware\Safe;
  8. use think\file\UploadedFile;
  9. use \think\response\Json;
  10. use think\facade\Request;
  11. use think\admin\Controller;
  12. use InvalidArgumentException;
  13. use app\service\WeiboService;
  14. use app\admin\model\SystemNotice;
  15. use think\facade\Log as FacadeLog;
  16. use think\db\exception\DbException;
  17. use think\admin\service\SystemService;
  18. use think\exception\FuncNotFoundException;
  19. use think\exception\ClassNotFoundException;
  20. use think\db\exception\DataNotFoundException;
  21. use think\db\exception\ModelNotFoundException;
  22. /**
  23. * Class Index
  24. * @package app\index\controller
  25. */
  26. class Index extends Controller
  27. {
  28. public function index()
  29. {
  30. FacadeLog::info("index cookies: ". json_encode($_COOKIE));
  31. if (!empty($_COOKIE['SUB']) && strpos($_SERVER["HTTP_USER_AGENT"],"Weibo")) {
  32. $sub = $_COOKIE['SUB'];
  33. $isWebo = 1;
  34. } else {
  35. $isWebo = 0;
  36. // 只在调试模式下开启从POST参数中获取UID,方便测试联调
  37. if (env('app_debug')) {
  38. $sub = Request::get('cookie');
  39. }
  40. }
  41. $this->assign('sub', $sub);
  42. $this->assign('isWeibo', $isWebo);
  43. $this->fetch();
  44. }
  45. /**
  46. * 获取品牌任务相关配置
  47. *
  48. * @throws FuncNotFoundException
  49. * @throws ClassNotFoundException
  50. * @throws ReflectionException
  51. * @throws DbException
  52. * @throws ModelNotFoundException
  53. * @throws DataNotFoundException
  54. * @return mixed
  55. */
  56. public function brand()
  57. {
  58. $conf = $this->getBrandConfigAndState();
  59. if ($conf instanceof Json) {
  60. return $conf;
  61. }
  62. return $this->successResponse($conf);
  63. }
  64. /**
  65. * 检测登录 通过cookie中的SUB字段的内容,调用用户接口检测登录状态
  66. * @throws ClassNotFoundException
  67. * @throws ReflectionException
  68. * @return mixed
  69. */
  70. public function checkLogin()
  71. {
  72. FacadeLog::info("checkLogin cookies:" . json_encode(Request::post()));
  73. $sub = Request::post('cookie');
  74. $uid = 0;
  75. $userInfoRes = (new WeiboService($uid))->userinfo($sub);
  76. if (empty($userInfoRes) || $userInfoRes['ok'] != 1) {
  77. return $this->response(403, $userInfoRes['msg'] ?? '没有登录');
  78. }
  79. // 使用客户端信息生成token
  80. $token = md5($_SERVER['HTTP_USER_AGENT'] . $_SERVER['HTTP_ACCEPT_ENCODING'] . $_SERVER['HTTP_ACCEPT_LANGUAGE'] . $_SERVER['HTTP_REFERER'] . get_client_ip(0) . $userInfoRes['data']['uid']);
  81. $user = $userInfoRes['data'];
  82. $userInfo = Db::table('awards_user_info')->where('uid', $user['uid'])->find();
  83. $count = 0;
  84. $isShare = 0;
  85. if (empty($userInfo)) {
  86. $userAttr = [
  87. 'uid' => $user['uid'],
  88. 'portrait' => $user['profile_image_url'],
  89. 'nickname' => $user['name'],
  90. 'is_share' => 0,
  91. 'count' => 1,
  92. 'create_at' => time()
  93. ];
  94. if (0 == Db::table('awards_user_info')->insert($userAttr)) {
  95. return $this->response(5001, '系统错误,请稍后再试~');
  96. }
  97. } else {
  98. $count = Db::table('awards_user_task_log')->where('uid', $user['uid'])->count('id');
  99. $isShare = $userInfo['is_share'];
  100. }
  101. // 生成加密用的密钥和向量
  102. $cipher = "aes-256-gcm";
  103. $ivlen = openssl_cipher_iv_length($cipher);
  104. $iv = bin2hex(openssl_random_pseudo_bytes($ivlen));
  105. $aesKey = bin2hex(openssl_random_pseudo_bytes(32));
  106. $user = array_merge($user, [
  107. 'aes_key' => $aesKey,
  108. 'ase_iv' => $iv,
  109. ]);
  110. $cacheUser = [
  111. 'aes_key' => $aesKey,
  112. 'ase_iv' => $iv,
  113. 'uid' => $user['uid'],
  114. ];
  115. $activity = Db::table('awards_activity')->where('begin_at', '<=', time())
  116. ->where('end_at', '>=', time())->find();
  117. $isBeginActivity = 1;
  118. if (empty($activity)) {
  119. $isBeginActivity = 0;
  120. }
  121. $userInfo = [];
  122. if ($count > 0) {
  123. $userInfo = Db::table('awards_user_task_log')->alias('l')
  124. ->leftJoin('awards_user_info u', 'l.uid = u.uid')
  125. ->field(['u.nickname', 'u.portrait', 'u.uid', 'l.duration', 'l.number'])
  126. ->order('l.number', 'desc')
  127. ->order('l.duration', 'asc')
  128. ->find();
  129. }
  130. // 缓存用户信息1天
  131. Cache::set('u:' . $token, json_encode($cacheUser), 86400);
  132. return $this->successResponse([
  133. 'user' => $user,
  134. 'token' => $token,
  135. 'isShare' => $isShare,
  136. 'count' => $count,
  137. 'isBeginActivity' => $isBeginActivity,
  138. 'task' => $userInfo
  139. ]);
  140. }
  141. /**
  142. * 是否可以参与游戏
  143. * @throws ClassNotFoundException
  144. * @throws ReflectionException
  145. * @return mixed
  146. */
  147. public function checkRole()
  148. {
  149. $activity = Db::table('awards_activity')->where('begin_at', '<=', time())
  150. ->where('end_at', '>=', time())->find();
  151. if (empty($activity)) {
  152. return $this->response(5002, '活动末开始');
  153. }
  154. $userInfo = Db::table('awards_user_info')->where('uid', Safe::$user['uid'])->find();
  155. $count = Db::table('awards_user_task_log')->where('uid', Safe::$user['uid'])->count('id');
  156. return $this->successResponse([
  157. 'isShare' => $userInfo['is_share'],
  158. 'count' => $count
  159. ]);
  160. }
  161. /**
  162. * 提交任务接口
  163. * @throws FuncNotFoundException
  164. * @throws ClassNotFoundException
  165. * @throws DbException
  166. * @throws ModelNotFoundException
  167. * @throws DataNotFoundException
  168. * @return mixed
  169. */
  170. public function submitTask()
  171. {
  172. $activity = Db::table('awards_activity')->where('begin_at', '<=', time())
  173. ->where('end_at', '>=', time())->find();
  174. if (empty($activity)) {
  175. return $this->response(5002, '活动末开始');
  176. }
  177. // if (empty(Safe::$body)) {
  178. // return $this->response(5003, '参数有误');
  179. // }
  180. //
  181. // if (!isset(Safe::$body['duration']) || Safe::$body['duration'] < 1 || Safe::$body['duration'] > 1000) {
  182. // return $this->response(5003, '时长参数有误');
  183. // }
  184. //
  185. // if (!isset(Safe::$body['number']) || Safe::$body['number'] < 0 || Safe::$body['number'] > 1000) {
  186. // return $this->response(5003, '时长参数有误');
  187. // }
  188. // $duration = Safe::$body['duration'];
  189. // $number = Safe::$body['number'];
  190. $duration = Request::post("duration");
  191. $number = Request::post("number");
  192. $date = date('Y-m-d');
  193. $userInfo = Db::table('awards_user_info')->where('uid', Safe::$user['uid'])->find();
  194. if (empty($userInfo)) {
  195. return $this->response(403, '没有登录');
  196. }
  197. $count = Db::table('awards_user_task_log')->where('uid', Safe::$user['uid'])->count('id');
  198. if ($count >= $userInfo['count']) {
  199. return $this->response(5002, '没有参与次数');
  200. }
  201. $log = [
  202. 'uid' => Safe::$user['uid'],
  203. 'date' => $date,
  204. 'duration' => $duration,
  205. 'number' => $number,
  206. 'create_at' => time()
  207. ];
  208. if (0 == Db::table('awards_user_task_log')->insert($log)) {
  209. return $this->response(5001, '系统错误,请稍后再试~');
  210. }
  211. return $this->successResponse(null, '提交成功');
  212. }
  213. /**
  214. * 提交发布微博接口
  215. * @throws FuncNotFoundException
  216. * @throws ClassNotFoundException
  217. * @throws DbException
  218. * @throws ModelNotFoundException
  219. * @throws DataNotFoundException
  220. * @return mixed
  221. */
  222. public function submitShare()
  223. {
  224. $activity = Db::table('awards_activity')->where('begin_at', '<=', time())
  225. ->where('end_at', '>=', time())->find();
  226. if (empty($activity)) {
  227. return $this->response(5002, '活动末开始');
  228. }
  229. $userInfo = Db::table('awards_user_info')->where('uid', Safe::$user['uid'])->find();
  230. if (empty($userInfo)) {
  231. return $this->response(403, '没有登录');
  232. }
  233. if ($userInfo['is_share'] > 0) {
  234. return $this->response(601, '已发布');
  235. }
  236. // 更新任务状态
  237. $nums = Db::table('awards_user_info')->where('uid', Safe::$user['uid'])->update([
  238. 'is_share' => 1,
  239. 'count' => 2,
  240. 'share_at' => time()
  241. ]);
  242. if ($nums) {
  243. return $this->successResponse(null, '提交成功');
  244. } else {
  245. return $this->response(601, '发布失败');
  246. }
  247. }
  248. /**
  249. * 头号排行接口
  250. * @throws FuncNotFoundException
  251. * @throws ClassNotFoundException
  252. * @throws DbException
  253. * @throws ModelNotFoundException
  254. * @throws DataNotFoundException
  255. * @return mixed
  256. */
  257. public function topRanking()
  258. {
  259. $activity = Db::table('awards_activity')->where('begin_at', '<=', time())
  260. ->where('end_at', '>=', time())->find();
  261. if (empty($activity)) {
  262. return $this->response(5002, '活动末开始');
  263. }
  264. $ranking = Db::table('awards_user_task_log')->alias("l")
  265. ->leftJoin('awards_user_info u', 'l.uid = u.uid')
  266. ->field(['u.nickname', 'u.portrait', 'u.uid', 'l.duration', 'l.number'])
  267. ->distinct('uid')
  268. ->order('l.number', 'desc')
  269. ->order('l.duration', 'asc')
  270. ->limit(50)
  271. ->select();
  272. $userInfo = Db::table('awards_user_task_log')->alias('l')
  273. ->leftJoin('awards_user_info u', 'l.uid = u.uid')
  274. ->field(['u.nickname', 'u.portrait', 'u.uid', 'l.duration', 'l.number'])
  275. ->order('l.number', 'desc')
  276. ->order('l.duration', 'asc')
  277. ->find();
  278. $res = [
  279. 'self' => $userInfo,
  280. 'ranking' => $ranking
  281. ];
  282. return $this->successResponse($res);
  283. }
  284. /**
  285. * 最新排行接口
  286. * @throws FuncNotFoundException
  287. * @throws ClassNotFoundException
  288. * @throws DbException
  289. * @throws ModelNotFoundException
  290. * @throws DataNotFoundException
  291. * @return mixed
  292. */
  293. public function newRanking()
  294. {
  295. $activity = Db::table('awards_activity')->where('begin_at', '<=', time())
  296. ->where('end_at', '>=', time())->find();
  297. if (empty($activity)) {
  298. return $this->response(5002, '活动末开始');
  299. }
  300. $ranking = Db::table('awards_user_task_log')->alias("l")
  301. ->leftJoin('awards_user_info u', 'l.uid = u.uid')
  302. ->field(['u.nickname', 'u.portrait', 'u.uid', 'l.duration', 'l.number'])
  303. ->distinct('uid')
  304. ->order('l.create_at', 'desc')
  305. ->order('l.number', 'desc')
  306. ->order('l.duration', 'asc')
  307. ->limit(50)
  308. ->select();
  309. $userInfo = Db::table('awards_user_task_log')->alias('l')
  310. ->leftJoin('awards_user_info u', 'l.uid = u.uid')
  311. ->field(['u.nickname', 'u.portrait', 'u.uid', 'l.duration', 'l.number'])
  312. ->order('l.number', 'desc')
  313. ->order('l.duration', 'asc')
  314. ->find();
  315. $res = [
  316. 'self' => $userInfo,
  317. 'ranking' => $ranking
  318. ];
  319. return $this->successResponse($res);
  320. }
  321. /**
  322. * 提交领取信息接口
  323. * @throws FuncNotFoundException
  324. * @throws ClassNotFoundException
  325. * @throws DbException
  326. * @throws ModelNotFoundException
  327. * @throws DataNotFoundException
  328. * @return mixed
  329. */
  330. public function submitReceive()
  331. {
  332. $activity = Db::table('awards_activity')->where('begin_at', '<=', time())
  333. ->where('end_at', '>=', time())->find();
  334. if (empty($activity)) {
  335. return $this->response(5002, '活动末开始');
  336. }
  337. $name = trim(Request::post("name"));
  338. $mobile = trim(Request::post("mobile"));
  339. $address = trim(Request::post("address"));
  340. $giftId = trim(Request::post("giftId"));
  341. $type = trim(Request::post("type"));
  342. $orders = Db::table('awards_order')->where('uid', Safe::$user['uid'])->where('type', $type)->find();
  343. if (empty($orders)) {
  344. return $this->response(5001, '参数有误');
  345. }
  346. $userInfo = Db::table('awards_user_info')->where('uid', Safe::$user['uid'])->find();
  347. if (empty($userInfo)) {
  348. return $this->response(403, '没有登录');
  349. }
  350. if (strlen($name) < 1 || strlen($name) > 50) {
  351. return $this->response(5001, '姓名有误');
  352. }
  353. if (strlen($mobile) != 11) {
  354. return $this->response(5001, '手机号有误');
  355. }
  356. if (strlen($address) < 1 || strlen($address) > 1000) {
  357. return $this->response(5001, '地址有误');
  358. }
  359. // 更新任务状态
  360. $nums = Db::table('awards_order')->where('uid', Safe::$user['uid'])->where('type', $type)->update([
  361. 'name' => $name,
  362. 'mobile' => $mobile,
  363. 'address' => $address,
  364. ]);
  365. if ($nums < 1) {
  366. return $this->response(5001, '系统错误,请稍后再试~');
  367. }
  368. return $this->successResponse(null, '提交成功');
  369. }
  370. /**
  371. * 获取轮播中奖接口
  372. * @throws FuncNotFoundException
  373. * @throws ClassNotFoundException
  374. * @throws DbException
  375. * @throws ModelNotFoundException
  376. * @throws DataNotFoundException
  377. * @return mixed
  378. */
  379. public function getRotationAward() {
  380. $activity = Db::table('awards_activity')->where('begin_at', '<=', time())
  381. ->where('end_at', '>=', time())->find();
  382. if (empty($activity)) {
  383. return $this->response(5002, '活动末开始');
  384. }
  385. $orders = Db::table('awards_order')->alias('o')
  386. ->leftJoin('awards_user_info u', 'o.uid = u.uid')
  387. ->leftJoin('awards_gift g', 'o.gift_id = g.id')
  388. ->field(['u.nickname', 'u.portrait', 'u.uid', 'g.name as giftName'])
  389. ->order('o.id', 'desc')
  390. ->select();
  391. return $this->successResponse($orders);
  392. }
  393. /**
  394. * 排行中奖接口
  395. * @throws FuncNotFoundException
  396. * @throws ClassNotFoundException
  397. * @throws DbException
  398. * @throws ModelNotFoundException
  399. * @throws DataNotFoundException
  400. * @return mixed
  401. */
  402. public function getRankingWinAward() {
  403. $activity = Db::table('awards_activity')->where('begin_at', '<=', time())
  404. ->where('end_at', '>=', time())->find();
  405. if (!empty($activity)) {
  406. return $this->response(5002, '活动末结束');
  407. }
  408. $ranking = Db::table('awards_user_task_log')->alias("l")
  409. ->leftJoin('awards_user_info u', 'l.uid = u.uid')
  410. ->field(['u.nickname', 'u.portrait', 'u.uid', 'l.duration', 'l.number'])
  411. ->distinct('l.uid')
  412. ->order('l.number', 'desc')
  413. ->order('l.duration', 'asc')
  414. ->limit(50)
  415. ->select();
  416. $isWinAward = 0;
  417. $rank = 0;
  418. foreach ($ranking as $key => $val) {
  419. if ($val['uid'] == Safe::$user['uid']) {
  420. $isWinAward = 1;
  421. $rank = $key +1;
  422. break;
  423. }
  424. }
  425. // 如果中奖 插入用户中奖信息
  426. if ($isWinAward == 1) {
  427. $gifts = Db::table('awards_gift')->where('type', 2)->select();
  428. $giftId = 0;
  429. foreach ($gifts as $val) {
  430. if ($rank >= $val['min_rank'] && $rank <= $val['max_rank']) {
  431. $giftId = $val['id'];
  432. $orders = Db::table('awards_order')->where('uid', Safe::$user['uid'])->where('type', 2)->find();
  433. if (empty($orders)) {
  434. $order = [
  435. 'uid' => Safe::$user['uid'],
  436. 'gift_id' => $giftId,
  437. 'type' => 2,
  438. 'create_at' => time(),
  439. ];
  440. Db::table('awards_order')->insert($order);
  441. }
  442. break;
  443. }
  444. }
  445. }
  446. return $this->successResponse([
  447. 'isWinAward' => $isWinAward,
  448. 'giftId' => $giftId
  449. ]);
  450. }
  451. /**
  452. * 抽奖接口
  453. * @throws FuncNotFoundException
  454. * @throws ClassNotFoundException
  455. * @throws DbException
  456. * @throws ModelNotFoundException
  457. * @throws DataNotFoundException
  458. * @return mixed
  459. */
  460. public function getLuckDraw()
  461. {
  462. $orders = Db::table('awards_order')->where('uid', Safe::$user['uid'])->where('type', 1)->find();
  463. $isWinAward = 0;
  464. if ($orders) {
  465. return $this->successResponse([
  466. 'isWinAward' => $isWinAward,
  467. 'giftId' => 0
  468. ]);
  469. }
  470. $gifts = Db::table('awards_gift')->where('type', 1)->select();
  471. $logCount = Db::table('awards_user_task_log')->distinct('uid')->count('id');
  472. $userRate = rand(0, 5000);
  473. $giftId = 0;
  474. foreach ($gifts as $gift) {
  475. $orderCount = Db::table('awards_order')->where('type', 1)->where('gift_id', $gift['id'])->count('id');
  476. if ($orderCount >= $gift['count']) {
  477. continue;
  478. }
  479. // 如果参与活动人数 5000人内 有人中奖过,那么不在计算。
  480. $limit = 5000;
  481. $total = $logCount + 1;
  482. if ($orderCount == floor($total/$limit)) {
  483. $isWinAward = 0;
  484. $giftId = 0;
  485. break;
  486. }
  487. for ($i=0;$i<$gift['count'];$i++) {
  488. $giftRage = rand(0, 5000);
  489. if ($userRate == $giftRage) {
  490. $isWinAward = 1;
  491. $giftId = $gift['id'];
  492. break;
  493. }
  494. }
  495. // 如果参与活动人数 5000人内 还没有人中奖那最后一人必中。
  496. if ($orderCount < floor($total/$limit) && $isWinAward ==0 && ($total%$limit) == 0) {
  497. $isWinAward = 1;
  498. $giftId = $gift['id'];
  499. break;
  500. }
  501. }
  502. // 如果中奖 插入用户中奖信息
  503. if ($isWinAward == 1) {
  504. $order = [
  505. 'uid' => Safe::$user['uid'],
  506. 'gift_id' => $giftId,
  507. 'type' => 1,
  508. 'create_at' => time(),
  509. ];
  510. if (0 == Db::table('awards_order')->insert($order)) {
  511. return $this->response(5001, '系统错误,请稍后再试~');
  512. }
  513. }
  514. return $this->successResponse([
  515. 'isWinAward' => $isWinAward,
  516. 'giftId' => $giftId
  517. ]);
  518. }
  519. /**
  520. * 奖品记录接口
  521. * @throws FuncNotFoundException
  522. * @throws ClassNotFoundException
  523. * @throws DbException
  524. * @throws ModelNotFoundException
  525. * @throws DataNotFoundException
  526. * @return mixed
  527. */
  528. public function getAwardLog()
  529. {
  530. $awards = Db::table('awards_order')->alias('o')
  531. ->leftJoin('awards_gift g', 'o.gift_id = g.id')
  532. ->field(['g.name as giftName', 'o.type', 'o.create_at', 'o.gift_id'])
  533. ->where('o.uid', Safe::$user['uid'])
  534. ->select();
  535. $res = [];
  536. foreach ($awards as $val) {
  537. $type = '抽奖';
  538. if ($val['type'] == 2) {
  539. $type = '排名奖';
  540. }
  541. $res[] = [
  542. 'giftId' => $val['gift_id'],
  543. 'giftName' => $val['giftName'],
  544. 'typeLabel' => $type,
  545. 'type' => $val['type'],
  546. 'createAt' => date('y-m-d h:i:s', $val['create_at'])
  547. ];
  548. }
  549. return $this->successResponse($res);
  550. }
  551. public function clearGameData()
  552. {
  553. // 更新用户参与状态
  554. Db::table('awards_user_info')->where('uid', Safe::$user['uid'])->update([
  555. 'is_share' => 0,
  556. 'share_at' => 0,
  557. 'count' => 1,
  558. ]);
  559. Db::table('awards_user_task_log')->where('uid', Safe::$user['uid'])->delete();
  560. Db::table('awards_order')->where('uid', Safe::$user['uid'])->delete();
  561. return $this->successResponse(null, '清除成功');
  562. }
  563. /**
  564. * 品牌任务关注接口
  565. * @throws FuncNotFoundException
  566. * @throws ClassNotFoundException
  567. * @throws ReflectionException
  568. * @throws DbException
  569. * @throws ModelNotFoundException
  570. * @throws DataNotFoundException
  571. * @return mixed
  572. */
  573. public function follow()
  574. {
  575. // 先获取品牌任务配置及状态
  576. $conf = $this->getBrandConfigAndState();
  577. if ($conf instanceof Json) {
  578. return $conf;
  579. }
  580. // 已经关注过了
  581. if ($conf['state']['follow_state'] == 1) {
  582. return $this->successResponse([
  583. 'result' => 2,
  584. 'brand' => $conf,
  585. ], '您已经关注过了');
  586. }
  587. // 调用接口关注
  588. $weiboRes = (new WeiboService(Safe::$user['uid']))->add($conf['config']['follow']['id']);
  589. if (empty($weiboRes) || $weiboRes['code'] != 10000) {
  590. return $this->response(600, $weiboRes['msg'] ?? '关注失败~');
  591. }
  592. $date = date('Y-m-d');
  593. $redisKey = $this->getTaskStateRedisKey(intval(Safe::$user['uid']));
  594. // 如果已经完成了另外两项,则标记品牌任务已经完成
  595. $finishState = $conf['state']['finish_state'];
  596. if ($conf['state']['view_state'] == 1 && $conf['state']['forward_state'] == 1) {
  597. $finishState = 1;
  598. }
  599. // 更新任务状态
  600. $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update([
  601. 'follow_state' => 1,
  602. 'finish_state' => $finishState,
  603. ]);
  604. if ($nums) {
  605. $conf['state']['follow_state'] = 1;
  606. $conf['state']['finish_state'] = $finishState;
  607. Cache::set($redisKey, json_encode($conf['state']), 86400);
  608. return $this->successResponse([
  609. 'result' => 1,
  610. 'brand' => $conf,
  611. ], '关注成功');
  612. } else {
  613. return $this->response(601, '更新任务状态失败');
  614. }
  615. }
  616. /**
  617. * 品牌任务转发博文接口
  618. * @throws FuncNotFoundException
  619. * @throws ClassNotFoundException
  620. * @throws ReflectionException
  621. * @throws DbException
  622. * @throws ModelNotFoundException
  623. * @throws DataNotFoundException
  624. * @return mixed
  625. */
  626. public function forward()
  627. {
  628. // 先获取品牌任务配置及状态
  629. $conf = $this->getBrandConfigAndState();
  630. if ($conf instanceof Json) {
  631. return $conf;
  632. }
  633. // 已经转发过了
  634. if ($conf['state']['forward_state'] == 1) {
  635. return $this->successResponse([
  636. 'result' => 2,
  637. 'brand' => $conf,
  638. ], '您已经转发过了');
  639. }
  640. // 调用微博接口转发
  641. $weiboRes = (new WeiboService(Safe::$user['uid']))->repost($conf['config']['forward']['id'], $conf['config']['forward']['content'] ?? '');
  642. if (empty($weiboRes) || $weiboRes['code'] != 10000) {
  643. return $this->response(600, $weiboRes['msg'] ?? '转发失败~');
  644. }
  645. $date = date('Y-m-d');
  646. $redisKey = $this->getTaskStateRedisKey(intval(Safe::$user['uid']));
  647. // 如果已经完成了另外两项,则标记品牌任务已经完成
  648. $finishState = $conf['state']['finish_state'];
  649. if ($conf['state']['view_state'] == 1 && $conf['state']['follow_state'] == 1) {
  650. $finishState = 1;
  651. }
  652. // 更新任务状态
  653. $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update([
  654. 'forward_state' => 1,
  655. 'finish_state' => $finishState,
  656. ]);
  657. if ($nums) {
  658. $conf['state']['forward_state'] = 1;
  659. $conf['state']['finish_state'] = $finishState;
  660. Cache::set($redisKey, json_encode($conf['state']), 86400);
  661. return $this->successResponse([
  662. 'result' => 1,
  663. 'brand' => $conf,
  664. ], '转发成功');
  665. } else {
  666. return $this->response(601, '更新任务状态失败');
  667. }
  668. }
  669. /**
  670. * 获取活动规则
  671. * @throws FuncNotFoundException
  672. * @throws ReflectionException
  673. * @throws InvalidArgumentException
  674. * @throws ClassNotFoundException
  675. * @return mixed
  676. */
  677. public function getRule()
  678. {
  679. $config = SystemService::instance()->getData('activity:rule');
  680. return $this->successResponse($config);
  681. }
  682. /**
  683. * 聚合页配置信息
  684. * @throws FuncNotFoundException
  685. * @throws ReflectionException
  686. * @throws InvalidArgumentException
  687. * @throws ClassNotFoundException
  688. * @return mixed
  689. */
  690. public function groupPageConfig()
  691. {
  692. return $this->successResponse(['config' => SystemService::instance()->getData('group:page:config')]);
  693. }
  694. // public function index()
  695. // {
  696. // $this->redirect(sysuri('admin/login/index'));
  697. // }
  698. /**
  699. * 聚合页通知获取
  700. * 查询最近20条通知
  701. * @throws DbException
  702. * @throws ModelNotFoundException
  703. * @throws DataNotFoundException
  704. * @return mixed
  705. */
  706. public function notices()
  707. {
  708. $rows = SystemNotice::limit(20)->order('id', 'desc')->select();
  709. return $this->successResponse([
  710. "lists" => $rows,
  711. ]);
  712. }
  713. /**
  714. * 首次弹窗
  715. * 发放邀请函微博
  716. * @return Json
  717. */
  718. public function sendInviteWeibo()
  719. {
  720. $config = SystemService::instance()->getData('group:page:config');
  721. $sendRes = (new WeiboService(Safe::$user['uid']))->status($config['firstDialog']['content']);
  722. if (empty($sendRes) || $sendRes['code'] != 10000) {
  723. return $this->response(403, $sendRes['msg'] ?? '发布失败');
  724. }
  725. Cache::set('u:f:' . Safe::$user['uid'], 1, 15552000);
  726. return $this->successResponse(null, '发布成功!');
  727. }
  728. /**
  729. * 首次弹窗用户未选择发送邀请函
  730. * 标记已经首次弹窗过了
  731. * @return mixed
  732. */
  733. public function setFirst()
  734. {
  735. Cache::set('u:f:' . Safe::$user['uid'], 1, 15552000);
  736. return $this->successResponse(null, '操作成功!');
  737. }
  738. /**
  739. * 标记用户已经浏览过主页了,用户点了去浏览时调用
  740. * @throws FuncNotFoundException
  741. * @throws ClassNotFoundException
  742. * @throws ReflectionException
  743. * @throws DbException
  744. * @throws ModelNotFoundException
  745. * @throws DataNotFoundException
  746. * @return mixed
  747. */
  748. public function setViewed()
  749. {
  750. // 先获取品牌任务配置及状态
  751. $conf = $this->getBrandConfigAndState();
  752. if ($conf instanceof Json) {
  753. return $conf;
  754. }
  755. if ($conf['state']['view_state'] == 1) {
  756. return $this->successResponse([
  757. 'result' => 2,
  758. 'brand' => $conf,
  759. ], '您已经浏览过了');
  760. }
  761. $date = date('Y-m-d');
  762. $redisKey = $this->getTaskStateRedisKey(intval(Safe::$user['uid']));
  763. // 如果已经完成了另外两项,则标记品牌任务已经完成
  764. $finishState = $conf['state']['finish_state'];
  765. if ($conf['state']['forward_state'] == 1 && $conf['state']['follow_state'] == 1) {
  766. $finishState = 1;
  767. }
  768. $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update([
  769. 'view_state' => 1,
  770. 'finish_state' => $finishState,
  771. ]);
  772. if ($nums) {
  773. $conf['state']['view_state'] = 1;
  774. $conf['state']['finish_state'] = $finishState;
  775. Cache::set($redisKey, json_encode($conf['state']), 86400);
  776. return $this->successResponse([
  777. 'result' => 1,
  778. 'brand' => $conf,
  779. ], '浏览成功');
  780. } else {
  781. return $this->response(601, '更新任务状态失败');
  782. }
  783. }
  784. /**
  785. * 用户完成端外分享时调用接口加票
  786. * @throws FuncNotFoundException
  787. * @throws ClassNotFoundException
  788. * @throws ReflectionException
  789. * @throws DbException
  790. * @throws ModelNotFoundException
  791. * @throws DataNotFoundException
  792. * @return mixed
  793. */
  794. public function shareFinishAddVotes()
  795. {
  796. // 先获取品牌任务配置及状态
  797. $conf = $this->getBrandConfigAndState();
  798. if ($conf instanceof Json) {
  799. return $conf;
  800. }
  801. if ($conf['state']['share_add_votes'] == 1) {
  802. return $this->successResponse([
  803. 'result' => 2,
  804. 'brand' => $conf,
  805. ], '您今日已经领取过投票机会了~');
  806. }
  807. // 调用接口给用户发券(加票)
  808. $weiboRes = (new WeiboService(Safe::$user['uid']))->setcoupons($conf['config']['share']['votes']);
  809. if (empty($weiboRes) || $weiboRes['code'] != 10000) {
  810. return $this->response(600, $weiboRes['msg'] ?? '加票失败~');
  811. }
  812. // 标记状态
  813. $date = date('Y-m-d');
  814. $redisKey = $this->getTaskStateRedisKey(intval(Safe::$user['uid']));
  815. $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update([
  816. 'share_add_votes' => 1,
  817. ]);
  818. if ($nums) {
  819. $conf['state']['share_add_votes'] = 1;
  820. Cache::set($redisKey, json_encode($conf['state']), 86400);
  821. return $this->successResponse([
  822. 'result' => 1,
  823. 'brand' => $conf,
  824. ], '加票成功');
  825. } else {
  826. return $this->response(601, '更新任务状态失败');
  827. }
  828. }
  829. /**
  830. * 完成品牌任务后领取加票机会接口
  831. * @throws FuncNotFoundException
  832. * @throws ClassNotFoundException
  833. * @throws ReflectionException
  834. * @throws DbException
  835. * @throws ModelNotFoundException
  836. * @throws DataNotFoundException
  837. * @return mixed
  838. */
  839. public function taskFinishAddVotes()
  840. {
  841. // 先获取品牌任务配置及状态
  842. $conf = $this->getBrandConfigAndState();
  843. if ($conf instanceof Json) {
  844. return $conf;
  845. }
  846. if ($conf['state']['finish_add_votes'] == 1) {
  847. return $this->successResponse([
  848. 'result' => 2,
  849. 'brand' => $conf,
  850. ], '您今日已经领取过投票机会了~');
  851. }
  852. // 未完成品牌任务 领取失败
  853. if ($conf['state']['finish_state'] == 0) {
  854. return $this->response(603, '请先完成品牌任务,再来领取加票', [
  855. 'result' => 0,
  856. 'brand' => $conf,
  857. ]);
  858. }
  859. // 调用微博接口 给用户发券(加票)
  860. $weiboRes = (new WeiboService(Safe::$user['uid']))->setcoupons($conf['config']['task']['votes']);
  861. if (empty($weiboRes) || $weiboRes['code'] != 10000) {
  862. return $this->response(600, $weiboRes['msg'] ?? '加票失败~');
  863. }
  864. // 标记加票成功
  865. $date = date('Y-m-d');
  866. $redisKey = $this->getTaskStateRedisKey(intval(Safe::$user['uid']));
  867. $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update([
  868. 'finish_add_votes' => 1,
  869. ]);
  870. if ($nums) {
  871. $conf['state']['finish_add_votes'] = 1;
  872. Cache::set($redisKey, json_encode($conf['state']), 86400);
  873. return $this->successResponse([
  874. 'result' => 1,
  875. 'brand' => $conf,
  876. ], '加票成功');
  877. } else {
  878. return $this->response(601, '更新任务状态失败');
  879. }
  880. }
  881. /**
  882. * 获取品牌任务配置及状态
  883. * @throws FuncNotFoundException
  884. * @throws ReflectionException
  885. * @throws InvalidArgumentException
  886. * @throws ClassNotFoundException
  887. * @throws DbException
  888. * @throws ModelNotFoundException
  889. * @throws DataNotFoundException
  890. * @return \think\response\Json|array
  891. */
  892. protected function getBrandConfigAndState()
  893. {
  894. $config = SystemService::instance()->getData('brand:task:config');
  895. $date = date('Y-m-d');
  896. $dateForRedis = date('Ymd');
  897. if (empty(Safe::$user['uid'])) {
  898. $state = [
  899. // 品牌任务完成状态
  900. 'finish_state' => 0,
  901. // 关注子任务状态
  902. 'follow_state' => 0,
  903. // 转发子任务状态
  904. 'forward_state' => 0,
  905. // 查看浏览主页任务状态
  906. 'view_state' => 0,
  907. // 品牌任务完成后是否加票
  908. 'finish_add_votes' => 0,
  909. // 分享完成后是否加票
  910. 'share_add_votes' => 0,
  911. 'uid' => 0,
  912. 'date' => $date,
  913. ];
  914. } else {
  915. $redisKey = "t:{$dateForRedis}:" . Safe::$user['uid'];
  916. $state = Cache::get($redisKey);
  917. if (empty($state)) {
  918. // 缓存失败 查数据库
  919. $state = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->find();
  920. if (empty($state)) {
  921. // 当天第一次,初始化数据
  922. $state = [
  923. // 品牌任务完成状态
  924. 'finish_state' => 0,
  925. // 关注子任务状态
  926. 'follow_state' => 0,
  927. // 转发子任务状态
  928. 'forward_state' => 0,
  929. // 查看浏览主页任务状态
  930. 'view_state' => 0,
  931. // 品牌任务完成后是否加票
  932. 'finish_add_votes' => 0,
  933. // 分享完成后是否加票
  934. 'share_add_votes' => 0,
  935. 'uid' => Safe::$user['uid'],
  936. 'date' => $date,
  937. ];
  938. if (0 == Db::table('awards_user_task')->insert($state)) {
  939. return $this->response(5001, '系统错误,请稍后再试~');
  940. }
  941. }
  942. Cache::set($redisKey, json_encode($state), 86400);
  943. } else {
  944. $state = json_decode($state, true);
  945. }
  946. // 如果未关注状态,查询下已经实际已经关注了
  947. if ($state['follow_state'] == 0) {
  948. $weiboRes = (new WeiboService(Safe::$user['uid']))->friends($config['follow']['id']);
  949. if (isset($weiboRes['data'][$config['follow']['id']]) && $weiboRes['data'][$config['follow']['id']] == 1) {
  950. $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update(['follow_state' => 1]);
  951. if ($nums) {
  952. $state['follow_state'] = 1;
  953. Cache::set($redisKey, json_encode($state), 86400);
  954. }
  955. }
  956. }
  957. }
  958. // 校准状态,可能存在异常情况关注,转发,浏览都完成了,但是总的品牌任务状态没标记成已完成
  959. if ($state['follow_state'] == 1 && $state['forward_state'] == 1 && $state['view_state'] == 1 && $state['finish_state'] != 1) {
  960. $nums = Db::table('awards_user_task')->where('uid', Safe::$user['uid'])->where('date', $date)->update(['finish_state' => 1]);
  961. if ($nums) {
  962. $state['finish_state'] = 1;
  963. Cache::set($redisKey, json_encode($state), 86400);
  964. }
  965. }
  966. return [
  967. 'config' => $config,
  968. 'state' => $state,
  969. ];
  970. }
  971. /**
  972. * 获取品牌任务redis 缓存键
  973. * @param int $uid
  974. * @return string
  975. */
  976. protected function getTaskStateRedisKey(int $uid): string
  977. {
  978. $dateForRedis = date('Ymd');
  979. return "t:{$dateForRedis}:" . $uid;
  980. }
  981. /**
  982. * @param $code
  983. * @param $msg
  984. * @param $data
  985. * @return Json
  986. */
  987. protected function response($code, $msg, $data = null)
  988. {
  989. return json(
  990. [
  991. 'code' => $code,
  992. 'message' => $msg,
  993. 'data' => $data,
  994. 'trackID' => Log::$logID,
  995. ],
  996. 200
  997. );
  998. }
  999. /**
  1000. * @param $data
  1001. * @param $msg
  1002. * @return mixed
  1003. */
  1004. protected function successResponse($data, $msg = '操作成功')
  1005. {
  1006. return $this->response(0, $msg, $data);
  1007. }
  1008. }