作者 刘锟

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

@@ -9,36 +9,17 @@ @@ -9,36 +9,17 @@
9 9
10 namespace App\Console\Commands\LyhTest; 10 namespace App\Console\Commands\LyhTest;
11 11
12 -use App\Console\Commands\Domain\DomainInfo;  
13 -use App\Helper\OaGlobalsoApi;  
14 -use App\Http\Logic\Aside\Project\ProjectLogic;  
15 use App\Models\Ai\AiBlog; 12 use App\Models\Ai\AiBlog;
16 -use App\Models\Ai\AiBlogAuthor;  
17 -use App\Models\Ai\AiCommand;  
18 -use App\Models\Com\NoticeLog;  
19 -use App\Models\Com\V6WeeklyReport;  
20 use App\Models\Product\Category; 13 use App\Models\Product\Category;
  14 +use App\Models\Project\AggregateKeywordAffix;
21 use App\Models\Project\AiBlogTask; 15 use App\Models\Project\AiBlogTask;
22 -use App\Models\Project\DeployBuild;  
23 -use App\Models\Project\DeployOptimize;  
24 -use App\Models\Project\OnlineCheck;  
25 use App\Models\Project\Project; 16 use App\Models\Project\Project;
26 use App\Models\Project\ProjectAiSetting; 17 use App\Models\Project\ProjectAiSetting;
27 -use App\Models\ProjectAssociation\ProjectAssociation;  
28 -use App\Models\RouteMap\RouteMap;  
29 use App\Models\Template\BTemplateMain; 18 use App\Models\Template\BTemplateMain;
30 use App\Models\Template\TemplateTypeMain; 19 use App\Models\Template\TemplateTypeMain;
31 -use App\Models\Visit\Visit;  
32 -use App\Models\WebSetting\TranslateBigProject;  
33 -use App\Models\WebSetting\WebLanguage;  
34 -use App\Models\WebSetting\WebSetting;  
35 -use App\Models\Workchat\MessagePush;  
36 use App\Services\AiBlogService; 20 use App\Services\AiBlogService;
37 -use App\Services\AiCommandService;  
38 use App\Services\ProjectServer; 21 use App\Services\ProjectServer;
39 use Illuminate\Console\Command; 22 use Illuminate\Console\Command;
40 -use Illuminate\Support\Facades\Schema;  
41 -use Illuminate\Support\Facades\Artisan;  
42 use Illuminate\Support\Facades\DB; 23 use Illuminate\Support\Facades\DB;
43 24
44 class lyhDemo extends Command 25 class lyhDemo extends Command
@@ -58,7 +39,7 @@ class lyhDemo extends Command @@ -58,7 +39,7 @@ class lyhDemo extends Command
58 protected $description = '更新路由'; 39 protected $description = '更新路由';
59 40
60 public function handle(){ 41 public function handle(){
61 - 42 + return true;
62 } 43 }
63 44
64 public function _actionTemplateMain(){ 45 public function _actionTemplateMain(){
@@ -6,7 +6,6 @@ use App\Models\Manage\Manage; @@ -6,7 +6,6 @@ use App\Models\Manage\Manage;
6 use App\Models\Project\Project; 6 use App\Models\Project\Project;
7 use App\Models\WorkOrder\TicketProject; 7 use App\Models\WorkOrder\TicketProject;
8 use Illuminate\Console\Command; 8 use Illuminate\Console\Command;
9 -use Illuminate\Support\Facades\Cache;  
10 use Illuminate\Support\Facades\Http; 9 use Illuminate\Support\Facades\Http;
11 10
12 class FetchTicketProjects extends Command 11 class FetchTicketProjects extends Command
@@ -16,7 +15,7 @@ class FetchTicketProjects extends Command @@ -16,7 +15,7 @@ class FetchTicketProjects extends Command
16 * 15 *
17 * @var string 16 * @var string
18 */ 17 */
19 - protected $signature = 'workorder:fetch-ticket-projects {version}'; 18 + protected $signature = 'workorder:fetch-ticket-projects {action}}';
20 19
21 /** 20 /**
22 * The console command description. 21 * The console command description.
@@ -42,15 +41,8 @@ class FetchTicketProjects extends Command @@ -42,15 +41,8 @@ class FetchTicketProjects extends Command
42 */ 41 */
43 public function handle() 42 public function handle()
44 { 43 {
45 - $version = $this->argument('version');  
46 - if ($version == 'v5') {  
47 - $this->fetch_v5();  
48 - } elseif ($version == 'v6') {  
49 - $this->fetch_v6();  
50 - } else {  
51 - $this->error('Invalid action. Use "v5" or "v6".');  
52 - return 1;  
53 - } 44 + $action = $this->argument('action');
  45 + $this->$action();
54 return 0; 46 return 0;
55 } 47 }
56 48
@@ -59,7 +51,7 @@ class FetchTicketProjects extends Command @@ -59,7 +51,7 @@ class FetchTicketProjects extends Command
59 * @return void 51 * @return void
60 * 请求:https://www.quanqiusou.cn/extend_api/webs/globalso_all.php 52 * 请求:https://www.quanqiusou.cn/extend_api/webs/globalso_all.php
61 */ 53 */
62 - public function fetch_v5() 54 + public function fetchV5()
63 { 55 {
64 # pm 项目经理 assm 售后服务经理 56 # pm 项目经理 assm 售后服务经理
65 $response = Http::get('https://www.quanqiusou.cn/extend_api/webs/globalso_all.php'); 57 $response = Http::get('https://www.quanqiusou.cn/extend_api/webs/globalso_all.php');
@@ -69,19 +61,25 @@ class FetchTicketProjects extends Command @@ -69,19 +61,25 @@ class FetchTicketProjects extends Command
69 # V5: 版本号+postid 61 # V5: 版本号+postid
70 $uuid = md5("V5{$item['postid']}"); 62 $uuid = md5("V5{$item['postid']}");
71 $project = TicketProject::where('uuid', $uuid)->first(); 63 $project = TicketProject::where('uuid', $uuid)->first();
72 -  
73 - $item['pm'] = $item['pm'] == '未安排' ? '杨长远' : $item['pm'];  
74 - $item['assm'] = $item['assm'] == '未安排' ? '杨长远' : $item['assm'];  
75 -  
76 - // 如果 $item['cate'] 包含”推广“字符,则$engineer_name = $item['assm']  
77 - $engineer_name = (strpos($item['cate'], '推广') !== false) ? $item['assm'] : $item['pm']; 64 + $assm_id = Manage::where('name', $item['assm'])->value('id') ?? Manage::where('name', '张鸿飞')->value('id') ?? 0; //售后服务经理
  65 + $seom_id = Manage::where('name', $item['yhs'])->value('id') ?? Manage::where('name', '陶婵')->value('id') ?? 0; //优化师
  66 + // 如果 $item['cate'] 包含”推广“字符,则 $engineer_name = $item['assm']
  67 + /**
  68 + * 第一负责人逻即说明:
  69 + * 优化推广项目:找售后服务经理??鸿飞
  70 + * 建站类项目: 找杨长远
  71 + */
  72 + $engineer_id = (strpos($item['cate'], '推广') !== false) ? $assm_id : Manage::where('name', '杨长远')->value('id') ?? 0;
78 73
79 $fields = [ 74 $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 - 'website' => $item['main_url'] ?? '', 75 + 'post_id' => $item['postid'],
  76 + 'company_name' => $item['company'],
  77 + 'title' => $item['title'],
  78 + 'engineer_id' => $engineer_id, // 第一负责人
  79 + 'assm_id' => $assm_id,
  80 + 'seom_id' => $seom_id,
  81 + 'website' => $item['main_url'] ?? '',
  82 + 'is_del' => 0,
85 ]; 83 ];
86 if (!$project) { 84 if (!$project) {
87 $new = new TicketProject(); 85 $new = new TicketProject();
@@ -104,8 +102,13 @@ class FetchTicketProjects extends Command @@ -104,8 +102,13 @@ class FetchTicketProjects extends Command
104 $project->save(); 102 $project->save();
105 } 103 }
106 } 104 }
107 - echo "V5: {$item['postid']} - {$item['title']} - {$item['company']} - {$item['main_url']}\n";  
108 } 105 }
  106 + $postids = collect($items)->pluck('postid')->toArray();
  107 + // 软删除 gl_ticket_projects 中不存在的项目
  108 + TicketProject::where('version', 5)
  109 + ->whereNotIn('post_id', $postids)
  110 + ->update(['is_del' => 1]);
  111 + echo date("Y-m-d H:i:s") . " V5: fetch completed, total " . count($items) . " items\n";
