作者 刘锟

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

@@ -79,6 +79,7 @@ class AiBlogAuthorTask extends Command @@ -79,6 +79,7 @@ class AiBlogAuthorTask extends Command
79 ProjectServer::useProject($info['project_id']); 79 ProjectServer::useProject($info['project_id']);
80 $this->saveAiBlogAuthor($result['data'] ?? [],$info['project_id']); 80 $this->saveAiBlogAuthor($result['data'] ?? [],$info['project_id']);
81 RouteMap::setRoute('top-blog',RouteMap::SOURCE_AI_BLOG_LIST,0,$info['project_id']);//写一条列表页路由 81 RouteMap::setRoute('top-blog',RouteMap::SOURCE_AI_BLOG_LIST,0,$info['project_id']);//写一条列表页路由
  82 + RouteMap::setRoute('top-video',RouteMap::SOURCE_AI_VIDEO_LIST,0,$info['project_id']);//写一条列表页路由
82 DB::disconnect('custom_mysql'); 83 DB::disconnect('custom_mysql');
83 //修改任务状态 84 //修改任务状态
84 $aiBlogTaskModel->edit(['status'=>2],['id'=>$info['id']]); 85 $aiBlogTaskModel->edit(['status'=>2],['id'=>$info['id']]);
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :AiBlogTask.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/2/14 11:14
  8 + */
  9 +
  10 +namespace App\Console\Commands\Ai;
  11 +
  12 +use App\Models\Ai\AiBlog;
  13 +use App\Models\Ai\AiBlogAuthor;
  14 +use App\Models\Ai\AiBlogList;
  15 +use App\Models\Ai\AiVideoList;
  16 +use App\Models\Domain\DomainInfo;
  17 +use App\Models\Project\ProjectAiSetting;
  18 +use App\Models\RouteMap\RouteMap;
  19 +use App\Services\AiBlogService;
  20 +use App\Services\AiVideoService;
  21 +use App\Services\ProjectServer;
  22 +use Illuminate\Console\Command;
  23 +use App\Models\Project\AiBlogTask as AiBlogTaskModel;
  24 +use Illuminate\Support\Facades\Cache;
  25 +use Illuminate\Support\Facades\DB;
  26 +use function Symfony\Component\String\s;
  27 +
  28 +/***
  29 + * @remark :根据项目更新blog列表
  30 + * @name :AiBlogListTask
  31 + * @author :lyh
  32 + * @method :post
  33 + * @time :2025/3/6 9:45
  34 + */
  35 +class AiVideoListTask extends Command
  36 +{
  37 + /**
  38 + * The name and signature of the console command.
  39 + *
  40 + * @var string
  41 + */
  42 + protected $signature = 'save_ai_video_list {project_id}';
  43 +
  44 + /**
  45 + * The console command description.
  46 + *
  47 + * @var string
  48 + */
  49 + protected $description = '生成video列表';
  50 +
  51 + public function handle(){
  52 + $project_id = $this->argument('project_id');
  53 + @file_put_contents(storage_path('logs/lyh_error.log'), var_export('执行的项目id->'.$project_id, true) . PHP_EOL, FILE_APPEND);
  54 + ProjectServer::useProject($project_id);
  55 + $this->updateBlogList($project_id);
  56 +// $this->curlDelRoute($project_id);
  57 + DB::disconnect('custom_mysql');
  58 + return true;
  59 + }
  60 +
  61 + /**
  62 + * @remark :更新列表页数据
  63 + * @name :updateBlogList
  64 + * @author :lyh
  65 + * @method :post
  66 + * @time :2025/3/5 11:07
  67 + */
  68 + public function updateBlogList($project_id){
  69 + $aiVideoService = new AiVideoService($project_id);
  70 + $page = 1;
  71 + $saveData = [];
  72 + $result = $aiVideoService->getAiVideoList($page,15);
  73 + if(!isset($result['status']) && $result['status'] != 200){
  74 + return true;
  75 + }
  76 + $total_page = $result['data']['total_page'];
  77 + //组装数据保存
  78 + $saveData[] = [
  79 + 'route'=>$page,
  80 + 'text'=>$result['data']['section'],
  81 + ];
  82 + while ($total_page > $page){
  83 + $page++;
  84 + $result = $aiVideoService->getAiVideoList($page,15);
  85 + if(isset($result['status']) && $result['status'] == 200){
  86 + $saveData[] = [
  87 + 'route'=>$page,
  88 + 'text'=>$result['data']['section'],
  89 + ];
  90 + }
  91 + }
  92 + $aiVideoListModel = new AiVideoList();
  93 + if(!empty($saveData)){
  94 + //写一条路由信息
  95 + $aiVideoListModel->truncate();
  96 + $aiVideoListModel->insertAll($saveData);
  97 + }
  98 + return true;
  99 + }
  100 +
  101 + /**
  102 + * @remark :通知C端生成界面
  103 + * @name :sendNotice
  104 + * @author :lyh
  105 + * @method :post
  106 + * @time :2025/3/6 11:51
  107 + */
  108 + public function curlDelRoute($project_id){
  109 + $domainModel = new DomainInfo();
  110 + //获取项目域名
  111 + $domain = $domainModel->getProjectIdDomain($project_id);
  112 + if(!empty($domain)){
  113 + $c_url = $domain.'api/update_page/';
  114 + $param = [
  115 + 'project_id' => $project_id,
  116 + 'type' => 1,
  117 + 'route' => 3,
  118 + 'url' => ['top-blog'],
  119 + 'language'=> [],
  120 + 'is_sitemap' => 0
  121 + ];
  122 + http_post($c_url, json_encode($param));
  123 + }
  124 + return true;
  125 + }
  126 +}
@@ -9,9 +9,18 @@ @@ -9,9 +9,18 @@
9 9
10 namespace App\Console\Commands\Ai; 10 namespace App\Console\Commands\Ai;
11 11
  12 +use App\Helper\Arr;
  13 +use App\Models\Ai\AiBlogAuthor;
12 use App\Models\Ai\AiVideo; 14 use App\Models\Ai\AiVideo;
  15 +use App\Models\Ai\AiVideoList;
  16 +use App\Models\Com\Notify;
  17 +use App\Models\Devops\ServerConfig;
  18 +use App\Models\Devops\ServersIp;
  19 +use App\Models\Domain\DomainInfo;
13 use App\Models\Project\AiVideoTask as AiVideoTaskModel; 20 use App\Models\Project\AiVideoTask as AiVideoTaskModel;
  21 +use App\Models\Project\Project;
14 use App\Models\RouteMap\RouteMap; 22 use App\Models\RouteMap\RouteMap;
  23 +use App\Services\AiBlogService;
