作者 赵彬吉
正在显示 41 个修改的文件 包含 1205 行增加357 行删除
... ... @@ -100,6 +100,9 @@ class AiBlogAutoPublish extends Command
//2、未达标的项目,开启AIblog, 并立即推送三篇;
//3、其他项目等下下周 1 (2025-03-17)开始推送第一篇, 之后按照正频率发送;
if (!$last_task) {
if(strpos($frequency[0],'/')){
$frequency = [1,1];//默认每天执行
}
if(!$compliance) {
for ($i = 0; $i < 3; $i++) {
$this->createTask($keywords, $project->id, $frequency);
... ... @@ -110,7 +113,18 @@ class AiBlogAutoPublish extends Command
}
}
} else {
$this->createTask($keywords, $project->id, $frequency);
if($frequency[0] == '1/2'){//一天2篇
$aiBlogTaskModel = new AiBlogTaskModel();
$frequency = explode('/', $frequency[0]);
//查询当前已发布几篇
$count = $aiBlogTaskModel->counts(['next_auto_date' => date('Y-m-d'),'project_id' => $project->id]);
while ($count < ($frequency[1] ?? 2)){
$this->createTask($keywords, $project->id, [$frequency[0],$frequency[0]]);
$count++;
}
}else{
$this->createTask($keywords, $project->id, $frequency);
}
}
}catch (\Exception $e){
(new DingService())->handle([
... ... @@ -133,7 +147,7 @@ class AiBlogAutoPublish extends Command
$result = $aiBlogService->createTask($keyword);
if ($result['status'] == 200) {
$aiBlogTaskModel = new AiBlogTaskModel();
$next_auto_date = date('Y-m-d', strtotime('+' . mt_rand($frequency[0],$frequency[1]) . 'days')); //每3-6天自动发布
$next_auto_date = date('Y-m-d', strtotime('+' . mt_rand($frequency[0] ?? 3, $frequency[1] ?? 6) . 'days')); //每3-6天自动发布
$aiBlogTaskModel->addReturnId(['project_id' => $project_id, 'type' => 2, 'task_id' => $result['data']['task_id'], 'status' => 1, 'next_auto_date' => $next_auto_date]);
ProjectServer::useProject($project_id);
$aiBlogModel = new AiBlog();
... ... @@ -141,7 +155,6 @@ class AiBlogAutoPublish extends Command
$end = strtotime('16:00:00');
$randomTimestamp = mt_rand($start, $end);
$created_at = date("Y-m-d H:i:s", $randomTimestamp);
$aiBlogModel->addReturnId(['keyword' => $keyword, 'status' => 1, 'task_id' => $result['data']['task_id'], 'project_id' => $project_id, 'created_at' => $created_at]);
DB::disconnect('custom_mysql');
$this->output("任务创建成功");
... ...
... ... @@ -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)) {
... ...
... ... @@ -241,7 +241,7 @@ class AiVideoAutoPublish extends Command
$storage = $aiVideoTaskModel->videoSetting()[$video_setting ?? 1];
$frequency = $aiVideoTaskModel->videoFrequency()[$frequency_setting ?? 1];
$frequencyArr = explode('-',$frequency);
$result = $aiVideoService->createTask($info['title'],$info['remark'],$info['images'],[],$storage);
$result = $aiVideoService->createTask($info['title'],$info['remark'],array_slice($info['images'], 0, 8),[],$storage);
if($result['status'] == 200){
$next_auto_date = date('Y-m-d', strtotime('+' . mt_rand($frequencyArr[0] ?? 5,$frequencyArr[1] ?? 7) . 'days')); //每5-7天自动发布
$aiVideoTaskModel->addReturnId(['next_auto_date'=>$next_auto_date,'task_id'=>$result['data']['task_id'],'project_id'=>$info['project_id'],'storage'=>$storage]);
... ... @@ -250,6 +250,8 @@ class AiVideoAutoPublish extends Command
$aiVideoModel->addReturnId(['title'=>$info['title'],'task_id'=>$result['data']['task_id'],'description'=>$info['remark'],'project_id'=>$info['project_id'],'images'=>json_encode($info['images'],true),'anchor'=>json_encode([],true)]);
DB::disconnect('custom_mysql');
$aiVideoAutoLogModel->edit(['status'=>2],['id'=>$info['id']]);
}else{
$aiVideoAutoLogModel->edit(['status'=>3],['id'=>$info['id']]);
}
}catch (\Exception $e){
$this->output( date('Y-m-d H:i:s').':当前数据不存在或已被删除'.$task_id);
... ...
... ... @@ -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;
}
... ... @@ -403,11 +403,18 @@ class DomainInfo extends Command
* @param $domain_id
* @param $domain
* @param $is_end
* @return bool
* @author Akun
* @date 2025/08/14 9:56
*/
public function domainChatMessage($project_id, $domain_id, $domain, $is_end)
{
//每周一推送
$week_day = date('w');
if ($week_day != 1) {
return true;
}
//项目是否有绑定群
$friend_id = ProjectAssociation::where('project_id', $project_id)
->where('status', ProjectAssociation::STATUS_NORMAL)
... ... @@ -431,6 +438,8 @@ class DomainInfo extends Command
$messagePushModel = new MessagePush();
$messagePushModel->add($param);
}
return true;
}
/**
... ... @@ -439,6 +448,12 @@ class DomainInfo extends Command
*/
public function domainChatMessageV5()
{
//每周一推送
$week_day = date('w');
if ($week_day != 1) {
return true;
}
$domain_json = @file_get_contents('https://www.quanqiusou.cn/extend_api/aicc/domain_expire_lists.php');
$domains = json_decode($domain_json, true);
if (empty($domains))
... ...
... ... @@ -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
*/
... ...
... ... @@ -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;
... ...
... ... @@ -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']),
... ...
<?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', '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;
$product->timestamps = false;
$product->thumb = Arr::a2s($thumb);
$product->save();
$this->output('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', '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;
$product->timestamps = false;
$product->thumb = Arr::a2s($thumb);
$product->save();
$this->output('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;
}
}
... ...
... ... @@ -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
... ...
... ... @@ -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(['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);
}
... ...
... ... @@ -60,7 +60,29 @@ class FetchTicketProjects extends Command
$postids = [];
while (true) {
$response = Http::get('https://www.quanqiusou.cn/extend_api/webs/globalso_all.php?page=' . $page);
try {
$maxRetries = 3;
$retryCount = 0;
while ($retryCount < $maxRetries) {
try {
$response = Http::get('https://www.quanqiusou.cn/extend_api/webs/globalso_all.php?page=' . $page);
break; // 如果请求成功,跳出重试循环
} catch (\Exception $e) {
$retryCount++;
if ($retryCount >= $maxRetries) {
// 如果达到最大重试次数,抛出异常
throw $e;
}
// 等待一段时间再重试
sleep(2);
}
}
}catch (\Exception $e){
echo now() . " | ERROR | " . $e->getMessage() . "\n" . $e->getTraceAsString() . "\n";
break;
}
if ($response->status() == 200) {
$resp_json = $response->json();
$items = $resp_json['data'] ?? [];
... ...
... ... @@ -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,93 @@ 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);
//获取与原图存储路径相同的压缩路径
$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('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);
}
}
... ...
... ... @@ -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',
... ... @@ -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'] . '}';
}
}
... ...
... ... @@ -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,11 @@ 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;
class TicketController extends BaseController
{
... ... @@ -37,7 +41,79 @@ class TicketController extends BaseController
}
/**
* @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->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->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)
{
// 完成工单,把子任务里面未完成的工单改为完成
... ...
... ... @@ -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);
}
... ...
... ... @@ -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){
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]);
$deptWeekModel = new TicketWeekDeptCount();
$deptWeekList = $deptWeekModel->list(['start_at'=>$start,'end_at'=>$end,'dept_id'=>$dept_id]);
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){
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]);
$deptWeekModel = new TicketMonthDeptCount();
$deptWeekList = $deptWeekModel->list(['start_at'=>$start,'end_at'=>$end,'dept_id'=>$dept_id]);
return $this->success(['manage'=>$manageWeekList,'dept'=>$deptWeekList]);
}
}
... ...
... ... @@ -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([]);
... ...
... ... @@ -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);
}
}
... ...
... ... @@ -79,6 +79,7 @@ class Project extends Base
3=>'2-4',
4=>'3-5',
5=>'5-7',
6=>'1/2'
];
if($val){
return $arr[$val] ?? '';
... ... @@ -177,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 => '开始推广',
2 => 'SEO设置',
3 => '排名达标',
4 => '剩余服务时常'
]
];
if(!empty($search)){
return $data[$search];
}
return $data;
}
/**
* @remark :新增搜索
* @name :searchParam
* @author :lyh
... ...
<?php
/**
* @remark :
* @name :TicketDailyDeptCount.php
* @author :lyh
* @method :post
* @time :2025/8/7 17:51
*/
namespace App\Models\Ticket;
use App\Models\Base;
/**
* @remark :工单月统计:按照技术组统计
* @name :TicketDailyDeptCount
* @author :lyh
* @method :post
* @time :2025/8/7 17:51
*/
class TicketMonthDeptCount extends Base
{
protected $table = 'gl_ticket_month_dept_count';
}
... ...
<?php
/**
* @remark :
* @name :TicketDailyManageCount.php
* @author :lyh
* @method :post
* @time :2025/8/7 17:52
*/
namespace App\Models\Ticket;
use App\Models\Base;
/**
* @remark :工单日统计:按照人员统计(月)
* @name :TicketDailyManageCount
* @author :lyh
* @method :post
* @time :2025/8/7 17:53
*/
class TicketMonthManageCount extends Base
{
protected $table = 'gl_ticket_month_manage_count';
}
... ...
<?php
/**
* @remark :
* @name :TicketDailyDeptCount.php
* @author :lyh
* @method :post
* @time :2025/8/7 17:51
*/
namespace App\Models\Ticket;
use App\Models\Base;
/**
* @remark :工单周统计:按照技术组统计
* @name :TicketDailyDeptCount
* @author :lyh
* @method :post
* @time :2025/8/7 17:51
*/
class TicketWeekDeptCount extends Base
{
protected $table = 'gl_ticket_week_dept_count';
}
... ...
<?php
/**
* @remark :
* @name :TicketDailyManageCount.php
* @author :lyh
* @method :post
* @time :2025/8/7 17:52
*/
namespace App\Models\Ticket;
use App\Models\Base;
/**
* @remark :工单日统计:按照人员统计(周)
* @name :TicketDailyManageCount
* @author :lyh
* @method :post
* @time :2025/8/7 17:53
*/
class TicketWeekManageCount extends Base
{
protected $table = 'gl_ticket_week_manage_count';
}
... ...
... ... @@ -9,6 +9,8 @@
namespace App\Services\Geo;
use Illuminate\Support\Facades\Http;
class GeoService
{
public $api_key = 'UkzZljFv83Z2qBi5YR1o3f2otAVWtug6';
... ... @@ -40,7 +42,7 @@ class GeoService
'platform' => $platform,
'security_check' => true
];
$data = http_post($url,json_encode($message,true),$header);
$data = http_post($url,json_encode($message,true),$header,true,180);
return $data;
}
... ... @@ -108,4 +110,31 @@ class GeoService
$data = http_post($url,json_encode($message,true),$header);
return $data;
}
/**
* 获取语句余弦相似度
* $text 会被拆解语句, 分析预警传$text
* @param string $standard 标准答案
* @param string $text 需要分析的语句
* @param string $embedding_model
* @param string $similarity_method
* @return \Illuminate\Http\Client\Response
*/
public function cosineSimilarity($standard, $text, $embedding_model = 'text-embedding-3-small', $similarity_method = 'cosine')
{
$url = 'http://knowledge_base.zabbix.waimaoq.com/v1/crud/split_similarity';
$header = [
'accept: application/json',
'Content-Type: application/json'
];
$param = [
'text1' => $standard,
'text2' => $text,
'embedding_model' => $embedding_model,
'similarity_method' => $similarity_method
];
$result = Http::post($url, $param);
return $result->json();
}
}
... ...
... ... @@ -103,9 +103,10 @@ return [
],
//域名解析别处记录日志
'analyze_other' => [
'driver' => 'custom',
'via' => \App\Factory\LogFormatterFactory::class,
'prefix' => 'analyze_other',
'driver' => 'daily',
'path' => storage_path('logs/analyze_other/laravel.log'),
'level' => 'debug',
'days' => 14,
],
'stack' => [
'driver' => 'stack',
... ... @@ -203,6 +204,12 @@ return [
'level' => 'debug',
'days' => 30,
],
'thumb_img' => [
'driver' => 'daily',
'path' => storage_path('logs/thumb_img/laravel.log'),
'level' => 'debug',
'days' => 14,
],
],
//操作日志
'operator_log' =>[
... ...
... ... @@ -66,6 +66,7 @@ Route::any('get_monitor_keyword', [\App\Http\Controllers\Api\PrivateController::
Route::post('selfSiteApi', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteApi']);
Route::post('selfSiteNotify', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteNotify']);
Route::post('selfSiteVerify', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteVerify']);
Route::post('selfSiteSsl', [\App\Http\Controllers\Api\SelfSiteController::class, 'selfSiteSsl']);
//创建301跳转任务
Route::any('/addRedirect',[\App\Http\Controllers\Api\NoticeController::class,'addRedirect']);
... ...
... ... @@ -253,6 +253,7 @@ Route::middleware(['aloginauth'])->group(function () {
// 售后工单改版
Route::prefix('tickets')->group(function () {
Route::get('/', [Aside\WorkOrder\AsideTicketController::class, 'index'])->name('admin.tickets.index')->summary('A端工单列表');
Route::post('/lists', [Aside\WorkOrder\AsideTicketController::class, 'lists'])->name('admin.tickets.lists')->summary('A端工单列表2');
Route::post('/', [Aside\WorkOrder\AsideTicketController::class, 'store'])->name('admin.tickets.store')->summary('A端创建工单');
Route::get('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'show'])->name('admin.tickets.show')->summary('A端工单详情');
Route::post('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'update'])->name('admin.tickets.update')->summary('A端更新工单,审核,邀请同事');
... ... @@ -636,6 +637,10 @@ Route::middleware(['aloginauth'])->group(function () {
//ticket
Route::prefix('ticket_count')->group(function () {
Route::any('/ticketCount', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'ticketCount'])->name('ticket_count_ticketCount');
Route::any('/getMonthList', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'getMonthList'])->name('ticket_count_getMonthList');//获取最近一个总统计的数据
Route::any('/getTime', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'getTime'])->name('ticket_count_getTime');//获取周/月时间
Route::any('/weekManageList', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'weekManageList'])->name('ticket_count_weekManageList');//周统计数据
Route::any('/monthManageList', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'monthManageList'])->name('ticket_count_monthManageList');//月统计数据
Route::any('/manageTicketCount', [\App\Http\Controllers\Aside\Ticket\TicketController::class,'manageTicketCount'])->name('ticket_count_manageTicketCount');
});
});
... ...