feat (farm): 设备商接口重构
- 设备厂接口 - 吉水两山 代码临时性解决现场问题
This commit is contained in:
@@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.farm.controller.admin.api.vo.*;
|
||||
import cn.iocoder.yudao.module.farm.dal.dataobject.deviceinfo.DeviceInfoDO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.RealTimeDataResponse;
|
||||
import cn.iocoder.yudao.module.farm.service.baseinfo.BaseInfoService;
|
||||
import cn.iocoder.yudao.module.farm.service.deviceinfo.DeviceInfoService;
|
||||
import cn.iocoder.yudao.module.farm.service.farmingrecord.FarmingRecordService;
|
||||
@@ -137,8 +138,8 @@ public class ApiController {
|
||||
|
||||
@PostMapping("/digital-cockpit/chart/device-monitoring")
|
||||
@Operation(summary = "数字驾驶舱-设备监测")
|
||||
public CommonResult<DeviceMonitoringRespVO> getDeviceMonitoring(@Valid @RequestBody DeviceMonitoringReqVO req) {
|
||||
return deviceInfoService.getDeviceMonitoring(req);// TODO: 2025/9/25
|
||||
public CommonResult<RealTimeDataResponse> getDeviceMonitoring(@Valid @RequestBody DeviceMonitoringReqVO req) {
|
||||
return deviceInfoService.getDeviceMonitoring(req);
|
||||
}
|
||||
|
||||
@PostMapping("/digital-cockpit/chart/disaster-statistics")
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package cn.iocoder.yudao.module.farm.controller.admin.api.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.RealTimeDataResponse;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description:
|
||||
* @author: binda
|
||||
@@ -14,42 +17,5 @@ import lombok.NoArgsConstructor;
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DeviceMonitoringRespVO {
|
||||
private String baseName;
|
||||
private DeviceMonitoringInfo deviceMonitoringInfo ;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class DeviceMonitoringInfo{
|
||||
@Schema(description = "节点编号")
|
||||
private Integer nodeId;
|
||||
@Schema(description = "节点名称")
|
||||
private String nodeName;
|
||||
@Schema(description = "节点类型")
|
||||
private Integer nodeType;
|
||||
|
||||
// 模拟量1 名称,单位,原值,显示值,报警等级
|
||||
@Schema(description = "temName" , example = "温度")
|
||||
private String temName;
|
||||
@Schema(description = "temUnit" , example = "`C")
|
||||
private String temUnit;
|
||||
@Schema(description = "temValue" , example = "28.100000381469727")
|
||||
private Double temValue;
|
||||
@Schema(description = "temValueStr" , example = "30.2")
|
||||
private String temValueStr;
|
||||
@Schema(description = "temAlarmStatus" , example = "0")
|
||||
private Integer temAlarmStatus;
|
||||
// 模拟量2 名称,单位,原值,显示值,报警等级
|
||||
@Schema(description = "humName" , example = "湿度")
|
||||
private String humName;
|
||||
@Schema(description = "humUnit" , example = "%RH")
|
||||
private String humUnit;
|
||||
@Schema(description = "humValue" , example = "13.699999809265137")
|
||||
private String humValue;
|
||||
@Schema(description = "humValueStr" , example = "13.7")
|
||||
private String humValueStr;
|
||||
@Schema(description = "humAlarmStatus" , example = "0")
|
||||
private String humAlarmStatus;
|
||||
}
|
||||
|
||||
private RealTimeDataResponse realTimeDataList ;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
package cn.iocoder.yudao.module.farm.controller.admin.api.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
/**
|
||||
* @description: 数字驾驶舱-统计图-灾害分析 请求实体
|
||||
* @author: binda
|
||||
@@ -13,6 +17,10 @@ import lombok.NoArgsConstructor;
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DisasterAnalysisReqVO {
|
||||
private String id;
|
||||
|
||||
@Schema(description = "基地D")
|
||||
@NotNull(message = "基地D: 不能为空")
|
||||
private String baseId;
|
||||
@Schema(description = "租户ID")
|
||||
@NotNull(message = "租户ID: 不能为空")
|
||||
private String tenantId;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package cn.iocoder.yudao.module.farm.controller.admin.api.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description: 数字驾驶舱-统计图-灾害分析 响应实体
|
||||
* @author: binda
|
||||
@@ -13,6 +16,19 @@ import lombok.NoArgsConstructor;
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DisasterAnalysisRespVO {
|
||||
private String id;
|
||||
|
||||
private Integer year;
|
||||
private List<DisasterReports> disasterReports;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class DisasterReports{
|
||||
@Schema(description = "月份")
|
||||
private Integer month;
|
||||
@Schema(description = "气象类发生次数")
|
||||
private Integer meteorologyCount;
|
||||
@Schema(description = "虫草病害类发生次数")
|
||||
private Integer pestCount;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -168,7 +168,6 @@ public class CropFarmingCenterController {
|
||||
@Operation(summary = "生产计划-结束按钮")
|
||||
@PutMapping("/production-plan/finish")
|
||||
public CommonResult<Boolean> finishPlanning(@RequestBody ProductionPlanUpdateReqVO updateReqVO) {
|
||||
updateReqVO.setPlanStatus(CommonConstants.PLAN_STATUS_3);
|
||||
cropFarmingCenterService.updateProductionPlan(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@@ -114,9 +114,10 @@ public class DeviceInfoController {
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得设备信息")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
// @Parameter(name = "dateType", description = "日期类型", required = false)
|
||||
public CommonResult<DeviceInfoDetailV2RespVO> getDeviceInfo(@RequestParam("id") String id) {
|
||||
DeviceInfoDetailV2RespVO res = deviceInfoService.getDeviceRealTimeInfo(id);
|
||||
DeviceInfoDetailV2RespVO res = deviceInfoService.getDeviceRealTimeInfo(id,"dateType");
|
||||
return success(res);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package cn.iocoder.yudao.module.farm.controller.admin.deviceinfo.vo.v2;
|
||||
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.HistoryDataResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.RealTimeDataResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.realtime.RealTimeDataRespVO;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
@@ -73,85 +76,8 @@ public class DeviceInfoDetailV2RespVO {
|
||||
@NoArgsConstructor
|
||||
public static class SoilInfo{
|
||||
private String deviceUniqueId;
|
||||
private RealTimeData realTimeData;
|
||||
private List<HistoryDataList> historyDataLis;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class RealTimeData{
|
||||
@Schema(description = "设备地址")
|
||||
private String deviceAddr;
|
||||
@Schema(description = "设备名称")
|
||||
private String deviceName;
|
||||
@Schema(description = "设备状态", example = "online")
|
||||
private String status;
|
||||
@Schema(description = "设备类型", example = "soil(土壤墒情)")
|
||||
private String deviceType;
|
||||
@Schema(description = "数据集合")
|
||||
private List<RealData> realDataList;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class RealData{
|
||||
@Schema(description = "节点编号")
|
||||
private Integer nodeId;
|
||||
@Schema(description = "节点名称")
|
||||
private String nodeName;
|
||||
@Schema(description = "节点类型")
|
||||
private Integer nodeType;
|
||||
|
||||
// 模拟量1 名称,单位,原值,显示值,报警等级
|
||||
@Schema(description = "temName" , example = "温度")
|
||||
private String temName;
|
||||
@Schema(description = "temUnit" , example = "`C")
|
||||
private String temUnit;
|
||||
@Schema(description = "temValue" , example = "28.100000381469727")
|
||||
private Double temValue;
|
||||
@Schema(description = "temValueStr" , example = "30.2")
|
||||
private String temValueStr;
|
||||
@Schema(description = "temAlarmStatus" , example = "0")
|
||||
private Integer temAlarmStatus;
|
||||
// 模拟量2 名称,单位,原值,显示值,报警等级
|
||||
@Schema(description = "humName" , example = "湿度")
|
||||
private String humName;
|
||||
@Schema(description = "humUnit" , example = "%RH")
|
||||
private String humUnit;
|
||||
@Schema(description = "humValue" , example = "13.699999809265137")
|
||||
private String humValue;
|
||||
@Schema(description = "humValueStr" , example = "13.7")
|
||||
private String humValueStr;
|
||||
@Schema(description = "humAlarmStatus" , example = "0")
|
||||
private String humAlarmStatus;
|
||||
}
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public static class HistoryDataList {
|
||||
@Schema(description = "历史记录ID")
|
||||
private Integer historyId;
|
||||
@Schema(description = "历史记录时间")
|
||||
@JsonFormat(pattern = "yyyy-MM-dd hh:MM:ss")
|
||||
private LocalDateTime recordTime;
|
||||
@Schema(description = "设备地址")
|
||||
private String deviceAddress;
|
||||
@Schema(description = "警告状态")
|
||||
private Integer alarmStatus;
|
||||
@Schema(description = "警告状态 (0:正常 1:报警)")
|
||||
private String alarmStatusName;
|
||||
|
||||
@Schema(description = "模拟量1 (字符)")
|
||||
private String temStr;
|
||||
@Schema(description = "模拟量1 (值)")
|
||||
private Double temValue;
|
||||
@Schema(description = "模拟量2 (字符)")
|
||||
private String humStr;
|
||||
@Schema(description = "模拟量2 (值)")
|
||||
private Double humValue;
|
||||
private RealTimeDataResponse realTimeData;
|
||||
private HistoryDataResponse historyData;
|
||||
}
|
||||
|
||||
@Data
|
||||
|
||||
@@ -39,13 +39,6 @@ public class HomeController {
|
||||
return success(homeService.getHomeInfo(baseId));
|
||||
}
|
||||
|
||||
// @Operation(summary = "农场首页")
|
||||
// @GetMapping("")
|
||||
// @Parameter(name = "baseId", description = "基地ID")
|
||||
// public CommonResult<List<HomeInfo>> getBaseInfo(@RequestParam("baseId") String baseId) {
|
||||
// return success(homeService.getHomeInfoList(baseId));
|
||||
// }
|
||||
|
||||
@Operation(summary = "农场首页-基地名称列表")
|
||||
@GetMapping("/baseNames")
|
||||
public CommonResult<List<BaseNameVO>> getBaseNameList() {
|
||||
|
||||
@@ -3,10 +3,14 @@ package cn.iocoder.yudao.module.farm.dal.mysql.screendisasterdata;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.farm.controller.admin.api.vo.DisasterAnalysisReqVO;
|
||||
import cn.iocoder.yudao.module.farm.controller.admin.api.vo.DisasterAnalysisRespVO;
|
||||
import cn.iocoder.yudao.module.farm.controller.admin.managementcenter.largescreen.screendisasterdata.vo.ScreenDisasterDataPageReqVO;
|
||||
import cn.iocoder.yudao.module.farm.dal.dataobject.screendisasterdata.ScreenDisasterDataDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 大屏数据-灾害数据 Mapper
|
||||
*
|
||||
@@ -29,4 +33,5 @@ public interface ScreenDisasterDataMapper extends BaseMapperX<ScreenDisasterData
|
||||
.orderByDesc(ScreenDisasterDataDO::getId));
|
||||
}
|
||||
|
||||
List<DisasterAnalysisRespVO> countDisasterAnalysis(DisasterAnalysisReqVO req);
|
||||
}
|
||||
@@ -16,15 +16,15 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class DeviceListResponse {
|
||||
private String code;
|
||||
private Integer code;
|
||||
private String message;
|
||||
private List<TokenCacheService.DeviceInfo> data;
|
||||
|
||||
public static DeviceListResponse success(List<TokenCacheService.DeviceInfo> data) {
|
||||
return new DeviceListResponse("200", "成功", data);
|
||||
return new DeviceListResponse(200, "成功", data);
|
||||
}
|
||||
|
||||
public static DeviceListResponse error(String message) {
|
||||
return new DeviceListResponse("500", message, null);
|
||||
return new DeviceListResponse(500, message, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import java.util.List;
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class SysUserDeviceRespVO {
|
||||
private String code;
|
||||
private Integer code;
|
||||
private String message;
|
||||
private List<DeviceInfo> data;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ import lombok.NoArgsConstructor;
|
||||
@NoArgsConstructor
|
||||
public class UserLoginRespVO {
|
||||
|
||||
private String code;
|
||||
private Integer code;
|
||||
private String message;
|
||||
private VendorData data;
|
||||
|
||||
|
||||
@@ -150,8 +150,9 @@ public abstract class AbstractDeviceService extends TokenCacheService implements
|
||||
// 遍历token缓存,查找匹配的token
|
||||
for (Map.Entry<String, TokenCacheService.TokenInfo> entry : tokenCacheMap.entrySet()) {
|
||||
if (entry.getKey().startsWith(getDeviceType() + ":" + tenantId + ":") &&
|
||||
token.equals(entry.getValue().getToken()) &&
|
||||
isTokenValid(entry.getKey())) {
|
||||
token.equals(entry.getValue().getToken())
|
||||
// && isTokenValid(entry.getKey())
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.AbstractDe
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.HistoryDataStorageService;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.service.TokenCacheService;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.utils.HttpClientUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.*;
|
||||
@@ -27,6 +28,7 @@ import java.util.stream.Collectors;
|
||||
* @author: binda
|
||||
* @date: 2025/9/25 20:40
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
public class SoilService extends AbstractDeviceService {
|
||||
|
||||
@@ -58,6 +60,7 @@ public class SoilService extends AbstractDeviceService {
|
||||
return convertToUnifiedResponse(vendorResponse);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return UnifiedLoginResponse.error("土壤设备登录失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
@@ -102,11 +105,11 @@ public class SoilService extends AbstractDeviceService {
|
||||
// 转换请求参数
|
||||
HistoryDataListPageReqVO soilRequest = (HistoryDataListPageReqVO) historyRequest;
|
||||
|
||||
// T调用土壤设备厂商API获取历史数据 GET 请求方式
|
||||
// 调用土壤设备厂商API获取历史数据 GET 请求方式
|
||||
HistoryDataListPageRespVO vendorResponse = callSoilHistoryDataApi(token, soilRequest);
|
||||
|
||||
// TODO: 2025/9/26 模拟保存到MySQL
|
||||
saveHistoryDataToDatabase(vendorResponse, soilRequest);
|
||||
// saveHistoryDataToDatabase(vendorResponse, soilRequest);
|
||||
|
||||
return HistoryDataResponse.success(vendorResponse);
|
||||
|
||||
@@ -116,12 +119,40 @@ public class SoilService extends AbstractDeviceService {
|
||||
}
|
||||
|
||||
private UserLoginRespVO callSoilVendorApi(UserLoginReqVO request) {
|
||||
String url = deviceConf.getFourSituations().getHosts() + deviceConf.getFourSituations().getGlobal().getUrl21();
|
||||
return httpClientUtils.doPost(url, null, request, UserLoginRespVO.class);
|
||||
try {
|
||||
String url = deviceConf.getFourSituations().getHosts() +
|
||||
deviceConf.getFourSituations().getGlobal().getUrl21();
|
||||
|
||||
log.info("调用土壤登录API: {}", url);
|
||||
log.info("请求参数: {}", request);
|
||||
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
// headers.put("User-Agent", "FarmDeviceManager/1.0");
|
||||
headers.put("Content-Type", "application/json");
|
||||
|
||||
// 先尝试获取原始响应进行调试
|
||||
String rawResponse = httpClientUtils.doGetRaw(
|
||||
url,
|
||||
headers,
|
||||
Collections.singletonMap("loginName", request.getLoginName())
|
||||
);
|
||||
|
||||
log.info("土壤登录原始响应: {}", rawResponse);
|
||||
|
||||
// 然后进行正式的POST请求
|
||||
UserLoginRespVO response = httpClientUtils.doPost(url, headers, request, UserLoginRespVO.class);
|
||||
log.info("土壤登录解析响应: {}", response);
|
||||
|
||||
return response;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("土壤登录API调用失败: {}", e.getMessage(), e);
|
||||
throw new RuntimeException("土壤设备登录接口调用失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private UnifiedLoginResponse convertToUnifiedResponse(UserLoginRespVO vendorResponse) {
|
||||
if (!"1000".equals(vendorResponse.getCode())) {
|
||||
if (1000 != vendorResponse.getCode()) {
|
||||
return UnifiedLoginResponse.error(vendorResponse.getMessage());
|
||||
}
|
||||
|
||||
@@ -154,7 +185,7 @@ public class SoilService extends AbstractDeviceService {
|
||||
}
|
||||
|
||||
private DeviceListResponse convertToUnifiedDeviceResponse(SysUserDeviceRespVO vendorResponse) {
|
||||
if (!"1000".equals(vendorResponse.getCode())) {
|
||||
if (1000 != vendorResponse.getCode()) {
|
||||
return DeviceListResponse.error(vendorResponse.getMessage());
|
||||
}
|
||||
|
||||
@@ -200,7 +231,6 @@ public class SoilService extends AbstractDeviceService {
|
||||
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("token", token);
|
||||
// headers.put("Authorization", "Bearer " + token);
|
||||
|
||||
Map<String, Object> params = new HashMap<>();
|
||||
params.put("beginTime", request.getBeginTime());
|
||||
|
||||
@@ -19,9 +19,11 @@ import java.util.Map;
|
||||
public class HttpClientUtils {
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
private final HttpResponseUtils httpResponseUtils;
|
||||
|
||||
public HttpClientUtils(RestTemplateBuilder restTemplateBuilder) {
|
||||
public HttpClientUtils(RestTemplateBuilder restTemplateBuilder, HttpResponseUtils httpResponseUtils) {
|
||||
this.restTemplate = restTemplateBuilder.build();
|
||||
this.httpResponseUtils = httpResponseUtils;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,15 +48,20 @@ public class HttpClientUtils {
|
||||
}
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(httpHeaders);
|
||||
ResponseEntity<T> response = restTemplate.exchange(
|
||||
|
||||
// 先以String类型接收响应
|
||||
ResponseEntity<String> response = restTemplate.exchange(
|
||||
builder.build().toUri(),
|
||||
HttpMethod.GET,
|
||||
entity,
|
||||
responseType
|
||||
String.class
|
||||
);
|
||||
|
||||
return response.getBody();
|
||||
// 使用增强的响应处理
|
||||
return httpResponseUtils.handleResponse(response, responseType);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException("HTTP GET请求失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
@@ -72,16 +79,50 @@ public class HttpClientUtils {
|
||||
}
|
||||
|
||||
HttpEntity<Object> entity = new HttpEntity<>(requestBody, httpHeaders);
|
||||
ResponseEntity<T> response = restTemplate.exchange(
|
||||
|
||||
// 先以String类型接收响应
|
||||
ResponseEntity<String> response = restTemplate.exchange(
|
||||
url,
|
||||
HttpMethod.POST,
|
||||
entity,
|
||||
responseType
|
||||
String.class
|
||||
);
|
||||
|
||||
// 使用增强的响应处理
|
||||
return httpResponseUtils.handleResponse(response, responseType);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("HTTP POST请求失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
public String doGetRaw(String url, Map<String, String> headers, Map<String, Object> params) {
|
||||
try {
|
||||
HttpHeaders httpHeaders = new HttpHeaders();
|
||||
if (headers != null) {
|
||||
headers.forEach(httpHeaders::set);
|
||||
}
|
||||
|
||||
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);
|
||||
if (params != null) {
|
||||
params.forEach((key, value) -> {
|
||||
if (value != null) {
|
||||
builder.queryParam(key, value.toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
HttpEntity<String> entity = new HttpEntity<>(httpHeaders);
|
||||
ResponseEntity<String> response = restTemplate.exchange(
|
||||
builder.build().toUri(),
|
||||
HttpMethod.GET,
|
||||
entity,
|
||||
String.class
|
||||
);
|
||||
|
||||
return response.getBody();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("HTTP POST请求失败: " + e.getMessage(), e);
|
||||
throw new RuntimeException("HTTP GET原始请求失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package cn.iocoder.yudao.module.farm.manager.equipmentproducer.utils;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
* @description: HTTP响应处理工具类
|
||||
* @author: binda
|
||||
* @date: 2025/9/28 21:52
|
||||
*/
|
||||
@Component
|
||||
public class HttpResponseUtils {
|
||||
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
public HttpResponseUtils() {
|
||||
this.objectMapper = new ObjectMapper();
|
||||
this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
this.objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理HTTP响应,支持更灵活的反序列化
|
||||
*/
|
||||
public <T> T handleResponse(ResponseEntity<String> response, Class<T> responseType) {
|
||||
try {
|
||||
String responseBody = response.getBody();
|
||||
if (responseBody == null) {
|
||||
throw new RuntimeException("响应体为空");
|
||||
}
|
||||
|
||||
// 记录原始响应用于调试
|
||||
System.out.println("原始响应: " + responseBody);
|
||||
|
||||
return objectMapper.readValue(responseBody, responseType);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("响应解析失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理通用响应,支持不同结构的响应
|
||||
*/
|
||||
public <T> T handleGenericResponse(ResponseEntity<String> response, Class<T> responseType, String... rootPaths) {
|
||||
try {
|
||||
String responseBody = response.getBody();
|
||||
if (responseBody == null) {
|
||||
throw new RuntimeException("响应体为空");
|
||||
}
|
||||
|
||||
JsonNode rootNode = objectMapper.readTree(responseBody);
|
||||
JsonNode targetNode = rootNode;
|
||||
|
||||
// 支持从指定路径提取数据
|
||||
for (String path : rootPaths) {
|
||||
if (targetNode.has(path)) {
|
||||
targetNode = targetNode.get(path);
|
||||
}
|
||||
}
|
||||
|
||||
return objectMapper.treeToValue(targetNode, responseType);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("响应解析失败: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import cn.iocoder.yudao.module.farm.dal.mysql.personnelmanagement.PersonnelManag
|
||||
import cn.iocoder.yudao.module.farm.dal.mysql.specieslibrary.SpeciesLibraryMapper;
|
||||
import cn.iocoder.yudao.module.farm.enums.CommonConstants;
|
||||
import cn.iocoder.yudao.module.farm.service.companyinfo.CompanyInfoService;
|
||||
import cn.iocoder.yudao.module.farm.service.deviceinfo.DeviceInfoService;
|
||||
import cn.iocoder.yudao.module.farm.service.personnelmanagement.PersonnelManagementService;
|
||||
import cn.iocoder.yudao.module.farm.service.plotinfo.PlotInfoService;
|
||||
import cn.iocoder.yudao.module.farm.service.productionplan.ProductionPlanService;
|
||||
@@ -77,6 +78,8 @@ public class BaseInfoServiceImpl implements BaseInfoService {
|
||||
private PlotInfoService plotInfoService;
|
||||
@Resource
|
||||
private CompanyInfoService companyInfoService;
|
||||
@Resource
|
||||
private DeviceInfoService deviceInfoService;
|
||||
|
||||
@SneakyThrows
|
||||
@Override
|
||||
@@ -322,6 +325,8 @@ public class BaseInfoServiceImpl implements BaseInfoService {
|
||||
String tenantId = req.getTenantId();
|
||||
String baseId = req.getBaseId();
|
||||
BaseInfoDO bDO = baseInfoMapper.selectOne("id", baseId, "tenant_id", tenantId);
|
||||
int countByTenant = deviceInfoService.countDevice("",tenantId);
|
||||
int countByBase = deviceInfoService.countDevice(baseId,tenantId);
|
||||
|
||||
FarmBaseOverviewRespVO.TenantInfo tenantInfo = new FarmBaseOverviewRespVO.TenantInfo();
|
||||
tenantInfo.setTenantId(bDO.getTenantId());
|
||||
@@ -329,7 +334,7 @@ public class BaseInfoServiceImpl implements BaseInfoService {
|
||||
tenantInfo.setBaseTotalCount(this.getBaseTotalCount(tenantId));
|
||||
tenantInfo.setPlotTotalCount(plotInfoService.getPlotTotalCount(tenantId));
|
||||
tenantInfo.setCropTotalCount(speciesLibraryService.getCropTotalCount(tenantId));
|
||||
tenantInfo.setIotDeviceTotalCount(0); // TODO: 2025/9/4
|
||||
tenantInfo.setIotDeviceTotalCount(countByTenant);
|
||||
|
||||
FarmBaseOverviewRespVO.BaseInfo baseInfo = new FarmBaseOverviewRespVO.BaseInfo();
|
||||
baseInfo.setBaseId(bDO.getId());
|
||||
@@ -339,7 +344,7 @@ public class BaseInfoServiceImpl implements BaseInfoService {
|
||||
baseInfo.setBaseCentrePoint(bDO.getCentrePoint());
|
||||
baseInfo.setPlantingCropCount(productionPlanService.getGrowingCropCount(baseId));
|
||||
baseInfo.setPlantingPlotCount(productionPlanService.getGrowingPlotCount(baseId));
|
||||
baseInfo.setIotDeviceCount(0); // TODO: 2025/9/4
|
||||
baseInfo.setIotDeviceCount(countByBase);
|
||||
baseInfo.setPlantingTaskCount(productionPlanService.getGrowingPlanCount(baseId));
|
||||
baseInfo.setAdministratorName(getAdministratorName(tenantId, bDO.getManager()));
|
||||
return CommonResult.success(new FarmBaseOverviewRespVO(tenantInfo, baseInfo));
|
||||
|
||||
@@ -237,8 +237,15 @@ public class CropFarmingCenterServiceImpl implements CropFarmingCenterService {
|
||||
|
||||
@Override
|
||||
public void updateProductionPlan(ProductionPlanUpdateReqVO updateReqVO) {
|
||||
validateProductionPlanExists(updateReqVO.getId());
|
||||
productionPlanMapper.updateById(BeanUtils.toBean(updateReqVO, ProductionPlanDO.class));
|
||||
ProductionPlanDO one = productionPlanMapper.selectById(updateReqVO.getId());
|
||||
if (one == null) {
|
||||
throw exception(PRODUCTION_PLAN_NOT_EXISTS);
|
||||
}
|
||||
|
||||
ProductionPlanDO planDO = BeanUtils.toBean(updateReqVO, ProductionPlanDO.class);
|
||||
planDO.setPlanStatus(CommonConstants.PLAN_STATUS_3);
|
||||
planDO.setPracticalYields(one.getPredictedYields());
|
||||
productionPlanMapper.updateById(planDO);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.farm.controller.admin.deviceinfo.vo.v2.DeviceStat
|
||||
import cn.iocoder.yudao.module.farm.dal.dataobject.deviceinfo.DeviceInfoDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.RealTimeDataResponse;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.util.List;
|
||||
@@ -63,7 +64,7 @@ public interface DeviceInfoService {
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
DeviceInfoDetailV2RespVO getDeviceRealTimeInfo(String id);
|
||||
DeviceInfoDetailV2RespVO getDeviceRealTimeInfo(String id,String dateType);
|
||||
|
||||
/**
|
||||
* 获得设备信息分页
|
||||
@@ -93,7 +94,7 @@ public interface DeviceInfoService {
|
||||
* @param req
|
||||
* @return
|
||||
*/
|
||||
CommonResult<DeviceMonitoringRespVO> getDeviceMonitoring(DeviceMonitoringReqVO req);
|
||||
CommonResult<RealTimeDataResponse> getDeviceMonitoring(DeviceMonitoringReqVO req);
|
||||
|
||||
/**
|
||||
* api接口
|
||||
@@ -110,4 +111,12 @@ public interface DeviceInfoService {
|
||||
List<String> getImage(String deviceType);
|
||||
|
||||
DeviceStateRespVO countDeviceState(String baseId, String tenantId);
|
||||
|
||||
/**
|
||||
* 设备数量统计
|
||||
* @param baseId
|
||||
* @param tenantId
|
||||
* @return
|
||||
*/
|
||||
int countDevice(String baseId, String tenantId);
|
||||
}
|
||||
@@ -15,6 +15,14 @@ import cn.iocoder.yudao.module.farm.dal.mysql.baseinfo.BaseInfoMapper;
|
||||
import cn.iocoder.yudao.module.farm.dal.mysql.deviceclassify.DeviceClassifyMapper;
|
||||
import cn.iocoder.yudao.module.farm.dal.mysql.plotinfo.PlotInfoMapper;
|
||||
import cn.iocoder.yudao.module.farm.enums.CommonConstants;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.EquipmentProducerManager;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.conf.DeviceConf;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.HistoryDataResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.RealTimeDataResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.UnifiedLoginResponse;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.history.HistoryDataListPageReqVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.login.UserLoginReqVO;
|
||||
import cn.iocoder.yudao.module.farm.manager.equipmentproducer.dto.soil.realtime.RealTimeDataReqVO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@@ -26,12 +34,16 @@ import cn.iocoder.yudao.framework.security.core.LoginUser;
|
||||
|
||||
import cn.iocoder.yudao.module.farm.dal.mysql.deviceinfo.DeviceInfoMapper;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
|
||||
import static cn.iocoder.yudao.module.farm.enums.ErrorCodeConstants.DEVICE_CLASS_TYPE_ERROR;
|
||||
@@ -54,6 +66,10 @@ public class DeviceInfoServiceImpl implements DeviceInfoService {
|
||||
private BaseInfoMapper baseInfoMapper;
|
||||
@Resource
|
||||
private PlotInfoMapper plotInfoMapper;
|
||||
@Resource
|
||||
private EquipmentProducerManager equipmentProducerManager;
|
||||
@Resource
|
||||
private DeviceConf deviceConf;
|
||||
|
||||
@Override
|
||||
public String createDeviceInfo(DeviceInfoSaveReqVO createReqVO) {
|
||||
@@ -121,7 +137,7 @@ public class DeviceInfoServiceImpl implements DeviceInfoService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceInfoDetailV2RespVO getDeviceRealTimeInfo(String id) {
|
||||
public DeviceInfoDetailV2RespVO getDeviceRealTimeInfo(String id,String dateType) {
|
||||
|
||||
List<DeviceClassifyDO> deviceClassifyDOS = deviceClassifyMapper.selectList();
|
||||
Map<String, String> map = deviceClassifyDOS.stream()
|
||||
@@ -133,8 +149,58 @@ public class DeviceInfoServiceImpl implements DeviceInfoService {
|
||||
DeviceInfoDetailV2RespVO target = BeanUtils.toBean(deviceInfo, DeviceInfoDetailV2RespVO.class);
|
||||
// 设备类型名称
|
||||
target.setDeviceTypeName(map.getOrDefault(target.getDeviceType(), ""));
|
||||
String deviceUniqueId = deviceInfo.getDeviceUniqueId();
|
||||
|
||||
String soil = "190"; // soil
|
||||
String wf = "189"; // water_fertilizer
|
||||
|
||||
String type = "";
|
||||
if (target.getDeviceType().equals(soil)) {
|
||||
type = "soil";
|
||||
|
||||
// soil
|
||||
UserLoginReqVO userLoginReqVO = new UserLoginReqVO(deviceConf.getFourSituations().getUsername(), deviceConf.getFourSituations().getPassword());
|
||||
UnifiedLoginResponse login = equipmentProducerManager.login(type, getLoginUser().getTenantId(), deviceUniqueId, userLoginReqVO);
|
||||
String token = login.getData().getToken();
|
||||
|
||||
RealTimeDataReqVO soilRequest = new RealTimeDataReqVO();
|
||||
soilRequest.setDeviceAddrs(deviceUniqueId);
|
||||
RealTimeDataResponse realTimeData = equipmentProducerManager.getRealTimeData(type, getLoginUser().getTenantId(), token, soilRequest);
|
||||
|
||||
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
LocalDateTime startLocalDateTime = now.minusDays(3);
|
||||
LocalDateTime endLocalDateTime = now;
|
||||
|
||||
|
||||
String startStr = startLocalDateTime.format(formatter1);
|
||||
String endStr=endLocalDateTime.format(formatter1);
|
||||
|
||||
System.out.println("标准格式-结束: " + startStr);
|
||||
System.out.println("标准格式-开始: " + endStr);
|
||||
|
||||
long startTime = startLocalDateTime.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
|
||||
long endTime = endLocalDateTime.atZone(ZoneId.systemDefault()).toInstant().getEpochSecond();
|
||||
|
||||
HistoryDataListPageReqVO req = new HistoryDataListPageReqVO(String.valueOf(startTime),String.valueOf(endTime));
|
||||
req.setDeviceAddr(deviceUniqueId);
|
||||
req.setPages(1);
|
||||
req.setLimit(500);
|
||||
HistoryDataResponse historyData = equipmentProducerManager.getHistoryData(type, getLoginUser().getTenantId(), token, req);
|
||||
|
||||
DeviceInfoDetailV2RespVO.SoilInfo soilInfo = new DeviceInfoDetailV2RespVO.SoilInfo(deviceUniqueId, realTimeData, historyData);
|
||||
|
||||
target.setSoilInfo(soilInfo);
|
||||
} else {
|
||||
// type = "water_fertilizer";
|
||||
// LoginReqVO loginReqVO = new LoginReqVO();
|
||||
// UnifiedLoginResponse login = equipmentProducerManager.login(type, getLoginUser().getTenantId(), deviceUniqueId, loginReqVO);
|
||||
// String token = login.getData().getToken();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO: 2025/9/26 从设备商服务 获取设备实时/历史数据
|
||||
|
||||
return target;
|
||||
}
|
||||
@@ -181,8 +247,27 @@ public class DeviceInfoServiceImpl implements DeviceInfoService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommonResult<DeviceMonitoringRespVO> getDeviceMonitoring(DeviceMonitoringReqVO req) {
|
||||
return null;
|
||||
public CommonResult<RealTimeDataResponse> getDeviceMonitoring(DeviceMonitoringReqVO req) {
|
||||
try {
|
||||
LambdaQueryWrapperX<DeviceInfoDO> wrapperX = new LambdaQueryWrapperX<>();
|
||||
wrapperX.eq(DeviceInfoDO::getBaseId, req.getBaseId());
|
||||
wrapperX.eq(DeviceInfoDO::getTenantId, req.getTenantId());
|
||||
List<DeviceInfoDO> list = deviceInfoMapper.selectList(wrapperX);
|
||||
DeviceInfoDO d = list.get(0);
|
||||
|
||||
String type = "soil";
|
||||
UserLoginReqVO userLoginReqVO = new UserLoginReqVO(deviceConf.getFourSituations().getUsername(), deviceConf.getFourSituations().getPassword());
|
||||
UnifiedLoginResponse login = equipmentProducerManager.login(type, Long.valueOf(req.getTenantId()), req.getTenantId(), userLoginReqVO);
|
||||
String token = login.getData().getToken();
|
||||
|
||||
RealTimeDataReqVO soilRequest = new RealTimeDataReqVO();
|
||||
soilRequest.setDeviceAddrs("");
|
||||
RealTimeDataResponse realTimeData = equipmentProducerManager.getRealTimeData(type, Long.valueOf(req.getTenantId()), token, soilRequest);
|
||||
|
||||
return success(realTimeData);
|
||||
} catch (Exception e) {
|
||||
return error(500, "");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -219,4 +304,14 @@ public class DeviceInfoServiceImpl implements DeviceInfoService {
|
||||
public DeviceStateRespVO countDeviceState(String baseId,String tenantId) {
|
||||
return deviceInfoMapper.countDeviceState(baseId,tenantId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countDevice(String baseId, String tenantId) {
|
||||
LambdaQueryWrapperX<DeviceInfoDO> wrapperX = new LambdaQueryWrapperX<>();
|
||||
wrapperX.eq(DeviceInfoDO::getTenantId, tenantId);
|
||||
wrapperX.eq(DeviceInfoDO::getDeleted, CommonConstants.NO_CODE);
|
||||
wrapperX.eqIfPresent(DeviceInfoDO::getBaseId, baseId);
|
||||
|
||||
return deviceInfoMapper.selectCount(wrapperX).intValue();
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.farm.dal.mysql.farmingrecord.FarmingRecordMapper;
|
||||
import cn.iocoder.yudao.module.farm.dal.mysql.farmingrecordinput.FarmingRecordInputMapper;
|
||||
import cn.iocoder.yudao.module.farm.dal.mysql.farmingtypemaintenance.FarmingTypeMaintenanceMapper;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
@@ -60,11 +61,13 @@ public class FarmingRecordServiceImpl implements FarmingRecordService {
|
||||
// 处理图片集合转换
|
||||
handleImageConversion(farmingRecord, createReqVO);
|
||||
//投入品集合单条保存
|
||||
createReqVO.getInvestGoodsList().forEach(e -> {
|
||||
e.setId(IdUtil.fastUUID());
|
||||
e.setFarmRecordId(farmingRecord.getId());
|
||||
farmingRecordInputMapper.insert(e);
|
||||
});
|
||||
if (ObjectUtils.isNotEmpty(createReqVO.getInvestGoodsList())) {
|
||||
createReqVO.getInvestGoodsList().forEach(e -> {
|
||||
e.setId(IdUtil.fastUUID());
|
||||
e.setFarmRecordId(farmingRecord.getId());
|
||||
farmingRecordInputMapper.insert(e);
|
||||
});
|
||||
}
|
||||
|
||||
farmingRecordMapper.insert(farmingRecord);
|
||||
// 返回
|
||||
|
||||
@@ -187,7 +187,7 @@ public class HomeServiceImpl implements HomeService {
|
||||
t.setTaskCount(taskCount);
|
||||
t.setLotCount(0); // TODO: 2025/8/31 物联设备数量
|
||||
t.setManager(employeeName);
|
||||
t.setQrCodeUrl(""); // TODO: 2025/8/31 暂无
|
||||
t.setQrCodeUrl(e.getBaseId());
|
||||
t.setPlanInfos(this.getPlanInfoList(e.getBaseId(), e.getPlotId(), employeeName));
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,8 @@ public class ScreenDisasterDataServiceImpl implements ScreenDisasterDataService
|
||||
|
||||
@Override
|
||||
public CommonResult<List<DisasterAnalysisRespVO>> getDisasterStatisticsChart(DisasterAnalysisReqVO req) {
|
||||
return null;
|
||||
List<DisasterAnalysisRespVO> res = screenDisasterDataMapper.countDisasterAnalysis(req);
|
||||
return CommonResult.success(res);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -52,7 +52,6 @@
|
||||
COALESCE(SUM(practical_yields), 0) AS practicalYields
|
||||
FROM farm_production_plan
|
||||
<where>
|
||||
plan_status = 3
|
||||
AND deleted = 0
|
||||
AND production_start_date IS NOT NULL
|
||||
<if test="tenantId != null and tenantId != ''">AND tenant_id = #{tenantId}</if>
|
||||
|
||||
@@ -9,4 +9,63 @@
|
||||
文档可见:https://www.iocoder.cn/MyBatis/x-plugins/
|
||||
-->
|
||||
|
||||
<resultMap id="DisasterAnalysisResultMap"
|
||||
type="cn.iocoder.yudao.module.farm.controller.admin.api.vo.DisasterAnalysisRespVO">
|
||||
<result property="year" column="year"/>
|
||||
<collection property="disasterReports"
|
||||
ofType="cn.iocoder.yudao.module.farm.controller.admin.api.vo.DisasterAnalysisRespVO$DisasterReports">
|
||||
<result property="month" column="month"/>
|
||||
<result property="meteorologyCount" column="meteorology_count"/>
|
||||
<result property="pestCount" column="pest_count"/>
|
||||
</collection>
|
||||
</resultMap>
|
||||
|
||||
<select id="countDisasterAnalysis"
|
||||
parameterType="cn.iocoder.yudao.module.farm.controller.admin.api.vo.DisasterAnalysisReqVO"
|
||||
resultMap="DisasterAnalysisResultMap">
|
||||
|
||||
SELECT y.year,
|
||||
m.month,
|
||||
COALESCE(SUM(CASE WHEN f.category = '0' THEN COALESCE(f.disaster_count, 0) ELSE 0 END),0) as meteorology_count,
|
||||
COALESCE(SUM(CASE WHEN f.category != '0' THEN COALESCE(f.disaster_count, 0) ELSE 0 END), 0) as pest_count
|
||||
FROM (SELECT YEAR (CURDATE()) as year UNION SELECT YEAR (CURDATE()) - 1) y
|
||||
CROSS JOIN
|
||||
(SELECT 1 as month
|
||||
UNION
|
||||
SELECT 2
|
||||
UNION
|
||||
SELECT 3
|
||||
UNION
|
||||
SELECT 4
|
||||
UNION
|
||||
SELECT 5
|
||||
UNION
|
||||
SELECT 6
|
||||
UNION
|
||||
SELECT 7
|
||||
UNION
|
||||
SELECT 8
|
||||
UNION
|
||||
SELECT 9
|
||||
UNION
|
||||
SELECT 10
|
||||
UNION
|
||||
SELECT 11
|
||||
UNION
|
||||
SELECT 12) m
|
||||
LEFT JOIN farm_screen_disaster_data f ON y.year = YEAR (STR_TO_DATE(f.disaster_time, '%Y-%m'))
|
||||
AND m.month = MONTH (STR_TO_DATE(f.disaster_time, '%Y-%m'))
|
||||
AND f.deleted = 0
|
||||
<if test="baseId != null and baseId != ''">
|
||||
AND f.base_id = #{baseId}
|
||||
</if>
|
||||
<if test="tenantId != null and tenantId != ''">
|
||||
AND f.tenant_id = #{tenantId}
|
||||
</if>
|
||||
AND f.disaster_time IS NOT NULL
|
||||
GROUP BY y.year, m.month
|
||||
ORDER BY y.year DESC, m.month
|
||||
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
Reference in New Issue
Block a user