作者 赵彬吉
@@ -27,7 +27,7 @@ class RemainDay extends Command @@ -27,7 +27,7 @@ class RemainDay extends Command
27 * @var 按优化时间统计 27 * @var 按优化时间统计
28 */ 28 */
29 protected $projectId = [ 29 protected $projectId = [
30 - 1434,1812,276,2414,2974 30 + 1434,1812,276,2414,2974,
31 ];//需要单独处理的项目 31 ];//需要单独处理的项目
32 32
33 /** 33 /**
@@ -37,7 +37,13 @@ class RemainDay extends Command @@ -37,7 +37,13 @@ class RemainDay extends Command
37 protected $bm_projectId = [ 37 protected $bm_projectId = [
38 4247,4299,4310,4215,4038,4084,4148,4178,4405 38 4247,4299,4310,4215,4038,4084,4148,4178,4405
39 ]; 39 ];
40 - 40 + /**
  41 + * @var
  42 + * 优化项目,中途切换按服务时间长计时,单独计算
  43 + */
  44 + protected $projectSwitchId = [
  45 + 793,
  46 + ];
41 47
42 /** 48 /**
43 * @var 暂停的项目 49 * @var 暂停的项目
@@ -85,8 +91,8 @@ class RemainDay extends Command @@ -85,8 +91,8 @@ class RemainDay extends Command
85 public function saveRemainDay(){ 91 public function saveRemainDay(){
86 $list = $this->project->list(['extend_type'=>Project::TYPE_ZERO,'type'=>['in',[Project::TYPE_TWO,Project::TYPE_THREE,Project::TYPE_FOUR,Project::TYPE_SIX]]],'id',['id','type','level','uptime','remain_day','is_remain_today','pause_days','finish_remain_day','bm_finish_remain_day']); 92 $list = $this->project->list(['extend_type'=>Project::TYPE_ZERO,'type'=>['in',[Project::TYPE_TWO,Project::TYPE_THREE,Project::TYPE_FOUR,Project::TYPE_SIX]]],'id',['id','type','level','uptime','remain_day','is_remain_today','pause_days','finish_remain_day','bm_finish_remain_day']);
87 foreach ($list as $item){ 93 foreach ($list as $item){
88 - $deploy_build = $this->deployBuild->read(['project_id'=>$item['id']],['service_duration','seo_service_duration','plan','seo_plan']);  
89 echo 'start->项目id:' . $item['id'] . '执行时间:'. date('Y-m-d H:i:s') . PHP_EOL; 94 echo 'start->项目id:' . $item['id'] . '执行时间:'. date('Y-m-d H:i:s') . PHP_EOL;
  95 + $deploy_build = $this->deployBuild->read(['project_id'=>$item['id']],['service_duration','seo_service_duration','plan','seo_plan']);
90 if(in_array($item['id'],$this->ceaseProjectId)){//暂停的项目 96 if(in_array($item['id'],$this->ceaseProjectId)){//暂停的项目
91 if(($item['type'] == Project::TYPE_TWO) && ($item['is_remain_today'] == 1)){ 97 if(($item['type'] == Project::TYPE_TWO) && ($item['is_remain_today'] == 1)){
92 $pause_days = $item['pause_days'] + 1; 98 $pause_days = $item['pause_days'] + 1;
@@ -97,6 +103,11 @@ class RemainDay extends Command @@ -97,6 +103,11 @@ class RemainDay extends Command
97 $this->project->edit(['pause_days'=>$pause_days],['id'=>$item['id']]); 103 $this->project->edit(['pause_days'=>$pause_days],['id'=>$item['id']]);
98 continue; 104 continue;
99 } 105 }
  106 + //todo::优化项目中途达标计时切换为按天计时
  107 + if(in_array($item['id'],$this->projectSwitchId)){
  108 + $this->project->edit(['remain_day'=>($item['remain_day'] - 1),'finish_remain_day'=>($item['finish_remain_day'] + 1)],['id'=>$item['id']]);
  109 + continue;
  110 + }
100 //白帽版本单独计算 111 //白帽版本单独计算
101 $this->seoRemainDay($deploy_build,$item); 112 $this->seoRemainDay($deploy_build,$item);
102 //默认版本统计 113 //默认版本统计
@@ -51,6 +51,12 @@ class GeoQuestionRes extends Command @@ -51,6 +51,12 @@ class GeoQuestionRes extends Command
51 sleep(300); 51 sleep(300);
52 continue; 52 continue;
53 } 53 }
  54 + $lock_key = "geo_task_lock:$task_id";
  55 + if (!Redis::setnx($lock_key, 1)) {
  56 + $this->output("任务 $task_id 已被其他进程锁定,跳过");
  57 + continue;
  58 + }
  59 + Redis::expire($lock_key, 1200); // 1小时自动解锁
54 $this->output('执行的任务ID:' . $task_id); 60 $this->output('执行的任务ID:' . $task_id);
55 $geoQuestionModel = new GeoQuestion(); 61 $geoQuestionModel = new GeoQuestion();
56 $taskInfo = $geoQuestionModel->read(['id'=>$task_id]); 62 $taskInfo = $geoQuestionModel->read(['id'=>$task_id]);
@@ -339,16 +345,19 @@ class GeoQuestionRes extends Command @@ -339,16 +345,19 @@ class GeoQuestionRes extends Command
339 $key = 'geo_task_list'; 345 $key = 'geo_task_list';
340 $task_id = Redis::rpop($key); 346 $task_id = Redis::rpop($key);
341 if(empty($task_id)){ 347 if(empty($task_id)){
342 - //todo::这里需要执行统计一次,统计当前项目当前日期的统计  
343 - # TODO 按照项目进行获取, 一个项目当天需要将所有跑完  
344 - $project_id = GeoQuestion::where('status', GeoQuestion::STATUS_OPEN)->where('next_time', '<=', date('Y-m-d'))->value('project_id');  
345 - if (!empty($project_id)){  
346 - $this->project_id = $project_id;  
347 - $ids = GeoQuestion::where(['project_id' => $project_id, 'status' => GeoQuestion::STATUS_OPEN])->where('next_time', '<=', date('Y-m-d'))->pluck('id');  
348 - foreach ($ids as $id) {  
349 - Redis::lpush($key, $id); 348 + $project_ids = GeoQuestion::where('status', GeoQuestion::STATUS_OPEN)->where('next_time', '<=', date('Y-m-d'))
  349 + ->orderBy('next_time', 'asc')->pluck('project_id')->unique()->values()->toArray();
  350 + if(!empty($project_ids)){
  351 + foreach ($project_ids as $project_id){
  352 + $ids = GeoQuestion::where(['project_id' => $project_id, 'status' => GeoQuestion::STATUS_OPEN])->where('next_time', '<=', date('Y-m-d'))->pluck('id');
  353 + foreach ($ids as $id) {
  354 + //检查任务是否执行过
  355 + if (!Redis::exists("geo_task_lock:$id")) {
  356 + Redis::lpush($key, $id);
  357 + }
  358 + }
  359 + $task_id = Redis::rpop($key);
350 } 360 }
351 - $task_id = Redis::rpop($key);  
352 } 361 }
353 } 362 }
354 return $task_id; 363 return $task_id;
@@ -73,7 +73,7 @@ class GeoWritingsTask extends Command @@ -73,7 +73,7 @@ class GeoWritingsTask extends Command
73 'status'=>2, 73 'status'=>2,
74 'writings_id'=>$id, 74 'writings_id'=>$id,
75 ]; 75 ];
76 - $geoWritingsTaskModel->edit($data,['task_id'=>$task_id]); 76 + $geoWritingsTaskModel->edit($data,['id'=>$task_id]);
77 }catch (\Exception $e){ 77 }catch (\Exception $e){
78 echo date('Y-m-d H:i:s').'保存失败:'.$task_id.$e->getMessage().PHP_EOL; 78 echo date('Y-m-d H:i:s').'保存失败:'.$task_id.$e->getMessage().PHP_EOL;
79 continue; 79 continue;
@@ -5,6 +5,7 @@ namespace App\Console\Commands\Inquiry; @@ -5,6 +5,7 @@ namespace App\Console\Commands\Inquiry;
5 use App\Models\Inquiry\ForwardCount; 5 use App\Models\Inquiry\ForwardCount;
6 use App\Models\Inquiry\InquiryInfo; 6 use App\Models\Inquiry\InquiryInfo;
7 use Illuminate\Console\Command; 7 use Illuminate\Console\Command;
  8 +use Illuminate\Support\Facades\Cache;
8 9
9 class InquiryForwardDayCount extends Command 10 class InquiryForwardDayCount extends Command
10 { 11 {
@@ -55,6 +56,8 @@ class InquiryForwardDayCount extends Command @@ -55,6 +56,8 @@ class InquiryForwardDayCount extends Command
55 $day_count->save(); 56 $day_count->save();
56 } 57 }
57 58
  59 + Cache::forget('inquiry_manage_count');
  60 +
58 $this->output('success'); 61 $this->output('success');
59 } 62 }
60 63
@@ -59,15 +59,30 @@ class MonthProjectCount extends Command @@ -59,15 +59,30 @@ class MonthProjectCount extends Command
59 * @time :2024/1/8 9:05 59 * @time :2024/1/8 9:05
60 */ 60 */
61 public function count($project_id,$url,$is_upgrade = 0){ 61 public function count($project_id,$url,$is_upgrade = 0){
62 - $data = [];  
63 $list = DB::connection('custom_mysql')->table('gl_customer_visit') 62 $list = DB::connection('custom_mysql')->table('gl_customer_visit')
64 ->select(DB::raw('DATE_FORMAT(updated_date, "%Y-%m") as month')) 63 ->select(DB::raw('DATE_FORMAT(updated_date, "%Y-%m") as month'))
65 ->orderBy('month', 'asc') 64 ->orderBy('month', 'asc')
66 ->groupBy('month')->get()->toArray(); 65 ->groupBy('month')->get()->toArray();
67 - foreach ($list as $v){  
68 - $data[] = $v->month; 66 + $data = [];
  67 + if (!empty($list)) {
  68 + // 提取已有月份
  69 + foreach ($list as $v) {
  70 + $data[] = $v->month;
  71 + }
  72 + // 生成连续月份
  73 + $startMonth = $data[0];
  74 + $endMonth = end($data);
  75 + $fullMonths = [];
  76 + $current = $startMonth;
  77 + while ($current <= $endMonth) {
  78 + $fullMonths[] = $current;
  79 + $current = date('Y-m', strtotime($current . ' +1 month'));
  80 + }
  81 + $data = $fullMonths;
  82 + } else {
  83 + $data = [];
69 } 84 }
70 - $list = $this->fillMissingMonths($data); 85 + $list = $data;
71 foreach ($list as $v){ 86 foreach ($list as $v){
72 $arr = []; 87 $arr = [];
73 $monthCountModel = new MonthCount(); 88 $monthCountModel = new MonthCount();
@@ -179,38 +194,4 @@ class MonthProjectCount extends Command @@ -179,38 +194,4 @@ class MonthProjectCount extends Command
179 $arr['referrer_port'] = json_encode($referrer_port); 194 $arr['referrer_port'] = json_encode($referrer_port);
180 return $arr; 195 return $arr;
181 } 196 }
182 -  
183 - /**  
184 - * @remark :补齐月份  
185 - * @name :fillMissingMonths  
186 - * @author :lyh  
187 - * @method :post  
188 - * @time :2024/8/14 11:11  
189 - */  
190 - public function fillMissingMonths($dates) {  
191 - // 将字符串日期转换为 Carbon 对象  
192 - $carbonDates = array_map(function($date) {  
193 - return Carbon::createFromFormat('Y-m', $date);  
194 - }, $dates);  
195 - // 排序日期,确保列表按时间顺序排列  
196 - usort($carbonDates, function($a, $b) {  
197 - return $a->gt($b);  
198 - });  
199 - // 用于存储完整日期的数组  
200 - $completeDates = [];  
201 - // 遍历日期列表,补齐中间缺失的月份  
202 - for ($i = 0; $i < count($carbonDates) - 1; $i++) {  
203 - $current = $carbonDates[$i];  
204 - $next = $carbonDates[$i + 1];  
205 - // 将当前月份加入完整日期数组  
206 - array_push($completeDates, $current->format('Y-m'));  
207 - // 循环补齐中间缺失的月份  
208 - while ($current->addMonth()->lt($next)) {  
209 - array_push($completeDates, $current->format('Y-m'));  
210 - }  
211 - }  
212 - // 加入最后一个月份  
213 - array_push($completeDates, $carbonDates[count($carbonDates) - 1]->format('Y-m'));  
214 - return $completeDates;  
215 - }  
216 } 197 }
@@ -53,24 +53,28 @@ class SendProduct extends Command @@ -53,24 +53,28 @@ class SendProduct extends Command
53 if(empty($domain)){ 53 if(empty($domain)){
54 continue; 54 continue;
55 } 55 }
56 - $arr1 = $this->sendProduct();  
57 - $arr2 = $this->sendBlog();  
58 - $arr3 = $this->sendNews();  
59 - $url = array_merge((array)$arr1,(array)$arr2,(array)$arr3);  
60 - if(!empty($url)){  
61 - $c_url = $domain.'api/update_page/';  
62 - $param = [  
63 - 'project_id' => $v['id'],  
64 - 'type' => 1,  
65 - 'route' => 3,  
66 - 'url' => $url,  
67 - 'language'=> [],  
68 - 'is_sitemap' => 0  
69 - ];  
70 - http_post($c_url, json_encode($param)); 56 + try {
  57 + $arr1 = $this->sendProduct();
  58 + $arr2 = $this->sendBlog();
  59 + $arr3 = $this->sendNews();
  60 + $url = array_merge((array)$arr1,(array)$arr2,(array)$arr3);
  61 + if(!empty($url)){
  62 + $c_url = $domain.'api/update_page/';
  63 + $param = [
  64 + 'project_id' => $v['id'],
  65 + 'type' => 1,
  66 + 'route' => 3,
  67 + 'url' => $url,
  68 + 'language'=> [],
  69 + 'is_sitemap' => 0
  70 + ];
  71 + //TODO::通知C端生成界面
  72 + http_post($c_url, json_encode($param));
  73 + }
  74 + }catch (\Exception $e){
  75 + DB::disconnect('custom_mysql');
  76 + continue;
71 } 77 }
72 - //TODO::通知C端生成界面  
73 - DB::disconnect('custom_mysql');  
74 } 78 }
75 echo date('Y-m-d H:i:s') . 'end' . PHP_EOL; 79 echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;
76 } 80 }
@@ -83,7 +87,6 @@ class SendProduct extends Command @@ -83,7 +87,6 @@ class SendProduct extends Command
83 * @time :2024/8/30 14:44 87 * @time :2024/8/30 14:44
84 */ 88 */
85 public function sendProduct(){ 89 public function sendProduct(){
86 - $start_date = date('Y-m-d 00:00:00');  
87 $end_date = date('Y-m-d 23:59:59'); 90 $end_date = date('Y-m-d 23:59:59');
88 $productModel = new Product(); 91 $productModel = new Product();
89 $arr = $productModel->formatQuery(['send_time'=>['<=',$end_date],'status'=>3])->pluck('route')->toArray(); 92 $arr = $productModel->formatQuery(['send_time'=>['<=',$end_date],'status'=>3])->pluck('route')->toArray();
@@ -99,7 +102,6 @@ class SendProduct extends Command @@ -99,7 +102,6 @@ class SendProduct extends Command
99 * @time :2024/8/30 15:19 102 * @time :2024/8/30 15:19
100 */ 103 */
101 public function sendBlog(){ 104 public function sendBlog(){
102 - $start_date = date('Y-m-d 00:00:00');  
103 $end_date = date('Y-m-d 23:59:59'); 105 $end_date = date('Y-m-d 23:59:59');
104 $blogModel = new Blog(); 106 $blogModel = new Blog();
105 $arr = $blogModel->formatQuery(['release_at'=>['<=',$end_date],'status'=>3])->pluck('url')->toArray(); 107 $arr = $blogModel->formatQuery(['release_at'=>['<=',$end_date],'status'=>3])->pluck('url')->toArray();
@@ -115,7 +117,6 @@ class SendProduct extends Command @@ -115,7 +117,6 @@ class SendProduct extends Command
115 * @time :2024/8/30 15:19 117 * @time :2024/8/30 15:19
116 */ 118 */
117 public function sendNews(){ 119 public function sendNews(){
118 - $start_date = date('Y-m-d 00:00:00');  
119 $end_date = date('Y-m-d 23:59:59'); 120 $end_date = date('Y-m-d 23:59:59');
120 $newsModel = new News(); 121 $newsModel = new News();
121 $arr = $newsModel->formatQuery(['release_at'=>['<=',$end_date],'status'=>3])->pluck('url')->toArray(); 122 $arr = $newsModel->formatQuery(['release_at'=>['<=',$end_date],'status'=>3])->pluck('url')->toArray();
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2025/10/27
  6 + * Time: 13:42
  7 + */
  8 +namespace App\Console\Commands\Product;
  9 +
  10 +use App\Console\Commands\Tdk\UpdateSeoTdk;
  11 +use App\Models\Product\Keyword;
  12 +use App\Models\Project\Project;
  13 +use App\Services\ProjectServer;
  14 +use Illuminate\Console\Command;
  15 +use Illuminate\Support\Arr;
  16 +use Illuminate\Support\Str;
  17 +
  18 +class SplicePrefix extends Command
  19 +{
  20 + /**
  21 + * The name and signature of the console command.
  22 + *
  23 + * @var string
  24 + */
  25 + protected $signature = 'splice_prefix';
  26 +
  27 + /**
  28 + * The console command description.
  29 + *
  30 + * @var string
  31 + */
  32 + protected $description = '未达标项目,拼接关键词聚合页前缀';
  33 +
  34 + /**
  35 + * @return bool
  36 + */
  37 + public function handle()
  38 + {
  39 + #TODO 获取当日不达标项目, 检查关键词前缀拼接
  40 + $project_ids = $this->getProject();
  41 + if (empty($project_ids))
  42 + return true;
  43 +
  44 + foreach ($project_ids as $project_id) {
  45 + if ($project_id == 1)
  46 + continue;
  47 + $this->output('project start: ' . $project_id);
  48 + $this->bind($project_id);
  49 + }
  50 + return true;
  51 + }
  52 +
  53 + /**
  54 + * @param $project_id
  55 + * @return bool
  56 + */
  57 + public function bind($project_id)
  58 + {
  59 + $project = ProjectServer::useProject($project_id);
  60 +
  61 + // 客户前缀
  62 + $tdk_class = new UpdateSeoTdk();
  63 + $info = $tdk_class->getDeployOptimize($project_id);
  64 + $fix_keyword = explode(",", $info['keyword_prefix']);
  65 + $fix_keyword = array_filter($fix_keyword);
  66 +
  67 + // 所有前缀
  68 + $all_prefixes = $tdk_class->getAllPrefix(1, $project_id);
  69 + $all_prefixes = array_map('strtolower', $all_prefixes);
  70 +
  71 + $keywords = Keyword::select(['id', 'title', 'seo_title'])->get();
  72 + foreach ($keywords as $item) {
  73 + $this_fix_keyword = $fix_keyword;
  74 + if (empty($item->title))
  75 + continue;
  76 +
  77 + $this->output('keyword id:' . $item->id . ' | title: ' . $item->title . ' | old seo title: ' . $item->seo_title);
  78 +
  79 + // 没有 SEO Title 直接生成
  80 + if (empty($item->seo_title)) {
  81 + $prefix = $tdk_class->getPrefixKeyword($project_id, 'prefix', 2, $item->title);
  82 + $suffix = $tdk_class->getPrefixKeyword($project_id, 'suffix', 2, trim($prefix . ' ' . $item->title));
  83 + if(Str::startsWith($suffix, ', ')){
  84 + $seo_title = $prefix . ' ' . $item->title . $suffix;
  85 + }else{
  86 + $seo_title = $prefix . ' ' . $item->title . ' ' . $suffix;
  87 + }
  88 +// $item->seo_title = trim($seo_title);
  89 +// $item->save();
  90 + $this->output('new seo title: ' . $seo_title);
  91 + continue;
  92 + }
  93 +
  94 + // 有 SEO Title 需要分析前后缀
  95 + $start = strpos($item->seo_title, $item->title);
  96 +
  97 + // Title 和 SEO Title 不存在包含关系
  98 + if ($start === FALSE) {
  99 + $this->output('Title 和 SEO Title 不存在包含关系');
  100 + continue;
  101 + }
  102 +
  103 + $prefix = $start == 0 ? '' : trim(substr($item->seo_title, 0, $start));
  104 + $prefix_array = explode(' ', $prefix);
  105 + $prefix_array = array_filter($prefix_array);
  106 + $need_num = 2 - count($prefix_array);
  107 + // 已经有两个前缀, 不在处理
  108 + if ($need_num <= 0) {
  109 + $this->output('已经有两个前缀, 不在处理');
  110 + continue;
  111 + }
  112 +
  113 + // 关键词最后一个词是前缀的词,前后缀都不拼
  114 + $title_words = explode(' ', strtolower($item->title));
  115 +
  116 + // 关键词最后一个词是前缀的词,前后缀都不拼
  117 + if(in_array(Arr::last($title_words), $all_prefixes)) {
  118 + $this->output('关键词最后一个词是前缀的词, 前后缀都不拼');
  119 + continue;
  120 + }
  121 +
  122 + // in,for,with,to,near,from 这些介词 只拼前缀,不拼后缀
  123 + $ban = [];
  124 +
  125 + // 关键词本身包含了前缀,也可以再拼一个不重复的前缀, 包含两个前缀就不拼前缀了
  126 + foreach ($title_words as $title_word) {
  127 + if(in_array($title_word, $all_prefixes)){
  128 + $ban[] = $title_word;
  129 + }
  130 + }
  131 + $need_num = $need_num - count($ban);
  132 +
  133 + // 关键词本身包含前缀,包含关键词大于等于需要的前缀,当前关键词不需要处理
  134 + if ($need_num <= 0) {
  135 + $this->output('关键词本身包含前缀,包含关键词大于等于需要的前缀,当前关键词不需要处理');
  136 + continue;
  137 + }
  138 +
  139 +
  140 + // services/service 结尾的词,后缀不拼manufacturer,factory
  141 + // manufacturer,factory 结尾的词,后缀不拼 services/service
  142 + // 有wholesale或cheap的词,后缀不拼 manufacturer,factory,exporter,company
  143 +
  144 + // 关键词以manufacturer,factory,exporter,company结尾, 前缀不拼wholesale或cheap的词
  145 + if (Str::endsWith(strtolower($item->title), ['manufacturer', 'manufacturers', 'factory', 'factories', 'exporter', 'exporters', 'company', 'companies', 'supplier', 'suppliers']))
  146 + $ban = array_merge($ban, ['wholesale', 'cheap', 'buy']);
  147 +
  148 +
  149 + foreach ($this_fix_keyword as $k => $keyword) {
  150 + // 被禁用的关键词
  151 + if (in_array(strtolower(Str::plural($keyword)), $ban)) {
  152 + unset($this_fix_keyword[$k]);
  153 + }
  154 + if (in_array(strtolower(Str::singular($keyword)), $ban)) {
  155 + unset($this_fix_keyword[$k]);
  156 + }
  157 + }
  158 + $this_fix_keyword = array_diff($this_fix_keyword, $prefix_array);
  159 + shuffle($this_fix_keyword);
  160 + $need_keyword = [];
  161 + foreach ($this_fix_keyword as $v) {
  162 + if ($need_num == 0)
  163 + break;
  164 +
  165 + $is_repeat = false;
  166 + foreach ($need_keyword as $keyword) {
  167 + if (Str::singular($keyword) == Str::singular($v)) {
  168 + $is_repeat = true;
  169 + break;
  170 + }
  171 + }
  172 + if ($is_repeat)
  173 + continue;
  174 +
  175 + $need_keyword[] = $v;
  176 + $need_num--;
  177 + }
  178 +// $item->seo_title = trim(implode(' ', $need_keyword) . ' ' . trim($item->seo_title));
  179 +// $item->save();
  180 + $this->output('new seo title: ' . implode(' ', $need_keyword) . ' ' . trim($item->seo_title));
  181 + }
  182 + return true;
  183 + }
  184 +
  185 + /**
  186 + * 获取当日未达标项目
  187 + * @return mixed
  188 + */
  189 + public function getProject()
  190 + {
  191 + $project_ids = Project::where(['type' => Project::TYPE_TWO, 'project_type' => Project::TYPE_ZERO, 'delete_status' => Project::IS_DEL_FALSE, 'is_remain_today' => 0])->pluck('id')->toArray();
  192 + return $project_ids;
  193 + }
  194 +
  195 + /**
  196 + * 输出日志
  197 + * @param $message
  198 + * @return bool
  199 + */
  200 + public function output($message)
  201 + {
  202 + $message = now() . ' ' . $message . PHP_EOL;
  203 + file_put_contents(storage_path('logs/splice_prefix.log'), $message, FILE_APPEND);
  204 + echo $message;
  205 + return true;
  206 + }
  207 +}
@@ -171,6 +171,10 @@ class HtmlCollect extends Command @@ -171,6 +171,10 @@ class HtmlCollect extends Command
171 $html = str_replace('Broflanilide', '', $html); 171 $html = str_replace('Broflanilide', '', $html);
172 $html = str_replace('broflanilide', '', $html); 172 $html = str_replace('broflanilide', '', $html);
173 } 173 }
  174 + if ($project_id == 587) {
  175 + //437项目单词替换
  176 + $html = str_replace('Horny Goat Weed', 'Icariin', $html);
  177 + }
174 $collect_info->html = $html; 178 $collect_info->html = $html;
175 $collect_info->status = CollectTask::STATUS_COM; 179 $collect_info->status = CollectTask::STATUS_COM;
176 $collect_info->save(); 180 $collect_info->save();
@@ -138,6 +138,10 @@ class ProjectUpdate extends Command @@ -138,6 +138,10 @@ class ProjectUpdate extends Command
138 //2078项目单词替换 138 //2078项目单词替换
139 $replace = ['Broflanilide' => '', 'broflanilide' => '']; 139 $replace = ['Broflanilide' => '', 'broflanilide' => ''];
140 } 140 }
  141 + if ($project_id == 587) {
  142 + //587项目单词替换
  143 + $replace = ['Horny Goat Weed' => 'Icariin'];
  144 + }
141 145
142 //设置数据库 146 //设置数据库
143 $project = ProjectServer::useProject($project_id); 147 $project = ProjectServer::useProject($project_id);
@@ -322,6 +326,16 @@ class ProjectUpdate extends Command @@ -322,6 +326,16 @@ class ProjectUpdate extends Command
322 //分类 326 //分类
323 $category_id = ''; 327 $category_id = '';
324 $category_arr = []; 328 $category_arr = [];
  329 + if ($project_id == 596 && empty($item['category'])) {
  330 + //596项目,产品没有分类,默认属于Featured分类
  331 + $item['category'] = [
  332 + [
  333 + 'id' => 623,
  334 + 'name' => 'Featured',
  335 + 'pid' => 0
  336 + ]
  337 + ];
  338 + }
325 if ($item['category'] ?? []) { 339 if ($item['category'] ?? []) {
326 if ($project_id == 4075 && count($item['category']) == 1 && $item['category'][0]['name'] == 'Featured') { 340 if ($project_id == 4075 && count($item['category']) == 1 && $item['category'][0]['name'] == 'Featured') {
327 //4075项目特殊处理:不采集Featured分类下的产品 341 //4075项目特殊处理:不采集Featured分类下的产品
@@ -31,15 +31,17 @@ class GeoController extends BaseController @@ -31,15 +31,17 @@ class GeoController extends BaseController
31 try { 31 try {
32 $token = trim($this->param['token']); 32 $token = trim($this->param['token']);
33 $param = Crypt::decrypt($token); 33 $param = Crypt::decrypt($token);
34 - if ($param['send_at'] + 86400 < time()) {}  
35 - $project_id = $param['project_id'];  
36 - } catch (\Exception $e) {  
37 - return $this->error('非法请求'); 34 + }catch (\Exception $e){
  35 + $this->response('非法请求',Code::SYSTEM_ERROR);
  36 + }
  37 + if ($param['send_at'] + 86400 < time()) {
  38 + $this->response('非法请求,已过期',Code::SYSTEM_ERROR);
38 } 39 }
  40 + $project_id = $param['project_id'];
39 $projectModel = new Project(); 41 $projectModel = new Project();
40 - $projectInfo = $projectModel->read(['project_id' => $project_id],['title','version']); 42 + $projectInfo = $projectModel->read(['id' => $project_id],['title','version']);
41 $geoWritingsModel = new GeoWritings(); 43 $geoWritingsModel = new GeoWritings();
42 - $lists = $geoWritingsModel->list(['project_id' => $project_id, 'status' => 2 ,'is_del' => GeoWritings::IS_DEL_FALSE],'id',['title', 'status', 'uniqid', 'confirm_at']); 44 + $lists = $geoWritingsModel->list(['project_id' => $project_id, 'status' => ['in',[GeoWritings::STATUS_RUNNING,GeoWritings::STATUS_FINISH]] ,'is_del' => GeoWritings::IS_DEL_FALSE],'id',['title', 'status', 'uniqid', 'confirm_at']);
43 $result = [ 45 $result = [
44 'project' => $projectInfo, 46 'project' => $projectInfo,
45 'list' => $lists 47 'list' => $lists
@@ -93,7 +95,7 @@ class GeoController extends BaseController @@ -93,7 +95,7 @@ class GeoController extends BaseController
93 $this->param['content_length'] = strlen($this->param['content']); 95 $this->param['content_length'] = strlen($this->param['content']);
94 $this->param['status'] = GeoWritings::STATUS_FINISH; 96 $this->param['status'] = GeoWritings::STATUS_FINISH;
95 $geoWritingsModel->edit($this->param,['uniqid' => $token]); 97 $geoWritingsModel->edit($this->param,['uniqid' => $token]);
96 - return true; 98 + $this->response('success',Code::SUCCESS);
97 } 99 }
98 100
99 /** 101 /**
@@ -106,13 +108,16 @@ class GeoController extends BaseController @@ -106,13 +108,16 @@ class GeoController extends BaseController
106 $token = trim($this->param['token']); 108 $token = trim($this->param['token']);
107 $data = GeoConfirm::where(['uniqid' => $token])->first(); 109 $data = GeoConfirm::where(['uniqid' => $token])->first();
108 if (empty($data)){ 110 if (empty($data)){
109 - return $this->error('当前授权已失效'); 111 + return $this->error('确认链接已重置,请查看最新推送链接!');
110 } 112 }
111 $content = explode("\n", $data->content); 113 $content = explode("\n", $data->content);
112 $confirm = explode("\n", $data->confirm); 114 $confirm = explode("\n", $data->confirm);
113 $type = $data->type; 115 $type = $data->type;
114 $status = $data->status; 116 $status = $data->status;
115 - $result = compact('content', 'confirm', 'type', 'status'); 117 + $projectModel = new Project();
  118 + $projectInfo = $projectModel->read(['id' => $data->project_id],['title','version']);
  119 + $project_title = $projectInfo['title'] ?? '';
  120 + $result = compact('content', 'confirm', 'type', 'status', 'project_title');
116 $this->response('success',Code::SUCCESS,$result); 121 $this->response('success',Code::SUCCESS,$result);
117 } 122 }
118 123
@@ -134,6 +139,8 @@ class GeoController extends BaseController @@ -134,6 +139,8 @@ class GeoController extends BaseController
134 ]); 139 ]);
135 $geoConfirmModel = new GeoConfirm(); 140 $geoConfirmModel = new GeoConfirm();
136 $this->param['status'] = $geoConfirmModel::STATUS_FINISH; 141 $this->param['status'] = $geoConfirmModel::STATUS_FINISH;
  142 + $this->param['confirm_ip'] = $this->request->ip();
  143 + $this->param['confirm_at'] = date('Y-m-d H:i:s');
137 $result = $geoConfirmModel->edit($this->param,['uniqid'=>$this->param['uniqid']]); 144 $result = $geoConfirmModel->edit($this->param,['uniqid'=>$this->param['uniqid']]);
138 $this->response('success',Code::SUCCESS,$result); 145 $this->response('success',Code::SUCCESS,$result);
139 } 146 }
@@ -205,4 +205,22 @@ class NoticeController extends BaseController @@ -205,4 +205,22 @@ class NoticeController extends BaseController
205 MessagePush::addInquiryMessage(0, $project->id, $country, $name, $submit); 205 MessagePush::addInquiryMessage(0, $project->id, $country, $name, $submit);
206 return $this->success(); 206 return $this->success();
207 } 207 }
  208 +
  209 + /**
  210 + * 获取6.0所有使用域名
  211 + * @return false|string
  212 + * @author Akun
  213 + * @date 2025/10/30 10:42
  214 + */
  215 + public function getAllDomain(){
  216 + $domainModel = new DomainInfo();
  217 + $lists = $domainModel->list(['status'=>DomainInfo::STATUS_ONE],'id',['domain','project_id'],'asc');
  218 +
  219 + $project_model = new Project();
  220 + foreach ($lists as &$v){
  221 + $pro_info = $project_model->read(['id'=>$v['project_id']],['company']);
  222 + $v['company'] = $pro_info ? $pro_info['company'] : '';
  223 + }
  224 + return $this->success($lists);
  225 + }
208 } 226 }
@@ -29,6 +29,27 @@ class GeoConfirmController extends BaseController @@ -29,6 +29,27 @@ class GeoConfirmController extends BaseController
29 } 29 }
30 30
31 /** 31 /**
  32 + * @remark :确认信息详情
  33 + * @name :getInfo
  34 + * @author :lyh
  35 + * @method :post
  36 + * @time :2025/10/30 09:08
  37 + */
  38 + public function getInfo()
  39 + {
  40 + $this->request->validate([
  41 + 'project_id' => 'required',
  42 + 'type' => 'required|integer',
  43 + ], [
  44 + 'project_id.required' => '项目ID不能为空',
  45 + 'type.required' => '确定数据类型不能为空',
  46 + 'type.integer' => '确定数据类型不正确',
  47 + ]);
  48 + $data = $this->logic->getConfirmInfo();
  49 + $this->response('success', Code::SUCCESS, $data);
  50 + }
  51 +
  52 + /**
32 * 保存确认数据, 并推送微信群 53 * 保存确认数据, 并推送微信群
33 * @param Request $request 54 * @param Request $request
34 * @throws \App\Exceptions\AsideGlobalException 55 * @throws \App\Exceptions\AsideGlobalException
@@ -50,4 +71,26 @@ class GeoConfirmController extends BaseController @@ -50,4 +71,26 @@ class GeoConfirmController extends BaseController
50 $data = $this->logic->saveConfirmContent($this->param); 71 $data = $this->logic->saveConfirmContent($this->param);
51 $this->response('success', Code::SUCCESS, $data); 72 $this->response('success', Code::SUCCESS, $data);
52 } 73 }
  74 +
  75 + /**
  76 + * @remark :保存确认信息
  77 + * @name :saveInfo
  78 + * @author :lyh
  79 + * @method :post
  80 + * @time :2025/10/30 11:30
  81 + */
  82 + public function saveInfo()
  83 + {
  84 + $this->request->validate([
  85 + 'id' => 'required',
  86 + 'confirm' => 'required',
  87 + 'confirm_num' => 'required',
  88 + ], [
  89 + 'id.required' => '主键id不能为空',
  90 + 'confirm.required' => '客户确认内容不能为空',
  91 + 'confirm_num.max' => '客户确认数量不能为空',
  92 + ]);
  93 + $data = $this->logic->saveConfirmInfo();
  94 + $this->response('success', Code::SUCCESS, $data);
  95 + }
53 } 96 }
@@ -68,4 +68,22 @@ class GeoController extends BaseController @@ -68,4 +68,22 @@ class GeoController extends BaseController
68 $data = $this->logic->saveConfig($this->param); 68 $data = $this->logic->saveConfig($this->param);
69 $this->response('success', Code::SUCCESS, $data); 69 $this->response('success', Code::SUCCESS, $data);
70 } 70 }
  71 +
  72 + /**
  73 + * @remark :统计数据
  74 + * @name :getCount
  75 + * @author :lyh
  76 + * @method :post
  77 + * @time :2025/10/30 10:37
  78 + */
  79 + public function getCount()
  80 + {
  81 + $this->request->validate([
  82 + 'project_id' => 'required',
  83 + ], [
  84 + 'project_id.required' => '项目ID不能为空',
  85 + ]);
  86 + $data = $this->logic->getCount();
  87 + $this->response('success', Code::SUCCESS, $data);
  88 + }
