package com.xiaopeng.account.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.PhoneUtil; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.account.constant.I18nKeyConstant; import com.xiaopeng.account.mapper.SysRoleMapper; import com.xiaopeng.account.mapper.XpOperationsRoleMapper; import com.xiaopeng.account.mapper.XpOperationsUserMapper; import com.xiaopeng.account.model.dto.EnableDisableDTO; import com.xiaopeng.account.model.dto.RePasswordDTO; import com.xiaopeng.account.model.dto.XpOperationsUserAddDTO; import com.xiaopeng.account.model.dto.XpOperationsUserDTO; import com.xiaopeng.account.model.query.XpOperationsUserPageQuery; import com.xiaopeng.account.model.query.XpOperationsUserQuery; import com.xiaopeng.account.service.*; import com.xiaopeng.account.util.AliOssDownloadUtil; import com.xiaopeng.api.dto.account.XpOperationsUserQueryDTO; import com.xiaopeng.api.feignClient.maintenance.XpClockInClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetOperationsClient; import com.xiaopeng.api.model.account.SysRole; import com.xiaopeng.api.model.account.XpOperationsRole; import com.xiaopeng.api.model.account.XpOperationsUser; import com.xiaopeng.api.model.account.XpQualificationAudit; import com.xiaopeng.api.model.vehicleConvoy.XpFleet; import com.xiaopeng.api.vo.account.*; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.common.core.utils.poi.ExcelUtil; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.security.utils.SecurityUtils; import com.xiaopeng.evi.oss.service.AliOssService; import lombok.extern.slf4j.Slf4j; 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.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.time.LocalDateTime; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** *

* 运维人员 服务实现类 *

