From 87d725aa16dcdcdd19f28cd3f3f162e950fd1d2f Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 03 十一月 2026 09:13:20 +0800
Subject: [PATCH] feat(aftersales): 工单助手 App 闭环(签到/转派/升级/处理记录/进度/统计)

---
 yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/ticket/AfterSaleTicketController.java |   84 ++++++++++++++++++++++++++++++++++++++---
 1 files changed, 77 insertions(+), 7 deletions(-)

diff --git a/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/ticket/AfterSaleTicketController.java b/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/ticket/AfterSaleTicketController.java
index 4f6cddd..35a0321 100644
--- a/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/ticket/AfterSaleTicketController.java
+++ b/yudao-module-aftersales/src/main/java/cn/iocoder/yudao/module/aftersales/controller/admin/ticket/AfterSaleTicketController.java
@@ -5,11 +5,19 @@
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketEscalateReqVO;
+import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketHandleReqVO;
+import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketLogRespVO;
 import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketPageReqVO;
 import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketRespVO;
 import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketSaveReqVO;
+import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketSignInReqVO;
+import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketStatisticsRespVO;
+import cn.iocoder.yudao.module.aftersales.controller.admin.ticket.vo.ticket.AfterSaleTicketTransferReqVO;
 import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketDO;
 import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketItemDO;
+import cn.iocoder.yudao.module.aftersales.dal.dataobject.ticket.AfterSaleTicketLogDO;
+import cn.iocoder.yudao.module.aftersales.enums.AfterSaleTicketLogActionEnum;
 import cn.iocoder.yudao.module.aftersales.service.ticket.AfterSaleTicketService;
 import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi;
 import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO;
@@ -73,7 +81,6 @@
     @GetMapping("/get")
     @Operation(summary = "鑾峰緱鍞悗宸ュ崟")
     @Parameter(name = "id", description = "宸ュ崟缂栧彿", required = true, example = "1")
