作者 刘锟

Merge remote-tracking branch 'origin/master' into akun

@@ -17,6 +17,7 @@ use App\Models\Product\Category; @@ -17,6 +17,7 @@ use App\Models\Product\Category;
17 use App\Models\Product\CategoryRelated; 17 use App\Models\Product\CategoryRelated;
18 use App\Models\Product\Column; 18 use App\Models\Product\Column;
19 use App\Models\Product\Detail; 19 use App\Models\Product\Detail;
  20 +use App\Models\Product\ExtendInfo;
20 use App\Models\Product\Product; 21 use App\Models\Product\Product;
21 use App\Models\RouteMap\RouteMap; 22 use App\Models\RouteMap\RouteMap;
22 use App\Models\Template\BTemplate; 23 use App\Models\Template\BTemplate;
@@ -51,14 +52,68 @@ class LyhImportTest extends Command @@ -51,14 +52,68 @@ class LyhImportTest extends Command
51 * @time :2023/11/20 15:13 52 * @time :2023/11/20 15:13
52 */ 53 */
53 public function handle(){ 54 public function handle(){
54 -// ProjectServer::useProject(3283);  
55 -// echo date('Y-m-d H:i:s') . 'start' . PHP_EOL;  
56 -// $this->importProduct('https://ecdn6.globalso.com/upload/p/1/file/2025-03/zy_boss_price_copy1.csv',3283);  
57 -// DB::disconnect('custom_mysql'); 55 + ProjectServer::useProject(3283);
  56 + echo date('Y-m-d H:i:s') . 'start' . PHP_EOL;
  57 +// $this->importProductCategory('https://ecdn6.globalso.com/upload/p/3283/file/2025-03/zy_boss_pricelistcat_202503131025.csv','3283');
  58 + $this->importProduct('https://ecdn6.globalso.com/upload/p/3283/file/2025-03/zy_boss_price_copy1.csv',3283);
  59 + DB::disconnect('custom_mysql');
58 echo date('Y-m-d H:i:s') . 'end' . PHP_EOL; 60 echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;
59 } 61 }
60 62
61 /** 63 /**
  64 + * @remark :导入产品分类
  65 + * @name :productCategory
  66 + * @author :lyh
  67 + * @method :post
  68 + * @time :2025/3/13 9:58
  69 + */
  70 + public function importProductCategory($url,$project_id){
  71 + $line_of_text = [];
  72 + $opts = [
  73 + 'http' => [
  74 + 'method' => 'GET',
  75 + 'header' => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246'
  76 + ],
  77 + 'ssl' => [
  78 + 'verify_peer' => false,
  79 + 'verify_peer_name' => false
  80 + ]
  81 + ];
  82 + $file_handle = fopen($url, 'r', null, stream_context_create($opts));
  83 + while (!feof($file_handle)) {
  84 + $line_of_text[] = fgetcsv($file_handle, 0, ',');
  85 + }
  86 + fclose($file_handle);
  87 + $categoryModel = new Category();
  88 + foreach ($line_of_text as $k => $val){
  89 + if($k < 1){
  90 + continue;
  91 + }
  92 + if(empty($val[1])){
  93 + continue;
  94 + }
  95 + try {
  96 + $id = $categoryModel->addReturnId(['project_id'=>$project_id,'title'=>$val[1],'seo_title'=>$val[0],'seo_keyword'=>$val[2]]);
  97 + $pid = 0;
  98 + if($val[2] != 0){
  99 + //查询上级id
  100 + $pidCate = $categoryModel->read(['seo_title'=>$val[2]]);
  101 + if($pidCate !== false){
  102 + $pid = $pidCate['id'];
  103 + }
  104 + }
  105 + $route = RouteMap::setRoute($val[1],RouteMap::SOURCE_PRODUCT_CATE,$id,$project_id);
  106 + $categoryModel->edit(['route'=>$route,'pid'=>$pid],['id'=>$id]);
  107 + echo date('Y-m-d H:i:s') . '产品分类id:'. $id.PHP_EOL;
  108 + }catch (\Exception $e){
  109 + echo date('Y-m-d H:i:s') . '跳过的产品名称:'. $val[1];
  110 + continue;
  111 + }
  112 + }
  113 + return true;
  114 + }
  115 +
  116 + /**
62 * @remark :导入分类 117 * @remark :导入分类
63 * @name :importProductCategory 118 * @name :importProductCategory
64 * @author :lyh 119 * @author :lyh
@@ -85,71 +140,166 @@ class LyhImportTest extends Command @@ -85,71 +140,166 @@ class LyhImportTest extends Command
85 $cateModel = new Category(); 140 $cateModel = new Category();
86 $productModel = new Product(); 141 $productModel = new Product();
87 $detailModel = new Detail(); 142 $detailModel = new Detail();
88 - $columnModel = new Column(); 143 + $extentInfoModel = new ExtendInfo();
89 foreach ($line_of_text as $k => $val){ 144 foreach ($line_of_text as $k => $val){
90 - if($k < 2){ 145 + if($k < 1){
91 continue; 146 continue;
92 } 147 }
93 $saveData = []; 148 $saveData = [];
94 - if($val[1] ?? ''){  
95 - $saveData['title'] = $val[1]; 149 + if(!empty($val[11])){
  150 + $saveData['title'] = $val[11];
96 }else{ 151 }else{
97 continue; 152 continue;
98 } 153 }
99 - if($val[0] ?? ''){  
100 - $cateInfo = $cateModel->read(['seo_title'=>trim($val[0])]); 154 + if(!empty($val[1])){
  155 + $cateInfo = $cateModel->read(['seo_title'=>trim($val[1])]);
101 if($cateInfo !== false){ 156 if($cateInfo !== false){
102 $saveData['category_id'] = ','.$cateInfo['id'].','; 157 $saveData['category_id'] = ','.$cateInfo['id'].',';
103 } 158 }
104 } 159 }
105 - $saveData['intro'] = $val[2];  
106 - $saveData['content'] = $val[3];  
107 - $seo = ['seo_title'=>$val[5]];  
108 - $saveData['seo_mate'] = json_encode($seo,true);  
109 - $thumb = ['alt'=>'主图','url'=>str_replace('/public','',$val[6])];  
110 - $gallery = [['alt'=>'主图','url'=>str_replace('/public','',$val[6])]];  
111 - $saveData['thumb'] = json_encode($thumb,true);  
112 - $saveData['gallery'] = json_encode($gallery,true);  
113 - $id = $productModel->addReturnId($saveData);  
114 - echo date('Y-m-d H:i:s') . '新增产品id:'.$id . PHP_EOL; 160 + $saveData['project_id'] = $project_id;
  161 + $saveData['status'] = 1;
  162 + $saveData['intro'] = $val[6] ?? '';
  163 + $seo = ['title'=>$val[11]];
  164 + $saveData['seo_mate'] = json_encode($seo,JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
  165 + $thumb = ['alt'=>'主图','url'=>str_replace('/public','/upload/p/3283',$val[12])];
  166 + $gallery = [['alt'=>'主图','url'=>str_replace('/public','/upload/p/3283',$val[12])]];
  167 + $saveData['thumb'] = json_encode($thumb,JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
  168 + $saveData['gallery'] = json_encode($gallery,JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
  169 + try {
  170 + $id = $productModel->addReturnId($saveData);
  171 + }catch (\Exception $e){
  172 + @file_put_contents(storage_path('logs/lyh_error.log'), var_export('未导入成功--标题:'.$val[0], true) . PHP_EOL, FILE_APPEND);
  173 + continue;
  174 + }
115 //设置关联关系 175 //设置关联关系
116 if($cateInfo !== false){ 176 if($cateInfo !== false){
117 CategoryRelated::saveRelated($id,[$cateInfo['id']]); 177 CategoryRelated::saveRelated($id,[$cateInfo['id']]);
118 } 178 }
119 //设置路由 179 //设置路由
120 - $route = RouteMap::setRoute($val[1],RouteMap::SOURCE_PRODUCT,$id,$project_id); 180 + $route = RouteMap::setRoute($val[11],RouteMap::SOURCE_PRODUCT,$id,$project_id);
121 $productModel->edit(['route'=>$route],['id'=>$id]); 181 $productModel->edit(['route'=>$route],['id'=>$id]);
122 - //设置产品描述  
123 - $detail = [  
124 - 'product_id'=>$id,  
125 - 'column_id'=>1,  
126 - 'text_type'=>1,  
127 - 'content'=>json_encode(['content'=>$val[3]])  
128 - ];  
129 - $detailModel->addReturnId($detail);  
130 - //扩展描述设置  
131 - $detailFaq = [  
132 - 'column_name'=>'FAQs',  
133 - 'product_id'=>$id  
134 - ];  
135 - $faqId = $columnModel->addReturnId($detailFaq); 182 + echo date('Y-m-d H:i:s') . '新增产品id:'.$id . PHP_EOL;
  183 + if(!empty($val[2])){
  184 + $extent = [
  185 + 'key'=>'pd_extended_field_4',
  186 + 'product_id'=>$id,
  187 + 'project_id'=>$project_id,
  188 + 'values'=>$val[2],
  189 + ];
  190 + try {
  191 + $extentInfoModel->addReturnId($extent);
  192 + }catch (\Exception $e){
  193 + echo '错误:'.$val[2];
  194 + }
136 195
137 - $faqsDetail = json_decode($val[4],true);  
138 - $faqContent = '';  
139 - if(!empty($faqsDetail) && is_array($faqsDetail)){  
140 - foreach ($faqsDetail as $faq_Val){  
141 - $faqContent .= "question:".$faq_Val['question'] . "<br />" . "answer:".$faq_Val['answer']. "<br />"; 196 + }
  197 + if(!empty($val[3])){
  198 + $extent = [
  199 + 'key'=>'pd_extended_field_1',
  200 + 'product_id'=>$id,
  201 + 'project_id'=>$project_id,
  202 + 'values'=>$val[3],
  203 + ];
  204 + try {
  205 + $extentInfoModel->addReturnId($extent);
  206 + }catch (\Exception $e){
  207 + echo '错误:'.$val[3];
142 } 208 }
143 - $detailFaqInfo = [ 209 + }
  210 + if(!empty($val[4])){
  211 + $extent = [
  212 + 'key'=>'pd_extended_field_2',
144 'product_id'=>$id, 213 'product_id'=>$id,
145 - 'column_id'=>$faqId, 214 + 'project_id'=>$project_id,
  215 + 'values'=>$val[4],
  216 + ];
  217 + try {
  218 + $extentInfoModel->addReturnId($extent);
  219 + }catch (\Exception $e){
  220 + echo '错误:'.$val[4];
  221 + }
  222 + }
  223 + if(!empty($val[5])){
  224 + $extent = [
  225 + 'key'=>'pd_extended_field_3',
  226 + 'product_id'=>$id,
  227 + 'project_id'=>$project_id,
  228 + 'values'=>$val[5],
  229 + ];
  230 + try {
  231 + $extentInfoModel->addReturnId($extent);
  232 + }catch (\Exception $e){
  233 + echo '错误:'.$val[5];
  234 + }
  235 + }
  236 + //产品描述
  237 + if(!empty($val[7])){
  238 + //设置产品描述
  239 + $detail = [
  240 + 'title'=>'SEODescription',
  241 + 'product_id'=>$id,
  242 + 'column_id'=>1,
146 'text_type'=>1, 243 'text_type'=>1,
147 - 'content'=>json_encode(['content'=>$faqContent]) 244 + 'content'=>json_encode(['content'=>$val[7]],JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
148 ]; 245 ];
149 - $detailModel->addReturnId($detailFaqInfo);  
150 - }else{  
151 - @file_put_contents(storage_path('logs/lyh_error.log'), var_export('产品标题:'. $val[1] . PHP_EOL .'faqs数据有问题:' . $val[4], true) . PHP_EOL, FILE_APPEND);  
152 - echo date('Y-m-d H:i:s') . '产品标题:'. $val[1] . PHP_EOL .'faqs数据有问题:' . $val[4]; 246 + $detailModel->addReturnId($detail);
  247 + }
  248 + //产品描述
  249 + if(!empty($val[8])){
  250 + //设置产品描述
  251 + $detail = [
  252 + 'title'=>'SEOSpecification',
  253 + 'product_id'=>$id,
  254 + 'column_id'=>1,
  255 + 'text_type'=>1,
  256 + 'content'=>json_encode(['content'=>$val[8]],JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
  257 + ];
  258 + $detailModel->addReturnId($detail);
  259 + }
  260 + if(!empty($val[9])){
  261 + try {
  262 + $faqsDetail = json_decode($val[9],JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
  263 + if(!empty($faqsDetail) && is_array($faqsDetail)){
  264 + $faqContent = '<div>';
  265 + foreach ($faqsDetail as $faq_Val){
  266 + $faqContent .= "<span>question:".$faq_Val['question'] . "</span><br /><span>" . "answer:".$faq_Val['answer']. "</span><br />";
  267 + }
  268 + $faqContent .= '</div>';
  269 + $detailFaqInfo = [
  270 + 'title'=>'SEOQandA',
  271 + 'product_id'=>$id,
  272 + 'column_id'=>1,
  273 + 'text_type'=>1,
  274 + 'content'=>json_encode(['content'=>$faqContent],JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
  275 + ];
  276 + $detailModel->addReturnId($detailFaqInfo);
  277 + }
  278 + }catch(\Exception $e){
  279 + echo 'fqs';
  280 + }
  281 + }
  282 + if(!empty($val[10])){
  283 + try {
  284 + $faqsDetail = json_decode($val[10],true);
  285 + if(!empty($faqsDetail) && is_array($faqsDetail)){
  286 + $faqContent = '<div>';
  287 + foreach ($faqsDetail as $faq_Val){
  288 + $faqContent .= "<span>question:".$faq_Val['question'] . "</span><br /><span>" . "answer:".$faq_Val['answer']. "</span><br />";
  289 + }
  290 + $faqContent .= '</div>';
  291 + $detailFaqInfo = [
  292 + 'title'=>'SEOQandA_Product',
  293 + 'product_id'=>$id,
  294 + 'column_id'=>1,
  295 + 'text_type'=>1,
  296 + 'content'=>json_encode(['content'=>$faqContent])
  297 + ];
  298 + $detailModel->addReturnId($detailFaqInfo);
  299 + }
  300 + }catch(\Exception $e){
  301 + continue;
  302 + }
153 } 303 }
154 } 304 }
155 return true; 305 return true;
@@ -16,9 +16,12 @@ use App\Models\CustomModule\CustomModuleContent; @@ -16,9 +16,12 @@ use App\Models\CustomModule\CustomModuleContent;
16 use App\Models\Product\CategoryRelated; 16 use App\Models\Product\CategoryRelated;
17 use App\Models\Product\Keyword; 17 use App\Models\Product\Keyword;
18 use App\Models\Product\Product; 18 use App\Models\Product\Product;
  19 +use App\Models\Project\DeployOptimize;
19 use App\Models\Project\Project; 20 use App\Models\Project\Project;
  21 +use App\Models\RankData\RankDataLog;
20 use App\Models\RouteMap\RouteMap; 22 use App\Models\RouteMap\RouteMap;
21 use App\Models\WebSetting\WebSetting; 23 use App\Models\WebSetting\WebSetting;
  24 +use App\Models\WebSetting\WebSettingSeo;
22 use App\Services\ProjectServer; 25 use App\Services\ProjectServer;
23 use App\Utils\HttpUtils; 26 use App\Utils\HttpUtils;
24 use GuzzleHttp\Exception\GuzzleException; 27 use GuzzleHttp\Exception\GuzzleException;
@@ -61,25 +64,35 @@ class UpdateRoute extends Command @@ -61,25 +64,35 @@ class UpdateRoute extends Command
61 $projectModel = new Project(); 64 $projectModel = new Project();
62 $lists = $projectModel->list(['delete_status'=>0],'id',['id']); 65 $lists = $projectModel->list(['delete_status'=>0],'id',['id']);
63 foreach ($lists as $v){ 66 foreach ($lists as $v){
64 - echo date('Y-m-d H:i:s') . 'project_id:'.$v['id'] . PHP_EOL; 67 + echo date('Y-m-d H:i:s') . '执行项目的project_id:'.$v['id'] . PHP_EOL;
65 ProjectServer::useProject($v['id']); 68 ProjectServer::useProject($v['id']);
66 - $webSettingModel = new WebSetting();  
67 - $settingInfo = $webSettingModel->read(['project_id'=>$v['id']]);  
68 - if($settingInfo === false){  
69 - echo date('Y-m-d H:i:s') . '当前项目的设置数据不存在:'.$v['id'] . PHP_EOL;  
70 - //新增一条数据  
71 - $data = [  
72 - 'anchor_setting'=>'["3","4","5"]',  
73 - 'anchor_is_enable'=>1,  
74 - 'anchor_page_num'=>1,  
75 - 'anchor_num'=>2,  
76 - 'anchor_keyword_is_enable'=>1,  
77 - 'project_id'=>$v['id']  
78 - ];  
79 - $webSettingModel->add($data);  
80 - } 69 + $this->updateSeo($v['id']);
81 DB::disconnect('custom_mysql'); 70 DB::disconnect('custom_mysql');
82 } 71 }
  72 +
  73 +// $this->updateProjectOp();
  74 +// $projectModel = new Project();
  75 +// $lists = $projectModel->list(['delete_status'=>0],'id',['id']);
  76 +// foreach ($lists as $v){
  77 +// echo date('Y-m-d H:i:s') . 'project_id:'.$v['id'] . PHP_EOL;
  78 +// ProjectServer::useProject($v['id']);
  79 +// $webSettingModel = new WebSetting();
  80 +// $settingInfo = $webSettingModel->read(['project_id'=>$v['id']]);
  81 +// if($settingInfo === false){
  82 +// echo date('Y-m-d H:i:s') . '当前项目的设置数据不存在:'.$v['id'] . PHP_EOL;
  83 +// //新增一条数据
  84 +// $data = [
  85 +// 'anchor_setting'=>'["3","4","5"]',
  86 +// 'anchor_is_enable'=>1,
  87 +// 'anchor_page_num'=>1,
  88 +// 'anchor_num'=>2,
  89 +// 'anchor_keyword_is_enable'=>1,
  90 +// 'project_id'=>$v['id']
  91 +// ];
  92 +// $webSettingModel->add($data);
  93 +// }
  94 +// DB::disconnect('custom_mysql');
  95 +// }
83 echo date('Y-m-d H:i:s') . 'end' . PHP_EOL; 96 echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;
84 } 97 }
85 98
@@ -482,4 +495,51 @@ class UpdateRoute extends Command @@ -482,4 +495,51 @@ class UpdateRoute extends Command
482 } 495 }
483 return true; 496 return true;
484 } 497 }
  498 +
  499 + /**
  500 + * @remark :更新优化设置表
  501 + * @name :updateProjectOp
  502 + * @author :lyh
  503 + * @method :post
  504 + * @time :2025/3/14 10:29
  505 + */
  506 + public function updateProjectOp(){
  507 + //查询优化中台数据
  508 + $projectModel = new Project();
  509 + $list = $projectModel->list(['type'=>2],['id']);
  510 + $rankDataModel = new RankDataLog();
  511 + $opModel = new DeployOptimize();
  512 + foreach ($list as $v){
  513 + $rankInfo = $rankDataModel->where('project_id', $v['id'])->where('is_compliance',1)->where('lang','')->orderBy('created_at', 'asc')->select('id', 'date' ,'project_id','is_compliance' ,'created_at')->first();
  514 + if(!empty($rankInfo)){
  515 + echo date('Y-m-d H:i:s') . '项目id:'.$v['id'] .'首次达标时间'. $rankInfo['date'] . PHP_EOL;
  516 + $opModel->edit(['first_compliance_time'=>$rankInfo['date']],['project_id'=>$v['id']]);
  517 + }
  518 + }
  519 + return true;
  520 + }
  521 +
  522 + /**
  523 + * @remark :更新产品分类前后缀
  524 + * @name :updateSeo
  525 + * @author :lyh
  526 + * @method :post
  527 + * @time :2025/3/14 14:39
  528 + */
  529 + public function updateSeo($project_id){
  530 + $seoModel = new WebSettingSeo();
  531 + $seo_info = $seoModel->read(['project_id'=>$project_id]);
  532 + if($seo_info !== false){
  533 + $prefix = $seo_info['product_category_prefix'] ?? [];
  534 + $suffix = $seo_info['product_category_suffix'] ?? [];
  535 + if(!empty($seo_info['product_cate_prefix'])){
  536 + $prefix[] = ['name'=>$seo_info['product_cate_prefix']];
  537 + }
  538 + if(!empty($seo_info['product_cate_suffix'])){
  539 + $suffix[] = ['name'=>$seo_info['product_cate_suffix']];
  540 + }
  541 + $seoModel->edit(['product_category_prefix'=>json_encode($prefix,true),'product_category_suffix'=>json_encode($suffix,true)],['project_id'=>$project_id]);
  542 + }
  543 + return true;
  544 + }
