作者 刘锟

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

... ... @@ -17,6 +17,7 @@ use App\Models\Product\Category;
use App\Models\Product\CategoryRelated;
use App\Models\Product\Column;
use App\Models\Product\Detail;
use App\Models\Product\ExtendInfo;
use App\Models\Product\Product;
use App\Models\RouteMap\RouteMap;
use App\Models\Template\BTemplate;
... ... @@ -51,14 +52,68 @@ class LyhImportTest extends Command
* @time :2023/11/20 15:13
*/
public function handle(){
// ProjectServer::useProject(3283);
// echo date('Y-m-d H:i:s') . 'start' . PHP_EOL;
// $this->importProduct('https://ecdn6.globalso.com/upload/p/1/file/2025-03/zy_boss_price_copy1.csv',3283);
// DB::disconnect('custom_mysql');
ProjectServer::useProject(3283);
echo date('Y-m-d H:i:s') . 'start' . PHP_EOL;
// $this->importProductCategory('https://ecdn6.globalso.com/upload/p/3283/file/2025-03/zy_boss_pricelistcat_202503131025.csv','3283');
$this->importProduct('https://ecdn6.globalso.com/upload/p/3283/file/2025-03/zy_boss_price_copy1.csv',3283);
DB::disconnect('custom_mysql');
echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;
}
/**
* @remark :导入产品分类
* @name :productCategory
* @author :lyh
* @method :post
* @time :2025/3/13 9:58
*/
public function importProductCategory($url,$project_id){
$line_of_text = [];
$opts = [
'http' => [
'method' => 'GET',
'header' => 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.246'
],
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false
]
];
$file_handle = fopen($url, 'r', null, stream_context_create($opts));
while (!feof($file_handle)) {
$line_of_text[] = fgetcsv($file_handle, 0, ',');
}
fclose($file_handle);
$categoryModel = new Category();
foreach ($line_of_text as $k => $val){
if($k < 1){
continue;
}
if(empty($val[1])){
continue;
}
try {
$id = $categoryModel->addReturnId(['project_id'=>$project_id,'title'=>$val[1],'seo_title'=>$val[0],'seo_keyword'=>$val[2]]);
$pid = 0;
if($val[2] != 0){
//查询上级id
$pidCate = $categoryModel->read(['seo_title'=>$val[2]]);
if($pidCate !== false){
$pid = $pidCate['id'];
}
}
$route = RouteMap::setRoute($val[1],RouteMap::SOURCE_PRODUCT_CATE,$id,$project_id);
$categoryModel->edit(['route'=>$route,'pid'=>$pid],['id'=>$id]);
echo date('Y-m-d H:i:s') . '产品分类id:'. $id.PHP_EOL;
}catch (\Exception $e){
echo date('Y-m-d H:i:s') . '跳过的产品名称:'. $val[1];
continue;
}
}
return true;
}
/**
* @remark :导入分类
* @name :importProductCategory
* @author :lyh
... ... @@ -85,71 +140,166 @@ class LyhImportTest extends Command
$cateModel = new Category();
$productModel = new Product();
$detailModel = new Detail();
$columnModel = new Column();
$extentInfoModel = new ExtendInfo();
foreach ($line_of_text as $k => $val){
if($k < 2){
if($k < 1){
continue;
}
$saveData = [];
if($val[1] ?? ''){
$saveData['title'] = $val[1];
if(!empty($val[11])){
$saveData['title'] = $val[11];
}else{
continue;
}
if($val[0] ?? ''){
$cateInfo = $cateModel->read(['seo_title'=>trim($val[0])]);
if(!empty($val[1])){
$cateInfo = $cateModel->read(['seo_title'=>trim($val[1])]);
if($cateInfo !== false){
$saveData['category_id'] = ','.$cateInfo['id'].',';
}
}
$saveData['intro'] = $val[2];
$saveData['content'] = $val[3];
$seo = ['seo_title'=>$val[5]];
$saveData['seo_mate'] = json_encode($seo,true);
$thumb = ['alt'=>'主图','url'=>str_replace('/public','',$val[6])];
$gallery = [['alt'=>'主图','url'=>str_replace('/public','',$val[6])]];
$saveData['thumb'] = json_encode($thumb,true);
$saveData['gallery'] = json_encode($gallery,true);
$id = $productModel->addReturnId($saveData);
echo date('Y-m-d H:i:s') . '新增产品id:'.$id . PHP_EOL;
$saveData['project_id'] = $project_id;
$saveData['status'] = 1;
$saveData['intro'] = $val[6] ?? '';
$seo = ['title'=>$val[11]];
$saveData['seo_mate'] = json_encode($seo,JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$thumb = ['alt'=>'主图','url'=>str_replace('/public','/upload/p/3283',$val[12])];
$gallery = [['alt'=>'主图','url'=>str_replace('/public','/upload/p/3283',$val[12])]];
$saveData['thumb'] = json_encode($thumb,JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$saveData['gallery'] = json_encode($gallery,JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
try {
$id = $productModel->addReturnId($saveData);
}catch (\Exception $e){
@file_put_contents(storage_path('logs/lyh_error.log'), var_export('未导入成功--标题:'.$val[0], true) . PHP_EOL, FILE_APPEND);
continue;
}
//设置关联关系
if($cateInfo !== false){
CategoryRelated::saveRelated($id,[$cateInfo['id']]);
}
//设置路由
$route = RouteMap::setRoute($val[1],RouteMap::SOURCE_PRODUCT,$id,$project_id);
$route = RouteMap::setRoute($val[11],RouteMap::SOURCE_PRODUCT,$id,$project_id);
$productModel->edit(['route'=>$route],['id'=>$id]);
//设置产品描述
$detail = [
'product_id'=>$id,
'column_id'=>1,
'text_type'=>1,
'content'=>json_encode(['content'=>$val[3]])
];
$detailModel->addReturnId($detail);
//扩展描述设置
$detailFaq = [
'column_name'=>'FAQs',
'product_id'=>$id
];
$faqId = $columnModel->addReturnId($detailFaq);
echo date('Y-m-d H:i:s') . '新增产品id:'.$id . PHP_EOL;
if(!empty($val[2])){
$extent = [
'key'=>'pd_extended_field_4',
'product_id'=>$id,
'project_id'=>$project_id,
'values'=>$val[2],
];
try {
$extentInfoModel->addReturnId($extent);
}catch (\Exception $e){
echo '错误:'.$val[2];
}
$faqsDetail = json_decode($val[4],true);
$faqContent = '';
if(!empty($faqsDetail) && is_array($faqsDetail)){
foreach ($faqsDetail as $faq_Val){
$faqContent .= "question:".$faq_Val['question'] . "<br />" . "answer:".$faq_Val['answer']. "<br />";
}
if(!empty($val[3])){
$extent = [
'key'=>'pd_extended_field_1',
'product_id'=>$id,
'project_id'=>$project_id,
'values'=>$val[3],
];
try {
$extentInfoModel->addReturnId($extent);
}catch (\Exception $e){
echo '错误:'.$val[3];
}
$detailFaqInfo = [
}
if(!empty($val[4])){
$extent = [
'key'=>'pd_extended_field_2',
'product_id'=>$id,
'column_id'=>$faqId,
'project_id'=>$project_id,
'values'=>$val[4],
];
try {
$extentInfoModel->addReturnId($extent);
}catch (\Exception $e){
echo '错误:'.$val[4];
}
}
if(!empty($val[5])){
$extent = [
'key'=>'pd_extended_field_3',
'product_id'=>$id,
'project_id'=>$project_id,
'values'=>$val[5],
];
try {
$extentInfoModel->addReturnId($extent);
}catch (\Exception $e){
echo '错误:'.$val[5];
}
}
//产品描述
if(!empty($val[7])){
//设置产品描述
$detail = [
'title'=>'SEODescription',
'product_id'=>$id,
'column_id'=>1,
'text_type'=>1,
'content'=>json_encode(['content'=>$faqContent])
'content'=>json_encode(['content'=>$val[7]],JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
];
$detailModel->addReturnId($detailFaqInfo);
}else{
@file_put_contents(storage_path('logs/lyh_error.log'), var_export('产品标题:'. $val[1] . PHP_EOL .'faqs数据有问题:' . $val[4], true) . PHP_EOL, FILE_APPEND);
echo date('Y-m-d H:i:s') . '产品标题:'. $val[1] . PHP_EOL .'faqs数据有问题:' . $val[4];
$detailModel->addReturnId($detail);
}
//产品描述
if(!empty($val[8])){
//设置产品描述
$detail = [
'title'=>'SEOSpecification',
'product_id'=>$id,
'column_id'=>1,
'text_type'=>1,
'content'=>json_encode(['content'=>$val[8]],JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
];
$detailModel->addReturnId($detail);
}
if(!empty($val[9])){
try {
$faqsDetail = json_decode($val[9],JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
if(!empty($faqsDetail) && is_array($faqsDetail)){
$faqContent = '<div>';
foreach ($faqsDetail as $faq_Val){
$faqContent .= "<span>question:".$faq_Val['question'] . "</span><br /><span>" . "answer:".$faq_Val['answer']. "</span><br />";
}
$faqContent .= '</div>';
$detailFaqInfo = [
'title'=>'SEOQandA',
'product_id'=>$id,
'column_id'=>1,
'text_type'=>1,
'content'=>json_encode(['content'=>$faqContent],JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
];
$detailModel->addReturnId($detailFaqInfo);
}
}catch(\Exception $e){
echo 'fqs';
}
}
if(!empty($val[10])){
try {
$faqsDetail = json_decode($val[10],true);
if(!empty($faqsDetail) && is_array($faqsDetail)){
$faqContent = '<div>';
foreach ($faqsDetail as $faq_Val){
$faqContent .= "<span>question:".$faq_Val['question'] . "</span><br /><span>" . "answer:".$faq_Val['answer']. "</span><br />";
}
$faqContent .= '</div>';
$detailFaqInfo = [
'title'=>'SEOQandA_Product',
'product_id'=>$id,
'column_id'=>1,
'text_type'=>1,
'content'=>json_encode(['content'=>$faqContent])
];
$detailModel->addReturnId($detailFaqInfo);
}
}catch(\Exception $e){
continue;
}
}
}
return true;
... ...
... ... @@ -16,9 +16,12 @@ use App\Models\CustomModule\CustomModuleContent;
use App\Models\Product\CategoryRelated;
use App\Models\Product\Keyword;
use App\Models\Product\Product;
use App\Models\Project\DeployOptimize;
use App\Models\Project\Project;
use App\Models\RankData\RankDataLog;
use App\Models\RouteMap\RouteMap;
use App\Models\WebSetting\WebSetting;
use App\Models\WebSetting\WebSettingSeo;
use App\Services\ProjectServer;
use App\Utils\HttpUtils;
use GuzzleHttp\Exception\GuzzleException;
... ... @@ -61,25 +64,35 @@ class UpdateRoute extends Command
$projectModel = new Project();
$lists = $projectModel->list(['delete_status'=>0],'id',['id']);
foreach ($lists as $v){
echo date('Y-m-d H:i:s') . 'project_id:'.$v['id'] . PHP_EOL;
echo date('Y-m-d H:i:s') . '执行项目的project_id:'.$v['id'] . PHP_EOL;
ProjectServer::useProject($v['id']);
$webSettingModel = new WebSetting();
$settingInfo = $webSettingModel->read(['project_id'=>$v['id']]);
if($settingInfo === false){
echo date('Y-m-d H:i:s') . '当前项目的设置数据不存在:'.$v['id'] . PHP_EOL;
//新增一条数据
$data = [
'anchor_setting'=>'["3","4","5"]',
'anchor_is_enable'=>1,
'anchor_page_num'=>1,
'anchor_num'=>2,
'anchor_keyword_is_enable'=>1,
'project_id'=>$v['id']
];
$webSettingModel->add($data);
}
$this->updateSeo($v['id']);
DB::disconnect('custom_mysql');
}
// $this->updateProjectOp();
// $projectModel = new Project();
// $lists = $projectModel->list(['delete_status'=>0],'id',['id']);
// foreach ($lists as $v){
// echo date('Y-m-d H:i:s') . 'project_id:'.$v['id'] . PHP_EOL;
// ProjectServer::useProject($v['id']);
// $webSettingModel = new WebSetting();
// $settingInfo = $webSettingModel->read(['project_id'=>$v['id']]);
// if($settingInfo === false){
// echo date('Y-m-d H:i:s') . '当前项目的设置数据不存在:'.$v['id'] . PHP_EOL;
// //新增一条数据
// $data = [
// 'anchor_setting'=>'["3","4","5"]',
// 'anchor_is_enable'=>1,
// 'anchor_page_num'=>1,
// 'anchor_num'=>2,
// 'anchor_keyword_is_enable'=>1,
// 'project_id'=>$v['id']
// ];
// $webSettingModel->add($data);
// }
// DB::disconnect('custom_mysql');
// }
echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;
}
... ... @@ -482,4 +495,51 @@ class UpdateRoute extends Command
}
return true;
}
/**
* @remark :更新优化设置表
* @name :updateProjectOp
* @author :lyh
* @method :post
* @time :2025/3/14 10:29
*/
public function updateProjectOp(){
//查询优化中台数据
$projectModel = new Project();
$list = $projectModel->list(['type'=>2],['id']);
$rankDataModel = new RankDataLog();
$opModel = new DeployOptimize();
foreach ($list as $v){
$rankInfo = $rankDataModel->where('project_id', $v['id'])->where('is_compliance',1)->where('lang','')->orderBy('created_at', 'asc')->select('id', 'date' ,'project_id','is_compliance' ,'created_at')->first();
if(!empty($rankInfo)){
echo date('Y-m-d H:i:s') . '项目id:'.$v['id'] .'首次达标时间'. $rankInfo['date'] . PHP_EOL;
$opModel->edit(['first_compliance_time'=>$rankInfo['date']],['project_id'=>$v['id']]);
}
}
return true;
}
/**
* @remark :更新产品分类前后缀
* @name :updateSeo
* @author :lyh
* @method :post
* @time :2025/3/14 14:39
*/
public function updateSeo($project_id){
$seoModel = new WebSettingSeo();
$seo_info = $seoModel->read(['project_id'=>$project_id]);
if($seo_info !== false){
$prefix = $seo_info['product_category_prefix'] ?? [];
$suffix = $seo_info['product_category_suffix'] ?? [];
if(!empty($seo_info['product_cate_prefix'])){
$prefix[] = ['name'=>$seo_info['product_cate_prefix']];
}
if(!empty($seo_info['product_cate_suffix'])){
$suffix[] = ['name'=>$seo_info['product_cate_suffix']];
}
$seoModel->edit(['product_category_prefix'=>json_encode($prefix,true),'product_category_suffix'=>json_encode($suffix,true)],['project_id'=>$project_id]);
}
return true;
}
}
... ...
<?php
/**
* Created by PhpStorm.
* User: zhl
* Date: 2025/3/11
* Time: 14:13
*/
namespace App\Console\Commands\Product;
use App\Models\Product\Keyword;
use App\Models\Project\OnlineCheck;
use App\Models\Project\Project;
use App\Models\RankData\RankData;
use App\Repositories\ToolRepository;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
/**
* Class SendKeyword
* @package App\Console\Commands\Product
*/
class SendKeyword extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'send_product_tag_keyword';
/**
* The console command description.
*
* @var string
*/
protected $description = '未达标项目 自动推送拼接关键词 到监控系统';
/**
* SendKeyword constructor.
*/
public function __construct()
{
parent::__construct();
}
/**
* TODO 查询不达标优化项目, 按照规则推送拼接关键词到监控系统
* http://zentao.globalso.com/index.php?m=task&f=view&taskID=185918
* @return bool
*/
public function handle()
{
$field = ['gl_project.id', 'gl_project.company', 'gl_project.main_lang_id', 'b.is_auto_keywords', 'b.start_date', 'b.api_no', 'd.domain'];
$projects = Project::select($field)->leftJoin('gl_project_deploy_optimize as b', 'gl_project.id', '=', 'b.project_id')
->leftJoin('gl_project_online_check as c', 'gl_project.id', '=', 'c.project_id')
->leftJoin('gl_domain_info as d', 'gl_project.id', '=', 'd.project_id')
->where('gl_project.type', Project::TYPE_TWO)
->where('gl_project.extend_type', 0) // 是否续费是由extend_type字段控制
->where('gl_project.delete_status', Project::IS_DEL_FALSE)
->where('gl_project.main_lang_id', '<>', 8) // 不需要俄语站点项目
->where(function ($subQuery) {
$subQuery->orwhere('c.qa_status', OnlineCheck::STATUS_ONLINE_TRUE)->orwhere('gl_project.is_upgrade', Project::IS_UPGRADE_TRUE);
})
->get();
$time = time();
$send_num = [30 => 1000, 60 => 3000, 90 => 6000];
$ban_domain = $this->banDomain();
foreach ($projects as $item) {
if (empty($item->is_auto_keywords))
continue;
if (in_array($item->domain, $ban_domain))
continue;
if (empty($item->api_no)) {
$this->output('项目ID:' . $item->id . ', api_no为空;');
continue;
}
if (empty($item->start_date)) {
$this->output('项目ID:' . $item->id . ', 推广开始时间为空;');
continue;
}
// 按照间隔时间发送不同关键词数量
$start_time = strtotime($item->start_date);
$day = intval(($time - $start_time) / 86400);
if (empty($send_num[$day])) {
$this->output('项目ID:' . $item->id . ', 推广天数:' . $day . ', 不需要推送;');
continue;
}
// 项目是否达标
$compliance = RankData::where(['project_id' => $item->id, 'api_no' => $item->api_no, 'lang' => ''])->value('is_compliance');
if (FALSE == empty($compliance))
return false;
$project = ProjectServer::useProject($item->id);
if (empty($project)) {
DB::disconnect('custom_mysql');
continue;
}
$send = $this->extendKeyword($item, $send_num[$day]);
DB::disconnect('custom_mysql');
// 数据成功后推送同志
if ($send) {
$item = $item->toArray();
unset($item['main_lang_id']);
unset($item['is_auto_keywords']);
$item['day'] = $day;
$this->sendNotice($item);
}
}
return true;
}
/**
* 截取关键词
* @param $item
* @param int $num
* @return bool
*/
public function extendKeyword($item, $num = 1000)
{
$keywords = Keyword::extendKeyword($item->id);
if (empty($keywords))
return false;
$keywords = array_filter(array_unique($keywords));
$sort = [];
foreach ($keywords as $keyword) {
$sort[] = strlen($keyword);
}
array_multisort($sort, SORT_ASC, $keywords);
$result = array_slice($keywords, 0, $num);
file_put_contents(storage_path('data/send_product_tag_keyword/' . $item->id . '.json'), json_encode($result, 256));
return true;
}
/**
* 通知
* @param $item
* @return bool
*/
public function sendNotice($item)
{
try {
$query = http_build_query($item);
$url = 'http://api.quanqiusou.cn/google-rank/api/v6_add_extend_keywords.php?' . $query;
app(ToolRepository::class)->curlRequest($url, [], 'GET');
// TODO 推送通知 待定
} catch (\Exception $e) {
$this->output('推送通知失败,项目ID:' . $item['id']);
}
return true;
}
/**
* 禁用
* @return array
*/
public function banDomain()
{
$array = [
'www.venttopurifier.com',
'www.gwxpcsheet.com',
'www.bizzyboi.com',
'www.wholesaleladyclothing.com',
'www.chuanbokeji.com',
'www.goalwhite.com',
'www.yusunheating.com',
'www.bretonprecision.com',
'www.chinarendering.com',
'www.centurybeauty.com',
'www.vazpocable.com',
'www.tengda-smart.com',
'www.kayne-bm.com',
'www.aimazingbag.com',
'www.alpha-lifetech.com',
'www.junyi-laser.com',
'www.unionfurnish.com',
'www.zphydraulic.com',
'www.younisicleaning.com',
'www.shibaodeprecision.com',
'www.semmcocoa.com',
'www.sbdmold.com',
'www.utsfabrictester.com',
'www.tlgantryrobot.com',
'www.slabyte.com',
'www.hysum.com',
'www.rsecobag.com',
'www.yuchomachine.com',
'www.hidinosaurs.com',
'www.medigauze.com',
'www.shtangkefresh.com',
'www.fkcrane.com',
'www.zkmparts.com',
'www.zhishuogroup.com',
'www.yunlinplushtoys.com',
];
return $array;
}
/**
* @param $message
*/
public function output($message)
{
$message = date('Y-m-d H:i:s') . ' ' . $message . PHP_EOL;
echo $message;
file_put_contents(storage_path('data/send_product_tag_keyword.log'), $message, FILE_APPEND);
}
}
\ No newline at end of file
... ...
... ... @@ -37,19 +37,19 @@ class CreateProject extends Command
}
public function sync($is_update = 0){
$title = date('Ymd') . '-广东威美建材科技有限公司';
$title = date('Ymd') . '-杭州露娜贸易有限公司';
$data = [
'project'=>[
'title' => $title,
'company' => '广东威美建材科技有限公司',
'lead_name' => '蔡伟文',
'mobile' => '13929953235',
'company' => '杭州露娜贸易有限公司',
'lead_name' => '13008931688',
'mobile' => '13008931688',
'mysql_id'=>Project::MYSQL_ID,
'serve_id'=>9,
'qq' => '',
'channel' => '{"user_id": "53", "zone_id": "4", "channel_id": "4"}',
'channel' => '{"user_id": "381", "zone_id": "4", "channel_id": "46"}',
'requirement' => '',
'cooperate_date' => '2019-04-01',
'cooperate_date' => '2019-11-13',
'from_order_id' => '',
'type' => $is_update,
'is_upgrade'=>$is_update,
... ... @@ -57,7 +57,7 @@ class CreateProject extends Command
'deploy_build' => [
'service_duration' => 0,
'plan' => $this->versionData('标准版'),
'login_mobile'=>'13929953235'
'login_mobile'=>'13008931688'
],
'deploy_optimize' => [
// 'api_no' => 0
... ...
... ... @@ -57,12 +57,11 @@ class RecommendedSuppliers extends Command
{
$project_list = $this->deployBuildModel->list(['is_supplier'=>1]);//TODO::已开启推荐供应商
foreach ($project_list as $v){
echo date('Y-m-d H:i:s') . 'project_id:'.$v['project_id'] . PHP_EOL;
echo date('Y-m-d H:i:s') . '推荐供应商执行的project_id:'.$v['project_id'] . PHP_EOL;
$result = $this->countPurchaser($v);
if($result !== false){
ProjectServer::useProject($v['project_id']);
$title = $this->getKeywords($v['project_id']);
echo date('Y-m-d H:i:s') . '开始:'.$v['project_id'] . PHP_EOL;
$this->savePurchaser($v['project_id'],$title);
DB::disconnect('custom_mysql');
}
... ... @@ -87,6 +86,7 @@ class RecommendedSuppliers extends Command
$plan = ['专业版'=>300, '标准版'=>500, '商务版'=>800, '旗舰版'=>1200];
$total_number = $plan[Project::planMap()[$v['plan']]] ?? 300;
if($count > $total_number){
echo date('Y-m-d H:i:s') . '达到数量上线关闭的项目:'.$v['project_id'] . PHP_EOL;
//更新数量上限字段,并关闭推荐供应商
$this->deployBuildModel->edit(['is_purchaser_count'=>1,'is_supplier'=>0],['project_id'=>$v['project_id']]);
return false;
... ... @@ -119,14 +119,14 @@ class RecommendedSuppliers extends Command
];
ksort($data);
$token = 'company_list+'.date('Y-m-d').'+'.http_build_query($data);
echo date('Y-m-d H:i:s') . '加密token:'.md5($token) . PHP_EOL;
// echo date('Y-m-d H:i:s') . '加密token:'.md5($token) . PHP_EOL;
$param = [
'prod_desc'=>$keyword,
'token'=>md5($token),
'total'=>$this->param['row'] ?? 10,
];
$res = http_post($url,json_encode($param));
echo date('Y-m-d H:i:s') . json_encode($res) . PHP_EOL;
// echo date('Y-m-d H:i:s') . json_encode($res) . PHP_EOL;
if(!empty($res) && isset($res['code']) && $res['code'] == 200 && !empty($res['data'])){
//保存多条数据
$saveData = [
... ...
... ... @@ -366,12 +366,16 @@ class UpdateSeoTdk extends Command
}
} else if ($table == 'gl_product_keyword' && $field == 'seo_title') {
# TODO 聚合页seo title 特殊处理 前缀_1 . 关键词 . 后缀_2
$prefix = $this->getPrefixKeyword($project_id, 'prefix', 1);
$suffix = $this->getPrefixKeyword($project_id, 'suffix', 2);
if (empty($prefix) || empty($suffix)){
continue;
}
$prefix = $this->getPrefixKeyword($project_id, 'prefix', 1, $v[$this->topic_fields[$table]]);
$suffix = $this->getPrefixKeyword($project_id, 'suffix', 2, $v[$this->topic_fields[$table]]);
if (empty($prefix) || empty($suffix))
continue;
$seo_title = $prefix . ' ' . $v[$this->topic_fields[$table]] . ' ' . $suffix;
$data[$field] = $seo_title;
$data[$field] = trim($seo_title);
$update[$table]['title']++;
} else if ($table == 'gl_ai_blog_list' && $field == 'seo_title') {
//直接使用 top blog
... ... @@ -547,6 +551,9 @@ class UpdateSeoTdk extends Command
//去掉标题存在的词
if ($topic) {
foreach ($fix_keyword as $k=>$keyword) {
// 前后缀如果已经存在, 就不在拼接当前类型
if (FALSE !== strpos($topic, $keyword))
return $str;
//处理单词复数 s es ies ves
$keyword = rtrim($keyword, 'ves');
$keyword = rtrim($keyword, 'ies');
... ... @@ -700,3 +707,4 @@ class UpdateSeoTdk extends Command
return $mail->add($data);
}
}
... ...
... ... @@ -19,20 +19,16 @@ class Kernel extends ConsoleKernel
// 每日更新最新模块
$schedule->command('template_label')->dailyAt('01:00')->withoutOverlapping(1);//最新模块
$schedule->command('popular_template_label')->dailyAt('01:30')->withoutOverlapping(1);//热门模块
// $schedule->command('inspire')->hourly();
$schedule->command('rank_data_task')->everyMinute()->withoutOverlapping(1); // 排名数据更新任务
$schedule->command('service_count')->dailyAt('01:00')->withoutOverlapping(1); //服务器使用情况,每天凌晨1点执行一次
// $schedule->command('web_traffic_special')->everyMinute()->withoutOverlapping(1); // 特殊引流
// $schedule->command('web_traffic_russia_special')->everyMinute()->withoutOverlapping(1); // 特殊引流
$schedule->command('sync_channel')->dailyAt('06:00')->withoutOverlapping(1); // 渠道信息,每天执行一次
$schedule->command('inquiry_count')->dailyAt('01:00')->withoutOverlapping(1); // 询盘统计数据,每天凌晨执行一次
// $schedule->command('domain_info')->dailyAt('01:20')->withoutOverlapping(1);// 更新域名|证书结束时间,每天凌晨1点执行一次
$schedule->command('share_user')->dailyAt('01:20')->withoutOverlapping(1);// 每天凌晨1点执行一次
$schedule->command('last_inquiry')->dailyAt('04:00')->withoutOverlapping(1);// 最近一次询盘信息
$schedule->command('update_seo_tdk_crontab')->dailyAt('20:00')->withoutOverlapping(1); //更新上线项目TDK
$schedule->command('sync_manager')->dailyAt('01:00')->withoutOverlapping(1); //TODO::手机号码同步 每天执行一次
$schedule->command('update_keyword_route')->dailyAt('01:00')->withoutOverlapping(1); //升级项目--清除路由相同的关键字
$schedule->command('recommended_suppliers')->dailyAt('03:00')->withoutOverlapping(1); //每天凌晨1点执行一次生成推荐商
// $schedule->command('recommended_suppliers')->dailyAt('03:00')->withoutOverlapping(1); //每天凌晨1点执行一次生成推荐商
$schedule->command('update_keyword_content')->hourly()->withoutOverlapping(1);
// 每日推送已完成视频任务项目生成对应界面
//更新AI站点数据
... ... @@ -41,9 +37,6 @@ class Kernel extends ConsoleKernel
$schedule->command('sync_inquiry_text')->dailyAt('09:00')->withoutOverlapping(1);
//FB询盘费用同步
$schedule->command('sync_ad_cost')->everyThirtyMinutes()->withoutOverlapping(1);
// $schedule->command('ai_blog_auto_publish auto_open')->everyMinute()->withoutOverlapping(1);
// $schedule->command('ai_blog_auto_publish auto_publish')->dailyAt('07:00')->withoutOverlapping(1);
}
/**
... ...
... ... @@ -213,7 +213,7 @@ class Common
}
$keyword = str_replace($str,'',$keyword);
$keyword = trim($keyword,'.');
if(strpos(strtolower($keyword),'hope') === false
if( (strpos(strtolower($keyword),'hope') === false || strpos(strtolower($keyword),'hopein') !== false)
&& (strpos(strtolower($keyword),'remember') === false || strpos(strtolower($keyword),'rememberance') !== false)
&& strpos(strtolower($keyword),'help') === false
&& strpos(strtolower($keyword),'website') === false
... ...
... ... @@ -432,4 +432,29 @@ class PrivateController extends BaseController
DB::disconnect('custom_mysql');
$this->response('success',Code::SUCCESS,$data);
}
/**
* 获取项目监控关键词
* @param Request $request
* @return false|string
*/
public function getMonitorKeyword(Request $request)
{
$domain = trim($request->input('domain'));
$domain_parse = parse_url($domain);
$domain = $domain_parse['host'] ?? $domain;
if (empty($domain)) {
return $this->error('非法参数!');
}
$project = Project::getProjectByDomain($domain);
if (empty($project)) {
return $this->error('未找到当前域名对应的项目!');
}
$json = file_get_contents(storage_path('data/send_product_tag_keyword/' . $project->id . '.json'));
$result = json_decode($json, true) ?: [];
return $this->success($result);
}
}
... ...
... ... @@ -224,6 +224,7 @@ class OptimizeController extends BaseController
'gl_project_deploy_optimize.backlink AS backlink',
'gl_project_deploy_optimize.ai_video AS ai_video',
'gl_project_deploy_optimize.api_no AS api_no',
'gl_project_deploy_optimize.first_compliance_time AS first_compliance_time',
'gl_domain_info.amp_status AS amp_status',
'gl_domain_info.domain AS domain',
];
... ...
... ... @@ -136,6 +136,9 @@ class ProductController extends BaseController
'id.required' => 'ID不能为空'
]);
$info = $product->read(['id'=>$this->param['id']]);
if($info === false){
$this->fail('当前数据不存在,或已被删除');
}
$info = $this->handleParam($info);
return $this->response('success',Code::SUCCESS,$info);
}
... ... @@ -659,6 +662,9 @@ class ProductController extends BaseController
if(isset($this->map['created_uid'])){
$query = $query->where('created_uid',$this->map['created_uid']);
}
if(isset($this->map['six_read'])){
$query = $query->where('six_read',$this->map['six_read']);
}
if(!empty($this->param['start_at']) && !empty($this->param['end_at'])){
if($this->user['project_id'] == 2059){
$query->where('send_time', '>=' ,$this->param['start_at'].' 00:00:00')->where('send_time', '<=' ,$this->param['end_at'].' 59:59:59');
... ...
... ... @@ -163,7 +163,7 @@ class ProjectLogic extends BaseLogic
$this->setTypeSevenEdit($this->param);
}else{
//初始化项目
$this->createProjectData($this->param);
$this->param = $this->createProjectData($this->param);
//双向绑定服务器,需放到保存项目的上方
$this->setServers($this->param['serve_id'],$this->param['id']);
//ai_blog
... ... @@ -196,32 +196,6 @@ class ProjectLogic extends BaseLogic
}
/**
* @remark :开启推荐供应商设置
* @name :isPurchaser
* @author :lyh
* @method :post
* @time :2025/3/10 15:33
*/
public function isPurchaser($project_id){
if($this->param['type'] == Project::TYPE_TWO){
if(empty($this->param['uptime'])){
$this->param['deploy_build']['is_supplier'] = 1;
}else{
//获取项目的上线时间
$projectInfo = $this->model->read(['id'=>$project_id],['uptime']);
//查看上线时间是否大于3天
$threeDaysAgo = date('Y-m-d H:i:s', strtotime('-3 days'));
if($projectInfo['uptime'] > $threeDaysAgo){
//上线时间大于当前时间的3天钱,默认不允许关闭推荐供应商
$this->param['deploy_build']['is_supplier'] = 1;
}
}
return true;
}
}
/**
* @remark :开启AI博客后
* @name :setAiBlog
* @author :lyh
... ... @@ -243,7 +217,7 @@ class ProjectLogic extends BaseLogic
$aiSettingInfo = $aiSettingModel->read(['project_id'=>$project_id]);
if($aiSettingInfo === false){
$aiBlogService = new AiBlogService();
$result = $aiBlogService->createProject($title,$languageInfo['short'],$projectInfo['company']);
$result = $aiBlogService->createProject($projectInfo['company'] ?? $title,$languageInfo['short'],$projectInfo['company']);
if(isset($result['status']) && $result['status'] == 200){
//查看当前项目是否已有记录
$resData = [
... ... @@ -350,8 +324,19 @@ class ProjectLogic extends BaseLogic
* @time :2023/8/30 12:14
*/
public function saveProject($param){
if((($param['type'] == Project::TYPE_TWO) || ($param['type'] == Project::TYPE_THREE)) && empty($param['uptime'])){
$param['uptime'] = date('Y-m-d H:i:s');
if((($param['type'] == Project::TYPE_TWO) || ($param['type'] == Project::TYPE_THREE))){
//自动开启推荐供应商
if(empty($param['uptime'])){
$this->param['deploy_build']['is_supplier'] = 1;
$param['uptime'] = date('Y-m-d H:i:s');
}else{
//查看上线时间是否大于3天
$threeDaysAgo = date('Y-m-d H:i:s', strtotime('-3 days'));
if($param['uptime'] > $threeDaysAgo){
//上线时间大于当前时间的3天钱,默认不允许关闭推荐供应商
$this->param['deploy_build']['is_supplier'] = 1;
}
}
}
if($param['type'] == Project::TYPE_FIVE){
$param['extend_type'] = Project::TYPE_FIVE;
... ... @@ -456,6 +441,7 @@ class ProjectLogic extends BaseLogic
//更改域名
$this->editDomainStatus($deploy_optimize['domain'],$deploy_optimize['project_id']);
}
$deploy_optimize['gw_search_logs'] = Arr::a2s($deploy_optimize['gw_search_logs'] ?? []);
$deploy_optimize['start_date'] = $deploy_optimize['start_date'] ?? '';
$deploy_optimize['g_top_plan'] = Arr::a2s($deploy_optimize['g_top_plan'] ?? []);
$deploy_optimize['special'] = !empty($deploy_optimize['special']) ? ','.trim($deploy_optimize['special'],',').',' : '';
... ... @@ -603,7 +589,7 @@ class ProjectLogic extends BaseLogic
//改为异步
NoticeLog::createLog(NoticeLog::TYPE_INIT_PROJECT, ['project_id' => $param['id']]);
}
return $this->success();
return $this->success($param);
}
/**
... ...
... ... @@ -490,18 +490,7 @@ class RankDataLogic extends BaseLogic
$without_extension_project_ids = [658]; //是否达标只统计主词的
$extension_project_ids = [354]; //扩展词也到达标的
$compliance_project_ids = [2163,257]; //直接达标处理的
$ceaseProjectId = [
47,
354,
378,
649,
1226,
1283,
1703,
1893,
2066,
];//暂停项目id
$ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066,];//暂停项目id
//一个项目多个api_no
$multiple_api_no_project_ids = [
2104 => [
... ... @@ -515,15 +504,6 @@ class RankDataLogic extends BaseLogic
$g_top_first_page_extension_num = 0;
foreach ($data as &$ranks){
ksort($ranks);
// foreach ($ranks as &$rank){
// //处理排名
// if(!in_array($project_id, $without_project_ids)){
// if($rank['position'] >= 10){
// $rank['position'] -= 5;
// }
// //todo 需要特殊处理排名的项目
// }
// }
$last = Arr::last($ranks);
//第一名
if($last['position'] == 1){
... ... @@ -586,6 +566,9 @@ class RankDataLogic extends BaseLogic
if (($model->updated_date != date('Y-m-d') || empty($model_is_compliance)) && !$lang) {
$compliance_day = Project::where(['id' => $project_id])->value('finish_remain_day') ?: 0;
if(!in_array($project_id,$ceaseProjectId)){
if($compliance_day == 0){//达标天数为0并当天达标 记录当前达标时间
DeployOptimize::where(['project_id'=>$project_id])->update(['first_compliance_time'=>date('Y-m-d')]);
}
//多api_no项目 要api_no都分别达标才算
if(in_array($project_id, array_keys($multiple_api_no_project_ids))){
$api_nos = array_keys($multiple_api_no_project_ids[$project_id]);
... ...
... ... @@ -50,6 +50,19 @@ class Keyword extends Base
];
/**
* 聚合页按照首字母归类
* @param $string
* @return int
*/
public function getFirstWord($string) {
$first_string = strtolower(mb_substr($string, 0, 1));
if (is_numeric($first_string))
return 0;
$string_key = array_search($first_string, $this->firstNumWord);
return $string_key ?: 27;
}
/**
* @remark :视频
* @name :getKeywordVideoAttribute
* @author :lyh
... ... @@ -97,4 +110,43 @@ class Keyword extends Base
return Keyword::where("project_id",$project->id)->where("status",1)->inRandomOrder()->take(10)->get();
}
/**
* 拆解关键词, 拼接成为长尾关键词
* @param $project_id
* @return array
*/
public static function extendKeyword($project_id)
{
$result = [];
$keywords = self::where(['project_id' => $project_id])->pluck('seo_title', 'title')->toArray();
if (empty($keywords))
return $result;
// $item:前缀 + 关键词 + 后缀
foreach ($keywords as $keyword => $item) {
try {
if (empty($keyword) || empty($item))
continue;
// 如果title数据无法正常解析, 就将数据完整填充
$tmp = explode($keyword, $item);
if (count($tmp) <= 1) {
array_push($result, $item);
continue;
}
// 正常数据 一个关键词会拆分成为 3或者5个关键词
// 拆分规则:前缀 + 关键词; 关键词 + 后缀;前缀 + 关键词 + 后缀;
$prefix = $tmp[0];
$suffix_array = explode(',', $tmp[1]);
array_push($result, trim($prefix . $keyword));
foreach ($suffix_array as $suffix) {
array_push($result, trim($keyword . $suffix));
array_push($result, trim($prefix . $keyword . $suffix));
}
} catch (\Exception $e) {
continue;
}
}
return $result;
}
}
... ...
... ... @@ -22,6 +22,11 @@ class DeployOptimize extends Base
public function getGTopPlanAttribute($value){
return Arr::s2a($value);
}
public function getGwSearchLogsAttribute($value){
return Arr::s2a($value);
}
public static function clearCache($row){
$cache_key = 'project_' . $row->original['domain'];
Cache::forget($cache_key);
... ...
... ... @@ -58,6 +58,8 @@ Route::any('get_project_online', [\App\Http\Controllers\Api\PrivateController::c
Route::any('mark_project_ads', [\App\Http\Controllers\Api\PrivateController::class, 'markProjectAds'])->name('api.mark_project_ads');
//获取对应产品关键词
Route::any('getProjectKeyword', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectKeyword'])->name('api.getProjectKeyword');
// 获取监控关键词 -> send_product_tag_keyword
Route::any('get_monitor_keyword', [\App\Http\Controllers\Api\PrivateController::class, 'getMonitorKeyword'])->name('api.get_monitor_keyword');
//自建站接口转接
Route::post('selfSiteApi', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteApi']);
Route::post('selfSiteNotify', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteNotify']);
... ...