15 use App\Services\AiVideoService; 24 use App\Services\AiVideoService;
16 use App\Services\DingService; 25 use App\Services\DingService;
17 use App\Services\ProjectServer; 26 use App\Services\ProjectServer;
@@ -30,14 +39,12 @@ class AiVideoTask extends Command @@ -30,14 +39,12 @@ class AiVideoTask extends Command
30 39
31 public $updateProject = [];//需更新的列表 40 public $updateProject = [];//需更新的列表
32 public $routes = [];//需要更新的路由 41 public $routes = [];//需要更新的路由
33 -  
34 /** 42 /**
35 * The console command description. 43 * The console command description.
36 * 44 *
37 * @var string 45 * @var string
38 */ 46 */
39 protected $description = '查询ai_video是否已经生成'; 47 protected $description = '查询ai_video是否已经生成';
40 -  
41 /** 48 /**
42 * @return bool 49 * @return bool
43 * @throws \Exception 50 * @throws \Exception
@@ -64,14 +71,14 @@ class AiVideoTask extends Command @@ -64,14 +71,14 @@ class AiVideoTask extends Command
64 { 71 {
65 $task_id = Redis::rpop('ai_video_task'); 72 $task_id = Redis::rpop('ai_video_task');
66 if (empty($task_id)) { 73 if (empty($task_id)) {
67 -// if(!empty($this->updateProject)){  
68 -// $this->updateProject($this->updateProject);  
69 -// $this->updateProject = [];  
70 -// }  
71 -// if(!empty($this->routes)){ 74 + if(!empty($this->updateProject)){
  75 + $this->updateProject($this->updateProject);
  76 + $this->updateProject = [];
  77 + }
  78 + if(!empty($this->routes)){
72 // $this->updateRoutes($this->routes); 79 // $this->updateRoutes($this->routes);
73 -// $this->routes = [];  
74 -// } 80 + $this->routes = [];
  81 + }
75 $aiVideoTaskModel = new AiVideoTaskModel(); 82 $aiVideoTaskModel = new AiVideoTaskModel();
76 $finish_at = date('Y-m-d H:i:s', strtotime('-' . $finish_at . ' hour')); 83 $finish_at = date('Y-m-d H:i:s', strtotime('-' . $finish_at . ' hour'));
77 $ids = $aiVideoTaskModel->formatQuery(['status'=>$aiVideoTaskModel::STATUS_RUNNING,'updated_at'=>['<=',$finish_at]])->pluck('id'); 84 $ids = $aiVideoTaskModel->formatQuery(['status'=>$aiVideoTaskModel::STATUS_RUNNING,'updated_at'=>['<=',$finish_at]])->pluck('id');
@@ -152,6 +159,13 @@ class AiVideoTask extends Command @@ -152,6 +159,13 @@ class AiVideoTask extends Command
152 'status'=>$aiVideoTaskModel::STATUS_FINISH 159 'status'=>$aiVideoTaskModel::STATUS_FINISH
153 ]; 160 ];
154 $aiVideoModel->edit($saveData,['task_id'=>$item['task_id']]); 161 $aiVideoModel->edit($saveData,['task_id'=>$item['task_id']]);
  162 + //需要更新的路由
  163 + if (!in_array($result['data']['author_id'], $this->updateProject[$item['project_id']] ?? [])) {
  164 + $this->updateProject[$item['project_id']][] = $result['data']['author_id'];
  165 + }
  166 + if (!in_array($route, $this->routes[$item['project_id']] ?? [])) {
  167 + $this->routes[$item['project_id']][] = $route;
  168 + }
155 DB::disconnect('custom_mysql'); 169 DB::disconnect('custom_mysql');
156 $aiVideoTaskModel->edit(['status'=>$aiVideoTaskModel::STATUS_FINISH],['id'=>$item['id']]); 170 $aiVideoTaskModel->edit(['status'=>$aiVideoTaskModel::STATUS_FINISH],['id'=>$item['id']]);
157 $this->output('success: task id: ' . $task_id); 171 $this->output('success: task id: ' . $task_id);
@@ -159,6 +173,103 @@ class AiVideoTask extends Command @@ -159,6 +173,103 @@ class AiVideoTask extends Command
159 } 173 }
160 174
161 /** 175 /**
  176 + * @remark :更新项目作者页面及列表页
  177 + * @name :updateProject
  178 + * @author :lyh
  179 + * @method :post
  180 + * @time :2025/4/30 15:43
  181 + */
  182 + public function updateProject($updateProject){
  183 + if(empty($updateProject)){
  184 + return true;
  185 + }
  186 + foreach ($updateProject as $project_id => $author){
  187 + ProjectServer::useProject($project_id);
  188 + $this->output('sync: list start, project_id: ' . $project_id);
  189 + $this->updateBlogList($project_id);
  190 + $this->output('sync: list end');
  191 + //更新作者
  192 + $this->output('sync: author start, project_id: ' . $project_id);
  193 + foreach ($author as $val){
  194 + $this->updateAiBlogAuthor($val,$project_id);
  195 + }
  196 + $this->output('sync: author end');
  197 + DB::disconnect('custom_mysql');
  198 + }
  199 +
  200 + return true;
  201 + }
  202 +
  203 + /**
  204 + * @remark :更新作者页面
  205 + * @name :updateAiBlogAuthor
  206 + * @author :lyh
  207 + * @method :post
  208 + * @time :2025/4/30 15:52
  209 + */
  210 + public function updateAiBlogAuthor($author_id,$project_id){
  211 + if(empty($author_id)){
  212 + return true;
  213 + }
  214 + $aiBlogService = new AiBlogService($project_id);
  215 + $aiBlogService->author_id = $author_id;
  216 + $result = $aiBlogService->getAuthorDetail();
  217 + if(isset($result['status']) && $result['status'] == 200){
  218 + //当前作者的页面
  219 + $aiBlogAuthorModel = new AiBlogAuthor();
  220 + $authorInfo = $aiBlogAuthorModel->read(['author_id'=>$author_id],['id','route']);
  221 + if($authorInfo !== false && !empty($result['data']['section'])){
  222 + //需要更新的路由
  223 + if (!in_array($authorInfo['route'], $this->routes[$project_id] ?? [])) {
  224 + $this->routes[$project_id][] = $authorInfo['route'];
  225 + }
  226 + $aiBlogAuthorModel->edit(['text'=>$result['data']['section']],['author_id'=>$author_id]);
  227 + }
  228 + }
  229 + return true;
  230 + }
  231 +
  232 + /**
  233 + * @remark :更新
  234 + * @name :updateBlogList
  235 + * @author :lyh
  236 + * @method :post
  237 + * @time :2025/4/30 15:45
  238 + */
  239 + public function updateBlogList($project_id){
  240 + $aiVideoService = new AiVideoService($project_id);
  241 + $page = 1;
  242 + $saveData = [];
  243 + $result = $aiVideoService->getAiVideoList($page,15);
  244 + if(!isset($result['status']) && $result['status'] != 200){
  245 + return true;
  246 + }
  247 + $total_page = $result['data']['total_page'];
  248 + //组装数据保存
  249 + $saveData[] = [
  250 + 'route'=>$page,
  251 + 'text'=>$result['data']['section'],
  252 + ];
  253 + while ($total_page > $page){
  254 + $page++;
  255 + $result = $aiVideoService->getAiVideoList($page,15);
  256 + if(isset($result['status']) && $result['status'] == 200){
  257 + $saveData[] = [
  258 + 'route'=>$page,
  259 + 'text'=>$result['data']['section'],
  260 + ];
  261 + }
  262 + }
  263 + $aiVideoListModel = new AiVideoList();
  264 + if(!empty($saveData)){
  265 + //写一条路由信息
  266 + RouteMap::setRoute('top-video',RouteMap::SOURCE_AI_VIDEO_LIST,0,$project_id);//写一条列表页路由
  267 + $aiVideoListModel->truncate();
  268 + $aiVideoListModel->insertAll($saveData);
  269 + }
  270 + return true;
  271 + }
  272 + /**
162 * 输入日志 273 * 输入日志
163 * @param $message 274 * @param $message
164 * @return bool 275 * @return bool
@@ -169,4 +280,64 @@ class AiVideoTask extends Command @@ -169,4 +280,64 @@ class AiVideoTask extends Command
169 echo $message; 280 echo $message;
170 return true; 281 return true;
171 } 282 }
  283 +
  284 + /**
  285 + * 通知C端生成界面
  286 + * @param $project_id
  287 + * @return bool
  288 + */
  289 + public function updateRoutes($routes){
  290 + $domainModel = new DomainInfo();
  291 + $project_model = new Project();
  292 + foreach ($routes as $project_id => $route){
  293 + $route[] = 'top-video';
  294 + $domain = $domainModel->getProjectIdDomain($project_id);
  295 + if (empty($domain)) {
  296 + $this->output('send: 域名不存在, project id: ' . $project_id);
  297 + continue;
  298 + }
  299 + //判断是否是自建站服务器,如果是,不请求C端接口,数据直接入库
  300 + $project_info = $project_model->read(['id'=>$project_id],['serve_id']);
  301 + if(!$project_info){
  302 + $this->output('send: 项目不存在, project id: ' . $project_id);
  303 + continue;
  304 + }
  305 + $serve_ip_model = new ServersIp();
  306 + $serve_ip_info = $serve_ip_model->read(['id'=>$project_info['serve_id']],['servers_id']);
  307 + $servers_id = $serve_ip_info ? $serve_ip_info['servers_id'] : 0;
  308 + if($servers_id == ServerConfig::SELF_SITE_ID){
  309 + //判断是否已有更新进行中
  310 + $notify_model = new Notify();
  311 + $data = [
  312 + 'project_id' => $project_id,
  313 + 'type' => Notify::TYPE_MASTER,
  314 + 'route' => Notify::ROUTE_AI_BLOG,
  315 + 'server_id' => ServerConfig::SELF_SITE_ID,
  316 + 'status' => ['!=',Notify::STATUS_FINISH_SITEMAP]
  317 + ];
  318 + $notify = $notify_model->read($data,['id']);
  319 + if(!$notify){
  320 + $domain_array = parse_url($domain);
  321 + $data['data'] = Arr::a2s(['domain'=>$domain_array['host'],'url'=>$route,'language'=>[]]);
  322 + $data['status'] = Notify::STATUS_INIT;
  323 + $data['sort'] = 2;
  324 + $notify_model->add($data);
  325 + }
  326 + $this->output('send: 自建站项目, project id: ' . $project_id);
  327 + }else{
  328 + $c_url = $domain.'api/update_page/';
  329 + $param = [
  330 + 'project_id' => $project_id,
  331 + 'type' => 1,
  332 + 'route' => 3,
  333 + 'url' => $route,
  334 + 'language'=> [],
  335 + 'is_sitemap' => 0
  336 + ];
  337 + $res = http_post($c_url, json_encode($param,true));
  338 + $this->output('notify: project id: ' . $project_id . ', result: ' . json_encode($res,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
  339 + }
  340 + }
  341 + return true;
  342 + }
172 } 343 }
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :CropImage.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/5/8 9:19
  8 + */
  9 +
  10 +namespace App\Console\Commands\CropImage;
  11 +
  12 +use App\Enums\Common\Code;
  13 +use App\Models\Domain\DomainInfo;
  14 +use App\Models\File\Image;
  15 +use App\Models\WebSetting\AggregationSetting;
  16 +use App\Models\WebSetting\WebSettingImage;
  17 +use App\Services\CosService;
  18 +use App\Services\ProjectServer;
  19 +use Illuminate\Console\Command;
  20 +use Illuminate\Support\Facades\DB;
  21 +
  22 +class CropImage extends Command
  23 +{
  24 + /**
  25 + * The name and signature of the console command.
  26 + *
  27 + * @var string
  28 + */
  29 + protected $signature = 'crop_image {project_id}';
  30 +
  31 + /**
  32 + * The console command description.
  33 + *
  34 + * @var string
  35 + */
  36 + protected $description = '裁剪图片';
  37 +
  38 + public function handle(){
  39 + echo '测试裁剪->cs-crop:'.PHP_EOL;
  40 + $project_id = $this->argument('project_id');
  41 + ProjectServer::useProject($project_id);
  42 + $data = $this->_keywordAction($project_id);
  43 + $this->_aiAction($project_id,$data[0] ?? []);
  44 + DB::disconnect('custom_mysql');
  45 + }
  46 +
  47 + /**
  48 + * @remark :执行的方法
  49 + * @name :_action
  50 + * @author :lyh
  51 + * @method :post
  52 + * @time :2025/5/8 9:21
  53 + */
  54 + public function _keywordAction($project_id){
  55 + $resData = [];
  56 + //聚合页裁剪
  57 + $data = $this->getKeywordImage($project_id);
  58 + $cosService = new CosService();
  59 + if(!empty($data)){
  60 + foreach ($data as $val){
  61 + //处理图片为相对路径
  62 + $image = str_replace_url($val);
  63 + $height = $cosService->getImageHeight($image);
  64 + if(empty($height)){
  65 + echo '未获取到图片高度。'.PHP_EOL;
  66 + continue;
  67 + }
  68 + echo '返回的图片高度:'.$height.PHP_EOL;
  69 + if($height > 220){
  70 + $result = $cosService->cropCosImage($image);
  71 + if(empty($result)){
  72 + continue;
  73 + }
  74 + $resData[] = $result['path'];
  75 + $this->saveMysql($project_id,$result['size'],$result['type'],$result['path'],$result['mime']);
  76 + }else{
  77 + $resData[] = $image;
  78 + }
  79 + }
  80 + }
  81 + $this->saveAggregationSetting($project_id,$resData);
  82 + return $resData;
  83 + }
  84 +
  85 + /**
  86 + * @remark :ai执行方法
  87 + * @name :_aiAction
  88 + * @author :lyh
  89 + * @method :post
  90 + * @time :2025/5/8 16:12
  91 + */
  92 + public function _aiAction($project_id,$keywordImage){
  93 + $cosService = new CosService();
  94 + //ai_blog裁剪
  95 + $ai_image = $this->getAiBlogImage($project_id,$keywordImage ?? []);
  96 + if(empty($ai_image)){
  97 + echo '当前图片不需要裁剪。'.PHP_EOL;
  98 + return true;
  99 + }
  100 + $height = $cosService->getImageHeight($ai_image);
  101 + if(empty($height)){
  102 + echo '未获取到AI_BLOG图片高度。'.PHP_EOL;
  103 + return true;
  104 + }
  105 + echo '返回的图片高度:'.$height.PHP_EOL;
  106 + if($height > 220){
  107 + $result = $cosService->cropCosImage($ai_image);
  108 + if(empty($result)){
  109 + return true;
  110 + }
  111 + $this->saveMysql($project_id,$result['size'],$result['type'],$result['path'],$result['mime']);
  112 + $webSettingImageModel = new WebSettingImage();
  113 + $webSettingImageModel->edit(['image'=>$result['path']],['project_id' => $project_id, 'type' => 4]);
  114 + }
  115 + return true;
  116 + }
  117 +
  118 + /**
  119 + * @remark :保存数据
  120 + * @name :saveAggregationSetting
  121 + * @author :lyh
  122 + * @method :post
  123 + * @time :2025/5/8 16:24
  124 + */
  125 + public function saveAggregationSetting($project_id,$data){
  126 + if(empty($data)){
  127 + return true;
  128 + }
  129 + //存全路径
  130 + foreach ($data as $key => $val){
  131 + $val = getImageUrl($val);
  132 + $data[$key] = $val;
  133 + }
  134 + $aggregationSettingModel = new AggregationSetting();
  135 + $info = $aggregationSettingModel->read(['project_id'=>$project_id]);
  136 + if($info === false){
  137 + $aggregationSettingModel->addReturnId(['project_id'=>$project_id,'top_banner'=>json_encode($data,true)]);
  138 + }else{
  139 + $aggregationSettingModel->edit(['top_banner'=>json_encode($data,true)],['id'=>$info['id']]);
  140 + }
  141 + return true;
  142 + }
  143 +
  144 + /**
  145 + * @remark :获取aiBlog图片
  146 + * @name :getAiBlogImage
  147 + * @author :lyh
  148 + * @method :post
  149 + * @time :2025/5/8 10:42
  150 + */
  151 + public function getAiBlogImage($project_id,$keywordImage){
  152 + // AI博客banner type:1:产品,2:博客,3:新闻,4:AIBlog
  153 + $webSettingImageModel = new WebSettingImage();
  154 + $aiBlogInfo = $webSettingImageModel->read(['project_id' => $project_id, 'type' => 4],['image']);
  155 + if($aiBlogInfo === false && !empty($keywordImage)){
  156 + $webSettingImageModel->addReturnId(['project_id'=>$project_id,'image'=>$keywordImage,'type'=>4]);
  157 + return '';
  158 + }
  159 + if(empty($aiBlogInfo['image']) && !empty($keywordImage)){
  160 + $webSettingImageModel->edit(['image'=>$keywordImage],['id'=>$aiBlogInfo['id']]);
  161 + return '';
  162 + }
  163 + $ai_image = str_replace_url($aiBlogInfo['image']);
  164 + return $ai_image;
  165 + }
  166 +
  167 + /**
  168 + * @remark :获取聚合页图片
  169 + * @name :getImage
  170 + * @author :lyh
  171 + * @method :post
  172 + * @time :2025/5/8 9:21
  173 + */
  174 + public function getKeywordImage($project_id){
  175 + $data = [];
  176 + // 聚合页banner
  177 + $aggregationSettingModel = new AggregationSetting();
  178 + $aggregationSettingInfo = $aggregationSettingModel->read(['project_id' => $project_id],['id','top_banner']);
  179 + if($aggregationSettingInfo !== false && !empty($aggregationSettingInfo['top_banner'])){
  180 + foreach ($aggregationSettingInfo['top_banner'] as $val){
  181 + if($val != 'jpg' && $val != 'png' && $val != 'webp'){
  182 + $data[] = $val;
  183 + }
  184 + }
  185 + }
  186 + if(empty($data)){
  187 + //重页面上获取首页banner
  188 + $data = $this->getDomImage($project_id);
  189 + }
  190 + return $data;
  191 + }
  192 +
  193 + /**
  194 + * @remark :页面上获取图片
  195 + * @name :getDomImage
  196 + * @author :lyh
  197 + * @method :post
  198 + * @time :2025/5/8 10:32
  199 + */
  200 + public function getDomImage($project_id){
  201 + $data = [];
  202 + echo '获取首页banner:' . $project_id . PHP_EOL;
  203 + $domainModel = new DomainInfo();
  204 + $domainInfo = $domainModel->read(['project_id' => $project_id, 'status' => 1]);
  205 + if ($domainInfo !== false) {
  206 + $dom = @file_get_html('https://' . $domainInfo['domain'] . '/');
  207 + if (empty($dom)) {
  208 + $this->output('获取HTML失败: ' . $project_id);
  209 + }else{
  210 + $banner_dom = $dom->find('main .section-banner-wrap-block img', 0);
  211 + $data[] = $banner_dom ? $banner_dom->src : '';
  212 + $dom->clear();
  213 + unset($dom);
  214 + }
  215 + }else{
  216 + $this->output('域名不存在: ' . $project_id);
  217 + }
  218 + return $data;
  219 + }
  220 +
  221 + /**
  222 + * @remark :写入数据库
  223 + * @name :saveMysql
  224 + * @author :lyh
  225 + * @method :post
  226 + * @time :2025/5/8 14:59
  227 + */
  228 + public function saveMysql($project_id,$size,$image_type,$path,$mime = ''){
  229 + $hash = md5($path);
  230 + $imageModel = new Image();
  231 + $info = $imageModel->read(['hash'=>$hash,'project_id'=>$project_id]);
  232 + $data = [
  233 + 'path' => $path,
  234 + 'size' => $size,
  235 + 'hash' => $hash,
  236 + 'type' => $image_type,
  237 + 'refer'=> 0,
  238 + 'mime' => $mime,
  239 + 'project_id'=>$project_id,
  240 + 'name'=>basename($path),
  241 + 'en_name'=>basename($path)
  242 + ];
  243 + if($info === false){
  244 + $imageModel->addReturnId($data);
  245 + }else{
  246 + $imageModel->edit($data,['id'=>$info['id']]);
  247 + }
  248 + return true;
  249 + }
  250 +
  251 + /**
  252 + * @remark :记录日志
  253 + * @name :output
  254 + * @author :lyh
  255 + * @method :post
  256 + * @time :2025/5/8 9:57
  257 + */
  258 + public function output($message, $log_file = 'logs/crop_image.log')
  259 + {
  260 + $message = date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;
  261 + echo $message;
  262 + file_put_contents(storage_path($log_file), $message, FILE_APPEND);
  263 + return true;
  264 + }
  265 +}
