作者 刘锟

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

@@ -63,6 +63,10 @@ class AiBlogAutoPublish extends Command @@ -63,6 +63,10 @@ class AiBlogAutoPublish extends Command
63 63
64 foreach ($projects as $project) { 64 foreach ($projects as $project) {
65 $this->output("项目{$project->id}开始自动发布"); 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 + }
66 if(($project->deploy_optimize['start_date'] > date('Y-m-d')) || !$project->deploy_optimize['start_date']){ 70 if(($project->deploy_optimize['start_date'] > date('Y-m-d')) || !$project->deploy_optimize['start_date']){
67 $this->output("项目{$project->id}未到推广时间" . $project->deploy_optimize['start_date']); 71 $this->output("项目{$project->id}未到推广时间" . $project->deploy_optimize['start_date']);
68 continue; 72 continue;
@@ -159,6 +163,11 @@ class AiBlogAutoPublish extends Command @@ -159,6 +163,11 @@ class AiBlogAutoPublish extends Command
159 if (!AiBlogOpenLog::isOpened($project->id)) { 163 if (!AiBlogOpenLog::isOpened($project->id)) {
160 //开启 164 //开启
161 $project->is_ai_blog = 1; 165 $project->is_ai_blog = 1;
  166 +
  167 + //开启自动发布
  168 + $project->deploy_optimize->is_ai_blog_send = 1;
  169 + $project->deploy_optimize->save();
  170 +
162 $project->save(); 171 $project->save();
163 //创建AI博客项目 172 //创建AI博客项目
164 $deploy_optimize = $project->deploy_optimize; 173 $deploy_optimize = $project->deploy_optimize;
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GoogleSearchKeyword.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/3/31 11:29
  8 + */
  9 +
  10 +namespace App\Console\Commands\GoogleSearch;
  11 +
  12 +use App\Models\Com\NoticeLog;
  13 +use App\Models\Domain\DomainInfo;
  14 +use App\Models\GoogleSearch\GoogleSearch;
  15 +use App\Models\GoogleSearch\GoogleSearchDetail;
  16 +use App\Models\Project\Project;
  17 +use App\Services\GoogleSearchService;
  18 +use App\Services\ProjectServer;
  19 +use Illuminate\Console\Command;
  20 +use Illuminate\Support\Facades\DB;
  21 +
  22 +/**
  23 + * @remark :客户搜索词
  24 + * @name :GoogleSearchKeyword
  25 + * @author :lyh
  26 + * @method :post
  27 + * @time :2025/3/31 11:29
  28 + */
  29 +class GoogleSearchKeyword extends Command
  30 +{
  31 + /**
  32 + * The name and signature of the console command.
  33 + *
  34 + * @var string
  35 + */
  36 + protected $signature = 'search_keyword';
  37 +
  38 + /**
  39 + * The console command description.
  40 + *
  41 + * @var string
  42 + */
  43 + protected $description = 'google搜索词';
  44 +
  45 + public $googleService;
  46 + public $searchModel;
  47 + public $detailModel;
  48 +
  49 + public function __construct()
  50 + {
  51 + $this->googleService = new GoogleSearchService();
  52 + $this->searchModel = new GoogleSearch();
  53 + $this->detailModel = new GoogleSearchDetail();
  54 + parent::__construct();
  55 + }
  56 +
  57 + /**
  58 + * @remark :拉取google搜索数据
  59 + * @name :handle
  60 + * @author :lyh
  61 + * @method :post
  62 + * @time :2025/3/31 11:37
  63 + */
  64 + public function handle(){
  65 + $projectModel = new Project();
  66 + $lists = $projectModel->list(['delete_status' => 0,'type'=>['!=',$projectModel::TYPE_ONE]], 'id', ['id']);
  67 + $domainModel = new DomainInfo();
  68 + foreach ($lists as $val) {
  69 + echo date('Y-m-d H:i:s') . '开始--项目的id:'. $val['id'] . PHP_EOL;
  70 + $domainInfo = $domainModel->read(['project_id'=>$val['id']]);
  71 + if($domainInfo === false){
  72 + echo '域名不存在。'.PHP_EOL;
  73 + continue;
  74 + }
  75 + $typeData = [1=>'date', 2=>'query', 3=>'page', 4=>'device', 5=>'country'];
  76 + foreach ($typeData as $keyT => $valT){
  77 + $this->_action($domainInfo['domain'],$valT,$val['id']);
  78 + }
  79 + }
  80 + return true;
  81 + }
  82 +
  83 + /**
  84 + * @remark :执行的方法
  85 + * @name :_action
  86 + * @author :lyh
  87 + * @method :post
  88 + * @time :2025/3/31 11:30
  89 + */
  90 + public function _action($domain,$type,$project_id){
  91 + $data = $this->googleService->googleSearch($domain,$type);
  92 + if(empty($data)){
  93 + echo '域名:'.$domain.'拉取数据为空.'.PHP_EOL;
  94 + return false;
  95 + }
  96 + //保存一条主记录诗句
  97 + $this->searchModel->addReturnId(['date'=>date('Y-m-d'),'project_id'=>$project_id,'type'=>$type]);
  98 + $saveData = [];
  99 + $clicksNum = array_sum(array_column($data, 'clicks'));
  100 + $impressionsNum = array_sum(array_column($data, 'impressions'));
  101 + echo 'clicksNum:'.$clicksNum.PHP_EOL;
  102 + echo 'impressionsNum:'.$impressionsNum.PHP_EOL;
  103 + foreach ($data as $val){
  104 + $saveData[] = [
  105 + 'date'=>date('Y-m-d'),
  106 + 'project_id'=>$project_id,
  107 + 'type'=>$type,
  108 + 'keys'=>$val['keys'][0],
  109 + 'clicks'=>$val['clicks'],
  110 + 'click_rate'=>number_format($val['clicks'] / (($clicksNum == 0) ? 1 : $clicksNum), 2),
  111 + 'impressions'=>$val['impressions'],
  112 + 'impressions_rate'=>number_format($val['impressions'] / (($impressionsNum == 0) ? 1 : $impressionsNum), 2),
  113 + 'ctr'=>$val['ctr'],
  114 + 'position'=>$val['position'],
  115 + ];
  116 + }
  117 + if(!empty($saveData)){
  118 + DB::beginTransaction();
  119 + try {
  120 + //清空以前的数据
  121 + $this->detailModel->del(['project_id'=>$project_id,'type'=>$type]);
  122 + $this->detailModel->insertAll($saveData);
  123 + DB::commit();
  124 + }catch (\Exception $e){
  125 + DB::rollBack();
  126 + echo '重新添加数据失败:project_id'.$project_id.PHP_EOL;
  127 + }
  128 + }
  129 + return true;
  130 + }
  131 +}
@@ -369,8 +369,8 @@ class UpdateSeoTdk extends Command @@ -369,8 +369,8 @@ class UpdateSeoTdk extends Command
369 } else if ($table == 'gl_product_keyword' && $field == 'seo_title') { 369 } else if ($table == 'gl_product_keyword' && $field == 'seo_title') {
370 # TODO 聚合页seo title 特殊处理 前缀_1 . 关键词 . 后缀_2 370 # TODO 聚合页seo title 特殊处理 前缀_1 . 关键词 . 后缀_2
371 $seo_title = $v[$this->topic_fields[$table]];; 371 $seo_title = $v[$this->topic_fields[$table]];;
372 - //只有推广项目才加 前后缀  
373 - if($project->type == Project::TYPE_TWO) { 372 + //只有推广项目 且未标记特殊前后缀 才加 前后缀
  373 + if($project->type == Project::TYPE_TWO && !in_array(8, explode(',', $project->deploy_optimize->special))) {
374 $prefix = $this->getPrefixKeyword($project_id, 'prefix', 1); 374 $prefix = $this->getPrefixKeyword($project_id, 'prefix', 1);
375 $suffix = $this->getPrefixKeyword($project_id, 'suffix', 2); 375 $suffix = $this->getPrefixKeyword($project_id, 'suffix', 2);
376 if (empty($prefix) || empty($suffix)) { 376 if (empty($prefix) || empty($suffix)) {
@@ -521,11 +521,14 @@ class UpdateSeoTdk extends Command @@ -521,11 +521,14 @@ class UpdateSeoTdk extends Command
521 } 521 }
522 $prompt = str_replace('{company detail}', $company_detail, $prompt); 522 $prompt = str_replace('{company detail}', $company_detail, $prompt);
523 } 523 }
  524 +
  525 + $project = Project::find($project_id);
  526 + if (!in_array(8, explode(',', $project->deploy_optimize->special))) {
524 // 前缀关键词 527 // 前缀关键词
525 - if(preg_match_all("/\{qz_(\d+)\}/", $prompt, $matches)) {  
526 - foreach ($matches[0] as $key=>$val) { 528 + if (preg_match_all("/\{qz_(\d+)\}/", $prompt, $matches)) {
  529 + foreach ($matches[0] as $key => $val) {
527 $keyword = $this->getPrefixKeyword($project_id, 'prefix', $matches[1][$key]); 530 $keyword = $this->getPrefixKeyword($project_id, 'prefix', $matches[1][$key]);
528 - if(!$keyword){ 531 + if (!$keyword) {
529 echo getmypid() . ' ' . '前缀关键词为空 跳过' . PHP_EOL; 532 echo getmypid() . ' ' . '前缀关键词为空 跳过' . PHP_EOL;
530 return false; 533 return false;
531 } 534 }
@@ -533,16 +536,17 @@ class UpdateSeoTdk extends Command @@ -533,16 +536,17 @@ class UpdateSeoTdk extends Command
533 } 536 }
534 } 537 }
535 // 后缀关键词 538 // 后缀关键词
536 - if(preg_match_all("/\{hz_(\d+)\}/", $prompt, $matches)) {  
537 - foreach ($matches[0] as $key=>$val) { 539 + if (preg_match_all("/\{hz_(\d+)\}/", $prompt, $matches)) {
  540 + foreach ($matches[0] as $key => $val) {
538 $keyword = $this->getPrefixKeyword($project_id, 'suffix', $matches[1][$key]); 541 $keyword = $this->getPrefixKeyword($project_id, 'suffix', $matches[1][$key]);
539 - if(!$keyword){ 542 + if (!$keyword) {
540 echo getmypid() . ' ' . '前缀关键词为空 跳过' . PHP_EOL; 543 echo getmypid() . ' ' . '前缀关键词为空 跳过' . PHP_EOL;
541 return false; 544 return false;
542 } 545 }
543 $prompt = str_replace($val, $keyword, $prompt); 546 $prompt = str_replace($val, $keyword, $prompt);
544 } 547 }
545 } 548 }
  549 + }
546 550
547 // 多个核心关键词 551 // 多个核心关键词
548 if(strpos($prompt, '{core keywords 8}') !== false) { 552 if(strpos($prompt, '{core keywords 8}') !== false) {
@@ -39,7 +39,6 @@ class Kernel extends ConsoleKernel @@ -39,7 +39,6 @@ class Kernel extends ConsoleKernel
39 $schedule->command('sync_ad_cost')->everyThirtyMinutes()->withoutOverlapping(1); 39 $schedule->command('sync_ad_cost')->everyThirtyMinutes()->withoutOverlapping(1);
40 // 优化预设关键词 同步 20点会开始TDK生成 40 // 优化预设关键词 同步 20点会开始TDK生成
41 $schedule->command('optimize_set_keyword_sync')->dailyAt('20:00')->withoutOverlapping(1); 41 $schedule->command('optimize_set_keyword_sync')->dailyAt('20:00')->withoutOverlapping(1);
42 - $schedule->command('after_count')->dailyAt('01:00')->withoutOverlapping(1); //售后日统计 每天统计一次  
43 } 42 }
44 43
45 /** 44 /**
@@ -492,6 +492,13 @@ class OptimizeController extends BaseController @@ -492,6 +492,13 @@ class OptimizeController extends BaseController
492 $this->processChunkedList($productCategoryModel, ['status' => $productCategoryModel::STATUS_ACTIVE], ['id', 'title', 'route'], $domain, $data, 'product_category'); 492 $this->processChunkedList($productCategoryModel, ['status' => $productCategoryModel::STATUS_ACTIVE], ['id', 'title', 'route'], $domain, $data, 'product_category');
493 $productKeywordModel = new Keyword(); 493 $productKeywordModel = new Keyword();
494 $this->processChunkedList($productKeywordModel, ['status' => $productKeywordModel::STATUS_ACTIVE], ['id', 'title', 'route'], $domain, $data, 'product_keyword'); 494 $this->processChunkedList($productKeywordModel, ['status' => $productKeywordModel::STATUS_ACTIVE], ['id', 'title', 'route'], $domain, $data, 'product_keyword');
  495 + $aiBlogModel = new AiBlog();
  496 + $list = $aiBlogModel->list(['route'=>['!=',null]],'id',['route','new_title']);
  497 + if(!empty($list)){
  498 + foreach ($list as $v){
  499 + $data['ai_blog'][] = $domain . 'blog/' . $v['route'] . '/{' . $v['new_title'] . '}';
  500 + }
  501 + }
495 DB::disconnect('custom_mysql'); 502 DB::disconnect('custom_mysql');
496 $this->response('success', Code::SUCCESS, $data); 503 $this->response('success', Code::SUCCESS, $data);
497 } 504 }
@@ -555,20 +562,23 @@ class OptimizeController extends BaseController @@ -555,20 +562,23 @@ class OptimizeController extends BaseController
555 ], [ 562 ], [
556 'project_id.required' => '项目id不能为空', 563 'project_id.required' => '项目id不能为空',
557 ]); 564 ]);
  565 + $domainModel = new DomainInfo();
  566 + $domainInfo = $domainModel->read(['project_id'=>$this->param['project_id']],['domain']);
  567 + if($domainInfo === false){
  568 + $this->response('success');
  569 + }
558 ProjectServer::useProject($this->param['project_id']); 570 ProjectServer::useProject($this->param['project_id']);
559 $aiBlogModel = new AiBlog(); 571 $aiBlogModel = new AiBlog();
560 - $list = $aiBlogModel->formatQuery(['route'=>['!=',null]])->pluck('route')->toArray(); 572 + $list = $aiBlogModel->list(['route'=>['!=',null]],'id',['route','new_title']);
  573 + $resultData = [];
561 if(!empty($list)){ 574 if(!empty($list)){
562 - $domainModel = new DomainInfo();  
563 - $DomainInfo = $domainModel->read(['project_id'=>$this->param['project_id']]);  
564 $DomainInfo['domain'] = $DomainInfo['domain'] ?? ''; 575 $DomainInfo['domain'] = $DomainInfo['domain'] ?? '';
565 - foreach ($list as $k => $v){  
566 - $v = ('https://'.$DomainInfo['domain'].'/') . 'blog/' . $v;  
567 - $list[$k] = $v; 576 + foreach ($list as $v){
  577 + $resultData[] = ('https://'.$DomainInfo['domain'].'/') . 'blog/' . $v['route'] . '/{' . $v['new_title'] . '}';
568 } 578 }
569 } 579 }
570 DB::disconnect('custom_mysql'); 580 DB::disconnect('custom_mysql');
571 - $this->response('success',Code::SUCCESS,$list); 581 + $this->response('success',Code::SUCCESS,$resultData);
572 } 582 }
573 583
574 /** 584 /**
@@ -117,6 +117,7 @@ class AdsController extends BaseController @@ -117,6 +117,7 @@ class AdsController extends BaseController
117 $ad_url = trim($request->input('ad_url')); 117 $ad_url = trim($request->input('ad_url'));
118 $ad_img = trim($request->input('ad_img')); 118 $ad_img = trim($request->input('ad_img'));
119 $num = intval($request->input('num')); 119 $num = intval($request->input('num'));
  120 + $is_show_fb_source = intval($request->input('is_show_fb_source'));
120 $status = intval($request->input('status')); 121 $status = intval($request->input('status'));
121 $is_replace_text = intval($request->input('is_replace_text')); 122 $is_replace_text = intval($request->input('is_replace_text'));
122 $ai_param = $request->input('ai_param'); 123 $ai_param = $request->input('ai_param');
@@ -138,7 +139,19 @@ class AdsController extends BaseController @@ -138,7 +139,19 @@ class AdsController extends BaseController
138 return $this->response('英文缩写参考不能为空!', Code::USER_ERROR, []); 139 return $this->response('英文缩写参考不能为空!', Code::USER_ERROR, []);
139 } 140 }
140 } 141 }
141 - ReInquiryTask::createTask($id, $title, $industry, $ad_id, $ad_url, $ad_img, $num, $status, $is_replace_text, $ai_param); 142 + $task = ReInquiryTask::createTask($id, $title, $industry, $ad_id, $ad_url, $ad_img, $num, $status, $is_replace_text, $ai_param, $is_show_fb_source);
  143 +
  144 + //是否显示FB标识
  145 + foreach ($task['target'] as $target){
  146 + if($target['is_v6']){
  147 + $project = Project::getProjectByDomain($target['url']);
  148 + if($project){
  149 + $project->is_show_fb_source = $is_show_fb_source;
  150 + $project->save();
  151 + }
  152 + }
  153 + }
  154 +
142 return $this->response('success', Code::SUCCESS, []); 155 return $this->response('success', Code::SUCCESS, []);
143 } 156 }
144 157
@@ -183,6 +196,15 @@ class AdsController extends BaseController @@ -183,6 +196,15 @@ class AdsController extends BaseController
183 } 196 }
184 foreach ($target as $v){ 197 foreach ($target as $v){
185 ReInquiryCount::addInquiryNum($id, $v['url'], 0); 198 ReInquiryCount::addInquiryNum($id, $v['url'], 0);
  199 +
  200 + //是否显示FB标识
  201 + if($v['is_v6']){
  202 + $project = Project::getProjectByDomain($v['url']);
  203 + if($project){
  204 + $project->is_show_fb_source = $task->is_show_fb_source;
  205 + $project->save();
  206 + }
  207 + }
186 } 208 }
187 209
188 //商城 210 //商城
@@ -209,6 +231,7 @@ class AdsController extends BaseController @@ -209,6 +231,7 @@ class AdsController extends BaseController
209 $task->shop_site = json_encode($shop_site); 231 $task->shop_site = json_encode($shop_site);
210 $task->fob_pro = json_encode($fob_pro); 232 $task->fob_pro = json_encode($fob_pro);
211 $task->save(); 233 $task->save();
  234 +
212 return $this->response('success', Code::SUCCESS, []); 235 return $this->response('success', Code::SUCCESS, []);
213 } 236 }
214 237
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GoogleKeywordInsightController.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/3/25 14:23
  8 + */
  9 +
  10 +namespace App\Http\Controllers\Bside\GoogleKeyword;
  11 +
  12 +use App\Enums\Common\Code;
  13 +use App\Http\Controllers\Bside\BaseController;
  14 +use App\Http\Logic\Bside\GoogleKeywordInsight\GoogleKeywordInsightLogic;
  15 +use App\Models\GoogleKeywordInsight\GoogleKeywordInsightDetail;
  16 +use App\Models\Project\ProjectKeyword;
  17 +
  18 +/**
  19 + * @remark :谷歌洞察数据
  20 + * @name :GoogleKeywordInsightController
  21 + * @author :lyh
  22 + * @method :post
  23 + * @time :2025/3/25 14:24
  24 + */
  25 +class GoogleKeywordInsightController extends BaseController
  26 +{
  27 + /**
  28 + * @remark :保存数据
  29 + * @name :saveKeywordInsight
  30 + * @author :lyh
  31 + * @method :post
  32 + * @time :2025/3/25 14:30
  33 + */
  34 + public function getKeywordInsight(GoogleKeywordInsightLogic $logic){
  35 + $this->request->validate([
  36 + 'keyword' => 'required'
  37 + ],[
  38 + 'keyword.required' => '关键词不能为空',
  39 + ]);
  40 + $logic->getGoogleInsight();
  41 + $detailModel = new GoogleKeywordInsightDetail();
  42 + $data = $detailModel->lists(['search'=>$this->param['keyword']],$this->page,$this->row);
  43 + $this->response('success',Code::SUCCESS,$data);
  44 + }
  45 +
  46 + /**
  47 + * @remark :获取优化关键词列表
  48 + * @name :getOptimizeList
  49 + * @author :lyh
  50 + * @method :post
  51 + * @time :2025/4/1 9:12
  52 + */
  53 + public function getOptimizeList(){
  54 + $projectKeywordModel = new ProjectKeyword();
  55 + $info = $projectKeywordModel->read(['project_id'=>$this->user['project_id']],['main_keyword','customer_keywords']);
  56 + if($info === false){
  57 + $this->response('success');
  58 + }
  59 + $main_keyword = explode("\r\n", $info['main_keyword']);
  60 + $customer_keywords = explode("\r\n", $info['customer_keywords']);
  61 + $array = array_merge($main_keyword, $customer_keywords);
  62 + $detailModel = new GoogleKeywordInsightDetail();
  63 + $resultData = [];
  64 + if(!empty($array)){
  65 + $resultData = $this->paginateArray($array,$this->page,$this->row);
  66 + $detailList = $detailModel->list(['search'=>['in',$resultData['list']]]);
  67 + foreach ($resultData['list'] as $key => $item){
  68 + $result['keyword'] = $item;
  69 + $searchKeyword = $this->getSearchDetail($item,$detailList);
  70 + if($searchKeyword === false){
  71 + $result['data'] = [];
  72 + }else{
  73 + $result['data'] = $searchKeyword;
  74 + }
  75 + $resultData['list'][$key] = $result;
  76 + }
  77 +
  78 + }
  79 + $this->response('success',Code::SUCCESS,$resultData);
  80 + }
  81 +
  82 + /**
  83 + * @remark :保存一条关键字数据
  84 + * @name :getKeywordInsightDetail
  85 + * @author :lyh
  86 + * @method :post
  87 + * @time :2025/4/1 11:23
  88 + */
  89 + public function getKeywordInsightDetail(GoogleKeywordInsightLogic $logic){
  90 + $this->request->validate([
  91 + 'keyword' => 'required'
  92 + ],[
  93 + 'keyword.required' => '关键词不能为空',
  94 + ]);
  95 + $result = $logic->getGoogleInsightDetail();
  96 + $detailModel = new GoogleKeywordInsightDetail();
  97 + $data = $detailModel->read(['id'=>$result['id']]);
  98 + $this->response('success',Code::SUCCESS,$data);
  99 + }
  100 +
  101 + /**
  102 + * @remark :查看当前数据是否存在数组中
  103 + * @name :getSearchDetail
  104 + * @author :lyh
  105 + * @method :post
  106 + * @time :2025/4/1 9:56
  107 + */
  108 + public function getSearchDetail($keyword,$detailList){
  109 + if(!empty($detailList)){
  110 + foreach ($detailList as $value){
  111 + if($keyword == $value['search']){
  112 + return $value;
  113 + }
  114 + }
  115 + }
  116 + return [];
  117 + }
  118 +
  119 + /**
  120 + * @remark :返回分页数据
  121 + * @name :paginateArray
  122 + * @author :lyh
  123 + * @method :post
  124 + * @time :2025/4/1 9:41
  125 + */
  126 + public function paginateArray($array, $page = 1, $pageSize = 20) {
  127 + $totalItems = count($array);
  128 + $totalPages = ceil($totalItems / $pageSize);
  129 + // 确保页码有效
  130 + $page = max(1, min($page, $totalPages));
  131 + $offset = ($page - 1) * $pageSize;
  132 + $data = array_slice($array, $offset, $pageSize);
  133 + return [
  134 + 'list' => $data,
  135 + 'page' => $page,
  136 + 'size' => $pageSize,
  137 + 'total_page' => $totalPages,
  138 + 'total' => $totalItems,
  139 + ];
  140 + }
  141 +}
@@ -7,10 +7,13 @@ @@ -7,10 +7,13 @@
7 * @time :2025/3/27 13:53 7 * @time :2025/3/27 13:53
8 */ 8 */
9 9
10 -namespace App\Http\Controllers\Bside\GoogleKeywordInsight; 10 +namespace App\Http\Controllers\Bside\GoogleKeyword;
11 11
12 use App\Enums\Common\Code; 12 use App\Enums\Common\Code;
13 use App\Http\Controllers\Bside\BaseController; 13 use App\Http\Controllers\Bside\BaseController;
  14 +use App\Models\Com\NoticeLog;
  15 +use App\Models\GoogleSearch\GoogleSearch;
  16 +use App\Models\GoogleSearch\GoogleSearchDetail;
14 use App\Services\GoogleSearchService; 17 use App\Services\GoogleSearchService;
15 18
16 class GoogleSearchController extends BaseController 19 class GoogleSearchController extends BaseController
@@ -24,14 +27,14 @@ class GoogleSearchController extends BaseController @@ -24,14 +27,14 @@ class GoogleSearchController extends BaseController
24 */ 27 */
25 public function getSearchList(){ 28 public function getSearchList(){
26 $this->request->validate([ 29 $this->request->validate([
27 - 'search' => 'required' 30 + 'type' => 'required'
28 ],[ 31 ],[
29 - 'search.required' => '搜索类型不能为空', 32 + 'type.required' => '搜索类型不能为空',
30 ]); 33 ]);
31 - //获取当前项目域名  
32 - $domain = parse_url($this->user['domain'], PHP_URL_HOST);  
33 - $googleService = new GoogleSearchService();  
34 - $data = $googleService->googleSearch($domain,$this->param['search']); 34 + //查询详情数据
  35 + $searchDetailModel = new GoogleSearchDetail();
  36 + $this->map['project_id']= $this->user['project_id'];
  37 + $data = $searchDetailModel->lists($this->map,$this->page,$this->row);
35 $this->response('success',Code::SUCCESS,$data); 38 $this->response('success',Code::SUCCESS,$data);
36 } 39 }
37 } 40 }
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :GoogleKeywordInsightController.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2025/3/25 14:23  
8 - */  
9 -  
10 -namespace App\Http\Controllers\Bside\GoogleKeywordInsight;  
11 -  
12 -use App\Enums\Common\Code;  
13 -use App\Http\Controllers\Bside\BaseController;  
14 -use App\Http\Logic\Bside\GoogleKeywordInsight\GoogleKeywordInsightLogic;  
15 -use App\Models\GoogleKeywordInsight\GoogleKeywordInsightDetail;  
16 -  
17 -/**  
18 - * @remark :谷歌洞察数据  
19 - * @name :GoogleKeywordInsightController  
20 - * @author :lyh  
21 - * @method :post  
22 - * @time :2025/3/25 14:24  
23 - */  
24 -class GoogleKeywordInsightController extends BaseController  
25 -{  
26 - /**  
27 - * @remark :保存数据  
28 - * @name :saveKeywordInsight  
29 - * @author :lyh  
30 - * @method :post  
31 - * @time :2025/3/25 14:30  
32 - */  
33 - public function getKeywordInsight(GoogleKeywordInsightLogic $logic){  
34 - $this->request->validate([  
35 - 'keyword' => 'required'  
36 - ],[  
37 - 'keyword.required' => '关键词不能为空',  
38 - ]);  
39 - $logic->getGoogleInsight();  
40 - $detailModel = new GoogleKeywordInsightDetail();  
41 - $data = $detailModel->lists(['search'=>$this->param['keyword']],$this->page,$this->row);  
42 - $this->response('success',Code::SUCCESS,$data);  
43 - }  
44 -}  
@@ -55,4 +55,29 @@ class GoogleKeywordInsightLogic extends BaseLogic @@ -55,4 +55,29 @@ class GoogleKeywordInsightLogic extends BaseLogic
55 } 55 }
56 return $this->success(); 56 return $this->success();
57 } 57 }
  58 +
  59 + /**
  60 + * @remark :保存一条数据
  61 + * @name :saveGoogleKeywordInsight
  62 + * @author :lyh
  63 + * @method :post
  64 + * @time :2025/3/25 14:36
  65 + */
  66 + public function getGoogleInsightDetail(){
  67 + $this->service = new GoogleSearchService();
  68 + $data = $this->service->requestUrl($this->param['keyword']);
  69 + if(!empty($data)){
  70 + DB::beginTransaction();
  71 + //保存数据库
  72 + try {
  73 + $detailModel = new GoogleKeywordInsightDetail();
  74 + $id = $detailModel->saveInsightDetailOne($this->user['project_id'],$this->param['keyword'],$data[0]);
  75 + DB::commit();
  76 + }catch (\Exception $e){
  77 + DB::rollBack();
  78 + $this->fail('保存失败,请联系管理员');
  79 + }
  80 + }
  81 + return $this->success(['id'=>$id ?? 0]);
  82 + }
