作者 赵彬吉
@@ -107,7 +107,9 @@ class VideoTask extends Command @@ -107,7 +107,9 @@ class VideoTask extends Command
107 'project_id' => $task_project->project_id, 107 'project_id' => $task_project->project_id,
108 'keyword_id' => $val->id, 108 'keyword_id' => $val->id,
109 'keyword' => $val->title, 109 'keyword' => $val->title,
110 - 'data' => json_encode(['url' => $keywordInfo['url'],'title' => $keywordInfo['title'], 'description' => $keywordInfo['keyword_content'], 'images' => $keywordInfo['product_list'], 'keywords' => $keywordInfo['keyword_list']]), 110 + 'data' => json_encode(['url' => $keywordInfo['url'],'title' => $keywordInfo['title'],
  111 + 'description' => $keywordInfo['keyword_content'], 'images' => $keywordInfo['product_list'],
  112 + 'keywords' => $keywordInfo['keyword_list']]),
111 'status' => KeywordVideoTaskLog::STATUS_INIT, 113 'status' => KeywordVideoTaskLog::STATUS_INIT,
112 'updated_at' => date('Y-m-d H:i:s'), 114 'updated_at' => date('Y-m-d H:i:s'),
113 'created_at' => date('Y-m-d H:i:s'), 115 'created_at' => date('Y-m-d H:i:s'),
@@ -226,7 +228,8 @@ class VideoTask extends Command @@ -226,7 +228,8 @@ class VideoTask extends Command
226 } 228 }
227 }else{ 229 }else{
228 $product_all_id = Product::where("project_id", $project_id)->where("status",Product::STATUS_ON)->pluck('id')->toArray(); 230 $product_all_id = Product::where("project_id", $project_id)->where("status",Product::STATUS_ON)->pluck('id')->toArray();
229 - $product_id = array_rand($product_all_id, 40); 231 + $number = 40;
  232 + $product_id = array_rand($product_all_id, min(count($product_all_id, $number-count($productIds))));
230 $products = Product::where("project_id", $project_id)->whereIn("id", $product_id)->get(); 233 $products = Product::where("project_id", $project_id)->whereIn("id", $product_id)->get();
231 } 234 }
232 } 235 }
@@ -239,6 +242,12 @@ class VideoTask extends Command @@ -239,6 +242,12 @@ class VideoTask extends Command
239 if(count($data) > 13){ 242 if(count($data) > 13){
240 break; 243 break;
241 } 244 }
  245 + if (strpos($item->keyword_id, ','.$productKeyword->id.',') === false) {
  246 + //不包含
  247 + $productModel = new Product();
  248 + $keyword_id = $item->keyword_id . $productKeyword->id.',';
  249 + $productModel->edit(['keyword_id'=>$keyword_id],['id'=>$item->id]);
  250 + }
242 $data[] = ['url'=>getImageUrl($item->thumb['url']),'title'=>$item->title]; 251 $data[] = ['url'=>getImageUrl($item->thumb['url']),'title'=>$item->title];
243 } 252 }
244 } 253 }
@@ -780,13 +780,30 @@ class ProjectUpdate extends Command @@ -780,13 +780,30 @@ class ProjectUpdate extends Command
780 $image = $item['images'] ?? ''; 780 $image = $item['images'] ?? '';
781 } 781 }
782 $new_img = $this->source_download($image, $project_id, $domain, $web_url_domain, $home_url); 782 $new_img = $this->source_download($image, $project_id, $domain, $web_url_domain, $home_url);
  783 + //描述
  784 + if (isset($item['description']) && $item['description']) {
  785 + //匹配描述资源
  786 + $source_list = $this->html_preg($item['description'], $project_id, $domain, $web_url_domain, $home_url);
  787 + if ($source_list) {
  788 + foreach ($source_list as $vs) {
  789 + if ($vs['download']) {
  790 + //需要下载资源
  791 + $down_url = $this->source_download($vs['url_complete'], $project_id, $domain, $web_url_domain, $home_url);
  792 + } else {
  793 + //已经下载过资源
  794 + $down_url = getImageUrl($vs['url_complete']);
  795 + }
  796 + $item['description'] = str_replace($vs['url'], $down_url, $item['description']);
  797 + }
  798 + }
  799 + }
