作者 李美松

Merge remote-tracking branch 'origin/develop' into lms

# Conflicts:
#	composer.lock
正在显示 42 个修改的文件 包含 4361 行增加325 行删除

要显示太多修改。

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

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,7 @@ @@ -3,6 +3,7 @@
3 /public/storage 3 /public/storage
4 /storage 4 /storage
5 /vendor 5 /vendor
  6 +/uploads
6 .env 7 .env
7 .env.backup 8 .env.backup
8 .phpunit.result.cache 9 .phpunit.result.cache
@@ -14,4 +15,6 @@ yarn-error.log @@ -14,4 +15,6 @@ yarn-error.log
14 /.idea 15 /.idea
15 /.vscode 16 /.vscode
16 composer.lock 17 composer.lock
17 -app/Console/Commands/Test/Demo.php  
  18 +app/Console/Commands/Test/Demo.php
  19 +/public/upload
  20 +/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_share_list = $ayr_share_model->list();
  47 + foreach ($ayr_share_list as $k => $v){
  48 + //查询当前用户是否有未推送的博文
  49 + $ayr_release = new AyrReleaseModel();
  50 + $release_info = $ayr_release->read(['idempotency_key'=>['>',date('Y-m-d H:i:s',time())],'share_id'=>$v['id']]);
  51 + //有推文时,直接跳出循环
  52 + if($release_info !== false){
  53 + continue;
  54 + }
  55 + //查看用户是否在一周内有发送博客
  56 + $start_at = Carbon::now()->modify('-7 days')->toDateString();
  57 + $end_at = Carbon::now()->toDateString();
  58 + $release_info = $ayr_release->read(['created_at'=>['between',[$start_at,$end_at]]]);
  59 + //有发送博文,则跳出循环
  60 + if($release_info == false){
  61 + continue;
  62 + }
  63 + //删除用户第三方配置
  64 + $ayr_share_helper = new AyrShareHelper();
  65 + $data_profiles = [
  66 + 'title'=>$v['title'],
  67 + 'profileKey'=>$v['profile_key']
  68 + ];
  69 + $res = $ayr_share_helper->deleted_profiles($data_profiles);
  70 + if($res['status'] == 'fail'){
  71 + $this->error++;
  72 + continue;
  73 + }
  74 + //更新数据库
  75 + $data = [
  76 + 'title'=>null,
  77 + 'bind_plat_from'=>null,
  78 + 'profile_key'=>null,
  79 + 'ref_id'=>null,
  80 + ];
  81 + $res = $ayr_share_model->edit($data,['id'=>$v['id']]);
  82 + if($res == false){
  83 + $this->error++;
  84 + }
  85 + }
  86 + return $this->error;
  87 + }
  88 +}
  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 - * 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']];
  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 +}
@@ -16,6 +16,13 @@ class Kernel extends ConsoleKernel @@ -16,6 +16,13 @@ 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点执行一次
19 } 26 }
20 27
21 /** 28 /**
@@ -18,4 +18,5 @@ final class Common extends Enum @@ -18,4 +18,5 @@ final class Common extends Enum
18 //端 18 //端
19 const A='a'; 19 const A='a';
20 const B='b'; 20 const B='b';
  21 + const C='c';
21 } 22 }
  1 +<?php
  2 +
  3 +namespace App\Exceptions;
  4 +
  5 +use App\Enums\Common\Code;
  6 +use Exception;
  7 +use Throwable;
  8 +
  9 +/**
  10 + * @notes: C端接口统一错误格式
  11 + * Class CsideGlobalException
  12 + * @package App\Exceptions
  13 + */
  14 +class CsideGlobalException extends Exception
  15 +{
  16 + public function __construct($code = 0, $message = "", Throwable $previous = null)
  17 + {
  18 + $this->code = $code;
  19 + $this->message = $message;
  20 + if (empty($this->message)) {
  21 + $this->message = Code::fromValue($code)->description;
  22 + }
  23 + }
  24 +}
@@ -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() .
@@ -73,6 +72,10 @@ class Handler extends ExceptionHandler @@ -73,6 +72,10 @@ class Handler extends ExceptionHandler
73 elseif($exception instanceof BsideGlobalException) { 72 elseif($exception instanceof BsideGlobalException) {
74 LogUtils::error("BsideGlobalException", [], $exceptionMessage); 73 LogUtils::error("BsideGlobalException", [], $exceptionMessage);
75 } 74 }
  75 + //C端错误
  76 + elseif($exception instanceof CsideGlobalException) {
  77 + LogUtils::error("CsideGlobalException", [], $exceptionMessage);
  78 + }
76 //验证错误(非手动抛出) 79 //验证错误(非手动抛出)
77 elseif ($exception instanceof ValidationException) { 80 elseif ($exception instanceof ValidationException) {
78 LogUtils::error("参数验证失败", [], $exceptionMessage); 81 LogUtils::error("参数验证失败", [], $exceptionMessage);
@@ -111,31 +114,28 @@ class Handler extends ExceptionHandler @@ -111,31 +114,28 @@ class Handler extends ExceptionHandler
111 $code = $exception->getCode(); 114 $code = $exception->getCode();
112 }elseif ($exception instanceof BsideGlobalException) { 115 }elseif ($exception instanceof BsideGlobalException) {
113 $code = $exception->getCode(); 116 $code = $exception->getCode();
  117 + }elseif ($exception instanceof CsideGlobalException) {
  118 + $code = $exception->getCode();
114 } elseif ($exception instanceof ValidationException) { 119 } elseif ($exception instanceof ValidationException) {
115 $code = Code::USER_PARAMS_ERROE(); 120 $code = Code::USER_PARAMS_ERROE();
116 - $message = Arr::first(Arr::first($exception->errors())); 121 + $message = $code->description = Arr::first(Arr::first($exception->errors()));
117 } elseif ($exception instanceof NotFoundHttpException || $exception instanceof MethodNotAllowedHttpException) { 122 } elseif ($exception instanceof NotFoundHttpException || $exception instanceof MethodNotAllowedHttpException) {
118 return response('404 Not Found', 404); 123 return response('404 Not Found', 404);
119 } else { 124 } else {
120 $code = Code::SYSTEM_ERROR(); 125 $code = Code::SYSTEM_ERROR();
121 } 126 }
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 错误原样输出 127 //开启debug 错误原样输出
132 $debub = config('app.debug'); 128 $debub = config('app.debug');
133 $message = $debub ? $message : ($code->description ?? $message); 129 $message = $debub ? $message : ($code->description ?? $message);
134 -  
135 $response = [ 130 $response = [
136 'code' => $code, 131 'code' => $code,
137 'message' => $message 132 'message' => $message
138 ]; 133 ];
  134 + // 调试模式
  135 + if(env('app_debug')){
  136 + $response['trace'] = $exception->getTrace();
  137 + }
  138 +