109 } 112 }
110 } 113 }
111 114
@@ -114,12 +117,15 @@ class FetchTicketProjects extends Command @@ -114,12 +117,15 @@ class FetchTicketProjects extends Command
114 * 1. 按照ID升序查询 gl_project 表 limit 10 117 * 1. 按照ID升序查询 gl_project 表 limit 10
115 * 2。同步到 TicketProject 后,redis 缓存 ID 118 * 2。同步到 TicketProject 后,redis 缓存 ID
116 */ 119 */
117 - public function fetch_v6() 120 + public function fetchV6()
118 { 121 {
  122 + $lastid = 0;
119 while (true) { 123 while (true) {
120 try { 124 try {
121 - $lastid = Cache::store('redis')->get('fetch_v6_lastid', 0);  
122 $items = Project::where('id', '>', intval($lastid)) 125 $items = Project::where('id', '>', intval($lastid))
  126 +// ->where('delete_status', 0)
  127 +// ->where('extend_type', '!=', 5) // 排除归档项目
  128 +// ->where('type', '!=', 8) // 排除归档项目
123 ->orderBy('id', 'asc') 129 ->orderBy('id', 'asc')
124 ->limit(10) 130 ->limit(10)
125 ->get(); 131 ->get();
@@ -128,24 +134,104 @@ class FetchTicketProjects extends Command @@ -128,24 +134,104 @@ class FetchTicketProjects extends Command
128 break; 134 break;
129 } 135 }
130 foreach ($items as $item) { 136 foreach ($items as $item) {
131 - $uuid = md5("V5{$item->id}"); 137 + $uuid = md5("V6{$item->id}");
132 $project = TicketProject::where('uuid', $uuid)->first(); 138 $project = TicketProject::where('uuid', $uuid)->first();
  139 + // 售后服务经理
  140 + $assm_id = collect([
  141 + $item->deploy_optimize->manager_mid ?? 0,
  142 + $item->deploy_optimize->tech_leader ?? 0,
  143 + 8, //张鸿飞
  144 + ])->first(fn($v) => $v !== null && $v !== 0, 0);
  145 + $seom_id = !empty($item->deploy_optimize->optimist_mid) ? $item->deploy_optimize->optimist_mid : $assm_id;
  146 + /**
  147 + * 第一负责人逻辑
  148 + * 建站类项目:找杨长远
  149 + * 推广类:找售后
  150 + */
  151 + if (in_array($item->type, [Project::TYPE_TWO, Project::TYPE_FOUR, Project::TYPE_SIX])) {
  152 + // 优化推广项目
  153 + $engineer_id = $assm_id;
  154 + } elseif ($item->type == Project::TYPE_THREE) {
  155 + $engineer_id = Manage::where('name', '杨长远')->value('id') ?? 0; // 建站类项目找杨长远
  156 + } else {
  157 + $engineer_id = collect([
  158 + $item->deploy_build->manager_mid ?? 0,
  159 + $item->deploy_build->leader_mid ?? 0,
  160 + 0
  161 + ])->first(fn($v) => $v !== null && $v !== 0, 0);
  162 + }
  163 + $is_del = (
  164 + $item->extend_type == 5
  165 + || $item->type == 8
  166 + || $item->delete_status == 1
  167 + || $item->site_status == 1
  168 + ) ? 1 : 0;
  169 +
  170 + $fields = [
  171 + 'company_name' => $item->company,
  172 + 'title' => $item->title,
  173 + 'assm_id' => $assm_id,
  174 + 'seom_id' => $seom_id,
  175 + 'engineer_id' => $engineer_id,
  176 + 'is_del' => $is_del
  177 + ];
133 if (!$project) { 178 if (!$project) {
134 $project = new TicketProject(); 179 $project = new TicketProject();
135 $project->uuid = $uuid; 180 $project->uuid = $uuid;
136 $project->post_id = $item->post_id; 181 $project->post_id = $item->post_id;
137 $project->version = 6; 182 $project->version = 6;
138 $project->table_id = $item->id; 183 $project->table_id = $item->id;
  184 + foreach ($fields as $k => $v) {
  185 + $project->$k = $v;
  186 + }
139 $project->save(); 187 $project->save();
140 - Cache::store('redis')->put('fetch_v6_lastid', $item->id); 188 + } else {
  189 + $changed = false;
  190 + foreach ($fields as $k => $v) {
  191 + if ($project->$k != $v) {
  192 + $project->$k = $v;
  193 + $changed = true;
  194 + }
  195 + }
  196 + if ($changed) {
  197 + $project->save();
  198 + }
141 } 199 }
142 - echo "V6: {$item->company}\n"; 200 + $lastid = $item->id;
  201 + echo date('Y-m-d H:i:s') . " V6: $item->id {$item->company} fetch ok \n";
143 } 202 }
144 - }catch (\Exception $exception) { 203 + } catch (\Exception $exception) {
145 echo $exception; 204 echo $exception;
146 break; 205 break;
147 } 206 }
148 } 207 }
  208 + }
