jiaxing.zhou

feat(exception-workorder): 新增异常工单数据导出功能

- 在API文档中添加异常工单数据导出接口说明
- 后端增加导出接口及对应的数据查询方法
- 前端实现异常工单导出功能并与后端对接
- 完善Excel导出服务集成与调用逻辑
- 更新相关权限控制与响应处理逻辑
- 补充前后端交互所需的类型定义和请求封装
...@@ -2423,8 +2423,418 @@ Authorization: Bearer <JWT_TOKEN> ...@@ -2423,8 +2423,418 @@ Authorization: Bearer <JWT_TOKEN>
2423 2423
2424 **响应:** 返回Excel文件流,文件名格式:`发票数据_yyyyMMdd_HHmmss.xlsx` 2424 **响应:** 返回Excel文件流,文件名格式:`发票数据_yyyyMMdd_HHmmss.xlsx`
2425 2425
2426 +### 4. 异常工单数据导出
2427 +
2428 +**接口路径:** `POST /api/exception-workorder/export`
2429 +**请求方法:** POST
2430 +**权限要求:** `exception:workorder:export`
2431 +
2432 +**请求参数:** 同异常工单查询接口参数
2433 +
2434 +**响应:** 返回Excel文件流,文件名格式:`异常工单数据_yyyyMMdd_HHmmss.xlsx`
2435 +
2436 +## 12. 异常工单管理 (ExceptionWorkorderController)
2437 +
2438 +### 12.1 分页查询异常工单列表
2439 +
2440 +**接口路径:** `GET /api/exception-workorder/list`
2441 +
2442 +**功能描述:** 根据条件分页查询异常工单列表
2443 +
2444 +**请求头:**
2445 +```
2446 +Authorization: Bearer <JWT_TOKEN>
2447 +```
2448 +
2449 +**请求参数:**
2450 +| 参数名 | 类型 | 必填 | 说明 |
2451 +|--------|------|------|------|
2452 +| workorderNo | String | 否 | 工单编号(模糊查询) |
2453 +| orderNo | String | 否 | 关联订单号(模糊查询) |
2454 +| dealerCode | String | 否 | 经销商编码 |
2455 +| dealerName | String | 否 | 经销商名称(模糊查询) |
2456 +| workorderStatus | Integer | 否 | 工单状态(1-待处理/2-处理中/3-已解决/4-已关闭) |
2457 +| exceptionType | Integer | 否 | 异常类型(1-逻辑验证异常/2-源头验证异常/3-交叉验证异常) |
2458 +| severityLevel | Integer | 否 | 严重程度(1-高/2-中/3-低) |
2459 +| handlerUser | String | 否 | 处理人(模糊查询) |
2460 +| startTime | String | 否 | 创建开始时间(yyyy-MM-dd HH:mm:ss) |
2461 +| endTime | String | 否 | 创建结束时间(yyyy-MM-dd HH:mm:ss) |
2462 +| pageNum | Integer | 是 | 页码,默认1 |
2463 +| pageSize | Integer | 是 | 每页大小,默认10 |
2464 +
2465 +**权限要求:** `exception:workorder:list`
2466 +
2467 +**响应示例:**
2468 +```json
2469 +{
2470 + "code": 200,
2471 + "message": "操作成功",
2472 + "data": {
2473 + "records": [
2474 + {
2475 + "workorderId": 1,
2476 + "workorderNo": "EW202501290001",
2477 + "orderNo": "ORD202501290001",
2478 + "dealerCode": "D001",
2479 + "dealerName": "北京经销商",
2480 + "exceptionType": 1,
2481 + "exceptionTypeName": "逻辑验证异常",
2482 + "severityLevel": 1,
2483 + "severityLevelName": "高",
2484 + "workorderStatus": 1,
2485 + "workorderStatusName": "待处理",
2486 + "createTime": "2025-01-29 10:00:00",
2487 + "expectCompleteTime": "2025-01-30 18:00:00",
2488 + "handlerUser": "张三",
2489 + "exceptionDesc": "订单金额与产品单价不匹配",
2490 + "handleSuggest": "请核实订单明细",
2491 + "dataSource": "系统自动生成",
2492 + "createBy": "system",
2493 + "updateBy": null,
2494 + "updateTime": null,
2495 + "workorderLogs": []
2496 + }
2497 + ],
2498 + "total": 1,
2499 + "size": 10,
2500 + "current": 1,
2501 + "pages": 1
2502 + }
2503 +}
2504 +```
2505 +
2506 +### 12.2 获取异常工单详情
2507 +
2508 +**接口路径:** `GET /api/exception-workorder/{workorderId}`
2509 +
2510 +**功能描述:** 根据工单ID获取异常工单详细信息,包含处理日志
2511 +
2512 +**请求头:**
2513 +```
2514 +Authorization: Bearer <JWT_TOKEN>
2515 +```
2516 +
2517 +**路径参数:**
2518 +| 参数名 | 类型 | 必填 | 说明 |
2519 +|--------|------|------|------|
2520 +| workorderId | Long | 是 | 工单ID |
2521 +
2522 +**权限要求:** `exception:workorder:detail`
2523 +
2524 +**响应示例:**
2525 +```json
2526 +{
2527 + "code": 200,
2528 + "message": "操作成功",
2529 + "data": {
2530 + "workorderId": 1,
2531 + "workorderNo": "EW202501290001",
2532 + "orderNo": "ORD202501290001",
2533 + "dealerCode": "D001",
2534 + "dealerName": "北京经销商",
2535 + "exceptionType": 1,
2536 + "exceptionTypeName": "逻辑验证异常",
2537 + "severityLevel": 1,
2538 + "severityLevelName": "高",
2539 + "workorderStatus": 2,
2540 + "workorderStatusName": "处理中",
2541 + "createTime": "2025-01-29 10:00:00",
2542 + "expectCompleteTime": "2025-01-30 18:00:00",
2543 + "handlerUser": "张三",
2544 + "exceptionDesc": "订单金额与产品单价不匹配",
2545 + "handleSuggest": "请核实订单明细",
2546 + "dataSource": "系统自动生成",
2547 + "createBy": "system",
2548 + "updateBy": "张三",
2549 + "updateTime": "2025-01-29 11:00:00",
2550 + "workorderLogs": [
2551 + {
2552 + "logId": 1,
2553 + "workorderId": 1,
2554 + "workorderNo": "EW202501290001",
2555 + "handleUser": "张三",
2556 + "handleTime": "2025-01-29 11:00:00",
2557 + "beforeStatus": 1,
2558 + "beforeStatusName": "待处理",
2559 + "afterStatus": 2,
2560 + "afterStatusName": "处理中",
2561 + "handleOpinion": "开始处理此工单",
2562 + "attachUrl": null,
2563 + "createBy": "张三",
2564 + "createTime": "2025-01-29 11:00:00"
2565 + }
2566 + ]
2567 + }
2568 +}
2569 +```
2570 +
2571 +### 12.3 新增异常工单
2572 +
2573 +**接口路径:** `POST /api/exception-workorder`
2574 +
2575 +**功能描述:** 创建新的异常工单
2576 +
2577 +**请求头:**
2578 +```
2579 +Authorization: Bearer <JWT_TOKEN>
2580 +Content-Type: application/json
2581 +```
2582 +
2583 +**请求体:**
2584 +```json
2585 +{
2586 + "workorderNo": "EW202501290002",
2587 + "orderNo": "ORD202501290002",
2588 + "dealerCode": "D002",
2589 + "dealerName": "上海经销商",
2590 + "exceptionType": 2,
2591 + "severityLevel": 2,
2592 + "workorderStatus": 1,
2593 + "expectCompleteTime": "2025-01-30 18:00:00",
2594 + "handlerUser": "李四",
2595 + "exceptionDesc": "经销商信息不完整",
2596 + "handleSuggest": "请补充经销商详细信息",
2597 + "dataSource": "手动创建"
2598 +}
2599 +```
2600 +
2601 +**权限要求:** `exception:workorder:add`
2602 +
2603 +**响应示例:**
2604 +```json
2605 +{
2606 + "code": 200,
2607 + "message": "新增异常工单成功",
2608 + "data": null
2609 +}
2610 +```
2611 +
2612 +### 12.4 更新异常工单
2613 +
2614 +**接口路径:** `PUT /api/exception-workorder`
2615 +
2616 +**功能描述:** 更新异常工单信息
2617 +
2618 +**请求头:**
2619 +```
2620 +Authorization: Bearer <JWT_TOKEN>
2621 +Content-Type: application/json
2622 +```
2623 +
2624 +**请求体:**
2625 +```json
2626 +{
2627 + "workorderId": 1,
2628 + "workorderNo": "EW202501290001",
2629 + "orderNo": "ORD202501290001",
2630 + "dealerCode": "D001",
2631 + "dealerName": "北京经销商",
2632 + "exceptionType": 1,
2633 + "severityLevel": 1,
2634 + "workorderStatus": 2,
2635 + "expectCompleteTime": "2025-01-30 18:00:00",
2636 + "handlerUser": "张三",
2637 + "exceptionDesc": "订单金额与产品单价不匹配",
2638 + "handleSuggest": "请核实订单明细并联系客户确认",
2639 + "dataSource": "系统自动生成"
2640 +}
2641 +```
2642 +
2643 +**权限要求:** `exception:workorder:edit`
2644 +
2645 +**响应示例:**
2646 +```json
2647 +{
2648 + "code": 200,
2649 + "message": "更新异常工单成功",
2650 + "data": null
2651 +}
2652 +```
2653 +
2654 +### 12.5 更新工单状态
2655 +
2656 +**接口路径:** `POST /api/exception-workorder/status`
2657 +
2658 +**功能描述:** 更新异常工单状态并记录处理日志
2659 +
2660 +**请求头:**
2661 +```
2662 +Authorization: Bearer <JWT_TOKEN>
2663 +Content-Type: application/json
2664 +```
2665 +
2666 +**请求体:**
2667 +```json
2668 +{
2669 + "workorderId": 1,
2670 + "workorderStatus": 3,
2671 + "handlerUser": "张三",
2672 + "handleOpinion": "问题已解决,客户确认无误",
2673 + "attachUrl": "http://example.com/attachment.pdf"
2674 +}
2675 +```
2676 +
2677 +**权限要求:** `exception:workorder:edit`
2678 +
2679 +**响应示例:**
2680 +```json
2681 +{
2682 + "code": 200,
2683 + "message": "更新工单状态成功",
2684 + "data": null
2685 +}
2686 +```
2687 +
2688 +### 12.6 删除异常工单
2689 +
2690 +**接口路径:** `DELETE /api/exception-workorder/{workorderId}`
2691 +
2692 +**功能描述:** 根据工单ID逻辑删除异常工单
2693 +
2694 +**请求头:**
2695 +```
2696 +Authorization: Bearer <JWT_TOKEN>
2697 +```
2698 +
2699 +**路径参数:**
2700 +| 参数名 | 类型 | 必填 | 说明 |
2701 +|--------|------|------|------|
2702 +| workorderId | Long | 是 | 工单ID |
2703 +
2704 +**权限要求:** `exception:workorder:delete`
2705 +
2706 +**响应示例:**
2707 +```json
2708 +{
2709 + "code": 200,
2710 + "message": "删除异常工单成功",
2711 + "data": null
2712 +}
2713 +```
2714 +
2715 +### 12.7 批量删除异常工单
2716 +
2717 +**接口路径:** `DELETE /api/exception-workorder/batch`
2718 +
2719 +**功能描述:** 根据工单ID列表批量逻辑删除异常工单
2720 +
2721 +**请求头:**
2722 +```
2723 +Authorization: Bearer <JWT_TOKEN>
2724 +Content-Type: application/json
2725 +```
2726 +
2727 +**请求体:**
2728 +```json
2729 +[1, 2, 3]
2730 +```
2731 +
2732 +**权限要求:** `exception:workorder:delete`
2733 +
2734 +**响应示例:**
2735 +```json
2736 +{
2737 + "code": 200,
2738 + "message": "批量删除异常工单成功",
2739 + "data": null
2740 +}
2741 +```
2742 +
2743 +### 12.8 批量更新工单状态
2744 +
2745 +**接口路径:** `POST /api/exception-workorder/batch-status`
2746 +
2747 +**功能描述:** 批量更新异常工单状态
2748 +
2749 +**请求头:**
2750 +```
2751 +Authorization: Bearer <JWT_TOKEN>
2752 +```
2753 +
2754 +**请求参数:**
2755 +| 参数名 | 类型 | 必填 | 说明 |
2756 +|--------|------|------|------|
2757 +| workorderIds | String | 是 | 工单ID列表,逗号分隔 |
2758 +| workorderStatus | Integer | 是 | 工单状态 |
2759 +| handlerUser | String | 是 | 处理人 |
2760 +
2761 +**权限要求:** `exception:workorder:edit`
2762 +
2763 +**响应示例:**
2764 +```json
2765 +{
2766 + "code": 200,
2767 + "message": "批量更新工单状态成功",
2768 + "data": null
2769 +}
2770 +```
2771 +
2772 +### 12.9 获取异常工单统计信息
2773 +
2774 +**接口路径:** `GET /api/exception-workorder/stats`
2775 +
2776 +**功能描述:** 获取异常工单的统计信息
2777 +
2778 +**请求头:**
2779 +```
2780 +Authorization: Bearer <JWT_TOKEN>
2781 +```
2782 +
2783 +**权限要求:** `exception:workorder:list`
2784 +
2785 +**响应示例:**
2786 +```json
2787 +{
2788 + "code": 200,
2789 + "message": "操作成功",
2790 + "data": [
2791 + {
2792 + "workorderNo": "total",
2793 + "workorderId": 10,
2794 + "exceptionType": 3,
2795 + "severityLevel": 2,
2796 + "workorderStatus": 4,
2797 + "handlerUser": 1,
2798 + "exceptionDesc": 5,
2799 + "handleSuggest": 3,
2800 + "dataSource": 2
2801 + }
2802 + ]
2803 +}
2804 +```
2805 +
2806 +### 12.10 导出异常工单数据
2807 +
2808 +**接口路径:** `POST /api/exception-workorder/export`
2809 +
2810 +**功能描述:** 根据查询条件导出异常工单数据到Excel
2811 +
2812 +**请求头:**
2813 +```
2814 +Authorization: Bearer <JWT_TOKEN>
2815 +Content-Type: application/json
2816 +```
2817 +
2818 +**请求体:** 同异常工单查询接口参数(可选,为空时导出所有数据)
2819 +
2820 +**权限要求:** `exception:workorder:export`
2821 +
2822 +**响应:** 返回Excel文件流,文件名格式:`异常工单数据_yyyyMMdd_HHmmss.xlsx`
2823 +
2824 +**导出字段:**
2825 +- 工单ID
2826 +- 工单编号
2827 +- 工单类型(异常类型名称)
2828 +- 严重程度(严重程度名称)
2829 +- 工单状态(工单状态名称)
2830 +- 问题描述
2831 +- 处理人
2832 +- 创建人
2833 +- 创建时间
2834 +- 更新时间
2835 +
2426 --- 2836 ---
2427 2837
2428 **文档版本:** 1.0.0 2838 **文档版本:** 1.0.0
2429 -**最后更新:** 2025-01-27 2839 +**最后更新:** 2025-01-29
2430 **维护人员:** Apple ERP Team 2840 **维护人员:** Apple ERP Team
......
...@@ -6,12 +6,14 @@ import com.apple.erp.dto.ExceptionWorkorderRes; ...@@ -6,12 +6,14 @@ import com.apple.erp.dto.ExceptionWorkorderRes;
6 import com.apple.erp.dto.ExceptionWorkorderStatusUpdateReq; 6 import com.apple.erp.dto.ExceptionWorkorderStatusUpdateReq;
7 import com.apple.erp.dto.ExceptionWorkorderUpdateReq; 7 import com.apple.erp.dto.ExceptionWorkorderUpdateReq;
8 import com.apple.erp.service.ExceptionWorkorderService; 8 import com.apple.erp.service.ExceptionWorkorderService;
9 +import com.apple.erp.service.ExcelExportService;
9 import com.apple.erp.dto.response.ApiRes; 10 import com.apple.erp.dto.response.ApiRes;
10 import com.baomidou.mybatisplus.extension.plugins.pagination.Page; 11 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
11 import io.swagger.v3.oas.annotations.Operation; 12 import io.swagger.v3.oas.annotations.Operation;
12 import io.swagger.v3.oas.annotations.Parameter; 13 import io.swagger.v3.oas.annotations.Parameter;
13 import io.swagger.v3.oas.annotations.tags.Tag; 14 import io.swagger.v3.oas.annotations.tags.Tag;
14 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.beans.factory.annotation.Autowired;
16 +import org.springframework.http.ResponseEntity;
15 import org.springframework.security.access.prepost.PreAuthorize; 17 import org.springframework.security.access.prepost.PreAuthorize;
16 import org.springframework.validation.annotation.Validated; 18 import org.springframework.validation.annotation.Validated;
17 import org.springframework.web.bind.annotation.*; 19 import org.springframework.web.bind.annotation.*;
...@@ -33,6 +35,9 @@ public class ExceptionWorkorderController { ...@@ -33,6 +35,9 @@ public class ExceptionWorkorderController {
33 35
34 @Autowired 36 @Autowired
35 private ExceptionWorkorderService exceptionWorkorderService; 37 private ExceptionWorkorderService exceptionWorkorderService;
38 +
39 + @Autowired
40 + private ExcelExportService excelExportService;
36 41
37 @Operation(summary = "分页查询异常工单列表", description = "根据条件分页查询异常工单列表") 42 @Operation(summary = "分页查询异常工单列表", description = "根据条件分页查询异常工单列表")
38 @GetMapping("/list") 43 @GetMapping("/list")
...@@ -168,4 +173,22 @@ public class ExceptionWorkorderController { ...@@ -168,4 +173,22 @@ public class ExceptionWorkorderController {
168 List<ExceptionWorkorderRes> stats = exceptionWorkorderService.getExceptionWorkorderStats(); 173 List<ExceptionWorkorderRes> stats = exceptionWorkorderService.getExceptionWorkorderStats();
169 return ApiRes.success(stats); 174 return ApiRes.success(stats);
170 } 175 }
176 +
177 + @Operation(summary = "导出异常工单数据", description = "根据查询条件导出异常工单数据到Excel")
178 + @PostMapping("/export")
179 + @PreAuthorize("hasAuthority('exception:workorder:export')")
180 + public ResponseEntity<byte[]> exportExceptionWorkorders(@RequestBody(required = false) ExceptionWorkorderQueryReq queryReq) {
181 + try {
182 + // 如果请求体为空,创建默认查询条件
183 + if (queryReq == null) {
184 + queryReq = new ExceptionWorkorderQueryReq();
185 + }
186 + // 获取异常工单数据
187 + List<ExceptionWorkorderRes> workorders = exceptionWorkorderService.getExceptionWorkorderListForExport(queryReq);
188 + // 导出Excel
189 + return excelExportService.exportExceptionWorkorders(workorders);
190 + } catch (Exception e) {
191 + throw new RuntimeException("导出异常工单数据失败: " + e.getMessage());
192 + }
193 + }
171 } 194 }
......
...@@ -54,4 +54,12 @@ public interface ExceptionWorkorderMapper extends BaseMapper<ExceptionWorkorder> ...@@ -54,4 +54,12 @@ public interface ExceptionWorkorderMapper extends BaseMapper<ExceptionWorkorder>
54 int batchUpdateWorkorderStatus(@Param("workorderIds") List<Long> workorderIds, 54 int batchUpdateWorkorderStatus(@Param("workorderIds") List<Long> workorderIds,
55 @Param("workorderStatus") Integer workorderStatus, 55 @Param("workorderStatus") Integer workorderStatus,
56 @Param("handlerUser") String handlerUser); 56 @Param("handlerUser") String handlerUser);
57 +
58 + /**
59 + * 获取异常工单列表用于导出
60 + *
61 + * @param queryReq 查询条件
62 + * @return 异常工单列表(不分页)
63 + */
64 + List<ExceptionWorkorderRes> selectExceptionWorkorderListForExport(@Param("query") ExceptionWorkorderQueryReq queryReq);
57 } 65 }
......
...@@ -91,4 +91,12 @@ public interface ExceptionWorkorderService extends IService<ExceptionWorkorder> ...@@ -91,4 +91,12 @@ public interface ExceptionWorkorderService extends IService<ExceptionWorkorder>
91 * @return 统计信息 91 * @return 统计信息
92 */ 92 */
93 List<ExceptionWorkorderRes> getExceptionWorkorderStats(); 93 List<ExceptionWorkorderRes> getExceptionWorkorderStats();
94 +
95 + /**
96 + * 获取异常工单列表用于导出
97 + *
98 + * @param queryReq 查询条件
99 + * @return 异常工单列表(不分页)
100 + */
101 + List<ExceptionWorkorderRes> getExceptionWorkorderListForExport(ExceptionWorkorderQueryReq queryReq);
94 } 102 }
......
...@@ -18,11 +18,9 @@ import org.springframework.beans.BeanUtils; ...@@ -18,11 +18,9 @@ import org.springframework.beans.BeanUtils;
18 import org.springframework.beans.factory.annotation.Autowired; 18 import org.springframework.beans.factory.annotation.Autowired;
19 import org.springframework.stereotype.Service; 19 import org.springframework.stereotype.Service;
20 import org.springframework.transaction.annotation.Transactional; 20 import org.springframework.transaction.annotation.Transactional;
21 -import org.springframework.util.StringUtils;
22 21
23 import java.time.LocalDateTime; 22 import java.time.LocalDateTime;
24 import java.util.List; 23 import java.util.List;
25 -import java.util.stream.Collectors;
26 24
27 /** 25 /**
28 * 异常工单Service实现类 26 * 异常工单Service实现类
...@@ -200,4 +198,10 @@ public class ExceptionWorkorderServiceImpl extends ServiceImpl<ExceptionWorkorde ...@@ -200,4 +198,10 @@ public class ExceptionWorkorderServiceImpl extends ServiceImpl<ExceptionWorkorde
200 public List<ExceptionWorkorderRes> getExceptionWorkorderStats() { 198 public List<ExceptionWorkorderRes> getExceptionWorkorderStats() {
201 return exceptionWorkorderMapper.selectExceptionWorkorderStats(); 199 return exceptionWorkorderMapper.selectExceptionWorkorderStats();
202 } 200 }
201 +
202 + @Override
203 + public List<ExceptionWorkorderRes> getExceptionWorkorderListForExport(ExceptionWorkorderQueryReq queryReq) {
204 + // 不分页查询所有数据用于导出
205 + return exceptionWorkorderMapper.selectExceptionWorkorderListForExport(queryReq);
206 + }
203 } 207 }
......
...@@ -150,4 +150,76 @@ ...@@ -150,4 +150,76 @@
150 AND del_flag = '0' 150 AND del_flag = '0'
151 </update> 151 </update>
152 152
153 + <!-- 获取异常工单列表用于导出 -->
154 + <select id="selectExceptionWorkorderListForExport" resultType="com.apple.erp.dto.ExceptionWorkorderRes">
155 + SELECT
156 + ew.workorder_id,
157 + ew.workorder_no,
158 + ew.order_no,
159 + ew.dealer_code,
160 + ew.dealer_name,
161 + ew.exception_type,
162 + CASE ew.exception_type
163 + WHEN 1 THEN '逻辑验证异常'
164 + WHEN 2 THEN '源头验证异常'
165 + WHEN 3 THEN '交叉验证异常'
166 + ELSE '未知类型'
167 + END AS exception_type_name,
168 + ew.severity_level,
169 + CASE ew.severity_level
170 + WHEN 1 THEN '高'
171 + WHEN 2 THEN '中'
172 + WHEN 3 THEN '低'
173 + ELSE '未知'
174 + END AS severity_level_name,
175 + ew.workorder_status,
176 + CASE ew.workorder_status
177 + WHEN 1 THEN '待处理'
178 + WHEN 2 THEN '处理中'
179 + WHEN 3 THEN '已解决'
180 + WHEN 4 THEN '已关闭'
181 + ELSE '未知状态'
182 + END AS workorder_status_name,
183 + ew.exception_desc,
184 + ew.handler_user,
185 + ew.create_by,
186 + ew.create_time,
187 + ew.update_time
188 + FROM t_exception_workorder ew
189 + <where>
190 + ew.del_flag = '0'
191 + <if test="query.workorderNo != null and query.workorderNo != ''">
192 + AND ew.workorder_no LIKE CONCAT('%', #{query.workorderNo}, '%')
193 + </if>
194 + <if test="query.orderNo != null and query.orderNo != ''">
195 + AND ew.order_no LIKE CONCAT('%', #{query.orderNo}, '%')
196 + </if>
197 + <if test="query.dealerCode != null and query.dealerCode != ''">
198 + AND ew.dealer_code = #{query.dealerCode}
199 + </if>
200 + <if test="query.dealerName != null and query.dealerName != ''">
201 + AND ew.dealer_name LIKE CONCAT('%', #{query.dealerName}, '%')
202 + </if>
203 + <if test="query.workorderStatus != null">
204 + AND ew.workorder_status = #{query.workorderStatus}
205 + </if>
206 + <if test="query.exceptionType != null">
207 + AND ew.exception_type = #{query.exceptionType}
208 + </if>
209 + <if test="query.severityLevel != null">
210 + AND ew.severity_level = #{query.severityLevel}
211 + </if>
212 + <if test="query.handlerUser != null and query.handlerUser != ''">
213 + AND ew.handler_user LIKE CONCAT('%', #{query.handlerUser}, '%')
214 + </if>
215 + <if test="query.startTime != null">
216 + AND ew.create_time >= #{query.startTime}
217 + </if>
218 + <if test="query.endTime != null">
219 + AND ew.create_time &lt;= #{query.endTime}
220 + </if>
221 + </where>
222 + ORDER BY ew.create_time DESC
223 + </select>
224 +
153 </mapper> 225 </mapper>
......
...@@ -146,6 +146,13 @@ export const exceptionWorkorderApi = { ...@@ -146,6 +146,13 @@ export const exceptionWorkorderApi = {
146 // 获取异常工单统计信息 146 // 获取异常工单统计信息
147 getExceptionWorkorderStats: () => { 147 getExceptionWorkorderStats: () => {
148 return request.get('/api/exception-workorder/stats') 148 return request.get('/api/exception-workorder/stats')
149 + },
150 +
151 + // 导出异常工单数据
152 + exportExceptionWorkorders: (params: ExceptionWorkorderQueryReq) => {
153 + return request.post('/api/exception-workorder/export', params, {
154 + responseType: 'blob'
155 + })
149 } 156 }
150 } 157 }
151 158
......
...@@ -734,8 +734,38 @@ const handleBatchProcess = () => { ...@@ -734,8 +734,38 @@ const handleBatchProcess = () => {
734 } 734 }
735 735
736 // 导出 736 // 导出
737 -const handleExport = () => { 737 +const handleExport = async () => {
738 - ElMessage.info('导出功能开发中...') 738 + try {
739 + await ElMessageBox.confirm('确定要导出异常工单数据吗?', '确认导出', {
740 + confirmButtonText: '确定',
741 + cancelButtonText: '取消',
742 + type: 'warning'
743 + })
744 +
745 + ElMessage.info('正在导出数据,请稍候...')
746 +
747 + const response = await exceptionWorkorderApi.exportExceptionWorkorders(searchParams.value)
748 +
749 + // 创建下载链接
750 + const blob = new Blob([response as unknown as BlobPart], {
751 + type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
752 + })
753 + const url = window.URL.createObjectURL(blob)
754 + const link = document.createElement('a')
755 + link.href = url
756 + link.download = `异常工单数据_${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.xlsx`
757 + document.body.appendChild(link)
758 + link.click()
759 + document.body.removeChild(link)
760 + window.URL.revokeObjectURL(url)
761 +
762 + ElMessage.success('导出成功')
763 + } catch (error: any) {
764 + if (error !== 'cancel') {
765 + console.error('导出失败:', error)
766 + ElMessage.error('导出失败: ' + (error?.message || '未知错误'))
767 + }
768 + }
739 } 769 }
740 770
741 // 提交新增 771 // 提交新增
......