139 //加密返回 139 //加密返回
140 if (config('app.params_encrypt')) { 140 if (config('app.params_encrypt')) {
141 $k = config('app.params_encrypt_key'); 141 $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 -}  
@@ -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 + * @name :(发帖)post_send_msg
  108 + * @author :lyh
  109 + * @method :post
  110 + * @time :2023/5/8 9:22
  111 + * @param :platforms: "facebook", "fbg", "twitter",
  112 + * "linkedin", "instagram","youtube", "reddit" ,"telegram""
  113 + */
  114 + public function post_send_msg($param,$api_key){
  115 + //平台参数处理
  116 + $this->headers['Accept-Encoding'] = 'gzip';
  117 + $this->headers['Authorization'] = $this->headers['Authorization'].$api_key;
  118 + $url = $this->path.'/api/post';
  119 + return $this->http_click('posts',$url,$param,$this->headers);
  120 + }
  121 +
  122 + /**
  123 + * @name :(上传图片或视频到ayr_share)post_media_upload
  124 + * @author :lyh
  125 + * @method :post
  126 + * @time :2023/5/8 9:47
  127 + * https://app.ayrshare.com/api/media/upload
  128 + */
  129 + public function post_media_upload($data,$api_key){
  130 + $param = [
  131 + 'file'=>$data['file'],//base64编码
  132 + ];
  133 + $this->headers['Authorization'] = $this->headers['Authorization'].$api_key;
  134 + $url = $this->path.'/api/media/upload';
  135 + return $this->http_click('post',$url,$param,$this->headers);
  136 + }
  137 +
  138 + /**
  139 + * @name :获取过去30天发布的历史记录(1-30)
  140 + * @author :lyh
  141 + * @method :get
  142 + * @time :2023/5/5 10:00
  143 + */
  144 + public function get_analytics_links($to_day){
  145 + $last_days = (string)$to_day;
  146 + $url = $this->path.'/analytics/links?lastDays='.$last_days;
  147 + return $this->http_click('get',$url);
  148 + }
  149 +
  150 + /**
  151 + * @name :(通过 Ayrshare 获取给定帖子的实时分析,例如点赞、印象、转推等)post_analytics
  152 + * @author :lyh
  153 + * @method :post
  154 + * @time :2023/5/5 11:56
  155 + */
  156 + public function post_analytics($id){
  157 + $param = [
  158 + 'id'=>$id,
  159 + 'platforms' => ['facebook', 'instagram', 'twitter', 'linkedin', 'pinterest', 'youtube', 'tiktok'],
  160 + ];
  161 + $url = $this->path.'/api/analytics/post';
  162 + return $this->http_click('post', $url, $param);
  163 + }
  164 + /**
  165 + * @name :(获取特定用户个人资料)analytics_post
  166 + * @author :lyh
  167 + * @method :post
  168 + * @time :2023/5/5 10:43
  169 + */
  170 + public function post_analytics_social(){
  171 + $post_data = [
  172 + 'platforms' => ['facebook', 'instagram', 'twitter', 'linkedin', 'pinterest', 'youtube', 'tiktok'],
  173 + ];
  174 + $url = $this->path.'/api/analytics/social';
  175 + return $this->http_click('post',$url,$post_data);
  176 + }
  177 +
  178 + /**
  179 + * @name :(设置自动计划)post_schedule_set
  180 + * @author :lyh
  181 + * @method :post
  182 + * @time :2023/5/5 13:58
  183 + */
  184 + public function post_schedule_set($data){
  185 + $param = [
  186 + 'schedule'=>["13:05Z", "20:14Z"],
  187 + 'title'=>$data['title'],
  188 + ];
  189 + $url = $this->path.'/api/auto-schedule/set';
  190 + return $this->http_click('post',$url,$param);
  191 + }
  192 +
  193 + /**
  194 + * @name :(删除自动计划)delete_schedule
  195 + * @author :lyh
  196 + * @method :post
  197 + * @time :2023/5/5 14:04
  198 + */
  199 + public function delete_schedule($data){
  200 + $param = [
  201 + 'title'=>$data['title'],
  202 + ];
  203 + $url = $this->path.'/api/auto-schedule/delete';
  204 + return $this->http_click('delete',$url,$param);
  205 + }
  206 +
  207 + /**
  208 + * @name :(列出自动计划)get_schedule_list
  209 + * @author :lyh
  210 + * @method :post
  211 + * @time :2023/5/5 14:08
  212 + */
  213 + public function get_schedule_list(){
  214 + $url = $this->path.'/api/auto-schedule/list';
  215 + return $this->http_click('get',$url);
  216 + }
  217 +
  218 + /**
  219 + * @name :(发布到用户个人资料)post_user
  220 + * @author :lyh
  221 + * @method :post
  222 + * @time :2023/5/5 15:00
  223 + */
  224 + public function post_profiles($data){
  225 + $param = [
  226 + 'post'=>$data['post'],
  227 + 'platforms'=>$data['platforms'],
  228 + 'profileKey'=>$this->profile_key,
  229 + 'mediaUrls'=>$data['mediaUrls']
  230 + ];
  231 + $url = $this->path.'/api/post';
  232 + return $this->http_click('post',$url,$param);
  233 + }
  234 +
  235 + /**
  236 + * 发送http post,get,put,delete请求
  237 + * @param type $url
  238 + * @param type $post_data
  239 + */
  240 + function http_click($method = 'post',$url, $param = [],$header = [])
  241 + {
  242 + if(!empty($param)){
  243 + $post_data['json'] = $param;
  244 + }
  245 + if(empty($header)){
  246 + $this->headers['Authorization'] = $this->headers['Authorization'].$this->api_key;
  247 + }
  248 + $post_data['headers'] = !empty($header) ? $header : $this->headers;
  249 + $client = new Client();
  250 + try {
  251 + $res = $client->request(strtoupper($method), $url, $post_data)->getBody()->getContents();
  252 + return (array)json_decode($res);
  253 + } catch (\Exception $e) {
  254 + return ["status"=>"fail","message"=>$e->getMessage()];
  255 + }
  256 + }
  257 +}
  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 +}
  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 + 'zh-CN' => [
  146 + 'text' => '中文(简体)',
  147 + 'lang_text' => '简体中文',
  148 + 'con_flag' => 'con_flag/zh.jfif',
  149 + 'shop_lang' => 'zh-cn',
  150 + ],
  151 + 'zh-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];
  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 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 +}
  1 +<?php
  2 +
  3 +
  4 +namespace App\Helper;
  5 +
  6 +use Illuminate\Support\Facades\Http;
  7 +
  8 +
  9 +/**
  10 + * 翻译接口
  11 + * Class Translate
  12 + * @package App\Service
  13 + * @author zbj
  14 + * @date 2023/2/7
  15 + */
  16 +class Translate
  17 +{
  18 + //接口地址
  19 + public static $url = 'https://translate.hbb618.cn/translates';
  20 +
  21 + public static $tls_list = [
  22 + 'en' => [
  23 + 'text' => '英语',
  24 + 'lang_text' => 'English',
  25 + 'con_flag' => 'con_flag/en.jfif',
  26 + 'shop_lang' => 'en-gb',
  27 + ],
  28 + 'zh' => [
  29 + 'text' => '中文',
  30 + 'lang_text' => '简体中文',
  31 + 'con_flag' => 'con_flag/zh.jfif',
  32 + 'shop_lang' => 'zh-cn',
  33 + ],
  34 + 'fr' => [
  35 + 'text' => '法语',
  36 + 'lang_text' => 'En français',
  37 + 'con_flag' => '',
  38 +
  39 + ],
  40 + 'de' => [
  41 + 'text' => '德语',
  42 + 'lang_text' => 'Das ist Deutsch.',
  43 + 'con_flag' => '',
  44 +
  45 + ],
  46 + 'ko' => [
  47 + 'text' => '韩语',
  48 + 'lang_text' => '',
  49 + 'con_flag' => '',
  50 +
  51 + ],
  52 + 'ja' => [
  53 + 'text' => '日语',
  54 + 'lang_text' => '',
  55 + 'con_flag' => '',
  56 +
  57 + ],
  58 + 'es' => [
  59 + 'text' => '西班牙语',
  60 + 'lang_text' => 'Español.',
  61 + 'con_flag' => '',
  62 +
  63 + ],
  64 + 'ar' => [
  65 + 'text' => '阿拉伯语',
  66 + 'lang_text' => '',
  67 + 'con_flag' => '',
  68 +
  69 + ],
  70 + 'pt' => [
  71 + 'text' => '葡萄牙语(葡萄牙、巴西)',
  72 + 'lang_text' => 'Língua portuguesa',
  73 + 'con_flag' => '',
  74 +
  75 + ],
  76 + 'ru' => [
  77 + 'text' => '俄语',
  78 + 'lang_text' => '',
  79 + 'con_flag' => '',
  80 +
  81 + ],
  82 + 'af' => [
  83 + 'text' => '南非荷兰语',
  84 + 'lang_text' => '',
  85 + 'con_flag' => '',
  86 +
  87 + ],
  88 + 'sq' => [
  89 + 'text' => '阿尔巴尼亚语',
  90 + 'lang_text' => '',
  91 + 'con_flag' => '',
  92 +
  93 + ],
  94 + 'am' => [
  95 + 'text' => '阿姆哈拉语',
  96 + 'lang_text' => '',
  97 + 'con_flag' => '',
  98 +
  99 + ],
  100 + 'hy' => [
  101 + 'text' => '亚美尼亚语',
  102 + 'lang_text' => '',
  103 + 'con_flag' => '',
  104 +
  105 + ],
  106 + 'az' => [
  107 + 'text' => '阿塞拜疆语',
  108 + 'lang_text' => '',
  109 + 'con_flag' => '',
  110 +
  111 + ],
  112 + 'eu' => [
  113 + 'text' => '巴斯克语',
  114 + 'lang_text' => '',
  115 + 'con_flag' => '',
  116 +
  117 + ],
  118 + 'be' => [
  119 + 'text' => '白俄罗斯语',
  120 + 'lang_text' => '',
  121 + 'con_flag' => '',
  122 +
  123 + ],
  124 + 'bn' => [
  125 + 'text' => '孟加拉语',
  126 + 'lang_text' => '',
  127 + 'con_flag' => '',
  128 +
  129 + ],
  130 + 'bs' => [
  131 + 'text' => '波斯尼亚语',
  132 + 'lang_text' => '',
  133 + 'con_flag' => '',
  134 +
  135 + ],
  136 + 'bg' => [
  137 + 'text' => '保加利亚语',
  138 + 'lang_text' => '',
  139 + 'con_flag' => '',
  140 +
  141 + ],
  142 + 'ca' => [
  143 + 'text' => '加泰罗尼亚语',
  144 + 'lang_text' => '',
  145 + 'con_flag' => '',
  146 +
  147 + ],
  148 + 'ceb' => [
  149 + 'text' => '宿务语',
  150 + 'lang_text' => '',
  151 + 'con_flag' => '',
  152 +
  153 + ],
  154 + 'zh-CN' => [
  155 + 'text' => '中文(简体)',
  156 + 'lang_text' => '简体中文',
  157 + 'con_flag' => 'con_flag/zh.jfif',
  158 + 'shop_lang' => 'zh-cn',
  159 + ],
  160 + 'zh-TW' => [
  161 + 'text' => '中文(繁体)',
  162 + 'lang_text' => '繁体中文',
  163 + 'con_flag' => 'con_flag/zh.jfif',
  164 +
  165 + ],
  166 + 'co' => [
  167 + 'text' => '科西嘉语',
  168 + 'lang_text' => '',
  169 + 'con_flag' => '',
  170 +
  171 + ],
  172 + 'hr' => [
  173 + 'text' => '克罗地亚语',
  174 + 'lang_text' => '',
  175 + 'con_flag' => '',
  176 +
  177 + ],
  178 + 'cs' => [
  179 + 'text' => '捷克语',
  180 + 'lang_text' => '',
  181 + 'con_flag' => '',
  182 +
  183 + ],
  184 + 'da' => [
  185 + 'text' => '丹麦语',
  186 + 'lang_text' => '',
  187 + 'con_flag' => '',
  188 +
  189 + ],
  190 + 'nl' => [
  191 + 'text' => '荷兰语',
  192 + 'lang_text' => '',
  193 + 'con_flag' => '',
  194 +
  195 + ],
  196 + 'eo' => [
  197 + 'text' => '世界语',
  198 + 'lang_text' => '',
  199 + 'con_flag' => '',
  200 +
  201 + ],
  202 + 'et' => [
  203 + 'text' => '爱沙尼亚语',
  204 + 'lang_text' => '',
  205 + 'con_flag' => '',
  206 +
  207 + ],
  208 + 'fi' => [
  209 + 'text' => '芬兰语',
  210 + 'lang_text' => '',
  211 + 'con_flag' => '',
  212 +
  213 + ],
  214 + 'fy' => [
  215 + 'text' => '弗里斯兰语',
  216 + 'lang_text' => '',
  217 + 'con_flag' => '',
  218 +
  219 + ],
  220 + 'gl' => [
  221 + 'text' => '加利西亚语',
  222 + 'lang_text' => '',
  223 + 'con_flag' => '',
  224 +
  225 + ],
  226 + 'ka' => [
  227 + 'text' => '格鲁吉亚语',
  228 + 'lang_text' => '',
  229 + 'con_flag' => '',
  230 +
  231 + ],
  232 + 'el' => [
  233 + 'text' => '希腊语',
  234 + 'lang_text' => '',
  235 + 'con_flag' => '',
  236 +
  237 + ],
  238 + 'gu' => [
  239 + 'text' => '古吉拉特语',
  240 + 'lang_text' => '',
  241 + 'con_flag' => '',
  242 +
  243 + ],
  244 + 'ht' => [
  245 + 'text' => '海地克里奥尔语',
  246 + 'lang_text' => '',
  247 + 'con_flag' => '',
  248 +
  249 + ],
  250 + 'ha' => [
  251 + 'text' => '豪萨语',
  252 + 'lang_text' => '',
  253 + 'con_flag' => '',
  254 +
  255 + ],
  256 + 'haw' => [
  257 + 'text' => '夏威夷语',
  258 + 'lang_text' => '',
  259 + 'con_flag' => '',
  260 +
  261 + ],
  262 + 'iw' => [
  263 + 'text' => '希伯来语',
  264 + 'lang_text' => '',
  265 + 'con_flag' => '',
  266 +
  267 + ],
  268 + 'hi' => [
  269 + 'text' => '印地语',
  270 + 'lang_text' => '',
  271 + 'con_flag' => '',
  272 +
  273 + ],
  274 + 'hmn' => [
  275 + 'text' => '苗语',
  276 + 'lang_text' => '',
  277 + 'con_flag' => '',
  278 +
  279 + ],
  280 + 'hu' => [
  281 + 'text' => '匈牙利语',
  282 + 'lang_text' => '',
  283 + 'con_flag' => '',
  284 +
  285 + ],
  286 + 'is' => [
  287 + 'text' => '冰岛语',
  288 + 'lang_text' => '',
  289 + 'con_flag' => '',
  290 +
  291 + ],
  292 + 'ig' => [
  293 + 'text' => '伊博语',
  294 + 'lang_text' => '',
  295 + 'con_flag' => '',
  296 +
  297 + ],
  298 + 'id' => [
  299 + 'text' => '印度尼西亚语',
  300 + 'lang_text' => 'Bahasa Indonesia',
  301 + 'con_flag' => 'con_flag/id.jfif',
  302 + 'shop_lang' => 'id',
  303 + ],
  304 + 'ga' => [
  305 + 'text' => '爱尔兰语',
  306 + 'lang_text' => '',
  307 + 'con_flag' => '',
  308 +
  309 + ],
  310 + 'it' => [
  311 + 'text' => '意大利语',
  312 + 'lang_text' => 'Lingua italiana',
  313 + 'con_flag' => '',
  314 +
  315 + ],
  316 + 'jw' => [
  317 + 'text' => '爪哇语',
  318 + 'lang_text' => '',
  319 + 'con_flag' => '',
  320 +
  321 + ],
  322 + 'kn' => [
  323 + 'text' => '卡纳达语',
  324 + 'lang_text' => '',
  325 + 'con_flag' => '',
  326 +
  327 + ],
  328 + 'kk' => [
  329 + 'text' => '哈萨克语',
  330 + 'lang_text' => '',
  331 + 'con_flag' => '',
  332 +
  333 + ],
  334 + 'km' => [
  335 + 'text' => '高棉语',
  336 + 'lang_text' => '',
  337 + 'con_flag' => '',
  338 +
  339 + ],
  340 + 'rw' => [
  341 + 'text' => '卢旺达语',
  342 + 'lang_text' => '',
  343 + 'con_flag' => '',
  344 +
  345 + ],
  346 + 'ku' => [
  347 + 'text' => '库尔德语',
  348 + 'lang_text' => '',
  349 + 'con_flag' => '',
  350 +
  351 + ],
  352 + 'ky' => [
  353 + 'text' => '吉尔吉斯语',
  354 + 'lang_text' => '',
  355 + 'con_flag' => '',
  356 +
  357 + ],
  358 + 'lo' => [
  359 + 'text' => '老挝文',
  360 + 'lang_text' => '',
  361 + 'con_flag' => '',
  362 +
  363 + ],
  364 + 'la' => [
  365 + 'text' => '拉丁文',
  366 + 'lang_text' => '',
  367 + 'con_flag' => '',
  368 +
  369 + ],
  370 + 'lv' => [
  371 + 'text' => '拉脱维亚语',
  372 + 'lang_text' => '',
  373 + 'con_flag' => '',
  374 +
  375 + ],
  376 + 'lt' => [
  377 + 'text' => '立陶宛语',
  378 + 'lang_text' => '',
  379 + 'con_flag' => '',
  380 +
  381 + ],
  382 + 'lb' => [
  383 + 'text' => '卢森堡语',
  384 + 'lang_text' => '',
  385 + 'con_flag' => '',
  386 +
  387 + ],
  388 + 'mk' => [
  389 + 'text' => '马其顿语',
  390 + 'lang_text' => '',
  391 + 'con_flag' => '',
  392 +
  393 + ],
  394 + 'mg' => [
  395 + 'text' => '马尔加什语',
  396 + 'lang_text' => '',
  397 + 'con_flag' => '',
  398 +
  399 + ],
  400 + 'ms' => [
  401 + 'text' => '马来语',
  402 + 'lang_text' => 'Bahasa Melayu',
  403 + 'con_flag' => 'con_flag/ms.jfif',
  404 + 'shop_lang' => 'ms-my',
  405 + ],
  406 + 'ml' => [
  407 + 'text' => '马拉雅拉姆文',
  408 + 'lang_text' => '',
  409 + 'con_flag' => '',
  410 +
  411 + ],
  412 + 'mt' => [
  413 + 'text' => '马耳他语',
  414 + 'lang_text' => '',
  415 + 'con_flag' => '',
  416 +
  417 + ],
  418 + 'mi' => [
  419 + 'text' => '毛利语',
  420 + 'lang_text' => '',
  421 + 'con_flag' => '',
  422 +
  423 + ],
  424 + 'mr' => [
  425 + 'text' => '马拉地语',
  426 + 'lang_text' => '',
  427 + 'con_flag' => '',
  428 +
  429 + ],
  430 + 'mn' => [
  431 + 'text' => '蒙古文',
  432 + 'lang_text' => '',
  433 + 'con_flag' => '',
  434 +
  435 + ],
  436 + 'my' => [
  437 + 'text' => '缅甸语',
  438 + 'lang_text' => '',
  439 + 'con_flag' => '',
  440 +
  441 + ],
  442 + 'ne' => [
  443 + 'text' => '尼泊尔语',
  444 + 'lang_text' => '',
  445 + 'con_flag' => '',
  446 +
  447 + ],
  448 + 'no' => [
  449 + 'text' => '挪威语',
  450 + 'lang_text' => '',
  451 + 'con_flag' => '',
  452 +
  453 + ],
  454 + 'ny' => [
  455 + 'text' => '尼杨扎语(齐切瓦语)',
  456 + 'lang_text' => '',
  457 + 'con_flag' => '',
  458 +
  459 + ],
  460 + 'or' => [
  461 + 'text' => '奥里亚语(奥里亚)',
  462 + 'lang_text' => '',
  463 + 'con_flag' => '',
  464 +
  465 + ],
  466 + 'ps' => [
  467 + 'text' => '普什图语',
  468 + 'lang_text' => '',
  469 + 'con_flag' => '',
  470 +
  471 + ],
  472 + 'fa' => [
  473 + 'text' => '波斯语',
  474 + 'lang_text' => '',
  475 + 'con_flag' => '',
  476 +
  477 + ],
  478 + 'pl' => [
  479 + 'text' => '波兰语',
  480 + 'lang_text' => '',
  481 + 'con_flag' => '',
  482 +
  483 + ],
  484 + 'pa' => [
  485 + 'text' => '旁遮普语',
  486 + 'lang_text' => '',
  487 + 'con_flag' => '',
  488 +
  489 + ],
  490 + 'ro' => [
  491 + 'text' => '罗马尼亚语',
  492 + 'lang_text' => '',
  493 + 'con_flag' => '',
  494 +
  495 + ],
  496 + 'sm' => [
  497 + 'text' => '萨摩亚语',
  498 + 'lang_text' => '',
  499 + 'con_flag' => '',
  500 +
  501 + ],
  502 + 'gd' => [
  503 + 'text' => '苏格兰盖尔语',
  504 + 'lang_text' => '',
  505 + 'con_flag' => '',
  506 +
  507 + ],
  508 + 'sr' => [
  509 + 'text' => '塞尔维亚语',
  510 + 'lang_text' => '',
  511 + 'con_flag' => '',
  512 +
  513 + ],
  514 + 'st' => [
  515 + 'text' => '塞索托语',
  516 + 'lang_text' => '',
  517 + 'con_flag' => '',
  518 +
  519 + ],
  520 + 'sn' => [
  521 + 'text' => '修纳语',
  522 + 'lang_text' => '',
  523 + 'con_flag' => '',
  524 +
  525 + ],
  526 + 'sd' => [
  527 + 'text' => '信德语',
  528 + 'lang_text' => '',
  529 + 'con_flag' => '',
  530 +
  531 + ],
  532 + 'si' => [
  533 + 'text' => '僧伽罗语',
  534 + 'lang_text' => '',
  535 + 'con_flag' => '',
  536 +
  537 + ],
  538 + 'sk' => [
  539 + 'text' => '斯洛伐克语',
  540 + 'lang_text' => '',
  541 + 'con_flag' => '',
  542 +
  543 + ],
  544 + 'sl' => [
  545 + 'text' => '斯洛文尼亚语',
  546 + 'lang_text' => '',
  547 + 'con_flag' => '',
  548 +
  549 + ],
  550 + 'so' => [
  551 + 'text' => '索马里语',
  552 + 'lang_text' => '',
  553 + 'con_flag' => '',
  554 +
  555 + ],
  556 + 'su' => [
  557 + 'text' => '巽他语',
  558 + 'lang_text' => '',
  559 + 'con_flag' => '',
  560 +
  561 + ],
  562 + 'sw' => [
  563 + 'text' => '斯瓦希里语',
  564 + 'lang_text' => '',
  565 + 'con_flag' => '',
  566 +
  567 + ],
  568 + 'sv' => [
  569 + 'text' => '瑞典语',
  570 + 'lang_text' => '',
  571 + 'con_flag' => '',
  572 +
  573 + ],
  574 + 'tl' => [
  575 + 'text' => '塔加路语(菲律宾语)',
  576 + 'lang_text' => 'Pilipino',
  577 + 'con_flag' => 'con_flag/tl.jfif',
  578 + 'shop_lang' => 'tl',
  579 + ],
  580 + 'tg' => [
  581 + 'text' => '塔吉克语',
  582 + 'lang_text' => '',
  583 + 'con_flag' => '',
  584 +
  585 + ],
  586 + 'ta' => [
  587 + 'text' => '泰米尔语',
  588 + 'lang_text' => '',
  589 + 'con_flag' => '',
  590 +
  591 + ],
  592 + 'tt' => [
  593 + 'text' => '鞑靼语',
  594 + 'lang_text' => '',
  595 + 'con_flag' => '',
  596 +
  597 + ],
  598 + 'te' => [
  599 + 'text' => '泰卢固语',
  600 + 'lang_text' => '',
  601 + 'con_flag' => '',
  602 +
  603 + ],
  604 + 'th' => [
  605 + 'text' => '泰文',
  606 + 'lang_text' => 'ไทย',
  607 + 'con_flag' => 'con_flag/th.jfif',
  608 + 'shop_lang' => 'th',
  609 + ],
  610 + 'tr' => [
  611 + 'text' => '土耳其语',
  612 + 'lang_text' => '',
  613 + 'con_flag' => '',
  614 +
  615 + ],
  616 + 'tk' => [
  617 + 'text' => '土库曼语',
  618 + 'lang_text' => '',
  619 + 'con_flag' => '',
  620 +
  621 + ],
  622 + 'uk' => [
  623 + 'text' => '乌克兰语',
  624 + 'lang_text' => '',
  625 + 'con_flag' => '',
  626 +
  627 + ],
  628 + 'ur' => [
  629 + 'text' => '乌尔都语',
  630 + 'lang_text' => '',
  631 + 'con_flag' => '',
  632 +
  633 + ],
  634 + 'ug' => [
  635 + 'text' => '维吾尔语',
  636 + 'lang_text' => '',
  637 + 'con_flag' => '',
  638 +
  639 + ],
  640 + 'uz' => [
  641 + 'text' => '乌兹别克语',
  642 + 'lang_text' => '',
  643 + 'con_flag' => '',
  644 +
  645 + ],
  646 + 'vi' => [
  647 + 'text' => '越南语',
  648 + 'lang_text' => '',
  649 + 'con_flag' => '',
  650 +
  651 + ],
  652 + 'cy' => [
  653 + 'text' => '威尔士语',
  654 + 'lang_text' => '',
  655 + 'con_flag' => '',
  656 +
  657 + ],
  658 + 'xh' => [
  659 + 'text' => '班图语',
  660 + 'lang_text' => '',
  661 + 'con_flag' => '',
  662 +
  663 + ],
  664 + 'yi' => [
  665 + 'text' => '意第绪语',
  666 + 'lang_text' => '',
  667 + 'con_flag' => '',
  668 +
  669 + ],
  670 + 'yo' => [
  671 + 'text' => '约鲁巴语',
  672 + 'lang_text' => '',
  673 + 'con_flag' => '',
  674 +
  675 + ],
  676 + 'zu' => [
  677 + 'text' => '祖鲁语',
  678 + 'lang_text' => '',
  679 + 'con_flag' => '',
  680 + ],
  681 + ];
  682 +
  683 + /**
  684 + * 获取语种列表
  685 + * @return array|string
  686 + * @author:dc
  687 + * @time 2022/3/30 13:52
  688 + */
  689 + public static function getTls($lang = null){
  690 + $tls = array_combine(array_keys(static::$tls_list),array_column(static::$tls_list, 'text'));
  691 +
  692 + if($lang === null){
  693 + return $tls;
  694 + }
  695 +
  696 + if (is_array($lang)){
  697 + foreach ($lang as $key=>$item){
  698 + unset($lang[$key]);
  699 + $lang[$item] = $tls[$item]??'';
  700 + }
  701 + return $lang;
  702 + }
  703 +
  704 + return $tls[$lang]??'';
  705 + }
  706 +
  707 + /**
  708 + * 翻译
  709 + * @param $texts
  710 + * @param $tls
  711 + * @return \Illuminate\Http\Client\Response
  712 + * @time 2022/3/30 15:58
  713 + */
  714 + public static function translate($texts, $tls)
  715 + {
  716 + if (is_string($texts)) {
  717 + $texts = [$texts];
  718 + }
  719 + if (is_string($tls)) {
  720 + $tls = [$tls];
  721 + }
  722 + $data = [
  723 + 'texts' => $texts,
  724 + 'sl' => 'auto',
  725 + 'tls' => $tls,
  726 + ];
  727 + return Http::post(self::$url, $data);
  728 + }
  729 +
  730 + /**
  731 + * @param $texts
  732 + * @param $tls
  733 + * @return string|array
  734 + * @author:dc
  735 + * @time 2022/3/30 15:59
  736 + */
  737 + public static function tran($texts, $tls)
  738 + {
  739 + if (!$texts) {
  740 + return '';
  741 + }
  742 +
  743 + $retsult = self::translate($texts, $tls)->json();
  744 +
  745 + return $retsult[0]['texts'] ?? '';
  746 +
  747 + }
  748 +
  749 +
  750 +}