71 } 89 }
@@ -32,7 +32,7 @@ class InquiryForwardController extends BaseController @@ -32,7 +32,7 @@ class InquiryForwardController extends BaseController
32 $this->map['message'] = ['like', '%' . $this->map['message'] . '%']; 32 $this->map['message'] = ['like', '%' . $this->map['message'] . '%'];
33 } 33 }
34 if (isset($this->param['start_date']) && isset($this->param['end_date'])) { 34 if (isset($this->param['start_date']) && isset($this->param['end_date'])) {
35 - $this->map['inquiry_date'] = ['between', [$this->map['start_date'] . ' 00:00:00', $this->map['end_date'] . ' 00:00:00']]; 35 + $this->map['inquiry_date'] = ['between', [$this->map['start_date'] . ' 00:00:00', $this->map['end_date'] . ' 23:59:59']];
36 unset($this->map['start_date']); 36 unset($this->map['start_date']);
37 unset($this->map['end_date']); 37 unset($this->map['end_date']);
38 } elseif (isset($this->param['start_date'])) { 38 } elseif (isset($this->param['start_date'])) {
@@ -462,7 +462,7 @@ class ProjectController extends BaseController @@ -462,7 +462,7 @@ class ProjectController extends BaseController
462 } 462 }
463 $manageModel = new ManageHr(); 463 $manageModel = new ManageHr();
464 //geo项目 464 //geo项目
465 - if (($item['plan'] == 0) && ($item['seo_plan'] != 0)) { 465 + if (($item['seo_plan'] != 0) && ($item['seo_plan'] != 9 || $item['plan'] == 0)) {
466 //geo项目负责人 466 //geo项目负责人
467 $geoConfModel = new GeoConf(); 467 $geoConfModel = new GeoConf();
468 $manage_id = $geoConfModel->getValue(['project_id' => $item['id']], 'manager_id'); 468 $manage_id = $geoConfModel->getValue(['project_id' => $item['id']], 'manager_id');
@@ -24,7 +24,7 @@ class AiBlogController extends BaseController @@ -24,7 +24,7 @@ class AiBlogController extends BaseController
24 if(isset($this->map['new_title']) && !empty($this->map['new_title'])){ 24 if(isset($this->map['new_title']) && !empty($this->map['new_title'])){
25 $this->map['new_title'] = ['like', '%'.$this->map['new_title'].'%']; 25 $this->map['new_title'] = ['like', '%'.$this->map['new_title'].'%'];
26 } 26 }
27 - $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','uuid','created_at','updated_at']);
28 if(!empty($lists) && !empty($lists['list'])){ 28 if(!empty($lists) && !empty($lists['list'])){
29 foreach ($lists['list'] as $k => $v){ 29 foreach ($lists['list'] as $k => $v){
30 $v['image'] = getImageUrl($v['image']); 30 $v['image'] = getImageUrl($v['image']);
@@ -236,8 +236,11 @@ class CNoticeController extends BaseController @@ -236,8 +236,11 @@ class CNoticeController extends BaseController
236 if(!$project_info){ 236 if(!$project_info){
237 $this->fail('未查询到项目数据'); 237 $this->fail('未查询到项目数据');
238 } 238 }
  239 + $project_ids = [
  240 + 4041,4094,3514
  241 + ];
239 // --------------------------------------------------- 特殊处理通知生成页面 -------------------------------------------------------------- 242 // --------------------------------------------------- 特殊处理通知生成页面 --------------------------------------------------------------
240 - if ($type == 2 && ($project_id != 4041) && ($project_id != 4094) && ($project_info['main_lang_id'] == 8)) { 243 + if ($type == 2 && !in_array($project_id,$project_ids) && ($project_info['main_lang_id'] == 8)) {
241 $this->fail('申请项目主语种为俄语,禁止翻译小语种,如若需要翻译小语种, 请联系售后人员确认!'); 244 $this->fail('申请项目主语种为俄语,禁止翻译小语种,如若需要翻译小语种, 请联系售后人员确认!');
242 } 245 }
243 246
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :SettingFaqController.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/10/29 16:32
  8 + */
  9 +
  10 +namespace App\Http\Controllers\Bside\Setting;
  11 +
  12 +use App\Enums\Common\Code;
  13 +use App\Http\Controllers\Bside\BaseController;
  14 +use App\Http\Logic\Bside\Setting\SettingFaqLogic;
  15 +use App\Models\RouteMap\RouteMap;
  16 +use Illuminate\Http\Request;
  17 +
  18 +class SettingFaqController extends BaseController
  19 +{
  20 +
  21 + public function __construct(Request $request)
  22 + {
  23 + parent::__construct($request);
  24 + $this->logic = new SettingFaqLogic();
  25 + }
  26 +
  27 + /**
  28 + * @remark :获取所有路由
  29 + * @name :getRouteList
  30 + * @author :lyh
  31 + * @method :post
  32 + * @time :2025/10/30 09:35
  33 + */
  34 + public function getRouteList(){
  35 + $data = $this->logic->getRouteList();
  36 + $this->response('success',Code::SUCCESS,$data);
  37 + }
  38 +
  39 + /**
  40 + * @remark :faq列表页数据
  41 + * @name :lists
  42 + * @author :lyh
  43 + * @method :post
  44 + * @time :2025/10/29 16:38
  45 + */
  46 + public function lists()
  47 + {
  48 + $lists = $this->logic->getFaqLists($this->map,$this->page,$this->row,$this->order);
  49 + $this->response('success',Code::SUCCESS,$lists);
  50 + }
  51 +
  52 + /**
  53 + * @remark :获取详情
  54 + * @name :getInfo
  55 + * @author :lyh
  56 + * @method :post
  57 + * @time :2025/10/30 09:28
  58 + */
  59 + public function getInfo()
  60 + {
  61 + $this->request->validate([
  62 + 'id'=>'required',
  63 + ],[
  64 + 'id.required' => 'ID不能为空',
  65 + ]);
  66 + $data = $this->logic->getFaqInfo();
  67 + $this->response('success',Code::SUCCESS,$data);
  68 + }
  69 +
  70 + /**
  71 + * @remark :保存faq数据
  72 + * @name :saveFaq
  73 + * @author :lyh
  74 + * @method :post
  75 + * @time :2025/10/29 17:21
  76 + */
  77 + public function saveFaq()
  78 + {
  79 + $this->request->validate([
  80 + 'route'=>'required',
  81 + 'qa'=>'required',
  82 + ],[
  83 + 'route.required' => '路由不能为空',
  84 + 'qa.required' => 'qa不能为空',
  85 + ]);
  86 + $data = $this->logic->saveFaq();
  87 + $this->response('success',Code::SUCCESS,$data);
  88 + }
  89 +
  90 + /**
  91 + * @remark :删除对应数据
  92 + * @name :deleteFaq
  93 + * @author :lyh
  94 + * @method :post
  95 + * @time :2025/10/29 17:23
  96 + */
  97 + public function deleteFaq(){
  98 + $this->request->validate([
  99 + 'id'=>'required|array',
  100 + ],[
  101 + 'id.required' => 'ID不能为空',
  102 + 'id.array' => 'ID为数组',
  103 + ]);
  104 + $data = $this->logic->deleteFaq();
  105 + $this->response('success',Code::SUCCESS,$data);
  106 + }
  107 +}
@@ -40,11 +40,11 @@ class GeoConfirmLogic extends BaseLogic @@ -40,11 +40,11 @@ class GeoConfirmLogic extends BaseLogic
40 public function saveConfirmContent($param) 40 public function saveConfirmContent($param)
41 { 41 {
42 try { 42 try {
43 - $info = $this->model->read(['project_id' => $param['project_id']]); 43 + $info = $this->model->read(['project_id' => $param['project_id'],'type' => $param['type']]);
44 if($info === false){ 44 if($info === false){
45 $id = $this->model->addReturnId($param); 45 $id = $this->model->addReturnId($param);
46 }else{ 46 }else{
47 - $id = $param['id']; 47 + $id = $info['id'];
48 $this->model->edit($param,['id'=>$info['id']]); 48 $this->model->edit($param,['id'=>$info['id']]);
49 } 49 }
50 $friend = ProjectAssociation::where(['project_id' => $param['project_id']])->first(); 50 $friend = ProjectAssociation::where(['project_id' => $param['project_id']])->first();
@@ -57,4 +57,35 @@ class GeoConfirmLogic extends BaseLogic @@ -57,4 +57,35 @@ class GeoConfirmLogic extends BaseLogic
57 } 57 }
58 return $this->success(['id'=>$id]); 58 return $this->success(['id'=>$id]);
59 } 59 }
  60 +
  61 + /**
  62 + * @remark :获取数据详情
  63 + * @name :getInfo
  64 + * @author :lyh
  65 + * @method :post
  66 + * @time :2025/10/30 09:13
  67 + */
  68 + public function getConfirmInfo()
  69 + {
  70 + $data = $this->model->read($this->param);
  71 + if($data === false){
  72 + $this->fail('当前数据不存在或者已被删除');
  73 + }
  74 + $data['confirm'] = $data['content'];
  75 + return $this->success($data);
  76 + }
  77 +
  78 + /**
  79 + * @remark :保存确认信息
  80 + * @name :saveConfirmInfo
  81 + * @author :lyh
  82 + * @method :post
  83 + * @time :2025/10/30 11:41
  84 + */
  85 + public function saveConfirmInfo()
  86 + {
  87 + $this->param['status'] = GeoConfirm::STATUS_FINISH;
  88 + $this->model->edit($this->param,['id'=>$this->param['id']]);
  89 + return $this->success(['id'=>$this->param['id']]);
  90 + }
60 } 91 }
@@ -9,8 +9,12 @@ @@ -9,8 +9,12 @@
9 9
10 namespace App\Http\Logic\Aside\Geo; 10 namespace App\Http\Logic\Aside\Geo;
11 11
  12 +use App\Console\Commands\Geo\GeoQuestionRes;
12 use App\Http\Logic\Aside\BaseLogic; 13 use App\Http\Logic\Aside\BaseLogic;
13 use App\Models\Geo\GeoConf; 14 use App\Models\Geo\GeoConf;
  15 +use App\Models\Geo\GeoLink;
  16 +use App\Models\Geo\GeoQuestion;
  17 +use App\Models\Geo\GeoWritings;
14 use App\Models\Manage\ManageHr; 18 use App\Models\Manage\ManageHr;
15 use App\Models\Project\KeywordPrefix; 19 use App\Models\Project\KeywordPrefix;
16 use App\Models\Project\Project; 20 use App\Models\Project\Project;
@@ -97,4 +101,20 @@ class GeoLogic extends BaseLogic @@ -97,4 +101,20 @@ class GeoLogic extends BaseLogic
97 return $this->success(['id'=>$id]); 101 return $this->success(['id'=>$id]);
98 } 102 }
99 103
  104 + /**
  105 + * @remark :获取统计数据
  106 + * @name :getCount
  107 + * @author :lyh
  108 + * @method :post
  109 + * @time :2025/10/30 10:39
  110 + */
  111 + public function getCount()
  112 + {
  113 + //获取问题数量
  114 + $geo_question_count = GeoQuestion::selectRaw('SUM(JSON_LENGTH(question)) as total_count')->where('project_id',$this->param['project_id'])->value('total_count');
  115 + $geo_pr_count = GeoLink::where('project_id',$this->param['project_id'])->count();
  116 + $geo_writings_count = GeoWritings::where('project_id',$this->param['project_id'])->count();
  117 + return $this->success(['geo_writings_count'=>$geo_writings_count,'geo_pr_count'=>$geo_pr_count,'geo_question_count'=>$geo_question_count]);
  118 + }
  119 +
100 } 120 }
@@ -54,6 +54,7 @@ class GeoWritingsLogic extends BaseLogic @@ -54,6 +54,7 @@ class GeoWritingsLogic extends BaseLogic
54 $id = $this->param['id']; 54 $id = $this->param['id'];
55 $this->model->edit($this->param,['id'=>$id]); 55 $this->model->edit($this->param,['id'=>$id]);
56 }else{ 56 }else{
  57 + $this->param['type'] = GeoWritings::TYPE_SUBMIT;
57 $this->param['uniqid'] = uniqid().$this->param['project_id']; 58 $this->param['uniqid'] = uniqid().$this->param['project_id'];
58 $id = $this->model->addReturnId($this->param); 59 $id = $this->model->addReturnId($this->param);
59 } 60 }
@@ -89,7 +90,10 @@ class GeoWritingsLogic extends BaseLogic @@ -89,7 +90,10 @@ class GeoWritingsLogic extends BaseLogic
89 public function sendWechatMessage() 90 public function sendWechatMessage()
90 { 91 {
91 $this->model->edit(['status'=>2],['status'=>1,'project_id'=>$this->param['project_id']]); 92 $this->model->edit(['status'=>2],['status'=>1,'project_id'=>$this->param['project_id']]);
92 - GeoWritings::sendConfirmMessage($this->param['project_id']);  
93 - return $this->success(); 93 + $data = GeoWritings::sendConfirmMessage($this->param['project_id']);
  94 + if($data === false){
  95 + $this->fail('项目未绑定微信群');
  96 + }
  97 + return $this->success($data);
94 } 98 }
95 } 99 }
@@ -17,6 +17,7 @@ use App\Models\Inquiry\InquiryRelayDetail; @@ -17,6 +17,7 @@ use App\Models\Inquiry\InquiryRelayDetail;
17 use App\Models\Inquiry\InquiryRelayDetailLog; 17 use App\Models\Inquiry\InquiryRelayDetailLog;
18 use App\Models\Manage\Manage; 18 use App\Models\Manage\Manage;
19 use Illuminate\Support\Arr; 19 use Illuminate\Support\Arr;
  20 +use Illuminate\Support\Facades\Cache;