149 209
  210 + public function fetch_uuid()
  211 + {
  212 + $lastid = 0;
  213 + while (true) {
  214 + try {
  215 + $items = TicketProject::where('id', '>', $lastid)
  216 + ->where('version', 6)
  217 + ->orderBy('id', 'asc')
  218 + ->limit(10)
  219 + ->get();
  220 + if ($items->isEmpty()) {
  221 + echo "not found items \n";
  222 + break;
  223 + }
  224 + foreach ($items as $item) {
  225 + $uuid = md5("V6{$item->table_id}");
  226 + $item->uuid = $uuid;
  227 + $item->save();
  228 + $lastid = $item->id;
  229 + echo date('Y-m-d H:i:s') . " V6: $item->id fetch ok \n";
  230 + }
  231 + } catch (\Exception $exception) {
  232 + echo $exception;
  233 + break;
  234 + }
  235 + }
150 } 236 }
151 } 237 }
1 <?php 1 <?php
2 2
3 -namespace App\Console\Commands; 3 +namespace App\Console\Commands\WorkOrder;
4 4
  5 +use App\Models\WorkOrder\TicketLog;
5 use App\Models\WorkOrder\WorkOrderLog; 6 use App\Models\WorkOrder\WorkOrderLog;
6 use App\Services\DingTalkService; 7 use App\Services\DingTalkService;
7 use Illuminate\Console\Command; 8 use Illuminate\Console\Command;
@@ -42,12 +43,12 @@ class WorkOrderDing extends Command @@ -42,12 +43,12 @@ class WorkOrderDing extends Command
42 { 43 {
43 while (true) { 44 while (true) {
44 try { 45 try {
45 - $log = WorkOrderLog::where('ding', 0)->first(); 46 + $log = TicketLog::where('ding', 0)->first();
46 if (!$log) { 47 if (!$log) {
47 sleep(3); 48 sleep(3);
48 continue; 49 continue;
49 } 50 }
50 - $mobile = $log->manager->mobile; 51 + $mobile = $log->engineer->mobile;
51 $response = Http::withBasicAuth( 52 $response = Http::withBasicAuth(
52 env('DINGDING_BASIC_USER'), 53 env('DINGDING_BASIC_USER'),
53 env('DINGDING_BASIC_PASS') 54 env('DINGDING_BASIC_PASS')
@@ -836,8 +836,18 @@ function ends_with($string, $suffix) @@ -836,8 +836,18 @@ function ends_with($string, $suffix)
836 return substr($string, -strlen($suffix)) === $suffix; 836 return substr($string, -strlen($suffix)) === $suffix;
837 } 837 }
838 838
839 -function getCustomRouteMap($module_route,$route = '') 839 +/**
  840 + * @remark :扩展模块分类路由
  841 + * @name :getCustomRouteMap
  842 + * @author :lyh
  843 + * @method :post
  844 + * @time :2025/6/21 9:57
  845 + */
  846 +function getCustomRouteMap($module_route,$route = '',$is_upgrade = 0)
840 { 847 {
  848 + if($is_upgrade == 0){
  849 + return $route;
  850 + }
841 if($module_route == $route){ 851 if($module_route == $route){
842 $resultRoute = $route; 852 $resultRoute = $route;
843 }else{ 853 }else{
@@ -29,6 +29,7 @@ class TicketController extends BaseController @@ -29,6 +29,7 @@ class TicketController extends BaseController
29 'logs.engineer:id,name', 29 'logs.engineer:id,name',
30 ]) 30 ])
31 ->where('project_id', $project->id) 31 ->where('project_id', $project->id)
  32 + ->where('submit_side', 2)
32 ->orderBy('id', 'desc') 33 ->orderBy('id', 'desc')
33 ->paginate($size, ['*'], 'page', $page); 34 ->paginate($size, ['*'], 'page', $page);
34 return response()->json(['data' => $tickets]); 35 return response()->json(['data' => $tickets]);
@@ -45,13 +46,10 @@ class TicketController extends BaseController @@ -45,13 +46,10 @@ class TicketController extends BaseController
45 { 46 {
46 $request->validated(); 47 $request->validated();
47 $project = TicketProject::where('uuid', $project_id)->first(); 48 $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 - } 49 + if (!$project) return response('未找到项目', 404);
  50 + if ($project->is_del) return response('项目状态异常', 400);
  51 + if (empty($project->first_engineer)) return response('项目未分配工单负责人', 400);
  52 +
55 $result = DB::transaction(function () use ($request, $project) { 53 $result = DB::transaction(function () use ($request, $project) {
56 $ticket = new Tickets(); 54 $ticket = new Tickets();
57 $ticket->project_id = $project->id; 55 $ticket->project_id = $project->id;
@@ -68,21 +66,7 @@ class TicketController extends BaseController @@ -68,21 +66,7 @@ class TicketController extends BaseController
68 $ticket->submit_username = $request->input('submit_username'); 66 $ticket->submit_username = $request->input('submit_username');
69 $ticket->save(); 67 $ticket->save();
70 $log = new TicketLog(); 68 $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 - } 69 + $log->engineer_id = $project->engineer_id; // 默认第一负责人
86 $ticket->logs()->save($log); 70 $ticket->logs()->save($log);
87 return $ticket; 71 return $ticket;
88 }); 72 });
@@ -103,16 +87,12 @@ class TicketController extends BaseController @@ -103,16 +87,12 @@ class TicketController extends BaseController
103 ]) 87 ])
104 ->find($id); 88 ->find($id);
105 89
106 - if (!$ticket) return $this->error('工单未找到', 404); 90 + if (!$ticket) return response('工单未找到', 404);
  91 +
  92 + if ($ticket->project->uuid !== $project_id) return response('无权限查看该工单', 403);
107 93
108 - if ($ticket->project->uuid !== $project_id) return $this->error('无权限查看该工单', 403); 94 + if ($ticket->project->is_del) return response('项目状态异常', 400);
109 95
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]); 96 return response()->json(['data' => $ticket]);
117 } 97 }
118 98
@@ -138,4 +118,17 @@ class TicketController extends BaseController @@ -138,4 +118,17 @@ class TicketController extends BaseController
138 { 118 {
139 // 119 //
140 } 120 }
  121 +
  122 + public function projectInfo($project_id)
  123 + {
  124 + $project = TicketProject::with([
  125 + 'projectV6:id,company',
  126 + 'assm:id,name',
  127 + 'seom:id,name',
  128 + 'first_engineer:id,name',
  129 + ])
  130 + ->where('uuid', $project_id)->first();
  131 + if (!$project) return $this->response('未找到项目', 404);
  132 + return response()->json(['data' => $project]);
  133 + }