@@ -61,7 +61,7 @@ class AfterDayCount extends Command @@ -61,7 +61,7 @@ class AfterDayCount extends Command
61 $this->managerHrModel = new ManageHr(); 61 $this->managerHrModel = new ManageHr();
62 $projectModel = new Project(); 62 $projectModel = new Project();
63 $rankDataLogModel = new RankDataLog(); 63 $rankDataLogModel = new RankDataLog();
64 - $todayMidnight = date('Y-m-d 00:00:00', strtotime('today')); 64 + $todayMidnight = date('Y-m-d', strtotime('today'));
65 $saveData = []; 65 $saveData = [];
66 $projectIdArr = $rankDataLogModel->selectField(['is_compliance'=>1,'lang'=>'','date'=>date('Y-m-d', strtotime('-3 months'))],'project_id');//3个月前达标的项目id 66 $projectIdArr = $rankDataLogModel->selectField(['is_compliance'=>1,'lang'=>'','date'=>date('Y-m-d', strtotime('-3 months'))],'project_id');//3个月前达标的项目id
67 foreach ($this->after_manager as $key => $valM){ 67 foreach ($this->after_manager as $key => $valM){
@@ -69,9 +69,9 @@ class AfterDayCount extends Command @@ -69,9 +69,9 @@ class AfterDayCount extends Command
69 $project_count = $projectModel->where('gl_project.extend_type',0) 69 $project_count = $projectModel->where('gl_project.extend_type',0)
70 ->where('gl_project.delete_status',0) 70 ->where('gl_project.delete_status',0)
71 ->where('gl_project.old_project_id',0) 71 ->where('gl_project.old_project_id',0)
72 - ->where('gl_project.created_at','<=',$todayMidnight) 72 + ->where('gl_project_deploy_optimize.start_date','<=',$todayMidnight)
73 ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr) 73 ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)
74 - ->whereIn('gl_project.type',[2,4]) 74 + ->whereIn('gl_project.type',[2,4,6])
75 ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id') 75 ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')
76 ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0") 76 ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0")
77 ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0") 77 ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0")
@@ -79,24 +79,25 @@ class AfterDayCount extends Command @@ -79,24 +79,25 @@ class AfterDayCount extends Command
79 $qualified_count = $projectModel->where('gl_project.extend_type',0) 79 $qualified_count = $projectModel->where('gl_project.extend_type',0)
80 ->where('gl_project.delete_status',0) 80 ->where('gl_project.delete_status',0)
81 ->where('gl_project.old_project_id',0) 81 ->where('gl_project.old_project_id',0)
82 - ->where('gl_project.created_at','<=',$todayMidnight) 82 + ->where('gl_project_deploy_optimize.start_date','<=',$todayMidnight)
83 ->where('gl_project.is_remain_today',1) 83 ->where('gl_project.is_remain_today',1)
84 ->where('gl_project_deploy_build.plan','!=',0) 84 ->where('gl_project_deploy_build.plan','!=',0)
85 ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr) 85 ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)
86 - ->whereIn('gl_project.type',[2,4]) 86 + ->whereIn('gl_project.type',[2,4,6])
87 ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id') 87 ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')
88 ->leftJoin('gl_project_deploy_build', 'gl_project.id', '=', 'gl_project_deploy_build.project_id') 88 ->leftJoin('gl_project_deploy_build', 'gl_project.id', '=', 'gl_project_deploy_build.project_id')
89 ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0") 89 ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0")
90 ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0") 90 ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0")
91 ->count(); 91 ->count();
92 $rate = number_format($qualified_count / $project_count, 2); 92 $rate = number_format($qualified_count / $project_count, 2);
93 - $threeMonthsAgo = date('Y-m-d 00:00:00', strtotime('-3 months')); 93 + $threeMonthsAgo = date('Y-m', strtotime('-3 months'));
94 $three_project_count = $projectModel->where('gl_project.extend_type',0) 94 $three_project_count = $projectModel->where('gl_project.extend_type',0)
95 ->where('gl_project.delete_status',0) 95 ->where('gl_project.delete_status',0)
96 ->where('gl_project.old_project_id',0) 96 ->where('gl_project.old_project_id',0)
97 - ->where('gl_project.created_at','<=',$threeMonthsAgo) 97 + ->where('gl_project_deploy_optimize.start_date','>=',$threeMonthsAgo.'-01')
  98 + ->where('gl_project_deploy_optimize.start_date','<=',$threeMonthsAgo.'-31')
98 ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr) 99 ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)
99 - ->whereIn('gl_project.type',[2,4]) 100 + ->whereIn('gl_project.type',[2,4,6])
100 ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id') 101 ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')
101 ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0") 102 ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0")
102 ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0") 103 ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0")
@@ -105,26 +106,31 @@ class AfterDayCount extends Command @@ -105,26 +106,31 @@ class AfterDayCount extends Command
105 ->whereIn('gl_project.id',$projectIdArr) 106 ->whereIn('gl_project.id',$projectIdArr)
106 ->where('gl_project.delete_status',0) 107 ->where('gl_project.delete_status',0)
107 ->where('gl_project.old_project_id',0) 108 ->where('gl_project.old_project_id',0)
108 - ->where('gl_project.created_at','<=',$threeMonthsAgo) 109 + ->where('gl_project_deploy_optimize.start_date','>=',$threeMonthsAgo.'-01')
  110 + ->where('gl_project_deploy_optimize.start_date','<=',$threeMonthsAgo.'-31')
109 ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr) 111 ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)
110 - ->whereIn('gl_project.type',[2,4]) 112 + ->whereIn('gl_project.type',[2,4,6])
111 ->where('gl_project_deploy_build.plan','!=',0) 113 ->where('gl_project_deploy_build.plan','!=',0)
112 ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id') 114 ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')
113 ->leftJoin('gl_project_deploy_build', 'gl_project.id', '=', 'gl_project_deploy_build.project_id') 115 ->leftJoin('gl_project_deploy_build', 'gl_project.id', '=', 'gl_project_deploy_build.project_id')
114 ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0") 116 ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0")
115 ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0") 117 ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0")
116 ->count(); 118 ->count();
117 - $three_rate = number_format($three_qualified_count / $three_project_count, 2); 119 + if($three_project_count != 0){
  120 + $three_rate = number_format($three_qualified_count / $three_project_count, 2);
  121 + }else{
  122 + $three_rate = 0;
  123 + }
118 $data = $projectModel->where('gl_project.extend_type',0) 124 $data = $projectModel->where('gl_project.extend_type',0)
119 ->where('gl_project.delete_status',0) 125 ->where('gl_project.delete_status',0)
120 - ->where('gl_project.created_at','<=',$todayMidnight) 126 + ->where('gl_project_deploy_optimize.start_date','<=',$todayMidnight)
121 ->where('gl_project.is_remain_today',1) 127 ->where('gl_project.is_remain_today',1)
122 ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr) 128 ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)
123 - ->whereIn('gl_project.type',[2,4]) 129 + ->whereIn('gl_project.type',[2,4,6])
124 ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id') 130 ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')
125 ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0") 131 ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0")
126 ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0") 132 ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0")
127 - ->pluck('gl_project.title')->toArray(); 133 + ->select(['gl_project.title','gl_project.finish_remain_day','gl_project_deploy_optimize.start_date'])->get()->toArray();
128 $saveData[] = [ 134 $saveData[] = [
129 'date'=>date('Y-m-d', strtotime('yesterday')), 135 'date'=>date('Y-m-d', strtotime('yesterday')),
130 'type'=> $key, 136 'type'=> $key,
@@ -290,6 +290,7 @@ class postInquiry extends Command @@ -290,6 +290,7 @@ class postInquiry extends Command
290 Log::channel('inquiry_relay')->error('inquiry_relay shop inquiry error', [$res, $url, $data]); 290 Log::channel('inquiry_relay')->error('inquiry_relay shop inquiry error', [$res, $url, $data]);
291 return false; 291 return false;
292 } 292 }
  293 + return true;
