作者 刘锟

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

@@ -64,6 +64,7 @@ class AiBlogAuthorTask extends Command @@ -64,6 +64,7 @@ class AiBlogAuthorTask extends Command
64 $aiBlogService->key = $aiSettingInfo['key']; 64 $aiBlogService->key = $aiSettingInfo['key'];
65 $result = $aiBlogService->getAuthor(); 65 $result = $aiBlogService->getAuthor();
66 if(!isset($result['status'])){ 66 if(!isset($result['status'])){
  67 + echo '错误:'.json_encode($result,true);
67 continue; 68 continue;
68 } 69 }
69 if($result['status'] != 200){ 70 if($result['status'] != 200){
@@ -71,17 +72,17 @@ class AiBlogAuthorTask extends Command @@ -71,17 +72,17 @@ class AiBlogAuthorTask extends Command
71 continue; 72 continue;
72 } 73 }
73 if(empty($result['data'])){ 74 if(empty($result['data'])){
74 - sleep(20); 75 + echo '没有作者任务-'.PHP_EOL;
75 continue; 76 continue;
76 } 77 }
77 //保存当前项目ai_blog数据 78 //保存当前项目ai_blog数据
78 ProjectServer::useProject($info['project_id']); 79 ProjectServer::useProject($info['project_id']);
79 $this->saveAiBlogAuthor($result['data'] ?? [],$info['project_id']); 80 $this->saveAiBlogAuthor($result['data'] ?? [],$info['project_id']);
  81 + RouteMap::setRoute('top-blog',RouteMap::SOURCE_AI_BLOG_LIST,0,$info['project_id']);//写一条列表页路由