141 } 134 }
@@ -67,7 +67,7 @@ class OptimizeController extends BaseController @@ -67,7 +67,7 @@ class OptimizeController extends BaseController
67 $v['g'] = implode(',', $v['g']); 67 $v['g'] = implode(',', $v['g']);
68 $v['keyword_num'] = implode(',', $v['keyword_num']); 68 $v['keyword_num'] = implode(',', $v['keyword_num']);
69 }else{ 69 }else{
70 - $data = $rankDataModel->read(['project_id'=>$v['id'],'lang'=>''],['first_page_num','indexed_pages_num']); 70 + $data = $rankDataModel->read(['project_id'=>$v['id'],'lang'=>'', 'api_no' => $v['api_no']],['first_page_num','indexed_pages_num']);
71 $v['first_page_num'] = $data['first_page_num'] ?? 0; 71 $v['first_page_num'] = $data['first_page_num'] ?? 0;
72 $v['indexed_pages_num'] = $data['indexed_pages_num'] ?? 0; 72 $v['indexed_pages_num'] = $data['indexed_pages_num'] ?? 0;
73 $v['g'] = $this->getGNum($v['id']); 73 $v['g'] = $this->getGNum($v['id']);
@@ -6,12 +6,10 @@ use App\Enums\Common\Code; @@ -6,12 +6,10 @@ use App\Enums\Common\Code;
6 use App\Http\Controllers\Aside\BaseController; 6 use App\Http\Controllers\Aside\BaseController;
7 use App\Http\Requests\Aside\WorkOrder\AsideTicketStoreRequest; 7 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\AsideTicketLogUpdateRequest;  
10 use App\Http\Requests\Aside\WorkOrder\AsideTicketUpdateRequest; 9 use App\Http\Requests\Aside\WorkOrder\AsideTicketUpdateRequest;
11 use App\Models\WorkOrder\TicketLog; 10 use App\Models\WorkOrder\TicketLog;
12 use App\Models\WorkOrder\TicketProject; 11 use App\Models\WorkOrder\TicketProject;
13 use App\Models\WorkOrder\Tickets; 12 use App\Models\WorkOrder\Tickets;
14 -use Illuminate\Http\Request;  
15 use Illuminate\Support\Facades\DB; 13 use Illuminate\Support\Facades\DB;
16 14
17 class AsideTicketController extends BaseController 15 class AsideTicketController extends BaseController
@@ -27,9 +25,9 @@ class AsideTicketController extends BaseController @@ -27,9 +25,9 @@ class AsideTicketController extends BaseController
27 * 1. 超管看所有工单 25 * 1. 超管看所有工单
28 * 2. 其他查看和自己有关的工单 26 * 2. 其他查看和自己有关的工单
29 */ 27 */
30 - $lists = TicketLog::with([  
31 - 'ticket.project.projectV6:id,company,title',  
32 - 'ticket.logs.engineer:id,name', 28 + $lists = Tickets::with([
  29 + 'logs.engineer:id,name',
  30 + 'project',
33 ]) 31 ])
34 ->when($this, function ($query) { 32 ->when($this, function ($query) {
35 $role = $this->manage['role']; 33 $role = $this->manage['role'];
@@ -38,31 +36,34 @@ class AsideTicketController extends BaseController @@ -38,31 +36,34 @@ class AsideTicketController extends BaseController
38 return $query; 36 return $query;
39 } 37 }
40 // 其他角色查自己参与的工单 38 // 其他角色查自己参与的工单
41 - return $query->where('engineer_id', $this->manage['id']); 39 + return $query->where(function ($q) {
  40 + $q->where('submit_user_id', $this->manage['id'])
  41 + ->orWhereHas('logs', function ($q1) {
  42 + $q1->where('engineer_id', $this->manage['id']);
  43 + });
  44 + });
42 }) 45 })
43 ->when($request->input('project_id') !== null, function ($query) use ($request) { 46 ->when($request->input('project_id') !== null, function ($query) use ($request) {
44 // project_id 查 gl_ticket_projects.uuid 47 // project_id 查 gl_ticket_projects.uuid
45 - return $query->whereHas('ticket.project', function ($q) use ($request) {  
46 - $q->where('uuid', $request->input('project_id')); 48 + $projectId = $request->input('project_id');
  49 + return $query->whereHas('project', function ($q) use ($projectId) {
  50 + $q->where('uuid', $projectId);
47 }); 51 });
48 }) 52 })
49 ->when($request->input('status') !== null, function ($query) use ($request) { 53 ->when($request->input('status') !== null, function ($query) use ($request) {
50 // status 查 gl_tickets.status 54 // status 查 gl_tickets.status
51 - return $query->whereHas('ticket', function ($q) use ($request) {  
52 - $q->where('status', $request->input('status'));  
53 - }); 55 + $status = $request->input('status');
  56 + return $query->where('status', $status);
54 }) 57 })
55 ->when($request->input('search'), function ($query) use ($request) { 58 ->when($request->input('search'), function ($query) use ($request) {
56 // search 查 gl_tickets.title 或 gl_ticket_projects.title 或 gl_ticket_projects.company_name 59 // search 查 gl_tickets.title 或 gl_ticket_projects.title 或 gl_ticket_projects.company_name
57 $search = $request->input('search'); 60 $search = $request->input('search');
58 - $query->where(function ($q) use ($search) {  
59 - $q->whereHas('ticket', function ($q1) use ($search) {  
60 - $q1->where('title', 'like', '%' . $search . '%');  
61 - })  
62 - ->orWhereHas('ticket.project', function ($q2) use ($search) {  
63 - $q2->where('title', 'like', '%' . $search . '%')  
64 - ->orWhere('company_name', 'like', '%' . $search . '%');  
65 - }); 61 + return $query->where(function ($q) use ($search) {
  62 + $q->where('title', 'like', '%' . $search . '%')
  63 + ->orWhereHas('project', function ($q1) use ($search) {
  64 + $q1->where('title', 'like', '%' . $search . '%')
  65 + ->orWhere('company_name', 'like', '%' . $search . '%');
  66 + });
66 }); 67 });
67 }) 68 })
68 ->orderBy('id', 'desc') 69 ->orderBy('id', 'desc')
@@ -72,16 +73,11 @@ class AsideTicketController extends BaseController @@ -72,16 +73,11 @@ class AsideTicketController extends BaseController
72 73
73 public function getProjects($search) 74 public function getProjects($search)
74 { 75 {
75 - $projects = TicketProject::with([  
76 - 'projectV6:id,company,title',  
77 - ]) 76 + $projects = TicketProject::where('is_del', 0)
78 ->where(function ($query) use ($search) { 77 ->where(function ($query) use ($search) {
  78 + // 查找项目名称或公司名称
79 $query->where('title', 'like', '%' . $search . '%') 79 $query->where('title', 'like', '%' . $search . '%')
80 - ->orWhere('company_name', 'like', '%' . $search . '%')  
81 - ->orWhereHas('projectV6', function ($q) use ($search) {  
82 - $q->where('company', 'like', '%' . $search . '%')  
83 - ->orWhere('title', 'like', '%' . $search . '%');  
84 - }); 80 + ->orWhere('company_name', 'like', '%' . $search . '%');
85 }) 81 })
86 ->get(); 82 ->get();
87 $this->response('success', Code::SUCCESS, $projects); 83 $this->response('success', Code::SUCCESS, $projects);
@@ -97,12 +93,7 @@ class AsideTicketController extends BaseController @@ -97,12 +93,7 @@ class AsideTicketController extends BaseController
97 { 93 {
98 $request->validated(); 94 $request->validated();
99 $project = TicketProject::where('uuid', $request->input('project_id'))->first(); 95 $project = TicketProject::where('uuid', $request->input('project_id'))->first();
100 - if ($project->version == 6){  
101 - if ($project->projectV6->delete_status) $this->response('该项目已被删除', Code::USER_MODEL_NOTFOUND_ERROE);  
102 - if ($project->projectV6->extend_type == 5) $this->response('未续费', Code::USER_MODEL_NOTFOUND_ERROE);  
103 - if ($project->projectV6->type == 8) $this->response('项目已归档', Code::USER_MODEL_NOTFOUND_ERROE);  
104 - if ($project->projectV6->site_status == 1) $this->response('站点已关闭', Code::USER_MODEL_NOTFOUND_ERROE);  
105 - } 96 + if ($project->is_del) $this->response('该项目状态异常', Code::USER_MODEL_NOTFOUND_ERROE);
106 $result = DB::transaction(function () use ($request, $project) { 97 $result = DB::transaction(function () use ($request, $project) {
107 $ticket = new Tickets(); 98 $ticket = new Tickets();
108 $ticket->project_id = $project->id; 99 $ticket->project_id = $project->id;
@@ -195,7 +186,6 @@ class AsideTicketController extends BaseController @@ -195,7 +186,6 @@ class AsideTicketController extends BaseController
195 186
196 $ticket->reply = $request->input('reply', null); 187 $ticket->reply = $request->input('reply', null);
197 $ticket->status = $request->input('status', $ticket->status); 188 $ticket->status = $request->input('status', $ticket->status);
198 - $ticket->save();  
199 if ($ticket->status == Tickets::STATUS_COMPLETED) 189 if ($ticket->status == Tickets::STATUS_COMPLETED)
200 { 190 {
201 // 完成工单,把子任务里面未完成的工单改为完成 191 // 完成工单,把子任务里面未完成的工单改为完成
@@ -203,6 +193,7 @@ class AsideTicketController extends BaseController @@ -203,6 +193,7 @@ class AsideTicketController extends BaseController
203 $ticket->logs()->where('status', '<', TicketLog::STATUS_COMPLETED) 193 $ticket->logs()->where('status', '<', TicketLog::STATUS_COMPLETED)
204 ->update(['status' => TicketLog::STATUS_COMPLETED, 'end_at' => now()]); 194 ->update(['status' => TicketLog::STATUS_COMPLETED, 'end_at' => now()]);
205 } 195 }
  196 + $ticket->save();
206 return $ticket; 197 return $ticket;
207 }); 198 });
208 $this->response('success', Code::SUCCESS, $result->toArray()); 199 $this->response('success', Code::SUCCESS, $result->toArray());
@@ -69,10 +69,11 @@ class AsideTicketLogController extends BaseController @@ -69,10 +69,11 @@ class AsideTicketLogController extends BaseController
69 if ($log->status >= TicketLog::STATUS_COMPLETED) 69 if ($log->status >= TicketLog::STATUS_COMPLETED)
70 { 70 {
71 // 我的工单标记为已完成 71 // 我的工单标记为已完成
72 - $log->status = $request->input('status');  
73 $log->end_at = now(); 72 $log->end_at = now();
74 } 73 }
75 } 74 }
  75 + if ($request->input('reply') !== null)
  76 + $log->reply = $request->input('reply', '');
76 $log->save(); 77 $log->save();
77 // 是否有未完成的子任务 78 // 是否有未完成的子任务
78 $pending = $ticket->logs() 79 $pending = $ticket->logs()
@@ -42,7 +42,7 @@ class CustomModuleCategoryController extends BaseController @@ -42,7 +42,7 @@ class CustomModuleCategoryController extends BaseController
42 $template_id = $this->getModuleTemplateId($this->param['module_id']); 42 $template_id = $this->getModuleTemplateId($this->param['module_id']);
43 foreach ($list as $k => $v){ 43 foreach ($list as $k => $v){
44 $v['is_renovation'] = $this->getIsRenovation($v['module_id'],BTemplate::IS_LIST,$template_id,$v['id'],BTemplate::IS_CUSTOM); 44 $v['is_renovation'] = $this->getIsRenovation($v['module_id'],BTemplate::IS_LIST,$template_id,$v['id'],BTemplate::IS_CUSTOM);
45 - $v['url'] = $this->user['domain'].getCustomRouteMap($moduleInfo['route'],$v['route']); 45 + $v['url'] = $this->user['domain'].getCustomRouteMap($moduleInfo['route'],$v['route'],$this->user['is_upgrade']);
46 $list[$k] = $v; 46 $list[$k] = $v;
47 } 47 }
48 } 48 }
@@ -202,7 +202,7 @@ class BlogCategoryLogic extends BaseLogic @@ -202,7 +202,7 @@ class BlogCategoryLogic extends BaseLogic
202 RouteMap::delRoute(RouteMap::SOURCE_BLOG_CATE, $id, $this->user['project_id']); 202 RouteMap::delRoute(RouteMap::SOURCE_BLOG_CATE, $id, $this->user['project_id']);
203 //生成一条删除路由记录 203 //生成一条删除路由记录
204 $info = $this->model->read(['id'=>$id],['id','alias']); 204 $info = $this->model->read(['id'=>$id],['id','alias']);
205 - $this->curlDelRoute(['old_route'=>$info['alias']]); 205 + $this->curlDelRoute(['old_route'=>$info['alias'],'source'=>RouteMap::SOURCE_BLOG_CATE]);
206 return $this->success(); 206 return $this->success();
207 } 207 }
208 208
@@ -161,7 +161,7 @@ class BlogLogic extends BaseLogic @@ -161,7 +161,7 @@ class BlogLogic extends BaseLogic
161 public function delRoute($id){ 161 public function delRoute($id){
162 //生成一条删除路由记录 162 //生成一条删除路由记录
163 $info = $this->model->read(['id'=>$id],['id','url']); 163 $info = $this->model->read(['id'=>$id],['id','url']);
164 - $this->curlDelRoute(['old_route'=>$info['url']]); 164 + $this->curlDelRoute(['old_route'=>$info['url'],'source'=>RouteMap::SOURCE_BLOG]);
165 return $this->success(); 165 return $this->success();
166 } 166 }
167 167
@@ -11,6 +11,7 @@ namespace App\Http\Logic\Bside\CustomModule; @@ -11,6 +11,7 @@ namespace App\Http\Logic\Bside\CustomModule;
11 11
12 use App\Http\Logic\Bside\BaseLogic; 12 use App\Http\Logic\Bside\BaseLogic;
13 use App\Models\Com\NoticeLog; 13 use App\Models\Com\NoticeLog;
  14 +use App\Models\CustomModule\CustomModule;