20 use Illuminate\Support\Facades\DB; 21 use Illuminate\Support\Facades\DB;
21 use Illuminate\Support\Str; 22 use Illuminate\Support\Str;
22 23
@@ -525,13 +526,36 @@ class InquiryForwardLogic extends BaseLogic @@ -525,13 +526,36 @@ class InquiryForwardLogic extends BaseLogic
525 */ 526 */
526 public function inquiryManageCount() 527 public function inquiryManageCount()
527 { 528 {
528 - $type = $this->param['type'] ?? 1;//统计类型:1周统计,2月统计 529 + $data = Cache::get('inquiry_manage_count');
  530 + if (!$data) {
  531 + $manage_ids = ForwardCount::select('manage_id')->orderBy('manage_id', 'asc')->distinct()->pluck('manage_id')->toArray();
  532 + $manageModel = new Manage();
  533 +
  534 + //月统计
  535 + $data_month = [];
  536 + $data_month_total = [];
  537 + $now_month = date('Y-m');
  538 + $last_year_month = date('Y-m', strtotime('-11 months'));
  539 + while ($last_year_month <= $now_month) {
  540 + $month_arr = explode('-', $last_year_month);
  541 + $year = $month_arr[0];
  542 + $month = $month_arr[1];
  543 +
  544 + foreach ($manage_ids as $mid) {
  545 + $name = $manageModel->getName($mid);
  546 + $month_count = intval(ForwardCount::where('manage_id', $mid)->where('year', $year)->where('month', $month)->sum('count') ?? 0);
  547 + $data_month_total[$name] = ($data_month_total[$name] ?? 0) + $month_count;
  548 + $data_month[$last_year_month][$name] = $month_count;
  549 + }
  550 +
  551 + $last_year_month = date('Y-m', strtotime($last_year_month . ' +1 month'));
  552 + }
  553 + $data_month['total'] = $data_month_total;
  554 +
529 555
530 - $manage_ids = ForwardCount::select('manage_id')->orderBy('manage_id', 'asc')->distinct()->pluck('manage_id')->toArray();  
531 - $manageModel = new Manage();  
532 - $data = [];  
533 - if ($type == 1) {  
534 //周统计 556 //周统计
  557 + $data_week = [];
  558 + $data_week_total = [];
535 $now_day = date('Y-m-d'); 559 $now_day = date('Y-m-d');
536 $last_week_day = date('Y-m-d', strtotime('-1 week')); 560 $last_week_day = date('Y-m-d', strtotime('-1 week'));
537 while ($last_week_day < $now_day) { 561 while ($last_week_day < $now_day) {
@@ -542,27 +566,18 @@ class InquiryForwardLogic extends BaseLogic @@ -542,27 +566,18 @@ class InquiryForwardLogic extends BaseLogic
542 566
543 foreach ($manage_ids as $mid) { 567 foreach ($manage_ids as $mid) {
544 $name = $manageModel->getName($mid); 568 $name = $manageModel->getName($mid);
545 - $data[$last_week_day][$name] = ForwardCount::where('manage_id', $mid)->where('year', $year)->where('month', $month)->where('day', $day)->value('count') ?? 0; 569 + $day_count = ForwardCount::where('manage_id', $mid)->where('year', $year)->where('month', $month)->where('day', $day)->value('count') ?? 0;
  570 + $data_week_total[$name] = ($data_week_total[$name] ?? 0) + $day_count;
  571 + $data_week[substr($last_week_day, 5)][$name] = $day_count;
546 } 572 }
547 573
548 $last_week_day = date('Y-m-d', strtotime($last_week_day . ' +1 day')); 574 $last_week_day = date('Y-m-d', strtotime($last_week_day . ' +1 day'));
549 } 575 }
550 - } else {  
551 - //月统计  
552 - $now_month = date('Y-m');  
553 - $last_year_month = date('Y-m', strtotime('-11 months'));  
554 - while ($last_year_month <= $now_month) {  
555 - $month_arr = explode('-', $last_year_month);  
556 - $year = $month_arr[0];  
557 - $month = $month_arr[1]; 576 + $data_week['total'] = $data_week_total;
558 577
559 - foreach ($manage_ids as $mid) {  
560 - $name = $manageModel->getName($mid);  
561 - $data[$last_year_month][$name] = intval(ForwardCount::where('manage_id', $mid)->where('year', $year)->where('month', $month)->sum('count') ?? 0);  
562 - } 578 + $data = ['data_month' => $data_month, 'data_week' => $data_week];
563 579
564 - $last_year_month = date('Y-m', strtotime($last_year_month . ' +1 month'));  
565 - } 580 + Cache::add('inquiry_manage_count', $data);
566 } 581 }
567 582
568 return $this->success($data); 583 return $this->success($data);
@@ -201,7 +201,7 @@ class TicketUploadDataLogic extends BaseLogic @@ -201,7 +201,7 @@ class TicketUploadDataLogic extends BaseLogic
201 'title' => $info['text']['title'], 201 'title' => $info['text']['title'],
202 'thumb'=>$thumb, 202 'thumb'=>$thumb,
203 'gallery'=>$info['text']['image'] ?? [], 203 'gallery'=>$info['text']['image'] ?? [],
204 - 'intro'=>$info['text']['remark'], 204 + 'intro'=>$info['text']['intro'] ?? '',
205 'category_id'=>$category_id ?? '', 205 'category_id'=>$category_id ?? '',
206 'keyword_id'=>$keyword_id ?? '', 206 'keyword_id'=>$keyword_id ?? '',
207 'status'=>1, 207 'status'=>1,
@@ -242,6 +242,7 @@ class TicketUploadDataLogic extends BaseLogic @@ -242,6 +242,7 @@ class TicketUploadDataLogic extends BaseLogic
242 'name' => $info['text']['title'], 242 'name' => $info['text']['title'],
243 'image'=>$info['text']['image'], 243 'image'=>$info['text']['image'],
244 'text'=>$info['text']['remark'], 244 'text'=>$info['text']['remark'],
  245 + 'remark'=>$info['text']['intro'] ?? '',
245 'category_id'=>$category_id ?? '', 246 'category_id'=>$category_id ?? '',
246 'status'=>1, 247 'status'=>1,
247 ]; 248 ];
@@ -276,6 +277,7 @@ class TicketUploadDataLogic extends BaseLogic @@ -276,6 +277,7 @@ class TicketUploadDataLogic extends BaseLogic
276 'name' => $info['text']['title'], 277 'name' => $info['text']['title'],
277 'image'=>$info['text']['image'], 278 'image'=>$info['text']['image'],
278 'text'=>$info['text']['remark'], 279 'text'=>$info['text']['remark'],
  280 + 'remark'=>$info['text']['intro'] ?? '',
