yanderong
2026-08-14 33ed7a54b6a6dd9f9bb8470245fc5029f5c73620
feat: 光伏电站管理、bug修改
11个文件已修改
171 ■■■■■ 已修改文件
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/energyreport/dto/EnergyReportQuery.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/energyreport/mapper/EnergyReportMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/energyreport/service/EnergyReportService.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/TStationEarnMapper.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/query/StationEarnQuery.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TStationEarnServiceImpl.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TStationInfoServiceImpl.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/util/KsolarUtils.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/resources/mapper/other/EnergyReportMapper.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/resources/mapper/other/TStationEarnMapper.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/test/java/com/ruoyi/other/energyreport/service/EnergyReportServiceTest.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/energyreport/dto/EnergyReportQuery.java
@@ -11,4 +11,6 @@
    private String stationId;
    private LocalDate startDate;
    private LocalDate endDate;
    /** 查看方式:station电站明细、summary按天汇总,默认station。 */
    private String viewMode;
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/energyreport/mapper/EnergyReportMapper.java
@@ -13,6 +13,8 @@
public interface EnergyReportMapper {
    IPage<PhotovoltaicReportRow> selectPhotovoltaicPage(Page<PhotovoltaicReportRow> page,
                                                        @Param("query") EnergyReportQuery query);
    IPage<PhotovoltaicReportRow> selectPhotovoltaicSummaryPage(Page<PhotovoltaicReportRow> page,
                                                               @Param("query") EnergyReportQuery query);
    List<PhotovoltaicReportRow> selectPhotovoltaicList(@Param("query") EnergyReportQuery query);
    IPage<StorageDailyReportRow> selectStoragePage(Page<StorageDailyReportRow> page,
                                                   @Param("query") EnergyReportQuery query);
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/energyreport/service/EnergyReportService.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.other.energyreport.dto.EnergyReportQuery;
import com.ruoyi.other.energyreport.mapper.EnergyReportMapper;
import com.ruoyi.other.energyreport.vo.PhotovoltaicReportRow;
@@ -20,7 +21,19 @@
    }
    public IPage<PhotovoltaicReportRow> photovoltaicPage(EnergyReportQuery query) {
        return mapper.selectPhotovoltaicPage(Page.of(pageNumber(query), pageSize(query)), query);
        if (query == null) {
            query = new EnergyReportQuery();
        }
        String viewMode = query.getViewMode() == null || query.getViewMode().trim().isEmpty()
                ? "station" : query.getViewMode().trim();
        Page<PhotovoltaicReportRow> page = Page.of(pageNumber(query), pageSize(query));
        if ("summary".equalsIgnoreCase(viewMode)) {
            return mapper.selectPhotovoltaicSummaryPage(page, query);
        }
        if ("station".equalsIgnoreCase(viewMode)) {
            return mapper.selectPhotovoltaicPage(page, query);
        }
        throw new ServiceException("查看方式仅支持station、summary");
    }
    public List<PhotovoltaicReportRow> photovoltaicList(EnergyReportQuery query) {
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/TStationEarnMapper.java
@@ -2,9 +2,14 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.other.api.domain.TStationEarn;
import com.ruoyi.other.api.domain.TStationInfo;
import java.util.List;
/**
 * 电站发电量统计 Mapper。
 */
public interface TStationEarnMapper extends BaseMapper<TStationEarn> {
    List<TStationInfo> selectStationInfoAll();
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/query/StationEarnQuery.java
@@ -17,4 +17,5 @@
    @ApiModelProperty("统计开始日期,yyyy-MM-dd") private LocalDate startSaveTime;
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @ApiModelProperty("统计结束日期,yyyy-MM-dd") private LocalDate endSaveTime;
    @ApiModelProperty("查看方式:station电站明细、summary按天汇总,默认station") private String viewMode;
}
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TStationEarnServiceImpl.java
@@ -3,21 +3,25 @@
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.page.PageInfo;
import com.ruoyi.other.api.domain.TStationEarn;
import com.ruoyi.other.api.domain.TStationInfo;
import com.ruoyi.other.mapper.TStationEarnMapper;
import com.ruoyi.other.query.StationEarnQuery;
import com.ruoyi.other.query.StationEarnOverviewQuery;
import com.ruoyi.other.query.StationEarnStatisticsQuery;
import com.ruoyi.other.service.TStationEarnService;
import com.ruoyi.other.util.KsolarUtils;
import com.ruoyi.other.vo.StationEarnStatisticsItemVO;
import com.ruoyi.other.vo.StationEarnStatisticsVO;
import com.ruoyi.other.vo.StationEarnOverviewVO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -27,10 +31,7 @@
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
 * 电站发电量统计服务实现。
@@ -39,6 +40,9 @@
public class TStationEarnServiceImpl
        extends ServiceImpl<TStationEarnMapper, TStationEarn>
        implements TStationEarnService {
    @Autowired
    public TStationEarnMapper mapper;
    private static final BigDecimal PHOTOVOLTAIC_CARBON_REDUCTION_FACTOR = new BigDecimal("0.0001564");
@@ -92,7 +96,14 @@
    public PageInfo<TStationEarn> pageList(StationEarnQuery query) {
        if (query == null) query = new StationEarnQuery();
        PageInfo<TStationEarn> page = new PageInfo<>(query.getPageCurr(), query.getPageSize());
        page(page, buildQueryWrapper(query));
        String viewMode = StringUtils.isBlank(query.getViewMode()) ? "station" : query.getViewMode().trim();
        if ("summary".equalsIgnoreCase(viewMode)) {
            page(page, buildSummaryQueryWrapper(query));
        } else if ("station".equalsIgnoreCase(viewMode)) {
            page(page, buildQueryWrapper(query));
        } else {
            throw new ServiceException("查看方式仅支持station、summary");
        }
        return page;
    }
@@ -157,9 +168,23 @@
        result.setDimension(dimension);
        result.setTotalGeneration(totalGeneration);
        result.setTotalEarn(totalEarn);
        result.setTotalCarbonReduction(calculateCarbonReduction(totalGeneration));
        result.setTotalCarbonReduction(getAllCo2());
        result.setItems(items);
        return result;
    }
    public BigDecimal getAllCo2() {
        BigDecimal co2List = BigDecimal.ZERO;
        List<TStationInfo> infos = mapper.selectStationInfoAll();
        if(CollectionUtils.isNotEmpty(infos)) {
            for (TStationInfo info : infos) {
                JSONObject stationEarnObj = KsolarUtils.getStationEarnDetail(info.getStationId(), KsolarUtils.token());
                if (Objects.nonNull(stationEarnObj)) {
                    co2List = co2List.add(parseBigDecimal(stationEarnObj.getString("co2")));
                }
            }
        }
        return co2List;
    }
    @Override
@@ -232,6 +257,20 @@
                .orderByDesc(TStationEarn::getCreateTime);
    }
    private QueryWrapper<TStationEarn> buildSummaryQueryWrapper(StationEarnQuery query) {
        return new QueryWrapper<TStationEarn>()
                .select("save_time",
                        "COALESCE(SUM(elec_total), 0) AS elec_total",
                        "COALESCE(SUM(earn_total), 0) AS earn_total")
                .eq(query.getPlatformId() != null, "platform_id", query.getPlatformId())
                .eq(StringUtils.isNotBlank(query.getStationId()), "station_id", query.getStationId())
                .ge(query.getStartSaveTime() != null, "save_time", query.getStartSaveTime())
                .le(query.getEndSaveTime() != null, "save_time", query.getEndSaveTime())
                .isNotNull("save_time")
                .groupBy("save_time")
                .orderByDesc("save_time");
    }
    static List<TStationEarn> buildStationEarnSyncList(JSONArray stationEarnList,
                                                        Map<String, TStationEarn> existingByKey) {
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TStationInfoServiceImpl.java
@@ -26,6 +26,7 @@
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
@@ -49,7 +50,7 @@
    @Transactional(rollbackFor = Exception.class)
    public void syncKsolarDataTask() {
        String token = KsolarUtils.token();
        JSONObject statusJsonObj = KsolarUtils.getListStatus(token);
        //JSONObject statusJsonObj = KsolarUtils.getListStatus(token);
        log.info("-------1开始同步科士达-电站列表信息----");
        // 电站列表
@@ -57,19 +58,41 @@
        // 电站基本信息列表
        JSONArray listBaseJsonArray = KsolarUtils.getStationListBase(1, 1000, token);
        List<TStationInfo> stationInfoList = build(listInfoJsonArray, listBaseJsonArray);
        if(CollectionUtils.isNotEmpty(stationInfoList)) {
            List<TStationInfo> existingStationList = lambdaQuery().select(TStationInfo::getStationId).list();
            Set<String> existingStationIds = new HashSet<>();
            for (TStationInfo stationInfo : existingStationList) {
                if (stationInfo.getStationId() != null) {
                    existingStationIds.add(stationInfo.getStationId());
            // 去除stationInfoList中的重复stationId
            Map<String, TStationInfo> stationMap = stationInfoList.stream().filter(item -> StringUtils.isNotEmpty(item.getStationId()))
                    .collect(Collectors.toMap(TStationInfo::getStationId, Function.identity(), (o1, o2) -> o2));
            stationInfoList = new ArrayList<>(stationMap.values());
            // 查询数据库已有数据
            List<TStationInfo> existingStationList = lambdaQuery().in(TStationInfo::getStationId, stationMap.keySet()).list();
            // 转Map,方便查找
            Map<String, TStationInfo> existingMap = existingStationList.stream().collect(Collectors.toMap(TStationInfo::getStationId, Function.identity()));
            List<TStationInfo> insertList = new ArrayList<>();
            List<TStationInfo> updateList = new ArrayList<>();
            for (TStationInfo station : stationInfoList) {
                TStationInfo dbStation = existingMap.get(station.getStationId());
                if (dbStation == null) {
                    // 数据库不存在
                    insertList.add(station);
                } else {
                    // 数据库存在,需要更新;保留数据库主键,否则updateBatchById无法更新
                    station.setId(dbStation.getId());
                    updateList.add(station);
                }
            }
            Set<String> pendingStationIds = new HashSet<>();
            stationInfoList.removeIf(stationInfo -> stationInfo.getStationId() == null || existingStationIds.contains(stationInfo.getStationId()) || !pendingStationIds.add(stationInfo.getStationId()));
            if (CollectionUtils.isNotEmpty(stationInfoList)) {
                saveBatch(stationInfoList);
            // 批量新增
            if (CollectionUtils.isNotEmpty(insertList)) {
                saveBatch(insertList);
            }
            // 批量更新
            if (CollectionUtils.isNotEmpty(updateList)) {
                updateBatchById(updateList);
            }
        }
        log.info("-------1结束同步科士达-电站列表信息----");
ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/util/KsolarUtils.java
@@ -380,5 +380,26 @@
        }
    }
    /**
     * 查询单个电站的发电量和收益
     */
    public static JSONObject getStationEarnDetail(String stationId, String token) {
        try {
            HttpRequest get = HttpUtil.createGet(KSOLAR_URL.concat("/station/detail/earn"));
            get.header("Authorization", "Bearer "+token);
            if(StringUtils.isNotEmpty(stationId)) {
                get.form("stationId", stationId);
            }
            HttpResponse execute = get.execute();
            String body = execute.body();
            JSONObject jsonObject = JSONObject.parseObject(body);
            Object data  = jsonObject.get("data");
            return JSONObject.parseObject(data.toString());
        } catch (Exception e) {
            log.error("电站的电量和收益统计查询-调用第三方接口报错:", e);
            return null;
        }
    }
}
ruoyi-service/ruoyi-other/src/main/resources/mapper/other/EnergyReportMapper.xml
@@ -29,6 +29,16 @@
        ORDER BY earn.save_time DESC, earn.id DESC
    </select>
    <select id="selectPhotovoltaicSummaryPage" resultType="com.ruoyi.other.energyreport.vo.PhotovoltaicReportRow">
        SELECT earn.save_time stat_date,
               COALESCE(SUM(earn.elec_total), 0) generation,
               COALESCE(SUM(earn.earn_total), 0) income
        FROM t_station_earn earn
        <include refid="photovoltaicWhere"/>
        GROUP BY earn.save_time
        ORDER BY earn.save_time DESC
    </select>
    <select id="selectPhotovoltaicList" resultType="com.ruoyi.other.energyreport.vo.PhotovoltaicReportRow">
        SELECT <include refid="photovoltaicColumns"/>
        FROM t_station_earn earn
ruoyi-service/ruoyi-other/src/main/resources/mapper/other/TStationEarnMapper.xml
@@ -2,5 +2,7 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.other.mapper.TStationEarnMapper">
    <select id="selectStationInfoAll" resultType="com.ruoyi.other.api.domain.TStationInfo">
        select * from t_station_info where del_flag = 0 and data_source = 2
    </select>
</mapper>
ruoyi-service/ruoyi-other/src/test/java/com/ruoyi/other/energyreport/service/EnergyReportServiceTest.java
@@ -50,4 +50,19 @@
        verify(mapper).selectPhotovoltaicList(same(query));
    }
    @Test
    void summaryViewUsesDailySummaryQuery() {
        EnergyReportService service = new EnergyReportService(mapper);
        EnergyReportQuery query = new EnergyReportQuery();
        query.setViewMode("summary");
        service.photovoltaicPage(query);
        @SuppressWarnings("unchecked")
        ArgumentCaptor<Page<PhotovoltaicReportRow>> page = ArgumentCaptor.forClass(Page.class);
        verify(mapper).selectPhotovoltaicSummaryPage(page.capture(), same(query));
        assertEquals(1, page.getValue().getCurrent());
        assertEquals(10, page.getValue().getSize());
    }
}