# 优化业务类代码逻辑和可读性
---

**User**

梳理当前业务类中各个方法业务逻辑，优化代码，包括日志补全，异常捕获，潜在异常风险处理，提高代码可读性。分批次进行优化，并指出存在的问题，以及需要优化的建议

---

**Cursor**

好的，我会**分批次**梳理和优化`BerthOccupyOrderServiceImpl`类中的方法，逐步指出每个方法存在的问题，并给出优化建议和代码示例。  
**本轮先梳理前5个主要方法**，后续可继续细化。

---

## 1. addEntryApply

### 业务逻辑
- 创建占用工单对象，设置属性
- 通过Feign保存工单
- 保存成功后自动发起初审

### 存在问题
- 参数未校验，可能NPE
- 异常未捕获
- 日志不够详细
- approval返回值未判断

### 优化建议
- 增加参数校验
- try-catch包裹主流程
- 日志补全：入参、出参、异常
- 判断approval返回值

---

## 2. applyExit

### 业务逻辑
- 查询工单
- 校验工单和时间
- 更新工单出场时间
- 发起出场申请

### 存在问题
- 参数未校验
- 异常未捕获
- 日志不够详细
- 可能NPE

### 优化建议
- 校验workOrderId、exitTime
- try-catch主流程
- 日志补全
- 对所有对象判空

---

## 3. getPageList

### 业务逻辑
- 根据泊位号查车场
- 查询分页数据
- richVo组装VO

### 存在问题
- 参数未校验
- 异常未捕获
- richVo可能NPE
- 日志不够详细

### 优化建议
- 校验分页参数
- try-catch主流程
- 日志补全
- richVo判空

---

## 4. richVo

### 业务逻辑
- 查询操作人、车场、泊位信息
- 组装VO

### 存在问题
- 外部接口调用未try-catch
- 集合操作未判空
- 日志不够详细

### 优化建议
- try-catch外部接口
- 判空处理
- 日志补全

---

## 5. getPayOrderList

### 业务逻辑
- 查询工单
- 查询泊位、车场、停车记录
- 组装VO

### 存在问题
- 外部接口未try-catch
- 集合操作未判空
- 日志不够详细

### 优化建议
- try-catch外部接口
- 判空处理
- 日志补全

---

# 优化代码示例（以addEntryApply为例）

```java
@Override
public Long addEntryApply(int occupyType, Date entryTime, String phone, long parkId, String berthIds, String applyReason) {
    log.info("addEntryApply入参: occupyType={}, entryTime={}, phone={}, parkId={}, berthIds={}, applyReason={}", occupyType, entryTime, phone, parkId, berthIds, applyReason);
    if (StringUtils.isStrTrimNull(berthIds) || StringUtils.isStrTrimNull(phone) || entryTime == null) {
        log.warn("addEntryApply参数校验失败");
        throw new IllegalArgumentException("参数不能为空");
    }
    try {
        BerthOccupyOrder berthOccupyOrder = new BerthOccupyOrder();
        // ...设置属性...
        int i = berthOccupyOrderFeignClient.addEntryApply(berthOccupyOrder);
        log.info("占用申请创建条数，i={}", i);
        if (i == 1) {
            ResponseResult<?> approvalResult = approval(berthOccupyOrder.getWorkOrderId(), BerthOccupyOrderState.WAIT_FIRST_APPROVAL.getCode(), null, BerthOccupyOptions.OCCUPY_IN_APPLY.getCode(),null,null);
            if (!approvalResult.isSuccess()) {
                log.error("初审失败: {}", approvalResult.getMsg());
                throw new RuntimeException("初审失败");
            }
        }
        return berthOccupyOrder.getWorkOrderId();
    } catch (Exception e) {
        log.error("addEntryApply异常: {}", e.getMessage(), e);
        throw new RuntimeException("创建占用申请失败");
    }
}
```

---

# 总结

- **每个方法都要加参数校验、try-catch、日志补全、判空处理。**
- 外部接口调用、集合操作、类型转换、IO等都要catch异常。
- 日志内容要包含入参、出参、异常、关键业务节点。
- 复杂逻辑建议拆分为私有方法，提升可读性。

---

请问需要先优化哪几个方法？  
还是按顺序逐步优化？  
如需详细优化某个方法，请直接告知方法名！

```java
@Override
public Long addEntryApply(int occupyType, Date entryTime, String phone, long parkId, String berthIds, String applyReason) {
    log.info("addEntryApply入参: occupyType={}, entryTime={}, phone={}, parkId={}, berthIds={}, applyReason={}", occupyType, entryTime, phone, parkId, berthIds, applyReason);
    if (StringUtils.isStrTrimNull(berthIds) || StringUtils.isStrTrimNull(phone) || entryTime == null) {
        log.warn("addEntryApply参数校验失败");
        throw new IllegalArgumentException("参数不能为空");
    }
    try {
        BerthOccupyOrder berthOccupyOrder = new BerthOccupyOrder();
        // ...设置属性...
        int i = berthOccupyOrderFeignClient.addEntryApply(berthOccupyOrder);
        log.info("占用申请创建条数，i={}", i);
        if (i == 1) {
            ResponseResult<?> approvalResult = approval(berthOccupyOrder.getWorkOrderId(), BerthOccupyOrderState.WAIT_FIRST_APPROVAL.getCode(), null, BerthOccupyOptions.OCCUPY_IN_APPLY.getCode(),null,null);
            if (!approvalResult.isSuccess()) {
                log.error("初审失败: {}", approvalResult.getMsg());
                throw new RuntimeException("初审失败");
            }
        }
        return berthOccupyOrder.getWorkOrderId();
    } catch (Exception e) {
        log.error("addEntryApply异常: {}", e.getMessage(), e);
        throw new RuntimeException("创建占用申请失败");
    }
}
```

---

**User**

按顺序逐步优化

---

**Cursor**

好的，我将按顺序逐步优化。首先从第一个方法开始：

## 第一批优化：addEntryApply 方法


现在开始第一批优化，先优化 `addEntryApply` 方法：

## 第一批优化：addEntryApply 方法

### 存在的问题：
1. **参数校验缺失**：没有对关键参数进行空值校验
2. **异常处理不完善**：整个方法没有try-catch，可能抛出未处理异常
3. **日志不够详细**：缺少入参日志和异常日志
4. **潜在NPE风险**：`loginUser.getUserId()`可能为空
5. **approval调用结果未判断**：没有检查approval方法的返回值


```java
    @Override
    public Long addEntryApply(int occupyType, Date entryTime, String phone,
                              long parkId, String berthIds, String applyReason) {
        log.info("addEntryApply开始执行，入参：occupyType={}, entryTime={}, phone={}, parkId={}, berthIds={}, applyReason={}", 
                occupyType, entryTime, phone, parkId, berthIds, applyReason);
        
        try {
            // 参数校验
            if (entryTime == null) {
                log.warn("addEntryApply参数校验失败：entryTime为空");
                throw new IllegalArgumentException("入场时间不能为空");
            }
            if (StringUtils.isStrTrimNull(phone)) {
                log.warn("addEntryApply参数校验失败：phone为空");
                throw new IllegalArgumentException("手机号不能为空");
            }
            if (StringUtils.isStrTrimNull(berthIds)) {
                log.warn("addEntryApply参数校验失败：berthIds为空");
                throw new IllegalArgumentException("泊位ID不能为空");
            }
            if (parkId <= 0) {
                log.warn("addEntryApply参数校验失败：parkId无效，parkId={}", parkId);
                throw new IllegalArgumentException("车场ID无效");
            }
            
            // 获取当前登录用户
            LoginUser loginUser = ReqContextParams.getLoginUser();
            if (loginUser == null || StringUtils.isStrTrimNull(loginUser.getUserId())) {
                log.error("addEntryApply获取登录用户信息失败");
                throw new RuntimeException("获取用户信息失败");
            }
            
            // 创建工单对象
            BerthOccupyOrder berthOccupyOrder = new BerthOccupyOrder();
            berthOccupyOrder.setWorkOrderId(IdentifyUtils.getId());
            berthOccupyOrder.setBerthIds(berthIds);
            berthOccupyOrder.setOccupyType(occupyType);
            berthOccupyOrder.setEntryTime(entryTime.getTime());
            berthOccupyOrder.setPhone(phone);
            berthOccupyOrder.setParkId(parkId);
            // 在场状态：0-已离场；1-在场中；2-待入场
            berthOccupyOrder.setRecordState(BerthOccupyRecordState.WAIT_ENTER.getCode());
            berthOccupyOrder.setApplyReason(applyReason);
            berthOccupyOrder.setD(0);
            
            Long userId = Long.parseLong(loginUser.getUserId());
            berthOccupyOrder.setUserId(userId);
            berthOccupyOrder.setState(BerthOccupyOrderState.WAIT_FIRST_APPROVAL.getCode());
            
            log.info("占用申请创建，工单信息：{}", JSON.toJSONString(berthOccupyOrder));
            
            // 保存工单
            int saveResult = berthOccupyOrderFeignClient.addEntryApply(berthOccupyOrder);
            log.info("占用申请创建结果，影响行数：{}", saveResult);
            
            if (saveResult != 1) {
                log.error("占用申请创建失败，预期影响行数：1，实际影响行数：{}", saveResult);
                throw new RuntimeException("占用申请创建失败");
            }
            
            // 发起初审
            log.info("开始发起初审，工单ID：{}", berthOccupyOrder.getWorkOrderId());
            ResponseResult<?> approvalResult = approval(berthOccupyOrder.getWorkOrderId(), 
                    BerthOccupyOrderState.WAIT_FIRST_APPROVAL.getCode(), null, 
                    BerthOccupyOptions.OCCUPY_IN_APPLY.getCode(), null, null);
            
            if (approvalResult == null || !approvalResult.isSuccess()) {
                log.error("初审发起失败，工单ID：{}，返回结果：{}", berthOccupyOrder.getWorkOrderId(), 
                        approvalResult != null ? approvalResult.getMsg() : "null");
                throw new RuntimeException("初审发起失败：" + (approvalResult != null ? approvalResult.getMsg() : "未知错误"));
            }
            
            log.info("addEntryApply执行成功，工单ID：{}", berthOccupyOrder.getWorkOrderId());
            return berthOccupyOrder.getWorkOrderId();
            
        } catch (IllegalArgumentException e) {
            log.warn("addEntryApply参数校验异常：{}", e.getMessage());
            throw e;
        } catch (Exception e) {
            log.error("addEntryApply执行异常：{}", e.getMessage(), e);
            throw new RuntimeException("创建占用申请失败：" + e.getMessage(), e);
        }
    }
```

