作者 zhl

merge origin/master

@@ -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 }
@@ -5,14 +5,20 @@ @@ -5,14 +5,20 @@
5 * Date: 2025/10/27 5 * Date: 2025/10/27
6 * Time: 13:42 6 * Time: 13:42
7 */ 7 */
  8 +
8 namespace App\Console\Commands\Product; 9 namespace App\Console\Commands\Product;
9 10
10 use App\Console\Commands\Tdk\UpdateSeoTdk; 11 use App\Console\Commands\Tdk\UpdateSeoTdk;
  12 +use App\Models\Com\NoticeLog;
  13 +use App\Models\Com\UpdateNotify;
  14 +use App\Models\Domain\DomainInfo;
11 use App\Models\Product\Keyword; 15 use App\Models\Product\Keyword;
  16 +use App\Models\Project\DeployBuild;
12 use App\Models\Project\Project; 17 use App\Models\Project\Project;
13 use App\Services\ProjectServer; 18 use App\Services\ProjectServer;
14 use Illuminate\Console\Command; 19 use Illuminate\Console\Command;
15 use Illuminate\Support\Arr; 20 use Illuminate\Support\Arr;
  21 +use Illuminate\Support\Facades\Cache;
16 use Illuminate\Support\Str; 22 use Illuminate\Support\Str;
17 23
18 class SplicePrefix extends Command 24 class SplicePrefix extends Command
@@ -36,20 +42,36 @@ class SplicePrefix extends Command @@ -36,20 +42,36 @@ class SplicePrefix extends Command
36 */ 42 */
37 public function handle() 43 public function handle()
38 { 44 {
39 - $this->output('project start: ' . 4410); #6 23 38 41 46 47 49  
40 - $this->bind(4410);  
41 - dd('end');  
42 - #TODO 获取当日不达标项目, 检查关键词前缀拼接 45 + //获取当日不达标项目, 检查关键词前缀拼接
43 $project_ids = $this->getProject(); 46 $project_ids = $this->getProject();
44 if (empty($project_ids)) 47 if (empty($project_ids))
45 return true; 48 return true;
46 49
  50 + //获取已经拼接的项目id
  51 + $key = 'splice_prefix_project_ids';
  52 + $has_splice_ids = Cache::get($key) ?? [];
  53 +
47 foreach ($project_ids as $project_id) { 54 foreach ($project_ids as $project_id) {
48 if ($project_id == 1) 55 if ($project_id == 1)
49 continue; 56 continue;
  57 +
  58 + if (in_array($project_id, $has_splice_ids)) {
  59 + continue;
  60 + }
  61 +
50 $this->output('project start: ' . $project_id); 62 $this->output('project start: ' . $project_id);
  63 +
51 $this->bind($project_id); 64 $this->bind($project_id);
  65 +
  66 + //处理完后加入已拼接项目id集
  67 + array_push($has_splice_ids, $project_id);
  68 +
  69 + $this->output('project end: ' . $project_id);
52 } 70 }
  71 +
  72 + //更新已拼接项目id缓存
  73 + Cache::put($key, $has_splice_ids);
  74 +
53 return true; 75 return true;
54 } 76 }
55 77
@@ -59,129 +81,147 @@ class SplicePrefix extends Command @@ -59,129 +81,147 @@ class SplicePrefix extends Command
59 */ 81 */
60 public function bind($project_id) 82 public function bind($project_id)
61 { 83 {
62 - $project = ProjectServer::useProject($project_id);  
63 -  
64 - // 客户前缀  
65 - $tdk_class = new UpdateSeoTdk();  
66 - $info = $tdk_class->getDeployOptimize($project_id);  
67 - $fix_keyword = explode(",", $info['keyword_prefix']);  
68 - $fix_keyword = array_filter($fix_keyword);  
69 -  
70 - // 所有前缀  
71 - $all_prefixes = $tdk_class->getAllPrefix(1, $project_id);  
72 - $all_prefixes = array_map('strtolower', $all_prefixes);  
73 -  
74 - $keywords = Keyword::select(['id', 'title', 'seo_title'])->get();  
75 - foreach ($keywords as $item) {  
76 - $this_fix_keyword = $fix_keyword;  
77 - if (empty($item->title))  
78 - continue; 84 + $notify_master = false;
  85 + if (ProjectServer::useProject($project_id)) {
79 86
80 - $this->output('keyword id:' . $item->id . ' | title: ' . $item->title . ' | old seo title: ' . $item->seo_title); 87 + // 客户前缀
  88 + $tdk_class = new UpdateSeoTdk();
  89 + $info = $tdk_class->getDeployOptimize($project_id);
  90 + $fix_keyword = explode(",", $info['keyword_prefix']);
  91 + $fix_keyword = array_filter($fix_keyword);
81 92
82 - // 没有 SEO Title 直接生成  
83 - if (empty($item->seo_title)) {  
84 - $prefix = $tdk_class->getPrefixKeyword($project_id, 'prefix', 2, $item->title);  
85 - $suffix = $tdk_class->getPrefixKeyword($project_id, 'suffix', 2, trim($prefix . ' ' . $item->title));  
86 - if(Str::startsWith($suffix, ', ')){  
87 - $seo_title = $prefix . ' ' . $item->title . $suffix;  
88 - }else{  
89 - $seo_title = $prefix . ' ' . $item->title . ' ' . $suffix;  
90 - }  
91 -// $item->seo_title = trim($seo_title);  
92 -// $item->save();  
93 - $this->output('new seo title: ' . $seo_title);  
94 - continue;  
95 - } 93 + // 所有前缀
  94 + $all_prefixes = $tdk_class->getAllPrefix(1, $project_id);
  95 + $all_prefixes = array_map('strtolower', $all_prefixes);
96 96
97 - // 有 SEO Title 需要分析前后缀  
98 - $start = strpos($item->seo_title, $item->title); 97 + $keywords = Keyword::select(['id', 'title', 'seo_title', 'route'])->get();
  98 + foreach ($keywords as $item) {
  99 + $this_fix_keyword = $fix_keyword;
  100 + if (empty($item->title))
  101 + continue;
99 102
100 - // Title 和 SEO Title 不存在包含关系  
101 - if ($start === FALSE) {  
102 - $this->output('Title 和 SEO Title 不存在包含关系');  
103 - continue;  
104 - } 103 + $this->output('keyword id:' . $item->id . ' | title: ' . $item->title . ' | old seo title: ' . $item->seo_title);
105 104
106 - $prefix = $start == 0 ? '' : trim(substr($item->seo_title, 0, $start));  
107 - $prefix_array = explode(' ', $prefix);  
108 - $prefix_array = array_filter($prefix_array);  
109 - $need_num = 2 - count($prefix_array);  
110 - // 已经有两个前缀, 不在处理  
111 - if ($need_num <= 0) {  
112 - $this->output('已经有两个前缀, 不在处理');  
113 - continue;  
114 - } 105 + // 没有 SEO Title 直接生成
  106 + if (empty($item->seo_title)) {
  107 + $prefix = $tdk_class->getPrefixKeyword($project_id, 'prefix', 2, $item->title);
  108 + $suffix = $tdk_class->getPrefixKeyword($project_id, 'suffix', 2, trim($prefix . ' ' . $item->title));
  109 + if (Str::startsWith($suffix, ', ')) {
  110 + $seo_title = $prefix . ' ' . $item->title . $suffix;
  111 + } else {
  112 + $seo_title = $prefix . ' ' . $item->title . ' ' . $suffix;
  113 + }
  114 + $item->seo_title = trim($seo_title);
  115 + $item->save();
115 116
116 - // 关键词最后一个词是前缀的词,前后缀都不拼  
117 - $title_words = explode(' ', strtolower($item->title)); 117 + //存入按需更新表
  118 + UpdateNotify::addUpdateItem($project_id, 'product_keyword', $item->route);
  119 + $notify_master = true;
118 120
119 - // 关键词最后一个词是前缀的词,前后缀都不拼  
120 - if(in_array(Arr::last($title_words), $all_prefixes)) {  
121 - $this->output('关键词最后一个词是前缀的词, 前后缀都不拼');  
122 - continue;  
123 - } 121 + $this->output('new seo title: ' . $seo_title);
  122 + continue;
  123 + }
124 124
125 - // in,for,with,to,near,from 这些介词 只拼前缀,不拼后缀  
126 - $ban = []; 125 + // 有 SEO Title 需要分析前后缀
  126 + $start = strpos($item->seo_title, $item->title);
127 127
128 - // 关键词本身包含了前缀,也可以再拼一个不重复的前缀, 包含两个前缀就不拼前缀了  
129 - foreach ($title_words as $title_word) {  
130 - if(in_array($title_word, $all_prefixes)){  
131 - $ban[] = $title_word; 128 + // Title 和 SEO Title 不存在包含关系
  129 + if ($start === FALSE) {
  130 + $this->output('Title 和 SEO Title 不存在包含关系');
  131 + continue;
132 } 132 }
133 - }  
134 - $need_num = $need_num - count($ban);  
135 133
136 - // 关键词本身包含前缀,包含关键词大于等于需要的前缀,当前关键词不需要处理  
137 - if ($need_num <= 0) {  
138 - $this->output('关键词本身包含前缀,包含关键词大于等于需要的前缀,当前关键词不需要处理');  
139 - continue;  
140 - } 134 + $prefix = $start == 0 ? '' : trim(substr($item->seo_title, 0, $start));
  135 + $prefix_array = explode(' ', $prefix);
  136 + $prefix_array = array_filter($prefix_array);
  137 + $need_num = 2 - count($prefix_array);
  138 + // 已经有两个前缀, 不在处理
  139 + if ($need_num <= 0) {
  140 + $this->output('已经有两个前缀, 不在处理');
  141 + continue;
  142 + }
141 143
  144 + // 关键词最后一个词是前缀的词,前后缀都不拼
  145 + $title_words = explode(' ', strtolower($item->title));
142 146
143 - // services/service 结尾的词,后缀不拼manufacturer,factory  
144 - // manufacturer,factory 结尾的词,后缀不拼 services/service  
145 - // 有wholesale或cheap的词,后缀不拼 manufacturer,factory,exporter,company 147 + // 关键词最后一个词是前缀的词,前后缀都不拼
  148 + if (in_array(Arr::last($title_words), $all_prefixes)) {
  149 + $this->output('关键词最后一个词是前缀的词, 前后缀都不拼');
  150 + continue;
  151 + }
146 152
147 - // 关键词以manufacturer,factory,exporter,company结尾, 前缀不拼wholesale或cheap的词  
148 - if (Str::endsWith(strtolower($item->title), ['manufacturer', 'manufacturers', 'factory', 'factories', 'exporter', 'exporters', 'company', 'companies', 'supplier', 'suppliers']))  
149 - $ban = array_merge($ban, ['wholesale', 'cheap', 'buy']); 153 + // in,for,with,to,near,from 这些介词 只拼前缀,不拼后缀
  154 + $ban = [];
150 155
  156 + // 关键词本身包含了前缀,也可以再拼一个不重复的前缀, 包含两个前缀就不拼前缀了
  157 + foreach ($title_words as $title_word) {
  158 + if (in_array($title_word, $all_prefixes)) {
  159 + $ban[] = $title_word;
  160 + }
  161 + }
  162 + $need_num = $need_num - count($ban);
151 163
152 - foreach ($this_fix_keyword as $k => $keyword) {  
153 - // 被禁用的关键词  
154 - if (in_array(strtolower(Str::plural($keyword)), $ban)) {  
155 - unset($this_fix_keyword[$k]); 164 + // 关键词本身包含前缀,包含关键词大于等于需要的前缀,当前关键词不需要处理
  165 + if ($need_num <= 0) {
  166 + $this->output('关键词本身包含前缀,包含关键词大于等于需要的前缀,当前关键词不需要处理');
  167 + continue;
156 } 168 }
157 - if (in_array(strtolower(Str::singular($keyword)), $ban)) {  
158 - unset($this_fix_keyword[$k]); 169 +
  170 +
  171 + // services/service 结尾的词,后缀不拼manufacturer,factory
  172 + // manufacturer,factory 结尾的词,后缀不拼 services/service
  173 + // 有wholesale或cheap的词,后缀不拼 manufacturer,factory,exporter,company
  174 +
  175 + // 关键词以manufacturer,factory,exporter,company结尾, 前缀不拼wholesale或cheap的词
  176 + if (Str::endsWith(strtolower($item->title), ['manufacturer', 'manufacturers', 'factory', 'factories', 'exporter', 'exporters', 'company', 'companies', 'supplier', 'suppliers']))
  177 + $ban = array_merge($ban, ['wholesale', 'cheap', 'buy']);
  178 +
  179 +
  180 + foreach ($this_fix_keyword as $k => $keyword) {
  181 + // 被禁用的关键词
  182 + if (in_array(strtolower(Str::plural($keyword)), $ban)) {
  183 + unset($this_fix_keyword[$k]);
  184 + }
  185 + if (in_array(strtolower(Str::singular($keyword)), $ban)) {
  186 + unset($this_fix_keyword[$k]);
  187 + }
159 } 188 }
160 - }  
161 - $this_fix_keyword = array_diff($this_fix_keyword, $prefix_array);  
162 - shuffle($this_fix_keyword);  
163 - $need_keyword = [];  
164 - foreach ($this_fix_keyword as $v) {  
165 - if ($need_num == 0)  
166 - break;  
167 -  
168 - $is_repeat = false;  
169 - foreach ($need_keyword as $keyword) {  
170 - if (Str::singular($keyword) == Str::singular($v)) {  
171 - $is_repeat = true; 189 + $this_fix_keyword = array_diff($this_fix_keyword, $prefix_array);
  190 + shuffle($this_fix_keyword);
  191 + $need_keyword = [];
  192 + foreach ($this_fix_keyword as $v) {
  193 + if ($need_num == 0)
172 break; 194 break;
  195 +
  196 + $is_repeat = false;
  197 + foreach ($need_keyword as $keyword) {
  198 + if (Str::singular($keyword) == Str::singular($v)) {
  199 + $is_repeat = true;
  200 + break;
  201 + }
173 } 202 }
  203 + if ($is_repeat)
  204 + continue;
  205 +
  206 + $need_keyword[] = $v;
  207 + $need_num--;
174 } 208 }
175 - if ($is_repeat)  
176 - continue; 209 + $item->seo_title = trim(implode(' ', $need_keyword) . ' ' . trim($item->seo_title));
  210 + $item->save();
177 211
178 - $need_keyword[] = $v;  
179 - $need_num--; 212 + //存入按需更新表
  213 + UpdateNotify::addUpdateItem($project_id, 'product_keyword', $item->route);
  214 + $notify_master = true;
  215 +
  216 + $this->output('new seo title: ' . implode(' ', $need_keyword) . ' ' . trim($item->seo_title));
180 } 217 }
181 -// $item->seo_title = trim(implode(' ', $need_keyword) . ' ' . trim($item->seo_title));  
182 -// $item->save();  
183 - $this->output('new seo title: ' . implode(' ', $need_keyword) . ' ' . trim($item->seo_title));  
184 } 218 }
  219 +
  220 + if ($notify_master) {
  221 + //通知主站按需更新
  222 + $this->sendNotify($project_id, 2);
  223 + }
  224 +
185 return true; 225 return true;
186 } 226 }
187 227
@@ -191,8 +231,40 @@ class SplicePrefix extends Command @@ -191,8 +231,40 @@ class SplicePrefix extends Command
191 */ 231 */
192 public function getProject() 232 public function getProject()
193 { 233 {
194 - $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();  
195 - return $project_ids; 234 + return Project::where(['type' => Project::TYPE_TWO, 'project_type' => Project::TYPE_ZERO, 'delete_status' => Project::IS_DEL_FALSE, 'is_remain_today' => 0])->pluck('id')->toArray();
  235 + }
  236 +
  237 + /**
  238 + * 页面更新
  239 + * @param $project_id
  240 + * @param $route
  241 + * @author Akun
  242 + * @date 2025/10/30 14:33
  243 + */
  244 + public function sendNotify($project_id, $route)
  245 + {
  246 + //获取当前项目的域名
  247 + $domainModel = new DomainInfo();
  248 + $domainInfo = $domainModel->read(['project_id' => $project_id]);
  249 + if ($domainInfo === false) {
  250 + //获取测试域名
  251 + $deployBuildModel = new DeployBuild();
  252 + $buildInfo = $deployBuildModel->read(['project_id' => $project_id]);
  253 + $domain = $buildInfo['test_domain'];
  254 + } else {
  255 + $domain = 'https://' . $domainInfo['domain'] . '/';
  256 + }
  257 + $url = $domain . 'api/update_page/';
  258 + $param = [
  259 + 'project_id' => $project_id,
  260 + 'type' => 1,
  261 + 'route' => $route,
  262 + 'url' => [],
  263 + 'language' => [],
  264 + ];
  265 + NoticeLog::createLog(NoticeLog::GENERATE_PAGE, ['c_url' => $url, 'c_params' => $param], date('Y-m-d H:i:s', time() + 300));
  266 +
  267 + $this->output('更新中请稍后, 更新完成将会发送站内信通知更新结果!');
196 } 268 }
197 269
198 /** 270 /**
@@ -207,4 +279,4 @@ class SplicePrefix extends Command @@ -207,4 +279,4 @@ class SplicePrefix extends Command
207 echo $message; 279 echo $message;
208 return true; 280 return true;
209 } 281 }
210 -}  
  282 +}
@@ -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);
@@ -41,7 +41,7 @@ class GeoController extends BaseController @@ -41,7 +41,7 @@ class GeoController extends BaseController
41 $projectModel = new Project(); 41 $projectModel = new Project();
42 $projectInfo = $projectModel->read(['id' => $project_id],['title','version']); 42 $projectInfo = $projectModel->read(['id' => $project_id],['title','version']);
43 $geoWritingsModel = new GeoWritings(); 43 $geoWritingsModel = new GeoWritings();
44 - $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']);
45 $result = [ 45 $result = [
46 'project' => $projectInfo, 46 'project' => $projectInfo,
47 'list' => $lists 47 'list' => $lists
@@ -108,13 +108,16 @@ class GeoController extends BaseController @@ -108,13 +108,16 @@ class GeoController extends BaseController
108 $token = trim($this->param['token']); 108 $token = trim($this->param['token']);
109 $data = GeoConfirm::where(['uniqid' => $token])->first(); 109 $data = GeoConfirm::where(['uniqid' => $token])->first();
110 if (empty($data)){ 110 if (empty($data)){
111 - return $this->error('当前授权已失效'); 111 + return $this->error('确认链接已重置,请查看最新推送链接!');
112 } 112 }
113 $content = explode("\n", $data->content); 113 $content = explode("\n", $data->content);
114 $confirm = explode("\n", $data->confirm); 114 $confirm = explode("\n", $data->confirm);
115 $type = $data->type; 115 $type = $data->type;
116 $status = $data->status; 116 $status = $data->status;
117 - $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');
118 $this->response('success',Code::SUCCESS,$result); 121 $this->response('success',Code::SUCCESS,$result);
119 } 122 }
120 123
@@ -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 }
@@ -71,4 +71,26 @@ class GeoConfirmController extends BaseController @@ -71,4 +71,26 @@ class GeoConfirmController extends BaseController
71 $data = $this->logic->saveConfirmContent($this->param); 71 $data = $this->logic->saveConfirmContent($this->param);
72 $this->response('success', Code::SUCCESS, $data); 72 $this->response('success', Code::SUCCESS, $data);
73 } 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 + }
74 } 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 }
@@ -78,8 +78,10 @@ class SettingFaqController extends BaseController @@ -78,8 +78,10 @@ class SettingFaqController extends BaseController
78 { 78 {
79 $this->request->validate([ 79 $this->request->validate([
80 'route'=>'required', 80 'route'=>'required',
  81 + 'qa'=>'required',
81 ],[ 82 ],[
82 'route.required' => '路由不能为空', 83 'route.required' => '路由不能为空',
  84 + 'qa.required' => 'qa不能为空',
83 ]); 85 ]);
84 $data = $this->logic->saveFaq(); 86 $data = $this->logic->saveFaq();
85 $this->response('success',Code::SUCCESS,$data); 87 $this->response('success',Code::SUCCESS,$data);
@@ -40,7 +40,7 @@ class GeoConfirmLogic extends BaseLogic @@ -40,7 +40,7 @@ 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{
@@ -68,6 +68,24 @@ class GeoConfirmLogic extends BaseLogic @@ -68,6 +68,24 @@ class GeoConfirmLogic extends BaseLogic
68 public function getConfirmInfo() 68 public function getConfirmInfo()
69 { 69 {
70 $data = $this->model->read($this->param); 70 $data = $this->model->read($this->param);
  71 + if($data === false){
  72 + $this->fail('当前数据不存在或者已被删除');
  73 + }
  74 + $data['confirm'] = $data['content'];
71 return $this->success($data); 75 return $this->success($data);
72 } 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 + }
73 } 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 }
@@ -479,6 +479,14 @@ class SyncSubmitTaskService @@ -479,6 +479,14 @@ class SyncSubmitTaskService
479 ){ 479 ){
480 throw new InquiryFilterException( '全局过滤'); 480 throw new InquiryFilterException( '全局过滤');
481 } 481 }
  482 + if(
  483 + empty($data['data']['name']) &&
  484 + strlen($data['data']['message']??'') >= 8 &&
  485 + preg_match('/^[a-zA-Z]+$/', $data['data']['message']??'') &&
  486 + in_array($data['country']??'', ['荷兰', '俄罗斯'])
  487 + ){
  488 + throw new InquiryFilterException( '全局过滤');
  489 + }
482 //全局过滤 ip 荷兰 有name、phone、email字段,但都是空 490 //全局过滤 ip 荷兰 有name、phone、email字段,但都是空
483 if( 491 if(
484 in_array($data['country']??'', ['荷兰', '俄罗斯']) && 492 in_array($data['country']??'', ['荷兰', '俄罗斯']) &&
@@ -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,11 +591,13 @@ Route::middleware(['aloginauth'])->group(function () { @@ -591,11 +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');
598 Route::any('/getInfo', [Aside\Geo\GeoConfirmController::class, 'getInfo'])->name('admin.geo_confirm_getInfo'); 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');
599 }); 601 });
600 //geoai文章任务管理 602 //geoai文章任务管理
601 Route::prefix('writing_task')->group(function () { 603 Route::prefix('writing_task')->group(function () {