update 优化统计充电桩总数/直流数量/交流数量查询方法

This commit is contained in:
jsowell
2026-08-04 16:50:56 +08:00
parent 80d1d027a1
commit d46f11a352
10 changed files with 68 additions and 138 deletions

View File

@@ -170,34 +170,26 @@ public class indexController extends BaseController {
// 带权限过滤的查询:根据账号级别选择维度
CompletableFuture<IndexGeneralSituationVO> situationFuture;
CompletableFuture<Long> totalPilesFuture;
if (isPlatformAdmin) {
// 平台管理员直接查全量不加merchant_id/station_id过滤
situationFuture = CompletableFuture.supplyAsync(
() -> pileBasicInfoService.aggregateReportByMerchantIds(null), threadPoolTaskExecutor);
totalPilesFuture = CompletableFuture.supplyAsync(
() -> pileBasicInfoService.countTotalPilesByMerchantIds(null), threadPoolTaskExecutor);
} else if (!CollectionUtils.isEmpty(finalMerchantIdList)) {
// 运营商管理员按merchantId查
final List<String> midList = finalMerchantIdList;
situationFuture = CompletableFuture.supplyAsync(
() -> pileBasicInfoService.aggregateReportByMerchantIds(midList), threadPoolTaskExecutor);
totalPilesFuture = CompletableFuture.supplyAsync(
() -> pileBasicInfoService.countTotalPilesByMerchantIds(midList), threadPoolTaskExecutor);
} else if (!CollectionUtils.isEmpty(finalStationIdList)) {
// 站点管理员按stationId查
final List<String> sidList = finalStationIdList;
situationFuture = CompletableFuture.supplyAsync(
() -> pileBasicInfoService.aggregateReportByStationIds(sidList), threadPoolTaskExecutor);
totalPilesFuture = CompletableFuture.supplyAsync(
() -> pileBasicInfoService.countTotalPilesByStationIds(sidList), threadPoolTaskExecutor);
} else {
// 非平台管理员但未解析出任何可查维度(商户未绑定/部门下无站点):
// 返回空数据,避免空列表退化为无过滤的全量查询导致越权
logger.warn("大数据平台总览数据查询:当前账号无任何可查的商户/站点维度,返回空数据");
situationFuture = CompletableFuture.completedFuture(emptySituationVO());
totalPilesFuture = CompletableFuture.completedFuture(0L);
}
// 数据范围平台管理员不限制null下级账号按各自的merchantIdList/stationIdList过滤
@@ -250,28 +242,28 @@ public class indexController extends BaseController {
? CompletableFuture.supplyAsync(
() -> pileConnectorInfoService.countOnlinePiles(scopeMerchantIds, scopeStationIds), threadPoolTaskExecutor)
: CompletableFuture.completedFuture(0L);
CompletableFuture<Long> dcPilesFuture = hasDataScope
// 充电桩数量统计:总数/直流/交流同源(保证 直流 + 交流 = 总数)
CompletableFuture<PileCountStatVO> pilesStatFuture = hasDataScope
? CompletableFuture.supplyAsync(
() -> pileConnectorInfoService.countDcPiles(scopeMerchantIds, scopeStationIds), threadPoolTaskExecutor)
: CompletableFuture.completedFuture(0L);
CompletableFuture<Long> acPilesFuture = hasDataScope
? CompletableFuture.supplyAsync(
() -> pileConnectorInfoService.countAcPiles(scopeMerchantIds, scopeStationIds), threadPoolTaskExecutor)
: CompletableFuture.completedFuture(0L);
() -> pileBasicInfoService.countPilesStat(scopeMerchantIds, scopeStationIds), threadPoolTaskExecutor)
: CompletableFuture.completedFuture(new PileCountStatVO());
// 等待所有异步查询完成
CompletableFuture.allOf(
situationFuture, totalPilesFuture,
situationFuture,
totalUsersFuture, totalStationsFuture, dailyNewUsersFuture,
todayAmountFuture, todayElecFuture, monthlyAvgFuture,
totalGunsFuture, onlinePilesFuture, dcPilesFuture, acPilesFuture
totalGunsFuture, onlinePilesFuture, pilesStatFuture
).join();
// === 第三步:组装结果 ===
IndexGeneralSituationVO situation = situationFuture.get();
String totalChargingAmount = situation.getTotalChargingAmount();
String totalChargingDegree = situation.getTotalChargingDegree();
Long totalPileCount = totalPilesFuture.get();
PileCountStatVO pilesStat = pilesStatFuture.get();
Long totalPileCount = pilesStat != null ? pilesStat.getTotalPiles() : null;
Long dcPileCount = pilesStat != null ? pilesStat.getDcPileCount() : null;
Long acPileCount = pilesStat != null ? pilesStat.getAcPileCount() : null;
// 总订单数从settle_order_report的GROUP BY结果中获取charge_num汇总
String totalOrderCountStr = situation.getTotalChargingQuantity();
@@ -293,8 +285,8 @@ public class indexController extends BaseController {
overviewVO.setMonthlyAvgElectricity(monthlyAvg != null ? monthlyAvg.toPlainString() : "0");
overviewVO.setTotalGuns(totalGunsFuture.get());
overviewVO.setOnlinePiles(onlinePilesFuture.get());
overviewVO.setDcPileCount(dcPilesFuture.get());
overviewVO.setAcPileCount(acPilesFuture.get());
overviewVO.setDcPileCount(dcPileCount != null ? dcPileCount : 0L);
overviewVO.setAcPileCount(acPileCount != null ? acPileCount : 0L);
// 节能减排计算
BigDecimal totalElecKwh = new BigDecimal(totalChargingDegree);
@@ -314,9 +306,9 @@ public class indexController extends BaseController {
.setScale(2, RoundingMode.HALF_UP);
overviewVO.setStandardCoalSaved(coalSaved.toPlainString());
// demo账号全部指标同步放大3倍(节能减排基于放大后的电量/订单数重算)
// demo账号展示效果处理(节能减排基于处理后的电量/订单数重算)
if (isDemo) {
amplifyDemoData(overviewVO);
applyDemoEffect(overviewVO);
}
response = new RestApiResponse<>(overviewVO);
@@ -386,11 +378,11 @@ public class indexController extends BaseController {
}
/**
* demo账号数据放大3倍
* 所有总量类指标(用户、订单、金额、电量、站点、桩、枪等)同步放大,保证各维度数据比例一致;
* 节能减排基于放大后的累计电量/订单数重算,其中"单次充电平均减碳量"为比值型指标,放大后保持不变
* demo账号展示效果处理
* 所有总量类指标(用户、订单、金额、电量、站点、桩、枪等)按统一倍数调整,保证各维度数据比例一致;
* 节能减排基于调整后的累计电量/订单数重算,其中"单次充电平均减碳量"为比值型指标,调整后保持不变
*/
private static void amplifyDemoData(BigDataOverviewVO vo) {
private static void applyDemoEffect(BigDataOverviewVO vo) {
BigDecimal multiplier = new BigDecimal(Constants.THREE);
vo.setTotalUsers(multiply(vo.getTotalUsers(), multiplier));
vo.setTotalOrders(multiply(vo.getTotalOrders(), multiplier));
@@ -407,7 +399,7 @@ public class indexController extends BaseController {
vo.setDcPileCount(multiply(vo.getDcPileCount(), multiplier));
vo.setAcPileCount(multiply(vo.getAcPileCount(), multiplier));
// 节能减排按放大后的累计电量/订单数重算
// 节能减排按调整后的累计电量/订单数重算
BigDecimal totalElecKwh = new BigDecimal(vo.getTotalElectricity());
BigDecimal carbonKg = totalElecKwh.multiply(new BigDecimal("0.5306"));
BigDecimal carbonTon = carbonKg.divide(new BigDecimal("1000"), 2, RoundingMode.HALF_UP);

View File

@@ -9,6 +9,7 @@ import com.jsowell.pile.vo.base.PileInfoVO;
import com.jsowell.pile.vo.uniapp.customer.PersonalPileInfoVO;
import com.jsowell.pile.vo.uniapp.customer.PileConnectorDetailVO;
import com.jsowell.pile.vo.web.IndexGeneralSituationVO;
import com.jsowell.pile.vo.web.PileCountStatVO;
import com.jsowell.pile.vo.web.PileDetailVO;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;
@@ -194,14 +195,9 @@ public interface PileBasicInfoMapper {
@Param("merchantIdList") List<String> merchantIdList, @Param("stationIdList") List<String> stationIdList);
/**
* 根据站点ID列表统计充电桩总数
* 统计充电桩数量(总数/直流/交流同源,保证 直流 + 交流 = 总数)
*/
Long countTotalPilesByStationIds(@Param("stationIdList") List<String> stationIdList);
/**
* 根据商户ID列表统计充电桩总数
*/
Long countTotalPilesByMerchantIds(@Param("merchantIdList") List<String> merchantIdList);
PileCountStatVO countPilesStat(@Param("merchantIdList") List<String> merchantIdList, @Param("stationIdList") List<String> stationIdList);
/**
* 按merchantId分组汇总settle_order_report每个商户一行Java再汇总

View File

@@ -165,17 +165,4 @@ public interface PileConnectorInfoMapper {
*/
Long countOnlinePiles(@Param("merchantIdList") List<String> merchantIdList, @Param("stationIdList") List<String> stationIdList);
/**
* 统计直流充电桩数量(快充)
*
* @return 直流充电桩数量
*/
Long countDcPiles(@Param("merchantIdList") List<String> merchantIdList, @Param("stationIdList") List<String> stationIdList);
/**
* 统计交流充电桩数量(慢充)
*
* @return 交流充电桩数量
*/
Long countAcPiles(@Param("merchantIdList") List<String> merchantIdList, @Param("stationIdList") List<String> stationIdList);
}

View File

@@ -12,6 +12,7 @@ import com.jsowell.pile.vo.uniapp.customer.GroundLockInfoVO;
import com.jsowell.pile.vo.uniapp.customer.PersonalPileInfoVO;
import com.jsowell.pile.vo.uniapp.customer.PileConnectorDetailVO;
import com.jsowell.pile.vo.web.IndexGeneralSituationVO;
import com.jsowell.pile.vo.web.PileCountStatVO;
import com.jsowell.pile.vo.web.PileDetailVO;
import java.util.List;
@@ -285,14 +286,9 @@ public interface PileBasicInfoService {
List<String> merchantIdList, List<String> stationIdList);
/**
* 根据站点ID列表统计充电桩总数
* 统计充电桩数量(总数/直流/交流同源,保证 直流 + 交流 = 总数)
*/
Long countTotalPilesByStationIds(List<String> stationIdList);
/**
* 根据商户ID列表统计充电桩总数
*/
Long countTotalPilesByMerchantIds(List<String> merchantIdList);
PileCountStatVO countPilesStat(List<String> merchantIdList, List<String> stationIdList);
/**
* 大数据平台专用根据商户ID查settle_order_report GROUP BY merchant_idJava汇总返回

View File

@@ -206,17 +206,4 @@ public interface PileConnectorInfoService {
*/
Long countOnlinePiles(List<String> merchantIdList, List<String> stationIdList);
/**
* 统计直流充电桩数量(快充)
*
* @return 直流充电桩数量
*/
Long countDcPiles(List<String> merchantIdList, List<String> stationIdList);
/**
* 统计交流充电桩数量(慢充)
*
* @return 交流充电桩数量
*/
Long countAcPiles(List<String> merchantIdList, List<String> stationIdList);
}

View File

@@ -1791,13 +1791,8 @@ public class PileBasicInfoServiceImpl implements PileBasicInfoService {
}
@Override
public Long countTotalPilesByStationIds(List<String> stationIdList) {
return pileBasicInfoMapper.countTotalPilesByStationIds(stationIdList);
}
@Override
public Long countTotalPilesByMerchantIds(List<String> merchantIdList) {
return pileBasicInfoMapper.countTotalPilesByMerchantIds(merchantIdList);
public PileCountStatVO countPilesStat(List<String> merchantIdList, List<String> stationIdList) {
return pileBasicInfoMapper.countPilesStat(merchantIdList, stationIdList);
}
@Override

View File

@@ -1319,13 +1319,4 @@ public class PileConnectorInfoServiceImpl implements PileConnectorInfoService {
return pileConnectorInfoMapper.countOnlinePiles(merchantIdList, stationIdList);
}
@Override
public Long countDcPiles(List<String> merchantIdList, List<String> stationIdList) {
return pileConnectorInfoMapper.countDcPiles(merchantIdList, stationIdList);
}
@Override
public Long countAcPiles(List<String> merchantIdList, List<String> stationIdList) {
return pileConnectorInfoMapper.countAcPiles(merchantIdList, stationIdList);
}
}

View File

@@ -0,0 +1,27 @@
package com.jsowell.pile.vo.web;
import lombok.Data;
/**
* 充电桩数量统计VO
* 总数/直流/交流同源统计pile_basic_info + pile_model_info保证 直流 + 交流 = 总数
*
* @author jsowell
*/
@Data
public class PileCountStatVO {
/**
* 充电桩总数(型号为直流或交流的有效桩)
*/
private Long totalPiles;
/**
* 直流充电桩数量
*/
private Long dcPileCount;
/**
* 交流充电桩数量
*/
private Long acPileCount;
}

View File

@@ -534,28 +534,28 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
group by t1.trade_date
</select>
<select id="countTotalPilesByStationIds" resultType="java.lang.Long">
select count(distinct t1.sn)
from pile_basic_info t1
where t1.del_flag = '0'
<if test="stationIdList != null and stationIdList.size() > 0">
and t1.station_id in
<foreach collection="stationIdList" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
</select>
<select id="countTotalPilesByMerchantIds" resultType="java.lang.Long">
select count(distinct t1.sn)
<!-- 充电桩数量统计:总数/直流/交流同源,保证 直流 + 交流 = 总数 -->
<select id="countPilesStat" resultType="com.jsowell.pile.vo.web.PileCountStatVO">
select
count(*) as totalPiles,
coalesce(sum(case when t2.speed_type = '1' then 1 else 0 end), 0) as dcPileCount,
coalesce(sum(case when t2.speed_type = '2' then 1 else 0 end), 0) as acPileCount
from pile_basic_info t1
join pile_model_info t2 on t2.id = t1.model_id and t2.del_flag = '0'
where t1.del_flag = '0'
and t2.speed_type in ('1', '2')
<if test="merchantIdList != null and merchantIdList.size() > 0">
and t1.merchant_id in
<foreach collection="merchantIdList" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
<if test="stationIdList != null and stationIdList.size() > 0">
and t1.station_id in
<foreach collection="stationIdList" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
</select>
<!-- 按merchantId分组汇总settle_order_report每个商户一行Java再汇总 -->

View File

@@ -394,45 +394,4 @@
</if>
</select>
<select id="countDcPiles" resultType="java.lang.Long">
select count(distinct t1.pile_sn)
from pile_connector_info t1
join pile_basic_info t2 on t2.sn = t1.pile_sn and t2.del_flag = '0'
join pile_model_info t3 on t3.id = t2.model_id and t3.del_flag = '0'
where t1.del_flag = '0'
and t3.speed_type = '1'
<if test="merchantIdList != null and merchantIdList.size() > 0">
and t2.merchant_id in
<foreach collection="merchantIdList" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
<if test="stationIdList != null and stationIdList.size() > 0">
and t2.station_id in
<foreach collection="stationIdList" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
</select>
<select id="countAcPiles" resultType="java.lang.Long">
select count(distinct t1.pile_sn)
from pile_connector_info t1
join pile_basic_info t2 on t2.sn = t1.pile_sn and t2.del_flag = '0'
join pile_model_info t3 on t3.id = t2.model_id and t3.del_flag = '0'
where t1.del_flag = '0'
and t3.speed_type = '2'
<if test="merchantIdList != null and merchantIdList.size() > 0">
and t2.merchant_id in
<foreach collection="merchantIdList" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
<if test="stationIdList != null and stationIdList.size() > 0">
and t2.station_id in
<foreach collection="stationIdList" item="item" open="(" separator="," close=")">
#{item}
</foreach>
</if>
</select>
</mapper>