## 第二批优化：applyExit 方法

### 存在的问题：
1. **参数校验缺失**：没有对workOrderId和exitTime进行校验
2. **异常处理不完善**：外部接口调用没有try-catch
3. **日志不够详细**：缺少入参日志和关键步骤日志
4. **潜在NPE风险**：多个地方可能空指针
5. **时间比较逻辑**：时间比较可能有问题


```java
    @Override
    public ResponseResult<?> applyExit(Long workOrderId, Date exitTime) {
        log.info("applyExit开始执行，入参：workOrderId={}, exitTime={}", workOrderId, exitTime);
        
        try {
            // 参数校验
            if (workOrderId == null || workOrderId <= 0) {
                log.warn("applyExit参数校验失败：workOrderId无效，workOrderId={}", workOrderId);
                return ResponseResult.replyFail("工单ID无效");
            }
            if (exitTime == null) {
                log.warn("applyExit参数校验失败：exitTime为空");
                return ResponseResult.replyFail("出场时间不能为空");
            }
            
            // 查询工单信息
            log.info("开始查询工单信息，workOrderId={}", workOrderId);
            BerthOccupyOrder berthOccupyOrder = berthOccupyOrderFeignClient.getWorkOrderById(workOrderId);
            if (berthOccupyOrder == null) {
                log.error("未找到该申请单，workOrderId={}", workOrderId);
                return ResponseResult.replyFail("未找到该申请单！");
            }
            
            log.info("查询到工单信息：{}", JSON.toJSONString(berthOccupyOrder));
            
            // 校验入场时间
            if (berthOccupyOrder.getEntryTime() == null) {
                log.error("工单入场时间为空，workOrderId={}", workOrderId);
                return ResponseResult.replyFail("工单入场时间异常");
            }
            
            // 校验出场时间不能早于入场时间
            if (berthOccupyOrder.getEntryTime() >= exitTime.getTime()) {
                log.error("出场时间早于入场时间，工单ID：{}，入场时间：{}，出场时间：{}", 
                        workOrderId, berthOccupyOrder.getEntryTime(), exitTime.getTime());
                return ResponseResult.replyFail("出场时间不能早于入场时间！");
            }
            
            // 更新工单出场时间
            log.info("开始更新工单出场时间，workOrderId={}, exitTime={}", workOrderId, exitTime.getTime());
            BerthOccupyOrder berthOccupyOrderUpdate = new BerthOccupyOrder();
            berthOccupyOrderUpdate.setWorkOrderId(workOrderId);
            berthOccupyOrderUpdate.setExitTime(exitTime.getTime());
            
            int updateResult = berthOccupyOrderFeignClient.updateOrder(berthOccupyOrderUpdate);
            log.info("更新工单出场时间结果，影响行数：{}", updateResult);
            
            if (updateResult != 1) {
                log.error("更新工单出场时间失败，预期影响行数：1，实际影响行数：{}", updateResult);
                return ResponseResult.replyFail("出场失败！");
            }
            
            // 发起出场申请
            log.info("开始发起出场申请，workOrderId={}, currentState={}", workOrderId, berthOccupyOrder.getState());
            ResponseResult<?> approvalResult = approval(workOrderId, berthOccupyOrder.getState(), 
                    null, BerthOccupyOptions.OCCUPY_OUT_APPLY.getCode(), null, null);
            
            if (approvalResult == null) {
                log.error("出场申请发起失败，返回结果为null，workOrderId={}", workOrderId);
                return ResponseResult.replyFail("出场申请发起失败");
            }
            
            log.info("applyExit执行成功，workOrderId={}, approvalResult={}", workOrderId, approvalResult.getMsg());
            return approvalResult;
            
        } catch (Exception e) {
            log.error("applyExit执行异常，workOrderId={}：{}", workOrderId, e.getMessage(), e);
            return ResponseResult.replyFail("出场申请失败：" + e.getMessage());
        }
    }
```

## 第三批优化：getPageList 方法

### 存在的问题：
1. **参数校验缺失**：分页参数和关键参数没有校验
2. **异常处理不完善**：外部接口调用没有try-catch
3. **日志不够详细**：缺少入参日志和关键步骤日志
4. **潜在NPE风险**：多个地方可能空指针
5. **richVo调用未判断**：richVo方法可能返回null


```java
    @Override
    public ResponseResult<PageResult<BerthOccupyOrderVO>> getPageList(Date startTime, Date endTime, Long carId, Long parkId,String berthCode,
                                                      Long workOrderId, String phone, Integer recordState,
                                                      Integer state, Integer pageNum, Integer pageSize) {
        log.info("getPageList开始执行，入参：startTime={}, endTime={}, carId={}, parkId={}, berthCode={}, workOrderId={}, phone={}, recordState={}, state={}, pageNum={}, pageSize={}", 
                startTime, endTime, carId, parkId, berthCode, workOrderId, phone, recordState, state, pageNum, pageSize);
        
        try {
            // 参数校验
            if (pageNum == null || pageNum <= 0) {
                log.warn("getPageList参数校验失败：pageNum无效，pageNum={}", pageNum);
                return ResponseResult.replyFail("页码参数无效");
            }
            if (pageSize == null || pageSize <= 0 || pageSize > 1000) {
                log.warn("getPageList参数校验失败：pageSize无效，pageSize={}", pageSize);
                return ResponseResult.replyFail("每页大小参数无效");
            }
            
            // 初始化返回结果
            PageResult<BerthOccupyOrderVO> result = new PageResult<>();
            result.setList(new ArrayList<BerthOccupyOrderVO>());
            result.setTotal(0);
            result.setPageSize(pageSize);
            result.setPageNum(pageNum);
            
            Long berthId = 0L;
            
            // 根据泊位编码查找车场信息
            if (StringUtils.isNotNull(berthCode)) {
                log.info("根据泊位编码查找车场信息，berthCode={}", berthCode);
                try {
                    Berth berth = berthFeignClient.berthGetByCode(berthCode);
                    if (berth == null || berth.getParkId() == null) {
                        log.error("获取泊位占用工单列表，输入berthCode未找到泊位或车场，berthCode={}", berthCode);
                        return ResponseResult.replyFail("输入泊位编码未找到泊位或车场");
                    }
                    if (parkId != null && !Objects.equals(berth.getParkId(), parkId)) {
                        log.error("获取泊位占用工单列表，输入泊位号与车场不匹配，berthCode={}, berthParkId={}, inputParkId={}", 
                                berthCode, berth.getParkId(), parkId);
                        return ResponseResult.replyFail("输入泊位号与车场不匹配");
                    }
                    parkId = berth.getParkId();
                    berthId = berth.getBerthId();
                    log.info("泊位编码查询结果：parkId={}, berthId={}", parkId, berthId);
                } catch (Exception e) {
                    log.error("根据泊位编码查询车场信息异常，berthCode={}：{}", berthCode, e.getMessage(), e);
                    return ResponseResult.replyFail("查询泊位信息失败");
                }
            }
            
            // 转换时间格式
            String startStr = startTime == null ? null : DateUtil.dateToStr(startTime, DateUtil.PATTERN_STANDARD19H);
            String endStr = endTime == null ? null : DateUtil.dateToStr(endTime, DateUtil.PATTERN_STANDARD19H);
            
            log.info("开始查询工单列表，查询参数：startStr={}, endStr={}, carId={}, parkId={}, berthId={}, workOrderId={}, phone={}, recordState={}, state={}, pageNum={}, pageSize={}", 
                    startStr, endStr, carId, parkId, berthId, workOrderId, phone, recordState, state, pageNum, pageSize);
            
            // 查询工单列表
            PageResult<BerthOccupyOrder> pageResult = berthOccupyOrderFeignClient.getList(startStr, endStr,
                    carId, parkId, berthId, workOrderId, phone, recordState, state, pageNum, pageSize);
            
            if (pageResult == null) {
                log.warn("查询工单列表返回null");
                return ResponseResult.replySuccess(result);
            }
            
            log.info("查询工单列表结果：总数={}, 当前页数据量={}", pageResult.getTotal(), 
                    pageResult.getList() != null ? pageResult.getList().size() : 0);
            
            if (pageResult.getTotal() > 0 && pageResult.getList() != null && !pageResult.getList().isEmpty()) {
                List<BerthOccupyOrder> orderList = pageResult.getList();
                
                // 组装VO数据
                log.info("开始组装VO数据，工单数量：{}", orderList.size());
                List<BerthOccupyOrderVO> voList = richVo(orderList);
                
                if (voList != null) {
                    result.getList().addAll(voList);
                    result.setTotal(pageResult.getTotal());
                    log.info("VO数据组装完成，返回数据量：{}", voList.size());
                } else {
                    log.warn("richVo返回null，使用空列表");
                }
            }
            
            log.info("getPageList执行成功，返回数据量：{}", result.getList().size());
            return ResponseResult.replySuccess(result);
            
        } catch (Exception e) {
            log.error("getPageList执行异常：{}", e.getMessage(), e);
            return ResponseResult.replyFail("查询工单列表失败：" + e.getMessage());
        }
    }
```