58 } 83 }
@@ -56,6 +56,7 @@ class InquiryLogic extends BaseLogic @@ -56,6 +56,7 @@ class InquiryLogic extends BaseLogic
56 ]; 56 ];
57 if (!empty($list['status']) && $list['status'] == 200) { 57 if (!empty($list['status']) && $list['status'] == 200) {
58 foreach ($list['data']['data'] as $item) { 58 foreach ($list['data']['data'] as $item) {
  59 + $item['is_fb'] = $project['is_show_fb_source'] && $item['source'] == 5 ? 1 : 0;
59 $data['list'][] = $item; 60 $data['list'][] = $item;
60 } 61 }
61 $data['total'] = $list['data']['total']; 62 $data['total'] = $list['data']['total'];
@@ -20,6 +20,7 @@ class NoticeLog extends Base @@ -20,6 +20,7 @@ class NoticeLog extends Base
20 const DELETE_NEWS_CATEGORY = 'delete_news_category'; 20 const DELETE_NEWS_CATEGORY = 'delete_news_category';
21 const DELETE_CUSTOM_CATEGORY = 'delete_custom_category'; 21 const DELETE_CUSTOM_CATEGORY = 'delete_custom_category';
22 const GENERATE_PAGE = 'generate_page';//生成页面单独改为守护进程 22 const GENERATE_PAGE = 'generate_page';//生成页面单独改为守护进程
  23 + const GOOGLE_SEARCH = 'google_search';//google搜索任务date
23 const STATUS_PENDING = 0; 24 const STATUS_PENDING = 0;
24 const STATUS_SUCCESS = 1; 25 const STATUS_SUCCESS = 1;
25 const STATUS_FAIL = 2; 26 const STATUS_FAIL = 2;
@@ -43,4 +43,28 @@ class GoogleKeywordInsightDetail extends Base @@ -43,4 +43,28 @@ class GoogleKeywordInsightDetail extends Base
43 } 43 }
44 return $this->insertAll($saveData); 44 return $this->insertAll($saveData);
45 } 45 }
  46 +
  47 + /**
  48 + * @remark :保存一条数据
  49 + * @name :saveInsightDetailOne
  50 + * @author :lyh
  51 + * @method :post
  52 + * @time :2025/4/1 11:32
  53 + */
  54 + public function saveInsightDetailOne($project_id,$keyword,$data){
  55 + $transData = Translate::tran($data['text'], 'zh');
  56 + $saveData = [
  57 + 'search'=>$keyword,
  58 + 'text'=>$data['text'],
  59 + 'zh_text'=>$transData ?? $data['text'],
  60 + 'project_id'=>$project_id,
  61 + 'volume'=>$data['volume'],
  62 + 'competition_level'=>$data['competition_level'],
  63 + 'competition_index'=>$data['competition_index'],
  64 + 'low_bid'=>$data['low_bid'],
  65 + 'high_bid'=>$data['high_bid'],
  66 + 'trend'=>$data['trend'],
  67 + ];
  68 + return $this->addReturnId($saveData);
  69 + }
