作者 ZhengBing He

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

正在显示 47 个修改的文件 包含 3318 行增加396 行删除

要显示太多修改。

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

... ... @@ -293,6 +293,9 @@ class AiBlogTask extends Command
$domainModel = new DomainInfo();
$project_model = new Project();
foreach ($routes as $project_id => $route){
if($project_id == 4339){
continue;
}
$route[] = 'top-blog';
$domain = $domainModel->getProjectIdDomain($project_id);
if (empty($domain)) {
... ...
... ... @@ -113,7 +113,7 @@ class DomainInfo extends Command
} else {
//除自建站项目外,记录已解析到别的ip的域名
if (!check_domain_record($v['domain'], $servers_ip_info)) {
Log::channel('analyze_other')->error('域名 [' . $v['domain'] . '] 已解析到别的IP');
Log::channel('analyze_other')->error('服务器ID [' . $servers_ip_info['servers_id'] . '] 域名 [' . $v['domain'] . '] 已解析到别的IP');
continue;
}
... ... @@ -166,7 +166,7 @@ class DomainInfo extends Command
if ($servers_ip_info['servers_id'] != ServerConfig::SELF_SITE_ID) {
//过滤已解析到别的ip的AMP域名
if (!check_domain_record($amp_domain, $servers_ip_info)) {
Log::channel('analyze_other')->error('AMP域名 [' . $amp_domain . '] 已解析到别的IP');
Log::channel('analyze_other')->error('服务器ID [' . $servers_ip_info['servers_id'] . '] AMP域名 [' . $amp_domain . '] 已解析到别的IP');
continue;
}
}
... ... @@ -324,7 +324,7 @@ class DomainInfo extends Command
//过滤已解析到别的ip的域名
if (!check_domain_record($v['custom_domain'], $servers_ip_info)) {
Log::channel('analyze_other')->error('自定义跳转域名 [' . $v['custom_domain'] . '] 已解析到别的IP');
Log::channel('analyze_other')->error('服务器ID [' . $servers_ip_info['servers_id'] . '] 自定义跳转域名 [' . $v['custom_domain'] . '] 已解析到别的IP');
continue;
}
... ...
... ... @@ -43,7 +43,7 @@ class RemainDay extends Command
* @var 暂停的项目
*/
protected $ceaseProjectId = [
354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250, 2193, 2399, 1685
354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250, 2193, 2399, 1685, 3931
];//需要单独处理的项目
/**
* The console command description.
... ... @@ -118,7 +118,7 @@ class RemainDay extends Command
*/
public function seoRemainDay($deploy_build,$item){
//白帽版本的系统
if($deploy_build['seo_plan'] == 1){
if($deploy_build['seo_plan'] != 0){
if($deploy_build['seo_service_duration'] != 0){
if(in_array($item['id'],$this->bm_projectId) || (in_array( 19,$item['level']))){
$compliance_day = (int)$item['bm_finish_remain_day'];
... ...
... ... @@ -119,24 +119,23 @@ class GeoQuestionRes extends Command
$hit_data = array_merge($url, $title, $hit_data);
}
$hit = 0;
//todo::与预期结果是否复合
if(!empty($taskInfo['expect_result'])){
$str = "客户提出的问题:{$question},客户得到的回复:{$result['text']},客户需要预期:{$taskInfo['expect_result']},请分析得到的回复和预期是否一致,仅回复我是或者否";
$strResult = $geo_service->getChatResult($str, 'gpt-4o-mini');
if(isset($strResult['text']) && !empty($strResult['text'])){
switch ($strResult['text']){
case '是':
$is_match = 1;
$hit++;
break;
case '否':
$is_match = 2;
break;
default:
$is_match = 0;
break;
}
$is_match = 0;
$cosine = 0;
$similarity = [];
// TODO 有预期结果,分析答案和预期结果
if(FALSE == empty($taskInfo['expect_result'])){
$cosine_result = $geo_service->cosineSimilarity($taskInfo['expect_result'], $result['text']);
// 语义是否一致
if (FALSE == empty($cosine_result['judgement'])) {
$is_match = $cosine_result['judgement'] == '语义相近' ? 1 : 2;
$hit++;
}
// 余弦相似度
if (FALSE == empty($cosine_result['similarity']))
$cosine = intval($cosine_result['similarity'] * 10000) / 100;
// 语句拆解结果
if (FALSE == empty($cosine_result['split_results']))
$similarity = $cosine_result['split_results'];
}
$hit_keyword = $this->getKeywords($taskInfo['keywords'],$hit_data);
if (!empty($hit_keyword['keywords'])) {
... ... @@ -165,6 +164,8 @@ class GeoQuestionRes extends Command
'url_num'=>$url_num ?? [],
'is_match'=>$is_match ?? 0,
'label'=>$taskInfo['label'] ?? null,
'cosine' => $cosine,
'similarity' => json_encode($similarity, true),
'created_at'=>date('Y-m-d H:i:s'),
'updated_at'=>date('Y-m-d H:i:s'),
];
... ... @@ -315,17 +316,6 @@ class GeoQuestionRes extends Command
}
/**
* @remark :预期结果对比
* @name :getExpectResult
* @author :lyh
* @method :post
* @time :2025/8/12 13:51
*/
public function getExpectResult($question,$answer,$expect){
$str = "客户提出的问题:{$question},客户得到的回复:{$answer},客户需要预期:{$expect},请分析得到的回复和预期是否一致,仅回复我是或者否";
}
/**
* 获取待执行任务ID
* @return mixed
*/
... ...
<?php
/**
* Created by PhpStorm.
* User: zhl
* Date: 2024/09/30
* Time: 11:51
*/
namespace App\Console\Commands\Inquiry;
use App\Helper\Common;
use App\Helper\Gpt;
use App\Helper\Translate;
use App\Helper\Validate;
use App\Models\Ai\AiCommand;
use App\Models\Inquiry\ReInquiryConfig;
use App\Models\Inquiry\ReInquiryDetail;
use App\Models\Inquiry\ReInquiryDetailLog;
use App\Models\Inquiry\ReInquiryForm;
use App\Models\Inquiry\ReInquiryTask;
use App\Models\Inquiry\ReInquiryText;
use App\Models\Project\InquiryFilterConfig;
use App\Models\Project\Project;
use App\Models\WebSetting\WebLanguage;
use Illuminate\Console\Command;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
/**
* Class RelayInquiry
* @package App\Console\Commands\Inquiry
*/
class RelayInquiryTest extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'relay_inquiry_test';
/**
* The console command description.
*
* @var string
*/
protected $description = '重启失败的转发询盘';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* 模拟访问来源占比
* @var array
*/
protected $lyzb = [
'https://www.google.com/' => 630,
'http://www.google.com/' => 30,
'http://www.bing.com/' => 20,
'https://www.bing.com/' => 5,
'https://www.youtube.com/' => 5,
'https://search.yahoo.com/' => 5,
'https://www.facebook.com/' => 5,
];
/**
* 俄语站 模拟访问来源占比
* @var array
*/
protected $eylyzb = [
'https://www.yandex.com/' => 630,
'https://www.google.com/' => 30,
'http://www.google.com/' => 30,
'http://www.bing.com/' => 20,
'https://www.bing.com/' => 5,
'https://www.youtube.com/' => 5,
'https://search.yahoo.com/' => 5,
'https://www.facebook.com/' => 5,
];
/**
* PC端访问头信息
* @var array
*/
protected $pc_ua = [
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',
1 => 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36',
2 => 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1'
];
/**
* 移动端访问头信息
* @var array
*/
protected $mobile_ua = [
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',
];
/**
* google域名后缀
* @var string[]
*/
protected $suffix = [
'co.jp' => '日本',
'com.tr' => '土耳其',
'nl' => '荷兰',
'ru' => '俄罗斯',
'fr' => '法国',
'co.kr' => '韩国',
'fi' => '芬兰',
'be' => '比利时',
'lt' => '立陶宛',
'es' => '西班牙',
'it' => '意大利',
'com.au' => '澳大利亚',
'no' => '挪威',
'al' => '阿尔巴尼亚',
'pt' => '葡萄牙',
'lv' => '拉脱维亚',
'hu' => '匈牙利',
'cz' => '捷克',
'de' => '德国',
'ca' => '加拿大',
'co.in' => '印度',
'co.uk' => '英国',
'com.vn' => '越南',
'com.br' => '巴西',
'co.il' => '以色列',
'pl' => '波兰',
'com.eg' => '埃及',
'co.th' => '泰国',
'sk' => '斯洛伐克',
'ro' => '罗马尼亚',
'com.mx' => '墨西哥',
'com.my' => '马来西亚',
'com.pk' => '巴基斯坦',
'co.nz' => '新西兰',
'co.za' => '南非',
'com.ar' => '阿根廷',
'com.kw' => '科威特',
'com.sg' => '新加坡',
'com.co' => '哥伦比亚',
'co.id' => '印度尼西亚',
'gr' => '希腊',
'bg' => '保加利亚',
'mn' => '蒙古',
'dk' => '丹麦',
'com.sa' => '沙特阿拉伯',
'com.pe' => '秘鲁',
'com.ph' => '菲律宾',
'com.ua' => '乌克兰',
'ge' => '格鲁吉亚',
'ae' => '阿拉伯联合酋长国',
'tn' => '突尼斯',
];
protected $otherzb = [700, 300]; //模拟访问来源占比 (非美国) google.com|google.其他后缀
/**
* 手机号过滤 0去掉+ 1不转发手机 2不处理
* @var int[]
*/
protected $filter_phone = [30,12,58];
/**
* 需要多个ip访问的国家
* @var
*/
protected $multiple_ip_visit_country = [
'阿尔及利亚',
'埃及',
'埃塞俄比亚',
'安哥拉',
'贝宁',
'博茨瓦纳',
'布基纳法索',
'布隆迪',
'赤道几内亚',
'多哥',
'厄立特里亚',
'佛得角',
'冈比亚',
'刚果共和国',
'刚果民主共和国',
'吉布提',
'几内亚',
'几内亚比绍共和国',
'加纳',
'加蓬',
'津巴布韦',
'喀麦隆',
'科摩罗',
'科特迪瓦',
'肯尼亚',
'莱索托',
'利比里亚',
'利比亞',
'留尼汪',
'卢旺达',
'马达加斯加',
'马拉维',
'马里',
'马约特',
'毛里求斯',
'毛里塔尼亚',
'摩洛哥',
'莫桑比克',
'纳米比亚',
'南非',
'南苏丹',
'尼日尔',
'尼日利亚',
'塞拉利昂',
'塞内加尔',
'塞舌尔',
'圣多美和普林西比',
'圣赫勒拿',
'斯威士兰',
'索马里',
'坦桑尼亚',
'突尼斯',
'乌干达',
'西撒哈拉',
'赞比亚',
'乍得',
'中非共和国',
'阿富汗',
'阿联酋',
'阿曼',
'阿塞拜疆',
'澳门',
'巴基斯坦',
'巴勒斯坦',
'巴林',
'不丹',
'东帝汶',
'菲律宾',
'格鲁吉亚',
'哈萨克斯坦',
'韩国',
'吉尔吉斯斯坦',
'柬埔寨',
'卡塔尔',
'科威特',
'老挝',
'黎巴嫩',
'马尔代夫',
'马来西亚',
'蒙古',
'孟加拉国',
'缅甸',
'尼泊尔',
'日本',
'塞浦路斯',
'沙特阿拉伯',
'斯里兰卡',
'塔吉克斯坦',
'泰国',
'土耳其',
'土库曼斯坦',
'文莱',
'乌兹别克斯坦',
'新加坡',
'亚美尼亚',
'也门',
'伊拉克',
'以色列',
'印度尼西亚',
'约旦',
'越南',
];
/**
* @return bool
*/
public function handle()
{
while (true) {
$inquiry = ReInquiryForm::where('created_at', '>', '2025-05-19 00:00:00')
->where('created_at', '<', '2025-05-22 18:00:00')
->where(['status' => ReInquiryForm::STATUS_FORGO])
->where('remark', '超时72小时未处理!')
->orderBy('id', 'asc')->get();
if ($inquiry->isEmpty()){
$this->output('未发现待处理询盘!');
sleep(60);
continue;
}
$this->output('开始处理本轮询盘!');
foreach ($inquiry as $key=>$val) {
$this->output('询盘ID:' . $val->id);
$detail_ids = ReInquiryDetail::where('form_id', $val->id)->pluck('id')->toArray();
$inquiry_log = ReInquiryDetailLog::whereIn('detail_id', $detail_ids)->where('type', ReInquiryDetailLog::TYPE_INQUIRY)->first();
//有询盘的了 就跳过
if($inquiry_log){
continue;
}
// 询盘对应广告
$ad_task = $this->getAdTask($val->ad_id);
// 没有获取到转发任务
if (empty($ad_task)) {
$val->status = ReInquiryForm::STATUS_FORGO;
$val->remark = '未找到需要转发的广告任务!';
$val->save();
continue;
}
// 未设置对法对象
$target_num_arr = array_map(function ($item) {
return count($item['target']) + count($item['shop_site']) + count($item['fob_pro']);
}, $ad_task);
if (!array_sum($target_num_arr)) {
$val->status = ReInquiryForm::STATUS_FORGO;
$val->remark = '广告任务转发对象为空!';
$val->save();
continue;
}
//是否要过滤
$filter_res = $this->filter($val);
if($filter_res !== true){
$val->status = ReInquiryForm::STATUS_FORGO;
$val->remark = $filter_res;
$val->save();
continue;
}
//验证手机号 无效 号码不推送
if(!Validate::phone($val->phone)){
$val->phone = '';
}
try {
$res = false;
foreach ($ad_task as $task){
$res += $this->relayDetail($task, $val);
$res += $this->relayShopDetail($task, $val);
$res += $this->relayFobDetail($task, $val);
}
$val->status = $res ? ReInquiryForm::STATUS_SUCCESS : ReInquiryForm::STATUS_FORGO;
$val->save();
} catch (\Exception $e) {
$this->logChannel()->info('执行询盘错误:',[$e->getMessage(), $e->getFile(), $e->getLine()]);
$this->output('执行询盘错误:' . $e->getMessage());
}
}
$this->output('本轮询盘处理结束!');
}
return true;
}
public function filter($data)
{
//通用过滤规则
$config = InquiryFilterConfig::getCacheInfoByProjectId(Project::DEMO_PROJECT_ID);
//FB询盘的全局过滤规则
$fb_config = ReInquiryConfig::getDefaultConfigCache(ReInquiryConfig::TYPE_FILTER_WORDS);
$fb_config['filter_contents'] = array_filter(explode("\r\n", $fb_config['filter_contents']??''));
$fb_config['filter_emails'] = array_filter(explode("\r\n", $fb_config['filter_emails']??''));
$fb_config['filter_mobiles'] = array_filter(explode("\r\n", $fb_config['filter_mobiles']??''));
$fb_config['filter_names'] = array_filter(explode("\r\n", $fb_config['filter_names']??''));
$config['filter_contents'] = array_unique(array_merge($fb_config['filter_contents'],$config['filter_contents']));
$config['filter_emails'] = array_unique(array_merge($fb_config['filter_emails'],$config['filter_emails']));
$config['filter_mobiles'] = array_unique(array_merge($fb_config['filter_mobiles'],$config['filter_mobiles']));
$config['filter_names'] = array_unique(array_merge($fb_config['filter_names'],$config['filter_names']));
//过滤内容
if(!empty($data['message']) && !empty($config['filter_contents'])) {
foreach ($config['filter_contents'] as $filter_content) {
if (Str::contains(strtolower($data['message']), strtolower($filter_content))) {
return '过滤内容:' . $filter_content;
}
}
}
//过滤邮箱
if(!empty($data['email']) && !empty($config['filter_emails'])){
foreach ($config['filter_emails'] as $filter_email){
if(Str::contains(strtolower($data['email']), strtolower($filter_email))){
return '过滤邮箱:' . $filter_email;
}
}
//邮箱有效性
if(!Validate::email($data['email'])){
return '邮箱无效';
}
}
//过滤电话
if(!empty($data['phone']) && !empty($config['filter_mobiles'])){
foreach ($config['filter_mobiles'] as $filter_mobile){
if(Str::contains(strtolower($data['phone']), strtolower($filter_mobile))){
return '过滤电话:' . $filter_mobile;
}
}
}
//过滤姓名
if(!empty($data['full_name'] && !empty($config['filter_names']))){
foreach ($config['filter_names'] as $filter_name){
if(Str::contains(strtolower($data['full_name']), strtolower($filter_name))){
return '过滤姓名:' . $filter_name;
}
}
}
return true;
}
/**
* 创建转发详情
* TODO 通过任务生成转发对象, 更具转发对象获取对应数据, 写入着陆记录
* @param $task
* @param $form
* @return bool
*/
public function relayDetail($task, $form)
{
$this->output('获取转发对象');
if(empty($task['target'] )){
$this->output('没有独立站转发对象');
return 0;
}
//是否有必选的渠道 渠道有一个及以上必选 就在组内随机一个
$require_agent_group = [];
foreach ($task['target'] as $item) {
if (!empty($item['is_require'])) {
$require_agent_group[] = $item['agent_group'];
}
}
$require_agent_group = array_unique($require_agent_group);
$require_agent_group_data = collect($task['target'])->whereIn('agent_group', $require_agent_group)->groupBy('agent_group');
$require_data = $require_agent_group_data->keys()->random(count($require_agent_group))->map(function ($group) use ($require_agent_group_data) {
return $require_agent_group_data[$group]->random();
})->all();
//代理商组 一个组只发一个
$agent_group = collect($task['target'])->whereNotIn('agent_group', $require_agent_group)->groupBy('agent_group');
// 获取转发对象 重置num数量, array_rand数量不足会报错
$task['num'] = $task['num'] - count($require_agent_group);
$num = $task['num'] > count($agent_group) ? count($agent_group) : $task['num'];
$random_data = $agent_group->keys()->random($num)->map(function ($group) use ($agent_group) {
return $agent_group[$group]->random();
})->all();
$random_data = array_merge($require_data, $random_data);
if (empty($random_data)) {
$this->logChannel()->info('当前任务未发现转发对象!', ['广告任务ID:' . $task['id'], '询盘ID:' . $form->id]);
$form->remark = $form->remark . '当前任务未发现转发对象,广告ID: ' . $form->ad_id . '!';
return false;
}
$this->logChannel()->info('随机域名', array_column($random_data, 'url'));
foreach ($random_data as $item) {
$times = 1;
$inquiry_time = 1;
//需要多个ip访问的国家 随机2-5次访问,只有一次询盘
if (in_array($form->country_name, $this->multiple_ip_visit_country)) {
$times = mt_rand(1, 2); //随机次数
$inquiry_time = mt_rand(1, $times); //第几次询盘
$this->output('多次访问模拟:' . $times .',第' . $inquiry_time . '次询盘');
}
for ($i = 1; $i <= $times; $i++) {
$is_inquiry = ($inquiry_time == $i);
if($is_inquiry){
$this->output('第' . $i . '次询盘');
}
//手机号过滤
$phone = $form->phone;
$filter_phone = $this->get_rand($this->filter_phone);
if($filter_phone == 0){
$phone = trim(str_replace("+", '', $phone));
}elseif($filter_phone == 1){
$phone = '';
}
// 推送站点
$domain = $item['url'];
$is_v6 = $item['is_v6'];
$re_website = 'https://' . $domain . '/';
//urls
list($urls, $lang, $inquiry_product_url) = $this->getUrls($is_v6, $domain, $re_website, $form, $task);
if(!$urls){
continue;
}
//ip
$ip_data = $this->getIpData($form->country_name);
$ip = $ip_data->ip;
$country_name = $ip_data->ip_area;
//message
$message = '';
$message_id = 0;
$msg_lang = '';
if($is_inquiry) {
list($message, $message_id, $msg_lang) = $this->getMessage($task, $form->message, $domain, $inquiry_product_url);
}
$lang = $lang ?: $msg_lang;
$this->output('获取转发设备信息');
// 客户端 头信息 来源
$device_port = $form->email ? '1' : '2'; //1 pc 2移动端
$user_agent = $form->email ? Arr::random($this->pc_ua) : Arr::random($this->mobile_ua);
$referrer = $this->getReferer($country_name, $lang);
$this->output('写入数据');
$pre = 0;
$start_time = strtotime($form->inquiry_date);
if($start_time < time()){
$start_time = time();
$seconds = rand(0, 72 * 3600); // 3天内发完
}else{
$seconds = rand(100, 2 * 3600);
}
$email = '';
if($is_inquiry) {
$exists = ReInquiryDetail::where('re_website', $domain)->where('email', $form->email)->first();
if ($exists) {
$this->output('转发站点邮件已存在');
// continue;
}
$email = $form->email;
}
dump(date('Y-m-d H:i:s', $start_time + $seconds));
// 写入推送详情
$re_detail = ReInquiryDetail::createInquiry($task['id'], $form->id, $domain, $country_name, $ip, $form->full_name, $email, $phone, $message, $message_id, $device_port,
$user_agent, $referrer, $urls, $is_v6, date('Y-m-d H:i:s', $start_time + $seconds));
foreach ($urls as $k=>$v){
$pre++;
$seconds += rand(5,60);
ReInquiryDetailLog::createInquiryLog($re_detail->id, ReInquiryDetailLog::TYPE_VISIT, $pre, $v, date('Y-m-d H:i:s', $start_time + $seconds));
// 最后一次访问询盘 加上询盘
if($is_inquiry && ($k+1) == count($urls)){
$this->output('第' . ($k+1) . '个链接询盘');
$seconds += rand(30,120);
$pre++;
ReInquiryDetailLog::createInquiryLog($re_detail->id, ReInquiryDetailLog::TYPE_INQUIRY, $pre, $v, date('Y-m-d H:i:s', $start_time + $seconds));
}
}
}
}
return true;
}
public function relayShopDetail($task, $form)
{
$this->output('获取商城转发对象');
if(empty($task['shop_site'])){
$this->output('没有商城转发对象');
return 0;
}
$num = $task['num'] > count($task['shop_site']) ? count($task['shop_site']) : $task['num'];
$shop_site = collect($task['shop_site'])->random($num)->all();
foreach ($shop_site as $item) {
//手机号过滤
$phone = $form->phone;
// 推送站点
$domain = $item;
$re_website = 'https://' . $domain . '/';
$paths = ['', 'contact-us'];
$url = $re_website . $paths[array_rand($paths)];
//ip
$ip_data = $this->getIpData($form->country_name);
$ip = $ip_data->ip;
$country_name = $ip_data->ip_area;
//message
list($message, $message_id, $lang) = $this->getMessage($task, $form->message, $domain);
$device_port = $form->email ? '1' : '2'; //1 pc 2移动端
$user_agent = $form->email ? Arr::random($this->pc_ua) : Arr::random($this->mobile_ua);
$referrer = $this->getReferer($country_name, $lang);
$start_time = strtotime($form->inquiry_date);
if($start_time < time()){
$start_time = time();
$seconds = rand(0, 48 * 3600); // 开始时间 从5-2小时后开始
}else{
$seconds = rand(100, 2 * 3600);
}
dump(date('Y-m-d H:i:s', $start_time + $seconds));
$exists = ReInquiryDetail::where('re_website', $domain)->where('email', $form->email)->first();
if($exists){
$this->output('转发站点邮件已存在');
continue;
}
$re_detail = ReInquiryDetail::createInquiry($task['id'], $form->id, $domain, $country_name, $ip, $form->full_name, $form->email, $phone, $message, $message_id,
$device_port, $user_agent, $referrer, [$url], 0, date('Y-m-d H:i:s', $start_time + $seconds), ReInquiryDetail::STATUS_INIT, 2);
ReInquiryDetailLog::createInquiryLog($re_detail->id, ReInquiryDetailLog::TYPE_INQUIRY, 1, $url, date('Y-m-d H:i:s', $start_time + $seconds));
}
return true;
}
public function relayFobDetail($task, $form)
{
$this->output('获取FOB转发对象');
if(empty($task['fob_pro'])){
$this->output('没有FOB转发对象');
return 0;
}
foreach ($task['fob_pro'] as $item) {
//手机号过滤
$phone = $form->phone;
// 推送站点
$postid = $item;
//message
list($message, $message_id, $lang) = $this->getMessage($task, $form->message, $postid);
$device_port = $form->email ? '1' : '2'; //1 pc 2移动端
$user_agent = $form->email ? Arr::random($this->pc_ua) : Arr::random($this->mobile_ua);
$start_time = strtotime($form->inquiry_date);
if($start_time < time()){
$start_time = time();
$seconds = rand(0, 10 * 3600); // 开始时间 从5-2小时后开始
}else{
$seconds = rand(100, 2 * 3600);
}
dump(date('Y-m-d H:i:s', $start_time + $seconds));
$exists = ReInquiryDetail::where('re_website', $postid)->where('email', $form->email)->first();
if($exists){
$this->output('转发站点邮件已存在');
continue;
}
$re_detail = ReInquiryDetail::createInquiry($task['id'], $form->id, $postid, $country_name??'', $ip??'', $form->full_name, $form->email, $phone,
$message, $message_id, $device_port, $user_agent, $referrer??'', [$postid], 0, date('Y-m-d H:i:s', $start_time + $seconds), ReInquiryDetail::STATUS_INIT, 3);
ReInquiryDetailLog::createInquiryLog($re_detail->id, ReInquiryDetailLog::TYPE_INQUIRY, 1, $postid, date('Y-m-d H:i:s', $start_time + $seconds));
}
return true;
}
public function getIpData($country_name){
$this->output('获取转发ip');
$country = $country_name;
// 有国家 通过国家查询, 如果没有获取到就随机获取
$where = [];
$country && $where['ip_area'] = $country;
$ip_data = DB::table('gl_xunpan_ipdata')->where($where)->inRandomOrder()->first();
if (empty($ip_data)) {
$ip_data = DB::table('gl_xunpan_ipdata')->inRandomOrder()->first();
}
return $ip_data;
}
public function getMessage($task, $message, $domain, $inquiry_product_url = ''){
$this->output('转发内容');
$form_message = $message;
$message_id = 0;
// TODO 当原始询盘内容长度大于15个字符, 60%几率直接发送原始内容。
if (strlen($message) >= 15) {
$not_use_probability = AiCommand::where('key', 'fb_inquiry_text')->value('not_use_probability');
$randomNumber = rand(0, 100);
if($randomNumber < $not_use_probability){
//原内容非英语,转为对应语种
if (is_numeric($form_message)) { //数字会被识别为中文
$lang = 'en';
} else {
$translateSl = Translate::translateSl($form_message);
$lang = $translateSl['texts']['sl'] ?? 'en';
}
return [$message, $message_id, $lang??''];
}
}
//开启文案替换
if ($task['is_replace_text'] == 2) {
//AI生成
$error = 0;
while ($error<3){
$message = $this->ai_send($task['ai_param'], $message, $inquiry_product_url);
if(!$message){
$this->output('AI文案生成失败');
$error++;
if($error==2){
$task['is_replace_text'] = 1;
$this->output('AI文案生成失败,使用文案库');
}
}else{
break;
}
}
}
if ($task['is_replace_text'] == 1 || strlen($message) <= 4) {
//配置文案库替换或者字符少于4个,直接替换文案
$use_ids = ReInquiryDetail::where(['re_website' => $domain])->where('status', '<>', ReInquiryDetail::STATUS_FAIL)->pluck('text_id')->toArray();
$text = ReInquiryText::whereNotIn('id', $use_ids)->where('status', ReInquiryText::STATUS_USABLE)->inRandomOrder()->first();
$message = $text->content;
$message_id = $text->id;
// 获取后,使用次数+1
$text->use_time += 1;
$text->save();
//原内容非英语,转为对应语种
if (is_numeric($form_message)) { //数字会被识别为中文
$lang = 'en';
} else {
$translateSl = Translate::translateSl($form_message);
$lang = $translateSl['texts']['sl'] ?? 'en';
}
if ($lang != 'en' && !Str::contains($lang, 'zh')) {
$message = Translate::tran($message, $lang);
}
}
return [$message, $message_id, $lang??''];
}
public function getUrls($is_v6, $domain, $re_website, $form, $task){
$this->output('转发对象:' . $domain);
$this->output('获取转发链接');
// v6:有邮箱推送主站,没有邮箱推送AMP站;v5:仅推送有邮箱到主站
$lang = '';
if ($is_v6) {
// 获取语种, 6.0是可以确定语种的
$project = Project::getProjectByDomain($domain);
if (empty($project)) {
$this->logChannel()->info('广告任务ID:' . $task['id'] . ', 转发对象:' . $re_website . '非v6链接,转发失败;', ['广告任务ID:' . $task['id'], '询盘ID:' . $form->id]);
return [[], $lang];
}
$lang = WebLanguage::getLangById($project->main_lang_id ?? 1)['short'];
// 获取访问明细和着陆页
$product_url = $this->getLinksFromSitemap($re_website . 'product_sitemap.xml');
$product_cate_url = $this->getLinksFromSitemap($re_website . 'product_category_sitemap.xml');
$keywords_url = $this->getLinksFromSitemap($re_website . 'product_keywords_sitemap.xml');
$page_url = $this->getLinksFromSitemap($re_website . 'page_sitemap.xml');
} else {
if($form->email){
//通过sitemap拿访问页面
$product_url = $this->getLinksFromSitemap($re_website . 'sitemap_post.xml');
$product_cate_url = $this->getLinksFromSitemap($re_website . 'sitemap_category.xml');
$keywords_url = $this->getLinksFromSitemap($re_website . 'sitemap_post_tag.xml');
$page_url = $this->getLinksFromSitemap($re_website . 'sitemap_page.xml');
}else{
//m站先就往contact-us着陆
$product_url = $product_cate_url = $keywords_url = [];
$page_url = [$re_website . 'contact-us/'];
}
}
// 所有可用url
$urls = $inquiry_urls = [];
//入口url 首页30%,单页10%,聚合页60%
$type = getRandByRatio([30,10,60]);
$inlet = $re_website;
$type == 1 && $inlet = $page_url ? Arr::random($page_url) : $re_website;
$type == 2 && $inlet = $keywords_url ? Arr::random($keywords_url) : $re_website;
$urls[] = $inquiry_urls[] = $inlet;
$all_urls = array_merge($urls, $product_url, $product_cate_url, $keywords_url, $page_url);
$inquiry_urls = array_merge($urls, $product_cate_url, $keywords_url, $page_url);
// 随机访问1-6个页面
$deep = rand(1,6);
if($deep > 2) {
$visit_urls = Arr::random($all_urls, rand(1, count($all_urls) > 4 ? 4 : count($all_urls)));
$urls = array_merge($urls, $visit_urls);
}
if($deep > 1) {
// 推送着落页只能是 首页、产品分类、单页面、聚合页
if (!in_array(end($urls), $inquiry_urls)) {
$urls[] = Arr::random($inquiry_urls);
}
}
//着陆页是否是产品页面或产品列表页
$inquiry_product_url = '';
if(in_array(Arr::last($urls), $product_url) || in_array(Arr::last($urls), $product_cate_url)){
$inquiry_product_url = Arr::last($urls);
}
return [$urls, $lang, $inquiry_product_url];
}
/**
* 获取待处理询盘表单
* @param int $num
* @return mixed
*/
public function getInquiry($num = 10)
{
$result = ReInquiryForm::where(['status' => ReInquiryForm::STATUS_INIT])->orderBy('id', 'asc')->limit($num)->get();
return $result;
}
/**
* 获取广告任务配置数据
* @param $ad_id
* @return array
*/
public function getAdTask($ad_id)
{
$cache_key = 'inquiry_ads_tasks';
$ads = Cache::get($cache_key, function () use ($cache_key) {
$ads = ReInquiryTask::where(['status' => ReInquiryTask::STATUS_OPEN])->get(['id', 'ad_id', 'num', 'target', 'is_replace_text', 'ai_param', 'shop_site', 'fob_pro']);
$array = [];
foreach ($ads as $key=>$val) {
$ad_ids = explode(',', $val['ad_id']);
foreach ($ad_ids as $ad_id){
$array[$ad_id][] = $val;
}
}
if ($array)
Cache::put($cache_key, $array, 60);
return $array;
});
return empty($ads[$ad_id]) ? [] : $ads[$ad_id];
}
/**
* 获取头信息
* @param $ip_area
* @param $lang
* @return int|string
*/
public function getReferer($ip_area, $lang)
{
if($lang == 'ru'){
return $this->get_rand($this->eylyzb);
}
if($ip_area == '美国'){
$referer = $this->get_rand($this->lyzb);
}else{
$referer = 'https://www.google.com/';
$suffix = array_search($ip_area, $this->suffix);
if($suffix){
$res_qtzb = $this->get_rand($this->otherzb);
if($res_qtzb == 1){
$referer = 'https://www.google.'.$suffix.'/';
}
}
}
return $referer;
}
/**
* 概率算法
* @param $proArr
* @return int|string
*/
protected function get_rand($proArr)
{
$result = '';
$proSum = array_sum($proArr);
foreach ($proArr as $key => $proCur) {
$randNum = mt_rand(1, $proSum);
if ($randNum <= $proCur) {
$result = $key;
break;
} else {
$proSum -= $proCur;
}
}
unset ($proArr);
return $result;
}
/**
* 获取sitemap内容
* @param $sitemapUrl
* @return array|mixed
*/
function getLinksFromSitemap($sitemapUrl) {
try {
//忽略cert证书 先下载到临时文件
$result = Http::withoutVerifying()->get($sitemapUrl)->body();
$tempFilePath = tempnam(sys_get_temp_dir(), 'remote_file_');
file_put_contents($tempFilePath, $result);
$xml = simplexml_load_file($tempFilePath);
$links = [];
foreach ($xml->url as $url) {
$loc = (string) $url->loc;
if(!Str::contains($loc, ['404', 'thanks', 'test'])){
$links[] = $loc;
}
}
//随机取20个
$total = count($links);
return Arr::random($links, $total > 20 ? 20 : $total);
}catch (\Exception $e){
echo date('Y-m-d H:i:s') . 'sitemap获取失败:' . $e->getMessage() . PHP_EOL;
return $links??[];
}
}
public function ai_send($ai_param, $incontent, $inquiry_product_url)
{
$ai_command = AiCommand::where('key', 'fb_inquiry_text')->value('ai');
if (!$ai_command) {
return '';
}
$translateSl = Translate::translateSl($incontent);
$lang = $translateSl['texts']['sl'] ?? 'en';
if ($lang == 'en' || $lang == 'ja' || $lang == 'ko' || Str::contains($lang, 'zh')) {
$language = '英文';
$lang = 'en';
}else{
$language = Translate::getTls($lang);
}
//着陆页是否是产品页面或产品列表页
if($inquiry_product_url){
$title = Common::getUrlTitle($inquiry_product_url);
if($title){
$ai_command = str_replace('{mkeywords}', $title, $ai_command);
}
}
$ai_command = str_replace('{mkeywords}', Arr::random(explode("\r\n", $ai_param['mkeywords'])), $ai_command);
$ai_command = str_replace('{incontent}', Arr::random(explode("\r\n", $incontent)), $ai_command);
$ai_command = str_replace('{characters}', Arr::random(explode("\r\n", $ai_param['characters'])), $ai_command);
// $ai_command = str_replace('{language}', Arr::random(explode("\r\n", $language)), $ai_command);
$ai_command = str_replace('{language}', '英语', $ai_command); //输出英文 后面再翻译
$ai_command = str_replace('{inkeywords}', Arr::random(explode("\r\n", $ai_param['inkeywords'])), $ai_command);
$ai_command = str_replace('{suoxie}', Arr::random(explode("\r\n", $ai_param['suoxie'])), $ai_command);
//中括号里的根据概率使用
preg_match_all("/\[([^\]]+)\]/", $ai_command, $matches);
foreach ($matches[1] as $k => $match){
//按比例使用
$matche_arr = explode('|', $match);
$percentage = intval(trim($matche_arr[0], "%"));
if(rand(1,100) <= $percentage){
//使用
$ai_command = str_replace($matches[0][$k], $matche_arr[1], $ai_command);
}else{
//删除中括号
$ai_command = str_replace($matches[0][$k], '', $ai_command);
}
}
$text = Gpt::instance()->openai_chat_qqs($ai_command);
if ($lang != 'en' && !Str::contains($lang, 'zh')) {
$text = Translate::tran($text, $lang);
}
$this->logChannel()->info("AI询盘文案", [$ai_command, $text]);
return Common::deal_str($text);
}
/**
* @return \Psr\Log\LoggerInterface
*/
public function logChannel()
{
return Log::channel('inquiry_relay');
}
public function output($message)
{
echo date('Y-m-d H:i:s') . ' | ' . $message . PHP_EOL;
}
}
... ...
... ... @@ -174,7 +174,7 @@ class VideoTask extends Command
'is_ytb'=>false,
'other_language_subtitle'=>false
];
$result = Http::post('http://216.250.255.116:7866/create_task', $data);
$result = Http::post('http://216.250.255.116:7866/create_task', $data);//todo::小天的接口
$res_json = json_decode($result,true);
$val->task_id = $task_id;
$val->status = KeywordVideoTaskLog::STATUS_ERROR;
... ...
... ... @@ -52,9 +52,10 @@ class LyhImportTest extends Command
* @time :2023/11/20 15:13
*/
public function handle(){
ProjectServer::useProject(3654);
echo date('Y-m-d H:i:s') . 'start' . PHP_EOL;
$this->importProductCategory('https://ecdn6-nc.globalso.com/upload/p/3654/file/2025-06/products-1.csv',3654);
ProjectServer::useProject(3531);
echo date('Y-m-d H:i:s') . 'start->3531' . PHP_EOL;
// $this->importProductCategory('https://ecdn6-nc.globalso.com/upload/p/3654/file/2025-06/products-1.csv',3654);
$this->import3531CustomModule(3531);
DB::disconnect('custom_mysql');
echo date('Y-m-d H:i:s') . 'end' . PHP_EOL;
}
... ... @@ -580,4 +581,1094 @@ class LyhImportTest extends Command
// }
}
}
/**
* @remark :导入扩展模块数据
* @name :import3153CustomModule
* @author :lyh
* @method :post
* @time :2025/9/10 14:44
*/
public function import3531CustomModule($project_id = 3531){
$str = '[
{
"release_at": "2024-09-22 10:07:56",
"name": "300199翰宇药业投资者关系管理信息20240905.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2024-05-0 01:06:09",
"name": "300199翰宇药业投资者关系管理信息20240510.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-05-10_300199-hanyu-pharmaceutical-investor-relations-management-information-20240510_3774.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2023-10-12 10:43:39",
"name": "300199翰宇药业2023-10-13_2023年10月11-12日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2023-10-13_2023-october-11-12-investor-relations-activity-record-sheet_7992.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2023-02-22 00:40:24",
"name": "300199翰宇药业2023年02月03日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2023-05-29_300199-hanyu-pharmaceutical-research-activity-information-20230529_5609.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2022-06-20 08:09:53",
"name": "300199翰宇药业调研活动信息20220601.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2022-05-0 02:58:18",
"name": "300199翰宇药业调研活动信息20220509.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2022-05-09_300199-hanyu-pharmaceutical-research-activity-information-20220509_8714.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2021-11-13 04:07:53",
"name": "300199翰宇药业调研活动信息20211102.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2021-11-02_300199-hanyu-pharmaceutical-research-activity-information-20211102_7796.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2021-09-2 10:36:12",
"name": "300199翰宇药业调研活动信息20210903.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2021-09-03_300199-hanyu-pharmaceutical-research-activity-information-20210903_4654.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2020-12-22 02:06:25",
"name": "300199翰宇药业调研活动信息20201203.doc",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2020-12-03_300199-hanyu-pharmaceutical-research-activity-information-20201203_3714.doc",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2020-10-16 01:11:15",
"name": "300199翰宇药业投资者关系管理制度20201016.doc",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceuticals-2020-10-16_300199-hanyu-pharmaceuticals-investor-relations-management-system-20201016_9487.doc",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2020-09-1 05:09:01",
"name": "300199翰宇药业投资者关系管理档案20200915_3643.doc",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceuticals-2020-09-15_300199-hanyu-pharmaceuticals-investor-relations-management-file-20200915_3643.doc",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2024-09-3 01:32:32",
"name": "300199翰宇药业投资者关系管理信息20240905_8114.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2020-08-9 01:15:23",
"name": "300199翰宇药业2020-08-25_投资者关系管理制度_7744.PDF",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2020-08-25_investor-relations-management-system_7744.PDF",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2024-08-20 11:07:20",
"name": "300199翰宇药业投资者关系管理档案20200807_9651.doc",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceuticals-2020-08-07_300199-hanyu-pharmaceuticals-investor-relations-management-file-20200807_9651.doc",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2020-07-21 04:43:26",
"name": "300199翰宇药业调研活动信息20200723_1044.doc",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2020-07-23_300199-hanyu-pharmaceutical-research-activity-information-20200723_1044.doc",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2018-10-4 04:57:34",
"name": "300199翰宇药业2018-10-12_2018年10月10日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-10-12_october-10-2018-investor-relations-activity-record_6079.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2018-08-1 03:03:44",
"name": "300199翰宇药业2018-08-16_2018年8月15日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-08-16_2018-august-15-investor-relations-activity-record_1590.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2018-08-3 02:46:31",
"name": "300199翰宇药业2018-10-12_2018年10月10日投资者关系活动记录表",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-10-12_october-10-2018-investor-relations-activity-record_6079.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2018-07-7 06:43:51",
"name": "300199翰宇药业2018-07-04_2018年6月28日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-07-04_investor-relations-activity-record-form-on-june-28-2018_7416.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2018-06-4 05:51:21",
"name": "300199翰宇药业2018-06-30_2018年6月27日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-06-30_investor-relations-activity-record-form-on-june-27-2018_1798.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2018-01-22 05:20:39",
"name": "300199翰宇药业2018-01-15_2018年1月12日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-01-15_investor-relations-activity-record-form-on-january-12-2018_7983.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2018-01-13 01:01:14",
"name": "300199翰宇药业投资者关系管理信息20240905_8114.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2018-01-11_2018-january-9-investor-relations-activity-record_3126.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-12-0 02:48:51",
"name": "300199翰宇药业2017-12-12_2017年12月8日投资者关系活动记录表.docx",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-12-12_investor-relations-activity-record-form-on-december-8-2017_4872.docx",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-12-24 01:34:45",
"name": "300199翰宇药业2017-12-06_2017年12月4日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-12-06_investor-relations-activity-record-form-on-december-4-2017_9265.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-11-19 10:52:44",
"name": "300199翰宇药业2017-11-29_2017年11月23日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-11-29_2017-november-23-investor-relations-activity-record_2045.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-11-11 07:31:15",
"name": "300199翰宇药业2017-11-10_2017年11月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-11-2 07:22:37",
"name": "300199翰宇药业2017-11-09_2017年11月6日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-11-09_november-6-2017-investor-relations-activity-record_4228.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-10-4 10:40:44",
"name": "300199翰宇药业2017-10-31_2017年10月27日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-10-31_2017-october-27-investor-relations-activity-record_i__6306.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-10-15 02:14:30",
"name": "300199翰宇药业2017-10-31_2017年10月27日投资者关系活动记录表_二.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-10-31_2017-october-27-investor-relations-activity-record_ii__4570.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-10-11 11:36:58",
"name": "300199翰宇药业2017-10-25_2017年10月17日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-10-25_2017-october-17-investor-relations-activity-record_6436.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-10-16 09:47:11",
"name": "300199翰宇药业2017-10-20_2017年10月18日投资者关系活动记录表_一.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-10-20_2017-october-18-investor-relations-activity-record-sheet_i__2433.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-10-5 09:56:44",
"name": "300199翰宇药业2017-10-20_2017年10月18日投资者关系活动记录表_二.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-10-5 04:20:08",
"name": "300199翰宇药业2017-10-11_2017年10月10日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-10-11_2017-october-10-investor-relations-activity-record_7981.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-09-3 06:20:49",
"name": "300199翰宇药业2017-09-22_2017年9月21日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-09-22_2017-september-21-investor-relations-activity-record_6296.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-09-8 10:35:03",
"name": "300199翰宇药业2017-09-21_2017年9月19日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-08-10 07:09:11",
"name": "300199翰宇药业2017-08-31_2017年8月30日投资者关系活动记录表_一.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-08-31_2017-august-30-investor-relations-activity-record_i__6623.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-08-11 00:30:12",
"name": "300199翰宇药业2017-08-31_2017年8月30日投资者关系活动记录表_二.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-08-31_2017-august-30-investor-relations-activity-record_ii__1600.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-07-5 05:58:57",
"name": "300199_翰宇药业2017-07-04_2017年6月30日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-07-04_investor-relations-activity-record-form-on-june-30-2017_3857.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-07-15 10:51:14",
"name": "300199翰宇药业2017-07-03_2017年6月29日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-07-03_investor-relations-activity-record-form-on-june-29-2017_6558.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-06-0 06:32:30",
"name": "300199翰宇药业2017-06-30_2017年6月28日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-06-30_investor-relations-activity-record-form-on-june-28-2017_5867.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-06-12 07:32:28",
"name": "300199翰宇药业2017-06-30_2017年6月28日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-06-30_investor-relations-activity-record-form-on-june-28-2017_3778.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-06-15 01:20:49",
"name": "300199翰宇药业2017-06-07_2017年5月25日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-06-07_may-25-2017-investor-relations-activity-record_5392.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-05-10 03:34:01",
"name": "300199翰宇药业2017-05-31_2017年5月26日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-05-31_2017-may-26-investor-relations-activity-record_4488.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-05-15 11:36:44",
"name": "300199翰宇药业2017-05-26_2017年5月25日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-05-26_may-25-2017-investor-relations-activity-record_1669.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-05-20 10:42:01",
"name": "300199翰宇药业2017-05-12_2017年5月11日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250724/300199_hanyu-pharmaceutical-2017-05-12_may-11-2017-investor-relations-activity-record_8189.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-05-14 00:23:03",
"name": "300199_翰宇药业2017-05-08_2017年5月5日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-05-3 09:15:35",
"name": "300199_翰宇药业2017-05-05_2017年5月4日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-04-7 11:46:44",
"name": "300199_翰宇药业2017-04-19_2017年4月17日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-04-18 03:23:11",
"name": "300199_翰宇药业2017-04-18_2017年4月14日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-8 02:36:19",
"name": "300199_翰宇药业2017-03-28_2017年3月27日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250522/300199_hanyu-pharmaceutical-2024-09-05_300199-hanyu-pharmaceutical-investor-relations-management-information-20240905_8114.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-24 09:45:46",
"name": "300199翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-7 05:03:11",
"name": "300199_翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-15 11:21:32",
"name": "300199_翰宇药业2017-03-08_2017年3月7日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-08_investor-relations-activity-record-for-march-7-2017_9347.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-02-5 11:09:12",
"name": "300199翰宇药业2017-02-16_2017年2月14日投资者关系活动记录表_一3396.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-16_investor-relations-activity-record-sheet-for-february-14-2017_i__3396.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-02-15 09:09:14",
"name": "300199翰宇药业2017-02-14_2017年2月10日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-14_investor-relations-activity-record-for-february-10-2017_9222.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-01-6 02:47:09",
"name": "300199翰宇药业2017-01-06_2017年1月5日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-01-06_january-5-2017-investor-relations-activity-record-sheet_2137.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-4 08:44:03",
"name": "300199翰宇药业2016-12-26_2016年12月22日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-26_investor-relations-activity-record-for-december-22-2016_4414.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-4 00:11:24",
"name": "300199翰宇药业2016-12-21_2016年12月20日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-21_investor-relations-activity-record-for-december-20-2016_7480.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-17 11:37:55",
"name": "300199翰宇药业2016-12-15_2016年12月14日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-15_investor-relations-activity-record-for-december-14-2016_8735.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-21 10:12:43",
"name": "300199翰宇药业2016-12-13_2016年12月12日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-12-13_investor-relations-activity-record-for-december-12-2016_3763.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-19 00:43:40",
"name": "300199翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-4 10:23:20",
"name": "300199_翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-7 04:51:39",
"name": "300199_翰宇药业2017-03-08_2017年3月7日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-08_investor-relations-activity-record-for-march-7-2017_9347.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-02-14 01:18:23",
"name": "300199翰宇药业2017-02-16_2017年2月14日投资者关系活动记录表_一3396.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-16_investor-relations-activity-record-sheet-for-february-14-2017_i__3396.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-02-6 10:32:52",
"name": "300199翰宇药业2017-02-14_2017年2月10日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-14_investor-relations-activity-record-for-february-10-2017_9222.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-01-8 02:43:38",
"name": "300199翰宇药业2017-01-06_2017年1月5日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-01-06_january-5-2017-investor-relations-activity-record-sheet_2137.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-21 07:37:24",
"name": "300199翰宇药业2016-12-26_2016年12月22日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-26_investor-relations-activity-record-for-december-22-2016_4414.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-12 07:11:21",
"name": "300199翰宇药业2016-12-21_2016年12月20日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-21_investor-relations-activity-record-for-december-20-2016_7480.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-12 10:08:40",
"name": "300199翰宇药业2016-12-15_2016年12月14日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-15_investor-relations-activity-record-for-december-14-2016_8735.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-23 02:23:55",
"name": "300199翰宇药业2016-12-13_2016年12月12日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-12-13_investor-relations-activity-record-for-december-12-2016_3763.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-5 10:30:23",
"name": "300199翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-4 04:06:45",
"name": "300199_翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-23 02:38:57",
"name": "300199_翰宇药业2017-03-08_2017年3月7日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-08_investor-relations-activity-record-for-march-7-2017_9347.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-02-15 00:09:47",
"name": "300199翰宇药业2017-02-16_2017年2月14日投资者关系活动记录表_一3396.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-16_investor-relations-activity-record-sheet-for-february-14-2017_i__3396.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-02-17 03:25:58",
"name": "300199翰宇药业2017-02-14_2017年2月10日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-14_investor-relations-activity-record-for-february-10-2017_9222.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-01-17 05:17:40",
"name": "300199翰宇药业2017-01-06_2017年1月5日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-01-06_january-5-2017-investor-relations-activity-record-sheet_2137.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-10 03:33:51",
"name": "300199翰宇药业2016-12-26_2016年12月22日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-26_investor-relations-activity-record-for-december-22-2016_4414.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-15 02:51:50",
"name": "300199翰宇药业2016-12-21_2016年12月20日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-21_investor-relations-activity-record-for-december-20-2016_7480.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-10 03:24:11",
"name": "300199翰宇药业2016-12-15_2016年12月14日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-15_investor-relations-activity-record-for-december-14-2016_8735.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-12 03:34:19",
"name": "300199翰宇药业2016-12-13_2016年12月12日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-12-13_investor-relations-activity-record-for-december-12-2016_3763.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-24 02:41:28",
"name": "300199翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-1 10:28:18",
"name": "300199_翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-24 00:16:45",
"name": "300199_翰宇药业2017-03-08_2017年3月7日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-08_investor-relations-activity-record-for-march-7-2017_9347.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-02-24 11:59:46",
"name": "300199翰宇药业2017-02-16_2017年2月14日投资者关系活动记录表_一3396.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-16_investor-relations-activity-record-sheet-for-february-14-2017_i__3396.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-02-4 00:03:38",
"name": "300199翰宇药业2017-02-14_2017年2月10日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-14_investor-relations-activity-record-for-february-10-2017_9222.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-01-6 06:08:19",
"name": "300199翰宇药业2017-01-06_2017年1月5日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-01-06_january-5-2017-investor-relations-activity-record-sheet_2137.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-8 11:38:16",
"name": "300199翰宇药业2016-12-26_2016年12月22日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-26_investor-relations-activity-record-for-december-22-2016_4414.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-2 11:40:31",
"name": "300199翰宇药业2016-12-21_2016年12月20日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-21_investor-relations-activity-record-for-december-20-2016_7480.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-1 11:12:59",
"name": "300199翰宇药业2016-12-15_2016年12月14日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-15_investor-relations-activity-record-for-december-14-2016_8735.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-2 11:14:06",
"name": "300199翰宇药业2016-12-13_2016年12月12日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-12-13_investor-relations-activity-record-for-december-12-2016_3763.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-22 01:45:15",
"name": "300199翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-20 07:43:24",
"name": "300199_翰宇药业2017-03-10_2017年3月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-10_investor-relations-activity-record-for-march-8-2017_4249.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-03-9 10:30:42",
"name": "300199_翰宇药业2017-03-08_2017年3月7日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2017-03-08_investor-relations-activity-record-for-march-7-2017_9347.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-02-6 07:35:38",
"name": "300199翰宇药业2017-02-16_2017年2月14日投资者关系活动记录表_一3396.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-16_investor-relations-activity-record-sheet-for-february-14-2017_i__3396.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-02-18 02:44:23",
"name": "300199翰宇药业2017-02-14_2017年2月10日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-02-14_investor-relations-activity-record-for-february-10-2017_9222.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2017-01-8 00:45:30",
"name": "300199翰宇药业2017-01-06_2017年1月5日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2017-01-06_january-5-2017-investor-relations-activity-record-sheet_2137.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-13 11:48:43",
"name": "300199翰宇药业2016-12-26_2016年12月22日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-26_investor-relations-activity-record-for-december-22-2016_4414.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-24 04:09:04",
"name": "300199翰宇药业2016-12-21_2016年12月20日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-21_investor-relations-activity-record-for-december-20-2016_7480.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-0 10:30:45",
"name": "300199翰宇药业2016-12-15_2016年12月14日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-12-15_investor-relations-activity-record-for-december-14-2016_8735.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-12-2 03:35:29",
"name": "300199翰宇药业2016-12-13_2016年12月12日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-12-13_investor-relations-activity-record-for-december-12-2016_3763.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-11-20 10:07:03",
"name": "300199翰宇药业2016-11-18_2016年11月17日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-11-18_november-17-2016-investor-relations-activity-record_3028.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-11-10 10:39:14",
"name": "300199翰宇药业2016-11-01_2016年10月26日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-11-01_october-26-2016-investor-relations-activity-record_3346.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-10-15 05:19:22",
"name": "300199翰宇药业2016-10-27_2016年10月25日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-10-27_october-25-2016-investor-relations-activity-record-sheet_4404.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-10-19 07:08:11",
"name": "300199翰宇药业2016-10-20_2016年10月18日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-10-20_october-18-2016-investor-relations-activity-record-sheet_7025.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-10-3 00:15:17",
"name": "300199翰宇药业2016-10-18_2016年10月17日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-10-18_october-17-2016-investor-relations-activity-record-sheet_7154.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-10-11 10:04:11",
"name": "300199翰宇药业2016-10-14_2016年10月13日投资者关系活动记录表.docx",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-10-14_october-13-2016-investor-relations-activity-record-sheet_2136.docx",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-09-4 10:08:25",
"name": "300199翰宇药业2016-09-28_2016年9月27日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-09-28_investor-relations-activity-record-sheet-for-september-27-2016_5997.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-09-7 05:32:27",
"name": "300199翰宇药业2016-09-26_2016年9月23日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-09-26_investor-relations-activity-record-for-september-23-2016_9551.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-09-12 04:55:18",
"name": "300199翰宇药业2016-09-14_2016年9月12日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-09-14_investor-relations-activity-record-for-september-12-2016_8051.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-09-8 05:32:27",
"name": "300199_翰宇药业2016-09-12_2016年9月8日投资者关系活动记录表_3358.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-09-12_investor-relations-activity-record-for-september-8-2016_3358.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-09-18 11:33:12",
"name": "300199翰宇药业2016-09-09_2016年9月6日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-09-09_investor-relations-activity-record-sheet-for-september-6-2016_8597.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-08-14 10:48:05",
"name": "300199翰宇药业2016-08-02_2016年7月28日投资者关系活动记录表_二.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-08-02_investor-relations-activity-record-sheet-for-july-28-2016_ii__5436.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-08-1 07:23:09",
"name": "300199翰宇药业2016-08-02_2016年7月28日投资者关系活动记录表_一.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-07-12_investor-relations-activity-record-for-july-8-2016_9778.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-07-22 11:19:18",
"name": "300199翰宇药业2016-07-12_2016年7月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-07-04_investor-relations-activity-record-for-july-1-2016_3227.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-07-6 07:25:13",
"name": "300199翰宇药业2016-07-04_2016年7月1日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-06-30_investor-relations-activity-record-for-june-27-2016_8256.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-06-13 11:16:08",
"name": "300199翰宇药业2016-06-30_2016年6月27日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-06-30_investor-relations-activity-record-for-june-27-2016_8256.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-06-0 01:54:53",
"name": "300199翰宇药业2016-06-16_2016年6月14日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-06-16_investor-relations-activity-record-sheet-june-14-2016_7707.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-03-12 00:19:56",
"name": "300199翰宇药业2016-03-18_2016年3月17日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-03-18_investor-relations-activity-record-for-march-17-2016_1065.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-03-18 06:28:16",
"name": "300199翰宇药业2016-03-09_2016年3月4日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-03-09_investor-relations-activity-record-for-march-4-2016_2872.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-02-0 05:23:16",
"name": "300199翰宇药业2016-02-23_2016年2月22日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-02-23_investor-relations-activity-record-for-february-22-2016_7179.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-02-10 11:07:19",
"name": "300199翰宇药业2016-02-19_2016年2月18日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2016-02-19_investor-relations-activity-record-for-february-18-2016_6199.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2016-01-4 07:39:04",
"name": "300199翰宇药业2016-01-18_2016年1月15日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2016-01-18_january-15-2016-investor-relations-activity-record_3283.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-12-24 03:50:13",
"name": "300199翰宇药业2015-12-07_2015年12月4日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-12-07_investor-relations-activity-record-for-december-4-2015_1184.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-11-7 03:04:24",
"name": "300199翰宇药业2015-11-26_2015年11月24日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-11-26_november-24-2015-investor-relations-activity-record_4876.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-11-2 04:52:21",
"name": "300199翰宇药业2015-11-10_2015年11月9日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2015-11-10_november-9-2015-investor-relations-activity-record_6243.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-11-3 10:18:40",
"name": "300199翰宇药业2015-11-02_2015年10月30日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-11-02_october-30-2015-investor-relations-activity-record_6537.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-10-8 01:54:07",
"name": "300199翰宇药业2015-10-28_2015年10月23日投资者关系活动记录表pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2015-10-28_october-23-2015-investor-relations-activity-record_9215.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-09-20 09:25:19",
"name": "300199翰宇药业2015-09-28_2015年9月25日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-09-28_investor-relations-activity-record-for-september-25-2015_4371.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-09-14 03:22:29",
"name": "300199翰宇药业2015-09-25_2015年9月23日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-09-25_investor-relations-activity-record-for-september-23-2015_1884.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-09-0 02:49:54",
"name": "300199翰宇药业2015-09-16_2015年9月15日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-09-16_investor-relations-activity-record-for-september-15-2015_5735.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-09-19 08:36:09",
"name": "300199翰宇药业2015-09-10_2015年9月9日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2015-09-10_investor-relations-activity-record-for-september-9-2015_9112.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-09-17 08:37:39",
"name": "300199翰宇药业2015-09-02_2015年9月2日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-09-02_investor-relations-activity-record-for-september-2-2015_4434.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-09-15 10:21:34",
"name": "300199翰宇药业2015-09-01_2015年8月31日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2015-09-01_august-31-2015-investor-relations-activity-record_6139.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-08-19 01:28:28",
"name": "300199翰宇药业2015-08-26_2015年8月25日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-08-26_august-25-2015-investor-relations-activity-record_2788.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-08-17 01:03:11",
"name": "300199翰宇药业2015-08-25_2015年8月24日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-08-25_investor-relations-activity-record-for-august-24-2015_7740.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-07-12 04:15:16",
"name": "300199翰宇药业2015-07-15_2015年7月13日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceutical-2015-07-15_investor-relations-activity-record-sheet-for-july-13-2015_3770.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-07-14 01:17:02",
"name": "300199翰宇药业2015-07-03_2015年7月2日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-07-03_investor-relations-activity-record-for-july-2-2015_2854.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-06-20 04:21:54",
"name": "300199翰宇药业2015-06-04_2015年6月3日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-06-04_investor-relations-activity-record-for-june-3-2015_7780.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-05-5 02:41:28",
"name": "300199翰宇药业2015-05-20_2015年5月19日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-05-20_may-19-2015-investor-relations-activity-record-sheet_5850.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-03-13 02:55:09",
"name": "300199翰宇药业2015-03-16_2015年3月13日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-03-16_investor-relations-activity-record-for-march-13-2015_9640.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2015-01-17 06:16:52",
"name": "300199翰宇药业2015-01-12_2015年1月9日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250901/300199_hanyu-pharmaceuticals-2015-01-12_january-9-2015-investor-relations-activity-record_8915.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2014-12-7 11:27:31",
"name": "300199翰宇药业2014-12-18_2014年12月17日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2014-12-18_investor-relations-activity-record-for-december-17-2014_1666.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2014-12-12 02:07:13",
"name": "300199翰宇药业2014-12-17_2014年12月16日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2014-12-17_2014-december-16-investor-relations-activity-record_9100.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2014-12-8 05:34:12",
"name": "300199翰宇药业2014-12-15_2014年12月11日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2014-12-15_investor-relations-activity-record-for-december-11-2014_3385.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2014-11-11 05:37:37",
"name": "300199翰宇药业2014-11-26_2014年11月25日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2014-11-26_november-25-2014-investor-relations-activity-record_5012.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2014-11-18 11:22:43",
"name": "300199翰宇药业2014-11-21_2014年11月20日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2014-11-21_november-20-2014-investor-relations-activity-record_8437.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2014-09-13 01:21:08",
"name": "300199翰宇药业2014-09-03_2014年9月2日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2014-09-03_investor-relations-activity-record-for-september-2-2014_3385.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2014-09-1 08:16:20",
"name": "300199翰宇药业2014-09-01_2014年8月28日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2014-09-01_august-28-2014-investor-relations-activity-record_6672.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2014-02-2 08:48:09",
"name": "300199翰宇药业2014-02-14_2014年2月12日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2014-02-14_investor-relations-activity-record-sheet-for-february-12-2014_5304.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-11-11 06:14:21",
"name": "300199翰宇药业2013-11-20_2013年11月19日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-11-20_november-19-2013-investor-relations-activity-record_3561.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-11-16 00:45:28",
"name": "300199翰宇药业2013-11-07_2013年11月7日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-11-07_november-7-2013-investor-relations-activity-record-sheet_4976.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-10-20 07:21:05",
"name": "300199翰宇药业2013-10-28_2013年10月24日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-10-28_october-24-2013-investor-relations-activity-record_4002.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-09-0 01:26:27",
"name": "300199翰宇药业2013-09-18_2013年9月16日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-09-18_investor-relations-activity-record-sheet-for-september-16-2013_8969.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-09-4 05:34:37",
"name": "300199翰宇药业2013-09-02_2013年8月29日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-09-02_august-29-2013-investor-relations-activity-record_3890.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-08-14 09:42:40",
"name": "300199翰宇药业2013-08-26_2013年8月23日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-08-26_investor-relations-activity-record-for-august-23-2013_8170.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-08-16 01:24:11",
"name": "300199翰宇药业2013-08-23_2013年8月21日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-08-23_august-21-2013-investor-relations-activity-record-sheet_4447.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-08-11 00:48:03",
"name": "300199翰宇药业2013-08-16_2013年8月15日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-08-16_investor-relations-activity-record-for-august-15-2013_8819.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-08-9 07:16:27",
"name": "300199翰宇药业2013-08-16_2013年8月14日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-08-16_august-14-2013-investor-relations-activity-record_6495.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-07-17 04:33:50",
"name": "300199翰宇药业2013-07-10_2013年7月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-07-10_investor-relations-activity-record-for-july-8-2013_1373.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-05-5 08:58:41",
"name": "300199翰宇药业2013-05-28_2013年5月24日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-05-28_may-24-2013-investor-relations-activity-record_6459.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-05-22 02:49:11",
"name": "300199翰宇药业2013-05-15_2013年5月13日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-05-15_may-13-2013-investor-relations-activity-record_4417.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-05-1 02:00:05",
"name": "300199翰宇药业2013-05-06_2013年4月26日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-05-06_investor-relations-activity-record-sheet-april-26-2013_2242.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-04-19 03:49:10",
"name": "300199翰宇药业2013-04-16_2013年4月12日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2013-04-16_investor-relations-activity-record-for-april-12-2013_8343.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-04-12 09:03:47",
"name": "300199翰宇药业2013-04-03_2013年4月2日投资者关系活动记录表.docx",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-04-03_investor-relations-activity-record-for-april-2-2013_2768.docx",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-03-9 09:45:36",
"name": "300199翰宇药业2013-03-29_2013年3月27日投资者关系活动记录表.docx",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-03-29_investor-relations-activity-record-for-march-27-2013_3656.docx",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-01-15 07:01:29",
"name": "300199翰宇药业2013-01-23_2013年1月21日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-01-23_january-21-2013-investor-relations-activity-record_2497.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-01-1 07:55:57",
"name": "300199翰宇药业2013-01-21_2013年1月17日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-01-21_january-17-2013-investor-relations-activity-record-sheet_8184.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2013-01-5 03:31:25",
"name": "300199翰宇药业2013-01-10_2013年1月8日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2013-01-10_january-8-2013-investor-relations-activity-record_2914.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2012-12-2 04:20:21",
"name": "300199翰宇药业2012-12-14_2012年12月12日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2012-12-14_investor-relations-activity-record-for-december-12-2012_9336.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2012-12-24 02:23:36",
"name": "300199翰宇药业2012-12-10_2012年12月6日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2012-12-10_investor-relations-activity-record-for-december-6-2012_3375.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2012-11-3 00:18:53",
"name": "300199翰宇药业2012-11-26_2012年11月23日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2012-11-26_november-23-2012-investor-relations-activity-record_2930.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2012-11-8 08:08:33",
"name": "300199翰宇药业2012-11-02_2012年10月30日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2012-11-02_october-30-2012-investor-relations-activity-record_3969.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2012-10-9 06:57:38",
"name": "300199翰宇药业2012-10-29_2012年10月25日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2012-10-29_october-25-2012-investor-relations-activity-record_7493.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2012-09-19 09:42:12",
"name": "300199翰宇药业2012-09-05_2012年9月3日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2012-09-05_investor-relations-activity-record-for-september-3-2012_6262.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2012-08-2 07:20:35",
"name": "300199翰宇药业2012-08-30_2012年8月28日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2012-08-30_investor-relations-activity-record-for-august-28-2012_7849.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2012-08-6 04:32:07",
"name": "300199翰宇药业2012-08-20_2012年8月16日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceuticals-2012-08-20_investor-relations-activity-record-for-august-16-2012_7963.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
},
{
"release_at": "2012-08-20 00:38:33",
"name": "300199翰宇药业2012-08-17_2012年8月15日投资者关系活动记录表.pdf",
"href": "/file_manage/3531/20250902/300199_hanyu-pharmaceutical-2012-08-17_investor-relations-activity-record-for-august-15-2012_4739.pdf",
"image": "/upload/p/3531/image_other/2025-05/downloads.png"
}
]';
$data = json_decode($str,true);
$customContentModel = new CustomModuleContent();
$customExtendContentTModel = new CustomModuleExtentContent();
foreach ($data as $item){
$info = $customContentModel->read(['name'=>$item['name'],'project_id'=>$project_id,'module_id'=>5]);
if($info === false){
$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]);
$route = RouteMap::setRoute($contentId, RouteMap::SOURCE_MODULE, $contentId, $project_id);
$customContentModel->edit(['route'=>$route],['id'=>$contentId]);
$saveData = [
['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')],
];
$customExtendContentTModel->insert($saveData);
}
}
return true;
}
}
... ...
... ... @@ -33,6 +33,7 @@ class CreateProject extends Command
protected $description = '创建项目';
public function handle(){
dd(1);
return $this->sync();
}
... ... @@ -42,10 +43,12 @@ class CreateProject extends Command
* @throws \Exception
*/
public function sync($is_update = 0){
$company = '济南市莱芜凤城铝合金有限公司';
$mobile = '13806340552';
$plan = '标准版';
$cooperate_date = '2019-11-19';
$company = '山东临磨数控机床装备有限公司(自建站)';
$mobile = '18663004388';
$lead_name = '18663004388';
$plan = '商务版';
$cooperate_date = '2025-08-21';
// $channel = '{"user_id": "732", "zone_id": "1", "channel_id": "95"}';
$channel = '{"user_id": "1989", "zone_id": "4", "channel_id": "13"}';
$title = date('Ymd') . '-' . $company;
... ... @@ -53,7 +56,7 @@ class CreateProject extends Command
'project'=>[
'title' => $title,
'company' => $company,
'lead_name' => $mobile,
'lead_name' => $lead_name,
'mobile' => $mobile,
'mysql_id'=>Project::MYSQL_ID,
'serve_id'=>9,
... ... @@ -61,7 +64,7 @@ class CreateProject extends Command
'channel' => $channel,
'requirement' => '',
'cooperate_date' => $cooperate_date,
'from_order_id' => '',
'from_order_id' => uniqid(),
'type' => $is_update,
'is_upgrade'=>$is_update,
],
... ...
... ... @@ -101,6 +101,19 @@ class SyncProject extends Command
if($data['data']['order_type'] == '续费'){
$this->renewSync($data['data']);
}
// TODO 如果是续费项目 并且有GEO版本,需要处理GEO版本
if (($data['data']['order_type'] == '续费') && !empty($data['data']['geo_plan']) && ($data['data']['geo_plan'] != '无')) {
// 续费单,并且有GEO版本, 正常版本不创建 初始化正常版本
$data['data']['plan_marketing'] = '无';
//创建对应的GEO版本
$projectModel = new Project();
$seo_plan = $this->versionSeoData($data['data']['geo_plan'] ?? '');
$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();
if (empty($projectInfo)) {
// 创建对应GEO项目
$this->sync($data['data'],$is_update);
}
}
$item->status = NoticeLog::STATUS_SUCCESS;
$item->save();
echo 'success:' . $item['id'] . '执行时间:' . date('Y-m-d H:i:s') . PHP_EOL;
... ... @@ -136,7 +149,7 @@ class SyncProject extends Command
* @time :2023/8/11 15:33
*/
public function renewSync($param){
$title = date('Ymd') . '-' . $param['company_name'];;
$title = date('Ymd') . '-' . $param['company_name'];
$data = [
'title' => '【续费单】'.$title,
'company' => $param['company_name'],
... ... @@ -146,7 +159,7 @@ class SyncProject extends Command
'channel' => json_encode(Channel::getProjectChannel($param['company_id'], $param['username_sales'])),
'requirement' => $param['remark'],
'cooperate_date' => date('Y-m-d', $param['create_time']),
// 'api_no' => $param['id'], //改手动填
'api_no' => $param['id'], //改手动填
'amount' => $param['plan_price'],
'contract' => json_encode($param['files']),
'bill' => json_encode($param['images']),
... ... @@ -203,7 +216,6 @@ class SyncProject extends Command
*/
public function sync($param,$is_update = 0){
//TODO::4月12日 之前的项目都是v6
$version = (($is_update == 1) ? Project::VERSION_SIX : (empty($param['version']) ? Project::VERSION_SEVEN : $param['version']));
$title = date('Ymd') . '-' . $param['company_name'];
$data = [
... ...
<?php
namespace App\Console\Commands\Project;
use App\Helper\Arr;
use App\Models\Product\Product;
use App\Models\Project\Project;
use App\Services\ProjectServer;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;
class ThumbProjectImage extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'thumb_project_image {project_id}';
/**
* The console command description.
*
* @var string
*/
protected $description = '处理项目产品缩略图';
public function handle()
{
$project_id = $this->argument('project_id');
if ($project_id > 0) {
//指定项目
$this->output('project_id:' . $project_id . ' | start');
$project_info = ProjectServer::useProject($project_id);
if ($project_info) {
$thumb_w = $project_info->deploy_build->thumb_w ?? 0;
Product::select(['id', 'project_id', 'thumb'])->chunk(100, function ($products) use ($thumb_w) {
foreach ($products as $product) {
$thumb = $product->thumb;
if (isset($thumb['url']) && $thumb['url']) {
$new_thumb = thumbImageByUrl($thumb['url'], $thumb_w);
if ($new_thumb != $thumb['url']) {
$thumb['url'] = $new_thumb;
$json_thumb = Arr::a2s($thumb);
if (strlen($json_thumb) <= 500) {
$product->timestamps = false;
$product->thumb = $json_thumb;
$product->save();
$this->output('project_id:' . $product->project_id . ',product_id:' . $product->id . ' | success');
}
}
}
}
});
DB::disconnect('custom_mysql');
}
$this->output('project_id:' . $project_id . ' | end');
} else {
//所有项目
$projectModel = new Project();
$list = $projectModel->list(['delete_status' => 0, 'is_upgrade' => 0, 'type' => ['in', [1, 2, 3, 4, 6]]], 'id', ['id'], 'asc');
foreach ($list as $k => $v) {
$project_id = $v['id'];
$this->output('project_id:' . $project_id . ' | start');
$project_info = ProjectServer::useProject($project_id);
if ($project_info) {
$thumb_w = $project_info->deploy_build->thumb_w ?? 0;
Product::select(['id', 'project_id', 'thumb'])->chunk(100, function ($products) use ($thumb_w) {
foreach ($products as $product) {
$thumb = $product->thumb;
if (isset($thumb['url']) && $thumb['url']) {
$new_thumb = thumbImageByUrl($thumb['url'], $thumb_w);
if ($new_thumb != $thumb['url']) {
$thumb['url'] = $new_thumb;
$json_thumb = Arr::a2s($thumb);
if (strlen($json_thumb) <= 500) {
$product->timestamps = false;
$product->thumb = $json_thumb;
$product->save();
$this->output('project_id:' . $product->project_id . ',product_id:' . $product->id . ' | success');
}
}
}
}
});
DB::disconnect('custom_mysql');
}
$this->output('project_id:' . $project_id . ' | end');
}
}
}
/**
* 输出处理日志
* @param $message
* @return bool
*/
public function output($message)
{
echo date('Y-m-d H:i:s') . ' | ' . $message . PHP_EOL;
return true;
}
}
... ...
... ... @@ -48,7 +48,7 @@ class IndexedPages extends BaseCommands
$project_ids[] = 2104;
}
foreach ($project_ids as $project_id){
$rank_data = RankData::where('project_id', $project_id)->where('lang', '')->first();
$rank_data = RankData::where('project_id', $project_id)->where('api_no', $api_no)->where('lang', '')->first();
if($rank_data){
$rank_data->indexed_pages_num = $num;
$rank_data->save();
... ...
... ... @@ -32,60 +32,29 @@ class SyncTimeFiles extends Command
{
$fileModel = new File();
// $imagesModel = new Image();
$start = '2024-11-07 15:00:00';
$end = '2024-11-07 15:25:00';
$start = '2025-08-20 00:00:00';
$end = '2025-08-28 00:00:00';
$lists = $fileModel->list(['created_at'=>['between',[$start,$end]]]);
foreach ($lists as $v){
$path = $v['path'];
$this->param['name'] = basename($path);
$this->param['path'] = str_replace('/'.$this->param['name'],'',$path);
$file_path = $this->getUrl($this->param['path'].'/'.$this->param['name'], 0,0);
$cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$this->param['path'].'" https://v6-file.globalso.com/upload.php';
echo date('Y-m-d H:i:s') . ' | ' . $cmd . PHP_EOL;
$code = shell_exec($cmd);
echo date('Y-m-d H:i:s') . ' | 图片链接:' . $path . PHP_EOL;
$code = $this->synchronizationFile($path);
if(200 != (int)$code){
echo date('Y-m-d H:i:s') . ' | 错误状态:' . $code . PHP_EOL;
// $errorFileModel = new ErrorFile();
// $errorFileModel->add(['path'=>$this->param['path'].'/'.$this->param['name']]);
$errorFileModel = new ErrorFile();
$errorFileModel->add(['path'=>$this->param['path'].'/'.$this->param['name']]);
}
echo date('Y-m-d H:i:s') . ' | ok:' . $code . PHP_EOL;
}
return true;
}
/**
* @remark :获取图片文件链接
* @name :getUrl
* @author :lyh
* @method :post
* @time :2024/5/22 11:53
*/
public function getUrl($path,$storage_type,$location){
if(is_array($path)){
$url =[];
foreach ($path as $v){
$url[] = $this->getUrl($v,$storage_type,$location);
}
}else{
if(empty($path)){
return '';
}
if((strpos($path,'https://')!== false) || (strpos($path,'http://') !== false)){
return $path;
}
if(substr($path,0,2) == '//'){
return 'https:'.$path;
}
if($location == 0){
$cos = config('filesystems.disks.cos');
$cosCdn = ($storage_type == 0) ? $cos['cdn'] : $cos['cdn1'];
$url = $cosCdn.$path;
}else{
$s3 = config('filesystems.disks.s3');
$cdn = $s3['cdn'];
$url = $cdn.$path;
}
}
return $url;
public function synchronizationFile($path_name){
//同步到大文件
$file_path = config('filesystems.disks.cos')['cdn1'].$path_name;
$directoryPath = pathinfo($path_name, PATHINFO_DIRNAME);
$cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$directoryPath.'" https://v6-file.globalso.com/upload.php';
return shell_exec($cmd);
}
}
... ...
... ... @@ -47,16 +47,11 @@ class SyncTimeMinuteFile extends Command
}
foreach ($lists as $v){
$path = $v['path'];
if (file_exists($dir.$path)) {
echo date('Y-m-d H:i:s') . ' | file_ok:' . $dir.$path . PHP_EOL;
continue;
}
$this->param['name'] = basename($path);
$this->param['path'] = str_replace('/'.$this->param['name'],'',$path);
$file_path = $this->getUrl($this->param['path'].'/'.$this->param['name'], 0,0);
$cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$this->param['path'].'" https://v6-file.globalso.com/upload.php';
echo date('Y-m-d H:i:s') . ' | ' . $cmd . PHP_EOL;
$code = shell_exec($cmd);
// if (file_exists($dir.$path)) {
// echo date('Y-m-d H:i:s') . ' | file_ok:' . $dir.$path . PHP_EOL;
// continue;
// }
$code = $this->synchronizationFile($path);
if(200 != (int)$code){
echo date('Y-m-d H:i:s') . ' | 错误状态:' . $code . PHP_EOL;
$errorFileModel = new ErrorFile();
... ... @@ -67,6 +62,14 @@ class SyncTimeMinuteFile extends Command
return true;
}
public function synchronizationFile($path_name){
//同步到大文件
$file_path = config('filesystems.disks.cos')['cdn1'].$path_name;
$directoryPath = pathinfo($path_name, PATHINFO_DIRNAME);
$cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$directoryPath.'" https://v6-file.globalso.com/upload.php';
return shell_exec($cmd);
}
/**
* @remark :获取图片文件链接
* @name :getUrl
... ...
... ... @@ -30,12 +30,7 @@ class SyncVideo extends Command
public function handle()
{
$path = $this->argument('path');
$this->param['name'] = basename($path);
$this->param['path'] = str_replace('/'.$this->param['name'],'',$path);
$file_path = $this->getUrl($this->param['path'].'/'.$this->param['name'], 0,0);
$cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$this->param['path'].'" https://v6-file.globalso.com/upload.php';
echo date('Y-m-d H:i:s') . ' | ' . $cmd . PHP_EOL;
$code = shell_exec($cmd);
$code = $this->synchronizationFile($path);
echo date('Y-m-d H:i:s') . ' | ' . $code . PHP_EOL;
if(200 != (int)$code){
echo date('Y-m-d H:i:s') . ' | ' . $code . PHP_EOL;
... ... @@ -45,6 +40,14 @@ class SyncVideo extends Command
return true;
}
public function synchronizationFile($path_name){
//同步到大文件
$file_path = config('filesystems.disks.cos')['cdn1'].$path_name;
$directoryPath = pathinfo($path_name, PATHINFO_DIRNAME);
$cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$directoryPath.'" https://v6-file.globalso.com/upload.php';
return shell_exec($cmd);
}
/**
* @remark :获取图片文件链接
* @name :getUrl
... ...
... ... @@ -85,7 +85,7 @@ class HyStockData extends Command
// 解析响应结果
$responseResult = json_decode($response, true);
if ($responseResult) {
$data = $responseResult['result'][0]['data'];
$data = $responseResult['result'][0]['data'] ?? [];
if ($data) {
//获取最近一条
$stock = StockData::orderBy('id', 'desc')->first();
... ...
... ... @@ -43,7 +43,34 @@ class Temp extends Command
public function handle()
{
$this->specialImport();
}
/**
* 项目缩略图还原
* @param $project_id
* @author Akun
* @date 2025/09/04 10:48
*/
public function thumbRollBack($project_id)
{
$project_info = ProjectServer::useProject($project_id);
if ($project_info) {
Product::select(['id', 'gallery'])->chunk(100, function ($products) {
foreach ($products as $product) {
$thumb = $product['gallery'][0] ?? [];
if (!empty($thumb)) {
$product->timestamps = false;
$product->thumb = Arr::a2s($thumb);
$product->save();
$this->output('product_id:' . $product->id . ' | success');
}
}
});
DB::disconnect('custom_mysql');
}
}
/**
... ...
... ... @@ -14,6 +14,10 @@ use App\Models\Manage\ManageHr;
use App\Models\Ticket\TicketDailyCount;
use App\Models\Ticket\TicketDailyDeptCount;
use App\Models\Ticket\TicketDailyManageCount;
use App\Models\Ticket\TicketMonthDeptCount;
use App\Models\Ticket\TicketMonthManageCount;
use App\Models\Ticket\TicketWeekDeptCount;
use App\Models\Ticket\TicketWeekManageCount;
use App\Models\WorkOrder\TicketLog;
use App\Models\WorkOrder\TicketProject;
use App\Models\WorkOrder\Tickets;
... ... @@ -55,9 +59,29 @@ class TicketCount extends Command
if($action == 'manage_action'){
$this->manage_action();
}
if($action == 'manage_week_action'){
$startOfLastWeek = Carbon::now()->subWeek()->startOfWeek(); // 上周一 00:00:00
$endOfLastWeek = Carbon::now()->subWeek()->endOfWeek(); // 上周日 23:59:59
$this->manage_week_month_action($startOfLastWeek,$endOfLastWeek,(new TicketWeekManageCount()));
}
if($action == 'manage_month_action'){
$startOfLastMonth = Carbon::now()->subMonth()->startOfMonth(); // 上个月 1号 00:00:00
$endOfLastMonth = Carbon::now()->subMonth()->endOfMonth(); // 上个月最后一天 23:59:59
$this->manage_week_month_action($startOfLastMonth,$endOfLastMonth,(new TicketMonthManageCount()));
}
if($action == 'dept_action'){
$this->dept_action();
}
if($action == 'dept_week_action'){
$startOfLastWeek = Carbon::now()->subWeek()->startOfWeek(); // 上周一 00:00:00
$endOfLastWeek = Carbon::now()->subWeek()->endOfWeek(); // 上周日 23:59:59
$this->dept_week_month_action($startOfLastWeek,$endOfLastWeek,(new TicketWeekDeptCount()));
}
if($action == 'dept_month_action'){
$startOfLastMonth = Carbon::now()->subMonth()->startOfMonth(); // 上个月 1号 00:00:00
$endOfLastMonth = Carbon::now()->subMonth()->endOfMonth(); // 上个月最后一天 23:59:59
$this->dept_week_month_action($startOfLastMonth,$endOfLastMonth,(new TicketMonthDeptCount()));
}
if($action == 'yesterday_daily_action'){
$this->yesterday_daily_action();
}
... ... @@ -80,24 +104,36 @@ class TicketCount extends Command
$timeout_ratio = null;
$this->output('按人员统计:执行的人员名称/id:'.$item['name'].'/'.$item['manage_id']);
$ticketLogModel = new TicketLog();
$ticket_num = $ticketLogModel->counts(['engineer_id'=>$item['manage_id'],'is_engineer'=>1]);
$ticket_num = $ticketLogModel->counts(['engineer_id'=>$item['manage_id'],'is_engineer'=>1,'status'=>['!=',9]]);
//工单总时长
$timeCount = $ticketLogModel->formatQuery(['engineer_id'=>$item['manage_id'],'is_engineer'=>1])->sum('end_time');
$complete_num = $ticketLogModel->counts(['engineer_id'=>$item['manage_id'],'is_engineer'=>1,'end_at'=>['!=',null]]);
$timeCount = $ticketLogModel->formatQuery(['engineer_id'=>$item['manage_id'],'is_engineer'=>1,'status'=>['!=',9]])->sum('end_time');
$complete_num = $ticketLogModel->counts(['engineer_id'=>$item['manage_id'],'status'=>['!=',9],'is_engineer'=>1,'end_at'=>['!=',null]]);
if(!empty($timeCount)){
$average_time = round($timeCount / $complete_num, 3);
}
//最快完成的时间
$fastest_time = $ticketLogModel->formatQuery(['engineer_id'=>$item['manage_id'],'is_engineer'=>1,'end_at'=>['!=',null]])->min('end_time');
$fastest_time = $ticketLogModel->formatQuery(['engineer_id'=>$item['manage_id'],'status'=>['!=',9],'is_engineer'=>1,'end_at'=>['!=',null]])->min('end_time');
//最快完成时间
if(!$fastest_time){
$fastest_time = null;
}
//超时工单数量
$timeout_num = $ticketLogModel->counts(['engineer_id'=>$item['manage_id'],'is_engineer'=>1,'plan_end_at'=>['>',date('Y-m-d H:i:s')]]);
$timeout_num = $ticketLogModel
->where('engineer_id', $item['manage_id'])->where('is_engineer', 1)->where('status','!=',9)
->where(function ($query) {
$query->where(function ($q) {
$q->whereNotNull('end_at')->whereColumn('plan_end_at', '<', 'end_at');
})->orWhere(function ($q) {
$q->whereNull('end_at')->where('plan_end_at', '<', now());
});
})
->count();
if(!empty($timeout_num)){
$timeout_ratio = round($timeout_num / $ticket_num, 3);
}
if(!empty($complete_num)){
$complete_ratio = round($complete_num / $ticket_num, 2);
}
$data = [
'date'=>$date,
'manage_id'=>$item['id'],
... ... @@ -108,7 +144,8 @@ class TicketCount extends Command
'timeout_num'=>$timeout_num,//超时工单数量
'complete_num'=>$complete_num,//完成工单数量
'dept_id'=>$item['dept_id'],
'timeout_ratio'=>$timeout_ratio ?? null
'timeout_ratio'=>$timeout_ratio ?? null,
'complete_ratio'=>$complete_ratio ?? null
];
//查询当前用户是否当日已有记录
$ticketManageInfo = $ticketManageCountModel->read(['date'=>$date,'manage_id'=>$item['id']],['id']);
... ... @@ -124,6 +161,56 @@ class TicketCount extends Command
}
/**
* @remark :按周/月统计数据
* @name :manage_week_action
* @author :lyh
* @method :post
* @time :2025/8/30 9:36
*/
public function manage_week_month_action($startOfLast,$endOfLast,$model){
$manageHrModel = new ManageHr();
$manageList = $manageHrModel->list(['status'=>1,'dept_id'=>['in',[1,2]]],'id',['id','dept_id','manage_id','name','nickname']);
$ticketLogModel = new TicketLog();
foreach ($manageList as $item){
$timeout_ratio = $average_time = null;
$this->output('按人员统计:执行的人员名称/id:'.$item['name'].'/'.$item['manage_id']);
//上一周新增工单总数
$add_num = $ticketLogModel->counts(['created_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>$item['manage_id'],'is_engineer'=>1,'status'=>['!=',9]]);
//上一周完成工单(创建+完成都在当周,算一条有效数据)
$complete_num = $ticketLogModel->counts(['created_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>$item['manage_id'],'status'=>['!=',9],'is_engineer'=>1,'end_at'=>['between',[$startOfLast,$endOfLast]]]);
//上一周最快完成时长
$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');
//上一周完成工单总时长
$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');
if(!empty($timeCount)){
$average_time = round($timeCount / $complete_num, 3);
}
$data = [
'manage_id'=>$item['id'],
'manage_name'=>$item['name'],
'add_num'=>$add_num,//上一周新增工单数量
'average_time'=>$average_time ?? null,//平均完成工单时长
'fastest_time'=>$fastest_time ?? null,//最快完成工单时间
'complete_num'=>$complete_num,//完成工单数量
'dept_id'=>$item['dept_id'],
'timeout_ratio'=>$timeout_ratio ?? null,
'start_at'=>$startOfLast,
'end_at'=>$endOfLast
];
//查询当前用户是否当日已有记录
$ticketManageInfo = $model->read(['start_at'=>$startOfLast,'end_at'=>$endOfLast,'manage_id'=>$item['id']],['id']);
if($ticketManageInfo === false){
//TODO::执行新增
$model->addReturnId($data);
}else{
//TODO::执行编辑
$model->edit($data,['id'=>$ticketManageInfo['id']]);
}
}
return true;
}
/**
* @remark :按技术组统计数据
* @name :dept_action
* @author :lyh
... ... @@ -138,17 +225,29 @@ class TicketCount extends Command
$ticketDailyDeptModel = new TicketDailyDeptCount();
$date = Carbon::yesterday()->toDateString(); // "2025-08-07"
foreach ($groupList as $item){
$average_time = null;
$timeout_ratio = null;
$timeout_ratio = $average_time = null;
$this->output('组统计:执行的组/id:'.$item['name'].'/'.$item['id']);
$manageIdArr = $manageHrModel->selectField(['belong_group'=>$item['id'],'status'=>1,'dept_id'=>1],'manage_id');
$ticket_num = $ticketLogModel->counts(['engineer_id'=>['in',$manageIdArr],'is_engineer'=>1]);
$timeCount = $ticketLogModel->formatQuery(['engineer_id'=>['in',$manageIdArr],'is_engineer'=>1])->sum('end_time');
$manageIdArr = $manageHrModel->selectField(['belong_group'=>$item['id'],'status'=>['!=',9],'status'=>1,'dept_id'=>1],'manage_id');
$ticket_num = $ticketLogModel->counts(['engineer_id'=>['in',$manageIdArr],'is_engineer'=>1,'status'=>['!=',9]]);
$timeCount = $ticketLogModel->formatQuery(['engineer_id'=>['in',$manageIdArr],'status'=>['!=',9],'is_engineer'=>1])->sum('end_time');
if(!empty($timeCount)){
$average_time = round($timeCount / $ticket_num, 3);
}
//超期工单数量
$timeout_num = $ticketLogModel->counts(['engineer_id'=>['in',$manageIdArr],'is_engineer'=>1,'plan_end_at'=>['>',date('Y-m-d H:i:s')]]);
$timeout_num = $ticketLogModel
->whereIn('engineer_id', $manageIdArr)
->where('is_engineer', 1)
->where('status','!=',9)//排除掉作废工单
->where(function ($query) {
$query->where(function ($q) {
$q->whereNotNull('end_at')
->whereColumn('plan_end_at', '<', 'end_at');
})->orWhere(function ($q) {
$q->whereNull('end_at')
->where('plan_end_at', '<', now());
});
})
->count();
if(!empty($timeout_num)){
$timeout_ratio = round($timeout_num / $ticket_num, 3);
}
... ... @@ -172,6 +271,70 @@ class TicketCount extends Command
}
/**
* @remark :技术组按周统计
* @name :dept_week_month_action
* @author :lyh
* @method :post
* @time :2025/8/30 14:01
*/
public function dept_week_month_action($startOfLast,$endOfLast,$model){
$belongingGroupModel = new BelongingGroup();
$groupList = $belongingGroupModel->list(['id'=>['in',[1,2,3,4,5,6,7,8,9]]],'id',['id','name']);
$manageHrModel = new ManageHr();
$ticketLogModel = new TicketLog();
foreach ($groupList as $item){
$timeout_ratio = $average_time = null;
$this->output('组统计:执行的组/id:'.$item['name'].'/'.$item['id']);
$manageIdArr = $manageHrModel->selectField(['belong_group'=>$item['id'],'status'=>['!=',9],'status'=>1,'dept_id'=>1],'manage_id');
//本周新增工单
$add_num = $ticketLogModel->counts(['created_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>['in',$manageIdArr],'is_engineer'=>1,'status'=>['!=',9]]);
$complete_num = $ticketLogModel->counts(['end_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>['in',$manageIdArr],'is_engineer'=>1,'status'=>['!=',9]]);
$timeCount = $ticketLogModel->formatQuery(['end_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>['in',$manageIdArr],'status'=>['!=',9],'is_engineer'=>1])->sum('end_time');
if(!empty($timeCount)){
$average_time = round($timeCount / $complete_num, 3);
}
//超期工单数量
$timeout_num = $ticketLogModel
->whereIn('engineer_id', $manageIdArr)
->where('is_engineer', 1)
->where('status','!=',9)//排除掉作废工单
->where(function ($query) use ($startOfLast,$endOfLast) {
$query->where(function ($q) use ($startOfLast,$endOfLast) {
$q->whereBetween('plan_end_at',[$startOfLast,$endOfLast])->whereNotNull('end_at')->whereColumn('plan_end_at', '<', 'end_at');
})->orWhere(function ($q) {
$q->whereNull('end_at')->where('plan_end_at', '<', now());
});
})
->count();
//预期结束时间在本周的所有工单
$ticket_num = $ticketLogModel->counts(['plan_end_at'=>['between',[$startOfLast,$endOfLast]],'engineer_id'=>['in',$manageIdArr],'is_engineer'=>1,'status'=>['!=',9]]);
if(!empty($timeout_num)){
$timeout_ratio = round($timeout_num / $ticket_num, 3);
}
$data = [
'dept_id'=>$item['id'],
'dept_name'=>$item['name'],
'add_num'=>$add_num ?? 0,
'complete_num'=>$complete_num ?? 0,
'average_time'=>$average_time ?? null,
'timeout_ratio'=>$timeout_ratio ?? null,
'timeout_num'=>$timeout_num,
'start_at'=>$startOfLast,
'end_at'=>$endOfLast
];
//查询当前用户是否当日已有记录
$ticketManageInfo = $model->read(['start_at'=>$startOfLast,'end_at'=>$endOfLast,'dept_id'=>$item['id']],['id']);
if($ticketManageInfo === false){
//TODO::执行新增
$model->addReturnId($data);
}else{
//TODO::执行编辑
$model->edit($data,['id'=>$ticketManageInfo['id']]);
}
}
return true;
}
/**
* @remark :技术组所有工单记录
* @name :daily_action
* @author :lyh
... ... @@ -180,6 +343,10 @@ class TicketCount extends Command
*/
public function yesterday_daily_action(){
$ticketModel = new Tickets();
$ticketLogModel = new TicketLog();
$ticketLogModel->whereIn('ticket_id', function ($query) {
$query->select('id')->from('gl_tickets')->where('status', 9);
})->update(['status' => 9]);
$date = Carbon::yesterday()->toDateString(); // "2025-08-07"
$ticket_num = $ticketModel->counts(['id'=>['!=',0]]);
$time_end_num = $ticketModel->counts(['end_at'=>['!=',null]]);//已完成的工单
... ... @@ -194,12 +361,17 @@ class TicketCount extends Command
$submit_b_side = $ticketModel->formatQuery(['submit_side'=>2])->sum('submit_side');
$dbResult = DB::table('gl_ticket_projects as p')->leftJoin('gl_tickets as t', 'p.id', '=', 't.project_id')
->select(
'p.project_cate',
DB::raw('COUNT(t.id) as ticket_count')
)
->groupBy('p.project_cate')
->pluck('ticket_count', 'project_cate');
$timeout_num = $ticketModel->counts(['end_at'=>null,'plan_end_at'=>['>',date('Y-m-d H:i:s')]]);
'p.project_cate', DB::raw('COUNT(t.id) as ticket_count')
)->groupBy('p.project_cate')->pluck('ticket_count', 'project_cate');
$timeout_num = $ticketModel->where('status','!=',9)
->where(function ($query) {
$query->where(function ($q) {
$q->whereNotNull('end_at')->whereColumn('plan_end_at', '<', 'end_at');
})->orWhere(function ($q) {
$q->whereNull('end_at')->where('plan_end_at', '<', now());
});
})
->count();
$timeout_ratio = null;
if(!empty($timeout_num)){
$timeout_ratio = round($timeout_num / $ticket_num, 3);
... ...
... ... @@ -138,6 +138,7 @@ class ProjectUpdate extends Command
//设置数据库
$project = ProjectServer::useProject($project_id);
if ($project) {
$thumb_w = $project->deploy_build->thumb_w ?? 0;//缩略图压缩宽度
if ($api_type == 'category') {
//产品分类
$url = $api_url . '?' . http_build_query(['w' => 'category']);
... ... @@ -332,6 +333,12 @@ class ProjectUpdate extends Command
$gallery[] = ['alt' => '', 'url' => $this->source_download($img, $project_id, $domain_arr['host'], $web_url_domain, $home_url)];
}
}
//缩略图
$thumb = $gallery[0] ?? [];
if (isset($thumb['url']) && $thumb['url']) {
//生成缩略图
$thumb['url'] = thumbImageByUrl($thumb['url'], $thumb_w);
}
//关键词
$keyword_id = '';
if ($item['tags'] ?? []) {
... ... @@ -371,7 +378,7 @@ class ProjectUpdate extends Command
'content' => $content,
'category_id' => $category_id,
'keyword_id' => $keyword_id,
'thumb' => isset($gallery[0]) ? Arr::a2s($gallery[0]) : '',
'thumb' => Arr::a2s($thumb),
'gallery' => Arr::a2s($gallery),
'attrs' => Arr::a2s($attrs),
'seo_mate' => Arr::a2s([
... ... @@ -417,7 +424,7 @@ class ProjectUpdate extends Command
'content' => $content,
'category_id' => $category_id,
'keyword_id' => $keyword_id,
'thumb' => isset($gallery[0]) ? Arr::a2s($gallery[0]) : '',
'thumb' => Arr::a2s($thumb),
'gallery' => Arr::a2s($gallery),
'attrs' => Arr::a2s($attrs),
'seo_mate' => Arr::a2s([
... ...
... ... @@ -77,6 +77,9 @@ class UpdateKeyword extends Command
if($updateObject['type'] == 0){//更新所有关键字
//获取所有关键字的id
$idArr = $keywordModel->selectField(['id'=>['>',0]],'id');
if(empty($idArr)){
return true;
}
if($info['update_method'] != 1){
$idArr = shuffle($idArr);
}
... ...
... ... @@ -431,7 +431,7 @@ class WebTraffic extends Command
$query->whereIn('ip_area', $main_countries);
}
if($filter_countries){
$query->whereNotIn('ip_area', $main_countries);
$query->whereNotIn('ip_area', $filter_countries);
}
})->inRandomOrder()->first();
if(!$ipdata){
... ...
... ... @@ -229,27 +229,30 @@ class FetchTicketProjects extends Command
ManageHr::where('status', 1)->find($item->deploy_optimize->tech_leader)->manage_id ?? 0,
8, //张鸿飞
])->first(fn($v) => $v !== null && $v !== 0, 0);
// 优化师
$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;
// 项目经理
$pm_id = ManageHr::where('status', 1)->find($item->deploy_build->manager_mid)->manage_id ?? ManageHr::where('status', 1)->where('name', '李洁玉')->value('manage_id') ?? 0;
// 第一负责人
/**
* 5.0升级6.0的项目,白帽SEO, GEO的项目 都划给售后
* 其他:建站中找项目经理,建站完成找杨长远,推广找售后服务经理
/**单纯的5.0升级6.0的项目,自帽SE0,GE0的项目 部划给售后
其他:建站中找项目经理,建站完成找杨长远,推广找售后服务经理
*/
if ($item->is_upgrade || $item->project_type == 1 || $item->deploy_build->seo_plan > 0)
$engineer_id = $assm_id; // V5升V6,白帽SEO,GEO,找售后服务经理
elseif ($status == 1)
$engineer_id = $pm_id; // 建站中找项目经理
elseif ($status == 2)
$engineer_id = Manage::where('status', 1)->where('name', '杨长远')->value('id') ?? 0; // 建站完成找杨长远
else
$engineer_id = $assm_id; // 推广找售后服务经理
//todo::建站或同时为v6版本+GEO的,建站中项目给项目经理
if(($status == 1) && ($item->deploy_build->plan > 0) && ($item->deploy_build->seo_plan > 0)){
$engineer_id = $pm_id; //找项目经理
}else{
if ($item->is_upgrade || $item->project_type == 1 || $item->deploy_build->seo_plan > 0)
$engineer_id = $assm_id; // V5升V6,白帽SEO,GEO,找售后服务经理
elseif ($status == 1)
$engineer_id = $pm_id; // 建站中找项目经理
elseif ($status == 2)
$engineer_id = Manage::where('status', 1)->where('name', '杨长远')->value('id') ?? 0; // 建站完成找杨长远
elseif ($status == 3)
$engineer_id = $assm_id; // 推广找售后服务经理
else
$engineer_id = $pm_id; //找项目经理
}
$is_del = (
$item->extend_type == 5
|| $item->type == 8
... ...
... ... @@ -13,6 +13,7 @@ use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Redis;
define('HTTP_OPENAI_URL', 'http://openai.waimaoq.com/');
... ... @@ -28,7 +29,7 @@ define('HTTP_OPENAI_URL', 'http://openai.waimaoq.com/');
if (!function_exists('generateRoute')) {
function generateRoute($string)
{
if(is_array($string)){
if (is_array($string)) {
$string = $string[0];
}
$sign = str_replace(".", "", trim(strtolower(preg_replace('/[^\w.]+/', '-', trim($string))), '-'));
... ... @@ -61,7 +62,7 @@ if (!function_exists('http_post')) {
* @param type $url
* @param type $post_data
*/
function http_post($url, $post_data, $header = [],$is_json = true,$timeout = 60)
function http_post($url, $post_data, $header = [], $is_json = true, $timeout = 60)
{
if (empty($header)) {
$header = array(
... ... @@ -87,7 +88,7 @@ if (!function_exists('http_post')) {
@file_put_contents(storage_path('logs/lyh_error.log'), var_export($error_message, true) . PHP_EOL, FILE_APPEND);
}
curl_close($ch);
if($is_json){
if ($is_json) {
return json_decode($res, true);
}
return trim($res);
... ... @@ -106,7 +107,7 @@ if (!function_exists('http_get')) {
if (empty($header)) {
$header[] = "content-type: application/json";
}
$ch1 = curl_init();
$ch1 = curl_init();
$timeout = 0;
curl_setopt($ch1, CURLOPT_URL, $url);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
... ... @@ -130,7 +131,7 @@ if (!function_exists('http_get')) {
if (!function_exists('curl_get')) {
function curl_get($url,$is_array=true)
function curl_get($url, $is_array = true)
{
$header = array(
'Expect:',
... ... @@ -161,7 +162,8 @@ if (!function_exists('curl_get')) {
* @method :post
* @time :2024/6/5 10:38
*/
function contains_russian($text) {
function contains_russian($text)
{
// 使用正则表达式检查是否包含俄语字符
return preg_match('/[\x{0400}-\x{04FF}]/u', $text) > 0;
... ... @@ -176,7 +178,8 @@ if (!function_exists('curl_c')) {
* @author Akun
* @date 2023/11/22 11:33
*/
function curl_c($url,$is_array=true,$replace=[]){
function curl_c($url, $is_array = true, $replace = [])
{
$header = array(
'Expect:',
'Content-Type: application/json; charset=utf-8'
... ... @@ -195,16 +198,16 @@ if (!function_exists('curl_c')) {
curl_setopt($ch, CURLOPT_SSLVERSION, 'all');
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$content = curl_exec($ch);
$http_code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if($http_code == 200){
if(!empty($replace)){
foreach ($replace as $k=>$v){
$content = str_replace($k,$v,$content);
if ($http_code == 200) {
if (!empty($replace)) {
foreach ($replace as $k => $v) {
$content = str_replace($k, $v, $content);
}
}
return $is_array ? json_decode($content, true) : $content;
}else{
} else {
return false;
}
}
... ... @@ -218,7 +221,8 @@ if (!function_exists('curl_code')) {
* @author Akun
* @date 2023/11/22 11:33
*/
function curl_code($url,$is_array=true){
function curl_code($url, $is_array = true)
{
$header = array(
'Expect:',
'Content-Type: application/json; charset=utf-8'
... ... @@ -237,11 +241,11 @@ if (!function_exists('curl_code')) {
curl_setopt($ch, CURLOPT_SSLVERSION, 'all');
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
$content = curl_exec($ch);
$http_code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if($http_code == 200){
if ($http_code == 200) {
return $is_array ? json_decode($content, true) : $content;
}else{
} else {
return $http_code;
}
}
... ... @@ -260,7 +264,7 @@ if (!function_exists('_get_child')) {
foreach ($arr as $v) {
$v = (array)$v;
if ($v['pid'] == $my_id) {
$v['sub'] = _get_child($v['id'], $arr);
$v['sub'] = _get_child($v['id'], $arr);
$new_arr[] = $v;
}
}
... ... @@ -274,7 +278,7 @@ if (!function_exists('_get_all_sub')) {
* @param int
* @return array
*/
function _get_all_sub($my_id,$id_Arr)
function _get_all_sub($my_id, $id_Arr)
{
$new_arr[] = $my_id;
foreach ($id_Arr as $v) {
... ... @@ -302,7 +306,7 @@ if (!function_exists('checkDomain')) {
if (empty($urlParts['host'])) {
$urlParts = parse_url('https://' . $value);
}
$host = $urlParts['host'] ?? '';
$host = $urlParts['host'] ?? '';
$scheme = $urlParts['scheme'] ?? 'https';
if (!in_array($scheme, ['http', 'https'])) {
return false;
... ... @@ -380,7 +384,7 @@ function list_to_tree($list, $pk = 'id', $pid = 'pid', $child = '_child', $root
// 如果是数字,则是root
if (is_numeric($pk)) {
$root = $pk;
$pk = 'id';
$pk = 'id';
}
// 创建Tree
$tree = array();
... ... @@ -505,7 +509,7 @@ if (!function_exists('getPreviousDaysDate')) {
$days = [];
while ($day > 0) {
$days[] = date("Y-m-d", strtotime("-{$day} days"));
$day -= 1;
$day -= 1;
}
return $days;
}
... ... @@ -522,7 +526,7 @@ if (!function_exists('getPreviousMonthsDate')) {
$months = [];
while ($month > 0) {
$months[] = date("Y-m", strtotime("-{$month} months"));
$month -= 1;
$month -= 1;
}
return $months;
}
... ... @@ -536,17 +540,17 @@ if (!function_exists('getInquiryInformation')) {
*/
function getInquiryInformation($domain, $sta_date)
{
$token = md5($domain . date("Y-m-d"));
$token = md5($domain . date("Y-m-d"));
$source = '1,3';
$url = "https://www.globalso.site/api/external-interface/country_con/15243d63ed5a5738?domain={$domain}&token={$token}&source={$source}&sta_date={$sta_date}";
$url = "https://www.globalso.site/api/external-interface/country_con/15243d63ed5a5738?domain={$domain}&token={$token}&source={$source}&sta_date={$sta_date}";
$client = new Client(['verify' => false]);
$http = $client->get($url);
$data = [];
$http = $client->get($url);
$data = [];
if ($http->getStatusCode() != 200) {
return $data;
}
$content = $http->getBody()->getContents();
$json = json_decode($content, true);
$json = json_decode($content, true);
if ($json['status'] != 200) {
return $content;
}
... ... @@ -597,7 +601,7 @@ if (!function_exists('checkIsMonth')) {
$now = time();
// 获取当月的起始时间戳和结束时间戳
$firstDay = strtotime(date('Y-m-01', $now));
$lastDay = strtotime(date('Y-m-t', $now));
$lastDay = strtotime(date('Y-m-t', $now));
// 传入日期的时间戳
$timestamp = strtotime($date);
// 判断传入日期是否在当月范围内
... ... @@ -621,8 +625,8 @@ if (!function_exists('getDateDays')) {
if (!is_null($date)) {
$dd = explode('-', $date);
if (!checkIsGreaterMonth($date) && !checkIsMonth($date)) {
$year = $dd[0];
$month = $dd[1];
$year = $dd[0];
$month = $dd[1];
$first_day_of_month = "{$year}-{$month}-01";
return getDateArray("{$year}-{$month}-" . date("t", strtotime($first_day_of_month)));
}
... ... @@ -641,7 +645,7 @@ if (!function_exists('getDateArray')) {
function getDateArray(string $date)
{
list($year, $month, $day) = explode('-', date($date));
$i = 1;
$i = 1;
$days = [];
while ($i <= $day) {
$days[] = "{$year}-{$month}-" . str_pad($i, 2, "0", STR_PAD_LEFT);
... ... @@ -659,34 +663,35 @@ if (!function_exists('getImageUrl')) {
* @method :post
* @time :2023/7/20 16:46
*/
function getImageUrl($path,$storage_type = 0,$location = 0,$image_cdn = 1){
if(is_array($path)){
$url =[];
foreach ($path as $v){
$url[] = getImageUrl($v,$storage_type,$location);
function getImageUrl($path, $storage_type = 0, $location = 0, $image_cdn = 1)
{
if (is_array($path)) {
$url = [];
foreach ($path as $v) {
$url[] = getImageUrl($v, $storage_type, $location);
}
}else{
if(empty($path)){
} else {
if (empty($path)) {
return '';
}
if((strpos($path,'https://')!== false) || (strpos($path,'http://') !== false)){
return $path;
if ((strpos($path, 'https://') !== false) || (strpos($path, 'http://') !== false)) {
return $path;
}
if(substr($path,0,2) == '//'){
return 'https:'.$path;
if (substr($path, 0, 2) == '//') {
return 'https:' . $path;
}
if($location == 0){
if ($location == 0) {
$cos = config('filesystems.disks.cos');
if($image_cdn == 0){//v6链接
if ($image_cdn == 0) {//v6链接
$cosCdn = $cos['cdn2'];
}else{
} else {
$cosCdn = ($storage_type == 0) ? $cos['cdn'] : $cos['cdn1'];
}
$url = $cosCdn.$path;
}else{
$url = $cosCdn . $path;
} else {
$s3 = config('filesystems.disks.s3');
$cdn = $s3['cdn'];
$url = $cdn.$path;
$url = $cdn . $path;
}
}
return $url;
... ... @@ -701,36 +706,37 @@ if (!function_exists('getFileUrl')) {
* @method :post
* @time :2023/7/20 16:46
*/
function getFileUrl($path,$storage_type = 0,$location = 0,$file_cdn = 0){
if(is_array($path)){
$url =[];
foreach ($path as $v){
$url[] = getFileUrl($v,$storage_type,$location,$file_cdn);
function getFileUrl($path, $storage_type = 0, $location = 0, $file_cdn = 0)
{
if (is_array($path)) {
$url = [];
foreach ($path as $v) {
$url[] = getFileUrl($v, $storage_type, $location, $file_cdn);
}
}else{
if(empty($path)){
} else {
if (empty($path)) {
return '';
}
if((strpos($path,'https://')!== false) || (strpos($path,'http://') !== false)){
return $path;
if ((strpos($path, 'https://') !== false) || (strpos($path, 'http://') !== false)) {
return $path;
}
if(substr($path,0,2) == '//'){
return 'https:'.$path;
if (substr($path, 0, 2) == '//') {
return 'https:' . $path;
}
$file_type = pathinfo($path, PATHINFO_EXTENSION);
$fileTypeArr = ['zip', 'pdf', 'mp4', 'doc', 'docx', 'm4v', 'xlsx'];
if(in_array(strtolower($file_type),$fileTypeArr) && ($file_cdn == 0)){
if (in_array(strtolower($file_type), $fileTypeArr) && ($file_cdn == 0)) {
$cdn2 = config('filesystems.disks.cos')['cdn2'];
return $cdn2.$path;
return $cdn2 . $path;
}
if($location == 0){
if ($location == 0) {
$cos = config('filesystems.disks.cos');
$cosCdn = ($storage_type == 0) ? $cos['cdn'] : $cos['cdn1'];
return $cosCdn.$path;
}else{
return $cosCdn . $path;
} else {
$s3 = config('filesystems.disks.s3');
$cdn = $s3['cdn'];
return $cdn.$path;
return $cdn . $path;
}
}
return $url;
... ... @@ -744,7 +750,8 @@ if (!function_exists('getFileUrl')) {
* @method :post
* @time :2023/6/28 17:39
*/
function characterTruncation($string,$pattern){
function characterTruncation($string, $pattern)
{
preg_match($pattern, $string, $matches);
if (isset($matches[0])) {
$result = $matches[0];
... ... @@ -761,7 +768,8 @@ function characterTruncation($string,$pattern){
* @method :post
* @time :2024/5/14 16:24
*/
function characterTruncationStr($string,$startStr,$endStr){
function characterTruncationStr($string, $startStr, $endStr)
{
$start = strpos($string, $startStr);
$end = strpos($string, $endStr) + strlen($endStr);
return substr($string, $start, $end - $start);
... ... @@ -798,7 +806,7 @@ if (!function_exists('str_replace_url')) {
$cosCdn1 = $cos['cdn1'];
$cosCdn2 = $cos['cdn2'];
$cosCdn3 = config('filesystems.disks.s3')['cdn'];
if($url && ((strpos($url,$cosCdn) !== false) || (strpos($url,$cosCdn1) !== false) || (strpos($url,$cosCdn2) !== false) || (strpos($url,$cosCdn3) !== false))){
if ($url && ((strpos($url, $cosCdn) !== false) || (strpos($url, $cosCdn1) !== false) || (strpos($url, $cosCdn2) !== false) || (strpos($url, $cosCdn3) !== false))) {
// 外部URL无需解析
// 使用 parse_url 函数来解析 URL
$urlParts = parse_url($url);
... ... @@ -812,7 +820,7 @@ if (!function_exists('str_replace_url')) {
}
}
if(!function_exists('curlGet')){
if (!function_exists('curlGet')) {
/**
* @remark :忽略证书curl请求
* @name :curlGet
... ... @@ -820,8 +828,9 @@ if(!function_exists('curlGet')){
* @method :post
* @time :2023/9/12 10:10
*/
function curlGet($url){
$ch1 = curl_init();
function curlGet($url)
{
$ch1 = curl_init();
$timeout = 60;
curl_setopt($ch1, CURLOPT_URL, $url);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
... ... @@ -852,15 +861,15 @@ function ends_with($string, $suffix)
* @method :post
* @time :2025/6/21 9:57
*/
function getCustomRouteMap($module_route,$route = '',$is_upgrade = 0)
function getCustomRouteMap($module_route, $route = '', $is_upgrade = 0)
{
if($is_upgrade == 0){
if ($is_upgrade == 0) {
return $route;
}
if($module_route == $route){
if ($module_route == $route) {
$resultRoute = $route;
}else{
$resultRoute = $module_route.'_catalog/'.$route;
} else {
$resultRoute = $module_route . '_catalog/' . $route;
}
return $resultRoute;
}
... ... @@ -872,48 +881,53 @@ function getCustomRouteMap($module_route,$route = '',$is_upgrade = 0)
* @method :post
* @time :2023/11/10 14:29
*/
function getRouteMap($source,$source_id,$is_upgrade = 0, $returnModel = false){
function getRouteMap($source, $source_id, $is_upgrade = 0, $returnModel = false)
{
$route = '';
$routeMapModel = new RouteMap();
$info = $routeMapModel->read(['source'=>$source,'source_id'=>$source_id]);
if($info !== false){
if($is_upgrade == 1){
if($source == $routeMapModel::SOURCE_NEWS_CATE){
if($info['route'] != 'news'){
return $routeMapModel::PATH_NEWS_CATE.'/'.$info['route'];
$info = $routeMapModel->read(['source' => $source, 'source_id' => $source_id]);
if ($info !== false) {
if ($is_upgrade == 1) {
if ($source == $routeMapModel::SOURCE_NEWS_CATE) {
if ($info['route'] != 'news') {
return $routeMapModel::PATH_NEWS_CATE . '/' . $info['route'];
}
}elseif ($source == $routeMapModel::SOURCE_BLOG_CATE){
if($info['route'] != 'blog'){
return $routeMapModel::PATH_BLOG_CATE.'/'.$info['route'];
} elseif ($source == $routeMapModel::SOURCE_BLOG_CATE) {
if ($info['route'] != 'blog') {
return $routeMapModel::PATH_BLOG_CATE . '/' . $info['route'];
}
}
$route = $info['route'];
return $route;
}
if(!empty($info['path'])){
if($info['path'] == 'blog'){
$info['path'] = $info['path'].'s';
if (!empty($info['path'])) {
if ($info['path'] == 'blog') {
$info['path'] = $info['path'] . 's';
}
$route = $info['path'].'/'.$info['route'];
}else{
$route = $info['path'] . '/' . $info['route'];
} else {
$route = $info['route'];
}
}
if($returnModel && ($info !== false)){
if ($returnModel && ($info !== false)) {
return $info;
}
return $route;
}
function redis_get($key){
function redis_get($key)
{
return Redis::connection()->client()->get($key);
}
function redis_del(...$key){
function redis_del(...$key)
{
return Redis::connection()->client()->del(...$key);
}
function redis_set($key,$val,$ttl=3600){
return Redis::connection()->client()->set($key,$val,$ttl);
function redis_set($key, $val, $ttl = 3600)
{
return Redis::connection()->client()->set($key, $val, $ttl);
}
/**
... ... @@ -925,7 +939,8 @@ function redis_set($key,$val,$ttl=3600){
* @author:dc
* @time 2023/10/25 9:48
*/
function redis_add($key,$val,$ttl=3600){
function redis_add($key, $val, $ttl = 3600)
{
return Redis::connection()->client()->eval(
"return redis.call('exists',KEYS[1])<1 and redis.call('setex',KEYS[1],ARGV[2],ARGV[1])", [$key, $val, $ttl], 1
);
... ... @@ -937,11 +952,12 @@ function redis_add($key,$val,$ttl=3600){
* @param $project_id
* @param $domain
* @param $is_complete
* @author Akun
* @return bool
* @date 2023/12/08 14:17
* @author Akun
*/
function check_remote_url_down($url,$project_id,$domain,$is_complete=0){
function check_remote_url_down($url, $project_id, $domain, $is_complete = 0)
{
if (!$url) {
return '';
... ... @@ -950,24 +966,24 @@ function check_remote_url_down($url,$project_id,$domain,$is_complete=0){
$arr = parse_url($url);
$scheme = $arr['scheme'] ?? '';
$host = $arr['host'] ?? '';
$host_arr = explode('.',$host);
$host_arr = explode('.', $host);
$path = $arr['path'] ?? '';
if(strpos($host_arr[0], 'cdn') !== false){
if (strpos($host_arr[0], 'cdn') !== false) {
return $url;
}
if($host_arr[0] == 'file' && $host_arr[1] == 'globalso'){
if ($host_arr[0] == 'file' && $host_arr[1] == 'globalso') {
return $url;
}
//475项目特殊处理
if($project_id == 475 && $host == 'www.ebuyplc.com'){
if ($project_id == 475 && $host == 'www.ebuyplc.com') {
$host = 'g934.goodao.net';
}
if($path && substr($path,0,1) != '/'){
$path = '/'.$path;
if ($path && substr($path, 0, 1) != '/') {
$path = '/' . $path;
}
if (
... ... @@ -978,13 +994,13 @@ function check_remote_url_down($url,$project_id,$domain,$is_complete=0){
) {
$url_complete = ($scheme ?: 'https') . '://' . ($host ?: $domain) . $path;
$new_url = CosService::uploadRemote($project_id,'image_product',$url_complete);
if($new_url){
$new_url = CosService::uploadRemote($project_id, 'image_product', $url_complete);
if ($new_url) {
return $is_complete ? getImageUrl($new_url) : $new_url;
}else{
} else {
return false;
}
}else{
} else {
return false;
}
}
... ... @@ -994,10 +1010,11 @@ function check_remote_url_down($url,$project_id,$domain,$is_complete=0){
* @author zbj
* @date 2024/3/29
*/
function textareaToArr($content, $separator = ','){
return array_values(array_filter(array_unique(array_map(function ($v){
function textareaToArr($content, $separator = ',')
{
return array_values(array_filter(array_unique(array_map(function ($v) {
return trim($v);
},explode($separator, $content)))));
}, explode($separator, $content)))));
}
/**
... ... @@ -1007,7 +1024,8 @@ function textareaToArr($content, $separator = ','){
* @method :post
* @time :2024/6/26 10:46
*/
function ip_to_unique_string($ip) {
function ip_to_unique_string($ip)
{
// 将IP地址转换为数值表示
$ip_number = ip2long($ip);
// 使用哈希函数生成唯一数值
... ... @@ -1021,7 +1039,8 @@ function ip_to_unique_string($ip) {
return strtolower($unique_string);
}
function base62_encode($num) {
function base62_encode($num)
{
$characters = '23456789abcdefghijkmnpqrstuvwxyz';
$base = strlen($characters);
$result = '';
... ... @@ -1039,8 +1058,9 @@ function base62_encode($num) {
* @method :post
* @time :2024/8/19 14:21
*/
function urlSafeBase64Encode($data = '') {
if(empty($data)){
function urlSafeBase64Encode($data = '')
{
if (empty($data)) {
return $data;
}
// 1. 使用标准的 BASE64 编码
... ... @@ -1061,7 +1081,8 @@ function urlSafeBase64Encode($data = '') {
* @method :post
* @time :2024/9/14 16:45
*/
function generateRandomString($length) {
function generateRandomString($length)
{
return substr(str_shuffle(str_repeat($x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil($length / strlen($x)))), 1, $length);
}
... ... @@ -1080,26 +1101,26 @@ if (!function_exists('check_domain_record')) {
$is_record = false;
//获取域名解析记录
$records = dns_get_record($domain,DNS_A);
if(count($records) == 1 && ($records[0]['host'] == $server_info['domain'] || $records[0]['ip'] == $server_info['ip'])){
$records = dns_get_record($domain, DNS_A);
if (count($records) == 1 && ($records[0]['host'] == $server_info['domain'] || $records[0]['ip'] == $server_info['ip'])) {
$is_record = true;
}
if(!$is_record){
if (!$is_record) {
//解析不正确,再判断是否开启cnd
$top_domain = getTopDomain($domain);
$cnd = curlGet('http://sitebak.globalso.com/get_records?domain=' . $top_domain);
if (isset($cnd['data']) && $cnd['data']) {
if($domain == $top_domain || substr($domain,0,4) == 'www.'){
if ($domain == $top_domain || substr($domain, 0, 4) == 'www.') {
$check_domain = $domain;
}else{
$check_domain = '*.'.$top_domain;
} else {
$check_domain = '*.' . $top_domain;
}
foreach ($cnd['data'] as $vc) {
if ($vc['name'] == $check_domain && $vc['type'] == 'A' && $vc['content'] == $server_info['ip']) {
$is_record = true;
break;
}elseif ($vc['name'] == $check_domain && $vc['type'] == 'CNAME' && $vc['content'] == $server_info['domain']){
} elseif ($vc['name'] == $check_domain && $vc['type'] == 'CNAME' && $vc['content'] == $server_info['domain']) {
$is_record = true;
break;
}
... ... @@ -1108,8 +1129,8 @@ if (!function_exists('check_domain_record')) {
}
return $is_record;
}catch (\Exception $e){
errorLog('dns_get_record',['domain'=>$domain],$e);
} catch (\Exception $e) {
errorLog('dns_get_record', ['domain' => $domain], $e);
return false;
}
}
... ... @@ -1123,7 +1144,8 @@ if (!function_exists('check_curl_status')) {
* @author Akun
* @date 2024/12/12 15:52
*/
function check_curl_status($url){
function check_curl_status($url)
{
$header = array(
'Expect:',
'Content-Type: application/json; charset=utf-8'
... ... @@ -1142,7 +1164,7 @@ if (!function_exists('check_curl_status')) {
curl_setopt($ch, CURLOPT_SSLVERSION, 'all');
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_exec($ch);
$http_code = curl_getinfo($ch,CURLINFO_HTTP_CODE);
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $http_code;
... ... @@ -1154,7 +1176,8 @@ if (!function_exists('check_curl_status')) {
* @author zbj
* @date 2024/10/25
*/
function email_desensitize($email){
function email_desensitize($email)
{
$parts = explode('@', $email);
$username = $parts[0] ?? '';
$domain = $parts[1] ?? '';
... ... @@ -1168,7 +1191,8 @@ function email_desensitize($email){
* @author zbj
* @date 2024/10/25
*/
function getRandByRatio($proArr){
function getRandByRatio($proArr)
{
$result = '';
$proSum = array_sum($proArr);
foreach ($proArr as $key => $proCur) {
... ... @@ -1206,7 +1230,7 @@ function getPrefixKeyword($project_id, $type, $num)
$keyword = array_slice($fix_keyword, 0, $num);
$str = implode(", ", $keyword);
foreach ($keyword as $k=>$v){
foreach ($keyword as $k => $v) {
$tmp = rtrim($v, 's');
if (substr_count($str, $tmp) > 1) {
unset($keyword[$k]);
... ... @@ -1224,16 +1248,17 @@ function getPrefixKeyword($project_id, $type, $num)
* @method :post
* @time :2025/2/11 14:58
*/
function getDeployOptimize($project_id){
function getDeployOptimize($project_id)
{
$cache_key = 'project_deploy_optimize_info_' . $project_id;
$info = Cache::get($cache_key);
if(!$info){
if (!$info) {
$projectOptimizeModel = new DeployOptimize();
$info = $projectOptimizeModel->read(['project_id' => $project_id], ['id', 'company_en_name', 'company_en_description', 'keyword_prefix', 'keyword_suffix', 'special']);
$projectKeywordModel = new ProjectKeyword();
$keywordInfo = $projectKeywordModel->read(['project_id'=>$project_id]);
$keywordInfo = $projectKeywordModel->read(['project_id' => $project_id]);
$info['main_keyword'] = '';
if(!empty($keywordInfo['main_keyword'])){
if (!empty($keywordInfo['main_keyword'])) {
$info['main_keyword'] = $keywordInfo['main_keyword'];
}
Cache::put($cache_key, $info, 600);
... ... @@ -1249,7 +1274,8 @@ function getDeployOptimize($project_id){
* @method :post
* @time :2025/4/1 9:41
*/
function paginateArray($array, $page = 1, $pageSize = 20) {
function paginateArray($array, $page = 1, $pageSize = 20)
{
$totalItems = count($array);
$totalPages = ceil($totalItems / $pageSize);
// 确保页码有效
... ... @@ -1272,8 +1298,9 @@ function paginateArray($array, $page = 1, $pageSize = 20) {
* @method :post
* @time :2025/4/3 16:19
*/
function getDomain($url) {
if(empty($url)){
function getDomain($url)
{
if (empty($url)) {
return $url;
}
$parsedUrl = parse_url($url);
... ... @@ -1394,12 +1421,13 @@ function analysisRoute($pathInfo)
return $router;
}
function getTopDomain ($url) {
function getTopDomain($url)
{
$url = strtolower($url); //首先转成小写
$url = mb_ereg_replace('^( | )+', '', trim($url));
$url = mb_ereg_replace('( | )+$', '', $url);
if (!preg_match('/^(http:\/\/|https)/', $url)) {
$url = "https://".$url;
$url = "https://" . $url;
}
$hosts = parse_url($url);
$host = $hosts['host'] ?? '';
... ... @@ -1413,10 +1441,10 @@ function getTopDomain ($url) {
$preg = '/[\w].+\.(com|net|org|gov|edu|co|ne)\.[\w]/';
if (($n > 2) && preg_match($preg, $host)) {
//双后缀取后3位
$host = $data[$n - 3].'.'.$data[$n - 2].'.'.$data[$n - 1];
$host = $data[$n - 3] . '.' . $data[$n - 2] . '.' . $data[$n - 1];
} else {
//非双后缀取后两位
$host = $data[$n - 2].'.'.$data[$n - 1];
$host = $data[$n - 2] . '.' . $data[$n - 1];
}
return $host;
}
... ... @@ -1440,3 +1468,126 @@ function diffInHours($startTime, $endTime)
return round($hours, 1);
}
/**
* 通过图片地址压缩图片
* @param $url
* @param int $width
* @return string
* @author Akun
* @date 2025/09/01 15:18
*/
function thumbImageByUrl($url, $width = 360)
{
if (empty($url)) {
return $url;
}
if ($width == 0) {
return $url;
}
if (strpos($url, '_thumb') !== false) {
return $url;
}
//获取图片完整访问地址
$url_complete = getImageUrl($url, 0, 0, 0);//先用v6-file地址
if (strpos($url_complete, 'v6-file') !== false) {
$is_exists = checkRemoteFileExists($url_complete);
if (!$is_exists) {
//不存在,再用cdn地址
$url_complete = getImageUrl($url);
}
}
//获取与原图存储路径相同的压缩路径
$path = parse_url($url_complete, PHP_URL_PATH);
$path_arr = explode('.', $path);
if (count($path_arr) != 2) {
return $url;
}
$path_arr[0] = $path_arr[0] . '_thumbW' . $width;
$key = implode('.', $path_arr);
try {
$img = \Intervention\Image\Facades\Image::make($url_complete);
//宽度按设定,高度自动调整
$img->resize($width, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
//获取处理后的图片二进制资源
$resource = $img->stream()->__toString();
//上传存储桶
$thumb_url = CosService::uploadRemote('', '', '', $key, $resource);
$url = $thumb_url ? $thumb_url : $url;
} catch (\Exception $e) {
Log::channel('thumb_img')->error($e->getMessage(), [$url, $width]);
}
return $url;
}
if (!function_exists('checkRemoteFileExists')) {
/**
* 判断远程文件是否存在
* @param $url
* @return bool
* @author Akun
* @date 2025/09/05 9:58
*/
function checkRemoteFileExists($url)
{
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_NOBODY, true);
$result = curl_exec($curl);
$found = false;
if ($result !== false) {
$statusCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($statusCode == 200) {
$found = true;
}
}
curl_close($curl);
return $found;
}
}
if (!function_exists('httpGetSsl')) {
/**
* 获取通配符证书
* @param $domain
* @return mixed
* @author Akun
* @date 2025/04/21 16:51
*/
function httpGetSsl($domain)
{
$header = array(
"Accept:application/json",
"Content-Type:application/json;charset=utf-8",
"X-CmerApi-Host:" . env('GET_SSL_HOST'),
"Apikey:" . env('GET_SSL_KEY'),
);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, env('GET_SSL_URL') . '?domain=' . $domain);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)');
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_AUTOREFERER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$res = curl_exec($ch);
curl_close($ch);
$result = json_decode($res, true);
return is_array($result) ? $result : $res;
}
}
... ...
... ... @@ -3,6 +3,7 @@
namespace App\Http\Controllers\Api;
use App\Exceptions\InquiryFilterException;
use App\Models\Domain\DomainInfo;
use App\Models\Mail\Mail;
use App\Models\Project\DeployBuild;
use App\Models\Project\Project;
... ... @@ -69,7 +70,7 @@ class SelfSiteController extends BaseController
$cos = new CosService();
$fileName = uniqid() . rand(10000, 99999) . '.' . $file['ext'];
$file_data = base64_decode($file['data']);
$path = $cos->uploadFile($file_data, '/inquiry/' . date('Ymd'), $fileName,true);
$path = $cos->uploadFile($file_data, '/inquiry/' . date('Ymd'), $fileName, true);
$data[$key] = [
'path' => $path,
'original_name' => $file['name'],
... ... @@ -191,4 +192,50 @@ class SelfSiteController extends BaseController
return $this->success([]);
}
/**
* 自建站获取通配符证书接口
* @param Request $request
* @return false|string
* @author Akun
* @date 2025/09/02 16:55
*/
public function selfSiteSsl(Request $request)
{
$token = $request->header('token');//token
$pid = $request->header('pid');//项目id
if (empty($token) || empty($pid)) {
return $this->error('token无效', 401);
}
//判断token是否有效
$project_model = new Project();
$project_info = $project_model->read(['id' => $pid, 'site_token' => $token]);
if (!$project_info) {
return $this->error('token无效', 401);
}
//获取域名信息
$domain_model = new DomainInfo();
$domain_info = $domain_model->read(['project_id' => $pid]);
if (!$domain_info) {
return $this->error('获取域名失败', 401);
}
//获取通配符证书
$top_domain = getTopDomain($domain_info['domain']);
$ssl_re = httpGetSsl($top_domain);
$return = [
'ssl_key' => '',
'ssl_cert' => ''
];
if (isset($ssl_re['status']) && $ssl_re['status'] == 2) {
//获取成功
$return['ssl_key'] = $ssl_re['ssl_key'];
$return['ssl_cert'] = $ssl_re['ssl_cert'];
}
return $this->success($return);
}
}
... ...
... ... @@ -2,9 +2,15 @@
namespace App\Http\Controllers\Api\WorkOrder;
use App\Enums\Common\Code;
use App\Http\Controllers\Api\BaseController;
use App\Http\Logic\Aside\Project\ProcessRecordsLogic;
use App\Http\Logic\Aside\Project\ProjectLogic;
use App\Http\Requests\Api\WorkOrder\TicketListRequest;
use App\Http\Requests\Api\WorkOrder\TicketStoreRequest;
use App\Models\Project\ProcessRecords;
use App\Models\Project\Project;
use App\Models\ProjectAssociation\ProjectAssociation;
use App\Models\WorkOrder\TicketLog;
use App\Models\WorkOrder\TicketProject;
use App\Models\WorkOrder\Tickets;
... ... @@ -183,4 +189,74 @@ class TicketController extends BaseController
$project->pushWechatGroupMsg("您好,我们同事没有及时回复,你可以查看工单进度!");
return response()->json(['message' => '工单推送成功']);
}
/**
* @remark :工单中获取
* @name :get_process_records
* @author :lyh
* @method :post
* @time :2025/9/9 15:28
*/
public function get_project_records(Request $request){
$request->validate([
'project_id'=>'required'
],[
'project_id.required' => '项目ID不能为空'
]);
$data = (new ProcessRecords())->read(['project_id'=>$this->param['project_id']]);
$project = (new Project())->with(['payment', 'deploy_build', 'deploy_optimize', 'online_check',
'project_after','inquiry_filter_config','web_traffic_config','project_keyword'])->where(['id'=>$this->param['project_id']])->first()->toArray();
if(!$data){
$data = [
'project_id' => $this->param['project_id'],
'record' => [],
'remark' => '',
'project_record'=>0,
'optimize_record'=>0,
'type'=>$project['type']
];
}else{
$data['type'] = $project['type'];
}
$data['record'] = array_filter($data['record'], function($item) {
return $item['date'] > '2025-09-01';
});
if($project['type'] == 2){
//优化项目 默认在seo优化中
if($data['optimize_record'] == 0) {
$data['optimize_record'] = 1;
}
//时间大于优化时间,默认
if(date('Y-m-d') > $project['deploy_optimize']['start_date']){
$data['optimize_record'] = 2;
}
//首次达标时间
if(!empty($project['deploy_optimize']['first_compliance_time'])){
$data['optimize_record'] = 3;
}
//无剩余时间
if($project['project_type'] == 1){
$remain_day = $project['seo_remain_day'];
if($project['seo_remain_day'] == 0){$data['optimize_record'] = 4;}
}else{
$remain_day = $project['remain_day'];
if($project['remain_day'] == 0){$data['optimize_record'] = 4;}
}
if(in_array(2,$project['level'])){
$data['date_project_record'] = ['暂停优化'];
}else{
$data['date_project_record'] = Project::projectProgress('optimize');
$data['date_project_record'][4] .= (': '.$remain_day.'天');
}
}else{
//查看是否绑定微信群
$projectAss = new ProjectAssociation();
$count = $projectAss->counts(['project_id'=>$this->param['project_id']]);
if(($count > 0) && ($data['project_record'] == 0)){
$data['project_record'] = 1;
}
$data['date_project_record'] = Project::projectProgress('build');
}
$this->response('success',Code::SUCCESS,$data);
}
}
... ...
... ... @@ -200,6 +200,7 @@ class OptimizeController extends BaseController
'gl_project.is_translate AS is_translate',
'gl_project.is_translate_tag AS is_translate_tag',
'gl_project.is_upgrade AS is_upgrade',
'gl_project.project_type AS project_type',
'gl_project.site_status AS site_status',
'gl_project_online_check.id AS online_check_id',
'gl_project_online_check.question AS question',
... ... @@ -322,9 +323,9 @@ class OptimizeController extends BaseController
$query = $query->where('gl_project_deploy_build.test_domain','like','%'.$this->map['test_domain'].'%');
}
$query = $query->where('gl_project.type',2)->where('gl_project.extend_type','!=',5);//TODO::2,4代表优化项目; 2024-06-05修改项目中台只显示为类型为2
$query->where(function ($subQuery) {
$subQuery->orwhere('gl_project_online_check.qa_status',1)->orwhere('gl_project.is_upgrade',1);
});
// $query->where(function ($subQuery) {
// $subQuery->where('gl_project.is_upgrade',1);
// });
return $query;
}
... ... @@ -547,9 +548,9 @@ class OptimizeController extends BaseController
ProjectServer::useProject($this->param['project_id']);
$productKeywordModel = new Keyword();
$data = [];
$lists = $productKeywordModel->list(['route'=>['!=',null]],'id',['id','route','seo_title']);
if (!empty($lists)){
foreach ($lists as $item){
$lists = $productKeywordModel->lists(['route'=>['!=',null]],1,500,'id',['id','route','seo_title']);
if (!empty($lists['list'])){
foreach ($lists['list'] as $item){
$data[] = $domain . $item['route'] . '/{' . $item['seo_title'] . '}';
}
}
... ...
... ... @@ -598,6 +598,7 @@ class ProjectController extends BaseController
$this->response('success',Code::SUCCESS,$data);
}
/**
* 保存进程记录
* @author zbj
... ...
... ... @@ -161,6 +161,7 @@ class RenewProjectController extends BaseController
$data = APublicModel::getNumByProjectId($item['id']);
}
$plan = Project::planMap();
$seoPlan = Project::seoMap();
$item = [
'id' => $item['id'],
'title' => $item['title'],
... ... @@ -178,8 +179,10 @@ class RenewProjectController extends BaseController
'optimize_tech' => $manageModel->getName($item['deploy_optimize']['tech_mid']), //售后技术
'type' => $item['type'],
'test_domain' => $item['deploy_build']['test_domain'] ?? 0,
'plan' =>$plan[$item['deploy_build']['plan']] ?? '白帽seo版本',
'plan' =>$plan[$item['deploy_build']['plan']] ?? '无',
'seo_plan' =>$seoPlan[$item['deploy_build']['seo_plan']] ?? '无',
'plan_id' =>$item['deploy_build']['plan'],
'seo_plan_id' =>$item['deploy_build']['seo_plan'],
'domain' => !empty($item['deploy_optimize']['domain']) ? $domainModel->getDomain($item['deploy_optimize']['domain']) : '',
'created_at' => date('Y年m月d日', strtotime($item['created_at'])),
'autologin_code' => getAutoLoginCode($item['id']),
... ...
... ... @@ -6,6 +6,7 @@ use App\Enums\Common\Code;
use App\Http\Controllers\Aside\BaseController;
use App\Http\Logic\Aside\Template\ATemplateLogic;
use App\Http\Requests\Aside\Template\ATemplateRequest;
use App\Models\Manage\Manage;
use App\Models\Template\TemplateLabel;
/**
... ... @@ -26,12 +27,14 @@ class ATemplateController extends BaseController
public function lists(ATemplateLogic $aTemplateLogic){
$templateLabel = new TemplateLabel();
$this->map = $this->searchLabelName($templateLabel);
$filed = ['id','name','image','url','status','sort','deleted_status','test_model','created_at','project_id'];
$filed = ['id','name','image','url','status','upload_id','sort','deleted_status','test_model','submit_time','design_msg','front_msg','created_at','project_id'];
$lists = $aTemplateLogic->aTemplateList($this->map,$this->page,$this->row,$this->order,$filed);
if(!empty($lists) && !empty($lists['list'])){
$manageModel = new Manage();
foreach ($lists['list'] as $k => $v){
$v['label'] = $templateLabel->list(['template_id'=>$v['id'],'type'=>1],'id',['id','name'],'desc',5);
$v['image_link'] = getImageUrl($v['image']);
$v['upload_name'] = $manageModel->getName($v['upload_id']);
$lists['list'][$k] = $v;
}
}
... ...
... ... @@ -12,7 +12,12 @@ namespace App\Http\Controllers\Aside\Ticket;
use App\Enums\Common\Code;
use App\Http\Controllers\Aside\BaseController;
use App\Http\Logic\Aside\Ticket\TicketLogic;
use App\Models\Ticket\TicketDailyCount;
use App\Models\Ticket\TicketMonthDeptCount;
use App\Models\Ticket\TicketWeekDeptCount;
use Illuminate\Http\Request;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Cache;
class TicketController extends BaseController
{
... ... @@ -30,14 +35,91 @@ class TicketController extends BaseController
* @time :2025/8/11 10:47
*/
public function ticketCount(){
$data['daily'] = $this->logic->getTicketCount();
$data['list'] = $this->logic->getDailyTicketCount();
$data['ticket'] = $this->logic->getTicketList();
$data = Cache::get('ticket_count');
if(empty($data)){
$data = [];
$data['daily'] = $this->logic->getTicketCount();
$data['list'] = $this->logic->getDailyTicketCount();
$data['ticket'] = $this->logic->getTicketList();
Cache::put('ticket_count',$data,1800);
}
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :技术组
* @remark :获取最近一个月的数据
* @name :getMonthList
* @author :lyh
* @method :post
* @time :2025/8/30 17:26
*/
public function getMonthList(){
$this->request->validate([
'start'=>'required',
'end'=>'required'
],[
'start.required' => 'start不能为空',
'end.required' => 'end不能为空',
]);
$dailyModel = new TicketDailyCount();
$dailyList = $dailyModel->list(['date'=>['between',[$this->param['start'],$this->param['end']]]],'date',['*'],'desc',30);//取最近30条数据
$this->response('success',Code::SUCCESS,$dailyList);
}
/**
* @remark :获取搜索时间
* @name :getTIme
* @author :lyh
* @method :post
* @time :2025/8/30 15:39
*/
public function getTime(){
$weekModel = new TicketWeekDeptCount();
$weekData = $weekModel->where('dept_id',1)->select('start_at', 'end_at')->distinct()->get()->toArray();
$monthModel = new TicketMonthDeptCount();
$monthData = $monthModel->where('dept_id',1)->select('start_at', 'end_at')->distinct()->get()->toArray();
$this->response('success',Code::SUCCESS,['week_data'=>$weekData,'month_data'=>$monthData]);
}
/**
* @remark :周记录数据(默认上一周)
* @name :weekManageList
* @author :lyh
* @method :post
* @time :2025/8/30 15:31
*/
public function weekManageList(){
$this->request->validate([
'start'=>'required',
'end'=>'required'
],[
'start.required' => 'start不能为空',
'end.required' => 'end不能为空',
]);
$data = $this->logic->getWeekManageList($this->param['start'],$this->param['end'],$this->param['dept_id'] ?? 1,$this->order,$this->param['sort'] ?? 'desc');
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :按月统计数据(默认上一月)
* @name :monthManageList
* @author :lyh
* @method :post
* @time :2025/8/30 15:35
*/
public function monthManageList(){
$this->request->validate([
'start'=>'required',
'end'=>'required'
],[
'start.required' => 'start不能为空',
'end.required' => 'end不能为空',
]);
$data = $this->logic->getMonthManageList($this->param['start'],$this->param['end'],$this->param['dept_id'] ?? 1,$this->order,$this->param['sort'] ?? 'desc');
$this->response('success',Code::SUCCESS,$data);
}
/**
* @remark :技术组总统计
* @name :manageTicketCount
* @author :lyh
* @method :post
... ...
... ... @@ -50,7 +50,31 @@ class AsideTicketController extends BaseController
->when($request->input('status') !== null, function ($query) use ($request) {
// status 查 gl_tickets.status
$status = $request->input('status');
return $query->where('status', $status);
if($status == 10){
$newTime = date("Y-m-d H:i:s", strtotime("-120 hours"));
return $query->where('status', 0)->where('plan_end_at','<',$newTime);//超过120个小时未处理的工单
}else{
return $query->where('status', $status);
}
})
->when($request->input('timeout') !== null, function ($query) use ($request) {
// status 查 gl_tickets.status
$timeout = $request->input('timeout');
switch ($timeout) {
case 1:
$newTime = date("Y-m-d H:i:s", strtotime("-24 hours"));
break;
case 2:
$newTime = date("Y-m-d H:i:s", strtotime("-48 hours"));
break;
case 3:
$newTime = date("Y-m-d H:i:s", strtotime("-72 hours"));
break;
default:
$newTime = date("Y-m-d H:i:s");
break;
}
return $query->where('status', 0)->where('plan_end_at','<',$newTime);//超过120个小时未处理的工单
})
->when($request->input('star') !== null, function ($query) use ($request) {
$star = $request->input('star');
... ... @@ -84,10 +108,30 @@ class AsideTicketController extends BaseController
//TODO::用户部门搜索
if(isset($this->param['dept_id']) && !empty($this->param['dept_id'])){
$manageHrModel = new ManageHr();
$manageIdArr = $manageHrModel->selectField(['dept_id'=>$this->param['dept_id'],'status'=>1],'manage_id');
$query->whereHas('logs', function ($q) use ($manageIdArr) {
$q->whereIn('engineer_id', $manageIdArr);
});
//售后优化+技术搜索
if($this->param['dept_id'] == 2 && !empty($this->param['entry_position'])) {//售后部
if ($this->param['entry_position'] == 1) {
$manageIdArr = $manageHrModel->selectField(['entry_position' => ['in', [44, 46, 49]], 'status' => 1], 'manage_id');
} else {
//售后技术
$manageIdArr = $manageHrModel->selectField(['entry_position' => ['in', [42, 43, 45, 48, 51]], 'status' => 1], 'manage_id');
}
$query->whereHas('logs', function ($q) use ($manageIdArr) {
$q->whereIn('engineer_id', $manageIdArr);
});
}else{
$manageIdArr = $manageHrModel->selectField(['dept_id'=>$this->param['dept_id'],'status'=>1],'manage_id');
$query->whereHas('logs', function ($q) use ($manageIdArr) {
$q->whereIn('engineer_id', $manageIdArr);
});
}
}
if(!empty($this->param['start_at']) && !empty($this->param['end_at'])){
$query->whereBetween('created_at',[$this->param['start_at'],$this->param['end_at']]);
}
//搜索提交人姓名
if(!empty($this->param['submit_username'])){
$query->where('submit_username','like','%'.$this->param['submit_username'].'%');
}
// 添加排序功能
$query->orderBy('status', 'asc');
... ... @@ -96,11 +140,24 @@ class AsideTicketController extends BaseController
$sortOrder = strtolower($request->input('sort_order', 'asc'));
$query->orderBy($sortField, $sortOrder);
if ($sortField != 'plan_end_at') $query->orderBy('plan_end_at', 'asc');
$lists = $query->paginate($this->row, ['*'], 'page', $this->page);
$lists = $query->paginate($this->row, ['*'], 'page', $this->page)->toArray();
if(!empty($lists) && !empty($lists['list'])){
foreach ($lists['list'] as $key => $item){
//计算超时多少个小时
if($item['status'] == 0){
$end = date('Y-m-d H:i:s');
$start = $item['plan_end_at'];
if($start < $end){
$item['plan_ent_time'] = diffInHours($start,$end);
}
}
$lists['list'][$key] = $item;
}
}
$this->response('success', Code::SUCCESS, $lists);
}
/**
/**
* @param $search
* @return void
* V5V6所有项目
... ... @@ -201,7 +258,6 @@ class AsideTicketController extends BaseController
$ticket->close_wechat = $request->input('close_wechat', false);
$ticket->num = $request->input('num', 0);
$ticket->save();
// 分配工单参与人
$ticket->saveEngineers($request->input('engineer_ids', []));
$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
$ticket->status = $request->input('status');
if ($request->input('num'))
$ticket->num = $request->input('num',0);
//同步更改工单时间
$ticket->logs()->where('status', '<', TicketLog::STATUS_COMPLETED)->where('is_engineer', 1)->update(['plan_end_at' => $ticket->plan_end_at]);
if ($ticket->status == Tickets::STATUS_COMPLETED)
{
// 完成工单,把子任务里面未完成的工单改为完成
... ... @@ -311,5 +368,4 @@ class AsideTicketController extends BaseController
$project->pushWechatGroupMsg();
$this->response('success', Code::SUCCESS);
}
}
... ...
... ... @@ -232,12 +232,12 @@ class CNoticeController extends BaseController
}
//获取项目所在服务器
$project_model = new Project();
$project_info = $project_model->read(['id'=>$project_id],['serve_id','is_upgrade', 'main_lang_id']);
$project_info = $project_model->read(['id'=>$project_id],['serve_id','type','is_upgrade', 'main_lang_id']);
if(!$project_info){
$this->fail('未查询到项目数据');
}
// --------------------------------------------------- 特殊处理通知生成页面 --------------------------------------------------------------
if ($type == 2 && $project_info['main_lang_id'] == 8) {
if ($type == 2 && ($project_id != 4041) && ($project_info['main_lang_id'] == 8)) {
$this->fail('申请项目主语种为俄语,禁止翻译小语种,如若需要翻译小语种, 请联系售后人员确认!');
}
... ...
... ... @@ -72,7 +72,7 @@ class GeoQuestionResController extends BaseController
'project_id.required' => 'project_id不能为空',
'type.required' => '品牌类型不能为空'
]);
$data = $this->logic->getResultList($this->map,$this->page,$this->row);
$data = $this->logic->getResultList($this->map,$this->page,$this->row,$this->order,$this->param['sort'] ?? 'desc');
$this->response('success',Code::SUCCESS,$data);
}
... ...
... ... @@ -398,7 +398,7 @@ class ImageController extends Controller
foreach ($str_data as $k => $v){
$arr = explode('/',$v);
if ($arr[0] == 'text') {
$arr[1] = urlSafeBase64Encode($arr[1]);
$arr[1] = urlSafeBase64Encode($arr[1] ?? 'shuiying');
$v = implode('/',$arr);
}
if ($arr[0] == 'font') {
... ...
... ... @@ -195,19 +195,25 @@ class DomainInfoLogic extends BaseLogic
$host = $domain_array['host'] ?? $domain_array['path'];
$host_array = explode('.',$host);
//已经解析泛域名的项目,更改项目解析状态
$host_array_any = $host_array;
if (count($host_array_any) <= 2) {
array_unshift($host_array_any, '*');
} else {
$host_array_any[0] = '*';
}
$any_domain = implode('.',$host_array_any);
$rand_str = generateRandomString(3);
$any_check_status = check_domain_record(str_replace('*',$rand_str,$any_domain), $serversIpInfo);
if($any_check_status){
$project_model->edit(['is_analysis'=>1],['id'=>$info['project_id']]);
}
if($this->param['type'] == 3){
//需要申请通配符证书
//判断*是否已经解析
$host_array_any = $host_array;
if (count($host_array_any) <= 2) {
array_unshift($host_array_any, '*');
} else {
$host_array_any[0] = '*';
}
$any_domain = implode('.',$host_array_any);
$rand_str = generateRandomString(3);
if(!check_domain_record(str_replace('*',$rand_str,$any_domain), $serversIpInfo)){
//判断是否已经解析泛域名
if(!$any_check_status){
$this->fail('域名' . $any_domain . '未解析至目标服务器');
}
... ...
... ... @@ -73,7 +73,7 @@ class GeoLinkLogic extends BaseLogic
foreach ($this->param['data'] as $item){
$data[] = [
'project_id'=>$this->param['project_id'],
'da'=>$item['da'],
'da'=>$item['da'] ?? '',
'url'=>$item['url'],
'send_time'=>$item['send_time']
];
... ...
... ... @@ -7,6 +7,7 @@ use App\Http\Logic\Aside\BaseLogic;
use App\Models\Domain\DomainInfo;
use App\Models\Project\ProcessRecords;
use App\Models\Project\Project;
use App\Models\ProjectAssociation\ProjectAssociation;
class ProcessRecordsLogic extends BaseLogic
{
... ... @@ -20,14 +21,19 @@ class ProcessRecordsLogic extends BaseLogic
public function getInfo($project_id)
{
$data = $this->model->read(['project_id'=>$project_id]);
$info = $data;
$project = ProjectLogic::instance()->getProjectInfo($project_id);
if(!$data){
$data = [
'project_id' => $project_id,
'record' => [],
'remark' => '',
'project_record'=>0,
'optimize_record'=>0,
'type'=>$project['type']
];
}
$data['type'] = $project['type'] ?? '';
$data['project_company'] = $project['company'] ?? '';
$plan = Project::planMap();
$seo_plan = Project::seoMap();
... ... @@ -55,6 +61,45 @@ class ProcessRecordsLogic extends BaseLogic
'item' => ['资料上传', '网站修改中', '网站搭建完成,客户确认中', '等待网站品控审核后上线']
]
];
// $data['record'] = array_filter($data['record'], function($item) {
// return $item['date'] > '2025-09-01';
// });
if($project['type'] == 2){
//优化项目 默认在seo优化中
if($data['optimize_record'] == 0) {
$data['optimize_record'] = 1;
}
//时间大于优化时间,默认
if(date('Y-m-d') > $project['deploy_optimize']['start_date']){
$data['optimize_record'] = 2;
}
//首次达标时间
if(!empty($project['deploy_optimize']['first_compliance_time'])){
$data['optimize_record'] = 3;
}
//无剩余时间
if($project['project_type'] == 1){
$remain_day = $project['seo_remain_day'];
if($project['seo_remain_day'] == 0){$data['optimize_record'] = 4;}
}else{
$remain_day = $project['remain_day'];
if($project['remain_day'] == 0){$data['optimize_record'] = 4;}
}
if(in_array(2,$project['level'])){
$data['date_project_record'] = ['暂停优化'];
}else{
$data['date_project_record'] = Project::projectProgress('optimize');
$data['date_project_record'][4] .= (': '.$remain_day.'天');
}
}else{
//查看是否绑定微信群
$projectAss = new ProjectAssociation();
$count = $projectAss->counts(['project_id'=>$project_id]);
if(($count > 0) && ($data['project_record'] == 0)){
$data['project_record'] = 1;
}
$data['date_project_record'] = Project::projectProgress('build');
}
return $this->success($data);
}
... ...
... ... @@ -472,7 +472,9 @@ class ProjectLogic extends BaseLogic
}
$param['confirm_file'] = Arr::a2s($param['confirm_file'] ?? []);
$remain_day = $param['deploy_build']['service_duration'] - $param['finish_remain_day'];
$seo_remain_day = $param['deploy_build']['seo_service_duration'] - $param['bm_finish_remain_day'];
$param['remain_day'] = ($remain_day > 0) ? $remain_day : 0;
$param['seo_remain_day'] = ($seo_remain_day > 0) ? $seo_remain_day : 0;
//文件上传默认值
if($param['is_upload_manage']){
$param['upload_config'] = [
... ...
... ... @@ -15,6 +15,10 @@ use App\Models\Project\Project;
use App\Models\Ticket\TicketDailyCount;
use App\Models\Ticket\TicketDailyDeptCount;
use App\Models\Ticket\TicketDailyManageCount;
use App\Models\Ticket\TicketMonthDeptCount;
use App\Models\Ticket\TicketMonthManageCount;
use App\Models\Ticket\TicketWeekDeptCount;
use App\Models\Ticket\TicketWeekManageCount;
use App\Models\WorkOrder\TicketLog;
use App\Models\WorkOrder\TicketProject;
use App\Models\WorkOrder\Tickets;
... ... @@ -42,7 +46,7 @@ class TicketLogic extends BaseLogic
$date = date('Y-m-d');//今日时间
$data['add_num'] = $ticketModel->counts(['created_at'=>['between',[$date.' 00:00:00',$date.' 23:59:59']]]);//今日新增工单
$data['processed_num'] = $ticketModel->counts(['end_at'=>['between',[$date.' 00:00:00',$date.' 23:59:59']]]);//今日已处理工单
$data['untreated_num'] = $ticketModel->counts(['end_at'=>null]);//今日未处理工单
$data['untreated_num'] = $ticketModel->counts(['end_at'=>null]);//未处理工单
$submit_a_side = $ticketModel->formatQuery(['submit_side'=>1])->sum('submit_side');
$submit_b_side = $ticketModel->formatQuery(['submit_side'=>2])->sum('submit_side');
$data['source'] = ['a'=>$submit_a_side,'b'=>$submit_b_side];
... ... @@ -110,4 +114,41 @@ class TicketLogic extends BaseLogic
return $this->success($manageList);
}
/**
* @remark :按月统计数据
* @name :getWeekManageList
* @author :lyh
* @method :post
* @time :2025/8/30 16:02
*/
public function getWeekManageList($start,$end,$dept_id = 1,$order = 'complete_num',$sort){
if(empty($start) || empty($end)){
$start = Carbon::now()->subWeek()->startOfWeek(); // 上周一 00:00:00
$end = Carbon::now()->subWeek()->endOfWeek(); // 上周日 23:59:59
}
$manageWeekModel = new TicketWeekManageCount();
$manageWeekList = $manageWeekModel->list(['start_at'=>$start,'end_at'=>$end,'dept_id'=>$dept_id],$order,['*'],$sort);
$deptWeekModel = new TicketWeekDeptCount();
$deptWeekList = $deptWeekModel->list(['start_at'=>$start,'end_at'=>$end]);
return $this->success(['manage'=>$manageWeekList,'dept'=>$deptWeekList ?? []]);
}
/**
* @remark :按月统计数据
* @name :getMonthManageList
* @author :lyh
* @method :post
* @time :2025/8/30 16:27
*/
public function getMonthManageList($start,$end,$dept_id = 1,$order = 'complete_num',$sort = 'desc'){
if(empty($start) || empty($end)){
$start = Carbon::now()->subMonth()->startOfMonth(); // 上个月 1号 00:00:00
$end = Carbon::now()->subMonth()->endOfMonth(); // 上个月最后一天 23:59:59
}
$manageWeekModel = new TicketMonthManageCount();
$manageWeekList = $manageWeekModel->list(['start_at'=>$start,'end_at'=>$end,'dept_id'=>$dept_id],$order,['*'],$sort);
$deptWeekModel = new TicketMonthDeptCount();
$deptWeekList = $deptWeekModel->list(['start_at'=>$start,'end_at'=>$end]);
return $this->success(['manage'=>$manageWeekList,'dept'=>$deptWeekList]);
}
}
... ...
... ... @@ -417,6 +417,8 @@ class CustomModuleContentLogic extends BaseLogic
$info = $this->model->read(['id'=>$this->param['id']]);
$param = $this->setContentParams($info);
$save_id = $this->model->insertGetId($param);
$route = RouteMap::setRoute($param['route'], RouteMap::SOURCE_MODULE, $save_id, $this->user['project_id']);
$this->edit(['route' => $route], ['id' => $save_id]);
$this->copyTemplate($this->param['id'],$info['project_id'],$save_id,$info['module_id']);
return $this->success(['id'=>$save_id]);
}
... ...
... ... @@ -46,9 +46,10 @@ class GeoQuestionResLogic extends BaseLogic
* @method :post
* @time :2025/7/4 9:48
*/
public function getResultList($map = [],$page = 1,$row = 20){
public function getResultList($map = [],$page = 1,$row = 20,$order = 'created_at',$sort = 'desc'){
unset($map['sort']);
$map['project_id'] = $this->user['project_id'];
$filed = ['id','project_id','question_id','platform','is_match','question','en_question','keywords','url','label','created_at','updated_at'];
$filed = ['id','project_id','question_id','platform','is_match','question','en_question','keywords','url','label','cosine','created_at','updated_at'];
if(!empty($map['created_at'])){
$map['created_at'] = ['between',[$map['created_at'].' 00:00:00',$map['created_at'].' 23:59:59']];
$this->model = new GeoQuestionLog();
... ... @@ -64,7 +65,7 @@ class GeoQuestionResLogic extends BaseLogic
// $q->whereRaw('JSON_LENGTH(keywords) > 0')
// ->orWhereRaw('JSON_LENGTH(url) > 0');
// });
$data = $query->orderByRaw('CHAR_LENGTH(question) ASC')->paginate($row, $filed, 'page', $page);;
$data = $query->orderBy($order,$sort)->orderByRaw('CHAR_LENGTH(question) ASC')->paginate($row, $filed, 'page', $page);
return $this->success($data);
}
... ... @@ -93,32 +94,50 @@ class GeoQuestionResLogic extends BaseLogic
$core_question_count = $questionTotalCount = $urlTotalCount = $keywordsTotalCount = 0;
$keywordArr = [];
$questionLogModel = new GeoQuestionLog();
$keywordUrlCount = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'hit'=>['!=',0]]);
$coreKeywordUrlCount = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'label'=>['like','%核心问题%'],'hit'=>['!=',0]]);
foreach ($list as $item){
$questionTotalCount += count($item['question'] ?? []);
//核心问题数
if(strpos($item['label'],'核心问题') !== false){
$core_question_count += count($item['question'] ?? []);
if($this->user['project_id'] == 4533){
$keywordUrlCount = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'is_match'=>1,'hit'=>['!=',0]]);
foreach ($list as $item){
$questionTotalCount += count($item['question'] ?? []);
//核心问题数
if(strpos($item['label'],'核心问题') !== false){
$core_question_count += count($item['question'] ?? []);
}
foreach ($item['keywords'] as $keyWordItem){
if (!array_key_exists($keyWordItem, $keywordArr)) {
$keywordArr[$keyWordItem] = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'is_match'=>1,'keywords'=>['like','%"'.$keyWordItem.'"%']]);
}
}
}
$keywordsTotalCount += count($item['keywords'] ?? []);
$urlTotalCount += count($item['url'] ?? []);
foreach ($item['keywords'] as $keyWordItem){
if (!array_key_exists($keyWordItem, $keywordArr)) {
$keywordArr[$keyWordItem] = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'keywords'=>['like','%"'.$keyWordItem.'"%']]);
$coreKeywordUrlCount = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'label'=>['like','%核心问题%'],'is_match'=>1,'hit'=>['!=',0]]);
$data = [
'question_count'=>$questionTotalCount,//问题总数
'core_question_count'=>$core_question_count,//核心问题总数
'keywords_url_count'=>$keywordUrlCount,
'keywords_arr' => $keywordArr,
'core_keyword_url_count'=>$coreKeywordUrlCount ?? 0
];
return $this->success($data);
}else{
$keywordUrlCount = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'hit'=>['!=',0]]);
foreach ($list as $item){
$questionTotalCount += count($item['question'] ?? []);
$keywordsTotalCount += count($item['keywords'] ?? []);
$urlTotalCount += count($item['url'] ?? []);
foreach ($item['keywords'] as $keyWordItem){
if (!array_key_exists($keyWordItem, $keywordArr)) {
$keywordArr[$keyWordItem] = $questionLogModel->counts(['project_id'=>$this->user['project_id'],'keywords'=>['like','%"'.$keyWordItem.'"%']]);
}
}
}
$data = [
'question_count'=>$questionTotalCount,
'keywords_count'=>$keywordsTotalCount,
'url_count'=>$urlTotalCount,
'keywords_url_count'=>$keywordUrlCount,
'keywords_arr' => $keywordArr,
];
return $this->success($data);
}
$data = [
'keywords_count'=>$keywordsTotalCount,
'url_count'=>$urlTotalCount,
'question_count'=>$questionTotalCount,
'keywords_url_count'=>$keywordUrlCount,
'keywords_arr' => $keywordArr,
'core_question_count'=>$core_question_count,
'core_keyword_url_count'=>$coreKeywordUrlCount
];
return $this->success($data);
}
/**
... ... @@ -134,7 +153,11 @@ class GeoQuestionResLogic extends BaseLogic
$list = $platformModel->list(['status'=>1],'id',['name','en_name']);
$questionResModel = new GeoQuestionLog();
foreach ($list as $item){
$data[$item['name']] = $questionResModel->counts(['project_id'=>$this->user['project_id'],'hit'=>['!=',0],'platform'=>$item['en_name']]);
if($this->user['project_id'] == 4533){
$data[$item['name']] = $questionResModel->counts(['project_id'=>$this->user['project_id'],'is_match'=>1,'hit'=>['!=',0],'platform'=>$item['en_name']]);
}else{
$data[$item['name']] = $questionResModel->counts(['project_id'=>$this->user['project_id'],'hit'=>['!=',0],'platform'=>$item['en_name']]);
}
}
return $this->success($data);
}
... ...
... ... @@ -356,7 +356,12 @@ class ProductLogic extends BaseLogic
$v['url'] = str_replace_url($v['url']);
$param['gallery'][$k] = $v;
}
$param['thumb'] = Arr::a2s($param['gallery'][0] ?? []);
$thumb = $param['gallery'][0] ?? [];
if(isset($thumb['url']) && $thumb['url']){
//生成缩略图
$thumb['url'] = thumbImageByUrl($thumb['url'],$this->user['thumb_w']??0);
}
$param['thumb'] = Arr::a2s($thumb);
$param['gallery'] = Arr::a2s($param['gallery'] ?? []);
}else{
$param['thumb'] = Arr::a2s([]);
... ...
... ... @@ -228,12 +228,12 @@ class RankDataLogic extends BaseLogic
$api_no = $project['deploy_optimize']['api_no'] ?? 0;
}
// if(!$api_no || Str::endsWith($api_no, '_bmseo')){
if(!$api_no || Str::endsWith($api_no, '_bmseo')){
$bm_api_no = RankDataBmseo::where('project_id', $project_id)->value('api_no');
if($bm_api_no){
$api_no = $bm_api_no;
}
// }
}
$domain = (!empty($project['deploy_optimize']['domain']) ? ((new DomainInfo())->getDomain($project['deploy_optimize']['domain'])) : '');
$domain_arr = parse_url($domain);
... ... @@ -555,7 +555,7 @@ class RankDataLogic extends BaseLogic
$without_extension_project_ids = [658]; //是否达标只统计主词的
$extension_project_ids = [354]; //扩展词也到达标的
$compliance_project_ids = [2163,257,823,1750,497]; //直接达标处理的
$ceaseProjectId = [354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250,2193,2399,1685];//暂停的项目
$ceaseProjectId = [354, 378, 649, 1226, 1283, 1703, 1893, 2066, 2250,2193,2399,1685, 3931];//暂停的项目
$uptimeProjectId = [1434,1812,276,2414,2974];//按上线时间统计的项目
//一个项目多个api_no
$multiple_api_no_project_ids = [
... ...
... ... @@ -322,6 +322,8 @@ class UserLoginLogic
$info['import_products_url'] = 'https://ecdn6.globalso.com/upload/p/1/file/2024-12/products.csv';
$info['import_news_url'] = 'https://ecdn6.globalso.com/upload/p/1/file/2024-12/news.csv';
$info['import_blogs_url'] = 'https://ecdn6.globalso.com/upload/p/1/file/2024-12/blogs.csv';
//缩略图宽度
$info['thumb_w'] = $project['deploy_build']['thumb_w'] ?? 0;
return $info;
}
... ...
... ... @@ -25,7 +25,7 @@ class AsideTicketListRequest extends FormRequest
{
return [
'project_id' => 'nullable|string',
'status' => 'nullable|in:0,1,2,3,9|integer',
'status' => 'nullable|in:0,1,2,3,9,10|integer',
'star' => 'nullable|in:1,2,3|integer',
'search' => 'nullable|string', // 搜索关键词
'engineer_id' => 'nullable|integer', // 工程师ID
... ...
... ... @@ -34,10 +34,8 @@ class SyncImageFileJob implements ShouldQueue
*/
public function handle()
{
$file_path = $this->getUrl($this->param['path'].'/'.$this->param['name'], 0,$this->param['location']);
$cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$this->param['path'].'" https://v6-file.globalso.com/upload.php';
echo date('Y-m-d H:i:s') . ' | ' . $cmd . PHP_EOL;
$code = shell_exec($cmd);
$code = $this->synchronizationFile($this->param['path'].'/'.$this->param['name']);
echo date('Y-m-d H:i:s') . ' | ' . $code . PHP_EOL;
if(200 != (int)$code){
$errorFileModel = new ErrorFile();
$errorFileModel->add(['path'=>$this->param['path'].'/'.$this->param['name']]);
... ... @@ -45,39 +43,12 @@ class SyncImageFileJob implements ShouldQueue
return true;
}
/**
* @remark :获取图片文件链接
* @name :getUrl
* @author :lyh
* @method :post
* @time :2024/5/22 11:53
*/
public function getUrl($path,$storage_type,$location){
if(is_array($path)){
$url =[];
foreach ($path as $v){
$url[] = $this->getUrl($v,$storage_type,$location);
}
}else{
if(empty($path)){
return '';
}
if((strpos($path,'https://')!== false) || (strpos($path,'http://') !== false)){
return $path;
}
if(substr($path,0,2) == '//'){
return 'https:'.$path;
}
if($location == 0){
$cos = config('filesystems.disks.cos');
$cosCdn = ($storage_type == 0) ? $cos['cdn'] : $cos['cdn1'];
$url = $cosCdn.$path;
}else{
$s3 = config('filesystems.disks.s3');
$cdn = $s3['cdn'];
$url = $cdn.$path;
}
}
return $url;
public function synchronizationFile($path_name){
//同步到大文件
$file_path = config('filesystems.disks.cos')['cdn1'].$path_name;
$directoryPath = pathinfo($path_name, PATHINFO_DIRNAME);
$cmd = 'curl -k -F "file_path='.$file_path.'" -F "save_path=/www/wwwroot/cos'.$directoryPath.'" https://v6-file.globalso.com/upload.php';
echo date('Y-m-d H:i:s') . ' | ' . $cmd . PHP_EOL;
return shell_exec($cmd);
}
}
... ...
... ... @@ -178,6 +178,38 @@ class Project extends Base
}
/**
* @remark :项目进度
* @name :projectProgress
* @author :lyh
* @method :post
* @time :2025/9/3 14:47
*/
public static function projectProgress($search){
$data = [
'build' => [
1 => '建立微信群',
2 => '对接资料',
3 => '确定风格',
4 => '资料上传',
5 => '页面调整',
6 => '关键词确认',
7 => '正式网站上线'
],
'optimize' => [
1 => 'SEO设置',
2 => '开始推广',
3 => '排名达标',
4 => '剩余服务时长'
]
];
if(!empty($search)){
return $data[$search];
}
return $data;
}
/**
* @remark :新增搜索
* @name :searchParam
* @author :lyh
... ...
... ... @@ -2,6 +2,7 @@
namespace App\Models\ProjectAssociation;
use App\Models\Base;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
... ... @@ -38,7 +39,7 @@ use Illuminate\Database\Eloquent\Model;
* @method Builder|ProjectAssociation whereUserName($value)
* @mixin \Eloquent
*/
class ProjectAssociation extends Model
class ProjectAssociation extends Base
{
protected $table = 'gl_project_association';
... ...