作者 刘锟

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

正在显示 33 个修改的文件 包含 437 行增加175 行删除
@@ -11,6 +11,7 @@ use App\Models\Project\ProjectKeyword; @@ -11,6 +11,7 @@ use App\Models\Project\ProjectKeyword;
11 use App\Models\RankData\RankData; 11 use App\Models\RankData\RankData;
12 use App\Models\WebSetting\WebSetting; 12 use App\Models\WebSetting\WebSetting;
13 use App\Services\AiBlogService; 13 use App\Services\AiBlogService;
  14 +use App\Services\DingService;
14 use App\Services\ProjectServer; 15 use App\Services\ProjectServer;
15 use Illuminate\Console\Command; 16 use Illuminate\Console\Command;
16 use Illuminate\Support\Facades\DB; 17 use Illuminate\Support\Facades\DB;
@@ -62,52 +63,64 @@ class AiBlogAutoPublish extends Command @@ -62,52 +63,64 @@ class AiBlogAutoPublish extends Command
62 $projects = Project::where('is_ai_blog', 1)->get(); 63 $projects = Project::where('is_ai_blog', 1)->get();
63 64
64 foreach ($projects as $project) { 65 foreach ($projects as $project) {
65 - $this->output("项目{$project->id}开始自动发布");  
66 - if(!$project->deploy_optimize['is_ai_blog_send']){  
67 - $this->output("项目{$project->id}未开启自动发布" . $project->deploy_optimize['start_date']);  
68 - continue;  
69 - }  
70 - if(($project->deploy_optimize['start_date'] > date('Y-m-d')) || !$project->deploy_optimize['start_date']){  
71 - $this->output("项目{$project->id}未到推广时间" . $project->deploy_optimize['start_date']);  
72 - continue;  
73 - }  
74 - $next_auto_date = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->whereNotNull('next_auto_date')->orderBy('id', 'desc')->value('next_auto_date');  
75 - if($next_auto_date && $next_auto_date > date('Y-m-d')){  
76 - $this->output("项目{$project->id}未到执行时间" . $next_auto_date);  
77 - continue;  
78 - }  
79 - //核心关键词+网站关键词  
80 - $main_keywords = ProjectKeyword::where('project_id', $project->id)->value('main_keyword');  
81 - $main_keywords = explode("\r\n", $main_keywords);  
82 - ProjectServer::useProject($project->id);  
83 - $site_keywords = WebSetting::where('project_id', $project->id)->value('keyword');  
84 - DB::disconnect('custom_mysql');  
85 - $site_keywords = explode(",", $site_keywords);  
86 - $keywords = array_filter(array_merge($main_keywords, $site_keywords));  
87 - $keywords = array_map('trim', $keywords);  
88 - if (empty($keywords)) {  
89 - $this->output("项目{$project->id}未获取到关键词");  
90 - continue;  
91 - }  
92 - $last_task = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->orderBy('id', 'desc')->first();  
93 - $compliance = RankData::where(['project_id' => $project->id, 'lang' => ''])->value('is_compliance');  
94 - $frequency = Project::typeBlogFrequency($project->deploy_optimize->send_ai_blog_frequency);  
95 - $frequency = explode('-', $frequency);  
96 - //1、之前测试那批项目,按照正常频率发送;  
97 - //2、未达标的项目,开启AIblog, 并立即推送三篇;  
98 - //3、其他项目等下下周 1 (2025-03-17)开始推送第一篇, 之后按照正频率发送;  
99 - if (!$last_task) {  
100 - if(!$compliance) {  
101 - for ($i = 0; $i < 3; $i++) {  
102 - $this->createTask($keywords, $project->id, $frequency);  
103 - }  
104 - }else{  
105 - if(date('Y-m-d') >= '2025-03-17'){  
106 - $this->createTask($keywords, $project->id, $frequency); 66 + try {
  67 + $this->output("项目{$project->id}开始自动发布");
  68 + if(!$project->deploy_optimize['is_ai_blog_send']){
  69 + $this->output("项目{$project->id}未开启自动发布" . $project->deploy_optimize['start_date']);
  70 + continue;
  71 + }
  72 + if(($project->deploy_optimize['start_date'] > date('Y-m-d')) || !$project->deploy_optimize['start_date']){
  73 + $this->output("项目{$project->id}未到推广时间" . $project->deploy_optimize['start_date']);
  74 + continue;
  75 + }
  76 + $next_auto_date = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->whereNotNull('next_auto_date')->orderBy('id', 'desc')->value('next_auto_date');
  77 + if($next_auto_date && $next_auto_date > date('Y-m-d')){
  78 + $this->output("项目{$project->id}未到执行时间" . $next_auto_date);
  79 + continue;
  80 + }
  81 + //核心关键词+网站关键词
  82 + $main_keywords = ProjectKeyword::where('project_id', $project->id)->value('main_keyword');
  83 + $main_keywords = explode("\r\n", $main_keywords);
  84 + ProjectServer::useProject($project->id);
  85 + $site_keywords = WebSetting::where('project_id', $project->id)->value('keyword');
  86 + DB::disconnect('custom_mysql');
  87 + $site_keywords = explode(",", $site_keywords);
  88 + $keywords = array_filter(array_merge($main_keywords, $site_keywords));
  89 + $keywords = array_map('trim', $keywords);
  90 + if (empty($keywords)) {
  91 + $this->output("项目{$project->id}未获取到关键词");
  92 + continue;
  93 + }
  94 + $last_task = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->orderBy('id', 'desc')->first();
  95 + $compliance = RankData::where(['project_id' => $project->id, 'lang' => ''])->value('is_compliance');
  96 + $frequency = Project::typeBlogFrequency($project->deploy_optimize->send_ai_blog_frequency);
  97 + $frequency = explode('-', $frequency);
  98 + //1、之前测试那批项目,按照正常频率发送;
  99 + //2、未达标的项目,开启AIblog, 并立即推送三篇;
  100 + //3、其他项目等下下周 1 (2025-03-17)开始推送第一篇, 之后按照正频率发送;
  101 + if (!$last_task) {
  102 + if(!$compliance) {
  103 + for ($i = 0; $i < 3; $i++) {
  104 + $this->createTask($keywords, $project->id, $frequency);
  105 + }
  106 + }else{
  107 + if(date('Y-m-d') >= '2025-03-17'){
  108 + $this->createTask($keywords, $project->id, $frequency);
  109 + }
107 } 110 }
  111 + } else {
  112 + $this->createTask($keywords, $project->id, $frequency);
108 } 113 }
109 - } else {  
110 - $this->createTask($keywords, $project->id, $frequency); 114 + }catch (\Exception $e){
  115 + (new DingService())->handle([
  116 + 'keyword' => 'AI_BLOG自动发布失败',
  117 + 'msg' => '项目ID:' . $project->id . PHP_EOL .
  118 + '错误信息:' . $e->getMessage() . PHP_EOL .
  119 + '错误文件:' . $e->getFile() . PHP_EOL .
  120 + '错误行数:' . $e->getLine(),
  121 + 'isAtAll' => true, // 是否@所有人
  122 + ]);
  123 + $this->output("自动发布失败:" . $e->getMessage() . $e->getFile() . $e->getLine());
111 } 124 }
112 } 125 }
113 } 126 }
@@ -159,23 +172,37 @@ class AiBlogAutoPublish extends Command @@ -159,23 +172,37 @@ class AiBlogAutoPublish extends Command
159 ->get(); 172 ->get();
160 173
161 foreach ($projects as $project) { 174 foreach ($projects as $project) {
162 - //未开启过 自动开启  
163 - if (!AiBlogOpenLog::isOpened($project->id)) {  
164 - //开启  
165 - $project->is_ai_blog = 1;  
166 -  
167 - //开启自动发布  
168 - $project->deploy_optimize->is_ai_blog_send = 1;  
169 - $project->deploy_optimize->save();  
170 -  
171 - $project->save();  
172 - //创建AI博客项目  
173 - $deploy_optimize = $project->deploy_optimize;  
174 - (new ProjectLogic())->setAiBlog($project->id, $project->main_lang_id, 1, $project->company, $deploy_optimize->company_en_name, $deploy_optimize->company_en_description);  
175 - //开启日志  
176 - AiBlogOpenLog::addLog($project->id);  
177 -  
178 - $this->output('自动开启项目:' . $project->id); 175 + try {
  176 + //未开启过 自动开启
  177 + if (!AiBlogOpenLog::isOpened($project->id)) {
  178 + //创建AI博客项目
  179 + $deploy_optimize = $project->deploy_optimize;
  180 + (new ProjectLogic())->setAiBlog($project->id, $project->main_lang_id, 1, $project->company, $deploy_optimize->company_en_name, $deploy_optimize->company_en_description);
  181 +
  182 + //开启
  183 + $project->is_ai_blog = 1;
  184 +
  185 + //开启自动发布
  186 + $project->deploy_optimize->is_ai_blog_send = 1;
  187 + $project->deploy_optimize->save();
  188 +
  189 + $project->save();
  190 +
  191 + //开启日志
  192 + AiBlogOpenLog::addLog($project->id);
  193 +
  194 + $this->output('自动开启项目:' . $project->id);
  195 + }
  196 + }catch (\Exception $e){
  197 + (new DingService())->handle([
  198 + 'keyword' => 'AI_BLOG自动开启失败',
  199 + 'msg' => '项目ID:' . $project->id . PHP_EOL .
  200 + '错误信息:' . $e->getMessage() . PHP_EOL .
  201 + '错误文件:' . $e->getFile() . PHP_EOL .
  202 + '错误行数:' . $e->getLine(),
  203 + 'isAtAll' => true, // 是否@所有人
  204 + ]);
  205 + $this->output("自动开启失败:" . $e->getMessage() . $e->getFile() . $e->getLine());
179 } 206 }
180 } 207 }
181 sleep(60); 208 sleep(60);
@@ -120,18 +120,18 @@ class AiBlogTask extends Command @@ -120,18 +120,18 @@ class AiBlogTask extends Command
120 DB::disconnect('custom_mysql'); 120 DB::disconnect('custom_mysql');
121 return false; 121 return false;
122 } 122 }
123 - //需要更新的路由  
124 - if (!in_array($result['data']['author_id'], $this->updateProject[$item['project_id']] ?? [])) {  
125 - $this->updateProject[$item['project_id']][] = $result['data']['author_id'];  
126 - }  
127 - if (!in_array($aiBlogInfo['route'], $this->routes[$item['project_id']] ?? [])) {  
128 - $this->routes[$item['project_id']][] = $aiBlogInfo['route'];  
129 - }  
130 //拿到返回的路由查看是否重复 123 //拿到返回的路由查看是否重复
131 $route = RouteMap::setRoute($result['data']['url'], RouteMap::SOURCE_AI_BLOG, $aiBlogInfo['id'], $item['project_id']); 124 $route = RouteMap::setRoute($result['data']['url'], RouteMap::SOURCE_AI_BLOG, $aiBlogInfo['id'], $item['project_id']);
132 if($route != $result['data']['url']){ 125 if($route != $result['data']['url']){
133 $aiBlogService->updateDetail(['route'=>$route,'task_id'=>$item['task_id']]); 126 $aiBlogService->updateDetail(['route'=>$route,'task_id'=>$item['task_id']]);
134 } 127 }
  128 + //需要更新的路由
  129 + if (!in_array($result['data']['author_id'], $this->updateProject[$item['project_id']] ?? [])) {
  130 + $this->updateProject[$item['project_id']][] = $result['data']['author_id'];
  131 + }
  132 + if (!in_array($route, $this->routes[$item['project_id']] ?? [])) {
  133 + $this->routes[$item['project_id']][] = $route;
  134 + }
