作者 lyh

Merge branch 'master' of http://47.244.231.31:8099/zhl/globalso-v6 into lyh-server

  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2025/7/4
  6 + * Time: 11:14
  7 + */
  8 +namespace App\Console\Commands\Statistics;
  9 +
  10 +use App\Models\Project\ProjectFlow;
  11 +use App\Services\UpyunService;
  12 +use Illuminate\Console\Command;
  13 +use Illuminate\Support\Str;
  14 +
  15 +class Flow extends Command
  16 +{
  17 + /**
  18 + * The name and signature of the console command.
  19 + *
  20 + * @var string
  21 + */
  22 + protected $signature = 'project_flow_statistics';
  23 +
  24 + /**
  25 + * The console command description.
  26 + *
  27 + * @var string
  28 + */
  29 + protected $description = '项目流量统计';
  30 +
  31 + /**
  32 + * Create a new command instance.
  33 + *
  34 + * @return void
  35 + */
  36 + public function __construct()
  37 + {
  38 + parent::__construct(); // 确保调用父类构造函数
  39 + }
  40 +
  41 + public function handle()
  42 + {
  43 + $this->cdnStatistics();
  44 + return true;
  45 + }
  46 +
  47 + public function cdnStatistics()
  48 + {
  49 + $class = new UpyunService();
  50 +
  51 + list($start_at, $end_at) = $this->getTime();
  52 + $date = date('Y-m-d', strtotime($end_at));
  53 + echo 'start_at: ' . $start_at . PHP_EOL;
  54 + echo 'end_at: ' . $end_at . PHP_EOL;
  55 + $result = $class->realTimeStatistics($start_at, $end_at);
  56 +
  57 + file_put_contents(storage_path('logs/flow/' . date('YmdHis', strtotime($start_at)) . '.json'), $result);
  58 +// $result = file_get_contents(storage_path('logs/flow/' . date('YmdHis', strtotime($start_at)) . '.json'));
  59 + $result = json_decode($result, true);
  60 + $flow = [];
  61 + if (FALSE == empty($result['data']) && is_array($result['data'])) {
  62 + // 结算 所有项目 流量
  63 + foreach ($result['data'] as $item) {
  64 + if (Str::startsWith($item['key'], '/upload/p/')) {
  65 + $tmp = explode('/', $item['key']);
  66 + $flow[$tmp[3]] = FALSE == empty($flow[$tmp[3]]) ? $flow[$tmp[3]] + $item['val'] : $item['val'];
  67 + }
  68 + }
  69 + }
  70 +
  71 + ksort($flow);
  72 + $total_flow = 0;
  73 + foreach ($flow as $project_id=>$val) {
  74 + ProjectFlow::flowInsert($project_id, $date, $val, $end_at);
  75 + $total_flow += $val;
  76 + }
  77 + echo 'total project: ' . count($flow) . PHP_EOL;
  78 + echo 'total flow: ' . $total_flow . PHP_EOL;
  79 + return true;
  80 + }
  81 +
  82 + /**
  83 + * @return array
  84 + */
  85 + public function getTime()
  86 + {
  87 + $last_at_log = ProjectFlow::orderBy('last_at', 'desc')->first();
  88 + $today = date('Y-m-d 00:00:00');
  89 + $start_at = $last_at_log ? $last_at_log->last_at : $today;
  90 + if (strtotime($start_at) < strtotime($today))
  91 + $start_at = $today;
  92 + $end_at = date('Y-m-d H:i:s', time() - 1);
  93 + return [$start_at, $end_at];
  94 + }
  95 +}
@@ -5,9 +5,11 @@ namespace App\Console\Commands\WorkOrder; @@ -5,9 +5,11 @@ namespace App\Console\Commands\WorkOrder;
5 use App\Models\Manage\Manage; 5 use App\Models\Manage\Manage;
6 use App\Models\Manage\ManageHr; 6 use App\Models\Manage\ManageHr;
7 use App\Models\Project\Project; 7 use App\Models\Project\Project;
  8 +use App\Models\ProjectAssociation\ProjectAssociation;
8 use App\Models\WorkOrder\TicketProject; 9 use App\Models\WorkOrder\TicketProject;
9 use Illuminate\Console\Command; 10 use Illuminate\Console\Command;
10 use Illuminate\Support\Facades\Http; 11 use Illuminate\Support\Facades\Http;
  12 +use Illuminate\Support\Str;
