作者 lyh

超过120小时未处理的工单

@@ -24,7 +24,9 @@ class AsideTicketController extends BaseController @@ -24,7 +24,9 @@ class AsideTicketController extends BaseController
24 */ 24 */
25 public function index(AsideTicketListRequest $request) 25 public function index(AsideTicketListRequest $request)
26 { 26 {
  27 +
27 $validated = $request->validated(); 28 $validated = $request->validated();
  29 +
28 $query = Tickets::with([ 30 $query = Tickets::with([
29 'logs.engineer', 31 'logs.engineer',
30 'project.pm', 32 'project.pm',
@@ -141,106 +143,111 @@ class AsideTicketController extends BaseController @@ -141,106 +143,111 @@ class AsideTicketController extends BaseController
141 } 143 }
142 $this->response('success', Code::SUCCESS, $lists); 144 $this->response('success', Code::SUCCESS, $lists);
143 } 145 }
144 -  
145 - /**  
146 - * @remark :列表数据  
147 - * @name :lists  
148 - * @author :lyh  
149 - * @method :post  
150 - * @time :2025/9/1 16:45  
151 - */  
152 public function lists(AsideTicketListRequest $request) 146 public function lists(AsideTicketListRequest $request)
153 { 147 {
154 $validated = $request->validated(); 148 $validated = $request->validated();
155 - $ticketsModel = new Tickets();  
156 - $query = $ticketsModel->leftJoin('gl_ticket_projects', 'gl_ticket_projects.id', '=', 'gl_tickets.project_id')  
157 - ->leftJoin('gl_ticket_logs', 'gl_ticket_logs.ticket_id', '=', 'gl_tickets.id')  
158 - ->select('gl_tickets.*', 'gl_ticket_logs.*', 'gl_ticket_projects.*')  
159 - ->distinct(); // 避免多条 logs 时数据重复  
160 149
161 - // 工程师过滤  
162 - if (!empty($validated['engineer_id'])) {  
163 - $engineerId = $validated['engineer_id'];  
164 - $query->where(function ($q) use ($engineerId) {  
165 - $q->where('gl_tickets.submit_user_id', $engineerId)  
166 - ->orWhere('gl_ticket_logs.engineer_id', $engineerId); 150 + // 1️⃣ 先构建主表查询(只查票据ID用于分页)
  151 + $ticketQuery = Tickets::query()
  152 + ->when(!empty($validated['engineer_id']), function ($query) use ($validated) {
  153 + $engineerId = $validated['engineer_id'];
  154 + return $query->where(function ($q) use ($engineerId) {
  155 + $q->where('submit_user_id', $engineerId)
  156 + ->orWhereHas('logs', function ($q1) use ($engineerId) {
  157 + $q1->where('engineer_id', $engineerId);
  158 + });
  159 + });
  160 + })
  161 + ->when($request->input('project_id') !== null, function ($query) use ($request) {
  162 + $projectId = $request->input('project_id');
  163 + return $query->whereHas('project', function ($q) use ($projectId) {
  164 + $q->where('uuid', $projectId);
  165 + });
  166 + })
  167 + ->when($request->input('status') !== null, function ($query) use ($request) {
  168 + $status = $request->input('status');
  169 + if($status == '-1'){
  170 + $newTime = now()->subHours(120);
  171 + return $query->where('status', 0)->where('plan_end_at', '<', $newTime);
  172 + } else {
  173 + return $query->where('status', $status);
  174 + }
  175 + })
  176 + ->when($request->input('timeout') !== null, function ($query) use ($request) {
  177 + $timeout = $request->input('timeout');
  178 + switch ($timeout) {
  179 + case 1: $newTime = now()->subHours(24); break;
  180 + case 2: $newTime = now()->subHours(48); break;
  181 + case 3: $newTime = now()->subHours(72); break;
  182 + default: $newTime = now(); break;
  183 + }
  184 + return $query->where('status', 0)->where('plan_end_at','<',$newTime);
  185 + })
  186 + ->when($request->input('star') !== null, function ($query) use ($request) {
  187 + return $query->where('star', $request->input('star'));
  188 + })
  189 + ->when($request->input('search'), function ($query) use ($request) {
  190 + $search = $request->input('search');
  191 + return $query->where(function ($q) use ($search) {
  192 + $q->where('title', 'like', "%{$search}%")
  193 + ->orWhereHas('project', function ($q1) use ($search) {
  194 + $q1->where('title', 'like', "%{$search}%")
  195 + ->orWhere('company_name', 'like', "%{$search}%");
  196 + });
  197 + });
  198 + })
  199 + ->when($request->input('project_status') !== null, function ($query) use ($request) {
  200 + return $query->whereHas('project', function ($q) use ($request) {
  201 + $q->where('status', $request->input('project_status'));
  202 + });
  203 + })
  204 + ->when($request->input('project_cate') !== null, function ($query) use ($request) {
  205 + return $query->whereHas('project', function ($q) use ($request) {
  206 + $q->where('project_cate', $request->input('project_cate'));
  207 + });
167 }); 208 });
168 - }  
169 - // project_id 过滤  
170 - if ($request->filled('project_id')) {  
171 - $query->where('gl_ticket_projects.uuid', $request->input('project_id'));  
172 - }  
173 - // status 过滤  
174 - if ($request->filled('status')) {  
175 - $status = $request->input('status');  
176 - if ($status == -1) {  
177 - $newTime = now()->subHours(120);  
178 - $query->where('gl_tickets.status', 0)  
179 - ->where('gl_tickets.plan_end_at', '<', $newTime);  
180 - } else {  
181 - $query->where('gl_tickets.status', $status);  
182 - }  
183 - }  
184 - // timeout 过滤  
185 - if ($request->filled('timeout')) {  
186 - $timeout = (int)$request->input('timeout');  
187 - switch ($timeout) {  
188 - case 1: $newTime = now()->subHours(24); break;  
189 - case 2: $newTime = now()->subHours(48); break;  
190 - case 3: $newTime = now()->subHours(72); break;  
191 - default: $newTime = now(); break;  
192 - }  
193 - $query->where('gl_tickets.status', 0)  
194 - ->where('gl_tickets.plan_end_at', '<', $newTime);  
195 - }  
196 - // star 过滤  
197 - if ($request->filled('star')) {  
198 - $query->where('gl_tickets.star', $request->input('star'));  
199 - }  
200 - // search 模糊搜索  
201 - if ($request->filled('search')) {  
202 - $search = $request->input('search');  
203 - $query->where(function ($q) use ($search) {  
204 - $q->where('gl_tickets.title', 'like', "%$search%")  
205 - ->orWhere('gl_ticket_projects.title', 'like', "%$search%")  
206 - ->orWhere('gl_ticket_projects.company_name', 'like', "%$search%"); 209 +
  210 + // 部门筛选
  211 + if(isset($this->param['dept_id']) && !empty($this->param['dept_id'])){
  212 + $manageIdArr = (new ManageHr())->selectField(['dept_id'=>$this->param['dept_id'],'status'=>1],'manage_id');
  213 + $ticketQuery->whereHas('logs', function ($q) use ($manageIdArr) {
  214 + $q->whereIn('engineer_id', $manageIdArr);
207 }); 215 });
208 } 216 }
209 - // project_status  
210 - if ($request->filled('project_status')) {  
211 - $query->where('gl_ticket_projects.status', $request->input('project_status'));  
212 - }  
213 - // project_cate  
214 - if ($request->filled('project_cate')) {  
215 - $query->where('gl_ticket_projects.project_cate', $request->input('project_cate'));  
216 - }  
217 - // 部门搜索  
218 - if (!empty($this->param['dept_id'])) {  
219 - $manageHrModel = new ManageHr();  
220 - $manageIdArr = $manageHrModel->selectField(['dept_id'=>$this->param['dept_id'],'status'=>1],'manage_id');  
221 - $query->whereIn('gl_ticket_logs.engineer_id', $manageIdArr);  
222 - }  
223 - // 时间区间  
224 - if (!empty($this->param['start_at']) && !empty($this->param['end_at'])) {  
225 - $query->whereBetween('gl_tickets.created_at', [$this->param['start_at'], $this->param['end_at']]); 217 +
  218 + // 时间区间筛选
  219 + if(!empty($this->param['start_at']) && !empty($this->param['end_at'])){
  220 + $ticketQuery->whereBetween('created_at', [$this->param['start_at'], $this->param['end_at']]);
226 } 221 }
227 // 排序 222 // 排序
228 - $query->orderBy('gl_tickets.status', 'asc');  
229 - $sortField = $request->input('sort_field', 'gl_tickets.plan_end_at'); 223 + $sortField = $request->input('sort_field', 'plan_end_at');
230 $sortOrder = strtolower($request->input('sort_order', 'asc')); 224 $sortOrder = strtolower($request->input('sort_order', 'asc'));
231 - $query->orderBy($sortField, $sortOrder);  
232 - if ($sortField != 'gl_tickets.plan_end_at') {  
233 - $query->orderBy('gl_tickets.plan_end_at', 'asc');  
234 - }  
235 - // 分页 (建议用 simplePaginate 提速)  
236 - $lists = $query->paginate($this->row, ['*'], 'page', $this->page);  
237 - // 计算超时小时数(也可以 SQL 里用 TIMESTAMPDIFF 算好)  
238 - foreach ($lists as $item) {  
239 - if ($item->status == 0 && $item->plan_end_at < now()) { 225 + $ticketQuery->orderBy('status', 'asc')
  226 + ->orderBy($sortField, $sortOrder);
  227 + if ($sortField != 'plan_end_at') $ticketQuery->orderBy('plan_end_at', 'asc');
  228 + // 2️⃣ 分页只获取主表ID
  229 + $page = $this->page;
  230 + $row = $this->row;
  231 + $ticketIds = $ticketQuery->clone()->paginate($row, ['id'], 'page', $page);
  232 + // 3️⃣ 批量加载关联表
  233 + $lists = Tickets::with([
  234 + 'logs.engineer',
  235 + 'project.pm',
  236 + 'project.projectV6'
  237 + ])->whereIn('id', $ticketIds->pluck('id'))->get();
  238 + // 4️⃣ 计算 plan_ent_time
  239 + $lists->transform(function($item){
  240 + if($item->status == 0 && $item->plan_end_at && $item->plan_end_at < now()){
240 $item->plan_ent_time = diffInHours($item->plan_end_at, now()); 241 $item->plan_ent_time = diffInHours($item->plan_end_at, now());
241 } 242 }
242 - }  
243 - $this->response('success', Code::SUCCESS, $lists); 243 + return $item;
  244 + });
  245 + $this->response('success', Code::SUCCESS, [
  246 + 'current_page' => $page,
  247 + 'last_page' => $ticketIds->lastPage(),
  248 + 'total' => $ticketIds->total(),
  249 + 'list' => $lists
  250 + ]);
244 } 251 }
245 252
246 /** 253 /**