作者 刘锟

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

正在显示 46 个修改的文件 包含 4401 行增加69 行删除

要显示太多修改。

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

@@ -9,20 +9,13 @@ namespace App\Console\Commands\KeywordInVideo; @@ -9,20 +9,13 @@ namespace App\Console\Commands\KeywordInVideo;
9 9
10 use App\Console\Commands\Model; 10 use App\Console\Commands\Model;
11 use App\Console\Commands\TaskSub; 11 use App\Console\Commands\TaskSub;
12 -use App\Enums\Common\Code;  
13 use App\Models\Com\KeywordVideoTask; 12 use App\Models\Com\KeywordVideoTask;
14 use App\Models\Com\KeywordVideoTaskLog; 13 use App\Models\Com\KeywordVideoTaskLog;
15 use App\Models\Domain\DomainInfo; 14 use App\Models\Domain\DomainInfo;
16 use App\Models\Product\Keyword; 15 use App\Models\Product\Keyword;
17 use App\Models\Product\Product; 16 use App\Models\Product\Product;
18 -use App\Models\RouteMap\RouteMap;  
19 -use App\Models\Template\BSettingTemplate;  
20 -use App\Models\Template\BTemplateCommon;  
21 -use App\Models\Template\Setting;  
22 use App\Services\ProjectServer; 17 use App\Services\ProjectServer;
23 use Illuminate\Console\Command; 18 use Illuminate\Console\Command;
24 -use Illuminate\Support\Facades\Cache;  
25 -use Illuminate\Support\Facades\DB;  
26 use Illuminate\Support\Facades\Http; 19 use Illuminate\Support\Facades\Http;
27 use Illuminate\Support\Facades\Log; 20 use Illuminate\Support\Facades\Log;
28 21
@@ -156,8 +149,11 @@ class VideoTask extends Command @@ -156,8 +149,11 @@ class VideoTask extends Command
156 'is_ytb'=>true 149 'is_ytb'=>true
157 ]; 150 ];
158 $result = Http::post('http://216.250.255.116:7866/create_task', $data); 151 $result = Http::post('http://216.250.255.116:7866/create_task', $data);
  152 + $res_json = json_decode($result,true);
159 $val->task_id = $task_id; 153 $val->task_id = $task_id;
  154 + if(isset($res_json['code']) && ($res_json['code'] == 200)){
160 $val->status = KeywordVideoTaskLog::STATUS_RUNNING; 155 $val->status = KeywordVideoTaskLog::STATUS_RUNNING;
  156 + }
161 $val->result_info = $result; 157 $val->result_info = $result;
162 $val->save(); 158 $val->save();
163 } 159 }
@@ -196,7 +196,56 @@ if (!function_exists('checkDomain')) { @@ -196,7 +196,56 @@ if (!function_exists('checkDomain')) {
196 } 196 }
197 } 197 }
198 198
  199 +if (!function_exists('page_init')) {
  200 + /**
  201 + * amp分页初始化
  202 + * @param $page
  203 + * @param $total
  204 + * @author Akun
  205 + * @date 2024/01/29 15:43
  206 + */
  207 + function page_init($page, $total)
  208 + {
  209 + //中间页处理
  210 + $center_page = [];
  211 + if ($total <= 5) {
  212 + for ($i = 1; $i <= $total; $i++) {
  213 + $center_page[] = $i;
  214 + }
  215 + } else {
  216 + if ($page < 5) {
  217 + for ($i = 1; $i <= 5; $i++) {
  218 + $center_page[] = $i;
  219 + }
  220 + } else {
  221 + if ($page == $total) {
  222 + for ($i = $total - 5; $i <= $total; $i++) {
  223 + $center_page[] = $i;
  224 + }
  225 + } else if ($page <= $total) {
  226 + if ($total - $page <= 5) {
  227 + if ($total - $page == 1) {
  228 + for ($i = $total - 4; $i <= $total; $i++) {
  229 + $center_page[] = $i;
  230 + }
  231 + } else {
  232 + for ($i = $page - 2; $i <= $page + 2; $i++) {
  233 + $center_page[] = $i;
  234 + }
  235 + }
  236 + } else {
  237 + for ($i = $page - 2; $i <= $page + 2; $i++) {
  238 + $center_page[] = $i;
  239 + }
  240 + }
  241 + }
199 242
  243 + }
  244 + }
  245 +
  246 + return $center_page;
  247 + }
  248 +}
200 /** 249 /**
201 * 把返回的数据集转换成Tree 250 * 把返回的数据集转换成Tree
202 * @param $list array 数据列表 251 * @param $list array 数据列表
@@ -240,6 +289,37 @@ function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root @@ -240,6 +289,37 @@ function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root
240 return $tree; 289 return $tree;
241 } 290 }
242 291
  292 +if (!function_exists('special2str')) {
  293 + /**
  294 + * 特殊字符串替换
  295 + * @param $str
  296 + * @return string|string[]
  297 + * @author Akun
  298 + * @date 2024/01/30 17:46
  299 + */
  300 + function special2str($str)
  301 + {
  302 + if (strpos($str, ';') === false) {
  303 + return $str;
  304 + }
  305 +
  306 + $list = [
  307 + '&lt;' => '<',
  308 + '&gt;' => '>',
  309 + '&amp;' => '&',
  310 + '&acute;' => '´',
  311 + '&quot;' => '“',
  312 + '&nbsp;' => ' '
  313 + ];
  314 +
  315 + foreach ($list as $k => $v) {
  316 + $str = str_replace($k, $v, $str);
  317 + }
  318 +
  319 + return $str;
  320 + }
  321 +}
  322 +
243 /** 323 /**
244 * tree数据转list 324 * tree数据转list
245 * @param $tree 325 * @param $tree
@@ -2,10 +2,14 @@ @@ -2,10 +2,14 @@
2 2
3 namespace App\Http\Controllers\Api; 3 namespace App\Http\Controllers\Api;
4 4
  5 +use App\Enums\Common\Code;
5 use App\Exceptions\InquiryFilterException; 6 use App\Exceptions\InquiryFilterException;
6 use App\Models\SyncSubmitTask\SyncSubmitTask; 7 use App\Models\SyncSubmitTask\SyncSubmitTask;
  8 +use App\Models\Visit\Visit;
7 use App\Services\CosService; 9 use App\Services\CosService;
  10 +use App\Services\ProjectServer;
8 use Illuminate\Http\Request; 11 use Illuminate\Http\Request;
  12 +use Illuminate\Support\Facades\DB;
9 13
10 /** 14 /**
11 * Class InquiryController 15 * Class InquiryController
@@ -51,4 +55,39 @@ class InquiryController extends BaseController @@ -51,4 +55,39 @@ class InquiryController extends BaseController
51 } 55 }
52 return $this->success(); 56 return $this->success();
53 } 57 }
  58 +
  59 + /**
  60 + * @remark :修改
  61 + * @name :editInquiryStatus
  62 + * @author :lyh
  63 + * @method :post
  64 + * @time :2024/3/22 15:41
  65 + */
  66 + public function editInquiryStatus(){
  67 + $this->request->validate([
  68 + 'project_id'=>'required',
  69 + 'ip'=>'required',
  70 + 'updated_date'=>'required',
  71 + ],[
  72 + 'project_id.required' => 'project_id不能为空',
  73 + 'ip.required' => 'ip不能为空',
  74 + 'updated_date.required' => '日期不能为空',
  75 + ]);
  76 + ProjectServer::useProject($this->param['project_id']);
  77 + $customerVisitModel = new Visit();
  78 + $info = $customerVisitModel->read([
  79 + 'ip'=>$this->param['ip'],
  80 + 'updated_date'=>$this->param['updated_date']
  81 + ]);
  82 + if($info === false){
  83 + $this->response('当前记录不存在',Code::SYSTEM_ERROR);
  84 + }
  85 + try {
  86 + $customerVisitModel->edit(['is_inquiry'=>1],['id'=>$info['id']]);
  87 + }catch (\Exception $e){
  88 + $this->response('操作失败',Code::SYSTEM_ERROR);
  89 + }
  90 + DB::disconnect('custom_mysql');
  91 + $this->response('success');
  92 + }
54 } 93 }
@@ -3,7 +3,12 @@ @@ -3,7 +3,12 @@
3 namespace App\Http\Controllers\Api; 3 namespace App\Http\Controllers\Api;
4 4
5 use App\Enums\Common\Code; 5 use App\Enums\Common\Code;
  6 +use App\Helper\Translate;
  7 +use App\Models\Product\Category;
  8 +use App\Models\Product\CategoryRelated;
6 use App\Models\Product\Product; 9 use App\Models\Product\Product;
  10 +use App\Models\RouteMap\RouteMap;
  11 +use App\Services\CosService;
7 use App\Services\ProjectServer; 12 use App\Services\ProjectServer;
8 use App\Utils\LogUtils; 13 use App\Utils\LogUtils;
9 use Illuminate\Http\Request; 14 use Illuminate\Http\Request;
@@ -25,7 +30,6 @@ class ProductController extends BaseController @@ -25,7 +30,6 @@ class ProductController extends BaseController
25 public function getImages(Request $request) 30 public function getImages(Request $request)
26 { 31 {
27 $project_id = $request->input('project_id'); 32 $project_id = $request->input('project_id');
28 -  
29 $project = ProjectServer::useProject($project_id); 33 $project = ProjectServer::useProject($project_id);
30 if (!$project) { 34 if (!$project) {
31 $this->response('项目不存在', Code::SYSTEM_ERROR); 35 $this->response('项目不存在', Code::SYSTEM_ERROR);
@@ -43,4 +47,208 @@ class ProductController extends BaseController @@ -43,4 +47,208 @@ class ProductController extends BaseController
43 } 47 }
44 $this->response('success', Code::SUCCESS, $info); 48 $this->response('success', Code::SUCCESS, $info);
45 } 49 }
  50 +
  51 + /**
  52 + * @remark :保存产品
  53 + * @name :saveProduct
  54 + * @author :lyh
  55 + * @method :post
  56 + * @time :2024/3/20 11:09
  57 + */
  58 + public function saveProduct(){
  59 + $api_key = '8242LYUGaOfUQ1koc4Rq6MhEEOG7NW68oRaB7iO9coJDjG5L5gA1Q';
  60 + if($this->request->header('api-key') != $api_key){
  61 + $this->response('非法请求',Code::SYSTEM_ERROR);
  62 + }
  63 + $this->request->validate([
  64 + 'project_id'=>'required',
  65 + 'title'=>'required',
  66 + ],[
  67 + 'project_id.required' => 'project_id不能为空',
  68 + 'title.required' => 'title不能为空',
  69 + ]);
  70 + $project = ProjectServer::useProject($this->param['project_id']);
  71 + if (!$project) {
  72 + $this->response('项目不存在', Code::SYSTEM_ERROR);
  73 + }
  74 + //处理图片
  75 + $imageInfo = $this->handleImage($this->param['image'],$this->param['project_id']);
  76 + $thumb = $imageInfo['thumb'];
  77 + $gallery = $imageInfo['gallery'];
  78 + //处理分类
  79 + $category_id = $this->handleCategory($this->param['category_name'],$this->param['project_id']);
  80 + try {
  81 + $productModel = new Product();
  82 + $productInfo = $productModel->read(['title'=>$this->param['title']]);
  83 + if($productInfo === false){
  84 + $productData = [
  85 + 'project_id'=>$this->param['project_id'],
  86 + 'title'=>$this->param['title'],
  87 + 'intro'=>$this->param['intro'] ?? '',
  88 + 'content'=>$this->param['content'] ?? '',
  89 + 'thumb'=>json_encode($thumb,true),
  90 + 'gallery'=>json_encode($gallery,true),
  91 + 'created_at'=>date('Y-m-d H:i:s'),
  92 + 'updated_at'=>date('Y-m-d H:i:s')
  93 + ];
  94 + if(!empty($category_id)){
  95 + $productData['category_id'] = ','.$category_id.',';
  96 + }
  97 + $product_id = $productModel->addReturnId($productData);
  98 + $route = RouteMap::setRoute($productData['title'], RouteMap::SOURCE_PRODUCT, $product_id, $this->param['project_id']);
  99 + $productModel->edit(['route'=>$route],['id'=>$product_id]);
  100 + //添加到关联分类
  101 + CategoryRelated::saveRelated($product_id, [$category_id]);
  102 + }
  103 + } catch (\Exception $e) {
  104 + LogUtils::error('Project Id: ' . $this->param['project_id'] . ' saveProduct error:' . $e->getMessage());
  105 + $this->response('保存失败,请联系管理员',Code::SYSTEM_ERROR);
  106 + }
  107 + $this->response('success');
  108 + }
  109 +
  110 + /**
  111 + * @remark :处理图片
  112 + * @name :handleImage
  113 + * @author :lyh
  114 + * @method :post
  115 + * @time :2024/3/20 14:44
  116 + */
  117 + public function handleImage($image,$project_id){
  118 + $gallery = [];
  119 + $thumb = [];
  120 + if(!empty($image) && is_array($image)){
  121 + foreach ($image as $k => $v){
  122 + //TODO::图片转存
  123 + $url = CosService::uploadRemote($project_id,'image_product',$v);
  124 + if($k == 0){
  125 + $thumb = ['url'=>$url,'alt'=>''];
  126 + }
  127 + $gallery[] = ['url'=>$url,'alt'=>''];
  128 + }
  129 + }
  130 + return ['thumb'=>$thumb,'gallery'=>$gallery];
  131 + }
  132 +
  133 + /**
  134 + * @remark :处理分类
  135 + * @name :handleCategory
  136 + * @author :lyh
  137 + * @method :post
  138 + * @time :2024/3/20 14:48
  139 + */
  140 + public function handleCategory($category_name,$project_id){
  141 + $category_id = '';
  142 + if(isset($category_name) && !empty($category_name)){
  143 + $categoryModel = new Category();
  144 + $cateInfo = $categoryModel->read(['title'=>$this->param['category_name']]);
  145 + if($cateInfo === false){
  146 + $cateData =[
  147 + 'project_id'=>$project_id,
  148 + 'title'=>$category_name,
  149 + 'pid'=>0,
  150 + 'created_at'=>date('Y-m-d H:i:s'),
  151 + 'updated_at'=>date('Y-m-d H:i:s')
  152 + ];
  153 + $cate_id = $categoryModel->addReturnId($cateData);
  154 + $route = RouteMap::setRoute($cateData['title'], RouteMap::SOURCE_PRODUCT_CATE, $cate_id, $project_id);
  155 + $categoryModel->edit(['route'=>$route],['id'=>$cate_id]);
  156 + }else{
  157 + $cate_id = $cateInfo['id'];
  158 + }
  159 + $category_id = $cate_id;
  160 + }
  161 + return $category_id;
  162 + }
  163 +
  164 + /**
  165 + * @param Request $request
  166 + * @author zbj
  167 + * @date 2024/1/22
  168 + */
  169 + protected function searchProduct(Request $request)
  170 + {
  171 + $project_id = $request->input('project_id');
  172 + $limit = $request->input('limit') ?: 5;
  173 + $text = $request->input('text');
  174 + $key = $request->input('key') ?: 'title';
  175 + $key_limit = $request->input('key_limit') ?: 15;
  176 +
  177 + $project = ProjectServer::useProject($project_id);
  178 + if (!$project) {
  179 + $this->response('项目不存在', Code::SYSTEM_ERROR);
  180 + }
  181 +
  182 + //匹配产品
  183 + $products = Product::with('category')
  184 + ->where("title", 'like', $text . '%')
  185 + ->where("status", 1)
  186 + ->orderBy("id", "DESC")
  187 + ->limit($limit)
  188 + ->select('title', 'thumb', 'id', 'route')
  189 + ->get()
  190 + ->toArray();
  191 +
  192 + //对应分类
  193 + $categories = [];
  194 + foreach ($products as &$product) {
  195 + foreach ($product['category'] as $category) {
  196 + $categories[$category['route']] = [
  197 + 'title' => $category['title'],
  198 + 'route' => '/' . $category['route'] . '/',
  199 + ];
  200 + }
  201 + unset($product['id']);
  202 + unset($product['category']);
  203 +
  204 + if(!empty($product['thumb']) && !empty($product['thumb']['url'])){
  205 + $product['thumb'] = getImageUrl($product['thumb']['url'],$project['storage_type'] ?? 0,$project['project_location']);
  206 + }
  207 +
  208 + $product['route'] = '/' . $product['route'] . '/';
  209 + }
  210 +
  211 + $data = [
  212 + 'products' => $products,
  213 + 'categories' => array_values($categories),
  214 + 'suggestions' => $this->searchSuggestion($text, $key, $key_limit)
  215 + ];
  216 +
  217 + $this->response('success', Code::SUCCESS, $data);
  218 +
  219 + }
  220 +
  221 + protected function searchSuggestion($text, $key, $key_limit): array
  222 + {
  223 + $model = new Product();
  224 + $columns = $model->getConnection()->getSchemaBuilder()->getColumnListing($model->getTable());
  225 +
  226 + //产品字段
  227 + if (in_array($key, $columns)) {
  228 + //匹配产品
  229 + $suggestions = Product::where("status", 1)
  230 + ->where($key, 'like', $text . '%')
  231 + ->orderBy("id", "DESC")
  232 + ->limit($key_limit)
  233 + ->select($key .' as title', 'route')
  234 + ->get()
  235 + ->toArray();
  236 + } else {
  237 + //扩展字段
  238 + $suggestions = Product::leftJoin('gl_product_extend_info as pei', 'gl_product.id', '=', 'pei.product_id')
  239 + ->where('pei.values', 'like', $text . '%')
  240 + ->where("gl_product.status", 1)
  241 + ->orderBy("gl_product.id", "DESC")
  242 + ->limit($key_limit)
  243 + ->select('pei.values','gl_product.route')
  244 + ->get()
  245 + ->toArray();
  246 + }
  247 +
  248 + foreach ($suggestions as &$suggestion){
  249 + $suggestion['route'] = '/' . $suggestion['route'] . '/';
  250 + }
  251 +
  252 + return $suggestions;
  253 + }
46 } 254 }
@@ -8,6 +8,7 @@ use App\Http\Logic\Bside\News\NewsLogic; @@ -8,6 +8,7 @@ use App\Http\Logic\Bside\News\NewsLogic;
8 use App\Http\Requests\Bside\News\NewsRequest; 8 use App\Http\Requests\Bside\News\NewsRequest;
9 use App\Models\News\News as NewsModel; 9 use App\Models\News\News as NewsModel;
10 use App\Models\News\NewsCategory; 10 use App\Models\News\NewsCategory;
  11 +use App\Models\Product\Product;
11 use App\Models\RouteMap\RouteMap; 12 use App\Models\RouteMap\RouteMap;
12 use App\Models\Template\BTemplate; 13 use App\Models\Template\BTemplate;
13 use App\Models\Template\Setting; 14 use App\Models\Template\Setting;
@@ -313,7 +314,20 @@ class NewsController extends BaseController @@ -313,7 +314,20 @@ class NewsController extends BaseController
313 ],[ 314 ],[
314 'keyword.required' => 'keyword不能为空', 315 'keyword.required' => 'keyword不能为空',
315 ]); 316 ]);
316 - $data = http_get('http://gnews.globalso.com/gnews_news.php?keyword='.$this->param['keyword'],['charset=utf-8']); 317 + $data = curl_c('http://gnews.globalso.com/gnews_news.php?keyword='.$this->param['keyword'],false);
317 $this->response('success',Code::SUCCESS,$data); 318 $this->response('success',Code::SUCCESS,$data);
318 } 319 }
  320 +
  321 + /**
  322 + * @remark :不分页产品列表
  323 + * @name :productNoPage
  324 + * @author :lyh
  325 + * @method :post
  326 + * @time :2024/3/20 11:02
  327 + */
  328 + public function newsNoPage(NewsModel $news){
  329 + $this->map['status'] = $news::STATUS_ONE;
  330 + $lists = $news->list($this->map);
  331 + $this->response('success',Code::SUCCESS,$lists);
  332 + }
319 } 333 }
@@ -68,7 +68,20 @@ class ProductController extends BaseController @@ -68,7 +68,20 @@ class ProductController extends BaseController
68 $lists['list'][$k] = $v; 68 $lists['list'][$k] = $v;
69 } 69 }
70 } 70 }
71 - return $this->response('success',Code::SUCCESS,$lists); 71 + $this->response('success',Code::SUCCESS,$lists);
  72 + }
  73 +
  74 + /**
  75 + * @remark :不分页产品列表
  76 + * @name :productNoPage
  77 + * @author :lyh
  78 + * @method :post
  79 + * @time :2024/3/20 11:02
  80 + */
  81 + public function productNoPage(Product $product){
  82 + $this->map['status'] = $product::STATUS_ON;
  83 + $lists = $product->list($this->map,'id',['id','title']);
  84 + $this->response('success',Code::SUCCESS,$lists);
72 } 85 }
73 86
74 /** 87 /**
@@ -129,8 +142,8 @@ class ProductController extends BaseController @@ -129,8 +142,8 @@ class ProductController extends BaseController
129 if(isset($this->map['status'])){ 142 if(isset($this->map['status'])){
130 $query = $query->where('status',$this->map['status']); 143 $query = $query->where('status',$this->map['status']);
131 } 144 }
132 - if(!empty($this->map['start_at']) && !empty($this->map['end_at'])){  
133 - $query->whereBetween('created_at', [$this->map['start_at'],$this->map['end_at']]); 145 + if(!empty($this->param['start_at']) && !empty($this->param['end_at'])){
  146 + $query->where('created_at', '>=' ,$this->param['start_at'].' 00:00:00')->where('created_at', '<=' ,$this->param['end_at'].' 59:59:59');
134 } 147 }
135 return $query; 148 return $query;
136 } 149 }
@@ -30,7 +30,6 @@ class ATemplateModuleLogic extends BaseLogic @@ -30,7 +30,6 @@ class ATemplateModuleLogic extends BaseLogic
30 */ 30 */
31 public function aTemplateModuleLists($map,$page,$row,$order = 'created_at',$filed = ['*']){ 31 public function aTemplateModuleLists($map,$page,$row,$order = 'created_at',$filed = ['*']){
32 $map['deleted_status'] = 0; 32 $map['deleted_status'] = 0;
33 - $map['status'] = 0;  
34 $lists = $this->model->lists($map,$page,$row,$order,$filed); 33 $lists = $this->model->lists($map,$page,$row,$order,$filed);
35 return $this->success($lists); 34 return $this->success($lists);
36 } 35 }
@@ -189,6 +189,9 @@ class NewsLogic extends BaseLogic @@ -189,6 +189,9 @@ class NewsLogic extends BaseLogic
189 if(isset($param['image'])){ 189 if(isset($param['image'])){
190 $param['image'] = str_replace_url($param['image'] ?? ''); 190 $param['image'] = str_replace_url($param['image'] ?? '');
191 } 191 }
  192 + if(isset($param['related_news_id'])){
  193 + $param['related_news_id'] = implode(',',$param['related_news_id']);
  194 + }