11 13
12 class FetchTicketProjects extends Command 14 class FetchTicketProjects extends Command
13 { 15 {
@@ -83,6 +85,7 @@ class FetchTicketProjects extends Command @@ -83,6 +85,7 @@ class FetchTicketProjects extends Command
83 'test_website' => $item['test_url'] ?? '', 85 'test_website' => $item['test_url'] ?? '',
84 'is_del' => 0, 86 'is_del' => 0,
85 'plan' => $item['plan'] ?? '', 87 'plan' => $item['plan'] ?? '',
  88 + 'project_cate' => 1,
86 ]; 89 ];
87 if (!$project) { 90 if (!$project) {
88 $new = new TicketProject(); 91 $new = new TicketProject();
@@ -177,6 +180,11 @@ class FetchTicketProjects extends Command @@ -177,6 +180,11 @@ class FetchTicketProjects extends Command
177 'test_website' => $item->deploy_build->test_domain ?? '', 180 'test_website' => $item->deploy_build->test_domain ?? '',
178 'version' => empty($item->version) ? 7 : $item->version, // 版本号 181 'version' => empty($item->version) ? 7 : $item->version, // 版本号
179 'plan' => $item->planMap()[$item->deploy_build->plan] ?? '', 182 'plan' => $item->planMap()[$item->deploy_build->plan] ?? '',
  183 + 'project_cate' => 2,
  184 + 'wechat_group_id' => ProjectAssociation::where('project_id', $project->table_id)
  185 + ->where('status', ProjectAssociation::STATUS_NORMAL)
  186 + ->where('binding_app', ProjectAssociation::ENTERPRISE_WECHAT)
  187 + ->value('friend_id')
180 ]; 188 ];
181 if (!$project) { 189 if (!$project) {
182 $project = new TicketProject(); 190 $project = new TicketProject();
@@ -209,6 +217,97 @@ class FetchTicketProjects extends Command @@ -209,6 +217,97 @@ class FetchTicketProjects extends Command
209 } 217 }
210 } 218 }
211 219
  220 + public function fetchAICC()
  221 + {
  222 + $lastid = 0;
  223 + while (true) {
  224 + try {
  225 + $response = Http::withBasicAuth('bill', 'bill@ai.cc')
  226 + ->get('https://fob.ai.cc/api/tickets/projects', [
  227 + 'lastid' => $lastid,
  228 + ]);
  229 + $items = $response->json();
  230 + if (empty($items))
  231 + {
  232 + echo now() . " | INFO | not found items \n";
  233 + break;
  234 + }
  235 +
  236 + foreach ($items as $item) {
  237 + $uuid = md5("AICC{$item['id']}");
  238 + $project = TicketProject::where('uuid', $uuid)->first();
  239 + // 判断套餐是超迹还是域途, 如果 $item['plans'][0]['name'] 包含 '超迹' 则为超迹,否则为域途
  240 + $project_cate = Str::contains($item['plans'][0]['name'], '超迹') ? 3 : 4;
  241 + print_r($item['cj_assm']);
  242 + print_r($item['yutu_assm']);
  243 + if ($project_cate == 3)
  244 + {
  245 + // 售后服务经理
  246 + $assm_id = collect([
  247 + ManageHr::where('name', $item['cj_assm']['real_name'] ?? '')->first()->manage_id ?? 0,
  248 + 20, //徐莹
  249 + ])->first(fn($v) => $v !== null && $v !== 0, 0);
  250 + }else
  251 + {
  252 + // 域途
  253 + $assm_id = collect([
  254 + ManageHr::where('name', $item['yutu_assm']['real_name'] ?? '')->first()->manage_id ?? 0,
  255 + 85, //黄小玉
  256 + ])->first(fn($v) => $v !== null && $v !== 0, 0);
  257 + }
  258 +
  259 + // 优化师
  260 + $seom_id = 0;
  261 + // 第一负责人
  262 + $engineer_id = $assm_id;
  263 + $is_del = 0;
  264 +
  265 + $fields = [
  266 + 'company_name' => $item['company'],
  267 + 'title' => $item['company'] . " - " . $item['plan'],
  268 + 'assm_id' => $assm_id,
  269 + 'seom_id' => $seom_id,
  270 + 'engineer_id' => $engineer_id,
  271 + 'is_del' => $is_del,
  272 + 'website' => '',
  273 + 'test_website' => '',
  274 + 'version' => 1, // 版本号
  275 + 'plan' => $item['plans'][0]['name'] ?? '',
  276 + 'project_cate' => $project_cate,
  277 + 'wechat_group_id' => $item['chatroom'],
  278 + ];
  279 +
  280 + if (!$project) {
  281 + $project = new TicketProject();
  282 + $project->uuid = $uuid;
  283 + $project->post_id = $item['postid'];
  284 + $project->table_id = $item['id'];
  285 + foreach ($fields as $k => $v) {
  286 + $project->$k = $v;
  287 + }
  288 + $project->save();
  289 + } else {
  290 + $changed = false;
  291 + foreach ($fields as $k => $v) {
  292 + if ($project->$k != $v) {
  293 + $project->$k = $v;
  294 + $changed = true;
  295 + }
  296 + }
  297 + if ($changed) {
  298 + $project->save();
  299 + }
  300 + }
  301 + $lastid = $item['id'];
  302 + echo now() . " | INFO | AICC: {$item['id']} {$item['company']} fetch ok \n";
  303 + }
  304 + }catch (\Exception $exception){
  305 + echo now() . " | ERROR | " . $exception->getMessage() . "\n" . $exception->getTraceAsString() . "\n";
  306 + break;
  307 + }
  308 + }
  309 + }
  310 +
