diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/api/road/RoadApiImpl.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/api/road/RoadApiImpl.java index 428601d..9e5325f 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/api/road/RoadApiImpl.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/api/road/RoadApiImpl.java @@ -5,6 +5,7 @@ import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.zteits.urbanops.framework.common.util.http.HttpUtils; import com.zteits.urbanops.framework.common.util.object.BeanUtils; +import com.zteits.urbanops.framework.datapermission.core.annotation.DataPermission; import com.zteits.urbanops.module.garden.controller.admin.road.vo.RoadRespVO; import com.zteits.urbanops.module.garden.dto.road.RoadReqDTO; import com.zteits.urbanops.module.garden.dto.road.RoadRespDTO; @@ -69,6 +70,7 @@ public class RoadApiImpl implements RoadApi { } @Override + @DataPermission(enable = false) public RoadStreetRespDTO getRoadInfoById(String id) { RoadRespVO roadRespVO = roadService.getUniqueRoad(Long.parseLong(id)); if(null == roadRespVO){ diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/app/homepage/vo/TaskDistanceSortRespVO.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/app/homepage/vo/TaskDistanceSortRespVO.java index b39709b..df7ce3c 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/app/homepage/vo/TaskDistanceSortRespVO.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/app/homepage/vo/TaskDistanceSortRespVO.java @@ -55,4 +55,7 @@ public class TaskDistanceSortRespVO extends TaskDetailsRspVo { /** 班组平均完成时长(分钟) */ private BigDecimal teamAvgMinutes; + + /** 个人历史完成率 = 6个月内已完成 / 6个月内总任务数 */ + private BigDecimal historyCompletionRate; } diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/UserTaskEfficiencyDO.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/UserTaskEfficiencyDO.java index 4800a99..eb3f089 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/UserTaskEfficiencyDO.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/dataobject/UserTaskEfficiencyDO.java @@ -53,6 +53,9 @@ public class UserTaskEfficiencyDO extends BaseDO { /** 效率比 = teamAvg / userAvg */ private BigDecimal efficiencyRatio; + /** 个人历史完成率 = 6个月内已完成 / 6个月内总任务数 */ + private BigDecimal historyCompletionRate; + /** 统计周期 yyyy-MM */ private String statPeriod; } diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/UserTaskEfficiencyMapper.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/UserTaskEfficiencyMapper.java index 6c3f04d..01216cf 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/UserTaskEfficiencyMapper.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/UserTaskEfficiencyMapper.java @@ -40,4 +40,7 @@ public interface UserTaskEfficiencyMapper extends BaseMapperX> statWorkOrderEfficiency(@Param("beginTime") String beginTime); + + /** 从 task_statistics 汇总用户 6 个月历史任务总量 */ + List> statHistoryTotalCount(@Param("beginDate") String beginDate); } diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/maintainplan/MaintainPlanDetailMapper.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/maintainplan/MaintainPlanDetailMapper.java index 99a8751..7d7a099 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/maintainplan/MaintainPlanDetailMapper.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/dal/mysql/maintainplan/MaintainPlanDetailMapper.java @@ -3,6 +3,7 @@ package com.zteits.urbanops.module.garden.dal.mysql.maintainplan; import com.baomidou.mybatisplus.core.metadata.IPage; import com.zteits.urbanops.framework.common.pojo.PageResult; +import com.zteits.urbanops.framework.common.util.collection.ArrayUtils; import com.zteits.urbanops.framework.mybatis.core.mapper.BaseMapperX; import com.zteits.urbanops.framework.mybatis.core.query.LambdaQueryWrapperX; import com.zteits.urbanops.module.garden.controller.admin.maintainplan.vo.MaintainPlanDetailPageReqVO; @@ -33,8 +34,8 @@ public interface MaintainPlanDetailMapper extends BaseMapperX getMaintainNotFinishPlanCommitDetail(@Param("req") AppMaintainNotFinishPlanDetailReqVO reqVO); -} \ No newline at end of file +} diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/job/TaskEfficiencyCalculateJob.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/job/TaskEfficiencyCalculateJob.java index c106657..3f28726 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/job/TaskEfficiencyCalculateJob.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/job/TaskEfficiencyCalculateJob.java @@ -39,6 +39,7 @@ public class TaskEfficiencyCalculateJob implements JobHandler { // 2. 6个月窗口 String beginTime = LocalDate.now().minusMonths(6).withDayOfMonth(1) + " 00:00:00"; + String beginDate = LocalDate.now().minusMonths(6).withDayOfMonth(1).toString(); // 3. 三类任务分别统计 List all = new ArrayList<>(); @@ -59,6 +60,19 @@ public class TaskEfficiencyCalculateJob implements JobHandler { e.setEfficiencyRatio(calcRatio(e.getAvgMinutes(), e.getTeamAvgMinutes())); } + // 5.5 计算个人历史完成率 + Map> historyMap = loadHistoryTotalMap(beginDate); + for (UserTaskEfficiencyDO e : all) { + Map h = historyMap.get(e.getUserId()); + if (h != null) { + long total = toLong(h.get("history_total")); + long completed = toLong(h.get("history_completed")); + e.setHistoryCompletionRate(total > 0 + ? BigDecimal.valueOf(completed).divide(BigDecimal.valueOf(total), 4, RoundingMode.HALF_UP) + : BigDecimal.ZERO); + } + } + // 6. 生成大类汇总(ALL) all.addAll(buildCategorySummary(all, statPeriod)); @@ -132,6 +146,17 @@ public class TaskEfficiencyCalculateJob implements JobHandler { return ratio; } + private Map> loadHistoryTotalMap(String beginDate) { + List> rows = userTaskEfficiencyMapper.statHistoryTotalCount(beginDate); + Map> map = new LinkedHashMap<>(); + if (rows != null) { + for (Map row : rows) { + map.put(toLong(row.get("user_id")), row); + } + } + return map; + } + private List buildCategorySummary(List all, String statPeriod) { Map> catMap = new LinkedHashMap<>(); for (UserTaskEfficiencyDO e : all) { @@ -178,6 +203,19 @@ public class TaskEfficiencyCalculateJob implements JobHandler { s.setEfficiencyRatio(ratioWeight > 0 ? weightedRatio.divide(BigDecimal.valueOf(ratioWeight), 4, RoundingMode.HALF_UP) : BigDecimal.ONE); + // 加权计算 historyCompletionRate + BigDecimal weightedRate = BigDecimal.ZERO; + int rateWeightCnt = 0; + for (UserTaskEfficiencyDO e : group) { + if (e.getCompletedCount() > 0 && e.getHistoryCompletionRate() != null) { + weightedRate = weightedRate.add( + e.getHistoryCompletionRate().multiply(BigDecimal.valueOf(e.getCompletedCount()))); + rateWeightCnt += e.getCompletedCount(); + } + } + s.setHistoryCompletionRate(rateWeightCnt > 0 + ? weightedRate.divide(BigDecimal.valueOf(rateWeightCnt), 4, RoundingMode.HALF_UP) + : BigDecimal.ZERO); summaries.add(s); } return summaries; diff --git a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/homepage/HomepageSummaryServiceImpl.java b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/homepage/HomepageSummaryServiceImpl.java index 8273e02..830d84c 100644 --- a/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/homepage/HomepageSummaryServiceImpl.java +++ b/urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/homepage/HomepageSummaryServiceImpl.java @@ -429,6 +429,8 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ @Override public TaskDistanceSortResultVO queryTaskDetailsWithDistance(AppTaskDistanceSortReqVO req) { + Log.info("queryTaskDetailsWithDistance: " + JSON.toJSONString(req)); + // 1. 获取当前登录用户信息 Long userId = SecurityFrameworkUtils.getLoginUserId(); Long deptId = SecurityFrameworkUtils.getDeptId(); @@ -456,9 +458,20 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ if (db == null) return -1; return da.compareTo(db); }); - result.setSortedTasks(sortedTasks); result.setTeamProgress(teamProgress); result.setTotalPendingTasks(sortedTasks.size()); + + // 4.5 加载效率数据,设置个人历史完成率 + Map effMap = loadEfficiencyMap(userId); + for (TaskDistanceSortRespVO task : sortedTasks) { + UserTaskEfficiencyDO effDO = lookupEfficiency(effMap, task.getTaskType(), task.getTaskSubType()); + if (effDO != null && effDO.getHistoryCompletionRate() != null) { + task.setHistoryCompletionRate(effDO.getHistoryCompletionRate()); + } + } + + result.setSortedTasks(sortedTasks); + int totalDist = 0; int totalWalkMin = 0; int totalTriMin = 0; @@ -506,6 +519,15 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ result.add(sortVo); } } + // 加载效率数据,设置个人历史完成率 + Map effMap = loadEfficiencyMap(userId); + for (TaskDistanceSortRespVO task : result) { + UserTaskEfficiencyDO effDO = lookupEfficiency(effMap, task.getTaskType(), task.getTaskSubType()); + if (effDO != null && effDO.getHistoryCompletionRate() != null) { + task.setHistoryCompletionRate(effDO.getHistoryCompletionRate()); + } + } + logTaskList("已办SQL原始记录", result); Log.info("返回App参数: " + JSON.toJSONString(result)); return result; } @@ -540,6 +562,7 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ LocalDateTime now = LocalDateTime.now(); List allTasks = homepageSummaryMapper .queryPendingTaskDetailsWithGps(roleIds, userId, deptId, now); + logTaskList("待办SQL原始记录(距离排序)", allTasks); // 分离有 GPS 和无 GPS 任务 List tasksWithGps = new ArrayList<>(); @@ -660,6 +683,7 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ @Override public TaskDistanceSortResultVO queryTaskDetailsWithSmartSort(AppTaskSmartSortReqVO req) { + Log.info("queryTaskDetailsWithSmartSort: " + JSON.toJSONString(req)); Long userId = SecurityFrameworkUtils.getLoginUserId(); Long deptId = SecurityFrameworkUtils.getDeptId(); @@ -669,17 +693,17 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ TeamProgressVO teamProgress = buildTeamProgress(userId, deptId); TaskDistanceSortResultVO result = new TaskDistanceSortResultVO(); sortedTasks.sort((a, b) -> { - Integer da = a.getDistance(), db = b.getDistance(); - if (da == null && db == null) return 0; - if (da == null) return 1; - if (db == null) return -1; - return da.compareTo(db); - }); - result.setSortedTasks(sortedTasks); + Integer da = a.getDistance(), db = b.getDistance(); + if (da == null && db == null) return 0; + if (da == null) return 1; + if (db == null) return -1; + return da.compareTo(db); + }); result.setTeamProgress(teamProgress); result.setTotalPendingTasks(sortedTasks.size()); + result.setSortedTasks(sortedTasks); Log.info("返回App参数: " + JSON.toJSONString(result)); - return result; + return result; } List roleIds = roleApi.getRoleIdsByUserId(userId); @@ -706,13 +730,23 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ } catch (Exception e) { Log.warn("读取智能排序配置失败", e); } + Log.info("智能排序配置: distWeight=" + distWeight + ", effWeight=" + effWeight + + ", threshold=" + threshold + ", clamp=[" + clampMin + "," + clampMax + "]"); // 2. 查询今日待办任务 List allTasks = homepageSummaryMapper .queryPendingTaskDetailsWithGps(roleIds, userId, deptId, LocalDateTime.now()); + Log.info("待办任务总数: " + (allTasks != null ? allTasks.size() : 0) + ", userId=" + userId + ", deptId=" + deptId); + logTaskList("待办SQL原始记录(智能排序)", allTasks); // 3. 查询效率矩阵 Map effMap = loadEfficiencyMap(userId); + Log.info("效率矩阵条目数: " + effMap.size()); + if (!effMap.isEmpty()) { + effMap.forEach((k, v) -> Log.info(" eff: key=" + k + ", ratio=" + v.getEfficiencyRatio() + + ", userAvg=" + v.getAvgMinutes() + ", teamAvg=" + v.getTeamAvgMinutes() + + ", cnt=" + v.getCompletedCount())); + } // 4. 为每个任务打分 List tasksWithGps = new ArrayList<>(); @@ -728,6 +762,7 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ if (effDO != null) { task.setUserAvgMinutes(effDO.getAvgMinutes()); task.setTeamAvgMinutes(effDO.getTeamAvgMinutes()); + task.setHistoryCompletionRate(effDO.getHistoryCompletionRate()); } if (task.getTaskLat() != null && task.getTaskLon() != null) { @@ -737,10 +772,20 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ double distScore = Math.max(0, 1 - dist / threshold); task.setDistanceScore(Math.round(distScore * 100.0) / 100.0); task.setCompositeScore(Math.round((distWeight * distScore + effWeight * effScore) * 100.0) / 100.0); + Log.info(" score: " + task.getTaskName() + " | dist=" + (int)dist + "m" + + " | distScore=" + task.getDistanceScore() + + " | effScore=" + task.getEfficiencyScore() + + " | eff%=" + task.getEfficiencyPercent() + + " | composite=" + task.getCompositeScore() + + " | type=" + task.getTaskType() + "/" + task.getTaskSubType()); tasksWithGps.add(task); } else { task.setDistanceScore(0.0); task.setCompositeScore(Math.round((effWeight * effScore) * 100.0) / 100.0); + Log.info(" score(无GPS): " + task.getTaskName() + + " | effScore=" + task.getEfficiencyScore() + + " | eff%=" + task.getEfficiencyPercent() + + " | type=" + task.getTaskType() + "/" + task.getTaskSubType()); tasksWithoutGps.add(task); } } @@ -782,9 +827,10 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ if (db == null) return -1; return da.compareTo(db); }); - result.setSortedTasks(sortedTasks); result.setTeamProgress(teamProgress); result.setTotalPendingTasks(sortedTasks.size()); + result.setSortedTasks(sortedTasks); + int totalDist = 0; for (TaskDistanceSortRespVO t : sortedTasks) { if (t.getDistance() != null) totalDist += t.getDistance(); @@ -833,4 +879,21 @@ public class HomepageSummaryServiceImpl implements HomepageSummaryService{ if (val < min) return min; return val; } + + private void logTaskList(String tag, List list) { + if (list == null) { + Log.info(tag + ": null"); + return; + } + Log.info(tag + ": 共" + list.size() + "条"); + for (int i = 0; i < list.size(); i++) { + TaskDistanceSortRespVO t = list.get(i); + Log.info(tag + "[" + i + "] taskName=" + t.getTaskName() + + ", taskType=" + t.getTaskType() + + ", planNo=" + t.getPlanNo() + + ", batchNo=" + t.getBatchNo() + + ", distance=" + t.getDistance() + + ", lat=" + t.getTaskLat() + ", lon=" + t.getTaskLon()); + } + } } diff --git a/urbanops-module-garden/src/main/resources/mapper/UserTaskEfficiencyMapper.xml b/urbanops-module-garden/src/main/resources/mapper/UserTaskEfficiencyMapper.xml index 9e14855..efeb5fa 100644 --- a/urbanops-module-garden/src/main/resources/mapper/UserTaskEfficiencyMapper.xml +++ b/urbanops-module-garden/src/main/resources/mapper/UserTaskEfficiencyMapper.xml @@ -71,4 +71,15 @@ GROUP BY t.ASSIGNEE_, u.dept_id, m.order_type + + + diff --git a/urbanops-module-garden/src/main/resources/mapper/homepage/HomepageSummaryMapper.xml b/urbanops-module-garden/src/main/resources/mapper/homepage/HomepageSummaryMapper.xml index c426137..3f2740b 100644 --- a/urbanops-module-garden/src/main/resources/mapper/homepage/HomepageSummaryMapper.xml +++ b/urbanops-module-garden/src/main/resources/mapper/homepage/HomepageSummaryMapper.xml @@ -647,7 +647,7 @@ #{roleId} - AND NOT EXISTS (SELECT 1 FROM garden_inspection_plan_commit ic WHERE ic.batch_no = a.batch_no AND ic.user_id = #{userId}) + AND r.starting_latitude IS NOT NULL AND r.starting_latitude != '' UNION ALL @@ -677,7 +677,7 @@ #{roleId} - AND NOT EXISTS (SELECT 1 FROM garden_maintain_plan_commit mc WHERE mc.batch_no = a.batch_no AND mc.user_id = #{userId}) + AND r.starting_latitude IS NOT NULL AND r.starting_latitude != '' ) t diff --git a/urbanops-module-system/src/main/java/com/zteits/urbanops/module/system/enums/DictTypeConstants.java b/urbanops-module-system/src/main/java/com/zteits/urbanops/module/system/enums/DictTypeConstants.java index a539820..3fddded 100644 --- a/urbanops-module-system/src/main/java/com/zteits/urbanops/module/system/enums/DictTypeConstants.java +++ b/urbanops-module-system/src/main/java/com/zteits/urbanops/module/system/enums/DictTypeConstants.java @@ -36,4 +36,6 @@ public interface DictTypeConstants { String TASK_SORT_WEIGHT_CONFIG = "task_sort_weight_config"; // 智能排序权重配置 + String COMPLETION_RATE_CONFIG = "completion_rate_config"; // 个人历史完成率配置 + } diff --git a/urbanops-server/src/main/resources/application.yaml b/urbanops-server/src/main/resources/application.yaml index 66d32b9..944caea 100644 --- a/urbanops-server/src/main/resources/application.yaml +++ b/urbanops-server/src/main/resources/application.yaml @@ -3,7 +3,7 @@ spring: name: urbanops-server profiles: - active: dev + active: prod main: