作者 lyh

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

@@ -18,7 +18,7 @@ class FetchTicketProjects extends Command @@ -18,7 +18,7 @@ class FetchTicketProjects extends Command
18 * 18 *
19 * @var string 19 * @var string
20 */ 20 */
21 - protected $signature = 'workorder:fetch-ticket-projects {action}}'; 21 + protected $signature = 'workorder:fetch-ticket-projects {action}';
22 22
23 /** 23 /**
24 * The console command description. 24 * The console command description.
@@ -234,72 +234,73 @@ class FetchTicketProjects extends Command @@ -234,72 +234,73 @@ class FetchTicketProjects extends Command
234 } 234 }
235 235
236 foreach ($items as $item) { 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 237 + foreach ($item['plans'] as $plan)
251 { 238 {
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 - } 239 + // 判断套餐是超迹还是域途, 如果 $item['plans'][0]['name'] 包含 '超迹' 则为超迹,否则为域途
  240 + $project_cate = Str::contains($plan['name'], '超迹') ? 3 : 4;
  241 + $uuid = md5("AICC{$item['id']}{$project_cate}");
  242 + $project = TicketProject::where('uuid', $uuid)->first();
  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 258
259 - // 优化师  
260 - $seom_id = 0;  
261 - // 第一负责人  
262 - $engineer_id = $assm_id;  
263 - $is_del = 0; 259 + // 优化师
  260 + $seom_id = 0;
  261 + // 第一负责人
  262 + $engineer_id = $assm_id;
  263 + $is_del = 0;
264 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 - ]; 265 + $fields = [
  266 + 'company_name' => $item['company'],
  267 + 'title' => $item['company'] . " - " . $plan['name'],
  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' => $plan['name'] ?? '',
  276 + 'project_cate' => $project_cate,
  277 + 'wechat_group_id' => $item['chatroom_id'],
  278 + ];
279 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) { 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) {
293 $project->$k = $v; 286 $project->$k = $v;
294 - $changed = true;  
295 } 287 }
296 - }  
297 - if ($changed) {  
298 $project->save(); 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 + }
299 } 300 }
  301 + $lastid = $item['id'];
  302 + echo now() . " | INFO | AICC: {$item['id']} {$item['company']} fetch ok \n";
300 } 303 }
301 - $lastid = $item['id'];  
302 - echo now() . " | INFO | AICC: {$item['id']} {$item['company']} fetch ok \n";  
303 } 304 }
304 }catch (\Exception $exception){ 305 }catch (\Exception $exception){
305 echo now() . " | ERROR | " . $exception->getMessage() . "\n" . $exception->getTraceAsString() . "\n"; 306 echo now() . " | ERROR | " . $exception->getMessage() . "\n" . $exception->getTraceAsString() . "\n";
1 -<?php  
2 -  
3 -namespace App\Console\Commands\WorkOrder;  
4 -  
5 -use App\Models\ProjectAssociation\ProjectAssociation;  
6 -use App\Models\Workchat\MessagePush;  
7 -use App\Models\WorkOrder\Tickets;  
8 -use Illuminate\Console\Command;  
9 -  
10 -class PushNotify extends Command  
11 -{  
12 - /**  
13 - * The name and signature of the console command.  
14 - *  
15 - * @var string  
16 - */  
17 - protected $signature = 'workorder:push-notify';  
18 -  
19 - /**  
20 - * The console command description.  
21 - *  
22 - * @var string  
23 - */  
24 - protected $description = 'tickets push notify';  
25 -  
26 - /**  
27 - * Create a new command instance.  
28 - *  
29 - * @return void  
30 - */  
31 - public function __construct()  
32 - {  
33 - parent::__construct();  
34 - }  
35 -  
36 - /**  
37 - * Execute the console command.  
38 - *  
39 - * @return int  
40 - */  
41 - public function handle()  
42 - {  
43 - while (true) {  
44 - try {  
45 - $tick = Tickets::where('ding', 0)  
46 - ->where('submit_side', 2)  
47 -// ->where('project_id', 1)  
48 - ->first();  
49 - if (!$tick) {  
50 - echo now() . " WARNING | 没有待推送的工单\n";  
51 - sleep(3);  
52 - continue;  
53 - }  
54 - $project = $tick->project;  
55 - if ($project->version != 6 || $project->is_del == 1) {  
56 - echo now() . " WARNING | 项目版本或状态异常 \n";  
57 - $tick->ding = 1;  
58 - $tick->save();  
59 - continue;  
60 - }  
61 - $message_push = new MessagePush();  
62 - $message_push->project_id = $project->table_id;  
63 - $message_push->friend_id = ProjectAssociation::where('project_id', $project->table_id)  
64 - ->where('status', ProjectAssociation::STATUS_NORMAL)  
65 - ->where('binding_app', ProjectAssociation::ENTERPRISE_WECHAT)  
66 - ->value('friend_id');  
67 - if (empty($message_push->friend_id))  
68 - {  
69 - echo now() . " WARNING | 项目ID:{$project->table_id} 没有绑定企微群\n";  
70 - $tick->ding = 1;  
71 - $tick->save();  
72 - continue;  
73 - }  
74 - $message_push->content_type = 'Link';  
75 - $message_push->content = json_encode([  
76 - 'title' => '工单查看 - ' . $project->company_name,  
77 - 'desc' => $tick->title,  
78 - 'size' => 0,  
79 - 'thumbSize' => 0,  
80 - 'thumbUrl' => 'https://oa.quanqiusou.cn/logo.ico',  
81 - 'url' => 'https://oa.quanqiusou.cn/tickets?project_id='.$project->uuid  
82 - ], JSON_UNESCAPED_UNICODE);  
83 - $message_push->send_time = now();  
84 - $message_push->type = MessagePush::TYPE_TICKET;  
85 - $message_push->save();  
86 - $tick->ding = 1;  
87 - $tick->save();  
88 - echo now() . " INFO | 项目ID:{$project->table_id} 工单ID:{$tick->id} 推送成功\n";  
89 - }catch (\Exception $exception){  
90 - echo date('Y-m-d H:i:s')." ERROR | ".$exception->getMessage()."\n";  
91 - break;  
92 - }  
93 - }  
94 - }  
95 -}  
@@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
2 2
3 namespace App\Console\Commands\WorkOrder; 3 namespace App\Console\Commands\WorkOrder;
4 4
  5 +use App\Models\Manage\Manage;
  6 +use App\Models\WorkOrder\TicketChat;