14 use App\Models\CustomModule\CustomModuleCategory; 15 use App\Models\CustomModule\CustomModuleCategory;
15 use App\Models\RouteMap\RouteMap; 16 use App\Models\RouteMap\RouteMap;
16 use App\Models\Template\BTemplate; 17 use App\Models\Template\BTemplate;
@@ -221,7 +222,10 @@ class CustomModuleCategoryLogic extends BaseLogic @@ -221,7 +222,10 @@ class CustomModuleCategoryLogic extends BaseLogic
221 } 222 }
222 RouteMap::delRoute(RouteMap::SOURCE_MODULE_CATE, $id, $this->user['project_id']); 223 RouteMap::delRoute(RouteMap::SOURCE_MODULE_CATE, $id, $this->user['project_id']);
223 //通知 224 //通知
224 - $this->curlDelRoute(['old_route'=>$info['route']]); 225 + //获取模块路由
  226 + $customModuleModel = new CustomModule();
  227 + $moduleInfo = $customModuleModel->read(['id'=>$info['module_id']]);
  228 + $this->curlDelRoute(['old_route'=>$info['route'],'path'=>getCustomRouteMap($moduleInfo['route'],$info['route'],$this->user['is_upgrade'])]);
225 return $this->success(); 229 return $this->success();
226 } 230 }
227 231
@@ -355,8 +355,13 @@ class CustomModuleContentLogic extends BaseLogic @@ -355,8 +355,13 @@ class CustomModuleContentLogic extends BaseLogic
355 { 355 {
356 RouteMap::delRoute(RouteMap::SOURCE_MODULE, $id, $this->user['project_id']); 356 RouteMap::delRoute(RouteMap::SOURCE_MODULE, $id, $this->user['project_id']);
357 //通知 357 //通知
358 - $info = $this->model->read(['id' => $id], ['id', 'route']);  
359 - $this->curlDelRoute(['old_route'=>$info['route']]); 358 + $info = $this->model->read(['id' => $id], ['id', 'route','category_id']);
  359 + $categoryIdArr = $info['category_id'];
  360 + $cate_id = (int)array_shift($categoryIdArr);
  361 + $routeMapModel = new RouteMap();
  362 + $routeInfo = $routeMapModel->read(['source'=>RouteMap::SOURCE_MODULE_CATE,'source_id'=>$cate_id]);
  363 + $path = ($routeInfo['route'] ?? '');
  364 + $this->curlDelRoute(['old_route'=>$info['route'],'path'=>$path]);
360 return $this->success(); 365 return $this->success();
361 } 366 }
362 367
@@ -216,7 +216,7 @@ class NewsCategoryLogic extends BaseLogic @@ -216,7 +216,7 @@ class NewsCategoryLogic extends BaseLogic
216 //删除路由映射 216 //删除路由映射
217 RouteMap::delRoute(RouteMap::SOURCE_NEWS_CATE, $id, $this->user['project_id']); 217 RouteMap::delRoute(RouteMap::SOURCE_NEWS_CATE, $id, $this->user['project_id']);
218 $info = $this->model->read(['id'=>$id],['id','alias']); 218 $info = $this->model->read(['id'=>$id],['id','alias']);
219 - $this->curlDelRoute(['old_route'=>$info['alias']]); 219 + $this->curlDelRoute(['old_route'=>$info['alias'],'source'=>RouteMap::SOURCE_NEWS_CATE]);
220 return $this->success(); 220 return $this->success();
221 } 221 }
222 222
@@ -357,7 +357,7 @@ class NewsLogic extends BaseLogic @@ -357,7 +357,7 @@ class NewsLogic extends BaseLogic
357 { 357 {
358 //生成一条删除路由记录 358 //生成一条删除路由记录
359 $info = $this->model->read(['id' => $id], ['id', 'url']); 359 $info = $this->model->read(['id' => $id], ['id', 'url']);
360 - $this->curlDelRoute(['old_route'=>$info['url']]); 360 + $this->curlDelRoute(['old_route'=>$info['url'],'source'=>RouteMap::SOURCE_NEWS]);
361 return $this->success(); 361 return $this->success();
362 } 362 }
363 363
@@ -199,7 +199,7 @@ class CategoryLogic extends BaseLogic @@ -199,7 +199,7 @@ class CategoryLogic extends BaseLogic
199 //生成一条删除路由记录 199 //生成一条删除路由记录
200 $info = $this->model->read(['id'=>$id],['id','route']); 200 $info = $this->model->read(['id'=>$id],['id','route']);
201 if($info !== false){ 201 if($info !== false){
202 - $this->curlDelRoute(['old_route'=>$info['route']]); 202 + $this->curlDelRoute(['old_route'=>$info['route'],'source'=>RouteMap::SOURCE_PRODUCT_CATE]);
203 } 203 }
204 return $this->success(); 204 return $this->success();
205 } 205 }
@@ -188,7 +188,7 @@ class KeywordLogic extends BaseLogic @@ -188,7 +188,7 @@ class KeywordLogic extends BaseLogic
188 //生成一条删除路由记录 188 //生成一条删除路由记录
189 $info = $this->model->read(['id'=>$id],['id','route']); 189 $info = $this->model->read(['id'=>$id],['id','route']);
190 if($info !== false){ 190 if($info !== false){
191 - $this->curlDelRoute(['old_route'=>$info['route']]); 191 + $this->curlDelRoute(['old_route'=>$info['route'],'source'=>RouteMap::SOURCE_PRODUCT_KEYWORD]);
192 } 192 }
193 return $this->success(); 193 return $this->success();
194 } 194 }
@@ -472,7 +472,7 @@ class ProductLogic extends BaseLogic @@ -472,7 +472,7 @@ class ProductLogic extends BaseLogic
472 public function delRoute($id){ 472 public function delRoute($id){
473 //生成一条删除路由记录 473 //生成一条删除路由记录
474 $info = $this->model->read(['id'=>$id],['id','route']); 474 $info = $this->model->read(['id'=>$id],['id','route']);
475 - $this->curlDelRoute(['old_route'=>$info['route']]); 475 + $this->curlDelRoute(['old_route'=>$info['route'],'source'=>RouteMap::SOURCE_PRODUCT]);
476 return $this->success(); 476 return $this->success();
477 } 477 }
478 478
@@ -2,11 +2,11 @@ @@ -2,11 +2,11 @@
2 2
3 namespace App\Models\WorkOrder; 3 namespace App\Models\WorkOrder;
4 4
  5 +use App\Models\Base;
