LinkController.php 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Administrator
  5. * Date: 2019/4/17 0017
  6. * Time: 16:27
  7. */
  8. namespace App\Http\Controllers\Admin;
  9. use App\Exports\BasicExport;
  10. use App\Exports\LinkCountExport;
  11. use App\Exports\LinkHallExport;
  12. use App\Http\Controllers\Controller;
  13. use App\Http\Logics\Admin\LinkLogic;
  14. use App\Http\Models\ArticleLinkNotice;
  15. use App\Http\Models\Business;
  16. use App\Http\Models\Link;
  17. use App\Http\Models\LinkCalc;
  18. use App\Http\Models\LinkStatistical;
  19. use App\Http\Models\LinkCase;
  20. use App\Http\Models\LinkNote;
  21. use App\Http\Models\LinkTask;
  22. use App\Http\Models\LinkTaskDetail;
  23. use App\Http\Models\LinkTaskScore;
  24. use App\Http\Models\LinkTaskUrl;
  25. use App\Http\Models\Role;
  26. use App\Http\Models\Site;
  27. use App\Http\Models\SiteEnterprise;
  28. use App\Http\Models\SiteInfo;
  29. use App\Http\Models\SiteMarketer;
  30. use App\Http\Models\SiteOptimizePage;
  31. use App\Http\Models\SiteSns;
  32. use App\Http\Models\User;
  33. use App\Http\Requests\Link\LinkCountSaveRequest;
  34. use App\Http\Requests\Link\SaveRequest;
  35. use App\Http\Requests\Link\CaseSaveRequest;
  36. use App\Http\Requests\Link\TaskSaveRequest;
  37. use App\Http\Requests\Link\TaskScoreRequest;
  38. use App\Http\Requests\Link\WorkerSaveRequest;
  39. use App\Http\Traits\HasSites;
  40. use App\Imports\ExternalChainLibraryImport;
  41. use App\Imports\ExternalCaseImport;
  42. use App\Imports\LinkHallWorker;
  43. use App\Imports\LinkImport;
  44. use App\Imports\SocialImport;
  45. use GuzzleHttp\Client;
  46. use GuzzleHttp\Pool;
  47. use GuzzleHttp\Psr7\Response;
  48. use Illuminate\Database\Eloquent\Builder;
  49. use Illuminate\Http\Request;
  50. use Illuminate\Support\Facades\Auth;
  51. use Illuminate\Support\Facades\DB;
  52. use Illuminate\Support\Facades\Log;
  53. use Maatwebsite\Excel\Facades\Excel;
  54. use Illuminate\Contracts\View\Factory;
  55. use Illuminate\Http\JsonResponse;
  56. use Illuminate\View\View;
  57. /**
  58. * 外链管理
  59. * Class LinkController
  60. * @package App\Http\Controllers\Admin
  61. */
  62. class LinkController extends Controller
  63. {
  64. use HasSites;
  65. protected $logic;
  66. public function __construct(LinkLogic $logic)
  67. {
  68. $this->logic = $logic;
  69. }
  70. /**
  71. * 外链库案例列表
  72. */
  73. public function infoIndex(Request $request )
  74. {
  75. if ($keyword = $request->input('keyword')) {
  76. $condition[] = ['link_url', '=',$keyword];
  77. }
  78. if (!$request->ajax()) {
  79. $list = LinkTaskDetail::query()
  80. ->selectRaw("link_type,count(id) as count")->groupBy('link_type')->get();
  81. foreach ($list as $value){
  82. $value['cn_title'] = LinkStatistical::query()
  83. ->where('site_id','=',$value['redundant_site_id'])
  84. ->value('cn_title');
  85. }
  86. $businesses = Business::query()->get();
  87. return view('admin/link/info', [
  88. 'list' => $list
  89. ]);
  90. }
  91. $link = LinkTaskDetail::query();
  92. $records = $link->where($condition ?? [])->orderByDesc('id')
  93. ->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);
  94. $items = $records->items();
  95. foreach ($items as $value){
  96. $value['cn_title'] = LinkStatistical::query()
  97. ->where('site_id','=',$value['redundant_site_id'])
  98. ->value('cn_title');
  99. }
  100. $businesses = Business::query()->pluck('title', 'id');
  101. array_walk($items, function ($item) use ($businesses) {
  102. if ($item->big_ball == 0) {
  103. $item->bigBall = '否';
  104. } else {
  105. $item->bigBall = '是';
  106. }
  107. $business = explode(',', $item->business_ids);
  108. $list = [];
  109. foreach ($business as $value) {
  110. $list[] = $businesses[$value] ?? '';
  111. }
  112. if (!empty($list)) {
  113. $item->business = implode(',', $list);
  114. } else {
  115. $item->business = '';
  116. }
  117. });
  118. return response()->json([
  119. 'rows' => $items,
  120. 'total' => $records->total()
  121. ]);
  122. }
  123. public function externalInfoExport(Request $request)
  124. {
  125. $link = LinkTaskDetail::query();
  126. $request = $request->all();
  127. if (!empty($request['keyword'])) {
  128. $link->where('link_url', '=', $request['keyword']);
  129. }
  130. $data = [];
  131. $list = $link->orderBy('id', 'desc')->get();
  132. foreach ($list as $value) {
  133. $cn_title = LinkStatistical::query()
  134. ->where('site_id','=',$value->redundant_site_id)
  135. ->value('cn_title');
  136. $list = [];
  137. $data[] = [
  138. 'link_type' => $value->link_type ?? '',
  139. 'cn_title'=>$cn_title,
  140. 'link_url' => $value->link_url,
  141. 'username' => $value->username,
  142. 'email' => $value->email,
  143. 'password' => $value->password,
  144. 'url ' => $value->url,
  145. 'created_at' => $value->created_at,
  146. ];
  147. }
  148. array_unshift($data, ['外链类型','项目名称', '平台链接', '用户名', '邮箱', ' 密码', 'profile演示地址', '创建时间']);
  149. return (new BasicExport($data))->download(sprintf('外链%s.xls', date('YmdHis')));
  150. }
  151. /**
  152. * 外链库案例列表
  153. */
  154. public function caseIndex(Request $request)
  155. {
  156. if (!$request->ajax()) {
  157. $list = LinkCase::query()
  158. ->selectRaw("type,count(id) as count")->groupBy('type')->get();
  159. foreach ($list as $value) {
  160. $value->type = LinkCase::TYPES[$value['type']] ?? '';
  161. }
  162. $businesses = Business::query()->get();
  163. return view('admin/link/case', [
  164. 'businesses' => $businesses,
  165. 'list' => $list
  166. ]);
  167. }
  168. $link = LinkCase::query();
  169. if ($keyword = $request->input('keyword')) {
  170. $condition[] = ['url', 'like', '%' . $keyword . '%'];
  171. }
  172. if ($type = $request->input('type')) {
  173. $condition[] = ['type', '=', $type];
  174. }
  175. if ($businessIds = $request->input('business_ids')) {
  176. $link->whereRaw('FIND_IN_SET(?,business_ids)', [$businessIds]);
  177. }
  178. $records = $link->where($condition ?? [])->orderByDesc('id')
  179. ->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);
  180. $items = $records->items();
  181. $businesses = Business::query()->pluck('title', 'id');
  182. array_walk($items, function ($item) use ($businesses) {
  183. $item->typeTitle = Link::TYPES[$item->type] ?? '';
  184. if ($item->big_ball == 0) {
  185. $item->bigBall = '否';
  186. } else {
  187. $item->bigBall = '是';
  188. }
  189. $business = explode(',', $item->business_ids);
  190. $list = [];
  191. foreach ($business as $value) {
  192. $list[] = $businesses[$value] ?? '';
  193. }
  194. if (!empty($list)) {
  195. $item->business = implode(',', $list);
  196. } else {
  197. $item->business = '';
  198. }
  199. });
  200. return response()->json([
  201. 'rows' => $items,
  202. 'total' => $records->total()
  203. ]);
  204. }
  205. /**
  206. * 外链库案例save
  207. */
  208. public function caseSave(CaseSaveRequest $request, $id)
  209. {
  210. if (!$request->ajax()) {
  211. $businesses = Business::query()->get();
  212. return view('admin/link/case_save', [
  213. 'data' => LinkCase::query()->find($id),
  214. 'typeList' => LinkCase::TYPES
  215. ]);
  216. }
  217. LinkCase::query()->updateOrCreate(['id' => $id], $request->validated());
  218. return response()->json(['message' => '操作成功']);
  219. }
  220. /************
  221. * 外链库案例删除
  222. * @param Request $request
  223. * @return JsonResponse
  224. */
  225. public function batchCaseDelete(Request $request)
  226. {
  227. $ids = $request->input('ids');
  228. if (!is_array($ids)) return response()->json(['message' => '删除时参数传递错误'], 422);
  229. LinkCase::destroy($ids);
  230. return response()->json(['message' => '操作成功']);
  231. }
  232. /************
  233. * 外链库案例导入
  234. * @param Request $request
  235. * @return JsonResponse
  236. */
  237. public function externalCaseImport(Request $request)
  238. {
  239. set_time_limit(0);
  240. if (!$request->input('excel_path')) {
  241. return response()->json(['message' => '请先上传excel文件'], 422);
  242. }
  243. try {
  244. Excel::import(new ExternalCaseImport(), $request->input('excel_path'), 'public');
  245. } catch (\Throwable $throwable) {
  246. Log::error(var_export($throwable->getMessage(), 1));
  247. return response()->json(['message' => '导入失败'], 400);
  248. }
  249. return response()->json(['message' => '操作成功']);
  250. }
  251. /**
  252. * 外链库管理列表
  253. * @param Request $request
  254. * @return Factory|JsonResponse|View
  255. */
  256. public function index(Request $request)
  257. {
  258. if (!$request->ajax()) {
  259. $list = Link::query()
  260. ->where('tag', '!=', '放弃')
  261. ->selectRaw("type,count(id) as count")->groupBy('type')->get();
  262. foreach ($list as $value) {
  263. $value->type = Link::TYPES[$value['type']] ?? '';
  264. }
  265. $businesses = Business::query()->get();
  266. return view('admin/link/index', [
  267. 'businesses' => $businesses,
  268. 'list' => $list
  269. ]);
  270. }
  271. $link = Link::query();
  272. if ($keyword = $request->input('keyword')) {
  273. $condition[] = ['url', 'like', '%' . $keyword . '%'];
  274. }
  275. if ($type = $request->input('type')) {
  276. $condition[] = ['type', '=', $type];
  277. }
  278. if ($businessIds = $request->input('business_ids')) {
  279. $link->whereRaw('FIND_IN_SET(?,business_ids)', [$businessIds]);
  280. }
  281. $records = $link->where($condition ?? [])->orderByDesc('id')
  282. ->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);
  283. $items = $records->items();
  284. $businesses = Business::query()->pluck('title', 'id');
  285. array_walk($items, function ($item) use ($businesses) {
  286. $item->typeTitle = Link::TYPES[$item->type] ?? '';
  287. if ($item->big_ball == 0) {
  288. $item->bigBall = '否';
  289. } else {
  290. $item->bigBall = '是';
  291. }
  292. $business = explode(',', $item->business_ids);
  293. $list = [];
  294. foreach ($business as $value) {
  295. $list[] = $businesses[$value] ?? '';
  296. }
  297. if (!empty($list)) {
  298. $item->business = implode(',', $list);
  299. } else {
  300. $item->business = '';
  301. }
  302. });
  303. return response()->json([
  304. 'rows' => $items,
  305. 'total' => $records->total()
  306. ]);
  307. }
  308. /**
  309. * 外链库管理列表导出
  310. * @param Request $request
  311. * @return Factory|JsonResponse|View
  312. */
  313. public function externalCaseExport(Request $request)
  314. {
  315. $link = LinkCase::query();
  316. $request = $request->all();
  317. if (!empty($request['type'])) {
  318. $link->where('type', $request['type']);
  319. }
  320. if (!empty($request['keyword'])) {
  321. $link->where('url', 'like', '%' . $request['keyword'] . '%');
  322. }
  323. $data = [];
  324. $list = $link->orderBy('id', 'desc')->get();
  325. foreach ($list as $value) {
  326. $list = [];
  327. $data[] = [
  328. 'typeTitle' => LinkCase::TYPES[$value->type] ?? '',
  329. 'url' => $value->url,
  330. 'username_history' => $value->username_history,
  331. 'email_history' => $value->email_history,
  332. 'password_history' => $value->password_history,
  333. 'url_history' => $value->url_history,
  334. 'created_at' => $value->created_at,
  335. ];
  336. }
  337. array_unshift($data, ['外链类型', '平台链接', '用户名', '邮箱', ' 密码', 'profile演示地址', '创建时间']);
  338. return (new BasicExport($data))->download(sprintf('外链案例%s.xls', date('YmdHis')));
  339. }
  340. //外链注意事项
  341. public function notice(Request $request)
  342. {
  343. if (!$request->ajax()) {
  344. $data = ArticleLinkNotice::query()->where(['type' => 'link'])->first();
  345. return view('admin/link/notice', [
  346. 'data' => $data ?? ''
  347. ]);
  348. }
  349. ArticleLinkNotice::query()->where(['type' => 'link'])->update([
  350. 'content' => $request->input('content')
  351. ]);
  352. return response()->json(['message' => '操作成功']);
  353. }
  354. public function save(SaveRequest $request, $id)
  355. {
  356. if (!$request->ajax()) {
  357. $businesses = Business::query()->get();
  358. return view('admin/link/save', [
  359. 'data' => Link::query()->find($id),
  360. 'typeList' => Link::TYPES,
  361. 'businesses' => $businesses
  362. ]);
  363. }
  364. Link::query()->updateOrCreate(['id' => $id], $request->validated());
  365. return response()->json(['message' => '操作成功']);
  366. }
  367. public function batchDelete(Request $request)
  368. {
  369. $ids = $request->input('ids');
  370. if (!is_array($ids)) return response()->json(['message' => '删除时参数传递错误'], 422);
  371. Link::destroy($ids);
  372. return response()->json(['message' => '操作成功']);
  373. }
  374. //外链统计
  375. public function linkCount(Request $request, $id)
  376. {
  377. if (!$request->ajax()) {
  378. return view(
  379. 'admin/link/link_count_for_site',
  380. ['siteId' => $id]
  381. );
  382. }
  383. $detailRecords = LinkTaskDetail::query()->selectRaw('link_id,any_value(id) as id')
  384. ->when($request->input('keyword'), function (Builder $builder, $keyword) {
  385. $linkIds = Link::query()->where('url', 'like', '%' . $keyword . '%')->pluck('id')->toArray();
  386. $builder->whereIn('link_id', $linkIds);
  387. })
  388. ->where([
  389. 'redundant_site_id' => $id,
  390. 'enable' => 1,
  391. 'status' => 5
  392. ])->groupBy('link_id')->orderByDesc('id')->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);
  393. $detailIds = array_column($detailRecords->items(), 'id');
  394. $records = $builder = LinkTaskDetail::query()->with(['linkTask', 'link'])
  395. ->withCount('urls')->whereIn('id', $detailIds)->orderByDesc('id')->get()->toArray();
  396. $linkTypes = Link::TYPES;
  397. array_walk($records, function (&$item) use (&$linkTypes) {
  398. $item['task_title'] = $item['link_task']['title'] ?? '';
  399. $item['link_url_source'] = $item['link']['url'] ?? '';
  400. $item['link_type_source'] = $linkTypes[($item['link']['type'] ?? 0)] ?? '';
  401. });
  402. return response()->json([
  403. 'rows' => $records,
  404. 'total' => $detailRecords->total()
  405. ]);
  406. }
  407. /**
  408. * 客户界面的外链统计
  409. * @param Request $request
  410. * @return Factory|JsonResponse|View
  411. */
  412. public function customerLinkCount(Request $request)
  413. {
  414. $oneSite = $this->hasUserOneSite();
  415. if (!$oneSite) {
  416. return view('admin/errors/tips');
  417. }
  418. if (!$request->ajax()) {
  419. return view(
  420. 'admin/link/customer_link_count',
  421. ['siteId' => $oneSite->id]
  422. );
  423. }
  424. $detailRecords = LinkTaskDetail::query()->selectRaw('link_id,any_value(id) as id')
  425. ->when($request->input('keyword'), function (\Illuminate\Database\Eloquent\Builder $builder, $keyword) {
  426. $linkIds = Link::query()->where('url', 'like', '%' . $keyword . '%')->pluck('id')->toArray();
  427. $builder->whereIn('link_id', $linkIds);
  428. })
  429. ->where([
  430. 'redundant_site_id' => $oneSite->id,
  431. 'enable' => 1,
  432. 'status' => 5
  433. ])
  434. // ->whereNotExists(function (Builder $builder) {
  435. // $builder->select(DB::raw(1))->from('link_tasks')
  436. // ->whereRaw('link_tasks_detail.task_id=link_tasks.id AND (link_tasks.status in (4) OR link_tasks.deleted_at is not null)');
  437. // })
  438. ->groupBy('link_id')->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);
  439. $detailIds = array_column($detailRecords->items(), 'id');
  440. $records = $builder = LinkTaskDetail::query()->with(['linkTask', 'link'])
  441. ->withCount('urls')->whereIn('id', $detailIds)->get()->toArray();
  442. $linkTypes = Link::TYPES;
  443. array_walk($records, function (&$item) use (&$linkTypes) {
  444. $item['task_title'] = $item['link_task']['title'] ?? '';
  445. $item['link_url_source'] = $item['link']['url'] ?? '';
  446. $item['link_type_source'] = $linkTypes[($item['link']['type'] ?? 0)] ?? '';
  447. });
  448. return response()->json([
  449. 'rows' => $records,
  450. 'total' => $detailRecords->total()
  451. ]);
  452. }
  453. //外链统计导出
  454. public function linkCountExport(Request $request, $siteId)
  455. {
  456. $detailRecords = LinkTaskDetail::query()->selectRaw('link_id,any_value(id) as id')
  457. ->when($request->input('keyword'), function (\Illuminate\Database\Eloquent\Builder $builder, $keyword) {
  458. $linkIds = Link::query()->where('url', 'like', '%' . $keyword . '%')->pluck('id')->toArray();
  459. $builder->whereIn('link_id', $linkIds);
  460. })
  461. ->where([
  462. 'redundant_site_id' => $siteId,
  463. 'enable' => 1,
  464. 'status' => 5
  465. ])
  466. // ->whereNotExists(function (Builder $builder) {
  467. // $builder->select(DB::raw(1))->from('link_tasks')
  468. // ->whereRaw('link_tasks_detail.task_id=link_tasks.id AND (link_tasks.status in (4) OR link_tasks.deleted_at is not null)');
  469. // })
  470. ->groupBy('link_id')->get()->toArray();
  471. $detailIds = array_column($detailRecords, 'id');
  472. $records = $builder = LinkTaskDetail::query()->with(['linkTask', 'link'])->whereIn('id', $detailIds)->get()->toArray();
  473. $results = [];
  474. $linkTypes = Link::TYPES;
  475. array_walk($records, function ($item) use (&$results, &$linkTypes) {
  476. $results[] = [
  477. 'task_title' => $item['link_task']['title'] ?? '',
  478. 'link_type' => $linkTypes[($item['link']['type'] ?? 0)] ?? '',
  479. 'link_url' => $item['link']['url'] ?? '',
  480. 'username' => $item['username'],
  481. 'password' => $item['password'],
  482. 'email' => $item['email'],
  483. 'url' => $item['url'],
  484. 'created_at' => (string)$item['created_at'],
  485. ];
  486. });
  487. array_unshift($results, ['关联外链标题', '类型', '平台链接', '用户名', '邮箱', '密码', 'profile演示地址', '创建时间']);
  488. return (new LinkCountExport($results))->download(sprintf('外链统计%s.xls', date('YmdHis')));
  489. }
  490. protected function getLinkUrlTime($dateRange)
  491. {
  492. if (!$dateRange) {
  493. return [];
  494. }
  495. $startDate = substr($dateRange, 0, 10);
  496. $endDate = substr($dateRange, -10);
  497. return [
  498. ['created_at', '>=', sprintf('%s 00:00:00', $startDate)],
  499. ['created_at', '<=', sprintf('%s 23:59:59', $endDate)]
  500. ];
  501. }
  502. public function linkUrl(Request $request, $siteId)
  503. {
  504. if (!$request->ajax()) {
  505. return view(
  506. 'admin/link/link_url_for_site',
  507. ['siteId' => $siteId]
  508. );
  509. }
  510. $dateRange = $request->input('date_range');
  511. $linkCondition = $this->getLinkUrlTime($dateRange);
  512. $condition[] = ['redundant_site_id', '=', $siteId];
  513. $condition[] = ['enable', '=', 1];
  514. $condition[] = ['status', '=', 5];
  515. $detailIds = LinkTaskDetail::query()->where($condition)->pluck('id')->toArray();
  516. $builder = LinkTaskUrl::query()->with(['linkDetails'])->whereIn('link_tasks_detail_id', $detailIds)->where($linkCondition)->where(['status' => 5]);
  517. $records = $builder->orderBy('id', 'desc')->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);
  518. $items = $records->items();
  519. $idMapLink = Link::query()->select(['type', 'url', 'id'])
  520. ->get()->keyBy('id')->toArray();
  521. array_walk($items, function ($item) use (&$idMapLink) {
  522. if (!empty($item->linkDetails->link_id)) {
  523. $item->link_url = sprintf('%s【%s】', $idMapLink[$item->linkDetails->link_id]['url'], Link::TYPES[$idMapLink[$item->linkDetails->link_id]['type']]);
  524. } else {
  525. $item->link_url = '';
  526. }
  527. $item->profile_url = $item->linkDetails->url ?? '';
  528. $item->detail_username = $item->linkDetails->username ?? '';
  529. $item->detail_email = $item->linkDetails->email ?? '';
  530. $item->detail_password = $item->linkDetails->password ?? '';
  531. });
  532. return response()->json([
  533. 'rows' => $items,
  534. 'total' => $records->total()
  535. ]);
  536. }
  537. //客户界面 link-url
  538. public function customerLinkUrl(Request $request)
  539. {
  540. $oneSite = $this->hasUserOneSite();
  541. if (!$oneSite) {
  542. return view('admin/errors/tips');
  543. }
  544. if (!$request->ajax()) {
  545. return view(
  546. 'admin/link/customer_link_url',
  547. ['siteId' => $oneSite->id]
  548. );
  549. }
  550. $dateRange = $request->input('date_range');
  551. $condition = $this->getLinkUrlTime($dateRange);
  552. $condition[] = ['redundant_site_id', '=', $oneSite->id];
  553. $condition[] = ['enable', '=', 1];
  554. $condition[] = ['status', '=', 5];
  555. $detailIds = LinkTaskDetail::query()->where($condition)->pluck('id')->toArray();
  556. $builder = LinkTaskUrl::query()->with(['linkDetails'])->whereIn('link_tasks_detail_id', $detailIds)->where(['status' => 5]);
  557. $records = $builder->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);
  558. $items = $records->items();
  559. $idMapLink = Link::query()->select(['type', 'url', 'id'])->get()->keyBy('id')->toArray();
  560. array_walk($items, function ($item) use (&$idMapLink) {
  561. if (!empty($item->linkDetails->link_id)) {
  562. $item->link_url = sprintf('%s【%s】', $idMapLink[$item->linkDetails->link_id]['url'], Link::TYPES[$idMapLink[$item->linkDetails->link_id]['type']]);
  563. } else {
  564. $item->link_url = '';
  565. }
  566. $item->profile_url = $item->linkDetails->url ?? '';
  567. $item->detail_username = $item->linkDetails->username ?? '';
  568. $item->detail_email = $item->linkDetails->email ?? '';
  569. $item->detail_password = $item->linkDetails->password ?? '';
  570. });
  571. return response()->json([
  572. 'rows' => $items,
  573. 'total' => $records->total()
  574. ]);
  575. }
  576. //导出外链url
  577. public function linkUrlExport(Request $request, $siteId)
  578. {
  579. $dateRange = $request->input('date_range');
  580. $linkCondition = $this->getLinkUrlTime($dateRange);
  581. $condition[] = ['redundant_site_id', '=', $siteId];
  582. $condition[] = ['enable', '=', 1];
  583. $condition[] = ['status', '=', 5];
  584. $detailIds = LinkTaskDetail::query()->where($condition)->pluck('id')->toArray();
  585. $builder = LinkTaskUrl::query()->with(['linkDetails'])
  586. ->whereIn('link_tasks_detail_id', $detailIds)->where($linkCondition)->where(['status' => 5])
  587. ->orderBy('id', 'desc');
  588. $records = $builder->get();
  589. $results = [];
  590. foreach ($records as $inx => $item) {
  591. if (!empty($item->linkDetails->link_id)) {
  592. $results[$inx][] = $item->link_url = sprintf(
  593. '%s【%s】',
  594. $item->linkDetails->link_url ?? '',
  595. $item->linkDetails->link_type ?? ''
  596. );
  597. } else {
  598. $results[][$inx] = '';
  599. }
  600. $results[$inx][] = $item->linkDetails->username ?? '';
  601. $results[$inx][] = $item->linkDetails->email ?? '';
  602. $results[$inx][] = $item->linkDetails->password ?? '';
  603. $results[$inx][] = $item->linkDetails->url ?? '';
  604. $results[$inx][] = $item->url ?? '';
  605. $results[$inx][] = $item->created_at;
  606. }
  607. array_unshift($results, ['平台链接', '用户名', '邮箱', '密码', 'profile演示地址', '外链地址', '创建时间']);
  608. return (new BasicExport($results))->download(sprintf('外链地址%s.xls', date('YmdHis')));
  609. }
  610. //删除 link-detail
  611. public function linkDetailDel(Request $request)
  612. {
  613. $ids = $request->input('ids');
  614. LinkTaskDetail::query()->whereIn('id', $ids)->update(['enable' => 0]);
  615. return response()->json(['message' => '操作成功']);
  616. }
  617. public function linkCountSave(LinkCountSaveRequest $request, $linkDetailId)
  618. {
  619. $siteId = $request->input('siteId');
  620. $allLinks = Link::all();
  621. if (!$request->ajax()) {
  622. return view('admin/link/link_count_save', [
  623. 'allLinks' => $allLinks,
  624. 'data' => LinkTaskDetail::query()->find($linkDetailId),
  625. 'siteId' => $siteId
  626. ]);
  627. }
  628. $validated = $request->validated();
  629. $exists = LinkTaskDetail::query()->where(['redundant_site_id' => $siteId, 'link_id' => $validated['link_id'], 'enable' => 1])->select(['id'])->first();
  630. if ($exists && $exists->id != $linkDetailId) {
  631. return response()->json(['message' => '外链类型已存在'], 400);
  632. }
  633. $validated['redundant_site_id'] = $siteId;
  634. $link = Link::query()->where(['id' => $validated['link_id']])->first();
  635. $validated['link_type'] = Link::TYPES[($link->type ?? 0)] ?? '';
  636. $validated['link_url'] = $link->url ?? '';
  637. $validated['enable'] = 1;
  638. $validated['status'] = 5;
  639. $validated['created_at'] = empty($validated['created_at']) ? date('Y-m-d H:i:s') : $validated['created_at'];
  640. LinkTaskDetail::query()->updateOrCreate(['id' => $linkDetailId], $validated);
  641. return response()->json(['message' => '操作成功']);
  642. }
  643. /**
  644. * 外链任务列表
  645. * @param Request $request
  646. * @return Factory|JsonResponse|View
  647. */
  648. public function taskIndex(Request $request)
  649. {
  650. if (!$request->ajax()) {
  651. return view('admin/link/task');
  652. }
  653. $records = $this->logic->taskFilters($request->input())->with(['worker', 'site', 'score'])->with('linkDetails')->with('linkUrls')
  654. ->orderByDesc('id')->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);
  655. $items = $records->items();
  656. array_walk($items, function ($item) {
  657. $item->typeTitle = $item->type_title;
  658. $item->worker_name = $item->worker->username ?? '';
  659. $item->site_title = $item->site->cn_title ?? '';
  660. $item->status_title = $item->status_with_css;
  661. $item->totalScore = $item->score->total ?? '';
  662. $totalUrls = 0;
  663. $detailIdList = $item->linkUrls->groupBy('link_tasks_detail_id')->toArray();
  664. foreach ($item->linkDetails as $detail) {
  665. if (empty($detailIdList[$detail->id])) {
  666. continue;
  667. }
  668. if ($detail->link_type == '一次性') {
  669. $totalUrls += (count($detailIdList[$detail->id]) * 2);
  670. } elseif ($detail->link_type == '书签') {
  671. $totalUrls += (count($detailIdList[$detail->id]) * 0.5);
  672. } else {
  673. $totalUrls += count($detailIdList[$detail->id]);
  674. }
  675. }
  676. $item->linkUrlsCount = $totalUrls;
  677. if ($item->release_at && $item->release_at > date('Y-m-d H:i:s')) {
  678. $item->un_release_at = $item->release_at;
  679. }
  680. });
  681. return response()->json(['rows' => $items,
  682. 'total' => $records->total()]);
  683. }
  684. public function optimizePage(Request $request)
  685. {
  686. $siteId = $request->input('siteId');
  687. $data = SiteOptimizePage::query()->where(['site_id' => $siteId])->get()->toArray();
  688. return response()->json(['data' => $data]);
  689. }
  690. //任务保存
  691. public function taskSave(TaskSaveRequest $request, $id)
  692. {
  693. if (!$request->ajax()) {
  694. if ($id > 0) { //编辑
  695. $link = LinkTask::query()->where(['id' => $id])->first();
  696. if (!$link) {
  697. return response()->json(['message' => '外链任务信息不存在'], 400);
  698. }
  699. $linkIds = LinkTaskDetail::query()->where('task_id', $id)->pluck('link_id')->toArray();
  700. $linkIdsStr = json_encode($linkIds);
  701. $selectedLinkTypeList = Link::query()->whereIn('id', $linkIds)->get();
  702. $optimizePageList = SiteOptimizePage::query()->where(['site_id' => $link->site_id])->get()->toArray();
  703. }
  704. $siteId = $request->input('siteId');
  705. if ($siteId && !isset($optimizePageList)) {
  706. $optimizePageList = SiteOptimizePage::query()->where(['site_id' => $siteId])->get()->toArray();
  707. }
  708. return view('admin/link/task_save', [
  709. 'sites' => $this->userSites(),
  710. 'workers' => User::query()->whereIn('role_id', [Role::TYPE_LINK_PART_CHONGQING, Role::TYPE_LINK_PART])->get(),
  711. 'data' => $link ?? null,
  712. 'siteId' => $request->input('siteId'), //为了项目外链管理 默认选中当前项目
  713. 'linkIdsStr' => $linkIdsStr ?? '',
  714. 'selectedLinkType' => Link::query()->get()->groupBy('type'),
  715. 'typeList' => Link::TYPES,
  716. 'selectedLinkTypeList' => $selectedLinkTypeList ?? [],
  717. 'optimizePageList' => $optimizePageList ?? []
  718. ]);
  719. }
  720. $validated = $request->validated();
  721. if ($id > 0 && !is_array($validated['link']['link_ids'] ?? null)) {
  722. return response()->json(['message' => '修改时请选择外链库'], 400);
  723. }
  724. if (!is_array($validated['link']['link_ids'] ?? null) && !is_array($validated['link']['link_ids_with_time'] ?? null)) {
  725. return response()->json(['message' => '至少选择一种外链方式'], 400);
  726. }
  727. if ($validated['link']['link_ids_with_time'] && $id == 0) {
  728. $groupId = 0;
  729. foreach ($validated['link']['link_ids_with_time'] as $item) {
  730. $this->logic->taskSave($id, $validated['task'], $item['link_ids'], $groupId, $item['release_at']);
  731. }
  732. } else {
  733. $groupId = -1;
  734. $this->logic->taskSave($id, $validated['task'], $validated['link']['link_ids'], $groupId);
  735. }
  736. return response()->json(['message' => '操作成功']);
  737. }
  738. //添加外链任务时 的 任务选择
  739. public function linkChose(Request $request, $taskId)
  740. {
  741. $linkIds = $request->input('linkIds');
  742. $records = Link::query()->get()->groupBy('type');
  743. if ($taskId) {
  744. $hasLinkIds = [];
  745. $task = LinkTask::query()->where(['id' => $taskId])->first();
  746. if ($task) {
  747. $hasLinkIds = $task->links->pluck('id')->toArray();
  748. }
  749. } else {
  750. $hasLinkIds = $linkIds ?? [];
  751. }
  752. $siteId = $request->input('siteId');
  753. if ($siteId) {
  754. $linkHad = Link::query()->whereExists(function (\Illuminate\Database\Query\Builder $query) use ($siteId) {
  755. $query->select(DB::raw(1))
  756. ->from('link_tasks_detail')
  757. ->whereRaw('links.id = link_tasks_detail.link_id and link_tasks_detail.redundant_site_id=' . $siteId);
  758. })->pluck('id')->toArray();
  759. }
  760. return view('admin/link/chose', [
  761. 'typeList' => Link::TYPES,
  762. 'typeLinks' => $records,
  763. 'hasLinkIds' => $hasLinkIds,
  764. 'task' => $task ?? null,
  765. 'linkHad' => $linkHad ?? []
  766. ]);
  767. }
  768. //任务批量删除
  769. public function batchTaskDelete(Request $request)
  770. {
  771. $ids = $request->input('ids');
  772. if (!is_array($ids)) return response()->json(['message' => '删除时参数传递错误'], 422);
  773. LinkTask::destroy($ids);
  774. return response()->json(['message' => '操作成功']);
  775. }
  776. /**
  777. * 外链任务大厅
  778. * @param Request $request
  779. * @return Factory|JsonResponse|View
  780. */
  781. public function hall(Request $request)
  782. {
  783. if (!$request->ajax()) {
  784. return view('admin/link/hall', [
  785. 'notice' => ArticleLinkNotice::query()->where(['type' => 'link'])->first()
  786. ]);
  787. }
  788. $builder = LinkTask::query()->with(['site', 'worker']);
  789. $status = $request->input('status');
  790. if ($status != 6) {
  791. $condition[] = ['status', '=', $status];
  792. }
  793. if ($status != 1) {
  794. $condition[] = ['worker_id', '=', Auth::id()];
  795. }
  796. if ($keyword = $request->input('keyword')) {
  797. $condition[] = ['title', 'like', '%' . $keyword . '%'];
  798. }
  799. $builder->where($condition ?? [])
  800. ->where(function (Builder $b) {
  801. $b->where('release_at', '<', date('Y-m-d H:i:s'))->orWhereNull('release_at');
  802. });
  803. if ($status == 2) {
  804. $noticeGroupIds = LinkTask::query()->where(['worker_id' => Auth::id()])
  805. ->where([
  806. ['release_at', '<', date('Y-m-d H:i:s', strtotime('+2 day'))],
  807. ['release_at', '>', date('Y-m-d H:i:s')],
  808. ['status', '=', 1]
  809. ])->pluck('group_id')->toArray();
  810. $noticeGroupIds = $noticeGroupIds ? $noticeGroupIds : [-1];
  811. $raw = sprintf('(CASE WHEN group_id in (%s) THEN 1 ELSE 0 END) AS flag,link_tasks.*', implode(',', $noticeGroupIds));
  812. $builder->selectRaw($raw)->orderByDesc('flag');
  813. }
  814. if ($status == 6) {
  815. //筛选和用户相关的项目
  816. $siteIds = DB::table('user_has_sites')->where('user_id', Auth::id())->pluck('site_id');
  817. $builder->whereIn('site_id', $siteIds);
  818. }
  819. $tasks = $builder->orderByDesc('id')
  820. ->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);
  821. $items = $tasks->items();
  822. array_walk($items, function ($item) {
  823. $item->status_title = $item->status_with_css;
  824. $item->site_title = $item->site->cn_title ?? '';
  825. $item->worker_name = $item->worker->username ?? '';
  826. });
  827. return response()->json([
  828. 'rows' => $items,
  829. 'total' => $tasks->total()
  830. ]);
  831. }
  832. //兼职外链导入
  833. public function hallWorkerImport(Request $request)
  834. {
  835. set_time_limit(0);
  836. $taskId = $request->input('taskId');
  837. if (!$request->input('excel_path')) {
  838. return response()->json(['message' => '请先上传excel文件'], 422);
  839. }
  840. if (!$taskId) {
  841. return response()->json(['message' => '参数错误'], 422);
  842. }
  843. $details = LinkTaskDetail::query()->where(['task_id' => $taskId])->get();
  844. if ($details->isEmpty()) {
  845. return response()->json(['message' => '外链统计信息不存在'], 422);
  846. }
  847. try {
  848. Excel::import(new LinkHallWorker($taskId), $request->input('excel_path'), 'public');
  849. } catch (\Throwable $throwable) {
  850. Log::error(var_export($throwable->getMessage(), 1));
  851. return response()->json(['message' => '导入失败'], 400);
  852. }
  853. return response()->json(['message' => '操作成功']);
  854. }
  855. //兼职外链导出
  856. public function hallWorkerExport(Request $request)
  857. {
  858. $taskId = $request->input('taskId');
  859. $records = [];
  860. $details = LinkTaskDetail::query()->with(['urls', 'link'])->where(['task_id' => $taskId])->get();
  861. $linkTypes = Link::TYPES;
  862. foreach ($details as $detail) {
  863. $showUrl = [];
  864. foreach ($detail->urls as $url) {
  865. $showUrl[] = $url->url;
  866. }
  867. $records[] = [
  868. // 'link_type' => $detail->link_type,
  869. 'link_type' => $linkTypes[($detail->link->type ?? 0)] ?? '',
  870. // 'link_url' => $detail->link_url,
  871. 'link_url' => $detail->link->url ?? '',
  872. 'link_remark' => $detail->link->remark ?? '',
  873. 'username' => $detail->username,
  874. 'email' => $detail->email,
  875. 'password' => $detail->password,
  876. 'url' => $detail->url,
  877. 'show_url' => implode("\n", $showUrl),
  878. 'remark' => $detail->remark
  879. ];
  880. }
  881. array_unshift($records, ['平台类型', '平台链接', '链接备注', '用户名', '注册邮箱', '密码', 'profile演示地址', '页面演示地址', '备注']);
  882. return (new LinkHallExport($records))->download(sprintf('兼职外链%s.xlsx', date('YmdHis')), \Maatwebsite\Excel\Excel::XLSX);
  883. }
  884. /***
  885. * 外链任务认领
  886. * @param $linkTaskId
  887. * @return \Illuminate\Http\JsonResponse
  888. */
  889. public function linkTaskClaim($linkTaskId)
  890. {
  891. $record = LinkTask::query()->where(['id' => $linkTaskId])->first();
  892. if (!$record) {
  893. return response()->json(['message' => '数据不存在'], 400);
  894. }
  895. if ($record->status != 1) {
  896. return response()->json(['message' => '该任务状态已被他人认领'], 400);
  897. }
  898. $record->status = 2; //任务中
  899. $record->worker_id = Auth::id();
  900. $record->save();
  901. if (!empty($record->group_id)) { //查询是否是分组的
  902. $groupLinkTaskList = LinkTask::query()->where(['group_id' => $record->group_id])->get();
  903. //将分组中其他未认领的 也分配到当前用户
  904. foreach ($groupLinkTaskList as $item) {
  905. if ($item->status == 1) {
  906. $item->status = 2;
  907. $item->worker_id = Auth::id();
  908. $item->save();
  909. }
  910. }
  911. }
  912. return response()->json(['message' => '操作成功']);
  913. }
  914. //释放任务
  915. public function linkTaskRelease($linkTaskId)
  916. {
  917. $record = LinkTask::query()->where(['id' => $linkTaskId])->first();
  918. if (!$record) {
  919. return response()->json(['message' => '数据不存在'], 400);
  920. }
  921. if (!in_array($record->status, [2, 4])) {
  922. return response()->json(['message' => '该任务状态已变化,任务释放失败'], 400);
  923. }
  924. //LinkTaskDetail::query()->where(['task_id'=>$record->id])->delete(); //删除之前人做的信息
  925. $record->worker_id = 0;
  926. $record->status = 1;//待分配
  927. $record->save();
  928. return response()->json(['message' => '操作成功']);
  929. }
  930. /**
  931. * 项目信息展示
  932. * @param $id
  933. * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
  934. */
  935. public function hallShow($id)
  936. {
  937. $record = LinkTask::query()->with('site')->where(['id' => $id])->first();
  938. if ($record) {
  939. $optimize_page_ids = json_decode($record->optimize_page_ids, true);
  940. $optimize_page_ids = is_array($optimize_page_ids) ? $optimize_page_ids : [];
  941. $optimizePageList = SiteOptimizePage::query()->whereIn('id', $optimize_page_ids)->get()->toArray();
  942. }
  943. $condition = ['site_id' => $record->site_id ?? 0];
  944. return view('admin/link/hall_show', [
  945. 'data' => $record,
  946. 'keywordData' => SiteInfo::query()->where($condition)->first(),
  947. 'optimizePageList' => $optimizePageList ?? [],
  948. 'enterpriseData' => SiteEnterprise::query()->with('business')->where($condition)->first(),
  949. 'marketerData' => SiteMarketer::query()->where($condition)->first(),
  950. 'snsData' => SiteSns::query()->where($condition)->first(),
  951. 'businesses' => Business::all(),
  952. 'natures' => Site::NATURE_TYPE,
  953. 'link_remark' => LinkNote::query()->where($condition)->first(),
  954. 'business_license' => Site::query()->where('id', $record->site_id)->value('business_license_business_scope') ?? ''
  955. ]);
  956. }
  957. /**
  958. * 兼职人员保存页面渲染
  959. * @param $id
  960. * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse|\Illuminate\View\View
  961. */
  962. public function hallSave($id)
  963. {
  964. $record = LinkTask::query()->with('links')->where(['id' => $id])->first();
  965. if (!$record) {
  966. return view('admin/errors/tips', [
  967. 'tips' => '数据不存在'
  968. ]);
  969. }
  970. $linkTaskDetailIds = [];
  971. foreach ($record->links as $link) {
  972. $linkTaskDetailIds[] = $link->pivot->id;
  973. }
  974. $idMapUrls = LinkTaskUrl::query()->whereIn('link_tasks_detail_id', $linkTaskDetailIds)
  975. ->get()->groupBy('link_tasks_detail_id')->toArray();
  976. return view('admin/link/hall_save', [
  977. 'data' => $record,
  978. 'linkTypes' => Link::TYPES,
  979. 'idMapUrls' => $idMapUrls ?? []
  980. ]);
  981. }
  982. /**
  983. * 兼职人员保存
  984. * @param WorkerSaveRequest $request
  985. * @param $id
  986. * @return \Illuminate\Http\JsonResponse
  987. */
  988. public function workerSave(WorkerSaveRequest $request, $id)
  989. {
  990. $record = LinkTaskDetail::query()->where(['id' => $id])->first();
  991. if (!$record) return response()->json(['message' => '数据不存在'], 422);
  992. $validated = $request->validated();
  993. $record->update($validated['link_tasks_detail']);
  994. return $this->logic->syncLinkTasksUrl($validated['link_tasks_url']['show_urls'] ?? [], $record->id);
  995. }
  996. /**
  997. * 用户提交审核
  998. * @param $id
  999. * @return \Illuminate\Http\JsonResponse
  1000. */
  1001. public function submitAudit($id)
  1002. {
  1003. $record = LinkTask::query()->where(['id' => $id])->first();
  1004. if (!$record) {
  1005. return response()->json(['message' => '数据不存在'], 422);
  1006. }
  1007. if (!in_array($record->status, [2, 4])) {
  1008. return response()->json(['message' => '只有待审核与审核失败才可提交审核'], 400);
  1009. }
  1010. $detailRecords = LinkTaskDetail::query()->where(['task_id' => $record->id])->get();
  1011. foreach ($detailRecords as $detailRecord) {
  1012. if (empty($detailRecord->url)) {
  1013. return response()->json(['message' => '请先完善信息'], 400);
  1014. }
  1015. }
  1016. $record->status = 3;
  1017. //初次审核时间
  1018. if (empty($record->first_audit_at)) {
  1019. $record->first_audit_at = date('Y-m-d H:i:s');
  1020. }
  1021. $record->save();
  1022. return response()->json(['message' => '操作成功']);
  1023. }
  1024. /**
  1025. * 404检测
  1026. * @param $taskId
  1027. * @return \Illuminate\Http\JsonResponse
  1028. */
  1029. public function check404($taskId)
  1030. {
  1031. $detailIds = LinkTaskDetail::query()->where(['task_id' => $taskId])->pluck('id');
  1032. $taskUrls = LinkTaskUrl::query()->whereIn('link_tasks_detail_id', $detailIds)->get();
  1033. $client = new Client([
  1034. 'verify' => false,
  1035. 'timeout' => 10
  1036. ]); //并发请求链接地址
  1037. $requests = function () use ($client, $taskUrls) {
  1038. foreach ($taskUrls as $item) {
  1039. if (empty($item->url))
  1040. continue;
  1041. yield new \GuzzleHttp\Psr7\Request('GET', $item->url);
  1042. }
  1043. };
  1044. $result = [];
  1045. $pool = new Pool($client, $requests(), [
  1046. 'concurrency' => 5, //同时并发抓取几个
  1047. 'fulfilled' => function (Response $response, $index) use (&$result) {
  1048. $result[$index] = 5; //成功
  1049. },
  1050. 'rejected' => function (\Throwable $throwable, $index) use (&$result) {
  1051. $result[$index] = 4; //失败的
  1052. },
  1053. ]);
  1054. $promise = $pool->promise();
  1055. $promise->wait();
  1056. foreach ($taskUrls as $key => &$item) {
  1057. $item->valid_status = $result[$key];
  1058. $item->save();
  1059. }
  1060. return response()->json(['message' => '操作成功']);
  1061. }
  1062. //更新任务url
  1063. public function updateTaskUrl(Request $request, $urlId)
  1064. {
  1065. $url = $request->input('url');
  1066. LinkTaskUrl::query()->where(['id' => $urlId])->update(['url' => $url]);
  1067. return response()->json(['message' => '操作成功']);
  1068. }
  1069. /**
  1070. * 项目详情外链任务页面渲染
  1071. * @param $id
  1072. * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
  1073. */
  1074. public function taskIndexForSite($id)
  1075. {
  1076. return view('admin/link/task_for_site', [
  1077. 'siteId' => $id
  1078. ]);
  1079. }
  1080. /**
  1081. * 链接审核通过
  1082. * @param Request $request
  1083. * @return \Illuminate\Http\JsonResponse
  1084. */
  1085. public function urlPass(Request $request)
  1086. {
  1087. $urlIds = $request->input('urlIds');
  1088. $taskDetailId = LinkTaskUrl::query()->whereIn('id', $urlIds)->pluck('link_tasks_detail_id');
  1089. $taskId = LinkTaskDetail::query()->whereIn('id', $taskDetailId)->pluck('task_id');
  1090. $linkReviewDate = LinkTask::query()->whereIn('id', $taskId)->first();
  1091. LinkTaskUrl::query()->whereIn('id', $urlIds)->update([
  1092. 'audit_at' => date('Y-m-d H:i:s'),
  1093. 'status' => 5,
  1094. 'audit_reason' => '',
  1095. 'created_at' => $linkReviewDate->link_review_at ?? date('Y-m-d H:i:s'),
  1096. ]);
  1097. return response()->json(['message' => '操作成功']);
  1098. }
  1099. /**
  1100. * 链接审核不通过
  1101. * @param Request $request
  1102. * @return \Illuminate\Http\JsonResponse
  1103. */
  1104. public function urlPassFail(Request $request)
  1105. {
  1106. LinkTaskUrl::query()->whereIn('id', $request->input('urlIds'))->update([
  1107. 'audit_at' => date('Y-m-d H:i:s'),
  1108. 'status' => 4,
  1109. 'audit_reason' => $request->input('audit_reason')
  1110. ]);
  1111. return response()->json(['message' => '操作成功']);
  1112. }
  1113. /**
  1114. * 外链任务详情
  1115. * @param $id
  1116. * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
  1117. */
  1118. public function taskDetail($id)
  1119. {
  1120. $record = LinkTask::query()->with(['site', 'worker', 'links'])->where(['id' => $id])->first();
  1121. $linkTaskDetailIds = [];
  1122. foreach ($record->links as $link) {
  1123. $linkTaskDetailIds[] = $link->pivot->id;
  1124. }
  1125. $taskUrls = LinkTaskUrl::query()->whereIn('link_tasks_detail_id', $linkTaskDetailIds)
  1126. ->get();
  1127. $idMapUrls = $taskUrls->groupBy('link_tasks_detail_id')->toArray();
  1128. return view('admin/link/task_detail_for_site', [
  1129. 'data' => $record,
  1130. 'idMapUrls' => $idMapUrls,
  1131. 'taskUrls' => $taskUrls,
  1132. 'taskScore' => LinkTaskScore::query()->where(['task_id' => $id])->first()
  1133. ]);
  1134. }
  1135. /**
  1136. * 外链任务审核通过
  1137. * @param Request $request
  1138. * @return \Illuminate\Http\JsonResponse
  1139. */
  1140. public function taskPass(Request $request)
  1141. {
  1142. $task = LinkTask::query()->where(['status' => 3, 'id' => $request->input('taskId')])->first();
  1143. if (!$task) {
  1144. return response()->json(['message' => '该任务不处于待审核状态或不存在'], 400);
  1145. }
  1146. $taskDetailRecords = LinkTaskDetail::query()->with(['urls', 'link'])->where(['task_id' => $task->id])->get();
  1147. foreach ($taskDetailRecords as $detailRecord) {
  1148. foreach ($detailRecord->urls as $item) {
  1149. if ($item->status == 3) {
  1150. return response()->json(['message' => '请先审核完演示地址'], 400);
  1151. }
  1152. }
  1153. }
  1154. $task->update(['status' => 5, 'audit_at' => date('Y-m-d H:i:s')]);
  1155. LinkTaskDetail::query()->where(['task_id' => $task->id])->update(['status' => 5]);
  1156. return response()->json(['message' => '操作成功']);
  1157. }
  1158. /**
  1159. * 外链任务审核失败
  1160. * @param Request $request
  1161. * @return \Illuminate\Http\JsonResponse
  1162. */
  1163. public function taskPassFail(Request $request)
  1164. {
  1165. $task = LinkTask::query()->where(['status' => 3, 'id' => $request->input('taskId')])->first();
  1166. if (!$task) {
  1167. return response()->json(['message' => '该任务不处于待审核状态或不存在'], 400);
  1168. }
  1169. $taskDetailRecords = LinkTaskDetail::query()->with(['urls'])->where(['task_id' => $task->id])->get();
  1170. foreach ($taskDetailRecords as $detailRecord) {
  1171. foreach ($detailRecord->urls as $item) {
  1172. if ($item->status == 3) {
  1173. return response()->json(['message' => '请先审核完演示地址'], 400);
  1174. }
  1175. }
  1176. }
  1177. $task->update(['status' => 4, 'audit_at' => date('Y-m-d H:i:s'), 'audit_reason' => $request->input('audit_reason')]);
  1178. LinkTaskDetail::query()->where(['task_id' => $task->id])->update(['status' => 4]);
  1179. return response()->json(['message' => '操作成功']);
  1180. }
  1181. /**
  1182. * 任务结算列表
  1183. * @param Request $request
  1184. * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\JsonResponse|\Illuminate\View\View
  1185. */
  1186. public function calc(Request $request)
  1187. {
  1188. if (!$request->ajax()) {
  1189. return view('admin/link/calc');
  1190. }
  1191. // 注意 group_concat长度限制
  1192. $records = $this->logic->calcFilter($request->input())//查询已审核的并按照兼职人员分组
  1193. ->where(['status' => 5])->selectRaw('worker_id,GROUP_CONCAT(id) as task_ids')
  1194. ->groupBy('worker_id')->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);
  1195. $items = $records->items();
  1196. //一次性注册任务每条演示地址记为2条计算、书签每条记为0.5条
  1197. //我也不想foreach套sql 计划赶不上变化
  1198. $result = [];
  1199. foreach ($items as $inx => $item) {
  1200. $taskIds = explode(',', $item->task_ids);
  1201. $taskDetailList = LinkTaskDetail::query()->select(['link_type', 'id'])->whereIn('task_id', $taskIds)->where(['status' => 5])->get();
  1202. $taskScoreList = LinkTaskScore::query()->whereIn('task_id', $taskIds)->get();
  1203. $totalScore = 0;
  1204. foreach ($taskScoreList as $taskScore) {
  1205. $totalScore += intval($taskScore->total);
  1206. }
  1207. //质量平均分
  1208. if ($taskScoreList->count() > 0) {
  1209. $avgScore = $totalScore / $taskScoreList->count();
  1210. } else {
  1211. $avgScore = 0;
  1212. }
  1213. $once = [];
  1214. $bookmark = [];
  1215. $other = [];
  1216. foreach ($taskDetailList as $detailItem) {
  1217. if ($detailItem->link_type == "一次性") {
  1218. $once[] = $detailItem->id;
  1219. } elseif ($detailItem->link_type == "书签") {
  1220. $bookmark[] = $detailItem->id;
  1221. } else {
  1222. $other[] = $detailItem->id;
  1223. }
  1224. }
  1225. $onceNum = LinkTaskUrl::query()->whereIn('link_tasks_detail_id', $once)->where(['status' => 5])->count();
  1226. $bookmarkNum = LinkTaskUrl::query()->whereIn('link_tasks_detail_id', $bookmark)->where(['status' => 5])->count();
  1227. $otherNum = LinkTaskUrl::query()->whereIn('link_tasks_detail_id', $other)->where(['status' => 5])->count();
  1228. $urlNum = $onceNum * 2 + $bookmarkNum * 0.5 + $otherNum;
  1229. $result[$inx]['url_num'] = $urlNum;
  1230. $result[$inx]['amount'] = $urlNum;
  1231. $result[$inx]['username'] = $item->worker->username ?? '';
  1232. $result[$inx]['user_id'] = $item->worker->id ?? '';
  1233. $result[$inx]['avgScore'] = round($avgScore, 2);
  1234. $result[$inx]['task_ids'] = $taskIds;
  1235. }
  1236. return response()->json([
  1237. 'rows' => array_values($result),
  1238. 'total' => $records->total()
  1239. ]);
  1240. }
  1241. //结算历史
  1242. public function calcHistory(Request $request)
  1243. {
  1244. $user = Auth::user();
  1245. // $filters[] = ['status', '=', 6];
  1246. if (empty($user->is_super)) {
  1247. $filters[] = ['user_id', '=', Auth::id()];
  1248. }
  1249. if (!$request->ajax()) {
  1250. // $taskUrlCount = LinkTask::query()->with(['worker'])->where($filters)->sum('settle_amount');
  1251. return view('/admin/link/calc_history', [
  1252. // 'totalAmount' => $taskUrlCount * 1
  1253. ]);
  1254. }
  1255. $inputs = $request->input();
  1256. if (!empty($inputs['keyword'])) {
  1257. $filters[] = ['username', 'like', '%' . $request->input('keyword') . '%'];
  1258. }
  1259. !empty($inputs['start_at']) && $filters[] = ['audit_at', '>=', $inputs['start_at']];
  1260. !empty($inputs['end_at']) && $filters[] = ['audit_at', '<=', $inputs['end_at']];
  1261. $records = LinkCalc::query()->where($filters ?? [])->paginate($request->input('pageSize') ?? TABLE_PAGE_SIZE);
  1262. $items = $records->items();
  1263. $result = [];
  1264. $totalAmount = 0;
  1265. $totalLinkNum = 0;
  1266. foreach ($items as $key => $item) {
  1267. $result[$key]['amount'] = $item->amount;
  1268. $result[$key]['link_num'] = $item->url_num;
  1269. $result[$key]['username'] = $item->username;
  1270. $result[$key]['settle_at'] = $item->settle_at;
  1271. $totalAmount = bcadd($totalAmount, intval($item->settle_amount), 2);
  1272. $totalLinkNum += intval($item->url_num);
  1273. }
  1274. return response()->json([
  1275. 'rows' => array_values($result),
  1276. 'total' => $records->total(),
  1277. 'totalAmount' => $totalAmount,
  1278. 'totalLinkNum' => $totalLinkNum
  1279. ]);
  1280. }
  1281. /**
  1282. * 任务结算
  1283. * @param Request $request
  1284. * @return \Illuminate\Http\JsonResponse
  1285. */
  1286. public function settle(Request $request)
  1287. {
  1288. $dataList = $request->input('dataList');
  1289. foreach ($dataList as $data) {
  1290. LinkTask::query()->whereIn('id', $data['task_ids'])->update([
  1291. 'status' => 6
  1292. ]);
  1293. LinkCalc::query()->create([
  1294. 'user_id' => $data['user_id'],
  1295. 'username' => $data['username'],
  1296. 'task_ids' => json_encode($data['task_ids']),
  1297. 'amount' => $data['amount'],
  1298. 'url_num' => $data['url_num'],
  1299. 'settle_at' => date('Y-m-d H:i:s')
  1300. ]);
  1301. }
  1302. return response()->json(['message' => '操作成功']);
  1303. }
  1304. //导入外链
  1305. public function linkImport(Request $request, $siteId)
  1306. {
  1307. set_time_limit(0);
  1308. if (!$request->input('excel_path')) {
  1309. return response()->json(['message' => '请先上传excel文件'], 422);
  1310. }
  1311. try {
  1312. Excel::import(new LinkImport($siteId), $request->input('excel_path'), 'public');
  1313. } catch (\Throwable $throwable) {
  1314. Log::error(var_export($throwable->getMessage(), 1));
  1315. return response()->json(['message' => '导入失败'], 400);
  1316. }
  1317. return response()->json(['message' => '操作成功']);
  1318. }
  1319. //任务评分
  1320. public function taskScore(TaskScoreRequest $request, $taskId)
  1321. {
  1322. $validated = $request->validated();
  1323. $taskScore = LinkTaskScore::query()->where(['task_id' => $taskId])->first();
  1324. if ($taskScore) {
  1325. $taskScore->update($validated);
  1326. } else {
  1327. $validated['task_id'] = $taskId;
  1328. LinkTaskScore::query()->create($validated);
  1329. }
  1330. return response()->json(['message' => '操作成功']);
  1331. }
  1332. //外链备注
  1333. public function siteLinkNote(Request $request, $siteId)
  1334. {
  1335. if (!$request->ajax()) {
  1336. $note = LinkNote::query()->where(['site_id' => $siteId])->first();
  1337. return view('admin.link.note', [
  1338. 'siteId' => $siteId,
  1339. 'data' => $note,
  1340. ]);
  1341. }
  1342. $content = $request->input('content');
  1343. $note = LinkNote::query()->where(['site_id' => $siteId])->first();
  1344. if ($note) {
  1345. $note->update(['content' => $content]);
  1346. } else {
  1347. LinkNote::query()->create([
  1348. 'site_id' => $siteId,
  1349. 'content' => $content,
  1350. ]);
  1351. }
  1352. return response()->json(['message' => '操作成功']);
  1353. }
  1354. public function externalChainLibraryImport(Request $request)
  1355. {
  1356. set_time_limit(0);
  1357. if (!$request->input('excel_path')) {
  1358. return response()->json(['message' => '请先上传excel文件'], 422);
  1359. }
  1360. try {
  1361. Excel::import(new ExternalChainLibraryImport(), $request->input('excel_path'), 'public');
  1362. } catch (\Throwable $throwable) {
  1363. Log::error(var_export($throwable->getMessage(), 1));
  1364. return response()->json(['message' => '导入失败'], 400);
  1365. }
  1366. return response()->json(['message' => '操作成功']);
  1367. }
  1368. public function externalChainLibraryExport(Request $request)
  1369. {
  1370. $link = Link::query();
  1371. $request = $request->all();
  1372. if (!empty($request['type'])) {
  1373. $link->where('type', $request['type']);
  1374. }
  1375. if (!empty($request['business_ids'])) {
  1376. $link->whereRaw('FIND_IN_SET(?,business_ids)', [$request['business_ids']]);
  1377. }
  1378. if (!empty($request['keyword'])) {
  1379. $link->where('url', 'like', '%' . $request['keyword'] . '%');
  1380. }
  1381. $businesses = Business::query()->pluck('title', 'id');
  1382. $data = [];
  1383. $list = $link->orderBy('id', 'desc')->get();
  1384. $type = [0 => '否', 1 => '是'];
  1385. foreach ($list as $value) {
  1386. $value->bigBall = $type[$value->big_ball] ?? '';
  1387. $business = explode(',', $value->business_ids);
  1388. $list = [];
  1389. foreach ($business as $item) {
  1390. $list[] = $businesses[$item] ?? '';
  1391. }
  1392. if (!empty($list)) {
  1393. $value->business = implode(',', $list);
  1394. } else {
  1395. $value->business = '';
  1396. }
  1397. $data[] = [
  1398. 'typeTitle' => Link::TYPES[$value->type] ?? '',
  1399. 'tag' => $value->tag,
  1400. 'url' => $value->url,
  1401. 'business' => $value->business,
  1402. 'authority_score' => $value->authority_score,
  1403. 'spam_score' => $value->spam_score,
  1404. 'bigBall' => $value->bigBall,
  1405. 'remark' => $value->remark,
  1406. 'created_at' => $value->created_at,
  1407. ];
  1408. }
  1409. array_unshift($data, ['外链类型', '标签', '平台链接', '行业', 'Authority Score', 'Spam Score', '锚文本', '备注', '创建时间']);
  1410. return (new BasicExport($data))->download(sprintf('外链列表%s.xls', date('YmdHis')));
  1411. }
  1412. }