783 $parent_id = $model->addReturnId([ 800 $parent_id = $model->addReturnId([
784 'project_id' => $project_id, 801 'project_id' => $project_id,
785 'title' => $item['name'], 802 'title' => $item['name'],
786 'image' => $new_img, 803 'image' => $new_img,
787 'pid' => $pid, 804 'pid' => $pid,
788 'keywords' => $item['keywords'] ?? '', 805 'keywords' => $item['keywords'] ?? '',
789 - 'describe' => $item['description'] ?? '', 806 + 'describe' => (isset($item['description']) && $item['description']) ? $item['description'] : '',
790 'original_id' => $item['id'], 807 'original_id' => $item['id'],
791 'route' => $route 808 'route' => $route
792 ]); 809 ]);
@@ -978,4 +995,101 @@ class ProjectUpdate extends Command @@ -978,4 +995,101 @@ class ProjectUpdate extends Command
978 return $key . $i; 995 return $key . $i;
979 } 996 }
980 } 997 }
  998 +
  999 + //正则匹配html资源
  1000 + protected function html_preg($html, $project_id, $domain, $web_url_domain, $home_url)
  1001 + {
  1002 + $source = [];
  1003 +
  1004 + if (!$html) {
  1005 + return $source;
  1006 + }
  1007 +
  1008 + //image
  1009 + preg_match_all('/<img\s+[^>]*?src\s*=\s*(\'|\")(.*?)\\1[^>]*?\/?\s*>/i', $html, $result_img);
  1010 + $img = $result_img[2] ?? [];
  1011 + foreach ($img as $vi) {
  1012 + $check_vi = $this->url_check($vi, $project_id, $domain, $web_url_domain, $home_url);
  1013 + if ($check_vi && (!in_array($check_vi, $source))) {
  1014 + $source[] = $check_vi;
  1015 + }
  1016 + }
  1017 +
  1018 + //video
  1019 + preg_match_all('/<source\s+[^>]*?src\s*=\s*(\'|\")(.*?)\\1[^>]*?\/?\s*>/i', $html, $result_video);
  1020 + $video = $result_video[2] ?? [];
  1021 + foreach ($video as $vv) {
  1022 + $check_vv = $this->url_check($vv, $project_id, $domain, $web_url_domain, $home_url);
  1023 + if ($check_vv && (!in_array($check_vv, $source))) {
  1024 + $source[] = $check_vv;
  1025 + }
  1026 + }
  1027 + preg_match_all('/<video\s+[^>]*?src\s*=\s*(\'|\")(.*?)\\1[^>]*?\/?\s*>/i', $html, $result_video_2);
  1028 + $video_2 = $result_video_2[2] ?? [];
  1029 + foreach ($video_2 as $vv2) {
  1030 + $check_vv2 = $this->url_check($vv2, $project_id, $domain, $web_url_domain, $home_url);
  1031 + if ($check_vv2 && (!in_array($check_vv2, $source))) {
  1032 + $source[] = $check_vv2;
  1033 + }
  1034 + }
  1035 +
  1036 + //a标签下载资源
  1037 + preg_match_all('/<a\s+[^>]*?href\s*=\s*(\'|\")(.*?)\\1[^>]*?\/?\s*>/i', $html, $result_a);
  1038 + $down = $result_a[2] ?? [];
  1039 + foreach ($down as $vd) {
  1040 + $check_vd = $this->url_check($vd, $project_id, $domain, $web_url_domain, $home_url);
  1041 + if ($check_vd && (!in_array($check_vd, $source))) {
  1042 + $source[] = $check_vd;
  1043 + }
  1044 + }
  1045 +
  1046 + return $source;
  1047 + }
  1048 +
  1049 + //判断资源是否需要下载
  1050 + protected function url_check($url, $project_id, $domain, $web_url_domain, $home_url)
  1051 + {
  1052 + $url = trim($url);
  1053 + if ($url) {
  1054 + $url = str_replace('&quot;', '', $url);
  1055 + $arr = parse_url($url);
  1056 + $scheme = $arr['scheme'] ?? '';
  1057 + $host = $arr['host'] ?? '';
  1058 + $path = $arr['path'] ?? '';
  1059 + $query = $arr['query'] ?? '';
  1060 +
  1061 + $path_arr = explode('.', $path);
  1062 + $path_end = end($path_arr);
  1063 + if (
  1064 + (empty($scheme) || $scheme == 'https' || $scheme == 'http')
  1065 + && (empty($host) || (strpos($web_url_domain, $host) !== false) || (strpos($home_url, $host) !== false))
  1066 + && $path
  1067 + && (substr($path, 0, 1) == '/')
  1068 + && (strpos($path, '.') !== false)
  1069 + && (strpos($path_end, 'html') === false)
  1070 + && (strpos($path_end, 'php') === false)
  1071 + && (strpos($path_end, 'com') === false)
  1072 + && (strpos($path_end, 'xml') === false)
  1073 + ) {
  1074 + $source = CollectSource::where('project_id', $project_id)->where('origin', $url)->first();
  1075 + if (!$source) {
  1076 + return [
  1077 + 'download' => true,
  1078 + 'url' => $url,
  1079 + 'url_complete' => ($scheme ?: 'https') . '://' . $domain . $path . ($query ? '?' . $query : '')
  1080 + ];
  1081 + } else {
  1082 + return [
  1083 + 'download' => false,
  1084 + 'url' => $url,
  1085 + 'url_complete' => $source['target']
  1086 + ];
  1087 + }
  1088 + } else {
  1089 + return false;
  1090 + }
  1091 + } else {
  1092 + return false;
  1093 + }
  1094 + }