293 } 294 }
294 295
295 public function FobInquiry($detail, $log){ 296 public function FobInquiry($detail, $log){
@@ -309,6 +310,7 @@ class postInquiry extends Command @@ -309,6 +310,7 @@ class postInquiry extends Command
309 Log::channel('inquiry_relay')->error('inquiry_relay fob inquiry error', [$res, 'https://fob.ai.cc/api/ad_to_scrm', $data]); 310 Log::channel('inquiry_relay')->error('inquiry_relay fob inquiry error', [$res, 'https://fob.ai.cc/api/ad_to_scrm', $data]);
310 return false; 311 return false;
311 } 312 }
  313 + return true;
312 } 314 }
313 315
314 public function output($message) 316 public function output($message)
@@ -52,9 +52,9 @@ class LyhImportTest extends Command @@ -52,9 +52,9 @@ class LyhImportTest extends Command
52 * @time :2023/11/20 15:13 52 * @time :2023/11/20 15:13
53 */ 53 */
54 public function handle(){ 54 public function handle(){
55 - ProjectServer::useProject(3283); 55 + ProjectServer::useProject(2140);
56 echo date('Y-m-d H:i:s') . 'start' . PHP_EOL; 56 echo date('Y-m-d H:i:s') . 'start' . PHP_EOL;
57 - $this->importProductCategory('https://ecdn6.globalso.com/upload/p/3283/file/2025-04/zhouyongpaxu.csv',3283); 57 + $this->import2140CustomModule('https://ecdn6.globalso.com/upload/p/2140/file/2025-05/all-202557.csv',2140);
58 DB::disconnect('custom_mysql'); 58 DB::disconnect('custom_mysql');
59 echo date('Y-m-d H:i:s') . 'end' . PHP_EOL; 59 echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;
60 } 60 }
@@ -463,7 +463,7 @@ class LyhImportTest extends Command @@ -463,7 +463,7 @@ class LyhImportTest extends Command
463 foreach ($line_of_text as $k => $item){ 463 foreach ($line_of_text as $k => $item){
464 // try { 464 // try {
465 //添加内容 465 //添加内容
466 - $contentId = $customContentModel->addReturnId(['name'=>$item[0],'image'=>'/upload/p/2140/image/'.$item[2],'module_id'=>2,'project_id'=>$project_id]); 466 + $contentId = $customContentModel->addReturnId(['name'=>$item[0],'image'=>'/upload/p/2140/image/'.$item[2],'module_id'=>7,'project_id'=>$project_id]);
467 echo date('Y-m-d H:i:s') . '当前扩展数据id:'. $contentId . PHP_EOL; 467 echo date('Y-m-d H:i:s') . '当前扩展数据id:'. $contentId . PHP_EOL;
468 //注册路由 468 //注册路由
469 $route = RouteMap::setRoute($item[0], RouteMap::SOURCE_MODULE, 469 $route = RouteMap::setRoute($item[0], RouteMap::SOURCE_MODULE,
@@ -82,11 +82,13 @@ class UpdateRoute extends Command @@ -82,11 +82,13 @@ class UpdateRoute extends Command
82 $projectModel = new Project(); 82 $projectModel = new Project();
83 $lists = $projectModel->list(['delete_status' => 0,'extend_type'=>0,'type'=>['in',[1,2,3,4]]], 'id', ['id']); 83 $lists = $projectModel->list(['delete_status' => 0,'extend_type'=>0,'type'=>['in',[1,2,3,4]]], 'id', ['id']);
84 foreach ($lists as $val) { 84 foreach ($lists as $val) {
85 - echo date('Y-m-d H:i:s') . '开始--项目的id:'. $val['id'] . PHP_EOL; 85 +// echo date('Y-m-d H:i:s') . '开始--项目的id:'. $val['id'] . PHP_EOL;
86 ProjectServer::useProject($val['id']); 86 ProjectServer::useProject($val['id']);
87 $aiBlogModel = new AiBlogAuthor(); 87 $aiBlogModel = new AiBlogAuthor();
88 $results = $aiBlogModel->whereColumn('title', '!=', 'seo_title')->get(); 88 $results = $aiBlogModel->whereColumn('title', '!=', 'seo_title')->get();
  89 + echo '项目id:'.json_encode($results,true).PHP_EOL;
89 if(!$results){ 90 if(!$results){
  91 + $aiBlogModel->edit(['seo_title'=>'','seo_keyword'=>'','seo_description'=>''],['id'=>['>',0]]);
90 echo '项目id:'.$val['id'].PHP_EOL; 92 echo '项目id:'.$val['id'].PHP_EOL;
91 } 93 }
92 DB::disconnect('custom_mysql'); 94 DB::disconnect('custom_mysql');
@@ -56,6 +56,8 @@ class SyncMobile extends Command @@ -56,6 +56,8 @@ class SyncMobile extends Command
56 if(!empty($data)){ 56 if(!empty($data)){
57 $userModel = new User(); 57 $userModel = new User();
58 try { 58 try {
  59 + $data[] = '13083988828';
  60 + $data[] = '6591559603';
59 $userModel->edit(['status'=>1],['project_id'=>1,'mobile'=>['not in',$data]]); 61 $userModel->edit(['status'=>1],['project_id'=>1,'mobile'=>['not in',$data]]);
60 $userModel->edit(['status'=>0],['project_id'=>1,'mobile'=>['in',$data]]); 62 $userModel->edit(['status'=>0],['project_id'=>1,'mobile'=>['in',$data]]);
61 }catch (\Exception $e){ 63 }catch (\Exception $e){
@@ -16,6 +16,7 @@ use App\Models\Domain\DomainInfo; @@ -16,6 +16,7 @@ use App\Models\Domain\DomainInfo;
16 use App\Models\HomeCount\Count; 16 use App\Models\HomeCount\Count;
17 use App\Models\HomeCount\MonthCount; 17 use App\Models\HomeCount\MonthCount;
18 use App\Models\Inquiry\InquiryFormData; 18 use App\Models\Inquiry\InquiryFormData;
  19 +use App\Models\Inquiry\InquiryRelateDomain;
19 use App\Models\Project\Project; 20 use App\Models\Project\Project;
20 use App\Models\RankData\ExternalLinks; 21 use App\Models\RankData\ExternalLinks;
21 use App\Models\RankData\IndexedPages; 22 use App\Models\RankData\IndexedPages;
@@ -290,7 +291,9 @@ class OptimizationReportController extends BaseController @@ -290,7 +291,9 @@ class OptimizationReportController extends BaseController
290 //复制站点域名 291 //复制站点域名
291 $ext_projects = $this->getExtendProjects(); 292 $ext_projects = $this->getExtendProjects();
292 $flg_ext = $this->getExtFlag($ext_projects, $domain, $api_no); 293 $flg_ext = $this->getExtFlag($ext_projects, $domain, $api_no);
293 - $ext_domain = str_replace('www.', '', $this->getExtendProjects($api_no)['ext'] ?? ''); 294 + $ext_domain = str_replace('www.', '', $this->getExtendProjects($api_no)['ext'] ?? '');//关联域名
  295 + //关联域名
  296 + $relate_domain = str_replace('www.', '', InquiryRelateDomain::getRelateDomain($domain, 'globalso_domain'));
294 //AI站点域名 297 //AI站点域名
295 $ai_projects = $this->getAiProjects()['data'] ?? []; 298 $ai_projects = $this->getAiProjects()['data'] ?? [];
296 $flg_ai = $this->getAiFlag($ai_projects, $domain); 299 $flg_ai = $this->getAiFlag($ai_projects, $domain);
@@ -316,6 +319,8 @@ class OptimizationReportController extends BaseController @@ -316,6 +319,8 @@ class OptimizationReportController extends BaseController
316 $domain_text = '星链域名:' . $ai_domain; 319 $domain_text = '星链域名:' . $ai_domain;
317 } else if ($last['r'] == $ext_domain) { 320 } else if ($last['r'] == $ext_domain) {
318 $domain_text = '主域名2:' . $ext_domain; 321 $domain_text = '主域名2:' . $ext_domain;
  322 + } else if ($last['r'] == $relate_domain) {
  323 + $domain_text = '主域名2:' . $relate_domain;
319 } else { 324 } else {
320 $domain_text = 'AI域名:' . $last['r']; 325 $domain_text = 'AI域名:' . $last['r'];
321 } 326 }
@@ -13,11 +13,13 @@ use App\Models\Ai\AiBlog; @@ -13,11 +13,13 @@ use App\Models\Ai\AiBlog;
13 use App\Models\Blog\Blog; 13 use App\Models\Blog\Blog;
14 use App\Models\Domain\DomainInfo; 14 use App\Models\Domain\DomainInfo;
15 use App\Models\Inquiry\InquiryRelateDomain; 15 use App\Models\Inquiry\InquiryRelateDomain;
  16 +use App\Models\Manage\ManageHr;
16 use App\Models\News\News; 17 use App\Models\News\News;
17 use App\Models\Product\Category; 18 use App\Models\Product\Category;
18 use App\Models\Product\CategoryRelated; 19 use App\Models\Product\CategoryRelated;
19 use App\Models\Product\Keyword; 20 use App\Models\Product\Keyword;
20 use App\Models\Product\Product; 21 use App\Models\Product\Product;
  22 +use App\Models\Project\DeployBuild;
21 use App\Models\Project\DeployOptimize; 23 use App\Models\Project\DeployOptimize;
22 use App\Models\Project\OnlineCheck; 24 use App\Models\Project\OnlineCheck;
23 use App\Models\Project\Project; 25 use App\Models\Project\Project;
@@ -491,4 +493,49 @@ class PrivateController extends BaseController @@ -491,4 +493,49 @@ class PrivateController extends BaseController
491 493
492 return $this->success($relate); 494 return $this->success($relate);
493 } 495 }
  496 +
  497 + /**
  498 + * 根据域名获取项目人员配置信息
  499 + * @param Request $request
  500 + * @return false|string
  501 + */
  502 + public function getProjectManageByDomain(Request $request)
  503 + {
  504 + $domain = trim($request->input('domain'));
  505 + $domain_parse = parse_url($domain);
  506 + $domain = $domain_parse['host'] ?? $domain;
  507 +
  508 + if (empty($domain)) {
  509 + return $this->error('非法参数!');
  510 + }
  511 +
  512 + $project = Project::getProjectByDomain($domain);
  513 + if (empty($project)) {
  514 + return $this->error('未找到当前域名对应的项目!');
  515 + }
  516 +
  517 + $build = DeployBuild::select(['leader_mid', 'manager_mid', 'designer_mid', 'tech_mid'])->where(['project_id' => $project->id])->first();
  518 + $optimize = DeployOptimize::select(['manager_mid', 'optimist_mid', 'assist_mid', 'tech_mid', 'tech_leader', 'quality_mid', 'design_mid'])->where(['project_id' => $project->id])->first();
  519 +
  520 + $build = $build ? $build->toArray() : [];
  521 + $optimize = $optimize ? $optimize->toArray() : [];
  522 + $manage_ids = array_merge(array_values($build), array_values($optimize));
  523 +
  524 +
  525 + $member = ManageHr::whereIn('id', $manage_ids)->pluck('name', 'id')->toArray();
  526 + $result = [
  527 + 'build_leader' => $build && $build['leader_mid'] ? $member[$build['leader_mid']] : '', // 组长
  528 + 'build_manager' => $build && $build['manager_mid'] ? $member[$build['manager_mid']] : '', // 项目经理
  529 + 'build_designer' => $build && $build['designer_mid'] ? $member[$build['designer_mid']] : '', // 设计师
  530 + 'build_tech' => $build && $build['tech_mid'] ? $member[$build['tech_mid']] : '', // 技术助理
  531 + 'optimize_manager' => $optimize && $optimize['manager_mid'] ? $member[$optimize['manager_mid']] : '', // 优化经理
  532 + 'optimize_optimist' => $optimize && $optimize['optimist_mid'] ? $member[$optimize['optimist_mid']] : '',// 优化师
  533 + 'optimize_assist' => $optimize && $optimize['assist_mid'] ? $member[$optimize['assist_mid']] : '', // 优化师助理
  534 + 'optimize_tech' => $optimize && $optimize['tech_mid'] ? $member[$optimize['tech_mid']] : '', // 售后技术
  535 + 'optimize_leader' => $optimize && $optimize['tech_leader'] ? $member[$optimize['tech_leader']] : '', // 售后主管
  536 + 'optimize_quality' => $optimize && $optimize['quality_mid'] ? $member[$optimize['quality_mid']] : '', // 品控
  537 + 'optimize_design' => $optimize && $optimize['design_mid'] ? $member[$optimize['design_mid']] : '', // 平面设计
  538 + ];
  539 + return $this->success($result);
  540 + }
494 } 541 }
@@ -7,6 +7,7 @@ use App\Helper\Translate; @@ -7,6 +7,7 @@ use App\Helper\Translate;
7 use App\Models\Product\Category; 7 use App\Models\Product\Category;
8 use App\Models\Product\CategoryRelated; 8 use App\Models\Product\CategoryRelated;
9 use App\Models\Product\Product; 9 use App\Models\Product\Product;
  10 +use App\Models\Project\ProjectAiSetting;
10 use App\Models\RouteMap\RouteMap; 11 use App\Models\RouteMap\RouteMap;
11 use App\Services\CosService; 12 use App\Services\CosService;
12 use App\Services\ProjectServer; 13 use App\Services\ProjectServer;
@@ -251,4 +252,30 @@ class ProductController extends BaseController @@ -251,4 +252,30 @@ class ProductController extends BaseController
251 252
252 return $suggestions; 253 return $suggestions;
253 } 254 }
  255 +
  256 + /**
  257 + * 搜索给AI博客 产品推荐用
  258 + * 全文搜索 产品标题
  259 + * @author zbj
  260 + * @date 2025/5/8
  261 + */
  262 + public function searchProductToAiBlog(Request $request){
  263 + $mch_id = $request->input('mch_id');
  264 + $key = $request->input('key');
  265 + $keyword = $request->input('keyword');
  266 +
  267 + if(!$keyword){
  268 + $this->response('关键词不能为空', Code::SYSTEM_ERROR);
  269 + }
  270 + $project_id = ProjectAiSetting::where('mch_id', $mch_id)->where('key', $key)->value('project_id');
  271 + if(!$project_id){
  272 + $this->response('项目不存在', Code::SYSTEM_ERROR);
  273 + }
  274 +
  275 + ProjectServer::useProject($project_id);
  276 +
  277 + $product = Product::whereFullText('title', $keyword)->inRandomOrder()->select(['title', 'intro', 'thumb'])->first();
  278 +
  279 + $this->response('success', Code::SUCCESS, $product?:[]);
  280 + }
254 } 281 }
@@ -48,6 +48,9 @@ class AiBlogController extends BaseController @@ -48,6 +48,9 @@ class AiBlogController extends BaseController
48 'id.required' => '主键不能为空', 48 'id.required' => '主键不能为空',
49 ]); 49 ]);
50 $info = $aiBlog->read(['id'=>$this->param['id']]); 50 $info = $aiBlog->read(['id'=>$this->param['id']]);
  51 + if(!empty($info['anchor'])){
  52 + $info['anchor'] = json_decode($info['anchor'],true);
  53 + }
