Commit deb9514431205d69a38c79408790ba37ff7526c0

Authored by 胡翰林
2 parents f97edeeb 84e7e517

Merge remote-tracking branch 'origin/0730_word'

... ... @@ -97,6 +97,38 @@
97 97 <artifactId>easyexcel</artifactId>
98 98 <version>3.1.0</version>
99 99 </dependency>
  100 + <dependency>
  101 + <groupId>org.apache.poi</groupId>
  102 + <artifactId>poi-ooxml</artifactId>
  103 + <version>4.1.2</version>
  104 + </dependency>
  105 + <dependency>
  106 + <groupId>org.apache.poi</groupId>
  107 + <artifactId>poi-scratchpad</artifactId>
  108 + <version>4.1.2</version>
  109 + </dependency>
  110 + <dependency>
  111 + <groupId>org.apache.poi</groupId>
  112 + <artifactId>poi-excelant</artifactId>
  113 + <version>4.1.2</version>
  114 + </dependency>
  115 + <dependency>
  116 + <groupId>org.apache.poi</groupId>
  117 + <artifactId>poi-ooxml-schemas</artifactId>
  118 + <version>4.1.2</version>
  119 + </dependency>
  120 + <dependency>
  121 + <groupId>org.jfree</groupId>
  122 + <artifactId>jfreechart</artifactId>
  123 + <version>1.5.3</version>
  124 + </dependency>
  125 + <dependency>
  126 + <groupId>com.deepoove</groupId>
  127 + <artifactId>poi-tl</artifactId>
  128 + <version>1.10.0</version>
  129 + </dependency>
  130 +
  131 +
100 132 </dependencies>
101 133 <build>
102 134 <plugins>
... ...
... ... @@ -3,20 +3,35 @@ package com.ash.controller;
3 3 import com.ash.base.*;
4 4 import com.ash.entity.Case;
5 5 import com.ash.entity.CaseAnalysis;
  6 +import com.ash.entity.WarningInstance;
  7 +import com.ash.entity.WarningInstanceAnalysis;
  8 +import com.ash.enums.JFChartTypeEnum;
6 9 import com.ash.service.CaseAnalysisService;
7 10 import com.ash.service.CaseService;
  11 +import com.ash.service.WarningInstanceAnalysisService;
8 12 import com.ash.service.WarningInstanceService;
9   -import com.ash.util.DateUtils;
  13 +import com.ash.util.*;
  14 +import com.deepoove.poi.XWPFTemplate;
  15 +import com.deepoove.poi.config.Configure;
  16 +import com.deepoove.poi.data.PictureType;
  17 +import com.deepoove.poi.data.Pictures;
  18 +import com.deepoove.poi.data.Tables;
  19 +import com.deepoove.poi.data.style.BorderStyle;
10 20 import lombok.extern.slf4j.Slf4j;
11 21 import org.apache.commons.collections.CollectionUtils;
  22 +import org.apache.commons.collections4.MapUtils;
12 23 import org.apache.commons.lang3.StringUtils;
  24 +import org.springframework.core.io.ClassPathResource;
13 25 import org.springframework.web.bind.annotation.*;
14 26
15 27 import javax.annotation.Resource;
16   -import java.util.ArrayList;
17   -import java.util.HashMap;
18   -import java.util.List;
19   -import java.util.Map;
  28 +import javax.servlet.http.HttpServletResponse;
  29 +import java.io.*;
  30 +import java.nio.charset.StandardCharsets;
  31 +import java.text.ParseException;
  32 +import java.text.SimpleDateFormat;
  33 +import java.util.*;
  34 +import java.util.concurrent.atomic.AtomicReference;