212 public function fetch_uuid() 311 public function fetch_uuid()
213 { 312 {
214 $lastid = 0; 313 $lastid = 0;
@@ -8,8 +8,10 @@ use App\Http\Requests\Api\WorkOrder\TicketStoreRequest; @@ -8,8 +8,10 @@ use App\Http\Requests\Api\WorkOrder\TicketStoreRequest;
8 use App\Models\WorkOrder\TicketLog; 8 use App\Models\WorkOrder\TicketLog;
9 use App\Models\WorkOrder\TicketProject; 9 use App\Models\WorkOrder\TicketProject;
10 use App\Models\WorkOrder\Tickets; 10 use App\Models\WorkOrder\Tickets;
  11 +use Darabonba\GatewaySpi\Models\InterceptorContext\response;
11 use Illuminate\Http\Request; 12 use Illuminate\Http\Request;
12 use Illuminate\Support\Facades\DB; 13 use Illuminate\Support\Facades\DB;
  14 +use Illuminate\Support\Facades\Http;
13 15
14 class TicketController extends BaseController 16 class TicketController extends BaseController
15 { 17 {
@@ -86,6 +88,7 @@ class TicketController extends BaseController @@ -86,6 +88,7 @@ class TicketController extends BaseController
86 $log = new TicketLog(); 88 $log = new TicketLog();
87 $log->engineer_id = $project->engineer_id; // 默认第一负责人 89 $log->engineer_id = $project->engineer_id; // 默认第一负责人
88 $ticket->logs()->save($log); 90 $ticket->logs()->save($log);
  91 + $project->pushWechatGroupMsg("客户新增了工单(ID:{$ticket->id}),请及时处理!");
89 return $ticket; 92 return $ticket;
90 }); 93 });
91 return response()->json(['data' => $result]); 94 return response()->json(['data' => $result]);
@@ -149,4 +152,36 @@ class TicketController extends BaseController @@ -149,4 +152,36 @@ class TicketController extends BaseController
149 if (!$project) return $this->response('未找到项目', 404); 152 if (!$project) return $this->response('未找到项目', 404);
150 return response()->json(['data' => $project]); 153 return response()->json(['data' => $project]);
151 } 154 }
  155 +
  156 + /**
  157 + * @param $friend_id
  158 + * @return void
  159 + * 企微群里@小超或艾丝,触发推送工单
  160 + * 接收群ID
  161 + */
  162 + public function pushTicketByBot($friend_id)
  163 + {
  164 + $project = TicketProject::where('wechat_group_id', $friend_id)->where('is_del', 0)->first();
  165 + if (!$project)
  166 + return response()->json(['message' => '未找到对应的工单项目'], 404);
  167 +
  168 +// $url = in_array($project->project_cate, [3,4]) ? 'https://hub.ai.cc/api/fob_ai_customer_service/push_message' : 'https://hub.ai.cc/api/globalso_ai_customer_service/send_msg';
  169 +// $response = Http::post($url, [
  170 +// 'type' => 'Link',
  171 +// 'friend_id' => $friend_id,
  172 +// 'content' => json_encode([
  173 +// 'title' => 'AI协同工单 - ' . $project->company_name,
  174 +// 'desc' => "您好,我们同事没有及时回复,你可以查看工单进度!",
  175 +// 'size' => 0,
  176 +// 'thumbSize' => 0,
  177 +// 'thumbUrl' => 'https://hub.globalso.com/logocm.png',
  178 +// 'url' => 'https://oa.quanqiusou.cn/afterorder?project_id='.$project->uuid
  179 +// ], JSON_UNESCAPED_UNICODE)
  180 +// ]);
  181 +// // 返回 $response 的相应内容以及网络状态码
  182 +// return response($response->body(), $response->status());
  183 +
  184 + $project->pushWechatGroupMsg("您好,我们同事没有及时回复,你可以查看工单进度!");
  185 + return response()->json(['message' => '工单推送成功']);
  186 + }
152 } 187 }
@@ -13,6 +13,7 @@ use App\Enums\Common\Code; @@ -13,6 +13,7 @@ use App\Enums\Common\Code;
13 use App\Http\Controllers\Aside\BaseController; 13 use App\Http\Controllers\Aside\BaseController;
14 use App\Models\Domain\DomainInfo; 14 use App\Models\Domain\DomainInfo;
15 use App\Models\Project\CountAllProject; 15 use App\Models\Project\CountAllProject;
  16 +use Illuminate\Support\Facades\DB;