51 $info['image'] = getImageUrl($info['image']); 54 $info['image'] = getImageUrl($info['image']);
52 $this->response('success',Code::SUCCESS,$info); 55 $this->response('success',Code::SUCCESS,$info);
53 } 56 }
@@ -79,13 +82,32 @@ class AiBlogController extends BaseController @@ -79,13 +82,32 @@ class AiBlogController extends BaseController
79 * @method :post 82 * @method :post
80 * @time :2023/7/5 14:33 83 * @time :2023/7/5 14:33
81 */ 84 */
82 - public function save(AiBlogRequest $aiBlogRequest,AiBlogLogic $aiBlogLogic){  
83 - $aiBlogRequest->validated(); 85 + public function save(AiBlogLogic $aiBlogLogic){
  86 +// $aiBlogRequest->validated();
84 $aiBlogLogic->blogSave(); 87 $aiBlogLogic->blogSave();
85 $this->response('success'); 88 $this->response('success');
86 } 89 }
87 90
88 /** 91 /**
  92 + * @remark :
  93 + * @name :saveText
  94 + * @author :lyh
  95 + * @method :post
  96 + * @time :2025/4/30 18:05
  97 + */
  98 + public function saveText(AiBlogLogic $aiBlogLogic){
  99 + $this->request->validate([
  100 + 'id'=>['required'],
  101 + 'text'=>['required'],
  102 + ],[
  103 + 'id.required' => '关键字不能为空',
  104 + 'text.required' => '场景不能为空',
  105 + ]);
  106 + $aiBlogLogic->blogSaveText();
  107 + $this->response('success');
  108 + }
  109 +
  110 + /**
89 * @remark :获取作者列表 111 * @remark :获取作者列表
90 * @name :getAiBlogAuthor 112 * @name :getAiBlogAuthor
91 * @author :lyh 113 * @author :lyh
@@ -13,6 +13,7 @@ use App\Enums\Common\Code; @@ -13,6 +13,7 @@ use App\Enums\Common\Code;
13 use App\Http\Controllers\Bside\BaseController; 13 use App\Http\Controllers\Bside\BaseController;
14 use App\Http\Logic\Bside\Ai\AiVideoLogic; 14 use App\Http\Logic\Bside\Ai\AiVideoLogic;
15 use App\Models\Ai\AiVideo; 15 use App\Models\Ai\AiVideo;
  16 +use App\Models\Ai\AiVideoList;
16 17
17 class AiVideoController extends BaseController 18 class AiVideoController extends BaseController
18 { 19 {
@@ -51,6 +52,8 @@ class AiVideoController extends BaseController @@ -51,6 +52,8 @@ class AiVideoController extends BaseController
51 'id.required' => '主键不能为空', 52 'id.required' => '主键不能为空',
52 ]); 53 ]);
53 $info = $aiVideo->read(['id'=>$this->param['id']]); 54 $info = $aiVideo->read(['id'=>$this->param['id']]);
  55 + $info['anchor'] = json_decode($info['anchor'] ?? [],true);
  56 + $info['images'] = json_decode($info['images'] ?? [],true);
54 $this->response('success',Code::SUCCESS,$info); 57 $this->response('success',Code::SUCCESS,$info);
55 } 58 }
56 59
@@ -109,4 +112,40 @@ class AiVideoController extends BaseController @@ -109,4 +112,40 @@ class AiVideoController extends BaseController
109 $result = $aiVideoLogic->videoDelete(); 112 $result = $aiVideoLogic->videoDelete();
110 $this->response('success',Code::SUCCESS,$result); 113 $this->response('success',Code::SUCCESS,$result);
111 } 114 }
  115 +
  116 +
  117 + /**
  118 + * @remark :获取列表页数据
  119 + * @name :getAiBlogList
  120 + * @author :lyh
  121 + * @method :post
  122 + * @time :2025/2/21 16:22
  123 + */
  124 + public function getAiVideoList(AiVideoList $aiVideoList){
  125 + $lists = $aiVideoList->lists($this->map,$this->page,$this->row,'id',['id','route','created_at','updated_at']);
  126 + if(!empty($lists) && !empty($lists['list'])){
  127 + foreach ($lists['list'] as $k => $v){
  128 + $v['route'] = $this->user['domain'] . 'top-video/' . (($v['route'] > 1) ? $v['route'] : '');
  129 + $lists['list'][$k] = $v;
  130 + }
  131 + }
  132 + $this->response('success',Code::SUCCESS,$lists);
  133 + }
  134 +
  135 + /**
  136 + * @remark :获取列表页数据详情
  137 + * @name :getAiBlogListInfo
  138 + * @author :lyh
  139 + * @method :post
  140 + * @time :2025/2/21 16:26
  141 + */
  142 + public function getAiBlogListInfo(AiVideoList $aiVideoList){
  143 + $this->request->validate([
  144 + 'id'=>['required'],
  145 + ],[
  146 + 'id.required' => '主键不能为空',
  147 + ]);
  148 + $info = $aiVideoList->read($this->map);
  149 + $this->response('success',Code::SUCCESS,$info);
  150 + }
112 } 151 }
@@ -147,6 +147,10 @@ class ComController extends BaseController @@ -147,6 +147,10 @@ class ComController extends BaseController
147 if($is_blogs != 1){ 147 if($is_blogs != 1){
148 $info['role_menu'] = trim(str_replace(',57,',',',','.$info['role_menu'].','),','); 148 $info['role_menu'] = trim(str_replace(',57,',',',','.$info['role_menu'].','),',');
149 } 149 }
  150 + $is_video = $this->getIsAiVideo();
  151 + if($is_video != 1){
  152 + $info['role_menu'] = trim(str_replace(',74,',',',','.$info['role_menu'].','),',');
  153 + }
150 $this->map = [ 154 $this->map = [
151 'status'=>0, 155 'status'=>0,
152 'is_role'=>0, 156 'is_role'=>0,
@@ -195,6 +199,10 @@ class ComController extends BaseController @@ -195,6 +199,10 @@ class ComController extends BaseController
195 if($is_ai_blog != 1){ 199 if($is_ai_blog != 1){
196 $data[] = 57; 200 $data[] = 57;
197 } 201 }
  202 + $is_ai_video = $this->getIsAiVideo();
  203 + if($is_ai_video != 1){
  204 + $data[] = 74;
  205 + }
198 if(!empty($data)){ 206 if(!empty($data)){
199 $this->map['id'] = ['not in',$data]; 207 $this->map['id'] = ['not in',$data];
200 } 208 }
@@ -291,6 +299,16 @@ class ComController extends BaseController @@ -291,6 +299,16 @@ class ComController extends BaseController
291 return $this->user['is_ai_blog'] ?? 0; 299 return $this->user['is_ai_blog'] ?? 0;
292 } 300 }
293 301
  302 + /**
  303 + * @remark :ai视频
  304 + * @name :getIsAiVideo
  305 + * @author :lyh
  306 + * @method :post
  307 + * @time :2025/5/6 14:33
  308 + */
  309 + public function getIsAiVideo(){
  310 + return $this->user['is_ai_video'] ?? 0;
  311 + }