80 DB::disconnect('custom_mysql'); 82 DB::disconnect('custom_mysql');
81 //修改任务状态 83 //修改任务状态
82 - RouteMap::setRoute('top-blog',RouteMap::SOURCE_AI_BLOG_LIST,0,$info['project_id']);//写一条列表页路由  
83 $aiBlogTaskModel->edit(['status'=>2],['id'=>$info['id']]); 84 $aiBlogTaskModel->edit(['status'=>2],['id'=>$info['id']]);
84 - echo '结束->任务id:' . $info['task_id'] . PHP_EOL . date('Y-m-d H:i:s'); 85 + echo '结束->任务id:' . $info['id'] . PHP_EOL . date('Y-m-d H:i:s');
85 } 86 }
86 return true; 87 return true;
87 } 88 }
@@ -117,18 +118,28 @@ class AiBlogAuthorTask extends Command @@ -117,18 +118,28 @@ class AiBlogAuthorTask extends Command
117 return true; 118 return true;
118 } 119 }
119 $aiBlogAuthorModel = new AiBlogAuthor(); 120 $aiBlogAuthorModel = new AiBlogAuthor();
120 - $info = $aiBlogAuthorModel->counts(['project_id'=>$project_id]);  
121 - if($info === false){  
122 - foreach ($data as $v){  
123 - $param = [  
124 - 'author_id'=>$v['id'],  
125 - 'title'=>$v['title'],  
126 - 'image'=>str_replace_url($v['picture']),  
127 - 'description'=>$v['description'],  
128 - ];  
129 - $id = $aiBlogAuthorModel->addReturnId($param);  
130 - $route = RouteMap::setRoute($v['route'] ?? $v['title'], RouteMap::SOURCE_AI_BLOG_AUTHOR, $id, $project_id);  
131 - $aiBlogAuthorModel->edit(['route'=>$route],['id'=>$id]); 121 + foreach ($data as $v){
  122 + //查询当前数据是否存在
  123 + $info = $aiBlogAuthorModel->read(['author_id'=>$v['id']]);
  124 + $param = [
  125 + 'author_id'=>$v['id'],
  126 + 'title'=>$v['title'],
  127 + 'image'=>str_replace_url($v['picture']),
  128 + 'description'=>$v['description'],
  129 + ];
  130 + try {
  131 + if($info === false){
  132 + echo '执行新增'.PHP_EOL;
  133 + $id = $aiBlogAuthorModel->addReturnId($param);
  134 + $route = RouteMap::setRoute($v['route'] ?? $v['title'], RouteMap::SOURCE_AI_BLOG_AUTHOR, $id, $project_id);
  135 + $aiBlogAuthorModel->edit(['route'=>$route],['id'=>$id]);
  136 + }else{
  137 + $aiBlogAuthorModel->edit($param,['id'=>$info['id']]);
  138 + echo '执行更新'.PHP_EOL;
  139 + }
  140 + }catch (\Exception $e){
  141 + echo 'error:'.$e->getMessage();
  142 + continue;
132 } 143 }
133 } 144 }
134 return true; 145 return true;
@@ -42,11 +42,12 @@ class AiBlogTask extends Command @@ -42,11 +42,12 @@ class AiBlogTask extends Command
42 public function handle(){ 42 public function handle(){
43 $aiBlogTaskModel = new AiBlogTaskModel(); 43 $aiBlogTaskModel = new AiBlogTaskModel();
44 while (true){ 44 while (true){
45 - $list = $aiBlogTaskModel->list(['status'=>1,'type'=>2, 'created_at' => ['<', date('Y-m-d H:i:s')]],'id',['*'],'asc',1000); 45 + $list = $aiBlogTaskModel->formatQuery(['status'=>1,'type'=>2])->inRandomOrder()->limit(1000)->get();
46 if(empty($list)){ 46 if(empty($list)){
47 sleep(300); 47 sleep(300);
48 continue; 48 continue;
49 } 49 }
  50 + $list = $list->toArray();
50 $updateProject = []; 51 $updateProject = [];
51 foreach ($list as $item){ 52 foreach ($list as $item){
52 echo '开始->任务id:' . $item['task_id'] . PHP_EOL . date('Y-m-d H:i:s'); 53 echo '开始->任务id:' . $item['task_id'] . PHP_EOL . date('Y-m-d H:i:s');
@@ -57,8 +58,12 @@ class AiBlogTask extends Command @@ -57,8 +58,12 @@ class AiBlogTask extends Command
57 $aiBlogService->key = $aiSettingInfo['key']; 58 $aiBlogService->key = $aiSettingInfo['key'];
58 $aiBlogService->task_id = $item['task_id']; 59 $aiBlogService->task_id = $item['task_id'];
59 $result = $aiBlogService->getDetail(); 60 $result = $aiBlogService->getDetail();
60 - if(!isset($result['status']) || $result['status'] != 200){  
61 - sleep(5); 61 + if(!isset($result['status'])){
  62 + echo json_encode($result,true).PHP_EOL;
  63 + continue;
  64 + }
  65 + if($result['status'] != 200){
  66 + echo '错误状态码:'.$result['status'].PHP_EOL;
62 continue; 67 continue;
63 } 68 }
64 //保存当前项目ai_blog数据 69 //保存当前项目ai_blog数据
@@ -66,6 +71,7 @@ class AiBlogTask extends Command @@ -66,6 +71,7 @@ class AiBlogTask extends Command
66 $aiBlogModel = new AiBlog(); 71 $aiBlogModel = new AiBlog();
67 $aiBlogInfo = $aiBlogModel->read(['task_id'=>$item['task_id']],['id']); 72 $aiBlogInfo = $aiBlogModel->read(['task_id'=>$item['task_id']],['id']);
68 if($aiBlogInfo === false){ 73 if($aiBlogInfo === false){
  74 + echo '任务id不存在:'.$item['task_id'].PHP_EOL;
69 $aiBlogTaskModel->edit(['status'=>2],['id'=>$item['id']]); 75 $aiBlogTaskModel->edit(['status'=>2],['id'=>$item['id']]);
70 continue; 76 continue;
71 } 77 }
@@ -80,10 +86,10 @@ class AiBlogTask extends Command @@ -80,10 +86,10 @@ class AiBlogTask extends Command
80 $aiBlogModel->edit(['new_title'=>$result['data']['title'], 'image'=>$result['data']['thumb'], 'text'=>$result['data']['section'], 'author_id'=>$result['data']['author_id'],'seo_title'=>$result['data']['title'],'seo_keyword'=>$result['data']['keyword'],'seo_description'=>$result['data']['description'], 'route'=>$route ,'status'=>2], ['task_id'=>$item['task_id']]); 86 $aiBlogModel->edit(['new_title'=>$result['data']['title'], 'image'=>$result['data']['thumb'], 'text'=>$result['data']['section'], 'author_id'=>$result['data']['author_id'],'seo_title'=>$result['data']['title'],'seo_keyword'=>$result['data']['keyword'],'seo_description'=>$result['data']['description'], 'route'=>$route ,'status'=>2], ['task_id'=>$item['task_id']]);
81 DB::disconnect('custom_mysql'); 87 DB::disconnect('custom_mysql');
82 $aiBlogTaskModel->edit(['status'=>2],['id'=>$item['id']]); 88 $aiBlogTaskModel->edit(['status'=>2],['id'=>$item['id']]);
  89 + echo '结束->任务id:' . $item['task_id'] . PHP_EOL . date('Y-m-d H:i:s');
83 } 90 }
84 //TODO::更新列表页及作者 91 //TODO::更新列表页及作者
85 $this->updateProject($updateProject); 92 $this->updateProject($updateProject);
86 - echo '结束->任务id:' . $item['task_id'] . PHP_EOL . date('Y-m-d H:i:s');  
87 } 93 }
88 return true; 94 return true;
89 } 95 }
@@ -207,7 +213,8 @@ class AiBlogTask extends Command @@ -207,7 +213,8 @@ class AiBlogTask extends Command
207 $domain = $domainModel->getProjectIdDomain($project_id); 213 $domain = $domainModel->getProjectIdDomain($project_id);
208 if(!empty($domain)){ 214 if(!empty($domain)){
209 $url = $domain.'api/update_page/?project_id='.$project_id.'&route=7'; 215 $url = $domain.'api/update_page/?project_id='.$project_id.'&route=7';
210 - shell_exec('curl -k "'.$url.'"'); 216 + $res = http_get($url);
  217 + echo '返回数据:'.json_encode($res,true).PHP_EOL;
211 }else{ 218 }else{
212 echo '域名不存在:' . $project_id . PHP_EOL . date('Y-m-d H:i:s'); 219 echo '域名不存在:' . $project_id . PHP_EOL . date('Y-m-d H:i:s');
213 } 220 }
@@ -530,15 +530,17 @@ class UpdateRoute extends Command @@ -530,15 +530,17 @@ class UpdateRoute extends Command
530 $seoModel = new WebSettingSeo(); 530 $seoModel = new WebSettingSeo();
531 $seo_info = $seoModel->read(['project_id'=>$project_id]); 531 $seo_info = $seoModel->read(['project_id'=>$project_id]);
532 if($seo_info !== false){ 532 if($seo_info !== false){
533 - $prefix = $seo_info['product_category_prefix'] ?? [];  
534 - $suffix = $seo_info['product_category_suffix'] ?? []; 533 + $prefix = [];
  534 + $suffix = [];
535 if(!empty($seo_info['product_cate_prefix'])){ 535 if(!empty($seo_info['product_cate_prefix'])){
536 - $prefix[] = ['name'=>$seo_info['product_cate_prefix']]; 536 + $prefix[] = ['val'=>[$seo_info['product_cate_prefix']],'level'=>1];
537 } 537 }
538 if(!empty($seo_info['product_cate_suffix'])){ 538 if(!empty($seo_info['product_cate_suffix'])){
539 - $suffix[] = ['name'=>$seo_info['product_cate_suffix']]; 539 + $suffix[] = ['val'=>[$seo_info['product_cate_suffix']],'level'=>1];
  540 + }
  541 + if(!empty($prefix) && !empty($suffix)){
  542 + $seoModel->edit(['product_category_prefix'=>json_encode($prefix,true),'product_category_suffix'=>json_encode($suffix,true)],['project_id'=>$project_id]);
540 } 543 }
541 - $seoModel->edit(['product_category_prefix'=>json_encode($prefix,true),'product_category_suffix'=>json_encode($suffix,true)],['project_id'=>$project_id]);  
542 } 544 }
543 return true; 545 return true;
544 } 546 }
@@ -55,18 +55,11 @@ class CopyProject extends Command @@ -55,18 +55,11 @@ class CopyProject extends Command
55 $this->output('CopyProjectJob start, project_id: ' . $old_project_id); 55 $this->output('CopyProjectJob start, project_id: ' . $old_project_id);
56 $data = $this->copyProject($old_project_id); 56 $data = $this->copyProject($old_project_id);
57 $project_id = $data['project_id']; 57 $project_id = $data['project_id'];
58 - $type = $data['type'];  
59 $this->copyDeployBuild($old_project_id,$project_id); 58 $this->copyDeployBuild($old_project_id,$project_id);
60 $this->copyDeployOptimize($old_project_id,$project_id); 59 $this->copyDeployOptimize($old_project_id,$project_id);
61 $this->copyPayment($old_project_id,$project_id); 60 $this->copyPayment($old_project_id,$project_id);
62 $this->copyAfter($old_project_id,$project_id); 61 $this->copyAfter($old_project_id,$project_id);
63 $this->copyUser($old_project_id,$project_id); 62 $this->copyUser($old_project_id,$project_id);
64 - if($type != 0){  
65 - $this->copyMysql($old_project_id,$project_id);  
66 - }  
67 - //修改项目状态  
68 - $projectModel->edit(['delete_status'=>0],['id'=>$project_id]);  
69 - $this->output('CopyProjectJob end, old project_id: ' . $old_project_id . ', new project_id: ' . $project_id);  
70 $item->status = NoticeLog::STATUS_SUCCESS; 63 $item->status = NoticeLog::STATUS_SUCCESS;
71 $item->save(); 64 $item->save();
72 }catch (\Exception $e){ 65 }catch (\Exception $e){
@@ -75,6 +68,14 @@ class CopyProject extends Command @@ -75,6 +68,14 @@ class CopyProject extends Command
75 $item->status = NoticeLog::STATUS_FAIL; 68 $item->status = NoticeLog::STATUS_FAIL;
76 $item->save(); 69 $item->save();
77 } 70 }
  71 + try {
  72 + $this->copyMysql($old_project_id,$project_id);
  73 + }catch (\Exception $e){
  74 + echo '复制数据库失败:'.$old_project_id . '<->'.$project_id;
  75 + }
  76 + //修改项目状态
  77 + $projectModel->edit(['delete_status'=>0],['id'=>$project_id]);
  78 + $this->output('CopyProjectJob end, old project_id: ' . $old_project_id . ', new project_id: ' . $project_id);
