Merge remote-tracking branch 'origin/master' into workorder
正在显示
47 个修改的文件
包含
3318 行增加
和
396 行删除
| @@ -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)) { |
| @@ -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 |
| @@ -43,7 +43,7 @@ class RemainDay extends Command | @@ -43,7 +43,7 @@ class RemainDay extends Command | ||
| 43 | * @var 暂停的项目 | 43 | * @var 暂停的项目 |
| 44 | */ | 44 | */ |
| 45 | protected $ceaseProjectId = [ | 45 | protected $ceaseProjectId = [ |
| 46 | - 354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250, 2193, 2399, 1685 | 46 | + 354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250, 2193, 2399, 1685, 3931 |
| 47 | ];//需要单独处理的项目 | 47 | ];//需要单独处理的项目 |
| 48 | /** | 48 | /** |
| 49 | * The console command description. | 49 | * The console command description. |
| @@ -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 | */ |
| 1 | +<?php | ||
| 2 | +/** | ||
| 3 | + * Created by PhpStorm. | ||
| 4 | + * User: zhl | ||
| 5 | + * Date: 2024/09/30 | ||
| 6 | + * Time: 11:51 | ||
| 7 | + */ | ||
| 8 | +namespace App\Console\Commands\Inquiry; | ||
| 9 | + | ||
| 10 | +use App\Helper\Common; | ||
| 11 | +use App\Helper\Gpt; | ||
| 12 | +use App\Helper\Translate; | ||
| 13 | +use App\Helper\Validate; | ||
| 14 | +use App\Models\Ai\AiCommand; | ||
| 15 | +use App\Models\Inquiry\ReInquiryConfig; | ||
| 16 | +use App\Models\Inquiry\ReInquiryDetail; | ||
| 17 | +use App\Models\Inquiry\ReInquiryDetailLog; | ||
| 18 | +use App\Models\Inquiry\ReInquiryForm; | ||
| 19 | +use App\Models\Inquiry\ReInquiryTask; | ||
| 20 | +use App\Models\Inquiry\ReInquiryText; | ||
| 21 | +use App\Models\Project\InquiryFilterConfig; | ||
| 22 | +use App\Models\Project\Project; | ||
| 23 | +use App\Models\WebSetting\WebLanguage; | ||
| 24 | +use Illuminate\Console\Command; | ||
| 25 | +use Illuminate\Support\Arr; | ||
| 26 | +use Illuminate\Support\Facades\Cache; | ||
| 27 | +use Illuminate\Support\Facades\DB; | ||
| 28 | +use Illuminate\Support\Facades\Http; | ||
| 29 | +use Illuminate\Support\Facades\Log; | ||
| 30 | +use Illuminate\Support\Str; | ||
| 31 | + | ||
| 32 | +/** | ||
| 33 | + * Class RelayInquiry | ||
| 34 | + * @package App\Console\Commands\Inquiry | ||
| 35 | + */ | ||
| 36 | +class RelayInquiryTest extends Command | ||
| 37 | +{ | ||
| 38 | + /** | ||
| 39 | + * The name and signature of the console command. | ||
| 40 | + * | ||
| 41 | + * @var string | ||
| 42 | + */ | ||
| 43 | + protected $signature = 'relay_inquiry_test'; | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * The console command description. | ||
| 47 | + * | ||
| 48 | + * @var string | ||
| 49 | + */ | ||
| 50 | + protected $description = '重启失败的转发询盘'; | ||
| 51 | + | ||
| 52 | + /** | ||
| 53 | + * Create a new command instance. | ||
| 54 | + * | ||
| 55 | + * @return void | ||
| 56 | + */ | ||
| 57 | + public function __construct() | ||
| 58 | + { | ||
| 59 | + parent::__construct(); | ||
| 60 | + } | ||
| 61 | + | ||
| 62 | + /** | ||
| 63 | + * 模拟访问来源占比 | ||
| 64 | + * @var array | ||
| 65 | + */ | ||
| 66 | + protected $lyzb = [ | ||
| 67 | + 'https://www.google.com/' => 630, | ||
| 68 | + 'http://www.google.com/' => 30, | ||
| 69 | + 'http://www.bing.com/' => 20, | ||
| 70 | + 'https://www.bing.com/' => 5, | ||
| 71 | + 'https://www.youtube.com/' => 5, | ||
| 72 | + 'https://search.yahoo.com/' => 5, | ||
| 73 | + 'https://www.facebook.com/' => 5, | ||
| 74 | + ]; | ||
| 75 | + | ||
| 76 | + /** | ||
| 77 | + * 俄语站 模拟访问来源占比 | ||
| 78 | + * @var array | ||
| 79 | + */ | ||
| 80 | + protected $eylyzb = [ | ||
| 81 | + 'https://www.yandex.com/' => 630, | ||
| 82 | + 'https://www.google.com/' => 30, | ||
| 83 | + 'http://www.google.com/' => 30, | ||
| 84 | + 'http://www.bing.com/' => 20, | ||
| 85 | + 'https://www.bing.com/' => 5, | ||
| 86 | + 'https://www.youtube.com/' => 5, | ||
| 87 | + 'https://search.yahoo.com/' => 5, | ||
| 88 | + 'https://www.facebook.com/' => 5, | ||
| 89 | + ]; | ||
| 90 | + | ||
| 91 | + /** | ||
| 92 | + * PC端访问头信息 | ||
| 93 | + * @var array | ||
| 94 | + */ | ||
| 95 | + protected $pc_ua = [ | ||
| 96 | + 0 => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11', | ||
| 97 | + 1 => 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36', | ||
| 98 | + 2 => 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1' | ||
| 99 | + ]; | ||
| 100 | + | ||
| 101 | + /** | ||
| 102 | + * 移动端访问头信息 | ||
| 103 | + * @var array | ||
| 104 | + */ | ||
| 105 | + protected $mobile_ua = [ | ||
| 106 | + 0 => 'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko; googleweblight) Chrome/38.0.1025.166 Mobile Safari/535.19', | ||
| 107 | + ]; | ||
| 108 | + | ||
| 109 | + /** | ||
| 110 | + * google域名后缀 | ||
| 111 | + * @var string[] | ||
| 112 | + */ | ||
| 113 | + protected $suffix = [ | ||
| 114 | + 'co.jp' => '日本', | ||
| 115 | + 'com.tr' => '土耳其', | ||
| 116 | + 'nl' => '荷兰', | ||
| 117 | + 'ru' => '俄罗斯', | ||
| 118 | + 'fr' => '法国', | ||
| 119 | + 'co.kr' => '韩国', | ||
| 120 | + 'fi' => '芬兰', | ||
| 121 | + 'be' => '比利时', | ||
| 122 | + 'lt' => '立陶宛', | ||
| 123 | + 'es' => '西班牙', | ||
| 124 | + 'it' => '意大利', | ||
| 125 | + 'com.au' => '澳大利亚', | ||
| 126 | + 'no' => '挪威', | ||
| 127 | + 'al' => '阿尔巴尼亚', | ||
| 128 | + 'pt' => '葡萄牙', | ||
| 129 | + 'lv' => '拉脱维亚', | ||
| 130 | + 'hu' => '匈牙利', | ||
| 131 | + 'cz' => '捷克', | ||
| 132 | + 'de' => '德国', | ||
| 133 | + 'ca' => '加拿大', | ||
| 134 | + 'co.in' => '印度', | ||
| 135 | + 'co.uk' => '英国', | ||
| 136 | + 'com.vn' => '越南', | ||
| 137 | + 'com.br' => '巴西', | ||
| 138 | + 'co.il' => '以色列', | ||
| 139 | + 'pl' => '波兰', | ||
| 140 | + 'com.eg' => '埃及', | ||
| 141 | + 'co.th' => '泰国', | ||
| 142 | + 'sk' => '斯洛伐克', | ||
| 143 | + 'ro' => '罗马尼亚', | ||
| 144 | + 'com.mx' => '墨西哥', | ||
| 145 | + 'com.my' => '马来西亚', | ||
| 146 | + 'com.pk' => '巴基斯坦', | ||
| 147 | + 'co.nz' => '新西兰', | ||
| 148 | + 'co.za' => '南非', | ||
| 149 | + 'com.ar' => '阿根廷', | ||
| 150 | + 'com.kw' => '科威特', | ||
| 151 | + 'com.sg' => '新加坡', | ||
| 152 | + 'com.co' => '哥伦比亚', | ||
| 153 | + 'co.id' => '印度尼西亚', | ||
| 154 | + 'gr' => '希腊', | ||
| 155 | + 'bg' => '保加利亚', | ||
| 156 | + 'mn' => '蒙古', | ||
| 157 | + 'dk' => '丹麦', | ||
| 158 | + 'com.sa' => '沙特阿拉伯', | ||
| 159 | + 'com.pe' => '秘鲁', | ||
| 160 | + 'com.ph' => '菲律宾', | ||
| 161 | + 'com.ua' => '乌克兰', | ||
| 162 | + 'ge' => '格鲁吉亚', | ||
| 163 | + 'ae' => '阿拉伯联合酋长国', | ||
| 164 | + 'tn' => '突尼斯', | ||
| 165 | + ]; | ||
| 166 | + | ||
| 167 | + protected $otherzb = [700, 300]; //模拟访问来源占比 (非美国) google.com|google.其他后缀 | ||
| 168 | + | ||
| 169 | + /** | ||
| 170 | + * 手机号过滤 0去掉+ 1不转发手机 2不处理 | ||
| 171 | + * @var int[] | ||
| 172 | + */ | ||
| 173 | + protected $filter_phone = [30,12,58]; | ||
| 174 | + | ||
| 175 | + /** | ||
| 176 | + * 需要多个ip访问的国家 | ||
| 177 | + * @var | ||
| 178 | + */ | ||
| 179 | + protected $multiple_ip_visit_country = [ | ||
| 180 | + '阿尔及利亚', | ||
| 181 | + '埃及', | ||
| 182 | + '埃塞俄比亚', | ||
| 183 | + '安哥拉', | ||
| 184 | + '贝宁', | ||
| 185 | + '博茨瓦纳', | ||
| 186 | + '布基纳法索', | ||
| 187 | + '布隆迪', | ||
| 188 | + '赤道几内亚', | ||
| 189 | + '多哥', | ||
| 190 | + '厄立特里亚', | ||
| 191 | + '佛得角', | ||
| 192 | + '冈比亚', | ||
| 193 | + '刚果共和国', | ||
| 194 | + '刚果民主共和国', | ||
| 195 | + '吉布提', | ||
| 196 | + '几内亚', | ||
| 197 | + '几内亚比绍共和国', | ||
| 198 | + '加纳', | ||
| 199 | + '加蓬', | ||
| 200 | + '津巴布韦', | ||
| 201 | + '喀麦隆', | ||
| 202 | + '科摩罗', | ||
| 203 | + '科特迪瓦', | ||
| 204 | + '肯尼亚', | ||
| 205 | + '莱索托', | ||
| 206 | + '利比里亚', | ||
| 207 | + '利比亞', | ||
| 208 | + '留尼汪', | ||
| 209 | + '卢旺达', | ||
| 210 | + '马达加斯加', | ||
| 211 | + '马拉维', | ||
| 212 | + '马里', | ||
| 213 | + '马约特', | ||
| 214 | + '毛里求斯', | ||
| 215 | + '毛里塔尼亚', | ||
| 216 | + '摩洛哥', | ||
| 217 | + '莫桑比克', | ||
| 218 | + '纳米比亚', | ||
| 219 | + '南非', | ||
| 220 | + '南苏丹', | ||
| 221 | + '尼日尔', | ||
| 222 | + '尼日利亚', | ||
| 223 | + '塞拉利昂', | ||
| 224 | + '塞内加尔', | ||
| 225 | + '塞舌尔', | ||
| 226 | + '圣多美和普林西比', | ||
| 227 | + '圣赫勒拿', | ||
| 228 | + '斯威士兰', | ||
| 229 | + '索马里', | ||
| 230 | + '坦桑尼亚', | ||
| 231 | + '突尼斯', | ||
| 232 | + '乌干达', | ||
| 233 | + '西撒哈拉', | ||
| 234 | + '赞比亚', | ||
| 235 | + '乍得', | ||
| 236 | + '中非共和国', | ||
| 237 | + '阿富汗', | ||
| 238 | + '阿联酋', | ||
| 239 | + '阿曼', | ||
| 240 | + '阿塞拜疆', | ||
| 241 | + '澳门', | ||
| 242 | + '巴基斯坦', | ||
| 243 | + '巴勒斯坦', | ||
| 244 | + '巴林', | ||
| 245 | + '不丹', | ||
| 246 | + '东帝汶', | ||
| 247 | + '菲律宾', | ||
| 248 | + '格鲁吉亚', | ||
| 249 | + '哈萨克斯坦', | ||
| 250 | + '韩国', | ||
| 251 | + '吉尔吉斯斯坦', | ||
| 252 | + '柬埔寨', | ||
| 253 | + '卡塔尔', | ||
| 254 | + '科威特', | ||
| 255 | + '老挝', | ||
| 256 | + '黎巴嫩', | ||
| 257 | + '马尔代夫', | ||
| 258 | + '马来西亚', | ||
| 259 | + '蒙古', | ||
| 260 | + '孟加拉国', | ||
| 261 | + '缅甸', | ||
| 262 | + '尼泊尔', | ||
| 263 | + '日本', | ||
| 264 | + '塞浦路斯', | ||
| 265 | + '沙特阿拉伯', | ||
| 266 | + '斯里兰卡', | ||
| 267 | + '塔吉克斯坦', | ||
| 268 | + '泰国', | ||
| 269 | + '土耳其', | ||
| 270 | + '土库曼斯坦', | ||
| 271 | + '文莱', | ||
| 272 | + '乌兹别克斯坦', | ||
| 273 | + '新加坡', | ||
| 274 | + '亚美尼亚', | ||
| 275 | + '也门', | ||
| 276 | + '伊拉克', | ||
| 277 | + '以色列', | ||
| 278 | + '印度尼西亚', | ||
| 279 | + '约旦', | ||
| 280 | + '越南', | ||
| 281 | + ]; | ||
| 282 | + | ||
| 283 | + /** | ||
| 284 | + * @return bool | ||
| 285 | + */ | ||
| 286 | + public function handle() | ||
| 287 | + { | ||
| 288 | + while (true) { | ||
| 289 | + $inquiry = ReInquiryForm::where('created_at', '>', '2025-05-19 00:00:00') | ||
| 290 | + ->where('created_at', '<', '2025-05-22 18:00:00') | ||
| 291 | + ->where(['status' => ReInquiryForm::STATUS_FORGO]) | ||
| 292 | + ->where('remark', '超时72小时未处理!') | ||
| 293 | + ->orderBy('id', 'asc')->get(); | ||
| 294 | + | ||
| 295 | + if ($inquiry->isEmpty()){ | ||
| 296 | + $this->output('未发现待处理询盘!'); | ||
| 297 | + sleep(60); | ||
| 298 | + continue; | ||
| 299 | + } | ||
| 300 | + | ||
| 301 | + $this->output('开始处理本轮询盘!'); | ||
| 302 | + foreach ($inquiry as $key=>$val) { | ||
| 303 | + $this->output('询盘ID:' . $val->id); | ||
| 304 | + | ||
| 305 | + | ||
| 306 | + $detail_ids = ReInquiryDetail::where('form_id', $val->id)->pluck('id')->toArray(); | ||
| 307 | + | ||
| 308 | + $inquiry_log = ReInquiryDetailLog::whereIn('detail_id', $detail_ids)->where('type', ReInquiryDetailLog::TYPE_INQUIRY)->first(); | ||
| 309 | + //有询盘的了 就跳过 | ||
| 310 | + if($inquiry_log){ | ||
| 311 | + continue; | ||
| 312 | + } | ||
| 313 | + | ||
| 314 | + // 询盘对应广告 | ||
| 315 | + $ad_task = $this->getAdTask($val->ad_id); | ||
| 316 | + // 没有获取到转发任务 | ||
| 317 | + if (empty($ad_task)) { | ||
| 318 | + $val->status = ReInquiryForm::STATUS_FORGO; | ||
| 319 | + $val->remark = '未找到需要转发的广告任务!'; | ||
| 320 | + $val->save(); | ||
| 321 | + continue; | ||
| 322 | + } | ||
| 323 | + // 未设置对法对象 | ||
| 324 | + $target_num_arr = array_map(function ($item) { | ||
| 325 | + return count($item['target']) + count($item['shop_site']) + count($item['fob_pro']); | ||
| 326 | + }, $ad_task); | ||
| 327 | + if (!array_sum($target_num_arr)) { | ||
| 328 | + $val->status = ReInquiryForm::STATUS_FORGO; | ||
| 329 | + $val->remark = '广告任务转发对象为空!'; | ||
| 330 | + $val->save(); | ||
| 331 | + continue; | ||
| 332 | + } | ||
| 333 | + //是否要过滤 | ||
| 334 | + $filter_res = $this->filter($val); | ||
| 335 | + if($filter_res !== true){ | ||
| 336 | + $val->status = ReInquiryForm::STATUS_FORGO; | ||
| 337 | + $val->remark = $filter_res; | ||
| 338 | + $val->save(); | ||
| 339 | + continue; | ||
| 340 | + } | ||
| 341 | + //验证手机号 无效 号码不推送 | ||
| 342 | + if(!Validate::phone($val->phone)){ | ||
| 343 | + $val->phone = ''; | ||
| 344 | + } | ||
| 345 | + try { | ||
| 346 | + $res = false; | ||
| 347 | + foreach ($ad_task as $task){ | ||
| 348 | + $res += $this->relayDetail($task, $val); | ||
| 349 | + $res += $this->relayShopDetail($task, $val); | ||
| 350 | + $res += $this->relayFobDetail($task, $val); | ||
| 351 | + } | ||
| 352 | + $val->status = $res ? ReInquiryForm::STATUS_SUCCESS : ReInquiryForm::STATUS_FORGO; | ||
| 353 | + $val->save(); | ||
| 354 | + } catch (\Exception $e) { | ||
| 355 | + $this->logChannel()->info('执行询盘错误:',[$e->getMessage(), $e->getFile(), $e->getLine()]); | ||
| 356 | + $this->output('执行询盘错误:' . $e->getMessage()); | ||
| 357 | + } | ||
| 358 | + } | ||
| 359 | + $this->output('本轮询盘处理结束!'); | ||
| 360 | + } | ||
| 361 | + return true; | ||
| 362 | + } | ||
| 363 | + | ||
| 364 | + | ||
| 365 | + public function filter($data) | ||
| 366 | + { | ||
| 367 | + //通用过滤规则 | ||
| 368 | + $config = InquiryFilterConfig::getCacheInfoByProjectId(Project::DEMO_PROJECT_ID); | ||
| 369 | + //FB询盘的全局过滤规则 | ||
| 370 | + $fb_config = ReInquiryConfig::getDefaultConfigCache(ReInquiryConfig::TYPE_FILTER_WORDS); | ||
| 371 | + | ||
| 372 | + $fb_config['filter_contents'] = array_filter(explode("\r\n", $fb_config['filter_contents']??'')); | ||
| 373 | + $fb_config['filter_emails'] = array_filter(explode("\r\n", $fb_config['filter_emails']??'')); | ||
| 374 | + $fb_config['filter_mobiles'] = array_filter(explode("\r\n", $fb_config['filter_mobiles']??'')); | ||
| 375 | + $fb_config['filter_names'] = array_filter(explode("\r\n", $fb_config['filter_names']??'')); | ||
| 376 | + | ||
| 377 | + $config['filter_contents'] = array_unique(array_merge($fb_config['filter_contents'],$config['filter_contents'])); | ||
| 378 | + $config['filter_emails'] = array_unique(array_merge($fb_config['filter_emails'],$config['filter_emails'])); | ||
| 379 | + $config['filter_mobiles'] = array_unique(array_merge($fb_config['filter_mobiles'],$config['filter_mobiles'])); | ||
| 380 | + $config['filter_names'] = array_unique(array_merge($fb_config['filter_names'],$config['filter_names'])); | ||
| 381 | + | ||
| 382 | + //过滤内容 | ||
| 383 | + if(!empty($data['message']) && !empty($config['filter_contents'])) { | ||
| 384 | + foreach ($config['filter_contents'] as $filter_content) { | ||
| 385 | + if (Str::contains(strtolower($data['message']), strtolower($filter_content))) { | ||
| 386 | + return '过滤内容:' . $filter_content; | ||
| 387 | + } | ||
| 388 | + } | ||
| 389 | + } | ||
| 390 | + //过滤邮箱 | ||
| 391 | + if(!empty($data['email']) && !empty($config['filter_emails'])){ | ||
| 392 | + foreach ($config['filter_emails'] as $filter_email){ | ||
| 393 | + if(Str::contains(strtolower($data['email']), strtolower($filter_email))){ | ||
| 394 | + return '过滤邮箱:' . $filter_email; | ||
| 395 | + } | ||
| 396 | + } | ||
| 397 | + //邮箱有效性 | ||
| 398 | + if(!Validate::email($data['email'])){ | ||
| 399 | + return '邮箱无效'; | ||
| 400 | + } | ||
| 401 | + } | ||
| 402 | + //过滤电话 | ||
| 403 | + if(!empty($data['phone']) && !empty($config['filter_mobiles'])){ | ||
| 404 | + foreach ($config['filter_mobiles'] as $filter_mobile){ | ||
| 405 | + if(Str::contains(strtolower($data['phone']), strtolower($filter_mobile))){ | ||
| 406 | + return '过滤电话:' . $filter_mobile; | ||
| 407 | + } | ||
| 408 | + } | ||
| 409 | + } | ||
| 410 | + //过滤姓名 | ||
| 411 | + if(!empty($data['full_name'] && !empty($config['filter_names']))){ | ||
| 412 | + foreach ($config['filter_names'] as $filter_name){ | ||
| 413 | + if(Str::contains(strtolower($data['full_name']), strtolower($filter_name))){ | ||
| 414 | + return '过滤姓名:' . $filter_name; | ||
| 415 | + } | ||
| 416 | + } | ||
| 417 | + } | ||
| 418 | + return true; | ||
| 419 | + } | ||
| 420 | + | ||
| 421 | + /** | ||
| 422 | + * 创建转发详情 | ||
| 423 | + * TODO 通过任务生成转发对象, 更具转发对象获取对应数据, 写入着陆记录 | ||
| 424 | + * @param $task | ||
| 425 | + * @param $form | ||
| 426 | + * @return bool | ||
| 427 | + */ | ||
| 428 | + public function relayDetail($task, $form) | ||
| 429 | + { | ||
| 430 | + $this->output('获取转发对象'); | ||
| 431 | + if(empty($task['target'] )){ | ||
| 432 | + $this->output('没有独立站转发对象'); | ||
| 433 | + return 0; | ||
| 434 | + } | ||
| 435 | + //是否有必选的渠道 渠道有一个及以上必选 就在组内随机一个 | ||
| 436 | + $require_agent_group = []; | ||
| 437 | + foreach ($task['target'] as $item) { | ||
| 438 | + if (!empty($item['is_require'])) { | ||
| 439 | + $require_agent_group[] = $item['agent_group']; | ||
| 440 | + } | ||
| 441 | + } | ||
| 442 | + $require_agent_group = array_unique($require_agent_group); | ||
| 443 | + $require_agent_group_data = collect($task['target'])->whereIn('agent_group', $require_agent_group)->groupBy('agent_group'); | ||
| 444 | + $require_data = $require_agent_group_data->keys()->random(count($require_agent_group))->map(function ($group) use ($require_agent_group_data) { | ||
| 445 | + return $require_agent_group_data[$group]->random(); | ||
| 446 | + })->all(); | ||
| 447 | + //代理商组 一个组只发一个 | ||
| 448 | + $agent_group = collect($task['target'])->whereNotIn('agent_group', $require_agent_group)->groupBy('agent_group'); | ||
| 449 | + // 获取转发对象 重置num数量, array_rand数量不足会报错 | ||
| 450 | + $task['num'] = $task['num'] - count($require_agent_group); | ||
| 451 | + $num = $task['num'] > count($agent_group) ? count($agent_group) : $task['num']; | ||
| 452 | + $random_data = $agent_group->keys()->random($num)->map(function ($group) use ($agent_group) { | ||
| 453 | + return $agent_group[$group]->random(); | ||
| 454 | + })->all(); | ||
| 455 | + $random_data = array_merge($require_data, $random_data); | ||
| 456 | + | ||
| 457 | + if (empty($random_data)) { | ||
| 458 | + $this->logChannel()->info('当前任务未发现转发对象!', ['广告任务ID:' . $task['id'], '询盘ID:' . $form->id]); | ||
| 459 | + $form->remark = $form->remark . '当前任务未发现转发对象,广告ID: ' . $form->ad_id . '!'; | ||
| 460 | + return false; | ||
| 461 | + } | ||
| 462 | + $this->logChannel()->info('随机域名', array_column($random_data, 'url')); | ||
| 463 | + foreach ($random_data as $item) { | ||
| 464 | + $times = 1; | ||
| 465 | + $inquiry_time = 1; | ||
| 466 | + | ||
| 467 | + //需要多个ip访问的国家 随机2-5次访问,只有一次询盘 | ||
| 468 | + if (in_array($form->country_name, $this->multiple_ip_visit_country)) { | ||
| 469 | + $times = mt_rand(1, 2); //随机次数 | ||
| 470 | + $inquiry_time = mt_rand(1, $times); //第几次询盘 | ||
| 471 | + $this->output('多次访问模拟:' . $times .',第' . $inquiry_time . '次询盘'); | ||
| 472 | + } | ||
| 473 | + for ($i = 1; $i <= $times; $i++) { | ||
| 474 | + $is_inquiry = ($inquiry_time == $i); | ||
| 475 | + if($is_inquiry){ | ||
| 476 | + $this->output('第' . $i . '次询盘'); | ||
| 477 | + } | ||
| 478 | + //手机号过滤 | ||
| 479 | + $phone = $form->phone; | ||
| 480 | + $filter_phone = $this->get_rand($this->filter_phone); | ||
| 481 | + if($filter_phone == 0){ | ||
| 482 | + $phone = trim(str_replace("+", '', $phone)); | ||
| 483 | + }elseif($filter_phone == 1){ | ||
| 484 | + $phone = ''; | ||
| 485 | + } | ||
| 486 | + | ||
| 487 | + // 推送站点 | ||
| 488 | + $domain = $item['url']; | ||
| 489 | + $is_v6 = $item['is_v6']; | ||
| 490 | + $re_website = 'https://' . $domain . '/'; | ||
| 491 | + | ||
| 492 | + //urls | ||
| 493 | + list($urls, $lang, $inquiry_product_url) = $this->getUrls($is_v6, $domain, $re_website, $form, $task); | ||
| 494 | + if(!$urls){ | ||
| 495 | + continue; | ||
| 496 | + } | ||
| 497 | + | ||
| 498 | + //ip | ||
| 499 | + $ip_data = $this->getIpData($form->country_name); | ||
| 500 | + $ip = $ip_data->ip; | ||
| 501 | + $country_name = $ip_data->ip_area; | ||
| 502 | + | ||
| 503 | + //message | ||
| 504 | + $message = ''; | ||
| 505 | + $message_id = 0; | ||
| 506 | + $msg_lang = ''; | ||
| 507 | + if($is_inquiry) { | ||
| 508 | + list($message, $message_id, $msg_lang) = $this->getMessage($task, $form->message, $domain, $inquiry_product_url); | ||
| 509 | + } | ||
| 510 | + $lang = $lang ?: $msg_lang; | ||
| 511 | + | ||
| 512 | + $this->output('获取转发设备信息'); | ||
| 513 | + // 客户端 头信息 来源 | ||
| 514 | + $device_port = $form->email ? '1' : '2'; //1 pc 2移动端 | ||
| 515 | + $user_agent = $form->email ? Arr::random($this->pc_ua) : Arr::random($this->mobile_ua); | ||
| 516 | + $referrer = $this->getReferer($country_name, $lang); | ||
| 517 | + $this->output('写入数据'); | ||
| 518 | + | ||
| 519 | + $pre = 0; | ||
| 520 | + $start_time = strtotime($form->inquiry_date); | ||
| 521 | + if($start_time < time()){ | ||
| 522 | + $start_time = time(); | ||
| 523 | + $seconds = rand(0, 72 * 3600); // 3天内发完 | ||
| 524 | + }else{ | ||
| 525 | + $seconds = rand(100, 2 * 3600); | ||
| 526 | + } | ||
| 527 | + $email = ''; | ||
| 528 | + if($is_inquiry) { | ||
| 529 | + $exists = ReInquiryDetail::where('re_website', $domain)->where('email', $form->email)->first(); | ||
| 530 | + if ($exists) { | ||
| 531 | + $this->output('转发站点邮件已存在'); | ||
| 532 | + // continue; | ||
| 533 | + } | ||
| 534 | + $email = $form->email; | ||
| 535 | + } | ||
| 536 | + dump(date('Y-m-d H:i:s', $start_time + $seconds)); | ||
| 537 | + // 写入推送详情 | ||
| 538 | + $re_detail = ReInquiryDetail::createInquiry($task['id'], $form->id, $domain, $country_name, $ip, $form->full_name, $email, $phone, $message, $message_id, $device_port, | ||
| 539 | + $user_agent, $referrer, $urls, $is_v6, date('Y-m-d H:i:s', $start_time + $seconds)); | ||
| 540 | + foreach ($urls as $k=>$v){ | ||
| 541 | + $pre++; | ||
| 542 | + $seconds += rand(5,60); | ||
| 543 | + ReInquiryDetailLog::createInquiryLog($re_detail->id, ReInquiryDetailLog::TYPE_VISIT, $pre, $v, date('Y-m-d H:i:s', $start_time + $seconds)); | ||
| 544 | + // 最后一次访问询盘 加上询盘 | ||
| 545 | + if($is_inquiry && ($k+1) == count($urls)){ | ||
| 546 | + $this->output('第' . ($k+1) . '个链接询盘'); | ||
| 547 | + $seconds += rand(30,120); | ||
| 548 | + $pre++; | ||
| 549 | + ReInquiryDetailLog::createInquiryLog($re_detail->id, ReInquiryDetailLog::TYPE_INQUIRY, $pre, $v, date('Y-m-d H:i:s', $start_time + $seconds)); | ||
| 550 | + } | ||
| 551 | + } | ||
| 552 | + } | ||
| 553 | + } | ||
| 554 | + return true; | ||
| 555 | + } | ||
| 556 | + | ||
| 557 | + public function relayShopDetail($task, $form) | ||
| 558 | + { | ||
| 559 | + $this->output('获取商城转发对象'); | ||
| 560 | + | ||
| 561 | + if(empty($task['shop_site'])){ | ||
| 562 | + $this->output('没有商城转发对象'); | ||
| 563 | + return 0; | ||
| 564 | + } | ||
| 565 | + | ||
| 566 | + $num = $task['num'] > count($task['shop_site']) ? count($task['shop_site']) : $task['num']; | ||
| 567 | + $shop_site = collect($task['shop_site'])->random($num)->all(); | ||
| 568 | + | ||
| 569 | + foreach ($shop_site as $item) { | ||
| 570 | + //手机号过滤 | ||
| 571 | + $phone = $form->phone; | ||
| 572 | + // 推送站点 | ||
| 573 | + $domain = $item; | ||
| 574 | + $re_website = 'https://' . $domain . '/'; | ||
| 575 | + $paths = ['', 'contact-us']; | ||
| 576 | + $url = $re_website . $paths[array_rand($paths)]; | ||
| 577 | + //ip | ||
| 578 | + $ip_data = $this->getIpData($form->country_name); | ||
| 579 | + $ip = $ip_data->ip; | ||
| 580 | + $country_name = $ip_data->ip_area; | ||
| 581 | + | ||
| 582 | + //message | ||
| 583 | + list($message, $message_id, $lang) = $this->getMessage($task, $form->message, $domain); | ||
| 584 | + | ||
| 585 | + $device_port = $form->email ? '1' : '2'; //1 pc 2移动端 | ||
| 586 | + $user_agent = $form->email ? Arr::random($this->pc_ua) : Arr::random($this->mobile_ua); | ||
| 587 | + $referrer = $this->getReferer($country_name, $lang); | ||
| 588 | + | ||
| 589 | + $start_time = strtotime($form->inquiry_date); | ||
| 590 | + if($start_time < time()){ | ||
| 591 | + $start_time = time(); | ||
| 592 | + $seconds = rand(0, 48 * 3600); // 开始时间 从5-2小时后开始 | ||
| 593 | + }else{ | ||
| 594 | + $seconds = rand(100, 2 * 3600); | ||
| 595 | + } | ||
| 596 | + dump(date('Y-m-d H:i:s', $start_time + $seconds)); | ||
| 597 | + $exists = ReInquiryDetail::where('re_website', $domain)->where('email', $form->email)->first(); | ||
| 598 | + if($exists){ | ||
| 599 | + $this->output('转发站点邮件已存在'); | ||
| 600 | + continue; | ||
| 601 | + } | ||
| 602 | + $re_detail = ReInquiryDetail::createInquiry($task['id'], $form->id, $domain, $country_name, $ip, $form->full_name, $form->email, $phone, $message, $message_id, | ||
| 603 | + $device_port, $user_agent, $referrer, [$url], 0, date('Y-m-d H:i:s', $start_time + $seconds), ReInquiryDetail::STATUS_INIT, 2); | ||
| 604 | + | ||
| 605 | + ReInquiryDetailLog::createInquiryLog($re_detail->id, ReInquiryDetailLog::TYPE_INQUIRY, 1, $url, date('Y-m-d H:i:s', $start_time + $seconds)); | ||
| 606 | + } | ||
| 607 | + return true; | ||
| 608 | + } | ||
| 609 | + | ||
| 610 | + | ||
| 611 | + public function relayFobDetail($task, $form) | ||
| 612 | + { | ||
| 613 | + $this->output('获取FOB转发对象'); | ||
| 614 | + | ||
| 615 | + if(empty($task['fob_pro'])){ | ||
| 616 | + $this->output('没有FOB转发对象'); | ||
| 617 | + return 0; | ||
| 618 | + } | ||
| 619 | + | ||
| 620 | + foreach ($task['fob_pro'] as $item) { | ||
| 621 | + //手机号过滤 | ||
| 622 | + $phone = $form->phone; | ||
| 623 | + // 推送站点 | ||
| 624 | + $postid = $item; | ||
| 625 | + //message | ||
| 626 | + list($message, $message_id, $lang) = $this->getMessage($task, $form->message, $postid); | ||
| 627 | + | ||
| 628 | + $device_port = $form->email ? '1' : '2'; //1 pc 2移动端 | ||
| 629 | + $user_agent = $form->email ? Arr::random($this->pc_ua) : Arr::random($this->mobile_ua); | ||
| 630 | + | ||
| 631 | + $start_time = strtotime($form->inquiry_date); | ||
| 632 | + if($start_time < time()){ | ||
| 633 | + $start_time = time(); | ||
| 634 | + $seconds = rand(0, 10 * 3600); // 开始时间 从5-2小时后开始 | ||
| 635 | + }else{ | ||
| 636 | + $seconds = rand(100, 2 * 3600); | ||
| 637 | + } | ||
| 638 | + dump(date('Y-m-d H:i:s', $start_time + $seconds)); | ||
| 639 | + $exists = ReInquiryDetail::where('re_website', $postid)->where('email', $form->email)->first(); | ||
| 640 | + if($exists){ | ||
| 641 | + $this->output('转发站点邮件已存在'); | ||
| 642 | + continue; | ||
| 643 | + } | ||
| 644 | + $re_detail = ReInquiryDetail::createInquiry($task['id'], $form->id, $postid, $country_name??'', $ip??'', $form->full_name, $form->email, $phone, | ||
| 645 | + $message, $message_id, $device_port, $user_agent, $referrer??'', [$postid], 0, date('Y-m-d H:i:s', $start_time + $seconds), ReInquiryDetail::STATUS_INIT, 3); | ||
| 646 | + | ||
| 647 | + ReInquiryDetailLog::createInquiryLog($re_detail->id, ReInquiryDetailLog::TYPE_INQUIRY, 1, $postid, date('Y-m-d H:i:s', $start_time + $seconds)); | ||
| 648 | + } | ||
| 649 | + return true; | ||
| 650 | + } | ||
| 651 | + | ||
| 652 | + public function getIpData($country_name){ | ||
| 653 | + $this->output('获取转发ip'); | ||
| 654 | + $country = $country_name; | ||
| 655 | + // 有国家 通过国家查询, 如果没有获取到就随机获取 | ||
| 656 | + $where = []; | ||
| 657 | + $country && $where['ip_area'] = $country; | ||
| 658 | + $ip_data = DB::table('gl_xunpan_ipdata')->where($where)->inRandomOrder()->first(); | ||
| 659 | + if (empty($ip_data)) { | ||
| 660 | + $ip_data = DB::table('gl_xunpan_ipdata')->inRandomOrder()->first(); | ||
| 661 | + } | ||
| 662 | + return $ip_data; | ||
| 663 | + } | ||
| 664 | + | ||
| 665 | + public function getMessage($task, $message, $domain, $inquiry_product_url = ''){ | ||
| 666 | + $this->output('转发内容'); | ||
| 667 | + $form_message = $message; | ||
| 668 | + $message_id = 0; | ||
| 669 | + | ||
| 670 | + // TODO 当原始询盘内容长度大于15个字符, 60%几率直接发送原始内容。 | ||
| 671 | + if (strlen($message) >= 15) { | ||
| 672 | + $not_use_probability = AiCommand::where('key', 'fb_inquiry_text')->value('not_use_probability'); | ||
| 673 | + $randomNumber = rand(0, 100); | ||
| 674 | + if($randomNumber < $not_use_probability){ | ||
| 675 | + //原内容非英语,转为对应语种 | ||
| 676 | + if (is_numeric($form_message)) { //数字会被识别为中文 | ||
| 677 | + $lang = 'en'; | ||
| 678 | + } else { | ||
| 679 | + $translateSl = Translate::translateSl($form_message); | ||
| 680 | + $lang = $translateSl['texts']['sl'] ?? 'en'; | ||
| 681 | + } | ||
| 682 | + return [$message, $message_id, $lang??'']; | ||
| 683 | + } | ||
| 684 | + } | ||
| 685 | + | ||
| 686 | + //开启文案替换 | ||
| 687 | + if ($task['is_replace_text'] == 2) { | ||
| 688 | + //AI生成 | ||
| 689 | + $error = 0; | ||
| 690 | + while ($error<3){ | ||
| 691 | + $message = $this->ai_send($task['ai_param'], $message, $inquiry_product_url); | ||
| 692 | + if(!$message){ | ||
| 693 | + $this->output('AI文案生成失败'); | ||
| 694 | + $error++; | ||
| 695 | + if($error==2){ | ||
| 696 | + $task['is_replace_text'] = 1; | ||
| 697 | + $this->output('AI文案生成失败,使用文案库'); | ||
| 698 | + } | ||
| 699 | + }else{ | ||
| 700 | + break; | ||
| 701 | + } | ||
| 702 | + } | ||
| 703 | + } | ||
| 704 | + if ($task['is_replace_text'] == 1 || strlen($message) <= 4) { | ||
| 705 | + //配置文案库替换或者字符少于4个,直接替换文案 | ||
| 706 | + $use_ids = ReInquiryDetail::where(['re_website' => $domain])->where('status', '<>', ReInquiryDetail::STATUS_FAIL)->pluck('text_id')->toArray(); | ||
| 707 | + $text = ReInquiryText::whereNotIn('id', $use_ids)->where('status', ReInquiryText::STATUS_USABLE)->inRandomOrder()->first(); | ||
| 708 | + $message = $text->content; | ||
| 709 | + $message_id = $text->id; | ||
| 710 | + // 获取后,使用次数+1 | ||
| 711 | + $text->use_time += 1; | ||
| 712 | + $text->save(); | ||
| 713 | + | ||
| 714 | + //原内容非英语,转为对应语种 | ||
| 715 | + if (is_numeric($form_message)) { //数字会被识别为中文 | ||
| 716 | + $lang = 'en'; | ||
| 717 | + } else { | ||
| 718 | + $translateSl = Translate::translateSl($form_message); | ||
| 719 | + $lang = $translateSl['texts']['sl'] ?? 'en'; | ||
| 720 | + } | ||
| 721 | + | ||
| 722 | + if ($lang != 'en' && !Str::contains($lang, 'zh')) { | ||
| 723 | + $message = Translate::tran($message, $lang); | ||
| 724 | + } | ||
| 725 | + } | ||
| 726 | + return [$message, $message_id, $lang??'']; | ||
| 727 | + } | ||
| 728 | + | ||
| 729 | + public function getUrls($is_v6, $domain, $re_website, $form, $task){ | ||
| 730 | + $this->output('转发对象:' . $domain); | ||
| 731 | + $this->output('获取转发链接'); | ||
| 732 | + // v6:有邮箱推送主站,没有邮箱推送AMP站;v5:仅推送有邮箱到主站 | ||
| 733 | + $lang = ''; | ||
| 734 | + if ($is_v6) { | ||
| 735 | + // 获取语种, 6.0是可以确定语种的 | ||
| 736 | + $project = Project::getProjectByDomain($domain); | ||
| 737 | + if (empty($project)) { | ||
| 738 | + $this->logChannel()->info('广告任务ID:' . $task['id'] . ', 转发对象:' . $re_website . '非v6链接,转发失败;', ['广告任务ID:' . $task['id'], '询盘ID:' . $form->id]); | ||
| 739 | + return [[], $lang]; | ||
| 740 | + } | ||
| 741 | + $lang = WebLanguage::getLangById($project->main_lang_id ?? 1)['short']; | ||
| 742 | + | ||
| 743 | + // 获取访问明细和着陆页 | ||
| 744 | + $product_url = $this->getLinksFromSitemap($re_website . 'product_sitemap.xml'); | ||
| 745 | + $product_cate_url = $this->getLinksFromSitemap($re_website . 'product_category_sitemap.xml'); | ||
| 746 | + $keywords_url = $this->getLinksFromSitemap($re_website . 'product_keywords_sitemap.xml'); | ||
| 747 | + $page_url = $this->getLinksFromSitemap($re_website . 'page_sitemap.xml'); | ||
| 748 | + } else { | ||
| 749 | + if($form->email){ | ||
| 750 | + //通过sitemap拿访问页面 | ||
| 751 | + $product_url = $this->getLinksFromSitemap($re_website . 'sitemap_post.xml'); | ||
| 752 | + $product_cate_url = $this->getLinksFromSitemap($re_website . 'sitemap_category.xml'); | ||
| 753 | + $keywords_url = $this->getLinksFromSitemap($re_website . 'sitemap_post_tag.xml'); | ||
| 754 | + $page_url = $this->getLinksFromSitemap($re_website . 'sitemap_page.xml'); | ||
| 755 | + }else{ | ||
| 756 | + //m站先就往contact-us着陆 | ||
| 757 | + $product_url = $product_cate_url = $keywords_url = []; | ||
| 758 | + $page_url = [$re_website . 'contact-us/']; | ||
| 759 | + } | ||
| 760 | + } | ||
| 761 | + | ||
| 762 | + // 所有可用url | ||
| 763 | + $urls = $inquiry_urls = []; | ||
| 764 | + //入口url 首页30%,单页10%,聚合页60% | ||
| 765 | + $type = getRandByRatio([30,10,60]); | ||
| 766 | + $inlet = $re_website; | ||
| 767 | + $type == 1 && $inlet = $page_url ? Arr::random($page_url) : $re_website; | ||
| 768 | + $type == 2 && $inlet = $keywords_url ? Arr::random($keywords_url) : $re_website; | ||
| 769 | + $urls[] = $inquiry_urls[] = $inlet; | ||
| 770 | + $all_urls = array_merge($urls, $product_url, $product_cate_url, $keywords_url, $page_url); | ||
| 771 | + $inquiry_urls = array_merge($urls, $product_cate_url, $keywords_url, $page_url); | ||
| 772 | + | ||
| 773 | + // 随机访问1-6个页面 | ||
| 774 | + $deep = rand(1,6); | ||
| 775 | + if($deep > 2) { | ||
| 776 | + $visit_urls = Arr::random($all_urls, rand(1, count($all_urls) > 4 ? 4 : count($all_urls))); | ||
| 777 | + $urls = array_merge($urls, $visit_urls); | ||
| 778 | + } | ||
| 779 | + if($deep > 1) { | ||
| 780 | + // 推送着落页只能是 首页、产品分类、单页面、聚合页 | ||
| 781 | + if (!in_array(end($urls), $inquiry_urls)) { | ||
| 782 | + $urls[] = Arr::random($inquiry_urls); | ||
| 783 | + } | ||
| 784 | + } | ||
| 785 | + //着陆页是否是产品页面或产品列表页 | ||
| 786 | + $inquiry_product_url = ''; | ||
| 787 | + if(in_array(Arr::last($urls), $product_url) || in_array(Arr::last($urls), $product_cate_url)){ | ||
| 788 | + $inquiry_product_url = Arr::last($urls); | ||
| 789 | + } | ||
| 790 | + | ||
| 791 | + return [$urls, $lang, $inquiry_product_url]; | ||
| 792 | + } | ||
| 793 | + /** | ||
| 794 | + * 获取待处理询盘表单 | ||
| 795 | + * @param int $num | ||
| 796 | + * @return mixed | ||
| 797 | + */ | ||
| 798 | + public function getInquiry($num = 10) | ||
| 799 | + { | ||
| 800 | + $result = ReInquiryForm::where(['status' => ReInquiryForm::STATUS_INIT])->orderBy('id', 'asc')->limit($num)->get(); | ||
| 801 | + return $result; | ||
| 802 | + } | ||
| 803 | + | ||
| 804 | + /** | ||
| 805 | + * 获取广告任务配置数据 | ||
| 806 | + * @param $ad_id | ||
| 807 | + * @return array | ||
| 808 | + */ | ||
| 809 | + public function getAdTask($ad_id) | ||
| 810 | + { | ||
| 811 | + $cache_key = 'inquiry_ads_tasks'; | ||
| 812 | + $ads = Cache::get($cache_key, function () use ($cache_key) { | ||
| 813 | + $ads = ReInquiryTask::where(['status' => ReInquiryTask::STATUS_OPEN])->get(['id', 'ad_id', 'num', 'target', 'is_replace_text', 'ai_param', 'shop_site', 'fob_pro']); | ||
| 814 | + $array = []; | ||
| 815 | + foreach ($ads as $key=>$val) { | ||
| 816 | + $ad_ids = explode(',', $val['ad_id']); | ||
| 817 | + foreach ($ad_ids as $ad_id){ | ||
| 818 | + $array[$ad_id][] = $val; | ||
| 819 | + } | ||
| 820 | + } | ||
| 821 | + if ($array) | ||
| 822 | + Cache::put($cache_key, $array, 60); | ||
| 823 | + return $array; | ||
| 824 | + }); | ||
| 825 | + return empty($ads[$ad_id]) ? [] : $ads[$ad_id]; | ||
| 826 | + } | ||
| 827 | + | ||
| 828 | + /** | ||
| 829 | + * 获取头信息 | ||
| 830 | + * @param $ip_area | ||
| 831 | + * @param $lang | ||
| 832 | + * @return int|string | ||
| 833 | + */ | ||
| 834 | + public function getReferer($ip_area, $lang) | ||
| 835 | + { | ||
| 836 | + if($lang == 'ru'){ | ||
| 837 | + return $this->get_rand($this->eylyzb); | ||
| 838 | + } | ||
| 839 | + if($ip_area == '美国'){ | ||
| 840 | + $referer = $this->get_rand($this->lyzb); | ||
| 841 | + }else{ | ||
| 842 | + $referer = 'https://www.google.com/'; | ||
| 843 | + $suffix = array_search($ip_area, $this->suffix); | ||
| 844 | + if($suffix){ | ||
| 845 | + $res_qtzb = $this->get_rand($this->otherzb); | ||
| 846 | + if($res_qtzb == 1){ | ||
| 847 | + $referer = 'https://www.google.'.$suffix.'/'; | ||
| 848 | + } | ||
| 849 | + } | ||
| 850 | + } | ||
| 851 | + return $referer; | ||
| 852 | + } | ||
| 853 | + | ||
| 854 | + /** | ||
| 855 | + * 概率算法 | ||
| 856 | + * @param $proArr | ||
| 857 | + * @return int|string | ||
| 858 | + */ | ||
| 859 | + protected function get_rand($proArr) | ||
| 860 | + { | ||
| 861 | + $result = ''; | ||
| 862 | + $proSum = array_sum($proArr); | ||
| 863 | + foreach ($proArr as $key => $proCur) { | ||
| 864 | + $randNum = mt_rand(1, $proSum); | ||
| 865 | + if ($randNum <= $proCur) { | ||
| 866 | + $result = $key; | ||
| 867 | + break; | ||
| 868 | + } else { | ||
| 869 | + $proSum -= $proCur; | ||
| 870 | + } | ||
| 871 | + } | ||
| 872 | + unset ($proArr); | ||
| 873 | + return $result; | ||
| 874 | + } | ||
| 875 | + | ||
| 876 | + /** | ||
| 877 | + * 获取sitemap内容 | ||
| 878 | + * @param $sitemapUrl | ||
| 879 | + * @return array|mixed | ||
| 880 | + */ | ||
| 881 | + function getLinksFromSitemap($sitemapUrl) { | ||
| 882 | + try { | ||
| 883 | + //忽略cert证书 先下载到临时文件 | ||
| 884 | + $result = Http::withoutVerifying()->get($sitemapUrl)->body(); | ||
| 885 | + $tempFilePath = tempnam(sys_get_temp_dir(), 'remote_file_'); | ||
| 886 | + file_put_contents($tempFilePath, $result); | ||
| 887 | + $xml = simplexml_load_file($tempFilePath); | ||
| 888 | + $links = []; | ||
| 889 | + foreach ($xml->url as $url) { | ||
| 890 | + $loc = (string) $url->loc; | ||
| 891 | + if(!Str::contains($loc, ['404', 'thanks', 'test'])){ | ||
| 892 | + $links[] = $loc; | ||
| 893 | + } | ||
| 894 | + } | ||
| 895 | + //随机取20个 | ||
| 896 | + $total = count($links); | ||
| 897 | + return Arr::random($links, $total > 20 ? 20 : $total); | ||
| 898 | + }catch (\Exception $e){ | ||
| 899 | + echo date('Y-m-d H:i:s') . 'sitemap获取失败:' . $e->getMessage() . PHP_EOL; | ||
| 900 | + return $links??[]; | ||
| 901 | + } | ||
| 902 | + } | ||
| 903 | + | ||
| 904 | + public function ai_send($ai_param, $incontent, $inquiry_product_url) | ||
| 905 | + { | ||
| 906 | + $ai_command = AiCommand::where('key', 'fb_inquiry_text')->value('ai'); | ||
| 907 | + if (!$ai_command) { | ||
| 908 | + return ''; | ||
| 909 | + } | ||
| 910 | + $translateSl = Translate::translateSl($incontent); | ||
| 911 | + $lang = $translateSl['texts']['sl'] ?? 'en'; | ||
| 912 | + if ($lang == 'en' || $lang == 'ja' || $lang == 'ko' || Str::contains($lang, 'zh')) { | ||
| 913 | + $language = '英文'; | ||
| 914 | + $lang = 'en'; | ||
| 915 | + }else{ | ||
| 916 | + $language = Translate::getTls($lang); | ||
| 917 | + } | ||
| 918 | + | ||
| 919 | + | ||
| 920 | + | ||
| 921 | + //着陆页是否是产品页面或产品列表页 | ||
| 922 | + if($inquiry_product_url){ | ||
| 923 | + $title = Common::getUrlTitle($inquiry_product_url); | ||
| 924 | + if($title){ | ||
| 925 | + $ai_command = str_replace('{mkeywords}', $title, $ai_command); | ||
| 926 | + } | ||
| 927 | + } | ||
| 928 | + $ai_command = str_replace('{mkeywords}', Arr::random(explode("\r\n", $ai_param['mkeywords'])), $ai_command); | ||
| 929 | + $ai_command = str_replace('{incontent}', Arr::random(explode("\r\n", $incontent)), $ai_command); | ||
| 930 | + $ai_command = str_replace('{characters}', Arr::random(explode("\r\n", $ai_param['characters'])), $ai_command); | ||
| 931 | +// $ai_command = str_replace('{language}', Arr::random(explode("\r\n", $language)), $ai_command); | ||
| 932 | + $ai_command = str_replace('{language}', '英语', $ai_command); //输出英文 后面再翻译 | ||
| 933 | + $ai_command = str_replace('{inkeywords}', Arr::random(explode("\r\n", $ai_param['inkeywords'])), $ai_command); | ||
| 934 | + $ai_command = str_replace('{suoxie}', Arr::random(explode("\r\n", $ai_param['suoxie'])), $ai_command); | ||
| 935 | + //中括号里的根据概率使用 | ||
| 936 | + preg_match_all("/\[([^\]]+)\]/", $ai_command, $matches); | ||
| 937 | + foreach ($matches[1] as $k => $match){ | ||
| 938 | + //按比例使用 | ||
| 939 | + $matche_arr = explode('|', $match); | ||
| 940 | + $percentage = intval(trim($matche_arr[0], "%")); | ||
| 941 | + if(rand(1,100) <= $percentage){ | ||
| 942 | + //使用 | ||
| 943 | + $ai_command = str_replace($matches[0][$k], $matche_arr[1], $ai_command); | ||
| 944 | + }else{ | ||
| 945 | + //删除中括号 | ||
| 946 | + $ai_command = str_replace($matches[0][$k], '', $ai_command); | ||
| 947 | + } | ||
| 948 | + } | ||
| 949 | + | ||
| 950 | + $text = Gpt::instance()->openai_chat_qqs($ai_command); | ||
| 951 | + if ($lang != 'en' && !Str::contains($lang, 'zh')) { | ||
| 952 | + $text = Translate::tran($text, $lang); | ||
| 953 | + } | ||
| 954 | + $this->logChannel()->info("AI询盘文案", [$ai_command, $text]); | ||
| 955 | + return Common::deal_str($text); | ||
| 956 | + } | ||
| 957 | + | ||
| 958 | + /** | ||
| 959 | + * @return \Psr\Log\LoggerInterface | ||
| 960 | + */ | ||
| 961 | + public function logChannel() | ||
| 962 | + { | ||
| 963 | + return Log::channel('inquiry_relay'); | ||
| 964 | + } | ||
| 965 | + | ||
| 966 | + public function output($message) | ||
| 967 | + { | ||
| 968 | + echo date('Y-m-d H:i:s') . ' | ' . $message . PHP_EOL; | ||
| 969 | + } | ||
| 970 | +} |
| @@ -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; |
| @@ -52,9 +52,10 @@ class LyhImportTest extends Command | @@ -52,9 +52,10 @@ class LyhImportTest extends Command | ||
| 52 | * @time :2023/11/20 15:13 | 52 | * @time :2023/11/20 15:13 |
| 53 | */ | 53 | */ |
| 54 | public function handle(){ | 54 | public function handle(){ |
| 55 | - ProjectServer::useProject(3654); | ||
| 56 | - echo date('Y-m-d H:i:s') . 'start' . PHP_EOL; | ||
| 57 | - $this->importProductCategory('https://ecdn6-nc.globalso.com/upload/p/3654/file/2025-06/products-1.csv',3654); | 55 | + ProjectServer::useProject(3531); |
| 56 | + echo date('Y-m-d H:i:s') . 'start->3531' . PHP_EOL; | ||
| 57 | +// $this->importProductCategory('https://ecdn6-nc.globalso.com/upload/p/3654/file/2025-06/products-1.csv',3654); | ||
| 58 | + $this->import3531CustomModule(3531); | ||
| 58 | DB::disconnect('custom_mysql'); | 59 | DB::disconnect('custom_mysql'); |
| 59 | echo date('Y-m-d H:i:s') . 'end' . PHP_EOL; | 60 | echo date('Y-m-d H:i:s') . 'end' . PHP_EOL; |
| 60 | } | 61 | } |
| @@ -580,4 +581,1094 @@ class LyhImportTest extends Command | @@ -580,4 +581,1094 @@ class LyhImportTest extends Command | ||
| 580 | // } | 581 | // } |
| 581 | } | 582 | } |
| 582 | } | 583 | } |
| 584 | + | ||
| 585 | + /** | ||
| 586 | + * @remark :导入扩展模块数据 | ||
| 587 | + * @name :import3153CustomModule | ||
| 588 | + * @author :lyh | ||
| 589 | + * @method :post | ||
| 590 | + * @time :2025/9/10 14:44 | ||
| 591 | + */ | ||
| 592 | + public function import3531CustomModule($project_id = 3531){ | ||
| 593 | + $str = '[ | ||
| 594 | + { | ||
| 595 | + "release_at": "2024-09-22 10:07:56", | ||
| 596 | + "name": "300199翰宇药业投资者关系管理信息20240905.pdf", | ||
| 597 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf", | ||
| 598 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 599 | + }, | ||
| 600 | + { | ||
| 601 | + "release_at": "2024-05-0 01:06:09", | ||
| 602 | + "name": "300199翰宇药业投资者关系管理信息20240510.pdf", | ||
| 603 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-05-10_300199-hanyu-pharmaceutical-investor-relations-management-information-20240510_3774.pdf", | ||
| 604 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 605 | + }, | ||
| 606 | + { | ||
| 607 | + "release_at": "2023-10-12 10:43:39", | ||
| 608 | + "name": "300199翰宇药业2023-10-13_2023年10月11-12日投资者关系活动记录表.pdf", | ||
| 609 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2023-10-13_2023-october-11-12-investor-relations-activity-record-sheet_7992.pdf", | ||
| 610 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 611 | + }, | ||
| 612 | + { | ||
| 613 | + "release_at": "2023-02-22 00:40:24", | ||
| 614 | + "name": "300199翰宇药业2023年02月03日投资者关系活动记录表.pdf", | ||
| 615 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2023-05-29_300199-hanyu-pharmaceutical-research-activity-information-20230529_5609.pdf", | ||
| 616 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 617 | + }, | ||
| 618 | + { | ||
| 619 | + "release_at": "2022-06-20 08:09:53", | ||
| 620 | + "name": "300199翰宇药业调研活动信息20220601.pdf", | ||
| 621 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf", | ||
| 622 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 623 | + }, | ||
| 624 | + { | ||
| 625 | + "release_at": "2022-05-0 02:58:18", | ||
| 626 | + "name": "300199翰宇药业调研活动信息20220509.pdf", | ||
| 627 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2022-05-09_300199-hanyu-pharmaceutical-research-activity-information-20220509_8714.pdf", | ||
| 628 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 629 | + }, | ||
| 630 | + { | ||
| 631 | + "release_at": "2021-11-13 04:07:53", | ||
| 632 | + "name": "300199翰宇药业调研活动信息20211102.pdf", | ||
| 633 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2021-11-02_300199-hanyu-pharmaceutical-research-activity-information-20211102_7796.pdf", | ||
| 634 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 635 | + }, | ||
| 636 | + { | ||
| 637 | + "release_at": "2021-09-2 10:36:12", | ||
| 638 | + "name": "300199翰宇药业调研活动信息20210903.pdf", | ||
| 639 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2021-09-03_300199-hanyu-pharmaceutical-research-activity-information-20210903_4654.pdf", | ||
| 640 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 641 | + }, | ||
| 642 | + { | ||
| 643 | + "release_at": "2020-12-22 02:06:25", | ||
| 644 | + "name": "300199翰宇药业调研活动信息20201203.doc", | ||
| 645 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2020-12-03_300199-hanyu-pharmaceutical-research-activity-information-20201203_3714.doc", | ||
| 646 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 647 | + }, | ||
| 648 | + { | ||
| 649 | + "release_at": "2020-10-16 01:11:15", | ||
| 650 | + "name": "300199翰宇药业投资者关系管理制度20201016.doc", | ||
| 651 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceuticals-2020-10-16_300199-hanyu-pharmaceuticals-investor-relations-management-system-20201016_9487.doc", | ||
| 652 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 653 | + }, | ||
| 654 | + { | ||
| 655 | + "release_at": "2020-09-1 05:09:01", | ||
| 656 | + "name": "300199翰宇药业投资者关系管理档案20200915_3643.doc", | ||
| 657 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceuticals-2020-09-15_300199-hanyu-pharmaceuticals-investor-relations-management-file-20200915_3643.doc", | ||
| 658 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 659 | + }, | ||
| 660 | + { | ||
| 661 | + "release_at": "2024-09-3 01:32:32", | ||
| 662 | + "name": "300199翰宇药业投资者关系管理信息20240905_8114.pdf", | ||
| 663 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf", | ||
| 664 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 665 | + }, | ||
| 666 | + { | ||
| 667 | + "release_at": "2020-08-9 01:15:23", | ||
| 668 | + "name": "300199翰宇药业2020-08-25_投资者关系管理制度_7744.PDF", | ||
| 669 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2020-08-25_investor-relations-management-system_7744.PDF", | ||
| 670 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 671 | + }, | ||
| 672 | + { | ||
| 673 | + "release_at": "2024-08-20 11:07:20", | ||
| 674 | + "name": "300199翰宇药业投资者关系管理档案20200807_9651.doc", | ||
| 675 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceuticals-2020-08-07_300199-hanyu-pharmaceuticals-investor-relations-management-file-20200807_9651.doc", | ||
| 676 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 677 | + }, | ||
| 678 | + { | ||
| 679 | + "release_at": "2020-07-21 04:43:26", | ||
| 680 | + "name": "300199翰宇药业调研活动信息20200723_1044.doc", | ||
| 681 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2020-07-23_300199-hanyu-pharmaceutical-research-activity-information-20200723_1044.doc", | ||
| 682 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 683 | + }, | ||
| 684 | + { | ||
| 685 | + "release_at": "2018-10-4 04:57:34", | ||
| 686 | + "name": "300199翰宇药业2018-10-12_2018年10月10日投资者关系活动记录表.pdf", | ||
| 687 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-10-12_october-10-2018-investor-relations-activity-record_6079.pdf", | ||
| 688 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 689 | + }, | ||
| 690 | + { | ||
| 691 | + "release_at": "2018-08-1 03:03:44", | ||
| 692 | + "name": "300199翰宇药业2018-08-16_2018年8月15日投资者关系活动记录表.pdf", | ||
| 693 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-08-16_2018-august-15-investor-relations-activity-record_1590.pdf", | ||
| 694 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 695 | + }, | ||
| 696 | + { | ||
| 697 | + "release_at": "2018-08-3 02:46:31", | ||
| 698 | + "name": "300199翰宇药业2018-10-12_2018年10月10日投资者关系活动记录表", | ||
| 699 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-10-12_october-10-2018-investor-relations-activity-record_6079.pdf", | ||
| 700 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 701 | + }, | ||
| 702 | + { | ||
| 703 | + "release_at": "2018-07-7 06:43:51", | ||
| 704 | + "name": "300199翰宇药业2018-07-04_2018年6月28日投资者关系活动记录表.pdf", | ||
| 705 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-07-04_investor-relations-activity-record-form-on-june-28-2018_7416.pdf", | ||
| 706 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 707 | + }, | ||
| 708 | + { | ||
| 709 | + "release_at": "2018-06-4 05:51:21", | ||
| 710 | + "name": "300199翰宇药业2018-06-30_2018年6月27日投资者关系活动记录表.pdf", | ||
| 711 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-06-30_investor-relations-activity-record-form-on-june-27-2018_1798.pdf", | ||
| 712 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 713 | + }, | ||
| 714 | + { | ||
| 715 | + "release_at": "2018-01-22 05:20:39", | ||
| 716 | + "name": "300199翰宇药业2018-01-15_2018年1月12日投资者关系活动记录表.pdf", | ||
| 717 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-01-15_investor-relations-activity-record-form-on-january-12-2018_7983.pdf", | ||
| 718 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 719 | + }, | ||
| 720 | + { | ||
| 721 | + "release_at": "2018-01-13 01:01:14", | ||
| 722 | + "name": "300199翰宇药业投资者关系管理信息20240905_8114.pdf", | ||
| 723 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-01-11_2018-january-9-investor-relations-activity-record_3126.pdf", | ||
| 724 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 725 | + }, | ||
| 726 | + { | ||
| 727 | + "release_at": "2017-12-0 02:48:51", | ||
| 728 | + "name": "300199翰宇药业2017-12-12_2017年12月8日投资者关系活动记录表.docx", | ||
| 729 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-12-12_investor-relations-activity-record-form-on-december-8-2017_4872.docx", | ||
| 730 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 731 | + }, | ||
| 732 | + { | ||
| 733 | + "release_at": "2017-12-24 01:34:45", | ||
| 734 | + "name": "300199翰宇药业2017-12-06_2017年12月4日投资者关系活动记录表.pdf", | ||
| 735 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-12-06_investor-relations-activity-record-form-on-december-4-2017_9265.pdf", | ||
| 736 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 737 | + }, | ||
| 738 | + { | ||
| 739 | + "release_at": "2017-11-19 10:52:44", | ||
| 740 | + "name": "300199翰宇药业2017-11-29_2017年11月23日投资者关系活动记录表.pdf", | ||
| 741 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-11-29_2017-november-23-investor-relations-activity-record_2045.pdf", | ||
| 742 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 743 | + }, | ||
| 744 | + { | ||
| 745 | + "release_at": "2017-11-11 07:31:15", | ||
| 746 | + "name": "300199翰宇药业2017-11-10_2017年11月8日投资者关系活动记录表.pdf", | ||
| 747 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf", | ||
| 748 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 749 | + }, | ||
| 750 | + { | ||
| 751 | + "release_at": "2017-11-2 07:22:37", | ||
| 752 | + "name": "300199翰宇药业2017-11-09_2017年11月6日投资者关系活动记录表.pdf", | ||
| 753 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-11-09_november-6-2017-investor-relations-activity-record_4228.pdf", | ||
| 754 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 755 | + }, | ||
| 756 | + { | ||
| 757 | + "release_at": "2017-10-4 10:40:44", | ||
| 758 | + "name": "300199翰宇药业2017-10-31_2017年10月27日投资者关系活动记录表.pdf", | ||
| 759 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-10-31_2017-october-27-investor-relations-activity-record_i__6306.pdf", | ||
| 760 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 761 | + }, | ||
| 762 | + { | ||
| 763 | + "release_at": "2017-10-15 02:14:30", | ||
| 764 | + "name": "300199翰宇药业2017-10-31_2017年10月27日投资者关系活动记录表_二.pdf", | ||
| 765 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-10-31_2017-october-27-investor-relations-activity-record_ii__4570.pdf", | ||
| 766 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 767 | + }, | ||
| 768 | + { | ||
| 769 | + "release_at": "2017-10-11 11:36:58", | ||
| 770 | + "name": "300199翰宇药业2017-10-25_2017年10月17日投资者关系活动记录表.pdf", | ||
| 771 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-10-25_2017-october-17-investor-relations-activity-record_6436.pdf", | ||
| 772 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 773 | + }, | ||
| 774 | + { | ||
| 775 | + "release_at": "2017-10-16 09:47:11", | ||
| 776 | + "name": "300199翰宇药业2017-10-20_2017年10月18日投资者关系活动记录表_一.pdf", | ||
| 777 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-10-20_2017-october-18-investor-relations-activity-record-sheet_i__2433.pdf", | ||
| 778 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 779 | + }, | ||
| 780 | + { | ||
| 781 | + "release_at": "2017-10-5 09:56:44", | ||
| 782 | + "name": "300199翰宇药业2017-10-20_2017年10月18日投资者关系活动记录表_二.pdf", | ||
| 783 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf", | ||
| 784 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 785 | + }, | ||
| 786 | + { | ||
| 787 | + "release_at": "2017-10-5 04:20:08", | ||
| 788 | + "name": "300199翰宇药业2017-10-11_2017年10月10日投资者关系活动记录表.pdf", | ||
| 789 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-10-11_2017-october-10-investor-relations-activity-record_7981.pdf", | ||
| 790 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 791 | + }, | ||
| 792 | + { | ||
| 793 | + "release_at": "2017-09-3 06:20:49", | ||
| 794 | + "name": "300199翰宇药业2017-09-22_2017年9月21日投资者关系活动记录表.pdf", | ||
| 795 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-09-22_2017-september-21-investor-relations-activity-record_6296.pdf", | ||
| 796 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 797 | + }, | ||
| 798 | + { | ||
| 799 | + "release_at": "2017-09-8 10:35:03", | ||
| 800 | + "name": "300199翰宇药业2017-09-21_2017年9月19日投资者关系活动记录表.pdf", | ||
| 801 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf", | ||
| 802 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 803 | + }, | ||
| 804 | + { | ||
| 805 | + "release_at": "2017-08-10 07:09:11", | ||
| 806 | + "name": "300199翰宇药业2017-08-31_2017年8月30日投资者关系活动记录表_一.pdf", | ||
| 807 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-08-31_2017-august-30-investor-relations-activity-record_i__6623.pdf", | ||
| 808 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 809 | + }, | ||
| 810 | + { | ||
| 811 | + "release_at": "2017-08-11 00:30:12", | ||
| 812 | + "name": "300199翰宇药业2017-08-31_2017年8月30日投资者关系活动记录表_二.pdf", | ||
| 813 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-08-31_2017-august-30-investor-relations-activity-record_ii__1600.pdf", | ||
| 814 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 815 | + }, | ||
| 816 | + { | ||
| 817 | + "release_at": "2017-07-5 05:58:57", | ||
| 818 | + "name": "300199_翰宇药业2017-07-04_2017年6月30日投资者关系活动记录表.pdf", | ||
| 819 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-07-04_investor-relations-activity-record-form-on-june-30-2017_3857.pdf", | ||
| 820 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 821 | + }, | ||
| 822 | + { | ||
| 823 | + "release_at": "2017-07-15 10:51:14", | ||
| 824 | + "name": "300199翰宇药业2017-07-03_2017年6月29日投资者关系活动记录表.pdf", | ||
| 825 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-07-03_investor-relations-activity-record-form-on-june-29-2017_6558.pdf", | ||
| 826 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 827 | + }, | ||
| 828 | + { | ||
| 829 | + "release_at": "2017-06-0 06:32:30", | ||
| 830 | + "name": "300199翰宇药业2017-06-30_2017年6月28日投资者关系活动记录表.pdf", | ||
| 831 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-06-30_investor-relations-activity-record-form-on-june-28-2017_5867.pdf", | ||
| 832 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 833 | + }, | ||
| 834 | + { | ||
| 835 | + "release_at": "2017-06-12 07:32:28", | ||
| 836 | + "name": "300199翰宇药业2017-06-30_2017年6月28日投资者关系活动记录表.pdf", | ||
| 837 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-06-30_investor-relations-activity-record-form-on-june-28-2017_3778.pdf", | ||
| 838 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 839 | + }, | ||
| 840 | + { | ||
| 841 | + "release_at": "2017-06-15 01:20:49", | ||
| 842 | + "name": "300199翰宇药业2017-06-07_2017年5月25日投资者关系活动记录表.pdf", | ||
| 843 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-06-07_may-25-2017-investor-relations-activity-record_5392.pdf", | ||
| 844 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 845 | + }, | ||
| 846 | + { | ||
| 847 | + "release_at": "2017-05-10 03:34:01", | ||
| 848 | + "name": "300199翰宇药业2017-05-31_2017年5月26日投资者关系活动记录表.pdf", | ||
| 849 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-05-31_2017-may-26-investor-relations-activity-record_4488.pdf", | ||
| 850 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 851 | + }, | ||
| 852 | + { | ||
| 853 | + "release_at": "2017-05-15 11:36:44", | ||
| 854 | + "name": "300199翰宇药业2017-05-26_2017年5月25日投资者关系活动记录表.pdf", | ||
| 855 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-05-26_may-25-2017-investor-relations-activity-record_1669.pdf", | ||
| 856 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 857 | + }, | ||
| 858 | + { | ||
| 859 | + "release_at": "2017-05-20 10:42:01", | ||
| 860 | + "name": "300199翰宇药业2017-05-12_2017年5月11日投资者关系活动记录表.pdf", | ||
| 861 | + "href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-05-12_may-11-2017-investor-relations-activity-record_8189.pdf", | ||
| 862 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 863 | + }, | ||
| 864 | + { | ||
| 865 | + "release_at": "2017-05-14 00:23:03", | ||
| 866 | + "name": "300199_翰宇药业2017-05-08_2017年5月5日投资者关系活动记录表.pdf", | ||
| 867 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf", | ||
| 868 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 869 | + }, | ||
| 870 | + { | ||
| 871 | + "release_at": "2017-05-3 09:15:35", | ||
| 872 | + "name": "300199_翰宇药业2017-05-05_2017年5月4日投资者关系活动记录表.pdf", | ||
| 873 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf", | ||
| 874 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 875 | + }, | ||
| 876 | + { | ||
| 877 | + "release_at": "2017-04-7 11:46:44", | ||
| 878 | + "name": "300199_翰宇药业2017-04-19_2017年4月17日投资者关系活动记录表.pdf", | ||
| 879 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf", | ||
| 880 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 881 | + }, | ||
| 882 | + { | ||
| 883 | + "release_at": "2017-04-18 03:23:11", | ||
| 884 | + "name": "300199_翰宇药业2017-04-18_2017年4月14日投资者关系活动记录表.pdf", | ||
| 885 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf", | ||
| 886 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 887 | + }, | ||
| 888 | + { | ||
| 889 | + "release_at": "2017-03-8 02:36:19", | ||
| 890 | + "name": "300199_翰宇药业2017-03-28_2017年3月27日投资者关系活动记录表.pdf", | ||
| 891 | + "href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf", | ||
| 892 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 893 | + }, | ||
| 894 | + { | ||
| 895 | + "release_at": "2017-03-24 09:45:46", | ||
| 896 | + "name": "300199翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf", | ||
| 897 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf", | ||
| 898 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 899 | + }, | ||
| 900 | + { | ||
| 901 | + "release_at": "2017-03-7 05:03:11", | ||
| 902 | + "name": "300199_翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf", | ||
| 903 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf", | ||
| 904 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 905 | + }, | ||
| 906 | + { | ||
| 907 | + "release_at": "2017-03-15 11:21:32", | ||
| 908 | + "name": "300199_翰宇药业2017-03-08_2017年3月7日投资者关系活动记录表.pdf", | ||
| 909 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-08_investor-relations-activity-record-for-march-7-2017_9347.pdf", | ||
| 910 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 911 | + }, | ||
| 912 | + { | ||
| 913 | + "release_at": "2017-02-5 11:09:12", | ||
| 914 | + "name": "300199翰宇药业2017-02-16_2017年2月14日投资者关系活动记录表_一3396.pdf", | ||
| 915 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-16_investor-relations-activity-record-sheet-for-february-14-2017_i__3396.pdf", | ||
| 916 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 917 | + }, | ||
| 918 | + { | ||
| 919 | + "release_at": "2017-02-15 09:09:14", | ||
| 920 | + "name": "300199翰宇药业2017-02-14_2017年2月10日投资者关系活动记录表.pdf", | ||
| 921 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-14_investor-relations-activity-record-for-february-10-2017_9222.pdf", | ||
| 922 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 923 | + }, | ||
| 924 | + { | ||
| 925 | + "release_at": "2017-01-6 02:47:09", | ||
| 926 | + "name": "300199翰宇药业2017-01-06_2017年1月5日投资者关系活动记录表.pdf", | ||
| 927 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-01-06_january-5-2017-investor-relations-activity-record-sheet_2137.pdf", | ||
| 928 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 929 | + }, | ||
| 930 | + { | ||
| 931 | + "release_at": "2016-12-4 08:44:03", | ||
| 932 | + "name": "300199翰宇药业2016-12-26_2016年12月22日投资者关系活动记录表.pdf", | ||
| 933 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-26_investor-relations-activity-record-for-december-22-2016_4414.pdf", | ||
| 934 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 935 | + }, | ||
| 936 | + { | ||
| 937 | + "release_at": "2016-12-4 00:11:24", | ||
| 938 | + "name": "300199翰宇药业2016-12-21_2016年12月20日投资者关系活动记录表.pdf", | ||
| 939 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-21_investor-relations-activity-record-for-december-20-2016_7480.pdf", | ||
| 940 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 941 | + }, | ||
| 942 | + { | ||
| 943 | + "release_at": "2016-12-17 11:37:55", | ||
| 944 | + "name": "300199翰宇药业2016-12-15_2016年12月14日投资者关系活动记录表.pdf", | ||
| 945 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-15_investor-relations-activity-record-for-december-14-2016_8735.pdf", | ||
| 946 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 947 | + }, | ||
| 948 | + { | ||
| 949 | + "release_at": "2016-12-21 10:12:43", | ||
| 950 | + "name": "300199翰宇药业2016-12-13_2016年12月12日投资者关系活动记录表.pdf", | ||
| 951 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-12-13_investor-relations-activity-record-for-december-12-2016_3763.pdf", | ||
| 952 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 953 | + }, | ||
| 954 | + { | ||
| 955 | + "release_at": "2017-03-19 00:43:40", | ||
| 956 | + "name": "300199翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf", | ||
| 957 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf", | ||
| 958 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 959 | + }, | ||
| 960 | + { | ||
| 961 | + "release_at": "2017-03-4 10:23:20", | ||
| 962 | + "name": "300199_翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf", | ||
| 963 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf", | ||
| 964 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 965 | + }, | ||
| 966 | + { | ||
| 967 | + "release_at": "2017-03-7 04:51:39", | ||
| 968 | + "name": "300199_翰宇药业2017-03-08_2017年3月7日投资者关系活动记录表.pdf", | ||
| 969 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-08_investor-relations-activity-record-for-march-7-2017_9347.pdf", | ||
| 970 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 971 | + }, | ||
| 972 | + { | ||
| 973 | + "release_at": "2017-02-14 01:18:23", | ||
| 974 | + "name": "300199翰宇药业2017-02-16_2017年2月14日投资者关系活动记录表_一3396.pdf", | ||
| 975 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-16_investor-relations-activity-record-sheet-for-february-14-2017_i__3396.pdf", | ||
| 976 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 977 | + }, | ||
| 978 | + { | ||
| 979 | + "release_at": "2017-02-6 10:32:52", | ||
| 980 | + "name": "300199翰宇药业2017-02-14_2017年2月10日投资者关系活动记录表.pdf", | ||
| 981 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-14_investor-relations-activity-record-for-february-10-2017_9222.pdf", | ||
| 982 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 983 | + }, | ||
| 984 | + { | ||
| 985 | + "release_at": "2017-01-8 02:43:38", | ||
| 986 | + "name": "300199翰宇药业2017-01-06_2017年1月5日投资者关系活动记录表.pdf", | ||
| 987 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-01-06_january-5-2017-investor-relations-activity-record-sheet_2137.pdf", | ||
| 988 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 989 | + }, | ||
| 990 | + { | ||
| 991 | + "release_at": "2016-12-21 07:37:24", | ||
| 992 | + "name": "300199翰宇药业2016-12-26_2016年12月22日投资者关系活动记录表.pdf", | ||
| 993 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-26_investor-relations-activity-record-for-december-22-2016_4414.pdf", | ||
| 994 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 995 | + }, | ||
| 996 | + { | ||
| 997 | + "release_at": "2016-12-12 07:11:21", | ||
| 998 | + "name": "300199翰宇药业2016-12-21_2016年12月20日投资者关系活动记录表.pdf", | ||
| 999 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-21_investor-relations-activity-record-for-december-20-2016_7480.pdf", | ||
| 1000 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1001 | + }, | ||
| 1002 | + { | ||
| 1003 | + "release_at": "2016-12-12 10:08:40", | ||
| 1004 | + "name": "300199翰宇药业2016-12-15_2016年12月14日投资者关系活动记录表.pdf", | ||
| 1005 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-15_investor-relations-activity-record-for-december-14-2016_8735.pdf", | ||
| 1006 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1007 | + }, | ||
| 1008 | + { | ||
| 1009 | + "release_at": "2016-12-23 02:23:55", | ||
| 1010 | + "name": "300199翰宇药业2016-12-13_2016年12月12日投资者关系活动记录表.pdf", | ||
| 1011 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-12-13_investor-relations-activity-record-for-december-12-2016_3763.pdf", | ||
| 1012 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1013 | + }, | ||
| 1014 | + { | ||
| 1015 | + "release_at": "2017-03-5 10:30:23", | ||
| 1016 | + "name": "300199翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf", | ||
| 1017 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf", | ||
| 1018 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1019 | + }, | ||
| 1020 | + { | ||
| 1021 | + "release_at": "2017-03-4 04:06:45", | ||
| 1022 | + "name": "300199_翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf", | ||
| 1023 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf", | ||
| 1024 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1025 | + }, | ||
| 1026 | + { | ||
| 1027 | + "release_at": "2017-03-23 02:38:57", | ||
| 1028 | + "name": "300199_翰宇药业2017-03-08_2017年3月7日投资者关系活动记录表.pdf", | ||
| 1029 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-08_investor-relations-activity-record-for-march-7-2017_9347.pdf", | ||
| 1030 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1031 | + }, | ||
| 1032 | + { | ||
| 1033 | + "release_at": "2017-02-15 00:09:47", | ||
| 1034 | + "name": "300199翰宇药业2017-02-16_2017年2月14日投资者关系活动记录表_一3396.pdf", | ||
| 1035 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-16_investor-relations-activity-record-sheet-for-february-14-2017_i__3396.pdf", | ||
| 1036 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1037 | + }, | ||
| 1038 | + { | ||
| 1039 | + "release_at": "2017-02-17 03:25:58", | ||
| 1040 | + "name": "300199翰宇药业2017-02-14_2017年2月10日投资者关系活动记录表.pdf", | ||
| 1041 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-14_investor-relations-activity-record-for-february-10-2017_9222.pdf", | ||
| 1042 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1043 | + }, | ||
| 1044 | + { | ||
| 1045 | + "release_at": "2017-01-17 05:17:40", | ||
| 1046 | + "name": "300199翰宇药业2017-01-06_2017年1月5日投资者关系活动记录表.pdf", | ||
| 1047 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-01-06_january-5-2017-investor-relations-activity-record-sheet_2137.pdf", | ||
| 1048 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1049 | + }, | ||
| 1050 | + { | ||
| 1051 | + "release_at": "2016-12-10 03:33:51", | ||
| 1052 | + "name": "300199翰宇药业2016-12-26_2016年12月22日投资者关系活动记录表.pdf", | ||
| 1053 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-26_investor-relations-activity-record-for-december-22-2016_4414.pdf", | ||
| 1054 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1055 | + }, | ||
| 1056 | + { | ||
| 1057 | + "release_at": "2016-12-15 02:51:50", | ||
| 1058 | + "name": "300199翰宇药业2016-12-21_2016年12月20日投资者关系活动记录表.pdf", | ||
| 1059 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-21_investor-relations-activity-record-for-december-20-2016_7480.pdf", | ||
| 1060 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1061 | + }, | ||
| 1062 | + { | ||
| 1063 | + "release_at": "2016-12-10 03:24:11", | ||
| 1064 | + "name": "300199翰宇药业2016-12-15_2016年12月14日投资者关系活动记录表.pdf", | ||
| 1065 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-15_investor-relations-activity-record-for-december-14-2016_8735.pdf", | ||
| 1066 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1067 | + }, | ||
| 1068 | + { | ||
| 1069 | + "release_at": "2016-12-12 03:34:19", | ||
| 1070 | + "name": "300199翰宇药业2016-12-13_2016年12月12日投资者关系活动记录表.pdf", | ||
| 1071 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-12-13_investor-relations-activity-record-for-december-12-2016_3763.pdf", | ||
| 1072 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1073 | + }, | ||
| 1074 | + { | ||
| 1075 | + "release_at": "2017-03-24 02:41:28", | ||
| 1076 | + "name": "300199翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf", | ||
| 1077 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf", | ||
| 1078 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1079 | + }, | ||
| 1080 | + { | ||
| 1081 | + "release_at": "2017-03-1 10:28:18", | ||
| 1082 | + "name": "300199_翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf", | ||
| 1083 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf", | ||
| 1084 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1085 | + }, | ||
| 1086 | + { | ||
| 1087 | + "release_at": "2017-03-24 00:16:45", | ||
| 1088 | + "name": "300199_翰宇药业2017-03-08_2017年3月7日投资者关系活动记录表.pdf", | ||
| 1089 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-08_investor-relations-activity-record-for-march-7-2017_9347.pdf", | ||
| 1090 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1091 | + }, | ||
| 1092 | + { | ||
| 1093 | + "release_at": "2017-02-24 11:59:46", | ||
| 1094 | + "name": "300199翰宇药业2017-02-16_2017年2月14日投资者关系活动记录表_一3396.pdf", | ||
| 1095 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-16_investor-relations-activity-record-sheet-for-february-14-2017_i__3396.pdf", | ||
| 1096 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1097 | + }, | ||
| 1098 | + { | ||
| 1099 | + "release_at": "2017-02-4 00:03:38", | ||
| 1100 | + "name": "300199翰宇药业2017-02-14_2017年2月10日投资者关系活动记录表.pdf", | ||
| 1101 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-14_investor-relations-activity-record-for-february-10-2017_9222.pdf", | ||
| 1102 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1103 | + }, | ||
| 1104 | + { | ||
| 1105 | + "release_at": "2017-01-6 06:08:19", | ||
| 1106 | + "name": "300199翰宇药业2017-01-06_2017年1月5日投资者关系活动记录表.pdf", | ||
| 1107 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-01-06_january-5-2017-investor-relations-activity-record-sheet_2137.pdf", | ||
| 1108 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1109 | + }, | ||
| 1110 | + { | ||
| 1111 | + "release_at": "2016-12-8 11:38:16", | ||
| 1112 | + "name": "300199翰宇药业2016-12-26_2016年12月22日投资者关系活动记录表.pdf", | ||
| 1113 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-26_investor-relations-activity-record-for-december-22-2016_4414.pdf", | ||
| 1114 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1115 | + }, | ||
| 1116 | + { | ||
| 1117 | + "release_at": "2016-12-2 11:40:31", | ||
| 1118 | + "name": "300199翰宇药业2016-12-21_2016年12月20日投资者关系活动记录表.pdf", | ||
| 1119 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-21_investor-relations-activity-record-for-december-20-2016_7480.pdf", | ||
| 1120 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1121 | + }, | ||
| 1122 | + { | ||
| 1123 | + "release_at": "2016-12-1 11:12:59", | ||
| 1124 | + "name": "300199翰宇药业2016-12-15_2016年12月14日投资者关系活动记录表.pdf", | ||
| 1125 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-15_investor-relations-activity-record-for-december-14-2016_8735.pdf", | ||
| 1126 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1127 | + }, | ||
| 1128 | + { | ||
| 1129 | + "release_at": "2016-12-2 11:14:06", | ||
| 1130 | + "name": "300199翰宇药业2016-12-13_2016年12月12日投资者关系活动记录表.pdf", | ||
| 1131 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-12-13_investor-relations-activity-record-for-december-12-2016_3763.pdf", | ||
| 1132 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1133 | + }, | ||
| 1134 | + { | ||
| 1135 | + "release_at": "2017-03-22 01:45:15", | ||
| 1136 | + "name": "300199翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf", | ||
| 1137 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf", | ||
| 1138 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1139 | + }, | ||
| 1140 | + { | ||
| 1141 | + "release_at": "2017-03-20 07:43:24", | ||
| 1142 | + "name": "300199_翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf", | ||
| 1143 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf", | ||
| 1144 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1145 | + }, | ||
| 1146 | + { | ||
| 1147 | + "release_at": "2017-03-9 10:30:42", | ||
| 1148 | + "name": "300199_翰宇药业2017-03-08_2017年3月7日投资者关系活动记录表.pdf", | ||
| 1149 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-08_investor-relations-activity-record-for-march-7-2017_9347.pdf", | ||
| 1150 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1151 | + }, | ||
| 1152 | + { | ||
| 1153 | + "release_at": "2017-02-6 07:35:38", | ||
| 1154 | + "name": "300199翰宇药业2017-02-16_2017年2月14日投资者关系活动记录表_一3396.pdf", | ||
| 1155 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-16_investor-relations-activity-record-sheet-for-february-14-2017_i__3396.pdf", | ||
| 1156 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1157 | + }, | ||
| 1158 | + { | ||
| 1159 | + "release_at": "2017-02-18 02:44:23", | ||
| 1160 | + "name": "300199翰宇药业2017-02-14_2017年2月10日投资者关系活动记录表.pdf", | ||
| 1161 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-14_investor-relations-activity-record-for-february-10-2017_9222.pdf", | ||
| 1162 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1163 | + }, | ||
| 1164 | + { | ||
| 1165 | + "release_at": "2017-01-8 00:45:30", | ||
| 1166 | + "name": "300199翰宇药业2017-01-06_2017年1月5日投资者关系活动记录表.pdf", | ||
| 1167 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-01-06_january-5-2017-investor-relations-activity-record-sheet_2137.pdf", | ||
| 1168 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1169 | + }, | ||
| 1170 | + { | ||
| 1171 | + "release_at": "2016-12-13 11:48:43", | ||
| 1172 | + "name": "300199翰宇药业2016-12-26_2016年12月22日投资者关系活动记录表.pdf", | ||
| 1173 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-26_investor-relations-activity-record-for-december-22-2016_4414.pdf", | ||
| 1174 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1175 | + }, | ||
| 1176 | + { | ||
| 1177 | + "release_at": "2016-12-24 04:09:04", | ||
| 1178 | + "name": "300199翰宇药业2016-12-21_2016年12月20日投资者关系活动记录表.pdf", | ||
| 1179 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-21_investor-relations-activity-record-for-december-20-2016_7480.pdf", | ||
| 1180 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1181 | + }, | ||
| 1182 | + { | ||
| 1183 | + "release_at": "2016-12-0 10:30:45", | ||
| 1184 | + "name": "300199翰宇药业2016-12-15_2016年12月14日投资者关系活动记录表.pdf", | ||
| 1185 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-15_investor-relations-activity-record-for-december-14-2016_8735.pdf", | ||
| 1186 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1187 | + }, | ||
| 1188 | + { | ||
| 1189 | + "release_at": "2016-12-2 03:35:29", | ||
| 1190 | + "name": "300199翰宇药业2016-12-13_2016年12月12日投资者关系活动记录表.pdf", | ||
| 1191 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-12-13_investor-relations-activity-record-for-december-12-2016_3763.pdf", | ||
| 1192 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1193 | + }, | ||
| 1194 | + { | ||
| 1195 | + "release_at": "2016-11-20 10:07:03", | ||
| 1196 | + "name": "300199翰宇药业2016-11-18_2016年11月17日投资者关系活动记录表.pdf", | ||
| 1197 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-11-18_november-17-2016-investor-relations-activity-record_3028.pdf", | ||
| 1198 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1199 | + }, | ||
| 1200 | + { | ||
| 1201 | + "release_at": "2016-11-10 10:39:14", | ||
| 1202 | + "name": "300199翰宇药业2016-11-01_2016年10月26日投资者关系活动记录表.pdf", | ||
| 1203 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-11-01_october-26-2016-investor-relations-activity-record_3346.pdf", | ||
| 1204 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1205 | + }, | ||
| 1206 | + { | ||
| 1207 | + "release_at": "2016-10-15 05:19:22", | ||
| 1208 | + "name": "300199翰宇药业2016-10-27_2016年10月25日投资者关系活动记录表.pdf", | ||
| 1209 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-10-27_october-25-2016-investor-relations-activity-record-sheet_4404.pdf", | ||
| 1210 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1211 | + }, | ||
| 1212 | + { | ||
| 1213 | + "release_at": "2016-10-19 07:08:11", | ||
| 1214 | + "name": "300199翰宇药业2016-10-20_2016年10月18日投资者关系活动记录表.pdf", | ||
| 1215 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-10-20_october-18-2016-investor-relations-activity-record-sheet_7025.pdf", | ||
| 1216 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1217 | + }, | ||
| 1218 | + { | ||
| 1219 | + "release_at": "2016-10-3 00:15:17", | ||
| 1220 | + "name": "300199翰宇药业2016-10-18_2016年10月17日投资者关系活动记录表.pdf", | ||
| 1221 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-10-18_october-17-2016-investor-relations-activity-record-sheet_7154.pdf", | ||
| 1222 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1223 | + }, | ||
| 1224 | + { | ||
| 1225 | + "release_at": "2016-10-11 10:04:11", | ||
| 1226 | + "name": "300199翰宇药业2016-10-14_2016年10月13日投资者关系活动记录表.docx", | ||
| 1227 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-10-14_october-13-2016-investor-relations-activity-record-sheet_2136.docx", | ||
| 1228 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1229 | + }, | ||
| 1230 | + { | ||
| 1231 | + "release_at": "2016-09-4 10:08:25", | ||
| 1232 | + "name": "300199翰宇药业2016-09-28_2016年9月27日投资者关系活动记录表.pdf", | ||
| 1233 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-09-28_investor-relations-activity-record-sheet-for-september-27-2016_5997.pdf", | ||
| 1234 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1235 | + }, | ||
| 1236 | + { | ||
| 1237 | + "release_at": "2016-09-7 05:32:27", | ||
| 1238 | + "name": "300199翰宇药业2016-09-26_2016年9月23日投资者关系活动记录表.pdf", | ||
| 1239 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-09-26_investor-relations-activity-record-for-september-23-2016_9551.pdf", | ||
| 1240 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1241 | + }, | ||
| 1242 | + { | ||
| 1243 | + "release_at": "2016-09-12 04:55:18", | ||
| 1244 | + "name": "300199翰宇药业2016-09-14_2016年9月12日投资者关系活动记录表.pdf", | ||
| 1245 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-09-14_investor-relations-activity-record-for-september-12-2016_8051.pdf", | ||
| 1246 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1247 | + }, | ||
| 1248 | + { | ||
| 1249 | + "release_at": "2016-09-8 05:32:27", | ||
| 1250 | + "name": "300199_翰宇药业2016-09-12_2016年9月8日投资者关系活动记录表_3358.pdf", | ||
| 1251 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-09-12_investor-relations-activity-record-for-september-8-2016_3358.pdf", | ||
| 1252 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1253 | + }, | ||
| 1254 | + { | ||
| 1255 | + "release_at": "2016-09-18 11:33:12", | ||
| 1256 | + "name": "300199翰宇药业2016-09-09_2016年9月6日投资者关系活动记录表.pdf", | ||
| 1257 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-09-09_investor-relations-activity-record-sheet-for-september-6-2016_8597.pdf", | ||
| 1258 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1259 | + }, | ||
| 1260 | + { | ||
| 1261 | + "release_at": "2016-08-14 10:48:05", | ||
| 1262 | + "name": "300199翰宇药业2016-08-02_2016年7月28日投资者关系活动记录表_二.pdf", | ||
| 1263 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-08-02_investor-relations-activity-record-sheet-for-july-28-2016_ii__5436.pdf", | ||
| 1264 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1265 | + }, | ||
| 1266 | + { | ||
| 1267 | + "release_at": "2016-08-1 07:23:09", | ||
| 1268 | + "name": "300199翰宇药业2016-08-02_2016年7月28日投资者关系活动记录表_一.pdf", | ||
| 1269 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-07-12_investor-relations-activity-record-for-july-8-2016_9778.pdf", | ||
| 1270 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1271 | + }, | ||
| 1272 | + { | ||
| 1273 | + "release_at": "2016-07-22 11:19:18", | ||
| 1274 | + "name": "300199翰宇药业2016-07-12_2016年7月8日投资者关系活动记录表.pdf", | ||
| 1275 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-07-04_investor-relations-activity-record-for-july-1-2016_3227.pdf", | ||
| 1276 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1277 | + }, | ||
| 1278 | + { | ||
| 1279 | + "release_at": "2016-07-6 07:25:13", | ||
| 1280 | + "name": "300199翰宇药业2016-07-04_2016年7月1日投资者关系活动记录表.pdf", | ||
| 1281 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-06-30_investor-relations-activity-record-for-june-27-2016_8256.pdf", | ||
| 1282 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1283 | + }, | ||
| 1284 | + { | ||
| 1285 | + "release_at": "2016-06-13 11:16:08", | ||
| 1286 | + "name": "300199翰宇药业2016-06-30_2016年6月27日投资者关系活动记录表.pdf", | ||
| 1287 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-06-30_investor-relations-activity-record-for-june-27-2016_8256.pdf", | ||
| 1288 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1289 | + }, | ||
| 1290 | + { | ||
| 1291 | + "release_at": "2016-06-0 01:54:53", | ||
| 1292 | + "name": "300199翰宇药业2016-06-16_2016年6月14日投资者关系活动记录表.pdf", | ||
| 1293 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-06-16_investor-relations-activity-record-sheet-june-14-2016_7707.pdf", | ||
| 1294 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1295 | + }, | ||
| 1296 | + { | ||
| 1297 | + "release_at": "2016-03-12 00:19:56", | ||
| 1298 | + "name": "300199翰宇药业2016-03-18_2016年3月17日投资者关系活动记录表.pdf", | ||
| 1299 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-03-18_investor-relations-activity-record-for-march-17-2016_1065.pdf", | ||
| 1300 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1301 | + }, | ||
| 1302 | + { | ||
| 1303 | + "release_at": "2016-03-18 06:28:16", | ||
| 1304 | + "name": "300199翰宇药业2016-03-09_2016年3月4日投资者关系活动记录表.pdf", | ||
| 1305 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-03-09_investor-relations-activity-record-for-march-4-2016_2872.pdf", | ||
| 1306 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1307 | + }, | ||
| 1308 | + { | ||
| 1309 | + "release_at": "2016-02-0 05:23:16", | ||
| 1310 | + "name": "300199翰宇药业2016-02-23_2016年2月22日投资者关系活动记录表.pdf", | ||
| 1311 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-02-23_investor-relations-activity-record-for-february-22-2016_7179.pdf", | ||
| 1312 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1313 | + }, | ||
| 1314 | + { | ||
| 1315 | + "release_at": "2016-02-10 11:07:19", | ||
| 1316 | + "name": "300199翰宇药业2016-02-19_2016年2月18日投资者关系活动记录表.pdf", | ||
| 1317 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-02-19_investor-relations-activity-record-for-february-18-2016_6199.pdf", | ||
| 1318 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1319 | + }, | ||
| 1320 | + { | ||
| 1321 | + "release_at": "2016-01-4 07:39:04", | ||
| 1322 | + "name": "300199翰宇药业2016-01-18_2016年1月15日投资者关系活动记录表.pdf", | ||
| 1323 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-01-18_january-15-2016-investor-relations-activity-record_3283.pdf", | ||
| 1324 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1325 | + }, | ||
| 1326 | + { | ||
| 1327 | + "release_at": "2015-12-24 03:50:13", | ||
| 1328 | + "name": "300199翰宇药业2015-12-07_2015年12月4日投资者关系活动记录表.pdf", | ||
| 1329 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-12-07_investor-relations-activity-record-for-december-4-2015_1184.pdf", | ||
| 1330 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1331 | + }, | ||
| 1332 | + { | ||
| 1333 | + "release_at": "2015-11-7 03:04:24", | ||
| 1334 | + "name": "300199翰宇药业2015-11-26_2015年11月24日投资者关系活动记录表.pdf", | ||
| 1335 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-11-26_november-24-2015-investor-relations-activity-record_4876.pdf", | ||
| 1336 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1337 | + }, | ||
| 1338 | + { | ||
| 1339 | + "release_at": "2015-11-2 04:52:21", | ||
| 1340 | + "name": "300199翰宇药业2015-11-10_2015年11月9日投资者关系活动记录表.pdf", | ||
| 1341 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2015-11-10_november-9-2015-investor-relations-activity-record_6243.pdf", | ||
| 1342 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1343 | + }, | ||
| 1344 | + { | ||
| 1345 | + "release_at": "2015-11-3 10:18:40", | ||
| 1346 | + "name": "300199翰宇药业2015-11-02_2015年10月30日投资者关系活动记录表.pdf", | ||
| 1347 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-11-02_october-30-2015-investor-relations-activity-record_6537.pdf", | ||
| 1348 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1349 | + }, | ||
| 1350 | + { | ||
| 1351 | + "release_at": "2015-10-8 01:54:07", | ||
| 1352 | + "name": "300199翰宇药业2015-10-28_2015年10月23日投资者关系活动记录表pdf", | ||
| 1353 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2015-10-28_october-23-2015-investor-relations-activity-record_9215.pdf", | ||
| 1354 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1355 | + }, | ||
| 1356 | + { | ||
| 1357 | + "release_at": "2015-09-20 09:25:19", | ||
| 1358 | + "name": "300199翰宇药业2015-09-28_2015年9月25日投资者关系活动记录表.pdf", | ||
| 1359 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-09-28_investor-relations-activity-record-for-september-25-2015_4371.pdf", | ||
| 1360 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1361 | + }, | ||
| 1362 | + { | ||
| 1363 | + "release_at": "2015-09-14 03:22:29", | ||
| 1364 | + "name": "300199翰宇药业2015-09-25_2015年9月23日投资者关系活动记录表.pdf", | ||
| 1365 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-09-25_investor-relations-activity-record-for-september-23-2015_1884.pdf", | ||
| 1366 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1367 | + }, | ||
| 1368 | + { | ||
| 1369 | + "release_at": "2015-09-0 02:49:54", | ||
| 1370 | + "name": "300199翰宇药业2015-09-16_2015年9月15日投资者关系活动记录表.pdf", | ||
| 1371 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-09-16_investor-relations-activity-record-for-september-15-2015_5735.pdf", | ||
| 1372 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1373 | + }, | ||
| 1374 | + { | ||
| 1375 | + "release_at": "2015-09-19 08:36:09", | ||
| 1376 | + "name": "300199翰宇药业2015-09-10_2015年9月9日投资者关系活动记录表.pdf", | ||
| 1377 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2015-09-10_investor-relations-activity-record-for-september-9-2015_9112.pdf", | ||
| 1378 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1379 | + }, | ||
| 1380 | + { | ||
| 1381 | + "release_at": "2015-09-17 08:37:39", | ||
| 1382 | + "name": "300199翰宇药业2015-09-02_2015年9月2日投资者关系活动记录表.pdf", | ||
| 1383 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-09-02_investor-relations-activity-record-for-september-2-2015_4434.pdf", | ||
| 1384 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1385 | + }, | ||
| 1386 | + { | ||
| 1387 | + "release_at": "2015-09-15 10:21:34", | ||
| 1388 | + "name": "300199翰宇药业2015-09-01_2015年8月31日投资者关系活动记录表.pdf", | ||
| 1389 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2015-09-01_august-31-2015-investor-relations-activity-record_6139.pdf", | ||
| 1390 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1391 | + }, | ||
| 1392 | + { | ||
| 1393 | + "release_at": "2015-08-19 01:28:28", | ||
| 1394 | + "name": "300199翰宇药业2015-08-26_2015年8月25日投资者关系活动记录表.pdf", | ||
| 1395 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-08-26_august-25-2015-investor-relations-activity-record_2788.pdf", | ||
| 1396 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1397 | + }, | ||
| 1398 | + { | ||
| 1399 | + "release_at": "2015-08-17 01:03:11", | ||
| 1400 | + "name": "300199翰宇药业2015-08-25_2015年8月24日投资者关系活动记录表.pdf", | ||
| 1401 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-08-25_investor-relations-activity-record-for-august-24-2015_7740.pdf", | ||
| 1402 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1403 | + }, | ||
| 1404 | + { | ||
| 1405 | + "release_at": "2015-07-12 04:15:16", | ||
| 1406 | + "name": "300199翰宇药业2015-07-15_2015年7月13日投资者关系活动记录表.pdf", | ||
| 1407 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2015-07-15_investor-relations-activity-record-sheet-for-july-13-2015_3770.pdf", | ||
| 1408 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1409 | + }, | ||
| 1410 | + { | ||
| 1411 | + "release_at": "2015-07-14 01:17:02", | ||
| 1412 | + "name": "300199翰宇药业2015-07-03_2015年7月2日投资者关系活动记录表.pdf", | ||
| 1413 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-07-03_investor-relations-activity-record-for-july-2-2015_2854.pdf", | ||
| 1414 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1415 | + }, | ||
| 1416 | + { | ||
| 1417 | + "release_at": "2015-06-20 04:21:54", | ||
| 1418 | + "name": "300199翰宇药业2015-06-04_2015年6月3日投资者关系活动记录表.pdf", | ||
| 1419 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-06-04_investor-relations-activity-record-for-june-3-2015_7780.pdf", | ||
| 1420 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1421 | + }, | ||
| 1422 | + { | ||
| 1423 | + "release_at": "2015-05-5 02:41:28", | ||
| 1424 | + "name": "300199翰宇药业2015-05-20_2015年5月19日投资者关系活动记录表.pdf", | ||
| 1425 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-05-20_may-19-2015-investor-relations-activity-record-sheet_5850.pdf", | ||
| 1426 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1427 | + }, | ||
| 1428 | + { | ||
| 1429 | + "release_at": "2015-03-13 02:55:09", | ||
| 1430 | + "name": "300199翰宇药业2015-03-16_2015年3月13日投资者关系活动记录表.pdf", | ||
| 1431 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-03-16_investor-relations-activity-record-for-march-13-2015_9640.pdf", | ||
| 1432 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1433 | + }, | ||
| 1434 | + { | ||
| 1435 | + "release_at": "2015-01-17 06:16:52", | ||
| 1436 | + "name": "300199翰宇药业2015-01-12_2015年1月9日投资者关系活动记录表.pdf", | ||
| 1437 | + "href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-01-12_january-9-2015-investor-relations-activity-record_8915.pdf", | ||
| 1438 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1439 | + }, | ||
| 1440 | + { | ||
| 1441 | + "release_at": "2014-12-7 11:27:31", | ||
| 1442 | + "name": "300199翰宇药业2014-12-18_2014年12月17日投资者关系活动记录表.pdf", | ||
| 1443 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2014-12-18_investor-relations-activity-record-for-december-17-2014_1666.pdf", | ||
| 1444 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1445 | + }, | ||
| 1446 | + { | ||
| 1447 | + "release_at": "2014-12-12 02:07:13", | ||
| 1448 | + "name": "300199翰宇药业2014-12-17_2014年12月16日投资者关系活动记录表.pdf", | ||
| 1449 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2014-12-17_2014-december-16-investor-relations-activity-record_9100.pdf", | ||
| 1450 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1451 | + }, | ||
| 1452 | + { | ||
| 1453 | + "release_at": "2014-12-8 05:34:12", | ||
| 1454 | + "name": "300199翰宇药业2014-12-15_2014年12月11日投资者关系活动记录表.pdf", | ||
| 1455 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2014-12-15_investor-relations-activity-record-for-december-11-2014_3385.pdf", | ||
| 1456 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1457 | + }, | ||
| 1458 | + { | ||
| 1459 | + "release_at": "2014-11-11 05:37:37", | ||
| 1460 | + "name": "300199翰宇药业2014-11-26_2014年11月25日投资者关系活动记录表.pdf", | ||
| 1461 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2014-11-26_november-25-2014-investor-relations-activity-record_5012.pdf", | ||
| 1462 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1463 | + }, | ||
| 1464 | + { | ||
| 1465 | + "release_at": "2014-11-18 11:22:43", | ||
| 1466 | + "name": "300199翰宇药业2014-11-21_2014年11月20日投资者关系活动记录表.pdf", | ||
| 1467 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2014-11-21_november-20-2014-investor-relations-activity-record_8437.pdf", | ||
| 1468 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1469 | + }, | ||
| 1470 | + { | ||
| 1471 | + "release_at": "2014-09-13 01:21:08", | ||
| 1472 | + "name": "300199翰宇药业2014-09-03_2014年9月2日投资者关系活动记录表.pdf", | ||
| 1473 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2014-09-03_investor-relations-activity-record-for-september-2-2014_3385.pdf", | ||
| 1474 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1475 | + }, | ||
| 1476 | + { | ||
| 1477 | + "release_at": "2014-09-1 08:16:20", | ||
| 1478 | + "name": "300199翰宇药业2014-09-01_2014年8月28日投资者关系活动记录表.pdf", | ||
| 1479 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2014-09-01_august-28-2014-investor-relations-activity-record_6672.pdf", | ||
| 1480 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1481 | + }, | ||
| 1482 | + { | ||
| 1483 | + "release_at": "2014-02-2 08:48:09", | ||
| 1484 | + "name": "300199翰宇药业2014-02-14_2014年2月12日投资者关系活动记录表.pdf", | ||
| 1485 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2014-02-14_investor-relations-activity-record-sheet-for-february-12-2014_5304.pdf", | ||
| 1486 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1487 | + }, | ||
| 1488 | + { | ||
| 1489 | + "release_at": "2013-11-11 06:14:21", | ||
| 1490 | + "name": "300199翰宇药业2013-11-20_2013年11月19日投资者关系活动记录表.pdf", | ||
| 1491 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-11-20_november-19-2013-investor-relations-activity-record_3561.pdf", | ||
| 1492 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1493 | + }, | ||
| 1494 | + { | ||
| 1495 | + "release_at": "2013-11-16 00:45:28", | ||
| 1496 | + "name": "300199翰宇药业2013-11-07_2013年11月7日投资者关系活动记录表.pdf", | ||
| 1497 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-11-07_november-7-2013-investor-relations-activity-record-sheet_4976.pdf", | ||
| 1498 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1499 | + }, | ||
| 1500 | + { | ||
| 1501 | + "release_at": "2013-10-20 07:21:05", | ||
| 1502 | + "name": "300199翰宇药业2013-10-28_2013年10月24日投资者关系活动记录表.pdf", | ||
| 1503 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-10-28_october-24-2013-investor-relations-activity-record_4002.pdf", | ||
| 1504 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1505 | + }, | ||
| 1506 | + { | ||
| 1507 | + "release_at": "2013-09-0 01:26:27", | ||
| 1508 | + "name": "300199翰宇药业2013-09-18_2013年9月16日投资者关系活动记录表.pdf", | ||
| 1509 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-09-18_investor-relations-activity-record-sheet-for-september-16-2013_8969.pdf", | ||
| 1510 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1511 | + }, | ||
| 1512 | + { | ||
| 1513 | + "release_at": "2013-09-4 05:34:37", | ||
| 1514 | + "name": "300199翰宇药业2013-09-02_2013年8月29日投资者关系活动记录表.pdf", | ||
| 1515 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-09-02_august-29-2013-investor-relations-activity-record_3890.pdf", | ||
| 1516 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1517 | + }, | ||
| 1518 | + { | ||
| 1519 | + "release_at": "2013-08-14 09:42:40", | ||
| 1520 | + "name": "300199翰宇药业2013-08-26_2013年8月23日投资者关系活动记录表.pdf", | ||
| 1521 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-08-26_investor-relations-activity-record-for-august-23-2013_8170.pdf", | ||
| 1522 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1523 | + }, | ||
| 1524 | + { | ||
| 1525 | + "release_at": "2013-08-16 01:24:11", | ||
| 1526 | + "name": "300199翰宇药业2013-08-23_2013年8月21日投资者关系活动记录表.pdf", | ||
| 1527 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-08-23_august-21-2013-investor-relations-activity-record-sheet_4447.pdf", | ||
| 1528 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1529 | + }, | ||
| 1530 | + { | ||
| 1531 | + "release_at": "2013-08-11 00:48:03", | ||
| 1532 | + "name": "300199翰宇药业2013-08-16_2013年8月15日投资者关系活动记录表.pdf", | ||
| 1533 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-08-16_investor-relations-activity-record-for-august-15-2013_8819.pdf", | ||
| 1534 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1535 | + }, | ||
| 1536 | + { | ||
| 1537 | + "release_at": "2013-08-9 07:16:27", | ||
| 1538 | + "name": "300199翰宇药业2013-08-16_2013年8月14日投资者关系活动记录表.pdf", | ||
| 1539 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-08-16_august-14-2013-investor-relations-activity-record_6495.pdf", | ||
| 1540 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1541 | + }, | ||
| 1542 | + { | ||
| 1543 | + "release_at": "2013-07-17 04:33:50", | ||
| 1544 | + "name": "300199翰宇药业2013-07-10_2013年7月8日投资者关系活动记录表.pdf", | ||
| 1545 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-07-10_investor-relations-activity-record-for-july-8-2013_1373.pdf", | ||
| 1546 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1547 | + }, | ||
| 1548 | + { | ||
| 1549 | + "release_at": "2013-05-5 08:58:41", | ||
| 1550 | + "name": "300199翰宇药业2013-05-28_2013年5月24日投资者关系活动记录表.pdf", | ||
| 1551 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-05-28_may-24-2013-investor-relations-activity-record_6459.pdf", | ||
| 1552 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1553 | + }, | ||
| 1554 | + { | ||
| 1555 | + "release_at": "2013-05-22 02:49:11", | ||
| 1556 | + "name": "300199翰宇药业2013-05-15_2013年5月13日投资者关系活动记录表.pdf", | ||
| 1557 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-05-15_may-13-2013-investor-relations-activity-record_4417.pdf", | ||
| 1558 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1559 | + }, | ||
| 1560 | + { | ||
| 1561 | + "release_at": "2013-05-1 02:00:05", | ||
| 1562 | + "name": "300199翰宇药业2013-05-06_2013年4月26日投资者关系活动记录表.pdf", | ||
| 1563 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-05-06_investor-relations-activity-record-sheet-april-26-2013_2242.pdf", | ||
| 1564 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1565 | + }, | ||
| 1566 | + { | ||
| 1567 | + "release_at": "2013-04-19 03:49:10", | ||
| 1568 | + "name": "300199翰宇药业2013-04-16_2013年4月12日投资者关系活动记录表.pdf", | ||
| 1569 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-04-16_investor-relations-activity-record-for-april-12-2013_8343.pdf", | ||
| 1570 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1571 | + }, | ||
| 1572 | + { | ||
| 1573 | + "release_at": "2013-04-12 09:03:47", | ||
| 1574 | + "name": "300199翰宇药业2013-04-03_2013年4月2日投资者关系活动记录表.docx", | ||
| 1575 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-04-03_investor-relations-activity-record-for-april-2-2013_2768.docx", | ||
| 1576 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1577 | + }, | ||
| 1578 | + { | ||
| 1579 | + "release_at": "2013-03-9 09:45:36", | ||
| 1580 | + "name": "300199翰宇药业2013-03-29_2013年3月27日投资者关系活动记录表.docx", | ||
| 1581 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-03-29_investor-relations-activity-record-for-march-27-2013_3656.docx", | ||
| 1582 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1583 | + }, | ||
| 1584 | + { | ||
| 1585 | + "release_at": "2013-01-15 07:01:29", | ||
| 1586 | + "name": "300199翰宇药业2013-01-23_2013年1月21日投资者关系活动记录表.pdf", | ||
| 1587 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-01-23_january-21-2013-investor-relations-activity-record_2497.pdf", | ||
| 1588 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1589 | + }, | ||
| 1590 | + { | ||
| 1591 | + "release_at": "2013-01-1 07:55:57", | ||
| 1592 | + "name": "300199翰宇药业2013-01-21_2013年1月17日投资者关系活动记录表.pdf", | ||
| 1593 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-01-21_january-17-2013-investor-relations-activity-record-sheet_8184.pdf", | ||
| 1594 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1595 | + }, | ||
| 1596 | + { | ||
| 1597 | + "release_at": "2013-01-5 03:31:25", | ||
| 1598 | + "name": "300199翰宇药业2013-01-10_2013年1月8日投资者关系活动记录表.pdf", | ||
| 1599 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-01-10_january-8-2013-investor-relations-activity-record_2914.pdf", | ||
| 1600 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1601 | + }, | ||
| 1602 | + { | ||
| 1603 | + "release_at": "2012-12-2 04:20:21", | ||
| 1604 | + "name": "300199翰宇药业2012-12-14_2012年12月12日投资者关系活动记录表.pdf", | ||
| 1605 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2012-12-14_investor-relations-activity-record-for-december-12-2012_9336.pdf", | ||
| 1606 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1607 | + }, | ||
| 1608 | + { | ||
| 1609 | + "release_at": "2012-12-24 02:23:36", | ||
| 1610 | + "name": "300199翰宇药业2012-12-10_2012年12月6日投资者关系活动记录表.pdf", | ||
| 1611 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2012-12-10_investor-relations-activity-record-for-december-6-2012_3375.pdf", | ||
| 1612 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1613 | + }, | ||
| 1614 | + { | ||
| 1615 | + "release_at": "2012-11-3 00:18:53", | ||
| 1616 | + "name": "300199翰宇药业2012-11-26_2012年11月23日投资者关系活动记录表.pdf", | ||
| 1617 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2012-11-26_november-23-2012-investor-relations-activity-record_2930.pdf", | ||
| 1618 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1619 | + }, | ||
| 1620 | + { | ||
| 1621 | + "release_at": "2012-11-8 08:08:33", | ||
| 1622 | + "name": "300199翰宇药业2012-11-02_2012年10月30日投资者关系活动记录表.pdf", | ||
| 1623 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2012-11-02_october-30-2012-investor-relations-activity-record_3969.pdf", | ||
| 1624 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1625 | + }, | ||
| 1626 | + { | ||
| 1627 | + "release_at": "2012-10-9 06:57:38", | ||
| 1628 | + "name": "300199翰宇药业2012-10-29_2012年10月25日投资者关系活动记录表.pdf", | ||
| 1629 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2012-10-29_october-25-2012-investor-relations-activity-record_7493.pdf", | ||
| 1630 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1631 | + }, | ||
| 1632 | + { | ||
| 1633 | + "release_at": "2012-09-19 09:42:12", | ||
| 1634 | + "name": "300199翰宇药业2012-09-05_2012年9月3日投资者关系活动记录表.pdf", | ||
| 1635 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2012-09-05_investor-relations-activity-record-for-september-3-2012_6262.pdf", | ||
| 1636 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1637 | + }, | ||
| 1638 | + { | ||
| 1639 | + "release_at": "2012-08-2 07:20:35", | ||
| 1640 | + "name": "300199翰宇药业2012-08-30_2012年8月28日投资者关系活动记录表.pdf", | ||
| 1641 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2012-08-30_investor-relations-activity-record-for-august-28-2012_7849.pdf", | ||
| 1642 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1643 | + }, | ||
| 1644 | + { | ||
| 1645 | + "release_at": "2012-08-6 04:32:07", | ||
| 1646 | + "name": "300199翰宇药业2012-08-20_2012年8月16日投资者关系活动记录表.pdf", | ||
| 1647 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2012-08-20_investor-relations-activity-record-for-august-16-2012_7963.pdf", | ||
| 1648 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1649 | + }, | ||
| 1650 | + { | ||
| 1651 | + "release_at": "2012-08-20 00:38:33", | ||
| 1652 | + "name": "300199翰宇药业2012-08-17_2012年8月15日投资者关系活动记录表.pdf", | ||
| 1653 | + "href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2012-08-17_investor-relations-activity-record-for-august-15-2012_4739.pdf", | ||
| 1654 | + "image": "/upload/p/3531/image_other/2025-05/downloads.png" | ||
| 1655 | + } | ||
| 1656 | +]'; | ||
| 1657 | + $data = json_decode($str,true); | ||
| 1658 | + $customContentModel = new CustomModuleContent(); | ||
| 1659 | + $customExtendContentTModel = new CustomModuleExtentContent(); | ||
| 1660 | + foreach ($data as $item){ | ||
| 1661 | + $info = $customContentModel->read(['name'=>$item['name'],'project_id'=>$project_id,'module_id'=>5]); | ||
| 1662 | + if($info === false){ | ||
| 1663 | + $contentId = $customContentModel->addReturnId(['name'=>$item['name'],'image'=>$item['image'],'project_id'=>$project_id,'release_at'=>date('Y-m-d H:i:s'),'module_id'=>5]); | ||
| 1664 | + $route = RouteMap::setRoute($contentId, RouteMap::SOURCE_MODULE, $contentId, $project_id); | ||
| 1665 | + $customContentModel->edit(['route'=>$route],['id'=>$contentId]); | ||
| 1666 | + $saveData = [ | ||
| 1667 | + ['key'=>'pd_extended_field_1', 'type'=>4, 'values'=>$item['href'], 'content_id'=>$contentId, 'project_id'=>$project_id, 'module_id'=>5, 'created_at'=>date('Y-m-d H:i:s'), 'updated_at'=>date('Y-m-d H:i:s')], | ||
| 1668 | + ]; | ||
| 1669 | + $customExtendContentTModel->insert($saveData); | ||
| 1670 | + } | ||
| 1671 | + } | ||
| 1672 | + return true; | ||
| 1673 | + } | ||
| 583 | } | 1674 | } |
| @@ -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']), |
| @@ -203,7 +216,6 @@ class SyncProject extends Command | @@ -203,7 +216,6 @@ class SyncProject extends Command | ||
| 203 | */ | 216 | */ |
| 204 | public function sync($param,$is_update = 0){ | 217 | public function sync($param,$is_update = 0){ |
| 205 | //TODO::4月12日 之前的项目都是v6 | 218 | //TODO::4月12日 之前的项目都是v6 |
| 206 | - | ||
| 207 | $version = (($is_update == 1) ? Project::VERSION_SIX : (empty($param['version']) ? Project::VERSION_SEVEN : $param['version'])); | 219 | $version = (($is_update == 1) ? Project::VERSION_SIX : (empty($param['version']) ? Project::VERSION_SEVEN : $param['version'])); |
| 208 | $title = date('Ymd') . '-' . $param['company_name']; | 220 | $title = date('Ymd') . '-' . $param['company_name']; |
| 209 | $data = [ | 221 | $data = [ |
| 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', 'project_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 | + $json_thumb = Arr::a2s($thumb); | ||
| 48 | + if (strlen($json_thumb) <= 500) { | ||
| 49 | + $product->timestamps = false; | ||
| 50 | + $product->thumb = $json_thumb; | ||
| 51 | + $product->save(); | ||
| 52 | + | ||
| 53 | + $this->output('project_id:' . $product->project_id . ',product_id:' . $product->id . ' | success'); | ||
| 54 | + } | ||
| 55 | + } | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | + }); | ||
| 59 | + | ||
| 60 | + DB::disconnect('custom_mysql'); | ||
| 61 | + } | ||
| 62 | + | ||
| 63 | + $this->output('project_id:' . $project_id . ' | end'); | ||
| 64 | + } else { | ||
| 65 | + //所有项目 | ||
| 66 | + $projectModel = new Project(); | ||
| 67 | + $list = $projectModel->list(['delete_status' => 0, 'is_upgrade' => 0, 'type' => ['in', [1, 2, 3, 4, 6]]], 'id', ['id'], 'asc'); | ||
| 68 | + foreach ($list as $k => $v) { | ||
| 69 | + $project_id = $v['id']; | ||
| 70 | + | ||
| 71 | + $this->output('project_id:' . $project_id . ' | start'); | ||
| 72 | + | ||
| 73 | + $project_info = ProjectServer::useProject($project_id); | ||
| 74 | + | ||
| 75 | + if ($project_info) { | ||
| 76 | + $thumb_w = $project_info->deploy_build->thumb_w ?? 0; | ||
| 77 | + Product::select(['id', 'project_id', 'thumb'])->chunk(100, function ($products) use ($thumb_w) { | ||
| 78 | + foreach ($products as $product) { | ||
| 79 | + $thumb = $product->thumb; | ||
| 80 | + if (isset($thumb['url']) && $thumb['url']) { | ||
| 81 | + $new_thumb = thumbImageByUrl($thumb['url'], $thumb_w); | ||
| 82 | + if ($new_thumb != $thumb['url']) { | ||
| 83 | + $thumb['url'] = $new_thumb; | ||
| 84 | + $json_thumb = Arr::a2s($thumb); | ||
| 85 | + if (strlen($json_thumb) <= 500) { | ||
| 86 | + $product->timestamps = false; | ||
| 87 | + $product->thumb = $json_thumb; | ||
| 88 | + $product->save(); | ||
| 89 | + | ||
| 90 | + $this->output('project_id:' . $product->project_id . ',product_id:' . $product->id . ' | success'); | ||
| 91 | + } | ||
| 92 | + } | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | + }); | ||
| 96 | + | ||
| 97 | + DB::disconnect('custom_mysql'); | ||
| 98 | + } | ||
| 99 | + | ||
| 100 | + $this->output('project_id:' . $project_id . ' | end'); | ||
| 101 | + } | ||
| 102 | + } | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + | ||
| 106 | + /** | ||
| 107 | + * 输出处理日志 | ||
| 108 | + * @param $message | ||
| 109 | + * @return bool | ||
| 110 | + */ | ||
| 111 | + public function output($message) | ||
| 112 | + { | ||
| 113 | + echo date('Y-m-d H:i:s') . ' | ' . $message . PHP_EOL; | ||
| 114 | + return true; | ||
| 115 | + } | ||
| 116 | +} |
| @@ -48,7 +48,7 @@ class IndexedPages extends BaseCommands | @@ -48,7 +48,7 @@ class IndexedPages extends BaseCommands | ||
| 48 | $project_ids[] = 2104; | 48 | $project_ids[] = 2104; |
| 49 | } | 49 | } |
| 50 | foreach ($project_ids as $project_id){ | 50 | foreach ($project_ids as $project_id){ |
| 51 | - $rank_data = RankData::where('project_id', $project_id)->where('lang', '')->first(); | 51 | + $rank_data = RankData::where('project_id', $project_id)->where('api_no', $api_no)->where('lang', '')->first(); |
| 52 | if($rank_data){ | 52 | if($rank_data){ |
| 53 | $rank_data->indexed_pages_num = $num; | 53 | $rank_data->indexed_pages_num = $num; |
| 54 | $rank_data->save(); | 54 | $rank_data->save(); |
| @@ -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 |
| @@ -85,7 +85,7 @@ class HyStockData extends Command | @@ -85,7 +85,7 @@ class HyStockData extends Command | ||
| 85 | // 解析响应结果 | 85 | // 解析响应结果 |
| 86 | $responseResult = json_decode($response, true); | 86 | $responseResult = json_decode($response, true); |
| 87 | if ($responseResult) { | 87 | if ($responseResult) { |
| 88 | - $data = $responseResult['result'][0]['data']; | 88 | + $data = $responseResult['result'][0]['data'] ?? []; |
| 89 | if ($data) { | 89 | if ($data) { |
| 90 | //获取最近一条 | 90 | //获取最近一条 |
| 91 | $stock = StockData::orderBy('id', 'desc')->first(); | 91 | $stock = StockData::orderBy('id', 'desc')->first(); |
| @@ -43,7 +43,34 @@ class Temp extends Command | @@ -43,7 +43,34 @@ class Temp extends Command | ||
| 43 | 43 | ||
| 44 | public function handle() | 44 | public function handle() |
| 45 | { | 45 | { |
| 46 | - $this->specialImport(); | 46 | + |
| 47 | + } | ||
| 48 | + | ||
| 49 | + /** | ||
| 50 | + * 项目缩略图还原 | ||
| 51 | + * @param $project_id | ||
| 52 | + * @author Akun | ||
| 53 | + * @date 2025/09/04 10:48 | ||
| 54 | + */ | ||
| 55 | + public function thumbRollBack($project_id) | ||
| 56 | + { | ||
| 57 | + $project_info = ProjectServer::useProject($project_id); | ||
| 58 | + if ($project_info) { | ||
| 59 | + Product::select(['id', 'gallery'])->chunk(100, function ($products) { | ||
| 60 | + foreach ($products as $product) { | ||
| 61 | + $thumb = $product['gallery'][0] ?? []; | ||
| 62 | + if (!empty($thumb)) { | ||
| 63 | + $product->timestamps = false; | ||
| 64 | + $product->thumb = Arr::a2s($thumb); | ||
| 65 | + $product->save(); | ||
| 66 | + | ||
| 67 | + $this->output('product_id:' . $product->id . ' | success'); | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + }); | ||
| 71 | + | ||
| 72 | + DB::disconnect('custom_mysql'); | ||
| 73 | + } | ||
| 47 | } | 74 | } |
| 48 | 75 | ||
| 49 | /** | 76 | /** |
| @@ -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(['created_at'=>['between',[$startOfLast,$endOfLast]],'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 | } |
| @@ -431,7 +431,7 @@ class WebTraffic extends Command | @@ -431,7 +431,7 @@ class WebTraffic extends Command | ||
| 431 | $query->whereIn('ip_area', $main_countries); | 431 | $query->whereIn('ip_area', $main_countries); |
| 432 | } | 432 | } |
| 433 | if($filter_countries){ | 433 | if($filter_countries){ |
| 434 | - $query->whereNotIn('ip_area', $main_countries); | 434 | + $query->whereNotIn('ip_area', $filter_countries); |
| 435 | } | 435 | } |
| 436 | })->inRandomOrder()->first(); | 436 | })->inRandomOrder()->first(); |
| 437 | if(!$ipdata){ | 437 | if(!$ipdata){ |
| @@ -229,27 +229,30 @@ class FetchTicketProjects extends Command | @@ -229,27 +229,30 @@ class FetchTicketProjects extends Command | ||
| 229 | ManageHr::where('status', 1)->find($item->deploy_optimize->tech_leader)->manage_id ?? 0, | 229 | ManageHr::where('status', 1)->find($item->deploy_optimize->tech_leader)->manage_id ?? 0, |
| 230 | 8, //张鸿飞 | 230 | 8, //张鸿飞 |
| 231 | ])->first(fn($v) => $v !== null && $v !== 0, 0); | 231 | ])->first(fn($v) => $v !== null && $v !== 0, 0); |
| 232 | - | ||
| 233 | // 优化师 | 232 | // 优化师 |
| 234 | $seom_id = ManageHr::where('status', 1)->find($item->deploy_optimize->optimist_mid) ? ManageHr::where('status', 1)->find($item->deploy_optimize->optimist_mid)->manage_id : 0; | 233 | $seom_id = ManageHr::where('status', 1)->find($item->deploy_optimize->optimist_mid) ? ManageHr::where('status', 1)->find($item->deploy_optimize->optimist_mid)->manage_id : 0; |
| 235 | - | ||
| 236 | // 项目经理 | 234 | // 项目经理 |
| 237 | $pm_id = ManageHr::where('status', 1)->find($item->deploy_build->manager_mid)->manage_id ?? ManageHr::where('status', 1)->where('name', '李洁玉')->value('manage_id') ?? 0; | 235 | $pm_id = ManageHr::where('status', 1)->find($item->deploy_build->manager_mid)->manage_id ?? ManageHr::where('status', 1)->where('name', '李洁玉')->value('manage_id') ?? 0; |
| 238 | 236 | ||
| 239 | // 第一负责人 | 237 | // 第一负责人 |
| 240 | - /** | ||
| 241 | - * 5.0升级6.0的项目,白帽SEO, GEO的项目 都划给售后 | ||
| 242 | - * 其他:建站中找项目经理,建站完成找杨长远,推广找售后服务经理 | 238 | + /**单纯的5.0升级6.0的项目,自帽SE0,GE0的项目 部划给售后 |
| 239 | + 其他:建站中找项目经理,建站完成找杨长远,推广找售后服务经理 | ||
| 243 | */ | 240 | */ |
| 244 | - if ($item->is_upgrade || $item->project_type == 1 || $item->deploy_build->seo_plan > 0) | ||
| 245 | - $engineer_id = $assm_id; // V5升V6,白帽SEO,GEO,找售后服务经理 | ||
| 246 | - elseif ($status == 1) | ||
| 247 | - $engineer_id = $pm_id; // 建站中找项目经理 | ||
| 248 | - elseif ($status == 2) | ||
| 249 | - $engineer_id = Manage::where('status', 1)->where('name', '杨长远')->value('id') ?? 0; // 建站完成找杨长远 | ||
| 250 | - else | ||
| 251 | - $engineer_id = $assm_id; // 推广找售后服务经理 | ||
| 252 | - | 241 | + //todo::建站或同时为v6版本+GEO的,建站中项目给项目经理 |
| 242 | + if(($status == 1) && ($item->deploy_build->plan > 0) && ($item->deploy_build->seo_plan > 0)){ | ||
| 243 | + $engineer_id = $pm_id; //找项目经理 | ||
| 244 | + }else{ | ||
| 245 | + if ($item->is_upgrade || $item->project_type == 1 || $item->deploy_build->seo_plan > 0) | ||
| 246 | + $engineer_id = $assm_id; // V5升V6,白帽SEO,GEO,找售后服务经理 | ||
| 247 | + elseif ($status == 1) | ||
| 248 | + $engineer_id = $pm_id; // 建站中找项目经理 | ||
| 249 | + elseif ($status == 2) | ||
| 250 | + $engineer_id = Manage::where('status', 1)->where('name', '杨长远')->value('id') ?? 0; // 建站完成找杨长远 | ||
| 251 | + elseif ($status == 3) | ||
| 252 | + $engineer_id = $assm_id; // 推广找售后服务经理 | ||
| 253 | + else | ||
| 254 | + $engineer_id = $pm_id; //找项目经理 | ||
| 255 | + } | ||
| 253 | $is_del = ( | 256 | $is_del = ( |
| 254 | $item->extend_type == 5 | 257 | $item->extend_type == 5 |
| 255 | || $item->type == 8 | 258 | || $item->type == 8 |
| @@ -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,126 @@ function diffInHours($startTime, $endTime) | @@ -1440,3 +1468,126 @@ 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, 0, 0, 0);//先用v6-file地址 | ||
| 1495 | + if (strpos($url_complete, 'v6-file') !== false) { | ||
| 1496 | + $is_exists = checkRemoteFileExists($url_complete); | ||
| 1497 | + if (!$is_exists) { | ||
| 1498 | + //不存在,再用cdn地址 | ||
| 1499 | + $url_complete = getImageUrl($url); | ||
| 1500 | + } | ||
| 1501 | + } | ||
| 1502 | + | ||
| 1503 | + //获取与原图存储路径相同的压缩路径 | ||
| 1504 | + $path = parse_url($url_complete, PHP_URL_PATH); | ||
| 1505 | + $path_arr = explode('.', $path); | ||
| 1506 | + if (count($path_arr) != 2) { | ||
| 1507 | + return $url; | ||
| 1508 | + } | ||
| 1509 | + $path_arr[0] = $path_arr[0] . '_thumbW' . $width; | ||
| 1510 | + $key = implode('.', $path_arr); | ||
| 1511 | + | ||
| 1512 | + try { | ||
| 1513 | + $img = \Intervention\Image\Facades\Image::make($url_complete); | ||
| 1514 | + | ||
| 1515 | + //宽度按设定,高度自动调整 | ||
| 1516 | + $img->resize($width, null, function ($constraint) { | ||
| 1517 | + $constraint->aspectRatio(); | ||
| 1518 | + $constraint->upsize(); | ||
| 1519 | + }); | ||
| 1520 | + | ||
| 1521 | + //获取处理后的图片二进制资源 | ||
| 1522 | + $resource = $img->stream()->__toString(); | ||
| 1523 | + | ||
| 1524 | + //上传存储桶 | ||
| 1525 | + $thumb_url = CosService::uploadRemote('', '', '', $key, $resource); | ||
| 1526 | + | ||
| 1527 | + $url = $thumb_url ? $thumb_url : $url; | ||
| 1528 | + } catch (\Exception $e) { | ||
| 1529 | + Log::channel('thumb_img')->error($e->getMessage(), [$url, $width]); | ||
| 1530 | + } | ||
| 1531 | + | ||
| 1532 | + return $url; | ||
| 1533 | +} | ||
| 1534 | + | ||
| 1535 | +if (!function_exists('checkRemoteFileExists')) { | ||
| 1536 | + /** | ||
| 1537 | + * 判断远程文件是否存在 | ||
| 1538 | + * @param $url | ||
| 1539 | + * @return bool | ||
| 1540 | + * @author Akun | ||
| 1541 | + * @date 2025/09/05 9:58 | ||
| 1542 | + */ | ||
| 1543 | + function checkRemoteFileExists($url) | ||
| 1544 | + { | ||
| 1545 | + $curl = curl_init($url); | ||
| 1546 | + curl_setopt($curl, CURLOPT_NOBODY, true); | ||
| 1547 | + $result = curl_exec($curl); | ||
| 1548 | + $found = false; | ||
| 1549 | + if ($result !== false) { | ||
| 1550 | + $statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); | ||
| 1551 | + if ($statusCode == 200) { | ||
| 1552 | + $found = true; | ||
| 1553 | + } | ||
| 1554 | + } | ||
| 1555 | + curl_close($curl); | ||
| 1556 | + | ||
| 1557 | + return $found; | ||
| 1558 | + } | ||
| 1559 | +} | ||
| 1560 | + | ||
| 1561 | +if (!function_exists('httpGetSsl')) { | ||
| 1562 | + /** | ||
| 1563 | + * 获取通配符证书 | ||
| 1564 | + * @param $domain | ||
| 1565 | + * @return mixed | ||
| 1566 | + * @author Akun | ||
| 1567 | + * @date 2025/04/21 16:51 | ||
| 1568 | + */ | ||
| 1569 | + function httpGetSsl($domain) | ||
| 1570 | + { | ||
| 1571 | + $header = array( | ||
| 1572 | + "Accept:application/json", | ||
| 1573 | + "Content-Type:application/json;charset=utf-8", | ||
| 1574 | + "X-CmerApi-Host:" . env('GET_SSL_HOST'), | ||
| 1575 | + "Apikey:" . env('GET_SSL_KEY'), | ||
| 1576 | + ); | ||
| 1577 | + $ch = curl_init(); | ||
| 1578 | + curl_setopt($ch, CURLOPT_URL, env('GET_SSL_URL') . '?domain=' . $domain); | ||
| 1579 | + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET"); | ||
| 1580 | + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); | ||
| 1581 | + curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); | ||
| 1582 | + curl_setopt($ch, CURLOPT_HTTPHEADER, $header); | ||
| 1583 | + curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)'); | ||
| 1584 | + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); | ||
| 1585 | + curl_setopt($ch, CURLOPT_AUTOREFERER, 1); | ||
| 1586 | + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); | ||
| 1587 | + $res = curl_exec($ch); | ||
| 1588 | + curl_close($ch); | ||
| 1589 | + | ||
| 1590 | + $result = json_decode($res, true); | ||
| 1591 | + return is_array($result) ? $result : $res; | ||
| 1592 | + } | ||
| 1593 | +} |
| @@ -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 | } |
| @@ -2,9 +2,15 @@ | @@ -2,9 +2,15 @@ | ||
| 2 | 2 | ||
| 3 | namespace App\Http\Controllers\Api\WorkOrder; | 3 | namespace App\Http\Controllers\Api\WorkOrder; |
| 4 | 4 | ||
| 5 | +use App\Enums\Common\Code; | ||
| 5 | use App\Http\Controllers\Api\BaseController; | 6 | use App\Http\Controllers\Api\BaseController; |
| 7 | +use App\Http\Logic\Aside\Project\ProcessRecordsLogic; | ||
| 8 | +use App\Http\Logic\Aside\Project\ProjectLogic; | ||
| 6 | use App\Http\Requests\Api\WorkOrder\TicketListRequest; | 9 | use App\Http\Requests\Api\WorkOrder\TicketListRequest; |
| 7 | use App\Http\Requests\Api\WorkOrder\TicketStoreRequest; | 10 | use App\Http\Requests\Api\WorkOrder\TicketStoreRequest; |
| 11 | +use App\Models\Project\ProcessRecords; | ||
| 12 | +use App\Models\Project\Project; | ||
| 13 | +use App\Models\ProjectAssociation\ProjectAssociation; | ||
| 8 | use App\Models\WorkOrder\TicketLog; | 14 | use App\Models\WorkOrder\TicketLog; |
| 9 | use App\Models\WorkOrder\TicketProject; | 15 | use App\Models\WorkOrder\TicketProject; |
| 10 | use App\Models\WorkOrder\Tickets; | 16 | use App\Models\WorkOrder\Tickets; |
| @@ -183,4 +189,74 @@ class TicketController extends BaseController | @@ -183,4 +189,74 @@ class TicketController extends BaseController | ||
| 183 | $project->pushWechatGroupMsg("您好,我们同事没有及时回复,你可以查看工单进度!"); | 189 | $project->pushWechatGroupMsg("您好,我们同事没有及时回复,你可以查看工单进度!"); |
| 184 | return response()->json(['message' => '工单推送成功']); | 190 | return response()->json(['message' => '工单推送成功']); |
| 185 | } | 191 | } |
| 192 | + | ||
| 193 | + /** | ||
| 194 | + * @remark :工单中获取 | ||
| 195 | + * @name :get_process_records | ||
| 196 | + * @author :lyh | ||
| 197 | + * @method :post | ||
| 198 | + * @time :2025/9/9 15:28 | ||
| 199 | + */ | ||
| 200 | + public function get_project_records(Request $request){ | ||
| 201 | + $request->validate([ | ||
| 202 | + 'project_id'=>'required' | ||
| 203 | + ],[ | ||
| 204 | + 'project_id.required' => '项目ID不能为空' | ||
| 205 | + ]); | ||
| 206 | + $data = (new ProcessRecords())->read(['project_id'=>$this->param['project_id']]); | ||
| 207 | + $project = (new Project())->with(['payment', 'deploy_build', 'deploy_optimize', 'online_check', | ||
| 208 | + 'project_after','inquiry_filter_config','web_traffic_config','project_keyword'])->where(['id'=>$this->param['project_id']])->first()->toArray(); | ||
| 209 | + if(!$data){ | ||
| 210 | + $data = [ | ||
| 211 | + 'project_id' => $this->param['project_id'], | ||
| 212 | + 'record' => [], | ||
| 213 | + 'remark' => '', | ||
| 214 | + 'project_record'=>0, | ||
| 215 | + 'optimize_record'=>0, | ||
| 216 | + 'type'=>$project['type'] | ||
| 217 | + ]; | ||
| 218 | + }else{ | ||
| 219 | + $data['type'] = $project['type']; | ||
| 220 | + } | ||
| 221 | + $data['record'] = array_filter($data['record'], function($item) { | ||
| 222 | + return $item['date'] > '2025-09-01'; | ||
| 223 | + }); | ||
| 224 | + if($project['type'] == 2){ | ||
| 225 | + //优化项目 默认在seo优化中 | ||
| 226 | + if($data['optimize_record'] == 0) { | ||
| 227 | + $data['optimize_record'] = 1; | ||
| 228 | + } | ||
| 229 | + //时间大于优化时间,默认 | ||
| 230 | + if(date('Y-m-d') > $project['deploy_optimize']['start_date']){ | ||
| 231 | + $data['optimize_record'] = 2; | ||
| 232 | + } | ||
| 233 | + //首次达标时间 | ||
| 234 | + if(!empty($project['deploy_optimize']['first_compliance_time'])){ | ||
| 235 | + $data['optimize_record'] = 3; | ||
| 236 | + } | ||
| 237 | + //无剩余时间 | ||
| 238 | + if($project['project_type'] == 1){ | ||
| 239 | + $remain_day = $project['seo_remain_day']; | ||
| 240 | + if($project['seo_remain_day'] == 0){$data['optimize_record'] = 4;} | ||
| 241 | + }else{ | ||
| 242 | + $remain_day = $project['remain_day']; | ||
| 243 | + if($project['remain_day'] == 0){$data['optimize_record'] = 4;} | ||
| 244 | + } | ||
| 245 | + if(in_array(2,$project['level'])){ | ||
| 246 | + $data['date_project_record'] = ['暂停优化']; | ||
| 247 | + }else{ | ||
| 248 | + $data['date_project_record'] = Project::projectProgress('optimize'); | ||
| 249 | + $data['date_project_record'][4] .= (': '.$remain_day.'天'); | ||
| 250 | + } | ||
| 251 | + }else{ | ||
| 252 | + //查看是否绑定微信群 | ||
| 253 | + $projectAss = new ProjectAssociation(); | ||
| 254 | + $count = $projectAss->counts(['project_id'=>$this->param['project_id']]); | ||
| 255 | + if(($count > 0) && ($data['project_record'] == 0)){ | ||
| 256 | + $data['project_record'] = 1; | ||
| 257 | + } | ||
| 258 | + $data['date_project_record'] = Project::projectProgress('build'); | ||
| 259 | + } | ||
| 260 | + $this->response('success',Code::SUCCESS,$data); | ||
| 261 | + } | ||
| 186 | } | 262 | } |
| @@ -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', |
| @@ -322,9 +323,9 @@ class OptimizeController extends BaseController | @@ -322,9 +323,9 @@ class OptimizeController extends BaseController | ||
| 322 | $query = $query->where('gl_project_deploy_build.test_domain','like','%'.$this->map['test_domain'].'%'); | 323 | $query = $query->where('gl_project_deploy_build.test_domain','like','%'.$this->map['test_domain'].'%'); |
| 323 | } | 324 | } |
| 324 | $query = $query->where('gl_project.type',2)->where('gl_project.extend_type','!=',5);//TODO::2,4代表优化项目; 2024-06-05修改项目中台只显示为类型为2 | 325 | $query = $query->where('gl_project.type',2)->where('gl_project.extend_type','!=',5);//TODO::2,4代表优化项目; 2024-06-05修改项目中台只显示为类型为2 |
| 325 | - $query->where(function ($subQuery) { | ||
| 326 | - $subQuery->orwhere('gl_project_online_check.qa_status',1)->orwhere('gl_project.is_upgrade',1); | ||
| 327 | - }); | 326 | +// $query->where(function ($subQuery) { |
| 327 | +// $subQuery->where('gl_project.is_upgrade',1); | ||
| 328 | +// }); | ||
| 328 | return $query; | 329 | return $query; |
| 329 | } | 330 | } |
| 330 | 331 | ||
| @@ -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 | } |
| @@ -598,6 +598,7 @@ class ProjectController extends BaseController | @@ -598,6 +598,7 @@ class ProjectController extends BaseController | ||
| 598 | $this->response('success',Code::SUCCESS,$data); | 598 | $this->response('success',Code::SUCCESS,$data); |
| 599 | } | 599 | } |
| 600 | 600 | ||
| 601 | + | ||
| 601 | /** | 602 | /** |
| 602 | * 保存进程记录 | 603 | * 保存进程记录 |
| 603 | * @author zbj | 604 | * @author zbj |
| @@ -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,12 @@ namespace App\Http\Controllers\Aside\Ticket; | @@ -12,7 +12,12 @@ 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; | ||
| 20 | +use Illuminate\Support\Facades\Cache; | ||
| 16 | 21 | ||
| 17 | class TicketController extends BaseController | 22 | class TicketController extends BaseController |
| 18 | { | 23 | { |
| @@ -30,14 +35,91 @@ class TicketController extends BaseController | @@ -30,14 +35,91 @@ class TicketController extends BaseController | ||
| 30 | * @time :2025/8/11 10:47 | 35 | * @time :2025/8/11 10:47 |
| 31 | */ | 36 | */ |
| 32 | public function ticketCount(){ | 37 | public function ticketCount(){ |
| 33 | - $data['daily'] = $this->logic->getTicketCount(); | ||
| 34 | - $data['list'] = $this->logic->getDailyTicketCount(); | ||
| 35 | - $data['ticket'] = $this->logic->getTicketList(); | 38 | + $data = Cache::get('ticket_count'); |
| 39 | + if(empty($data)){ | ||
| 40 | + $data = []; | ||
| 41 | + $data['daily'] = $this->logic->getTicketCount(); | ||
| 42 | + $data['list'] = $this->logic->getDailyTicketCount(); | ||
| 43 | + $data['ticket'] = $this->logic->getTicketList(); | ||
| 44 | + Cache::put('ticket_count',$data,1800); | ||
| 45 | + } | ||
| 36 | $this->response('success',Code::SUCCESS,$data); | 46 | $this->response('success',Code::SUCCESS,$data); |
| 37 | } | 47 | } |
| 38 | 48 | ||
| 39 | /** | 49 | /** |
| 40 | - * @remark :技术组 | 50 | + * @remark :获取最近一个月的数据 |
| 51 | + * @name :getMonthList | ||
| 52 | + * @author :lyh | ||
| 53 | + * @method :post | ||
| 54 | + * @time :2025/8/30 17:26 | ||
| 55 | + */ | ||
| 56 | + public function getMonthList(){ | ||
| 57 | + $this->request->validate([ | ||
| 58 | + 'start'=>'required', | ||
| 59 | + 'end'=>'required' | ||
| 60 | + ],[ | ||
| 61 | + 'start.required' => 'start不能为空', | ||
| 62 | + 'end.required' => 'end不能为空', | ||
| 63 | + ]); | ||
| 64 | + $dailyModel = new TicketDailyCount(); | ||
| 65 | + $dailyList = $dailyModel->list(['date'=>['between',[$this->param['start'],$this->param['end']]]],'date',['*'],'desc',30);//取最近30条数据 | ||
| 66 | + $this->response('success',Code::SUCCESS,$dailyList); | ||
| 67 | + } | ||
| 68 | + /** | ||
| 69 | + * @remark :获取搜索时间 | ||
| 70 | + * @name :getTIme | ||
| 71 | + * @author :lyh | ||
| 72 | + * @method :post | ||
| 73 | + * @time :2025/8/30 15:39 | ||
| 74 | + */ | ||
| 75 | + public function getTime(){ | ||
| 76 | + $weekModel = new TicketWeekDeptCount(); | ||
| 77 | + $weekData = $weekModel->where('dept_id',1)->select('start_at', 'end_at')->distinct()->get()->toArray(); | ||
| 78 | + $monthModel = new TicketMonthDeptCount(); | ||
| 79 | + $monthData = $monthModel->where('dept_id',1)->select('start_at', 'end_at')->distinct()->get()->toArray(); | ||
| 80 | + $this->response('success',Code::SUCCESS,['week_data'=>$weekData,'month_data'=>$monthData]); | ||
| 81 | + } | ||
| 82 | + | ||
| 83 | + /** | ||
| 84 | + * @remark :周记录数据(默认上一周) | ||
| 85 | + * @name :weekManageList | ||
| 86 | + * @author :lyh | ||
| 87 | + * @method :post | ||
| 88 | + * @time :2025/8/30 15:31 | ||
| 89 | + */ | ||
| 90 | + public function weekManageList(){ | ||
| 91 | + $this->request->validate([ | ||
| 92 | + 'start'=>'required', | ||
| 93 | + 'end'=>'required' | ||
| 94 | + ],[ | ||
| 95 | + 'start.required' => 'start不能为空', | ||
| 96 | + 'end.required' => 'end不能为空', | ||
| 97 | + ]); | ||
| 98 | + $data = $this->logic->getWeekManageList($this->param['start'],$this->param['end'],$this->param['dept_id'] ?? 1,$this->order,$this->param['sort'] ?? 'desc'); | ||
| 99 | + $this->response('success',Code::SUCCESS,$data); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + /** | ||
| 103 | + * @remark :按月统计数据(默认上一月) | ||
| 104 | + * @name :monthManageList | ||
| 105 | + * @author :lyh | ||
| 106 | + * @method :post | ||
| 107 | + * @time :2025/8/30 15:35 | ||
| 108 | + */ | ||
| 109 | + public function monthManageList(){ | ||
| 110 | + $this->request->validate([ | ||
| 111 | + 'start'=>'required', | ||
| 112 | + 'end'=>'required' | ||
| 113 | + ],[ | ||
| 114 | + 'start.required' => 'start不能为空', | ||
| 115 | + 'end.required' => 'end不能为空', | ||
| 116 | + ]); | ||
| 117 | + $data = $this->logic->getMonthManageList($this->param['start'],$this->param['end'],$this->param['dept_id'] ?? 1,$this->order,$this->param['sort'] ?? 'desc'); | ||
| 118 | + $this->response('success',Code::SUCCESS,$data); | ||
| 119 | + } | ||
| 120 | + | ||
| 121 | + /** | ||
| 122 | + * @remark :技术组总统计 | ||
| 41 | * @name :manageTicketCount | 123 | * @name :manageTicketCount |
| 42 | * @author :lyh | 124 | * @author :lyh |
| 43 | * @method :post | 125 | * @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 | // 完成工单,把子任务里面未完成的工单改为完成 |
| @@ -311,5 +368,4 @@ class AsideTicketController extends BaseController | @@ -311,5 +368,4 @@ class AsideTicketController extends BaseController | ||
| 311 | $project->pushWechatGroupMsg(); | 368 | $project->pushWechatGroupMsg(); |
| 312 | $this->response('success', Code::SUCCESS); | 369 | $this->response('success', Code::SUCCESS); |
| 313 | } | 370 | } |
| 314 | - | ||
| 315 | } | 371 | } |
| @@ -232,12 +232,12 @@ class CNoticeController extends BaseController | @@ -232,12 +232,12 @@ class CNoticeController extends BaseController | ||
| 232 | } | 232 | } |
| 233 | //获取项目所在服务器 | 233 | //获取项目所在服务器 |
| 234 | $project_model = new Project(); | 234 | $project_model = new Project(); |
| 235 | - $project_info = $project_model->read(['id'=>$project_id],['serve_id','is_upgrade', 'main_lang_id']); | 235 | + $project_info = $project_model->read(['id'=>$project_id],['serve_id','type','is_upgrade', 'main_lang_id']); |
| 236 | if(!$project_info){ | 236 | if(!$project_info){ |
| 237 | $this->fail('未查询到项目数据'); | 237 | $this->fail('未查询到项目数据'); |
| 238 | } | 238 | } |
| 239 | // --------------------------------------------------- 特殊处理通知生成页面 -------------------------------------------------------------- | 239 | // --------------------------------------------------- 特殊处理通知生成页面 -------------------------------------------------------------- |
| 240 | - if ($type == 2 && $project_info['main_lang_id'] == 8) { | 240 | + if ($type == 2 && ($project_id != 4041) && ($project_info['main_lang_id'] == 8)) { |
| 241 | $this->fail('申请项目主语种为俄语,禁止翻译小语种,如若需要翻译小语种, 请联系售后人员确认!'); | 241 | $this->fail('申请项目主语种为俄语,禁止翻译小语种,如若需要翻译小语种, 请联系售后人员确认!'); |
| 242 | } | 242 | } |
| 243 | 243 |
| @@ -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 |
| @@ -398,7 +398,7 @@ class ImageController extends Controller | @@ -398,7 +398,7 @@ class ImageController extends Controller | ||
| 398 | foreach ($str_data as $k => $v){ | 398 | foreach ($str_data as $k => $v){ |
| 399 | $arr = explode('/',$v); | 399 | $arr = explode('/',$v); |
| 400 | if ($arr[0] == 'text') { | 400 | if ($arr[0] == 'text') { |
| 401 | - $arr[1] = urlSafeBase64Encode($arr[1]); | 401 | + $arr[1] = urlSafeBase64Encode($arr[1] ?? 'shuiying'); |
| 402 | $v = implode('/',$arr); | 402 | $v = implode('/',$arr); |
| 403 | } | 403 | } |
| 404 | if ($arr[0] == 'font') { | 404 | if ($arr[0] == 'font') { |
| @@ -195,19 +195,25 @@ class DomainInfoLogic extends BaseLogic | @@ -195,19 +195,25 @@ class DomainInfoLogic extends BaseLogic | ||
| 195 | $host = $domain_array['host'] ?? $domain_array['path']; | 195 | $host = $domain_array['host'] ?? $domain_array['path']; |
| 196 | $host_array = explode('.',$host); | 196 | $host_array = explode('.',$host); |
| 197 | 197 | ||
| 198 | + //已经解析泛域名的项目,更改项目解析状态 | ||
| 199 | + $host_array_any = $host_array; | ||
| 200 | + if (count($host_array_any) <= 2) { | ||
| 201 | + array_unshift($host_array_any, '*'); | ||
| 202 | + } else { | ||
| 203 | + $host_array_any[0] = '*'; | ||
| 204 | + } | ||
| 205 | + $any_domain = implode('.',$host_array_any); | ||
| 206 | + $rand_str = generateRandomString(3); | ||
| 207 | + $any_check_status = check_domain_record(str_replace('*',$rand_str,$any_domain), $serversIpInfo); | ||
| 208 | + if($any_check_status){ | ||
| 209 | + $project_model->edit(['is_analysis'=>1],['id'=>$info['project_id']]); | ||
| 210 | + } | ||
| 211 | + | ||
| 198 | if($this->param['type'] == 3){ | 212 | if($this->param['type'] == 3){ |
| 199 | //需要申请通配符证书 | 213 | //需要申请通配符证书 |
| 200 | 214 | ||
| 201 | - //判断*是否已经解析 | ||
| 202 | - $host_array_any = $host_array; | ||
| 203 | - if (count($host_array_any) <= 2) { | ||
| 204 | - array_unshift($host_array_any, '*'); | ||
| 205 | - } else { | ||
| 206 | - $host_array_any[0] = '*'; | ||
| 207 | - } | ||
| 208 | - $any_domain = implode('.',$host_array_any); | ||
| 209 | - $rand_str = generateRandomString(3); | ||
| 210 | - if(!check_domain_record(str_replace('*',$rand_str,$any_domain), $serversIpInfo)){ | 215 | + //判断是否已经解析泛域名 |
| 216 | + if(!$any_check_status){ | ||
| 211 | $this->fail('域名' . $any_domain . '未解析至目标服务器'); | 217 | $this->fail('域名' . $any_domain . '未解析至目标服务器'); |
| 212 | } | 218 | } |
| 213 | 219 |
| @@ -73,7 +73,7 @@ class GeoLinkLogic extends BaseLogic | @@ -73,7 +73,7 @@ class GeoLinkLogic extends BaseLogic | ||
| 73 | foreach ($this->param['data'] as $item){ | 73 | foreach ($this->param['data'] as $item){ |
| 74 | $data[] = [ | 74 | $data[] = [ |
| 75 | 'project_id'=>$this->param['project_id'], | 75 | 'project_id'=>$this->param['project_id'], |
| 76 | - 'da'=>$item['da'], | 76 | + 'da'=>$item['da'] ?? '', |
| 77 | 'url'=>$item['url'], | 77 | 'url'=>$item['url'], |
| 78 | 'send_time'=>$item['send_time'] | 78 | 'send_time'=>$item['send_time'] |
| 79 | ]; | 79 | ]; |
| @@ -7,6 +7,7 @@ use App\Http\Logic\Aside\BaseLogic; | @@ -7,6 +7,7 @@ use App\Http\Logic\Aside\BaseLogic; | ||
| 7 | use App\Models\Domain\DomainInfo; | 7 | use App\Models\Domain\DomainInfo; |
| 8 | use App\Models\Project\ProcessRecords; | 8 | use App\Models\Project\ProcessRecords; |
| 9 | use App\Models\Project\Project; | 9 | use App\Models\Project\Project; |
| 10 | +use App\Models\ProjectAssociation\ProjectAssociation; | ||
| 10 | 11 | ||
| 11 | class ProcessRecordsLogic extends BaseLogic | 12 | class ProcessRecordsLogic extends BaseLogic |
| 12 | { | 13 | { |
| @@ -20,14 +21,19 @@ class ProcessRecordsLogic extends BaseLogic | @@ -20,14 +21,19 @@ class ProcessRecordsLogic extends BaseLogic | ||
| 20 | public function getInfo($project_id) | 21 | public function getInfo($project_id) |
| 21 | { | 22 | { |
| 22 | $data = $this->model->read(['project_id'=>$project_id]); | 23 | $data = $this->model->read(['project_id'=>$project_id]); |
| 24 | + $info = $data; | ||
| 23 | $project = ProjectLogic::instance()->getProjectInfo($project_id); | 25 | $project = ProjectLogic::instance()->getProjectInfo($project_id); |
| 24 | if(!$data){ | 26 | if(!$data){ |
| 25 | $data = [ | 27 | $data = [ |
| 26 | 'project_id' => $project_id, | 28 | 'project_id' => $project_id, |
| 27 | 'record' => [], | 29 | 'record' => [], |
| 28 | 'remark' => '', | 30 | 'remark' => '', |
| 31 | + 'project_record'=>0, | ||
| 32 | + 'optimize_record'=>0, | ||
| 33 | + 'type'=>$project['type'] | ||
| 29 | ]; | 34 | ]; |
| 30 | } | 35 | } |
| 36 | + $data['type'] = $project['type'] ?? ''; | ||
| 31 | $data['project_company'] = $project['company'] ?? ''; | 37 | $data['project_company'] = $project['company'] ?? ''; |
| 32 | $plan = Project::planMap(); | 38 | $plan = Project::planMap(); |
| 33 | $seo_plan = Project::seoMap(); | 39 | $seo_plan = Project::seoMap(); |
| @@ -55,6 +61,45 @@ class ProcessRecordsLogic extends BaseLogic | @@ -55,6 +61,45 @@ class ProcessRecordsLogic extends BaseLogic | ||
| 55 | 'item' => ['资料上传', '网站修改中', '网站搭建完成,客户确认中', '等待网站品控审核后上线'] | 61 | 'item' => ['资料上传', '网站修改中', '网站搭建完成,客户确认中', '等待网站品控审核后上线'] |
| 56 | ] | 62 | ] |
| 57 | ]; | 63 | ]; |
| 64 | +// $data['record'] = array_filter($data['record'], function($item) { | ||
| 65 | +// return $item['date'] > '2025-09-01'; | ||
| 66 | +// }); | ||
| 67 | + if($project['type'] == 2){ | ||
| 68 | + //优化项目 默认在seo优化中 | ||
| 69 | + if($data['optimize_record'] == 0) { | ||
| 70 | + $data['optimize_record'] = 1; | ||
| 71 | + } | ||
| 72 | + //时间大于优化时间,默认 | ||
| 73 | + if(date('Y-m-d') > $project['deploy_optimize']['start_date']){ | ||
| 74 | + $data['optimize_record'] = 2; | ||
| 75 | + } | ||
| 76 | + //首次达标时间 | ||
| 77 | + if(!empty($project['deploy_optimize']['first_compliance_time'])){ | ||
| 78 | + $data['optimize_record'] = 3; | ||
| 79 | + } | ||
| 80 | + //无剩余时间 | ||
| 81 | + if($project['project_type'] == 1){ | ||
| 82 | + $remain_day = $project['seo_remain_day']; | ||
| 83 | + if($project['seo_remain_day'] == 0){$data['optimize_record'] = 4;} | ||
| 84 | + }else{ | ||
| 85 | + $remain_day = $project['remain_day']; | ||
| 86 | + if($project['remain_day'] == 0){$data['optimize_record'] = 4;} | ||
| 87 | + } | ||
| 88 | + if(in_array(2,$project['level'])){ | ||
| 89 | + $data['date_project_record'] = ['暂停优化']; | ||
| 90 | + }else{ | ||
| 91 | + $data['date_project_record'] = Project::projectProgress('optimize'); | ||
| 92 | + $data['date_project_record'][4] .= (': '.$remain_day.'天'); | ||
| 93 | + } | ||
| 94 | + }else{ | ||
| 95 | + //查看是否绑定微信群 | ||
| 96 | + $projectAss = new ProjectAssociation(); | ||
| 97 | + $count = $projectAss->counts(['project_id'=>$project_id]); | ||
| 98 | + if(($count > 0) && ($data['project_record'] == 0)){ | ||
| 99 | + $data['project_record'] = 1; | ||
| 100 | + } | ||
| 101 | + $data['date_project_record'] = Project::projectProgress('build'); | ||
| 102 | + } | ||
| 58 | return $this->success($data); | 103 | return $this->success($data); |
| 59 | } | 104 | } |
| 60 | 105 |
| @@ -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,$order = 'complete_num',$sort){ | ||
| 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],$order,['*'],$sort); | ||
| 131 | + $deptWeekModel = new TicketWeekDeptCount(); | ||
| 132 | + $deptWeekList = $deptWeekModel->list(['start_at'=>$start,'end_at'=>$end]); | ||
| 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 = 1,$order = 'complete_num',$sort = 'desc'){ | ||
| 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],$order,['*'],$sort); | ||
| 150 | + $deptWeekModel = new TicketMonthDeptCount(); | ||
| 151 | + $deptWeekList = $deptWeekModel->list(['start_at'=>$start,'end_at'=>$end]); | ||
| 152 | + return $this->success(['manage'=>$manageWeekList,'dept'=>$deptWeekList]); | ||
| 153 | + } | ||
| 113 | } | 154 | } |
| @@ -417,6 +417,8 @@ class CustomModuleContentLogic extends BaseLogic | @@ -417,6 +417,8 @@ class CustomModuleContentLogic extends BaseLogic | ||
| 417 | $info = $this->model->read(['id'=>$this->param['id']]); | 417 | $info = $this->model->read(['id'=>$this->param['id']]); |
| 418 | $param = $this->setContentParams($info); | 418 | $param = $this->setContentParams($info); |
| 419 | $save_id = $this->model->insertGetId($param); | 419 | $save_id = $this->model->insertGetId($param); |
| 420 | + $route = RouteMap::setRoute($param['route'], RouteMap::SOURCE_MODULE, $save_id, $this->user['project_id']); | ||
| 421 | + $this->edit(['route' => $route], ['id' => $save_id]); | ||
| 420 | $this->copyTemplate($this->param['id'],$info['project_id'],$save_id,$info['module_id']); | 422 | $this->copyTemplate($this->param['id'],$info['project_id'],$save_id,$info['module_id']); |
| 421 | return $this->success(['id'=>$save_id]); | 423 | return $this->success(['id'=>$save_id]); |
| 422 | } | 424 | } |
| @@ -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([]); |
| @@ -228,12 +228,12 @@ class RankDataLogic extends BaseLogic | @@ -228,12 +228,12 @@ class RankDataLogic extends BaseLogic | ||
| 228 | $api_no = $project['deploy_optimize']['api_no'] ?? 0; | 228 | $api_no = $project['deploy_optimize']['api_no'] ?? 0; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | -// if(!$api_no || Str::endsWith($api_no, '_bmseo')){ | 231 | + if(!$api_no || Str::endsWith($api_no, '_bmseo')){ |
| 232 | $bm_api_no = RankDataBmseo::where('project_id', $project_id)->value('api_no'); | 232 | $bm_api_no = RankDataBmseo::where('project_id', $project_id)->value('api_no'); |
| 233 | if($bm_api_no){ | 233 | if($bm_api_no){ |
| 234 | $api_no = $bm_api_no; | 234 | $api_no = $bm_api_no; |
| 235 | } | 235 | } |
| 236 | -// } | 236 | + } |
| 237 | 237 | ||
| 238 | $domain = (!empty($project['deploy_optimize']['domain']) ? ((new DomainInfo())->getDomain($project['deploy_optimize']['domain'])) : ''); | 238 | $domain = (!empty($project['deploy_optimize']['domain']) ? ((new DomainInfo())->getDomain($project['deploy_optimize']['domain'])) : ''); |
| 239 | $domain_arr = parse_url($domain); | 239 | $domain_arr = parse_url($domain); |
| @@ -555,7 +555,7 @@ class RankDataLogic extends BaseLogic | @@ -555,7 +555,7 @@ class RankDataLogic extends BaseLogic | ||
| 555 | $without_extension_project_ids = [658]; //是否达标只统计主词的 | 555 | $without_extension_project_ids = [658]; //是否达标只统计主词的 |
| 556 | $extension_project_ids = [354]; //扩展词也到达标的 | 556 | $extension_project_ids = [354]; //扩展词也到达标的 |
| 557 | $compliance_project_ids = [2163,257,823,1750,497]; //直接达标处理的 | 557 | $compliance_project_ids = [2163,257,823,1750,497]; //直接达标处理的 |
| 558 | - $ceaseProjectId = [354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250,2193,2399,1685];//暂停的项目 | 558 | + $ceaseProjectId = [354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250,2193,2399,1685, 3931];//暂停的项目 |
| 559 | $uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目 | 559 | $uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目 |
| 560 | //一个项目多个api_no | 560 | //一个项目多个api_no |
| 561 | $multiple_api_no_project_ids = [ | 561 | $multiple_api_no_project_ids = [ |
| @@ -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 | } |
| @@ -178,6 +178,38 @@ class Project extends Base | @@ -178,6 +178,38 @@ class Project extends Base | ||
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | /** | 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 => 'SEO设置', | ||
| 200 | + 2 => '开始推广', | ||
| 201 | + 3 => '排名达标', | ||
| 202 | + 4 => '剩余服务时长' | ||
| 203 | + ] | ||
| 204 | + ]; | ||
| 205 | + | ||
| 206 | + if(!empty($search)){ | ||
| 207 | + return $data[$search]; | ||
| 208 | + } | ||
| 209 | + return $data; | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + /** | ||
| 181 | * @remark :新增搜索 | 213 | * @remark :新增搜索 |
| 182 | * @name :searchParam | 214 | * @name :searchParam |
| 183 | * @author :lyh | 215 | * @author :lyh |
| @@ -2,6 +2,7 @@ | @@ -2,6 +2,7 @@ | ||
| 2 | 2 | ||
| 3 | namespace App\Models\ProjectAssociation; | 3 | namespace App\Models\ProjectAssociation; |
| 4 | 4 | ||
| 5 | +use App\Models\Base; | ||
| 5 | use Illuminate\Database\Eloquent\Builder; | 6 | use Illuminate\Database\Eloquent\Builder; |
| 6 | use Illuminate\Database\Eloquent\Model; | 7 | use Illuminate\Database\Eloquent\Model; |
| 7 | 8 | ||
| @@ -38,7 +39,7 @@ use Illuminate\Database\Eloquent\Model; | @@ -38,7 +39,7 @@ use Illuminate\Database\Eloquent\Model; | ||
| 38 | * @method Builder|ProjectAssociation whereUserName($value) | 39 | * @method Builder|ProjectAssociation whereUserName($value) |
| 39 | * @mixin \Eloquent | 40 | * @mixin \Eloquent |
| 40 | */ | 41 | */ |
| 41 | -class ProjectAssociation extends Model | 42 | +class ProjectAssociation extends Base |
| 42 | { | 43 | { |
| 43 | 44 | ||
| 44 | protected $table = 'gl_project_association'; | 45 | protected $table = 'gl_project_association'; |
-
请 注册 或 登录 后发表评论