279 'category_id'=>$category_id ?? '', 281 'category_id'=>$category_id ?? '',
280 'status'=>1, 282 'status'=>1,
281 ]; 283 ];
@@ -187,7 +187,9 @@ class AiBlogLogic extends BaseLogic @@ -187,7 +187,9 @@ class AiBlogLogic extends BaseLogic
187 } 187 }
188 if(isset($param['id']) && !empty($param['id'])){ 188 if(isset($param['id']) && !empty($param['id'])){
189 $id = $param['id']; 189 $id = $param['id'];
190 - $data['task_id'] = $param['task_id']; 190 + if(!empty($param['task_id'])){
  191 + $data['task_id'] = $param['task_id'];
  192 + }
191 if(!isset($param['seo_keyword']) || empty($param['seo_keyword'])){ 193 if(!isset($param['seo_keyword']) || empty($param['seo_keyword'])){
192 $ai = "contains keyword {$param['title']} recommend 8 purchaser search keywords, separated by commas"; 194 $ai = "contains keyword {$param['title']} recommend 8 purchaser search keywords, separated by commas";
193 $text = Gpt::instance()->openai_chat_qqs($ai); 195 $text = Gpt::instance()->openai_chat_qqs($ai);
@@ -222,7 +224,7 @@ class AiBlogLogic extends BaseLogic @@ -222,7 +224,7 @@ class AiBlogLogic extends BaseLogic
222 //todo::更新列表页 224 //todo::更新列表页
223 shell_exec("php artisan save_ai_blog_list {$this->user['project_id']} > /dev/null 2>&1 &"); 225 shell_exec("php artisan save_ai_blog_list {$this->user['project_id']} > /dev/null 2>&1 &");
224 }else{ 226 }else{
225 - $this->fail('发布失败,请编辑后重新发布'); 227 + $this->fail('文章已发布,文章无法同步到列表,请编辑后保存');
226 } 228 }
227 return $this->success(); 229 return $this->success();
228 } 230 }
@@ -135,16 +135,23 @@ class GeoQuestionResLogic extends BaseLogic @@ -135,16 +135,23 @@ class GeoQuestionResLogic extends BaseLogic
135 ]; 135 ];
136 }else{ 136 }else{
137 $keywordUrlCount = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'hit'=>['!=',0]]); 137 $keywordUrlCount = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'hit'=>['!=',0]]);
  138 + $keywordArrs = [];
  139 + $urlArrs = [];
