作者 ZhengBing He

del

要显示太多修改。

为保证性能只显示 35 of 35+ 个文件。

1 -root = true  
2 -  
3 -[*]  
4 -charset = utf-8  
5 -end_of_line = lf  
6 -insert_final_newline = true  
7 -indent_style = space  
8 -indent_size = 4  
9 -trim_trailing_whitespace = true  
10 -  
11 -[*.md]  
12 -trim_trailing_whitespace = false  
13 -  
14 -[*.{yml,yaml}]  
15 -indent_size = 2  
16 -  
17 -[docker-compose.yml]  
18 -indent_size = 4  
1 -APP_NAME=Laravel  
2 -APP_ENV=development  
3 -APP_KEY=base64:+ouoKlz2sFDOisnROMRpxT/u9xkZJVrXlzP4cfTqPow=  
4 -APP_DEBUG=false  
5 -APP_URL=http://localhost  
6 -  
7 -LOG_CHANNEL=stack  
8 -LOG_DEPRECATIONS_CHANNEL=null  
9 -LOG_LEVEL=debug  
10 -  
11 -DB_CONNECTION=mysql  
12 -DB_HOST=127.0.0.1  
13 -DB_PORT=3306F  
14 -DB_DATABASE=globalso  
15 -DB_USERNAME=debian-sys-maint  
16 -DB_PASSWORD=WtujxV73XIclQet0  
17 -  
18 -BROADCAST_DRIVER=log  
19 -CACHE_DRIVER=file  
20 -FILESYSTEM_DRIVER=local  
21 -QUEUE_CONNECTION=sync  
22 -SESSION_DRIVER=file  
23 -SESSION_LIFETIME=120  
24 -  
25 -MEMCACHED_HOST=127.0.0.1  
26 -  
27 -REDIS_HOST=127.0.0.1  
28 -REDIS_PASSWORD=null  
29 -REDIS_PORT=6379  
30 -  
31 -MAIL_MAILER=smtp  
32 -MAIL_HOST=mailhog  
33 -MAIL_PORT=1025  
34 -MAIL_USERNAME=null  
35 -MAIL_PASSWORD=null  
36 -MAIL_ENCRYPTION=null  
37 -MAIL_FROM_ADDRESS=null  
38 -MAIL_FROM_NAME="${APP_NAME}"  
39 -  
40 -AWS_ACCESS_KEY_ID=  
41 -AWS_SECRET_ACCESS_KEY=  
42 -AWS_DEFAULT_REGION=us-east-1  
43 -AWS_BUCKET=  
44 -AWS_USE_PATH_STYLE_ENDPOINT=false  
45 -  
46 -PUSHER_APP_ID=  
47 -PUSHER_APP_KEY=  
48 -PUSHER_APP_SECRET=  
49 -PUSHER_APP_CLUSTER=mt1  
50 -  
51 -MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"  
52 -MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"  
1 -APP_NAME=Laravel  
2 -APP_ENV=local  
3 -APP_KEY=base64:+ouoKlz2sFDOisnROMRpxT/u9xkZJVrXlzP4cfTqPow=  
4 -APP_DEBUG=false  
5 -APP_URL=http://localhost  
6 -  
7 -LOG_CHANNEL=stack  
8 -LOG_DEPRECATIONS_CHANNEL=null  
9 -LOG_LEVEL=debug  
10 -  
11 -DB_CONNECTION=mysql  
12 -DB_HOST=127.0.0.1  
13 -DB_PORT=3306  
14 -DB_DATABASE=globalso  
15 -DB_USERNAME=debian-sys-maint  
16 -DB_PASSWORD=WtujxV73XIclQet0  
17 -  
18 -BROADCAST_DRIVER=log  
19 -CACHE_DRIVER=file  
20 -FILESYSTEM_DRIVER=local  
21 -QUEUE_CONNECTION=sync  
22 -SESSION_DRIVER=file  
23 -SESSION_LIFETIME=120  
24 -  
25 -MEMCACHED_HOST=127.0.0.1  
26 -  
27 -REDIS_HOST=127.0.0.1  
28 -REDIS_PASSWORD=null  
29 -REDIS_PORT=6379  
30 -  
31 -MAIL_MAILER=smtp  
32 -MAIL_HOST=mailhog  
33 -MAIL_PORT=1025  
34 -MAIL_USERNAME=null  
35 -MAIL_PASSWORD=null  
36 -MAIL_ENCRYPTION=null  
37 -MAIL_FROM_ADDRESS=null  
38 -MAIL_FROM_NAME="${APP_NAME}"  
39 -  
40 -AWS_ACCESS_KEY_ID=  
41 -AWS_SECRET_ACCESS_KEY=  
42 -AWS_DEFAULT_REGION=us-east-1  
43 -AWS_BUCKET=  
44 -AWS_USE_PATH_STYLE_ENDPOINT=false  
45 -  
46 -PUSHER_APP_ID=  
47 -PUSHER_APP_KEY=  
48 -PUSHER_APP_SECRET=  
49 -PUSHER_APP_CLUSTER=mt1  
50 -  
51 -MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"  
52 -MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"  
1 -* text=auto  
2 -  
3 -*.blade.php diff=html  
4 -*.css diff=css  
5 -*.html diff=html  
6 -*.md diff=markdown  
7 -*.php diff=php  
8 -  
9 -/.github export-ignore  
10 -CHANGELOG.md export-ignore  
1 -/node_modules  
2 -/public/hot  
3 -/public/storage  
4 -/public/.user.ini  
5 -/storage  
6 -/vendor  
7 -/uploads  
8 -composer.lock  
9 -.env  
10 -.env.backup  
11 -.phpunit.result.cache  
12 -docker-compose.override.yml  
13 -Homestead.json  
14 -Homestead.yaml  
15 -npm-debug.log  
16 -yarn-error.log  
17 -/.idea  
18 -/.vscode  
19 -composer.lock  
20 -app/Console/Commands/Test/DataRecovery.php  
21 -/public/upload  
22 -/public/runtime  
23 -public/nginx.htaccess  
24 -public/.htaccess  
25 -.gitignore  
1 -php:  
2 - preset: laravel  
3 - version: 8  
4 - disabled:  
5 - - no_unused_imports  
6 - finder:  
7 - not-name:  
8 - - index.php  
9 - - server.php  
10 -js:  
11 - finder:  
12 - not-name:  
13 - - webpack.mix.js  
14 -css: true  
1 -<html>  
2 -<head><title>404 Not Found</title></head>  
3 -<body>  
4 -<center><h1>404 Not Found</h1></center>  
5 -<hr><center>nginx</center>  
6 -</body>  
7 -</html>  
1 -# 基础框架 - 后端管理系统  
2 -## 路由  
3 -### 路由提供者Provider中预定义两个路由  
4 -- bside 代表B端用户访问路由 完整路由:{{url}}/a/xxx  
5 -- aside 代表管理员访问路由 完整路由:{{url}}/b/xxx  
6 -  
7 -## 枚举  
8 -### 使用插件bensampo/laravel-enum 版本4 github地址:https://github.com/BenSampo/laravel-enum/blob/v4.2.0/README.md  
9 -- 创建枚举类 : php artisan make:enum ”文件名“  
10 -- 给枚举类生成注释: php artisan enum:annotate "文件名"  
11 -- 如有翻译本地化需求,在 resources/lang/zh-CN/enums.php文件中中文翻译,英文语言包不用写,会自动翻译键名  
12 -- 在验证器中使用 : '参数名' => ['required ', new EnumValue(CaptchaType::class)],(或者按照键名new EnumKey)  
13 -- 可参考Enums/Common/Common.php枚举类  
14 -  
15 -## 状态码  
16 -- 该系统所有状态码都定义在 App\Enums\Commom\Code枚举类中  
17 -- 大大类 和 大类不能变动 ,以大类为基准步长为100,根据业务自定义状态码  
18 -  
19 -## 中间件  
20 -- 登录验证中间件 ”loginauth“  
21 -- Bside路由默认已经使用的中间件组为bside  
22 -- Aside路由默认已经使用的中间件组为aside  
23 -  
24 -## 参数加密  
25 -- .env文件中有三个配置,其中iv必须是八位  
26 -- 参数加密不开启的时候,前端正常传入参数,是明文不安全  
27 -  
28 -  
29 -## 控制器  
30 -- 各个端控制器目录:App\Http\Controllers\XXXside  
31 -- BaseController基础控制器,需要被其他控制器继承  
32 -- 控制器中只需要干三件事情:  
33 - 第一,验证参数(如果注入了自定义验证Request就可以省略$request->validate这一步)  
34 - 第二,调用逻辑层Logic  
35 - 第三,success返回---错误直接走异常处理  
36 -  
37 -## 请求and响应  
38 -- 控制器方法注入请求Illuminate\Http\Request或者注入自定义请求表单  
39 -- 创建请求表单: php artisan make:request 文件名  
40 -- 请求表单中定义,用户是否有权限请求以及参数验证规则  
41 -- 控制器中调用request->validated()  
42 -- 响应只能调用BaseController的success()方法  
43 -> 注意!全站返回不能编写自定义的message,只能通过Code码  
44 -  
45 -## 逻辑层  
46 -- App\Http\Logic逻辑层只能被控制器调用  
47 -- 要继承基类BaseLogic,return 使用基类定义的方法  
48 -## 错误截获  
49 -- 自定义某端全局异常:App\Exceptions\XXXsideGlobalException,throw new XXXsideGlobalException($code); 注意也只能传入Code码  
50 -  
51 -> 注意!.env文件APP_DEBUG控制是否显示详细错误信息,否则就按照本地化的错误码的message来显示  
52 -  
53 -## 日志规范  
54 -- 配置文件logging.php中预定义了B端错误日志bside  
55 -- 日志格式:logs -> bside(端)-> 2022-06(年月)-> 日期_级别.log (预定义了两个级别 errors和info)  
56 -- errors错误日志会在异常抛出的时候自动记录,info手动调用  
57 -- 共工具类App\Utils\LogUtils 提供了两个方法errorBside,infoBside记录日志  
58 -  
59 -## 数据迁移  
60 -- 每个版本的迭代如有数据结构修改,必须写到数据迁移里面  
61 -- 创建迁移 :php artisan make:migration create_users_table --create=users 或者 php artisan make:migration  
62 - add_votes_to_users_table --table=users (--create是创建表 --table是编辑表)  
63 -- 编写迁移脚本  
64 -- 执行迁移: php artisan migrate  
65 -  
66 -## 数据填充  
67 -- 每个版本的迭代如有数据预设置,必须写到数据填充里面  
68 -- 创建填充 : php artisan make:seeder 文件名  
69 -- 如果是简单的直接在seeder文件的run()方法中写insert  
70 -- 如果较复杂需要编写模型工厂:php artisan make:factory UserFactory  
71 -- 执行填充 : composer dump-autoload (用来重新生成composer映射) ,php artisan db:seed  
72 -  
73 -## Redis  
74 -- 配置文件database.php中的redis  
75 -- 所有使用到的键名需要在枚举类中定义:App\Enums\Common\RedisKey  
76 -- 工具类App\Utils\RedisUtils中提供了获取redis实例的方法  
77 -- traits文件App\Traits\RedisTraits中,定义了常用的redis方法,使用的时候只需要: use RedisTrait;  
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :AiBlogAuthorId.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2025/5/26 15:57  
8 - */  
9 -  
10 -namespace App\Console\Commands\Ai;  
11 -  
12 -use App\Helper\Arr;  
13 -use App\Models\Com\Notify;  
14 -use App\Models\Devops\ServerConfig;  
15 -use App\Models\Devops\ServersIp;  
16 -use App\Models\Domain\DomainInfo;  
17 -use App\Models\Project\AiBlogTask as AiBlogTaskModel;  
18 -use App\Models\Ai\AiBlogAuthor as AiBlogAuthorModel;  
19 -use App\Models\Project\Project;  
20 -use App\Services\AiBlogService;  
21 -use App\Services\ProjectServer;  
22 -use Illuminate\Console\Command;  
23 -use Illuminate\Support\Facades\DB;  
24 -use Illuminate\Support\Facades\Redis;  
25 -  
26 -class AiBlogAuthorId extends Command  
27 -{  
28 - /**  
29 - * The name and signature of the console command.  
30 - *  
31 - * @var string  
32 - */  
33 - protected $signature = 'save_ai_blog_author_id';  
34 -  
35 - /**  
36 - * The console command description.  
37 - *  
38 - * @var string  
39 - */  
40 - protected $description = '拉取对应作者的页面';  
41 -  
42 - public $route = [];  
43 -  
44 - public function handle(){  
45 - while (true){  
46 - //获取任务id  
47 - $task_id = $this->getTaskId();  
48 - if(empty($task_id)){  
49 - sleep(300);  
50 - continue;  
51 - }  
52 - $this->_action($task_id);  
53 - }  
54 - }  
55 -  
56 - public function getTaskId()  
57 - {  
58 - $task_id = Redis::rpop('ai_blog_author_id');  
59 - if (empty($task_id)) {  
60 - $aiBlogTaskModel = new AiBlogTaskModel();  
61 - $ids = $aiBlogTaskModel->formatQuery(['status'=>$aiBlogTaskModel::STATUS_RUNNING, 'type'=>$aiBlogTaskModel::TYPE_AUTHOR_ID])->pluck('id');  
62 - if(!empty($ids)){  
63 - foreach ($ids as $id) {  
64 - Redis::lpush('ai_blog_author_id', $id);  
65 - }  
66 - }  
67 - $task_id = Redis::rpop('ai_blog_author_id');  
68 - }  
69 - return $task_id;  
70 - }  
71 -  
72 - /**  
73 - * @remark :执行方法  
74 - * @name :_action  
75 - * @author :lyh  
76 - * @method :post  
77 - * @time :2025/5/26 16:06  
78 - */  
79 - public function _action($task_id){  
80 - $aiBlogTaskModel = new AiBlogTaskModel();  
81 - $item = $aiBlogTaskModel->read(['id'=>$task_id]);  
82 - if($item === false){  
83 - echo '当前数据不存在.'.$item['id'].PHP_EOL;  
84 - return true;  
85 - }  
86 - $aiBlogService = new AiBlogService($item['project_id']);  
87 - ProjectServer::useProject($item['project_id']);  
88 - $aiBlogService->author_id = $item['task_id'];  
89 - $result = $aiBlogService->getAuthorDetail();  
90 - if(isset($result['status']) && $result['status'] == 200){  
91 - //当前作者的页面  
92 - $aiBlogAuthorModel = new AiBlogAuthorModel();  
93 - $authorInfo = $aiBlogAuthorModel->read(['author_id'=>$item['task_id']],['id','route']);  
94 - if($authorInfo !== false && !empty($result['data']['section'])){  
95 - $this->route[] = $authorInfo['route'];  
96 - $aiBlogAuthorModel->edit(['text'=>$result['data']['section']],['author_id'=>$item['task_id']]);  
97 - }  
98 - }  
99 - DB::disconnect('custom_mysql');  
100 - $aiBlogTaskModel->edit(['status'=>2],['id'=>$task_id]);  
101 - $this->sendCPost($item['project_id']);  
102 - return true;  
103 - }  
104 -  
105 - /**  
106 - * @remark :通知C端  
107 - * @name :sendCPost  
108 - * @author :lyh  
109 - * @method :post  
110 - * @time :2025/5/26 16:21  
111 - */  
112 - public function sendCPost($project_id){  
113 - //获取项目所在服务器  
114 - $project_model = new Project();  
115 - $project_info = $project_model->read(['id'=>$project_id],['serve_id','is_upgrade', 'main_lang_id']);  
116 - if(!$project_info){  
117 - return false;  
118 - }  
119 - $serve_ip_model = new ServersIp();  
120 - $serve_ip_info = $serve_ip_model->read(['id'=>$project_info['serve_id']],['servers_id']);  
121 - $servers_id = $serve_ip_info ? $serve_ip_info['servers_id'] : 0;  
122 - if($servers_id == ServerConfig::SELF_SITE_ID){  
123 - //自建站服务器:如果项目已经上线,不请求C端接口,数据直接入库  
124 - $domain_model = new DomainInfo();  
125 - $domain_info = $domain_model->read(['project_id'=>$project_id],['domain']);  
126 - if($domain_info){  
127 - //判断是否已有更新进行中  
128 - $notify_model = new Notify();  
129 - $data = [  
130 - 'project_id' => $project_id,  
131 - 'type' => 1,  
132 - 'route' => 3,  
133 - 'server_id' => ServerConfig::SELF_SITE_ID,  
134 - 'status' => ['!=',Notify::STATUS_FINISH_SITEMAP]  
135 - ];  
136 - $notify = $notify_model->read($data,['id']);  
137 - if(!$notify){  
138 - $domain = $domain_info['domain'];  
139 - $data['data'] = Arr::a2s(['domain'=>$domain,'url'=>$this->route,'language'=>[]]);  
140 - $data['status'] = Notify::STATUS_INIT;  
141 - $data['is_pull_html_zip'] = Notify::IS_PULL_HTML_ZIP_FALSE;  
142 - $data['sort'] = 1;  
143 - $notify_model->add($data);  
144 - }  
145 - }  
146 - }else{  
147 - $domainModel = new DomainInfo();  
148 - $domain = $domainModel->getProjectIdDomain($project_id);  
149 - $c_url = $domain.'api/update_page/';  
150 - $param = [  
151 - 'project_id' => $project_id,  
152 - 'type' => 1,  
153 - 'route' => 3,  
154 - 'url' => $this->route,  
155 - 'language'=> [],  
156 - 'is_sitemap' => 0  
157 - ];  
158 - $res = http_post($c_url, json_encode($param,true));  
159 - echo 'notify: project id: ' . $project_id . ', result: ' . json_encode($res,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);  
160 - }  
161 - }  
162 -}  
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :AiBlogAuthorTask.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2025/2/21 11:12  
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\Project\AiBlogTask as AiBlogTaskModel;  
15 -use App\Models\Project\ProjectAiSetting;  
16 -use App\Models\RouteMap\RouteMap;  
17 -use App\Services\AiBlogService;  
18 -use App\Services\ProjectServer;  
19 -use Illuminate\Console\Command;  
20 -use Illuminate\Support\Facades\Cache;  
21 -use Illuminate\Support\Facades\DB;  
22 -  
23 -class AiBlogAuthorTask extends Command  
24 -{  
25 - /**  
26 - * The name and signature of the console command.  
27 - *  
28 - * @var string  
29 - */  
30 - protected $signature = 'save_ai_blog_author';  
31 -  
32 - /**  
33 - * The console command description.  
34 - *  
35 - * @var string  
36 - */  
37 - protected $description = '查询ai_blog_author是否已经生成';  
38 -  
39 -  
40 - /**  
41 - * @remark :获取作者  
42 - * @name :handle  
43 - * @author :lyh  
44 - * @method :post  
45 - * @time :2025/2/21 11:30  
46 - */  
47 - public function handle(){  
48 - $aiBlogTaskModel = new AiBlogTaskModel();  
49 - while (true){  
50 - $info = $aiBlogTaskModel->where('status',1)->where('type',1)->inRandomOrder()->first();  
51 - if(empty($info)){  
52 - sleep(300);  
53 - continue;  
54 - }  
55 - $info = $info->toArray();  
56 - echo date('Y-m-d H:i:s').'开始->project_id:' . $info['project_id'] . PHP_EOL;  
57 - //获取配置  
58 - $aiSettingInfo = $this->getSetting($info['project_id']);  
59 - if(empty($aiSettingInfo)){  
60 - continue;  
61 - }  
62 - $aiBlogService = new AiBlogService();  
63 - $aiBlogService->mch_id = $aiSettingInfo['mch_id'];  
64 - $aiBlogService->key = $aiSettingInfo['key'];  
65 - $result = $aiBlogService->getAuthor();  
66 - if(!isset($result['status'])){  
67 - echo '错误:'.json_encode($result,true);  
68 - continue;  
69 - }  
70 - if($result['status'] != 200){  
71 - sleep(10);  
72 - continue;  
73 - }  
74 - if(empty($result['data'])){  
75 - echo '没有作者任务-'.PHP_EOL;  
76 - continue;  
77 - }  
78 - //保存当前项目ai_blog数据  
79 - ProjectServer::useProject($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']);//写一条列表页路由  
82 - RouteMap::setRoute('top-video',RouteMap::SOURCE_AI_VIDEO_LIST,0,$info['project_id']);//写一条列表页路由  
83 - DB::disconnect('custom_mysql');  
84 - //修改任务状态  
85 - $aiBlogTaskModel->edit(['status'=>2],['id'=>$info['id']]);  
86 - echo date('Y-m-d H:i:s').'结束->任务id:' . $info['id'] . PHP_EOL;  
87 - }  
88 - return true;  
89 - }  
90 -  
91 -  
92 - /**  
93 - * @remark :获取项目配置  
94 - * @name :getSetting  
95 - * @author :lyh  
96 - * @method :post  
97 - * @time :2025/2/14 11:27  
98 - */  
99 - public function getSetting($project_id){  
100 - $ai_cache = Cache::get('ai_blog_'.$project_id);  
101 - if($ai_cache){  
102 - return $ai_cache;  
103 - }  
104 - $projectAiSettingModel = new ProjectAiSetting();  
105 - $aiSettingInfo = $projectAiSettingModel->read(['project_id'=>$project_id]);  
106 - Cache::put('ai_blog_'.$project_id,$aiSettingInfo,3600);  
107 - return $aiSettingInfo;  
108 - }  
109 -  
110 - /**  
111 - * @remark :保存数据  
112 - * @name :saveAiBlogAuthor  
113 - * @author :lyh  
114 - * @method :post  
115 - * @time :2025/2/21 11:36  
116 - */  
117 - public function saveAiBlogAuthor($data,$project_id){  
118 - if(empty($data)){  
119 - return true;  
120 - }  
121 - $aiBlogAuthorModel = new AiBlogAuthor();  
122 - foreach ($data as $v){  
123 - $param = [  
124 - 'author_id'=>$v['id'],  
125 - 'title'=>$v['title'],  
126 - 'image'=>str_replace_url($v['picture']),  
127 - 'description'=>$v['description'],  
128 - ];  
129 - //查询当前数据是否存在  
130 - $info = $aiBlogAuthorModel->read(['author_id'=>$v['id']]);  
131 - try {  
132 - if($info === false){  
133 - echo '执行新增'.PHP_EOL;  
134 - $id = $aiBlogAuthorModel->addReturnId($param);  
135 - $param['route'] = RouteMap::setRoute($v['route'] ?? $v['title'], RouteMap::SOURCE_AI_BLOG_AUTHOR, $id, $project_id);  
136 - $aiBlogAuthorModel->edit(['route'=>$param['route']],['id'=>$id]);  
137 - }else{  
138 - $param['route'] = RouteMap::setRoute($v['route'] ?? $v['title'], RouteMap::SOURCE_AI_BLOG_AUTHOR, $info['id'], $project_id);  
139 - $aiBlogAuthorModel->edit($param,['id'=>$info['id']]);  
140 - echo '执行更新'.PHP_EOL;  
141 - }  
142 - $aiSettingInfo = $this->getSetting($project_id);  
143 - $aiBlogService = new AiBlogService();  
144 - $aiBlogService->mch_id = $aiSettingInfo['mch_id'];  
145 - $aiBlogService->key = $aiSettingInfo['key'];  
146 - $aiBlogService->updateAuthorInfo(['author_id'=>$param['author_id'],'route'=>$param['route'],'title'=>$param['title'],'picture'=>$param['image'],'description'=>$param['description']]);  
147 - }catch (\Exception $e){  
148 - echo 'error:'.$e->getMessage().PHP_EOL;  
149 - continue;  
150 - }  
151 - }  
152 - return true;  
153 - }  
154 -}  
1 -<?php  
2 -  
3 -namespace App\Console\Commands\Ai;  
4 -  
5 -use App\Http\Logic\Aside\Project\ProjectLogic;  
6 -use App\Models\Ai\AiBlog;  
7 -use App\Models\Ai\AiBlogKeyword;  
8 -use App\Models\Ai\AiBlogOpenLog;  
9 -use App\Models\Project\AiBlogTask as AiBlogTaskModel;  
10 -use App\Models\Project\Project;  
11 -use App\Models\Project\ProjectKeyword;  
12 -use App\Models\RankData\RankData;  
13 -use App\Models\WebSetting\WebSetting;  
14 -use App\Services\AiBlogService;  
15 -use App\Services\DingService;  
16 -use App\Services\ProjectServer;  
17 -use Illuminate\Console\Command;  
18 -use Illuminate\Support\Facades\DB;  
19 -use Illuminate\Support\Facades\Log;  
20 -  
21 -/**  
22 - * 自动发布AI博客任务  
23 - * Class AiBlogAutoPublish  
24 - * @package App\Console\Commands\Ai  
25 - * @author zbj  
26 - * @date 2025/3/6  
27 - */  
28 -class AiBlogAutoPublish extends Command  
29 -{  
30 - /**  
31 - * The name and signature of the console command.  
32 - *  
33 - * @var string  
34 - */  
35 - protected $signature = 'ai_blog_auto_publish {action}';  
36 -  
37 - /**  
38 - * The console command description.  
39 - *  
40 - * @var string  
41 - */  
42 - protected $description = '自动发布AI Blog';  
43 -  
44 -  
45 - /**  
46 - * @return bool  
47 - * @author zbj  
48 - * @date 2025/3/6  
49 - */  
50 - public function handle()  
51 - {  
52 - $action = $this->argument('action');  
53 - if($action == 'auto_publish'){  
54 - $this->auto_publish();  
55 - }  
56 - if($action == 'auto_open'){  
57 - $this->auto_open();  
58 - }  
59 - }  
60 -  
61 - public function auto_publish()  
62 - {  
63 - $this->output('开始自动发布博客文章');  
64 - $projects = Project::where('is_ai_blog', 1)->whereIn('type',[1,2,3,4,6])->where('delete_status',0)->where('site_status',0)->where('extend_type',0)->get();  
65 - foreach ($projects as $project) {  
66 - try {  
67 - $this->output("项目{$project->id}开始自动发布");  
68 - if(!$project->deploy_optimize['is_ai_blog_send']){  
69 - $this->output("项目{$project->id}未开启自动发布" . $project->deploy_optimize['start_date']);  
70 - continue;  
71 - }  
72 - if(($project->deploy_optimize['start_date'] > date('Y-m-d')) || !$project->deploy_optimize['start_date']){  
73 - $this->output("项目{$project->id}未到推广时间" . $project->deploy_optimize['start_date']);  
74 - continue;  
75 - }  
76 - $next_auto_date = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->whereNotNull('next_auto_date')->orderBy('id', 'desc')->value('next_auto_date');  
77 - if($next_auto_date && $next_auto_date > date('Y-m-d')){  
78 - $this->output("项目{$project->id}未到执行时间" . $next_auto_date);  
79 - continue;  
80 - }  
81 - $aiKeywordModel = new AiBlogKeyword();  
82 - $keywords = $aiKeywordModel->getValue(['project_id'=>$project->id],'keywords');  
83 - if(empty($keywords)){  
84 - //核心关键词+网站关键词+白帽关键词  
85 - $main_keywords = ProjectKeyword::where('project_id', $project->id)->value('main_keyword');  
86 - $main_keywords = explode("\r\n", $main_keywords);  
87 - $seo_keywords = ProjectKeyword::where('project_id', $project->id)->value('seo_keywords');  
88 - $seo_keywords = explode("\r\n", $seo_keywords);  
89 - ProjectServer::useProject($project->id);  
90 - $site_keywords = WebSetting::where('project_id', $project->id)->value('keyword');  
91 - DB::disconnect('custom_mysql');  
92 - $site_keywords = explode(",", $site_keywords);  
93 - $keywords = array_filter(array_merge($main_keywords, $site_keywords, $seo_keywords));  
94 - $keywords = array_map('trim', $keywords);  
95 - }else{  
96 - $keywords = explode("\r\n", $keywords);  
97 - $keywords = array_map('trim', $keywords); // 清理空格  
98 - $keywords = array_filter($keywords); // 移除空值  
99 - }  
100 - if (empty($keywords)) {  
101 - $this->output("项目{$project->id}未获取到关键词");  
102 - continue;  
103 - }  
104 - $last_task = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->orderBy('id', 'desc')->first();  
105 - $compliance = RankData::where(['project_id' => $project->id, 'lang' => ''])->value('is_compliance');  
106 - $frequency = Project::typeBlogFrequency($project->deploy_optimize->send_ai_blog_frequency);  
107 - $frequency = explode('-', $frequency);  
108 - //1、之前测试那批项目,按照正常频率发送;  
109 - //2、未达标的项目,开启AIblog, 并立即推送三篇;  
110 - //3、其他项目等下下周 1 (2025-03-17)开始推送第一篇, 之后按照正频率发送;  
111 - if (!$last_task) {  
112 - if(strpos($frequency[0],'/')){  
113 - $frequency = [1,1];//默认每天执行  
114 - }  
115 - if(!$compliance) {  
116 - for ($i = 0; $i < 3; $i++) {  
117 - $this->createTask($keywords, $project->id, $frequency);  
118 - }  
119 - }else{  
120 - if(date('Y-m-d') >= '2025-03-17'){  
121 - $this->createTask($keywords, $project->id, $frequency);  
122 - }  
123 - }  
124 - } else {  
125 - if(strpos($frequency[0],'/')){//一天2/3篇  
126 - $aiBlogTaskModel = new AiBlogTaskModel();  
127 - $frequency = explode('/', $frequency[0]);  
128 - //查询当前已发布几篇  
129 - $count = $aiBlogTaskModel->counts(['next_auto_date' => date('Y-m-d', strtotime('+1 day')),'project_id' => $project->id]);  
130 - while ($count < ($frequency[1] ?? 2) && ($count <= 3)){  
131 - $this->createTask($keywords, $project->id, [1,1]);  
132 - $count++;  
133 - }  
134 - }else{  
135 - $this->createTask($keywords, $project->id, $frequency);  
136 - }  
137 - }  
138 - }catch (\Exception $e){  
139 - (new DingService())->handle([  
140 - 'keyword' => 'AI_BLOG自动发布失败',  
141 - 'msg' => '项目ID:' . $project->id . PHP_EOL .  
142 - '错误信息:' . $e->getMessage() . PHP_EOL .  
143 - '错误文件:' . $e->getFile() . PHP_EOL .  
144 - '错误行数:' . $e->getLine(),  
145 - 'isAtAll' => true, // 是否@所有人  
146 - ]);  
147 - $this->output("自动发布失败:" . $e->getMessage() . $e->getFile() . $e->getLine());  
148 - }  
149 - sleep(5);  
150 - }  
151 - }  
152 -  
153 - public function createTask($keywords, $project_id, $frequency){  
154 - $keyword = $keywords[array_rand($keywords)];  
155 - $aiBlogService = new AiBlogService($project_id);  
156 - $result = $aiBlogService->createTask($keyword);  
157 - if ($result['status'] == 200) {  
158 - $aiBlogTaskModel = new AiBlogTaskModel();  
159 - $next_auto_date = date('Y-m-d', strtotime('+' . mt_rand($frequency[0] ?? 3, $frequency[1] ?? 6) . 'days')); //每3-6天自动发布  
160 - $aiBlogTaskModel->addReturnId(['project_id' => $project_id, 'type' => 2, 'task_id' => $result['data']['task_id'], 'status' => 1, 'next_auto_date' => $next_auto_date]);  
161 - ProjectServer::useProject($project_id);  
162 - $aiBlogModel = new AiBlog();  
163 - $start = strtotime('10:00:00');  
164 - $end = strtotime('16:00:00');  
165 - $randomTimestamp = mt_rand($start, $end);  
166 - $created_at = date("Y-m-d H:i:s", $randomTimestamp);  
167 - $aiBlogModel->addReturnId(['keyword' => $keyword, 'status' => 1, 'task_id' => $result['data']['task_id'], 'project_id' => $project_id, 'created_at' => $created_at]);  
168 - DB::disconnect('custom_mysql');  
169 - $this->output("任务创建成功");  
170 - } else {  
171 - $this->output('任务创建失败:' . json_encode($result));  
172 - }  
173 - }  
174 -  
175 - /**  
176 - * 上线的推广项目自动开启  
177 - * @author zbj  
178 - * @date 2025/3/7  
179 - */  
180 - public function auto_open()  
181 - {  
182 - while (true) {  
183 - $this->output('上线的推广项目自动开启');  
184 -  
185 - $projects = Project::whereIn('type', [Project::TYPE_TWO, Project::TYPE_FOUR])  
186 - ->whereIn('id', function ($query) {  
187 - //按推广时间  
188 - $query->select('project_id')  
189 - ->from('gl_project_deploy_optimize')  
190 - ->where('start_date', '<=', date('Y-m-d'))  
191 - ->where('start_date', '<>', '');  
192 - })  
193 - ->where('is_ai_blog', 0)  
194 - ->get();  
195 -  
196 - foreach ($projects as $project) {  
197 - try {  
198 - //未开启过 自动开启  
199 - if (!AiBlogOpenLog::isOpened($project->id)) {  
200 - //创建AI博客项目  
201 - $deploy_optimize = $project->deploy_optimize;  
202 - (new ProjectLogic())->setAiBlog($project->id, $project->main_lang_id, 1, $project->company, $deploy_optimize->company_en_name, $deploy_optimize->company_en_description,$project->is_related_video ?? 0);  
203 -  
204 - //开启  
205 - $project->is_ai_blog = 1;  
206 -  
207 - //开启自动发布  
208 - $project->deploy_optimize->is_ai_blog_send = 1;  
209 - $project->deploy_optimize->save();  
210 -  
211 - $project->save();  
212 -  
213 - //开启日志  
214 - AiBlogOpenLog::addLog($project->id);  
215 -  
216 - $this->output('自动开启项目:' . $project->id);  
217 - }  
218 - }catch (\Exception $e){  
219 - (new DingService())->handle([  
220 - 'keyword' => 'AI_BLOG自动开启失败',  
221 - 'msg' => '项目ID:' . $project->id . PHP_EOL .  
222 - '错误信息:' . $e->getMessage() . PHP_EOL .  
223 - '错误文件:' . $e->getFile() . PHP_EOL .  
224 - '错误行数:' . $e->getLine(),  
225 - 'isAtAll' => true, // 是否@所有人  
226 - ]);  
227 - $this->output("自动开启失败:" . $e->getMessage() . $e->getFile() . $e->getLine());  
228 - }  
229 - }  
230 - sleep(60);  
231 - }  
232 - }  
233 -  
234 - /**  
235 - * 输出message  
236 - * @param $message  
237 - */  
238 - public function output($message)  
239 - {  
240 - Log::channel('ai_blog')->info($message);  
241 - echo date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;  
242 - }  
243 -}  
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\Domain\DomainInfo;  
16 -use App\Models\Project\Project;  
17 -use App\Models\Project\ProjectAiSetting;  
18 -use App\Models\RouteMap\RouteMap;  
19 -use App\Services\AiBlogService;  
20 -use App\Services\ProjectServer;  
21 -use Illuminate\Console\Command;  
22 -use App\Models\Project\AiBlogTask as AiBlogTaskModel;  
23 -use Illuminate\Support\Facades\Cache;  
24 -use Illuminate\Support\Facades\DB;  
25 -use function Symfony\Component\String\s;  
26 -  
27 -/***  
28 - * @remark :根据项目更新blog列表  
29 - * @name :AiBlogListProjectTask  
30 - * @author :lyh  
31 - * @method :post  
32 - * @time :2025/3/6 9:45  
33 - */  
34 -class AiBlogListAllTask extends Command  
35 -{  
36 - /**  
37 - * The name and signature of the console command.  
38 - *  
39 - * @var string  
40 - */  
41 - protected $signature = 'save_all_ai_blog_list';  
42 -  
43 - /**  
44 - * The console command description.  
45 - *  
46 - * @var string  
47 - */  
48 - protected $description = '生成blog列表';  
49 -  
50 - public function handle(){  
51 - $projectModel = new Project();  
52 - $lists = $projectModel->list(['delete_status' => 0,'project_type'=>0,'extend_type'=>0,'type'=>['in',[2,3,4,6]]], 'id', ['id']);  
53 - foreach ($lists as $item){  
54 - echo '执行的项目的id'.$item['id'].PHP_EOL;  
55 - $project_id = $item['id'];  
56 - ProjectServer::useProject($project_id);  
57 - $projectAiSettingModel = new ProjectAiSetting();  
58 - $aiSettingInfo = $projectAiSettingModel->read(['project_id'=>$project_id]);  
59 - if($aiSettingInfo === false){  
60 - echo '未加载到配置。'.PHP_EOL;  
61 - continue;  
62 - }  
63 - $this->updateBlogList($aiSettingInfo);  
64 - $this->curlDelRoute($project_id);  
65 - DB::disconnect('custom_mysql');  
66 - }  
67 - return true;  
68 - }  
69 -  
70 - /**  
71 - * @remark :更新列表页数据  
72 - * @name :updateBlogList  
73 - * @author :lyh  
74 - * @method :post  
75 - * @time :2025/3/5 11:07  
76 - */  
77 - public function updateBlogList($aiSettingInfo){  
78 - $aiBlogService = new AiBlogService();  
79 - $aiBlogService->mch_id = $aiSettingInfo['mch_id'];  
80 - $aiBlogService->key = $aiSettingInfo['key'];  
81 - $page = 1;  
82 - $saveData = [];  
83 - $result = $aiBlogService->getAiBlogList($page,15);  
84 - if(!isset($result['status']) || $result['status'] != 200){  
85 - return true;  
86 - }  
87 - $total_page = $result['data']['total_page'];  
88 - //组装数据保存  
89 - $saveData[] = [  
90 - 'route'=>$page,  
91 - 'text'=>$result['data']['section'],  
92 - ];  
93 - while ($total_page > $page){  
94 - $page++;  
95 - $result = $aiBlogService->getAiBlogList($page,15);  
96 - if(isset($result['status']) && $result['status'] == 200){  
97 - $saveData[] = [  
98 - 'route'=>$page,  
99 - 'text'=>$result['data']['section'],  
100 - ];  
101 - }  
102 - }  
103 - $aiBlogListModel = new AiBlogList();  
104 - if(!empty($saveData)){  
105 - //写一条路由信息  
106 - $aiBlogListModel->truncate();  
107 - $aiBlogListModel->insertAll($saveData);  
108 - }  
109 - return true;  
110 - }  
111 -  
112 - /**  
113 - * @remark :通知C端生成界面  
114 - * @name :sendNotice  
115 - * @author :lyh  
116 - * @method :post  
117 - * @time :2025/3/6 11:51  
118 - */  
119 - public function curlDelRoute($project_id){  
120 - $domainModel = new DomainInfo();  
121 - //获取项目域名  
122 - $domain = $domainModel->getProjectIdDomain($project_id);  
123 - if(!empty($domain)){  
124 - $c_url = $domain.'api/update_page/';  
125 - $param = [  
126 - 'project_id' => $project_id,  
127 - 'type' => 1,  
128 - 'route' => 3,  
129 - 'url' => ['top-blog'],  
130 - 'language'=> [],  
131 - 'is_sitemap' => 0  
132 - ];  
133 - http_post($c_url, json_encode($param));  
134 - }  
135 - return true;  
136 - }  
137 -}  
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\Domain\DomainInfo;  
16 -use App\Models\Project\ProjectAiSetting;  
17 -use App\Models\RouteMap\RouteMap;  
18 -use App\Services\AiBlogService;  
19 -use App\Services\ProjectServer;  
20 -use Illuminate\Console\Command;  
21 -use App\Models\Project\AiBlogTask as AiBlogTaskModel;  
22 -use Illuminate\Support\Facades\Cache;  
23 -use Illuminate\Support\Facades\DB;  
24 -use function Symfony\Component\String\s;  
25 -  
26 -/***  
27 - * @remark :根据项目更新blog列表  
28 - * @name :AiBlogListProjectTask  
29 - * @author :lyh  
30 - * @method :post  
31 - * @time :2025/3/6 9:45  
32 - */  
33 -class AiBlogListProjectTask extends Command  
34 -{  
35 - /**  
36 - * The name and signature of the console command.  
37 - *  
38 - * @var string  
39 - */  
40 - protected $signature = 'save_ai_blog_list {project_id}';  
41 -  
42 - /**  
43 - * The console command description.  
44 - *  
45 - * @var string  
46 - */  
47 - protected $description = '根据项目生成blog列表';  
48 -  
49 - public function handle(){  
50 - $project_id = $this->argument('project_id');  
51 - @file_put_contents(storage_path('logs/lyh_error.log'), var_export('执行的项目id->'.$project_id, true) . PHP_EOL, FILE_APPEND);  
52 - ProjectServer::useProject($project_id);  
53 - $projectAiSettingModel = new ProjectAiSetting();  
54 - $aiSettingInfo = $projectAiSettingModel->read(['project_id'=>$project_id]);  
55 - $this->updateBlogList($aiSettingInfo);  
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($aiSettingInfo){  
69 - $aiBlogService = new AiBlogService();  
70 - $aiBlogService->mch_id = $aiSettingInfo['mch_id'];  
71 - $aiBlogService->key = $aiSettingInfo['key'];  
72 - $page = 1;  
73 - $saveData = [];  
74 - $result = $aiBlogService->getAiBlogList($page,15);  
75 - if(!isset($result['status']) || $result['status'] != 200){  
76 - echo '请示失败。'.json_encode($result, JSON_UNESCAPED_UNICODE);  
77 - return true;  
78 - }  
79 - $total_page = $result['data']['total_page'];  
80 - //组装数据保存  
81 - $saveData[] = [  
82 - 'route'=>$page,  
83 - 'text'=>$result['data']['section'],  
84 - ];  
85 - while ($total_page > $page){  
86 - $page++;  
87 - $result = $aiBlogService->getAiBlogList($page,15);  
88 - if(isset($result['status']) && $result['status'] == 200){  
89 - $saveData[] = [  
90 - 'route'=>$page,  
91 - 'text'=>$result['data']['section'],  
92 - ];  
93 - }  
94 - }  
95 - $aiBlogListModel = new AiBlogList();  
96 - if(!empty($saveData)){  
97 - //写一条路由信息  
98 - $aiBlogListModel->truncate();  
99 - $aiBlogListModel->insertAll($saveData);  
100 - }  
101 - return true;  
102 - }  
103 -  
104 - /**  
105 - * @remark :通知C端生成界面  
106 - * @name :sendNotice  
107 - * @author :lyh  
108 - * @method :post  
109 - * @time :2025/3/6 11:51  
110 - */  
111 - public function curlDelRoute($project_id){  
112 - $domainModel = new DomainInfo();  
113 - //获取项目域名  
114 - $domain = $domainModel->getProjectIdDomain($project_id);  
115 - if(!empty($domain)){  
116 - $c_url = $domain.'api/update_page/';  
117 - $param = [  
118 - 'project_id' => $project_id,  
119 - 'type' => 1,  
120 - 'route' => 3,  
121 - 'url' => ['top-blog'],  
122 - 'language'=> [],  
123 - 'is_sitemap' => 0  
124 - ];  
125 - http_post($c_url, json_encode($param));  
126 - }  
127 - return true;  
128 - }  
129 -}  
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\Domain\DomainInfo;  
16 -use App\Models\Project\ProjectAiSetting;  
17 -use App\Models\RouteMap\RouteMap;  
18 -use App\Services\AiBlogService;  
19 -use App\Services\ProjectServer;  
20 -use Illuminate\Console\Command;  
21 -use App\Models\Project\AiBlogTask as AiBlogTaskModel;  
22 -use Illuminate\Support\Facades\Cache;  
23 -use Illuminate\Support\Facades\DB;  
24 -use Illuminate\Support\Facades\Redis;  
25 -use function Symfony\Component\String\s;  
26 -  
27 -/***  
28 - * @remark :根据项目更新blog列表  
29 - * @name :AiBlogListProjectTask  
30 - * @author :lyh  
31 - * @method :post  
32 - * @time :2025/3/6 9:45  
33 - */  
34 -class AiBlogListTask extends Command  
35 -{  
36 - /**  
37 - * The name and signature of the console command.  
38 - *  
39 - * @var string  
40 - */  
41 - protected $signature = 'save_ai_blog_list_task';  
42 -  
43 - /**  
44 - * The console command description.  
45 - *  
46 - * @var string  
47 - */  
48 - protected $description = '生成blog列表页';  
49 -  
50 - public function handle(){  
51 - while (true){  
52 - $task_id = $this->getTaskId();  
53 - if(empty($task_id)){  
54 - sleep(200);  
55 - continue;  
56 - }  
57 - $aiBlogTaskModel = new AiBlogTaskModel();  
58 - $info = $aiBlogTaskModel->read(['id'=>$task_id,'type'=>$aiBlogTaskModel::TYPE_LIST]);  
59 - if($info === false){  
60 - echo date('Y-m-d H:i:s').',当前数据不存在或者已被删除。'.PHP_EOL;  
61 - }  
62 - $project_id = $info['project_id'];  
63 - echo '执行的项目ID:'.$info['project_id'].PHP_EOL;  
64 - ProjectServer::useProject($project_id);  
65 - $projectAiSettingModel = new ProjectAiSetting();  
66 - $aiSettingInfo = $projectAiSettingModel->read(['project_id'=>$project_id]);  
67 - $res = $this->updateBlogList($aiSettingInfo);  
68 - if($res){  
69 - $aiBlogTaskModel->edit(['status'=>2],['id'=>$task_id]);  
70 - }else{  
71 - if($info['sort'] >= 5){  
72 - $aiBlogTaskModel->edit(['status'=>9],['id'=>$task_id]);  
73 - }else{  
74 - $aiBlogTaskModel->edit(['status'=>9,'sort'=>($info['sort'] + 1)],['id'=>$task_id]);  
75 - }  
76 - }  
77 - $this->curlDelRoute($project_id);  
78 - DB::disconnect('custom_mysql');  
79 - }  
80 - return true;  
81 - }  
82 -  
83 - /**  
84 - * @remark :更新列表页数据  
85 - * @name :updateBlogList  
86 - * @author :lyh  
87 - * @method :post  
88 - * @time :2025/3/5 11:07  
89 - */  
90 - public function updateBlogList($aiSettingInfo){  
91 - $aiBlogService = new AiBlogService();  
92 - $aiBlogService->mch_id = $aiSettingInfo['mch_id'];  
93 - $aiBlogService->key = $aiSettingInfo['key'];  
94 - $page = 1;  
95 - $saveData = [];  
96 - $result = $aiBlogService->getAiBlogList($page,15);  
97 - if(!isset($result['status']) || $result['status'] != 200){  
98 - echo '请求失败。'.json_encode($result, JSON_UNESCAPED_UNICODE);  
99 - return false;  
100 - }  
101 - $total_page = $result['data']['total_page'];  
102 - //组装数据保存  
103 - $saveData[] = [  
104 - 'route'=>$page,  
105 - 'text'=>$result['data']['section'],  
106 - ];  
107 - while ($total_page > $page){  
108 - $page++;  
109 - $result = $aiBlogService->getAiBlogList($page,15);  
110 - if(isset($result['status']) && $result['status'] == 200){  
111 - $saveData[] = [  
112 - 'route'=>$page,  
113 - 'text'=>$result['data']['section'],  
114 - ];  
115 - }else{  
116 - echo '请求失败。'.json_encode($result, JSON_UNESCAPED_UNICODE);  
117 - return false;  
118 - }  
119 - }  
120 - $aiBlogListModel = new AiBlogList();  
121 - if(!empty($saveData)){  
122 - //写一条路由信息  
123 - $aiBlogListModel->truncate();  
124 - $aiBlogListModel->insertAll($saveData);  
125 - return true;  
126 - }  
127 - return true;  
128 - }  
129 -  
130 - /**  
131 - * @remark :通知C端生成界面  
132 - * @name :sendNotice  
133 - * @author :lyh  
134 - * @method :post  
135 - * @time :2025/3/6 11:51  
136 - */  
137 - public function curlDelRoute($project_id){  
138 - $domainModel = new DomainInfo();  
139 - //获取项目域名  
140 - $domain = $domainModel->getProjectIdDomain($project_id);  
141 - if(!empty($domain)){  
142 - $c_url = $domain.'api/update_page/';  
143 - $param = [  
144 - 'project_id' => $project_id,  
145 - 'type' => 1,  
146 - 'route' => 3,  
147 - 'url' => ['top-blog'],  
148 - 'language'=> [],  
149 - 'is_sitemap' => 0  
150 - ];  
151 - http_post($c_url, json_encode($param));  
152 - }  
153 - return true;  
154 - }  
155 -  
156 - /**  
157 - * 获取任务id  
158 - * @param int $finish_at  
159 - * @return mixed  
160 - */  
161 - public function getTaskId($finish_at = 2)  
162 - {  
163 - $keys = 'ai_blog_list_task';  
164 - $task_id = Redis::rpop($keys);  
165 - if (empty($task_id)) {  
166 - $aiBlogTaskModel = new AiBlogTaskModel();  
167 - $finish_at = date('Y-m-d H:i:s', strtotime('-' . $finish_at . ' hour'));  
168 - $ids = $aiBlogTaskModel->formatQuery(['status'=>$aiBlogTaskModel::STATUS_RUNNING, 'type'=>$aiBlogTaskModel::TYPE_LIST, 'updated_at'=>['<=',$finish_at]])->pluck('id');  
169 - if(!empty($ids)){  
170 - foreach ($ids as $id) {  
171 - Redis::lpush($keys, $id);  
172 - }  
173 - }  
174 - $task_id = Redis::rpop($keys);  
175 - }  
176 - return $task_id;  
177 - }  
178 -}  
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\Helper\Arr;  
13 -use App\Models\Ai\AiBlog;  
14 -use App\Models\Ai\AiBlogAuthor;  
15 -use App\Models\Ai\AiBlogList;  
16 -use App\Models\Com\NoticeLog;  
17 -use App\Models\Com\Notify;  
18 -use App\Models\Devops\ServerConfig;  
19 -use App\Models\Devops\ServersIp;  
20 -use App\Models\Domain\DomainInfo;  
21 -use App\Models\Project\Project;  
22 -use App\Models\Project\ProjectAiSetting;  
23 -use App\Models\RouteMap\RouteMap;  
24 -use App\Services\AiBlogService;  
25 -use App\Services\DingService;  
26 -use App\Services\ProjectServer;  
27 -use Illuminate\Console\Command;  
28 -use App\Models\Project\AiBlogTask as AiBlogTaskModel;  
29 -use Illuminate\Support\Facades\DB;  
30 -use Illuminate\Support\Facades\Redis;  
31 -  
32 -class AiBlogTask extends Command  
33 -{  
34 - /**  
35 - * The name and signature of the console command.  
36 - *  
37 - * @var string  
38 - */  
39 - protected $signature = 'save_ai_blog';  
40 -  
41 - public $updateProject = [];//需更新的列表  
42 - public $projectSetting = [];  
43 - public $routes = [];//需要更新的路由  
44 -  
45 - /**  
46 - * The console command description.  
47 - *  
48 - * @var string  
49 - */  
50 - protected $description = '查询ai_blog是否已经生成';  
51 -  
52 - /**  
53 - * @return bool  
54 - * @throws \Exception  
55 - */  
56 - public function handle(){  
57 - while (true){  
58 - //获取任务id  
59 - $task_id = $this->getTaskId();  
60 - if(empty($task_id)){  
61 - sleep(300);  
62 - continue;  
63 - }  
64 - $this->sendRequest($task_id);  
65 - }  
66 - return true;  
67 - }  
68 -  
69 - /**  
70 - * 请求方法  
71 - * @param $task_id  
72 - * @return bool  
73 - * @throws \Exception  
74 - */  
75 - public function sendRequest($task_id){  
76 - $aiBlogTaskModel = new AiBlogTaskModel();  
77 - $item = $aiBlogTaskModel->read(['id'=>$task_id]);  
78 - $this->output('start:project ID: ' . $item['project_id'] . ',task ID: ' . $task_id);  
79 - //获取配置  
80 - $aiSettingInfo = $this->getSetting($item['project_id']);  
81 - $aiBlogService = new AiBlogService();  
82 - $aiBlogService->mch_id = $aiSettingInfo['mch_id'];  
83 - $aiBlogService->key = $aiSettingInfo['key'];  
84 - $aiBlogService->task_id = $item['task_id'];  
85 - //拉取文章数据  
86 - $result = $aiBlogService->getDetail();  
87 - if(empty($result['status']) || ($result['status'] != 200)){  
88 - if($item['sort'] < 5){  
89 - $aiBlogTaskModel->edit(['sort'=>$item['sort'] + 1],['id'=>$item['id']]);  
90 - }else{  
91 - $aiBlogTaskModel->edit(['status'=>9],['id'=>$item['id']]);  
92 - // 钉钉通知  
93 - $dingService = new DingService();  
94 - $body = [  
95 - 'keyword' => 'AI_BLOG获取失败',  
96 - 'msg' => '任务ID:' . $item['task_id'] . PHP_EOL . '返回信息:' . json_encode($result,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),  
97 - 'isAtAll' => false, // 是否@所有人  
98 - ];  
99 - $dingService->handle($body);  
100 - }  
101 - $this->output('error: 数据获取失败,status:' . $result['status'] . ',message: ' . ($result['message'] ?? 'null'));  
102 - return false;  
103 - }  
104 - //保存当前项目ai_blog数据  
105 - ProjectServer::useProject($item['project_id']);  
106 - $aiBlogModel = new AiBlog();  
107 - $aiBlogInfo = $aiBlogModel->read(['task_id'=>$item['task_id']],['id','route']);  
108 - if($aiBlogInfo === false){  
109 - // 钉钉通知  
110 - $dingService = new DingService();  
111 - $body = [  
112 - 'keyword' => 'AI_BLOG生成错误',  
113 - 'msg' => '任务ID:' . $item['task_id'] . ', 子库获取数据失败, 检查子库数据是否被删除!',  
114 - 'isAtAll' => false, // 是否@所有人  
115 - ];  
116 - $dingService->handle($body);  
117 - $this->output('error: 子库获取数据失败, task id: ' . $task_id);  
118 - $aiBlogTaskModel->edit(['status'=>9],['id'=>$item['id']]);  
119 - DB::disconnect('custom_mysql');  
120 - return false;  
121 - }  
122 - //拿到返回的路由查看是否重复  
123 - $route = RouteMap::setRoute($result['data']['url'], RouteMap::SOURCE_AI_BLOG, $aiBlogInfo['id'], $item['project_id']);  
124 - if($route != $result['data']['url']){  
125 - $aiBlogService->updateDetail(['route'=>$route,'task_id'=>$item['task_id']]);  
126 - }  
127 - //需要更新的路由  
128 - if (!in_array($result['data']['author_id'], $this->updateProject[$item['project_id']] ?? [])) {  
129 - $this->updateProject[$item['project_id']][] = $result['data']['author_id'];  
130 - }  
131 - if (!in_array($route, $this->routes[$item['project_id']] ?? [])) {  
132 - $this->routes[$item['project_id']][] = $route;  
133 - }  
134 - $aiBlogModel->edit(['new_title'=>$result['data']['title'], 'image'=>$result['data']['thumb'], 'text'=>$result['data']['section'], 'author_id'=>$result['data']['author_id'],'seo_title'=>$result['data']['title'],'seo_keyword'=>$result['data']['keyword'],'seo_description'=>$result['data']['description'], 'route'=>$route ,'status'=>$aiBlogModel::STATUS_FINISH], ['task_id'=>$item['task_id']]);  
135 - DB::disconnect('custom_mysql');  
136 - $aiBlogTaskModel->edit(['status'=>$aiBlogModel::STATUS_FINISH],['id'=>$item['id']]);  
137 - $this->output('success: task id: ' . $task_id);  
138 - return true;  
139 - }  
140 -  
141 - /**  
142 - * 获取任务id  
143 - * @param int $finish_at  
144 - * @return mixed  
145 - */  
146 - public function getTaskId($finish_at = 2)  
147 - {  
148 - $task_id = Redis::rpop('ai_blog_task');  
149 - if (empty($task_id)) {  
150 - if(!empty($this->updateProject)){  
151 - $this->updateProject($this->updateProject);  
152 - $this->updateProject = [];  
153 - }  
154 - if(!empty($this->routes)){  
155 - $this->updateRoutes($this->routes);  
156 - $this->routes = [];  
157 - }  
158 - $aiBlogTaskModel = new AiBlogTaskModel();  
159 - $finish_at = date('Y-m-d H:i:s', strtotime('-' . $finish_at . ' hour'));  
160 - $ids = $aiBlogTaskModel->formatQuery(['status'=>$aiBlogTaskModel::STATUS_RUNNING, 'type'=>$aiBlogTaskModel::TYPE_BLOG, 'updated_at'=>['<=',$finish_at]])->pluck('id');  
161 - if(!empty($ids)){  
162 - foreach ($ids as $id) {  
163 - Redis::lpush('ai_blog_task', $id);  
164 - }  
165 - }  
166 - $task_id = Redis::rpop('ai_blog_task');  
167 - }  
168 - return $task_id;  
169 - }  
170 -  
171 - /**  
172 - * 更新项目作者页面及列表页  
173 - * @param $updateProject  
174 - * @return bool  
175 - */  
176 - public function updateProject($updateProject){  
177 - if(empty($updateProject)){  
178 - return true;  
179 - }  
180 - foreach ($updateProject as $project_id => $author){  
181 - ProjectServer::useProject($project_id);  
182 - $aiSettingInfo = $this->getSetting($project_id);  
183 - $this->output('sync: list start, project_id: ' . $project_id);  
184 - $this->updateBlogList($aiSettingInfo,$project_id);  
185 - $this->output('sync: list end');  
186 - //更新作者  
187 - $this->output('sync: author start, project_id: ' . $project_id);  
188 - foreach ($author as $val){  
189 - $this->updateAiBlogAuthor($aiSettingInfo,$val,$project_id);  
190 - }  
191 - $this->output('sync: author end');  
192 - DB::disconnect('custom_mysql');  
193 - }  
194 -  
195 - return true;  
196 - }  
197 -  
198 - /**  
199 - * 获取项目配置  
200 - * @param $project_id  
201 - * @return bool  
202 - */  
203 - public function getSetting($project_id)  
204 - {  
205 - $project_setting = $this->projectSetting;  
206 - if (FALSE == empty($project_setting[$project_id])){  
207 - return $project_setting[$project_id];  
208 - }  
209 - $projectAiSettingModel = new ProjectAiSetting();  
210 - $aiSettingInfo = $projectAiSettingModel->read(['project_id'=>$project_id]);  
211 - $this->projectSetting[$project_id] = $aiSettingInfo;  
212 - return $aiSettingInfo;  
213 - }  
214 -  
215 - /**  
216 - * 更新作者的页面  
217 - * @param $aiSettingInfo  
218 - * @param $author_id  
219 - * @return bool  
220 - */  
221 - public function updateAiBlogAuthor($aiSettingInfo,$author_id,$project_id){  
222 - if(empty($author_id)){  
223 - return true;  
224 - }  
225 - $aiBlogService = new AiBlogService();  
226 - $aiBlogService->mch_id = $aiSettingInfo['mch_id'];  
227 - $aiBlogService->key = $aiSettingInfo['key'];  
228 - $aiBlogService->author_id = $author_id;  
229 - $result = $aiBlogService->getAuthorDetail();  
230 - if(isset($result['status']) && $result['status'] == 200){  
231 - //当前作者的页面  
232 - $aiBlogAuthorModel = new AiBlogAuthor();  
233 - $authorInfo = $aiBlogAuthorModel->read(['author_id'=>$author_id],['id','route']);  
234 - if($authorInfo !== false && !empty($result['data']['section'])){  
235 - //需要更新的路由  
236 - if (!in_array($authorInfo['route'], $this->routes[$project_id] ?? [])) {  
237 - $this->routes[$project_id][] = $authorInfo['route'];  
238 - }  
239 - $aiBlogAuthorModel->edit(['text'=>$result['data']['section']],['author_id'=>$author_id]);  
240 - }  
241 - }  
242 - return true;  
243 - }  
244 -  
245 - /**  
246 - * 更新列表页  
247 - * @param $aiSettingInfo  
248 - * @return bool  
249 - */  
250 - public function updateBlogList($aiSettingInfo,$project_id = 0){  
251 - $aiBlogService = new AiBlogService();  
252 - $aiBlogService->mch_id = $aiSettingInfo['mch_id'];  
253 - $aiBlogService->key = $aiSettingInfo['key'];  
254 - $page = 1;  
255 - $saveData = [];  
256 - $result = $aiBlogService->getAiBlogList($page,15);  
257 - if(!isset($result['status']) || $result['status'] != 200){  
258 - try {  
259 - // 钉钉通知  
260 - $dingService = new DingService();  
261 - $body = [  
262 - 'keyword' => 'AI_BLOG列表页未生成拉取失败',  
263 - 'msg' => '项目ID:' . $project_id . PHP_EOL . '返回信息:' . json_encode($result,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),  
264 - 'isAtAll' => false, // 是否@所有人  
265 - ];  
266 - $dingService->handle($body);  
267 - //写一条更新记录  
268 - $aiBlogTaskModel = new AiBlogTaskModel();  
269 - $aiBlogTaskModel->addReturnId(['project_id'=>$project_id,'task_id'=>$project_id,'status'=>$aiBlogTaskModel::STATUS_RUNNING,'type'=>$aiBlogTaskModel::TYPE_LIST]);  
270 - }catch (\Exception $e){  
271 - $this->output('更新列表页失败同时通知失败--error:' . $e->getMessage());  
272 - }  
273 - return true;  
274 - }  
275 - $total_page = $result['data']['total_page'];  
276 - //组装数据保存  
277 - $saveData[] = [  
278 - 'route'=>$page,  
279 - 'text'=>$result['data']['section'],  
280 - ];  
281 - while ($total_page > $page){  
282 - $page++;  
283 - $result = $aiBlogService->getAiBlogList($page,15);  
284 - if(isset($result['status']) && $result['status'] == 200){  
285 - $saveData[] = [  
286 - 'route'=>$page,  
287 - 'text'=>$result['data']['section'],  
288 - ];  
289 - }  
290 - }  
291 - $aiBlogListModel = new AiBlogList();  
292 - if(!empty($saveData)){  
293 - //写一条路由信息  
294 - $aiBlogListModel->truncate();  
295 - $aiBlogListModel->insertAll($saveData);  
296 - }  
297 - return true;  
298 - }  
299 -  
300 - /**  
301 - * 通知C端生成界面  
302 - * @param $project_id  
303 - * @return bool  
304 - */  
305 - public function updateRoutes($routes){  
306 - $domainModel = new DomainInfo();  
307 - $project_model = new Project();  
308 - foreach ($routes as $project_id => $route){  
309 - if($project_id == 4339){  
310 - continue;  
311 - }  
312 - $route[] = 'top-blog';  
313 - $domain = $domainModel->getProjectIdDomain($project_id);  
314 - if (empty($domain)) {  
315 - $this->output('send: 域名不存在, project id: ' . $project_id);  
316 - continue;  
317 - }  
318 - //判断是否是自建站服务器,如果是,不请求C端接口,数据直接入库  
319 - $project_info = $project_model->read(['id'=>$project_id],['serve_id']);  
320 - if(!$project_info){  
321 - $this->output('send: 项目不存在, project id: ' . $project_id);  
322 - continue;  
323 - }  
324 - $serve_ip_model = new ServersIp();  
325 - $serve_ip_info = $serve_ip_model->read(['id'=>$project_info['serve_id']],['servers_id']);  
326 - $servers_id = $serve_ip_info ? $serve_ip_info['servers_id'] : 0;  
327 - if($servers_id == ServerConfig::SELF_SITE_ID){  
328 - //判断是否已有更新进行中  
329 - $notify_model = new Notify();  
330 - $data = [  
331 - 'project_id' => $project_id,  
332 - 'type' => Notify::TYPE_MASTER,  
333 - 'route' => Notify::ROUTE_AI_BLOG,  
334 - 'server_id' => ServerConfig::SELF_SITE_ID,  
335 - 'status' => ['!=',Notify::STATUS_FINISH_SITEMAP]  
336 - ];  
337 - $notify = $notify_model->read($data,['id']);  
338 - if(!$notify){  
339 - $domain_array = parse_url($domain);  
340 - $data['data'] = Arr::a2s(['domain'=>$domain_array['host'],'url'=>$route,'language'=>[]]);  
341 - $data['status'] = Notify::STATUS_INIT;  
342 - $data['sort'] = 2;  
343 - $notify_model->add($data);  
344 - }  
345 - $this->output('send: 自建站项目, project id: ' . $project_id);  
346 - }else{  
347 - $c_url = $domain.'api/update_page/';  
348 - $param = [  
349 - 'project_id' => $project_id,  
350 - 'type' => 1,  
351 - 'route' => 3,  
352 - 'url' => $route,  
353 - 'language'=> [],  
354 - 'is_sitemap' => 0  
355 - ];  
356 - $res = http_post($c_url, json_encode($param,true));  
357 - if(empty($res)){  
358 - NoticeLog::createLog(NoticeLog::GENERATE_PAGE, ['c_url'=>$c_url,'c_params'=>$param],date('Y-m-d H:i:s',time()+300));  
359 - }  
360 - $this->output('notify: project id: ' . $project_id . ', result: ' . json_encode($res,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));  
361 - }  
362 - }  
363 - return true;  
364 - }  
365 -  
366 - /**  
367 - * 输入日志  
368 - * @param $message  
369 - * @return bool  
370 - */  
371 - public function output($message)  
372 - {  
373 - $message = date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;  
374 - echo $message;  
375 - file_put_contents(storage_path('logs/AiBlog/') . date('Ymd') . '.log', $message, FILE_APPEND);  
376 - return true;  
377 - }  
378 -}  
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :AiDomainTask.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2025/6/19 10:53  
8 - */  
9 -  
10 -namespace App\Console\Commands\Ai;  
11 -  
12 -use App\Models\Domain\DomainInfo;  
13 -use Illuminate\Console\Command;  
14 -  
15 -/**  
16 - * @remark :拉取项目Ai域名  
17 - * @name :AiDomainTask  
18 - * @author :lyh  
19 - * @method :post  
20 - * @time :2025/6/19 10:54  
21 - */  
22 -class AiDomainTask extends Command  
23 -{  
24 - /**  
25 - * The name and signature of the console command.  
26 - *  
27 - * @var string  
28 - */  
29 - protected $signature = 'ai_domain';  
30 -  
31 - /**  
32 - * The console command description.  
33 - *  
34 - * @var string  
35 - */  
36 - protected $description = '获取对应域名的ai复制站域名';  
37 -  
38 - public $url = 'https://www.cmer.site/api/globalso_site';  
39 -  
40 - /**  
41 - * @remark :执行方法  
42 - * @name :handle  
43 - * @author :lyh  
44 - * @method :post  
45 - * @time :2025/6/19 11:32  
46 - */  
47 - public function handle(){  
48 - $pageSize = 300;  
49 - $page = 1;  
50 - $res = http_get($this->url.'?pagesize='.$pageSize.'&page='.$page);  
51 - if($res['status'] != 200){  
52 - echo date('Y-m-d H:i:s').'请求失败,状态码错误'.PHP_EOL;  
53 - return false;  
54 - }  
55 - if(empty($res['data']['data'])){  
56 - echo date('Y-m-d H:i:s').'请求失败,未拉取到数据'.PHP_EOL;  
57 - return false;  
58 - }  
59 - $data = $res['data']['data'];  
60 - while($page <= $res['data']['last_page']){  
61 - $res = http_get($this->url.'?pagesize='.$pageSize.'&page='.$page);  
62 - if($res['status'] != 200){  
63 - echo date('Y-m-d H:i:s').'第'.$page.'请求失败,未拉取到数据'.PHP_EOL;  
64 - return false;  
65 - }  
66 - $data = array_values(array_merge($data,$res['data']['data']));  
67 - $page++;  
68 - }  
69 - //处理数据  
70 - $this->handleData($data);  
71 - echo 'end'.PHP_EOL;  
72 - return true;  
73 - }  
74 -  
75 - /**  
76 - * @remark :处理数据  
77 - * @name :handleData  
78 - * @author :lyh  
79 - * @method :post  
80 - * @time :2025/6/19 11:21  
81 - */  
82 - public function handleData($data){  
83 - $domainInfoModel = new DomainInfo();  
84 - foreach ($data as $item){  
85 - $info = $domainInfoModel->read(['domain'=>$item['domain']],'id');  
86 - if($info === false){  
87 - $info = $domainInfoModel->read(['domain'=>$item['globalso_domain']],'id');  
88 - if($info !== false){  
89 - $domainInfoModel->edit(['ai_domain'=>$item['domain']],['id'=>$info['id']]);  
90 - }  
91 - }else{  
92 - $domainInfoModel->edit(['ai_domain'=>$item['globalso_domain']],['id'=>$info['id']]);  
93 - }  
94 - }  
95 - return true;  
96 - }  
97 -}  
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :AiVideoAutoPublish.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2025/8/1 15:19  
8 - */  
9 -  
10 -namespace App\Console\Commands\Ai;  
11 -  
12 -use App\Models\Ai\AiVideo;  
13 -use App\Models\AyrShare\AyrShare;  
14 -use App\Models\Domain\DomainInfo;  
15 -use App\Models\Product\Keyword;  
16 -use App\Models\Product\Product;  
17 -use App\Models\Project\AiBlogTask as AiBlogTaskModel;  
18 -use App\Models\Project\AiVideoAutoLog;  
19 -use App\Models\Project\DeployOptimize;  
20 -use App\Models\Project\Project;  
21 -use App\Services\AiVideoService;  
22 -use App\Services\MidJourneyService;  
23 -use App\Services\ProjectServer;  
24 -use Illuminate\Console\Command;  
25 -use Illuminate\Support\Facades\DB;  
26 -use Illuminate\Support\Facades\Log;  
27 -use App\Models\Project\AiVideoTask;  
28 -use Illuminate\Support\Facades\Redis;  
29 -  
30 -/**  
31 - * @remark :ai视频自动发布  
32 - * @name :AiVideoAutoPublish  
33 - * @author :lyh  
34 - * @method :post  
35 - * @time :2025/8/1 15:19  
36 - */  
37 -class AiVideoAutoPublish extends Command  
38 -{  
39 - /**  
40 - * The name and signature of the console command.  
41 - *  
42 - * @var string  
43 - */  
44 - protected $signature = 'ai_video_auto_publish {action}';  
45 -  
46 - /**  
47 - * The console command description.  
48 - *  
49 - * @var string  
50 - */  
51 - protected $description = '自动发布AI Video';  
52 -  
53 - public function handle(){  
54 - $action = $this->argument('action');  
55 - if($action == 'auto_publish'){  
56 - $this->auto_publish();  
57 - }  
58 - if($action == 'auto_send_video'){  
59 - $this->auto_send_video();  
60 - }  
61 - if($action == 'auto_save_video_task'){  
62 - $this->auto_save_video_task();  
63 - }  
64 - }  
65 -  
66 - /**  
67 - * @remark :自动发布aiVideo组装数据(写入一条记录)  
68 - * @name :auto_six_publish  
69 - * @author :lyh  
70 - * @method :post  
71 - * @time :2025/8/1 15:22  
72 - */  
73 - public function auto_publish(){  
74 - $this->output('开始自动发布Video文章');  
75 - $projectModel = new Project();  
76 - $optimizeModel = new DeployOptimize();  
77 - $projectList = $projectModel->list(['is_ai_video'=>1,'type'=>['in',[1,2,3,4,6]],'delete_status'=>0,'site_status'=>0,'extend_type'=>0],'id',['id','project_type']);  
78 - foreach ($projectList as $item){  
79 - $this->output("项目{$item['id']}开始自动发布");  
80 - //获取当前是否开启自动发布aiVideo  
81 - $opInfo = $optimizeModel->read(['project_id'=>$item['id']],['is_ai_video_send','send_ai_video_frequency','start_date']);  
82 - if($opInfo['is_ai_video_send'] != 1){  
83 - $this->output("项目{$item['id']}未开启自动发布" . $opInfo['start_date']);  
84 - continue;  
85 - }  
86 - if(($opInfo['start_date'] > date('Y-m-d')) || empty($opInfo['start_date'])){  
87 - $this->output("项目{$item['id']}未到推广时间" . $opInfo['start_date']);  
88 - continue;  
89 - }  
90 - $aiVideoTaskModel = new AiVideoTask();  
91 - $next_auto_date = $aiVideoTaskModel->formatQuery(['project_id'=>$item['id'],'next_auto_date'=>['!=',null]])->orderBy('id', 'desc')->value('next_auto_date');  
92 - if($next_auto_date && ($next_auto_date > date('Y-m-d'))){  
93 - $this->output("项目{$item['id']}未到执行时间" . $next_auto_date);  
94 - continue;  
95 - }  
96 - if($item['project_type'] == 1){  
97 - //todo::页面上获取数据  
98 - $data = $this->getAiVideoParam($item['id']);  
99 - }else{  
100 - //获取当前网站的标题  
101 - ProjectServer::useProject($item['id']);  
102 - $data = $this->getVideoInfo();  
103 - DB::disconnect('custom_mysql');  
104 - }  
105 - if(!empty($data)){  
106 - //写入一条零时生成视频记录  
107 - $aiVideoAutoLogModel = new AiVideoAutoLog();  
108 - $aiVideoAutoLogModel->addReturnId(  
109 - ['project_id'=>$item['id'],'title'=>$data['title'],'remark'=>$data['remark'],'images'=>json_encode($data['images'],true),'date'=>date('Y-m-d')]  
110 - );  
111 - }  
112 - }  
113 - return true;  
114 - }  
115 -  
116 - /**  
117 - * @remark :获取产品标题+产品描述  
118 - * @name :getProduct  
119 - * @author :lyh  
120 - * @method :post  
121 - * @time :2025/8/1 16:09  
122 - */  
123 - public function getVideoInfo(){  
124 - $data = [];  
125 - $random = rand(1, 2);  
126 - if($random == 1){//取产品  
127 - $productModel = new Product();  
128 - $info = $productModel->formatQuery(['status'=>1,'title'=>['!=',null],'intro'=>['!=',null]])->select(['title','gallery','intro'])->inRandomOrder()->first();  
129 - if(empty($info)){  
130 - return $data;  
131 - }  
132 - $data['title'] = $info['title'];  
133 - $data['remark'] = $info['intro'];  
134 - $data['images'] = array_filter(array_map(function ($item) use ($data) {  
135 - if (!empty($item['url'])) {  
136 - return [  
137 - 'alt' => $item['title'] ?? $data['title'],  
138 - 'url' => getImageUrl($item['url']),  
139 - ];  
140 - }  
141 - return null;  
142 - }, $info['gallery']));  
143 - return $data;  
144 - }else{  
145 - //聚合页获取当前关联产品的图片  
146 - $keywordModel = new Keyword();  
147 - $keywordInfo = $keywordModel->formatQuery(['keyword_title'=>['!=',null],'keyword_content'=>['!=',null]])->select(['keyword_title','keyword_content'])->inRandomOrder()->first();  
148 - if(empty($keywordInfo)){  
149 - return $data;  
150 - }  
151 - $data['title'] = $keywordInfo['keyword_title'];  
152 - $data['remark'] = $keywordInfo['keyword_content'];  
153 - $data['remark'] = strip_tags($keywordInfo['intro']);  
154 - if(empty($data['remark'])){  
155 - $data['remark'] = $data['title'];  
156 - }  
157 - $data['images'] = [];  
158 - $productModel = new Product();  
159 - $productList = $productModel->list(['keyword_id'=>['like','%,'.$keywordInfo['id'].',%']],'id',['gallery'],'desc',10);  
160 - foreach ($productList as $info){  
161 - $images = array_filter(array_map(function ($item) use ($data) {  
162 - if (!empty($item['url'])) {  
163 - return [  
164 - 'alt' => $item['title'] ?? $data['title'],  
165 - 'url' => getImageUrl($item['url']),  
166 - ];  
167 - }  
168 - return null; // 返回 null 让 array_filter 去除  
169 - }, $info['gallery']));  
170 - $data['images'] = array_merge($data['images'],$images);  
171 - }  
172 - return $data;  
173 - }  
174 - }  
175 -  
176 - /**  
177 - * @remark :组装缺少图片数据-推送至发送平台  
178 - * @name :send_video  
179 - * @author :lyh  
180 - * @method :post  
181 - * @time :2025/8/2 10:37  
182 - */  
183 - public function auto_send_video(){  
184 - $number = Redis::get('ai_video_image') ?? 0;  
185 - $aiVideoAutoLogModel = new AiVideoAutoLog();  
186 - while (true){  
187 - if($number > 5){  
188 - echo date('Y-m-d H:i:s').':当前生成图片数量已达到最大限度。'.$number.PHP_EOL;  
189 - sleep(300);  
190 - continue;  
191 - }  
192 - $item = $aiVideoAutoLogModel->read(['status'=>0,'trigger_id'=>null]);  
193 - if($item === false){  
194 - sleep(60);  
195 - continue;  
196 - }  
197 - if(count($item['images']) < 6){  
198 - echo date('Y-m-d H:i:s').':提交生成图片。'.$item['project_id'].PHP_EOL;  
199 - //需要生成图片  
200 - $content = "{$item['remark']}{$item['title']}4K,高清 --no logo --ar 16:9";  
201 - $midJourneyService = new MidJourneyService();  
202 - $result = $midJourneyService->imagine($content);  
203 - if($result && !empty($result['trigger_id'])){  
204 - echo '提交的数据详情。'.json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES).$item['project_id'].PHP_EOL;  
205 - Redis::incr('ai_video_image');  
206 - $aiVideoAutoLogModel->edit(['trigger_id'=>$result['trigger_id']],['id'=>$item['id']]);  
207 - }  
208 - }else{  
209 - //提交到待执行  
210 - $aiVideoAutoLogModel->edit(['status'=>1],['id'=>$item['id']]);  
211 - }  
212 - }  
213 - }  
214 -  
215 - /**  
216 - * @remark :状态为1的数据推送至生成视频任务表  
217 - * @name :auto_save_video_task  
218 - * @author :lyh  
219 - * @method :post  
220 - * @time :2025/8/4 9:39  
221 - */  
222 - public function auto_save_video_task(){  
223 - $aiVideoAutoLogModel = new AiVideoAutoLog();  
224 - while (true){  
225 - //获取任务id  
226 - $task_id = $this->getAutoTaskId();  
227 - if(empty($task_id)){  
228 - sleep(300);  
229 - continue;  
230 - }  
231 - $info = $aiVideoAutoLogModel->read(['id'=>$task_id]);  
232 - if($info === false){  
233 - $this->output(date('Y-m-d H:i:s').':当前数据不存在或已被删除'.$task_id);  
234 - continue;  
235 - }  
236 - try {  
237 - $aiVideoTaskModel = new AiVideoTask();  
238 - $aiVideoService = new AiVideoService($info['project_id']);  
239 - $projectModel = new DeployOptimize();  
240 - $video_setting = $projectModel->getValue(['project_id'=>$info['project_id']],'video_setting');  
241 - $frequency_setting = $projectModel->getValue(['project_id'=>$info['project_id']],'send_ai_video_frequency');  
242 - $storage = $aiVideoTaskModel->videoSetting()[$video_setting ?? 1];  
243 - $frequency = $aiVideoTaskModel->videoFrequency()[$frequency_setting ?? 1];  
244 - $frequencyArr = explode('-',$frequency);  
245 - if($storage == 'YOUTUBE'){  
246 - //查看是否有ayr账号  
247 - $ayrModel = new AyrShare();  
248 - $ayrInfo = $ayrModel->read(['project_id'=>$this->param['project_id'],'bind_platforms'=>['like','%"youtube"%'],'profile_key'=>['!=',null]]);  
249 - if($ayrInfo !== false){  
250 - $ayrshare_profile_key = $ayrInfo['profile_key'];  
251 - }  
252 - }  
253 - $result = $aiVideoService->createTask($info['title'],$info['remark'],array_slice($info['images'], 0, 8),[],$storage,$ayrshare_profile_key ?? '');  
254 - if($result['status'] == 200){  
255 - $next_auto_date = date('Y-m-d', strtotime('+' . mt_rand($frequencyArr[0] ?? 5,$frequencyArr[1] ?? 7) . 'days')); //每5-7天自动发布  
256 - $aiVideoTaskModel->addReturnId(['next_auto_date'=>$next_auto_date,'task_id'=>$result['data']['task_id'],'project_id'=>$info['project_id'],'storage'=>$storage]);  
257 - ProjectServer::useProject($info['project_id']);  
258 - $aiVideoModel = new AiVideo();  
259 - $aiVideoModel->addReturnId(['title'=>$info['title'],'task_id'=>$result['data']['task_id'],'description'=>$info['remark'],'project_id'=>$info['project_id'],'images'=>json_encode($info['images'],true),'anchor'=>json_encode([],true)]);  
260 - DB::disconnect('custom_mysql');  
261 - $aiVideoAutoLogModel->edit(['status'=>2],['id'=>$info['id']]);  
262 - }else{  
263 - $aiVideoAutoLogModel->edit(['status'=>3],['id'=>$info['id']]);  
264 - }  
265 - }catch (\Exception $e){  
266 - $this->output( date('Y-m-d H:i:s').':当前数据不存在或已被删除'.$task_id);  
267 - continue;  
268 - }  
269 - }  
270 - }  
271 -  
272 - /**  
273 - * @remark :火锅自动发布任务id  
274 - * @name :getAutoTaskId  
275 - * @author :lyh  
276 - * @method :post  
277 - * @time :2025/8/4 9:44  
278 - */  
279 - public function getAutoTaskId()  
280 - {  
281 - $task_id = Redis::rpop('auto_ai_video_task');  
282 - if (empty($task_id)) {  
283 - $aiVideoAutoLogModel = new AiVideoAutoLog();  
284 - $ids = $aiVideoAutoLogModel->formatQuery(['status'=>1])->pluck('id');  
285 - if(!empty($ids)){  
286 - foreach ($ids as $id) {  
287 - Redis::lpush('auto_ai_video_task', $id);  
288 - }  
289 - }  
290 - $task_id = Redis::rpop('auto_ai_video_task');  
291 - }  
292 - return $task_id;  
293 - }  
294 -  
295 - /**  
296 - * @remark :页面获取  
297 - * @name :getAiVideoParam  
298 - * @author :lyh  
299 - * @method :post  
300 - * @time :2025/8/1 16:25  
301 - */  
302 - public function getAiVideoParam($project_id)  
303 - {  
304 - //获取当前网站域名  
305 - $domainModel = new DomainInfo();  
306 - $domain = $domainModel->getValue(['project_id'=>$project_id],'domain');  
307 - if(empty($domain)){  
308 - return true;  
309 - }  
310 - $domain = str_replace('blog.', 'www.', $domain);  
311 - //todo::看是否获取建站的产品数据  
312 - try {  
313 - $sitemap_url = 'https://' . $domain . '/sitemap_post_tag.xml';  
314 - $sitemap_string = file_get_contents($sitemap_url);  
315 - $xml = new \SimpleXMLElement($sitemap_string);  
316 - $json = json_encode($xml);  
317 - $array = json_decode($json, true);  
318 - $urls = array_column($array['url'], 'loc');  
319 - $num = 0;  
320 - if ($num >= 10) {  
321 - return false;  
322 - }  
323 - AGAIN:  
324 - $url = $urls[array_rand($urls)];  
325 - $dom = file_get_html($url);  
326 - $h1 = $dom->find('.layout .global_section h1', 0);  
327 - $title = $h1 ? trim($h1->plaintext) : '';  
328 - $p = $dom->find('.layout .global_section p', 0);  
329 - $content = $p ? trim($p->plaintext) : '';  
330 - $img = $dom->find('.layout .global_section img');  
331 - $images = [];  
332 - foreach ($img as $item) {  
333 - if (empty($item->src) || empty($item->alt)){  
334 - continue;  
335 - }  
336 - array_push($images, ['url' => $item->src, 'alt' => $item->alt]);  
337 - }  
338 - if (empty($title) || empty($content) || empty($images)) {  
339 - $num++;  
340 - goto AGAIN;  
341 - }  
342 - return ['title'=>$title,'remark'=>$content,'images'=>$images];  
343 - } catch (\Exception $e) {  
344 - $this->output('project_id: ' . $project_id . ', domain: ' . $domain . ', error: ' . $e->getMessage());  
345 - echo 'project_id: ' . $project_id . ', domain: ' . $domain . ', error: ' . $e->getMessage() . PHP_EOL;  
346 - return [];  
347 - }  
348 - }  
349 -  
350 - /**  
351 - * @remark :日志  
352 - * @name :output  
353 - * @author :lyh  
354 - * @method :post  
355 - * @time :2025/8/1 15:28  
356 - */  
357 - public function output($message)  
358 - {  
359 - Log::channel('ai_video')->info($message);  
360 - echo date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;  
361 - }  
362 -}  
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 :AiBlogListProjectTask  
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 -}  
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :AiVideoTask.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2025/4/30 11:18  
8 - */  
9 -  
10 -namespace App\Console\Commands\Ai;  
11 -  
12 -use App\Helper\Arr;  
13 -use App\Models\Ai\AiBlogAuthor;  
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;  
20 -use App\Models\Project\AiVideoTask as AiVideoTaskModel;  
21 -use App\Models\Project\Project;  
22 -use App\Models\RouteMap\RouteMap;  
23 -use App\Services\AiBlogService;  
24 -use App\Services\AiVideoService;  
25 -use App\Services\DingService;  
26 -use App\Services\ProjectServer;  
27 -use Illuminate\Console\Command;  
28 -use Illuminate\Support\Facades\DB;  
29 -use Illuminate\Support\Facades\Redis;  
30 -  
31 -class AiVideoTask extends Command  
32 -{  
33 - /**  
34 - * The name and signature of the console command.  
35 - *  
36 - * @var string  
37 - */  
38 - protected $signature = 'save_ai_video';  
39 -  
40 - public $updateProject = [];//需更新的列表  
41 - public $routes = [];//需要更新的路由  
42 - /**  
43 - * The console command description.  
44 - *  
45 - * @var string  
46 - */  
47 - protected $description = '查询ai_video是否已经生成';  
48 - /**  
49 - * @return bool  
50 - * @throws \Exception  
51 - */  
52 - public function handle(){  
53 - while (true){  
54 - //获取任务id  
55 - $task_id = $this->getTaskId();  
56 - if(empty($task_id)){  
57 - sleep(300);  
58 - continue;  
59 - }  
60 - $this->_action($task_id);  
61 - }  
62 - return true;  
63 - }  
64 -  
65 - /**  
66 - * 获取任务id  
67 - * @param int $finish_at  
68 - * @return mixed  
69 - */  
70 - public function getTaskId($finish_at = 2)  
71 - {  
72 - $task_id = Redis::rpop('ai_video_task');  
73 - if (empty($task_id)) {  
74 - if(!empty($this->updateProject)){  
75 - $this->updateProject($this->updateProject);  
76 - $this->updateProject = [];  
77 - }  
78 - if(!empty($this->routes)){  
79 - $this->updateRoutes($this->routes);  
80 - $this->routes = [];  
81 - }  
82 - $aiVideoTaskModel = new AiVideoTaskModel();  
83 - $finish_at = date('Y-m-d H:i:s', strtotime('-' . $finish_at . ' hour'));  
84 - $ids = $aiVideoTaskModel->formatQuery(['status'=>$aiVideoTaskModel::STATUS_RUNNING,'updated_at'=>['<=',$finish_at]])->pluck('id');  
85 - if(!empty($ids)){  
86 - foreach ($ids as $id) {  
87 - Redis::lpush('ai_video_task', $id);  
88 - }  
89 - }  
90 - $task_id = Redis::rpop('ai_video_task');  
91 - }  
92 - return $task_id;  
93 - }  
94 -  
95 - /**  
96 - * @remark :请求  
97 - * @name :sendRequest  
98 - * @author :lyh  
99 - * @method :post  
100 - * @time :2025/4/30 11:31  
101 - */  
102 - public function _action($task_id){  
103 - $aiVideoTaskModel = new AiVideoTaskModel();  
104 - $item = $aiVideoTaskModel->read(['id'=>$task_id]);  
105 - $this->output('ai_video->start:project ID: ' . $item['project_id'] . ',task ID: ' . $task_id);  
106 - $aiVideoService = new AiVideoService($item['project_id']);  
107 - $aiVideoService->task_id = $item['task_id'];  
108 - //拉取文章数据  
109 - $result = $aiVideoService->getVideoDetail();  
110 - if(empty($result['status']) || ($result['status'] != 200)){  
111 - if($item['number'] < 5){  
112 - $aiVideoTaskModel->edit(['number'=>$item['number'] + 1],['id'=>$item['id']]);  
113 - }else{  
114 - $aiVideoTaskModel->edit(['status'=>9],['id'=>$item['id']]);  
115 - // 钉钉通知  
116 - $dingService = new DingService();  
117 - $body = [  
118 - 'keyword' => 'AI_VIDEO获取失败',  
119 - 'msg' => '任务ID:' . $item['task_id'] . PHP_EOL . '返回信息:' . json_encode($result,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),  
120 - 'isAtAll' => false, // 是否@所有人  
121 - ];  
122 - $dingService->handle($body);  
123 - }  
124 - $this->output('error: 数据获取失败,status:' . $result['status'] . ',message: ' . ($result['message'] ?? 'null'));  
125 - return false;  
126 - }  
127 - //保存当前项目ai_blog数据  
128 - ProjectServer::useProject($item['project_id']);  
129 - $aiVideoModel = new AiVideo();  
130 - $aiVideoInfo = $aiVideoModel->read(['task_id'=>$item['task_id']],['id','route']);  
131 - if($aiVideoInfo === false){  
132 - // 钉钉通知  
133 - $dingService = new DingService();  
134 - $body = [  
135 - 'keyword' => 'AI_VIDEO生成错误',  
136 - 'msg' => '任务ID:' . $item['task_id'] . ', 子库获取数据失败, 检查子库数据是否被删除!',  
137 - 'isAtAll' => false, // 是否@所有人  
138 - ];  
139 - $dingService->handle($body);  
140 - $this->output('error: 子库获取数据失败, task id: ' . $task_id);  
141 - $aiVideoTaskModel->edit(['status'=>9],['id'=>$item['id']]);  
142 - DB::disconnect('custom_mysql');  
143 - return false;  
144 - }  
145 - //拿到返回的路由查看是否重复  
146 - $route = RouteMap::setRoute($result['data']['url'], RouteMap::SOURCE_AI_VIDEO, $aiVideoInfo['id'], $item['project_id']);  
147 - if($route != $result['data']['url']){  
148 - $aiVideoService->updateDetail(['url'=>$route,'task_id'=>$item['task_id']]);  
149 - }  
150 - $saveData = [  
151 - 'title'=>$result['data']['title'],  
152 - 'image'=>$result['data']['thumb'],  
153 - 'video_url'=>$result['data']['video_url'],  
154 - 'route'=>$route,  
155 - 'author_id'=>$result['data']['author_id'],  
156 - 'keyword'=>json_encode($result['data']['keyword'],true),  
157 - 'content'=>$result['data']['content'],  
158 - 'text'=>$result['data']['section'],  
159 - 'status'=>$aiVideoTaskModel::STATUS_FINISH,  
160 - 'seo_title'=>$result['data']['title'],  
161 - 'seo_keyword'=>implode(',',$result['data']['keyword']),  
162 - 'seo_description'=>$result['data']['description'] ?? '',  
163 - ];  
164 - $aiVideoModel->edit($saveData,['task_id'=>$item['task_id']]);  
165 - //需要更新的路由  
166 - if (!in_array($result['data']['author_id'], $this->updateProject[$item['project_id']] ?? [])) {  
167 - $this->updateProject[$item['project_id']][] = $result['data']['author_id'];  
168 - }  
169 - if (!in_array($route, $this->routes[$item['project_id']] ?? [])) {  
170 - $this->routes[$item['project_id']][] = $route;  
171 - }  
172 - DB::disconnect('custom_mysql');  
173 - $aiVideoTaskModel->edit(['status'=>$aiVideoTaskModel::STATUS_FINISH],['id'=>$item['id']]);  
174 - $this->output('success: task id: ' . $task_id);  
175 - return true;  
176 - }  
177 -  
178 - /**  
179 - * @remark :更新项目作者页面及列表页  
180 - * @name :updateProject  
181 - * @author :lyh  
182 - * @method :post  
183 - * @time :2025/4/30 15:43  
184 - */  
185 - public function updateProject($updateProject){  
186 - if(empty($updateProject)){  
187 - return true;  
188 - }  
189 - foreach ($updateProject as $project_id => $author){  
190 - ProjectServer::useProject($project_id);  
191 - $this->output('sync: list start, project_id: ' . $project_id);  
192 - $this->updateBlogList($project_id);  
193 - $this->output('sync: list end');  
194 - //更新作者  
195 - $this->output('sync: author start, project_id: ' . $project_id);  
196 - foreach ($author as $val){  
197 - $this->updateAiBlogAuthor($val,$project_id);  
198 - }  
199 - $this->output('sync: author end');  
200 - DB::disconnect('custom_mysql');  
201 - }  
202 -  
203 - return true;  
204 - }  
205 -  
206 - /**  
207 - * @remark :更新作者页面  
208 - * @name :updateAiBlogAuthor  
209 - * @author :lyh  
210 - * @method :post  
211 - * @time :2025/4/30 15:52  
212 - */  
213 - public function updateAiBlogAuthor($author_id,$project_id){  
214 - if(empty($author_id)){  
215 - return true;  
216 - }  
217 - $aiBlogService = new AiBlogService($project_id);  
218 - $aiBlogService->author_id = $author_id;  
219 - $result = $aiBlogService->getAuthorDetail();  
220 - if(isset($result['status']) && $result['status'] == 200){  
221 - //当前作者的页面  
222 - $aiBlogAuthorModel = new AiBlogAuthor();  
223 - $authorInfo = $aiBlogAuthorModel->read(['author_id'=>$author_id],['id','route']);  
224 - if($authorInfo !== false && !empty($result['data']['section'])){  
225 - //需要更新的路由  
226 - if (!in_array($authorInfo['route'], $this->routes[$project_id] ?? [])) {  
227 - $this->routes[$project_id][] = $authorInfo['route'];  
228 - }  
229 - $aiBlogAuthorModel->edit(['text'=>$result['data']['section']],['author_id'=>$author_id]);  
230 - }  
231 - }  
232 - return true;  
233 - }  
234 -  
235 - /**  
236 - * @remark :更新  
237 - * @name :updateBlogList  
238 - * @author :lyh  
239 - * @method :post  
240 - * @time :2025/4/30 15:45  
241 - */  
242 - public function updateBlogList($project_id){  
243 - $aiVideoService = new AiVideoService($project_id);  
244 - $page = 1;  
245 - $saveData = [];  
246 - $result = $aiVideoService->getAiVideoList($page,15);  
247 - if(!isset($result['status']) && $result['status'] != 200){  
248 - return true;  
249 - }  
250 - $total_page = $result['data']['total_page'];  
251 - //组装数据保存  
252 - $saveData[] = [  
253 - 'route'=>$page,  
254 - 'text'=>$result['data']['section'],  
255 - ];  
256 - while ($total_page > $page){  
257 - $page++;  
258 - $result = $aiVideoService->getAiVideoList($page,15);  
259 - if(isset($result['status']) && $result['status'] == 200){  
260 - $saveData[] = [  
261 - 'route'=>$page,  
262 - 'text'=>$result['data']['section'],  
263 - ];  
264 - }  
265 - }  
266 - $aiVideoListModel = new AiVideoList();  
267 - if(!empty($saveData)){  
268 - //写一条路由信息  
269 - RouteMap::setRoute('top-video',RouteMap::SOURCE_AI_VIDEO_LIST,0,$project_id);//写一条列表页路由  
270 - $aiVideoListModel->truncate();  
271 - $aiVideoListModel->insertAll($saveData);  
272 - }  
273 - return true;  
274 - }  
275 - /**  
276 - * 输入日志  
277 - * @param $message  
278 - * @return bool  
279 - */  
280 - public function output($message)  
281 - {  
282 - $message = date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;  
283 - echo $message;  
284 - return true;  
285 - }  
286 -  
287 - /**  
288 - * 通知C端生成界面  
289 - * @param $project_id  
290 - * @return bool  
291 - */  
292 - public function updateRoutes($routes){  
293 - $domainModel = new DomainInfo();  
294 - $project_model = new Project();  
295 - foreach ($routes as $project_id => $route){  
296 - $route[] = 'top-video';  
297 - $domain = $domainModel->getProjectIdDomain($project_id);  
298 - if (empty($domain)) {  
299 - $this->output('send: 域名不存在, project id: ' . $project_id);  
300 - continue;  
301 - }  
302 - //判断是否是自建站服务器,如果是,不请求C端接口,数据直接入库  
303 - $project_info = $project_model->read(['id'=>$project_id],['serve_id']);  
304 - if(!$project_info){  
305 - $this->output('send: 项目不存在, project id: ' . $project_id);  
306 - continue;  
307 - }  
308 - $serve_ip_model = new ServersIp();  
309 - $serve_ip_info = $serve_ip_model->read(['id'=>$project_info['serve_id']],['servers_id']);  
310 - $servers_id = $serve_ip_info ? $serve_ip_info['servers_id'] : 0;  
311 - if($servers_id == ServerConfig::SELF_SITE_ID){  
312 - //判断是否已有更新进行中  
313 - $notify_model = new Notify();  
314 - $data = [  
315 - 'project_id' => $project_id,  
316 - 'type' => Notify::TYPE_MASTER,  
317 - 'route' => Notify::ROUTE_AI_BLOG,  
318 - 'server_id' => ServerConfig::SELF_SITE_ID,  
319 - 'status' => ['!=',Notify::STATUS_FINISH_SITEMAP]  
320 - ];  
321 - $notify = $notify_model->read($data,['id']);  
322 - if(!$notify){  
323 - $domain_array = parse_url($domain);  
324 - $data['data'] = Arr::a2s(['domain'=>$domain_array['host'],'url'=>$route,'language'=>[]]);  
325 - $data['status'] = Notify::STATUS_INIT;  
326 - $data['sort'] = 2;  
327 - $notify_model->add($data);  
328 - }  
329 - $this->output('send: 自建站项目, project id: ' . $project_id);  
330 - }else{  
331 - $c_url = $domain.'api/update_page/';  
332 - $param = [  
333 - 'project_id' => $project_id,  
334 - 'type' => 1,  
335 - 'route' => 3,  
336 - 'url' => $route,  
337 - 'language'=> [],  
338 - 'is_sitemap' => 0  
339 - ];  
340 - $res = http_post($c_url, json_encode($param,true));  
341 - $this->output('notify: project id: ' . $project_id . ', result: ' . json_encode($res,JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));  
342 - }  
343 - }  
344 - return true;  
345 - }  
346 -}  
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :AuthorityScore.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2025/7/1 16:43  
8 - */  
9 -  
10 -namespace App\Console\Commands\AuthorityScore;  
11 -  
12 -use App\Models\AuthorityScore\AuthorityScore as AuthorityScoreModel;  
13 -use App\Models\Domain\DomainInfo;  
14 -use App\Models\Project\Project;  
15 -use Illuminate\Console\Command;  
16 -  
17 -class AuthorityScore extends Command  
18 -{  
19 - /**  
20 - * The name and signature of the console command.  
21 - *  
22 - * @var string  
23 - */  
24 - protected $signature = 'authority_score';  
25 -  
26 - /**  
27 - * The console command description.  
28 - *  
29 - * @var string  
30 - */  
31 - protected $description = '白帽外链数据详情,每月统计一次';  
32 -  
33 - /**  
34 - * @remark :执行方法  
35 - * @name :handle  
36 - * @author :lyh  
37 - * @method :post  
38 - * @time :2025/7/1 16:46  
39 - */  
40 - public function handle(){  
41 - $projectModel = new Project();  
42 - $projectIdArr = $projectModel->selectField(['project_type'=>1,'delete_status' => 0,'extend_type'=>0,'type'=>2],'id');  
43 - $domainModel = new DomainInfo();  
44 - $url = 'https://www.cmer.site/api/domain/organic?domain=';  
45 - foreach ($projectIdArr as $item){  
46 - $domainInfo = $domainModel->read(['project_id'=>$item],['domain']);  
47 - if($domainInfo === false){  
48 - continue;  
49 - }  
50 - echo '执行的项目id'.$item.PHP_EOL;  
51 - $urls = $url.$domainInfo['domain'];  
52 - echo $urls.PHP_EOL;  
53 - $data = http_get($urls);  
54 - if(!empty($data) && !empty($data['data'])){  
55 - echo json_encode($data).PHP_EOL;  
56 - $data = $data['data'];  
57 - $this->saveHandleData($data,$item);  
58 - }  
59 - }  
60 - return true;  
61 - }  
62 -  
63 - /**  
64 - * @remark :保存数据  
65 - * @name :handleData  
66 - * @author :lyh  
67 - * @method :post  
68 - * @time :2025/7/1 17:23  
69 - */  
70 - public function saveHandleData($data,$project_id){  
71 - $authorityScoreModel = new AuthorityScoreModel();  
72 - return $authorityScoreModel->addReturnId([  
73 - 'project_id'=>$project_id,  
74 - 'ascore'=>(int)($data['ascore'] ?? 0),  
75 - 'total'=>(int)($data['total'] ?? 0),  
76 - 'domains_num'=>(int)($data['domains_num'] ?? 0),  
77 - 'rank'=>(int)($data['Rank'] ?? 0),  
78 - 'organic_keywords'=>(int)($data['Organic_Keywords'] ?? 0),  
79 - 'organic_traffic'=>(int)($data['Organic_Traffic'] ?? 0),  
80 - 'date'=>date('Y-m-d')  
81 - ]);  
82 - }  
83 -}  
1 -<?php  
2 -  
3 -namespace App\Console\Commands\AyrShare;  
4 -  
5 -use App\Helper\AyrShare as AyrShareHelper;  
6 -use App\Models\AyrShare\AyrShare as AyrShareModel;  
7 -use Illuminate\Console\Command;  
8 -  
9 -class ShareConfig extends Command  
10 -{  
11 - public $error = 0;  
12 - /**  
13 - * The name and signature of the console command.  
14 - *  
15 - * @var string  
16 - */  
17 - protected $signature = 'share_config';  
18 -  
19 - /**  
20 - * The console command description.  
21 - *  
22 - * @var string  
23 - */  
24 - protected $description = '更新用户Ayr_share配置';  
25 - /**  
26 - * @name :(定时执行更新用户配置)handle  
27 - * @author :lyh  
28 - * @method :post  
29 - * @time :2023/5/12 14:48  
30 - */  
31 - public function handle()  
32 - {  
33 - $ayrShareModel = new AyrShareModel();  
34 - //更新用户配置  
35 - $lists = $ayrShareModel->lists($this->map,$this->page,$this->row,'id',['id','profile_key','bind_plat_from']);  
36 - foreach ($lists['list'] as $k => $v){  
37 - if(empty($v['profile_key'])){  
38 - continue;  
39 - }  
40 - //获取当前用户配置  
41 - $ayrShareHelper = new AyrShareHelper();  
42 - $share_info = $ayrShareHelper->get_profiles_users($v['profile_key']);  
43 - if(!isset($share_info['activeSocialAccounts'])){  
44 - $ayrShareModel->edit(['bind_plat_from'=>''],['id'=>$v['id']]);  
45 - continue;  
46 - }  
47 - $str = json_encode($share_info['activeSocialAccounts']);  
48 - if($str != $v['bind_plat_from']){  
49 - $rs = $ayrShareModel->edit(['bind_plat_from'=>$str],['id'=>$v['id']]);  
50 - if($rs === false){  
51 - $this->error++;  
52 - }  
53 - }  
54 - }  
55 - echo $this->error;  
56 - }  
57 -}  
1 -<?php  
2 -  
3 -namespace App\Console\Commands\AyrShare;  
4 -use App\Helper\AyrShare as AyrShareHelper;  
5 -use App\Models\Ai\AiVideo;  
6 -use App\Models\AyrShare\AyrRelease as AyrReleaseModel;  
7 -use App\Models\Project\AiVideoTask;  
8 -use App\Services\ProjectServer;  
9 -use Carbon\Carbon;  
10 -use App\Models\AyrShare\AyrShare as AyrShareModel;  
11 -use Illuminate\Console\Command;  
12 -use Illuminate\Support\Facades\DB;  
13 -  
14 -class ShareUser extends Command  
15 -{  
16 - public $error = 0;  
17 - /**  
18 - * The name and signature of the console command.  
19 - *  
20 - * @var string  
21 - */  
22 - protected $signature = 'share_user';  
23 -  
24 - /**  
25 - * The console command description.  
26 - *  
27 - * @var string  
28 - */  
29 - protected $description = '用户一周内无记录清除Ayr_share';  
30 - /**  
31 - * @name :(定时执行)handle  
32 - * @author :lyh  
33 - * @method :post  
34 - * @time :2023/5/12 14:48  
35 - */  
36 - public function handle()  
37 - {  
38 - $this->output('start');  
39 - $this->user_operator_record();  
40 - return true;  
41 - }  
42 -  
43 - /**  
44 - * @name : 检测用户是否无操作记录  
45 - * @author :lyh  
46 - * @method :post  
47 - * @time :2023/5/12 14:55  
48 - */  
49 - protected function user_operator_record(){  
50 - //获取所有ayr_share用户  
51 - $ayr_share_model = new AyrShareModel();  
52 - $ayr_release = new AyrReleaseModel();  
53 - $ayr_share_list = $ayr_share_model->list(['profile_key'=>['!=','']]);  
54 - foreach ($ayr_share_list as $v){  
55 - $this->output('执行数据的邮箱--'.$v['title']);  
56 - $time = Carbon::now()->modify('-1 days')->toDateString();  
57 - //创建时间小于7天前的当前时间  
58 - if($v['created_at'] > $time){  
59 - $this->output('创建时间小于7天跳过--'.$v['title']);  
60 - continue;  
61 - }  
62 - //查询当前用户是否有未推送的博文  
63 - $release_info = $this->release_info($ayr_release,$v);  
64 - //有推文时,直接跳出循环  
65 - if($release_info !== false){  
66 - $this->output('有未推送的推文直接跳过--'.$v['title']);  
67 - continue;  
68 - }  
69 - //查询7天是否发送博文  
70 - $release_info = $this->release_seven_info($ayr_release,$v);  
71 - //有发送博文,则跳出循环  
72 - if($release_info !== false){  
73 - $this->output('7天内有推文跳过--'.$v['title']);  
74 - continue;  
75 - }  
76 - $aiVideoInfo = $this->aiVideoInfo($v['project_id'] ?? 0);  
77 - if($aiVideoInfo !== false){  
78 - $this->output('7天内有ai视频推送跳过--'.$v['title']);  
79 - continue;  
80 - }  
81 - //删除用户第三方配置  
82 - if(!empty($v['profile_key'])){  
83 - $res = $this->del_profiles($v);  
84 - if($res === false){  
85 - continue;  
86 - }  
87 - }  
88 - //更新数据库  
89 - $this->save_ayr_share($ayr_share_model,$v);  
90 - }  
91 - return $this->error;  
92 - }  
93 -  
94 - /**  
95 - * @name :(删除第三方配置)del_profiles  
96 - * @author :lyh  
97 - * @method :post  
98 - * @time :2023/6/14 16:10  
99 - */  
100 - public function del_profiles($v){  
101 - $ayr_share_helper = new AyrShareHelper();  
102 - $data_profiles = [  
103 - 'title'=>$v['title'],  
104 - 'profileKey'=>$v['profile_key']  
105 - ];  
106 - $res = $ayr_share_helper->deleted_profiles($data_profiles);  
107 - if($res['status'] == 'fail'){  
108 - $this->output('第三方删除失败'.json_encode($data_profiles,true));  
109 - return false;  
110 - }  
111 - return true;  
112 - }  
113 -  
114 - /**  
115 - * @name :(更新数据库)save_ayr_share  
116 - * @author :lyh  
117 - * @method :post  
118 - * @time :2023/6/14 16:14  
119 - */  
120 - public function save_ayr_share(&$ayr_share_model,$v){  
121 -  
122 - //更新数据库  
123 - $data = [  
124 - 'title'=>'',  
125 - 'bind_platforms'=>'',  
126 - 'profile_key'=>'',  
127 - 'ref_id'=>'',  
128 - ];  
129 - $res = $ayr_share_model->edit($data,['id'=>$v['id']]);  
130 - if($res == false){  
131 - echo '更新数据库失败';  
132 - return true;  
133 - }  
134 - return true;  
135 - }  
136 -  
137 - /**  
138 - * @name :(查询是否有定时发送报文)info  
139 - * @author :lyh  
140 - * @method :post  
141 - * @time :2023/6/14 16:17  
142 - */  
143 - public function release_info(&$ayr_release,$v){  
144 - //查询当前用户是否有未推送的博文  
145 - $release_info = $ayr_release->read(['schedule_date'=>['>',date('Y-m-d H:i:s',time())],'share_id'=>$v['id']]);  
146 - return $release_info;  
147 - }  
148 -  
149 - /**  
150 - * @param $ayr_release  
151 - * @name :7天内无发送记录release_seven_info  
152 - * @author :lyh  
153 - * @method :post  
154 - * @time :2023/6/14 16:28  
155 - */  
156 - public function release_seven_info(&$ayr_release,$v){  
157 - //查看用户是否在一周内有发送博客  
158 - $start_at = Carbon::now()->modify('-7 days')->toDateString();  
159 - $end_at = Carbon::now()->toDateString();  
160 - $release_info = $ayr_release->read(['created_at'=>['between',[$start_at,$end_at]],'share_id'=>$v['id']]);  
161 - return $release_info;  
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 - }  
182 -  
183 - /**  
184 - * 输入日志  
185 - * @param $message  
186 - * @return bool  
187 - */  
188 - public function output($message)  
189 - {  
190 - $message = date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;  
191 - echo $message;  
192 - file_put_contents(storage_path('logs/share_user/') . date('Ymd') . '.log', $message, FILE_APPEND);  
193 - return true;  
194 - }  
195 -}  
1 -<?php  
2 -  
3 -namespace App\Console\Commands;  
4 -  
5 -  
6 -use Illuminate\Console\Command;  
7 -  
8 -/**  
9 - * TODO:: 如果想要在终止 任务时不让数据丢失或者异常,请使用此类  
10 - * @author:dc  
11 - * @time 2023/8/21 11:03  
12 - * Class CmdSignal  
13 - * @package App\Console\Commands  
14 - */  
15 -trait CmdSignal  
16 -{  
17 -  
18 - /**  
19 - * 是否停止  
20 - * @var bool  
21 - */  
22 - public $isStop = false;  
23 -  
24 - /**  
25 - * 超时未退出,强制退出 暂时未实现  
26 - * @var int  
27 - */  
28 - public $stopTimeOut = 30;  
29 -  
30 -  
31 - public $debugLogFile = null;  
32 -  
33 - /**  
34 - * 调试输出  
35 - * @param $msg  
36 - * @author:dc  
37 - * @time 2023/8/21 11:22  
38 - */  
39 - public function debug_echo($msg){  
40 - if($this->debugLogFile){  
41 - @file_put_contents($this->debugLogFile,date('Y-m-d H:i:s')." ===> ".print_r($msg,1).PHP_EOL,FILE_APPEND);  
42 - }else{  
43 - echo date('Y-m-d H:i:s')." ===> ".print_r($msg,1).PHP_EOL;  
44 - }  
45 - }  
46 -  
47 - /**  
48 - * @return bool  
49 - */  
50 - public function handle()  
51 - {  
52 -  
53 - if($this->isRunning()){  
54 - $this->debug_echo('脚本已运行,请无重复运行');  
55 - return 1;  
56 - }  
57 -  
58 - $this->debug_echo('已启动脚本');  
59 -  
60 - // 启动时  
61 - if(method_exists($this,'init')){  
62 - $this->init();  
63 - }  
64 -  
65 -// 注册信号处理程序  
66 -// SIGHUP:终端控制进程时终止或挂起进程  
67 -//SIGINT:中断进程(通常由CTRL+C发出)  
68 -//SIGQUIT:退出进程并生成核心转储  
69 -//SIGILL:非法指令  
70 -//SIGABRT:由调试程序触发的异常终止信号  
71 -//SIGFPE:浮点异常  
72 -//SIGKILL:无条件终止进程  
73 -//SIGSEGV:无效的内存引用  
74 -//SIGPIPE:写入已关闭的FIFO或套接字时产生的信号  
75 -//SIGTERM:要求终止进程的信号  
76 -//SIGUSR1:用户定义的信号1  
77 -//SIGUSR2:用户定义的信号2  
78 - $handler = function ($signal){  
79 - // 可以处理其他程序  
80 - $this->isStop = true;  
81 - };  
82 - pcntl_signal(SIGTERM, $handler);  
83 - pcntl_signal(SIGINT, $handler);  
84 -// pcntl_signal(SIGHUP, $handler);  
85 -  
86 - // 检查是否接收到信号  
87 - pcntl_signal_dispatch();  
88 -  
89 - $tryNum = 0;  
90 -// 无限循环,模拟进程运行  
91 - while (true) {  
92 - // 做一些工作... 异常超过5次就重启下进程  
93 - if($this->isStop || $tryNum>5){  
94 - break;  
95 - }  
96 -  
97 - try {  
98 - $this->start();  
99 - }catch (\Throwable $e){  
100 - $tryNum++;  
101 - // 保证此程序正常  
102 - $this->debug_echo('异常消息:'.$e->getMessage());  
103 - $this->debug_echo('异常文件:'.$e->getFile().':'.$e->getLine());  
104 - $this->debug_echo($e->getTraceAsString());  
105 - }  
106 -  
107 -  
108 - }  
109 -  
110 - $this->debug_echo('已退出程序');  
111 -  
112 -  
113 - return Command::SUCCESS;  
114 - }  
115 -  
116 -  
117 - /**  
118 - * 获取进程启动名称  
119 - * @return mixed  
120 - * @throws \Exception  
121 - * @author:dc  
122 - * @time 2023/8/21 11:43  
123 - */  
124 - public function getSignature(){  
125 - if(empty($this->signature)){  
126 - throw new \Exception('无法获取到启动命令');  
127 - }  
128 - return $this->signature;  
129 - }  
130 -  
131 - /**  
132 - * 是否已运行  
133 - * @param int $max 最大运行多少进程  
134 - * @return bool  
135 - * @throws \Exception  
136 - * @author:dc  
137 - * @time 2023/8/21 11:54  
138 - */  
139 - public function isRunning($max=1):bool {  
140 -  
141 - $ps = "ps -ef | grep \"artisan ".$this->getSignature()."\" | grep -v grep | wc -l";  
142 -  
143 - $num = exec($ps);  
144 -  
145 - if(property_exists($this,'maxRunNumber')){  
146 - $max = $this->maxRunNumber;  
147 - }  
148 -  
149 - if($num>$max){  
150 - return true;  
151 - }  
152 -  
153 - return false;  
154 - }  
155 -  
156 -  
157 -  
158 -}  
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 -}  
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :AfterDayCount.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2025/3/26 15:28  
8 - */  
9 -  
10 -namespace App\Console\Commands\DayCount;  
11 -  
12 -use App\Models\ASide\APublicModel;  
13 -use App\Models\Channel\Channel;  
14 -use App\Models\Manage\ManageHr;  
15 -use App\Models\Project\Project;  
16 -use App\Models\RankData\RankDataLog;  
17 -use Carbon\Carbon;  
18 -use App\Models\HomeCount\AfterCount as AfterCountModel;  
19 -use Illuminate\Console\Command;  
20 -  
21 -class AfterDayCount extends Command  
22 -{  
23 - /**  
24 - * The name and signature of the console command.  
25 - *  
26 - * @var string  
27 - */  
28 - protected $signature = 'after_count';  
29 -  
30 - protected $managerHrModel;  
31 -  
32 - public $after_manager = [  
33 - 1 => ['许璐','王袁袁'],  
34 - 2 => ['陈思蓓'],  
35 - 3 => ['张国英']  
36 - ];  
37 -  
38 - /**  
39 - * The console command description.  
40 - *  
41 - * @var string  
42 - */  
43 - protected $description = '统计昨日售后数据';  
44 -  
45 - public function handle(){  
46 - echo date('Y-m-d H:i:s').'统计start->'.PHP_EOL;  
47 - $saveData = $this->_action();  
48 - $afterModel = new AfterCountModel();  
49 - //保存数据  
50 - $afterModel->insertAll($saveData);  
51 - echo date('Y-m-d H:i:s').'->统计end'.PHP_EOL;  
52 - return true;  
53 - }  
54 -  
55 - /**  
56 - * @remark :执行方法  
57 - * @name :_action  
58 - * @author :lyh  
59 - * @method :post  
60 - * @time :2025/3/26 15:29  
61 - */  
62 - public function _action(){  
63 - $this->managerHrModel = new ManageHr();  
64 - $projectModel = new Project();  
65 - $rankDataLogModel = new RankDataLog();  
66 - $date = date('Y-m-d');  
67 - $saveData = [];  
68 -// $projectIdArr = $rankDataLogModel->selectField(['is_compliance'=>1,'lang'=>'','date'=>date('Y-m-d', strtotime('-3 months'))],'project_id');//3个月前达标的项目id  
69 - foreach ($this->after_manager as $key => $valM){  
70 - $idArr = $this->managerHrModel->selectField(['name'=>['in',$valM]],'id');  
71 - echo '对应优化师id:'.json_encode($idArr).PHP_EOL;  
72 - $project_count = $projectModel->where('gl_project.extend_type',0)  
73 - ->where('gl_project.delete_status',0)  
74 - ->where('gl_project.old_project_id',0)  
75 - ->where('gl_project_deploy_optimize.start_date','<=',$date)  
76 - ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)  
77 - ->whereIn('gl_project.type',[2,4,6])  
78 - ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')  
79 - ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0")  
80 - ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0")  
81 - ->count();  
82 - $qualified_count = $projectModel->where('gl_project.extend_type',0)  
83 - ->where('gl_project.delete_status',0)  
84 - ->where('gl_project.old_project_id',0)  
85 - ->where('gl_project_deploy_optimize.start_date','<=',$date)  
86 - ->where('gl_project.is_remain_today',1)  
87 - ->where('gl_project_deploy_build.plan','!=',0)  
88 - ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)  
89 - ->whereIn('gl_project.type',[2,4,6])  
90 - ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')  
91 - ->leftJoin('gl_project_deploy_build', 'gl_project.id', '=', 'gl_project_deploy_build.project_id')  
92 - ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0")  
93 - ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0")  
94 - ->count();  
95 - $rate = number_format($qualified_count / $project_count, 2);  
96 - $threeMonthsAgo = date('Y-m', strtotime('-3 months'));  
97 - echo '3个月前的时间:'.$threeMonthsAgo.PHP_EOL;  
98 - $three_project_count = $projectModel->where('gl_project.extend_type',0)  
99 - ->where('gl_project.delete_status',0)  
100 - ->where('gl_project.old_project_id',0)  
101 - ->where('gl_project_deploy_optimize.start_date','>=',$threeMonthsAgo.'-01')  
102 - ->where('gl_project_deploy_optimize.start_date','<=',$threeMonthsAgo.'-31')  
103 - ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)  
104 - ->whereIn('gl_project.type',[2,4,6])  
105 - ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')  
106 - ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0")  
107 - ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0")  
108 - ->count();  
109 - $three_qualified_count = $projectModel->where('gl_project.extend_type',0)  
110 - ->where('gl_project.delete_status',0)  
111 - ->where('gl_project.old_project_id',0)  
112 - ->where('gl_project.is_remain_today',1)  
113 - ->where('gl_project_deploy_optimize.start_date','>=',$threeMonthsAgo.'-01')  
114 - ->where('gl_project_deploy_optimize.start_date','<=',$threeMonthsAgo.'-31')  
115 - ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)  
116 - ->whereIn('gl_project.type',[2,4,6])  
117 - ->where('gl_project_deploy_build.plan','!=',0)  
118 - ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')  
119 - ->leftJoin('gl_project_deploy_build', 'gl_project.id', '=', 'gl_project_deploy_build.project_id')  
120 - ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0")  
121 - ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0")  
122 - ->count();  
123 - if($three_project_count != 0){  
124 - $three_rate = number_format($three_qualified_count / $three_project_count, 2);  
125 - }else{  
126 - $three_rate = 0;  
127 - }  
128 - $data = $projectModel->where('gl_project.extend_type',0)  
129 - ->where('gl_project.delete_status',0)  
130 - ->where('gl_project.old_project_id',0)  
131 - ->where('gl_project_deploy_optimize.start_date','>=',$threeMonthsAgo.'-01')  
132 - ->where('gl_project_deploy_optimize.start_date','<=',$threeMonthsAgo.'-31')  
133 - ->where('gl_project.is_remain_today',1)  
134 - ->whereIn('gl_project_deploy_optimize.optimist_mid',$idArr)  
135 - ->whereIn('gl_project.type',[2,4,6])  
136 - ->leftJoin('gl_project_payment', 'gl_project.id', '=', 'gl_project_payment.project_id')  
137 - ->leftJoin('gl_project_deploy_build', 'gl_project.id', '=', 'gl_project_deploy_build.project_id')  
138 - ->leftJoin('gl_domain_info', 'gl_project.id', '=', 'gl_domain_info.project_id')  
139 - ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')  
140 - ->leftJoin('gl_project_online_check', 'gl_project.id', '=', 'gl_project_online_check.project_id')  
141 - ->whereRaw("FIND_IN_SET('2', gl_project.level) = 0 AND FIND_IN_SET('3', gl_project.level) = 0")  
142 - ->whereRaw("FIND_IN_SET('7', gl_project_deploy_optimize.special) = 0 AND FIND_IN_SET('8', gl_project_deploy_optimize.special) = 0")  
143 - ->select($this->selectParam())->get()->toArray();  
144 - foreach ($data as $k=>$val){  
145 - $this->handleParam($val);  
146 - $data[$k] = $val;  
147 - }  
148 - $saveData[] = [  
149 - 'date'=>date('Y-m-d'),  
150 - 'type'=> $key,  
151 - 'project_count'=>$project_count,  
152 - 'qualified_count'=>$qualified_count,  
153 - 'rate'=>$rate,  
154 - 'three_project_count'=>$three_project_count,  
155 - 'three_qualified_count'=>$three_qualified_count,  
156 - 'three_rate'=>$three_rate,  
157 - 'data' => json_encode($data,true)  
158 - ];  
159 - }  
160 - return $saveData;  
161 - }  
162 -  
163 -  
164 - public function selectParam(){  
165 - $select = [  
166 - 'gl_project.id AS id',  
167 - 'gl_project.title AS title',  
168 - 'gl_project.level AS level',  
169 - 'gl_project.channel AS channel',  
170 - 'gl_project.company AS company',  
171 - 'gl_project.type AS type',  
172 - 'gl_project.created_at AS created_at',  
173 - 'gl_project.is_language AS is_language',  
174 - 'gl_project.cooperate_date AS cooperate_date',  
175 - 'gl_project.finish_remain_day AS finish_remain_day',  
176 - 'gl_project.is_remain_today AS is_remain_today',  
177 - 'gl_project.remain_day AS remain_day',  
178 - 'gl_project.seo_remain_day AS seo_remain_day',  
179 - 'gl_project.robots AS robots',  
180 - 'gl_project.is_minor_languages AS is_minor_languages',  
181 - 'gl_project.is_translate AS is_translate',  
182 - 'gl_project.is_translate_tag AS is_translate_tag',  
183 - 'gl_project.is_upgrade AS is_upgrade',  
184 - 'gl_project.site_status AS site_status',  
185 - 'gl_project_online_check.id AS online_check_id',  
186 - 'gl_project_online_check.question AS question',  
187 - 'gl_project_online_check.go_question AS go_question',  
188 - 'gl_project_online_check.optimist_status AS optimist_status',  
189 - 'gl_project_online_check.qa_status AS qa_status',  
190 - 'gl_project_online_check.updated_at AS online_updated_at',  
191 - 'gl_project_payment.amount AS amount',  
192 - 'gl_project_deploy_build.dept_id AS dept_id',  
193 - 'gl_project_deploy_build.keyword_num AS key',  
194 - 'gl_project_deploy_build.service_duration AS day',  
195 - 'gl_project_deploy_build.leader_mid AS leader_mid',  
196 - 'gl_project_deploy_build.manager_mid AS manager_mid',  
197 - 'gl_project_deploy_build.designer_mid AS designer_mid',  
198 - 'gl_project_deploy_build.tech_mid AS tech_mid',  
199 - 'gl_project_deploy_build.test_domain AS test_domain',  
200 - 'gl_project_deploy_build.plan AS plan',  
201 - 'gl_project_deploy_build.seo_plan AS seo_plan',  
202 - 'gl_project_deploy_optimize.dept_id AS optimize_dept_id',  
203 - 'gl_project_deploy_optimize.manager_mid AS optimize_manager_mid',  
204 - 'gl_project_deploy_optimize.optimist_mid AS optimize_optimist_mid',  
205 - 'gl_project_deploy_optimize.assist_mid AS optimize_assist_mid',  
206 - 'gl_project_deploy_optimize.tech_mid AS optimize_tech_mid',  
207 - 'gl_project_deploy_optimize.design_mid AS design_mid',  
208 - 'gl_project_deploy_optimize.tech_leader AS tech_leader',  
209 - 'gl_project_deploy_optimize.quality_mid AS quality_mid',  
210 - 'gl_project_deploy_optimize.design_mid AS design_mid',  
211 - 'gl_project_deploy_optimize.start_date AS start_date',  
212 - 'gl_project_deploy_optimize.backlink AS backlink',  
213 - 'gl_project_deploy_optimize.ai_video AS ai_video',  
214 - 'gl_project_deploy_optimize.api_no AS api_no',  
215 - 'gl_project_deploy_optimize.first_compliance_time AS first_compliance_time',  
216 - 'gl_domain_info.amp_status AS amp_status',  
217 - 'gl_domain_info.domain AS domain',  
218 - ];  
219 - return $select;  
220 - }  
221 -  
222 - public function handleParam(&$item){  
223 - $data = APublicModel::getNumByProjectId($item['id']);  
224 - $manageModel = new ManageHr();  
225 - $plan = Project::planMap();  
226 - $seo_plan = Project::seoMap();  
227 - $item['plan'] = $plan[$item['plan']] ?? $seo_plan[1];  
228 - $item['channel'] = Channel::getChannelText($item['channel']['user_id'] ?? 0);  
229 - $item['build_leader'] = $manageModel->getName($item['leader_mid']);  
230 - $item['build_manager'] = $manageModel->getName($item['manager_mid']);  
231 - $item['build_designer'] = $manageModel->getName($item['designer_mid']);  
232 - $item['build_tech'] = $manageModel->getName($item['tech_mid']);  
233 - $item['optimize_manager'] = $manageModel->getName($item['optimize_manager_mid']);  
234 - $item['optimize_optimist'] = $manageModel->getName($item['optimize_optimist_mid']);  
235 - $item['optimize_assist'] = $manageModel->getName($item['optimize_assist_mid']);  
236 - $item['optimize_tech'] = $manageModel->getName($item['optimize_tech_mid']);  
237 - $item['quality_mid_name'] = $manageModel->getName($item['quality_mid']);  
238 - $item['created_at'] = date('Y年m月d日', strtotime($item['cooperate_date']));  
239 - $item['autologin_code'] = getAutoLoginCode($item['id']);  
240 - $item['domain'] = 'https://'.$item['domain'].'/';  
241 - if(!empty($item['domain']) && $item['amp_status'] == 1){  
242 - $item['amp_domain'] = str_replace('www','m',$item['domain']);  
243 - }  
244 - $item['product_num'] = $data['product'] ?? 0;  
245 - $item['keyword_num'] = $item['key'] ?? 0;  
246 - $item['inquiry_num'] = $data['inquiry'] ?? 0;  
247 - $item['autologin_code'] = getAutoLoginCode($item['id']);  
248 - return $item;  
249 - }  
250 -}  
1 -<?php  
2 -  
3 -namespace App\Console\Commands\DayCount;  
4 -  
5 -use App\Helper\FormGlobalsoApi;  
6 -use App\Models\Domain\DomainInfo;  
7 -use App\Models\Inquiry\InquiryFormData;  
8 -use App\Models\Project\Project;  
9 -use App\Services\ProjectServer;  
10 -use Carbon\Carbon;  
11 -use Illuminate\Console\Command;  
12 -use Illuminate\Support\Facades\DB;  
13 -use Illuminate\Support\Facades\Log;  
14 -  
15 -class Count extends Command  
16 -{  
17 - const STATUS_ERROR = 400;  
18 - public $error = 0;  
19 - /**  
20 - * The name and signature of the console command.  
21 - *  
22 - * @var string  
23 - */  
24 - protected $signature = 'count';  
25 -  
26 - /**  
27 - * The console command description.  
28 - *  
29 - * @var string  
30 - */  
31 - protected $description = '统计昨日数据';  
32 -  
33 - /**  
34 - * @name :(定时执行生成昨日数据统计)handle  
35 - * @author :lyh  
36 - * @method :post  
37 - * @time :2023/5/12 14:48  
38 - */  
39 - public function handle()  
40 - {  
41 - $list = DB::table('gl_project')->where('gl_project.extend_type',0)->where('gl_project.delete_status',0)  
42 - ->whereIn('gl_project.type',[1,2,3,4,6])  
43 - ->leftJoin('gl_project_deploy_build', 'gl_project.id', '=', 'gl_project_deploy_build.project_id')  
44 - ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')  
45 - ->select($this->selectParam())->get();  
46 - try {  
47 - if(!empty($list)){  
48 - $list = $list->toArray();  
49 - $yesterday = Carbon::yesterday()->toDateString();  
50 - $domainInfo = new DomainInfo();  
51 - foreach ($list as $v){  
52 - $v = (array)$v;  
53 - echo date('Y-m-d H:i:s') . 'project_id:'.$v['id'] . PHP_EOL;  
54 - if($v['type'] == Project::TYPE_ZERO){  
55 - continue;  
56 - }  
57 - if(!empty($v['domain'])){  
58 - $info = $domainInfo->read(['id'=>$v['domain']]);  
59 - if($info !== false){  
60 - $v['test_domain'] = $info['domain'];  
61 - }  
62 - }  
63 - $arr = [];  
64 - //统计时间  
65 - $arr['date'] = $yesterday;  
66 - ProjectServer::useProject($v['id']);  
67 - //pv统计  
68 - $arr['pv_num'] = $this->pv_num($yesterday);  
69 - //ip统计  
70 - $arr['ip_num'] = $this->ip_num($yesterday);  
71 - DB::disconnect('custom_mysql');  
72 - //服务达标天数  
73 - $arr['compliance_day'] = $v['finish_remain_day'];  
74 - //剩余服务时常  
75 - $arr['service_day'] = ($v['remain_day'] - 1) < 0 ? 0: $v['remain_day'] - 1;  
76 - //项目id  
77 - $arr['project_id'] = $v['project_id'];  
78 - $arr['created_at'] = date('Y-m-d H:i:s');  
79 - $arr['updated_at'] = date('Y-m-d H:i:s');  
80 - //询盘统计  
81 - $arr = $this->inquiry($arr,$v['test_domain'], $v['id'] , $v['is_upgrade'] ?? 0);  
82 - //查询当天数据是否存在 存在则更新  
83 - $countModel = new \App\Models\HomeCount\Count();  
84 - $info = $countModel->read(['date'=>$arr['date'],'project_id'=>$v['id']]);  
85 - if($info === false){  
86 - DB::table('gl_count')->insert($arr);  
87 - }else{  
88 - $countModel->edit($arr,['id'=>$info['id']]);  
89 - }  
90 - Log::channel('day_count')->error('日期:'.$arr['created_at'].'success: ' .$v['test_domain']);  
91 - }  
92 - }  
93 - }catch (\Exception $e){  
94 - Log::channel('day_count')->error('day_count:->error ' . $e->getMessage());  
95 - }  
96 - Log::channel('day_count')->error('success:end');  
97 - echo $this->error;  
98 - }  
99 -  
100 - /**  
101 - * @name :(统计pv)pv_num  
102 - * @author :lyh  
103 - * @method :post  
104 - * @time :2023/6/14 15:40  
105 - */  
106 - public function pv_num($yesterday){  
107 - $pv = DB::connection('custom_mysql')->table('gl_customer_visit_item')->whereDate('updated_date', $yesterday)->count();  
108 - return $pv;  
109 - }  
110 -  
111 - /**  
112 - * @name :(统计ip)ip_num  
113 - * @author :lyh  
114 - * @method :post  
115 - * @time :2023/6/14 15:40  
116 - */  
117 - public function ip_num($yesterday){  
118 - $ip = DB::connection('custom_mysql')->table('gl_customer_visit')->whereDate('updated_date', $yesterday)->count();  
119 - return $ip;  
120 - }  
121 -  
122 - /**  
123 - * @param $arr  
124 - * @param $domain  
125 - * @name :(询盘统计)inquiry  
126 - * @author :lyh  
127 - * @method :post  
128 - * @time :2023/6/14 15:44  
129 - */  
130 - public function inquiry($arr,$domain,$project_id,$is_upgrade = 0){  
131 - $inquiry_list = (new FormGlobalsoApi())->getInquiryAll($domain,$is_upgrade);  
132 - if($inquiry_list == false){  
133 - return $arr;  
134 - }  
135 - if($inquiry_list['status'] == self::STATUS_ERROR){  
136 - $arr['inquiry_num'] = 0;  
137 - $countryArr = [];  
138 - }else{  
139 - $arr['inquiry_num'] = $inquiry_list['data']['count'];  
140 - //询盘国家统计  
141 - $countryArr = $inquiry_list['data']['country'];  
142 - }  
143 - //加上其他询盘  
144 - ProjectServer::useProject($project_id);  
145 - $arr['inquiry_num'] += InquiryFormData::getCount();  
146 - $countryData = InquiryFormData::getCountryCount();  
147 - foreach ($countryData as $v1){  
148 - if(isset($countryArr[$v1['country']])){  
149 - $countryArr[$v1['country']] += $v1['count'];  
150 - }else{  
151 - $countryArr[$v1['country']] = $v1['count'];  
152 - }  
153 - }  
154 - arsort($countryArr);  
155 - $top20 = array_slice($countryArr, 0, 20, true);  
156 - $arr['country'] = json_encode($top20);  
157 - return $arr;  
158 - }  
159 -  
160 - /**  
161 - * @name :(查询参数设置)selectParam  
162 - * @author :lyh  
163 - * @method :post  
164 - * @time :2023/6/14 15:00  
165 - */  
166 - public function selectParam(){  
167 - $select = [  
168 - 'gl_project.id AS id',  
169 - 'gl_project.type AS type',  
170 - 'gl_project.extend_type AS extend_type',  
171 - 'gl_project.is_upgrade AS is_upgrade',  
172 - 'gl_project.remain_day AS remain_day',  
173 - 'gl_project.finish_remain_day AS finish_remain_day',  
174 - 'gl_project_deploy_build.test_domain AS test_domain',  
175 - 'gl_project_deploy_optimize.domain AS domain',  
176 - 'gl_project_deploy_build.project_id AS project_id',  
177 - 'gl_project.cooperate_date AS cooperate_date',  
178 - 'gl_project_deploy_build.service_duration AS service_duration',  
179 - ];  
180 - return $select;  
181 - }  
182 -}  
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :CountProject.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2024/1/8 9:03  
8 - */  
9 -  
10 -namespace App\Console\Commands\DayCount;  
11 -  
12 -use App\Helper\FormGlobalsoApi;  
13 -use App\Models\Inquiry\InquiryFormData;  
14 -use App\Models\Project\Project;  
15 -use App\Services\ProjectServer;  
16 -use Illuminate\Console\Command;  
17 -use Illuminate\Support\Facades\DB;  
18 -use App\Models\HomeCount\Count;  
19 -  
20 -class CountAll extends Command  
21 -{  
22 - const STATUS_ERROR = 400;  
23 - public $error = 0;  
24 - /**  
25 - * The name and signature of the console command.  
26 - *  
27 - * @var string  
28 - */  
29 - protected $signature = 'count_all';  
30 -  
31 - /**  
32 - * The console command description.  
33 - *  
34 - * @var string  
35 - */  
36 - protected $description = '所有项目统计';  
37 -  
38 - public function handle(){  
39 - $projectModel = new Project();  
40 - $list = $projectModel->list(['delete_status'=>0,'type'=>['in',[1,2,3,4,6]]]);  
41 - foreach ($list as $v) {  
42 - echo date('Y-m-d H:i:s') . '项目id:'.$v['id'] . PHP_EOL;  
43 - ProjectServer::useProject($v['id']);  
44 - $this->count($v['id']);  
45 - DB::disconnect('custom_mysql');  
46 - }  
47 - return true;  
48 - }  
49 -  
50 - /**  
51 - * @remark :日统计记录  
52 - * @name :count  
53 - * @author :lyh  
54 - * @method :post  
55 - * @time :2024/1/8 9:05  
56 - */  
57 - public function count($project_id){  
58 - $list = DB::connection('custom_mysql')->table('gl_customer_visit')->select('updated_date')  
59 - ->groupBy('updated_date')->get()->toArray();  
60 - $project = new Project();  
61 - $projectInfo = $project->read(['id'=>$project_id]);  
62 - if(!empty($list)){  
63 - $arr = [];  
64 - foreach ($list as $k=>$v){  
65 - $v = (array)$v;  
66 - if($v['updated_date'] == date('Y-m-d')){  
67 - continue;  
68 - }  
69 - echo date('Y-m-d H:i:s') . '时间:'.$v['updated_date'] . PHP_EOL;  
70 - $count = new Count();  
71 - $arr['project_id'] = $project_id;  
72 - $arr['date'] = $v['updated_date'];  
73 - $arr['pv_num'] = $this->pv_num($v['updated_date']);  
74 - $arr['ip_num'] = $this->ip_num($v['updated_date']);  
75 - $arr['inquiry_num'] = $this->inquiry_num($v['updated_date']);  
76 - //服务达标天数  
77 - $arr['compliance_day'] = $projectInfo['finish_remain_day'];  
78 - //剩余服务时常  
79 - $arr['service_day'] = $projectInfo['remain_day'];  
80 - $arr['country'] = json_encode([]);  
81 - //查询当天数据是否存在 存在则更新  
82 - $info = $count->read(['date'=>$v['updated_date'],'project_id'=>$project_id]);  
83 - if($info === false){  
84 - $arr['created_at'] = $v['updated_date'].' 01:00:00';  
85 - $arr['updated_at'] = $v['updated_date'].' 01:00:00';  
86 - $count->insert($arr);  
87 - }else{  
88 - $count->edit($arr,['id'=>$info['id']]);  
89 - }  
90 - }  
91 - }  
92 - echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;  
93 - }  
94 -  
95 - /**  
96 - * @param $arr  
97 - * @param $domain  
98 - * @name :(询盘统计)inquiry  
99 - * @author :lyh  
100 - * @method :post  
101 - * @time :2023/6/14 15:44  
102 - */  
103 - public function inquiry($arr,$domain,$project_id,$is_upgrade = 0){  
104 - $inquiry_list = (new FormGlobalsoApi())->getInquiryAll($domain,$is_upgrade);  
105 - if($inquiry_list == false){  
106 - return $arr;  
107 - }  
108 - if($inquiry_list['status'] == self::STATUS_ERROR){  
109 - $arr['inquiry_num'] = 0;  
110 - $countryArr = [];  
111 - }else{  
112 - $arr['inquiry_num'] = $inquiry_list['data']['count'];  
113 - //询盘国家统计  
114 - $countryArr = $inquiry_list['data']['country'];  
115 - }  
116 - //加上其他询盘  
117 - ProjectServer::useProject($project_id);  
118 - $arr['inquiry_num'] += InquiryFormData::getCount();  
119 - $countryData = InquiryFormData::getCountryCount();  
120 - foreach ($countryData as $v1){  
121 - if(isset($countryArr[$v1['country']])){  
122 - $countryArr[$v1['country']] += $v1['count'];  
123 - }else{  
124 - $countryArr[$v1['country']] = $v1['count'];  
125 - }  
126 - }  
127 - arsort($countryArr);  
128 - $top20 = array_slice($countryArr, 0, 20, true);  
129 - $arr['country'] = json_encode($top20);  
130 - return $arr;  
131 - }  
132 -  
133 - /**  
134 - * @remark :询盘数量  
135 - * @name :inquiry_num  
136 - * @author :lyh  
137 - * @method :post  
138 - * @time :2024/1/8 9:24  
139 - */  
140 - public function inquiry_num($day){  
141 - $count = DB::connection('custom_mysql')->table('gl_customer_visit')->whereDate('updated_date', $day)->where('is_inquiry',1)->count();  
142 - return $count;  
143 - }  
144 -  
145 - /**  
146 - * @name :(统计pv)pv_num  
147 - * @author :lyh  
148 - * @method :post  
149 - * @time :2023/6/14 15:40  
150 - */  
151 - public function pv_num($day){  
152 - //$pv = DB::connection('custom_mysql')->table('gl_customer_visit_item')->whereDate('updated_date', $day)->count();  
153 - $pv = DB::connection('custom_mysql')->table('gl_customer_visit')->whereDate('updated_date', $day)->sum('depth');  
154 - return $pv;  
155 - }  
156 -  
157 - /**  
158 - * @name :(统计ip)ip_num  
159 - * @author :lyh  
160 - * @method :post  
161 - * @time :2023/6/14 15:40  
162 - */  
163 - public function ip_num($day){  
164 - $ip = DB::connection('custom_mysql')->table('gl_customer_visit')->whereDate('updated_date', $day)->count();  
165 - return $ip;  
166 - }  
167 -  
168 -  
169 -  
170 -}  
1 -<?php  
2 -  
3 -namespace App\Console\Commands\DayCount;  
4 -  
5 -use App\Helper\FormGlobalsoApi;  
6 -use App\Models\Domain\DomainInfo;  
7 -use App\Models\Inquiry\InquiryFormData;  
8 -use App\Models\Project\Project;  
9 -use App\Services\ProjectServer;  
10 -use Illuminate\Console\Command;  
11 -use Illuminate\Support\Facades\DB;  
12 -use Illuminate\Support\Facades\Log;  
13 -  
14 -class CountDate extends Command  
15 -{  
16 - const STATUS_ERROR = 400;  
17 - public $error = 0;  
18 - /**  
19 - * The name and signature of the console command.  
20 - *  
21 - * @var string  
22 - */  
23 - protected $signature = 'count_data {date}';  
24 -  
25 - /**  
26 - * The console command description.  
27 - *  
28 - * @var string  
29 - */  
30 - protected $description = '按时间统计所有项目记录';  
31 -  
32 - /**  
33 - * @name :(定时执行生成昨日数据统计)handle  
34 - * @author :lyh  
35 - * @method :post  
36 - * @time :2023/5/12 14:48  
37 - */  
38 - public function handle()  
39 - {  
40 - $date = $this->argument('date');  
41 - $list = DB::table('gl_project')->where('gl_project.extend_type','=',0)  
42 - ->whereIn('gl_project.type',[1,2,3,4,6])  
43 - ->leftJoin('gl_project_deploy_build', 'gl_project.id', '=', 'gl_project_deploy_build.project_id')  
44 - ->leftJoin('gl_project_deploy_optimize', 'gl_project.id', '=', 'gl_project_deploy_optimize.project_id')  
45 - ->select($this->selectParam())->get();  
46 - try {  
47 - if(!empty($list)){  
48 - $list = $list->toArray();  
49 -// $yesterday = Carbon::yesterday()->toDateString();  
50 - $yesterday = $date;  
51 - $domainInfo = new DomainInfo();  
52 - foreach ($list as $v){  
53 - $v = (array)$v;  
54 - echo date('Y-m-d H:i:s') . 'project_id:'.$v['id'] . PHP_EOL;  
55 - if($v['type'] == Project::TYPE_ZERO){  
56 - continue;  
57 - }  
58 - if(!empty($v['domain'])){  
59 - $info = $domainInfo->read(['id'=>$v['domain']]);  
60 - if($info !== false){  
61 - $v['test_domain'] = $info['domain'];  
62 - }  
63 - }  
64 - $arr = [];  
65 - //统计时间  
66 - $arr['date'] = $yesterday;  
67 - ProjectServer::useProject($v['id']);  
68 - //pv统计  
69 - $arr['pv_num'] = $this->pv_num($yesterday);  
70 - //ip统计  
71 - $arr['ip_num'] = $this->ip_num($yesterday);  
72 - DB::disconnect('custom_mysql');  
73 - //服务达标天数  
74 - $arr['compliance_day'] = $v['finish_remain_day'];  
75 - //剩余服务时常  
76 - $arr['service_day'] = ($v['remain_day'] - 1) < 0 ? 0: $v['remain_day'] - 1;  
77 - //项目id  
78 - $arr['project_id'] = $v['project_id'];  
79 - $arr['created_at'] = date('Y-m-d H:i:s');  
80 - $arr['updated_at'] = date('Y-m-d H:i:s');  
81 - //询盘统计  
82 - $arr = $this->inquiry($arr,$v['test_domain'], $v['id'],$v['is_upgrade'] ?? 0);  
83 - if($arr === false){  
84 - continue;  
85 - }  
86 - //查询当天数据是否存在 存在则更新  
87 - $countModel = new \App\Models\HomeCount\Count();  
88 - $info = $countModel->read(['date'=>$arr['date'],'project_id'=>$v['id']]);  
89 - if($info === false){  
90 - DB::table('gl_count')->insert($arr);  
91 - }else{  
92 - $countModel->edit($arr,['id'=>$info['id']]);  
93 - }  
94 - Log::channel('day_count')->error('日期:'.$arr['created_at'].'success: ' .$v['test_domain']);  
95 - }  
96 - }  
97 - }catch (\Exception $e){  
98 - Log::channel('day_count')->error('day_count:->error ' . $e->getMessage());  
99 - }  
100 - Log::channel('day_count')->error('success:end');  
101 - echo $this->error;  
102 - }  
103 -  
104 - /**  
105 - * @name :(统计pv)pv_num  
106 - * @author :lyh  
107 - * @method :post  
108 - * @time :2023/6/14 15:40  
109 - */  
110 - public function pv_num($yesterday){  
111 - $pv = DB::connection('custom_mysql')->table('gl_customer_visit_item')->whereDate('updated_date', $yesterday)->count();  
112 - return $pv;  
113 - }  
114 -  
115 - /**  
116 - * @name :(统计ip)ip_num  
117 - * @author :lyh  
118 - * @method :post  
119 - * @time :2023/6/14 15:40  
120 - */  
121 - public function ip_num($yesterday){  
122 - $ip = DB::connection('custom_mysql')->table('gl_customer_visit')->whereDate('updated_date', $yesterday)->count();  
123 - return $ip;  
124 - }  
125 -  
126 - /**  
127 - * @param $arr  
128 - * @param $domain  
129 - * @name :(询盘统计)inquiry  
130 - * @author :lyh  
131 - * @method :post  
132 - * @time :2023/6/14 15:44  
133 - */  
134 - public function inquiry($arr,$domain,$project_id,$is_upgrade = 0){  
135 - $inquiry_list = (new FormGlobalsoApi())->getInquiryAll($domain,$is_upgrade);  
136 - if($inquiry_list == false){  
137 - return $arr;  
138 - }  
139 - if($inquiry_list['status'] == self::STATUS_ERROR){  
140 - $arr['inquiry_num'] = 0;  
141 - $countryArr = [];  
142 - }else{  
143 - $arr['inquiry_num'] = $inquiry_list['data']['count'];  
144 - //询盘国家统计  
145 - $countryArr = $inquiry_list['data']['country'];  
146 - }  
147 - //加上其他询盘  
148 - ProjectServer::useProject($project_id);  
149 - $arr['inquiry_num'] += InquiryFormData::getCount();  
150 - $countryData = InquiryFormData::getCountryCount();  
151 - foreach ($countryData as $v1){  
152 - if(isset($countryArr[$v1['country']])){  
153 - $countryArr[$v1['country']] += $v1['count'];  
154 - }else{  
155 - $countryArr[$v1['country']] = $v1['count'];  
156 - }  
157 - }  
158 - arsort($countryArr);  
159 - $top20 = array_slice($countryArr, 0, 20, true);  
160 - $arr['country'] = json_encode($top20);  
161 - return $arr;  
162 - }  
163 -  
164 - /**  
165 - * @name :(查询参数设置)selectParam  
166 - * @author :lyh  
167 - * @method :post  
168 - * @time :2023/6/14 15:00  
169 - */  
170 - public function selectParam(){  
171 - $select = [  
172 - 'gl_project.id AS id',  
173 - 'gl_project.type AS type',  
174 - 'gl_project.extend_type AS extend_type',  
175 - 'gl_project.is_upgrade AS is_upgrade',  
176 - 'gl_project.remain_day AS remain_day',  
177 - 'gl_project.finish_remain_day AS finish_remain_day',  
178 - 'gl_project_deploy_build.test_domain AS test_domain',  
179 - 'gl_project_deploy_optimize.domain AS domain',  
180 - 'gl_project_deploy_build.project_id AS project_id',  
181 - 'gl_project.cooperate_date AS cooperate_date',  
182 - 'gl_project_deploy_build.service_duration AS service_duration',  
183 - ];  
184 - return $select;  
185 - }  
186 -}  
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :CountProject.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2024/1/8 9:03  
8 - */  
9 -  
10 -namespace App\Console\Commands\DayCount;  
11 -  
12 -use App\Helper\FormGlobalsoApi;  
13 -use App\Models\Domain\DomainInfo;  
14 -use App\Models\Inquiry\InquiryFormData;  
15 -use App\Models\Project\DeployOptimize;  
16 -use App\Models\Project\Project;  
17 -use App\Services\ProjectServer;  
18 -use Illuminate\Console\Command;  
19 -use Illuminate\Support\Facades\DB;  
20 -use App\Models\HomeCount\Count;  
21 -  
22 -class CountProject extends Command  
23 -{  
24 - const STATUS_ERROR = 400;  
25 - public $error = 0;  
26 - /**  
27 - * The name and signature of the console command.  
28 - *  
29 - * @var string  
30 - */  
31 - protected $signature = 'count_project {project_id}';  
32 -  
33 - /**  
34 - * The console command description.  
35 - *  
36 - * @var string  
37 - */  
38 - protected $description = '按项目统计日记录';  
39 -  
40 - public function handle(){  
41 - $project_id = $this->argument('project_id');  
42 - ProjectServer::useProject($project_id);  
43 - $this->count($project_id);  
44 - DB::disconnect('custom_mysql');  
45 - }  
46 -  
47 - /**  
48 - * @remark :日统计记录  
49 - * @name :count  
50 - * @author :lyh  
51 - * @method :post  
52 - * @time :2024/1/8 9:05  
53 - */  
54 - public function count($project_id,$is_upgrade = 0){  
55 - $list = DB::connection('custom_mysql')->table('gl_customer_visit')->select('updated_date')  
56 - ->groupBy('updated_date')->get()->toArray();  
57 - $project = new Project();  
58 - $projectInfo = $project->read(['id'=>$project_id]);  
59 - $projectOptimizeModel = new DeployOptimize();  
60 - $optimizeInfo = $projectOptimizeModel->read(['project_id'=>$project_id]);  
61 - $domain = '';  
62 - if(!empty($optimizeInfo['domain'])){  
63 - $domainInfoModel = new DomainInfo();  
64 - $domainInfo = $domainInfoModel->read(['id'=>$optimizeInfo['domain']]);  
65 - if($domainInfo !== false){  
66 - $domain = $domainInfo['domain'];  
67 - }  
68 - }  
69 - if(empty($domain)){  
70 - return false;  
71 - }  
72 - if(!empty($list)){  
73 - $arr = [];  
74 - foreach ($list as $k=>$v){  
75 - $v = (array)$v;  
76 - if($v['updated_date'] == date('Y-m-d')){  
77 - continue;  
78 - }  
79 - echo date('Y-m-d H:i:s') . '时间:'.$v['updated_date'] . PHP_EOL;  
80 - $count = new Count();  
81 - $arr['project_id'] = $project_id;  
82 - $arr['date'] = $v['updated_date'];  
83 - $arr['pv_num'] = $this->pv_num($v['updated_date']);  
84 - $arr['ip_num'] = $this->ip_num($v['updated_date']);  
85 - //服务达标天数  
86 - $arr['compliance_day'] = $projectInfo['finish_remain_day'];  
87 - //剩余服务时常  
88 - $arr['service_day'] = $projectInfo['remain_day'];  
89 - $arr = $this->inquiry($arr,$domain, $project_id,$projectInfo['is_upgrade'] ?? 0);  
90 - if($arr === false){  
91 - continue;  
92 - }  
93 - //查询当天数据是否存在 存在则更新  
94 - $info = $count->read(['date'=>$v['updated_date'],'project_id'=>$project_id]);  
95 - if($info === false){  
96 - $arr['created_at'] = $v['updated_date'].' 01:00:00';  
97 - $arr['updated_at'] = $v['updated_date'].' 01:00:00';  
98 - $count->insert($arr);  
99 - }else{  
100 - $count->edit($arr,['id'=>$info['id']]);  
101 - }  
102 - }  
103 - }  
104 - echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;  
105 - }  
106 -  
107 - /**  
108 - * @remark :询盘数量  
109 - * @name :inquiry_num  
110 - * @author :lyh  
111 - * @method :post  
112 - * @time :2024/1/8 9:24  
113 - */  
114 - public function inquiry_num($day){  
115 - $count = DB::connection('custom_mysql')->table('gl_customer_visit')->whereDate('updated_date', $day)->where('is_inquiry',1)->count();  
116 - return $count;  
117 - }  
118 -  
119 - /**  
120 - * @name :(统计pv)pv_num  
121 - * @author :lyh  
122 - * @method :post  
123 - * @time :2023/6/14 15:40  
124 - */  
125 - public function pv_num($day){  
126 - $pv = DB::connection('custom_mysql')->table('gl_customer_visit')->whereDate('updated_date', $day)->sum('depth');  
127 - return $pv;  
128 - }  
129 -  
130 - /**  
131 - * @name :(统计ip)ip_num  
132 - * @author :lyh  
133 - * @method :post  
134 - * @time :2023/6/14 15:40  
135 - */  
136 - public function ip_num($day){  
137 - $ip = DB::connection('custom_mysql')->table('gl_customer_visit')->whereDate('updated_date', $day)->count();  
138 - return $ip;  
139 - }  
140 -  
141 - /**  
142 - * @param $arr  
143 - * @param $domain  
144 - * @name :(询盘统计)inquiry  
145 - * @author :lyh  
146 - * @method :post  
147 - * @time :2023/6/14 15:44  
148 - */  
149 - public function inquiry($arr,$domain,$project_id,$is_upgrade = 0){  
150 - $inquiry_list = (new FormGlobalsoApi())->getInquiryAll($domain,$is_upgrade);  
151 - if($inquiry_list == false){  
152 - return $arr;  
153 - }  
154 -// echo date('Y-m-d H:i:s') . '拉取询盘状态:' .json_encode($inquiry_list) . PHP_EOL;  
155 - if($inquiry_list['status'] == self::STATUS_ERROR){  
156 - $arr['inquiry_num'] = 0;  
157 - $countryArr = [];  
158 - }else{  
159 - $arr['inquiry_num'] = $inquiry_list['data']['count'];  
160 - //询盘国家统计  
161 - $countryArr = $inquiry_list['data']['country'];  
162 - }  
163 - //加上其他询盘  
164 - ProjectServer::useProject($project_id);  
165 - $arr['inquiry_num'] += InquiryFormData::getCount();  
166 - $countryData = InquiryFormData::getCountryCount();  
167 - foreach ($countryData as $v1){  
168 - if(isset($countryArr[$v1['country']])){  
169 - $countryArr[$v1['country']] += $v1['count'];  
170 - }else{  
171 - $countryArr[$v1['country']] = $v1['count'];  
172 - }  
173 - }  
174 - arsort($countryArr);  
175 - $top20 = array_slice($countryArr, 0, 20, true);  
176 - $arr['country'] = json_encode($top20);  
177 - return $arr;  
178 - }  
179 -  
180 -}  
1 -<?php  
2 -  
3 -namespace App\Console\Commands\DayCount;  
4 -  
5 -use App\Models\Inquiry\InquiryCount as InquiryCountModel;  
6 -use App\Models\Inquiry\InquiryInfo;  
7 -use Carbon\Carbon;  
8 -use Illuminate\Console\Command;  
9 -use Illuminate\Support\Facades\Log;  
10 -  
11 -/**  
12 - * @remark :  
13 - * @class :InquiryCount.php  
14 - * @author :lyh  
15 - * @time :2023/7/14 16:20  
16 - */  
17 -class InquiryCount extends Command  
18 -{  
19 - /**  
20 - * The name and signature of the console command.  
21 - *  
22 - * @var string  
23 - */  
24 - protected $signature = 'inquiry_count';  
25 -  
26 - /**  
27 - * The console command description.  
28 - *  
29 - * @var string  
30 - */  
31 - protected $description = '每天统计询盘数量';  
32 -  
33 - /**  
34 - * @var :根据状态统计  
35 - */  
36 - public $status = [  
37 - 1=>'站群询盘',  
38 - 2=>'ai站群询盘',  
39 - 3=>'amp自建平台',  
40 - 4=>'fb询盘',  
41 - 5=>'fb广告',  
42 - 6=>'广告采集建站',  
43 - 7=>'黄金平台询盘',  
44 - 8=>'内部统计',  
45 - 9=>'GlobalImporter',  
46 - 10=>'whatsapp',  
47 - 11=>'Skype',  
48 - 12=>'建站客户',  
49 - 13=>'ChinaCn',  
50 - 14=>'EC21',  
51 - 15=>'邮件群发'  
52 - ];  
53 -  
54 - /**  
55 - * @remark :统计  
56 - * @name :handle  
57 - * @author :lyh  
58 - * @method :post  
59 - * @time :2023/7/14 16:21  
60 - */  
61 - public function handle(){  
62 - $data = [];  
63 - //获取昨天的时间  
64 - $yesterday = Carbon::yesterday()->toDateString();  
65 - $inquiryInfoModel = new InquiryInfo();  
66 - try {  
67 - foreach ($this->status as $k=>$v){  
68 - $total = $inquiryInfoModel->formatQuery(['created_at'=>['between',[$yesterday.' 00:00:00',$yesterday.' 23:59:59']]])->count();  
69 - $untreated = $inquiryInfoModel->formatQuery(['created_at'=>['between',[$yesterday.' 00:00:00',$yesterday.' 23:59:59']],'status'=>1])->count();  
70 - $invalid = $inquiryInfoModel->formatQuery(['created_at'=>['between',[$yesterday.' 00:00:00',$yesterday.' 23:59:59']],'status'=>0])->count();  
71 - $data[] = [  
72 - 'type'=>$k,  
73 - 'day'=>$yesterday,  
74 - 'total'=>$total ?? 0,  
75 - 'untreated'=>$untreated ?? 0,  
76 - 'invalid'=>$invalid ?? 0  
77 - ];  
78 - }  
79 - $inquiryCount = new InquiryCountModel();  
80 - $inquiryCount->insert($data);  
81 - }catch (\Exception $e){  
82 - Log::error('inquiry_count : error');  
83 - }  
84 - return true;  
85 - }  
86 -}  
1 -<?php  
2 -  
3 -namespace App\Console\Commands\DayCount;  
4 -  
5 -use App\Models\Inquiry\InquiryInfo;  
6 -use Illuminate\Console\Command;  
7 -  
8 -/**  
9 - * @remark :  
10 - * @class :InquiryDelay.php  
11 - * @author :lyh  
12 - * @time :2023/7/14 10:16  
13 - */  
14 -class InquiryDelay extends Command  
15 -{  
16 - /**  
17 - * The name and signature of the console command.  
18 - *  
19 - * @var string  
20 - */  
21 - protected $signature = 'inquiry_delay';  
22 -  
23 - /**  
24 - * The console command description.  
25 - *  
26 - * @var string  
27 - */  
28 - protected $description = '延时询盘转发(暂时弃用)';  
29 -  
30 - /**  
31 - * @remark :延时询盘转发  
32 - * @name :handle  
33 - * @author :lyh  
34 - * @method :post  
35 - * @time :2023/7/14 10:17  
36 - */  
37 - public function handle()  
38 - {  
39 -// $inquiryInfoModel = new InquiryInfo();  
40 -// $param = $inquiryInfoModel->formatQuery(['status'=>$inquiryInfoModel::STATUS_FOUR])->orderBy('send_time','asc')->first();  
41 -// if(!empty($param)){  
42 -// $time = date('Y-m-d H:i:s');  
43 -// if($time >= $param['send_time']){  
44 -// $data = [];  
45 -// //TODO::处理转发的url  
46 -// $arr_url = explode(',',$param['forward_url']);  
47 -// foreach ($arr_url as $v){  
48 -// $data['url'] = $v;  
49 -// $this->inquiryForward($data);  
50 -// }  
51 -// $inquiryInfoModel->edit(['status'=>$inquiryInfoModel::STATUS_THREE],['id'=>$param['id']]);  
52 -// }  
53 -// }  
54 - return true;  
55 - }  
56 -  
57 - /**  
58 - * @remark :询盘转发  
59 - * @name :inquiryForward  
60 - * @author :lyh  
61 - * @method :post  
62 - * @time :2023/7/13 14:39  
63 - */  
64 - public function inquiryForward($post_data){  
65 - $url = 'https://www.globalso.site/api/external-interface/add/fa043f9cbec6b38f';  
66 - $post_data_new = [];  
67 - $post_data_new['refer'] = $post_data['url'];  
68 - $post_data_new['name'] = $post_data['name'];  
69 - $post_data_new['email'] = $post_data['email'];  
70 - $post_data_new['phone'] = $post_data['phone'];  
71 - $post_data_new['ip'] = $post_data['ip'];  
72 - $post_data_new['message'] = $post_data['message'];  
73 - $post_data_new['submit_time'] = date('Y-m-d H:i:s',time()+20);  
74 - $token = md5($post_data_new['refer'].$post_data_new['name'].$post_data_new['ip'].date("Y-m-d",time()));  
75 - $post_data_new['token'] = $token;  
76 - $header = array(  
77 - 'CLIENT-IP: '.$post_data['ip'],  
78 - 'X-FORWARDED-FOR: '.$post_data['ip']  
79 - );  
80 - return http_post($url,$post_data_new,$header);  
81 - }  
82 -  
83 -}  
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :DeleteProductCategory.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2024/5/16 14:59  
8 - */  
9 -  
10 -namespace App\Console\Commands\DeleteCategory;  
11 -  
12 -use App\Helper\Arr;  
13 -use App\Models\Blog\Blog;  
14 -use App\Models\Blog\BlogCategory;  
15 -use App\Models\Com\NoticeLog;  
16 -use App\Models\Project\Project;  
17 -use App\Services\ProjectServer;  
18 -use Illuminate\Console\Command;  
19 -use Illuminate\Support\Facades\DB;  
20 -  
21 -/**  
22 - * @remark :删除分类  
23 - * @name :DeleteProductCategory  
24 - * @author :lyh  
25 - * @method :post  
26 - * @time :2024/5/16 15:00  
27 - */  
28 -class DeleteBlogCategory extends Command  
29 -{  
30 - /**  
31 - * The name and signature of the console command.  
32 - *  
33 - * @var string  
34 - */  
35 - protected $signature = 'delete_blog_category';  
36 -  
37 - /**  
38 - * The console command description.  
39 - *  
40 - * @var string  
41 - */  
42 - protected $description = '删除博客分类';  
43 -  
44 - /**  
45 - * Create a new command instance.  
46 - *  
47 - * @return void  
48 - */  
49 - public function __construct()  
50 - {  
51 - parent::__construct();  
52 - }  
53 -  
54 - /**  
55 - * @remark :批量处理  
56 - * @name :handle  
57 - * @author :lyh  
58 - * @method :post  
59 - * @time :2024/5/16 15:02  
60 - */  
61 - public function handle(){  
62 - while (true){  
63 - $noticeLogModel = new NoticeLog();  
64 - $list = $noticeLogModel->list(['status'=>NoticeLog::STATUS_PENDING,'type'=>NoticeLog::DELETE_BLOG_CATEGORY],'id',['*'],'asc',100);  
65 - if(empty($list)){  
66 - sleep(10);  
67 - continue;  
68 - }  
69 - foreach ($list as $item){  
70 - echo 'start:' . $item['id'] . PHP_EOL;  
71 - try {  
72 - $projectModel = new Project();  
73 - $projectInfo = $projectModel->read(['id'=>$item['data']['project_id']]);  
74 - if($projectInfo === false){  
75 - continue;  
76 - }  
77 - ProjectServer::useProject($projectInfo['id']);  
78 - $this->updateCategory();  
79 - DB::disconnect('custom_mysql');  
80 - $noticeLogModel->edit(['status'=>NoticeLog::STATUS_SUCCESS],['id'=>$item['id']]);  
81 - echo 'success:' . $item['id'] . '执行时间:'. date('Y-m-d H:i:s') . PHP_EOL;  
82 - }catch (\Exception $e){  
83 - echo 'error:' . $item['id'] . $e->getMessage() . '执行时间:'.date('Y-m-d H:i:s') . PHP_EOL;  
84 - errorLog('delete_blog_category删除失败'.date('Y-m-d H:i:s'), $item, $e);  
85 - }  
86 - }  
87 - return true;  
88 - }  
89 - }  
90 -  
91 - /**  
92 - * @remark :更新分类  
93 - * @name :updateProductCategory  
94 - * @author :lyh  
95 - * @method :post  
96 - * @time :2024/5/16 15:38  
97 - */  
98 - public function updateCategory(){  
99 - $page = 1;  
100 - $blogModel = new Blog();  
101 - while (true){  
102 - $blogList = $blogModel->lists(['status'=>1],$page,1000,'id',['id','category_id']);  
103 - if(empty($blogList) || empty($blogList['list'])){  
104 - return false;  
105 - }  
106 - foreach ($blogList['list'] as $v){  
107 - $category_id_arr = Arr::setToArr(trim($v['category_id'],','));  
108 - if(empty($category_id_arr)){  
109 - continue;  
110 - }  
111 - $categoryModel = new BlogCategory();  
112 - foreach ($category_id_arr as $k=>$cate_id){  
113 - $cateInfo = $categoryModel->read(['id'=>$cate_id],['id']);  
114 - if($cateInfo == false){  
115 - //删除关联表  
116 - unset($category_id_arr[$k]);  
117 - }  
118 - }  
119 - $str = !empty($category_id_arr) ? ','.Arr::arrToSet($category_id_arr).',' : '';  
120 - $blogModel->edit(['category_id'=>$str],['id'=>$v['id']]);  
121 - }  
122 - $page++;  
123 - }  
124 - return true;  
125 - }  
126 -}  
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :DeleteProductCategory.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2024/5/16 14:59  
8 - */  
9 -  
10 -namespace App\Console\Commands\DeleteCategory;  
11 -  
12 -use App\Helper\Arr;  
13 -use App\Models\Com\NoticeLog;  
14 -use App\Models\CustomModule\CustomModuleCategory;  
15 -use App\Models\CustomModule\CustomModuleContent;  
16 -use App\Models\Project\Project;  
17 -use App\Services\ProjectServer;  
18 -use Illuminate\Console\Command;  
19 -use Illuminate\Support\Facades\DB;  
20 -  
21 -/**  
22 - * @remark :删除分类  
23 - * @name :DeleteProductCategory  
24 - * @author :lyh  
25 - * @method :post  
26 - * @time :2024/5/16 15:00  
27 - */  
28 -class DeleteCustomCategory extends Command  
29 -{  
30 - /**  
31 - * The name and signature of the console command.  
32 - *  
33 - * @var string  
34 - */  
35 - protected $signature = 'delete_custom_category';  
36 -  
37 - /**  
38 - * The console command description.  
39 - *  
40 - * @var string  
41 - */  
42 - protected $description = '删除扩展模块分类';  
43 -  
44 - /**  
45 - * Create a new command instance.  
46 - *  
47 - * @return void  
48 - */  
49 - public function __construct()  
50 - {  
51 - parent::__construct();  
52 - }  
53 -  
54 - /**  
55 - * @remark :批量处理  
56 - * @name :handle  
57 - * @author :lyh  
58 - * @method :post  
59 - * @time :2024/5/16 15:02  
60 - */  
61 - public function handle(){  
62 - while (true){  
63 - $noticeLogModel = new NoticeLog();  
64 - $list = $noticeLogModel->list(['status'=>NoticeLog::STATUS_PENDING,'type'=>NoticeLog::DELETE_CUSTOM_CATEGORY],'id',['*'],'asc',100);  
65 - if(empty($list)){  
66 - sleep(10);  
67 - continue;  
68 - }  
69 - foreach ($list as $item){  
70 - echo 'start:' . $item['id'] . PHP_EOL;  
71 - try {  
72 - $projectModel = new Project();  
73 - $projectInfo = $projectModel->read(['id'=>$item['data']['project_id']]);  
74 - if($projectInfo === false){  
75 - continue;  
76 - }  
77 - ProjectServer::useProject($projectInfo['id']);  
78 - $this->updateCategory();  
79 - DB::disconnect('custom_mysql');  
80 - $noticeLogModel->edit(['status'=>NoticeLog::STATUS_SUCCESS],['id'=>$item['id']]);  
81 - echo 'success:' . $item['id'] . '执行时间:'. date('Y-m-d H:i:s') . PHP_EOL;  
82 - }catch (\Exception $e){  
83 - echo 'error:' . $item['id'] . $e->getMessage() . '执行时间:'. date('Y-m-d H:i:s') . PHP_EOL;  
84 - errorLog('delete_custom_category删除失败', $item, $e);  
85 - }  
86 - }  
87 - return true;  
88 - }  
89 - }  
90 -  
91 - /**  
92 - * @remark :更新分类  
93 - * @name :updateProductCategory  
94 - * @author :lyh  
95 - * @method :post  
96 - * @time :2024/5/16 15:38  
97 - */  
98 - public function updateCategory(){  
99 - $page = 1;  
100 - $customModel = new CustomModuleContent();  
101 - while (true){  
102 - $customList = $customModel->lists(['status'=>0],$page,1000,'id',['id','category_id']);  
103 - if(empty($customList) || empty($customList['list'])){  
104 - return false;  
105 - }  
106 - foreach ($customList['list'] as $v){  
107 - $category_id_arr = $v['category_id'];  
108 - if(empty($category_id_arr)){  
109 - continue;  
110 - }  
111 - $categoryModel = new CustomModuleCategory();  
112 - foreach ($category_id_arr as $k=>$cate_id){  
113 - $cateInfo = $categoryModel->read(['id'=>$cate_id],['id']);  
114 - if($cateInfo == false){  
115 - //删除关联表  
116 - unset($category_id_arr[$k]);  
117 - }  
118 - }  
119 - $str = !empty($category_id_arr) ? ','.Arr::arrToSet($category_id_arr).',' : '';  
120 - $customModel->edit(['category_id'=>$str],['id'=>$v['id']]);  
121 - }  
122 - $page++;  
123 - }  
124 - return true;  
125 - }  
126 -}  
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :DeleteProductCategory.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2024/5/16 14:59  
8 - */  
9 -  
10 -namespace App\Console\Commands\DeleteCategory;  
11 -  
12 -use App\Helper\Arr;  
13 -use App\Models\Com\NoticeLog;  
14 -use App\Models\News\News;  
15 -use App\Models\News\NewsCategory;  
16 -use App\Models\Project\Project;  
17 -use App\Services\ProjectServer;  
18 -use Illuminate\Console\Command;  
19 -use Illuminate\Support\Facades\DB;  
20 -  
21 -/**  
22 - * @remark :删除分类  
23 - * @name :DeleteProductCategory  
24 - * @author :lyh  
25 - * @method :post  
26 - * @time :2024/5/16 15:00  
27 - */  
28 -class DeleteNewsCategory extends Command  
29 -{  
30 - /**  
31 - * The name and signature of the console command.  
32 - *  
33 - * @var string  
34 - */  
35 - protected $signature = 'delete_news_category';  
36 -  
37 - /**  
38 - * The console command description.  
39 - *  
40 - * @var string  
41 - */  
42 - protected $description = '删除新闻分类';  
43 -  
44 - /**  
45 - * Create a new command instance.  
46 - *  
47 - * @return void  
48 - */  
49 - public function __construct()  
50 - {  
51 - parent::__construct();  
52 - }  
53 -  
54 - /**  
55 - * @remark :批量处理  
56 - * @name :handle  
57 - * @author :lyh  
58 - * @method :post  
59 - * @time :2024/5/16 15:02  
60 - */  
61 - public function handle(){  
62 - while (true){  
63 - $noticeLogModel = new NoticeLog();  
64 - $list = $noticeLogModel->list(['status'=>NoticeLog::STATUS_PENDING,'type'=>NoticeLog::DELETE_NEWS_CATEGORY],'id',['*'],'asc',100);  
65 - if(empty($list)){  
66 - sleep(10);  
67 - continue;  
68 - }  
69 - foreach ($list as $item){  
70 - echo 'start:' . $item['id'] . PHP_EOL;  
71 - try {  
72 - $projectModel = new Project();  
73 - $projectInfo = $projectModel->read(['id'=>$item['data']['project_id']]);  
74 - if($projectInfo === false){  
75 - continue;  
76 - }  
77 - ProjectServer::useProject($projectInfo['id']);  
78 - $this->updateCategory();  
79 - DB::disconnect('custom_mysql');  
80 - $noticeLogModel->edit(['status'=>NoticeLog::STATUS_SUCCESS],['id'=>$item['id']]);  
81 - echo 'success:' . $item['id'] . '执行时间:'.date('Y-m-d H:i:s') . PHP_EOL;  
82 - }catch (\Exception $e){  
83 - echo 'error:' . $item['id'] . $e->getMessage() . '执行时间:'.date('Y-m-d H:i:s') . PHP_EOL;  
84 - errorLog('delete_news_category删除失败', $item, $e);  
85 - }  
86 - }  
87 - return true;  
88 - }  
89 - }  
90 -  
91 - /**  
92 - * @remark :更新分类  
93 - * @name :updateProductCategory  
94 - * @author :lyh  
95 - * @method :post  
96 - * @time :2024/5/16 15:38  
97 - */  
98 - public function updateCategory(){  
99 - $page = 1;  
100 - $newsModel = new News();  
101 - while (true){  
102 - $newsList = $newsModel->lists(['status'=>1],$page,1000,'id',['id','category_id']);  
103 - if(empty($newsList) || empty($newsList['list'])){  
104 - return false;  
105 - }  
106 - foreach ($newsList['list'] as $v){  
107 - $category_id_arr = Arr::setToArr(trim($v['category_id'],','));  
108 - if(empty($category_id_arr)){  
109 - continue;  
110 - }  
111 - $categoryModel = new NewsCategory();  
112 - foreach ($category_id_arr as $k=>$cate_id){  
113 - $cateInfo = $categoryModel->read(['id'=>$cate_id],['id']);  
114 - if($cateInfo === false){  
115 - //删除关联表  
116 - unset($category_id_arr[$k]);  
117 - }  
118 - }  
119 - $str = !empty($category_id_arr) ? ','.Arr::arrToSet($category_id_arr).',' : '';  
120 - $newsModel->edit(['category_id'=>$str],['id'=>$v['id']]);  
121 - }  
122 - $page++;  
123 - }  
124 - return true;  
125 - }  
126 -}