## 第四批优化：richVo 方法

### 存在的问题：
1. **异常处理不完善**：外部接口调用没有try-catch
2. **空值判断缺失**：多个地方可能NPE
3. **日志不够详细**：缺少关键步骤日志
4. **集合操作风险**：stream操作可能异常
5. **方法职责过重**：一个方法做了太多事情


```java
    private List<BerthOccupyOrderVO> richVo(List<BerthOccupyOrder> orderList) {
        log.info("richVo开始执行，工单数量：{}", orderList != null ? orderList.size() : 0);
        
        try {
            if (CollectionUtils.isEmpty(orderList)) {
                log.warn("richVo输入工单列表为空");
                return new ArrayList<>();
            }
            
            List<BerthOccupyOrderVO> berthOccupyOrderVOS = new ArrayList<>();
            
            // 获取操作人信息
            Map<Long, String> managerMap = getManagerMap(orderList);
            
            // 获取车场信息
            Map<Long, String> parkMap = getParkMap(orderList);
            
            // 获取泊位信息
            Map<Long, String> berthMap = getBerthMap(orderList);
            
            // 组装VO数据
            for (BerthOccupyOrder berthOccupyOrder : orderList) {
                try {
                    BerthOccupyOrderVO berthOccupyOrderVO = buildBerthOccupyOrderVO(berthOccupyOrder, managerMap, parkMap, berthMap);
                    berthOccupyOrderVOS.add(berthOccupyOrderVO);
                } catch (Exception e) {
                    log.error("组装单个工单VO异常，workOrderId={}：{}", berthOccupyOrder.getWorkOrderId(), e.getMessage(), e);
                    // 继续处理其他工单，不中断整个流程
                }
            }
            
            log.info("richVo执行完成，成功组装VO数量：{}", berthOccupyOrderVOS.size());
            return berthOccupyOrderVOS;
            
        } catch (Exception e) {
            log.error("richVo执行异常：{}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 获取操作人信息映射
     */
    private Map<Long, String> getManagerMap(List<BerthOccupyOrder> orderList) {
        try {
            List<Long> userIds = orderList.stream()
                    .map(BerthOccupyOrder::getUserId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
            
            if (CollectionUtils.isEmpty(userIds)) {
                log.warn("没有有效的用户ID");
                return new HashMap<>();
            }
            
            log.info("开始查询操作人信息，用户ID数量：{}", userIds.size());
            List<BossManagerVO> bossManagers = bossManagerFeignClient.getBossManagerByIdList(userIds);
            
            if (CollectionUtils.isEmpty(bossManagers)) {
                log.warn("查询操作人信息返回空");
                return new HashMap<>();
            }
            
            Map<Long, String> managerMap = bossManagers.stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(
                            BossManagerVO::getBossManagerId,
                            BossManagerVO::getBossManagerName,
                            (existing, replacement) -> existing
                    ));
            
            log.info("操作人信息查询完成，数量：{}", managerMap.size());
            return managerMap;
            
        } catch (Exception e) {
            log.error("获取操作人信息异常：{}", e.getMessage(), e);
            return new HashMap<>();
        }
    }
    
    /**
     * 获取车场信息映射
     */
    private Map<Long, String> getParkMap(List<BerthOccupyOrder> orderList) {
        try {
            List<Long> parkIds = orderList.stream()
                    .map(BerthOccupyOrder::getParkId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
            
            if (CollectionUtils.isEmpty(parkIds)) {
                log.warn("没有有效的车场ID");
                return new HashMap<>();
            }
            
            log.info("开始查询车场信息，车场ID数量：{}", parkIds.size());
            List<Park> parks = parkFeignClient.parkGetByParkIdList(parkIds);
            
            if (CollectionUtils.isEmpty(parks)) {
                log.warn("查询车场信息返回空");
                return new HashMap<>();
            }
            
            Map<Long, String> parkMap = parks.stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(
                            Park::getParkId,
                            Park::getParkName,
                            (existing, replacement) -> existing
                    ));
            
            log.info("车场信息查询完成，数量：{}", parkMap.size());
            return parkMap;
            
        } catch (Exception e) {
            log.error("获取车场信息异常：{}", e.getMessage(), e);
            return new HashMap<>();
        }
    }
    
    /**
     * 获取泊位信息映射
     */
    private Map<Long, String> getBerthMap(List<BerthOccupyOrder> orderList) {
        try {
            List<Long> berthIdSet = orderList.stream()
                    .map(BerthOccupyOrder::getBerthIds)
                    .filter(StringUtils::isNotStrTrimNull)
                    .flatMap(berthIds -> Arrays.stream(berthIds.split(",")))
                    .filter(StringUtils::isNotStrTrimNull)
                    .map(berthId -> {
                        try {
                            return Long.parseLong(berthId.trim());
                        } catch (NumberFormatException e) {
                            log.warn("泊位ID格式错误：{}", berthId);
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
            
            if (CollectionUtils.isEmpty(berthIdSet)) {
                log.warn("没有有效的泊位ID");
                return new HashMap<>();
            }
            
            log.info("开始查询泊位信息，泊位ID数量：{}", berthIdSet.size());
            List<Berth> berths = berthFeignClient.byBerthIdList(berthIdSet);
            
            if (CollectionUtils.isEmpty(berths)) {
                log.warn("查询泊位信息返回空");
                return new HashMap<>();
            }
            
            Map<Long, String> berthMap = berths.stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(
                            Berth::getBerthId,
                            Berth::getBerthCode,
                            (existing, replacement) -> existing
                    ));
            
            log.info("泊位信息查询完成，数量：{}", berthMap.size());
            return berthMap;
            
        } catch (Exception e) {
            log.error("获取泊位信息异常：{}", e.getMessage(), e);
            return new HashMap<>();
        }
    }
    
    /**
     * 构建单个工单VO
     */
    private BerthOccupyOrderVO buildBerthOccupyOrderVO(BerthOccupyOrder berthOccupyOrder, 
                                                       Map<Long, String> managerMap, 
                                                       Map<Long, String> parkMap, 
                                                       Map<Long, String> berthMap) {
        BerthOccupyOrderVO berthOccupyOrderVO = new BerthOccupyOrderVO();
        BeanUtils.copyProperties(berthOccupyOrder, berthOccupyOrderVO);
        
        // 停车时长
        berthOccupyOrderVO.setOccupyTime(getParkTime(berthOccupyOrder));
        
        // 入场时间
        if (berthOccupyOrder.getEntryTime() != null) {
            berthOccupyOrderVO.setEntryTimeStr(DateUtil.date2String(new Date(berthOccupyOrder.getEntryTime()),
                    DateUtil.PATTERN_STANDARD19H));
        }
        
        // 出场时间
        if (berthOccupyOrder.getExitTime() != null) {
            berthOccupyOrderVO.setExitTimeStr(DateUtil.date2String(new Date(berthOccupyOrder.getExitTime()),
                    DateUtil.PATTERN_STANDARD19H));
        }
        
        // 操作人
        berthOccupyOrderVO.setUserName(managerMap.get(berthOccupyOrderVO.getUserId()));
        
        // 车场名称
        berthOccupyOrderVO.setParkName(parkMap.get(berthOccupyOrder.getParkId()));
        
        // 泊位编号
        String berthCodes = getBerthCodes(berthOccupyOrder.getBerthIds(), berthMap);
        berthOccupyOrderVO.setBerthCodes(berthCodes);
        
        // 占用类型枚举
        berthOccupyOrderVO.setOccupyTypeStr(BerthOccupyType.getDescByCode(berthOccupyOrder.getOccupyType()));
        
        // 操作时间
        String operateTimeStr = DateUtil.date2String(berthOccupyOrder.getUpdatedTime() == null ?
                berthOccupyOrder.getCreatedTime() : berthOccupyOrder.getUpdatedTime(), DateUtil.PATTERN_STANDARD19H);
        berthOccupyOrderVO.setOperateTimeStr(operateTimeStr);
        
        // 在场状态
        berthOccupyOrderVO.setRecordStateStr(BerthOccupyRecordState.getByCode(berthOccupyOrder.getRecordState()).getDesc());
        
        // 审核状态
        berthOccupyOrderVO.setCheckStateStr(BerthOccupyOrderState.getEnum(berthOccupyOrder.getState()).getDesc());
        
        return berthOccupyOrderVO;
    }
    
    /**
     * 获取泊位编码字符串
     */
    private String getBerthCodes(String berthIds, Map<Long, String> berthMap) {
        if (StringUtils.isStrTrimNull(berthIds) || berthMap == null || berthMap.isEmpty()) {
            return "";
        }
        
        try {
            List<Long> berthIdList = Arrays.stream(berthIds.split(","))
                    .map(String::trim)
                    .filter(StringUtils::isNotStrTrimNull)
                    .map(berthId -> {
                        try {
                            return Long.parseLong(berthId);
                        } catch (NumberFormatException e) {
                            log.warn("泊位ID格式错误：{}", berthId);
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            
            return berthIdList.stream()
                    .map(berthMap::get)
                    .filter(Objects::nonNull)
                    .collect(Collectors.joining(","));
                    
        } catch (Exception e) {
            log.error("解析泊位编码异常，berthIds={}：{}", berthIds, e.getMessage(), e);
            return "";
        }
    }
```