5 use App\Models\WorkOrder\TicketLog; 7 use App\Models\WorkOrder\TicketLog;
6 use App\Services\DingTalkService; 8 use App\Services\DingTalkService;
7 use Illuminate\Console\Command; 9 use Illuminate\Console\Command;
@@ -14,7 +16,7 @@ class WorkOrderDing extends Command @@ -14,7 +16,7 @@ class WorkOrderDing extends Command
14 * 16 *
15 * @var string 17 * @var string
16 */ 18 */
17 - protected $signature = 'workorder:ding'; 19 + protected $signature = 'workorder:ding {action}';
18 20
19 /** 21 /**
20 * The console command description. 22 * The console command description.
@@ -40,11 +42,17 @@ class WorkOrderDing extends Command @@ -40,11 +42,17 @@ class WorkOrderDing extends Command
40 */ 42 */
41 public function handle() 43 public function handle()
42 { 44 {
  45 + $action = $this->argument('action');
  46 + $this->$action();
  47 + }
  48 +
  49 + public function dingLog()
  50 + {
43 while (true) { 51 while (true) {
44 try { 52 try {
45 $log = TicketLog::where('ding', 0)->first(); 53 $log = TicketLog::where('ding', 0)->first();
46 if (!$log) { 54 if (!$log) {
47 - echo now() . " INFO | 没有通知任务\n"; 55 + echo now() . " | INFO | 没有通知任务\n";
48 sleep(3); 56 sleep(3);
49 continue; 57 continue;
50 } 58 }
@@ -55,23 +63,82 @@ class WorkOrderDing extends Command @@ -55,23 +63,82 @@ class WorkOrderDing extends Command
55 )->get('https://oa.cmer.com/api/dingding/user/' . $mobile); 63 )->get('https://oa.cmer.com/api/dingding/user/' . $mobile);
56 if ($response->status() == 200) { 64 if ($response->status() == 200) {
57 $userid = $response->json()['data']['userid']; 65 $userid = $response->json()['data']['userid'];
58 - $text = "**您有新的售后工单**<br>";  
59 - $text .= "工单ID:{$log->work_order_id}<br>";  
60 - $text .= "工单类型:<font color='red'>{$log->workOrder->product}</font><br>";  
61 - $text .= "项目:{$log->workOrder->project->title}<br>";  
62 - $text .= "时间:{$log->created_at}<br>";  
63 $ding = new DingTalkService(); 66 $ding = new DingTalkService();
64 $resp = $ding->danliao(json_encode([ 67 $resp = $ding->danliao(json_encode([
65 - 'text' => $text,  
66 - 'title' => '售后工单通知',  
67 - ]), [$userid]); 68 + 'text' => "您有新的工单(ID: {$log->ticket_id}),请及时处理!",
  69 + 'title' => 'AI协同工单 - ' . $log->ticket->project->title,
  70 + 'picUrl' => 'https://hub.globalso.com/logocm.png',
  71 + 'messageUrl' => 'https://oa.quanqiusou.cn/afterorder?project_id=' . $log->ticket->project->uuid,
  72 + ]), [$userid], 'sampleLink');
68 $log->ding = 1; 73 $log->ding = 1;
  74 + echo now() . " | INFO | 工单ID: {$log->ticket_id} 通知成功\n";
69 }else 75 }else
  76 + {
70 $log->ding = 2; 77 $log->ding = 2;
  78 + echo now() . " | ERROR | 工单ID: {$log->ticket_id} 通知失败\n";
  79 + }
71 $log->save(); 80 $log->save();
72 }catch (\Exception $exception){ 81 }catch (\Exception $exception){
73 - echo now() . " ERROR | ".$exception->getMessage()."\n";  
74 - break; 82 + echo now() . " | ERROR | log ID {$log->id} {$exception->getMessage()} {$exception->getTraceAsString()} \n";
  83 + $log->ding = 2;
  84 + $log->save();
  85 + }
  86 + }
  87 + }
  88 +
  89 + public function dingChat()
  90 + {
  91 + while (true) {
  92 + $chat = TicketChat::where([
  93 + 'ding' => 0,
  94 + 'submit_side' => 2
  95 + ])->first();
  96 +
  97 + if (!$chat) {
  98 + echo now() . " | INFO | 没有通知任务\n";
  99 + sleep(3);
  100 + continue;
  101 + }
  102 +
  103 + try {
  104 + $project = $chat->ticket->project;
  105 +
  106 + // 通知谁?暂时通知A端最近一次提交的chat记录的人,如果没有,则通第一负责人
  107 + $lastChat = TicketChat::where('ticket_id', $chat->ticket_id)
  108 + ->where('submit_side', 1)
  109 + ->orderBy('id', 'desc')
  110 + ->first();
  111 + if ($lastChat) {
  112 + $mobile = Manage::where('id', $lastChat->manage_id)->first()->mobile;
  113 + }else
  114 + {
  115 + $mobile = Manage::where('id', $project->first_engineer)->first()->mobile;
  116 + }
  117 + $response = Http::withBasicAuth(
  118 + env('DINGDING_BASIC_USER'),
  119 + env('DINGDING_BASIC_PASS')
  120 + )->get('https://oa.cmer.com/api/dingding/user/' . $mobile);
  121 + if ($response->status() == 200) {
  122 + $userid = $response->json()['data']['userid'];
  123 + $ding = new DingTalkService();
  124 + $resp = $ding->danliao(json_encode([
  125 + 'text' => "客户对工单(ID: {$chat->ticket_id})进行了补充,请及时查看处理!",
  126 + 'title' => 'AI协同工单 - ' . $project->title,
  127 + 'picUrl' => 'https://hub.globalso.com/logocm.png',
  128 + 'messageUrl' => 'https://oa.quanqiusou.cn/afterorder?project_id=' . $project->uuid,
  129 + ]), [$userid], 'sampleLink');
  130 + $chat->ding = 1;
  131 + echo now() . " | INFO | 工单ID: {$chat->ticket_id} 通知成功\n";
  132 + }else
  133 + {
  134 + $chat->ding = 2;
  135 + echo now() . " | ERROR | 工单ID: {$chat->ticket_id} 通知失败\n";
  136 + }
  137 + $chat->save();
  138 + }catch (\Exception $exception) {
  139 + echo now() . " | ERROR | chat ID {$chat->id} {$exception->getMessage()} {$exception->getTraceAsString()} \n";
  140 + $chat->ding = 2;
  141 + $chat->save();
75 } 142 }
76 } 143 }
77 } 144 }
@@ -17,10 +17,10 @@ class TicketChatController extends Controller @@ -17,10 +17,10 @@ class TicketChatController extends Controller
17 */ 17 */
18 public function index($project_id, $ticket_id) 18 public function index($project_id, $ticket_id)
19 { 19 {
20 - $ticket = Tickets::find($ticket_id);;  
21 - if (!$ticket) return response('工单未找到', 404);  
22 - if ($ticket->project->uuid !== $project_id) return response('无权限查看该工单', 403);  
23 - if ($ticket->project->is_del) return response('项目状态异常', 400); 20 + $ticket = Tickets::find($ticket_id);
  21 + if (!$ticket) return response()->json(['message' => '工单未找到'], 404);
  22 + if ($ticket->project->uuid !== $project_id) return response()->json(['message' => '无权限查看该工单'], 403);
  23 + if ($ticket->project->is_del) return response()->json(['message' => '项目状态异常'], 400);
24 24
25 $chats = TicketChat::where('ticket_id', $ticket->id) 25 $chats = TicketChat::where('ticket_id', $ticket->id)
26 ->get(); 26 ->get();
@@ -47,9 +47,11 @@ class TicketChatController extends Controller @@ -47,9 +47,11 @@ class TicketChatController extends Controller
47 { 47 {
48 $request->validated(); 48 $request->validated();
49 $ticket = Tickets::with(['project'])->find($ticket_id); 49 $ticket = Tickets::with(['project'])->find($ticket_id);
50 - if (!$ticket) return response('工单未找到', 404);  
51 - if ($ticket->project->uuid !== $project_id) return response('无权限查看该工单', 403);  
52 - if ($ticket->project->is_del) return response('项目状态异常', 400); 50 + if (!$ticket) return response()->json(['message' => '工单未找到'], 404);
  51 + if ($ticket->status >= Tickets::STATUS_COMPLETED) return response()->json(['message' => '工单已完成或已关闭'], 400);
  52 +
  53 + if ($ticket->project->uuid !== $project_id) return response()->json(['message' => '无权限查看该工单'], 403);
  54 + if ($ticket->project->is_del) return response()->json(['message' => '项目状态异常'], 400);
53 55
54 $chat = new TicketChat(); 56 $chat = new TicketChat();
55 $chat->ticket_id = $ticket->id; 57 $chat->ticket_id = $ticket->id;
@@ -45,6 +45,7 @@ class TicketChatController extends BaseController @@ -45,6 +45,7 @@ class TicketChatController extends BaseController
45 $validated = $request->validated(); 45 $validated = $request->validated();
46 $ticket = Tickets::find($ticket_id); 46 $ticket = Tickets::find($ticket_id);
47 if (!$ticket) return response('工单未找到', 404); 47 if (!$ticket) return response('工单未找到', 404);
  48 + if ($ticket->status >= Tickets::STATUS_COMPLETED) return response('工单已完成或已关闭', 400);
48 if ($ticket->project->is_del) return response('项目状态异常', 400); 49 if ($ticket->project->is_del) return response('项目状态异常', 400);
49 50
50 $chat = new TicketChat(); 51 $chat = new TicketChat();
@@ -66,7 +66,7 @@ class MessagePush extends Base @@ -66,7 +66,7 @@ class MessagePush extends Base
66 //9-21 点,每条消息及时通知 66 //9-21 点,每条消息及时通知
67 //21-第二天 9 点,整合一起通知 67 //21-第二天 9 点,整合一起通知
68 $hour = date('H', strtotime($submit_at)); 68 $hour = date('H', strtotime($submit_at));
69 - if(($hour >= 9 && $hour < 21) || in_array($project_id, $special_project_ids)) { 69 + if(($hour >= 8 && $hour < 21) || in_array($project_id, $special_project_ids)) {
70 $model = new self(); 70 $model = new self();
71 $model->project_id = $project_id; 71 $model->project_id = $project_id;
72 $model->friend_id = $friend_id; 72 $model->friend_id = $friend_id;
@@ -76,7 +76,7 @@ class MessagePush extends Base @@ -76,7 +76,7 @@ class MessagePush extends Base
76 $model->send_time = $submit_at; 76 $model->send_time = $submit_at;
77 }else{ 77 }else{
78 //定时发送时间 78 //定时发送时间
79 - $send_time = $hour >= 9 ? date('Y-m-d 09:00:00', strtotime($submit_at . '+1 day')) : date('Y-m-d 09:00:00', strtotime($submit_at)); 79 + $send_time = $hour >= 8 ? date('Y-m-d 08:00:00', strtotime($submit_at . '+1 day')) : date('Y-m-d 08:00:00', strtotime($submit_at));
80 $model = self::where('project_id', $project_id)->where('type', self::TYPE_INQUIRY)->where('send_time', $send_time)->first(); 80 $model = self::where('project_id', $project_id)->where('type', self::TYPE_INQUIRY)->where('send_time', $send_time)->first();
81 if(!$model){ 81 if(!$model){
82 $model = new self(); 82 $model = new self();
@@ -86,7 +86,7 @@ class MessagePush extends Base @@ -86,7 +86,7 @@ class MessagePush extends Base
86 $model->ref_ids = $id; 86 $model->ref_ids = $id;
87 $model->countries = $country; 87 $model->countries = $country;
88 $model->send_time = $send_time; 88 $model->send_time = $send_time;
89 - $model->content = '[09:00] 您的全球搜网站收到来自【' . $country . $name . '】的询盘信息,请登录后台或APP进行查看!'; 89 + $model->content = '[08:00] 您的全球搜网站收到来自【' . $country . $name . '】的询盘信息,请登录后台或APP进行查看!';
90 }else{ 90 }else{
91 $ref_ids = explode(',', $model->ref_ids); 91 $ref_ids = explode(',', $model->ref_ids);
92 $ref_ids[] = $id; 92 $ref_ids[] = $id;
@@ -105,7 +105,7 @@ class MessagePush extends Base @@ -105,7 +105,7 @@ class MessagePush extends Base
105 $country = implode(',', $countries); 105 $country = implode(',', $countries);
106 } 106 }
107 } 107 }
108 - $model->content = '[09:00] 您的全球搜网站收到来自【' . $country . '】'.$count.'条询盘信息,请登录后台或APP进行查看!'; 108 + $model->content = '[08:00] 您的全球搜网站收到来自【' . $country . '】'.$count.'条询盘信息,请登录后台或APP进行查看!';
109 } 109 }
110 } 110 }
111 $model->save(); 111 $model->save();
@@ -45,7 +45,7 @@ class DingTalkService @@ -45,7 +45,7 @@ class DingTalkService
45 } 45 }
46 46
47 /** 批量发送私聊消息 */ 47 /** 批量发送私聊消息 */
48 - public function danliao(string $text, array $user_ids) 48 + public function danliao(string $text, array $user_ids, string $msg_key='sampleMarkdown')
49 { 49 {
50 $endpoint = '/v1/danliao'; 50 $endpoint = '/v1/danliao';
51 $payload = [ 51 $payload = [
@@ -53,7 +53,8 @@ class DingTalkService @@ -53,7 +53,8 @@ class DingTalkService
53 "appSecret" => $this->appSecret, 53 "appSecret" => $this->appSecret,
54 "robotCode" => $this->robotCode, 54 "robotCode" => $this->robotCode,
55 "msg_param" => $text, 55 "msg_param" => $text,
56 - "user_ids" => $user_ids 56 + "user_ids" => $user_ids,
  57 + "msg_key" => $msg_key
57 ]; 58 ];
58 return $this->send_request('POST', $this->bashUrl . $endpoint, $payload); 59 return $this->send_request('POST', $this->bashUrl . $endpoint, $payload);
59 } 60 }