作者 赵彬吉
@@ -43,7 +43,7 @@ class RemainDay extends Command @@ -43,7 +43,7 @@ class RemainDay extends Command
43 * @var 暂停的项目 43 * @var 暂停的项目
44 */ 44 */
45 protected $ceaseProjectId = [ 45 protected $ceaseProjectId = [
46 - 354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250, 2193, 2399, 1685, 3931,2273,3647 46 + 354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250, 2193, 2399, 1685, 3931,2273,3647,1934
47 ];//需要单独处理的项目 47 ];//需要单独处理的项目
48 /** 48 /**
49 * The console command description. 49 * The console command description.
@@ -63,7 +63,7 @@ class GeoQuestionRes extends Command @@ -63,7 +63,7 @@ class GeoQuestionRes extends Command
63 $geoQuestionModel->edit(['status'=>$geoQuestionModel::STATUS_CLOSE],['id'=>$task_id]); 63 $geoQuestionModel->edit(['status'=>$geoQuestionModel::STATUS_CLOSE],['id'=>$task_id]);
64 continue; 64 continue;
65 } 65 }
66 - if(empty($taskInfo['question']) || ($taskInfo['project_id'] != 4533) || (empty($taskInfo['keywords']) && empty($taskInfo['url']) && empty($taskInfo['expect_result']))){ 66 + if(empty($taskInfo['question']) || (empty($taskInfo['keywords']) && empty($taskInfo['url']) && empty($taskInfo['expect_result']))){
67 $this->output('task id: ' . $task_id . ', error: 任务数据缺失, continue!'); 67 $this->output('task id: ' . $task_id . ', error: 任务数据缺失, continue!');
68 $geoQuestionModel->edit(['status'=>$geoQuestionModel::STATUS_CLOSE],['id'=>$task_id]); 68 $geoQuestionModel->edit(['status'=>$geoQuestionModel::STATUS_CLOSE],['id'=>$task_id]);
69 continue; 69 continue;
@@ -337,13 +337,14 @@ class GeoQuestionRes extends Command @@ -337,13 +337,14 @@ class GeoQuestionRes extends Command
337 $key = 'geo_task_list'; 337 $key = 'geo_task_list';
338 $task_id = Redis::rpop($key); 338 $task_id = Redis::rpop($key);
339 if(empty($task_id)){ 339 if(empty($task_id)){
340 - $questionModel = new GeoQuestion();  
341 - $ids = $questionModel->selectField(['status'=>$questionModel::STATUS_OPEN,'next_time'=>['<=',date('Y-m-d')]],'id');  
342 - if(!empty($ids)){ 340 + # TODO 按照项目进行获取, 一个项目当天需要将所有跑完
  341 + $project_id = GeoQuestion::where('status', GeoQuestion::STATUS_OPEN)->where('next_time', '<=', date('Y-m-d'))->value('project_id');
  342 + if (empty($project_id))
  343 + return $task_id;
  344 + $ids = GeoQuestion::where(['project_id' => $project_id, 'status' => GeoQuestion::STATUS_OPEN])->where('current_time', '<>', date('Y-m-d'))->pluck('id');
343 foreach ($ids as $id) { 345 foreach ($ids as $id) {
344 Redis::lpush($key, $id); 346 Redis::lpush($key, $id);
345 } 347 }
346 - }  
347 $task_id = Redis::rpop($key); 348 $task_id = Redis::rpop($key);
348 } 349 }
349 return $task_id; 350 return $task_id;
@@ -8,9 +8,15 @@ @@ -8,9 +8,15 @@
8 8
9 namespace App\Console\Commands\Inquiry; 9 namespace App\Console\Commands\Inquiry;
10 10
  11 +use App\Helper\Arr;
  12 +use App\Helper\Common;
  13 +use App\Helper\Gpt;
11 use App\Helper\Translate; 14 use App\Helper\Translate;
12 use App\Helper\Validate; 15 use App\Helper\Validate;
  16 +use App\Http\Logic\Aside\Optimize\InquiryForwardLogic;
  17 +use App\Models\Ai\AiCommand;
13 use App\Models\Inquiry\InquiryInfo; 18 use App\Models\Inquiry\InquiryInfo;
  19 +use App\Models\Inquiry\InquiryRelayAi;
14 use App\Models\Project\InquiryFilterConfig; 20 use App\Models\Project\InquiryFilterConfig;
15 use App\Models\Project\Project; 21 use App\Models\Project\Project;
16 use App\Services\InquiryRelayService; 22 use App\Services\InquiryRelayService;
@@ -221,7 +227,65 @@ class SyncInquiryRelay extends Command @@ -221,7 +227,65 @@ class SyncInquiryRelay extends Command
221 $remark = $this->inquiryFilter($unique_sign, $country, $data['ip'], $data['message'], $data['refer'], $data['email'], $data['phone'], $data['name']); 227 $remark = $this->inquiryFilter($unique_sign, $country, $data['ip'], $data['message'], $data['refer'], $data['email'], $data['phone'], $data['name']);
222 $status = $remark ? InquiryInfo::STATUS_INVALID : InquiryInfo::STATUS_INIT; 228 $status = $remark ? InquiryInfo::STATUS_INVALID : InquiryInfo::STATUS_INIT;
223 229
224 - $model->createInquiry($data['name'], $data['phone'], $data['email'], $data['ip'], $country, $data['message'], $message_cn, $type, $data['time'], $data['refer'], $data['title'], $keywords, $message_sign, $data['origin_key'], $data['image'], $email_status, $phone_status, $unique_sign, $status, $remark); 230 + $form_id = $model->createInquiry($data['name'], $data['phone'], $data['email'], $data['ip'], $country, $data['message'], $message_cn, $type, $data['time'], $data['refer'], $data['title'], $keywords, $message_sign, $data['origin_key'], $data['image'], $email_status, $phone_status, $unique_sign, $status, $remark);
  231 +
  232 + if ($form_id && $status == InquiryInfo::STATUS_INIT) {
  233 + $inquiry_ai_info = InquiryRelayAi::where('form_id', $form_id)->first();
  234 + if (!$inquiry_ai_info) {
  235 + //AI匹配询盘关键词
  236 + $ai_info = AiCommand::select(['ai'])->where('key', 'inquiry_keyword_extract')->first();
  237 + if (!$ai_info) {
  238 + $this->output('AI重写指令[inquiry_keyword_extract]未配置');
  239 + return true;
  240 + }
  241 +
  242 + $ai_command = $ai_info['ai'];
  243 + $ai_command = str_replace('{title}', $data['title'], $ai_command);
  244 + $ai_command = str_replace('{keywords}', $keywords, $ai_command);
  245 + $ai_command = str_replace('{content}', $data['message'], $ai_command);
  246 + $ai_keyword = Common::deal_str(Gpt::instance()->openai_chat_qqs($ai_command));
  247 + if (!$ai_keyword) {
  248 + $this->output('询盘ID:' . $form_id . ',AI提取询盘关键词失败');
  249 + return true;
  250 + }
  251 +
  252 + //关键词查询项目着陆页:先精准匹配,没有数据再全文索引匹配
  253 + $inquiryForwardLogic = new InquiryForwardLogic();
  254 + $forward_list = $inquiryForwardLogic->searchKeywords($ai_keyword, 2, 3);
  255 + if (count($forward_list) < 3) {
  256 + $forward_list_against = $inquiryForwardLogic->searchKeywords($ai_keyword, 1, 3 - count($forward_list));
  257 + foreach ($forward_list_against as $against) {
  258 + array_push($forward_list, $against);
  259 + }
  260 + }
  261 + if (empty($forward_list)) {
  262 + $this->output('询盘ID:' . $form_id . ',根据关键词[' . $ai_keyword . ']查询项目着陆页为空');
  263 + return true;
  264 + }
  265 +
  266 + //重写询盘内容
  267 + $ai_message_list = [];
  268 + for ($i = 0; $i < count($forward_list); $i++) {
  269 + $message_re = $inquiryForwardLogic->aiRewrite($data['message'], $data['title'], $keywords);
  270 + if (isset($message_re['ai_message']) && $message_re['ai_message']) {
  271 + $ai_message_list[] = $message_re['ai_message'];
  272 + }
  273 + }
  274 + if (empty($ai_message_list)) {
  275 + $this->output('询盘ID:' . $form_id . ',AI重写询盘内容失败');
  276 + return true;
  277 + }
  278 +
  279 +
  280 + $inquiry_ai_info = new InquiryRelayAi();
  281 + $inquiry_ai_info->form_id = $form_id;
  282 + $inquiry_ai_info->keywords = $ai_keyword;
  283 + $inquiry_ai_info->forward_url = Arr::a2s($forward_list);
  284 + $inquiry_ai_info->message_ai = Arr::a2s($ai_message_list);
  285 + $inquiry_ai_info->save();
  286 + }
  287 + }
  288 +
225 return true; 289 return true;
226 } 290 }
227 291
@@ -11,6 +11,7 @@ namespace App\Console\Commands\LyhTest; @@ -11,6 +11,7 @@ namespace App\Console\Commands\LyhTest;
11 11
12 use App\Helper\OaGlobalsoApi; 12 use App\Helper\OaGlobalsoApi;
13 use App\Models\Ai\AiBlog; 13 use App\Models\Ai\AiBlog;
  14 +use App\Models\Geo\GeoLink;
14 use App\Models\News\News; 15 use App\Models\News\News;
15 use App\Models\Product\Category; 16 use App\Models\Product\Category;
16 use App\Models\Project\AggregateKeywordAffix; 17 use App\Models\Project\AggregateKeywordAffix;
@@ -35,6 +36,7 @@ use App\Services\Geo\GeoService; @@ -35,6 +36,7 @@ use App\Services\Geo\GeoService;
35 use App\Services\MidJourneyService; 36 use App\Services\MidJourneyService;
36 use App\Services\ProjectServer; 37 use App\Services\ProjectServer;
37 use Illuminate\Console\Command; 38 use Illuminate\Console\Command;
  39 +use Illuminate\Support\Carbon;
38 use Illuminate\Support\Facades\DB; 40 use Illuminate\Support\Facades\DB;
39 41
40 class lyhDemo extends Command 42 class lyhDemo extends Command
@@ -57,6 +59,51 @@ class lyhDemo extends Command @@ -57,6 +59,51 @@ class lyhDemo extends Command
57 return $this->translate_action(); 59 return $this->translate_action();
58 } 60 }
59 61
  62 + public function _actionDa()
  63 + {
  64 + $geoLinkModel = new GeoLink();
  65 + $lists = $geoLinkModel->list(['da'=>0,'time'=>null]);
  66 + $geoService = new GeoService();
  67 + foreach ($lists as $info){
  68 + if(!empty($info['time'])){
  69 + $start = Carbon::parse($info['time']);
  70 + $end = Carbon::parse(date('Y-m-d'));
  71 + $diff = $start->diffInDays($end);
  72 + if($diff >= 60){
  73 + $host = $this->getDomainWithWWW($info['url']);
  74 + $result = $geoService->daResult($host);
  75 + }else{
  76 + continue;
  77 + }
  78 + }else{
  79 + $host = $this->getDomainWithWWW($info['url']);
  80 + $result = $geoService->daResult($host);
  81 + }
  82 + if(!isset($result['data']) || empty($result['data'])){
  83 + $this->model->edit(['time'=>date('Y-m-d')], ['id'=>$info['id']]);
  84 + continue;
  85 + }
  86 + $info['da'] = (int)$result['data']['mozDA'];//获取数据中的da值
  87 + $this->model->edit(['time'=>date('Y-m-d'),'da'=>$info['da']], ['id'=>$info['id']]);
  88 + }
  89 + }
  90 +
  91 + public function getDomainWithWWW($url) {
  92 + // 获取 host
  93 + $host = parse_url($url, PHP_URL_HOST);
  94 + // 去掉端口号等情况
  95 + $host = preg_replace('/:\d+$/', '', $host);
  96 + // 分割域名
  97 + $parts = explode('.', $host);
  98 + // 判断是几段
  99 + $count = count($parts);
  100 + // 如果只有两段,比如 fox8.com、theamericawatch.com,就拼接 www.
  101 + if ($count === 2) {
  102 + return 'www.' . $host;
  103 + }
  104 + return $host;
  105 + }
  106 +
60 /** 107 /**
61 * @remark :查看路由是否为空 108 * @remark :查看路由是否为空
62 * @name :_actionRoute 109 * @name :_actionRoute
@@ -54,7 +54,7 @@ class ExternalLinkMake extends Command @@ -54,7 +54,7 @@ class ExternalLinkMake extends Command
54 continue; 54 continue;
55 } 55 }
56 56
57 - $yesterday = RankDataLog::where(['project_id' => $project->id, 'date' => date('Y-m-d', '-1 day')])->first(); 57 + $yesterday = RankDataLog::where(['project_id' => $project->id, 'date' => date('Y-m-d', strtotime('-1 day'))])->first();
58 if (FALSE == empty($yesterday) && $yesterday->is_compliance == 1){ 58 if (FALSE == empty($yesterday) && $yesterday->is_compliance == 1){
59 $this->output('项目昨日达标: ' . $project->id . ', 跳过'); 59 $this->output('项目昨日达标: ' . $project->id . ', 跳过');
60 continue; 60 continue;
@@ -33,10 +33,11 @@ class SyncImage extends Command @@ -33,10 +33,11 @@ class SyncImage extends Command
33 33
34 34
35 // public function handle(){ 35 // public function handle(){
36 -// $str = $this->getProjectConfig(1808); 36 +// $str = $this->getProjectConfig(4240);
37 // $imageModel = new Image(); 37 // $imageModel = new Image();
38 -// $str_image = '/upload/p/1808/image_product/2024-09/ppp.png,/upload/p/1808/image_product/2024-09/86e4866b-7432-40c1-8c06-d335cd736e29.png,/upload/p/1808/image_product/2024-09/7fd109cc-56f4-457c-a9c4-c3fa8d8195b2.png,/upload/p/1808/image_product/2024-09/1.png,/upload/p/1808/image_product/2024-08/bxb12501-3-1.png,/upload/p/1808/image_product/2024-08/bxa10801-3-1.png,/upload/p/1808/image_product/2024-08/bxa007-3-1.png,/upload/p/1808/image_product/2024-08/auto-parts-rectifier-bxf1070-for-alternator-1-1.png,/upload/p/1808/image_product/2024-08/auto-parts-rectifier-bxd1102-for-alternator-2-1.png,/upload/p/1808/image_product/2024-08/11407-3-1.png,/upload/p/1808/image_product/2024-07/gfjty.jpg,/upload/p/1808/image_product/2024-07/bxn11508-g1-2.png,/upload/p/1808/image_product/2024-07/bxn11508-g1-1.png,/upload/p/1808/image_product/2024-07/bxb12501-2.png,/upload/p/1808/image_product/2024-07/bxb12501-1.png,/upload/p/1808/image_product/2024-07/bxb1209-2.png,/upload/p/1808/image_product/2024-07/bxb1209-1.png,/upload/p/1808/image_product/2024-07/bxa10801-2.png,/upload/p/1808/image_product/2024-07/bxa10801-1.png,/upload/p/1808/image_product/2024-07/bxa007-2.png,/upload/p/1808/image_product/2024-07/bxa007-1.png,/upload/p/1808/image_product/2024-07/auto-parts-rectifier-bxf6102-for-alternator-2.png,/upload/p/1808/image_product/2024-07/auto-parts-rectifier-bxf1070-for-alternator-3.png,/upload/p/1808/image_product/2024-07/auto-parts-rectifier-bxf1070-for-alternator-2.png,/upload/p/1808/image_product/2024-07/auto-parts-rectifier-bxd9410-for-alternator-1.png,/upload/p/1808/image_product/2024-07/auto-parts-rectifier-bxd1102-for-alternator-3.png,/upload/p/1808/image_product/2024-07/auto-parts-rectifier-bxd1102-for-alternator-1.png,/upload/p/1808/image_product/2024-07/auto-parts-rectifier-bxb12807-for-alternator-2.png,/upload/p/1808/image_product/2024-07/auto-parts-rectifier-bxb12807-for-alternator-1.png,/upload/p/1808/image_product/2024-07/11407-2.png,/upload/p/1808/image_product/2024-07/11407-1.png';  
39 -// $lists = explode(',',$str_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'=>4240],'path');
  40 +// $lists = explode(',',$strImage);
40 // $domain = 'http://globalso-v6-1309677403.cos.ap-hongkong.myqcloud.com';//cos域名 41 // $domain = 'http://globalso-v6-1309677403.cos.ap-hongkong.myqcloud.com';//cos域名
41 // foreach ($lists as $v){ 42 // foreach ($lists as $v){
42 // $url = $domain . $v.'?'.$str; 43 // $url = $domain . $v.'?'.$str;
@@ -51,7 +52,7 @@ class SyncImage extends Command @@ -51,7 +52,7 @@ class SyncImage extends Command
51 $data = []; 52 $data = [];
52 $domain = 'https://ecdn6.globalso.com/'; 53 $domain = 'https://ecdn6.globalso.com/';
53 $imageModel = new Image(); 54 $imageModel = new Image();
54 - $lists = $imageModel->list(['project_id'=>1808]); 55 + $lists = $imageModel->list(['project_id'=>4240]);
55 foreach ($lists as $k => $v){ 56 foreach ($lists as $k => $v){
56 $url = $domain . $v['path']; 57 $url = $domain . $v['path'];
57 echo date('Y-m-d H:i:s') . '刷新路径:'. $url .',主键id:'. $v['id'] . PHP_EOL; 58 echo date('Y-m-d H:i:s') . '刷新路径:'. $url .',主键id:'. $v['id'] . PHP_EOL;
@@ -3,13 +3,19 @@ @@ -3,13 +3,19 @@
3 namespace App\Console\Commands\Test; 3 namespace App\Console\Commands\Test;
4 4
5 use App\Helper\Arr; 5 use App\Helper\Arr;
  6 +use App\Helper\Common;
  7 +use App\Helper\Gpt;
  8 +use App\Http\Logic\Aside\Optimize\InquiryForwardLogic;
6 use App\Http\Logic\Bside\Product\CategoryLogic; 9 use App\Http\Logic\Bside\Product\CategoryLogic;
  10 +use App\Models\Ai\AiCommand;
7 use App\Models\Com\Notify; 11 use App\Models\Com\Notify;
8 use App\Models\CustomModule\CustomModuleContent; 12 use App\Models\CustomModule\CustomModuleContent;
9 use App\Models\Devops\ServerConfig; 13 use App\Models\Devops\ServerConfig;
10 use App\Models\Devops\ServersIp; 14 use App\Models\Devops\ServersIp;
11 use App\Models\Domain\DomainCreateTask; 15 use App\Models\Domain\DomainCreateTask;
12 use App\Models\Domain\DomainInfo; 16 use App\Models\Domain\DomainInfo;
  17 +use App\Models\Inquiry\InquiryInfo;
  18 +use App\Models\Inquiry\InquiryRelayAi;
13 use App\Models\Product\Category; 19 use App\Models\Product\Category;
14 use App\Models\Product\CategoryRelated; 20 use App\Models\Product\CategoryRelated;
15 use App\Models\Product\Keyword; 21 use App\Models\Product\Keyword;
@@ -43,7 +49,81 @@ class Temp extends Command @@ -43,7 +49,81 @@ class Temp extends Command
43 49
44 public function handle() 50 public function handle()
45 { 51 {
  52 + $this->inquiryAiCheck(17259, 27468);
  53 + }
46 54
  55 + /**
  56 + * AI预处理询盘
  57 + * @param $start_id
  58 + * @param $end_id
  59 + * @return bool
  60 + * @author Akun
  61 + * @date 2025/10/10 15:45
  62 + */
  63 + public function inquiryAiCheck($start_id, $end_id)
  64 + {
  65 + //AI匹配询盘关键词
  66 + $ai_info = AiCommand::select(['ai'])->where('key', 'inquiry_keyword_extract')->first();
  67 + if (!$ai_info) {
  68 + $this->output('AI重写指令[inquiry_keyword_extract]未配置');
  69 + return true;
  70 + }
  71 +
  72 + InquiryInfo::select(['id', 'message', 'url_title', 'url_keyword'])->whereBetween('id', [$start_id, $end_id])->where('status', InquiryInfo::STATUS_INIT)->chunk(100, function ($inquiries) use ($ai_info) {
  73 + foreach ($inquiries as $inquiry) {
  74 + $inquiry_ai_info = InquiryRelayAi::where('form_id', $inquiry['id'])->first();
  75 + if (!$inquiry_ai_info) {
  76 +
  77 + $ai_command = $ai_info['ai'];
  78 + $ai_command = str_replace('{title}', $inquiry['url_title'], $ai_command);
  79 + $ai_command = str_replace('{keywords}', $inquiry['url_keyword'], $ai_command);
  80 + $ai_command = str_replace('{content}', $inquiry['message'], $ai_command);
  81 + $ai_keyword = Common::deal_str(Gpt::instance()->openai_chat_qqs($ai_command));
  82 + if (!$ai_keyword) {
  83 + $this->output('询盘ID:' . $inquiry['id'] . ',AI提取询盘关键词失败');
  84 + continue;
  85 + }
  86 +
  87 + //关键词查询项目着陆页:先精准匹配,没有数据再全文索引匹配
  88 + $inquiryForwardLogic = new InquiryForwardLogic();
  89 + $forward_list = $inquiryForwardLogic->searchKeywords($ai_keyword, 2, 3);
  90 + if (count($forward_list) < 3) {
  91 + $forward_list_against = $inquiryForwardLogic->searchKeywords($ai_keyword, 1, 3 - count($forward_list));
  92 + foreach ($forward_list_against as $against) {
  93 + array_push($forward_list, $against);
  94 + }
  95 + }
  96 + if (empty($forward_list)) {
  97 + $this->output('询盘ID:' . $inquiry['id'] . ',根据关键词[' . $ai_keyword . ']查询项目着陆页为空');
  98 + continue;
  99 + }
  100 +
  101 + //重写询盘内容
  102 + $ai_message_list = [];
  103 + for ($i = 0; $i < count($forward_list); $i++) {
  104 + $message_re = $inquiryForwardLogic->aiRewrite($inquiry['message'], $inquiry['url_title'], $inquiry['url_keyword']);
  105 + if (isset($message_re['ai_message']) && $message_re['ai_message']) {
  106 + $ai_message_list[] = $message_re['ai_message'];
  107 + }
  108 + }
  109 + if (empty($ai_message_list)) {
  110 + $this->output('询盘ID:' . $inquiry['id'] . ',AI重写询盘内容失败');
  111 + continue;
  112 + }
  113 +
  114 + $inquiry_ai_info = new InquiryRelayAi();
  115 + $inquiry_ai_info->form_id = $inquiry['id'];
  116 + $inquiry_ai_info->keywords = $ai_keyword;
  117 + $inquiry_ai_info->forward_url = Arr::a2s($forward_list);
  118 + $inquiry_ai_info->message_ai = Arr::a2s($ai_message_list);
  119 + $inquiry_ai_info->save();
  120 +
  121 + $this->output('询盘ID:' . $inquiry['id'] . ',success');
  122 + }
  123 + }
  124 + });
  125 +
  126 + return true;
47 } 127 }
48 128
49 /** 129 /**
@@ -15,6 +15,7 @@ use App\Models\Blog\BlogCategory; @@ -15,6 +15,7 @@ use App\Models\Blog\BlogCategory;
15 use App\Models\News\NewsCategory; 15 use App\Models\News\NewsCategory;
16 use App\Models\Product\Category; 16 use App\Models\Product\Category;
17 use App\Models\Product\Keyword; 17 use App\Models\Product\Keyword;
  18 +use App\Models\RouteMap\RouteMap;
18 use App\Models\Ticket\TicketUploadData; 19 use App\Models\Ticket\TicketUploadData;
19 use App\Services\ProjectServer; 20 use App\Services\ProjectServer;
20 use Illuminate\Http\Request; 21 use Illuminate\Http\Request;
@@ -167,6 +168,12 @@ class TicketUploadDataController extends BaseController @@ -167,6 +168,12 @@ class TicketUploadDataController extends BaseController
167 'type.required' => '上传类型不能为空', 168 'type.required' => '上传类型不能为空',
168 'text' => '数据详情不为空' 169 'text' => '数据详情不为空'
169 ]); 170 ]);
  171 + if(empty($this->param['text']['image'])){
  172 + $this->response('参数错误',Code::SYSTEM_ERROR);
  173 + }
  174 + if(empty($this->param['text']['title'])){
  175 + $this->response('参数错误,标题不能为空',Code::SYSTEM_ERROR);
  176 + }
170 //验证当前数据是否已提交 177 //验证当前数据是否已提交
171 $this->param['text'] = json_encode($this->param['text'], true); 178 $this->param['text'] = json_encode($this->param['text'], true);
172 if(isset($this->param['id']) && !empty($this->param['id'])){ 179 if(isset($this->param['id']) && !empty($this->param['id'])){
@@ -202,20 +209,38 @@ class TicketUploadDataController extends BaseController @@ -202,20 +209,38 @@ class TicketUploadDataController extends BaseController
202 $this->request->validate([ 209 $this->request->validate([
203 'project_id' => 'required', 210 'project_id' => 'required',
204 'type' => 'required', 211 'type' => 'required',
205 - 'search' => 'required'  
206 ], [ 212 ], [
207 'project_id.required' => 'project_id不能为空', 213 'project_id.required' => 'project_id不能为空',
208 'type.required' => 'type不能为空', 214 'type.required' => 'type不能为空',
209 - 'search.required' => '搜索参数不能为空',  
210 ]); 215 ]);
211 - ProjectServer::useProject($this->param['project_id']);  
212 - if ($this->param['type'] == 1) { 216 + ProjectServer::useProject($this->map['project_id']);
  217 + if ($this->map['type'] == 1) {
213 //todo::搜索获取分类 218 //todo::搜索获取分类
214 $productCateModel = new Category(); 219 $productCateModel = new Category();
215 - $data = $productCateModel->lists(['title' => ['like','%' . $this->param['search'] . '%']], 1, 20,'id',['id','title as name']); 220 + if(!empty($this->map['search']) && isset($this->map['search'])){
  221 + $this->map['name'] = ['like' , '%' . $this->map['search'] . '%'];
  222 + unset($this->param['search']);
  223 + }
  224 + unset($this->map['type']);
  225 + $cate_list = $productCateModel->list($this->map, 'sort',['id','title','pid']);
  226 + if ($cate_list === false) {
  227 + $this->response('无分类');
  228 + }
  229 + $data = [];
  230 + foreach ($cate_list as $v) {
  231 + $v = (array)$v;
  232 + if ($v['pid'] == 0) {
  233 + $v['sub'] = _get_child($v['id'], $cate_list);
  234 + $data[] = $v;
  235 + }
  236 + }
216 } else { 237 } else {
217 $keywordModel = new Keyword(); 238 $keywordModel = new Keyword();
218 - $data = $keywordModel->lists(['title' => ['like','%' . $this->param['search'] . '%']], 1, 20,'id',['id','title as name']); 239 + if(!isset($this->map['search']) || empty($this->map['search'])){
  240 + $data = $keywordModel->lists([], 1, 20,'id',['id','title as name']);
  241 + }else{
  242 + $data = $keywordModel->lists(['title' => ['like','%' . $this->map['search'] . '%']], 1, 20,'id',['id','title as name']);
  243 + }
219 } 244 }
220 DB::disconnect('custom_mysql'); 245 DB::disconnect('custom_mysql');
221 $this->response('success', Code::SUCCESS, $data); 246 $this->response('success', Code::SUCCESS, $data);
@@ -232,16 +257,29 @@ class TicketUploadDataController extends BaseController @@ -232,16 +257,29 @@ class TicketUploadDataController extends BaseController
232 { 257 {
233 $this->request->validate([ 258 $this->request->validate([
234 'project_id' => 'required', 259 'project_id' => 'required',
235 - 'search' => 'required'  
236 ], [ 260 ], [
237 'project_id.required' => 'project_id不能为空', 261 'project_id.required' => 'project_id不能为空',
238 - 'search.required' => '搜索参数不能为空',  
239 ]); 262 ]);
240 - ProjectServer::useProject($this->param['project_id']);  
241 - $blogCateModel = new BlogCategory();  
242 - $data = $blogCateModel->lists(['name' => ['like' ,'%' . $this->param['search'] . '%']], 1, 20,'id',['id','name']); 263 + ProjectServer::useProject($this->map['project_id']);
  264 + $newsCateModel = new NewsCategory();
  265 + if(!empty($this->map['search']) && isset($this->map['search'])){
  266 + $this->map['name'] = ['like' , '%' . $this->map['search'] . '%'];
  267 + unset($this->map['search']);
  268 + }
  269 + $cate_list = $newsCateModel->list($this->map, 'sort',['id','name as title','pid']);
  270 + if ($cate_list === false) {
  271 + $this->response('error', Code::USER_ERROR);
  272 + }
  273 + $list = [];
  274 + foreach ($cate_list as $v) {
  275 + $v = (array)$v;
  276 + if ($v['pid'] == 0) {
  277 + $v['sub'] = _get_child($v['id'], $cate_list);
  278 + $list[] = $v;
  279 + }
  280 + }
243 DB::disconnect('custom_mysql'); 281 DB::disconnect('custom_mysql');
244 - $this->response('success', Code::SUCCESS, $data); 282 + $this->response('success', Code::SUCCESS, $list);
245 } 283 }
246 284
247 /** 285 /**
@@ -255,15 +293,142 @@ class TicketUploadDataController extends BaseController @@ -255,15 +293,142 @@ class TicketUploadDataController extends BaseController
255 { 293 {
256 $this->request->validate([ 294 $this->request->validate([
257 'project_id' => 'required', 295 'project_id' => 'required',
258 - 'search' => 'required'  
259 ], [ 296 ], [
260 'project_id.required' => 'project_id不能为空', 297 'project_id.required' => 'project_id不能为空',
261 - 'search.required' => '搜索参数不能为空',  
262 ]); 298 ]);
263 - ProjectServer::useProject($this->param['project_id']); 299 + ProjectServer::useProject($this->map['project_id']);
264 $newsCateModel = new NewsCategory(); 300 $newsCateModel = new NewsCategory();
265 - $data = $newsCateModel->lists(['name' => ['like' , '%' . $this->param['search'] . '%']], 1, 20,'id',['id','name']); 301 + if(!empty($this->map['search']) && isset($this->map['search'])){
  302 + $this->map['name'] = ['like' , '%' . $this->map['search'] . '%'];
  303 + unset($this->map['search']);
  304 + }
  305 + $cate_list = $newsCateModel->list($this->map, 'sort',['id','name as title','pid']);
  306 + if ($cate_list === false) {
  307 + $this->response('error', Code::USER_ERROR);
  308 + }
  309 + $list = [];
  310 + foreach ($cate_list as $v) {
  311 + $v = (array)$v;
  312 + if ($v['pid'] == 0) {
  313 + $v['sub'] = _get_child($v['id'], $cate_list);
  314 + $list[] = $v;
  315 + }
  316 + }
  317 + $this->response('success', Code::SUCCESS, $list);
  318 + }
  319 +
  320 + /**
  321 + * @remark :保存关键字
  322 + * @name :saveKeyword
  323 + * @author :lyh
  324 + * @method :post
  325 + * @time :2025/10/10 10:50
  326 + */
  327 + public function saveKeyword()
  328 + {
  329 + $this->request->validate([
  330 + 'project_id' => 'required',
  331 + 'title' => 'required'
  332 + ], [
  333 + 'project_id.required' => 'project_id不能为空',
  334 + 'title.required' => '分类标题不能为空',
  335 + ]);
  336 + ProjectServer::useProject($this->param['project_id']);
  337 + $keywordModel = new Keyword();
  338 + $id = $keywordModel->addReturnId(['project_id' => $this->param['project_id'], 'title' => $this->param['title']]);
  339 + $route = RouteMap::setRoute($this->param['title'],RouteMap::SOURCE_PRODUCT_KEYWORD,$id,$this->param['project_id']);
  340 + $keywordModel->edit(['route'=>$route],['id'=>$id]);
266 DB::disconnect('custom_mysql'); 341 DB::disconnect('custom_mysql');
267 - $this->response('success', Code::SUCCESS, $data); 342 + $this->response('success', Code::SUCCESS, ['id'=>$id,'title'=>$this->param['title']]);
  343 + }
  344 +
  345 + /**
  346 + * @remark :新增分类
  347 + * @name :saveCategory
  348 + * @author :lyh
  349 + * @method :post
  350 + * @time :2025/10/10 10:13
  351 + */
  352 + public function saveCategory()
  353 + {
  354 + $this->request->validate([
  355 + 'project_id' => 'required',
  356 + 'type' => 'required',
  357 + 'title' => 'required'
  358 + ], [
  359 + 'project_id.required' => 'project_id不能为空',
  360 + 'type.required' => '类型不能为空',
  361 + 'title.required' => '分类标题不能为空',
  362 + ]);
  363 + ProjectServer::useProject($this->param['project_id']);
  364 + if($this->param['type'] == 1){//增加产品分类
  365 + $data = $this->addProductCategory($this->param['title'],$this->param['project_id'],$this->param['pid'] ?? 0);
  366 + }elseif ($this->param['type'] == 2){//增加blog分类
  367 + $data = $this->addBlogCategory($this->param['title'],$this->param['project_id'],$this->param['pid'] ?? 0);
  368 + }else{
  369 + $data = $this->addNewsCategory($this->param['title'],$this->param['project_id'],$this->param['pid'] ?? 0);
  370 + }
  371 + DB::disconnect('custom_mysql');
  372 + $this->response('success',Code::SUCCESS, $data);
  373 + }
  374 +
  375 + /**
  376 + * @remark :新增分类
  377 + * @name :addProductCategory
  378 + * @author :lyh
  379 + * @method :post
  380 + * @time :2025/10/10 10:43
  381 + */
  382 + public function addProductCategory($title,$project_id,$pid){
  383 + $productCateModel = new Category();
  384 + $info = $productCateModel->read(['title'=>$title],['id','title']);
  385 + if($info !== false){
  386 + return $info;
  387 + }else{
  388 + $id = $productCateModel->addReturnId(['title'=>$title,'project_id'=>$project_id,'pid'=>$pid]);
  389 + $route = RouteMap::setRoute($title,RouteMap::SOURCE_PRODUCT_CATE,$id,$project_id);
  390 + $productCateModel->edit(['route'=>$route],['id'=>$id]);
  391 + return ['id'=>$id,'title'=>$title];
  392 + }
  393 + }
  394 +
  395 + /**
  396 + * @remark :新增blog分类
  397 + * @name :addBlogCategory
  398 + * @author :lyh
  399 + * @method :post
  400 + * @time :2025/10/10 10:44
  401 + */
  402 + public function addBlogCategory($title,$project_id,$pid){
  403 + $blogCateModel = new BlogCategory();
  404 + $info = $blogCateModel->read(['name'=>$title],['id','name as title']);
  405 + if($info !== false){
  406 + return $info;
  407 + }else{
  408 + $id = $blogCateModel->addReturnId(['name'=>$title,'project_id'=>$project_id,'pid'=>$pid]);
  409 + $route = RouteMap::setRoute($title,RouteMap::SOURCE_BLOG_CATE,$id,$project_id);
  410 + $blogCateModel->edit(['alias'=>$route],['id'=>$id]);
  411 + return ['id'=>$id,'title'=>$title];
  412 + }
  413 + }
  414 +
  415 + /**
  416 + * @remark :新增news分类
  417 + * @name :addNewsCategory
  418 + * @author :lyh
  419 + * @method :post
  420 + * @time :2025/10/10 10:46
  421 + */
  422 + public function addNewsCategory($title,$project_id,$pid){
  423 + $newsCateModel = new NewsCategory();//增加新闻分类
  424 + $info = $newsCateModel->read(['name'=>$title],['id','name as title']);
  425 + if($info !== false){
  426 + return $info;
  427 + }else{
  428 + $id = $newsCateModel->addReturnId(['name'=>$title,'project_id'=>$project_id,'pid'=>$pid]);
  429 + $route = RouteMap::setRoute($title,RouteMap::SOURCE_NEWS_CATE,$id,$project_id);
  430 + $newsCateModel->edit(['alias'=>$route],['id'=>$id]);
  431 + return ['id'=>$id,'title'=>$title];
  432 + }
268 } 433 }
269 } 434 }
@@ -127,4 +127,21 @@ class GeoLinkController extends BaseController @@ -127,4 +127,21 @@ class GeoLinkController extends BaseController
127 } 127 }
128 $this->response('success',Code::SUCCESS,$data); 128 $this->response('success',Code::SUCCESS,$data);
129 } 129 }
  130 +
  131 + /**
  132 + * @remark :执行da值返回数据
  133 + * @name :daResultData
  134 + * @author :lyh
  135 + * @method :post
  136 + * @time :2025/10/9 09:39
  137 + */
  138 + public function daResultData(){
  139 + $this->request->validate([
  140 + 'id'=>'required',
  141 + ],[
  142 + 'id.required' => 'ID不能为空',
  143 + ]);
  144 + $data = $this->logic->daResultData();
  145 + $this->response('success',Code::SUCCESS,$data);
  146 + }