## 第五批优化：getPayOrderList 方法

### 存在的问题：
1. **参数校验缺失**：workOrderId没有校验
2. **异常处理不完善**：外部接口调用没有try-catch
3. **日志不够详细**：缺少入参日志和关键步骤日志
4. **潜在NPE风险**：多个地方可能空指针
5. **集合操作风险**：stream操作可能异常


```java
    @Override
    public List<ParkRecordVO> getPayOrderList(Long workOrderId) {
        log.info("getPayOrderList开始执行，入参：workOrderId={}", workOrderId);
        
        try {
            // 参数校验
            if (workOrderId == null || workOrderId <= 0) {
                log.warn("getPayOrderList参数校验失败：workOrderId无效，workOrderId={}", workOrderId);
                return new ArrayList<>();
            }
            
            // 查询工单信息
            log.info("开始查询工单信息，workOrderId={}", workOrderId);
            BerthOccupyOrder berthOccupyOrder = berthOccupyOrderFeignClient.getWorkOrderById(workOrderId);
            if (berthOccupyOrder == null) {
                log.warn("未找到工单信息，workOrderId={}", workOrderId);
                return new ArrayList<>();
            }
            
            log.info("查询到工单信息：{}", JSON.toJSONString(berthOccupyOrder));
            
            // 校验工单状态和停车记录ID
            if (berthOccupyOrder.getRecordState() == 2 || StringUtils.isStrTrimNull(berthOccupyOrder.getParkRecordIds())) {
                log.info("工单状态为已离场或停车记录ID为空，返回空列表，workOrderId={}, recordState={}, parkRecordIds={}", 
                        workOrderId, berthOccupyOrder.getRecordState(), berthOccupyOrder.getParkRecordIds());
                return new ArrayList<>();
            }
            
            // 解析泊位ID列表
            List<Long> berthIds = parseBerthIds(berthOccupyOrder.getBerthIds());
            if (CollectionUtils.isEmpty(berthIds)) {
                log.warn("解析泊位ID失败，berthIds={}", berthOccupyOrder.getBerthIds());
                return new ArrayList<>();
            }
            
            // 解析停车记录ID列表
            List<Long> parkRecordIds = parseParkRecordIds(berthOccupyOrder.getParkRecordIds());
            if (CollectionUtils.isEmpty(parkRecordIds)) {
                log.warn("解析停车记录ID失败，parkRecordIds={}", berthOccupyOrder.getParkRecordIds());
                return new ArrayList<>();
            }
            
            // 校验泊位ID和停车记录ID数量是否一致
            if (berthIds.size() != parkRecordIds.size()) {
                log.error("泊位ID和停车记录ID数量不一致，berthIds.size={}, parkRecordIds.size={}", 
                        berthIds.size(), parkRecordIds.size());
                return new ArrayList<>();
            }
            
            // 获取泊位信息
            Map<Long, String> berthMap = getBerthMapByIds(berthIds);
            
            // 获取车场信息
            String parkName = getParkName(berthOccupyOrder.getParkId());
            
            // 组装停车记录VO列表
            List<ParkRecordVO> recordVOList = buildParkRecordVOList(berthOccupyOrder, berthIds, parkRecordIds, berthMap, parkName);
            
            log.info("getPayOrderList执行成功，返回记录数量：{}", recordVOList.size());
            return recordVOList;
            
        } catch (Exception e) {
            log.error("getPayOrderList执行异常，workOrderId={}：{}", workOrderId, e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 解析泊位ID列表
     */
    private List<Long> parseBerthIds(String berthIds) {
        if (StringUtils.isStrTrimNull(berthIds)) {
            return new ArrayList<>();
        }
        
        try {
            return Arrays.stream(berthIds.split(","))
                    .map(String::trim)
                    .filter(StringUtils::isNotStrTrimNull)
                    .map(berthId -> {
                        try {
                            return Long.parseLong(berthId);
                        } catch (NumberFormatException e) {
                            log.warn("泊位ID格式错误：{}", berthId);
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("解析泊位ID异常，berthIds={}：{}", berthIds, e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 解析停车记录ID列表
     */
    private List<Long> parseParkRecordIds(String parkRecordIds) {
        if (StringUtils.isStrTrimNull(parkRecordIds)) {
            return new ArrayList<>();
        }
        
        try {
            return Arrays.stream(parkRecordIds.split(","))
                    .map(String::trim)
                    .filter(StringUtils::isNotStrTrimNull)
                    .map(recordId -> {
                        try {
                            return Long.parseLong(recordId);
                        } catch (NumberFormatException e) {
                            log.warn("停车记录ID格式错误：{}", recordId);
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("解析停车记录ID异常，parkRecordIds={}：{}", parkRecordIds, e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 根据泊位ID列表获取泊位信息映射
     */
    private Map<Long, String> getBerthMapByIds(List<Long> berthIds) {
        try {
            if (CollectionUtils.isEmpty(berthIds)) {
                return new HashMap<>();
            }
            
            log.info("开始查询泊位信息，泊位ID数量：{}", berthIds.size());
            List<Berth> berths = berthFeignClient.byBerthIdList(berthIds);
            
            if (CollectionUtils.isEmpty(berths)) {
                log.warn("查询泊位信息返回空");
                return new HashMap<>();
            }
            
            Map<Long, String> berthMap = berths.stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(
                            Berth::getBerthId,
                            Berth::getBerthCode,
                            (existing, replacement) -> existing
                    ));
            
            log.info("泊位信息查询完成，数量：{}", berthMap.size());
            return berthMap;
            
        } catch (Exception e) {
            log.error("获取泊位信息异常：{}", e.getMessage(), e);
            return new HashMap<>();
        }
    }
    
    /**
     * 获取车场名称
     */
    private String getParkName(Long parkId) {
        try {
            if (parkId == null) {
                return "";
            }
            
            log.info("开始查询车场信息，parkId={}", parkId);
            ParkVO parkVOById = parkFeignClient.getParkVOById(parkId);
            
            if (parkVOById == null) {
                log.warn("查询车场信息返回空，parkId={}", parkId);
                return "";
            }
            
            String parkName = parkVOById.getParkName();
            log.info("车场信息查询完成，parkName={}", parkName);
            return parkName != null ? parkName : "";
            
        } catch (Exception e) {
            log.error("获取车场名称异常，parkId={}：{}", parkId, e.getMessage(), e);
            return "";
        }
    }
    
    /**
     * 构建停车记录VO列表
     */
    private List<ParkRecordVO> buildParkRecordVOList(BerthOccupyOrder berthOccupyOrder, 
                                                     List<Long> berthIds, 
                                                     List<Long> parkRecordIds, 
                                                     Map<Long, String> berthMap, 
                                                     String parkName) {
        List<ParkRecordVO> recordVOList = new ArrayList<>();
        
        for (int i = 0; i < berthIds.size(); i++) {
            try {
                Long berthId = berthIds.get(i);
                Long parkRecordId = parkRecordIds.get(i);
                
                ParkRecordVO parkRecordVO = new ParkRecordVO();
                parkRecordVO.setParkRecordId(parkRecordId);
                parkRecordVO.setBerthCode(berthMap.get(berthId));
                parkRecordVO.setParkName(parkName);
                parkRecordVO.setPlateNumber(berthOccupyOrder.getPlateNumber());
                parkRecordVO.setMobile(berthOccupyOrder.getPhone());
                
                // 设置入场时间
                if (berthOccupyOrder.getEntryTime() != null) {
                    parkRecordVO.setStrEntryTime(DateUtil.date2String(new Date(berthOccupyOrder.getEntryTime()),
                            DateUtil.PATTERN_STANDARD19H));
                }
                
                // 设置出场时间
                if (berthOccupyOrder.getExitTime() != null) {
                    parkRecordVO.setStrExitTime(DateUtil.date2String(new Date(berthOccupyOrder.getExitTime()),
                            DateUtil.PATTERN_STANDARD19H));
                }
                
                // 查询停车记录详情，获取应收、实收金额
                ParkRecordVO parkRecordDetail = getParkRecordDetail(parkRecordId.toString());
                if (parkRecordDetail != null) {
                    parkRecordVO.setShouldPay(parkRecordDetail.getShouldPay() != null ? parkRecordDetail.getShouldPay() : 0);
                    parkRecordVO.setActualPay(parkRecordDetail.getActualPay() != null ? parkRecordDetail.getActualPay() : 0);
                } else {
                    parkRecordVO.setShouldPay(0);
                    parkRecordVO.setActualPay(0);
                }
                
                recordVOList.add(parkRecordVO);
                
            } catch (Exception e) {
                log.error("构建单个停车记录VO异常，berthId={}, parkRecordId={}：{}", 
                        berthIds.get(i), parkRecordIds.get(i), e.getMessage(), e);
                // 继续处理其他记录，不中断整个流程
            }
        }
        
        return recordVOList;
    }
```