294 312
295 /** 313 /**
296 * @name :登录用户编辑资料/修改密码 314 * @name :登录用户编辑资料/修改密码
@@ -43,16 +43,6 @@ class TestController extends BaseController @@ -43,16 +43,6 @@ class TestController extends BaseController
43 * @time :2025/2/13 16:34 43 * @time :2025/2/13 16:34
44 */ 44 */
45 public function ceshi(){ 45 public function ceshi(){
46 - $this->param = [  
47 - 'title'=>'apple',  
48 - 'description'=>'apples',  
49 - 'images'=>[  
50 - ['url'=>'https://ecdn6.globalso.com/upload/public/template/64e332671b32e25328.png','title'=>'apple'],  
51 - ['url'=>'https://ecdn6.globalso.com/upload/public/template/64e32a24b314a39425.png','title'=>'apples'],  
52 - ],  
53 - ];  
54 - $aiVideoService = new AiVideoService(467);  
55 - $result = $aiVideoService->createTask($this->param['title'],$this->param['description'],$this->param['images'],$this->param['anchor'] ?? []);  
56 - $this->response('success',Code::SUCCESS,$result); 46 + $this->response('success',Code::SUCCESS,[]);
57 } 47 }
58 } 48 }
@@ -166,7 +166,7 @@ class ProjectLogic extends BaseLogic @@ -166,7 +166,7 @@ class ProjectLogic extends BaseLogic
166 }else{ 166 }else{
167 $this->param = $this->handleLevelStr($this->param);//处理星级客户暂停优化默认参数 167 $this->param = $this->handleLevelStr($this->param);//处理星级客户暂停优化默认参数
168 $this->saveSeoPlan($this->param);//保存seo白帽类型,上线保存一条审核记录 168 $this->saveSeoPlan($this->param);//保存seo白帽类型,上线保存一条审核记录
169 - $this->checkAiBlog($this->param);//开启白帽验证参数 169 + $this->checkAiBlog($this->param);//开启ai相关功能验证参数
170 DB::beginTransaction(); 170 DB::beginTransaction();
171 try { 171 try {
172 //初始化项目 172 //初始化项目
@@ -174,8 +174,9 @@ class ProjectLogic extends BaseLogic @@ -174,8 +174,9 @@ class ProjectLogic extends BaseLogic
174 //双向绑定服务器,需放到保存项目的上方 174 //双向绑定服务器,需放到保存项目的上方
175 $this->setServers($this->param['serve_id'],$this->param['id']); 175 $this->setServers($this->param['serve_id'],$this->param['id']);
176 //ai_blog 176 //ai_blog
177 - $this->setAiBlog($this->param['id'],$this->param['main_lang_id'],$this->param['is_ai_blog'],  
178 - $this->param['company']??"", $this->param['deploy_optimize']['company_en_name'] ?? '',$this->param['deploy_optimize']['company_en_description'] ?? ''); 177 + $this->setAiBlog($this->param['id'],$this->param['main_lang_id'],$this->param['is_ai_blog'] ?? 0,
  178 + $this->param['company']??"", $this->param['deploy_optimize']['company_en_name'] ?? '',
  179 + $this->param['deploy_optimize']['company_en_description'] ?? '',$this->param['is_ai_video'] ?? 0);
179 //保存项目信息 180 //保存项目信息
180 $this->saveProject($this->param); 181 $this->saveProject($this->param);
181 //保存建站部署信息 182 //保存建站部署信息
@@ -217,6 +218,7 @@ class ProjectLogic extends BaseLogic @@ -217,6 +218,7 @@ class ProjectLogic extends BaseLogic
217 if (in_array('2', $param['level']) || in_array('3', $param['level'])) { 218 if (in_array('2', $param['level']) || in_array('3', $param['level'])) {
218 //优化设置默认关闭 219 //优化设置默认关闭
219 $param['is_ai_blog'] = 0; 220 $param['is_ai_blog'] = 0;
  221 + $param['is_ai_video'] = 0;
220 $param['deploy_optimize']['is_ai_blog_send'] = 0; 222 $param['deploy_optimize']['is_ai_blog_send'] = 0;
221 $param['deploy_optimize']['is_auto_keywords'] = 0; 223 $param['deploy_optimize']['is_auto_keywords'] = 0;
222 } 224 }
@@ -259,7 +261,7 @@ class ProjectLogic extends BaseLogic @@ -259,7 +261,7 @@ class ProjectLogic extends BaseLogic
259 } 261 }
260 262
261 /** 263 /**
262 - * @remark :开启白帽验证参数 264 + * @remark :开启ai博客及视频
263 * @name :checkAiBlog 265 * @name :checkAiBlog
264 * @author :lyh 266 * @author :lyh
265 * @method :post 267 * @method :post
@@ -272,7 +274,7 @@ class ProjectLogic extends BaseLogic @@ -272,7 +274,7 @@ class ProjectLogic extends BaseLogic
272 $company = $param['company'] ?? ''; 274 $company = $param['company'] ?? '';
273 $company_en_name = $param['deploy_optimize']['company_en_name'] ?? ''; 275 $company_en_name = $param['deploy_optimize']['company_en_name'] ?? '';
274 $company_en_description = $param['deploy_optimize']['company_en_description'] ?? ''; 276 $company_en_description = $param['deploy_optimize']['company_en_description'] ?? '';
275 - if($is_ai_blog == 1 || $is_ai_video){ 277 + if($is_ai_blog == 1 || $is_ai_video == 1){
276 if(empty($main_lang_id) || empty($company) || empty($company_en_name) || empty($company_en_description)){ 278 if(empty($main_lang_id) || empty($company) || empty($company_en_name) || empty($company_en_description)){
277 $this->fail('开启ai博客/视频功能--请填写主语种+公司名称+公司英文名称+公司英文介绍'); 279 $this->fail('开启ai博客/视频功能--请填写主语种+公司名称+公司英文名称+公司英文介绍');
278 } 280 }
@@ -287,11 +289,11 @@ class ProjectLogic extends BaseLogic @@ -287,11 +289,11 @@ class ProjectLogic extends BaseLogic
287 * @method :post 289 * @method :post
288 * @time :2025/2/13 16:02 290 * @time :2025/2/13 16:02
289 */ 291 */
290 - public function setAiBlog($project_id,$main_lang_id,$is_ai_blog,$company,$company_en_name,$company_en_description){  
291 - if(empty($main_lang_id) || empty($is_ai_blog)){ 292 + public function setAiBlog($project_id,$main_lang_id,$is_ai_blog,$company,$company_en_name,$company_en_description,$is_ai_video = 0){
  293 + if(empty($main_lang_id) || (empty($is_ai_blog) && empty($is_ai_video))){
292 return true; 294 return true;
293 } 295 }
294 - $projectInfo = $this->model->read(['id'=>$project_id],['title','is_ai_blog','main_lang_id','company']); 296 + $projectInfo = $this->model->read(['id'=>$project_id],['title','main_lang_id','company']);
295 $projectOptimize = DeployOptimize::where('project_id', $project_id)->first(); 297 $projectOptimize = DeployOptimize::where('project_id', $project_id)->first();
296 //获取项目主语种 298 //获取项目主语种
297 $languageModel = new WebLanguage(); 299 $languageModel = new WebLanguage();
@@ -57,17 +57,18 @@ class AiBlogLogic extends BaseLogic @@ -57,17 +57,18 @@ class AiBlogLogic extends BaseLogic
57 $this->param['image'] = str_replace_url($this->param['image']); 57 $this->param['image'] = str_replace_url($this->param['image']);
58 } 58 }
59 $this->param['route'] = RouteMap::setRoute($this->param['route'], RouteMap::SOURCE_AI_BLOG, $this->param['id'], $this->user['project_id']); 59 $this->param['route'] = RouteMap::setRoute($this->param['route'], RouteMap::SOURCE_AI_BLOG, $this->param['id'], $this->user['project_id']);
  60 + $anchor = $this->param['anchor'] ?? [];
  61 + $this->param['anchor'] = json_encode($anchor,true);
60 $this->model->edit($this->param,['id'=>$this->param['id']]); 62 $this->model->edit($this->param,['id'=>$this->param['id']]);
61 $aiSettingInfo = $this->getProjectAiSetting(); 63 $aiSettingInfo = $this->getProjectAiSetting();
62 $aiBlogService = new AiBlogService(); 64 $aiBlogService = new AiBlogService();
63 $aiBlogService->mch_id = $aiSettingInfo['mch_id']; 65 $aiBlogService->mch_id = $aiSettingInfo['mch_id'];
64 $aiBlogService->key = $aiSettingInfo['key']; 66 $aiBlogService->key = $aiSettingInfo['key'];
65 - $aiBlogService->updateDetail(['task_id'=>$this->param['task_id'],'title'=>$this->param['new_title'],'thumb'=>$this->param['image'],'route'=>$this->param['route'],'author_id'=>$this->param['author_id']]);  
66 - $aiBlogTaskModel = new AiBlogTask();  
67 - $aiBlogTaskModel->edit(['status'=>AiBlogTask::STATUS_RUNNING],['task_id'=>$this->param['task_id']]);//重新走拉取流程 67 + $aiBlogService->updateDetail(['task_id'=>$this->param['task_id'],'title'=>$this->param['new_title'],'thumb'=>$this->param['image'],'route'=>$this->param['route'],'author_id'=>$anchor]);
68 }catch (\Exception $e){ 68 }catch (\Exception $e){
69 $this->fail('保存失败,请联系管理员'); 69 $this->fail('保存失败,请联系管理员');
70 } 70 }
  71 + shell_exec("php artisan save_ai_blog_list {$this->user['project_id']} > /dev/null 2>&1 &");