981 } 1095 }
@@ -55,7 +55,7 @@ class UpdateRoute extends Command @@ -55,7 +55,7 @@ class UpdateRoute extends Command
55 */ 55 */
56 public function handle(){ 56 public function handle(){
57 $projectModel = new Project(); 57 $projectModel = new Project();
58 - $list = $projectModel->list(['id'=>206]); 58 + $list = $projectModel->list(['id'=>969]);
59 $data = []; 59 $data = [];
60 foreach ($list as $v){ 60 foreach ($list as $v){
61 echo date('Y-m-d H:i:s') . 'project_id:'.$v['id'] . PHP_EOL; 61 echo date('Y-m-d H:i:s') . 'project_id:'.$v['id'] . PHP_EOL;
@@ -11,6 +11,8 @@ use App\Enums\Common\Code; @@ -11,6 +11,8 @@ use App\Enums\Common\Code;
11 use App\Http\Controllers\Controller; 11 use App\Http\Controllers\Controller;
12 use Illuminate\Http\Exceptions\HttpResponseException; 12 use Illuminate\Http\Exceptions\HttpResponseException;
13 use Illuminate\Http\JsonResponse; 13 use Illuminate\Http\JsonResponse;
  14 +use Illuminate\Http\Request;
  15 +use Illuminate\Support\Facades\Cache;
14 16
15 /** 17 /**
16 * Class BaseController 18 * Class BaseController
@@ -18,6 +20,12 @@ use Illuminate\Http\JsonResponse; @@ -18,6 +20,12 @@ use Illuminate\Http\JsonResponse;
18 */ 20 */
19 class BaseController extends Controller 21 class BaseController extends Controller
20 { 22 {
  23 + public $param;
  24 + public function __construct(Request $request)
  25 + {
  26 + $this->request = $request;
  27 + $this->param = $this->request->all();
  28 + }
21 /** 29 /**
22 * @param array $data 30 * @param array $data
23 * @param string $message 31 * @param string $message
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :OptimizationReportController.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2024/3/7 15:57
  8 + */
  9 +
  10 +namespace App\Http\Controllers\Api;
  11 +
  12 +use App\Enums\Common\Code;
  13 +use App\Helper\Arr;
  14 +use App\Helper\FormGlobalsoApi;
  15 +use App\Models\Domain\DomainInfo;
  16 +use App\Models\HomeCount\Count;
  17 +use App\Models\Inquiry\InquiryFormData;
  18 +use App\Models\Project\Project;
  19 +use App\Models\RankData\ExternalLinks;
  20 +use App\Models\RankData\IndexedPages;
  21 +use App\Models\RankData\RankData;
  22 +use App\Models\RankData\RankWeek;
  23 +use App\Models\RankData\Speed;
  24 +use App\Models\Visit\Visit;
  25 +use App\Models\Visit\VisitItem;
  26 +use App\Services\ProjectServer;
  27 +use App\Utils\HttpUtils;
  28 +use GuzzleHttp\Exception\GuzzleException;
  29 +use Illuminate\Support\Facades\Cache;
  30 +use Illuminate\Support\Facades\DB;
  31 +
  32 +class OptimizationReportController extends BaseController
  33 +{
  34 + /**
  35 + * @remark :优化报告
  36 + * @name :getOptimizationReport
  37 + * @author :lyh
  38 + * @method :post
  39 + * @time :2024/3/7 15:54
  40 + */
  41 + public function getOptimizationReport(){
  42 + $this->request->validate([
  43 + 'project_id' => 'required',
  44 + 'date'=>'required',
  45 + ], [
  46 + 'project_id.required' => '项目id不能为空',
  47 + 'date.required' => '时间不能为空',
  48 + ]);
  49 + ProjectServer::useProject($this->param['project_id']);
  50 + $data = [];
  51 + $projectModel = new Project();
  52 + $projectInfo = $projectModel->with('payment')->with('deploy_build')
  53 + ->with('deploy_optimize')->with('online_check')->where(['id'=>$this->param['project_id']])->first();
  54 + $domainModel = new DomainInfo();
  55 + $domain_info = $domainModel->where('project_id', $this->param['project_id'])->first();
  56 + if(!$domain_info){
  57 + return [];
  58 + }else{
  59 + $domain_info = [
  60 + 'domain' => 'https://'.$domain_info['domain'].'/',
  61 + 'domain_info' => date('Y-m-d', strtotime($domain_info['domain_start_time'])) . ' - ' .date('Y-m-d', strtotime($domain_info['domain_end_time'])),
  62 + 'cert_info' => date('Y-m-d', strtotime($domain_info['certificate_start_time'])) . ' - ' .date('Y-m-d', strtotime($domain_info['certificate_end_time'])),
  63 + ];
  64 + }
  65 + //外链周期分析
  66 + $external_links = ExternalLinks::where('project_id', $this->param['project_id'])->first();
  67 + $data['domain'] = $domain_info;
  68 + //方案信息
  69 + $data['plan_information'] = $this->plan_information($projectInfo,$domain_info);
  70 + //排名数据
  71 + $data['first_total'] = $this->first_total($external_links);
  72 + //关键词排名分析图
  73 + $data['rank_chat'] = $this->rank_chat();
  74 + //关键词排名明细
  75 + $data['keywords_rank_list'] = $this->keywords_rank_list($this->param['project_id'],$projectInfo);
  76 + //pv_ip统计
  77 + $data['pv_ip'] = $this->pv_ip($domain_info['domain']);
  78 + //30天统计
  79 + $data['count_30'] = $this->count_30_total();
  80 + //访问国家前10
  81 + $data['access_country_count'] = $this->access_country_count();
  82 +
  83 + //SEO数据周期分析图 外链数
  84 + $data['external_links_chat'] = [
  85 + 'labels' => array_keys($external_links['data'] ?? []),
  86 + 'data' => array_values($external_links['data'] ?? []),
  87 + ];
  88 + $indexed_pages = IndexedPages::where('project_id', $this->param['project_id'])->first();
  89 + //SEO数据周期分析图 收录数
  90 + $data['indexed_pages_chat'] = [
  91 + 'labels' => array_keys($indexed_pages['data'] ?? []),
  92 + 'data' => array_values($indexed_pages['data'] ?? []),
  93 + ];
  94 + //月统计报告
  95 + $data['month_count'] = $this->currentMonthCount($domain_info['domain'],$this->param['project_id']);
  96 + //测速
  97 + $speed = Speed::where('project_id', $this->param['project_id'])->first();
  98 + $data['speed'] = $speed['data'] ?? [];
  99 + //询盘
  100 + $data['inquiry'] = $this->getApiList($projectInfo);
  101 + DB::disconnect('custom_mysql');
  102 + $this->response('success',Code::SUCCESS,$data);
  103 + }
  104 +
  105 + /**
  106 + * @remark :获取当前月数据统计
  107 + * @name :currentMonth
  108 + * @author :lyh
  109 + * @method :post
  110 + * @time :2023/7/3 9:55
  111 + */
  112 + public function currentMonthCount($domain,$project_id){
  113 + // 获取当前月的开始时间
  114 + $startTime = date('Y-m-01', strtotime($this->param['date']));
  115 + // 获取当前月的结束时间
  116 + $endTime = date('Y-m-t', strtotime($this->param['date']));
  117 + $arr = [];
  118 + $arr = $this->inquiryCount($arr,$startTime,$endTime,$domain);
  119 + $arr = $this->flowCount($arr,$startTime,$endTime,$project_id);
  120 + $arr = $this->sourceCount($arr,$startTime,$endTime,$domain);
  121 + $arr['month'] = date('Y-m',time());
  122 + return $arr;
  123 + }
  124 +
  125 + /**
  126 + * @param $domain
  127 + * @param $project_id
  128 + * @remark :询盘按月统计
  129 + * @name :inquiryCount
  130 + * @author :lyh
  131 + * @method :post
  132 + * @time :2023/6/30 14:29
  133 + */
  134 + public function inquiryCount(&$arr,&$startTime,&$endTime,$domain){
  135 + $inquiry_list = (new FormGlobalsoApi())->getInquiryList($domain,'',1,100000000);
  136 + if(!empty($inquiry_list)){
  137 + //总数
  138 + $arr['total'] = $inquiry_list['data']['total'] ?? 0;
  139 + //数据详情
  140 + $data = $inquiry_list['data']['data'] ?? '';
  141 + $arr['month_total'] = 0;
  142 + $countryArr = [];
  143 + if(isset($data) && !empty($data)){
  144 + foreach ($data as $v){
  145 + if(($startTime.' 00:00:00' <= $v['submit_time']) && $v['submit_time'] <= $endTime.' 23:59:59'){
  146 + $arr['month_total']++;
  147 + if(isset($countryArr[$v['country']])){
  148 + $countryArr[$v['country']]++;
  149 + }else{
  150 + $countryArr[$v['country']] = 1;
  151 + }
  152 + }
  153 + }
  154 + }
  155 + }
  156 + //加上其他询盘
  157 + $arr['total'] += InquiryFormData::getCount();
  158 + $arr['month_total'] += InquiryFormData::getCount([$startTime, $endTime]);
  159 + $countryData = InquiryFormData::getCountryCount([$startTime, $endTime]);
  160 + foreach ($countryData as $v1){
  161 + if(isset($countryArr[$v1['country']])){
  162 + $countryArr[$v1['country']] += $v1['count'];
  163 + }else{
  164 + $countryArr[$v1['country']] = $v1['count'];
  165 + }
  166 + }
  167 + arsort($countryArr);
  168 + $top20 = array_slice($countryArr, 0, 15, true);
  169 + $arr['country'] = $top20;
  170 + return $arr;
  171 + }
  172 +
  173 + /**
  174 + * @remark :流量统计
  175 + * @name :flowCount
  176 + * @author :lyh
  177 + * @method :post
  178 + * @time :2023/6/30 14:31
  179 + */
  180 + public function flowCount(&$arr,&$startTime,&$endTime,$project_id){
  181 + $pv_ip = DB::table('gl_count')
  182 + ->where(['project_id'=>$project_id])
  183 + ->whereBetween('date', [$startTime,$endTime])
  184 + ->select(DB::raw('SUM(pv_num) as pv_num'), DB::raw('SUM(ip_num) as ip_num'))
  185 + ->orderBy('id','desc')
  186 + ->first();
  187 + $arr['pv'] = $pv_ip->pv_num;
  188 + $arr['ip'] = $pv_ip->ip_num;
  189 + $arr['rate'] = 0;
  190 + if($arr['ip'] != 0){
  191 + $arr['rate'] = round(($arr['month_total'] / $arr['ip']) * 100,2);
  192 + }
  193 + return $arr;
  194 + }
  195 +
  196 + /**
  197 + * @remark :来源访问前8
  198 + * @name :sourceCount
  199 + * @author :lyh
  200 + * @method :post
  201 + * @time :2023/6/30 16:14
  202 + */
  203 + public function sourceCount(&$arr,$startTime,$endTime,$domain){
  204 + //访问来源前10
  205 + $source = DB::connection('custom_mysql')->table('gl_customer_visit')
  206 + ->select('referrer_url', DB::raw('COUNT(*) as count'))
  207 + ->groupBy('referrer_url')
  208 + ->where('referrer_url','!=','')
  209 + ->whereBetween('updated_date', [$startTime,$endTime])
  210 + ->orderByDesc('count')->limit(10)->get()->toArray();
  211 + $arr['source'] = $source;
  212 + //访问国家前15
  213 + $query = DB::connection('custom_mysql')->table('gl_customer_visit')
  214 + ->select('country',DB::raw('COUNT(*) as ip'),DB::raw('SUM(depth) as pv'))
  215 + ->groupBy('country');
  216 +
  217 + $query->where('country','<>','中国');
  218 +
  219 + $source_country = $query->whereBetween('updated_date', [$startTime,$endTime])
  220 + ->orderBy('ip','desc')->limit(15)->get()->toArray();
  221 + $arr['source_country'] = $source_country;
  222 + //受访界面前15
  223 + $referrer_url = DB::connection('custom_mysql')->table('gl_customer_visit')
  224 + ->select('url',DB::raw('COUNT(*) as num'))
  225 + ->orderBy('num','desc')
  226 + ->whereBetween('updated_date', [$startTime,$endTime])
  227 + ->groupBy('url')
  228 + ->limit(15)->get()->toArray();
  229 + $arr['referrer_url'] = $referrer_url;
  230 + //访问断后
  231 + $referrer_port = DB::connection('custom_mysql')->table('gl_customer_visit')
  232 + ->select('device_port',DB::raw('COUNT(*) as num'))
  233 + ->orderBy('num','desc')
  234 + ->whereBetween('updated_date', [$startTime,$endTime])
  235 + ->groupBy('device_port')
  236 + ->limit(15)->get()->toArray();
  237 + $arr['referrer_port'] = $referrer_port;
  238 + return $arr;
  239 + }
  240 +
  241 + public function getApiList($projectInfo,$export = false)
  242 + {
  243 + $this->form_globalso_api = new FormGlobalsoApi();
  244 + if(isset($this->request['row'])){
  245 + $page_size = $this->request['row'];
  246 + }else{
  247 + $page_size = $export ? 1000 : 20;
  248 + }
  249 + $search = $this->request['search'] ?: '';
  250 + $page = $this->request['page'] ?: 1;
  251 + $domain = (!empty($projectInfo['deploy_optimize']['domain']) ? ((new DomainInfo())->getDomain($projectInfo['deploy_optimize']['domain'])) : '');
  252 + $list = $this->form_globalso_api->getInquiryList($domain, $search, $page, $page_size);
  253 + //处理格式 免得前端又改
  254 + $data = [
  255 + "list" => [],
  256 + "total" => 0,
  257 + "page" => $page,
  258 + "total_page" => 1,
  259 + "size" => $page_size
  260 + ];
  261 + if (!empty($list['status']) && $list['status'] == 200) {
  262 + foreach ($list['data']['data'] as $item) {
  263 + $data['list'][] = $item;
  264 + }
  265 + $data['total'] = $list['data']['total'];
  266 + $data['total_page'] = $list['data']['last_page'];
  267 + }
  268 + return $data;
  269 + }
  270 +
  271 + /**
  272 + * @remark :方案信息
  273 + * @name :plan_information
  274 + * @author :lyh
  275 + * @method :post
  276 + * @time :2024/3/7 17:00
  277 + */
  278 + public function plan_information($projectInfo,$domain_info){
  279 + return [
  280 + 'company' => $projectInfo['company'],
  281 + 'domain' => $domain_info['domain'] ?? '',
  282 + 'domain_info' => $domain_info['domain_info'] ?? '',
  283 + 'cert_info' => $domain_info['cert_info'] ?? '',
  284 + 'plan' => Project::planMap()[$projectInfo['deploy_build']['plan']],
  285 + 'keyword_num' => $projectInfo['deploy_build']['keyword_num'],
  286 + 'compliance_day' => $projectInfo['finish_remain_day'] ?? 0,
  287 + 'start_time' => $projectInfo['deploy_optimize']['start_date'] ?? '',
  288 + 'remain_day' => $projectInfo['deploy_build']['service_duration'] - ($projectInfo['finish_remain_day'] ?? 0),
  289 + ];
  290 + }
  291 +
  292 + /**
  293 + * @remark :排名数据
  294 + * @name :ce
  295 + * @author :lyh
  296 + * @method :post
  297 + * @time :2024/3/7 16:58
  298 + */
  299 + public function first_total($external_links){
  300 + $rank = RankData::where('project_id', $this->param['project_id'])->first();
  301 + return [
  302 + 'first_num' => $rank['first_num'] ?? 0,
  303 + 'first_page_num' => $rank['first_page_num'] ?? 0,
  304 + 'first_three_pages_num' => $rank['first_three_pages_num'] ?? 0,
  305 + 'first_five_pages_num' => $rank['first_five_pages_num'] ?? 0,
  306 + 'first_ten_pages_num' => $rank['first_ten_pages_num'] ?? 0,
  307 + 'indexed_pages_num' => $rank['indexed_pages_num'] ?? 0,
  308 + 'external_links_num' => $external_links['total'] ?? 0,
  309 + ];
  310 + }
  311 +
  312 + /**
  313 + * @remark :关键词排名分析图
  314 + * @name :ceshi
  315 + * @author :lyh
  316 + * @method :post
  317 + * @time :2024/3/7 17:39
  318 + */
  319 + public function rank_chat(){
  320 + //关键词排名分析图
  321 + $rank_week = RankWeek::where('project_id', $this->param['project_id'])->first();
  322 + return [
  323 + 'data' => $rank_week['data'] ?? [],
  324 + 'labels' => $rank_week['date'] ?? [],
  325 + ];
  326 + }
  327 +
  328 + /**
  329 + * @remark :30天统计
  330 + * @name :count_30_total
  331 + * @author :lyh
  332 + * @method :post
  333 + * @time :2024/3/7 16:56
  334 + */
  335 + public function count_30_total(){
  336 + $count_param = [
  337 + 'date' => ['between',[now()->subDays(30)->startOfDay()->toDateString(),now()->startOfDay()->toDateString()]],
  338 + 'project_id' => $this->param['project_id']
  339 + ];
  340 + return (new Count())->list($count_param,'date',['id','pv_num','ip_num','date']);
  341 + }
  342 +
  343 + /**
  344 + * @remark :pv_ip
  345 + * @name :visit_data
  346 + * @author :lyh
  347 + * @method :post
  348 + * @time :2024/3/7 16:53
  349 + */
  350 + public function pv_ip($domain){
  351 + $pv = (new VisitItem())->count();
  352 + $ip = (new Visit())->count();
  353 + $inquiry_list = (new FormGlobalsoApi())->getInquiryList($domain,'',1,100000000);
  354 + if(!empty($inquiry_list)){
  355 + $total = $inquiry_list['data']['total'] ?? 0;
  356 + }
  357 + return [
  358 + 'total_pv'=>$pv,
  359 + 'total_ip'=>$ip,
  360 + 'conversion_rate' => (isset($total) && !empty($total) && ($ip != 0)) ? round(($total / $ip) * 10,2) : 0,
  361 + ];
  362 + }
  363 +
  364 + /**
  365 + * @name :(访问国家统计)access_country_count
  366 + * @author :lyh
  367 + * @method :post
  368 + * @time :2023/5/24 15:56
  369 + */
  370 + public function access_country_count(){
  371 + $customerVisitModel = new Visit();
  372 + $data = $customerVisitModel->select('country',DB::raw('COUNT(*) as ip'),DB::raw('SUM(depth) as pv'))
  373 + ->groupBy('country')
  374 + ->orderBy('ip','desc')->limit(11)->get()->toArray();
  375 + $result =array();
  376 + if(!empty($data)){
  377 + foreach ($data as $k => $v){
  378 + $v['pv'] = (int)$v['pv'];
  379 + $result[] = $v;
  380 + }
  381 + }
  382 + return $result;
  383 + }
  384 +
  385 + public function keywords_rank_list($project_id,$projectInfo,$export = false)
  386 + {
  387 + $page = 1;
  388 + $lang = $this->request['lang'] ?: '';
  389 + $api_no = $projectInfo['deploy_optimize']['api_no'] ?? '';
  390 + $domain = (!empty($projectInfo['deploy_optimize']['domain']) ? ((new DomainInfo())->getDomain($projectInfo['deploy_optimize']['domain'])) : '');
  391 + $domain_arr = parse_url($domain);
  392 + $domain = $domain_arr['host'] ?? $domain_arr['path'];
  393 + //复制站点域名
  394 + $ext_projects = $this->getExtendProjects();
  395 + $flg_ext = $this->getExtFlag($ext_projects, $domain, $api_no);
  396 + $ext_domain = str_replace('www.', '', $this->getExtendProjects($api_no)['ext'] ?? '');
  397 + //AI站点域名
  398 + $ai_projects = $this->getAiProjects()['data'] ?? [];
  399 + $flg_ai = $this->getAiFlag($ai_projects, $domain);
  400 + $ai_domain = str_replace('www.', '', $this->getAiProjects($domain)['domain'] ?? '');
  401 + $list = RankData::where('project_id', $project_id)->where('lang', $lang)->value('data') ?: [];
  402 + $list30 = []; //排名前三十的
  403 + $list30_0 = []; //排名前三十且近三天没有排名的
  404 + $list100 = []; //排名前100的
  405 + $list0 = [];//排名为0的
  406 + foreach ($list as $key => $v) {
  407 + $last = Arr::last($v);
  408 + $data = [];
  409 + //处理日期
  410 + foreach ($v as $date => $position) {
  411 + $data[date('m-d', strtotime($date . '+ 1 day'))] = $position['position'];
  412 + }
  413 + //域名类型
  414 + $domain_text = '主域名:' . str_replace('www.', '', $domain);
  415 + if (!empty($last['r'])) {
  416 + $domain_text = 'AI域名:' . $last['r'];
  417 + if (in_array($flg_ext, [1, 2]) || $flg_ai == 1) {
  418 + if ($last['r'] == $ai_domain) {
  419 + $domain_text = '星链域名:' . $ai_domain;
  420 + } else if ($last['r'] == $ext_domain) {
  421 + $domain_text = '主域名2:' . $ext_domain;
  422 + } else {
  423 + $domain_text = 'AI域名:' . $last['r'];
  424 + }
  425 + }
  426 + }
  427 + $domain_arr = explode(':', $domain_text);
  428 + $v = [
  429 + 'keyword' => $key,
  430 + 'domain_type' => $domain_arr[0],
  431 + 'domain' => $domain_arr[1],
  432 + 'domain_text' => $domain_text,
  433 + 'g' => $last['g'], //1核心关键词
  434 + 'position' => $data,
  435 + ];
  436 + //图片排名
  437 + if(isset($last['p_img'])){
  438 + $v['img_position'] = $last['p_img'];
  439 + }
  440 + //视频排名
  441 + if(isset($last['p_vid'])){
  442 + $v['video_position'] = $last['p_vid'];
  443 + }
  444 +
  445 + if ($last['position'] == 0) {
  446 + $list0[] = $v;
  447 + } elseif ($last['position'] <= 30) {
  448 + if (($v['position'][date('m-d', strtotime('-1day'))] ?? '') == 0 ||
  449 + ($v['position'][date('m-d', strtotime('-2day'))] ?? '') == 0) {
  450 + $list30_0[] = $v;
  451 + } else {
  452 + $list30[] = $v;
  453 + }
  454 + } else {
  455 + $list100[] = $v;
  456 + }
  457 + }
  458 + //排序 排名前30的 按关键词长短排序 最近三天无排名的排后; 后30名的按排名排序
  459 + $list30 = collect($list30)->sortBy(function ($item) {
  460 + return strlen($item['keyword']);
  461 + })->values()->all();
  462 + $list30_0 = collect($list30_0)->sortBy(function ($item) {
  463 + return strlen($item['keyword']);
  464 + })->values()->all();
  465 + $list100 = collect($list100)->sortBy(function ($item) {
  466 + return Arr::last($item['position']);
  467 + })->values()->all();
  468 + $list = collect($list30)->merge($list30_0)->merge($list100)->merge($list0)->filter(function ($item) {
  469 + //搜索
  470 + if ($this->request['search']) {
  471 + return strpos($item['keyword'], $this->request['search']) !== false;
  472 + }
  473 + //前几名
  474 + if ($this->request['first']) {
  475 + $position = Arr::last($item['position']);
  476 + return $position > 0 && $position <= $this->request['first'];
  477 + }
  478 + //核心词
  479 + if ($this->request['g']) {
  480 + return $item['g'] == $this->request['g'];
  481 + }
  482 + return true;
  483 + })->values();
  484 +
  485 + if($export){
  486 + return $list->toArray();
  487 + }
  488 + $data = [
  489 + "list" => $list->forPage($page, 100)->toArray(),
  490 + "total" => $list->count(),
  491 + "page" => $page,
  492 + "total_page" => ceil($list->count() / 100),
  493 + "size" => 100
  494 + ];
  495 + return $data;
  496 + }
  497 +
  498 + /**
  499 + * 获取复制站点项目
  500 + * @author zbj
  501 + * @date 2023/5/12
  502 + */
  503 + public function getExtendProjects($api_no = null)
  504 + {
  505 + $key = 'extend_projects_list';
  506 + $data = Cache::get($key);
  507 + if (!$data) {
  508 + $api_url = 'http://api.quanqiusou.cn/google-rank/api/extend_projects.php';
  509 + try {
  510 + $data = HttpUtils::get($api_url, []);
  511 + if ($data) {
  512 + $data = Arr::s2a($data);
  513 + Cache::put($key, $data, 4 * 3600);
  514 + }
  515 + } catch (\Exception | GuzzleException $e) {
  516 + errorLog('复制站点项目获取失败', [], $e);
  517 + return false;
  518 + }
  519 + }
  520 + if ($api_no !== null) {
  521 + $data = collect($data)->where('apino', $api_no)->first();
  522 + return $data ?: [];
  523 + }
  524 + return $data;
  525 + }
  526 +
  527 + /**
  528 + * 获取AI站点项目
  529 + * @author zbj
  530 + * @date 2023/5/12
  531 + */
  532 + public function getAiProjects($domain = null)
  533 + {
  534 + $key = 'ai_projects_list';
  535 + $data = Cache::get($key);
  536 + if (!$data) {
  537 + $api_url = 'https://demosite5.globalso.com/api/domain';
  538 + try {
  539 + $data = HttpUtils::get($api_url, []);
  540 + if ($data) {
  541 + $data = Arr::s2a($data);
  542 + Cache::put($key, $data, 4 * 3600);
  543 + }
  544 + } catch (\Exception | GuzzleException $e) {
  545 + errorLog('AI站点项目获取失败', [], $e);
  546 + return false;
  547 + }
  548 + }
  549 + if ($domain !== null) {
  550 + $domain = parse_url($domain);
  551 + $data = collect($data['data'])->where('bind_domain', $domain['host'] ?? $domain['path'])->first();
  552 + return $data ?: [];
  553 + }
  554 + return $data;
  555 + }
  556 +
  557 + /**
  558 + * 获取复制项目标识
  559 + * @author zbj
  560 + * @date 2023/5/15
  561 + */
  562 + protected function getExtFlag($ext_projects, $domain, $api_no)
  563 + {
  564 + //复制站点标识
  565 + $flg_ext = 0;
  566 + if ($ext_projects) {
  567 + $ext_urls = array_column($ext_projects, 'ext');
  568 + $api_nos = array_column($ext_projects, 'apino');
  569 + if (in_array($api_no, $api_nos)) {
  570 + $flg_ext = 1;
  571 + }
  572 + if (in_array($domain, $ext_urls)) {
  573 + $flg_ext = 2;
  574 + }
  575 + }
  576 + return $flg_ext;
  577 + }
  578 +
  579 + /**
  580 + * 获取AI项目标识
  581 + * @author zbj
  582 + * @date 2023/5/15
  583 + */
  584 + protected function getAiFlag($ai_projects, $domain)
  585 + {
  586 + $flg_ai = 0;
  587 + foreach ($ai_projects as $ai_project) {
  588 + if ($ai_project['bind_domain'] == $domain) {
  589 + $flg_ai = 1;
  590 + }
  591 + }
  592 + return $flg_ai;
  593 + }
  594 +}
@@ -6,6 +6,7 @@ use App\Enums\Common\Code; @@ -6,6 +6,7 @@ use App\Enums\Common\Code;
6 use App\Helper\Arr; 6 use App\Helper\Arr;
7 use App\Helper\Common; 7 use App\Helper\Common;
8 use App\Http\Controllers\Bside\BaseController; 8 use App\Http\Controllers\Bside\BaseController;
  9 +use App\Http\Logic\Aside\Project\ProjectLogic;
9 use App\Http\Logic\Bside\User\UserLogic; 10 use App\Http\Logic\Bside\User\UserLogic;
10 use App\Jobs\PurchaserJob; 11 use App\Jobs\PurchaserJob;
11 use App\Models\Com\Purchaser; 12 use App\Models\Com\Purchaser;
@@ -328,5 +329,4 @@ class ComController extends BaseController @@ -328,5 +329,4 @@ class ComController extends BaseController
328 $this->response('success',Code::SUCCESS,$data); 329 $this->response('success',Code::SUCCESS,$data);
329 } 330 }
330 331
331 -  
332 } 332 }
@@ -39,6 +39,8 @@ class SuppliersController extends BaseController @@ -39,6 +39,8 @@ class SuppliersController extends BaseController
39 foreach ($lists as $v){ 39 foreach ($lists as $v){
40 $resultData = json_decode($v['data']); 40 $resultData = json_decode($v['data']);
41 foreach ($resultData as $value){ 41 foreach ($resultData as $value){
  42 + $value = (array)$value;
  43 + $value['keyword'] = $v['keyword'];
42 $data[] = $value; 44 $data[] = $value;
43 } 45 }
44 } 46 }
@@ -59,7 +61,10 @@ class SuppliersController extends BaseController @@ -59,7 +61,10 @@ class SuppliersController extends BaseController
59 $token = $action_name. '+' .date('Y-m-d'). '+' .http_build_query($param); 61 $token = $action_name. '+' .date('Y-m-d'). '+' .http_build_query($param);
60 $param['token'] = md5($token); 62 $param['token'] = md5($token);
61 $res = http_post($url,json_encode($param)); 63 $res = http_post($url,json_encode($param));
62 - if($res['code'] != 200){ 64 + if(isset($res['code']) && $res['code'] != 200){
  65 + $this->response($res['message'],Code::SYSTEM_ERROR);
  66 + }
  67 + if(isset($res['status_code']) && $res['status_code'] != 200){
63 $this->response($res['message'],Code::SYSTEM_ERROR); 68 $this->response($res['message'],Code::SYSTEM_ERROR);
64 } 69 }
65 return $this->success($res['data']); 70 return $this->success($res['data']);
@@ -152,9 +157,13 @@ class SuppliersController extends BaseController @@ -152,9 +157,13 @@ class SuppliersController extends BaseController
152 $action_name = 'supplier_area'; 157 $action_name = 'supplier_area';
153 $param = [ 158 $param = [
154 'prod_desc'=>$this->param['prod_desc'] ?? '', 159 'prod_desc'=>$this->param['prod_desc'] ?? '',
155 - 'start_date'=>$this->param['start_date'] ?? '',  
156 - 'end_date'=>$this->param['end_date'] ?? '',  
157 ]; 160 ];
  161 + if(isset($this->param['start_date'] )){
  162 + $param['start_date'] = $this->param['start_date'] ?? '';
  163 + }
  164 + if(isset($this->param['end_date'] )){
  165 + $param['end_date'] = $this->param['end_date'] ?? '';
  166 + }
158 $res = $this->_action($api_url,$action_name,$param); 167 $res = $this->_action($api_url,$action_name,$param);
159 $this->response('success',Code::SUCCESS,$res); 168 $this->response('success',Code::SUCCESS,$res);
160 } 169 }
@@ -171,8 +180,10 @@ class SuppliersController extends BaseController @@ -171,8 +180,10 @@ class SuppliersController extends BaseController
171 $action_name = 'trade_partner'; 180 $action_name = 'trade_partner';
172 $param = [ 181 $param = [
173 'com_id'=>$this->param['com_id'] ?? '', 182 'com_id'=>$this->param['com_id'] ?? '',
174 - 'com_role'=>$this->param['com_role'] ?? '',  
175 ]; 183 ];
  184 + if(isset($this->param['com_role'] )){
  185 + $param['com_role'] = $this->param['com_role'] ?? '';
  186 + }
