作者 赵彬吉
正在显示 41 个修改的文件 包含 1205 行增加357 行删除
@@ -100,6 +100,9 @@ class AiBlogAutoPublish extends Command @@ -100,6 +100,9 @@ class AiBlogAutoPublish extends Command
100 //2、未达标的项目,开启AIblog, 并立即推送三篇; 100 //2、未达标的项目,开启AIblog, 并立即推送三篇;
101 //3、其他项目等下下周 1 (2025-03-17)开始推送第一篇, 之后按照正频率发送; 101 //3、其他项目等下下周 1 (2025-03-17)开始推送第一篇, 之后按照正频率发送;
102 if (!$last_task) { 102 if (!$last_task) {
  103 + if(strpos($frequency[0],'/')){
  104 + $frequency = [1,1];//默认每天执行
  105 + }
103 if(!$compliance) { 106 if(!$compliance) {
104 for ($i = 0; $i < 3; $i++) { 107 for ($i = 0; $i < 3; $i++) {
105 $this->createTask($keywords, $project->id, $frequency); 108 $this->createTask($keywords, $project->id, $frequency);
@@ -110,7 +113,18 @@ class AiBlogAutoPublish extends Command @@ -110,7 +113,18 @@ class AiBlogAutoPublish extends Command
110 } 113 }
111 } 114 }
112 } else { 115 } else {
113 - $this->createTask($keywords, $project->id, $frequency); 116 + if($frequency[0] == '1/2'){//一天2篇
  117 + $aiBlogTaskModel = new AiBlogTaskModel();
  118 + $frequency = explode('/', $frequency[0]);
  119 + //查询当前已发布几篇
  120 + $count = $aiBlogTaskModel->counts(['next_auto_date' => date('Y-m-d'),'project_id' => $project->id]);
  121 + while ($count < ($frequency[1] ?? 2)){
  122 + $this->createTask($keywords, $project->id, [$frequency[0],$frequency[0]]);
  123 + $count++;
  124 + }
  125 + }else{
  126 + $this->createTask($keywords, $project->id, $frequency);
  127 + }
114 } 128 }
115 }catch (\Exception $e){ 129 }catch (\Exception $e){
116 (new DingService())->handle([ 130 (new DingService())->handle([
@@ -133,7 +147,7 @@ class AiBlogAutoPublish extends Command @@ -133,7 +147,7 @@ class AiBlogAutoPublish extends Command
133 $result = $aiBlogService->createTask($keyword); 147 $result = $aiBlogService->createTask($keyword);
134 if ($result['status'] == 200) { 148 if ($result['status'] == 200) {
135 $aiBlogTaskModel = new AiBlogTaskModel(); 149 $aiBlogTaskModel = new AiBlogTaskModel();
136 - $next_auto_date = date('Y-m-d', strtotime('+' . mt_rand($frequency[0],$frequency[1]) . 'days')); //每3-6天自动发布 150 + $next_auto_date = date('Y-m-d', strtotime('+' . mt_rand($frequency[0] ?? 3, $frequency[1] ?? 6) . 'days')); //每3-6天自动发布
137 $aiBlogTaskModel->addReturnId(['project_id' => $project_id, 'type' => 2, 'task_id' => $result['data']['task_id'], 'status' => 1, 'next_auto_date' => $next_auto_date]); 151 $aiBlogTaskModel->addReturnId(['project_id' => $project_id, 'type' => 2, 'task_id' => $result['data']['task_id'], 'status' => 1, 'next_auto_date' => $next_auto_date]);
138 ProjectServer::useProject($project_id); 152 ProjectServer::useProject($project_id);
139 $aiBlogModel = new AiBlog(); 153 $aiBlogModel = new AiBlog();
@@ -141,7 +155,6 @@ class AiBlogAutoPublish extends Command @@ -141,7 +155,6 @@ class AiBlogAutoPublish extends Command
141 $end = strtotime('16:00:00'); 155 $end = strtotime('16:00:00');
142 $randomTimestamp = mt_rand($start, $end); 156 $randomTimestamp = mt_rand($start, $end);
143 $created_at = date("Y-m-d H:i:s", $randomTimestamp); 157 $created_at = date("Y-m-d H:i:s", $randomTimestamp);
144 -  
145 $aiBlogModel->addReturnId(['keyword' => $keyword, 'status' => 1, 'task_id' => $result['data']['task_id'], 'project_id' => $project_id, 'created_at' => $created_at]); 158 $aiBlogModel->addReturnId(['keyword' => $keyword, 'status' => 1, 'task_id' => $result['data']['task_id'], 'project_id' => $project_id, 'created_at' => $created_at]);
146 DB::disconnect('custom_mysql'); 159 DB::disconnect('custom_mysql');
147 $this->output("任务创建成功"); 160 $this->output("任务创建成功");
@@ -293,6 +293,9 @@ class AiBlogTask extends Command @@ -293,6 +293,9 @@ class AiBlogTask extends Command
293 $domainModel = new DomainInfo(); 293 $domainModel = new DomainInfo();
294 $project_model = new Project(); 294 $project_model = new Project();
295 foreach ($routes as $project_id => $route){ 295 foreach ($routes as $project_id => $route){
  296 + if($project_id == 4339){
  297 + continue;
  298 + }
296 $route[] = 'top-blog'; 299 $route[] = 'top-blog';
297 $domain = $domainModel->getProjectIdDomain($project_id); 300 $domain = $domainModel->getProjectIdDomain($project_id);
298 if (empty($domain)) { 301 if (empty($domain)) {
@@ -241,7 +241,7 @@ class AiVideoAutoPublish extends Command @@ -241,7 +241,7 @@ class AiVideoAutoPublish extends Command
241 $storage = $aiVideoTaskModel->videoSetting()[$video_setting ?? 1]; 241 $storage = $aiVideoTaskModel->videoSetting()[$video_setting ?? 1];
242 $frequency = $aiVideoTaskModel->videoFrequency()[$frequency_setting ?? 1]; 242 $frequency = $aiVideoTaskModel->videoFrequency()[$frequency_setting ?? 1];
243 $frequencyArr = explode('-',$frequency); 243 $frequencyArr = explode('-',$frequency);
244 - $result = $aiVideoService->createTask($info['title'],$info['remark'],$info['images'],[],$storage); 244 + $result = $aiVideoService->createTask($info['title'],$info['remark'],array_slice($info['images'], 0, 8),[],$storage);
245 if($result['status'] == 200){ 245 if($result['status'] == 200){
246 $next_auto_date = date('Y-m-d', strtotime('+' . mt_rand($frequencyArr[0] ?? 5,$frequencyArr[1] ?? 7) . 'days')); //每5-7天自动发布 246 $next_auto_date = date('Y-m-d', strtotime('+' . mt_rand($frequencyArr[0] ?? 5,$frequencyArr[1] ?? 7) . 'days')); //每5-7天自动发布
247 $aiVideoTaskModel->addReturnId(['next_auto_date'=>$next_auto_date,'task_id'=>$result['data']['task_id'],'project_id'=>$info['project_id'],'storage'=>$storage]); 247 $aiVideoTaskModel->addReturnId(['next_auto_date'=>$next_auto_date,'task_id'=>$result['data']['task_id'],'project_id'=>$info['project_id'],'storage'=>$storage]);
@@ -250,6 +250,8 @@ class AiVideoAutoPublish extends Command @@ -250,6 +250,8 @@ class AiVideoAutoPublish extends Command
250 $aiVideoModel->addReturnId(['title'=>$info['title'],'task_id'=>$result['data']['task_id'],'description'=>$info['remark'],'project_id'=>$info['project_id'],'images'=>json_encode($info['images'],true),'anchor'=>json_encode([],true)]); 250 $aiVideoModel->addReturnId(['title'=>$info['title'],'task_id'=>$result['data']['task_id'],'description'=>$info['remark'],'project_id'=>$info['project_id'],'images'=>json_encode($info['images'],true),'anchor'=>json_encode([],true)]);
251 DB::disconnect('custom_mysql'); 251 DB::disconnect('custom_mysql');
252 $aiVideoAutoLogModel->edit(['status'=>2],['id'=>$info['id']]); 252 $aiVideoAutoLogModel->edit(['status'=>2],['id'=>$info['id']]);
  253 + }else{
  254 + $aiVideoAutoLogModel->edit(['status'=>3],['id'=>$info['id']]);
253 } 255 }
254 }catch (\Exception $e){ 256 }catch (\Exception $e){
255 $this->output( date('Y-m-d H:i:s').':当前数据不存在或已被删除'.$task_id); 257 $this->output( date('Y-m-d H:i:s').':当前数据不存在或已被删除'.$task_id);
@@ -113,7 +113,7 @@ class DomainInfo extends Command @@ -113,7 +113,7 @@ class DomainInfo extends Command
113 } else { 113 } else {
114 //除自建站项目外,记录已解析到别的ip的域名 114 //除自建站项目外,记录已解析到别的ip的域名
115 if (!check_domain_record($v['domain'], $servers_ip_info)) { 115 if (!check_domain_record($v['domain'], $servers_ip_info)) {
116 - Log::channel('analyze_other')->error('域名 [' . $v['domain'] . '] 已解析到别的IP'); 116 + Log::channel('analyze_other')->error('服务器ID [' . $servers_ip_info['servers_id'] . '] 域名 [' . $v['domain'] . '] 已解析到别的IP');
117 continue; 117 continue;
118 } 118 }
119 119
@@ -166,7 +166,7 @@ class DomainInfo extends Command @@ -166,7 +166,7 @@ class DomainInfo extends Command
166 if ($servers_ip_info['servers_id'] != ServerConfig::SELF_SITE_ID) { 166 if ($servers_ip_info['servers_id'] != ServerConfig::SELF_SITE_ID) {
167 //过滤已解析到别的ip的AMP域名 167 //过滤已解析到别的ip的AMP域名
168 if (!check_domain_record($amp_domain, $servers_ip_info)) { 168 if (!check_domain_record($amp_domain, $servers_ip_info)) {
169 - Log::channel('analyze_other')->error('AMP域名 [' . $amp_domain . '] 已解析到别的IP'); 169 + Log::channel('analyze_other')->error('服务器ID [' . $servers_ip_info['servers_id'] . '] AMP域名 [' . $amp_domain . '] 已解析到别的IP');
170 continue; 170 continue;
171 } 171 }
172 } 172 }
@@ -324,7 +324,7 @@ class DomainInfo extends Command @@ -324,7 +324,7 @@ class DomainInfo extends Command
324 324
325 //过滤已解析到别的ip的域名 325 //过滤已解析到别的ip的域名
326 if (!check_domain_record($v['custom_domain'], $servers_ip_info)) { 326 if (!check_domain_record($v['custom_domain'], $servers_ip_info)) {
327 - Log::channel('analyze_other')->error('自定义跳转域名 [' . $v['custom_domain'] . '] 已解析到别的IP'); 327 + Log::channel('analyze_other')->error('服务器ID [' . $servers_ip_info['servers_id'] . '] 自定义跳转域名 [' . $v['custom_domain'] . '] 已解析到别的IP');
328 continue; 328 continue;
329 } 329 }
330 330
@@ -403,11 +403,18 @@ class DomainInfo extends Command @@ -403,11 +403,18 @@ class DomainInfo extends Command
403 * @param $domain_id 403 * @param $domain_id
404 * @param $domain 404 * @param $domain
405 * @param $is_end 405 * @param $is_end
  406 + * @return bool
406 * @author Akun 407 * @author Akun
407 * @date 2025/08/14 9:56 408 * @date 2025/08/14 9:56
408 */ 409 */
409 public function domainChatMessage($project_id, $domain_id, $domain, $is_end) 410 public function domainChatMessage($project_id, $domain_id, $domain, $is_end)
410 { 411 {
  412 + //每周一推送
  413 + $week_day = date('w');
  414 + if ($week_day != 1) {
  415 + return true;
  416 + }
  417 +
411 //项目是否有绑定群 418 //项目是否有绑定群
412 $friend_id = ProjectAssociation::where('project_id', $project_id) 419 $friend_id = ProjectAssociation::where('project_id', $project_id)
413 ->where('status', ProjectAssociation::STATUS_NORMAL) 420 ->where('status', ProjectAssociation::STATUS_NORMAL)
@@ -431,6 +438,8 @@ class DomainInfo extends Command @@ -431,6 +438,8 @@ class DomainInfo extends Command
431 $messagePushModel = new MessagePush(); 438 $messagePushModel = new MessagePush();
432 $messagePushModel->add($param); 439 $messagePushModel->add($param);
433 } 440 }
  441 +
  442 + return true;
434 } 443 }
435 444
436 /** 445 /**
@@ -439,6 +448,12 @@ class DomainInfo extends Command @@ -439,6 +448,12 @@ class DomainInfo extends Command
439 */ 448 */
440 public function domainChatMessageV5() 449 public function domainChatMessageV5()
441 { 450 {
  451 + //每周一推送
  452 + $week_day = date('w');
  453 + if ($week_day != 1) {
  454 + return true;
  455 + }
  456 +
442 $domain_json = @file_get_contents('https://www.quanqiusou.cn/extend_api/aicc/domain_expire_lists.php'); 457 $domain_json = @file_get_contents('https://www.quanqiusou.cn/extend_api/aicc/domain_expire_lists.php');
443 $domains = json_decode($domain_json, true); 458 $domains = json_decode($domain_json, true);
444 if (empty($domains)) 459 if (empty($domains))
@@ -118,7 +118,7 @@ class RemainDay extends Command @@ -118,7 +118,7 @@ class RemainDay extends Command
118 */ 118 */
119 public function seoRemainDay($deploy_build,$item){ 119 public function seoRemainDay($deploy_build,$item){
120 //白帽版本的系统 120 //白帽版本的系统
121 - if($deploy_build['seo_plan'] == 1){ 121 + if($deploy_build['seo_plan'] != 0){
122 if($deploy_build['seo_service_duration'] != 0){ 122 if($deploy_build['seo_service_duration'] != 0){
123 if(in_array($item['id'],$this->bm_projectId) || (in_array( 19,$item['level']))){ 123 if(in_array($item['id'],$this->bm_projectId) || (in_array( 19,$item['level']))){
124 $compliance_day = (int)$item['bm_finish_remain_day']; 124 $compliance_day = (int)$item['bm_finish_remain_day'];
@@ -119,24 +119,23 @@ class GeoQuestionRes extends Command @@ -119,24 +119,23 @@ class GeoQuestionRes extends Command
119 $hit_data = array_merge($url, $title, $hit_data); 119 $hit_data = array_merge($url, $title, $hit_data);
120 } 120 }
121 $hit = 0; 121 $hit = 0;
122 - //todo::与预期结果是否复合  
123 - if(!empty($taskInfo['expect_result'])){  
124 - $str = "客户提出的问题:{$question},客户得到的回复:{$result['text']},客户需要预期:{$taskInfo['expect_result']},请分析得到的回复和预期是否一致,仅回复我是或者否";  
125 - $strResult = $geo_service->getChatResult($str, 'gpt-4o-mini');  
126 - if(isset($strResult['text']) && !empty($strResult['text'])){  
127 - switch ($strResult['text']){  
128 - case '是':  
129 - $is_match = 1;  
130 - $hit++;  
131 - break;  
132 - case '否':  
133 - $is_match = 2;  
134 - break;  
135 - default:  
136 - $is_match = 0;  
137 - break;  
138 - } 122 + $is_match = 0;
  123 + $cosine = 0;
  124 + $similarity = [];
  125 + // TODO 有预期结果,分析答案和预期结果
  126 + if(FALSE == empty($taskInfo['expect_result'])){
  127 + $cosine_result = $geo_service->cosineSimilarity($taskInfo['expect_result'], $result['text']);
  128 + // 语义是否一致
  129 + if (FALSE == empty($cosine_result['judgement'])) {
  130 + $is_match = $cosine_result['judgement'] == '语义相近' ? 1 : 2;
  131 + $hit++;
139 } 132 }
  133 + // 余弦相似度
  134 + if (FALSE == empty($cosine_result['similarity']))
  135 + $cosine = intval($cosine_result['similarity'] * 10000) / 100;
  136 + // 语句拆解结果
  137 + if (FALSE == empty($cosine_result['split_results']))
  138 + $similarity = $cosine_result['split_results'];
140 } 139 }
141 $hit_keyword = $this->getKeywords($taskInfo['keywords'],$hit_data); 140 $hit_keyword = $this->getKeywords($taskInfo['keywords'],$hit_data);
142 if (!empty($hit_keyword['keywords'])) { 141 if (!empty($hit_keyword['keywords'])) {
@@ -165,6 +164,8 @@ class GeoQuestionRes extends Command @@ -165,6 +164,8 @@ class GeoQuestionRes extends Command
165 'url_num'=>$url_num ?? [], 164 'url_num'=>$url_num ?? [],
166 'is_match'=>$is_match ?? 0, 165 'is_match'=>$is_match ?? 0,
167 'label'=>$taskInfo['label'] ?? null, 166 'label'=>$taskInfo['label'] ?? null,
  167 + 'cosine' => $cosine,
  168 + 'similarity' => json_encode($similarity, true),
168 'created_at'=>date('Y-m-d H:i:s'), 169 'created_at'=>date('Y-m-d H:i:s'),
169 'updated_at'=>date('Y-m-d H:i:s'), 170 'updated_at'=>date('Y-m-d H:i:s'),
170 ]; 171 ];
@@ -315,17 +316,6 @@ class GeoQuestionRes extends Command @@ -315,17 +316,6 @@ class GeoQuestionRes extends Command
315 } 316 }
316 317
317 /** 318 /**
318 - * @remark :预期结果对比  
319 - * @name :getExpectResult  
320 - * @author :lyh  
321 - * @method :post  
322 - * @time :2025/8/12 13:51  
323 - */  
324 - public function getExpectResult($question,$answer,$expect){  
325 - $str = "客户提出的问题:{$question},客户得到的回复:{$answer},客户需要预期:{$expect},请分析得到的回复和预期是否一致,仅回复我是或者否";  
326 - }  
327 -  
328 - /**  
329 * 获取待执行任务ID 319 * 获取待执行任务ID
330 * @return mixed 320 * @return mixed
331 */ 321 */
@@ -174,7 +174,7 @@ class VideoTask extends Command @@ -174,7 +174,7 @@ class VideoTask extends Command
174 'is_ytb'=>false, 174 'is_ytb'=>false,
175 'other_language_subtitle'=>false 175 'other_language_subtitle'=>false
176 ]; 176 ];
177 - $result = Http::post('http://216.250.255.116:7866/create_task', $data); 177 + $result = Http::post('http://216.250.255.116:7866/create_task', $data);//todo::小天的接口
178 $res_json = json_decode($result,true); 178 $res_json = json_decode($result,true);
179 $val->task_id = $task_id; 179 $val->task_id = $task_id;
180 $val->status = KeywordVideoTaskLog::STATUS_ERROR; 180 $val->status = KeywordVideoTaskLog::STATUS_ERROR;
@@ -33,6 +33,7 @@ class CreateProject extends Command @@ -33,6 +33,7 @@ class CreateProject extends Command
33 protected $description = '创建项目'; 33 protected $description = '创建项目';
34 34
35 public function handle(){ 35 public function handle(){
  36 + dd(1);
36 return $this->sync(); 37 return $this->sync();
37 } 38 }
38 39
@@ -42,10 +43,12 @@ class CreateProject extends Command @@ -42,10 +43,12 @@ class CreateProject extends Command
42 * @throws \Exception 43 * @throws \Exception
43 */ 44 */
44 public function sync($is_update = 0){ 45 public function sync($is_update = 0){
45 - $company = '济南市莱芜凤城铝合金有限公司';  
46 - $mobile = '13806340552';  
47 - $plan = '标准版';  
48 - $cooperate_date = '2019-11-19'; 46 + $company = '山东临磨数控机床装备有限公司(自建站)';
  47 + $mobile = '18663004388';
  48 + $lead_name = '18663004388';
  49 + $plan = '商务版';
  50 + $cooperate_date = '2025-08-21';
  51 +// $channel = '{"user_id": "732", "zone_id": "1", "channel_id": "95"}';
49 $channel = '{"user_id": "1989", "zone_id": "4", "channel_id": "13"}'; 52 $channel = '{"user_id": "1989", "zone_id": "4", "channel_id": "13"}';
50 53
51 $title = date('Ymd') . '-' . $company; 54 $title = date('Ymd') . '-' . $company;
@@ -53,7 +56,7 @@ class CreateProject extends Command @@ -53,7 +56,7 @@ class CreateProject extends Command
53 'project'=>[ 56 'project'=>[
54 'title' => $title, 57 'title' => $title,
55 'company' => $company, 58 'company' => $company,
56 - 'lead_name' => $mobile, 59 + 'lead_name' => $lead_name,
57 'mobile' => $mobile, 60 'mobile' => $mobile,
58 'mysql_id'=>Project::MYSQL_ID, 61 'mysql_id'=>Project::MYSQL_ID,
59 'serve_id'=>9, 62 'serve_id'=>9,
@@ -61,7 +64,7 @@ class CreateProject extends Command @@ -61,7 +64,7 @@ class CreateProject extends Command
61 'channel' => $channel, 64 'channel' => $channel,
62 'requirement' => '', 65 'requirement' => '',
63 'cooperate_date' => $cooperate_date, 66 'cooperate_date' => $cooperate_date,
64 - 'from_order_id' => '', 67 + 'from_order_id' => uniqid(),
65 'type' => $is_update, 68 'type' => $is_update,
66 'is_upgrade'=>$is_update, 69 'is_upgrade'=>$is_update,
67 ], 70 ],
@@ -101,6 +101,19 @@ class SyncProject extends Command @@ -101,6 +101,19 @@ class SyncProject extends Command
101 if($data['data']['order_type'] == '续费'){ 101 if($data['data']['order_type'] == '续费'){
102 $this->renewSync($data['data']); 102 $this->renewSync($data['data']);
103 } 103 }
  104 + // TODO 如果是续费项目 并且有GEO版本,需要处理GEO版本
  105 + if (($data['data']['order_type'] == '续费') && !empty($data['data']['geo_plan']) && ($data['data']['geo_plan'] != '无')) {
  106 + // 续费单,并且有GEO版本, 正常版本不创建 初始化正常版本
  107 + $data['data']['plan_marketing'] = '无';
  108 + //创建对应的GEO版本
  109 + $projectModel = new Project();
  110 + $seo_plan = $this->versionSeoData($data['data']['geo_plan'] ?? '');
  111 + $projectInfo = $projectModel->leftJoin('gl_project_deploy_build', 'gl_project.id', '=', 'gl_project_deploy_build.project_id')->where('gl_project.company', $data['data']['company_name'])->where('gl_project_deploy_build.seo_plan',$seo_plan)->select(['gl_project.id AS id'])->first();
  112 + if (empty($projectInfo)) {
  113 + // 创建对应GEO项目
  114 + $this->sync($data['data'],$is_update);
  115 + }
  116 + }
104 $item->status = NoticeLog::STATUS_SUCCESS; 117 $item->status = NoticeLog::STATUS_SUCCESS;
105 $item->save(); 118 $item->save();
106 echo 'success:' . $item['id'] . '执行时间:' . date('Y-m-d H:i:s') . PHP_EOL; 119 echo 'success:' . $item['id'] . '执行时间:' . date('Y-m-d H:i:s') . PHP_EOL;
@@ -136,7 +149,7 @@ class SyncProject extends Command @@ -136,7 +149,7 @@ class SyncProject extends Command
136 * @time :2023/8/11 15:33 149 * @time :2023/8/11 15:33
137 */ 150 */
138 public function renewSync($param){ 151 public function renewSync($param){
139 - $title = date('Ymd') . '-' . $param['company_name'];; 152 + $title = date('Ymd') . '-' . $param['company_name'];
140 $data = [ 153 $data = [
141 'title' => '【续费单】'.$title, 154 'title' => '【续费单】'.$title,
142 'company' => $param['company_name'], 155 'company' => $param['company_name'],
@@ -146,7 +159,7 @@ class SyncProject extends Command @@ -146,7 +159,7 @@ class SyncProject extends Command
146 'channel' => json_encode(Channel::getProjectChannel($param['company_id'], $param['username_sales'])), 159 'channel' => json_encode(Channel::getProjectChannel($param['company_id'], $param['username_sales'])),
147 'requirement' => $param['remark'], 160 'requirement' => $param['remark'],
148 'cooperate_date' => date('Y-m-d', $param['create_time']), 161 'cooperate_date' => date('Y-m-d', $param['create_time']),
149 -// 'api_no' => $param['id'], //改手动填 162 + 'api_no' => $param['id'], //改手动填
150 'amount' => $param['plan_price'], 163 'amount' => $param['plan_price'],
151 'contract' => json_encode($param['files']), 164 'contract' => json_encode($param['files']),
152 'bill' => json_encode($param['images']), 165 'bill' => json_encode($param['images']),
  1 +<?php
  2 +
  3 +namespace App\Console\Commands\Project;
  4 +
  5 +use App\Helper\Arr;
  6 +use App\Models\Product\Product;
  7 +use App\Models\Project\Project;
  8 +use App\Services\ProjectServer;
  9 +use Illuminate\Console\Command;
  10 +use Illuminate\Support\Facades\DB;
  11 +
  12 +class ThumbProjectImage extends Command
  13 +{
  14 + /**
  15 + * The name and signature of the console command.
  16 + *
  17 + * @var string
  18 + */
  19 + protected $signature = 'thumb_project_image {project_id}';
  20 +
  21 + /**
  22 + * The console command description.
  23 + *
  24 + * @var string
  25 + */
  26 + protected $description = '处理项目产品缩略图';
  27 +
  28 + public function handle()
  29 + {
  30 + $project_id = $this->argument('project_id');
  31 +
  32 + if ($project_id > 0) {
  33 + //指定项目
  34 + $this->output('project_id:' . $project_id . ' | start');
  35 +
  36 + $project_info = ProjectServer::useProject($project_id);
  37 +
  38 + if ($project_info) {
  39 + $thumb_w = $project_info->deploy_build->thumb_w ?? 0;
  40 + Product::select(['id', 'thumb'])->chunk(100, function ($products) use ($thumb_w) {
  41 + foreach ($products as $product) {
  42 + $thumb = $product->thumb;
  43 + if (isset($thumb['url']) && $thumb['url']) {
  44 + $new_thumb = thumbImageByUrl($thumb['url'], $thumb_w);
  45 + if ($new_thumb != $thumb['url']) {
  46 + $thumb['url'] = $new_thumb;
  47 + $product->timestamps = false;
  48 + $product->thumb = Arr::a2s($thumb);
  49 + $product->save();
  50 +
  51 + $this->output('product_id:' . $product->id . ' | success');
  52 + }
  53 + }
  54 + }
  55 + });
  56 +
  57 + DB::disconnect('custom_mysql');
  58 + }
  59 +
  60 + $this->output('project_id:' . $project_id . ' | end');
  61 + } else {
  62 + //所有项目
  63 + $projectModel = new Project();
  64 + $list = $projectModel->list(['delete_status' => 0, 'is_upgrade' => 0, 'type' => ['in', [1, 2, 3, 4, 6]]], 'id', ['id'], 'asc');
  65 + foreach ($list as $k => $v) {
  66 + $project_id = $v['id'];
  67 +
  68 + $this->output('project_id:' . $project_id . ' | start');
  69 +
  70 + $project_info = ProjectServer::useProject($project_id);
  71 +
  72 + if ($project_info) {
  73 + $thumb_w = $project_info->deploy_build->thumb_w ?? 0;
  74 + Product::select(['id', 'thumb'])->chunk(100, function ($products) use ($thumb_w) {
  75 + foreach ($products as $product) {
  76 + $thumb = $product->thumb;
  77 + if (isset($thumb['url']) && $thumb['url']) {
  78 + $new_thumb = thumbImageByUrl($thumb['url'], $thumb_w);
  79 + if ($new_thumb != $thumb['url']) {
  80 + $thumb['url'] = $new_thumb;
  81 + $product->timestamps = false;
  82 + $product->thumb = Arr::a2s($thumb);
  83 + $product->save();
  84 +
  85 + $this->output('product_id:' . $product->id . ' | success');
  86 + }
  87 + }
  88 + }
  89 + });
  90 +
  91 + DB::disconnect('custom_mysql');
  92 + }
  93 +
  94 + $this->output('project_id:' . $project_id . ' | end');
  95 + }
  96 + }
  97 + }
  98 +
  99 +
  100 + /**
  101 + * 输出处理日志
  102 + * @param $message
  103 + * @return bool
  104 + */
  105 + public function output($message)
  106 + {
  107 + echo date('Y-m-d H:i:s') . ' | ' . $message . PHP_EOL;
  108 + return true;
  109 + }
  110 +}
@@ -32,60 +32,29 @@ class SyncTimeFiles extends Command @@ -32,60 +32,29 @@ class SyncTimeFiles extends Command
32 { 32 {
33 $fileModel = new File(); 33 $fileModel = new File();
34 // $imagesModel = new Image(); 34 // $imagesModel = new Image();
35 - $start = '2024-11-07 15:00:00';  
36 - $end = '2024-11-07 15:25:00'; 35 + $start = '2025-08-20 00:00:00';
  36 + $end = '2025-08-28 00:00:00';
37 $lists = $fileModel->list(['created_at'=>['between',[$start,$end]]]); 37 $lists = $fileModel->list(['created_at'=>['between',[$start,$end]]]);
38 foreach ($lists as $v){ 38 foreach ($lists as $v){
39 $path = $v['path']; 39 $path = $v['path'];
40 - $this->param['name'] = basename($path);  
41 - $this->param['path'] = str_replace('/'.$this->param['name'],'',$path);  
42 - $file_path = $this->getUrl($this->param['path'].'/'.$this->param['name'], 0,0);  
43 - $cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$this->param['path'].'" https://v6-file.globalso.com/upload.php';  
44 - echo date('Y-m-d H:i:s') . ' | ' . $cmd . PHP_EOL;  
45 - $code = shell_exec($cmd); 40 + echo date('Y-m-d H:i:s') . ' | 图片链接:' . $path . PHP_EOL;
  41 + $code = $this->synchronizationFile($path);
46 if(200 != (int)$code){ 42 if(200 != (int)$code){
47 echo date('Y-m-d H:i:s') . ' | 错误状态:' . $code . PHP_EOL; 43 echo date('Y-m-d H:i:s') . ' | 错误状态:' . $code . PHP_EOL;
48 -// $errorFileModel = new ErrorFile();  
49 -// $errorFileModel->add(['path'=>$this->param['path'].'/'.$this->param['name']]); 44 + $errorFileModel = new ErrorFile();
  45 + $errorFileModel->add(['path'=>$this->param['path'].'/'.$this->param['name']]);
50 } 46 }
51 echo date('Y-m-d H:i:s') . ' | ok:' . $code . PHP_EOL; 47 echo date('Y-m-d H:i:s') . ' | ok:' . $code . PHP_EOL;
52 } 48 }
53 return true; 49 return true;
54 } 50 }
55 51
56 - /**  
57 - * @remark :获取图片文件链接  
58 - * @name :getUrl  
59 - * @author :lyh  
60 - * @method :post  
61 - * @time :2024/5/22 11:53  
62 - */  
63 - public function getUrl($path,$storage_type,$location){  
64 - if(is_array($path)){  
65 - $url =[];  
66 - foreach ($path as $v){  
67 - $url[] = $this->getUrl($v,$storage_type,$location);  
68 - }  
69 - }else{  
70 - if(empty($path)){  
71 - return '';  
72 - }  
73 - if((strpos($path,'https://')!== false) || (strpos($path,'http://') !== false)){  
74 - return $path;  
75 - }  
76 - if(substr($path,0,2) == '//'){  
77 - return 'https:'.$path;  
78 - }  
79 - if($location == 0){  
80 - $cos = config('filesystems.disks.cos');  
81 - $cosCdn = ($storage_type == 0) ? $cos['cdn'] : $cos['cdn1'];  
82 - $url = $cosCdn.$path;  
83 - }else{  
84 - $s3 = config('filesystems.disks.s3');  
85 - $cdn = $s3['cdn'];  
86 - $url = $cdn.$path;  
87 - }  
88 - }  
89 - return $url; 52 + public function synchronizationFile($path_name){
  53 + //同步到大文件
  54 + $file_path = config('filesystems.disks.cos')['cdn1'].$path_name;
  55 + $directoryPath = pathinfo($path_name, PATHINFO_DIRNAME);
  56 + $cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$directoryPath.'" https://v6-file.globalso.com/upload.php';
  57 + return shell_exec($cmd);
90 } 58 }
  59 +
91 } 60 }
@@ -47,16 +47,11 @@ class SyncTimeMinuteFile extends Command @@ -47,16 +47,11 @@ class SyncTimeMinuteFile extends Command
47 } 47 }
48 foreach ($lists as $v){ 48 foreach ($lists as $v){
49 $path = $v['path']; 49 $path = $v['path'];
50 - if (file_exists($dir.$path)) {  
51 - echo date('Y-m-d H:i:s') . ' | file_ok:' . $dir.$path . PHP_EOL;  
52 - continue;  
53 - }  
54 - $this->param['name'] = basename($path);  
55 - $this->param['path'] = str_replace('/'.$this->param['name'],'',$path);  
56 - $file_path = $this->getUrl($this->param['path'].'/'.$this->param['name'], 0,0);  
57 - $cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$this->param['path'].'" https://v6-file.globalso.com/upload.php';  
58 - echo date('Y-m-d H:i:s') . ' | ' . $cmd . PHP_EOL;  
59 - $code = shell_exec($cmd); 50 +// if (file_exists($dir.$path)) {
  51 +// echo date('Y-m-d H:i:s') . ' | file_ok:' . $dir.$path . PHP_EOL;
  52 +// continue;
  53 +// }
  54 + $code = $this->synchronizationFile($path);
60 if(200 != (int)$code){ 55 if(200 != (int)$code){
61 echo date('Y-m-d H:i:s') . ' | 错误状态:' . $code . PHP_EOL; 56 echo date('Y-m-d H:i:s') . ' | 错误状态:' . $code . PHP_EOL;
62 $errorFileModel = new ErrorFile(); 57 $errorFileModel = new ErrorFile();
@@ -67,6 +62,14 @@ class SyncTimeMinuteFile extends Command @@ -67,6 +62,14 @@ class SyncTimeMinuteFile extends Command
67 return true; 62 return true;
68 } 63 }
69 64
  65 + public function synchronizationFile($path_name){
  66 + //同步到大文件
  67 + $file_path = config('filesystems.disks.cos')['cdn1'].$path_name;
  68 + $directoryPath = pathinfo($path_name, PATHINFO_DIRNAME);
  69 + $cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$directoryPath.'" https://v6-file.globalso.com/upload.php';
  70 + return shell_exec($cmd);
  71 + }
  72 +
70 /** 73 /**
71 * @remark :获取图片文件链接 74 * @remark :获取图片文件链接
72 * @name :getUrl 75 * @name :getUrl
@@ -30,12 +30,7 @@ class SyncVideo extends Command @@ -30,12 +30,7 @@ class SyncVideo extends Command
30 public function handle() 30 public function handle()
31 { 31 {
32 $path = $this->argument('path'); 32 $path = $this->argument('path');
33 - $this->param['name'] = basename($path);  
34 - $this->param['path'] = str_replace('/'.$this->param['name'],'',$path);  
35 - $file_path = $this->getUrl($this->param['path'].'/'.$this->param['name'], 0,0);  
36 - $cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$this->param['path'].'" https://v6-file.globalso.com/upload.php';  
37 - echo date('Y-m-d H:i:s') . ' | ' . $cmd . PHP_EOL;  
38 - $code = shell_exec($cmd); 33 + $code = $this->synchronizationFile($path);
39 echo date('Y-m-d H:i:s') . ' | ' . $code . PHP_EOL; 34 echo date('Y-m-d H:i:s') . ' | ' . $code . PHP_EOL;
40 if(200 != (int)$code){ 35 if(200 != (int)$code){
41 echo date('Y-m-d H:i:s') . ' | ' . $code . PHP_EOL; 36 echo date('Y-m-d H:i:s') . ' | ' . $code . PHP_EOL;
@@ -45,6 +40,14 @@ class SyncVideo extends Command @@ -45,6 +40,14 @@ class SyncVideo extends Command
45 return true; 40 return true;
46 } 41 }
47 42
  43 + public function synchronizationFile($path_name){
  44 + //同步到大文件
  45 + $file_path = config('filesystems.disks.cos')['cdn1'].$path_name;
  46 + $directoryPath = pathinfo($path_name, PATHINFO_DIRNAME);
  47 + $cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$directoryPath.'" https://v6-file.globalso.com/upload.php';
  48 + return shell_exec($cmd);
  49 + }
  50 +
48 /** 51 /**
49 * @remark :获取图片文件链接 52 * @remark :获取图片文件链接
50 * @name :getUrl 53 * @name :getUrl
@@ -14,6 +14,10 @@ use App\Models\Manage\ManageHr; @@ -14,6 +14,10 @@ use App\Models\Manage\ManageHr;
14 use App\Models\Ticket\TicketDailyCount; 14 use App\Models\Ticket\TicketDailyCount;
15 use App\Models\Ticket\TicketDailyDeptCount; 15 use App\Models\Ticket\TicketDailyDeptCount;
16 use App\Models\Ticket\TicketDailyManageCount; 16 use App\Models\Ticket\TicketDailyManageCount;
  17 +use App\Models\Ticket\TicketMonthDeptCount;
  18 +use App\Models\Ticket\TicketMonthManageCount;
  19 +use App\Models\Ticket\TicketWeekDeptCount;
  20 +use App\Models\Ticket\TicketWeekManageCount;
17 use App\Models\WorkOrder\TicketLog; 21 use App\Models\WorkOrder\TicketLog;
18 use App\Models\WorkOrder\TicketProject; 22 use App\Models\WorkOrder\TicketProject;
19 use App\Models\WorkOrder\Tickets; 23 use App\Models\WorkOrder\Tickets;
@@ -55,9 +59,29 @@ class TicketCount extends Command @@ -55,9 +59,29 @@ class TicketCount extends Command
55 if($action == 'manage_action'){ 59 if($action == 'manage_action'){
56 $this->manage_action(); 60 $this->manage_action();
57 } 61 }
  62 + if($action == 'manage_week_action'){
  63 + $startOfLastWeek = Carbon::now()->subWeek()->startOfWeek(); // 上周一 00:00:00
  64 + $endOfLastWeek = Carbon::now()->subWeek()->endOfWeek(); // 上周日 23:59:59
  65 + $this->manage_week_month_action($startOfLastWeek,$endOfLastWeek,(new TicketWeekManageCount()));
  66 + }
  67 + if($action == 'manage_month_action'){
  68 + $startOfLastMonth = Carbon::now()->subMonth()->startOfMonth(); // 上个月 1号 00:00:00
  69 + $endOfLastMonth = Carbon::now()->subMonth()->endOfMonth(); // 上个月最后一天 23:59:59
  70 + $this->manage_week_month_action($startOfLastMonth,$endOfLastMonth,(new TicketMonthManageCount()));
  71 + }
58 if($action == 'dept_action'){ 72 if($action == 'dept_action'){
59 $this->dept_action(); 73 $this->dept_action();
60 } 74 }
  75 + if($action == 'dept_week_action'){
  76 + $startOfLastWeek = Carbon::now()->subWeek()->startOfWeek(); // 上周一 00:00:00
  77 + $endOfLastWeek = Carbon::now()->subWeek()->endOfWeek(); // 上周日 23:59:59
  78 + $this->dept_week_month_action($startOfLastWeek,$endOfLastWeek,(new TicketWeekDeptCount()));
  79 + }
  80 + if($action == 'dept_month_action'){
  81 + $startOfLastMonth = Carbon::now()->subMonth()->startOfMonth(); // 上个月 1号 00:00:00
  82 + $endOfLastMonth = Carbon::now()->subMonth()->endOfMonth(); // 上个月最后一天 23:59:59
  83 + $this->dept_week_month_action($startOfLastMonth,$endOfLastMonth,(new TicketMonthDeptCount()));
  84 + }
61 if($action == 'yesterday_daily_action'){ 85 if($action == 'yesterday_daily_action'){
62 $this->yesterday_daily_action(); 86 $this->yesterday_daily_action();
63 } 87 }
@@ -80,24 +104,36 @@ class TicketCount extends Command @@ -80,24 +104,36 @@ class TicketCount extends Command
80 $timeout_ratio = null; 104 $timeout_ratio = null;
81 $this->output('按人员统计:执行的人员名称/id:'.$item['name'].'/'.$item['manage_id']); 105 $this->output('按人员统计:执行的人员名称/id:'.$item['name'].'/'.$item['manage_id']);
82 $ticketLogModel = new TicketLog(); 106 $ticketLogModel = new TicketLog();
83 - $ticket_num = $ticketLogModel->counts(['engineer_id'=>$item['manage_id'],'is_engineer'=>1]); 107 + $ticket_num = $ticketLogModel->counts(['engineer_id'=>$item['manage_id'],'is_engineer'=>1,'status'=>['!=',9]]);
84 //工单总时长 108 //工单总时长
85 - $timeCount = $ticketLogModel->formatQuery(['engineer_id'=>$item['manage_id'],'is_engineer'=>1])->sum('end_time');  
86 - $complete_num = $ticketLogModel->counts(['engineer_id'=>$item['manage_id'],'is_engineer'=>1,'end_at'=>['!=',null]]); 109 + $timeCount = $ticketLogModel->formatQuery(['engineer_id'=>$item['manage_id'],'is_engineer'=>1,'status'=>['!=',9]])->sum('end_time');
  110 + $complete_num = $ticketLogModel->counts(['engineer_id'=>$item['manage_id'],'status'=>['!=',9],'is_engineer'=>1,'end_at'=>['!=',null]]);
87 if(!empty($timeCount)){ 111 if(!empty($timeCount)){
88 $average_time = round($timeCount / $complete_num, 3); 112 $average_time = round($timeCount / $complete_num, 3);
89 } 113 }
90 //最快完成的时间 114 //最快完成的时间
91 - $fastest_time = $ticketLogModel->formatQuery(['engineer_id'=>$item['manage_id'],'is_engineer'=>1,'end_at'=>['!=',null]])->min('end_time'); 115 + $fastest_time = $ticketLogModel->formatQuery(['engineer_id'=>$item['manage_id'],'status'=>['!=',9],'is_engineer'=>1,'end_at'=>['!=',null]])->min('end_time');
92 //最快完成时间 116 //最快完成时间
93 if(!$fastest_time){ 117 if(!$fastest_time){
94 $fastest_time = null; 118 $fastest_time = null;
95 } 119 }
96 //超时工单数量 120 //超时工单数量
97 - $timeout_num = $ticketLogModel->counts(['engineer_id'=>$item['manage_id'],'is_engineer'=>1,'plan_end_at'=>['>',date('Y-m-d H:i:s')]]); 121 + $timeout_num = $ticketLogModel
  122 + ->where('engineer_id', $item['manage_id'])->where('is_engineer', 1)->where('status','!=',9)
  123 + ->where(function ($query) {
  124 + $query->where(function ($q) {
  125 + $q->whereNotNull('end_at')->whereColumn('plan_end_at', '<', 'end_at');
  126 + })->orWhere(function ($q) {
  127 + $q->whereNull('end_at')->where('plan_end_at', '<', now());
  128 + });
  129 + })
  130 + ->count();
98 if(!empty($timeout_num)){ 131 if(!empty($timeout_num)){
99 $timeout_ratio = round($timeout_num / $ticket_num, 3); 132 $timeout_ratio = round($timeout_num / $ticket_num, 3);
100 } 133 }
  134 + if(!empty($complete_num)){
  135 + $complete_ratio = round($complete_num / $ticket_num, 2);
  136 + }
101 $data = [ 137 $data = [
102 'date'=>$date, 138 'date'=>$date,
103 'manage_id'=>$item['id'], 139 'manage_id'=>$item['id'],
@@ -108,7 +144,8 @@ class TicketCount extends Command @@ -108,7 +144,8 @@ class TicketCount extends Command
108 'timeout_num'=>$timeout_num,//超时工单数量 144 'timeout_num'=>$timeout_num,//超时工单数量
109 'complete_num'=>$complete_num,//完成工单数量 145 'complete_num'=>$complete_num,//完成工单数量
110 'dept_id'=>$item['dept_id'], 146 'dept_id'=>$item['dept_id'],
111 - 'timeout_ratio'=>$timeout_ratio ?? null 147 + 'timeout_ratio'=>$timeout_ratio ?? null,
  148 + 'complete_ratio'=>$complete_ratio ?? null
112 ]; 149 ];
113 //查询当前用户是否当日已有记录 150 //查询当前用户是否当日已有记录
114 $ticketManageInfo = $ticketManageCountModel->read(['date'=>$date,'manage_id'=>$item['id']],['id']); 151 $ticketManageInfo = $ticketManageCountModel->read(['date'=>$date,'manage_id'=>$item['id']],['id']);
@@ -124,6 +161,56 @@ class TicketCount extends Command @@ -124,6 +161,56 @@ class TicketCount extends Command
124 } 161 }
125 162
126 /** 163 /**
  164 + * @remark :按周/月统计数据
  165 + * @name :manage_week_action
  166 + * @author :lyh
  167 + * @method :post
  168 + * @time :2025/8/30 9:36
  169 + */
  170 + public function manage_week_month_action($startOfLast,$endOfLast,$model){
  171 + $manageHrModel = new ManageHr();
  172 + $manageList = $manageHrModel->list(['status'=>1,'dept_id'=>['in',[1,2]]],'id',['id','dept_id','manage_id','name','nickname']);
  173 + $ticketLogModel = new TicketLog();
  174 + foreach ($manageList as $item){
  175 + $timeout_ratio = $average_time = null;
  176 + $this->output('按人员统计:执行的人员名称/id:'.$item['name'].'/'.$item['manage_id']);
  177 + //上一周新增工单总数
  178 + $add_num = $ticketLogModel->counts(['created_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>$item['manage_id'],'is_engineer'=>1,'status'=>['!=',9]]);
  179 + //上一周完成工单(创建+完成都在当周,算一条有效数据)
  180 + $complete_num = $ticketLogModel->counts(['created_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>$item['manage_id'],'status'=>['!=',9],'is_engineer'=>1,'end_at'=>['between',[$startOfLast,$endOfLast]]]);
  181 + //上一周最快完成时长
  182 + $fastest_time = $ticketLogModel->formatQuery(['engineer_id'=>$item['manage_id'],'status'=>['!=',9],'is_engineer'=>1,'end_at'=>['between',[$startOfLast,$endOfLast]]])->min('end_time');
  183 + //上一周完成工单总时长
  184 + $timeCount = $ticketLogModel->formatQuery(['created_at'=>['between',[$startOfLast,$endOfLast]],'end_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>$item['manage_id'],'is_engineer'=>1,'status'=>['!=',9]])->sum('end_time');
  185 + if(!empty($timeCount)){
  186 + $average_time = round($timeCount / $complete_num, 3);
  187 + }
  188 + $data = [
  189 + 'manage_id'=>$item['id'],
  190 + 'manage_name'=>$item['name'],
  191 + 'add_num'=>$add_num,//上一周新增工单数量
  192 + 'average_time'=>$average_time ?? null,//平均完成工单时长
  193 + 'fastest_time'=>$fastest_time ?? null,//最快完成工单时间
  194 + 'complete_num'=>$complete_num,//完成工单数量
  195 + 'dept_id'=>$item['dept_id'],
  196 + 'timeout_ratio'=>$timeout_ratio ?? null,
  197 + 'start_at'=>$startOfLast,
  198 + 'end_at'=>$endOfLast
  199 + ];
  200 + //查询当前用户是否当日已有记录
  201 + $ticketManageInfo = $model->read(['start_at'=>$startOfLast,'end_at'=>$endOfLast,'manage_id'=>$item['id']],['id']);
  202 + if($ticketManageInfo === false){
  203 + //TODO::执行新增
  204 + $model->addReturnId($data);
  205 + }else{
  206 + //TODO::执行编辑
  207 + $model->edit($data,['id'=>$ticketManageInfo['id']]);
  208 + }
  209 + }
  210 + return true;
  211 + }
  212 +
  213 + /**
127 * @remark :按技术组统计数据 214 * @remark :按技术组统计数据
128 * @name :dept_action 215 * @name :dept_action
129 * @author :lyh 216 * @author :lyh
@@ -138,17 +225,29 @@ class TicketCount extends Command @@ -138,17 +225,29 @@ class TicketCount extends Command
138 $ticketDailyDeptModel = new TicketDailyDeptCount(); 225 $ticketDailyDeptModel = new TicketDailyDeptCount();
139 $date = Carbon::yesterday()->toDateString(); // "2025-08-07" 226 $date = Carbon::yesterday()->toDateString(); // "2025-08-07"
140 foreach ($groupList as $item){ 227 foreach ($groupList as $item){
141 - $average_time = null;  
142 - $timeout_ratio = null; 228 + $timeout_ratio = $average_time = null;
143 $this->output('组统计:执行的组/id:'.$item['name'].'/'.$item['id']); 229 $this->output('组统计:执行的组/id:'.$item['name'].'/'.$item['id']);
144 - $manageIdArr = $manageHrModel->selectField(['belong_group'=>$item['id'],'status'=>1,'dept_id'=>1],'manage_id');  
145 - $ticket_num = $ticketLogModel->counts(['engineer_id'=>['in',$manageIdArr],'is_engineer'=>1]);  
146 - $timeCount = $ticketLogModel->formatQuery(['engineer_id'=>['in',$manageIdArr],'is_engineer'=>1])->sum('end_time'); 230 + $manageIdArr = $manageHrModel->selectField(['belong_group'=>$item['id'],'status'=>['!=',9],'status'=>1,'dept_id'=>1],'manage_id');
  231 + $ticket_num = $ticketLogModel->counts(['engineer_id'=>['in',$manageIdArr],'is_engineer'=>1,'status'=>['!=',9]]);
  232 + $timeCount = $ticketLogModel->formatQuery(['engineer_id'=>['in',$manageIdArr],'status'=>['!=',9],'is_engineer'=>1])->sum('end_time');
147 if(!empty($timeCount)){ 233 if(!empty($timeCount)){
148 $average_time = round($timeCount / $ticket_num, 3); 234 $average_time = round($timeCount / $ticket_num, 3);
149 } 235 }
150 //超期工单数量 236 //超期工单数量
151 - $timeout_num = $ticketLogModel->counts(['engineer_id'=>['in',$manageIdArr],'is_engineer'=>1,'plan_end_at'=>['>',date('Y-m-d H:i:s')]]); 237 + $timeout_num = $ticketLogModel
  238 + ->whereIn('engineer_id', $manageIdArr)
  239 + ->where('is_engineer', 1)
  240 + ->where('status','!=',9)//排除掉作废工单
  241 + ->where(function ($query) {
  242 + $query->where(function ($q) {
  243 + $q->whereNotNull('end_at')
  244 + ->whereColumn('plan_end_at', '<', 'end_at');
  245 + })->orWhere(function ($q) {
  246 + $q->whereNull('end_at')
  247 + ->where('plan_end_at', '<', now());
  248 + });
  249 + })
  250 + ->count();
152 if(!empty($timeout_num)){ 251 if(!empty($timeout_num)){
153 $timeout_ratio = round($timeout_num / $ticket_num, 3); 252 $timeout_ratio = round($timeout_num / $ticket_num, 3);
154 } 253 }
@@ -172,6 +271,70 @@ class TicketCount extends Command @@ -172,6 +271,70 @@ class TicketCount extends Command
172 } 271 }
173 272
174 /** 273 /**
  274 + * @remark :技术组按周统计
  275 + * @name :dept_week_month_action
  276 + * @author :lyh
  277 + * @method :post
  278 + * @time :2025/8/30 14:01
  279 + */
  280 + public function dept_week_month_action($startOfLast,$endOfLast,$model){
  281 + $belongingGroupModel = new BelongingGroup();
  282 + $groupList = $belongingGroupModel->list(['id'=>['in',[1,2,3,4,5,6,7,8,9]]],'id',['id','name']);
  283 + $manageHrModel = new ManageHr();
  284 + $ticketLogModel = new TicketLog();
  285 + foreach ($groupList as $item){
  286 + $timeout_ratio = $average_time = null;
  287 + $this->output('组统计:执行的组/id:'.$item['name'].'/'.$item['id']);
  288 + $manageIdArr = $manageHrModel->selectField(['belong_group'=>$item['id'],'status'=>['!=',9],'status'=>1,'dept_id'=>1],'manage_id');
  289 + //本周新增工单
  290 + $add_num = $ticketLogModel->counts(['created_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>['in',$manageIdArr],'is_engineer'=>1,'status'=>['!=',9]]);
  291 + $complete_num = $ticketLogModel->counts(['end_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>['in',$manageIdArr],'is_engineer'=>1,'status'=>['!=',9]]);
  292 + $timeCount = $ticketLogModel->formatQuery(['end_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>['in',$manageIdArr],'status'=>['!=',9],'is_engineer'=>1])->sum('end_time');
  293 + if(!empty($timeCount)){
  294 + $average_time = round($timeCount / $complete_num, 3);
  295 + }
  296 + //超期工单数量
  297 + $timeout_num = $ticketLogModel
  298 + ->whereIn('engineer_id', $manageIdArr)
  299 + ->where('is_engineer', 1)
  300 + ->where('status','!=',9)//排除掉作废工单
  301 + ->where(function ($query) use ($startOfLast,$endOfLast) {
  302 + $query->where(function ($q) use ($startOfLast,$endOfLast) {
  303 + $q->whereBetween('plan_end_at',[$startOfLast,$endOfLast])->whereNotNull('end_at')->whereColumn('plan_end_at', '<', 'end_at');
  304 + })->orWhere(function ($q) {
  305 + $q->whereNull('end_at')->where('plan_end_at', '<', now());
  306 + });
  307 + })
  308 + ->count();
  309 + //预期结束时间在本周的所有工单
  310 + $ticket_num = $ticketLogModel->counts(['plan_end_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>['in',$manageIdArr],'is_engineer'=>1,'status'=>['!=',9]]);
  311 + if(!empty($timeout_num)){
  312 + $timeout_ratio = round($timeout_num / $ticket_num, 3);
  313 + }
  314 + $data = [
  315 + 'dept_id'=>$item['id'],
  316 + 'dept_name'=>$item['name'],
  317 + 'add_num'=>$add_num ?? 0,
  318 + 'complete_num'=>$complete_num ?? 0,
  319 + 'average_time'=>$average_time ?? null,
  320 + 'timeout_ratio'=>$timeout_ratio ?? null,
  321 + 'timeout_num'=>$timeout_num,
  322 + 'start_at'=>$startOfLast,
  323 + 'end_at'=>$endOfLast
  324 + ];
  325 + //查询当前用户是否当日已有记录
  326 + $ticketManageInfo = $model->read(['start_at'=>$startOfLast,'end_at'=>$endOfLast,'dept_id'=>$item['id']],['id']);
  327 + if($ticketManageInfo === false){
  328 + //TODO::执行新增
  329 + $model->addReturnId($data);
  330 + }else{
  331 + //TODO::执行编辑
  332 + $model->edit($data,['id'=>$ticketManageInfo['id']]);
  333 + }
  334 + }
  335 + return true;
  336 + }
  337 + /**
175 * @remark :技术组所有工单记录 338 * @remark :技术组所有工单记录
176 * @name :daily_action 339 * @name :daily_action
177 * @author :lyh 340 * @author :lyh
@@ -180,6 +343,10 @@ class TicketCount extends Command @@ -180,6 +343,10 @@ class TicketCount extends Command
180 */ 343 */
181 public function yesterday_daily_action(){ 344 public function yesterday_daily_action(){
182 $ticketModel = new Tickets(); 345 $ticketModel = new Tickets();
  346 + $ticketLogModel = new TicketLog();
  347 + $ticketLogModel->whereIn('ticket_id', function ($query) {
  348 + $query->select('id')->from('gl_tickets')->where('status', 9);
  349 + })->update(['status' => 9]);
183 $date = Carbon::yesterday()->toDateString(); // "2025-08-07" 350 $date = Carbon::yesterday()->toDateString(); // "2025-08-07"
184 $ticket_num = $ticketModel->counts(['id'=>['!=',0]]); 351 $ticket_num = $ticketModel->counts(['id'=>['!=',0]]);
185 $time_end_num = $ticketModel->counts(['end_at'=>['!=',null]]);//已完成的工单 352 $time_end_num = $ticketModel->counts(['end_at'=>['!=',null]]);//已完成的工单
@@ -194,12 +361,17 @@ class TicketCount extends Command @@ -194,12 +361,17 @@ class TicketCount extends Command
194 $submit_b_side = $ticketModel->formatQuery(['submit_side'=>2])->sum('submit_side'); 361 $submit_b_side = $ticketModel->formatQuery(['submit_side'=>2])->sum('submit_side');
195 $dbResult = DB::table('gl_ticket_projects as p')->leftJoin('gl_tickets as t', 'p.id', '=', 't.project_id') 362 $dbResult = DB::table('gl_ticket_projects as p')->leftJoin('gl_tickets as t', 'p.id', '=', 't.project_id')
196 ->select( 363 ->select(
197 - 'p.project_cate',  
198 - DB::raw('COUNT(t.id) as ticket_count')  
199 - )  
200 - ->groupBy('p.project_cate')  
201 - ->pluck('ticket_count', 'project_cate');  
202 - $timeout_num = $ticketModel->counts(['end_at'=>null,'plan_end_at'=>['>',date('Y-m-d H:i:s')]]); 364 + 'p.project_cate', DB::raw('COUNT(t.id) as ticket_count')
  365 + )->groupBy('p.project_cate')->pluck('ticket_count', 'project_cate');
  366 + $timeout_num = $ticketModel->where('status','!=',9)
  367 + ->where(function ($query) {
  368 + $query->where(function ($q) {
  369 + $q->whereNotNull('end_at')->whereColumn('plan_end_at', '<', 'end_at');
  370 + })->orWhere(function ($q) {
  371 + $q->whereNull('end_at')->where('plan_end_at', '<', now());
  372 + });
  373 + })
  374 + ->count();
203 $timeout_ratio = null; 375 $timeout_ratio = null;
204 if(!empty($timeout_num)){ 376 if(!empty($timeout_num)){
205 $timeout_ratio = round($timeout_num / $ticket_num, 3); 377 $timeout_ratio = round($timeout_num / $ticket_num, 3);
@@ -138,6 +138,7 @@ class ProjectUpdate extends Command @@ -138,6 +138,7 @@ class ProjectUpdate extends Command
138 //设置数据库 138 //设置数据库
139 $project = ProjectServer::useProject($project_id); 139 $project = ProjectServer::useProject($project_id);
140 if ($project) { 140 if ($project) {
  141 + $thumb_w = $project->deploy_build->thumb_w ?? 0;//缩略图压缩宽度
141 if ($api_type == 'category') { 142 if ($api_type == 'category') {
142 //产品分类 143 //产品分类
143 $url = $api_url . '?' . http_build_query(['w' => 'category']); 144 $url = $api_url . '?' . http_build_query(['w' => 'category']);
@@ -332,6 +333,12 @@ class ProjectUpdate extends Command @@ -332,6 +333,12 @@ class ProjectUpdate extends Command
332 $gallery[] = ['alt' => '', 'url' => $this->source_download($img, $project_id, $domain_arr['host'], $web_url_domain, $home_url)]; 333 $gallery[] = ['alt' => '', 'url' => $this->source_download($img, $project_id, $domain_arr['host'], $web_url_domain, $home_url)];
333 } 334 }
334 } 335 }
  336 + //缩略图
  337 + $thumb = $gallery[0] ?? [];
  338 + if (isset($thumb['url']) && $thumb['url']) {
  339 + //生成缩略图
  340 + $thumb['url'] = thumbImageByUrl($thumb['url'], $thumb_w);
  341 + }
335 //关键词 342 //关键词
336 $keyword_id = ''; 343 $keyword_id = '';
337 if ($item['tags'] ?? []) { 344 if ($item['tags'] ?? []) {
@@ -371,7 +378,7 @@ class ProjectUpdate extends Command @@ -371,7 +378,7 @@ class ProjectUpdate extends Command
371 'content' => $content, 378 'content' => $content,
372 'category_id' => $category_id, 379 'category_id' => $category_id,
373 'keyword_id' => $keyword_id, 380 'keyword_id' => $keyword_id,
374 - 'thumb' => isset($gallery[0]) ? Arr::a2s($gallery[0]) : '', 381 + 'thumb' => Arr::a2s($thumb),
375 'gallery' => Arr::a2s($gallery), 382 'gallery' => Arr::a2s($gallery),
376 'attrs' => Arr::a2s($attrs), 383 'attrs' => Arr::a2s($attrs),
377 'seo_mate' => Arr::a2s([ 384 'seo_mate' => Arr::a2s([
@@ -417,7 +424,7 @@ class ProjectUpdate extends Command @@ -417,7 +424,7 @@ class ProjectUpdate extends Command
417 'content' => $content, 424 'content' => $content,
418 'category_id' => $category_id, 425 'category_id' => $category_id,
419 'keyword_id' => $keyword_id, 426 'keyword_id' => $keyword_id,
420 - 'thumb' => isset($gallery[0]) ? Arr::a2s($gallery[0]) : '', 427 + 'thumb' => Arr::a2s($thumb),
421 'gallery' => Arr::a2s($gallery), 428 'gallery' => Arr::a2s($gallery),
422 'attrs' => Arr::a2s($attrs), 429 'attrs' => Arr::a2s($attrs),
423 'seo_mate' => Arr::a2s([ 430 'seo_mate' => Arr::a2s([
@@ -77,6 +77,9 @@ class UpdateKeyword extends Command @@ -77,6 +77,9 @@ class UpdateKeyword extends Command
77 if($updateObject['type'] == 0){//更新所有关键字 77 if($updateObject['type'] == 0){//更新所有关键字
78 //获取所有关键字的id 78 //获取所有关键字的id
79 $idArr = $keywordModel->selectField(['id'=>['>',0]],'id'); 79 $idArr = $keywordModel->selectField(['id'=>['>',0]],'id');
  80 + if(empty($idArr)){
  81 + return true;
  82 + }
80 if($info['update_method'] != 1){ 83 if($info['update_method'] != 1){
81 $idArr = shuffle($idArr); 84 $idArr = shuffle($idArr);
82 } 85 }
@@ -60,7 +60,29 @@ class FetchTicketProjects extends Command @@ -60,7 +60,29 @@ class FetchTicketProjects extends Command
60 $postids = []; 60 $postids = [];
61 61
62 while (true) { 62 while (true) {
63 - $response = Http::get('https://www.quanqiusou.cn/extend_api/webs/globalso_all.php?page=' . $page); 63 + try {
  64 + $maxRetries = 3;
  65 + $retryCount = 0;
  66 +
  67 + while ($retryCount < $maxRetries) {
  68 + try {
  69 + $response = Http::get('https://www.quanqiusou.cn/extend_api/webs/globalso_all.php?page=' . $page);
  70 + break; // 如果请求成功,跳出重试循环
  71 + } catch (\Exception $e) {
  72 + $retryCount++;
  73 + if ($retryCount >= $maxRetries) {
  74 + // 如果达到最大重试次数,抛出异常
  75 + throw $e;
  76 + }
  77 + // 等待一段时间再重试
  78 + sleep(2);
  79 + }
  80 + }
  81 + }catch (\Exception $e){
  82 + echo now() . " | ERROR | " . $e->getMessage() . "\n" . $e->getTraceAsString() . "\n";
  83 + break;
  84 + }
  85 +
64 if ($response->status() == 200) { 86 if ($response->status() == 200) {
65 $resp_json = $response->json(); 87 $resp_json = $response->json();
66 $items = $resp_json['data'] ?? []; 88 $items = $resp_json['data'] ?? [];
@@ -13,6 +13,7 @@ use GuzzleHttp\Client; @@ -13,6 +13,7 @@ use GuzzleHttp\Client;
13 use GuzzleHttp\Exception\GuzzleException; 13 use GuzzleHttp\Exception\GuzzleException;
14 use Illuminate\Support\Carbon; 14 use Illuminate\Support\Carbon;
15 use Illuminate\Support\Facades\Cache; 15 use Illuminate\Support\Facades\Cache;
  16 +use Illuminate\Support\Facades\Log;
16 use Illuminate\Support\Facades\Redis; 17 use Illuminate\Support\Facades\Redis;
17 18
18 define('HTTP_OPENAI_URL', 'http://openai.waimaoq.com/'); 19 define('HTTP_OPENAI_URL', 'http://openai.waimaoq.com/');
@@ -28,7 +29,7 @@ define('HTTP_OPENAI_URL', 'http://openai.waimaoq.com/'); @@ -28,7 +29,7 @@ define('HTTP_OPENAI_URL', 'http://openai.waimaoq.com/');
28 if (!function_exists('generateRoute')) { 29 if (!function_exists('generateRoute')) {
29 function generateRoute($string) 30 function generateRoute($string)
30 { 31 {
31 - if(is_array($string)){ 32 + if (is_array($string)) {
32 $string = $string[0]; 33 $string = $string[0];
33 } 34 }
34 $sign = str_replace(".", "", trim(strtolower(preg_replace('/[^\w.]+/', '-', trim($string))), '-')); 35 $sign = str_replace(".", "", trim(strtolower(preg_replace('/[^\w.]+/', '-', trim($string))), '-'));
@@ -61,7 +62,7 @@ if (!function_exists('http_post')) { @@ -61,7 +62,7 @@ if (!function_exists('http_post')) {
61 * @param type $url 62 * @param type $url
62 * @param type $post_data 63 * @param type $post_data
63 */ 64 */
64 - function http_post($url, $post_data, $header = [],$is_json = true,$timeout = 60) 65 + function http_post($url, $post_data, $header = [], $is_json = true, $timeout = 60)
65 { 66 {
66 if (empty($header)) { 67 if (empty($header)) {
67 $header = array( 68 $header = array(
@@ -87,7 +88,7 @@ if (!function_exists('http_post')) { @@ -87,7 +88,7 @@ if (!function_exists('http_post')) {
87 @file_put_contents(storage_path('logs/lyh_error.log'), var_export($error_message, true) . PHP_EOL, FILE_APPEND); 88 @file_put_contents(storage_path('logs/lyh_error.log'), var_export($error_message, true) . PHP_EOL, FILE_APPEND);
88 } 89 }
89 curl_close($ch); 90 curl_close($ch);
90 - if($is_json){ 91 + if ($is_json) {
91 return json_decode($res, true); 92 return json_decode($res, true);
92 } 93 }
93 return trim($res); 94 return trim($res);
@@ -106,7 +107,7 @@ if (!function_exists('http_get')) { @@ -106,7 +107,7 @@ if (!function_exists('http_get')) {
106 if (empty($header)) { 107 if (empty($header)) {
107 $header[] = "content-type: application/json"; 108 $header[] = "content-type: application/json";
108 } 109 }
109 - $ch1 = curl_init(); 110 + $ch1 = curl_init();
110 $timeout = 0; 111 $timeout = 0;
111 curl_setopt($ch1, CURLOPT_URL, $url); 112 curl_setopt($ch1, CURLOPT_URL, $url);
112 curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true); 113 curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
@@ -130,7 +131,7 @@ if (!function_exists('http_get')) { @@ -130,7 +131,7 @@ if (!function_exists('http_get')) {
130 131
131 132
132 if (!function_exists('curl_get')) { 133 if (!function_exists('curl_get')) {
133 - function curl_get($url,$is_array=true) 134 + function curl_get($url, $is_array = true)
134 { 135 {
135 $header = array( 136 $header = array(
136 'Expect:', 137 'Expect:',
@@ -161,7 +162,8 @@ if (!function_exists('curl_get')) { @@ -161,7 +162,8 @@ if (!function_exists('curl_get')) {
161 * @method :post 162 * @method :post
162 * @time :2024/6/5 10:38 163 * @time :2024/6/5 10:38
163 */ 164 */
164 -function contains_russian($text) { 165 +function contains_russian($text)
  166 +{
165 // 使用正则表达式检查是否包含俄语字符 167 // 使用正则表达式检查是否包含俄语字符
166 return preg_match('/[\x{0400}-\x{04FF}]/u', $text) > 0; 168 return preg_match('/[\x{0400}-\x{04FF}]/u', $text) > 0;
167 169
@@ -176,7 +178,8 @@ if (!function_exists('curl_c')) { @@ -176,7 +178,8 @@ if (!function_exists('curl_c')) {
176 * @author Akun 178 * @author Akun
177 * @date 2023/11/22 11:33 179 * @date 2023/11/22 11:33
178 */ 180 */
179 - function curl_c($url,$is_array=true,$replace=[]){ 181 + function curl_c($url, $is_array = true, $replace = [])
  182 + {
180 $header = array( 183 $header = array(
181 'Expect:', 184 'Expect:',
182 'Content-Type: application/json; charset=utf-8' 185 'Content-Type: application/json; charset=utf-8'
@@ -195,16 +198,16 @@ if (!function_exists('curl_c')) { @@ -195,16 +198,16 @@ if (!function_exists('curl_c')) {
195 curl_setopt($ch, CURLOPT_SSLVERSION, 'all'); 198 curl_setopt($ch, CURLOPT_SSLVERSION, 'all');
196 curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 199 curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
197 $content = curl_exec($ch); 200 $content = curl_exec($ch);
198 - $http_code = curl_getinfo($ch,CURLINFO_HTTP_CODE); 201 + $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
199 curl_close($ch); 202 curl_close($ch);
200 - if($http_code == 200){  
201 - if(!empty($replace)){  
202 - foreach ($replace as $k=>$v){  
203 - $content = str_replace($k,$v,$content); 203 + if ($http_code == 200) {
  204 + if (!empty($replace)) {
  205 + foreach ($replace as $k => $v) {
  206 + $content = str_replace($k, $v, $content);
204 } 207 }
205 } 208 }
206 return $is_array ? json_decode($content, true) : $content; 209 return $is_array ? json_decode($content, true) : $content;
207 - }else{ 210 + } else {
208 return false; 211 return false;
209 } 212 }
210 } 213 }
@@ -218,7 +221,8 @@ if (!function_exists('curl_code')) { @@ -218,7 +221,8 @@ if (!function_exists('curl_code')) {
218 * @author Akun 221 * @author Akun
219 * @date 2023/11/22 11:33 222 * @date 2023/11/22 11:33
220 */ 223 */
221 - function curl_code($url,$is_array=true){ 224 + function curl_code($url, $is_array = true)
  225 + {
222 $header = array( 226 $header = array(
223 'Expect:', 227 'Expect:',
224 'Content-Type: application/json; charset=utf-8' 228 'Content-Type: application/json; charset=utf-8'
@@ -237,11 +241,11 @@ if (!function_exists('curl_code')) { @@ -237,11 +241,11 @@ if (!function_exists('curl_code')) {
237 curl_setopt($ch, CURLOPT_SSLVERSION, 'all'); 241 curl_setopt($ch, CURLOPT_SSLVERSION, 'all');
238 curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 242 curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
239 $content = curl_exec($ch); 243 $content = curl_exec($ch);
240 - $http_code = curl_getinfo($ch,CURLINFO_HTTP_CODE); 244 + $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
241 curl_close($ch); 245 curl_close($ch);
242 - if($http_code == 200){ 246 + if ($http_code == 200) {
243 return $is_array ? json_decode($content, true) : $content; 247 return $is_array ? json_decode($content, true) : $content;
244 - }else{ 248 + } else {
245 return $http_code; 249 return $http_code;
246 } 250 }
247 } 251 }
@@ -260,7 +264,7 @@ if (!function_exists('_get_child')) { @@ -260,7 +264,7 @@ if (!function_exists('_get_child')) {
260 foreach ($arr as $v) { 264 foreach ($arr as $v) {
261 $v = (array)$v; 265 $v = (array)$v;
262 if ($v['pid'] == $my_id) { 266 if ($v['pid'] == $my_id) {
263 - $v['sub'] = _get_child($v['id'], $arr); 267 + $v['sub'] = _get_child($v['id'], $arr);
264 $new_arr[] = $v; 268 $new_arr[] = $v;
265 } 269 }
266 } 270 }
@@ -274,7 +278,7 @@ if (!function_exists('_get_all_sub')) { @@ -274,7 +278,7 @@ if (!function_exists('_get_all_sub')) {
274 * @param int 278 * @param int
275 * @return array 279 * @return array
276 */ 280 */
277 - function _get_all_sub($my_id,$id_Arr) 281 + function _get_all_sub($my_id, $id_Arr)
278 { 282 {
279 $new_arr[] = $my_id; 283 $new_arr[] = $my_id;
280 foreach ($id_Arr as $v) { 284 foreach ($id_Arr as $v) {
@@ -302,7 +306,7 @@ if (!function_exists('checkDomain')) { @@ -302,7 +306,7 @@ if (!function_exists('checkDomain')) {
302 if (empty($urlParts['host'])) { 306 if (empty($urlParts['host'])) {
303 $urlParts = parse_url('https://' . $value); 307 $urlParts = parse_url('https://' . $value);
304 } 308 }
305 - $host = $urlParts['host'] ?? ''; 309 + $host = $urlParts['host'] ?? '';
306 $scheme = $urlParts['scheme'] ?? 'https'; 310 $scheme = $urlParts['scheme'] ?? 'https';
307 if (!in_array($scheme, ['http', 'https'])) { 311 if (!in_array($scheme, ['http', 'https'])) {
308 return false; 312 return false;
@@ -380,7 +384,7 @@ function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root @@ -380,7 +384,7 @@ function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root
380 // 如果是数字,则是root 384 // 如果是数字,则是root
381 if (is_numeric($pk)) { 385 if (is_numeric($pk)) {
382 $root = $pk; 386 $root = $pk;
383 - $pk = 'id'; 387 + $pk = 'id';
384 } 388 }
385 // 创建Tree 389 // 创建Tree
386 $tree = array(); 390 $tree = array();
@@ -505,7 +509,7 @@ if (!function_exists('getPreviousDaysDate')) { @@ -505,7 +509,7 @@ if (!function_exists('getPreviousDaysDate')) {
505 $days = []; 509 $days = [];
506 while ($day > 0) { 510 while ($day > 0) {
507 $days[] = date("Y-m-d", strtotime("-{$day} days")); 511 $days[] = date("Y-m-d", strtotime("-{$day} days"));
508 - $day -= 1; 512 + $day -= 1;
509 } 513 }
510 return $days; 514 return $days;
511 } 515 }
@@ -522,7 +526,7 @@ if (!function_exists('getPreviousMonthsDate')) { @@ -522,7 +526,7 @@ if (!function_exists('getPreviousMonthsDate')) {
522 $months = []; 526 $months = [];
523 while ($month > 0) { 527 while ($month > 0) {
524 $months[] = date("Y-m", strtotime("-{$month} months")); 528 $months[] = date("Y-m", strtotime("-{$month} months"));
525 - $month -= 1; 529 + $month -= 1;
526 } 530 }
527 return $months; 531 return $months;
528 } 532 }
@@ -536,17 +540,17 @@ if (!function_exists('getInquiryInformation')) { @@ -536,17 +540,17 @@ if (!function_exists('getInquiryInformation')) {
536 */ 540 */
537 function getInquiryInformation($domain, $sta_date) 541 function getInquiryInformation($domain, $sta_date)
538 { 542 {
539 - $token = md5($domain . date("Y-m-d")); 543 + $token = md5($domain . date("Y-m-d"));
540 $source = '1,3'; 544 $source = '1,3';
541 - $url = "https://www.globalso.site/api/external-interface/country_con/15243d63ed5a5738?domain={$domain}&token={$token}&source={$source}&sta_date={$sta_date}"; 545 + $url = "https://www.globalso.site/api/external-interface/country_con/15243d63ed5a5738?domain={$domain}&token={$token}&source={$source}&sta_date={$sta_date}";
542 $client = new Client(['verify' => false]); 546 $client = new Client(['verify' => false]);
543 - $http = $client->get($url);  
544 - $data = []; 547 + $http = $client->get($url);
  548 + $data = [];
545 if ($http->getStatusCode() != 200) { 549 if ($http->getStatusCode() != 200) {
546 return $data; 550 return $data;
547 } 551 }
548 $content = $http->getBody()->getContents(); 552 $content = $http->getBody()->getContents();
549 - $json = json_decode($content, true); 553 + $json = json_decode($content, true);
550 if ($json['status'] != 200) { 554 if ($json['status'] != 200) {
551 return $content; 555 return $content;
552 } 556 }
@@ -597,7 +601,7 @@ if (!function_exists('checkIsMonth')) { @@ -597,7 +601,7 @@ if (!function_exists('checkIsMonth')) {
597 $now = time(); 601 $now = time();
598 // 获取当月的起始时间戳和结束时间戳 602 // 获取当月的起始时间戳和结束时间戳
599 $firstDay = strtotime(date('Y-m-01', $now)); 603 $firstDay = strtotime(date('Y-m-01', $now));
600 - $lastDay = strtotime(date('Y-m-t', $now)); 604 + $lastDay = strtotime(date('Y-m-t', $now));
601 // 传入日期的时间戳 605 // 传入日期的时间戳
602 $timestamp = strtotime($date); 606 $timestamp = strtotime($date);
603 // 判断传入日期是否在当月范围内 607 // 判断传入日期是否在当月范围内
@@ -621,8 +625,8 @@ if (!function_exists('getDateDays')) { @@ -621,8 +625,8 @@ if (!function_exists('getDateDays')) {
621 if (!is_null($date)) { 625 if (!is_null($date)) {
622 $dd = explode('-', $date); 626 $dd = explode('-', $date);
623 if (!checkIsGreaterMonth($date) && !checkIsMonth($date)) { 627 if (!checkIsGreaterMonth($date) && !checkIsMonth($date)) {
624 - $year = $dd[0];  
625 - $month = $dd[1]; 628 + $year = $dd[0];
  629 + $month = $dd[1];
626 $first_day_of_month = "{$year}-{$month}-01"; 630 $first_day_of_month = "{$year}-{$month}-01";
627 return getDateArray("{$year}-{$month}-" . date("t", strtotime($first_day_of_month))); 631 return getDateArray("{$year}-{$month}-" . date("t", strtotime($first_day_of_month)));
628 } 632 }
@@ -641,7 +645,7 @@ if (!function_exists('getDateArray')) { @@ -641,7 +645,7 @@ if (!function_exists('getDateArray')) {
641 function getDateArray(string $date) 645 function getDateArray(string $date)
642 { 646 {
643 list($year, $month, $day) = explode('-', date($date)); 647 list($year, $month, $day) = explode('-', date($date));
644 - $i = 1; 648 + $i = 1;
645 $days = []; 649 $days = [];
646 while ($i <= $day) { 650 while ($i <= $day) {
647 $days[] = "{$year}-{$month}-" . str_pad($i, 2, "0", STR_PAD_LEFT); 651 $days[] = "{$year}-{$month}-" . str_pad($i, 2, "0", STR_PAD_LEFT);
@@ -659,34 +663,35 @@ if (!function_exists('getImageUrl')) { @@ -659,34 +663,35 @@ if (!function_exists('getImageUrl')) {
659 * @method :post 663 * @method :post
660 * @time :2023/7/20 16:46 664 * @time :2023/7/20 16:46
661 */ 665 */
662 - function getImageUrl($path,$storage_type = 0,$location = 0,$image_cdn = 1){  
663 - if(is_array($path)){  
664 - $url =[];  
665 - foreach ($path as $v){  
666 - $url[] = getImageUrl($v,$storage_type,$location); 666 + function getImageUrl($path, $storage_type = 0, $location = 0, $image_cdn = 1)
  667 + {
  668 + if (is_array($path)) {
  669 + $url = [];
  670 + foreach ($path as $v) {
  671 + $url[] = getImageUrl($v, $storage_type, $location);
667 } 672 }
668 - }else{  
669 - if(empty($path)){ 673 + } else {
  674 + if (empty($path)) {
670 return ''; 675 return '';
671 } 676 }
672 - if((strpos($path,'https://')!== false) || (strpos($path,'http://') !== false)){  
673 - return $path; 677 + if ((strpos($path, 'https://') !== false) || (strpos($path, 'http://') !== false)) {
  678 + return $path;
674 } 679 }
675 - if(substr($path,0,2) == '//'){  
676 - return 'https:'.$path; 680 + if (substr($path, 0, 2) == '//') {
  681 + return 'https:' . $path;
677 } 682 }
678 - if($location == 0){ 683 + if ($location == 0) {
679 $cos = config('filesystems.disks.cos'); 684 $cos = config('filesystems.disks.cos');
680 - if($image_cdn == 0){//v6链接 685 + if ($image_cdn == 0) {//v6链接
681 $cosCdn = $cos['cdn2']; 686 $cosCdn = $cos['cdn2'];
682 - }else{ 687 + } else {
683 $cosCdn = ($storage_type == 0) ? $cos['cdn'] : $cos['cdn1']; 688 $cosCdn = ($storage_type == 0) ? $cos['cdn'] : $cos['cdn1'];
684 } 689 }
685 - $url = $cosCdn.$path;  
686 - }else{ 690 + $url = $cosCdn . $path;
  691 + } else {
687 $s3 = config('filesystems.disks.s3'); 692 $s3 = config('filesystems.disks.s3');
688 $cdn = $s3['cdn']; 693 $cdn = $s3['cdn'];
689 - $url = $cdn.$path; 694 + $url = $cdn . $path;
690 } 695 }
691 } 696 }
692 return $url; 697 return $url;
@@ -701,36 +706,37 @@ if (!function_exists('getFileUrl')) { @@ -701,36 +706,37 @@ if (!function_exists('getFileUrl')) {
701 * @method :post 706 * @method :post
702 * @time :2023/7/20 16:46 707 * @time :2023/7/20 16:46
703 */ 708 */
704 - function getFileUrl($path,$storage_type = 0,$location = 0,$file_cdn = 0){  
705 - if(is_array($path)){  
706 - $url =[];  
707 - foreach ($path as $v){  
708 - $url[] = getFileUrl($v,$storage_type,$location,$file_cdn); 709 + function getFileUrl($path, $storage_type = 0, $location = 0, $file_cdn = 0)
  710 + {
  711 + if (is_array($path)) {
  712 + $url = [];
  713 + foreach ($path as $v) {
  714 + $url[] = getFileUrl($v, $storage_type, $location, $file_cdn);
709 } 715 }
710 - }else{  
711 - if(empty($path)){ 716 + } else {
  717 + if (empty($path)) {
712 return ''; 718 return '';
713 } 719 }
714 - if((strpos($path,'https://')!== false) || (strpos($path,'http://') !== false)){  
715 - return $path; 720 + if ((strpos($path, 'https://') !== false) || (strpos($path, 'http://') !== false)) {
  721 + return $path;
716 } 722 }
717 - if(substr($path,0,2) == '//'){  
718 - return 'https:'.$path; 723 + if (substr($path, 0, 2) == '//') {
  724 + return 'https:' . $path;
719 } 725 }
720 $file_type = pathinfo($path, PATHINFO_EXTENSION); 726 $file_type = pathinfo($path, PATHINFO_EXTENSION);
721 $fileTypeArr = ['zip', 'pdf', 'mp4', 'doc', 'docx', 'm4v', 'xlsx']; 727 $fileTypeArr = ['zip', 'pdf', 'mp4', 'doc', 'docx', 'm4v', 'xlsx'];
722 - if(in_array(strtolower($file_type),$fileTypeArr) && ($file_cdn == 0)){ 728 + if (in_array(strtolower($file_type), $fileTypeArr) && ($file_cdn == 0)) {
723 $cdn2 = config('filesystems.disks.cos')['cdn2']; 729 $cdn2 = config('filesystems.disks.cos')['cdn2'];
724 - return $cdn2.$path; 730 + return $cdn2 . $path;
725 } 731 }
726 - if($location == 0){ 732 + if ($location == 0) {
727 $cos = config('filesystems.disks.cos'); 733 $cos = config('filesystems.disks.cos');
728 $cosCdn = ($storage_type == 0) ? $cos['cdn'] : $cos['cdn1']; 734 $cosCdn = ($storage_type == 0) ? $cos['cdn'] : $cos['cdn1'];
729 - return $cosCdn.$path;  
730 - }else{ 735 + return $cosCdn . $path;
  736 + } else {
731 $s3 = config('filesystems.disks.s3'); 737 $s3 = config('filesystems.disks.s3');
732 $cdn = $s3['cdn']; 738 $cdn = $s3['cdn'];
733 - return $cdn.$path; 739 + return $cdn . $path;
734 } 740 }
735 } 741 }
736 return $url; 742 return $url;
@@ -744,7 +750,8 @@ if (!function_exists('getFileUrl')) { @@ -744,7 +750,8 @@ if (!function_exists('getFileUrl')) {
744 * @method :post 750 * @method :post
745 * @time :2023/6/28 17:39 751 * @time :2023/6/28 17:39
746 */ 752 */
747 -function characterTruncation($string,$pattern){ 753 +function characterTruncation($string, $pattern)
  754 +{
748 preg_match($pattern, $string, $matches); 755 preg_match($pattern, $string, $matches);
749 if (isset($matches[0])) { 756 if (isset($matches[0])) {
750 $result = $matches[0]; 757 $result = $matches[0];
@@ -761,7 +768,8 @@ function characterTruncation($string,$pattern){ @@ -761,7 +768,8 @@ function characterTruncation($string,$pattern){
761 * @method :post 768 * @method :post
762 * @time :2024/5/14 16:24 769 * @time :2024/5/14 16:24
763 */ 770 */
764 -function characterTruncationStr($string,$startStr,$endStr){ 771 +function characterTruncationStr($string, $startStr, $endStr)
  772 +{
765 $start = strpos($string, $startStr); 773 $start = strpos($string, $startStr);
766 $end = strpos($string, $endStr) + strlen($endStr); 774 $end = strpos($string, $endStr) + strlen($endStr);
767 return substr($string, $start, $end - $start); 775 return substr($string, $start, $end - $start);
@@ -798,7 +806,7 @@ if (!function_exists('str_replace_url')) { @@ -798,7 +806,7 @@ if (!function_exists('str_replace_url')) {
798 $cosCdn1 = $cos['cdn1']; 806 $cosCdn1 = $cos['cdn1'];
799 $cosCdn2 = $cos['cdn2']; 807 $cosCdn2 = $cos['cdn2'];
800 $cosCdn3 = config('filesystems.disks.s3')['cdn']; 808 $cosCdn3 = config('filesystems.disks.s3')['cdn'];
801 - if($url && ((strpos($url,$cosCdn) !== false) || (strpos($url,$cosCdn1) !== false) || (strpos($url,$cosCdn2) !== false) || (strpos($url,$cosCdn3) !== false))){ 809 + if ($url && ((strpos($url, $cosCdn) !== false) || (strpos($url, $cosCdn1) !== false) || (strpos($url, $cosCdn2) !== false) || (strpos($url, $cosCdn3) !== false))) {
802 // 外部URL无需解析 810 // 外部URL无需解析
803 // 使用 parse_url 函数来解析 URL 811 // 使用 parse_url 函数来解析 URL
804 $urlParts = parse_url($url); 812 $urlParts = parse_url($url);
@@ -812,7 +820,7 @@ if (!function_exists('str_replace_url')) { @@ -812,7 +820,7 @@ if (!function_exists('str_replace_url')) {
812 } 820 }
813 } 821 }
814 822
815 -if(!function_exists('curlGet')){ 823 +if (!function_exists('curlGet')) {
816 /** 824 /**
817 * @remark :忽略证书curl请求 825 * @remark :忽略证书curl请求
818 * @name :curlGet 826 * @name :curlGet
@@ -820,8 +828,9 @@ if(!function_exists('curlGet')){ @@ -820,8 +828,9 @@ if(!function_exists('curlGet')){
820 * @method :post 828 * @method :post
821 * @time :2023/9/12 10:10 829 * @time :2023/9/12 10:10
822 */ 830 */
823 - function curlGet($url){  
824 - $ch1 = curl_init(); 831 + function curlGet($url)
  832 + {
  833 + $ch1 = curl_init();
825 $timeout = 60; 834 $timeout = 60;
826 curl_setopt($ch1, CURLOPT_URL, $url); 835 curl_setopt($ch1, CURLOPT_URL, $url);
827 curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true); 836 curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
@@ -852,15 +861,15 @@ function ends_with($string, $suffix) @@ -852,15 +861,15 @@ function ends_with($string, $suffix)
852 * @method :post 861 * @method :post
853 * @time :2025/6/21 9:57 862 * @time :2025/6/21 9:57
854 */ 863 */
855 -function getCustomRouteMap($module_route,$route = '',$is_upgrade = 0) 864 +function getCustomRouteMap($module_route, $route = '', $is_upgrade = 0)
856 { 865 {
857 - if($is_upgrade == 0){ 866 + if ($is_upgrade == 0) {
858 return $route; 867 return $route;
859 } 868 }
860 - if($module_route == $route){ 869 + if ($module_route == $route) {
861 $resultRoute = $route; 870 $resultRoute = $route;
862 - }else{  
863 - $resultRoute = $module_route.'_catalog/'.$route; 871 + } else {
  872 + $resultRoute = $module_route . '_catalog/' . $route;
864 } 873 }
865 return $resultRoute; 874 return $resultRoute;
866 } 875 }
@@ -872,48 +881,53 @@ function getCustomRouteMap($module_route,$route = '',$is_upgrade = 0) @@ -872,48 +881,53 @@ function getCustomRouteMap($module_route,$route = '',$is_upgrade = 0)
872 * @method :post 881 * @method :post
873 * @time :2023/11/10 14:29 882 * @time :2023/11/10 14:29
874 */ 883 */
875 -function getRouteMap($source,$source_id,$is_upgrade = 0, $returnModel = false){ 884 +function getRouteMap($source, $source_id, $is_upgrade = 0, $returnModel = false)
  885 +{
876 $route = ''; 886 $route = '';
877 $routeMapModel = new RouteMap(); 887 $routeMapModel = new RouteMap();
878 - $info = $routeMapModel->read(['source'=>$source,'source_id'=>$source_id]);  
879 - if($info !== false){  
880 - if($is_upgrade == 1){  
881 - if($source == $routeMapModel::SOURCE_NEWS_CATE){  
882 - if($info['route'] != 'news'){  
883 - return $routeMapModel::PATH_NEWS_CATE.'/'.$info['route']; 888 + $info = $routeMapModel->read(['source' => $source, 'source_id' => $source_id]);
  889 + if ($info !== false) {
  890 + if ($is_upgrade == 1) {
  891 + if ($source == $routeMapModel::SOURCE_NEWS_CATE) {
  892 + if ($info['route'] != 'news') {
  893 + return $routeMapModel::PATH_NEWS_CATE . '/' . $info['route'];
884 } 894 }
885 - }elseif ($source == $routeMapModel::SOURCE_BLOG_CATE){  
886 - if($info['route'] != 'blog'){  
887 - return $routeMapModel::PATH_BLOG_CATE.'/'.$info['route']; 895 + } elseif ($source == $routeMapModel::SOURCE_BLOG_CATE) {
  896 + if ($info['route'] != 'blog') {
  897 + return $routeMapModel::PATH_BLOG_CATE . '/' . $info['route'];
888 } 898 }
889 } 899 }
890 $route = $info['route']; 900 $route = $info['route'];
891 return $route; 901 return $route;
892 } 902 }
893 - if(!empty($info['path'])){  
894 - if($info['path'] == 'blog'){  
895 - $info['path'] = $info['path'].'s'; 903 + if (!empty($info['path'])) {
  904 + if ($info['path'] == 'blog') {
  905 + $info['path'] = $info['path'] . 's';
896 } 906 }
897 - $route = $info['path'].'/'.$info['route'];  
898 - }else{ 907 + $route = $info['path'] . '/' . $info['route'];
  908 + } else {
899 $route = $info['route']; 909 $route = $info['route'];
900 } 910 }
901 } 911 }
902 - if($returnModel && ($info !== false)){ 912 + if ($returnModel && ($info !== false)) {
903 return $info; 913 return $info;
904 } 914 }
905 return $route; 915 return $route;
906 } 916 }
907 917
908 -function redis_get($key){ 918 +function redis_get($key)
  919 +{
909 return Redis::connection()->client()->get($key); 920 return Redis::connection()->client()->get($key);
910 } 921 }
911 -function redis_del(...$key){ 922 +
  923 +function redis_del(...$key)
  924 +{
912 return Redis::connection()->client()->del(...$key); 925 return Redis::connection()->client()->del(...$key);
913 } 926 }
914 927
915 -function redis_set($key,$val,$ttl=3600){  
916 - return Redis::connection()->client()->set($key,$val,$ttl); 928 +function redis_set($key, $val, $ttl = 3600)
  929 +{
  930 + return Redis::connection()->client()->set($key, $val, $ttl);
917 } 931 }
918 932
919 /** 933 /**
@@ -925,7 +939,8 @@ function redis_set($key,$val,$ttl=3600){ @@ -925,7 +939,8 @@ function redis_set($key,$val,$ttl=3600){
925 * @author:dc 939 * @author:dc
926 * @time 2023/10/25 9:48 940 * @time 2023/10/25 9:48
927 */ 941 */
928 -function redis_add($key,$val,$ttl=3600){ 942 +function redis_add($key, $val, $ttl = 3600)
  943 +{
929 return Redis::connection()->client()->eval( 944 return Redis::connection()->client()->eval(
930 "return redis.call('exists',KEYS[1])<1 and redis.call('setex',KEYS[1],ARGV[2],ARGV[1])", [$key, $val, $ttl], 1 945 "return redis.call('exists',KEYS[1])<1 and redis.call('setex',KEYS[1],ARGV[2],ARGV[1])", [$key, $val, $ttl], 1
931 ); 946 );
@@ -937,11 +952,12 @@ function redis_add($key,$val,$ttl=3600){ @@ -937,11 +952,12 @@ function redis_add($key,$val,$ttl=3600){
937 * @param $project_id 952 * @param $project_id
938 * @param $domain 953 * @param $domain
939 * @param $is_complete 954 * @param $is_complete
940 - * @author Akun  
941 * @return bool 955 * @return bool
942 * @date 2023/12/08 14:17 956 * @date 2023/12/08 14:17
  957 + * @author Akun
943 */ 958 */
944 -function check_remote_url_down($url,$project_id,$domain,$is_complete=0){ 959 +function check_remote_url_down($url, $project_id, $domain, $is_complete = 0)
  960 +{
945 961
946 if (!$url) { 962 if (!$url) {
947 return ''; 963 return '';
@@ -950,24 +966,24 @@ function check_remote_url_down($url,$project_id,$domain,$is_complete=0){ @@ -950,24 +966,24 @@ function check_remote_url_down($url,$project_id,$domain,$is_complete=0){
950 $arr = parse_url($url); 966 $arr = parse_url($url);
951 $scheme = $arr['scheme'] ?? ''; 967 $scheme = $arr['scheme'] ?? '';
952 $host = $arr['host'] ?? ''; 968 $host = $arr['host'] ?? '';
953 - $host_arr = explode('.',$host); 969 + $host_arr = explode('.', $host);
954 $path = $arr['path'] ?? ''; 970 $path = $arr['path'] ?? '';
955 971
956 - if(strpos($host_arr[0], 'cdn') !== false){ 972 + if (strpos($host_arr[0], 'cdn') !== false) {
957 return $url; 973 return $url;
958 } 974 }
959 975
960 - if($host_arr[0] == 'file' && $host_arr[1] == 'globalso'){ 976 + if ($host_arr[0] == 'file' && $host_arr[1] == 'globalso') {
961 return $url; 977 return $url;
962 } 978 }
963 979
964 //475项目特殊处理 980 //475项目特殊处理
965 - if($project_id == 475 && $host == 'www.ebuyplc.com'){ 981 + if ($project_id == 475 && $host == 'www.ebuyplc.com') {
966 $host = 'g934.goodao.net'; 982 $host = 'g934.goodao.net';
967 } 983 }
968 984
969 - if($path && substr($path,0,1) != '/'){  
970 - $path = '/'.$path; 985 + if ($path && substr($path, 0, 1) != '/') {
  986 + $path = '/' . $path;
971 } 987 }
972 988
973 if ( 989 if (
@@ -978,13 +994,13 @@ function check_remote_url_down($url,$project_id,$domain,$is_complete=0){ @@ -978,13 +994,13 @@ function check_remote_url_down($url,$project_id,$domain,$is_complete=0){
978 ) { 994 ) {
979 $url_complete = ($scheme ?: 'https') . '://' . ($host ?: $domain) . $path; 995 $url_complete = ($scheme ?: 'https') . '://' . ($host ?: $domain) . $path;
980 996
981 - $new_url = CosService::uploadRemote($project_id,'image_product',$url_complete);  
982 - if($new_url){ 997 + $new_url = CosService::uploadRemote($project_id, 'image_product', $url_complete);
  998 + if ($new_url) {
983 return $is_complete ? getImageUrl($new_url) : $new_url; 999 return $is_complete ? getImageUrl($new_url) : $new_url;
984 - }else{ 1000 + } else {
985 return false; 1001 return false;
986 } 1002 }
987 - }else{ 1003 + } else {
988 return false; 1004 return false;
989 } 1005 }
990 } 1006 }
@@ -994,10 +1010,11 @@ function check_remote_url_down($url,$project_id,$domain,$is_complete=0){ @@ -994,10 +1010,11 @@ function check_remote_url_down($url,$project_id,$domain,$is_complete=0){
994 * @author zbj 1010 * @author zbj
995 * @date 2024/3/29 1011 * @date 2024/3/29
996 */ 1012 */
997 -function textareaToArr($content, $separator = ','){  
998 - return array_values(array_filter(array_unique(array_map(function ($v){ 1013 +function textareaToArr($content, $separator = ',')
  1014 +{
  1015 + return array_values(array_filter(array_unique(array_map(function ($v) {
999 return trim($v); 1016 return trim($v);
1000 - },explode($separator, $content))))); 1017 + }, explode($separator, $content)))));
1001 } 1018 }
1002 1019
1003 /** 1020 /**
@@ -1007,7 +1024,8 @@ function textareaToArr($content, $separator = ','){ @@ -1007,7 +1024,8 @@ function textareaToArr($content, $separator = ','){
1007 * @method :post 1024 * @method :post
1008 * @time :2024/6/26 10:46 1025 * @time :2024/6/26 10:46
1009 */ 1026 */
1010 -function ip_to_unique_string($ip) { 1027 +function ip_to_unique_string($ip)
  1028 +{
1011 // 将IP地址转换为数值表示 1029 // 将IP地址转换为数值表示
1012 $ip_number = ip2long($ip); 1030 $ip_number = ip2long($ip);
1013 // 使用哈希函数生成唯一数值 1031 // 使用哈希函数生成唯一数值
@@ -1021,7 +1039,8 @@ function ip_to_unique_string($ip) { @@ -1021,7 +1039,8 @@ function ip_to_unique_string($ip) {
1021 return strtolower($unique_string); 1039 return strtolower($unique_string);
1022 } 1040 }
1023 1041
1024 -function base62_encode($num) { 1042 +function base62_encode($num)
  1043 +{
1025 $characters = '23456789abcdefghijkmnpqrstuvwxyz'; 1044 $characters = '23456789abcdefghijkmnpqrstuvwxyz';
1026 $base = strlen($characters); 1045 $base = strlen($characters);
1027 $result = ''; 1046 $result = '';
@@ -1039,8 +1058,9 @@ function base62_encode($num) { @@ -1039,8 +1058,9 @@ function base62_encode($num) {
1039 * @method :post 1058 * @method :post
1040 * @time :2024/8/19 14:21 1059 * @time :2024/8/19 14:21
1041 */ 1060 */
1042 -function urlSafeBase64Encode($data = '') {  
1043 - if(empty($data)){ 1061 +function urlSafeBase64Encode($data = '')
  1062 +{
  1063 + if (empty($data)) {
1044 return $data; 1064 return $data;
1045 } 1065 }
1046 // 1. 使用标准的 BASE64 编码 1066 // 1. 使用标准的 BASE64 编码
@@ -1061,7 +1081,8 @@ function urlSafeBase64Encode($data = '') { @@ -1061,7 +1081,8 @@ function urlSafeBase64Encode($data = '') {
1061 * @method :post 1081 * @method :post
1062 * @time :2024/9/14 16:45 1082 * @time :2024/9/14 16:45
1063 */ 1083 */
1064 -function generateRandomString($length) { 1084 +function generateRandomString($length)
  1085 +{
1065 return substr(str_shuffle(str_repeat($x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)))), 1, $length); 1086 return substr(str_shuffle(str_repeat($x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)))), 1, $length);
1066 } 1087 }
1067 1088
@@ -1080,26 +1101,26 @@ if (!function_exists('check_domain_record')) { @@ -1080,26 +1101,26 @@ if (!function_exists('check_domain_record')) {
1080 $is_record = false; 1101 $is_record = false;
1081 1102
1082 //获取域名解析记录 1103 //获取域名解析记录
1083 - $records = dns_get_record($domain,DNS_A);  
1084 - if(count($records) == 1 && ($records[0]['host'] == $server_info['domain'] || $records[0]['ip'] == $server_info['ip'])){ 1104 + $records = dns_get_record($domain, DNS_A);
  1105 + if (count($records) == 1 && ($records[0]['host'] == $server_info['domain'] || $records[0]['ip'] == $server_info['ip'])) {
1085 $is_record = true; 1106 $is_record = true;
1086 } 1107 }
1087 1108
1088 - if(!$is_record){ 1109 + if (!$is_record) {
1089 //解析不正确,再判断是否开启cnd 1110 //解析不正确,再判断是否开启cnd
1090 $top_domain = getTopDomain($domain); 1111 $top_domain = getTopDomain($domain);
1091 $cnd = curlGet('http://sitebak.globalso.com/get_records?domain=' . $top_domain); 1112 $cnd = curlGet('http://sitebak.globalso.com/get_records?domain=' . $top_domain);
1092 if (isset($cnd['data']) && $cnd['data']) { 1113 if (isset($cnd['data']) && $cnd['data']) {
1093 - if($domain == $top_domain || substr($domain,0,4) == 'www.'){ 1114 + if ($domain == $top_domain || substr($domain, 0, 4) == 'www.') {
1094 $check_domain = $domain; 1115 $check_domain = $domain;
1095 - }else{  
1096 - $check_domain = '*.'.$top_domain; 1116 + } else {
  1117 + $check_domain = '*.' . $top_domain;
1097 } 1118 }
1098 foreach ($cnd['data'] as $vc) { 1119 foreach ($cnd['data'] as $vc) {
1099 if ($vc['name'] == $check_domain && $vc['type'] == 'A' && $vc['content'] == $server_info['ip']) { 1120 if ($vc['name'] == $check_domain && $vc['type'] == 'A' && $vc['content'] == $server_info['ip']) {
1100 $is_record = true; 1121 $is_record = true;
1101 break; 1122 break;
1102 - }elseif ($vc['name'] == $check_domain && $vc['type'] == 'CNAME' && $vc['content'] == $server_info['domain']){ 1123 + } elseif ($vc['name'] == $check_domain && $vc['type'] == 'CNAME' && $vc['content'] == $server_info['domain']) {
1103 $is_record = true; 1124 $is_record = true;
1104 break; 1125 break;
1105 } 1126 }
@@ -1108,8 +1129,8 @@ if (!function_exists('check_domain_record')) { @@ -1108,8 +1129,8 @@ if (!function_exists('check_domain_record')) {
1108 } 1129 }
1109 1130
1110 return $is_record; 1131 return $is_record;
1111 - }catch (\Exception $e){  
1112 - errorLog('dns_get_record',['domain'=>$domain],$e); 1132 + } catch (\Exception $e) {
  1133 + errorLog('dns_get_record', ['domain' => $domain], $e);
1113 return false; 1134 return false;
1114 } 1135 }
1115 } 1136 }
@@ -1123,7 +1144,8 @@ if (!function_exists('check_curl_status')) { @@ -1123,7 +1144,8 @@ if (!function_exists('check_curl_status')) {
1123 * @author Akun 1144 * @author Akun
1124 * @date 2024/12/12 15:52 1145 * @date 2024/12/12 15:52
1125 */ 1146 */
1126 - function check_curl_status($url){ 1147 + function check_curl_status($url)
  1148 + {
1127 $header = array( 1149 $header = array(
1128 'Expect:', 1150 'Expect:',
1129 'Content-Type: application/json; charset=utf-8' 1151 'Content-Type: application/json; charset=utf-8'
@@ -1142,7 +1164,7 @@ if (!function_exists('check_curl_status')) { @@ -1142,7 +1164,7 @@ if (!function_exists('check_curl_status')) {
1142 curl_setopt($ch, CURLOPT_SSLVERSION, 'all'); 1164 curl_setopt($ch, CURLOPT_SSLVERSION, 'all');
1143 curl_setopt($ch, CURLOPT_HTTPHEADER, $header); 1165 curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
1144 curl_exec($ch); 1166 curl_exec($ch);
1145 - $http_code = curl_getinfo($ch,CURLINFO_HTTP_CODE); 1167 + $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1146 curl_close($ch); 1168 curl_close($ch);
1147 1169
1148 return $http_code; 1170 return $http_code;
@@ -1154,7 +1176,8 @@ if (!function_exists('check_curl_status')) { @@ -1154,7 +1176,8 @@ if (!function_exists('check_curl_status')) {
1154 * @author zbj 1176 * @author zbj
1155 * @date 2024/10/25 1177 * @date 2024/10/25
1156 */ 1178 */
1157 -function email_desensitize($email){ 1179 +function email_desensitize($email)
  1180 +{
1158 $parts = explode('@', $email); 1181 $parts = explode('@', $email);
1159 $username = $parts[0] ?? ''; 1182 $username = $parts[0] ?? '';
1160 $domain = $parts[1] ?? ''; 1183 $domain = $parts[1] ?? '';
@@ -1168,7 +1191,8 @@ function email_desensitize($email){ @@ -1168,7 +1191,8 @@ function email_desensitize($email){
1168 * @author zbj 1191 * @author zbj
1169 * @date 2024/10/25 1192 * @date 2024/10/25
1170 */ 1193 */
1171 -function getRandByRatio($proArr){ 1194 +function getRandByRatio($proArr)
  1195 +{
1172 $result = ''; 1196 $result = '';
1173 $proSum = array_sum($proArr); 1197 $proSum = array_sum($proArr);
1174 foreach ($proArr as $key => $proCur) { 1198 foreach ($proArr as $key => $proCur) {
@@ -1206,7 +1230,7 @@ function getPrefixKeyword($project_id, $type, $num) @@ -1206,7 +1230,7 @@ function getPrefixKeyword($project_id, $type, $num)
1206 $keyword = array_slice($fix_keyword, 0, $num); 1230 $keyword = array_slice($fix_keyword, 0, $num);
1207 $str = implode(", ", $keyword); 1231 $str = implode(", ", $keyword);
1208 1232
1209 - foreach ($keyword as $k=>$v){ 1233 + foreach ($keyword as $k => $v) {
1210 $tmp = rtrim($v, 's'); 1234 $tmp = rtrim($v, 's');
1211 if (substr_count($str, $tmp) > 1) { 1235 if (substr_count($str, $tmp) > 1) {
1212 unset($keyword[$k]); 1236 unset($keyword[$k]);
@@ -1224,16 +1248,17 @@ function getPrefixKeyword($project_id, $type, $num) @@ -1224,16 +1248,17 @@ function getPrefixKeyword($project_id, $type, $num)
1224 * @method :post 1248 * @method :post
1225 * @time :2025/2/11 14:58 1249 * @time :2025/2/11 14:58
1226 */ 1250 */
1227 -function getDeployOptimize($project_id){ 1251 +function getDeployOptimize($project_id)
  1252 +{
1228 $cache_key = 'project_deploy_optimize_info_' . $project_id; 1253 $cache_key = 'project_deploy_optimize_info_' . $project_id;
1229 $info = Cache::get($cache_key); 1254 $info = Cache::get($cache_key);
1230 - if(!$info){ 1255 + if (!$info) {
1231 $projectOptimizeModel = new DeployOptimize(); 1256 $projectOptimizeModel = new DeployOptimize();
1232 $info = $projectOptimizeModel->read(['project_id' => $project_id], ['id', 'company_en_name', 'company_en_description', 'keyword_prefix', 'keyword_suffix', 'special']); 1257 $info = $projectOptimizeModel->read(['project_id' => $project_id], ['id', 'company_en_name', 'company_en_description', 'keyword_prefix', 'keyword_suffix', 'special']);
1233 $projectKeywordModel = new ProjectKeyword(); 1258 $projectKeywordModel = new ProjectKeyword();
1234 - $keywordInfo = $projectKeywordModel->read(['project_id'=>$project_id]); 1259 + $keywordInfo = $projectKeywordModel->read(['project_id' => $project_id]);
1235 $info['main_keyword'] = ''; 1260 $info['main_keyword'] = '';
1236 - if(!empty($keywordInfo['main_keyword'])){ 1261 + if (!empty($keywordInfo['main_keyword'])) {
1237 $info['main_keyword'] = $keywordInfo['main_keyword']; 1262 $info['main_keyword'] = $keywordInfo['main_keyword'];
1238 } 1263 }
1239 Cache::put($cache_key, $info, 600); 1264 Cache::put($cache_key, $info, 600);
@@ -1249,7 +1274,8 @@ function getDeployOptimize($project_id){ @@ -1249,7 +1274,8 @@ function getDeployOptimize($project_id){
1249 * @method :post 1274 * @method :post
1250 * @time :2025/4/1 9:41 1275 * @time :2025/4/1 9:41
1251 */ 1276 */
1252 -function paginateArray($array, $page = 1, $pageSize = 20) { 1277 +function paginateArray($array, $page = 1, $pageSize = 20)
  1278 +{
1253 $totalItems = count($array); 1279 $totalItems = count($array);
1254 $totalPages = ceil($totalItems / $pageSize); 1280 $totalPages = ceil($totalItems / $pageSize);
1255 // 确保页码有效 1281 // 确保页码有效
@@ -1272,8 +1298,9 @@ function paginateArray($array, $page = 1, $pageSize = 20) { @@ -1272,8 +1298,9 @@ function paginateArray($array, $page = 1, $pageSize = 20) {
1272 * @method :post 1298 * @method :post
1273 * @time :2025/4/3 16:19 1299 * @time :2025/4/3 16:19
1274 */ 1300 */
1275 -function getDomain($url) {  
1276 - if(empty($url)){ 1301 +function getDomain($url)
  1302 +{
  1303 + if (empty($url)) {
1277 return $url; 1304 return $url;
1278 } 1305 }
1279 $parsedUrl = parse_url($url); 1306 $parsedUrl = parse_url($url);
@@ -1394,12 +1421,13 @@ function analysisRoute($pathInfo) @@ -1394,12 +1421,13 @@ function analysisRoute($pathInfo)
1394 return $router; 1421 return $router;
1395 } 1422 }
1396 1423
1397 -function getTopDomain ($url) { 1424 +function getTopDomain($url)
  1425 +{
1398 $url = strtolower($url); //首先转成小写 1426 $url = strtolower($url); //首先转成小写
1399 $url = mb_ereg_replace('^( | )+', '', trim($url)); 1427 $url = mb_ereg_replace('^( | )+', '', trim($url));
1400 $url = mb_ereg_replace('( | )+$', '', $url); 1428 $url = mb_ereg_replace('( | )+$', '', $url);
1401 if (!preg_match('/^(http:\/\/|https)/', $url)) { 1429 if (!preg_match('/^(http:\/\/|https)/', $url)) {
1402 - $url = "https://".$url; 1430 + $url = "https://" . $url;
1403 } 1431 }
1404 $hosts = parse_url($url); 1432 $hosts = parse_url($url);
1405 $host = $hosts['host'] ?? ''; 1433 $host = $hosts['host'] ?? '';
@@ -1413,10 +1441,10 @@ function getTopDomain ($url) { @@ -1413,10 +1441,10 @@ function getTopDomain ($url) {
1413 $preg = '/[\w].+\.(com|net|org|gov|edu|co|ne)\.[\w]/'; 1441 $preg = '/[\w].+\.(com|net|org|gov|edu|co|ne)\.[\w]/';
1414 if (($n > 2) && preg_match($preg, $host)) { 1442 if (($n > 2) && preg_match($preg, $host)) {
1415 //双后缀取后3位 1443 //双后缀取后3位
1416 - $host = $data[$n - 3].'.'.$data[$n - 2].'.'.$data[$n - 1]; 1444 + $host = $data[$n - 3] . '.' . $data[$n - 2] . '.' . $data[$n - 1];
1417 } else { 1445 } else {
1418 //非双后缀取后两位 1446 //非双后缀取后两位
1419 - $host = $data[$n - 2].'.'.$data[$n - 1]; 1447 + $host = $data[$n - 2] . '.' . $data[$n - 1];
1420 } 1448 }
1421 return $host; 1449 return $host;
1422 } 1450 }
@@ -1440,3 +1468,93 @@ function diffInHours($startTime, $endTime) @@ -1440,3 +1468,93 @@ function diffInHours($startTime, $endTime)
1440 return round($hours, 1); 1468 return round($hours, 1);
1441 } 1469 }
1442 1470
  1471 +/**
  1472 + * 通过图片地址压缩图片
  1473 + * @param $url
  1474 + * @param int $width
  1475 + * @return string
  1476 + * @author Akun
  1477 + * @date 2025/09/01 15:18
  1478 + */
  1479 +function thumbImageByUrl($url, $width = 360)
  1480 +{
  1481 + if (empty($url)) {
  1482 + return $url;
  1483 + }
  1484 +
  1485 + if ($width == 0) {
  1486 + return $url;
  1487 + }
  1488 +
  1489 + if (strpos($url, '_thumb') !== false) {
  1490 + return $url;
  1491 + }
  1492 +
  1493 + //获取图片完整访问地址
  1494 + $url_complete = getImageUrl($url);
  1495 +
  1496 + //获取与原图存储路径相同的压缩路径
  1497 + $path = parse_url($url_complete, PHP_URL_PATH);
  1498 + $path_arr = explode('.', $path);
  1499 + if (count($path_arr) != 2) {
  1500 + return $url;
  1501 + }
  1502 + $path_arr[0] = $path_arr[0] . '_thumbW' . $width;
  1503 + $key = implode('.', $path_arr);
  1504 +
  1505 + try {
  1506 + $img = \Intervention\Image\Facades\Image::make($url_complete);
  1507 +
  1508 + //宽度按设定,高度自动调整
  1509 + $img->resize($width, null, function ($constraint) {
  1510 + $constraint->aspectRatio();
  1511 + $constraint->upsize();
  1512 + });
  1513 +
  1514 + //获取处理后的图片二进制资源
  1515 + $resource = $img->stream()->__toString();
  1516 +
  1517 + //上传存储桶
  1518 + $thumb_url = CosService::uploadRemote('', '', '', $key, $resource);
  1519 +
  1520 + $url = $thumb_url ? $thumb_url : $url;
  1521 + } catch (\Exception $e) {
  1522 + Log::channel('thumb_img')->error($e->getMessage(), [$url, $width]);
  1523 + }
  1524 +
  1525 + return $url;
  1526 +}
  1527 +
  1528 +if (!function_exists('httpGetSsl')) {
  1529 + /**
  1530 + * 获取通配符证书
  1531 + * @param $domain
  1532 + * @return mixed
  1533 + * @author Akun
  1534 + * @date 2025/04/21 16:51
  1535 + */
  1536 + function httpGetSsl($domain)
  1537 + {
  1538 + $header = array(
  1539 + "Accept:application/json",
  1540 + "Content-Type:application/json;charset=utf-8",
  1541 + "X-CmerApi-Host:" . env('GET_SSL_HOST'),
  1542 + "Apikey:" . env('GET_SSL_KEY'),
  1543 + );
  1544 + $ch = curl_init();
  1545 + curl_setopt($ch, CURLOPT_URL, env('GET_SSL_URL') . '?domain=' . $domain);
  1546 + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
  1547 + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  1548 + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
  1549 + curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
  1550 + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
  1551 + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
  1552 + curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
  1553 + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  1554 + $res = curl_exec($ch);
  1555 + curl_close($ch);
  1556 +
  1557 + $result = json_decode($res, true);
  1558 + return is_array($result) ? $result : $res;
  1559 + }
  1560 +}
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 namespace App\Http\Controllers\Api; 3 namespace App\Http\Controllers\Api;
4 4
5 use App\Exceptions\InquiryFilterException; 5 use App\Exceptions\InquiryFilterException;
  6 +use App\Models\Domain\DomainInfo;
6 use App\Models\Mail\Mail; 7 use App\Models\Mail\Mail;
7 use App\Models\Project\DeployBuild; 8 use App\Models\Project\DeployBuild;
8 use App\Models\Project\Project; 9 use App\Models\Project\Project;
@@ -69,7 +70,7 @@ class SelfSiteController extends BaseController @@ -69,7 +70,7 @@ class SelfSiteController extends BaseController
69 $cos = new CosService(); 70 $cos = new CosService();
70 $fileName = uniqid() . rand(10000, 99999) . '.' . $file['ext']; 71 $fileName = uniqid() . rand(10000, 99999) . '.' . $file['ext'];
71 $file_data = base64_decode($file['data']); 72 $file_data = base64_decode($file['data']);
72 - $path = $cos->uploadFile($file_data, '/inquiry/' . date('Ymd'), $fileName,true); 73 + $path = $cos->uploadFile($file_data, '/inquiry/' . date('Ymd'), $fileName, true);
73 $data[$key] = [ 74 $data[$key] = [
74 'path' => $path, 75 'path' => $path,
75 'original_name' => $file['name'], 76 'original_name' => $file['name'],
@@ -191,4 +192,50 @@ class SelfSiteController extends BaseController @@ -191,4 +192,50 @@ class SelfSiteController extends BaseController
191 192
192 return $this->success([]); 193 return $this->success([]);
193 } 194 }
  195 +
  196 + /**
  197 + * 自建站获取通配符证书接口
  198 + * @param Request $request
  199 + * @return false|string
  200 + * @author Akun
  201 + * @date 2025/09/02 16:55
  202 + */
  203 + public function selfSiteSsl(Request $request)
  204 + {
  205 + $token = $request->header('token');//token
  206 + $pid = $request->header('pid');//项目id
  207 +
  208 + if (empty($token) || empty($pid)) {
  209 + return $this->error('token无效', 401);
  210 + }
  211 +
  212 + //判断token是否有效
  213 + $project_model = new Project();
  214 + $project_info = $project_model->read(['id' => $pid, 'site_token' => $token]);
  215 + if (!$project_info) {
  216 + return $this->error('token无效', 401);
  217 + }
  218 +
  219 + //获取域名信息
  220 + $domain_model = new DomainInfo();
  221 + $domain_info = $domain_model->read(['project_id' => $pid]);
  222 + if (!$domain_info) {
  223 + return $this->error('获取域名失败', 401);
  224 + }
  225 +
  226 + //获取通配符证书
  227 + $top_domain = getTopDomain($domain_info['domain']);
  228 + $ssl_re = httpGetSsl($top_domain);
  229 + $return = [
  230 + 'ssl_key' => '',
  231 + 'ssl_cert' => ''
  232 + ];
  233 + if (isset($ssl_re['status']) && $ssl_re['status'] == 2) {
  234 + //获取成功
  235 + $return['ssl_key'] = $ssl_re['ssl_key'];
  236 + $return['ssl_cert'] = $ssl_re['ssl_cert'];
  237 + }
  238 +
  239 + return $this->success($return);
  240 + }
194 } 241 }
@@ -200,6 +200,7 @@ class OptimizeController extends BaseController @@ -200,6 +200,7 @@ class OptimizeController extends BaseController
200 'gl_project.is_translate AS is_translate', 200 'gl_project.is_translate AS is_translate',
201 'gl_project.is_translate_tag AS is_translate_tag', 201 'gl_project.is_translate_tag AS is_translate_tag',
202 'gl_project.is_upgrade AS is_upgrade', 202 'gl_project.is_upgrade AS is_upgrade',
  203 + 'gl_project.project_type AS project_type',
203 'gl_project.site_status AS site_status', 204 'gl_project.site_status AS site_status',
204 'gl_project_online_check.id AS online_check_id', 205 'gl_project_online_check.id AS online_check_id',
205 'gl_project_online_check.question AS question', 206 'gl_project_online_check.question AS question',
@@ -547,9 +548,9 @@ class OptimizeController extends BaseController @@ -547,9 +548,9 @@ class OptimizeController extends BaseController
547 ProjectServer::useProject($this->param['project_id']); 548 ProjectServer::useProject($this->param['project_id']);
548 $productKeywordModel = new Keyword(); 549 $productKeywordModel = new Keyword();
549 $data = []; 550 $data = [];
550 - $lists = $productKeywordModel->list(['route'=>['!=',null]],'id',['id','route','seo_title']);  
551 - if (!empty($lists)){  
552 - foreach ($lists as $item){ 551 + $lists = $productKeywordModel->lists(['route'=>['!=',null]],1,500,'id',['id','route','seo_title']);
  552 + if (!empty($lists['list'])){
  553 + foreach ($lists['list'] as $item){
553 $data[] = $domain . $item['route'] . '/{' . $item['seo_title'] . '}'; 554 $data[] = $domain . $item['route'] . '/{' . $item['seo_title'] . '}';
554 } 555 }
555 } 556 }
@@ -161,6 +161,7 @@ class RenewProjectController extends BaseController @@ -161,6 +161,7 @@ class RenewProjectController extends BaseController
161 $data = APublicModel::getNumByProjectId($item['id']); 161 $data = APublicModel::getNumByProjectId($item['id']);
162 } 162 }
163 $plan = Project::planMap(); 163 $plan = Project::planMap();
  164 + $seoPlan = Project::seoMap();
164 $item = [ 165 $item = [
165 'id' => $item['id'], 166 'id' => $item['id'],
166 'title' => $item['title'], 167 'title' => $item['title'],
@@ -178,8 +179,10 @@ class RenewProjectController extends BaseController @@ -178,8 +179,10 @@ class RenewProjectController extends BaseController
178 'optimize_tech' => $manageModel->getName($item['deploy_optimize']['tech_mid']), //售后技术 179 'optimize_tech' => $manageModel->getName($item['deploy_optimize']['tech_mid']), //售后技术
179 'type' => $item['type'], 180 'type' => $item['type'],
180 'test_domain' => $item['deploy_build']['test_domain'] ?? 0, 181 'test_domain' => $item['deploy_build']['test_domain'] ?? 0,
181 - 'plan' =>$plan[$item['deploy_build']['plan']] ?? '白帽seo版本', 182 + 'plan' =>$plan[$item['deploy_build']['plan']] ?? '无',
  183 + 'seo_plan' =>$seoPlan[$item['deploy_build']['seo_plan']] ?? '无',
182 'plan_id' =>$item['deploy_build']['plan'], 184 'plan_id' =>$item['deploy_build']['plan'],
  185 + 'seo_plan_id' =>$item['deploy_build']['seo_plan'],
183 'domain' => !empty($item['deploy_optimize']['domain']) ? $domainModel->getDomain($item['deploy_optimize']['domain']) : '', 186 'domain' => !empty($item['deploy_optimize']['domain']) ? $domainModel->getDomain($item['deploy_optimize']['domain']) : '',
184 'created_at' => date('Y年m月d日', strtotime($item['created_at'])), 187 'created_at' => date('Y年m月d日', strtotime($item['created_at'])),
185 'autologin_code' => getAutoLoginCode($item['id']), 188 'autologin_code' => getAutoLoginCode($item['id']),
@@ -6,6 +6,7 @@ use App\Enums\Common\Code; @@ -6,6 +6,7 @@ use App\Enums\Common\Code;
6 use App\Http\Controllers\Aside\BaseController; 6 use App\Http\Controllers\Aside\BaseController;
7 use App\Http\Logic\Aside\Template\ATemplateLogic; 7 use App\Http\Logic\Aside\Template\ATemplateLogic;
8 use App\Http\Requests\Aside\Template\ATemplateRequest; 8 use App\Http\Requests\Aside\Template\ATemplateRequest;
  9 +use App\Models\Manage\Manage;
9 use App\Models\Template\TemplateLabel; 10 use App\Models\Template\TemplateLabel;
10 11
11 /** 12 /**
@@ -26,12 +27,14 @@ class ATemplateController extends BaseController @@ -26,12 +27,14 @@ class ATemplateController extends BaseController
26 public function lists(ATemplateLogic $aTemplateLogic){ 27 public function lists(ATemplateLogic $aTemplateLogic){
27 $templateLabel = new TemplateLabel(); 28 $templateLabel = new TemplateLabel();
28 $this->map = $this->searchLabelName($templateLabel); 29 $this->map = $this->searchLabelName($templateLabel);
29 - $filed = ['id','name','image','url','status','sort','deleted_status','test_model','created_at','project_id']; 30 + $filed = ['id','name','image','url','status','upload_id','sort','deleted_status','test_model','submit_time','design_msg','front_msg','created_at','project_id'];
30 $lists = $aTemplateLogic->aTemplateList($this->map,$this->page,$this->row,$this->order,$filed); 31 $lists = $aTemplateLogic->aTemplateList($this->map,$this->page,$this->row,$this->order,$filed);
31 if(!empty($lists) && !empty($lists['list'])){ 32 if(!empty($lists) && !empty($lists['list'])){
  33 + $manageModel = new Manage();
32 foreach ($lists['list'] as $k => $v){ 34 foreach ($lists['list'] as $k => $v){
33 $v['label'] = $templateLabel->list(['template_id'=>$v['id'],'type'=>1],'id',['id','name'],'desc',5); 35 $v['label'] = $templateLabel->list(['template_id'=>$v['id'],'type'=>1],'id',['id','name'],'desc',5);
34 $v['image_link'] = getImageUrl($v['image']); 36 $v['image_link'] = getImageUrl($v['image']);
  37 + $v['upload_name'] = $manageModel->getName($v['upload_id']);
35 $lists['list'][$k] = $v; 38 $lists['list'][$k] = $v;
36 } 39 }
37 } 40 }
@@ -12,7 +12,11 @@ namespace App\Http\Controllers\Aside\Ticket; @@ -12,7 +12,11 @@ namespace App\Http\Controllers\Aside\Ticket;
12 use App\Enums\Common\Code; 12 use App\Enums\Common\Code;
13 use App\Http\Controllers\Aside\BaseController; 13 use App\Http\Controllers\Aside\BaseController;
14 use App\Http\Logic\Aside\Ticket\TicketLogic; 14 use App\Http\Logic\Aside\Ticket\TicketLogic;
  15 +use App\Models\Ticket\TicketDailyCount;
  16 +use App\Models\Ticket\TicketMonthDeptCount;
  17 +use App\Models\Ticket\TicketWeekDeptCount;
15 use Illuminate\Http\Request; 18 use Illuminate\Http\Request;
  19 +use Illuminate\Support\Carbon;
16 20
17 class TicketController extends BaseController 21 class TicketController extends BaseController
18 { 22 {
@@ -37,7 +41,79 @@ class TicketController extends BaseController @@ -37,7 +41,79 @@ class TicketController extends BaseController
37 } 41 }
38 42
39 /** 43 /**
40 - * @remark :技术组 44 + * @remark :获取最近一个月的数据
  45 + * @name :getMonthList
  46 + * @author :lyh
  47 + * @method :post
  48 + * @time :2025/8/30 17:26
  49 + */
  50 + public function getMonthList(){
  51 + $this->request->validate([
  52 + 'start'=>'required',
  53 + 'end'=>'required'
  54 + ],[
  55 + 'start.required' => 'start不能为空',
  56 + 'end.required' => 'end不能为空',
  57 + ]);
  58 + $dailyModel = new TicketDailyCount();
  59 + $dailyList = $dailyModel->list(['date'=>['between',[$this->param['start'],$this->param['end']]]],'date',['*'],'desc',30);//取最近30条数据
  60 + $this->response('success',Code::SUCCESS,$dailyList);
  61 + }
  62 + /**
  63 + * @remark :获取搜索时间
  64 + * @name :getTIme
  65 + * @author :lyh
  66 + * @method :post
  67 + * @time :2025/8/30 15:39
  68 + */
  69 + public function getTime(){
  70 + $weekModel = new TicketWeekDeptCount();
  71 + $weekData = $weekModel->where('dept_id',1)->select('start_at', 'end_at')->distinct()->get()->toArray();
  72 + $monthModel = new TicketMonthDeptCount();
  73 + $monthData = $monthModel->where('dept_id',1)->select('start_at', 'end_at')->distinct()->get()->toArray();
  74 + $this->response('success',Code::SUCCESS,['week_data'=>$weekData,'month_data'=>$monthData]);
  75 + }
  76 +
  77 + /**
  78 + * @remark :周记录数据(默认上一周)
  79 + * @name :weekManageList
  80 + * @author :lyh
  81 + * @method :post
  82 + * @time :2025/8/30 15:31
  83 + */
  84 + public function weekManageList(){
  85 + $this->request->validate([
  86 + 'start'=>'required',
  87 + 'end'=>'required'
  88 + ],[
  89 + 'start.required' => 'start不能为空',
  90 + 'end.required' => 'end不能为空',
  91 + ]);
  92 + $data = $this->logic->getWeekManageList($this->param['start'],$this->param['end'],$this->param['dept_id'] ?? 1);
  93 + $this->response('success',Code::SUCCESS,$data);
  94 + }
  95 +
  96 + /**
  97 + * @remark :按月统计数据(默认上一月)
  98 + * @name :monthManageList
  99 + * @author :lyh
  100 + * @method :post
  101 + * @time :2025/8/30 15:35
  102 + */
  103 + public function monthManageList(){
  104 + $this->request->validate([
  105 + 'start'=>'required',
  106 + 'end'=>'required'
  107 + ],[
  108 + 'start.required' => 'start不能为空',
  109 + 'end.required' => 'end不能为空',
  110 + ]);
  111 + $data = $this->logic->getMonthManageList($this->param['start'],$this->param['end'],$this->param['dept_id'] ?? 1);
  112 + $this->response('success',Code::SUCCESS,$data);
  113 + }
  114 +
  115 + /**
  116 + * @remark :技术组总统计
41 * @name :manageTicketCount 117 * @name :manageTicketCount
42 * @author :lyh 118 * @author :lyh
43 * @method :post 119 * @method :post
@@ -50,7 +50,31 @@ class AsideTicketController extends BaseController @@ -50,7 +50,31 @@ class AsideTicketController extends BaseController
50 ->when($request->input('status') !== null, function ($query) use ($request) { 50 ->when($request->input('status') !== null, function ($query) use ($request) {
51 // status 查 gl_tickets.status 51 // status 查 gl_tickets.status
52 $status = $request->input('status'); 52 $status = $request->input('status');
53 - return $query->where('status', $status); 53 + if($status == 10){
  54 + $newTime = date("Y-m-d H:i:s", strtotime("-120 hours"));
  55 + return $query->where('status', 0)->where('plan_end_at','<',$newTime);//超过120个小时未处理的工单
  56 + }else{
  57 + return $query->where('status', $status);
  58 + }
  59 + })
  60 + ->when($request->input('timeout') !== null, function ($query) use ($request) {
  61 + // status 查 gl_tickets.status
  62 + $timeout = $request->input('timeout');
  63 + switch ($timeout) {
  64 + case 1:
  65 + $newTime = date("Y-m-d H:i:s", strtotime("-24 hours"));
  66 + break;
  67 + case 2:
  68 + $newTime = date("Y-m-d H:i:s", strtotime("-48 hours"));
  69 + break;
  70 + case 3:
  71 + $newTime = date("Y-m-d H:i:s", strtotime("-72 hours"));
  72 + break;
  73 + default:
  74 + $newTime = date("Y-m-d H:i:s");
  75 + break;
  76 + }
  77 + return $query->where('status', 0)->where('plan_end_at','<',$newTime);//超过120个小时未处理的工单
54 }) 78 })
55 ->when($request->input('star') !== null, function ($query) use ($request) { 79 ->when($request->input('star') !== null, function ($query) use ($request) {
56 $star = $request->input('star'); 80 $star = $request->input('star');
@@ -84,10 +108,30 @@ class AsideTicketController extends BaseController @@ -84,10 +108,30 @@ class AsideTicketController extends BaseController
84 //TODO::用户部门搜索 108 //TODO::用户部门搜索
85 if(isset($this->param['dept_id']) && !empty($this->param['dept_id'])){ 109 if(isset($this->param['dept_id']) && !empty($this->param['dept_id'])){
86 $manageHrModel = new ManageHr(); 110 $manageHrModel = new ManageHr();
87 - $manageIdArr = $manageHrModel->selectField(['dept_id'=>$this->param['dept_id'],'status'=>1],'manage_id');  
88 - $query->whereHas('logs', function ($q) use ($manageIdArr) {  
89 - $q->whereIn('engineer_id', $manageIdArr);  
90 - }); 111 + //售后优化+技术搜索
  112 + if($this->param['dept_id'] == 2 && !empty($this->param['entry_position'])) {//售后部
  113 + if ($this->param['entry_position'] == 1) {
  114 + $manageIdArr = $manageHrModel->selectField(['entry_position' => ['in', [44, 46, 49]], 'status' => 1], 'manage_id');
  115 + } else {
  116 + //售后技术
  117 + $manageIdArr = $manageHrModel->selectField(['entry_position' => ['in', [42, 43, 45, 48, 51]], 'status' => 1], 'manage_id');
  118 + }
  119 + $query->whereHas('logs', function ($q) use ($manageIdArr) {
  120 + $q->whereIn('engineer_id', $manageIdArr);
  121 + });
  122 + }else{
  123 + $manageIdArr = $manageHrModel->selectField(['dept_id'=>$this->param['dept_id'],'status'=>1],'manage_id');
  124 + $query->whereHas('logs', function ($q) use ($manageIdArr) {
  125 + $q->whereIn('engineer_id', $manageIdArr);
  126 + });
  127 + }
  128 + }
  129 + if(!empty($this->param['start_at']) && !empty($this->param['end_at'])){
  130 + $query->whereBetween('created_at',[$this->param['start_at'],$this->param['end_at']]);
  131 + }
  132 + //搜索提交人姓名
  133 + if(!empty($this->param['submit_username'])){
  134 + $query->where('submit_username','like','%'.$this->param['submit_username'].'%');
91 } 135 }
92 // 添加排序功能 136 // 添加排序功能
93 $query->orderBy('status', 'asc'); 137 $query->orderBy('status', 'asc');
@@ -96,11 +140,24 @@ class AsideTicketController extends BaseController @@ -96,11 +140,24 @@ class AsideTicketController extends BaseController
96 $sortOrder = strtolower($request->input('sort_order', 'asc')); 140 $sortOrder = strtolower($request->input('sort_order', 'asc'));
97 $query->orderBy($sortField, $sortOrder); 141 $query->orderBy($sortField, $sortOrder);
98 if ($sortField != 'plan_end_at') $query->orderBy('plan_end_at', 'asc'); 142 if ($sortField != 'plan_end_at') $query->orderBy('plan_end_at', 'asc');
99 - $lists = $query->paginate($this->row, ['*'], 'page', $this->page); 143 + $lists = $query->paginate($this->row, ['*'], 'page', $this->page)->toArray();
  144 + if(!empty($lists) && !empty($lists['list'])){
  145 + foreach ($lists['list'] as $key => $item){
  146 + //计算超时多少个小时
  147 + if($item['status'] == 0){
  148 + $end = date('Y-m-d H:i:s');
  149 + $start = $item['plan_end_at'];
  150 + if($start < $end){
  151 + $item['plan_ent_time'] = diffInHours($start,$end);
  152 + }
  153 + }
  154 + $lists['list'][$key] = $item;
  155 + }
  156 + }
100 $this->response('success', Code::SUCCESS, $lists); 157 $this->response('success', Code::SUCCESS, $lists);
101 } 158 }
102 159
103 - /** 160 + /**
104 * @param $search 161 * @param $search
105 * @return void 162 * @return void
106 * V5V6所有项目 163 * V5V6所有项目
@@ -201,7 +258,6 @@ class AsideTicketController extends BaseController @@ -201,7 +258,6 @@ class AsideTicketController extends BaseController
201 $ticket->close_wechat = $request->input('close_wechat', false); 258 $ticket->close_wechat = $request->input('close_wechat', false);
202 $ticket->num = $request->input('num', 0); 259 $ticket->num = $request->input('num', 0);
203 $ticket->save(); 260 $ticket->save();
204 -  
205 // 分配工单参与人 261 // 分配工单参与人
206 $ticket->saveEngineers($request->input('engineer_ids', [])); 262 $ticket->saveEngineers($request->input('engineer_ids', []));
207 $nickname = ManageHr::where('manage_id', $this->manage['id'])->value('nickname') ?? mb_substr($ticket->submit_username, 0, 1) . '**'; 263 $nickname = ManageHr::where('manage_id', $this->manage['id'])->value('nickname') ?? mb_substr($ticket->submit_username, 0, 1) . '**';
@@ -259,7 +315,8 @@ class AsideTicketController extends BaseController @@ -259,7 +315,8 @@ class AsideTicketController extends BaseController
259 $ticket->status = $request->input('status'); 315 $ticket->status = $request->input('status');
260 if ($request->input('num')) 316 if ($request->input('num'))
261 $ticket->num = $request->input('num',0); 317 $ticket->num = $request->input('num',0);
262 - 318 + //同步更改工单时间
  319 + $ticket->logs()->where('status', '<', TicketLog::STATUS_COMPLETED)->where('is_engineer', 1)->update(['plan_end_at' => $ticket->plan_end_at]);
263 if ($ticket->status == Tickets::STATUS_COMPLETED) 320 if ($ticket->status == Tickets::STATUS_COMPLETED)
264 { 321 {
265 // 完成工单,把子任务里面未完成的工单改为完成 322 // 完成工单,把子任务里面未完成的工单改为完成
@@ -72,7 +72,7 @@ class GeoQuestionResController extends BaseController @@ -72,7 +72,7 @@ class GeoQuestionResController extends BaseController
72 'project_id.required' => 'project_id不能为空', 72 'project_id.required' => 'project_id不能为空',
73 'type.required' => '品牌类型不能为空' 73 'type.required' => '品牌类型不能为空'
74 ]); 74 ]);
75 - $data = $this->logic->getResultList($this->map,$this->page,$this->row); 75 + $data = $this->logic->getResultList($this->map,$this->page,$this->row,$this->order,$this->param['sort'] ?? 'desc');
76 $this->response('success',Code::SUCCESS,$data); 76 $this->response('success',Code::SUCCESS,$data);
77 } 77 }
78 78
@@ -472,7 +472,9 @@ class ProjectLogic extends BaseLogic @@ -472,7 +472,9 @@ class ProjectLogic extends BaseLogic
472 } 472 }
473 $param['confirm_file'] = Arr::a2s($param['confirm_file'] ?? []); 473 $param['confirm_file'] = Arr::a2s($param['confirm_file'] ?? []);
474 $remain_day = $param['deploy_build']['service_duration'] - $param['finish_remain_day']; 474 $remain_day = $param['deploy_build']['service_duration'] - $param['finish_remain_day'];
  475 + $seo_remain_day = $param['deploy_build']['seo_service_duration'] - $param['bm_finish_remain_day'];
475 $param['remain_day'] = ($remain_day > 0) ? $remain_day : 0; 476 $param['remain_day'] = ($remain_day > 0) ? $remain_day : 0;
  477 + $param['seo_remain_day'] = ($seo_remain_day > 0) ? $seo_remain_day : 0;
476 //文件上传默认值 478 //文件上传默认值
477 if($param['is_upload_manage']){ 479 if($param['is_upload_manage']){
478 $param['upload_config'] = [ 480 $param['upload_config'] = [
@@ -15,6 +15,10 @@ use App\Models\Project\Project; @@ -15,6 +15,10 @@ use App\Models\Project\Project;
15 use App\Models\Ticket\TicketDailyCount; 15 use App\Models\Ticket\TicketDailyCount;
16 use App\Models\Ticket\TicketDailyDeptCount; 16 use App\Models\Ticket\TicketDailyDeptCount;
17 use App\Models\Ticket\TicketDailyManageCount; 17 use App\Models\Ticket\TicketDailyManageCount;
  18 +use App\Models\Ticket\TicketMonthDeptCount;
  19 +use App\Models\Ticket\TicketMonthManageCount;
  20 +use App\Models\Ticket\TicketWeekDeptCount;
  21 +use App\Models\Ticket\TicketWeekManageCount;
18 use App\Models\WorkOrder\TicketLog; 22 use App\Models\WorkOrder\TicketLog;
19 use App\Models\WorkOrder\TicketProject; 23 use App\Models\WorkOrder\TicketProject;
20 use App\Models\WorkOrder\Tickets; 24 use App\Models\WorkOrder\Tickets;
@@ -42,7 +46,7 @@ class TicketLogic extends BaseLogic @@ -42,7 +46,7 @@ class TicketLogic extends BaseLogic
42 $date = date('Y-m-d');//今日时间 46 $date = date('Y-m-d');//今日时间
43 $data['add_num'] = $ticketModel->counts(['created_at'=>['between',[$date.' 00:00:00',$date.' 23:59:59']]]);//今日新增工单 47 $data['add_num'] = $ticketModel->counts(['created_at'=>['between',[$date.' 00:00:00',$date.' 23:59:59']]]);//今日新增工单
44 $data['processed_num'] = $ticketModel->counts(['end_at'=>['between',[$date.' 00:00:00',$date.' 23:59:59']]]);//今日已处理工单 48 $data['processed_num'] = $ticketModel->counts(['end_at'=>['between',[$date.' 00:00:00',$date.' 23:59:59']]]);//今日已处理工单
45 - $data['untreated_num'] = $ticketModel->counts(['end_at'=>null]);//今日未处理工单 49 + $data['untreated_num'] = $ticketModel->counts(['end_at'=>null]);//未处理工单
46 $submit_a_side = $ticketModel->formatQuery(['submit_side'=>1])->sum('submit_side'); 50 $submit_a_side = $ticketModel->formatQuery(['submit_side'=>1])->sum('submit_side');
47 $submit_b_side = $ticketModel->formatQuery(['submit_side'=>2])->sum('submit_side'); 51 $submit_b_side = $ticketModel->formatQuery(['submit_side'=>2])->sum('submit_side');
48 $data['source'] = ['a'=>$submit_a_side,'b'=>$submit_b_side]; 52 $data['source'] = ['a'=>$submit_a_side,'b'=>$submit_b_side];
@@ -110,4 +114,41 @@ class TicketLogic extends BaseLogic @@ -110,4 +114,41 @@ class TicketLogic extends BaseLogic
110 return $this->success($manageList); 114 return $this->success($manageList);
111 } 115 }
112 116
  117 + /**
  118 + * @remark :按月统计数据
  119 + * @name :getWeekManageList
  120 + * @author :lyh
  121 + * @method :post
  122 + * @time :2025/8/30 16:02
  123 + */
  124 + public function getWeekManageList($start,$end,$dept_id = 1){
  125 + if(empty($start) || empty($end)){
  126 + $start = Carbon::now()->subWeek()->startOfWeek(); // 上周一 00:00:00
  127 + $end = Carbon::now()->subWeek()->endOfWeek(); // 上周日 23:59:59
  128 + }
  129 + $manageWeekModel = new TicketWeekManageCount();
  130 + $manageWeekList = $manageWeekModel->list(['start_at'=>$start,'end_at'=>$end,'dept_id'=>$dept_id]);
  131 + $deptWeekModel = new TicketWeekDeptCount();
  132 + $deptWeekList = $deptWeekModel->list(['start_at'=>$start,'end_at'=>$end,'dept_id'=>$dept_id]);
  133 + return $this->success(['manage'=>$manageWeekList,'dept'=>$deptWeekList]);
  134 + }
  135 +
  136 + /**
  137 + * @remark :按月统计数据
  138 + * @name :getMonthManageList
  139 + * @author :lyh
  140 + * @method :post
  141 + * @time :2025/8/30 16:27
  142 + */
  143 + public function getMonthManageList($start,$end,$dept_id){
  144 + if(empty($start) || empty($end)){
  145 + $start = Carbon::now()->subMonth()->startOfMonth(); // 上个月 1号 00:00:00
  146 + $end = Carbon::now()->subMonth()->endOfMonth(); // 上个月最后一天 23:59:59
  147 + }
  148 + $manageWeekModel = new TicketMonthManageCount();
  149 + $manageWeekList = $manageWeekModel->list(['start_at'=>$start,'end_at'=>$end,'dept_id'=>$dept_id]);
  150 + $deptWeekModel = new TicketMonthDeptCount();
  151 + $deptWeekList = $deptWeekModel->list(['start_at'=>$start,'end_at'=>$end,'dept_id'=>$dept_id]);
  152 + return $this->success(['manage'=>$manageWeekList,'dept'=>$deptWeekList]);
  153 + }
113 } 154 }
@@ -46,9 +46,10 @@ class GeoQuestionResLogic extends BaseLogic @@ -46,9 +46,10 @@ class GeoQuestionResLogic extends BaseLogic
46 * @method :post 46 * @method :post
47 * @time :2025/7/4 9:48 47 * @time :2025/7/4 9:48
48 */ 48 */
49 - public function getResultList($map = [],$page = 1,$row = 20){ 49 + public function getResultList($map = [],$page = 1,$row = 20,$order = 'created_at',$sort = 'desc'){
  50 + unset($map['sort']);
50 $map['project_id'] = $this->user['project_id']; 51 $map['project_id'] = $this->user['project_id'];
51 - $filed = ['id','project_id','question_id','platform','is_match','question','en_question','keywords','url','label','created_at','updated_at']; 52 + $filed = ['id','project_id','question_id','platform','is_match','question','en_question','keywords','url','label','cosine','created_at','updated_at'];
52 if(!empty($map['created_at'])){ 53 if(!empty($map['created_at'])){
53 $map['created_at'] = ['between',[$map['created_at'].' 00:00:00',$map['created_at'].' 23:59:59']]; 54 $map['created_at'] = ['between',[$map['created_at'].' 00:00:00',$map['created_at'].' 23:59:59']];
54 $this->model = new GeoQuestionLog(); 55 $this->model = new GeoQuestionLog();
@@ -64,7 +65,7 @@ class GeoQuestionResLogic extends BaseLogic @@ -64,7 +65,7 @@ class GeoQuestionResLogic extends BaseLogic
64 // $q->whereRaw('JSON_LENGTH(keywords) > 0') 65 // $q->whereRaw('JSON_LENGTH(keywords) > 0')
65 // ->orWhereRaw('JSON_LENGTH(url) > 0'); 66 // ->orWhereRaw('JSON_LENGTH(url) > 0');
66 // }); 67 // });
67 - $data = $query->orderByRaw('CHAR_LENGTH(question) ASC')->paginate($row, $filed, 'page', $page);; 68 + $data = $query->orderBy($order,$sort)->orderByRaw('CHAR_LENGTH(question) ASC')->paginate($row, $filed, 'page', $page);
68 return $this->success($data); 69 return $this->success($data);
69 } 70 }
70 71
@@ -93,32 +94,50 @@ class GeoQuestionResLogic extends BaseLogic @@ -93,32 +94,50 @@ class GeoQuestionResLogic extends BaseLogic
93 $core_question_count = $questionTotalCount = $urlTotalCount = $keywordsTotalCount = 0; 94 $core_question_count = $questionTotalCount = $urlTotalCount = $keywordsTotalCount = 0;
94 $keywordArr = []; 95 $keywordArr = [];
95 $questionLogModel = new GeoQuestionLog(); 96 $questionLogModel = new GeoQuestionLog();
96 - $keywordUrlCount = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'hit'=>['!=',0]]);  
97 - $coreKeywordUrlCount = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'label'=>['like','%核心问题%'],'hit'=>['!=',0]]);  
98 - foreach ($list as $item){  
99 - $questionTotalCount += count($item['question'] ?? []);  
100 - //核心问题数  
101 - if(strpos($item['label'],'核心问题') !== false){  
102 - $core_question_count += count($item['question'] ?? []); 97 + if($this->user['project_id'] == 4533){
  98 + $keywordUrlCount = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'is_match'=>1,'hit'=>['!=',0]]);
  99 + foreach ($list as $item){
  100 + $questionTotalCount += count($item['question'] ?? []);
  101 + //核心问题数
  102 + if(strpos($item['label'],'核心问题') !== false){
  103 + $core_question_count += count($item['question'] ?? []);
  104 + }
  105 + foreach ($item['keywords'] as $keyWordItem){
  106 + if (!array_key_exists($keyWordItem, $keywordArr)) {
  107 + $keywordArr[$keyWordItem] = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'is_match'=>1,'keywords'=>['like','%"'.$keyWordItem.'"%']]);
  108 + }
  109 + }
103 } 110 }
104 - $keywordsTotalCount += count($item['keywords'] ?? []);  
105 - $urlTotalCount += count($item['url'] ?? []);  
106 - foreach ($item['keywords'] as $keyWordItem){  
107 - if (!array_key_exists($keyWordItem, $keywordArr)) {  
108 - $keywordArr[$keyWordItem] = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'keywords'=>['like','%"'.$keyWordItem.'"%']]); 111 + $coreKeywordUrlCount = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'label'=>['like','%核心问题%'],'is_match'=>1,'hit'=>['!=',0]]);
  112 + $data = [
  113 + 'question_count'=>$questionTotalCount,//问题总数
  114 + 'core_question_count'=>$core_question_count,//核心问题总数
  115 + 'keywords_url_count'=>$keywordUrlCount,
  116 + 'keywords_arr' => $keywordArr,
  117 + 'core_keyword_url_count'=>$coreKeywordUrlCount ?? 0
  118 + ];
  119 + return $this->success($data);
  120 + }else{
  121 + $keywordUrlCount = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'hit'=>['!=',0]]);
  122 + foreach ($list as $item){
  123 + $questionTotalCount += count($item['question'] ?? []);
  124 + $keywordsTotalCount += count($item['keywords'] ?? []);
  125 + $urlTotalCount += count($item['url'] ?? []);
  126 + foreach ($item['keywords'] as $keyWordItem){
  127 + if (!array_key_exists($keyWordItem, $keywordArr)) {
  128 + $keywordArr[$keyWordItem] = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'keywords'=>['like','%"'.$keyWordItem.'"%']]);
  129 + }
109 } 130 }
110 } 131 }
  132 + $data = [
  133 + 'question_count'=>$questionTotalCount,
  134 + 'keywords_count'=>$keywordsTotalCount,
  135 + 'url_count'=>$urlTotalCount,
  136 + 'keywords_url_count'=>$keywordUrlCount,
  137 + 'keywords_arr' => $keywordArr,
  138 + ];
  139 + return $this->success($data);
111 } 140 }
112 - $data = [  
113 - 'keywords_count'=>$keywordsTotalCount,  
114 - 'url_count'=>$urlTotalCount,  
115 - 'question_count'=>$questionTotalCount,  
116 - 'keywords_url_count'=>$keywordUrlCount,  
117 - 'keywords_arr' => $keywordArr,  
118 - 'core_question_count'=>$core_question_count,  
119 - 'core_keyword_url_count'=>$coreKeywordUrlCount  
120 - ];  
121 - return $this->success($data);  
122 } 141 }
123 142
124 /** 143 /**
@@ -134,7 +153,11 @@ class GeoQuestionResLogic extends BaseLogic @@ -134,7 +153,11 @@ class GeoQuestionResLogic extends BaseLogic
134 $list = $platformModel->list(['status'=>1],'id',['name','en_name']); 153 $list = $platformModel->list(['status'=>1],'id',['name','en_name']);
135 $questionResModel = new GeoQuestionLog(); 154 $questionResModel = new GeoQuestionLog();
136 foreach ($list as $item){ 155 foreach ($list as $item){
137 - $data[$item['name']] = $questionResModel->counts(['project_id'=>$this->user['project_id'],'hit'=>['!=',0],'platform'=>$item['en_name']]); 156 + if($this->user['project_id'] == 4533){
  157 + $data[$item['name']] = $questionResModel->counts(['project_id'=>$this->user['project_id'],'is_match'=>1,'hit'=>['!=',0],'platform'=>$item['en_name']]);
  158 + }else{
  159 + $data[$item['name']] = $questionResModel->counts(['project_id'=>$this->user['project_id'],'hit'=>['!=',0],'platform'=>$item['en_name']]);
  160 + }
138 } 161 }
139 return $this->success($data); 162 return $this->success($data);
140 } 163 }
@@ -356,7 +356,12 @@ class ProductLogic extends BaseLogic @@ -356,7 +356,12 @@ class ProductLogic extends BaseLogic
356 $v['url'] = str_replace_url($v['url']); 356 $v['url'] = str_replace_url($v['url']);
357 $param['gallery'][$k] = $v; 357 $param['gallery'][$k] = $v;
358 } 358 }
359 - $param['thumb'] = Arr::a2s($param['gallery'][0] ?? []); 359 + $thumb = $param['gallery'][0] ?? [];
  360 + if(isset($thumb['url']) && $thumb['url']){
  361 + //生成缩略图
  362 + $thumb['url'] = thumbImageByUrl($thumb['url'],$this->user['thumb_w']??0);
  363 + }
  364 + $param['thumb'] = Arr::a2s($thumb);
360 $param['gallery'] = Arr::a2s($param['gallery'] ?? []); 365 $param['gallery'] = Arr::a2s($param['gallery'] ?? []);
361 }else{ 366 }else{
362 $param['thumb'] = Arr::a2s([]); 367 $param['thumb'] = Arr::a2s([]);
@@ -322,6 +322,8 @@ class UserLoginLogic @@ -322,6 +322,8 @@ class UserLoginLogic
322 $info['import_products_url'] = 'https://ecdn6.globalso.com/upload/p/1/file/2024-12/products.csv'; 322 $info['import_products_url'] = 'https://ecdn6.globalso.com/upload/p/1/file/2024-12/products.csv';
323 $info['import_news_url'] = 'https://ecdn6.globalso.com/upload/p/1/file/2024-12/news.csv'; 323 $info['import_news_url'] = 'https://ecdn6.globalso.com/upload/p/1/file/2024-12/news.csv';
324 $info['import_blogs_url'] = 'https://ecdn6.globalso.com/upload/p/1/file/2024-12/blogs.csv'; 324 $info['import_blogs_url'] = 'https://ecdn6.globalso.com/upload/p/1/file/2024-12/blogs.csv';
  325 + //缩略图宽度
  326 + $info['thumb_w'] = $project['deploy_build']['thumb_w'] ?? 0;
325 return $info; 327 return $info;
326 } 328 }
327 329
@@ -25,7 +25,7 @@ class AsideTicketListRequest extends FormRequest @@ -25,7 +25,7 @@ class AsideTicketListRequest extends FormRequest
25 { 25 {
26 return [ 26 return [
27 'project_id' => 'nullable|string', 27 'project_id' => 'nullable|string',
28 - 'status' => 'nullable|in:0,1,2,3,9|integer', 28 + 'status' => 'nullable|in:0,1,2,3,9,10|integer',
29 'star' => 'nullable|in:1,2,3|integer', 29 'star' => 'nullable|in:1,2,3|integer',
30 'search' => 'nullable|string', // 搜索关键词 30 'search' => 'nullable|string', // 搜索关键词
31 'engineer_id' => 'nullable|integer', // 工程师ID 31 'engineer_id' => 'nullable|integer', // 工程师ID
@@ -34,10 +34,8 @@ class SyncImageFileJob implements ShouldQueue @@ -34,10 +34,8 @@ class SyncImageFileJob implements ShouldQueue
34 */ 34 */
35 public function handle() 35 public function handle()
36 { 36 {
37 - $file_path = $this->getUrl($this->param['path'].'/'.$this->param['name'], 0,$this->param['location']);  
38 - $cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$this->param['path'].'" https://v6-file.globalso.com/upload.php';  
39 - echo date('Y-m-d H:i:s') . ' | ' . $cmd . PHP_EOL;  
40 - $code = shell_exec($cmd); 37 + $code = $this->synchronizationFile($this->param['path'].'/'.$this->param['name']);
  38 + echo date('Y-m-d H:i:s') . ' | ' . $code . PHP_EOL;
41 if(200 != (int)$code){ 39 if(200 != (int)$code){
42 $errorFileModel = new ErrorFile(); 40 $errorFileModel = new ErrorFile();
43 $errorFileModel->add(['path'=>$this->param['path'].'/'.$this->param['name']]); 41 $errorFileModel->add(['path'=>$this->param['path'].'/'.$this->param['name']]);
@@ -45,39 +43,12 @@ class SyncImageFileJob implements ShouldQueue @@ -45,39 +43,12 @@ class SyncImageFileJob implements ShouldQueue
45 return true; 43 return true;
46 } 44 }
47 45
48 - /**  
49 - * @remark :获取图片文件链接  
50 - * @name :getUrl  
51 - * @author :lyh  
52 - * @method :post  
53 - * @time :2024/5/22 11:53  
54 - */  
55 - public function getUrl($path,$storage_type,$location){  
56 - if(is_array($path)){  
57 - $url =[];  
58 - foreach ($path as $v){  
59 - $url[] = $this->getUrl($v,$storage_type,$location);  
60 - }  
61 - }else{  
62 - if(empty($path)){  
63 - return '';  
64 - }  
65 - if((strpos($path,'https://')!== false) || (strpos($path,'http://') !== false)){  
66 - return $path;  
67 - }  
68 - if(substr($path,0,2) == '//'){  
69 - return 'https:'.$path;  
70 - }  
71 - if($location == 0){  
72 - $cos = config('filesystems.disks.cos');  
73 - $cosCdn = ($storage_type == 0) ? $cos['cdn'] : $cos['cdn1'];  
74 - $url = $cosCdn.$path;  
75 - }else{  
76 - $s3 = config('filesystems.disks.s3');  
77 - $cdn = $s3['cdn'];  
78 - $url = $cdn.$path;  
79 - }  
80 - }  
81 - return $url; 46 + public function synchronizationFile($path_name){
  47 + //同步到大文件
  48 + $file_path = config('filesystems.disks.cos')['cdn1'].$path_name;
  49 + $directoryPath = pathinfo($path_name, PATHINFO_DIRNAME);
  50 + $cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$directoryPath.'" https://v6-file.globalso.com/upload.php';
  51 + echo date('Y-m-d H:i:s') . ' | ' . $cmd . PHP_EOL;
  52 + return shell_exec($cmd);
82 } 53 }
83 } 54 }
@@ -79,6 +79,7 @@ class Project extends Base @@ -79,6 +79,7 @@ class Project extends Base
79 3=>'2-4', 79 3=>'2-4',
80 4=>'3-5', 80 4=>'3-5',
81 5=>'5-7', 81 5=>'5-7',
  82 + 6=>'1/2'
82 ]; 83 ];
83 if($val){ 84 if($val){
84 return $arr[$val] ?? ''; 85 return $arr[$val] ?? '';
@@ -177,6 +178,38 @@ class Project extends Base @@ -177,6 +178,38 @@ class Project extends Base
177 } 178 }
178 179
179 /** 180 /**
  181 + * @remark :项目进度
  182 + * @name :projectProgress
  183 + * @author :lyh
  184 + * @method :post
  185 + * @time :2025/9/3 14:47
  186 + */
  187 + public static function projectProgress($search){
  188 + $data = [
  189 + 'build' => [
  190 + 1 => '建立微信群',
  191 + 2 => '对接资料',
  192 + 3 => '确定风格',
  193 + 4 => '资料上传',
  194 + 5 => '页面调整',
  195 + 6 => '关键词确认',
  196 + 7 => '正式网站上线'
  197 + ],
  198 + 'optimize' => [
  199 + 1 => '开始推广',
  200 + 2 => 'SEO设置',
  201 + 3 => '排名达标',
  202 + 4 => '剩余服务时常'
  203 + ]
  204 + ];
  205 +
  206 + if(!empty($search)){
  207 + return $data[$search];
  208 + }
  209 + return $data;
  210 + }
  211 +
  212 + /**
180 * @remark :新增搜索 213 * @remark :新增搜索
181 * @name :searchParam 214 * @name :searchParam
182 * @author :lyh 215 * @author :lyh
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :TicketDailyDeptCount.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/8/7 17:51
  8 + */
  9 +
  10 +namespace App\Models\Ticket;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +/**
  15 + * @remark :工单月统计:按照技术组统计
  16 + * @name :TicketDailyDeptCount
  17 + * @author :lyh
  18 + * @method :post
  19 + * @time :2025/8/7 17:51
  20 + */
  21 +class TicketMonthDeptCount extends Base
  22 +{
  23 + protected $table = 'gl_ticket_month_dept_count';
  24 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :TicketDailyManageCount.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/8/7 17:52
  8 + */
  9 +
  10 +namespace App\Models\Ticket;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +/**
  15 + * @remark :工单日统计:按照人员统计(月)
  16 + * @name :TicketDailyManageCount
  17 + * @author :lyh
  18 + * @method :post
  19 + * @time :2025/8/7 17:53
  20 + */
  21 +class TicketMonthManageCount extends Base
  22 +{
  23 + protected $table = 'gl_ticket_month_manage_count';
  24 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :TicketDailyDeptCount.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/8/7 17:51
  8 + */
  9 +
  10 +namespace App\Models\Ticket;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +/**
  15 + * @remark :工单周统计:按照技术组统计
  16 + * @name :TicketDailyDeptCount
  17 + * @author :lyh
  18 + * @method :post
  19 + * @time :2025/8/7 17:51
  20 + */
  21 +class TicketWeekDeptCount extends Base
  22 +{
  23 + protected $table = 'gl_ticket_week_dept_count';
  24 +}
  1 +<?php
  2 +/**
  3 + * @remark :
  4 + * @name :TicketDailyManageCount.php
  5 + * @author :lyh
  6 + * @method :post
  7 + * @time :2025/8/7 17:52
  8 + */
  9 +
  10 +namespace App\Models\Ticket;
  11 +
  12 +use App\Models\Base;
  13 +
  14 +/**
  15 + * @remark :工单日统计:按照人员统计(周)
  16 + * @name :TicketDailyManageCount
  17 + * @author :lyh
  18 + * @method :post
  19 + * @time :2025/8/7 17:53
  20 + */
  21 +class TicketWeekManageCount extends Base
  22 +{
  23 + protected $table = 'gl_ticket_week_manage_count';
  24 +}
@@ -9,6 +9,8 @@ @@ -9,6 +9,8 @@
9 9
10 namespace App\Services\Geo; 10 namespace App\Services\Geo;
11 11
  12 +use Illuminate\Support\Facades\Http;
  13 +
12 class GeoService 14 class GeoService
13 { 15 {
14 public $api_key = 'UkzZljFv83Z2qBi5YR1o3f2otAVWtug6'; 16 public $api_key = 'UkzZljFv83Z2qBi5YR1o3f2otAVWtug6';
@@ -40,7 +42,7 @@ class GeoService @@ -40,7 +42,7 @@ class GeoService
40 'platform' => $platform, 42 'platform' => $platform,
41 'security_check' => true 43 'security_check' => true
42 ]; 44 ];
43 - $data = http_post($url,json_encode($message,true),$header); 45 + $data = http_post($url,json_encode($message,true),$header,true,180);
44 return $data; 46 return $data;
45 } 47 }
46 48
@@ -108,4 +110,31 @@ class GeoService @@ -108,4 +110,31 @@ class GeoService
108 $data = http_post($url,json_encode($message,true),$header); 110 $data = http_post($url,json_encode($message,true),$header);
109 return $data; 111 return $data;
110 } 112 }
  113 +
  114 + /**
  115 + * 获取语句余弦相似度
  116 + * $text 会被拆解语句, 分析预警传$text
  117 + * @param string $standard 标准答案
  118 + * @param string $text 需要分析的语句
  119 + * @param string $embedding_model
  120 + * @param string $similarity_method
  121 + * @return \Illuminate\Http\Client\Response
  122 + */
  123 + public function cosineSimilarity($standard, $text, $embedding_model = 'text-embedding-3-small', $similarity_method = 'cosine')
  124 + {
  125 + $url = 'http://knowledge_base.zabbix.waimaoq.com/v1/crud/split_similarity';
  126 + $header = [
  127 + 'accept: application/json',
  128 + 'Content-Type: application/json'
  129 + ];
  130 + $param = [
  131 + 'text1' => $standard,
  132 + 'text2' => $text,
  133 + 'embedding_model' => $embedding_model,
  134 + 'similarity_method' => $similarity_method
  135 + ];
  136 +
  137 + $result = Http::post($url, $param);
  138 + return $result->json();
  139 + }
111 } 140 }
@@ -103,9 +103,10 @@ return [ @@ -103,9 +103,10 @@ return [
103 ], 103 ],
104 //域名解析别处记录日志 104 //域名解析别处记录日志
105 'analyze_other' => [ 105 'analyze_other' => [
106 - 'driver' => 'custom',  
107 - 'via' => \App\Factory\LogFormatterFactory::class,  
108 - 'prefix' => 'analyze_other', 106 + 'driver' => 'daily',
  107 + 'path' => storage_path('logs/analyze_other/laravel.log'),
  108 + 'level' => 'debug',
  109 + 'days' => 14,
109 ], 110 ],
110 'stack' => [ 111 'stack' => [
111 'driver' => 'stack', 112 'driver' => 'stack',
@@ -203,6 +204,12 @@ return [ @@ -203,6 +204,12 @@ return [
203 'level' => 'debug', 204 'level' => 'debug',
204 'days' => 30, 205 'days' => 30,
205 ], 206 ],
  207 + 'thumb_img' => [
  208 + 'driver' => 'daily',
  209 + 'path' => storage_path('logs/thumb_img/laravel.log'),
  210 + 'level' => 'debug',
  211 + 'days' => 14,
  212 + ],
206 ], 213 ],
207 //操作日志 214 //操作日志
208 'operator_log' =>[ 215 'operator_log' =>[
@@ -66,6 +66,7 @@ Route::any('get_monitor_keyword', [\App\Http\Controllers\Api\PrivateController:: @@ -66,6 +66,7 @@ Route::any('get_monitor_keyword', [\App\Http\Controllers\Api\PrivateController::
66 Route::post('selfSiteApi', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteApi']); 66 Route::post('selfSiteApi', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteApi']);
67 Route::post('selfSiteNotify', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteNotify']); 67 Route::post('selfSiteNotify', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteNotify']);
68 Route::post('selfSiteVerify', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteVerify']); 68 Route::post('selfSiteVerify', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteVerify']);
  69 +Route::post('selfSiteSsl', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteSsl']);
69 70
70 //创建301跳转任务 71 //创建301跳转任务
71 Route::any('/addRedirect',[\App\Http\Controllers\Api\NoticeController::class,'addRedirect']); 72 Route::any('/addRedirect',[\App\Http\Controllers\Api\NoticeController::class,'addRedirect']);
@@ -253,6 +253,7 @@ Route::middleware(['aloginauth'])->group(function () { @@ -253,6 +253,7 @@ Route::middleware(['aloginauth'])->group(function () {
253 // 售后工单改版 253 // 售后工单改版
254 Route::prefix('tickets')->group(function () { 254 Route::prefix('tickets')->group(function () {
255 Route::get('/', [Aside\WorkOrder\AsideTicketController::class, 'index'])->name('admin.tickets.index')->summary('A端工单列表'); 255 Route::get('/', [Aside\WorkOrder\AsideTicketController::class, 'index'])->name('admin.tickets.index')->summary('A端工单列表');
  256 + Route::post('/lists', [Aside\WorkOrder\AsideTicketController::class, 'lists'])->name('admin.tickets.lists')->summary('A端工单列表2');
256 Route::post('/', [Aside\WorkOrder\AsideTicketController::class, 'store'])->name('admin.tickets.store')->summary('A端创建工单'); 257 Route::post('/', [Aside\WorkOrder\AsideTicketController::class, 'store'])->name('admin.tickets.store')->summary('A端创建工单');
257 Route::get('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'show'])->name('admin.tickets.show')->summary('A端工单详情'); 258 Route::get('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'show'])->name('admin.tickets.show')->summary('A端工单详情');
258 Route::post('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'update'])->name('admin.tickets.update')->summary('A端更新工单,审核,邀请同事'); 259 Route::post('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'update'])->name('admin.tickets.update')->summary('A端更新工单,审核,邀请同事');
@@ -636,6 +637,10 @@ Route::middleware(['aloginauth'])->group(function () { @@ -636,6 +637,10 @@ Route::middleware(['aloginauth'])->group(function () {
636 //ticket 637 //ticket
637 Route::prefix('ticket_count')->group(function () { 638 Route::prefix('ticket_count')->group(function () {
638 Route::any('/ticketCount', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'ticketCount'])->name('ticket_count_ticketCount'); 639 Route::any('/ticketCount', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'ticketCount'])->name('ticket_count_ticketCount');
  640 + Route::any('/getMonthList', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'getMonthList'])->name('ticket_count_getMonthList');//获取最近一个总统计的数据
  641 + Route::any('/getTime', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'getTime'])->name('ticket_count_getTime');//获取周/月时间
  642 + Route::any('/weekManageList', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'weekManageList'])->name('ticket_count_weekManageList');//周统计数据
  643 + Route::any('/monthManageList', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'monthManageList'])->name('ticket_count_monthManageList');//月统计数据
639 Route::any('/manageTicketCount', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'manageTicketCount'])->name('ticket_count_manageTicketCount'); 644 Route::any('/manageTicketCount', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'manageTicketCount'])->name('ticket_count_manageTicketCount');
640 }); 645 });
641 }); 646 });