78 } 79 }
79 } 80 }
80 return true; 81 return true;
@@ -9,6 +9,7 @@ namespace App\Http\Controllers\Api; @@ -9,6 +9,7 @@ namespace App\Http\Controllers\Api;
9 9
10 use App\Enums\Common\Code; 10 use App\Enums\Common\Code;
11 use App\Http\Logic\Bside\User\UserLoginLogic; 11 use App\Http\Logic\Bside\User\UserLoginLogic;
  12 +use App\Models\Ai\AiBlog;
12 use App\Models\Blog\Blog; 13 use App\Models\Blog\Blog;
13 use App\Models\Domain\DomainInfo; 14 use App\Models\Domain\DomainInfo;
14 use App\Models\News\News; 15 use App\Models\News\News;
@@ -313,16 +314,17 @@ class PrivateController extends BaseController @@ -313,16 +314,17 @@ class PrivateController extends BaseController
313 ProjectServer::useProject($project->id); 314 ProjectServer::useProject($project->id);
314 $result = []; 315 $result = [];
315 // 查询有效时间后 有效的产品、新闻、博客、聚合页 链接 316 // 查询有效时间后 有效的产品、新闻、博客、聚合页 链接
316 - $product = Product::where(['status' => Product::STATUS_ON])->where('created_at', '>=', $date)->pluck('route'); 317 +// $product = Product::where(['status' => Product::STATUS_ON])->where('created_at', '>=', $date)->pluck('route');
317 $news = News::where(['status' => News::STATUS_ONE])->where('release_at', '>', $date)->pluck('url'); 318 $news = News::where(['status' => News::STATUS_ONE])->where('release_at', '>', $date)->pluck('url');
318 $blog = Blog::where(['status' => Blog::STATUS_ONE])->where('release_at', '>', $date)->pluck('url'); 319 $blog = Blog::where(['status' => Blog::STATUS_ONE])->where('release_at', '>', $date)->pluck('url');
319 // $keyword = Keyword::where('created_at', '>', $date)->pluck('route'); 320 // $keyword = Keyword::where('created_at', '>', $date)->pluck('route');
  321 + $ai_blog = AiBlog::where(['status' => AiBlog::STATUS_FINISH])->where('updated_at', '>=', $date)->pluck('route');
