From 024249f52421fe60b8358549b3d9206bff113246 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=BE=BE=E5=AF=8C=E6=96=8C?= Date: Tue, 2 Sep 2025 20:40:01 +0800 Subject: [PATCH] =?UTF-8?q?feat=20(farm):=20=E5=86=9C=E5=9C=BA=E9=A6=96?= =?UTF-8?q?=E9=A1=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为生产计划随机一个在其地块范围内的坐标 --- .../controller/admin/home/vo/HomeInfo.java | 3 +- .../farm/scheduled/FarmingRecordJob.java | 4 +- .../farm/service/home/HomeServiceImpl.java | 18 ++- .../module/farm/utils/LeafletjsUtil.java | 113 ++++++++++++++++++ 4 files changed, 133 insertions(+), 5 deletions(-) create mode 100644 yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/utils/LeafletjsUtil.java diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/home/vo/HomeInfo.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/home/vo/HomeInfo.java index 8e60001f..f9a0a8aa 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/home/vo/HomeInfo.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/controller/admin/home/vo/HomeInfo.java @@ -167,7 +167,6 @@ public class HomeInfo { private String plotName; @Schema(description = "基地负责人") private String manager; - @Schema(description = "物种名称") private String plantSpeciesName; @Schema(description = "计划编号") @@ -188,5 +187,7 @@ public class HomeInfo { private Integer planSubStatus; @Schema(description = "计划执行子状态-名称") private String planSubStatusName; + @Schema(description = "计划模型坐标") + private String planModelPoint; } } diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/scheduled/FarmingRecordJob.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/scheduled/FarmingRecordJob.java index 623ff9c2..238818b5 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/scheduled/FarmingRecordJob.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/scheduled/FarmingRecordJob.java @@ -76,9 +76,9 @@ public class FarmingRecordJob implements JobHandler { // 获取[进行中]状态的计划 List plans = productionPlanService.getProductionPlans(); Map planMap = plans.stream().filter(e -> Objects.equals(e.getPlanStatus(), PLAN_STATUS_2)).collect(Collectors.toMap(ProductionPlanDO::getId, e -> e, (v1, v2) -> v1)); - List taskIdList = plans.stream().filter(e -> Objects.equals(e.getPlanStatus(), PLAN_STATUS_2)).map(ProductionPlanDO::getId).toList(); - // 获取引用模型集合 + + // 获取引用模型集合 key: modelId; Map> modelIdMap = modelManagementService.getRecordList(taskIdList); List farmingRecordSaveReqVOList = new ArrayList<>(); diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/home/HomeServiceImpl.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/home/HomeServiceImpl.java index 1959086f..17c3276b 100644 --- a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/home/HomeServiceImpl.java +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/service/home/HomeServiceImpl.java @@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.farm.service.modelmanagement.ModelManagementServi 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; +import cn.iocoder.yudao.module.farm.utils.LeafletjsUtil; import org.apache.commons.lang3.ObjectUtils; import org.springframework.stereotype.Service; @@ -68,11 +69,20 @@ public class HomeServiceImpl implements HomeService { BaseOverviewInfo baseOverviewInfo = this.getBaseOverviewInfo(baseObj, employeeNameMap); List plotPopupFrames = this.getPlotPopupFrame(baseObj, employeeNameMap); List plotInfos = this.getPlotInfoList(baseId, employeeNameMap); - List planInfos = this.getPlanInfoList(baseId, "", null); +// List planInfos = this.getPlanInfoList(baseId, "", null); + List planInfos = getPlans(plotInfos); StatisticalInfo statisticalInfo = this.getStatisticalInfo(baseId); return new HomeInfo(baseOverviewInfo, plotPopupFrames, plotInfos, planInfos, statisticalInfo); } + private List getPlans(List plotInfos) { + List res = new ArrayList<>(); + for (PlotInfo plotInfo : plotInfos) { + res.addAll(plotInfo.getPlotOrCropInfo().getPlanInfos()); + } + return res; + } + private StatisticalInfo getStatisticalInfo(String baseId) { Integer taskCount = productionPlanService.getTodayTaskCount(baseId); Integer warningCount = 0; // TODO: 2025/9/1 告警数量 @@ -163,6 +173,7 @@ public class HomeServiceImpl implements HomeService { private List getPlanInfoList(String baseId,String plotId,String employeeName) { List targetList = new ArrayList<>(); + PlotInfoDO plotObj = plotInfoService.getPlotInfoByPlotId(plotId); List plans = productionPlanService.getProductionPlans(baseId,plotId); for (ProductionPlanDO e : plans) { String beingCropName = productionPlanService.getPlantSpeciesCodeForName(e.getPlantSpeciesCode()); @@ -184,12 +195,15 @@ public class HomeServiceImpl implements HomeService { target.setPlanStatus(e.getPlanStatus()); target.setPlanStatusName(PLAN_MAP.getOrDefault(e.getPlanStatus(),"未开始")); target.setPlanSubStatus(e.getPlanSubStatus()); - target.setPlanSubStatusName(PLAN_MAP.getOrDefault(e.getPlanSubStatus(),"逾期未开始")); + target.setPlanSubStatusName(PLAN_MAP.getOrDefault(e.getPlanSubStatus(), "逾期未开始")); + String pointsInPolygon = LeafletjsUtil.generateRandomPointsInPolygon(plotObj.getPoint()); + target.setPlanModelPoint(pointsInPolygon); targetList.add(target); } return targetList; } + @Override public OutlinedInfoVO getOutlinedInfo(String baseId) { OutlinedInfoVO res = new OutlinedInfoVO(); diff --git a/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/utils/LeafletjsUtil.java b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/utils/LeafletjsUtil.java new file mode 100644 index 00000000..0c9549f7 --- /dev/null +++ b/yudao-module-farm/src/main/java/cn/iocoder/yudao/module/farm/utils/LeafletjsUtil.java @@ -0,0 +1,113 @@ +package cn.iocoder.yudao.module.farm.utils; + + +import lombok.Data; +import org.aspectj.bridge.Message; + +import java.awt.geom.Path2D; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * @description: 天地图工具类 + * @author: binda + * @date: 2025/9/2 19:38 + */ +public class LeafletjsUtil { + + public static void main(String[] args) { + String s = "{\"marker\": null, \"polygon\": [{\"lat\": 28.99705470774261, \"lng\": 118.18360090255736}, {\"lat\": 28.99717666335354, \"lng\": 118.18385839462282}, {\"lat\": 28.99706408894856, \"lng\": 118.18441629409791}, {\"lat\": 28.996726364998096, \"lng\": 118.18449139595032}, {\"lat\": 28.99656688386018, \"lng\": 118.18440020084384}, {\"lat\": 28.996407307540014, \"lng\": 118.18392276763916}, {\"lat\": 28.99628249933895, \"lng\": 118.18372108295289}, {\"lat\": 28.99648245256991, \"lng\": 118.18348824977876}, {\"lat\": 28.99678265239978, \"lng\": 118.18330585956576}, {\"lat\": 28.99682017731722, \"lng\": 118.1834936141968}]}"; + System.out.println(generateRandomPointsInPolygon(s)); + } + + public static String generateRandomPointsInPolygon(String pointJsonStr) { + List points = LeafletjsUtil.generateRandomPointsInPolygon(pointJsonStr, 3); + Point point = points.stream().findAny().get(); + return "{\"lat\": "+point.getLat()+", \"lng\": "+point.getLng()+"}"; + } + + /** + * 在多边形内生成随机点 + */ + public static List generateRandomPointsInPolygon(String pointJsonStr, int count) { + List polygon = parsePolygonFromJson(pointJsonStr); + + List points = new ArrayList<>(); + Random random = new Random(); + + // 计算多边形的边界框 + double minLat = Double.MAX_VALUE; + double maxLat = Double.MIN_VALUE; + double minLng = Double.MAX_VALUE; + double maxLng = Double.MIN_VALUE; + + for (Point point : polygon) { + minLat = Math.min(minLat, point.lat); + maxLat = Math.max(maxLat, point.lat); + minLng = Math.min(minLng, point.lng); + maxLng = Math.max(maxLng, point.lng); + } + + // 创建多边形路径 + Path2D.Double path = new Path2D.Double(); + Point first = polygon.get(0); + path.moveTo(first.lng, first.lat); + for (int i = 1; i < polygon.size(); i++) { + Point point = polygon.get(i); + path.lineTo(point.lng, point.lat); + } + path.closePath(); + + // 生成随机点直到满足数量要求 + while (points.size() < count) { + // 在边界框内生成随机点 + double lat = minLat + random.nextDouble() * (maxLat - minLat); + double lng = minLng + random.nextDouble() * (maxLng - minLng); + + // 检查点是否在多边形内 + if (path.contains(lng, lat)) { + points.add(new Point(lat, lng)); + } + } + + return points; + } + + public static List parsePolygonFromJson(String jsonString) { + List points = new ArrayList<>(); + + // 正则表达式匹配lat和lng + Pattern pattern = Pattern.compile("\"lat\":\\s*([\\d.]+),\\s*\"lng\":\\s*([\\d.]+)"); + Matcher matcher = pattern.matcher(jsonString); + + while (matcher.find()) { + double lat = Double.parseDouble(matcher.group(1)); + double lng = Double.parseDouble(matcher.group(2)); + points.add(new Point(lat, lng)); + } + + if (points.isEmpty()) { + throw new IllegalArgumentException("未找到有效的坐标数据"); + } + + return points; + } + + /** + * 点类 + */ + @Data + public static class Point { + double lat; + double lng; + + public Point(double lat, double lng) { + this.lat = lat; + this.lng = lng; + } + } +}