130 } 147 }
@@ -103,7 +103,7 @@ class InquiryForwardController extends BaseController @@ -103,7 +103,7 @@ class InquiryForwardController extends BaseController
103 'id' => 'required',//ID 103 'id' => 'required',//ID
104 'name' => 'required',//名称 104 'name' => 'required',//名称
105 'email' => 'required',//邮箱 105 'email' => 'required',//邮箱
106 - 'ip' => 'required',//ip 106 + 'ip' => 'required|max:200',//ip
107 'forward_url' => 'required',//转发网址 107 'forward_url' => 'required',//转发网址
108 'message' => 'required',//发送内容 108 'message' => 'required',//发送内容
109 ], [ 109 ], [
@@ -111,6 +111,7 @@ class InquiryForwardController extends BaseController @@ -111,6 +111,7 @@ class InquiryForwardController extends BaseController
111 'name.required' => '名称不能为空', 111 'name.required' => '名称不能为空',
112 'email.required' => '邮箱不能为空', 112 'email.required' => '邮箱不能为空',
113 'ip.required' => 'ip不能为空', 113 'ip.required' => 'ip不能为空',
  114 + 'ip.max' => '请使用正确的ipv4地址',
114 'forward_url.required' => '转发网址不能为空', 115 'forward_url.required' => '转发网址不能为空',
115 'message.required' => '内容不能为空', 116 'message.required' => '内容不能为空',
116 ]); 117 ]);
@@ -152,7 +153,10 @@ class InquiryForwardController extends BaseController @@ -152,7 +153,10 @@ class InquiryForwardController extends BaseController
152 'type.required' => '搜索类型不能为空', 153 'type.required' => '搜索类型不能为空',
153 ]); 154 ]);
154 155
155 - $lists = $inquiryForwardLogic->searchKeywords(); 156 + $keywords = $this->param['keywords'];
  157 + $type = $this->param['type'];
  158 + $num = $this->param['num'] ?? 3;
  159 + $lists = $inquiryForwardLogic->searchKeywords($keywords, $type, $num);