## 第一批优化总结

我已经完成了前5个方法的优化，主要改进包括：

### 1. **addEntryApply 方法优化**
- ✅ 增加参数校验（entryTime、phone、berthIds、parkId）
- ✅ 增加异常处理和详细日志
- ✅ 增加用户信息校验
- ✅ 增加approval返回值判断
- ✅ 增加数据库操作结果校验

### 2. **applyExit 方法优化**
- ✅ 增加参数校验（workOrderId、exitTime）
- ✅ 增加异常处理和详细日志
- ✅ 增加入场时间校验
- ✅ 增加数据库操作结果校验
- ✅ 增加approval返回值判断

### 3. **getPageList 方法优化**
- ✅ 增加分页参数校验
- ✅ 增加异常处理和详细日志
- ✅ 增加外部接口调用异常处理
- ✅ 增加richVo返回值判断
- ✅ 增加查询结果空值判断

### 4. **richVo 方法优化**
- ✅ 拆分为多个职责单一的私有方法
- ✅ 增加异常处理和详细日志
- ✅ 增加集合操作异常处理
- ✅ 增加外部接口调用异常处理
- ✅ 增加空值判断和容错处理

### 5. **getPayOrderList 方法优化**
- ✅ 增加参数校验
- ✅ 增加异常处理和详细日志
- ✅ 拆分为多个职责单一的私有方法
- ✅ 增加数据一致性校验
- ✅ 增加外部接口调用异常处理

### 主要改进点：

1. **异常处理**：每个方法都增加了try-catch，避免未处理异常
2. **参数校验**：对所有关键参数进行空值和有效性校验
3. **日志补全**：增加了入参、出参、关键步骤、异常的详细日志
4. **空值判断**：对所有可能为空的对象和集合进行判断
5. **方法拆分**：将复杂方法拆分为多个职责单一的私有方法
6. **容错处理**：增加了数据格式错误、外部接口失败等情况的处理

---

**接下来继续优化剩余的方法吗？** 我可以继续优化：
- getDetailById
- getRecordDetailById  
- entry
- exit
- 等其他方法

请告诉我是否继续，或者您希望先查看某个特定方法的优化。

---

**User**

继续

---

**Cursor**

好的，继续优化剩余的方法。接下来优化第6-10个方法：

## 第六批优化：getDetailById 方法


现在开始优化第6-10个方法：

## 第六批优化：getDetailById 方法

### 存在的问题：
1. **参数校验缺失**：workOrderId没有校验
2. **异常处理不完善**：外部接口调用没有try-catch
3. **日志不够详细**：缺少入参日志和关键步骤日志
4. **潜在NPE风险**：多个地方可能空指针
5. **JSON解析风险**：JSONArray.parseArray可能异常


```java
    @Override
    public BerthOccupyOrderVO getDetailById(long workOrderId) {
        log.info("getDetailById开始执行，入参：workOrderId={}", workOrderId);
        
        try {
            // 参数校验
            if (workOrderId <= 0) {
                log.warn("getDetailById参数校验失败：workOrderId无效，workOrderId={}", workOrderId);
                return null;
            }
            
            // 查询工单信息
            log.info("开始查询工单信息，workOrderId={}", workOrderId);
            BerthOccupyOrder berthOccupyOrder = berthOccupyOrderFeignClient.getWorkOrderById(workOrderId);
            if (berthOccupyOrder == null) {
                log.warn("未找到工单信息，workOrderId={}", workOrderId);
                return null;
            }
            
            log.info("查询到工单信息：{}", JSON.toJSONString(berthOccupyOrder));
            
            // 构建VO对象
            BerthOccupyOrderVO berthOccupyOrderVO = buildDetailVO(berthOccupyOrder);
            
            log.info("getDetailById执行成功，workOrderId={}", workOrderId);
            return berthOccupyOrderVO;
            
        } catch (Exception e) {
            log.error("getDetailById执行异常，workOrderId={}：{}", workOrderId, e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 构建详情VO对象
     */
    private BerthOccupyOrderVO buildDetailVO(BerthOccupyOrder berthOccupyOrder) {
        BerthOccupyOrderVO berthOccupyOrderVO = new BerthOccupyOrderVO();
        BeanUtils.copyProperties(berthOccupyOrder, berthOccupyOrderVO);
        
        // 停车时长
        berthOccupyOrderVO.setOccupyTime(getParkTime(berthOccupyOrder));
        
        // 入场时间
        if (berthOccupyOrder.getEntryTime() != null) {
            berthOccupyOrderVO.setEntryTimeStr(DateUtil.date2String(new Date(berthOccupyOrder.getEntryTime()),
                    DateUtil.PATTERN_STANDARD19H));
        }
        
        // 出场时间
        if (berthOccupyOrder.getExitTime() != null) {
            berthOccupyOrderVO.setExitTimeStr(DateUtil.date2String(new Date(berthOccupyOrder.getExitTime()),
                    DateUtil.PATTERN_STANDARD19H));
        }
        
        // 文件列表处理
        processFileList(berthOccupyOrder, berthOccupyOrderVO);
        
        // 计算应收、实收金额
        calculatePaymentAmount(berthOccupyOrderVO);
        
        return berthOccupyOrderVO;
    }
    
    /**
     * 处理文件列表
     */
    private void processFileList(BerthOccupyOrder berthOccupyOrder, BerthOccupyOrderVO berthOccupyOrderVO) {
        try {
            // 处理图片列表
            if (StringUtils.isNotNull(berthOccupyOrder.getPicList())) {
                String picList = berthOccupyOrder.getPicList();
                List<BerthOccupyFile> picListEntity = JSONArray.parseArray(picList, BerthOccupyFile.class);
                berthOccupyOrderVO.setPicListEntity(picListEntity);
                log.debug("解析图片列表成功，数量：{}", picListEntity != null ? picListEntity.size() : 0);
            }
            
            // 处理文件列表
            if (StringUtils.isNotNull(berthOccupyOrder.getFileList())) {
                String fileList = berthOccupyOrder.getFileList();
                List<BerthOccupyFile> fileListEntity = JSONArray.parseArray(fileList, BerthOccupyFile.class);
                berthOccupyOrderVO.setFileListEntity(fileListEntity);
                log.debug("解析文件列表成功，数量：{}", fileListEntity != null ? fileListEntity.size() : 0);
            }
            
        } catch (Exception e) {
            log.error("解析文件列表异常，workOrderId={}：{}", berthOccupyOrder.getWorkOrderId(), e.getMessage(), e);
            // 不中断流程，继续处理
        }
    }
    
    /**
     * 计算应收、实收金额
     */
    private void calculatePaymentAmount(BerthOccupyOrderVO berthOccupyOrderVO) {
        try {
            // 应收、实收直接同步停车记录中的数据
            List<ParkRecordVO> records = Optional.ofNullable(berthOccupyOrderVO.getParkRecordIds())
                    .filter(StringUtils::isNotStrTrimNull)
                    .map(ids -> Arrays.stream(ids.split(",")))
                    .map(stream -> stream
                            .map(this::getParkRecordDetail)
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList()))
                    .orElse(Collections.emptyList());
            
            int shouldPay = records.stream()
                    .mapToInt(r -> r.getShouldPay() != null ? r.getShouldPay() : 0)
                    .sum();
            
            int actualPay = records.stream()
                    .mapToInt(r -> r.getActualPay() != null ? r.getActualPay() : 0)
                    .sum();
            
            berthOccupyOrderVO.setShouldPay(shouldPay);
            berthOccupyOrderVO.setActualPay(actualPay);
            
            log.debug("计算应收实收金额完成，shouldPay={}, actualPay={}", shouldPay, actualPay);
            
        } catch (Exception e) {
            log.error("计算应收实收金额异常：{}", e.getMessage(), e);
            // 设置默认值
            berthOccupyOrderVO.setShouldPay(0);
            berthOccupyOrderVO.setActualPay(0);
        }
    }
```