138 foreach ($list as $item){ 140 foreach ($list as $item){
  141 + $keywordArrs = array_merge($keywordArrs,$item['keywords'] ?? []);
  142 + $urlArrs = array_merge($urlArrs,$item['url'] ??[]);
139 $questionTotalCount += count($item['question'] ?? []); 143 $questionTotalCount += count($item['question'] ?? []);
140 - $keywordsTotalCount += count($item['keywords'] ?? []);  
141 - $urlTotalCount += count($item['url'] ?? []);  
142 foreach ($item['keywords'] as $keyWordItem){ 144 foreach ($item['keywords'] as $keyWordItem){
143 if (!array_key_exists($keyWordItem, $keywordArr)) { 145 if (!array_key_exists($keyWordItem, $keywordArr)) {
144 $keywordArr[$keyWordItem] = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'keywords'=>['like','%"'.$keyWordItem.'"%']]); 146 $keywordArr[$keyWordItem] = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'keywords'=>['like','%"'.$keyWordItem.'"%']]);
145 } 147 }
146 } 148 }
147 } 149 }
  150 + // 去重
  151 + $keywordArrs = array_unique($keywordArrs);
  152 + $keywordsTotalCount = count($keywordArrs);
  153 + $urlArrs = array_unique($urlArrs);
  154 + $urlTotalCount = count($urlArrs);