485 } 545 }
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2025/3/11
  6 + * Time: 14:13
  7 + */
  8 +namespace App\Console\Commands\Product;
  9 +
  10 +use App\Models\Product\Keyword;
  11 +use App\Models\Project\OnlineCheck;
  12 +use App\Models\Project\Project;
  13 +use App\Models\RankData\RankData;
  14 +use App\Repositories\ToolRepository;
  15 +use App\Services\ProjectServer;
  16 +use Illuminate\Console\Command;
  17 +use Illuminate\Support\Facades\DB;
  18 +
  19 +/**
  20 + * Class SendKeyword
  21 + * @package App\Console\Commands\Product
  22 + */
  23 +class SendKeyword extends Command
  24 +{
  25 + /**
  26 + * The name and signature of the console command.
  27 + *
  28 + * @var string
  29 + */
  30 + protected $signature = 'send_product_tag_keyword';
  31 +
  32 + /**
  33 + * The console command description.
  34 + *
  35 + * @var string
  36 + */
  37 + protected $description = '未达标项目 自动推送拼接关键词 到监控系统';
  38 +
  39 + /**
  40 + * SendKeyword constructor.
  41 + */
  42 + public function __construct()
  43 + {
  44 + parent::__construct();
  45 + }
  46 +
  47 + /**
  48 + * TODO 查询不达标优化项目, 按照规则推送拼接关键词到监控系统
  49 + * http://zentao.globalso.com/index.php?m=task&f=view&taskID=185918
  50 + * @return bool
  51 + */
  52 + public function handle()
  53 + {
  54 + $field = ['gl_project.id', 'gl_project.company', 'gl_project.main_lang_id', 'b.is_auto_keywords', 'b.start_date', 'b.api_no', 'd.domain'];
  55 + $projects = Project::select($field)->leftJoin('gl_project_deploy_optimize as b', 'gl_project.id', '=', 'b.project_id')
  56 + ->leftJoin('gl_project_online_check as c', 'gl_project.id', '=', 'c.project_id')
  57 + ->leftJoin('gl_domain_info as d', 'gl_project.id', '=', 'd.project_id')
  58 + ->where('gl_project.type', Project::TYPE_TWO)
  59 + ->where('gl_project.extend_type', 0) // 是否续费是由extend_type字段控制
  60 + ->where('gl_project.delete_status', Project::IS_DEL_FALSE)
  61 + ->where('gl_project.main_lang_id', '<>', 8) // 不需要俄语站点项目
  62 + ->where(function ($subQuery) {
  63 + $subQuery->orwhere('c.qa_status', OnlineCheck::STATUS_ONLINE_TRUE)->orwhere('gl_project.is_upgrade', Project::IS_UPGRADE_TRUE);
  64 + })
  65 + ->get();
  66 + $time = time();
  67 + $send_num = [30 => 1000, 60 => 3000, 90 => 6000];
  68 + $ban_domain = $this->banDomain();
  69 + foreach ($projects as $item) {
  70 + if (empty($item->is_auto_keywords))
  71 + continue;
  72 + if (in_array($item->domain, $ban_domain))
  73 + continue;
  74 + if (empty($item->api_no)) {
  75 + $this->output('项目ID:' . $item->id . ', api_no为空;');
  76 + continue;
  77 + }
  78 + if (empty($item->start_date)) {
  79 + $this->output('项目ID:' . $item->id . ', 推广开始时间为空;');
  80 + continue;
  81 + }
  82 + // 按照间隔时间发送不同关键词数量
  83 + $start_time = strtotime($item->start_date);
  84 + $day = intval(($time - $start_time) / 86400);
  85 + if (empty($send_num[$day])) {
  86 + $this->output('项目ID:' . $item->id . ', 推广天数:' . $day . ', 不需要推送;');
  87 + continue;
  88 + }
  89 +
  90 + // 项目是否达标
  91 + $compliance = RankData::where(['project_id' => $item->id, 'api_no' => $item->api_no, 'lang' => ''])->value('is_compliance');
  92 + if (FALSE == empty($compliance))
  93 + return false;
  94 +
  95 + $project = ProjectServer::useProject($item->id);
  96 + if (empty($project)) {
  97 + DB::disconnect('custom_mysql');
  98 + continue;
  99 + }
  100 +
  101 + $send = $this->extendKeyword($item, $send_num[$day]);
  102 + DB::disconnect('custom_mysql');
  103 + // 数据成功后推送同志
  104 + if ($send) {
  105 + $item = $item->toArray();
  106 + unset($item['main_lang_id']);
  107 + unset($item['is_auto_keywords']);
  108 + $item['day'] = $day;
  109 + $this->sendNotice($item);
  110 + }
  111 + }
  112 + return true;
  113 + }
  114 +
  115 + /**
  116 + * 截取关键词
  117 + * @param $item
  118 + * @param int $num
  119 + * @return bool
  120 + */
  121 + public function extendKeyword($item, $num = 1000)
  122 + {
  123 + $keywords = Keyword::extendKeyword($item->id);
  124 + if (empty($keywords))
  125 + return false;
  126 + $keywords = array_filter(array_unique($keywords));
  127 + $sort = [];
  128 + foreach ($keywords as $keyword) {
  129 + $sort[] = strlen($keyword);
  130 + }
  131 + array_multisort($sort, SORT_ASC, $keywords);
  132 + $result = array_slice($keywords, 0, $num);
  133 + file_put_contents(storage_path('data/send_product_tag_keyword/' . $item->id . '.json'), json_encode($result, 256));
  134 + return true;
  135 + }
  136 +
  137 + /**
  138 + * 通知
  139 + * @param $item
  140 + * @return bool
  141 + */
  142 + public function sendNotice($item)
  143 + {
  144 + try {
  145 + $query = http_build_query($item);
  146 + $url = 'http://api.quanqiusou.cn/google-rank/api/v6_add_extend_keywords.php?' . $query;
  147 + app(ToolRepository::class)->curlRequest($url, [], 'GET');
  148 + // TODO 推送通知 待定
  149 + } catch (\Exception $e) {
  150 + $this->output('推送通知失败,项目ID:' . $item['id']);
  151 + }
  152 + return true;
  153 + }
  154 +
  155 + /**
  156 + * 禁用
  157 + * @return array
  158 + */
  159 + public function banDomain()
  160 + {
  161 + $array = [
  162 + 'www.venttopurifier.com',
  163 + 'www.gwxpcsheet.com',
  164 + 'www.bizzyboi.com',
  165 + 'www.wholesaleladyclothing.com',
  166 + 'www.chuanbokeji.com',
  167 + 'www.goalwhite.com',
  168 + 'www.yusunheating.com',
  169 + 'www.bretonprecision.com',
  170 + 'www.chinarendering.com',
  171 + 'www.centurybeauty.com',
  172 + 'www.vazpocable.com',
  173 + 'www.tengda-smart.com',
  174 + 'www.kayne-bm.com',
  175 + 'www.aimazingbag.com',
  176 + 'www.alpha-lifetech.com',
  177 + 'www.junyi-laser.com',
  178 + 'www.unionfurnish.com',
  179 + 'www.zphydraulic.com',
  180 + 'www.younisicleaning.com',
  181 + 'www.shibaodeprecision.com',
  182 + 'www.semmcocoa.com',
  183 + 'www.sbdmold.com',
  184 + 'www.utsfabrictester.com',
  185 + 'www.tlgantryrobot.com',
  186 + 'www.slabyte.com',
  187 + 'www.hysum.com',
  188 + 'www.rsecobag.com',
  189 + 'www.yuchomachine.com',
  190 + 'www.hidinosaurs.com',
  191 + 'www.medigauze.com',
  192 + 'www.shtangkefresh.com',
  193 + 'www.fkcrane.com',
  194 + 'www.zkmparts.com',
  195 + 'www.zhishuogroup.com',
  196 + 'www.yunlinplushtoys.com',
  197 + ];
  198 + return $array;
  199 + }
  200 +
  201 + /**
  202 + * @param $message
  203 + */
  204 + public function output($message)
  205 + {
  206 + $message = date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;
  207 + echo $message;
  208 + file_put_contents(storage_path('data/send_product_tag_keyword.log'), $message, FILE_APPEND);
  209 + }
  210 +}