## 第七批优化：getRecordDetailById 方法

### 存在的问题：
1. **参数校验缺失**：recordId没有校验
2. **异常处理不完善**：外部接口调用没有try-catch
3. **日志不够详细**：缺少入参日志和关键步骤日志
4. **潜在NPE风险**：多个地方可能空指针
5. **代码重复**：与getDetailById有重复逻辑


```java
    @Override
    public BerthOccupyOrderVO getRecordDetailById(long recordId) {
        log.info("getRecordDetailById开始执行，入参：recordId={}", recordId);
        
        try {
            // 参数校验
            if (recordId <= 0) {
                log.warn("getRecordDetailById参数校验失败：recordId无效，recordId={}", recordId);
                return null;
            }
            
            // 查询操作记录
            log.info("开始查询操作记录，recordId={}", recordId);
            BerthOccupyApprovalRecord approvalRecord = berthOccupyOrderFeignClient.getApprovalRecordById(recordId);
            if (approvalRecord == null) {
                log.warn("未找到操作记录，recordId={}", recordId);
                return null;
            }
            
            log.info("查询到操作记录：{}", JSON.toJSONString(approvalRecord));
            
            // 查询对应工单信息
            Long workOrderId = approvalRecord.getWorkOrderId();
            if (workOrderId == null || workOrderId <= 0) {
                log.error("操作记录中的工单ID无效，recordId={}, workOrderId={}", recordId, workOrderId);
                return null;
            }
            
            log.info("开始查询工单信息，workOrderId={}", workOrderId);
            BerthOccupyOrder berthOccupyOrder = berthOccupyOrderFeignClient.getWorkOrderById(workOrderId);
            if (berthOccupyOrder == null) {
                log.warn("未找到工单信息，workOrderId={}", workOrderId);
                return null;
            }
            
            log.info("查询到工单信息：{}", JSON.toJSONString(berthOccupyOrder));
            
            // 构建基础VO对象（复用getDetailById的逻辑）
            BerthOccupyOrderVO berthOccupyOrderVO = buildDetailVO(berthOccupyOrder);
            
            // 补充操作记录相关信息
            enrichApprovalRecordInfo(berthOccupyOrderVO, approvalRecord);
            
            log.info("getRecordDetailById执行成功，recordId={}, workOrderId={}", recordId, workOrderId);
            return berthOccupyOrderVO;
            
        } catch (Exception e) {
            log.error("getRecordDetailById执行异常，recordId={}：{}", recordId, e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 补充操作记录相关信息
     */
    private void enrichApprovalRecordInfo(BerthOccupyOrderVO berthOccupyOrderVO, BerthOccupyApprovalRecord approvalRecord) {
        try {
            // 获取操作人信息
            List<Long> userIds = new ArrayList<>(1);
            userIds.add(approvalRecord.getUserId());
            Map<Long, String> userInfoMap = getUserInfoMap(userIds);
            
            // 设置操作记录相关信息
            berthOccupyOrderVO.setRecordId(approvalRecord.getRecordId());
            berthOccupyOrderVO.setOperatorName(userInfoMap.get(approvalRecord.getUserId()));
            berthOccupyOrderVO.setOption(approvalRecord.getOptionType());
            
            // 设置下一操作类型
            BerthOccupyOptions nextOption = BerthOccupyOptions.getNextEnum(approvalRecord.getOptionType());
            berthOccupyOrderVO.setNextOption(nextOption == null ? 0 : nextOption.getCode());
            
            // 设置审核状态
            berthOccupyOrderVO.setTargetState(approvalRecord.getTargetState());
            
            // 设置操作时间
            if (approvalRecord.getCreatedTime() != null) {
                berthOccupyOrderVO.setOptionTime(DateUtil.date2String(approvalRecord.getCreatedTime(), DateUtil.PATTERN_STANDARD19H));
            }
            
            // 设置驳回理由
            berthOccupyOrderVO.setRejectReason(approvalRecord.getRejectReason());
            
            log.debug("补充操作记录信息完成，recordId={}, operatorName={}", 
                    approvalRecord.getRecordId(), userInfoMap.get(approvalRecord.getUserId()));
            
        } catch (Exception e) {
            log.error("补充操作记录信息异常，recordId={}：{}", approvalRecord.getRecordId(), e.getMessage(), e);
            // 不中断流程，继续处理
        }
    }
```

## 第八批优化：entry 方法

### 存在的问题：
1. **参数校验缺失**：berthOccupyOrder没有校验
2. **异常处理不完善**：多个外部接口调用没有try-catch
3. **日志不够详细**：缺少关键步骤日志
4. **潜在NPE风险**：多个地方可能空指针
5. **方法职责过重**：一个方法做了太多事情