1 <?php 1 <?php
2 2
  3 +use App\Utils\LogUtils;
  4 +use Illuminate\Support\Carbon;
  5 +
  6 +define('HTTP_OPENAI_URL','http://openai.waimaoq.com/');
3 /** 7 /**
4 * 生成路由标识 8 * 生成路由标识
5 * @param $string 9 * @param $string
@@ -7,6 +11,215 @@ @@ -7,6 +11,215 @@
7 * @author zbj 11 * @author zbj
8 * @date 2023/4/15 12 * @date 2023/4/15
9 */ 13 */
10 -function generateRoute($string){  
11 - return trim(strtolower(preg_replace( '/[\W]+/', '-', trim($string))), '-'); 14 +
  15 +if (!function_exists('generateRoute')) {
  16 + function generateRoute($string)
  17 + {
  18 + return trim(strtolower(preg_replace('/[\W]+/', '-', trim($string))), '-');
  19 + }
  20 +}
  21 +
  22 +
  23 +/**
  24 + * 手动记录错误日志
  25 + * @param $title
  26 + * @param $params
  27 + * @param Throwable $exception
  28 + * @author zbj
  29 + * @date 2023/4/27
  30 + */
  31 +function errorLog($title, $params, Throwable $exception){
  32 + $exceptionMessage = "错误CODE:" . $exception->getCode() .
  33 + "-----错误message:" . $exception->getMessage() .
  34 + '------错误文件:' . $exception->getFile() .
  35 + '-------错误行数:' . $exception->getLine();
  36 +
  37 + LogUtils::error($title, $params, $exceptionMessage);
  38 +}
  39 +
  40 +if(!function_exists('http_post')){
  41 + /**
  42 + * 发送http post请求
  43 + * @param type $url
  44 + * @param type $post_data
  45 + */
  46 + function http_post($url, $post_data,$header = [])
  47 + {
  48 + if(empty($header)){
  49 + $header = array(
  50 + "Accept: application/json",
  51 + "Content-Type:application/json;charset=utf-8",
  52 + );
  53 + }
  54 + $ch = curl_init();
  55 + curl_setopt($ch, CURLOPT_URL, $url);
  56 + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
  57 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  58 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
  59 + curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  60 + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
  61 + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  62 + curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
  63 + curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
  64 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  65 + $res = curl_exec($ch);
  66 + if (curl_errno($ch)) {
  67 + Log::write(print_r(curl_errno($ch),1),'debug---1');
  68 + }
  69 + curl_close($ch);
  70 + return json_decode($res, true);
  71 + }
  72 +}
  73 +
  74 +if(!function_exists('http_get')){
  75 + /**
  76 + * 发送http get请求
  77 + * @param type $url
  78 + * @return type
  79 + */
  80 + function http_get($url,$header = [])
  81 + {
  82 + if(empty($header)){
  83 + $header[] = "content-type: application/json;
  84 + charset = UTF-8";
  85 + }
  86 + $ch1 = curl_init();
  87 + $timeout = 5;
  88 + curl_setopt($ch1, CURLOPT_URL, $url);
  89 + curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1);
  90 + curl_setopt($ch1, CURLOPT_HTTPHEADER, $header);
  91 + curl_setopt($ch1, CURLOPT_CONNECTTIMEOUT, $timeout);
  92 + curl_setopt($ch1, CURLOPT_SSL_VERIFYPEER, false);
  93 + curl_setopt($ch1, CURLOPT_SSL_VERIFYHOST, false);
  94 + $access_txt = curl_exec($ch1);
  95 + curl_close($ch1);
  96 + return json_decode($access_txt, true);
  97 + }
  98 +}
  99 +
  100 +
  101 +if(!function_exists('_get_child')){
  102 + /**
  103 + * 菜单权限->得到子级数组
  104 + * @param int
  105 + * @return array
  106 + */
  107 + function _get_child($my_id, $arr)
  108 + {
  109 + $new_arr = array();
  110 + foreach ($arr as $k => $v) {
  111 + $v = (array)$v;
  112 + if ($v['pid'] == $my_id) {
  113 + $v['sub'] = _get_child($v['id'],$arr);
  114 + $new_arr[] = $v;
  115 + }
  116 + }
  117 + return $new_arr ? $new_arr : false;
  118 + }
  119 +}
  120 +
  121 +
  122 +
  123 +if (!function_exists('checkDomain')) {
  124 + /**
  125 + * 检查并补全域名协议
  126 + * @return false|string
  127 + * @author zbj
  128 + * @date 2023/5/5
  129 + */
  130 + function checkDomain($value)
  131 + {
  132 + $urlParts = parse_url(strtolower($value));
  133 + if(empty($urlParts['host'])){
  134 + $urlParts = parse_url('https://' . $value);
  135 + }
  136 + $host = $urlParts['host'] ?? '';
  137 + $scheme = $urlParts['scheme'] ?? 'https';
  138 + if(!in_array($scheme, ['http', 'https'])){
  139 + return false;
  140 + }
  141 + if (preg_match('/^(?:[-A-Za-z0-9]+\.)+[A-Za-z]{2,6}$/', $host)) {
  142 + return $scheme . '://' . $host;
  143 + } else {
  144 + return false;
  145 + }
  146 + }
  147 +}
  148 +
  149 +
  150 +
  151 +/**
  152 + * 把返回的数据集转换成Tree
  153 + * @param $list array 数据列表
  154 + * @param string|int $pk 主键|root
  155 + * @param string $pid 父id
  156 + * @param string $child 子键
  157 + * @param int $root 获取哪个id下面
  158 + * @param bool $empty_child 当子数据不存在,是否要返回空子数据
  159 + * @return array
  160 + */
  161 +function list_to_tree($list, $pk='id',$pid = 'pid',$child = '_child',$root=0,$empty_child=true) {
  162 + // 如果是数字,则是root
  163 + if(is_numeric($pk)){
  164 + $root = $pk;
  165 + $pk = 'id';
  166 + }
  167 + // 创建Tree
  168 + $tree = array();
  169 + if(is_array($list)) {
  170 + // 创建基于主键的数组引用
  171 + $refer = array();
  172 + foreach ($list as $key => $data) {
  173 + if($empty_child){
  174 + $list[$key][$child] = [];
  175 + }
  176 + $refer[$data[$pk]] =& $list[$key];
  177 + }
  178 + foreach ($list as $key => $data) {
  179 + // 判断是否存在parent
  180 + $parentId = $data[$pid];
  181 + if ($root == $parentId) {
  182 + $tree[] =& $list[$key];
  183 + }else{
  184 + if (isset($refer[$parentId])) {
  185 + $refer[$parentId][$child][] = & $list[$key];
  186 + }
  187 + }
  188 + }
  189 + }
  190 + return $tree;
  191 +}
  192 +
  193 +/**
  194 + * tree数据转list
  195 + * @param $tree
  196 + * @param string $child
  197 + * @return array
  198 + * @author:dc
  199 + * @time 2022/1/11 10:13
  200 + */
  201 +function tree_to_list($tree, $child='_child'){
  202 + $lists = [];
  203 + foreach ($tree as $item){
  204 + $c = $item[$child]??[];
  205 + unset($item[$child]);
  206 + $lists[] = $item;
  207 + if ($c){
  208 + $lists = array_merge($lists,tree_to_list($c, $child));
  209 + }
  210 + }
  211 + return $lists;
  212 +}
  213 +
  214 +if (!function_exists('getThisWeekStarDate')) {
  215 + /**
  216 + * 获取本周一的日期
  217 + * @return mixed
  218 + * @author zbj
  219 + * @date 2023/5/11
  220 + */
  221 + function getThisWeekStarDate()
  222 + {
  223 + return Carbon::now()->startOfWeek()->toDateString();
  224 + }
12 } 225 }
  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Aside\Ai;
  4 +
  5 +use App\Enums\Common\Code;
  6 +use App\Http\Controllers\Aside\BaseController;
  7 +use App\Http\Logic\Aside\Ai\AiCommandLogic;
  8 +use App\Http\Requests\Aside\Ai\AiCommandRequest;
  9 +use App\Models\Ai\AiCommand as AiCommandModel;
  10 +use Illuminate\Http\Request;
  11 +use function App\Helper\send_openai_msg;
  12 +
  13 +/**
  14 + * @name:ai指令
  15 + */
  16 +class AiCommandController extends BaseController
  17 +{
  18 + /**
  19 + * @name :指令列表
  20 + * @return void
  21 + * @author :liyuhang
  22 + * @method
  23 + */
  24 + public function lists(AiCommandModel $aiCommandModel){
  25 + $lists = $aiCommandModel->lists($this->map,$this->page,$this->row,$this->order);
  26 + $this->response('success',Code::SUCCESS,$lists);
  27 + }
  28 +
  29 + /**
  30 + * @name :详情
  31 + * @return void
  32 + * @author :liyuhang
  33 + * @method
  34 + */
  35 + public function info(AiCommandLogic $aiCommandLogic){
  36 + $this->request->validate([
  37 + 'id'=>'required'
  38 + ],[
  39 + 'id.required' => 'ID不能为空'
  40 + ]);
  41 + $aiCommandLogic->ai_info();
  42 + $this->response('success');
  43 + }
  44 + /**
  45 + * @name
  46 + * @return void
  47 + * @author :liyuhang
  48 + * @method
  49 + */
  50 + public function add(AiCommandRequest $request,AiCommandLogic $aiCommandLogic){
  51 + $request->validated();
  52 + $aiCommandLogic->ai_add();
  53 + $this->response('success');
  54 + }
  55 +
  56 + /**
  57 + * @name
  58 + * @return void
  59 + * @author :liyuhang
  60 + * @method
  61 + */
  62 + public function edit(AiCommandRequest $request,AiCommandLogic $aiCommandLogic){
  63 + $request->validate([
  64 + 'id'=>'required'
  65 + ],[
  66 + 'id.required' => 'ID不能为空'
  67 + ]);
  68 + $aiCommandLogic->ai_edit();
  69 + $this->response('success');
  70 + }
  71 +
  72 + /**
  73 + * @name
  74 + * @return void
  75 + * @author :liyuhang
  76 + * @method
  77 + */
  78 + public function del(AiCommandLogic $aiCommandLogic){
  79 + $this->request->validate([
  80 + 'id'=>'required'
  81 + ],[
  82 + 'id.required' => 'ID不能为空'
  83 + ]);
  84 + $aiCommandLogic->ai_del();
  85 + $this->response('success');
  86 + }
  87 +}
  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Aside\Ai;
  4 +
  5 +use App\Enums\Common\Code;
  6 +use App\Http\Controllers\Aside\BaseController;
  7 +use App\Models\Ai\AiLog as AiLogModel;
  8 +
  9 +
  10 +class AiLogController extends BaseController
  11 +{
  12 + /**
  13 + * @name :ai日志列表
  14 + * @return void
  15 + * @author :liyuhang
  16 + * @method
  17 + */
  18 + public function lists(AiLogModel $aiLogModel){
  19 + $lists = $aiLogModel->lists($this->map,$this->page,$this->row,$this->order);
  20 + $this->response('success',Code::SUCCESS,$lists);
  21 + }
  22 +}
