drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/controller/GdPatrolTaskController.java
@@ -27,11 +27,14 @@ import org.springblade.core.mp.support.Condition; import org.springblade.core.mp.support.Query; import org.springblade.core.tool.api.R; import org.springblade.core.tool.utils.BeanUtil; import org.springblade.core.tool.utils.Func; import org.springframework.web.bind.annotation.*; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import org.sxkj.gd.workorder.entity.GdPatrolTaskEntity; import org.sxkj.gd.workorder.param.GdPatrolTaskAddParam; import org.sxkj.gd.workorder.param.GdPatrolTaskAuditParam; import org.sxkj.gd.workorder.vo.GdPatrolTaskVO; import org.sxkj.gd.workorder.excel.GdPatrolTaskExcel; import org.sxkj.gd.workorder.wrapper.GdPatrolTaskWrapper; @@ -41,8 +44,11 @@ import org.springblade.core.excel.util.ExcelUtil; import org.springblade.core.tool.constant.BladeConstant; import springfox.documentation.annotations.ApiIgnore; import java.util.ArrayList; import java.util.Map; import java.util.List; import java.util.Objects; import javax.servlet.http.HttpServletResponse; /** @@ -72,13 +78,13 @@ /** * 巡查任务表 分页 */ @GetMapping("/list") @ApiOperationSupport(order = 2) @ApiOperation(value = "分页", notes = "传入gdPatrolTask") public R<IPage<GdPatrolTaskVO>> list(@ApiIgnore @RequestParam Map<String, Object> gdPatrolTask, Query query) { IPage<GdPatrolTaskEntity> pages = gdPatrolTaskService.page(Condition.getPage(query), Condition.getQueryWrapper(gdPatrolTask, GdPatrolTaskEntity.class)); return R.data(GdPatrolTaskWrapper.build().pageVO(pages)); } // @GetMapping("/list") // @ApiOperationSupport(order = 2) // @ApiOperation(value = "分页", notes = "传入gdPatrolTask") // public R<IPage<GdPatrolTaskVO>> list(@ApiIgnore @RequestParam Map<String, Object> gdPatrolTask, Query query) { // IPage<GdPatrolTaskEntity> pages = gdPatrolTaskService.page(Condition.getPage(query), Condition.getQueryWrapper(gdPatrolTask, GdPatrolTaskEntity.class)); // return R.data(GdPatrolTaskWrapper.build().pageVO(pages)); // } /** * 巡查任务表 自定义分页 @@ -97,29 +103,34 @@ @PostMapping("/save") @ApiOperationSupport(order = 4) @ApiOperation(value = "新增", notes = "传入gdPatrolTask") public R save(@Valid @RequestBody GdPatrolTaskEntity gdPatrolTask) { return R.status(gdPatrolTaskService.save(gdPatrolTask)); public R save(@Valid @RequestBody List<GdPatrolTaskAddParam> gdPatrolTaskList) { List<GdPatrolTaskEntity> taskEntityList = new ArrayList<>(); gdPatrolTaskList.forEach(gdPatrolTask -> { GdPatrolTaskEntity gdPatrolTaskEntity = Objects.requireNonNull(BeanUtil.copy(gdPatrolTask, GdPatrolTaskEntity.class)); taskEntityList.add(gdPatrolTaskEntity); }); return R.status(gdPatrolTaskService.savePatrolTask(taskEntityList)); } /** * 巡查任务表 修改 */ @PostMapping("/update") @ApiOperationSupport(order = 5) @ApiOperation(value = "修改", notes = "传入gdPatrolTask") public R update(@Valid @RequestBody GdPatrolTaskEntity gdPatrolTask) { return R.status(gdPatrolTaskService.updateById(gdPatrolTask)); } // @PostMapping("/update") // @ApiOperationSupport(order = 5) // @ApiOperation(value = "修改", notes = "传入gdPatrolTask") // public R update(@Valid @RequestBody GdPatrolTaskEntity gdPatrolTask) { // return R.status(gdPatrolTaskService.updateById(gdPatrolTask)); // } /** * 巡查任务表 新增或修改 */ @PostMapping("/submit") @ApiOperationSupport(order = 6) @ApiOperation(value = "新增或修改", notes = "传入gdPatrolTask") public R submit(@Valid @RequestBody GdPatrolTaskEntity gdPatrolTask) { return R.status(gdPatrolTaskService.saveOrUpdate(gdPatrolTask)); } // @PostMapping("/submit") // @ApiOperationSupport(order = 6) // @ApiOperation(value = "新增或修改", notes = "传入gdPatrolTask") // public R submit(@Valid @RequestBody GdPatrolTaskEntity gdPatrolTask) { // return R.status(gdPatrolTaskService.saveOrUpdate(gdPatrolTask)); // } /** * 巡查任务表 删除 @@ -148,4 +159,15 @@ ExcelUtil.export(response, "巡查任务表数据" + DateUtil.time(), "巡查任务表数据表", list, GdPatrolTaskExcel.class); } /** * 审核巡查任务 */ @PostMapping("/audit") @ApiOperationSupport(order = 10) @ApiOperation(value = "审核巡查任务", notes = "传入审核参数,拒绝时必须填写拒绝原因") public R audit(@Valid @RequestBody GdPatrolTaskAuditParam auditParam) { boolean result = gdPatrolTaskService.auditPatrolTask(auditParam.getId(), auditParam.getAuditStatus(), auditParam.getRejectReason()); return R.status(result); } } drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/enums/PatrolTaskStatusEnum.java
New file @@ -0,0 +1,100 @@ package org.sxkj.gd.workorder.enums; import com.baomidou.mybatisplus.annotation.EnumValue; import com.fasterxml.jackson.annotation.JsonValue; import lombok.AllArgsConstructor; import lombok.Getter; /** * 巡查任务状态枚举 * 用于标识巡查任务的不同状态 * * @author BladeX * @date 2026-01-19 */ @Getter @AllArgsConstructor public enum PatrolTaskStatusEnum { /** * 待签收 */ PENDING_SIGNING("0", "待签收"), /** * 拒绝签收 */ REJECTED_SIGNING("1", "拒绝签收"), /** * 已撤回 */ WITHDRAWN("2", "已撤回"), /** * 待审核 */ PENDING_AUDIT("3", "待审核"), /** * 审核驳回 */ AUDIT_REJECTED("4", "审核驳回"), /** * 审核通过 */ AUDIT_PASSED("5", "审核通过"), /** * 待验收 */ PENDING_ACCEPTANCE("6", "待验收"), /** * 拒绝验收 */ REJECTED_ACCEPTANCE("7", "拒绝验收"), /** * 验收通过 */ ACCEPTANCE_PASSED("8", "验收通过"); /** * 枚举值,对应数据库存储值 */ @EnumValue private final String value; /** * 枚举描述,用于展示 */ @JsonValue private final String desc; /** * 根据值获取对应的枚举 * * @param value 枚举值 * @return 对应的枚举,如果未找到则返回null */ public static PatrolTaskStatusEnum getByValue(String value) { for (PatrolTaskStatusEnum status : values()) { if (status.getValue().equals(value)) { return status; } } return null; } /** * 判断值是否为有效的巡查任务状态 * * @param value 待验证的值 * @return 是否有效 */ public static boolean isValidValue(String value) { return getByValue(value) != null; } } drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdPatrolTaskMapper.xml
@@ -26,7 +26,26 @@ <select id="selectGdPatrolTaskPage" resultMap="gdPatrolTaskResultMap"> select * from ja_gd_patrol_task where is_deleted = 0 select pt.*, wo.work_order_name from ja_gd_patrol_task pt left join ja_gd_work_order wo on pt.work_order_id = wo.id <where> <if test="param2.workOrderId != null and param2.workOrderId != ''"> and pt.work_order_id = #{param2.workOrderId} </if> <if test="param2.patrolTaskName != null and param2.patrolTaskName != ''"> and pt.patrol_task_name like concat(#{param2.patrolTaskName},'%') </if> <if test="param2.patrolTaskType != null and param2.patrolTaskType != ''"> and pt.patrol_task_type = #{param2.patrolTaskType} </if> <if test="param2.taskStatus != null and param2.taskStatus != ''"> and pt.task_status = #{param2.taskStatus} </if> <if test="param2.startTime != null and param2.startTime != '' and param2.endTime != null and param2.endTime != '' "> and pt.execute_time BETWEEN #{param2.startTime} AND #{param2.endTime} </if> </where> </select> drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/mapper/GdWorkOrderMapper.xml
@@ -39,6 +39,10 @@ <if test="param2.workOrderType != null and param2.workOrderType != ''"> and work_order_type = #{param2.workOrderType} </if> <if test="param2.createUser != null and param2.createUser != ''"> and create_user = #{param2.createUser} </if> </where> </select> drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/param/GdPatrolTaskAddParam.java
New file @@ -0,0 +1,57 @@ package org.sxkj.gd.workorder.param; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.Date; @Data public class GdPatrolTaskAddParam { /** * 关联工单任务表ID */ @ApiModelProperty(value = "关联工单任务表ID") private Long workOrderId; /** * 巡查任务名称 */ @ApiModelProperty(value = "巡查任务名称") private String patrolTaskName; /** * 巡查任务类型(巡查类/安检类等) */ @ApiModelProperty(value = "巡查任务类型(巡查类/安检类等)") private String patrolTaskType; /** * 执行时间 */ @ApiModelProperty(value = "执行时间") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date executeTime; /** * 巡查任务航线URL */ @ApiModelProperty(value = "巡查任务航线URL") private String patrolRouteUrl; /** * 推荐飞手名称 */ @ApiModelProperty(value = "推荐飞手名称") private String recommendFlyerName; /** * 关联设备ID */ @ApiModelProperty(value = "关联设备ID") private Long deviceId; /** * 任务描述 */ @ApiModelProperty(value = "任务描述") private String taskDesc; /** * 状态:0草稿、1待签收、2拒绝签收、3待审核 */ @ApiModelProperty(value = "状态:0草稿、1待签收、2拒绝签收、3待审核") private Byte taskStatus; } drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/param/GdPatrolTaskAuditParam.java
New file @@ -0,0 +1,30 @@ package org.sxkj.gd.workorder.param; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; @Data public class GdPatrolTaskAuditParam { /** * 任务ID */ @ApiModelProperty(value = "任务ID", required = true) @NotNull(message = "任务ID不能为空") private Long id; /** * 审核状态:4审核通过、5审核拒绝 */ @ApiModelProperty(value = "审核状态:4审核通过、5审核拒绝", required = true) @NotNull(message = "审核状态不能为空") private String auditStatus; /** * 拒绝原因(审核拒绝时必填) */ @ApiModelProperty(value = "拒绝原因(审核拒绝时必填)") private String rejectReason; } drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/param/WorkOrderPageParam.java
@@ -25,4 +25,7 @@ @ApiModelProperty(value = "工单状态:0草稿、10发布中_接单中、11发布中_拒绝接单、20响应中_待拆分、21响应中_申请取消、22响应中_申请修改、23响应中_已取消、30执行中_待全部完成、31执行中_协商修改、40完成待验_待全部验收、50验收通过_待结算、60结算完成_已结算") @NotNull private String workOrderStatus; @ApiModelProperty(value = "创建人") private Long createUser; } drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/IGdPatrolTaskService.java
@@ -49,4 +49,19 @@ */ List<GdPatrolTaskExcel> exportGdPatrolTask(Wrapper<GdPatrolTaskEntity> queryWrapper); /** * 批量保存或更新 * @param taskEntityList * @return */ boolean savePatrolTask(List<GdPatrolTaskEntity> taskEntityList); /** * 审核巡查任务 * @param id 任务ID * @param auditStatus 审核状态:4审核通过、5审核拒绝 * @param rejectReason 拒绝原因(审核拒绝时必填) * @return */ boolean auditPatrolTask(Long id, String auditStatus, String rejectReason); } drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/service/impl/GdPatrolTaskServiceImpl.java
@@ -16,7 +16,15 @@ */ package org.sxkj.gd.workorder.service.impl; import org.springblade.core.secure.utils.AuthUtil; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.sxkj.gd.workorder.entity.GdPatrolTaskEntity; import org.sxkj.gd.workorder.entity.GdWorkOrderFlowEntity; import org.sxkj.gd.workorder.enums.PatrolTaskStatusEnum; import org.sxkj.gd.workorder.enums.WorkOrderStatusEnum; import org.sxkj.gd.workorder.enums.WorkOrderTypeEnum; import org.sxkj.gd.workorder.service.IGdWorkOrderFlowService; import org.sxkj.gd.workorder.vo.GdPatrolTaskVO; import org.sxkj.gd.workorder.excel.GdPatrolTaskExcel; import org.sxkj.gd.workorder.mapper.GdPatrolTaskMapper; @@ -25,6 +33,8 @@ import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import org.springblade.core.mp.base.BaseServiceImpl; import java.util.Date; import java.util.List; /** @@ -35,6 +45,9 @@ */ @Service public class GdPatrolTaskServiceImpl extends BaseServiceImpl<GdPatrolTaskMapper, GdPatrolTaskEntity> implements IGdPatrolTaskService { @Autowired private IGdWorkOrderFlowService gdWorkOrderFlowService; @Override public IPage<GdPatrolTaskVO> selectGdPatrolTaskPage(IPage<GdPatrolTaskVO> page, GdPatrolTaskVO gdPatrolTask) { @@ -51,4 +64,148 @@ return gdPatrolTaskList; } @Override @Transactional(rollbackFor = Exception.class) public boolean savePatrolTask(List<GdPatrolTaskEntity> taskEntityList) { // 更新流程节点 for (GdPatrolTaskEntity gdPatrolTaskEntity : taskEntityList) { // 保存巡逻任务 boolean save = save(gdPatrolTaskEntity); if (!save) { // 任务保存失败,抛出异常触发回滚 throw new RuntimeException("保存巡逻任务失败:" + gdPatrolTaskEntity.toString()); } // 保存流转记录 GdWorkOrderFlowEntity gdWorkOrderFlowEntity = new GdWorkOrderFlowEntity(); gdWorkOrderFlowEntity.setCreateUser(AuthUtil.getUserId()); gdWorkOrderFlowEntity.setWorkOrderId(gdPatrolTaskEntity.getId()); gdWorkOrderFlowEntity.setFlowName(PatrolTaskStatusEnum.PENDING_SIGNING.getDesc()); gdWorkOrderFlowEntity.setFlowDesc(AuthUtil.getUserName() + " " + org.springblade.core.tool.utils.DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")); gdWorkOrderFlowEntity.setOperator(AuthUtil.getUserName()); gdWorkOrderFlowEntity.setType(WorkOrderTypeEnum.PATROL_TASK.getValue()); gdWorkOrderFlowEntity.setAreaCode(gdPatrolTaskEntity.getAreaCode()); gdWorkOrderFlowEntity.setCreateDept(Long.valueOf(AuthUtil.getDeptId())); boolean save1 = gdWorkOrderFlowService.save(gdWorkOrderFlowEntity); if (!save1) { // 流转记录保存失败,抛出异常触发回滚 throw new RuntimeException("保存流转记录失败:" + gdWorkOrderFlowEntity.toString()); } } // 所有任务和流转记录都保存成功 return true; } @Override @Transactional(rollbackFor = Exception.class) public boolean auditPatrolTask(Long id, String auditStatus, String rejectReason) { // 1. 获取巡查任务 GdPatrolTaskEntity task = getById(id); if (task == null) { throw new RuntimeException("巡查任务不存在"); } // 2. 检查任务状态是否为待审核 if (!PatrolTaskStatusEnum.PENDING_AUDIT.getValue().equals(task.getTaskStatus().toString())) { throw new RuntimeException("任务当前状态无法审核"); } // 3. 如果审核拒绝,检查拒绝原因是否为空 if (PatrolTaskStatusEnum.REJECTED_SIGNING.getValue().equals(auditStatus) && (rejectReason == null || rejectReason.trim().isEmpty())) { throw new RuntimeException("拒绝签收时必须填写拒绝原因"); } // 4. 检查其他需要拒绝原因的状态 if ((PatrolTaskStatusEnum.AUDIT_REJECTED.getValue().equals(auditStatus) || PatrolTaskStatusEnum.REJECTED_ACCEPTANCE.getValue().equals(auditStatus)) && (rejectReason == null || rejectReason.trim().isEmpty())) { throw new RuntimeException("审核驳回或拒绝验收时必须填写拒绝原因"); } // 4. 更新任务状态 task.setTaskStatus(Byte.valueOf(auditStatus)); boolean updateResult = updateById(task); if (!updateResult) { throw new RuntimeException("更新任务状态失败"); } // 5. 保存流转记录 GdWorkOrderFlowEntity flowEntity = new GdWorkOrderFlowEntity(); flowEntity.setCreateUser(AuthUtil.getUserId()); flowEntity.setWorkOrderId(id); // 设置流转名称和描述 String[] flowInfo = buildFlowInfo(auditStatus, rejectReason); String flowName = flowInfo[0]; String flowDesc = AuthUtil.getUserName() + " " + org.springblade.core.tool.utils.DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss") + flowInfo[1]; flowEntity.setFlowName(flowName); flowEntity.setFlowDesc(flowDesc); flowEntity.setOperator(AuthUtil.getUserName()); flowEntity.setType(WorkOrderTypeEnum.PATROL_TASK.getValue()); flowEntity.setAreaCode(task.getAreaCode()); flowEntity.setCreateDept(Long.valueOf(AuthUtil.getDeptId())); boolean saveFlowResult = gdWorkOrderFlowService.save(flowEntity); if (!saveFlowResult) { throw new RuntimeException("保存流转记录失败"); } return true; } /** * 构建流转信息 * @param status 状态值 * @param rejectReason 拒绝原因 * @return 包含流转名称和描述的数组 [flowName, flowDescSuffix] */ private String[] buildFlowInfo(String status, String rejectReason) { String flowName; String flowDescSuffix; switch (status) { case "0": flowName = PatrolTaskStatusEnum.PENDING_SIGNING.getDesc(); flowDescSuffix = " 待签收"; break; case "1": flowName = PatrolTaskStatusEnum.REJECTED_SIGNING.getDesc(); flowDescSuffix = " 拒绝签收:" + rejectReason; break; case "2": flowName = PatrolTaskStatusEnum.WITHDRAWN.getDesc(); flowDescSuffix = " 已撤回"; break; case "3": flowName = PatrolTaskStatusEnum.PENDING_AUDIT.getDesc(); flowDescSuffix = " 待审核"; break; case "4": flowName = PatrolTaskStatusEnum.AUDIT_REJECTED.getDesc(); flowDescSuffix = " 审核驳回:" + rejectReason; break; case "5": flowName = PatrolTaskStatusEnum.AUDIT_PASSED.getDesc(); flowDescSuffix = " 审核通过"; break; case "6": flowName = PatrolTaskStatusEnum.PENDING_ACCEPTANCE.getDesc(); flowDescSuffix = " 待验收"; break; case "7": flowName = PatrolTaskStatusEnum.REJECTED_ACCEPTANCE.getDesc(); flowDescSuffix = " 拒绝验收:" + rejectReason; break; case "8": flowName = PatrolTaskStatusEnum.ACCEPTANCE_PASSED.getDesc(); flowDescSuffix = " 验收通过"; break; default: flowName = "未知状态"; flowDescSuffix = " 未知状态"; break; } return new String[]{flowName, flowDescSuffix}; } } drone-service/drone-gd/src/main/java/org/sxkj/gd/workorder/vo/GdPatrolTaskVO.java
@@ -16,6 +16,7 @@ */ package org.sxkj.gd.workorder.vo; import io.swagger.annotations.ApiModelProperty; import org.sxkj.gd.workorder.entity.GdPatrolTaskEntity; import lombok.Data; import lombok.EqualsAndHashCode; @@ -31,4 +32,10 @@ public class GdPatrolTaskVO extends GdPatrolTaskEntity { private static final long serialVersionUID = 1L; @ApiModelProperty(value = "开始时间") private String startTime; @ApiModelProperty(value = "结束时间") private String endTime; }