192 if(isset($this->param['id'])){ 195 if(isset($this->param['id'])){
193 $param['operator_id'] = $this->user['id']; 196 $param['operator_id'] = $this->user['id'];
194 if(isset($param['category_id']) && !empty($param['category_id'])){ 197 if(isset($param['category_id']) && !empty($param['category_id'])){
@@ -62,8 +62,9 @@ class KeywordLogic extends BaseLogic @@ -62,8 +62,9 @@ class KeywordLogic extends BaseLogic
62 $this->fail('当前title已存在'); 62 $this->fail('当前title已存在');
63 } 63 }
64 //TODO::不能修改路由 64 //TODO::不能修改路由
  65 + $route = RouteMap::setRoute($this->param['route'], RouteMap::SOURCE_PRODUCT_KEYWORD, $this->param['id'], $this->user['project_id']);
  66 + $this->param['route'] = $route;
65 $this->model->edit($this->param,['id'=>$this->param['id']]); 67 $this->model->edit($this->param,['id'=>$this->param['id']]);
66 - $route = RouteMap::getRoute(RouteMap::SOURCE_PRODUCT_KEYWORD,$this->param['id'], $this->user['project_id']);  
67 $data = ['id'=>$this->param['id']]; 68 $data = ['id'=>$this->param['id']];
68 }else{ 69 }else{
69 $info = $this->model->read(['title'=>$this->param['title']]); 70 $info = $this->model->read(['title'=>$this->param['title']]);
@@ -12,6 +12,7 @@ namespace App\Http\Logic\Bside\Scoring; @@ -12,6 +12,7 @@ namespace App\Http\Logic\Bside\Scoring;
12 use App\Http\Logic\Bside\BaseLogic; 12 use App\Http\Logic\Bside\BaseLogic;
13 use App\Models\Scoring\RatingQuestion; 13 use App\Models\Scoring\RatingQuestion;
14 use App\Models\Scoring\ScoringSystem; 14 use App\Models\Scoring\ScoringSystem;
  15 +use App\Models\User\User;
15 use AWS\CRT\Log; 16 use AWS\CRT\Log;
16 17
17 class RatingLogic extends BaseLogic 18 class RatingLogic extends BaseLogic
@@ -34,7 +35,7 @@ class RatingLogic extends BaseLogic @@ -34,7 +35,7 @@ class RatingLogic extends BaseLogic
34 public function getRatingRead(){ 35 public function getRatingRead(){
35 $data = [ 36 $data = [
36 'company'=>$this->project['company'], 37 'company'=>$this->project['company'],
37 - 'mobile'=>$this->project['mobile'], 38 + 'mobile'=>$this->user['mobile'],
38 'uptime'=>$this->project['uptime'], 39 'uptime'=>$this->project['uptime'],
39 'domain'=>$this->user['domain'], 40 'domain'=>$this->user['domain'],
40 'question'=>$this->model->list(['type'=>$this->param['type']]), 41 'question'=>$this->model->list(['type'=>$this->param['type']]),
@@ -43,6 +44,7 @@ class RatingLogic extends BaseLogic @@ -43,6 +44,7 @@ class RatingLogic extends BaseLogic
43 return $this->success($data); 44 return $this->success($data);
44 } 45 }
45 46
  47 +
46 /** 48 /**
47 * @remark :提交统计 49 * @remark :提交统计
48 * @name :ratingSave 50 * @name :ratingSave
@@ -34,7 +34,7 @@ class TranslateLogic extends BaseLogic @@ -34,7 +34,7 @@ class TranslateLogic extends BaseLogic
34 if($this->param['url'] == 'All'){ 34 if($this->param['url'] == 'All'){
35 $info = $this->model->read(['url'=>$this->param['url'],'language_id'=>$this->param['language_id'],'type'=>$this->param['type']]); 35 $info = $this->model->read(['url'=>$this->param['url'],'language_id'=>$this->param['language_id'],'type'=>$this->param['type']]);
36 if(!empty($info) && !empty($info['data'])){ 36 if(!empty($info) && !empty($info['data'])){
37 - $translateInfo = json_decode($info['data'],true); 37 + $translateInfo = json_decode($info['data'],JSON_UNESCAPED_UNICODE);
38 foreach ($translateInfo as $k => $v){ 38 foreach ($translateInfo as $k => $v){
39 $data[] = [$k=>$v]; 39 $data[] = [$k=>$v];
40 } 40 }
@@ -48,7 +48,7 @@ class TranslateLogic extends BaseLogic @@ -48,7 +48,7 @@ class TranslateLogic extends BaseLogic
48 // 原始校对内容 48 // 原始校对内容
49 $info = $this->model->read(['url'=>$this->param['url'],'language_id'=>$this->param['language_id'],'type'=>$this->param['type']]); 49 $info = $this->model->read(['url'=>$this->param['url'],'language_id'=>$this->param['language_id'],'type'=>$this->param['type']]);
50 if($info !== false){ 50 if($info !== false){
51 - $data_read = json_decode($info['data'],true); 51 + $data_read = json_decode($info['data'],JSON_UNESCAPED_UNICODE);
52 foreach ($data_read as $k => $v){ 52 foreach ($data_read as $k => $v){
53 $data[] = [$k => $v]; 53 $data[] = [$k => $v];
54 } 54 }
@@ -130,7 +130,7 @@ class TranslateLogic extends BaseLogic @@ -130,7 +130,7 @@ class TranslateLogic extends BaseLogic
130 $info = $this->model->read(['url'=>$this->param['url'],'language_id'=>$this->param['language_id'],'type'=>$this->param['type']]); 130 $info = $this->model->read(['url'=>$this->param['url'],'language_id'=>$this->param['language_id'],'type'=>$this->param['type']]);
131 $data = []; 131 $data = [];
132 if(!empty($info) && !empty($info['data'])){ 132 if(!empty($info) && !empty($info['data'])){
133 - $translateInfo = json_decode($info['data'],true); 133 + $translateInfo = json_decode($info['data'],JSON_UNESCAPED_UNICODE);
134 foreach ($translateInfo as $k => $v){ 134 foreach ($translateInfo as $k => $v){
135 $data[] = [$k=>$v]; 135 $data[] = [$k=>$v];
136 } 136 }
@@ -151,7 +151,7 @@ class TranslateLogic extends BaseLogic @@ -151,7 +151,7 @@ class TranslateLogic extends BaseLogic
151 } 151 }
152 $new_list = $this->getUrlImageRead($url); 152 $new_list = $this->getUrlImageRead($url);
153 $old_list = []; 153 $old_list = [];
154 - $data_read = json_decode($info['data'],true); 154 + $data_read = json_decode($info['data'],JSON_UNESCAPED_UNICODE);
155 foreach ($data_read as $k=>$v){ 155 foreach ($data_read as $k=>$v){
156 $old_list[] = $k; 156 $old_list[] = $k;
157 $data[] = [ 157 $data[] = [
@@ -282,10 +282,10 @@ class TranslateLogic extends BaseLogic @@ -282,10 +282,10 @@ class TranslateLogic extends BaseLogic
282 'language_id'=>$this->param['language_id'], 282 'language_id'=>$this->param['language_id'],
283 'alias'=>$this->param['alias'], 283 'alias'=>$this->param['alias'],
284 ]; 284 ];
285 - $param['data'] = json_encode($data,true); 285 + $param['data'] = json_encode($data,JSON_UNESCAPED_UNICODE);
286 $this->model->add($param); 286 $this->model->add($param);
287 }else{ 287 }else{
288 - $data = json_encode($data,true); 288 + $data = json_encode($data,JSON_UNESCAPED_UNICODE);
289 $this->model->edit(['data'=>$data],['language_id'=>$this->param['language_id'],'url'=>$this->param['url'],'type'=>$this->param['type']]); 289 $this->model->edit(['data'=>$data],['language_id'=>$this->param['language_id'],'url'=>$this->param['url'],'type'=>$this->param['type']]);
290 } 290 }
291 }catch (\Exception $e){ 291 }catch (\Exception $e){
@@ -223,19 +223,19 @@ class UserLoginLogic @@ -223,19 +223,19 @@ class UserLoginLogic
223 $date = date('Y-m-d H:i:s'); 223 $date = date('Y-m-d H:i:s');
224 $scoringSystem = new ScoringSystem(); 224 $scoringSystem = new ScoringSystem();
225 if($date <= $after30Days){ 225 if($date <= $after30Days){
226 - $info = $scoringSystem->read(['type'=>1]);//第一阶段是否有值 226 + $info = $scoringSystem->read(['type'=>1,'project_id'=>$projectInfo['id']]);//第一阶段是否有值
227 if($info === false){ 227 if($info === false){
228 return $this->success(1); 228 return $this->success(1);
229 } 229 }
230 } 230 }
231 if($date >= $afterThreeMonths && $date <= $afterSixMonths){ 231 if($date >= $afterThreeMonths && $date <= $afterSixMonths){
232 - $info = $scoringSystem->read(['type'=>2]);//第一阶段是否有值 232 + $info = $scoringSystem->read(['type'=>2,'project_id'=>$projectInfo['id']]);//第一阶段是否有值
233 if($info === false){ 233 if($info === false){
234 return $this->success(2); 234 return $this->success(2);
235 } 235 }
236 } 236 }
237 if($date >= $afterOneYear){ 237 if($date >= $afterOneYear){
238 - $info = $scoringSystem->read(['type'=>3]);//第一阶段是否有值 238 + $info = $scoringSystem->read(['type'=>3,'project_id'=>$projectInfo['id']]);//第一阶段是否有值
239 if($info === false){ 239 if($info === false){
240 return $this->success(3); 240 return $this->success(3);
241 } 241 }
@@ -7,4 +7,32 @@ use App\Models\Base; @@ -7,4 +7,32 @@ use App\Models\Base;
7 class Notify extends Base 7 class Notify extends Base
8 { 8 {
9 protected $table = 'gl_notify'; 9 protected $table = 'gl_notify';
  10 + /**
  11 + * 状态 0:待处理, 1:路由生成完成, 2:页面生成完成
  12 + */
  13 + const STATUS_INIT = 0;
  14 + const STATUS_FINISH_ROUTE = 1;
  15 + const STATUS_FINISH_PAGE = 2;
  16 +
  17 + /**
  18 + * 类型 1:主站, 2:小语种
  19 + */
  20 + const TYPE_MASTER = 1;
  21 + const TYPE_MINOR = 2;
  22 +
  23 + /**
  24 + * 路由
  25 + * 1:所有路由,整站生成,
  26 + * 2:修改过内容的路由,按需生成,
  27 + * 3:指定路由,按url生成
  28 + * 4:生成聚合页生成
  29 + * 5:生成漏翻页面
  30 + * 6:生成视频聚合页
  31 + */
  32 + const ROUTE_ALL = 1;
  33 + const ROUTE_NEED = 2;
  34 + const ROUTE_URL = 3;
  35 + const ROUTE_PRODUCT_KEYWORD = 4;
  36 + const ROUTE_NOT_TRANSLATE = 5;
  37 + const ROUTE_PRODUCT_VIDEO_KEYWORD = 6;
10 } 38 }
@@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
10 namespace App\Models\CustomModule; 10 namespace App\Models\CustomModule;
11 11
12 use App\Models\Base; 12 use App\Models\Base;
  13 +use App\Models\Module\ModuleCategory;
13 14
14 class CustomModule extends Base 15 class CustomModule extends Base
15 { 16 {
@@ -16,4 +16,20 @@ class CustomModuleCategory extends Base @@ -16,4 +16,20 @@ class CustomModuleCategory extends Base
16 protected $table = 'gl_custom_module_category'; 16 protected $table = 'gl_custom_module_category';
17 //连接数据库 17 //连接数据库
18 protected $connection = 'custom_mysql'; 18 protected $connection = 'custom_mysql';
  19 +
  20 + /**
  21 + * 根据路由获取模块分类及模块信息
  22 + */
  23 + public static function getModuleCategoryAndExtendByRoute($projectId,$route)
  24 + {
  25 + return self::with("getExtend")->where("project_id",$projectId)->where("route",$route)->where("status",0)->first();
  26 + }
  27 +
  28 + /**
  29 + * 根据路由获取模块分类及模块信息
  30 + */
  31 + public static function getModuleCategoryAndExtendById($projectId,$id)
  32 + {
  33 + return self::with("getExtend")->where("project_id",$projectId)->where("id",$id)->where("status",0)->first();
  34 + }
19 } 35 }
@@ -11,6 +11,9 @@ namespace App\Models\CustomModule; @@ -11,6 +11,9 @@ namespace App\Models\CustomModule;
11 11
12 use App\Helper\Arr; 12 use App\Helper\Arr;
13 use App\Models\Base; 13 use App\Models\Base;
  14 +use App\Models\Module\CustomModule;
  15 +use App\Models\Module\ModuleCategory;
  16 +use App\Services\Html\PageService;
14 17
15 class CustomModuleContent extends Base 18 class CustomModuleContent extends Base
16 { 19 {
@@ -18,8 +21,9 @@ class CustomModuleContent extends Base @@ -18,8 +21,9 @@ class CustomModuleContent extends Base
18 //连接数据库 21 //连接数据库
19 protected $connection = 'custom_mysql'; 22 protected $connection = 'custom_mysql';
20 23
21 - public function getCategoryIdAttribute($value){  
22 - return explode(',',trim($value,',')); 24 + public function getCategoryIdAttribute($value)
  25 + {
  26 + return explode(',', trim($value, ','));
23 } 27 }
24 28
25 /** 29 /**
@@ -29,10 +33,114 @@ class CustomModuleContent extends Base @@ -29,10 +33,114 @@ class CustomModuleContent extends Base
29 * @method :post 33 * @method :post
30 * @time :2024/1/23 14:31 34 * @time :2024/1/23 14:31
31 */ 35 */
32 - public function getVideoAttribute($value){  
33 - if(!empty($value)){ 36 + public function getVideoAttribute($value)
  37 + {
  38 + if (!empty($value)) {
34 $value = Arr::s2a($value); 39 $value = Arr::s2a($value);
35 } 40 }
36 return $value; 41 return $value;
37 } 42 }
  43 +
  44 + /**
  45 + * 根据路由获取模块信息
  46 + */
  47 + public static function getModuleAndExtendById($projectId, $id)
  48 + {
  49 + return self::with("getExtend")->where("project_id", $projectId)->where("id", $id)->where("status", 0)->first();
  50 + }
  51 +
  52 + /**
  53 + * 关联模块信息
  54 + */
  55 + public function getExtend(): \Illuminate\Database\Eloquent\Relations\HasOne
  56 + {
  57 + return $this->hasOne(CustomModule::class, 'id', 'module_id');
  58 + }
  59 +
  60 + /**
  61 + * module数据处理
  62 + */
  63 + public static function modulesListDataHandle($moduleCategoryInfo, $modules): array
  64 + {
  65 + $newT = [];
  66 + $pageService = new PageService();
  67 + if (!empty($modules)) {
  68 + foreach ($modules as $key => $item) {
  69 + if (!empty($item->remark)) {
  70 + $remark = $item->remark;
  71 + } else {
  72 + $text = strip_tags($item->content);
  73 + $remark = strlen($text) > 260 ? substr($text, 0, 260) . '...' : $text;
  74 + }
  75 + $newT[$key]["id"] = $item->id;
  76 + if (!empty($item->category_id)) {
  77 + $categoryIdArr = explode(",", $item->category_id);
  78 + if (!empty($categoryIdArr)) {
  79 + $categoryIdArr = array_filter($categoryIdArr);
  80 + $categoryId = (int)array_shift($categoryIdArr);
  81 + $newT[$key]["category_id"] = $categoryId;
  82 + }
  83 + }
  84 + //视频
  85 + $newT[$key]["video"] = !empty($item->video) ? json_decode($item->video) : null;
  86 + $newT[$key]["image"] = !empty($item->image) ? $pageService->getImageUrl($item->image) : "";
  87 + $newT[$key]["content"] = !empty($item->content) ? $item->content : "";
  88 + $newT[$key]["name"] = !empty($item->name) ? $item->name : "";
  89 + $newT[$key]["remark"] = $remark;
  90 + if (isset($item->release_at) && !empty(isset($item->release_at))) {
  91 + $newT[$key]["created_at"] = $item->release_at;
  92 + } else {
  93 + $time = !empty($item->created_at) ? $item->created_at->toArray()['formatted'] : "";
  94 + $newT[$key]["created_at"] = $time;
  95 + }
  96 + $newT[$key]["created_at"] = strtotime($newT[$key]["created_at"]);
  97 + $newT[$key]["created_at"] = date("Y-m-d", $newT[$key]["created_at"]);
  98 +
  99 + if (isset($newT[$key]["category_id"]) && !empty($newT[$key]["category_id"])) {
  100 + $categoryInfo = CustomModuleCategory::getModuleCategoryAndExtendById($item->project_id, $newT[$key]["category_id"]);
  101 + $newT[$key]["aUrl"] = !empty($categoryInfo) ? $categoryInfo->route . "/" . $item->route : "";
  102 + } else {
  103 + $newT[$key]["aUrl"] = !empty($item->route) ? $moduleCategoryInfo->route . "/" . $item->route : "";
  104 + }
  105 + }
  106 + }
  107 + return $newT;
  108 + }
  109 +
  110 + /**
  111 + * 根据模块查找自定义模块分类数据
  112 + */
  113 + public static function getModuleCategory($projectId, $modules)
  114 + {
  115 + $moduleCategoryInfo = null;
  116 + if (isset($modules->category_id) && !empty($modules->category_id) && $modules->category_id != ",,") {
  117 + $cateArr = explode(",", $modules->category_id);
  118 + $cateArr = array_filter($cateArr);
  119 + if (!empty($cateArr)) {
  120 + $cateId = (int)array_shift($cateArr);
  121 + $moduleCategoryInfo = CustomModuleCategory::getModuleCategoryAndExtendById($projectId, $cateId);
  122 + }
  123 + }
  124 + return $moduleCategoryInfo;
  125 + }
  126 +
  127 + /**
  128 + * 是否是自定义扩展模块
  129 + */
  130 + public static function isModule($moduleDataModule)
  131 + {
  132 + $moduleDataModuleArr = explode("-", $moduleDataModule);
  133 + if (count($moduleDataModuleArr) == 2) {
  134 + $moduleArr = $moduleDataModuleArr;
  135 + if (!empty($moduleArr)) {
  136 + $moduleArr[0] = isset($moduleArr[0]) && !empty($moduleArr[0]) ? $moduleArr[0] : null;
  137 + $moduleArr[1] = isset($moduleArr[1]) && !empty($moduleArr[1]) ? (int)$moduleArr[1] : null;
  138 + }
  139 + return $moduleArr;
  140 + } else {
  141 +// return $moduleDataModule;
  142 + return null;
  143 + }
  144 +
  145 + }
38 } 146 }
@@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
2 2
3 namespace App\Models\News; 3 namespace App\Models\News;
4 4
  5 +use App\Helper\Arr;
5 use App\Models\Base; 6 use App\Models\Base;
6 7
7 class News extends Base 8 class News extends Base
@@ -22,4 +23,8 @@ class News extends Base @@ -22,4 +23,8 @@ class News extends Base
22 } 23 }
23 return $value; 24 return $value;
24 } 25 }
  26 +
  27 + public function getRelatedNewsIdAttribute($value){
  28 + return Arr::setToArr($value);
  29 + }
25 } 30 }
@@ -17,4 +17,7 @@ class NewsCategory extends Base @@ -17,4 +17,7 @@ class NewsCategory extends Base
17 const STATUS_SHOW = 0; 17 const STATUS_SHOW = 0;
18 const STATUS_HIDE = 1; 18 const STATUS_HIDE = 1;
19 19
  20 + //新闻分类,博客分类列表分页条数
  21 + public static $newsCategoryPagePercent = 10;
  22 +
20 } 23 }
@@ -21,6 +21,63 @@ class Category extends Base @@ -21,6 +21,63 @@ class Category extends Base
21 protected $connection = 'custom_mysql'; 21 protected $connection = 'custom_mysql';
22 22
23 const STATUS_ACTIVE = 1; 23 const STATUS_ACTIVE = 1;
  24 + //新闻产品分类列表分页条数
  25 + public static $productCategoryPagePercent = 15;
  26 + public static $productSearchPagePercent = 12;
  27 +
  28 + /**
  29 + * 根据分类ID查询上面所有父级,递归
  30 + */
  31 + public static function getAllFatherCategory($categoryId): array
  32 + {
  33 + $category = self::find($categoryId);
  34 + return $category->getAncestorsRecursive();
  35 + }
  36 +
  37 + /**
  38 + * 根据产品分类获取分类列表和产品
  39 + */
  40 + public static function getCategoryBySelfCategory($projectId,$routerMap)
  41 + {
  42 + if ($routerMap->source_id == 0){
  43 + $categoryList = Category::with("products")->where("project_id",$projectId)->where("pid",0)->where("status",1)->orderBy("sort","desc")->orderBy("id","desc")->get();
  44 + }else{
  45 + $categoryIds = [];
  46 + $category = Category::where("project_id",$projectId)->where("pid",$routerMap->source_id)->where("status",1)->orderBy("sort","desc")->orderBy("id","desc")->get();
  47 + if (count($category)>=1){
  48 + foreach ($category as $categoryItem){
  49 + $categoryIds[] = $categoryItem->id;
  50 + }
  51 + }else{
  52 + $categoryIds[] = $routerMap->source_id;
  53 + }
  54 + $categoryList = Category::with("products")->where("project_id",$projectId)->whereIn("id",$categoryIds)->where("status",1)->orderBy("sort","desc")->orderBy("id","desc")->get();
  55 + }
  56 + return $categoryList;
  57 + }
  58 +
  59 + /**
  60 + * 森联数据处理
  61 + */
  62 + public static function getSenLianCategoryAndProducts($routerMap)
  63 + {
  64 + $data = [];
  65 + //下级分类及产品+产品扩展型号
  66 + $categorys = null;
  67 + $sonData = self::with("productsSl")->where("project_id",$routerMap->project_id)->where("status",1)->where("pid",$routerMap->source_id)->orderBy("id","desc")->get();
  68 + if ($routerMap->route == "products" || !empty($sonData)){
  69 + if ($routerMap->route == "products"){
  70 + $categorys = self::with("productsSl")->where("project_id",$routerMap->project_id)->where("status",1)->where("pid",0)->where("route","!=","products")->orderBy("id","desc")->get();
  71 + }else{
  72 + $categorys = $sonData;
  73 + }
  74 + }
  75 + if (!empty($categorys)){
  76 + $categorys = $categorys->toArray();
  77 + }
  78 + $data["categorySon"] = $categorys;
  79 + return $data;
  80 + }
24 81
25 /** 82 /**
26 * 获取指定分类的所有子分类IDS(包括自己) 83 * 获取指定分类的所有子分类IDS(包括自己)
@@ -72,4 +129,33 @@ class Category extends Base @@ -72,4 +129,33 @@ class Category extends Base
72 $count = count($productArr); 129 $count = count($productArr);
73 return $count; 130 return $count;
74 } 131 }
  132 +
  133 + /**
  134 + * 根据分类ID查询下面所有子级ID,递归
  135 + */
  136 + public static function getAllSonCategoryById($projectId,$id): array
  137 + {
  138 + $ids = [];
  139 + $ids[] = $id;
  140 + self::getProductCategoryList($projectId,$id,$ids);
  141 + return $ids;
  142 +
  143 + }
  144 +
  145 + /**
  146 + * 获取分类
  147 + */
  148 + public static function getProductCategoryList($projectId,$id,&$ids)
  149 + {
  150 + $categoryListPid = self::where("project_id",$projectId)->where("pid",$id)->get();
  151 + if (!empty($categoryListPid)){
  152 + foreach ($categoryListPid as $item){
  153 + $ids[] = $item->id;
  154 + self::getProductCategoryList($projectId,$item->id,$ids);
  155 + }
  156 + }else{
  157 + $ids[] = $categoryListPid->id;
  158 + }
  159 + return $ids;
  160 + }
75 } 161 }
@@ -17,4 +17,10 @@ class Extend extends Base @@ -17,4 +17,10 @@ class Extend extends Base
17 protected $table = 'gl_product_extend'; 17 protected $table = 'gl_product_extend';
18 //连接数据库 18 //连接数据库
19 protected $connection = 'custom_mysql'; 19 protected $connection = 'custom_mysql';
  20 +
  21 + //产品详情扩展字段类型 1,文本输入框 2,代码块 3,图片列表 4,文件列表
  22 + public static $textExtendType = 1;
  23 + public static $codeExtendType = 2;
  24 + public static $imageExtendType = 3;
  25 + public static $fileExtendType = 4;
20 } 26 }
@@ -17,4 +17,76 @@ class ExtendInfo extends Base @@ -17,4 +17,76 @@ class ExtendInfo extends Base
17 protected $table = 'gl_product_extend_info'; 17 protected $table = 'gl_product_extend_info';
18 //连接数据库 18 //连接数据库
19 protected $connection = 'custom_mysql'; 19 protected $connection = 'custom_mysql';
  20 +
  21 + /**
  22 + * 搜索模块-广州万天实业有限公司-项目ID:194,获取产品品牌和型号扩展字段的值
  23 + * key值固定为:pd_extended_field_1:品牌,pd_extended_field_2:型号
  24 + */
  25 + public static function getProductsAllBrandAndModel($projectId): array
  26 + {
  27 + $brandAndModel = [];
  28 + $brandArr = [];
  29 + $productIds = [];
  30 + $productsExtendInfo = self::where("project_id",$projectId)->get();
  31 + if (!empty($productsExtendInfo)){
  32 + $productsExtendBrandInfo = $productsExtendInfo->where("key","pd_extended_field_1");
  33 + if (!empty($productsExtendBrandInfo)){
  34 + foreach ($productsExtendBrandInfo as $productsExtendBrandInfoItem){
  35 + if (!empty($productsExtendBrandInfoItem->values)){
  36 + $brand = explode(",",$productsExtendBrandInfoItem->values);
  37 + $brands = array_filter($brand);
  38 + if (!empty($brands)){
  39 + foreach ($brands as $brandsItem){
  40 + $brandArr[] = $brandsItem;
  41 + }
  42 + }
  43 + }
  44 + }
  45 + }
  46 + }
  47 + //临时数据
  48 + if (!empty($brandArr)){
  49 + $brandArr = array_unique($brandArr);
  50 + $key = 0;
  51 + foreach ($brandArr as $brandArrItem){
  52 + $brandKeys = $productsExtendInfo->where("key","pd_extended_field_1");
  53 + if (!empty($brandKeys)){
  54 + foreach ($brandKeys as $brandKeysItem){
  55 + if ($brandKeysItem->values){
  56 + if (strpos($brandKeysItem->values, $brandArrItem) !== false){
  57 + $brandAndModel[$key]["ids"][] = $brandKeysItem->product_id;
  58 + $brandAndModel[$key]["brand"] = $brandArrItem;
  59 + }
  60 + }
  61 + }
  62 + }
  63 + $key++;
  64 + }
  65 + }
  66 +
  67 + if (!empty($brandAndModel)){
  68 + foreach ($brandAndModel as $keyItem=>$brandAndModelItem){
  69 + if (!empty($brandAndModelItem["ids"])){
  70 + $productIds = array_unique($brandAndModelItem["ids"]);
  71 + $modelKeys = $productsExtendInfo->where("key","pd_extended_field_2")->whereIn("product_id",$productIds);
  72 + $models = [];
  73 + if (!empty($modelKeys)){
  74 + foreach ($modelKeys as $modelKeysItem){
  75 + if (!empty($modelKeysItem->values)){
  76 + $modelArr = array_filter(explode(",",$modelKeysItem->values));
  77 + foreach ($modelArr as $modelArrItem){
  78 + $models[] = $modelArrItem;
  79 + }
  80 + }
  81 + }
  82 + }
  83 + if (!empty($models)){
  84 + $models = array_unique($models);
  85 + $brandAndModel[$keyItem]["model"] = $models;
  86 + }
  87 + }
  88 + }
  89 + }
  90 + return $brandAndModel;
  91 + }
20 } 92 }
@@ -55,4 +55,13 @@ class Keyword extends Base @@ -55,4 +55,13 @@ class Keyword extends Base
55 } 55 }
56 return $value ?: []; 56 return $value ?: [];
57 } 57 }
  58 +
  59 + /**
  60 + * 随机获取关键词列表
  61 + */
  62 + public function getProductsKeywordsList($project)
  63 + {
  64 + return Keyword::where("project_id",$project->id)->where("status",1)->inRandomOrder()->take(10)->get();
  65 + }
  66 +
58 } 67 }
@@ -4,6 +4,7 @@ namespace App\Models\Product; @@ -4,6 +4,7 @@ namespace App\Models\Product;
4 4
5 use App\Helper\Arr; 5 use App\Helper\Arr;
6 use App\Models\Base; 6 use App\Models\Base;
  7 +use Illuminate\Database\Eloquent\Relations\BelongsToMany;