156 $this->response('success', Code::SUCCESS, $lists); 160 $this->response('success', Code::SUCCESS, $lists);
157 } 161 }
158 162
@@ -172,7 +176,8 @@ class InquiryForwardController extends BaseController @@ -172,7 +176,8 @@ class InquiryForwardController extends BaseController
172 'message.required' => '需要重写的文案不能为空', 176 'message.required' => '需要重写的文案不能为空',
173 ]); 177 ]);
174 178
175 - $data = $inquiryForwardLogic->aiRewrite(); 179 + $message = $this->param['message'];
  180 + $data = $inquiryForwardLogic->aiRewrite($message);
176 $this->response('success', Code::SUCCESS, $data); 181 $this->response('success', Code::SUCCESS, $data);
177 } 182 }
178 183
@@ -109,6 +109,7 @@ class ProjectController extends BaseController @@ -109,6 +109,7 @@ class ProjectController extends BaseController
109 'gl_project_deploy_build.dept_id AS dept_id', 109 'gl_project_deploy_build.dept_id AS dept_id',
110 'gl_project_deploy_build.keyword_num AS key', 110 'gl_project_deploy_build.keyword_num AS key',
111 'gl_project_deploy_build.service_duration AS day', 111 'gl_project_deploy_build.service_duration AS day',
  112 + 'gl_project_deploy_build.seo_service_duration AS seo_day',