46 } 70 }
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GoogleSearch.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/3/31 13:36
  8 + */
  9 +
  10 +namespace App\Models\GoogleSearch;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +class GoogleSearch extends Base
  15 +{
  16 + protected $table = 'gl_google_search';
  17 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GoogleSearchDetail.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/3/31 13:40
  8 + */
  9 +
  10 +namespace App\Models\GoogleSearch;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +class GoogleSearchDetail extends Base
  15 +{
  16 + protected $table = 'gl_google_search_detail';
  17 +}
@@ -41,7 +41,7 @@ class ReInquiryTask extends Base @@ -41,7 +41,7 @@ class ReInquiryTask extends Base
41 * @param int $status 41 * @param int $status
42 * @return ReInquiryTask 42 * @return ReInquiryTask
43 */ 43 */
44 - public static function createTask($id, $title, $industry, $ad_id, $ad_url, $ad_img, $num, $status, $is_replace_text, $ai_param) 44 + public static function createTask($id, $title, $industry, $ad_id, $ad_url, $ad_img, $num, $status, $is_replace_text, $ai_param, $is_show_fb_source)
45 { 45 {
46 $self = self::where(['id' => $id])->first(); 46 $self = self::where(['id' => $id])->first();
47 if (empty($self)) 47 if (empty($self))
@@ -55,6 +55,7 @@ class ReInquiryTask extends Base @@ -55,6 +55,7 @@ class ReInquiryTask extends Base
55 $self->status = $status; 55 $self->status = $status;
56 $self->is_replace_text = $is_replace_text; 56 $self->is_replace_text = $is_replace_text;
57 $self->ai_param = $ai_param; 57 $self->ai_param = $ai_param;
  58 + $self->is_show_fb_source = $is_show_fb_source;
58 $self->save(); 59 $self->save();
59 return $self; 60 return $self;
60 } 61 }
@@ -74,7 +74,6 @@ class GoogleSearchService @@ -74,7 +74,6 @@ class GoogleSearchService
74 $err = curl_error($curl); 74 $err = curl_error($curl);
75 curl_close($curl); 75 curl_close($curl);
76 if ($err) { 76 if ($err) {
77 - errorLog("热门关键词cURL Error #:", $url, $err);  
78 return false; 77 return false;
79 } else { 78 } else {
80 return json_decode($response,true); 79 return json_decode($response,true);
@@ -90,24 +89,13 @@ class GoogleSearchService @@ -90,24 +89,13 @@ class GoogleSearchService
90 * @param :date,query,page,device,country/时间、聚合、前页、设备、国家 89 * @param :date,query,page,device,country/时间、聚合、前页、设备、国家
91 */ 90 */
92 public function googleSearch($domain,$search){ 91 public function googleSearch($domain,$search){
93 - $data = [  
94 - 1=>'date',  
95 - 2=>'query',  
96 - 3=>'page',  
97 - 4=>'device',  
98 - 5=>'country'  
99 - ];  
100 $this->url = 'https://www.cmer.site/api/google/search'; 92 $this->url = 'https://www.cmer.site/api/google/search';
101 - $url = $this->url.'?domain='.$domain.'&q='.$data[$search]; 93 + $url = $this->url.'?domain='.$domain.'&q='.$search;
102 $data = http_get($url); 94 $data = http_get($url);
103 - $data = $data['data'] ?? [];  
104 - if(!empty($data) && ($search == 5)){  
105 - foreach ($data as $key => $val){  
106 - $val['keys_country'] = Country::getCountryNameByAlpha3(strtoupper($val['keys'][0]));  
107 - $data[$key] = $val;  
108 - } 95 + if(!isset($data['status']) || $data['status'] != 200){
  96 + return [];
109 } 97 }
  98 + $data = $data['data'] ?? [];
110 return $data; 99 return $data;
111 } 100 }
112 -  
113 } 101 }
@@ -698,11 +698,14 @@ Route::middleware(['bloginauth'])->group(function () { @@ -698,11 +698,14 @@ Route::middleware(['bloginauth'])->group(function () {
698 698
699 //google数据洞察 699 //google数据洞察
700 Route::prefix('google_keyword_insight')->group(function () { 700 Route::prefix('google_keyword_insight')->group(function () {
701 - Route::any('/getKeywordInsight', [\App\Http\Controllers\Bside\GoogleKeywordInsight\GoogleKeywordInsightController::class, 'getKeywordInsight'])->name('google_keyword_insight_getKeywordInsight'); 701 + Route::any('/getKeywordInsight', [\App\Http\Controllers\Bside\GoogleKeyword\GoogleKeywordInsightController::class, 'getKeywordInsight'])->name('google_keyword_insight_getKeywordInsight');
  702 + Route::any('/getOptimizeList', [\App\Http\Controllers\Bside\GoogleKeyword\GoogleKeywordInsightController::class, 'getOptimizeList'])->name('google_keyword_insight_getOptimizeList');
  703 + Route::any('/getKeywordInsightDetail', [\App\Http\Controllers\Bside\GoogleKeyword\GoogleKeywordInsightController::class, 'getKeywordInsightDetail'])->name('google_keyword_insight_getKeywordInsightDetail');
  704 +
702 }); 705 });
703 //google搜索数据 706 //google搜索数据
704 Route::prefix('google_search')->group(function () { 707 Route::prefix('google_search')->group(function () {
705 - Route::any('/getSearchList', [\App\Http\Controllers\Bside\GoogleKeywordInsight\GoogleSearchController::class, 'getSearchList'])->name('google_search_getSearchList'); 708 + Route::any('/getSearchList', [\App\Http\Controllers\Bside\GoogleKeyword\GoogleSearchController::class, 'getSearchList'])->name('google_search_getSearchList');
706 }); 709 });
707 //企业产品库 710 //企业产品库
708 Route::prefix('enterprise_product')->group(function () { 711 Route::prefix('enterprise_product')->group(function () {