VoterController.php 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159
  1. <?php
  2. namespace App\Http\Controllers\Api;
  3. use App\Http\Controllers\Api\Repositories\PostsRepositores;
  4. use App\Jobs\CalculateFollowsNumJob;
  5. use App\Jobs\CalculateLikesNumJob;
  6. use App\Jobs\Posts\UpdatePostOnlyTextJob;
  7. use App\Jobs\Posts\UpdatePostVideoIdJob;
  8. use App\Lib\WeApp\WeApp;
  9. use App\Models\Posts\WxPost;
  10. use App\Models\User\WxUser;
  11. use App\Models\Voter\WxVoter;
  12. use App\Models\Voter\WxVoterPlayer;
  13. use App\Models\Voter\WxVoterPlayerBallot;
  14. use App\Models\Voter\WxVoterTemplate;
  15. use App\Wen\Utils\FieldUtils;
  16. use App\Wen\Utils\Settings;
  17. use App\Wen\Utils\StrUtils;
  18. use App\Wen\Utils\UserUtils;
  19. use App\Wen\Utils\Utils;
  20. use Illuminate\Http\Request;
  21. use Illuminate\Support\Carbon;
  22. use Illuminate\Support\Facades\Cache;
  23. use Illuminate\Support\Facades\DB;
  24. use Illuminate\Support\Facades\Redis;
  25. class VoterController extends BaseController
  26. {
  27. public function list(Request $request){
  28. $uid = $request->uid;
  29. if(_empty_($uid)){
  30. $uid = 0;
  31. }
  32. $user_id = _empty_default_($request->user_id, 0);
  33. $keyword = _empty_default_($request->keyword, '');
  34. $master = _empty_default_($request->master, 0);
  35. // player已经被系统占用
  36. $player = _empty_default_($request->player, 0);
  37. $playerd = _empty_default_($request->playerd, 0);
  38. if($playerd == 1){
  39. $player = 1;
  40. }
  41. $voted = _empty_default_($request->voted, 0);
  42. $template = _empty_default_($request->template, '');
  43. $isTenant = _empty_default_($request->isTenant, false);
  44. if(_empty_($isTenant)){
  45. $isTenant = false;
  46. }else{
  47. $isTenant = true;
  48. }
  49. if(is_string($template)){
  50. $template = explode(',', $template);
  51. }
  52. $orderBy = _empty_default_($request->orderBy, 'created_at');
  53. $order = _empty_default_($request->order, 'desc');
  54. if(!in_array($orderBy, ['created_at'])){
  55. $orderBy = 'created_at';
  56. }
  57. if(!in_array($order, ['desc', 'asc'])){
  58. $order = 'desc';
  59. }
  60. if(_empty_($user_id)){
  61. if($master == -1){
  62. $app_voter_tab = Settings::get('app_voter_tab', [], true);
  63. if($app_voter_tab && count($app_voter_tab) > 0){
  64. $tab = $app_voter_tab[0];
  65. $keyword = '';
  66. $master = _array_key($tab, 'master', 0);
  67. $player = _array_key($tab, 'player', 0);
  68. $voted = _array_key($tab, 'voted', 0);
  69. $orderBy = _array_key($tab, 'orderBy', 'created_at');
  70. $order = _array_key($tab, 'order', 'desc');
  71. $template = _array_key($tab, 'template', []);
  72. if(is_string($template)){
  73. $template = explode(',', $template);
  74. }
  75. }else{
  76. $keyword = '';
  77. $master = 0;
  78. $player = 0;
  79. $voted = 0;
  80. $orderBy = 'created_at';
  81. $order = 'desc';
  82. $template = [];
  83. }
  84. }
  85. }
  86. if(!is_array($template)){
  87. $template = [];
  88. }
  89. if(_empty_(end($template))){
  90. array_pop($template);
  91. }
  92. $query = WxVoter::where('is_exposure', 1);
  93. if($isTenant){
  94. global $__MINI_GLOBAL_TENANT_ID__;
  95. $query = $query->where('tenant_id', $__MINI_GLOBAL_TENANT_ID__);
  96. }
  97. if($keyword){
  98. $query = $query->where('status', 1);
  99. $query->where(function ($query) use ($keyword) {
  100. $query->orWhere('title', 'like', '%' . $keyword . '%')
  101. ->orWhere('content', 'like', '%' . $keyword . '%')
  102. ->orWhere('id', $keyword);
  103. });
  104. }else{
  105. if($template && count($template) > 0){
  106. $query = $query->whereIn('template_id', $template);
  107. }
  108. if($master == 1){
  109. if($user_id > 0){
  110. $query = $query->where('user_id', $user_id);
  111. }else if($uid > 0){
  112. $query = $query->where('user_id', $uid);
  113. }else{
  114. $query = $query->where('id', '<=', 0);
  115. }
  116. }else{
  117. $query = $query->where('status', 1);
  118. }
  119. if($player == 1){
  120. if($user_id > 0){
  121. $query = $query->whereIn('id', function ($query) use ($user_id) {
  122. $query->select('voter_id')
  123. ->from('wx_voter_player')
  124. ->where('user_id', $user_id)
  125. ->orderByDesc('created_at');
  126. });
  127. }else if($uid > 0){
  128. $query = $query->whereIn('id', function ($query) use ($uid) {
  129. $query->select('voter_id')
  130. ->from('wx_voter_player')
  131. ->where('user_id', $uid)
  132. ->orderByDesc('created_at');
  133. });
  134. }else{
  135. $query = $query->where('id', '<=', 0);
  136. }
  137. }
  138. if($voted == 1){
  139. if($uid > 0){
  140. $query = $query->whereIn('id', function ($query) use ($uid) {
  141. $query->select('voter_id')
  142. ->from('wx_voter_player_ballot')
  143. ->where('user_id', $uid)
  144. ->groupBy('voter_id')
  145. ->orderByDesc('created_at');
  146. });
  147. }else{
  148. $query = $query->where('id', '<=', 0);
  149. }
  150. }
  151. }
  152. $data = $query->orderBy('is_sticky', 'desc')->orderBy($orderBy, $order)->orderBy('id', 'desc')->simplePaginate(10);
  153. if($data){
  154. $data->map(function ($v) use ($uid){
  155. $this->voter_item_process($v, $uid);
  156. return $v;
  157. });
  158. return $this->success($data);
  159. }
  160. return $this->fail(200003);
  161. }
  162. public function detail(Request $request){
  163. $uid = $request->uid;
  164. $voter_id = _empty_default_($request->id, 0);
  165. if(_empty_($voter_id)){
  166. return $this->fail(200001);
  167. }
  168. $voter = WxVoter::where('id', $request->id)->first();
  169. if(!$voter){
  170. return $this->fail(200003);
  171. }
  172. $this->voter_item_process($voter, $uid);
  173. return $this->success($voter);
  174. }
  175. private function voter_item_process(WxVoter &$voter, $uid){
  176. global $__MINI_GLOBAL_IS_ADMIN_SUPER__;
  177. $voter->tabs = [
  178. ['name' => '参与'. $voter->player_called, 'action' => 'player'],
  179. ['name'=>'排行榜', 'action'=>'rank'],
  180. ['name'=>'简介', 'action'=>'brief'],
  181. // ['name'=>'互动', 'action'=>'comment']
  182. ];
  183. $result = DB::table('wx_voter_player_ballot')
  184. ->selectRaw(
  185. 'SUM(num) as totalNum, ' .
  186. 'COUNT(DISTINCT user_id) as uniqueUserCount'
  187. )
  188. ->where('voter_id', $voter->id)
  189. ->first();
  190. $voter->ballot_total = $result->totalNum ?: 0;
  191. $voter->player_count = WxVoterPlayer::where('voter_id', $voter->id)->where('status', 1)->count();
  192. $voter->user_count = $result->uniqueUserCount ?: 0;
  193. if($uid > 0){
  194. $voter->user_ballot_rest = $this->get_user_voter_rest_ballot($voter, $uid);
  195. }else{
  196. // user_day_limit,user_total_limit
  197. if($voter->user_total_limit > 0){
  198. $voter->user_ballot_rest = $voter->user_total_limit;
  199. }else{
  200. $voter->user_ballot_rest = $voter->user_day_limit;
  201. }
  202. }
  203. if($voter->user_total_limit > 0){
  204. $voter->user_ballot_tip = '总共拥有'.$voter->user_total_limit.$voter->unit_called.',剩余' .$voter->user_ballot_rest.$voter->unit_called;
  205. }else{
  206. $voter->user_ballot_tip = '每日可投'.$voter->user_day_limit.$voter->unit_called.',今日剩余'.$voter->user_ballot_rest.$voter->unit_called;
  207. }
  208. if($uid > 0){
  209. if(is_object_user_special($uid, $voter->tenant_id, true) || $uid == $voter->user_id){
  210. if($voter->player_count > 0){
  211. $voter->action_sheets = ['删除'];
  212. }else{
  213. $voter->action_sheets = ['编辑', '删除'];
  214. }
  215. }
  216. }
  217. }
  218. public function voter_process(Request $request){
  219. $type = _empty_default_($request->type, '');
  220. if($type == 'push' || $type == 'update'){
  221. return $this->voter_push($request);
  222. }else if($type == 'push_player'){
  223. return $this->voter_player_push($request);
  224. }else if($type == 'player_ballot'){
  225. return $this->player_ballot($request);
  226. }else if($type == 'delete'){
  227. return $this->voter_delete($request);
  228. }else if($type == 'echo'){
  229. return $this->voter_echo($request);
  230. }else if($type == 'voter_share'){
  231. return $this->voter_share($request);
  232. }
  233. }
  234. private function voter_share(Request &$request){
  235. $uid = _empty_default_($request->uid, 0);
  236. $voter_id_ = _abs(_empty_default_($request->voter_id, 0));
  237. global $__MINI_GLOBAL_DEVICE__;
  238. if(_empty_($voter_id_)){
  239. return $this->fail(200001);
  240. }
  241. global $__MINI_GLOBAL_IS_ADMIN_SUPER__;
  242. $new_app = new WeApp();
  243. $wxlink = $new_app->getWxLink();
  244. $voter = WxVoter::find($voter_id_);
  245. if(!$voter){
  246. return $this->fail(200003);
  247. }
  248. $voter_user_id = $voter->user_id;
  249. $voter_title = StrUtils::limit($voter->title);
  250. $s_content = preg_replace("/<(img|video).*?src[^\'\"]+[\'\"]([^\"\']+)[^>]+>/is", '', $voter->content);
  251. $s_content = trim_all_space(strip_tags(html_entity_decode($s_content)), true);
  252. $this->voter_item_process($voter, $uid);
  253. $result = [
  254. 'user' => [],
  255. 'url' => '',
  256. 'social' => [
  257. ],
  258. 'other' => [],
  259. // 临时加下
  260. 'current_page' => 1
  261. ];
  262. if($uid && $uid > 0){
  263. if(!is_mini_examine_mode(11)){
  264. $data = DB::table('wx_user')
  265. ->whereIn('id', function ($query) use ($uid) {
  266. $query->select('object_id')
  267. ->from('wx_chat')
  268. ->where('user_id', $uid)
  269. ->groupBy('object_id')
  270. ->orderByDesc('created_at');
  271. })->simplePaginate(10, FieldUtils::userInfoColums());
  272. if($data->isEmpty()){
  273. $data = WxUser::where('is_official', 1)->simplePaginate(10, FieldUtils::userInfoColums());
  274. }
  275. $result['user'] = $data;
  276. }
  277. }
  278. global $__MINI_GLOBAL_TENANT_ID__;
  279. if(Settings::get('app_h5_home', '')){
  280. $result['url'] = Settings::get('app_h5_home', '').'/#/pagesV/voter/detail/detail?id='.$voter->id . '&fph=1&from_user=' .$uid. '&tenant=' . $__MINI_GLOBAL_TENANT_ID__;
  281. }else{
  282. $result['url'] = env('APP_URL');
  283. }
  284. $the_only_path = '/pagesV/voter/detail/detail?id=' . $voter->id. '&fph=1&from_user=' .$uid. '&tenant=' . $__MINI_GLOBAL_TENANT_ID__;
  285. $share_types = Settings::get('app_voter_social_share_types', []);
  286. foreach (['refer', 'wechat', 'timeline', 'qq', 'qzone', 'weibo'] as $key){
  287. if(!in_array($key, $share_types)){
  288. continue;
  289. }
  290. if($key == 'refer'){
  291. $result['social'][] = [
  292. 'action' => 'slider',
  293. 'color' => Settings::get('--color-primary', '#FC3A72'),
  294. 'text' => '站内转发',
  295. 'icon' => 'mini-icon mini-zhanneizhuanfa',
  296. 'unicode' => 'e699',
  297. 'target_type' => 6,
  298. 'target_id' => '/pages/creat/index/creat?voter_id=' . $voter->id
  299. ];
  300. }else if($key == 'wechat'){
  301. $result['social'][] = [
  302. 'action' => 'wechat',
  303. 'color' => '#57be6a',
  304. 'text' => '微信好友',
  305. 'icon' => 'mini-icon mini-weixin',
  306. 'unicode' => 'e60b',
  307. 'share' => json_encode([
  308. 'provider' => 'weixin',
  309. 'type' => _empty_(Settings::get('app_meta_appid', '')) ? 0 : 5,
  310. 'title' => $voter_title,
  311. 'scene' => 'WXSceneSession',
  312. 'href' => $result['url'],
  313. 'imageUrl' => $voter->pic,
  314. 'miniProgram' => [
  315. 'id' => Settings::get('app_meta_appid', ''),
  316. 'path' => $the_only_path,
  317. 'type' => 0,
  318. 'webUrl' => $result['url']
  319. ]
  320. ]),
  321. ];
  322. }else if($key == 'timeline'){
  323. if($__MINI_GLOBAL_DEVICE__ != 'mp'){
  324. $result['social'][] = [
  325. 'action' => 'timeline',
  326. 'color' => '#80cc46',
  327. 'text' => '朋友圈',
  328. 'icon' => 'mini-icon mini-pengyouquan1',
  329. 'unicode' => 'e669',
  330. 'share' => json_encode([
  331. 'provider' => 'weixin',
  332. 'type' => 0,
  333. 'title' => $voter_title,
  334. 'summary' => $s_content,
  335. 'scene' => 'WXSceneTimeline',
  336. 'href' => $result['url'],
  337. 'imageUrl' => $voter->pic,
  338. 'miniProgram' => [
  339. 'id' => Settings::get('app_meta_appid', ''),
  340. 'path' => $the_only_path,
  341. 'type' => 0,
  342. 'webUrl' => $result['url']
  343. ]
  344. ])
  345. ];
  346. }
  347. }else if($key == 'qq'){
  348. if(!_empty_(Settings::get('app_qq_app_appid', ''))){
  349. if($__MINI_GLOBAL_DEVICE__ != 'mp') {
  350. $result['social'][] = [
  351. 'action' => 'qq',
  352. 'color' => '#54b4ef',
  353. 'text' => 'QQ好友',
  354. 'icon' => 'mini-icon mini-qq1',
  355. 'unicode' => 'e66c',
  356. 'share' => json_encode([
  357. 'provider' => 'qq',
  358. 'type' => 1,
  359. 'title' => $voter_title,
  360. 'summary' => $s_content,
  361. 'href' => $result['url'],
  362. 'imageUrl' => $voter->pic
  363. ])
  364. ];
  365. }
  366. }
  367. }else if($key == 'qzone'){
  368. if(!_empty_(Settings::get('app_qq_app_appid', ''))){
  369. if($__MINI_GLOBAL_DEVICE__ != 'mp') {
  370. $result['social'][] = [
  371. 'action' => 'qzone',
  372. 'color' => '#f7cf46',
  373. 'text' => 'QQ空间',
  374. 'icon' => 'mini-icon mini-Rrl_s_112',
  375. 'unicode' => 'e62a',
  376. 'share' => json_encode([
  377. 'provider' => 'qq',
  378. 'type' => 1,
  379. 'title' => $voter_title,
  380. 'href' => $result['url'],
  381. 'imageUrl' => $voter->pic
  382. ])
  383. ];
  384. }
  385. }
  386. }else if($key == 'weibo'){
  387. if(!_empty_(Settings::get('app_weibo_app_appid', ''))){
  388. if($__MINI_GLOBAL_DEVICE__ != 'mp') {
  389. $result['social'][] = [
  390. 'action' => 'weibo',
  391. 'color' => '#d4382a',
  392. 'text' => '微博',
  393. 'icon' => 'mini-icon mini-weibo',
  394. 'unicode' => 'e73c',
  395. 'share' => json_encode([
  396. 'provider' => 'sinaweibo',
  397. 'type' => 0,
  398. 'title' => $voter_title,
  399. 'href' => $result['url'],
  400. 'imageUrl' => $voter->pic
  401. ])
  402. ];
  403. }
  404. }
  405. }
  406. }
  407. $system_types = Settings::get('app_voter_social_system_types', ['edit', 'copyUrl', 'report' ]);
  408. // promotion
  409. foreach (['edit', 'copyUrl', 'report'] as $key){
  410. if(!in_array($key, $system_types)){
  411. continue;
  412. }
  413. if($key == 'showCode'){
  414. $result['other'][] = [
  415. 'text' => '生成海报',
  416. 'icon' => 'mini-icon mini-shengchenghaibao',
  417. 'action' => 'slider',
  418. 'unicode' => 'e697',
  419. 'target_type' => 6,
  420. 'target_id' => '/pagesZ/organize-voter/poster/poster?id=' . $voter->id
  421. ];
  422. }else if($key == 'edit'){
  423. if((is_array($voter->action_sheets) && in_array('编辑', $voter->action_sheets)) || $__MINI_GLOBAL_IS_ADMIN_SUPER__){
  424. $result['other'][] = [
  425. 'text' => '编辑',
  426. 'icon' => 'mini-icon mini-xie',
  427. 'unicode' => 'e6fd',
  428. 'action' => 'slider',
  429. 'target_type' => 6,
  430. 'target_id' => '/pagesV/voter/creat/creat?voter_id=' . $voter->id
  431. ];
  432. }
  433. }else if($key == 'copyUrl'){
  434. try {
  435. $the_only_path_arr = explode('?', $the_only_path);
  436. $url_link = Cache::remember(md5($the_only_path), 3600 * 24, function () use (&$wxlink, &$the_only_path_arr){
  437. return $wxlink->genWxUrllink($the_only_path_arr[0] ?? '', $the_only_path_arr[1] ?? '');
  438. });
  439. }catch (\Exception $e){
  440. $url_link = $result['url'];
  441. }
  442. $voter_group_text = '';
  443. $result['other'][] = [
  444. 'text' => '复制链接',
  445. 'icon' => 'mini-icon mini-fuzhilianjie',
  446. 'unicode' => 'e691',
  447. 'action' => 'copyUrl',
  448. 'copy' => '🌟'.$voter_title.'
  449. ⏰活动时间:'.$voter->start_time .' 至 '.$voter->end_time.'
  450. 📍报名'.$voter->player_called.':'.$voter->player_count.'
  451. 🏁发起人:'.$voter->master_user_name.'
  452. '.$voter_group_text.'
  453. - - - - - - - - - - - - - - - - - - - -
  454. 🌟选票活动:'.$url_link.'
  455. ',
  456. ];
  457. }else if($key == 'report'){
  458. if($voter_user_id != $uid){
  459. $result['other'][] = [
  460. 'text' => '举报',
  461. 'icon' => 'mini-icon mini-jubao',
  462. 'unicode' => 'e694',
  463. 'action' => 'slider',
  464. 'target_type' => 6,
  465. 'target_id' => '/pages/common/report?type=6&object_id=' . $voter->id
  466. ];
  467. }
  468. }
  469. }
  470. if((is_array($voter->action_sheets) && in_array('删除', $voter->action_sheets)) || $__MINI_GLOBAL_IS_ADMIN_SUPER__){
  471. $result['other'][] = [
  472. 'text' => '删除',
  473. 'icon' => 'mini-icon mini-shanchu211',
  474. 'unicode' => 'e6f3',
  475. 'action' => 'delete',
  476. 'voter_id' => $voter->id
  477. ];
  478. }
  479. // _logger_(__file__, __line__, $result);
  480. return $this->success($result);
  481. }
  482. private function voter_echo(Request &$request){
  483. $uid = $request->uid;
  484. if(_empty_($uid)){
  485. return $this->fail(503002);
  486. }
  487. $voter_id = (int)(_empty_default_($request->voter_id, 0));
  488. if(_empty_($voter_id)){
  489. return $this->fail(200001);
  490. }
  491. global $__MINI_GLOBAL_IS_ADMIN_SUPER__;
  492. $the_voter = WxVoter::find($voter_id);
  493. if(_empty_($the_voter)){
  494. return $this->fail(200003);
  495. }
  496. if(!$__MINI_GLOBAL_IS_ADMIN_SUPER__ && $the_voter->user_id != $uid){
  497. return $this->fail(200000);
  498. }
  499. if ($the_voter->user_total_limit > 0) {
  500. // 总限制存在
  501. $voteTimes = [1, $the_voter->user_total_limit - 1];
  502. } elseif ($the_voter->user_day_limit > 0) {
  503. // 每日限制存在
  504. $voteTimes = [0, $the_voter->user_day_limit - 1];
  505. } else {
  506. // 无限制
  507. $voteTimes = [0, 0];
  508. }
  509. $start_time = $the_voter->start_time;
  510. $end_time = $the_voter->end_time;
  511. $enter_start_time = $the_voter->enter_start_time;
  512. $enter_end_time = $the_voter->enter_end_time;
  513. // 将时间转为秒
  514. $start_time_unix = strtotime($start_time);
  515. $end_time_unix = strtotime($end_time);
  516. $enter_start_time_unix = strtotime($enter_start_time);
  517. $enter_end_time_unix = strtotime($enter_end_time);
  518. // 将时间转换为毫秒
  519. $start_time_ms = $start_time_unix * 1000;
  520. $end_time_ms = $end_time_unix * 1000;
  521. $enter_start_time_ms = $enter_start_time_unix * 1000;
  522. $enter_end_time_ms = $enter_end_time_unix * 1000;
  523. // 验证时间戳长度
  524. if (strlen((string)$start_time_ms) != 13 || strlen((string)$end_time_ms) != 13) {
  525. return $this->fail(200004, [], '时间戳格式错误');
  526. }
  527. $res_obj = [
  528. 'type' => 'update',
  529. 'id' => $the_voter->id,
  530. 'master_user_avatar' => $the_voter->master_user_avatar,
  531. 'master_user_name' => $the_voter->master_user_name,
  532. 'template_id' => $the_voter->template_id,
  533. 'title' => $the_voter->title,
  534. 'notice' => $the_voter->notice,
  535. 'vcontent' => $the_voter->content, // 由于传输参数不能是 content,加了个v
  536. 'banners' => $the_voter->banners,
  537. 'is_open_enter' => $the_voter->is_open_enter,
  538. 'is_exposure' => $the_voter->is_exposure,
  539. 'is_open_vote_comment' => $the_voter->is_open_vote_comment,
  540. 'is_open_player_comment' => $the_voter->is_open_player_comment,
  541. 'is_can_be_anonymous' => $the_voter->is_can_be_anonymous,
  542. 'is_hide_rank' => $the_voter->is_hide_rank,
  543. 'is_hide_vote_record' => $the_voter->is_hide_vote_record,
  544. 'is_hide_player_count' => $the_voter->is_hide_player_count,
  545. 'music_url' => $the_voter->music_url,
  546. 'music_name' => $the_voter->music_name,
  547. 'is_music_auto' => $the_voter->is_music_auto,
  548. 'start_time' => $start_time_ms,
  549. 'end_time' => $end_time_ms,
  550. 'enter_start_time' => $enter_start_time_ms,
  551. 'enter_end_time' => $enter_end_time_ms,
  552. 'user_day_limit' => $the_voter->user_day_limit,
  553. 'user_total_limit' => $the_voter->user_total_limit,
  554. 'player_called' => $the_voter->player_called,
  555. 'unit_called' => $the_voter->unit_called,
  556. 'main_background_image' => $the_voter->main_background_image,
  557. 'user_background_image' => $the_voter->user_background_image,
  558. 'background_color' => $the_voter->background_color,
  559. 'text_color' => $the_voter->text_color,
  560. 'main_color' => $the_voter->main_color,
  561. 'button_bg_color' => $the_voter->button_bg_color,
  562. 'button_text_color' => $the_voter->button_text_color,
  563. 'text_navigation_bar_color' => $the_voter->text_navigation_bar_color,
  564. 'voteTimes' => $voteTimes,
  565. ];
  566. return $this->success($res_obj);
  567. }
  568. private function voter_delete(Request &$request){
  569. $uid = $request->uid;
  570. if(_empty_($uid)){
  571. return $this->fail(503002);
  572. }
  573. $voter_id = (int)(_empty_default_($request->voter_id, 0));
  574. if(_empty_($voter_id)){
  575. return $this->fail(200001);
  576. }
  577. $the_voter = WxVoter::find($voter_id);
  578. if(_empty_($the_voter)){
  579. return $this->fail(200003);
  580. }
  581. if(!is_object_user_special($uid, $the_voter->tenant_id, true) && $the_voter->user_id != $uid){
  582. return $this->fail(200000);
  583. }
  584. DB::beginTransaction();
  585. try {
  586. // todo:
  587. WxVoter::where('id', $the_voter->id)->delete();
  588. WxVoterPlayer::where('voter_id', $the_voter->id)->delete();
  589. WxPost::where('voter_id', $the_voter->id)->update(['is_examine'=>2, 'overrule_content'=>'选票已被删除']);
  590. DB::commit();
  591. return $this->success();
  592. } catch (\Exception $e) {
  593. DB::rollBack();
  594. _logger_(__file__, __line__, $e->getMessage());
  595. return $this->fail(200002);
  596. }
  597. }
  598. private function player_ballot(Request $request){
  599. $uid = $request->uid;
  600. $voter_id = _empty_default_($request->voter_id, 0);
  601. $player_id = _empty_default_($request->player_id, 0);
  602. $num = _empty_default_($request->num, 0);
  603. if(_empty_($voter_id) || _empty_($player_id) || _empty_($num)){
  604. return $this->fail(200001);
  605. }
  606. $voter = WxVoter::find($voter_id);
  607. if ($voter) {
  608. // 使用Carbon进行日期时间比较
  609. $now = Carbon::now();
  610. $endTime = Carbon::parse($voter->end_time);
  611. $startTime = Carbon::parse($voter->start_time);
  612. if ($now->gt($endTime)) {
  613. // 当前时间已超过end_time
  614. return $this->fail(200046, [], '当前时间已超过投票截止时间');
  615. } else {
  616. // 当前时间未超过end_time
  617. }
  618. if ($now->gt($startTime)) {
  619. // 当前时间已超过start_time
  620. } else {
  621. // 当前时间未超过start_time
  622. return $this->fail(200046, [], '当前时间未达到投票开始时间');
  623. }
  624. } else {
  625. return $this->fail(200003, [], '选票活动不存在');
  626. }
  627. $player = WxVoterPlayer::find($player_id);
  628. if(!$player){
  629. return $this->fail(200003, [], '选手不存在');
  630. }
  631. $rest = $this->get_user_voter_rest_ballot($voter, $uid);
  632. if($rest < $num){
  633. return $this->fail(200046, [], '您剩余的票数为'.$rest.',不足以本次投票');
  634. }
  635. DB::beginTransaction();
  636. try {
  637. // todo:
  638. $ballot = new WxVoterPlayerBallot();
  639. $ballot->user_id = $uid;
  640. $ballot->voter_id = $voter->id;
  641. $ballot->player_id = $player->id;
  642. $ballot->num = $num;
  643. $r = $ballot->save();
  644. if($r){
  645. DB::commit();
  646. Cache::forget('user:gird_voter:tip:'.$uid);
  647. return $this->success();
  648. }
  649. DB::rollBack();
  650. return $this->fail(200002);
  651. } catch (\Exception $e) {
  652. DB::rollBack();
  653. _logger_(__file__, __line__, $e->getMessage());
  654. return $this->fail(200002);
  655. }
  656. }
  657. private function get_user_voter_rest_ballot(WxVoter $voter, $user_id){
  658. $voter_id = $voter->id; // 需要查询的voter_id
  659. $todayStart = Carbon::today()->startOfDay();
  660. $todayEnd = Carbon::today()->endOfDay();
  661. $sums = WxVoterPlayerBallot::selectRaw('
  662. SUM(num) as historySum,
  663. SUM(CASE WHEN created_at BETWEEN ? AND ? THEN num ELSE 0 END) as todaySum',
  664. [$todayStart, $todayEnd])
  665. ->where('user_id', $user_id)
  666. ->where('voter_id', $voter_id)
  667. ->first();
  668. // user_day_limit,user_total_limit
  669. if($voter->user_total_limit > 0){
  670. $rest = $voter->user_total_limit - $sums->historySum;
  671. }else{
  672. $rest = $voter->user_day_limit - $sums->todaySum;
  673. }
  674. if($rest >= 0){
  675. return $rest;
  676. }
  677. return 0;
  678. }
  679. private function voter_player_push(Request $request){
  680. $voter_id = _empty_default_($request->voter_id, 0);
  681. $uid = $request->uid;
  682. $show_name = _empty_default_($request->show_name, '');
  683. $work_name = _empty_default_($request->work_name, '');
  684. $work_desc = _empty_default_($request->work_desc, '');
  685. $video_url = _empty_default_($request->video_url, '');
  686. $video_cover = _empty_default_($request->video_cover, '');
  687. $img_urls = _empty_default_($request->img_urls, []);
  688. $contact_text = _empty_default_($request->contact_text, '');
  689. // 判断当前时间是否在报名截止时间
  690. $wxVoter = WxVoter::find($voter_id);
  691. if ($wxVoter) {
  692. // 使用Carbon进行日期时间比较
  693. $now = Carbon::now();
  694. $enterEndTime = Carbon::parse($wxVoter->enter_end_time);
  695. $enterStartTime = Carbon::parse($wxVoter->enter_start_time);
  696. if ($now->gt($enterEndTime)) {
  697. // 当前时间已超过enter_end_time
  698. return $this->fail(200046, [], '当前时间已超过报名截止时间');
  699. } else {
  700. // 当前时间未超过enter_end_time
  701. }
  702. if ($now->gt($enterStartTime)) {
  703. // 当前时间已超过enter_start_time
  704. } else {
  705. // 当前时间未超过enter_start_time
  706. return $this->fail(200046, [], '当前时间未达到报名开始时间');
  707. }
  708. } else {
  709. return $this->fail(200003, [], '选票活动不存在');
  710. }
  711. if(_empty_($show_name)){
  712. return $this->fail(200004, [], '请输入展示名字');
  713. }
  714. $img_state_change_list = [];
  715. $img_urls__ = [];
  716. if(is_string($img_urls)){
  717. $img_urls = json_decode($img_urls, true);
  718. }
  719. if(_empty_($img_urls) || !is_array($img_urls)){
  720. return $this->fail(200004, [], '未上传图片');
  721. }
  722. foreach ($img_urls as $url){
  723. $url = stripslashes($url);
  724. $img_urls__[] = $url;
  725. $img_state_change_list[] = $url;
  726. }
  727. if(_empty_($video_url)){
  728. $video_cover = '';
  729. }
  730. if($video_cover){
  731. $img_state_change_list[] = $video_cover;
  732. $img_state_change_list[] = $video_url;
  733. }
  734. $voterplayer = WxVoterPlayer::withTrashed()->where('user_id', $uid)->where('voter_id', $voter_id)->first();
  735. if($voterplayer){
  736. if ($voterplayer->trashed()) {
  737. $voterplayer->restore();
  738. }
  739. return $this->fail(200010, [], '你已经报名过了,请联系管理员');
  740. }
  741. $current_relative_id = WxVoterPlayer::withTrashed()->where('voter_id', $voter_id)->max('relative_id');
  742. if(_empty_($current_relative_id)){
  743. $current_relative_id = 0;
  744. }
  745. DB::beginTransaction();
  746. try {
  747. // todo:
  748. $voterplayer = new WxVoterPlayer();
  749. $voterplayer->show_name = $show_name;
  750. $voterplayer->voter_id = $voter_id;
  751. $voterplayer->relative_id = $current_relative_id + 1;
  752. $voterplayer->user_id = $uid;
  753. $voterplayer->work_name = $work_name;
  754. $voterplayer->work_desc = $work_desc;
  755. $voterplayer->video_url = $video_url;
  756. $voterplayer->video_cover = $video_cover;
  757. $voterplayer->contact_text = $contact_text;
  758. $voterplayer->img_urls = json_encode($img_urls__);
  759. $voterplayer->status = 0;
  760. $r = $voterplayer->save();
  761. if($r){
  762. Utils::image_state_change($img_state_change_list, 1);
  763. UserUtils::assistant_notice_review(105, $voterplayer->id);
  764. UserUtils::assistant_notice_review(105, $voterplayer->id, $wxVoter->user_id);
  765. DB::commit();
  766. Cache::forget('user:gird_voter:tip:'.$uid);
  767. return $this->success($voter_id);
  768. }
  769. DB::rollBack();
  770. return $this->fail(200002);
  771. } catch (\Exception $e) {
  772. DB::rollBack();
  773. _logger_(__file__, __line__, $e->getMessage());
  774. return $this->fail(200002);
  775. }
  776. }
  777. private function voter_push(Request $request){
  778. global $__MINI_GLOBAL_TENANT_ID__,$__MINI_GLOBAL_DEVICE__,$__MINI_GLOBAL_IS_ADMIN_SUPER__;
  779. $uid = $request->uid;
  780. $update_voter_id = _empty_default_($request->id, 0);
  781. if($update_voter_id > 0){
  782. $the_voter = WxVoter::find($update_voter_id);
  783. if(_empty_($the_voter)){
  784. return $this->fail(200003);
  785. }
  786. if(!is_object_user_special($uid, $the_voter->tenant_id, true) && $the_voter->user_id != $uid){
  787. return $this->fail(200000);
  788. }
  789. if(WxVoterPlayer::where('voter_id', $the_voter->id)->where('status', 1)->count() > 0){
  790. return $this->fail(200010, [], '已经有人报名的选票不能二次修改');
  791. }
  792. }
  793. $title = _empty_default_($request->title, '');
  794. $notice = _empty_default_($request->notice, '');
  795. $content = _empty_default_($request->vcontent, '');
  796. $banners = _empty_default_($request->banners, '');
  797. $start_time = _empty_default_($request->start_time, 0);
  798. $end_time = _empty_default_($request->end_time, 0);
  799. $template_id = _empty_default_($request->template_id, 0);
  800. $voteTimes = _empty_default_($request->voteTimes, []);
  801. $master_user_avatar = _empty_default_($request->master_user_avatar, '');
  802. $master_user_name = _empty_default_($request->master_user_name, '');
  803. $is_exposure = _empty_($request->is_exposure) ? 0 : 1;
  804. if(_empty_($title) || _empty_($content) || _empty_($template_id)){
  805. return $this->fail(200001);
  806. }
  807. if(is_string($banners)){
  808. $banners = json_decode($banners, true);
  809. }else if(is_array($banners)){
  810. }else{
  811. return $this->fail(200004);
  812. }
  813. if(_empty_($banners) || !is_array($banners) || _empty_($banners)){
  814. return $this->fail(200001);
  815. }
  816. if(_empty_($start_time) || _empty_($end_time)){
  817. return $this->fail(200001);
  818. }
  819. if(strlen($start_time) != 13 || strlen($end_time) != 13){
  820. return $this->fail(200004);
  821. }
  822. $start_time = floor($start_time / 1000);
  823. $end_time = floor($end_time / 1000);
  824. // 检查合理性-毫秒
  825. if($end_time - $start_time < 10){
  826. return $this->fail(200004, [], '无法创建持续时间不足10秒钟的选票');
  827. }
  828. if($end_time < time()){
  829. return $this->fail(200004, [], '选票结束时间小于当前时间');
  830. }
  831. // master
  832. $master = WxUser::find($uid);
  833. $template = WxVoterTemplate::find($template_id);
  834. if(!$template){
  835. return $this->fail(200004, [], '选票模板不存在');
  836. }
  837. $img_state_change_list = [];
  838. $img_urls = [];
  839. foreach ($banners as $banner){
  840. if(strpos($banner, 'http') === 0){
  841. $banner = stripslashes($banner);
  842. $img_urls[] = $banner;
  843. $img_state_change_list[] = $banner;
  844. }
  845. }
  846. if(is_string($voteTimes)){
  847. $voteTimes = json_decode($voteTimes, true);
  848. }
  849. if(_empty_($voteTimes) || !is_array($voteTimes) || count($voteTimes) != 2){
  850. return $this->fail(200004, [], '选票次数限制错误');
  851. }
  852. if(!in_array($voteTimes[0], [0, 1])){
  853. return $this->fail(200004, [], '选票次数限制错误0');
  854. }
  855. // 1-50次
  856. if($voteTimes[1] < 0 || $voteTimes[1] > 49){
  857. return $this->fail(200004, [], '选票次数限制错误1');
  858. }
  859. $voteTimes[1] += 1;
  860. if($master_user_avatar){
  861. $img_state_change_list[] = $master_user_avatar;
  862. }
  863. DB::beginTransaction();
  864. try {
  865. // todo:
  866. if($update_voter_id > 0){
  867. $voter = WxVoter::find($update_voter_id);
  868. }else{
  869. $voter = new WxVoter();
  870. $voter->template_id = $template->id;
  871. $voter->main_background_image = $template->main_background_image;
  872. $voter->user_background_image = $template->user_background_image;
  873. $voter->background_color = $template->background_color;
  874. $voter->text_color = $template->text_color;
  875. $voter->main_color = $template->main_color;
  876. $voter->button_bg_color = $template->button_bg_color;
  877. $voter->button_text_color = $template->button_text_color;
  878. $voter->text_navigation_bar_color = $template->text_navigation_bar_color;
  879. if($__MINI_GLOBAL_TENANT_ID__ > 0){
  880. $voter->tenant_id = $__MINI_GLOBAL_TENANT_ID__;
  881. }
  882. }
  883. $voter->user_id = $master->id;
  884. $voter->master_user_avatar = stripslashes($master_user_avatar) ?: $master->user_avatar;
  885. $voter->master_user_name = $master_user_name ?: $master->user_avatar;
  886. $voter->title = $title;
  887. $voter->notice = $notice;
  888. $voter->content = $content;
  889. $voter->banners = json_encode($img_urls);
  890. $voter->start_time = timetostr($start_time);
  891. $voter->end_time = timetostr($end_time);
  892. $voter->enter_start_time = timetostr($start_time);
  893. $voter->enter_end_time = timetostr($end_time);
  894. if($voteTimes[0] == 1){
  895. $voter->user_total_limit = $voteTimes[1];
  896. }else{
  897. $voter->user_day_limit = $voteTimes[1];
  898. }
  899. $voter->player_called = '选手';
  900. $voter->unit_called = '票';
  901. $voter->is_exposure = $is_exposure;
  902. $voter->status = $update_voter_id > 0 ? 1 : 0;
  903. $r = $voter->save();
  904. if($r){
  905. $voter_id = $voter->id;
  906. Utils::image_state_change($img_state_change_list, 1);
  907. if($update_voter_id > 0){
  908. }else{
  909. if($is_exposure == 1){
  910. $post_id = PostsRepositores::add($master->id, 1, '', '我发布了一个选票~', 0, null, null, !_empty_('') ? [['url'=>'']] : [], '', null, null, null, null,
  911. null, null, null, null, $__MINI_GLOBAL_DEVICE__, null, null, null, [], null, false, $voter->id);
  912. if ($post_id) {
  913. CalculateLikesNumJob::dispatch($post_id);
  914. UpdatePostVideoIdJob::dispatch($post_id);
  915. CalculateFollowsNumJob::dispatch($uid);
  916. Redis::sadd('realtime:post:set', $post_id);
  917. UpdatePostOnlyTextJob::dispatch(0);
  918. UserUtils::add_user_experience($uid, 15, 10);
  919. }
  920. }
  921. UserUtils::assistant_notice_review(104, $voter_id);
  922. }
  923. DB::commit();
  924. Cache::forget('user:gird_voter:tip:'.$master->id);
  925. return $this->success($voter_id);
  926. }
  927. DB::rollBack();
  928. return $this->fail(200002);
  929. } catch (\Exception $e) {
  930. DB::rollBack();
  931. _logger_(__file__, __line__, $e->getMessage());
  932. return $this->fail(200002);
  933. }
  934. }
  935. public function template_info(Request $request){
  936. $template_id = _empty_default_($request->id, 0);
  937. if(_empty_($template_id)){
  938. return $this->fail(200001);
  939. }
  940. $template = WxVoterTemplate::find($template_id);
  941. if($template){
  942. return $this->success($template);
  943. }
  944. return $this->fail(200003);
  945. }
  946. public function player_detail(Request $request){
  947. $uid = $request->uid;
  948. $player_id = _empty_default_($request->id, 0);
  949. if(_empty_($player_id)){
  950. return $this->fail(200001);
  951. }
  952. $player = WxVoterPlayer::find($player_id);
  953. if(!$player){
  954. return $this->fail(200003);
  955. }
  956. $voter_id = $player->voter_id;
  957. $voter = WxVoter::find($voter_id);
  958. if(!$voter){
  959. return $this->fail(200003);
  960. }
  961. $player->user = UserUtils::get_cached_user($player->user_id);
  962. $this->voter_item_process($voter, $uid);
  963. $player->voter = $voter;
  964. return $this->success($player);
  965. }
  966. public function player_list(Request $request){
  967. $voter_id = _empty_default_($request->voter_id, 0);
  968. if(_empty_($voter_id)){
  969. return $this->fail(200001);
  970. }
  971. $keyword = _empty_default_($request->keyword, '');
  972. $orderBy = _empty_default_($request->orderBy, 'created_at');
  973. $order = _empty_default_($request->order, 'desc');
  974. if(!in_array($orderBy, ['created_at', 'num', 'default'])){
  975. $orderBy = 'created_at';
  976. }
  977. if(!in_array($order, ['desc', 'asc'])){
  978. $order = 'desc';
  979. }
  980. if($orderBy == 'created_at' || $orderBy == 'default'){
  981. $query = WxVoterPlayer::where('status', 1);
  982. if($keyword){
  983. $query = $query->where(function ($query_) use ($keyword) {
  984. $query_->orWhere('relative_id', $keyword)
  985. ->orWhere('show_name', 'like', '%' . $keyword . '%');
  986. });
  987. }
  988. if($orderBy == 'created_at'){
  989. $query = $query->orderBy($orderBy, $order);
  990. }
  991. if($voter_id){
  992. $query = $query->where('voter_id', $voter_id);
  993. }
  994. }else if($orderBy == 'num'){
  995. $query = WxVoterPlayer::select('wx_voter_player.*')
  996. ->leftJoin('wx_voter_player_ballot', 'wx_voter_player.id', '=', 'wx_voter_player_ballot.player_id')
  997. ->where([['wx_voter_player.status', '=', 1], ['wx_voter_player.voter_id', '=', $voter_id]])
  998. ->groupBy('wx_voter_player.id')
  999. ->orderByDesc(
  1000. DB::raw('SUM(wx_voter_player_ballot.num)')
  1001. );
  1002. }
  1003. $players = $query->simplePaginate(10);
  1004. if($players){
  1005. $players->map(function ($v, $k){
  1006. $this->player_process($v);
  1007. return $v;
  1008. });
  1009. return $this->success($players);
  1010. }
  1011. return $this->fail(200003);
  1012. }
  1013. private function player_process(WxVoterPlayer &$player){
  1014. if($player->video_cover){
  1015. $player->pic = $player->video_cover . '?imageMogr2/thumbnail/1000x';
  1016. }else if($player->img_urls){
  1017. $player->pic = $player->img_urls[0] . '?imageMogr2/thumbnail/1000x';
  1018. }
  1019. $player->ballot_total = WxVoterPlayerBallot::where('voter_id', $player->voter_id)->where('player_id', $player->id)->sum('num');
  1020. $player->user = UserUtils::get_cached_user($player->user_id);
  1021. }
  1022. public function template_list(Request $request){
  1023. $templates = WxVoterTemplate::where('status', 1)->orderBy('created_at','desc')->select('id','name','cover')->simplePaginate(6);
  1024. if($templates){
  1025. return $this->success($templates);
  1026. }
  1027. return $this->fail(200003);
  1028. }
  1029. }