112 'gl_project_deploy_build.is_comment AS is_comment', 113 'gl_project_deploy_build.is_comment AS is_comment',
113 'gl_project_deploy_build.leader_mid AS leader_mid', 114 'gl_project_deploy_build.leader_mid AS leader_mid',
114 'gl_project_deploy_build.manager_mid AS manager_mid', 115 'gl_project_deploy_build.manager_mid AS manager_mid',
@@ -845,6 +846,9 @@ class ProjectController extends BaseController @@ -845,6 +846,9 @@ class ProjectController extends BaseController
845 $domain_array = parse_url($domain_pro ? $domain_pro->domain : ''); 846 $domain_array = parse_url($domain_pro ? $domain_pro->domain : '');
846 $domain = $domain_array['host'] ?? $domain_array['path']; 847 $domain = $domain_array['host'] ?? $domain_array['path'];
847 } 848 }
  849 + $item['channel']['channel'] = Channel::where('id', $item['channel']['channel_id'])->value('title');
  850 + $item['channel']['zone'] = Zone::where('id', $item['channel']['zone_id'])->value('title');
  851 + $item['channel']['user'] = User::where('id', $item['channel']['user_id'])->value('name');
848 $manageHr = new ManageHr(); 852 $manageHr = new ManageHr();
849 $param = [ 853 $param = [
850 "id" => $item['id'], 854 "id" => $item['id'],
@@ -79,4 +79,21 @@ class LinkDataController extends BaseController @@ -79,4 +79,21 @@ class LinkDataController extends BaseController
79 $result = $linkData->del(['id'=>['in',$this->param['id']]]); 79 $result = $linkData->del(['id'=>['in',$this->param['id']]]);
80 $this->response('success',Code::SUCCESS,$result); 80 $this->response('success',Code::SUCCESS,$result);
81 } 81 }
  82 +
  83 + /**
  84 + * @remark :执行da值返回数据
  85 + * @name :daResultData
  86 + * @author :lyh
  87 + * @method :post
  88 + * @time :2025/10/9 09:39
  89 + */
  90 + public function daResultData(LinkDataLogic $logic){
  91 + $this->request->validate([
  92 + 'id'=>'required',
  93 + ],[
  94 + 'id.required' => 'ID不能为空',
  95 + ]);
  96 + $data = $logic->daResultData();
  97 + $this->response('success',Code::SUCCESS,$data);
  98 + }
