package com.xiaopeng.vehicleConvoy.service.impl;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.dto.account.XpOperationsUserQueryDTO;
import com.xiaopeng.api.feignClient.account.XpOperationUserClient;
import com.xiaopeng.api.feignClient.maintenance.XpCheckLocationClient;
import com.xiaopeng.api.feignClient.operation.XpElectronicClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.account.SysRole;
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.model.maintenance.XpCheckLocation;
import com.xiaopeng.api.model.operation.XpElectronicFence;
import com.xiaopeng.api.model.vehicleConvoy.XpFleet;
import com.xiaopeng.api.model.vehicleConvoy.XpFleetOperations;
import com.xiaopeng.api.model.vehicleConvoy.XpFleetVehicle;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.account.XpOperationsUserWithRoleVO;
import com.xiaopeng.api.vo.operation.ElectronicFenceDetailVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.vehicleConvoy.constant.I18nKeyConstant;
import com.xiaopeng.vehicleConvoy.mapper.XpFleetMapper;
import com.xiaopeng.vehicleConvoy.model.dto.FleetAddDTO;
import com.xiaopeng.vehicleConvoy.model.dto.FleetEditDTO;
import com.xiaopeng.vehicleConvoy.model.query.FleetPageQuery;
import com.xiaopeng.vehicleConvoy.model.query.FleetUserPageQuery;
import com.xiaopeng.vehicleConvoy.model.query.FleetVehiclePageQuery;
import com.xiaopeng.vehicleConvoy.model.vo.FleetDetailVO;
import com.xiaopeng.vehicleConvoy.model.vo.FleetPageVO;
import com.xiaopeng.vehicleConvoy.model.vo.FleetUserVO;
import com.xiaopeng.vehicleConvoy.model.vo.FleetVehicleVO;
import com.xiaopeng.vehicleConvoy.service.IXpFleetOperationsService;
import com.xiaopeng.vehicleConvoy.service.IXpFleetService;
import com.xiaopeng.vehicleConvoy.service.IXpFleetVehicleService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
*
* 车队管理 服务实现类
*
*
* @author mitao
* @since 2026-02-03
*/
@Service
@RequiredArgsConstructor(onConstructor_ = @Lazy)
public class XpFleetServiceImpl extends ServiceImpl implements IXpFleetService {
private final IXpFleetOperationsService xpFleetOperationsService;
private final IXpFleetVehicleService xpFleetVehicleService;
private final XpOperationUserClient xpOperationUserClient;
private final XpVehicleClient xpVehicleClient;
private final XpElectronicClient xpElectronicClient;
private final XpCheckLocationClient xpCheckLocationClient;
@Override
public List listByIds(List ids) {
if (CollectionUtils.isEmpty(ids)) {
return new ArrayList<>();
}
return super.listByIds(ids);
}
@Override
@Transactional
@ShardingSphereTransactionType(TransactionType.BASE)
public R add(FleetAddDTO dto) {
// 1. 校验车队名称不能重复
long count = this.count(new LambdaQueryWrapper()
.eq(XpFleet::getFleetName, dto.getFleetName()));
if (count > 0) {
throw new ServiceException("车队名称已存在");
}
// 2. 校验运维人员绑定
validateUserBinding(dto.getOperationsUserIds(), null);
// 3. 处理车辆绑定(自动解绑已绑定的车辆)
handleVehicleBinding(dto.getVehicleIds(), null);
// 4. 插入车队主表记录
XpFleet fleet = new XpFleet();
fleet.setFleetName(dto.getFleetName());
fleet.setOperationsUserId(dto.getOperationsUserId());
fleet.setLocationId(dto.getLocationId());
this.save(fleet);
// 5. 批量插入车队-人员关联表
List operationsList = dto.getOperationsUserIds().stream()
.map(userId -> {
XpFleetOperations operations = new XpFleetOperations();
operations.setFleetId(fleet.getId());
operations.setOperationsUserId(userId);
return operations;
}).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(operationsList)) {
xpFleetOperationsService.saveBatch(operationsList);
}
// 6. 批量插入车队-车辆关联表
List vehicleList = dto.getVehicleIds().stream()
.map(vehicleId -> {
XpFleetVehicle fleetVehicle = new XpFleetVehicle();
fleetVehicle.setFleetId(fleet.getId());
fleetVehicle.setVehicleId(vehicleId);
return fleetVehicle;
}).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(vehicleList)) {
xpFleetVehicleService.saveBatch(vehicleList);
//推送车辆和区域的绑定关系个车端
}
return R.ok();
}
@Override
public R edit(FleetEditDTO dto) {
// 1. 查询车队是否存在
XpFleet fleet = this.getById(dto.getId());
if (fleet == null) {
throw new ServiceException("车队不存在");
}
// 2. 校验车队名称不能与其他车队重复
long count = this.count(new LambdaQueryWrapper()
.eq(XpFleet::getFleetName, dto.getFleetName())
.ne(XpFleet::getId, dto.getId()));
if (count > 0) {
throw new ServiceException("车队名称已存在");
}
// 3. 校验负责人绑定(如果修改了负责人)
if (!dto.getOperationsUserId().equals(fleet.getOperationsUserId())) {
List userIds = new ArrayList<>();
userIds.add(dto.getOperationsUserId());
validateUserBinding(userIds, dto.getId());
}
// 4. 更新车队主表记录
fleet.setFleetName(dto.getFleetName());
fleet.setOperationsUserId(dto.getOperationsUserId());
fleet.setLocationId(dto.getLocationId());
this.updateById(fleet);
return R.ok();
}
/**
* 校验人员绑定
*
* @param userIds 人员ID列表
* @param excludeFleetId 排除的车队ID(编辑时使用)
*/
private void validateUserBinding(List userIds, Long excludeFleetId) {
if (CollectionUtils.isEmpty(userIds)) {
return;
}
for (Long userId : userIds) {
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.eq(XpFleetOperations::getOperationsUserId, userId);
if (excludeFleetId != null) {
wrapper.ne(XpFleetOperations::getFleetId, excludeFleetId);
}
wrapper.last("limit 1");
XpFleetOperations operations = xpFleetOperationsService.getOne(wrapper);
if (operations != null) {
// 查询人员姓名和车队名称
R userResult = xpOperationUserClient.queryById(userId);
XpFleet fleet = this.getById(operations.getFleetId());
String userName = userResult.getData() != null ? userResult.getData().getNickName() : "未知";
String fleetName = fleet != null ? fleet.getFleetName() : "未知";
List