@@ -4,19 +4,18 @@ namespace App\Http\Controllers\Aside; @@ -4,19 +4,18 @@ namespace App\Http\Controllers\Aside;
4 4
5 use App\Enums\Common\Code; 5 use App\Enums\Common\Code;
6 use App\Http\Controllers\Controller; 6 use App\Http\Controllers\Controller;
7 -use App\Utils\EncryptUtils;  
8 -use Illuminate\Http\Exceptions\HttpResponseException;  
9 use Illuminate\Http\JsonResponse; 7 use Illuminate\Http\JsonResponse;
10 use Illuminate\Http\Request; 8 use Illuminate\Http\Request;
11 -use Illuminate\Http\Response; 9 +use Illuminate\Http\Exceptions\HttpResponseException;
12 use Illuminate\Support\Facades\Cache; 10 use Illuminate\Support\Facades\Cache;
  11 +use Illuminate\Support\Facades\Session;
13 12
14 -class BaseController extends Controller 13 +class BaseController extends Controller
15 { 14 {
16 protected $param = [];//所有请求参数 15 protected $param = [];//所有请求参数
17 protected $token = ''; //token 16 protected $token = ''; //token
18 protected $request = [];//助手函数 17 protected $request = [];//助手函数
19 - protected $p = 1;//当前页 18 + protected $page = 1;//当前页
20 protected $row = 20;//每页条数 19 protected $row = 20;//每页条数
21 protected $header = [];//设置请求头参数 20 protected $header = [];//设置请求头参数
22 protected $order = 'id'; 21 protected $order = 'id';
@@ -31,23 +30,17 @@ class BaseController extends Controller @@ -31,23 +30,17 @@ class BaseController extends Controller
31 $this->request = $request; 30 $this->request = $request;
32 $this->param = $this->request->all(); 31 $this->param = $this->request->all();
33 $this->token = $this->request->header('token'); 32 $this->token = $this->request->header('token');
34 - $this->get_param();  
35 - $this->auth_token();  
36 - }  
37 -  
38 - /**  
39 - * @name  
40 - * @return void  
41 - * @author :liyuhang  
42 - * @method  
43 - */  
44 - public function auth_token(){  
45 - $info = Cache::get($this->token);  
46 - if(isset($info) && !empty($info)){ 33 + if(!empty($this->token) && !empty(Cache::get($this->token))){
  34 + $info = Cache::get($this->token);
47 $this->user = $info; 35 $this->user = $info;
48 $this->uid = $info['id']; 36 $this->uid = $info['id'];
  37 + //参数处理
  38 + $this->get_param();
49 } 39 }
  40 +
50 } 41 }
  42 +
  43 +