82 } 99 }
@@ -10,7 +10,10 @@ @@ -10,7 +10,10 @@
10 namespace App\Http\Logic\Aside\Geo; 10 namespace App\Http\Logic\Aside\Geo;
11 11
12 use App\Http\Logic\Aside\BaseLogic; 12 use App\Http\Logic\Aside\BaseLogic;
  13 +use App\Models\Geo\DomainDa;
13 use App\Models\Geo\GeoLink; 14 use App\Models\Geo\GeoLink;
  15 +use App\Services\Geo\GeoService;
  16 +use Illuminate\Support\Carbon;
14 17
15 /** 18 /**
16 * @remark :geo权威新闻(链接数据) 19 * @remark :geo权威新闻(链接数据)
@@ -101,4 +104,70 @@ class GeoLinkLogic extends BaseLogic @@ -101,4 +104,70 @@ class GeoLinkLogic extends BaseLogic
101 } 104 }
102 return $this->success(); 105 return $this->success();
103 } 106 }
  107 +
  108 + /**
  109 + * @remark :返回数据data
  110 + * @name :daResultData
  111 + * @author :lyh
  112 + * @method :post
  113 + * @time :2025/10/9 09:43
  114 + */
  115 + public function daResultData()
  116 + {
  117 + $info = $this->model->read(['id'=>$this->param['id']]);
  118 + if($info === false){
  119 + $this->fail('当前数据不存在或者已被删除');
  120 + }
  121 + $host = $this->getDomainWithWWW($info['url']);
  122 + $domainDaModel = new DomainDa();
  123 + $daInfo = $domainDaModel->read(['domain'=>$host]);
  124 + if($daInfo !== false){
  125 + //判断时间是否大于60天
  126 + $start = Carbon::parse(date('Y-m-d', strtotime($daInfo['updated_at'])));
  127 + $end = Carbon::parse(date('Y-m-d'));
  128 + $diff = $start->diffInDays($end);
  129 + if($diff <= 60){
  130 + $info['da'] = $daInfo['da'];
  131 + $this->model->edit(['da'=>$daInfo['da'],'time'=>date('Y-m-d')], ['id'=>$info['id']]);
  132 + return $this->success($info);
  133 + }
  134 + }
  135 + $geoService = new GeoService();
  136 + $result = $geoService->daResult($host);
  137 + if(!isset($result['data']) || empty($result['data'])){
  138 + return $this->success($info);
  139 + }
  140 + $info['da'] = (int)$result['data']['mozDA'];//获取数据中的da值
  141 + //保存数据
  142 + if($daInfo !== false){
  143 + $domainDaModel->edit(['da'=>$info['da'],'result'=>json_encode($result,true)],['id'=>$daInfo['id']]);
  144 + }else{
  145 + $domainDaModel->addReturnId(['da'=>$info['da'],'domain'=>$host,'result'=>json_encode($result,true)]);
  146 + }
  147 + $this->model->edit(['da'=>$info['da'],'time'=>date('Y-m-d')], ['id'=>$info['id']]);
  148 + return $this->success($info);
  149 + }
  150 +
  151 + /**
  152 + * @remark :获取域名
  153 + * @name :getDomainWithWWW
  154 + * @author :lyh
  155 + * @method :post
  156 + * @time :2025/10/9 10:28
  157 + */
  158 + public function getDomainWithWWW($url) {
  159 + // 获取 host
  160 + $host = parse_url($url, PHP_URL_HOST);
  161 + // 去掉端口号等情况
  162 + $host = preg_replace('/:\d+$/', '', $host);
  163 + // 分割域名
  164 + $parts = explode('.', $host);
  165 + // 判断是几段
  166 + $count = count($parts);
  167 + // 如果只有两段,比如 fox8.com、theamericawatch.com,就拼接 www.
  168 + if ($count === 2) {
  169 + return 'www.' . $host;
  170 + }
  171 + return $host;
  172 + }
104 } 173 }
@@ -11,8 +11,10 @@ use App\Models\Inquiry\AreaTimezone; @@ -11,8 +11,10 @@ use App\Models\Inquiry\AreaTimezone;
11 use App\Models\Inquiry\InquiryInfo; 11 use App\Models\Inquiry\InquiryInfo;
12 use App\Models\Inquiry\InquiryProject; 12 use App\Models\Inquiry\InquiryProject;
13 use App\Models\Inquiry\InquiryProjectRoute; 13 use App\Models\Inquiry\InquiryProjectRoute;
  14 +use App\Models\Inquiry\InquiryRelayAi;
14 use App\Models\Inquiry\InquiryRelayDetail; 15 use App\Models\Inquiry\InquiryRelayDetail;
15 use App\Models\Inquiry\InquiryRelayDetailLog; 16 use App\Models\Inquiry\InquiryRelayDetailLog;
  17 +use App\Models\Manage\Manage;
16 use Illuminate\Support\Arr; 18 use Illuminate\Support\Arr;
17 use Illuminate\Support\Facades\DB; 19 use Illuminate\Support\Facades\DB;
18 use Illuminate\Support\Str; 20 use Illuminate\Support\Str;
@@ -102,6 +104,21 @@ class InquiryForwardLogic extends BaseLogic @@ -102,6 +104,21 @@ class InquiryForwardLogic extends BaseLogic
102 if ($info === false) { 104 if ($info === false) {
103 $this->fail('获取询盘详情失败'); 105 $this->fail('获取询盘详情失败');
104 } 106 }
  107 +
  108 + $keywords_ai = '';
  109 + $forward_url_ai = [];
  110 + $message_ai = [];
  111 + $inquiry_ai_model = new InquiryRelayAi();
  112 + $ai_info = $inquiry_ai_model->read(['form_id' => $this->param['id']], ['keywords', 'forward_url', 'message_ai']);
  113 + if ($ai_info) {
  114 + $keywords_ai = $ai_info['keywords'];
  115 + $forward_url_ai = json_decode($ai_info['forward_url'], true);
  116 + $message_ai = json_decode($ai_info['message_ai'], true);
  117 + }
  118 + $info['keywords_ai'] = $keywords_ai;
  119 + $info['forward_url_ai'] = $forward_url_ai;
  120 + $info['message_ai'] = $message_ai;
  121 +