-    @PreAuthorize("@ss.hasPermission('aftersales:ticket:query')")
     public CommonResult<AfterSaleTicketRespVO> getTicket(@RequestParam("id") Long id) {
         AfterSaleTicketDO ticket = ticketService.getTicket(id);
         List<AfterSaleTicketItemDO> items = ticketService.getTicketItemListByTicketId(id);
@@ -87,7 +94,6 @@
 
     @GetMapping("/page")
     @Operation(summary = "鑾峰緱鍞悗宸ュ崟鍒嗛〉")
-    @PreAuthorize("@ss.hasPermission('aftersales:ticket:query')")
     public CommonResult<PageResult<AfterSaleTicketRespVO>> getTicketPage(@Valid AfterSaleTicketPageReqVO pageReqVO) {
         PageResult<AfterSaleTicketDO> pageResult = ticketService.getTicketPage(pageReqVO, getLoginUserId());
         List<AfterSaleTicketRespVO> list = buildTicketDetailList(pageResult.getList());
@@ -99,7 +105,7 @@
     @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')")
     public CommonResult<Boolean> assignTicket(@RequestParam("id") Long id,
                                               @RequestParam("handlerUserId") Long handlerUserId) {
-        ticketService.assignTicket(id, handlerUserId);
+        ticketService.assignTicket(id, handlerUserId, getLoginUserId());
         return success(true);
     }
 
@@ -110,7 +116,7 @@
                                                 @RequestParam("issueType") Integer issueType,
                                                 @RequestParam(value = "issueCategory", required = false) String issueCategory,
                                                 @RequestParam(value = "severityLevel", required = false) Integer severityLevel) {
-        ticketService.classifyTicket(id, issueType, issueCategory, severityLevel);
+        ticketService.classifyTicket(id, issueType, issueCategory, severityLevel, getLoginUserId());
         return success(true);
     }
 
@@ -118,7 +124,7 @@
     @Operation(summary = "瀹岀粨宸ュ崟")
     @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')")
     public CommonResult<Boolean> resolveTicket(@RequestParam("id") Long id) {
-        ticketService.resolveTicket(id);
+        ticketService.resolveTicket(id, getLoginUserId());
         return success(true);
     }
 
@@ -126,7 +132,7 @@
     @Operation(summary = "鍏抽棴宸ュ崟")
     @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')")
     public CommonResult<Boolean> closeTicket(@RequestParam("id") Long id) {
-        ticketService.closeTicket(id);
+        ticketService.closeTicket(id, getLoginUserId());
         return success(true);
     }
 
@@ -134,10 +140,74 @@
     @Operation(summary = "鍙栨秷宸ュ崟")
     @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')")
     public CommonResult<Boolean> cancelTicket(@RequestParam("id") Long id) {
-        ticketService.cancelTicket(id);
+        ticketService.cancelTicket(id, getLoginUserId());
         return success(true);
     }
 
+    @PostMapping("/sign-in")
+    @Operation(summary = "鐜板満绛惧埌")
+    @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')")
+    public CommonResult<Boolean> signInTicket(@Valid @RequestBody AfterSaleTicketSignInReqVO reqVO) {
+        ticketService.signInTicket(reqVO, getLoginUserId());
+        return success(true);
+    }
+
+    @PostMapping("/transfer")
+    @Operation(summary = "杞淳宸ュ崟")
+    @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')")
+    public CommonResult<Boolean> transferTicket(@Valid @RequestBody AfterSaleTicketTransferReqVO reqVO) {
+        ticketService.transferTicket(reqVO, getLoginUserId());
+        return success(true);
+    }
+
+    @PostMapping("/escalate")
+    @Operation(summary = "鍗囩骇宸ュ崟")
+    @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')")
+    public CommonResult<Boolean> escalateTicket(@Valid @RequestBody AfterSaleTicketEscalateReqVO reqVO) {
+        ticketService.escalateTicket(reqVO, getLoginUserId());
+        return success(true);
+    }
+
+    @PostMapping("/handle")
+    @Operation(summary = "鏂板澶勭悊璁板綍")
+    @PreAuthorize("@ss.hasPermission('aftersales:ticket:update')")
+    public CommonResult<Boolean> addHandleRecord(@Valid @RequestBody AfterSaleTicketHandleReqVO reqVO) {
+        ticketService.addHandleRecord(reqVO, getLoginUserId());
+        return success(true);
+    }
+
+    @GetMapping("/log-list")
+    @Operation(summary = "鑾峰緱宸ュ崟鎿嶄綔/杩涘害璁板綍鍒楄〃")
+    @Parameter(name = "ticketId", description = "宸ュ崟缂栧彿", required = true, example = "1")
+    public CommonResult<List<AfterSaleTicketLogRespVO>> getTicketLogList(@RequestParam("ticketId") Long ticketId) {
+        return success(buildLogRespList(ticketService.getTicketLogList(ticketId)));
+    }
+
+    @GetMapping("/statistics")
+    @Operation(summary = "鑾峰緱宸ュ崟鍔╂墜缁熻")
+    @Parameter(name = "sceneType", description = "鍦烘櫙绫诲瀷: 1-鎴戣礋璐g殑 2-鎴戝弬涓庣殑 3-涓嬪睘璐熻矗鐨� 4-鍏ㄩ儴", example = "4")
+    public CommonResult<AfterSaleTicketStatisticsRespVO> getTicketStatistics(
+            @RequestParam(value = "sceneType", required = false) Integer sceneType) {
+        return success(ticketService.getTicketStatistics(sceneType, getLoginUserId()));
+    }
+
+    // ========== 鍐呴儴鏂规硶锛氭嫾瑁呰繘搴﹁褰� ==========
+
+    private List<AfterSaleTicketLogRespVO> buildLogRespList(List<AfterSaleTicketLogDO> logList) {
+        if (CollUtil.isEmpty(logList)) {
+            return Collections.emptyList();
+        }
+        Set<Long> userIds = convertSet(logList, AfterSaleTicketLogDO::getOperatorUserId);
+        Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(userIds);
+        return BeanUtils.toBean(logList, AfterSaleTicketLogRespVO.class, vo -> {
+            vo.setActionName(AfterSaleTicketLogActionEnum.getName(vo.getActionType()));
+            AdminUserRespDTO user = userMap.get(vo.getOperatorUserId());
+            if (user != null) {
+                vo.setOperatorUserName(user.getNickname());
+            }
+        });
+    }
+
     // ========== 鍐呴儴鏂规硶锛氭壒閲忔嫾瑁呭叧鑱斿悕绉� ==========
 
     private List<AfterSaleTicketRespVO> buildTicketDetailList(List<AfterSaleTicketDO> ticketList) {

--
Gitblit v1.9.3