作者 刘锟

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

@@ -2,10 +2,14 @@ @@ -2,10 +2,14 @@
2 2
3 namespace App\Console\Commands\AyrShare; 3 namespace App\Console\Commands\AyrShare;
4 use App\Helper\AyrShare as AyrShareHelper; 4 use App\Helper\AyrShare as AyrShareHelper;
  5 +use App\Models\Ai\AiVideo;
5 use App\Models\AyrShare\AyrRelease as AyrReleaseModel; 6 use App\Models\AyrShare\AyrRelease as AyrReleaseModel;
  7 +use App\Models\Project\AiVideoTask;
  8 +use App\Services\ProjectServer;
6 use Carbon\Carbon; 9 use Carbon\Carbon;
7 use App\Models\AyrShare\AyrShare as AyrShareModel; 10 use App\Models\AyrShare\AyrShare as AyrShareModel;
8 use Illuminate\Console\Command; 11 use Illuminate\Console\Command;
  12 +use Illuminate\Support\Facades\DB;
9 13
10 class ShareUser extends Command 14 class ShareUser extends Command
11 { 15 {
@@ -32,6 +36,7 @@ class ShareUser extends Command @@ -32,6 +36,7 @@ class ShareUser extends Command
32 public function handle() 36 public function handle()
33 { 37 {
34 echo $this->user_operator_record(); 38 echo $this->user_operator_record();
  39 + return true;
35 } 40 }
36 41
37 /** 42 /**
@@ -46,6 +51,7 @@ class ShareUser extends Command @@ -46,6 +51,7 @@ class ShareUser extends Command
46 $ayr_release = new AyrReleaseModel(); 51 $ayr_release = new AyrReleaseModel();
47 $ayr_share_list = $ayr_share_model->list(['profile_key'=>['!=','']]); 52 $ayr_share_list = $ayr_share_model->list(['profile_key'=>['!=','']]);
48 foreach ($ayr_share_list as $v){ 53 foreach ($ayr_share_list as $v){
  54 + echo date('Y-m-d H:i:s').'执行数据的邮箱--'.$v['title'].PHP_EOL;
49 $time = Carbon::now()->modify('-1 days')->toDateString(); 55 $time = Carbon::now()->modify('-1 days')->toDateString();
50 //创建时间小于7天前的当前时间 56 //创建时间小于7天前的当前时间
51 if($v['created_at'] > $time){ 57 if($v['created_at'] > $time){
@@ -60,15 +66,24 @@ class ShareUser extends Command @@ -60,15 +66,24 @@ class ShareUser extends Command
60 continue; 66 continue;
61 } 67 }
62 //查询7天是否发送博文 68 //查询7天是否发送博文
63 - $release_info = $this->release_seven_info($ayr_release); 69 + $release_info = $this->release_seven_info($ayr_release,$v);
64 //有发送博文,则跳出循环 70 //有发送博文,则跳出循环
65 if($release_info !== false){ 71 if($release_info !== false){
66 echo '7天内有推文跳过。'.date('Y-m-d H:i:s').PHP_EOL; 72 echo '7天内有推文跳过。'.date('Y-m-d H:i:s').PHP_EOL;
67 continue; 73 continue;
68 } 74 }
  75 + $aiVideoInfo = $this->aiVideoInfo($v['project_id'] ?? 0);
  76 + if($aiVideoInfo !== false){
  77 + echo '7天内有ai视频推送跳过。'.date('Y-m-d H:i:s').PHP_EOL;
  78 + continue;
  79 + }
69 //删除用户第三方配置 80 //删除用户第三方配置
70 if(!empty($v['profile_key'])){ 81 if(!empty($v['profile_key'])){
71 - $this->del_profiles($v); 82 + $res = $this->del_profiles($v);
  83 + if($res === false){
  84 + //删除失败-跳过
  85 + continue;
  86 + }
72 } 87 }
73 //更新数据库 88 //更新数据库
74 $this->save_ayr_share($ayr_share_model,$v); 89 $this->save_ayr_share($ayr_share_model,$v);
@@ -90,8 +105,8 @@ class ShareUser extends Command @@ -90,8 +105,8 @@ class ShareUser extends Command
90 ]; 105 ];
91 $res = $ayr_share_helper->deleted_profiles($data_profiles); 106 $res = $ayr_share_helper->deleted_profiles($data_profiles);
92 if($res['status'] == 'fail'){ 107 if($res['status'] == 'fail'){
93 - echo '第三方删除失败';  
94 - return true; 108 + echo '第三方删除失败'.json_encode($data_profiles,true);
  109 + return false;
95 } 110 }
96 return true; 111 return true;
97 } 112 }
@@ -138,11 +153,30 @@ class ShareUser extends Command @@ -138,11 +153,30 @@ class ShareUser extends Command
138 * @method :post 153 * @method :post
139 * @time :2023/6/14 16:28 154 * @time :2023/6/14 16:28
140 */ 155 */
141 - public function release_seven_info(&$ayr_release){ 156 + public function release_seven_info(&$ayr_release,$v){
142 //查看用户是否在一周内有发送博客 157 //查看用户是否在一周内有发送博客
143 $start_at = Carbon::now()->modify('-7 days')->toDateString(); 158 $start_at = Carbon::now()->modify('-7 days')->toDateString();
144 $end_at = Carbon::now()->toDateString(); 159 $end_at = Carbon::now()->toDateString();
145 - $release_info = $ayr_release->read(['created_at'=>['between',[$start_at,$end_at]]]); 160 + $release_info = $ayr_release->read(['created_at'=>['between',[$start_at,$end_at]],'share_id'=>$v['id']]);
146 return $release_info; 161 return $release_info;
147 } 162 }
  163 +
  164 + /**
  165 + * @remark :7天内是否推送了ai视频
  166 + * @name :aiVidoe
  167 + * @author :lyh
  168 + * @method :post
  169 + * @time :2025/9/22 17:13
  170 + */
  171 + public function aiVideoInfo($project_id)
  172 + {
  173 + if($project_id == 0){
  174 + return false;
  175 + }
  176 + $start_at = Carbon::now()->modify('-7 days')->toDateString();
  177 + $end_at = Carbon::now()->toDateString();
  178 + $aiVideoModel = new AiVideoTask();
  179 + $videoInfo = $aiVideoModel->read(['project_id'=>$project_id,'next_auto_date'=>null,'created_at'=>['between',[$start_at,$end_at]]]);
  180 + return $videoInfo;
  181 + }
148 } 182 }
@@ -17,6 +17,7 @@ use App\Models\Project\AggregateKeywordAffix; @@ -17,6 +17,7 @@ use App\Models\Project\AggregateKeywordAffix;
17 use App\Models\Project\AiBlogTask; 17 use App\Models\Project\AiBlogTask;
18 use App\Models\Project\DeployBuild; 18 use App\Models\Project\DeployBuild;
19 use App\Models\Project\KeywordPrefix; 19 use App\Models\Project\KeywordPrefix;
  20 +use App\Models\Project\Payment;
