From 5ce73992b3ac444e41832e646735eacb9d13d7be Mon Sep 17 00:00:00 2001 From: litao Date: Thu, 7 Nov 2024 13:23:45 +0800 Subject: [PATCH] =?UTF-8?q?feat(workOrder):=20=E6=96=B0=E5=A2=9E=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E8=AE=A2=E5=8D=95=E4=BF=9D=E5=AD=98=E8=8D=89=E7=A8=BF?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=B9=B6=E4=BC=98=E5=8C=96=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增保存草稿接口,支持批量保存 - 优化工作订单列表查询逻辑,增加数据权限控制 - 重构工作订单保存和更新方法,提高代码复用性 - 优化附件保存逻辑,减少冗余操作 - 更新数据库连接配置,使用外网地址 --- .../controller/DeviceController.java | 53 ++++++---- .../controller/WorkOrderController.java | 82 +++++++++++++-- .../modules/workOrder/dto/DeviceDTO.java | 10 ++ .../modules/workOrder/entity/WorkOrder.java | 2 +- .../workOrder/service/IWorkOrderService.java | 2 + .../service/impl/WorkOrderServiceImpl.java | 99 +++++++++++-------- src/main/resources/application-dev.yml | 7 +- src/main/resources/application.yml | 12 +-- 8 files changed, 191 insertions(+), 76 deletions(-) diff --git a/src/main/java/org/springblade/modules/workOrder/controller/DeviceController.java b/src/main/java/org/springblade/modules/workOrder/controller/DeviceController.java index ff86dcb..055cc5a 100644 --- a/src/main/java/org/springblade/modules/workOrder/controller/DeviceController.java +++ b/src/main/java/org/springblade/modules/workOrder/controller/DeviceController.java @@ -1,6 +1,7 @@ package org.springblade.modules.workOrder.controller; -import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -14,6 +15,7 @@ import lombok.extern.slf4j.Slf4j; import org.springblade.core.secure.BladeUser; import org.springblade.core.mp.support.Condition; import org.springblade.core.mp.support.Query; +import org.springblade.core.secure.utils.AuthUtil; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.BeanUtil; import org.springblade.core.tool.utils.CollectionUtil; @@ -22,7 +24,6 @@ import org.springblade.modules.workOrder.dto.DeviceDTO; import org.springblade.modules.workOrder.entity.DeviceAttach; import org.springblade.modules.workOrder.entity.WorkOrder; import org.springblade.modules.workOrder.service.IDeviceAttachService; -import org.springblade.modules.workOrder.vo.WorkOrderVO; import org.springframework.web.bind.annotation.*; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -35,18 +36,7 @@ import org.springblade.core.tool.utils.DateUtil; import org.springblade.core.excel.util.ExcelUtil; import org.springblade.core.tool.constant.BladeConstant; import springfox.documentation.annotations.ApiIgnore; -import sun.misc.BASE64Encoder; - -import java.io.ByteArrayOutputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.StandardCopyOption; + import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; @@ -88,9 +78,38 @@ public class DeviceController extends BladeController { @GetMapping("/list") @ApiOperationSupport(order = 2) @ApiOperation(value = "分页", notes = "传入device") - public R> list(@ApiIgnore @RequestParam Map device, Query query) { - IPage pages = deviceService.page(Condition.getPage(query), Condition.getQueryWrapper(device, Device.class)); - return R.data(pages); + public R> list(@ApiIgnore DeviceDTO device, Query query) { + if (device == null || query == null) { + throw new IllegalArgumentException("Device or Query cannot be null"); + } + + // 验证用户身份 + Long userId = AuthUtil.getUserId(); + if (userId == null) { + throw new IllegalArgumentException("User not authenticated"); + } + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(Device.class); + wrapper.like(StringUtils.isNotBlank(sanitizeInput(device.getName())), Device::getName, device.getName()); + wrapper.eq(StringUtils.isNotBlank(sanitizeInput(device.getPosition())), Device::getPosition, device.getPosition()); + wrapper.eq(StringUtils.isNotBlank(sanitizeInput(device.getType())), Device::getType, device.getType()); + wrapper.eq(Device::getCreateUser, AuthUtil.getUserId()); + wrapper.orderByDesc(Device::getCreateTime); + try { + IPage pages = deviceService.page(Condition.getPage(query), wrapper); + return R.data(pages); + } catch (Exception e) { + // 记录异常日志 + log.error("Error occurred while fetching device list", e); + throw new RuntimeException("Failed to fetch device list", e); + } + } + + private String sanitizeInput(String input) { + // 对输入进行清理,防止 SQL 注入等安全问题 + if (input == null) { + return null; + } + return input.replaceAll("[^a-zA-Z0-9_\\-\\. ]", ""); } /** diff --git a/src/main/java/org/springblade/modules/workOrder/controller/WorkOrderController.java b/src/main/java/org/springblade/modules/workOrder/controller/WorkOrderController.java index 87bbab1..7439cfd 100644 --- a/src/main/java/org/springblade/modules/workOrder/controller/WorkOrderController.java +++ b/src/main/java/org/springblade/modules/workOrder/controller/WorkOrderController.java @@ -11,6 +11,7 @@ import lombok.AllArgsConstructor; import javax.validation.Valid; +import lombok.extern.slf4j.Slf4j; import org.springblade.core.log.annotation.ApiLog; import org.springblade.core.secure.BladeUser; import org.springblade.core.mp.support.Condition; @@ -34,8 +35,10 @@ import org.springblade.core.excel.util.ExcelUtil; import org.springblade.core.tool.constant.BladeConstant; import springfox.documentation.annotations.ApiIgnore; +import java.util.Collections; import java.util.Map; import java.util.List; +import java.util.stream.Collectors; import javax.servlet.http.HttpServletResponse; /** @@ -44,6 +47,7 @@ import javax.servlet.http.HttpServletResponse; * @author BladeX * @since 2024-10-14 */ +@Slf4j @RestController @AllArgsConstructor @RequestMapping("/workOrder") @@ -65,35 +69,87 @@ public class WorkOrderController extends BladeController { } /** - * 工单表 分页 + * 查询工作订单列表 + * + * @param workOrderDTO 工作订单DTO,包含查询条件 + * @param query 分页查询对象 + * @return 返回工作订单列表的响应对象 */ @GetMapping("/list") @ApiOperationSupport(order = 2) @ApiOperation(value = "分页", notes = "传入workOrder") public R> list(@ApiIgnore WorkOrderDTO workOrderDTO, Query query) { + // 创建工作订单的查询条件包装器 LambdaQueryWrapper eq = Wrappers.lambdaQuery(WorkOrder.class); + // 数据权限 - if (StringUtils.isNotBlank(workOrderDTO.getDataType())) { - eq.eq("1".equals(workOrderDTO.getDataType()), WorkOrder::getCreateUser, AuthUtil.getUserId());// 客户 - eq.in("2".equals(workOrderDTO.getDataType()), WorkOrder::getCreateDept, Func.toLongList(AuthUtil.getDeptId()));// 客服 - eq.eq("3".equals(workOrderDTO.getDataType()), WorkOrder::getMaintenanceTeam, AuthUtil.getDeptId());// 维修负责人 - eq.eq("4".equals(workOrderDTO.getDataType()), WorkOrder::getRepairPerson, AuthUtil.getUserId());// 维修人员 + try { + if (StringUtils.isNotBlank(workOrderDTO.getDataType())) { + setDataTypeConditions(eq, workOrderDTO.getDataType()); + } + } catch (Exception e) { + // 处理异常,例如记录日志或返回错误信息 + log.error("Error setting data type conditions", e); + return R.fail("数据权限设置失败"); } + + // 设置查询条件:故障地点、故障类型、创建时间范围,并按创建时间降序排序 eq.eq(StringUtils.isNotBlank(workOrderDTO.getFaultLocation()), WorkOrder::getFaultLocation, workOrderDTO.getFaultLocation()) .eq(StringUtils.isNotBlank(workOrderDTO.getFaultType()), WorkOrder::getFaultType, workOrderDTO.getFaultType()) .between(workOrderDTO.getStartTime() != null && workOrderDTO.getEndTime() != null, WorkOrder::getCreateTime, workOrderDTO.getStartTime(), workOrderDTO.getEndTime()) .orderByDesc(WorkOrder::getCreateTime); + // 执行分页查询 IPage pages = workOrderService.page(Condition.getPage(query), eq); + + // 获取查询结果列表 List records = pages.getRecords(); + + // 批量查询设备名称 + List deviceIds = records.stream().map(WorkOrder::getDeviceId).collect(Collectors.toList()); + Map deviceNameMap = getDeviceNameMap(deviceIds); + for (WorkOrder record : records) { - Device device = deviceService.getById(record.getDeviceId()); - record.setDeviceName(device != null ? device.getName() : ""); + record.setDeviceName(deviceNameMap.getOrDefault(record.getDeviceId(), "")); } + + // 更新查询结果列表 pages.setRecords(records); + + // 返回查询结果 return R.data(pages); } + private void setDataTypeConditions(LambdaQueryWrapper eq, String dataType) { + switch (dataType) { + case "1": + eq.eq(WorkOrder::getCreateUser, AuthUtil.getUserId()); // 客户 + break; + case "2": + eq.in(WorkOrder::getCreateDept, Func.toLongList(AuthUtil.getDeptId())); // 客服 + break; + case "3": + eq.eq(WorkOrder::getMaintenanceTeam, AuthUtil.getDeptId()); // 维修负责人 + break; + case "4": + eq.eq(WorkOrder::getRepairPerson, AuthUtil.getUserId()); // 维修人员 + break; + default: + // 处理未知的数据类型 + log.warn("Unknown data type: {}", dataType); + } + } + + private Map getDeviceNameMap(List deviceIds) { + if (deviceIds.isEmpty()) { + return Collections.emptyMap(); + } + + List devices = deviceService.listByIds(deviceIds); + return devices.stream().collect(Collectors.toMap(Device::getId, Device::getName)); + } + + /** * 工单表 自定义分页 */ @@ -116,6 +172,16 @@ public class WorkOrderController extends BladeController { return R.status(workOrderService.saveAndAttach(workOrder)); } + /** + * 工单表 保存草稿 + */ + @ApiLog(value = "提报管理-保存草稿") + @PostMapping("/draft") + @ApiOperation(value = "保存草稿", notes = "传入workOrder") + public R draft(@Valid @RequestBody List workOrder) { + return R.status(workOrderService.draftAndAttach(workOrder)); + } + /** * 工单表 修改 */ diff --git a/src/main/java/org/springblade/modules/workOrder/dto/DeviceDTO.java b/src/main/java/org/springblade/modules/workOrder/dto/DeviceDTO.java index 458fa31..4a508ff 100644 --- a/src/main/java/org/springblade/modules/workOrder/dto/DeviceDTO.java +++ b/src/main/java/org/springblade/modules/workOrder/dto/DeviceDTO.java @@ -20,4 +20,14 @@ public class DeviceDTO extends Device { private static final long serialVersionUID = 1L; private List attaches; + + // 设备名称 + private String name; + + // 设备位置 + private String position; + + // 设备类型 + private String type; + } diff --git a/src/main/java/org/springblade/modules/workOrder/entity/WorkOrder.java b/src/main/java/org/springblade/modules/workOrder/entity/WorkOrder.java index b651bad..de3b689 100644 --- a/src/main/java/org/springblade/modules/workOrder/entity/WorkOrder.java +++ b/src/main/java/org/springblade/modules/workOrder/entity/WorkOrder.java @@ -21,7 +21,7 @@ import java.util.Date; @EqualsAndHashCode(callSuper = true) public class WorkOrder extends BaseEntity { - // 工单状态(0待客服接单 1待班组派单 2待维修人员确认 3待维修 4待领导审批 5待评价 6已完成 7已驳回(维修人员) 8已驳回(维修负责人) 9已关闭(客服)) + // 工单状态(-1草稿 0待客服接单 1待班组派单 2待维修人员确认 3待维修 4待领导审批 5待评价 6已完成 7已驳回(维修人员) 8已驳回(维修负责人) 9已关闭(客服)) /** * 故障位置 diff --git a/src/main/java/org/springblade/modules/workOrder/service/IWorkOrderService.java b/src/main/java/org/springblade/modules/workOrder/service/IWorkOrderService.java index c7e8d89..2eb35f8 100644 --- a/src/main/java/org/springblade/modules/workOrder/service/IWorkOrderService.java +++ b/src/main/java/org/springblade/modules/workOrder/service/IWorkOrderService.java @@ -42,4 +42,6 @@ public interface IWorkOrderService extends BaseService { boolean evaluateSign(WorkOrderVO workOrder); boolean updateAttach(WorkOrderVO workOrder); + + boolean draftAndAttach(List workOrder); } diff --git a/src/main/java/org/springblade/modules/workOrder/service/impl/WorkOrderServiceImpl.java b/src/main/java/org/springblade/modules/workOrder/service/impl/WorkOrderServiceImpl.java index d5742ba..f5e9a27 100644 --- a/src/main/java/org/springblade/modules/workOrder/service/impl/WorkOrderServiceImpl.java +++ b/src/main/java/org/springblade/modules/workOrder/service/impl/WorkOrderServiceImpl.java @@ -15,6 +15,7 @@ import org.springblade.modules.system.entity.User; import org.springblade.modules.system.service.IUserService; import org.springblade.modules.system.vo.PostVO; import org.springblade.modules.workOrder.dto.WorkOrderDTO; +import org.springblade.modules.workOrder.entity.KnowledgeBaseAttach; import org.springblade.modules.workOrder.entity.WorkOrder; import org.springblade.modules.workOrder.entity.WorkOrderAttach; import org.springblade.modules.workOrder.entity.WorkOrderRepairMaterial; @@ -130,28 +131,11 @@ public class WorkOrderServiceImpl extends BaseServiceImpl videoAttaches = workOrder.getVideoAttaches(); - if (CollectionUtils.isNotEmpty(videoAttaches)) { - videoAttaches.forEach(videoAttach -> { - videoAttach.setOrderId(workOrder.getId()); - videoAttach.setAttachType(2); - }); - workOrderAttachService.saveBatch(videoAttaches); - } - - // 保存图片附件 - List picAttaches = workOrder.getPicAttaches(); - if (CollectionUtils.isNotEmpty(picAttaches)) { - picAttaches.forEach(picAttache -> { - picAttache.setOrderId(workOrder.getId()); - picAttache.setAttachType(1); - }); - workOrderAttachService.saveBatch(picAttaches); - } + // 保存附件 + saveFiles(workOrder.getVideoAttaches(), workOrder.getPicAttaches(), workOrder.getId()); } return save; } @@ -170,27 +154,8 @@ public class WorkOrderServiceImpl extends BaseServiceImpl picAttaches = workOrder.getPicAttaches(); - // 图片 - if (org.springblade.core.tool.utils.CollectionUtil.isNotEmpty(picAttaches)) { - workOrderAttachService.remove(Wrappers.lambdaQuery(WorkOrderAttach.class).eq(WorkOrderAttach::getOrderId, workOrder.getId()).eq(WorkOrderAttach::getAttachType, 1)); - picAttaches.forEach(picAttache -> { - picAttache.setOrderId(workOrder.getId()); - picAttache.setAttachType(1); - } - ); - workOrderAttachService.saveBatch(picAttaches); - } - // 视频 - List videoAttaches = workOrder.getVideoAttaches(); - if (org.springblade.core.tool.utils.CollectionUtil.isNotEmpty(videoAttaches)) { - workOrderAttachService.remove(Wrappers.lambdaQuery(WorkOrderAttach.class).eq(WorkOrderAttach::getOrderId, workOrder.getId()).eq(WorkOrderAttach::getAttachType, 2)); - videoAttaches.forEach(videoAttache -> { - videoAttache.setOrderId(workOrder.getId()); - videoAttache.setAttachType(2); - }); - workOrderAttachService.saveBatch(videoAttaches); - } + // 保存附件 + saveFiles(workOrder.getVideoAttaches(), workOrder.getPicAttaches(), workOrder.getId()); List materials = workOrder.getMaterials(); // 维修材料 if (CollectionUtil.isNotEmpty(materials)) { @@ -200,4 +165,56 @@ public class WorkOrderServiceImpl extends BaseServiceImpl workOrders) { + boolean save = false; + for (WorkOrderVO workOrder : workOrders) { + // 查询今天已提报数量 + workOrder.setStatus(-1);// 草稿 + save = this.saveOrUpdate(workOrder); + + // 保存附件 + saveFiles(workOrder.getVideoAttaches(), workOrder.getPicAttaches(), workOrder.getId()); + } + return save; + } + + private void saveFiles(List videoAttaches, List picAttaches, Long orderId) { + // 保存视频附件 + if (CollectionUtils.isNotEmpty(videoAttaches)) { + // 需要新增的附件 + List newSavePic = videoAttaches.stream().filter(workOrderAttach -> workOrderAttach.getId() == null).collect(Collectors.toList()); + // 不删除的附件ids + List ids = videoAttaches.stream().filter(workOrderAttach -> workOrderAttach.getId() != null).map(WorkOrderAttach::getId).collect(Collectors.toList()); + workOrderAttachService.remove(Wrappers.lambdaQuery(WorkOrderAttach.class) + .eq(WorkOrderAttach::getOrderId, orderId) + .eq(WorkOrderAttach::getAttachType, 2) + .notIn(CollectionUtils.isNotEmpty(ids), WorkOrderAttach::getId, ids)); + + newSavePic.forEach(videoAttach -> { + videoAttach.setOrderId(orderId); + videoAttach.setAttachType(2); + }); + workOrderAttachService.saveBatch(newSavePic); + } + + // 保存图片附件 + if (CollectionUtils.isNotEmpty(picAttaches)) { + // 需要新增的附件 + List newSaveVideo = picAttaches.stream().filter(workOrderAttach -> workOrderAttach.getId() == null).collect(Collectors.toList()); + // 不删除的附件ids + List ids = picAttaches.stream().filter(workOrderAttach -> workOrderAttach.getId() != null).map(WorkOrderAttach::getId).collect(Collectors.toList()); + workOrderAttachService.remove(Wrappers.lambdaQuery(WorkOrderAttach.class) + .eq(WorkOrderAttach::getOrderId, orderId) + .eq(WorkOrderAttach::getAttachType, 1) + .notIn(CollectionUtils.isNotEmpty(ids), WorkOrderAttach::getId, ids)); + + newSaveVideo.forEach(picAttache -> { + picAttache.setOrderId(orderId); + picAttache.setAttachType(1); + }); + workOrderAttachService.saveBatch(newSaveVideo); + } + } + } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 1d651d2..9ce26a1 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -15,10 +15,11 @@ spring: # commandTimeout: 5000 datasource: # MySql - url: jdbc:mysql://localhost:3306/data_operation?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true +# url: jdbc:mysql://localhost:3306/data_operation?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true + url: jdbc:mysql://124.221.142.15:3306/data_operation?useSSL=false&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true&allowPublicKeyRetrieval=true username: root - password: 123456 -# password: jiahe123! +# password: 123456 + password: jiahe123! # PostgreSQL #url: jdbc:postgresql://127.0.0.1:5432/bladex_boot #username: postgres diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index d3045d0..0b8eb48 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -138,16 +138,16 @@ oss: #租户模式 tenant-mode: false #oss服务地址 - endpoint: http://192.168.0.105:9000 -# endpoint: http://124.221.142.15:9000 +# endpoint: http://192.168.0.105:9000 + endpoint: http://124.221.142.15:9000 #minio转换服务地址,用于内网上传后将返回地址改为转换的外网地址 # transform-endpoint: http://localhost:9000 #访问key - access-key: pJv3uZvE9kMgPfb9 -# access-key: DBTbUmfs1uvvyspvSKKo +# access-key: pJv3uZvE9kMgPfb9 + access-key: DBTbUmfs1uvvyspvSKKo #密钥key - secret-key: HgKxhiNxxEJf3UAPGHLtywxTKAALmt3s -# secret-key: NNmKEWBJUnJNdk58P26Y9IcMdUKbGXJy2hLDx92p +# secret-key: HgKxhiNxxEJf3UAPGHLtywxTKAALmt3s + secret-key: NNmKEWBJUnJNdk58P26Y9IcMdUKbGXJy2hLDx92p #存储桶 bucket-name: laboratory