176 $res = $this->_action($api_url,$action_name,$param); 187 $res = $this->_action($api_url,$action_name,$param);
177 $this->response('success',Code::SUCCESS,$res); 188 $this->response('success',Code::SUCCESS,$res);
178 } 189 }
@@ -58,7 +58,7 @@ class InquiryLogic extends BaseLogic @@ -58,7 +58,7 @@ class InquiryLogic extends BaseLogic
58 $data['total'] = $list['data']['total']; 58 $data['total'] = $list['data']['total'];
59 $data['total_page'] = $list['data']['last_page']; 59 $data['total_page'] = $list['data']['last_page'];
60 } 60 }
61 - return $this->success($data); 61 + return $data;
62 } 62 }
63 63
64 public function getOtherList($export = false){ 64 public function getOtherList($export = false){
@@ -83,10 +83,32 @@ class TranslateLogic extends BaseLogic @@ -83,10 +83,32 @@ class TranslateLogic extends BaseLogic
83 83
84 } 84 }
85 } 85 }
  86 + $data = $this->unique_multidimensional_array($data);
86 return $this->success($data); 87 return $this->success($data);
87 } 88 }
88 89
89 /** 90 /**
  91 + * @remark :多维数组去重
  92 + * @name :unique_multidimensional_array
  93 + * @author :lyh
  94 + * @method :post
  95 + * @time :2024/3/8 16:38
  96 + */
  97 + public function unique_multidimensional_array($array) {
  98 + $tempArray = [];
  99 + $uniqueArray = [];
  100 + foreach ($array as $value) {
  101 + // 使用键作为临时数组的键,如果不存在则添加到去重后的数组中
  102 + $key = key($value);
  103 + if (!isset($tempArray[$key])) {
  104 + $tempArray[$key] = true;
  105 + $uniqueArray[] = $value;
  106 + }
  107 + }
  108 + return $uniqueArray;
  109 + }
  110 +
  111 + /**
90 * @remark :获取图片列表 112 * @remark :获取图片列表
91 * @name :imageList 113 * @name :imageList
92 * @author :lyh 114 * @author :lyh
@@ -30,10 +30,10 @@ class KeywordRequest extends FormRequest @@ -30,10 +30,10 @@ class KeywordRequest extends FormRequest
30 public function rules() 30 public function rules()
31 { 31 {
32 return [ 32 return [
33 - 'title'=>'required|max:50',  
34 - 'seo_title'=>'max:200',  
35 - 'seo_keywords'=>'max:200',  
36 - 'seo_description'=>'max:200', 33 + 'title'=>'required|max:200',
  34 + 'seo_title'=>'max:255',
  35 + 'seo_keywords'=>'max:500',
  36 + 'seo_description'=>'max:500',
37 'related_news_ids'=>'array|max:2', 37 'related_news_ids'=>'array|max:2',
38 'related_blog_ids'=>'array|max:2', 38 'related_blog_ids'=>'array|max:2',
39 ]; 39 ];
@@ -43,10 +43,10 @@ class KeywordRequest extends FormRequest @@ -43,10 +43,10 @@ class KeywordRequest extends FormRequest
43 { 43 {
44 return [ 44 return [
45 'title.required' => '请输入关键词', 45 'title.required' => '请输入关键词',
46 - 'title.max' => '关键词不能超过50个字符',  
47 - 'seo_title.max' => 'SEO标题不能超过200个字符',  
48 - 'seo_keywords.max' => 'SEO关键词不能超过200个字符',  
49 - 'seo_description.max' => 'SEO描述不能超过200个字符', 46 + 'title.max' => '关键词不能超过200个字符',
  47 + 'seo_title.max' => 'SEO标题不能超过255个字符',
  48 + 'seo_keywords.max' => 'SEO关键词不能超过500个字符',
  49 + 'seo_description.max' => 'SEO描述不能超过500个字符',
50 'related_news_ids.max' => '关联新闻不能超过两条', 50 'related_news_ids.max' => '关联新闻不能超过两条',
51 'related_blog_ids.max' => '关联博客不能超过两条', 51 'related_blog_ids.max' => '关联博客不能超过两条',
52 ]; 52 ];
@@ -23,5 +23,5 @@ Route::get('optimize_project_list', [\App\Http\Controllers\Api\PrivateController @@ -23,5 +23,5 @@ Route::get('optimize_project_list', [\App\Http\Controllers\Api\PrivateController
23 Route::get('get_project_route', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectRoute'])->name('api.get_project_route'); 23 Route::get('get_project_route', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectRoute'])->name('api.get_project_route');
24 Route::any('get_product_images', [\App\Http\Controllers\Api\ProductController::class, 'getImages'])->name('api.get_product_images'); 24 Route::any('get_product_images', [\App\Http\Controllers\Api\ProductController::class, 'getImages'])->name('api.get_product_images');
25 Route::post('inquiry_submit', [\App\Http\Controllers\Api\InquiryController::class, 'submit'])->name('api.inquiry_submit'); 25 Route::post('inquiry_submit', [\App\Http\Controllers\Api\InquiryController::class, 'submit'])->name('api.inquiry_submit');
26 -  
27 -Route::post('video_task_callback', [\App\Http\Controllers\Api\NoticeController::class, 'videoTaskCallback'])->name('api.video_task_callback');  
  26 +Route::any('getOptimizationReport', [\App\Http\Controllers\Api\OptimizationReportController::class, 'getOptimizationReport'])->name('api.getOptimizationReport');
  27 +Route::post('video_task_callback', [\App\Http\Controllers\Api\NoticeController::class, 'videoTaskCallback'])->name('api.video_task_callback');