5 use App\Models\Manage\Manage; 6 use App\Models\Manage\Manage;
6 use Illuminate\Database\Eloquent\Factories\HasFactory; 7 use Illuminate\Database\Eloquent\Factories\HasFactory;
7 -use Illuminate\Database\Eloquent\Model;  
8 8
9 -class TicketLog extends Model 9 +class TicketLog extends Base
10 { 10 {
11 use HasFactory; 11 use HasFactory;
12 12
@@ -2,12 +2,12 @@ @@ -2,12 +2,12 @@
2 2
3 namespace App\Models\WorkOrder; 3 namespace App\Models\WorkOrder;
4 4
  5 +use App\Models\Base;
5 use App\Models\Manage\Manage; 6 use App\Models\Manage\Manage;
6 use App\Models\Project\Project; 7 use App\Models\Project\Project;
7 use Illuminate\Database\Eloquent\Factories\HasFactory; 8 use Illuminate\Database\Eloquent\Factories\HasFactory;
8 -use Illuminate\Database\Eloquent\Model;  
9 9
10 -class TicketProject extends Model 10 +class TicketProject extends Base
11 { 11 {
12 use HasFactory; 12 use HasFactory;
13 13
@@ -19,4 +19,26 @@ class TicketProject extends Model @@ -19,4 +19,26 @@ class TicketProject extends Model
19 ->where('version', 6); 19 ->where('version', 6);
20 } 20 }
21 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 + }
22 } 44 }
@@ -2,10 +2,10 @@ @@ -2,10 +2,10 @@
2 2
3 namespace App\Models\WorkOrder; 3 namespace App\Models\WorkOrder;
4 4
  5 +use App\Models\Base;
