MeterLogic.php 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: Administrator
  5. * Date: 2019/4/29 0029
  6. * Time: 17:16
  7. */
  8. namespace App\Http\Logics\Admin;
  9. use App\Http\Models\Article;
  10. use App\Http\Models\Business;
  11. use App\Http\Models\Contract;
  12. use App\Http\Models\CustomerLog;
  13. use App\Http\Models\Link;
  14. use App\Http\Models\LinkTask;
  15. use App\Http\Models\LinkTaskDetail;
  16. use App\Http\Models\MasterMeter;
  17. use App\Http\Models\Role;
  18. use App\Http\Models\Site;
  19. use App\Http\Models\SiteProcess;
  20. use App\Http\Models\UrlCheck;
  21. use App\Http\Models\User;
  22. use \Illuminate\Database\ConnectionInterface;
  23. use Illuminate\Database\Query\Builder;
  24. use Illuminate\Support\Collection;
  25. use Illuminate\Support\Facades\Auth;
  26. use Illuminate\Support\Facades\DB;
  27. use Illuminate\Database\Eloquent\Relations\HasMany;
  28. class MeterLogic
  29. {
  30. public function indexLast5Sites(ConnectionInterface $rankDatabase, &$validSiteIds)
  31. {
  32. $contracts = Contract::query()->pluck('title', 'id')->toArray();
  33. //order_at 下单时间=合同时间 文章数
  34. $last5Sites = Site::query()->whereIn('id', $validSiteIds)->withCount(['articles', 'linkTasks'])
  35. ->with(['users'])->limit(5)->orderByDesc('order_at')->get();
  36. //top10 首页 top30 前三页
  37. //rank 205 project doKeyword line
  38. $oldIds = array_filter($last5Sites->pluck('old_id')->toArray());
  39. // $oldIds = [90];
  40. $last5SitesKeywords = $rankDatabase->table('project_keyword')->selectRaw('
  41. SUM(CASE WHEN google_rank <= 10 THEN 1 ELSE 0 END) as top10,
  42. SUM(CASE WHEN google_rank <= 30 THEN 1 ELSE 0 END) as top30,
  43. SUM(CASE WHEN google_rank <= 50 THEN 1 ELSE 0 END) as top100,
  44. project_id
  45. ')->where('google_rank', '<>', 9999)->whereIn('project_id', $oldIds)
  46. ->groupBy('project_id')->get()->keyBy('project_id')->toArray();
  47. foreach ($last5Sites as $lastSite) {
  48. $contractIds = $lastSite->contract_ids ?? [];
  49. $lastSite->contractsTitle = implode(',', array_map(function ($item) use (&$contracts) {
  50. return $contracts[$item];
  51. }, $contractIds));
  52. // $lastSite->keywords = $last5SitesKeywords[90] ?? [];
  53. $lastSite->keywords = $last5SitesKeywords[$lastSite->old_id] ?? [];
  54. //到期时间 达标日期往后推10个月
  55. // $lastSite->is_expired = (time() > strtotime('+10 month', strtotime($lastSite['reach_at'])));
  56. $lastSite->expired_time = $lastSite['reach_at'] ?
  57. strtotime('+10 month', strtotime($lastSite['reach_at'])) : null;
  58. //引擎力顾问
  59. $lastSite->managesInfo = $lastSite->users->where('role_id', Role::TYPE_MANAGER);
  60. $lastSite->serverUsersArray = array_values($lastSite->users->where('role_id', Role::TYPE_SERVER)->toArray());
  61. }
  62. return $last5Sites;
  63. }
  64. public function indexDropKeywordSites(ConnectionInterface $rankDatabase, &$validSiteIds)
  65. {
  66. //关键词排名急剧下降
  67. $nowMonthKeywords = $rankDatabase->table('project_history')->selectRaw('max(create_time),top10,project_id')->where([
  68. ['create_time', '>', strtotime(date('Y-m-01'))],
  69. ['create_time', '<', strtotime(date('Y-m-t 23:59:59'))],
  70. ])->groupBy('project_id')->pluck('top10', 'project_id')->toArray();
  71. $lastMonthKeywords = $rankDatabase->table('project_history')->selectRaw('max(create_time),top10,project_id')->where([
  72. ['create_time', '>', strtotime(date('Y-m-01', strtotime('-1 month')))],
  73. ['create_time', '<', strtotime(date('Y-m-t 23:59:59', strtotime('-1 month')))],
  74. ])->groupBy('project_id')->pluck('top10', 'project_id')->toArray();
  75. $dropResults = [];
  76. foreach ($lastMonthKeywords as $inx => $val) {
  77. $nowTop10 = $nowMonthKeywords[$inx] ?? 0;
  78. $lessVal = $val - $nowTop10;
  79. if ($lessVal > 20) {
  80. $dropResults[$inx] = ['project_id' => $inx, 'nowTop10' => $nowTop10, 'lastTop10' => $val];
  81. }
  82. }
  83. $keyDropSites = Site::query()->with('users')->select(['id', 'old_id', 'domain', 'cn_title'])->whereIn('id', $validSiteIds)
  84. ->whereIn('old_id', array_column($dropResults, 'project_id'))->get()->keyBy('id');
  85. foreach ($keyDropSites as $item){
  86. $item->dropResults = $dropResults[$item->old_id];
  87. $item->managers_title = implode('-', $item->users->where('role_id', Role::TYPE_MANAGER)->pluck('nickname')->toArray());
  88. $item->optimizerTitle = implode('-', $item->users->where('role_id', Role::TYPE_OPTIMIZER)->pluck('nickname')->toArray());
  89. }
  90. return $keyDropSites;
  91. }
  92. public function indexReachSites(&$validSiteIds, $dateRangeFilter = null)
  93. {
  94. //关键词达标的 sites_process.process_id=17 关键词达标
  95. $builder = Site::query()->select(['reach_at', 'cn_title', 'id', 'domain'])->with(['sitesProcess' => function (HasMany $builder) {
  96. $builder->where(['process_id' => 17]);
  97. }, 'sitePayment'])->whereExists(function (Builder $builder) {
  98. $builder->select(DB::raw(1))->from('sites_process')
  99. ->whereRaw('sites.id=sites_process.site_id AND sites_process.process_id=17 AND sites_process.active=1');
  100. });
  101. if ($dateRangeFilter) {
  102. $builder->where($dateRangeFilter);
  103. } else {
  104. $builder->where([['reach_at', '<', date('Y-m-d H:i:s')]]);
  105. }
  106. return $builder->whereIn('id', $validSiteIds)->get();
  107. }
  108. public function indexBuildDoneSites(&$validSiteIds, $dateRangeFilter = null)
  109. {
  110. ////建站完成的 process_id_15网站上线
  111. $builder = Site::query()->select(['reach_at', 'cn_title', 'id', 'domain'])->with(['sitesProcess' => function (HasMany $builder) {
  112. $builder->where(['process_id' => 15]);
  113. }])->whereExists(function (Builder $builder) {
  114. $builder->select(DB::raw(1))->from('sites_process')
  115. ->whereRaw('sites.id=sites_process.site_id AND sites_process.process_id=15 AND sites_process.active=1');
  116. });
  117. if ($dateRangeFilter) {
  118. $builder->where($dateRangeFilter);
  119. }
  120. return $builder->whereIn('id', $validSiteIds)->get();
  121. }
  122. public function indexMasterMeterTrafficsRemark(ConnectionInterface $rankDatabase, &$validSiteIds)
  123. {
  124. $masterMeterRecords = MasterMeter::query()->where([
  125. ['ym', '=', date('Ym')],
  126. ['traffic', '>=', 300]
  127. ])->whereIn('site_id', $validSiteIds)->get()->groupBy('site_id');
  128. $masterMeterRecords = $masterMeterRecords->map(function (Collection $items) {
  129. return $items->last();
  130. });
  131. $masterMeterRecordsList = $masterMeterRecords->toArray();
  132. $oldIds = array_column($masterMeterRecordsList, 'old_id');
  133. // $rankDatabase->table('project_history')->select('top10')->orderByDesc('create_time')->first();
  134. $top10ListMap = $rankDatabase->table('project_keyword')
  135. ->selectRaw('SUM(CASE WHEN google_rank <= 10 THEN 1 ELSE 0 END) as top10,project_id')->whereIn('project_id', $oldIds)
  136. ->groupBy('project_id')->get()->keyBy('project_id')->toArray();
  137. array_walk($masterMeterRecordsList, function (&$record) use (&$top10ListMap) {
  138. $record['top10'] = '-';
  139. foreach ($top10ListMap as $item) {
  140. if ($item->project_id == $record['old_id']) {
  141. $record['top10'] = $item->top10;
  142. }
  143. }
  144. });
  145. $groupList = [300 => [], 500 => [], 1000 => []];
  146. foreach ($masterMeterRecordsList as $item) {
  147. if ($item['traffic'] >= 300 && $item['traffic'] < 500) {
  148. $groupList[300][] = $item;
  149. }
  150. if ($item['traffic'] >= 500 && $item['traffic'] < 1000) {
  151. $groupList[500][] = $item;
  152. }
  153. if ($item['traffic'] >= 1000) {
  154. $groupList[1000][] = $item;
  155. }
  156. }
  157. return $groupList;
  158. }
  159. public function indexMasterMeterTraffics(ConnectionInterface $rankDatabase, &$validSiteIds)
  160. {
  161. $masterMeterRecords = MasterMeter::query()->where([
  162. ['ym', '=', date('Ym')],
  163. ['traffic', '>=', 300]
  164. ])->whereIn('site_id', $validSiteIds)->get()->groupBy('site_id');
  165. $masterMeterRecords = $masterMeterRecords->map(function (Collection $items) {
  166. return $items->last();
  167. });
  168. $oldIdMapProjects = $masterMeterRecords->keyBy('old_id')->toArray();
  169. $masterMeterRecordsList = $masterMeterRecords->toArray();
  170. $oldIds = array_column($masterMeterRecordsList, 'old_id');
  171. $top10ListMap = $rankDatabase->table('project_keyword')
  172. ->selectRaw('SUM(CASE WHEN google_rank <= 10 THEN 1 ELSE 0 END) as top10,project_id')->whereIn('project_id', $oldIds)
  173. ->groupBy('project_id')->get()->keyBy('project_id')->toArray();
  174. // array_walk($masterMeterRecordsList, function (&$record) use (&$top10ListMap) {
  175. // $record['top10'] = '-';
  176. // foreach ($top10ListMap as $item) {
  177. // if ($item->project_id == $record['old_id']) {
  178. // $record['top10'] = $item->top10;
  179. // }
  180. // }
  181. // });
  182. //
  183. $oldIdMapClicks = $rankDatabase->table('webmaster_effect')->selectRaw('SUM(clicks) as clicks,project_id')
  184. ->whereIn('project_id', $oldIds)->where(['ym' => date('Ym', strtotime('first day of -1 month'))])
  185. ->groupBy('project_id')->get()->keyBy('project_id')->toArray();
  186. $groupList = [300 => [], 500 => [], 1000 => []];
  187. foreach ($oldIdMapClicks as $inx => $item) {
  188. $clicks = intval($item->clicks);
  189. if ($clicks >= 300 && $clicks < 500) {
  190. $groupList[300][] = $oldIdMapProjects[$inx] + ['clicks' => $clicks] + ['top10' => $top10ListMap[$inx]->top10 ?? 0];
  191. }
  192. if ($clicks >= 500 && $clicks < 1000) {
  193. $groupList[500][] = $oldIdMapProjects[$inx] + ['clicks' => $clicks] + ['top10' => $top10ListMap[$inx]->top10 ?? 0];
  194. }
  195. if ($clicks >= 1000) {
  196. $groupList[1000][] = $oldIdMapProjects[$inx] + ['clicks' => $clicks] + ['top10' => $top10ListMap[$inx]->top10 ?? 0];
  197. }
  198. }
  199. return $groupList;
  200. }
  201. public function indexKeywordTotal(ConnectionInterface $rankDatabase, &$validOldSiteIds)
  202. {
  203. //'project.number' => 1, //1,2,3
  204. // //关键词总量
  205. return $rankDatabase->table('project_keyword')
  206. ->leftJoin('project', 'project.id', '=', 'project_keyword.project_id')
  207. ->where(['project.allow_googlerank' => 1])
  208. ->whereIn('project_id', $validOldSiteIds)
  209. ->count();
  210. }
  211. public function indexSiteStatus(&$validSiteIds)
  212. {
  213. //"上线确认之后"就是建站期结束进入优化期,达标确认之后就是优化期结束进入服务期
  214. //建站期项目数 15 网站上线
  215. // $onlineSiteIds = SiteProcess::query()->where(['process_id' => 15, 'active' => 1])->pluck('site_id')->toArray();
  216. // $onlineCount = Site::query()->where(['status' => 1])->whereNotIn('id', $onlineSiteIds)->count();
  217. $onlineCount = Site::query()->whereIn('id', $validSiteIds)->where(['status' => 1])->count();
  218. //实施期项目数 seo检查16 关键词达标17 处理中期间则说明处于实施期
  219. // $implementSiteIds = SiteProcess::query()->where(['process_id' => 16, 'active' => 2])->orWhere([
  220. // 'process_id' => 17, 'active' => 2
  221. // ])->pluck('site_id')->toArray();
  222. // $implementCount = Site::query()->where(['status' => 1])->whereIn('id', $implementSiteIds)->count();
  223. $implementCount = Site::query()->whereIn('id', $validSiteIds)->where(['status' => 2])->count();
  224. //服务期项目数
  225. // $serviceSiteIds = SiteProcess::query()->where(['process_id' => 17, 'active' => 1])->pluck('site_id')->toArray();
  226. // $serviceCount = Site::query()->where(['status' => 1])->whereIn('id', $serviceSiteIds)->count();
  227. $serviceCount = Site::query()->whereIn('id', $validSiteIds)->where(['status' => 3])->count();
  228. //暂停的项目数
  229. $pauseCount = Site::query()->whereIn('id', $validSiteIds)->where(['status' => 4])->count();
  230. return [
  231. 'xAxis' => ['建站期', '实施期', '服务期', '暂停期'],
  232. 'yAxis' => [$onlineCount, $implementCount, $serviceCount, $pauseCount],
  233. 'hybrid' => [
  234. ['name' => '建站期', 'value' => $onlineCount],
  235. ['name' => '实施期', 'value' => $implementCount],
  236. ['name' => '服务期', 'value' => $serviceCount],
  237. ['name' => '暂停期', 'value' => $pauseCount],
  238. ]
  239. ];
  240. }
  241. public function indexNature(&$validSiteIds)
  242. {
  243. //公司类型统计
  244. $natureCount = Site::query()->selectRaw('COUNT(id) as total,nature_type')
  245. ->whereIn('id', $validSiteIds)
  246. ->groupBy('nature_type')->get()->toArray();
  247. $natureCountMap = array_column($natureCount, 'total', 'nature_type');
  248. $natureHybrid = array_map(function ($item) use ($natureCountMap) {
  249. return [
  250. 'name' => $item['val'],
  251. 'value' => $natureCountMap[$item['inx']] ?? 0
  252. ];
  253. }, Site::NATURE_TYPE);
  254. return [
  255. 'name' => array_column(Site::NATURE_TYPE, 'val'),
  256. 'hybrid' => $natureHybrid
  257. ];
  258. }
  259. public function indexBusiness(&$validSiteIds)
  260. {
  261. //根据公司行业
  262. $businessCount = Site::query()->selectRaw('COUNT(id) as total,business_id')
  263. ->whereIn('id', $validSiteIds)->groupBy('business_id')->get()->toArray();
  264. $businessCountMap = array_column($businessCount, 'total', 'business_id');
  265. $businessMap = Business::query()->select(['title', 'id'])->get()->toArray();
  266. $businessHybrid = array_map(function ($item) use ($businessCountMap) {
  267. return [
  268. 'name' => $item['title'],
  269. 'value' => $businessCountMap[$item['id']] ?? 0
  270. ];
  271. }, $businessMap);
  272. return [
  273. 'name' => array_column($businessMap, 'title'),
  274. 'hybrid' => $businessHybrid
  275. ];
  276. }
  277. protected function lastSixMonths()
  278. {
  279. $sixMonth = [];
  280. for ($i = 0; $i < 6; $i++) {
  281. $sixMonth[] = date("Y-m", strtotime("first day of -$i month"));
  282. }
  283. return $sixMonth;
  284. }
  285. protected function lastSixMonthsASC()
  286. {
  287. $sixMonth = [];
  288. for ($i = 5; $i >= 0; $i--) {
  289. $sixMonth[] = date("Y-m", strtotime("first day of -$i month"));
  290. }
  291. return $sixMonth;
  292. }
  293. protected function passSixMonthsASC()
  294. {
  295. $sixMonth = [];
  296. for ($i = 6; $i >= 1; $i--) {
  297. $sixMonth[] = date("Y-m", strtotime("first day of -$i month"));
  298. }
  299. return $sixMonth;
  300. }
  301. public function indexSales(&$validSiteIds)
  302. {
  303. $channelType = [Role::TYPE_CHANNEL_BOSS, Role::TYPE_CHANNEL_MANAGER, Role::TYPE_CHANNEL_WORKER];
  304. //渠道销售占比
  305. $channelSales = Site::query()->whereIn('id', $validSiteIds)->selectRaw('COUNT(id) as total,LEFT(order_at,7) as orderYm')->whereExists(function (Builder $builder) use ($channelType) {
  306. $builder->select(DB::raw(1))->from('users')
  307. // ->whereRaw(sprintf('users.id=sites.creator_id AND users.role_id=%s', Role::TYPE_CHANNEL));
  308. ->whereRaw(sprintf('users.id=sites.creator_id AND users.role_id in (%s)', implode(',', $channelType)));
  309. })->groupBy('orderYm')->orderByDesc('orderYm')->get()->pluck('total', 'orderYm')->toArray();
  310. $notChannelSales = Site::query()->whereIn('id', $validSiteIds)->selectRaw('COUNT(id) as total,LEFT(order_at,7) as orderYm')->whereNotExists(function (Builder $builder) use ($channelType) {
  311. $builder->select(DB::raw(1))->from('users')
  312. // ->whereRaw(sprintf('users.id=sites.creator_id AND users.role_id=%s', Role::TYPE_CHANNEL));
  313. ->whereRaw(sprintf('users.id=sites.creator_id AND users.role_id in (%s)', implode(',', $channelType)));
  314. })->groupBy('orderYm')->orderByDesc('orderYm')->get()->pluck('total', 'orderYm')->toArray();
  315. $lastSixMonths = $this->lastSixMonths();
  316. $channelResults = $notChannelResults = [];
  317. foreach ($lastSixMonths as $month) {
  318. $channelResults[$month] = $channelSales[$month] ?? 0;
  319. $notChannelResults[$month] = $notChannelSales[$month] ?? 0;
  320. }
  321. return [
  322. 'xAxis' => $lastSixMonths,
  323. 'channelSales' => array_values($channelResults),
  324. 'notChannelSales' => array_values($notChannelResults)
  325. ];
  326. }
  327. public function indexCertExpiredSites(&$validSiteIds)
  328. {
  329. //证书过期项目
  330. return $certExpiredSites = Site::query()->whereIn('id', $validSiteIds)
  331. ->whereDate('cert_expired_date', '<', date('Y-m-d', strtotime('+1 month')))->get();
  332. }
  333. public function indexDomainExpiredSites(&$validSiteIds)
  334. {
  335. //域名过期项目
  336. return $domainExpiredSites = Site::query()->whereIn('id', $validSiteIds)
  337. ->whereDate('domain_expired_date', '<', date('Y-m-d', strtotime('+1 month')))->get();
  338. }
  339. public function indexLinksLine()
  340. {
  341. $linkTypes = Link::TYPES + [0 => '已过期'];
  342. $linkRecords = Link::query()->selectRaw('COUNT(id) as total,type')
  343. ->groupBy('type')->pluck('total', 'type')->toArray();
  344. $typeTotals = [];
  345. foreach ($linkTypes as $key => $val) {
  346. $typeTotals[$key] = $linkRecords[$key] ?? 0;
  347. }
  348. $typeTotals[0] = Link::onlyTrashed()->count();//获取已删除的
  349. return [
  350. 'xAxis' => array_values($linkTypes),
  351. 'yAxis' => array_values($typeTotals),
  352. ];
  353. }
  354. public function indexExpireSiteProcessList(&$validSiteIds)
  355. {
  356. //流程过期提醒
  357. return SiteProcess::query()->with(['process', 'site'])->where([
  358. ['active', '=', 2],
  359. ['should_end_at', '<', date('Y-m-d H:i:s')],
  360. ])->whereIn('site_id', $validSiteIds)->get();
  361. }
  362. const CUSTOMER_FIELD_MAP = [
  363. 'addition' => [ //网站信息
  364. 'domain_type' => '新域名注册',
  365. 'new_domain' => '新域名信息',
  366. 'old_domain' => '旧域名信息-域名',
  367. 'old_url' => '旧域名信息-注册网址',
  368. 'old_account' => '旧域名信息-登陆账号',
  369. 'old_password' => '旧域名信息-密码',
  370. 'old_expired' => '旧域名信息-域名到期时间',
  371. 'site_url' => '网站后台账号-后台网址',
  372. 'site_account' => '网站后台账号-用户名',
  373. 'site_password' => '网站后台账号-密码',
  374. 'ftp_account' => 'FTP-FTP Username',
  375. 'ftp_domain' => 'FTP-FTP 服务器',
  376. 'ftp_password' => 'FTP-登录密码',
  377. 'ftp_port' => 'FTP-连接端口',
  378. 'ftp_ip' => 'FTP-IP地址',
  379. ],
  380. 'enterprise' => [ //项目基础信息
  381. 'export_region' => '主要出口国家或市场',
  382. 'business_id' => '所属行业',
  383. 'nature_type' => '公司类型',
  384. 'customer_scope' => '客户群体',
  385. 'brand' => '品牌',
  386. 'cn_title' => '公司名称(中文)',
  387. 'cn_profile' => '公司简介(中文)',
  388. 'en_title' => '公司名称(英文)',
  389. 'en_profile' => '公司简介(英文)',
  390. 'cn_address' => '公司地址(中文)',
  391. 'en_address' => '公司地址(英文)',
  392. 'setup_time' => '公司成立时间',
  393. 'postcode' => '邮编',
  394. 'line_phone' => '公司座机',
  395. 'fax' => '公司传真',
  396. 'email' => '公司邮箱',
  397. 'deliver_period' => '发货期',
  398. 'supply' => '供应量',
  399. 'min_supply' => '最低供应量',
  400. 'price_range' => '价格区间',
  401. 'packing_way' => '包装方式',
  402. 'pay_way' => '支付方式*',
  403. 'skype' => '聊天工具-Skype账号',
  404. 'whats_app' => '聊天工具-Skype账号',
  405. 'wechat' => '聊天工具-Wechat 二维码',
  406. 'qq' => '聊天工具-QQ',
  407. 'other' => '聊天工具-其他',
  408. ],
  409. 'station' => [ //其他项目信息
  410. 'portal_sites' => '门户网站',
  411. 'compete_sites' => '竞争对手网址',
  412. 'other_sites' => '公司其他网站',
  413. ],
  414. 'keyword' => [
  415. 'keyword' => '核心关键词'
  416. ],
  417. 'marketer' => [
  418. 'en_name' => '联系人英文姓名',
  419. 'en_profile' => '联系人简介英文',
  420. 'birthday' => '联系人出生年月',
  421. 'sex_text' => '联系人性别 ',
  422. 'position' => '联系人职位 ',
  423. 'department' => '联系人部门',
  424. 'contact' => '联系人电话',
  425. 'enterprise_login_url' => '企业邮箱外链用-登陆地址',
  426. 'enterprise_email' => '企业邮箱外链用-邮箱',
  427. 'enterprise_email_password' => '企业邮箱外链用-密码',
  428. 'gmail_account' => 'Gmail-邮箱',
  429. 'gmail_password' => 'Gmail-密码',
  430. 'gmail_contact' => 'Gmail-验证手机号码',
  431. 'gmail_assist' => 'Gmail-辅助邮箱',
  432. ],
  433. 'sns' => [
  434. 'youtube_url' => 'Youtube-展示url地址:',
  435. 'youtube_account' => 'Youtube-用户名(登入邮箱)',
  436. 'youtube_password' => 'Youtube-密码',
  437. 'facebook_url' => 'Facebook-企业page展示url地址',
  438. 'facebook_account' => 'Facebook-用户名(登入邮箱)',
  439. 'facebook_password' => 'Facebook-密码',
  440. 'twitter_url' => 'Twitter-展示url地址',
  441. 'twitter_account' => 'Twitter-用户名(登入邮箱)',
  442. 'twitter_password' => 'Twitter-密码',
  443. 'linkedin_url' => 'linkedin-企业page展示url地址',
  444. 'linkedin_account' => 'linkedin-用户名(登入邮箱)',
  445. 'linkedin_password' => 'linkedin-密码',
  446. 'pinterst_url' => 'Pinterst-展示url地址',
  447. 'pinterst_account' => 'Pinterst-用户名(登入邮箱)',
  448. 'pinterst_password' => 'Pinterst-密码',
  449. ]
  450. ];
  451. public function indexCustomerLog(&$validSiteIds)
  452. {
  453. $business = Business::query()->pluck('title', 'id')->toArray();
  454. $natureTypes = array_column(Site::NATURE_TYPE, 'val', 'inx');
  455. $records = CustomerLog::query()->whereIn('site_id', $validSiteIds)->get();
  456. foreach ($records as $key => $record) {
  457. $content = unserialize($record->content);
  458. $oldContent = unserialize($record->old_content);
  459. $mapFields = self::CUSTOMER_FIELD_MAP[$record->type] ?? [];
  460. $resultOldContent = '';
  461. foreach ($oldContent as $inx => $item) {
  462. if ($record->type == 'enterprise') {
  463. if ($inx == 'business_id') {
  464. $item = $business[$item] ?? '';
  465. }
  466. if ($inx == 'nature_type') {
  467. $item = $natureTypes[$item] ?? '';
  468. }
  469. }
  470. if ($record->type == 'station') {
  471. if (is_array($item)) {
  472. $item = implode(',', $item);
  473. }
  474. }
  475. $resultOldContent .= sprintf('%s:%s', ($mapFields[$inx] ?? ''), $item) . ',';
  476. }
  477. $resultContent = '';
  478. foreach ($content as $inx => $item) {
  479. if ($record->type == 'enterprise') {
  480. if ($inx == 'business_id') {
  481. $item = $business[$item] ?? '';
  482. }
  483. if ($inx == 'nature_type') {
  484. $item = $natureTypes[$item] ?? '';
  485. }
  486. }
  487. if ($record->type == 'station' && is_array($item)) {
  488. if (count($item) == count($item, 1)) {
  489. $item = implode(',', $item);
  490. } else {
  491. $tempStr = '';
  492. foreach ($item as $k => $v) {
  493. $tempStr .= ($v['url'] ?? '') . ($v['remark'] ?? '') . ',';
  494. }
  495. $item = $tempStr;
  496. }
  497. }
  498. $resultContent .= sprintf('%s:%s', ($mapFields[$inx] ?? ''), $item) . ',';
  499. }
  500. $record->detail = sprintf('[%s]修改了[%s]-修改之前数据为%s修改之后数据为%s', $record->operator_name, $record->title, $resultOldContent, $resultContent);
  501. }
  502. return $records;
  503. }
  504. public function indexTokenExpired()
  505. {
  506. //linked token过期提醒
  507. // $linkedExpired = Social::query()->where([['type', '=', 'linkedIn'], ['token_expired_at', '<', date('Y-m-d H:i:s', strtotime('+5 days'))]])->exists();
  508. // if ($linkedExpired) {
  509. // //todo
  510. // }
  511. }
  512. public function singleReachDays($site)
  513. {
  514. //关键词达标的 17 关键词达标
  515. $nowDatetime = new \DateTime();
  516. $reachDatetime = new \DateTime($site->reach_at);
  517. $interval = $reachDatetime->diff($nowDatetime);
  518. $diffDays = $interval->format('%R%a');
  519. return $diffDays;
  520. }
  521. public function singleBuildDone($siteId)
  522. {
  523. //建站完成的 15网站上线 未打分的
  524. return SiteProcess::query()->where([
  525. 'process_id' => 15,
  526. 'active' => 1,
  527. 'evaluate' => null,
  528. 'site_id' => $siteId
  529. ])->first();
  530. }
  531. public function singleUrlFailed($siteId)
  532. {
  533. //网址异常
  534. return UrlCheck::query()->where([
  535. 'site_id' => $siteId
  536. ])->first();
  537. }
  538. public function singleKeywordLessVal(ConnectionInterface $rankDatabase, $oldId)
  539. {
  540. if (!$oldId) {
  541. return 0;
  542. }
  543. //关键词排名急剧下降
  544. $nowMonthKeyword = $rankDatabase->table('project_history')->selectRaw('top10')->where([
  545. ['project_id', '=', $oldId],
  546. ['create_time', '>', strtotime(date('Y-m-01'))],
  547. ['create_time', '<', strtotime(date('Y-m-t 23:59:59'))],
  548. ])->orderByDesc('create_time')->first();
  549. $lastMonthKeyword = $rankDatabase->table('project_history')->selectRaw('top10')->where([
  550. ['project_id', '=', $oldId],
  551. ['create_time', '>', strtotime(date('Y-m-01', strtotime('-1 month')))],
  552. ['create_time', '<', strtotime(date('Y-m-t 23:59:59', strtotime('-1 month')))],
  553. ])->orderByDesc('create_time')->first();
  554. return ($nowMonthKeyword->top10 ?? 0) - ($lastMonthKeyword->top10 ?? 0);
  555. // return -10;
  556. }
  557. public function singleSiteProfile(ConnectionInterface $rankDatabase, $site)
  558. {
  559. //项目概况
  560. //合作项目
  561. $contracts = Contract::query()->pluck('title', 'id')->toArray();
  562. $contractIds = $site->contract_ids ?? [];
  563. $site->contractsTitle = implode(',', array_map(function ($item) use (&$contracts) {
  564. return $contracts[$item];
  565. }, $contractIds));
  566. //引擎力顾问
  567. $site->managesInfo = $site->users->where('role_id', Role::TYPE_MANAGER);
  568. //到期时间
  569. // $site->is_expired = (time() > strtotime('+10 month', strtotime($site->reach_at)));
  570. // $site->expired_at = date('Y-m-d H:i:s', strtotime('+10 month', strtotime($site->reach_at)));
  571. $site->expired_time = $site->reach_at ? strtotime('+10 month', strtotime($site->reach_at)) : null;
  572. //首页 前三页 前10页
  573. if ($site->old_id) {
  574. $topKeywords = $rankDatabase->table('project_keyword')->selectRaw('
  575. SUM(CASE WHEN google_rank <= 10 THEN 1 ELSE 0 END) as top10,
  576. SUM(CASE WHEN google_rank <= 30 THEN 1 ELSE 0 END) as top30,
  577. SUM(CASE WHEN google_rank <= 50 THEN 1 ELSE 0 END) as top100
  578. ')->where('google_rank', '<>', 9999)->where('project_id', $site->old_id)->first();
  579. }
  580. $site->topKeywords = $topKeywords ?? null;
  581. }
  582. public function singleMyArticles($siteId)
  583. { //我的文章
  584. $myArticles = Article::query()->with(['site', 'translator'])->where(['site_id' => $siteId])->orderByDesc('id')->limit(5)->get();
  585. $myArticles->each(function ($item) {
  586. $item->status_title = $item->status_with_css;
  587. $item->site_title = $item->site->cn_title ?? '';
  588. $item->translator_name = $item->translator->username ?? '';
  589. });
  590. return $myArticles;
  591. }
  592. public function singleMyLinksTasks($siteId)
  593. {
  594. //我的外链任务
  595. $myLinkTasks = LinkTask::query()->with(['site', 'worker'])->where(['site_id' => $siteId])->orderByDesc('id')->limit(5)->get();
  596. $myLinkTasks->each(function ($item) {
  597. $item->worker_name = $item->worker->username ?? '';
  598. $item->site_title = $item->site->cn_title ?? '';
  599. $item->status_title = $item->status_with_css;
  600. });
  601. return $myLinkTasks;
  602. }
  603. public function singleTrafficLine(ConnectionInterface $masterDatabase)
  604. {
  605. $lastSixMonths = $this->passSixMonthsASC();
  606. //流量折线图
  607. $trafficVal = [];
  608. $traffic = $masterDatabase->table('traffic_report_hourly')->selectRaw('SUM(pv) AS pv,FROM_UNIXTIME(timestamp,"%Y-%m") as Ym')->where([
  609. ])->groupBy('Ym')->orderByDesc('Ym')->get()->pluck('pv', 'Ym')->toArray();
  610. foreach ($lastSixMonths as $month) {
  611. $trafficVal[$month] = $traffic[$month] ?? 0;
  612. }
  613. return [
  614. 'xAxis' => $lastSixMonths,
  615. 'yAxis' => array_values($trafficVal)
  616. ];
  617. }
  618. public function twoCompare($one, $two)
  619. {
  620. $result = $one - $two;
  621. if ($result === 0) {
  622. $status = 'same';
  623. } elseif ($result > 0) {
  624. $status = 'up';
  625. } else {
  626. $status = 'down';
  627. }
  628. return [
  629. 'one' => $one,
  630. 'two' => $two,
  631. 'diff' => abs($result),
  632. 'status' => $status
  633. ];
  634. }
  635. public function passTwoMonth()
  636. {
  637. $passTwoMonth = [];
  638. for ($i = 1; $i <= 2; $i++) {
  639. $passTwoMonth[] = date("Ym", strtotime("first day of -$i month"));
  640. }
  641. return $passTwoMonth;
  642. }
  643. public function singleCompare($last1, $last2, $last3)
  644. {
  645. $last2Diff = $last1 - $last2;
  646. if ($last2Diff === 0) {
  647. $last2Status = 'same';
  648. } elseif ($last2Diff > 0) {
  649. $last2Status = 'up';
  650. } else {
  651. $last2Status = 'down';
  652. }
  653. $last3Diff = $last1 - $last3;
  654. if ($last3Diff === 0) {
  655. $last3Status = 'same';
  656. } elseif ($last3Diff > 0) {
  657. $last3Status = 'up';
  658. } else {
  659. $last3Status = 'down';
  660. }
  661. return [
  662. 'last1' => $last1,
  663. 'last2' => [
  664. 'val' => $last2,
  665. 'diff' => abs($last2Diff),
  666. 'status' => $last2Status
  667. ],
  668. 'last3' => [
  669. 'val' => $last3,
  670. 'diff' => abs($last3Diff),
  671. 'status' => $last3Status
  672. ]
  673. ];
  674. }
  675. public function singlePvUvcData(ConnectionInterface $masterDatabase)
  676. {
  677. $pvList = [];
  678. $uvList = [];
  679. for ($i = 1; $i <= 3; $i++) {
  680. $result = $masterDatabase->table('traffic_report_hourly')->selectRaw('SUM(pv) AS pv,SUM(uv) AS uv')
  681. ->where([
  682. ['timestamp', '>', strtotime(date('Y-m-d 00:00:00', strtotime('first day of -' . $i . ' month')))],
  683. ['timestamp', '<', strtotime(date('Y-m-d 23:59:59', strtotime('last day of -' . $i . ' month')))]
  684. ])->first();
  685. $pvList[] = $result->pv ?? 0;
  686. $uvList[] = $result->uv ?? 0;
  687. }
  688. $totalResult = $masterDatabase->table('traffic_report_hourly')->selectRaw('SUM(pv) AS pv,SUM(uv) AS uv')->first();
  689. $pvResult = $this->singleCompare($pvList[0], $pvList[1], $pvList[2]);
  690. $uvResult = $this->singleCompare($uvList[0], $uvList[1], $uvList[2]);
  691. return [
  692. 'pv' => $pvResult,
  693. 'uv' => $uvResult,
  694. 'pvTotal'=>$totalResult->pv??0,
  695. 'uvTotal'=>$totalResult->uv??0,
  696. ];
  697. }
  698. public function singleTopKeywordData(ConnectionInterface $rankDatabase, $oldId)
  699. {
  700. $top10List = [];
  701. $top30List = [];
  702. $top50List = [];
  703. for ($i = 1; $i <= 3; $i++) {
  704. $start = strtotime(date('Y-m-d 00:00:00', strtotime('first day of -' . $i . ' month')));
  705. $end = strtotime(date('Y-m-d 23:59:59', strtotime('last day of -' . $i . ' month')));
  706. $result = $rankDatabase->table('project_history')->where(['project_id' => $oldId])->where([
  707. ['create_time', '>', $start],
  708. ['create_time', '<', $end]
  709. ])->orderByDesc('create_time')->first();
  710. $top10List[] = $result->top10 ?? 0;
  711. $top30List[] = $result->top30 ?? 0;
  712. $top50List[] = $result->top50 ?? 0;
  713. }
  714. $top10Res = $this->singleCompare($top10List[0], $top10List[1], $top10List[2]);
  715. $top30Res = $this->singleCompare($top30List[0], $top30List[1], $top30List[2]);
  716. $top50Res = $this->singleCompare($top50List[0], $top50List[1], $top50List[2]);
  717. return [
  718. 'top10' => $top10Res,
  719. 'top30' => $top30Res,
  720. 'top50' => $top50Res,
  721. 'top10History' => $top10List
  722. ];
  723. }
  724. public function singleInquireData(ConnectionInterface $masterDatabase)
  725. {
  726. $resultList = [];
  727. $one_last = strtotime(date('Y-m-d 23:59:59', strtotime('last day of - 1 month')));
  728. $two_last = strtotime(date('Y-m-d 23:59:59', strtotime('last day of - 2 month')));
  729. $three_last = strtotime(date('Y-m-d 23:59:59', strtotime('last day of - 3 month')));
  730. $one_begin = strtotime(date('Y-m-01 00:00:00', strtotime('last day of - 1 month')));
  731. $two_begin = strtotime(date('Y-m-01 00:00:00', strtotime('last day of - 2 month')));
  732. $three_begin = strtotime(date('Y-m-01 00:00:00', strtotime('last day of - 3 month')));
  733. // for ($i = 1; $i <= 3; $i++) {
  734. // $resultList[] = $masterDatabase->table('user_msg')
  735. // ->where([
  736. // ['is_delete', '=', 0],
  737. // ['create_time', '<', strtotime(date('Y-m-d 23:59:59', strtotime('last day of -' . $i . ' month')))]
  738. // ])->count();
  739. // }
  740. $resultList[0]=$resultList[] = $masterDatabase->table('user_msg')
  741. ->where([
  742. ['is_delete', '=', 0],
  743. ])->whereBetween('create_time',[$one_begin,$one_last])->count();
  744. $resultList[1]=$resultList[] = $masterDatabase->table('user_msg')
  745. ->where([
  746. ['is_delete', '=', 0],
  747. ])->whereBetween('create_time',[$two_begin,$two_last])->count();
  748. $resultList[2]=$resultList[] = $masterDatabase->table('user_msg')
  749. ->where([
  750. ['is_delete', '=', 0],
  751. ])->whereBetween('create_time',[$three_begin,$three_last])->count();
  752. var_dump($resultList);
  753. $res = $this->singleCompare($resultList[0], $resultList[1], $resultList[2]);
  754. return $res;
  755. }
  756. public function singleWebmasterEffectData(ConnectionInterface $rankDatabase, $oldId)
  757. {
  758. $pass3Month = [];
  759. for ($i = 1; $i <= 3; $i++) {
  760. $pass3Month[] = date('Ym', strtotime('first day of -' . $i . ' month'));
  761. }
  762. $results = $rankDatabase->table('webmaster_effect')->selectRaw('ym,SUM(clicks) as clicks,SUM(impressions) AS impressions')
  763. ->where(['project_id' => $oldId])->whereIn('ym', $pass3Month)->groupBy('ym')->get()->keyBy('ym')->toArray();
  764. $last1 = empty($results[$pass3Month[0]]) ? 0 : $results[$pass3Month[0]]->impressions;
  765. $last2 = empty($results[$pass3Month[1]]) ? 0 : $results[$pass3Month[1]]->impressions;
  766. $last3 = empty($results[$pass3Month[2]]) ? 0 : $results[$pass3Month[2]]->impressions;
  767. $res = $this->singleCompare($last1, $last2, $last3);
  768. return $res;
  769. }
  770. public function singlePageCount(ConnectionInterface $masterDatabase)
  771. {
  772. $pageList = [];
  773. for ($i = 1; $i <= 3; $i++) {
  774. $end = strtotime(date('Y-m-d 23:59:59', strtotime('last day of -' . $i . ' month')));
  775. $pageList[] = $masterDatabase->table('content')->where(['is_enabled' => 1, 'redirect' => '', 'lang' => 'en'])
  776. ->whereNotIn('uri', ['404', 'search'])->where('create_time', '<=', $end)->count();
  777. }
  778. return $this->singleCompare($pageList[0], $pageList[1], $pageList[2]);
  779. }
  780. public function singleArticleRate($site)
  781. {
  782. $reachList = [];
  783. for ($i = 1; $i <= 3; $i++) {
  784. $end = strtotime(date('Y-m-d 23:59:59', strtotime('last day of -' . $i . ' month')));
  785. $reachList[] = Article::query()->where([
  786. ['site_id', '=', $site->id],
  787. // ['publish_at', '>', 0],
  788. ['publish_at', '<=', date('Y-m-d H:i:s', $end)],
  789. ])->count();
  790. }
  791. return [
  792. 'goal' => $site->article_goal,
  793. 'last1Reach' => $reachList[0],
  794. 'last2Reach' => $reachList[1],
  795. 'last3Reach' => $reachList[2],
  796. ];
  797. }
  798. public function singleLinkRate($site)
  799. {
  800. $reachList = [];
  801. for ($i = 1; $i <= 3; $i++) {
  802. $end = strtotime(date('Y-m-d 23:59:59', strtotime('last day of -' . $i . ' month')));
  803. $reachList[] = LinkTaskDetail::query()->selectRaw('link_id')->where([
  804. 'redundant_site_id' => $site->id,
  805. 'enable' => 1,
  806. 'status' => 5
  807. ])->where('created_at', '<=', date('Y-m-d H:i:s', $end))->groupBy('link_id')->get()->count();
  808. };
  809. return [
  810. 'goal' => $site->link_goal,
  811. 'last1Reach' => $reachList[0],
  812. 'last2Reach' => $reachList[1],
  813. 'last3Reach' => $reachList[2],
  814. ];
  815. }
  816. public function singleTopKeywordGoalData()
  817. {
  818. }
  819. public function singleInquireLine(ConnectionInterface $masterDatabase)
  820. {
  821. //询盘折线图
  822. $lastSixMonths = $this->passSixMonthsASC();
  823. $inquiresVal = [];
  824. foreach ($lastSixMonths as $month) {
  825. $inquiresVal[$month] = $masterDatabase->table('user_msg')->where([
  826. ['is_delete', '=', '0'],
  827. ['create_time', '>=', strtotime($month)],
  828. ['create_time', '<=', strtotime(sprintf('%s 23:59:59', date('Y-m-t', strtotime($month))))]
  829. ])->count();
  830. }
  831. return [
  832. 'xAxis' => $lastSixMonths,
  833. 'yAxis' => array_values($inquiresVal)
  834. ];
  835. }
  836. public function singleKeywordLine(ConnectionInterface $rankDatabase, $oldId)
  837. {
  838. //关键词折线图
  839. $lastSixMonths = $this->passSixMonthsASC();
  840. $keywordVal = [];
  841. foreach ($lastSixMonths as $month) {
  842. if (!$oldId) {
  843. $keywordVal[$month] = 0;
  844. continue;
  845. }
  846. $history = $rankDatabase->table('project_history')
  847. ->selectRaw('top10')->where([
  848. ['project_id', '=', $oldId],
  849. ['create_time', '>=', strtotime($month)],
  850. ['create_time', '<=', strtotime(sprintf('%s 23:59:59', date('Y-m-t', strtotime($month))))],
  851. ])
  852. ->orderByDesc('create_time')->first();
  853. $keywordVal[$month] = $history->top10 ?? 0;
  854. }
  855. return [
  856. 'xAxis' => $lastSixMonths,
  857. 'yAxis' => array_values($keywordVal)
  858. ];
  859. }
  860. public function getSingleSite()
  861. {
  862. $user = auth()->user();
  863. if ($user->is_super) {
  864. return Site::query()->first();
  865. }
  866. /** @var \App\Http\Models\User $user */
  867. return $user->sites()->first();
  868. }
  869. }