作者 邓超

Merge branch 'develop' into dc

@@ -41,6 +41,7 @@ class ShareConfig extends Command @@ -41,6 +41,7 @@ class ShareConfig extends Command
41 $ayrShareHelper = new AyrShareHelper(); 41 $ayrShareHelper = new AyrShareHelper();
42 $share_info = $ayrShareHelper->get_profiles_users($v['profile_key']); 42 $share_info = $ayrShareHelper->get_profiles_users($v['profile_key']);
43 if(!isset($share_info['activeSocialAccounts'])){ 43 if(!isset($share_info['activeSocialAccounts'])){
  44 + $ayrShareModel->edit(['bind_plat_from'=>''],['id'=>$v['id']]);
44 continue; 45 continue;
45 } 46 }
46 $str = json_encode($share_info['activeSocialAccounts']); 47 $str = json_encode($share_info['activeSocialAccounts']);
@@ -62,7 +62,11 @@ class ShareUser extends Command @@ -62,7 +62,11 @@ class ShareUser extends Command
62 } 62 }
63 //删除用户第三方配置 63 //删除用户第三方配置
64 $ayr_share_helper = new AyrShareHelper(); 64 $ayr_share_helper = new AyrShareHelper();
65 - $res = $ayr_share_helper->deleted_profiles(); 65 + $data_profiles = [
  66 + 'title'=>$v['title'],
  67 + 'profileKey'=>$v['profile_key']
  68 + ];
  69 + $res = $ayr_share_helper->deleted_profiles($data_profiles);
