Commit f7fcb204d96745b842137441373d15cabeafc87a

Authored by 王彪总
1 parent 1606feb1

feat(garden): 新增任务距离排序和智能排序功能

- 实现任务按距离排序和班组进度统计功能
- 添加任务智能排序(距离+个人效率加权)功能
- 新增GPS距离计算工具类和相关数据传输对象
- 添加出行速度配置和智能排序权重配置字典类型
- 实现用户任务效率预计算定时任务
- 优化API签名切面注解使用方式
- 添加微信公众号开放平台回调接口免登录配置
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 import jakarta.annotation.Resource;
7 7 import lombok.extern.slf4j.Slf4j;
8 8 import org.springframework.stereotype.Component;
  9 +import org.springframework.transaction.annotation.Transactional;
9 10  
10 11 import java.math.BigDecimal;
11 12 import java.math.RoundingMode;
... ... @@ -28,6 +29,7 @@ public class TaskEfficiencyCalculateJob implements JobHandler {
28 29 private UserTaskEfficiencyMapper userTaskEfficiencyMapper;
29 30  
30 31 @Override
  32 + @Transactional(rollbackFor = Exception.class)
31 33 public String execute(String param) {
32 34 String statPeriod = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM"));
33 35 log.info("TaskEfficiencyCalculateJob start, statPeriod={}", statPeriod);
... ... @@ -67,8 +69,8 @@ public class TaskEfficiencyCalculateJob implements JobHandler {
67 69 e.setUpdater("job");
68 70 e.setCreateTime(now);
69 71 e.setUpdateTime(now);
70   - userTaskEfficiencyMapper.insert(e);
71 72 }
  73 + userTaskEfficiencyMapper.insertBatch(all);
72 74  
73 75 log.info("TaskEfficiencyCalculateJob done, total={}", all.size());
74 76 return "success, total=" + all.size();
... ... @@ -155,8 +157,27 @@ public class TaskEfficiencyCalculateJob implements JobHandler {
155 157 s.setAvgMinutes(totalCnt > 0
156 158 ? BigDecimal.valueOf(totalMin).divide(BigDecimal.valueOf(totalCnt), 2, RoundingMode.HALF_UP)
157 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 181 summaries.add(s);
161 182 }
162 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 599 int d = (int) Math.round(GpsDistanceUtil.haversineDistance(userLat, userLon,
600 600 t.getTaskLat().doubleValue(), t.getTaskLon().doubleValue()));
601 601 t.setDistance(d);
  602 + t.setCumulativeDistance(null);
602 603 t.setEstimatedWalkingMinutes((int) Math.ceil(d / walkingSpeedMperMin));
603 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 26 double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
27 27 + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
28 28 * Math.sin(dLon / 2) * Math.sin(dLon / 2);
  29 + a = Math.min(1.0, a); // 防止浮点精度导致 a > 1 产生 NaN
29 30 double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
30 31 return EARTH_RADIUS_M * c;
31 32 }
... ...