作者 刘锟

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

正在显示 33 个修改的文件 包含 437 行增加175 行删除
... ... @@ -11,6 +11,7 @@ use App\Models\Project\ProjectKeyword;
use App\Models\RankData\RankData;
use App\Models\WebSetting\WebSetting;
use App\Services\AiBlogService;
use App\Services\DingService;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
... ... @@ -62,52 +63,64 @@ class AiBlogAutoPublish extends Command
$projects = Project::where('is_ai_blog', 1)->get();
foreach ($projects as $project) {
$this->output("项目{$project->id}开始自动发布");
if(!$project->deploy_optimize['is_ai_blog_send']){
$this->output("项目{$project->id}未开启自动发布" . $project->deploy_optimize['start_date']);
continue;
}
if(($project->deploy_optimize['start_date'] > date('Y-m-d')) || !$project->deploy_optimize['start_date']){
$this->output("项目{$project->id}未到推广时间" . $project->deploy_optimize['start_date']);
continue;
}
$next_auto_date = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->whereNotNull('next_auto_date')->orderBy('id', 'desc')->value('next_auto_date');
if($next_auto_date && $next_auto_date > date('Y-m-d')){
$this->output("项目{$project->id}未到执行时间" . $next_auto_date);
continue;
}
//核心关键词+网站关键词
$main_keywords = ProjectKeyword::where('project_id', $project->id)->value('main_keyword');
$main_keywords = explode("\r\n", $main_keywords);
ProjectServer::useProject($project->id);
$site_keywords = WebSetting::where('project_id', $project->id)->value('keyword');
DB::disconnect('custom_mysql');
$site_keywords = explode(",", $site_keywords);
$keywords = array_filter(array_merge($main_keywords, $site_keywords));
$keywords = array_map('trim', $keywords);
if (empty($keywords)) {
$this->output("项目{$project->id}未获取到关键词");
continue;
}
$last_task = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->orderBy('id', 'desc')->first();
$compliance = RankData::where(['project_id' => $project->id, 'lang' => ''])->value('is_compliance');
$frequency = Project::typeBlogFrequency($project->deploy_optimize->send_ai_blog_frequency);
$frequency = explode('-', $frequency);
//1、之前测试那批项目,按照正常频率发送;
//2、未达标的项目,开启AIblog, 并立即推送三篇;
//3、其他项目等下下周 1 (2025-03-17)开始推送第一篇, 之后按照正频率发送;
if (!$last_task) {
if(!$compliance) {
for ($i = 0; $i < 3; $i++) {
$this->createTask($keywords, $project->id, $frequency);
}
}else{
if(date('Y-m-d') >= '2025-03-17'){
$this->createTask($keywords, $project->id, $frequency);
try {
$this->output("项目{$project->id}开始自动发布");
if(!$project->deploy_optimize['is_ai_blog_send']){
$this->output("项目{$project->id}未开启自动发布" . $project->deploy_optimize['start_date']);
continue;
}
if(($project->deploy_optimize['start_date'] > date('Y-m-d')) || !$project->deploy_optimize['start_date']){
$this->output("项目{$project->id}未到推广时间" . $project->deploy_optimize['start_date']);
continue;
}
$next_auto_date = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->whereNotNull('next_auto_date')->orderBy('id', 'desc')->value('next_auto_date');
if($next_auto_date && $next_auto_date > date('Y-m-d')){
$this->output("项目{$project->id}未到执行时间" . $next_auto_date);
continue;
}
//核心关键词+网站关键词
$main_keywords = ProjectKeyword::where('project_id', $project->id)->value('main_keyword');
$main_keywords = explode("\r\n", $main_keywords);
ProjectServer::useProject($project->id);
$site_keywords = WebSetting::where('project_id', $project->id)->value('keyword');
DB::disconnect('custom_mysql');
$site_keywords = explode(",", $site_keywords);
$keywords = array_filter(array_merge($main_keywords, $site_keywords));
$keywords = array_map('trim', $keywords);
if (empty($keywords)) {
$this->output("项目{$project->id}未获取到关键词");
continue;
}
$last_task = AiBlogTaskModel::where('project_id', $project->id)->where('type', 2)->orderBy('id', 'desc')->first();
$compliance = RankData::where(['project_id' => $project->id, 'lang' => ''])->value('is_compliance');
$frequency = Project::typeBlogFrequency($project->deploy_optimize->send_ai_blog_frequency);
$frequency = explode('-', $frequency);
//1、之前测试那批项目,按照正常频率发送;
//2、未达标的项目,开启AIblog, 并立即推送三篇;
//3、其他项目等下下周 1 (2025-03-17)开始推送第一篇, 之后按照正频率发送;
if (!$last_task) {
if(!$compliance) {
for ($i = 0; $i < 3; $i++) {
$this->createTask($keywords, $project->id, $frequency);
}
}else{
if(date('Y-m-d') >= '2025-03-17'){
$this->createTask($keywords, $project->id, $frequency);
}
}
} else {
$this->createTask($keywords, $project->id, $frequency);
}
} else {
$this->createTask($keywords, $project->id, $frequency);
}catch (\Exception $e){
(new DingService())->handle([
'keyword' => 'AI_BLOG自动发布失败',
'msg' => '项目ID:' . $project->id . PHP_EOL .
'错误信息:' . $e->getMessage() . PHP_EOL .
'错误文件:' . $e->getFile() . PHP_EOL .
'错误行数:' . $e->getLine(),
'isAtAll' => true, // 是否@所有人
]);
$this->output("自动发布失败:" . $e->getMessage() . $e->getFile() . $e->getLine());
}
}
}
... ... @@ -159,23 +172,37 @@ class AiBlogAutoPublish extends Command
->get();
foreach ($projects as $project) {
//未开启过 自动开启
if (!AiBlogOpenLog::isOpened($project->id)) {
//开启
$project->is_ai_blog = 1;
//开启自动发布
$project->deploy_optimize->is_ai_blog_send = 1;
$project->deploy_optimize->save();
$project->save();
//创建AI博客项目
$deploy_optimize = $project->deploy_optimize;
(new ProjectLogic())->setAiBlog($project->id, $project->main_lang_id, 1, $project->company, $deploy_optimize->company_en_name, $deploy_optimize->company_en_description);
//开启日志
AiBlogOpenLog::addLog($project->id);
$this->output('自动开启项目:' . $project->id);
try {
//未开启过 自动开启
if (!AiBlogOpenLog::isOpened($project->id)) {
//创建AI博客项目
$deploy_optimize = $project->deploy_optimize;
(new ProjectLogic())->setAiBlog($project->id, $project->main_lang_id, 1, $project->company, $deploy_optimize->company_en_name, $deploy_optimize->company_en_description);
//开启
$project->is_ai_blog = 1;
//开启自动发布
$project->deploy_optimize->is_ai_blog_send = 1;
$project->deploy_optimize->save();
$project->save();
//开启日志
AiBlogOpenLog::addLog($project->id);
$this->output('自动开启项目:' . $project->id);
}
}catch (\Exception $e){
(new DingService())->handle([
'keyword' => 'AI_BLOG自动开启失败',
'msg' => '项目ID:' . $project->id . PHP_EOL .
'错误信息:' . $e->getMessage() . PHP_EOL .
'错误文件:' . $e->getFile() . PHP_EOL .
'错误行数:' . $e->getLine(),
'isAtAll' => true, // 是否@所有人
]);
$this->output("自动开启失败:" . $e->getMessage() . $e->getFile() . $e->getLine());
}
}
sleep(60);
... ...
... ... @@ -120,18 +120,18 @@ class AiBlogTask extends Command
DB::disconnect('custom_mysql');
return false;
}
//需要更新的路由
if (!in_array($result['data']['author_id'], $this->updateProject[$item['project_id']] ?? [])) {
$this->updateProject[$item['project_id']][] = $result['data']['author_id'];
}
if (!in_array($aiBlogInfo['route'], $this->routes[$item['project_id']] ?? [])) {
$this->routes[$item['project_id']][] = $aiBlogInfo['route'];
}
//拿到返回的路由查看是否重复
$route = RouteMap::setRoute($result['data']['url'], RouteMap::SOURCE_AI_BLOG, $aiBlogInfo['id'], $item['project_id']);
if($route != $result['data']['url']){
$aiBlogService->updateDetail(['route'=>$route,'task_id'=>$item['task_id']]);
}
//需要更新的路由
if (!in_array($result['data']['author_id'], $this->updateProject[$item['project_id']] ?? [])) {
$this->updateProject[$item['project_id']][] = $result['data']['author_id'];
}
if (!in_array($route, $this->routes[$item['project_id']] ?? [])) {
$this->routes[$item['project_id']][] = $route;
}
$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']]);
DB::disconnect('custom_mysql');
$aiBlogTaskModel->edit(['status'=>$aiBlogModel::STATUS_FINISH],['id'=>$item['id']]);
... ...
<?php
/**
* @remark :
* @name :AfterCount.php
* @name :AfterDayCount.php
* @author :lyh
* @method :post
* @time :2025/3/26 15:28
... ... @@ -16,7 +16,7 @@ use Carbon\Carbon;
use App\Models\HomeCount\AfterCount as AfterCountModel;
use Illuminate\Console\Command;
class AfterCount extends Command
class AfterDayCount extends Command
{
/**
* The name and signature of the console command.
... ... @@ -44,6 +44,7 @@ class AfterCount extends Command
echo date('Y-m-d H:i:s').'统计start->'.PHP_EOL;
$saveData = $this->_action();
$afterModel = new AfterCountModel();
//保存数据
$afterModel->insertAll($saveData);
echo date('Y-m-d H:i:s').'->统计end'.PHP_EOL;
return true;
... ... @@ -62,7 +63,7 @@ class AfterCount extends Command
$rankDataLogModel = new RankDataLog();
$todayMidnight = date('Y-m-d 00:00:00', strtotime('today'));
$saveData = [];
$projectIdArr = $rankDataLogModel->selectField(['is_compliance'=>1,'lang'=>null,'date'=>date('Y-m-d', strtotime('-3 months'))],'project_id');//3个月前达标的项目id
$projectIdArr = $rankDataLogModel->selectField(['is_compliance'=>1,'lang'=>'','date'=>date('Y-m-d', strtotime('-3 months'))],'project_id');//3个月前达标的项目id
foreach ($this->after_manager as $key => $valM){
$idArr = $this->managerHrModel->selectField(['name'=>['in',$valM]],'id');
$project_count = $projectModel->where('gl_project.extend_type',0)
... ... @@ -108,9 +109,9 @@ class AfterCount extends Command
'project_count'=>$project_count,
'qualified_count'=>$qualified_count,
'rate'=>$rate,
'three_project_count'=>$project_count - $three_project_count,
'three_qualified_count'=>$qualified_count - $three_qualified_count,
'three_rate'=>$rate - $three_rate,
'three_project_count'=>$three_project_count,
'three_qualified_count'=>$three_qualified_count,
'three_rate'=>$three_rate,
'data' => json_encode($data,true)
];
}
... ...
... ... @@ -4,10 +4,8 @@ namespace App\Console\Commands\Domain;
use App\Models\Project\DeployBuild;
use App\Models\Project\DeployOptimize;
use App\Models\Project\OnlineCheck;
use App\Models\Project\Project;
use Illuminate\Console\Command;
use App\Models\Domain\DomainInfo as DomainInfoModel;
/**
* 剩余服务时长
... ... @@ -45,6 +43,7 @@ class RemainDay extends Command
1703,
1893,
2066,
2250
];//需要单独处理的项目
/**
* The console command description.
... ...
... ... @@ -736,7 +736,7 @@ class RelayInquiry extends Command
// 所有可用url
$urls = $inquiry_urls = [];
//入口url 首页30%,单页10%,聚合页60%
$type = getRandByRatio([30,10,60]);
$type = getRandByRatio([40,20,40]);
$inlet = $re_website;
$type == 1 && $inlet = $page_url ? Arr::random($page_url) : $re_website;
$type == 2 && $inlet = $keywords_url ? Arr::random($keywords_url) : $re_website;
... ...
... ... @@ -19,6 +19,7 @@ use App\Models\GoogleSearch\GoogleCodeCountry;
use App\Models\Product\CategoryRelated;
use App\Models\Product\Keyword;
use App\Models\Product\Product;
use App\Models\Project\AggregateKeyword;
use App\Models\Project\AiBlogTask;
use App\Models\Project\DeployOptimize;
use App\Models\Project\Project;
... ... @@ -66,7 +67,59 @@ class UpdateRoute extends Command
*/
public function handle()
{
$this->insertData();
return $this->keyword_actions();
}
public function keyword_actions(){
$a = new AggregateKeyword();
// $list = $a->formatQuery(['status'=>1])->pluck('project_id')->unique()->values()->toArray();
$list = [2368,2168,1786,2289,3685,3008];
foreach ($list as $v){
if($v == 1){
continue;
}
echo date('Y-m-d H:i:s').' 执行的项目id:'.$v.PHP_EOL;
ProjectServer::useProject($v);
$bak_lists = DB::connection('custom_mysql')->table('gl_product_keyword_bak')->where('status',1)->get()->toArray();
$keywordModel = new Keyword();
$keywordModel->truncate();
$routeMapModel = new RouteMap();
$routeMapModel->del(['source'=>'product_keyword']);
foreach ($bak_lists as $bakV){
$info = $keywordModel->read(['title'=>$bakV['title']],['id']);
if($info !== false){
echo '当前关键词已存在,跳过的关键词'.$bakV['title'].PHP_EOL;
continue;
}
//执行新增数据
unset($bakV['id']);
$id = $keywordModel->addReturnId($bakV);
$route = RouteMap::setRoute($bakV['route'],'product_keyword',$id,$v);
$keywordModel->edit(['route'=>$route],['id'=>$id]);
echo '执行新增----'.$bakV['title'].PHP_EOL;
}
DB::disconnect('custom_mysql');
}
}
/**
* @remark :清洗数据
* @name :_action
* @author :lyh
* @method :post
* @time :2025/4/10 17:08
*/
public function _action(){
$projectModel = new Project();
$lists = $projectModel->list(['delete_status'=>0,'extend_type'=>0,'type'=>['!=',0]],'id',['id']);
$keywordModel = new Keyword();
foreach ($lists as $v){
ProjectServer::useProject($v['id']);
echo date('Y-m-d H:i:s').' 执行的项目id:'.$v['id'].PHP_EOL;
$keywordModel->edit(['type'=>1],['id'=>['!=',0]]);
DB::disconnect('custom_mysql');
}
return true;
}
/**
* @remark :
... ...
... ... @@ -58,8 +58,6 @@ class OptimizeSetKeywordSync extends Command
$item->status = AggregateKeyword::STATUS_FINISH;
$item->save();
}
Common::del_user_cache('product_keyword',$this->user['project_id']);
NoticeLog::createLog(NoticeLog::TYPE_INIT_KEYWORD, ['project_id' => $this->user['project_id']]);
return true;
}
... ... @@ -71,13 +69,12 @@ class OptimizeSetKeywordSync extends Command
*/
public function syncKeyword($project_id, $keywords)
{
$keywords = explode("\n", $keywords);
$keywords = explode("\r\n", $keywords);
$keywords = array_unique(array_filter($keywords));
ProjectServer::useProject($project_id);
$keywordModel = new Keyword();
$keywordModel->saveBKeyword($project_id,$keywords);
$keywordModel->saveBKeyword($project_id,$keywords,Keyword::TYPE_ORDER_KEYWORD);
DB::disconnect('custom_mysql');
return true;
}
}
\ No newline at end of file
}
... ...
... ... @@ -20,6 +20,7 @@ use App\Models\User\User as UserModel;
use App\Services\ProjectServer;
use Hashids\Hashids;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
... ... @@ -43,7 +44,6 @@ class CopyProject extends Command
public function handle()
{
while (true) {
$projectModel = new Project();
$list = NoticeLog::where('type', NoticeLog::TYPE_COPY_PROJECT)->where('status', NoticeLog::STATUS_PENDING)->get();
if(empty($list)){
sleep(30);
... ... @@ -68,14 +68,12 @@ class CopyProject extends Command
$item->status = NoticeLog::STATUS_FAIL;
$item->save();
}
sleep(180);
sleep(60);
try {
$this->copyMysql($old_project_id,$project_id);
}catch (\Exception $e){
echo '复制数据库失败:'.$old_project_id . '<->'.$project_id;
}
//修改项目状态
$projectModel->edit(['delete_status'=>0],['id'=>$project_id]);
$this->output('CopyProjectJob end, old project_id: ' . $old_project_id . ', new project_id: ' . $project_id);
}
}
... ... @@ -92,6 +90,7 @@ class CopyProject extends Command
$data['finish_remain_day'] = 0;
$data['title'] = $data['title'].'-copy';
$data['delete_status'] = 1;
$data['is_ai_blog'] = 0;
unset($data['id'],$data['exclusive_aicc_day'],$data['aicc'],$data['robots'],$data['is_translate_tag'],$data['is_translate'],$data['is_minor_languages'],$data['uptime']);
$project_id = $projectModel->insertGetId($data);
$hashids = new Hashids($data['from_order_id'], 13, 'abcdefghjkmnpqrstuvwxyz1234567890');
... ... @@ -145,7 +144,7 @@ class CopyProject extends Command
$optimizeData = $optimizeModel::where('project_id', $old_project_id)->first();
if(!empty($optimizeData)){
$optimizeData = $optimizeData->getAttributes();
unset($optimizeData['id'],$optimizeData['domain'],$optimizeData['backlink'],$optimizeData['ai_video']);
unset($optimizeData['id'],$optimizeData['domain'],$optimizeData['backlink'],$optimizeData['ai_video'],$optimizeData['is_ai_blog_send']);
$optimizeData['project_id'] = $project_id;
$optimizeData['api_no'] = 0;
$optimizeModel->insert($optimizeData);
... ... @@ -207,59 +206,13 @@ class CopyProject extends Command
}
//复制数据库
public function copyMysql($project_id,$new_project_id){
//切换数据库配置
$project = ProjectServer::useProject($new_project_id);
//创建数据库
ProjectServer::createDatabase($project);
//创建表
$this->initTable($project_id,$new_project_id);
Artisan::call("php artisan copy_project_s $project_id $new_project_id");
//修改项目状态
$projectModel = new Project();
$projectModel->edit(['delete_status'=>0],['id'=>$new_project_id]);
}
/**
* @remark :创建数据库
* @name :initTable
* @author :lyh
* @method :post
* @time :2023/12/11 10:09
*/
public function initTable($project_id, $news_project_id)
{
// 设置源数据库
config(['database.connections.custom_tmp_mysql_copy.database' => 'gl_data_' . $project_id]);
$database_name = DB::connection('custom_tmp_mysql_copy')->getDatabaseName();
// 获取源数据库的所有表
$tables = Schema::connection('custom_tmp_mysql_copy')->getAllTables();
$tables = array_column($tables, 'Tables_in_' . $database_name);
foreach ($tables as $table) {
// 1. 删除目标数据库中的表
DB::connection('custom_mysql')->statement("DROP TABLE IF EXISTS {$table}");
// 2. 重新创建表
$sql = DB::connection('custom_tmp_mysql_copy')->select("SHOW CREATE TABLE {$table}");
DB::connection('custom_mysql')->statement(get_object_vars($sql[0])['Create Table']);
// 3. 跳过指定的表
if (in_array($table, ['gl_customer_visit', 'gl_customer_visit_item', 'gl_inquiry_other', 'gl_inquiry_form_data', 'gl_inquiry_form'])) {
continue;
}
try {
// 4. 重新插入数据
DB::connection('custom_mysql')->table($table)->insertUsing(
[], // 插入所有列
function ($query) use ($table, $project_id) {
$name = 'gl_data_' . $project_id . '.' . $table;
$query->select('*')->from("{$name}");
}
);
}catch (\Exception $e){
continue;
}
// 5. 更新 project_id(如果存在)
if (Schema::connection('custom_mysql')->hasColumn($table, 'project_id')) {
DB::connection('custom_mysql')->table($table)->update(['project_id' => $news_project_id]);
}
}
return true;
}
/**
* @param $message
* @return bool
*/
... ...
... ... @@ -199,8 +199,10 @@ class SyncProject extends Command
* @author :lyh
* @method :post
* @time :2023/8/9 15:04
* @param :version:7->v7版本(升级项目默认为v7)
*/
public function sync($param,$is_update = 0){
$version = (($is_update == 1) ? Project::VERSION_SEVEN : ($param['version'] ?? Project::VERSION_ZERO));
$title = date('Ymd') . '-' . $param['company_name'];
$data = [
'project'=>[
... ... @@ -222,6 +224,7 @@ class SyncProject extends Command
'notice_order_id' => $param['id'],
'type' => $is_update,
'is_upgrade'=>$is_update,
'version'=>$version
],
'deploy_build' => [
'login_mobile'=>$param['principal_mobile']
... ... @@ -245,11 +248,11 @@ class SyncProject extends Command
}
DB::beginTransaction();
try {
if(isset($data['deploy_build']['plan']) && ($data['deploy_build']['plan'] == 15)){
if(isset($data['deploy_build']['seo_plan']) && ($data['deploy_build']['seo_plan'] == 1)){
$data['project']['project_type'] = 1;//白帽版本
}
$id = $this->saveProject($data['project']);
$this->setPostId($data['deploy_build']['plan'],$id);
$this->setPostId($data['deploy_build']['plan'] ?? 1,$id);
$this->savePayment($data['payment'],$id);
$this->saveDeployBuild($data['deploy_build'],$id);
$this->saveDeployOptimize($data['deploy_optimize'],$id);
... ...
... ... @@ -4,6 +4,7 @@ namespace App\Console\Commands\Sync;
use App\Exceptions\InquiryFilterException;
use App\Models\Inquiry\InquiryRelateDomain;
use App\Models\Project\Project;
use App\Models\SyncSubmitTask\SyncSubmitTask as SyncSubmitTaskModel;
use App\Services\SyncSubmitTaskService;
... ... @@ -53,10 +54,18 @@ class SyncSubmitTask extends Command
try {
$project = Project::getProjectByDomain($task_info['data']['domain'] ?? '');
if(!$project){
throw new \Exception('项目不存在');
//是否有关联的域名
$relate_domain = InquiryRelateDomain::getRelateDomain($task_info['data']['domain'] ?? '');
if(!$relate_domain){
throw new \Exception('项目不存在1');
}
$project = Project::getProjectByDomain($relate_domain);
if(!$project){
throw new \Exception('项目不存在2');
}
}
$task_info->project_id = $project->id;
SyncSubmitTaskService::handler($task_info);
SyncSubmitTaskService::handler($task_info, '', $relate_domain??'');
$task_info->status = 1;
$task_info->save();
... ...
<?php
namespace App\Console\Commands\Tdk;
use App\Http\Controllers\Bside\News\NewsController;
use App\Models\News\News;
use App\Models\News\NewsCategory;
use App\Models\Project\Project;
use App\Models\Project\ProjectUpdateTdk;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
/**
* 重跑异常tdk
* Class RerunSeoTdk
* @package App\Console\Commands\Tdk
* @author zbj
* @date 2025/4/12
*/
class RerunSeoTdk extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'rerun_seo_tdk';
/**
* The console command description.
*
* @var string
*/
protected $description = '重跑项目sdk';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* @return bool
*/
public function handle()
{
$project_ids = Project::where('type', Project::TYPE_TWO)->pluck('id')->toArray();
foreach ($project_ids as $project_id){
try {
ProjectServer::useProject($project_id);
$this->judgeAnomalies($project_id);
DB::disconnect('custom_mysql');
}catch (\Exception $e){
dump($e->getMessage());
}
}
}
/**
* 判断异常
* @author zbj
* @date 2025/4/12
*/
public function judgeAnomalies($project_id){
//获取当前项目的所有分类
$categories = NewsCategory::pluck('name', 'id')->toArray();
//新闻 seo_keyword 和 分类名一样的
$news_ids = [];
foreach ($categories as $category){
$ids = News::WhereRaw("FIND_IN_SET('{$category}', `seo_keywords`)")->pluck('id')->toArray();
$news_ids = array_unique(array_merge($news_ids, $ids));
}
$count = count($news_ids);
if($count){
echo "项目{$project_id},共{$count}条需要重跑";
News::whereIn('id', $news_ids)->update(['seo_keywords' => '']);
ProjectUpdateTdk::add_task($project_id);
}
}
}
... ...
... ... @@ -385,7 +385,7 @@ class UpdateSeoTdk extends Command
//in,for,with,to,near,from 这些介词 只拼前缀,不拼后缀
$suffix_ban = ['in ', 'for ', 'with ', 'to ', 'near ','from ', 'In ', 'For ', 'With ', 'To ', 'Near ','From '];
$suffix = '';
if(Str::contains($title, $suffix_ban)){
if(!Str::contains($title, $suffix_ban)){
// 某些后缀不能并存的情况
$ban_suffix = [];
//services/service 结尾的词,后缀不拼manufacturer,factory
... ...
... ... @@ -1206,6 +1206,9 @@ function paginateArray($array, $page = 1, $pageSize = 20) {
* @time :2025/4/3 16:19
*/
function getDomain($url) {
if(empty($url)){
return $url;
}
$parsedUrl = parse_url($url);
return $parsedUrl['host'] ?? $url; // 如果解析失败,返回原始 URL
}
... ...
... ... @@ -21,6 +21,8 @@ use Illuminate\Support\Facades\Cache;
class BaseController extends Controller
{
public $param;
public $request;
public function __construct(Request $request)
{
$this->request = $request;
... ...
... ... @@ -12,6 +12,7 @@ use App\Http\Logic\Bside\User\UserLoginLogic;
use App\Models\Ai\AiBlog;
use App\Models\Blog\Blog;
use App\Models\Domain\DomainInfo;
use App\Models\Inquiry\InquiryRelateDomain;
use App\Models\News\News;
use App\Models\Product\Category;
use App\Models\Product\CategoryRelated;
... ... @@ -463,4 +464,31 @@ class PrivateController extends BaseController
$result = json_decode($json, true) ?: [];
return $this->success($result);
}
public function inquiry_relate_domain(Request $request){
$this->request->validate([
'from_domain' => 'required',
'to_domain' => 'required',
]);
$from_domain = trim($this->param['from_domain']);
$to_domain = trim($this->param['to_domain']);
$from_domain = parse_url($from_domain, PHP_URL_HOST) ?: $from_domain;
$to_domain = parse_url($to_domain, PHP_URL_HOST) ?: $to_domain;
$project = Project::getProjectByDomain($to_domain);
if (empty($project)) {
return $this->error('未找到被关联域名对应的项目!');
}
$relate = InquiryRelateDomain::where('from_domain', $from_domain)->first();
if(!$relate){
$relate = new InquiryRelateDomain();
}
$relate->from_domain = $from_domain;
$relate->to_domain = $to_domain;
$relate->save();
return $this->success($relate);
}
}
... ...
... ... @@ -43,6 +43,8 @@ class DomainInfoController extends BaseController
$lists['list'][$k]['company'] = $company;
}
}
$lists['y_status'] = $domainModel->counts(['status'=>1]);
$lists['n_status'] = $domainModel->counts(['status'=>0]);
return $this->response('success', Code::SUCCESS, $lists);
}
... ...
... ... @@ -32,7 +32,7 @@ class InquiryForwardController extends BaseController
$this->map['message'] = ['like', '%' . $this->map['message'] . '%'];
}
if (isset($this->param['start_date']) && isset($this->param['end_date'])) {
$this->map['inquiry_date'] = ['between', [$this->map['start_date'] . ' 00:00:00', $this->map['end_date'] . ' 23:59:59']];
$this->map['inquiry_date'] = ['between', [$this->map['start_date'] . ' 00:00:00', $this->map['end_date'] . ' 00:00:00']];
unset($this->map['start_date']);
unset($this->map['end_date']);
} elseif (isset($this->param['start_date'])) {
... ...
... ... @@ -39,7 +39,7 @@ class GoogleKeywordInsightController extends BaseController
]);
$logic->getGoogleInsight();
$detailModel = new GoogleKeywordInsightDetail();
$data = $detailModel->lists(['search'=>$this->param['keyword']],$this->page,$this->row);
$data = $detailModel->lists(['search'=>$this->param['keyword']],$this->page,$this->row,'id',['*'],'asc');
$this->response('success',Code::SUCCESS,$data);
}
... ...
... ... @@ -26,19 +26,18 @@ class GoogleLinkController extends BaseController
public function getLink(){
$linkModel = new GoogleLink();
$this->map['project_id'] = $this->user['project_id'];
$lists = $linkModel->lists($this->map,$this->page,$this->row,'id',['url','moz_da','status','google_search','date','project_id','domain']);
$this->map['status'] = 1;
$this->map['date'] = ['>=', date('Y-m-d 00:00:00', strtotime('-7 days'))];
$lists = $linkModel->lists($this->map,$this->page,$this->row,'id',['url','moz_da','status','url_domain','google_search','date','project_id','domain']);
if(empty($lists['list'])){
$linkService = new GoogleLinkService();
$data = $linkService->linkPageData($this->user['domain'],$this->user['project_id']);
if(is_array($data)){
$lists = paginateArray($data,$this->page,$this->row);
}else{
@file_put_contents(storage_path('logs/lyh_error.log'), var_export($data, true) . PHP_EOL, FILE_APPEND);
$this->response('success',Code::SUCCESS,[]);
$this->response('success');
}
}
$lists['y_total'] = $linkModel->counts(['status'=>1,'project_id'=>$this->user['project_id']]);
$lists['n_total'] = $linkModel->counts(['status'=>0,'project_id'=>$this->user['project_id']]);
$this->response('success',Code::SUCCESS,$lists);
}
... ...
... ... @@ -37,7 +37,7 @@ class GoogleSearchController extends BaseController
//查询详情数据
$searchDetailModel = new GoogleSearchDetail();
$this->map['project_id'] = $this->user['project_id'];
$data = $searchDetailModel->lists($this->map,$this->page,$this->row,'clicks',['keys','click_rate','impressions_rate']);
$data = $searchDetailModel->lists($this->map,$this->page,$this->row,'impressions',['keys','click_rate','impressions_rate']);
if(!empty($data)){
if($this->param['type'] == 'country'){
$codeCountryModel = new GoogleCodeCountry();
... ...
... ... @@ -554,6 +554,8 @@ class ProductController extends BaseController
}
if(!empty($v['og_image'])){
$v['og_image'] = getImageUrl($v['og_image'] ?? '',$this->user['storage_type'],$this->user['project_location']);
}else{
$v['og_image'] = $v['thumb']['url'] ?? '';
}
if(!empty($v['icon'])){
foreach ($v['icon'] as $icon_k => $icon_v){
... ...
... ... @@ -87,7 +87,7 @@ class DomainInfoLogic extends BaseLogic
//查看当前域名是否有项目在使用
if($this->param['status'] != $this->model::STATUS_ONE){
$info = $this->model->read(['id'=>$this->param['id']]);
if($info === false){
if($info['project_id'] != 0){
$this->fail('当前域名有项目正在使用中');
}
}
... ...
... ... @@ -533,7 +533,7 @@ class ProjectLogic extends BaseLogic
//单独保存行业信息
ProjectIndustryRelated::saveRelated($deploy_optimize['project_id'],$deploy_optimize['industry'] ?? []);
$deployOptimizeModel = new DeployOptimize();
if(isset($deploy_optimize['domain']) && !empty($deploy_optimize['domain'])){
if(isset($deploy_optimize['domain'])){
//更改域名
$this->editDomainStatus($deploy_optimize['domain'],$deploy_optimize['project_id']);
}
... ... @@ -576,6 +576,7 @@ class ProjectLogic extends BaseLogic
'main_keyword'=>$project_keyword['main_keyword'] ?? '',
'customer_keywords'=>$project_keyword['customer_keywords'] ?? '',
'search_keywords'=>$project_keyword['search_keywords'] ?? '',
'seo_keywords'=>$project_keyword['seo_keywords'] ?? '',
];
if(isset($project_keyword['operator_log']) && !empty($project_keyword['operator_log'])){
$data['operator_log'] = json_encode($project_keyword['operator_log'] ?? []);
... ... @@ -914,15 +915,11 @@ class ProjectLogic extends BaseLogic
}
$domainModel = new DomainInfo();
//查看当前域名是否已使用
$domainInfo = $domainModel->read(['id'=>$domain,'project_id'=>['!=',0]]);
$domainInfo = $domainModel->read(['id'=>$domain,'status'=>1,'project_id'=>['!=',0]]);
if($domainInfo !== false){
$this->fail('当前域名已被其他服务器使用');
}
//先清空上一次所绑定的域名
$info = $domainModel->read(['project_id'=>$project_id]);
if($info !== false){
$domainModel->edit(['project_id'=>0,'status'=>DomainInfo::STATUS_ZERO],['id'=>$info['id']]);
}
$domainModel->edit(['project_id'=>0,'status'=>DomainInfo::STATUS_ZERO],['project_id'=>$project_id]);
//重新设置域名
$domainModel->edit(['status'=>DomainInfo::STATUS_ONE,'project_id'=>$project_id],['id'=>$domain]);
return $this->success();
... ... @@ -958,10 +955,15 @@ class ProjectLogic extends BaseLogic
$noticeModel = new NoticeLog();
$info = $noticeModel->read(['type'=>NoticeLog::TYPE_COPY_PROJECT,'status'=>0,'data'=>['like','%"'.$this->param['project_id'].'"%']]);
if($info !== false){
return $this->success('当前项目已在复制中');
return $this->success(['message'=>'当前项目已在复制中']);
}
$projectModel = new Project();
$projectInfo = $projectModel->read(['type'=>0,'old_project_id'=>$this->param['project_id']]);
if($projectInfo !== false){
return $this->success(['message'=>'当前项目已复制过']);
}
NoticeLog::createLog(NoticeLog::TYPE_COPY_PROJECT, ['project_id' => $this->param['project_id']]);
return $this->success('项目复制中,请稍后前往初始化项目查看;');
return $this->success(['message'=>'项目复制中,请稍后前往初始化项目查看;']);
}
/**
... ...
... ... @@ -138,7 +138,6 @@ class CustomTemplateLogic extends BaseLogic
$condition['source'] = $this->getType(BTemplate::COMMON_FOOTER);
$footerComInfo = $bTemplateComModel->read($condition);
if($footerComInfo === false){
$template_id = $this->getTemplateId();
//取默认首页的
$condition['source'] = BTemplate::SOURCE_COM;
$footerComInfo = $bTemplateComModel->read($condition);
... ...
... ... @@ -357,8 +357,10 @@ class ProductLogic extends BaseLogic
$param['thumb'] = Arr::a2s([]);
$param['gallery'] = Arr::a2s([]);
}
if(isset($param['og_image'])){
if(isset($param['og_image']) && !empty($param['og_image'])){
$param['og_image'] = str_replace_url($param['og_image'] ?? '');
}else{
$param['og_image'] = $param['thumb']['url'] ?? '';
}
if(isset($param['files'])){
$param['files']['url'] = str_replace_url($param['files']['url'] ?? '');
... ...
... ... @@ -493,7 +493,7 @@ class RankDataLogic extends BaseLogic
$without_extension_project_ids = [658]; //是否达标只统计主词的
$extension_project_ids = [354]; //扩展词也到达标的
$compliance_project_ids = [2163,257,823]; //直接达标处理的
$ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066];//暂停的项目
$ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250];//暂停的项目
$uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目
//一个项目多个api_no
$multiple_api_no_project_ids = [
... ...
<?php
/**
* @remark :
* @name :AfterCount.php
* @name :AfterDayCount.php
* @author :lyh
* @method :post
* @time :2025/3/26 15:31
... ...
<?php
namespace App\Models\Inquiry;
use App\Helper\Arr;
use App\Models\Base;
use App\Utils\HttpUtils;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
/**
* Class InquiryRelateDomain
* @package App\Models\Inquiry
* @author zbj
* @date 2025/4/12
*/
class InquiryRelateDomain extends Base
{
//设置关联表名
protected $table = 'gl_inquiry_relate_domain';
/**
* 获取关联域名
* @throws \Exception
* @author zbj
* @date 2025/4/12
*/
public static function getRelateDomain($domain){
$list_cache_key = 'RelateDomainList';
$data = Cache::get($list_cache_key);
if(!$data){
$data = [];
$page = 1;
while (true) {
try {
$res = HttpUtils::get('https://www.cmer.site/api/globalso_site', ['pagesite' => 100, 'page' => $page]);
if($res) {
$res = Arr::s2a($res);
$arr = [];
foreach ($res['data']['data'] as $item){
$arr[$item['domain']] = $item['globalso_domain'];
}
$data = array_merge($data, $arr);
if ($res['data']['last_page'] == $page) {
break;
}
}
$page++;
} catch (\Exception | GuzzleException $e) {
throw new \Exception('关联域名接口错误' . $e->getMessage());
}
}
Cache::put($list_cache_key, $data, 3600);
}
return $data[$domain]??'';
}
}
... ...
... ... @@ -21,6 +21,8 @@ class Keyword extends Base
//连接数据库
protected $connection = 'custom_mysql';
const TYPE_ORDER_KEYWORD = 1;//关键词标识,预约关键词标识
const STATUS_ACTIVE = 1;
//获取字母对应数字
public $firstNumWord = [
... ... @@ -110,7 +112,7 @@ class Keyword extends Base
public static function extendKeyword($project_id)
{
$result = [];
$keywords = self::where(['project_id' => $project_id])->pluck('seo_title', 'title')->toArray();
$keywords = self::where(['project_id' => $project_id])->where('type',self::TYPE_ORDER_KEYWORD)->pluck('seo_title', 'title')->toArray();
if (empty($keywords))
return $result;
// $item:前缀 + 关键词 + 后缀
... ... @@ -149,16 +151,17 @@ class Keyword extends Base
* @method :post
* @time :2025/3/25 16:28
*/
public function saveBKeyword($project_id,$keywords){
public function saveBKeyword($project_id,$keywords,$type = 0){
foreach ($keywords as $v){
if(empty($v)){
continue;
}
$info = $this->read(['title'=>$v],['id']);
if($info === false){
$info = $this->read(['title'=>trim($v)],['id']);
if($info == false){
$param['project_id'] = $project_id;
$param['title'] = $v;
$param['first_word'] = $this->first_word($param['title']);
$param['type'] = $type;
$this->addReturnId($param);
}
}
... ...
... ... @@ -38,6 +38,12 @@ class Project extends Base
const IS_DEL_TRUE = 1;
const PROJECT_TYPE_SEO = 1;//白帽seo项目
//版本信息
const VERSION_ZERO = 0;//普通版本
const VERSION_SIX = 6;//6.0版本
const VERSION_SEVEN = 7;//7.0版本
/**
* 星级客户
* @return string[]
... ... @@ -77,6 +83,7 @@ class Project extends Base
return $arr;
}
/**
* 项目类型
* @return string[]
... ...
... ... @@ -88,8 +88,10 @@ class GoogleLinkService
public function saveLink($data,$project_id,$domain){
$saveData = [];
foreach ($data as $val){
$timestamp = strtotime($val['created_at']);
$date = date('Y-m-d H:i:s', $timestamp ?? time());
$date = date('Y-m-d 00:00:00', time());
if($val['status'] != 1){
continue;
}
$saveData[] = [
'url'=>$val['url'],
'moz_da'=>$val['mozDA'],
... ... @@ -97,11 +99,15 @@ class GoogleLinkService
'google_search'=>$val['googlesearch'],
'date'=>$date,
'project_id'=>$project_id,
'domain'=>$domain
'domain'=>$domain,
'url_domain'=>getDomain($val['url'] ?? '')
];
}
$linkModel = new GoogleLink();
$linkModel->insertAll($saveData);
if(!empty($saveData)){
$linkModel->del(['project_id'=>$project_id]);
$linkModel->insertAll($saveData);
}
return $saveData;
}
}
... ...
... ... @@ -42,9 +42,24 @@ class SyncSubmitTaskService
* @author zbj
* @date 2023/11/28
*/
public static function handler($task, $date = '')
public static function handler($task, $date = '', $relate_domain = '')
{
$data = $task['data'];
//有关联域名 替换原数据url
if($relate_domain){
$domain = $data['domain'];
foreach ($data as $k=>&$item){
if($k == 'data'){
foreach ($item as &$v){
$v = str_replace($domain, $relate_domain, $v);
}
}else{
$item = str_replace($domain, $relate_domain, $item);
}
}
}
$checkIpCountry = self::checkIpCountry($data['domain'], $data['ip'], $task['type']);
$data['ip'] = $checkIpCountry['ip'];
... ...
... ... @@ -68,4 +68,7 @@ Route::post('selfSiteVerify', [\App\Http\Controllers\Api\SelfSiteController::cla
//创建301跳转任务
Route::any('/addRedirect',[\App\Http\Controllers\Api\NoticeController::class,'addRedirect']);
//关联域名
Route::post('/inquiry_relate_domain', [\App\Http\Controllers\Api\PrivateController::class, 'inquiry_relate_domain']);
... ...