ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TStationCollect.java
New file @@ -0,0 +1,134 @@ package com.ruoyi.other.api.domain; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.time.LocalDateTime; /** * 电站逆变器实体。 */ @Data @TableName("t_station_collect") @ApiModel(value = "TStationCollect对象", description = "电站逆变器") public class TStationCollect implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.AUTO) @ApiModelProperty("主键ID") private Long id; @TableField("platform_id") @ApiModelProperty("所属平台ID(0科士达、1华为、2阳光、3古瑞瓦特)") private Long platformId; @TableField("station_id") @ApiModelProperty("电站ID") private String stationId; @TableField("station_name") @ApiModelProperty("电站名称") private String stationName; @TableField("collect_id") @ApiModelProperty("逆变器ID") private String collectId; @TableField("collect_name") @ApiModelProperty("逆变器名称") private String collectName; @TableField("device_model") @ApiModelProperty("机型型号") private String deviceModel; @TableField("inverter_id") @ApiModelProperty("逆变器SN") private String inverterId; @TableField("installed_capacity") @ApiModelProperty("装机容量(kW)") private String installedCapacity; @TableField("power_num") @ApiModelProperty("装机容量数量") private Integer powerNum; @TableField("province_name") @ApiModelProperty("省") private String provinceName; @TableField("city_name") @ApiModelProperty("市") private String cityName; @TableField("area_name") @ApiModelProperty("区/县") private String areaName; @TableField("address") @ApiModelProperty("详细地址") private String address; @TableField("latitude") @ApiModelProperty("纬度") private String latitude; @TableField("longitude") @ApiModelProperty("经度") private String longitude; @TableField("status") @ApiModelProperty("上网状态(1在线、2离线、3故障)") private String status; @TableField("data_source") @ApiModelProperty("数据来源(1系统创建、2第三方接口)") private Integer dataSource; @TableField("sort_order") @ApiModelProperty("显示顺序") private Integer sortOrder; @TableField("create_by") @ApiModelProperty("创建者") private String createBy; @TableField(value = "create_time", fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty("创建时间") private LocalDateTime createTime; @TableField("sync_time") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty("同步时间") private LocalDateTime syncTime; @TableField("update_by") @ApiModelProperty("更新者") private String updateBy; @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty("更新时间") private LocalDateTime updateTime; @TableField("remark") @ApiModelProperty("备注") private String remark; @TableField("del_flag") @TableLogic(value = "0", delval = "2") @ApiModelProperty("删除标志(0存在、2删除)") private String delFlag; } ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TStationEarn.java
New file @@ -0,0 +1,88 @@ package com.ruoyi.other.api.domain; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; /** * 电站发电量统计实体。 */ @Data @TableName("t_station_earn") @ApiModel(value = "TStationEarn对象", description = "电站发电量统计") public class TStationEarn implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.AUTO) @ApiModelProperty("主键ID") private Long id; @TableField("platform_id") @ApiModelProperty("平台ID,0表示科士达") private Long platformId; @TableField("station_id") @ApiModelProperty("电站ID") private String stationId; @TableField("station_name") @ApiModelProperty("电站名称") private String stationName; @TableField("save_time") @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8") @ApiModelProperty("统计时间") private LocalDate saveTime; @TableField("elec_total") @ApiModelProperty("总发电量") private BigDecimal elecTotal; @TableField("earn_total") @ApiModelProperty("总收益") private BigDecimal earnTotal; @TableField("create_by") @ApiModelProperty("创建者") private String createBy; @TableField(value = "create_time", fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty("创建时间") private LocalDateTime createTime; @TableField("update_by") @ApiModelProperty("更新者") private String updateBy; @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty("更新时间") private LocalDateTime updateTime; @TableField("remark") @ApiModelProperty("备注") private String remark; @TableField("del_flag") @TableLogic(value = "0", delval = "2") @ApiModelProperty("删除标志(0存在、2删除)") private String delFlag; @TableField("data_source") @ApiModelProperty("数据来源(1系统创建、2第三方接口)") private Integer dataSource; } ruoyi-api/ruoyi-api-other/src/main/java/com/ruoyi/other/api/domain/TStationInfo.java
New file @@ -0,0 +1,160 @@ package com.ruoyi.other.api.domain; import com.baomidou.mybatisplus.annotation.FieldFill; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.io.Serializable; import java.math.BigDecimal; import java.time.LocalDateTime; /** * 电站信息实体。 */ @Data @TableName("t_station_info") @ApiModel(value = "TStationInfo对象", description = "电站信息") public class TStationInfo implements Serializable { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.AUTO) @ApiModelProperty("主键ID") private Long id; @TableField("platform_id") @ApiModelProperty("所属平台ID(0科士达、1华为、2阳光、3古瑞瓦特)") private Long platformId; @TableField("station_id") @ApiModelProperty("电站ID") private String stationId; @TableField("station_name") @ApiModelProperty("电站名称") private String stationName; @TableField("station_image") @ApiModelProperty("电站图片地址") private String stationImage; @TableField("station_type") @ApiModelProperty("电站类型(1光伏、2储能)") private String stationType; @TableField("run_status") @ApiModelProperty("运行状态(0正常/在线、1离线、2告警)") private String runStatus; @TableField("installed_capacity") @ApiModelProperty("装机容量(kW)") private BigDecimal installedCapacity; @TableField("realtime_power") @ApiModelProperty("实时功率(W)") private BigDecimal realtimePower; @TableField("device_count") @ApiModelProperty("设备总数") private Integer deviceCount; @TableField("daily_generation") @ApiModelProperty("日发电量(度/kWh)") private BigDecimal dailyGeneration; @TableField("grid_status") @ApiModelProperty("上网状态(0未上网、1已上网)") private String gridStatus; @TableField("data_time") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty("指标数据时间") private LocalDateTime dataTime; @TableField("elec_price") @ApiModelProperty("电价") private String elecPrice; @TableField("contact_name") @ApiModelProperty("联系人") private String contactName; @TableField("phone") @ApiModelProperty("电话") private String phone; @TableField("province_name") @ApiModelProperty("省") private String provinceName; @TableField("city_name") @ApiModelProperty("市") private String cityName; @TableField("area_name") @ApiModelProperty("区/县") private String areaName; @TableField("address") @ApiModelProperty("详细地址") private String address; @TableField("latitude") @ApiModelProperty("纬度") private String latitude; @TableField("longitude") @ApiModelProperty("经度") private String longitude; @TableField("loan_status") @ApiModelProperty("并网状态(1未并网、2并网中、3已并网)") private Integer loanStatus; @TableField("data_source") @ApiModelProperty("数据来源(1系统创建、2第三方接口)") private Integer dataSource; @TableField("sort_order") @ApiModelProperty("显示顺序") private Integer sortOrder; @TableField("create_by") @ApiModelProperty("创建者") private String createBy; @TableField(value = "create_time", fill = FieldFill.INSERT) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty("创建时间") private LocalDateTime createTime; @TableField("sync_time") @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty("同步时间") private LocalDateTime syncTime; @TableField("update_by") @ApiModelProperty("更新者") private String updateBy; @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") @ApiModelProperty("更新时间") private LocalDateTime updateTime; @TableField("remark") @ApiModelProperty("备注") private String remark; @TableField("del_flag") @TableLogic(value = "0", delval = "2") @ApiModelProperty("删除标志(0存在、2删除)") private String delFlag; } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TStationCollectController.java
New file @@ -0,0 +1,62 @@ package com.ruoyi.other.controller; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.page.PageInfo; import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.security.annotation.Logical; import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.other.api.domain.TStationCollect; import com.ruoyi.other.query.StationCollectQuery; import com.ruoyi.other.service.TStationCollectService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.Arrays; @Api(tags = "管理后台-电站逆变器") @RestController @RequestMapping("/station-collect") public class TStationCollectController { @Resource private TStationCollectService stationCollectService; @RequiresPermissions(value = {"/stationCollect/list"}, logical = Logical.OR) @GetMapping("/pageList") @ApiOperation("分页查询逆变器") public AjaxResult<PageInfo<TStationCollect>> pageList(StationCollectQuery query) { return AjaxResult.success(stationCollectService.pageList(query)); } @RequiresPermissions(value = {"/stationCollect/add"}, logical = Logical.OR) @PostMapping("/add") @ApiOperation("添加逆变器") @Log(title = "【电站逆变器】新增", businessType = BusinessType.INSERT) public AjaxResult add(@RequestBody TStationCollect stationCollect) { return stationCollectService.addStationCollect(stationCollect) ? AjaxResult.success() : AjaxResult.error("新增失败"); } @RequiresPermissions(value = {"/stationCollect/update"}, logical = Logical.OR) @PutMapping("/edit") @ApiOperation("编辑逆变器") @Log(title = "【电站逆变器】编辑", businessType = BusinessType.UPDATE) public AjaxResult edit(@RequestBody TStationCollect stationCollect) { return stationCollectService.updateStationCollect(stationCollect) ? AjaxResult.success() : AjaxResult.error("编辑失败"); } @RequiresPermissions(value = {"/stationCollect/del"}, logical = Logical.OR) @DeleteMapping("/delete") @ApiOperation("删除逆变器") @Log(title = "【电站逆变器】删除", businessType = BusinessType.DELETE) public AjaxResult delete(@RequestBody Long[] ids) { if (ids == null || ids.length == 0) return AjaxResult.error("请选择需要删除的数据"); return stationCollectService.removeByIds(Arrays.asList(ids)) ? AjaxResult.success() : AjaxResult.error("删除失败"); } @RequiresPermissions(value = {"/stationCollect/detail"}, logical = Logical.OR) @GetMapping("/detail/{id}") @ApiOperation("查询逆变器详情") public AjaxResult<TStationCollect> detail(@PathVariable Long id) { TStationCollect stationCollect = stationCollectService.getStationCollectDetail(id); return stationCollect == null ? AjaxResult.error("逆变器记录不存在") : AjaxResult.success(stationCollect); } } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TStationEarnController.java
New file @@ -0,0 +1,87 @@ package com.ruoyi.other.controller; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; import com.ruoyi.common.core.utils.WebUtils; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.page.PageInfo; import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.security.annotation.Logical; import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.other.api.domain.TStationEarn; 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.vo.StationEarnExportVO; import com.ruoyi.other.vo.StationEarnOverviewVO; import com.ruoyi.other.vo.StationEarnStatisticsVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.apache.poi.ss.usermodel.Workbook; import org.springframework.beans.BeanUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; @Api(tags = "管理后台-电站收益统计") @RestController @RequestMapping("/station-earn") public class TStationEarnController { @Resource private TStationEarnService stationEarnService; @RequiresPermissions(value = {"/stationEarn/list"}, logical = Logical.OR) @GetMapping("/pageList") @ApiOperation("分页查询电站收益") public AjaxResult<PageInfo<TStationEarn>> pageList(StationEarnQuery query) { return AjaxResult.success(stationEarnService.pageList(query)); } @RequiresPermissions(value = {"/stationEarn/list"}, logical = Logical.OR) @GetMapping("/statistics") @ApiOperation("前端发电量分析统计") public AjaxResult<StationEarnStatisticsVO> statistics(StationEarnStatisticsQuery query) { return AjaxResult.success(stationEarnService.statistics(query)); } @RequiresPermissions(value = {"/stationEarn/list"}, logical = Logical.OR) @GetMapping("/generationOverview") @ApiOperation("今日、本月和本年发电量概览") public AjaxResult<StationEarnOverviewVO> generationOverview(StationEarnOverviewQuery query) { return AjaxResult.success(stationEarnService.generationOverview(query)); } @RequiresPermissions(value = {"/stationEarn/export"}, logical = Logical.OR) @GetMapping("/export") @ApiOperation("导出电站收益") @Log(title = "【电站收益统计】导出", businessType = BusinessType.EXPORT) public void export(StationEarnQuery query) throws Exception { List<TStationEarn> stationEarnList = stationEarnService.exportList(query == null ? new StationEarnQuery() : query); List<StationEarnExportVO> exportList = new ArrayList<>(stationEarnList.size()); for (TStationEarn stationEarn : stationEarnList) { StationEarnExportVO exportVO = new StationEarnExportVO(); BeanUtils.copyProperties(stationEarn, exportVO); exportVO.buildPlatformName(stationEarn.getPlatformId()); exportVO.setSaveTime(stationEarn.getSaveTime() == null ? "" : stationEarn.getSaveTime().toString()); exportList.add(exportVO); } Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams(), StationEarnExportVO.class, exportList); HttpServletResponse response = WebUtils.response(); response.setContentType("application/vnd.ms-excel;charset=UTF-8"); response.setCharacterEncoding("utf-8"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("电站收益统计.xls", "UTF-8")); try (ServletOutputStream outputStream = response.getOutputStream()) { workbook.write(outputStream); outputStream.flush(); } finally { workbook.close(); } } } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/controller/TStationInfoController.java
New file @@ -0,0 +1,67 @@ package com.ruoyi.other.controller; import com.ruoyi.common.core.web.domain.AjaxResult; import com.ruoyi.common.core.web.page.PageInfo; import com.ruoyi.common.log.annotation.Log; import com.ruoyi.common.log.enums.BusinessType; import com.ruoyi.common.security.annotation.Logical; import com.ruoyi.common.security.annotation.RequiresPermissions; import com.ruoyi.other.api.domain.TStationInfo; import com.ruoyi.other.query.StationInfoQuery; import com.ruoyi.other.service.TStationInfoService; import com.ruoyi.other.vo.StationInfoStatusVO; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import java.util.Arrays; @Api(tags = "管理后台-电站信息") @RestController @RequestMapping("/station-info") public class TStationInfoController { @Resource private TStationInfoService stationInfoService; @GetMapping("/pageList") @ApiOperation("分页查询电站信息") public AjaxResult<PageInfo<TStationInfo>> pageList(StationInfoQuery query) { return AjaxResult.success(stationInfoService.pageList(query)); } @RequiresPermissions(value = {"/stationInfo/add"}, logical = Logical.OR) @PostMapping("/add") @ApiOperation("新增电站信息") @Log(title = "【电站信息】新增", businessType = BusinessType.INSERT) public AjaxResult add(@RequestBody TStationInfo info) { return stationInfoService.addStationInfo(info) ? AjaxResult.success() : AjaxResult.error("新增失败"); } @RequiresPermissions(value = {"/stationInfo/update"}, logical = Logical.OR) @PutMapping("/edit") @ApiOperation("编辑电站信息") @Log(title = "【电站信息】编辑", businessType = BusinessType.UPDATE) public AjaxResult edit(@RequestBody TStationInfo info) { return stationInfoService.updateStationInfo(info) ? AjaxResult.success() : AjaxResult.error("编辑失败"); } @RequiresPermissions(value = {"/stationInfo/del"}, logical = Logical.OR) @DeleteMapping("/delete") @ApiOperation("删除电站信息") @Log(title = "【电站信息】删除", businessType = BusinessType.DELETE) public AjaxResult delete(@RequestBody Long[] ids) { if (ids == null || ids.length == 0) return AjaxResult.error("请选择需要删除的数据"); return stationInfoService.removeByIds(Arrays.asList(ids)) ? AjaxResult.success() : AjaxResult.error("删除失败"); } /** * 调用第三方接口获取实时功率和电站状态 */ @GetMapping("/getStationStatus") @ApiOperation("获取电站状态") public AjaxResult<StationInfoStatusVO> getStationStatus() { return AjaxResult.success(stationInfoService.getStationStatus()); } @PostMapping("/syncKsolarDataTask") @ApiOperation("手动同步数据") public void syncKsolarDataTask() { stationInfoService.syncKsolarDataTask(); } } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/TStationCollectMapper.java
New file @@ -0,0 +1,10 @@ package com.ruoyi.other.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.other.api.domain.TStationCollect; /** * 电站逆变器 Mapper。 */ public interface TStationCollectMapper extends BaseMapper<TStationCollect> { } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/TStationEarnMapper.java
New file @@ -0,0 +1,10 @@ package com.ruoyi.other.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.other.api.domain.TStationEarn; /** * 电站发电量统计 Mapper。 */ public interface TStationEarnMapper extends BaseMapper<TStationEarn> { } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/mapper/TStationInfoMapper.java
New file @@ -0,0 +1,10 @@ package com.ruoyi.other.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.ruoyi.other.api.domain.TStationInfo; /** * 电站信息 Mapper。 */ public interface TStationInfoMapper extends BaseMapper<TStationInfo> { } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/query/StationCollectQuery.java
New file @@ -0,0 +1,17 @@ package com.ruoyi.other.query; import com.ruoyi.common.core.web.page.BasePage; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("电站逆变器分页查询参数") public class StationCollectQuery extends BasePage { @ApiModelProperty("所属平台ID") private Long platformId; @ApiModelProperty("电站名称") private String stationName; @ApiModelProperty("逆变器名称") private String collectName; @ApiModelProperty("机型型号") private String deviceModel; @ApiModelProperty("逆变器SN") private String inverterId; @ApiModelProperty("状态") private String status; } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/query/StationEarnOverviewQuery.java
New file @@ -0,0 +1,16 @@ package com.ruoyi.other.query; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("电站发电量概览查询参数") public class StationEarnOverviewQuery { @ApiModelProperty("所属平台ID,不传表示全部平台") private Long platformId; @ApiModelProperty("电站ID,不传表示全部电站") private String stationId; } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/query/StationEarnQuery.java
New file @@ -0,0 +1,20 @@ package com.ruoyi.other.query; import com.ruoyi.common.core.web.page.BasePage; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDate; @Data @ApiModel("电站收益分页查询参数") public class StationEarnQuery extends BasePage { @ApiModelProperty("所属平台ID") private Long platformId; @ApiModelProperty("电站ID") private String stationId; @DateTimeFormat(pattern = "yyyy-MM-dd") @ApiModelProperty("统计开始日期,yyyy-MM-dd") private LocalDate startSaveTime; @DateTimeFormat(pattern = "yyyy-MM-dd") @ApiModelProperty("统计结束日期,yyyy-MM-dd") private LocalDate endSaveTime; } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/query/StationEarnStatisticsQuery.java
New file @@ -0,0 +1,30 @@ package com.ruoyi.other.query; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDate; @Data @ApiModel("电站发电量统计查询参数") public class StationEarnStatisticsQuery { @ApiModelProperty("统计维度:day按天、month按月、year按年") private String dimension = "day"; @ApiModelProperty("所属平台ID,不传表示全部平台") private Long platformId; @ApiModelProperty("电站ID,不传表示全部电站") private String stationId; @DateTimeFormat(pattern = "yyyy-MM-dd") @ApiModelProperty("按天统计开始日期,yyyy-MM-dd") private LocalDate startSaveTime; @DateTimeFormat(pattern = "yyyy-MM-dd") @ApiModelProperty("按天统计结束日期,yyyy-MM-dd") private LocalDate endSaveTime; } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/query/StationInfoQuery.java
New file @@ -0,0 +1,16 @@ package com.ruoyi.other.query; import com.ruoyi.common.core.web.page.BasePage; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel("电站信息分页查询参数") public class StationInfoQuery extends BasePage { @ApiModelProperty("所属平台ID") private Long platformId; @ApiModelProperty("电站名称") private String stationName; @ApiModelProperty("电站类型") private String stationType; @ApiModelProperty("运行状态") private String runStatus; @ApiModelProperty("上网状态") private String gridStatus; } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TStationCollectService.java
New file @@ -0,0 +1,23 @@ package com.ruoyi.other.service; import com.alibaba.fastjson.JSONArray; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.common.core.web.page.PageInfo; import com.ruoyi.other.api.domain.TStationCollect; import com.ruoyi.other.query.StationCollectQuery; /** * 电站逆变器服务。 */ public interface TStationCollectService extends IService<TStationCollect> { boolean addStationCollect(TStationCollect stationCollect); boolean saveCollectBaseList(JSONArray collectBaseList); PageInfo<TStationCollect> pageList(StationCollectQuery query); boolean updateStationCollect(TStationCollect stationCollect); TStationCollect getStationCollectDetail(Long id); } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TStationEarnService.java
New file @@ -0,0 +1,34 @@ package com.ruoyi.other.service; import com.alibaba.fastjson.JSONArray; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.common.core.web.page.PageInfo; import com.ruoyi.other.api.domain.TStationEarn; import com.ruoyi.other.query.StationEarnQuery; import com.ruoyi.other.query.StationEarnOverviewQuery; import com.ruoyi.other.query.StationEarnStatisticsQuery; import com.ruoyi.other.vo.StationEarnOverviewVO; import com.ruoyi.other.vo.StationEarnStatisticsVO; import java.time.LocalDate; import java.util.List; /** * 电站发电量统计服务。 */ public interface TStationEarnService extends IService<TStationEarn> { boolean addStationEarn(TStationEarn stationEarn); boolean saveStationEarnList(JSONArray stationEarnList); LocalDate getMaxSaveTime(); PageInfo<TStationEarn> pageList(StationEarnQuery query); List<TStationEarn> exportList(StationEarnQuery query); StationEarnStatisticsVO statistics(StationEarnStatisticsQuery query); StationEarnOverviewVO generationOverview(StationEarnOverviewQuery query); } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/TStationInfoService.java
New file @@ -0,0 +1,34 @@ package com.ruoyi.other.service; import com.alibaba.fastjson.JSONArray; import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.other.api.domain.TStationInfo; import com.ruoyi.common.core.web.page.PageInfo; import com.ruoyi.other.query.StationInfoQuery; import com.ruoyi.other.vo.StationInfoStatusVO; import org.springframework.transaction.annotation.Transactional; import java.util.List; /** * 电站信息服务。 */ public interface TStationInfoService extends IService<TStationInfo> { boolean addStationInfo(TStationInfo stationInfo); PageInfo<TStationInfo> pageList(StationInfoQuery query); boolean updateStationInfo(TStationInfo stationInfo); /** * 每天同步科士达数据到数据库 */ void syncKsolarDataTask(); /** * 实时获取电站状态 */ StationInfoStatusVO getStationStatus(); } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TStationCollectServiceImpl.java
New file @@ -0,0 +1,280 @@ package com.ruoyi.other.service.impl; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 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.TStationCollect; import com.ruoyi.other.api.domain.TStationInfo; import com.ruoyi.other.mapper.TStationCollectMapper; import com.ruoyi.other.mapper.TStationInfoMapper; import com.ruoyi.other.query.StationCollectQuery; import com.ruoyi.other.service.TStationCollectService; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.math.BigDecimal; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; /** * 电站逆变器服务实现。 */ @Service public class TStationCollectServiceImpl extends ServiceImpl<TStationCollectMapper, TStationCollect> implements TStationCollectService { @Resource private TStationInfoMapper stationInfoMapper; @Override @Transactional(rollbackFor = Exception.class) public boolean addStationCollect(TStationCollect stationCollect) { validate(stationCollect); stationCollect.setCollectId("1"+System.currentTimeMillis()); stationCollect.setDataSource(1); fillDefaults(stationCollect); stationCollect.setId(null); stationCollect.setCreateTime(LocalDateTime.now()); stationCollect.setUpdateTime(LocalDateTime.now()); return save(stationCollect); } @Override public PageInfo<TStationCollect> pageList(StationCollectQuery query) { if (query == null) query = new StationCollectQuery(); PageInfo<TStationCollect> page = new PageInfo<>(query.getPageCurr(), query.getPageSize()); lambdaQuery() .eq(query.getPlatformId() != null, TStationCollect::getPlatformId, query.getPlatformId()) .like(StringUtils.isNotBlank(query.getStationName()), TStationCollect::getStationName, query.getStationName()) .like(StringUtils.isNotBlank(query.getCollectName()), TStationCollect::getCollectName, query.getCollectName()) .like(StringUtils.isNotBlank(query.getDeviceModel()), TStationCollect::getDeviceModel, query.getDeviceModel()) .like(StringUtils.isNotBlank(query.getInverterId()), TStationCollect::getInverterId, query.getInverterId()) .eq(StringUtils.isNotBlank(query.getStatus()), TStationCollect::getStatus, query.getStatus()) .orderByAsc(TStationCollect::getSortOrder).orderByDesc(TStationCollect::getCreateTime).page(page); fillStationAddress(page.getRecords()); return page; } @Override public TStationCollect getStationCollectDetail(Long id) { if (id == null) { return null; } TStationCollect stationCollect = getById(id); if (stationCollect != null) { List<TStationCollect> stationCollectList = new ArrayList<>(1); stationCollectList.add(stationCollect); fillStationAddress(stationCollectList); } return stationCollect; } private void fillStationAddress(List<TStationCollect> stationCollectList) { if (stationCollectList == null || stationCollectList.isEmpty()) { return; } Set<String> stationIds = stationCollectList.stream() .map(TStationCollect::getStationId) .filter(StringUtils::isNotBlank) .collect(Collectors.toSet()); if (stationIds.isEmpty()) { return; } List<TStationInfo> stationInfoList = stationInfoMapper.selectList( new LambdaQueryWrapper<TStationInfo>() .select(TStationInfo::getStationId, TStationInfo::getProvinceName, TStationInfo::getCityName, TStationInfo::getAreaName, TStationInfo::getAddress) .in(TStationInfo::getStationId, stationIds)); Map<String, TStationInfo> stationInfoMap = stationInfoList.stream() .filter(item -> StringUtils.isNotBlank(item.getStationId())) .collect(Collectors.toMap(TStationInfo::getStationId, Function.identity(), (first, ignored) -> first)); for (TStationCollect stationCollect : stationCollectList) { TStationInfo stationInfo = stationInfoMap.get(stationCollect.getStationId()); if (stationInfo != null) { stationCollect.setProvinceName(stationInfo.getProvinceName()); stationCollect.setCityName(stationInfo.getCityName()); stationCollect.setAreaName(stationInfo.getAreaName()); stationCollect.setAddress(stationInfo.getAddress()); } } } @Override @Transactional(rollbackFor = Exception.class) public boolean updateStationCollect(TStationCollect stationCollect) { if (stationCollect == null || stationCollect.getId() == null) { throw new ServiceException("逆变器记录ID不能为空"); } if (getById(stationCollect.getId()) == null) { throw new ServiceException("逆变器记录不存在"); } validate(stationCollect); if (lambdaQuery().eq(TStationCollect::getCollectId, stationCollect.getCollectId()) .ne(TStationCollect::getId, stationCollect.getId()).count() > 0) { throw new ServiceException("逆变器ID已存在"); } stationCollect.setCreateBy(null); stationCollect.setCreateTime(null); stationCollect.setDelFlag(null); stationCollect.setUpdateTime(LocalDateTime.now()); return updateById(stationCollect); } /** * 将第三方逆变器基础数据转换为实体并批量保存。 */ @Override @Transactional(rollbackFor = Exception.class) public boolean saveCollectBaseList(JSONArray collectBaseList) { if (collectBaseList == null || collectBaseList.isEmpty()) { return false; } Set<String> existingKeys = getExistingCollectKeys(); // 数据库中存在的所有逆变器ID List<TStationCollect> stationCollectList = new ArrayList<>(collectBaseList.size()); for (Object item : collectBaseList) { JSONObject jsonObject = JSONObject.parseObject(item.toString()); TStationCollect stationCollect = buildStationCollect(jsonObject); if (existingKeys.contains(stationCollect.getCollectId())) { continue; } stationCollectList.add(stationCollect); } return !stationCollectList.isEmpty() && saveBatch(stationCollectList); } private TStationCollect buildStationCollect(JSONObject jsonObject) { String stationId = jsonObject.getString("stationId"); String stationName = jsonObject.getString("stationName"); String collectName = jsonObject.getString("collectName"); TStationCollect stationCollect = new TStationCollect(); stationCollect.setPlatformId(0L); stationCollect.setStationId(stationId); stationCollect.setStationName(stationName); stationCollect.setCollectId(jsonObject.getString("collectId")); stationCollect.setCollectName(collectName); stationCollect.setDeviceModel(jsonObject.getString("deviceModel")); stationCollect.setInverterId(jsonObject.getString("inverterId")); stationCollect.setInstalledCapacity(jsonObject.getString("capacity")); stationCollect.setPowerNum(parsePowerNum(jsonObject.getString("powerNum"))); stationCollect.setProvinceName(jsonObject.getString("province")); stationCollect.setCityName(jsonObject.getString("city")); stationCollect.setAreaName(jsonObject.getString("district")); stationCollect.setAddress(jsonObject.getString("address")); stationCollect.setLatitude(jsonObject.getString("lat")); stationCollect.setLongitude(jsonObject.getString("lon")); stationCollect.setDataSource(2); stationCollect.setSyncTime(LocalDateTime.now()); stationCollect.setCreateTime(parseDateTime(jsonObject.getString("saveTime"))); stationCollect.setUpdateTime(LocalDateTime.now()); fillDefaults(stationCollect); return stationCollect; } private Set<String> getExistingCollectKeys() { List<TStationCollect> existingList = lambdaQuery().select(TStationCollect::getCollectId).list(); Set<String> existingKeys = new HashSet<>(); for (TStationCollect stationCollect : existingList) { existingKeys.add(stationCollect.getCollectId()); } return existingKeys; } private void validate(TStationCollect stationCollect) { if (stationCollect == null) { throw new ServiceException("电站逆变器参数不能为空"); } if (stationCollect.getStationId() == null) { throw new ServiceException("电站ID不能为空"); } if (StringUtils.isBlank(stationCollect.getStationName())) { throw new ServiceException("电站名称不能为空"); } if (StringUtils.isBlank(stationCollect.getCollectName())) { throw new ServiceException("逆变器名称不能为空"); } } private void fillDefaults(TStationCollect stationCollect) { stationCollect.setPlatformId(stationCollect.getPlatformId() == null ? 0L : stationCollect.getPlatformId()); stationCollect.setPowerNum(stationCollect.getPowerNum() == null ? 0 : stationCollect.getPowerNum()); stationCollect.setStatus(StringUtils.isBlank(stationCollect.getStatus()) ? "0" : stationCollect.getStatus()); stationCollect.setSortOrder(stationCollect.getSortOrder() == null ? 0 : stationCollect.getSortOrder()); stationCollect.setCreateBy(StringUtils.defaultString(stationCollect.getCreateBy())); stationCollect.setUpdateBy(StringUtils.defaultString(stationCollect.getUpdateBy())); stationCollect.setDelFlag("0"); } private Long parseLong(String value) { if (StringUtils.isBlank(value)) { return null; } try { return Long.valueOf(value); } catch (NumberFormatException exception) { return null; } } private BigDecimal parseBigDecimal(String value) { if (StringUtils.isBlank(value)) { return BigDecimal.ZERO; } try { return new BigDecimal(value); } catch (NumberFormatException exception) { return BigDecimal.ZERO; } } private Integer parsePowerNum(String value) { if (StringUtils.isBlank(value)) { return 0; } String number = value.replaceAll("[^0-9.]", ""); if (StringUtils.isBlank(number)) { return 0; } try { return new BigDecimal(number).intValue(); } catch (NumberFormatException exception) { return 0; } } private LocalDateTime parseDateTime(String value) { if (StringUtils.isBlank(value)) { return null; } try { return LocalDateTime.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); } catch (DateTimeParseException exception) { return null; } } private String firstNotBlank(String preferred, String fallback) { return StringUtils.isNotBlank(preferred) ? preferred : fallback; } } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TStationEarnServiceImpl.java
New file @@ -0,0 +1,335 @@ package com.ruoyi.other.service.impl; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 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.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.vo.StationEarnStatisticsItemVO; import com.ruoyi.other.vo.StationEarnStatisticsVO; import com.ruoyi.other.vo.StationEarnOverviewVO; import org.apache.commons.collections4.CollectionUtils; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; /** * 电站发电量统计服务实现。 */ @Service public class TStationEarnServiceImpl extends ServiceImpl<TStationEarnMapper, TStationEarn> implements TStationEarnService { @Override @Transactional(rollbackFor = Exception.class) public boolean addStationEarn(TStationEarn stationEarn) { validate(stationEarn); stationEarn.setId(null); stationEarn.setCreateTime(LocalDateTime.now()); stationEarn.setUpdateTime(LocalDateTime.now()); return save(stationEarn); } /** * 将第三方电站收益数据转换为实体并批量保存。 */ @Override @Transactional(rollbackFor = Exception.class) public boolean saveStationEarnList(JSONArray stationEarnList) { if (stationEarnList == null || stationEarnList.isEmpty()) { return false; } Set<String> existingKeys = getExistingEarnKeys(); Set<String> pendingKeys = new HashSet<>(); List<TStationEarn> earnList = new ArrayList<>(stationEarnList.size()); for (Object item : stationEarnList) { JSONObject jsonObject = JSONObject.parseObject(item.toString()); TStationEarn stationEarn = buildStationEarn(jsonObject); if (stationEarn == null) { continue; } String earnKey = buildEarnKey(stationEarn); if (existingKeys.contains(earnKey) || !pendingKeys.add(earnKey)) { continue; } earnList.add(stationEarn); } if(CollectionUtils.isNotEmpty(earnList)) { List<List<TStationEarn>> earnAllList = Lists.partition(earnList, 500); earnAllList.forEach(this::saveBatch); } return true; } /** * 查询发电量统计记录中的最大统计日期。 * * @return 最大统计日期,无记录时返回 null */ @Override public LocalDate getMaxSaveTime() { TStationEarn latest = lambdaQuery() .select(TStationEarn::getSaveTime) .isNotNull(TStationEarn::getSaveTime) .orderByDesc(TStationEarn::getSaveTime) .last("LIMIT 1") .one(); return latest == null ? null : latest.getSaveTime(); } @Override 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)); return page; } @Override public List<TStationEarn> exportList(StationEarnQuery query) { return list(buildQueryWrapper(query)); } @Override public StationEarnStatisticsVO statistics(StationEarnStatisticsQuery query) { if (query == null) { query = new StationEarnStatisticsQuery(); } String dimension = StringUtils.isBlank(query.getDimension()) ? "day" : query.getDimension().toLowerCase(); LocalDate today = LocalDate.now(); LocalDate startDate = null; LocalDate endDate = null; if ("day".equals(dimension)) { startDate = query.getStartSaveTime(); endDate = query.getEndSaveTime(); if (startDate == null || endDate == null) { throw new ServiceException("按天统计时开始日期和结束日期不能为空"); } if (startDate.isAfter(endDate)) { throw new ServiceException("开始日期不能晚于结束日期"); } } else if ("month".equals(dimension)) { startDate = today.withDayOfYear(1); endDate = today; } else if (!"year".equals(dimension)) { throw new ServiceException("统计维度仅支持day、month、year"); } LambdaQueryWrapper<TStationEarn> wrapper = new LambdaQueryWrapper<TStationEarn>() .select(TStationEarn::getSaveTime, TStationEarn::getElecTotal, TStationEarn::getEarnTotal) .eq(query.getPlatformId() != null, TStationEarn::getPlatformId, query.getPlatformId()) .eq(StringUtils.isNotBlank(query.getStationId()), TStationEarn::getStationId, query.getStationId()) .ge(startDate != null, TStationEarn::getSaveTime, startDate) .le(endDate != null, TStationEarn::getSaveTime, endDate) .isNotNull(TStationEarn::getSaveTime) .orderByAsc(TStationEarn::getSaveTime); List<TStationEarn> records = list(wrapper); Map<String, BigDecimal[]> grouped = createStatisticsGroups(dimension, startDate, endDate); for (TStationEarn record : records) { String label = statisticsLabel(dimension, record.getSaveTime()); BigDecimal[] values = grouped.computeIfAbsent(label, key -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO}); values[0] = values[0].add(defaultZero(record.getElecTotal())); values[1] = values[1].add(defaultZero(record.getEarnTotal())); } BigDecimal totalGeneration = BigDecimal.ZERO; BigDecimal totalEarn = BigDecimal.ZERO; List<StationEarnStatisticsItemVO> items = new ArrayList<>(grouped.size()); for (Map.Entry<String, BigDecimal[]> entry : grouped.entrySet()) { totalGeneration = totalGeneration.add(entry.getValue()[0]); totalEarn = totalEarn.add(entry.getValue()[1]); items.add(new StationEarnStatisticsItemVO(entry.getKey(), entry.getValue()[0], entry.getValue()[1])); } StationEarnStatisticsVO result = new StationEarnStatisticsVO(); result.setDimension(dimension); result.setTotalGeneration(totalGeneration); result.setTotalEarn(totalEarn); result.setItems(items); return result; } @Override public StationEarnOverviewVO generationOverview(StationEarnOverviewQuery query) { if (query == null) { query = new StationEarnOverviewQuery(); } LocalDate today = LocalDate.now(); LocalDate yearStart = today.withDayOfYear(1); LocalDate monthStart = today.withDayOfMonth(1); List<TStationEarn> records = list(new LambdaQueryWrapper<TStationEarn>() .select(TStationEarn::getSaveTime, TStationEarn::getElecTotal) .eq(query.getPlatformId() != null, TStationEarn::getPlatformId, query.getPlatformId()) .eq(StringUtils.isNotBlank(query.getStationId()), TStationEarn::getStationId, query.getStationId()) .between(TStationEarn::getSaveTime, yearStart, today)); BigDecimal todayGeneration = BigDecimal.ZERO; BigDecimal monthGeneration = BigDecimal.ZERO; BigDecimal yearGeneration = BigDecimal.ZERO; for (TStationEarn record : records) { BigDecimal generation = defaultZero(record.getElecTotal()); yearGeneration = yearGeneration.add(generation); if (!record.getSaveTime().isBefore(monthStart)) { monthGeneration = monthGeneration.add(generation); } if (today.equals(record.getSaveTime())) { todayGeneration = todayGeneration.add(generation); } } StationEarnOverviewVO result = new StationEarnOverviewVO(); result.setTodayGeneration(todayGeneration); result.setMonthGeneration(monthGeneration); result.setYearGeneration(yearGeneration.divide(new BigDecimal("10000"), 4, RoundingMode.HALF_UP) .stripTrailingZeros()); return result; } private Map<String, BigDecimal[]> createStatisticsGroups(String dimension, LocalDate startDate, LocalDate endDate) { Map<String, BigDecimal[]> groups = new LinkedHashMap<>(); if ("day".equals(dimension)) { for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) { groups.put(date.toString(), new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO}); } } else if ("month".equals(dimension)) { for (LocalDate date = startDate.withDayOfMonth(1); !date.isAfter(endDate); date = date.plusMonths(1)) { groups.put(date.getMonthValue() + "月", new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO}); } } return groups; } private String statisticsLabel(String dimension, LocalDate saveTime) { if ("day".equals(dimension)) { return saveTime.toString(); } if ("month".equals(dimension)) { return saveTime.getMonthValue() + "月"; } return String.valueOf(saveTime.getYear()); } private LambdaQueryWrapper<TStationEarn> buildQueryWrapper(StationEarnQuery query) { return new LambdaQueryWrapper<TStationEarn>() .eq(query.getPlatformId() != null, TStationEarn::getPlatformId, query.getPlatformId()) .eq(StringUtils.isNotBlank(query.getStationId()), TStationEarn::getStationId, query.getStationId()) .ge(query.getStartSaveTime() != null, TStationEarn::getSaveTime, query.getStartSaveTime()) .le(query.getEndSaveTime() != null, TStationEarn::getSaveTime, query.getEndSaveTime()) .orderByDesc(TStationEarn::getSaveTime) .orderByDesc(TStationEarn::getCreateTime); } private TStationEarn buildStationEarn(JSONObject jsonObject) { String stationId = jsonObject.getString("stationId"); LocalDate saveTime = parseSaveTime(jsonObject.getString("saveTime")); if (StringUtils.isBlank(stationId) || saveTime == null) { return null; } LocalDateTime now = LocalDateTime.now(); TStationEarn stationEarn = new TStationEarn(); stationEarn.setPlatformId(0L); stationEarn.setStationId(stationId); stationEarn.setStationName(jsonObject.getString("stationName")); stationEarn.setSaveTime(saveTime); stationEarn.setEarnTotal(parseBigDecimal(jsonObject.getString("earnTotal"))); stationEarn.setElecTotal(parseBigDecimal(jsonObject.getString("elecTotal"))); stationEarn.setDataSource(2); stationEarn.setCreateBy(""); stationEarn.setUpdateBy(""); stationEarn.setCreateTime(now); stationEarn.setUpdateTime(now); stationEarn.setDelFlag("0"); return stationEarn; } private Set<String> getExistingEarnKeys() { List<TStationEarn> existingList = lambdaQuery().select(TStationEarn::getStationId, TStationEarn::getSaveTime).list(); Set<String> existingKeys = new HashSet<>(); for (TStationEarn stationEarn : existingList) { if (StringUtils.isNotBlank(stationEarn.getStationId()) && stationEarn.getSaveTime() != null) { existingKeys.add(buildEarnKey(stationEarn)); } } return existingKeys; } private String buildEarnKey(TStationEarn stationEarn) { return stationEarn.getStationId() + "|" + stationEarn.getSaveTime(); } private void validate(TStationEarn stationEarn) { if (stationEarn == null) { throw new ServiceException("发电量统计参数不能为空"); } if (stationEarn.getSaveTime() == null) { throw new ServiceException("统计时间不能为空"); } } private BigDecimal defaultZero(BigDecimal value) { return value == null ? BigDecimal.ZERO : value; } private BigDecimal parseBigDecimal(String value) { if (StringUtils.isBlank(value)) { return BigDecimal.ZERO; } try { return new BigDecimal(value); } catch (NumberFormatException exception) { return BigDecimal.ZERO; } } private LocalDate parseSaveTime(String value) { if (StringUtils.isBlank(value)) { return null; } DateTimeFormatter[] formatters = { DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"), DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss") }; for (DateTimeFormatter formatter : formatters) { try { return LocalDateTime.parse(value, formatter).toLocalDate(); } catch (DateTimeParseException ignored) { // 尝试下一个时间格式 } } try { return LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd")); } catch (DateTimeParseException exception) { return null; } } } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/service/impl/TStationInfoServiceImpl.java
New file @@ -0,0 +1,337 @@ package com.ruoyi.other.service.impl; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; 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.TStationInfo; import com.ruoyi.other.mapper.TStationInfoMapper; import com.ruoyi.other.service.TStationCollectService; import com.ruoyi.other.service.TStationEarnService; import com.ruoyi.other.service.TStationInfoService; import com.ruoyi.other.query.StationInfoQuery; import com.ruoyi.other.util.KsolarUtils; import com.ruoyi.other.vo.StationInfoStatusVO; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; /** * 电站信息服务实现。 */ @Service @Slf4j public class TStationInfoServiceImpl extends ServiceImpl<TStationInfoMapper, TStationInfo> implements TStationInfoService { @Autowired private TStationCollectService collectService; @Autowired private TStationEarnService stationEarnService; /** * 每天同步科士达数据到数据库 */ @Transactional(rollbackFor = Exception.class) public void syncKsolarDataTask() { String token = KsolarUtils.token(); JSONObject statusJsonObj = KsolarUtils.getListStatus(token); log.info("-------1开始同步科士达-电站列表信息----"); // 电站列表 JSONArray listInfoJsonArray = KsolarUtils.getStationListInfo(1, 1000, token); // 电站基本信息列表 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()); } } 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); } } log.info("-------1结束同步科士达-电站列表信息----"); log.info("-------2开始同步科士达-逆变器列表----"); // 逆变器列表 JSONArray collectBaseList = KsolarUtils.getCollectBaseList(1, 1000, token); collectService.saveCollectBaseList(collectBaseList); log.info("-------2结束同步科士达-逆变器列表----"); log.info("-------3开始同步科士达-电站的电量和收益统计查询----"); LocalDate startDate = stationEarnService.getMaxSaveTime(); String startDateStr = ""; String endDateStr = ""; if(Objects.nonNull(startDate)) { DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd"); // String dateStr = startDate.plusDays(1).format(formatter); String dateStr = startDate.format(formatter); startDateStr = dateStr + " 00:00:00"; endDateStr = LocalDateTime.now().format(formatter); } JSONArray stationEarnList = KsolarUtils.getStationElecList(startDateStr, endDateStr, token); stationEarnService.saveStationEarnList(stationEarnList); log.info("-------3结束同步科士达-电站的电量和收益统计查询----"); } /** * 根据电站列表信息和电站基础信息批量构建电站对象。 * 两个数组通过 stationId 进行关联。 */ public List<TStationInfo> build(JSONArray listInfoJsonArray, JSONArray listBaseJsonArray) { if (listInfoJsonArray == null || listInfoJsonArray.isEmpty()) { log.error("电站列表信息获取第三方API数据为空!"); return null; } Map<String, JSONObject> baseMap = buildBaseMap(listBaseJsonArray); List<TStationInfo> stationInfoList = new ArrayList<>(listInfoJsonArray.size()); for (Object item : listInfoJsonArray) { JSONObject info = JSONObject.parseObject(item.toString()); String stationId = info.getString("stationId"); if (StringUtils.isBlank(stationId)) { log.error("电站列表信息中的stationId不能为空!"); continue; } stationInfoList.add(buildStationInfo(info, baseMap.get(stationId))); } return stationInfoList; } private TStationInfo buildStationInfo(JSONObject info, JSONObject base) { String stationId = info.getString("stationId"); TStationInfo stationInfo = new TStationInfo(); stationInfo.setPlatformId(0L); stationInfo.setStationId(stationId); stationInfo.setStationName(info.getString("stationName")); stationInfo.setStationType(info.getString("stationType")); stationInfo.setRunStatus(info.getString("status")); stationInfo.setRealtimePower(toBigDecimal(info, "powerInter")); stationInfo.setInstalledCapacity(toBigDecimal(info, "installCapacity")); stationInfo.setDailyGeneration(toBigDecimal(info, "dayGeneration")); stationInfo.setDeviceCount(info.getInteger("collects")); stationInfo.setAddress(info.getString("address")); stationInfo.setStationImage(info.getString("stationImage")); if (base != null) { stationInfo.setStationName(firstNotBlank(base.getString("stationName"), stationInfo.getStationName())); stationInfo.setInstalledCapacity(firstNotNull( toBigDecimal(base, "installCapacity"), stationInfo.getInstalledCapacity())); stationInfo.setAreaName(base.getString("areaName")); stationInfo.setCityName(base.getString("cityName")); stationInfo.setElecPrice(base.getString("elecPrice")); stationInfo.setLatitude(base.getString("latitude")); stationInfo.setLongitude(base.getString("longitude")); stationInfo.setPhone(firstNotBlank(base.getString("Phone"), base.getString("phone"))); stationInfo.setProvinceName(base.getString("provinceName")); stationInfo.setAddress(firstNotBlank( base.getString("stationAddressDetail"), stationInfo.getAddress())); stationInfo.setLoanStatus(base.getInteger("loanStatus")); stationInfo.setGridStatus(Objects.equals(stationInfo.getLoanStatus(), 3) ? "1" : "0"); stationInfo.setDataTime(parseDataTime(base.getString("saveTime"))); } stationInfo.setDataSource(2); stationInfo.setSyncTime(LocalDateTime.now()); fillDefaults(stationInfo); return stationInfo; } @Override @Transactional(rollbackFor = Exception.class) public boolean addStationInfo(TStationInfo stationInfo) { validate(stationInfo); stationInfo.setStationId("1"+System.currentTimeMillis()); stationInfo.setDataSource(1); if (lambdaQuery().eq(TStationInfo::getPlatformId, stationInfo.getPlatformId() == null ? 0L : stationInfo.getPlatformId()) .eq(TStationInfo::getStationId, stationInfo.getStationId()).count() > 0) { throw new ServiceException("该平台下的电站信息已存在"); } fillDefaults(stationInfo); stationInfo.setId(null); stationInfo.setCreateTime(LocalDateTime.now()); stationInfo.setUpdateTime(LocalDateTime.now()); return save(stationInfo); } @Override public PageInfo<TStationInfo> pageList(StationInfoQuery query) { if (query == null) query = new StationInfoQuery(); PageInfo<TStationInfo> page = new PageInfo<>(query.getPageCurr(), query.getPageSize()); lambdaQuery() .eq(query.getPlatformId() != null, TStationInfo::getPlatformId, query.getPlatformId()) .like(StringUtils.isNotBlank(query.getStationName()), TStationInfo::getStationName, query.getStationName()) .eq(StringUtils.isNotBlank(query.getStationType()), TStationInfo::getStationType, query.getStationType()) .eq(StringUtils.isNotBlank(query.getRunStatus()), TStationInfo::getRunStatus, query.getRunStatus()) .eq(StringUtils.isNotBlank(query.getGridStatus()), TStationInfo::getGridStatus, query.getGridStatus()) .orderByAsc(TStationInfo::getSortOrder).orderByDesc(TStationInfo::getCreateTime).page(page); return page; } @Override @Transactional(rollbackFor = Exception.class) public boolean updateStationInfo(TStationInfo stationInfo) { if (stationInfo == null || stationInfo.getId() == null) throw new ServiceException("电站信息ID不能为空"); TStationInfo old = getById(stationInfo.getId()); if (old == null) throw new ServiceException("电站信息不存在"); if (stationInfo.getStationId() != null && lambdaQuery() .eq(TStationInfo::getPlatformId, stationInfo.getPlatformId() == null ? old.getPlatformId() : stationInfo.getPlatformId()) .eq(TStationInfo::getStationId, stationInfo.getStationId()).ne(TStationInfo::getId, stationInfo.getId()).count() > 0) { throw new ServiceException("该平台下的电站信息已存在"); } stationInfo.setCreateBy(null); stationInfo.setCreateTime(null); stationInfo.setDelFlag(null); stationInfo.setUpdateTime(LocalDateTime.now()); return updateById(stationInfo); } private void validate(TStationInfo stationInfo) { if (stationInfo == null) { throw new ServiceException("电站信息参数不能为空"); } if (StringUtils.isBlank(stationInfo.getStationName())) { throw new ServiceException("电站名称不能为空"); } } private void fillDefaults(TStationInfo stationInfo) { stationInfo.setPlatformId(stationInfo.getPlatformId() == null ? 0L : stationInfo.getPlatformId()); stationInfo.setStationType(StringUtils.isBlank(stationInfo.getStationType()) ? "1" : stationInfo.getStationType()); stationInfo.setRunStatus(StringUtils.isBlank(stationInfo.getRunStatus()) ? "0" : stationInfo.getRunStatus()); stationInfo.setInstalledCapacity(stationInfo.getInstalledCapacity() == null ? BigDecimal.ZERO : stationInfo.getInstalledCapacity()); stationInfo.setRealtimePower(stationInfo.getRealtimePower() == null ? BigDecimal.ZERO : stationInfo.getRealtimePower()); stationInfo.setDeviceCount(stationInfo.getDeviceCount() == null ? 0 : stationInfo.getDeviceCount()); stationInfo.setDailyGeneration(stationInfo.getDailyGeneration() == null ? BigDecimal.ZERO : stationInfo.getDailyGeneration()); stationInfo.setGridStatus(StringUtils.isBlank(stationInfo.getGridStatus()) ? "0" : stationInfo.getGridStatus()); stationInfo.setSortOrder(stationInfo.getSortOrder() == null ? 0 : stationInfo.getSortOrder()); stationInfo.setCreateBy(StringUtils.defaultString(stationInfo.getCreateBy())); stationInfo.setUpdateBy(StringUtils.defaultString(stationInfo.getUpdateBy())); stationInfo.setDelFlag("0"); } private Map<String, JSONObject> buildBaseMap(JSONArray jsonArray) { Map<String, JSONObject> baseMap = new HashMap<>(); if (jsonArray != null) { for (Object item : jsonArray) { JSONObject object = JSONObject.parseObject(item.toString()); String stationId = object.getString("stationId"); if (StringUtils.isNotBlank(stationId)) { baseMap.put(stationId, object); } } } return baseMap; } private Long parseStationId(String stationId) { try { return Long.valueOf(stationId); } catch (NumberFormatException exception) { log.error("stationId格式不正确:" + stationId); return null; } } private BigDecimal toBigDecimal(JSONObject object, String key) { if (object == null || object.get(key) == null || StringUtils.isBlank(object.getString(key))) { return null; } try { return new BigDecimal(object.getString(key)); } catch (NumberFormatException exception) { log.error(key + "格式不正确:" + object.getString(key)); return null; } } private LocalDateTime parseDataTime(String value) { if (StringUtils.isBlank(value)) { return null; } DateTimeFormatter[] dateTimeFormatters = { DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"), DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss") }; for (DateTimeFormatter formatter : dateTimeFormatters) { try { return LocalDateTime.parse(value, formatter); } catch (DateTimeParseException ignored) { // 尝试下一个时间格式 } } try { return LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay(); } catch (DateTimeParseException exception) { log.error("saveTime格式不正确:" + value); return null; } } private String firstNotBlank(String preferred, String fallback) { return StringUtils.isNotBlank(preferred) ? preferred : fallback; } private <T> T firstNotNull(T preferred, T fallback) { return preferred != null ? preferred : fallback; } /** * 实时获取电站状态 */ public StationInfoStatusVO getStationStatus() { StationInfoStatusVO statusVO = new StationInfoStatusVO(); String token = KsolarUtils.token(); JSONObject statusJsonObj = KsolarUtils.getListStatus(token); JSONObject earnJsonObj = KsolarUtils.getListEarn("", token); if(Objects.nonNull(statusJsonObj)) { statusVO.setAlarm(statusJsonObj.getInteger("alarm")); statusVO.setOffline(statusJsonObj.getInteger("offline")); statusVO.setOnline(statusJsonObj.getInteger("online")); statusVO.setTotal(statusJsonObj.getInteger("total")); } if(Objects.nonNull(earnJsonObj)) { statusVO.setRealPower(earnJsonObj.getDouble("realPower")); statusVO.setDayGeneration(earnJsonObj.getDouble("dayGeneration")); } // 统计电站数量 List<TStationInfo> stationInfoList = lambdaQuery().eq(TStationInfo::getDelFlag, "0").list(); if(CollectionUtils.isNotEmpty(stationInfoList)) { statusVO.setStationCount(stationInfoList.size()); List<TStationInfo> onStatusList = stationInfoList.stream().filter(s -> Objects.nonNull(s.getLoanStatus()) && s.getLoanStatus() == 3).collect(Collectors.toList()); statusVO.setOnStatusCount(onStatusList.size()); statusVO.setOffStatusCount(stationInfoList.size() - onStatusList.size()); } return statusVO; } } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/task/ExchangeCodeExpireTask.java
@@ -1,6 +1,7 @@ package com.ruoyi.other.task; import com.ruoyi.other.service.TExchangeCodePackageService; import com.ruoyi.other.service.TStationInfoService; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -12,8 +13,19 @@ @Resource private TExchangeCodePackageService exchangeCodePackageService; @Resource private TStationInfoService tStationInfoService; @Scheduled(cron = "0 */5 * * * ?") public void refreshExpiredPackageCodes() { exchangeCodePackageService.refreshExpiredPackageCodes(); } /** * 每天11点执行科士达的数据同步 */ @Scheduled(cron = "0 0 23 * * ?") public void syncKsolarDataTask() { tStationInfoService.syncKsolarDataTask(); } } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/util/KsolarUtils.java
@@ -4,27 +4,21 @@ import cn.hutool.http.HttpResponse; import cn.hutool.http.HttpUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.ruoyi.other.api.domain.TSystemConfiguration; import com.ruoyi.other.mapper.TSystemConfigurationMapper; import com.ruoyi.other.vo.ScreenStorageConfigVO; import org.springframework.scheduling.annotation.Scheduled; import com.ruoyi.common.core.utils.StringUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import javax.annotation.Resource; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.*; /** * 定时任务:储能放电情况 光伏发电情况 */ @Slf4j @Service public class KsolarUtils { @@ -36,6 +30,7 @@ private static List<String> stationIds= Arrays.asList("2025060710462417","2025060711331323","2025060715425437","2025060716010425"); private static final String KSOLAR_URL = "http://111.230.136.62:8092"; /** * 获取今日总发电量 @@ -175,6 +170,7 @@ post.basicAuth("kstar","kstarSecret"); post.form("username", "环岛光伏"); post.form("password", "cR8GGwIXMI462A8Dfl9eXg=="); System.out.println(post); HttpResponse execute = post.execute(); String body = execute.body(); JSONObject jsonObject = JSONObject.parseObject(body); @@ -234,11 +230,155 @@ } return valueTotal+"_"+value; } public static void main(String[] args) throws Exception { String electricity = getAccessToken(); System.out.println(electricity); /** * 获取用户的发电量和收益统计 */ public static JSONObject getListEarn(String time, String token) { try { HttpRequest get = HttpUtil.createGet(KSOLAR_URL.concat("/station/list/earn")); get.header("Authorization", "Bearer "+token); if(StringUtils.isNotEmpty(time)) { get.form("startDate", time); } HttpResponse execute = get.execute(); String body = execute.body(); JSONObject jsonObject = JSONObject.parseObject(body); String code = jsonObject.get("code").toString(); if("200".equals(code)){ Object data = jsonObject.get("data"); return JSONObject.parseObject(data.toString()); } return null; } catch (Exception e) { log.error("获取用户的发电量和收益统计-调用第三方接口报错:", e); return null; } } /** * 获取用户的电站状态统计 */ public static JSONObject getListStatus(String token) { try { HttpRequest get = HttpUtil.createGet(KSOLAR_URL.concat("/station/list/status")); get.header("Authorization", "Bearer "+token); HttpResponse execute = get.execute(); String body = execute.body(); JSONObject jsonObject = JSONObject.parseObject(body); String code = jsonObject.get("code").toString(); if("200".equals(code)){ Object data = jsonObject.get("data"); return JSONObject.parseObject(data.toString()); } return null; } catch (Exception e) { log.error("获取用户的电站状态统计-调用第三方接口报错:", e); return null; } } /** * 电站列表信息 */ public static JSONArray getStationListInfo(Integer pageNumber, Integer pageSize, String token) { try { HttpRequest get = HttpUtil.createGet(KSOLAR_URL.concat("/station/list/info")); get.header("Authorization", "Bearer "+token); get.form("pageNumber", pageNumber); get.form("pageSize", pageSize); HttpResponse execute = get.execute(); String body = execute.body(); JSONObject jsonObject = JSONObject.parseObject(body); String code = jsonObject.get("code").toString(); if("0".equals(code)){ String rows = jsonObject.get("rows").toString(); return JSONArray.parseArray(rows); } return null; } catch (Exception e) { log.error("电站列表信息-调用第三方接口报错:", e); return null; } } /** * 电站基本信息列表 */ public static JSONArray getStationListBase(Integer pageNumber, Integer pageSize, String token) { try { HttpRequest post = HttpUtil.createPost(KSOLAR_URL.concat("/station/list/base")); post.header("Authorization", "Bearer "+token); post.header("Content-Type", "application/json"); JSONObject param = new JSONObject(); param.put("pageNumber", pageNumber); param.put("pageSize", pageSize); HttpResponse execute = post.body(param.toJSONString()).execute(); String body = execute.body(); JSONObject jsonObject = JSONObject.parseObject(body); String code = jsonObject.get("code").toString(); if("0".equals(code)){ String rows = jsonObject.get("rows").toString(); return JSONArray.parseArray(rows); } return null; } catch (Exception e) { log.error("电站列表信息-调用第三方接口报错:", e); return null; } } /** * 逆变器列表 */ public static JSONArray getCollectBaseList(Integer pageNumber, Integer pageSize, String token) { try { HttpRequest post = HttpUtil.createPost(KSOLAR_URL.concat("/collect/manager/base/list")); post.header("Authorization", "Bearer "+token); post.header("Content-Type", "application/json"); JSONObject param = new JSONObject(); param.put("pageNumber", pageNumber); param.put("pageSize", pageSize); HttpResponse execute = post.body(param.toJSONString()).execute(); String body = execute.body(); JSONObject jsonObject = JSONObject.parseObject(body); String code = jsonObject.get("code").toString(); if("0".equals(code)){ String rows = jsonObject.get("rows").toString(); return JSONArray.parseArray(rows); } return null; } catch (Exception e) { log.error("逆变器列表-调用第三方接口报错:", e); return null; } } /** * 电站发电量和收益统计明细 */ public static JSONArray getStationElecList(String startDate, String endDate, String token) { try { HttpRequest get = HttpUtil.createGet(KSOLAR_URL.concat("/protocol/station/statistic/elec/detail")); get.header("Authorization", "Bearer "+token); if(StringUtils.isNotEmpty(startDate)) { get.form("startDate", startDate); } if(StringUtils.isNotEmpty(endDate)) { get.form("endDate", endDate); } HttpResponse execute = get.execute(); String body = execute.body(); return JSONArray.parseArray(body); } catch (Exception e) { log.error("电站的电量和收益统计查询-调用第三方接口报错:", e); return null; } } } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/StationEarnExportVO.java
New file @@ -0,0 +1,32 @@ package com.ruoyi.other.vo; import cn.afterturn.easypoi.excel.annotation.Excel; import lombok.Data; import java.math.BigDecimal; import java.util.Objects; @Data public class StationEarnExportVO { @Excel(name = "平台", width = 15) private String platformName; @Excel(name = "电站ID", width = 24) private String stationId; @Excel(name = "电站名称", width = 25) private String stationName; @Excel(name = "统计日期", width = 18) private String saveTime; @Excel(name = "总发电量(度)", width = 20) private BigDecimal elecTotal; @Excel(name = "总收益(元)", width = 20) private BigDecimal earnTotal; public void buildPlatformName(Long platformId) { // 0科士达,1华为,2阳光,3古瑞瓦特 if(Objects.nonNull(platformId)) { if(platformId == 0) { this.setPlatformName("科士达"); }else if(platformId == 1) { this.setPlatformName("华为"); }else if(platformId == 2) { this.setPlatformName("阳光"); }else if(platformId == 3) { this.setPlatformName("古瑞瓦特"); } } } } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/StationEarnOverviewVO.java
New file @@ -0,0 +1,21 @@ package com.ruoyi.other.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; @Data @ApiModel("电站发电量概览") public class StationEarnOverviewVO { @ApiModelProperty("今日发电量(度)") private BigDecimal todayGeneration; @ApiModelProperty("本月发电量(度)") private BigDecimal monthGeneration; @ApiModelProperty("本年发电量(万度)") private BigDecimal yearGeneration; } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/StationEarnStatisticsItemVO.java
New file @@ -0,0 +1,25 @@ package com.ruoyi.other.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.math.BigDecimal; @Data @NoArgsConstructor @AllArgsConstructor @ApiModel("电站发电量统计图表数据项") public class StationEarnStatisticsItemVO { @ApiModelProperty("横轴标签:日期、月份或年份") private String label; @ApiModelProperty("发电量(度/kWh)") private BigDecimal generation; @ApiModelProperty("收益(元)") private BigDecimal earn; } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/StationEarnStatisticsVO.java
New file @@ -0,0 +1,25 @@ package com.ruoyi.other.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; import java.util.List; @Data @ApiModel("电站发电量统计结果") public class StationEarnStatisticsVO { @ApiModelProperty("统计维度:day、month、year") private String dimension; @ApiModelProperty("合计发电量(度/kWh)") private BigDecimal totalGeneration; @ApiModelProperty("合计收益(元)") private BigDecimal totalEarn; @ApiModelProperty("图表数据") private List<StationEarnStatisticsItemVO> items; } ruoyi-service/ruoyi-other/src/main/java/com/ruoyi/other/vo/StationInfoStatusVO.java
New file @@ -0,0 +1,39 @@ package com.ruoyi.other.vo; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; @Data @ApiModel("电站状态") public class StationInfoStatusVO { @ApiModelProperty("告警个数") private Integer alarm; @ApiModelProperty("离线个数") private Integer offline; @ApiModelProperty("在线个数") private Integer online; @ApiModelProperty("电站总数") private Integer total; @ApiModelProperty("实时功率") private Double realPower; @ApiModelProperty("日发电量") private Double dayGeneration; @ApiModelProperty("电站数量") private Integer stationCount; @ApiModelProperty("已上网数量") private Integer onStatusCount; @ApiModelProperty("未上网数量") private Integer offStatusCount; } ruoyi-service/ruoyi-other/src/main/resources/mapper/other/TStationCollectMapper.xml
New file @@ -0,0 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.other.mapper.TStationCollectMapper"> </mapper> ruoyi-service/ruoyi-other/src/main/resources/mapper/other/TStationEarnMapper.xml
New file @@ -0,0 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!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"> </mapper> ruoyi-service/ruoyi-other/src/main/resources/mapper/other/TStationInfoMapper.xml
New file @@ -0,0 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.ruoyi.other.mapper.TStationInfoMapper"> </mapper> ruoyi-service/ruoyi-other/src/main/resources/sql/t_station_collect.sql
New file @@ -0,0 +1,62 @@ -- ---------------------------- -- 电站逆变器表 -- ---------------------------- SET NAMES utf8mb4; CREATE TABLE IF NOT EXISTS `t_station_collect` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `platform_id` BIGINT NOT NULL DEFAULT 0 COMMENT '所属平台ID(0科士达,1华为,2阳光,3古瑞瓦特)', `station_id` VARCHAR(100) DEFAULT NULL COMMENT '电站ID', `station_name` VARCHAR(255) DEFAULT NULL COMMENT '电站名称', `collect_id` VARCHAR(100) NOT NULL COMMENT '逆变器ID', `collect_name` VARCHAR(255) NOT NULL COMMENT '逆变器名称', `device_model` VARCHAR(200) DEFAULT NULL COMMENT '机型型号', `inverter_id` VARCHAR(200) DEFAULT NULL COMMENT '逆变器SN', `installed_capacity` VARCHAR(100) DEFAULT NULL COMMENT '装机容量(kW)', `power_num` INT DEFAULT 0 COMMENT '装机容量', `province_name` VARCHAR(200) DEFAULT NULL COMMENT '省', `city_name` VARCHAR(200) DEFAULT NULL COMMENT '市', `area_name` VARCHAR(200) DEFAULT NULL COMMENT '区/县', `address` VARCHAR(1000) DEFAULT NULL COMMENT '详细地址', `latitude` VARCHAR(100) DEFAULT NULL COMMENT '纬度', `longitude` VARCHAR(100) DEFAULT NULL COMMENT '经度', `status` CHAR(1) DEFAULT '0' COMMENT '状态(1在线 2离线 3故障)', `data_source` INT DEFAULT NULL COMMENT '数据来源(1系统创建,2第三方接口)', `sort_order` INT DEFAULT 0 COMMENT '显示顺序', `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', `create_time` DATETIME DEFAULT NULL COMMENT '创建时间', `sync_time` DATETIME DEFAULT NULL COMMENT '同步时间', `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', `update_time` DATETIME DEFAULT NULL COMMENT '更新时间', `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', `del_flag` CHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标志(0存在 2删除)', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='电站逆变器表'; ruoyi-service/ruoyi-other/src/main/resources/sql/t_station_earn.sql
New file @@ -0,0 +1,24 @@ -- ---------------------------- -- 发电量表 -- 对应发电量分析中的发电量、收益和碳减排统计数据 -- ---------------------------- SET NAMES utf8mb4; CREATE TABLE IF NOT EXISTS `t_station_earn` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID', `platform_id` bigint NOT NULL DEFAULT 0 COMMENT '平台ID,0表示科士达', `station_id` varchar(100) NULL COMMENT '电站ID', `station_name` varchar(100) NULL COMMENT '电站名称', `save_time` date NOT NULL COMMENT '时间', `elec_total` decimal(18,4) Null DEFAULT 0.0000 COMMENT '总发电量', `earn_total` decimal(18,4) Null DEFAULT 0.0000 COMMENT '总收益', `create_by` varchar(64) NULL DEFAULT '' COMMENT '创建者', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_by` varchar(64) NULL DEFAULT '' COMMENT '更新者', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `remark` varchar(500) DEFAULT NULL COMMENT '备注', `del_flag` char(1) NOT NULL DEFAULT '0' COMMENT '删除标志(0存在 2删除)', data_source int default NULL null comment '数据来源(1系统创建,2第三方接口)', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='发电量统计表'; ruoyi-service/ruoyi-other/src/main/resources/sql/t_station_info.sql
New file @@ -0,0 +1,44 @@ -- ---------------------------- -- 电站明细表 -- 对应电站概览卡片中的基础信息、运行状态及发电指标 -- ---------------------------- SET NAMES utf8mb4; CREATE TABLE IF NOT EXISTS `charging_pile_other`.`t_station_info` ( `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键ID', `platform_id` BIGINT NOT NULL DEFAULT 0 COMMENT '所属平台ID(0科十达,1华为,2阳光,3古瑞瓦特)', `station_id` VARCHAR(100) NOT NULL COMMENT '电站ID', `station_name` VARCHAR(255) NOT NULL COMMENT '电站名称', `station_image` VARCHAR(500) DEFAULT NULL COMMENT '电站图片地址', `station_type` CHAR(1) NOT NULL DEFAULT '1' COMMENT '电站类型(1光伏、2储能)', `run_status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '运行状态(0正常/在线 1离线 2告警)', `installed_capacity` DECIMAL(18,4) NOT NULL DEFAULT 0.0000 COMMENT '装机容量(kW)', `realtime_power` DECIMAL(18,4) NOT NULL DEFAULT 0.0000 COMMENT '实时功率(W)', `device_count` INT NOT NULL DEFAULT 0 COMMENT '设备总数', `daily_generation` DECIMAL(18,4) NOT NULL DEFAULT 0.0000 COMMENT '日发电量(度/kWh)', `grid_status` CHAR(1) NOT NULL DEFAULT '0' COMMENT '上网状态(0未上网 1已上网)', `data_time` DATETIME DEFAULT NULL COMMENT '指标数据时间', `elec_price` VARCHAR(100) DEFAULT NULL COMMENT '电价', `contact_name` VARCHAR(255) DEFAULT NULL COMMENT '联系人', `phone` VARCHAR(50) DEFAULT NULL COMMENT '电话', `province_name` VARCHAR(200) DEFAULT NULL COMMENT '省', `city_name` VARCHAR(200) DEFAULT NULL COMMENT '市', `area_name` VARCHAR(200) DEFAULT NULL COMMENT '区/县', `address` VARCHAR(1000) DEFAULT NULL COMMENT '详细地址', `latitude` VARCHAR(100) DEFAULT NULL COMMENT '纬度', `longitude` VARCHAR(100) DEFAULT NULL COMMENT '经度', `loan_status` INT DEFAULT NULL COMMENT '并网状态(1未并网,2并网中,3已并网)', `data_source` INT DEFAULT NULL COMMENT '数据来源(1系统创建,2第三方接口)', `sort_order` INT NOT NULL DEFAULT 0 COMMENT '显示顺序', `create_by` VARCHAR(64) DEFAULT NULL COMMENT '创建者', `create_time` DATETIME DEFAULT NULL COMMENT '创建时间', `sync_time` DATETIME DEFAULT NULL COMMENT '同步时间', `update_by` VARCHAR(64) DEFAULT NULL COMMENT '更新者', `update_time` DATETIME DEFAULT NULL COMMENT '更新时间', `remark` VARCHAR(500) DEFAULT NULL COMMENT '备注', `del_flag` CHAR(1) NOT NULL DEFAULT '0' COMMENT '删除标志(0存在 2删除)', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='电站信息表';