From ddaa44400aa478058ffe9349d59904a130b7ce9c Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期四, 28 八月 2025 17:33:11 +0800
Subject: [PATCH] 2025.8.28 1. 新增走航任务统计功能(待完成)

---
 src/main/kotlin/com/flightfeather/uav/biz/mission/MissionUtil.kt                         |    2 
 src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt          |    5 
 src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt |   28 ++
 src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt           |    8 
 src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceControllerTest.kt       |   51 ++--
 src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt                  |    3 
 src/main/kotlin/com/flightfeather/uav/common/file/Docx4jGenerator.kt                     |  228 +++++++++++-----------
 src/test/kotlin/com/flightfeather/uav/biz/report/MissionSummaryTest.kt                   |   55 +++++
 src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt                     |   33 +++
 src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt  |   88 +-------
 pom.xml                                                                                  |   49 ++--
 11 files changed, 312 insertions(+), 238 deletions(-)

diff --git a/pom.xml b/pom.xml
index 6b67ad9..a0c3395 100644
--- a/pom.xml
+++ b/pom.xml
@@ -267,30 +267,31 @@
             <artifactId>commons-lang3</artifactId>
             <version>3.17.0</version>
         </dependency>
-        <dependency>
-            <groupId>org.docx4j</groupId>
-            <artifactId>docx4j-core</artifactId>
-            <version>11.4.9</version> <!-- 浣跨敤鏈�鏂扮ǔ瀹氱増 -->
-        </dependency>
-        <!-- 濡傞渶澶勭悊鍥剧墖/琛ㄦ牸绛夐珮绾у姛鑳斤紝鍙坊鍔� -->
-        <dependency>
-            <groupId>org.docx4j</groupId>
-            <artifactId>docx4j-ImportXHTML</artifactId>
-            <version>11.4.8</version>
-        </dependency>
-        <!-- MockK 鍗曞厓娴嬭瘯搴擄紙鐢ㄤ簬 Kotlin锛� -->
-        <dependency>
-            <groupId>io.mockk</groupId>
-            <artifactId>mockk</artifactId>
-            <version>1.14.5</version> <!-- 浣跨敤鏈�鏂扮ǔ瀹氱増 -->
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.junit.jupiter</groupId>
-            <artifactId>junit-jupiter</artifactId>
-            <version>RELEASE</version>
-            <scope>test</scope>
-        </dependency>
+<!--        <dependency>-->
+<!--            <groupId>org.docx4j</groupId>-->
+<!--            <artifactId>docx4j-core</artifactId>-->
+<!--            <version>11.4.9</version> &lt;!&ndash; 浣跨敤鏈�鏂扮ǔ瀹氱増 &ndash;&gt;-->
+<!--        </dependency>-->
+<!--        &lt;!&ndash; 濡傞渶澶勭悊鍥剧墖/琛ㄦ牸绛夐珮绾у姛鑳斤紝鍙坊鍔� &ndash;&gt;-->
+<!--        <dependency>-->
+<!--            <groupId>org.docx4j</groupId>-->
+<!--            <artifactId>docx4j-ImportXHTML</artifactId>-->
+<!--            <version>11.4.8</version>-->
+<!--        </dependency>-->
+<!--        &lt;!&ndash; MockK 鍗曞厓娴嬭瘯搴擄紙鐢ㄤ簬 Kotlin锛� &ndash;&gt;-->
+<!--        <dependency>-->
+<!--            <groupId>io.mockk</groupId>-->
+<!--            <artifactId>mockk</artifactId>-->
+<!--            <version>1.14.5</version> &lt;!&ndash; 浣跨敤鏈�鏂扮ǔ瀹氱増 &ndash;&gt;-->
+<!--            <scope>test</scope>-->
+<!--        </dependency>-->
+<!--        <dependency>-->
+<!--            <groupId>org.junit.jupiter</groupId>-->
+<!--            <artifactId>junit-jupiter</artifactId>-->
+<!--            <version>RELEASE</version>-->
+<!--            <scope>test</scope>-->
+<!--        </dependency>-->
+
 
 
     </dependencies>
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/mission/MissionUtil.kt b/src/main/kotlin/com/flightfeather/uav/biz/mission/MissionUtil.kt
index 1edaf99..be6523c 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/mission/MissionUtil.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/mission/MissionUtil.kt
@@ -54,6 +54,6 @@
         // 灏哤GS84鍧愭爣杞崲涓篏CJ02鍧愭爣鍚庤繘琛岄�嗗湴鐞嗙紪鐮佽幏鍙栧湴鍧�淇℃伅
         val address = AMapService.reGeo(MapUtil.wgs84ToGcj02(pair as Pair<Double, Double>))
         // 杩斿洖涔¢晣鍜岃閬撳悕绉扮粍鍚�
-        return address.township + address.street
+        return address.township
     }
 }
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt
index fe910c4..26a597a 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/report/MissionInventory.kt
@@ -1,9 +1,11 @@
 package com.flightfeather.uav.biz.report
 
+import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue
 import com.flightfeather.uav.domain.entity.Mission
 import com.flightfeather.uav.domain.entity.SceneInfo
 import com.flightfeather.uav.lightshare.bean.FactorStatistics
 import com.flightfeather.uav.socket.eunm.FactorType
+import com.flightfeather.uav.socket.sender.MsgType
 
 /**
  * 璧拌埅婧簮娓呭崟
@@ -29,6 +31,37 @@
     class MissionDetail : Mission() {
         var keyScene: List<SceneInfo>? = null
         var dataStatistics: List<FactorStatistics>? = null
+    }
 
+    /**
+     * 杈撳嚭璧拌埅娓呭崟
+     */
+    fun missionList(missionClues: List<Pair<Mission?, List<PollutedClue?>>>): List<MissionInfo> {
+
+        val missionMap = mutableMapOf<String, MissionInfo>()
+        missionClues.forEach { (mission, clue) ->
+            mission ?: return@forEach
+            clue ?: return@forEach
+            val missionInfo = missionMap[mission.missionCode] ?: MissionInfo().apply {
+                missionMap[mission.missionCode] = this
+            }
+            val abnormalFactors = mutableListOf<FactorType>()
+            var sceneCount = 0
+            clue.forEach {
+                if (it?.msgType == MsgType.PolClue.value) {
+                    it.pollutedData?.statisticMap?.keys?.forEach { k->
+                        if (!abnormalFactors.contains(k)) {
+                            abnormalFactors.add(k)
+                        }
+                    }
+                }
+            }
+            // 璁$畻姣忎釜璧拌埅浠诲姟鐨勬墍鏈夊紓甯稿洜瀛�
+
+            // 璁$畻姣忎釜璧拌埅浠诲姟鐨勯瑕佹薄鏌撶墿
+
+            // 璁$畻姣忎釜璧拌埅浠诲姟鐨勬函婧愬満鏅暟閲�
+        }
+        return mutableListOf()
     }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt
index d2b696f..eb0f7eb 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceController.kt
@@ -45,14 +45,16 @@
                     .withMain(FactorType.CO)
 //                    .withMain(FactorType.H2S)
 //                    .withMain(FactorType.SO2)
-                    .withMain(FactorType.O3)
+//                    .withMain(FactorType.O3)
                     .withMain(FactorType.PM25)
                     .withMain(FactorType.PM10)
-                    .withMain(FactorType.VOC)
+//                    .withMain(FactorType.VOC)
+                    .withMain(FactorType.NO)
                     .withCombination(
                         listOf(
                             listOf(FactorType.PM25, FactorType.PM10),
-                            listOf(FactorType.VOC, FactorType.CO),
+//                            listOf(FactorType.VOC, FactorType.CO),
+                            listOf(FactorType.NO, FactorType.NO2),
                         )
                     )
                     .create()
