Commit f7fcb204d96745b842137441373d15cabeafc87a
1 parent
1606feb1
feat(garden): 新增任务距离排序和智能排序功能
- 实现任务按距离排序和班组进度统计功能 - 添加任务智能排序(距离+个人效率加权)功能 - 新增GPS距离计算工具类和相关数据传输对象 - 添加出行速度配置和智能排序权重配置字典类型 - 实现用户任务效率预计算定时任务 - 优化API签名切面注解使用方式 - 添加微信公众号开放平台回调接口免登录配置
Showing
3 changed files
with
26 additions
and
3 deletions
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/job/TaskEfficiencyCalculateJob.java
| @@ -6,6 +6,7 @@ import com.zteits.urbanops.module.garden.dal.mysql.UserTaskEfficiencyMapper; | @@ -6,6 +6,7 @@ import com.zteits.urbanops.module.garden.dal.mysql.UserTaskEfficiencyMapper; | ||
| 6 | import jakarta.annotation.Resource; | 6 | import jakarta.annotation.Resource; |
| 7 | import lombok.extern.slf4j.Slf4j; | 7 | import lombok.extern.slf4j.Slf4j; |
| 8 | import org.springframework.stereotype.Component; | 8 | import org.springframework.stereotype.Component; |
| 9 | +import org.springframework.transaction.annotation.Transactional; | ||
| 9 | 10 | ||
| 10 | import java.math.BigDecimal; | 11 | import java.math.BigDecimal; |
| 11 | import java.math.RoundingMode; | 12 | import java.math.RoundingMode; |
| @@ -28,6 +29,7 @@ public class TaskEfficiencyCalculateJob implements JobHandler { | @@ -28,6 +29,7 @@ public class TaskEfficiencyCalculateJob implements JobHandler { | ||
| 28 | private UserTaskEfficiencyMapper userTaskEfficiencyMapper; | 29 | private UserTaskEfficiencyMapper userTaskEfficiencyMapper; |
| 29 | 30 | ||
| 30 | @Override | 31 | @Override |
| 32 | + @Transactional(rollbackFor = Exception.class) | ||
| 31 | public String execute(String param) { | 33 | public String execute(String param) { |
| 32 | String statPeriod = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM")); | 34 | String statPeriod = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM")); |
| 33 | log.info("TaskEfficiencyCalculateJob start, statPeriod={}", statPeriod); | 35 | log.info("TaskEfficiencyCalculateJob start, statPeriod={}", statPeriod); |
| @@ -67,8 +69,8 @@ public class TaskEfficiencyCalculateJob implements JobHandler { | @@ -67,8 +69,8 @@ public class TaskEfficiencyCalculateJob implements JobHandler { | ||
| 67 | e.setUpdater("job"); | 69 | e.setUpdater("job"); |
| 68 | e.setCreateTime(now); | 70 | e.setCreateTime(now); |
| 69 | e.setUpdateTime(now); | 71 | e.setUpdateTime(now); |
| 70 | - userTaskEfficiencyMapper.insert(e); | ||
| 71 | } | 72 | } |
| 73 | + userTaskEfficiencyMapper.insertBatch(all); | ||
| 72 | 74 | ||
| 73 | log.info("TaskEfficiencyCalculateJob done, total={}", all.size()); | 75 | log.info("TaskEfficiencyCalculateJob done, total={}", all.size()); |
| 74 | return "success, total=" + all.size(); | 76 | return "success, total=" + all.size(); |
| @@ -155,8 +157,27 @@ public class TaskEfficiencyCalculateJob implements JobHandler { | @@ -155,8 +157,27 @@ public class TaskEfficiencyCalculateJob implements JobHandler { | ||
| 155 | s.setAvgMinutes(totalCnt > 0 | 157 | s.setAvgMinutes(totalCnt > 0 |
| 156 | ? BigDecimal.valueOf(totalMin).divide(BigDecimal.valueOf(totalCnt), 2, RoundingMode.HALF_UP) | 158 | ? BigDecimal.valueOf(totalMin).divide(BigDecimal.valueOf(totalCnt), 2, RoundingMode.HALF_UP) |
| 157 | : BigDecimal.ZERO); | 159 | : BigDecimal.ZERO); |
| 158 | - s.setTeamAvgMinutes(group.get(0).getTeamAvgMinutes()); | ||
| 159 | - s.setEfficiencyRatio(calcRatio(s.getAvgMinutes(), s.getTeamAvgMinutes())); | 160 | + // 大类汇总:按 completed_count 加权计算 teamAvg 和 efficiencyRatio |
| 161 | + long teamTotalMin = 0; | ||
| 162 | + int teamTotalCnt = 0; | ||
| 163 | + BigDecimal weightedRatio = BigDecimal.ZERO; | ||
| 164 | + int ratioWeight = 0; | ||
| 165 | + for (UserTaskEfficiencyDO e : group) { | ||
| 166 | + if (e.getCompletedCount() > 0 && e.getEfficiencyRatio() != null) { | ||
| 167 | + weightedRatio = weightedRatio.add( | ||
| 168 | + e.getEfficiencyRatio().multiply(BigDecimal.valueOf(e.getCompletedCount()))); | ||
| 169 | + ratioWeight += e.getCompletedCount(); | ||
| 170 | + } | ||
| 171 | + teamTotalMin += e.getTeamAvgMinutes() != null | ||
| 172 | + ? e.getTeamAvgMinutes().multiply(BigDecimal.valueOf(e.getCompletedCount())).longValue() : 0; | ||
| 173 | + teamTotalCnt += e.getCompletedCount() != null ? e.getCompletedCount() : 0; | ||
| 174 | + } | ||
| 175 | + s.setTeamAvgMinutes(teamTotalCnt > 0 | ||
| 176 | + ? BigDecimal.valueOf(teamTotalMin).divide(BigDecimal.valueOf(teamTotalCnt), 2, RoundingMode.HALF_UP) | ||
| 177 | + : BigDecimal.ZERO); | ||
| 178 | + s.setEfficiencyRatio(ratioWeight > 0 | ||
| 179 | + ? weightedRatio.divide(BigDecimal.valueOf(ratioWeight), 4, RoundingMode.HALF_UP) | ||
| 180 | + : BigDecimal.ONE); | ||
| 160 | summaries.add(s); | 181 | summaries.add(s); |
| 161 | } | 182 | } |
| 162 | return summaries; | 183 | return summaries; |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/homepage/HomepageSummaryServiceImpl.java
| @@ -599,6 +599,7 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ | @@ -599,6 +599,7 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ | ||
| 599 | int d = (int) Math.round(GpsDistanceUtil.haversineDistance(userLat, userLon, | 599 | int d = (int) Math.round(GpsDistanceUtil.haversineDistance(userLat, userLon, |
| 600 | t.getTaskLat().doubleValue(), t.getTaskLon().doubleValue())); | 600 | t.getTaskLat().doubleValue(), t.getTaskLon().doubleValue())); |
| 601 | t.setDistance(d); | 601 | t.setDistance(d); |
| 602 | + t.setCumulativeDistance(null); | ||
| 602 | t.setEstimatedWalkingMinutes((int) Math.ceil(d / walkingSpeedMperMin)); | 603 | t.setEstimatedWalkingMinutes((int) Math.ceil(d / walkingSpeedMperMin)); |
| 603 | t.setEstimatedTricycleMinutes((int) Math.ceil(d / tricycleSpeedMperMin)); | 604 | t.setEstimatedTricycleMinutes((int) Math.ceil(d / tricycleSpeedMperMin)); |
| 604 | } | 605 | } |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/util/GpsDistanceUtil.java
| @@ -26,6 +26,7 @@ public class GpsDistanceUtil { | @@ -26,6 +26,7 @@ public class GpsDistanceUtil { | ||
| 26 | double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) | 26 | double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) |
| 27 | + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) | 27 | + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) |
| 28 | * Math.sin(dLon / 2) * Math.sin(dLon / 2); | 28 | * Math.sin(dLon / 2) * Math.sin(dLon / 2); |
| 29 | + a = Math.min(1.0, a); // 防止浮点精度导致 a > 1 产生 NaN | ||
| 29 | double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); | 30 | double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); |
| 30 | return EARTH_RADIUS_M * c; | 31 | return EARTH_RADIUS_M * c; |
| 31 | } | 32 | } |