7 use Illuminate\Database\Eloquent\SoftDeletes; 8 use Illuminate\Database\Eloquent\SoftDeletes;
8 9
9 /** 10 /**
@@ -209,4 +210,15 @@ class Product extends Base @@ -209,4 +210,15 @@ class Product extends Base
209 } 210 }
210 return $value; 211 return $value;
211 } 212 }
  213 +
  214 + /**
  215 + * 多对多关联
  216 + * @return BelongsToMany
  217 + * @author zbj
  218 + * @date 2024/1/22
  219 + */
  220 + public function category(): BelongsToMany
  221 + {
  222 + return $this->belongsToMany(Category::class, 'gl_product_category_related', 'product_id', 'cate_id');
  223 + }
212 } 224 }
@@ -3,8 +3,29 @@ @@ -3,8 +3,29 @@
3 namespace App\Models\Project; 3 namespace App\Models\Project;
4 4
5 use App\Models\Base; 5 use App\Models\Base;
  6 +use App\Models\WebSetting\WebLanguage;
  7 +use App\Models\WebSetting\WebSetting;
  8 +use Illuminate\Support\Facades\Redis;
6 9
7 class Country extends Base 10 class Country extends Base
8 { 11 {
9 protected $table = 'gl_project_country'; 12 protected $table = 'gl_project_country';
  13 +
  14 + public static function getProjectCountry($projectId)
  15 + {
  16 + if (Redis::get("project_" . $projectId . "_country") == null) {
  17 + $country = Country::where("project_id", $projectId)->first();
  18 + if (!empty($country)) {
  19 +// $webCountry = WebLanguage::with("countryCustom")->whereIn("id", explode(",", $country->country_lists))->get();
  20 + $webCountry = WebLanguage::with(["countryCustom" => function($query) use ($projectId) {
  21 + $query->where('project_id', $projectId);
  22 + }])->whereIn("id", explode(",", $country->country_lists))->orderByRaw(DB::raw("FIND_IN_SET(id,'" . $country->country_lists. "'" . ')'))->get();
  23 + } else {
  24 + $webCountry = null;
  25 + }
  26 + Redis::set("project_" . $projectId . "_country", json_encode($webCountry));
  27 + Redis::expire("project_" . $projectId . "_country", WebSetting::$redisExpireTime);
  28 + }
  29 + return json_decode(Redis::get("project_".$projectId."_country"));
  30 + }
10 } 31 }
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 namespace App\Models\Project; 3 namespace App\Models\Project;
4 4
5 use App\Models\Base; 5 use App\Models\Base;
  6 +use App\Models\WebSetting\WebSetting;
6 use Illuminate\Database\Eloquent\SoftDeletes; 7 use Illuminate\Database\Eloquent\SoftDeletes;
7 8
8 class CountryCustom extends Base 9 class CountryCustom extends Base
@@ -10,4 +11,14 @@ class CountryCustom extends Base @@ -10,4 +11,14 @@ class CountryCustom extends Base
10 use SoftDeletes; 11 use SoftDeletes;
11 12
12 protected $table = 'gl_project_country_custom'; 13 protected $table = 'gl_project_country_custom';
  14 +
  15 +
  16 + public static function getCountryCustomByProjectId($projectId){
  17 + if (Redis::get("project_" . $projectId . "_country_custom") == null) {
  18 + $countryCustomInfo = self::with("countryCustomLanguage")->where("project_id",$projectId)->where("status",1)->where("is_create",1)->get();
  19 + Redis::set("project_" . $projectId . "_country_custom", json_encode($countryCustomInfo));
  20 + Redis::expire("project_" . $projectId . "_country_custom", WebSetting::$redisExpireTime);
  21 + }
  22 + return json_decode(Redis::get("project_".$projectId."_country_custom"));
  23 + }
13 } 24 }
@@ -4,8 +4,6 @@ namespace App\Models\Project; @@ -4,8 +4,6 @@ namespace App\Models\Project;
4 4
5 use App\Helper\Arr; 5 use App\Helper\Arr;
6 use App\Models\Base; 6 use App\Models\Base;
7 -use App\Models\Devops\ServerConfig;  
8 -use Illuminate\Support\Facades\Cache;  
9 7
10 class DomainInfo extends Base 8 class DomainInfo extends Base
11 { 9 {
@@ -14,7 +14,25 @@ class Project extends Base @@ -14,7 +14,25 @@ class Project extends Base
14 { 14 {
15 //设置关联表名 15 //设置关联表名
16 protected $table = 'gl_project'; 16 protected $table = 'gl_project';
17 - 17 + public static $domainEndSlash = 1; //斜杠结尾
  18 + public static $projectLocationZero = 0; //普通项目
  19 + public static $projectLocationDangerous = 1; //危险项目
  20 + public static $storageTypeZero = 0; //默认腾讯压缩存储桶
  21 + public static $storageTypeOne = 1; //非压缩存储桶
  22 +
  23 + public static $storageTypeZeroFileFix = "ecdn6.globalso.com"; //非压缩存储桶
  24 + public static $storageTypeOneFileFix = "ecdn6-nc.globalso.com"; //压缩存储桶
  25 + public static $projectLocationDangerousFileFix = "globalso-v6.s3.us-west-2.amazonaws.com"; //危险项目存储桶
  26 +
  27 + //项目标识集合
  28 + public static $blockItems = "blockitems"; //html循环项父级标识
  29 + public static $blockAttrItems = "[blockitems]"; //html循环项父级属性标识
  30 + public static $blockItem = "blockitem"; //html循环项标识
  31 + public static $blockAttrItem = "[blockitem]"; //html循环项属性标识
  32 + public static $productListBlock = "productlistblock"; //html产品列表标识
  33 + public static $newListBlock = "newlistblock"; //html新闻列表标识
  34 + public static $blogListBlock = "bloglistblock"; //html博客列表标识
  35 + public static $productCategoryListBlock = "productcategorylistblock"; //html产品分类列表标识
18 const DATABASE_NAME_FIX = 'gl_data_'; 36 const DATABASE_NAME_FIX = 'gl_data_';
19 37
20 const CUSTOMIZED_ONE = 1;//定制项目 38 const CUSTOMIZED_ONE = 1;//定制项目
  1 +<?php
  2 +
  3 +namespace App\Models\Project;
  4 +
  5 +use Illuminate\Database\Eloquent\Model;
  6 +
  7 +/**
  8 + * @method static where(string $string, int $param)
  9 + * @method static find($id)
  10 + * @method static get()
  11 + * @method static insertGetId()
  12 + * @method static create(array $array)
  13 + * @method static offset(float|int $param)
  14 + * @method static select(string $string)
  15 + * @method static orderBy(string $string, string $string1)
  16 + */
  17 +class UpdateMasterWebsiteModel extends Model
  18 +{
  19 + protected $connection = "custom_mysql";
  20 + protected $table = 'gl_update_master_website';
  21 +}
  1 +<?php
  2 +
  3 +namespace App\Models\Project;
  4 +
  5 +use Illuminate\Database\Eloquent\Model;
  6 +
  7 +/**
  8 + * @method static where(string $string, int $param)
  9 + * @method static find($id)
  10 + * @method static get()
  11 + * @method static insertGetId()
  12 + * @method static create(array $array)
  13 + * @method static select(string $string)
  14 + * @method static orderBy(string $string, string $string1)
  15 + */
  16 +class UpdateMinorLanguagesModel extends Model
  17 +{
  18 + protected $connection = "custom_mysql";
  19 + protected $table = 'gl_update_minor_languages';
  20 +}
1 -<?php  
2 -  
3 -namespace App\Models\Template;  
4 -  
5 -use App\Models\Base;  
6 -  
7 -/**  
8 - * @remark :默认主题  
9 - * @name :Setting  
10 - * @author :lyh  
11 - * @time :2023/6/28 16:51  
12 - */  
13 -class BSettingTemplate extends Base  
14 -{  
15 - protected $table = 'gl_web_setting_template';  
16 - //连接数据库  
17 - protected $connection = 'custom_mysql';  
18 -}  
@@ -16,4 +16,5 @@ class BTemplateCommon extends Base @@ -16,4 +16,5 @@ class BTemplateCommon extends Base
16 protected $table = 'gl_web_template_common'; 16 protected $table = 'gl_web_template_common';
17 //连接数据库 17 //连接数据库
18 protected $connection = 'custom_mysql'; 18 protected $connection = 'custom_mysql';
  19 +
19 } 20 }
@@ -13,4 +13,12 @@ use App\Models\Base; @@ -13,4 +13,12 @@ use App\Models\Base;
13 class Setting extends Base 13 class Setting extends Base
14 { 14 {
15 protected $table = 'gl_web_setting_template'; 15 protected $table = 'gl_web_setting_template';
  16 +
  17 + /**
  18 + * 获取项目模板信息
  19 + */
  20 + public static function getProjectTemplateInfo($projectId)
  21 + {
  22 + return self::where("project_id",$projectId)->first();
  23 + }
16 } 24 }
1 -<?php  
2 -/**  
3 - * @remark :  
4 - * @name :TemplateProject.php  
5 - * @author :lyh  
6 - * @method :post  
7 - * @time :2023/11/15 14:38  
8 - */  
9 -  
10 -namespace App\Models\Template;  
11 -  
12 -use App\Models\Base;  
13 -  
14 -class TemplateProject extends Base  
15 -{  
16 - protected $table = 'gl_web_setting_template';  
17 - //连接数据库  
18 - protected $connection = 'custom_mysql';  
19 -}  
@@ -25,4 +25,9 @@ class SettingNum extends Base @@ -25,4 +25,9 @@ class SettingNum extends Base
25 protected $table = 'gl_setting_num'; 25 protected $table = 'gl_setting_num';
26 //连接数据库 26 //连接数据库
27 protected $connection = 'custom_mysql'; 27 protected $connection = 'custom_mysql';
  28 +
  29 + //列表页种类
  30 + public static $productListType = 1;
  31 + public static $blogListType = 2;
  32 + public static $newsListType = 3;
28 } 33 }
@@ -16,4 +16,8 @@ class Translate extends Base @@ -16,4 +16,8 @@ class Translate extends Base
16 protected $table = 'gl_translate'; 16 protected $table = 'gl_translate';
17 //连接数据库 17 //连接数据库
18 protected $connection = 'custom_mysql'; 18 protected $connection = 'custom_mysql';
  19 +
  20 + public static $textType = 1;
  21 + public static $imageType = 2;
  22 +
19 } 23 }
@@ -10,13 +10,30 @@ @@ -10,13 +10,30 @@
10 namespace App\Models\WebSetting; 10 namespace App\Models\WebSetting;
11 11
12 use App\Models\Base; 12 use App\Models\Base;
  13 +use App\Models\Project\CountryCustom;
13 use Illuminate\Support\Facades\Cache; 14 use Illuminate\Support\Facades\Cache;
14 15
15 class WebLanguage extends Base 16 class WebLanguage extends Base
16 { 17 {
17 protected $table = 'gl_web_language'; 18 protected $table = 'gl_web_language';
18 19
19 - 20 + /**
  21 + * 关键词17种语种
  22 + */
  23 + public static function getKeywordsCountry($project = null)
  24 + {
  25 + $languageIds = [1,4,5,6,7,8,9,10,11,14,15,18,22,26,40,68,78,95,99];
  26 + //加入项目主语种
  27 + if (!empty($project)){
  28 + $mainLangId = $project->main_lang_id;
  29 + array_unshift($languageIds,(int)$mainLangId);
  30 + }
  31 + $projectId = $project->id;
  32 + $languageIds=array_unique($languageIds);
  33 + return WebLanguage::with(["countryCustom" => function($query) use ($projectId) {
  34 + $query->where('project_id', $projectId);
  35 + }])->whereIn("id",$languageIds)->get();
  36 + }
20 /** 37 /**
21 * @param $id 38 * @param $id
22 * @return mixed 39 * @return mixed
@@ -48,4 +65,39 @@ class WebLanguage extends Base @@ -48,4 +65,39 @@ class WebLanguage extends Base
48 } 65 }
49 return $id; 66 return $id;
50 } 67 }
  68 +
  69 + /**
  70 + * 获取项目主语种
  71 + */
  72 + public static function getProjectMainLang($mainLangId = 1)
  73 + {
  74 + $mainLang = self::find($mainLangId);
  75 + if (empty($mainLang)){
  76 + return null;
  77 + }
  78 + return $mainLang;
  79 + }
  80 +
  81 + /**
  82 + * 关键词17种语种IDS
  83 + */
  84 + public static function getKeywordsCountryIds($project = null): array
  85 + {
  86 + $languageIds = [1,4,5,6,7,8,9,10,11,14,15,18,22,26,40,68,78,95,99];
  87 + //加入项目主语种
  88 + if (!empty($project)){
  89 + $mainLangId = $project->main_lang_id;
  90 + array_unshift($languageIds,(int)$mainLangId);
  91 + }
  92 + return array_unique($languageIds);
  93 + }
  94 +
  95 + /**
  96 + * 关联语种自定义跳转设置
  97 + */
  98 + public function countryCustom(): \Illuminate\Database\Eloquent\Relations\HasOne
  99 + {
  100 + return $this->hasOne(CountryCustom::class, 'language_id', 'id');
  101 + }
  102 +
51 } 103 }
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 namespace App\Models\WebSetting; 3 namespace App\Models\WebSetting;
4 4
5 use App\Models\Base; 5 use App\Models\Base;
  6 +use Illuminate\Support\Facades\Redis;
6 7
7 class WebSetting extends Base 8 class WebSetting extends Base
8 { 9 {
@@ -12,5 +13,26 @@ class WebSetting extends Base @@ -12,5 +13,26 @@ class WebSetting extends Base
12 //连接数据库 13 //连接数据库
13 protected $connection = 'custom_mysql'; 14 protected $connection = 'custom_mysql';
14 15
  16 + //网站缓存过期时间
  17 + public static $redisExpireTime = 600;
  18 + public static $redisUpdateHtmlExpireTime = 60;
  19 + public static $okStatus = 200;
  20 + public static $errStatus = 500;
15 21
  22 + /**
  23 + * 网站设置
  24 + */
  25 + public static function getWebSetting($project)
  26 + {
  27 + if (Redis::get("project_".$project->id."_web_setting") == null) {
  28 + $webSetting = self::where("project_id", $project->id)->first();
  29 + if (!empty($webSetting)) {
  30 + Redis::set("project_".$project->id."_web_setting", json_encode($webSetting->toArray()));
  31 + } else {
  32 + Redis::set("project_".$project->id."_web_setting", null);
  33 + }
  34 + Redis::expire("project_".$project->id."_web_setting", WebSetting::$redisExpireTime);
  35 + }
  36 + return json_decode(Redis::get("project_".$project->id."_web_setting"));
  37 + }
16 } 38 }
  1 +<?php
  2 +
  3 +namespace App\Models\WebSetting;
  4 +
  5 +use Illuminate\Database\Eloquent\Model;
  6 +
  7 +/**
  8 + * @method static whereIn(string $string, false|string[] $explode)
  9 + * @method static where(string $string, mixed|string $lang)
  10 + */
  11 +class WebSettingCountry extends Model
  12 +{
  13 + protected $table = 'gl_web_setting_country';
  14 +}
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 namespace App\Models\WebSetting; 3 namespace App\Models\WebSetting;
4 4
5 use App\Models\Base; 5 use App\Models\Base;
  6 +use Illuminate\Support\Facades\Redis;
6 7
7 class WebSettingText extends Base 8 class WebSettingText extends Base
8 { 9 {
@@ -27,4 +28,21 @@ class WebSettingText extends Base @@ -27,4 +28,21 @@ class WebSettingText extends Base
27 self::TYPE_NEWS=>'新闻页', 28 self::TYPE_NEWS=>'新闻页',
28 self::TYPE_BLOG=>'博客页', 29 self::TYPE_BLOG=>'博客页',
29 ]; 30 ];
  31 +
  32 + /**
  33 + * 网站锚文本
  34 + */
  35 + public static function getWebSettingText($project)
  36 + {
  37 + if (Redis::get("project_".$project->id."_web_setting_text") == null) {
  38 + $webSettingText = WebSettingText::where("project_id",$project->id)->get();
  39 + if (!empty($webSettingText)) {
  40 + Redis::set("project_".$project->id."_web_setting_text", json_encode($webSettingText->toArray()));
  41 + } else {
  42 + Redis::set("project_".$project->id."_web_setting_text", null);
  43 + }
  44 + Redis::expire("project_".$project->id."_web_setting_text", WebSetting::$redisExpireTime);
  45 + }
  46 + return json_decode(Redis::get("project_".$project->id."_web_setting_text"));
  47 + }