* * @author mitao * @since 2026-02-03 */ @Slf4j @Service public class XpOperationsUserServiceImpl extends ServiceImpl implements IXpOperationsUserService { @Autowired private XpFleetOperationsClient xpFleetOperationsClient; @Autowired private XpFleetClient xpFleetClient; @Autowired private XpOperationsRoleMapper xpOperationsRoleMapper; @Autowired private IXpOperationsRoleService xpOperationsRoleService; @Autowired private XpClockInClient xpClockInClient; @Autowired private IXpQualificationAuditService xpQualificationAuditService; @Autowired private SysRoleMapper sysRoleMapper; @Autowired private ISysRoleService iSysRoleService; @Autowired private AliOssService aliOssService; @Autowired private AliOssDownloadUtil aliOssDownloadUtil; @Autowired private ISysGroupService sysGroupService; @Override public XpOperationsUser getById(Serializable userId){ XpOperationsUser user = baseMapper.selectById(userId); //获取登录用户权限信息 user.setPhoneNumber(sysGroupService.getPhoneDesensitization(user.getPhoneNumber())); return user; } @Override public List listByName(String nickName) { if (StringUtils.isBlank(nickName)) { return Collections.emptyList(); } List list = lambdaQuery().like(XpOperationsUser::getNickName, nickName).list(); for (XpOperationsUser obj : list) { obj.setPhoneNumber(sysGroupService.getPhoneDesensitization(obj.getPhoneNumber())); } return list; } @Override public PageInfo selectUserPageByConditions(XpOperationsUserPageQuery query) { PageInfo pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); Page page = baseMapper.selectUserPageByConditions(pageInfo, query); for (XpOperationsUserWithRoleVO record : page.getRecords()) { record.setPhoneNumber(sysGroupService.getPhoneDesensitization(record.getPhoneNumber())); } pageInfo.setRecords(page.getRecords()); return pageInfo; } @Override public List findList(XpOperationsUserQueryDTO query){ return baseMapper.selectUserPageByConditions(query); } @Override public XpOperationsUserProfileVO getUserProfile(Long userId) { // 1. 查询运维人员基础信息 XpOperationsUser user = this.getById(userId); if (user == null) { throw new ServiceException("运维人员不存在"); } XpOperationsUserProfileVO vo = new XpOperationsUserProfileVO(); BeanUtils.copyProperties(user, vo); vo.setPhoneNumber(sysGroupService.getPhoneDesensitization(vo.getPhoneNumber())); vo.setAvatar(aliOssDownloadUtil.getPictureJSONObject(vo.getAvatar())); // 2. 查询关联的车队ID列表(一个运维人员只能关联一个车队) R> fleetIdsResult = xpFleetOperationsClient.getFleetIdsByUserId(userId); List fleetIds = fleetIdsResult.getData(); if (!CollectionUtils.isEmpty(fleetIds)) { // 3. 获取第一个车队ID(因为只能关联一个车队) Long fleetId = fleetIds.get(0); // 4. 查询车队信息 R> fleetsResult = xpFleetClient.listByIds(Collections.singletonList(fleetId)); List fleets = fleetsResult.getData(); if (!CollectionUtils.isEmpty(fleets)) { XpFleet fleet = fleets.get(0); // 5. 组装车队信息VO FleetInfoVO fleetVO = new FleetInfoVO(); fleetVO.setFleetId(fleet.getId()); fleetVO.setFleetName(fleet.getFleetName()); fleetVO.setProvinceName(fleet.getProvinceName()); fleetVO.setCityName(fleet.getCityName()); fleetVO.setDistrictName(fleet.getDistrictName()); // 6. 查询并填充车队队长信息 if (fleet.getOperationsUserId() != null) { XpOperationsUser captain = this.getById(fleet.getOperationsUserId()); if (captain != null) { fleetVO.setCaptainId(captain.getId()); fleetVO.setFleetLeaderName(captain.getNickName()); fleetVO.setFleetLeaderAvatar(captain.getAvatar()); } } vo.setFleet(fleetVO); } } // 7. 查询是否上班中 try { R workStatusResult = xpClockInClient.checkWorkStatus(userId); if (workStatusResult != null && workStatusResult.getCode() == 200) { vo.setWorkFlag(workStatusResult.getData()); } else { // 调用失败,默认 false vo.setWorkFlag(1); log.warn("查询用户上班状态失败, userId={}, result={}", userId, workStatusResult); } } catch (Exception e) { // 异常情况,默认 false vo.setWorkFlag(1); log.error("查询用户上班状态异常, userId={}", userId, e); } // 8. 查询角色信息 List userWithRoles = this.selectUsersWithRoleByIds(Collections.singletonList(userId)); XpOperationsUserWithRoleVO operationsUserWithRoleVO = userWithRoles.get(0); if (CollUtil.isNotEmpty(operationsUserWithRoleVO.getRoles())) { List roleVOs = operationsUserWithRoleVO.getRoles().stream() .map(item -> { XpOperationsUserProfileVO.RoleInfoVO roleInfoVO = BeanUtil.copyProperties(item, XpOperationsUserProfileVO.RoleInfoVO.class); roleInfoVO.setRoleId(item.getId()); return roleInfoVO; }) .collect(Collectors.toList()); vo.setRoles(roleVOs); } return vo; } @Override @Transactional @ShardingSphereTransactionType(TransactionType.BASE) public void saveCertificate(XpOperationsUserDTO dto) { // XpOperationsUser xpOperationsUser = BeanUtil.copyProperties(dto, XpOperationsUser.class); // updateById(xpOperationsUser); //保存审核记录 XpQualificationAudit xpQualificationAudit = BeanUtil.copyProperties(dto, XpQualificationAudit.class, "id"); xpQualificationAudit.setAuditStatus(1); xpQualificationAudit.setOperationsUserId(dto.getId()); xpQualificationAuditService.save(xpQualificationAudit); } @Override public PageInfo pageList(XpOperationsUserQuery query) { PageInfo pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize()); List list = this.baseMapper.pageList(pageInfo, query); if(CollectionUtils.isEmpty(list)){ return pageInfo; } // 查询角色名称 List operationsUserIds = list.stream().map(XpOperationsUserVO::getId).collect(Collectors.toList()); // 查询用户信息 List xpOperationsRoles = xpOperationsRoleMapper.selectList(Wrappers.lambdaQuery(XpOperationsRole.class) .in(XpOperationsRole::getOperationsUserId, operationsUserIds)); if(!CollectionUtils.isEmpty(xpOperationsRoles)){ List roleIds = xpOperationsRoles.stream().map(XpOperationsRole::getRoleId).distinct().collect(Collectors.toList()); // 查询列表关联的所有角色 List sysRoles = sysRoleMapper.selectList(Wrappers.lambdaQuery(SysRole.class) .in(SysRole::getId, roleIds)); if(!CollectionUtils.isEmpty(sysRoles)){ // 角色匹配账号id Map> map = new HashMap<>(); for (XpOperationsRole xpOperationsRole : xpOperationsRoles) { List sysRoleList = sysRoles.stream().filter(sysRole -> sysRole.getId().equals(xpOperationsRole.getRoleId())).collect(Collectors.toList()); List roleList = map.get(xpOperationsRole.getOperationsUserId()); if(!CollectionUtils.isEmpty(roleList)){ sysRoleList.addAll(roleList); } map.put(xpOperationsRole.getOperationsUserId(), sysRoleList); } // 角色名称匹配 for (XpOperationsUserVO xpOperationsUserVO : list) { xpOperationsUserVO.setSysRoles(map.get(xpOperationsUserVO.getId())); } } } for (XpOperationsUserVO xpOperationsUserVO : list) { xpOperationsUserVO.setPhoneNumber(sysGroupService.getPhoneDesensitization(xpOperationsUserVO.getPhoneNumber())); String avatar = xpOperationsUserVO.getAvatar(); // 处理空的情况 if (avatar == null) { continue; } JSONObject jsonObject = JSONObject.parseObject(avatar); String downloadUrl = null; try { // 1 if(Objects.nonNull(jsonObject)){ downloadUrl = aliOssService.getDownloadUrl(jsonObject.getString("id"), jsonObject.getString("name"), true); jsonObject.put("url", downloadUrl); xpOperationsUserVO.setAvatar(jsonObject.toJSONString()); } } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } pageInfo.setRecords(list); return pageInfo; } @Override public R addOperationsUser(XpOperationsUserAddDTO dto) { long userCount = this.count(Wrappers.lambdaQuery(XpOperationsUser.class) .eq(XpOperationsUser::getPhoneNumber, dto.getPhoneNumber())); if (StringUtils.isNotBlank(dto.getPhoneNumber()) && userCount>0) { throw new ServiceException("登录账号重复", I18nKeyConstant.ACCOUNT_DUPLICATE); } //校验编号是否唯一 long numberCount = this.count(Wrappers.lambdaQuery(XpOperationsUser.class) .eq(XpOperationsUser::getUniqueNumber, dto.getUniqueNumber())); if (numberCount > 0) { throw new ServiceException("用户编号已存在", I18nKeyConstant.ACCOUNT_UNIQUE_NUMBER_DUPLICATE); } // 密码加密 dto.setPassword(SecurityUtils.encryptPassword(dto.getPassword())); // 保存 this.save(dto); // 存储角色 List roleIds = dto.getRoleIds(); if(!CollectionUtils.isEmpty(roleIds)){ List xpOperationsRoles = roleIds.stream().map(roleId -> { XpOperationsRole xpOperationsRole = new XpOperationsRole(); xpOperationsRole.setOperationsUserId(dto.getId()); xpOperationsRole.setRoleId(roleId); return xpOperationsRole; }).collect(Collectors.toList()); xpOperationsRoleService.saveBatch(xpOperationsRoles); } return R.ok(); } @Override public R editOperationsUser(XpOperationsUserAddDTO dto) { XpOperationsUser operationsUser = this.getOne(Wrappers.lambdaQuery(XpOperationsUser.class) .eq(XpOperationsUser::getPhoneNumber, dto.getPhoneNumber()) .last("LIMIT 1")); if (StringUtils.isNotBlank(dto.getPhoneNumber()) && (Objects.nonNull(operationsUser) && !dto.getId().equals(operationsUser.getId()) )) { throw new ServiceException("手机号已开通账号", I18nKeyConstant.ACCOUNT_PHONE_DUPLICATE); } if (dto.getPassword() != null && !dto.getPassword().isEmpty()) { dto.setPassword(null); } this.updateById(dto); //删除旧的角色数据,添加新的角色 xpOperationsRoleService.remove(new LambdaQueryWrapper().eq(XpOperationsRole::getOperationsUserId, dto.getId())); // 存储角色 List roleIds = dto.getRoleIds(); if(!CollectionUtils.isEmpty(roleIds)){ List xpOperationsRoles = roleIds.stream().map(roleId -> { XpOperationsRole xpOperationsRole = new XpOperationsRole(); xpOperationsRole.setOperationsUserId(dto.getId()); xpOperationsRole.setRoleId(roleId); return xpOperationsRole; }).collect(Collectors.toList()); xpOperationsRoleService.saveBatch(xpOperationsRoles); } return R.ok(); } @Override public void enableDisableById(EnableDisableDTO dto) { XpOperationsUser operationsUser = this.getById(dto.getId()); operationsUser.setStatus(dto.getStatus()); this.updateById(operationsUser); } @Override public void rePassword(RePasswordDTO dto) { XpOperationsUser operationsUser = this.getById(dto.getId()); // 密码加密 operationsUser.setPassword(SecurityUtils.encryptPassword(dto.getNewPassword())); this.updateById(operationsUser); } @Override public XpOperationsUserVO detailById(Long id) { // 查询用户信息 XpOperationsUser xpOperationsUser = this.getById(id); XpOperationsUserVO xpOperationsUserVO = new XpOperationsUserVO(); BeanUtils.copyProperties(xpOperationsUser, xpOperationsUserVO); // 查询角色 List xpOperationsRoles = xpOperationsRoleMapper.selectList(Wrappers.lambdaQuery(XpOperationsRole.class) .eq(XpOperationsRole::getOperationsUserId, id)); if(!CollectionUtils.isEmpty(xpOperationsRoles)){ List roleIds = xpOperationsRoles.stream().map(XpOperationsRole::getRoleId).collect(Collectors.toList()); List sysRoles = sysRoleMapper.selectList(Wrappers.lambdaQuery(SysRole.class) .in(SysRole::getId, roleIds)); xpOperationsUserVO.setSysRoles(sysRoles); } return xpOperationsUserVO; } /** * 导出运维人员列表 * @param query */ @Override public void exportOperationsUser(XpOperationsUserQuery query, HttpServletResponse response) { List list = this.baseMapper.exportOperationsUser(query); ExcelUtil util = new ExcelUtil(ExportOperationsUserVo.class); util.exportExcel(response, list, "运维人员管理列表"); } /** * 导入运维人员数据 * @param file */ @Override public void importOperationsUser(MultipartFile file) { ExcelUtil util = new ExcelUtil(ExportOperationsUserVo.class); List list = null; try { list = util.importExcel(file.getInputStream()); } catch (Exception e) { throw new ServiceException("导入运维人员数据异常", I18nKeyConstant.ACCOUNT_IMPORT_ERROR); } for (ExportOperationsUserVo exportOperationsUserVo : list) { XpOperationsUser xpOperationsUser = new XpOperationsUser(); xpOperationsUser.setNickName(exportOperationsUserVo.getNickName()); xpOperationsUser.setUniqueNumber(exportOperationsUserVo.getUniqueNumber()); xpOperationsUser.setAvatar(exportOperationsUserVo.getAvatar()); boolean isPhone = PhoneUtil.isMobile(exportOperationsUserVo.getPhoneNumber()); if (!isPhone) { throw new ServiceException("以下帐号格式不正确:", I18nKeyConstant.ACCOUNT_FORMAT_ERROR,new Object[]{exportOperationsUserVo.getPhoneNumber()}); } // 判断账号是否已存在 long count = this.count(Wrappers.lambdaQuery(XpOperationsUser.class) .eq(XpOperationsUser::getPhoneNumber, exportOperationsUserVo.getPhoneNumber())); if (count > 0) { throw new ServiceException("以下帐号已存在:", I18nKeyConstant.ACCOUNT_EXIST,new Object[]{exportOperationsUserVo.getPhoneNumber()}); } xpOperationsUser.setPhoneNumber(exportOperationsUserVo.getPhoneNumber()); xpOperationsUser.setPassword(SecurityUtils.encryptPassword("a123456")); xpOperationsUser.setRemarks(exportOperationsUserVo.getRemarks()); xpOperationsUser.setStatus(true); xpOperationsUser.setIdCardFront(StringUtils.isBlank(exportOperationsUserVo.getIdCardFront()) ? null : exportOperationsUserVo.getIdCardFront()); xpOperationsUser.setIdCardBack(StringUtils.isBlank(exportOperationsUserVo.getIdCardBack()) ? null : exportOperationsUserVo.getIdCardBack()); xpOperationsUser.setDriverLicense(StringUtils.isBlank(exportOperationsUserVo.getDriverLicense()) ? null : exportOperationsUserVo.getDriverLicense()); xpOperationsUser.setCertificateOfNoCriminalRecord(StringUtils.isBlank(exportOperationsUserVo.getCertificateOfNoCriminalRecord()) ? null : exportOperationsUserVo.getCertificateOfNoCriminalRecord()); xpOperationsUser.setTrainingGraduationCertificate(StringUtils.isBlank(exportOperationsUserVo.getTrainingGraduationCertificate()) ? null : exportOperationsUserVo.getTrainingGraduationCertificate()); xpOperationsUser.setDeleted(false); xpOperationsUser.setCreateTime(LocalDateTime.now()); xpOperationsUser.setUpdateTime(LocalDateTime.now()); this.save(xpOperationsUser); // 通过角色名称查询角色 String roleName = exportOperationsUserVo.getRoleName(); if(StringUtils.isNotBlank(roleName)){ List sysRoles = iSysRoleService.list(Wrappers.lambdaQuery(SysRole.class) .in(SysRole::getRoleName, Arrays.asList(roleName.split(",")))); if(!CollectionUtils.isEmpty(sysRoles)){ List xpOperationsRoles = new ArrayList<>(); for (SysRole sysRole : sysRoles) { XpOperationsRole xpOperationsRole = new XpOperationsRole(); xpOperationsRole.setOperationsUserId(xpOperationsUser.getId()); xpOperationsRole.setRoleId(sysRole.getId()); xpOperationsRoles.add(xpOperationsRole); } xpOperationsRoleService.saveBatch(xpOperationsRoles); }else { throw new ServiceException("角色["+roleName+"]不存在",I18nKeyConstant.ROlE_NOT_EXISTS); } } } } /** * 导出模板 * @param response */ @Override public void exportTemplate(HttpServletResponse response) { ExcelUtil util = new ExcelUtil(ExportOperationsUserVo.class); util.importTemplateExcel(response, "运维人员管理列表"); } @Override public List selectUsersWithRoleByIds(List ids) { if (CollUtil.isEmpty(ids)) { return Collections.emptyList(); } List operationsUsers = listByIds(ids); if (CollUtil.isEmpty(operationsUsers)) { return Collections.emptyList(); } // 查询用户角色信息 List userIds = operationsUsers.stream() .map(XpOperationsUser::getId) .filter(Objects::nonNull) .distinct() .collect(Collectors.toList()); if (CollUtil.isEmpty(userIds)) { return Collections.emptyList(); } // 获取关联角色ids List operationsRoles = xpOperationsRoleMapper.selectList( Wrappers.lambdaQuery(XpOperationsRole.class) .in(XpOperationsRole::getOperationsUserId, userIds) ); // userId -> 该用户关联的 roleId 列表 Map> userRoleIdsMap = CollUtil.isNotEmpty(operationsRoles) ? operationsRoles.stream() .filter(r -> r.getOperationsUserId() != null && r.getRoleId() != null) .collect(Collectors.groupingBy( XpOperationsRole::getOperationsUserId, Collectors.mapping(XpOperationsRole::getRoleId, Collectors.collectingAndThen(Collectors.toList(), list -> list.stream().distinct().collect(Collectors.toList()))) )) : Collections.emptyMap(); // 一次性查出所有角色 List roleIds = userRoleIdsMap.values().stream() .flatMap(Collection::stream) .distinct() .collect(Collectors.toList()); Map roleMap = CollUtil.isNotEmpty(roleIds) ? iSysRoleService.listByIds(roleIds).stream() .collect(Collectors.toMap(SysRole::getId, Function.identity(), (a, b) -> a)) : Collections.emptyMap(); // 组装 VO:每个用户对应角色列表 return operationsUsers.stream().map(u -> { Long uid = u.getId(); List roleIdList = userRoleIdsMap.getOrDefault(uid, Collections.emptyList()); List roles = roleIdList.stream() .map(roleMap::get) .filter(Objects::nonNull) .collect(Collectors.toList()); // 根据你的 VO 字段调整 XpOperationsUserWithRoleVO vo = BeanUtil.copyProperties(u, XpOperationsUserWithRoleVO.class); vo.setRoles(roles); return vo; }).collect(Collectors.toList()); } @Override public List getByPhoneNumber(String phoneNumber) { if (StringUtils.isBlank(phoneNumber)) { return Collections.emptyList(); } return lambdaQuery().like(XpOperationsUser::getPhoneNumber, phoneNumber).list(); } }