71 return $this->success(); 72 return $this->success();
72 } 73 }
73 74
@@ -29,21 +29,6 @@ class AiVideoLogic extends BaseLogic @@ -29,21 +29,6 @@ class AiVideoLogic extends BaseLogic
29 $this->model = new AiVideo(); 29 $this->model = new AiVideo();
30 } 30 }
31 31
32 - /**  
33 - * @remark :获取配置信息  
34 - * @name :getProjectAiSetting  
35 - * @author :lyh  
36 - * @method :post  
37 - * @time :2025/2/21 14:51  
38 - */  
39 - public function getProjectAiSetting(){  
40 - $projectAiSettingModel = new ProjectAiSetting();  
41 - $aiSettingInfo = $projectAiSettingModel->read(['project_id'=>$this->user['project_id']]);  
42 - if($aiSettingInfo === false){  
43 - $this->fail('请先联系管理员开启Ai配置');  
44 - }  
45 - return $aiSettingInfo;  
46 - }  
47 32
48 /** 33 /**
49 * @remark :ai发布博客 34 * @remark :ai发布博客
@@ -54,13 +39,14 @@ class AiVideoLogic extends BaseLogic @@ -54,13 +39,14 @@ class AiVideoLogic extends BaseLogic
54 */ 39 */
55 public function videoSave(){ 40 public function videoSave(){
56 try { 41 try {
57 - $this->param['route'] = RouteMap::setRoute($this->param['tit'], RouteMap::SOURCE_AI_VIDEO, $this->param['id'], $this->user['project_id']); 42 + $this->param['route'] = RouteMap::setRoute($this->param['route'], RouteMap::SOURCE_AI_VIDEO, $this->param['id'], $this->user['project_id']);
  43 + $anchor = $this->param['anchor'] ?? [];
  44 + $this->param['anchor'] = json_encode($anchor,true);
  45 + $this->param['images'] = json_encode($this->param['images'],true);
58 $this->model->edit($this->param,['id'=>$this->param['id']]); 46 $this->model->edit($this->param,['id'=>$this->param['id']]);
59 - $aiSettingInfo = $this->getProjectAiSetting();  
60 - $aiBlogService = new AiBlogService();  
61 - $aiBlogService->mch_id = $aiSettingInfo['mch_id'];  
62 - $aiBlogService->key = $aiSettingInfo['key'];  
63 - $aiBlogService->updateDetail(['task_id'=>$this->param['task_id'],'title'=>$this->param['new_title'],'thumb'=>$this->param['image'],'route'=>$this->param['route'],'author_id'=>$this->param['author_id']]); 47 + $aiVideoService = new AiVideoService($this->user['project_id']);
  48 + $aiVideoService->updateDetail(['task_id'=>$this->param['task_id'],'title'=>$this->param['title'],
  49 + 'content'=>$this->param['content'] ?? '','video_url'=>$this->param['video_url'],'anchor'=>$anchor,'thumb'=>$this->param['image'],'url'=>$this->param['route'],'author_id'=>$this->param['author_id']]);
64 }catch (\Exception $e){ 50 }catch (\Exception $e){
65 $this->fail('保存失败,请联系管理员'); 51 $this->fail('保存失败,请联系管理员');
66 } 52 }
@@ -81,7 +67,7 @@ class AiVideoLogic extends BaseLogic @@ -81,7 +67,7 @@ class AiVideoLogic extends BaseLogic
81 if($result['status'] == 200){ 67 if($result['status'] == 200){
82 $aiVideoTaskModel = new AiVideoTask(); 68 $aiVideoTaskModel = new AiVideoTask();
83 $aiVideoTaskModel->addReturnId(['task_id'=>$result['data']['task_id'],'project_id'=>$this->user['project_id']]); 69 $aiVideoTaskModel->addReturnId(['task_id'=>$result['data']['task_id'],'project_id'=>$this->user['project_id']]);
84 - $id = $this->model->addReturnId(['task_id'=>$result['data']['task_id'],'description'=>$this->param['description'],'project_id'=>$this->user['project_id'],'images'=>json_encode($this->param['images'],true),'anchor'=>json_encode($this->param['anchor'] ?? [],true)]); 70 + $id = $this->model->addReturnId(['title'=>$this->param['title'],'task_id'=>$result['data']['task_id'],'description'=>$this->param['description'],'project_id'=>$this->user['project_id'],'images'=>json_encode($this->param['images'],true),'anchor'=>json_encode($this->param['anchor'] ?? [],true)]);
85 return $this->success(['id'=>$id]); 71 return $this->success(['id'=>$id]);
86 } 72 }
87 return $this->success(); 73 return $this->success();
@@ -96,13 +82,10 @@ class AiVideoLogic extends BaseLogic @@ -96,13 +82,10 @@ class AiVideoLogic extends BaseLogic
96 */ 82 */
97 public function videoDelete(){ 83 public function videoDelete(){
98 try { 84 try {
99 - $aiSettingInfo = $this->getProjectAiSetting();  
100 - $aiBlogService = new AiBlogService(); 85 + $aiBlogService = new AiVideoService($this->user['project_id']);
101 foreach ($this->param['ids'] as $id) { 86 foreach ($this->param['ids'] as $id) {
102 $info = $this->model->read(['id'=>$id],['task_id']); 87 $info = $this->model->read(['id'=>$id],['task_id']);
103 - $aiBlogService->mch_id = $aiSettingInfo['mch_id'];  
104 - $aiBlogService->key = $aiSettingInfo['key'];  
105 - $aiBlogService->delDetail($info['task_id']); 88 + $aiBlogService->delVideoDetail($info['task_id']);
106 //删除路由映射 89 //删除路由映射
107 RouteMap::delRoute(RouteMap::SOURCE_AI_VIDEO, $id, $this->user['project_id']); 90 RouteMap::delRoute(RouteMap::SOURCE_AI_VIDEO, $id, $this->user['project_id']);
108 $this->model->del(['id'=>$id]); 91 $this->model->del(['id'=>$id]);
@@ -11,6 +11,7 @@ use App\Http\Logic\Aside\Project\DomainInfoLogic; @@ -11,6 +11,7 @@ use App\Http\Logic\Aside\Project\DomainInfoLogic;
11 use App\Http\Logic\Aside\Project\ProjectLogic; 11 use App\Http\Logic\Aside\Project\ProjectLogic;
12 use App\Http\Logic\Bside\BaseLogic; 12 use App\Http\Logic\Bside\BaseLogic;
13 use App\Models\Domain\DomainInfo; 13 use App\Models\Domain\DomainInfo;
  14 +use App\Models\Inquiry\InquiryRelateDomain;
14 use App\Models\Project\DeployBuild; 15 use App\Models\Project\DeployBuild;
15 use App\Models\Project\DeployOptimize; 16 use App\Models\Project\DeployOptimize;
16 use App\Models\Project\MinorLanguages; 17 use App\Models\Project\MinorLanguages;
@@ -233,6 +234,8 @@ class RankDataLogic extends BaseLogic @@ -233,6 +234,8 @@ class RankDataLogic extends BaseLogic
233 $flg_ext = $this->getExtFlag($ext_projects, $domain, $api_no); 234 $flg_ext = $this->getExtFlag($ext_projects, $domain, $api_no);
234 $ext_domain = str_replace('www.', '', $this->getExtendProjects($api_no)['ext'] ?? ''); 235 $ext_domain = str_replace('www.', '', $this->getExtendProjects($api_no)['ext'] ?? '');
235 $main_domain = str_replace('www.', '', $this->getExtendProjects($api_no)['url'] ?? ''); 236 $main_domain = str_replace('www.', '', $this->getExtendProjects($api_no)['url'] ?? '');
  237 + //关联域名
  238 + $relate_domain = str_replace('www.', '', InquiryRelateDomain::getRelateDomain($domain, 'globalso_domain'));
236 //AI站点域名 239 //AI站点域名
237 $ai_projects = $this->getAiProjects()['data'] ?? []; 240 $ai_projects = $this->getAiProjects()['data'] ?? [];
238 $flg_ai = $this->getAiFlag($ai_projects, $domain); 241 $flg_ai = $this->getAiFlag($ai_projects, $domain);
@@ -263,6 +266,8 @@ class RankDataLogic extends BaseLogic @@ -263,6 +266,8 @@ class RankDataLogic extends BaseLogic
263 $domain_text = '星链域名:' . $ai_domain; 266 $domain_text = '星链域名:' . $ai_domain;
264 } else if ($last['r'] == $ext_domain) { 267 } else if ($last['r'] == $ext_domain) {
265 $domain_text = '主域名2:' . $ext_domain; 268 $domain_text = '主域名2:' . $ext_domain;
  269 + } else if ($last['r'] == $relate_domain) {
  270 + $domain_text = '主域名2:' . $relate_domain;
266 } else { 271 } else {
267 $domain_text = 'AI域名:' . $last['r']; 272 $domain_text = 'AI域名:' . $last['r'];
268 } 273 }
@@ -540,7 +545,7 @@ class RankDataLogic extends BaseLogic @@ -540,7 +545,7 @@ class RankDataLogic extends BaseLogic
540 $without_project_ids = []; //不用处理排名的项目 545 $without_project_ids = []; //不用处理排名的项目
541 $without_extension_project_ids = [658]; //是否达标只统计主词的 546 $without_extension_project_ids = [658]; //是否达标只统计主词的
542 $extension_project_ids = [354]; //扩展词也到达标的 547 $extension_project_ids = [354]; //扩展词也到达标的
543 - $compliance_project_ids = [2163,257,823,1750]; //直接达标处理的 548 + $compliance_project_ids = [2163,257,823,1750,497]; //直接达标处理的
544 $ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250];//暂停的项目 549 $ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250];//暂停的项目
545 $uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目 550 $uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目
546 //一个项目多个api_no 551 //一个项目多个api_no
@@ -274,7 +274,8 @@ class UserLoginLogic @@ -274,7 +274,8 @@ class UserLoginLogic
274 $info['is_show_blog'] = $project['is_show_blog']; 274 $info['is_show_blog'] = $project['is_show_blog'];
275 $info['upload_config'] = $project['upload_config']; 275 $info['upload_config'] = $project['upload_config'];
276 $info['main_lang_id'] = $project['main_lang_id']; 276 $info['main_lang_id'] = $project['main_lang_id'];
277 - $info['is_ai_blog'] = $project['is_ai_blog']; 277 + $info['is_ai_blog'] = $project['is_ai_blog'] ?? 0;
  278 + $info['is_ai_video'] = $project['is_ai_video'] ?? 0;
278 $info['image_max'] = $project['image_max']; 279 $info['image_max'] = $project['image_max'];
279 $info['is_del_inquiry'] = $project['is_del_inquiry'] ?? 0; 280 $info['is_del_inquiry'] = $project['is_del_inquiry'] ?? 0;
280 $info['uptime_type'] = $this->getHistory($project); 281 $info['uptime_type'] = $this->getHistory($project);
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :AiBlogList.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/2/21 15:57
  8 + */
  9 +
  10 +namespace App\Models\Ai;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +class AiVideoList extends Base
  15 +{
  16 + protected $table = 'gl_ai_video_list';
  17 + //连接数据库
  18 + protected $connection = 'custom_mysql';
  19 +}
@@ -28,8 +28,8 @@ class InquiryRelateDomain extends Base @@ -28,8 +28,8 @@ class InquiryRelateDomain extends Base
28 * @author zbj 28 * @author zbj
29 * @date 2025/4/12 29 * @date 2025/4/12
30 */ 30 */
31 - public static function getRelateDomain($domain){  
32 - $list_cache_key = 'RelateDomainList'; 31 + public static function getRelateDomain($domain, $k = 'domain'){
  32 + $list_cache_key = 'RelateDomainList_' . $k;
33 $data = Cache::get($list_cache_key); 33 $data = Cache::get($list_cache_key);
34 if(!$data){ 34 if(!$data){
35 $data = []; 35 $data = [];
@@ -41,7 +41,11 @@ class InquiryRelateDomain extends Base @@ -41,7 +41,11 @@ class InquiryRelateDomain extends Base
41 $res = Arr::s2a($res); 41 $res = Arr::s2a($res);
42 $arr = []; 42 $arr = [];
43 foreach ($res['data']['data'] as $item){ 43 foreach ($res['data']['data'] as $item){
44 - $arr[$item['domain']] = $item['globalso_domain']; 44 + if($k == 'domain'){
  45 + $arr[$item['domain']] = $item['globalso_domain'];
  46 + }else{
  47 + $arr[$item['globalso_domain']] = $item['domain'];
  48 + }
45 } 49 }
46 $data = array_merge($data, $arr); 50 $data = array_merge($data, $arr);
47 if ($res['data']['last_page'] == $page) { 51 if ($res['data']['last_page'] == $page) {
@@ -37,6 +37,7 @@ class RouteMap extends Base @@ -37,6 +37,7 @@ class RouteMap extends Base
37 const SOURCE_AI_VIDEO = 'ai_video'; 37 const SOURCE_AI_VIDEO = 'ai_video';
38 const SOURCE_AI_BLOG_AUTHOR = 'ai_blog_author';//ai博客作者 38 const SOURCE_AI_BLOG_AUTHOR = 'ai_blog_author';//ai博客作者
39 const SOURCE_AI_BLOG_LIST = 'ai_blog_list'; 39 const SOURCE_AI_BLOG_LIST = 'ai_blog_list';
  40 + const SOURCE_AI_VIDEO_LIST = 'ai_blog_video';
40 //自定义模块分类 41 //自定义模块分类
41 const SOURCE_MODULE_CATE = 'module_category'; 42 const SOURCE_MODULE_CATE = 'module_category';
42 43
@@ -99,6 +99,41 @@ class AiVideoService @@ -99,6 +99,41 @@ class AiVideoService
99 } 99 }
100 100
101 /** 101 /**
  102 + * @remark :获取列表页数据
  103 + * @name :getAiVideoList
  104 + * @author :lyh
  105 + * @method :post
  106 + * @time :2025/4/30 15:48
  107 + */
  108 + public function getAiVideoList($page,$page_size){
  109 + $request_url = $this->url.'api/video/list';
  110 + $param['mch_id'] = $this->mch_id;
  111 + $param['page'] = $page;
  112 + $param['page_size'] = $page_size;
  113 + $this->sign = $this->generateSign($param,$this->key);
  114 + $param['sign'] = $this->sign;
  115 + $result = http_post($request_url,json_encode($param,true));
  116 + return $result;
  117 + }
  118 +
  119 + /**
  120 + * @remark :删除详情数据
  121 + * @name :delDetail
  122 + * @author :lyh
  123 + * @method :post
  124 + * @time :2025/4/30 16:00
  125 + */
  126 + public function delVideoDetail($task_id){
  127 + $param['task_id'] = $task_id;
  128 + $request_url = $this->url.'api/video/delete';
  129 + $param['mch_id'] = $this->mch_id;
  130 + $this->sign = $this->generateSign($param,$this->key);
  131 + $param['sign'] = $this->sign;
  132 + $result = http_post($request_url,json_encode($param,true));
  133 + return $result;
  134 + }
  135 +
  136 + /**
102 * @remark :计算签名 137 * @remark :计算签名
103 * @name :generateSign 138 * @name :generateSign
104 * @author :lyh 139 * @author :lyh
@@ -312,4 +312,70 @@ class CosService @@ -312,4 +312,70 @@ class CosService
312 'HelveticaNeue.dfont' 312 'HelveticaNeue.dfont'
313 ]; 313 ];
314 } 314 }
  315 +
  316 + /**
  317 + * @remark :获取cos图片高度
  318 + * @name :getImageHeight
  319 + * @author :lyh
  320 + * @method :post
  321 + * @time :2025/5/8 10:58
  322 + * @param :pathUrl->存储桶相对路径
  323 + */
  324 + public function getImageHeight($pathUrl){
  325 + $cos = config('filesystems.disks.cos');
  326 + $url = 'https://' . $cos['bucket'] . '.cos.' . $cos['region'] . '.myqcloud.com/' . ltrim($pathUrl, '/') . '?image/info';
  327 + $imageInfo = @getimagesize($url);
  328 + if ($imageInfo) {
  329 +// $width = $imageInfo[0];
  330 + $height = $imageInfo[1];
  331 + return $height;
  332 + }
  333 + return '';
  334 + }
  335 +
  336 + /**
  337 + * @remark :裁剪图片
  338 + * @name :cropCosImage
  339 + * @author :lyh
  340 + * @method :post
  341 + * @time :2025/5/8 11:06
  342 + */
  343 + public function cropCosImage($cosUrl,$height = 220)
  344 + {
  345 + $cos = config('filesystems.disks.cos');
  346 + $cosClient = new Client([
  347 + 'region' => $cos['region'],
  348 + 'credentials' => [
  349 + 'secretId' => $cos['credentials']['secretId'],
  350 + 'secretKey' => $cos['credentials']['secretKey'],
  351 + ],
  352 + ]);
  353 + $pathInfo = pathinfo($cosUrl);
  354 + $newKey = $pathInfo['dirname'] . '/crop_' . $pathInfo['filename'] .'.'. $pathInfo['extension'];
  355 + $operations = [
  356 + 'is_pic_info' => 0,
  357 + 'rules' => [
  358 + [
  359 + // 注意 fileid 要 base64 编码,并与 Key 相同才能覆盖
  360 + 'fileid' => $newKey,
  361 + 'rule' => 'imageMogr2/crop/x'.$height.'/gravity/center'
  362 + ]
  363 + ]
  364 + ];
  365 + // 执行裁剪并覆盖
  366 + $res = $cosClient->ImageProcess([
  367 + 'Bucket' => $cos['bucket'],
  368 + 'Key' => $cosUrl, // 要处理的对象路径
  369 + 'PicOperations' => json_encode($operations),
  370 + ]);
  371 + if($res){
  372 + return [
  373 + 'path' => '/'.$res['ProcessResults']['Object'][0]['Key'] ?? '',
  374 + 'size' => (int)$res['ProcessResults']['Object'][0]['Size'] ?? 0,
  375 + 'mime' => 'image/'.($res['ProcessResults']['Object'][0]['Format'] ?? 'jpg'),
  376 + 'type' => $res['ProcessResults']['Object'][0]['Format'] ?? 'jpg',
  377 + ];
  378 + }
  379 + return [];
  380 + }
315 } 381 }
@@ -286,9 +286,9 @@ class SyncSubmitTaskService @@ -286,9 +286,9 @@ class SyncSubmitTaskService
286 //转化询盘 286 //转化询盘
287 Visit::isInquiry($data['ip']); 287 Visit::isInquiry($data['ip']);
288 288
289 - //推送企微消息 289 + //推送企微消息 测试域名不发
290 Log::channel('inquiry')->info($task_id . '询盘结果', [$id]); 290 Log::channel('inquiry')->info($task_id . '询盘结果', [$id]);
291 - if($id){ 291 + if($id && !Str::contains($data['domain'], 'globalso.site')){
292 try { 292 try {
293 $name = empty($data['data']['name']) ? '' : ' ' . $data['data']['name']; 293 $name = empty($data['data']['name']) ? '' : ' ' . $data['data']['name'];
294 MessagePush::addInquiryMessage($id, $data['project_id'], $data['country'], $name, $data['submit_at']); 294 MessagePush::addInquiryMessage($id, $data['project_id'], $data['country'], $name, $data['submit_at']);
@@ -18,7 +18,6 @@ @@ -18,7 +18,6 @@
18 "laravel/framework": "^8.75", 18 "laravel/framework": "^8.75",
19 "laravel/sanctum": "^2.11", 19 "laravel/sanctum": "^2.11",
20 "laravel/tinker": "^2.5", 20 "laravel/tinker": "^2.5",
21 - "mongodb/mongodb": "^1.6",  
22 "mrgoon/aliyun-sms": "^2.0", 21 "mrgoon/aliyun-sms": "^2.0",
23 "phpoffice/phpspreadsheet": "^1.28", 22 "phpoffice/phpspreadsheet": "^1.28",
24 "qcloud/cos-sdk-v5": "^v2.6.6", 23 "qcloud/cos-sdk-v5": "^v2.6.6",
1 -Options +FollowSymLinks -Indexes  
2 -RewriteEngine On  
3 -  
4 -RewriteCond %{HTTP:Authorization} .  
5 -RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]  
6 -  
7 -RewriteCond %{REQUEST_FILENAME} !-d  
8 -RewriteCond %{REQUEST_FILENAME} !-f  
9 -RewriteRule ^ index.php [L]  
@@ -24,6 +24,7 @@ Route::get('get_project_route', [\App\Http\Controllers\Api\PrivateController::cl @@ -24,6 +24,7 @@ Route::get('get_project_route', [\App\Http\Controllers\Api\PrivateController::cl
24 Route::any('get_product_images', [\App\Http\Controllers\Api\ProductController::class, 'getImages'])->name('api.get_product_images'); 24 Route::any('get_product_images', [\App\Http\Controllers\Api\ProductController::class, 'getImages'])->name('api.get_product_images');
25 Route::any('saveProduct', [\App\Http\Controllers\Api\ProductController::class, 'saveProduct'])->name('api.saveProduct'); 25 Route::any('saveProduct', [\App\Http\Controllers\Api\ProductController::class, 'saveProduct'])->name('api.saveProduct');
26 Route::any('searchProduct', [\App\Http\Controllers\Api\ProductController::class, 'searchProduct'])->name('api.searchProduct'); 26 Route::any('searchProduct', [\App\Http\Controllers\Api\ProductController::class, 'searchProduct'])->name('api.searchProduct');
  27 +Route::any('searchProductToAiBlog', [\App\Http\Controllers\Api\ProductController::class, 'searchProductToAiBlog'])->name('api.searchProductToAiBlog');
27 Route::post('inquiry_submit', [\App\Http\Controllers\Api\InquiryController::class, 'submit'])->name('api.inquiry_submit'); 28 Route::post('inquiry_submit', [\App\Http\Controllers\Api\InquiryController::class, 'submit'])->name('api.inquiry_submit');
28 Route::post('editInquiryStatus', [\App\Http\Controllers\Api\InquiryController::class, 'editInquiryStatus'])->name('api.inquiry_editInquiryStatus'); 29 Route::post('editInquiryStatus', [\App\Http\Controllers\Api\InquiryController::class, 'editInquiryStatus'])->name('api.inquiry_editInquiryStatus');
29 Route::any('get_inquiry_random_ip', [\App\Http\Controllers\Api\InquiryController::class, 'getRandomIp'])->name('api.inquiry_getRandomIp'); 30 Route::any('get_inquiry_random_ip', [\App\Http\Controllers\Api\InquiryController::class, 'getRandomIp'])->name('api.inquiry_getRandomIp');
@@ -70,5 +71,5 @@ Route::any('/addRedirect',[\App\Http\Controllers\Api\NoticeController::class,'ad @@ -70,5 +71,5 @@ Route::any('/addRedirect',[\App\Http\Controllers\Api\NoticeController::class,'ad
70 71
71 //关联域名 72 //关联域名
72 Route::post('/inquiry_relate_domain', [\App\Http\Controllers\Api\PrivateController::class, 'inquiry_relate_domain']); 73 Route::post('/inquiry_relate_domain', [\App\Http\Controllers\Api\PrivateController::class, 'inquiry_relate_domain']);
73 -  
74 - 74 +// 通过域名获取项目人员配置
  75 +Route::get('/get_manage_by_domain', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectManageByDomain']);
@@ -157,7 +157,10 @@ Route::middleware(['bloginauth'])->group(function () { @@ -157,7 +157,10 @@ Route::middleware(['bloginauth'])->group(function () {
157 Route::any('/', [\App\Http\Controllers\Bside\Ai\AiVideoController::class, 'lists'])->name('ai_video_lists'); 157 Route::any('/', [\App\Http\Controllers\Bside\Ai\AiVideoController::class, 'lists'])->name('ai_video_lists');
158 Route::any('/getInfo', [\App\Http\Controllers\Bside\Ai\AiVideoController::class, 'getInfo'])->name('ai_video_getInfo'); 158 Route::any('/getInfo', [\App\Http\Controllers\Bside\Ai\AiVideoController::class, 'getInfo'])->name('ai_video_getInfo');
159 Route::any('/sendTask', [\App\Http\Controllers\Bside\Ai\AiVideoController::class, 'sendTask'])->name('ai_video_sendTask'); 159 Route::any('/sendTask', [\App\Http\Controllers\Bside\Ai\AiVideoController::class, 'sendTask'])->name('ai_video_sendTask');
  160 + Route::any('/save', [\App\Http\Controllers\Bside\Ai\AiVideoController::class, 'save'])->name('ai_video_save');
160 Route::any('/del', [\App\Http\Controllers\Bside\Ai\AiVideoController::class, 'delete'])->name('ai_video_delete'); 161 Route::any('/del', [\App\Http\Controllers\Bside\Ai\AiVideoController::class, 'delete'])->name('ai_video_delete');
  162 + Route::any('/getAiVideoList', [\App\Http\Controllers\Bside\Ai\AiVideoController::class, 'getAiVideoList'])->name('ai_video_getAiVideoList');
  163 + Route::any('/getAiBlogListInfo', [\App\Http\Controllers\Bside\Ai\AiVideoController::class, 'getAiBlogListInfo'])->name('ai_video_getAiBlogListInfo');
161 }); 164 });
162 //ai 165 //ai
163 Route::any('/news/', [\App\Http\Controllers\Bside\Ai\AiNewsController::class, 'save'])->name('ai_news_save'); 166 Route::any('/news/', [\App\Http\Controllers\Bside\Ai\AiNewsController::class, 'save'])->name('ai_news_save');