51 /** 44 /**
52 * 成功返回 45 * 成功返回
53 * @param array $data 46 * @param array $data
@@ -68,19 +61,11 @@ class BaseController extends Controller @@ -68,19 +61,11 @@ class BaseController extends Controller
68 'data' => $data, 61 'data' => $data,
69 'msg' => $code->description, 62 'msg' => $code->description,
70 ]; 63 ];
71 - //加密-返回数据  
72 - if (config('app.params_encrypt')) {  
73 - $k = config('app.params_encrypt_key');  
74 - $i = config('app.params_encrypt_iv');  
75 - $response = [  
76 - 'p' => (new EncryptUtils())->openssl_en($response, $k, $i)];  
77 - } 64 + $this->header['token'] = $this->token;
78 return response()->json($response,200,$this->header); 65 return response()->json($response,200,$this->header);
79 } 66 }
80 -  
81 /** 67 /**
82 - * @name 参数过滤  
83 - * @return void 68 + * @name :参数过滤
84 * @author :liyuhang 69 * @author :liyuhang
85 * @method 70 * @method
86 */ 71 */
@@ -94,20 +79,23 @@ class BaseController extends Controller @@ -94,20 +79,23 @@ class BaseController extends Controller
94 case "order": 79 case "order":
95 $this->order = $v; 80 $this->order = $v;
96 break; 81 break;
97 - case 'p':  
98 - $this->p = $v; 82 + case 'page':
  83 + $this->page = $v;
