作者 lyh

Merge branch 'dev'

正在显示 38 个修改的文件 包含 4344 行增加245 行删除

要显示太多修改。

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

1 -APP_NAME=Laravel  
2 -APP_ENV=test  
3 -APP_KEY=base64:+ouoKlz2sFDOisnROMRpxT/u9xkZJVrXlzP4cfTqPow=  
4 -APP_DEBUG=false  
5 -APP_URL=http://localhost  
6 -  
7 -LOG_CHANNEL=stack  
8 -LOG_DEPRECATIONS_CHANNEL=null  
9 -LOG_LEVEL=debug  
10 -  
11 -DB_CONNECTION=mysql  
12 -DB_HOST=127.0.0.1  
13 -DB_PORT=3306  
14 -DB_DATABASE=globalso  
15 -DB_USERNAME=debian-sys-maint  
16 -DB_PASSWORD=WtujxV73XIclQet0  
17 -  
18 -BROADCAST_DRIVER=log  
19 -CACHE_DRIVER=file  
20 -FILESYSTEM_DRIVER=local  
21 -QUEUE_CONNECTION=sync  
22 -SESSION_DRIVER=file  
23 -SESSION_LIFETIME=120  
24 -  
25 -MEMCACHED_HOST=127.0.0.1  
26 -  
27 -REDIS_HOST=127.0.0.1  
28 -REDIS_PASSWORD=null  
29 -REDIS_PORT=6379  
30 -  
31 -MAIL_MAILER=smtp  
32 -MAIL_HOST=mailhog  
33 -MAIL_PORT=1025  
34 -MAIL_USERNAME=null  
35 -MAIL_PASSWORD=null  
36 -MAIL_ENCRYPTION=null  
37 -MAIL_FROM_ADDRESS=null  
38 -MAIL_FROM_NAME="${APP_NAME}"  
39 -  
40 -AWS_ACCESS_KEY_ID=  
41 -AWS_SECRET_ACCESS_KEY=  
42 -AWS_DEFAULT_REGION=us-east-1  
43 -AWS_BUCKET=  
44 -AWS_USE_PATH_STYLE_ENDPOINT=false  
45 -  
46 -PUSHER_APP_ID=  
47 -PUSHER_APP_KEY=  
48 -PUSHER_APP_SECRET=  
49 -PUSHER_APP_CLUSTER=mt1  
50 -  
51 -MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"  
52 -MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"  
@@ -3,6 +3,8 @@ @@ -3,6 +3,8 @@
3 /public/storage 3 /public/storage
4 /storage 4 /storage
5 /vendor 5 /vendor
  6 +/uploads
  7 +composer.json
