作者 ZhengBing He

ok

@@ -80,6 +80,7 @@ class FetchTicketProjects extends Command @@ -80,6 +80,7 @@ class FetchTicketProjects extends Command
80 'assm_id' => $assm_id, 80 'assm_id' => $assm_id,
81 'seom_id' => $seom_id, 81 'seom_id' => $seom_id,
82 'website' => $item['main_url'] ?? '', 82 'website' => $item['main_url'] ?? '',
  83 + 'test_website' => $item['test_url'] ?? '',
83 'is_del' => 0, 84 'is_del' => 0,
84 ]; 85 ];
85 if (!$project) { 86 if (!$project) {
@@ -170,7 +171,9 @@ class FetchTicketProjects extends Command @@ -170,7 +171,9 @@ class FetchTicketProjects extends Command
170 'assm_id' => $assm_id, 171 'assm_id' => $assm_id,
171 'seom_id' => $seom_id, 172 'seom_id' => $seom_id,
172 'engineer_id' => $engineer_id, 173 'engineer_id' => $engineer_id,
173 - 'is_del' => $is_del 174 + 'is_del' => $is_del,
  175 + 'website' => !empty($item->domainInfo->domain) ? 'https://'.$item->domainInfo->domain : '',
  176 + 'test_website' => $item->deploy_build->test_domain ?? '',
174 ]; 177 ];
175 if (!$project) { 178 if (!$project) {
176 $project = new TicketProject(); 179 $project = new TicketProject();
  1 +<?php
  2 +
  3 +namespace App\Http\Controllers\Api\WorkOrder;
  4 +
  5 +use App\Http\Controllers\Controller;
  6 +use App\Http\Requests\Api\WorkOrder\TicketChatStoreRequest;
  7 +use App\Models\WorkOrder\TicketChat;
  8 +use App\Models\WorkOrder\Tickets;
  9 +use Illuminate\Http\Request;
  10 +
  11 +class TicketChatController extends Controller
  12 +{
  13 + /**
  14 + * Display a listing of the resource.
  15 + *
  16 + * @return \Illuminate\Http\Response
  17 + */
  18 + public function index($project_id, $ticket_id)
  19 + {
  20 + $ticket = Tickets::find($ticket_id);;
  21 + if (!$ticket) return response('工单未找到', 404);
  22 + if ($ticket->project->uuid !== $project_id) return response('无权限查看该工单', 403);
  23 + if ($ticket->project->is_del) return response('项目状态异常', 400);
  24 +
  25 + $chats = TicketChat::where('ticket_id', $ticket->id)
  26 + ->get();
  27 + return response()->json(['data' => $chats]);
  28 + }
  29 +
  30 + /**
  31 + * Show the form for creating a new resource.
  32 + *
  33 + * @return \Illuminate\Http\Response
  34 + */
  35 + public function create()
  36 + {
  37 + //
  38 + }
  39 +
  40 + /**
  41 + * Store a newly created resource in storage.
  42 + *
  43 + * @param \Illuminate\Http\Request $request
  44 + * @return \Illuminate\Http\Response
  45 + */
  46 + public function store(TicketChatStoreRequest $request, $project_id, $ticket_id)
  47 + {
  48 + $request->validated();
  49 + $ticket = Tickets::with(['project'])->find($ticket_id);
  50 + if (!$ticket) return response('工单未找到', 404);
  51 + if ($ticket->project->uuid !== $project_id) return response('无权限查看该工单', 403);
  52 + if ($ticket->project->is_del) return response('项目状态异常', 400);
  53 +
  54 + $chat = new TicketChat();
  55 + $chat->ticket_id = $ticket->id;
  56 + $chat->content = $request->input('content');
  57 + $files = $request->input('files');
  58 + if (empty($files) || (is_array($files) && count(array_filter($files, function($v){ return !is_null($v); })) === 0)) {
  59 + $ticket->files = null;
  60 + } else {
  61 + $ticket->files = json_encode($files);
  62 + }
  63 + $chat->submit_side = 2;
  64 + $chat->submit_username = $request->input('submit_username');
  65 + $chat->save();
  66 + return response()->json(['data' => $chat]);
  67 + }
  68 +
  69 + /**
  70 + * Display the specified resource.
  71 + *
  72 + * @param int $id
  73 + * @return \Illuminate\Http\Response
  74 + */
  75 + public function show($id)
  76 + {
  77 + //
  78 + }
  79 +
  80 + /**
  81 + * Show the form for editing the specified resource.
  82 + *
  83 + * @param int $id
  84 + * @return \Illuminate\Http\Response
  85 + */
  86 + public function edit($id)
  87 + {
  88 + //
  89 + }
  90 +
  91 + /**
  92 + * Update the specified resource in storage.
  93 + *
  94 + * @param \Illuminate\Http\Request $request
  95 + * @param int $id
  96 + * @return \Illuminate\Http\Response
  97 + */
  98 + public function update(Request $request, $id)
  99 + {
  100 + //
  101 + }
  102 +
  103 + /**
  104 + * Remove the specified resource from storage.
  105 + *
  106 + * @param int $id
  107 + * @return \Illuminate\Http\Response
  108 + */
  109 + public function destroy($id)
  110 + {
  111 + //
  112 + }
  113 +}
@@ -25,7 +25,7 @@ class TicketController extends BaseController @@ -25,7 +25,7 @@ class TicketController extends BaseController
25 $size = (int)$request->input('size', 10); 25 $size = (int)$request->input('size', 10);
26 26
27 $tickets = Tickets::with([ 27 $tickets = Tickets::with([
28 - 'project.projectV6:id,company,version', 28 + 'project:*',
29 'logs.engineer:id,name', 29 'logs.engineer:id,name',
30 ]) 30 ])
31 ->where('project_id', $project->id) 31 ->where('project_id', $project->id)
@@ -15,31 +15,24 @@ use Illuminate\Support\Facades\DB; @@ -15,31 +15,24 @@ use Illuminate\Support\Facades\DB;
15 class AsideTicketController extends BaseController 15 class AsideTicketController extends BaseController
16 { 16 {
17 /** 17 /**
18 - * Display a listing of the resource. 18 + * A端查看所有工单
19 * 19 *
20 * @return \Illuminate\Http\Response 20 * @return \Illuminate\Http\Response
21 */ 21 */
22 public function index(AsideTicketListRequest $request) 22 public function index(AsideTicketListRequest $request)
23 { 23 {
24 - /**  
25 - * 1. 超管看所有工单  
26 - * 2. 其他查看和自己有关的工单  
27 - */ 24 + $validated = $request->validated();
28 $lists = Tickets::with([ 25 $lists = Tickets::with([
29 'logs.engineer:id,name', 26 'logs.engineer:id,name',
30 'project', 27 'project',
31 ]) 28 ])
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(function ($q) {  
40 - $q->where('submit_user_id', $this->manage['id'])  
41 - ->orWhereHas('logs', function ($q1) {  
42 - $q1->where('engineer_id', $this->manage['id']); 29 + ->when($validated['engineer_id'], function ($query) use ($validated) {
  30 + // 查 gl_tickets 表 submit_user_id 或 gl_ticket_logs 表 engineer_id
  31 + $engineerId = $validated['engineer_id'];
  32 + return $query->where(function ($q) use ($engineerId) {
  33 + $q->where('submit_user_id', $engineerId)
  34 + ->orWhereHas('logs', function ($q1) use ($engineerId) {
  35 + $q1->where('engineer_id', $engineerId);
43 }); 36 });
44 }); 37 });
45 }) 38 })
@@ -71,6 +64,11 @@ class AsideTicketController extends BaseController @@ -71,6 +64,11 @@ class AsideTicketController extends BaseController
71 $this->response('success', Code::SUCCESS, $lists); 64 $this->response('success', Code::SUCCESS, $lists);
72 } 65 }
73 66
  67 + /**
  68 + * @param $search
  69 + * @return void
  70 + * V5V6所有项目
  71 + */
74 public function getProjects($search) 72 public function getProjects($search)
75 { 73 {
76 $projects = TicketProject::where('is_del', 0) 74 $projects = TicketProject::where('is_del', 0)
@@ -136,37 +134,19 @@ class AsideTicketController extends BaseController @@ -136,37 +134,19 @@ class AsideTicketController extends BaseController
136 134
137 if (!$ticket) $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE); 135 if (!$ticket) $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE);
138 136
139 - if ($this->manage['role'] != 1  
140 - && $ticket->submit_user_id != $this->manage['id']  
141 - && $ticket->logs()->where('engineer_id', $this->manage['id'])->count() == 0)  
142 - // 只能查看自己的工单  
143 - $this->response('没有权限查看该工单', Code::USER_PERMISSION_ERROE);  
144 -  
145 - // TODO 判断是否有查看工单详情权限,待添加  
146 $this->response('success', Code::SUCCESS, $ticket->toArray()); 137 $this->response('success', Code::SUCCESS, $ticket->toArray());
147 } 138 }
148 139
149 /** 140 /**
150 - * A端修改工单  
151 - * 1. 邀请协同的同事  
152 - * 2. 审核工单 141 + * A端负责人修改工单
  142 + * 1. 邀请同事
  143 + * 2. 修改工单状态
153 */ 144 */
154 public function update(AsideTicketUpdateRequest $request, $id) 145 public function update(AsideTicketUpdateRequest $request, $id)
155 { 146 {
156 $request->validated(); 147 $request->validated();
157 $ticket = Tickets::find($id); 148 $ticket = Tickets::find($id);
158 if (!$ticket) $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE); 149 if (!$ticket) $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE);
159 - // 检测修改权限  
160 - if ($ticket->submit_side == 1 && $ticket->submit_user_id != $this->manage['id']) {  
161 - // A端提交的工单,只有提交人可以修改  
162 - $this->response('没有权限操作该工单', Code::USER_PERMISSION_ERROE);  
163 - } elseif ($ticket->submit_side == 2)  
164 - {  
165 - // B端提交的工单,只有第一对接人可以修改  
166 - $log = $ticket->logs()->first();  
167 - if ($log->engineer_id != $this->manage['id'])  
168 - $this->response('没有权限操作该工单', Code::USER_PERMISSION_ERROE);  
169 - }  
170 150
171 // 开始修改 151 // 开始修改
172 $result = DB::transaction(function () use ($request, $ticket) { 152 $result = DB::transaction(function () use ($request, $ticket) {
  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\Api\WorkOrder\TicketChatStoreRequest;
  8 +use App\Models\WorkOrder\TicketChat;
  9 +use App\Models\WorkOrder\Tickets;
  10 +use Illuminate\Http\Request;
  11 +
  12 +class TicketChatController extends BaseController
  13 +{
  14 + /**
  15 + * Display a listing of the resource.
  16 + *
  17 + * @return \Illuminate\Http\Response
  18 + */
  19 + public function index($ticket_id)
  20 + {
  21 + $ticket = Tickets::find($ticket_id);;
  22 + if (!$ticket) return response('工单未找到', 404);
  23 + $chats = TicketChat::where('ticket_id', $ticket->id)->get();
  24 + $this->response('success', Code::SUCCESS, $chats);
  25 + }
  26 +
  27 + /**
  28 + * Show the form for creating a new resource.
  29 + *
  30 + * @return \Illuminate\Http\Response
  31 + */
  32 + public function create()
  33 + {
  34 + //
  35 + }
  36 +
  37 + /**
  38 + * Store a newly created resource in storage.
  39 + *
  40 + * @param \Illuminate\Http\Request $request
  41 + * @return \Illuminate\Http\Response
  42 + */
  43 + public function store(TicketChatStoreRequest $request, $ticket_id)
  44 + {
  45 + $validated = $request->validated();
  46 + $ticket = Tickets::find($request->input('ticket_id'));
  47 + if (!$ticket) return response('工单未找到', 404);
  48 + if ($ticket->project->is_del) return response('项目状态异常', 400);
  49 +
  50 + $chat = new TicketChat();
  51 + $chat->ticket_id = $ticket->id;
  52 + $chat->content = $validated['content'];
  53 +
  54 + $files = $validated['files'];
  55 + if (empty($files) || (is_array($files) && count(array_filter($files, function($v){ return !is_null($v); })) === 0)) {
  56 + $ticket->files = null;
  57 + } else {
  58 + $ticket->files = json_encode($files);
  59 + }
  60 +
  61 + $chat->submit_username = $this->manage['name'];
  62 + $chat->submit_side = 1;
  63 + $chat->manage_id = $this->manage['id'];
  64 + $chat->save();
  65 + $this->response('success', Code::SUCCESS, $chat);
  66 + }
  67 +
  68 + /**
  69 + * Display the specified resource.
  70 + *
  71 + * @param int $id
  72 + * @return \Illuminate\Http\Response
  73 + */
  74 + public function show($id)
  75 + {
  76 + //
  77 + }
  78 +
  79 + /**
  80 + * Show the form for editing the specified resource.
  81 + *
  82 + * @param int $id
  83 + * @return \Illuminate\Http\Response
  84 + */
  85 + public function edit($id)
  86 + {
  87 + //
  88 + }
  89 +
  90 + /**
  91 + * Update the specified resource in storage.
  92 + *
  93 + * @param \Illuminate\Http\Request $request
  94 + * @param int $id
  95 + * @return \Illuminate\Http\Response
  96 + */
  97 + public function update(Request $request, $id)
  98 + {
  99 + //
  100 + }
  101 +
  102 + /**
  103 + * Remove the specified resource from storage.
  104 + *
  105 + * @param int $id
  106 + * @return \Illuminate\Http\Response
  107 + */
  108 + public function destroy($id)
  109 + {
  110 + //
  111 + }
  112 +}
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\WorkOrderListRequest;  
8 -use App\Http\Requests\Aside\WorkOrder\WorkOrderUpdateRequest;  
9 -use App\Models\WorkOrder\WorkOrder;  
10 -use App\Models\WorkOrder\WorkOrderLog;  
11 -use Illuminate\Support\Facades\DB;  
12 -  
13 -class WorkOrderController extends BaseController  
14 -{  
15 - /**  
16 - * A端工单列表  
17 - * 显示有我参与的工单列表  
18 - */  
19 - public function index(WorkOrderListRequest $request)  
20 - {  
21 - /*  
22 - * A端工程师工单列表, 查询我的工单  
23 - */  
24 - $request->validated();  
25 - # manage_id 或 engineer_id 是我  
26 - $lists = WorkOrderLog::with([  
27 - 'workOrder.logs.manager:id,name',  
28 - 'workOrder.project:id,company,title',  
29 - ])  
30 - ->where('manage_id', $this->manage['id'])  
31 - ->when($request->input('project_id') !== null, function ($query) use ($request) {  
32 - // project_id 查 workOrder  
33 - return $query->whereHas('workOrder', function ($q) use ($request) {  
34 - $q->where('project_id', $request->input('project_id'));  
35 - });  
36 - })  
37 - ->when($request->input('status') !== null, function ($query) use ($request) {  
38 - // status 查 workOrder  
39 - return $query->whereHas('workOrder', function ($q) use ($request) {  
40 - $q->where('status', $request->input('status'));  
41 - });  
42 - })  
43 - ->when($request->input('search'), function ($query) use ($request) {  
44 - // search 查 workOrder  
45 - return $query->whereHas('workOrder', function ($q) use ($request) {  
46 - $q->where('product', 'like', '%' . $request->input('search') . '%')  
47 - ->orWhere('content', 'like', '%' . $request->input('search') . '%');  
48 - });  
49 - })  
50 - ->orderBy('id', 'desc')  
51 - ->paginate($this->row, ['*'], 'page', $this->page);  
52 - $this->response('success', Code::SUCCESS, $lists);  
53 - }  
54 -  
55 -  
56 - /**  
57 - * @param WorkOrderListRequest $request  
58 - * @return void  
59 - * A端管理员的工单列表  
60 - */  
61 - public function manager(WorkOrderListRequest $request)  
62 - {  
63 - $request->validated();  
64 - // 管理员查看所有工单  
65 - $lists = WorkOrder::with([  
66 - 'user:id,name',  
67 - 'manager:id,name',  
68 - 'engineer:id,name',  
69 - 'logs.manager:id,name',  
70 - 'project:id,company:title',  
71 - ])  
72 - ->when($request->input('project_id') !== null, function ($query) use ($request) {  
73 - return $query->where('project_id', $request->input('project_id'));  
74 - })  
75 - ->when($request->input('status') !== null, function ($query) use ($request) {  
76 - return $query->where('status', $request->input('status'));  
77 - })  
78 - ->when($request->input('search'), function ($query) use ($request) {  
79 - return $query->where('product', 'like', '%' . $request->input('search') . '%')  
80 - ->orWhere('content', 'like', '%' . $request->input('search') . '%');  
81 - })  
82 - ->orderBy('id', 'desc')  
83 - ->paginate($this->row, ['*'], 'page', $this->page);  
84 - $this->response('success', Code::SUCCESS, $lists);  
85 - }  
86 -  
87 - /**  
88 - * A端工单详情  
89 - *  
90 - * @param int $id  
91 - * @return \Illuminate\Http\Response  
92 - */  
93 - public function show($id)  
94 - {  
95 - $workOrder = WorkOrder::with([  
96 - 'logs.manager:id,name',  
97 - 'user:id,name',  
98 - 'manager:id,name',  
99 - 'engineer:id,name',  
100 - 'project:id,company:title',  
101 - ])->find($id);  
102 -  
103 - if (!$workOrder)  
104 - $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE);  
105 -  
106 - // TODO 判断是否有查看工单详情权限,待添加  
107 - $this->response('success', Code::SUCCESS, $workOrder->toArray());  
108 - }  
109 -  
110 - /**  
111 - * A端操作工单,工程师操作的是工单日志  
112 - * - 工程师:回复工单,自动��拆分给自己的子任务改为完成  
113 - * - 工单第一对接人:  
114 - * - 邀请工程师处理工单  
115 - * - 修改工单状态  
116 - * 若全部子任务完成,则将工单状态改为完成  
117 - */  
118 - public function update(WorkOrderUpdateRequest $request, $id)  
119 - {  
120 - $request->validated();  
121 - $log = WorkOrderLog::find($id); // 拆分的子工单  
122 - if (!$log) {  
123 - $this->response('工单不存在', Code::USER_MODEL_NOTFOUND_ERROE);  
124 - }  
125 - if ($log->manage_id != $this->manage['id']) {  
126 - // 只能操作自己的工单  
127 - $this->response('没有权限操作该工单', Code::USER_PERMISSION_ERROE);  
128 - }  
129 - $workOrder = $log->workOrder;  
130 - $result = DB::transaction(function () use ($request, $workOrder, $log) {  
131 - if ($request->input('engineer_ids'))  
132 - {  
133 - // 有邀请工程师协同处理  
134 - foreach ($request->input('engineer_ids') as $engineer_id)  
135 - {  
136 - try {  
137 - // 利用唯一索引去重  
138 - $new_log = new WorkOrderLog();  
139 - $new_log->manage_id = $engineer_id;  
140 - $workOrder->logs()->save($new_log);  
141 - $workOrder->engineer_id = $engineer_id;  
142 - $workOrder->save();  
143 - }catch (\Exception $exception){}  
144 - }  
145 - }  
146 - if ($request->input('content'))  
147 - $log->content = $request->input('content');  
148 - if ($request->input('files'))  
149 - $log->files = $request->input('files');  
150 - if ($request->input('status') !== null)  
151 - {  
152 - $log->status = $request->input('status');  
153 - if ($log->status >= WorkOrder::STATUS_COMPLETED)  
154 - {  
155 - // 我的工单标记为已完成  
156 - $log->status = $request->input('status');  
157 - $log->end_at = now();  
158 - }  
159 - }  
160 - $log->save();  
161 - // 是否有未完成的子任务  
162 - $pending = $workOrder->logs()  
163 - ->where('status', '<', WorkOrderLog::STATUS_COMPLETED)  
164 - ->count();  
165 - if ($pending)  
166 - {  
167 - $workOrder->status = WorkOrder::STATUS_PROCESSING;  
168 - }else  
169 - {  
170 - $workOrder->status = WorkOrder::STATUS_COMPLETED;  
171 - // 如果所有子任务都完成了,则将工单状态改为已完成  
172 - $workOrder->end_at = now();  
173 - }  
174 - $workOrder->save();  
175 - return $log;  
176 - });  
177 - $this->response('success', Code::SUCCESS, $result->toArray());  
178 - }  
179 -  
180 -}  
1 -<?php  
2 -  
3 -namespace App\Http\Controllers\Bside\WorkOrder;  
4 -  
5 -use App\Enums\Common\Code;  
6 -use App\Http\Controllers\Bside\BaseController;  
7 -use App\Http\Requests\Aside\WorkOrder\WorkOrderListRequest;  
8 -use App\Http\Requests\Bside\WorkOrder\WorkOrderCreateRequest;  
9 -use App\Http\Requests\Bside\WorkOrder\WorkOrderUpdateRequest;  
10 -use App\Models\Project\Project;  
11 -use App\Models\WorkOrder\WorkOrder;  
12 -use App\Models\WorkOrder\WorkOrderLog;  
13 -use Illuminate\Support\Facades\DB;  
14 -  
15 -class WorkOrderController extends BaseController  
16 -{  
17 - /**  
18 - * B端售后工单列表  
19 - *  
20 - * @return \Illuminate\Http\Response  
21 - */  
22 - public function index(WorkOrderListRequest $request)  
23 - {  
24 - $request->validated();  
25 - $where = [  
26 - 'project_id' => $this->user['project_id'],  
27 - ];  
28 - // 分页查询  
29 - $lists = WorkOrder::with([  
30 - 'manager:id,name',  
31 - ])  
32 - ->where($where)  
33 - ->when($request->input('status'), function ($query) use ($request) {  
34 - return $query->where('status', $request->input('status'));  
35 - })  
36 - ->when($request->input('search'), function ($query) use ($request) {  
37 - return $query->where('product', 'like', '%' . $request->input('search') . '%')  
38 - ->orWhere('content', 'like', '%' . $request->input('search') . '%');  
39 - })  
40 - ->orderBy('id', 'desc')->paginate($this->row, ['*'], 'page', $this->page);  
41 - $this->response('success', Code::SUCCESS, $lists);  
42 - }  
43 -  
44 - /**  
45 - * B端用户提交工单  
46 - *  
47 - * @return \Illuminate\Http\Response  
48 - */  
49 - public function store(WorkOrderCreateRequest $request)  
50 - {  
51 - $request->validated();  
52 - $result = DB::transaction(function () use ($request) {  
53 - $workOrder = new WorkOrder;  
54 - $workOrder->product = $request->input('product');  
55 - $workOrder->content = $request->input('content');  
56 - $workOrder->files = json_encode($request->input('files'));  
57 - $workOrder->project_user_id = $this->user['id'];  
58 - $workOrder->project_id = $this->user['project_id'];  
59 - $workOrder->engineer_id = 0;  
60 - if ($this->project['type'] == 3){  
61 - // 项目类型是优化推广,项目负责人找优化  
62 - $seo = Project::find($this->user['project_id'])->deploy_optimize;  
63 - $workOrder->manage_id = $seo->manager_mid ?? $seo->optimist_mid ?? 0;  
64 - }else{  
65 - // 非优化推广项目,项目负责人找技术组长  
66 - $build = Project::find($this->user['project_id'])->deploy_build;  
67 - $workOrder->manage_id = $build->leader_mid ?? 0;  
68 - }  
69 - $workOrder->save();  
70 - // 添加工单日志  
71 - $log = new WorkOrderLog();  
72 - $log->manage_id = $workOrder->manage_id;  
73 - $workOrder->logs()->save($log);  
74 - return $workOrder;  
75 - });  
76 - $this->response('success', Code::SUCCESS, $result->toArray());  
77 - }  
78 -  
79 - /**  
80 - * Display the specified resource.  
81 - *  
82 - * @param int $id  
83 - * @return \Illuminate\Http\Response  
84 - */  
85 - public function show($id)  
86 - {  
87 - $workOrder = WorkOrder::with([  
88 - 'logs.manager:id,name',  
89 - 'user:id,name',  
90 - 'manager:id,name',  
91 - 'engineer:id,name',  
92 - ])->find($id);  
93 - if (!$workOrder) {  
94 - $this->response('工单未找到', 404);  
95 - }  
96 - if ($workOrder->project_id != $this->user['project_id'] && $workOrder->engineer_id != $this->user['id']) {  
97 - $this->response('无权限查看该工单', 403);  
98 - }  
99 - $this->response('success', Code::SUCCESS, $workOrder->toArray());  
100 - }  
101 -  
102 - /**  
103 - * B端用户修改工单,只能是修改工单状态  
104 - *  
105 - * @param \Illuminate\Http\Request $request  
106 - * @param int $id  
107 - * @return \Illuminate\Http\Response  
108 - */  
109 - public function update(WorkOrderUpdateRequest $request, $id)  
110 - {  
111 - $request->validated();  
112 - $workOrder = WorkOrder::find($id);  
113 - if (!$workOrder) {  
114 - $this->response('工单未找到', 404);  
115 - }  
116 - // b端只有自己项目下的账号可以更新工单  
117 - if ($workOrder->project_id != $this->user['project_id']) {  
118 - $this->response('无权限更新该工单', 403);  
119 - }  
120 - // 更新工单状态  
121 - $workOrder->status = WorkOrder::STATUS_COMPLETED;  
122 - $workOrder->end_at = now();  
123 - $workOrder->save();  
124 - // B端完成工单,将所有未完成的子工单状态改为已完成。并记录完成时间  
125 - $workOrder->logs()->where('status', '<', WorkOrderLog::STATUS_COMPLETED)  
126 - ->update(['status' => WorkOrderLog::STATUS_COMPLETED, 'end_at' => now()]);  
127 - $this->response('success', Code::SUCCESS);  
128 - }  
129 -  
130 - public function destroy($id)  
131 - {  
132 - $workOrder = WorkOrder::find($id);  
133 - if (!$workOrder) {  
134 - $this->response('工单未找到', 404);  
135 - }  
136 - if ($workOrder->status >= WorkOrder::STATUS_COMPLETED)  
137 - $this->response('已完结的工单不能删除', 403);  
138 -  
139 - if ($this->user['type'] != 1 && $workOrder->project_user_id != $this->user['id']) {  
140 - // 只有项目负责人可以删除工单  
141 - $this->response('无权限删除该工单', 403);  
142 - }  
143 - # 删除工单  
144 - $workOrder->delete();  
145 - $this->response('工单已删除', Code::SUCCESS);  
146 -  
147 - }  
148 -  
149 -}  
1 <?php 1 <?php
2 2
3 -namespace App\Http\Requests\Bside\WorkOrder; 3 +namespace App\Http\Requests\Api\WorkOrder;
4 4
5 use Illuminate\Foundation\Http\FormRequest; 5 use Illuminate\Foundation\Http\FormRequest;
6 6
7 -class WorkOrderCreateRequest extends FormRequest 7 +class TicketChatStoreRequest extends FormRequest
8 { 8 {
9 /** 9 /**
10 * Determine if the user is authorized to make this request. 10 * Determine if the user is authorized to make this request.
@@ -24,9 +24,9 @@ class WorkOrderCreateRequest extends FormRequest @@ -24,9 +24,9 @@ class WorkOrderCreateRequest extends FormRequest
24 public function rules() 24 public function rules()
25 { 25 {
26 return [ 26 return [
27 - 'product' => 'required|string',  
28 'content' => 'required|string', 27 'content' => 'required|string',
29 'files' => 'nullable|array', 28 'files' => 'nullable|array',
  29 + 'submit_username' => 'required|string',
30 ]; 30 ];
31 } 31 }
32 } 32 }
@@ -24,9 +24,10 @@ class AsideTicketListRequest extends FormRequest @@ -24,9 +24,10 @@ class AsideTicketListRequest extends FormRequest
24 public function rules() 24 public function rules()
25 { 25 {
26 return [ 26 return [
27 - 'project_id' => 'nullable|string', // 产品ID 27 + 'project_id' => 'nullable|string',
28 'status' => 'nullable|in:0,1,2,3|integer', 28 'status' => 'nullable|in:0,1,2,3|integer',
29 'search' => 'nullable|string', // 搜索关键词 29 'search' => 'nullable|string', // 搜索关键词
  30 + 'engineer_id' => 'nullable|integer', // 工程师ID
30 'page' => 'nullable|integer', 31 'page' => 'nullable|integer',
31 'size' => 'nullable|integer', 32 'size' => 'nullable|integer',
32 ]; 33 ];
1 -<?php  
2 -  
3 -namespace App\Http\Requests\Aside\WorkOrder;  
4 -  
5 -use Illuminate\Foundation\Http\FormRequest;  
6 -  
7 -class WorkOrderListRequest 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 - 'page' => 'nullable|integer',  
28 - 'size' => 'nullable|integer',  
29 - 'project_id' => 'nullable|integer', // 产品ID  
30 - 'status' => 'nullable|in:0,1,2,3|integer',  
31 - 'search' => 'nullable|string', // 搜索关键词  
32 - ];  
33 - }  
34 -}  
1 -<?php  
2 -  
3 -namespace App\Http\Requests\Aside\WorkOrder;  
4 -  
5 -use Illuminate\Foundation\Http\FormRequest;  
6 -  
7 -class WorkOrderUpdateRequest 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 - * A端更新售后工单  
24 - */  
25 - public function rules()  
26 - {  
27 - return [  
28 - 'status' => 'nullable|in:0,1,2,3|integer',  
29 - 'engineer_ids' => 'nullable|array',  
30 - 'content' => 'nullable|string',  
31 - 'files' => 'nullable|array',  
32 - ];  
33 - }  
34 -}  
1 -<?php  
2 -  
3 -namespace App\Http\Requests\Bside\WorkOrder;  
4 -  
5 -use Illuminate\Foundation\Http\FormRequest;  
6 -  
7 -class WorkOrderUpdateRequest 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 - 'engineer_ids' => 'nullable|array',  
29 - 'content' => 'nullable|string',  
30 - 'files' => 'nullable|array',  
31 - ];  
32 - }  
33 -}  
  1 +<?php
  2 +
  3 +namespace App\Models\WorkOrder;
  4 +
  5 +use App\Models\Base;
  6 +use Illuminate\Database\Eloquent\Factories\HasFactory;
  7 +
  8 +class TicketChat extends Base
  9 +{
  10 + use HasFactory;
  11 +
  12 + protected $table = 'gl_ticket_chats';
  13 +
  14 + /**
  15 + * 关联工单
  16 + */
  17 + public function ticket()
  18 + {
  19 + return $this->belongsTo(Tickets::class, 'ticket_id', 'id');
  20 + }
  21 +}
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 App\Models\User\User;  
9 -  
10 -class WorkOrder extends Base  
11 -{  
12 - protected $table = 'gl_work_orders';  
13 -  
14 - const STATUS_PEDDING = 0; // 待处理  
15 - const STATUS_PROCESSING = 1; // 处理中  
16 - const STATUS_COMPLETED = 2; // 已完成  
17 - const STATUS_CLOSED = 3; // 已关闭  
18 -  
19 -  
20 - /**  
21 - * 工单操作日志  
22 - */  
23 - public function logs()  
24 - {  
25 - return $this->hasMany(WorkOrderLog::class, 'work_order_id', 'id');  
26 - }  
27 -  
28 - /**  
29 - * 提交工单的用户  
30 - */  
31 - public function user()  
32 - {  
33 - return $this->belongsTo(User::class, 'project_user_id', 'id');  
34 - }  
35 -  
36 - /**  
37 - * 工单分配的管理员  
38 - */  
39 - public function manager()  
40 - {  
41 - return $this->belongsTo(Manage::class, 'manage_id', 'id');  
42 - }  
43 -  
44 - /**  
45 - * 工单分配的工程师  
46 - */  
47 - public function engineer()  
48 - {  
49 - return $this->belongsTo(Manage::class, 'engineer_id', 'id');  
50 - }  
51 -  
52 - /** 工单所属项目 */  
53 - public function project()  
54 - {  
55 - return $this->belongsTo(Project::class, 'project_id', 'id');  
56 - }  
57 -}  
1 -<?php  
2 -  
3 -namespace App\Models\WorkOrder;  
4 -  
5 -use App\Models\Base;  
6 -use App\Models\Manage\Manage;  
7 -  
8 -class WorkOrderLog extends Base  
9 -{  
10 - protected $table = 'gl_work_order_logs';  
11 -  
12 - const STATUS_PEDDING = 0; // 待处理  
13 - const STATUS_PROCESSING = 1; // 处理中  
14 - const STATUS_COMPLETED = 2; // 已完成  
15 - const STATUS_CLOSED = 3; // 已关闭  
16 -  
17 - /**  
18 - * 所属工单  
19 - */  
20 - public function workOrder()  
21 - {  
22 - return $this->belongsTo(WorkOrder::class, 'work_order_id');  
23 - }  
24 -  
25 - /**  
26 - * 分配的工单负责人,工程师等  
27 - */  
28 - public function manager()  
29 - {  
30 - return $this->belongsTo(Manage::class, 'manage_id', 'id');  
31 - }  
32 -}  
  1 +<?php
  2 +
  3 +use Illuminate\Database\Migrations\Migration;
  4 +use Illuminate\Database\Schema\Blueprint;
  5 +use Illuminate\Support\Facades\Schema;
  6 +
  7 +class CreateTicketChatsTable extends Migration
  8 +{
  9 + /**
  10 + * Run the migrations.
  11 + *
  12 + * @return void
  13 + */
  14 + public function up()
  15 + {
  16 + Schema::create('ticket_chats', function (Blueprint $table) {
  17 + $table->id();
  18 + $table->longText('content')->comment('消息内容');
  19 + $table->json('files')->nullable()->comment('附件');
  20 + $table->foreignId('ticket_id')->constrained('gl_tickets')->onDelete('cascade')->comment('工单ID');
  21 + $table->integer('manage_id')->default(0)->comment('gl_manage 表ID');
  22 + $table->integer('submit_side')->index()->default(1)->comment('提交方,1: A端, 2: B端');
  23 + $table->string('submit_username')->nullable()->comment('提交人姓名,B端在企微群提交时,留个姓名即可');
  24 + $table->timestamps();
  25 + });
  26 + }
  27 +
  28 + /**
  29 + * Reverse the migrations.
  30 + *
  31 + * @return void
  32 + */
  33 + public function down()
  34 + {
  35 + Schema::dropIfExists('ticket_chats');
  36 + }
  37 +}
@@ -83,4 +83,6 @@ Route::prefix('tickets')->group(function () { @@ -83,4 +83,6 @@ Route::prefix('tickets')->group(function () {
83 Route::get('/projectInfo/{project_id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'projectInfo'])->summary('B端,渠道-项目信息')->name('tickets.projectInfo'); 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'); 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'); 85 Route::get('/{project_id}/{id}', [\App\Http\Controllers\Api\WorkOrder\TicketController::class, 'show'])->summary('B端,渠道-工单详情')->name('tickets.show');
  86 + Route::get('/chat/{project_id}/{ticket_id}', [\App\Http\Controllers\Api\WorkOrder\TicketChatController::class, 'index'])->summary('B端,渠道-工单聊天记录')->name('tickets.chat.index');
  87 + Route::post('/chat/{project_id}/{ticket_id}', [\App\Http\Controllers\Api\WorkOrder\TicketChatController::class, 'store'])->summary('B端,渠道-工单聊天记录提交')->name('tickets.chat.store');
86 }); 88 });
@@ -248,13 +248,6 @@ Route::middleware(['aloginauth'])->group(function () { @@ -248,13 +248,6 @@ Route::middleware(['aloginauth'])->group(function () {
248 Route::post('/save_follow', [Aside\Task\TaskController::class, 'save_follow'])->name('admin.task_save_follow'); 248 Route::post('/save_follow', [Aside\Task\TaskController::class, 'save_follow'])->name('admin.task_save_follow');
249 Route::any('/getUserTaskList', [Aside\Task\TaskController::class, 'getUserTaskList'])->name('admin.task_getUserTaskList'); 249 Route::any('/getUserTaskList', [Aside\Task\TaskController::class, 'getUserTaskList'])->name('admin.task_getUserTaskList');
250 }); 250 });
251 - // 售后工单  
252 - Route::prefix('workorder')->group(function () {  
253 - Route::get('/', [Aside\WorkOrder\WorkOrderController::class, 'index'])->name('admin.workorder.index')->summary('A端工程师的工单列表');  
254 - Route::get('/manager', [Aside\WorkOrder\WorkOrderController::class, 'manager'])->name('admin.workorder.manager')->summary('A端管理员的工单列表');  
255 - 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 - });  
258 // 售后工单改版 251 // 售后工单改版
259 Route::prefix('tickets')->group(function () { 252 Route::prefix('tickets')->group(function () {
260 Route::get('/', [Aside\WorkOrder\AsideTicketController::class, 'index'])->name('admin.tickets.index')->summary('A端工单列表'); 253 Route::get('/', [Aside\WorkOrder\AsideTicketController::class, 'index'])->name('admin.tickets.index')->summary('A端工单列表');
@@ -263,6 +256,8 @@ Route::middleware(['aloginauth'])->group(function () { @@ -263,6 +256,8 @@ Route::middleware(['aloginauth'])->group(function () {
263 Route::post('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'update'])->name('admin.tickets.update')->summary('A端更新工单,审核,邀请同事'); 256 Route::post('/{id}', [Aside\WorkOrder\AsideTicketController::class, 'update'])->name('admin.tickets.update')->summary('A端更新工单,审核,邀请同事');
264 Route::get('/projects/{search}', [Aside\WorkOrder\AsideTicketController::class, 'getProjects'])->name('admin.tickets.projects')->summary('A端V5V6项目列表'); 257 Route::get('/projects/{search}', [Aside\WorkOrder\AsideTicketController::class, 'getProjects'])->name('admin.tickets.projects')->summary('A端V5V6项目列表');
265 Route::post('/log/{id}', [Aside\WorkOrder\AsideTicketLogController::class, 'update'])->name('admin.tickets.log.update')->summary('A端工单操作日志更新,完成工单'); 258 Route::post('/log/{id}', [Aside\WorkOrder\AsideTicketLogController::class, 'update'])->name('admin.tickets.log.update')->summary('A端工单操作日志更新,完成工单');
  259 + Route::get('/chat/{ticket_id}', [Aside\WorkOrder\TicketChatController::class, 'index'])->name('admin.tickets.chat.index')->summary('A端工单聊天记录');
  260 + Route::post('/chat/{ticket_id}', [Aside\WorkOrder\TicketChatController::class, 'store'])->name('admin.tickets.chat.store')->summary('A端工单聊天记录创建');
266 }); 261 });
267 262
268 //服务器配置 263 //服务器配置