```java
    private void entry(BerthOccupyOrder berthOccupyOrder) {
        log.info("entry开始执行，工单信息：{}", JSON.toJSONString(berthOccupyOrder));
        
        try {
            // 参数校验
            if (berthOccupyOrder == null) {
                log.error("entry参数校验失败：berthOccupyOrder为空");
                return;
            }
            if (StringUtils.isStrTrimNull(berthOccupyOrder.getBerthIds())) {
                log.error("entry参数校验失败：berthIds为空，workOrderId={}", berthOccupyOrder.getWorkOrderId());
                return;
            }
            if (berthOccupyOrder.getParkId() == null) {
                log.error("entry参数校验失败：parkId为空，workOrderId={}", berthOccupyOrder.getWorkOrderId());
                return;
            }
            
            // 解析泊位ID
            List<Long> berthIds = parseBerthIdsForEntry(berthOccupyOrder.getBerthIds());
            if (CollectionUtils.isEmpty(berthIds)) {
                log.error("解析泊位ID失败，berthIds={}", berthOccupyOrder.getBerthIds());
                return;
            }
            
            // 获取泊位信息
            Map<Long, String> berthMap = getBerthMapForEntry(berthIds);
            if (berthMap.isEmpty()) {
                log.error("获取泊位信息失败，berthIds={}", berthIds);
                return;
            }
            
            // 获取车场信息
            ParkVO parkVO = getParkVOForEntry(berthOccupyOrder.getParkId());
            if (parkVO == null) {
                log.error("获取车场信息失败，parkId={}", berthOccupyOrder.getParkId());
                return;
            }
            
            // 获取随机车牌
            Car newPlate = getNewPlate();
            if (newPlate == null) {
                log.error("获取随机车牌失败");
                return;
            }
            log.info("获取随机车牌成功：{}", objectMapper.writeValueAsString(newPlate));
            
            // 创建停车记录
            List<Long> parkRecordIds = createParkRecords(berthOccupyOrder, berthIds, berthMap, parkVO, newPlate);
            if (CollectionUtils.isEmpty(parkRecordIds)) {
                log.error("创建停车记录失败，workOrderId={}", berthOccupyOrder.getWorkOrderId());
                return;
            }
            
            // 更新工单状态
            updateOrderAfterEntry(berthOccupyOrder, parkRecordIds, newPlate);
            
            // 发送入场通知
            sendEntryNotification(berthOccupyOrder, parkVO, newPlate);
            
            log.info("entry执行成功，workOrderId={}", berthOccupyOrder.getWorkOrderId());
            
        } catch (Exception e) {
            log.error("entry执行异常，workOrderId={}：{}", 
                    berthOccupyOrder != null ? berthOccupyOrder.getWorkOrderId() : "null", e.getMessage(), e);
        }
    }
    
    /**
     * 解析泊位ID（用于入场）
     */
    private List<Long> parseBerthIdsForEntry(String berthIds) {
        try {
            String[] berthIdStr = berthIds.split(",");
            return Arrays.stream(berthIdStr)
                    .map(String::trim)
                    .filter(StringUtils::isNotStrTrimNull)
                    .map(berthId -> {
                        try {
                            return Long.parseLong(berthId);
                        } catch (NumberFormatException e) {
                            log.warn("泊位ID格式错误：{}", berthId);
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("解析泊位ID异常，berthIds={}：{}", berthIds, e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 获取泊位信息（用于入场）
     */
    private Map<Long, String> getBerthMapForEntry(List<Long> berthIds) {
        try {
            log.info("开始查询泊位信息，泊位ID数量：{}", berthIds.size());
            List<Berth> berths = berthFeignClient.byBerthIdList(berthIds);
            
            if (CollectionUtils.isEmpty(berths)) {
                log.warn("查询泊位信息返回空");
                return new HashMap<>();
            }
            
            Map<Long, String> berthMap = berths.stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(
                            Berth::getBerthId,
                            Berth::getBerthCode,
                            (existing, replacement) -> existing
                    ));
            
            log.info("泊位信息查询完成，数量：{}", berthMap.size());
            return berthMap;
            
        } catch (Exception e) {
            log.error("获取泊位信息异常：{}", e.getMessage(), e);
            return new HashMap<>();
        }
    }
    
    /**
     * 获取车场信息（用于入场）
     */
    private ParkVO getParkVOForEntry(Long parkId) {
        try {
            log.info("开始查询车场信息，parkId={}", parkId);
            ParkVO parkVO = parkFeignClient.getParkVOById(parkId);
            
            if (parkVO == null) {
                log.warn("查询车场信息返回空，parkId={}", parkId);
                return null;
            }
            
            log.info("车场信息查询完成，parkCode={}", parkVO.getParkCode());
            return parkVO;
            
        } catch (Exception e) {
            log.error("获取车场信息异常，parkId={}：{}", parkId, e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 创建停车记录
     */
    private List<Long> createParkRecords(BerthOccupyOrder berthOccupyOrder, List<Long> berthIds, 
                                        Map<Long, String> berthMap, ParkVO parkVO, Car newPlate) {
        List<Long> parkRecordIds = new ArrayList<>();
        
        for (Long berthId : berthIds) {
            try {
                ParkRecord record = buildParkRecord(berthOccupyOrder, berthId, berthMap, parkVO, newPlate);
                if (record != null) {
                    long parkRecordId = record.getParkRecordId();
                    parkRecordIds.add(parkRecordId);
                    log.info("创建停车记录成功，parkRecordId={}, berthId={}", parkRecordId, berthId);
                }
            } catch (Exception e) {
                log.error("创建停车记录异常，berthId={}：{}", berthId, e.getMessage(), e);
                // 继续处理其他泊位，不中断整个流程
            }
        }
        
        return parkRecordIds;
    }
    
    /**
     * 构建停车记录
     */
    private ParkRecord buildParkRecord(BerthOccupyOrder berthOccupyOrder, Long berthId, 
                                      Map<Long, String> berthMap, ParkVO parkVO, Car newPlate) {
        try {
            ParkRecord record = new ParkRecord();
            long parkRecordId = IdentifyUtils.getId();
            
            record.setParkRecordId(parkRecordId);
            record.setBerthId(berthId);
            record.setBerthCode(berthMap.get(berthId));
            record.setParkCode(parkVO.getParkCode());
            record.setParkId(parkVO.getParkId());
            record.setCarId(newPlate.getCarId());
            record.setPlateNumber(newPlate.getPlateNumber());
            record.setEntryTime(berthOccupyOrder.getEntryTime());
            record.setRecordCode(UUID.randomUUID().toString().replaceAll("-", ""));
            
            // 上传业务图片，获取流水号
            String oprNum = uploadBusinessPic(parkVO.getParkCode(), berthMap.get(berthId), berthOccupyOrder.getEntryTime());
            record.setEntryOprNum(oprNum);
            
            // 创建流水
            record.setEntryId(IdentifyUtils.getId());
            record.setEntryDataSource(DataSource.MANUAL_ENTER.code());
            
            // 创建入场OCR记录
            createEntryOcrRecord(record);
            
            // 保存停车记录
            microRecordFeignClient.onlyEntry(record);
            
            return record;
            
        } catch (Exception e) {
            log.error("构建停车记录异常，berthId={}：{}", berthId, e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 更新工单状态（入场后）
     */
    private void updateOrderAfterEntry(BerthOccupyOrder berthOccupyOrder, List<Long> parkRecordIds, Car newPlate) {
        try {
            log.info("开始更新工单状态，workOrderId={}", berthOccupyOrder.getWorkOrderId());
            
            BerthOccupyOrder berthOccupyOrderUpdate = new BerthOccupyOrder();
            berthOccupyOrderUpdate.setWorkOrderId(berthOccupyOrder.getWorkOrderId());
            berthOccupyOrderUpdate.setRecordState(BerthOccupyRecordState.IN_PRESENCE.getCode());
            berthOccupyOrderUpdate.setParkRecordIds(Joiner.on(",").join(parkRecordIds));
            berthOccupyOrderUpdate.setPlateNumber(newPlate.getPlateNumber());
            berthOccupyOrderUpdate.setCarId(newPlate.getCarId());
            
            int updateResult = berthOccupyOrderFeignClient.updateOrder(berthOccupyOrderUpdate);
            log.info("更新工单状态结果，影响行数：{}", updateResult);
            
            if (updateResult != 1) {
                log.error("更新工单状态失败，预期影响行数：1，实际影响行数：{}", updateResult);
            }
            
        } catch (Exception e) {
            log.error("更新工单状态异常，workOrderId={}：{}", berthOccupyOrder.getWorkOrderId(), e.getMessage(), e);
        }
    }
    
    /**
     * 发送入场通知
     */
    private void sendEntryNotification(BerthOccupyOrder berthOccupyOrder, ParkVO parkVO, Car newPlate) {
        try {
            log.info("开始发送入场通知，workOrderId={}", berthOccupyOrder.getWorkOrderId());
            
            String uniKey = UUID.randomUUID().toString();
            String caller = "mirco-acb";
            
            // 短信动态字段参数
            Map<String, String> params = new HashMap<>(3);
            params.put("parkName", StringUtils.isNotStrTrimNull(parkVO.getParentParkName()) ?
                    parkVO.getParentParkName() : parkVO.getParkName());
            params.put("entryTime", DateUtil.date2String(new Date(berthOccupyOrder.getEntryTime()),
                    DateUtil.PATTERN_STANDARD19H));
            params.put("plateNumber", newPlate.getPlateNumber());
            
            SmsModel smsModel = new SmsModel();
            smsModel.setPhoneNumber(berthOccupyOrder.getPhone());
            smsModel.setContent(TemplateParseUtils.parseTemplate(NoticeTmpl.BERTH_OCCUPY_ENTRY_SMS.getContent(), params));
            smsModel.setTmplCode(NoticeTmpl.BERTH_OCCUPY_ENTRY_SMS.getCode());
            smsModel.setUniKey(uniKey);
            smsModel.setCaller(caller);
            smsModel.setOperatorId(berthOccupyOrder.getUserId());
            
            messageFeignClient.sms(smsModel);
            log.info("入场通知发送成功，workOrderId={}", berthOccupyOrder.getWorkOrderId());
            
        } catch (Exception e) {
            log.error("发送入场通知异常，workOrderId={}：{}", berthOccupyOrder.getWorkOrderId(), e.getMessage(), e);
        }
    }
```

让我重新尝试优化entry方法：


现在优化entry方法：