20 use App\Models\Project\Project; 21 use App\Models\Project\Project;
21 use App\Models\Project\ProjectAiSetting; 22 use App\Models\Project\ProjectAiSetting;
22 use App\Models\Project\ProjectWhiteHatAffix; 23 use App\Models\Project\ProjectWhiteHatAffix;
@@ -50,7 +51,17 @@ class lyhDemo extends Command @@ -50,7 +51,17 @@ class lyhDemo extends Command
50 protected $description = '更新路由'; 51 protected $description = '更新路由';
51 52
52 public function handle(){ 53 public function handle(){
53 - return $this->_actionRoute(); 54 + $projectModel = new Payment();
  55 + $lists = $projectModel->list(['renewal_record'=>['not like','"expire_at": null']]);
  56 + foreach ($lists as $item){
  57 + foreach ($item['renewal_record'] as $key => $val){
  58 + if(!isset($val['end_time']) && !empty($val['expire_at'])){
  59 + $val['end_time'] = $val['expire_at'];
  60 + }
  61 + $item['renewal_record'][$key] = $val;
  62 + }
  63 + $projectModel->edit(['renewal_record'=>json_encode($item['renewal_record'],true)],['id'=>$item['id']]);
  64 + }
54 return true; 65 return true;
55 } 66 }
56 67
@@ -1588,4 +1588,27 @@ if (!function_exists('httpGetSsl')) { @@ -1588,4 +1588,27 @@ if (!function_exists('httpGetSsl')) {
1588 $result = json_decode($res, true); 1588 $result = json_decode($res, true);
1589 return is_array($result) ? $result : $res; 1589 return is_array($result) ? $result : $res;
1590 } 1590 }
  1591 +
  1592 + /**
  1593 + * @remark :截取自付出啊
  1594 + * @name :truncate_words
  1595 + * @author :lyh
  1596 + * @method :post
  1597 + * @time :2025/9/22 14:46
  1598 + */
  1599 + function truncate_text($text, $limit = 300) {
  1600 + // 长度小于限制直接返回
  1601 + if (mb_strlen($text, 'UTF-8') <= $limit) {
  1602 + return $text;
  1603 + }
  1604 + // 先取前 $limit 个字符
  1605 + $truncated = mb_substr($text, 0, $limit, 'UTF-8');
  1606 + // 如果这一段包含空格(说明有英文单词),尽量在最后一个空格处截断
  1607 + $lastSpace = mb_strrpos($truncated, ' ', 0, 'UTF-8');
  1608 + if ($lastSpace !== false) {
  1609 + // 在最后一个空格处截断,避免英文单词被截断
  1610 + $truncated = mb_substr($truncated, 0, $lastSpace, 'UTF-8');
  1611 + }
  1612 + return $truncated;
  1613 + }
1591 } 1614 }
@@ -229,13 +229,11 @@ class AiBlogController extends BaseController @@ -229,13 +229,11 @@ class AiBlogController extends BaseController
229 'image'=>['required'], 229 'image'=>['required'],
230 'author_id'=>['required'], 230 'author_id'=>['required'],
231 'text'=>['required'], 231 'text'=>['required'],
232 - 'description'=>['required'],  
233 ],[ 232 ],[
234 'new_title.required' => '标题不能为空', 233 'new_title.required' => '标题不能为空',
235 'image.required' => '缩略图不能为空', 234 'image.required' => '缩略图不能为空',
236 'author_id.required' => '作者id不能为空', 235 'author_id.required' => '作者id不能为空',
237 - 'text.required' => '作者id不能为空',  
238 - 'description.required' => '短描述不能为空', 236 + 'text.required' => '内容不能为空',
239 ]); 237 ]);
240 $data = $aiBlogLogic->customSaveBlog($this->param); 238 $data = $aiBlogLogic->customSaveBlog($this->param);
241 $this->response('success',Code::SUCCESS,$data); 239 $this->response('success',Code::SUCCESS,$data);
@@ -182,6 +182,7 @@ class ProjectLogic extends BaseLogic @@ -182,6 +182,7 @@ class ProjectLogic extends BaseLogic
182 $this->setAiBlog($this->param['id'],$this->param['main_lang_id'],$this->param['is_ai_blog'] ?? 0, 182 $this->setAiBlog($this->param['id'],$this->param['main_lang_id'],$this->param['is_ai_blog'] ?? 0,
183 $this->param['company']??"", $this->param['deploy_optimize']['company_en_name'] ?? '', 183 $this->param['company']??"", $this->param['deploy_optimize']['company_en_name'] ?? '',
184 $this->param['deploy_optimize']['company_en_description'] ?? '',$this->param['is_ai_video'] ?? 0,$this->param['is_related_video'] ?? 0); 184 $this->param['deploy_optimize']['company_en_description'] ?? '',$this->param['is_ai_video'] ?? 0,$this->param['is_related_video'] ?? 0);
  185 + $this->param = $this->getPaymentRamainDay($this->param);
185 //保存项目信息 186 //保存项目信息
186 $this->saveProject($this->param); 187 $this->saveProject($this->param);
187 //保存建站部署信息 188 //保存建站部署信息
@@ -412,6 +413,53 @@ class ProjectLogic extends BaseLogic @@ -412,6 +413,53 @@ class ProjectLogic extends BaseLogic
412 } 413 }
413 414
414 /** 415 /**
  416 + * @remark :推广续费网站设置剩余服务时常
  417 + * @name :getPaymentRamainDay
  418 + * @author :lyh
  419 + * @method :post
  420 + * @time :2025/9/22 11:13
  421 + */
  422 + public function getPaymentRamainDay($param)
  423 + {
  424 + // 推广续费网站单独处理
  425 + if (in_array($param['type'] ,[2,3,4])) {
  426 + // 先找到 expire_at 不为 null 的记录
  427 + $validRecords = array_filter(
  428 + $param['payment']['renewal_record'] ?? [],
  429 + fn($item) => !is_null($item['expire_at'] ?? null)
  430 + );
  431 + $maxExpireAt = null;
  432 + if ($validRecords) {
  433 + // 取出最大日期
  434 + $maxExpireAt = max(array_column($validRecords, 'expire_at'));
  435 + }
  436 + if (!$maxExpireAt) {
  437 + return $this->success($param);
  438 + }
  439 + // 遍历原始 renewal_record(用引用,方便写回)
  440 + foreach ($param['payment']['renewal_record'] as &$record) {
  441 + if (!is_null($record['expire_at'] ?? null) && $record['expire_at'] === $maxExpireAt) {
  442 + // 如果 end_time 不存在或与 expire_at 不一致,则更新
  443 + if (!isset($record['end_time']) || $record['end_time'] != $record['expire_at']) {
  444 + $record['end_time'] = $record['expire_at']; // ✅ 写回原数据
  445 + // 重新计算剩余天数
  446 + $diff = (strtotime($record['expire_at']) - strtotime(date('Y-m-d'))) / (60 * 60 * 24);
  447 + if ($param['project_type'] == Project::PROJECT_TYPE_SEO) {
  448 + $param['deploy_build']['seo_service_duration'] = $diff + $param['deploy_build']['seo_service_duration'];
  449 + } else {
  450 + $param['deploy_build']['service_duration'] = $diff + $param['deploy_build']['service_duration'];
  451 + }
  452 + }
  453 + break; // 找到后跳出循环
  454 + }
  455 + }
  456 + unset($record); // 释放引用
  457 + }
  458 + return $this->success($param);
  459 + }
  460 +
  461 +
  462 + /**
415 * @remark :保存项目 463 * @remark :保存项目
416 * @name :setExtendType 464 * @name :setExtendType
417 * @author :lyh 465 * @author :lyh
@@ -751,24 +799,6 @@ class ProjectLogic extends BaseLogic @@ -751,24 +799,6 @@ class ProjectLogic extends BaseLogic
751 //改为异步 799 //改为异步
752 NoticeLog::createLog(NoticeLog::TYPE_INIT_PROJECT, ['project_id' => $param['id']]); 800 NoticeLog::createLog(NoticeLog::TYPE_INIT_PROJECT, ['project_id' => $param['id']]);
753 } 801 }
754 - //推广续费网站单独处理  
755 - if($param['type'] == Project::TYPE_FOUR){  
756 - // 提取非 null 的 expire_at 字段  
757 - $validDates = array_filter(  
758 - array_column($param['payment']['renewal_record'] ?? [], 'expire_at'),  
759 - fn($date) => !is_null($date)  
760 - );  
761 - // 获取最大日期(如果有)  
762 - $maxExpireAt = $validDates ? max($validDates) : null;  
763 - if(!empty($maxExpireAt)){  
764 - $diff = (strtotime($maxExpireAt) - strtotime($param['uptime'] ?? date('Y-m-d'))) / (60 * 60 * 24);  
765 - if($param['project_type'] == Project::PROJECT_TYPE_SEO){  
766 - $param['deploy_build']['seo_service_duration'] = $diff;  
767 - }else{  
768 - $param['deploy_build']['service_duration'] = $diff;  
769 - }  
770 - }  
771 - }  
772 return $this->success($param); 802 return $this->success($param);
773 } 803 }
774 804
@@ -179,6 +179,9 @@ class AiBlogLogic extends BaseLogic @@ -179,6 +179,9 @@ class AiBlogLogic extends BaseLogic
179 'title'=>$param['new_title'], 'thumb'=>$param['image'], 'foreword'=>$param['description'] ?? '', 179 'title'=>$param['new_title'], 'thumb'=>$param['image'], 'foreword'=>$param['description'] ?? '',
180 'author_id'=>$this->param['author_id'], 'url'=>$param['route'], 180 'author_id'=>$this->param['author_id'], 'url'=>$param['route'],
181 ]; 181 ];
  182 + if(!isset($param['description']) || empty($param['description'])){
  183 + $param['description'] = truncate_text($param['text']);
  184 + }
182 if(isset($param['id']) && !empty($param['id'])){ 185 if(isset($param['id']) && !empty($param['id'])){
183 $id = $param['id']; 186 $id = $param['id'];
184 $data['task_id'] = $param['task_id']; 187 $data['task_id'] = $param['task_id'];
@@ -196,13 +199,6 @@ class AiBlogLogic extends BaseLogic @@ -196,13 +199,6 @@ class AiBlogLogic extends BaseLogic
196 $text1 = Common::deal_str($text1); 199 $text1 = Common::deal_str($text1);
197 $param['seo_keyword'] = $text1; 200 $param['seo_keyword'] = $text1;
198 } 201 }
199 - if(!isset($param['description']) || empty($param['description'])){  
200 - $ai = "According to the keyword {$param['title']}, write a seo meta description show to purchaser within 100 characters";  
201 - $text2 = Gpt::instance()->openai_chat_qqs($ai);  
202 - $text2 = Common::deal_keywords($text2);  
203 - $text2 = Common::deal_str($text2);  
204 - $param['description'] = $text2;  
205 - }  
206 $param['route'] = RouteMap::setRoute($param['route'], RouteMap::SOURCE_AI_BLOG, $id, $this->user['project_id']); 202 $param['route'] = RouteMap::setRoute($param['route'], RouteMap::SOURCE_AI_BLOG, $id, $this->user['project_id']);
207 $this->model->edit($param,['id'=>$param['id']]); 203 $this->model->edit($param,['id'=>$param['id']]);
208 }else{ 204 }else{