105 return $this->success($info); 122 return $this->success($info);
106 } 123 }
107 124
@@ -123,16 +140,28 @@ class InquiryForwardLogic extends BaseLogic @@ -123,16 +140,28 @@ class InquiryForwardLogic extends BaseLogic
123 $this->fail('当前询盘状态无法转发'); 140 $this->fail('当前询盘状态无法转发');
124 } 141 }
125 142
126 - DB::beginTransaction();  
127 - try {  
128 - $num = 0;  
129 - $now = date('Y-m-d H:i:s'); 143 + if (is_array($this->param['message'])) {
  144 + $message_list = $this->param['message'];
  145 + } else {
  146 + $message_list = [$this->param['message']];
  147 + }
  148 + $message_count = count($message_list);
  149 + if ($message_count == 0) {
  150 + $this->fail('内容不能为空');
  151 + }
  152 +
130 if (is_array($this->param['forward_url'])) { 153 if (is_array($this->param['forward_url'])) {
131 $forward_url = $this->param['forward_url']; 154 $forward_url = $this->param['forward_url'];
132 } else { 155 } else {
133 $forward_url = explode(',', $this->param['forward_url']); 156 $forward_url = explode(',', $this->param['forward_url']);
134 } 157 }
135 - foreach ($forward_url as $url) { 158 +
  159 + DB::beginTransaction();
  160 + try {
  161 + $num = 0;
  162 + $now = date('Y-m-d H:i:s');
  163 +
  164 + foreach ($forward_url as $key => $url) {
136 $url = trim($url); 165 $url = trim($url);
137 $domain_array = parse_url($url); 166 $domain_array = parse_url($url);
138 $website = $domain_array['host'] ?? ''; 167 $website = $domain_array['host'] ?? '';
@@ -201,7 +230,10 @@ class InquiryForwardLogic extends BaseLogic @@ -201,7 +230,10 @@ class InquiryForwardLogic extends BaseLogic
201 $start_at = $now; 230 $start_at = $now;
202 } 231 }
203 232
204 - InquiryRelayDetail::createInquiry($info['id'], $website, $country, $this->param['ip'], $this->param['name'], $this->param['email'], $this->param['phone'] ?? '', $this->param['message'], $is_v6, json_encode([$url]), $start_at); 233 + //获取询盘内容
  234 + $message = $message_list[$key % $message_count] ?? $message_list[0];
  235 +
  236 + InquiryRelayDetail::createInquiry($info['id'], $website, $country, $this->param['ip'], $this->param['name'], $this->param['email'], $this->param['phone'] ?? '', $message, $is_v6, json_encode([$url]), $start_at);
205 237
206 $num += 1; 238 $num += 1;
207 } 239 }
@@ -240,22 +272,24 @@ class InquiryForwardLogic extends BaseLogic @@ -240,22 +272,24 @@ class InquiryForwardLogic extends BaseLogic
240 272
241 /** 273 /**
242 * 关键词查询项目着陆页 274 * 关键词查询项目着陆页
  275 + * @param $keywords
  276 + * @param $type
  277 + * @param $num
243 * @return int|mixed 278 * @return int|mixed
244 * @author Akun 279 * @author Akun
245 * @date 2025/02/26 17:13 280 * @date 2025/02/26 17:13
246 */ 281 */
247 - public function searchKeywords() 282 + public function searchKeywords($keywords, $type, $num)
248 { 283 {
249 - $num = $this->param['num'] ?? 3;  
250 284
251 $model = new InquiryProjectRoute(); 285 $model = new InquiryProjectRoute();
252 -// if ($this->param['type'] == 1) {  
253 -// //使用全文索引搜索  
254 -// $routeQuery = $model->select(['project_id', 'route'])->whereRaw("MATCH(title) AGAINST(? IN BOOLEAN MODE)", [$this->param['keywords']]);  
255 -// } else { 286 + if ($type == 1) {
  287 + //使用全文索引搜索
  288 + $routeQuery = $model->select(['project_id', 'route'])->whereRaw("MATCH(title) AGAINST(? IN BOOLEAN MODE)", [$keywords]);
  289 + } else {
256 //使用like查询 290 //使用like查询
257 - $routeQuery = $model->select(['project_id', 'route'])->where('title', 'like', '%' . $this->param['keywords'] . '%');  
258 -// } 291 + $routeQuery = $model->select(['project_id', 'route'])->where('title', 'like', '%' . $keywords . '%');
  292 + }
259 293
260 $re_route = $routeQuery->inRandomOrder()->take(100)->get()->toArray(); 294 $re_route = $routeQuery->inRandomOrder()->take(100)->get()->toArray();
261 295
@@ -297,7 +331,8 @@ class InquiryForwardLogic extends BaseLogic @@ -297,7 +331,8 @@ class InquiryForwardLogic extends BaseLogic
297 'route' => $vp->domain . $route, 331 'route' => $vp->domain . $route,
298 'recent_inquiry' => $vp->recent_inquiry, 332 'recent_inquiry' => $vp->recent_inquiry,
299 'remark' => $vp->remark ?: '', 333 'remark' => $vp->remark ?: '',
300 - 'version' => $vp->version 334 + 'version' => $vp->version,
  335 + 'type' => $type
301 ]; 336 ];
302 } 337 }
303 } 338 }
@@ -309,22 +344,29 @@ class InquiryForwardLogic extends BaseLogic @@ -309,22 +344,29 @@ class InquiryForwardLogic extends BaseLogic
309 344
310 /** 345 /**
311 * AI重写询盘文案 346 * AI重写询盘文案
  347 + * @param $in_content
  348 + * @param $title
  349 + * @param $keywords
312 * @return array 350 * @return array
313 * @throws \App\Exceptions\AsideGlobalException 351 * @throws \App\Exceptions\AsideGlobalException
314 * @throws \App\Exceptions\BsideGlobalException 352 * @throws \App\Exceptions\BsideGlobalException
315 * @author Akun 353 * @author Akun
316 * @date 2025/02/27 10:40 354 * @date 2025/02/27 10:40
317 */ 355 */
318 - public function aiRewrite() 356 + public function aiRewrite($in_content, $title = '', $keywords = '')
319 { 357 {
320 - $ai_info = AiCommand::select(['ai', 'not_use_probability'])->where('key', 'inquiry_text_rewrite')->first(); 358 + if ($title && $keywords) {
  359 + $command_key = 'inquiry_text_rewrite_v2';
  360 + } else {
  361 + $command_key = 'inquiry_text_rewrite';
  362 + }
  363 + $ai_info = AiCommand::select(['ai', 'not_use_probability'])->where('key', $command_key)->first();
321 if (!$ai_info) { 364 if (!$ai_info) {
322 $this->fail('AI重写指令未配置'); 365 $this->fail('AI重写指令未配置');
323 } 366 }
324 367
325 $ai_command = $ai_info['ai']; 368 $ai_command = $ai_info['ai'];
326 $not_use_probability = $ai_info['not_use_probability']; 369 $not_use_probability = $ai_info['not_use_probability'];
327 - $in_content = $this->param['message'];  
328 370
329 // 当原始询盘内容长度大于15个字符, 60%几率直接发送原始内容。 371 // 当原始询盘内容长度大于15个字符, 60%几率直接发送原始内容。
330 if (strlen($in_content) >= 15) { 372 if (strlen($in_content) >= 15) {
@@ -340,6 +382,10 @@ class InquiryForwardLogic extends BaseLogic @@ -340,6 +382,10 @@ class InquiryForwardLogic extends BaseLogic
340 $lang = 'en'; 382 $lang = 'en';
341 } 383 }
342 384
  385 + if ($title && $keywords) {
  386 + $ai_command = str_replace('{title}', $title, $ai_command);
  387 + $ai_command = str_replace('{keywords}', $keywords, $ai_command);
  388 + }
343 $ai_command = str_replace('{incontent}', Arr::random(explode("\r\n", $in_content)), $ai_command); 389 $ai_command = str_replace('{incontent}', Arr::random(explode("\r\n", $in_content)), $ai_command);
344 390
345 $text = Gpt::instance()->openai_chat_qqs($ai_command); 391 $text = Gpt::instance()->openai_chat_qqs($ai_command);
@@ -392,6 +438,23 @@ class InquiryForwardLogic extends BaseLogic @@ -392,6 +438,23 @@ class InquiryForwardLogic extends BaseLogic
392 { 438 {
393 $model = new InquiryRelayDetail(); 439 $model = new InquiryRelayDetail();
394 $lists = $model->listsWith($map, $page, $row, $order, $filed, 'desc', ['detailLog']); 440 $lists = $model->listsWith($map, $page, $row, $order, $filed, 'desc', ['detailLog']);
  441 +
  442 + //获取操作人
  443 + $inquiry_info_model = new InquiryInfo();
  444 + $manage_model = new Manage();
  445 + foreach ($lists['list'] as $k => $v) {
  446 + $operator_name = '';
  447 + $inquiry_info = $inquiry_info_model->read(['id' => $v['form_id']], ['operator_id']);
  448 + if ($inquiry_info) {
  449 + $manage_info = $manage_model->read(['id' => $inquiry_info['operator_id']], ['name']);
  450 + if ($manage_info) {
  451 + $operator_name = $manage_info['name'];
  452 + }
  453 + }
  454 +
  455 + $lists['list'][$k]['operator_name'] = $operator_name;
  456 + }
  457 +
395 return $this->success($lists); 458 return $this->success($lists);
396 } 459 }
397 460
@@ -438,7 +501,8 @@ class InquiryForwardLogic extends BaseLogic @@ -438,7 +501,8 @@ class InquiryForwardLogic extends BaseLogic
438 $data[$s_date] = [ 501 $data[$s_date] = [
439 'total' => 0, 502 'total' => 0,
440 'invalid' => 0, 503 'invalid' => 0,
441 - 'init' => 0 504 + 'init' => 0,
  505 + 'finish' => 0
442 ]; 506 ];
443 $s_date = date('Y-m-d', strtotime($s_date . ' + 1 day')); 507 $s_date = date('Y-m-d', strtotime($s_date . ' + 1 day'));
444 } 508 }
@@ -451,10 +515,10 @@ class InquiryForwardLogic extends BaseLogic @@ -451,10 +515,10 @@ class InquiryForwardLogic extends BaseLogic
451 515
452 if ($value['status'] == InquiryInfo::STATUS_INVALID) { 516 if ($value['status'] == InquiryInfo::STATUS_INVALID) {
453 $data[$inquiry_date]['invalid'] += 1; 517 $data[$inquiry_date]['invalid'] += 1;
454 - }  
455 -  
456 - if ($value['status'] == InquiryInfo::STATUS_INIT) { 518 + } elseif ($value['status'] == InquiryInfo::STATUS_INIT) {
457 $data[$inquiry_date]['init'] += 1; 519 $data[$inquiry_date]['init'] += 1;
  520 + } else {
  521 + $data[$inquiry_date]['finish'] += 1;
458 } 522 }
459 } 523 }
460 524
@@ -208,7 +208,7 @@ class ProjectLogic extends BaseLogic @@ -208,7 +208,7 @@ class ProjectLogic extends BaseLogic
208 $this->fail('保存失败,请联系管理员'); 208 $this->fail('保存失败,请联系管理员');
209 } 209 }
210 } 210 }
211 - return $this->success(); 211 + return $this->success($this->param);
212 } 212 }
213 213
214 /** 214 /**
@@ -440,7 +440,7 @@ class ProjectLogic extends BaseLogic @@ -440,7 +440,7 @@ class ProjectLogic extends BaseLogic
440 foreach ($param['payment']['renewal_record'] as &$record) { 440 foreach ($param['payment']['renewal_record'] as &$record) {
441 if (!is_null($record['expire_at'] ?? null) && $record['expire_at'] === $maxExpireAt) { 441 if (!is_null($record['expire_at'] ?? null) && $record['expire_at'] === $maxExpireAt) {
442 // 如果 end_time 不存在或与 expire_at 不一致,则更新 442 // 如果 end_time 不存在或与 expire_at 不一致,则更新
443 - if (!isset($record['end_time']) || $record['end_time'] != $record['expire_at']) { 443 + if (!isset($record['end_time']) || ($record['end_time'] != $record['expire_at'])) {
444 $record['end_time'] = $record['expire_at']; // ✅ 写回原数据 444 $record['end_time'] = $record['expire_at']; // ✅ 写回原数据
445 // 重新计算剩余天数 445 // 重新计算剩余天数
446 $diff = (strtotime($record['expire_at']) - strtotime(date('Y-m-d'))) / (60 * 60 * 24); 446 $diff = (strtotime($record['expire_at']) - strtotime(date('Y-m-d'))) / (60 * 60 * 24);
@@ -203,13 +203,13 @@ class TicketUploadDataLogic extends BaseLogic @@ -203,13 +203,13 @@ class TicketUploadDataLogic extends BaseLogic
203 'intro'=>$info['text']['remark'], 203 'intro'=>$info['text']['remark'],
204 'category_id'=>$category_id ?? '', 204 'category_id'=>$category_id ?? '',
205 'keyword_id'=>$keyword_id ?? '', 205 'keyword_id'=>$keyword_id ?? '',
206 - 'status'=>0, 206 + 'status'=>1,
207 ]; 207 ];
208 $id = $productModel->addReturnId($data); 208 $id = $productModel->addReturnId($data);
209 CategoryRelated::saveRelated($id, $info['text']['category_id'] ?? []);//分类关联 209 CategoryRelated::saveRelated($id, $info['text']['category_id'] ?? []);//分类关联
210 KeywordRelated::saveRelated($id,$info['text']['keyword_id'] ?? []);//关键字关联 210 KeywordRelated::saveRelated($id,$info['text']['keyword_id'] ?? []);//关键字关联
211 $route = RouteMap::setRoute($data['title'],RouteMap::SOURCE_PRODUCT,$id,$info['project_id']); 211 $route = RouteMap::setRoute($data['title'],RouteMap::SOURCE_PRODUCT,$id,$info['project_id']);
212 - $this->model->edit(['route'=>$route],['id'=>$id]); 212 + $productModel->edit(['route'=>$route],['id'=>$id]);
213 }catch (\Exception $e){ 213 }catch (\Exception $e){
214 $this->fail('保存失败,请联系管理员'); 214 $this->fail('保存失败,请联系管理员');
215 } 215 }
@@ -237,13 +237,13 @@ class TicketUploadDataLogic extends BaseLogic @@ -237,13 +237,13 @@ class TicketUploadDataLogic extends BaseLogic
237 'image'=>$info['text']['image'], 237 'image'=>$info['text']['image'],
238 'text'=>$info['text']['remark'], 238 'text'=>$info['text']['remark'],
239 'category_id'=>$category_id ?? '', 239 'category_id'=>$category_id ?? '',
240 - 'status'=>0, 240 + 'status'=>1,
241 ]; 241 ];
242 try { 242 try {
243 $blogModel = new Blog(); 243 $blogModel = new Blog();
244 $id = $blogModel->addReturnId($data); 244 $id = $blogModel->addReturnId($data);
245 $route = RouteMap::setRoute($data['name'],RouteMap::SOURCE_BLOG,$id,$info['project_id']); 245 $route = RouteMap::setRoute($data['name'],RouteMap::SOURCE_BLOG,$id,$info['project_id']);
246 - $this->model->edit(['url'=>$route],['id'=>$id]); 246 + $blogModel->edit(['url'=>$route],['id'=>$id]);
247 }catch (\Exception $e){ 247 }catch (\Exception $e){
248 $this->fail('保存失败,请联系管理员'); 248 $this->fail('保存失败,请联系管理员');
249 } 249 }
@@ -271,13 +271,13 @@ class TicketUploadDataLogic extends BaseLogic @@ -271,13 +271,13 @@ class TicketUploadDataLogic extends BaseLogic
271 'image'=>$info['text']['image'], 271 'image'=>$info['text']['image'],
272 'text'=>$info['text']['remark'], 272 'text'=>$info['text']['remark'],
273 'category_id'=>$category_id ?? '', 273 'category_id'=>$category_id ?? '',
274 - 'status'=>0, 274 + 'status'=>1,
275 ]; 275 ];
276 try { 276 try {
277 $newsModel = new News(); 277 $newsModel = new News();
278 $id = $newsModel->addReturnId($data); 278 $id = $newsModel->addReturnId($data);
279 $route = RouteMap::setRoute($data['name'],RouteMap::SOURCE_NEWS,$id,$info['project_id']); 279 $route = RouteMap::setRoute($data['name'],RouteMap::SOURCE_NEWS,$id,$info['project_id']);
280 - $this->model->edit(['route'=>$route],['id'=>$id]); 280 + $newsModel->edit(['url'=>$route],['id'=>$id]);
281 }catch (\Exception $e){ 281 }catch (\Exception $e){
282 $this->fail('保存失败,请联系管理员'); 282 $this->fail('保存失败,请联系管理员');
283 } 283 }
@@ -66,6 +66,7 @@ class AiVideoLogic extends BaseLogic @@ -66,6 +66,7 @@ class AiVideoLogic extends BaseLogic
66 $aiVideoTaskModel = new AiVideoTask(); 66 $aiVideoTaskModel = new AiVideoTask();
67 $aiVideoService = new AiVideoService($this->user['project_id']); 67 $aiVideoService = new AiVideoService($this->user['project_id']);
68 $storage = $aiVideoTaskModel->videoSetting()[$this->user['video_setting'] ?? 1]; 68 $storage = $aiVideoTaskModel->videoSetting()[$this->user['video_setting'] ?? 1];
  69 + //todo::获取ayr的key
69 $result = $aiVideoService->createTask($this->param['title'],$this->param['description'],$this->param['images'],$this->param['anchor'] ?? [],$storage); 70 $result = $aiVideoService->createTask($this->param['title'],$this->param['description'],$this->param['images'],$this->param['anchor'] ?? [],$storage);
70 if($result['status'] == 200){ 71 if($result['status'] == 200){
71 $aiVideoTaskModel->addReturnId(['task_id'=>$result['data']['task_id'],'project_id'=>$this->user['project_id'],'storage'=>$storage]); 72 $aiVideoTaskModel->addReturnId(['task_id'=>$result['data']['task_id'],'project_id'=>$this->user['project_id'],'storage'=>$storage]);
@@ -555,7 +555,7 @@ class RankDataLogic extends BaseLogic @@ -555,7 +555,7 @@ class RankDataLogic extends BaseLogic
555 $without_extension_project_ids = [658]; //是否达标只统计主词的 555 $without_extension_project_ids = [658]; //是否达标只统计主词的
556 $extension_project_ids = [354]; //扩展词也到达标的 556 $extension_project_ids = [354]; //扩展词也到达标的
557 $compliance_project_ids = [2163,257,823,1750,497,1006]; //直接达标处理的 557 $compliance_project_ids = [2163,257,823,1750,497,1006]; //直接达标处理的
558 - $ceaseProjectId = [354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250,2193,2399,1685, 3931,2273,3647];//暂停的项目 558 + $ceaseProjectId = [354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250,2193,2399,1685, 3931,2273,3647,1934];//暂停的项目
559 $uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目 559 $uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目
560 //一个项目多个api_no 560 //一个项目多个api_no
561 $multiple_api_no_project_ids = [ 561 $multiple_api_no_project_ids = [
@@ -10,7 +10,11 @@ @@ -10,7 +10,11 @@
10 namespace App\Http\Logic\Bside\SeoSetting; 10 namespace App\Http\Logic\Bside\SeoSetting;
11 11
12 use App\Http\Logic\Bside\BaseLogic; 12 use App\Http\Logic\Bside\BaseLogic;
  13 +use App\Models\Geo\DomainDa;
13 use App\Models\SeoSetting\LinkData; 14 use App\Models\SeoSetting\LinkData;
  15 +use App\Services\Geo\GeoService;
  16 +use Illuminate\Support\Carbon;
  17 +use Nette\Utils\DateTime;
14 18
15 /** 19 /**
16 * @remark :获取外链数据 20 * @remark :获取外链数据
@@ -50,4 +54,70 @@ class LinkDataLogic extends BaseLogic @@ -50,4 +54,70 @@ class LinkDataLogic extends BaseLogic
50 } 54 }
51 return $this->success(); 55 return $this->success();
52 } 56 }
  57 +
  58 + /**
  59 + * @remark :返回数据data
  60 + * @name :daResultData
  61 + * @author :lyh
  62 + * @method :post
  63 + * @time :2025/10/9 09:43
  64 + */
  65 + public function daResultData()
  66 + {
  67 + $info = $this->model->read(['id'=>$this->param['id']]);
  68 + if($info === false){
  69 + $this->fail('当前数据不存在或者已被删除');
  70 + }
  71 + $host = $this->getDomainWithWWW($info['url']);
  72 + $domainDaModel = new DomainDa();
  73 + $daInfo = $domainDaModel->read(['domain'=>$host]);
  74 + if($daInfo !== false){
  75 + //判断时间是否大于60天
  76 + $start = Carbon::parse(date('Y-m-d', strtotime($daInfo['updated_at'])));
  77 + $end = Carbon::parse(date('Y-m-d'));
  78 + $diff = $start->diffInDays($end);
  79 + if($diff <= 60){
  80 + $info['da_values'] = $daInfo['da'];
  81 + $this->model->edit(['da_values'=>$daInfo['da'],'time'=>date('Y-m-d')], ['id'=>$info['id']]);
  82 + return $this->success($info);
  83 + }
  84 + }
  85 + $geoService = new GeoService();
  86 + $result = $geoService->daResult($host);
  87 + if(!isset($result['data']) || empty($result['data'])){
  88 + return $this->success($info);
  89 + }
  90 + $info['da_values'] = (int)$result['data']['mozDA'];//获取数据中的da值
  91 + //保存数据
  92 + if($daInfo !== false){
  93 + $domainDaModel->edit(['da'=>$info['da_values'],'result'=>json_encode($result,true)],['id'=>$daInfo['id']]);
  94 + }else{
  95 + $domainDaModel->addReturnId(['da'=>$info['da_values'],'domain'=>$host,'result'=>json_encode($result,true)]);
  96 + }
  97 + $this->model->edit(['da_values'=>$info['da_values'],'time'=>date('Y-m-d')], ['id'=>$info['id']]);
  98 + return $this->success($info);
  99 + }
  100 +
  101 + /**
  102 + * @remark :获取域名
  103 + * @name :getDomainWithWWW
  104 + * @author :lyh
  105 + * @method :post
  106 + * @time :2025/10/9 10:28
  107 + */
  108 + public function getDomainWithWWW($url) {
  109 + // 获取 host
  110 + $host = parse_url($url, PHP_URL_HOST);
  111 + // 去掉端口号等情况
  112 + $host = preg_replace('/:\d+$/', '', $host);
  113 + // 分割域名
  114 + $parts = explode('.', $host);
  115 + // 判断是几段
  116 + $count = count($parts);
  117 + // 如果只有两段,比如 fox8.com、theamericawatch.com,就拼接 www.
  118 + if ($count === 2) {
  119 + return 'www.' . $host;
  120 + }
  121 + return $host;
  122 + }