30 } 48 }
  1 +<?php
  2 +namespace App\Repositories\Bt;
  3 +/**
  4 + * 宝塔面板站点操作类库
  5 + * @author 阿良 or Youngxj(二次开发)
  6 + * @link https://www.bt.cn/api-doc.pdf
  7 + * @link https://gitee.com/youngxj0/Bty1.0
  8 + * @version 1.0
  9 + * @example
  10 + * $bt = new Bt('http://127.0.0.1/8888','xxxxxxxxxxxxxxxx');
  11 + * echo $bt->GetSystemTotal();//获取系统基础统计
  12 + * @return Array
  13 + */
  14 +class Bt
  15 +{
  16 + private $BT_KEY = ""; //接口密钥
  17 + private $BT_PANEL = "http://127.0.0.1/8888"; //面板地址
  18 +
  19 + /**
  20 + * 初始化
  21 + * @param [type] $bt_panel 宝塔接口地址
  22 + * @param [type] $bt_key 宝塔Api密钥
  23 + */
  24 + public function __construct($bt_panel = null,$bt_key = null){
  25 + if($bt_panel) $this->BT_PANEL = $bt_panel;
  26 + if($bt_key) $this->BT_KEY = $bt_key;
  27 + }
  28 +
  29 + /**
  30 + * 获取系统基础统计
  31 + */
  32 + public function GetSystemTotal(){
  33 + $url = $this->BT_PANEL.$this->config("GetSystemTotal");
  34 +
  35 + $p_data = $this->GetKeyData();
  36 +
  37 + $result = $this->HttpPostCookie($url,$p_data);
  38 +
  39 + $data = json_decode($result,true);
  40 + return $data;
  41 + }
  42 +
  43 + /**
  44 + * 获取磁盘分区信息
  45 + */
  46 + public function GetDiskInfo(){
  47 + $url = $this->BT_PANEL.$this->config("GetDiskInfo");
  48 +
  49 + $p_data = $this->GetKeyData();
  50 +
  51 + $result = $this->HttpPostCookie($url,$p_data);
  52 +
  53 + $data = json_decode($result,true);
  54 + return $data;
  55 + }
  56 +
  57 + /**
  58 + * 获取实时状态信息
  59 + * (CPU、内存、网络、负载)
  60 + */
  61 + public function GetNetWork(){
  62 + $url = $this->BT_PANEL.$this->config("GetNetWork");
  63 +
  64 + $p_data = $this->GetKeyData();
  65 +
  66 + $result = $this->HttpPostCookie($url,$p_data);
  67 +
  68 + $data = json_decode($result,true);
  69 + return $data;
  70 + }
  71 +
  72 + /**
  73 + * 检查是否有安装任务
  74 + */
  75 + public function GetTaskCount(){
  76 + $url = $this->BT_PANEL.$this->config("GetTaskCount");
  77 +
  78 + $p_data = $this->GetKeyData();
  79 +
  80 + $result = $this->HttpPostCookie($url,$p_data);
  81 +
  82 + $data = json_decode($result,true);
  83 + return $data;
  84 + }
  85 +
  86 + /**
  87 + * 检查面板更新
  88 + */
  89 + public function UpdatePanel($check=false,$force=false){
  90 + $url = $this->BT_PANEL.$this->config("UpdatePanel");
  91 +
  92 + $p_data = $this->GetKeyData();
  93 + $p_data['check'] = $check;
  94 + $p_data['force'] = $force;
  95 +
  96 + $result = $this->HttpPostCookie($url,$p_data);
  97 +
  98 + $data = json_decode($result,true);
  99 + return $data;
  100 + }
  101 + /**
  102 + * 申请ssl
  103 + */
  104 + public function ApplyCert($domains,$id){
  105 + $url = $this->BT_PANEL.$this->config("ApplyCert");
  106 + $p_data = $this->GetKeyData();
  107 + $p_data['domains'] = $domains;
  108 + $p_data['auth_type'] = "http";
  109 + $p_data['auth_to'] = $id;
  110 + $p_data['auto_wildcard'] = 0;
  111 + $p_data['id'] = $id;
  112 + $result = $this->HttpPostCookie($url,$p_data);
  113 +
  114 + $data = json_decode($result,true);
  115 + return $data;
  116 + }
  117 + /**
  118 + * 续签ssl
  119 + */
  120 + public function RenewCert($index){
  121 + $url = $this->BT_PANEL.$this->config("RenewCert");
  122 + $p_data = $this->GetKeyData();
  123 +
  124 + $p_data['index'] = $index;
  125 +
  126 + $result = $this->HttpPostCookie($url,$p_data);
  127 + $data = json_decode($result,true);
  128 + return $data;
  129 + }
  130 +
  131 +
  132 +
  133 + /**
  134 + * 获取网站列表
  135 + * @param string $page 当前分页
  136 + * @param string $limit 取出的数据行数
  137 + * @param string $type 分类标识 -1: 分部分类 0: 默认分类
  138 + * @param string $order 排序规则 使用 id 降序:id desc 使用名称升序:name desc
  139 + * @param string $tojs 分页 JS 回调,若不传则构造 URI 分页连接
  140 + * @param string $search 搜索内容
  141 + */
  142 + public function Websites($search='',$page='1',$limit='15',$type='-1',$order='id desc',$tojs=''){
  143 + $url = $this->BT_PANEL.$this->config("Websites");
  144 +
  145 + $p_data = $this->GetKeyData();
  146 + $p_data['p'] = $page;
  147 + $p_data['limit'] = $limit;
  148 + $p_data['type'] = $type;
  149 + $p_data['order'] = $order;
  150 + $p_data['tojs'] = $tojs;
  151 + $p_data['search'] = $search;
  152 +
  153 + $result = $this->HttpPostCookie($url,$p_data);
  154 +
  155 + $data = json_decode($result,true);
  156 + return $data;
  157 + }
  158 +
  159 + /**
  160 + * 获取网站FTP列表
  161 + * @param string $page 当前分页
  162 + * @param string $limit 取出的数据行数
  163 + * @param string $type 分类标识 -1: 分部分类 0: 默认分类
  164 + * @param string $order 排序规则 使用 id 降序:id desc 使用名称升序:name desc
  165 + * @param string $tojs 分页 JS 回调,若不传则构造 URI 分页连接
  166 + * @param string $search 搜索内容
  167 + */
  168 + public function WebFtpList($search='',$page='1',$limit='15',$type='-1',$order='id desc',$tojs=''){
  169 + $url = $this->BT_PANEL.$this->config("WebFtpList");
  170 +
  171 + $p_data = $this->GetKeyData();
  172 + $p_data['p'] = $page;
  173 + $p_data['limit'] = $limit;
  174 + $p_data['type'] = $type;
  175 + $p_data['order'] = $order;
  176 + $p_data['tojs'] = $tojs;
  177 + $p_data['search'] = $search;
  178 +
  179 + $result = $this->HttpPostCookie($url,$p_data);
  180 +
  181 + $data = json_decode($result,true);
  182 + return $data;
  183 + }
  184 +
  185 + /**
  186 + * 获取网站SQL列表
  187 + * @param string $page 当前分页
  188 + * @param string $limit 取出的数据行数
  189 + * @param string $type 分类标识 -1: 分部分类 0: 默认分类
  190 + * @param string $order 排序规则 使用 id 降序:id desc 使用名称升序:name desc
  191 + * @param string $tojs 分页 JS 回调,若不传则构造 URI 分页连接
  192 + * @param string $search 搜索内容
  193 + */
  194 + public function WebSqlList($search='',$page='1',$limit='15',$type='-1',$order='id desc',$tojs=''){
  195 + $url = $this->BT_PANEL.$this->config("WebSqlList");
  196 +
  197 + $p_data = $this->GetKeyData();
  198 + $p_data['p'] = $page;
  199 + $p_data['limit'] = $limit;
  200 + $p_data['type'] = $type;
  201 + $p_data['order'] = $order;
  202 + $p_data['tojs'] = $tojs;
  203 + $p_data['search'] = $search;
  204 +
  205 + $result = $this->HttpPostCookie($url,$p_data);
  206 +
  207 + $data = json_decode($result,true);
  208 + return $data;
  209 + }
  210 +
  211 + /**
  212 + * 获取所有网站分类
  213 + */
  214 + public function Webtypes(){
  215 + $url = $this->BT_PANEL.$this->config("Webtypes");
  216 +
  217 + $p_data = $this->GetKeyData();
  218 +
  219 + $result = $this->HttpPostCookie($url,$p_data);
  220 +
  221 + $data = json_decode($result,true);
  222 + return $data;
  223 + }
  224 +
  225 + /**
  226 + * 获取已安装的 PHP 版本列表
  227 + */
  228 + public function GetPHPVersion(){
  229 + //拼接URL地址
  230 + $url = $this->BT_PANEL.$this->config("GetPHPVersion");
  231 +
  232 + //准备POST数据
  233 + $p_data = $this->GetKeyData(); //取签名
  234 +
  235 + //请求面板接口
  236 + $result = $this->HttpPostCookie($url,$p_data);
  237 +
  238 + //解析JSON数据
  239 + $data = json_decode($result,true);
  240 +
  241 + return $data;
  242 + }
  243 +
  244 + /**
  245 + * 修改指定网站的PHP版本
  246 + * @param [type] $site 网站名
  247 + * @param [type] $php PHP版本
  248 + */
  249 + public function SetPHPVersion($site,$php){
  250 +
  251 + $url = $this->BT_PANEL.$this->config("SetPHPVersion");
  252 +
  253 + $p_data = $this->GetKeyData();
  254 + $p_data['siteName'] = $site;
  255 + $p_data['version'] = $php;
  256 + $result = $this->HttpPostCookie($url,$p_data);
  257 +
  258 + $data = json_decode($result,true);
  259 + return $data;
  260 + }
  261 +
  262 + /**
  263 + * 获取指定网站运行的PHP版本
  264 + * @param [type] $site 网站名
  265 + */
  266 + public function GetSitePHPVersion($site){
  267 + $url = $this->BT_PANEL.$this->config("GetSitePHPVersion");
  268 +
  269 + $p_data = $this->GetKeyData();
  270 + $p_data['siteName'] = $site;
  271 + $result = $this->HttpPostCookie($url,$p_data);
  272 +
  273 + $data = json_decode($result,true);
  274 + return $data;
  275 + }
  276 +
  277 +
  278 + /**
  279 + * 新增网站
  280 + * @param [type] $webname 网站域名 json格式
  281 + * @param [type] $path 网站路径
  282 + * @param [type] $type_id 网站分类ID
  283 + * @param string $type 网站类型
  284 + * @param [type] $version PHP版本
  285 + * @param [type] $port 网站端口
  286 + * @param [type] $ps 网站备注
  287 + * @param [type] $ftp 网站是否开通FTP
  288 + * @param [type] $ftp_username FTP用户名
  289 + * @param [type] $ftp_password FTP密码
  290 + * @param [type] $sql 网站是否开通数据库
  291 + * @param [type] $codeing 数据库编码类型 utf8|utf8mb4|gbk|big5
  292 + * @param [type] $datauser 数据库账号
  293 + * @param [type] $datapassword 数据库密码
  294 + */
  295 + public function AddSite($infoArr=[]){
  296 + $url = $this->BT_PANEL.$this->config("WebAddSite");
  297 + //准备POST数据
  298 + $p_data = $this->GetKeyData(); //取签名
  299 + $p_data['webname'] = $infoArr['webname'];
  300 + $p_data['path'] = $infoArr['path'];
  301 + $p_data['type_id'] = $infoArr['type_id'];
  302 + $p_data['type'] = $infoArr['type'];
  303 + $p_data['version'] = $infoArr['version'];
  304 + $p_data['port'] = $infoArr['port'];
  305 + $p_data['ps'] = $infoArr['ps'];
  306 + $p_data['ftp'] = $infoArr['ftp'];
  307 + $p_data['ftp_username'] = $infoArr['ftp_username'];
  308 + $p_data['ftp_password'] = $infoArr['ftp_password'];
  309 + $p_data['sql'] = $infoArr['sql'];
  310 + $p_data['codeing'] = $infoArr['codeing'];
  311 + $p_data['datauser'] = $infoArr['datauser'];
  312 + $p_data['datapassword'] = $infoArr['datapassword'];
  313 +
  314 +
  315 +
  316 + //请求面板接口
  317 + $result = $this->HttpPostCookie($url,$p_data);
  318 + //var_dump($result);
  319 + //解析JSON数据
  320 + $data = json_decode($result,true);
  321 + return $data;
  322 + }
  323 +
  324 + /**
  325 + * 删除网站
  326 + * @param [type] $id 网站ID
  327 + * @param [type] $webname 网站名称
  328 + * @param [type] $ftp 是否删除关联FTP
  329 + * @param [type] $database 是否删除关联数据库
  330 + * @param [type] $path 是否删除关联网站根目录
  331 + *
  332 + */
  333 + public function WebDeleteSite($id,$webname,$ftp,$database,$path){
  334 + $url = $this->BT_PANEL.$this->config("WebDeleteSite");
  335 +
  336 + $p_data = $this->GetKeyData();
  337 + $p_data['id'] = $id;
  338 + $p_data['webname'] = $webname;
  339 + $p_data['ftp'] = $ftp;
  340 + $p_data['database'] = $database;
  341 + $p_data['path'] = $path;
  342 +
  343 + $result = $this->HttpPostCookie($url,$p_data);
  344 +
  345 + $data = json_decode($result,true);
  346 + return $data;
  347 + }
  348 +
  349 + /**
  350 + * 停用站点
  351 + * @param [type] $id 网站ID
  352 + * @param [type] $name 网站域名
  353 + */
  354 + public function WebSiteStop($id,$name){
  355 + $url = $this->BT_PANEL.$this->config("WebSiteStop");
  356 +
  357 + $p_data = $this->GetKeyData();
  358 + $p_data['id'] = $id;
  359 + $p_data['name'] = $name;
  360 + $result = $this->HttpPostCookie($url,$p_data);
  361 +
  362 + $data = json_decode($result,true);
  363 + return $data;
  364 + }
  365 +
  366 + /**
  367 + * 启用网站
  368 + * @param [type] $id 网站ID
  369 + * @param [type] $name 网站域名
  370 + */
  371 + public function WebSiteStart($id,$name){
  372 + $url = $this->BT_PANEL.$this->config("WebSiteStart");
  373 +
  374 + $p_data = $this->GetKeyData();
  375 + $p_data['id'] = $id;
  376 + $p_data['name'] = $name;
  377 + $result = $this->HttpPostCookie($url,$p_data);
  378 +
  379 + $data = json_decode($result,true);
  380 + return $data;
  381 + }
  382 +
  383 + /**
  384 + * 设置网站到期时间
  385 + * @param [type] $id 网站ID
  386 + * @param [type] $edate 网站到期时间 格式:2019-01-01,永久:0000-00-00
  387 + */
  388 + public function WebSetEdate($id,$edate){
  389 + $url = $this->BT_PANEL.$this->config("WebSetEdate");
  390 +
  391 + $p_data = $this->GetKeyData();
  392 + $p_data['id'] = $id;
  393 + $p_data['edate'] = $edate;
  394 + $result = $this->HttpPostCookie($url,$p_data);
  395 +
  396 + $data = json_decode($result,true);
  397 + return $data;
  398 + }
  399 +
  400 + /**
  401 + * 修改网站备注
  402 + * @param [type] $id 网站ID
  403 + * @param [type] $ps 网站备注
  404 + */
  405 + public function WebSetPs($id,$ps){
  406 + $url = $this->BT_PANEL.$this->config("WebSetPs");
  407 +
  408 + $p_data = $this->GetKeyData();
  409 + $p_data['id'] = $id;
  410 + $p_data['ps'] = $ps;
  411 + $result = $this->HttpPostCookie($url,$p_data);
  412 +
  413 + $data = json_decode($result,true);
  414 + return $data;
  415 + }
  416 +
  417 + /**
  418 + * 获取网站备份列表
  419 + * @param [type] $id 网站ID
  420 + * @param string $page 当前分页
  421 + * @param string $limit 每页取出的数据行数
  422 + * @param string $type 备份类型 目前固定为0
  423 + * @param string $tojs 分页js回调若不传则构造 URI 分页连接 get_site_backup
  424 + */
  425 + public function WebBackupList($id,$page='1',$limit='5',$type='0',$tojs=''){
  426 + $url = $this->BT_PANEL.$this->config("WebBackupList");
  427 +
  428 + $p_data = $this->GetKeyData();
  429 + $p_data['p'] = $page;
  430 + $p_data['limit'] = $limit;
  431 + $p_data['type'] = $type;
  432 + $p_data['tojs'] = $tojs;
  433 + $p_data['search'] = $id;
  434 + $result = $this->HttpPostCookie($url,$p_data);
  435 +
  436 + $data = json_decode($result,true);
  437 + return $data;
  438 + }
  439 +
  440 + /**
  441 + * 创建网站备份
  442 + * @param [type] $id 网站ID
  443 + */
  444 + public function WebToBackup($id){
  445 + $url = $this->BT_PANEL.$this->config("WebToBackup");
  446 +
  447 + $p_data = $this->GetKeyData();
  448 + $p_data['id'] = $id;
  449 + $result = $this->HttpPostCookie($url,$p_data);
  450 +
  451 + $data = json_decode($result,true);
  452 + return $data;
  453 + }
  454 +
  455 + /**
  456 + * 删除网站备份
  457 + * @param [type] $id 网站备份ID
  458 + */
  459 + public function WebDelBackup($id){
  460 + $url = $this->BT_PANEL.$this->config("WebDelBackup");
  461 +
  462 + $p_data = $this->GetKeyData();
  463 + $p_data['id'] = $id;
  464 + $result = $this->HttpPostCookie($url,$p_data);
  465 +
  466 + $data = json_decode($result,true);
  467 + return $data;
  468 + }
  469 +
  470 + /**
  471 + * 删除数据库备份
  472 + * @param [type] $id 数据库备份ID
  473 + */
  474 + public function SQLDelBackup($id){
  475 + $url = $this->BT_PANEL.$this->config("SQLDelBackup");
  476 +
  477 + $p_data = $this->GetKeyData();
  478 + $p_data['id'] = $id;
  479 + $result = $this->HttpPostCookie($url,$p_data);
  480 +
  481 + $data = json_decode($result,true);
  482 + return $data;
  483 + }
  484 +
  485 + /**
  486 + * 备份数据库
  487 + * @param [type] $id 数据库列表ID
  488 + */
  489 + public function SQLToBackup($id){
  490 + $url = $this->BT_PANEL.$this->config("SQLToBackup");
  491 +
  492 + $p_data = $this->GetKeyData();
  493 + $p_data['id'] = $id;
  494 + $result = $this->HttpPostCookie($url,$p_data);
  495 +
  496 + $data = json_decode($result,true);
  497 + return $data;
  498 + }
  499 +
  500 + /**
  501 + * 获取网站域名列表
  502 + * @param [type] $id 网站ID
  503 + * @param boolean $list 固定传true
  504 + */
  505 + public function WebDoaminList($id,$list=true){
  506 + $url = $this->BT_PANEL.$this->config("WebDoaminList");
  507 +
  508 + $p_data = $this->GetKeyData();
  509 + $p_data['search'] = $id;
  510 + $p_data['list'] = $list;
  511 + $result = $this->HttpPostCookie($url,$p_data);
  512 +
  513 + $data = json_decode($result,true);
  514 + return $data;
  515 + }
  516 +
  517 + /**
  518 + * 获取网站列表
  519 + * @param string $search
  520 + * @param int $p
  521 + * @param int $limit
  522 + * @param int $type
  523 + * @return mixed
  524 + */
  525 + public function WebSiteList($search = '', $p = 1, $limit = 20, $type = 0){
  526 + $url = $this->BT_PANEL.$this->config("WebSiteList");
  527 +
  528 + $p_data = $this->GetKeyData();
  529 + $p_data['search'] = $search;
  530 + $p_data['p'] = $p;
  531 + $p_data['limit'] = $limit;
  532 + $p_data['type'] = $type;
  533 + $result = $this->HttpPostCookie($url,$p_data);
  534 +
  535 + $data = json_decode($result,true);
  536 + return $data;
  537 + }
  538 +
  539 + /**
  540 + * 添加域名
  541 + * @param [type] $id 网站ID
  542 + * @param [type] $webname 网站名称
  543 + * @param [type] $domain 要添加的域名:端口 80 端品不必构造端口,多个域名用换行符隔开
  544 + */
  545 + public function WebAddDomain($id,$webname,$domain){
  546 + $url = $this->BT_PANEL.$this->config("WebAddDomain");
  547 +
  548 + $p_data = $this->GetKeyData();
  549 + $p_data['id'] = $id;
  550 + $p_data['webname'] = $webname;
  551 + $p_data['domain'] = $domain;
  552 + $result = $this->HttpPostCookie($url,$p_data);
  553 +
  554 + $data = json_decode($result,true);
  555 + return $data;
  556 + }
  557 +
  558 + /**
  559 + * 删除网站域名
  560 + * @param [type] $id 网站ID
  561 + * @param [type] $webname 网站名
  562 + * @param [type] $domain 网站域名
  563 + * @param [type] $port 网站域名端口
  564 + */
  565 + public function WebDelDomain($id,$webname,$domain,$port){
  566 + $url = $this->BT_PANEL.$this->config("WebDelDomain");
  567 +
  568 + $p_data = $this->GetKeyData();
  569 + $p_data['id'] = $id;
  570 + $p_data['webname'] = $webname;
  571 + $p_data['domain'] = $domain;
  572 + $p_data['port'] = $port;
  573 + $result = $this->HttpPostCookie($url,$p_data);
  574 +
  575 + $data = json_decode($result,true);
  576 + return $data;
  577 + }
  578 +
  579 + /**
  580 + * 获取可选的预定义伪静态列表
  581 + * @param [type] $siteName 网站名
  582 + */
  583 + public function GetRewriteList($siteName){
  584 + $url = $this->BT_PANEL.$this->config("GetRewriteList");
  585 +
  586 + $p_data = $this->GetKeyData();
  587 + $p_data['siteName'] = $siteName;
  588 + $result = $this->HttpPostCookie($url,$p_data);
  589 +
  590 + $data = json_decode($result,true);
  591 + return $data;
  592 + }
  593 +
  594 + /**
  595 + * 获取预置伪静态规则内容(文件内容)
  596 + * @param [type] $path 规则名
  597 + * @param [type] $type 0->获取内置伪静态规则;1->获取当前站点伪静态规则
  598 + */
  599 + public function GetFileBody($path,$type=0){
  600 + $url = $this->BT_PANEL.$this->config("GetFileBody");
  601 + $p_data = $this->GetKeyData();
  602 +// $path_dir = $type?'vhost/rewrite':'rewrite/nginx';
  603 + if ($type == 2) {
  604 + $path_dir = 'vhost/nginx';
  605 + } elseif ($type == 1) {
  606 + $path_dir = 'vhost/rewrite';
  607 + } else {
  608 + $path_dir = 'rewrite/nginx';
  609 + }
  610 +
  611 + //获取当前站点伪静态规则
  612 + ///www/server/panel/vhost/rewrite/user_hvVBT_1.test.com.conf
  613 + //获取内置伪静态规则
  614 + ///www/server/panel/rewrite/nginx/EmpireCMS.conf
  615 + //保存伪静态规则到站点
  616 + ///www/server/panel/vhost/rewrite/user_hvVBT_1.test.com.conf
  617 + ///www/server/panel/rewrite/nginx/typecho.conf
  618 + $p_data['path'] = '/www/server/panel/'.$path_dir.'/'.$path.'.conf';
  619 + //var_dump($p_data['path']);
  620 + $result = $this->HttpPostCookie($url,$p_data);
  621 +
  622 + $data = json_decode($result,true);
  623 + return $data;
  624 + }
  625 +
  626 + /**
  627 + * 保存伪静态规则内容(保存文件内容)
  628 + * @param [type] $path 规则名
  629 + * @param [type] $data 规则内容
  630 + * @param string $encoding 规则编码强转utf-8
  631 + * @param number $type 0->系统默认路径;1->自定义全路径
  632 + */
  633 + public function SaveFileBody($path,$data,$encoding='utf-8',$type=0){
  634 + $url = $this->BT_PANEL.$this->config("SaveFileBody");
  635 + if($type){
  636 + $path_dir = $path;
  637 + }else{
  638 + $path_dir = '/www/server/panel/vhost/rewrite/'.$path.'.conf';
  639 + }
  640 + $p_data = $this->GetKeyData();
  641 + $p_data['path'] = $path_dir;
  642 + $p_data['data'] = $data;
  643 + $p_data['encoding'] = $encoding;
  644 + $result = $this->HttpPostCookie($url,$p_data);
  645 +
  646 + $data = json_decode($result,true);
  647 + return $data;
  648 + }
  649 +
  650 +
  651 +
  652 + /**
  653 + * 设置密码访问网站
  654 + * @param [type] $id 网站ID
  655 + * @param [type] $username 用户名
  656 + * @param [type] $password 密码
  657 + */
  658 + public function SetHasPwd($id,$username,$password){
  659 + $url = $this->BT_PANEL.$this->config("SetHasPwd");
  660 +
  661 + $p_data = $this->GetKeyData();
  662 + $p_data['id'] = $id;
  663 + $p_data['username'] = $username;
  664 + $p_data['password'] = $password;
  665 + $result = $this->HttpPostCookie($url,$p_data);
  666 +
  667 + $data = json_decode($result,true);
  668 + return $data;
  669 + }
  670 +
  671 + /**
  672 + * 关闭密码访问网站
  673 + * @param [type] $id 网站ID
  674 + */
  675 + public function CloseHasPwd($id){
  676 + $url = $this->BT_PANEL.$this->config("CloseHasPwd");
  677 +
  678 + $p_data = $this->GetKeyData();
  679 + $p_data['id'] = $id;
  680 + $result = $this->HttpPostCookie($url,$p_data);
  681 +
  682 + $data = json_decode($result,true);
  683 + return $data;
  684 + }
  685 +
  686 + /**
  687 + * 获取网站日志
  688 + * @param [type] $site 网站名
  689 + */
  690 + public function GetSiteLogs($site){
  691 + $url = $this->BT_PANEL.$this->config("GetSiteLogs");
  692 +
  693 + $p_data = $this->GetKeyData();
  694 + $p_data['siteName'] = $site;
  695 + $result = $this->HttpPostCookie($url,$p_data);
  696 +
  697 + $data = json_decode($result,true);
  698 + return $data;
  699 + }
  700 +
  701 + /**
  702 + * 获取网站盗链状态及规则信息
  703 + * @param [type] $id 网站ID
  704 + * @param [type] $site 网站名
  705 + */
  706 + public function GetSecurity($id,$site){
  707 + $url = $this->BT_PANEL.$this->config("GetSecurity");
  708 +
  709 + $p_data = $this->GetKeyData();
  710 + $p_data['id'] = $id;
  711 + $p_data['name'] = $site;
  712 + $result = $this->HttpPostCookie($url,$p_data);
  713 +
  714 + $data = json_decode($result,true);
  715 + return $data;
  716 + }
  717 +
  718 + /**
  719 + * 设置网站盗链状态及规则信息
  720 + * @param [type] $id 网站ID
  721 + * @param [type] $site 网站名
  722 + * @param [type] $fix URL后缀
  723 + * @param [type] $domains 许可域名
  724 + * @param [type] $status 状态
  725 + */
  726 + public function SetSecurity($id,$site,$fix,$domains,$status){
  727 + $url = $this->BT_PANEL.$this->config("SetSecurity");
  728 +
  729 + $p_data = $this->GetKeyData();
  730 + $p_data['id'] = $id;
  731 + $p_data['name'] = $site;
  732 + $p_data['fix'] = $fix;
  733 + $p_data['domains'] = $domains;
  734 + $p_data['status'] = $status;
  735 + $result = $this->HttpPostCookie($url,$p_data);
  736 +
  737 + $data = json_decode($result,true);
  738 + return $data;
  739 + }
  740 +
  741 + /**
  742 + * 获取网站三项配置开关(防跨站、日志、密码访问)
  743 + * @param [type] $id 网站ID
  744 + * @param [type] $path 网站运行目录
  745 + */
  746 + public function GetDirUserINI($id,$path){
  747 + $url = $this->BT_PANEL.$this->config("GetDirUserINI");
  748 +
  749 + $p_data = $this->GetKeyData();
  750 + $p_data['id'] = $id;
  751 + $p_data['path'] = $path;
  752 + $result = $this->HttpPostCookie($url,$p_data);
  753 +
  754 + $data = json_decode($result,true);
  755 + return $data;
  756 + }
  757 +
  758 + /**
  759 + * 开启强制HTTPS
  760 + * @param [type] $site 网站域名(纯域名)
  761 + */
  762 + public function HttpToHttps($site){
  763 + $url = $this->BT_PANEL.$this->config("HttpToHttps");
  764 +
  765 + $p_data = $this->GetKeyData();
  766 + $p_data['siteName'] = $site;
  767 + $result = $this->HttpPostCookie($url,$p_data);
  768 +
  769 + $data = json_decode($result,true);
  770 + return $data;
  771 + }
  772 +
  773 + /**
  774 + * 关闭强制HTTPS
  775 + * @param [type] $site 域名(纯域名)
  776 + */
  777 + public function CloseToHttps($site){
  778 + $url = $this->BT_PANEL.$this->config("CloseToHttps");
  779 +
  780 + $p_data = $this->GetKeyData();
  781 + $p_data['siteName'] = $site;
  782 + $result = $this->HttpPostCookie($url,$p_data);
  783 +
  784 + $data = json_decode($result,true);
  785 + return $data;
  786 + }
  787 +
  788 + /**
  789 + * 设置SSL域名证书
  790 + * @param [type] $type 类型
  791 + * @param [type] $site 网站名
  792 + * @param [type] $key 证书key
  793 + * @param [type] $csr 证书PEM
  794 + */
  795 + public function SetSSL($type,$site,$key,$csr){
  796 + $url = $this->BT_PANEL.$this->config("SetSSL");
  797 +
  798 + $p_data = $this->GetKeyData();
  799 + $p_data['type'] = $type;
  800 + $p_data['siteName'] = $site;
  801 + $p_data['key'] = $key;
  802 + $p_data['csr'] = $csr;
  803 + $result = $this->HttpPostCookie($url,$p_data);
  804 +
  805 + $data = json_decode($result,true);
  806 + return $data;
  807 +
  808 + }
  809 +
  810 + /**
  811 + * 关闭SSL
  812 + * @param [type] $updateOf 修改状态码
  813 + * @param [type] $site 域名(纯域名)
  814 + */
  815 + public function CloseSSLConf($updateOf,$site){
  816 + $url = $this->BT_PANEL.$this->config("CloseSSLConf");
  817 +
  818 + $p_data = $this->GetKeyData();
  819 + $p_data['updateOf'] = $updateOf;
  820 + $p_data['siteName'] = $site;
  821 + $result = $this->HttpPostCookie($url,$p_data);
  822 +
  823 + $data = json_decode($result,true);
  824 + return $data;
  825 + }
  826 +
  827 + /**
  828 + * 获取SSL状态及证书信息
  829 + * @param [type] $site 域名(纯域名)
  830 + */
  831 + public function GetSSL($site){
  832 + $url = $this->BT_PANEL.$this->config("GetSSL");
  833 +
  834 + $p_data = $this->GetKeyData();
  835 + $p_data['siteName'] = $site;
  836 + $result = $this->HttpPostCookie($url,$p_data);
  837 +
  838 + $data = json_decode($result,true);
  839 + return $data;
  840 + }
  841 +
  842 + /**
  843 + * 获取网站默认文件
  844 + * @param [type] $id 网站ID
  845 + */
  846 + public function WebGetIndex($id){
  847 + $url = $this->BT_PANEL.$this->config("WebGetIndex");
  848 +
  849 + $p_data = $this->GetKeyData();
  850 + $p_data['id'] = $id;
  851 + $result = $this->HttpPostCookie($url,$p_data);
  852 +
  853 + $data = json_decode($result,true);
  854 + return $data;
  855 + }
  856 +
  857 + /**
  858 + * 设置网站默认文件
  859 + * @param [type] $id 网站ID
  860 + * @param [type] $index 内容
  861 + */
  862 + public function WebSetIndex($id,$index){
  863 + $url = $this->BT_PANEL.$this->config("WebSetIndex");
  864 +
  865 + $p_data = $this->GetKeyData();
  866 + $p_data['id'] = $id;
  867 + $p_data['Index'] = $index;
  868 + $result = $this->HttpPostCookie($url,$p_data);
  869 +
  870 + $data = json_decode($result,true);
  871 + return $data;
  872 + }
  873 +
  874 + /**
  875 + * 获取网站流量限制信息
  876 + * @param [type] $id [description]
  877 + */
  878 + public function GetLimitNet($id){
  879 + $url = $this->BT_PANEL.$this->config("GetLimitNet");
  880 +
  881 + $p_data = $this->GetKeyData();
  882 + $p_data['id'] = $id;
  883 + $result = $this->HttpPostCookie($url,$p_data);
  884 +
  885 + $data = json_decode($result,true);
  886 + return $data;
  887 + }
  888 +
  889 + /**
  890 + * 设置网站流量限制信息
  891 + * @param [type] $id 网站ID
  892 + * @param [type] $perserver 并发限制
  893 + * @param [type] $perip 单IP限制
  894 + * @param [type] $limit_rate 流量限制
  895 + */
  896 + public function SetLimitNet($id,$perserver,$perip,$limit_rate){
  897 + $url = $this->BT_PANEL.$this->config("SetLimitNet");
  898 +
  899 + $p_data = $this->GetKeyData();
  900 + $p_data['id'] = $id;
  901 + $p_data['perserver'] = $perserver;
  902 + $p_data['perip'] = $perip;
  903 + $p_data['limit_rate'] = $limit_rate;
  904 + $result = $this->HttpPostCookie($url,$p_data);
  905 +
  906 + $data = json_decode($result,true);
  907 + return $data;
  908 + }
  909 +
  910 + /**
  911 + * 关闭网站流量限制
  912 + * @param [type] $id 网站ID
  913 + */
  914 + public function CloseLimitNet($id){
  915 + $url = $this->BT_PANEL.$this->config("CloseLimitNet");
  916 +
  917 + $p_data = $this->GetKeyData();
  918 + $p_data['id'] = $id;
  919 + $result = $this->HttpPostCookie($url,$p_data);
  920 +
  921 + $data = json_decode($result,true);
  922 + return $data;
  923 + }
  924 +
  925 + /**
  926 + * 获取网站301重定向信息
  927 + * @param [type] $site 网站名
  928 + */
  929 + public function Get301Status($site){
  930 + $url = $this->BT_PANEL.$this->config("Get301Status");
  931 +
  932 + $p_data = $this->GetKeyData();
  933 + $p_data['siteName'] = $site;
  934 + $result = $this->HttpPostCookie($url,$p_data);
  935 +
  936 + $data = json_decode($result,true);
  937 + return $data;
  938 + }
  939 +
  940 + /**
  941 + * 设置网站301重定向信息
  942 + * @param [type] $site 网站名
  943 + * @param [type] $toDomain 目标Url
  944 + * @param [type] $srcDomain 来自Url
  945 + * @param [type] $type 类型
  946 + */
  947 + public function Set301Status($site,$toDomain,$srcDomain,$type){
  948 + $url = $this->BT_PANEL.$this->config("Set301Status");
  949 +
  950 + $p_data = $this->GetKeyData();
  951 + $p_data['siteName'] = $site;
  952 + $p_data['toDomain'] = $toDomain;
  953 + $p_data['srcDomain'] = $srcDomain;
  954 + $p_data['type'] = $type;
  955 + $result = $this->HttpPostCookie($url,$p_data);
  956 +
  957 + $data = json_decode($result,true);
  958 + return $data;
  959 + }
  960 +
  961 + /**
  962 + * 获取网站反代信息及状态
  963 + * @param [type] $site [description]
  964 + */
  965 + public function GetProxyList($site){
  966 + $url = $this->BT_PANEL.$this->config("GetProxyList");
  967 +
  968 + $p_data = $this->GetKeyData();
  969 + $p_data['sitename'] = $site;
  970 + $result = $this->HttpPostCookie($url,$p_data);
  971 +
  972 + $data = json_decode($result,true);
  973 + return $data;
  974 + }
  975 +
  976 + /**
  977 + * 添加网站反代信息
  978 + * @param [type] $cache 是否缓存
  979 + * @param [type] $proxyname 代理名称
  980 + * @param [type] $cachetime 缓存时长 /小时
  981 + * @param [type] $proxydir 代理目录
  982 + * @param [type] $proxysite 反代URL
  983 + * @param [type] $todomain 目标域名
  984 + * @param [type] $advanced 高级功能:开启代理目录
  985 + * @param [type] $sitename 网站名
  986 + * @param [type] $subfilter 文本替换json格式[{"sub1":"百度","sub2":"白底"},{"sub1":"","sub2":""}]
  987 + * @param [type] $type 开启或关闭 0关;1开
  988 + */
  989 + public function CreateProxy($cache,$proxyname,$cachetime,$proxydir,$proxysite,$todomain,$advanced,$sitename,$subfilter,$type){
  990 + $url = $this->BT_PANEL.$this->config("CreateProxy");
  991 +
  992 + $p_data = $this->GetKeyData();
  993 + $p_data['cache'] = $cache;
  994 + $p_data['proxyname'] = $proxyname;
  995 + $p_data['cachetime'] = $cachetime;
  996 + $p_data['proxydir'] = $proxydir;
  997 + $p_data['proxysite'] = $proxysite;
  998 + $p_data['todomain'] = $todomain;
  999 + $p_data['advanced'] = $advanced;
  1000 + $p_data['sitename'] = $sitename;
  1001 + $p_data['subfilter'] = $subfilter;
  1002 + $p_data['type'] = $type;
  1003 + $result = $this->HttpPostCookie($url,$p_data);
  1004 +
  1005 + $data = json_decode($result,true);
  1006 + return $data;
  1007 + }
  1008 +
  1009 + /**
  1010 + * 添加网站反代信息
  1011 + * @param [type] $cache 是否缓存
  1012 + * @param [type] $proxyname 代理名称
  1013 + * @param [type] $cachetime 缓存时长 /小时
  1014 + * @param [type] $proxydir 代理目录
  1015 + * @param [type] $proxysite 反代URL
  1016 + * @param [type] $todomain 目标域名
  1017 + * @param [type] $advanced 高级功能:开启代理目录
  1018 + * @param [type] $sitename 网站名
  1019 + * @param [type] $subfilter 文本替换json格式[{"sub1":"百度","sub2":"白底"},{"sub1":"","sub2":""}]
  1020 + * @param [type] $type 开启或关闭 0关;1开
  1021 + */
  1022 + public function ModifyProxy($cache,$proxyname,$cachetime,$proxydir,$proxysite,$todomain,$advanced,$sitename,$subfilter,$type){
  1023 + $url = $this->BT_PANEL.$this->config("ModifyProxy");
  1024 +
  1025 + $p_data = $this->GetKeyData();
  1026 + $p_data['cache'] = $cache;
  1027 + $p_data['proxyname'] = $proxyname;
  1028 + $p_data['cachetime'] = $cachetime;
  1029 + $p_data['proxydir'] = $proxydir;
  1030 + $p_data['proxysite'] = $proxysite;
  1031 + $p_data['todomain'] = $todomain;
  1032 + $p_data['advanced'] = $advanced;
  1033 + $p_data['sitename'] = $sitename;
  1034 + $p_data['subfilter'] = $subfilter;
  1035 + $p_data['type'] = $type;
  1036 + $result = $this->HttpPostCookie($url,$p_data);
  1037 +
  1038 + $data = json_decode($result,true);
  1039 + return $data;
  1040 + }
  1041 +
  1042 + /**
  1043 + * 获取网站域名绑定二级目录信息
  1044 + * @param [type] $id 网站ID
  1045 + */
  1046 + public function GetDirBinding($id){
  1047 + $url = $this->BT_PANEL.$this->config("GetDirBinding");
  1048 +
  1049 + $p_data = $this->GetKeyData();
  1050 + $p_data['id'] = $id;
  1051 + $result = $this->HttpPostCookie($url,$p_data);
  1052 +
  1053 + $data = json_decode($result,true);
  1054 + return $data;
  1055 + }
  1056 +
  1057 + /**
  1058 + * 设置网站域名绑定二级目录
  1059 + * @param [type] $id 网站ID
  1060 + * @param [type] $domain 域名
  1061 + * @param [type] $dirName 目录
  1062 + */
  1063 + public function AddDirBinding($id,$domain,$dirName){
  1064 + $url = $this->BT_PANEL.$this->config("AddDirBinding");
  1065 +
  1066 + $p_data = $this->GetKeyData();
  1067 + $p_data['id'] = $id;
  1068 + $p_data['domain'] = $domain;
  1069 + $p_data['dirName'] = $dirName;
  1070 + $result = $this->HttpPostCookie($url,$p_data);
  1071 +
  1072 + $data = json_decode($result,true);
  1073 + return $data;
  1074 + }
  1075 +
  1076 + /**
  1077 + * 删除网站域名绑定二级目录
  1078 + * @param [type] $dirid 子目录ID
  1079 + */
  1080 + public function DelDirBinding($dirid){
  1081 + $url = $this->BT_PANEL.$this->config("DelDirBinding");
  1082 +
  1083 + $p_data = $this->GetKeyData();
  1084 + $p_data['id'] = $dirid;
  1085 + $result = $this->HttpPostCookie($url,$p_data);
  1086 +
  1087 + $data = json_decode($result,true);
  1088 + return $data;
  1089 + }
  1090 +
  1091 + /**
  1092 + * 获取网站子目录绑定伪静态信息
  1093 + * @param [type] $dirid 子目录绑定ID
  1094 + */
  1095 + public function GetDirRewrite($dirid,$type=0){
  1096 + $url = $this->BT_PANEL.$this->config("GetDirRewrite");
  1097 +
  1098 + $p_data = $this->GetKeyData();
  1099 + $p_data['id'] = $dirid;
  1100 + if($type){
  1101 + $p_data['add'] = 1;
  1102 + }
  1103 + $result = $this->HttpPostCookie($url,$p_data);
  1104 +
  1105 + $data = json_decode($result,true);
  1106 + return $data;
  1107 + }
  1108 +
  1109 + /**
  1110 + * 修改FTP账号密码
  1111 + * @param [type] $id FTPID
  1112 + * @param [type] $ftp_username 用户名
  1113 + * @param [type] $new_password 密码
  1114 + */
  1115 + public function SetUserPassword($id,$ftp_username,$new_password){
  1116 + $url = $this->BT_PANEL.$this->config("SetUserPassword");
  1117 +
  1118 + $p_data = $this->GetKeyData();
  1119 + $p_data['id'] = $id;
  1120 + $p_data['ftp_username'] = $ftp_username;
  1121 + $p_data['new_password'] = $new_password;
  1122 + $result = $this->HttpPostCookie($url,$p_data);
  1123 +
  1124 + $data = json_decode($result,true);
  1125 + return $data;
  1126 + }
  1127 +
  1128 + /**
  1129 + * 修改SQL账号密码
  1130 + * @param [type] $id SQLID
  1131 + * @param [type] $ftp_username 用户名
  1132 + * @param [type] $new_password 密码
  1133 + */
  1134 + public function ResDatabasePass($id,$name,$password){
  1135 + $url = $this->BT_PANEL.$this->config("ResDatabasePass");
  1136 +
  1137 + $p_data = $this->GetKeyData();
  1138 + $p_data['id'] = $id;
  1139 + $p_data['name'] = $name;
  1140 + $p_data['password'] = $password;
  1141 + $result = $this->HttpPostCookie($url,$p_data);
  1142 +
  1143 + $data = json_decode($result,true);
  1144 + return $data;
  1145 + }
  1146 +
  1147 + /**
  1148 + * 启用/禁用FTP
  1149 + * @param [type] $id FTPID
  1150 + * @param [type] $username 用户名
  1151 + * @param [type] $status 状态 0->关闭;1->开启
  1152 + */
  1153 + public function SetStatus($id,$username,$status){
  1154 + $url = $this->BT_PANEL.$this->config("SetStatus");
  1155 +
  1156 + $p_data = $this->GetKeyData();
  1157 + $p_data['id'] = $id;
  1158 + $p_data['username'] = $username;
  1159 + $p_data['status'] = $status;
  1160 + $result = $this->HttpPostCookie($url,$p_data);
  1161 +
  1162 + $data = json_decode($result,true);
  1163 + return $data;
  1164 + }
  1165 +
  1166 + /**
  1167 + * 宝塔一键部署列表
  1168 + * @param string $search 搜索关键词
  1169 + * @return [type] [description]
  1170 + */
  1171 + public function deployment($search=''){
  1172 + if($search){
  1173 + $url = $this->BT_PANEL.$this->config("deployment").'&search='.$search;
  1174 + }else{
  1175 + $url = $this->BT_PANEL.$this->config("deployment");
  1176 + }
  1177 +
  1178 + $p_data = $this->GetKeyData();
  1179 + $result = $this->HttpPostCookie($url,$p_data);
  1180 +
  1181 + $data = json_decode($result,true);
  1182 + return $data;
  1183 + }
  1184 +
  1185 + /**
  1186 + * 宝塔一键部署执行
  1187 + * @param [type] $dname 部署程序名
  1188 + * @param [type] $site_name 部署到网站名
  1189 + * @param [type] $php_version PHP版本
  1190 + */
  1191 + public function SetupPackage($dname,$site_name,$php_version){
  1192 + $url = $this->BT_PANEL.$this->config("SetupPackage");
  1193 +
  1194 + $p_data = $this->GetKeyData();
  1195 + $p_data['dname'] = $dname;
  1196 + $p_data['site_name'] = $site_name;
  1197 + $p_data['php_version'] = $php_version;
  1198 + $result = $this->HttpPostCookie($url,$p_data);
  1199 +
  1200 + $data = json_decode($result,true);
  1201 + return $data;
  1202 + }
  1203 +
  1204 + /**
  1205 + * 设置文件权限
  1206 + * @param $path
  1207 + * @param $user
  1208 + * @param $access
  1209 + * @param $all
  1210 + * @return mixed
  1211 + */
  1212 + public function setFileAccess($path, $user, $access, $all) {
  1213 + $url = $this->BT_PANEL.$this->config("SetFileAccess");
  1214 + $p_data = $this->GetKeyData();
  1215 + $p_data['user'] = $user;
  1216 + $p_data['access'] = $access;
  1217 + $p_data['all'] = $all;
  1218 + $p_data['filename'] = $path;
  1219 + $result = $this->HttpPostCookie($url,$p_data);
  1220 +
  1221 + $data = json_decode($result,true);
  1222 + return $data;
  1223 + }
  1224 +
  1225 + /**
  1226 + * 获取队列
  1227 + * @return mixed
  1228 + */
  1229 + public function getProcessList()
  1230 + {
  1231 + $url = $this->BT_PANEL.$this->config("GetProcessList");
  1232 + $p_data = $this->GetKeyData();
  1233 + $result = $this->HttpPostCookie($url,$p_data);
  1234 +
  1235 + $data = json_decode($result,true);
  1236 + return $data;
  1237 + }
  1238 +
  1239 + /**
  1240 + * 停止队列
  1241 + * @param $program
  1242 + * @param int $numprocs
  1243 + * @return mixed
  1244 + */
  1245 + public function stopProcess($program, $numprocs = 1)
  1246 + {
  1247 + $url = $this->BT_PANEL.$this->config("StopProcess");
  1248 + $p_data = $this->GetKeyData();
  1249 + $p_data['program'] = $program;
  1250 + $p_data['numprocs'] = $numprocs;
  1251 + $result = $this->HttpPostCookie($url,$p_data);
  1252 +
  1253 + $data = json_decode($result,true);
  1254 + return $data;
  1255 + }
  1256 +
  1257 + /**
  1258 + * 启动队列
  1259 + * @param $program
  1260 + * @param int $numprocs
  1261 + * @return mixed
  1262 + */
  1263 + public function startProcess($program, $numprocs = 1)
  1264 + {
  1265 + $url = $this->BT_PANEL.$this->config("StartProcess");
  1266 + $p_data = $this->GetKeyData();
  1267 + $p_data['program'] = $program;
  1268 + $p_data['numprocs'] = $numprocs;
  1269 + $result = $this->HttpPostCookie($url,$p_data);
  1270 +
  1271 + $data = json_decode($result,true);
  1272 + return $data;
  1273 + }
  1274 +
  1275 + /**
  1276 + * 设置文件权限
  1277 + * @param $path
  1278 + * @return mixed
  1279 + */
  1280 + public function DeleteFile($path) {
  1281 + $url = $this->BT_PANEL.$this->config("DeleteFile");
  1282 + $p_data = $this->GetKeyData();
  1283 + $p_data['path'] = $path;
  1284 + $result = $this->HttpPostCookie($url,$p_data);
  1285 +
  1286 + $data = json_decode($result,true);
  1287 + return $data;
  1288 + }
  1289 +
  1290 + /**
  1291 + * 更新网站目录
  1292 + * @param $site_id
  1293 + * @param $path
  1294 + * @return mixed
  1295 + */
  1296 + public function SetPath($site_id, $path)
  1297 + {
  1298 + $url = $this->BT_PANEL.$this->config("SetPath");
  1299 + $p_data = $this->GetKeyData();
  1300 + $p_data['id'] = $site_id;
  1301 + $p_data['path'] = $path;
  1302 + $result = $this->HttpPostCookie($url,$p_data);
  1303 + $data = json_decode($result,true);
  1304 + return $data;
  1305 + }
  1306 +
  1307 +
  1308 + /**
  1309 + * 更新运行目录
  1310 + * @param $site_id
  1311 + * @param $path
  1312 + * @return mixed
  1313 + */
  1314 + public function SetSiteRunPath($site_id, $path)
  1315 + {
  1316 + $url = $this->BT_PANEL.$this->config("SetSiteRunPath");
  1317 + $p_data = $this->GetKeyData();
  1318 + $p_data['id'] = $site_id;
  1319 + $p_data['runPath'] = $path;
  1320 + $result = $this->HttpPostCookie($url,$p_data);
  1321 + $data = json_decode($result,true);
  1322 + return $data;
  1323 + }
  1324 +
  1325 +
  1326 + /**
  1327 + * 构造带有签名的关联数组
  1328 + */
  1329 + public function GetKeyData(){
  1330 + $now_time = time();
  1331 + $p_data = array(
  1332 + 'request_token' => md5($now_time.''.md5($this->BT_KEY)),
  1333 + 'request_time' => $now_time
  1334 + );
  1335 + return $p_data;
  1336 + }
  1337 +
  1338 + /**
  1339 + * 发起POST请求
  1340 + * @param String $url 目标网填,带http://
  1341 + * @param Array|String $data 欲提交的数据
  1342 + * @return string
  1343 + */
  1344 + private function HttpPostCookie($url, $data,$timeout = 60)
  1345 + {
  1346 + //定义cookie保存位置
  1347 + $cookie_file='./'.md5($this->BT_PANEL).'.cookie';
  1348 + if(!file_exists($cookie_file)){
  1349 + $fp = fopen($cookie_file,'w+');
  1350 + fclose($fp);
  1351 + }
  1352 +
  1353 + $ch = curl_init();
  1354 + curl_setopt($ch, CURLOPT_URL, $url);
  1355 + curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
  1356 + curl_setopt($ch, CURLOPT_POST, 1);
  1357 + curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
  1358 + curl_setopt($ch, CURLOPT_COOKIEJAR, $cookie_file);
  1359 + curl_setopt($ch, CURLOPT_COOKIEFILE, $cookie_file);
  1360 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  1361 + curl_setopt($ch, CURLOPT_HEADER, 0);
  1362 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  1363 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  1364 + $output = curl_exec($ch);
  1365 + curl_close($ch);
  1366 + return $output;
  1367 + }
  1368 +
  1369 + /**
  1370 + * 加载宝塔数据接口
  1371 + * @param [type] $str [description]
  1372 + * @return [type] [description]
  1373 + */
  1374 + private function config($str){
  1375 + $config = config("bt");
  1376 + //var_dump($config);
  1377 + return $config[$str];
  1378 + }
  1379 +}
  1380 +
  1381 +
  1382 +
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2023/09/18
  6 + * Time: 20:56
  7 + */
  8 +
  9 +namespace App\Repositories;
  10 +
  11 +use App\Repositories\Bt\Bt;
  12 +use Illuminate\Support\Facades\Log;
  13 +
  14 +/**
  15 + * Class BtRepository
  16 + * @package App\Repositories
  17 + */
  18 +class BtRepository
  19 +{
  20 + public $instance = [];
  21 +
  22 + /**
  23 + * @param $domain
  24 + * @return array|bool
  25 + */
  26 + public function createBtSite($domain, $rewrite = [], $domain_list = [])
  27 + {
  28 + $domain_array = parse_url($domain);
  29 + $host = $domain_array['host'] ?? $domain_array['path'];
  30 +
  31 + // TODO 验证当前服务器是否已经创建过了
  32 + $bt = $this->getBtObject();
  33 + $site_list = $bt->WebSiteList($host);
  34 + if (!empty($site_list['data'])) {
  35 + return ['site_id' => $site_list['data'][0]['id']];
  36 + }
  37 +
  38 +// if ($domain_list) {
  39 +// $web_name = ['domain' => $host, 'domainlist' => $domain_list, 'count' => 0];
  40 +// } else {
  41 +// $host_array = explode('.', $host);
  42 +// if (FALSE == empty($host_array[0]) && $host_array[0] == 'www')
  43 +// unset($host_array[0]);
  44 +// $domain_top = implode('.', $host_array);
  45 +// if ($domain_top == $host){
  46 +// $web_name = ['domain' => $host, 'domainlist' => ['www.'.$domain_top, '*.' . $host], 'count' => 0];
  47 +// }else{
  48 +// $web_name = ['domain' => $host, 'domainlist' => [$domain_top, '*.' . $domain_top], 'count' => 0];
  49 +// }
  50 +// }
  51 + $web_name = ['domain' => $host, 'domainlist' => $domain_list, 'count' => 0];
  52 +
  53 + $array = [
  54 + 'webname' => json_encode($web_name),
  55 + 'path' => '/www/wwwroot/createSite',
  56 + 'type_id' => 0,
  57 + 'type' => 'PHP',
  58 + 'version' => '80',
  59 + 'port' => '80',
  60 + 'ps' => $host,
  61 + 'ftp' => false,
  62 + 'ftp_username' => '',
  63 + 'ftp_password' => '',
  64 + 'sql' => false,
  65 + 'codeing' => '',
  66 + 'datauser' => '',
  67 + 'datapassword' => '',
  68 + ];
  69 +
  70 +
  71 + $result = $bt->AddSite($array);
  72 +// result 返回信息
  73 +// $result = ['siteStatus' => true, 'siteId' => 39, 'ftpStatus' => false, 'databaseStatus' => false,];
  74 + if (empty($result) || empty($result['siteId']))
  75 + return false;
  76 + // 更新站点目录 更新站点运行目录
  77 + $bt->SetPath($result['siteId'], public_path());
  78 +
  79 + // 删除 .user.ini
  80 + $bt->DeleteFile('/www/wwwroot/c-globalso/public/.user.ini');
  81 + $bt->DeleteFile('/www/wwwroot/c-globalso/.user.ini');
  82 +// $bt->SetSiteRunPath($result['siteId'], '/');
  83 + #---------------------------------------------------------------------------------------------------------------
  84 + // 伪静态设置
  85 +// $htaccess = $this->rewrite301($rewrite);
  86 +// if ($htaccess)
  87 +// $bt->SaveFileBody($host, $htaccess);
  88 + // 获取配置
  89 + // 设置Nginx配置
  90 +// $nginx_config = $this->getAfterNginxConfStr($host);
  91 +// $bt->SaveFileBody('/www/server/panel/vhost/nginx/' . $host . '.conf', $nginx_config, 'utf-8', 1);
  92 + #---------------------------------------------------------------------------------------------------------------
  93 +
  94 + return ['site_id' => $result['siteId']];
  95 + }
  96 +
  97 + /**
  98 + * 申请免费证书
  99 + * @param string $domain
  100 + * @param array $rewrite
  101 + * @param array $otherDomain
  102 + * @param int $is_https
  103 + * @return bool
  104 + */
  105 + public function applySsl($domain, $rewrite = [], $otherDomain = [], $is_https = 0)
  106 + {
  107 + $domain_array = parse_url($domain);
  108 + $host = $domain_array['host'] ?? $domain_array['path'];
  109 +
  110 + $bt = $this->getBtObject();
  111 + $site_list = $bt->WebSiteList($host);
  112 + if (empty($site_list['data'])) {
  113 + $site = $this->createBtSite($domain,$rewrite,$otherDomain);
  114 + $site_id = $site['site_id'];
  115 + }else{
  116 + $site_id = $site_list['data'][0]['id'];
  117 + $host = $site_list['data'][0]['name'];
  118 + }
  119 +
  120 + // 获取站点域名
  121 + $site_domain = $bt->WebDoaminList($site_id);
  122 + $domain_list = [];
  123 + foreach ($site_domain as $val) {
  124 + if (FALSE === strpos($val['name'], '*')) {
  125 + array_push($domain_list, $val['name']);
  126 + }
  127 + }
  128 +
  129 + //添加站点域名
  130 + $this->addDomain($site_id, $host, $otherDomain, $site_domain);
  131 +
  132 + //还原配置
  133 + $nginx_config = $this->getBeforeNginxConfStr($host);
  134 + $bt->SaveFileBody('/www/server/panel/vhost/nginx/' . $host . '.conf', $nginx_config, 'utf-8', 1);
  135 +
  136 + // 如果已经申请了ssl证书, 并且证书有效期超过3天, 那么就使用已经申请好的证书
  137 + $ssl = $bt->GetSSL($host);
  138 + $is_set_status = false;//是否需要设置证书
  139 + if (FALSE == empty($ssl['cert_data']['notAfter']) && strtotime($ssl['cert_data']['notAfter']) - time() > 259200) {
  140 + $key = $ssl['key'];
  141 + $cer = $ssl['csr'];
  142 + $is_set_status = !$ssl['status'];
  143 + } else {
  144 + // 申请证书时需要将重写规则情况, 不然会跳转到其他地方
  145 + $bt->SaveFileBody($host, '');
  146 + // 如果没有证书, 申请证书并设置证书
  147 + $rs = $bt->ApplyCert(json_encode($domain_list),$site_id);
  148 + if(isset($rs['status']) && $rs['status']){
  149 + //申请成功,设置证书
  150 + $key = $rs['private_key'];
  151 + $cer = $rs['cert'];
  152 + $is_set_status = true;
  153 + }else{
  154 + $key = '';
  155 + $cer = '';
  156 + }
  157 + }
  158 + if($key && $cer && $is_set_status){
  159 + $bt->SetSSL(1, $host, $key, $cer);
  160 + }
  161 +
  162 + $bt->DeleteFile('/www/wwwroot/c-globalso/public/.user.ini');
  163 + $bt->DeleteFile('/www/wwwroot/c-globalso/.user.ini');
  164 + $htaccess = $this->rewrite301($rewrite,$is_https);
  165 + if ($htaccess)
  166 + $bt->SaveFileBody($host, $htaccess);
  167 + // 更新配置
  168 + $nginx_config = $this->getAfterNginxConfStr($host);
  169 + $bt->SaveFileBody('/www/server/panel/vhost/nginx/' . $host . '.conf', $nginx_config, 'utf-8', 1);
  170 + return true;
  171 + }
  172 +
  173 +
  174 + /**
  175 + * 设置ssl证书
  176 + * @param string $domain
  177 + * @param array $rewrite
  178 + * @param array $otherDomain
  179 + * @param string $private_key
  180 + * @param string $cert
  181 + * @param int $is_https
  182 + * @return bool
  183 + */
  184 + public function setSsl($domain, $rewrite = [], $otherDomain = [], $private_key = '', $cert = '', $is_https = 0)
  185 + {
  186 + $domain_array = parse_url($domain);
  187 + $host = $domain_array['host'] ?? $domain_array['path'];
  188 + $bt = $this->getBtObject();
  189 + $site_list = $bt->WebSiteList($host);
  190 + if (empty($site_list['data'])) {
  191 + $site = $this->createBtSite($domain,$rewrite,$otherDomain);
  192 + $site_id = $site['site_id'];
  193 + }else{
  194 + $host = $site_list['data'][0]['name'];
  195 + $site_id = $site_list['data'][0]['id'];
  196 + }
  197 +
  198 +
  199 + //添加站点域名
  200 + $this->addDomain($site_id, $host, $otherDomain);
  201 +
  202 + // 还原配置
  203 + $nginx_config = $this->getBeforeNginxConfStr($host);
  204 + $bt->SaveFileBody('/www/server/panel/vhost/nginx/' . $host . '.conf', $nginx_config, 'utf-8', 1);
  205 + $bt->SetSSL(1, $host, $private_key, $cert);
  206 +
  207 + $bt->DeleteFile('/www/wwwroot/c-globalso/public/.user.ini');
  208 + $bt->DeleteFile('/www/wwwroot/c-globalso/.user.ini');
  209 +
  210 + // 设置301跳转
  211 + $htaccess = $this->rewrite301($rewrite,$is_https);
  212 + if ($htaccess)
  213 + $bt->SaveFileBody($host, $htaccess);
  214 + // 更新配置
  215 + $nginx_config = $this->getAfterNginxConfStr($host);
  216 + $bt->SaveFileBody('/www/server/panel/vhost/nginx/' . $host . '.conf', $nginx_config, 'utf-8', 1);
  217 +
  218 + return true;
  219 + }
  220 +
  221 + /**
  222 + * 获取bt对象
  223 + * @param string $key
  224 + * @param string $panel
  225 + * @return Bt
  226 + */
  227 + public function getBtObject($key = '', $panel = '')
  228 + {
  229 + $key = $key ?: env('BT_KEY');
  230 + $panel = $panel ?: env('BT_PANEL');
  231 + $object_key = md5($key . $panel);
  232 + if (empty($this->instance[$object_key])) {
  233 + $bt = new Bt($panel, $key);
  234 + $this->instance[$object_key] = $bt;
  235 + }
  236 + return $this->instance[$object_key];
  237 + }
  238 +
  239 + /**
  240 + * 获取配置前的文件内容
  241 + * @param $domain
  242 + * @return string|string[]
  243 + */
  244 + public function getBeforeNginxConfStr($domain)
  245 + {
  246 + $bt = $this->getBtObject();
  247 + $conf = $bt->GetFileBody($domain, 2);
  248 +
  249 + //如果有变量标识,去掉变量标识
  250 + if (FALSE !== strpos($conf['data'], 'map $domain_prefix')){
  251 + $conf['data'] = str_replace($this->domainPrefixConf(),'',$conf['data']);
  252 + //去掉自定义配置
  253 + $conf['data'] = str_replace($this->customConf($domain),'root ' . public_path() . ';', $conf['data']);
  254 + }
  255 +
  256 +// preg_match('/set \$root[\S\s]+root \$root;/iU', $conf['data'], $matches);
  257 +// if (FALSE == empty($matches[0])) {
  258 +// $conf['data'] = str_replace($matches[0], 'root ' . public_path() . ';', $conf['data']);
  259 +// }
  260 + return $conf['data'];
  261 + }
  262 +
  263 + /**
  264 + * 获取配置后的文件内容
  265 + * @param $domain
  266 + * @return mixed
  267 + */
  268 + public function getAfterNginxConfStr($domain)
  269 + {
  270 + $bt = $this->getBtObject();
  271 + $conf = $bt->GetFileBody($domain, 2);
  272 +// $conf['data'] = file_get_contents(storage_path('logs/nginx.conf'));
  273 + // 如果没有变量, 添加变量识别
  274 + if (FALSE === strpos($conf['data'], 'map $domain_prefix')){
  275 + $conf['data'] = $this->domainPrefixConf() . $conf['data'];
  276 + // 替换自定义配置
  277 + $conf['data'] = str_replace('root ' . public_path() . ';', $this->customConf($domain), $conf['data']);
  278 + }
  279 +
  280 + return $conf['data'];
  281 + }
  282 +
  283 +
  284 + /**
  285 + * 需要定制修改的配置
  286 + * @return string
  287 + */
  288 + public function customConf($domain): string
  289 + {
  290 + $string = ' root '.public_path().'; # 设置根目录
  291 +
  292 + set $domain_prefix "";
  293 + if ($host ~* "^(?<domain_prefix>[^.]+)\.") {
  294 + set $domain_prefix $1;
  295 + }
  296 +
  297 + location / {
  298 + root '.public_path().'/'.$domain.'; # 设置根目录
  299 + if ($is_prefix_in_string = 1) {
  300 + root '.public_path().'/'.$domain.'/$domain_prefix;
  301 + }
  302 + try_files $uri $uri/ /404/index.html =404;
  303 + }
  304 +
  305 + location ~ ^/(api|search) {
  306 + root '.public_path().'; # 设置/api /search /.well-known的根目录
  307 + try_files $uri $uri/ /index.php?$query_string;
  308 + }
  309 +
  310 + location ~ ^/(well-known) {
  311 + root '.public_path().';
  312 + try_files $uri $uri/ /404/index.html =404;
  313 + }
  314 + error_page 403 /404/index.html;';
  315 + return $string;
  316 + }
  317 +
  318 +
  319 + /**
  320 + * 解析301跳转
  321 + * @param $rewrite
  322 + * @param $is_https
  323 + * @return string
  324 + */
  325 + public function rewrite301($rewrite,$is_https)
  326 + {
  327 + $string = '# 屏蔽蜘蛛
  328 + if ($http_user_agent ~* "(Knowledge|SiteAuditBot|DotBot|rogerbot|MJ12bot|MegaIndex|Paracrawl|HubSpot|serpstatbot|SemrushBot|DataForSeoBot|BLEXBot|Bytespider|Sogou|Seekport|HubSpot|Barkrowler|PetalBot|Amazonbot|RainBot|test-bot|fidget-spinner-bot)") {
  329 + return 444;
  330 + }
  331 + # 设置跳转
  332 + ';
  333 + if (FALSE == is_array($rewrite))
  334 + return $string;
  335 +
  336 + foreach ($rewrite as $val) {
  337 + if (empty($val['origin']) || empty($val['target']))
  338 + continue;
  339 + $origin_tmp = parse_url($val['origin']);
  340 + $origin = $origin_tmp['host'] ?? $origin_tmp['path'];
  341 + $target_tmp = parse_url($val['target']);
  342 + $target = $target_tmp['host'] ?? $target_tmp['path'];
  343 + $string .= '
  344 + if ($host ~ "^' . $origin . '"){
  345 + return 301 $scheme://' . $target . '$request_uri;
  346 + }
  347 + ';
  348 + }
  349 + if($is_https){
  350 + $string .= '
  351 + #HTTP_TO_HTTPS_START
  352 + if ($server_port !~ 443){
  353 + rewrite ^(/.*)$ https://$host$1 permanent;
  354 + }
  355 + ';
  356 + }
  357 + return $string;
  358 + }
  359 +
  360 +
  361 + /**
  362 + * 配置变量
  363 + * @return string
  364 + */
  365 + public function domainPrefixConf()
  366 + {
  367 + return 'map $domain_prefix $is_prefix_in_string {
  368 + default 0; en 1; zh 1; fr 1; de 1; ko 1; ja 1; es 1; ar 1; pt 1; ru 1; af 1; sq 1;
  369 + am 1; hy 1; az 1; eu 1; be 1; bn 1; bs 1; bg 1; ca 1; ceb 1; zh-CN 1; zh-TW 1; co 1;
  370 + hr 1; cs 1; da 1; nl 1; eo 1; et 1; fi 1; fy 1; gl 1; ka 1; el 1; gu 1; ht 1; ha 1; haw 1;
  371 + iw 1; hi 1; hmn 1; hu 1; is 1; ig 1; id 1; ga 1; it 1; jw 1; kn 1; kk 1; km 1; rw 1;
  372 + ku 1; ky 1; lo 1; la 1; lv 1; lt 1; lb 1; mk 1; mg 1; ms 1; ml 1; mt 1; mi 1; mr 1; mn 1;
  373 + my 1; ne 1; no 1; ny 1; or 1; ps 1; fa 1; pl 1; pa 1; ro 1; sm 1; gd 1; sr 1; st 1; sn 1;
  374 + sd 1; si 1; sk 1; sl 1; so 1; su 1; sw 1; sv 1; tl 1; tg 1; ta 1; tt 1; te 1; th 1; tr 1;
  375 + tk 1; uk 1; ur 1; ug 1; uz 1; vi 1; cy 1; xh 1; yi 1; yo 1; zu 1;
  376 +}';
  377 + }
  378 +
  379 +
  380 + //添加站点域名
  381 + protected function addDomain($site_id, $domain, $otherDomains, $site_domain = [])
  382 + {
  383 + $bt = $this->getBtObject();
  384 + if(!$site_domain){
  385 + $site_domain = $bt->WebDoaminList($site_id);
  386 + }
  387 +
  388 + $site_domain = array_column($site_domain, 'name');
  389 + foreach ($otherDomains as $k => $otherDomain) {
  390 + // 如果已经包含, 就不添加
  391 + if (in_array($otherDomain, $site_domain)) {
  392 + unset($otherDomains[$k]);
  393 + }
  394 + }
  395 +
  396 + if ($otherDomains) {
  397 + $otherDomains = implode(',', $otherDomains);
  398 +
  399 + $res = $bt->WebAddDomain($site_id, $domain, $otherDomains);
  400 + if (!$res['status']) {
  401 + return false;
  402 + }
  403 + }
  404 + return true;
  405 + }
  406 +
  407 + /**
  408 + * 创建amp站点
  409 + * @param $domain
  410 + * @param $key
  411 + * @param $cer
  412 + * @return array|bool
  413 + * @author Akun
  414 + * @date 2024/02/18 17:04
  415 + */
  416 + public function createBtSiteAmp($domain,$key,$cer)
  417 + {
  418 + $domain_array = parse_url($domain);
  419 + $host = $domain_array['host'] ?? $domain_array['path'];
  420 + $host_array = explode('.',$host);
  421 + if(count($host_array) <= 2){
  422 + array_unshift($host_array,'m');
  423 + }else{
  424 + $host_array[0] = 'm';
  425 + }
  426 + $host = implode('.',$host_array);
  427 +
  428 + // 验证当前服务器是否已经创建过了
  429 + $bt = $this->getBtObject();
  430 + $site_list = $bt->WebSiteList($host);
  431 + if (!empty($site_list['data'])) {
  432 + $site_id = $site_list['data'][0]['id'];
  433 + }else{
  434 +
  435 + $web_name = ['domain' => $host, 'domainlist' => [], 'count' => 0];
  436 +
  437 + $array = [
  438 + 'webname' => json_encode($web_name),
  439 + 'path' => '/www/wwwroot/createSite',
  440 + 'type_id' => 0,
  441 + 'type' => 'PHP',
  442 + 'version' => '80',
  443 + 'port' => '80',
  444 + 'ps' => $host,
  445 + 'ftp' => false,
  446 + 'ftp_username' => '',
  447 + 'ftp_password' => '',
  448 + 'sql' => false,
  449 + 'codeing' => '',
  450 + 'datauser' => '',
  451 + 'datapassword' => '',
  452 + ];
  453 +
  454 +
  455 + $result = $bt->AddSite($array);
  456 +
  457 + if (empty($result) || empty($result['siteId']))
  458 + return false;
  459 +
  460 + $site_id = $result['siteId'];
  461 +
  462 + // 更新站点目录 更新站点运行目录
  463 + $bt->SetPath($site_id, public_path());
  464 +
  465 + // 删除 .user.ini
  466 + $bt->DeleteFile('/www/wwwroot/c-globalso/public/.user.ini');
  467 + $bt->DeleteFile('/www/wwwroot/c-globalso/.user.ini');
  468 + }
  469 +
  470 + if(empty($key) || empty($cer)){
  471 + $ssl = $bt->GetSSL($host);
  472 + $is_set_status = false;//是否需要设置证书
  473 + if (FALSE == empty($ssl['cert_data']['notAfter']) && strtotime($ssl['cert_data']['notAfter']) - time() > 259200) {
  474 + // 如果已经申请了ssl证书, 并且证书有效期超过3天, 那么就使用已经申请好的证书
  475 + $key = $ssl['key'];
  476 + $cer = $ssl['csr'];
  477 + $is_set_status = !$ssl['status'];
  478 + } else {
  479 + // 如果没有证书, 申请证书并设置证书
  480 + $bt->SaveFileBody($host, ''); // 申请证书时需要将重写规则清空, 不然会跳转到其他地方
  481 + $rs = $bt->ApplyCert(json_encode([$host]),$site_id);
  482 + if(isset($rs['status']) && $rs['status']){
  483 + //申请成功,设置证书
  484 + $key = $rs['private_key'];
  485 + $cer = $rs['cert'];
  486 + $is_set_status = true;
  487 + }else{
  488 + $key = '';
  489 + $cer = '';
  490 + }
  491 + }
  492 + }else{
  493 + $is_set_status = true;
  494 + }
  495 +
  496 + if($key && $cer && $is_set_status){
  497 + $bt->SetSSL(1, $host, $key, $cer);
  498 + }
  499 +
  500 + // 伪静态设置
  501 + $bt->SaveFileBody($host, 'location / {
  502 + try_files $uri $uri/ /index.php?$query_string;
  503 +}');
  504 +
  505 + return ['site_id' => $site_id];
  506 + }
  507 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2023/8/31
  6 + * Time: 14:54
  7 + */
  8 +
  9 +namespace App\Repositories;
  10 +
  11 +use App\Helper\Translate;
  12 +use App\Models\CustomModule\CustomModule;
  13 +use App\Models\CustomModule\CustomModuleCategory;
  14 +use App\Models\Module\Module;
  15 +use App\Models\Module\ModuleCategory;
  16 +use App\Models\RouteMap\RouteMap;
  17 +use App\Models\WebSetting\Translate as WebTranslate;
  18 +
  19 +/**
  20 + * Class StaticHtmlRepository
  21 + * @package App\Repositories
  22 + */
  23 +class StaticHtmlRepository
  24 +{
  25 +
  26 + /**
  27 + * 通过域名和路由 获取主语种HTML
  28 + * @param string $domain
  29 + * @param string $route
  30 + * @return string
  31 + */
  32 + public function getMainHtml($domain, $route)
  33 + {
  34 + $html = '';
  35 + return $html;
  36 + }
  37 +
  38 + /**
  39 + * 5.0生成路径
  40 + */
  41 + public function getProjectRoutePath5($project,$route,$page): string
  42 + {
  43 + $routerMap = RouteMap::where("project_id",$project->id)->where("route",$route)->where("path","")->first();
  44 + if (empty($routerMap)){
  45 + $routerMap = RouteMap::where("project_id",$project->id)->where("route",$route)->first();
  46 + }
  47 + if (!empty($routerMap)){
  48 + if ($routerMap->source == "news"){
  49 + $route = "news/".$route;
  50 + }elseif($routerMap->source == "blog" || $routerMap->source == "blogs"){
  51 + $route = "blogs/".$route;
  52 + }elseif ($routerMap->source == "news_category"){
  53 + if ($route == "news"){
  54 + $route = $page == null || $page == 1 ? $route : $route . "/page";
  55 + }else{
  56 + $route = $page == null || $page == 1 ? "news_catalog/".$route : "news_catalog/".$route."/page";
  57 + }
  58 + }elseif ($routerMap->source == "blog_category"){
  59 + if ($route == "blog"){
  60 + $route = $page == null || $page == 1 ? $route : $route."/page";
  61 + }else{
  62 + $route = $page == null || $page == 1 ? "blog_catalog/".$route : "blog_catalog/".$route."/page";
  63 + }
  64 + }elseif ($routerMap->source == "product_category"){
  65 + $route = $page == null || $page == 1 ? $route : $route."/page";
  66 + }elseif ($routerMap->source == "module_category"){
  67 + $moduleCategory = CustomModuleCategory::getModuleCategoryAndExtendById($project->id,$routerMap->source_id);
  68 + if (!empty($moduleCategory->getExtend->route)){
  69 + if ($moduleCategory->getExtend->route == $route){
  70 + $route = $moduleCategory->route;
  71 + }else{
  72 + $route = $moduleCategory->getExtend->route."_catalog/".$moduleCategory->route."/page";
  73 + }
  74 + }else{
  75 + $route = $moduleCategory->route."/page";
  76 + }
  77 + }elseif ($routerMap->source == "module"){
  78 + $modules = CustomModule::where("project_id",$project->id)->where("id",$routerMap->source_id)->where("status",0)->first();
  79 + $moduleCategoryInfo = CustomModule::getModuleCategory($project->id,$modules);
  80 + if (isset($moduleCategoryInfo->getExtend->route) && !empty($moduleCategoryInfo->getExtend->route)){
  81 + $route = $moduleCategoryInfo->route."/".$modules->route;
  82 + }
  83 + }else{
  84 + $route = $route == "index" ? "/" : $route;
  85 + }
  86 + }else{
  87 + if ($route == "products"){
  88 + if ($page == null || $page == 1){
  89 + }else{
  90 + $route = $route."/page";
  91 + }
  92 + }elseif ($route == "news"){
  93 + }elseif ($route == "blog"){
  94 + $route = $page == null || $page == 1 ? "blog_catalog/".$route : "blog_catalog/".$route."/page";
  95 + }else{
  96 + $route = $route == "index" ? "/" : $route;
  97 + }
  98 + }
  99 + return $route;
  100 + }
  101 +
  102 + /**
  103 + * 6.0生成路径
  104 + */
  105 + public function getProjectRoutePath6($project,$route): string
  106 + {
  107 + $routerMap = RouteMap::where("project_id",$project->id)->where("route",$route)->first();
  108 + if (!empty($routerMap)){
  109 + if ($routerMap->source == "news"){
  110 + $route = "news/".$route;
  111 + }elseif($routerMap->source == "blog"){
  112 + $route = "blogs/".$route;
  113 + }elseif($routerMap->source == "module"){
  114 + $modules = CustomModule::where("project_id",$project->id)->where("id",$routerMap->source_id)->where("status",0)->first();
  115 + $moduleCategoryInfo = CustomModule::getModuleCategory($project->id,$modules);
  116 + if (isset($moduleCategoryInfo->route) && !empty($moduleCategoryInfo->route)){
  117 + $route = $moduleCategoryInfo->route."/".$route;
  118 + }
  119 + }else{
  120 + $route = $route == "index" ? "/" : $route;
  121 + }
  122 + }else{
  123 + $route = $route == "index" ? "/" : $route;
  124 + }
  125 + return $route;
  126 + }
  127 +
  128 + public function compactUrl($project,$route,$page): string
  129 + {
  130 + //是否是5.0升级项目
  131 + if (isset($project->update_info["is_update"]) && $project->update_info["is_update"] == 1){
  132 + //5.0生成路径
  133 + $path = $this->getProjectRoutePath5($project,$route,$page);
  134 + }else{
  135 + //6.0生成路径
  136 + $path = $this->getProjectRoutePath6($project,$route);
  137 + }
  138 + return $path;
  139 + }
  140 +
  141 +
  142 + /**
  143 + * 通过域名和路由以及目标语种 获取小语种HTML
  144 + * @param string $domain
  145 + * @param string $route
  146 + * @param string $tl
  147 + * @return string
  148 + */
  149 + public function getOtherLangHtml($domain, $route, $tl)
  150 + {
  151 + $path = '通过域名和路由获取主语种静态文件路径';
  152 + if (is_file($path)) {
  153 + $main_html = file_get_contents($path);
  154 + } else {
  155 + $main_html = $this->getMainHtml($domain, $route);
  156 + }
  157 + $html = '通过主语种HTML生成小语种HTML 并处理小语种特有的内容';
  158 + return $html;
  159 + }
  160 +
  161 + /**
  162 + * 获取翻译后的HTML
  163 + * TODO HTML转dom, 提取需要渲染的词, 翻译关键词, 根据节点还原关键词, 清除dom, 返回HTML
  164 + * @param string $html 原HTML
  165 + * @param string $tl 目标语种
  166 + * @param string $sl 原语种
  167 + * @return mixed
  168 + */
  169 + public function getTranHtml($project,string $html, string $tl,$route,$page, string $sl = 'auto')
  170 + {
  171 + $dom = str_get_html($html);
  172 +// file_put_contents(public_path("aaa.html"), $html);
  173 + if (is_bool($dom)){
  174 + return $html;
  175 + }
  176 + $texts = $dom->find("text");
  177 +
  178 + $description = $dom->find("meta[name=description]",0);
  179 + $keywords = $dom->find("meta[name=keywords]",0);
  180 + // 组装需要翻译的内容 HTML内文案、meta description、meta keywords
  181 + $need_tran = [];
  182 + //处理图片alt
  183 + $images = $dom->find("img");
  184 + foreach ($images as $img){
  185 + $alt = $img->alt;
  186 + if($alt){
  187 + $need_tran[] = $alt;
  188 + }
  189 + }
  190 + //处理a标签title
  191 + $aTitles = $dom->find("a");
  192 + foreach ($aTitles as $aTitle){
  193 + $title = $aTitle->title;
  194 + if($title){
  195 + $need_tran[] = $title;
  196 + }
  197 + }
  198 + foreach ($texts as $k=>$text) {
  199 + $tag= $text->parent()->tag;
  200 + if (in_array($tag, ['script', 'style', 'root']))
  201 + continue;
  202 +
  203 + $string = trim($text->text());
  204 + if (empty($string))
  205 + continue;
  206 +
  207 + $country_class = '';
  208 + if (method_exists($text->parent()->parent(),"find") && $text->parent()->parent()->find("b")) {
  209 + $country_class = $text->parent()->parent()->find("b",0)->class;
  210 + }
  211 + if(FALSE !== strpos($country_class, 'country-flag'))
  212 + continue;
  213 + $need_tran[] = htmlspecialchars_decode(html_entity_decode($string));
  214 + }
  215 + if (isset($description->attr['content'])){
  216 + $need_tran[] = $description->attr['content'];
  217 + }
  218 + if (isset($keywords->attr['content'])){
  219 + $need_tran[] = $keywords->attr['content'];
  220 + }
  221 +
  222 + // 翻译内容字符串, 最多翻译三次, 超过三次没有结果, 返回原文
  223 + $tran_string = [];
  224 + if ($need_tran) {
  225 + $i = 0;
  226 + $tl_tran = $tl == "zh-ct" ? "zh-TW" : $tl;
  227 + TranslateArray:
  228 + $tran_result = Translate::translate($need_tran, $tl_tran, $sl);
  229 + if (!isset($tran_result[0]) || empty($tran_result[0]['code'] || $tran_result[0]['code'] != 200)) {
  230 + if ($i >= 3)
  231 + return $html;
  232 + $i++;
  233 + goto TranslateArray;
  234 + }
  235 +
  236 + $tran_string = $tran_result[0]['texts'];
  237 + }
  238 +
  239 + //组装路由
  240 + $page = $page == null || $page == 1 ? "" : "/".$page;
  241 + $route = $this->compactUrl($project,$route,$page);
  242 + $url = $route.$page;
  243 + //图片翻译校对数据
  244 + $webImageTranslate = WebTranslate::where("alias",$tl)->where("url",$url)->where("type",WebTranslate::$imageType)->first();
  245 + $webImageAllTranslate = WebTranslate::where("alias",$tl)->where("url","All")->where("type",WebTranslate::$imageType)->first();
  246 + $imageAllData = !empty($webImageAllTranslate) ? json_decode($webImageAllTranslate->data,true) : [];
  247 + $imageSelfData = !empty($webImageTranslate) ? json_decode($webImageTranslate->data,true) : [];
  248 + $imageData = array_merge($imageAllData,$imageSelfData);
  249 + //文本翻译校对数据
  250 + $webTextTranslate = WebTranslate::where("alias",$tl)->where("url",$url)->where("type",WebTranslate::$textType)->first();
  251 + $webTextAllTranslate = WebTranslate::where("alias",$tl)->where("url","All")->where("type",WebTranslate::$textType)->first();
  252 + $textAllData = !empty($webTextAllTranslate) ? json_decode($webTextAllTranslate->data,true) : [];
  253 + $textSelfData = !empty($webTextTranslate) ? json_decode($webTextTranslate->data,true) : [];
  254 + $textData = array_merge($textSelfData, $textAllData);
  255 + // 图片按照节点还原
  256 + $tmp = [];
  257 + foreach ($images as $img){
  258 + $alt = $img->alt;
  259 + if($alt){
  260 + $tmp[] = $alt;
  261 + $key = count($tmp) - 1;
  262 + if (!empty($imageData) && isset($imageData[$alt])){
  263 + $img->attr['alt'] = $imageData[$alt];
  264 + }else{
  265 + $img->attr['alt'] = $tran_string[$key];
  266 + }
  267 + }
  268 + }
  269 +
  270 + foreach ($aTitles as $aTitle){
  271 + $title = $aTitle->title;
  272 + if($title){
  273 + $tmp[] = $title;
  274 + $key = count($tmp) - 1;
  275 + if (!empty($textData) && isset($textData[$title])){
  276 + $aTitle->attr['title'] = $textData[$title];
  277 + }else{
  278 + $aTitle->attr['title'] = $tran_string[$key];
  279 + }
  280 + }
  281 + }
  282 +
  283 + foreach ($texts as $text) {
  284 + $tag= $text->parent()->tag;
  285 + if (in_array($tag, ['script', 'style', 'root']))
  286 + continue;
  287 +
  288 + $string = trim($text->text());
  289 + if (empty($string))
  290 + continue;
  291 +
  292 + $country_class = '';
  293 + if (method_exists($text->parent()->parent(),"find") && $text->parent()->parent()->find("b")) {
  294 + $country_class = $text->parent()->parent()->find("b",0)->class;
  295 + }
  296 + if(FALSE !== strpos($country_class, 'country-flag'))
  297 + continue;
  298 +
  299 + $tmp[] = htmlspecialchars_decode(html_entity_decode($string));
  300 + // FIXME 查找校对内容中是否有当前值 优先使用校对内容,没有获取翻译内容
  301 + $key = count($tmp) - 1;
  302 +// dump($string);
  303 + $string = html_entity_decode($string);
  304 + if (!empty($textData) && isset($textData[$string])){
  305 +// dump("数据库:".$textData[$string]);
  306 + $text->outertext = $textData[$string];
  307 + }else{
  308 +// dump("翻译:".$tran_string[$key]);
  309 + $text->outertext = $tran_string[$key];
  310 + }
  311 + }
  312 + // 按照节点还原 description、keywords
  313 + $tmp[] = $description;
  314 + $key = count($tmp) - 1;
  315 + if (isset($description->attr['content'])){
  316 + $dom->find("meta[name=description]")[0]->attr['content'] = $tran_string[$key];
  317 + }
  318 + $tmp[] = $keywords;
  319 + $key = count($tmp) - 1;
  320 + if (isset($description->attr['keywords'])){
  321 + $dom->find("meta[name=keywords]")[0]->attr['content'] = $tran_string[$key];
  322 + }
  323 +
  324 + // 保存修改 清除缓存
  325 + $html_string = $dom->save();
  326 + $dom->clear();
  327 + return $html_string;
  328 + }
  329 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2024/1/6
  6 + * Time: 14:00
  7 + */
  8 +namespace App\Repositories;
  9 +
  10 +use App\Models\SyncSubmitTask\SyncSubmitTask;
  11 +use App\Models\Visit\Visit;
  12 +
  13 +/**
  14 + * Class SyncSubmitRepository
  15 + * @package App\Repositories
  16 + */
  17 +class SyncSubmitRepository
  18 +{
  19 + /**
  20 + * 上线站点引流
  21 + * @param $ip
  22 + * @param $url
  23 + * @param $user_agent
  24 + * @param string $referrer_url
  25 + * @param int $device_port
  26 + * @param int $traffic
  27 + * @return bool
  28 + */
  29 + public function trafficVisit($ip, $url, $user_agent, $referrer_url = '', $device_port = Visit::DEVICE_PC, $traffic = SyncSubmitTask::TRAFFIC_DEFAULT)
  30 + {
  31 + if (empty($ip) || $ip == '127.0.0.1')
  32 + return false;
  33 + if ($this->isBot($user_agent))
  34 + return false;
  35 + $url_array = parse_url($url);
  36 + if (empty($url_array['host']))
  37 + return false;
  38 +
  39 + // 检查重置来源URL
  40 + $referrer_url = $this->initReferrer($referrer_url);
  41 + // 头信息中带有这些信息, 代表是手机端, 重置设备类型
  42 + if (preg_match('/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|Mobile|wap|windowsce|ucweb/', $user_agent)) {
  43 + $device_port = 2;
  44 + }
  45 +
  46 + // 组装字段数据
  47 + $array = [
  48 + 'ip' => $ip,
  49 + 'domain' => $url_array['host'],
  50 + 'referer' => $referrer_url,
  51 + 'user_agent' => $user_agent,
  52 + 'data' => [
  53 + 'url' => $url,
  54 + 'domain' => $url_array['scheme'] . '://' . $url_array['host'],
  55 + 'device_port' => in_array($device_port, array_keys(Visit::deviceMap())) ? $device_port : Visit::DEVICE_PC,
  56 + 'referrer_url' => $referrer_url
  57 + ]
  58 + ];
  59 + SyncSubmitTask::createTask($array, SyncSubmitTask::TYPE_VISIT, $traffic);
  60 + return true;
  61 + }
  62 +
  63 + /**
  64 + * 通过头信息,判断是否是蜘蛛爬虫
  65 + * @param $agent
  66 + * @return bool
  67 + */
  68 + public function isBot($agent)
  69 + {
  70 + $spiderSite= ["TencentTraveler", "Baiduspider+", "BaiduGame", "Googlebot", "msnbot", "Sosospider+", "Sogou web spider", "ia_archiver", "Yahoo! Slurp", "YoudaoBot",
  71 + "Yahoo Slurp", "MSNBot", "Java (Often spam bot)", "BaiDuSpider", "Voila", "Yandex bot", "BSpider", "twiceler", "Sogou Spider", "Speedy Spider", "Google AdSense",
  72 + "Heritrix", "Python-urllib", "Alexa (IA Archiver)", "Ask", "Exabot", "Custo", "OutfoxBot/YodaoBot", "yacy", "SurveyBot", "legs", "lwp-trivial", "Nutch", "StackRambler",
  73 + "The web archive (IA Archiver)", "Perl tool", "MJ12bot", "Netcraft", "MSIECrawler", "WGet tools", "larbin", "Fish search", "yandex.com/bots", "google.com/bot",
  74 + "bingbot", "YandexMobileBot", "BingPreview", "AhrefsBot", "bot"
  75 + ];
  76 +
  77 + foreach($spiderSite as $val) {
  78 + $str = strtolower($val);
  79 + if (strpos($agent, $str) !== false) {
  80 + return true;
  81 + }
  82 + }
  83 + return false;
  84 + }
  85 +
  86 + /**
  87 + * 按照规则重置referrer信息
  88 + * TODO 如果来自特定网站的原样返回, 其他的重置到google
  89 + * @param $referrer
  90 + * @return string
  91 + */
  92 + public function initReferrer($referrer)
  93 + {
  94 + if (empty($referrer))
  95 + return '';
  96 + if (preg_match('/google|facebook|bing|yahoo|youtobe|linkedin|messefrankfurt|yandex|tiktok|twitter|instagram|reddit|telegram|pinterest|tumblr/', $referrer)) {
  97 + return $referrer;
  98 + }else{
  99 + return 'https://www.google.com/';
  100 + }
  101 + }
  102 +}
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2023/10/26
  6 + * Time: 13:55
  7 + */
  8 +namespace App\Repositories;
  9 +
  10 +/**
  11 + * Class ToolRepository
  12 + * @package App\Repositories
  13 + */
  14 +class ToolRepository
  15 +{
  16 + /**
  17 + * @param $url
  18 + * @param $data
  19 + * @param string $method
  20 + * @param array $header
  21 + * @param int $time_out
  22 + * @return array
  23 + */
  24 + public function curlRequest($url, $data, $method = 'POST', $header = [], $time_out = 60)
  25 + {
  26 + $ch = curl_init();
  27 + curl_setopt($ch, CURLOPT_TIMEOUT, $time_out);
  28 + curl_setopt($ch, CURLOPT_URL, $url);
  29 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  30 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
  31 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
  32 + if ($data)
  33 + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
  34 + curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge([
  35 + 'Expect:',
  36 + 'Content-type: application/json',
  37 + 'Accept: application/json',
  38 + ], $header)
  39 + );
  40 + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
  41 + $response = curl_exec($ch);
  42 + $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  43 + curl_close($ch);
  44 + return [$code, $response];
  45 + }
  46 +
  47 + /**
  48 + * 多请求批处理
  49 + * @param $host
  50 + * @param $request_urls
  51 + * @return array
  52 + */
  53 + public function batCurlblobr($request_urls)
  54 + {
  55 +// //脚本开始的毫秒时刻
  56 +// $start = microtime(true);
  57 +
  58 + //打开一个curl批处理句柄
  59 + $mh = curl_multi_init();
  60 + $headers = [
  61 + "X-BLOBR-KEY:" . $this->key
  62 + ];
  63 + $ch = [];
  64 + foreach ($request_urls as $key => $url) {
  65 + //初始化cURL会话
  66 + $ch[$key] = curl_init($url);
  67 + //设置curl传输选项
  68 + curl_setopt($ch[$key], CURLOPT_RETURNTRANSFER, true);
  69 + curl_setopt($ch[$key], CURLOPT_FOLLOWLOCATION, true);
  70 + curl_setopt($ch[$key], CURLOPT_ENCODING, "");
  71 + curl_setopt($ch[$key], CURLOPT_MAXREDIRS, 10);
  72 +// curl_setopt($ch[$key], CURLOPT_TIMEOUT, $this->time_out);
  73 + curl_setopt($ch[$key], CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
  74 + curl_setopt($ch[$key], CURLOPT_CUSTOMREQUEST, 'GET');
  75 + curl_setopt($ch[$key], CURLOPT_HTTPHEADER, $headers);
  76 +// curl_setopt($ch[$key], CURLOPT_HEADER, 0);
  77 + //关闭https请求验证
  78 +// if (strpos($url,'https')){
  79 +// curl_setopt ( $ch[$key], CURLOPT_SSL_VERIFYPEER, false );
  80 +// curl_setopt ( $ch[$key], CURLOPT_SSL_VERIFYHOST, 2 );
  81 +// }
  82 + //向批处理句柄中添加单独的curl句柄
  83 + curl_multi_add_handle($mh, $ch[$key]);
  84 + }
  85 + $running = null;
  86 + //执行批处理句柄
  87 + do {
  88 + $mrc = curl_multi_exec($mh, $running);
  89 + } while ($mrc == CURLM_CALL_MULTI_PERFORM);
  90 +
  91 + while ($running && $mrc == CURLM_OK) {
  92 + if (curl_multi_select($mh) != -1) {
  93 + do {
  94 + $mrc = curl_multi_exec($mh, $running);
  95 + } while ($mrc == CURLM_CALL_MULTI_PERFORM);
  96 + }
  97 + }
  98 +
  99 + $res = [];
  100 + //获取内容
  101 + foreach ($request_urls as $k => $url) {
  102 + //关闭执行完的子句柄
  103 + curl_multi_remove_handle($mh, $ch[$k]);
  104 + //返回获取的输出文本流
  105 + $res[$k] = curl_multi_getcontent($ch[$k]);
  106 + }
  107 + //5.关闭父curl
  108 + curl_multi_close($mh);
  109 +
  110 +// $end = microtime(true) - $start;
  111 +// file_put_contents(__DIR__ . '/exec_time.log', $end . PHP_EOL, FILE_APPEND);
  112 + return $res;
  113 + }
  114 +
  115 +
  116 + /**
  117 + * 多请求批处理
  118 + * @param $headers
  119 + * @param $request_urls
  120 + * @return array
  121 + */
  122 + public function batCurl($request_urls, $headers = [])
  123 + {
  124 +// //脚本开始的毫秒时刻
  125 +// $start = microtime(true);
  126 +
  127 + //打开一个curl批处理句柄
  128 + $mh = curl_multi_init();
  129 + $ch = [];
  130 + foreach ($request_urls as $key => $url) {
  131 + //初始化cURL会话
  132 + $ch[$key] = curl_init($url);
  133 + //设置curl传输选项
  134 + curl_setopt($ch[$key], CURLOPT_RETURNTRANSFER, true);
  135 + curl_setopt($ch[$key], CURLOPT_FOLLOWLOCATION, true);
  136 + curl_setopt($ch[$key], CURLOPT_ENCODING, "");
  137 + curl_setopt($ch[$key], CURLOPT_MAXREDIRS, 10);
  138 + curl_setopt($ch[$key], CURLOPT_TIMEOUT, 30);
  139 + curl_setopt($ch[$key], CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
  140 + curl_setopt($ch[$key], CURLOPT_CUSTOMREQUEST, 'GET');
  141 + curl_setopt($ch[$key], CURLOPT_HTTPHEADER, $headers);
  142 +// curl_setopt($ch[$key], CURLOPT_HEADER, 0);
  143 + //关闭https请求验证
  144 +// if (strpos($url,'https')){
  145 +// curl_setopt ( $ch[$key], CURLOPT_SSL_VERIFYPEER, false );
  146 +// curl_setopt ( $ch[$key], CURLOPT_SSL_VERIFYHOST, 2 );
  147 +// }
  148 + //向批处理句柄中添加单独的curl句柄
  149 + curl_multi_add_handle($mh, $ch[$key]);
  150 + }
  151 + $running = null;
  152 + //执行批处理句柄
  153 + do {
  154 + $mrc = curl_multi_exec($mh, $running);
  155 + } while ($mrc == CURLM_CALL_MULTI_PERFORM);
  156 +
  157 + while ($running && $mrc == CURLM_OK) {
  158 + if (curl_multi_select($mh) != -1) {
  159 + do {
  160 + $mrc = curl_multi_exec($mh, $running);
  161 + } while ($mrc == CURLM_CALL_MULTI_PERFORM);
  162 + }
  163 + }
  164 +
  165 + $res = [];
  166 + //获取内容
  167 + foreach ($request_urls as $k => $url) {
  168 + //关闭执行完的子句柄
  169 + curl_multi_remove_handle($mh, $ch[$k]);
  170 + //返回获取的输出文本流
  171 + $res[$k] = curl_multi_getcontent($ch[$k]);
  172 + }
  173 + //5.关闭父curl
  174 + curl_multi_close($mh);
  175 +
  176 +// $end = microtime(true) - $start;
  177 +// file_put_contents(__DIR__ . '/exec_time.log', $end . PHP_EOL, FILE_APPEND);
  178 + return $res;
  179 + }
  180 +
  181 + /**
  182 + * 替换特殊词汇
  183 + * @param $data
  184 + * @return array
  185 + */
  186 + public function filterString($data)
  187 + {
  188 + if (is_array($data)) {
  189 + foreach ($data as $key => $val) {
  190 + $data[$key] = $this->filterString($val);
  191 + }
  192 + } else {
  193 + $data = ' ' . $data;
  194 + $array = "/\(\w.*\)| company| Company| inc| Inc| Co| co| Ltd| ltd| Llc| llc| Import And Export| Limited| limited|,|\./";
  195 + $result = preg_replace($array, '', $data);
  196 + return $result == ' ' ? '' : $result;
  197 + }
  198 + return $data;
  199 + }
  200 +}
  1 +<?php
  2 +
  3 +
  4 +namespace App\Services\Html;
  5 +
  6 +
  7 +use App\Models\Blog\Blog;
  8 +use App\Models\News\News;
  9 +use App\Models\Product\Category;
  10 +use App\Models\Product\CategoryRelated;
  11 +use App\Models\Product\Keyword;
  12 +use App\Models\Product\Product;
  13 +use App\Models\RouteMap\RouteMap;
  14 +use App\Models\WebSetting\SettingNum;
  15 +use App\Models\WebSetting\WebSetting;
  16 +use App\Models\WebSetting\WebSettingAmp;
  17 +use App\Models\WebSetting\WebSettingSeo;
  18 +
  19 +class AmpService
  20 +{
  21 + /**
  22 + * 获取首页html
  23 + * @param $project
  24 + * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
  25 + * @author Akun
  26 + * @date 2024/03/14 15:04
  27 + */
  28 + public static function getIndexHtml($project)
  29 + {
  30 + //站点配置
  31 + $project_config = self::getProjectConfig($project->id);
  32 +
  33 + //产品所有分类
  34 + $category = self::getProductsCategory($project->id);
  35 +
  36 + //排序最前的3个产品
  37 + $products = self::getProductsList($project->id, 1, 3)['data'];
  38 +
  39 + //排序最前的3篇新闻
  40 + $news = self::getNewsBlogList($project->id, 1, 1, 3)['data'];
  41 +
  42 + //排序最前的3篇博客
  43 + $blogs = AmpService::getNewsBlogList($project->id, 2, 1, 3)['data'];
  44 +
  45 + //当前页面地址
  46 + $current_url = self::getCurrentUrl($project->domain);
  47 +
  48 + return view('amp/index', compact('project_config', 'category', 'products', 'news', 'blogs', 'current_url'));
  49 + }
  50 +
  51 + /**
  52 + * 获取路由页html
  53 + * @param $project
  54 + * @param $route
  55 + * @param $source
  56 + * @param $page
  57 + * @return \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
  58 + * @author Akun
  59 + * @date 2024/03/14 15:05
  60 + */
  61 + public static function getHtmlByRoute($project, $route, $source, $page)
  62 + {
  63 + //站点配置
  64 + $project_config = self::getProjectConfig($project->id);
  65 +
  66 + //产品所有分类
  67 + $category = self::getProductsCategory($project->id);
  68 +
  69 + //固定菜单页面
  70 + if ($route == '404') {
  71 + //404页面
  72 + $current_url = self::getCurrentUrl($project->domain, '/404/');
  73 + return view('amp/404', compact('project_config', 'category', 'current_url'));
  74 + } elseif ($route == 'contact-us') {
  75 + //contact-us页面
  76 + $current_url = self::getCurrentUrl($project->domain, '/contact-us/');
  77 + return view('amp/contact', compact('project_config', 'category', 'current_url'));
  78 + } elseif ($route == 'about-us') {
  79 + //about-us页面
  80 + $current_url = self::getCurrentUrl($project->domain, '/aboout-us/');
  81 + return view('amp/about', compact('project_config', 'category', 'current_url'));
  82 + } elseif ($route == 'products') {
  83 + //产品列表
  84 + $products = self::getProductsList($project->id, $page, 8);
  85 +
  86 + //当前分类详情
  87 + $category_info = self::getCategoryInfo($project->id, 0);
  88 +
  89 + $current_url = self::getCurrentUrl($project->domain, '/' . $category_info['route'] . '/' . ($page > 1 ? $page . '/' : ''));
  90 +
  91 + return view('amp/products', compact('project_config', 'category', 'products', 'category_info', 'page', 'current_url'));
  92 + } elseif ($route == 'news') {
  93 + //新闻列表
  94 + $news = self::getNewsBlogList($project->id, 1, $page, 5);
  95 +
  96 + $current_url = self::getCurrentUrl($project->domain, '/news/' . ($page > 1 ? $page . '/' : ''));
  97 + return view('amp/news', compact('project_config', 'category', 'news', 'page', 'current_url'));
  98 + } elseif ($route == 'blog') {
  99 + //博客列表
  100 + $blogs = self::getNewsBlogList($project->id, 2, $page, 5);
  101 +
  102 + $current_url = self::getCurrentUrl($project->domain, '/blog/' . ($page > 1 ? $page . '/' : ''));
  103 + return view('amp/blogs', compact('project_config', 'category', 'blogs', 'page', 'current_url'));
  104 + } elseif (strpos($route, 'top-search') !== false) {
  105 + //top-search页面
  106 + $pageService = new PageService();
  107 + $search_list = $pageService->getProductKeywordsByLetter($project, $route, $page);
  108 +
  109 + //处理路由后缀为-tag的关键词
  110 + foreach ($search_list['pageInfo']['pageListData'] as &$v) {
  111 + if (substr($v['route'], -4, 4) == '-tag') {
  112 + $v['route'] = substr($v['route'], 0, -4);
  113 + }
  114 + }
  115 +
  116 + //俄语站没有首字母筛选
  117 + if ($project->serve_id == 3) {
  118 + $search_list['keywordsLabel'] = [];
  119 + }
  120 +
  121 + $total_page = count($search_list['pageInfo']['pageNum']);
  122 + $search_list['pageInfo']['center_pages'] = page_init($page, $total_page);
  123 + $search_list['pageInfo']['prev'] = max($page - 1, 1);
  124 + $search_list['pageInfo']['next'] = min($page + 1, $total_page);
  125 +
  126 + $current_url = self::getCurrentUrl($project->domain, '/' . $route . '/' . ($page > 1 ? $page . '/' : ''));
  127 + return view('amp/top_search', compact('project_config', 'category', 'search_list', 'page', 'route', 'current_url'));
  128 + } else {
  129 + //剩下的页面:产品分类,产品详情,新闻详情,关键词详情
  130 + $map = ['route' => $route];
  131 + if ($source) {
  132 + $map['source'] = $source;
  133 + }
  134 + $route_info = RouteMap::where($map)->orderByRaw("FIELD(source, 'product_category','product','news','blog','product_keyword')")->first();
  135 + if (!$route_info) {
  136 + //特殊情况:关键词后缀为-tag
  137 + $map['route'] = $route . '-tag';
  138 + $map['source'] = 'product_keyword';
  139 + $route_info = RouteMap::where($map)->first();
  140 + }
  141 + if (!$route_info) {
  142 + $current_url = self::getCurrentUrl($project->domain, '/404/');
  143 + return view('amp/404', compact('project_config', 'category', 'current_url'));
  144 + }
  145 +
  146 + switch ($route_info->source) {
  147 + case 'product_category':
  148 + //产品列表
  149 + $products = self::getProductsList($project->id, $page, 8, $route_info->source_id);
  150 +
  151 + //当前分类详情
  152 + $category_info = self::getCategoryInfo($project->id, $route_info->source_id);
  153 +
  154 + $current_url = self::getCurrentUrl($project->domain, '/' . $category_info['route'] . '/' . ($page > 1 ? $page . '/' : ''));
  155 + return view('amp/products', compact('project_config', 'category', 'products', 'category_info', 'page', 'current_url'));
  156 + case 'product':
  157 + //获取产品详情
  158 + $product_info = self::getProductInfo($project->id, $route_info->source_id);
  159 +
  160 + //获取关联产品
  161 + $relate_products = self::getRelateProducts($project->id, $product_info['id'], $product_info['category_id'], 8);
  162 +
  163 + $current_url = self::getCurrentUrl($project->domain, '/' . $product_info['route'] . '/');
  164 + return view('amp/product_info', compact('project_config', 'category', 'product_info', 'relate_products', 'current_url'));
  165 + case 'news':
  166 + //新闻详情
  167 + $news_info = self::getNewsBlogInfo($project->id, 1, $route_info->source_id);
  168 +
  169 + $current_url = self::getCurrentUrl($project->domain, '/news/' . $news_info['url'] . '/');
  170 + return view('amp/news_info', compact('project_config', 'category', 'news_info', 'current_url'));
  171 + case 'blog':
  172 + //博客详情
  173 + $blog_info = self::getNewsBlogInfo($project->id, 2, $route_info->source_id);
  174 +
  175 + $current_url = self::getCurrentUrl($project->domain, '/blog/' . $blog_info['url'] . '/');
  176 + return view('amp/blog_info', compact('project_config', 'category', 'blog_info', 'current_url'));
  177 + case 'product_keyword':
  178 + //获取关键词详情
  179 + $tag_info = self::getTagInfo($project->id, $route_info->source_id);
  180 +
  181 + //获取关联产品和热门产品
  182 + $pageService = new PageService();
  183 + $products = $pageService->getRecommendAndHotProducts($project, $tag_info['route']) ?: [];
  184 +
  185 + //获取关联新闻
  186 + $news = self::getNewsBlogList($project->id, 1, 1, 2)['data'];
  187 +
  188 + //随机获取关键词列表
  189 + $relate_tags = self::getRelateTags($project->id);
  190 +
  191 + $current_url = self::getCurrentUrl($project->domain, '/' . $tag_info['route'] . '/');
  192 + return view('amp/tag', compact('project_config', 'category', 'tag_info', 'products', 'news', 'relate_tags', 'current_url'));
  193 + default:
  194 + $current_url = self::getCurrentUrl($project->domain, '/404/');
  195 + return view('amp/404', compact('project_config', 'category', 'current_url'));
  196 + }
  197 + }
  198 + }
  199 +
  200 + /**
  201 + * 拼接当前页面完整路径
  202 + * @param $domain
  203 + * @param $path
  204 + * @return string
  205 + * @author Akun
  206 + * @date 2024/03/15 15:48
  207 + */
  208 + public static function getCurrentUrl($domain, $path = '')
  209 + {
  210 + $host_array = explode('.', $domain);
  211 + if (count($host_array) <= 2) {
  212 + array_unshift($host_array, 'm');
  213 + } else {
  214 + $host_array[0] = 'm';
  215 + }
  216 + $amp_domain = implode('.', $host_array);
  217 +
  218 + return 'https://' . $amp_domain . $path;
  219 + }
  220 +
  221 + /**
  222 + * 获取站点amp配置
  223 + * @param $project_id
  224 + * @return mixed
  225 + * @author Akun
  226 + * @date 2024/01/26 16:07
  227 + */
  228 + public static function getProjectConfig($project_id)
  229 + {
  230 + $config_amp = WebSettingAmp::where('project_id', $project_id)->first();
  231 +
  232 + $config_index = WebSetting::where('project_id', $project_id)->first();
  233 +
  234 + $config_seo = WebSettingSeo::where('project_id', $project_id)->first();
  235 +
  236 + $show_news = News::where('project_id', $project_id)->where('status', 1)->count('id');
  237 +
  238 + $show_blogs = Blog::where('project_id', $project_id)->where('status', 1)->count('id');
  239 +
  240 + return [
  241 + 'show_news' => $show_news,
  242 + 'show_blogs' => $show_blogs,
  243 + 'top_backgroundcolor' => $config_amp->top_backgroundcolor ?? '',
  244 + 'web_icon' => $config_amp->web_icon ?? '',
  245 + 'top_logo' => $config_amp->top_logo ?? [],
  246 + 'index_banner' => $config_amp->index_banner ?? [],
  247 + 'index_intro' => $config_amp->index_intro ?? '',
  248 + 'company_image' => $config_amp->company_image ?? [],
  249 + 'company_about' => $config_amp->company_about ?? '',
  250 + 'company_email' => $config_amp->company_email ?? '',
  251 + 'company_address' => $config_amp->company_address ?? '',
  252 + 'company_tel' => $config_amp->company_tel ?? '',
  253 + 'third_code' => $config_amp->third_code ?? '',
  254 + 'index_title' => $config_index->title ?? '',
  255 + 'index_description' => $config_index->remark ?? '',
  256 + 'index_keywords' => $config_index->keyword ?? '',
  257 + 'single_page_suffix' => $config_seo->single_page_suffix ?? '',
  258 + 'tab_suffix' => $config_seo->tab_suffix ?? '',
  259 + 'tab_prefix' => $config_seo->tab_prefix ?? '',
  260 + 'product_cate_suffix' => $config_seo->product_cate_suffix ?? '',
  261 + 'product_cate_prefix' => $config_seo->product_cate_prefix ?? '',
  262 + 'product_suffix' => $config_seo->product_suffix ?? '',
  263 + 'product_prefix' => $config_seo->product_prefix ?? '',
  264 + ];
  265 + }
  266 +
  267 + /**
  268 + * 获取分类列表
  269 + * @param $project_id
  270 + * @return array
  271 + * @author Akun
  272 + * @date 2024/01/29 11:25
  273 + */
  274 + public static function getProductsCategory($project_id)
  275 + {
  276 + $category = [];
  277 + $result = Category::where('project_id', $project_id)->where('title', '!=', 'Featured Products')->where('status', 1)->orderBy("sort", "desc")->orderBy("id", "desc")->get();
  278 + if ($result->count() > 0) {
  279 + $result_tree = list_to_tree($result->toArray());
  280 + foreach ($result_tree as $cate) {
  281 + if ($cate['title'] == 'Products' || $cate['title'] == 'products') {
  282 + foreach ($cate['_child'] as $child) {
  283 + $category[] = $child;
  284 + }
  285 + } else {
  286 + $category[] = $cate;
  287 + }
  288 + }
  289 + }
  290 +
  291 +
  292 + return $category;
  293 + }
  294 +
  295 + /**
  296 + * 获取分类详情
  297 + * @param $project_id
  298 + * @param $category_id
  299 + * @return array
  300 + * @author Akun
  301 + * @date 2024/01/29 11:31
  302 + */
  303 + public static function getCategoryInfo($project_id, $category_id)
  304 + {
  305 + if ($category_id > 0) {
  306 + $category_info = Category::where('project_id', $project_id)->where('id', $category_id)->first();
  307 + } else {
  308 + $category_info = Category::where('project_id', $project_id)->whereIn('title', ['Products', 'products'])->first();
  309 + if ($category_info) {
  310 + $category_info->id = 0;
  311 + } else {
  312 + return [
  313 + 'id' => 0,
  314 + 'route' => 'products',
  315 + 'title' => 'Products',
  316 + 'keywords' => '',
  317 + 'describe' => '',
  318 + 'seo_title' => '',
  319 + 'seo_keywords' => '',
  320 + 'seo_description' => '',
  321 + ];
  322 + }
  323 + }
  324 +
  325 + return [
  326 + 'id' => $category_info->id ?? 0,
  327 + 'route' => $category_info->route ?? '',
  328 + 'title' => $category_info->title ?? '',
  329 + 'keywords' => $category_info->keywords ?? '',
  330 + 'describe' => $category_info->describe ?? '',
  331 + 'seo_title' => $category_info->seo_title ?? '',
  332 + 'seo_keywords' => $category_info->seo_keywords ?? '',
  333 + 'seo_description' => $category_info->seo_des ?? '',
  334 + ];
  335 + }
  336 +
  337 + /**
  338 + * 根据分类id获取产品id
  339 + * @param $category_id
  340 + * @return mixed
  341 + * @author Akun
  342 + * @date 2024/01/29 11:26
  343 + */
  344 + public static function getProductIdByCategory($category_id)
  345 + {
  346 + return CategoryRelated::where('cate_id', $category_id)->pluck('product_id')->toArray();
  347 + }
  348 +
  349 + /**
  350 + * 获取产品列表
  351 + * @param int $project_id
  352 + * @param int $page
  353 + * @param int $limit
  354 + * @param int $category_id
  355 + * @param string $search
  356 + * @return array
  357 + * @author Akun
  358 + * @date 2024/01/26 16:07
  359 + */
  360 + public static function getProductsList($project_id, $page = 1, $limit = 20, $category_id = 0, $search = '')
  361 + {
  362 + $total_page = 0;
  363 + $products = [];
  364 +
  365 + $model = Product::where('project_id', $project_id)->where('status', 1);
  366 + //根据分类id获取关联的产品id
  367 + if ($category_id > 0) {
  368 + $product_ids = self::getProductIdByCategory($category_id);
  369 + if ($product_ids) {
  370 + $model = $model->whereIn('id', $product_ids);
  371 + }
  372 + } else {
  373 + //获取所有产品需要排除掉Featured Products分类
  374 + $fp_cate_id = Category::where('title', 'Featured Products')->value('id');
  375 + $model->where('category_id', '!=', ',' . $fp_cate_id . ',');
  376 + }
  377 + //搜索条件
  378 + if ($search) {
  379 + if (strpos($search, '\\') !== false) {
  380 + $search = str_replace('\\', '\\\\', $search);
  381 + }
  382 + $model = $model->where('title', 'like', "%$search%");
  383 + }
  384 +
  385 + $count = $model->count('id');
  386 + if ($count > 0) {
  387 + $total_page = (int)ceil($count / $limit);
  388 +
  389 + //获取产品自定义排序规则
  390 + $sort_rule = self::getProductSortRule($project_id);
  391 + foreach ($sort_rule as $rk => $rv) {
  392 + $model = $model->orderBy($rk, $rv);
  393 + }
  394 +
  395 + $result = $model->select(['id', 'title', 'thumb', 'intro', 'content', 'route'])->offset(($page - 1) * $limit)->limit($limit)->get();
  396 + if ($result->count() > 0) {
  397 + foreach ($result as $value) {
  398 + $thumb = [];
  399 + if ($value->thumb) {
  400 + $thumb_arr = json_decode($value->thumb, true);
  401 + $thumb = [
  402 + 'alt' => (isset($thumb_arr['alt']) && $thumb_arr['alt']) ? $thumb_arr['alt'] : $value->title,
  403 + 'url' => getImageUrl($thumb_arr['url'] ?? '')
  404 + ];
  405 + }
  406 + $intro = $value->intro ?: $value->content;
  407 + $intro = strip_tags(special2str($intro));
  408 + $products[] = [
  409 + 'id' => $value->id,
  410 + 'title' => $value->title,
  411 + 'thumb' => $thumb,
  412 + 'route' => $value->route,
  413 + 'intro' => strlen($intro) > 200 ? substr($intro, 0, 200) . '...' : $intro,
  414 + ];
  415 + }
  416 + }
  417 + }
  418 +
  419 + $pre = max($page - 1, 1);
  420 + $next = min($page + 1, $total_page);
  421 + $center_pages = page_init($page, $total_page);
  422 +
  423 + return ['data' => $products, 'total_page' => $total_page, 'prev' => $pre, 'next' => $next, 'center_pages' => $center_pages];
  424 + }
  425 +
  426 + /**
  427 + * 获取产品自定义排序规则
  428 + * @param $project_id
  429 + * @return array|string[]
  430 + * @author Akun
  431 + * @date 2024/03/21 11:13
  432 + */
  433 + public static function getProductSortRule($project_id)
  434 + {
  435 + $order_list = [];
  436 + $orderDataFirst = SettingNum::where('project_id', $project_id)->where('type', 10)->first();
  437 + if ($orderDataFirst && $orderDataFirst->data) {
  438 + $orderData = json_decode($orderDataFirst->data, true);
  439 + foreach ($orderData as $key => $orderDataItem) {
  440 + $orderKey = $key == "created_at" ? "send_time" : $key;
  441 + $order_list[$orderKey] = $orderDataItem;
  442 + if ($key != "id") {
  443 + $order_list['id'] = 'desc';
  444 + }
  445 + }
  446 + } else {
  447 + $order_list = [
  448 + 'sort' => 'desc',
  449 + 'id' => 'desc'
  450 + ];
  451 + }
  452 +
  453 + return $order_list;
  454 + }
  455 +
  456 + /**
  457 + * 获取产品详情
  458 + * @param $project_id
  459 + * @param $id
  460 + * @return array
  461 + * @author Akun
  462 + * @date 2024/01/30 9:22
  463 + */
  464 + public static function getProductInfo($project_id, $id)
  465 + {
  466 + $gallery = [];
  467 + $seo = [
  468 + 'title' => '',
  469 + 'keywords' => '',
  470 + 'description' => ''
  471 + ];
  472 + $product_info = Product::where('project_id', $project_id)->where('status', 1)->where('id', $id)->first();
  473 + if ($product_info) {
  474 + if ($product_info->gallery) {
  475 + $gallery_arr = json_decode($product_info->gallery, true);
  476 + foreach ($gallery_arr as $vg) {
  477 + $gallery[] = [
  478 + 'alt' => (isset($vg['alt']) && $vg['alt']) ? $vg['alt'] : $product_info->title,
  479 + 'url' => getImageUrl($vg['url'] ?? '')
  480 + ];
  481 + }
  482 + }
  483 +
  484 + if ($product_info->seo_mate) {
  485 + $seo_arr = json_decode($product_info->seo_mate, true);
  486 + $seo['title'] = $seo_arr['title'] ?? '';
  487 + $seo['keywords'] = $seo_arr['keywords'] ?? '';
  488 + $seo['description'] = $seo_arr['description'] ?? '';
  489 + }
  490 + }
  491 +
  492 + return [
  493 + 'id' => $product_info->id ?? 0,
  494 + 'route' => $product_info->route ?? '',
  495 + 'gallery' => $gallery,
  496 + 'title' => $product_info->title ?? '',
  497 + 'intro' => $product_info->intro ?? '',
  498 + 'content' => $product_info->content ?? '',
  499 + 'seo' => $seo,
  500 + 'category_id' => $product_info->category_id ?? ''
  501 + ];
  502 + }
  503 +
  504 + /**
  505 + * 获取关联产品
  506 + * @param $project_id
  507 + * @param $id
  508 + * @param $category_id
  509 + * @param $limit
  510 + * @return array
  511 + * @author Akun
  512 + * @date 2024/01/30 9:34
  513 + */
  514 + public static function getRelateProducts($project_id, $id, $category_id, $limit = 2)
  515 + {
  516 + if (is_string($category_id)) {
  517 + $category_id = explode(',', $category_id);
  518 + }
  519 +
  520 + $relate_ids = CategoryRelated::whereIn('cate_id', $category_id)->where('product_id', '!=', $id)->limit($limit)->pluck('product_id')->toArray();
  521 +
  522 + $relate_products = [];
  523 + if ($relate_ids) {
  524 + $result = Product::where('project_id', $project_id)->whereIn('id', $relate_ids)->where('status', 1)->orderBy('sort', 'desc')->limit(8)->get();
  525 + if ($result->count() == 0) {
  526 + $result = Product::where('project_id', $project_id)->where('status', 1)->inRandomOrder()->take(8)->get();
  527 + }
  528 + if ($result->count() > 0) {
  529 + foreach ($result as $value) {
  530 + $thumb = '';
  531 + if ($value->thumb) {
  532 + $thumb_arr = json_decode($value->thumb, true);
  533 + $thumb = [
  534 + 'alt' => (isset($thumb_arr['alt']) && $thumb_arr['alt']) ? $thumb_arr['alt'] : $value->title,
  535 + 'url' => getImageUrl($thumb_arr['url'] ?? '')
  536 + ];
  537 + }
  538 + $relate_products[] = [
  539 + 'id' => $value->id,
  540 + 'route' => $value->route,
  541 + 'title' => $value->title,
  542 + 'thumb' => $thumb
  543 + ];
  544 + }
  545 + }
  546 + }
  547 +
  548 + return $relate_products;
  549 + }
  550 +
  551 + /**
  552 + * 获取新闻博客列表
  553 + * @param $project_id
  554 + * @param int $type
  555 + * @param int $page
  556 + * @param int $limit
  557 + * @return array
  558 + * @author Akun
  559 + * @date 2024/01/26 16:38
  560 + */
  561 + public static function getNewsBlogList($project_id, $type = 1, $page = 1, $limit = 10)
  562 + {
  563 + $total_page = 0;
  564 + $news = [];
  565 +
  566 + if ($type == 1) {
  567 + $model = new News();
  568 + } else {
  569 + $model = new Blog();
  570 + }
  571 + $count = $model->where('project_id', $project_id)->where('status', 1)->count('id');
  572 + if ($count > 0) {
  573 + $total_page = (int)ceil($count / $limit);
  574 +
  575 + $result = $model->select(['id', 'name', 'image', 'remark', 'text', 'release_at', 'created_at', 'url'])->where('project_id', $project_id)->where('status', 1)->orderBy('sort', 'desc')->orderBy('id', 'desc')->offset(($page - 1) * $limit)->limit($limit)->get();
  576 + if ($result->count() > 0) {
  577 + foreach ($result as $value) {
  578 + $remark = $value->remark ?: $value->text;
  579 + $remark = strip_tags(special2str($remark));
  580 + $news[] = [
  581 + 'type' => $type,
  582 + 'id' => $value->id,
  583 + 'name' => $value->name,
  584 + 'url' => $value->url,
  585 + 'image' => getImageUrl($value->image),
  586 + 'remark' => strlen($remark) > 200 ? substr($remark, 0, 200) . '...' : $remark,
  587 + 'release_at' => $value->release_at ? $value->release_at : $value->created_at
  588 + ];
  589 + }
  590 + }
  591 + }
  592 +
  593 + $pre = max($page - 1, 1);
  594 + $next = min($page + 1, $total_page);
  595 + $center_pages = page_init($page, $total_page);
  596 +
  597 +
  598 + return ['data' => $news, 'total_page' => $total_page, 'prev' => $pre, 'next' => $next, 'center_pages' => $center_pages];
  599 + }
  600 +
  601 + /**
  602 + * 获取新闻博客详情
  603 + * @param $project_id
  604 + * @param $type
  605 + * @param $id
  606 + * @return array
  607 + * @author Akun
  608 + * @date 2024/01/30 11:17
  609 + */
  610 + public static function getNewsBlogInfo($project_id, $type, $id)
  611 + {
  612 + if ($type == 1) {
  613 + $model = new News();
  614 + } else {
  615 + $model = new Blog();
  616 + }
  617 +
  618 + $news_info = $model->where('project_id', $project_id)->where('status', 1)->where('id', $id)->first();
  619 +
  620 + $release_at = '';
  621 + if (isset($news_info->release_at) && $news_info->release_at) {
  622 + $release_at = $news_info->release_at;
  623 + } elseif (isset($news_info->created_at) && $news_info->created_at) {
  624 + $release_at = $news_info->created_at;
  625 + }
  626 +
  627 + return [
  628 + 'id' => $news_info->id ?? 0,
  629 + 'name' => $news_info->name ?? '',
  630 + 'sort' => $news_info->sort ?? 0,
  631 + 'url' => $news_info->url ?? 0,
  632 + 'text' => $news_info->text ?? '',
  633 + 'image' => getImageUrl($news_info->image ?? ''),
  634 + 'seo_title' => $news_info->seo_title ?? '',
  635 + 'seo_keywords' => $news_info->seo_keywords ?? '',
  636 + 'seo_description' => $news_info->seo_description ?? '',
  637 + 'release_at' => $release_at
  638 + ];
  639 + }
  640 +
  641 + /**
  642 + * 获取关键词详情
  643 + * @param $project_id
  644 + * @param $id
  645 + * @return array
  646 + * @author Akun
  647 + * @date 2024/01/30 16:17
  648 + */
  649 + public static function getTagInfo($project_id, $id)
  650 + {
  651 + $tag_info = Keyword::where('project_id', $project_id)->where('status', 1)->where('id', $id)->first();
  652 +
  653 + return [
  654 + 'id' => $tag_info->id ?? 0,
  655 + 'route' => $tag_info->route ?? '',
  656 + 'title' => $tag_info->title ?? '',
  657 + 'keyword_title' => $tag_info->keyword_title ?? '',
  658 + 'keyword_content' => $tag_info->keyword_content ?? '',
  659 + 'seo_title' => $tag_info->seo_title ?? '',
  660 + 'seo_keywords' => $tag_info->seo_keywords ?? '',
  661 + 'seo_description' => $tag_info->seo_description ?? '',
  662 + ];
  663 + }
  664 +
  665 + /**
  666 + * 获取关联关键词
  667 + * @param $project_id
  668 + * @return mixed
  669 + * @author Akun
  670 + * @date 2024/01/30 18:30
  671 + */
  672 + public static function getRelateTags($project_id)
  673 + {
  674 + return Keyword::select(['id', 'title', 'route'])->where('project_id', $project_id)->where('status', 1)->inRandomOrder()->take(10)->get()->toArray();
  675 + }
  676 +}
  1 +<?php
  2 +
  3 +
  4 +namespace App\Services\Html;
  5 +
  6 +use App\Helper\Translate;
  7 +use App\Models\Com\UpdateProgress;
  8 +use App\Models\Project\DeployBuild;
  9 +use App\Models\Project\DeployOptimize;
  10 +use App\Models\Project\DomainInfo;
  11 +use App\Models\Project\Project;
  12 +use App\Models\RouteMap\RouteMap;
  13 +use App\Models\WebSetting\Proofreading;
  14 +use App\Models\WebSetting\WebLanguage;
  15 +use App\Models\WebSetting\WebProofreading;
  16 +use App\Models\WebSetting\WebSetting;
  17 +use App\Models\WebSetting\WebSettingCountry;
  18 +use App\Models\WebSetting\WebSettingHtml;
  19 +use App\Models\WebSetting\WebSettingText;
  20 +use App\Models\WebSetting\WebTemplateCommon;
  21 +use App\Services\ProjectServer;
  22 +use Illuminate\Support\Facades\Redis;
  23 +use phpQuery;
  24 +
  25 +/**
  26 + * 生成静态页相关
  27 + */
  28 +class CommonService
  29 +{
  30 +
  31 + /**
  32 + * 翻译
  33 + */
  34 + public function webHtmlTranslate($project,$content, $lang,$domain)
  35 + {
  36 + //翻译过滤器
  37 + $lang = $lang == "zh-ct" ? "zh-TW" : $lang;
  38 + $tlsList = Translate::$tls_list;
  39 + if (isset($tlsList[$lang])){
  40 + $main_lang = $project->main_lang_id;
  41 + $mainLangInfo = WebLanguage::getProjectMainLang($main_lang);
  42 + $master_lang = $mainLangInfo ? $mainLangInfo->short : 'en';
  43 + //翻译
  44 + if ($master_lang != 'en') {
  45 + $result = Translate::translate($content, $lang, $master_lang);
  46 + $content = $result[0]['texts'] ?? '';
  47 + } else {
  48 + $content = Translate::tran($content, $lang);
  49 + }
  50 + // 翻译有时会返回空数据 再翻译一次 FIXME 后续需要重新封装
  51 + if (empty($content)) {
  52 + $result = Translate::translate($content, $lang, $master_lang);
  53 + $content = $result[0]['texts'] ?? '';
  54 + }
  55 +
  56 + //翻译校对
  57 + $content = $this->translationProofread($project,$content,$lang,$domain);
  58 + }
  59 + return $content;
  60 + }
  61 +
  62 + /**
  63 + * 翻译校对
  64 + */
  65 + public function translationProofread($project, $content, $lang,$domain)
  66 + {
  67 + $webProofreading = Proofreading::where("project_id",$project->id)->where("alias",$lang)->get();
  68 + if (!empty($webProofreading)){
  69 + foreach ($webProofreading as $item){
  70 + $content = str_ireplace($item->text,$item->translate,$content);
  71 + }
  72 + }
  73 + return $content;
  74 + }
  75 +
  76 + /**
  77 + * 处理第三方代码
  78 + */
  79 + public function thirdPartyCodeHandle($project,$content,$route,$routeMap=null): string
  80 + {
  81 + if (Redis::get("project_".$project->id."_third_party_code") != null){
  82 + $webSettingHtml = json_decode(Redis::get("project_".$project->id."_third_party_code"));
  83 + }else{
  84 + $webSettingHtml = WebSettingHtml::where("project_id",$project->id)->first();
  85 + Redis::set("project_".$project->id."_third_party_code", json_encode($webSettingHtml));
  86 + Redis::expire("project_".$project->id."_third_party_code", WebSetting::$redisExpireTime);
  87 + }
  88 + $phpQueryDom = phpQuery::newDocument($content);
  89 + //网站icon
  90 + $webIcon = WebSetting::where("project_id",$project->id)->first();
  91 + if (!empty($webIcon)){
  92 + $iconDom = $phpQueryDom->find("link[rel=icon]");
  93 + if (count($iconDom) >= 1){
  94 + if (isset($webIcon->web_site_icon) && !empty($webIcon->web_site_icon) && $webIcon->web_site_icon != "" && $webIcon->web_site_icon != 0){
  95 + $iconDom->attr("href",$webIcon->web_site_icon);
  96 + }else{
  97 + $iconDom->attr("href","");
  98 + }
  99 + }
  100 + }
  101 + //第三方代码(网页顶部,中间,底部),以后启用位置
  102 + if (!empty($webSettingHtml)) {
  103 + $phpQueryDom->find('head')->append($webSettingHtml->head_html?:'');
  104 + $phpQueryDom->find('body')->append($webSettingHtml->body_html?:'');
  105 + $phpQueryDom->find('html')->append($webSettingHtml->footer_html?:'');
  106 + }
  107 + //A端添加的网站追踪代码
  108 + $deployOptimize = DeployOptimize::where("project_id",$project->id)->first();
  109 + if (!empty($deployOptimize)){
  110 + if (isset($deployOptimize->meta) && !empty($deployOptimize->meta)){
  111 + $phpQueryDom->find('head')->append($deployOptimize->meta);
  112 + }
  113 + }
  114 + //首页头部独立样式
  115 + if ($route == "index"){
  116 + $phpQueryDom->find('header')->attr("headerprivate","");
  117 + }
  118 + //处理header顶部搜索跳转链接
  119 + $phpQueryDom->find('header form')->attr("action", "/search/");
  120 + //C端访问埋点
  121 + $isBodyEnd = $phpQueryDom->find('body')->eq(0);
  122 + if (count($isBodyEnd)>=1){
  123 + $phpQueryDom->find('body')->append("<script src='https://ecdn6.globalso.com/public/customerVisit.min.js'></script>");
  124 + }else{
  125 + $phpQueryDom->find('html')->append("<script src='https://ecdn6.globalso.com/public/customerVisit.min.js'></script>");
  126 + }
  127 + $data = date("Y-m-d H:i:s");
  128 + $phpQueryDom->find('html')->append("<!-- Globalso Cache file was created on ".$data." -->");
  129 + //这个功能其他类型页面移到面包屑导航处理
  130 + if ($route == "index" || (!empty($routeMap) && $routeMap->source == RouteMap::SOURCE_PAGE)){
  131 + $phpQueryDom->find('head')->append('<script>var currentPage = "'.$route.'"</script>');
  132 + }
  133 + if ($route == "search"){
  134 + //暂时先去掉小语种按钮显示
  135 + $phpQueryDom->find(".change-language")->remove();
  136 + $phpQueryDom->find('head')->append('<meta name="robots" content="noindex, nofollow"/>');
  137 + }
  138 + $phpQueryDom->find('body')->attr("unevents","");
  139 + $content = $phpQueryDom->htmlOuter();
  140 + unset($phpQueryDom);
  141 + phpQuery::unloadDocuments();
  142 + //处理全部内容,如果有上线正式域名,则把所有的测试域名替换为正式域名
  143 + $projectDomainInfo = DomainInfo::where("project_id",$project->id)->first();
  144 + if (!empty($projectDomainInfo)){
  145 + $deployBuild = DeployBuild::where("project_id",$project->id)->first();
  146 + if (!empty($deployBuild)){
  147 + $parsedUrl = parse_url($deployBuild->test_domain);
  148 + $domain = $projectDomainInfo->domain;
  149 + $testDomain = $parsedUrl['host'];
  150 + if ($domain != '' && $testDomain != ''){
  151 + $content = str_replace($testDomain,$domain,$content);
  152 + }
  153 + }
  154 + }
  155 + return $content;
  156 + }
  157 +
  158 + /**
  159 + * 处理锚文本
  160 + */
  161 + public function anchorTextHandle($project,$route,$content): string
  162 + {
  163 + $source = "";
  164 + //解析路由
  165 + if ($route != "index"){
  166 + $routerNewsMap = RouteMap::where("project_id",$project->id)->where("route",$route)->first();
  167 + if (!empty($routerNewsMap)){
  168 + $source = $routerNewsMap->source;
  169 + }
  170 + }else{
  171 + $source = "index";
  172 + }
  173 +
  174 + //判断来源类型
  175 + switch ($source) {
  176 + case 'news_category' || 'news':
  177 + $num = 4;
  178 + break;
  179 + case 'product_category' || 'product':
  180 + $num = 2;
  181 + break;
  182 + case 'blog_category' || 'blog':
  183 + $num = 6;
  184 + break;
  185 + case 'page':
  186 + $num = 1;
  187 + break;
  188 + default:
  189 + $num = 1;
  190 + }
  191 +
  192 + //网站设置锚文本
  193 + $webSetting = WebSetting::getWebSetting($project);
  194 + if (!empty($webSetting)){
  195 + $anchorIsEnable = $webSetting->anchor_is_enable;
  196 + if ($anchorIsEnable == 0){
  197 + $anchorSetting = $webSetting->anchor_setting;
  198 + $anchorSettingArr = explode(',', substr($anchorSetting, 1, -1));
  199 + foreach ($anchorSettingArr as $item){
  200 + $itemArr = explode('"', substr($item, 1, -1));
  201 + $tracingText[] = intval($itemArr[0]);
  202 + }
  203 + if (in_array($num, $tracingText)) {
  204 + $webSettingText = WebSettingText::getWebSettingText($project);
  205 + $phpQueryDom=phpQuery::newDocument($content);
  206 + $mainElement = $phpQueryDom->find('main');
  207 + $con = $mainElement->html();
  208 + if (!empty($webSettingText)){
  209 + foreach ($webSettingText as $v){
  210 + $con = str_replace( $v->key_words, '<a target="_blank" href="'. $v->url.'">'. $v->key_words.'</a>', $con);
  211 + }
  212 + }
  213 + $mainElement->html($con);
  214 + return $phpQueryDom->htmlOuter();
  215 + }
  216 + }
  217 + }
  218 + return $content;
  219 + }
  220 +
  221 + /**
  222 + * 链接项目
  223 + */
  224 + public function connectProject($updateData)
  225 + {
  226 + $project = null;
  227 + $projectIn = Project::getProjectByDomain($updateData->domain);
  228 + if (!empty($projectIn)){
  229 + $project = Project::where("id",$projectIn->project_id)->first();
  230 + if (!empty($project)){
  231 + $project->domain = $updateData->domain;
  232 + }
  233 + ProjectServer::useProject($project->id);
  234 + }
  235 + return $project;
  236 + }
  237 +
  238 + /**
  239 + * 获取小语种更新国家
  240 + */
  241 + public function getMinorLanguage($updateData)
  242 + {
  243 + $minorLanguage = [];
  244 + $updateProgressQuery = UpdateProgress::find($updateData->id);
  245 + if (!empty($updateProgressQuery)){
  246 + $extends = $updateProgressQuery->extends;
  247 + if (!empty($extends)){
  248 + $extends = json_decode($extends);
  249 + if (isset($extends->language) && !empty($extends->language)){
  250 + $language = $extends->language;
  251 + foreach ($language as $lang){
  252 + $minorLanguage[] = (int)$lang;
  253 + }
  254 + }
  255 + }
  256 + }
  257 + return WebSettingCountry::whereIn("id", $minorLanguage)->get();
  258 + }
  259 +}