| | |
| | | */ |
| | | package org.sxkj.gd.workorder.service.impl; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springblade.core.mp.base.BaseServiceImpl; |
| | | import org.springblade.core.oss.model.BladeFile; |
| | | import org.springblade.core.secure.utils.AuthUtil; |
| | | import org.springblade.core.tool.api.R; |
| | | import org.springblade.core.tool.constant.BladeConstant; |
| | | import org.springblade.core.tool.utils.DateUtil; |
| | | import org.springblade.core.tool.utils.FileUtil; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.scheduling.annotation.Async; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.util.CollectionUtils; |
| | | import org.sxkj.common.constant.WordOrderConstant; |
| | | import org.sxkj.common.utils.OrderNumUtils; |
| | | import org.springblade.core.tool.api.R; |
| | | import org.springblade.core.tool.constant.BladeConstant; |
| | | import org.springblade.core.tool.utils.FileUtil; |
| | | import org.springblade.core.tool.utils.StringUtil; |
| | | import org.sxkj.gd.common.GdMultipartFileUtil; |
| | | import org.sxkj.gd.workorder.dto.GdXingtuFlyTaskSaveDTO; |
| | | import org.sxkj.gd.workorder.entity.GdPatrolTaskEntity; |
| | | import org.sxkj.gd.workorder.entity.GdTaskResultEntity; |
| | | import org.sxkj.gd.workorder.entity.GdWorkOrderEntity; |
| | |
| | | import org.sxkj.gd.workorder.enums.WorkOrderTypeEnum; |
| | | import org.sxkj.gd.workorder.excel.GdPatrolTaskExcel; |
| | | import org.sxkj.gd.workorder.mapper.GdPatrolTaskMapper; |
| | | import org.sxkj.gd.workorder.mapper.GdWorkOrderMapper; |
| | | import org.sxkj.gd.workorder.param.GdPatrolTaskAuditParam; |
| | | import org.sxkj.gd.workorder.param.GdPatrolTaskPageParam; |
| | | import org.sxkj.gd.workorder.param.GdPatrolTaskPendingAcceptanceQueryParam; |
| | | import org.sxkj.gd.workorder.service.IGdManageDeviceService; |
| | | import org.sxkj.gd.workorder.service.IGdPatrolTaskService; |
| | | import org.sxkj.gd.workorder.service.IGdTaskResultService; |
| | | import org.sxkj.gd.workorder.service.IGdWorkOrderFlowService; |
| | | import org.sxkj.gd.workorder.utils.GdPatrolReportWordUtil; |
| | | import org.sxkj.gd.workorder.vo.GdPatrolTaskSimpleVO; |
| | | import org.sxkj.gd.workorder.vo.GdPatrolTaskVO; |
| | | import org.sxkj.gd.common.GdMultipartFileUtil; |
| | | import org.sxkj.gd.xingtu.JianXingtuApiService; |
| | | import org.sxkj.resource.entity.Attach; |
| | | import org.sxkj.resource.feign.IAttachClient; |
| | | import org.sxkj.system.cache.SysCache; |
| | |
| | | |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 巡查任务表 服务实现类 |
| | |
| | | * @author lw |
| | | * @since 2026-01-14 |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | public class GdPatrolTaskServiceImpl extends BaseServiceImpl<GdPatrolTaskMapper, GdPatrolTaskEntity> implements IGdPatrolTaskService { |
| | | |
| | | @Autowired |
| | | private IGdWorkOrderFlowService gdWorkOrderFlowService; |
| | | |
| | | // @Autowired |
| | | // private IGdWorkOrderService gdWorkOrderService; |
| | | @Autowired |
| | | private IGdWorkOrderFlowService gdWorkOrderFlowService; |
| | | @Autowired |
| | | private ISysClient sysClient; |
| | | @Autowired |
| | |
| | | private IAttachClient attachClient; |
| | | @Autowired |
| | | private IGdTaskResultService gdTaskResultService; |
| | | @Override |
| | | public IPage<GdPatrolTaskVO> selectGdPatrolTaskPage(IPage<GdPatrolTaskVO> page, GdPatrolTaskPageParam gdPatrolTask) { |
| | | return page.setRecords(baseMapper.selectGdPatrolTaskPage(page, gdPatrolTask, SysCache.getDeptChildIds(Long.valueOf(AuthUtil.getDeptId())))); |
| | | } |
| | | @Autowired |
| | | private JianXingtuApiService jianXingtuApiService; |
| | | @Autowired |
| | | private IGdManageDeviceService gdManageDeviceService; |
| | | @Autowired |
| | | private GdWorkOrderMapper gdWorkOrderMapper; |
| | | |
| | | @Override |
| | | public IPage<GdPatrolTaskVO> selectGdPatrolTaskPage(IPage<GdPatrolTaskVO> page, GdPatrolTaskPageParam gdPatrolTask) { |
| | | List<Long> deptList = new ArrayList<>(); |
| | | if (!AuthUtil.isAdministrator() || !AuthUtil.isAdmin()) { |
| | | deptList = SysCache.getDeptChildIds(Long.valueOf(StringUtil.isBlank(AuthUtil.getDeptId()) ? "0" : AuthUtil.getDeptId())); |
| | | } |
| | | gdPatrolTask.setDeptList(deptList); |
| | | List<GdPatrolTaskVO> gdPatrolTaskVOS = baseMapper.selectGdPatrolTaskPage(page, gdPatrolTask); |
| | | return page.setRecords(gdPatrolTaskVOS); |
| | | } |
| | | |
| | | @Override |
| | | public List<GdPatrolTaskExcel> exportGdPatrolTask(Wrapper<GdPatrolTaskEntity> queryWrapper) { |
| | | List<GdPatrolTaskExcel> gdPatrolTaskList = baseMapper.exportGdPatrolTask(queryWrapper); |
| | | // gdPatrolTaskList.forEach(gdPatrolTask -> { |
| | | // gdPatrolTask.setTypeName(DictCache.getValue(DictEnum.YES_NO, GdPatrolTask.getType())); |
| | | //}); |
| | | return gdPatrolTaskList; |
| | | } |
| | | @Override |
| | | public List<GdPatrolTaskExcel> exportGdPatrolTask(Wrapper<GdPatrolTaskEntity> queryWrapper) { |
| | | List<GdPatrolTaskExcel> gdPatrolTaskList = baseMapper.exportGdPatrolTask(queryWrapper); |
| | | // gdPatrolTaskList.forEach(gdPatrolTask -> { |
| | | // gdPatrolTask.setTypeName(DictCache.getValue(DictEnum.YES_NO, GdPatrolTask.getType())); |
| | | //}); |
| | | return gdPatrolTaskList; |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean savePatrolTask(List<GdPatrolTaskEntity> taskEntityList) { |
| | | // 更新流程节点 |
| | | for (GdPatrolTaskEntity gdPatrolTaskEntity : taskEntityList) { |
| | | // 生成巡查任务编号 |
| | | if (StringUtils.isBlank(gdPatrolTaskEntity.getTaskNo())) { |
| | | // 使用时间戳生成唯一巡查任务编号 |
| | | String timestamp = OrderNumUtils.initOrderNum(WordOrderConstant.PATROL_TASK_KEY); |
| | | gdPatrolTaskEntity.setTaskNo(WordOrderConstant.PATROL_TASK_PREFIX + timestamp); |
| | | } |
| | | |
| | | // 设置初始状态为待签收(对应流程图:等待接单) |
| | | gdPatrolTaskEntity.setTaskStatus(PatrolTaskStatusEnum.PENDING_SIGNING.getValue()); |
| | | |
| | | // 保存巡逻任务 |
| | | 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.getStageDesc()); |
| | | gdWorkOrderFlowEntity.setFlowDesc(AuthUtil.getUserName() + " " + 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; |
| | | } |
| | | |
| | | /** |
| | | * 审核巡查任务 |
| | | * |
| | | * @param auditParam 审核参数,包含任务ID、审核状态和拒绝原因 |
| | | * @return 是否审核成功 |
| | | * @throws RuntimeException 当任务不存在、状态不允许转换或操作失败时抛出 |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean auditPatrolTask(GdPatrolTaskAuditParam auditParam) { |
| | | // 1. 获取巡查任务 |
| | | GdPatrolTaskEntity task = getById(auditParam.getId()); |
| | | if (task == null) { |
| | | throw new RuntimeException("巡查任务不存在"); |
| | | } |
| | | |
| | | // 2. 状态权限校验 |
| | | PatrolTaskStatusEnum currentStatus = PatrolTaskStatusEnum.getByValue(task.getTaskStatus()); |
| | | Integer auditStatus = auditParam.getAuditStatus(); |
| | | if (currentStatus == null || !currentStatus.isAllowedTransition(auditStatus)) { |
| | | throw new RuntimeException("当前任务状态无法进行该操作"); |
| | | } |
| | | // 1.同意签收、2.拒绝签收 、3.撤回任务 、4.同意审核、 5.拒绝审核、 6.验收通过、 7.验收拒绝 |
| | | // 3. 确定新状态和流转名称 |
| | | PatrolTaskStatusEnum newStatusEnum; |
| | | switch (auditStatus) { |
| | | case 1: // 接单 |
| | | newStatusEnum = PatrolTaskStatusEnum.PENDING_AUDIT; |
| | | break; |
| | | case 2: // 拒接接单 |
| | | newStatusEnum = PatrolTaskStatusEnum.REJECTED_SIGNING; |
| | | break; |
| | | case 3: // 撤回任务 |
| | | newStatusEnum = PatrolTaskStatusEnum.WITHDRAWN; |
| | | break; |
| | | case 4: // 同意审核 |
| | | newStatusEnum = PatrolTaskStatusEnum.AUDIT_PASSED; |
| | | break; |
| | | case 5: // 拒绝审核 |
| | | newStatusEnum = PatrolTaskStatusEnum.AUDIT_REJECTED; |
| | | break; |
| | | case 6: // 验收通过 |
| | | newStatusEnum = PatrolTaskStatusEnum.ACCEPTANCE_PASSED; |
| | | break; |
| | | case 7: // 验收拒绝 |
| | | newStatusEnum = PatrolTaskStatusEnum.REJECTED_ACCEPTANCE; |
| | | break; |
| | | default: // 无效操作类型 |
| | | return false; |
| | | } |
| | | |
| | | // 4. 更新任务状态 |
| | | Date now = new Date(); |
| | | task.setTaskStatus(newStatusEnum.getValue()); |
| | | task.setUpdateUser(AuthUtil.getUserId()); |
| | | task.setUpdateTime(now); |
| | | task.setRejectReason(auditParam.getRejectReason()); |
| | | boolean updateResult = updateById(task); |
| | | if (!updateResult) { |
| | | throw new RuntimeException("更新任务状态失败"); |
| | | } |
| | | |
| | | // 5. 保存流转记录 |
| | | boolean b = saveWorkOrderFlow(task.getId(), newStatusEnum, auditParam.getRejectReason(), task.getAreaCode()); |
| | | // 6. 判断是否审核成功,如果是,需要判断是否整个订单的子任务都审核成功了,除了被撤回和验收拒绝的 |
| | | if (auditStatus == 4) { |
| | | // 查询同一个工单下的所有子任务 |
| | | List<GdPatrolTaskEntity> subTasks = list(Wrappers.<GdPatrolTaskEntity>lambdaQuery() |
| | | .eq(GdPatrolTaskEntity::getWorkOrderId, task.getWorkOrderId())); |
| | | |
| | | // 检查是否所有子任务都审核成功(除了被撤回和验收拒绝的) |
| | | boolean allSubTasksAudited = checkAllSubTasksStatus(subTasks, PatrolTaskStatusEnum.AUDIT_PASSED); |
| | | // 示例:如果所有子任务都审核成功,可以更新工单状态为已完成 |
| | | if (allSubTasksAudited) { |
| | | // 执行工单状态更新逻辑 |
| | | return updateWorkOrderStatusAndFlow(task.getWorkOrderId(), |
| | | WorkOrderStatusEnum.EXECUTING_TO_BE_COMPLETED); |
| | | } |
| | | } |
| | | // 7. 验收拒绝 |
| | | if (auditStatus == 7) { |
| | | return updateWorkOrderStatusAndFlow(task.getWorkOrderId(), |
| | | WorkOrderStatusEnum.EXECUTING_TO_BE_COMPLETED); |
| | | } |
| | | // 8. 验收通过 |
| | | if (auditStatus == 6) { |
| | | // 查询同一个工单下的所有子任务 |
| | | List<GdPatrolTaskEntity> subTasks = list(Wrappers.<GdPatrolTaskEntity>lambdaQuery() |
| | | .eq(GdPatrolTaskEntity::getWorkOrderId, task.getWorkOrderId())); |
| | | |
| | | // 检查是否所有子任务都验收通过(除了被撤回和验收拒绝的) |
| | | boolean allSubTasksAudited = checkAllSubTasksStatus(subTasks, PatrolTaskStatusEnum.ACCEPTANCE_PASSED); |
| | | // 这里可以根据allSubTasksAudited的结果执行后续逻辑,比如更新工单状态等 |
| | | if (allSubTasksAudited) { |
| | | // 1.验收通过,生成报告 |
| | | asyncExportPatrolReport(task.getId()); |
| | | // 2.执行工单状态更新逻辑 |
| | | return updateWorkOrderStatusAndFlow(task.getWorkOrderId(), |
| | | WorkOrderStatusEnum.ACCEPTED_TO_BE_SETTLED); |
| | | } |
| | | } |
| | | return b; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 检查是否所有子任务都达到指定状态(除了被撤回和验收拒绝的) |
| | | * |
| | | * @param subTasks 子任务列表 |
| | | * @param targetStatus 目标状态枚举 |
| | | * @return 是否所有子任务都达到指定状态 |
| | | */ |
| | | private boolean checkAllSubTasksStatus(List<GdPatrolTaskEntity> subTasks, PatrolTaskStatusEnum targetStatus) { |
| | | for (GdPatrolTaskEntity subTask : subTasks) { |
| | | String taskStatus = subTask.getTaskStatus(); |
| | | PatrolTaskStatusEnum statusEnum = PatrolTaskStatusEnum.getByValue(taskStatus); |
| | | |
| | | // 如果任务状态不是目标状态,且不是被撤回和验收拒绝的,则返回false |
| | | if (statusEnum != targetStatus && |
| | | statusEnum != PatrolTaskStatusEnum.WITHDRAWN && |
| | | statusEnum != PatrolTaskStatusEnum.REJECTED_ACCEPTANCE) { |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 更新工单状态并保存流转记录 |
| | | * |
| | | * @param workOrderId 工单ID |
| | | * @param newStatus 新的工单状态枚举 |
| | | * @return 是否更新成功 |
| | | */ |
| | | private boolean updateWorkOrderStatusAndFlow(Long workOrderId, WorkOrderStatusEnum newStatus) { |
| | | // 1. 更新工单状态 |
| | | GdWorkOrderEntity gdWorkOrderEntity = new GdWorkOrderEntity(); |
| | | gdWorkOrderEntity.setId(workOrderId); |
| | | gdWorkOrderEntity.setWorkOrderStatus(newStatus.getCode()); |
| | | Integer updateResult = baseMapper.updateWorkOrderById(gdWorkOrderEntity); |
| | | if (updateResult <= 0) { |
| | | return false; |
| | | } |
| | | |
| | | // 2. 保存流转记录 |
| | | GdWorkOrderFlowEntity flowEntity = new GdWorkOrderFlowEntity(); |
| | | flowEntity.setCreateUser(AuthUtil.getUserId()); |
| | | flowEntity.setWorkOrderId(workOrderId); |
| | | flowEntity.setFlowName(newStatus.getDesc()); |
| | | flowEntity.setFlowDesc(String.format("%s %s 更新了任务信息,状态转换为:%s", |
| | | AuthUtil.getUserName(), |
| | | DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), |
| | | newStatus.getDesc())); |
| | | flowEntity.setOperator(AuthUtil.getUserName()); |
| | | flowEntity.setType(WorkOrderTypeEnum.WORK_ORDER_TASK.getValue()); |
| | | flowEntity.setCreateDept(Long.valueOf(AuthUtil.getDeptId())); |
| | | return gdWorkOrderFlowService.save(flowEntity); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean republishPatrolTask(GdPatrolTaskEntity taskEntity) { |
| | | if (taskEntity == null || taskEntity.getId() == null) { |
| | | throw new RuntimeException("任务信息或ID不能为空"); |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean savePatrolTask(List<GdPatrolTaskEntity> taskEntityList) { |
| | | // 参数校验:防止空指针 |
| | | if (taskEntityList == null || taskEntityList.isEmpty()) { |
| | | throw new RuntimeException("任务列表不能为空"); |
| | | } |
| | | |
| | | // 1. 验证任务是否存在 |
| | | GdPatrolTaskEntity existingTask = getById(taskEntity.getId()); |
| | | taskEntity.setId(existingTask.getId()); |
| | | if (existingTask == null) { |
| | | throw new RuntimeException("巡查任务不存在"); |
| | | } |
| | | // 获取第一个任务的工单ID |
| | | Long workOrderId = taskEntityList.get(0).getWorkOrderId(); |
| | | if (workOrderId == null) { |
| | | throw new RuntimeException("工单ID不能为空"); |
| | | } |
| | | |
| | | // 2. 先确定枚举状态:根据当前状态确定新的枚举状态 |
| | | PatrolTaskStatusEnum targetStatus; |
| | | String currentStatus = existingTask.getTaskStatus(); |
| | | // 1.发布中_拒绝接单 、 4.响应中_审核驳回 |
| | | switch (currentStatus) { |
| | | case "1": // 发布中_拒绝接单 → 发布中_接单中 |
| | | targetStatus = PatrolTaskStatusEnum.PENDING_SIGNING; |
| | | break; |
| | | case "4": // 响应中_审核驳回 → 响应中_待审核 |
| | | targetStatus = PatrolTaskStatusEnum.PENDING_AUDIT; |
| | | break; |
| | | default: |
| | | // 其他状态,保持原有状态 |
| | | targetStatus = PatrolTaskStatusEnum.getByValue(currentStatus); |
| | | // 如果无法获取枚举,使用待签收作为默认状态 |
| | | if (targetStatus == null) { |
| | | targetStatus = PatrolTaskStatusEnum.PENDING_SIGNING; |
| | | } |
| | | break; |
| | | } |
| | | // 查询工单信息 |
| | | GdWorkOrderEntity gdWorkOrderEntity = gdWorkOrderMapper.selectById(workOrderId); |
| | | if (gdWorkOrderEntity == null) { |
| | | throw new RuntimeException("工单不存在,工单ID: " + workOrderId); |
| | | } |
| | | |
| | | // 3. 设置任务状态:使用枚举设置任务状态 |
| | | taskEntity.setTaskStatus(targetStatus.getValue()); |
| | | // 更新流程节点 |
| | | for (GdPatrolTaskEntity gdPatrolTaskEntity : taskEntityList) { |
| | | if (gdPatrolTaskEntity == null) { |
| | | log.warn("跳过空任务对象"); |
| | | continue; |
| | | } |
| | | |
| | | // 4. 更新任务信息:合并传入的任务信息 |
| | | taskEntity.setUpdateUser(AuthUtil.getUserId()); |
| | | taskEntity.setUpdateTime(new Date()); |
| | | // 设置航线ID |
| | | gdPatrolTaskEntity.setAirlineId(gdPatrolTaskEntity.getPatrolRouteUrl()); |
| | | // 生成巡查任务编号 |
| | | if (StringUtils.isBlank(gdPatrolTaskEntity.getTaskNo())) { |
| | | // 使用时间戳生成唯一巡查任务编号 |
| | | String timestamp = OrderNumUtils.initOrderNum(WordOrderConstant.PATROL_TASK_KEY); |
| | | gdPatrolTaskEntity.setTaskNo(WordOrderConstant.PATROL_TASK_PREFIX + timestamp); |
| | | } |
| | | // 从工单实体中获取区域编码,防止空指针 |
| | | String areaCode = gdWorkOrderEntity.getAreaCode(); |
| | | gdPatrolTaskEntity.setAreaCode(areaCode != null ? areaCode : ""); |
| | | // 设置初始状态为待签收(对应流程图:等待接单) |
| | | gdPatrolTaskEntity.setTaskStatus(PatrolTaskStatusEnum.PENDING_SIGNING.getValue()); |
| | | |
| | | // 5. 更新数据库 |
| | | boolean updateResult = updateById(taskEntity); |
| | | if (!updateResult) { |
| | | throw new RuntimeException("更新任务信息失败"); |
| | | } |
| | | // 保存巡逻任务 |
| | | boolean save = save(gdPatrolTaskEntity); |
| | | if (!save) { |
| | | // 任务保存失败,抛出异常触发回滚 |
| | | throw new RuntimeException("保存巡逻任务失败:" + gdPatrolTaskEntity.toString()); |
| | | } |
| | | |
| | | // 6. 保存流转记录:使用枚举设置flowName |
| | | GdWorkOrderFlowEntity flowEntity = new GdWorkOrderFlowEntity(); |
| | | flowEntity.setCreateUser(AuthUtil.getUserId()); |
| | | flowEntity.setWorkOrderId(taskEntity.getId()); |
| | | flowEntity.setFlowName(targetStatus.getDesc()); |
| | | flowEntity.setFlowDesc(AuthUtil.getUserName() + " " + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss") + " 更新了任务信息,状态转换为:" + targetStatus.getDesc()); |
| | | flowEntity.setOperator(AuthUtil.getUserName()); |
| | | flowEntity.setType(WorkOrderTypeEnum.PATROL_TASK.getValue()); |
| | | flowEntity.setAreaCode(existingTask.getAreaCode()); |
| | | flowEntity.setCreateDept(Long.valueOf(AuthUtil.getDeptId())); |
| | | // 保存流转记录(发布任务,等待接单) |
| | | GdWorkOrderFlowEntity gdWorkOrderFlowEntity = new GdWorkOrderFlowEntity(); |
| | | gdWorkOrderFlowEntity.setCreateUser(AuthUtil.getUserId() == null ? 0L : AuthUtil.getUserId()); |
| | | gdWorkOrderFlowEntity.setWorkOrderId(gdPatrolTaskEntity.getId()); |
| | | gdWorkOrderFlowEntity.setFlowName(PatrolTaskStatusEnum.PENDING_SIGNING.getStageDesc()); |
| | | gdWorkOrderFlowEntity.setFlowDesc(PatrolTaskStatusEnum.PENDING_SIGNING.getStageDesc()); |
| | | gdWorkOrderFlowEntity.setOperator(StringUtil.isBlank(AuthUtil.getNickName()) ? "系统" : AuthUtil.getNickName()); |
| | | gdWorkOrderFlowEntity.setType(WorkOrderTypeEnum.PATROL_TASK.getValue()); |
| | | // 使用局部变量areaCode,防止空指针 |
| | | gdWorkOrderFlowEntity.setAreaCode(areaCode != null ? areaCode : ""); |
| | | gdWorkOrderFlowEntity.setCreateDept(Long.valueOf(StringUtil.isBlank(AuthUtil.getDeptId()) ? "0" : AuthUtil.getDeptId())); |
| | | boolean save1 = gdWorkOrderFlowService.save(gdWorkOrderFlowEntity); |
| | | if (!save1) { |
| | | // 流转记录保存失败,抛出异常触发回滚 |
| | | throw new RuntimeException("保存流转记录失败:" + gdWorkOrderFlowEntity.toString()); |
| | | } |
| | | } |
| | | |
| | | return gdWorkOrderFlowService.save(flowEntity); |
| | | } |
| | | // 所有任务和流转记录都保存成功 |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 审核巡查任务 |
| | | * |
| | | * @param auditParam 审核参数,包含任务ID、审核状态和拒绝原因 |
| | | * @return 是否审核成功 |
| | | * @throws RuntimeException 当任务不存在、状态不允许转换或操作失败时抛出 |
| | | */ |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean auditPatrolTask(GdPatrolTaskAuditParam auditParam) { |
| | | // 1. 获取巡查任务 |
| | | GdPatrolTaskEntity task = getById(auditParam.getId()); |
| | | if (task == null) { |
| | | throw new RuntimeException("巡查任务不存在"); |
| | | } |
| | | |
| | | // 2. 状态权限校验 |
| | | PatrolTaskStatusEnum currentStatus = PatrolTaskStatusEnum.getByValue(task.getTaskStatus()); |
| | | Integer auditStatus = auditParam.getAuditStatus(); |
| | | if (currentStatus == null || !currentStatus.isAllowedTransition(auditStatus)) { |
| | | throw new RuntimeException("当前任务状态无法进行该操作"); |
| | | } |
| | | // 1.同意签收、2.拒绝签收 、3.撤回任务 、4.同意审核、 5.拒绝审核、 6.验收通过、 7.验收拒绝 |
| | | // 3. 确定新状态和流转名称 |
| | | PatrolTaskStatusEnum newStatusEnum; |
| | | switch (auditStatus) { |
| | | case 1: // 接单 |
| | | newStatusEnum = PatrolTaskStatusEnum.PENDING_AUDIT; |
| | | break; |
| | | case 2: // 拒接接单 |
| | | newStatusEnum = PatrolTaskStatusEnum.REJECTED_SIGNING; |
| | | break; |
| | | case 3: // 撤回任务 |
| | | newStatusEnum = PatrolTaskStatusEnum.WITHDRAWN; |
| | | break; |
| | | case 4: // 同意审核 |
| | | newStatusEnum = PatrolTaskStatusEnum.AUDIT_PASSED; |
| | | break; |
| | | case 5: // 拒绝审核 |
| | | newStatusEnum = PatrolTaskStatusEnum.AUDIT_REJECTED; |
| | | break; |
| | | case 6: // 验收通过 |
| | | newStatusEnum = PatrolTaskStatusEnum.ACCEPTANCE_PASSED; |
| | | break; |
| | | case 7: // 验收拒绝 |
| | | newStatusEnum = PatrolTaskStatusEnum.REJECTED_ACCEPTANCE; |
| | | break; |
| | | default: // 无效操作类型 |
| | | return false; |
| | | } |
| | | |
| | | // 4. 更新任务状态 |
| | | Date now = new Date(); |
| | | task.setTaskStatus(newStatusEnum.getValue()); |
| | | task.setUpdateUser(AuthUtil.getUserId() == null ? 0L : AuthUtil.getUserId()); |
| | | task.setUpdateTime(now); |
| | | task.setRejectReason(auditParam.getRejectReason()); |
| | | boolean updateResult = updateById(task); |
| | | if (!updateResult) { |
| | | throw new RuntimeException("更新任务状态失败"); |
| | | } |
| | | |
| | | // 5. 保存流转记录 |
| | | boolean b = saveWorkOrderFlow(task.getId(), newStatusEnum, auditParam.getRejectReason(), task.getAreaCode()); |
| | | // 6. 判断是否审核成功,如果是,需要判断是否整个订单的子任务都审核成功了,除了被撤回和验收拒绝的 |
| | | if (auditStatus == 4) { |
| | | // 将审核后的任务信息推送到星图 |
| | | R pushResult = pushXingtuFlyTask(auditParam.getId()); |
| | | // 检查推送结果,如果失败则抛出异常回滚事务 |
| | | if (pushResult != null && !pushResult.isSuccess()) { |
| | | String errorMsg = pushResult.getMsg(); |
| | | log.error("推送星图飞行任务失败: {}", errorMsg); |
| | | throw new RuntimeException(errorMsg + ",请更改执行时间重新提交。"); |
| | | } |
| | | // 查询同一个工单下的所有子任务 |
| | | List<GdPatrolTaskEntity> subTasks = list(Wrappers.<GdPatrolTaskEntity>lambdaQuery() |
| | | .eq(GdPatrolTaskEntity::getWorkOrderId, task.getWorkOrderId())); |
| | | |
| | | // 检查是否所有子任务都审核成功(除了被撤回和验收拒绝的) |
| | | boolean allSubTasksAudited = isAllSubTasksAudited(subTasks, task, PatrolTaskStatusEnum.PENDING_AUDIT); |
| | | if (!allSubTasksAudited) { |
| | | // 执行工单状态更新逻辑 |
| | | return updateWorkOrderStatusAndFlow(task.getWorkOrderId(), |
| | | WorkOrderStatusEnum.EXECUTING_TO_BE_COMPLETED); |
| | | } |
| | | } |
| | | if (auditStatus == 3) { |
| | | // 撤回任务操作:查询同一个工单下的所有子任务 |
| | | List<GdPatrolTaskEntity> subTasks = list(Wrappers.<GdPatrolTaskEntity>lambdaQuery() |
| | | .eq(GdPatrolTaskEntity::getWorkOrderId, task.getWorkOrderId())); |
| | | |
| | | // 检查是否所有子任务都已撤回 |
| | | boolean allSubTasksWithdrawn = subTasks.stream() |
| | | .allMatch(item -> item.getTaskStatus().equals(PatrolTaskStatusEnum.WITHDRAWN.getValue())); |
| | | |
| | | // 如果所有子任务都已撤回,则将工单状态更新为"接单响应_已取消" |
| | | if (allSubTasksWithdrawn) { |
| | | return updateWorkOrderStatusAndFlow(task.getWorkOrderId(), |
| | | WorkOrderStatusEnum.RESPONDING_CANCELED); |
| | | } |
| | | } |
| | | // 7. 验收拒绝 |
| | | if (auditStatus == 7) { |
| | | return updateWorkOrderStatusAndFlow(task.getWorkOrderId(), |
| | | WorkOrderStatusEnum.EXECUTING_TO_BE_COMPLETED); |
| | | } |
| | | // 8. 验收通过 |
| | | if (auditStatus == 6) { |
| | | // 查询同一个工单下的所有子任务 |
| | | List<GdPatrolTaskEntity> subTasks = list(Wrappers.<GdPatrolTaskEntity>lambdaQuery() |
| | | .eq(GdPatrolTaskEntity::getWorkOrderId, task.getWorkOrderId())); |
| | | |
| | | // 检查是否所有子任务都验收通过(除了被撤回和验收拒绝的) |
| | | boolean allSubTasksAudited = isAllSubTasksAudited(subTasks, task, PatrolTaskStatusEnum.ACCEPTANCE_PASSED); |
| | | // 这里可以根据allSubTasksAudited的结果执行后续逻辑,比如更新工单状态等 |
| | | if (!allSubTasksAudited) { |
| | | // 1.验收通过,生成报告 |
| | | asyncExportPatrolReport(task.getId()); |
| | | // 2.执行工单状态更新逻辑 |
| | | return updateWorkOrderStatusAndFlow(task.getWorkOrderId(), |
| | | WorkOrderStatusEnum.ACCEPTED_TO_BE_SETTLED); |
| | | } |
| | | } |
| | | return b; |
| | | } |
| | | |
| | | /** |
| | | * @param subTasks |
| | | * @param task |
| | | * @param pendingAudit |
| | | * @return |
| | | */ |
| | | private static boolean isAllSubTasksAudited(List<GdPatrolTaskEntity> subTasks, GdPatrolTaskEntity task, PatrolTaskStatusEnum pendingAudit) { |
| | | List<String> validStatusList = subTasks.stream() |
| | | // 过滤掉当前任务本身 |
| | | .filter(subTask -> !subTask.getId().equals(task.getId())) |
| | | .map(GdPatrolTaskEntity::getTaskStatus) |
| | | .filter(Objects::nonNull) |
| | | // 过滤掉撤回或验收拒绝的任务 |
| | | .filter(status -> !status.equals(PatrolTaskStatusEnum.WITHDRAWN.getValue()) && |
| | | !status.equals(PatrolTaskStatusEnum.REJECTED_ACCEPTANCE.getValue())) |
| | | .collect(Collectors.toList()); |
| | | |
| | | // 如果过滤后没有有效任务,直接返回false |
| | | if (validStatusList.isEmpty()) { |
| | | return false; |
| | | } |
| | | |
| | | // 判断是否有小于待审核的任务 |
| | | boolean allSubTasksAudited = validStatusList.stream() |
| | | .anyMatch(status -> status.compareTo(pendingAudit.getValue()) < 0); |
| | | return allSubTasksAudited; |
| | | |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 更新工单状态并保存流转记录 |
| | | * |
| | | * @param workOrderId 工单ID |
| | | * @param newStatus 新的工单状态枚举 |
| | | * @return 是否更新成功 |
| | | */ |
| | | private boolean updateWorkOrderStatusAndFlow(Long workOrderId, WorkOrderStatusEnum newStatus) { |
| | | // 1. 更新工单状态 |
| | | GdWorkOrderEntity gdWorkOrderEntity = new GdWorkOrderEntity(); |
| | | gdWorkOrderEntity.setId(workOrderId); |
| | | gdWorkOrderEntity.setWorkOrderStatus(newStatus.getCode()); |
| | | Integer updateResult = baseMapper.updateWorkOrderById(gdWorkOrderEntity); |
| | | if (updateResult <= 0) { |
| | | return false; |
| | | } |
| | | |
| | | // 2. 保存流转记录 |
| | | GdWorkOrderFlowEntity flowEntity = new GdWorkOrderFlowEntity(); |
| | | flowEntity.setCreateUser(AuthUtil.getUserId() == null ? 0L : AuthUtil.getUserId()); |
| | | flowEntity.setWorkOrderId(workOrderId); |
| | | flowEntity.setFlowName(newStatus.getStageDesc()); |
| | | flowEntity.setFlowDesc(newStatus.getDesc()); |
| | | flowEntity.setOperator(StringUtil.isBlank(AuthUtil.getNickName()) ? "系统" : AuthUtil.getNickName()); |
| | | flowEntity.setType(WorkOrderTypeEnum.WORK_ORDER_TASK.getValue()); |
| | | flowEntity.setFlowStatus(newStatus.getMaxCode()); |
| | | flowEntity.setWorkStatus(newStatus.getCode()); |
| | | flowEntity.setCreateDept(Long.valueOf(StringUtil.isBlank(AuthUtil.getDeptId()) ? "0" : AuthUtil.getDeptId())); |
| | | return gdWorkOrderFlowService.save(flowEntity); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public boolean republishPatrolTask(GdPatrolTaskEntity taskEntity) { |
| | | if (taskEntity == null || taskEntity.getId() == null) { |
| | | throw new RuntimeException("任务信息或ID不能为空"); |
| | | } |
| | | |
| | | // 1. 验证任务是否存在 |
| | | GdPatrolTaskEntity existingTask = getById(taskEntity.getId()); |
| | | taskEntity.setId(existingTask.getId()); |
| | | if (existingTask == null) { |
| | | throw new RuntimeException("巡查任务不存在"); |
| | | } |
| | | |
| | | // 2. 先确定枚举状态:根据当前状态确定新的枚举状态 |
| | | PatrolTaskStatusEnum targetStatus; |
| | | String currentStatus = existingTask.getTaskStatus(); |
| | | // 1.发布中_拒绝接单 、 4.响应中_审核驳回 |
| | | switch (currentStatus) { |
| | | case "1": // 发布中_拒绝接单 → 发布中_接单中 |
| | | targetStatus = PatrolTaskStatusEnum.PENDING_SIGNING; |
| | | break; |
| | | case "4": // 响应中_审核驳回 → 响应中_待审核 |
| | | targetStatus = PatrolTaskStatusEnum.PENDING_AUDIT; |
| | | break; |
| | | default: |
| | | // 其他状态,保持原有状态 |
| | | targetStatus = PatrolTaskStatusEnum.getByValue(currentStatus); |
| | | // 如果无法获取枚举,使用待签收作为默认状态 |
| | | if (targetStatus == null) { |
| | | targetStatus = PatrolTaskStatusEnum.PENDING_SIGNING; |
| | | } |
| | | } |
| | | |
| | | // 3. 设置任务状态:使用枚举设置任务状态 |
| | | taskEntity.setTaskStatus(targetStatus.getValue()); |
| | | |
| | | // 4. 更新任务信息:合并传入的任务信息 |
| | | taskEntity.setUpdateUser(AuthUtil.getUserId() == null ? 0L : AuthUtil.getUserId()); |
| | | taskEntity.setUpdateTime(new Date()); |
| | | |
| | | // 5. 更新数据库 |
| | | boolean updateResult = updateById(taskEntity); |
| | | if (!updateResult) { |
| | | throw new RuntimeException("更新任务信息失败"); |
| | | } |
| | | |
| | | // 6. 保存流转记录:使用枚举设置flowName |
| | | GdWorkOrderFlowEntity flowEntity = new GdWorkOrderFlowEntity(); |
| | | flowEntity.setCreateUser(AuthUtil.getUserId() == null ? 0L : AuthUtil.getUserId()); |
| | | flowEntity.setWorkOrderId(taskEntity.getId()); |
| | | flowEntity.setFlowName(targetStatus.getDesc()); |
| | | flowEntity.setFlowDesc((StringUtil.isBlank(AuthUtil.getNickName()) ? "系统" : AuthUtil.getNickName()) + " " + DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss") + " 更新了任务信息,状态转换为:" + targetStatus.getDesc()); |
| | | flowEntity.setOperator(StringUtil.isBlank(AuthUtil.getNickName()) ? "系统" : AuthUtil.getNickName()); |
| | | flowEntity.setType(WorkOrderTypeEnum.PATROL_TASK.getValue()); |
| | | flowEntity.setAreaCode(existingTask.getAreaCode()); |
| | | flowEntity.setCreateDept(Long.valueOf(StringUtil.isBlank(AuthUtil.getDeptId()) ? "0" : AuthUtil.getDeptId())); |
| | | |
| | | return gdWorkOrderFlowService.save(flowEntity); |
| | | } |
| | | |
| | | @Override |
| | | public boolean exportPatrolReport(Long patrolTaskId) { |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 检查拒绝原因是否必填 |
| | | * |
| | | * @param newStatus 新状态 |
| | | * @param rejectReason 拒绝原因 |
| | | * @throws RuntimeException 当需要拒绝原因但未提供时抛出 |
| | | */ |
| | | // private void checkRejectReason(PatrolTaskStatusEnum newStatus, String rejectReason) { |
| | | // // 拒绝类状态需要填写拒绝原因 |
| | | // if ((newStatus == PatrolTaskStatusEnum.REJECTED_SIGNING || |
| | | // newStatus == PatrolTaskStatusEnum.AUDIT_REJECTED || |
| | | // newStatus == PatrolTaskStatusEnum.REJECTED_ACCEPTANCE) && |
| | | // (rejectReason == null || rejectReason.trim().isEmpty())) { |
| | | // throw new RuntimeException("拒绝操作时必须填写拒绝原因"); |
| | | // } |
| | | // } |
| | | /** |
| | | * 检查拒绝原因是否必填 |
| | | * |
| | | * @param newStatus 新状态 |
| | | * @param rejectReason 拒绝原因 |
| | | * @throws RuntimeException 当需要拒绝原因但未提供时抛出 |
| | | */ |
| | | // private void checkRejectReason(PatrolTaskStatusEnum newStatus, String rejectReason) { |
| | | // // 拒绝类状态需要填写拒绝原因 |
| | | // if ((newStatus == PatrolTaskStatusEnum.REJECTED_SIGNING || |
| | | // newStatus == PatrolTaskStatusEnum.AUDIT_REJECTED || |
| | | // newStatus == PatrolTaskStatusEnum.REJECTED_ACCEPTANCE) && |
| | | // (rejectReason == null || rejectReason.trim().isEmpty())) { |
| | | // throw new RuntimeException("拒绝操作时必须填写拒绝原因"); |
| | | // } |
| | | // } |
| | | |
| | | /** |
| | | * 保存工单流转记录 |
| | | * |
| | | * @param workOrderId 工单ID |
| | | * @param newStatus 新状态 |
| | | * @param rejectReason 拒绝原因 |
| | | * @param areaCode 区域编码 |
| | | * @return 是否保存成功 |
| | | * @throws RuntimeException 当保存失败时抛出 |
| | | */ |
| | | private boolean saveWorkOrderFlow(Long workOrderId, PatrolTaskStatusEnum newStatus, |
| | | String rejectReason, String areaCode) { |
| | | GdWorkOrderFlowEntity flowEntity = new GdWorkOrderFlowEntity(); |
| | | flowEntity.setCreateUser(AuthUtil.getUserId()); |
| | | flowEntity.setWorkOrderId(workOrderId); |
| | | flowEntity.setFlowName(newStatus.getStageDesc()); |
| | | /** |
| | | * 保存工单流转记录 |
| | | * |
| | | * @param workOrderId 工单ID |
| | | * @param newStatus 新状态 |
| | | * @param rejectReason 拒绝原因 |
| | | * @param areaCode 区域编码 |
| | | * @return 是否保存成功 |
| | | * @throws RuntimeException 当保存失败时抛出 |
| | | */ |
| | | private boolean saveWorkOrderFlow(Long workOrderId, PatrolTaskStatusEnum newStatus, |
| | | String rejectReason, String areaCode) { |
| | | GdWorkOrderFlowEntity flowEntity = new GdWorkOrderFlowEntity(); |
| | | flowEntity.setCreateUser(AuthUtil.getUserId() == null ? 0L : AuthUtil.getUserId()); |
| | | flowEntity.setWorkOrderId(workOrderId); |
| | | flowEntity.setFlowName(newStatus.getStageDesc()); |
| | | flowEntity.setFlowDesc(newStatus.getStageDesc()); |
| | | flowEntity.setOperator(StringUtil.isBlank(AuthUtil.getNickName()) ? "系统" : AuthUtil.getNickName()); |
| | | flowEntity.setType(WorkOrderTypeEnum.PATROL_TASK.getValue()); |
| | | flowEntity.setAreaCode(areaCode); |
| | | flowEntity.setCreateDept(Long.valueOf(StringUtil.isBlank(AuthUtil.getDeptId()) ? "0" : AuthUtil.getDeptId())); |
| | | |
| | | // 构建流转描述 |
| | | String flowDesc = buildFlowDesc(newStatus, rejectReason); |
| | | flowEntity.setFlowDesc(flowDesc); |
| | | boolean saveResult = gdWorkOrderFlowService.save(flowEntity); |
| | | if (!saveResult) { |
| | | throw new RuntimeException("保存流转记录失败"); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | flowEntity.setOperator(AuthUtil.getUserName()); |
| | | flowEntity.setType(WorkOrderTypeEnum.PATROL_TASK.getValue()); |
| | | flowEntity.setAreaCode(areaCode); |
| | | flowEntity.setCreateDept(Long.valueOf(AuthUtil.getDeptId())); |
| | | |
| | | boolean saveResult = gdWorkOrderFlowService.save(flowEntity); |
| | | if (!saveResult) { |
| | | throw new RuntimeException("保存流转记录失败"); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * 构建流转描述 |
| | | * |
| | | * @param newStatus 新状态 |
| | | * @param rejectReason 拒绝原因 |
| | | * @return 流转描述 |
| | | */ |
| | | private String buildFlowDesc(PatrolTaskStatusEnum newStatus, String rejectReason) { |
| | | String baseDesc = String.format("%s %s ", |
| | | AuthUtil.getUserName(), |
| | | DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss")); |
| | | |
| | | // 拒绝类状态需要添加拒绝原因 |
| | | if (newStatus == PatrolTaskStatusEnum.REJECTED_SIGNING || |
| | | newStatus == PatrolTaskStatusEnum.AUDIT_REJECTED || |
| | | newStatus == PatrolTaskStatusEnum.REJECTED_ACCEPTANCE) { |
| | | return String.format("%s%s:%s", baseDesc, newStatus.getDesc(), rejectReason); |
| | | } |
| | | |
| | | // 其他状态直接使用枚举描述 |
| | | return baseDesc + newStatus.getDesc(); |
| | | } |
| | | |
| | | /** |
| | | * 根据部门ID获取部门名称 |
| | | * |
| | | * @param deptId 部门ID |
| | | * @return 部门名称,缺失时返回"/" |
| | | */ |
| | | private String getDeptName(Long deptId) { |
| | | if (deptId == null) { |
| | | return "/"; |
| | |
| | | return dept.getDeptName(); |
| | | } |
| | | |
| | | /** |
| | | * 根据用户ID获取用户姓名 |
| | | * |
| | | * @param userId 用户ID |
| | | * @return 用户姓名,缺失时返回"/" |
| | | */ |
| | | private String getUserName(Long userId) { |
| | | if (userId == null) { |
| | | return "/"; |
| | |
| | | return StringUtil.isBlank(realName) ? "/" : realName; |
| | | } |
| | | |
| | | /** |
| | | * 上传巡查报告并保存附件信息 |
| | | * |
| | | * @param reportFile 报告文件 |
| | | * @param taskEntity 巡查任务 |
| | | * @return 是否保存成功 |
| | | */ |
| | | private boolean saveAttachFile(File reportFile, GdPatrolTaskEntity taskEntity) throws IOException { |
| | | if (reportFile == null || !reportFile.exists()) { |
| | | throw new RuntimeException("巡查报告文件不存在"); |
| | |
| | | if (bladeFile == null || StringUtil.isBlank(bladeFile.getLink())) { |
| | | throw new RuntimeException("附件上传失败"); |
| | | } |
| | | Integer resultType = parseResultType(taskEntity != null ? taskEntity.getPatrolTaskType() : null); |
| | | Attach attach = buildAttachInfo(taskEntity, reportFile, bladeFile, resultType, desiredName); |
| | | // Integer resultType = parseResultType(taskEntity != null ? taskEntity.getPatrolTaskType() : null); |
| | | Attach attach = buildAttachInfo(taskEntity, reportFile, bladeFile, taskEntity.getPatrolTaskType(), desiredName); |
| | | Boolean saved = attachClient.saveAttachInfo(attach); |
| | | if (!Boolean.TRUE.equals(saved)) { |
| | | log.error("附件信息保存失败,报告文件:" + desiredName); |
| | |
| | | return true; |
| | | } |
| | | |
| | | private Attach buildAttachInfo(GdPatrolTaskEntity taskEntity, File reportFile, BladeFile bladeFile, Integer resultType, String desiredName) { |
| | | /** |
| | | * 构建附件元数据 |
| | | * |
| | | * @param taskEntity 巡查任务 |
| | | * @param reportFile 报告文件 |
| | | * @param bladeFile 文件上传结果 |
| | | * @param resultType 结果类型 |
| | | * @param desiredName 期望文件名 |
| | | * @return 附件信息 |
| | | */ |
| | | private Attach buildAttachInfo(GdPatrolTaskEntity taskEntity, File reportFile, BladeFile bladeFile, List<List<String>> resultType, String desiredName) { |
| | | Attach attach = new Attach(); |
| | | attach.setDomainUrl(bladeFile.getDomain()); |
| | | attach.setLink(bladeFile.getLink()); |
| | | attach.setName(desiredName); |
| | | attach.setOriginalName(desiredName); |
| | | attach.setName(bladeFile.getName()); |
| | | attach.setOriginalName(bladeFile.getOriginalName()); |
| | | attach.setAttachSize(reportFile.length()); |
| | | attach.setExtension(FileUtil.getFileExtension(reportFile.getName())); |
| | | attach.setResultType(resultType); |
| | |
| | | Long updateUser = taskEntity != null ? taskEntity.getUpdateUser() : null; |
| | | Long createDept = taskEntity != null ? taskEntity.getCreateDept() : null; |
| | | if (createUser == null) { |
| | | createUser = AuthUtil.getUserId(); |
| | | createUser = AuthUtil.getUserId() == null ? 0L : AuthUtil.getUserId(); |
| | | } |
| | | if (updateUser == null) { |
| | | updateUser = createUser; |
| | | } |
| | | if (createDept == null) { |
| | | createDept = Long.valueOf(AuthUtil.getDeptId()); |
| | | createDept = Long.valueOf(StringUtil.isBlank(AuthUtil.getDeptId()) ? "0" : AuthUtil.getDeptId()); |
| | | } |
| | | Date now = new Date(); |
| | | attach.setCreateUser(createUser); |
| | |
| | | return attach; |
| | | } |
| | | |
| | | /** |
| | | * 生成报告附件名称 |
| | | * |
| | | * @param taskEntity 巡查任务 |
| | | * @param fallbackName 兜底文件名 |
| | | * @return 附件名称 |
| | | */ |
| | | private String buildReportAttachName(GdPatrolTaskEntity taskEntity, String fallbackName) { |
| | | String taskNo = taskEntity != null ? taskEntity.getTaskNo() : null; |
| | | if (StringUtil.isBlank(taskNo)) { |
| | |
| | | return taskNo + ".docx"; |
| | | } |
| | | |
| | | /** |
| | | * 解析巡查任务类型为结果类型 |
| | | * |
| | | * @param patrolTaskType 巡查任务类型 |
| | | * @return 结果类型 |
| | | */ |
| | | private Integer parseResultType(String patrolTaskType) { |
| | | if (StringUtil.isBlank(patrolTaskType)) { |
| | | return null; |
| | |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public R pushXingtuFlyTask(Long patrolTaskId) { |
| | | if (patrolTaskId == null) { |
| | | return R.fail("巡查任务主键不能为空"); |
| | | } |
| | | GdPatrolTaskVO taskEntity = baseMapper.getPatrolTaskIdById(patrolTaskId); |
| | | if (taskEntity == null) { |
| | | return R.fail("巡查任务不存在"); |
| | | } |
| | | GdXingtuFlyTaskSaveDTO param = buildXingtuFlyTask(taskEntity); |
| | | return jianXingtuApiService.saveFlyTask(param); |
| | | } |
| | | |
| | | /** |
| | | * 构建巡察任务推送的巡察任务信息 |
| | | * |
| | | * @param gdPatrolTaskVO |
| | | * @return |
| | | */ |
| | | private GdXingtuFlyTaskSaveDTO buildXingtuFlyTask(GdPatrolTaskVO gdPatrolTaskVO) { |
| | | GdXingtuFlyTaskSaveDTO param = new GdXingtuFlyTaskSaveDTO(); |
| | | if (StringUtil.isNotBlank(gdPatrolTaskVO.getPatrolTaskName())) { |
| | | param.setName(gdPatrolTaskVO.getPatrolTaskName()); |
| | | } else if (StringUtil.isNotBlank(gdPatrolTaskVO.getTaskNo())) { |
| | | param.setName(gdPatrolTaskVO.getTaskNo()); |
| | | } |
| | | // if (StringUtil.isNotBlank(gdPatrolTaskVO.getPatrolTaskType())) { |
| | | // param.setInspectionType(gdPatrolTaskVO.getPatrolTaskType()); |
| | | // } |
| | | if ((gdPatrolTaskVO.getId() != null)) { |
| | | param.setPatrolTaskId(String.valueOf(gdPatrolTaskVO.getId())); |
| | | } |
| | | param.setTimingType("单次执行"); |
| | | if (StringUtil.isNotBlank(gdPatrolTaskVO.getAirlineId())) { |
| | | param.setAirlineId(gdPatrolTaskVO.getAirlineId()); |
| | | } |
| | | if (gdPatrolTaskVO.getExecuteTime() != null) { |
| | | param.setSingleTime(DateUtil.format(gdPatrolTaskVO.getExecuteTime(), "yyyy-MM-dd HH:mm:ss")); |
| | | } |
| | | if (StringUtil.isNotBlank(gdPatrolTaskVO.getAreaCode())) { |
| | | // regionCode : "3600,3608,360802" |
| | | String regionCode = convertAreaCodeToRegionCode(gdPatrolTaskVO.getAreaCode()); |
| | | param.setRegionCode(regionCode); |
| | | } |
| | | if (StringUtil.isNotBlank(gdPatrolTaskVO.getAirportId())) { |
| | | param.setAirportId(gdPatrolTaskVO.getAirportId()); |
| | | } |
| | | if (StringUtil.isNotBlank(gdPatrolTaskVO.getDeviceFlyerId())) { |
| | | param.setDeviceFlyerId(gdPatrolTaskVO.getDeviceFlyerId()); |
| | | } |
| | | if (gdPatrolTaskVO.getAlgorithmIds() != null && !gdPatrolTaskVO.getAlgorithmIds().isEmpty()) { |
| | | // 将 List<String> 转换为逗号分隔的字符串 |
| | | String algorithmIdStr = String.join(",", gdPatrolTaskVO.getAlgorithmIds()); |
| | | param.setAlgorithmId(algorithmIdStr); |
| | | } |
| | | // 机构 |
| | | param.setDeptId(gdPatrolTaskVO.getCreateDept()); |
| | | // 巡检类型 |
| | | param.setInspectionTypeArr(gdPatrolTaskVO.getPatrolTaskType()); |
| | | // param.setInspectionType(gdPatrolTaskVO.getPatrolTaskType()); |
| | | // 机巢名称 |
| | | param.setAirportName(gdPatrolTaskVO.getDeviceName()); |
| | | param.setStatus("待执行"); |
| | | param.setTaskType("定时飞行"); |
| | | return param; |
| | | } |
| | | |
| | | @Override |
| | | public GdPatrolTaskVO getPatrolTaskDetail(GdPatrolTaskEntity gdPatrolTaskEntity) { |
| | | return baseMapper.getPatrolTaskDetail(gdPatrolTaskEntity); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) // 添加事务注解,确保数据一致性 |
| | | public boolean updatePatrolTaskById(GdPatrolTaskEntity auditParam) { |
| | | // 1. 更新当前任务状态 |
| | | boolean updateResult = updateById(auditParam); |
| | | if (!updateResult) { |
| | | log.warn("更新任务失败,任务ID: {}", auditParam.getId()); |
| | | return false; |
| | | } |
| | | |
| | | // 2. 获取当前任务实体(优先使用 auditParam 中的数据,避免重复查询) |
| | | GdPatrolTaskEntity patrolTaskEntity = Optional.ofNullable(getById(auditParam.getId())) |
| | | .orElseThrow(() -> new RuntimeException("任务不存在,任务ID: " + auditParam.getId())); |
| | | |
| | | // 3. 保存巡查工单流转(使用传入的实际状态) |
| | | PatrolTaskStatusEnum statusEnum = PatrolTaskStatusEnum.getByValue(auditParam.getTaskStatus()); |
| | | if (statusEnum != null) { |
| | | saveWorkOrderFlow(patrolTaskEntity.getId(), statusEnum, null, patrolTaskEntity.getAreaCode()); |
| | | } |
| | | |
| | | // 4. 查询同一个工单下的所有子任务 |
| | | List<GdPatrolTaskEntity> subTasks = list(Wrappers.<GdPatrolTaskEntity>lambdaQuery() |
| | | .eq(GdPatrolTaskEntity::getWorkOrderId, patrolTaskEntity.getWorkOrderId())); |
| | | |
| | | // 5. 判空处理,防止 NullPointerException |
| | | if (CollectionUtils.isEmpty(subTasks)) { |
| | | log.info("工单ID {} 下无子任务", patrolTaskEntity.getWorkOrderId()); |
| | | return true; |
| | | } |
| | | |
| | | // 6. 判断是否有小于待验收的工单(统一使用枚举值比较) |
| | | boolean hasLessThanPendingAcceptance = subTasks.stream() |
| | | .map(GdPatrolTaskEntity::getTaskStatus) |
| | | .filter(Objects::nonNull) |
| | | .anyMatch(status -> status.compareTo(PatrolTaskStatusEnum.PENDING_ACCEPTANCE.getValue()) < 0); |
| | | |
| | | // 7. 根据判断结果决定是否更新工单状态 |
| | | if (!hasLessThanPendingAcceptance) { |
| | | updateWorkOrderStatusAndFlow(patrolTaskEntity.getWorkOrderId(), WorkOrderStatusEnum.COMPLETED_TO_BE_INSPECTED); |
| | | log.info("工单ID {} 下所有子任务均已达到待验收状态,更新工单状态为完成待验", patrolTaskEntity.getWorkOrderId()); |
| | | } else { |
| | | log.warn("工单ID {} 下存在未达待验收状态的子任务", patrolTaskEntity.getWorkOrderId()); |
| | | } |
| | | |
| | | return updateResult; |
| | | } |
| | | |
| | | @Override |
| | | public List<GdPatrolTaskSimpleVO> selectListByWorkOrderId(Long workOrderId) { |
| | | return baseMapper.selectListByWorkOrderId(workOrderId); |
| | | } |
| | | |
| | | /** |
| | | * 查询待验收状态的巡查任务列表(对外接口) |
| | | * |
| | | * @param queryParam 查询参数,包含任务名称和时间区间 |
| | | * @return 待验收状态的巡查任务列表 |
| | | */ |
| | | @Override |
| | | public List<GdPatrolTaskVO> selectPendingAcceptanceTasks(GdPatrolTaskPendingAcceptanceQueryParam queryParam) { |
| | | // 1. 参数校验:防止空指针 |
| | | if (queryParam == null) { |
| | | queryParam = new GdPatrolTaskPendingAcceptanceQueryParam(); |
| | | } |
| | | |
| | | // 2. 调用Mapper查询待验收状态的巡查任务 |
| | | List<GdPatrolTaskVO> pendingAcceptanceTasks = baseMapper.selectPendingAcceptanceTasks(queryParam); |
| | | |
| | | // 3. 返回查询结果 |
| | | return pendingAcceptanceTasks; |
| | | } |
| | | |
| | | /** |
| | | * 将区域编码转换为多级行政区划编码格式 |
| | | * |
| | | * @param areaCode 区域编码(如:360802) |
| | | * @return 多级行政区划编码,格式为 "省编码,市编码,区编码"(如:"3600,3608,360802") |
| | | */ |
| | | private String convertAreaCodeToRegionCode(String areaCode) { |
| | | if (StringUtil.isBlank(areaCode)) { |
| | | return null; |
| | | } |
| | | |
| | | // 如果已经是逗号分隔的格式,直接返回 |
| | | if (areaCode.contains(",")) { |
| | | return areaCode; |
| | | } |
| | | |
| | | // 去除空格并确保长度为6位 |
| | | String cleanCode = areaCode.trim(); |
| | | // 如果长度大于6位,只取前6位 |
| | | if (cleanCode.length() > 6) { |
| | | log.warn("区域编码长度超过6位,截取前6位: {}", cleanCode); |
| | | cleanCode = cleanCode.substring(0, 6); |
| | | } |
| | | if (cleanCode.length() != 6) { |
| | | log.warn("区域编码格式不正确,期望6位数字,实际为: {}", cleanCode); |
| | | return cleanCode; |
| | | } |
| | | |
| | | try { |
| | | // 提取省、市、区三级编码 |
| | | String provinceCode = cleanCode.substring(0, 2) + "00"; // 省级编码(如:3600) |
| | | String cityCode = cleanCode.substring(0, 4); // 市级编码(如:3608) |
| | | String districtCode = cleanCode; // 区级编码(如:360802) |
| | | |
| | | return provinceCode + "," + cityCode + "," + districtCode; |
| | | } catch (Exception e) { |
| | | log.error("区域编码转换失败: {}", e.getMessage()); |
| | | return areaCode; |
| | | } |
| | | } |
| | | |
| | | } |