16 17
17 /** 18 /**
18 * @remark :统计所有项目(4.0,5.0,6.0) 19 * @remark :统计所有项目(4.0,5.0,6.0)
@@ -46,6 +47,27 @@ class AllProjectController extends BaseController @@ -46,6 +47,27 @@ class AllProjectController extends BaseController
46 $this->map['company'] = ['like','%'.$this->map['company'].'%']; 47 $this->map['company'] = ['like','%'.$this->map['company'].'%'];
47 } 48 }
48 $data = $allProject->lists($this->map,$this->page,$this->row); 49 $data = $allProject->lists($this->map,$this->page,$this->row);
  50 +
  51 + if (!empty($data['list'])) {
  52 + foreach ($data['list'] as $key => $value) {
  53 + $ticketProject = null;
  54 + if ($value['version'] == 1) {
  55 + // version 为 1:6.0
  56 + $ticketProject = DB::table('gl_ticket_projects')
  57 + ->where('table_id', $value['project_id'])
  58 + ->where('project_cate', 2)
  59 + ->first();
  60 + } else {
  61 + // version 不为 1
  62 + $ticketProject = DB::table('gl_ticket_projects')
  63 + ->where('post_id', $value['project_id'])
  64 + ->where('project_cate', 1)
  65 + ->first();
  66 + }
  67 + $data['list'][$key]['uuid'] = $ticketProject ? $ticketProject->uuid : null;
  68 + }
  69 + }
  70 +
49 $this->response('success',Code::SUCCESS,$data); 71 $this->response('success',Code::SUCCESS,$data);
50 } 72 }
51 } 73 }
@@ -37,6 +37,7 @@ use App\Models\RankData\RankData; @@ -37,6 +37,7 @@ use App\Models\RankData\RankData;
37 use App\Models\Task\Task; 37 use App\Models\Task\Task;
38 use App\Models\WebSetting\WebLanguage; 38 use App\Models\WebSetting\WebLanguage;
39 use Illuminate\Http\Request; 39 use Illuminate\Http\Request;
  40 +use Illuminate\Support\Facades\DB;
40 41
41 /** 42 /**
42 * 项目管理 43 * 项目管理
@@ -69,6 +70,16 @@ class ProjectController extends BaseController @@ -69,6 +70,16 @@ class ProjectController extends BaseController
69 if(!empty($lists) && !empty($lists['list'])){ 70 if(!empty($lists) && !empty($lists['list'])){
70 foreach ($lists['list'] as $k => $v){ 71 foreach ($lists['list'] as $k => $v){
71 $v = $this->handleParam($v); 72 $v = $this->handleParam($v);
  73 +
  74 + // 组装 工单UUID
  75 + $ticketProject = null;
  76 + $ticketProject = DB::table('gl_ticket_projects')
  77 + ->where('table_id', $v['id'])
  78 + ->where('project_cate', 2)
  79 + ->first();
  80 + $v['uuid'] = $ticketProject ? $ticketProject->uuid : null;
  81 + // 组装 工单UUID END
  82 +
72 $lists['list'][$k] = $v; 83 $lists['list'][$k] = $v;
73 } 84 }
74 } 85 }
@@ -8,13 +8,13 @@ use App\Http\Requests\Aside\WorkOrder\AsideTicketStoreRequest; @@ -8,13 +8,13 @@ use App\Http\Requests\Aside\WorkOrder\AsideTicketStoreRequest;
8 use App\Http\Requests\Aside\WorkOrder\AsideTicketListRequest; 8 use App\Http\Requests\Aside\WorkOrder\AsideTicketListRequest;
9 use App\Http\Requests\Aside\WorkOrder\AsideTicketUpdateRequest; 9 use App\Http\Requests\Aside\WorkOrder\AsideTicketUpdateRequest;
10 use App\Http\Requests\Aside\WorkOrder\TicketProjectListRequest; 10 use App\Http\Requests\Aside\WorkOrder\TicketProjectListRequest;
11 -use App\Models\ProjectAssociation\ProjectAssociation;  
12 use App\Models\Workchat\MessagePush; 11 use App\Models\Workchat\MessagePush;
13 use App\Models\WorkOrder\TicketLog; 12 use App\Models\WorkOrder\TicketLog;
14 use App\Models\WorkOrder\TicketProject; 13 use App\Models\WorkOrder\TicketProject;
15 use App\Models\WorkOrder\Tickets; 14 use App\Models\WorkOrder\Tickets;
16 use Illuminate\Support\Facades\DB; 15 use Illuminate\Support\Facades\DB;
17 16
  17 +
18 class AsideTicketController extends BaseController 18 class AsideTicketController extends BaseController
19 { 19 {
20 /** 20 /**
@@ -106,6 +106,11 @@ class AsideTicketController extends BaseController @@ -106,6 +106,11 @@ class AsideTicketController extends BaseController
106 $version = $validated['version']; 106 $version = $validated['version'];
107 return $query->where('version', $version); 107 return $query->where('version', $version);
108 }) 108 })
  109 + ->when(!empty($validated['project_cate']), function ($query) use ($validated) {
  110 + // 版本号筛选
  111 + $project_cate = $validated['project_cate'];
  112 + return $query->where('project_cate', $project_cate);
  113 + })
109 ->paginate($this->row, ['*'], 'page', $this->page); 114 ->paginate($this->row, ['*'], 'page', $this->page);
110 $this->response('success', Code::SUCCESS, $lists); 115 $this->response('success', Code::SUCCESS, $lists);
111 } 116 }
@@ -143,6 +148,7 @@ class AsideTicketController extends BaseController @@ -143,6 +148,7 @@ class AsideTicketController extends BaseController
143 $log->engineer_id = $engineer_id; 148 $log->engineer_id = $engineer_id;
144 $ticket->logs()->save($log); 149 $ticket->logs()->save($log);
145 } 150 }
  151 + $project->pushWechatGroupMsg("创贸({$ticket->submit_username})新增了工单(ID:{$ticket->id}),请及时处理!");
146 return $ticket; 152 return $ticket;
147 }); 153 });
148 $this->response('success', Code::SUCCESS, $result->toArray()); 154 $this->response('success', Code::SUCCESS, $result->toArray());
@@ -232,34 +238,11 @@ class AsideTicketController extends BaseController @@ -232,34 +238,11 @@ class AsideTicketController extends BaseController
232 if (empty($project)) 238 if (empty($project))
233 $this->response('工单项目不存在', Code::USER_MODEL_NOTFOUND_ERROE); 239 $this->response('工单项目不存在', Code::USER_MODEL_NOTFOUND_ERROE);
234 240
235 - if (empty($project->association)) { 241 + if (empty($project->wechat_group_id)) {
236 $this->response('该工单没有绑定的企微群', Code::USER_MODEL_NOTFOUND_ERROE); 242 $this->response('该工单没有绑定的企微群', Code::USER_MODEL_NOTFOUND_ERROE);
237 } 243 }
238 -  
239 - $ticket = Tickets::where('project_id', $project->id)  
240 - ->orderBy('id', 'desc')  
241 - ->first();  
242 -  
243 - $message_push = new MessagePush();  
244 - $message_push->project_id = $project->table_id;  
245 - $message_push->friend_id = $project->association->friend_id;  
246 - $message_push->content_type = 'Link';  
247 - $message_push->content = json_encode([  
248 - 'title' => '工单查看 - ' . $project->company_name,  
249 - 'desc' => $ticket ? $ticket->title : "工单列表",  
250 - 'size' => 0,  
251 - 'thumbSize' => 0,  
252 - 'thumbUrl' => 'https://oa.quanqiusou.cn/logo.ico',  
253 - 'url' => 'https://oa.quanqiusou.cn/afterorder?project_id='.$project->uuid  
254 - ], JSON_UNESCAPED_UNICODE);  
255 - $message_push->send_time = now();  
256 - $message_push->type = MessagePush::TYPE_TICKET;  
257 - $message_push->save();  
258 -  
259 - if (!empty($ticket)) {  
260 - $ticket->ding = 1; // 标记为已推送  
261 - $ticket->save();  
262 - } 244 + $project->pushWechatGroupMsg();
263 $this->response('success', Code::SUCCESS); 245 $this->response('success', Code::SUCCESS);
264 } 246 }
  247 +
265 } 248 }
@@ -87,6 +87,8 @@ class AsideTicketLogController extends BaseController @@ -87,6 +87,8 @@ class AsideTicketLogController extends BaseController
87 $ticket->status = Tickets::STATUS_COMPLETED; 87 $ticket->status = Tickets::STATUS_COMPLETED;
88 // 如果所有子任务都完成了,则将工单状态改为已完成 88 // 如果所有子任务都完成了,则将工单状态改为已完成
89 $ticket->end_at = now(); 89 $ticket->end_at = now();
  90 + $project = $ticket->project;
  91 + $project->pushWechatGroupMsg("工单(ID:{$ticket->id})已全部完成,请访问查看详情!");
90 } 92 }
91 $ticket->save(); 93 $ticket->save();
92 return $log; 94 return $log;
@@ -62,6 +62,8 @@ class TicketChatController extends BaseController @@ -62,6 +62,8 @@ class TicketChatController extends BaseController
62 $chat->submit_side = 1; 62 $chat->submit_side = 1;
63 $chat->manage_id = $this->manage['id']; 63 $chat->manage_id = $this->manage['id'];
64 $chat->save(); 64 $chat->save();
  65 + $project = $ticket->project;
  66 + $project->pushWechatGroupMsg("{$chat->submit_username}对工单(ID:{$ticket->id})进行了补充,请及时查看处理!");
65 $this->response('success', Code::SUCCESS, $chat); 67 $this->response('success', Code::SUCCESS, $chat);
66 } 68 }
67 69
@@ -25,7 +25,8 @@ class TicketProjectListRequest extends FormRequest @@ -25,7 +25,8 @@ class TicketProjectListRequest extends FormRequest
25 { 25 {
26 return [ 26 return [
27 'search' => 'nullable|string', // 搜索关键词 27 'search' => 'nullable|string', // 搜索关键词
28 - 'version' => 'nullable|in:5,6,7', // 版本号 28 + 'project_cate' => 'nullable|in:1,2,3,4', // 项目分类:1V5,2V6,3超迹,4域途
  29 + 'version' => 'nullable|integer', // 版本号
29 ]; 30 ];
30 } 31 }
31 } 32 }
@@ -14,4 +14,5 @@ use App\Models\Base; @@ -14,4 +14,5 @@ use App\Models\Base;
14 class CountAllProject extends Base 14 class CountAllProject extends Base
15 { 15 {
16 protected $table = 'gl_all_project'; 16 protected $table = 'gl_all_project';
  17 +
17 } 18 }
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: zhl
  5 + * Date: 2025/7/4
  6 + * Time: 15:05
  7 + */
  8 +namespace App\Models\Project;
  9 +
  10 +use App\Models\Base;
  11 +
  12 +/**
  13 + * 流量统计
  14 + * Class ProjectFlow
  15 + * @package App\Models\Project
  16 + */
  17 +class ProjectFlow extends Base
  18 +{
  19 + /**
  20 + * 表名
  21 + * @var string
  22 + */
  23 + protected $table = 'gl_project_flow';
  24 +
  25 + /**
  26 + * 流量日志记录
  27 + * @param $project_id
  28 + * @param $date
  29 + * @param $cdn_flow
  30 + * @param $last_at
  31 + * @return ProjectFlow
  32 + */
  33 + public static function flowInsert($project_id, $date, $cdn_flow, $last_at)
  34 + {
  35 + $flow = self::where(['project_id' => $project_id, 'date' => $date])->first();
  36 + if (empty($flow)) {
  37 + $flow = new self();
  38 + $flow->project_id = $project_id;
  39 + $flow->date = $date;
  40 + $flow->cdn_flow = $cdn_flow;
  41 + } else {
  42 + $flow->cdn_flow = $flow->cdn_flow + $cdn_flow;
  43 + }
  44 + $flow->last_at = $last_at;
  45 + $flow->save();
  46 + return $flow;
  47 + }
  48 +}
