Merge branch 'master' of http://47.244.231.31:8099/zhl/globalso-v6
正在显示
20 个修改的文件
包含
1371 行增加
和
93 行删除
| @@ -18,6 +18,7 @@ use App\Models\Ai\AiCommand; | @@ -18,6 +18,7 @@ use App\Models\Ai\AiCommand; | ||
| 18 | use App\Models\Com\NoticeLog; | 18 | use App\Models\Com\NoticeLog; |
| 19 | use App\Models\Com\V6WeeklyReport; | 19 | use App\Models\Com\V6WeeklyReport; |
| 20 | use App\Models\Product\Category; | 20 | use App\Models\Product\Category; |
| 21 | +use App\Models\Project\AggregateKeywordAffix; | ||
| 21 | use App\Models\Project\AiBlogTask; | 22 | use App\Models\Project\AiBlogTask; |
| 22 | use App\Models\Project\DeployBuild; | 23 | use App\Models\Project\DeployBuild; |
| 23 | use App\Models\Project\DeployOptimize; | 24 | use App\Models\Project\DeployOptimize; |
| @@ -58,7 +59,22 @@ class lyhDemo extends Command | @@ -58,7 +59,22 @@ class lyhDemo extends Command | ||
| 58 | protected $description = '更新路由'; | 59 | protected $description = '更新路由'; |
| 59 | 60 | ||
| 60 | public function handle(){ | 61 | public function handle(){ |
| 61 | - | 62 | + $aggregateKeywordAffixModel = new AggregateKeywordAffix(); |
| 63 | + $info = $aggregateKeywordAffixModel->read(['project_id'=>3298]); | ||
| 64 | + $projectModel = new Project(); | ||
| 65 | + $lists = $projectModel->list(['delete_status' => 0,'project_type'=>0,'extend_type'=>0,'type'=>2], 'id', ['id']); | ||
| 66 | + foreach ($lists as $item){ | ||
| 67 | + if(in_array($item['id'],[467,110,3298])){ | ||
| 68 | + continue; | ||
| 69 | + } | ||
| 70 | + $data = [ | ||
| 71 | + 'project_id'=>$item['id'], | ||
| 72 | + 'prefix'=>$info['prefix'], | ||
| 73 | + 'suffix'=>$info['suffix'] | ||
| 74 | + ]; | ||
| 75 | + $aggregateKeywordAffixModel->addReturnId($data); | ||
| 76 | + } | ||
| 77 | + return true; | ||
| 62 | } | 78 | } |
| 63 | 79 | ||
| 64 | public function _actionTemplateMain(){ | 80 | public function _actionTemplateMain(){ |
| @@ -43,7 +43,7 @@ class Temp extends Command | @@ -43,7 +43,7 @@ class Temp extends Command | ||
| 43 | 43 | ||
| 44 | public function handle() | 44 | public function handle() |
| 45 | { | 45 | { |
| 46 | - $this->check_no_cname_projects(); | 46 | + $this->change_cname_projects(); |
| 47 | } | 47 | } |
| 48 | 48 | ||
| 49 | /** | 49 | /** |
| @@ -600,15 +600,18 @@ class Temp extends Command | @@ -600,15 +600,18 @@ class Temp extends Command | ||
| 600 | 600 | ||
| 601 | 601 | ||
| 602 | /** | 602 | /** |
| 603 | - * 240服务器上解析cname的项目迁移 | 603 | + * 服务器上解析cname的项目迁移 |
| 604 | * @author Akun | 604 | * @author Akun |
| 605 | * @date 2025/02/17 14:21 | 605 | * @date 2025/02/17 14:21 |
| 606 | */ | 606 | */ |
| 607 | - public function change_cname_projects_240() | 607 | + public function change_cname_projects() |
| 608 | { | 608 | { |
| 609 | + $origin_server_id = 20;//原服务器 | ||
| 610 | + $target_server_id = 27;//目标服务器 | ||
| 611 | + | ||
| 609 | $server_ip_model = new ServersIp(); | 612 | $server_ip_model = new ServersIp(); |
| 610 | 613 | ||
| 611 | - $server_ip_ids = $server_ip_model->where('servers_id', 1)->get()->pluck('id')->toArray(); | 614 | + $server_ip_ids = $server_ip_model->where('servers_id', $origin_server_id)->get()->pluck('id')->toArray(); |
| 612 | 615 | ||
| 613 | $project_list = Project::select(['id', 'serve_id'])->whereIn('serve_id', $server_ip_ids)->get(); | 616 | $project_list = Project::select(['id', 'serve_id'])->whereIn('serve_id', $server_ip_ids)->get(); |
| 614 | 617 | ||
| @@ -626,60 +629,70 @@ class Temp extends Command | @@ -626,60 +629,70 @@ class Temp extends Command | ||
| 626 | $domain = $domain_info['domain']; | 629 | $domain = $domain_info['domain']; |
| 627 | 630 | ||
| 628 | //迁移主站 | 631 | //迁移主站 |
| 629 | - $check = dns_get_record($domain, DNS_A); | ||
| 630 | - $host = $check[0]['host'] ?? ''; | ||
| 631 | - if ($host == 'cname.globalso.com') { | ||
| 632 | - //获取主站备份证书 | ||
| 633 | - $ssl_info = DB::table('gl_domain_ssl_backup')->select(['private_key', 'private_cert'])->where('domain', $domain)->first(); | ||
| 634 | - if (!$ssl_info) { | ||
| 635 | - $this->output('项目id:' . $project_id . ' | 未备份主站证书'); | ||
| 636 | - continue; | ||
| 637 | - } | ||
| 638 | - | ||
| 639 | - //创建主站建站任务 | ||
| 640 | - $task_info = DomainCreateTask::where('type', 1)->where('server_id', 20)->where('project_id', $project_id)->where('status', '!=', DomainCreateTask::STATUS_SUC)->first(); | ||
| 641 | - if (!$task_info) { | ||
| 642 | - $task_model = new DomainCreateTask(); | ||
| 643 | - $task_model->type = 1; | ||
| 644 | - $task_model->server_id = 20; | ||
| 645 | - $task_model->project_id = $project_id; | ||
| 646 | - $task_model->domain_id = $domain_id; | ||
| 647 | - $task_model->certs = json_encode(['key' => $ssl_info->private_key, 'csr' => $ssl_info->private_cert]); | ||
| 648 | - $task_model->save(); | ||
| 649 | - } | ||
| 650 | - | ||
| 651 | - //创建主站页面生成任务 | ||
| 652 | - $notify_data = [ | ||
| 653 | - 'project_id' => $project_id, | ||
| 654 | - 'type' => 1, | ||
| 655 | - 'route' => 1, | ||
| 656 | - 'server_id' => 20, | ||
| 657 | - 'status' => ['!=', Notify::STATUS_FINISH_SITEMAP] | ||
| 658 | - ]; | ||
| 659 | - $notify = $notify_model->read($notify_data, ['id']); | 632 | +// try { |
| 633 | +// $check = dns_get_record($domain, DNS_A); | ||
| 634 | +// $host = $check[0]['host'] ?? ''; | ||
| 635 | +// } catch (\Exception $e) { | ||
| 636 | +// $this->output($domain . ' | 获取解析记录失败'); | ||
| 637 | +// continue; | ||
| 638 | +// } | ||
| 639 | +// | ||
| 640 | +// if ($host != 'cname.globalso.com') { | ||
| 641 | +// $this->output($domain . ' | 未解析cname'); | ||
| 642 | +// continue; | ||
| 643 | +// } | ||
| 644 | + | ||
| 645 | + //获取主站备份证书 | ||
| 646 | + $ssl_info = DB::table('gl_domain_ssl_backup')->select(['private_key', 'private_cert'])->where('domain', $domain)->first(); | ||
| 647 | + if (!$ssl_info) { | ||
| 648 | + $this->output($domain . ' | 未备份证书'); | ||
| 649 | + continue; | ||
| 650 | + } | ||
| 660 | 651 | ||
| 661 | - if (!$notify) { | ||
| 662 | - $notify_data['data'] = Arr::a2s(['domain' => $domain, 'url' => null, 'language' => []]); | ||
| 663 | - $notify_data['status'] = Notify::STATUS_INIT; | ||
| 664 | - $notify_model->add($notify_data); | ||
| 665 | - } | 652 | + //创建主站建站任务 |
| 653 | + $task_info = DomainCreateTask::where('type', 1)->where('server_id', $target_server_id)->where('project_id', $project_id)->where('status', '!=', DomainCreateTask::STATUS_SUC)->first(); | ||
| 654 | + if (!$task_info) { | ||
| 655 | + $task_model = new DomainCreateTask(); | ||
| 656 | + $task_model->type = 1; | ||
| 657 | + $task_model->server_id = $target_server_id; | ||
| 658 | + $task_model->project_id = $project_id; | ||
| 659 | + $task_model->domain_id = $domain_id; | ||
| 660 | + $task_model->certs = json_encode(['key' => $ssl_info->private_key, 'csr' => $ssl_info->private_cert]); | ||
| 661 | + $task_model->save(); | ||
| 662 | + } | ||
| 666 | 663 | ||
| 667 | - //创建主站关键词页面生成任务 | ||
| 668 | - $notify_keyword_data = [ | ||
| 669 | - 'project_id' => $project_id, | ||
| 670 | - 'type' => 1, | ||
| 671 | - 'route' => 4, | ||
| 672 | - 'server_id' => 20, | ||
| 673 | - 'status' => ['!=', Notify::STATUS_FINISH_SITEMAP] | ||
| 674 | - ]; | ||
| 675 | - $notify_keyword = $notify_model->read($notify_keyword_data, ['id']); | 664 | +// //创建主站页面生成任务 |
| 665 | +// $notify_data = [ | ||
| 666 | +// 'project_id' => $project_id, | ||
| 667 | +// 'type' => 1, | ||
| 668 | +// 'route' => 1, | ||
| 669 | +// 'server_id' => 20, | ||
| 670 | +// 'status' => ['!=', Notify::STATUS_FINISH_SITEMAP] | ||
| 671 | +// ]; | ||
| 672 | +// $notify = $notify_model->read($notify_data, ['id']); | ||
| 673 | +// | ||
| 674 | +// if (!$notify) { | ||
| 675 | +// $notify_data['data'] = Arr::a2s(['domain' => $domain, 'url' => null, 'language' => []]); | ||
| 676 | +// $notify_data['status'] = Notify::STATUS_INIT; | ||
| 677 | +// $notify_model->add($notify_data); | ||
| 678 | +// } | ||
| 679 | +// | ||
| 680 | +// //创建主站关键词页面生成任务 | ||
| 681 | +// $notify_keyword_data = [ | ||
| 682 | +// 'project_id' => $project_id, | ||
| 683 | +// 'type' => 1, | ||
| 684 | +// 'route' => 4, | ||
| 685 | +// 'server_id' => 20, | ||
| 686 | +// 'status' => ['!=', Notify::STATUS_FINISH_SITEMAP] | ||
| 687 | +// ]; | ||
| 688 | +// $notify_keyword = $notify_model->read($notify_keyword_data, ['id']); | ||
| 689 | +// | ||
| 690 | +// if (!$notify_keyword) { | ||
| 691 | +// $notify_keyword_data['data'] = Arr::a2s(['domain' => $domain, 'url' => null, 'language' => []]); | ||
| 692 | +// $notify_keyword_data['status'] = Notify::STATUS_INIT; | ||
| 693 | +// $notify_model->add($notify_keyword_data); | ||
| 694 | +// } | ||
| 676 | 695 | ||
| 677 | - if (!$notify_keyword) { | ||
| 678 | - $notify_keyword_data['data'] = Arr::a2s(['domain' => $domain, 'url' => null, 'language' => []]); | ||
| 679 | - $notify_keyword_data['status'] = Notify::STATUS_INIT; | ||
| 680 | - $notify_model->add($notify_keyword_data); | ||
| 681 | - } | ||
| 682 | - } | ||
| 683 | 696 | ||
| 684 | if ($domain_info['amp_status'] == 1) { | 697 | if ($domain_info['amp_status'] == 1) { |
| 685 | //迁移amp站 | 698 | //迁移amp站 |
| @@ -693,44 +706,53 @@ class Temp extends Command | @@ -693,44 +706,53 @@ class Temp extends Command | ||
| 693 | } | 706 | } |
| 694 | $amp_domain = implode('.', $host_array); | 707 | $amp_domain = implode('.', $host_array); |
| 695 | 708 | ||
| 696 | - $check_amp = dns_get_record($amp_domain, DNS_A); | ||
| 697 | - $host_amp = $check_amp[0]['host'] ?? ''; | ||
| 698 | - if ($host_amp == 'cname.globalso.com') { | ||
| 699 | - //获取amp站备份证书 | ||
| 700 | - $ssl_info_amp = DB::table('gl_domain_ssl_backup')->select(['private_key', 'private_cert'])->where('domain', $amp_domain)->first(); | ||
| 701 | - if (!$ssl_info_amp) { | ||
| 702 | - $this->output('项目id:' . $project_id . ' | 未备份amp站证书'); | ||
| 703 | - continue; | ||
| 704 | - } | ||
| 705 | - | ||
| 706 | - //创建amp站建站任务 | ||
| 707 | - $task_info_amp = DomainCreateTask::where('type', 2)->where('server_id', 20)->where('project_id', $project_id)->where('status', '!=', DomainCreateTask::STATUS_SUC)->first(); | ||
| 708 | - if (!$task_info_amp) { | ||
| 709 | - $task_model = new DomainCreateTask(); | ||
| 710 | - $task_model->type = 2; | ||
| 711 | - $task_model->server_id = 20; | ||
| 712 | - $task_model->project_id = $project_id; | ||
| 713 | - $task_model->domain_id = $domain_id; | ||
| 714 | - $task_model->certs = json_encode(['key' => $ssl_info_amp->private_key, 'csr' => $ssl_info_amp->private_cert]); | ||
| 715 | - $task_model->save(); | ||
| 716 | - } | 709 | +// try { |
| 710 | +// $check_amp = dns_get_record($amp_domain, DNS_A); | ||
| 711 | +// $host_amp = $check_amp[0]['host'] ?? ''; | ||
| 712 | +// } catch (\Exception $e) { | ||
| 713 | +// $this->output($amp_domain . ' | 获取解析记录失败'); | ||
| 714 | +// continue; | ||
| 715 | +// } | ||
| 716 | +// | ||
| 717 | +// if ($host_amp != 'cname.globalso.com') { | ||
| 718 | +// $this->output($amp_domain . ' | 未解析cname'); | ||
| 719 | +// continue; | ||
| 720 | +// } | ||
| 721 | + | ||
| 722 | + //获取amp站备份证书 | ||
| 723 | + $ssl_info_amp = DB::table('gl_domain_ssl_backup')->select(['private_key', 'private_cert'])->where('domain', $amp_domain)->first(); | ||
| 724 | + if (!$ssl_info_amp) { | ||
| 725 | + $this->output($amp_domain . ' | 未备份证书'); | ||
| 726 | + continue; | ||
| 727 | + } | ||
| 717 | 728 | ||
| 718 | - //创建amp站页面生成任务 | ||
| 719 | - $notify_amp_data = [ | ||
| 720 | - 'project_id' => $project_id, | ||
| 721 | - 'type' => 3, | ||
| 722 | - 'route' => 1, | ||
| 723 | - 'server_id' => 20, | ||
| 724 | - 'status' => ['!=', Notify::STATUS_FINISH_SITEMAP] | ||
| 725 | - ]; | ||
| 726 | - $notify_amp = $notify_model->read($notify_amp_data, ['id']); | ||
| 727 | - | ||
| 728 | - if (!$notify_amp) { | ||
| 729 | - $notify_amp_data['data'] = Arr::a2s(['domain' => $amp_domain, 'url' => null, 'language' => []]); | ||
| 730 | - $notify_amp_data['status'] = Notify::STATUS_INIT; | ||
| 731 | - $notify_model->add($notify_amp_data); | ||
| 732 | - } | 729 | + //创建amp站建站任务 |
| 730 | + $task_info_amp = DomainCreateTask::where('type', 2)->where('server_id', $target_server_id)->where('project_id', $project_id)->where('status', '!=', DomainCreateTask::STATUS_SUC)->first(); | ||
| 731 | + if (!$task_info_amp) { | ||
| 732 | + $task_model = new DomainCreateTask(); | ||
| 733 | + $task_model->type = 2; | ||
| 734 | + $task_model->server_id = $target_server_id; | ||
| 735 | + $task_model->project_id = $project_id; | ||
| 736 | + $task_model->domain_id = $domain_id; | ||
| 737 | + $task_model->certs = json_encode(['key' => $ssl_info_amp->private_key, 'csr' => $ssl_info_amp->private_cert]); | ||
| 738 | + $task_model->save(); | ||
| 733 | } | 739 | } |
| 740 | + | ||
| 741 | +// //创建amp站页面生成任务 | ||
| 742 | +// $notify_amp_data = [ | ||
| 743 | +// 'project_id' => $project_id, | ||
| 744 | +// 'type' => 3, | ||
| 745 | +// 'route' => 1, | ||
| 746 | +// 'server_id' => 20, | ||
| 747 | +// 'status' => ['!=', Notify::STATUS_FINISH_SITEMAP] | ||
| 748 | +// ]; | ||
| 749 | +// $notify_amp = $notify_model->read($notify_amp_data, ['id']); | ||
| 750 | +// | ||
| 751 | +// if (!$notify_amp) { | ||
| 752 | +// $notify_amp_data['data'] = Arr::a2s(['domain' => $amp_domain, 'url' => null, 'language' => []]); | ||
| 753 | +// $notify_amp_data['status'] = Notify::STATUS_INIT; | ||
| 754 | +// $notify_model->add($notify_amp_data); | ||
| 755 | +// } | ||
| 734 | } | 756 | } |
| 735 | } | 757 | } |
| 736 | } | 758 | } |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace App\Console\Commands\WorkOrder; | ||
| 4 | + | ||
| 5 | +use App\Models\Manage\Manage; | ||
| 6 | +use App\Models\Project\Project; | ||
| 7 | +use App\Models\WorkOrder\TicketProject; | ||
| 8 | +use Illuminate\Console\Command; | ||
| 9 | +use Illuminate\Support\Facades\Http; | ||
| 10 | + | ||
| 11 | +class FetchTicketProjects extends Command | ||
| 12 | +{ | ||
| 13 | + /** | ||
| 14 | + * The name and signature of the console command. | ||
| 15 | + * | ||
| 16 | + * @var string | ||
| 17 | + */ | ||
| 18 | + protected $signature = 'workorder:fetch-ticket-projects {version}'; | ||
| 19 | + | ||
| 20 | + /** | ||
| 21 | + * The console command description. | ||
| 22 | + * | ||
| 23 | + * @var string | ||
| 24 | + */ | ||
| 25 | + protected $description = '同步V5,V6的项目到 gl_ticket_projects 表'; | ||
| 26 | + | ||
| 27 | + /** | ||
| 28 | + * Create a new command instance. | ||
| 29 | + * | ||
| 30 | + * @return void | ||
| 31 | + */ | ||
| 32 | + public function __construct() | ||
| 33 | + { | ||
| 34 | + parent::__construct(); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * Execute the console command. | ||
| 39 | + * | ||
| 40 | + * @return int | ||
| 41 | + */ | ||
| 42 | + public function handle() | ||
| 43 | + { | ||
| 44 | + $version = $this->argument('version'); | ||
| 45 | + if ($version == 'v5') { | ||
| 46 | + $this->fetch_v5(); | ||
| 47 | + } elseif ($version == 'v6') { | ||
| 48 | + $this->fetch_v6(); | ||
| 49 | + } else { | ||
| 50 | + $this->error('Invalid action. Use "v5" or "v6".'); | ||
| 51 | + return 1; | ||
| 52 | + } | ||
| 53 | + return 0; | ||
| 54 | + } | ||
| 55 | + | ||
| 56 | + | ||
| 57 | + /** | ||
| 58 | + * @return void | ||
| 59 | + * 请求:https://www.quanqiusou.cn/extend_api/webs/globalso_all.php | ||
| 60 | + */ | ||
| 61 | + public function fetch_v5() | ||
| 62 | + { | ||
| 63 | + # pm 项目经理 assm 售后服务经理 | ||
| 64 | + $response = Http::get('https://www.quanqiusou.cn/extend_api/webs/globalso_all.php'); | ||
| 65 | + if ($response->status() == 200) { | ||
| 66 | + $items = $response->json(); | ||
| 67 | + foreach ($items as $item) { | ||
| 68 | + # V5: 版本号+postid | ||
| 69 | + $uuid = md5("V5{$item['postid']}"); | ||
| 70 | + $project = TicketProject::where('uuid', $uuid)->first(); | ||
| 71 | + | ||
| 72 | + $item['pm'] = $item['pm'] == '未安排' ? '杨长远' : $item['pm']; | ||
| 73 | + $item['assm'] = $item['assm'] == '未安排' ? '杨长远' : $item['assm']; | ||
| 74 | + $item['yhs'] = $item['yhs'] == '未安排' ? '杨长远' : $item['yhs']; | ||
| 75 | + | ||
| 76 | + // 如果 $item['cate'] 包含”推广“字符,则$engineer_name = $item['assm'] | ||
| 77 | + $engineer_name = (strpos($item['cate'], '推广') !== false) ? $item['yhs'] : $item['assm']; | ||
| 78 | + | ||
| 79 | + $fields = [ | ||
| 80 | + 'post_id' => $item['postid'], | ||
| 81 | + 'company_name' => $item['company'], | ||
| 82 | + 'title' => $item['title'], | ||
| 83 | + 'engineer_id' => Manage::where('name', $engineer_name)->value('id') ?? 0, // 第一负责人 | ||
| 84 | + 'assm_id' => Manage::where('name', $item['assm'])->value('id') ?? 0, //售后服务经理 | ||
| 85 | + 'seom_id' => Manage::where('name', $item['yhs'])->value('id') ?? 0, //售后服务经理 | ||
| 86 | + 'website' => $item['main_url'] ?? '', | ||
| 87 | + ]; | ||
| 88 | + if (!$project) { | ||
| 89 | + $new = new TicketProject(); | ||
| 90 | + $new->uuid = $uuid; | ||
| 91 | + $new->version = 5; | ||
| 92 | + $new->table_id = 0; | ||
| 93 | + foreach ($fields as $k => $v) { | ||
| 94 | + $new->$k = $v; | ||
| 95 | + } | ||
| 96 | + $new->save(); | ||
| 97 | + } else { | ||
| 98 | + $changed = false; | ||
| 99 | + foreach ($fields as $k => $v) { | ||
| 100 | + if ($project->$k != $v) { | ||
| 101 | + $project->$k = $v; | ||
| 102 | + $changed = true; | ||
| 103 | + } | ||
| 104 | + } | ||
| 105 | + if ($changed) { | ||
| 106 | + $project->save(); | ||
| 107 | + } | ||
| 108 | + } | ||
| 109 | + echo "V5: {$item['postid']} - {$item['title']} - {$item['company']} - {$item['main_url']}\n"; | ||
| 110 | + } | ||
| 111 | + } | ||
| 112 | + } | ||
| 113 | + | ||
| 114 | + /** | ||
| 115 | + * @return void | ||
| 116 | + * 1. 按照ID升序查询 gl_project 表 limit 10 | ||
| 117 | + * 2。同步到 TicketProject 后,redis 缓存 ID | ||
| 118 | + */ | ||
| 119 | + public function fetch_v6() | ||
| 120 | + { | ||
| 121 | + $lastid = 0; | ||
| 122 | + while (true) { | ||
| 123 | + try { | ||
| 124 | + $items = Project::where('id', '>', intval($lastid)) | ||
| 125 | + ->orderBy('id', 'asc') | ||
| 126 | + ->limit(10) | ||
| 127 | + ->get(); | ||
| 128 | + if ($items->isEmpty()) { | ||
| 129 | + echo "not found items \n"; | ||
| 130 | + break; | ||
| 131 | + } | ||
| 132 | + foreach ($items as $item) { | ||
| 133 | + $uuid = md5("V5{$item->id}"); | ||
| 134 | + $project = TicketProject::where('uuid', $uuid)->first(); | ||
| 135 | + $fields = [ | ||
| 136 | + 'company_name' => $item->company, | ||
| 137 | + 'title' => $item->title, | ||
| 138 | + 'assm_id' => $item->type ==3 ? $item->deploy_optimize->manager_mid ?? 0 : $item->deploy_build->manager_mid ?? 0, // 售后服务经理 | ||
| 139 | + 'seom_id' => $item->deploy_optimize->optimist_mid ?? $item->deploy_optimize->manager_mid ?? $item->deploy_optimize->tech_leader ?? 0, // 优化推广负责人 | ||
| 140 | + 'engineer_id' => $item->type == 3 ? | ||
| 141 | + $item->deploy_optimize->optimist_mid ?? $item->deploy_optimize->manager_mid ?? $item->deploy_optimize->tech_leader ?? 0 | ||
| 142 | + : $item->deploy_build->manager_mid ?? $item->deploy_build->leader_mid ?? 0, // 技术组长 | ||
| 143 | + ]; | ||
| 144 | + if (!$project) { | ||
| 145 | + $project = new TicketProject(); | ||
| 146 | + $project->uuid = $uuid; | ||
| 147 | + $project->post_id = $item->post_id; | ||
| 148 | + $project->version = 6; | ||
| 149 | + $project->table_id = $item->id; | ||
| 150 | + foreach ($fields as $k => $v) { | ||
| 151 | + $project->$k = $v; | ||
| 152 | + } | ||
| 153 | + $project->save(); | ||
| 154 | + }else{ | ||
| 155 | + $changed = false; | ||
| 156 | + foreach ($fields as $k => $v) { | ||
| 157 | + if ($project->$k != $v) { | ||
| 158 | + $project->$k = $v; | ||
| 159 | + $changed = true; | ||
| 160 | + } | ||
| 161 | + } | ||
| 162 | + if ($changed) { | ||
| 163 | + $project->save(); | ||
| 164 | + } | ||
| 165 | + } | ||
| 166 | + $lastid = $item->id; | ||
| 167 | + echo date('Y-m-d H:i:s') . " V6: $item->id {$item->company} fetch ok \n"; | ||
| 168 | + } | ||
| 169 | + }catch (\Exception $exception) { | ||
| 170 | + echo $exception; | ||
| 171 | + break; | ||
| 172 | + } | ||
| 173 | + } | ||
| 174 | + } | ||
| 175 | +} |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace App\Http\Controllers\Api\WorkOrder; | ||
| 4 | + | ||
| 5 | +use App\Http\Controllers\Api\BaseController; | ||
| 6 | +use App\Http\Requests\Api\WorkOrder\TicketStoreRequest; | ||
| 7 | +use App\Models\WorkOrder\TicketLog; | ||
| 8 | +use App\Models\WorkOrder\TicketProject; | ||
| 9 | +use App\Models\WorkOrder\Tickets; | ||
| 10 | +use Illuminate\Http\Request; | ||
| 11 | +use Illuminate\Support\Facades\DB; | ||
| 12 | + | ||
| 13 | +class TicketController extends BaseController | ||
| 14 | +{ | ||
| 15 | + /** | ||
| 16 | + * Display a listing of the resource. | ||
| 17 | + * | ||
| 18 | + * @return \Illuminate\Http\Response | ||
| 19 | + */ | ||
| 20 | + public function index($project_id, Request $request) | ||
| 21 | + { | ||
| 22 | + $project = TicketProject::where('uuid', $project_id)->first(); | ||
| 23 | + if (!$project) return $this->error('未找到项目', 404); | ||
| 24 | + $page = (int)$request->input('page', 1); | ||
| 25 | + $size = (int)$request->input('size', 10); | ||
| 26 | + | ||
| 27 | + $tickets = Tickets::with([ | ||
| 28 | + 'project.projectV6:id,company,version', | ||
| 29 | + 'logs.engineer:id,name', | ||
| 30 | + ]) | ||
| 31 | + ->where('project_id', $project->id) | ||
| 32 | + ->orderBy('id', 'desc') | ||
| 33 | + ->paginate($size, ['*'], 'page', $page); | ||
| 34 | + return response()->json(['data' => $tickets]); | ||
| 35 | + } | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * Store a newly created resource in storage. | ||
| 39 | + * | ||
| 40 | + * @param \Illuminate\Http\Request $request | ||
| 41 | + * @return \Illuminate\Http\Response | ||
| 42 | + * B端用户在企微群里提交工单 | ||
| 43 | + */ | ||
| 44 | + public function store($project_id, TicketStoreRequest $request) | ||
| 45 | + { | ||
| 46 | + $request->validated(); | ||
| 47 | + $project = TicketProject::where('uuid', $project_id)->first(); | ||
| 48 | + if (!$project) return $this->error('未找到项目', 404); | ||
| 49 | + if ($project->version == 6){ | ||
| 50 | + if ($project->project->projectV6->delete_status) return $this->error('该项目已被删除', 400); | ||
| 51 | + if ($project->project->projectV6->extend_type == 5) return $this->error('未续费', 400); | ||
| 52 | + if ($project->project->projectV6->type == 8) return $this->error('项目已归档', 400); | ||
| 53 | + if ($project->project->projectV6->site_status == 1) return $this->error('站点已关闭', 400); | ||
| 54 | + } | ||
| 55 | + $result = DB::transaction(function () use ($request, $project) { | ||
| 56 | + $ticket = new Tickets(); | ||
| 57 | + $ticket->project_id = $project->id; | ||
| 58 | + $ticket->title = $request->input('title'); | ||
| 59 | + $ticket->content = $request->input('content'); | ||
| 60 | + // $files = [NULL] | ||
| 61 | + $files = $request->input('files'); | ||
| 62 | + if (empty($files) || (is_array($files) && count(array_filter($files, function($v){ return !is_null($v); })) === 0)) { | ||
| 63 | + $ticket->files = null; | ||
| 64 | + } else { | ||
| 65 | + $ticket->files = json_encode($files); | ||
| 66 | + } | ||
| 67 | + $ticket->submit_side = 2; // 2 for B-side submission | ||
| 68 | + $ticket->submit_username = $request->input('submit_username'); | ||
| 69 | + $ticket->save(); | ||
| 70 | + $log = new TicketLog(); | ||
| 71 | + if ($project->version == 5){ | ||
| 72 | + # V5 | ||
| 73 | + $log->engineer_id = $project->engineer_id; | ||
| 74 | + }else{ | ||
| 75 | + # V6 的项目 | ||
| 76 | + if ($project->projectV6->type == 3){ | ||
| 77 | + // 项目类型是优化推广,项目负责人找优化 | ||
| 78 | + $seo = $project->projectV6->deploy_optimize; | ||
| 79 | + $log->engineer_id = $seo->manager_mid ?? $seo->optimist_mid ?? 0; | ||
| 80 | + }else{ | ||
| 81 | + // 非优化推广项目,项目负责人找技术组长 | ||
| 82 | + $build = $project->projectV6->deploy_build; | ||
| 83 | + $log->engineer_id = $build->leader_mid ?? 0; | ||
| 84 | + } | ||
| 85 | + } | ||
| 86 | + $ticket->logs()->save($log); | ||
| 87 | + return $ticket; | ||
| 88 | + }); | ||
| 89 | + return response()->json(['data' => $result]); | ||
| 90 | + } | ||
| 91 | + | ||
| 92 | + /** | ||
| 93 | + * Display the specified resource. | ||
| 94 | + * | ||
| 95 | + * @param int $id | ||
| 96 | + * @return \Illuminate\Http\Response | ||
| 97 | + */ | ||
| 98 | + public function show($project_id, $id) | ||
| 99 | + { | ||
| 100 | + $ticket = Tickets::with([ | ||
| 101 | + 'logs.engineer:id,name', | ||
| 102 | + 'project.projectV6:id,company', | ||
| 103 | + ]) | ||
| 104 | + ->find($id); | ||
| 105 | + | ||
| 106 | + if (!$ticket) return $this->error('工单未找到', 404); | ||
| 107 | + | ||
| 108 | + if ($ticket->project->uuid !== $project_id) return $this->error('无权限查看该工单', 403); | ||
| 109 | + | ||
| 110 | + if ($ticket->project->version == 6){ | ||
| 111 | + if ($ticket->project->projectV6->delete_status) return $this->error('该项目已被删除', 400); | ||
| 112 | + if ($ticket->project->projectV6->extend_type == 5) return $this->error('未续费', 400); | ||
| 113 | + if ($ticket->project->projectV6->type == 8) return $this->error('项目已归档', 400); | ||
| 114 | + if ($ticket->project->projectV6->site_status == 1) return $this->error('站点已关闭', 400); | ||
| 115 | + } | ||
| 116 | + return response()->json(['data' => $ticket]); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + /** | ||
| 120 | + * Update the specified resource in storage. | ||
| 121 | + * | ||
| 122 | + * @param \Illuminate\Http\Request $request | ||
| 123 | + * @param int $id | ||
| 124 | + * @return \Illuminate\Http\Response | ||
| 125 | + */ | ||
| 126 | + public function update(Request $request, $id) | ||
| 127 | + { | ||
| 128 | + // | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + /** | ||
| 132 | + * Remove the specified resource from storage. | ||
| 133 | + * | ||
| 134 | + * @param int $id | ||
| 135 | + * @return \Illuminate\Http\Response | ||
| 136 | + */ | ||
| 137 | + public function destroy($id) | ||
| 138 | + { | ||
| 139 | + // | ||
| 140 | + } | ||
| 141 | + | ||
| 142 | + public function projectInfo($project_id) | ||
| 143 | + { | ||
| 144 | + $project = TicketProject::with([ | ||
| 145 | + 'projectV6:id,company', | ||
| 146 | + 'assm:id,name', | ||
| 147 | + 'seom:id,name', | ||
| 148 | + 'first_engineer:id,name', | ||
| 149 | + ]) | ||
| 150 | + ->where('uuid', $project_id)->first(); | ||
| 151 | + if (!$project) return $this->error('未找到项目', 404); | ||
| 152 | + return response()->json(['data' => $project]); | ||
| 153 | + } | ||
| 154 | +} |
| @@ -12,10 +12,23 @@ namespace App\Http\Controllers\Aside\Com; | @@ -12,10 +12,23 @@ namespace App\Http\Controllers\Aside\Com; | ||
| 12 | 12 | ||
| 13 | use App\Enums\Common\Code; | 13 | use App\Enums\Common\Code; |
| 14 | use App\Http\Controllers\Aside\BaseController; | 14 | use App\Http\Controllers\Aside\BaseController; |
| 15 | +use App\Models\Blog\Blog; | ||
| 16 | +use App\Models\Blog\BlogCategory; | ||
| 17 | +use App\Models\CustomModule\CustomModuleCategory; | ||
| 18 | +use App\Models\CustomModule\CustomModuleContent; | ||
| 15 | use App\Models\Domain\DomainInfo; | 19 | use App\Models\Domain\DomainInfo; |
| 20 | +use App\Models\News\News; | ||
| 21 | +use App\Models\News\NewsCategory; | ||
| 22 | +use App\Models\Product\Category; | ||
| 23 | +use App\Models\Product\CategoryRelated; | ||
| 24 | +use App\Models\Product\Keyword; | ||
| 25 | +use App\Models\Product\Product; | ||
| 16 | use App\Models\Project\Country as CountryModel; | 26 | use App\Models\Project\Country as CountryModel; |
| 17 | use App\Models\Project\DeployBuild; | 27 | use App\Models\Project\DeployBuild; |
| 28 | +use App\Models\WebSetting\SettingNum; | ||
| 29 | +use App\Models\WebSetting\TranslateBigProject; | ||
| 18 | use App\Models\WebSetting\WebLanguage; | 30 | use App\Models\WebSetting\WebLanguage; |
| 31 | +use App\Services\ProjectServer; | ||
| 19 | use Illuminate\Http\Request; | 32 | use Illuminate\Http\Request; |
| 20 | use Illuminate\Support\Facades\DB; | 33 | use Illuminate\Support\Facades\DB; |
| 21 | 34 | ||
| @@ -30,6 +43,69 @@ use Illuminate\Support\Facades\DB; | @@ -30,6 +43,69 @@ use Illuminate\Support\Facades\DB; | ||
| 30 | class CNoticeController extends BaseController | 43 | class CNoticeController extends BaseController |
| 31 | { | 44 | { |
| 32 | /** | 45 | /** |
| 46 | + * @remark :计算页面数量 | ||
| 47 | + * @name :countLanguagePage | ||
| 48 | + * @author :lyh | ||
| 49 | + * @method :post | ||
| 50 | + * @time :2025/6/19 17:14 | ||
| 51 | + */ | ||
| 52 | + public function countLanguagePage(){ | ||
| 53 | + $this->request->validate([ | ||
| 54 | + 'language'=>'required', | ||
| 55 | + 'project_id'=>'required', | ||
| 56 | + ],[ | ||
| 57 | + 'language.required' => 'language不能为空', | ||
| 58 | + 'project_id.required' => 'project_id不能为空', | ||
| 59 | + ]); | ||
| 60 | + $bigProjectModel = new TranslateBigProject(); | ||
| 61 | + $project_id_arr = $bigProjectModel->selectField(['status'=>1],'project_id') ?? []; | ||
| 62 | + if(in_array($this->param['project_id'],$project_id_arr)){ | ||
| 63 | + $this->response('success'); | ||
| 64 | + } | ||
| 65 | + $lang_num = count($this->param['language']); | ||
| 66 | + ProjectServer::useProject($this->param['project_id']); | ||
| 67 | + $keyword_num = (new Keyword())->counts(['route'=>['!=',null]]); | ||
| 68 | + $data_num = $this->productNum() + $this->customNum() + $this->newsNum() + $this->blogNum(); | ||
| 69 | + DB::disconnect('custom_mysql'); | ||
| 70 | + $number = $keyword_num * 18 + $lang_num * $data_num; | ||
| 71 | + if($number >= 450000){ | ||
| 72 | + $this->response('success',Code::SUCCESS,['msg'=>'翻译数量过多, 大概页面数量:'.$number.', 磁盘空间占用可能会超过40G,请联系管理员操作!']); | ||
| 73 | + } | ||
| 74 | + $this->response('success'); | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + /** | ||
| 78 | + * @remark :产品分类页面数量 | ||
| 79 | + * @name :productCateNum | ||
| 80 | + * @author :lyh | ||
| 81 | + * @method :post | ||
| 82 | + * @time :2025/1/4 10:43 | ||
| 83 | + */ | ||
| 84 | + public function productNum(){ | ||
| 85 | + $number = (new Product())->counts(['status'=>1]); | ||
| 86 | + $settingModel = new SettingNum(); | ||
| 87 | + $info = $settingModel->read(['type'=>1]); | ||
| 88 | + if($info === false){ | ||
| 89 | + $product_page_number = 15; | ||
| 90 | + }else{ | ||
| 91 | + $product_page_number = $info['num']; | ||
| 92 | + } | ||
| 93 | + $productCateModel = new Category(); | ||
| 94 | + $productCateList = $productCateModel->list(['status'=>1]); | ||
| 95 | + if(!empty($productCateList)){ | ||
| 96 | + $cateReModel = new CategoryRelated(); | ||
| 97 | + foreach ($productCateList as $v){ | ||
| 98 | + $cate_num = $cateReModel->counts(['cate_id'=>$v['id']]); | ||
| 99 | + if($cate_num == 0){ | ||
| 100 | + $number += 1; | ||
| 101 | + }else{ | ||
| 102 | + $number += ceil($cate_num / $product_page_number); | ||
| 103 | + } | ||
| 104 | + } | ||
| 105 | + } | ||
| 106 | + return $number; | ||
| 107 | + } | ||
| 108 | + /** | ||
| 33 | * 更新通知C端 | 109 | * 更新通知C端 |
| 34 | * @param Request $request | 110 | * @param Request $request |
| 35 | * @return \Illuminate\Http\JsonResponse | 111 | * @return \Illuminate\Http\JsonResponse |
| @@ -58,8 +134,102 @@ class CNoticeController extends BaseController | @@ -58,8 +134,102 @@ class CNoticeController extends BaseController | ||
| 58 | http_post($url, json_encode($param)); | 134 | http_post($url, json_encode($param)); |
| 59 | $this->response('更新中请稍后, 更新完成将会发送站内信通知更新结果!'); | 135 | $this->response('更新中请稍后, 更新完成将会发送站内信通知更新结果!'); |
| 60 | } | 136 | } |
| 137 | + /** | ||
| 138 | + * @remark :新闻数量 | ||
| 139 | + * @name :newsNum | ||
| 140 | + * @author :lyh | ||
| 141 | + * @method :post | ||
| 142 | + * @time :2025/1/4 11:21 | ||
| 143 | + */ | ||
| 144 | + public function newsNum(){ | ||
| 145 | + $newsModel = new News(); | ||
| 146 | + $number = $newsModel->counts(['status'=>1]); | ||
| 147 | + $settingModel = new SettingNum(); | ||
| 148 | + $info = $settingModel->read(['type'=>2]); | ||
| 149 | + if($info === false){ | ||
| 150 | + $news_page_number = 10; | ||
| 151 | + }else{ | ||
| 152 | + $news_page_number = $info['num']; | ||
| 153 | + } | ||
| 154 | + $newsCateModel = new NewsCategory(); | ||
| 155 | + $newsCateList = $newsCateModel->list(['status'=>0]); | ||
| 156 | + if(!empty($newsCateList)){ | ||
| 157 | + foreach ($newsCateList as $v){ | ||
| 158 | + $cate_num = $newsModel->counts(['category_id'=>['like',','.$v['id'].',']]); | ||
| 159 | + if($cate_num == 0){ | ||
| 160 | + $number += 1; | ||
| 161 | + }else{ | ||
| 162 | + $number += ceil($cate_num / $news_page_number); | ||
| 163 | + } | ||
| 164 | + } | ||
| 165 | + } | ||
| 166 | + return $number; | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + /** | ||
| 170 | + * @remark :博客数量 | ||
| 171 | + * @name :blogNum | ||
| 172 | + * @author :lyh | ||
| 173 | + * @method :post | ||
| 174 | + * @time :2025/1/4 11:21 | ||
| 175 | + */ | ||
| 176 | + public function blogNum(){ | ||
| 177 | + $blogModel = new Blog(); | ||
| 178 | + $number = $blogModel->counts(['status'=>1]); | ||
| 179 | + $settingModel = new SettingNum(); | ||
| 180 | + $info = $settingModel->read(['type'=>3]); | ||
| 181 | + if($info === false){ | ||
| 182 | + $news_page_number = 10; | ||
| 183 | + }else{ | ||
| 184 | + $news_page_number = $info['num']; | ||
| 185 | + } | ||
| 186 | + $blogCateModel = new BlogCategory(); | ||
| 187 | + $blogCateList = $blogCateModel->list(['status'=>0]); | ||
| 188 | + if(!empty($blogCateList)){ | ||
| 189 | + foreach ($blogCateList as $v){ | ||
| 190 | + $cate_num = $blogModel->counts(['category_id'=>['like',','.$v['id'].',']]); | ||
| 191 | + if($cate_num == 0){ | ||
| 192 | + $number += 1; | ||
| 193 | + }else{ | ||
| 194 | + $number += ceil($cate_num / $news_page_number); | ||
| 195 | + } | ||
| 196 | + } | ||
| 197 | + } | ||
| 198 | + return $number; | ||
| 199 | + } | ||
| 61 | 200 | ||
| 62 | /** | 201 | /** |
| 202 | + * @remark :扩展模块数量 | ||
| 203 | + * @name :blogNum | ||
| 204 | + * @author :lyh | ||
| 205 | + * @method :post | ||
| 206 | + * @time :2025/1/4 11:21 | ||
| 207 | + */ | ||
| 208 | + public function customNum(){ | ||
| 209 | + $contentModel = new CustomModuleContent(); | ||
| 210 | + $number = $contentModel->counts(['status'=>0]); | ||
| 211 | + $settingModel = new SettingNum(); | ||
| 212 | + $info = $settingModel->read(['type'=>2]); | ||
| 213 | + if($info === false){ | ||
| 214 | + $news_page_number = 10; | ||
| 215 | + }else{ | ||
| 216 | + $news_page_number = $info['num']; | ||
| 217 | + } | ||
| 218 | + $cateModel = new CustomModuleCategory(); | ||
| 219 | + $cateList = $cateModel->list(['status'=>0]); | ||
| 220 | + if(!empty($cateList)){ | ||
| 221 | + foreach ($cateList as $v){ | ||
| 222 | + $cate_num = $contentModel->counts(['category_id'=>['like',','.$v['id'].',']]); | ||
| 223 | + if($cate_num == 0){ | ||
| 224 | + $number += 1; | ||
| 225 | + }else{ | ||
| 226 | + $number += ceil($cate_num / $news_page_number); | ||
| 227 | + } | ||
| 228 | + } | ||
| 229 | + } | ||
| 230 | + return $number; | ||
| 231 | + } | ||
| 232 | + /** | ||
| 63 | * @remark :获取当前项目选中的语种 | 233 | * @remark :获取当前项目选中的语种 |
| 64 | * @name :getCountry | 234 | * @name :getCountry |
| 65 | * @author :lyh | 235 | * @author :lyh |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace App\Http\Controllers\Aside\WorkOrder; | ||
| 4 | + | ||
| 5 | +use App\Enums\Common\Code; | ||
| 6 | +use App\Http\Controllers\Aside\BaseController; | ||
| 7 | +use App\Http\Requests\Aside\WorkOrder\AsideTicketStoreRequest; | ||
| 8 | +use App\Http\Requests\Aside\WorkOrder\AsideTicketListRequest; | ||
| 9 | +use App\Http\Requests\Aside\WorkOrder\AsideTicketUpdateRequest; | ||
| 10 | +use App\Models\WorkOrder\TicketLog; | ||
| 11 | +use App\Models\WorkOrder\TicketProject; | ||
| 12 | +use App\Models\WorkOrder\Tickets; | ||
| 13 | +use Illuminate\Support\Facades\DB; | ||
| 14 | + | ||
| 15 | +class AsideTicketController extends BaseController | ||
| 16 | +{ | ||
| 17 | + /** | ||
| 18 | + * Display a listing of the resource. | ||
| 19 | + * | ||
| 20 | + * @return \Illuminate\Http\Response | ||
| 21 | + */ | ||
| 22 | + public function index(AsideTicketListRequest $request) | ||
| 23 | + { | ||
| 24 | + /** | ||
| 25 | + * 1. 超管看所有工单 | ||
| 26 | + * 2. 其他查看和自己有关的工单 | ||
| 27 | + */ | ||
| 28 | + $lists = TicketLog::with([ | ||
| 29 | + 'ticket.project.projectV6:id,company,title', | ||
| 30 | + 'ticket.logs.engineer:id,name', | ||
| 31 | + ]) | ||
| 32 | + ->when($this, function ($query) { | ||
| 33 | + $role = $this->manage['role']; | ||
| 34 | + // 超管 role = 1 | ||
| 35 | + if ($role == 1) { | ||
| 36 | + return $query; | ||
| 37 | + } | ||
| 38 | + // 其他角色查自己参与的工单 | ||
| 39 | + return $query->where('engineer_id', $this->manage['id']); | ||
| 40 | + }) | ||
| 41 | + ->when($request->input('project_id') !== null, function ($query) use ($request) { | ||
| 42 | + // project_id 查 gl_ticket_projects.uuid | ||
| 43 | + return $query->whereHas('ticket.project', function ($q) use ($request) { | ||
| 44 | + $q->where('uuid', $request->input('project_id')); | ||
| 45 | + }); | ||
| 46 | + }) | ||
| 47 | + ->when($request->input('status') !== null, function ($query) use ($request) { | ||
| 48 | + // status 查 gl_tickets.status | ||
| 49 | + return $query->whereHas('ticket', function ($q) use ($request) { | ||
| 50 | + $q->where('status', $request->input('status')); | ||
| 51 | + }); | ||
| 52 | + }) | ||
| 53 | + ->when($request->input('search'), function ($query) use ($request) { | ||
| 54 | + // search 查 gl_tickets.title 或 gl_ticket_projects.title 或 gl_ticket_projects.company_name | ||
| 55 | + $search = $request->input('search'); | ||
| 56 | + $query->where(function ($q) use ($search) { | ||
| 57 | + $q->whereHas('ticket', function ($q1) use ($search) { | ||
| 58 | + $q1->where('title', 'like', '%' . $search . '%'); | ||
| 59 | + }) | ||
| 60 | + ->orWhereHas('ticket.project', function ($q2) use ($search) { | ||
| 61 | + $q2->where('title', 'like', '%' . $search . '%') | ||
| 62 | + ->orWhere('company_name', 'like', '%' . $search . '%'); | ||
| 63 | + }); | ||
| 64 | + }); | ||
| 65 | + }) | ||
| 66 | + ->orderBy('id', 'desc') | ||
| 67 | + ->paginate($this->row, ['*'], 'page', $this->page); | ||
| 68 | + $this->response('success', Code::SUCCESS, $lists); | ||
| 69 | + } | ||
| 70 | + | ||
| 71 | + public function getProjects($search) | ||
| 72 | + { | ||
| 73 | + $projects = TicketProject::with([ | ||
| 74 | + 'projectV6:id,company,title', | ||
| 75 | + ]) | ||
| 76 | + ->where(function ($query) use ($search) { | ||
| 77 | + $query->where('title', 'like', '%' . $search . '%') | ||
| 78 | + ->orWhere('company_name', 'like', '%' . $search . '%') | ||
| 79 | + ->orWhereHas('projectV6', function ($q) use ($search) { | ||
| 80 | + $q->where('company', 'like', '%' . $search . '%') | ||
| 81 | + ->orWhere('title', 'like', '%' . $search . '%'); | ||
| 82 | + }); | ||
| 83 | + }) | ||
| 84 | + ->get(); | ||
| 85 | + $this->response('success', Code::SUCCESS, $projects); | ||
| 86 | + } | ||
| 87 | + | ||
| 88 | + /** | ||
| 89 | + * Store a newly created resource in storage. | ||
| 90 | + * | ||
| 91 | + * @param \Illuminate\Http\Request $request | ||
| 92 | + * @return \Illuminate\Http\Response | ||
| 93 | + */ | ||
| 94 | + public function store(AsideTicketStoreRequest $request) | ||
| 95 | + { | ||
| 96 | + $request->validated(); | ||
| 97 | + $project = TicketProject::where('uuid', $request->input('project_id'))->first(); | ||
| 98 | + if ($project->version == 6){ | ||
| 99 | + if ($project->projectV6->delete_status) $this->response('该项目已被删除', Code::USER_MODEL_NOTFOUND_ERROE); | ||
| 100 | + if ($project->projectV6->extend_type == 5) $this->response('未续费', Code::USER_MODEL_NOTFOUND_ERROE); | ||
| 101 | + if ($project->projectV6->type == 8) $this->response('项目已归档', Code::USER_MODEL_NOTFOUND_ERROE); | ||
| 102 | + if ($project->projectV6->site_status == 1) $this->response('站点已关闭', Code::USER_MODEL_NOTFOUND_ERROE); | ||
| 103 | + } | ||
| 104 | + $result = DB::transaction(function () use ($request, $project) { | ||
| 105 | + $ticket = new Tickets(); | ||
| 106 | + $ticket->project_id = $project->id; | ||
| 107 | + $ticket->title = $request->input('title'); | ||
| 108 | + $ticket->content = $request->input('content'); | ||
| 109 | + // $files = [NULL] | ||
| 110 | + $files = $request->input('files'); | ||
| 111 | + if (empty($files) || (is_array($files) && count(array_filter($files, function($v){ return !is_null($v); })) === 0)) { | ||
| 112 | + $ticket->files = null; | ||
| 113 | + } else { | ||
| 114 | + $ticket->files = json_encode($files); | ||
| 115 | + } | ||
| 116 | + $ticket->submit_side = 1; // 1 for A-side submission | ||
| 117 | + $ticket->submit_user_id = $this->manage['id']; | ||
| 118 | + $ticket->submit_username = $this->manage['name']; | ||
| 119 | + $ticket->save(); | ||
| 120 | + // A 端提工单,都是针对客户提的需求等开发任务;比如翻译,修改页面等。。。 | ||
| 121 | + foreach ($request->input('engineer_ids', []) as $engineer_id) { | ||
| 122 | + $log = new TicketLog(); | ||
| 123 | + $log->engineer_id = $engineer_id; | ||
| 124 | + $ticket->logs()->save($log); | ||
| 125 | + } | ||
| 126 | + return $ticket; | ||
| 127 | + }); | ||
| 128 | + $this->response('success', Code::SUCCESS, $result->toArray()); | ||
| 129 | + } | ||
| 130 | + | ||
| 131 | + /** | ||
| 132 | + * Display the specified resource. | ||
| 133 | + * | ||
| 134 | + * @param int $id | ||
| 135 | + * @return \Illuminate\Http\Response | ||
| 136 | + */ | ||
| 137 | + public function show($id) | ||
| 138 | + { | ||
| 139 | + $ticket = Tickets::with([ | ||
| 140 | + 'logs.engineer', | ||
| 141 | + 'project.projectV6:id,company,title', | ||
| 142 | + ])->find($id); | ||
| 143 | + | ||
| 144 | + if (!$ticket) $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE); | ||
| 145 | + | ||
| 146 | + if ($this->manage['role'] != 1 | ||
| 147 | + && $ticket->submit_user_id != $this->manage['id'] | ||
| 148 | + && $ticket->logs()->where('engineer_id', $this->manage['id'])->count() == 0) | ||
| 149 | + // 只能查看自己的工单 | ||
| 150 | + $this->response('没有权限查看该工单', Code::USER_PERMISSION_ERROE); | ||
| 151 | + | ||
| 152 | + // TODO 判断是否有查看工单详情权限,待添加 | ||
| 153 | + $this->response('success', Code::SUCCESS, $ticket->toArray()); | ||
| 154 | + } | ||
| 155 | + | ||
| 156 | + /** | ||
| 157 | + * A端修改工单 | ||
| 158 | + * 1. 邀请协同的同事 | ||
| 159 | + * 2. 审核工单 | ||
| 160 | + */ | ||
| 161 | + public function update(AsideTicketUpdateRequest $request, $id) | ||
| 162 | + { | ||
| 163 | + $request->validated(); | ||
| 164 | + $ticket = Tickets::find($id); | ||
| 165 | + if (!$ticket) $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE); | ||
| 166 | + // 检测修改权限 | ||
| 167 | + if ($ticket->submit_side == 1 && $ticket->submit_user_id != $this->manage['id']) { | ||
| 168 | + // A端提交的工单,只有提交人可以修改 | ||
| 169 | + $this->response('没有权限操作该工单', Code::USER_PERMISSION_ERROE); | ||
| 170 | + } elseif ($ticket->submit_side == 2) | ||
| 171 | + { | ||
| 172 | + // B端提交的工单,只有第一对接人可以修改 | ||
| 173 | + $log = $ticket->logs()->first(); | ||
| 174 | + if ($log->engineer_id != $this->manage['id']) | ||
| 175 | + $this->response('没有权限操作该工单', Code::USER_PERMISSION_ERROE); | ||
| 176 | + } | ||
| 177 | + | ||
| 178 | + // 开始修改 | ||
| 179 | + $result = DB::transaction(function () use ($request, $ticket) { | ||
| 180 | + if ($request->input('engineer_ids')) | ||
| 181 | + { | ||
| 182 | + // 有邀请工程师协同处理 | ||
| 183 | + foreach ($request->input('engineer_ids') as $engineer_id) | ||
| 184 | + { | ||
| 185 | + try { | ||
| 186 | + // 利用唯一索引去重 | ||
| 187 | + $new_log = new TicketLog(); | ||
| 188 | + $new_log->engineer_id = $engineer_id; | ||
| 189 | + $ticket->logs()->save($new_log); | ||
| 190 | + }catch (\Exception $exception){} | ||
| 191 | + } | ||
| 192 | + } | ||
| 193 | + | ||
| 194 | + $ticket->reply = $request->input('reply', null); | ||
| 195 | + $ticket->status = $request->input('status', $ticket->status); | ||
| 196 | + $ticket->save(); | ||
| 197 | + if ($ticket->status == Tickets::STATUS_COMPLETED) | ||
| 198 | + { | ||
| 199 | + // 完成工单,把子任务里面未完成的工单改为完成 | ||
| 200 | + $ticket->end_at = now(); | ||
| 201 | + $ticket->logs()->where('status', '<', TicketLog::STATUS_COMPLETED) | ||
| 202 | + ->update(['status' => TicketLog::STATUS_COMPLETED, 'end_at' => now()]); | ||
| 203 | + } | ||
| 204 | + return $ticket; | ||
| 205 | + }); | ||
| 206 | + $this->response('success', Code::SUCCESS, $result->toArray()); | ||
| 207 | + } | ||
| 208 | + | ||
| 209 | + /** | ||
| 210 | + * Remove the specified resource from storage. | ||
| 211 | + * | ||
| 212 | + * @param int $id | ||
| 213 | + * @return \Illuminate\Http\Response | ||
| 214 | + */ | ||
| 215 | + public function destroy($id) | ||
| 216 | + { | ||
| 217 | + // | ||
| 218 | + } | ||
| 219 | +} |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace App\Http\Controllers\Aside\WorkOrder; | ||
| 4 | + | ||
| 5 | +use App\Enums\Common\Code; | ||
| 6 | +use App\Http\Controllers\Aside\BaseController; | ||
| 7 | +use App\Http\Requests\Aside\WorkOrder\AsideTicketLogUpdateRequest; | ||
| 8 | +use App\Models\WorkOrder\TicketLog; | ||
| 9 | +use App\Models\WorkOrder\Tickets; | ||
| 10 | +use Illuminate\Http\Request; | ||
| 11 | +use Illuminate\Support\Facades\DB; | ||
| 12 | + | ||
| 13 | +class AsideTicketLogController extends BaseController | ||
| 14 | +{ | ||
| 15 | + /** | ||
| 16 | + * Display a listing of the resource. | ||
| 17 | + * | ||
| 18 | + * @return \Illuminate\Http\Response | ||
| 19 | + */ | ||
| 20 | + public function index() | ||
| 21 | + { | ||
| 22 | + // | ||
| 23 | + } | ||
| 24 | + | ||
| 25 | + /** | ||
| 26 | + * Store a newly created resource in storage. | ||
| 27 | + * | ||
| 28 | + * @param \Illuminate\Http\Request $request | ||
| 29 | + * @return \Illuminate\Http\Response | ||
| 30 | + */ | ||
| 31 | + public function store(Request $request) | ||
| 32 | + { | ||
| 33 | + // | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * Display the specified resource. | ||
| 38 | + * | ||
| 39 | + * @param int $id | ||
| 40 | + * @return \Illuminate\Http\Response | ||
| 41 | + */ | ||
| 42 | + public function show($id) | ||
| 43 | + { | ||
| 44 | + // | ||
| 45 | + } | ||
| 46 | + | ||
| 47 | + /** | ||
| 48 | + * A 端完结工单任务 | ||
| 49 | + */ | ||
| 50 | + public function update(AsideTicketLogUpdateRequest $request, $id) | ||
| 51 | + { | ||
| 52 | + $log = TicketLog::find($id); // 拆分的子工单 | ||
| 53 | + if (!$log) { | ||
| 54 | + $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE); | ||
| 55 | + } | ||
| 56 | + if ($log->engineer_id != $this->manage['id']) { | ||
| 57 | + // 只能操作自己的工单 | ||
| 58 | + $this->response('没有权限操作该工单', Code::USER_PERMISSION_ERROE); | ||
| 59 | + } | ||
| 60 | + if ($log->status >= TicketLog::STATUS_COMPLETED) { | ||
| 61 | + // 已经完成的工单不能再操作 | ||
| 62 | + $this->response('工单已完成,不能再操作', Code::USER_PERMISSION_ERROE); | ||
| 63 | + } | ||
| 64 | + $ticket = $log->ticket; | ||
| 65 | + $result = DB::transaction(function () use ($request, $ticket, $log) { | ||
| 66 | + if ($request->input('status') !== null) | ||
| 67 | + { | ||
| 68 | + $log->status = $request->input('status'); | ||
| 69 | + if ($log->status >= TicketLog::STATUS_COMPLETED) | ||
| 70 | + { | ||
| 71 | + // 我的工单标记为已完成 | ||
| 72 | + $log->status = $request->input('status'); | ||
| 73 | + $log->end_at = now(); | ||
| 74 | + } | ||
| 75 | + } | ||
| 76 | + $log->save(); | ||
| 77 | + // 是否有未完成的子任务 | ||
| 78 | + $pending = $ticket->logs() | ||
| 79 | + ->where('status', '<', TicketLog::STATUS_COMPLETED) | ||
| 80 | + ->count(); | ||
| 81 | + if ($pending) | ||
| 82 | + { | ||
| 83 | + $ticket->status = Tickets::STATUS_PROCESSING; | ||
| 84 | + }else | ||
| 85 | + { | ||
| 86 | + $ticket->status = Tickets::STATUS_COMPLETED; | ||
| 87 | + // 如果所有子任务都完成了,则将工单状态改为已完成 | ||
| 88 | + $ticket->end_at = now(); | ||
| 89 | + } | ||
| 90 | + $ticket->save(); | ||
| 91 | + return $log; | ||
| 92 | + }); | ||
| 93 | + $this->response('success', Code::SUCCESS, $result->toArray()); | ||
| 94 | + | ||
| 95 | + } | ||
| 96 | + | ||
| 97 | + /** | ||
| 98 | + * Remove the specified resource from storage. | ||
| 99 | + * | ||
| 100 | + * @param int $id | ||
| 101 | + * @return \Illuminate\Http\Response | ||
| 102 | + */ | ||
| 103 | + public function destroy($id) | ||
| 104 | + { | ||
| 105 | + // | ||
| 106 | + } | ||
| 107 | +} |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace App\Http\Requests\Api\WorkOrder; | ||
| 4 | + | ||
| 5 | +use Illuminate\Foundation\Http\FormRequest; | ||
| 6 | + | ||
| 7 | +class TicketStoreRequest extends FormRequest | ||
| 8 | +{ | ||
| 9 | + /** | ||
| 10 | + * Determine if the user is authorized to make this request. | ||
| 11 | + * | ||
| 12 | + * @return bool | ||
| 13 | + */ | ||
| 14 | + public function authorize() | ||
| 15 | + { | ||
| 16 | + return true; | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * Get the validation rules that apply to the request. | ||
| 21 | + * | ||
| 22 | + * @return array | ||
| 23 | + */ | ||
| 24 | + public function rules() | ||
| 25 | + { | ||
| 26 | + return [ | ||
| 27 | + 'title' => 'required|string', | ||
| 28 | + 'content' => 'required|string', | ||
| 29 | + 'files' => 'nullable|array', | ||
| 30 | + 'submit_username' => 'required|string', | ||
| 31 | + ]; | ||
| 32 | + } | ||
| 33 | +} |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace App\Http\Requests\Aside\WorkOrder; | ||
| 4 | + | ||
| 5 | +use Illuminate\Foundation\Http\FormRequest; | ||
| 6 | + | ||
| 7 | +class AsideTicketListRequest extends FormRequest | ||
| 8 | +{ | ||
| 9 | + /** | ||
| 10 | + * Determine if the user is authorized to make this request. | ||
| 11 | + * | ||
| 12 | + * @return bool | ||
| 13 | + */ | ||
| 14 | + public function authorize() | ||
| 15 | + { | ||
| 16 | + return true; | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * Get the validation rules that apply to the request. | ||
| 21 | + * | ||
| 22 | + * @return array | ||
| 23 | + */ | ||
| 24 | + public function rules() | ||
| 25 | + { | ||
| 26 | + return [ | ||
| 27 | + 'project_id' => 'nullable|string', // 产品ID | ||
| 28 | + 'status' => 'nullable|in:0,1,2,3|integer', | ||
| 29 | + 'search' => 'nullable|string', // 搜索关键词 | ||
| 30 | + 'page' => 'nullable|integer', | ||
| 31 | + 'size' => 'nullable|integer', | ||
| 32 | + ]; | ||
| 33 | + } | ||
| 34 | +} |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace App\Http\Requests\Aside\WorkOrder; | ||
| 4 | + | ||
| 5 | +use Illuminate\Foundation\Http\FormRequest; | ||
| 6 | + | ||
| 7 | +class AsideTicketLogUpdateRequest extends FormRequest | ||
| 8 | +{ | ||
| 9 | + /** | ||
| 10 | + * Determine if the user is authorized to make this request. | ||
| 11 | + * | ||
| 12 | + * @return bool | ||
| 13 | + */ | ||
| 14 | + public function authorize() | ||
| 15 | + { | ||
| 16 | + return true; | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * Get the validation rules that apply to the request. | ||
| 21 | + * | ||
| 22 | + * @return array | ||
| 23 | + */ | ||
| 24 | + public function rules() | ||
| 25 | + { | ||
| 26 | + return [ | ||
| 27 | + 'status' => 'required|in:0,1,2,3|integer', | ||
| 28 | + 'reply' => 'nullable|string', | ||
| 29 | + ]; | ||
| 30 | + } | ||
| 31 | +} |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace App\Http\Requests\Aside\WorkOrder; | ||
| 4 | + | ||
| 5 | +use Illuminate\Foundation\Http\FormRequest; | ||
| 6 | + | ||
| 7 | +class AsideTicketStoreRequest extends FormRequest | ||
| 8 | +{ | ||
| 9 | + /** | ||
| 10 | + * Determine if the user is authorized to make this request. | ||
| 11 | + * | ||
| 12 | + * @return bool | ||
| 13 | + */ | ||
| 14 | + public function authorize() | ||
| 15 | + { | ||
| 16 | + return true; | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * Get the validation rules that apply to the request. | ||
| 21 | + * | ||
| 22 | + * @return array | ||
| 23 | + */ | ||
| 24 | + public function rules() | ||
| 25 | + { | ||
| 26 | + return [ | ||
| 27 | + 'project_id' => 'required|exists:gl_ticket_projects,uuid', | ||
| 28 | + 'title' => 'required|string', | ||
| 29 | + 'content' => 'required|string', | ||
| 30 | + 'files' => 'nullable|array', | ||
| 31 | + 'engineer_ids' => 'array', | ||
| 32 | + ]; | ||
| 33 | + } | ||
| 34 | +} |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace App\Http\Requests\Aside\WorkOrder; | ||
| 4 | + | ||
| 5 | +use Illuminate\Foundation\Http\FormRequest; | ||
| 6 | + | ||
| 7 | +class AsideTicketUpdateRequest extends FormRequest | ||
| 8 | +{ | ||
| 9 | + /** | ||
| 10 | + * Determine if the user is authorized to make this request. | ||
| 11 | + * | ||
| 12 | + * @return bool | ||
| 13 | + */ | ||
| 14 | + public function authorize() | ||
| 15 | + { | ||
| 16 | + return true; | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * Get the validation rules that apply to the request. | ||
| 21 | + * | ||
| 22 | + * @return array | ||
| 23 | + */ | ||
| 24 | + public function rules() | ||
| 25 | + { | ||
| 26 | + return [ | ||
| 27 | + 'status' => 'nullable|in:0,1,2,3|integer', | ||
| 28 | + 'reply' => 'nullable|string', | ||
| 29 | + 'engineer_ids' => 'nullable|array', | ||
| 30 | + ]; | ||
| 31 | + } | ||
| 32 | +} |
app/Models/WorkOrder/TicketLog.php
0 → 100644
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace App\Models\WorkOrder; | ||
| 4 | + | ||
| 5 | +use App\Models\Base; | ||
| 6 | +use App\Models\Manage\Manage; | ||
| 7 | +use Illuminate\Database\Eloquent\Factories\HasFactory; | ||
| 8 | + | ||
| 9 | +class TicketLog extends Base | ||
| 10 | +{ | ||
| 11 | + use HasFactory; | ||
| 12 | + | ||
| 13 | + protected $table = 'gl_ticket_logs'; | ||
| 14 | + | ||
| 15 | + const STATUS_PEDDING = 0; // 待处理 | ||
| 16 | + const STATUS_PROCESSING = 1; // 处理中 | ||
| 17 | + const STATUS_COMPLETED = 2; // 已完成 | ||
| 18 | + const STATUS_CLOSED = 3; // 已关闭 | ||
| 19 | + | ||
| 20 | + public function engineer() | ||
| 21 | + { | ||
| 22 | + return $this->belongsTo(Manage::class, 'engineer_id', 'id') | ||
| 23 | + ->select(['id', 'name']); | ||
| 24 | + } | ||
| 25 | + | ||
| 26 | + public function ticket() | ||
| 27 | + { | ||
| 28 | + return $this->belongsTo(Tickets::class, 'ticket_id', 'id'); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | +} |
app/Models/WorkOrder/TicketProject.php
0 → 100644
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace App\Models\WorkOrder; | ||
| 4 | + | ||
| 5 | +use App\Models\Base; | ||
| 6 | +use App\Models\Manage\Manage; | ||
| 7 | +use App\Models\Project\Project; | ||
| 8 | +use Illuminate\Database\Eloquent\Factories\HasFactory; | ||
| 9 | + | ||
| 10 | +class TicketProject extends Base | ||
| 11 | +{ | ||
| 12 | + use HasFactory; | ||
| 13 | + | ||
| 14 | + protected $table = 'gl_ticket_projects'; | ||
| 15 | + | ||
| 16 | + public function projectV6() | ||
| 17 | + { | ||
| 18 | + return $this->hasOne(Project::class, 'id', 'table_id') | ||
| 19 | + ->where('version', 6); | ||
| 20 | + } | ||
| 21 | + | ||
| 22 | + //售后服务经理 | ||
| 23 | + public function assm() | ||
| 24 | + { | ||
| 25 | + return $this->hasOne(Manage::class, 'id', 'assm_id') | ||
| 26 | + ->select(['id', 'name']); | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + // 优化师 | ||
| 30 | + public function seom() | ||
| 31 | + { | ||
| 32 | + return $this->hasOne(Manage::class, 'id', 'seom_id') | ||
| 33 | + ->select(['id', 'name']); | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + /** | ||
| 37 | + * 第一负责人 | ||
| 38 | + */ | ||
| 39 | + public function first_engineer() | ||
| 40 | + { | ||
| 41 | + return $this->hasOne(Manage::class, 'id', 'engineer_id') | ||
| 42 | + ->select(['id', 'name']); | ||
| 43 | + } | ||
| 44 | +} |
app/Models/WorkOrder/Tickets.php
0 → 100644
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +namespace App\Models\WorkOrder; | ||
| 4 | + | ||
| 5 | +use App\Models\Base; | ||
| 6 | +use Illuminate\Database\Eloquent\Factories\HasFactory; | ||
| 7 | + | ||
| 8 | +class Tickets extends Base | ||
| 9 | +{ | ||
| 10 | + use HasFactory; | ||
| 11 | + | ||
| 12 | + protected $table = 'gl_tickets'; | ||
| 13 | + | ||
| 14 | + const STATUS_PEDDING = 0; // 待处理 | ||
| 15 | + const STATUS_PROCESSING = 1; // 处理中 | ||
| 16 | + const STATUS_COMPLETED = 2; // 已完成 | ||
| 17 | + const STATUS_CLOSED = 3; // 已关闭 | ||
| 18 | + | ||
| 19 | + /** | ||
| 20 | + * @return void | ||
| 21 | + * 关联的工单日志 | ||
| 22 | + */ | ||
| 23 | + public function logs() | ||
| 24 | + { | ||
| 25 | + return $this->hasMany(TicketLog::class, 'ticket_id', 'id'); | ||
| 26 | + } | ||
| 27 | + | ||
| 28 | + /** | ||
| 29 | + * 关联项目 | ||
| 30 | + */ | ||
| 31 | + public function project() | ||
| 32 | + { | ||
| 33 | + return $this->belongsTo(TicketProject::class, 'project_id', 'id'); | ||
| 34 | + } | ||
| 35 | +} |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +use Illuminate\Database\Migrations\Migration; | ||
| 4 | +use Illuminate\Database\Schema\Blueprint; | ||
| 5 | +use Illuminate\Support\Facades\Schema; | ||
| 6 | + | ||
| 7 | +class CreateTicketProjectsTable extends Migration | ||
| 8 | +{ | ||
| 9 | + /** | ||
| 10 | + * Run the migrations. | ||
| 11 | + * | ||
| 12 | + * @return void | ||
| 13 | + */ | ||
| 14 | + public function up() | ||
| 15 | + { | ||
| 16 | + Schema::create('gl_ticket_projects', function (Blueprint $table) { | ||
| 17 | + $table->id(); | ||
| 18 | + $table->integer('post_id')->index(); | ||
| 19 | + $table->integer('version')->default(5)->comment('版本号: 5, 6'); | ||
| 20 | + $table->integer('table_id')->index()->comment('来源表ID'); | ||
| 21 | + $table->string('uuid', 32)->unique()->comment('项目链接唯一标识符'); | ||
| 22 | + $table->string('company_name')->nullable()->index()->comment('公司名称'); | ||
| 23 | + $table->string('title')->nullable()->index()->comment('项目标题'); | ||
| 24 | + $table->bigInteger('engineer_id')->default(0)->index()->comment('V5项目的第一负责人 gl_manage 表ID'); | ||
| 25 | + $table->string('website')->nullable()->index()->comment('站点域名'); | ||
| 26 | + $table->timestamps(); | ||
| 27 | + }); | ||
| 28 | + \Illuminate\Support\Facades\DB::statement("ALTER TABLE `gl_ticket_projects` comment '售后工单项目整合表V5,V6'"); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * Reverse the migrations. | ||
| 33 | + * | ||
| 34 | + * @return void | ||
| 35 | + */ | ||
| 36 | + public function down() | ||
| 37 | + { | ||
| 38 | + Schema::dropIfExists('gl_ticket_projects'); | ||
| 39 | + } | ||
| 40 | +} |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +use Illuminate\Database\Migrations\Migration; | ||
| 4 | +use Illuminate\Database\Schema\Blueprint; | ||
| 5 | +use Illuminate\Support\Facades\Schema; | ||
| 6 | + | ||
| 7 | +class CreateTicketsTable extends Migration | ||
| 8 | +{ | ||
| 9 | + /** | ||
| 10 | + * Run the migrations. | ||
| 11 | + * | ||
| 12 | + * @return void | ||
| 13 | + */ | ||
| 14 | + public function up() | ||
| 15 | + { | ||
| 16 | + Schema::create('gl_tickets', function (Blueprint $table) { | ||
| 17 | + $table->id(); | ||
| 18 | + $table->foreignId('project_id')->constrained('gl_ticket_projects')->onDelete('cascade')->comment('项目ID'); | ||
| 19 | + $table->string('title')->nullable()->comment('工单类型,工单标题'); | ||
| 20 | + $table->longText('content')->comment('工单图文描述'); | ||
| 21 | + $table->json('files')->nullable()->comment('附件'); | ||
| 22 | + $table->integer('status')->index()->default(0)->comment('工单状态,0:待处理, 1:处理中,2:已完成, 3:已关闭'); | ||
| 23 | + $table->integer('submit_side')->default(1)->index()->comment('提交方,1: A端, 2: B端'); | ||
| 24 | + $table->string('submit_username')->nullable()->comment('提交人姓名,B端在企微群提交时,留个姓名即可'); | ||
| 25 | + $table->integer('submit_user_id')->default(0)->index()->comment('A端提交时,提交人 gl_manage ID'); | ||
| 26 | + $table->timestamp('end_at')->nullable()->comment('结束时间,工单状态为已完成或已关闭时有值'); | ||
| 27 | + $table->longText('reply')->nullable()->comment('回复内容,审核意见,可以为空'); | ||
| 28 | + $table->timestamps(); | ||
| 29 | + }); | ||
| 30 | + \Illuminate\Support\Facades\DB::statement("ALTER TABLE `gl_tickets` comment '工单表,注意:B端,A端都会提工单'"); | ||
| 31 | + } | ||
| 32 | + | ||
| 33 | + /** | ||
| 34 | + * Reverse the migrations. | ||
| 35 | + * | ||
| 36 | + * @return void | ||
| 37 | + */ | ||
| 38 | + public function down() | ||
| 39 | + { | ||
| 40 | + Schema::dropIfExists('gl_tickets'); | ||
| 41 | + } | ||
| 42 | +} |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | +use Illuminate\Database\Migrations\Migration; | ||
| 4 | +use Illuminate\Database\Schema\Blueprint; | ||
| 5 | +use Illuminate\Support\Facades\Schema; | ||
| 6 | + | ||
| 7 | +class CreateTicketLogsTable extends Migration | ||
| 8 | +{ | ||
| 9 | + /** | ||
| 10 | + * Run the migrations. | ||
| 11 | + * | ||
| 12 | + * @return void | ||
| 13 | + */ | ||
| 14 | + public function up() | ||
| 15 | + { | ||
| 16 | + Schema::create('gl_ticket_logs', function (Blueprint $table) { | ||
| 17 | + $table->id(); | ||
| 18 | + $table->foreignId('ticket_id')->constrained('gl_tickets')->onDelete('cascade')->comment('工单ID'); | ||
| 19 | + $table->unsignedInteger('engineer_id')->comment('处理人 gl_manage ID'); | ||
| 20 | + $table->foreign('engineer_id')->references('id')->on('gl_manage')->onDelete('cascade'); | ||
| 21 | + $table->longText('reply')->nullable()->comment('回复内容可以为空'); | ||
| 22 | + $table->integer('status')->default(0)->index()->comment('工单状态,0:待处理, 1:处理中,2:已完成, 3:已关闭'); | ||
| 23 | + $table->boolean('ding')->default(false)->index()->comment('钉钉通知'); | ||
| 24 | + $table->timestamp('end_at')->nullable()->comment('结束时间,工单状态为已完成或已关闭时有值'); | ||
| 25 | + $table->unique(['ticket_id', 'engineer_id'], 'ticket_engineer_unique'); # 唯一索引,防止同一工单被同一人多次操作,同一工单,可以多人协作 | ||
| 26 | + $table->timestamps(); | ||
| 27 | + }); | ||
| 28 | + \Illuminate\Support\Facades\DB::statement("ALTER TABLE `gl_ticket_logs` comment '工单操作日志表,记录工单的分配处理任务等'"); | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + /** | ||
| 32 | + * Reverse the migrations. | ||
| 33 | + * | ||
| 34 | + * @return void | ||
| 35 | + */ | ||
| 36 | + public function down() | ||
| 37 | + { | ||
| 38 | + Schema::dropIfExists('gl_ticket_logs'); | ||
| 39 | + } | ||
| 40 | +} |
| @@ -75,4 +75,12 @@ Route::post('/inquiry_relate_domain', [\App\Http\Controllers\Api\PrivateControll | @@ -75,4 +75,12 @@ Route::post('/inquiry_relate_domain', [\App\Http\Controllers\Api\PrivateControll | ||
| 75 | Route::get('/get_manage_by_domain', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectManageByDomain']); | 75 | Route::get('/get_manage_by_domain', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectManageByDomain']); |
| 76 | 76 | ||
| 77 | // 获取信息通过商户号 | 77 | // 获取信息通过商户号 |
| 78 | -Route::any('/get_project_by_mch_id', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectByMchId']); | ||
| 78 | +Route::any('/get_project_by_mch_id', [\App\Http\Controllers\Api\PrivateController::class, 'getProjectByMchId']); | ||
| 79 | + | ||
| 80 | +// B端,渠道在企微群操作-售后工单 | ||
| 81 | +Route::prefix('tickets')->group(function () { | ||
| 82 | + Route::get('/{project_id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'index'])->summary('B端,渠道-工单列表')->name('tickets.list'); | ||
| 83 | + Route::get('/projectInfo/{project_id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'projectInfo'])->summary('B端,渠道-项目信息')->name('tickets.projectInfo'); | ||
| 84 | + Route::post('/{project_id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'store'])->summary('B端,渠道-提工单')->name('tickets.store'); | ||
| 85 | + Route::get('/{project_id}/{id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'show'])->summary('B端,渠道-工单详情')->name('tickets.show'); | ||
| 86 | +}); |
| @@ -15,6 +15,7 @@ Route::middleware(['aloginauth'])->group(function () { | @@ -15,6 +15,7 @@ Route::middleware(['aloginauth'])->group(function () { | ||
| 15 | Route::any('/logout', [Aside\LoginController::class, 'logout'])->name('admin.logout.white'); | 15 | Route::any('/logout', [Aside\LoginController::class, 'logout'])->name('admin.logout.white'); |
| 16 | Route::any('/getAccessAddress', [Aside\LoginController::class, 'getAccessAddress'])->name('admin.getAccessAddress');//获取B端地址 | 16 | Route::any('/getAccessAddress', [Aside\LoginController::class, 'getAccessAddress'])->name('admin.getAccessAddress');//获取B端地址 |
| 17 | Route::any('/sendNotify', [Aside\Com\CNoticeController::class, 'sendNotify'])->name('admin.sendNotify'); | 17 | Route::any('/sendNotify', [Aside\Com\CNoticeController::class, 'sendNotify'])->name('admin.sendNotify'); |
| 18 | + Route::any('/countLanguagePage', [Aside\Com\CNoticeController::class, 'countLanguagePage'])->name('admin.countLanguagePage');//统计页面数量 | ||
| 18 | Route::any('/getCountry', [Aside\Com\CNoticeController::class, 'getCountry'])->name('admin.getCountry'); | 19 | Route::any('/getCountry', [Aside\Com\CNoticeController::class, 'getCountry'])->name('admin.getCountry'); |
| 19 | Route::any('/getDynamicPassword', [Aside\Com\IndexController::class, 'getDynamicPassword'])->name('admin.getDynamicPassword'); | 20 | Route::any('/getDynamicPassword', [Aside\Com\IndexController::class, 'getDynamicPassword'])->name('admin.getDynamicPassword'); |
| 20 | Route::any('/notAiHumanizer', [Aside\Com\IndexController::class, 'notAiHumanizer'])->name('admin.notAiHumanizer'); | 21 | Route::any('/notAiHumanizer', [Aside\Com\IndexController::class, 'notAiHumanizer'])->name('admin.notAiHumanizer'); |
| @@ -255,6 +256,16 @@ Route::middleware(['aloginauth'])->group(function () { | @@ -255,6 +256,16 @@ Route::middleware(['aloginauth'])->group(function () { | ||
| 255 | Route::get('/{id}', [Aside\WorkOrder\WorkOrderController::class, 'show'])->name('admin.workorder.show')->summary('A端工单详情'); | 256 | Route::get('/{id}', [Aside\WorkOrder\WorkOrderController::class, 'show'])->name('admin.workorder.show')->summary('A端工单详情'); |
| 256 | Route::post('/{id}', [Aside\WorkOrder\WorkOrderController::class, 'update'])->name('admin.workorder.update')->summary('A端更新工单'); | 257 | Route::post('/{id}', [Aside\WorkOrder\WorkOrderController::class, 'update'])->name('admin.workorder.update')->summary('A端更新工单'); |
| 257 | }); | 258 | }); |
| 259 | + // 售后工单改版 | ||
| 260 | + Route::prefix('tickets')->group(function () { | ||
| 261 | + Route::get('/', [Aside\WorkOrder\AsideTicketController::class, 'index'])->name('admin.tickets.index')->summary('A端工单列表'); | ||
| 262 | + Route::post('/', [Aside\WorkOrder\AsideTicketController::class, 'store'])->name('admin.tickets.store')->summary('A端创建工单'); | ||
| 263 | + Route::get('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'show'])->name('admin.tickets.show')->summary('A端工单详情'); | ||
| 264 | + Route::post('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'update'])->name('admin.tickets.update')->summary('A端更新工单,审核,邀请同事'); | ||
| 265 | + Route::get('/projects/{search}', [Aside\WorkOrder\AsideTicketController::class, 'getProjects'])->name('admin.tickets.projects')->summary('A端V5V6项目列表'); | ||
| 266 | + Route::post('/log/{id}', [Aside\WorkOrder\AsideTicketLogController::class, 'update'])->name('admin.tickets.log.update')->summary('A端工单操作日志更新,完成工单'); | ||
| 267 | + }); | ||
| 268 | + | ||
| 258 | //服务器配置 | 269 | //服务器配置 |
| 259 | Route::prefix('devops')->group(function () { | 270 | Route::prefix('devops')->group(function () { |
| 260 | Route::any('/', [Aside\Devops\ServerConfigController::class, 'lists'])->name('admin.devops.lists'); | 271 | Route::any('/', [Aside\Devops\ServerConfigController::class, 'lists'])->name('admin.devops.lists'); |
-
请 注册 或 登录 后发表评论