20 35 import java.util.stream.Collectors;
21 36 import java.util.stream.Stream;
22 37
... ... @@ -29,6 +44,9 @@ public class StatisticsController extends BaseController {
29 44 private WarningInstanceService warningInstanceService;
30 45
31 46 @Resource
  47 + private WarningInstanceAnalysisService warningInstanceAnalysisService;
  48 +
  49 + @Resource
32 50 private CaseAnalysisService caseAnalysisService;
33 51
34 52 @Resource
... ... @@ -168,6 +186,11 @@ public class StatisticsController extends BaseController {
168 186
169 187 }
170 188
  189 + dataList.sort((d1, d2) -> {
  190 + double value = ObjectValueOption.getObjDouble(d2.getValue()) - ObjectValueOption.getObjDouble(d1.getValue());
  191 + return (int) value;
  192 + });
  193 +
171 194
172 195 return JsonResult.ok(OptionStatus.OPT_SUCCESS.getName(), dataList);
173 196 } catch (Exception ex) {
... ... @@ -224,6 +247,11 @@ public class StatisticsController extends BaseController {
224 247
225 248 }
226 249
  250 + dataList.sort((d1, d2) -> {
  251 + double value = ObjectValueOption.getObjDouble(d2.getValue()) - ObjectValueOption.getObjDouble(d1.getValue());
  252 + return (int) value;
  253 + });
  254 +
227 255
228 256 return JsonResult.ok(OptionStatus.OPT_SUCCESS.getName(), dataList);
229 257 } catch (Exception ex) {
... ... @@ -351,4 +379,356 @@ public class StatisticsController extends BaseController {
351 379 }
352 380
353 381
  382 + @GetMapping("/downloadReport")
  383 + public void downloadReport(@RequestParam(value = "startTime", required = true) String startTime,
  384 + @RequestParam(value = "endTime", required = true) String endTime,
  385 + HttpServletResponse response) throws ParseException, IOException {
  386 + Map<String, Object> dataMap = new HashMap<>();
  387 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  388 + StatisticsParams statisticsParams = new StatisticsParams();
  389 + statisticsParams.setStartTime(DateUtils.weeHours(sdf.parse(startTime), 0));
  390 + statisticsParams.setEndTime(DateUtils.weeHours(sdf.parse(endTime), 1));
  391 + JsonResult totalWiInfo = totalWiInfo(statisticsParams);
  392 + dataMap.put("totalInfo", totalWiInfo.getData());
  393 +
  394 + JsonResult totalCaseInfo = totalCaseInfo(statisticsParams);
  395 + dataMap.put("totalCaseInfo", totalCaseInfo.getData());
  396 +
  397 + //警情各地市分布饼图
  398 + List<PieChartVo> wiAreaData = warningInstanceService.statisticsCountByArea(statisticsParams);
  399 + dataMap.put("wiAreaData", wiAreaData);
  400 +
  401 + //警情各地市环比变化柱状图
  402 + JsonResult wissAreaData = wiStatisticsSequentialByArea(statisticsParams);
  403 + dataMap.put("wissAreaData", wissAreaData.getData());
  404 +
  405 + //警情子类分布
  406 + List<PieChartVo> wiSubTypeData = warningInstanceService.statisticsCountBySubType(statisticsParams);
  407 + dataMap.put("wiSubTypeData", wiSubTypeData);
  408 +
  409 + //警情趋势
  410 + List<BarChartVo> wisDateData = warningInstanceService.statisticsByDate(statisticsParams);
  411 + List<PieChartVo> pdWisDateData = wisDateData.stream()
  412 + .map(e -> new PieChartVo(e.getName(), e.getValue())).collect(Collectors.toList());
  413 + dataMap.put("wisDateData", pdWisDateData);
  414 +
  415 + //案件各地市分布
  416 + List<PieChartVo> caseAreaData = caseService.statisticsCountByArea(statisticsParams);
  417 + dataMap.put("caseAreaData", caseAreaData);
  418 +
  419 + //电诈案件环比情况
  420 + JsonResult caseSsAreaData = caseStatisticsSequentialByArea(statisticsParams);
  421 + dataMap.put("caseSsAreaData", caseSsAreaData.getData());
  422 +
  423 + //案件诈骗类型分布
  424 + JsonResult csfData = caseStatisticsByFraudType(statisticsParams);
  425 + dataMap.put("csfData", csfData.getData());
  426 +
  427 + //案件引流方式分布图
  428 + List<PieChartVo> ccrmData = caseService.statisticsCountByRainageMethod(statisticsParams);
  429 + dataMap.put("ccrmData", ccrmData);
  430 +
  431 + //案件支付方式分布图
  432 + List<PieChartVo> ccpmData = caseService.statisticsCountByPayMethod(statisticsParams);
  433 + dataMap.put("ccpmData", ccpmData);
  434 +
  435 + //案件受害人职业分布图
  436 + List<PieChartVo> ccCareerData = caseService.statisticsCountByCareer(statisticsParams);
  437 + dataMap.put("ccCareerData", ccCareerData);
  438 +
  439 + //案损分布
  440 + List<PieChartVo> ccLossData = caseService.statisticsByLoss(statisticsParams);
  441 + dataMap.put("ccLossData", ccLossData);
  442 +
  443 + //发案趋势
  444 + List<PieChartVo> ccDateData = caseService.statisticsByDate(statisticsParams);
  445 + dataMap.put("ccDateData", ccDateData);
  446 +
  447 + //案件受害人性别占比
  448 + List<PieChartVo> sexData = caseService.statisticsCountBySex(statisticsParams);
  449 + dataMap.put("sexData", sexData);
  450 +
  451 + //案件受害人年龄占比
  452 + List<PieChartVo> ageData = caseService.statisticsByAge(statisticsParams);
  453 + dataMap.put("ageData", ageData);
  454 +
  455 + //50w以上案件
  456 + JsonResult majorCaseData = majorCasePage(statisticsParams);
  457 + dataMap.put("majorCaseData", majorCaseData.getData());
  458 +
  459 + //50w以上警情
  460 + List<WarningInstance> majorWiData = warningInstanceService.majorWiPage(statisticsParams);
  461 + if (CollectionUtils.isNotEmpty(majorWiData)) {
  462 + List<String> wiIds = majorWiData
  463 + .stream().map(WarningInstance::getId).collect(Collectors.toList());
  464 + Map<String, WarningInstanceAnalysis> analysisMap = warningInstanceAnalysisService.listByWiId(wiIds);
  465 + majorWiData.forEach(e -> e.setAnalysis(analysisMap.get(e.getId())));
  466 + }
  467 + dataMap.put("majorWiData", majorWiData);
  468 +
  469 + // 生成最终文件路径
  470 + String fileName = UUIDGenerator.uuid() + ".docx";
  471 + String filePath = JFChartUtils.OUTPUT_DIR + fileName;
  472 +
  473 + String dataRange = "【" + (startTime.equals(endTime) ? startTime : startTime + "~" + endTime) + "】";
  474 +
  475 + buildWord(dataMap, dataRange, filePath);
  476 + try {
  477 + response.setContentType("application/octet-stream");
  478 + response.setCharacterEncoding("utf-8");
  479 + String downloadName = "统计报表";
  480 + downloadName = new String(downloadName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
  481 + response.setHeader("Content-Disposition", "attachment;filename=" + downloadName + ".docx");
  482 +
  483 + InputStream inputStream = new FileInputStream(filePath);
  484 + OutputStream outputStream = response.getOutputStream();
  485 + byte[] buffer = new byte[4096];
  486 + int bytesRead = -1;
  487 + while ((bytesRead = inputStream.read(buffer)) != -1) {
  488 + outputStream.write(buffer, 0, bytesRead);
  489 + }
  490 + inputStream.close();
  491 + outputStream.close();
  492 + } catch (Exception e) {
  493 + e.printStackTrace();
  494 + }
  495 +
  496 + }
  497 +
  498 + @SuppressWarnings("unchecked")
  499 + public void buildWord(Map<String, Object> data, String dataRange, String filePath) throws IOException {
  500 +
  501 + ClassPathResource resource = new ClassPathResource("/template/statisticsReport.docx");
  502 + File file = new File(resource.getFile().toPath().toString());
  503 +
  504 + Map<String, Object> dataMap = new HashMap<>();
  505 +
  506 + Map<String, Object> totalInfo = (Map<String, Object>) data.get("totalInfo");
  507 + // 警情总体情况
  508 + dataMap.put("date", dataRange);
  509 + dataMap.put("wiValue", totalInfo.get("value"));
  510 +
  511 + String sequential = (String) totalInfo.get("sequential");
  512 + if ("--".equals(sequential)) {
  513 + dataMap.put("ns", true);
  514 + } else {
  515 + dataMap.put("hs", true);
  516 + dataMap.put("sequential", sequential.replaceAll("-", ""));
  517 + dataMap.put("sequentialType", sequential.contains("-") ? "下降" : "上升");
  518 + }
  519 +
  520 + //案件总体情况
  521 + Map<String, Object> totalCaseInfo = (Map<String, Object>) data.get("totalCaseInfo");
  522 + dataMap.put("caseValue", totalCaseInfo.get("value"));
  523 + String caseSequential = (String) totalCaseInfo.get("sequential");
  524 + if ("--".equals(caseSequential)) {
  525 + dataMap.put("cns", true);
  526 + } else {
  527 + dataMap.put("chs", true);
  528 + dataMap.put("caseSequential", caseSequential.replaceAll("-", ""));
  529 + dataMap.put("caseSequentialType", caseSequential.contains("-") ? "下降" : "上升");
  530 + }
  531 +
  532 + //警情各地市分布饼图
  533 + List<PieChartVo> wiAreaDataList = (List<PieChartVo>) data.get("wiAreaData");
  534 + String dailyPicFile = JFChartUtils.createChart(wiAreaDataList, JFChartTypeEnum.PIE, dataRange + "警情分布图", "市", "数量");
  535 + dataMap.put("sWIAreaPic", Pictures.ofStream(new FileInputStream(dailyPicFile), PictureType.JPEG).size(600, 200).create());
  536 +
  537 + //警情各地市环比变化柱状图
  538 + List<PieChartVo> wissAreaData = (List<PieChartVo>) data.get("wissAreaData");
  539 + String sWISeqAreaPic = JFChartUtils.createChart(wissAreaData, JFChartTypeEnum.BAR, dataRange + "警情环比情况", "市", "环比");
  540 + dataMap.put("sWISeqAreaPic", Pictures.ofStream(new FileInputStream(sWISeqAreaPic), PictureType.JPEG).size(600, 200).create());
  541 +
  542 + //警情子类分布
  543 + List<PieChartVo> wiSubTypeData = (List<PieChartVo>) data.get("wiSubTypeData");
  544 + String wiSubTypeDataPic = JFChartUtils.createChart(wiSubTypeData, JFChartTypeEnum.PIE, dataRange + "警情类别分布", "警情类别", "数量");
  545 + dataMap.put("wiSubTypeDataPic", Pictures.ofStream(new FileInputStream(wiSubTypeDataPic), PictureType.JPEG).size(600, 200).create());
  546 +
  547 +
  548 + //警情分析
  549 + List<PieChartVo> wisDateData = (List<PieChartVo>) data.get("wisDateData");
  550 + String wisDateDataPic = JFChartUtils.createChart(wisDateData, JFChartTypeEnum.LINE, dataRange + "警情趋势", "市", "数量");
  551 + dataMap.put("wisDateDataPic", Pictures.ofStream(new FileInputStream(wisDateDataPic), PictureType.JPEG).size(600, 200).create());
  552 +
  553 + //案件各地市分布
  554 + List<PieChartVo> caseAreaData = (List<PieChartVo>) data.get("caseAreaData");
  555 + String caseAreaDataPic = JFChartUtils.createChart(caseAreaData, JFChartTypeEnum.PIE, dataRange + "案件分布图", "市", "数量");
  556 + dataMap.put("caseAreaDataPic", Pictures.ofStream(new FileInputStream(caseAreaDataPic), PictureType.JPEG).size(600, 200).create());
  557 +
  558 + //电诈案件环比情况
  559 + List<PieChartVo> caseSsAreaData = (List<PieChartVo>) data.get("caseSsAreaData");
  560 + String caseSsAreaDataPic = JFChartUtils.createChart(caseSsAreaData, JFChartTypeEnum.BAR, dataRange + "电诈案件环比情况", "市", "环比");
  561 + dataMap.put("caseSsAreaDataPic", Pictures.ofStream(new FileInputStream(caseSsAreaDataPic), PictureType.JPEG).size(600, 200).create());
  562 +
  563 + //案件诈骗类型分布
  564 + List<PieChartVo> csfData = (List<PieChartVo>) data.get("csfData");
  565 + String sCsfDataPic = JFChartUtils.createChart(csfData, JFChartTypeEnum.PIE, dataRange + "诈骗类型分布", "诈骗类型", "数量");
  566 + dataMap.put("sCsfDataaPic", Pictures.ofStream(new FileInputStream(sCsfDataPic), PictureType.JPEG).size(600, 200).create());
  567 +
  568 + //案件引流方式分布图
  569 + List<PieChartVo> ccrmData = (List<PieChartVo>) data.get("ccrmData");
  570 + String ccrmDataPic = JFChartUtils.createChart(ccrmData, JFChartTypeEnum.PIE, dataRange + "引流方式分布图", "引流方式", "数量");
  571 + dataMap.put("ccrmDataPic", Pictures.ofStream(new FileInputStream(ccrmDataPic), PictureType.JPEG).size(600, 200).create());
  572 +
  573 + //案件支付方式分布图
  574 + List<PieChartVo> ccpmData = (List<PieChartVo>) data.get("ccpmData");
  575 + String ccpmDataPic = JFChartUtils.createChart(ccpmData, JFChartTypeEnum.PIE, dataRange + "支付方式分布图", "支付方式", "数量");
  576 + dataMap.put("ccpmDataPic", Pictures.ofStream(new FileInputStream(ccpmDataPic), PictureType.JPEG).size(600, 200).create());
  577 +
  578 + //案件受害人职业分布图
  579 + List<PieChartVo> ccCareerData = (List<PieChartVo>) data.get("ccCareerData");
  580 + String ccCareerDataPic = JFChartUtils.createChart(ccCareerData, JFChartTypeEnum.BAR, dataRange + "受害人职业分布图", "受害人职业", "数量");
  581 + dataMap.put("ccCareerDataPic", Pictures.ofStream(new FileInputStream(ccCareerDataPic), PictureType.JPEG).size(600, 200).create());
  582 +
  583 + //案损分布
  584 + List<PieChartVo> ccLossData = (List<PieChartVo>) data.get("ccLossData");
  585 + String ccLossDataPic = JFChartUtils.createChart(ccLossData, JFChartTypeEnum.BAR, dataRange + "案损分布", "案损", "数量");
  586 + dataMap.put("ccLossDataPic", Pictures.ofStream(new FileInputStream(ccLossDataPic), PictureType.JPEG).size(600, 200).create());
  587 +
  588 + int clIndex = 1;
  589 + for (PieChartVo clData : ccLossData) {
  590 + String key = "clr" + clIndex++;
  591 + dataMap.put(key, clData.getValue());
  592 + }
  593 +
  594 + //发案趋势
  595 + List<PieChartVo> ccDateData = (List<PieChartVo>) data.get("ccDateData");
  596 + String ccDateDataPic = JFChartUtils.createChart(ccDateData, JFChartTypeEnum.LINE, dataRange + "发案趋势", "日期", "数量");
  597 + dataMap.put("ccDateDataPic", Pictures.ofStream(new FileInputStream(ccDateDataPic), PictureType.JPEG).size(600, 200).create());
  598 +
  599 +
  600 + //案件受害人性别占比
  601 + List<PieChartVo> sexData = (List<PieChartVo>) data.get("sexData");
  602 + if (CollectionUtils.isNotEmpty(sexData)) {
  603 + AtomicReference<Integer> st = new AtomicReference<>(0);
  604 + sexData.forEach(e -> st.updateAndGet(v -> v + (Integer) e.getValue()));
  605 + for (PieChartVo cd : sexData) {
  606 + if ("男".equals(cd.getName())) {
  607 + dataMap.put("cMValue", cd.getValue());
  608 + dataMap.put("cMValuePer", String.format("%.1f", (Integer) cd.getValue() * 100.0 / st.get()) + "%");
  609 + } else if ("女".equals(cd.getName())) {
  610 + dataMap.put("cFValue", cd.getValue());
  611 + dataMap.put("cFValuePer", String.format("%.1f", (Integer) cd.getValue() * 100.0 / st.get()) + "%");
  612 +
  613 + }
  614 + }
  615 + }
  616 +
  617 + //案件受害人年龄占比
  618 + List<PieChartVo> ageData = (List<PieChartVo>) data.get("ageData");
  619 + if (CollectionUtils.isNotEmpty(ageData)) {
  620 + AtomicReference<Integer> at = new AtomicReference<>(0);
  621 + ageData.forEach(e -> at.updateAndGet(v -> v + (Integer) e.getValue()));
  622 + for (PieChartVo cd : ageData) {
  623 + dataMap.put(cd.getName(), cd.getValue());
  624 + dataMap.put(cd.getName() + "Per", String.format("%.1f", (Integer) cd.getValue() * 100.0 / at.get()) + "%");
  625 + }
  626 + }
  627 +
  628 + //案损列表
  629 + List<Case> majorCaseData = (List<Case>) data.get("majorCaseData");
  630 + List<CaseLossVo> nllDataList = new ArrayList<>();
  631 + CaseLossVo header = new CaseLossVo();
  632 + header.setCode("案件编号");
  633 + header.setArea("地区");
  634 + header.setCounty("县区");
  635 + header.setTotalAmount("案损");
  636 + header.setFraudType("诈骗类型");
  637 + header.setRainageMethod("引流方式");
  638 + header.setPayMethod("资金支持途径");
  639 + header.setSex("受害人性别");
  640 + header.setCareer("受害人职业");
  641 + nllDataList.add(header);
  642 +
  643 + String caseLossAreas = "";
  644 + Map<String, String> caseLossAreaMap = new HashMap<>();
  645 + if (CollectionUtils.isNotEmpty(majorCaseData)) {
  646 + for (Case cd : majorCaseData) {
  647 + CaseLossVo clv = new CaseLossVo();
  648 + clv.setCode(cd.getCode());
  649 + clv.setArea(cd.getAnalysis().getArea());
  650 + clv.setCounty(cd.getAnalysis().getCounty());
  651 + clv.setTotalAmount(String.valueOf(cd.getAnalysis().getTotalAmount()));
  652 + clv.setFraudType(cd.getAnalysis().getFraudType());
  653 + clv.setRainageMethod(cd.getAnalysis().getRainageMethod());
  654 + clv.setPayMethod(cd.getAnalysis().getPayMethod());
  655 + clv.setSex(cd.getAnalysis().getSex());
  656 + clv.setCareer(cd.getAnalysis().getCareer());
  657 + nllDataList.add(clv);
  658 + caseLossAreaMap.put(cd.getAnalysis().getArea(), "");
  659 + }
  660 + }
  661 +
  662 +
  663 + String[][] majorCaseDataArray = nllDataList.stream()
  664 + .map(e -> new String[]{e.getArea(), e.getCounty(), e.getCode()
  665 + , e.getTotalAmount(), e.getFraudType(), e.getRainageMethod()
  666 + , e.getPayMethod(), e.getSex(), e.getCareer()
  667 + }).toArray(String[][]::new);
  668 + dataMap.put("tableMcd", Tables.of(majorCaseDataArray).border(BorderStyle.DEFAULT).create());
  669 +
  670 + //警情损失列表
  671 + List<WarningInstance> majorWiData = (List<WarningInstance>) data.get("majorWiData");
  672 + List<WiLossVo> mwiDataList = new ArrayList<>();
  673 + WiLossVo wiHeader = new WiLossVo();
  674 + wiHeader.setCode("案件编号");
  675 + wiHeader.setArea("地区");
  676 + wiHeader.setCounty("县区");
  677 + wiHeader.setAlarmSubType("案件类别");
  678 + wiHeader.setAmount("案损");
  679 + wiHeader.setRainageMethod("引流方式");
  680 + wiHeader.setPayMethod("支付渠道");
  681 + wiHeader.setSex("受害人性别");
  682 + wiHeader.setCareer("受害人职业");
  683 + mwiDataList.add(wiHeader);
  684 +
  685 + Integer wi50wValue = 0;
  686 + Integer wi100wValue = 0;
  687 + if (CollectionUtils.isNotEmpty(majorWiData)) {
  688 + for (WarningInstance cd : majorWiData) {
  689 + WiLossVo clv = new WiLossVo();
  690 + clv.setCode(cd.getCode());
  691 + clv.setArea(cd.getAnalysis().getArea());
  692 + clv.setCounty(cd.getAnalysis().getCounty());
  693 + clv.setAlarmSubType(cd.getAlarmSubType());
  694 + clv.setAmount(String.valueOf(cd.getAnalysis().getAmount()));
  695 + clv.setRainageMethod(cd.getAnalysis().getRainageMethod());
  696 + clv.setPayMethod(cd.getAnalysis().getPayMethod());
  697 + clv.setSex(cd.getAnalysis().getSex());
  698 + clv.setCareer(cd.getAnalysis().getCareer());
  699 + mwiDataList.add(clv);
  700 + caseLossAreaMap.put(cd.getAnalysis().getArea(), "");
  701 + if (cd.getAnalysis().getAmount() < 1000000) {
  702 + wi50wValue++;
  703 + } else {
  704 + wi100wValue++;
  705 + }
  706 + }
  707 + }
  708 +
  709 + dataMap.put("wi50wValue", wi50wValue);
  710 + dataMap.put("wi100wValue", wi100wValue);
  711 +
  712 + String[][] majorWiDataArray = mwiDataList.stream()
  713 + .map(e -> new String[]{e.getCode(), e.getArea(), e.getCounty()
  714 + , e.getAlarmSubType(), e.getAmount(), e.getRainageMethod()
  715 + , e.getPayMethod(), e.getSex(), e.getCareer()
  716 + }).toArray(String[][]::new);
  717 + dataMap.put("tableMwd", Tables.of(majorWiDataArray).border(BorderStyle.DEFAULT).create());
  718 +
  719 + if (MapUtils.isNotEmpty(caseLossAreaMap)) {
  720 + caseLossAreas = String.join(",", caseLossAreaMap.keySet());
  721 + }
  722 +
  723 + caseLossAreas = StringUtils.isNotBlank(caseLossAreas) ? caseLossAreas : "--";
  724 + dataMap.put("caseLossAreas", caseLossAreas);
  725 +
  726 +
  727 + try (XWPFTemplate template = XWPFTemplate.compile(file, Configure.newBuilder().buildGramer("${", "}").build())
  728 + .render(dataMap)) {
  729 + template.writeToFile(filePath);
  730 + }
  731 +
  732 + }
  733 +
354 734 }
... ...
... ... @@ -88,4 +88,7 @@ public class Case extends BaseModel {
88 88
89 89 @Transient
90 90 private transient Double totalAmount;
  91 +
  92 + @Transient
  93 + private transient Integer age;
91 94 }
... ...
... ... @@ -30,6 +30,12 @@ public class WarningInstanceAnalysis extends BaseModel {
30 30 private String area;
31 31
32 32 /**
  33 + * 县区
  34 + */
  35 + @TableField(value = "county")
  36 + private String county;
  37 +
  38 + /**
33 39 * 案损金额
34 40 */
35 41 @TableField(value = "amount")
... ...
  1 +package com.ash.enums;
  2 +
  3 +public enum CaseVictimAgeRangeEnum {
  4 + CVAR1("小于30岁"),
  5 + CVAR2("31-40岁"),
  6 + CVAR3("41-50岁"),
  7 + CVAR4("大于50岁"),
  8 + ;
  9 +
  10 + private final String text;
  11 +
  12 + private CaseVictimAgeRangeEnum(String text) {
  13 + this.text = text;
  14 + }
  15 +
  16 + public String getText() {
  17 + return text;
  18 + }
  19 +}
... ...
  1 +package com.ash.enums;
  2 +
  3 +public enum JFChartTypeEnum {
  4 + LINE("折线图"),
  5 + PIE("饼状图"),
  6 + BAR("柱形图"),
  7 + ;
  8 +
  9 +
  10 + private final String text;
  11 +
  12 + private JFChartTypeEnum(String text) {
  13 + this.text = text;
  14 + }
  15 +
  16 + public String getText() {
  17 + return text;
  18 + }
  19 +}
... ...
  1 +package com.ash.enums;
  2 +
  3 +public enum LossRangeEnum {
  4 + R1("小于10万"),
  5 + R2("10万-20万"),
  6 + R3("20万-50万"),
  7 + R4("50万-100万"),
  8 + R5("大于100万"),
  9 + ;
  10 +
  11 +
  12 + private final String text;
  13 +
  14 + private LossRangeEnum(String text) {
  15 + this.text = text;
  16 + }
  17 +
  18 + public String getText() {
  19 + return text;
  20 + }
  21 +}
... ...
... ... @@ -10,7 +10,9 @@ import com.ash.entity.Case;
10 10 import com.ash.entity.CaseAnalysis;
11 11 import com.ash.entity.dao.CaseMapper;
12 12 import com.ash.enums.AnalysisStatusEnum;
  13 +import com.ash.enums.CaseVictimAgeRangeEnum;
13 14 import com.ash.enums.ConformStatusEnum;
  15 +import com.ash.enums.LossRangeEnum;
14 16 import com.ash.excelData.CaseExcelData;
15 17 import com.ash.listener.CaseExcelListener;
16 18 import com.ash.util.*;
... ... @@ -49,6 +51,22 @@ public class CaseService {
49 51 @Resource
50 52 private CaseAnalysisService caseAnalysisService;
51 53
  54 + private static List<String> lossRangeList = new ArrayList<>();
  55 + private static List<String> cvaRangeList = new ArrayList<>();
  56 +
  57 + static {
  58 + lossRangeList.add(LossRangeEnum.R1.getText());
  59 + lossRangeList.add(LossRangeEnum.R2.getText());
  60 + lossRangeList.add(LossRangeEnum.R3.getText());
  61 + lossRangeList.add(LossRangeEnum.R4.getText());
  62 + lossRangeList.add(LossRangeEnum.R5.getText());
  63 +
  64 + cvaRangeList.add(CaseVictimAgeRangeEnum.CVAR1.name());
  65 + cvaRangeList.add(CaseVictimAgeRangeEnum.CVAR2.name());
  66 + cvaRangeList.add(CaseVictimAgeRangeEnum.CVAR3.name());
  67 + cvaRangeList.add(CaseVictimAgeRangeEnum.CVAR4.name());
  68 + }
  69 +
52 70 public Boolean save(Case data) {
53 71 String uuid = UUIDGenerator.uuid();
54 72 data.setId(uuid);
... ... @@ -145,7 +163,7 @@ public class CaseService {
145 163
146 164 public List<Case> getCaseLoss(StatisticsParams params) {
147 165 MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<Case>();
148   - mpjQueryWrapper.select("t.id,ca.total_amount as totalAmount")
  166 + mpjQueryWrapper.select("t.id,ca.total_amount as totalAmount,ca.age")
149 167 .leftJoin("t_ash_case_analysis ca on t.id=ca.case_id");
150 168
151 169 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
... ... @@ -161,6 +179,64 @@ public class CaseService {
161 179 return caseMapper.selectJoinList(Case.class, mpjQueryWrapper);
162 180 }
163 181
  182 + public List<PieChartVo> statisticsByLoss(StatisticsParams params) {
  183 + LinkedHashMap<String, Integer> dataMap = new LinkedHashMap<>();
  184 + lossRangeList.forEach(e -> dataMap.put(e, 0));
  185 + List<Case> caseLoss = getCaseLoss(params);
  186 + for (Case loss : caseLoss) {
  187 + Double totalAmount = loss.getTotalAmount();
  188 + if (totalAmount == null) {
  189 + continue;
  190 + }
  191 + LossRangeEnum lossRange = LossRangeEnum.R1;
  192 + if (totalAmount < 100000) {
  193 + lossRange = LossRangeEnum.R1;
  194 + } else if (totalAmount >= 100000 && totalAmount < 200000) {
  195 + lossRange = LossRangeEnum.R2;
  196 + } else if (totalAmount >= 200000 && totalAmount < 500000) {
  197 + lossRange = LossRangeEnum.R3;
  198 + } else if (totalAmount >= 500000 && totalAmount < 1000000) {
  199 + lossRange = LossRangeEnum.R4;
  200 + } else if (totalAmount >= 1000000) {
  201 + lossRange = LossRangeEnum.R4;
  202 + }
  203 + Integer cv = dataMap.get(lossRange.getText());
  204 + cv++;
  205 + dataMap.put(lossRange.getText(), cv);
  206 + }
  207 +
  208 + return dataMap.keySet().stream()
  209 + .map(e -> new PieChartVo(e, dataMap.get(e))).collect(Collectors.toList());
  210 + }
  211 +
  212 + public List<PieChartVo> statisticsByAge(StatisticsParams params) {
  213 + LinkedHashMap<String, Integer> dataMap = new LinkedHashMap<>();
  214 + cvaRangeList.forEach(e -> dataMap.put(e, 0));
  215 + List<Case> caseLoss = getCaseLoss(params);
  216 + for (Case loss : caseLoss) {
  217 + Integer age = loss.getAge();
  218 + if (age == null) {
  219 + continue;
  220 + }
  221 + CaseVictimAgeRangeEnum cvaRange = CaseVictimAgeRangeEnum.CVAR1;
  222 + if (age <= 30) {
  223 + cvaRange = CaseVictimAgeRangeEnum.CVAR1;
  224 + } else if (age <= 40) {
  225 + cvaRange = CaseVictimAgeRangeEnum.CVAR2;
  226 + } else if (age <= 50) {
  227 + cvaRange = CaseVictimAgeRangeEnum.CVAR3;
  228 + } else {
  229 + cvaRange = CaseVictimAgeRangeEnum.CVAR4;
  230 + }
  231 + Integer cv = dataMap.get(cvaRange.name());
  232 + cv++;
  233 + dataMap.put(cvaRange.name(), cv);
  234 + }
  235 +
  236 + return dataMap.keySet().stream()
  237 + .map(e -> new PieChartVo(e, dataMap.get(e))).collect(Collectors.toList());
  238 + }
  239 +
164 240 public int getCaseTopLoss(StatisticsParams params) {
165 241 MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<Case>();
166 242 mpjQueryWrapper.select("t.id,ca.total_amount as totalAmount")
... ... @@ -185,9 +261,35 @@ public class CaseService {
185 261 }
186 262 }
187 263
  264 + public List<PieChartVo> statisticsByDate(StatisticsParams params) {
  265 + MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<>();
  266 + mpjQueryWrapper.select("DATE_FORMAT(t.alarm_date, '%Y-%m-%d') as alarmDate,count(0) as field_count");
  267 +
  268 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  269 + if (params.getStartTime() != null) {
  270 + mpjQueryWrapper.ge("t.alarm_date", sdf.format(DateUtils.weeHours(params.getStartTime(), 0)));
  271 +
  272 + }
  273 +
  274 + if (params.getEndTime() != null) {
  275 + mpjQueryWrapper.le("t.alarm_date", sdf.format(DateUtils.weeHours(params.getEndTime(), 1)));
  276 + }
  277 +
  278 + mpjQueryWrapper.groupBy("DATE_FORMAT(t.alarm_date, '%Y-%m-%d')");
  279 + mpjQueryWrapper.orderByAsc("DATE_FORMAT(t.alarm_date, '%Y-%m-%d')");
  280 + List<Map<String, Object>> dataList = caseMapper.selectJoinMaps(mpjQueryWrapper);
  281 + List<PieChartVo> resultList = new ArrayList<>();
  282 + resultList = dataList.stream().map(e -> {
  283 + Integer fieldCount = ObjectValueOption.getObjInt(e.get("field_count"));
  284 + return new PieChartVo(ObjectValueOption.getObjString(e.get("alarmDate")), fieldCount);
  285 + }
  286 + ).filter(e -> StringUtils.isNotBlank(e.getName())).collect(Collectors.toList());
  287 + return resultList;
  288 + }
  289 +
188 290
189 291 public List<BarChartVo> statisticsByArea(StatisticsParams params) {
190   - MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<Case>();
  292 + MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<>();
191 293 mpjQueryWrapper.select("ca.area,count(t.id) as field_count")
192 294 .leftJoin("t_ash_case_analysis ca on t.id=ca.case_id");
193 295
... ... @@ -214,8 +316,7 @@ public class CaseService {
214 316 total.updateAndGet(v -> v + fieldCount);
215 317 return new BarChartVo(ObjectValueOption.getObjString(e.get("area")), fieldCount.toString());
216 318 }
217   - ).collect(Collectors.toList());
218   - resultList = resultList.stream().filter(e -> StringUtils.isNotBlank(e.getName())).collect(Collectors.toList());
  319 + ).filter(e -> StringUtils.isNotBlank(e.getName())).collect(Collectors.toList());
219 320 if (resultList.size() > 7) {
220 321 resultList = resultList.subList(0, 7);
221 322 }
... ... @@ -229,6 +330,161 @@ public class CaseService {
229 330 return resultList;
230 331 }
231 332
  333 + public List<PieChartVo> statisticsCountByArea(StatisticsParams params) {
  334 + MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<>();
  335 + mpjQueryWrapper.select("ca.area,count(t.id) as field_count")
  336 + .leftJoin("t_ash_case_analysis ca on t.id=ca.case_id");
  337 +
  338 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  339 + if (params.getStartTime() != null) {
  340 + mpjQueryWrapper.ge("t.alarm_date", sdf.format(DateUtils.weeHours(params.getStartTime(), 0)));
  341 +
  342 + }
  343 +
  344 + if (params.getEndTime() != null) {
  345 + mpjQueryWrapper.le("t.alarm_date", sdf.format(DateUtils.weeHours(params.getEndTime(), 1)));
  346 + }
  347 +
  348 + mpjQueryWrapper.groupBy("ca.area");
  349 + mpjQueryWrapper.orderByDesc("field_count");
  350 +
  351 + List<Map<String, Object>> dataList = caseMapper.selectJoinMaps(mpjQueryWrapper);
  352 + List<PieChartVo> resultList = new ArrayList<>();
  353 + if (!CollectionUtils.isEmpty(dataList)) {
  354 + resultList = dataList.stream().map(e -> {
  355 + Integer fieldCount = ObjectValueOption.getObjInt(e.get("field_count"));
  356 + return new PieChartVo(ObjectValueOption.getObjString(e.get("area")), fieldCount);
  357 + }
  358 + ).filter(e -> StringUtils.isNotBlank(e.getName())).collect(Collectors.toList());
  359 +
  360 + }
  361 + return resultList;
  362 + }
  363 +
  364 + public List<PieChartVo> statisticsCountByRainageMethod(StatisticsParams params) {
  365 + MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<>();
  366 + mpjQueryWrapper.select("ca.rainage_method,count(t.id) as field_count")
  367 + .leftJoin("t_ash_case_analysis ca on t.id=ca.case_id");
  368 +
  369 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  370 + if (params.getStartTime() != null) {
  371 + mpjQueryWrapper.ge("t.alarm_date", sdf.format(DateUtils.weeHours(params.getStartTime(), 0)));
  372 +
  373 + }
  374 +
  375 + if (params.getEndTime() != null) {
  376 + mpjQueryWrapper.le("t.alarm_date", sdf.format(DateUtils.weeHours(params.getEndTime(), 1)));
  377 + }
  378 +
  379 + mpjQueryWrapper.groupBy("ca.rainage_method");
  380 + mpjQueryWrapper.orderByDesc("field_count");
  381 +
  382 + List<Map<String, Object>> dataList = caseMapper.selectJoinMaps(mpjQueryWrapper);
  383 + List<PieChartVo> resultList = new ArrayList<>();
  384 + if (!CollectionUtils.isEmpty(dataList)) {
  385 + resultList = dataList.stream().map(e -> {
  386 + Integer fieldCount = ObjectValueOption.getObjInt(e.get("field_count"));
  387 + return new PieChartVo(ObjectValueOption.getObjString(e.get("rainage_method")), fieldCount);
  388 + }
  389 + ).filter(e -> StringUtils.isNotBlank(e.getName())).collect(Collectors.toList());
  390 +
  391 + }
  392 + return resultList;
  393 + }
  394 +
  395 + public List<PieChartVo> statisticsCountByPayMethod(StatisticsParams params) {
  396 + MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<>();
  397 + mpjQueryWrapper.select("ca.pay_method,count(t.id) as field_count")
  398 + .leftJoin("t_ash_case_analysis ca on t.id=ca.case_id");
  399 +
  400 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  401 + if (params.getStartTime() != null) {
  402 + mpjQueryWrapper.ge("t.alarm_date", sdf.format(DateUtils.weeHours(params.getStartTime(), 0)));
  403 +
  404 + }
  405 +
  406 + if (params.getEndTime() != null) {
  407 + mpjQueryWrapper.le("t.alarm_date", sdf.format(DateUtils.weeHours(params.getEndTime(), 1)));
  408 + }
  409 +
  410 + mpjQueryWrapper.groupBy("ca.pay_method");
  411 + mpjQueryWrapper.orderByDesc("field_count");
  412 +
  413 + List<Map<String, Object>> dataList = caseMapper.selectJoinMaps(mpjQueryWrapper);
  414 + List<PieChartVo> resultList = new ArrayList<>();
  415 + if (!CollectionUtils.isEmpty(dataList)) {
  416 + resultList = dataList.stream().map(e -> {
  417 + Integer fieldCount = ObjectValueOption.getObjInt(e.get("field_count"));
  418 + return new PieChartVo(ObjectValueOption.getObjString(e.get("pay_method")), fieldCount);
  419 + }
  420 + ).filter(e -> StringUtils.isNotBlank(e.getName())).collect(Collectors.toList());
  421 +
  422 + }
  423 + return resultList;
  424 + }
  425 +
  426 + public List<PieChartVo> statisticsCountByCareer(StatisticsParams params) {
  427 + MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<>();
  428 + mpjQueryWrapper.select("ca.career,count(t.id) as field_count")
  429 + .leftJoin("t_ash_case_analysis ca on t.id=ca.case_id");
  430 +
  431 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  432 + if (params.getStartTime() != null) {
  433 + mpjQueryWrapper.ge("t.alarm_date", sdf.format(DateUtils.weeHours(params.getStartTime(), 0)));
  434 +
  435 + }
  436 +
  437 + if (params.getEndTime() != null) {
  438 + mpjQueryWrapper.le("t.alarm_date", sdf.format(DateUtils.weeHours(params.getEndTime(), 1)));
  439 + }
  440 +
  441 + mpjQueryWrapper.groupBy("ca.career");
  442 + mpjQueryWrapper.orderByDesc("field_count");
  443 +
  444 + List<Map<String, Object>> dataList = caseMapper.selectJoinMaps(mpjQueryWrapper);
  445 + List<PieChartVo> resultList = new ArrayList<>();
  446 + if (!CollectionUtils.isEmpty(dataList)) {
  447 + resultList = dataList.stream().map(e -> {
  448 + Integer fieldCount = ObjectValueOption.getObjInt(e.get("field_count"));
  449 + return new PieChartVo(ObjectValueOption.getObjString(e.get("career")), fieldCount);
  450 + }
  451 + ).filter(e -> StringUtils.isNotBlank(e.getName())).collect(Collectors.toList());
  452 +
  453 + }
  454 + return resultList;
  455 + }
  456 +
  457 + public List<PieChartVo> statisticsCountBySex(StatisticsParams params) {
  458 + MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<>();
  459 + mpjQueryWrapper.select("ca.sex,count(t.id) as field_count")
  460 + .leftJoin("t_ash_case_analysis ca on t.id=ca.case_id");
  461 +
  462 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  463 + if (params.getStartTime() != null) {
  464 + mpjQueryWrapper.ge("t.alarm_date", sdf.format(DateUtils.weeHours(params.getStartTime(), 0)));
  465 +
  466 + }
  467 +
  468 + if (params.getEndTime() != null) {
  469 + mpjQueryWrapper.le("t.alarm_date", sdf.format(DateUtils.weeHours(params.getEndTime(), 1)));
  470 + }
  471 +
  472 + mpjQueryWrapper.groupBy("ca.sex");
  473 + mpjQueryWrapper.orderByDesc("field_count");
  474 +
  475 + List<Map<String, Object>> dataList = caseMapper.selectJoinMaps(mpjQueryWrapper);
  476 + List<PieChartVo> resultList = new ArrayList<>();
  477 + if (!CollectionUtils.isEmpty(dataList)) {
  478 + resultList = dataList.stream().map(e -> {
  479 + Integer fieldCount = ObjectValueOption.getObjInt(e.get("field_count"));
  480 + return new PieChartVo(ObjectValueOption.getObjString(e.get("sex")), fieldCount);
  481 + }
  482 + ).filter(e -> StringUtils.isNotBlank(e.getName())).collect(Collectors.toList());
  483 +
  484 + }
  485 + return resultList;
  486 + }
  487 +
232 488 public List<PieChartVo> statisticsByFraudType(StatisticsParams params) {
233 489 MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<Case>();
234 490 mpjQueryWrapper.select("ca.fraud_type as fraudType,count(t.id) as field_count")
... ... @@ -294,7 +550,7 @@ public class CaseService {
294 550 }
295 551
296 552 public List<BarChartVo> statisticsSequentialByArea(StatisticsParams params) {
297   - MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<Case>();
  553 + MPJQueryWrapper<Case> mpjQueryWrapper = new MPJQueryWrapper<>();
298 554 mpjQueryWrapper.select("ca.area,count(t.id) as field_count")
299 555 .leftJoin("t_ash_case_analysis ca on t.id=ca.case_id");
300 556
... ...
... ... @@ -145,7 +145,7 @@ public class WarningInstanceService {
145 145 }
146 146
147 147 public List<BarChartVo> statisticsByArea(StatisticsParams params) {
148   - MPJQueryWrapper<WarningInstance> mpjQueryWrapper = new MPJQueryWrapper<WarningInstance>();
  148 + MPJQueryWrapper<WarningInstance> mpjQueryWrapper = new MPJQueryWrapper<>();
149 149 mpjQueryWrapper.select("wia.area,count(t.id) as field_count")
150 150 .leftJoin("t_ash_warning_instance_analysis wia on t.id=wia.wi_id");
151 151
... ... @@ -186,6 +186,88 @@ public class WarningInstanceService {
186 186 return resultList;
187 187 }
188 188
  189 + public List<PieChartVo> statisticsCountByArea(StatisticsParams params) {
  190 + MPJQueryWrapper<WarningInstance> mpjQueryWrapper = new MPJQueryWrapper<>();
  191 + mpjQueryWrapper.select("wia.area,count(t.id) as field_count")
  192 + .leftJoin("t_ash_warning_instance_analysis wia on t.id=wia.wi_id");
  193 +
  194 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  195 + if (params.getStartTime() != null) {
  196 + mpjQueryWrapper.ge("t.alarm_date", sdf.format(DateUtils.weeHours(params.getStartTime(), 0)));
  197 +
  198 + }
  199 +
  200 + if (params.getEndTime() != null) {
  201 + mpjQueryWrapper.le("t.alarm_date", sdf.format(DateUtils.weeHours(params.getEndTime(), 1)));
  202 + }
  203 +
  204 + mpjQueryWrapper.groupBy("wia.area");
  205 + mpjQueryWrapper.orderByDesc("field_count");
  206 +
  207 + List<Map<String, Object>> dataList = warningInstanceMapper.selectJoinMaps(mpjQueryWrapper);
  208 + List<PieChartVo> resultList = new ArrayList<>();
  209 + if (!CollectionUtils.isEmpty(dataList)) {
  210 + resultList = dataList.stream().map(e -> {
  211 + Integer fieldCount = ObjectValueOption.getObjInt(e.get("field_count"));
  212 + return new PieChartVo(ObjectValueOption.getObjString(e.get("area")), fieldCount);
  213 + }
  214 + ).filter(e -> StringUtils.isNotBlank(e.getName())).collect(Collectors.toList());
  215 + }
  216 + return resultList;
  217 + }
  218 +
  219 + public List<PieChartVo> statisticsCountBySubType(StatisticsParams params) {
  220 + MPJQueryWrapper<WarningInstance> mpjQueryWrapper = new MPJQueryWrapper<>();
  221 + mpjQueryWrapper.select("t.sub_type,count(t.id) as field_count");
  222 +
  223 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  224 + if (params.getStartTime() != null) {
  225 + mpjQueryWrapper.ge("t.alarm_date", sdf.format(DateUtils.weeHours(params.getStartTime(), 0)));
  226 +
  227 + }
  228 +
  229 + if (params.getEndTime() != null) {
  230 + mpjQueryWrapper.le("t.alarm_date", sdf.format(DateUtils.weeHours(params.getEndTime(), 1)));
  231 + }
  232 +
  233 + mpjQueryWrapper.groupBy("t.sub_type");
  234 + mpjQueryWrapper.orderByDesc("field_count");
  235 +
  236 + List<Map<String, Object>> dataList = warningInstanceMapper.selectJoinMaps(mpjQueryWrapper);
  237 + List<PieChartVo> resultList = new ArrayList<>();
  238 + if (!CollectionUtils.isEmpty(dataList)) {
  239 + resultList = dataList.stream().map(e -> {
  240 + Integer fieldCount = ObjectValueOption.getObjInt(e.get("field_count"));
  241 + return new PieChartVo(ObjectValueOption.getObjString(e.get("sub_type")), fieldCount);
  242 + }
  243 + ).filter(e -> StringUtils.isNotBlank(e.getName())).collect(Collectors.toList());
  244 + }
  245 + return resultList;
  246 + }
  247 +
  248 + public List<WarningInstance> majorWiPage(StatisticsParams params) {
  249 + MPJQueryWrapper<WarningInstance> mpjQueryWrapper = new MPJQueryWrapper<>();
  250 + mpjQueryWrapper.select("t.*")
  251 + .leftJoin("t_ash_warning_instance_analysis wia on t.id=wia.wi_id");
  252 +
  253 + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  254 + if (params.getStartTime() != null) {
  255 + mpjQueryWrapper.ge("t.alarm_date", sdf.format(DateUtils.weeHours(params.getStartTime(), 0)));
  256 +
  257 + }
  258 +
  259 + if (params.getEndTime() != null) {
  260 + mpjQueryWrapper.le("t.alarm_date", sdf.format(DateUtils.weeHours(params.getEndTime(), 1)));
  261 + }
  262 +
  263 + mpjQueryWrapper.ge("wia.amount", 500000);
  264 + mpjQueryWrapper.orderByDesc("amount");
  265 +
  266 + return warningInstanceMapper.selectJoinList(WarningInstance.class, mpjQueryWrapper);
  267 +
  268 +
  269 + }
  270 +
189 271 public List<BarChartVo> statisticsByDate(StatisticsParams params) {
190 272 MPJQueryWrapper<WarningInstance> mpjQueryWrapper = new MPJQueryWrapper<WarningInstance>();
191 273 mpjQueryWrapper.select("DATE_FORMAT(t.alarm_date, '%Y-%m-%d') as alarmDate,count(0) as field_count");
... ... @@ -322,6 +404,7 @@ public class WarningInstanceService {
322 404 WarningInstanceAnalysis wa = new WarningInstanceAnalysis();
323 405 wa.setWiId(cd.getId());
324 406 wa.setArea(cd.getMunicipalPolice().replaceAll("公安局", ""));
  407 + wa.setCounty(analysisResult.getString("area"));
325 408 wa.setAmount(analysisResult.getDouble("value"));
326 409 wa.setSex(analysisResult.getString("gender"));
327 410 wa.setCareer(analysisResult.getString("occupation"));
... ...
  1 +package com.ash.util;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * 报表导出案损列表vo
  7 + */
  8 +@Data
  9 +public class CaseLossVo {
  10 + /**
  11 + * 案件编号
  12 + */
  13 + private String code;
  14 +
  15 + /**
  16 + * 地区
  17 + */
  18 + private String area;
  19 +
  20 + /**
  21 + * 县区
  22 + */
  23 + private String county;
  24 +
  25 + /**
  26 + * 案损
  27 + */
  28 + private String totalAmount;
  29 +
  30 + /**
  31 + * 诈骗类型
  32 + */
  33 + private String fraudType;
  34 +
  35 + /**
  36 + * 引流方式
  37 + */
  38 + private String rainageMethod;
  39 +
  40 + /**
  41 + * 支付方式
  42 + */
  43 + private String payMethod;
  44 +
  45 + /**
  46 + * 受害人性别
  47 + */
  48 + private String sex;
  49 +
  50 + /**
  51 + * 受害人职业
  52 + */
  53 + private String career;
  54 +
  55 +}
... ...
  1 +package com.ash.util;
  2 +
  3 +import com.ash.base.PieChartVo;
  4 +import com.ash.enums.JFChartTypeEnum;
  5 +import com.deepoove.poi.XWPFTemplate;
  6 +import com.deepoove.poi.config.Configure;
  7 +import com.deepoove.poi.data.PictureType;
  8 +import com.deepoove.poi.data.Pictures;
  9 +import com.deepoove.poi.data.Tables;
  10 +import com.deepoove.poi.data.style.BorderStyle;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.jfree.chart.ChartFactory;
  13 +import org.jfree.chart.ChartUtils;
  14 +import org.jfree.chart.JFreeChart;
  15 +import org.jfree.chart.StandardChartTheme;
  16 +import org.jfree.chart.plot.CategoryPlot;
  17 +import org.jfree.data.category.DefaultCategoryDataset;
  18 +import org.springframework.util.ResourceUtils;
  19 +
  20 +import java.awt.*;
  21 +import java.io.File;
  22 +import java.io.FileInputStream;
  23 +import java.io.IOException;
  24 +import java.time.LocalDate;
  25 +import java.util.ArrayList;
  26 +import java.util.HashMap;
  27 +import java.util.Map;
  28 +import java.util.List;
  29 +
  30 +@Slf4j
  31 +public class JFCTest {
  32 + private static final String TEMPLATE_PATH = "D:/data/jfreetest/report.docx";
  33 + private static final String OUTPUT_DIR = "D:/data/jfreetest/analysis/";
  34 + private static final String PIC_DIR = OUTPUT_DIR + "pic/";
  35 +
  36 + public static void main(String[] args) {
  37 + List<PieChartVo> dataList = new ArrayList<>();
  38 + PieChartVo d1 = new PieChartVo("类型1", 1.2);
  39 + PieChartVo d2 = new PieChartVo("类型2", 4.2);
  40 + PieChartVo d3 = new PieChartVo("类型3", -3.2);
  41 + PieChartVo d4 = new PieChartVo("类型4", 10.2);
  42 + PieChartVo d5 = new PieChartVo("类型5", 10.2);
  43 + PieChartVo d6 = new PieChartVo("类型6", -10.2);
  44 + PieChartVo d7 = new PieChartVo("类型7", 20.2);
  45 +
  46 + dataList.add(d1);
  47 + dataList.add(d2);
  48 + dataList.add(d3);
  49 + dataList.add(d4);
  50 + dataList.add(d5);
  51 + dataList.add(d6);
  52 + dataList.add(d7);
  53 + getWord(dataList);
  54 + }
  55 +
  56 +
  57 + public static void getWord(List<PieChartVo> dataList) {
  58 + try {
  59 + // 获取模板文件
  60 + File file = ResourceUtils.getFile(TEMPLATE_PATH);
  61 +
  62 + // 构建模板替换的数据
  63 + Map<String, Object> dataMap = buildTemplateData(dataList);
  64 + //表格
  65 + dataMap.put("table0", Tables.of(new String[][] {
  66 + new String[] { "00", "01" },
  67 + new String[] { "10", "11" }
  68 + }).border(BorderStyle.DEFAULT).create());
  69 +
  70 +
  71 + // 生成最终文件路径
  72 + String fileName = UUIDGenerator.uuid() + ".docx";
  73 + String filePath = OUTPUT_DIR + fileName;
  74 +
  75 + // 使用 POI-TL 渲染模板并保存
  76 + try (XWPFTemplate template = XWPFTemplate.compile(file, Configure.newBuilder().buildGramer("${", "}").build())
  77 + .render(dataMap)) {
  78 + template.writeToFile(filePath);
  79 + }
  80 + //上传文件返回附件id
  81 + } catch (Exception e) {
  82 + e.printStackTrace();
  83 + }
  84 + }
  85 +
  86 + private static Map<String, Object> buildTemplateData(List<PieChartVo> dataList) throws IOException {
  87 + Map<String, Object> dataMap = new HashMap<>();
  88 +
  89 + // 设置日期和在线总数
  90 + dataMap.put("date", LocalDate.now());
  91 + // 查询设备数据
  92 + dataMap.put("onlineTotal", 100);
  93 + // 生成每日在线图表
  94 + String dailyPicFile = JFChartUtils.createChart(dataList, JFChartTypeEnum.BAR, "监测站总在线数", "小时", "数量");
  95 + //图片插入就用Pictures类构建PictureBuilder,可查看Pictures其他方法,比如插入base64等
  96 + dataMap.put("dailyOnlinePic", Pictures.ofStream(new FileInputStream(dailyPicFile), PictureType.JPEG).size(600, 200).create());
  97 + return dataMap;
  98 + }
  99 +
  100 +
  101 +}
... ...
  1 +package com.ash.util;
  2 +
  3 +import com.ash.base.PieChartVo;
  4 +import com.ash.enums.JFChartTypeEnum;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.jfree.chart.*;
  7 +import org.jfree.chart.axis.AxisLocation;
  8 +import org.jfree.chart.axis.CategoryAxis;
  9 +import org.jfree.chart.axis.NumberAxis;
  10 +import org.jfree.chart.labels.StandardCategoryItemLabelGenerator;
  11 +import org.jfree.chart.labels.StandardPieSectionLabelGenerator;
  12 +import org.jfree.chart.plot.CategoryPlot;
  13 +import org.jfree.chart.plot.PiePlot;
  14 +import org.jfree.chart.renderer.category.BarRenderer;
  15 +import org.jfree.chart.renderer.category.CategoryItemRenderer;
  16 +import org.jfree.chart.renderer.category.StandardBarPainter;
  17 +import org.jfree.data.category.DefaultCategoryDataset;
  18 +import org.jfree.data.general.DefaultPieDataset;
  19 +import org.springframework.stereotype.Component;
  20 +
  21 +import java.awt.*;
  22 +import java.io.File;
  23 +import java.io.IOException;
  24 +import java.text.DecimalFormat;
  25 +import java.util.ArrayList;
  26 +import java.util.List;
  27 +
  28 +@Slf4j
  29 +@Component
  30 +public class JFChartUtils {
  31 +
  32 + public static final String OUTPUT_DIR = "D:/data/jfreetest/analysis/";
  33 + private static final String PIC_DIR = OUTPUT_DIR + "pic/";
  34 +
  35 + public static List<Color> colorList = new ArrayList<>();
  36 +
  37 + static {
  38 + Color c1 = new Color(65, 105, 225);
  39 + Color c2 = new Color(0, 191, 255);
  40 + Color c3 = new Color(135, 206, 250);
  41 + Color c4 = new Color(192, 192, 192);
  42 + Color c5 = new Color(144, 238, 144);
  43 + Color c6 = new Color(147, 112, 219);
  44 + colorList.add(c1);
  45 + colorList.add(c2);
  46 + colorList.add(c3);
  47 + colorList.add(c4);
  48 + colorList.add(c5);
  49 + colorList.add(c6);
  50 + }
  51 +
  52 + // 设置折现图表样式
  53 + private static void setLineChartStyle(JFreeChart chart) {
  54 + CategoryPlot plot = chart.getCategoryPlot();
  55 + chart.setBackgroundPaint(Color.WHITE);
  56 + plot.setBackgroundPaint(Color.WHITE);
  57 + plot.setDomainGridlinePaint(Color.LIGHT_GRAY);
  58 + plot.setRangeGridlinePaint(Color.LIGHT_GRAY);
  59 + // 设置第一条折线的粗细
  60 + plot.getRenderer().setSeriesStroke(0, new BasicStroke(3.0f));
  61 + // 根据样式设置折线颜色
  62 + plot.getRenderer().setSeriesPaint(0, colorList.get(0));
  63 + plot.setNoDataMessage("暂无数据");
  64 +
  65 + }
  66 +
  67 + // 设置柱形图表样式
  68 + private static void setBarChartStyle(JFreeChart chart) {
  69 +
  70 + CategoryPlot categoryplot = (CategoryPlot) chart.getPlot(); //获取图表对象
  71 + categoryplot.setBackgroundPaint(ChartColor.WHITE); //设置图表的背景颜色
  72 + categoryplot.setOutlinePaint(ChartColor.BLACK); //图表边框颜色
  73 + categoryplot.setDomainAxisLocation(AxisLocation.BOTTOM_OR_LEFT); //设置xy轴的位置
  74 + categoryplot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);
  75 + categoryplot.setNoDataMessage("暂无数据");
  76 +
  77 + BarRenderer customBarRenderer = (BarRenderer) categoryplot.getRenderer();
  78 + //取消柱子上的渐变色
  79 + customBarRenderer.setBarPainter(new StandardBarPainter());
  80 + //设置阴影,false代表没有阴影
  81 + customBarRenderer.setShadowVisible(false);
  82 + //设置柱子宽度,如果宽度设置的太小,会导致文字不在柱子的中间。
  83 + customBarRenderer.setMaximumBarWidth(30);
  84 + customBarRenderer.setMinimumBarLength(0.8);
  85 + customBarRenderer.setItemMargin(-1.2); //设置柱子间距
  86 + customBarRenderer.setSeriesPaint(0, colorList.get(0));
  87 + customBarRenderer.setDrawBarOutline(false);
  88 + customBarRenderer.setIncludeBaseInRange(true);
  89 +
  90 + CategoryItemRenderer renderer = categoryplot.getRenderer();
  91 + renderer.setDefaultItemLabelGenerator(new StandardCategoryItemLabelGenerator());
  92 + renderer.setDefaultItemLabelsVisible(true);
  93 +
  94 +
  95 + //数据轴设置
  96 + NumberAxis numberaxis = (NumberAxis) categoryplot.getRangeAxis();
  97 + numberaxis.setUpperMargin(0.1);//设置最高的一个柱与图片顶端的距离(最高柱的10%)
  98 + numberaxis.setLowerMargin(0.1);
  99 + numberaxis.setTickLabelFont(new Font("宋体", Font.BOLD, 12));
  100 + numberaxis.setLabelFont(new Font("宋体", Font.BOLD, 12));
  101 +
  102 + //项目轴设置
  103 + CategoryAxis domainAxis = categoryplot.getDomainAxis();
  104 + domainAxis.setTickLabelFont(new Font("宋体", Font.BOLD, 15));
  105 +
  106 + }
  107 +
  108 + // 设置饼图表样式
  109 + private static void setPieChartStyle(JFreeChart chart, DefaultPieDataset pieData) {
  110 +
  111 + PiePlot plot = (PiePlot) chart.getPlot();
  112 + chart.setBackgroundPaint(Color.WHITE);
  113 + plot.setBackgroundPaint(Color.WHITE);
  114 + // 设置标签字体
  115 + plot.setLabelFont(new Font("宋体", Font.PLAIN, 14));
  116 + // 设置无数据信息字体(如果需要)
  117 + plot.setNoDataMessageFont(new Font("宋体", Font.PLAIN, 18));
  118 + plot.setNoDataMessage("暂无数据");
  119 + plot.setLabelGenerator(new StandardPieSectionLabelGenerator(
  120 + "{2}",
  121 + new DecimalFormat("#,##0"), // 数值格式(带千分位)
  122 + new DecimalFormat("0.0%") // 百分比格式
  123 + ));
  124 + for (int i = 0; i < pieData.getItemCount() && i < colorList.size(); i++) {
  125 + plot.setSectionPaint(pieData.getKey(i).toString(), colorList.get(i));
  126 + }
  127 +
  128 + }
  129 +
  130 +
  131 + private static DefaultCategoryDataset buildDailyDataset(List<PieChartVo> dataList) {
  132 + DefaultCategoryDataset dataset = new DefaultCategoryDataset();
  133 + dataList.forEach(t -> dataset.addValue(ObjectValueOption.getObjDouble(t.getValue()), "", t.getName()));
  134 + return dataset;
  135 + }
  136 +
  137 +
  138 + private static DefaultPieDataset buildPieDataset(List<PieChartVo> dataList) {
  139 + DefaultPieDataset dataset = new DefaultPieDataset();
  140 + dataList.forEach(t -> dataset.setValue(t.getName(), ObjectValueOption.getObjDouble(t.getValue())));
  141 + return dataset;
  142 + }
  143 +
  144 +
  145 + // 生成图表并保存为图片
  146 + public static String createChart(List<PieChartVo> dataList, JFChartTypeEnum type, String title, String xAxisLabel, String yAxisLabel) throws IOException {
  147 + // 设置全局字体(支持中文)
  148 + StandardChartTheme chartTheme = new StandardChartTheme("CN");
  149 + chartTheme.setExtraLargeFont(new Font("宋体", Font.PLAIN, 14)); // 标题字体
  150 + chartTheme.setLargeFont(new Font("宋体", Font.PLAIN, 14)); // 图例字体
  151 + chartTheme.setRegularFont(new Font("宋体", Font.PLAIN, 12)); // 轴标签字体
  152 + ChartFactory.setChartTheme(chartTheme);
  153 + JFreeChart chart = null;
  154 + switch (type) {
  155 + case LINE:
  156 + DefaultCategoryDataset dataset = buildDailyDataset(dataList);
  157 + chart = ChartFactory.createLineChart(title, xAxisLabel, yAxisLabel, dataset);
  158 + setLineChartStyle(chart);
  159 + break;
  160 + case PIE:
  161 + DefaultPieDataset pieData = buildPieDataset(dataList);
  162 + chart = ChartFactory.createPieChart(title, pieData, true, true, false);
  163 + setPieChartStyle(chart, pieData);
  164 + break;
  165 + case BAR:
  166 + DefaultCategoryDataset batData = buildDailyDataset(dataList);
  167 + chart = ChartFactory.createBarChart(title, xAxisLabel, yAxisLabel, batData);
  168 + setBarChartStyle(chart);
  169 + break;
  170 + }
  171 +
  172 +
  173 + // 保存图表为图片
  174 + String picFile = PIC_DIR + UUIDGenerator.uuid() + ".png";
  175 + File file = new File(picFile);
  176 + if (!file.getParentFile().exists()) {
  177 + if (!file.getParentFile().mkdirs()) {
  178 + log.error("目录创建失败!" + file.getParentFile().getAbsolutePath());
  179 + }
  180 + }
  181 + //int numberOfCategories = dataset.getColumnCount();
  182 + //int width = Math.max(800, numberOfCategories * 50); // 每个类别宽度为50,最小宽度为800
  183 + ChartUtils.saveChartAsPNG(file, chart, 1200, 400);
  184 + return picFile;
  185 + }
  186 +
  187 +
  188 +}
... ...
... ... @@ -17,4 +17,12 @@ public class ObjectValueOption {
17 17 return Integer.parseInt(ojb.toString());
18 18
19 19 }
  20 +
  21 + public static Double getObjDouble(Object ojb) {
  22 + if (ojb == null) {
  23 + return 0D;
  24 + }
  25 + return Double.parseDouble(ojb.toString());
  26 +
  27 + }
20 28 }
... ...
  1 +package com.ash.util;
  2 +
  3 +import lombok.Data;
  4 +
  5 +/**
  6 + * 报表导出警情损列表vo
  7 + */
  8 +@Data
  9 +public class WiLossVo {
  10 + /**
  11 + * 案件编号
  12 + */
  13 + private String code;
  14 +
  15 + /**
  16 + * 地区
  17 + */
  18 + private String area;
  19 +
  20 + /**
  21 + * 县区
  22 + */
  23 + private String county;
  24 +
  25 + /**
  26 + * 接警警情子类
  27 + */
  28 + private String alarmSubType;
  29 +
  30 + /**
  31 + * 案损
  32 + */
  33 + private String amount;
  34 +
  35 + /**
  36 + * 引流方式
  37 + */
  38 + private String rainageMethod;
  39 +
  40 + /**
  41 + * 支付方式
  42 + */
  43 + private String payMethod;
  44 +
  45 + /**
  46 + * 受害人性别
  47 + */
  48 + private String sex;
  49 +
  50 + /**
  51 + * 受害人职业
  52 + */
  53 + private String career;
  54 +
  55 +}
... ...