新建立了MapLyStatistic包,在里面重新实现了一些逻辑。核心逻辑是通过一个baseservice查询每个任务下的各表,目前只实现了对小班的区级查询。街道查询同理可以先筛选出要查询的街道再调用baseservice方法进行查询

This commit is contained in:
dbc
2025-11-22 20:21:41 +08:00
parent 3a4aa12619
commit 49485a7ac1
15 changed files with 425 additions and 33 deletions

View File

@@ -5,7 +5,7 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.whu.edu.LyStatistic.*.mapper")
@MapperScan("com.whu.edu.LyStatistic")
public class BootApplication {
public static void main(String[] args) {

View File

@@ -0,0 +1,74 @@
package com.whu.edu.LyStatistic.MapLyStatistic.Controller;
import com.whu.edu.LyStatistic.MapLyStatistic.Dto.DistrictStatsDTO;
import com.whu.edu.LyStatistic.MapLyStatistic.Dto.PlotStatsDTO;
import com.whu.edu.LyStatistic.MapLyStatistic.Service.StatisticsService;
import com.whu.edu.LyStatistic.Util.ApiResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.LinkedHashMap;
import java.util.Map;
@RestController
@RequestMapping("/api/stats")
public class StatisticsController {
@Autowired
private StatisticsService statisticsService;
/**
* 区级统计
*/
@GetMapping("/district")
public ApiResponse<DistrictStatsDTO> getDistrictStats() {
try {
// 1⃣ 获取 Map<区名, PlotStatsDTO>
Map<String, PlotStatsDTO> statsMap = statisticsService.getAllDistrictStats();
// 2⃣ 构建 DistrictStatsDTO
Map<String, String> completionStatus = new LinkedHashMap<>();
Map<String, Double> plotArea = new LinkedHashMap<>();
Map<String, Integer> plotCount = new LinkedHashMap<>();
for (Map.Entry<String, PlotStatsDTO> entry : statsMap.entrySet()) {
String district = entry.getKey();
PlotStatsDTO stats = entry.getValue();
// 计算完成状态(示例逻辑,可根据需求调整)
String status;
if (safeInt(stats.getApprovedCount()) > 0) {
status = "已完成";
} else if (safeInt(stats.getCollectedCount()) > 0) {
status = "未完成";
} else {
status = "未开始";
}
completionStatus.put(district, status);
plotArea.put(district, safeDouble(stats.getTotalArea()));
plotCount.put(district, safeInt(stats.getPlotCount()));
}
DistrictStatsDTO dto = new DistrictStatsDTO(completionStatus, plotArea, plotCount);
return ApiResponse.success(dto);
} catch (Exception e) {
return ApiResponse.error("区级统计查询失败:" + e.getMessage());
}
}
// 防止 null
private int safeInt(Integer value) {
return (value != null) ? value : 0;
}
private double safeDouble(Double value) {
return (value != null) ? value : 0.0;
}
}

View File

@@ -0,0 +1,16 @@
package com.whu.edu.LyStatistic.MapLyStatistic.Dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Map;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DistrictStatsDTO {
private Map<String, String> completionStatus; // 区 -> 完成状态
private Map<String, Double> plotArea; // 区 -> 图斑面积
private Map<String, Integer> plotCount; // 区 -> 图斑数量
}

View File

@@ -0,0 +1,20 @@
package com.whu.edu.LyStatistic.MapLyStatistic.Dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PlotStatsDTO {
private Integer plotCount; // 图斑总数量
private Double totalArea; // 图斑总面积sum XBMJ
private Integer unPassedCount; // -1 审核未通过
private Integer assignedCount; // 0 已分配,未审核
private Integer collectedCount; // 1 已采集,未审核
private Integer approvedCount; // 2 已审核
}

View File

@@ -0,0 +1,12 @@
package com.whu.edu.LyStatistic.MapLyStatistic.Dto;
import lombok.Data;
@Data
public class UnitInfo {
private String taskName;
private String schemaCode;
private String unitName;
private String district;
private String village;
}

View File

@@ -0,0 +1,15 @@
package com.whu.edu.LyStatistic.MapLyStatistic.Mapper;
import java.util.List;
import com.whu.edu.LyStatistic.MapLyStatistic.Dto.UnitInfo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface InfoMapper {
List<UnitInfo> findByDistrict(@Param("district") String district);
List<UnitInfo> findByVillage(@Param("village") String village);
List<UnitInfo> findAll();
}

View File

@@ -0,0 +1,41 @@
package com.whu.edu.LyStatistic.MapLyStatistic.Mapper;
import com.whu.edu.LyStatistic.MapLyStatistic.Dto.PlotStatsDTO;
//import com.whu.edu.LyStatistic.MapLyStatistic.Dto.PlotDetailDTO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* TaskCommonMapper.xml
* 通用 Mapper用于不同 schema 下的 roottable1 表
*/
@Mapper
public interface TaskCommonMapper {
/**
* 统计图斑信息(数量、面积、各状态)
* @param schema schema 名(任务库)
* @return 统计结果 DTO
*/
PlotStatsDTO selectPlotStats(@Param("schema") String schema);
// /**
// * 查询单个图斑详情
// * @param schema schema 名
// * @param plotId 图斑 ID
// * @return 图斑详情 DTO
// */
// PlotDetailDTO getPlotDetail(@Param("schema") String schema,
// @Param("plotId") Long plotId);
// /**
// * 查询单个图斑对应的照片路径
// * @param schema schema 名
// * @param plotId 图斑 ID
// * @return 照片路径列表
// */
// List<String> getPlotPhotos(@Param("schema") String schema,
// @Param("plotId") Long plotId);
}

View File

@@ -0,0 +1,63 @@
package com.whu.edu.LyStatistic.MapLyStatistic.Service.BaseService;
import com.whu.edu.LyStatistic.MapLyStatistic.Dto.PlotStatsDTO;
import com.whu.edu.LyStatistic.MapLyStatistic.Mapper.TaskCommonMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.*;
@Service
public class BaseTaskQueryService {
@Autowired
private TaskCommonMapper taskCommonMapper;
/**
* 安全查询单个任务的图斑统计
* schema 不存在或 roottable1 表不存在时,返回全 0
*/
public PlotStatsDTO queryPlotStats(String schema) {
try {
PlotStatsDTO stats = taskCommonMapper.selectPlotStats(schema);
if (stats == null) {
// 防止 mapper 返回 null
return new PlotStatsDTO(0, 0.0, 0, 0, 0, 0);
}
return stats;
} catch (Exception e) {
// 表不存在或 schema 不存在,直接跳过
// 不管是什么异常,都返回默认统计,保证批量统计不被中断
return new PlotStatsDTO(0, 0.0, 0, 0, 0, 0);
}
}
/**
* 批量查询多个任务的图斑统计
*/
public Map<String, PlotStatsDTO> queryPlotStatsBatch(List<String> schemas) {
Map<String, PlotStatsDTO> result = new HashMap<>();
for (String schema : schemas) {
PlotStatsDTO stats = queryPlotStats(schema);
result.put(schema, stats);
}
return result;
}
/**
* 查询某个区的图斑统计
*/
public Map<String, PlotStatsDTO> queryByDistrict(List<String> schemas, String district) {
// 这里可结合 UnitInfo 表过滤 schemas
// 假设前端传入的 schemas 已经是该区的任务列表
return queryPlotStatsBatch(schemas);
}
/**
* 查询某个街道的图斑统计
*/
public Map<String, PlotStatsDTO> queryByVillage(List<String> schemas, String village) {
// 这里可结合 UnitInfo 表过滤 schemas
// 假设前端传入的 schemas 已经是该街道的任务列表
return queryPlotStatsBatch(schemas);
}
}

View File

@@ -0,0 +1,111 @@
package com.whu.edu.LyStatistic.MapLyStatistic.Service;
import com.whu.edu.LyStatistic.MapLyStatistic.Dto.PlotStatsDTO;
import com.whu.edu.LyStatistic.MapLyStatistic.Dto.UnitInfo;
import com.whu.edu.LyStatistic.MapLyStatistic.Mapper.InfoMapper;
import com.whu.edu.LyStatistic.MapLyStatistic.Service.BaseService.BaseTaskQueryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class StatisticsService {
@Autowired
private InfoMapper unitInfoMapper; // 查询 unit_info 表
@Autowired
private BaseTaskQueryService baseQueryService; // 通用任务查询 Service
/**
* 查询单个区的统计信息
*/
public PlotStatsDTO getDistrictStats(String district) {
// 1. 获取该区所有任务schema
List<UnitInfo> tasks = unitInfoMapper.findByDistrict(district);
// 2. 初始化统计对象
PlotStatsDTO total = new PlotStatsDTO(0, 0.0, 0, 0, 0, 0);
// 3. 遍历每个任务 schema累加统计
for (UnitInfo task : tasks) {
String schema = task.getSchemaCode();
PlotStatsDTO stats = baseQueryService.queryPlotStats(schema);
merge(total, stats);
}
return total;
}
/**
* 查询所有区的统计信息
* 返回 Map<区名, PlotStatsDTO>
*/
public Map<String, PlotStatsDTO> getAllDistrictStats() {
// 1⃣ 查询 unit_info 全部数据
List<UnitInfo> allTasks = unitInfoMapper.findAll();
// 2⃣ 按 district 分组
Map<String, List<UnitInfo>> grouped =
allTasks.stream().collect(Collectors.groupingBy(UnitInfo::getDistrict));
Map<String, PlotStatsDTO> result = new LinkedHashMap<>();
// 3⃣ 遍历每个区,累加统计
for (Map.Entry<String, List<UnitInfo>> entry : grouped.entrySet()) {
String district = entry.getKey();
List<UnitInfo> tasks = entry.getValue();
// 初始化累加对象
PlotStatsDTO total = new PlotStatsDTO(0, 0.0, 0, 0, 0, 0);
for (UnitInfo task : tasks) {
String schema = task.getSchemaCode();
PlotStatsDTO stats = baseQueryService.queryPlotStats(schema); // ✅ 使用安全方法
if (stats != null) {
// 累加
total.setPlotCount(total.getPlotCount() + safeInt(stats.getPlotCount()));
total.setTotalArea(total.getTotalArea() + safeDouble(stats.getTotalArea()));
total.setUnPassedCount(total.getUnPassedCount() + safeInt(stats.getUnPassedCount()));
total.setAssignedCount(total.getAssignedCount() + safeInt(stats.getAssignedCount()));
total.setCollectedCount(total.getCollectedCount() + safeInt(stats.getCollectedCount()));
total.setApprovedCount(total.getApprovedCount() + safeInt(stats.getApprovedCount()));
}
}
result.put(district, total);
}
return result;
}
// ✅ 防止 null 值累加
private int safeInt(Integer value) {
return (value != null) ? value : 0;
}
private double safeDouble(Double value) {
return (value != null) ? value : 0.0;
}
/**
* 合并两个 PlotStatsDTO
*/
private void merge(PlotStatsDTO total, PlotStatsDTO add) {
if (add == null) return;
total.setPlotCount(total.getPlotCount() + add.getPlotCount());
total.setTotalArea(total.getTotalArea() + add.getTotalArea());
total.setUnPassedCount(total.getUnPassedCount() + add.getUnPassedCount());
total.setAssignedCount(total.getAssignedCount() + add.getAssignedCount());
total.setCollectedCount(total.getCollectedCount() + add.getCollectedCount());
total.setApprovedCount(total.getApprovedCount() + add.getApprovedCount());
}
}

View File

@@ -1,4 +1,4 @@
package com.whu.edu.LyStatistic.statistic.Util;
package com.whu.edu.LyStatistic.Util;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

View File

@@ -1,28 +0,0 @@
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> corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern("*");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
config.setAllowCredentials(true); // 如果需要携带 Cookie
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
bean.setOrder(0); // 设置为最优先,优先于 Shiro
return bean;
}
}