@@ -37,19 +37,19 @@ class CreateProject extends Command @@ -37,19 +37,19 @@ class CreateProject extends Command
37 } 37 }
38 38
39 public function sync($is_update = 0){ 39 public function sync($is_update = 0){
40 - $title = date('Ymd') . '-广东威美建材科技有限公司'; 40 + $title = date('Ymd') . '-杭州露娜贸易有限公司';
41 $data = [ 41 $data = [
42 'project'=>[ 42 'project'=>[
43 'title' => $title, 43 'title' => $title,
44 - 'company' => '广东威美建材科技有限公司',  
45 - 'lead_name' => '蔡伟文',  
46 - 'mobile' => '13929953235', 44 + 'company' => '杭州露娜贸易有限公司',
  45 + 'lead_name' => '13008931688',
  46 + 'mobile' => '13008931688',
47 'mysql_id'=>Project::MYSQL_ID, 47 'mysql_id'=>Project::MYSQL_ID,
48 'serve_id'=>9, 48 'serve_id'=>9,
49 'qq' => '', 49 'qq' => '',
50 - 'channel' => '{"user_id": "53", "zone_id": "4", "channel_id": "4"}', 50 + 'channel' => '{"user_id": "381", "zone_id": "4", "channel_id": "46"}',
51 'requirement' => '', 51 'requirement' => '',
52 - 'cooperate_date' => '2019-04-01', 52 + 'cooperate_date' => '2019-11-13',
53 'from_order_id' => '', 53 'from_order_id' => '',
54 'type' => $is_update, 54 'type' => $is_update,
55 'is_upgrade'=>$is_update, 55 'is_upgrade'=>$is_update,
@@ -57,7 +57,7 @@ class CreateProject extends Command @@ -57,7 +57,7 @@ class CreateProject extends Command
57 'deploy_build' => [ 57 'deploy_build' => [
58 'service_duration' => 0, 58 'service_duration' => 0,
59 'plan' => $this->versionData('标准版'), 59 'plan' => $this->versionData('标准版'),
60 - 'login_mobile'=>'13929953235' 60 + 'login_mobile'=>'13008931688'
61 ], 61 ],
62 'deploy_optimize' => [ 62 'deploy_optimize' => [
63 // 'api_no' => 0 63 // 'api_no' => 0
@@ -57,12 +57,11 @@ class RecommendedSuppliers extends Command @@ -57,12 +57,11 @@ class RecommendedSuppliers extends Command
57 { 57 {
58 $project_list = $this->deployBuildModel->list(['is_supplier'=>1]);//TODO::已开启推荐供应商 58 $project_list = $this->deployBuildModel->list(['is_supplier'=>1]);//TODO::已开启推荐供应商
59 foreach ($project_list as $v){ 59 foreach ($project_list as $v){
60 - echo date('Y-m-d H:i:s') . 'project_id:'.$v['project_id'] . PHP_EOL; 60 + echo date('Y-m-d H:i:s') . '推荐供应商执行的project_id:'.$v['project_id'] . PHP_EOL;
61 $result = $this->countPurchaser($v); 61 $result = $this->countPurchaser($v);
62 if($result !== false){ 62 if($result !== false){
63 ProjectServer::useProject($v['project_id']); 63 ProjectServer::useProject($v['project_id']);
64 $title = $this->getKeywords($v['project_id']); 64 $title = $this->getKeywords($v['project_id']);
65 - echo date('Y-m-d H:i:s') . '开始:'.$v['project_id'] . PHP_EOL;  
66 $this->savePurchaser($v['project_id'],$title); 65 $this->savePurchaser($v['project_id'],$title);
67 DB::disconnect('custom_mysql'); 66 DB::disconnect('custom_mysql');
68 } 67 }
@@ -87,6 +86,7 @@ class RecommendedSuppliers extends Command @@ -87,6 +86,7 @@ class RecommendedSuppliers extends Command
87 $plan = ['专业版'=>300, '标准版'=>500, '商务版'=>800, '旗舰版'=>1200]; 86 $plan = ['专业版'=>300, '标准版'=>500, '商务版'=>800, '旗舰版'=>1200];
88 $total_number = $plan[Project::planMap()[$v['plan']]] ?? 300; 87 $total_number = $plan[Project::planMap()[$v['plan']]] ?? 300;
89 if($count > $total_number){ 88 if($count > $total_number){
  89 + echo date('Y-m-d H:i:s') . '达到数量上线关闭的项目:'.$v['project_id'] . PHP_EOL;
90 //更新数量上限字段,并关闭推荐供应商 90 //更新数量上限字段,并关闭推荐供应商
91 $this->deployBuildModel->edit(['is_purchaser_count'=>1,'is_supplier'=>0],['project_id'=>$v['project_id']]); 91 $this->deployBuildModel->edit(['is_purchaser_count'=>1,'is_supplier'=>0],['project_id'=>$v['project_id']]);
92 return false; 92 return false;
@@ -119,14 +119,14 @@ class RecommendedSuppliers extends Command @@ -119,14 +119,14 @@ class RecommendedSuppliers extends Command
119 ]; 119 ];
120 ksort($data); 120 ksort($data);
121 $token = 'company_list+'.date('Y-m-d').'+'.http_build_query($data); 121 $token = 'company_list+'.date('Y-m-d').'+'.http_build_query($data);
122 - echo date('Y-m-d H:i:s') . '加密token:'.md5($token) . PHP_EOL; 122 +// echo date('Y-m-d H:i:s') . '加密token:'.md5($token) . PHP_EOL;
123 $param = [ 123 $param = [
124 'prod_desc'=>$keyword, 124 'prod_desc'=>$keyword,
125 'token'=>md5($token), 125 'token'=>md5($token),
126 'total'=>$this->param['row'] ?? 10, 126 'total'=>$this->param['row'] ?? 10,
127 ]; 127 ];
128 $res = http_post($url,json_encode($param)); 128 $res = http_post($url,json_encode($param));
129 - echo date('Y-m-d H:i:s') . json_encode($res) . PHP_EOL; 129 +// echo date('Y-m-d H:i:s') . json_encode($res) . PHP_EOL;
130 if(!empty($res) && isset($res['code']) && $res['code'] == 200 && !empty($res['data'])){ 130 if(!empty($res) && isset($res['code']) && $res['code'] == 200 && !empty($res['data'])){
131 //保存多条数据 131 //保存多条数据
132 $saveData = [ 132 $saveData = [
@@ -366,12 +366,16 @@ class UpdateSeoTdk extends Command @@ -366,12 +366,16 @@ class UpdateSeoTdk extends Command
366 } 366 }
367 } else if ($table == 'gl_product_keyword' && $field == 'seo_title') { 367 } else if ($table == 'gl_product_keyword' && $field == 'seo_title') {
368 # TODO 聚合页seo title 特殊处理 前缀_1 . 关键词 . 后缀_2 368 # TODO 聚合页seo title 特殊处理 前缀_1 . 关键词 . 后缀_2
  369 + $prefix = $this->getPrefixKeyword($project_id, 'prefix', 1);
  370 + $suffix = $this->getPrefixKeyword($project_id, 'suffix', 2);
  371 + if (empty($prefix) || empty($suffix)){
  372 + continue;
  373 + }
  374 +
369 $prefix = $this->getPrefixKeyword($project_id, 'prefix', 1, $v[$this->topic_fields[$table]]); 375 $prefix = $this->getPrefixKeyword($project_id, 'prefix', 1, $v[$this->topic_fields[$table]]);
370 $suffix = $this->getPrefixKeyword($project_id, 'suffix', 2, $v[$this->topic_fields[$table]]); 376 $suffix = $this->getPrefixKeyword($project_id, 'suffix', 2, $v[$this->topic_fields[$table]]);
371 - if (empty($prefix) || empty($suffix))  
372 - continue;  
373 $seo_title = $prefix . ' ' . $v[$this->topic_fields[$table]] . ' ' . $suffix; 377 $seo_title = $prefix . ' ' . $v[$this->topic_fields[$table]] . ' ' . $suffix;
374 - $data[$field] = $seo_title; 378 + $data[$field] = trim($seo_title);
375 $update[$table]['title']++; 379 $update[$table]['title']++;
376 } else if ($table == 'gl_ai_blog_list' && $field == 'seo_title') { 380 } else if ($table == 'gl_ai_blog_list' && $field == 'seo_title') {
377 //直接使用 top blog 381 //直接使用 top blog
@@ -547,6 +551,9 @@ class UpdateSeoTdk extends Command @@ -547,6 +551,9 @@ class UpdateSeoTdk extends Command
547 //去掉标题存在的词 551 //去掉标题存在的词
548 if ($topic) { 552 if ($topic) {
549 foreach ($fix_keyword as $k=>$keyword) { 553 foreach ($fix_keyword as $k=>$keyword) {
  554 + // 前后缀如果已经存在, 就不在拼接当前类型
  555 + if (FALSE !== strpos($topic, $keyword))
  556 + return $str;
550 //处理单词复数 s es ies ves 557 //处理单词复数 s es ies ves
551 $keyword = rtrim($keyword, 'ves'); 558 $keyword = rtrim($keyword, 'ves');
552 $keyword = rtrim($keyword, 'ies'); 559 $keyword = rtrim($keyword, 'ies');
@@ -700,3 +707,4 @@ class UpdateSeoTdk extends Command @@ -700,3 +707,4 @@ class UpdateSeoTdk extends Command
700 return $mail->add($data); 707 return $mail->add($data);
701 } 708 }
702 } 709 }
  710 +
@@ -19,20 +19,16 @@ class Kernel extends ConsoleKernel @@ -19,20 +19,16 @@ class Kernel extends ConsoleKernel
19 // 每日更新最新模块 19 // 每日更新最新模块
20 $schedule->command('template_label')->dailyAt('01:00')->withoutOverlapping(1);//最新模块 20 $schedule->command('template_label')->dailyAt('01:00')->withoutOverlapping(1);//最新模块
21 $schedule->command('popular_template_label')->dailyAt('01:30')->withoutOverlapping(1);//热门模块 21 $schedule->command('popular_template_label')->dailyAt('01:30')->withoutOverlapping(1);//热门模块
22 - // $schedule->command('inspire')->hourly();  
23 $schedule->command('rank_data_task')->everyMinute()->withoutOverlapping(1); // 排名数据更新任务 22 $schedule->command('rank_data_task')->everyMinute()->withoutOverlapping(1); // 排名数据更新任务
24 $schedule->command('service_count')->dailyAt('01:00')->withoutOverlapping(1); //服务器使用情况,每天凌晨1点执行一次 23 $schedule->command('service_count')->dailyAt('01:00')->withoutOverlapping(1); //服务器使用情况,每天凌晨1点执行一次
25 -// $schedule->command('web_traffic_special')->everyMinute()->withoutOverlapping(1); // 特殊引流  
26 -// $schedule->command('web_traffic_russia_special')->everyMinute()->withoutOverlapping(1); // 特殊引流  
27 $schedule->command('sync_channel')->dailyAt('06:00')->withoutOverlapping(1); // 渠道信息,每天执行一次 24 $schedule->command('sync_channel')->dailyAt('06:00')->withoutOverlapping(1); // 渠道信息,每天执行一次
28 $schedule->command('inquiry_count')->dailyAt('01:00')->withoutOverlapping(1); // 询盘统计数据,每天凌晨执行一次 25 $schedule->command('inquiry_count')->dailyAt('01:00')->withoutOverlapping(1); // 询盘统计数据,每天凌晨执行一次
29 -// $schedule->command('domain_info')->dailyAt('01:20')->withoutOverlapping(1);// 更新域名|证书结束时间,每天凌晨1点执行一次  
30 $schedule->command('share_user')->dailyAt('01:20')->withoutOverlapping(1);// 每天凌晨1点执行一次 26 $schedule->command('share_user')->dailyAt('01:20')->withoutOverlapping(1);// 每天凌晨1点执行一次
31 $schedule->command('last_inquiry')->dailyAt('04:00')->withoutOverlapping(1);// 最近一次询盘信息 27 $schedule->command('last_inquiry')->dailyAt('04:00')->withoutOverlapping(1);// 最近一次询盘信息
32 $schedule->command('update_seo_tdk_crontab')->dailyAt('20:00')->withoutOverlapping(1); //更新上线项目TDK 28 $schedule->command('update_seo_tdk_crontab')->dailyAt('20:00')->withoutOverlapping(1); //更新上线项目TDK
33 $schedule->command('sync_manager')->dailyAt('01:00')->withoutOverlapping(1); //TODO::手机号码同步 每天执行一次 29 $schedule->command('sync_manager')->dailyAt('01:00')->withoutOverlapping(1); //TODO::手机号码同步 每天执行一次
34 $schedule->command('update_keyword_route')->dailyAt('01:00')->withoutOverlapping(1); //升级项目--清除路由相同的关键字 30 $schedule->command('update_keyword_route')->dailyAt('01:00')->withoutOverlapping(1); //升级项目--清除路由相同的关键字
35 - $schedule->command('recommended_suppliers')->dailyAt('03:00')->withoutOverlapping(1); //每天凌晨1点执行一次生成推荐商 31 +// $schedule->command('recommended_suppliers')->dailyAt('03:00')->withoutOverlapping(1); //每天凌晨1点执行一次生成推荐商
36 $schedule->command('update_keyword_content')->hourly()->withoutOverlapping(1); 32 $schedule->command('update_keyword_content')->hourly()->withoutOverlapping(1);
37 // 每日推送已完成视频任务项目生成对应界面 33 // 每日推送已完成视频任务项目生成对应界面
38 //更新AI站点数据 34 //更新AI站点数据
@@ -41,9 +37,6 @@ class Kernel extends ConsoleKernel @@ -41,9 +37,6 @@ class Kernel extends ConsoleKernel
41 $schedule->command('sync_inquiry_text')->dailyAt('09:00')->withoutOverlapping(1); 37 $schedule->command('sync_inquiry_text')->dailyAt('09:00')->withoutOverlapping(1);
42 //FB询盘费用同步 38 //FB询盘费用同步
43 $schedule->command('sync_ad_cost')->everyThirtyMinutes()->withoutOverlapping(1); 39 $schedule->command('sync_ad_cost')->everyThirtyMinutes()->withoutOverlapping(1);
44 -  
45 -// $schedule->command('ai_blog_auto_publish auto_open')->everyMinute()->withoutOverlapping(1);  
46 -// $schedule->command('ai_blog_auto_publish auto_publish')->dailyAt('07:00')->withoutOverlapping(1);  
47 } 40 }
48 41
49 /** 42 /**
@@ -213,7 +213,7 @@ class Common @@ -213,7 +213,7 @@ class Common
213 } 213 }
214 $keyword = str_replace($str,'',$keyword); 214 $keyword = str_replace($str,'',$keyword);
215 $keyword = trim($keyword,'.'); 215 $keyword = trim($keyword,'.');
216 - if(strpos(strtolower($keyword),'hope') === false 216 + if( (strpos(strtolower($keyword),'hope') === false || strpos(strtolower($keyword),'hopein') !== false)
217 && (strpos(strtolower($keyword),'remember') === false || strpos(strtolower($keyword),'rememberance') !== false) 217 && (strpos(strtolower($keyword),'remember') === false || strpos(strtolower($keyword),'rememberance') !== false)
218 && strpos(strtolower($keyword),'help') === false 218 && strpos(strtolower($keyword),'help') === false
219 && strpos(strtolower($keyword),'website') === false 219 && strpos(strtolower($keyword),'website') === false
@@ -432,4 +432,29 @@ class PrivateController extends BaseController @@ -432,4 +432,29 @@ class PrivateController extends BaseController
432 DB::disconnect('custom_mysql'); 432 DB::disconnect('custom_mysql');
433 $this->response('success',Code::SUCCESS,$data); 433 $this->response('success',Code::SUCCESS,$data);
434 } 434 }
  435 +
  436 + /**
  437 + * 获取项目监控关键词
  438 + * @param Request $request
  439 + * @return false|string
  440 + */
  441 + public function getMonitorKeyword(Request $request)
  442 + {
  443 + $domain = trim($request->input('domain'));
  444 + $domain_parse = parse_url($domain);
  445 + $domain = $domain_parse['host'] ?? $domain;
  446 +
  447 + if (empty($domain)) {
  448 + return $this->error('非法参数!');
  449 + }
  450 +
  451 + $project = Project::getProjectByDomain($domain);
  452 + if (empty($project)) {
  453 + return $this->error('未找到当前域名对应的项目!');
  454 + }
  455 +
  456 + $json = file_get_contents(storage_path('data/send_product_tag_keyword/' . $project->id . '.json'));
  457 + $result = json_decode($json, true) ?: [];
  458 + return $this->success($result);
  459 + }
435 } 460 }
@@ -224,6 +224,7 @@ class OptimizeController extends BaseController @@ -224,6 +224,7 @@ class OptimizeController extends BaseController
224 'gl_project_deploy_optimize.backlink AS backlink', 224 'gl_project_deploy_optimize.backlink AS backlink',
225 'gl_project_deploy_optimize.ai_video AS ai_video', 225 'gl_project_deploy_optimize.ai_video AS ai_video',
226 'gl_project_deploy_optimize.api_no AS api_no', 226 'gl_project_deploy_optimize.api_no AS api_no',
  227 + 'gl_project_deploy_optimize.first_compliance_time AS first_compliance_time',
227 'gl_domain_info.amp_status AS amp_status', 228 'gl_domain_info.amp_status AS amp_status',
228 'gl_domain_info.domain AS domain', 229 'gl_domain_info.domain AS domain',
229 ]; 230 ];
@@ -136,6 +136,9 @@ class ProductController extends BaseController @@ -136,6 +136,9 @@ class ProductController extends BaseController
136 'id.required' => 'ID不能为空' 136 'id.required' => 'ID不能为空'
137 ]); 137 ]);
138 $info = $product->read(['id'=>$this->param['id']]); 138 $info = $product->read(['id'=>$this->param['id']]);
  139 + if($info === false){
  140 + $this->fail('当前数据不存在,或已被删除');
  141 + }
139 $info = $this->handleParam($info); 142 $info = $this->handleParam($info);
140 return $this->response('success',Code::SUCCESS,$info); 143 return $this->response('success',Code::SUCCESS,$info);
141 } 144 }
@@ -659,6 +662,9 @@ class ProductController extends BaseController @@ -659,6 +662,9 @@ class ProductController extends BaseController
659 if(isset($this->map['created_uid'])){ 662 if(isset($this->map['created_uid'])){
660 $query = $query->where('created_uid',$this->map['created_uid']); 663 $query = $query->where('created_uid',$this->map['created_uid']);
661 } 664 }
  665 + if(isset($this->map['six_read'])){
  666 + $query = $query->where('six_read',$this->map['six_read']);
  667 + }
662 if(!empty($this->param['start_at']) && !empty($this->param['end_at'])){ 668 if(!empty($this->param['start_at']) && !empty($this->param['end_at'])){
663 if($this->user['project_id'] == 2059){ 669 if($this->user['project_id'] == 2059){
664 $query->where('send_time', '>=' ,$this->param['start_at'].' 00:00:00')->where('send_time', '<=' ,$this->param['end_at'].' 59:59:59'); 670 $query->where('send_time', '>=' ,$this->param['start_at'].' 00:00:00')->where('send_time', '<=' ,$this->param['end_at'].' 59:59:59');
@@ -163,7 +163,7 @@ class ProjectLogic extends BaseLogic @@ -163,7 +163,7 @@ class ProjectLogic extends BaseLogic
163 $this->setTypeSevenEdit($this->param); 163 $this->setTypeSevenEdit($this->param);
164 }else{ 164 }else{
165 //初始化项目 165 //初始化项目
166 - $this->createProjectData($this->param); 166 + $this->param = $this->createProjectData($this->param);
167 //双向绑定服务器,需放到保存项目的上方 167 //双向绑定服务器,需放到保存项目的上方
168 $this->setServers($this->param['serve_id'],$this->param['id']); 168 $this->setServers($this->param['serve_id'],$this->param['id']);
169 //ai_blog 169 //ai_blog
@@ -196,32 +196,6 @@ class ProjectLogic extends BaseLogic @@ -196,32 +196,6 @@ class ProjectLogic extends BaseLogic
196 } 196 }
197 197
198 /** 198 /**
199 - * @remark :开启推荐供应商设置  
200 - * @name :isPurchaser  
201 - * @author :lyh  
202 - * @method :post  
203 - * @time :2025/3/10 15:33  
204 - */  
205 - public function isPurchaser($project_id){  
206 - if($this->param['type'] == Project::TYPE_TWO){  
207 - if(empty($this->param['uptime'])){  
208 - $this->param['deploy_build']['is_supplier'] = 1;  
209 - }else{  
210 - //获取项目的上线时间  
211 - $projectInfo = $this->model->read(['id'=>$project_id],['uptime']);  
212 - //查看上线时间是否大于3天  
213 - $threeDaysAgo = date('Y-m-d H:i:s', strtotime('-3 days'));  
214 - if($projectInfo['uptime'] > $threeDaysAgo){  
215 - //上线时间大于当前时间的3天钱,默认不允许关闭推荐供应商  
216 - $this->param['deploy_build']['is_supplier'] = 1;  
217 - }  
218 - }  
219 - return true;  
220 - }  
221 -  
222 - }  
223 -  
224 - /**  
225 * @remark :开启AI博客后 199 * @remark :开启AI博客后
226 * @name :setAiBlog 200 * @name :setAiBlog
227 * @author :lyh 201 * @author :lyh
@@ -243,7 +217,7 @@ class ProjectLogic extends BaseLogic @@ -243,7 +217,7 @@ class ProjectLogic extends BaseLogic
243 $aiSettingInfo = $aiSettingModel->read(['project_id'=>$project_id]); 217 $aiSettingInfo = $aiSettingModel->read(['project_id'=>$project_id]);
244 if($aiSettingInfo === false){ 218 if($aiSettingInfo === false){
245 $aiBlogService = new AiBlogService(); 219 $aiBlogService = new AiBlogService();
246 - $result = $aiBlogService->createProject($title,$languageInfo['short'],$projectInfo['company']); 220 + $result = $aiBlogService->createProject($projectInfo['company'] ?? $title,$languageInfo['short'],$projectInfo['company']);
247 if(isset($result['status']) && $result['status'] == 200){ 221 if(isset($result['status']) && $result['status'] == 200){
248 //查看当前项目是否已有记录 222 //查看当前项目是否已有记录
249 $resData = [ 223 $resData = [
@@ -350,8 +324,19 @@ class ProjectLogic extends BaseLogic @@ -350,8 +324,19 @@ class ProjectLogic extends BaseLogic
350 * @time :2023/8/30 12:14 324 * @time :2023/8/30 12:14
351 */ 325 */
352 public function saveProject($param){ 326 public function saveProject($param){
353 - if((($param['type'] == Project::TYPE_TWO) || ($param['type'] == Project::TYPE_THREE)) && empty($param['uptime'])){  
354 - $param['uptime'] = date('Y-m-d H:i:s'); 327 + if((($param['type'] == Project::TYPE_TWO) || ($param['type'] == Project::TYPE_THREE))){
  328 + //自动开启推荐供应商
  329 + if(empty($param['uptime'])){
  330 + $this->param['deploy_build']['is_supplier'] = 1;
  331 + $param['uptime'] = date('Y-m-d H:i:s');
  332 + }else{
  333 + //查看上线时间是否大于3天
  334 + $threeDaysAgo = date('Y-m-d H:i:s', strtotime('-3 days'));
  335 + if($param['uptime'] > $threeDaysAgo){
  336 + //上线时间大于当前时间的3天钱,默认不允许关闭推荐供应商
  337 + $this->param['deploy_build']['is_supplier'] = 1;
  338 + }
  339 + }
355 } 340 }
356 if($param['type'] == Project::TYPE_FIVE){ 341 if($param['type'] == Project::TYPE_FIVE){
357 $param['extend_type'] = Project::TYPE_FIVE; 342 $param['extend_type'] = Project::TYPE_FIVE;
@@ -456,6 +441,7 @@ class ProjectLogic extends BaseLogic @@ -456,6 +441,7 @@ class ProjectLogic extends BaseLogic
456 //更改域名 441 //更改域名
457 $this->editDomainStatus($deploy_optimize['domain'],$deploy_optimize['project_id']); 442 $this->editDomainStatus($deploy_optimize['domain'],$deploy_optimize['project_id']);
458 } 443 }
  444 + $deploy_optimize['gw_search_logs'] = Arr::a2s($deploy_optimize['gw_search_logs'] ?? []);
459 $deploy_optimize['start_date'] = $deploy_optimize['start_date'] ?? ''; 445 $deploy_optimize['start_date'] = $deploy_optimize['start_date'] ?? '';
460 $deploy_optimize['g_top_plan'] = Arr::a2s($deploy_optimize['g_top_plan'] ?? []); 446 $deploy_optimize['g_top_plan'] = Arr::a2s($deploy_optimize['g_top_plan'] ?? []);
461 $deploy_optimize['special'] = !empty($deploy_optimize['special']) ? ','.trim($deploy_optimize['special'],',').',' : ''; 447 $deploy_optimize['special'] = !empty($deploy_optimize['special']) ? ','.trim($deploy_optimize['special'],',').',' : '';
@@ -603,7 +589,7 @@ class ProjectLogic extends BaseLogic @@ -603,7 +589,7 @@ class ProjectLogic extends BaseLogic
603 //改为异步 589 //改为异步
604 NoticeLog::createLog(NoticeLog::TYPE_INIT_PROJECT, ['project_id' => $param['id']]); 590 NoticeLog::createLog(NoticeLog::TYPE_INIT_PROJECT, ['project_id' => $param['id']]);
605 } 591 }
606 - return $this->success(); 592 + return $this->success($param);
607 } 593 }
608 594
609 /** 595 /**
@@ -490,18 +490,7 @@ class RankDataLogic extends BaseLogic @@ -490,18 +490,7 @@ class RankDataLogic extends BaseLogic
490 $without_extension_project_ids = [658]; //是否达标只统计主词的 490 $without_extension_project_ids = [658]; //是否达标只统计主词的
491 $extension_project_ids = [354]; //扩展词也到达标的 491 $extension_project_ids = [354]; //扩展词也到达标的
492 $compliance_project_ids = [2163,257]; //直接达标处理的 492 $compliance_project_ids = [2163,257]; //直接达标处理的
493 - $ceaseProjectId = [  
494 - 47,  
495 - 354,  
496 - 378,  
497 - 649,  
498 - 1226,  
499 - 1283,  
500 - 1703,  
501 - 1893,  
502 - 2066,  
503 - ];//暂停项目id  
504 - 493 + $ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066,];//暂停项目id
505 //一个项目多个api_no 494 //一个项目多个api_no
506 $multiple_api_no_project_ids = [ 495 $multiple_api_no_project_ids = [
507 2104 => [ 496 2104 => [
@@ -515,15 +504,6 @@ class RankDataLogic extends BaseLogic @@ -515,15 +504,6 @@ class RankDataLogic extends BaseLogic
515 $g_top_first_page_extension_num = 0; 504 $g_top_first_page_extension_num = 0;
516 foreach ($data as &$ranks){ 505 foreach ($data as &$ranks){
517 ksort($ranks); 506 ksort($ranks);
518 -// foreach ($ranks as &$rank){  
519 -// //处理排名  
520 -// if(!in_array($project_id, $without_project_ids)){  
521 -// if($rank['position'] >= 10){  
522 -// $rank['position'] -= 5;  
523 -// }  
524 -// //todo 需要特殊处理排名的项目  
525 -// }  
526 -// }  
527 $last = Arr::last($ranks); 507 $last = Arr::last($ranks);
528 //第一名 508 //第一名
529 if($last['position'] == 1){ 509 if($last['position'] == 1){
@@ -586,6 +566,9 @@ class RankDataLogic extends BaseLogic @@ -586,6 +566,9 @@ class RankDataLogic extends BaseLogic
586 if (($model->updated_date != date('Y-m-d') || empty($model_is_compliance)) && !$lang) { 566 if (($model->updated_date != date('Y-m-d') || empty($model_is_compliance)) && !$lang) {
587 $compliance_day = Project::where(['id' => $project_id])->value('finish_remain_day') ?: 0; 567 $compliance_day = Project::where(['id' => $project_id])->value('finish_remain_day') ?: 0;
588 if(!in_array($project_id,$ceaseProjectId)){ 568 if(!in_array($project_id,$ceaseProjectId)){
  569 + if($compliance_day == 0){//达标天数为0并当天达标 记录当前达标时间
  570 + DeployOptimize::where(['project_id'=>$project_id])->update(['first_compliance_time'=>date('Y-m-d')]);
  571 + }
589 //多api_no项目 要api_no都分别达标才算 572 //多api_no项目 要api_no都分别达标才算
590 if(in_array($project_id, array_keys($multiple_api_no_project_ids))){ 573 if(in_array($project_id, array_keys($multiple_api_no_project_ids))){
591 $api_nos = array_keys($multiple_api_no_project_ids[$project_id]); 574 $api_nos = array_keys($multiple_api_no_project_ids[$project_id]);
@@ -50,6 +50,19 @@ class Keyword extends Base @@ -50,6 +50,19 @@ class Keyword extends Base
50 ]; 50 ];
51 51
52 /** 52 /**
  53 + * 聚合页按照首字母归类
  54 + * @param $string
  55 + * @return int
  56 + */
  57 + public function getFirstWord($string) {
  58 + $first_string = strtolower(mb_substr($string, 0, 1));
  59 + if (is_numeric($first_string))
  60 + return 0;
  61 + $string_key = array_search($first_string, $this->firstNumWord);
  62 + return $string_key ?: 27;
  63 + }
  64 +
  65 + /**
53 * @remark :视频 66 * @remark :视频
54 * @name :getKeywordVideoAttribute 67 * @name :getKeywordVideoAttribute
55 * @author :lyh 68 * @author :lyh
@@ -97,4 +110,43 @@ class Keyword extends Base @@ -97,4 +110,43 @@ class Keyword extends Base
97 return Keyword::where("project_id",$project->id)->where("status",1)->inRandomOrder()->take(10)->get(); 110 return Keyword::where("project_id",$project->id)->where("status",1)->inRandomOrder()->take(10)->get();
98 } 111 }
99 112
  113 + /**
  114 + * 拆解关键词, 拼接成为长尾关键词
  115 + * @param $project_id
  116 + * @return array
  117 + */
  118 + public static function extendKeyword($project_id)
  119 + {
  120 + $result = [];
  121 + $keywords = self::where(['project_id' => $project_id])->pluck('seo_title', 'title')->toArray();
  122 + if (empty($keywords))
  123 + return $result;
  124 + // $item:前缀 + 关键词 + 后缀
  125 + foreach ($keywords as $keyword => $item) {
  126 + try {
  127 + if (empty($keyword) || empty($item))
  128 + continue;
  129 +
  130 + // 如果title数据无法正常解析, 就将数据完整填充
  131 + $tmp = explode($keyword, $item);
  132 + if (count($tmp) <= 1) {
  133 + array_push($result, $item);
  134 + continue;
  135 + }
  136 +
  137 + // 正常数据 一个关键词会拆分成为 3或者5个关键词
  138 + // 拆分规则:前缀 + 关键词; 关键词 + 后缀;前缀 + 关键词 + 后缀;
  139 + $prefix = $tmp[0];
  140 + $suffix_array = explode(',', $tmp[1]);
  141 + array_push($result, trim($prefix . $keyword));
  142 + foreach ($suffix_array as $suffix) {
  143 + array_push($result, trim($keyword . $suffix));
  144 + array_push($result, trim($prefix . $keyword . $suffix));
  145 + }
  146 + } catch (\Exception $e) {
  147 + continue;
  148 + }
  149 + }
  150 + return $result;
  151 + }
100 } 152 }
@@ -22,6 +22,11 @@ class DeployOptimize extends Base @@ -22,6 +22,11 @@ class DeployOptimize extends Base
22 public function getGTopPlanAttribute($value){ 22 public function getGTopPlanAttribute($value){
23 return Arr::s2a($value); 23 return Arr::s2a($value);
24 } 24 }
  25 +
  26 + public function getGwSearchLogsAttribute($value){
  27 + return Arr::s2a($value);
  28 + }
  29 +