99 break; 84 break;
100 case 'row': 85 case 'row':
101 $this->row = $v; 86 $this->row = $v;
102 break; 87 break;
103 - case "created_at": 88 + case "name":
  89 + $this->map['name'] = ['like','%'.$v.'%'];
  90 + break;
  91 + case "start_at":
104 $this->_btw[0] = $v; 92 $this->_btw[0] = $v;
105 $this->_btw[1] = date('Y-m-d H:i:s',time()); 93 $this->_btw[1] = date('Y-m-d H:i:s',time());
106 - $this->map['create_at'] = ['between', $this->_btw]; 94 + $this->map['created_at'] = ['between', $this->_btw];
107 break; 95 break;
108 - case "updated_at": 96 + case "end_at":
109 $this->_btw[1] = $v; 97 $this->_btw[1] = $v;
110 - $this->map['update_at'] = ['between', $this->_btw]; 98 + $this->map['updated_at'] = ['between', $this->_btw];
111 break; 99 break;
112 default: 100 default:
113 if (!empty($v)) { 101 if (!empty($v)) {
@@ -116,20 +104,20 @@ class BaseController extends Controller @@ -116,20 +104,20 @@ class BaseController extends Controller
116 break; 104 break;
117 } 105 }
118 } 106 }
119 -  
120 } 107 }
121 /** 108 /**
122 * @name 统一返回参数 109 * @name 统一返回参数
123 - * @return void 110 + * @return JsonResponse
124 * @author :liyuhang 111 * @author :liyuhang
125 * @method 112 * @method
126 */ 113 */
127 - public function response($msg,$code = 200,$data = [],$result_code = null,$type = 'application/json'){  
128 - $result_code === null && $result_code = $code; 114 + public function response($msg = null,string $code = Code::SUCCESS,$data = [],$result_code = 200,$type = 'application/json'): JsonResponse
  115 + {
  116 + $code = Code::fromValue($code);
129 $result = [ 117 $result = [
130 - 'msg' =>$msg,  
131 - 'code'=>$result_code,  
132 - 'data'=>$data 118 + 'msg' => $msg == ' ' ? $code->description : $msg,
  119 + 'code' => $code->value,
  120 + 'data' => $this->_extents($data),
133 ]; 121 ];
134 $this->header['Content-Type'] = $type; 122 $this->header['Content-Type'] = $type;
135 $this->header['token'] = $this->token; 123 $this->header['token'] = $this->token;
@@ -137,25 +125,40 @@ class BaseController extends Controller @@ -137,25 +125,40 @@ class BaseController extends Controller
137 throw new HttpResponseException($response); 125 throw new HttpResponseException($response);
138 } 126 }
139 127
  128 +