@@ -6,6 +6,7 @@ use App\Models\Base; @@ -6,6 +6,7 @@ use App\Models\Base;
6 use App\Models\Manage\Manage; 6 use App\Models\Manage\Manage;
7 use App\Models\Project\Project; 7 use App\Models\Project\Project;
8 use App\Models\ProjectAssociation\ProjectAssociation; 8 use App\Models\ProjectAssociation\ProjectAssociation;
  9 +use App\Models\Workchat\MessagePush;
9 use Illuminate\Database\Eloquent\Factories\HasFactory; 10 use Illuminate\Database\Eloquent\Factories\HasFactory;
10 11
11 class TicketProject extends Base 12 class TicketProject extends Base
@@ -53,4 +54,31 @@ class TicketProject extends Base @@ -53,4 +54,31 @@ class TicketProject extends Base
53 ->where('binding_app', ProjectAssociation::ENTERPRISE_WECHAT) 54 ->where('binding_app', ProjectAssociation::ENTERPRISE_WECHAT)
54 ->select(['id', 'project_id', 'friend_id', 'binding_app']); 55 ->select(['id', 'project_id', 'friend_id', 'binding_app']);
55 } 56 }
  57 +
  58 +
  59 + /**
  60 + * @return void
  61 + * 企微群推送工单消息
  62 + */
  63 + public function pushWechatGroupMsg($desc="可提交新的工单、查询工单进度、AI会同步通知售后人员!")
  64 + {
  65 + if (!empty($this->wechat_group_id))
  66 + {
  67 + $message_push = new MessagePush();
  68 + $message_push->project_id = $this->table_id;
  69 + $message_push->friend_id = $this->wechat_group_id;
  70 + $message_push->content_type = 'Link';
  71 + $message_push->content = json_encode([
  72 + 'title' => "AI协同工单 - " . $this->company_name,
  73 + 'desc' => $desc,
  74 + 'size' => 0,
  75 + 'thumbSize' => 0,
  76 + 'thumbUrl' => 'https://hub.globalso.com/logocm.png',
  77 + 'url' => 'https://oa.quanqiusou.cn/afterorder?project_id='.$this->uuid
  78 + ], JSON_UNESCAPED_UNICODE);
  79 + $message_push->send_time = now();
  80 + $message_push->type = MessagePush::TYPE_TICKET;
  81 + $message_push->save();
  82 + }
  83 + }