53 } 123 }
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :DomainDa.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/10/11 10:18
  8 + */
  9 +
  10 +namespace App\Models\Geo;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +class DomainDa extends Base
  15 +{
  16 + protected $table = 'gl_domain_da';
  17 +}
@@ -119,7 +119,7 @@ class InquiryInfo extends Base @@ -119,7 +119,7 @@ class InquiryInfo extends Base
119 $self->status = $status; 119 $self->status = $status;
120 $self->remark = $remark; 120 $self->remark = $remark;
121 $self->save(); 121 $self->save();
122 - return true; 122 + return $self->id;
123 } catch (\Exception $e) { 123 } catch (\Exception $e) {
124 return false; 124 return false;
125 } 125 }
  1 +<?php
  2 +
  3 +namespace App\Models\Inquiry;
  4 +
  5 +use App\Models\Base;
  6 +
  7 +class InquiryRelayAi extends Base
  8 +{
  9 + protected $table = 'gl_inquiry_relay_ai';
  10 +}
@@ -55,9 +55,12 @@ class AiVideoService @@ -55,9 +55,12 @@ class AiVideoService
55 * @method :post 55 * @method :post
56 * @time :2025/4/29 17:59 56 * @time :2025/4/29 17:59
57 */ 57 */
58 - public function createTask($title,$description,$images = [],$anchor = [],$storage = 'CDN'){ 58 + public function createTask($title,$description,$images = [],$anchor = [],$storage = 'CDN',$ayrshare_profile_key = ''){
59 $request_url = $this->url.'api/video/create'; 59 $request_url = $this->url.'api/video/create';
60 $param = ['title'=>$title, 'description'=>$description, 'images'=>$images,'anchor'=>$anchor,'storage'=>$storage]; 60 $param = ['title'=>$title, 'description'=>$description, 'images'=>$images,'anchor'=>$anchor,'storage'=>$storage];
  61 + if(!empty($ayrshare_profile_key)){
  62 + $param['ayrshare_profile_key'] = $ayrshare_profile_key;
  63 + }
61 $param['mch_id'] = $this->mch_id; 64 $param['mch_id'] = $this->mch_id;
62 $this->sign = $this->generateSign($param,$this->key); 65 $this->sign = $this->generateSign($param,$this->key);
63 $param['sign'] = $this->sign; 66 $param['sign'] = $this->sign;
@@ -137,4 +137,18 @@ class GeoService @@ -137,4 +137,18 @@ class GeoService
137 $result = Http::post($url, $param); 137 $result = Http::post($url, $param);
138 return $result->json(); 138 return $result->json();
139 } 139 }
  140 +
  141 + /**
  142 + * @remark :根据域名获取da值
  143 + * @name :daResult
  144 + * @author :lyh
  145 + * @method :post
  146 + * @time :2025/10/9 09:33
  147 + */
  148 + public function daResult($domain)
  149 + {
  150 + $url = 'https://www.cmer.site/api/get_domain_da?domain='.$domain;
  151 + $result = http_get($url);
  152 + return $result;
  153 + }
