Index.php 37 KB

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