148 $data = [ 155 $data = [
149 'question_count'=>$questionTotalCount, 156 'question_count'=>$questionTotalCount,
150 'keywords_count'=>$keywordsTotalCount, 157 'keywords_count'=>$keywordsTotalCount,
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :SettingFaqLogic.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/10/29 16:34
  8 + */
  9 +
  10 +namespace App\Http\Logic\Bside\Setting;
  11 +
  12 +use App\Http\Logic\Bside\BaseLogic;
  13 +use App\Models\RouteMap\RouteMap;
  14 +use App\Models\WebSetting\SettingFaq;
  15 +
  16 +class SettingFaqLogic extends BaseLogic
  17 +{
  18 + public function __construct()
  19 + {
  20 + parent::__construct();
  21 + $this->model = new SettingFaq();
  22 + $this->param = $this->requestAll;
  23 + }
  24 +
  25 + /**
  26 + * @remark :获取数据
  27 + * @name :getRouteList
  28 + * @author :lyh
  29 + * @method :post
  30 + * @time :2025/10/30 09:36
  31 + */
  32 + public function getRouteList($map = [])
  33 + {
  34 + $routeModel = new RouteMap();
  35 + $list = $routeModel->list($map,'id',['*'],'desc',20);
  36 + return $this->success($list);
  37 + }
  38 +
  39 + /**
  40 + * @remark :获取列表页数据
  41 + * @name :getFaqLists
  42 + * @author :lyh
  43 + * @method :post
  44 + * @time :2025/10/29 16:50
  45 + */
  46 + public function getFaqLists($map = [],$page = 1, $row = 10,$order = 'id')
  47 + {
  48 + $lists = $this->model->lists($map,$page,$row,$order);
  49 + return $this->success($lists);
  50 + }
  51 +
  52 + /**
  53 + * @remark :获取详情数据
  54 + * @name :getFaqById
  55 + * @author :lyh
  56 + * @method :post
  57 + * @time :2025/10/30 09:29
  58 + */
  59 + public function getFaqInfo(){
  60 + $data = $this->model->read($this->param);
  61 + return $this->success($data);
  62 + }
  63 +
  64 + /**
  65 + * @remark :保存数据
  66 + * @name :saveFaq
  67 + * @author :lyh
  68 + * @method :post
  69 + * @time :2025/10/29 16:50
  70 + */
  71 + public function saveFaq()
  72 + {
  73 + //todo::根据路由获取对应数据详情
  74 + $routeModel = new RouteMap();
  75 + $routeInfo = $routeModel->read(['route'=>$this->param['route']],['source','source_id']);
  76 + if($routeInfo === false){
  77 + $this->fail('路由不存在');
  78 + }
  79 + $this->param['qa'] = json_encode($this->param['qa'],true);
  80 + $this->param['source'] = $routeInfo['source'];
  81 + $this->param['source_id'] = $routeInfo['source_id'];
  82 + if(isset($this->param['id']) && !empty($this->param['id'])){
  83 + $id = $this->param['id'];
  84 + $this->model->edit($this->param,['id'=>$id]);
  85 + }else{
  86 + $id = $this->model->addReturnId($this->param);
  87 + }
  88 + return $this->success(['id' => $id]);
  89 + }
  90 +
  91 + /**
  92 + * @remark :删除数据
  93 + * @name :deleteFaq
  94 + * @author :lyh
  95 + * @method :post
  96 + * @time :2025/10/29 17:27
  97 + */
  98 + public function deleteFaq(){
  99 + $this->model->del(['id'=>['in',$this->param['id']]]);
  100 + return $this->success();
  101 + }
  102 +}
@@ -35,7 +35,7 @@ class GeoConf extends Base @@ -35,7 +35,7 @@ class GeoConf extends Base
35 $optimize = Cache::get($key); 35 $optimize = Cache::get($key);
36 if (empty($optimize)) { 36 if (empty($optimize)) {
37 $optimize = ManageHr::where(['status' => ManageHr::STATUS_ONE, 'entry_position' => 46])->pluck('name', 'id')->toArray(); 37 $optimize = ManageHr::where(['status' => ManageHr::STATUS_ONE, 'entry_position' => 46])->pluck('name', 'id')->toArray();
38 - $optimize[1] = '陶婵'; 38 + $optimize[11] = '陶婵';
39 $optimize[875] = '艾媛媛'; 39 $optimize[875] = '艾媛媛';
40 ksort($optimize); 40 ksort($optimize);
41 Cache::put($key, $optimize, 3600); 41 Cache::put($key, $optimize, 3600);
@@ -79,7 +79,7 @@ class GeoWritings extends Base @@ -79,7 +79,7 @@ class GeoWritings extends Base
79 { 79 {
80 $friend = ProjectAssociation::where(['project_id' => $project_id])->first(); 80 $friend = ProjectAssociation::where(['project_id' => $project_id])->first();
81 if (empty($friend)) { 81 if (empty($friend)) {
82 - throw new \Exception('项目未绑定微信群'); 82 + return false;
83 } 83 }
84 $content_type = 'Link'; 84 $content_type = 'Link';
85 $send_time = now(); 85 $send_time = now();
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :SettingFaq.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/10/29 16:35
  8 + */
  9 +
  10 +namespace App\Models\WebSetting;
  11 +
  12 +use App\Helper\Arr;
  13 +use App\Models\Base;
  14 +
  15 +class SettingFaq extends Base
  16 +{
  17 + protected $table = 'gl_setting_faq';
  18 +
  19 + //连接数据库
  20 + protected $connection = 'custom_mysql';
  21 +
  22 + public function getQaAttribute($value)
  23 + {
  24 + $value = Arr::s2a($value);
  25 + return $value;
  26 + }
  27 +}
@@ -74,6 +74,9 @@ Route::post('selfSiteSsl', [\App\Http\Controllers\Api\SelfSiteController::class, @@ -74,6 +74,9 @@ Route::post('selfSiteSsl', [\App\Http\Controllers\Api\SelfSiteController::class,
74 //创建301跳转任务 74 //创建301跳转任务
75 Route::any('/addRedirect',[\App\Http\Controllers\Api\NoticeController::class,'addRedirect']); 75 Route::any('/addRedirect',[\App\Http\Controllers\Api\NoticeController::class,'addRedirect']);
76 76
  77 +//获取所有有效域名
  78 +Route::any('/getAllDomain',[\App\Http\Controllers\Api\NoticeController::class,'getAllDomain']);
  79 +
77 //关联域名 80 //关联域名
78 Route::post('/inquiry_relate_domain', [\App\Http\Controllers\Api\PrivateController::class, 'inquiry_relate_domain']); 81 Route::post('/inquiry_relate_domain', [\App\Http\Controllers\Api\PrivateController::class, 'inquiry_relate_domain']);
79 // 通过域名获取项目人员配置 82 // 通过域名获取项目人员配置
@@ -591,10 +591,13 @@ Route::middleware(['aloginauth'])->group(function () { @@ -591,10 +591,13 @@ Route::middleware(['aloginauth'])->group(function () {
591 Route::prefix('conf')->group(function () { 591 Route::prefix('conf')->group(function () {
592 Route::any('/getConfig', [Aside\Geo\GeoController::class, 'getConfig'])->name('admin.geo_conf_getConfig'); 592 Route::any('/getConfig', [Aside\Geo\GeoController::class, 'getConfig'])->name('admin.geo_conf_getConfig');
593 Route::any('/saveConfig', [Aside\Geo\GeoController::class, 'saveConfig'])->name('admin.geo_conf_saveConfig'); 593 Route::any('/saveConfig', [Aside\Geo\GeoController::class, 'saveConfig'])->name('admin.geo_conf_saveConfig');
  594 + Route::any('/getCount', [Aside\Geo\GeoController::class, 'getCount'])->name('admin.geo_conf_getCount');
594 }); 595 });
595 //geo客户确认信息 596 //geo客户确认信息
596 Route::prefix('confirm')->group(function () { 597 Route::prefix('confirm')->group(function () {
597 Route::any('/saveConfirmContent', [Aside\Geo\GeoConfirmController::class, 'saveConfirmContent'])->name('admin.geo_confirm_saveConfirmContent'); 598 Route::any('/saveConfirmContent', [Aside\Geo\GeoConfirmController::class, 'saveConfirmContent'])->name('admin.geo_confirm_saveConfirmContent');
  599 + Route::any('/getInfo', [Aside\Geo\GeoConfirmController::class, 'getInfo'])->name('admin.geo_confirm_getInfo');
  600 + Route::any('/saveInfo', [Aside\Geo\GeoConfirmController::class, 'saveInfo'])->name('admin.geo_confirm_saveInfo');
598 }); 601 });
599 //geoai文章任务管理 602 //geoai文章任务管理
600 Route::prefix('writing_task')->group(function () { 603 Route::prefix('writing_task')->group(function () {
@@ -768,6 +768,15 @@ Route::middleware(['bloginauth'])->group(function () { @@ -768,6 +768,15 @@ Route::middleware(['bloginauth'])->group(function () {
768 Route::any('/getSearchDate', [\App\Http\Controllers\Bside\Geo\GeoQuestionResController::class, 'getSearchDate'])->name('geo_result_getSearchDate');//搜索记录时间 768 Route::any('/getSearchDate', [\App\Http\Controllers\Bside\Geo\GeoQuestionResController::class, 'getSearchDate'])->name('geo_result_getSearchDate');//搜索记录时间
769 Route::any('/getPlatformCount', [\App\Http\Controllers\Bside\Geo\GeoQuestionResController::class, 'getPlatformCount'])->name('geo_result_getPlatformCount');//搜索记录时间 769 Route::any('/getPlatformCount', [\App\Http\Controllers\Bside\Geo\GeoQuestionResController::class, 'getPlatformCount'])->name('geo_result_getPlatformCount');//搜索记录时间
770 }); 770 });
  771 +
  772 + //faq渲染数据
  773 + Route::prefix('faq')->group(function () {
  774 + Route::any('/', [\App\Http\Controllers\Bside\Setting\SettingFaqController::class,'lists'])->name('faq_lists');
  775 + Route::any('/getRouteList', [\App\Http\Controllers\Bside\Setting\SettingFaqController::class,'getRouteList'])->name('faq_getRouteList');
  776 + Route::any('/saveFaq', [\App\Http\Controllers\Bside\Setting\SettingFaqController::class,'saveFaq'])->name('faq_saveFaq');
  777 + Route::any('/deleteFaq', [\App\Http\Controllers\Bside\Setting\SettingFaqController::class,'deleteFaq'])->name('faq_deleteFaq');
  778 + Route::any('/getInfo', [\App\Http\Controllers\Bside\Setting\SettingFaqController::class,'getInfo'])->name('faq_getInfo');
  779 + });
771 }); 780 });
772 //无需登录验证的路由组 781 //无需登录验证的路由组
773 Route::group([], function () { 782 Route::group([], function () {