CommonController.php 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625
  1. <?php
  2. namespace App\Http\Controllers\Api;
  3. use App\Http\Controllers\Api\Repositories\PostsRepositores;
  4. use App\Http\Controllers\Api\Repositories\WxCircleRepositores;
  5. use App\Http\Requests\Api\PostsRequests\CircleRequest;
  6. use App\Jobs\Icon\UpdateIconImgWHJob;
  7. use App\Jobs\System\CheckBatchCahceDataLossJob;
  8. use App\Jobs\TopicImgJob;
  9. use App\Jobs\UserInputSafeCheckJob;
  10. use App\Lib\Classes\AcAutomation;
  11. use App\Lib\WeApp\WeApp;
  12. use App\Models\Circle\WxCircle;
  13. use App\Models\Posts\WxPost;
  14. use App\Models\Posts\WxPostsTag;
  15. use App\Models\Posts\WxTag;
  16. use App\Models\WxActivity;
  17. use App\Models\WxCaptchaImg;
  18. use App\Models\WxIcon;
  19. use App\Models\WxPageEvent;
  20. use App\Models\WxQuestion;
  21. use App\Models\WxTenant;
  22. use App\Wen\Utils\AdminUtils;
  23. use App\Wen\Utils\BaiduUtils;
  24. use App\Wen\Utils\CircleUtils;
  25. use App\Wen\Utils\FieldUtils;
  26. use App\Wen\Utils\ImageUtils;
  27. use App\Wen\Utils\PostUtils;
  28. use App\Wen\Utils\RealtimeUtils;
  29. use App\Wen\Utils\SearchUtils;
  30. use App\Wen\Utils\Settings;
  31. use App\Wen\Utils\ShopUtils;
  32. use App\Wen\Utils\UserUtils;
  33. use App\Wen\Utils\Utils;
  34. use App\Http\Controllers\Api\Repositories\WxSearchRepositores;
  35. use App\Models\WxClause;
  36. use App\Models\WxSearch;
  37. use App\Models\WxSlideshow;
  38. use App\Models\User\WxUser;
  39. use Illuminate\Http\Request;
  40. use Illuminate\Support\Facades\Cache;
  41. use Illuminate\Support\Facades\DB;
  42. use Illuminate\Support\Str;
  43. use Laravel\Socialite\Facades\Socialite;
  44. class CommonController extends BaseController
  45. {
  46. /** 把日志写到公共日志
  47. * @param Request $request
  48. * @return \Illuminate\Http\JsonResponse
  49. */
  50. public function putLog(Request $request){
  51. $log = $request->log;
  52. _logger_(__file__, __line__, $log);
  53. return $this->success();
  54. }
  55. public function tenants(Request $request){
  56. $latitude = $request->latitude;
  57. $longitude = $request->longitude;
  58. $keyword = _empty_default_($request->keyword, '');
  59. $uid = $request->uid;
  60. if(_empty_($latitude) && _empty_($longitude)){
  61. if($uid > 0){
  62. $user = UserUtils::get_cached_user($uid);
  63. if($user && _abs(_array_key($user, 'latitude', 0)) > 0 && _abs(_array_key($user, 'longitude', 0)) > 0){
  64. $latitude = $user['latitude'];
  65. $longitude = $user['longitude'];
  66. }else{
  67. // return $this->fail(200001);
  68. }
  69. }else{
  70. // return $this->fail(200001);
  71. }
  72. }
  73. try {
  74. $is_multi_site = Settings::get('is_multi_site', 0);
  75. $query = WxTenant::where('status', 0);
  76. if($is_multi_site == 1){
  77. $query = $query->where('tenant_id', '!=', 999);
  78. }else if($is_multi_site == 2){
  79. }else if($is_multi_site == 3){
  80. $query = $query->where('tenant_id', '!=', 0)->where('tenant_id', '!=', 999);
  81. }else{
  82. $query = $query->where('tenant_id', 0);
  83. }
  84. if($keyword){
  85. $query = $query->where(function ($query) use ($keyword) {
  86. if(is_numeric($keyword)){
  87. $query->orWhere('name', 'like', '%' . $keyword . '%')
  88. ->orWhere('short', 'like', '%' . $keyword . '%')
  89. ->orWhere('tenant_id', $keyword);
  90. }else{
  91. $query->orWhere('name', 'like', '%' . $keyword . '%')
  92. ->orWhere('short', 'like', '%' . $keyword . '%');
  93. }
  94. });
  95. }
  96. if(_abs($latitude) > 0 && _abs($longitude) > 0){
  97. $tenants = $query->select(DB::raw('*, ( 6371 * acos( cos( radians('.$latitude.') ) * cos( radians( add_latitude ) ) * cos( radians( add_longitude ) - radians('.$longitude.') ) + sin( radians('.$latitude.') ) * sin( radians( add_latitude ) ) ) ) AS distance'))
  98. ->orderBy('distance')->orderBy('order', 'desc')->orderBy('tenant_id', 'desc')->get();
  99. if($uid > 0){
  100. WxUser::where('id', $uid)->update(['longitude'=>$longitude, 'latitude'=>$latitude]);
  101. Cache::forget('get:cached:user:'.$uid);
  102. }
  103. }else{
  104. $tenants = $query->orderBy('order', 'desc')->orderBy('tenant_id', 'desc')->get();
  105. }
  106. if($tenants){
  107. $tenants->map(function ($v){
  108. global $__MINI_GLOBAL_TENANTS_ARR__;
  109. if(in_array($v->tenant_id, $__MINI_GLOBAL_TENANTS_ARR__)){
  110. $v->auth = true;
  111. }else{
  112. $v->auth = false;
  113. }
  114. if($v->distance && $v->distance > 0){
  115. $v->distance = (int)(1000 * $v->distance);
  116. if($v->distance < 10){
  117. $v->distance = '<10m';
  118. }else if($v->distance >= 1000 && $v->distance <= 200000){
  119. $v->distance = '<'. round($v->distance / 1000, 2).'km';
  120. }else if($v->distance > 200000){
  121. $v->distance = round($v->distance / 1000, 2).'km';
  122. }else{
  123. $v->distance = '<'.(int)$v->distance.'m';
  124. }
  125. }else{
  126. $v->distance = '';
  127. }
  128. return $v;
  129. });
  130. }
  131. return $this->success($tenants);
  132. }catch (\Exception $e){
  133. _logger_(__file__, __line__, $e->getMessage());
  134. return $this->fail(200006);
  135. }
  136. }
  137. public function download(Request $request){
  138. $path = $request->path;
  139. if(file_exists(public_path('storage/'.$path))){
  140. return response()->download(public_path('storage/'.$path));
  141. }else{
  142. return $this->fail(200003);
  143. }
  144. }
  145. public function clause(Request $request){
  146. $id = $request->id;
  147. if(_empty_($id)){
  148. return $this->fail(200001);
  149. }
  150. $clause = WxClause::find($id);
  151. if($clause){
  152. return view('common/default', ['title' => $clause->title, 'body'=>$clause->content]);
  153. }
  154. return $this->fail(200003);
  155. }
  156. public function express_range(){
  157. return $this->success(ShopUtils::get_expree_name_range());
  158. }
  159. /**
  160. * 搜索
  161. * @param Request $request
  162. * type 0:笔记;1:圈子;2:用户 3:商品
  163. */
  164. public function search(Request $request)
  165. {
  166. $keyword = $request->keyword;
  167. $type = $request->type;
  168. $uid = $request->uid;
  169. $is_tenant = _empty_default_($request->isTenant, false);
  170. if(_empty_($is_tenant)){
  171. $is_tenant = false;
  172. }else{
  173. $is_tenant = true;
  174. }
  175. if(_empty_($uid)){
  176. $uid = 0;
  177. }
  178. if(_empty_($type, true)){
  179. return $this->fail(200001);
  180. }
  181. if(_empty_($keyword)){
  182. if($type == 1 || $type == 3){
  183. }else{
  184. return $this->fail(200001);
  185. }
  186. }
  187. _limit_user('search', $uid, 40);
  188. $limit = $request->input('limit', 10);
  189. $keyword_actree = (SearchUtils::is_use_es() && $keyword) ? new AcAutomation(SearchUtils::split_keywords($keyword)) : null;
  190. if ($type == 0) {
  191. $data = SearchUtils::search_post($keyword_actree, $keyword, $uid, $limit, $is_tenant);
  192. } else if ($type == 1) {
  193. if($keyword){
  194. $data = SearchUtils::search_cicle($keyword_actree, $keyword, $uid, $limit, $is_tenant);
  195. }else{
  196. $follow = _empty_default_($request->follow, 0);
  197. if($follow == -1){
  198. $app_find_tab = Settings::get('app_find_tab', []);
  199. if(_empty_($app_find_tab) || _empty_($app_find_tab[0])){
  200. return $this->fail(200004, [], '请先去后台[移动端-发现-圈子发现页-tab]进行配置');
  201. }
  202. $follow = $app_find_tab[0]['follow_status'];
  203. $orderBy = $app_find_tab[0]['orderBy'];
  204. $order = $app_find_tab[0]['order'];
  205. $tags = $app_find_tab[0]['tags'];
  206. if(_empty_($orderBy)){
  207. $orderBy = 'created_at';
  208. }
  209. $master = $app_find_tab[0]['master'] ?? 0;
  210. }else{
  211. if(!in_array($follow, [0, 1, 2])){
  212. return $this->fail(200004);
  213. }
  214. $orderBy = _empty_default_($request->orderBy, 'created_at');
  215. if(!in_array($orderBy, ['created_at', 'last_publish_at', 'last_enter_at', 'total_post_count', 'total_comment_count', 'follow_at', 'count_circle_follow', 'count_pay_content'])){
  216. return $this->fail(200004);
  217. }
  218. $order = _empty_default_($request->order, 'desc');
  219. if(!in_array($order, ['desc', 'asc'])){
  220. return $this->fail(200004);
  221. }
  222. $tags = _empty_default_($request->tags, '');
  223. $master = _empty_default_($request->master, 0);
  224. }
  225. if(is_string($tags)){
  226. $tags = explode(',', $tags);
  227. }
  228. if($master == 1){
  229. $master = 1;
  230. }else{
  231. $master = 0;
  232. }
  233. $tags_ = [];
  234. if(is_array($tags) && $tags){
  235. foreach ($tags as $tag){
  236. $tag = (int)$tag;
  237. if($tag > 0){
  238. $tags_[] = $tag;
  239. }
  240. }
  241. }
  242. $data = CircleUtils::circle_filter($is_tenant, $follow, $tags, $orderBy, $order, $master);
  243. }
  244. } else if($type == 2){
  245. $data = SearchUtils::search_user($keyword_actree, $keyword, $uid, true, $limit, $is_tenant);
  246. } else if($type == 3){
  247. if($keyword){
  248. $data = SearchUtils::search_goods($keyword_actree, $keyword, $uid, $limit);
  249. }else{
  250. $follow = _empty_default_($request->follow, 0);
  251. if($follow == -1){
  252. $app_find_tab = Settings::get('app_find2_tab', []);
  253. if(_empty_($app_find_tab) || _empty_($app_find_tab[0])){
  254. return $this->fail(200004, [], '请先去后台[移动端-商品发现页-tab]进行配置');
  255. }
  256. $follow = $app_find_tab[0]['follow_status'];
  257. $orderBy = $app_find_tab[0]['orderBy'];
  258. $order = $app_find_tab[0]['order'];
  259. $ids = $app_find_tab[0]['ids'];
  260. $types = $app_find_tab[0]['types'];
  261. if(is_string($types)){
  262. $types = json_decode($types, true);
  263. }
  264. if(_empty_(end($types))){
  265. array_pop($types);
  266. }
  267. if(_empty_($types)){
  268. $types = [];
  269. }
  270. if(_empty_($orderBy)){
  271. $orderBy = 'created_at';
  272. }
  273. $master = $app_find_tab[0]['master'] ?? 0;
  274. }else{
  275. if(!in_array($follow, [0, 1, 2])){
  276. return $this->fail(200004);
  277. }
  278. $orderBy = _empty_default_($request->orderBy, 'created_at');
  279. if(!in_array($orderBy, ['created_at', 'order', 'last_enter_at', 'follow_shop_at', 'buys'])){
  280. return $this->fail(200004);
  281. }
  282. $order = _empty_default_($request->order, 'desc');
  283. if(!in_array($order, ['desc', 'asc'])){
  284. return $this->fail(200004);
  285. }
  286. $ids = _empty_default_($request->ids, '');
  287. $master = _empty_default_($request->master, 0);
  288. $types = _empty_default_($request->types, '');
  289. if(is_string($types)){
  290. $types = explode(',', $types);
  291. }
  292. if(_empty_(end($types))){
  293. array_pop($types);
  294. }
  295. if(_empty_($types)){
  296. $types = [];
  297. }
  298. }
  299. if(is_string($ids)){
  300. $ids = explode(',', $ids);
  301. }
  302. if(is_string($types)){
  303. $types = explode(',', $types);
  304. }
  305. if($master == 1){
  306. $master = 1;
  307. }else{
  308. $master = 0;
  309. }
  310. $data = ShopUtils::goods_filter($is_tenant, $follow, $ids, $types, $orderBy, $order, $master);
  311. }
  312. }
  313. return $this->success($data);
  314. }
  315. /** 微信小程序预拉取
  316. * @param Request $request
  317. * @return \Illuminate\Http\JsonResponse
  318. */
  319. public function backgroundFetchPre(Request $request){
  320. $timestamp = $request->timestamp;
  321. if(time() - $timestamp > 60 ){
  322. return $this->fail(200009);
  323. }
  324. $path = $request->path;
  325. if($path){
  326. $path = str_replace('\\/', '/', $path);
  327. }
  328. $query = $request->query;
  329. $wx_scene = $request->scene;
  330. $uid = $request->uid;
  331. // ["1685360117","pages/tabbar/index/index",{},"1001",11691]
  332. if($path == 'pages/tabbar/index/index'){
  333. // 首页预拉取
  334. $data = PostsRepositores::list($uid, 10);
  335. _logger_(__file__, __line__, '预拉取......');
  336. return $this->success($data, 2009001);
  337. }
  338. return $this->success(['path'=>$path, 'query'=>$query]);
  339. }
  340. /** 微信小程序 周期性拉取
  341. * @param Request $request
  342. * @return \Illuminate\Http\JsonResponse
  343. *
  344. */
  345. public function backgroundFetchPeriod(Request $request){
  346. $timestamp = $request->timestamp;
  347. $uid = $request->uid;
  348. // 周期性拉取什么数据? 1、用户信息, 2、
  349. if($uid > 0){
  350. $login_user = WxUser::where('id', $uid)->first(FieldUtils::userInfoColums());
  351. if($login_user){
  352. // 超级管理员
  353. if($login_user->is_official){
  354. if(UserUtils::is_mini_supder_admin($login_user->id)){
  355. $login_user->is_official = 2;
  356. }
  357. }
  358. UserUtils::user_expend($login_user, true, true, true, true, 5);
  359. $time = time();
  360. $login_user->timeStamp = $time;
  361. return $this->success([
  362. 'user' => $login_user
  363. ]);
  364. }else{
  365. return $this->success(['test'=>'test']);
  366. }
  367. }else{
  368. return $this->success(['test'=>'test']);
  369. }
  370. }
  371. /**
  372. * 创建圈子
  373. * @param CircleRequest $request
  374. * @return \Illuminate\Http\JsonResponse
  375. * @throws \Illuminate\Auth\Access\AuthorizationException
  376. * @throws \Illuminate\Validation\ValidationException
  377. */
  378. public function createCircle(CircleRequest $request)
  379. {
  380. // 验证
  381. $request->validate('addMsg');
  382. $uid = $request->uid;
  383. _limit_user('add:circle', $uid, 10);
  384. if(!UserUtils::is_user_can_speak($uid)){
  385. return $this->fail(200043, [
  386. 'title' => '禁言中,无法言论',
  387. 'content' => '是否前往解除限制',
  388. 'confirmText' => '去解除',
  389. 'target_type' => 6,
  390. 'target_id' => '/pagesA/mine/unlock/unlock?user_id='.$uid
  391. ], '您当前处于禁言期间,无法言论');
  392. }
  393. $the_circle_id = _empty_default_($request->id, 0);
  394. $the_circle = null;
  395. if($the_circle_id > 0){
  396. // 修改圈子
  397. $the_circle = WxCircle::find($the_circle);
  398. if(_empty_($the_circle)){
  399. return $this->fail(200004);
  400. }
  401. $circle_user_id = $the_circle->user_id;
  402. if($circle_user_id != $uid && is_object_user_special($uid, $the_circle->tenant_id, true)){
  403. return $this->fail(200000, [], '您不是该圈的'.env('circle_user_call', '圈主'));
  404. }
  405. }else{
  406. $arr = UserUtils::user_action_permissions_check($uid,'create_circle');
  407. if($arr['code'] == 0){
  408. return $this->fail(200000, [], $arr['msg']);
  409. }
  410. }
  411. $circle_name = $request->circle_name;
  412. $circle_introduce = $request->circle_introduce;
  413. if($the_circle_id > 0){
  414. if($the_circle){
  415. if($the_circle->tenant_show == -1){
  416. $exists = WxCircle::where('circle_name', $circle_name)->where('id', '<>', $the_circle_id)->exists();
  417. if($exists){
  418. return $this->fail(200010, [], '请联系管理员,你的圈子属于全站圈子,但存在其他圈子名称重复问题');
  419. }
  420. }else{
  421. $exists = WxCircle::where('circle_name', $circle_name)->where('id', '<>', $the_circle_id)->where('tenant_show', -1)->exists();
  422. if($exists){
  423. return $this->fail(200010, [], '已经存在这个名称的全站'.env('circle_call', '圈子'));
  424. }
  425. $exists = WxCircle::where('circle_name', $circle_name)->where('id', '<>', $the_circle_id)->where('tenant_show', $the_circle->tenant_show)->exists();
  426. if($exists){
  427. return $this->fail(200010, [], '这个名称的'.env('circle_call', '圈子').'已经存在啦,您换一个吧');
  428. }
  429. }
  430. }
  431. }else{
  432. $exists = WxCircle::where('circle_name', $circle_name)->where('circle_state', 1)->exists();
  433. if($exists){
  434. return $this->fail(200010, [], '这个名称的'.env('circle_call', '圈子').'已经存在啦,您换一个吧');
  435. }
  436. }
  437. // 百度审核
  438. $need_manual_review = true;
  439. if(_empty_($circle_name) || _empty_($circle_introduce)){
  440. return $this->fail(200001);
  441. }
  442. $audit_create_cirlce = Settings::get('is_audit_create_cirlce', 0);
  443. if ($audit_create_cirlce == 0) {
  444. // 手动审核
  445. $need_manual_review = true;
  446. }else if($audit_create_cirlce == 2){
  447. // 机审
  448. $filter_result = BaiduUtils::text_filter($circle_name .' '. $circle_introduce);
  449. if($filter_result){
  450. if($filter_result['hit_level'] == 2){
  451. // 不合规
  452. return $this->fail(200016, ['tip'=>$filter_result['tip_list'], 'hit_word'=>$filter_result['hit_word']]);
  453. }else if($filter_result['hit_level'] == 0){
  454. // 审核通过
  455. $need_manual_review = false;
  456. }
  457. }
  458. }else{
  459. // 不审核
  460. $need_manual_review = false;
  461. }
  462. // (0审核中,1正常,2驳回)
  463. $circle_state = 1;
  464. if($need_manual_review && !UserUtils::is_mini_supder_admin($uid)){
  465. $circle_state = 0;
  466. }
  467. $circle_id = WxCircleRepositores::add($request->all(), $circle_state);
  468. if($circle_id){
  469. UserInputSafeCheckJob::dispatch($uid, $circle_name .' '. $circle_introduce);
  470. Utils::image_state_change([$request->head_portrait, $request->background_maps], 1);
  471. update_user_visit($uid, 2, $circle_id);
  472. if($circle_state === 0){
  473. UserUtils::assistant_notice_review(107, $circle_id);
  474. }
  475. return $this->success();
  476. }else{
  477. return $this->fail(200002);
  478. }
  479. }
  480. /*
  481. * app版本更新
  482. */
  483. public function appUpdate(Request $request){
  484. if(_empty_($request->versionName) || _empty_($request->type) ){
  485. return $this->fail(200001);
  486. }
  487. if($request->type == 1101){
  488. // 安卓
  489. $version = Settings::get('admin_app_android_update', []);
  490. }else{
  491. $version = Settings::get('admin_app_ios_update', []);
  492. }
  493. if(_empty_($version)){
  494. return $this->fail(200003);
  495. }
  496. $version = end($version);
  497. if(_version_compare($version['version'], $request->versionName) == '>'){
  498. /* res的数据说明
  499. * | 参数名称 | 一定返回 | 类型 | 描述
  500. * | -------------|--------- | --------- | ------------- |
  501. * | versionCode | y | int | 版本号 |
  502. * | versionName | y | String | 版本名称 |
  503. * | versionInfo | y | String | 版本信息 |
  504. * | forceUpdate | y | boolean | 是否强制更新 |
  505. * | downloadUrl | y | String | 版本下载链接(IOS安装包更新请放跳转store应用商店链接,安卓apk和wgt文件放文件下载链接) |
  506. */
  507. return $this->success(
  508. [
  509. 'versionCode' => 1,
  510. 'versionName' => $version['version'],
  511. 'versionInfo' => $version['desc'],
  512. 'updateType' => $version['type'] ?: 'solicit',
  513. 'downloadUrl' => $version['url']
  514. ]
  515. );
  516. }
  517. return $this->fail(200007);
  518. }
  519. /**
  520. * 统计搜索结果数量
  521. */
  522. public function searcheCountJson(Request $request)
  523. {
  524. $keyword = $request->keyword;
  525. $is_tenant = _empty_default_($request->isTenant, false);
  526. if(_empty_($is_tenant)){
  527. $is_tenant = false;
  528. }else{
  529. $is_tenant = true;
  530. }
  531. $hits = [];
  532. if($keyword){
  533. $trigger_word = Settings::get('app_search_trigger_word', []);
  534. if($trigger_word){
  535. foreach ($trigger_word as $word){
  536. if(_array_key($word, 'match', 1) == 1){
  537. if($keyword == $word['text']){
  538. $hits = $word;
  539. break;
  540. }
  541. }else if(_array_key($word, 'match', 1) == 2){
  542. // 包含匹配
  543. if(str_contains($keyword, $word['text'])){
  544. $hits = $word;
  545. break;
  546. }
  547. }
  548. }
  549. }
  550. }
  551. $posts_count = SearchUtils::search_post_count($keyword, $is_tenant);
  552. $circle_count = SearchUtils::search_circle_count($keyword, $is_tenant);
  553. $user_count = SearchUtils::search_user_count($keyword, $is_tenant);
  554. return $this->success(['posts_count'=>$posts_count, 'circle_count'=>$circle_count, 'user_count'=>$user_count, 'hits' => $hits]);
  555. }
  556. /*
  557. * 引导图
  558. */
  559. public function guide(Request $request){
  560. $admin_app_guide = Settings::get('admin_app_guide', []);
  561. if(_empty_($admin_app_guide)){
  562. return $this->fail(200003);
  563. }
  564. if(count($admin_app_guide) != 3){
  565. return $this->fail(200008);
  566. }
  567. return $this->success(['page1'=>[
  568. 'title' => _array_key($admin_app_guide[0], 'title', ''),
  569. 'desc' => _array_key($admin_app_guide[0], 'desc', ''),
  570. 'img' => _array_key($admin_app_guide[0], 'img', '')
  571. ], 'page2'=>[
  572. 'title' => _array_key($admin_app_guide[1], 'title', ''),
  573. 'desc' => _array_key($admin_app_guide[1], 'desc', ''),
  574. 'img' => _array_key($admin_app_guide[1], 'img', '')
  575. ], 'page3'=>[
  576. 'title' => _array_key($admin_app_guide[2], 'title', ''),
  577. 'desc' => _array_key($admin_app_guide[2], 'desc', ''),
  578. 'img' => _array_key($admin_app_guide[2], 'img', '')
  579. ]]);
  580. }
  581. /**
  582. * 热门搜索列表
  583. */
  584. public function hotSearch()
  585. {
  586. return $this->success(WxSearchRepositores::hot_search(16));
  587. }
  588. /**
  589. * 首页轮播搜索关键字列表
  590. */
  591. public function HomeCarousel()
  592. {
  593. return $this->success(explode('|', Settings::get('app_search_carousel', '')));
  594. }
  595. /**
  596. * 获取条款内容
  597. */
  598. public function getClauseDetail(Request $request)
  599. {
  600. $id = $request->id;
  601. $data = WxClause::where('id', $id)->first(['title','content']);
  602. if($data){
  603. return $this->success($data);
  604. }
  605. return $this->fail(200003);
  606. }
  607. public function getUrlLink(Request $request){
  608. $path = ltrim(trim(_empty_default_($request->path, '')), '/');
  609. $query = _empty_default_($request->query, '');
  610. $short_last_path = $path;
  611. if(!_empty_($query)){
  612. $short_last_path .= '?'.$path;
  613. }
  614. $url_link_path = '';
  615. if(!_empty_($path)){
  616. $url_link_path .= ('/'.$path);
  617. }
  618. $new_app = new WeApp();
  619. $wxlink = $new_app->getWxLink();
  620. try {
  621. $link = $wxlink->genWxShortlink($short_last_path, '', true);
  622. $url_link = $wxlink->genWxUrllink($url_link_path, $query);
  623. return $this->success(['short_link'=>$link, 'url_link'=>$url_link]);
  624. }catch (\Exception $e){
  625. return $this->fail(200004, [], $e->getMessage());
  626. }
  627. }
  628. public function getIcon(Request $request){
  629. $id = _empty_default_($request->id, 0);
  630. if(_empty_($id)){
  631. return $this->fail(200001);
  632. }
  633. $icon = WxIcon::find($id);
  634. if($icon){
  635. if(!_empty_($icon->img)){
  636. if($icon->img_width === null){
  637. UpdateIconImgWHJob::dispatch($icon->id);
  638. }
  639. }
  640. return $this->success($icon);
  641. }else{
  642. return $this->fail(200003);
  643. }
  644. }
  645. /**
  646. * 获取说明内容
  647. */
  648. public function getHelp(Request $request){
  649. $help_type = $request->type;
  650. if(!in_array($help_type, array_keys(FieldUtils::getQuestionTypes()))){
  651. return $this->fail(200003);
  652. }
  653. $result = [
  654. 'title' => FieldUtils::getQuestionTypes()[$help_type],
  655. 'questions' => []
  656. ];
  657. $questions = WxQuestion::where('type', $help_type)->orderBy('updated_at', 'desc')->limit(200)->get();
  658. if(_empty_($questions)){
  659. return $this->success($result);
  660. }
  661. $result['questions'] = $questions;
  662. return $this->success($result);
  663. }
  664. private function default_configData(){
  665. global $__MINI_GLOBAL_DEVICE__,$__MINI_GLOBAL_TENANT_ID__,$__MINI_GLOBAL_CURRENT_USER_ID__,$__MINI_GLOBAL_IS_ADMIN_SUPER__,$__MINI_GLOBAL_CURRENT_PLAYER_ID__;
  666. $app_share_format = json_decode(Cache::get('app_share_format', ''), true) ?? [];
  667. if(_empty_($app_share_format)){
  668. CheckBatchCahceDataLossJob::dispatch();
  669. }
  670. if($__MINI_GLOBAL_TENANT_ID__ > 0){
  671. if(is_array($app_share_format)){
  672. $multi_text_share = Settings::get('app_multi_index_text_share', '', true);
  673. if($multi_text_share){
  674. $app_share_format['app_share_right'] = $multi_text_share;
  675. }
  676. }
  677. }
  678. // 马甲账号
  679. $admin_played_users = json_decode(Cache::get(_multi_key('admin_played_users'), '')) ?? [];
  680. if($__MINI_GLOBAL_TENANT_ID__ > 0){
  681. // 分站模式下
  682. if($__MINI_GLOBAL_IS_ADMIN_SUPER__ || $__MINI_GLOBAL_CURRENT_PLAYER_ID__ > 0){
  683. $admin_played_users_primary = json_decode(Cache::get('admin_played_users', '')) ?? [];
  684. if($admin_played_users_primary){
  685. $admin_played_users = array_merge($admin_played_users_primary, $admin_played_users);
  686. }
  687. }
  688. }
  689. if(_empty_($admin_played_users)){
  690. // CheckBatchCahceDataLossJob::dispatch();
  691. }
  692. $played_users = explode(',', Settings::get('app_admin_played_users', '', true));
  693. $played_users_ = [];
  694. if($played_users){
  695. foreach ($played_users as $play_user){
  696. if($play_user > 0){
  697. $played_users_[] = (int)$play_user;
  698. }
  699. }
  700. }
  701. if($__MINI_GLOBAL_TENANT_ID__ > 0){
  702. // 分站模式下
  703. if($__MINI_GLOBAL_IS_ADMIN_SUPER__ || $__MINI_GLOBAL_CURRENT_PLAYER_ID__ > 0){
  704. $played_users_main = explode(',', Settings::get('app_admin_played_users', ''));
  705. if($played_users_main){
  706. foreach ($played_users_main as $play_user){
  707. if($play_user > 0){
  708. $played_users_[] = (int)$play_user;
  709. }
  710. }
  711. }
  712. }
  713. }
  714. if($played_users_){
  715. $played_users_ = array_unique($played_users_);
  716. }
  717. $app_page_animation = json_decode(Cache::get('app_page_animation', '[]'), true);
  718. if(_empty_($app_page_animation)){
  719. CheckBatchCahceDataLossJob::dispatch();
  720. }
  721. $config_app_post_list_footer = json_decode( Cache::get(_multi_key('config:app:post:list:footer'), '{ "left": [1], "right": [2,3,4] }') );
  722. if(_empty_($config_app_post_list_footer)){
  723. CheckBatchCahceDataLossJob::dispatch();
  724. }
  725. $img_all_style_names = json_decode(Cache::get('img_all_style_names', '[]'), true);
  726. $default_share = Settings::get('img_share_default');
  727. if($__MINI_GLOBAL_TENANT_ID__ > 0){
  728. $multi_img_share = Settings::get('app_multi_index_img_share', '', true);
  729. if($multi_img_share){
  730. $default_share = $multi_img_share;
  731. }
  732. }
  733. return [
  734. 'OK' => true,
  735. 'version' => Settings::get('__global_config_version__', 1),
  736. 'tab' => Settings::get('app_index_tab', [], true),
  737. 'app' => [
  738. 'multi' => Settings::get('is_multi_site', 0),
  739. 'tenants' => Utils::get_online_tenants(),
  740. 'mode' => is_mini_examine_mode() ? 'examine' : 'normal',
  741. 'basic' => [
  742. 'intro_page' => Settings::get('admin_app_introduce_page'),
  743. 'url_schemes' => Settings::get('admin_app_url_schemes')
  744. ],
  745. 'wechat' => [
  746. 'app' => [
  747. 'appid' => Settings::get('app_app_id'),
  748. ],
  749. 'mini' => [
  750. 'appid' => Settings::get('app_id'),
  751. 'meta_appid' => Settings::get('app_meta_appid'),
  752. ],
  753. 'mp' => [
  754. 'appid' => Settings::get('mp_app_id'),
  755. ],
  756. 'web' => [
  757. 'appid' => '',
  758. ],
  759. 'mch' => [
  760. 'appid' => Settings::get('mch_id'),
  761. ]
  762. ],
  763. 'phone' => [
  764. 'hard' => Settings::get('app_force_phone_hard', 0),
  765. 'pages' => Settings::get('app_force_phone_pages', []),
  766. ],
  767. 'vip' => [
  768. 'options' => Settings::get('app_vip_options', []),
  769. 'clause' => Settings::get('app_vip_clause', 0),
  770. 'discount' => Settings::get('app_vip_paycontent_discount', 0),
  771. 'anonymous' => Settings::get('app_vip_anonymous_only', 0),
  772. ],
  773. "coins" => [
  774. "name" => Settings::get('app_coin_name', '硬币'),
  775. "rate" => Settings::get('app_coin_pay_rate', 100),
  776. "percent_every" => _between_(Settings::get('app_coin_pay_percent_every', 100),0, 100),
  777. "pay" => Settings::get('app_coin_pay_open', 0) == 1,
  778. "reward" => [
  779. "mp" => [
  780. "reward_unit" => Settings::get('ad_mp_reward_unit', ''),
  781. "every" => Settings::get('ad_mp_reward_every', 20),
  782. "times" => Settings::get('ad_mp_reward_every_day_times', 10)
  783. ],
  784. "uni" => [
  785. "reward_unit" => Settings::get('ad_uni_reward_unit', ''),
  786. "every" => Settings::get('ad_uni_reward_every', 20),
  787. "times" => Settings::get('ad_uni_reward_every_day_times', 10)
  788. ]
  789. ],
  790. "give_coin_open" => Settings::get('app_coin_give_switch', 1) == 1,
  791. "give_options" => Settings::get('app_coin_give_options', []),
  792. "give_clause" => Settings::get('app_coin_give_clause', 0),
  793. ],
  794. "lv" =>[
  795. "permission" => [
  796. 'watch_video' => Settings::get('app_user_lv_watch_video', 1),
  797. 'publish_video' => Settings::get('app_user_lv_publish_video', 1),
  798. 'open_chat' => Settings::get('app_user_lv_open_chat', 1)
  799. ]
  800. ],
  801. 'ip' => [
  802. 'comment' => Settings::get('app_ip_comment_show', 0),
  803. 'post' => Settings::get('app_ip_post_show', 0),
  804. 'user' => Settings::get('app_ip_user_show', 0),
  805. ],
  806. 'post' => [
  807. 'list' => [
  808. 'media' => Settings::get('sticky_list_media_style', 2, true),
  809. 'footer' => $config_app_post_list_footer,
  810. ]
  811. ],
  812. ],
  813. 'h5' => [
  814. 'home' => Settings::get('app_h5_home'),
  815. 'app_url' => Settings::get('admin_app_introduce_page', 'https://www.minisns.cn'),
  816. 'redirect' => Settings::get('h5_normal_browser_redirect', 1) == 1 ? 1 : 0,
  817. 'redirect_pages' => Settings::get('h5_normal_browser_redirect_pages', 5)
  818. ],
  819. 'about'=> [
  820. 'logo' => Settings::get('about_logo'),
  821. 'name' => Settings::get('app_title'),
  822. 'desc' => Settings::get('app_intro'),
  823. 'slogan' => Settings::get('about_title'),
  824. 'copyright' => Settings::get('about_copyright'),
  825. 'icp' => Settings::get('about_icp'),
  826. 'email' => Settings::get('about_sms'),
  827. 'address' => Settings::get('about_address'),
  828. 'phone' => Settings::get('about_phone'),
  829. 'qq' => Settings::get('about_qq')
  830. ],
  831. 'pay' => [
  832. 'wechat' => Settings::get('app_app_pay_type_wechat'),
  833. 'alipay' => Settings::get('app_app_pay_type_ali'),
  834. 'apple' => Settings::get('app_app_pay_type_apple'),
  835. 'mini2mp' => Settings::get('mini_ios_virtual_products_mp_pay', 0) == 1 ? 1 : 0
  836. ],
  837. 'share' => [
  838. 'format' => $app_share_format,
  839. ],
  840. 'code' => [
  841. 'mini' => Settings::get('app_mini_code'),
  842. 'mp' => Settings::get('app_mp_code'),
  843. 'app' => Settings::get('app_app_code'),
  844. 'douyin' => Settings::get('app_douyin_code')
  845. ],
  846. 'user' => [
  847. 'login_style' => Utils::get_login_styles(),
  848. 'register_style' => Utils::get_login_styles(0),
  849. 'login_force' => Settings::get('app_login_force', 0),
  850. 'default_user_name' => Settings::get('default_user_name_', ''),
  851. 'user_background_maps' => Settings::get('user_background_maps'),
  852. 'official_popup' => Settings::get('official_popup_poster'),
  853. 'members_popup' => Settings::get('members_popup_poster'),
  854. 'authentication_popup' => Settings::get('authentication_popup_poster'),
  855. 'user_default_introduce' => Settings::get('app_user_introduce', '',true),
  856. ],
  857. 'img' => [
  858. 'empty' => Settings::get('img_empty'),
  859. 'default' => Utils::imgWithStyle(Settings::get('img_default'), 1),
  860. 'default_share' => $default_share,
  861. 'post_poster' => Settings::get('img_post_poster_default'),
  862. 'default_avatar' => Settings::get('img_default_avatar'),
  863. 'topic_avatar' => Settings::get('img_default_topic_avatar'),
  864. 'favicon_ico' => Settings::get('browser_favicon_ico'),
  865. 'styleNames' => $img_all_style_names,
  866. 'phone_popup' => Settings::get('img_get_phone_popup', 'https://img.mini.minisns.cn/images/phone.jpg'),
  867. "reward_select" => Settings::get('popup_reward_select_img', 'https://img.mini.minisns.cn/icons/rain.png'),
  868. "beliked_count" => Settings::get('popup_beliked_count_img', 'https://img.mini.minisns.cn/icons/collect-likes.png'),
  869. ],
  870. 'audit' => [
  871. 'is_audit_posts' => Settings::get('is_audit_posts', 0) == '1' ? 1 : 0,
  872. 'is_audit_comment' => Settings::get('is_audit_comment', 0) == '1' ? 1 : 0,
  873. 'is_audit_user_info' => Settings::get('is_audit_user_info', 0) == '1' ? 1 : 0,
  874. 'is_user_center_show_posts' => 0,
  875. 'is_audit_create_cirlce' => Settings::get('is_audit_create_cirlce', 0) == '1' ? 1 : 0,
  876. 'is_reward' => Settings::get('is_reward', '1') == '1' ? 1 : 0,
  877. 'is_withdrawal' => Settings::get('is_withdrawal') == '1' ? 1 : 0,
  878. ],
  879. 'color' => [
  880. '--color-primary' => Settings::get('uni_color_primary', '#fc3a72')
  881. ],
  882. 'page' => [
  883. 'animation' => $app_page_animation,
  884. 'index' => [
  885. 'header' => AdminUtils::get_nav_left_right_icon( ($__MINI_GLOBAL_DEVICE__ == 'mp' ? 'app_index_header_icon' : 'app_app_index_header_icon')),
  886. 'channels' => [
  887. 'style' => Settings::get('app_index_top_nav_style', 0)
  888. ],
  889. 'searchCarousel' => explode('|', Settings::get('app_search_carousel', '', true)),
  890. 'banner' => WxSlideshow::wherein('id', explode(',', Settings::get('app_index_banner', '', true)))->orderBy(DB::raw('FIND_IN_SET(id, "' . Settings::get('app_index_banner', '', true) . '"' . ")"))->get(['id', 'poster', 'target_id', 'slideshow_type']),
  891. 'banner_height' => Settings::get('app_index_banner_height', 300, true),
  892. 'notice' => Settings::get('app_index_notice', [], true),
  893. 'nav' => Settings::get('app_index_nav', [], true),
  894. 'shop_nav' => Settings::get('app_index_shop_nav', [], true),
  895. 'flow' => Settings::get('app_index_flow', 1, true)
  896. ],
  897. 'find' => [
  898. 'header' => AdminUtils::get_nav_left_right_icon('app_find_header_icon', true),
  899. 'banner' => WxSlideshow::wherein('id', explode(',', Settings::get('app_find_banner', '', true)))->orderBy(DB::raw('FIND_IN_SET(id, "' . Settings::get('app_find_banner', '', true) . '"' . ")"))->get(['id', 'poster', 'target_id', 'slideshow_type']),
  900. 'tabs' => Settings::get('app_find_tab', [], true)
  901. ],
  902. 'find2' => [
  903. 'header' => AdminUtils::get_nav_left_right_icon('app_find2_header_icon', true),
  904. 'banner' => WxSlideshow::wherein('id', explode(',', Settings::get('app_find2_banner', '', true)))->orderBy(DB::raw('FIND_IN_SET(id, "' . Settings::get('app_find2_banner', '', true) . '"' . ")"))->get(['id', 'poster', 'target_id', 'slideshow_type']),
  905. 'tabs' => Settings::get('app_find2_tab', [], true)
  906. ],
  907. 'shop' => [
  908. 'accordion' => Settings::get('is_app_shop_accordion', true) == '1' ? 1 : 0,
  909. 'hot' => Settings::get('is_app_shop_hot_list', true) == '1' ? 1 : 0,
  910. 'servicer' => [
  911. 'servicer_target_type' => Settings::get('app_shop_servicer_target_type'),
  912. 'servicer_target_id' => Settings::get('app_shop_servicer_target_id'),
  913. ]
  914. ],
  915. 'notice' => [
  916. 'mp_follow' => Settings::get('app_notice_mp_follow', 1),
  917. 'style' => Settings::get('app_notice_img_style', 0),
  918. 'icons' => [
  919. 'system' => Settings::get('app_notice_img_system', ''),
  920. 'like' => Settings::get('app_notice_img_like', ''),
  921. 'comment' => Settings::get('app_notice_img_comment', ''),
  922. 'servicer' => Settings::get('app_notice_img_servicer', ''),
  923. 'mp_servicer' => Settings::get('app_notice_img_servicer_mp_servicer', 0, true),
  924. 'servicer_target_type' => Settings::get('app_notice_img_servicer_target_type', 1, true),
  925. 'servicer_target_id' => Settings::get('app_notice_img_servicer_target_id', null, true),
  926. 'circle' => Settings::get('app_notice_img_circle', ''),
  927. ],
  928. ],
  929. 'mine' => [
  930. 'header' => AdminUtils::get_nav_left_right_icon('app_mine_header_icon'),
  931. 'style' => Settings::get('app_user_list_style', 0),
  932. ],
  933. 'circle' => [
  934. 'style' => Settings::get('app_circle_list_style', 0, true),
  935. ],
  936. 'topic' => [
  937. 'style' => Settings::get('app_topic_list_style', 0),
  938. ],
  939. 'circle_class' => [
  940. ],
  941. 'qa' => [
  942. 'type' => Settings::get('app_qa_types', [])
  943. ],
  944. 'create' => [
  945. "fix2_left" => Settings::get('app_publish_tools_fixed2_left', ['location', 'circle']),
  946. "fix2_right" => Settings::get('app_publish_tools_fixed2_right', ['pay']),
  947. 'imagetext_switch' => Settings::get('app_publish_imagetext_switch', 1, true) == 1,
  948. 'max_file' => Settings::get('app_upload_max_files', 5, true),
  949. 'max_sounds' => Settings::get('app_upload_max_sounds', 1, true),
  950. 'max_vote_option' => Settings::get('app_vote_max_options', 10, true),
  951. 'max_coins' => Settings::get('app_pay_max_coins', 10000),
  952. 'max_blance' => Settings::get('app_pay_max_balance', 1000),
  953. 'video_press' => Settings::get('app_upload_video_compress', 1, true),
  954. 'circle_require' => Settings::get('app_publish_circle_required', 0, true),
  955. 'media_require' => Settings::get('app_publish_media_required', 0, true),
  956. 'edit_need' => Settings::get('app_publish_edit_need_coin', ($__MINI_GLOBAL_TENANT_ID__ > 0 ? Settings::get('app_publish_edit_need_coin', 100) : 100), true)
  957. ],
  958. 'login' => [
  959. 'bg' => Settings::get('app_login_bg', 'https://img.mini.minisns.cn/2023/03/25/68b11834f85f49711ae1ba875f7d7ab1.jpg', true),
  960. 'scroll' => Settings::get('app_login_bg_scroll', 1, true),
  961. ],
  962. 'sticky' => [
  963. 'video_slide' => Settings::device_get('sticky_video_slide_in_mp', 'sticky_video_slide_in_h5', 'sticky_video_slide_in_android_app', 'sticky_video_slide_in_ios_app', '', false, true) == 1,
  964. ]
  965. ],
  966. 'admin' => [
  967. 'played' => $admin_played_users,
  968. 'playlist' => $played_users_,
  969. 'nav' => Settings::get('app_admin_nav', [])
  970. ],
  971. 'events' => $this->get_page_events(),
  972. 'pays' => [
  973. 'paycode_0' => true,
  974. 'paycode_1' => true,
  975. 'paycode_2' => true,
  976. 'paycode_3' => true,
  977. 'paycode_4' => true,
  978. 'paycode_5' => true,
  979. 'paycode_6' => true,
  980. 'paycode_7' => true,
  981. 'paycode_8' => true,
  982. 'paycode_9' => true,
  983. 'paycode_10' => true,
  984. 'paycode_11' => true,
  985. 'paycode_12' => true,
  986. 'paycode_13' => true,
  987. 'paycode_14' => true,
  988. 'paycode_15' => true,
  989. 'paycode_16' => true,
  990. 'paycode_17' => true,
  991. 'paycode_18' => true,
  992. 'paycode_19' => true,
  993. 'paycode_20' => true,
  994. 'paycode_21' => true,
  995. 'paycode_22' => true,
  996. 'paycode_23' => true,
  997. 'paycode_24' => true,
  998. 'paycode_36' => true,
  999. ],
  1000. 'pupop' => get_site_meta(_multi_key('app_publish_popup_config'), 'j')
  1001. ];
  1002. }
  1003. private function get_page_events(){
  1004. $page_events = [];
  1005. WxPageEvent::all()->map(function ($v) use (&$page_events){
  1006. if(isset($page_events[$v->scene])){
  1007. $page_events[$v->scene][] = $v;
  1008. }else{
  1009. $page_events[$v->scene] = [$v];
  1010. }
  1011. });
  1012. return $page_events;
  1013. }
  1014. private function third_configData(){
  1015. return [
  1016. 'OK' => true,
  1017. 'version' => Settings::get('__global_config_version__', 1),
  1018. ];
  1019. }
  1020. private function fourth_configData(){
  1021. return [
  1022. 'OK' => true,
  1023. 'version' => Settings::get('__global_config_version__', 1),
  1024. 'pets' => [
  1025. ]
  1026. ];
  1027. }
  1028. private function second_configData(){
  1029. $mine_list = Settings::get('app_user_about_mine_list', []);
  1030. if(true){
  1031. if(Settings::get('app_user_about_mine_minisns_show', 1) == 1){
  1032. $mine_list[] = [
  1033. 'name' => '迷你SNS驱动',
  1034. 'type' =>11,
  1035. 'target' => 'wx3663aa159a362f52|gh_31aec555bf2f|pages/tabbar/index/index?from_user=' . Settings::get('app_user_about_mine_minisns_id', 11691)
  1036. ];
  1037. }
  1038. }else{
  1039. $mine_list[] = [
  1040. 'name' => '迷你SNS驱动',
  1041. 'type' =>11,
  1042. 'target' => 'wx3663aa159a362f52|gh_31aec555bf2f|pages/tabbar/index/index?from_user=' . Settings::get('app_user_about_mine_minisns_id', 11691)
  1043. ];
  1044. }
  1045. // 首页是否瀑布流
  1046. $index_is_waterfall = false;
  1047. $index_tab = json_decode(Settings::get('app_index_tab', '', true), true);
  1048. if(!_empty_($index_tab)){
  1049. $index_is_waterfall = _array_key($index_tab[1], 'waterfall', '0') == '1';
  1050. }
  1051. $publish2_square_list = explode(',', Settings::get('app_publish2_square_list', '', true));
  1052. $publish2_square_icons = [];
  1053. if($publish2_square_list){
  1054. $publish2_square_icons = WxIcon::whereIn('id', $publish2_square_list)->orderBy(DB::raw('FIND_IN_SET(id, "' . implode(",", $publish2_square_list) . '"' . ")"))->limit(2)->get();
  1055. }
  1056. $app_publish2_post_show = explode(',', Settings::get('app_publish2_post_show', '', true));
  1057. $publish2_post_show = [];
  1058. if($app_publish2_post_show && $app_publish2_post_show[0]){
  1059. $publish2_post_show = [
  1060. 'id' => $app_publish2_post_show[0],
  1061. 'title' => PostUtils::get_the_title('', $app_publish2_post_show[0]),
  1062. 'user' => UserUtils::get_simple_cached_user(WxPost::where('id', $app_publish2_post_show[0])->value('user_id'), ['id', 'user_name', 'user_avatar'])
  1063. ];
  1064. }
  1065. $cosConfig = Settings::get('cosv5', []);
  1066. return [
  1067. 'OK' => true,
  1068. 'version' => Settings::get('__global_config_version__', 1),
  1069. 'page' => [
  1070. 'sticky' => [
  1071. 'statement' => Settings::get('sticky_content_statement', '', true),
  1072. 'slider_comment_page' => Settings::get('sticky_reach_bottom_comment_page', 0),
  1073. 'is_recommendation' => Settings::get('is_sticky_content_recommendation', 0, true),
  1074. ],
  1075. 'circle' => [
  1076. 'publish_icon' => Settings::get('app_circle_list_publish_icon', 0, true),
  1077. ],
  1078. 'wallpapers' => [
  1079. 'name' => Settings::get('app_wallpapers_name', '图集')
  1080. ],
  1081. 'mine' => [
  1082. 'about' => [
  1083. 'list' => $mine_list
  1084. ],
  1085. 'earnings' => [
  1086. 'recharge_list' => Settings::get('app_balance_recharge_list', []),
  1087. 'balance_clause' => Settings::get('app_balance_recharge_clause', 0),
  1088. 'child_refund_clause' => Settings::get('app_balance_recharge_child_refund_clause', 0),
  1089. 'withdrawal_way' => Settings::get('app_balance_withdrawal_way', []),
  1090. 'withdrawal_min_once' => Settings::get('app_balance_withdrawal_min_once', 1),
  1091. 'withdrawal_max_once' => Settings::get('app_balance_withdrawal_max_once', 200),
  1092. 'withdrawal_day_times' => Settings::get('app_balance_withdrawal_day_times', 3),
  1093. 'withdrawal_tips' => Settings::get('app_balance_withdrawal_tips', [])
  1094. ]
  1095. ],
  1096. 'publish2' => [
  1097. 'bg' => Settings::get('app_publish2_bg_img', 'https://img.mini.minisns.cn/images/hbx/publish2-bg.jpg'),
  1098. 'post' => $publish2_post_show,
  1099. 'items' => $publish2_square_icons
  1100. ],
  1101. 'used' => [
  1102. 'index' => [
  1103. 'header' => AdminUtils::get_nav_left_right_icon('app_used_header_icon'),
  1104. 'banner' => WxSlideshow::wherein('id', explode(',', Settings::get('used_mall_index_banner', '', true)))->orderBy(DB::raw('FIND_IN_SET(id, "' . Settings::get('used_mall_index_banner', '', true) . '"' . ")"))->get(['id', 'poster', 'target_id', 'slideshow_type']),
  1105. ],
  1106. 'detail' => [
  1107. 'map' => Settings::get('used_mall_detail_self_pick_show_map', 1, true),
  1108. 'buy' => Settings::get('used_mall_detail_can_buy', 1)
  1109. ],
  1110. 'push' => [
  1111. 'force_classify' => Settings::get('used_mall_push_force_classify', 0, true) == 1 ? 1 : 0
  1112. ]
  1113. ],
  1114. 'bureau' => [
  1115. 'index' => [
  1116. 'header' => [],
  1117. 'banner' => [],
  1118. ],
  1119. 'settle_in' => [
  1120. 'bg' => ''
  1121. ],
  1122. "detail" => [
  1123. "price" => 0,
  1124. "price_gray" => ''
  1125. ]
  1126. ],
  1127. 'reward' => [
  1128. 'inspire' => [
  1129. 'img' => Settings::get('ad_reward_inspire_img', 'https://img.mini.minisns.cn/images/inspire-face.png')
  1130. ]
  1131. ],
  1132. 'certification' => [
  1133. 'img_tip' => Settings::get('app_user_authenticate_img_tip', [])
  1134. ],
  1135. 'find' => [
  1136. 'icons' => [
  1137. 'header' => AdminUtils::get_nav_left_right_icon('app_find2_header_icon', true),
  1138. 'icons' => Settings::get('app_find9_icons', [], true)
  1139. ],
  1140. ],
  1141. 'voter' => [
  1142. 'header' => AdminUtils::get_nav_left_right_icon('app_voter_header_icon', true),
  1143. 'banner' => WxSlideshow::wherein('id', explode(',', Settings::get('app_voter_banner', '', true)))->orderBy(DB::raw('FIND_IN_SET(id, "' . Settings::get('app_voter_banner', '', true) . '"' . ")"))->get(['id', 'poster', 'target_id', 'slideshow_type']),
  1144. 'tabs' => Settings::get('app_voter_tab', [], true)
  1145. ],
  1146. ],
  1147. 'emoji' => [
  1148. 'page_1' => json_decode(Settings::get('app_emoji_page_1', ''), true),
  1149. 'page_2' => json_decode(Settings::get('app_emoji_page_2', ''), true),
  1150. 'page_3' => json_decode(Settings::get('app_emoji_page_3', ''), true),
  1151. ],
  1152. 'invite' => [
  1153. 'status' => Settings::get('user_invite_benefit_status', 0) == 1,
  1154. 'lv' => Settings::get('app_user_lv_invite_benefit', 2),
  1155. 'max_layer' => Settings::get('user_invite_benefit_max_layer', 3),
  1156. ],
  1157. 'app' => [
  1158. 'withdrawal' => [
  1159. 'platform_percent' => _between_(Settings::get('app_withdrawal_platform_percent', 10.0), 0, 100),
  1160. 'type' => Settings::get('user_withdrawal_type', 0)
  1161. ],
  1162. 'contact_apply' => [
  1163. 'platform_percent' => _between_(Settings::get('app_contact_pay_platform_percent', 10.0), 0, 100),
  1164. ]
  1165. ],
  1166. 'placeholder' => [
  1167. 'publish_word' => Settings::get('app_publish_placeholder_text', '', true),
  1168. ],
  1169. 'user' => [
  1170. 'labels' => Settings::get('app_user_labels', [],true)
  1171. ],
  1172. 'waterfall' => [
  1173. 'scene_1' => $index_is_waterfall,
  1174. 'scene_6' => Settings::get('app_circle_list_style', '0') == '1',
  1175. 'scene_7' => Settings::get('app_topic_list_style', '0') == '1',
  1176. 'scene_8' => Settings::get('app_user_list_style', '0') == '1',
  1177. ],
  1178. 'used' => [
  1179. 'share' => [
  1180. 'index_title' => Settings::get('used_mall_index_share_title', ''),
  1181. 'index_image' => Settings::get('used_mall_index_share_image', ''),
  1182. 'detail_title' => Settings::get('used_mall_detail_share_title', '[good_title] - 限制'),
  1183. ],
  1184. ],
  1185. 'cos' => [
  1186. 'bucket' => _array_key($cosConfig, 'bucket', '') . '-' ._array_key($cosConfig, 'appId', ''),
  1187. 'region' => _array_key($cosConfig, 'region', '')
  1188. ],
  1189. 'bureau' => [
  1190. 'tags' => [],
  1191. 'club' => [
  1192. 'avatar' => '',
  1193. 'clause' => 0
  1194. ],
  1195. 'share' => [
  1196. 'index_title' => '',
  1197. 'index_image' => '',
  1198. 'detail_title' => '',
  1199. ],
  1200. ]
  1201. ];
  1202. }
  1203. /*
  1204. * 返回站点信息
  1205. */
  1206. public function configData(Request $request){
  1207. global $__MINI_GLOBAL_FRONT_VERSION__;
  1208. $device = $request->header('device','mp');
  1209. if(_empty_($device)){
  1210. $device = 'mp';
  1211. }
  1212. $uid = $request->uid;
  1213. if(_empty_($uid)){
  1214. $uid = 0;
  1215. }
  1216. $platform = $request->header('platform','android');
  1217. if(!in_array($platform, ['android', 'ios'])){
  1218. $platform = 'android';
  1219. }
  1220. global $__MINI_GLOBAL_TENANT_ID__;
  1221. $which = $request->which;
  1222. if($which && $which > 1 && $which <= 5){
  1223. }else{
  1224. $which = '';
  1225. }
  1226. if(_empty_($device) || !in_array($device, ['app', 'mp', 'h5', 'pc'])){
  1227. return $this->fail(200001);
  1228. }
  1229. // app需要分安卓和ios
  1230. if($device == 'app'){
  1231. $device = $device.':'.$platform;
  1232. }
  1233. $device = 'tenant_'.$__MINI_GLOBAL_TENANT_ID__ . ':' . $device;
  1234. $the_cache_key = 'configData'.$which.':'.$__MINI_GLOBAL_FRONT_VERSION__.':'.$device;
  1235. $data = json_decode(Cache::tags('configData')->get($the_cache_key, '[]'), true);
  1236. if(!_empty_($data)){
  1237. }else{
  1238. if($which == 3){
  1239. $data = $this->third_configData();
  1240. }else if($which == 4){
  1241. $data = $this->fourth_configData();
  1242. }else if($which == 2){
  1243. $data = $this->second_configData();
  1244. }else{
  1245. $data = $this->default_configData();
  1246. }
  1247. if($which == 3){
  1248. // 特殊用户自定义的配置
  1249. Cache::tags('configData')->put($the_cache_key, json_encode($data), 3600 * 3 );
  1250. }else{
  1251. Cache::tags('configData')->put($the_cache_key, json_encode($data));
  1252. }
  1253. }
  1254. if(!($which > 1)){
  1255. if($data && is_array($data) && $data['app']['mode'] == 'examine' && $uid > 0){
  1256. if(!is_mini_examine_mode(11)){
  1257. $data['app']['mode'] = 'normal';
  1258. }
  1259. }
  1260. }
  1261. return $this->success($data);
  1262. }
  1263. /**
  1264. * 用户搜索列表
  1265. */
  1266. public function mySearch(Request $request)
  1267. {
  1268. $uid = $request->uid;
  1269. if ($uid) {
  1270. return $this->success(WxSearch::where('user_id', $uid)
  1271. ->orderBy('id', 'desc')
  1272. ->get(['search_content', 'id']));
  1273. }else{
  1274. return $this->success([]);
  1275. }
  1276. }
  1277. public function realtime_post(Request $request){
  1278. $type = $request->type;
  1279. $posts = RealtimeUtils::get_top_posts();
  1280. if($posts){
  1281. if($type == '50'){
  1282. $posts['posts'] = array_slice($posts['posts'], 0, 50);
  1283. }else{
  1284. $posts['posts'] = array_slice($posts['posts'], 0, 10);
  1285. }
  1286. $posts['format_time'] = format_datetime($posts['update_time']);
  1287. return $this->success($posts);
  1288. }
  1289. return $this->fail(200003);
  1290. }
  1291. public function realtime_topics(Request $request){
  1292. if(true){
  1293. $topics = RealtimeUtils::get_topic_top();
  1294. if($topics){
  1295. $topics['topics'] = array_slice($topics['topics'], 0, 10);
  1296. if($topics['topics']){
  1297. for ($i = 0; $i < count($topics['topics']); $i++){
  1298. $topics['topics'][$i]['head_portrait'] = Utils::imgWithStyle($topics['topics'][$i]['head_portrait'], 2);
  1299. }
  1300. }
  1301. $topics['format_time'] = format_datetime($topics['update_time']);
  1302. return $this->success($topics);
  1303. }
  1304. }else{
  1305. $topics = [
  1306. 'topics' => [],
  1307. 'format_time' => ''
  1308. ];
  1309. $tags = WxTag::where('tags_state', 0)
  1310. ->where('tags_number', '>', 0)
  1311. ->orderBy('tags_number', 'desc')->limit(10)->get();
  1312. $tags->map(function ($items) {
  1313. $items->tags_number = WxPostsTag::where('tags_id', $items->id)->count();
  1314. if(_empty_($items->head_portrait)){
  1315. $items->head_portrait = Settings::get('img_default_topic_avatar');
  1316. TopicImgJob::dispatch($items->id);
  1317. }
  1318. });
  1319. if($tags){
  1320. $topics['topics'] = $tags;
  1321. }
  1322. return $this->success($topics);
  1323. }
  1324. }
  1325. public function captcha_process(Request $request){
  1326. $action = _empty_default_($request->action);
  1327. if($action == 'src'){
  1328. $code = WxCaptchaImg::where('status', 1)->inRandomOrder()->first();
  1329. if(!$code){
  1330. return $this->fail(200008, [], '管理员暂未配置人机验证码库');
  1331. }
  1332. $rotate = rand(10, 340);
  1333. $random_str = Str::random(8);
  1334. Cache::put('captcha:'.$random_str, $rotate, 60);
  1335. return $this->success([
  1336. 'src' => ImageUtils::get_img_base64($code->img, $rotate),
  1337. 'random' => $random_str,
  1338. ]);
  1339. }else if($action == 'check'){
  1340. global $__MINI_GLOBAL_DEVICE__,$__MINI_GLOBAL_PLATFORM__,$__MINI_GLOBAL_IP__;
  1341. $random = _empty_default_($request->random, '');
  1342. if(_empty_($random)){
  1343. return $this->fail(200001);
  1344. }
  1345. $rotate = Cache::get('captcha:'.$random);
  1346. if(_empty_($rotate)){
  1347. return $this->fail(200044);
  1348. }
  1349. $margin = 25;
  1350. $rotationAngle = _empty_default_($request->rotationAngle, 0);
  1351. $totalRotation = ($rotationAngle + $rotate) % 360;
  1352. if ($totalRotation <= $margin || $totalRotation >= (360 - $margin)) {
  1353. Cache::put('captcha:ip:'.$__MINI_GLOBAL_DEVICE__.':'.$__MINI_GLOBAL_PLATFORM__.':'.$__MINI_GLOBAL_IP__, 1, 600);
  1354. return $this->success();
  1355. }else{
  1356. return $this->fail(200004, [], '验证未通过');
  1357. }
  1358. }
  1359. return $this->fail(200001);
  1360. }
  1361. public function idd(){
  1362. if(!file_exists(storage_path('app/idd/idd.json'))){
  1363. return $this->fail(200003);
  1364. }
  1365. return $this->success(json_decode(file_get_contents(storage_path('app/idd/idd.json'))));
  1366. }
  1367. /**
  1368. * 用户删除搜索记录
  1369. * id
  1370. */
  1371. public function myDelSearch(Request $request)
  1372. {
  1373. $id = $request->id;
  1374. return $this->success(WxSearch::where('id', $id)->delete());
  1375. }
  1376. /**
  1377. * 用户删除全部搜索记录
  1378. * id
  1379. */
  1380. public function myDelAllSearch(Request $request)
  1381. {
  1382. $uid = $request->uid;
  1383. return $this->success(WxSearch::where('user_id', $uid)->delete());
  1384. }
  1385. public function towebview($action, $unique){
  1386. $url = '';
  1387. if($action == 'mplogin'){
  1388. config(['services.wechat_service_account.redirect' => env('APP_URL').'/common/webview/action?action=mplogin&unique='.$unique]);
  1389. return Socialite::driver('wechat_service_account')->redirect();
  1390. }
  1391. if($action == 'mpbind'){
  1392. config(['services.wechat_service_account.redirect' => env('APP_URL').'/common/webview/action?action=mpbind&unique='.$unique]);
  1393. return Socialite::driver('wechat_service_account')->redirect();
  1394. }
  1395. return view('common/webview', compact('url'));
  1396. }
  1397. public function webview(Request $request){
  1398. $uid = $request->uid;
  1399. $action = $request->action;
  1400. $unique = $request->unique;
  1401. $pre_scene = _empty_default_($request->pre_scene, 0);
  1402. $pre_scene_id = _empty_default_($request->pre_scene_id, 0);
  1403. $url = '';
  1404. if(!_empty_($pre_scene)){
  1405. Cache::put($action.':unique:'.$unique.':scene', json_encode([
  1406. 'scene' => $pre_scene,
  1407. 'pre_scene_id' => $pre_scene_id
  1408. ]), 120);
  1409. }
  1410. if($action == 'mplogin'){
  1411. config(['services.wechat_service_account.redirect' => env('APP_URL').'/common/webview/action?action=mplogin&unique='.$unique]);
  1412. return Socialite::driver('wechat_service_account')->redirect();
  1413. }
  1414. if($action == 'mpbind'){
  1415. config(['services.wechat_service_account.redirect' => env('APP_URL').'/common/webview/action?action=mpbind&unique='.$unique]);
  1416. return Socialite::driver('wechat_service_account')->redirect();
  1417. }
  1418. return view('common/webview', compact('url'));
  1419. }
  1420. public function webviewAction(Request $request){
  1421. $action = $request->action;
  1422. $unique = $request->unique;
  1423. if($action == 'mpuser'){
  1424. $userData = Socialite::driver('wechat_service_account')->user();
  1425. if($userData){
  1426. $user = $userData->user;
  1427. $data = [
  1428. 'openId'=>$user['openid'], 'avatarUrl'=>$user['headimgurl'] ?: '', 'city'=>$user['city'] ?: '', 'country'=>$user['country'] ?: '',
  1429. 'province'=>$user['province'] ?: '', 'language'=>'','nickName'=>$user['nickname'] ?: '',
  1430. 'gender'=>$user['sex'] ?: 0, 'unionId'=>$user['unionid'] ?? ''
  1431. ];
  1432. $wxUserModel = new WxUser();
  1433. $r = $wxUserModel->registerUser($data, 'mp');
  1434. if($r > 0){
  1435. return '获取成功!';
  1436. }else{
  1437. return '获取失败';
  1438. }
  1439. }
  1440. return '未获取到用户信息';
  1441. }
  1442. if($action == 'mplogin'){
  1443. $userData = Socialite::driver('wechat_service_account')->user();
  1444. if($userData){
  1445. $user = $userData->user;
  1446. $data = [
  1447. 'openId'=>$user['openid'], 'avatarUrl'=>$user['headimgurl'] ?: '', 'city'=>$user['city'] ?: '', 'country'=>$user['country'] ?: '',
  1448. 'province'=>$user['province'] ?: '', 'language'=>'','nickName'=>$user['nickname'] ?: '',
  1449. 'gender'=>$user['sex'] ?: 0, 'unionId'=>$user['unionid'] ?? ''
  1450. ];
  1451. $wxUserModel = new WxUser();
  1452. $user_id = $wxUserModel->registerUser($data, 'mp');
  1453. if($user_id > 0){
  1454. if($user_id && $unique){
  1455. Cache::put('mini:mplogin:unique:' . $unique, $user_id, 10 * 60);
  1456. }
  1457. $to_path = 'pages/tabbar/index/index?';
  1458. $scene = json_decode(Cache::get($action.':unique:'.$unique.':scene', '[]'), true);
  1459. if($scene && _array_key($scene, 'scene', 0) > 0)
  1460. if($scene['scene'] == 31){
  1461. $to_path = 'pagesA/mine/members/members?';
  1462. }else if($scene['scene'] == 84){
  1463. $to_path = 'pagesC/promotion/post?';
  1464. }
  1465. $href = Settings::get('app_h5_home') .'/#/'.$to_path.'action=mplogin&unique='. $unique;
  1466. $html = '
  1467. <!DOCTYPE html>
  1468. <html lang="en">
  1469. <head>
  1470. <meta charset="UTF-8">
  1471. <title>正在获取用户授权信息...请稍后</title>
  1472. </head>
  1473. <body>
  1474. <div>获取成功,若未自动跳转,可手动关闭即可</div>
  1475. <script>
  1476. function redict(){
  1477. window.location.href = \''. $href .'\'
  1478. }
  1479. redict();
  1480. </script>
  1481. </body>
  1482. </html>
  1483. ';
  1484. return $html;
  1485. }else{
  1486. _logger_(__file__, __line__, '发生错误2...');
  1487. }
  1488. }else{
  1489. _logger_(__file__, __line__, '发生错误...');
  1490. }
  1491. }
  1492. if($action == 'mpbind'){
  1493. $userData = Socialite::driver('wechat_service_account')->user();
  1494. if($userData){
  1495. $user = $userData->user;
  1496. $data = [
  1497. 'openId'=>$user['openid'], 'avatarUrl'=>$user['headimgurl'] ?: '', 'city'=>$user['city'] ?: '', 'country'=>$user['country'] ?: '',
  1498. 'province'=>$user['province'] ?: '', 'language'=>'','nickName'=>$user['nickname'] ?: '',
  1499. 'gender'=>$user['sex'] ?: 0, 'unionId'=>$user['unionid']
  1500. ];
  1501. $wxUserModel = new WxUser();
  1502. $r = $wxUserModel->registerUser($data, 'mp');
  1503. if($r > 0){
  1504. return '<html><head><title>获取成功!请截图关注公众号</title></head><body><h1 style="text-align: center">获取成功!截图关注公众号即可</h1><div style="text-align: center;justify-content: center;margin: auto"><img style="max-width: 300px;" src="'.Settings::get('app_mp_code').'"></div></body></html>';
  1505. }else{
  1506. return '获取失败,可重新再试';
  1507. }
  1508. }
  1509. return '未获取到用户信息';
  1510. }
  1511. return 'success';
  1512. }
  1513. public function getActivityList(Request $request){
  1514. return $this->success(WxActivity::orderBy('created_at', 'desc')->get());
  1515. }
  1516. }