320 322
321 // 组装链接 323 // 组装链接
322 - foreach ($product as $item) {  
323 - $url = 'https://' . $domain . '/' . $item;  
324 - array_push($result, $url);  
325 - } 324 +// foreach ($product as $item) {
  325 +// $url = 'https://' . $domain . '/' . $item;
  326 +// array_push($result, $url);
  327 +// }
326 // foreach ($keyword as $item) { 328 // foreach ($keyword as $item) {
327 // $url = 'https://' . $domain . '/' . $item; 329 // $url = 'https://' . $domain . '/' . $item;
328 // array_push($result, $url); 330 // array_push($result, $url);
@@ -335,6 +337,10 @@ class PrivateController extends BaseController @@ -335,6 +337,10 @@ class PrivateController extends BaseController
335 $url = 'https://' . $domain . '/blogs/' . $item; 337 $url = 'https://' . $domain . '/blogs/' . $item;
336 array_push($result, $url); 338 array_push($result, $url);
337 } 339 }
  340 + foreach ($ai_blog as $item) {
  341 + $url = 'https://' . $domain . '/blog/' . $item;
  342 + array_push($result, $url);
  343 + }
338 return $this->success($result); 344 return $this->success($result);
339 } 345 }
340 346
@@ -250,7 +250,7 @@ class ProjectLogic extends BaseLogic @@ -250,7 +250,7 @@ class ProjectLogic extends BaseLogic
250 public function createAuthor($project_id,$mch_id,$key){ 250 public function createAuthor($project_id,$mch_id,$key){
251 //查看当前项目是否已经创建了作者 251 //查看当前项目是否已经创建了作者
252 $aiBlogTaskModel = new AiBlogTask(); 252 $aiBlogTaskModel = new AiBlogTask();
253 - $count = $aiBlogTaskModel->counts(['project_id'=>$project_id]); 253 + $count = $aiBlogTaskModel->counts(['project_id'=>$project_id,'type' => 1]);
254 if($count > 0){ 254 if($count > 0){
255 return true; 255 return true;
256 } 256 }
@@ -259,6 +259,7 @@ class ProjectLogic extends BaseLogic @@ -259,6 +259,7 @@ class ProjectLogic extends BaseLogic
259 $aiBlogService->key = $key; 259 $aiBlogService->key = $key;
260 $result = $aiBlogService->createAuthor(); 260 $result = $aiBlogService->createAuthor();
261 if($result['status'] == 200){ 261 if($result['status'] == 200){
  262 + //查看当前是否已有未执行的
262 $aiBlogTaskModel->add(['project_id'=>$project_id,'status'=>1,'type'=>1]); 263 $aiBlogTaskModel->add(['project_id'=>$project_id,'status'=>1,'type'=>1]);
263 } 264 }
264 return true; 265 return true;
@@ -489,7 +489,7 @@ class RankDataLogic extends BaseLogic @@ -489,7 +489,7 @@ class RankDataLogic extends BaseLogic
489 $without_project_ids = []; //不用处理排名的项目 489 $without_project_ids = []; //不用处理排名的项目
490 $without_extension_project_ids = [658]; //是否达标只统计主词的 490 $without_extension_project_ids = [658]; //是否达标只统计主词的
491 $extension_project_ids = [354]; //扩展词也到达标的 491 $extension_project_ids = [354]; //扩展词也到达标的
492 - $compliance_project_ids = [2163,257]; //直接达标处理的 492 + $compliance_project_ids = [2163,257,823]; //直接达标处理的
493 $ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066,];//暂停项目id 493 $ceaseProjectId = [47, 354, 378, 649, 1226, 1283, 1703, 1893, 2066,];//暂停项目id
494 //一个项目多个api_no 494 //一个项目多个api_no
495 $multiple_api_no_project_ids = [ 495 $multiple_api_no_project_ids = [
@@ -63,7 +63,10 @@ class UserLoginLogic @@ -63,7 +63,10 @@ class UserLoginLogic
63 $projectArr[] = $v['project_id']; 63 $projectArr[] = $v['project_id'];
64 } 64 }
65 $projectModel = new Project(); 65 $projectModel = new Project();
66 - $project_list = $projectModel->list(['id'=>['in',$projectArr],'delete_status'=>0],'id',['id','title']); 66 + $project_list = $projectModel->list(['id'=>['in',$projectArr],'type'=>['!=',8],'delete_status'=>0],'id',['id','title']);
  67 + if(empty($project_list)){
  68 + $this->fail('当前项目已关闭,请联系管理员');
  69 + }
67 foreach ($project_list as $k => $v){ 70 foreach ($project_list as $k => $v){
68 $v['domain'] = (new DomainInfo())->getProjectIdDomain($v['id']); 71 $v['domain'] = (new DomainInfo())->getProjectIdDomain($v['id']);
69 $project_list[$k] = $v; 72 $project_list[$k] = $v;
@@ -181,12 +184,15 @@ class UserLoginLogic @@ -181,12 +184,15 @@ class UserLoginLogic
181 * @time :2023/8/29 15:26 184 * @time :2023/8/29 15:26
182 */ 185 */
183 public function assembleParam($mobile,$project_id){ 186 public function assembleParam($mobile,$project_id){
184 - $info = $this->model->read(['mobile'=>$mobile,'project_id'=>$project_id],['id','mobile','status','role_id','token','name','wechat','project_id']); 187 + $info = $this->model->read(['mobile'=>$mobile,'project_id'=>$project_id],['id','mobile','status','type','role_id','token','name','wechat','project_id']);
185 //获取项目详情 188 //获取项目详情
186 $project = $this->getProjectInfo($project_id); 189 $project = $this->getProjectInfo($project_id);
187 if($project['site_status'] != 0){//关闭站点 190 if($project['site_status'] != 0){//关闭站点
188 $this->fail('当前网站已过期,请联系管理员及时续费。'); 191 $this->fail('当前网站已过期,请联系管理员及时续费。');
189 } 192 }
  193 + if($project['type'] == 8){//关闭项目
  194 + $this->fail('当前网站已关闭,请联系管理员。');
  195 + }
190 $info = $this->handleInfo($info,$project); 196 $info = $this->handleInfo($info,$project);
191 $info['login_source'] = User::LOGIN_PASSWORD_SOURCE;//账号密码登录返回 197 $info['login_source'] = User::LOGIN_PASSWORD_SOURCE;//账号密码登录返回
192 //保存项目缓存 198 //保存项目缓存
@@ -10,4 +10,7 @@ class AiBlog extends Base @@ -10,4 +10,7 @@ class AiBlog extends Base
10 //连接数据库 10 //连接数据库
11 protected $connection = 'custom_mysql'; 11 protected $connection = 'custom_mysql';
12 12
  13 + const STATUS_INIT = 0;
  14 + const STATUS_RUNNING = 1;
  15 + const STATUS_FINISH = 2;
13 } 16 }
@@ -70,6 +70,28 @@ class Base extends Model @@ -70,6 +70,28 @@ class Base extends Model
70 } 70 }
71 71
72 /** 72 /**
  73 + * @remark :随机获取数据
  74 + * @name :limit_list
  75 + * @author :lyh
  76 + * @method :post
  77 + * @time :2025/3/17 17:26
  78 + */
  79 + public function limit_list($map = [],$order = 'id',$fields = ['*'],$sort = 'desc',$row = 0): array
  80 + {
  81 + $query = $this->formatQuery($map);
  82 + if($row != 0){
  83 + $query = $query->limit($row);
  84 + }
  85 + $query = $this->sortOrder($query,$order,$sort);
  86 + $lists = $query->select($fields)->get();
  87 + if (empty($lists)) {
  88 + return [];
  89 + }
  90 + $lists = $lists->toArray();
  91 + return $lists;
  92 + }
  93 +
  94 + /**
73 * @remark :获取数据详情 95 * @remark :获取数据详情
74 * @name :read 96 * @name :read
75 * @author :lyh 97 * @author :lyh
@@ -91,7 +91,8 @@ class Project extends Base @@ -91,7 +91,8 @@ class Project extends Base
91 4 => '推广续网站', 91 4 => '推广续网站',
92 5 => '未续费项目', 92 5 => '未续费项目',
93 6 => '特殊推广项目', 93 6 => '特殊推广项目',
94 - 7 => '提单错误转续费' 94 + 7 => '提单错误转续费',
  95 + 8 => '关闭项目',
95 ]; 96 ];
96 } 97 }
97 98