25 public static function clearCache($row){ 30 public static function clearCache($row){
26 $cache_key = 'project_' . $row->original['domain']; 31 $cache_key = 'project_' . $row->original['domain'];
27 Cache::forget($cache_key); 32 Cache::forget($cache_key);
@@ -58,6 +58,8 @@ Route::any('get_project_online', [\App\Http\Controllers\Api\PrivateController::c @@ -58,6 +58,8 @@ Route::any('get_project_online', [\App\Http\Controllers\Api\PrivateController::c
58 Route::any('mark_project_ads', [\App\Http\Controllers\Api\PrivateController::class, 'markProjectAds'])->name('api.mark_project_ads'); 58 Route::any('mark_project_ads', [\App\Http\Controllers\Api\PrivateController::class, 'markProjectAds'])->name('api.mark_project_ads');
59 //获取对应产品关键词 59 //获取对应产品关键词
60 Route::any('getProjectKeyword', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectKeyword'])->name('api.getProjectKeyword'); 60 Route::any('getProjectKeyword', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectKeyword'])->name('api.getProjectKeyword');
  61 +// 获取监控关键词 -> send_product_tag_keyword
  62 +Route::any('get_monitor_keyword', [\App\Http\Controllers\Api\PrivateController::class, 'getMonitorKeyword'])->name('api.get_monitor_keyword');
61 //自建站接口转接 63 //自建站接口转接
62 Route::post('selfSiteApi', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteApi']); 64 Route::post('selfSiteApi', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteApi']);
63 Route::post('selfSiteNotify', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteNotify']); 65 Route::post('selfSiteNotify', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteNotify']);