From ec7d0e09df19018cd5b190c3135a0eb807bd8b19 Mon Sep 17 00:00:00 2001 From: moonlight557 <2292218861@qq.com> Date: Mon, 13 Oct 2025 16:27:30 +0800 Subject: [PATCH] init --- .../statistic/Util/ApiResponse.java | 2 +- .../statistic/config/CorsConfig.java | 28 +++ .../controller/OrgStatisticController.java | 35 ---- .../controller/StatisticController.java | 86 ++++++++ .../LyStatistic/statistic/dto/RootTask.java | 18 ++ .../statistic/dto/TaskStatisticResult.java | 5 +- .../statistic/dto/UserStatistic.java | 6 +- .../statistic/dto/UserTaskCount.java | 14 -- .../mapper/DistrictSchemaMapper.java | 16 ++ .../statistic/mapper/SchemaMapper.java | 13 ++ .../statistic/mapper/TaskStatisticMapper.java | 49 +++-- .../statistic/mapper/UnitInfoMapper.java | 14 ++ .../service/DistrictStatisticService.java | 45 +++++ .../service/OrgStatisticService.java | 19 +- .../service/TaskStatisticService.java | 183 +++++++++++++----- .../statistic/service/UnitInfoService.java | 24 +++ .../service/UserStatisticService.java | 45 +++++ src/main/resources/application.properties | 2 +- .../resources/mapper/DistrictSchemaMapper.xml | 25 +++ src/main/resources/mapper/SchemaMapper.xml | 14 ++ .../resources/mapper/TaskStatisticMapper.xml | 85 ++++++-- src/main/resources/mapper/UnitInfoMapper.xml | 34 ++++ src/main/resources/mapper/UserStaffMapper.xml | 4 +- 23 files changed, 620 insertions(+), 146 deletions(-) create mode 100644 src/main/java/com/whu/edu/LyStatistic/statistic/config/CorsConfig.java delete mode 100644 src/main/java/com/whu/edu/LyStatistic/statistic/controller/OrgStatisticController.java create mode 100644 src/main/java/com/whu/edu/LyStatistic/statistic/controller/StatisticController.java create mode 100644 src/main/java/com/whu/edu/LyStatistic/statistic/dto/RootTask.java delete mode 100644 src/main/java/com/whu/edu/LyStatistic/statistic/dto/UserTaskCount.java create mode 100644 src/main/java/com/whu/edu/LyStatistic/statistic/mapper/DistrictSchemaMapper.java create mode 100644 src/main/java/com/whu/edu/LyStatistic/statistic/mapper/SchemaMapper.java create mode 100644 src/main/java/com/whu/edu/LyStatistic/statistic/mapper/UnitInfoMapper.java create mode 100644 src/main/java/com/whu/edu/LyStatistic/statistic/service/DistrictStatisticService.java create mode 100644 src/main/java/com/whu/edu/LyStatistic/statistic/service/UnitInfoService.java create mode 100644 src/main/java/com/whu/edu/LyStatistic/statistic/service/UserStatisticService.java create mode 100644 src/main/resources/mapper/DistrictSchemaMapper.xml create mode 100644 src/main/resources/mapper/SchemaMapper.xml create mode 100644 src/main/resources/mapper/UnitInfoMapper.xml diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/Util/ApiResponse.java b/src/main/java/com/whu/edu/LyStatistic/statistic/Util/ApiResponse.java index bc2fb8d..61695ae 100644 --- a/src/main/java/com/whu/edu/LyStatistic/statistic/Util/ApiResponse.java +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/Util/ApiResponse.java @@ -19,7 +19,7 @@ public class ApiResponse { } public static ApiResponse success(String message, T data) { - return new ApiResponse<>(0, message, data); + return new ApiResponse<>(200, message, data); } public static ApiResponse error(int code, String message) { diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/config/CorsConfig.java b/src/main/java/com/whu/edu/LyStatistic/statistic/config/CorsConfig.java new file mode 100644 index 0000000..15ac840 --- /dev/null +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/config/CorsConfig.java @@ -0,0 +1,28 @@ +package com.whu.edu.LyStatistic.statistic.config; + +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +@Configuration +public class CorsConfig { + + @Bean + public FilterRegistrationBean corsFilter() { + CorsConfiguration config = new CorsConfiguration(); + config.addAllowedOriginPattern("*"); + config.addAllowedHeader("*"); + config.addAllowedMethod("*"); + config.setAllowCredentials(true); // 如果需要携带 Cookie + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + + FilterRegistrationBean bean = new FilterRegistrationBean<>(new CorsFilter(source)); + bean.setOrder(0); // 设置为最优先,优先于 Shiro + return bean; + } +} diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/controller/OrgStatisticController.java b/src/main/java/com/whu/edu/LyStatistic/statistic/controller/OrgStatisticController.java deleted file mode 100644 index d59eb56..0000000 --- a/src/main/java/com/whu/edu/LyStatistic/statistic/controller/OrgStatisticController.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.whu.edu.LyStatistic.statistic.controller; - -import com.whu.edu.LyStatistic.statistic.Util.ApiResponse; -import com.whu.edu.LyStatistic.statistic.dto.TaskStatisticResult; -import com.whu.edu.LyStatistic.statistic.service.OrgStatisticService; -import org.springframework.format.annotation.DateTimeFormat; -import org.springframework.web.bind.annotation.*; - -import java.time.LocalDateTime; -import java.util.*; - - -@RestController -@RequestMapping("/api/org-statistics") -public class OrgStatisticController { - - private final OrgStatisticService orgStatisticService; - - public OrgStatisticController(OrgStatisticService orgStatisticService) { - this.orgStatisticService = orgStatisticService; - } - - @GetMapping - public ApiResponse> getOrgStatistics( - @RequestParam String orgName, - @RequestParam(required = false) - @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime time) { - - List tables = Arrays.asList("roottable1"); - Map result = - orgStatisticService.getOrgTaskStatistics(orgName, time, tables); - - return ApiResponse.success(result); - } -} \ No newline at end of file diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/controller/StatisticController.java b/src/main/java/com/whu/edu/LyStatistic/statistic/controller/StatisticController.java new file mode 100644 index 0000000..c136290 --- /dev/null +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/controller/StatisticController.java @@ -0,0 +1,86 @@ +package com.whu.edu.LyStatistic.statistic.controller; + +import com.whu.edu.LyStatistic.statistic.Util.ApiResponse; +import com.whu.edu.LyStatistic.statistic.dto.TaskStatisticResult; +import com.whu.edu.LyStatistic.statistic.service.*; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.web.bind.annotation.*; + +import java.time.LocalDateTime; +import java.util.*; + + +@RestController +@RequestMapping("/api") +public class StatisticController { + + private final OrgStatisticService orgStatisticService; + private final DistrictStatisticService districtStatisticService; + private final UserStatisticService userStatisticService ; + private final UnitInfoService unitInfoService; + public StatisticController(OrgStatisticService orgStatisticService, DistrictStatisticService districtStatisticService,UserStatisticService userStatisticService,UnitInfoService unitInfoService) { + this.orgStatisticService = orgStatisticService; + this.districtStatisticService = districtStatisticService; + this.userStatisticService = userStatisticService; + this.unitInfoService = unitInfoService; + } + @GetMapping("/org-statistics") + public ApiResponse> getOrgStatistics( + @RequestParam String orgName, + @RequestParam(required = false) + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime, + @RequestParam(required = false) + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) { + + Map result = + orgStatisticService.getOrgTaskStatistics(orgName, startTime, endTime); + + return ApiResponse.success(result); + } + + /** + * 按区/镇统计任务数量和人员参与情况 + * + * @param district 区名称,可选 + * @param village 镇名称,可选 + * @return 统一返回格式 + */ + @GetMapping("/district-statistics") + public ApiResponse> getDistrictStatistics( + @RequestParam(required = false) String district, + @RequestParam(required = false) String village, + @RequestParam(required = false) + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime, + @RequestParam(required = false) + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) { + + Map result = + districtStatisticService.getDistrictTaskStatistics(district, village, startTime, endTime); + + return ApiResponse.success(result); + } + + /** + * 按人名和时间统计任务情况(遍历全部 schema) + * + * @param username 模糊人名,可选 + * @return 每个 schema 的统计结果 + */ + @GetMapping("/user-statistics") + public ApiResponse> getUserStatistics( + @RequestParam(required = false) String username, + @RequestParam(required = false) + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime, + @RequestParam(required = false) + @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) { + Map result = + userStatisticService.getUserTaskStatistics(username,startTime, endTime); + + return ApiResponse.success(result); + } + @GetMapping("/dropdown-options") + public ApiResponse>> getDropdownOptions() { + Map> result = unitInfoService.getDropdownOptions(); + return ApiResponse.success(result); + } +} \ No newline at end of file diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/dto/RootTask.java b/src/main/java/com/whu/edu/LyStatistic/statistic/dto/RootTask.java new file mode 100644 index 0000000..54393b3 --- /dev/null +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/dto/RootTask.java @@ -0,0 +1,18 @@ +package com.whu.edu.LyStatistic.statistic.dto; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +/** + * 根表任务实体类,对应 roottable1。 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class RootTask implements Serializable { + private Long id; + private Long collector; + private Long reviewer; +} \ No newline at end of file diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/dto/TaskStatisticResult.java b/src/main/java/com/whu/edu/LyStatistic/statistic/dto/TaskStatisticResult.java index 73e9413..26eb192 100644 --- a/src/main/java/com/whu/edu/LyStatistic/statistic/dto/TaskStatisticResult.java +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/dto/TaskStatisticResult.java @@ -11,6 +11,9 @@ import java.util.List; @NoArgsConstructor public class TaskStatisticResult { private String schema; - private Integer totalCount; private List userStatistics; + private int totalRootCount; + private int totalT1sub1Count; + private int totalT1sub2Count; + private int totalT1sub3Count; } \ No newline at end of file diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/dto/UserStatistic.java b/src/main/java/com/whu/edu/LyStatistic/statistic/dto/UserStatistic.java index 98574a3..9fe7c12 100644 --- a/src/main/java/com/whu/edu/LyStatistic/statistic/dto/UserStatistic.java +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/dto/UserStatistic.java @@ -9,5 +9,9 @@ import lombok.NoArgsConstructor; @NoArgsConstructor public class UserStatistic { private String username; - private Integer taskCount; + // private Integer taskCount; + private int rootCount; // 小班数量(roottable1) + private int t1sub1Count; // 样地数量 + private int t1sub2Count; // 样木数量 + private int t1sub3Count; // 灌木数量 } \ No newline at end of file diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/dto/UserTaskCount.java b/src/main/java/com/whu/edu/LyStatistic/statistic/dto/UserTaskCount.java deleted file mode 100644 index 5c7665f..0000000 --- a/src/main/java/com/whu/edu/LyStatistic/statistic/dto/UserTaskCount.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.whu.edu.LyStatistic.statistic.dto; - -import lombok.AllArgsConstructor; -import lombok.Data; -import lombok.NoArgsConstructor; - -import java.util.List; - -@Data -public class UserTaskCount { - private Long userId; - private Integer count; -} - diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/DistrictSchemaMapper.java b/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/DistrictSchemaMapper.java new file mode 100644 index 0000000..1491a6d --- /dev/null +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/DistrictSchemaMapper.java @@ -0,0 +1,16 @@ +package com.whu.edu.LyStatistic.statistic.mapper; + +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +@Mapper +public interface DistrictSchemaMapper { + /** + * 根据区/镇获取 schema 列表 + * 如果 village 为 null,则返回该区下所有 schema + */ + List findSchemasByDistrictAndVillage(@Param("district") String district, + @Param("village") String village); +} \ No newline at end of file diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/SchemaMapper.java b/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/SchemaMapper.java new file mode 100644 index 0000000..28d1bf5 --- /dev/null +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/SchemaMapper.java @@ -0,0 +1,13 @@ +package com.whu.edu.LyStatistic.statistic.mapper; + +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface SchemaMapper { + /** + * 查询所有 schema 名称 + */ + List findAllSchemas(); +} diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/TaskStatisticMapper.java b/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/TaskStatisticMapper.java index fbe94a4..ed717f0 100644 --- a/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/TaskStatisticMapper.java +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/TaskStatisticMapper.java @@ -1,25 +1,48 @@ package com.whu.edu.LyStatistic.statistic.mapper; -import org.apache.ibatis.annotations.Mapper; + +import com.whu.edu.LyStatistic.statistic.dto.RootTask; +import org.apache.ibatis.annotations.MapKey; import org.apache.ibatis.annotations.Param; + import java.time.LocalDateTime; import java.util.List; -import com.whu.edu.LyStatistic.statistic.dto.UserTaskCount; -@Mapper +import java.util.Map; + public interface TaskStatisticMapper { /** - * 统计 collector 数量 + * 查询根表任务(支持时间范围 + 人员过滤) */ - List countByCollector(@Param("schema") String schema, - @Param("table") String table, - @Param("timeParam") LocalDateTime timeParam, - @Param("userIds") List userIds); + List findRootTasksByTimeRange( + @Param("schema") String schema, + @Param("startTime") LocalDateTime startTime, + @Param("endTime") LocalDateTime endTime, + @Param("userIds") List userIds + ); /** - * 统计 reviewer 数量 + * 统计子表数量,返回每个 parentID 对应的数量 */ - List countByReviewer(@Param("schema") String schema, - @Param("table") String table, - @Param("timeParam") LocalDateTime timeParam, - @Param("userIds") List userIds); + List> countGroupByParent(@Param("schema") String schema, + @Param("table") String table, + @Param("column") String column, + @Param("parentIds") List parentIds); + + /** + * 查询子表 ID 列表,并按 parentID 分组 + */ + @MapKey("parentid") + List> findSubIdsGroupByParent(@Param("schema") String schema, + @Param("table") String table, + @Param("column") String column, + @Param("parentIds") List parentIds); + + + /** + * 查询 t1sub2 子表数量,单个 parentID + */ + Integer countByParentId(@Param("schema") String schema, + @Param("table") String table, + @Param("column") String column, + @Param("parentId") Long parentId); } diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/UnitInfoMapper.java b/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/UnitInfoMapper.java new file mode 100644 index 0000000..2fc1377 --- /dev/null +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/mapper/UnitInfoMapper.java @@ -0,0 +1,14 @@ +package com.whu.edu.LyStatistic.statistic.mapper; + +import org.apache.ibatis.annotations.Mapper; +import java.util.List; + +@Mapper +public interface UnitInfoMapper { + + List findDistinctDistricts(); + + List findDistinctVillages(); + + List findDistinctUnits(); +} diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/service/DistrictStatisticService.java b/src/main/java/com/whu/edu/LyStatistic/statistic/service/DistrictStatisticService.java new file mode 100644 index 0000000..d363895 --- /dev/null +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/service/DistrictStatisticService.java @@ -0,0 +1,45 @@ +package com.whu.edu.LyStatistic.statistic.service; +import com.whu.edu.LyStatistic.statistic.dto.TaskStatisticResult; +import com.whu.edu.LyStatistic.statistic.mapper.DistrictSchemaMapper; +import org.springframework.stereotype.Service; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class DistrictStatisticService { + + private final TaskStatisticService taskStatisticService; + private final DistrictSchemaMapper districtSchemaMapper; + + public DistrictStatisticService(TaskStatisticService taskStatisticService, + DistrictSchemaMapper districtSchemaMapper) { + this.taskStatisticService = taskStatisticService; + this.districtSchemaMapper = districtSchemaMapper; + } + + /** + * 获取区/镇任务统计 + * + * @param district 区名称,可为空 + * @param village 镇名称,可为空 + */ + public Map getDistrictTaskStatistics(String district, + String village, + LocalDateTime startTime, + LocalDateTime endTime) { + // 1. 找出该区/镇对应的全部 schema + List schemas = districtSchemaMapper.findSchemasByDistrictAndVillage(district, village); + + Map resultMap = new HashMap<>(); + + // 2. 遍历 schema,调用通用统计方法 + for (String schema : schemas) { + TaskStatisticResult stat = taskStatisticService.getStatistics(schema, startTime, endTime, null); + resultMap.put(schema, stat); + } + + return resultMap; + } +} \ No newline at end of file diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/service/OrgStatisticService.java b/src/main/java/com/whu/edu/LyStatistic/statistic/service/OrgStatisticService.java index 755b647..c34e4c7 100644 --- a/src/main/java/com/whu/edu/LyStatistic/statistic/service/OrgStatisticService.java +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/service/OrgStatisticService.java @@ -21,24 +21,19 @@ public class OrgStatisticService { /** * 按单位和时间统计任务信息 * @param orgName 单位名称 - * @param timeParam 截止时间 - * @param tables 根表及子表 * @return Map */ public Map getOrgTaskStatistics(String orgName, - LocalDateTime timeParam, - List tables) { - // 1. 获取该单位对应的所有 schema + LocalDateTime startTime, + LocalDateTime endTime) { + // 1. 找到该单位对应的 schema 列表 List schemas = orgSchemaMapper.findSchemasByOrgName(orgName); - if (schemas == null || schemas.isEmpty()) { - return Collections.emptyMap(); - } + Map resultMap = new HashMap<>(); - // 2. 循环每个 schema 调用通用统计 - Map resultMap = new LinkedHashMap<>(); + // 2. 对每个 schema 执行统计方法 for (String schema : schemas) { - TaskStatisticResult result = taskStatisticService.getStatistics(schema, timeParam, null, tables); - resultMap.put(schema, result); + TaskStatisticResult stat = taskStatisticService.getStatistics(schema, startTime, endTime, null); + resultMap.put(schema, stat); } return resultMap; diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/service/TaskStatisticService.java b/src/main/java/com/whu/edu/LyStatistic/statistic/service/TaskStatisticService.java index 497938e..0b1668c 100644 --- a/src/main/java/com/whu/edu/LyStatistic/statistic/service/TaskStatisticService.java +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/service/TaskStatisticService.java @@ -1,31 +1,39 @@ package com.whu.edu.LyStatistic.statistic.service; + +import com.whu.edu.LyStatistic.statistic.dto.*; +import com.whu.edu.LyStatistic.statistic.mapper.TaskStatisticMapper; +import com.whu.edu.LyStatistic.statistic.mapper.UserStaffMapper; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; + import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; -import com.whu.edu.LyStatistic.statistic.dto.UserTaskCount; -import com.whu.edu.LyStatistic.statistic.dto.TaskStatisticResult; -import com.whu.edu.LyStatistic.statistic.dto.UserStatistic; -import com.whu.edu.LyStatistic.statistic.mapper.TaskStatisticMapper; -import com.whu.edu.LyStatistic.statistic.mapper.UserStaffMapper; -import com.whu.edu.LyStatistic.statistic.dto.UserStaff; +import java.util.stream.Stream; + @Service public class TaskStatisticService { - private final TaskStatisticMapper taskStatisticMapper; - private final UserStaffMapper userStaffMapper; + @Autowired + private UserStaffMapper userStaffMapper; - public TaskStatisticService(TaskStatisticMapper taskStatisticMapper, UserStaffMapper userStaffMapper) { - this.taskStatisticMapper = taskStatisticMapper; - this.userStaffMapper = userStaffMapper; - } + @Autowired + private TaskStatisticMapper taskStatisticMapper; + /** + * 按 schema 和时间区间统计任务数据 + * + * @param schema 数据库 schema 名称 + * @param startTime 起始时间(可选) + * @param endTime 截止时间(可选) + * @param nameLike 人名模糊查询(可选) + */ public TaskStatisticResult getStatistics(String schema, - LocalDateTime timeParam, - String nameLike, - List tables) { + LocalDateTime startTime, + LocalDateTime endTime, + String nameLike) { - // 1. 查询模糊匹配的人员ID(若有) + // 1️⃣ 模糊匹配人员ID List userIds = null; if (nameLike != null && !nameLike.isEmpty()) { userIds = userStaffMapper.findByNameLike(nameLike) @@ -34,38 +42,125 @@ public class TaskStatisticService { .collect(Collectors.toList()); } - // 2. 按schema统计任务量(collector+reviewer) - Map countMap = new HashMap<>(); - - for (String table : tables) { - List collectorCounts = taskStatisticMapper.countByCollector(schema, table, timeParam, userIds); - List reviewerCounts = taskStatisticMapper.countByReviewer(schema, table, timeParam, userIds); - - for (UserTaskCount c : collectorCounts) { - countMap.merge(c.getUserId(), c.getCount(), Integer::sum); - } - for (UserTaskCount r : reviewerCounts) { - countMap.merge(r.getUserId(), r.getCount(), Integer::sum); - } + // 2️⃣ 查询根表记录(支持时间区间) + List rootTasks = taskStatisticMapper.findRootTasksByTimeRange(schema, startTime, endTime, userIds); + if (rootTasks.isEmpty()) { + return new TaskStatisticResult(schema, Collections.emptyList(), 0, 0, 0, 0); } - if (countMap.isEmpty()) { - return new TaskStatisticResult(schema, 0, Collections.emptyList()); - } - - // 3. 查询所有 userId 对应 username - List allUserIds = new ArrayList<>(countMap.keySet()); - Map idToName = userStaffMapper.findByIds(allUserIds) - .stream() - .collect(Collectors.toMap(UserStaff::getId, UserStaff::getUsername)); - - // 4. 构造结果:username -> count - List userStats = countMap.entrySet().stream() - .map(e -> new UserStatistic(idToName.getOrDefault(e.getKey(), "未知用户"), e.getValue())) + // 3️⃣ 获取所有根表ID + List rootIds = rootTasks.stream() + .map(RootTask::getId) + .filter(Objects::nonNull) .collect(Collectors.toList()); - int total = countMap.values().stream().mapToInt(Integer::intValue).sum(); + // 4️⃣ 查询子表计数 + Map t1sub1Map = safeCountByParent(schema, "t1sub1", rootIds); + Map t1sub3Map = safeCountByParent(schema, "t1sub3", rootIds); - return new TaskStatisticResult(schema, total, userStats); + // 4.1️⃣ t1sub2 层级统计 + List> sub1List = safeFindSubIds(schema, "t1sub1", rootIds); + Map> rootToSub1Ids = rootIds.stream() + .collect(Collectors.toMap( + rid -> rid, + rid -> sub1List.stream() + .filter(m -> m.get("parentid") != null && + rid.equals(((Number) m.get("parentid")).longValue())) + .map(m -> ((Number) m.get("ID")).longValue()) + .collect(Collectors.toList()) + )); + + Map t1sub2Map = new HashMap<>(); + for (Map.Entry> entry : rootToSub1Ids.entrySet()) { + int total = 0; + for (Long sub1Id : entry.getValue()) { + Integer count = safeCountByParentId(schema, "t1sub2", sub1Id); + total += (count != null) ? count : 0; + } + t1sub2Map.put(entry.getKey(), total); + } + + // 5️⃣ 汇总用户统计(排除 null 和 -1) + Map userStats = new HashMap<>(); + for (RootTask task : rootTasks) { + Long rootId = task.getId(); + if (rootId == null) continue; + + Stream.of(task.getCollector(), task.getReviewer()) + .filter(uid -> uid != null && uid != -1) + .forEach(uid -> { + UserStatistic stat = userStats.computeIfAbsent(uid, k -> new UserStatistic()); + stat.setRootCount(stat.getRootCount() + 1); + stat.setT1sub1Count(stat.getT1sub1Count() + t1sub1Map.getOrDefault(rootId, 0)); + stat.setT1sub2Count(stat.getT1sub2Count() + t1sub2Map.getOrDefault(rootId, 0)); + stat.setT1sub3Count(stat.getT1sub3Count() + t1sub3Map.getOrDefault(rootId, 0)); + }); + } + + // 6️⃣ 填充用户名 + Map idToName = new HashMap<>(); + if (!userStats.isEmpty()) { + userIds = new ArrayList<>(userStats.keySet()); + List userList = userStaffMapper.findByIds(userIds); + if (userList != null && !userList.isEmpty()) { + idToName = userList.stream() + .filter(u -> u.getId() != null) + .collect(Collectors.toMap( + UserStaff::getId, + UserStaff::getUsername, + (a, b) -> a // 避免重复键 + )); + } + } + + final Map nameMap = idToName; // ✅ 实际 final,可安全用于 lambda + + List results = userStats.entrySet().stream() + .map(e -> { + UserStatistic stat = e.getValue(); + stat.setUsername(nameMap.getOrDefault(e.getKey(), "未知用户")); + return stat; + }) + .collect(Collectors.toList()); + + // 7️⃣ 总量统计 + int totalRootCount = rootTasks.size(); + int totalT1sub1Count = t1sub1Map.values().stream().mapToInt(Integer::intValue).sum(); + int totalT1sub2Count = t1sub2Map.values().stream().mapToInt(Integer::intValue).sum(); + int totalT1sub3Count = t1sub3Map.values().stream().mapToInt(Integer::intValue).sum(); + + return new TaskStatisticResult(schema, results, + totalRootCount, totalT1sub1Count, totalT1sub2Count, totalT1sub3Count); + } + + // 🧩 安全封装:防止 schema 无表时报错 + private Map safeCountByParent(String schema, String table, List rootIds) { + try { + return taskStatisticMapper.countGroupByParent(schema, table, "parentID", rootIds) + .stream() + .filter(m -> m.get("parentid") != null) + .collect(Collectors.toMap( + m -> ((Number) m.get("parentid")).longValue(), + m -> ((Number) m.getOrDefault("count", 0)).intValue() + )); + } catch (Exception e) { + return new HashMap<>(); + } + } + + private List> safeFindSubIds(String schema, String table, List rootIds) { + try { + return taskStatisticMapper.findSubIdsGroupByParent(schema, table, "parentID", rootIds); + } catch (Exception e) { + return Collections.emptyList(); + } + } + + private Integer safeCountByParentId(String schema, String table, Long parentId) { + try { + return taskStatisticMapper.countByParentId(schema, table, "parentID", parentId); + } catch (Exception e) { + return 0; + } } } diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/service/UnitInfoService.java b/src/main/java/com/whu/edu/LyStatistic/statistic/service/UnitInfoService.java new file mode 100644 index 0000000..968b873 --- /dev/null +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/service/UnitInfoService.java @@ -0,0 +1,24 @@ +package com.whu.edu.LyStatistic.statistic.service; + +import com.whu.edu.LyStatistic.statistic.mapper.UnitInfoMapper; +import org.springframework.stereotype.Service; + +import java.util.*; + +@Service +public class UnitInfoService { + + private final UnitInfoMapper unitInfoMapper; + + public UnitInfoService(UnitInfoMapper unitInfoMapper) { + this.unitInfoMapper = unitInfoMapper; + } + + public Map> getDropdownOptions() { + Map> map = new HashMap<>(); + map.put("districts", unitInfoMapper.findDistinctDistricts()); + map.put("villages", unitInfoMapper.findDistinctVillages()); + map.put("units", unitInfoMapper.findDistinctUnits()); + return map; + } +} diff --git a/src/main/java/com/whu/edu/LyStatistic/statistic/service/UserStatisticService.java b/src/main/java/com/whu/edu/LyStatistic/statistic/service/UserStatisticService.java new file mode 100644 index 0000000..b2b8262 --- /dev/null +++ b/src/main/java/com/whu/edu/LyStatistic/statistic/service/UserStatisticService.java @@ -0,0 +1,45 @@ +package com.whu.edu.LyStatistic.statistic.service; + +import com.whu.edu.LyStatistic.statistic.dto.TaskStatisticResult; +import com.whu.edu.LyStatistic.statistic.mapper.SchemaMapper; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class UserStatisticService { + + private final TaskStatisticService taskStatisticService; + private final SchemaMapper schemaMapper; + + public UserStatisticService(TaskStatisticService taskStatisticService, + SchemaMapper schemaMapper) { + this.taskStatisticService = taskStatisticService; + this.schemaMapper = schemaMapper; + } + + /** + * 按人名和时间统计任务数量 + * + * @param username 模糊人名,可选 + * @return 各 schema 的统计结果 + */ + public Map getUserTaskStatistics(String username, LocalDateTime startTime, + LocalDateTime endTime) { + // 查询所有 schema + List schemas = schemaMapper.findAllSchemas(); + + Map resultMap = new HashMap<>(); + for (String schema : schemas) { + // 调用通用统计方法 + TaskStatisticResult statistic = taskStatisticService.getStatistics(schema, startTime, endTime, username); + resultMap.put(schema, statistic); + } + + return resultMap; + } +} + diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 0bab0c1..d92b157 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -4,7 +4,7 @@ server.port=9001 server.address=0.0.0.0 spring.datasource.host=120.48.89.193 spring.datasource.port=5432 -spring.datasource.database=tj_lydc +spring.datasource.database=lydc_statistic spring.datasource.driver-class-name=org.postgresql.Driver spring.datasource.url=jdbc:postgresql://${spring.datasource.host}:${spring.datasource.port}/${spring.datasource.database}?useSSL=true&allowMultiQueries=true spring.datasource.username=postgres diff --git a/src/main/resources/mapper/DistrictSchemaMapper.xml b/src/main/resources/mapper/DistrictSchemaMapper.xml new file mode 100644 index 0000000..548a7f5 --- /dev/null +++ b/src/main/resources/mapper/DistrictSchemaMapper.xml @@ -0,0 +1,25 @@ + + + + + + + + + diff --git a/src/main/resources/mapper/SchemaMapper.xml b/src/main/resources/mapper/SchemaMapper.xml new file mode 100644 index 0000000..97edacf --- /dev/null +++ b/src/main/resources/mapper/SchemaMapper.xml @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/src/main/resources/mapper/TaskStatisticMapper.xml b/src/main/resources/mapper/TaskStatisticMapper.xml index 1714429..3a4a5ff 100644 --- a/src/main/resources/mapper/TaskStatisticMapper.xml +++ b/src/main/resources/mapper/TaskStatisticMapper.xml @@ -4,36 +4,79 @@ - + SELECT "ID" AS id, + "collector" AS collector, + "reviewer" AS reviewer + FROM "${schema}".roottable1 + WHERE 1=1 - AND update_time <= #{timeParam} + AND create_time >= #{timeParam} - AND collector IN + AND ("collector" IN #{id} + OR "reviewer" IN + + #{id} + ) + + + - + SELECT "${column}" AS parentid, + COUNT(*) AS count + FROM "${schema}".${table} + WHERE "${column}" IN + + #{pid} + + GROUP BY "${column}" + + + + + + + diff --git a/src/main/resources/mapper/UnitInfoMapper.xml b/src/main/resources/mapper/UnitInfoMapper.xml new file mode 100644 index 0000000..24f606d --- /dev/null +++ b/src/main/resources/mapper/UnitInfoMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + diff --git a/src/main/resources/mapper/UserStaffMapper.xml b/src/main/resources/mapper/UserStaffMapper.xml index c8dfbb0..52abc8c 100644 --- a/src/main/resources/mapper/UserStaffMapper.xml +++ b/src/main/resources/mapper/UserStaffMapper.xml @@ -6,7 +6,7 @@ @@ -20,6 +20,4 @@ #{id} - -