135 $aiBlogModel->edit(['new_title'=>$result['data']['title'], 'image'=>$result['data']['thumb'], 'text'=>$result['data']['section'], 'author_id'=>$result['data']['author_id'],'seo_title'=>$result['data']['title'],'seo_keyword'=>$result['data']['keyword'],'seo_description'=>$result['data']['description'], 'route'=>$route ,'status'=>$aiBlogModel::STATUS_FINISH], ['task_id'=>$item['task_id']]); 135 $aiBlogModel->edit(['new_title'=>$result['data']['title'], 'image'=>$result['data']['thumb'], 'text'=>$result['data']['section'], 'author_id'=>$result['data']['author_id'],'seo_title'=>$result['data']['title'],'seo_keyword'=>$result['data']['keyword'],'seo_description'=>$result['data']['description'], 'route'=>$route ,'status'=>$aiBlogModel::STATUS_FINISH], ['task_id'=>$item['task_id']]);
136 DB::disconnect('custom_mysql'); 136 DB::disconnect('custom_mysql');
137 $aiBlogTaskModel->edit(['status'=>$aiBlogModel::STATUS_FINISH],['id'=>$item['id']]); 137 $aiBlogTaskModel->edit(['status'=>$aiBlogModel::STATUS_FINISH],['id'=>$item['id']]);
1 <?php 1 <?php
2 /** 2 /**
3 * @remark : 3 * @remark :
4 - * @name :AfterCount.php 4 + * @name :AfterDayCount.php
5 * @author :lyh 5 * @author :lyh
6 * @method :post 6 * @method :post
7 * @time :2025/3/26 15:28 7 * @time :2025/3/26 15:28
@@ -16,7 +16,7 @@ use Carbon\Carbon; @@ -16,7 +16,7 @@ use Carbon\Carbon;
16 use App\Models\HomeCount\AfterCount as AfterCountModel; 16 use App\Models\HomeCount\AfterCount as AfterCountModel;
17 use Illuminate\Console\Command; 17 use Illuminate\Console\Command;
18 18
19 -class AfterCount extends Command 19 +class AfterDayCount extends Command
20 { 20 {
21 /** 21 /**
22 * The name and signature of the console command. 22 * The name and signature of the console command.
@@ -44,6 +44,7 @@ class AfterCount extends Command @@ -44,6 +44,7 @@ class AfterCount extends Command
44 echo date('Y-m-d H:i:s').'统计start->'.PHP_EOL; 44 echo date('Y-m-d H:i:s').'统计start->'.PHP_EOL;
45 $saveData = $this->_action(); 45 $saveData = $this->_action();
46 $afterModel = new AfterCountModel(); 46 $afterModel = new AfterCountModel();
  47 + //保存数据
47 $afterModel->insertAll($saveData); 48 $afterModel->insertAll($saveData);
48 echo date('Y-m-d H:i:s').'->统计end'.PHP_EOL; 49 echo date('Y-m-d H:i:s').'->统计end'.PHP_EOL;
49 return true; 50 return true;
@@ -62,7 +63,7 @@ class AfterCount extends Command @@ -62,7 +63,7 @@ class AfterCount extends Command
62 $rankDataLogModel = new RankDataLog(); 63 $rankDataLogModel = new RankDataLog();
63 $todayMidnight = date('Y-m-d 00:00:00', strtotime('today')); 64 $todayMidnight = date('Y-m-d 00:00:00', strtotime('today'));
64 $saveData = []; 65 $saveData = [];
65 - $projectIdArr = $rankDataLogModel->selectField(['is_compliance'=>1,'lang'=>null,'date'=>date('Y-m-d', strtotime('-3 months'))],'project_id');//3个月前达标的项目id 66 + $projectIdArr = $rankDataLogModel->selectField(['is_compliance'=>1,'lang'=>'','date'=>date('Y-m-d', strtotime('-3 months'))],'project_id');//3个月前达标的项目id
66 foreach ($this->after_manager as $key => $valM){ 67 foreach ($this->after_manager as $key => $valM){
67 $idArr = $this->managerHrModel->selectField(['name'=>['in',$valM]],'id'); 68 $idArr = $this->managerHrModel->selectField(['name'=>['in',$valM]],'id');
68 $project_count = $projectModel->where('gl_project.extend_type',0) 69 $project_count = $projectModel->where('gl_project.extend_type',0)
@@ -108,9 +109,9 @@ class AfterCount extends Command @@ -108,9 +109,9 @@ class AfterCount extends Command
108 'project_count'=>$project_count, 109 'project_count'=>$project_count,
109 'qualified_count'=>$qualified_count, 110 'qualified_count'=>$qualified_count,
110 'rate'=>$rate, 111 'rate'=>$rate,
111 - 'three_project_count'=>$project_count - $three_project_count,  
112 - 'three_qualified_count'=>$qualified_count - $three_qualified_count,  
113 - 'three_rate'=>$rate - $three_rate, 112 + 'three_project_count'=>$three_project_count,
  113 + 'three_qualified_count'=>$three_qualified_count,
  114 + 'three_rate'=>$three_rate,
114 'data' => json_encode($data,true) 115 'data' => json_encode($data,true)
115 ]; 116 ];
116 } 117 }
@@ -4,10 +4,8 @@ namespace App\Console\Commands\Domain; @@ -4,10 +4,8 @@ namespace App\Console\Commands\Domain;
4 4
5 use App\Models\Project\DeployBuild; 5 use App\Models\Project\DeployBuild;
6 use App\Models\Project\DeployOptimize; 6 use App\Models\Project\DeployOptimize;
7 -use App\Models\Project\OnlineCheck;  
8 use App\Models\Project\Project; 7 use App\Models\Project\Project;
9 use Illuminate\Console\Command; 8 use Illuminate\Console\Command;
10 -use App\Models\Domain\DomainInfo as DomainInfoModel;  
11 9
12 /** 10 /**
13 * 剩余服务时长 11 * 剩余服务时长
@@ -45,6 +43,7 @@ class RemainDay extends Command @@ -45,6 +43,7 @@ class RemainDay extends Command
45 1703, 43 1703,
46 1893, 44 1893,
47 2066, 45 2066,
  46 + 2250
48 ];//需要单独处理的项目 47 ];//需要单独处理的项目
49 /** 48 /**
50 * The console command description. 49 * The console command description.
@@ -736,7 +736,7 @@ class RelayInquiry extends Command @@ -736,7 +736,7 @@ class RelayInquiry extends Command
736 // 所有可用url 736 // 所有可用url
737 $urls = $inquiry_urls = []; 737 $urls = $inquiry_urls = [];
738 //入口url 首页30%,单页10%,聚合页60% 738 //入口url 首页30%,单页10%,聚合页60%
739 - $type = getRandByRatio([30,10,60]); 739 + $type = getRandByRatio([40,20,40]);
740 $inlet = $re_website; 740 $inlet = $re_website;
741 $type == 1 && $inlet = $page_url ? Arr::random($page_url) : $re_website; 741 $type == 1 && $inlet = $page_url ? Arr::random($page_url) : $re_website;
742 $type == 2 && $inlet = $keywords_url ? Arr::random($keywords_url) : $re_website; 742 $type == 2 && $inlet = $keywords_url ? Arr::random($keywords_url) : $re_website;
@@ -19,6 +19,7 @@ use App\Models\GoogleSearch\GoogleCodeCountry; @@ -19,6 +19,7 @@ use App\Models\GoogleSearch\GoogleCodeCountry;
19 use App\Models\Product\CategoryRelated; 19 use App\Models\Product\CategoryRelated;
20 use App\Models\Product\Keyword; 20 use App\Models\Product\Keyword;
21 use App\Models\Product\Product; 21 use App\Models\Product\Product;
  22 +use App\Models\Project\AggregateKeyword;
22 use App\Models\Project\AiBlogTask; 23 use App\Models\Project\AiBlogTask;
23 use App\Models\Project\DeployOptimize; 24 use App\Models\Project\DeployOptimize;
24 use App\Models\Project\Project; 25 use App\Models\Project\Project;
@@ -66,7 +67,59 @@ class UpdateRoute extends Command @@ -66,7 +67,59 @@ class UpdateRoute extends Command
66 */ 67 */
67 public function handle() 68 public function handle()
68 { 69 {
69 - $this->insertData(); 70 + return $this->keyword_actions();
  71 + }
  72 +
  73 + public function keyword_actions(){
  74 + $a = new AggregateKeyword();
  75 +// $list = $a->formatQuery(['status'=>1])->pluck('project_id')->unique()->values()->toArray();
  76 + $list = [2368,2168,1786,2289,3685,3008];
  77 + foreach ($list as $v){
  78 + if($v == 1){
  79 + continue;
  80 + }
  81 + echo date('Y-m-d H:i:s').' 执行的项目id:'.$v.PHP_EOL;
  82 + ProjectServer::useProject($v);
  83 + $bak_lists = DB::connection('custom_mysql')->table('gl_product_keyword_bak')->where('status',1)->get()->toArray();
  84 + $keywordModel = new Keyword();
  85 + $keywordModel->truncate();
  86 + $routeMapModel = new RouteMap();
  87 + $routeMapModel->del(['source'=>'product_keyword']);
  88 + foreach ($bak_lists as $bakV){
  89 + $info = $keywordModel->read(['title'=>$bakV['title']],['id']);
  90 + if($info !== false){
  91 + echo '当前关键词已存在,跳过的关键词'.$bakV['title'].PHP_EOL;
  92 + continue;
  93 + }
  94 + //执行新增数据
  95 + unset($bakV['id']);
  96 + $id = $keywordModel->addReturnId($bakV);
  97 + $route = RouteMap::setRoute($bakV['route'],'product_keyword',$id,$v);
  98 + $keywordModel->edit(['route'=>$route],['id'=>$id]);
  99 + echo '执行新增----'.$bakV['title'].PHP_EOL;
  100 + }
  101 + DB::disconnect('custom_mysql');
  102 + }
  103 + }
  104 +
  105 + /**
  106 + * @remark :清洗数据
  107 + * @name :_action
  108 + * @author :lyh
  109 + * @method :post
  110 + * @time :2025/4/10 17:08
  111 + */
  112 + public function _action(){
  113 + $projectModel = new Project();
  114 + $lists = $projectModel->list(['delete_status'=>0,'extend_type'=>0,'type'=>['!=',0]],'id',['id']);
  115 + $keywordModel = new Keyword();
  116 + foreach ($lists as $v){
  117 + ProjectServer::useProject($v['id']);
  118 + echo date('Y-m-d H:i:s').' 执行的项目id:'.$v['id'].PHP_EOL;
  119 + $keywordModel->edit(['type'=>1],['id'=>['!=',0]]);
  120 + DB::disconnect('custom_mysql');
  121 + }
  122 + return true;
70 } 123 }
71 /** 124 /**
72 * @remark : 125 * @remark :
@@ -58,8 +58,6 @@ class OptimizeSetKeywordSync extends Command @@ -58,8 +58,6 @@ class OptimizeSetKeywordSync extends Command
58 $item->status = AggregateKeyword::STATUS_FINISH; 58 $item->status = AggregateKeyword::STATUS_FINISH;
59 $item->save(); 59 $item->save();
60 } 60 }
61 - Common::del_user_cache('product_keyword',$this->user['project_id']);  
62 - NoticeLog::createLog(NoticeLog::TYPE_INIT_KEYWORD, ['project_id' => $this->user['project_id']]);  
63 return true; 61 return true;
64 } 62 }
65 63
@@ -71,13 +69,12 @@ class OptimizeSetKeywordSync extends Command @@ -71,13 +69,12 @@ class OptimizeSetKeywordSync extends Command
71 */ 69 */
72 public function syncKeyword($project_id, $keywords) 70 public function syncKeyword($project_id, $keywords)
73 { 71 {
74 - $keywords = explode("\n", $keywords); 72 + $keywords = explode("\r\n", $keywords);
75 $keywords = array_unique(array_filter($keywords)); 73 $keywords = array_unique(array_filter($keywords));
76 -  
77 ProjectServer::useProject($project_id); 74 ProjectServer::useProject($project_id);
78 $keywordModel = new Keyword(); 75 $keywordModel = new Keyword();
79 - $keywordModel->saveBKeyword($project_id,$keywords); 76 + $keywordModel->saveBKeyword($project_id,$keywords,Keyword::TYPE_ORDER_KEYWORD);
80 DB::disconnect('custom_mysql'); 77 DB::disconnect('custom_mysql');
81 return true; 78 return true;
82 } 79 }
83 -}  
  80 +}
