PC端

APP端
Controller层
package com.cnpc.dj.party.controller;
import com.alibaba.fastjson.JSONObject;
import com.cnpc.dj.common.JsonResult;
import com.cnpc.dj.common.context.BaseContextHandler;
import com.cnpc.dj.common.utils.DateUtils;
import com.cnpc.dj.party.common.ReturnExamEnum;
import com.cnpc.dj.party.service.GridDataStatisticService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/dataStatistic")
public class GridDataStatisticController {
@Autowired
private GridDataStatisticService gridDataStatisticService ;
@PostMapping("/doStatisticForGrid")
public JsonResult<?> doStatisticForGrid(@RequestBody JSONObject requestBody) {
// 检查入参合法性.
BigDecimal orgId = requestBody.getBigDecimal("orgId");
if (Objects.isNull(orgId)) {
return JsonResult.error(ReturnExamEnum.GRID_ILLEGAL_ARGUMENT, "必要参数<orgId>未填写");
}
BigDecimal tenantId = BaseContextHandler.getDecimalTenantId();
long beginTime = System.currentTimeMillis();
log.info("\n[ {} ][ 网格员 - 数据统计任务 ]: 开始所有任务(当前租户ID: {} ).", DateUtils.format(new Date(beginTime), "yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒"), tenantId);
// 创建统计结果容器.
JSONObject result = new JSONObject();
// 创建异步统计任务: 调用各统计方法.
CompletableFuture<?> task1 = gridDataStatisticService.gridNumberAsyncStatistic(tenantId, orgId, result);
CompletableFuture<?> task2 = gridDataStatisticService.gridPersonNumberAsyncStatistic(tenantId, orgId, result);
// 等待, 直到所有任务执行完毕.
CompletableFuture.allOf(task1,task2).join();
long endTime = System.currentTimeMillis();
log.info("\n[ {} ][ 网格员 - 数据统计任务 ]: 所有任务完成, 总计耗时 {} 毫秒.", DateUtils.format(new Date(endTime), "yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒"), endTime - beginTime);
// 返回统计结果.
return JsonResult.success(result);
}
}
Service层
package com.cnpc.dj.party.service;
import com.alibaba.fastjson.JSONObject;
import com.cnpc.dj.common.utils.DateUtils;
import com.cnpc.dj.party.common.EChartsResult;
import com.cnpc.dj.party.common.KeyValuePair;
import com.cnpc.dj.party.repository.GridDataStatisticMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
@Service
@Slf4j
public class GridDataStatisticService {
@Autowired
private GridDataStatisticMapper gridDataStatisticMapper;
private static String convert(long timeMillis) {
return DateUtils.format(new Date(timeMillis), "yyyy年MM月dd日 HH时mm分ss秒 SSS毫秒");
}
/**
* 获取网格信息
* @param orgId 入参: 组织ID.
* @return 统计结果.
*/
@Async
public CompletableFuture<?> gridNumberAsyncStatistic(BigDecimal tenantId, BigDecimal orgId, JSONObject parent) {
long t0 = System.currentTimeMillis();
log.info("\n[ {} ][ 网格情况 ][ 网格数量统计 ]: 任务开始.", convert(t0));
// 查询数据库, 获取原始数据
List<KeyValuePair<BigDecimal>> list = gridDataStatisticMapper.statisticGrid(tenantId, orgId);
long t1 = System.currentTimeMillis();
log.info("\n[ {} ][ 网格情况 ][ 网格数量统计 ]: 原始数据查询成功: 本步耗时 {} 毫秒, 总计耗时 {} 毫秒.", convert(t1),t1 - t0,t1 - t0);
// 初始化查询结果容器.
// 初始化查询结果容器.管理类,科研类,生产经营类,项目建设类,生产作业类,网格总数
String[] mapEntry = {"Manage", "Scientific", "ProductionOperation", "ProjectBuild","FlowHomework", "GridTotal"};
EChartsResult result = new EChartsResult();
result.init(null, mapEntry, null);
BigDecimal gridTotal = BigDecimal.ZERO;
// 处理原始数据, 填充查询结果容器.
for (KeyValuePair<BigDecimal> item : list) {
if (Objects.nonNull(item.getKey())) {
switch (item.getKey()) {
case "1":
result.addToMap(mapEntry[0], item.getValue());
gridTotal = gridTotal.add(item.getValue());
break;
case "2":
result.addToMap(mapEntry[1], item.getValue());
gridTotal = gridTotal.add(item.getValue());
break;
case "3":
result.addToMap(mapEntry[2], item.getValue());
gridTotal = gridTotal.add(item.getValue());
break;
case "4":
result.addToMap(mapEntry[3], item.getValue());
gridTotal = gridTotal.add(item.getValue());
break;
default:
result.addToMap(mapEntry[4], item.getValue());
gridTotal = gridTotal.add(item.getValue());
}
}
}
result.addToMap(mapEntry[5], gridTotal);
// 返回查询结果.
parent.put("GridStatistic", result.getMap());
long t2 = System.currentTimeMillis();
log.info("\n[ {} ][ 网格情况 ][ 网格数量统计 ]: 数据处理完成, 任务结束: 本步耗时 {} 毫秒, 总计耗时 {} 毫秒.", convert(t2), t2 - t1,
t2 - t0);
return CompletableFuture.completedFuture(parent);
}
/**
* 获取网格人员信息
* @param orgId 入参: 组织ID.
* @return 统计结果.
*/
@Async
public CompletableFuture<?> gridPersonNumberAsyncStatistic(BigDecimal tenantId, BigDecimal orgId, JSONObject parent) {
long t0 = System.currentTimeMillis();
log.info("\n[ {} ][ 网格人员情况 ][ 网格人数统计 ]: 任务开始.", convert(t0));
// 查询数据库, 获取原始数据
List<KeyValuePair<BigDecimal>> list = gridDataStatisticMapper.statisticGridPerson(tenantId, orgId);
long t1 = System.currentTimeMillis();
log.info("\n[ {} ][ 网格人员情况 ][ 网格人数统计 ]: 原始数据查询成功: 本步耗时 {} 毫秒, 总计耗时 {} 毫秒.", convert(t1),t1 - t0,t1 - t0);
// 初始化查询结果容器.
// 初始化查询结果容器.管理类,科研类,生产经营类,项目建设类,生产作业类,网格人员总数
String[] mapEntry = {"Manage", "Scientific", "ProductionOperation", "ProjectBuild","FlowHomework", "GridPersonTotal"};
EChartsResult result = new EChartsResult();
result.init(null, mapEntry, null);
BigDecimal gridTotal = BigDecimal.ZERO;
// 处理原始数据, 填充查询结果容器.
for (KeyValuePair<BigDecimal> item : list) {
if (Objects.nonNull(item.getKey())) {
switch (item.getKey()) {
case "1":
result.addToMap(mapEntry[0], item.getValue());
gridTotal = gridTotal.add(item.getValue());
break;
case "2":
result.addToMap(mapEntry[1], item.getValue());
gridTotal = gridTotal.add(item.getValue());
break;
case "3":
result.addToMap(mapEntry[2], item.getValue());
gridTotal = gridTotal.add(item.getValue());
break;
case "4":
result.addToMap(mapEntry[3], item.getValue());
gridTotal = gridTotal.add(item.getValue());
break;
default:
result.addToMap(mapEntry[4], item.getValue());
gridTotal = gridTotal.add(item.getValue());
}
}
}
result.addToMap(mapEntry[5], gridTotal);
// 返回查询结果.
parent.put("GridPersonStatistic", result.getMap());
long t2 = System.currentTimeMillis();
log.info("\n[ {} ][ 网格人员情况 ][ 网格人数统计 ]: 数据处理完成, 任务结束: 本步耗时 {} 毫秒, 总计耗时 {} 毫秒.", convert(t2), t2 - t1,
t2 - t0);
return CompletableFuture.completedFuture(parent);
}
}
Mapper层
package com.cnpc.dj.party.repository;
import com.cnpc.dj.party.common.KeyValuePair;
import org.apache.ibatis.annotations.Mapper;
import java.math.BigDecimal;
import java.util.List;
@Mapper
public interface GridDataStatisticMapper {
/**
* 统计网格数量
* @param tenantId
* @param orgId
* @return K V
*/
List<KeyValuePair<BigDecimal>> statisticGrid(BigDecimal tenantId, BigDecimal orgId);
/**
* 统计网格人数
* @param tenantId
* @param orgId
* @return K V
*/
List<KeyValuePair<BigDecimal>> statisticGridPerson(BigDecimal tenantId, BigDecimal orgId);
}
Mapper.xml层
<?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.cnpc.dj.party.repository.GridDataStatisticMapper">
<resultMap id="KeyValuePair" type="com.cnpc.dj.party.common.KeyValuePair">
<result column="K" property="key" jdbcType="VARCHAR" javaType="java.lang.String"/>
<result column="V" property="value" jdbcType="INTEGER" javaType="java.math.BigDecimal"/>
</resultMap>
<select id="statisticGrid" parameterType="java.math.BigDecimal" resultMap="KeyValuePair">
SELECT G.GRID_CLASS k,
COUNT(*) v
FROM ZHONGHY_ONLINE_ANSWERS.DJ_GRID G
WHERE G.IS_DELETE = '0'
AND G.ORG_CODE IN (SELECT o.ORG_CODE
FROM ZHONGHY_BASIC_INFO.DJ_ORG O
WHERE o.is_delete = '0'
AND o.is_del_org = '0'
AND o.tenant_id = #{tenantId, jdbcType=DECIMAL}
AND !REGEXP_LIKE(o.org_code, '^(000.001|000.002)')
CONNECT BY PRIOR o.id = o.parent_id
START WITH o.id = #{orgId, jdbcType=DECIMAL})
GROUP BY G.GRID_CLASS
ORDER BY G.GRID_CLASS
</select>
<select id="statisticGridPerson" parameterType="java.math.BigDecimal" resultMap="KeyValuePair">
SELECT G.GRID_CLASS k,
COUNT(*) v
FROM ZHONGHY_ONLINE_ANSWERS.DJ_GRID_RANGE R
LEFT JOIN ZHONGHY_ONLINE_ANSWERS.DJ_GRID G
ON R.GRID_ID = G.ID AND R.IS_DELETE = '0'
WHERE G.IS_DELETE = '0'
AND G.ORG_CODE IN (SELECT o.ORG_CODE
FROM ZHONGHY_BASIC_INFO.DJ_ORG O
WHERE o.is_delete = '0'
AND o.is_del_org = '0'
AND o.tenant_id = #{tenantId, jdbcType=DECIMAL}
AND !REGEXP_LIKE(o.org_code, '^(000.001|000.002)')
CONNECT BY PRIOR o.id = o.parent_id
START WITH o.id = #{orgId, jdbcType=DECIMAL})
GROUP BY G.GRID_CLASS
ORDER BY G.GRID_CLASS
</select>
</mapper>
公共类EChartsResult
package com.cnpc.dj.party.common;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
/**
* 陕西信合 - 数据统计.
*/
public class EChartsResult {
public static final Comparator<? super Entry> VALUE_ASC = Comparator.comparing(Entry::getValue);
public static final Comparator<? super Entry> VALUE_DESC = (Entry o1, Entry o2) -> o2.getValue()
.compareTo(
o1.getValue());
private Comparator<? super Entry> comparator;
private LinkedHashMap<String, Entry> entryMap;
private LinkedHashMap<String, BigDecimal> valueMap;
private BigDecimal total;
public void init(String[] names, String[] keys, Comparator<? super Entry> comparator) {
// 初始化EntryMap
if (names != null && names.length > 0) {
this.entryMap = new LinkedHashMap<>(names.length);
for (String name : names) {
this.entryMap.put(name, new Entry(name, BigDecimal.ZERO, null));
}
}
// 初始化ValueMap
if (keys != null && keys.length > 0) {
this.valueMap = new LinkedHashMap<>(keys.length);
for (String key : keys) {
this.valueMap.put(key, BigDecimal.ZERO);
}
}
// 设置Comparator
this.comparator = comparator;
}
public void setComparator(Comparator<? super Entry> comparator) {
this.comparator = comparator;
}
public void addToList(String name, BigDecimal value) {
if (this.entryMap == null) {
this.entryMap = new LinkedHashMap<>();
}
if (this.entryMap.containsKey(name)) {
this.entryMap.get(name).addValue(value);
} else {
this.entryMap.put(name, new Entry(name, value, null));
}
}
public void addToMap(String key, BigDecimal value) {
if (this.valueMap == null) {
this.valueMap = new LinkedHashMap<>();
}
this.valueMap.put(key, this.valueMap.containsKey(key)
? this.valueMap.get(key).add(value)
: value);
}
public void calculate() {
this.calculateTotal();
this.calculatePercent();
}
public void calculate(BigDecimal total) {
this.calculateTotal();
this.calculatePercent(total);
}
private void calculateTotal() {
if (this.entryMap != null) {
// 初始化Total.
this.total = BigDecimal.ZERO;
// 累加求和.
for (Entry entry : this.entryMap.values()) {
this.total = this.total.add(entry.getValue());
}
}
}
private void calculatePercent() {
if (this.entryMap != null) {
// 若Total未初始化, 则先计算Total.
if (this.total == null) {
this.calculateTotal();
}
// 遍历EntryMap的所有项目, 计算百分比.
this.entryMap.values().forEach(entry -> entry.calculatePercent(this.total));
}
}
private void calculatePercent(BigDecimal total) {
if (this.entryMap != null) {
// 遍历EntryMap的所有项目, 计算百分比.
this.entryMap.values().forEach(entry -> entry.calculatePercent(total));
}
}
public void buildMap() {
this.calculate();
LinkedList<Entry> list = this.getList();
if (list != null) {
for (Entry entry : list) {
this.addToMap(entry.getName(), entry.getValue());
this.addToMap(entry.getName() + "Percent", entry.getPercent());
}
this.addToMap("Total", this.total);
}
}
public LinkedList<Entry> getList() {
if (this.entryMap != null) {
LinkedList<Entry> list = new LinkedList<>(this.entryMap.values());
if (this.comparator != null) {
list.sort(this.comparator);
}
return list;
}
return null;
}
public LinkedHashMap<String, BigDecimal> getMap() {
return this.valueMap;
}
public BigDecimal getTotal() {
return this.total;
}
/**
* ECharts 统计列表项.
*
* @author wangzijie05@cnpc.com.cn
* @since 2019-03-15
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Entry {
private String name;
private BigDecimal value;
private BigDecimal percent;
void addValue(BigDecimal augend) {
this.value = this.value.add(augend);
}
void calculatePercent(BigDecimal total) {
if (BigDecimal.ZERO.equals(total)) {
this.percent = BigDecimal.ZERO;
} else {
this.percent = this.value.abs().divide(total, 10, BigDecimal.ROUND_HALF_UP);
}
}
}
}
公共类KeyValuePair
package com.cnpc.dj.party.common;
import lombok.Data;
@Data
public class KeyValuePair<T> {
private String key;
private T value;
}
postman测试
