package com.zsElectric.boot.business.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.zsElectric.boot.business.mapper.BannerInfoMapper; import com.zsElectric.boot.business.mapper.PolicyFeeMapper; import com.zsElectric.boot.business.mapper.ThirdPartyStationInfoMapper; import com.zsElectric.boot.business.mapper.UserFirmMapper; import com.zsElectric.boot.charging.entity.ThirdPartyChargeStatus; import com.zsElectric.boot.charging.entity.ThirdPartyConnectorInfo; import com.zsElectric.boot.charging.entity.ThirdPartyEquipmentInfo; import com.zsElectric.boot.charging.mapper.ThirdPartyChargeStatusMapper; import com.zsElectric.boot.charging.mapper.ThirdPartyConnectorInfoMapper; import com.zsElectric.boot.charging.entity.ThirdPartyEquipmentPricePolicy; import com.zsElectric.boot.charging.entity.ThirdPartyPolicyInfo; import com.zsElectric.boot.charging.entity.ThirdPartyStationInfo; import com.zsElectric.boot.business.mapper.ThirdPartyEquipmentInfoMapper; import com.zsElectric.boot.charging.mapper.ThirdPartyEquipmentPricePolicyMapper; import com.zsElectric.boot.charging.mapper.ThirdPartyPolicyInfoMapper; import com.zsElectric.boot.business.model.entity.BannerInfo; import com.zsElectric.boot.business.model.entity.PolicyFee; import com.zsElectric.boot.business.model.entity.UserFirm; import com.zsElectric.boot.business.model.query.StationInfoQuery; import com.zsElectric.boot.business.model.vo.AppletConnectorListVO; import com.zsElectric.boot.business.model.vo.AppletStationDetailVO; import com.zsElectric.boot.business.model.vo.AppletStationPriceListVO; import com.zsElectric.boot.business.model.vo.BannerInfoVO; import com.zsElectric.boot.business.model.vo.StationInfoMapVO; import com.zsElectric.boot.business.model.vo.StationInfoVO; import com.zsElectric.boot.business.model.vo.applet.AppletChargingCostVO; import com.zsElectric.boot.business.service.AppletHomeService; import com.zsElectric.boot.business.converter.BannerInfoConverter; import com.zsElectric.boot.security.util.SecurityUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.LocalTime; import java.time.format.DateTimeFormatter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Slf4j @Service @RequiredArgsConstructor public class AppletHomeServiceImpl implements AppletHomeService { private final ThirdPartyStationInfoMapper thirdPartyStationInfoMapper; private final UserFirmMapper userFirmMapper; private final BannerInfoMapper bannerInfoMapper; private final BannerInfoConverter bannerInfoConverter; private final ThirdPartyConnectorInfoMapper thirdPartyConnectorInfoMapper; private final ThirdPartyEquipmentInfoMapper thirdPartyEquipmentInfoMapper; private final ThirdPartyEquipmentPricePolicyMapper thirdPartyEquipmentPricePolicyMapper; private final ThirdPartyPolicyInfoMapper thirdPartyPolicyInfoMapper; private final PolicyFeeMapper policyFeeMapper; private final ThirdPartyChargeStatusMapper thirdPartyChargeStatusMapper; /** * 时间格式化器 HHmmss */ private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HHmmss"); @Override public IPage getStationInfoPage(StationInfoQuery queryParams) { // 查询用户是否为企业用户,获取企业ID Long firmId = null; boolean isFirmUser = false; if (queryParams.getUserId() != null) { UserFirm userFirm = userFirmMapper.selectOne( new LambdaQueryWrapper() .eq(UserFirm::getUserId, queryParams.getUserId()) .last("LIMIT 1") ); if (userFirm != null) { firmId = userFirm.getFirmId(); isFirmUser = true; } } // 获取当前时间(HHmmss格式) String currentTime = LocalTime.now().format(TIME_FORMATTER); // 构建分页对象 Page page = new Page<>(queryParams.getPageNum(), queryParams.getPageSize()); // 执行查询 IPage resultPage = thirdPartyStationInfoMapper.selectAppletStationInfoPage( page, queryParams, currentTime, firmId ); // 设置是否企业用户标识 final boolean finalIsFirmUser = isFirmUser; resultPage.getRecords().forEach(vo -> vo.setFirmUser(finalIsFirmUser)); return resultPage; } @Override public List getStationInfoMapList(BigDecimal longitude, BigDecimal latitude) { // 获取当前时间(HHmmss格式) String currentTime = LocalTime.now().format(TIME_FORMATTER); // 查询站点列表(按距离排序) return thirdPartyStationInfoMapper.selectStationMapList( longitude, latitude, currentTime ); } @Override public List getBannerList() { // 查询启用状态的Banner,按排序字段降序 List bannerList = bannerInfoMapper.selectList( new LambdaQueryWrapper() .eq(BannerInfo::getStatus, 1) .orderByDesc(BannerInfo::getSort) ); return bannerInfoConverter.toVO(bannerList); } @Override public AppletStationDetailVO getStationDetail(Long stationId, BigDecimal longitude, BigDecimal latitude) { // 获取当前登录用户ID Long userId = SecurityUtils.getUserId(); // 查询用户是否为企业用户,获取企业ID Long firmId = null; boolean isFirmUser = false; if (userId != null) { UserFirm userFirm = userFirmMapper.selectOne( new LambdaQueryWrapper() .eq(UserFirm::getUserId, userId) .last("LIMIT 1") ); if (userFirm != null) { firmId = userFirm.getFirmId(); isFirmUser = true; } } // 获取当前时间(HHmmss格式) String currentTime = LocalTime.now().format(TIME_FORMATTER); // 查询站点详情基本信息 AppletStationDetailVO result = thirdPartyStationInfoMapper.selectStationDetail( stationId, longitude, latitude, currentTime, firmId ); if (result == null) { return null; } // 设置是否企业用户 result.setFirmUser(isFirmUser); // 计算预计省多少(当前价 - 原价,如果为负则取绝对值) if (result.getCurrentPrice() != null && result.getOriginalPrice() != null) { BigDecimal saving = result.getOriginalPrice().subtract(result.getCurrentPrice()); result.setEstimatedSaving(saving.compareTo(BigDecimal.ZERO) > 0 ? saving : BigDecimal.ZERO); result.setShowSpecialPriceTag(saving.compareTo(BigDecimal.ZERO) > 0); } // 查询站点对应的stationId ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectById(stationId); if (stationInfo == null) { return result; } // 根据站点stationId查询设备列表(third_party_equipment_info) List equipmentList = thirdPartyEquipmentInfoMapper.selectList( new LambdaQueryWrapper() .eq(ThirdPartyEquipmentInfo::getStationId, stationInfo.getStationId()) ); // 构建设备ID到设备类型的映射 Map equipmentTypeMap = equipmentList.stream() .collect(Collectors.toMap( ThirdPartyEquipmentInfo::getEquipmentId, e -> e.getEquipmentType() != null ? e.getEquipmentType() : 0, (v1, v2) -> v1 )); // 根据设备列表的equipmentId查询充电接口信息(third_party_connector_info) List connectorList = new ArrayList<>(); if (!equipmentList.isEmpty()) { List equipmentIds = equipmentList.stream() .map(ThirdPartyEquipmentInfo::getEquipmentId) .collect(Collectors.toList()); connectorList = thirdPartyConnectorInfoMapper.selectList( new LambdaQueryWrapper() .in(ThirdPartyConnectorInfo::getEquipmentId, equipmentIds) ); } // 统计终端状态 int idleCount = 0; int occupiedCount = 0; int offlineCount = 0; List connectorVOList = new ArrayList<>(); for (ThirdPartyConnectorInfo connector : connectorList) { AppletStationDetailVO.ConnectorInfoVO vo = new AppletStationDetailVO.ConnectorInfoVO(); vo.setConnectorId(connector.getId()); vo.setConnectorName(connector.getConnectorName()); vo.setConnectorCode(connector.getConnectorId()); // 设备分类:从设备表获取设备类型(1-直流设备,2-交流设备,3-交直流一体设备,4-无线设备,5-其他) Integer equipmentType = equipmentTypeMap.get(connector.getEquipmentId()); if (equipmentType != null) { switch (equipmentType) { case 1: vo.setEquipmentType("直流设备"); break; case 2: vo.setEquipmentType("交流设备"); break; case 3: vo.setEquipmentType("交直流一体设备"); break; case 4: vo.setEquipmentType("无线设备"); break; case 5: vo.setEquipmentType("其他"); break; default: vo.setEquipmentType("未知"); } } // 从充电接口表获取实际状态 // 0-离网,1-空闲,2-占用(未充电),3-占用(充电中),4-占用(预约锁定),255-故障 Integer connectorStatus = connector.getStatus(); if (connectorStatus == null) { // 默认为离网 connectorStatus = 0; } vo.setStatus(connectorStatus); // 设置状态名称并统计 switch (connectorStatus) { case 0: vo.setStatusName("离网"); offlineCount++; break; case 1: vo.setStatusName("空闲"); idleCount++; break; case 2: vo.setStatusName("占用(未充电)"); occupiedCount++; break; case 3: vo.setStatusName("占用(充电中)"); occupiedCount++; break; case 4: vo.setStatusName("占用(预约锁定)"); occupiedCount++; break; case 255: vo.setStatusName("故障"); offlineCount++; break; default: vo.setStatusName("未知"); offlineCount++; } connectorVOList.add(vo); } result.setConnectorList(connectorVOList); result.setIdleCount(idleCount); result.setOccupiedCount(occupiedCount); result.setOfflineCount(offlineCount); return result; } @Override public AppletConnectorListVO getConnectorList(Long stationId) { // 查询站点信息 ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectById(stationId); if (stationInfo == null) { return null; } AppletConnectorListVO result = new AppletConnectorListVO(); result.setStationId(stationId); result.setStationName(stationInfo.getStationName()); result.setTips(stationInfo.getStationTips()); // 根据站点stationId查询设备列表 List equipmentList = thirdPartyEquipmentInfoMapper.selectList( new LambdaQueryWrapper() .eq(ThirdPartyEquipmentInfo::getStationId, stationInfo.getStationId()) ); // 构建设备ID到设备类型的映射 Map equipmentTypeMap = equipmentList.stream() .collect(Collectors.toMap( ThirdPartyEquipmentInfo::getEquipmentId, e -> e.getEquipmentType() != null ? e.getEquipmentType() : 0, (v1, v2) -> v1 )); // 查询充电接口信息 List connectorList = new ArrayList<>(); if (!equipmentList.isEmpty()) { List equipmentIds = equipmentList.stream() .map(ThirdPartyEquipmentInfo::getEquipmentId) .collect(Collectors.toList()); connectorList = thirdPartyConnectorInfoMapper.selectList( new LambdaQueryWrapper() .in(ThirdPartyConnectorInfo::getEquipmentId, equipmentIds) ); } // 统计终端状态 int idleCount = 0; int occupiedCount = 0; int offlineCount = 0; List connectorVOList = new ArrayList<>(); for (ThirdPartyConnectorInfo connector : connectorList) { AppletConnectorListVO.ConnectorItemVO vo = new AppletConnectorListVO.ConnectorItemVO(); vo.setConnectorId(connector.getId()); vo.setConnectorName(connector.getConnectorName()); vo.setConnectorCode(connector.getConnectorId()); // 设备分类 Integer equipmentType = equipmentTypeMap.get(connector.getEquipmentId()); vo.setEquipmentType(getEquipmentTypeName(equipmentType)); // 状态处理 Integer connectorStatus = connector.getStatus(); if (connectorStatus == null) { connectorStatus = 0; } vo.setStatus(connectorStatus); vo.setStatusName(getStatusName(connectorStatus)); // 统计 switch (connectorStatus) { case 1: idleCount++; break; case 2: case 3: case 4: occupiedCount++; break; default: offlineCount++; } connectorVOList.add(vo); } result.setConnectorList(connectorVOList); result.setIdleCount(idleCount); result.setOccupiedCount(occupiedCount); result.setOfflineCount(offlineCount); return result; } @Override public AppletStationPriceListVO getStationPriceList(Long stationId) { // 查询站点信息 ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectById(stationId); if (stationInfo == null) { return null; } AppletStationPriceListVO result = new AppletStationPriceListVO(); result.setStationId(stationId); result.setStationName(stationInfo.getStationName()); result.setTips(stationInfo.getStationTips()); // 获取当前登录用户ID Long userId = SecurityUtils.getUserId(); // 查询用户是否为企业用户,获取企业ID Long firmId = null; if (userId != null) { UserFirm userFirm = userFirmMapper.selectOne( new LambdaQueryWrapper() .eq(UserFirm::getUserId, userId) .last("LIMIT 1") ); if (userFirm != null) { firmId = userFirm.getFirmId(); } } // 获取当前时间(HHmmss格式) String currentTime = LocalTime.now().format(TIME_FORMATTER); // 查询站点对应的价格策略 // 1. 先查询充电接口 ThirdPartyConnectorInfo connector = thirdPartyConnectorInfoMapper.selectOne( new LambdaQueryWrapper() .eq(ThirdPartyConnectorInfo::getStationId, stationInfo.getStationId()) .last("LIMIT 1") ); if (connector == null) { result.setPriceList(new ArrayList<>()); return result; } // 2. 查询价格策略 ThirdPartyEquipmentPricePolicy pricePolicy = thirdPartyEquipmentPricePolicyMapper.selectOne( new LambdaQueryWrapper() .eq(ThirdPartyEquipmentPricePolicy::getConnectorId, connector.getConnectorId()) .eq(ThirdPartyEquipmentPricePolicy::getIsDeleted, 0) .last("LIMIT 1") ); if (pricePolicy == null) { result.setPriceList(new ArrayList<>()); return result; } // 3. 查询价格明细列表 List policyInfoList = thirdPartyPolicyInfoMapper.selectList( new LambdaQueryWrapper() .eq(ThirdPartyPolicyInfo::getPricePolicyId, pricePolicy.getId()) .eq(ThirdPartyPolicyInfo::getIsDeleted, 0) .orderByAsc(ThirdPartyPolicyInfo::getStartTime) ); // 4. 如果是企业用户,查询企业价格 Map enterprisePriceMap = new HashMap<>(); boolean hasEnterprisePrice = false; if (firmId != null) { List policyFeeList = policyFeeMapper.selectList( new LambdaQueryWrapper() .eq(PolicyFee::getStationInfoId, stationId) .eq(PolicyFee::getSalesType, 1) // 1-企业 .eq(PolicyFee::getFirmId, firmId) .eq(PolicyFee::getIsDeleted, 0) ); // 如果查询到企业价格记录,设置标志为true if (!policyFeeList.isEmpty()) { hasEnterprisePrice = true; } // 构建企业价格映射 (startTime -> enterprisePrice) for (PolicyFee policyFee : policyFeeList) { // 查找对应的时段价格信息 ThirdPartyPolicyInfo matchedPolicyInfo = policyInfoList.stream() .filter(info -> info.getStartTime().equals(policyFee.getStartTime())) .findFirst() .orElse(null); if (matchedPolicyInfo != null) { // 企业价格 = 电费 + 服务费 + 运营费 + 综合销售费 BigDecimal elecPrice = matchedPolicyInfo.getElecPrice() != null ? matchedPolicyInfo.getElecPrice() : BigDecimal.ZERO; BigDecimal servicePrice = matchedPolicyInfo.getServicePrice() != null ? matchedPolicyInfo.getServicePrice() : BigDecimal.ZERO; BigDecimal opFee = policyFee.getOpFee() != null ? policyFee.getOpFee() : BigDecimal.ZERO; BigDecimal compSalesFee = policyFee.getCompSalesFee() != null ? policyFee.getCompSalesFee() : BigDecimal.ZERO; BigDecimal enterprisePrice = elecPrice.add(servicePrice).add(opFee).add(compSalesFee); enterprisePriceMap.put(policyFee.getStartTime(), enterprisePrice); } } } // 设置是否有企业价格 result.setHasEnterprisePrice(hasEnterprisePrice); // 5. 构建价格列表 List priceList = new ArrayList<>(); for (int i = 0; i < policyInfoList.size(); i++) { ThirdPartyPolicyInfo policyInfo = policyInfoList.get(i); AppletStationPriceListVO.PriceItemVO priceItem = new AppletStationPriceListVO.PriceItemVO(); // 时段格式化:HHmmss -> HH:mm String startTime = formatTime(policyInfo.getStartTime()); // 下一个时段的开始时间作为当前时段的结束时间 String endTime = (i + 1 < policyInfoList.size()) ? formatTime(policyInfoList.get(i + 1).getStartTime()) : "24:00"; priceItem.setTimePeriod(startTime + "-" + endTime); priceItem.setPeriodFlag(policyInfo.getPeriodFlag()); priceItem.setPeriodFlagName(getPeriodFlagName(policyInfo.getPeriodFlag())); priceItem.setElecPrice(policyInfo.getElecPrice()); priceItem.setServicePrice(policyInfo.getServicePrice()); // 合计充电价 = 电费 + 服务费 BigDecimal elecPrice = policyInfo.getElecPrice() != null ? policyInfo.getElecPrice() : BigDecimal.ZERO; BigDecimal servicePrice = policyInfo.getServicePrice() != null ? policyInfo.getServicePrice() : BigDecimal.ZERO; priceItem.setTotalPrice(elecPrice.add(servicePrice)); // 设置企业价格(如果有) BigDecimal enterprisePrice = enterprisePriceMap.get(policyInfo.getStartTime()); priceItem.setEnterprisePrice(enterprisePrice); // 判断是否为当前时段 priceItem.setCurrentPeriod(isCurrentPeriod(policyInfo.getStartTime(), (i + 1 < policyInfoList.size()) ? policyInfoList.get(i + 1).getStartTime() : null, currentTime)); priceList.add(priceItem); } result.setPriceList(priceList); return result; } /** * 获取设备类型名称 */ private String getEquipmentTypeName(Integer equipmentType) { if (equipmentType == null) { return "未知"; } switch (equipmentType) { case 1: return "直流设备"; case 2: return "交流设备"; case 3: return "交直流一体设备"; case 4: return "无线设备"; case 5: return "其他"; default: return "未知"; } } /** * 获取状态名称 */ private String getStatusName(Integer status) { if (status == null) { return "未知"; } switch (status) { case 0: return "离网"; case 1: return "空闲"; case 2: return "占用(未充电)"; case 3: return "占用(充电中)"; case 4: return "占用(预约锁定)"; case 255: return "故障"; default: return "未知"; } } /** * 获取时段标志名称 */ private String getPeriodFlagName(Integer periodFlag) { if (periodFlag == null) { return ""; } switch (periodFlag) { case 1: return "尖"; case 2: return "峰"; case 3: return "平"; case 4: return "谷"; default: return ""; } } /** * 格式化时间 HHmmss -> HH:mm */ private String formatTime(String time) { if (time == null || time.length() < 4) { return "00:00"; } return time.substring(0, 2) + ":" + time.substring(2, 4); } /** * 判断是否为当前时段 */ private boolean isCurrentPeriod(String startTime, String nextStartTime, String currentTime) { if (startTime == null || currentTime == null) { return false; } // 当前时间 >= 开始时间 且 当前时间 < 下一个时段开始时间 if (currentTime.compareTo(startTime) >= 0) { if (nextStartTime == null || currentTime.compareTo(nextStartTime) < 0) { return true; } } return false; } @Override public AppletChargingCostVO getCurrentChargingCost(String chargeOrderNo) { // 1. 查询充电状态记录 ThirdPartyChargeStatus chargeStatus = thirdPartyChargeStatusMapper.selectOne( new LambdaQueryWrapper() .eq(ThirdPartyChargeStatus::getStartChargeSeq, chargeOrderNo) .orderByDesc(ThirdPartyChargeStatus::getUpdateTime) .last("LIMIT 1") ); if (chargeStatus == null) { return null; } // 2. 通过connector_id查询充电终端信息 ThirdPartyConnectorInfo connectorInfo = thirdPartyConnectorInfoMapper.selectOne( new LambdaQueryWrapper() .eq(ThirdPartyConnectorInfo::getConnectorId, chargeStatus.getConnectorId()) .last("LIMIT 1") ); if (connectorInfo == null) { return null; } // 3. 通过station_id查询站点信息 ThirdPartyStationInfo stationInfo = thirdPartyStationInfoMapper.selectOne( new LambdaQueryWrapper() .eq(ThirdPartyStationInfo::getStationId, connectorInfo.getStationId()) .last("LIMIT 1") ); // 4. 构建返回结果 AppletChargingCostVO result = new AppletChargingCostVO(); result.setChargeOrderNo(chargeOrderNo); result.setStationName(stationInfo != null ? stationInfo.getStationName() : ""); result.setConnectorName(connectorInfo.getConnectorName()); // 订单状态 result.setOrderStatus(chargeStatus.getStartChargeSeqStat()); result.setOrderStatusDesc(getOrderStatusDesc(chargeStatus.getStartChargeSeqStat())); // 充电时长 if (chargeStatus.getStartTime() != null && chargeStatus.getEndTime() != null) { long duration = java.time.Duration.between( chargeStatus.getStartTime(), chargeStatus.getEndTime() ).getSeconds(); result.setChargingDuration(duration); result.setChargingDurationDesc(formatDuration(duration)); } // 费用信息 result.setTotalPower(chargeStatus.getTotalPower() != null ? chargeStatus.getTotalPower() : BigDecimal.ZERO); result.setElecMoney(chargeStatus.getElecMoney() != null ? chargeStatus.getElecMoney() : BigDecimal.ZERO); result.setServiceMoney(chargeStatus.getServiceMoney() != null ? chargeStatus.getServiceMoney() : BigDecimal.ZERO); result.setTotalMoney(chargeStatus.getTotalMoney() != null ? chargeStatus.getTotalMoney() : BigDecimal.ZERO); // SOC result.setSoc(chargeStatus.getSoc()); // 电压电流(取A相为主,如果没有则取其他相) BigDecimal current = chargeStatus.getCurrentA() != null ? chargeStatus.getCurrentA() : (chargeStatus.getCurrentB() != null ? chargeStatus.getCurrentB() : chargeStatus.getCurrentC()); BigDecimal voltage = chargeStatus.getVoltageA() != null ? chargeStatus.getVoltageA() : (chargeStatus.getVoltageB() != null ? chargeStatus.getVoltageB() : chargeStatus.getVoltageC()); result.setCurrent(current); result.setVoltage(voltage); // 功率 = 电压 × 电流 / 1000 (kW) if (current != null && voltage != null) { BigDecimal power = voltage.multiply(current).divide(new BigDecimal("1000"), 2, BigDecimal.ROUND_HALF_UP); result.setPower(power); } // 时间信息 if (chargeStatus.getStartTime() != null) { result.setStartTime(chargeStatus.getStartTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); } if (chargeStatus.getUpdateTime() != null) { result.setLastUpdateTime(chargeStatus.getUpdateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); } return result; } /** * 获取订单状态描述 */ private String getOrderStatusDesc(Integer status) { if (status == null) { return "未知"; } switch (status) { case 1: return "启动中"; case 2: return "充电中"; case 3: return "停止中"; case 4: return "已结束"; case 5: return "未知"; default: return "未知"; } } /** * 格式化时长(秒)为 HH:mm:ss */ private String formatDuration(long seconds) { long hours = seconds / 3600; long minutes = (seconds % 3600) / 60; long secs = seconds % 60; return String.format("%02d:%02d:%02d", hours, minutes, secs); } }