@@ -20,6 +20,7 @@ use App\Models\User\User as UserModel; @@ -20,6 +20,7 @@ use App\Models\User\User as UserModel;
20 use App\Services\ProjectServer; 20 use App\Services\ProjectServer;
21 use Hashids\Hashids; 21 use Hashids\Hashids;
22 use Illuminate\Console\Command; 22 use Illuminate\Console\Command;
  23 +use Illuminate\Support\Facades\Artisan;
23 use Illuminate\Support\Facades\DB; 24 use Illuminate\Support\Facades\DB;
24 use Illuminate\Support\Facades\Log; 25 use Illuminate\Support\Facades\Log;
25 use Illuminate\Support\Facades\Schema; 26 use Illuminate\Support\Facades\Schema;
@@ -43,7 +44,6 @@ class CopyProject extends Command @@ -43,7 +44,6 @@ class CopyProject extends Command
43 public function handle() 44 public function handle()
44 { 45 {
45 while (true) { 46 while (true) {
46 - $projectModel = new Project();  
47 $list = NoticeLog::where('type', NoticeLog::TYPE_COPY_PROJECT)->where('status', NoticeLog::STATUS_PENDING)->get(); 47 $list = NoticeLog::where('type', NoticeLog::TYPE_COPY_PROJECT)->where('status', NoticeLog::STATUS_PENDING)->get();
48 if(empty($list)){ 48 if(empty($list)){
49 sleep(30); 49 sleep(30);
@@ -68,14 +68,12 @@ class CopyProject extends Command @@ -68,14 +68,12 @@ class CopyProject extends Command
68 $item->status = NoticeLog::STATUS_FAIL; 68 $item->status = NoticeLog::STATUS_FAIL;
69 $item->save(); 69 $item->save();
70 } 70 }
71 - sleep(180); 71 + sleep(60);
72 try { 72 try {
73 $this->copyMysql($old_project_id,$project_id); 73 $this->copyMysql($old_project_id,$project_id);
74 }catch (\Exception $e){ 74 }catch (\Exception $e){
75 echo '复制数据库失败:'.$old_project_id . '<->'.$project_id; 75 echo '复制数据库失败:'.$old_project_id . '<->'.$project_id;
76 } 76 }
77 - //修改项目状态  
78 - $projectModel->edit(['delete_status'=>0],['id'=>$project_id]);  
79 $this->output('CopyProjectJob end, old project_id: ' . $old_project_id . ', new project_id: ' . $project_id); 77 $this->output('CopyProjectJob end, old project_id: ' . $old_project_id . ', new project_id: ' . $project_id);
80 } 78 }
81 } 79 }
@@ -92,6 +90,7 @@ class CopyProject extends Command @@ -92,6 +90,7 @@ class CopyProject extends Command
92 $data['finish_remain_day'] = 0; 90 $data['finish_remain_day'] = 0;
93 $data['title'] = $data['title'].'-copy'; 91 $data['title'] = $data['title'].'-copy';
94 $data['delete_status'] = 1; 92 $data['delete_status'] = 1;
  93 + $data['is_ai_blog'] = 0;