140 /** 129 /**
141 - * @name :上传图片  
142 - * @return void 130 + * @param $data
  131 + * @name :返回参数统一处理
  132 + * @return array|string
143 * @author :liyuhang 133 * @author :liyuhang
144 * @method 134 * @method
145 */ 135 */
146 - public function uploads(){  
147 - $files = $this->request->file('file');  
148 - if(empty($files)){  
149 - return $this->response('没有上传文件',Code::USER_ERROR); 136 + protected function _extents($data) {
  137 +
  138 + if (empty($data) || !is_array($data)) {
  139 + return empty($data) ? is_array($data) ? [] : '' : $data;
150 } 140 }
151 - $url = './uploads/images/';  
152 - $param = $this->request->post();  
153 - if($this->request->hasFile('image') && $files->isValid()){  
154 - $filename = date('ymdHis').rand(10000,99999).$this->request->file('image');  
155 - $this->request->file('image')->move('./uploads/images/',$filename);  
156 - }else{  
157 - return false; 141 + foreach ($data as $k => $v) {
  142 + if (is_array($v)) {
  143 + $data[$k] = $this->_extents($v);
  144 + } else {
  145 + if (is_null($v)) {
  146 + $data[$k] = '';
  147 + continue;
  148 + }
  149 + switch ((string) $k) {
  150 + case 'image':
  151 + $v['image_link'] = url('/a/image/' . $v);
  152 + break;
  153 + }
  154 + }
158 } 155 }
159 - return $url.$filename; 156 + return $data;
160 } 157 }
  158 +
  159 +
  160 +
  161 +
  162 +
  163 +