5 use Illuminate\Database\Eloquent\Factories\HasFactory; 6 use Illuminate\Database\Eloquent\Factories\HasFactory;
6 -use Illuminate\Database\Eloquent\Model;  
7 7
8 -class Tickets extends Model 8 +class Tickets extends Base
9 { 9 {
10 use HasFactory; 10 use HasFactory;
11 11
@@ -80,6 +80,7 @@ Route::any('/get_project_by_mch_id', [\App\Http\Controllers\Api\PrivateControlle @@ -80,6 +80,7 @@ Route::any('/get_project_by_mch_id', [\App\Http\Controllers\Api\PrivateControlle
80 // B端,渠道在企微群操作-售后工单 80 // B端,渠道在企微群操作-售后工单
81 Route::prefix('tickets')->group(function () { 81 Route::prefix('tickets')->group(function () {
82 Route::get('/{project_id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'index'])->summary('B端,渠道-工单列表')->name('tickets.list'); 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');
83 Route::post('/{project_id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'store'])->summary('B端,渠道-提工单')->name('tickets.store'); 84 Route::post('/{project_id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'store'])->summary('B端,渠道-提工单')->name('tickets.store');
84 Route::get('/{project_id}/{id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'show'])->summary('B端,渠道-工单详情')->name('tickets.show'); 85 Route::get('/{project_id}/{id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'show'])->summary('B端,渠道-工单详情')->name('tickets.show');
85 }); 86 });
@@ -621,6 +621,8 @@ Route::group([], function () { @@ -621,6 +621,8 @@ Route::group([], function () {
621 Route::any('/collect', [Aside\Collect\CollectController::class, 'index'])->name('admin.collect'); 621 Route::any('/collect', [Aside\Collect\CollectController::class, 'index'])->name('admin.collect');
622 //同步询盘 622 //同步询盘
623 Route::any('/sync_inquiry', [Aside\Com\IndexController::class, 'sync_inquiry'])->name('admin.sync_inquiry'); 623 Route::any('/sync_inquiry', [Aside\Com\IndexController::class, 'sync_inquiry'])->name('admin.sync_inquiry');
  624 + Route::post('/images_uploads', [\App\Http\Controllers\File\ImageController::class, 'upload'])->name('admin.images_uploads');//无需登录上传
  625 + Route::post('/files_uploads', [\App\Http\Controllers\File\FileController::class, 'upload'])->name('admin.files_uploads');
624 }); 626 });
625 627
626 628