95 unset($data['id'],$data['exclusive_aicc_day'],$data['aicc'],$data['robots'],$data['is_translate_tag'],$data['is_translate'],$data['is_minor_languages'],$data['uptime']); 94 unset($data['id'],$data['exclusive_aicc_day'],$data['aicc'],$data['robots'],$data['is_translate_tag'],$data['is_translate'],$data['is_minor_languages'],$data['uptime']);
96 $project_id = $projectModel->insertGetId($data); 95 $project_id = $projectModel->insertGetId($data);
97 $hashids = new Hashids($data['from_order_id'], 13, 'abcdefghjkmnpqrstuvwxyz1234567890'); 96 $hashids = new Hashids($data['from_order_id'], 13, 'abcdefghjkmnpqrstuvwxyz1234567890');
@@ -145,7 +144,7 @@ class CopyProject extends Command @@ -145,7 +144,7 @@ class CopyProject extends Command
145 $optimizeData = $optimizeModel::where('project_id', $old_project_id)->first(); 144 $optimizeData = $optimizeModel::where('project_id', $old_project_id)->first();
146 if(!empty($optimizeData)){ 145 if(!empty($optimizeData)){
147 $optimizeData = $optimizeData->getAttributes(); 146 $optimizeData = $optimizeData->getAttributes();
148 - unset($optimizeData['id'],$optimizeData['domain'],$optimizeData['backlink'],$optimizeData['ai_video']); 147 + unset($optimizeData['id'],$optimizeData['domain'],$optimizeData['backlink'],$optimizeData['ai_video'],$optimizeData['is_ai_blog_send']);
149 $optimizeData['project_id'] = $project_id; 148 $optimizeData['project_id'] = $project_id;
150 $optimizeData['api_no'] = 0; 149 $optimizeData['api_no'] = 0;
151 $optimizeModel->insert($optimizeData); 150 $optimizeModel->insert($optimizeData);
@@ -207,59 +206,13 @@ class CopyProject extends Command @@ -207,59 +206,13 @@ class CopyProject extends Command
207 } 206 }
208 //复制数据库 207 //复制数据库
209 public function copyMysql($project_id,$new_project_id){ 208 public function copyMysql($project_id,$new_project_id){
210 - //切换数据库配置  
211 - $project = ProjectServer::useProject($new_project_id);  
212 - //创建数据库  
213 - ProjectServer::createDatabase($project);  
214 - //创建表  
215 - $this->initTable($project_id,$new_project_id); 209 + Artisan::call("php artisan copy_project_s $project_id $new_project_id");
  210 + //修改项目状态
  211 + $projectModel = new Project();
  212 + $projectModel->edit(['delete_status'=>0],['id'=>$new_project_id]);
216 } 213 }
217 214
218 /** 215 /**
219 - * @remark :创建数据库  
220 - * @name :initTable  
221 - * @author :lyh  
222 - * @method :post  
223 - * @time :2023/12/11 10:09  
224 - */  
225 - public function initTable($project_id, $news_project_id)  
226 - {  
227 - // 设置源数据库  
228 - config(['database.connections.custom_tmp_mysql_copy.database' => 'gl_data_' . $project_id]);  
229 - $database_name = DB::connection('custom_tmp_mysql_copy')->getDatabaseName();  
230 - // 获取源数据库的所有表  
231 - $tables = Schema::connection('custom_tmp_mysql_copy')->getAllTables();  
232 - $tables = array_column($tables, 'Tables_in_' . $database_name);  
233 - foreach ($tables as $table) {  
234 - // 1. 删除目标数据库中的表  
235 - DB::connection('custom_mysql')->statement("DROP TABLE IF EXISTS {$table}");  
236 - // 2. 重新创建表  
237 - $sql = DB::connection('custom_tmp_mysql_copy')->select("SHOW CREATE TABLE {$table}");  
238 - DB::connection('custom_mysql')->statement(get_object_vars($sql[0])['Create Table']);  
239 - // 3. 跳过指定的表  
240 - if (in_array($table, ['gl_customer_visit', 'gl_customer_visit_item', 'gl_inquiry_other', 'gl_inquiry_form_data', 'gl_inquiry_form'])) {  
241 - continue;  
242 - }  
243 - try {  
244 - // 4. 重新插入数据  
245 - DB::connection('custom_mysql')->table($table)->insertUsing(  
246 - [], // 插入所有列  
247 - function ($query) use ($table, $project_id) {  
248 - $name = 'gl_data_' . $project_id . '.' . $table;  
249 - $query->select('*')->from("{$name}");  
250 - }  
251 - );  
252 - }catch (\Exception $e){  
253 - continue;  
254 - }  
255 - // 5. 更新 project_id(如果存在)  
256 - if (Schema::connection('custom_mysql')->hasColumn($table, 'project_id')) {  
257 - DB::connection('custom_mysql')->table($table)->update(['project_id' => $news_project_id]);  
258 - }  
259 - }  
260 - return true;  
261 - }  
262 - /**  
263 * @param $message 216 * @param $message
264 * @return bool 217 * @return bool
265 */ 218 */
@@ -199,8 +199,10 @@ class SyncProject extends Command @@ -199,8 +199,10 @@ class SyncProject extends Command
199 * @author :lyh 199 * @author :lyh
200 * @method :post 200 * @method :post
201 * @time :2023/8/9 15:04 201 * @time :2023/8/9 15:04
  202 + * @param :version:7->v7版本(升级项目默认为v7)