View File

@@ -1,6 +1,6 @@
package com.whu.edu.LyStatistic.statistic.controller;
import com.whu.edu.LyStatistic.statistic.Util.ApiResponse;
import com.whu.edu.LyStatistic.Util.ApiResponse;
import com.whu.edu.LyStatistic.statistic.dto.TaskStatisticResult;
import com.whu.edu.LyStatistic.statistic.service.*;
import org.springframework.format.annotation.DateTimeFormat;

View File

@@ -2,9 +2,9 @@ spring.application.name=LydcStatistic
spring.profiles.active=dev
server.port=9001
server.address=0.0.0.0
spring.datasource.host=120.48.89.193
spring.datasource.host=127.0.0.1
spring.datasource.port=5432
spring.datasource.database=tj_lydc
spring.datasource.database=tj_project
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

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.whu.edu.LyStatistic.MapLyStatistic.Mapper.InfoMapper">
<select id="findByDistrict" resultType="com.whu.edu.LyStatistic.MapLyStatistic.Dto.UnitInfo">
SELECT task_name, schema_code, unit_name, district, village
FROM public.unit_info
WHERE district = #{district}
</select>
<select id="findByVillage" resultType="com.whu.edu.LyStatistic.MapLyStatistic.Dto.UnitInfo">
SELECT task_name, schema_code, unit_name, district, village
FROM public.unit_info
WHERE village = #{village}
</select>
<select id="findAll" resultType="com.whu.edu.LyStatistic.MapLyStatistic.Dto.UnitInfo">
SELECT task_name, schema_code, unit_name, district, village
FROM public.unit_info
</select>
</mapper>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.whu.edu.LyStatistic.MapLyStatistic.Mapper.TaskCommonMapper">
<!--
统计图斑信息:
- plotCount: 图斑数量
- totalArea: 图斑面积汇总 (XBMJ)
- 各状态数量 (-1,0,1,2)
-->
<select id="selectPlotStats" resultType="com.whu.edu.LyStatistic.MapLyStatistic.Dto.PlotStatsDTO">
SELECT
COUNT(*) AS plotCount,
COALESCE(SUM("XBMJ"), 0) AS totalArea,
COALESCE(SUM(CASE WHEN "status" = -1 THEN 1 ELSE 0 END), 0) AS unPassedCount,
COALESCE(SUM(CASE WHEN "status" = 0 THEN 1 ELSE 0 END), 0) AS assignedCount,
COALESCE(SUM(CASE WHEN "status" = 1 THEN 1 ELSE 0 END), 0) AS collectedCount,
COALESCE(SUM(CASE WHEN "status" = 2 THEN 1 ELSE 0 END), 0) AS approvedCount
FROM "${schema}".roottable1
</select>
<!-- 查询单个图斑详情 -->
<!-- <select id="getPlotDetail" resultType="com.whu.edu.LyStatistic.MapLyStatistic.Dto.PlotDetailDTO">-->
<!-- SELECT-->
<!-- plot_id,-->
<!-- XBMJ AS area,-->
<!-- status-->
<!-- FROM ${schema}.roottable1-->
<!-- WHERE plot_id = #{plotId}-->
<!-- </select>-->
<!-- 查询单个图斑的照片路径 -->
<select id="getPlotPhotos" resultType="string">
SELECT photo_path
FROM ${schema}.photo_table
WHERE plot_id = #{plotId}
</select>
</mapper>