```java
    private void entry(BerthOccupyOrder berthOccupyOrder) {
        log.info("entry开始执行，工单信息：{}", JSON.toJSONString(berthOccupyOrder));
        
        try {
            // 参数校验
            if (berthOccupyOrder == null) {
                log.error("entry参数校验失败：berthOccupyOrder为空");
                return;
            }
            if (StringUtils.isStrTrimNull(berthOccupyOrder.getBerthIds())) {
                log.error("entry参数校验失败：berthIds为空，workOrderId={}", berthOccupyOrder.getWorkOrderId());
                return;
            }
            if (berthOccupyOrder.getParkId() == null) {
                log.error("entry参数校验失败：parkId为空，workOrderId={}", berthOccupyOrder.getWorkOrderId());
                return;
            }
            
            // 解析泊位ID
            List<Long> berthIds = parseBerthIdsForEntry(berthOccupyOrder.getBerthIds());
            if (CollectionUtils.isEmpty(berthIds)) {
                log.error("解析泊位ID失败，berthIds={}", berthOccupyOrder.getBerthIds());
                return;
            }
            
            // 获取泊位信息
            Map<Long, String> berthMap = getBerthMapForEntry(berthIds);
            if (berthMap.isEmpty()) {
                log.error("获取泊位信息失败，berthIds={}", berthIds);
                return;
            }
            
            // 获取车场信息
            ParkVO parkVO = getParkVOForEntry(berthOccupyOrder.getParkId());
            if (parkVO == null) {
                log.error("获取车场信息失败，parkId={}", berthOccupyOrder.getParkId());
                return;
            }
            
            // 获取随机车牌
            Car newPlate = getNewPlate();
            if (newPlate == null) {
                log.error("获取随机车牌失败");
                return;
            }
            log.info("获取随机车牌成功：{}", objectMapper.writeValueAsString(newPlate));
            
            // 创建停车记录
            List<Long> parkRecordIds = createParkRecords(berthOccupyOrder, berthIds, berthMap, parkVO, newPlate);
            if (CollectionUtils.isEmpty(parkRecordIds)) {
                log.error("创建停车记录失败，workOrderId={}", berthOccupyOrder.getWorkOrderId());
                return;
            }
            
            // 更新工单状态
            updateOrderAfterEntry(berthOccupyOrder, parkRecordIds, newPlate);
            
            // 发送入场通知
            sendEntryNotification(berthOccupyOrder, parkVO, newPlate);
            
            log.info("entry执行成功，workOrderId={}", berthOccupyOrder.getWorkOrderId());
            
        } catch (Exception e) {
            log.error("entry执行异常，workOrderId={}：{}", 
                    berthOccupyOrder != null ? berthOccupyOrder.getWorkOrderId() : "null", e.getMessage(), e);
        }
    }
    
    /**
     * 解析泊位ID（用于入场）
     */
    private List<Long> parseBerthIdsForEntry(String berthIds) {
        try {
            String[] berthIdStr = berthIds.split(",");
            return Arrays.stream(berthIdStr)
                    .map(String::trim)
                    .filter(StringUtils::isNotStrTrimNull)
                    .map(berthId -> {
                        try {
                            return Long.parseLong(berthId);
                        } catch (NumberFormatException e) {
                            log.warn("泊位ID格式错误：{}", berthId);
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
        } catch (Exception e) {
            log.error("解析泊位ID异常，berthIds={}：{}", berthIds, e.getMessage(), e);
            return new ArrayList<>();
        }
    }
    
    /**
     * 获取泊位信息（用于入场）
     */
    private Map<Long, String> getBerthMapForEntry(List<Long> berthIds) {
        try {
            log.info("开始查询泊位信息，泊位ID数量：{}", berthIds.size());
            List<Berth> berths = berthFeignClient.byBerthIdList(berthIds);
            
            if (CollectionUtils.isEmpty(berths)) {
                log.warn("查询泊位信息返回空");
                return new HashMap<>();
            }
            
            Map<Long, String> berthMap = berths.stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(
                            Berth::getBerthId,
                            Berth::getBerthCode,
                            (existing, replacement) -> existing
                    ));
            
            log.info("泊位信息查询完成，数量：{}", berthMap.size());
            return berthMap;
            
        } catch (Exception e) {
            log.error("获取泊位信息异常：{}", e.getMessage(), e);
            return new HashMap<>();
        }
    }
    
    /**
     * 获取车场信息（用于入场）
     */
    private ParkVO getParkVOForEntry(Long parkId) {
        try {
            log.info("开始查询车场信息，parkId={}", parkId);
            ParkVO parkVO = parkFeignClient.getParkVOById(parkId);
            
            if (parkVO == null) {
                log.warn("查询车场信息返回空，parkId={}", parkId);
                return null;
            }
            
            log.info("车场信息查询完成，parkCode={}", parkVO.getParkCode());
            return parkVO;
            
        } catch (Exception e) {
            log.error("获取车场信息异常，parkId={}：{}", parkId, e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 创建停车记录
     */
    private List<Long> createParkRecords(BerthOccupyOrder berthOccupyOrder, List<Long> berthIds, 
                                        Map<Long, String> berthMap, ParkVO parkVO, Car newPlate) {
        List<Long> parkRecordIds = new ArrayList<>();
        
        for (Long berthId : berthIds) {
            try {
                ParkRecord record = buildParkRecord(berthOccupyOrder, berthId, berthMap, parkVO, newPlate);
                if (record != null) {
                    long parkRecordId = record.getParkRecordId();
                    parkRecordIds.add(parkRecordId);
                    log.info("创建停车记录成功，parkRecordId={}, berthId={}", parkRecordId, berthId);
                }
            } catch (Exception e) {
                log.error("创建停车记录异常，berthId={}：{}", berthId, e.getMessage(), e);
                // 继续处理其他泊位，不中断整个流程
            }
        }
        
        return parkRecordIds;
    }
    
    /**
     * 构建停车记录
     */
    private ParkRecord buildParkRecord(BerthOccupyOrder berthOccupyOrder, Long berthId, 
                                      Map<Long, String> berthMap, ParkVO parkVO, Car newPlate) {
        try {
            ParkRecord record = new ParkRecord();
            long parkRecordId = IdentifyUtils.getId();
            
            record.setParkRecordId(parkRecordId);
            record.setBerthId(berthId);
            record.setBerthCode(berthMap.get(berthId));
            record.setParkCode(parkVO.getParkCode());
            record.setParkId(parkVO.getParkId());
            record.setCarId(newPlate.getCarId());
            record.setPlateNumber(newPlate.getPlateNumber());
            record.setEntryTime(berthOccupyOrder.getEntryTime());
            record.setRecordCode(UUID.randomUUID().toString().replaceAll("-", ""));
            
            // 上传业务图片，获取流水号
            String oprNum = uploadBusinessPic(parkVO.getParkCode(), berthMap.get(berthId), berthOccupyOrder.getEntryTime());
            record.setEntryOprNum(oprNum);
            
            // 创建流水
            record.setEntryId(IdentifyUtils.getId());
            record.setEntryDataSource(DataSource.MANUAL_ENTER.code());
            
            // 创建入场OCR记录
            createEntryOcrRecord(record);
            
            // 保存停车记录
            microRecordFeignClient.onlyEntry(record);
            
            return record;
            
        } catch (Exception e) {
            log.error("构建停车记录异常，berthId={}：{}", berthId, e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 更新工单状态（入场后）
     */
    private void updateOrderAfterEntry(BerthOccupyOrder berthOccupyOrder, List<Long> parkRecordIds, Car newPlate) {
        try {
            log.info("开始更新工单状态，workOrderId={}", berthOccupyOrder.getWorkOrderId());
            
            BerthOccupyOrder berthOccupyOrderUpdate = new BerthOccupyOrder();
            berthOccupyOrderUpdate.setWorkOrderId(berthOccupyOrder.getWorkOrderId());
            berthOccupyOrderUpdate.setRecordState(BerthOccupyRecordState.IN_PRESENCE.getCode());
            berthOccupyOrderUpdate.setParkRecordIds(Joiner.on(",").join(parkRecordIds));
            berthOccupyOrderUpdate.setPlateNumber(newPlate.getPlateNumber());
            berthOccupyOrderUpdate.setCarId(newPlate.getCarId());
            
            int updateResult = berthOccupyOrderFeignClient.updateOrder(berthOccupyOrderUpdate);
            log.info("更新工单状态结果，影响行数：{}", updateResult);
            
            if (updateResult != 1) {
                log.error("更新工单状态失败，预期影响行数：1，实际影响行数：{}", updateResult);
            }
            
        } catch (Exception e) {
            log.error("更新工单状态异常，workOrderId={}：{}", berthOccupyOrder.getWorkOrderId(), e.getMessage(), e);
        }
    }
    
    /**
     * 发送入场通知
     */
    private void sendEntryNotification(BerthOccupyOrder berthOccupyOrder, ParkVO parkVO, Car newPlate) {
        try {
            log.info("开始发送入场通知，workOrderId={}", berthOccupyOrder.getWorkOrderId());
            
            String uniKey = UUID.randomUUID().toString();
            String caller = "mirco-acb";
            
            // 短信动态字段参数
            Map<String, String> params = new HashMap<>(3);
            params.put("parkName", StringUtils.isNotStrTrimNull(parkVO.getParentParkName()) ?
                    parkVO.getParentParkName() : parkVO.getParkName());
            params.put("entryTime", DateUtil.date2String(new Date(berthOccupyOrder.getEntryTime()),
                    DateUtil.PATTERN_STANDARD19H));
            params.put("plateNumber", newPlate.getPlateNumber());
            
            SmsModel smsModel = new SmsModel();
            smsModel.setPhoneNumber(berthOccupyOrder.getPhone());
            smsModel.setContent(TemplateParseUtils.parseTemplate(NoticeTmpl.BERTH_OCCUPY_ENTRY_SMS.getContent(), params));
            smsModel.setTmplCode(NoticeTmpl.BERTH_OCCUPY_ENTRY_SMS.getCode());
            smsModel.setUniKey(uniKey);
            smsModel.setCaller(caller);
            smsModel.setOperatorId(berthOccupyOrder.getUserId());
            
            messageFeignClient.sms(smsModel);
            log.info("入场通知发送成功，workOrderId={}", berthOccupyOrder.getWorkOrderId());
            
        } catch (Exception e) {
            log.error("发送入场通知异常，workOrderId={}：{}", berthOccupyOrder.getWorkOrderId(), e.getMessage(), e);
        }
    }
```


已完成第6-8批方法的优化，主要内容如下：

---

### 6. getDetailById 方法
- 增加参数校验、异常捕获、详细日志，所有外部接口和JSON解析都加try-catch，避免NPE和格式异常。
- 复杂逻辑（如文件列表处理、金额计算）拆分为私有方法，提升可读性和可维护性。

### 7. getRecordDetailById 方法
- 增加参数校验、异常捕获、详细日志，所有外部接口调用都加try-catch。
- 复用getDetailById的VO组装逻辑，避免重复代码。
- 操作记录相关信息单独封装为私有方法，便于维护。

### 8. entry 方法
- 增加参数校验、异常捕获、详细日志。
- 复杂流程（如泊位ID解析、泊位/车场信息获取、停车记录创建、工单状态更新、通知发送）全部拆分为私有方法，主流程清晰明了。
- 所有外部接口和数据转换都加try-catch，避免NPE和格式异常。

---



