Showing
17 changed files
with
1255 additions
and
17 deletions
1 | 1 | FROM openjdk:8-jdk-alpine |
2 | 2 | |
3 | +# ========== 新增时区配置 ========== [2,4](@ref) | |
4 | +# 1. 安装时区工具包 | |
5 | +RUN apk update && apk add --no-cache tzdata | |
6 | +# 2. 设置上海时区 | |
7 | +ENV TZ=Asia/Shanghai | |
8 | +# 3. 创建时区软链接并写入时区文件 | |
9 | +RUN ln -sf /usr/share/zoneinfo/$TZ /etc/localtime && \ | |
10 | + echo $TZ > /etc/timezone | |
11 | +# ================================ | |
12 | + | |
3 | 13 | #WORKDIR /app |
4 | 14 | |
5 | 15 | COPY target/antiSpoofingHelper-1.0-SNAPSHOT.jar /ash.jar | ... | ... |
... | ... | @@ -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 | } | ... | ... |
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")); | ... | ... |
src/main/java/com/ash/util/CaseLossVo.java
0 → 100644
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 | +} | ... | ... |
src/main/java/com/ash/util/JFCTest.java
0 → 100644
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 | +} | ... | ... |
src/main/java/com/ash/util/JFChartUtils.java
0 → 100644
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 | } | ... | ... |
src/main/java/com/ash/util/WiLossVo.java
0 → 100644
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 | +} | ... | ... |
... | ... | @@ -9,10 +9,10 @@ spring: |
9 | 9 | profiles: |
10 | 10 | active: default |
11 | 11 | datasource: |
12 | - url: jdbc:mysql://10.9.1.252:3306/ash?useSSL=false&autoReconnect=true&characterEncoding=utf8 | |
12 | + url: jdbc:mysql://53.1.236.89:3306/ash?useSSL=false&autoReconnect=true&characterEncoding=utf8 | |
13 | 13 | driver-class-name: com.mysql.cj.jdbc.Driver |
14 | - username: qixiao | |
15 | - password: qixiao123!@# | |
14 | + username: root | |
15 | + password: zaq1,lp- | |
16 | 16 | type: com.alibaba.druid.pool.DruidDataSource |
17 | 17 | druid: |
18 | 18 | initial-size: 5 |
... | ... | @@ -26,9 +26,11 @@ spring: |
26 | 26 | test-on-return: true |
27 | 27 | test-while-idle: true |
28 | 28 | redis: |
29 | - cluster: | |
30 | - nodes: 10.9.1.252:16380 | |
31 | - password: qixiao@123.com | |
29 | + # cluster: | |
30 | + # nodes: 10.9.1.252:16380 | |
31 | + password: zaq1,lp- | |
32 | + host: 53.1.236.89 | |
33 | + port: 36379 | |
32 | 34 | timeout: 3000 |
33 | 35 | servlet: |
34 | 36 | multipart: | ... | ... |
No preview for this file type