66 if($res['status'] == 'fail'){ 70 if($res['status'] == 'fail'){
67 $this->error++; 71 $this->error++;
68 continue; 72 continue;
@@ -48,7 +48,7 @@ class RankData extends BaseCommands @@ -48,7 +48,7 @@ class RankData extends BaseCommands
48 48
49 foreach ($list as $item){ 49 foreach ($list as $item){
50 $model = GoogleRankModel::where('project_id', $item['project_id'])->where('lang', '')->first(); 50 $model = GoogleRankModel::where('project_id', $item['project_id'])->where('lang', '')->first();
51 - if (!$model || $model->updated_date == date('Y-m-d')) { 51 + if (!$model || $model->updated_date != date('Y-m-d')) {
52 $res = $api->getGoogleRank($item['api_no']); 52 $res = $api->getGoogleRank($item['api_no']);
53 if(!$res){ 53 if(!$res){
54 $error++; 54 $error++;
@@ -63,7 +63,7 @@ class RankData extends BaseCommands @@ -63,7 +63,7 @@ class RankData extends BaseCommands
63 //有小语种的 63 //有小语种的
64 if($item['minor_languages']){ 64 if($item['minor_languages']){
65 $model = GoogleRankModel::where('project_id', $item['project_id'])->where('lang', '<>', '')->first(); 65 $model = GoogleRankModel::where('project_id', $item['project_id'])->where('lang', '<>', '')->first();
66 - if (!$model || $model->updated_date == date('Y-m-d')) { 66 + if (!$model || $model->updated_date != date('Y-m-d')) {
67 $res = $api->getGoogleRank($item['api_no'], 1); 67 $res = $api->getGoogleRank($item['api_no'], 1);
68 if(!$res){ 68 if(!$res){
69 $error++; 69 $error++;
@@ -98,6 +98,7 @@ class RankData extends BaseCommands @@ -98,6 +98,7 @@ class RankData extends BaseCommands
98 98
99 if(!$lang){ 99 if(!$lang){
100 foreach ($data as &$ranks){ 100 foreach ($data as &$ranks){
  101 + ksort($ranks);
101 foreach ($ranks as &$rank){ 102 foreach ($ranks as &$rank){
102 //处理排名 103 //处理排名
103 if(!in_array($project_id, $without_project_ids)){ 104 if(!in_array($project_id, $without_project_ids)){
@@ -137,4 +137,70 @@ class QuanqiusouApi @@ -137,4 +137,70 @@ class QuanqiusouApi
137 return $res; 137 return $res;
138 } 138 }
139 139
  140 +
  141 + /**
  142 + * 获取历史排名统计数据
  143 + * @param $api_no
  144 + * @param string $lang
  145 + * @return array|false|int|mixed|null
  146 + * @author zbj
  147 + * @date 2023/5/15
  148 + */
  149 + public function getHistoryCount($api_no, $lang = '')
  150 + {
  151 + $key = "quanqiusou_api_history_count_{$api_no}_{$lang}_" . date('Y-m-d');
  152 + $res = Cache::get($key);
  153 + if (!$res) {
  154 + $api_url = $this->url . '/google-rank/history_count.php';
  155 + $param = [
  156 + 'apino' => $api_no,
  157 + ];
  158 + if ($lang) {
  159 + $param['lang'] = $lang;
  160 + }
  161 + try {
  162 + $res = HttpUtils::get($api_url, $param);
  163 + if($res){
  164 + $res = Arr::s2a($res);
  165 + Cache::put($key, $res, 24 * 3600);
  166 + }
  167 + } catch (\Exception | GuzzleException $e) {
  168 + errorLog('获取历史排名统计数据失败', [], $e);
  169 + return false;
  170 + }
  171 + }
  172 + return $res;
  173 + }
  174 +
  175 +
  176 + /**
  177 + * 获取小语种项目
  178 + * @return array|false|int|mixed|null
  179 + * @author zbj
  180 + * @date 2023/5/15
  181 + */
  182 + public function getLangList()
  183 + {
  184 + $key = "quanqiusou_api_lang_list_" . date('Y-m-d');
  185 + $res = Cache::get($key);
  186 + if (!$res) {
  187 + $api_url = $this->url . '/api/index/langlist';
  188 + $param = [
  189 + 'key' => '289c1fc81c89d79c04ed4fd72822948e',
  190 + ];
  191 + try {
  192 + $res = HttpUtils::get($api_url, $param);
  193 + if($res){
  194 + $res = Arr::s2a($res);
  195 + Cache::put($key, $res, 2 * 3600);
  196 + }
  197 + } catch (\Exception | GuzzleException $e) {
  198 + errorLog('获取小语种项目数据失败', [], $e);
  199 + return false;
  200 + }
  201 + }
  202 + return $res;
  203 + }
  204 +
  205 +
140 } 206 }
@@ -5,13 +5,9 @@ namespace App\Http\Controllers\Bside\AyrShare; @@ -5,13 +5,9 @@ namespace App\Http\Controllers\Bside\AyrShare;
5 use App\Enums\Common\Code; 5 use App\Enums\Common\Code;
6 use App\Helper\AyrShare as AyrShareHelper; 6 use App\Helper\AyrShare as AyrShareHelper;
7 use App\Http\Controllers\Bside\BaseController; 7 use App\Http\Controllers\Bside\BaseController;
8 -use App\Http\Controllers\Bside\FileController;  
9 -use App\Http\Controllers\File\ImageController;  
10 use App\Http\Logic\Bside\AyrShare\AyrReleaseLogic; 8 use App\Http\Logic\Bside\AyrShare\AyrReleaseLogic;
11 use App\Http\Logic\Bside\AyrShare\AyrShareLogic; 9 use App\Http\Logic\Bside\AyrShare\AyrShareLogic;
12 use App\Http\Requests\Bside\AyrRelease\AyrReleaseRequest; 10 use App\Http\Requests\Bside\AyrRelease\AyrReleaseRequest;
13 -use App\Models\File\Image;  
14 -use App\Models\File\Image as ImageModel;  
15 11
16 /** 12 /**
17 * @name:社交发布 13 * @name:社交发布
@@ -61,9 +57,10 @@ class AyrReleaseController extends BaseController @@ -61,9 +57,10 @@ class AyrReleaseController extends BaseController
61 public function send_post(AyrReleaseRequest $ayrReleaseRequest,AyrReleaseLogic $ayrReleaseLogic, 57 public function send_post(AyrReleaseRequest $ayrReleaseRequest,AyrReleaseLogic $ayrReleaseLogic,
62 AyrShareLogic $ayrShareLogic,AyrShareHelper $ayrShare){ 58 AyrShareLogic $ayrShareLogic,AyrShareHelper $ayrShare){
63 $ayrReleaseRequest->validated(); 59 $ayrReleaseRequest->validated();
64 - //验证发送平台  
65 //获取发送账号详情 60 //获取发送账号详情
66 $share_info = $ayrShareLogic->ayr_share_info(); 61 $share_info = $ayrShareLogic->ayr_share_info();
  62 + //验证发送平台
  63 + $ayrShareLogic->verify_param($share_info);
67 $data = [ 64 $data = [
68 'images'=>$this->param['images'], 65 'images'=>$this->param['images'],
69 'files'=>$this->param['video'], 66 'files'=>$this->param['video'],
@@ -25,20 +25,22 @@ class AyrShareController extends BaseController @@ -25,20 +25,22 @@ class AyrShareController extends BaseController
25 public function lists(AyrShareModel $ayrShareModel,AyrShareLogic $ayrShareLogic){ 25 public function lists(AyrShareModel $ayrShareModel,AyrShareLogic $ayrShareLogic){
26 //授权配置列表 26 //授权配置列表
27 $share_list = $ayrShareModel->platforms; 27 $share_list = $ayrShareModel->platforms;
28 - $lists = $ayrShareModel->lists($this->map,$this->page,$this->row,'id',['id','name','title','profile_key','bind_plat_from','operator_id','created_at','updated_at']); 28 + $lists = $ayrShareModel->lists($this->map,$this->page,$this->row,'id',['id','name','title','profile_key','bind_platforms','operator_id','created_at','updated_at']);
29 foreach ($lists['list'] as $k => $v){ 29 foreach ($lists['list'] as $k => $v){
30 if(!empty($v['profile_key'])){ 30 if(!empty($v['profile_key'])){
31 $ayrShareHelper = new AyrShareHelper(); 31 $ayrShareHelper = new AyrShareHelper();
32 $share_info = $ayrShareHelper->get_profiles_users($v['profile_key']); 32 $share_info = $ayrShareHelper->get_profiles_users($v['profile_key']);
33 if(isset($share_info['activeSocialAccounts'])){ 33 if(isset($share_info['activeSocialAccounts'])){
34 $str = json_encode($share_info['activeSocialAccounts']); 34 $str = json_encode($share_info['activeSocialAccounts']);
35 - if($str != $v['bind_plat_from']){  
36 - $ayrShareLogic->ayr_share_edit(['bind_plat_from'=>$str]); 35 + if($str != $v['bind_platforms']){
  36 + $ayrShareLogic->ayr_share_edit(['bind_platforms'=>$str],$v['id']);
37 } 37 }
  38 + }else{
  39 + $ayrShareLogic->ayr_share_edit(['bind_platforms'=>''],$v['id']);
38 } 40 }
39 } 41 }
40 } 42 }
41 - $lists['share_list'] = $share_list; 43 + $lists['list']['share_list'] = $share_list;
42 $this->response('列表',Code::SUCCESS,$lists); 44 $this->response('列表',Code::SUCCESS,$lists);
43 } 45 }
44 46
@@ -59,11 +61,13 @@ class AyrShareController extends BaseController @@ -59,11 +61,13 @@ class AyrShareController extends BaseController
59 $share_info = $ayrShareHelper->get_profiles_users($info['profile_key']); 61 $share_info = $ayrShareHelper->get_profiles_users($info['profile_key']);
60 if(isset($share_info['activeSocialAccounts'])){ 62 if(isset($share_info['activeSocialAccounts'])){
61 $str = json_encode($share_info['activeSocialAccounts']); 63 $str = json_encode($share_info['activeSocialAccounts']);
62 - if($str != $info['bind_plat_from']){  
63 - $res = $ayrShareLogic->ayr_share_edit(['bind_plat_from'=>$str]); 64 + if($str != $info['bind_platforms']){
  65 + $res = $ayrShareLogic->ayr_share_edit(['bind_platforms'=>$str],$this->param['share_id']);
64 }else{ 66 }else{
65 $res = false; 67 $res = false;
66 } 68 }
  69 + }else{
  70 + $res = $ayrShareLogic->ayr_share_edit(['bind_platforms'=>''],$this->param['share_id']);
67 } 71 }
68 $this->response('success',Code::SUCCESS,['is_true'=>$res]); 72 $this->response('success',Code::SUCCESS,['is_true'=>$res]);
69 } 73 }
@@ -2,8 +2,14 @@ @@ -2,8 +2,14 @@
2 2
3 namespace App\Http\Controllers\Bside; 3 namespace App\Http\Controllers\Bside;
4 4
  5 +
  6 +use App\Helper\GoogleSpeedApi;
  7 +use App\Helper\QuanqiusouApi;
  8 +use App\Http\Logic\Aside\Project\ProjectLogic;
5 use App\Http\Logic\Bside\RankDataLogic; 9 use App\Http\Logic\Bside\RankDataLogic;
6 -use Illuminate\Http\Request; 10 +use App\Models\RankData\Speed as GoogleSpeedModel;
  11 +use App\Services\BatchExportService;
  12 +use Illuminate\Support\Facades\Storage;
7 13
8 /** 14 /**
9 * Class GoogleRankController 15 * Class GoogleRankController
@@ -20,8 +26,126 @@ class RankDataController extends BaseController @@ -20,8 +26,126 @@ class RankDataController extends BaseController
20 return $this->success($data); 26 return $this->success($data);
21 } 27 }
22 28
  29 + /**
  30 + * 关键词排名列表
  31 + * @param RankDataLogic $logic
  32 + * @return \Illuminate\Http\JsonResponse
  33 + * @author zbj
  34 + * @date 2023/5/15
  35 + */
23 public function keywords_rank_list(RankDataLogic $logic){ 36 public function keywords_rank_list(RankDataLogic $logic){
24 $data = $logic->keywords_rank_list(); 37 $data = $logic->keywords_rank_list();
25 return $this->success($data); 38 return $this->success($data);
26 } 39 }
  40 +
  41 +
  42 + /**
  43 + * 刷新测速
  44 + * @param ProjectLogic $projectLogic
  45 + * @param GoogleSpeedApi $googleSpeedApi
  46 + * @return \Illuminate\Http\JsonResponse
  47 + * @throws \App\Exceptions\AsideGlobalException
  48 + * @throws \App\Exceptions\BsideGlobalException
  49 + * @author zbj
  50 + * @date 2023/5/15
  51 + */
  52 + public function speed(ProjectLogic $projectLogic, GoogleSpeedApi $googleSpeedApi){
  53 + $project_id = $this->user['project_id'];
  54 + $project = $projectLogic->getInfo($project_id);
  55 + $domain = $project['deploy_optimize']['domain'] ?? '';
  56 + $data = $googleSpeedApi->run($domain);
  57 + if($data){
  58 + $model = GoogleSpeedModel::where('project_id', $project_id)->first();
  59 + $model->project_id = $project_id;
  60 + $model->data = $data;
  61 + $model->updated_date = date('Y-m-d');
  62 + $model->save();
  63 + }
  64 + return $this->success($data);
  65 + }
  66 +
  67 + /**
  68 + * 数据导出
  69 + * @author zbj
  70 + * @date 2023/5/15
  71 + */
  72 + public function export(RankDataLogic $logic){
  73 + $data = $logic->keywords_rank_list(true);
  74 + foreach ($data as &$item){
  75 + $item['domain'] = explode(':', $item['domain'])[1];
  76 + $item['lang'] = $this->request['lang'] ?: 'en';
  77 + $item['g_text'] = $item['g'] == 1 ? '主关键词' : '拓展关键词';
  78 + foreach ($item['position'] as $date => $position){
  79 + $item[$date] = $position;
  80 + }
  81 + }
  82 +
  83 + $map = [
  84 + 'keyword' => '关键词',
  85 + 'domain' => '排名网址',
  86 + 'lang' => '语言',
  87 + 'g_text' => '关键词类型',
  88 + ];
  89 + foreach ($data[0]['position'] as $date => $position){
  90 + $map[$date] = $date;
  91 + }
  92 +
  93 + //生成文件,发送到客户端
  94 + $table = new BatchExportService("关键词数据导出");
  95 + $file = $table->head($map)->data($data)->save();
  96 + if (!$file) {
  97 + throw new \Exception('文件生成失败,请重试');
  98 + }
  99 + $fileurl = Storage::disk('runtime')->url($file);
  100 +// return Storage::disk('runtime')->download($file); //直接下载
  101 + return $this->success(['url' => $fileurl]);
  102 + }
  103 +
  104 + /**
  105 + * 数据导出
  106 + * @author zbj
  107 + * @date 2023/5/15
  108 + */
  109 + public function export_history(RankDataLogic $logic, ProjectLogic $projectLogic, QuanqiusouApi $quanqiusouApi){
  110 + $project_id = $this->user['project_id'];
  111 + $project = $projectLogic->getInfo($project_id);
  112 + $lang = $this->request['lang'] ??'';
  113 + $data = $quanqiusouApi->getHistoryCount($project['deploy_optimize']['api_no'], $lang);
  114 + if($lang){
  115 + foreach ($data['data'] as &$item){
  116 + $item['c_date'] = date("Y-m-d",strtotime($item['c_date'] . ' +1day'));
  117 + $item['reach'] = $item['home_cnt'] >= $data['bz_count'] ? '是' : '否';
  118 + }
  119 + $map = [
  120 + 'c_date' => '日期',
  121 + 'home_cnt' => '第一页',
  122 + 'reach' => '是否达标',
  123 + ];
  124 + }else{
  125 + foreach ($data['data'] as &$item){
  126 + $item['c_date'] = date("Y-m-d",strtotime($item['c_date'] . ' +1day'));
  127 + $item['reach'] = $item['cnt_home'] >= $project['deploy_build']['keyword_num'] ? '是' : '否';
  128 + }
  129 + $map = [
  130 + 'c_date' => '日期',
  131 + 'cnt_first' => '排名第一',
  132 + 'cnt_home' => '第一页',
  133 + 'cnt_thirty' => '前三页',
  134 + 'cnt_fifty' => '前五页',
  135 + 'cnt_hundred' => '前十页',
  136 + 'reach' => '是否达标',
  137 + ];
  138 + }
  139 +
  140 +
  141 + //生成文件,发送到客户端
  142 + $table = new BatchExportService($lang . "关键词历史数据导出");
  143 + $file = $table->head($map)->data($data['data'])->save();
  144 + if (!$file) {
  145 + throw new \Exception('文件生成失败,请重试');
  146 + }
  147 + $fileurl = Storage::disk('runtime')->url($file);
  148 +// return Storage::disk('runtime')->download($file); //直接下载
  149 + return $this->success(['url' => $fileurl]);
  150 + }
27 } 151 }
  1 +<?php
  2 +
  3 +namespace App\Http\Logic\Aside\Project;
  4 +
  5 +
  6 +use App\Http\Logic\Aside\BaseLogic;
  7 +use App\Models\Project\DomainInfo;
  8 +use App\Models\Project\Payment;
  9 +use MongoDB\Client;
  10 +
  11 +class DomainInfoLogic extends BaseLogic
  12 +{
  13 + public function __construct()
  14 + {
  15 + parent::__construct();
  16 +
  17 + $this->model = new DomainInfo();
  18 + }
  19 +
  20 + public function getDomainInfo($project_id)
  21 + {
  22 + $project = app(ProjectLogic::class)->getInfo($project_id);
  23 + $domain = $project['deploy_optimize']['domain'];
  24 + $info = $this->model->where('project_id', $project_id)->first();
  25 + //不存在或时间过期了 重新获取信息
  26 + $expiration_date = $info['domain_info']['expiration_date'] ?? '';
  27 + $end_time = $info['ssl']['end_time'] ?? '';
  28 + if(!$info || $expiration_date < date("Y-m-d") || $end_time < date('Y-m-d')){
  29 + try {
  30 + $mongo = new Client("mongodb://root:globalso8837840@23.228.125.2:27017");
  31 + $db = $mongo->globalso_monitor;
  32 + $collection = $db->project_v1;
  33 + $project_zk = $collection->findOne(['main_url' => $domain]);
  34 + $info['domain'] = $domain;
  35 + $info['domain_info'] = (array) $project_zk['domain_info'] ?? [];
  36 + $info['ssl'] = (array) $project_zk['ssl'] ?? [];
  37 + parent::save($info);
  38 + }catch (\Exception $e){
  39 + return [];
  40 + }
  41 + }
  42 + return $info;
  43 + }
  44 +}
@@ -56,7 +56,8 @@ class AyrReleaseLogic extends BaseLogic @@ -56,7 +56,8 @@ class AyrReleaseLogic extends BaseLogic
56 $arr = []; 56 $arr = [];
57 foreach ($data as $k => $v){ 57 foreach ($data as $k => $v){
58 if($k == 'images'){ 58 if($k == 'images'){
59 - $images = explode(',',$v); 59 +// $images = explode(',',$v);
  60 + $images = $v;
60 $imageModel = new Image(); 61 $imageModel = new Image();
61 $list = $imageModel->list(['hash'=>['in',$images]],'id'); 62 $list = $imageModel->list(['hash'=>['in',$images]],'id');
62 foreach ($list as $v1){ 63 foreach ($list as $v1){
@@ -6,10 +6,32 @@ use App\Http\Logic\Bside\BaseLogic; @@ -6,10 +6,32 @@ use App\Http\Logic\Bside\BaseLogic;
6 use App\Models\AyrShare\AyrShare; 6 use App\Models\AyrShare\AyrShare;
7 use App\Models\File\File as FileModel; 7 use App\Models\File\File as FileModel;
8 use App\Models\File\Image as ImageModel; 8 use App\Models\File\Image as ImageModel;
9 - 9 +/**
  10 + * @name:社交发布图片数量
  11 + * Facebook Pages and Groups: 10 images, including a carousel post.
  12 + * Instagram: 10 images.
  13 + * Google : 1 image.
  14 + * LinkedIn: 9 images.
  15 + * Pinterest: 1 image.
  16 + * Reddit: 1 image.
  17 + * Telegram: 1 image.
  18 + * Twitter:4 image
  19 + */
10 class AyrShareLogic extends BaseLogic 20 class AyrShareLogic extends BaseLogic
11 { 21 {
12 - 22 + /**
  23 + * @var :发布图片数量
  24 + */
  25 + public $send_num = [
  26 + 'facebook' => 10,
  27 + 'instagram' => 10,
  28 + 'google' => 1,
  29 + 'linkedin'=>9,
  30 + 'reddit'=>1,
  31 + 'pinterest'=>1,
  32 + 'telegram'=>1,
  33 + 'Twitter'=>1,
  34 + ];
13 35
14 public function __construct() 36 public function __construct()
15 { 37 {
@@ -61,8 +83,8 @@ class AyrShareLogic extends BaseLogic @@ -61,8 +83,8 @@ class AyrShareLogic extends BaseLogic
61 * @method :post 83 * @method :post
62 * @time :2023/5/9 14:44 84 * @time :2023/5/9 14:44
63 */ 85 */
64 - public function ayr_share_edit($param){  
65 - $rs = $this->model->edit($param,['id'=>$this->param['id']]); 86 + public function ayr_share_edit($param,$id = ''){
  87 + $rs = $this->model->edit($param,['id'=>$id]);
66 if($rs === false){ 88 if($rs === false){
67 $this->fail('error'); 89 $this->fail('error');
68 } 90 }
@@ -83,7 +105,7 @@ class AyrShareLogic extends BaseLogic @@ -83,7 +105,7 @@ class AyrShareLogic extends BaseLogic
83 return $this->success(); 105 return $this->success();
84 } 106 }
85 /** 107 /**
86 - * @name :(更新图片库)save_info_info 108 + * @name :(根据hash获取图片详情)save_info_info
87 * @author :lyh 109 * @author :lyh
88 * @method :post 110 * @method :post
89 * @time :2023/5/10 15:01 111 * @time :2023/5/10 15:01
@@ -98,7 +120,7 @@ class AyrShareLogic extends BaseLogic @@ -98,7 +120,7 @@ class AyrShareLogic extends BaseLogic
98 } 120 }
99 121
100 /** 122 /**
101 - * @name :(更新图片库)save_info_info 123 + * @name :(根据hash视频详情)save_info_info
102 * @author :lyh 124 * @author :lyh
103 * @method :post 125 * @method :post
104 * @time :2023/5/10 15:01 126 * @time :2023/5/10 15:01
@@ -171,6 +193,33 @@ class AyrShareLogic extends BaseLogic @@ -171,6 +193,33 @@ class AyrShareLogic extends BaseLogic
171 } 193 }
172 return $this->success(); 194 return $this->success();
173 } 195 }
  196 +
  197 + /**
  198 + * @name :(验证平台参数)verify_param
  199 + * @author :lyh
  200 + * @method :post
  201 + * @time :2023/5/16 9:19
  202 + * ["facebook","fbg","gmb","instagram","linkedin","pinterest","reddit","telegram","tiktok","twitter","youtube"]
  203 + */
  204 + public function verify_param($info){
  205 + //验证发送平台
  206 + foreach ($this->param['platforms'] as $k => $v){
  207 + if(!in_array($v,json_decode($info['bind_platforms']))){
  208 + $this->fail('未绑定平台');
  209 + }
  210 + //验证图片数
  211 + $img_num = count($this->param['images']);
  212 + if($img_num > $this->send_num[$v]){
  213 + $this->fail('发布图片数量超过最大限制,'.$v.'只允许'.$this->send_num[$v].'张图');
  214 + }
  215 + //验证图片数
  216 + $img_num = count($this->param['video']);
  217 + if($img_num > 1){
  218 + $this->fail('发布视频数量超过最大限制,'.$v.'只允许'.$this->send_num[$v].'个视频');
  219 + }
  220 + }
  221 + return $this->success();
  222 + }
174 } 223 }
175 224
176 225
@@ -5,6 +5,7 @@ namespace App\Http\Logic\Bside; @@ -5,6 +5,7 @@ namespace App\Http\Logic\Bside;
5 5
6 use App\Helper\Arr; 6 use App\Helper\Arr;
7 use App\Helper\Translate; 7 use App\Helper\Translate;
  8 +use App\Http\Logic\Aside\Project\DomainInfoLogic;
8 use App\Http\Logic\Aside\Project\ProjectLogic; 9 use App\Http\Logic\Aside\Project\ProjectLogic;
9 use App\Models\RankData\ExternalLinks; 10 use App\Models\RankData\ExternalLinks;
10 use App\Models\RankData\IndexedPages; 11 use App\Models\RankData\IndexedPages;
@@ -12,6 +13,9 @@ use App\Models\RankData\RankData; @@ -12,6 +13,9 @@ use App\Models\RankData\RankData;
12 use App\Models\RankData\RankWeek; 13 use App\Models\RankData\RankWeek;
13 use App\Models\RankData\RecommDomain; 14 use App\Models\RankData\RecommDomain;
14 use App\Models\RankData\Speed; 15 use App\Models\RankData\Speed;
  16 +use App\Utils\HttpUtils;
  17 +use GuzzleHttp\Exception\GuzzleException;
  18 +use Illuminate\Support\Facades\Cache;
15 use Illuminate\Support\Str; 19 use Illuminate\Support\Str;
16 20
17 class RankDataLogic extends BaseLogic 21 class RankDataLogic extends BaseLogic
@@ -28,6 +32,7 @@ class RankDataLogic extends BaseLogic @@ -28,6 +32,7 @@ class RankDataLogic extends BaseLogic
28 32
29 //查数据 33 //查数据
30 $project = app(ProjectLogic::class)->getInfo($project_id); 34 $project = app(ProjectLogic::class)->getInfo($project_id);
  35 + $domain_info = app(DomainInfoLogic::class)->getDomainInfo($project_id);
31 $rank = RankData::where('project_id', $project_id)->first(); 36 $rank = RankData::where('project_id', $project_id)->first();
32 $rank_week = RankWeek::where('project_id', $project_id)->first(); 37 $rank_week = RankWeek::where('project_id', $project_id)->first();
33 $recomm_domain = RecommDomain::where('project_id', $project_id)->first(); 38 $recomm_domain = RecommDomain::where('project_id', $project_id)->first();
@@ -48,7 +53,7 @@ class RankDataLogic extends BaseLogic @@ -48,7 +53,7 @@ class RankDataLogic extends BaseLogic
48 53
49 //小语种列表 54 //小语种列表
50 $langs = Arr::pluck($project['deploy_optimize']['minor_languages'], 'tl'); 55 $langs = Arr::pluck($project['deploy_optimize']['minor_languages'], 'tl');
51 - foreach ($langs as $lang){ 56 + foreach ($langs as $lang) {
52 $data['langs'][$lang] = Translate::getTls($lang); 57 $data['langs'][$lang] = Translate::getTls($lang);
53 } 58 }
54 59
@@ -56,8 +61,8 @@ class RankDataLogic extends BaseLogic @@ -56,8 +61,8 @@ class RankDataLogic extends BaseLogic
56 $data['project'] = [ 61 $data['project'] = [
57 'company' => $project['company'], 62 'company' => $project['company'],
58 'domain' => $project['deploy_optimize']['domain'], 63 'domain' => $project['deploy_optimize']['domain'],
59 - 'domain_info' => '',  
60 - 'cert_info' => '', 64 + 'domain_info' => ($domain_info['domain_info']['creation_date'] ?? '') . ' - ' . ($domain_info['domain_info']['expiration_date'] ?? ''),
  65 + 'cert_info' => ($domain_info['ssl']['start_time'] ?? '') . ' - ' . ($domain_info['ssl']['end_time'] ?? ''),
61 'plan' => str_replace('营销大师-', '全球搜-', $project['deploy_build']['plan'][0]), 66 'plan' => str_replace('营销大师-', '全球搜-', $project['deploy_build']['plan'][0]),
62 'keyword_num' => $project['deploy_build']['keyword_num'], 67 'keyword_num' => $project['deploy_build']['keyword_num'],
63 'compliance_day' => $rank['compliance_day'] ?? 0, 68 'compliance_day' => $rank['compliance_day'] ?? 0,
@@ -96,7 +101,7 @@ class RankDataLogic extends BaseLogic @@ -96,7 +101,7 @@ class RankDataLogic extends BaseLogic
96 'data' => array_values($indexed_pages['data'] ?? []), 101 'data' => array_values($indexed_pages['data'] ?? []),
97 ]; 102 ];
98 //收录数加上当日数据 103 //收录数加上当日数据
99 - if((Arr::last($data['indexed_pages_chat']['labels'])) != date('Y-m-d')){ 104 + if ((Arr::last($data['indexed_pages_chat']['labels'])) != date('Y-m-d')) {
100 $data['indexed_pages_chat']['labels'][] = date('Y-m-d'); 105 $data['indexed_pages_chat']['labels'][] = date('Y-m-d');
101 $data['indexed_pages_chat']['data'][] = $data['indexed_pages_num']; 106 $data['indexed_pages_chat']['data'][] = $data['indexed_pages_num'];
102 } 107 }
@@ -114,7 +119,209 @@ class RankDataLogic extends BaseLogic @@ -114,7 +119,209 @@ class RankDataLogic extends BaseLogic
114 * @author zbj 119 * @author zbj
115 * @date 2023/5/12 120 * @date 2023/5/12
116 */ 121 */
117 - public function keywords_rank_list(){  
118 - $lang = $this->request['lang']; 122 + public function keywords_rank_list($export = false)
  123 + {
  124 + $page = intval($this->request['page'] ?: 1);
  125 + $lang = $this->request['lang'] ?: '';
  126 + $project_id = $this->user['project_id'];
  127 + $project = app(ProjectLogic::class)->getInfo($project_id);
  128 + $api_no = $project['deploy_optimize']['api_no'] ?? '';
  129 + $domain = $project['deploy_optimize']['domain'] ?? '';
  130 + $domain_arr = parse_url($domain);
  131 + $domain = $domain_arr['host'] ?? $domain_arr['path'];
  132 +
  133 + //复制站点域名
  134 + $ext_projects = $this->getExtendProjects();
  135 + $flg_ext = $this->getExtFlag($ext_projects, $domain, $api_no);
  136 + $ext_domain = str_replace('www.', '', $this->getExtendProjects($api_no)['ext'] ?? '');
  137 + //AI站点域名
  138 + $ai_projects = $this->getAiProjects()['data'] ?? [];
  139 + $flg_ai = $this->getAiFlag($ai_projects, $domain);
  140 + $ai_domain = str_replace('www.', '', $this->getAiProjects($domain)['domain'] ?? '');
  141 +
  142 +
  143 + $list = RankData::where('project_id', $project_id)->where('lang', $lang)->value('data');
  144 + $list30 = []; //排名前三十的
  145 + $list30_0 = []; //排名前三十且近三天没有排名的
  146 + $list100 = []; //排名前100的
  147 + $list0 = [];//排名为0的
  148 + foreach ($list as $key => $v) {
  149 + $last = Arr::last($v);
  150 + $data = [];
  151 +
  152 + //处理日期
  153 + foreach ($v as $date => $position) {
  154 + $data[date('m-d', strtotime($date . '+ 1 day'))] = $position['position'];
  155 + }
  156 +
  157 + //域名类型
  158 + $domain_text = '主域名:' . str_replace('www.', '', $domain);
  159 + if (!empty($last['r'])) {
  160 + $domain_text = 'AI域名:' . $last['r'];
  161 + if (in_array($flg_ext, [1, 2]) || $flg_ai == 1) {
  162 + if ($last['r'] == $ai_domain) {
  163 + $domain_text = '星链域名:' . $ai_domain;
  164 + } else if ($last['r'] == $ext_domain) {
  165 + $domain_text = '主域名2:' . $ext_domain;
  166 + } else {
  167 + $domain_text = 'AI域名:' . $last['r'];
  168 + }
  169 + }
  170 + }
  171 + $v = [
  172 + 'keyword' => $key,
  173 + 'domain' => $domain_text,
  174 + 'g' => $last['g'], //1核心关键词
  175 + 'position' => $data
  176 + ];
  177 + if ($last['position'] == 0) {
  178 + $list0[] = $v;
  179 + } elseif ($last['position'] <= 30) {
  180 + if (($v['position'][date('m-d', strtotime('-1day'))] ?? '') == 0 ||
  181 + ($v['position'][date('m-d', strtotime('-2day'))] ?? '') == 0) {
  182 + $list30_0[] = $v;
  183 + } else {
  184 + $list30[] = $v;
  185 + }
  186 + } else {
  187 + $list100[] = $v;
  188 + }
  189 + }
  190 + //排序 排名前30的 按关键词长短排序 最近三天无排名的排后; 后30名的按排名排序
  191 + $list30 = collect($list30)->sortBy(function ($item) {
  192 + return strlen($item['keyword']);
  193 + })->values()->all();
  194 + $list30_0 = collect($list30_0)->sortBy(function ($item) {
  195 + return strlen($item['keyword']);
  196 + })->values()->all();
  197 + $list100 = collect($list100)->sortBy(function ($item) {
  198 + return Arr::last($item['position']);
  199 + })->values()->all();
  200 + $list = collect($list30)->merge($list30_0)->merge($list100)->merge($list0)->filter(function ($item) {
  201 + //搜索
  202 + if ($this->request['search']) {
  203 + return strpos($item['keyword'], $this->request['search']) !== false;
  204 + }
  205 + //前几名
  206 + if ($this->request['first']) {
  207 + $position = Arr::last($item['position']);
  208 + return $position > 0 && $position <= $this->request['first'];
  209 + }
  210 + //核心词
  211 + if ($this->request['g']) {
  212 + return $item['g'] == $this->request['g'];
  213 + }
  214 + return true;
  215 + })->values();
  216 +
  217 + if($export){
  218 + return $list->toArray();
  219 + }
  220 + $data = [
  221 + "list" => $list->forPage($page, 100)->toArray(),
  222 + "total" => $list->count(),
  223 + "page" => $page,
  224 + "total_page" => ceil($list->count() / 100),
  225 + "size" => 100
  226 + ];
  227 + return $this->success($data);
  228 + }
  229 +
  230 +
  231 + /**
  232 + * 获取复制站点项目
  233 + * @author zbj
  234 + * @date 2023/5/12
  235 + */
  236 + public function getExtendProjects($api_no = null)
  237 + {
  238 + $key = 'extend_projects_list';
  239 + $data = Cache::get($key);
  240 + if (!$data) {
  241 + $api_url = 'http://api.quanqiusou.cn/google-rank/api/extend_projects.php';
  242 + try {
  243 + $data = HttpUtils::get($api_url, []);
  244 + if ($data) {
  245 + $data = Arr::s2a($data);
  246 + Cache::put($key, $data, 4 * 3600);
  247 + }
  248 + } catch (\Exception | GuzzleException $e) {
  249 + errorLog('复制站点项目获取失败', [], $e);
  250 + return false;
  251 + }
  252 + }
  253 + if ($api_no !== null) {
  254 + $data = collect($data)->where('apino', $api_no)->first();
  255 + return $data ?: [];
  256 + }
  257 + return $data;
  258 + }
  259 +
  260 + /**
  261 + * 获取AI站点项目
  262 + * @author zbj
  263 + * @date 2023/5/12
  264 + */
  265 + public function getAiProjects($domain = null)
  266 + {
  267 + $key = 'ai_projects_list';
  268 + $data = Cache::get($key);
  269 + if (!$data) {
  270 + $api_url = 'https://demosite5.globalso.com/api/domain';
  271 + try {
  272 + $data = HttpUtils::get($api_url, []);
  273 + if ($data) {
  274 + $data = Arr::s2a($data);
  275 + Cache::put($key, $data, 4 * 3600);
  276 + }
  277 + } catch (\Exception | GuzzleException $e) {
  278 + errorLog('AI站点项目获取失败', [], $e);
  279 + return false;
  280 + }
  281 + }
  282 + if ($domain !== null) {
  283 + $domain = parse_url($domain);
  284 + $data = collect($data['data'])->where('bind_domain', $domain['host'] ?? $domain['path'])->first();
  285 + return $data ?: [];
  286 + }
  287 + return $data;
  288 + }
  289 +
  290 + /**
  291 + * 获取复制项目标识
  292 + * @author zbj
  293 + * @date 2023/5/15
  294 + */
  295 + protected function getExtFlag($ext_projects, $domain, $api_no)
  296 + {
  297 + //复制站点标识
  298 + $flg_ext = 0;
  299 + if ($ext_projects) {
  300 + $ext_urls = array_column($ext_projects, 'ext');
  301 + $api_nos = array_column($ext_projects, 'apino');
  302 + if (in_array($api_no, $api_nos)) {
  303 + $flg_ext = 1;
  304 + }
  305 + if (in_array($domain, $ext_urls)) {
  306 + $flg_ext = 2;
  307 + }
  308 + }
  309 + return $flg_ext;
  310 + }
  311 +
  312 + /**
  313 + * 获取AI项目标识
  314 + * @author zbj
  315 + * @date 2023/5/15
  316 + */
  317 + protected function getAiFlag($ai_projects, $domain)
  318 + {
  319 + $flg_ai = 0;
  320 + foreach ($ai_projects as $ai_project) {
  321 + if ($ai_project['bind_domain'] == $domain) {
  322 + $flg_ai = 1;
  323 + }
  324 + }
  325 + return $flg_ai;
119 } 326 }
120 } 327 }
@@ -24,11 +24,11 @@ class AyrReleaseRequest extends FormRequest @@ -24,11 +24,11 @@ class AyrReleaseRequest extends FormRequest
24 { 24 {
25 return [ 25 return [
26 'title'=>'required', 26 'title'=>'required',
27 - 'images'=>'required', 27 + 'images'=>'required|array',
28 'video'=>'required', 28 'video'=>'required',
29 'content'=>'required', 29 'content'=>'required',
30 'share_id'=>'required', 30 'share_id'=>'required',
31 - 'platforms'=>'required', 31 + 'platforms'=>'required|array',
32 'idempotency_key'=>'required', 32 'idempotency_key'=>'required',
33 ]; 33 ];
34 } 34 }
@@ -23,7 +23,7 @@ class AyrShareRequest extends FormRequest @@ -23,7 +23,7 @@ class AyrShareRequest extends FormRequest
23 public function rules() 23 public function rules()
24 { 24 {
25 return [ 25 return [
26 - 'name'=>'required||unique:gl_ayr_share,name', 26 + 'name'=>'required|unique:gl_ayr_share,name',
27 ]; 27 ];
28 } 28 }
29 29
@@ -31,6 +31,7 @@ class AyrShareRequest extends FormRequest @@ -31,6 +31,7 @@ class AyrShareRequest extends FormRequest
31 { 31 {
32 return [ 32 return [
33 'name.required'=>'请填写名称', 33 'name.required'=>'请填写名称',
  34 +
34 ]; 35 ];
35 } 36 }
36 } 37 }
  1 +<?php
  2 +
  3 +namespace App\Models\Project;
  4 +
  5 +use App\Helper\Arr;
  6 +use App\Models\Base;
  7 +use App\Models\Devops\ServerConfig;
  8 +use Illuminate\Support\Facades\Cache;
  9 +
  10 +class DomainInfo extends Base
  11 +{
  12 + //设置关联表名
  13 + protected $table = 'gl_project_domain_info';
  14 +
  15 +
  16 + public function setDomainInfoAttribute($value){
  17 + $this->attributes['domain_info'] = Arr::a2s($value);
  18 + }
  19 +
  20 + public function getDomainInfoAttribute($value){
  21 + return Arr::s2a($value);
  22 + }
  23 +
  24 + public function setSslAttribute($value){
  25 + $this->attributes['ssl'] = Arr::a2s($value);
  26 + }
  27 +
  28 + public function getSslAttribute($value){
  29 + return Arr::s2a($value);
  30 + }
  31 +}
@@ -14,6 +14,7 @@ @@ -14,6 +14,7 @@
14 "laravel/framework": "^8.75", 14 "laravel/framework": "^8.75",
15 "laravel/sanctum": "^2.11", 15 "laravel/sanctum": "^2.11",
16 "laravel/tinker": "^2.5", 16 "laravel/tinker": "^2.5",
  17 + "mongodb/mongodb": "^1.6",
17 "phpoffice/phpspreadsheet": "^1.28" 18 "phpoffice/phpspreadsheet": "^1.28"
18 }, 19 },
19 "require-dev": { 20 "require-dev": {
@@ -256,6 +256,9 @@ Route::middleware(['bloginauth'])->group(function () { @@ -256,6 +256,9 @@ Route::middleware(['bloginauth'])->group(function () {
256 Route::prefix('rank_data')->group(function () { 256 Route::prefix('rank_data')->group(function () {
257 Route::any('/index', [\App\Http\Controllers\Bside\RankDataController::class, 'index'])->name('rank_data'); 257 Route::any('/index', [\App\Http\Controllers\Bside\RankDataController::class, 'index'])->name('rank_data');
258 Route::any('/keywords_rank_list', [\App\Http\Controllers\Bside\RankDataController::class, 'keywords_rank_list'])->name('rank_data_keywords_rank_list'); 258 Route::any('/keywords_rank_list', [\App\Http\Controllers\Bside\RankDataController::class, 'keywords_rank_list'])->name('rank_data_keywords_rank_list');
  259 + Route::any('/speed', [\App\Http\Controllers\Bside\RankDataController::class, 'speed'])->name('rank_data_speed');
  260 + Route::any('/export', [\App\Http\Controllers\Bside\RankDataController::class, 'export'])->name('rank_data_export');
  261 + Route::any('/export_history', [\App\Http\Controllers\Bside\RankDataController::class, 'export_history'])->name('rank_data_export_history');
259 }); 262 });
260 263
261 264