diff --git a/src/main/kotlin/com/flightfeather/uav/common/file/Docx4jGenerator.kt b/src/main/kotlin/com/flightfeather/uav/common/file/Docx4jGenerator.kt
index d33e105..8b14f83 100644
--- a/src/main/kotlin/com/flightfeather/uav/common/file/Docx4jGenerator.kt
+++ b/src/main/kotlin/com/flightfeather/uav/common/file/Docx4jGenerator.kt
@@ -1,114 +1,114 @@
-package com.flightfeather.uav.common.file
-
-import freemarker.template.Configuration
-import freemarker.template.Template
-
-import org.docx4j.openpackaging.packages.WordprocessingMLPackage
-import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart
-import java.io.ByteArrayInputStream
-import java.io.ByteArrayOutputStream
-import java.io.File
-import java.io.OutputStreamWriter
-import java.nio.charset.StandardCharsets
-
-/**
- * Word鏂囦欢鐢熸垚鍣紙鍩轰簬Docx4j + FreeMarker锛�
- * @date 2025/8/28 09:29
- * @author feiyu
- */
-class Docx4jGenerator(
-    private val templatePath: String,
-    private val freemarkerConfig: Configuration = defaultFreemarkerConfig()
-) {
-    private var wordMLPackage: WordprocessingMLPackage? = null
-    private var mainDocumentPart: MainDocumentPart? = null
-
-    /**
-     * 鍒涘缓Word鏂囨。鍖�
-     */
-    fun loadTemplate(): Docx4jGenerator {
-        wordMLPackage = WordprocessingMLPackage.createPackage()
-        mainDocumentPart = wordMLPackage?.mainDocumentPart
-
-        return this
-    }
-
-    /**
-     * 浣跨敤FreeMarker濉厖妯℃澘鏁版嵁
-     */
-    fun fillData(dataModel: Map<String, Any>): Docx4jGenerator {
-        val template = freemarkerConfig.getTemplate(templatePath.substringAfterLast("/"))
-        val xmlContent = renderTemplate(template, dataModel)
-
-        mainDocumentPart?.unmarshal(ByteArrayInputStream(xmlContent.toByteArray(StandardCharsets.UTF_8)))
-        return this
-    }
-
-    /**
-     * 娣诲姞鍥剧墖鍒癢ord鏂囨。
-     * @param imagePath 鍥剧墖璺緞
-     * @param width 瀹藉害(鍍忕礌)
-     * @param height 楂樺害(鍍忕礌)
-     * @param paragraphId 娈佃惤ID锛屾寚瀹氬浘鐗囨彃鍏ヤ綅缃�
-     */
-    fun addImage(imagePath: String, width: Int, height: Int, paragraphId: String): Docx4jGenerator {
-        // 瀹炵幇鍥剧墖娣诲姞閫昏緫
-        return this
-    }
-
-    /**
-     * 娣诲姞琛ㄦ牸鍒癢ord鏂囨。
-     * @param data 琛ㄦ牸鏁版嵁
-     * @param paragraphId 娈佃惤ID锛屾寚瀹氳〃鏍兼彃鍏ヤ綅缃�
-     */
-    fun addTable(data: List<List<String>>, paragraphId: String): Docx4jGenerator {
-        // 瀹炵幇琛ㄦ牸娣诲姞閫昏緫
-        return this
-    }
-
-    /**
-     * 淇濆瓨鐢熸垚鐨刉ord鏂囦欢
-     * @param outputPath 杈撳嚭鏂囦欢璺緞
-     */
-    fun save(outputPath: String) {
-        wordMLPackage?.save(File(outputPath))
-    }
-
-    /**
-     * 浣跨敤FreeMarker娓叉煋妯℃澘
-     */
-    private fun renderTemplate(template: Template, dataModel: Map<String, Any>): String {
-        val outputStream = ByteArrayOutputStream()
-        val writer = OutputStreamWriter(outputStream, StandardCharsets.UTF_8)
-        template.process(dataModel, writer)
-        writer.flush()
-        return outputStream.toString(StandardCharsets.UTF_8.name())
-    }
-
-    companion object {
-        /**
-         * 榛樿FreeMarker閰嶇疆
-         */
-        fun defaultFreemarkerConfig(): Configuration {
-            val config = Configuration(Configuration.VERSION_2_3_31)
-            config.defaultEncoding = "UTF-8"
-            config.setClassForTemplateLoading(Docx4jGenerator::class.java, "/templates")
-            return config
-        }
-
-        /**
-         * 绠�鍖栬皟鐢ㄧ殑闈欐�佹柟娉�
-         */
-        fun generate(
-            templatePath: String,
-            outputPath: String,
-            dataModel: Map<String, Any>,
-            config: Configuration = defaultFreemarkerConfig()
-        ) {
-            Docx4jGenerator(templatePath, config)
-                .loadTemplate()
-                .fillData(dataModel)
-                .save(outputPath)
-        }
-    }
-}
\ No newline at end of file
+//package com.flightfeather.uav.common.file
+//
+//import freemarker.template.Configuration
+//import freemarker.template.Template
+//
+//import org.docx4j.openpackaging.packages.WordprocessingMLPackage
+//import org.docx4j.openpackaging.parts.WordprocessingML.MainDocumentPart
+//import java.io.ByteArrayInputStream
+//import java.io.ByteArrayOutputStream
+//import java.io.File
+//import java.io.OutputStreamWriter
+//import java.nio.charset.StandardCharsets
+//
+///**
+// * Word鏂囦欢鐢熸垚鍣紙鍩轰簬Docx4j + FreeMarker锛�
+// * @date 2025/8/28 09:29
+// * @author feiyu
+// */
+//class Docx4jGenerator(
+//    private val templatePath: String,
+//    private val freemarkerConfig: Configuration = defaultFreemarkerConfig()
+//) {
+//    private var wordMLPackage: WordprocessingMLPackage? = null
+//    private var mainDocumentPart: MainDocumentPart? = null
+//
+//    /**
+//     * 鍒涘缓Word鏂囨。鍖�
+//     */
+//    fun loadTemplate(): Docx4jGenerator {
+//        wordMLPackage = WordprocessingMLPackage.createPackage()
+//        mainDocumentPart = wordMLPackage?.mainDocumentPart
+//
+//        return this
+//    }
+//
+//    /**
+//     * 浣跨敤FreeMarker濉厖妯℃澘鏁版嵁
+//     */
+//    fun fillData(dataModel: Map<String, Any>): Docx4jGenerator {
+//        val template = freemarkerConfig.getTemplate(templatePath.substringAfterLast("/"))
+//        val xmlContent = renderTemplate(template, dataModel)
+//
+//        mainDocumentPart?.unmarshal(ByteArrayInputStream(xmlContent.toByteArray(StandardCharsets.UTF_8)))
+//        return this
+//    }
+//
+//    /**
+//     * 娣诲姞鍥剧墖鍒癢ord鏂囨。
+//     * @param imagePath 鍥剧墖璺緞
+//     * @param width 瀹藉害(鍍忕礌)
+//     * @param height 楂樺害(鍍忕礌)
+//     * @param paragraphId 娈佃惤ID锛屾寚瀹氬浘鐗囨彃鍏ヤ綅缃�
+//     */
+//    fun addImage(imagePath: String, width: Int, height: Int, paragraphId: String): Docx4jGenerator {
+//        // 瀹炵幇鍥剧墖娣诲姞閫昏緫
+//        return this
+//    }
+//
+//    /**
+//     * 娣诲姞琛ㄦ牸鍒癢ord鏂囨。
+//     * @param data 琛ㄦ牸鏁版嵁
+//     * @param paragraphId 娈佃惤ID锛屾寚瀹氳〃鏍兼彃鍏ヤ綅缃�
+//     */
+//    fun addTable(data: List<List<String>>, paragraphId: String): Docx4jGenerator {
+//        // 瀹炵幇琛ㄦ牸娣诲姞閫昏緫
+//        return this
+//    }
+//
+//    /**
+//     * 淇濆瓨鐢熸垚鐨刉ord鏂囦欢
+//     * @param outputPath 杈撳嚭鏂囦欢璺緞
+//     */
+//    fun save(outputPath: String) {
+//        wordMLPackage?.save(File(outputPath))
+//    }
+//
+//    /**
+//     * 浣跨敤FreeMarker娓叉煋妯℃澘
+//     */
+//    private fun renderTemplate(template: Template, dataModel: Map<String, Any>): String {
+//        val outputStream = ByteArrayOutputStream()
+//        val writer = OutputStreamWriter(outputStream, StandardCharsets.UTF_8)
+//        template.process(dataModel, writer)
+//        writer.flush()
+//        return outputStream.toString(StandardCharsets.UTF_8.name())
+//    }
+//
+//    companion object {
+//        /**
+//         * 榛樿FreeMarker閰嶇疆
+//         */
+//        fun defaultFreemarkerConfig(): Configuration {
+//            val config = Configuration(Configuration.VERSION_2_3_31)
+//            config.defaultEncoding = "UTF-8"
+//            config.setClassForTemplateLoading(Docx4jGenerator::class.java, "/templates")
+//            return config
+//        }
+//
+//        /**
+//         * 绠�鍖栬皟鐢ㄧ殑闈欐�佹柟娉�
+//         */
+//        fun generate(
+//            templatePath: String,
+//            outputPath: String,
+//            dataModel: Map<String, Any>,
+//            config: Configuration = defaultFreemarkerConfig()
+//        ) {
+//            Docx4jGenerator(templatePath, config)
+//                .loadTemplate()
+//                .fillData(dataModel)
+//                .save(outputPath)
+//        }
+//    }
+//}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt b/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt
index dccef45..f33ac6f 100644
--- a/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt
+++ b/src/main/kotlin/com/flightfeather/uav/domain/entity/BaseRealTimeData.kt
@@ -147,6 +147,9 @@
 }
 
 fun List<BaseRealTimeData>.avg(): BaseRealTimeData {
+    if (isEmpty()) {
+        return BaseRealTimeData()
+    }
     //椋庡悜閲囩敤鍗曚綅鐭㈤噺娉曟眰鍙栧潎鍊�
     var u = .0//涓滆タ鏂逛綅鍒嗛噺鎬诲拰
     var v = .0//鍗楀寳鏂逛綅鍒嗛噺鎬诲拰
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt
index b84e115..61683df 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/DataAnalysisService.kt
@@ -2,7 +2,10 @@
 
 import com.flightfeather.uav.biz.dataanalysis.BaseExceptionResult
 import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult
+import com.flightfeather.uav.biz.report.MissionSummary
 import com.flightfeather.uav.biz.sourcetrace.model.BasePollutedMsg
+import com.flightfeather.uav.lightshare.bean.AreaVo
+import java.util.*
 
 /**
  *
@@ -18,4 +21,6 @@
     fun pollutionTrace(missionCode: String): List<ExceptionResult>
 
     fun fetchHistory(missionCode: String): String
+
+    fun missionSummary(startTime: Date, endTime: Date, areaVo: AreaVo): MissionSummary.Summary
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt
index f8ad2c7..3982b5c 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/DataAnalysisServiceImpl.kt
@@ -4,17 +4,26 @@
 import com.flightfeather.uav.biz.dataanalysis.BaseExceptionResult
 import com.flightfeather.uav.biz.dataanalysis.ExceptionAnalysisController
 import com.flightfeather.uav.biz.dataanalysis.model.ExceptionResult
+import com.flightfeather.uav.biz.report.MissionSummary
 import com.flightfeather.uav.biz.sourcetrace.model.BasePollutedMsg
+import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue
 import com.flightfeather.uav.common.exception.BizException
 import com.flightfeather.uav.common.location.LocationRoadNearby
 import com.flightfeather.uav.common.utils.GsonUtils
+import com.flightfeather.uav.domain.entity.Mission
+import com.flightfeather.uav.domain.mapper.MissionMapper
 import com.flightfeather.uav.domain.repository.MissionRep
 import com.flightfeather.uav.domain.repository.RealTimeDataRep
 import com.flightfeather.uav.domain.repository.SegmentInfoRep
 import com.flightfeather.uav.domain.repository.SourceTraceRep
+import com.flightfeather.uav.lightshare.bean.AreaVo
 import com.flightfeather.uav.lightshare.service.DataAnalysisService
 import com.flightfeather.uav.socket.eunm.FactorType
 import org.springframework.stereotype.Service
+import tk.mybatis.mapper.entity.Example
+import java.time.LocalDateTime
+import java.time.ZoneId
+import java.util.*
 
 /**
  *
@@ -24,6 +33,7 @@
 @Service
 class DataAnalysisServiceImpl(
     private val missionRep: MissionRep,
+    private val missionMapper: MissionMapper,
     private val realTimeDataRep: RealTimeDataRep,
     private val locationRoadNearby: LocationRoadNearby,
     private val segmentInfoRep: SegmentInfoRep,
@@ -56,4 +66,22 @@
         val res = sourceTraceRep.fetchList(mission.deviceCode, mission.startTime, mission.endTime)
         return GsonUtils.gson.toJson(res)
     }
+
+    override fun missionSummary(startTime: Date, endTime: Date, areaVo: AreaVo): MissionSummary.Summary {
+        val clues = mutableListOf<PollutedClue?>()
+        val missions = missionMapper.selectByExample(Example(Mission::class.java).apply {
+            createCriteria().andBetween("startTime", startTime, endTime)
+                .andEqualTo("provinceCode", areaVo.provinceCode)
+                .andEqualTo("cityCode", areaVo.cityCode)
+                .andEqualTo("districtCode", areaVo.districtCode)
+                .andIsNotNull("kilometres")
+                .andNotEqualTo("kilometres", 0)
+        }).onEach {
+            it ?: return@onEach
+            val clue = sourceTraceRep.fetchList(it.deviceCode, it.startTime, it.endTime).filterIsInstance<PollutedClue?>()
+            clues.addAll(clue)
+        }
+        val summary = MissionSummary().execute(startTime, endTime, missions, clues)
+        return summary
+    }
 }
\ No newline at end of file
diff --git a/src/test/kotlin/com/flightfeather/uav/biz/report/MissionSummaryTest.kt b/src/test/kotlin/com/flightfeather/uav/biz/report/MissionSummaryTest.kt
new file mode 100644
index 0000000..398bd1e
--- /dev/null
+++ b/src/test/kotlin/com/flightfeather/uav/biz/report/MissionSummaryTest.kt
@@ -0,0 +1,55 @@
+package com.flightfeather.uav.biz.report
+
+import com.flightfeather.uav.biz.sourcetrace.model.PollutedClue
+import com.flightfeather.uav.domain.entity.Mission
+import com.flightfeather.uav.domain.mapper.MissionMapper
+import com.flightfeather.uav.domain.repository.SourceTraceRep
+import com.flightfeather.uav.lightshare.bean.AreaVo
+import com.flightfeather.uav.lightshare.service.DataAnalysisService
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.junit4.SpringRunner
+import tk.mybatis.mapper.entity.Example
+import java.time.LocalDateTime
+import java.time.ZoneId
+import java.time.ZoneOffset
+import java.util.Date
+
+@RunWith(SpringRunner::class)
+@SpringBootTest
+class MissionSummaryTest {
+
+    private val missionSummary: MissionSummary = MissionSummary()
+
+    @Autowired
+    lateinit var missionMapper: MissionMapper
+
+    @Autowired
+    lateinit var sourceTraceRep: SourceTraceRep
+
+    @Autowired
+    lateinit var dataAnalysisService: DataAnalysisService
+
+    @Test
+    fun testMissionSummary() {
+        val startTime = Date.from(LocalDateTime.of(2025,7,1,0,0,0).atZone(ZoneId.systemDefault()).toInstant())
+        val endTime = Date.from(LocalDateTime.of(2025, 9, 30, 23, 59, 59).atZone(ZoneId.systemDefault()).toInstant())
+        val summary = dataAnalysisService.missionSummary(startTime, endTime, AreaVo().apply {
+            provinceCode = "31"
+            cityCode = "3100"
+            districtCode = "310106"
+        })
+
+//        val deviceCode = "TX105"
+//        val missions = missionMapper.selectByExample(Example(Mission::class.java).apply {
+//            createCriteria().andEqualTo("deviceCode", deviceCode)
+//                .andBetween("startTime", startTime, endTime)
+//        })
+//        val clues = sourceTraceRep.fetchList(deviceCode, startTime, endTime)
+//            .filterIsInstance<PollutedClue?>()
+//        val summary = missionSummary.execute(startTime, endTime, missions, clues)
+        println(summary)
+    }
+}
\ No newline at end of file
diff --git a/src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceControllerTest.kt b/src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceControllerTest.kt
index 5988849..c7ea7e8 100644
--- a/src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceControllerTest.kt
+++ b/src/test/kotlin/com/flightfeather/uav/biz/sourcetrace/SourceTraceControllerTest.kt
@@ -14,6 +14,8 @@
 import org.springframework.boot.test.context.SpringBootTest
 import org.springframework.test.context.junit4.SpringRunner
 import tk.mybatis.mapper.entity.Example
+import java.time.LocalDateTime
+import java.time.ZoneId
 
 @RunWith(SpringRunner::class)
 @SpringBootTest
@@ -37,30 +39,33 @@
     @Test
     fun autoSourceTrace() {
         val sourceTraceController = SourceTraceController(sceneInfoRep, sourceTraceRep, false)
-        val mCode = listOf(
-            "SH-CN-20241227", "SH-CN-20241127", "SH-CN-20240906", "SH-CN-20240830(05)",
-            "SH-CN-20240830(04)", "SH-CN-20240823",
-            "SH-CN-20240723(02)",
-//            "SH-CN-20250723(01)"
-        )
-        mCode.forEach { c->
-            missionRep.findOne(c)?.let {m ->
-                val rtData = realTimeDataService.getSecondData(
-                    m?.deviceType,
-                    m?.deviceCode,
-                    DateUtil.instance.dateToString(m?.startTime, DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS),
-                    DateUtil.instance.dateToString(m?.endTime, DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS),
-                    null,
-                    1,
-                    10000
-                )
-                rtData.data?.forEach { d ->
-                    val rtdVehicle = d.toBaseRealTimeData(RealTimeDataVehicle::class.java)
+//        val mCode = listOf(
+//            "SH-CN-20241227", "SH-CN-20241127", "SH-CN-20240906", "SH-CN-20240830(05)",
+//            "SH-CN-20240830(04)", "SH-CN-20240823",
+//            "SH-CN-20240723(02)",
+////            "SH-CN-20250723(01)"
+//        )
+        val startTime = LocalDateTime.of(2025, 7, 1, 0, 0, 0).atZone(ZoneId.systemDefault()).toInstant()
+        val endTime = LocalDateTime.of(2025, 9, 30, 23, 59, 59).atZone(ZoneId.systemDefault()).toInstant()
+        val missions = missionMapper.selectByExample(Example(Mission::class.java).apply {
+            createCriteria().andBetween("startTime", startTime, endTime)
+        })
+        missions.forEach { m ->
+            val rtData = realTimeDataService.getSecondData(
+                m?.deviceType,
+                m?.deviceCode,
+                DateUtil.instance.dateToString(m?.startTime, DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS),
+                DateUtil.instance.dateToString(m?.endTime, DateUtil.DateStyle.YYYY_MM_DD_HH_MM_SS),
+                null,
+                1,
+                10000
+            )
+            rtData.data?.forEach { d ->
+                val rtdVehicle = d.toBaseRealTimeData(RealTimeDataVehicle::class.java)
 //            Thread.sleep(500)
-                    sourceTraceController.addOneData(rtdVehicle)
-                }
-                sourceTraceController.initTask()
+                sourceTraceController.addOneData(rtdVehicle)
             }
+            sourceTraceController.initTask()
         }
 //        val missions = missionMapper.selectByExample(Example(Mission::class.java).apply {
 //            createCriteria().andEqualTo("deviceType", "0a")
@@ -109,7 +114,7 @@
             "SH-CN-20240723(02)",
 //            "SH-CN-20250723(01)"
         )
-        mCode.forEach {c ->
+        mCode.forEach { c ->
             missionRep.findOne(c)?.let {
                 sourceTraceRep.delete(it)
             }
diff --git a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt
index f21cc8c..3d3dba5 100644
--- a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt
+++ b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/MissionServiceImplTest.kt
@@ -2,30 +2,25 @@
 
 import com.flightfeather.uav.biz.FactorFilter
 import com.flightfeather.uav.biz.report.MissionReport
-import com.flightfeather.uav.common.exception.BizException
-import com.flightfeather.uav.domain.repository.MissionRep
+import com.flightfeather.uav.domain.entity.Mission
+import com.flightfeather.uav.domain.mapper.MissionMapper
 import com.flightfeather.uav.lightshare.service.MissionService
-
+import org.junit.Test
+import org.junit.runner.RunWith
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.boot.test.context.SpringBootTest
 import org.springframework.test.context.junit4.SpringRunner
-import javax.servlet.http.HttpServletResponse
+import tk.mybatis.mapper.entity.Example
 
-import org.junit.jupiter.api.Assertions.*
-import org.junit.jupiter.api.Test
-import org.junit.jupiter.api.assertThrows
-import org.junit.runner.RunWith
-
-import io.mockk.every
-import io.mockk.mockk
-import io.mockk.verify
-
+@RunWith(SpringRunner::class)
+@SpringBootTest
 class MissionServiceImplTest {
 
     @Autowired
     lateinit var missionService: MissionService
 
-    private var missionRep: MissionRep = mockk()
+    @Autowired
+    lateinit var missionMapper: MissionMapper
 
     @Autowired
     lateinit var missionReport: MissionReport
@@ -37,65 +32,12 @@
     }
 
     @Test
-    fun `calMissionInfo should throw BizException when mission not found`() {
-        // Arrange
-        val missionCode = "M001"
-        every { missionRep.findOne(missionCode) } returns null
-
-        // Act & Assert
-        val exception = assertThrows<BizException> {
-            missionService.calMissionInfo(missionCode)
+    fun calMissionInfo() {
+        missionMapper.selectByExample(Example(Mission::class.java).apply {
+            createCriteria().andGreaterThanOrEqualTo("startTime", "2025-08-08 08:30:00")
+        }).forEach {mission ->
+            mission?.let { missionService.calMissionInfo(it.missionCode) }
+            Thread.sleep(1000)
         }
-        assertEquals("璧拌埅浠诲姟涓嶅瓨鍦�", exception.message)
-    }
-
-    @Test
-    fun `calMissionInfo should calculate and update mission info successfully`() {
-        // Arrange
-        val missionCode = "M001"
-        val mission = Mission(missionCode)
-        val data = listOf<RealTimeData>()
-
-        every { missionRep.findOne(missionCode) } returns mission
-        every { realTimeDataRep.fetchData(mission) } returns data
-        every { missionUtil.calKilometres(data) } returns 100.0
-        every { missionUtil.calRegion(data) } returns "Center"
-        every { missionRep.updateMission(mission) } returns true
-
-        // Act
-        val result = missionService.calMissionInfo(missionCode)
-
-        // Assert
-        assertTrue(result)
-        assertEquals(100.0f, mission.kilometres)
-        assertEquals("Center", mission.region)
-
-        verify {
-            missionRep.findOne(missionCode)
-            realTimeDataRep.fetchData(mission)
-            missionUtil.calKilometres(data)
-            missionUtil.calRegion(data)
-            missionRep.updateMission(mission)
-        }
-    }
-
-    @Test
-    fun `calMissionInfo should return false when update fails`() {
-        // Arrange
-        val missionCode = "M001"
-        val mission = Mission(missionCode)
-        val data = listOf<RealTimeData>()
-
-        every { missionRep.findOne(missionCode) } returns mission
-        every { realTimeDataRep.fetchData(mission) } returns data
-        every { missionUtil.calKilometres(data) } returns 100.0
-        every { missionUtil.calRegion(data) } returns "Center"
-        every { missionRep.updateMission(mission) } returns false
-
-        // Act
-        val result = missionService.calMissionInfo(missionCode)
-
-        // Assert
-        assertFalse(result)
     }
 }
\ No newline at end of file

--
Gitblit v1.9.3