56 } 84 }
@@ -168,7 +168,7 @@ class ProjectAssociationServices extends BaseService @@ -168,7 +168,7 @@ class ProjectAssociationServices extends BaseService
168 } 168 }
169 $param['sign'] = $this->getSign($param); 169 $param['sign'] = $this->getSign($param);
170 $url = 'https://hub.ai.cc/api/globalso_ai_customer_service/chatroom_list'; 170 $url = 'https://hub.ai.cc/api/globalso_ai_customer_service/chatroom_list';
171 - $result = Http::withoutVerifying()->post($url, $param)->json(); 171 + $result = Http::withoutVerifying()->withOptions(['proxy' => env('CURL_PROXY')])->post($url, $param)->json();
172 if(empty($result) || $result['status'] != 200){ 172 if(empty($result) || $result['status'] != 200){
173 return []; 173 return [];
174 } 174 }
@@ -189,7 +189,7 @@ class ProjectAssociationServices extends BaseService @@ -189,7 +189,7 @@ class ProjectAssociationServices extends BaseService
189 ]; 189 ];
190 $param['sign'] = $this->getSign($param); 190 $param['sign'] = $this->getSign($param);
191 $url = 'https://hub.ai.cc/api/globalso_ai_customer_service/send_msg'; 191 $url = 'https://hub.ai.cc/api/globalso_ai_customer_service/send_msg';
192 - $result = Http::withoutVerifying()->timeout(30)->post($url, $param)->json(); 192 + $result = Http::withoutVerifying()->withOptions(['proxy' => env('CURL_PROXY')])->timeout(30)->post($url, $param)->json();
193 if(empty($result) || $result['status'] != 200){ 193 if(empty($result) || $result['status'] != 200){
194 throw new \Exception($result['message'] ?? ''); 194 throw new \Exception($result['message'] ?? '');
195 } 195 }
@@ -67,6 +67,47 @@ class UpyunService @@ -67,6 +67,47 @@ class UpyunService
67 } 67 }
68 68
69 /** 69 /**
  70 + * 统计流量
  71 + * @param $start_time
  72 + * @param $end_time
  73 + * @param string $domain
  74 + * @return mixed
  75 + */
  76 + public function commonData($start_time, $end_time, $domain = 'ecdn6.globalso.com')
  77 + {
  78 + $action = '/flow/common_data';
  79 + $param = [
  80 + 'start_time' => $start_time,
  81 + 'end_time' => $end_time,
  82 + 'domain' => $domain,
  83 + ];
  84 +// dd($param);
  85 + list($status, $result) = $this->curlRequest($action, $param, 'GET', $this->getHeader());
  86 + return $result;
  87 + }
  88 +
  89 + /**
  90 + * 统计流量
  91 + * @param $start_time
  92 + * @param $end_time
  93 + * @param string $domain
  94 + * @return mixed
  95 + */
  96 + public function realTimeStatistics($start_time, $end_time, $domain = 'ecdn6.globalso.com')
  97 + {
  98 + $action = '/flow/real_time_statistics';
  99 + $param = [
  100 + 'start_time' => $start_time,
  101 + 'end_time' => $end_time,
  102 + 'query_domain' => $domain,
  103 + 'query_type' => 'uri_flux'
  104 + ];
  105 +// dd($param);
  106 + list($status, $result) = $this->curlRequest($action, $param, 'GET', $this->getHeader());
  107 + return $result;
  108 + }
  109 +
  110 + /**
70 * 头信息需要携带授权token 111 * 头信息需要携带授权token
71 * @return array 112 * @return array
72 */ 113 */
@@ -88,6 +129,9 @@ class UpyunService @@ -88,6 +129,9 @@ class UpyunService
88 public function curlRequest($url, $data, $method = 'POST', $header = [], $time_out = 60) 129 public function curlRequest($url, $data, $method = 'POST', $header = [], $time_out = 60)
89 { 130 {
90 $url = config('custom.upyun.api_url') . $url; 131 $url = config('custom.upyun.api_url') . $url;
  132 + if ($method == 'GET') {
  133 + $url .= '?' . http_build_query($data);
  134 + }
91 $ch = curl_init(); 135 $ch = curl_init();
92 curl_setopt($ch, CURLOPT_TIMEOUT, $time_out); 136 curl_setopt($ch, CURLOPT_TIMEOUT, $time_out);
93 curl_setopt($ch, CURLOPT_URL, $url); 137 curl_setopt($ch, CURLOPT_URL, $url);
@@ -86,3 +86,4 @@ Route::prefix('tickets')->group(function () { @@ -86,3 +86,4 @@ Route::prefix('tickets')->group(function () {
86 Route::get('/chat/{project_id}/{ticket_id}', [\App\Http\Controllers\Api\WorkOrder\TicketChatController::class, 'index'])->summary('B端,渠道-工单聊天记录')->name('tickets.chat.index'); 86 Route::get('/chat/{project_id}/{ticket_id}', [\App\Http\Controllers\Api\WorkOrder\TicketChatController::class, 'index'])->summary('B端,渠道-工单聊天记录')->name('tickets.chat.index');
87 Route::post('/chat/{project_id}/{ticket_id}', [\App\Http\Controllers\Api\WorkOrder\TicketChatController::class, 'store'])->summary('B端,渠道-工单聊天记录提交')->name('tickets.chat.store'); 87 Route::post('/chat/{project_id}/{ticket_id}', [\App\Http\Controllers\Api\WorkOrder\TicketChatController::class, 'store'])->summary('B端,渠道-工单聊天记录提交')->name('tickets.chat.store');
88 }); 88 });
  89 +Route::get('/pushTicketByBot/{friend_id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'pushTicketByBot'])->summary('企微群@机器人触发工单推送')->name('tickets.pushTicketByBot');
@@ -255,8 +255,10 @@ Route::middleware(['aloginauth'])->group(function () { @@ -255,8 +255,10 @@ Route::middleware(['aloginauth'])->group(function () {
255 Route::post('/', [Aside\WorkOrder\AsideTicketController::class, 'store'])->name('admin.tickets.store')->summary('A端创建工单'); 255 Route::post('/', [Aside\WorkOrder\AsideTicketController::class, 'store'])->name('admin.tickets.store')->summary('A端创建工单');
256 Route::get('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'show'])->name('admin.tickets.show')->summary('A端工单详情'); 256 Route::get('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'show'])->name('admin.tickets.show')->summary('A端工单详情');
257 Route::post('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'update'])->name('admin.tickets.update')->summary('A端更新工单,审核,邀请同事'); 257 Route::post('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'update'])->name('admin.tickets.update')->summary('A端更新工单,审核,邀请同事');
  258 + Route::get('/pushNotify/{id}', [Aside\WorkOrder\AsideTicketController::class, 'pushNotify'])->name('admin.tickets.pushNotify')->summary('A端工单推送企微群');
258 Route::get('/projects/{search}', [Aside\WorkOrder\AsideTicketController::class, 'getProjects'])->name('admin.tickets.projects')->summary('A端V5V6项目列表'); 259 Route::get('/projects/{search}', [Aside\WorkOrder\AsideTicketController::class, 'getProjects'])->name('admin.tickets.projects')->summary('A端V5V6项目列表');
259 - Route::get('/v56_projects/list', [Aside\WorkOrder\AsideTicketController::class, 'projectList'])->name('admin.tickets.projectList')->summary('A端V5V6项目列表'); 260 + Route::get('/v56_projects/list', [Aside\WorkOrder\AsideTicketController::class, 'projectList'])->name('admin.tickets.projectList')->summary('A端V5V6项目列表')
  261 + ->description("project_cate[项目分类1]: 1 V5, 2 V6, 3 超迹, 4 域途");
260 Route::post('/log/{id}', [Aside\WorkOrder\AsideTicketLogController::class, 'update'])->name('admin.tickets.log.update')->summary('A端工单操作日志更新,完成工单'); 262 Route::post('/log/{id}', [Aside\WorkOrder\AsideTicketLogController::class, 'update'])->name('admin.tickets.log.update')->summary('A端工单操作日志更新,完成工单');
261 Route::get('/chat/{ticket_id}', [Aside\WorkOrder\TicketChatController::class, 'index'])->name('admin.tickets.chat.index')->summary('A端工单聊天记录'); 263 Route::get('/chat/{ticket_id}', [Aside\WorkOrder\TicketChatController::class, 'index'])->name('admin.tickets.chat.index')->summary('A端工单聊天记录');
262 Route::post('/chat/{ticket_id}', [Aside\WorkOrder\TicketChatController::class, 'store'])->name('admin.tickets.chat.store')->summary('A端工单聊天记录创建'); 264 Route::post('/chat/{ticket_id}', [Aside\WorkOrder\TicketChatController::class, 'store'])->name('admin.tickets.chat.store')->summary('A端工单聊天记录创建');