202 */ 203 */
203 public function sync($param,$is_update = 0){ 204 public function sync($param,$is_update = 0){
  205 + $version = (($is_update == 1) ? Project::VERSION_SEVEN : ($param['version'] ?? Project::VERSION_ZERO));
204 $title = date('Ymd') . '-' . $param['company_name']; 206 $title = date('Ymd') . '-' . $param['company_name'];
205 $data = [ 207 $data = [
206 'project'=>[ 208 'project'=>[
@@ -222,6 +224,7 @@ class SyncProject extends Command @@ -222,6 +224,7 @@ class SyncProject extends Command
222 'notice_order_id' => $param['id'], 224 'notice_order_id' => $param['id'],
223 'type' => $is_update, 225 'type' => $is_update,
224 'is_upgrade'=>$is_update, 226 'is_upgrade'=>$is_update,
  227 + 'version'=>$version
225 ], 228 ],
226 'deploy_build' => [ 229 'deploy_build' => [
227 'login_mobile'=>$param['principal_mobile'] 230 'login_mobile'=>$param['principal_mobile']
@@ -245,11 +248,11 @@ class SyncProject extends Command @@ -245,11 +248,11 @@ class SyncProject extends Command
245 } 248 }
246 DB::beginTransaction(); 249 DB::beginTransaction();
247 try { 250 try {
248 - if(isset($data['deploy_build']['plan']) && ($data['deploy_build']['plan'] == 15)){ 251 + if(isset($data['deploy_build']['seo_plan']) && ($data['deploy_build']['seo_plan'] == 1)){
249 $data['project']['project_type'] = 1;//白帽版本 252 $data['project']['project_type'] = 1;//白帽版本
250 } 253 }
251 $id = $this->saveProject($data['project']); 254 $id = $this->saveProject($data['project']);
252 - $this->setPostId($data['deploy_build']['plan'],$id); 255 + $this->setPostId($data['deploy_build']['plan'] ?? 1,$id);
253 $this->savePayment($data['payment'],$id); 256 $this->savePayment($data['payment'],$id);
254 $this->saveDeployBuild($data['deploy_build'],$id); 257 $this->saveDeployBuild($data['deploy_build'],$id);
255 $this->saveDeployOptimize($data['deploy_optimize'],$id); 258 $this->saveDeployOptimize($data['deploy_optimize'],$id);
@@ -4,6 +4,7 @@ namespace App\Console\Commands\Sync; @@ -4,6 +4,7 @@ namespace App\Console\Commands\Sync;
4 4
5 5
6 use App\Exceptions\InquiryFilterException; 6 use App\Exceptions\InquiryFilterException;
  7 +use App\Models\Inquiry\InquiryRelateDomain;
7 use App\Models\Project\Project; 8 use App\Models\Project\Project;
8 use App\Models\SyncSubmitTask\SyncSubmitTask as SyncSubmitTaskModel; 9 use App\Models\SyncSubmitTask\SyncSubmitTask as SyncSubmitTaskModel;
9 use App\Services\SyncSubmitTaskService; 10 use App\Services\SyncSubmitTaskService;
@@ -53,10 +54,18 @@ class SyncSubmitTask extends Command @@ -53,10 +54,18 @@ class SyncSubmitTask extends Command
53 try { 54 try {
54 $project = Project::getProjectByDomain($task_info['data']['domain'] ?? ''); 55 $project = Project::getProjectByDomain($task_info['data']['domain'] ?? '');
55 if(!$project){ 56 if(!$project){
56 - throw new \Exception('项目不存在'); 57 + //是否有关联的域名
  58 + $relate_domain = InquiryRelateDomain::getRelateDomain($task_info['data']['domain'] ?? '');
  59 + if(!$relate_domain){
  60 + throw new \Exception('项目不存在1');
  61 + }
  62 + $project = Project::getProjectByDomain($relate_domain);
  63 + if(!$project){
  64 + throw new \Exception('项目不存在2');
  65 + }
57 } 66 }
58 $task_info->project_id = $project->id; 67 $task_info->project_id = $project->id;
59 - SyncSubmitTaskService::handler($task_info); 68 + SyncSubmitTaskService::handler($task_info, '', $relate_domain??'');
60 $task_info->status = 1; 69 $task_info->status = 1;
61 $task_info->save(); 70 $task_info->save();
62 71
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\Tdk;
  4 +
  5 +
  6 +use App\Http\Controllers\Bside\News\NewsController;
  7 +use App\Models\News\News;
  8 +use App\Models\News\NewsCategory;
  9 +use App\Models\Project\Project;
  10 +use App\Models\Project\ProjectUpdateTdk;
  11 +use App\Services\ProjectServer;
  12 +use Illuminate\Console\Command;
  13 +use Illuminate\Support\Facades\DB;
  14 +
  15 +/**
  16 + * 重跑异常tdk
  17 + * Class RerunSeoTdk
  18 + * @package App\Console\Commands\Tdk
  19 + * @author zbj
  20 + * @date 2025/4/12
  21 + */
  22 +class RerunSeoTdk extends Command
  23 +{
  24 + /**
  25 + * The name and signature of the console command.
  26 + *
  27 + * @var string
  28 + */
  29 + protected $signature = 'rerun_seo_tdk';
  30 +
  31 + /**
  32 + * The console command description.
  33 + *
  34 + * @var string
  35 + */
  36 + protected $description = '重跑项目sdk';
  37 +
  38 + /**
  39 + * Create a new command instance.
  40 + *
  41 + * @return void
  42 + */
  43 + public function __construct()
  44 + {
  45 + parent::__construct();
  46 + }
  47 +
  48 + /**
  49 + * @return bool
  50 + */
  51 + public function handle()
  52 + {
  53 + $project_ids = Project::where('type', Project::TYPE_TWO)->pluck('id')->toArray();
  54 + foreach ($project_ids as $project_id){
  55 + try {
  56 + ProjectServer::useProject($project_id);
  57 + $this->judgeAnomalies($project_id);
  58 + DB::disconnect('custom_mysql');
  59 + }catch (\Exception $e){
  60 + dump($e->getMessage());
  61 + }
  62 + }
  63 + }
  64 +
  65 + /**
  66 + * 判断异常
  67 + * @author zbj
  68 + * @date 2025/4/12
  69 + */
  70 + public function judgeAnomalies($project_id){
  71 + //获取当前项目的所有分类
  72 + $categories = NewsCategory::pluck('name', 'id')->toArray();
  73 + //新闻 seo_keyword 和 分类名一样的
  74 + $news_ids = [];
  75 + foreach ($categories as $category){
  76 + $ids = News::WhereRaw("FIND_IN_SET('{$category}', `seo_keywords`)")->pluck('id')->toArray();
  77 + $news_ids = array_unique(array_merge($news_ids, $ids));
  78 + }
  79 +
  80 + $count = count($news_ids);
  81 + if($count){
  82 + echo "项目{$project_id},共{$count}条需要重跑";
  83 + News::whereIn('id', $news_ids)->update(['seo_keywords' => '']);
  84 + ProjectUpdateTdk::add_task($project_id);
  85 + }
  86 + }
  87 +}
@@ -385,7 +385,7 @@ class UpdateSeoTdk extends Command @@ -385,7 +385,7 @@ class UpdateSeoTdk extends Command
385 //in,for,with,to,near,from 这些介词 只拼前缀,不拼后缀 385 //in,for,with,to,near,from 这些介词 只拼前缀,不拼后缀
386 $suffix_ban = ['in ', 'for ', 'with ', 'to ', 'near ','from ', 'In ', 'For ', 'With ', 'To ', 'Near ','From ']; 386 $suffix_ban = ['in ', 'for ', 'with ', 'to ', 'near ','from ', 'In ', 'For ', 'With ', 'To ', 'Near ','From '];
387 $suffix = ''; 387 $suffix = '';
388 - if(Str::contains($title, $suffix_ban)){ 388 + if(!Str::contains($title, $suffix_ban)){
389 // 某些后缀不能并存的情况 389 // 某些后缀不能并存的情况
390 $ban_suffix = []; 390 $ban_suffix = [];
391 //services/service 结尾的词,后缀不拼manufacturer,factory 391 //services/service 结尾的词,后缀不拼manufacturer,factory
@@ -1206,6 +1206,9 @@ function paginateArray($array, $page = 1, $pageSize = 20) { @@ -1206,6 +1206,9 @@ function paginateArray($array, $page = 1, $pageSize = 20) {
1206 * @time :2025/4/3 16:19 1206 * @time :2025/4/3 16:19
1207 */ 1207 */
1208 function getDomain($url) { 1208 function getDomain($url) {
  1209 + if(empty($url)){
  1210 + return $url;
  1211 + }
1209 $parsedUrl = parse_url($url); 1212 $parsedUrl = parse_url($url);
1210 return $parsedUrl['host'] ?? $url; // 如果解析失败,返回原始 URL 1213 return $parsedUrl['host'] ?? $url; // 如果解析失败,返回原始 URL
1211 } 1214 }
@@ -21,6 +21,8 @@ use Illuminate\Support\Facades\Cache; @@ -21,6 +21,8 @@ use Illuminate\Support\Facades\Cache;
21 class BaseController extends Controller 21 class BaseController extends Controller
22 { 22 {
23 public $param; 23 public $param;
  24 + public $request;
  25 +
24 public function __construct(Request $request) 26 public function __construct(Request $request)
25 { 27 {
26 $this->request = $request; 28 $this->request = $request;
@@ -12,6 +12,7 @@ use App\Http\Logic\Bside\User\UserLoginLogic; @@ -12,6 +12,7 @@ use App\Http\Logic\Bside\User\UserLoginLogic;
12 use App\Models\Ai\AiBlog; 12 use App\Models\Ai\AiBlog;
13 use App\Models\Blog\Blog; 13 use App\Models\Blog\Blog;
14 use App\Models\Domain\DomainInfo; 14 use App\Models\Domain\DomainInfo;
  15 +use App\Models\Inquiry\InquiryRelateDomain;
15 use App\Models\News\News; 16 use App\Models\News\News;
16 use App\Models\Product\Category; 17 use App\Models\Product\Category;
17 use App\Models\Product\CategoryRelated; 18 use App\Models\Product\CategoryRelated;
@@ -463,4 +464,31 @@ class PrivateController extends BaseController @@ -463,4 +464,31 @@ class PrivateController extends BaseController
463 $result = json_decode($json, true) ?: []; 464 $result = json_decode($json, true) ?: [];
464 return $this->success($result); 465 return $this->success($result);
465 } 466 }
  467 +
  468 + public function inquiry_relate_domain(Request $request){
  469 + $this->request->validate([
  470 + 'from_domain' => 'required',
  471 + 'to_domain' => 'required',
  472 + ]);
  473 + $from_domain = trim($this->param['from_domain']);
  474 + $to_domain = trim($this->param['to_domain']);
  475 +
  476 + $from_domain = parse_url($from_domain, PHP_URL_HOST) ?: $from_domain;
  477 + $to_domain = parse_url($to_domain, PHP_URL_HOST) ?: $to_domain;
  478 +
  479 + $project = Project::getProjectByDomain($to_domain);
  480 + if (empty($project)) {
  481 + return $this->error('未找到被关联域名对应的项目!');
  482 + }
  483 +
  484 + $relate = InquiryRelateDomain::where('from_domain', $from_domain)->first();
  485 + if(!$relate){
  486 + $relate = new InquiryRelateDomain();
  487 + }
  488 + $relate->from_domain = $from_domain;
  489 + $relate->to_domain = $to_domain;
  490 + $relate->save();
  491 +
  492 + return $this->success($relate);
  493 + }
466 } 494 }
@@ -43,6 +43,8 @@ class DomainInfoController extends BaseController @@ -43,6 +43,8 @@ class DomainInfoController extends BaseController
43 $lists['list'][$k]['company'] = $company; 43 $lists['list'][$k]['company'] = $company;
44 } 44 }
45 } 45 }
  46 + $lists['y_status'] = $domainModel->counts(['status'=>1]);
  47 + $lists['n_status'] = $domainModel->counts(['status'=>0]);
46 return $this->response('success', Code::SUCCESS, $lists); 48 return $this->response('success', Code::SUCCESS, $lists);
47 } 49 }
48 50
@@ -32,7 +32,7 @@ class InquiryForwardController extends BaseController @@ -32,7 +32,7 @@ class InquiryForwardController extends BaseController
32 $this->map['message'] = ['like', '%' . $this->map['message'] . '%']; 32 $this->map['message'] = ['like', '%' . $this->map['message'] . '%'];
33 } 33 }
34 if (isset($this->param['start_date']) && isset($this->param['end_date'])) { 34 if (isset($this->param['start_date']) && isset($this->param['end_date'])) {
35 - $this->map['inquiry_date'] = ['between', [$this->map['start_date'] . ' 00:00:00', $this->map['end_date'] . ' 23:59:59']]; 35 + $this->map['inquiry_date'] = ['between', [$this->map['start_date'] . ' 00:00:00', $this->map['end_date'] . ' 00:00:00']];
36 unset($this->map['start_date']); 36 unset($this->map['start_date']);
37 unset($this->map['end_date']); 37 unset($this->map['end_date']);
38 } elseif (isset($this->param['start_date'])) { 38 } elseif (isset($this->param['start_date'])) {
@@ -39,7 +39,7 @@ class GoogleKeywordInsightController extends BaseController @@ -39,7 +39,7 @@ class GoogleKeywordInsightController extends BaseController
39 ]); 39 ]);
40 $logic->getGoogleInsight(); 40 $logic->getGoogleInsight();
41 $detailModel = new GoogleKeywordInsightDetail(); 41 $detailModel = new GoogleKeywordInsightDetail();
42 - $data = $detailModel->lists(['search'=>$this->param['keyword']],$this->page,$this->row); 42 + $data = $detailModel->lists(['search'=>$this->param['keyword']],$this->page,$this->row,'id',['*'],'asc');
43 $this->response('success',Code::SUCCESS,$data); 43 $this->response('success',Code::SUCCESS,$data);
44 } 44 }
45 45
@@ -26,19 +26,18 @@ class GoogleLinkController extends BaseController @@ -26,19 +26,18 @@ class GoogleLinkController extends BaseController
26 public function getLink(){ 26 public function getLink(){
27 $linkModel = new GoogleLink(); 27 $linkModel = new GoogleLink();
28 $this->map['project_id'] = $this->user['project_id']; 28 $this->map['project_id'] = $this->user['project_id'];
29 - $lists = $linkModel->lists($this->map,$this->page,$this->row,'id',['url','moz_da','status','google_search','date','project_id','domain']); 29 + $this->map['status'] = 1;
  30 + $this->map['date'] = ['>=', date('Y-m-d 00:00:00', strtotime('-7 days'))];
  31 + $lists = $linkModel->lists($this->map,$this->page,$this->row,'id',['url','moz_da','status','url_domain','google_search','date','project_id','domain']);
30 if(empty($lists['list'])){ 32 if(empty($lists['list'])){
31 $linkService = new GoogleLinkService(); 33 $linkService = new GoogleLinkService();
32 $data = $linkService->linkPageData($this->user['domain'],$this->user['project_id']); 34 $data = $linkService->linkPageData($this->user['domain'],$this->user['project_id']);
33 if(is_array($data)){ 35 if(is_array($data)){
34 $lists = paginateArray($data,$this->page,$this->row); 36 $lists = paginateArray($data,$this->page,$this->row);
35 }else{ 37 }else{
36 - @file_put_contents(storage_path('logs/lyh_error.log'), var_export($data, true) . PHP_EOL, FILE_APPEND);  
37 - $this->response('success',Code::SUCCESS,[]); 38 + $this->response('success');
38 } 39 }
39 } 40 }
40 - $lists['y_total'] = $linkModel->counts(['status'=>1,'project_id'=>$this->user['project_id']]);  
41 - $lists['n_total'] = $linkModel->counts(['status'=>0,'project_id'=>$this->user['project_id']]);  
42 $this->response('success',Code::SUCCESS,$lists); 41 $this->response('success',Code::SUCCESS,$lists);
43 } 42 }
44 43
@@ -37,7 +37,7 @@ class GoogleSearchController extends BaseController @@ -37,7 +37,7 @@ class GoogleSearchController extends BaseController
37 //查询详情数据 37 //查询详情数据
38 $searchDetailModel = new GoogleSearchDetail(); 38 $searchDetailModel = new GoogleSearchDetail();
39 $this->map['project_id'] = $this->user['project_id']; 39 $this->map['project_id'] = $this->user['project_id'];
40 - $data = $searchDetailModel->lists($this->map,$this->page,$this->row,'clicks',['keys','click_rate','impressions_rate']); 40 + $data = $searchDetailModel->lists($this->map,$this->page,$this->row,'impressions',['keys','click_rate','impressions_rate']);
41 if(!empty($data)){ 41 if(!empty($data)){
42 if($this->param['type'] == 'country'){ 42 if($this->param['type'] == 'country'){
43 $codeCountryModel = new GoogleCodeCountry(); 43 $codeCountryModel = new GoogleCodeCountry();
@@ -554,6 +554,8 @@ class ProductController extends BaseController @@ -554,6 +554,8 @@ class ProductController extends BaseController
554 } 554 }
555 if(!empty($v['og_image'])){ 555 if(!empty($v['og_image'])){
556 $v['og_image'] = getImageUrl($v['og_image'] ?? '',$this->user['storage_type'],$this->user['project_location']); 556 $v['og_image'] = getImageUrl($v['og_image'] ?? '',$this->user['storage_type'],$this->user['project_location']);
  557 + }else{
  558 + $v['og_image'] = $v['thumb']['url'] ?? '';
557 } 559 }
558 if(!empty($v['icon'])){ 560 if(!empty($v['icon'])){
559 foreach ($v['icon'] as $icon_k => $icon_v){ 561 foreach ($v['icon'] as $icon_k => $icon_v){
@@ -87,7 +87,7 @@ class DomainInfoLogic extends BaseLogic @@ -87,7 +87,7 @@ class DomainInfoLogic extends BaseLogic
87 //查看当前域名是否有项目在使用 87 //查看当前域名是否有项目在使用
88 if($this->param['status'] != $this->model::STATUS_ONE){ 88 if($this->param['status'] != $this->model::STATUS_ONE){
89 $info = $this->model->read(['id'=>$this->param['id']]); 89 $info = $this->model->read(['id'=>$this->param['id']]);
90 - if($info === false){ 90 + if($info['project_id'] != 0){
91 $this->fail('当前域名有项目正在使用中'); 91 $this->fail('当前域名有项目正在使用中');
92 } 92 }
93 } 93 }
@@ -533,7 +533,7 @@ class ProjectLogic extends BaseLogic @@ -533,7 +533,7 @@ class ProjectLogic extends BaseLogic
533 //单独保存行业信息 533 //单独保存行业信息
534 ProjectIndustryRelated::saveRelated($deploy_optimize['project_id'],$deploy_optimize['industry'] ?? []); 534 ProjectIndustryRelated::saveRelated($deploy_optimize['project_id'],$deploy_optimize['industry'] ?? []);
535 $deployOptimizeModel = new DeployOptimize(); 535 $deployOptimizeModel = new DeployOptimize();
536 - if(isset($deploy_optimize['domain']) && !empty($deploy_optimize['domain'])){ 536 + if(isset($deploy_optimize['domain'])){
537 //更改域名 537 //更改域名
538 $this->editDomainStatus($deploy_optimize['domain'],$deploy_optimize['project_id']); 538 $this->editDomainStatus($deploy_optimize['domain'],$deploy_optimize['project_id']);
539 } 539 }
@@ -576,6 +576,7 @@ class ProjectLogic extends BaseLogic @@ -576,6 +576,7 @@ class ProjectLogic extends BaseLogic
576 'main_keyword'=>$project_keyword['main_keyword'] ?? '', 576 'main_keyword'=>$project_keyword['main_keyword'] ?? '',
577 'customer_keywords'=>$project_keyword['customer_keywords'] ?? '', 577 'customer_keywords'=>$project_keyword['customer_keywords'] ?? '',
578 'search_keywords'=>$project_keyword['search_keywords'] ?? '', 578 'search_keywords'=>$project_keyword['search_keywords'] ?? '',
  579 + 'seo_keywords'=>$project_keyword['seo_keywords'] ?? '',
579 ]; 580 ];
580 if(isset($project_keyword['operator_log']) && !empty($project_keyword['operator_log'])){ 581 if(isset($project_keyword['operator_log']) && !empty($project_keyword['operator_log'])){
581 $data['operator_log'] = json_encode($project_keyword['operator_log'] ?? []); 582 $data['operator_log'] = json_encode($project_keyword['operator_log'] ?? []);
@@ -914,15 +915,11 @@ class ProjectLogic extends BaseLogic @@ -914,15 +915,11 @@ class ProjectLogic extends BaseLogic
914 } 915 }
915 $domainModel = new DomainInfo(); 916 $domainModel = new DomainInfo();
916 //查看当前域名是否已使用 917 //查看当前域名是否已使用
917 - $domainInfo = $domainModel->read(['id'=>$domain,'project_id'=>['!=',0]]); 918 + $domainInfo = $domainModel->read(['id'=>$domain,'status'=>1,'project_id'=>['!=',0]]);
918 if($domainInfo !== false){ 919 if($domainInfo !== false){
919 $this->fail('当前域名已被其他服务器使用'); 920 $this->fail('当前域名已被其他服务器使用');
920 } 921 }
921 - //先清空上一次所绑定的域名  
922 - $info = $domainModel->read(['project_id'=>$project_id]);  
923 - if($info !== false){  
924 - $domainModel->edit(['project_id'=>0,'status'=>DomainInfo::STATUS_ZERO],['id'=>$info['id']]);  
925 - } 922 + $domainModel->edit(['project_id'=>0,'status'=>DomainInfo::STATUS_ZERO],['project_id'=>$project_id]);
926 //重新设置域名 923 //重新设置域名
927 $domainModel->edit(['status'=>DomainInfo::STATUS_ONE,'project_id'=>$project_id],['id'=>$domain]); 924 $domainModel->edit(['status'=>DomainInfo::STATUS_ONE,'project_id'=>$project_id],['id'=>$domain]);
928 return $this->success(); 925 return $this->success();
@@ -958,10 +955,15 @@ class ProjectLogic extends BaseLogic @@ -958,10 +955,15 @@ class ProjectLogic extends BaseLogic
958 $noticeModel = new NoticeLog(); 955 $noticeModel = new NoticeLog();
959 $info = $noticeModel->read(['type'=>NoticeLog::TYPE_COPY_PROJECT,'status'=>0,'data'=>['like','%"'.$this->param['project_id'].'"%']]); 956 $info = $noticeModel->read(['type'=>NoticeLog::TYPE_COPY_PROJECT,'status'=>0,'data'=>['like','%"'.$this->param['project_id'].'"%']]);
960 if($info !== false){ 957 if($info !== false){
961 - return $this->success('当前项目已在复制中'); 958 + return $this->success(['message'=>'当前项目已在复制中']);
  959 + }
  960 + $projectModel = new Project();
  961 + $projectInfo = $projectModel->read(['type'=>0,'old_project_id'=>$this->param['project_id']]);
  962 + if($projectInfo !== false){
  963 + return $this->success(['message'=>'当前项目已复制过']);
962 } 964 }
963 NoticeLog::createLog(NoticeLog::TYPE_COPY_PROJECT, ['project_id' => $this->param['project_id']]); 965 NoticeLog::createLog(NoticeLog::TYPE_COPY_PROJECT, ['project_id' => $this->param['project_id']]);
964 - return $this->success('项目复制中,请稍后前往初始化项目查看;'); 966 + return $this->success(['message'=>'项目复制中,请稍后前往初始化项目查看;']);
965 } 967 }
966 968
967 /** 969 /**
@@ -138,7 +138,6 @@ class CustomTemplateLogic extends BaseLogic @@ -138,7 +138,6 @@ class CustomTemplateLogic extends BaseLogic
138 $condition['source'] = $this->getType(BTemplate::COMMON_FOOTER); 138 $condition['source'] = $this->getType(BTemplate::COMMON_FOOTER);
139 $footerComInfo = $bTemplateComModel->read($condition); 139 $footerComInfo = $bTemplateComModel->read($condition);
140 if($footerComInfo === false){ 140 if($footerComInfo === false){
141 - $template_id = $this->getTemplateId();  
142 //取默认首页的 141 //取默认首页的
143 $condition['source'] = BTemplate::SOURCE_COM; 142 $condition['source'] = BTemplate::SOURCE_COM;
144 $footerComInfo = $bTemplateComModel->read($condition); 143 $footerComInfo = $bTemplateComModel->read($condition);
@@ -357,8 +357,10 @@ class ProductLogic extends BaseLogic @@ -357,8 +357,10 @@ class ProductLogic extends BaseLogic
357 $param['thumb'] = Arr::a2s([]); 357 $param['thumb'] = Arr::a2s([]);
358 $param['gallery'] = Arr::a2s([]); 358 $param['gallery'] = Arr::a2s([]);
359 } 359 }
360 - if(isset($param['og_image'])){ 360 + if(isset($param['og_image']) && !empty($param['og_image'])){
361 $param['og_image'] = str_replace_url($param['og_image'] ?? ''); 361 $param['og_image'] = str_replace_url($param['og_image'] ?? '');
  362 + }else{
  363 + $param['og_image'] = $param['thumb']['url'] ?? '';
362 } 364 }
363 if(isset($param['files'])){ 365 if(isset($param['files'])){
364 $param['files']['url'] = str_replace_url($param['files']['url'] ?? ''); 366 $param['files']['url'] = str_replace_url($param['files']['url'] ?? '');
@@ -493,7 +493,7 @@ class RankDataLogic extends BaseLogic @@ -493,7 +493,7 @@ class RankDataLogic extends BaseLogic
493 $without_extension_project_ids = [658]; //是否达标只统计主词的 493 $without_extension_project_ids = [658]; //是否达标只统计主词的
494 $extension_project_ids = [354]; //扩展词也到达标的 494 $extension_project_ids = [354]; //扩展词也到达标的
495 $compliance_project_ids = [2163,257,823]; //直接达标处理的 495 $compliance_project_ids = [2163,257,823]; //直接达标处理的
496 - $ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066];//暂停的项目 496 + $ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250];//暂停的项目
497 $uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目 497 $uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目
498 //一个项目多个api_no 498 //一个项目多个api_no
499 $multiple_api_no_project_ids = [ 499 $multiple_api_no_project_ids = [
1 <?php 1 <?php
2 /** 2 /**
3 * @remark : 3 * @remark :
4 - * @name :AfterCount.php 4 + * @name :AfterDayCount.php
5 * @author :lyh 5 * @author :lyh
6 * @method :post 6 * @method :post
7 * @time :2025/3/26 15:31 7 * @time :2025/3/26 15:31
  1 +<?php
  2 +
  3 +namespace App\Models\Inquiry;
  4 +
  5 +
  6 +use App\Helper\Arr;
  7 +use App\Models\Base;
  8 +use App\Utils\HttpUtils;
  9 +use GuzzleHttp\Exception\GuzzleException;
  10 +use Illuminate\Support\Facades\Cache;
  11 +use Illuminate\Support\Facades\Http;
  12 +
  13 +/**
  14 + * Class InquiryRelateDomain
  15 + * @package App\Models\Inquiry
  16 + * @author zbj
  17 + * @date 2025/4/12
  18 + */
  19 +class InquiryRelateDomain extends Base
  20 +{
  21 +
  22 + //设置关联表名
  23 + protected $table = 'gl_inquiry_relate_domain';
  24 +
  25 + /**
  26 + * 获取关联域名
  27 + * @throws \Exception
  28 + * @author zbj
  29 + * @date 2025/4/12
  30 + */
  31 + public static function getRelateDomain($domain){
  32 + $list_cache_key = 'RelateDomainList';
  33 + $data = Cache::get($list_cache_key);
  34 + if(!$data){
  35 + $data = [];
  36 + $page = 1;
  37 + while (true) {
  38 + try {
  39 + $res = HttpUtils::get('https://www.cmer.site/api/globalso_site', ['pagesite' => 100, 'page' => $page]);
  40 + if($res) {
  41 + $res = Arr::s2a($res);
  42 + $arr = [];
  43 + foreach ($res['data']['data'] as $item){
  44 + $arr[$item['domain']] = $item['globalso_domain'];
  45 + }
  46 + $data = array_merge($data, $arr);
  47 + if ($res['data']['last_page'] == $page) {
  48 + break;
  49 + }
  50 + }
  51 + $page++;
  52 + } catch (\Exception | GuzzleException $e) {
  53 + throw new \Exception('关联域名接口错误' . $e->getMessage());
  54 + }
  55 + }
  56 + Cache::put($list_cache_key, $data, 3600);
  57 + }
  58 + return $data[$domain]??'';
  59 + }
  60 +}
@@ -21,6 +21,8 @@ class Keyword extends Base @@ -21,6 +21,8 @@ class Keyword extends Base
21 //连接数据库 21 //连接数据库
22 protected $connection = 'custom_mysql'; 22 protected $connection = 'custom_mysql';
23 23
  24 + const TYPE_ORDER_KEYWORD = 1;//关键词标识,预约关键词标识
  25 +
24 const STATUS_ACTIVE = 1; 26 const STATUS_ACTIVE = 1;
25 //获取字母对应数字 27 //获取字母对应数字
26 public $firstNumWord = [ 28 public $firstNumWord = [
@@ -110,7 +112,7 @@ class Keyword extends Base @@ -110,7 +112,7 @@ class Keyword extends Base
110 public static function extendKeyword($project_id) 112 public static function extendKeyword($project_id)
111 { 113 {
112 $result = []; 114 $result = [];
113 - $keywords = self::where(['project_id' => $project_id])->pluck('seo_title', 'title')->toArray(); 115 + $keywords = self::where(['project_id' => $project_id])->where('type',self::TYPE_ORDER_KEYWORD)->pluck('seo_title', 'title')->toArray();
114 if (empty($keywords)) 116 if (empty($keywords))
115 return $result; 117 return $result;
116 // $item:前缀 + 关键词 + 后缀 118 // $item:前缀 + 关键词 + 后缀
@@ -149,16 +151,17 @@ class Keyword extends Base @@ -149,16 +151,17 @@ class Keyword extends Base
149 * @method :post 151 * @method :post
150 * @time :2025/3/25 16:28 152 * @time :2025/3/25 16:28
151 */ 153 */
152 - public function saveBKeyword($project_id,$keywords){ 154 + public function saveBKeyword($project_id,$keywords,$type = 0){
153 foreach ($keywords as $v){ 155 foreach ($keywords as $v){
154 if(empty($v)){ 156 if(empty($v)){
155 continue; 157 continue;
156 } 158 }
157 - $info = $this->read(['title'=>$v],['id']);  
158 - if($info === false){ 159 + $info = $this->read(['title'=>trim($v)],['id']);
  160 + if($info == false){
159 $param['project_id'] = $project_id; 161 $param['project_id'] = $project_id;
160 $param['title'] = $v; 162 $param['title'] = $v;
161 $param['first_word'] = $this->first_word($param['title']); 163 $param['first_word'] = $this->first_word($param['title']);
  164 + $param['type'] = $type;
162 $this->addReturnId($param); 165 $this->addReturnId($param);
163 } 166 }
164 } 167 }
@@ -38,6 +38,12 @@ class Project extends Base @@ -38,6 +38,12 @@ class Project extends Base
38 const IS_DEL_TRUE = 1; 38 const IS_DEL_TRUE = 1;
39 39
40 const PROJECT_TYPE_SEO = 1;//白帽seo项目 40 const PROJECT_TYPE_SEO = 1;//白帽seo项目
  41 +
  42 +
  43 + //版本信息
  44 + const VERSION_ZERO = 0;//普通版本
  45 + const VERSION_SIX = 6;//6.0版本
  46 + const VERSION_SEVEN = 7;//7.0版本
41 /** 47 /**
42 * 星级客户 48 * 星级客户
43 * @return string[] 49 * @return string[]
@@ -77,6 +83,7 @@ class Project extends Base @@ -77,6 +83,7 @@ class Project extends Base
77 return $arr; 83 return $arr;
78 } 84 }
79 85
  86 +
80 /** 87 /**
81 * 项目类型 88 * 项目类型
82 * @return string[] 89 * @return string[]
@@ -88,8 +88,10 @@ class GoogleLinkService @@ -88,8 +88,10 @@ class GoogleLinkService
88 public function saveLink($data,$project_id,$domain){ 88 public function saveLink($data,$project_id,$domain){
89 $saveData = []; 89 $saveData = [];
90 foreach ($data as $val){ 90 foreach ($data as $val){
91 - $timestamp = strtotime($val['created_at']);  
92 - $date = date('Y-m-d H:i:s', $timestamp ?? time()); 91 + $date = date('Y-m-d 00:00:00', time());
  92 + if($val['status'] != 1){
  93 + continue;
  94 + }
93 $saveData[] = [ 95 $saveData[] = [
94 'url'=>$val['url'], 96 'url'=>$val['url'],
95 'moz_da'=>$val['mozDA'], 97 'moz_da'=>$val['mozDA'],
@@ -97,11 +99,15 @@ class GoogleLinkService @@ -97,11 +99,15 @@ class GoogleLinkService
97 'google_search'=>$val['googlesearch'], 99 'google_search'=>$val['googlesearch'],
98 'date'=>$date, 100 'date'=>$date,
99 'project_id'=>$project_id, 101 'project_id'=>$project_id,
100 - 'domain'=>$domain 102 + 'domain'=>$domain,
  103 + 'url_domain'=>getDomain($val['url'] ?? '')
101 ]; 104 ];
102 } 105 }
103 $linkModel = new GoogleLink(); 106 $linkModel = new GoogleLink();
104 - $linkModel->insertAll($saveData); 107 + if(!empty($saveData)){
  108 + $linkModel->del(['project_id'=>$project_id]);
  109 + $linkModel->insertAll($saveData);
  110 + }
105 return $saveData; 111 return $saveData;
106 } 112 }
107 } 113 }
@@ -42,9 +42,24 @@ class SyncSubmitTaskService @@ -42,9 +42,24 @@ class SyncSubmitTaskService
42 * @author zbj 42 * @author zbj
43 * @date 2023/11/28 43 * @date 2023/11/28
44 */ 44 */
45 - public static function handler($task, $date = '') 45 + public static function handler($task, $date = '', $relate_domain = '')
46 { 46 {
47 $data = $task['data']; 47 $data = $task['data'];
  48 +
  49 + //有关联域名 替换原数据url
  50 + if($relate_domain){
  51 + $domain = $data['domain'];
  52 + foreach ($data as $k=>&$item){
  53 + if($k == 'data'){
  54 + foreach ($item as &$v){
  55 + $v = str_replace($domain, $relate_domain, $v);
  56 + }
  57 + }else{
  58 + $item = str_replace($domain, $relate_domain, $item);
  59 + }
  60 + }
  61 + }
  62 +
48 $checkIpCountry = self::checkIpCountry($data['domain'], $data['ip'], $task['type']); 63 $checkIpCountry = self::checkIpCountry($data['domain'], $data['ip'], $task['type']);
49 64
50 $data['ip'] = $checkIpCountry['ip']; 65 $data['ip'] = $checkIpCountry['ip'];
@@ -68,4 +68,7 @@ Route::post('selfSiteVerify', [\App\Http\Controllers\Api\SelfSiteController::cla @@ -68,4 +68,7 @@ Route::post('selfSiteVerify', [\App\Http\Controllers\Api\SelfSiteController::cla
68 //创建301跳转任务 68 //创建301跳转任务
69 Route::any('/addRedirect',[\App\Http\Controllers\Api\NoticeController::class,'addRedirect']); 69 Route::any('/addRedirect',[\App\Http\Controllers\Api\NoticeController::class,'addRedirect']);
70 70
  71 +//关联域名
  72 +Route::post('/inquiry_relate_domain', [\App\Http\Controllers\Api\PrivateController::class, 'inquiry_relate_domain']);
  73 +
71 74