161 } 164 }
1 -<?php  
2 -  
3 -namespace App\Http\Controllers\Aside;  
4 -  
5 -use App\Http\Logic\Aside\DemoLogic;  
6 -use App\Http\Requests\Aside\DemoRequest;  
7 -  
8 -class DemoController extends BaseController  
9 -{  
10 - /**  
11 - * Deom控制器  
12 - * @param DemoRequest $request  
13 - * @param DemoLogic $logic  
14 - * @return \Illuminate\Http\JsonResponse  
15 - * @throws \Psr\Container\ContainerExceptionInterface  
16 - * @throws \Psr\Container\NotFoundExceptionInterface  
17 - */  
18 - public function test(DemoRequest $request,DemoLogic $logic)  
19 - {  
20 - $request->validated();  
21 - $data=$logic->testLogic();  
22 - return $this->success($data);  
23 - }  
24 -}  
  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Aside\Devops;
  4 +
  5 +use App\Http\Controllers\Aside\BaseController;
  6 +
  7 +use App\Http\Logic\Aside\Devops\ServerConfigLogic;
  8 +use App\Http\Requests\Aside\Devops\ServerConfigRequest;
  9 +use Illuminate\Http\Request;
  10 +use Illuminate\Support\Str;
  11 +use Illuminate\Validation\Rule;
  12 +
  13 +/**
  14 + * 项目服务器、数据库配置
  15 + * Class ServerConfigController
  16 + * @package App\Http\Controllers\Aside
  17 + * @author zbj
  18 + * @date 2023/4/24
  19 + */
  20 +class ServerConfigController extends BaseController
  21 +{
  22 +
  23 + /**
  24 + * 保存配置
  25 + * @param ServerConfigRequest $request
  26 + * @param ServerConfigLogic $logic
  27 + * @author zbj
  28 + * @date 2023/4/23
  29 + */
  30 + public function save(ServerConfigRequest $request, ServerConfigLogic $logic){
  31 + $data = $logic->save($this->param);
  32 + return $this->success($data);
  33 + }
  34 +
  35 + /**
  36 + * 更新表结构
  37 + * @param ServerConfigLogic $logic
  38 + * @author zbj
  39 + * @date 2023/4/24
  40 + */
  41 + public function updateDatabase(Request $request, ServerConfigLogic $logic){
  42 + $request->validate([
  43 + 'type' => 'in:1,2,3',
  44 + 'id'=> Rule::requiredIf($request->type == 1),
  45 + 'sql' => ['required', function ($attribute, $value, $fail) {
  46 + if(Str::contains(Str::lower($value), ['drop', 'delete', 'truncate'])){
  47 + $fail('危险操作');
  48 + }
  49 + }]
  50 + ],[
  51 + 'id.required' => 'ID不能为空',
  52 + 'sql.required' => '请输入Sql语句',
  53 + ]);
  54 +
  55 + switch ($this->param['type']){
  56 + case "1":
  57 + $data = $logic->updateTable($this->param);
  58 + break;
  59 + case "2":
  60 + $data = $logic->updateLocalTable($this->param);
  61 + break;
  62 + case "3":
  63 + $data = $logic->updateAllTable($this->param);
  64 + break;
  65 + }
  66 +
  67 + return $this->success($data);
  68 + }
  69 +
  70 + /**
  71 + * 更新代码
  72 + * @param ServerConfigLogic $logic
  73 + * @author zbj
  74 + * @date 2023/4/24
  75 + */
  76 + public function updateCode(){
  77 + //todo
  78 + //C端
  79 +// $process = new Process(['git', 'pull']);
  80 +// $process->run();
  81 +// dump($process->getExitCodeText());
  82 +// dump($process->getExitCode());
  83 +// dump($process->getErrorOutput());
  84 +// $output = explode(PHP_EOL, $process->getOutput());
  85 +// dump($output);
  86 +// exit;
  87 + }
  88 +}
  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Aside;
  4 +
  5 +use App\Http\Controllers\Controller;
  6 +use Illuminate\Http\Request;
  7 +
  8 +/**
  9 + * Class IndexController
  10 + * @package App\Http\Controllers\Aside
  11 + * @author zbj
  12 + * @date 2023/4/19
  13 + */
  14 +class IndexController extends Controller
  15 +{
  16 + /**
  17 + * 首页
  18 + * @param Request $request
  19 + * @return \Illuminate\Http\JsonResponse
  20 + */
  21 + public function index(Request $request)
  22 + {
  23 +
  24 + }
  25 +
  26 +}
  1 +<?php
  2 +
  3 +
  4 +namespace App\Http\Controllers\Aside;
  5 +
  6 +use App\Http\Logic\Aside\LoginLogic;
  7 +use App\Rules\Mobile;
  8 +use Illuminate\Http\Request;
  9 +
  10 +/**
  11 + * Class LoginController
  12 + * @package App\Http\Controllers\Aside
  13 + * @author zbj
  14 + * @date 2023/4/19
  15 + */
  16 +class LoginController extends BaseController
  17 +{
  18 +
  19 + function login(Request $request, LoginLogic $logic)
  20 + {
  21 + if ($request->isMethod('POST')) {
  22 + $request->validate([
  23 + 'mobile' => ['required', new Mobile()],
  24 + 'password' => 'required',
  25 + ], [
  26 + 'mobile.required' => '请输入手机号',
  27 + 'password.required' => '请输入密码',
  28 + ]);
  29 +
  30 + $logic->login();
  31 +
  32 + return $this->success();
  33 + }
  34 + if($logic->manage()){
  35 + return redirect(route('admin.home.white'));
  36 + }
  37 + return view('admin.login');
  38 + }
  39 +
  40 + public function logout(LoginLogic $logic)
  41 + {
  42 + return $logic->logout();
  43 + }
  44 +}
  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Aside\Mail;
  4 +
  5 +use App\Enums\Common\Code;
  6 +use App\Http\Controllers\Aside\BaseController;
  7 +use App\Http\Logic\Aside\Mail\MailLogic;
  8 +use App\Http\Requests\Aside\Mail\MailRequest;
  9 +use App\Models\Mail\Mail as MailModel;
  10 +
  11 +/**
  12 + * @name:站内信
  13 + */
  14 +class MailController extends BaseController
  15 +{
  16 + public function lists(){
  17 + $mailModel = new MailModel();
  18 + $lists = $mailModel->lists($this->map,$this->page,$this->row,$this->order);
  19 + $this->response('列表',Code::SUCCESS,$lists);
  20 + }
  21 +
  22 + /**
  23 + * @name :详情
  24 + * @return void
  25 + * @author :liyuhang
  26 + * @method
  27 + */
  28 + public function info(MailLogic $mailLogic){
  29 + $this->request->validate([
  30 + 'id'=>'required'
  31 + ],[
  32 + 'id.required' => 'ID不能为空'
  33 + ]);
  34 + $info = $mailLogic->mail_info();
  35 + $this->response('success',Code::SUCCESS,$info);
  36 + }
  37 +
  38 +
  39 + /**
  40 + * @name :添加站内信
  41 + * @return void
  42 + * @author :liyuhang
  43 + * @method
  44 + */
  45 + public function add(MailRequest $mailRequest,MailLogic $mailLogic){
  46 + $mailRequest->validated();
  47 + $mailLogic->mail_add();
  48 + $this->response('success');
  49 + }
  50 +
  51 + /**
  52 + * @name :编辑站内信
  53 + * @return void
  54 + * @author :liyuhang
  55 + * @method
  56 + */
  57 + public function edit(MailRequest $mailRequest,MailLogic $mailLogic){
  58 + $mailRequest->validate([
  59 + 'id'=>'required'
  60 + ],[
  61 + 'id.required' => 'ID不能为空'
  62 + ]);
  63 + $mailLogic->mail_edit();
  64 + $this->response('success');
  65 + }
  66 +
  67 + /**
  68 + * @name :逻辑删除站内信
  69 + * @return void
  70 + * @author :liyuhang
  71 + * @method
  72 + */
  73 + public function del(MailLogic $mailLogic){
  74 + $this->request->validate([
  75 + 'id'=>'required'
  76 + ],[
  77 + 'id.required' => 'ID不能为空'
  78 + ]);
  79 + $mailLogic->mail_del();
  80 + $this->response('success');
  81 + }
  82 +}
  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Aside\Manage;
  4 +
  5 +use App\Helper\Arr;
  6 +use App\Http\Controllers\Aside\BaseController;
  7 +use App\Http\Logic\Aside\Manage\DeptLogic;
  8 +use App\Http\Requests\Aside\Manage\DeptRequest;
  9 +use App\Rules\Ids;
  10 +use Illuminate\Http\Request;
  11 +
  12 +/**
  13 + * Class DeptController
  14 + * @package App\Http\Controllers\Aside
  15 + * @author zbj
  16 + * @date 2023/4/20
  17 + */
  18 +class DeptController extends BaseController
  19 +{
  20 +
  21 + public function list(DeptLogic $logic)
  22 + {
  23 + $map = [];
  24 + if(!empty($this->param['search'])){
  25 + $map[] = ['title', 'like', "%{$this->param['search']}%"];
  26 + }
  27 + $sort = ['id' => 'desc'];
  28 + $data = $logic->getList($map, $sort, ['id', 'pid', 'title'],0);
  29 +
  30 + return view("admin.dept", ["list" => Arr::listToTree($data)]);
  31 + }
  32 +
  33 + public function info(Request $request, DeptLogic $logic){
  34 + $request->validate([
  35 + 'id'=>'required'
  36 + ],[
  37 + 'id.required' => 'ID不能为空'
  38 + ]);
  39 + $data = $logic->getInfo($this->param['id']);
  40 + return $this->success(Arr::twoKeepKeys($data, ['id', 'pid', 'title', 'manager_uids', 'remark']));
  41 + }
  42 +
  43 + public function save(DeptRequest $request, DeptLogic $logic)
  44 + {
  45 + $data = $logic->save($this->param);
  46 + return $this->success($data);
  47 + }
  48 +
  49 + public function delete(Request $request, DeptLogic $logic)
  50 + {
  51 + $request->validate([
  52 + 'ids'=>['required', new Ids()]
  53 + ],[
  54 + 'ids.required' => 'ID不能为空'
  55 + ]);
  56 +
  57 + $data = $logic->delete($this->param['ids']);
  58 + return $this->success($data);
  59 + }
  60 +}
  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Aside\Manage;
  4 +
  5 +use App\Helper\Arr;
  6 +use App\Http\Controllers\Aside\BaseController;
  7 +use App\Http\Logic\Aside\Manage\GroupLogic;
  8 +use App\Http\Requests\Aside\Manage\GroupRequest;
  9 +use App\Rules\Ids;
  10 +use Illuminate\Http\Request;
  11 +
  12 +/**
  13 + * 用户组
  14 + * Class Group
  15 + * @package App\Http\Controllers\Aside
  16 + * @author zbj
  17 + * @date 2023/4/19
  18 + */
  19 +class GroupController extends BaseController
  20 +{
  21 +
  22 + public function list(Request $request, GroupLogic $logic)
  23 + {
  24 + $list = $logic->getList();
  25 + return view("admin.group", ["list" => $list]);
  26 + }
  27 +
  28 + public function info(Request $request, GroupLogic $logic){
  29 + $request->validate([
  30 + 'id'=>'required'
  31 + ],[
  32 + 'id.required' => 'ID不能为空'
  33 + ]);
  34 + $data = $logic->getInfo($this->param['id']);
  35 + return $this->success($data);
  36 + }
  37 +
  38 + public function save(GroupRequest $request, GroupLogic $logic){
  39 + $data = $logic->save($this->param);
  40 + return $this->success($data);
  41 + }
  42 +
  43 + public function delete(Request $request, GroupLogic $logic){
  44 + $request->validate([
  45 + 'ids'=>['required', new Ids()]
  46 + ],[
  47 + 'ids.required' => 'ID不能为空'
  48 + ]);
  49 +
  50 + $data = $logic->delete($this->param['ids']);
  51 + return $this->success($data);
  52 + }
  53 +
  54 +}
  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Aside\Manage;
  4 +
  5 +use App\Helper\Arr;
  6 +use App\Http\Controllers\Aside\BaseController;
  7 +use App\Http\Logic\Aside\Manage\ManageLogic;
  8 +use App\Http\Requests\Aside\Manage\ManageRequest;
  9 +use App\Rules\Ids;
  10 +use Illuminate\Http\Request;
  11 +
  12 +/**
  13 + * 后台用户
  14 + * Class ManageController
  15 + * @package App\Http\Controllers\Aside
  16 + * @author zbj
  17 + * @date 2023/4/20
  18 + */
  19 +class ManageController extends BaseController
  20 +{
  21 +
  22 + public function list(Request $request, ManageLogic $logic)
  23 + {
  24 + $list = $logic->getList();
  25 + return view("admin.manage", ["list" => $list]);
  26 + }
  27 +
  28 + public function info(Request $request, ManageLogic $logic){
  29 + $request->validate([
  30 + 'id'=>'required'
  31 + ],[
  32 + 'id.required' => 'ID不能为空'
  33 + ]);
  34 + $data = $logic->getInfo($this->param['id']);
  35 + return $this->success($data);
  36 + }
  37 +
  38 + public function save(ManageRequest $request, ManageLogic $logic){
  39 + $data = $logic->save($this->param);
  40 + return $this->success($data);
  41 + }
  42 +
  43 + public function delete(Request $request, ManageLogic $logic){
  44 + $request->validate([
  45 + 'ids'=>['required', new Ids()]
  46 + ],[
  47 + 'ids.required' => 'ID不能为空'
  48 + ]);
  49 +
  50 + $data = $logic->delete($this->param['ids']);
  51 + return $this->success($data);
  52 + }
  53 +
  54 +}
  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Aside\Manage;
  4 +
  5 +use App\Helper\Arr;
  6 +use App\Http\Controllers\Aside\BaseController;
  7 +use App\Http\Logic\Aside\Manage\MenuLogic;
  8 +use App\Http\Requests\Aside\Manage\MenuRequest;
  9 +use App\Rules\Ids;
  10 +use Illuminate\Http\Request;
  11 +
  12 +/**
  13 + * 后台菜单
  14 + * Class MenuController
  15 + * @package App\Http\Controllers\Aside
  16 + * @author zbj
  17 + * @date 2023/4/19
  18 + */
  19 +class MenuController extends BaseController
  20 +{
  21 +
  22 + public function list(Request $request, MenuLogic $logic)
  23 + {
  24 + $map = [];
  25 + $sort = ['id' => 'desc'];
  26 + $list = $logic->getList($map, $sort, ['*'],0);
  27 + return view("admin.menu", ["list" => Arr::listToTree($list)]);
  28 + }
  29 +
  30 + public function info(Request $request, MenuLogic $logic){
  31 + $request->validate([
  32 + 'id'=>'required'
  33 + ],[
  34 + 'id.required' => 'ID不能为空'
  35 + ]);
  36 + $data = $logic->getInfo($this->param['id']);
  37 + return $this->success($data);
  38 + }
  39 +
  40 + public function save(MenuRequest $request, MenuLogic $logic){
  41 + $data = $logic->save($this->param);
  42 + return $this->success($data);
  43 + }
  44 +
  45 + public function delete(Request $request, MenuLogic $logic){
  46 + $request->validate([
  47 + 'ids'=>['required', new Ids()]
  48 + ],[
  49 + 'ids.required' => 'ID不能为空'
  50 + ]);
  51 +
  52 + $data = $logic->delete($this->param['ids']);
  53 + return $this->success($data);
  54 + }
  55 +
  56 +}