140 } 154 }
@@ -102,5 +102,7 @@ Route::prefix('ticket_upload')->group(function () { @@ -102,5 +102,7 @@ Route::prefix('ticket_upload')->group(function () {
102 Route::any('/getProductCate', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getProductCate'])->name('ticket_upload.getProductCate'); 102 Route::any('/getProductCate', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getProductCate'])->name('ticket_upload.getProductCate');
103 Route::any('/getBlogCate', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getBlogCate'])->name('ticket_upload.getBlogCate'); 103 Route::any('/getBlogCate', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getBlogCate'])->name('ticket_upload.getBlogCate');
104 Route::any('/getNewsCate', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getNewsCate'])->name('ticket_upload.getNewsCate'); 104 Route::any('/getNewsCate', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'getNewsCate'])->name('ticket_upload.getNewsCate');
  105 + Route::any('/saveCategory', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'saveCategory'])->name('ticket_upload.saveCategory');
  106 + Route::any('/saveKeyword', [\App\Http\Controllers\Api\WorkOrder\TicketUploadDataController::class, 'saveKeyword'])->name('ticket_upload.saveKeyword');
105 }); 107 });
106 108
@@ -583,6 +583,7 @@ Route::middleware(['aloginauth'])->group(function () { @@ -583,6 +583,7 @@ Route::middleware(['aloginauth'])->group(function () {
583 Route::any('/info', [Aside\Geo\GeoLinkController::class, 'info'])->name('admin.geo_link_info'); 583 Route::any('/info', [Aside\Geo\GeoLinkController::class, 'info'])->name('admin.geo_link_info');
584 Route::any('/del', [Aside\Geo\GeoLinkController::class, 'del'])->name('admin.geo_link_del'); 584 Route::any('/del', [Aside\Geo\GeoLinkController::class, 'del'])->name('admin.geo_link_del');
585 Route::any('/downloadGeoLink', [Aside\Geo\GeoLinkController::class, 'downloadGeoLink'])->name('admin.geo_link_downloadGeoLink'); 585 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');
586 }); 587 });
587 }); 588 });
588 // 任务相关 589 // 任务相关
@@ -715,6 +715,7 @@ Route::middleware(['bloginauth'])->group(function () { @@ -715,6 +715,7 @@ Route::middleware(['bloginauth'])->group(function () {
715 Route::any('/batchSave', [\App\Http\Controllers\Bside\SeoSetting\LinkDataController::class, 'batchSave'])->name('link_data_batchSave'); 715 Route::any('/batchSave', [\App\Http\Controllers\Bside\SeoSetting\LinkDataController::class, 'batchSave'])->name('link_data_batchSave');
716 Route::any('/info', [\App\Http\Controllers\Bside\SeoSetting\LinkDataController::class, 'info'])->name('link_data_info'); 716 Route::any('/info', [\App\Http\Controllers\Bside\SeoSetting\LinkDataController::class, 'info'])->name('link_data_info');
717 Route::any('/del', [\App\Http\Controllers\Bside\SeoSetting\LinkDataController::class, 'del'])->name('link_data_del'); 717 Route::any('/del', [\App\Http\Controllers\Bside\SeoSetting\LinkDataController::class, 'del'])->name('link_data_del');
  718 + Route::any('/daResultData', [\App\Http\Controllers\Bside\SeoSetting\LinkDataController::class, 'daResultData'])->name('link_data_daResultData');
718 }); 719 });
719 720
720 //seo白帽 域名设置 721 //seo白帽 域名设置