6 .env 8 .env
7 .env.backup 9 .env.backup
8 .phpunit.result.cache 10 .phpunit.result.cache
@@ -14,4 +16,6 @@ yarn-error.log @@ -14,4 +16,6 @@ yarn-error.log
14 /.idea 16 /.idea
15 /.vscode 17 /.vscode
16 composer.lock 18 composer.lock
17 -app/Console/Commands/Test/Demo.php  
  19 +app/Console/Commands/Test/Demo.php
  20 +/public/upload
  21 +/public/runtime
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\AyrShare;
  4 +
  5 +use App\Helper\AyrShare as AyrShareHelper;
  6 +use App\Models\AyrShare\AyrShare as AyrShareModel;
  7 +use Illuminate\Console\Command;
  8 +
  9 +class ShareConfig extends Command
  10 +{
  11 + public $error = 0;
  12 + /**
  13 + * The name and signature of the console command.
  14 + *
  15 + * @var string
  16 + */
  17 + protected $signature = 'share_config';
  18 +
  19 + /**
  20 + * The console command description.
  21 + *
  22 + * @var string
  23 + */
  24 + protected $description = '更新用户Ayr_share配置';
  25 + /**
  26 + * @name :(定时执行更新用户配置)handle
  27 + * @author :lyh
  28 + * @method :post
  29 + * @time :2023/5/12 14:48
  30 + */
  31 + public function handle()
  32 + {
  33 + $ayrShareModel = new AyrShareModel();
  34 + //更新用户配置
  35 + $lists = $ayrShareModel->lists($this->map,$this->page,$this->row,'id',['id','profile_key','bind_plat_from']);
  36 + foreach ($lists['list'] as $k => $v){
  37 + if(empty($v['profile_key'])){
  38 + continue;
  39 + }
  40 + //获取当前用户配置
  41 + $ayrShareHelper = new AyrShareHelper();
  42 + $share_info = $ayrShareHelper->get_profiles_users($v['profile_key']);
  43 + if(!isset($share_info['activeSocialAccounts'])){
  44 + $ayrShareModel->edit(['bind_plat_from'=>''],['id'=>$v['id']]);
  45 + continue;
  46 + }
  47 + $str = json_encode($share_info['activeSocialAccounts']);
  48 + if($str != $v['bind_plat_from']){
  49 + $rs = $ayrShareModel->edit(['bind_plat_from'=>$str],['id'=>$v['id']]);
  50 + if($rs === false){
  51 + $this->error++;
  52 + }
  53 + }
  54 + }
  55 + echo $this->error;
  56 + }
  57 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\AyrShare;
  4 +use App\Helper\AyrShare as AyrShareHelper;
  5 +use App\Models\AyrShare\AyrRelease as AyrReleaseModel;
  6 +use Carbon\Carbon;
  7 +use App\Models\AyrShare\AyrShare as AyrShareModel;
  8 +use Illuminate\Console\Command;
  9 +
  10 +class ShareUser extends Command
  11 +{
  12 + public $error = 0;
  13 + /**
  14 + * The name and signature of the console command.
  15 + *
  16 + * @var string
  17 + */
  18 + protected $signature = 'share_user';
  19 +
  20 + /**
  21 + * The console command description.
  22 + *
  23 + * @var string
  24 + */
  25 + protected $description = '用户一周内无记录清除Ayr_share';
  26 + /**
  27 + * @name :(定时执行)handle
  28 + * @author :lyh
  29 + * @method :post
  30 + * @time :2023/5/12 14:48
  31 + */
  32 + public function handle()
  33 + {
  34 + echo $this->user_operator_record();
  35 + }
  36 +
  37 + /**
  38 + * @name : 检测用户是否无操作记录
  39 + * @author :lyh
  40 + * @method :post
  41 + * @time :2023/5/12 14:55
  42 + */
  43 + protected function user_operator_record(){
  44 + //获取所有ayr_share用户
  45 + $ayr_share_model = new AyrShareModel();
  46 + $ayr_release = new AyrReleaseModel();
  47 + $ayr_share_list = $ayr_share_model->list(['profile_key'=>['!=','']]);
  48 + foreach ($ayr_share_list as $v){
  49 + $time = Carbon::now()->modify('-7 days')->toDateString();
  50 + //创建时间小于7天前的当前时间
  51 + if($v['created_at'] > $time){
  52 + continue;
  53 + }
  54 + //查询当前用户是否有未推送的博文
  55 + $release_info = $this->release_info($ayr_release,$v);
  56 + //有推文时,直接跳出循环
  57 + if($release_info !== false){
  58 + continue;
  59 + }
  60 + //查询7天是否发送博文
  61 + $release_info = $this->release_seven_info($ayr_release);
  62 + //有发送博文,则跳出循环
  63 + if($release_info !== false){
  64 + continue;
  65 + }
  66 + //删除用户第三方配置
  67 + if(!empty($v['profile_key'])){
  68 + $this->del_profiles($v);
  69 + continue;
  70 + }
  71 + //更新数据库
  72 + $this->save_ayr_share($ayr_share_model,$v);
  73 + }
  74 + return $this->error;
  75 + }
  76 +
  77 + /**
  78 + * @name :(删除第三方配置)del_profiles
  79 + * @author :lyh
  80 + * @method :post
  81 + * @time :2023/6/14 16:10
  82 + */
  83 + public function del_profiles($v){
  84 + $ayr_share_helper = new AyrShareHelper();
  85 + $data_profiles = [
  86 + 'title'=>$v['title'],
  87 + 'profileKey'=>$v['profile_key']
  88 + ];
  89 + $res = $ayr_share_helper->deleted_profiles($data_profiles);
  90 + if($res['status'] == 'fail'){
  91 + echo '第三方删除失败';
  92 + return true;
  93 + }
  94 + return true;
  95 + }
  96 +
  97 + /**
  98 + * @name :(更新数据库)save_ayr_share
  99 + * @author :lyh
  100 + * @method :post
  101 + * @time :2023/6/14 16:14
  102 + */
  103 + public function save_ayr_share(&$ayr_share_model,$v){
  104 +
  105 + //更新数据库
  106 + $data = [
  107 + 'title'=>'',
  108 + 'bind_platforms'=>'',
  109 + 'profile_key'=>'',
  110 + 'ref_id'=>'',
  111 + ];
  112 + $res = $ayr_share_model->edit($data,['id'=>$v['id']]);
  113 + if($res == false){
  114 + echo '更新数据库失败';
  115 + return true;
  116 + }
  117 + return true;
  118 + }
  119 +
  120 + /**
  121 + * @name :(查询是否有定时发送报文)info
  122 + * @author :lyh
  123 + * @method :post
  124 + * @time :2023/6/14 16:17
  125 + */
  126 + public function release_info(&$ayr_release,$v){
  127 + //查询当前用户是否有未推送的博文
  128 + $release_info = $ayr_release->read(['schedule_date'=>['>',date('Y-m-d H:i:s',time())],'share_id'=>$v['id']]);
  129 + return $release_info;
  130 + }
  131 +
  132 + /**
  133 + * @param $ayr_release
  134 + * @name :(7天内无发送记录)release_seven_info
  135 + * @author :lyh
  136 + * @method :post
  137 + * @time :2023/6/14 16:28
  138 + */
  139 + public function release_seven_info(&$ayr_release){
  140 + //查看用户是否在一周内有发送博客
  141 + $start_at = Carbon::now()->modify('-7 days')->toDateString();
  142 + $end_at = Carbon::now()->toDateString();
  143 + $release_info = $ayr_release->read(['created_at'=>['between',[$start_at,$end_at]]]);
  144 + return $release_info;
  145 + }
  146 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\Bside\Statistics;
  4 +
  5 +use App\Models\Bside\Statistics\TrafficStatistics;
  6 +use App\Models\CustomerVisit\CustomerVisit;
  7 +use Illuminate\Console\Command;
  8 +use Illuminate\Support\Facades\DB;
  9 +use Throwable;
  10 +
  11 +class Logic
  12 +{
  13 +
  14 + /**
  15 + * @param int $type 统计类型
  16 + * @return array
  17 + */
  18 + public function getMonths(int $type = TrafficStatistics::TYPE_SOURCE)
  19 + {
  20 + $date = getPreviousMonthsDate();
  21 + $TrafficStatistics = new TrafficStatistics();
  22 + $lists = $TrafficStatistics->getMonthsLists($type, $date);
  23 + if (!empty($lists)) {
  24 + $dd = [];
  25 + $lists->map(function ($item) use (&$dd) {
  26 + $dd[] = $item->year . '-' . str_pad($item->month, 2, '0', STR_PAD_LEFT);
  27 + });
  28 + $date = array_diff($date, $dd);
  29 + }
  30 + return $date;
  31 + }
  32 +
  33 + /**
  34 + * @param array $column 统计数据
  35 + * @param int $type 统计类型
  36 + * @param string|null $date 日期 格式:Y-m
  37 + * @param string $message
  38 + * @return array
  39 + * @throws Throwable
  40 + */
  41 + public function save(array $column, int $type = TrafficStatistics::TYPE_SOURCE, string $date = null, $message = '统计当月访问来源数据')
  42 + {
  43 + DB::beginTransaction();
  44 + // 获取当天的IP|PV数量
  45 + $customerVisit = new CustomerVisit();
  46 + $ip_count = $customerVisit->getMonthIPCount($date);
  47 + $pv_count = $customerVisit->getMonthPVCount($date);
  48 + $column['pvnum'] = $pv_count;
  49 + $column['ipnum'] = $ip_count;
  50 + $date = $date ?? date('Y-m');
  51 + // 统计数据并插入到数据库
  52 + $dd = explode('-', $date);
  53 + $year = $dd[0];
  54 + $month = $dd[1];
  55 + $column['year'] = $year;
  56 + $column['month'] = $month;
  57 + $trafficStatistics = new TrafficStatistics();
  58 + $isRes = $trafficStatistics->getMonth($type, $year, $month);
  59 + if ($isRes) {
  60 + $trafficStatistics = $isRes;
  61 + }
  62 + foreach ($column as $key => $value) {
  63 + $trafficStatistics->$key = $value;
  64 + }
  65 + $res = $trafficStatistics->save();
  66 + if ($res) {
  67 + DB::commit();
  68 + $meg = "{$date} - {$message}成功!";
  69 + } else {
  70 + DB::rollBack();
  71 + $meg = "{$date} - {$message}失败!";
  72 + }
  73 + return ['status' => $res, 'msg' => $meg];
  74 + }
  75 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\Bside\Statistics;
  4 +
  5 +use App\Models\Bside\Statistics\TrafficTrends;
  6 +use App\Models\CustomerVisit\CustomerVisit;
  7 +use GuzzleHttp\Exception\GuzzleException;
  8 +use Illuminate\Console\Command;
  9 +use Illuminate\Support\Facades\DB;
  10 +use Throwable;
  11 +
  12 +class StatisticsDayTrend extends Command
  13 +{
  14 + public $error = 0;
  15 + /**
  16 + * The name and signature of the console command.
  17 + *
  18 + * @var string
  19 + */
  20 + protected $signature = 'statistics_day_trend';
  21 +
  22 + /**
  23 + * The console command description.
  24 + *
  25 + * @var string
  26 + */
  27 + protected $description = '统计当天流量趋势数据';
  28 +
  29 + /**
  30 + * @return void
  31 + * @throws GuzzleException
  32 + * @throws Throwable
  33 + */
  34 + public function handle()
  35 + {
  36 + $date = getPreviousDaysDate();
  37 + $trafficTrends = new TrafficTrends();
  38 + $lists = $trafficTrends->getDaysLists($date);
  39 + if (!empty($lists)) {
  40 + $date = array_diff($date, $lists->pluck('day')->all());
  41 + }
  42 + if (!empty($date)) {
  43 + foreach ($date as $value) {
  44 + echo $this->statistics_day_trend($value);
  45 + }
  46 + }
  47 + echo $this->statistics_day_trend();
  48 + }
  49 +
  50 + /**
  51 + * 统计当天流量趋势数据PV|IP数量
  52 + * @return int|mixed
  53 + * @throws GuzzleException|Throwable
  54 + */
  55 + protected function statistics_day_trend($date = null)
  56 + {
  57 + DB::beginTransaction();
  58 + $date = $date ?? date('Y-m-d');
  59 + // 获取当天的IP|PV数量
  60 + $customerVisit = new CustomerVisit();
  61 + $ip_count = $customerVisit->getDayIPCount($date);
  62 + $pv_count = $customerVisit->getDayPVCount($date);
  63 + // 统计数据并插入到数据库
  64 + $trafficTrends = new TrafficTrends();
  65 + $isRes = $trafficTrends->getDay($date);
  66 + if ($isRes) {
  67 + $trafficTrends = $isRes;
  68 + }
  69 + $trafficTrends->day = $date;
  70 + $trafficTrends->pvnum = $pv_count;
  71 + $trafficTrends->ipnum = $ip_count;
  72 + $res = $trafficTrends->save();
  73 + if ($res) {
  74 + DB::commit();
  75 + $this->info($date . ' - 统计当天流量趋势数据PV|IP数量成功');
  76 + } else {
  77 + DB::rollBack();
  78 + $this->error++;
  79 + $this->info($date . ' - 统计当天流量趋势数据PV|IP数量失败');
  80 + }
  81 + return $this->error;
  82 + }
  83 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\Bside\Statistics;
  4 +
  5 +use App\Models\Bside\Statistics\TrafficStatistics;
  6 +use App\Models\CustomerVisit\CustomerVisit;
  7 +use Illuminate\Console\Command;
  8 +use Throwable;
  9 +
  10 +class StatisticsDistribution extends Command
  11 +{
  12 + public $error = 0;
  13 + /**
  14 + * The name and signature of the console command.
  15 + *
  16 + * @var string
  17 + */
  18 + protected $signature = 'statistics_distribution';
  19 +
  20 + /**
  21 + * The console command description.
  22 + *
  23 + * @var string
  24 + */
  25 + protected $description = '统计当月地域分布数据';
  26 +
  27 + public $logic;
  28 +
  29 + public function __construct()
  30 + {
  31 + parent::__construct();
  32 + $this->logic = new Logic();
  33 + }
  34 +
  35 + /**
  36 + * 定时执行
  37 + * @return void
  38 + * @throws Throwable
  39 + */
  40 + public function handle()
  41 + {
  42 + $date = $this->logic->getMonths(TrafficStatistics::TYPE_DISTRIBUTION);
  43 + if (!empty($date)) {
  44 + foreach ($date as $value) {
  45 + echo $this->statistics_distribution($value);
  46 + }
  47 + }
  48 + echo $this->statistics_distribution();
  49 + }
  50 +
  51 + /**
  52 + * 统计当天流量趋势数据PV|IP数量
  53 + * @param string|null $date
  54 + * @return int|mixed
  55 + * @throws Throwable
  56 + */
  57 + protected function statistics_distribution(string $date = null)
  58 + {
  59 + $customerVisit = new CustomerVisit();
  60 + $type = TrafficStatistics::TYPE_DISTRIBUTION;
  61 + $top = json_encode($customerVisit->getCountryCount($date) ?? []);
  62 + $res = $this->logic->save(compact('top', 'type'), $type, $date, '统计当月地域分布数据');
  63 + if (!$res['status']) {
  64 + $this->info($res['msg']);
  65 + $this->error++;
  66 + }
  67 + $this->info($res['msg']);
  68 + return $this->error;
  69 + }
  70 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\Bside\Statistics;
  4 +
  5 +use App\Models\Bside\Statistics\TrafficStatistics;
  6 +use App\Models\CustomerVisit\CustomerVisit;
  7 +use Illuminate\Console\Command;
  8 +use Throwable;
  9 +
  10 +class StatisticsPage extends Command
  11 +{
  12 + public $error = 0;
  13 +
  14 + /**
  15 + * The name and signature of the console command.
  16 + *
  17 + * @var string
  18 + */
  19 + protected $signature = 'statistics_page';
  20 +
  21 + /**
  22 + * The console command description.
  23 + *
  24 + * @var string
  25 + */
  26 + protected $description = '统计当月受访页面数据';
  27 +
  28 + public $logic;
  29 +
  30 + public function __construct()
  31 + {
  32 + parent::__construct();
  33 + $this->logic = new Logic();
  34 + }
  35 +
  36 + /**
  37 + * 定时执行
  38 + * @return void
  39 + */
  40 + public function handle()
  41 + {
  42 + $date = $this->logic->getMonths(TrafficStatistics::TYPE_PAGE);
  43 + if (!empty($date)) {
  44 + foreach ($date as $value) {
  45 + echo $this->statistics_page($value);
  46 + }
  47 + }
  48 + echo $this->statistics_page();
  49 + }
  50 +
  51 + /**
  52 + * 统计当月受访页面数据
  53 + * @param null $date
  54 + * @return int|mixed
  55 + * @throws Throwable
  56 + */
  57 + protected function statistics_page($date = null)
  58 + {
  59 + $customerVisit = new CustomerVisit();
  60 + $top = json_encode($customerVisit->getPageCount($date) ?? []);
  61 + $type = TrafficStatistics::TYPE_PAGE;
  62 + $res = $this->logic->save(compact('top', 'type'), $type, $date, '统计当月受访页面数据');
  63 + if (!$res['status']) {
  64 + $this->info($res['msg']);
  65 + $this->error++;
  66 + }
  67 + $this->info($res['msg']);
  68 + return $this->error;
  69 + }
  70 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\Bside\Statistics;
  4 +
  5 +use App\Models\Bside\Statistics\TrafficStatistics;
  6 +use App\Models\CustomerVisit\CustomerVisit;
  7 +use Illuminate\Console\Command;
  8 +use Throwable;
  9 +
  10 +class StatisticsSource extends Command
  11 +{
  12 + public $error = 0;
  13 + /**
  14 + * The name and signature of the console command.
  15 + *
  16 + * @var string
  17 + */
  18 + protected $signature = 'statistics_source';
  19 +
  20 + /**
  21 + * The console command description.
  22 + *
  23 + * @var string
  24 + */
  25 + protected $description = '统计当月访问来源数据';
  26 +
  27 + public $logic;
  28 +
  29 + public function __construct()
  30 + {
  31 + parent::__construct();
  32 + $this->logic = new Logic();
  33 + }
  34 +
  35 + /**
  36 + * @return void
  37 + * @throws Throwable
  38 + */
  39 + public function handle()
  40 + {
  41 + $date = $this->logic->getMonths();
  42 + if (!empty($date)) {
  43 + foreach ($date as $value) {
  44 + echo $this->statistics_source($value);
  45 + }
  46 + }
  47 + echo $this->statistics_source();
  48 + }
  49 +
  50 + /**
  51 + * 统计当天流量趋势数据
  52 + * @param string|null $date
  53 + * @return int|mixed
  54 + * @throws Throwable
  55 + */
  56 + protected function statistics_source(string $date = null)
  57 + {
  58 + // 获取当天的IP|PV数量
  59 + $customerVisit = new CustomerVisit();
  60 + $top = json_encode($customerVisit->getUrlCount($date) ?? []);
  61 + $type = TrafficStatistics::TYPE_SOURCE;
  62 + $res = $this->logic->save(compact('top', 'type'), $type, $date);
  63 + if (!$res['status']) {
  64 + $this->info($res['msg']);
  65 + $this->error++;
  66 + }
  67 + $this->info($res['msg']);
  68 + return $this->error;
  69 + }
  70 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\Bside\Statistics;
  4 +
  5 +use App\Models\Bside\Statistics\TrafficStatistics;
  6 +use App\Models\CustomerVisit\CustomerVisit;
  7 +use GuzzleHttp\Exception\GuzzleException;
  8 +use Illuminate\Console\Command;
  9 +use Throwable;
  10 +
  11 +class StatisticsTerminal extends Command
  12 +{
  13 + public $error = 0;
  14 +
  15 + /**
  16 + * The name and signature of the console command.
  17 + *
  18 + * @var string
  19 + */
  20 + protected $signature = 'statistics_terminal';
  21 +
  22 + /**
  23 + * The console command description.
  24 + *
  25 + * @var string
  26 + */
  27 + protected $description = '统计当月访问终端数据';
  28 +
  29 + public $logic;
  30 +
  31 + public function __construct()
  32 + {
  33 + parent::__construct();
  34 + $this->logic = new Logic();
  35 + }
  36 +
  37 + /**
  38 + * @return void
  39 + * @throws Throwable
  40 + */
  41 + public function handle()
  42 + {
  43 + $date = $this->logic->getMonths(TrafficStatistics::TYPE_TERMINAL);
  44 + if (!empty($date)) {
  45 + foreach ($date as $value) {
  46 + echo $this->statistics_terminal($value);
  47 + }
  48 + }
  49 + echo $this->statistics_terminal();
  50 + }
  51 +
  52 + /**
  53 + * 统计当月访问终端数据
  54 + * @param string|null $date
  55 + * @return int|mixed
  56 + * @throws Throwable
  57 + */
  58 + protected function statistics_terminal(string $date = null)
  59 + {
  60 + $customerVisit = new CustomerVisit();
  61 + $pcnum = $customerVisit->getTerminalPcCount($date);
  62 + $mbnum = $customerVisit->getTerminalMobileCount($date);
  63 + $top = json_encode($customerVisit->getCountryCount($date) ?? []);
  64 + $type = TrafficStatistics::TYPE_TERMINAL;
  65 + $res = $this->logic->save(compact('top', 'type', 'pcnum', 'mbnum'), $type, $date, '统计当月访问终端数据');
  66 + if (!$res['status']) {
  67 + $this->info($res['msg']);
  68 + $this->error++;
  69 + }
  70 + $this->info($res['msg']);
  71 + return $this->error;
  72 + }
  73 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\Bside\Statistics;
  4 +
  5 +use App\Models\Bside\Statistics\TrafficStatistics;
  6 +use GuzzleHttp\Exception\GuzzleException;
  7 +use Illuminate\Console\Command;
  8 +use Throwable;
  9 +
  10 +class StatisticsTrend extends Command
  11 +{
  12 + public $error = 0;
  13 +
  14 + /**
  15 + * The name and signature of the console command.
  16 + *
  17 + * @var string
  18 + */
  19 + protected $signature = 'statistics_trend';
  20 +
  21 + /**
  22 + * The console command description.
  23 + *
  24 + * @var string
  25 + */
  26 + protected $description = '统计当月流量趋势数据';
  27 +
  28 + public $logic;
  29 +
  30 + public function __construct()
  31 + {
  32 + parent::__construct();
  33 + $this->logic = new Logic();
  34 + }
  35 +
  36 + /**
  37 + * 定时执行
  38 + * @return void
  39 + * @throws GuzzleException|Throwable
  40 + */
  41 + public function handle()
  42 + {
  43 + $date = $this->logic->getMonths(TrafficStatistics::TYPE_TREND);
  44 + if (!empty($date)) {
  45 + foreach ($date as $value) {
  46 + echo $this->statistics_trend($value);
  47 + }
  48 + }
  49 + echo $this->statistics_trend();
  50 + }
  51 +
  52 + /**
  53 + * 统计当天流量趋势数据
  54 + * @param string|null $date
  55 + * @return int|mixed
  56 + * @throws GuzzleException|Throwable
  57 + */
  58 + protected function statistics_trend(string $date = null)
  59 + {
  60 + $domain = request()->getHttpHost(); //'www.wowstainless.com';
  61 + $sta_date = !is_null($date) ? $date . "-01" : date('Y-m-01');
  62 + $inquiry = getInquiryInformation($domain, $sta_date);
  63 + $innum = $inquiry['count'] ?? 0;
  64 + $top = json_encode($inquiry['lists'] ?? []);
  65 + $type = TrafficStatistics::TYPE_TREND;
  66 + $res = $this->logic->save(compact('top', 'type', 'innum'), $type, $date, '统计当月流量趋势数据');
  67 + if (!$res['status']) {
  68 + $this->info($res['msg']);
  69 + $this->error++;
  70 + }
  71 + $this->info($res['msg']);
  72 + return $this->error;
  73 + }
  74 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands;
  4 +
  5 +
  6 +use App\Models\Devops\DevopsTaskLog;
  7 +use App\Models\Project\Project;
  8 +use Illuminate\Console\Command;
  9 +use App\Models\Devops\DevopsTask as DevopsTaskModel;
  10 +
  11 +/**
  12 + * Class DevopsTask
  13 + * @package App\Console\Commands
  14 + * @author zbj
  15 + * @date 2023/4/25
  16 + */
  17 +class DevopsTask extends Command
  18 +{
  19 + /**
  20 + * The name and signature of the console command.
  21 + *
  22 + * @var string
  23 + */
  24 + protected $signature = 'devops_task';
  25 +
  26 + /**
  27 + * The console command description.
  28 + *
  29 + * @var string
  30 + */
  31 + protected $description = '运维任务执行';
  32 +
  33 + /**
  34 + * Create a new command instance.
  35 + *
  36 + * @return void
  37 + */
  38 + public function __construct()
  39 + {
  40 + parent::__construct();
  41 + }
  42 +
  43 + /**
  44 + * @return bool
  45 + */
  46 + public function handle()
  47 + {
  48 + while (true){
  49 + $tasks = DevopsTaskModel::where('status', DevopsTaskModel::STATUS_PENDING)->get();
  50 + foreach ($tasks as $task){
  51 + echo "Start task " . $task->id . PHP_EOL;
  52 + if($task->type == DevopsTaskModel::TYPE_MYSQL){
  53 + $this->updateTable($task);
  54 + }
  55 + echo "End task " . $task->id . PHP_EOL;
  56 + }
  57 + sleep(10);
  58 + }
  59 + }
  60 +
  61 + public function updateTable($task){
  62 + $projects = Project::all();
  63 + foreach ($projects as $project){
  64 + echo "project " . $project->id;
  65 + $log = DevopsTaskLog::addLog($task->id, $project->id);
  66 + if($log->status == DevopsTaskModel::STATUS_ACTIVE){
  67 + continue;
  68 + }
  69 + if(!$project->mysqlConfig){
  70 + $log->status = DevopsTaskLog::STATUS_ERROR;
  71 + $log->remark = '未配置数据库';
  72 + $log->save();
  73 + continue;
  74 + }
  75 + //DB类是单例模式,生命周期内修改配置不会生效
  76 + $conn = new \mysqli(
  77 + $project->mysqlConfig->host,
  78 + $project->mysqlConfig->user,
  79 + $project->mysqlConfig->password,
  80 + $project->databaseName(),
  81 + $project->mysqlConfig->port,
  82 + );
  83 + $res = $conn->query($task->sql);
  84 +
  85 + $log->status = $res ? DevopsTaskLog::STATUS_ACTIVE : DevopsTaskLog::STATUS_ERROR;
  86 + $log->remark = $res ? '成功' : 'sql执行失败';
  87 + $log->save();
  88 + echo '-->' . $log->remark . PHP_EOL;
  89 + }
  90 + $task->status = DevopsTaskModel::STATUS_ACTIVE;
  91 + $task->save();
  92 + }
  93 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\Domain;
  4 +
  5 +use App\Exceptions\AsideGlobalException;
  6 +use App\Exceptions\BsideGlobalException;
  7 +use App\Http\Logic\Aside\Domain\DomainInfoLogic;
  8 +use GuzzleHttp\Exception\GuzzleException;
  9 +use Illuminate\Console\Command;
  10 +
  11 +class DomainTime extends Command
  12 +{
  13 + public $error = 0;
  14 + /**
  15 + * The name and signature of the console command.
  16 + *
  17 + * @var string
  18 + */
  19 + protected $signature = 'domain_time';
  20 +
  21 + /**
  22 + * The console command description.
  23 + *
  24 + * @var string
  25 + */
  26 + protected $description = '域名定时任务 更新域名|证书到期时间';
  27 +
  28 + /**
  29 + * @name :(定时执行)handle
  30 + * @author :lyh
  31 + * @method :post
  32 + * @time :2023/5/12 14:48
  33 + */
  34 + public function handle()
  35 + {
  36 + echo $this->update_domain_time();
  37 + }
  38 +
  39 + /**
  40 + * 更新域名|证书到期时间
  41 + * @return int|mixed|void
  42 + * @throws AsideGlobalException
  43 + * @throws BsideGlobalException|GuzzleException
  44 + */
  45 + protected function update_domain_time()
  46 + {
  47 + $domainCon = new DomainInfoLogic();
  48 + $all = $domainCon->getAllDomain();
  49 + $all = $all->toArray();
  50 + if ( empty( $all ) ) {
  51 + $this->info( '未获取到数据' );
  52 + return;
  53 + }
  54 + foreach ( $all as $item ) {
  55 + $domain = $item['domain'];
  56 + // 域名到期时间
  57 + $domainT = $domainCon->getDomainTime( $domain );
  58 + if ( $domainT ) {
  59 + $domain_time = $item['domain_end_time'];
  60 + $domainValidFrom = $domainT['validFrom'];
  61 + $domainValidTo = $domainT['validTo'];
  62 + if ( strtotime( $domain_time ) < strtotime( $domainValidTo ) ) {
  63 + $this->info( $domain . '域名到期时间更新成功' );
  64 + $domainCon->updateDomain( $item['id'], [ 'domain_end_time' => $domainValidTo ] );
  65 + }
  66 + } else {
  67 + $this->error++;
  68 + $this->info( $domain . '域名到期时间获取失败' );
  69 + }
  70 + // 证书到期时间
  71 + $certificateT = $domainCon->getDomainCertificateTime( $domain );
  72 + if ( $certificateT ) {
  73 + $certificate_time = $item['certificate_end_time'];
  74 + $certificateValidFrom = $certificateT['validFrom'];
  75 + $certificateValidTo = $certificateT['validTo'];
  76 + if ( strtotime( $certificate_time ) < strtotime( $certificateValidTo ) ) {
  77 + $this->info( $domain . '证书到期时间更新成功' );
  78 + $domainCon->updateDomain( $item['id'], [ 'certificate_end_time' => $certificateValidTo ] );
  79 + }
  80 + } else {
  81 + $this->error++;
  82 + $this->info( $domain . '证书到期时间获取失败' );
  83 + }
  84 + }
  85 + return $this->error;
  86 + }
  87 +}
1 -<?php  
2 -/**  
3 - * Created by PhpStorm.  
4 - * User: zhl  
5 - * Date: 2023/4/12  
6 - * Time: 15:33  
7 - */  
8 -namespace App\Console\Commands;  
9 -  
10 -use App\Models\Project;  
11 -use App\Services\ProjectServer;  
12 -use Illuminate\Console\Command;  
13 -use Illuminate\Support\Facades\DB;  
14 -use Illuminate\Support\Facades\Schema;  
15 -  
16 -/**  
17 - * Class ProjectInitDatabase  
18 - * @package App\Console\Commands  
19 - */  
20 -class ProjectInit extends Command  
21 -{  
22 - /**  
23 - * The name and signature of the console command.  
24 - *  
25 - * @var string  
26 - */  
27 - protected $signature = 'project:init';  
28 -  
29 - /**  
30 - * The console command description.  
31 - *  
32 - * @var string  
33 - */  
34 - protected $description = '项目数据库初始化';  
35 -  
36 - protected $connect = null;  
37 -  
38 - /**  
39 - * Create a new command instance.  
40 - *  
41 - * @return void  
42 - */  
43 - public function __construct()  
44 - {  
45 - parent::__construct();  
46 - }  
47 -  
48 - /**  
49 - * @return bool  
50 - */  
51 - public function handle()  
52 - {  
53 - #TODO 通过项目ID获取项目部署数据库配置, 创建数据库, 同步数据表  
54 - $project_id = 102;  
55 - $project = Project::getProjectById($project_id);  
56 - if (empty($project) || empty($project->mysqlConfig()))  
57 - return true;  
58 - $this->initDatabase($project);  
59 -  
60 - return true;  
61 - }  
62 -  
63 - /**  
64 - * @param Project $project  
65 - * @return bool  
66 - */  
67 - public function initDatabase($project)  
68 - {  
69 - $create_flag = $this->createDatabase($project);  
70 -  
71 - if (!$create_flag) {  
72 - // 创建数据库失败 添加通知以及再次处理  
73 - }  
74 - // 设置 database.connections.custom_mysql 数据  
75 - ProjectServer::useProject($project->id);  
76 -  
77 - // TODO 创建对应库 初始化数据表  
78 - $this->initTable();  
79 - return true;  
80 - }  
81 -  
82 - /**  
83 - * @return bool  
84 - */  
85 - public function initTable()  
86 - {  
87 - $database_name = DB::connection('custom_tmp_mysql')->getDatabaseName();  
88 -  
89 - $table = Schema::connection('custom_tmp_mysql')->getAllTables();  
90 - $table = array_column($table, 'Tables_in_' . $database_name);  
91 - foreach ($table as $v) {  
92 - $has_table = Schema::connection('custom_mysql')->hasTable($v);  
93 - if ($has_table)  
94 - continue;  
95 -  
96 - $connection = DB::connection('custom_tmp_mysql');  
97 - $sql = $connection->getDoctrineSchemaManager()  
98 - ->getDatabasePlatform()  
99 - ->getCreateTableSQL($connection->getDoctrineSchemaManager()->listTableDetails($v));  
100 -  
101 - DB::connection('custom_mysql')->select($sql[0]);  
102 - }  
103 - return true;  
104 - }  
105 -  
106 - /**  
107 - * 创建数据库  
108 - * 链接mysql 查询数据库是否存在 创建数据库  
109 - * @param Project $project  
110 - * @return bool|\mysqli_result|null  
111 - */  
112 - public function createDatabase($project)  
113 - {  
114 - # 该方法需要:composer require parity-bit/laravel-db-commands  
115 -// $result = Artisan::call('db:create', [  
116 -// '--database' => $database_name,  
117 -// ]);  
118 -//  
119 -// return $result;  
120 -  
121 - if ($this->connect)  
122 - return $this->connect;  
123 -  
124 - //连接到 MySQL 服务器  
125 - $servername = $project->mysqlConfig()->host;  
126 - $username = $project->mysqlConfig()->user;  
127 - $password = $project->mysqlConfig()->password;  
128 - $conn = new \mysqli($servername, $username, $password);  
129 - //检查连接是否成功  
130 - if ($conn->connect_error) {  
131 - die("连接失败: " . $conn->connect_error);  
132 - }  
133 - $this->connect = $conn;  
134 -// $result = $conn->query('SHOW DATABASES LIKE \'' . $database_name . '\';');  
135 -// if ($result)  
136 -// return true;  
137 - $result = $conn->query('CREATE DATABASE ' . $project->databaseName() . ';');  
138 - return $result;  
139 - }  
140 -}  
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\RankData;
  4 +
  5 +use Illuminate\Console\Command;
  6 +
  7 +/**
  8 + * Class BaseCommands
  9 + * @package App\Console\Commands\RankData
  10 + * @author zbj
  11 + * @date 2023/5/11
  12 + */
  13 +abstract class BaseCommands extends Command
  14 +{
  15 + /**
  16 + * @author zbj
  17 + * @date 2023/5/11
  18 + */
  19 + public function handle()
  20 + {
  21 + $try = 3;
  22 + do{
  23 + $try--;
  24 + if($try == 0){
  25 + break;
  26 + }
  27 +
  28 + $error = 0;
  29 + try {
  30 + if(!$this->do()){
  31 + $error = 1;
  32 + }
  33 + }catch (\Exception $e){
  34 + errorLog($this->signature . ' error', [], $e);
  35 + $error = 1;
  36 + }
  37 +
  38 + if($error){
  39 + echo 'error';
  40 + }
  41 + $error && sleep(60);
  42 + }while($error);
  43 + }
  44 +
  45 + abstract function do();
  46 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\RankData;
  4 +
  5 +use App\Helper\Arr;
  6 +use App\Helper\SemrushApi;
  7 +use App\Models\RankData\ExternalLinks as ExternalLinksModel;
  8 +use App\Models\Project\DeployOptimize;
  9 +
  10 +/**
  11 + * Class ExternalLinks
  12 + * @package App\Console\Commands
  13 + * @author zbj
  14 + * @date 2023/5/9
  15 + */
  16 +class ExternalLinks extends BaseCommands
  17 +{
  18 + /**
  19 + * The name and signature of the console command.
  20 + *
  21 + * @var string
  22 + */
  23 + protected $signature = 'rank_data_external_links';
  24 +
  25 + /**
  26 + * The console command description.
  27 + *
  28 + * @var string
  29 + */
  30 + protected $description = '排名数据-外链数据';
  31 +
  32 + /**
  33 + * @author zbj
  34 + * @date 2023/5/6
  35 + */
  36 + public function do()
  37 + {
  38 + $error = 0;
  39 + $semrushApi = new SemrushApi();
  40 + //有排名api编号的项目
  41 + $list = DeployOptimize::where('api_no', '>', 0)->pluck('domain', 'project_id')->toArray();
  42 +
  43 + foreach ($list as $project_id => $domain) {
  44 + if(!$domain){
  45 + continue;
  46 + }
  47 + $model = ExternalLinksModel::where('project_id', $project_id)->first();
  48 + if ($model && $model->updated_date == getThisWeekStarDate()) {
  49 + continue;
  50 + }
  51 + if (!$model) {
  52 + $model = new ExternalLinksModel();
  53 + }
  54 +
  55 + //外链数据
  56 + $res = $semrushApi->backlinks_overview($domain);
  57 + if (!$res) {
  58 + $error++;
  59 + continue;
  60 + }
  61 +
  62 + $data = $this->_data($project_id, $res['total']);
  63 +
  64 + $model->project_id = $project_id;
  65 + $model->total = $data['total'];
  66 + $model->data = $data['data'];
  67 + $model->updated_date = date('Y-m-d');
  68 + $model->save();
  69 + }
  70 + return !$error;
  71 + }
  72 +
  73 +
  74 + /**
  75 + * 构造chat数据
  76 + * @param $project_id
  77 + * @param $total
  78 + * @return array|mixed
  79 + * @author zbj
  80 + * @date 2023/5/10
  81 + */
  82 + public function _data($project_id, $total)
  83 + {
  84 + // //外链数
  85 + $data['total'] = intval($total);
  86 + $model = ExternalLinksModel::where('project_id', $project_id)->first();
  87 + if ($model) {
  88 + //特殊处理的外链数
  89 +// $data['total'] = ($total > $model->total) ? intval($total) : $model->total; //特殊处理的
  90 +
  91 + //chat数据
  92 + $chat_data = Arr::s2a($model['data']);
  93 + if (empty($chat_data[date('Y-m-d')])) {
  94 + array_shift($chat_data);
  95 + }
  96 + } else {
  97 + //chat数据
  98 + for ($i = 1; $i < 12; $i++) {
  99 + $date = date("Y-m-d", strtotime(-7 * $i . 'days'));
  100 + $chat_data[$date] = ceil($total - ($total * rand(5, 10) / 100));
  101 + }
  102 + }
  103 + $chat_data[date('Y-m-d')] = $data['total'];
  104 + $data['data'] = $chat_data;
  105 + return $data;
  106 + }
  107 +
  108 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\RankData;
  4 +
  5 +use App\Helper\QuanqiusouApi;
  6 +use App\Models\Project\DeployOptimize;
  7 +use App\Models\RankData\IndexedPages as IndexedPagesModel;
  8 +
  9 +/**
  10 + * Class IndexedPages
  11 + * @package App\Console\Commands
  12 + * @author zbj
  13 + * @date 2023/5/11
  14 + */
  15 +class IndexedPages extends BaseCommands
  16 +{
  17 + /**
  18 + * The name and signature of the console command.
  19 + *
  20 + * @var string
  21 + */
  22 + protected $signature = 'rank_data_indexed_pages';
  23 +
  24 + /**
  25 + * The console command description.
  26 + *
  27 + * @var string
  28 + */
  29 + protected $description = '排名数据-页面收录数';
  30 +
  31 + /**
  32 + * @throws \Exception
  33 + * @author zbj
  34 + * @date 2023/5/11
  35 + */
  36 + public function do(){
  37 + $error = 0;
  38 + $api = new QuanqiusouApi();
  39 + //有排名api编号的项目
  40 + $list = DeployOptimize::where('api_no', '>', 0)->pluck('api_no', 'project_id')->toArray();
  41 +
  42 + foreach ($list as $project_id => $api_no) {
  43 + $model = IndexedPagesModel::where('project_id', $project_id)->first();
  44 + if($model && $model->updated_date == getThisWeekStarDate()){
  45 + continue;
  46 + }
  47 +
  48 + if(!$model){
  49 + $model = new IndexedPagesModel();
  50 + }
  51 +
  52 + $res = $api->getSiteResPer($api_no);
  53 + if(!$res){
  54 + $error++;
  55 + continue;
  56 + }
  57 +
  58 + $model->project_id = $project_id;
  59 + $model->data = $res['data'];
  60 + $model->updated_date = date('Y-m-d');
  61 + $model->save();
  62 + }
  63 +
  64 + return !$error;
  65 + }
  66 +
  67 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\RankData;
  4 +
  5 +use App\Helper\Arr;
  6 +use App\Helper\QuanqiusouApi;
  7 +use App\Models\Project\DeployBuild;
  8 +use App\Models\Project\DeployOptimize;
  9 +use App\Models\RankData\RankData as GoogleRankModel;
  10 +
  11 +/**
  12 + * Class GoogleRank
  13 + * @package App\Console\Commands
  14 + * @author zbj
  15 + * @date 2023/5/6
  16 + */
  17 +class RankData extends BaseCommands
  18 +{
  19 + /**
  20 + * The name and signature of the console command.
  21 + *
  22 + * @var string
  23 + */
  24 + protected $signature = 'rank_data';
  25 +
  26 + /**
  27 + * The console command description.
  28 + *
  29 + * @var string
  30 + */
  31 + protected $description = '谷歌排名数据';
  32 +
  33 + /**
  34 + * @author zbj
  35 + * @date 2023/5/6
  36 + */
  37 + public function do()
  38 + {
  39 + $error = 0;
  40 + $api = new QuanqiusouApi();
  41 + //有排名api编号的项目
  42 + $list = DeployOptimize::where('api_no', '>' , 0)->select('api_no','minor_languages','project_id')->get();
  43 + //当日所有站点谷歌收录数据
  44 + $site_res = $api->getSiteRes();
  45 + if(!$site_res){
  46 + return false;
  47 + }
  48 + foreach ($list as $item){
  49 + $model = GoogleRankModel::where('project_id', $item['project_id'])->where('lang', '')->first();
  50 + if (!$model || $model->updated_date != date('Y-m-d')) {
  51 + $res = $api->getGoogleRank($item['api_no']);
  52 + if(!$res){
  53 + $error++;
  54 + continue;
  55 + }
  56 + //收录数
  57 + $indexed_pages_num = $site_res[$item['api_no']] ?? 0;
  58 +
  59 + $this->save_rank($item['project_id'], $res, $indexed_pages_num);
  60 + }
  61 +
  62 + //有小语种的
  63 + $lang_list = $api->getLangList();
  64 + if(!empty($lang_list[$item['api_no']])){
  65 + $model = GoogleRankModel::where('project_id', $item['project_id'])->where('lang', '<>', '')->first();
  66 + if (!$model || $model->updated_date != date('Y-m-d')) {
  67 + $res = $api->getGoogleRank($item['api_no'], 1);
  68 + if(!$res){
  69 + $error++;
  70 + continue;
  71 + }
  72 + $data = [];
  73 + //不同的小语种取出来
  74 + foreach ($res as $keyword => $v){
  75 + $data[Arr::last($v)['lang']][$keyword] = $v;
  76 + }
  77 + foreach ($data as $lang => $rank){
  78 + $this->save_rank($item['project_id'], $rank, 0, $lang);
  79 + }
  80 + }
  81 + }
  82 + }
  83 + return !$error;
  84 + }
  85 +
  86 + /**
  87 + * @param $project_id
  88 + * @param int $indexed_pages_num
  89 + * @param $data
  90 + * @param string $lang
  91 + * @author zbj
  92 + * @date 2023/5/8
  93 + */
  94 + public function save_rank($project_id, $data, int $indexed_pages_num = 0, string $lang = ''){
  95 + $without_project_ids = []; //不用处理排名的项目
  96 +
  97 + $first_num = $first_page_num = $first_three_pages_num = $first_five_pages_num = $first_ten_pages_num = 0;
  98 +
  99 + if(!$lang){
  100 + foreach ($data as &$ranks){
  101 + ksort($ranks);
  102 + foreach ($ranks as &$rank){
  103 + //处理排名
  104 + if(!in_array($project_id, $without_project_ids)){
  105 + if($rank['position'] >= 10){
  106 + $rank['position'] -= 5;
  107 + }
  108 + //todo 需要特殊处理排名的项目
  109 + }
  110 + }
  111 + $last = Arr::last($ranks);
  112 + //第一名
  113 + if($last['position'] == 1){
  114 + $first_num ++;
  115 + }
  116 + //排名第一页
  117 + if($last['position'] > 0 && $last['position'] <= 10){
  118 + $first_page_num ++;
  119 + }
  120 + //排名前三页
  121 + if($last['position'] > 0 && $last['position'] <= 30){
  122 + $first_three_pages_num ++;
  123 + }
  124 + //排名前五页
  125 + if($last['position'] > 0 && $last['position'] <= 50){
  126 + $first_five_pages_num ++;
  127 + }
  128 + //排名前十页
  129 + if($last['position'] > 0 && $last['position'] <= 100){
  130 + $first_ten_pages_num ++;
  131 + }
  132 + }
  133 + }
  134 +
  135 + $where = [
  136 + 'project_id' => $project_id,
  137 + 'lang' => $lang
  138 + ];
  139 + $model = GoogleRankModel::where($where)->first();
  140 + if(!$model){
  141 + $model = new GoogleRankModel();
  142 + }
  143 +
  144 + //关键词达标天数
  145 + if($model->updated_date != date('Y-m-d')){
  146 + //保证关键词数
  147 + $keyword_num = DeployBuild::where('project_id', $project_id)->value('keyword_num');
  148 + if($first_page_num >= $keyword_num){
  149 + $model->compliance_day = $model->compliance_day + 1;
  150 + }
  151 + }
  152 +
  153 + $model->project_id = $project_id;
  154 + $model->first_num = $first_num;
  155 + $model->first_page_num = $first_page_num;
  156 + $model->first_three_pages_num = $first_three_pages_num;
  157 + $model->first_five_pages_num = $first_five_pages_num;
  158 + $model->first_ten_pages_num = $first_ten_pages_num;
  159 + $model->indexed_pages_num = $indexed_pages_num;
  160 + $model->lang = $lang;
  161 + $model->data = $data;
  162 + $model->updated_date = date('Y-m-d');
  163 + $model->save();
  164 + }
  165 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\RankData;
  4 +
  5 +
  6 +use App\Helper\Arr;
  7 +use App\Helper\QuanqiusouApi;
  8 +use App\Models\Project\DeployOptimize;
  9 +use App\Models\RankData\RankWeek as RankWeekModel;
  10 +
  11 +/**
  12 + * Class WeekRank
  13 + * @package App\Console\Commands
  14 + * @author zbj
  15 + * @date 2023/5/11
  16 + */
  17 +class RankWeek extends BaseCommands
  18 +{
  19 + /**
  20 + * The name and signature of the console command.
  21 + *
  22 + * @var string
  23 + */
  24 + protected $signature = 'rank_data_week';
  25 +
  26 + /**
  27 + * The console command description.
  28 + *
  29 + * @var string
  30 + */
  31 + protected $description = '排名数据-每周排名数据';
  32 +
  33 + /**
  34 + * @author zbj
  35 + * @date 2023/5/6
  36 + */
  37 + public function do()
  38 + {
  39 + $error = 0;
  40 +
  41 + //获取每周排名数据
  42 + $api = new QuanqiusouApi();
  43 +
  44 + $res = $api->getGoogleRankWeek();
  45 + if (!$res) {
  46 + return false;
  47 + }
  48 +
  49 + $res = Arr::s2a($res);
  50 + //有排名api编号的项目
  51 + $list = DeployOptimize::where('api_no', '>', 0)->pluck('api_no', 'project_id')->toArray();
  52 +
  53 + foreach ($list as $project_id => $api_no) {
  54 + $rank_week = RankWeekModel::where('project_id', $project_id)->first();
  55 + if ($rank_week && $rank_week->updated_date == getThisWeekStarDate()) {
  56 + //本周数据已更新
  57 + continue;
  58 + }
  59 +
  60 + if (!$rank_week) {
  61 + $rank_week = new RankWeekModel();
  62 + }
  63 +
  64 + $rank_week->project_id = $project_id;
  65 + $rank_week->data = $res['data'][$api_no];
  66 + $rank_week->date = $res['date'];
  67 + $rank_week->updated_date = date('Y-m-d');
  68 + $rank_week->save();
  69 + }
  70 +
  71 + return !$error;
  72 + }
  73 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\RankData;
  4 +
  5 +use App\Helper\SemrushApi;
  6 +use App\Models\RankData\RecommDomain as RecommDomainModel;
  7 +use App\Models\Project\DeployOptimize;
  8 +
  9 +/**
  10 + * Class RecommDomain
  11 + * @package App\Console\Commands
  12 + * @author zbj
  13 + * @date 2023/5/9
  14 + */
  15 +class RecommDomain extends BaseCommands
  16 +{
  17 + /**
  18 + * The name and signature of the console command.
  19 + *
  20 + * @var string
  21 + */
  22 + protected $signature = 'rank_data_recomm_domain';
  23 +
  24 + /**
  25 + * The console command description.
  26 + *
  27 + * @var string
  28 + */
  29 + protected $description = '排名数据-外链引荐域名数据';
  30 +
  31 + /**
  32 + * @author zbj
  33 + * @date 2023/5/6
  34 + */
  35 + public function do()
  36 + {
  37 + $error = 0;
  38 + $semrushApi = new SemrushApi();
  39 + //有排名api编号的项目
  40 + $list = DeployOptimize::where('api_no', '>', 0)->pluck('domain', 'project_id')->toArray();
  41 +
  42 + foreach ($list as $project_id => $domain) {
  43 + if(!$domain){
  44 + continue;
  45 + }
  46 + $model = RecommDomainModel::where('project_id', $project_id)->first();
  47 + if ($model && $model->updated_date == getThisWeekStarDate()) {
  48 + continue;
  49 + }
  50 + if (!$model) {
  51 + $model = new RecommDomainModel();
  52 + }
  53 +
  54 + //外链引荐域名
  55 + $data = $semrushApi->backlinks_refdomains($domain);
  56 + if (!$data) {
  57 + $error++;
  58 + continue;
  59 + }
  60 +
  61 + $model->project_id = $project_id;
  62 + $model->data = $data;
  63 + $model->updated_date = date('Y-m-d');
  64 + $model->save();
  65 + }
  66 + return !$error;
  67 + }
  68 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\RankData;
  4 +
  5 +use App\Helper\Arr;
  6 +use App\Helper\GoogleSpeedApi;
  7 +use App\Models\Project\DeployOptimize;
  8 +use App\Models\RankData\Speed as GoogleSpeedModel;
  9 +
  10 +/**
  11 + * Class GoogleSpeed
  12 + * @package App\Console\Commands
  13 + * @author zbj
  14 + * @date 2023/5/10
  15 + */
  16 +class Speed extends BaseCommands
  17 +{
  18 + /**
  19 + * The name and signature of the console command.
  20 + *
  21 + * @var string
  22 + */
  23 + protected $signature = 'rank_data_speed';
  24 +
  25 + /**
  26 + * The console command description.
  27 + *
  28 + * @var string
  29 + */
  30 + protected $description = '排名数据-测速数据';
  31 +
  32 +
  33 + /**
  34 + * @author zbj
  35 + * @date 2023/5/10
  36 + */
  37 + public function do()
  38 + {
  39 + $error = 0;
  40 +
  41 + $googleSpeedApi = new GoogleSpeedApi();
  42 +
  43 + //有排名api编号的项目
  44 + $list = DeployOptimize::where('api_no', '>', 0)->pluck('domain', 'project_id')->toArray();
  45 +
  46 + foreach ($list as $project_id => $domain) {
  47 + $model = GoogleSpeedModel::where('project_id', $project_id)->first();
  48 + if ($model && $model->updated_date == getThisWeekStarDate()) {
  49 + //今周已更新 跳过
  50 + continue;
  51 + }
  52 +
  53 + $res = $googleSpeedApi->run($domain);
  54 + if (!$res) {
  55 + $error++;
  56 + }
  57 + if (!$model) {
  58 + $model = new GoogleSpeedModel;
  59 + }
  60 + $model->project_id = $project_id;
  61 + $model->data = $res;
  62 + $model->updated_date = date('Y-m-d');
  63 + $model->save();
  64 + }
  65 +
  66 + return !$error;
  67 + }
  68 +}
@@ -7,6 +7,8 @@ @@ -7,6 +7,8 @@
7 */ 7 */
8 namespace App\Console\Commands\Test; 8 namespace App\Console\Commands\Test;
9 9
  10 +use App\Models\Devops\ServerConfig;
  11 +use App\Services\ProjectServer;
10 use GuzzleHttp\Client; 12 use GuzzleHttp\Client;
11 use Illuminate\Console\Command; 13 use Illuminate\Console\Command;
12 use Illuminate\Support\Facades\DB; 14 use Illuminate\Support\Facades\DB;
@@ -42,10 +44,11 @@ class Demo extends Command @@ -42,10 +44,11 @@ class Demo extends Command
42 */ 44 */
43 public function handle() 45 public function handle()
44 { 46 {
45 - $sql = 'CREATE DATABASE database_name;';  
46 - $results = DB::select($sql);  
47 - dd($results);  
48 - return true; 47 + preg_match_all("/\@include\(\"([a-z0-9_]+)\"\)/i",'
  48 +@include("asdf")@include("")@include("asdtrw2erf")
  49 + ',$include);
  50 +
  51 + print_r($include);
49 } 52 }
50 53
51 public function printMessage() 54 public function printMessage()
@@ -86,4 +89,4 @@ class Demo extends Command @@ -86,4 +89,4 @@ class Demo extends Command
86 } 89 }
87 dd(1); 90 dd(1);
88 } 91 }
89 -}  
  92 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\Test;
  4 +
  5 +
  6 +
  7 +
  8 +use App\Helper\Arr;
  9 +use Illuminate\Console\Command;
  10 +use Illuminate\Support\Facades\DB;
  11 +
  12 +class DiffDb extends Command
  13 +{
  14 + protected $signature = 'project:diff_db';
  15 +
  16 + /**
  17 + * The console command description.
  18 + *
  19 + * @var string
  20 + */
  21 + protected $description = '对比数据库结构';
  22 +
  23 + /**
  24 + * Create a new command instance.
  25 + *
  26 + * @return void
  27 + */
  28 + public function __construct()
  29 + {
  30 + parent::__construct();
  31 + }
  32 +
  33 + public function handle()
  34 + {
  35 + $custom_mysql_config = [
  36 + 'database.connections.custom_mysql.host' => '127.0.0.1',
  37 + 'database.connections.custom_mysql.port' => '3306',
  38 + 'database.connections.custom_mysql.database' => 'globalso_project_1',
  39 + 'database.connections.custom_mysql.username' => 'root',
  40 + 'database.connections.custom_mysql.password' => 'root',
  41 + ];
  42 + config($custom_mysql_config);
  43 +
  44 + $this->output->writeln("开始进行数据表对比!");
  45 + $tablesSource = DB::select("show tables");
  46 + $tablesRemote = DB::connection('custom_mysql')->select("show tables");
  47 + $tablesSource = array_map(function($item){
  48 + return Arr::first($item);
  49 + }, $tablesSource);
  50 + $tablesRemote = array_map(function($item){
  51 + return Arr::first($item);
  52 + }, $tablesRemote);
  53 +
  54 +
  55 + $tablesNotInRemote = [];
  56 + $tablesInRemote = [];
  57 +
  58 + foreach ($tablesSource as $t) {
  59 + if (!in_array($t, $tablesRemote)) {
  60 + $tablesNotInRemote[] = $t;
  61 + } else {
  62 + $tablesInRemote[] = $t;
  63 + }
  64 + }
  65 +
  66 + //print reports
  67 + echo "本地存在,但是不在custom_mysql中的表:" . PHP_EOL;
  68 + echo ">>>>>>==================================<<<<<<" . PHP_EOL;
  69 + foreach ($tablesNotInRemote as $t) {
  70 + echo $t . PHP_EOL;
  71 + }
  72 + echo ">>>>>>==================================<<<<<<" . PHP_EOL . PHP_EOL . PHP_EOL;
  73 +
  74 +
  75 + echo "本地与custom_mysql结构不一致的表:" . PHP_EOL;
  76 + echo ">>>>>>==================================<<<<<<" . PHP_EOL;
  77 +
  78 + $only127 = $onlyRemote = $modify127 = [];
  79 + foreach ($tablesInRemote as $t) {
  80 + $columns127 = DB::select("show columns from `{$t}`");
  81 + foreach ($columns127 as &$item){
  82 + $item = get_object_vars($item);
  83 + }
  84 + $columnsRemote = DB::connection('custom_mysql')->select("show columns from `{$t}`");
  85 + foreach ($columnsRemote as &$item){
  86 + $item = get_object_vars($item);
  87 + }
  88 +
  89 + $fields127 = $fieldsRemote = [];
  90 + foreach ($columns127 as $v) {
  91 + $fields127[$v['Field']] = $v;
  92 + }
  93 + foreach ($columnsRemote as $v) {
  94 + $fieldsRemote[$v['Field']] = $v;
  95 + }
  96 +
  97 + foreach ($fields127 as $f => $column) {
  98 + if (!isset($fieldsRemote[$f])) {
  99 + $only127[$t][] = $f;
  100 + } else if ($column !== $fieldsRemote[$f]) {
  101 + dump($column);
  102 + dump($fieldsRemote[$f]);
  103 + $modify127[$t][] = $f;
  104 + }
  105 + }
  106 +
  107 + foreach ($fieldsRemote as $f => $column) {
  108 + if (!isset($fields127[$f])) {
  109 + $onlyRemote[$t][] = $f;
  110 + }
  111 + }
  112 + }
  113 +
  114 + if (!empty($only127)) {
  115 + echo "只本地存在:" . PHP_EOL;
  116 + foreach ($only127 as $t => $columns) {
  117 + echo $t . ":";
  118 + foreach ($columns as $field) {
  119 + echo $field . "\t";
  120 + }
  121 + echo PHP_EOL;
  122 + }
  123 + }
  124 + if (!empty($onlyRemote)) {
  125 + echo "只custom_mysql存在:" . PHP_EOL;
  126 + foreach ($onlyRemote as $t => $columns) {
  127 + echo $t . ":";
  128 + foreach ($columns as $field) {
  129 + echo $field . "\t";
  130 + }
  131 + echo PHP_EOL;
  132 + }
  133 + }
  134 + if (!empty($modify127)) {
  135 + echo "本地更新:" . PHP_EOL;
  136 + foreach ($modify127 as $t => $columns) {
  137 + echo $t . ":";
  138 + foreach ($columns as $field) {
  139 + echo $field . "\t";
  140 + }
  141 + echo PHP_EOL;
  142 + }
  143 + }
  144 + echo ">>>>>>==================================<<<<<<" . PHP_EOL . PHP_EOL . PHP_EOL;
  145 + }
  146 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands;
  4 +
  5 +use App\Helper\Arr;
  6 +use App\Models\Product\Category;
  7 +use App\Models\Product\Product;
  8 +use App\Models\RouteMap;
  9 +use GuzzleHttp\Client;
  10 +use GuzzleHttp\Promise\Utils;
  11 +use Illuminate\Console\Command;
  12 +use Illuminate\Support\Facades\DB;
  13 +use Illuminate\Support\Str;
  14 +
  15 +/**
  16 + * 网站引流
  17 + * Class Traffic
  18 + * @package App\Console\Commands
  19 + * @author zbj
  20 + * @date 2023/5/18
  21 + */
  22 +class WebTraffic extends Command
  23 +{
  24 + /**
  25 + * The name and signature of the console command.
  26 + *
  27 + * @var string
  28 + */
  29 + protected $signature = 'web_traffic {type}';
  30 +
  31 + /**
  32 + * The console command description.
  33 + *
  34 + * @var string
  35 + */
  36 + protected $description = '网站引流';
  37 +
  38 + /**
  39 + * Create a new command instance.
  40 + *
  41 + * @return void
  42 + */
  43 + public function __construct()
  44 + {
  45 + parent::__construct();
  46 + }
  47 +
  48 + /**
  49 + * google域名后缀
  50 + * @var string[]
  51 + */
  52 + protected $suffix = [
  53 + 'co.jp' => '日本',
  54 + 'com.tr' => '土耳其',
  55 + 'nl' => '荷兰',
  56 + 'ru' => '俄罗斯',
  57 + 'fr' => '法国',
  58 + 'co.kr' => '韩国',
  59 + 'fi' => '芬兰',
  60 + 'be' => '比利时',
  61 + 'lt' => '立陶宛',
  62 + 'es' => '西班牙',
  63 + 'it' => '意大利',
  64 + 'com.au' => '澳大利亚',
  65 + 'no' => '挪威',
  66 + 'al' => '阿尔巴尼亚',
  67 + 'pt' => '葡萄牙',
  68 + 'lv' => '拉脱维亚',
  69 + 'hu' => '匈牙利',
  70 + 'cz' => '捷克',
  71 + 'de' => '德国',
  72 + 'ca' => '加拿大',
  73 + 'co.in' => '印度',
  74 + 'co.uk' => '英国',
  75 + 'com.vn' => '越南',
  76 + 'com.br' => '巴西',
  77 + 'co.il' => '以色列',
  78 + 'pl' => '波兰',
  79 + 'com.eg' => '埃及',
  80 + 'co.th' => '泰国',
  81 + 'sk' => '斯洛伐克',
  82 + 'ro' => '罗马尼亚',
  83 + 'com.mx' => '墨西哥',
  84 + 'com.my' => '马来西亚',
  85 + 'com.pk' => '巴基斯坦',
  86 + 'co.nz' => '新西兰',
  87 + 'co.za' => '南非',
  88 + 'com.ar' => '阿根廷',
  89 + 'com.kw' => '科威特',
  90 + 'com.sg' => '新加坡',
  91 + 'com.co' => '哥伦比亚',
  92 + 'co.id' => '印度尼西亚',
  93 + 'gr' => '希腊',
  94 + 'bg' => '保加利亚',
  95 + 'mn' => '蒙古',
  96 + 'dk' => '丹麦',
  97 + 'com.sa' => '沙特阿拉伯',
  98 + 'com.pe' => '秘鲁',
  99 + 'com.ph' => '菲律宾',
  100 + 'com.ua' => '乌克兰',
  101 + 'ge' => '格鲁吉亚',
  102 + 'ae' => '阿拉伯联合酋长国',
  103 + 'tn' => '突尼斯',
  104 + ];
  105 +
  106 + /**
  107 + * 概率值
  108 + * @var int[]
  109 + */
  110 + protected $sjjg = [720, 280];//访问间隔占比 访问|不访问
  111 + //访问页面类型占比 产品详情页、单页|产品分类页
  112 + protected $ymzb = [
  113 + 'urls_cats' => 700,
  114 + 'urls_details' => 300
  115 + ];
  116 + protected $sdzb = [600, 200, 150, 50]; //访问页面深度占比 1页|2页|3-6页|7-11页
  117 + protected $yddzb = [1 => 700, 2 => 300]; //移动端占比 pc|mobile
  118 + //模拟访问来源占比 (美国)
  119 + protected $lyzb = [
  120 + 'https://www.google.com/' => 630,
  121 + 'http://www.google.com/' => 30,
  122 + 'http://www.bing.com/' => 20,
  123 + 'https://www.bing.com/' => 5,
  124 + 'https://www.youtube.com/' => 5,
  125 + 'https://search.yahoo.com/' => 5,
  126 + 'https://www.facebook.com/' => 5,
  127 + ];
  128 + protected $otherzb = [700, 300]; //模拟访问来源占比 (非美国) google.com|google.其他后缀
  129 +
  130 + protected $pc_ua = [
  131 + 0 => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
  132 + 1 => 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36',
  133 + 2 => 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1'
  134 + ];
  135 +
  136 + protected $mobile_ua = [
  137 + 0 => 'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko; googleweblight) Chrome/38.0.1025.166 Mobile Safari/535.19',
  138 + ];
  139 +
  140 + /**
  141 + * @return bool
  142 + */
  143 + public function handle()
  144 + {
  145 + $type = $this->argument('type');
  146 +
  147 + $this->sleep($type);
  148 +
  149 + $project_list = $this->getProjectList($type);
  150 + $project_chunk = array_chunk($project_list,500,true);
  151 +
  152 + foreach ($project_chunk as $chunk) {
  153 + $need_project = [];
  154 + foreach ($chunk as $project) {
  155 + //随机引流间隔
  156 + $res_sjjg = $this->get_rand($this->sjjg);
  157 + if ($res_sjjg == 1) {
  158 + continue;
  159 + }
  160 +
  161 + $project_urls = $this->getProductUrls($project['project_id']);
  162 + $project_urls['home'] = $project['domain'];
  163 + //随机访问页面
  164 + $project['visit_urls'] = $this->getVisitUrls($project_urls);
  165 + //随机客户端
  166 + $project['device_port'] = $this->get_rand($this->yddzb);
  167 + $project['user_agent'] = $project['device_port'] == 1 ? Arr::random($this->pc_ua) : Arr::random($this->mobile_ua);
  168 +
  169 + $need_project[] = $project;
  170 + }
  171 +
  172 + //随机访问ip
  173 + $ips = $this->getIpAreas(count($need_project));
  174 + //最多10层深度
  175 + $client = new Client(['verify' => false]);
  176 + for ($j = 0; $j < 10; $j++) {
  177 + for ($j = 0; $j < 10; $j++) {
  178 + //并发请求
  179 + $promises = [];
  180 + foreach ($need_project as $project_key => $project) {
  181 + if (empty($project['visit_urls'][$j])) {
  182 + continue;
  183 + }
  184 +
  185 + $data = [
  186 + 'ip' => $ips[$project_key]['ip'],
  187 + 'referer' => $this->getReferer($ips[$project_key]['ip_area']),
  188 + 'url' => $project['visit_urls'][$j],
  189 + 'device_port' => $this->get_rand($this->yddzb)
  190 + ];
  191 + $promises[] = $client->postAsync($project['domain'] . 'api/customerVisit', ['form_params' => $data]);
  192 + }
  193 + Utils::settle($promises)->wait();
  194 +
  195 + //每个深度随机等待
  196 + sleep(rand(2, 10));
  197 + }
  198 + }
  199 + }
  200 + }
  201 +
  202 + /**
  203 + * 不同项目 休眠
  204 + */
  205 + protected function sleep($type){
  206 + if($type == 1){ //1-3个月的项目
  207 + sleep(rand(5,480));
  208 + }elseif($type == 2){ //4-8个月的项目
  209 + sleep(rand(5,240));
  210 + }elseif($type == 3){ // 大于9个月的项目
  211 + sleep(rand(5,120));
  212 + }
  213 + }
  214 +
  215 + /**
  216 + * 引流的项目
  217 + */
  218 + protected function getProjectList($type){
  219 + //todo 根据type获取需要引流的项目
  220 + return [
  221 + [
  222 + 'project_id' => 1,
  223 + 'domain' => 'https://demomark.globalso.com/',
  224 + ]
  225 + ];
  226 + }
  227 +
  228 + /**
  229 + * 获取产品分类、单页和详情链接
  230 + */
  231 + protected function getProductUrls($project_id){
  232 + //产品分类页面
  233 + $product_cate_ids = Category::where('project_id', $project_id)->where('status', Category::STATUS_ACTIVE)->pluck('id')->toArray();
  234 + $data['urls_cats'] = RouteMap::where('project_id', $project_id)->where('source', RouteMap::SOURCE_PRODUCT_CATE)->whereIn('source_id', $product_cate_ids)->get()->toArray();
  235 + //单页面
  236 + //todo 发布状态的单页面id
  237 + $data['urls_page'] = RouteMap::where('project_id', $project_id)->where('source', RouteMap::SOURCE_PAGE)->get()->toArray();
  238 + //产品详情页
  239 + $product_ids = Product::where('project_id', $project_id)->where('status', Product::STATUS_ON)->pluck('id')->toArray();
  240 + $data['urls_details'] = RouteMap::where('project_id', $project_id)->where('source', RouteMap::SOURCE_PRODUCT)->whereIn('source_id', $product_ids)->get()->toArray();
  241 +
  242 + $data['urls_cats'] = array_merge($data['urls_cats'], $data['urls_page']);
  243 + if(empty($data['urls_cats'])){
  244 + $data['urls_cats'] = $data['urls_details'];
  245 + }
  246 +
  247 + return $data;
  248 + }
  249 +
  250 + /**
  251 + * 获取地区IP
  252 + */
  253 + protected function getIpAreas($num)
  254 + {
  255 + //本地时间为7-23点的地区
  256 + $h = date('H');
  257 + $areas = [];
  258 + $list = DB::table('gl_area_timezone')->get();
  259 + foreach ($list as $v) {
  260 + $v = (array)$v;
  261 + $country_hour = $h + $v['diff'];
  262 + if ($country_hour < 0) {
  263 + $country_hour = 24 + $country_hour;
  264 + }
  265 + if ($country_hour >= 7 && $country_hour < 23) {
  266 + $areas[] = $v['name'];
  267 + }
  268 + }
  269 + //根据地区随机取该地区的IP
  270 + $data = DB::table('gl_xunpan_ipdata')->whereIn('ip_area', $areas)->inRandomOrder()->limit($num)->get();
  271 + return Arr::s2a(Arr::a2s($data));
  272 + }
  273 +
  274 + /**
  275 + * 概率算法
  276 + */
  277 + protected function get_rand($proArr) {
  278 + $result = '';
  279 + $proSum = array_sum($proArr);
  280 + foreach ($proArr as $key => $proCur) {
  281 + $randNum = mt_rand(1, $proSum);
  282 + if ($randNum <= $proCur) {
  283 + $result = $key;
  284 + break;
  285 + } else {
  286 + $proSum -= $proCur;
  287 + }
  288 + }
  289 + unset ($proArr);
  290 + return $result;
  291 + }
  292 +
  293 + /**
  294 + * 根据随机访问深度 随机获取访问页面
  295 + */
  296 + protected function getVisitUrls($project_urls){
  297 + //没有分类页 就只访问首页
  298 + if(!$project_urls['urls_cats']){
  299 + $url[] = $project_urls['home'];
  300 + return $url;
  301 + }
  302 + //随机访问深度
  303 + $res_sdzb = $this->get_rand($this->sdzb);
  304 + //随机访问页面类型
  305 + $res_ymzb = $this->get_rand($this->ymzb);
  306 +
  307 + $all_url = array_merge($project_urls['urls_cats'],$project_urls['urls_details']);
  308 + if(!$all_url){
  309 + $url[] = $project_urls['home'];
  310 + return $url;
  311 + }
  312 +
  313 + $url = [];
  314 + if($res_sdzb == 0){//深度一页
  315 + $url[] = $project_urls[$res_ymzb] ? Arr::random($project_urls[$res_ymzb])['route'] : '';
  316 + }elseif($res_sdzb == 1){//深度两页
  317 + $url[] = $project_urls['home'];
  318 + $url[] = $project_urls[$res_ymzb] ? Arr::random($project_urls[$res_ymzb])['route'] : '';
  319 + }elseif($res_sdzb == 2){//深度3-6页
  320 + $yms = rand(2,5); //随机页面数
  321 + $url = Arr::pluck(Arr::random($all_url, $yms), 'route');
  322 + $url = Arr::prepend($url, $project_urls['home']);//首页加到最前面去
  323 + }elseif($res_sdzb == 3){//深度7-11页
  324 + $yms = rand(6,10); //随机页面数
  325 + $url = Arr::pluck(Arr::random($all_url, $yms), 'route');
  326 + $url = Arr::prepend($url, $project_urls['home']);//首页加到最前面去
  327 + }
  328 + foreach ($url as &$v){
  329 + if(!Str::contains($v, $project_urls['home'])){
  330 + $v = $project_urls['home'] . $v;
  331 + }
  332 + }
  333 + return array_unique(array_filter($url));
  334 + }
  335 +
  336 + /**
  337 + * 获取访问来路
  338 + */
  339 + protected function getReferer($ip_area){
  340 + if($ip_area == '美国'){
  341 + $referer = $this->get_rand($this->lyzb);
  342 + }else{
  343 + $referer = 'https://www.google.com/';
  344 +
  345 + $suffix = array_search($ip_area, $this->suffix);
  346 + if($suffix){
  347 + $res_qtzb = $this->get_rand($this->otherzb);
  348 + if($res_qtzb == 1){
  349 + $referer = 'https://www.google.'.$suffix.'/';
  350 + }
  351 + }
  352 + }
  353 + return $referer;
  354 + }
  355 +}
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\YesterdayCount;
  4 +
  5 +use App\Helper\Common;
  6 +use App\Helper\FormGlobalsoApi;
  7 +use App\Http\Logic\Aside\Project\ProjectLogic;
  8 +use App\Models\CustomerVisit\CustomerVisitItem;
  9 +use App\Models\Project\DeployBuild;
  10 +use Carbon\Carbon;
  11 +use Illuminate\Console\Command;
  12 +use Illuminate\Support\Facades\DB;
  13 +
  14 +class Yesterday extends Command
  15 +{
  16 + const STATUS_ERROR = 400;
  17 + public $error = 0;
  18 + /**
  19 + * The name and signature of the console command.
  20 + *
  21 + * @var string
  22 + */
  23 + protected $signature = 'yesterday_count';
  24 +
  25 + /**
  26 + * The console command description.
  27 + *
  28 + * @var string
  29 + */
  30 + protected $description = '统计昨日数据';
  31 + /**
  32 + * @name :(定时执行生成昨日数据统计)handle
  33 + * @author :lyh
  34 + * @method :post
  35 + * @time :2023/5/12 14:48
  36 + */
  37 + public function handle()
  38 + {
  39 + $deployModel = new DeployBuild();
  40 + $list = $deployModel->list();
  41 + $data = [];
  42 + $yesterday = Carbon::yesterday()->toDateString();
  43 + foreach ($list as $v){
  44 + $arr = [];
  45 + //统计时间
  46 + $arr['date'] = $yesterday;
  47 + //pv统计
  48 + $arr['pv_num'] = $this->pv_num($yesterday,$v['test_domain']);
  49 + //ip统计
  50 + $arr['ip_num'] = $this->ip_num($yesterday,$v['test_domain']);
  51 + //服务达标天数
  52 + $arr['compliance_day'] = $this->compliance_day($yesterday);
  53 + //剩余服务时常
  54 + $arr['service_day'] = $v['service_duration'] - Common::getDaysToTargetDate($v['created_at']);
  55 + //项目id
  56 + $arr['project_id'] = $v['project_id'];
  57 + $arr['created_at'] = date('Y-m-d H:i:s');
  58 + $arr['updated_at'] = date('Y-m-d H:i:s');
  59 + //询盘统计
  60 + $arr = $this->inquiry($arr,$v['test_domain']);
  61 + $data[] = $arr;
  62 + }
  63 + //判断数据是否存在
  64 + DB::table('gl_count')->insert($data);
  65 + echo $this->error;
  66 + }
  67 +
  68 + /**
  69 + * @name :(统计pv)pv_num
  70 + * @author :lyh
  71 + * @method :post
  72 + * @time :2023/6/14 15:40
  73 + */
  74 + public function pv_num($yesterday,$domain){
  75 + $pv = DB::table('gl_customer_visit_item')->whereDate('updated_date', $yesterday)->where('domain',$domain)->count();
  76 + return $pv;
  77 + }
  78 +
  79 + /**
  80 + * @name :(统计pv)pv_num
  81 + * @author :lyh
  82 + * @method :post
  83 + * @time :2023/6/14 15:40
  84 + */
  85 + public function ip_num($yesterday,$domain){
  86 + $ip = DB::table('gl_customer_visit')->whereDate('updated_date', $yesterday)->where('domain',$domain)->count();
  87 + return $ip;
  88 + }
  89 +
  90 + /**
  91 + * @param $arr
  92 + * @param $domain
  93 + * @name :(询盘统计)inquiry
  94 + * @author :lyh
  95 + * @method :post
  96 + * @time :2023/6/14 15:44
  97 + */
  98 + public function inquiry($arr,$domain){
  99 + $inquiry_list = (new FormGlobalsoApi())->getInquiryList($domain,'',1,100000000);
  100 + if($inquiry_list['status'] == self::STATUS_ERROR){
  101 + $arr['inquiry_num'] = 0;
  102 + }else{
  103 + $arr['inquiry_num'] = $inquiry_list['data']['total'];
  104 + //询盘国家统计
  105 + $countryData = $inquiry_list['data']['data'];
  106 + $countryArr = [];
  107 + foreach ($countryData as $v1){
  108 + if(isset($countryArr[$v1['country']])){
  109 + $countryArr[$v1['country']]++;
  110 + }else{
  111 + $countryArr[$v1['country']] = 0;
  112 + }
  113 + }
  114 + arsort($countryArr);
  115 + $top20 = array_slice($countryArr, 0, 20, true);
  116 + $arr['country'] = json_encode($top20);
  117 + }
  118 + return $arr;
  119 + }
  120 +
  121 + /**
  122 + * @param $yesterday
  123 + * @name :(服务达标天数)compliance_day
  124 + * @author :lyh
  125 + * @method :post
  126 + * @time :2023/6/14 15:48
  127 + */
  128 + public function compliance_day($yesterday){
  129 + //服务达标天数
  130 + $rank_info = DB::table('gl_rank_data')->where(['updated_date'=>$yesterday,'lang'=>''])->select(['compliance_day'])->first();
  131 + if(empty($rank_info)){
  132 + $compliance_day = 0;
  133 + }else{
  134 + $compliance_day = $rank_info->compliance_day;
  135 + }
  136 + return $compliance_day;
  137 + }
  138 +}
@@ -16,6 +16,34 @@ class Kernel extends ConsoleKernel @@ -16,6 +16,34 @@ class Kernel extends ConsoleKernel
16 protected function schedule(Schedule $schedule) 16 protected function schedule(Schedule $schedule)
17 { 17 {
18 // $schedule->command('inspire')->hourly(); 18 // $schedule->command('inspire')->hourly();
  19 + $schedule->command('rank_data')->dailyAt('01:00')->withoutOverlapping(1); // 排名数据,每天凌晨执行一次
  20 + $schedule->command('rank_data_speed')->weeklyOn(1, '01:00')->withoutOverlapping(1); // 排名数据-测速数据,每周一凌晨执行一次
  21 + $schedule->command('rank_data_external_links')->weeklyOn(1, '01:00')->withoutOverlapping(1); // 排名数据-外链,每周一凌晨执行一次
  22 + $schedule->command('rank_data_indexed_pages')->weeklyOn(1, '01:00')->withoutOverlapping(1); // 排名数据-页面收录,每周一凌晨执行一次
  23 + $schedule->command('rank_data_recomm_domain')->weeklyOn(1, '01:00')->withoutOverlapping(1); // 排名数据-引荐域名,每周一凌晨执行一次
  24 + $schedule->command('rank_data_week')->weeklyOn(1, '01:00')->withoutOverlapping(1); // 排名数据,每周一凌晨执行一次
  25 + $schedule->command('share_user')->dailyAt('01:00')->withoutOverlapping(1); // 清除用户ayr_share数据,每天凌晨1点执行一次
  26 + $schedule->command('yesterday_count')->dailyAt('01:00')->withoutOverlapping(1); // 清除用户ayr_share数据,每天凌晨1点执行一次
  27 + $schedule->command('web_traffic 1')->everyThirtyMinutes(); // 引流 1-3个月的项目,半小时一次
  28 + $schedule->command('web_traffic 2')->cron('*/18 * * * *'); // 引流 4-8个月的项目,18分钟一次
  29 + $schedule->command('web_traffic 3')->cron('*/12 * * * *'); // 引流 大于9个月的项目,12分钟一次
  30 +// // 更新域名|证书结束时间,每天凌晨1点执行一次
  31 +// $schedule->command('domain_time')->dailyAt('01:00')->withoutOverlapping(1);
  32 +// // B站 - 网站数据统计
  33 +// // 获取当前月份最后一天
  34 +// $lastDay = date('Y-m-t');
  35 +// // 统计当月访问来源数据,每月最后一天23:59点执行一次
  36 +// $schedule->command('statistics_source')->monthlyOn($lastDay, '23:59')->withoutOverlapping(1);
  37 +// // 统计当月地域分布数据,每月最后一天23:59点执行一次
  38 +// $schedule->command('statistics_distribution')->monthlyOn($lastDay, '23:59')->withoutOverlapping(1);
  39 +// // 统计当月受访页面数据,每月最后一天23:59点执行一次
  40 +// $schedule->command('statistics_page')->monthlyOn($lastDay, '23:59')->withoutOverlapping(1);
  41 +// // 统计当月访问终端数据,每月最后一天23:59点执行一次
  42 +// $schedule->command('statistics_terminal')->monthlyOn($lastDay, '23:59')->withoutOverlapping(1);
  43 +// // 统计当月流量趋势数据,每月最后一天23:59点执行一次
  44 +// $schedule->command('statistics_trend')->monthlyOn($lastDay, '23:59')->withoutOverlapping(1);
  45 +// // 统计当天流量趋势数据,每天23:59点执行一次
  46 +// $schedule->command('statistics_day_trend')->dailyAt('23:59')->withoutOverlapping(1);
19 } 47 }
20 48
21 /** 49 /**
@@ -3,13 +3,13 @@ @@ -3,13 +3,13 @@
3 namespace App\Exceptions; 3 namespace App\Exceptions;
4 4
5 use App\Enums\Common\Code; 5 use App\Enums\Common\Code;
6 -use App\Enums\Common\Common;  
7 use App\Services\DingService; 6 use App\Services\DingService;
8 use App\Utils\EncryptUtils; 7 use App\Utils\EncryptUtils;
9 use App\Utils\LogUtils; 8 use App\Utils\LogUtils;
10 use Illuminate\Database\Eloquent\ModelNotFoundException; 9 use Illuminate\Database\Eloquent\ModelNotFoundException;
11 use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; 10 use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
12 use Illuminate\Support\Arr; 11 use Illuminate\Support\Arr;
  12 +use Illuminate\Support\Facades\Cache;
13 use Illuminate\Support\Facades\Route; 13 use Illuminate\Support\Facades\Route;
14 use Illuminate\Validation\ValidationException; 14 use Illuminate\Validation\ValidationException;
15 use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; 15 use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
@@ -59,7 +59,6 @@ class Handler extends ExceptionHandler @@ -59,7 +59,6 @@ class Handler extends ExceptionHandler
59 */ 59 */
60 public function report(Throwable $exception) 60 public function report(Throwable $exception)
61 { 61 {
62 -  
63 //日志记录 62 //日志记录
64 $exceptionMessage = "错误CODE:" . $exception->getCode() . 63 $exceptionMessage = "错误CODE:" . $exception->getCode() .
65 "-----错误message:" . $exception->getMessage() . 64 "-----错误message:" . $exception->getMessage() .
@@ -111,31 +110,26 @@ class Handler extends ExceptionHandler @@ -111,31 +110,26 @@ class Handler extends ExceptionHandler
111 $code = $exception->getCode(); 110 $code = $exception->getCode();
112 }elseif ($exception instanceof BsideGlobalException) { 111 }elseif ($exception instanceof BsideGlobalException) {
113 $code = $exception->getCode(); 112 $code = $exception->getCode();
114 - } elseif ($exception instanceof ValidationException) { 113 + }elseif ($exception instanceof ValidationException) {
115 $code = Code::USER_PARAMS_ERROE(); 114 $code = Code::USER_PARAMS_ERROE();
116 - $message = Arr::first(Arr::first($exception->errors())); 115 + $message = $code->description = Arr::first(Arr::first($exception->errors()));
117 } elseif ($exception instanceof NotFoundHttpException || $exception instanceof MethodNotAllowedHttpException) { 116 } elseif ($exception instanceof NotFoundHttpException || $exception instanceof MethodNotAllowedHttpException) {
118 return response('404 Not Found', 404); 117 return response('404 Not Found', 404);
119 } else { 118 } else {
120 $code = Code::SYSTEM_ERROR(); 119 $code = Code::SYSTEM_ERROR();
121 } 120 }
122 - //钉钉通知错误信息  
123 - if (in_array(config('app.env'), ['test', 'production']) && (in_array(substr($code, 0, 1), ['B', 'C']))) {  
124 - $exceptionMessage = "路由:" . Route::current()->uri .  
125 - "-----错误CODE:" . $exception->getCode() .  
126 - "-----错误message:" . $exception->getMessage() .  
127 - '------错误文件:' . $exception->getFile() . '-------错误行数:' .  
128 - $exception->getLine();  
129 - (new DingService())->handle(['keyword' => "ERROR", 'msg' => config('app.env') . '环境报错:' . $exceptionMessage, 'isAtAll' => false]);  
130 - }  
131 //开启debug 错误原样输出 121 //开启debug 错误原样输出
132 $debub = config('app.debug'); 122 $debub = config('app.debug');
133 $message = $debub ? $message : ($code->description ?? $message); 123 $message = $debub ? $message : ($code->description ?? $message);
134 -  
135 $response = [ 124 $response = [
136 'code' => $code, 125 'code' => $code,
137 'message' => $message 126 'message' => $message
138 ]; 127 ];
  128 + // 调试模式
  129 + if(env('app_debug')){
  130 + $response['trace'] = $exception->getTrace();
  131 + }
  132 +
139 //加密返回 133 //加密返回
140 if (config('app.params_encrypt')) { 134 if (config('app.params_encrypt')) {
141 $k = config('app.params_encrypt_key'); 135 $k = config('app.params_encrypt_key');
1 -<?php  
2 -  
3 -namespace App\Files;  
4 -  
5 -use Illuminate\Http\Request;  
6 -  
7 -class Image  
8 -{  
9 - protected $request = [];  
10 -  
11 - public function __construct(Request $request)  
12 - {  
13 - $this->request = $request;  
14 - }  
15 -  
16 - /**  
17 - * @name :上传图片  
18 - * @return void  
19 - * @author :liyuhang  
20 - * @method  
21 - */  
22 - public function uploads(){  
23 - $url = './uploads/images/';  
24 - $param = $this->request->post();  
25 - if($this->request->hasFile('image') && $this->request->file('image')->isValid()){  
26 - $filename = date('ymdHis').rand(10000,99999).$this->request->file('image');  
27 - $this->request->file('image')->move('./uploads/images/',$filename);  
28 - }else{  
29 - return false;  
30 - }  
31 - return $url.$filename;  
32 - }  
33 -}  
  1 +<?php
  2 +
  3 +namespace App\Helper;
  4 +
  5 +class AliSms
  6 +{
  7 +
  8 + private $_msg = array( //状态对照
  9 + 1 => "发送成功",
  10 + 0 => "其他系统错误",
  11 + -1 => "短信余额不足",
  12 + -2 => "资金账户被锁定",
  13 + -3 => "用户被锁定",
  14 + -4 => "号码在黑名单内",
  15 + -5 => "用户名或密码不正确",
  16 + -6 => "号码不正确",
  17 + -7 => "接口连接失败",
  18 + -8 => "号码格式错误",
  19 + -9 => "通道编号错误",
  20 + -10 => "定时发送时间不正确",
  21 + -11 => "没有输入短信内容",
  22 + -12 => "短信内容超出长度限制",
  23 + -15 => "内容含非法关键字",
  24 + -16 => "超出发送时间范围",
  25 + -17 => "通道被关闭",
  26 + -18 => "短信内容没有签名",
  27 + -30 => "手机未认证",
  28 + -31 => "身份未认证",
  29 + -32 => "请勿重复发送",
  30 + -33 => "验证码已过期,请重新获取",
  31 + -34 => "手机号码格式不正确",
  32 + -35 => "验证码不正确",
  33 + );
  34 + // 保存错误信息
  35 + public $error;
  36 + public $_code = "";
  37 + public $_name = "";
  38 + public $_key_str = ""; // cache full name.
  39 + protected $_expire = 600; // 验证码过期时间(s)
  40 + public $_key = [
  41 + ];
  42 + // Access Key ID
  43 + private $accessKeyId = '';
  44 + // Access Key Secret
  45 + private $accessKeySecret = '';
  46 + // 签名
  47 + private $signName = '';
  48 + // 模版ID
  49 + public $templateCode = '';
  50 +
  51 + public function __construct($config = array())
  52 + {
  53 + $config = array(
  54 + 'accessKeyId' => config('aliyunsms.access_key'),
  55 + 'accessKeySecret' => config('aliyunsms.access_secret'),
  56 + 'signName' => config('aliyunsms.sign_name'),
  57 + 'templateCode' => config('aliyunsms.login_sms_temp'),
  58 + );
  59 + // 配置参数
  60 + $this->accessKeyId = $config['accessKeyId'];
  61 + $this->accessKeySecret = $config['accessKeySecret'];
  62 + $this->signName = $config['signName'];
  63 + $this->templateCode = $config['templateCode'];
  64 + }
  65 +
  66 + /**
  67 + * 规范化字符串以符合阿里云短信接口
  68 + * @param $string
  69 + * @return mixed|string
  70 + */
  71 + private function percentEncode($string)
  72 + {
  73 + $string = urlencode($string);
  74 + $string = preg_replace('/\+/', '%20', $string);
  75 + $string = preg_replace('/\*/', '%2A', $string);
  76 + $string = preg_replace('/%7E/', '~', $string);
  77 + return $string;
  78 + }
  79 +
  80 + /**
  81 + * 签名
  82 + *
  83 + * @param unknown $parameters
  84 + * @param unknown $accessKeySecret
  85 + * @return string
  86 + */
  87 + private function computeSignature($parameters, $accessKeySecret)
  88 + {
  89 + ksort($parameters);
  90 + $canonicalizedQueryString = '';
  91 + foreach ($parameters as $key => $value) {
  92 + $canonicalizedQueryString .= '&' . $this->percentEncode($key) . '=' . $this->percentEncode($value);
  93 + }
  94 + $stringToSign = 'GET&%2F&' . $this->percentencode(substr($canonicalizedQueryString, 1));
  95 + $signature = base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret . '&', true));
  96 + return $signature;
  97 + }
  98 +
  99 + /**
  100 + * 发送验证码 https://help.aliyun.com/document_detail/44364.html?spm=5176.doc44368.6.126.gSngXV
  101 + *
  102 + * @param unknown $mobile
  103 + * @param unknown $verify_code
  104 + *
  105 + */
  106 + public function send_sms($mobile, $paramstring)
  107 + {
  108 + $params = array(
  109 + // 公共参数
  110 + 'SignName' => $this->signName,
  111 + 'Format' => 'JSON',
  112 + 'Version' => '2016-09-27',
  113 + 'AccessKeyId' => $this->accessKeyId,
  114 + 'SignatureVersion' => '1.0',
  115 + 'SignatureMethod' => 'HMAC-SHA1',
  116 + 'SignatureNonce' => uniqid(),
  117 + 'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
  118 + // 接口参数
  119 + 'Action' => 'SingleSendSms',
  120 + 'TemplateCode' => $this->templateCode,
  121 + 'RecNum' => $mobile,
  122 + 'ParamString' => $paramstring,
  123 + );
  124 + // 计算签名并把签名结果加入请求参数
  125 + $params['Signature'] = $this->computeSignature($params, $this->accessKeySecret);
  126 +
  127 + // 发送请求
  128 + $url = 'https://sms.aliyuncs.com/?' . http_build_query($params);
  129 + $result = http_get($url); //TODO:上线前打开
  130 + if (isset($result['Code'])) {
  131 + $this->error = $this->getErrorMessage($result['Code']);
  132 + return false;
  133 + }
  134 + return true;
  135 + }
  136 +
  137 + /**
  138 + * 发送验证码 https://help.aliyun.com/document_detail/44364.html?spm=5176.doc44368.6.126.gSngXV
  139 + *
  140 + * @param unknown $mobile
  141 + * @param unknown $verify_code
  142 + *
  143 + */
  144 + public function send_verify($mobile)
  145 + {
  146 + if ($this->checkMobile($mobile) === false) {
  147 + $this->error = $this->_msg[-34];
  148 + return -34;
  149 + }
  150 + $session = cache($this->_key_str . $mobile);
  151 + if ($session && time() - $session['time'] < 60) {
  152 + if ($session['code'] == null) {
  153 + return true;
  154 + } else {
  155 + $this->error = $this->_msg[-32];
  156 + return -32;
  157 + }
  158 + }
  159 + $this->_code = rand(1000, 9999);
  160 + $params = array(
  161 + // 公共参数
  162 + 'SignName' => $this->signName,
  163 + 'Format' => 'JSON',
  164 + 'Version' => '2016-09-27',
  165 + 'AccessKeyId' => $this->accessKeyId,
  166 + 'SignatureVersion' => '1.0',
  167 + 'SignatureMethod' => 'HMAC-SHA1',
  168 + 'SignatureNonce' => uniqid(),
  169 + 'Timestamp' => gmdate('Y-m-d\TH:i:s\Z'),
  170 + // 接口参数
  171 + 'Action' => 'SingleSendSms',
  172 + 'TemplateCode' => $this->templateCode,
  173 + 'RecNum' => $mobile,
  174 + 'ParamString' => '{"msgcode":"' . $this->_code . '"}',
  175 + );
  176 + // 计算签名并把签名结果加入请求参数
  177 + $params['Signature'] = $this->computeSignature($params, $this->accessKeySecret);
  178 + // 发送请求
  179 + $url = 'https://sms.aliyuncs.com/?' . http_build_query($params);
  180 + $result = http_get($url); //TODO:上线前打开
  181 + // $result =1;
  182 + if ($result) {
  183 + $session = array();
  184 + $session['code'] = $this->_code; // 把校验码保存到session
  185 + $session['time'] = time(); // 验证码创建时间
  186 + cache($this->_key_str . $mobile, $session, $this->_expire);
  187 + } else {
  188 + return $this->error = $this->_msg[0];
  189 + }
  190 + if (isset($result['Code'])) {
  191 + $this->error = $this->getErrorMessage($result['Code']);
  192 + return false;
  193 + }
  194 + return true;
  195 + }
  196 + /**
  197 + * 验证手机号码
  198 + */
  199 + public function checkMobile($tel)
  200 + {
  201 + if (preg_match("/^1[3,4,6,5,8,7,9][0-9]{1}[0-9]{8}$/", $tel)) {
  202 + //验证通过
  203 + return true;
  204 + } else {
  205 + $this->error = $this->_msg[-34];
  206 + //手机号码格式不对
  207 + return false;
  208 + }
  209 + }
  210 +
  211 + /**
  212 + * 验证码是否正确
  213 + * @param string $key 手机号码
  214 + * @param int|string $code 验证码
  215 + * @param int|string $type 类型 reg-注册时获取 sms-快速登录时 pwd-修改密码时 bind-绑定手机时 unbind-解绑时
  216 + * @return boolean 验证短信验证码是否正确
  217 + */
  218 + public function check($key, $code, $type = 'reg')
  219 + {
  220 + $this->_key_str = $type . '_' . $key;
  221 + $session = cache($this->_key_str);
  222 + if (empty($code) || empty($session)) {
  223 + $this->error = $this->_msg[-33] . $this->_key_str;
  224 + return false;
  225 + }
  226 + if (time() - $session['time'] > $this->_expire) {
  227 + cache($this->_key_str, null);
  228 + $this->error = $this->_msg[-33] . $this->_key_str;
  229 + return false;
  230 + }
  231 + if ($code == $session['code']) {
  232 + return true;
  233 + }
  234 + $this->error = $this->_msg[-35] . $this->_key_str;
  235 + return false;
  236 + }
  237 +
  238 + /**
  239 + * 验证成功后调用清空验证码
  240 + */
  241 + public function afterCheck()
  242 + {
  243 + cache($this->_key_str, null);
  244 + }
  245 +
  246 + /**
  247 + * 获取详细错误信息
  248 + *
  249 + * @param unknown $status
  250 + */
  251 + public function getErrorMessage($status)
  252 + {
  253 +
  254 + $message = array(
  255 + 'InvalidDayuStatus.Malformed' => '账户短信开通状态不正确',
  256 + 'InvalidSignName.Malformed' => '短信签名不正确或签名状态不正确',
  257 + 'InvalidTemplateCode.MalFormed' => '短信模板Code不正确或者模板状态不正确',
  258 + 'InvalidRecNum.Malformed' => '目标手机号不正确,单次发送数量不能超过100',
  259 + 'InvalidParamString.MalFormed' => '短信模板中变量不是json格式',
  260 + 'InvalidParamStringTemplate.Malformed' => '短信模板中变量与模板内容不匹配',
  261 + 'InvalidSendSms' => '1小时只能请求7次,谢谢',
  262 + 'InvalidDayu.Malformed' => '变量不能是url,可以将变量固化在模板中',
  263 + );
  264 + if (isset($message[$status])) {
  265 + return $message[$status];
  266 + }
  267 + return $status;
  268 + }
  269 +
  270 + private function _addlog($name, $title)
  271 + {
  272 + $this->_keys["code"] = $this->_code;
  273 +// addlog($this->_keys, $title, 1, $this->_url);
  274 + }
  275 +}
@@ -3,6 +3,8 @@ @@ -3,6 +3,8 @@
3 namespace App\Helper; 3 namespace App\Helper;
4 4
5 5
  6 +use Illuminate\Support\Collection;
  7 +
6 /** 8 /**
7 * 数组类函数 9 * 数组类函数
8 * Class Arrays 10 * Class Arrays
@@ -125,4 +127,89 @@ class Arr extends \Illuminate\Support\Arr @@ -125,4 +127,89 @@ class Arr extends \Illuminate\Support\Arr
125 127
126 return $signle ? $rows[0] : $rows; 128 return $signle ? $rows[0] : $rows;
127 } 129 }
  130 +
  131 +
  132 + /**
  133 + * 数组转字符串
  134 + * @param $arr
  135 + * @return string
  136 + * @author zbj
  137 + * @date 2023/4/17
  138 + */
  139 + public static function a2s($arr): string
  140 + {
  141 + return json_encode($arr, JSON_UNESCAPED_UNICODE);
  142 + }
  143 +
  144 +
  145 + /**
  146 + * 字符串转数组
  147 + * @param $str
  148 + * @return array|mixed
  149 + * @author zbj
  150 + * @date 2023/4/17
  151 + */
  152 + public static function s2a($str)
  153 + {
  154 + if (is_array($str)) {
  155 + return $str;
  156 + }
  157 + return is_object($str) ? (array)$str : json_decode($str, true);
  158 + }
  159 +
  160 +
  161 + /**
  162 + * 数组转set形式字符串
  163 + * @param $arr
  164 + * @param string $format
  165 + * @return string
  166 + * @author zbj
  167 + * @date 2023/4/17
  168 + */
  169 + public static function arrToSet($arr, string $format = 'intval'): string
  170 + {
  171 + $arr = array_unique(array_filter(Arr::splitFilterToArray($arr, $format, ',')));
  172 + return $arr ? implode(',', $arr) : '';
  173 + }
  174 +
  175 + /**
  176 + * set形式字符串转数组
  177 + * @param $str
  178 + * @param string $format
  179 + * @return array
  180 + * @author zbj
  181 + * @date 2023/4/17
  182 + */
  183 + public static function setToArr($str, string $format = 'intval')
  184 + {
  185 + if (is_string($str)) {
  186 + return Arr::splitFilterToArray($str, $format, ',');
  187 + }
  188 + return $str ?: [];
  189 + }
  190 +
  191 +
  192 + /**
  193 + * 将数组设置成某个键的值
  194 + * @param $arr
  195 + * @param $key
  196 + * @return array
  197 + * @author zbj
  198 + * @date 2023/5/16
  199 + */
  200 + public static function setValueToKey($arr, $key)
  201 + {
  202 + $data = [];
  203 + if (!$arr) {
  204 + return $data;
  205 + }
  206 + foreach ($arr as $v) {
  207 + $data[$v[$key]] = $v;
  208 + }
  209 +
  210 + if ($arr instanceof Collection) {
  211 + $data = new Collection($data);
  212 + }
  213 + return $data;
  214 + }
128 } 215 }
  1 +<?php
  2 +
  3 +namespace App\Helper;
  4 +
  5 +use GuzzleHttp\Client;
  6 +
  7 +/**
  8 + * @name: ayr_share社交绑定
  9 + */
  10 +class AyrShare
  11 +{
  12 + public $path = 'https://app.ayrshare.com';
  13 + //api_key
  14 + public $api_key = 'G8GQW3X-XBTMGXW-QPDDZ9A-WE1Z5SB';
  15 + //系统设置
  16 + public $config = [
  17 + 'facebook'=>'#best https://www.facebook.com',
  18 + 'google'=>'#best https://www.google.com',
  19 + 'instagram'=>'#best https://www.instagram.com',
  20 + 'linkedin'=>'#best https://www.linkedin.com',
  21 + 'twitter'=>'#best https://www.twitter.com',
  22 + 'telegram'=>'#best https://www.telegram.com',
  23 + 'tiktok'=>'#bestvideo',
  24 + ];
  25 + //profile_key
  26 + public $profile_key = '';
  27 + //设置请求头
  28 + public $headers = [
  29 + 'Authorization' => 'Bearer ',
  30 + 'Content-Type' => 'application/json',
  31 + ];
  32 + //私钥
  33 + private $private_key = "-----BEGIN RSA PRIVATE KEY-----
  34 +MIICWgIBAAKBgGFatMeBeaw7QJrqmylMLZlwuuO0FA/EZg5/g7Rrqu+FgpwvFkJq
  35 +9twEZJY+aIdDH8/RVrCZQGR/xUxKw9v4ows+sLwi4g41m8KRKDXUcJwQvSlwsHAi
  36 +h9hPGZxDsRK0Nv4pZ7XqGgh0Wb0VypX/+Q1dhX9BnXQmvEKayk8GQWQxAgMBAAEC
  37 +gYAFqOJNnudV7fPpja4LjpQwEW+sATIRYJeWTC9587ByUE6xicM/hTxouhCm82Xc
  38 +Rzi4OjFR/vbRYOQ1dTtBtIi18fdRrseQNyR/N2NZjw1X8n5aZcw5NVaa3d3YTQNa
  39 +uzjnYF5eYSOD4pNKKIDc35VHdmvGCV/JXwQKMTgu1+4AAQJBAL5jjN3kvMKFF8vG
  40 +DyYR8k+wPG9iXAdR0HjVNB3OzxKVW0MTwM32pJBXCmF1MOziL8WC48VHQL48hVRa
  41 +52xRqAECQQCC53rrrOPhPCLIb6kBfgqnxCojqlUK9paFL7NYTPtLYcOajY6+NiKT
  42 +CG1gaOwZh4r34HF7I59l/Ds98Z4nQDwxAkAC4/oIiGeBQIoK8vfZ6R3XreJNAp5J
  43 +EinrG7mN1kz4iEH5c7xSpDL9agTjU+cpQYneIs2Yeit2d+7CSBsJXvgBAkBDFsfU
  44 +yYLxCJT7DN8dOK/VU6AVL1Luj3qNP+k2tB2GgNBzAWHK8ou9t2/3HU8DtofuikUe
  45 +yx8Cccca9B4OF8nBAkAgIUZKGmVNFcGnFFo55vSJInNXFo4HCJ2o4DunBORVtQ/j
  46 +zFePUMXy1bFghAfzNKlrc5XgH4ixeeMh3cDtU97K
  47 +-----END RSA PRIVATE KEY-----";
  48 +
  49 + /**
  50 + * @name :(创建子账户配置文件)post_create_profiles
  51 + * @author :lyh
  52 + * @method :post
  53 + * @time :2023/5/5 15:16
  54 + */
  55 + public function post_create_profiles($data){
  56 + $param = [
  57 + 'title'=>$data['title'],
  58 + ];
  59 + $url = $this->path.'/api/profiles/profile';
  60 + return $this->http_click('post',$url,$param);
  61 + }
  62 + /**
  63 + * @name :(删除子账户配置文件)deleted_profiles
  64 + * @author :lyh
  65 + * @method :post
  66 + * @time :2023/5/5 15:16
  67 + */
  68 + public function deleted_profiles($data){
  69 + $param = [
  70 +// 'title'=>$data['title'],
  71 + 'profileKey'=>$data['profileKey'],
  72 + ];
  73 + $url = $this->path.'/api/profiles/profile';
  74 + return $this->http_click('delete',$url,$param);
  75 + }
  76 +
  77 + /**
  78 + * @name :(跳转第三方生成jwt令牌)post_generate_jwt
  79 + * @author :lyh
  80 + * @method :post
  81 + * @time :2023/5/5 18:07 https://app.ayrshare.com/api/profiles/generateJWT
  82 + */
  83 + public function post_generate_jwt($data,$domain = 'globalso'){
  84 + $param = [
  85 + 'domain'=>$domain,
  86 + 'privateKey'=>$this->private_key,
  87 + 'profileKey'=>$data['profileKey'],
  88 + 'logout'=>true
  89 + ];
  90 + $url = $this->path.'/api/profiles/generateJWT';
  91 + return $this->http_click('post',$url,$param);
  92 + }
  93 +
  94 + /**
  95 + * @name :(获取指定api_key的配置文件)get_profiles_users
  96 + * @author :lyh
  97 + * @method :post
  98 + * @time :2023/5/6 16:44
  99 + */
  100 + public function get_profiles_users($api_key){
  101 + $this->headers['Authorization'] = $this->headers['Authorization'].$api_key;
  102 + $url = $this->path.'/api/user';
  103 + return $this->http_click('get',$url,[],$this->headers);
  104 + }
  105 +
  106 +
  107 + /**
  108 + * @name :(发帖)post_send_msg
  109 + * @author :lyh
  110 + * @method :post
  111 + * @time :2023/5/8 9:22
  112 + * @param :platforms: "facebook", "fbg", "twitter",
  113 + * "linkedin", "instagram","youtube", "reddit" ,"telegram""
  114 + */
  115 + public function post_send_msg($param,$api_key){
  116 + //平台参数处理
  117 + $param['idempotencyKey'] = uniqid().time();
  118 + $url = $this->path.'/api/post';
  119 + return $this->http_post_ayr($url,$param,$api_key);
  120 + }
  121 + public function http_post_ayr($url,$param,$api_key){
  122 + $curl = curl_init();
  123 + curl_setopt_array($curl, array(
  124 + CURLOPT_URL => $url,
  125 + CURLOPT_RETURNTRANSFER => true,
  126 + CURLOPT_ENCODING => '',
  127 + CURLOPT_MAXREDIRS => 10,
  128 + CURLOPT_TIMEOUT => 0,
  129 + CURLOPT_FOLLOWLOCATION => true,
  130 + CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  131 + CURLOPT_CUSTOMREQUEST => 'POST',
  132 + CURLOPT_POSTFIELDS => http_build_query($param),
  133 + CURLOPT_HTTPHEADER => array(
  134 + 'Authorization: Bearer '.$api_key,
  135 + 'Accept-Encoding: gzip'
  136 + ),
  137 + ));
  138 + $response = curl_exec($curl);
  139 + curl_close($curl);
  140 + return $response;
  141 + }
  142 + /**
  143 + * @name :(上传图片或视频到ayr_share)post_media_upload
  144 + * @author :lyh
  145 + * @method :post
  146 + * @time :2023/5/8 9:47
  147 + * https://app.ayrshare.com/api/media/upload
  148 + */
  149 + public function post_media_upload($data,$api_key){
  150 + $param = [
  151 + 'file'=>$data['file'],//base64编码
  152 + ];
  153 + $this->headers['Authorization'] = $this->headers['Authorization'].$api_key;
  154 + $url = $this->path.'/api/media/upload';
  155 + return $this->http_click('post',$url,$param,$this->headers);
  156 + }
  157 +
  158 + /**
  159 + * @name :获取过去30天发布的历史记录(1-30)
  160 + * @author :lyh
  161 + * @method :get
  162 + * @time :2023/5/5 10:00
  163 + */
  164 + public function get_analytics_links($to_day){
  165 + $last_days = (string)$to_day;
  166 + $url = $this->path.'/analytics/links?lastDays='.$last_days;
  167 + return $this->http_click('get',$url);
  168 + }
  169 +
  170 + /**
  171 + * @name :(通过 Ayrshare 获取给定帖子的实时分析,例如点赞、印象、转推等)post_analytics
  172 + * @author :lyh
  173 + * @method :post
  174 + * @time :2023/5/5 11:56
  175 + */
  176 + public function post_analytics($id){
  177 + $param = [
  178 + 'id'=>$id,
  179 + 'platforms' => ['facebook', 'instagram', 'twitter', 'linkedin', 'pinterest', 'youtube', 'tiktok'],
  180 + ];
  181 + $url = $this->path.'/api/analytics/post';
  182 + return $this->http_click('post', $url, $param);
  183 + }
  184 + /**
  185 + * @name :(获取特定用户个人资料)analytics_post
  186 + * @author :lyh
  187 + * @method :post
  188 + * @time :2023/5/5 10:43
  189 + */
  190 + public function post_analytics_social(){
  191 + $post_data = [
  192 + 'platforms' => ['facebook', 'instagram', 'twitter', 'linkedin', 'pinterest', 'youtube', 'tiktok'],
  193 + ];
  194 + $url = $this->path.'/api/analytics/social';
  195 + return $this->http_click('post',$url,$post_data);
  196 + }
  197 +
  198 + /**
  199 + * @name :(设置自动计划)post_schedule_set
  200 + * @author :lyh
  201 + * @method :post
  202 + * @time :2023/5/5 13:58
  203 + */
  204 + public function post_schedule_set($data){
  205 + $param = [
  206 + 'schedule'=>["13:05Z", "20:14Z"],
  207 + 'title'=>$data['title'],
  208 + ];
  209 + $url = $this->path.'/api/auto-schedule/set';
  210 + return $this->http_click('post',$url,$param);
  211 + }
  212 +
  213 + /**
  214 + * @name :(删除自动计划)delete_schedule
  215 + * @author :lyh
  216 + * @method :post
  217 + * @time :2023/5/5 14:04
  218 + */
  219 + public function delete_schedule($data){
  220 + $param = [
  221 + 'title'=>$data['title'],
  222 + ];
  223 + $url = $this->path.'/api/auto-schedule/delete';
  224 + return $this->http_click('delete',$url,$param);
  225 + }
  226 +
  227 + /**
  228 + * @name :(列出自动计划)get_schedule_list
  229 + * @author :lyh
  230 + * @method :post
  231 + * @time :2023/5/5 14:08
  232 + */
  233 + public function get_schedule_list(){
  234 + $url = $this->path.'/api/auto-schedule/list';
  235 + return $this->http_click('get',$url);
  236 + }
  237 +
  238 + /**
  239 + * @name :(发布到用户个人资料)post_user
  240 + * @author :lyh
  241 + * @method :post
  242 + * @time :2023/5/5 15:00
  243 + */
  244 + public function post_profiles($data){
  245 + $param = [
  246 + 'post'=>$data['post'],
  247 + 'platforms'=>$data['platforms'],
  248 + 'profileKey'=>$this->profile_key,
  249 + 'mediaUrls'=>$data['mediaUrls']
  250 + ];
  251 + $url = $this->path.'/api/post';
  252 + return $this->http_click('post',$url,$param);
  253 + }
  254 +
  255 + /**
  256 + * 发送http post,get,put,delete请求
  257 + * @param type $url
  258 + * @param type $post_data
  259 + */
  260 + function http_click($method = 'post',$url, $param = [],$header = [])
  261 + {
  262 + if(!empty($param)){
  263 + $post_data['json'] = $param;
  264 + }
  265 + if(empty($header)){
  266 + $this->headers['Authorization'] = $this->headers['Authorization'].$this->api_key;
  267 + }
  268 + $post_data['headers'] = !empty($header) ? $header : $this->headers;
  269 + $client = new Client();
  270 + try {
  271 + $res = $client->request(strtoupper($method), $url, $post_data)->getBody()->getContents();
  272 + return (array)json_decode($res);
  273 + } catch (\Exception $e) {
  274 + return ["status"=>"fail","message"=>$e->getMessage()];
  275 + }
  276 + }
  277 +}
  1 +<?php
  2 +
  3 +namespace App\Helper;
  4 +
  5 +use App\Models\Ai\AiCommand as AiCommandModel;
  6 +use App\Models\User\UserLog as UserLogModel;
  7 +use App\Models\User\UserLogin as UserLoginModel;
  8 +use Illuminate\Support\Facades\Cache;
  9 +
  10 +/**
  11 + * @name:
  12 + */
  13 +class Common
  14 +{
  15 + /**
  16 + * @name :生成用户操作日志
  17 + * @return void
  18 + * @author :liyuhang
  19 + * @method
  20 + */
  21 + public static function set_user_log($param = []){
  22 + $data = [
  23 + 'operator_id'=>$param['operator_id'],
  24 + 'model'=>$param['model'],
  25 + 'remark'=>$param['remark']
  26 + ];
  27 + $model = new UserLogModel();
  28 + return $model->add($data);
  29 + }
  30 +
  31 + /**
  32 + * @name :写入登录日志
  33 + * @return void
  34 + * @author :liyuhang
  35 + * @method
  36 + */
  37 + public static function set_user_login($param = []){
  38 + $data = [
  39 + 'user_id'=>$param['user_id'],
  40 + 'ip'=>$param['ip']
  41 + ];
  42 + $model = new UserLoginModel();
  43 + return $model->add($data);
  44 + }
  45 +
  46 + /**
  47 + * @name :ai自动生成
  48 + * @return mixed
  49 + * @author :liyuhang
  50 + * @method
  51 + */
  52 + public static function send_openai_msg($url,$param){
  53 + $url = HTTP_OPENAI_URL.$url;
  54 + $aiCommandModel = New AiCommandModel();
  55 + //指定库获取指令
  56 + $info = $aiCommandModel->read(['key'=>$param['key']]);
  57 + if($info === false){
  58 + response('指令不存在',400);
  59 + }
  60 + //替换关键字
  61 + $content = str_replace('$keyword$', $param['keywords'], $info['ai']);
  62 + $data = [
  63 + 'messages'=>[
  64 + ['role'=>'system','content'=>$info['scene']],
  65 + ['role'=>'assistant','content'=>$content],
  66 + ]
  67 + ];
  68 + return http_post($url,json_encode($data));
  69 + }
  70 +
  71 + /**
  72 + * @name :获取缓存
  73 + * @return void
  74 + * @author :liyuhang
  75 + * @method
  76 + */
  77 + public static function get_user_cache($table,$id,$type = 'B'){
  78 + $data = [];
  79 + $cache = config('cache.user_is_cache');
  80 + if(isset($cache) && ($cache['is_cache'] == true)){
  81 + $key = 'cache_'.$table.'_'.$id.'_type';
  82 + $data = Cache::store('file')->get($key);
  83 + }
  84 + return $data;
  85 + }
  86 +
  87 + /**
  88 + * @name :写入缓存
  89 + * @return bool
  90 + * @author :liyuhang
  91 + * @method
  92 + */
  93 + public static function set_user_cache($data = [],$table,$id,$type = 'B'){
  94 + $cache = config('cache.user_is_cache');
  95 + if(isset($cache) && ($cache['is_cache'] == true)){
  96 + $key = 'cache_'.$table.'_'.$id.'_type';
  97 + Cache::store('file')->set($key,$data,3600);
  98 + }
  99 + return true;
  100 + }
  101 +
  102 + /**
  103 + * @name :清除缓存
  104 + * @return bool
  105 + * @author :liyuhang
  106 + * @method
  107 + */
  108 + public static function del_user_cache($table,$id,$type = 'B'){
  109 + $cache = config('cache.user_is_cache');
  110 + if(isset($cache) && ($cache['is_cache'] == true)){
  111 + if(is_array($id)){
  112 + foreach ($id as $v){
  113 + $key = 'cache_'.$table.'_'.$v.'_type';
  114 + Cache::store('file')->pull($key);
  115 + }
  116 + }else{
  117 + $key = 'cache_'.$table.'_'.$id.'_type';
  118 + }
  119 + Cache::store('file')->pull($key);
  120 + }
  121 + return true;
  122 + }
  123 +
  124 + /**
  125 + * @name :(多维数组去重)array_deduplication
  126 + * @author :lyh
  127 + * @method :post
  128 + * @time :2023/5/9 10:47
  129 + */
  130 + public static function uniqueMultiArray($arr) {
  131 + $arr = array_map('serialize', $arr);
  132 + $arr = array_unique($arr);
  133 + $arr = array_map('unserialize', $arr);
  134 + return $arr;
  135 + }
  136 +
  137 + /**
  138 + * @param $targetDateTime
  139 + * @name :(获取时间差,精确时分秒,返回天数)getDaysToTargetDate
  140 + * @author :lyh
  141 + * @method :post
  142 + * @time :2023/5/24 9:38
  143 + */
  144 + public static function getDaysToTargetDate($targetDateTime)
  145 + {
  146 + $currentTimestamp = time();
  147 + $targetTimestamp = strtotime($targetDateTime);
  148 + $days = floor(($currentTimestamp - $targetTimestamp) / (60 * 60 * 24));
  149 + return (int)$days;
  150 + }
  151 +}
  1 +<?php
  2 +
  3 +namespace App\Helper;
  4 +
  5 +use App\Models\WebSetting\WebSettingCountry;
  6 +
  7 +/**
  8 + * @name:多语言国家设置
  9 + */
  10 +class Country
  11 +{
  12 + public $tls_list = [
  13 + 'en' => [
  14 + 'text' => '英语',
  15 + 'lang_text' => 'English',
  16 + 'con_flag' => 'con_flag/en.jfif',
  17 + 'shop_lang' => 'en-gb',
  18 + ],
  19 + 'zh' => [
  20 + 'text' => '中文',
  21 + 'lang_text' => '简体中文',
  22 + 'con_flag' => 'con_flag/zh.jfif',
  23 + 'shop_lang' => 'zh-cn',
  24 + ],
  25 + 'fr' => [
  26 + 'text' => '法语',
  27 + 'lang_text' => 'En français',
  28 + 'con_flag' => '',
  29 +
  30 + ],
  31 + 'de' => [
  32 + 'text' => '德语',
  33 + 'lang_text' => 'Das ist Deutsch.',
  34 + 'con_flag' => '',
  35 +
  36 + ],
  37 + 'ko' => [
  38 + 'text' => '韩语',
  39 + 'lang_text' => '',
  40 + 'con_flag' => '',
  41 +
  42 + ],
  43 + 'ja' => [
  44 + 'text' => '日语',
  45 + 'lang_text' => '',
  46 + 'con_flag' => '',
  47 +
  48 + ],
  49 + 'es' => [
  50 + 'text' => '西班牙语',
  51 + 'lang_text' => 'Español.',
  52 + 'con_flag' => '',
  53 +
  54 + ],
  55 + 'ar' => [
  56 + 'text' => '阿拉伯语',
  57 + 'lang_text' => '',
  58 + 'con_flag' => '',
  59 +
  60 + ],
  61 + 'pt' => [
  62 + 'text' => '葡萄牙语(葡萄牙、巴西)',
  63 + 'lang_text' => 'Língua portuguesa',
  64 + 'con_flag' => '',
  65 +
  66 + ],
  67 + 'ru' => [
  68 + 'text' => '俄语',
  69 + 'lang_text' => '',
  70 + 'con_flag' => '',
  71 +
  72 + ],
  73 + 'af' => [
  74 + 'text' => '南非荷兰语',
  75 + 'lang_text' => '',
  76 + 'con_flag' => '',
  77 +
  78 + ],
  79 + 'sq' => [
  80 + 'text' => '阿尔巴尼亚语',
  81 + 'lang_text' => '',
  82 + 'con_flag' => '',
  83 +
  84 + ],
  85 + 'am' => [
  86 + 'text' => '阿姆哈拉语',
  87 + 'lang_text' => '',
  88 + 'con_flag' => '',
  89 +
  90 + ],
  91 + 'hy' => [
  92 + 'text' => '亚美尼亚语',
  93 + 'lang_text' => '',
  94 + 'con_flag' => '',
  95 +
  96 + ],
  97 + 'az' => [
  98 + 'text' => '阿塞拜疆语',
  99 + 'lang_text' => '',
  100 + 'con_flag' => '',
  101 +
  102 + ],
  103 + 'eu' => [
  104 + 'text' => '巴斯克语',
  105 + 'lang_text' => '',
  106 + 'con_flag' => '',
  107 +
  108 + ],
  109 + 'be' => [
  110 + 'text' => '白俄罗斯语',
  111 + 'lang_text' => '',
  112 + 'con_flag' => '',
  113 +
  114 + ],
  115 + 'bn' => [
  116 + 'text' => '孟加拉语',
  117 + 'lang_text' => '',
  118 + 'con_flag' => '',
  119 +
  120 + ],
  121 + 'bs' => [
  122 + 'text' => '波斯尼亚语',
  123 + 'lang_text' => '',
  124 + 'con_flag' => '',
  125 +
  126 + ],
  127 + 'bg' => [
  128 + 'text' => '保加利亚语',
  129 + 'lang_text' => '',
  130 + 'con_flag' => '',
  131 +
  132 + ],
  133 + 'ca' => [
  134 + 'text' => '加泰罗尼亚语',
  135 + 'lang_text' => '',
  136 + 'con_flag' => '',
  137 +
  138 + ],
  139 + 'ceb' => [
  140 + 'text' => '宿务语',
  141 + 'lang_text' => '',
  142 + 'con_flag' => '',
  143 +
  144 + ],
  145 + 'cn' => [
  146 + 'text' => '中文(简体)',
  147 + 'lang_text' => '简体中文',
  148 + 'con_flag' => 'con_flag/zh.jfif',
  149 + 'shop_lang' => 'zh-cn',
  150 + ],
  151 + 'tw' => [
  152 + 'text' => '中文(繁体)',
  153 + 'lang_text' => '繁体中文',
  154 + 'con_flag' => 'con_flag/zh.jfif',
  155 +
  156 + ],
  157 + 'co' => [
  158 + 'text' => '科西嘉语',
  159 + 'lang_text' => '',
  160 + 'con_flag' => '',
  161 +
  162 + ],
  163 + 'hr' => [
  164 + 'text' => '克罗地亚语',
  165 + 'lang_text' => '',
  166 + 'con_flag' => '',
  167 +
  168 + ],
  169 + 'cs' => [
  170 + 'text' => '捷克语',
  171 + 'lang_text' => '',
  172 + 'con_flag' => '',
  173 +
  174 + ],
  175 + 'da' => [
  176 + 'text' => '丹麦语',
  177 + 'lang_text' => '',
  178 + 'con_flag' => '',
  179 +
  180 + ],
  181 + 'nl' => [
  182 + 'text' => '荷兰语',
  183 + 'lang_text' => '',
  184 + 'con_flag' => '',
  185 +
  186 + ],
  187 + 'eo' => [
  188 + 'text' => '世界语',
  189 + 'lang_text' => '',
  190 + 'con_flag' => '',
  191 +
  192 + ],
  193 + 'et' => [
  194 + 'text' => '爱沙尼亚语',
  195 + 'lang_text' => '',
  196 + 'con_flag' => '',
  197 +
  198 + ],
  199 + 'fi' => [
  200 + 'text' => '芬兰语',
  201 + 'lang_text' => '',
  202 + 'con_flag' => '',
  203 +
  204 + ],
  205 + 'fy' => [
  206 + 'text' => '弗里斯兰语',
  207 + 'lang_text' => '',
  208 + 'con_flag' => '',
  209 +
  210 + ],
  211 + 'gl' => [
  212 + 'text' => '加利西亚语',
  213 + 'lang_text' => '',
  214 + 'con_flag' => '',
  215 +
  216 + ],
  217 + 'ka' => [
  218 + 'text' => '格鲁吉亚语',
  219 + 'lang_text' => '',
  220 + 'con_flag' => '',
  221 +
  222 + ],
  223 + 'el' => [
  224 + 'text' => '希腊语',
  225 + 'lang_text' => '',
  226 + 'con_flag' => '',
  227 +
  228 + ],
  229 + 'gu' => [
  230 + 'text' => '古吉拉特语',
  231 + 'lang_text' => '',
  232 + 'con_flag' => '',
  233 +
  234 + ],
  235 + 'ht' => [
  236 + 'text' => '海地克里奥尔语',
  237 + 'lang_text' => '',
  238 + 'con_flag' => '',
  239 +
  240 + ],
  241 + 'ha' => [
  242 + 'text' => '豪萨语',
  243 + 'lang_text' => '',
  244 + 'con_flag' => '',
  245 +
  246 + ],
  247 + 'haw' => [
  248 + 'text' => '夏威夷语',
  249 + 'lang_text' => '',
  250 + 'con_flag' => '',
  251 +
  252 + ],
  253 + 'iw' => [
  254 + 'text' => '希伯来语',
  255 + 'lang_text' => '',
  256 + 'con_flag' => '',
  257 +
  258 + ],
  259 + 'hi' => [
  260 + 'text' => '印地语',
  261 + 'lang_text' => '',
  262 + 'con_flag' => '',
  263 +
  264 + ],
  265 + 'hmn' => [
  266 + 'text' => '苗语',
  267 + 'lang_text' => '',
  268 + 'con_flag' => '',
  269 +
  270 + ],
  271 + 'hu' => [
  272 + 'text' => '匈牙利语',
  273 + 'lang_text' => '',
  274 + 'con_flag' => '',
  275 +
  276 + ],
  277 + 'is' => [
  278 + 'text' => '冰岛语',
  279 + 'lang_text' => '',
  280 + 'con_flag' => '',
  281 +
  282 + ],
  283 + 'ig' => [
  284 + 'text' => '伊博语',
  285 + 'lang_text' => '',
  286 + 'con_flag' => '',
  287 +
  288 + ],
  289 + 'id' => [
  290 + 'text' => '印度尼西亚语',
  291 + 'lang_text' => 'Bahasa Indonesia',
  292 + 'con_flag' => 'con_flag/id.jfif',
  293 + 'shop_lang' => 'id',
  294 + ],
  295 + 'ga' => [
  296 + 'text' => '爱尔兰语',
  297 + 'lang_text' => '',
  298 + 'con_flag' => '',
  299 +
  300 + ],
  301 + 'it' => [
  302 + 'text' => '意大利语',
  303 + 'lang_text' => 'Lingua italiana',
  304 + 'con_flag' => '',
  305 +
  306 + ],
  307 + 'jw' => [
  308 + 'text' => '爪哇语',
  309 + 'lang_text' => '',
  310 + 'con_flag' => '',
  311 +
  312 + ],
  313 + 'kn' => [
  314 + 'text' => '卡纳达语',
  315 + 'lang_text' => '',
  316 + 'con_flag' => '',
  317 +
  318 + ],
  319 + 'kk' => [
  320 + 'text' => '哈萨克语',
  321 + 'lang_text' => '',
  322 + 'con_flag' => '',
  323 +
  324 + ],
  325 + 'km' => [
  326 + 'text' => '高棉语',
  327 + 'lang_text' => '',
  328 + 'con_flag' => '',
  329 +
  330 + ],
  331 + 'rw' => [
  332 + 'text' => '卢旺达语',
  333 + 'lang_text' => '',
  334 + 'con_flag' => '',
  335 +
  336 + ],
  337 + 'ku' => [
  338 + 'text' => '库尔德语',
  339 + 'lang_text' => '',
  340 + 'con_flag' => '',
  341 +
  342 + ],
  343 + 'ky' => [
  344 + 'text' => '吉尔吉斯语',
  345 + 'lang_text' => '',
  346 + 'con_flag' => '',
  347 +
  348 + ],
  349 + 'lo' => [
  350 + 'text' => '老挝文',
  351 + 'lang_text' => '',
  352 + 'con_flag' => '',
  353 +
  354 + ],
  355 + 'la' => [
  356 + 'text' => '拉丁文',
  357 + 'lang_text' => '',
  358 + 'con_flag' => '',
  359 +
  360 + ],
  361 + 'lv' => [
  362 + 'text' => '拉脱维亚语',
  363 + 'lang_text' => '',
  364 + 'con_flag' => '',
  365 +
  366 + ],
  367 + 'lt' => [
  368 + 'text' => '立陶宛语',
  369 + 'lang_text' => '',
  370 + 'con_flag' => '',
  371 +
  372 + ],
  373 + 'lb' => [
  374 + 'text' => '卢森堡语',
  375 + 'lang_text' => '',
  376 + 'con_flag' => '',
  377 +
  378 + ],
  379 + 'mk' => [
  380 + 'text' => '马其顿语',
  381 + 'lang_text' => '',
  382 + 'con_flag' => '',
  383 +
  384 + ],
  385 + 'mg' => [
  386 + 'text' => '马尔加什语',
  387 + 'lang_text' => '',
  388 + 'con_flag' => '',
  389 +
  390 + ],
  391 + 'ms' => [
  392 + 'text' => '马来语',
  393 + 'lang_text' => 'Bahasa Melayu',
  394 + 'con_flag' => 'con_flag/ms.jfif',
  395 + 'shop_lang' => 'ms-my',
  396 + ],
  397 + 'ml' => [
  398 + 'text' => '马拉雅拉姆文',
  399 + 'lang_text' => '',
  400 + 'con_flag' => '',
  401 +
  402 + ],
  403 + 'mt' => [
  404 + 'text' => '马耳他语',
  405 + 'lang_text' => '',
  406 + 'con_flag' => '',
  407 +
  408 + ],
  409 + 'mi' => [
  410 + 'text' => '毛利语',
  411 + 'lang_text' => '',
  412 + 'con_flag' => '',
  413 +
  414 + ],
  415 + 'mr' => [
  416 + 'text' => '马拉地语',
  417 + 'lang_text' => '',
  418 + 'con_flag' => '',
  419 +
  420 + ],
  421 + 'mn' => [
  422 + 'text' => '蒙古文',
  423 + 'lang_text' => '',
  424 + 'con_flag' => '',
  425 +
  426 + ],
  427 + 'my' => [
  428 + 'text' => '缅甸语',
  429 + 'lang_text' => '',
  430 + 'con_flag' => '',
  431 +
  432 + ],
  433 + 'ne' => [
  434 + 'text' => '尼泊尔语',
  435 + 'lang_text' => '',
  436 + 'con_flag' => '',
  437 +
  438 + ],
  439 + 'no' => [
  440 + 'text' => '挪威语',
  441 + 'lang_text' => '',
  442 + 'con_flag' => '',
  443 +
  444 + ],
  445 + 'ny' => [
  446 + 'text' => '尼杨扎语(齐切瓦语)',
  447 + 'lang_text' => '',
  448 + 'con_flag' => '',
  449 +
  450 + ],
  451 + 'or' => [
  452 + 'text' => '奥里亚语(奥里亚)',
  453 + 'lang_text' => '',
  454 + 'con_flag' => '',
  455 +
  456 + ],
  457 + 'ps' => [
  458 + 'text' => '普什图语',
  459 + 'lang_text' => '',
  460 + 'con_flag' => '',
  461 +
  462 + ],
  463 + 'fa' => [
  464 + 'text' => '波斯语',
  465 + 'lang_text' => '',
  466 + 'con_flag' => '',
  467 +
  468 + ],
  469 + 'pl' => [
  470 + 'text' => '波兰语',
  471 + 'lang_text' => '',
  472 + 'con_flag' => '',
  473 +
  474 + ],
  475 + 'pa' => [
  476 + 'text' => '旁遮普语',
  477 + 'lang_text' => '',
  478 + 'con_flag' => '',
  479 +
  480 + ],
  481 + 'ro' => [
  482 + 'text' => '罗马尼亚语',
  483 + 'lang_text' => '',
  484 + 'con_flag' => '',
  485 +
  486 + ],
  487 + 'sm' => [
  488 + 'text' => '萨摩亚语',
  489 + 'lang_text' => '',
  490 + 'con_flag' => '',
  491 +
  492 + ],
  493 + 'gd' => [
  494 + 'text' => '苏格兰盖尔语',
  495 + 'lang_text' => '',
  496 + 'con_flag' => '',
  497 +
  498 + ],
  499 + 'sr' => [
  500 + 'text' => '塞尔维亚语',
  501 + 'lang_text' => '',
  502 + 'con_flag' => '',
  503 +
  504 + ],
  505 + 'st' => [
  506 + 'text' => '塞索托语',
  507 + 'lang_text' => '',
  508 + 'con_flag' => '',
  509 +
  510 + ],
  511 + 'sn' => [
  512 + 'text' => '修纳语',
  513 + 'lang_text' => '',
  514 + 'con_flag' => '',
  515 +
  516 + ],
  517 + 'sd' => [
  518 + 'text' => '信德语',
  519 + 'lang_text' => '',
  520 + 'con_flag' => '',
  521 +
  522 + ],
  523 + 'si' => [
  524 + 'text' => '僧伽罗语',
  525 + 'lang_text' => '',
  526 + 'con_flag' => '',
  527 +
  528 + ],
  529 + 'sk' => [
  530 + 'text' => '斯洛伐克语',
  531 + 'lang_text' => '',
  532 + 'con_flag' => '',
  533 +
  534 + ],
  535 + 'sl' => [
  536 + 'text' => '斯洛文尼亚语',
  537 + 'lang_text' => '',
  538 + 'con_flag' => '',
  539 +
  540 + ],
  541 + 'so' => [
  542 + 'text' => '索马里语',
  543 + 'lang_text' => '',
  544 + 'con_flag' => '',
  545 +
  546 + ],
  547 + 'su' => [
  548 + 'text' => '巽他语',
  549 + 'lang_text' => '',
  550 + 'con_flag' => '',
  551 +
  552 + ],
  553 + 'sw' => [
  554 + 'text' => '斯瓦希里语',
  555 + 'lang_text' => '',
  556 + 'con_flag' => '',
  557 +
  558 + ],
  559 + 'sv' => [
  560 + 'text' => '瑞典语',
  561 + 'lang_text' => '',
  562 + 'con_flag' => '',
  563 +
  564 + ],
  565 + 'tl' => [
  566 + 'text' => '塔加路语(菲律宾语)',
  567 + 'lang_text' => 'Pilipino',
  568 + 'con_flag' => 'con_flag/tl.jfif',
  569 + 'shop_lang' => 'tl',
  570 + ],
  571 + 'tg' => [
  572 + 'text' => '塔吉克语',
  573 + 'lang_text' => '',
  574 + 'con_flag' => '',
  575 +
  576 + ],
  577 + 'ta' => [
  578 + 'text' => '泰米尔语',
  579 + 'lang_text' => '',
  580 + 'con_flag' => '',
  581 +
  582 + ],
  583 + 'tt' => [
  584 + 'text' => '鞑靼语',
  585 + 'lang_text' => '',
  586 + 'con_flag' => '',
  587 +
  588 + ],
  589 + 'te' => [
  590 + 'text' => '泰卢固语',
  591 + 'lang_text' => '',
  592 + 'con_flag' => '',
  593 +
  594 + ],
  595 + 'th' => [
  596 + 'text' => '泰文',
  597 + 'lang_text' => 'ไทย',
  598 + 'con_flag' => 'con_flag/th.jfif',
  599 + 'shop_lang' => 'th',
  600 + ],
  601 + 'tr' => [
  602 + 'text' => '土耳其语',
  603 + 'lang_text' => '',
  604 + 'con_flag' => '',
  605 +
  606 + ],
  607 + 'tk' => [
  608 + 'text' => '土库曼语',
  609 + 'lang_text' => '',
  610 + 'con_flag' => '',
  611 +
  612 + ],
  613 + 'uk' => [
  614 + 'text' => '乌克兰语',
  615 + 'lang_text' => '',
  616 + 'con_flag' => '',
  617 +
  618 + ],
  619 + 'ur' => [
  620 + 'text' => '乌尔都语',
  621 + 'lang_text' => '',
  622 + 'con_flag' => '',
  623 +
  624 + ],
  625 + 'ug' => [
  626 + 'text' => '维吾尔语',
  627 + 'lang_text' => '',
  628 + 'con_flag' => '',
  629 +
  630 + ],
  631 + 'uz' => [
  632 + 'text' => '乌兹别克语',
  633 + 'lang_text' => '',
  634 + 'con_flag' => '',
  635 +
  636 + ],
  637 + 'vi' => [
  638 + 'text' => '越南语',
  639 + 'lang_text' => '',
  640 + 'con_flag' => '',
  641 +
  642 + ],
  643 + 'cy' => [
  644 + 'text' => '威尔士语',
  645 + 'lang_text' => '',
  646 + 'con_flag' => '',
  647 +
  648 + ],
  649 + 'xh' => [
  650 + 'text' => '班图语',
  651 + 'lang_text' => '',
  652 + 'con_flag' => '',
  653 +
  654 + ],
  655 + 'yi' => [
  656 + 'text' => '意第绪语',
  657 + 'lang_text' => '',
  658 + 'con_flag' => '',
  659 +
  660 + ],
  661 + 'yo' => [
  662 + 'text' => '约鲁巴语',
  663 + 'lang_text' => '',
  664 + 'con_flag' => '',
  665 +
  666 + ],
  667 + 'zu' => [
  668 + 'text' => '祖鲁语',
  669 + 'lang_text' => '',
  670 + 'con_flag' => '',
  671 + ],
  672 + ];
  673 +
  674 + /**
  675 + * @name :(获取翻译国家)set_country
  676 + * @author :lyh
  677 + * @method :post
  678 + * @time :2023/5/4 17:57
  679 + */
  680 + public function set_country(){
  681 + $data = [];
  682 + foreach ($this->tls_list as $k=>$v){
  683 + $data[] = ['name'=>$v['text'],'alias'=>$k,'image'=>$k.'.png','con_flag'=>$v['con_flag'],'lang_text'=>$v['lang_text']];
  684 + }
  685 + $webCountry = new WebSettingCountry();
  686 + $webCountry->insert($data);
  687 + return true;
  688 + }
  689 +}
  1 +<?php
  2 +
  3 +
  4 +namespace App\Helper;
  5 +
  6 +/**
  7 + * 计算文件hash
  8 + *
  9 + * 七牛云的计算规则
  10 + */
  11 +class FileEtag
  12 +{
  13 + const BLOCK_SIZE = 4194304; //4*1024*1024 分块上传块大小,该参数为接口规格,不能修改
  14 +
  15 + private static function packArray($v, $a)
  16 + {
  17 + return call_user_func_array('pack', array_merge(array($v), (array)$a));
  18 + }
  19 +
  20 + private static function blockCount($fsize)
  21 + {
  22 + return intval(($fsize + (self::BLOCK_SIZE - 1)) / self::BLOCK_SIZE);
  23 + }
  24 +
  25 + private static function calcSha1($data)
  26 + {
  27 + $sha1Str = sha1($data, true);
  28 + $err = error_get_last();
  29 + if ($err !== null) {
  30 + return array(null, $err);
  31 + }
  32 + $byteArray = unpack('C*', $sha1Str);
  33 + return array($byteArray, null);
  34 + }
  35 +
  36 + private static function base64_urlSafeEncode($data)
  37 + {
  38 + $find = array('+', '/');
  39 + $replace = array('-', '_');
  40 + return str_replace($find, $replace, base64_encode($data));
  41 + }
  42 +
  43 + public static function sum($filename)
  44 + {
  45 + $fhandler = fopen($filename, 'r');
  46 + $err = error_get_last();
  47 + if ($err !== null) {
  48 + return array(null, $err);
  49 + }
  50 +
  51 + $fstat = fstat($fhandler);
  52 + $fsize = $fstat['size'];
  53 + if ((int)$fsize === 0) {
  54 + fclose($fhandler);
  55 + return array('Fto5o-5ea0sNMlW_75VgGJCv2AcJ', null);
  56 + }
  57 + $blockCnt = self::blockCount($fsize);
  58 + $sha1Buf = array();
  59 +
  60 + if ($blockCnt <= 1) {
  61 + array_push($sha1Buf, 0x16);
  62 + $fdata = fread($fhandler, self::BLOCK_SIZE);
  63 + if ($err !== null) {
  64 + fclose($fhandler);
  65 + return array(null, $err);
  66 + }
  67 + list($sha1Code,) = self::calcSha1($fdata);
  68 + $sha1Buf = array_merge($sha1Buf, $sha1Code);
  69 + } else {
  70 + array_push($sha1Buf, 0x96);
  71 + $sha1BlockBuf = array();
  72 + for ($i = 0; $i < $blockCnt; $i++) {
  73 + $fdata = fread($fhandler, self::BLOCK_SIZE);
  74 + list($sha1Code, $err) = self::calcSha1($fdata);
  75 + if ($err !== null) {
  76 + fclose($fhandler);
  77 + return array(null, $err);
  78 + }
  79 + $sha1BlockBuf = array_merge($sha1BlockBuf, $sha1Code);
  80 + }
  81 + $tmpData = self::packArray('C*', $sha1BlockBuf);
  82 + list($sha1Final,) = self::calcSha1($tmpData);
  83 + $sha1Buf = array_merge($sha1Buf, $sha1Final);
  84 + }
  85 + $etag = self::base64_urlSafeEncode(self::packArray('C*', $sha1Buf));
  86 + return array($etag, null);
  87 + }
  88 +}
  1 +<?php
  2 +
  3 +
  4 +namespace App\Helper;
  5 +
  6 +use App\Utils\HttpUtils;
  7 +use GuzzleHttp\Exception\GuzzleException;
  8 +
  9 +
  10 +/**
  11 + * Class FormGlobalsoApi
  12 + * @package App\Helper
  13 + * @author zbj
  14 + * @date 2023/5/17
  15 + */
  16 +class FormGlobalsoApi
  17 +{
  18 + //接口地址
  19 + protected $url = 'https://form.globalso.com';
  20 +
  21 + /**
  22 + * 设置询盘通知
  23 + * @author zbj
  24 + * @date 2023/5/17
  25 + */
  26 + public function setInquiry($domain, $emails, $phones)
  27 + {
  28 + $api_url = $this->url . '/api/external-project/save/dc77a54480b184c4';
  29 +
  30 + $params = [
  31 + 'token' => md5($domain.$emails.$phones.date("Y-m-d")),
  32 + 'domain' => $domain,
  33 + 'email' => $emails,
  34 + 'phone' => $phones,
  35 + ];
  36 +
  37 + try {
  38 + $res = HttpUtils::get($api_url, $params);
  39 + $res = Arr::s2a($res);
  40 + } catch (\Exception | GuzzleException $e) {
  41 + errorLog('设置询盘通知', $params, $e);
  42 + return false;
  43 + }
  44 + return $res;
  45 + }
  46 +
  47 + /**
  48 + * 询盘列表
  49 + * @author zbj
  50 + * @date 2023/5/17
  51 + */
  52 + public function getInquiryList($domain, $search = '', $page = 1, $page_size = 20)
  53 + {
  54 + $api_url = $this->url . '/api/external-interface/6a1bd159b1fd60af';
  55 +
  56 + $params = [
  57 + 'token' => md5($domain.$search.date("Y-m-d")),
  58 + 'domain' => $domain,
  59 + 'limit' => $page_size,
  60 + 'page' => $page,
  61 + 'source' => '1,3' //来源类型 新项目用1,3
  62 + ];
  63 + if($search){
  64 + $params['name'] = $search;
  65 + }
  66 + try {
  67 + $res = HttpUtils::get($api_url, $params);
  68 + $res = Arr::s2a($res);
  69 + } catch (\Exception | GuzzleException $e) {
  70 + errorLog('询盘列表', $params, $e);
  71 + return false;
  72 + }
  73 + return $res;
  74 + }
  75 +
  76 + /**
  77 + * 设置询盘信息已读
  78 + * @author zbj
  79 + * @date 2023/5/17
  80 + */
  81 + public function saveInquiryRead($domain, $id)
  82 + {
  83 + $api_url = $this->url . '/api/external-interface/save/d1483a8e57cb485a';
  84 +
  85 + $params = [
  86 + 'token' => md5($domain.$id.date("Y-m-d")),
  87 + 'domain' => $domain,
  88 + 'id' => $id,
  89 + ];
  90 +
  91 + try {
  92 + $res = HttpUtils::get($api_url, $params);
  93 + $res = Arr::s2a($res);
  94 + } catch (\Exception | GuzzleException $e) {
  95 + errorLog('设置询盘信息已读', $params, $e);
  96 + return false;
  97 + }
  98 + return $res;
  99 + }
  100 +
  101 + /**
  102 + * 删除询盘信息
  103 + * @author zbj
  104 + * @date 2023/5/17
  105 + */
  106 + public function delInquiry($domain, $ids)
  107 + {
  108 + $api_url = $this->url . '/api/external-interface/del/c4b11cf6f1508489';
  109 + $ids = Arr::arrToSet($ids);
  110 + $params = [
  111 + 'token' => md5($domain.$ids.date("Y-m-d")),
  112 + 'domain' => $domain,
  113 + 'id' => $ids,
  114 + ];
  115 + try {
  116 + $res = HttpUtils::get($api_url, $params);
  117 + $res = Arr::s2a($res);
  118 + } catch (\Exception | GuzzleException $e) {
  119 + errorLog('删除询盘信息', $params, $e);
  120 + return false;
  121 + }
  122 + return $res;
  123 + }
  124 +}
  1 +<?php
  2 +
  3 +
  4 +namespace App\Helper;
  5 +
  6 +use App\Utils\HttpUtils;
  7 +use GuzzleHttp\Exception\GuzzleException;
  8 +
  9 +
  10 +/**
  11 + * Class PageSpeed
  12 + * @package App\Helper
  13 + * @author zbj
  14 + * @date 2023/5/10
  15 + */
  16 +class GoogleSpeedApi
  17 +{
  18 +
  19 + protected $areas = [
  20 + [
  21 + "area" => "洛杉矶",
  22 + "numericValue" => 0,
  23 + ],
  24 + [
  25 + "area" => "圣地亚哥",
  26 + "numericValue" => 0,
  27 + ],
  28 + [
  29 + "area" => "伦敦",
  30 + "numericValue" => 0,
  31 + ],
  32 + [
  33 + "area" => "西雅图",
  34 + "numericValue" => 0,
  35 + ],
  36 + [
  37 + "area" => "吉隆坡",
  38 + "numericValue" => 0,
  39 + ],
  40 + [
  41 + "area" => "雅加达",
  42 + "numericValue" => 0,
  43 + ],
  44 + [
  45 + "area" => "孟买",
  46 + "numericValue" => 0,
  47 + ],
  48 + [
  49 + "area" => "迪拜",
  50 + "numericValue" => 0,
  51 + ],
  52 + [
  53 + "area" => "法兰克福",
  54 + "numericValue" => 0,
  55 + ],
  56 + [
  57 + "area" => "新加坡",
  58 + "numericValue" => 0,
  59 + ],
  60 + [
  61 + "area" => "悉尼",
  62 + "numericValue" => 0,
  63 + ],
  64 + [
  65 + "area" => "东京",
  66 + "numericValue" => 0,
  67 + ],
  68 + [
  69 + "area" => "硅谷",
  70 + "numericValue" => 0,
  71 + ],
  72 + [
  73 + "area" => "弗吉尼亚",
  74 + "numericValue" => 0,
  75 + ],
  76 + [
  77 + "area" => "香港",
  78 + "numericValue" => 0,
  79 + ],
  80 + [
  81 + "area" => "圣保罗",
  82 + "numericValue" => 0,
  83 + ],
  84 + [
  85 + "area" => "雅典",
  86 + "numericValue" => 0,
  87 + ],
  88 + [
  89 + "area" => "巴黎",
  90 + "numericValue" => 0,
  91 + ],
  92 + [
  93 + "area" => "罗马",
  94 + "numericValue" => 0,
  95 + ],
  96 + [
  97 + "area" => "马德里",
  98 + "numericValue" => 0,
  99 + ],
  100 + ];
  101 +
  102 + /**
  103 + * @param $url
  104 + * @return array|false
  105 + * @author zbj
  106 + * @date 2023/5/10
  107 + */
  108 + function run($url)
  109 + {
  110 + try {
  111 + $params = [
  112 + 'url' => $url
  113 + ];
  114 + $res = HttpUtils::get('http://45.136.131.72/api.php', $params);
  115 + if ($res) {
  116 + $res = Arr::s2a($res);
  117 + $area_data = Arr::s2a($res['area_data']);
  118 + }
  119 + $numericValue = $area_data[0]['numericValue'] ?? rand(500, 1000);
  120 + foreach ($this->areas as &$area) {
  121 + $start = -$numericValue * 0.5;
  122 + $end = $numericValue * 0.5;
  123 + $numer = rand($start, $end);
  124 + $area["numericValue"] = ceil($numericValue - $numer);
  125 + }
  126 +
  127 + return [
  128 + "url" => $url,
  129 + "area_data" => $this->areas,
  130 + "created_at" => date("Y-m-d H:i:s")
  131 + ];
  132 +
  133 + } catch (\Exception | GuzzleException $e) {
  134 + errorLog('测速失败', $params, $e);
  135 + return false;
  136 + }
  137 + }
  138 +}
  1 +<?php
  2 +
  3 +
  4 +namespace App\Helper;
  5 +
  6 +use App\Utils\HttpUtils;
  7 +use GuzzleHttp\Exception\GuzzleException;
  8 +use Illuminate\Support\Facades\Cache;
  9 +
  10 +
  11 +/**
  12 + * Class QuanqiusouApi
  13 + * @package App\Helper
  14 + * @author zbj
  15 + * @date 2023/5/11
  16 + */
  17 +class QuanqiusouApi
  18 +{
  19 + //接口地址
  20 + protected $url = 'http://api.quanqiusou.cn';
  21 +
  22 + /**
  23 + * 所有站点收录页面数
  24 + * @author zbj
  25 + * @date 2023/5/11
  26 + */
  27 + public function getSiteRes()
  28 + {
  29 + $key = 'quanqiusou_api_site_res_' . date('Y-m-d');
  30 + $res = Cache::get($key);
  31 + if (!$res) {
  32 + $api_url = $this->url . '/google-rank/echo_site_res.php';
  33 + try {
  34 + $res = HttpUtils::get($api_url, []);
  35 + if($res){
  36 + $res = Arr::s2a($res);
  37 + Cache::put($key, $res, 24 * 3600);
  38 + }
  39 + } catch (\Exception | GuzzleException $e) {
  40 + errorLog('获取站点收录页面数', [], $e);
  41 + return false;
  42 + }
  43 + }
  44 + return $res;
  45 + }
  46 +
  47 + /**
  48 + * 指定站点收录页面数
  49 + * @param $api_no
  50 + * @return array|false|mixed
  51 + * @author zbj
  52 + * @date 2023/5/11
  53 + */
  54 + public function getSiteResPer($api_no){
  55 + $key = 'quanqiusou_api_site_res_per_' . $api_no . '_' . date('Y-m-d');
  56 + $res = Cache::get($key);
  57 + if (!$res) {
  58 + $api_url = $this->url . '/google-rank/echo_site_res_per.php';
  59 + try {
  60 + $res = HttpUtils::get($api_url, ['apino' => $api_no]);
  61 + if($res){
  62 + $res = Arr::s2a($res);
  63 + Cache::put($key, $res, 24 * 3600);
  64 + }
  65 + } catch (\Exception | GuzzleException $e) {
  66 + errorLog('获取站点收录页面数', [], $e);
  67 + return false;
  68 + }
  69 + }
  70 + return $res;
  71 + }
  72 +
  73 +
  74 + /**
  75 + * 获取谷歌排名数据
  76 + * @param $api_no
  77 + * @param int $lang
  78 + * @param int $day
  79 + * @return array|false|mixed
  80 + * @author zbj
  81 + * @date 2023/5/11
  82 + */
  83 + public function getGoogleRank($api_no, int $lang = 0, int $day = 7)
  84 + {
  85 + $key = "quanqiusou_api_rank_{$api_no}_{$lang}_{$day}_" . date('Y-m-d');
  86 + $res = Cache::get($key);
  87 + if (!$res) {
  88 + $param = [
  89 + 'key' => '289c1fc81c89d79c04ed4fd72822948e',
  90 + 'w' => $api_no,
  91 + 'type' => $day
  92 + ];
  93 + if ($lang) {
  94 + $param['lang'] = $lang;
  95 + }
  96 +
  97 + $api_url = $this->url . '/api';
  98 +
  99 + try {
  100 + $res = HttpUtils::get($api_url, $param);
  101 + if($res){
  102 + $res = Arr::s2a($res);
  103 + Cache::put($key, $res, 24 * 3600);
  104 + }
  105 + } catch (\Exception | GuzzleException $e) {
  106 + errorLog('获取谷歌排名数据失败', $api_no, $e);
  107 + return false;
  108 + }
  109 + }
  110 +
  111 + return $res;
  112 + }
  113 +
  114 + /**
  115 + * 获取每周谷歌排名数据
  116 + * @return array|false|mixed
  117 + * @author zbj
  118 + * @date 2023/5/11
  119 + */
  120 + public function getGoogleRankWeek()
  121 + {
  122 + $key = "quanqiusou_api_week_data_" . date('Y-m-d');
  123 + $res = Cache::get($key);
  124 + if (!$res) {
  125 + $api_url = $this->url . '/google-rank/echo_week_data.php';
  126 + try {
  127 + $res = HttpUtils::get($api_url, []);
  128 + if($res){
  129 + $res = Arr::s2a($res);
  130 + Cache::put($key, $res, 24 * 3600);
  131 + }
  132 + } catch (\Exception | GuzzleException $e) {
  133 + errorLog('获取每周谷歌排名数据失败', [], $e);
  134 + return false;
  135 + }
  136 + }
  137 + return $res;
  138 + }
  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 + /**
  206 + * 获取项目小语种信息
  207 + * @return array|false|int|mixed|null
  208 + * @author zbj
  209 + * @date 2023/5/15
  210 + */
  211 + public function getLangRankData($api_no)
  212 + {
  213 + $key = "quanqiusou_get_language_rank_data_{$api_no}_" . date('Y-m-d');
  214 + $res = Cache::get($key);
  215 + if (!$res) {
  216 + $api_url = $this->url . '/api/index/get_language_rank_data';
  217 + $param = [
  218 + 'apino' => $api_no,
  219 + ];
  220 + try {
  221 + $res = HttpUtils::get($api_url, $param);
  222 + if($res){
  223 + $res = Arr::s2a($res);
  224 + Cache::put($key, $res, 24 * 3600);
  225 + }
  226 + } catch (\Exception | GuzzleException $e) {
  227 + errorLog('获取项目小语种数据失败', [], $e);
  228 + return false;
  229 + }
  230 + }
  231 + return $res;
  232 + }
  233 +
  234 +
  235 +}
  1 +<?php
  2 +
  3 +
  4 +namespace App\Helper;
  5 +
  6 +use App\Utils\HttpUtils;
  7 +use GuzzleHttp\Exception\GuzzleException;
  8 +
  9 +
  10 +/**
  11 + * Class SemrushApi
  12 + * @package App\Helper
  13 + * @author zbj
  14 + * @date 2023/5/9
  15 + */
  16 +class SemrushApi
  17 +{
  18 + //接口地址
  19 + protected $url = 'https://api.semrush.com';
  20 +
  21 + protected $key = '2927058317c47207e4a8c4cacf10acfd';
  22 +
  23 + /**
  24 + * 反链概述
  25 + */
  26 + function backlinks_overview($target,$target_type = "root_domain"){
  27 + if($target){
  28 + $url = $this->url."/analytics/v1/?";
  29 + $params = [
  30 + "type"=>"backlinks_overview",
  31 + "key"=>$this->key,
  32 + "target"=>$target,
  33 + "target_type"=>$target_type,
  34 + "export_columns"=>"ascore,total,domains_num,urls_num,ips_num,ipclassc_num,follows_num,nofollows_num,sponsored_num,ugc_num,texts_num,images_num,forms_num,frames_num"
  35 + ];
  36 + try {
  37 + $res = HttpUtils::get($url, $params);
  38 + return $this->data($res)[0];
  39 + }catch (\Exception|GuzzleException $e){
  40 + errorLog('获取站点外链数据', $params, $e);
  41 + return false;
  42 + }
  43 + }
  44 + return [];
  45 + }
  46 +
  47 + /**
  48 + * 引荐域名
  49 + */
  50 + public function backlinks_refdomains($target,$target_type = "root_domain",$offset = 0){
  51 + if($target){
  52 + $url = $this->url."/analytics/v1/?";
  53 + $params = [
  54 + "type"=>"backlinks_refdomains",
  55 + "key"=>$this->key,
  56 + "target"=>$target,
  57 + "target_type"=>$target_type,
  58 + "export_columns"=>"domain_ascore,domain,backlinks_num,ip,country,first_seen,last_seen",
  59 + "display_limit"=>10,
  60 + "display_offset"=>$offset
  61 + ];
  62 + try {
  63 + $res = HttpUtils::get($url, $params);
  64 + return $this->data($res);
  65 + }catch (\Exception|GuzzleException $e){
  66 + errorLog('获取站点外链数据', $params, $e);
  67 + return false;
  68 + }
  69 + }
  70 + return [];
  71 + }
  72 +
  73 +
  74 + /**
  75 + * 处理结果
  76 + * @param $res
  77 + * @return array
  78 + * @author zbj
  79 + * @date 2023/5/9
  80 + */
  81 + protected function data($res){
  82 + $temp = explode("\n",$res);
  83 +
  84 + $arr =array_map(function ($v){
  85 + return explode(";",$v);
  86 + }, $temp);
  87 + $data = [];
  88 +
  89 + for ($i = 1; $i < count($arr) - 1; $i++) {
  90 + $tmp = [];
  91 + foreach($arr[0] as $k =>$v){
  92 + $tmp[trim($v)] = trim($arr[$i][$k]);
  93 + }
  94 + $data[] = $tmp;
  95 + }
  96 + return $data;
  97 + }
  98 +
  99 +}