作者 刘锟

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

正在显示 45 个修改的文件 包含 1545 行增加139 行删除
@@ -113,7 +113,7 @@ class AiBlogAutoPublish extends Command @@ -113,7 +113,7 @@ class AiBlogAutoPublish extends Command
113 } 113 }
114 } 114 }
115 } else { 115 } else {
116 - if($frequency[0] == '1/2'){//一天2篇 116 + if(strpos($frequency[0],'/')){//一天2篇
117 $aiBlogTaskModel = new AiBlogTaskModel(); 117 $aiBlogTaskModel = new AiBlogTaskModel();
118 $frequency = explode('/', $frequency[0]); 118 $frequency = explode('/', $frequency[0]);
119 //查询当前已发布几篇 119 //查询当前已发布几篇
@@ -11,6 +11,7 @@ namespace App\Console\Commands\Geo; @@ -11,6 +11,7 @@ namespace App\Console\Commands\Geo;
11 11
12 use App\Models\Geo\GeoQuestionLog; 12 use App\Models\Geo\GeoQuestionLog;
13 use App\Models\Geo\GeoQuestionResult; 13 use App\Models\Geo\GeoQuestionResult;
  14 +use App\Models\Project\Project;
14 use Illuminate\Console\Command; 15 use Illuminate\Console\Command;
15 use Illuminate\Support\Carbon; 16 use Illuminate\Support\Carbon;
16 use App\Models\Geo\GeoCount as GeoCountModel; 17 use App\Models\Geo\GeoCount as GeoCountModel;
@@ -64,15 +65,23 @@ class GeoCount extends Command @@ -64,15 +65,23 @@ class GeoCount extends Command
64 $geoQuestionResModel = new GeoQuestionResult(); 65 $geoQuestionResModel = new GeoQuestionResult();
65 $platforms = ['gemini','openai','deepseek','poe','perplexity','google_ai_overview','openai-not-network','claude']; 66 $platforms = ['gemini','openai','deepseek','poe','perplexity','google_ai_overview','openai-not-network','claude'];
66 foreach ($project_id as $item){ 67 foreach ($project_id as $item){
  68 + $projectModel = new Project();
  69 + $geo_qualify_num = $projectModel->getValue(['id'=>$item],'geo_qualify_num');
67 $this->output('执行的项目ID----'.$item); 70 $this->output('执行的项目ID----'.$item);
68 //收录总数 71 //收录总数
69 $total = $geoQuestionResModel->counts(['project_id' => $item,'hit'=>['!=',0],'created_at' => ['between',[$start,$end]]]); 72 $total = $geoQuestionResModel->counts(['project_id' => $item,'hit'=>['!=',0],'created_at' => ['between',[$start,$end]]]);
  73 + $qualify_total = $geoQuestionResModel->counts(['platform'=>['in',['openai', 'gemini','google_ai_overview']],'project_id' => $item,'hit'=>['!=',0],'created_at' => ['between',[$start,$end]]]);
  74 + if($qualify_total > $geo_qualify_num){
  75 + $is_qualify = 1;
  76 + }
70 $data = [ 77 $data = [
71 'project_id' => $item, 78 'project_id' => $item,
72 'date' => $date, 79 'date' => $date,
73 'created_at' => Carbon::now()->format('Y-m-d H:i:s'), 80 'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
74 'updated_at' => Carbon::now()->format('Y-m-d H:i:s'), 81 'updated_at' => Carbon::now()->format('Y-m-d H:i:s'),
75 'total'=>$total,//收录总数 82 'total'=>$total,//收录总数
  83 + 'is_qualify'=>$is_qualify,
  84 + 'qualify_total'=>$qualify_total
76 ]; 85 ];
77 foreach ($platforms as $platform){ 86 foreach ($platforms as $platform){
78 if($platform == 'openai-not-network'){ 87 if($platform == 'openai-not-network'){
@@ -11,6 +11,7 @@ namespace App\Console\Commands\Geo; @@ -11,6 +11,7 @@ namespace App\Console\Commands\Geo;
11 11
12 use App\Models\Geo\GeoQuestionLog; 12 use App\Models\Geo\GeoQuestionLog;
13 use App\Models\Geo\GeoQuestionResult; 13 use App\Models\Geo\GeoQuestionResult;
  14 +use App\Models\Project\Project;
14 use Illuminate\Console\Command; 15 use Illuminate\Console\Command;
15 use Illuminate\Support\Carbon; 16 use Illuminate\Support\Carbon;
16 use App\Models\Geo\GeoCount as GeoCountModel; 17 use App\Models\Geo\GeoCount as GeoCountModel;
@@ -68,15 +69,23 @@ class GeoCountAll extends Command @@ -68,15 +69,23 @@ class GeoCountAll extends Command
68 $geoQuestionResModel = new GeoQuestionLog(); 69 $geoQuestionResModel = new GeoQuestionLog();
69 $platforms = ['gemini','openai','deepseek','poe','perplexity','google_ai_overview','openai-not-network','claude']; 70 $platforms = ['gemini','openai','deepseek','poe','perplexity','google_ai_overview','openai-not-network','claude'];
70 foreach ($project_id as $item){ 71 foreach ($project_id as $item){
  72 + $projectModel = new Project();
  73 + $geo_qualify_num = $projectModel->getValue(['id'=>$item],'geo_qualify_num');
71 $this->output('执行的项目ID----'.$item); 74 $this->output('执行的项目ID----'.$item);
72 //收录总数 75 //收录总数
73 $total = $geoQuestionResModel->counts(['project_id' => $item,'hit'=>['!=',0],'created_at' => ['between',[$start,$end]]]); 76 $total = $geoQuestionResModel->counts(['project_id' => $item,'hit'=>['!=',0],'created_at' => ['between',[$start,$end]]]);
  77 + $qualify_total = $geoQuestionResModel->counts(['platform'=>['in',['openai', 'gemini','google_ai_overview']],'project_id' => $item,'hit'=>['!=',0],'created_at' => ['between',[$start,$end]]]);
  78 + if($total > $geo_qualify_num){
  79 + $is_qualify = 1;
  80 + }
74 $data = [ 81 $data = [
75 'project_id' => $item, 82 'project_id' => $item,
76 'date' => $date, 83 'date' => $date,
77 'created_at' => Carbon::now()->format('Y-m-d H:i:s'), 84 'created_at' => Carbon::now()->format('Y-m-d H:i:s'),
78 'updated_at' => Carbon::now()->format('Y-m-d H:i:s'), 85 'updated_at' => Carbon::now()->format('Y-m-d H:i:s'),
79 'total'=>$total,//收录总数 86 'total'=>$total,//收录总数
  87 + 'is_qualify'=>$is_qualify,
  88 + 'qualify_total'=>$qualify_total
80 ]; 89 ];
81 foreach ($platforms as $platform){ 90 foreach ($platforms as $platform){
82 if($platform == 'openai-not-network'){ 91 if($platform == 'openai-not-network'){
@@ -340,12 +340,11 @@ class GeoQuestionRes extends Command @@ -340,12 +340,11 @@ class GeoQuestionRes extends Command
340 $task_id = Redis::rpop($key); 340 $task_id = Redis::rpop($key);
341 if(empty($task_id)){ 341 if(empty($task_id)){
342 //todo::这里需要执行统计一次,统计当前项目当前日期的统计 342 //todo::这里需要执行统计一次,统计当前项目当前日期的统计
343 -  
344 # TODO 按照项目进行获取, 一个项目当天需要将所有跑完 343 # TODO 按照项目进行获取, 一个项目当天需要将所有跑完
345 $project_id = GeoQuestion::where('status', GeoQuestion::STATUS_OPEN)->where('next_time', '<=', date('Y-m-d'))->value('project_id'); 344 $project_id = GeoQuestion::where('status', GeoQuestion::STATUS_OPEN)->where('next_time', '<=', date('Y-m-d'))->value('project_id');
346 if (!empty($project_id)){ 345 if (!empty($project_id)){
347 $this->project_id = $project_id; 346 $this->project_id = $project_id;
348 - $ids = GeoQuestion::where(['project_id' => $project_id, 'status' => GeoQuestion::STATUS_OPEN])->where('current_time', '<>', date('Y-m-d'))->pluck('id'); 347 + $ids = GeoQuestion::where(['project_id' => $project_id, 'status' => GeoQuestion::STATUS_OPEN])->where('next_time', '<=', date('Y-m-d'))->pluck('id');
349 foreach ($ids as $id) { 348 foreach ($ids as $id) {
350 Redis::lpush($key, $id); 349 Redis::lpush($key, $id);
351 } 350 }
@@ -9,10 +9,7 @@ @@ -9,10 +9,7 @@
9 9
10 namespace App\Console\Commands\LyhTest; 10 namespace App\Console\Commands\LyhTest;
11 11
12 -use App\Models\CustomModule\CustomModuleCategory;  
13 -use App\Models\CustomModule\CustomModuleContent;  
14 -use App\Models\CustomModule\CustomModuleExtentContent;  
15 -use App\Models\News\News; 12 +
16 use App\Models\Product\Category; 13 use App\Models\Product\Category;
17 use App\Models\Product\CategoryRelated; 14 use App\Models\Product\CategoryRelated;
18 use App\Models\Product\Column; 15 use App\Models\Product\Column;
@@ -25,6 +22,7 @@ use App\Models\Template\Template; @@ -25,6 +22,7 @@ use App\Models\Template\Template;
25 use App\Services\ProjectServer; 22 use App\Services\ProjectServer;
26 use Illuminate\Console\Command; 23 use Illuminate\Console\Command;
27 use Illuminate\Support\Facades\DB; 24 use Illuminate\Support\Facades\DB;
  25 +use PhpOffice\PhpSpreadsheet\IOFactory;
28 26
29 class LyhImportTest extends Command 27 class LyhImportTest extends Command
30 { 28 {
@@ -52,15 +50,92 @@ class LyhImportTest extends Command @@ -52,15 +50,92 @@ class LyhImportTest extends Command
52 */ 50 */
53 public function handle() 51 public function handle()
54 { 52 {
55 - ProjectServer::useProject(3531);  
56 - echo date('Y-m-d H:i:s') . 'start->3531' . PHP_EOL;  
57 -// $this->importProductCategory('https://ecdn6-nc.globalso.com/upload/p/3654/file/2025-06/products-1.csv',3654);  
58 - $this->import3531CustomModule(3531); 53 + ProjectServer::useProject(1517);
  54 + echo date('Y-m-d H:i:s') . 'start->1517' . PHP_EOL;
  55 + $url1 = 'https://ecdn6.globalso.com/upload/p/1517/file/2025-10/horse-racing-tkd-modification-1.xlsx';//改tdk
  56 + $url2 = 'https://v6-file.globalso.com/upload/p/1517/file/2025-10/horse-racing-url-modification.xlsx';//改url路由+tdk
  57 + $this->download_1517_action($url2);
59 DB::disconnect('custom_mysql'); 58 DB::disconnect('custom_mysql');
60 echo date('Y-m-d H:i:s') . 'end' . PHP_EOL; 59 echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;
61 } 60 }
62 61
63 /** 62 /**
  63 + * @remark :导入
  64 + * @name :download_1517_action
  65 + * @author :lyh
  66 + * @method :post
  67 + * @time :2025/10/22 16:47
  68 + */
  69 + public function download_1517_action($url)
  70 + {
  71 + // 临时文件路径(确保目录存在)
  72 + $tempDir = storage_path('app');
  73 + if (!is_dir($tempDir)) {
  74 + mkdir($tempDir, 0755, true);
  75 + }
  76 + $tempPath = $tempDir . '/temp_url.xlsx';
  77 + try {
  78 + // 使用 cURL 下载文件,防止403问题
  79 + $ch = curl_init($url);
  80 + curl_setopt_array($ch, [
  81 + CURLOPT_RETURNTRANSFER => true,
  82 + CURLOPT_FOLLOWLOCATION => true, // 跟随重定向
  83 + CURLOPT_USERAGENT => 'Mozilla/5.0 (compatible; LaravelApp/1.0)', // 模拟浏览器
  84 + CURLOPT_TIMEOUT => 30, // 超时防止卡死
  85 + ]);
  86 + $data = curl_exec($ch);
  87 + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  88 + curl_close($ch);
  89 + // 检查下载是否成功
  90 + if ($httpCode !== 200 || !$data) {
  91 + echo "文件下载失败,HTTP状态码:{$httpCode}";
  92 + }
  93 + // 保存到临时文件
  94 + file_put_contents($tempPath, $data);
  95 + // 加载 Excel 文件
  96 + $spreadsheet = IOFactory::load($tempPath);
  97 + $sheet = $spreadsheet->getActiveSheet();
  98 + $rows = $sheet->toArray();
  99 + // 删除临时文件
  100 + if (file_exists($tempPath)) {
  101 + unlink($tempPath);
  102 + }
  103 + $d = [];
  104 + //todo::处理数据
  105 + $productModel = new Product();
  106 + foreach ($rows as $key => $row) {
  107 + if($key == 0){
  108 + continue;
  109 + }
  110 + $path = parse_url($row[1], PHP_URL_PATH);
  111 + $path = ltrim(parse_url($path, PHP_URL_PATH), '/');
  112 + $info = $productModel->read(['route'=>$path],['id','title','route','seo_mate']);
  113 + if($info === false){
  114 + echo '未找到数据->'.$row[0].PHP_EOL;
  115 + $d[] = $row[0];
  116 + continue;
  117 + }
  118 + $seo_mate = $info['seo_mate'];
  119 + $seo_mate['title'] = $row[2] ?? '';
  120 + $seo_mate['keyword'] = $row[3] ?? '';
  121 + //todo::重新生成路由
  122 + $route = RouteMap::setRoute($row[2],RouteMap::SOURCE_PRODUCT,$info['id'],$info['project_id']);
  123 + $productModel->edit(['route'=>$route,'old_route'=>$path,'seo_mate'=>json_encode($seo_mate,true),'title'=>$row[2]],['id'=>$info['id']]);
  124 + echo '执行的ID:'.$info['id'].PHP_EOL;
  125 + }
  126 + } catch (\Exception $e) {
  127 + // 输出更清晰的错误信息
  128 + echo '文件下载或解析失败:' . $e->getMessage() . PHP_EOL;
  129 + // 清理资源
  130 + if (file_exists($tempPath)) {
  131 + unlink($tempPath);
  132 + }
  133 + DB::disconnect('custom_mysql');
  134 + }
  135 + }
  136 +
  137 +
  138 + /**
64 * @remark :3951项目导入产品 139 * @remark :3951项目导入产品
65 * @name :import3951Product 140 * @name :import3951Product
66 * @author :lyh 141 * @author :lyh
@@ -86,8 +86,8 @@ class SendProduct extends Command @@ -86,8 +86,8 @@ class SendProduct extends Command
86 $start_date = date('Y-m-d 00:00:00'); 86 $start_date = date('Y-m-d 00:00:00');
87 $end_date = date('Y-m-d 23:59:59'); 87 $end_date = date('Y-m-d 23:59:59');
88 $productModel = new Product(); 88 $productModel = new Product();
89 - $arr = $productModel->formatQuery(['send_time'=>['between',[$start_date,$end_date]],'status'=>3])->pluck('route')->toArray();  
90 - $productModel->edit(['status'=>1],['send_time'=>['between',[$start_date,$end_date]],'status'=>3]); 89 + $arr = $productModel->formatQuery(['send_time'=>['<=',$end_date],'status'=>3])->pluck('route')->toArray();
  90 + $productModel->edit(['status'=>1],['send_time'=>['<=',$end_date],'status'=>3]);
91 return $arr; 91 return $arr;
92 } 92 }
93 93
@@ -102,8 +102,8 @@ class SendProduct extends Command @@ -102,8 +102,8 @@ class SendProduct extends Command
102 $start_date = date('Y-m-d 00:00:00'); 102 $start_date = date('Y-m-d 00:00:00');
103 $end_date = date('Y-m-d 23:59:59'); 103 $end_date = date('Y-m-d 23:59:59');
104 $blogModel = new Blog(); 104 $blogModel = new Blog();
105 - $arr = $blogModel->formatQuery(['release_at'=>['between',[$start_date,$end_date]],'status'=>3])->pluck('url')->toArray();  
106 - $blogModel->edit(['status'=>1],['release_at'=>['between',[$start_date,$end_date]],'status'=>3]); 105 + $arr = $blogModel->formatQuery(['release_at'=>['<=',$end_date],'status'=>3])->pluck('url')->toArray();
  106 + $blogModel->edit(['status'=>1],['release_at'=>['<=',$end_date],'status'=>3]);
107 return $arr; 107 return $arr;
108 } 108 }
109 109
@@ -118,8 +118,8 @@ class SendProduct extends Command @@ -118,8 +118,8 @@ class SendProduct extends Command
118 $start_date = date('Y-m-d 00:00:00'); 118 $start_date = date('Y-m-d 00:00:00');
119 $end_date = date('Y-m-d 23:59:59'); 119 $end_date = date('Y-m-d 23:59:59');
120 $newsModel = new News(); 120 $newsModel = new News();
121 - $arr = $newsModel->formatQuery(['release_at'=>['between',[$start_date,$end_date]],'status'=>3])->pluck('url')->toArray();  
122 - $newsModel->edit(['status'=>1],['release_at'=>['between',[$start_date,$end_date]],'status'=>3]); 121 + $arr = $newsModel->formatQuery(['release_at'=>['<=',$end_date],'status'=>3])->pluck('url')->toArray();
  122 + $newsModel->edit(['status'=>1],['release_at'=>['<=',$end_date],'status'=>3]);
123 return $arr; 123 return $arr;
124 } 124 }
125 } 125 }
@@ -33,11 +33,11 @@ class SyncImage extends Command @@ -33,11 +33,11 @@ class SyncImage extends Command
33 33
34 34
35 public function handle(){ 35 public function handle(){
36 - $str = $this->getProjectConfig(4636); 36 + $str = $this->getProjectConfig(2123);
37 $imageModel = new Image(); 37 $imageModel = new Image();
38 -// $strImage = '/upload/p/4240/image_other/2025-09/picture-18-copy-3.jpg,/upload/p/4240/image_other/2025-09/picture-17-copy-2.jpg,/upload/p/4240/image_other/2025-09/picture-16-copy-2.jpg,/upload/p/4240/image_other/2025-09/picture-12-copy-3.jpg,/upload/p/4240/image_other/2025-09/picture-5-copy-1.jpg,/upload/p/4240/image_other/2025-09/picture-6-copy-1.jpg,/upload/p/4240/image_other/2025-09/picture-10-copy-2.jpg,/upload/p/4240/image_other/2025-09/picture-11-copy-2.jpg,/upload/p/4240/image_other/2025-09/4-1.jpg,/upload/p/4240/image_other/2025-09/picture-18-copy-2.jpg,/upload/p/4240/image_other/2025-09/picture-16-copy-1.jpg,/upload/p/4240/image_other/2025-09/picture-17-copy-1.jpg,/upload/p/4240/image_other/2025-09/picture-15-copy-2.jpg,/upload/p/4240/image_other/2025-09/picture-13-copy-1.jpg,/upload/p/4240/image_other/2025-09/picture-14-copy-1.jpg,/upload/p/4240/image_other/2025-09/picture-12-copy-2.jpg,/upload/p/4240/image_other/2025-09/picture-10-copy-1.jpg,/upload/p/4240/image_other/2025-09/picture-11-copy-1.jpg,/upload/p/4240/image_other/2025-09/picture-20-copy-1.jpg,/upload/p/4240/image_other/2025-09/picture-18-copy-1.jpg,/upload/p/4240/image_other/2025-09/picture-19-copy-1.jpg,/upload/p/4240/image_other/2025-09/image-1-copy.jpg,/upload/p/4240/image_other/2025-09/image-2-copy.jpg,/upload/p/4240/image_other/2025-09/picture-3-copy.jpg,/upload/p/4240/image_other/2025-09/picture-6-copy.jpg,/upload/p/4240/image_other/2025-09/picture-4-copy.jpg,/upload/p/4240/image_other/2025-09/picture-5-copy.jpg,/upload/p/4240/image_other/2025-09/picture-9-copy.jpg,/upload/p/4240/image_other/2025-09/picture-7-copy.jpg,/upload/p/4240/image_other/2025-09/picture-8-copy.jpg,/upload/p/4240/image_other/2025-09/picture-15-copy-1.jpg,/upload/p/4240/image_other/2025-09/picture-14-copy.jpg,/upload/p/4240/image_other/2025-09/picture-13-copy.jpg,/upload/p/4240/image_other/2025-09/picture-12-copy-1.jpg,/upload/p/4240/image_other/2025-08/picture-44-copy.jpg,/upload/p/4240/image_other/2025-08/45.jpg,/upload/p/4240/image_other/2025-09/picture-10-copy.jpg,/upload/p/4240/image_other/2025-09/picture-11-copy.jpg,/upload/p/4240/image_other/2025-08/43.jpg,/upload/p/4240/image_other/2025-08/42.jpg,/upload/p/4240/image_other/2025-08/picture-38-copy.jpg,/upload/p/4240/image_other/2025-08/picture-37-copy.jpg,/upload/p/4240/image_other/2025-08/picture-36-copy.jpg,/upload/p/4240/image_other/2025-08/picture-35-copy-1.jpg,/upload/p/4240/image_other/2025-08/picture-30-copy.jpg,/upload/p/4240/image_other/2025-08/29.jpg,/upload/p/4240/image_other/2025-08/28-1.jpg,/upload/p/4240/image_other/2025-08/27-1.jpg,/upload/p/4240/image_other/2025-08/picture-23-copy.jpg,/upload/p/4240/image_other/2025-08/22-1.jpg,/upload/p/4240/image_other/2025-08/21.jpg,/upload/p/4240/image_other/2025-08/17.jpg,/upload/p/4240/image_other/2025-08/16.jpg,/upload/p/4240/image_other/2025-08/picture-15-copy.jpg,/upload/p/4240/image_other/2025-08/11-2.jpg,/upload/p/4240/image_other/2025-08/10-1.jpg,/upload/p/4240/image_other/2025-08/picture-6.jpg,/upload/p/4240/image_other/2025-08/picture-5.jpg,/upload/p/4240/image_other/2025-08/picture-4.jpg,/upload/p/4240/image_other/2025-08/api-standard-welded-pipe.jpg,/upload/p/4240/image_other/2025-08/gb-standard-welded-pipe.jpg,/upload/p/4240/image_other/2025-08/gost-standard-welded-pipe.jpg,/upload/p/4240/image_other/2025-08/jis-standard-welded-pipe.jpg,/upload/p/4240/image_other/2025-08/asmeastm-welded-pipe.jpg,/upload/p/4240/image_other/2025-08/en-standard-welded-pipe.jpg,/upload/p/4240/image_other/2025-08/api-corrosion-resistant-alloy-cra-pipe.jpg,/upload/p/4240/image_other/2025-08/nickel-alloy-seamless-pipe.jpg,/upload/p/4240/image_other/2025-08/duplexsuper-duplex-seamless-pipe.jpg,/upload/p/4240/image_other/2025-08/super-austenitic-seamless-pipe.jpg,/upload/p/4240/image_other/2025-08/austenitic-stainless-steel-seamless-pipe.jpg,/upload/p/4240/image_other/2025-08/thick-zinc-coated-pipe.jpg,/upload/p/4240/image_other/2025-08/galvanized-fbe-pipe.jpg,/upload/p/4240/image_other/2025-08/electro-galvanized-pipe.jpg,/upload/p/4240/image_other/2025-08/hot-dip-galvanized-pipe.jpg,/upload/p/4240/image_other/2025-08/q235-galvanized-pipe.jpg,/upload/p/4240/image_other/2025-08/q195-galvanized-pipe.jpg,/upload/p/4240/image_other/2025-08/bare-ssaw-steel-pipe.jpg,/upload/p/4240/image_other/2025-08/fbe-coated-ssaw-steel-pipe.jpg,/upload/p/4240/image_other/2025-08/x52-ssaw-steel-pipe.jpg,/upload/p/4240/image_other/2025-08/q235b-ssaw-steel-pipe.jpg,/upload/p/4240/image_other/2025-08/low-alloy-steel-erw-pipe.jpg,/upload/p/4240/image_other/2025-08/carbon-steel-erw-pipe.jpg,/upload/p/4240/image_other/2025-08/black-carbon-steel-pipe.jpg,/upload/p/4240/image_other/2025-08/picture-19-copy.jpg,/upload/p/4240/image_other/2025-08/hydrogen-energy-skid.jpg';  
39 - $lists = $imageModel->selectField(['project_id'=>4636],'path');  
40 -// $lists = explode(',',$strImage); 38 + $strImage = '/upload/p/2123/image_other/2025-10/1-361.jpg,/upload/p/2123/image_other/2025-10/3-255.jpg,/upload/p/2123/image_other/2025-10/4-237.jpg,/upload/p/2123/image_other/2025-10/5-104.jpg,/upload/p/2123/image_other/2025-10/6-53.jpg,/upload/p/2123/image_other/2025-10/7-31.jpg,/upload/p/2123/image_other/2025-10/8-27.jpg,/upload/p/2123/image_other/2025-10/5-105.jpg';
  39 +// $lists = $imageModel->selectField(['project_id'=>4636],'path');
  40 + $lists = explode(',',$strImage);
41 $domain = 'http://globalso-v6-1309677403.cos.ap-hongkong.myqcloud.com';//cos域名 41 $domain = 'http://globalso-v6-1309677403.cos.ap-hongkong.myqcloud.com';//cos域名
42 foreach ($lists as $v){ 42 foreach ($lists as $v){
43 $url = $domain . $v.'?'.$str; 43 $url = $domain . $v.'?'.$str;
@@ -100,9 +100,11 @@ class UpdateKeyword extends Command @@ -100,9 +100,11 @@ class UpdateKeyword extends Command
100 }else{ 100 }else{
101 $randomNumber = $text[$key] ?? rand(0, $number - 1); 101 $randomNumber = $text[$key] ?? rand(0, $number - 1);
102 } 102 }
  103 + if(isset($text[$randomNumber])){
103 $keywordModel->edit(['keyword_content'=>$text[$randomNumber]],['title'=>$item]); 104 $keywordModel->edit(['keyword_content'=>$text[$randomNumber]],['title'=>$item]);
104 } 105 }
105 } 106 }
  107 + }
106 //按给定的数量更新 108 //按给定的数量更新
107 if(!empty($updateObject['number']) && ($updateObject['number'] != 0)){ 109 if(!empty($updateObject['number']) && ($updateObject['number'] != 0)){
108 $keywordIdArr = $keywordModel->where("status",1)->inRandomOrder()->take($updateObject['number'])->pluck('id')->toArray(); 110 $keywordIdArr = $keywordModel->where("status",1)->inRandomOrder()->take($updateObject['number'])->pluck('id')->toArray();
@@ -112,10 +114,12 @@ class UpdateKeyword extends Command @@ -112,10 +114,12 @@ class UpdateKeyword extends Command
112 }else{ 114 }else{
113 $randomNumber = $text[$key] ?? rand(0, $number - 1); 115 $randomNumber = $text[$key] ?? rand(0, $number - 1);
114 } 116 }
  117 + if(isset($text[$randomNumber])){
115 $keywordModel->edit(['keyword_content'=>$text[$randomNumber]],['title'=>$item]); 118 $keywordModel->edit(['keyword_content'=>$text[$randomNumber]],['title'=>$item]);
116 } 119 }
117 } 120 }
118 } 121 }
  122 + }
119 return true; 123 return true;
120 } 124 }
121 125
@@ -163,6 +163,62 @@ class FormGlobalsoApi @@ -163,6 +163,62 @@ class FormGlobalsoApi
163 } 163 }
164 164
165 /** 165 /**
  166 + *
  167 + * 自定义邮件发送接口
  168 + * @param string $to_email 接收邮箱
  169 + * @param string $subject 标题
  170 + * @param string $message 发送内容
  171 + * @param string $ip 发送ip
  172 + * @param string $refer 来源页面
  173 + * @param string $submit_time 询盘发送时间
  174 + * @param string $reply_email 回复邮箱
  175 + * @return bool
  176 + */
  177 + function customizeInquiryEmail($to_email, $subject, $message, $ip, $refer, $submit_time, $reply_email = '')
  178 + {
  179 + $post_data['from_email'] = 'mail@goodao.cn';
  180 + $post_data['to_email'] = trim($to_email);
  181 + $post_data['title'] = trim($subject);
  182 + $post_data['message'] = $message;
  183 + $post_data['ip'] = trim($ip);
  184 + $post_data['refer'] = trim($refer);
  185 + $post_data['reply_email'] = trim($reply_email);
  186 + if(!$reply_email){
  187 + $post_data['reply_email'] = $post_data['from_email'];
  188 + }
  189 + $post_data['submit_time'] = $submit_time;
  190 + $url = "https://form.globalso.com/api/b4153b7556";
  191 + $curl = curl_init($url);
  192 + curl_setopt($curl, CURLOPT_POST, 1);
  193 + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  194 + curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 30);
  195 + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
  196 + curl_setopt($curl, CURLOPT_AUTOREFERER, 1);
  197 + curl_setopt($curl, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36');
  198 + curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
  199 + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
  200 + curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
  201 + $curl_response = curl_exec($curl);
  202 + curl_close($curl);
  203 + return true;
  204 + }
  205 +
  206 + /**
  207 + * 推送自定义询盘短信
  208 + * @param string $phones 多个手机号码, 使用英文逗号隔开
  209 + * @param string $country
  210 + * @param string $domain
  211 + * @return mixed|string
  212 + */
  213 + public function customizeInquirySms($phones, $country, $domain)
  214 + {
  215 + $param = compact('phones', 'country', 'domain');
  216 + $url = 'https://form.globalso.com/api/send_sms?' . http_build_query($param);
  217 + $result = http_get($url,['charset=utf-8']);
  218 + return $result;
  219 + }
  220 +
  221 + /**
166 * @remark :获取当前项目所有询盘及询盘国家 222 * @remark :获取当前项目所有询盘及询盘国家
167 * @name :getInquiryAll 223 * @name :getInquiryAll
168 * @author :lyh 224 * @author :lyh
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2025/10/23
  6 + * Time: 17:29
  7 + */
  8 +namespace App\Http\Controllers\Api;
  9 +
  10 +use App\Models\Geo\GeoConfirm;
  11 +use App\Models\Geo\GeoWritings;
  12 +use App\Models\Project\Project;
  13 +use Illuminate\Http\Request;
  14 +use Illuminate\Support\Facades\Crypt;
  15 +
  16 +/**
  17 + * GEO相关
  18 + * Class GeoController
  19 + * @package App\Http\Controllers\Api
  20 + */
  21 +class GeoController extends BaseController
  22 +{
  23 + /**
  24 + * 获取确认文章列表
  25 + * @param Request $request
  26 + * @return false|string
  27 + */
  28 + public function getWritingsList()
  29 + {
  30 + try {
  31 + $token = trim($this->param['token']);
  32 + $param = Crypt::decrypt($token);
  33 + if ($param['send_at'] + 86400 < time()) {}
  34 + $project_id = $param['project_id'];
  35 + } catch (\Exception $e) {
  36 + return $this->error('非法请求');
  37 + }
  38 + $project = Project::select('title', 'version')->where(['project_id' => $this->param['project_id']])->first();
  39 + $list = GeoWritings::select(['title', 'status', 'uniqid', 'confirm_at'])->where(['project_id' => $project_id, 'is_del' => GeoWritings::IS_DEL_FALSE])->get();
  40 + $result = [
  41 + 'project' => $project,
  42 + 'list' => $list
  43 + ];
  44 + return $this->success($result);
  45 + }
  46 +
  47 + /**
  48 + * 获取详情
  49 + * @param Request $request
  50 + * @return false|string
  51 + */
  52 + public function getWritingsDetail(Request $request)
  53 + {
  54 + $token = trim($request->input('token'));
  55 + $detail = GeoWritings::select(['title', 'content', 'status'])->where(['uniqid' => $token])->first();
  56 + return $this->success($detail);
  57 + }
  58 +
  59 +
  60 + /**
  61 + * 确认核心文章数据
  62 + * @param Request $request
  63 + * @return false|string
  64 + */
  65 + public function confirmWritings(Request $request)
  66 + {
  67 + $request->validate([
  68 + 'token' => 'required',
  69 + 'title' => 'required|max:120',
  70 + 'content' => 'required|max:5000'
  71 + ], [
  72 + 'token.required' => '非法请求',
  73 + 'title.required' => '标题不能为空',
  74 + 'title.max' => '最大长度不能超过120字符',
  75 + 'content.required' => '内容不能为空',
  76 + 'content.max' => '内容过长保存失败',
  77 + ]);
  78 + $token = trim($request->input('token'));
  79 + $data = GeoWritings::where(['uniqid' => $token])->first();
  80 + if (empty($data)){
  81 + return $this->error('非法请求');
  82 + }
  83 +
  84 + if ($data->status != GeoWritings::STATUS_RUNNING){
  85 + return $this->error('当前文章已确认,不可再次确认');
  86 + }
  87 +
  88 +
  89 + // FIXME 验证完成,保存数据,计算内容长度,处理内容中的资源, IP 确认时间 状态
  90 + return $data;
  91 + }
  92 +
  93 + /**
  94 + * 获取确认数据
  95 + * @param Request $request
  96 + * @return false|string
  97 + */
  98 + public function getConfirm(Request $request)
  99 + {
  100 + $token = trim($request->input('token'));
  101 + $data = GeoConfirm::where(['uniqid' => $token])->first();
  102 + if (empty($data)){
  103 + return $this->error('当前授权已失效');
  104 + }
  105 + $content = explode("\n", $data->content);
  106 + $confirm = explode("\n", $data->confirm);
  107 + $type = $data->type;
  108 + $status = $data->status;
  109 + $result = compact('content', 'confirm', 'type', 'status');
  110 + return $this->success($result);
  111 + }
  112 +
  113 + /**
  114 + * 保存确认数据
  115 + * 验证当前确认数据状态, 不可重复确认
  116 + * @param Request $request
  117 + */
  118 + public function saveConfirm(Request $request)
  119 + {}
  120 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GeoConfirmController.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/10/25 11:35
  8 + */
  9 +
  10 +namespace App\Http\Controllers\Aside\Geo;
  11 +
  12 +use App\Enums\Common\Code;
  13 +use App\Http\Controllers\Aside\BaseController;
  14 +use App\Http\Logic\Aside\Geo\GeoConfirmLogic;
  15 +use Illuminate\Http\Request;
  16 +
  17 +/**
  18 + * @remark :用户确认信息表
  19 + * @name :GeoConfirmController
  20 + * @author :lyh
  21 + * @method :post
  22 + * @time :2025/10/25 11:37
  23 + */
  24 +class GeoConfirmController extends BaseController
  25 +{
  26 + public function __construct(Request $request){
  27 + parent::__construct($request);
  28 + $this->logic = new GeoConfirmLogic();
  29 + }
  30 +
  31 + /**
  32 + * 保存确认数据, 并推送微信群
  33 + * @param Request $request
  34 + * @throws \App\Exceptions\AsideGlobalException
  35 + */
  36 + public function saveConfirmContent()
  37 + {
  38 + $this->request->validate([
  39 + 'project_id' => 'required',
  40 + 'type' => 'required|integer',
  41 + 'content' => 'required',
  42 + 'max_num' => 'required',
  43 + ], [
  44 + 'project_id.required' => '项目ID不能为空',
  45 + 'type.required' => '确定数据类型不能为空',
  46 + 'type.integer' => '确定数据类型不正确',
  47 + 'content.required' => '确定数据不能为空',
  48 + 'max_num.required' => '最大确认数量不能为空',
  49 + ]);
  50 + $data = $this->logic->saveConfirmContent($this->param);
  51 + $this->response('success', Code::SUCCESS, $data);
  52 + }
  53 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2025/10/23
  6 + * Time: 10:23
  7 + */
  8 +namespace App\Http\Controllers\Aside\Geo;
  9 +
  10 +use App\Enums\Common\Code;
  11 +use App\Http\Controllers\Aside\BaseController;
  12 +use App\Http\Logic\Aside\Geo\GeoLogic;
  13 +use App\Models\Geo\GeoConf;
  14 +use App\Models\Geo\GeoConfirm;
  15 +use App\Models\Manage\ManageHr;
  16 +use App\Models\Project\KeywordPrefix;
  17 +use App\Models\Project\Project;
  18 +use App\Models\ProjectAssociation\ProjectAssociation;
  19 +use Illuminate\Http\Request;
  20 +
  21 +/**
  22 + * Class GeoController
  23 + * @package App\Http\Controllers\Aside\Geo
  24 + */
  25 +class GeoController extends BaseController
  26 +{
  27 + public function __construct(Request $request){
  28 + parent::__construct($request);
  29 + $this->logic = new GeoLogic();
  30 + }
  31 +
  32 + /**
  33 + * 获取GEO相关配置
  34 + * @param Request $request
  35 + */
  36 + public function getConfig()
  37 + {
  38 + $this->request->validate([
  39 + 'project_id' => 'required',
  40 + ], [
  41 + 'project_id.required' => '项目ID不能为空',
  42 + ]);
  43 + $data = $this->logic->getCongInfo($this->param['project_id']);
  44 + $this->response('success', Code::SUCCESS, $data);
  45 + }
  46 +
  47 + /**
  48 + * 保存GEO配置
  49 + * TODO 单独保存GEO开启状态, 达标数量
  50 + * @param Request $request
  51 + * @throws \App\Exceptions\AsideGlobalException
  52 + */
  53 + public function saveConfig()
  54 + {
  55 + $this->request->validate([
  56 + 'project_id' => 'required',
  57 + 'manager_id' => 'nullable|integer',
  58 + 'company' => 'nullable|max:200',
  59 + 'brand' => 'nullable|max:200',
  60 + 'description' => 'nullable|max:500',
  61 + ], [
  62 + 'project_id.required' => '项目ID不能为空',
  63 + 'manager_id.integer' => '管理员参数非法',
  64 + 'company.max' => '公司名称不能超过200个字符',
  65 + 'brand.max' => '品牌名不能超过200个字符',
  66 + 'description.max' => '描述不能超过500个字符',
  67 + ]);
  68 + $data = $this->logic->saveConfig($this->param);
  69 + $this->response('success', Code::SUCCESS, $data);
  70 + }
  71 +
  72 +
  73 +
  74 + /**
  75 + * OA后台管理员,保存确认数据
  76 + * 客户可以进行确认, OA后台也可以进行确认,以及修改
  77 + * @param Request $request
  78 + */
  79 + public function saveConfirmData(Request $request)
  80 + {
  81 +
  82 + }
  83 +}
@@ -11,7 +11,7 @@ namespace App\Http\Controllers\Aside\Geo; @@ -11,7 +11,7 @@ namespace App\Http\Controllers\Aside\Geo;
11 11
12 use App\Enums\Common\Code; 12 use App\Enums\Common\Code;
13 use App\Http\Controllers\Aside\BaseController; 13 use App\Http\Controllers\Aside\BaseController;
14 -use App\Http\Logic\Aside\Geo\GeoLogic; 14 +use App\Http\Logic\Aside\Geo\GeoQuestionLogic;
15 use Illuminate\Http\Request; 15 use Illuminate\Http\Request;
16 16
17 /** 17 /**
@@ -26,7 +26,7 @@ class GeoQuestionController extends BaseController @@ -26,7 +26,7 @@ class GeoQuestionController extends BaseController
26 public function __construct(Request $request) 26 public function __construct(Request $request)
27 { 27 {
28 parent::__construct($request); 28 parent::__construct($request);
29 - $this->logic = new GeoLogic(); 29 + $this->logic = new GeoQuestionLogic();
30 } 30 }
31 31
32 /** 32 /**
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GeoWritingTaskController.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/10/25 10:40
  8 + */
  9 +
  10 +namespace App\Http\Controllers\Aside\Geo;
  11 +
  12 +use App\Enums\Common\Code;
  13 +use App\Http\Controllers\Aside\BaseController;
  14 +use App\Http\Logic\Aside\Geo\GeoWritingsTaskLogic;
  15 +use App\Http\Requests\Aside\Geo\GeoWritingsTaskRequest;
  16 +use Illuminate\Http\Request;
  17 +
  18 +/**
  19 + * @remark :文章任务(收集数据)
  20 + * @name :GeoWritingTaskController
  21 + * @author :lyh
  22 + * @method :post
  23 + * @time :2025/10/25 10:40
  24 + */
  25 +class GeoWritingTaskController extends BaseController
  26 +{
  27 + public function __construct(Request $request)
  28 + {
  29 + parent::__construct($request);
  30 + $this->logic = new GeoWritingsTaskLogic();
  31 + }
  32 +
  33 + /**
  34 + * @remark :ai文章列表页
  35 + * @name :lists
  36 + * @author :lyh
  37 + * @method :post
  38 + * @time :2025/10/25 15:12
  39 + */
  40 + public function lists(){
  41 + $data = $this->logic->listWritingTask($this->map,$this->page,$this->row,$this->order);
  42 + $this->response('success',Code::SUCCESS,$data);
  43 + }
  44 +
  45 + /**
  46 + * @remark :保存geoAi文章生成数据
  47 + * @name :lists
  48 + * @author :lyh
  49 + * @method :post
  50 + * @time :2025/10/25 10:41
  51 + */
  52 + public function saveWritingTask(){
  53 + $request = new GeoWritingsTaskRequest();
  54 + $request->validated();
  55 + $data = $this->logic->saveWritingTask();
  56 + $this->response('success',Code::SUCCESS,$data);
  57 + }
  58 +
  59 + /**
  60 + * @remark :批量删除文章任务
  61 + * @name :delWritingTask
  62 + * @author :lyh
  63 + * @method :post
  64 + * @time :2025/10/25 15:03
  65 + */
  66 + public function delWritingTask(){
  67 + $this->request->validate([
  68 + 'id'=>'required|array',
  69 + ],[
  70 + 'id.required' => 'ID不能为空',
  71 + 'id.array' => 'ID为数组',
  72 + ]);
  73 + $data = $this->logic->delWritingTask();
  74 + $this->response('success',Code::SUCCESS,$data);
  75 + }
  76 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GeoWritingsController.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/10/25 10:41
  8 + */
  9 +
  10 +namespace App\Http\Controllers\Aside\Geo;
  11 +
  12 +use App\Http\Controllers\Aside\BaseController;
  13 +
  14 +/**
  15 + * @remark :geo文章
  16 + * @name :GeoWritingsController
  17 + * @author :lyh
  18 + * @method :post
  19 + * @time :2025/10/25 10:41
  20 + */
  21 +class GeoWritingsController extends BaseController
  22 +{
  23 +
  24 +}
@@ -160,7 +160,7 @@ class OptimizeController extends BaseController @@ -160,7 +160,7 @@ class OptimizeController extends BaseController
160 $manageModel = new ManageHr(); 160 $manageModel = new ManageHr();
161 $plan = Project::planMap(); 161 $plan = Project::planMap();
162 $seo_plan = Project::seoMap(); 162 $seo_plan = Project::seoMap();
163 - $item['plan'] = $plan[$item['plan']] ?? $seo_plan[1]; 163 + $item['plan'] = $plan[$item['plan']] ?? ($seo_plan[$item['seo_plan']] ?? '');
164 $item['channel'] = Channel::getChannelText($item['channel']['user_id'] ?? 0); 164 $item['channel'] = Channel::getChannelText($item['channel']['user_id'] ?? 0);
165 $item['build_leader'] = $manageModel->getName($item['leader_mid']); 165 $item['build_leader'] = $manageModel->getName($item['leader_mid']);
166 $item['build_manager'] = $manageModel->getName($item['manager_mid']); 166 $item['build_manager'] = $manageModel->getName($item['manager_mid']);
@@ -10,7 +10,6 @@ use App\Http\Logic\Aside\Project\OnlineCheckLogic; @@ -10,7 +10,6 @@ use App\Http\Logic\Aside\Project\OnlineCheckLogic;
10 use App\Http\Logic\Aside\Project\ProcessRecordsLogic; 10 use App\Http\Logic\Aside\Project\ProcessRecordsLogic;
11 use App\Http\Logic\Aside\Project\ProjectLogic; 11 use App\Http\Logic\Aside\Project\ProjectLogic;
12 use App\Http\Requests\Aside\Project\ProcessRecordsRequest; 12 use App\Http\Requests\Aside\Project\ProcessRecordsRequest;
13 -use App\Models\Ai\AiVideo;  
14 use App\Models\ASide\APublicModel; 13 use App\Models\ASide\APublicModel;
15 use App\Models\Channel\Channel; 14 use App\Models\Channel\Channel;
16 use App\Models\Channel\User; 15 use App\Models\Channel\User;
@@ -23,7 +22,10 @@ use App\Models\Devops\ServersIp; @@ -23,7 +22,10 @@ use App\Models\Devops\ServersIp;
23 use App\Models\Domain\DomainCreateTask; 22 use App\Models\Domain\DomainCreateTask;
24 use App\Models\Domain\DomainInfo; 23 use App\Models\Domain\DomainInfo;
25 use App\Models\Domain\DomainInfo as DomainInfoModel; 24 use App\Models\Domain\DomainInfo as DomainInfoModel;
  25 +use App\Models\Geo\GeoArticle;
  26 +use App\Models\Geo\GeoConf;
26 use App\Models\Geo\GeoLink; 27 use App\Models\Geo\GeoLink;
  28 +use App\Models\Geo\GeoQuestionResult;
27 use App\Models\HomeCount\Count; 29 use App\Models\HomeCount\Count;
28 use App\Models\Industry\ProjectIndustry; 30 use App\Models\Industry\ProjectIndustry;
29 use App\Models\Inquiry\InquirySet; 31 use App\Models\Inquiry\InquirySet;
@@ -31,7 +33,6 @@ use App\Models\Manage\BelongingGroup; @@ -31,7 +33,6 @@ use App\Models\Manage\BelongingGroup;
31 use App\Models\Manage\ManageHr; 33 use App\Models\Manage\ManageHr;
32 use App\Models\Project\AiVideoTask; 34 use App\Models\Project\AiVideoTask;
33 use App\Models\Project\DeployBuild; 35 use App\Models\Project\DeployBuild;
34 -use App\Models\Project\DeployOptimize;  
35 use App\Models\Project\Payment; 36 use App\Models\Project\Payment;
36 use App\Models\Project\ProcessRecords; 37 use App\Models\Project\ProcessRecords;
37 use App\Models\Project\Project; 38 use App\Models\Project\Project;
@@ -43,7 +44,7 @@ use App\Models\Task\Task; @@ -43,7 +44,7 @@ use App\Models\Task\Task;
43 use App\Models\WebSetting\WebLanguage; 44 use App\Models\WebSetting\WebLanguage;
44 use App\Models\WorkOrder\TicketProject; 45 use App\Models\WorkOrder\TicketProject;
45 use Illuminate\Http\Request; 46 use Illuminate\Http\Request;
46 -use Illuminate\Support\Facades\DB; 47 +use Illuminate\Support\Facades\Http;
47 48
48 /** 49 /**
49 * 项目管理 50 * 项目管理
@@ -225,7 +226,7 @@ class ProjectController extends BaseController @@ -225,7 +226,7 @@ class ProjectController extends BaseController
225 if($this->map['domain_type'] == 'domain'){ 226 if($this->map['domain_type'] == 'domain'){
226 $parsedUrl = parse_url($this->map['domain_search']); 227 $parsedUrl = parse_url($this->map['domain_search']);
227 $this->map['domain_search'] = $parsedUrl['host'] ?? $this->map['domain_search']; 228 $this->map['domain_search'] = $parsedUrl['host'] ?? $this->map['domain_search'];
228 - $ids = DomainInfo::where('domain', 'like', '%'.$this->map['domain_search'].'%')->pluck('id')->toArray(); 229 + $ids = DomainInfoModel::where('domain', 'like', '%'.$this->map['domain_search'].'%')->pluck('id')->toArray();
229 $query->whereIn('gl_project_deploy_optimize.domain', $ids); 230 $query->whereIn('gl_project_deploy_optimize.domain', $ids);
230 }else{ 231 }else{
231 $query->where('gl_project_deploy_build.test_domain','like','%'.$this->map['domain_search'].'%'); 232 $query->where('gl_project_deploy_build.test_domain','like','%'.$this->map['domain_search'].'%');
@@ -319,8 +320,12 @@ class ProjectController extends BaseController @@ -319,8 +320,12 @@ class ProjectController extends BaseController
319 }); 320 });
320 } 321 }
321 } 322 }
322 - if(isset($this->map['seo_plan'])){  
323 - $query = $query->where('gl_project_deploy_build.seo_plan','!=',0); 323 + if (isset($this->map['seo_plan'])) {
  324 + $query = $query->where('gl_project_deploy_build.seo_plan', '!=', 0)
  325 + ->where(function ($subQuery) {
  326 + $subQuery->where('gl_project_deploy_build.plan', '=', 0)
  327 + ->orWhere('gl_project_deploy_build.seo_plan', '!=', 9);
  328 + });
324 } 329 }
325 if(isset($this->map['site_status'])){ 330 if(isset($this->map['site_status'])){
326 $query = $query->where('gl_project.site_status',$this->map['site_status']); 331 $query = $query->where('gl_project.site_status',$this->map['site_status']);
@@ -444,7 +449,19 @@ class ProjectController extends BaseController @@ -444,7 +449,19 @@ class ProjectController extends BaseController
444 $item['type'] = $item['extend_type']; 449 $item['type'] = $item['extend_type'];
445 } 450 }
446 $manageModel = new ManageHr(); 451 $manageModel = new ManageHr();
447 - $item['channel'] = Channel::getChannelText($item['channel']['user_id'] ?? 0); 452 + //geo项目
  453 + if(($item['plan'] == 0) && ($item['seo_plan'] != 0)){
  454 + //geo项目负责人
  455 + $geoConfModel = new GeoConf();
  456 + $manage_id = $geoConfModel->getValue(['project_id'=>$item['id']],'manager_id');
  457 + $item['geo_manage_name'] = $manageModel->getName($manage_id);
  458 + $geoArticleModel = new GeoArticle();
  459 + $item['geo_article_num'] = $geoArticleModel->counts(['project_id'=>$item['id']]);//文章数量
  460 + $geoLinkModel = new GeoLink();
  461 + $item['geo_link_num'] = $geoLinkModel->counts(['project_id'=>$item['id']]);//权威新闻数量
  462 + $questionResModel = new GeoQuestionResult();
  463 + $item['geo_qualify_num'] = $questionResModel->counts(['project_id'=>$item['id'],'hit'=>['!=',0],'platform'=>['in',['openai', 'gemini','google_ai_overview']]]);//排名
  464 + }
448 $item['build_leader'] = $manageModel->getName($item['leader_mid']); 465 $item['build_leader'] = $manageModel->getName($item['leader_mid']);
449 $item['build_manager'] = $manageModel->getName($item['manager_mid']); 466 $item['build_manager'] = $manageModel->getName($item['manager_mid']);
450 $item['build_designer'] = $manageModel->getName($item['designer_mid']); 467 $item['build_designer'] = $manageModel->getName($item['designer_mid']);
@@ -458,18 +475,19 @@ class ProjectController extends BaseController @@ -458,18 +475,19 @@ class ProjectController extends BaseController
458 $seoPlanMap = Project::seoMap(); 475 $seoPlanMap = Project::seoMap();
459 $item['plan'] = $planMap[$item['plan']] ?? ''; 476 $item['plan'] = $planMap[$item['plan']] ?? '';
460 $item['seo_plan'] = $seoPlanMap[$item['seo_plan']] ?? ''; 477 $item['seo_plan'] = $seoPlanMap[$item['seo_plan']] ?? '';
461 - $item['created_at'] = date('Y年m月d日', strtotime($item['cooperate_date']));  
462 - $item['autologin_code'] = getAutoLoginCode($item['id']);  
463 - $domainModel = new DomainInfo(); 478 + $domainModel = new DomainInfoModel();
464 $item['domain'] = !empty($item['domain']) ? $domainModel->getDomain($item['domain']) : ''; 479 $item['domain'] = !empty($item['domain']) ? $domainModel->getDomain($item['domain']) : '';
  480 + $item['uuid'] = TicketProject::where('table_id', $item['id'])->where('project_cate', 2)->value('uuid') ?? null;
  481 + $item['friend_id'] = ProjectAssociation::where('project_id', $item['id'])->where('status', ProjectAssociation::STATUS_NORMAL)->where('binding_app', ProjectAssociation::ENTERPRISE_WECHAT)->value('friend_id') ?? null;
  482 + $item['autologin_code'] = getAutoLoginCode($item['id']);
  483 + $item['created_at'] = date('Y年m月d日', strtotime($item['cooperate_date']));
465 $item['product_num'] = $data['product'] ?? 0; 484 $item['product_num'] = $data['product'] ?? 0;
466 $item['keyword_num'] = $data['key'] ?? 0; 485 $item['keyword_num'] = $data['key'] ?? 0;
467 $item['article_num'] = ($data['blog'] ?? 0) + ($data['news'] ?? 0); 486 $item['article_num'] = ($data['blog'] ?? 0) + ($data['news'] ?? 0);
468 $item['task_finish_num'] = Task::getNumByProjectId($item['id'], Task::STATUS_DOWN); 487 $item['task_finish_num'] = Task::getNumByProjectId($item['id'], Task::STATUS_DOWN);
469 $item['task_pending_num'] = Task::getNumByProjectId($item['id'], [Task::STATUS_DONGING, Task::STATUS_WAIT]); 488 $item['task_pending_num'] = Task::getNumByProjectId($item['id'], [Task::STATUS_DONGING, Task::STATUS_WAIT]);
470 $item['collect_time'] = $item['is_upgrade'] ? UpdateLog::getProjectUpdate($item['id']) : ''; 489 $item['collect_time'] = $item['is_upgrade'] ? UpdateLog::getProjectUpdate($item['id']) : '';
471 - $item['uuid'] = TicketProject::where('table_id', $item['id'])->where('project_cate', 2)->value('uuid') ?? null;  
472 - $item['friend_id'] = ProjectAssociation::where('project_id', $item['id'])->where('status', ProjectAssociation::STATUS_NORMAL)->where('binding_app', ProjectAssociation::ENTERPRISE_WECHAT)->value('friend_id') ?? null; 490 + $item['channel'] = Channel::getChannelText($item['channel']['user_id'] ?? 0);
473 return $item; 491 return $item;
474 } 492 }
475 493
@@ -792,7 +810,6 @@ class ProjectController extends BaseController @@ -792,7 +810,6 @@ class ProjectController extends BaseController
792 $order_by_sort = $request->input('order_by_sort', 'desc'); 810 $order_by_sort = $request->input('order_by_sort', 'desc');
793 $start_time = $this->param['start_time'] ?? ''; 811 $start_time = $this->param['start_time'] ?? '';
794 $end_time = $this->param['end_time'] ?? ''; 812 $end_time = $this->param['end_time'] ?? '';
795 -  
796 if(!$source_id && !$id){ 813 if(!$source_id && !$id){
797 $this->response('参数异常',Code::SYSTEM_ERROR); 814 $this->response('参数异常',Code::SYSTEM_ERROR);
798 } 815 }
@@ -886,7 +903,6 @@ class ProjectController extends BaseController @@ -886,7 +903,6 @@ class ProjectController extends BaseController
886 $param['yesterday_ip_count'] = $yesterday_count['ip_num'] ?? 0; 903 $param['yesterday_ip_count'] = $yesterday_count['ip_num'] ?? 0;
887 $param['today_ip_count'] = $today_count['ip_num'] ?? 0; 904 $param['today_ip_count'] = $today_count['ip_num'] ?? 0;
888 $param['inquiry_num'] = $today_count['inquiry_num'] ?? 0; 905 $param['inquiry_num'] = $today_count['inquiry_num'] ?? 0;
889 -  
890 $list[] = $param; 906 $list[] = $param;
891 } 907 }
892 $data['list'] = $list; 908 $data['list'] = $list;
@@ -1177,7 +1193,6 @@ class ProjectController extends BaseController @@ -1177,7 +1193,6 @@ class ProjectController extends BaseController
1177 'id.required' => '项目id不能为空', 1193 'id.required' => '项目id不能为空',
1178 'site_status.required' => '状态不能为空', 1194 'site_status.required' => '状态不能为空',
1179 ]); 1195 ]);
1180 -  
1181 //获取项目数据 1196 //获取项目数据
1182 $projectModel = new Project(); 1197 $projectModel = new Project();
1183 $projectInfo = $projectModel->read(['id'=>$this->param['id']],['project_type','serve_id','site_status','site_token']); 1198 $projectInfo = $projectModel->read(['id'=>$this->param['id']],['project_type','serve_id','site_status','site_token']);
@@ -1187,14 +1202,12 @@ class ProjectController extends BaseController @@ -1187,14 +1202,12 @@ class ProjectController extends BaseController
1187 if($projectInfo['site_status'] == $this->param['site_status']){ 1202 if($projectInfo['site_status'] == $this->param['site_status']){
1188 $this->response('success'); 1203 $this->response('success');
1189 } 1204 }
1190 -  
1191 //获取服务器数据 1205 //获取服务器数据
1192 $serverIpModel = new ServersIp(); 1206 $serverIpModel = new ServersIp();
1193 $serversIpInfo = $serverIpModel->read(['id' => $projectInfo['serve_id']], ['servers_id']); 1207 $serversIpInfo = $serverIpModel->read(['id' => $projectInfo['serve_id']], ['servers_id']);
1194 if(!$serversIpInfo){ 1208 if(!$serversIpInfo){
1195 $this->fail('获取项目所属服务器失败'); 1209 $this->fail('获取项目所属服务器失败');
1196 } 1210 }
1197 -  
1198 if($serversIpInfo['servers_id'] == ServerConfig::SELF_SITE_ID){ 1211 if($serversIpInfo['servers_id'] == ServerConfig::SELF_SITE_ID){
1199 //自建站项目 1212 //自建站项目
1200 if($this->param['site_status'] == 1){ 1213 if($this->param['site_status'] == 1){
@@ -1204,7 +1217,6 @@ class ProjectController extends BaseController @@ -1204,7 +1217,6 @@ class ProjectController extends BaseController
1204 //开启站点 1217 //开启站点
1205 $site_token = str_replace('_expired','',$projectInfo['site_token']); 1218 $site_token = str_replace('_expired','',$projectInfo['site_token']);
1206 } 1219 }
1207 -  
1208 $projectModel->edit(['site_status'=>$this->param['site_status'],'site_token'=>$site_token],['id'=>$this->param['id']]); 1220 $projectModel->edit(['site_status'=>$this->param['site_status'],'site_token'=>$site_token],['id'=>$this->param['id']]);
1209 }else{ 1221 }else{
1210 //普通项目 1222 //普通项目
@@ -1214,7 +1226,6 @@ class ProjectController extends BaseController @@ -1214,7 +1226,6 @@ class ProjectController extends BaseController
1214 if(!$domainInfo){ 1226 if(!$domainInfo){
1215 $this->fail('获取域名数据失败'); 1227 $this->fail('获取域名数据失败');
1216 } 1228 }
1217 -  
1218 if($this->param['site_status'] == 1){ 1229 if($this->param['site_status'] == 1){
1219 //关闭站点:通知C端 1230 //关闭站点:通知C端
1220 $re = curl_get('https://'.$domainInfo['domain'].'/api/stop_or_start_website'); 1231 $re = curl_get('https://'.$domainInfo['domain'].'/api/stop_or_start_website');
@@ -1255,10 +1266,8 @@ class ProjectController extends BaseController @@ -1255,10 +1266,8 @@ class ProjectController extends BaseController
1255 } 1266 }
1256 } 1267 }
1257 } 1268 }
1258 -  
1259 $projectModel->edit(['site_status'=>$this->param['site_status']],['id'=>$this->param['id']]); 1269 $projectModel->edit(['site_status'=>$this->param['site_status']],['id'=>$this->param['id']]);
1260 } 1270 }
1261 -  
1262 $this->response('success'); 1271 $this->response('success');
1263 } 1272 }
1264 1273
@@ -1328,4 +1337,27 @@ class ProjectController extends BaseController @@ -1328,4 +1337,27 @@ class ProjectController extends BaseController
1328 $data['videoFrequency'] =$videoModel->videoFrequency(); 1337 $data['videoFrequency'] =$videoModel->videoFrequency();
1329 $this->response('success',Code::SUCCESS,$data); 1338 $this->response('success',Code::SUCCESS,$data);
1330 } 1339 }
  1340 +
  1341 + /**
  1342 + * @remark :获取广告先投特批
  1343 + * @name :getSpAdsLists
  1344 + * @author :lyh
  1345 + * @method :post
  1346 + * @time :2025/10/22 16:59
  1347 + */
  1348 + public function getSpAdsLists()
  1349 + {
  1350 + $params = $this->param;
  1351 + $url = 'https://oa.cmer.com/api/sp_ads_lists';
  1352 + // 发送 GET 请求(附带 token)
  1353 + $params['token'] = md5('qqs' . date('Y-m-d'));
  1354 + $response = Http::get($url, $params);
  1355 + // 判断请求是否成功
  1356 + if ($response->successful()) {
  1357 + $data = $response->json(); // 自动解析 JSON
  1358 + $this->response('success', Code::SUCCESS, $data);
  1359 + } else {
  1360 + $this->fail('拉取结果失败,请联系管理员');
  1361 + }
  1362 + }
1331 } 1363 }
@@ -21,6 +21,9 @@ class AiBlogController extends BaseController @@ -21,6 +21,9 @@ class AiBlogController extends BaseController
21 * @time :2025/2/14 13:59 21 * @time :2025/2/14 13:59
22 */ 22 */
23 public function getAiBlog(AiBlog $aiBlog){ 23 public function getAiBlog(AiBlog $aiBlog){
  24 + if(isset($this->map['new_title']) && !empty($this->map['new_title'])){
  25 + $this->map['new_title'] = ['like', '%'.$this->map['new_title'].'%'];
  26 + }
24 $lists = $aiBlog->lists($this->map,$this->page,$this->row,'id',['id','keyword','new_title','route','image','task_id','status','created_at','updated_at']); 27 $lists = $aiBlog->lists($this->map,$this->page,$this->row,'id',['id','keyword','new_title','route','image','task_id','status','created_at','updated_at']);
25 if(!empty($lists) && !empty($lists['list'])){ 28 if(!empty($lists) && !empty($lists['list'])){
26 foreach ($lists['list'] as $k => $v){ 29 foreach ($lists['list'] as $k => $v){
@@ -389,14 +389,17 @@ class FileController @@ -389,14 +389,17 @@ class FileController
389 */ 389 */
390 public function getFileList(){ 390 public function getFileList(){
391 if(isset($this->cache['project_id']) && !empty($this->cache['project_id'])){ 391 if(isset($this->cache['project_id']) && !empty($this->cache['project_id'])){
392 - $this->map['project_id'] = $this->cache['project_id']; 392 + $this->param['project_id'] = $this->cache['project_id'];
393 } 393 }
394 $fileModel = new File(); 394 $fileModel = new File();
395 - $this->map['type'] = 'mp4';  
396 - $lists = $fileModel->list($this->map,'id',['id','hash','type','path','created_at','name']);  
397 - foreach ($lists as $k => $v){ 395 + $this->param['type'] = 'mp4';
  396 + $page = $this->param['page'] ?? 1;
  397 + $row = $this->param['row'] ?? 20;
  398 + unset($this->param['page'],$this->param['row']);
  399 + $lists = $fileModel->lists($this->param,$page,$row,'id',['id','hash','type','path','created_at','name']);
  400 + foreach ($lists['list'] as $k => $v){
398 $v['file_link'] = getFileUrl($v['path'],$this->cache['storage_type'] ?? 0,$this->cache['project_location'] ?? 0,$this->cache['file_cdn'] ?? 0); 401 $v['file_link'] = getFileUrl($v['path'],$this->cache['storage_type'] ?? 0,$this->cache['project_location'] ?? 0,$this->cache['file_cdn'] ?? 0);
399 - $lists[$k] = $v; 402 + $lists['list'][$k] = $v;
400 } 403 }
401 $this->response('success',Code::SUCCESS,$lists); 404 $this->response('success',Code::SUCCESS,$lists);
402 } 405 }
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GeoConfirmLogic.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/10/25 11:36
  8 + */
  9 +
  10 +namespace App\Http\Logic\Aside\Geo;
  11 +
  12 +use App\Enums\Common\Code;
  13 +use App\Http\Logic\Aside\BaseLogic;
  14 +use App\Models\Geo\GeoConfirm;
  15 +use App\Models\ProjectAssociation\ProjectAssociation;
  16 +
  17 +/**
  18 + * @remark :用户确认信息
  19 + * @name :GeoConfirmLogic
  20 + * @author :lyh
  21 + * @method :post
  22 + * @time :2025/10/25 11:37
  23 + */
  24 +class GeoConfirmLogic extends BaseLogic
  25 +{
  26 + public function __construct()
  27 + {
  28 + parent::__construct();
  29 + $this->param = $this->requestAll;
  30 + $this->model = new GeoConfirm();
  31 + }
  32 +
  33 + /**
  34 + * @remark :保存数据->并推送微信群客户确认
  35 + * @name :saveConfirmContent
  36 + * @author :lyh
  37 + * @method :post
  38 + * @time :2025/10/25 11:41
  39 + */
  40 + public function saveConfirmContent($param)
  41 + {
  42 + try {
  43 + $info = $this->model->read(['project_id' => $param['project_id']]);
  44 + if($info === false){
  45 + $id = $this->model->addReturnId($param);
  46 + }else{
  47 + $id = $param['id'];
  48 + $this->model->edit($param,['id'=>$info['id']]);
  49 + }
  50 + $friend = ProjectAssociation::where(['project_id' => $param['project_id']])->first();
  51 + if (empty($friend)){
  52 + $this->fail('项目未绑定微信群, 推送消息失败!');
  53 + }
  54 + GeoConfirm::sendConfirmMessage($id, $friend->friend_id);
  55 + } catch (\Exception $e) {
  56 + $this->fail('操作失败, error:' . $e->getMessage());
  57 + }
  58 + return $this->success(['id'=>$id]);
  59 + }
  60 +}
@@ -4,109 +4,99 @@ @@ -4,109 +4,99 @@
4 * @name :GeoLogic.php 4 * @name :GeoLogic.php
5 * @author :lyh 5 * @author :lyh
6 * @method :post 6 * @method :post
7 - * @time :2025/7/2 17:51 7 + * @time :2025/10/25 11:08
8 */ 8 */
9 9
10 namespace App\Http\Logic\Aside\Geo; 10 namespace App\Http\Logic\Aside\Geo;
11 11
  12 +use App\Enums\Common\Code;
12 use App\Http\Logic\Aside\BaseLogic; 13 use App\Http\Logic\Aside\BaseLogic;
13 -use App\Models\Geo\GeoPlatform; 14 +use App\Models\Geo\GeoConf;
14 use App\Models\Geo\GeoQuestion; 15 use App\Models\Geo\GeoQuestion;
  16 +use App\Models\Manage\ManageHr;
  17 +use App\Models\Project\KeywordPrefix;
15 use App\Models\Project\Project; 18 use App\Models\Project\Project;
16 19
  20 +/**
  21 + * @remark :geo设置
  22 + * @name :GeoLogic
  23 + * @author :lyh
  24 + * @method :post
  25 + * @time :2025/10/25 11:08
  26 + */
17 class GeoLogic extends BaseLogic 27 class GeoLogic extends BaseLogic
18 { 28 {
19 public function __construct() 29 public function __construct()
20 { 30 {
21 parent::__construct(); 31 parent::__construct();
22 $this->param = $this->requestAll; 32 $this->param = $this->requestAll;
23 - $this->model = new GeoQuestion(); 33 + $this->model = new GeoConf();
24 } 34 }
25 35
26 /** 36 /**
27 - * @remark :设置geo状态  
28 - * @name :setGeoStatus 37 + * @remark :获取geo设置数据详情
  38 + * @name :getCongInfo
29 * @author :lyh 39 * @author :lyh
30 * @method :post 40 * @method :post
31 - * @time :2025/7/2 17:51 41 + * @time :2025/10/25 11:10
32 */ 42 */
33 - public function setGeoStatus(){ 43 + public function getCongInfo($project_id)
  44 + {
34 $projectModel = new Project(); 45 $projectModel = new Project();
35 - $data = $projectModel->edit(['geo_status'=>$this->param['geo_status'],'geo_frequency'=>$this->param['geo_frequency']],['id'=>$this->param['project_id']]);  
36 - $questionModel = new GeoQuestion();  
37 - $questionModel->edit(['status'=>$this->param['geo_status']],['project_id'=>$this->param['project_id']]);  
38 - return $this->success($data); 46 + $project_geo_conf = $projectModel->read(['id' => $project_id],['title', 'version', 'geo_status', 'geo_qualify_num']);
  47 + $geoConfModel = new GeoConf();
  48 + $geo_conf = $geoConfModel->read(['project_id' => $project_id]);
  49 + if($geo_conf === false){//数据未初始化
  50 + $geo_conf = [
  51 + 'project_id' => $project_id, 'manager_id'=>0, 'company'=>$project_geo_conf['title'], 'brand'=>'', 'description'=>''
  52 + ];
39 } 53 }
40 -  
41 - /**  
42 - * @remark :获取类型  
43 - * @name :getType  
44 - * @author :lyh  
45 - * @method :post  
46 - * @time :2025/7/3 10:47  
47 - */  
48 - public function getType(){  
49 - $data['type'] = $this->model->brandType();  
50 - $data['frequency'] = $this->model->frequency;  
51 - $geoPlatformModel = new GeoPlatform();  
52 - $data['platform'] = $geoPlatformModel->getList();  
53 - return $this->success($data);  
54 - }  
55 -  
56 - /**  
57 - * @remark :获取问题列表  
58 - * @name :getGeoQuestionList  
59 - * @author :lyh  
60 - * @method :post  
61 - * @time :2025/7/3 9:12  
62 - */  
63 - public function getGeoQuestionList($map,$page,$row,$order,$field = ['*']){  
64 - $data = $this->model->lists($map,$page,$row,$order,$field);  
65 - if(!empty($data) && !empty($data['list'])){  
66 - foreach ($data['list'] as $key => $item){  
67 - $item['type_name'] = $this->model->brandType()[$item['type']];  
68 - $data['list'][$key] = $item; 54 + //负责人集合
  55 + $geo_manage_list = $geoConfModel->geoManage();
  56 + // geo配置管理员,已经移除管理员列表,补充管理员信息
  57 + if ($geo_conf && $geo_conf['manager_id'] && empty($geo_manage_list[$geo_conf['manager_id']])) {
  58 + $manage = ManageHr::where(['id' => $geo_conf['manager_id']])->pluck('name', 'id')->toArray();
  59 + $geo_manage_list = array_merge($geo_manage_list, $manage);
69 } 60 }
70 - }  
71 - return $this->success($data); 61 + $result = [
  62 + 'project_geo_conf' => $project_geo_conf,
  63 + 'geo_conf' => $geo_conf,
  64 + 'geo_manage_list' => $geo_manage_list,
  65 + 'geo_keyword' => [
  66 + 'prefix' => KeywordPrefix::getKeyword($project_id, KeywordPrefix::TYPE_GEO_PREFIX),
  67 + 'suffix' => KeywordPrefix::getKeyword($project_id, KeywordPrefix::TYPE_GEO_SUFFIX),
  68 + ],
  69 + ];
  70 + return $this->success($result);
72 } 71 }
73 72
74 /** 73 /**
75 - * @remark :保存数据  
76 - * @name :saveGeoQuestion 74 + * @remark :保存数据详情
  75 + * @name :saveCongInfo
77 * @author :lyh 76 * @author :lyh
78 * @method :post 77 * @method :post
79 - * @time :2025/7/3 9:47  
80 - * @param : question->提交的问题  
81 - * @param : url->提交的网址  
82 - * @param : keywords->提交的关键字  
83 - * @param : project_id->项目id 78 + * @time :2025/10/25 11:14
  79 + * @param->gl_geo_conf : project_id->项目id;manager_id->管理员id;company->公司名称;brand->品牌名;description->描述(必传)
  80 + * @param :prefix->前缀;suffix->后缀(非必传)
  81 + * @param->gl_project : geo_status->开启/关闭状态 geo_qualify_num->达标数量
84 */ 82 */
85 - public function saveGeoQuestion(){  
86 - //处理数据  
87 - $this->param['question'] = json_encode($this->param['question'] ?? [],true);  
88 - $this->param['url'] = json_encode($this->param['url'] ?? [],true);  
89 - $this->param['keywords'] = json_encode($this->param['keywords'] ?? [],true);  
90 - //执行时间设置为今天  
91 - if(isset($this->param['id']) && !empty($this->param['id'])){  
92 - $id = $this->param['id'];  
93 - $this->model->edit($this->param,['id'=>$id]); 83 + public function saveConfig($param)
  84 + {
  85 + $projectModel = new Project();
  86 + $projectModel->edit(['geo_status'=>$param['geo_status'],'geo_qualify_num'=>$param['geo_qualify_num']],['id'=>$param['project_id']]);
  87 + try {
  88 + unset($param['geo_status'],$param['geo_qualify_num']);//无需保存
  89 + $info = $this->model->read(['project_id' => $param['project_id']]);
  90 + if($info === false){
  91 + $id = $this->model->addReturnId($param);
94 }else{ 92 }else{
95 - $this->param['next_time'] = date('Y-m-d');  
96 - $id = $this->model->addReturnId($this->param); 93 + $id = $param['id'];
  94 + $this->model->edit($param,['id'=>$info['id']]);
  95 + }
  96 + } catch (\Exception $e) {
  97 + $this->fail('配置保存失败, error:' . $e->getMessage());
97 } 98 }
98 return $this->success(['id'=>$id]); 99 return $this->success(['id'=>$id]);
99 } 100 }
100 101
101 - /**  
102 - * @remark :删除数据  
103 - * @name :delGeoQuestion  
104 - * @author :lyh  
105 - * @method :post  
106 - * @time :2025/7/3 10:13  
107 - */  
108 - public function delGeoQuestion(){  
109 - $data = $this->model->del(['id'=>['in',$this->param['ids']]]);  
110 - return $this->success($data);  
111 - }  
112 } 102 }
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GeoQuestionLogic.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/7/2 17:51
  8 + */
  9 +
  10 +namespace App\Http\Logic\Aside\Geo;
  11 +
  12 +use App\Http\Logic\Aside\BaseLogic;
  13 +use App\Models\Geo\GeoPlatform;
  14 +use App\Models\Geo\GeoQuestion;
  15 +use App\Models\Project\Project;
  16 +
  17 +class GeoQuestionLogic extends BaseLogic
  18 +{
  19 + public function __construct()
  20 + {
  21 + parent::__construct();
  22 + $this->param = $this->requestAll;
  23 + $this->model = new GeoQuestion();
  24 + }
  25 +
  26 + /**
  27 + * @remark :设置geo状态
  28 + * @name :setGeoStatus
  29 + * @author :lyh
  30 + * @method :post
  31 + * @time :2025/7/2 17:51
  32 + */
  33 + public function setGeoStatus(){
  34 + $projectModel = new Project();
  35 + $data = $projectModel->edit(['geo_status'=>$this->param['geo_status'],'geo_frequency'=>$this->param['geo_frequency']],['id'=>$this->param['project_id']]);
  36 + $questionModel = new GeoQuestion();
  37 + $questionModel->edit(['status'=>$this->param['geo_status']],['project_id'=>$this->param['project_id']]);
  38 + return $this->success($data);
  39 + }
  40 +
  41 + /**
  42 + * @remark :获取类型
  43 + * @name :getType
  44 + * @author :lyh
  45 + * @method :post
  46 + * @time :2025/7/3 10:47
  47 + */
  48 + public function getType(){
  49 + $data['type'] = $this->model->brandType();
  50 + $data['frequency'] = $this->model->frequency;
  51 + $geoPlatformModel = new GeoPlatform();
  52 + $data['platform'] = $geoPlatformModel->getList();
  53 + return $this->success($data);
  54 + }
  55 +
  56 + /**
  57 + * @remark :获取问题列表
  58 + * @name :getGeoQuestionList
  59 + * @author :lyh
  60 + * @method :post
  61 + * @time :2025/7/3 9:12
  62 + */
  63 + public function getGeoQuestionList($map,$page,$row,$order,$field = ['*']){
  64 + $data = $this->model->lists($map,$page,$row,$order,$field);
  65 + if(!empty($data) && !empty($data['list'])){
  66 + foreach ($data['list'] as $key => $item){
  67 + $item['type_name'] = $this->model->brandType()[$item['type']];
  68 + $data['list'][$key] = $item;
  69 + }
  70 + }
  71 + return $this->success($data);
  72 + }
  73 +
  74 + /**
  75 + * @remark :保存数据
  76 + * @name :saveGeoQuestion
  77 + * @author :lyh
  78 + * @method :post
  79 + * @time :2025/7/3 9:47
  80 + * @param : question->提交的问题
  81 + * @param : url->提交的网址
  82 + * @param : keywords->提交的关键字
  83 + * @param : project_id->项目id
  84 + */
  85 + public function saveGeoQuestion(){
  86 + //处理数据
  87 + $this->param['question'] = json_encode($this->param['question'] ?? [],true);
  88 + $this->param['url'] = json_encode($this->param['url'] ?? [],true);
  89 + $this->param['keywords'] = json_encode($this->param['keywords'] ?? [],true);
  90 + //执行时间设置为今天
  91 + if(isset($this->param['id']) && !empty($this->param['id'])){
  92 + $id = $this->param['id'];
  93 + $this->model->edit($this->param,['id'=>$id]);
  94 + }else{
  95 + $this->param['next_time'] = date('Y-m-d');
  96 + $id = $this->model->addReturnId($this->param);
  97 + }
  98 + return $this->success(['id'=>$id]);
  99 + }
  100 +
  101 + /**
  102 + * @remark :删除数据
  103 + * @name :delGeoQuestion
  104 + * @author :lyh
  105 + * @method :post
  106 + * @time :2025/7/3 10:13
  107 + */
  108 + public function delGeoQuestion(){
  109 + $data = $this->model->del(['id'=>['in',$this->param['ids']]]);
  110 + return $this->success($data);
  111 + }
  112 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GeoWritingsLogic.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/10/25 10:43
  8 + */
  9 +
  10 +namespace App\Http\Logic\Aside\Geo;
  11 +
  12 +use App\Http\Logic\Aside\BaseLogic;
  13 +use App\Models\Geo\GeoWritings;
  14 +
  15 +/**
  16 + * @remark :文章任务
  17 + * @name :GeoWritingsLogic
  18 + * @author :lyh
  19 + * @method :post
  20 + * @time :2025/10/25 10:44
  21 + */
  22 +class GeoWritingsLogic extends BaseLogic
  23 +{
  24 + public function __construct()
  25 + {
  26 + parent::__construct();
  27 + $this->param = $this->requestAll;
  28 + $this->model = new GeoWritings();
  29 + }
  30 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GeoWritingsTaskLogic.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/10/25 10:45
  8 + */
  9 +
  10 +namespace App\Http\Logic\Aside\Geo;
  11 +
  12 +use App\Http\Logic\Aside\BaseLogic;
  13 +use App\Models\Geo\GeoWritings;
  14 +use App\Models\Geo\GeoWritingsTask;
  15 +
  16 +class GeoWritingsTaskLogic extends BaseLogic
  17 +{
  18 + public function __construct()
  19 + {
  20 + parent::__construct();
  21 + $this->param = $this->requestAll;
  22 + $this->model = new GeoWritingsTask();
  23 + }
  24 +
  25 + /**
  26 + * @remark :
  27 + * @name :listWritingTask
  28 + * @author :lyh
  29 + * @method :post
  30 + * @time :2025/10/25 15:13
  31 + */
  32 + public function listWritingTask($map,$page,$row,$order){
  33 + $data = $this->model->lists($map,$page,$row,$order);
  34 + return $this->success($data);
  35 + }
  36 +
  37 + /**
  38 + * @remark :保存AI文章数据
  39 + * @name :saveWritingTask
  40 + * @author :lyh
  41 + * @method :post
  42 + * @time :2025/10/25 14:41
  43 + * @param :project_id->项目ID;company->公司名称;brand->品牌词;keyword->关键词;prefix->前缀;suffix->后缀;event_title->事件标题;
  44 + * event_content->事件内容;title->标题;description->描述;footer->结尾引用;img->图片;ai_model->ai_model
  45 + */
  46 + public function saveWritingTask(){
  47 + try {
  48 + if(isset($this->param['id']) &&!empty($this->param['id'])){
  49 + $id = $this->param['id'];
  50 + $this->model->edit($this->param,['id'=>$id]);
  51 + }else{
  52 + $id = $this->model->addReturnId($this->param);
  53 + }
  54 + }catch (\Exception $e){
  55 + $this->fail('保存数据失败,请联系管理员'.$e->getMessage());
  56 + }
  57 + return $this->success(['id'=>$id]);
  58 + }
  59 +
  60 + /**
  61 + * @remark :删除数据
  62 + * @name :delWritingTask
  63 + * @author :lyh
  64 + * @method :post
  65 + * @time :2025/10/25 15:05
  66 + */
  67 + public function delWritingTask()
  68 + {
  69 + $res = $this->model->del(['id'=>['in',$this->param['id']]]);
  70 + if($res === false){
  71 + $this->fail('删除失败,请联系管理员');
  72 + }
  73 + return $this->success();
  74 + }
  75 +}
@@ -123,10 +123,6 @@ class ProjectLogic extends BaseLogic @@ -123,10 +123,6 @@ class ProjectLogic extends BaseLogic
123 $info['collect_test_domain'] = $info['is_upgrade'] ? CollectLog::getCollectTestDomain($id) : ''; 123 $info['collect_test_domain'] = $info['is_upgrade'] ? CollectLog::getCollectTestDomain($id) : '';
124 //获取项目所属行业 124 //获取项目所属行业
125 $info['deploy_optimize']['industry'] = ProjectIndustryRelated::where('project_id', $id)->pluck('industry_id')->toArray(); 125 $info['deploy_optimize']['industry'] = ProjectIndustryRelated::where('project_id', $id)->pluck('industry_id')->toArray();
126 - $questionModel = new GeoQuestionResult();  
127 - $info['question_qualify_count'] = $questionModel->where('project_id', $id)  
128 - ->where('hit','!=',0)->whereIn('platform',['openai', 'gemini','google_ai_overview'])  
129 - ->count();  
130 return $this->success($info); 126 return $this->success($info);
131 } 127 }
132 128
@@ -34,9 +34,20 @@ class GeoQuestionResLogic extends BaseLogic @@ -34,9 +34,20 @@ class GeoQuestionResLogic extends BaseLogic
34 * @time :2025/7/8 17:16 34 * @time :2025/7/8 17:16
35 */ 35 */
36 public function getCount(){ 36 public function getCount(){
37 - $total = $this->model->counts(['project_id'=>$this->user['project_id']]);  
38 - $type_1 = $this->model->counts(['type'=>$this->model::BRAND_TYPE,'project_id'=>$this->user['project_id']]);  
39 - $type_2 = $this->model->counts(['type'=>$this->model::MARKETING_TYPE,'project_id'=>$this->user['project_id']]); 37 + $total = $this->model
  38 + ->where('project_id', $this->user['project_id'])
  39 + ->distinct('question')
  40 + ->count('question');
  41 + $type_1 = $this->model
  42 + ->where('type', $this->model::BRAND_TYPE)
  43 + ->where('project_id', $this->user['project_id'])
  44 + ->distinct('question')
  45 + ->count('question');
  46 + $type_2 = $this->model
  47 + ->where('type', $this->model::MARKETING_TYPE)
  48 + ->where('project_id', $this->user['project_id'])
  49 + ->distinct('question')
  50 + ->count('question');
40 return $this->success(['total'=>$total,'type_1'=>$type_1,'type_2'=>$type_2]); 51 return $this->success(['total'=>$total,'type_1'=>$type_1,'type_2'=>$type_2]);
41 } 52 }
42 53
@@ -5,6 +5,8 @@ namespace App\Http\Logic\Bside\HomeCount; @@ -5,6 +5,8 @@ namespace App\Http\Logic\Bside\HomeCount;
5 5
6 use App\Helper\FormGlobalsoApi; 6 use App\Helper\FormGlobalsoApi;
7 use App\Http\Logic\Bside\BaseLogic; 7 use App\Http\Logic\Bside\BaseLogic;
  8 +use App\Models\Geo\GeoCount;
  9 +use App\Models\RankData\RankDataBmseo;
8 use App\Models\Template\BCustomTemplate; 10 use App\Models\Template\BCustomTemplate;
9 use App\Models\Visit\Visit; 11 use App\Models\Visit\Visit;
10 use App\Models\Visit\VisitItem; 12 use App\Models\Visit\VisitItem;
@@ -101,8 +103,13 @@ class CountLogic extends BaseLogic @@ -101,8 +103,13 @@ class CountLogic extends BaseLogic
101 * @time :2023/5/24 14:03 103 * @time :2023/5/24 14:03
102 */ 104 */
103 public function keyword_data_count(){ 105 public function keyword_data_count(){
  106 + $version = $this->project['version'] ?? '';
104 $yesterday = date('Y-m-d'); 107 $yesterday = date('Y-m-d');
  108 + if($this->user['project_seo_type'] == 1){
  109 + $rankDataModel = new RankDataBmseo();
  110 + }else{
105 $rankDataModel = new RankDataModel(); 111 $rankDataModel = new RankDataModel();
  112 + }
106 $param = [ 113 $param = [
107 'updated_date' => $yesterday, 114 'updated_date' => $yesterday,
108 'project_id' => $this->user['project_id'] 115 'project_id' => $this->user['project_id']
@@ -117,6 +124,13 @@ class CountLogic extends BaseLogic @@ -117,6 +124,13 @@ class CountLogic extends BaseLogic
117 $data = []; 124 $data = [];
118 } 125 }
119 } 126 }
  127 + if(!empty($version) && ($version == '7.5')){
  128 + $geoCountModel = new GeoCount();
  129 + $geoInfo = $geoCountModel->where('project_id',$this->user['project_id'])->where('date', '<=', date('Y-m-d'))->orderBy('date', 'desc')->first();
  130 + $geoInfo = $geoInfo ? $geoInfo->toArray() : [];
  131 + $data['geo_qualify_total'] = $geoInfo['qualify_total'] ?? 0;
  132 + $data['total_count'] = ($this->project['deploy_build']['keyword_num'] ?? 0) + ($this->project['geo_qualify_num'] ?? 0);
  133 + }
120 return $this->success($data); 134 return $this->success($data);
121 } 135 }
122 136
@@ -93,7 +93,7 @@ class ProductLogic extends BaseLogic @@ -93,7 +93,7 @@ class ProductLogic extends BaseLogic
93 $route = $param['route']; 93 $route = $param['route'];
94 $is_upgrade = $param['is_upgrade'] ?? 0;//1:5.0数据 0:6.0 94 $is_upgrade = $param['is_upgrade'] ?? 0;//1:5.0数据 0:6.0
95 $six_read = $param['six_read'] ?? 0;//是否按6.0显示 95 $six_read = $param['six_read'] ?? 0;//是否按6.0显示
96 - if($six_read == 0 && $is_upgrade == 1){ 96 + if($six_read == 1 && $is_upgrade == 1){
97 unset($param['route']); 97 unset($param['route']);
98 }else{ 98 }else{
99 $param['route'] = RouteMap::setRoute($param['route'], RouteMap::SOURCE_PRODUCT, $this->param['id'], $this->user['project_id']); 99 $param['route'] = RouteMap::setRoute($param['route'], RouteMap::SOURCE_PRODUCT, $this->param['id'], $this->user['project_id']);
@@ -35,6 +35,9 @@ class WebSettingReceivingLogic extends BaseLogic @@ -35,6 +35,9 @@ class WebSettingReceivingLogic extends BaseLogic
35 */ 35 */
36 public function setting_receiving_save(){ 36 public function setting_receiving_save(){
37 $data = []; 37 $data = [];
  38 + if(!isset($this->param['data']) || empty($this->param['data'])){
  39 + $this->fail('参数错误,请联系管理员');
  40 + }
38 foreach ($this->param['data'] as $v){ 41 foreach ($this->param['data'] as $v){
39 if($v['type'] == 1){ 42 if($v['type'] == 1){
40 // 使用正则表达式匹配中国大陆手机号 43 // 使用正则表达式匹配中国大陆手机号
@@ -286,6 +286,7 @@ class UserLoginLogic @@ -286,6 +286,7 @@ class UserLoginLogic
286 $info['is_watermark'] = $project['is_watermark']; 286 $info['is_watermark'] = $project['is_watermark'];
287 $info['configuration'] = $project['deploy_build']['configuration']; 287 $info['configuration'] = $project['deploy_build']['configuration'];
288 $info['project_type'] = $project['type']; 288 $info['project_type'] = $project['type'];
  289 + $info['version'] = $project['version'] ?? 6;
289 $info['project_seo_type'] = $project['project_type']; 290 $info['project_seo_type'] = $project['project_type'];
290 $info['storage_type'] = $project['storage_type']; 291 $info['storage_type'] = $project['storage_type'];
291 $info['open_export_product'] = $project['open_export_product']; 292 $info['open_export_product'] = $project['open_export_product'];
@@ -55,7 +55,7 @@ class LoginAuthMiddleware @@ -55,7 +55,7 @@ class LoginAuthMiddleware
55 //操作权限设置 55 //操作权限设置
56 $projectRoleModel = new ProjectRoleModel(); 56 $projectRoleModel = new ProjectRoleModel();
57 $role_info = $projectRoleModel->read(['id'=>$info['role_id']]); 57 $role_info = $projectRoleModel->read(['id'=>$info['role_id']]);
58 - if($role_info['status'] != 0){ 58 + if($role_info === false || $role_info['status'] != 0){
59 return response(['code'=>Code::USER_LOGIN_ERROE,'message'=>'当前用户角色被禁用']); 59 return response(['code'=>Code::USER_LOGIN_ERROE,'message'=>'当前用户角色被禁用']);
60 } 60 }
61 return $role_info; 61 return $role_info;
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GeoWritingsTaskRequest.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/10/25 14:21
  8 + */
  9 +
  10 +namespace App\Http\Requests\Aside\Geo;
  11 +
  12 +use Illuminate\Foundation\Http\FormRequest;
  13 +
  14 +class GeoWritingsTaskRequest extends FormRequest
  15 +{
  16 + /**
  17 + * Determine if the user is authorized to make this request.
  18 + *
  19 + * @return bool
  20 + */
  21 + public function authorize()
  22 + {
  23 + return true;
  24 + }
  25 +
  26 + /**
  27 + * Get the validation rules that apply to the request.
  28 + *
  29 + * @return array
  30 + */
  31 + public function rules()
  32 + {
  33 + return [
  34 + 'project_id' => 'required',
  35 + 'company' => 'required|string',
  36 + 'brand' => 'required|string',
  37 + 'keyword' => 'required|string',
  38 + 'prefix' => 'required|string',
  39 + 'suffix' => 'required|string',
  40 + 'event_title' => 'required|string',
  41 + 'event_content' => 'required|string',
  42 + 'title' => 'required|string',
  43 + 'description' => 'required|string',
  44 + 'footer' => 'required|string',
  45 + 'img' => 'required|string',
  46 + 'ai_model' => 'required|string',
  47 + ];
  48 + }
  49 +}
@@ -26,7 +26,7 @@ class NewsRequest extends FormRequest @@ -26,7 +26,7 @@ class NewsRequest extends FormRequest
26 return [ 26 return [
27 'name'=>'required|max:200', 27 'name'=>'required|max:200',
28 'url'=>'required', 28 'url'=>'required',
29 -// 'seo_title' => 'max:70', 29 + 'seo_title' => 'max:70',
30 'seo_keywords' => 'max:300', 30 'seo_keywords' => 'max:300',
31 'seo_description' => 'max:200', 31 'seo_description' => 'max:200',
32 ]; 32 ];
@@ -38,7 +38,7 @@ class NewsRequest extends FormRequest @@ -38,7 +38,7 @@ class NewsRequest extends FormRequest
38 'name.required'=>'请填写名称', 38 'name.required'=>'请填写名称',
39 'name.max'=>'名称超过最长长度200', 39 'name.max'=>'名称超过最长长度200',
40 'url.required'=>'链接不能为空', 40 'url.required'=>'链接不能为空',
41 -// 'seo_title.max' => 'SEO标题不能超过70个字符', 41 + 'seo_title.max' => 'SEO标题不能超过70个字符',
42 'seo_keywords.max' => 'SEO关键词不能超过300个字符', 42 'seo_keywords.max' => 'SEO关键词不能超过300个字符',
43 'seo_description.max' => 'SEO描述不能超过200个字符', 43 'seo_description.max' => 'SEO描述不能超过200个字符',
44 ]; 44 ];
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2025/10/22
  6 + * Time: 17:01
  7 + */
  8 +namespace App\Models\Geo;
  9 +
  10 +use App\Models\Base;
  11 +use App\Models\Manage\ManageHr;
  12 +use Illuminate\Support\Facades\Cache;
  13 +
  14 +/**
  15 + * GEO 相关配置
  16 + * Class GeoConf
  17 + * @package App\Models\Geo
  18 + */
  19 +class GeoConf extends Base
  20 +{
  21 + /**
  22 + * @var string table
  23 + */
  24 + protected $table = 'gl_project_geo_conf';
  25 +
  26 +
  27 + /**
  28 + * GEO 负责人集合
  29 + * TODO 负责人:优化师 + 陶婵 + 艾媛媛
  30 + * @return array
  31 + */
  32 + public function geoManage()
  33 + {
  34 + $key = 'geo_manage_list_' . date('Ymd');
  35 + $optimize = Cache::get($key);
  36 + if (empty($optimize)) {
  37 + $optimize = ManageHr::where(['status' => ManageHr::STATUS_ONE, 'entry_position' => 46])->pluck('name', 'id')->toArray();
  38 + $optimize[1] = '陶婵';
  39 + $optimize[875] = '艾媛媛';
  40 + ksort($optimize);
  41 + Cache::put($key, $optimize, 3600);
  42 + }
  43 + return $optimize;
  44 + }
  45 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2025/10/22
  6 + * Time: 17:03
  7 + */
  8 +namespace App\Models\Geo;
  9 +
  10 +use App\Models\Base;
  11 +use App\Models\Workchat\MessagePush;
  12 +
  13 +/**
  14 + * GEO 客户确认相关数据
  15 + * Class GeoConfirm
  16 + * @package App\Models\Geo
  17 + */
  18 +class GeoConfirm extends Base
  19 +{
  20 + /**
  21 + * @var string table
  22 + */
  23 + protected $table = 'gl_project_geo_confirm';
  24 +
  25 + /**
  26 + * 客户确认类型
  27 + */
  28 + const TYPE_TITLE = 1;
  29 + const TYPE_KEYWORD = 2;
  30 +
  31 + /**
  32 + * 数据状态
  33 + */
  34 + const STATUS_INIT = 1; # 初始化数据,仅保存完成
  35 + const STATUS_RUNNING = 2; # 已推送客户,等待客户确认
  36 + const STATUS_FINISH = 3; # 客户已确认完成
  37 +
  38 + /**
  39 + * 客户确认数据类型
  40 + * @return array
  41 + */
  42 + public static function typeMapping()
  43 + {
  44 + return [
  45 + self::TYPE_TITLE => '确认标题',
  46 + self::TYPE_KEYWORD => '确认关键词'
  47 + ];
  48 + }
  49 +
  50 + /**
  51 + * 客户确认数据状态
  52 + * @return array
  53 + */
  54 + public static function statusMapping()
  55 + {
  56 + return [
  57 + self::STATUS_INIT => '初始数据',
  58 + self::STATUS_RUNNING => '数据确认中',
  59 + self::STATUS_FINISH => '客户已确认'
  60 + ];
  61 + }
  62 +
  63 +
  64 + /**
  65 + * 保存确认数据
  66 + * @param $project_id
  67 + * @param $type
  68 + * @param $confirm
  69 + * @param $confirm_num
  70 + * @param $confirm_ip
  71 + * @return bool
  72 + */
  73 + public static function saveConfirm($project_id, $type, $confirm, $confirm_num, $confirm_ip)
  74 + {
  75 + $data = self::where(compact('project_id', 'type'))->first();
  76 + if (empty($data))
  77 + return false;
  78 + $data->confirm = $confirm;
  79 + $data->confirm_ip = $confirm_ip;
  80 + $data->confirm_num = $confirm_num;
  81 + $data->confirm_at = now();
  82 + $data->status = self::STATUS_FINISH;
  83 + $data->save();
  84 + return $data;
  85 + }
  86 +
  87 + /**
  88 + * 推送确认消息
  89 + * @param $id
  90 + * @return bool
  91 + */
  92 + public static function sendConfirmMessage($id, $friend_id)
  93 + {
  94 + $data = self::where(compact('id'))->first();
  95 + $project_id = $data->project_id;
  96 + $content_type = 'Link';
  97 + $send_time = now();
  98 + $type = MessagePush::TYPE_GEO_CONFIRM;
  99 + $token = uniqid().$friend_id;
  100 + $created_at = $updated_at = now();
  101 + $content_array = [
  102 + 'title' => self::typeMapping()[$data->type],
  103 + 'desc' => self::typeMapping()[$data->type],
  104 + 'size' => 0,
  105 + 'thumbSize' => 0,
  106 + 'thumbUrl' => 'https://hub.globalso.com/logocm.png',
  107 + 'url' => 'https://oa.quanqiusou.cn/public-geo-confirm?token=' . $token
  108 + ];
  109 + $content = json_encode($content_array, JSON_UNESCAPED_UNICODE);
  110 + MessagePush::insert(compact('project_id', 'friend_id', 'type', 'content_type', 'content', 'send_time', 'updated_at', 'created_at'));
  111 + // 消息推送, 更新数据
  112 + $data->confirm = '';
  113 + $data->send_at = now();
  114 + $data->uniqid = $token;
  115 + $data->status = self::STATUS_RUNNING;
  116 + $data->save();
  117 + return $data;
  118 + }
  119 +}
@@ -35,7 +35,7 @@ class GeoPlatform extends Base @@ -35,7 +35,7 @@ class GeoPlatform extends Base
35 public function getList(){ 35 public function getList(){
36 // $data = Cache::get('geo_platform'); 36 // $data = Cache::get('geo_platform');
37 // if(empty($data)){ 37 // if(empty($data)){
38 - $data = $this->list(['status'=>$this::STATUS_ON],'id',['name','en_name','icon','sort'],'asc'); 38 + $data = $this->list(['status'=>$this::STATUS_ON],'sort',['name','en_name','icon','sort'],'desc');
39 Cache::put('geo_platform',$data,'12 * 3600'); 39 Cache::put('geo_platform',$data,'12 * 3600');
40 // } 40 // }
41 return $data; 41 return $data;
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2025/10/22
  6 + * Time: 17:25
  7 + */
  8 +namespace App\Models\Geo;
  9 +
  10 +use App\Models\Base;
  11 +use App\Models\ProjectAssociation\ProjectAssociation;
  12 +use App\Models\Workchat\MessagePush;
  13 +use Illuminate\Support\Facades\Crypt;
  14 +
  15 +/**
  16 + * GEO 文章相关
  17 + * Class GeoWritings
  18 + * @package App\Models\Geo
  19 + */
  20 +class GeoWritings extends Base
  21 +{
  22 + /**
  23 + * @var string $table
  24 + */
  25 + protected $table = 'gl_project_geo_writings';
  26 +
  27 + /**
  28 + * 文章来源类型
  29 + */
  30 + const TYPE_AI_CREATE = 1;
  31 + const TYPE_SUBMIT = 2;
  32 +
  33 + /**
  34 + * 文章状态类型
  35 + */
  36 + const STATUS_INIT = 1; # 文章仅保存完成,未推送给客户
  37 + const STATUS_RUNNING = 2; # 已推送客户,等待客户确认
  38 + const STATUS_FINISH = 3; # 客户已确认完成
  39 + const STATUS_AI_WAIT = 7; # 任务提交成功,等待AI生成
  40 + const STATUS_AI_RUNNING = 8; # AI生成中
  41 +
  42 + const IS_DEL_FALSE = 0;
  43 + const IS_DEL_TRUE = 1;
  44 +
  45 + /**
  46 + * @return array
  47 + */
  48 + public static function typeMapping()
  49 + {
  50 + return [
  51 + self::TYPE_AI_CREATE => 'AI生成文章',
  52 + self::TYPE_SUBMIT => '上传已有文章'
  53 + ];
  54 + }
  55 +
  56 + /**
  57 + * 状态隐私
  58 + * @return array
  59 + */
  60 + public static function statusMapping()
  61 + {
  62 + return [
  63 + self::STATUS_INIT => '已就绪,待推送',
  64 + self::STATUS_RUNNING => '已推送,待确认',
  65 + self::STATUS_FINISH => '已确认',
  66 + self::STATUS_AI_WAIT => '等待生成',
  67 + self::STATUS_AI_RUNNING => '生成中',
  68 + ];
  69 + }
  70 +
  71 + /**
  72 + * 推送确认消息
  73 + * TODO 通过项目ID,时间生成推送token,页面打开后, 回传token解码确定展示项目数据
  74 + * @param $project_id
  75 + * @return bool
  76 + * @throws \Exception
  77 + */
  78 + public static function sendConfirmMessage($project_id)
  79 + {
  80 + $friend = ProjectAssociation::where(['project_id' => $project_id])->first();
  81 + if (empty($friend)) {
  82 + throw new \Exception('项目未绑定微信群');
  83 + }
  84 + $content_type = 'Link';
  85 + $send_time = now();
  86 + $type = MessagePush::TYPE_GEO_CONFIRM;
  87 + $friend_id = $friend->friend_id;
  88 + $created_at = $updated_at = now();
  89 + $param = [
  90 + 'project_id' => $project_id,
  91 + 'send_at' => time()
  92 + ];
  93 + $token = Crypt::encrypt($param);
  94 + $content_array = [
  95 + 'title' => "确认核心文章",
  96 + 'desc' => '确认核心文章',
  97 + 'size' => 0,
  98 + 'thumbSize' => 0,
  99 + 'thumbUrl' => 'https://hub.globalso.com/logocm.png',
  100 + 'url' => 'https://oa.quanqiusou.cn/public-geo-article-list?token=' . $token
  101 + ];
  102 + $content = json_encode($content_array, JSON_UNESCAPED_UNICODE);
  103 + MessagePush::insert(compact('project_id', 'friend_id', 'type', 'content_type', 'content', 'send_time', 'updated_at', 'created_at'));
  104 + return true;
  105 + }
  106 +
  107 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :GeoWritingsTask.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/10/25 10:47
  8 + */
  9 +
  10 +namespace App\Models\Geo;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +/**
  15 + * @remark :文章生成任务
  16 + * @name :GeoWritingsTask
  17 + * @author :lyh
  18 + * @method :post
  19 + * @time :2025/10/25 10:48
  20 + */
  21 +class GeoWritingsTask extends Base
  22 +{
  23 + protected $table = 'gl_project_geo_writings_task';
  24 +}
@@ -5,10 +5,10 @@ namespace App\Models\Inquiry; @@ -5,10 +5,10 @@ namespace App\Models\Inquiry;
5 use App\Helper\Arr; 5 use App\Helper\Arr;
6 use App\Helper\FormGlobalsoApi; 6 use App\Helper\FormGlobalsoApi;
7 use App\Models\Base; 7 use App\Models\Base;
8 -use App\Utils\LogUtils;  
9 use Illuminate\Database\Eloquent\SoftDeletes; 8 use Illuminate\Database\Eloquent\SoftDeletes;
10 use Illuminate\Support\Facades\DB; 9 use Illuminate\Support\Facades\DB;
11 use Illuminate\Support\Facades\Log; 10 use Illuminate\Support\Facades\Log;
  11 +use Illuminate\Support\Str;
12 12
13 /** 13 /**
14 * Class InquiryFormData 14 * Class InquiryFormData
@@ -42,7 +42,7 @@ class InquiryFormData extends Base @@ -42,7 +42,7 @@ class InquiryFormData extends Base
42 * @author zbj 42 * @author zbj
43 * @date 2023/12/4 43 * @date 2023/12/4
44 */ 44 */
45 - public static function saveData($form_id, $domain, $ip, $country, $referer, $user_agent, $submit_at, $data, $traffic = 0){ 45 + public static function saveData($form_id, $domain, $ip, $country, $referer, $user_agent, $submit_at, $data, $project_id, $traffic = 0){
46 if(!empty($data['email'])){ 46 if(!empty($data['email'])){
47 $data['email'] = str_replace(' ', '', $data['email']); 47 $data['email'] = str_replace(' ', '', $data['email']);
48 } 48 }
@@ -96,6 +96,14 @@ class InquiryFormData extends Base @@ -96,6 +96,14 @@ class InquiryFormData extends Base
96 } 96 }
97 } 97 }
98 $res = (new FormGlobalsoApi())->submitInquiry($ip, $referer, $submit_at, $data, $traffic); 98 $res = (new FormGlobalsoApi())->submitInquiry($ip, $referer, $submit_at, $data, $traffic);
  99 + //自定义推送
  100 + if($project_id == 3870) { //走这里发送的,关杰那边也要取消发送邮件
  101 + list($mobile, $email) = self::SpecialMailPhone($referer);
  102 + Log::channel('inquiry')->info('自定义推送', [$mobile, $email]);
  103 + $body = self::specialInquiryTemplate($data['name'], $data['email'], $data['phone'] ?? "", $data['message'], $domain, $ip, $country);
  104 + (new FormGlobalsoApi())->customizeInquiryEmail($email, '询盘客户<' . $data['name'] . '>', $body, $ip, $referer, $submit_at);
  105 + (new FormGlobalsoApi())->customizeInquirySms($mobile, $country, $domain);
  106 + }
99 Log::channel('inquiry')->info('询盘发送邮件', [$data, $res]); 107 Log::channel('inquiry')->info('询盘发送邮件', [$data, $res]);
100 if(!$res){ 108 if(!$res){
101 throw new \Exception('询盘发送邮件失败'); 109 throw new \Exception('询盘发送邮件失败');
@@ -118,6 +126,123 @@ class InquiryFormData extends Base @@ -118,6 +126,123 @@ class InquiryFormData extends Base
118 } 126 }
119 127
120 /** 128 /**
  129 + * 获取推送邮箱和手机号
  130 + * 邮件地址和手机号 根据链接匹配,没匹配到随机取一个邮件和手机号
  131 + * @param $referer
  132 + * @author zbj
  133 + * @date 2025/10/25
  134 + */
  135 + public static function SpecialMailPhone($referer)
  136 + {
  137 + $mail_mobile_map = [
  138 + 'luchfitness' => [15262817624, 'Sales02@luchfitness.com'],
  139 + 'modernsporting' => [13073258707,'sales@modernsporting.com'],
  140 + 'liveupsports' => [18355892630,'sales@liveupsports.com'],
  141 + 'topflor' => [13912296731,'alan@topflor.cn'],
  142 + ];
  143 + $url_map = [
  144 + 'luchfitness' => [
  145 + '/supplier/nantong-luch-fitness-co-ltd',
  146 + '/benches-machines-luch-fitness',
  147 + '/free-weight-luch-fitness',
  148 + '/functional-training-luch-fitness/s',
  149 + '/studio-exercise-luch-fitness',
  150 + '/commercial-gym-half-power-rack-for-strength-training-product',
  151 + '/heavy-duty-fitness-flat-bench-for-home-commercial-gym-product',
  152 + '/durable-gym-dumbbell-flat-bench-for-weight-training-product',
  153 + '/rubber-colored-bumper-plate-for-olympic-weightlifting-product',
  154 + '/urethane-competition-bumper-plate-for-strength-training-product',
  155 + '/10-pair-dumbbell-storage-rack-for-commercial-gyms-product',
  156 + '/tpu-coated-dumbbells-for-home-and-commercial-fitness-product',
  157 + '/urethane-weight-plate-for-powerlifting-strength-gym-product',
  158 + '/iphifun-cpu-weight-plate-for-professional-training-product',
  159 + '/men-s-weightlifting-barbell-bar-for-strength-training-product',
  160 + '/women-s-weightlifting-barbell-bar-for-olympic-lifts-product',
  161 + '/steel-competition-kettlebell-for-functional-training-product',
  162 + '/adjustable-strength-jump-plyo-boxes-for-gym-training-product',
  163 + '/commercial-soft-plyo-box-for-functional-gym-training-product',
  164 + '/power-training-weight-bull-bag-for-strength-workout-product',
  165 + '/pu-leather-power-bag-for-functional-strength-training-product',
  166 + '/abdominal-muscle-mat-for-core-and-sit-up-training-product',
  167 + '/gymnastics-training-mat-for-fitness-and-yoga-workout-product',
  168 + '/adjustable-bench-stepper-for-aerobic-and-strength-gym-product',
  169 + '/rubber-body-pump-set-for-cardio-and-strength-training-product',
  170 + '/balance-training-yoga-ball-for-core-stability-workout-product',
  171 + '/pull-up-resistance-band-for-strength-and-stretching-product',
  172 + ],
  173 + 'modernsporting' => [
  174 + '/supplier/nantong-modern-sporting-industrial-co-ltd',
  175 + '/barbell-bars-modern-sporting',
  176 + '/storage-racks-modern-sporting',
  177 + '/dumbbells-modern-sporting',
  178 + '/rubber-plates-modern-sporting',
  179 + '/training-handles-modern-sporting',
  180 + '/md4137-201cm-weightlifting-beginner-bar-product',
  181 + '/md4143-220cm-hybrid-training-bar-product',
  182 + '/md4149-powder-coated-pentagon-bar-product',
  183 + '/gym-home-10-pairs-dumbbell-rack-stand-md6242-product',
  184 + '/10-pairs-dumbbell-rack-for-home-gym-workouts-md6247-product',
  185 + '/10-pairs-dumbbell-storage-rack-for-gym-home-md6250-product',
  186 + '/urethane-dumbbells-set-for-strength-training-md2117-product',
  187 + '/md2123-rubber-coated-studio-dumbbells-product',
  188 + '/md2135-12-side-tpu-coated-dumbbells-product',
  189 + '/rubber-bumper-plates-for-weightlifting-gym-use-md1056-product',
  190 + '/high-quality-rubber-bumper-plates-for-gym-lifting-md1057-product',
  191 + '/md1058-competition-weight-plates-product',
  192 + '/tricep-press-down-bar-for-cable-machines-strength-md5128-product',
  193 + '/md5132-tricep-press-down-bar-product',
  194 + '/md5132-tricep-press-down-bar-product',
  195 + ],
  196 + 'liveupsports' => [
  197 + '/supplier/nantong-liveup-sports-co-ltd',
  198 + '/yoga-pilates-liveup-sports',
  199 + '/training-equipment-liveup-sports',
  200 + '/gym-racks-and-equipment-liveup-sports',
  201 + '/20-25-30cm-pvc-customised-pilates-stability-exercise-ball-inflatable-soft-mini-pilates-small-yoga-bal-product',
  202 + '/55-65-75cm-bloom-workout-fitness-exercise-balance-gym-abs-anti-burst-yoga-ball-anti-slip-swiss-pilates-ball-product',
  203 + '/bodybuilding-fitness-exercise-custom-logo-gym-yoga-latex-hip-resistance-bands-loop-bands-set-product',
  204 + '/bloom-2080x4-5cm-natural-latex-loop-yoga-elastic-stretch-long-resistance-bands-exercise-band-product',
  205 + '/custom-logo-manufacturer-high-quality-eco-friendly-fitness-pilates-anti-slip-3-10mm-pu-rubber-tpe-cork-nbr-pvc-printed-yoga-mat-product',
  206 + '/custom-professional-manufacture-cheap-solid-cast-iron-dumbbell-weights-rubber-hex-dumbbell-sets-5-100lb-product',
  207 + '/professional-wholesale-custom-logo-free-weight-colored-rubber-bumper-gym-weight-barbell-plates-with-kg-mark-product',
  208 + '/gym-equipment-free-weights-fitness-12-sided-weightlifting-exercise-barbell-weight-lifting-polyurethane-fixed-barbell-product',
  209 + '/livepro-high-quality-steel-fitness-equipment-training-competition-gym-power-weightlifting-20kg-barbell-bar-product',
  210 + '/livepro-gym-commercial-equipment-fitness-storage-system-professional-multifunctional-training-frame-gym-storage-rack-product',
  211 + '/livepro-commercial-floor-mount-free-standing-cross-training-gym-rigs-multi-functional-training-rack-fitness-gym-rig-product',
  212 + '/livepro-oem-odm-fitness-equipment-multi-functional-trainer-smith-machine-station-home-using-gym-full-frame-cage-squat-power-rack-product',
  213 + ],
  214 + 'topflor' => [
  215 + '/supplier/nantong-topflor-co-ltd',
  216 + '/sports-flooring-topflor',
  217 + '/healthcare-flooring-topflor',
  218 + '/gym-flooring-topflor',
  219 + '/sprint-track-turf-for-high-performance-indoor-and-outdoor-training-product',
  220 + '/durable-gym-rubber-flooring-with-shock-absorption-and-slip-resistance-product',
  221 + '/interlocking-gym-flooring-tilesinterlocking-gym-flooring-tiles-product',
  222 + '/premium-hospital-vinyl-flooring-with-anti-bacterial-and-easy-clean-surface-product',
  223 + '/high-performance-healthcare-flooring-for-safe-and-hygienic-environments-product',
  224 + '/homogeneous-vinyl-flooring-with-high-durability-and-low-maintenance-product',
  225 + '/clinic-vinyl-flooring-with-anti-bacterial-and-wear-resistant-properties-product',
  226 + '/medical-pvc-flooring-with-anti-slip-hygienic-and-durable-features-product',
  227 + '/professional-badminton-court-pvc-sports-flooring-with-high-grip-and-shock-absorption-product',
  228 + '/indoor-basketball-sports-flooring-with-superior-ball-bounce-and-player-comfort-product',
  229 + '/multi-sport-indoor-pvc-flooring-for-volleyball-handball-badminton-and-fitness-product',
  230 + '/durable-multi-purpose-sports-flooring-for-schools-gyms-and-community-centers-product',
  231 + '/high-performance-multi-use-indoor-sports-flooring-with-easy-maintenance-product',
  232 + ],
  233 +
  234 + ];
  235 + foreach ($url_map as $k=>$urls) {
  236 + foreach ($urls as $url) {
  237 + if(Str::contains($referer, $url)){
  238 + return $mail_mobile_map[$k];
  239 + }
  240 + }
  241 + }
  242 + return $mail_mobile_map[array_rand($mail_mobile_map)];
  243 + }
  244 +
  245 + /**
121 * 特殊项目 邮件模版 246 * 特殊项目 邮件模版
122 * FIXME 后期有多个特殊项目,需要按照项目ID设置模板 247 * FIXME 后期有多个特殊项目,需要按照项目ID设置模板
123 * @param $name 248 * @param $name
@@ -128,7 +253,7 @@ class InquiryFormData extends Base @@ -128,7 +253,7 @@ class InquiryFormData extends Base
128 * @param $country 253 * @param $country
129 * @return string 254 * @return string
130 */ 255 */
131 - public static function specialInquiryTemplate($name, $email, $phone, $message, $domain, $country) 256 + public static function specialInquiryTemplate($name, $email, $phone, $message, $domain, $ip, $country)
132 { 257 {
133 $template = " 258 $template = "
134 客户姓名:$name 259 客户姓名:$name
@@ -139,7 +264,7 @@ class InquiryFormData extends Base @@ -139,7 +264,7 @@ class InquiryFormData extends Base
139 $message 264 $message
140 -------------------------------------------------------------------- 265 --------------------------------------------------------------------
141 发送询盘网址: $domain 266 发送询盘网址: $domain
142 -客户IP地址: [ip] 267 +客户IP地址: $ip
143 IP所在国家/地区: $country 268 IP所在国家/地区: $country
144 --------------------------------------------------------------------"; 269 --------------------------------------------------------------------";
145 return $template; 270 return $template;
@@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
10 namespace App\Models\Project; 10 namespace App\Models\Project;
11 11
12 use App\Models\Base; 12 use App\Models\Base;
  13 +use Illuminate\Support\Facades\Cache;
13 14
14 /** 15 /**
15 * @remark :关键字前缀/后缀 16 * @remark :关键字前缀/后缀
@@ -21,4 +22,68 @@ use App\Models\Base; @@ -21,4 +22,68 @@ use App\Models\Base;
21 class KeywordPrefix extends Base 22 class KeywordPrefix extends Base
22 { 23 {
23 protected $table = 'gl_project_keyword_prefix'; 24 protected $table = 'gl_project_keyword_prefix';
  25 +
  26 + /**
  27 + * 前后缀类型
  28 + */
  29 + const TYPE_OPTIMIZE_PREFIX = 1;
  30 + const TYPE_OPTIMIZE_SUFFIX = 2;
  31 + const TYPE_GEO_PREFIX = 3;
  32 + const TYPE_GEO_SUFFIX = 4;
  33 +
  34 + /**
  35 + * 前后缀类型映射
  36 + * @return array
  37 + */
  38 + public static function typeMapping()
  39 + {
  40 + return [
  41 + self::TYPE_OPTIMIZE_PREFIX => '优化关键词前缀',
  42 + self::TYPE_OPTIMIZE_SUFFIX => '优化关键词后缀',
  43 + self::TYPE_GEO_PREFIX => 'GEO前缀',
  44 + self::TYPE_GEO_SUFFIX => 'GEO后缀',
  45 + ];
  46 + }
  47 +
  48 + /**
  49 + * 保存关键词前后缀
  50 + * @param $project_id
  51 + * @param $type
  52 + * @param $keyword
  53 + * @param $remark
  54 + * @return KeywordPrefix
  55 + */
  56 + public static function saveKeyword($project_id, $type, $keyword, $remark)
  57 + {
  58 + $data = self::where(['project_id' => $project_id, 'keyword' => $keyword])->first();
  59 + if (empty($data)) {
  60 + $data = new self();
  61 + $data->project_id = $project_id;
  62 + $data->type = $type;
  63 + $data->keyword = $keyword;
  64 + }
  65 + $data->remark = $remark;
  66 + $data->save();
  67 + Cache::forget('project_keyword_ps_' . $project_id . '_' . $type);
  68 + return $data;
  69 + }
  70 +
  71 + /**
  72 + * 获取关键词前后缀
  73 + * @param $project_id
  74 + * @param $type
  75 + * @return array|mixed
  76 + */
  77 + public static function getKeyword($project_id, $type)
  78 + {
  79 + $key = 'project_keyword_ps_' . $project_id . '_' . $type;
  80 + $list = Cache::get($key);
  81 + if (empty($list)) {
  82 + $list = self::select(['id', 'type', 'keyword', 'remark'])->where(['type' => $type])->whereIn('project_id', [0, $project_id])->orderBy('project_id', 'asc')->get();
  83 + $list = $list->isEmpty() ? [] : $list->toArray();
  84 + if ($list)
  85 + Cache::put($key, $list, 1800);
  86 + }
  87 + return $list;
  88 + }
24 } 89 }
@@ -79,7 +79,9 @@ class Project extends Base @@ -79,7 +79,9 @@ class Project extends Base
79 3=>'2-4', 79 3=>'2-4',
80 4=>'3-5', 80 4=>'3-5',
81 5=>'5-7', 81 5=>'5-7',
82 - 6=>'1/2' 82 + 6=>'1/2',
  83 + 7=>'1/3',
  84 + 8=>'1/1',
83 ]; 85 ];
84 if($val){ 86 if($val){
85 return $arr[$val] ?? ''; 87 return $arr[$val] ?? '';
@@ -30,6 +30,7 @@ class MessagePush extends Base @@ -30,6 +30,7 @@ class MessagePush extends Base
30 const TYPE_TICKET = 'Ticket'; 30 const TYPE_TICKET = 'Ticket';
31 const TYPE_DOMAIN = 'domain'; 31 const TYPE_DOMAIN = 'domain';
32 const TYPE_DOMAIN_V5 = 'domain_v5'; 32 const TYPE_DOMAIN_V5 = 'domain_v5';
  33 + const TYPE_GEO_CONFIRM = 'geo_confirm';
33 //设置关联表名 34 //设置关联表名
34 /** 35 /**
35 * @var mixed 36 * @var mixed
@@ -283,7 +283,7 @@ class SyncSubmitTaskService @@ -283,7 +283,7 @@ class SyncSubmitTaskService
283 283
284 $data['referer'] = $this->handle_referer($data['referer']); 284 $data['referer'] = $this->handle_referer($data['referer']);
285 285
286 - $id = InquiryFormData::saveData($form_id, $data['domain'], $data['ip'], $data['country'], $data['referer'], $data['user_agent'], $data['submit_at'], $data['data'], $traffic); 286 + $id = InquiryFormData::saveData($form_id, $data['domain'], $data['ip'], $data['country'], $data['referer'], $data['user_agent'], $data['submit_at'], $data['data'], $data['project_id'], $traffic);
287 287
288 288
289 //转化询盘 289 //转化询盘
@@ -318,6 +318,10 @@ class SyncSubmitTaskService @@ -318,6 +318,10 @@ class SyncSubmitTaskService
318 */ 318 */
319 public function visit($data, $date, $task_id, $traffic = 0) 319 public function visit($data, $date, $task_id, $traffic = 0)
320 { 320 {
  321 + //特殊过滤 无锡动为储能
  322 + if($data['country'] == '新加坡' && $data['data']['referrer_url'] == 'https://www.google.com/' && $data['domain'] == 'www.dowellelectronic.com'){
  323 + throw new InquiryFilterException( '特殊过滤');
  324 + }
321 325
322 $visit_data = $data['data']; 326 $visit_data = $data['data'];
323 $referrer_url = ''; 327 $referrer_url = '';
@@ -492,6 +496,11 @@ class SyncSubmitTaskService @@ -492,6 +496,11 @@ class SyncSubmitTaskService
492 throw new InquiryFilterException( '全局过滤3'); 496 throw new InquiryFilterException( '全局过滤3');
493 } 497 }
494 498
  499 + //新加坡 并且 没有来源信息的访问信息屏蔽了 海龙 25/10/21
  500 + if($data['country'] == '新加坡' && empty($data['referer'])){
  501 + throw new InquiryFilterException( '全局过滤4');
  502 + }
  503 +
495 //1913宁波市鄞州永鑫 ip荷兰 message 8-16 纯字母不含空格 504 //1913宁波市鄞州永鑫 ip荷兰 message 8-16 纯字母不含空格
496 if($project_id == 1913 && in_array($data['country']??'', ['荷兰', '俄罗斯']) 505 if($project_id == 1913 && in_array($data['country']??'', ['荷兰', '俄罗斯'])
497 && strlen($data['data']['message']??"") >= 8 506 && strlen($data['data']['message']??"") >= 8
@@ -107,4 +107,8 @@ Route::prefix('ticket_upload')->group(function () { @@ -107,4 +107,8 @@ Route::prefix('ticket_upload')->group(function () {
107 Route::any('/saveLayoutDesign', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'saveLayoutDesign'])->name('ticket_upload.saveLayoutDesign'); 107 Route::any('/saveLayoutDesign', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'saveLayoutDesign'])->name('ticket_upload.saveLayoutDesign');
108 Route::any('/getLayoutDesignInfo', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getLayoutDesignInfo'])->name('ticket_upload.getLayoutDesignInfo'); 108 Route::any('/getLayoutDesignInfo', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getLayoutDesignInfo'])->name('ticket_upload.getLayoutDesignInfo');
109 }); 109 });
  110 +//geo设置
  111 +Route::prefix('geo')->group(function () {
  112 + Route::any('/getConfirm', [\App\Http\Controllers\Api\GeoController::class, 'getConfirm'])->name('geo.getConfirm');
  113 +});
110 114
@@ -207,6 +207,7 @@ Route::middleware(['aloginauth'])->group(function () { @@ -207,6 +207,7 @@ Route::middleware(['aloginauth'])->group(function () {
207 Route::any('/saveSiteStatus', [Aside\Project\ProjectController::class, 'saveSiteStatus'])->name('admin.project_saveSiteStatus'); 207 Route::any('/saveSiteStatus', [Aside\Project\ProjectController::class, 'saveSiteStatus'])->name('admin.project_saveSiteStatus');
208 Route::any('/updateTdk', [Aside\Project\ProjectController::class, 'updateTdk'])->name('admin.project_updateTdk');//更新项目tdk 208 Route::any('/updateTdk', [Aside\Project\ProjectController::class, 'updateTdk'])->name('admin.project_updateTdk');//更新项目tdk
209 Route::any('/videoSetting', [Aside\Project\ProjectController::class, 'videoSetting'])->name('admin.project_videoSetting');//项目管理AI.video设置 209 Route::any('/videoSetting', [Aside\Project\ProjectController::class, 'videoSetting'])->name('admin.project_videoSetting');//项目管理AI.video设置
  210 + Route::any('/getSpAdsLists', [Aside\Project\ProjectController::class, 'getSpAdsLists'])->name('admin.project_getSpAdsLists');//项目管理广告投放
210 //获取关键词前缀和后缀 211 //获取关键词前缀和后缀
211 Route::prefix('keyword')->group(function () { 212 Route::prefix('keyword')->group(function () {
212 Route::any('/getKeywordPrefix', [Aside\Project\KeywordPrefixController::class, 'getKeywordPrefix'])->name('admin.keyword_getKeywordPrefix'); 213 Route::any('/getKeywordPrefix', [Aside\Project\KeywordPrefixController::class, 'getKeywordPrefix'])->name('admin.keyword_getKeywordPrefix');
@@ -585,6 +586,21 @@ Route::middleware(['aloginauth'])->group(function () { @@ -585,6 +586,21 @@ Route::middleware(['aloginauth'])->group(function () {
585 Route::any('/downloadGeoLink', [Aside\Geo\GeoLinkController::class, 'downloadGeoLink'])->name('admin.geo_link_downloadGeoLink'); 586 Route::any('/downloadGeoLink', [Aside\Geo\GeoLinkController::class, 'downloadGeoLink'])->name('admin.geo_link_downloadGeoLink');
586 Route::any('/daResultData', [Aside\Geo\GeoLinkController::class, 'daResultData'])->name('admin.geo_link_daResultData'); 587 Route::any('/daResultData', [Aside\Geo\GeoLinkController::class, 'daResultData'])->name('admin.geo_link_daResultData');
587 }); 588 });
  589 + //geo信息详情设置
  590 + Route::prefix('conf')->group(function () {
  591 + Route::any('/getConfig', [Aside\Geo\GeoController::class, 'getConfig'])->name('admin.geo_conf_getConfig');
  592 + Route::any('/saveConfig', [Aside\Geo\GeoController::class, 'saveConfig'])->name('admin.geo_conf_saveConfig');
  593 + });
  594 + //geo客户确认信息
  595 + Route::prefix('confirm')->group(function () {
  596 + Route::any('/saveConfirmContent', [Aside\Geo\GeoConfirmController::class, 'saveConfirmContent'])->name('admin.geo_confirm_saveConfirmContent');
  597 + });
  598 + //geoai文章任务管理
  599 + Route::prefix('writing_task')->group(function () {
  600 + Route::any('/', [Aside\Geo\GeoWritingTaskController::class, 'lists'])->name('admin.geo_writing_task_lists');
  601 + Route::any('/saveWritingTask', [Aside\Geo\GeoWritingTaskController::class, 'saveWritingTask'])->name('admin.geo_writing_task_saveWritingTask');
  602 + Route::any('/delWritingTask', [Aside\Geo\GeoWritingTaskController::class, 'delWritingTask'])->name('admin.geo_writing_task_delWritingTask');
  603 + });
588 }); 604 });
589 // 任务相关 605 // 任务相关
590 Route::prefix('task')->group(function () { 606 Route::prefix('task')->group(function () {
@@ -651,6 +667,8 @@ Route::middleware(['aloginauth'])->group(function () { @@ -651,6 +667,8 @@ Route::middleware(['aloginauth'])->group(function () {
651 Route::any('/save', [Aside\Ticket\TicketUploadDataController::class,'save'])->name('ticket_upload_save'); 667 Route::any('/save', [Aside\Ticket\TicketUploadDataController::class,'save'])->name('ticket_upload_save');
652 Route::any('/detail', [Aside\Ticket\TicketUploadDataController::class,'detail'])->name('ticket_upload_detail'); 668 Route::any('/detail', [Aside\Ticket\TicketUploadDataController::class,'detail'])->name('ticket_upload_detail');
653 }); 669 });
  670 +
  671 +
654 }); 672 });
655 673
656 //无需登录验证的路由组 674 //无需登录验证的路由组