From 84569abda51ecf6c5549dec4cadee8d043422379 Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期二, 30 九月 2025 09:33:28 +0800
Subject: [PATCH] 2025.9.30

---
 src/test/kotlin/com/flightfeather/grid/web/ClueTaskControllerTest.kt             |   20 +
 src/main/kotlin/com/flightfeather/grid/config/CorsConfig.kt                      |    4 
 src/main/resources/mapper/ds1/ClueInternalMapper.xml                             |   81 +++++
 src/main/kotlin/com/flightfeather/grid/domain/ds1/mapper/ClueInternalMapper.kt   |   14 
 src/main/kotlin/com/flightfeather/grid/service/ClueTaskService.kt                |    9 
 src/main/resources/mapper/ds1/ClueTaskMapper.xml                                 |   67 ++++
 src/main/kotlin/com/flightfeather/grid/web/ClueQuestionController.kt             |    4 
 src/main/kotlin/com/flightfeather/grid/web/ClueTaskController.kt                 |   21 +
 src/main/kotlin/com/flightfeather/grid/vo/BaseResponse.kt                        |    5 
 src/test/kotlin/com/flightfeather/grid/external/ClueHttpServiceTest.kt           |    2 
 src/main/kotlin/com/flightfeather/grid/domain/ds1/mapper/ClueTaskMapper.kt       |    8 
 src/main/kotlin/com/flightfeather/grid/service/impl/ClueQuestionServiceImpl.kt   |   32 +
 src/main/kotlin/com/flightfeather/grid/vo/ClueTaskOptions.kt                     |   35 ++
 src/main/kotlin/com/flightfeather/grid/domain/ds1/entity/ClueTask.java           |   16 +
 src/main/kotlin/com/flightfeather/grid/service/impl/ClueTaskServiceImpl.kt       |   46 +++
 src/main/kotlin/com/flightfeather/grid/service/impl/ClueConclusionServiceImpl.kt |   31 +
 /dev/null                                                                        |    0 
 src/main/kotlin/com/flightfeather/grid/domain/ds1/entity/ClueInternal.java       |  381 +++++++++++++++++++++++++
 src/main/resources/generator/generatorConfig.xml                                 |   24 
 src/main/kotlin/com/flightfeather/grid/external/ClueHttpService.kt               |   14 
 src/main/kotlin/com/flightfeather/grid/vo/ClueTaskSummaryVo.kt                   |   31 ++
 src/main/kotlin/com/flightfeather/grid/service/ClueQuestionService.kt            |    2 
 src/main/kotlin/com/flightfeather/grid/web/BaseResPack.kt                        |    8 
 23 files changed, 805 insertions(+), 50 deletions(-)

diff --git a/gridServer.rar b/gridServer.rar
deleted file mode 100644
index 25c7373..0000000
--- a/gridServer.rar
+++ /dev/null
Binary files differ
diff --git a/src/main/kotlin/com/flightfeather/grid/config/CorsConfig.kt b/src/main/kotlin/com/flightfeather/grid/config/CorsConfig.kt
index f413316..ceec622 100644
--- a/src/main/kotlin/com/flightfeather/grid/config/CorsConfig.kt
+++ b/src/main/kotlin/com/flightfeather/grid/config/CorsConfig.kt
@@ -6,7 +6,7 @@
 import org.springframework.web.cors.UrlBasedCorsConfigurationSource
 import org.springframework.web.filter.CorsFilter
 
-@Configuration
+//@Configuration
 class CorsConfig {
 
     private fun buildConfig(): CorsConfiguration {
@@ -22,7 +22,7 @@
         }
     }
 
-    @Bean
+//    @Bean
     fun corsFilter(): CorsFilter {
         val source = UrlBasedCorsConfigurationSource().apply {
             registerCorsConfiguration("/**", buildConfig())
diff --git a/src/main/kotlin/com/flightfeather/grid/domain/ds1/entity/ClueInternal.java b/src/main/kotlin/com/flightfeather/grid/domain/ds1/entity/ClueInternal.java
new file mode 100644
index 0000000..62492de
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/grid/domain/ds1/entity/ClueInternal.java
@@ -0,0 +1,381 @@
+package com.flightfeather.grid.domain.ds1.entity;
+
+import java.util.Date;
+import javax.persistence.*;
+
+@Table(name = "g_t_clue_internal")
+public class ClueInternal {
+    @Id
+    @Column(name = "C_Id")
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    private Integer cId;
+
+    /**
+     * 绾跨储鍚嶇О
+     */
+    @Column(name = "C_Clue_Name")
+    private String cClueName;
+
+    /**
+     * 绾跨储缁撹
+     */
+    @Column(name = "C_Conclusion")
+    private String cConclusion;
+
+    /**
+     * 鎶ヨ鏃堕棿
+     */
+    @Column(name = "C_Alarm_Time")
+    private Date cAlarmTime;
+
+    /**
+     * 鎶ヨ绔欑偣鍚嶇О
+     */
+    @Column(name = "C_Site_Name")
+    private String cSiteName;
+
+    /**
+     * 鎶ヨ鍥犲瓙锛堝崟鍥犲瓙锛�
+     */
+    @Column(name = "C_Factor")
+    private String cFactor;
+
+    /**
+     * 涓嬪彂鏃堕棿
+     */
+    @Column(name = "C_Release_Time")
+    private Date cReleaseTime;
+
+    @Column(name = "C_Air_Checked_Options")
+    private String cAirCheckedOptions;
+
+    @Column(name = "C_Pollution_Checked_Options")
+    private String cPollutionCheckedOptions;
+
+    @Column(name = "C_Create_Time")
+    private Date cCreateTime;
+
+    @Column(name = "C_Center")
+    private String cCenter;
+
+    @Column(name = "C_Zoom")
+    private String cZoom;
+
+    @Column(name = "C_Longitude")
+    private Double cLongitude;
+
+    @Column(name = "C_Latitude")
+    private Double cLatitude;
+
+    @Column(name = "C_Site_Type")
+    private String cSiteType;
+
+    /**
+     * 绾跨储涓婃姤鏃堕棿
+     */
+    @Column(name = "C_Report_Time")
+    private Date cReportTime;
+
+    @Column(name = "C_Upload_Time")
+    private Date cUploadTime;
+
+    @Column(name = "C_Uploaded")
+    private Boolean cUploaded;
+
+    @Column(name = "C_Address")
+    private String cAddress;
+
+    /**
+     * @return C_Id
+     */
+    public Integer getCId() {
+        return cId;
+    }
+
+    /**
+     * @param cId
+     */
+    public void setCId(Integer cId) {
+        this.cId = cId;
+    }
+
+    /**
+     * 鑾峰彇绾跨储鍚嶇О
+     *
+     * @return C_Clue_Name - 绾跨储鍚嶇О
+     */
+    public String getCClueName() {
+        return cClueName;
+    }
+
+    /**
+     * 璁剧疆绾跨储鍚嶇О
+     *
+     * @param cClueName 绾跨储鍚嶇О
+     */
+    public void setCClueName(String cClueName) {
+        this.cClueName = cClueName == null ? null : cClueName.trim();
+    }
+
+    /**
+     * 鑾峰彇绾跨储缁撹
+     *
+     * @return C_Conclusion - 绾跨储缁撹
+     */
+    public String getCConclusion() {
+        return cConclusion;
+    }
+
+    /**
+     * 璁剧疆绾跨储缁撹
+     *
+     * @param cConclusion 绾跨储缁撹
+     */
+    public void setCConclusion(String cConclusion) {
+        this.cConclusion = cConclusion == null ? null : cConclusion.trim();
+    }
+
+    /**
+     * 鑾峰彇鎶ヨ鏃堕棿
+     *
+     * @return C_Alarm_Time - 鎶ヨ鏃堕棿
+     */
+    public Date getCAlarmTime() {
+        return cAlarmTime;
+    }
+
+    /**
+     * 璁剧疆鎶ヨ鏃堕棿
+     *
+     * @param cAlarmTime 鎶ヨ鏃堕棿
+     */
+    public void setCAlarmTime(Date cAlarmTime) {
+        this.cAlarmTime = cAlarmTime;
+    }
+
+    /**
+     * 鑾峰彇鎶ヨ绔欑偣鍚嶇О
+     *
+     * @return C_Site_Name - 鎶ヨ绔欑偣鍚嶇О
+     */
+    public String getCSiteName() {
+        return cSiteName;
+    }
+
+    /**
+     * 璁剧疆鎶ヨ绔欑偣鍚嶇О
+     *
+     * @param cSiteName 鎶ヨ绔欑偣鍚嶇О
+     */
+    public void setCSiteName(String cSiteName) {
+        this.cSiteName = cSiteName == null ? null : cSiteName.trim();
+    }
+
+    /**
+     * 鑾峰彇鎶ヨ鍥犲瓙锛堝崟鍥犲瓙锛�
+     *
+     * @return C_Factor - 鎶ヨ鍥犲瓙锛堝崟鍥犲瓙锛�
+     */
+    public String getCFactor() {
+        return cFactor;
+    }
+
+    /**
+     * 璁剧疆鎶ヨ鍥犲瓙锛堝崟鍥犲瓙锛�
+     *
+     * @param cFactor 鎶ヨ鍥犲瓙锛堝崟鍥犲瓙锛�
+     */
+    public void setCFactor(String cFactor) {
+        this.cFactor = cFactor == null ? null : cFactor.trim();
+    }
+
+    /**
+     * 鑾峰彇涓嬪彂鏃堕棿
+     *
+     * @return C_Release_Time - 涓嬪彂鏃堕棿
+     */
+    public Date getCReleaseTime() {
+        return cReleaseTime;
+    }
+
+    /**
+     * 璁剧疆涓嬪彂鏃堕棿
+     *
+     * @param cReleaseTime 涓嬪彂鏃堕棿
+     */
+    public void setCReleaseTime(Date cReleaseTime) {
+        this.cReleaseTime = cReleaseTime;
+    }
+
+    /**
+     * @return C_Air_Checked_Options
+     */
+    public String getCAirCheckedOptions() {
+        return cAirCheckedOptions;
+    }
+
+    /**
+     * @param cAirCheckedOptions
+     */
+    public void setCAirCheckedOptions(String cAirCheckedOptions) {
+        this.cAirCheckedOptions = cAirCheckedOptions == null ? null : cAirCheckedOptions.trim();
+    }
+
+    /**
+     * @return C_Pollution_Checked_Options
+     */
+    public String getCPollutionCheckedOptions() {
+        return cPollutionCheckedOptions;
+    }
+
+    /**
+     * @param cPollutionCheckedOptions
+     */
+    public void setCPollutionCheckedOptions(String cPollutionCheckedOptions) {
+        this.cPollutionCheckedOptions = cPollutionCheckedOptions == null ? null : cPollutionCheckedOptions.trim();
+    }
+
+    /**
+     * @return C_Create_Time
+     */
+    public Date getCCreateTime() {
+        return cCreateTime;
+    }
+
+    /**
+     * @param cCreateTime
+     */
+    public void setCCreateTime(Date cCreateTime) {
+        this.cCreateTime = cCreateTime;
+    }
+
+    /**
+     * @return C_Center
+     */
+    public String getCCenter() {
+        return cCenter;
+    }
+
+    /**
+     * @param cCenter
+     */
+    public void setCCenter(String cCenter) {
+        this.cCenter = cCenter == null ? null : cCenter.trim();
+    }
+
+    /**
+     * @return C_Zoom
+     */
+    public String getCZoom() {
+        return cZoom;
+    }
+
+    /**
+     * @param cZoom
+     */
+    public void setCZoom(String cZoom) {
+        this.cZoom = cZoom == null ? null : cZoom.trim();
+    }
+
+    /**
+     * @return C_Longitude
+     */
+    public Double getCLongitude() {
+        return cLongitude;
+    }
+
+    /**
+     * @param cLongitude
+     */
+    public void setCLongitude(Double cLongitude) {
+        this.cLongitude = cLongitude;
+    }
+
+    /**
+     * @return C_Latitude
+     */
+    public Double getCLatitude() {
+        return cLatitude;
+    }
+
+    /**
+     * @param cLatitude
+     */
+    public void setCLatitude(Double cLatitude) {
+        this.cLatitude = cLatitude;
+    }
+
+    /**
+     * @return C_Site_Type
+     */
+    public String getCSiteType() {
+        return cSiteType;
+    }
+
+    /**
+     * @param cSiteType
+     */
+    public void setCSiteType(String cSiteType) {
+        this.cSiteType = cSiteType == null ? null : cSiteType.trim();
+    }
+
+    /**
+     * 鑾峰彇绾跨储涓婃姤鏃堕棿
+     *
+     * @return C_Report_Time - 绾跨储涓婃姤鏃堕棿
+     */
+    public Date getCReportTime() {
+        return cReportTime;
+    }
+
+    /**
+     * 璁剧疆绾跨储涓婃姤鏃堕棿
+     *
+     * @param cReportTime 绾跨储涓婃姤鏃堕棿
+     */
+    public void setCReportTime(Date cReportTime) {
+        this.cReportTime = cReportTime;
+    }
+
+    /**
+     * @return C_Upload_Time
+     */
+    public Date getCUploadTime() {
+        return cUploadTime;
+    }
+
+    /**
+     * @param cUploadTime
+     */
+    public void setCUploadTime(Date cUploadTime) {
+        this.cUploadTime = cUploadTime;
+    }
+
+    /**
+     * @return C_Uploaded
+     */
+    public Boolean getCUploaded() {
+        return cUploaded;
+    }
+
+    /**
+     * @param cUploaded
+     */
+    public void setCUploaded(Boolean cUploaded) {
+        this.cUploaded = cUploaded;
+    }
+
+    /**
+     * @return C_Address
+     */
+    public String getCAddress() {
+        return cAddress;
+    }
+
+    /**
+     * @param cAddress
+     */
+    public void setCAddress(String cAddress) {
+        this.cAddress = cAddress == null ? null : cAddress.trim();
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/grid/domain/ds1/entity/ClueTask.java b/src/main/kotlin/com/flightfeather/grid/domain/ds1/entity/ClueTask.java
index 381cf83..420f718 100644
--- a/src/main/kotlin/com/flightfeather/grid/domain/ds1/entity/ClueTask.java
+++ b/src/main/kotlin/com/flightfeather/grid/domain/ds1/entity/ClueTask.java
@@ -74,6 +74,8 @@
     @Column(name = "internal_task")
     private Boolean internalTask;
 
+    private Boolean finished;
+
     /**
      * @return guid
      */
@@ -345,4 +347,18 @@
     public void setInternalTask(Boolean internalTask) {
         this.internalTask = internalTask;
     }
+
+    /**
+     * @return finished
+     */
+    public Boolean getFinished() {
+        return finished;
+    }
+
+    /**
+     * @param finished
+     */
+    public void setFinished(Boolean finished) {
+        this.finished = finished;
+    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/grid/domain/ds1/mapper/ClueInternalMapper.kt b/src/main/kotlin/com/flightfeather/grid/domain/ds1/mapper/ClueInternalMapper.kt
new file mode 100644
index 0000000..14347f2
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/grid/domain/ds1/mapper/ClueInternalMapper.kt
@@ -0,0 +1,14 @@
+package com.flightfeather.grid.domain.ds1.mapper
+
+import com.flightfeather.grid.domain.ds1.entity.ClueInternal
+import com.flightfeather.grid.domain.util.MyMapper
+import com.flightfeather.grid.vo.ClueVo
+import org.apache.ibatis.annotations.Mapper
+
+@Mapper
+interface ClueInternalMapper : MyMapper<ClueInternal?> {
+
+    fun getClue(sTime: String?, eTime: String?): List<ClueInternal?>
+
+    fun getClueById(clueId: Int?): ClueInternal?
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/grid/domain/ds1/mapper/ClueTaskMapper.kt b/src/main/kotlin/com/flightfeather/grid/domain/ds1/mapper/ClueTaskMapper.kt
index ee47cde..1ddbb94 100644
--- a/src/main/kotlin/com/flightfeather/grid/domain/ds1/mapper/ClueTaskMapper.kt
+++ b/src/main/kotlin/com/flightfeather/grid/domain/ds1/mapper/ClueTaskMapper.kt
@@ -2,7 +2,13 @@
 
 import com.flightfeather.grid.domain.ds1.entity.ClueTask
 import com.flightfeather.grid.domain.util.MyMapper
+import com.flightfeather.grid.vo.ClueTaskOptions
+import com.flightfeather.grid.vo.ClueTaskSummaryVo
 import org.apache.ibatis.annotations.Mapper
 
 @Mapper
-interface ClueTaskMapper : MyMapper<ClueTask?>
\ No newline at end of file
+interface ClueTaskMapper : MyMapper<ClueTask?> {
+
+    // 鏌ヨ浠诲姟鏁伴噺銆佸畬鎴愭暟鎹�佸唴閮ㄤ换鍔℃暟閲�
+    fun selectSummaryCount(options: ClueTaskOptions): ClueTaskSummaryVo
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/grid/external/ClueHttpService.kt b/src/main/kotlin/com/flightfeather/grid/external/ClueHttpService.kt
index 777baae..1f8990d 100644
--- a/src/main/kotlin/com/flightfeather/grid/external/ClueHttpService.kt
+++ b/src/main/kotlin/com/flightfeather/grid/external/ClueHttpService.kt
@@ -34,7 +34,10 @@
         private const val TAG = "ClueHttpService"
         private const val TOKEN = "e6dc8bb9e1ff0ce973fb92b4af2e4c3f"
     }
-    private val httpMethod: HttpMethod = HttpMethod("101.230.224.80", 8082)
+    // 鍘熷IP鍦板潃
+//    private val httpMethod: HttpMethod = HttpMethod("101.230.224.80", 8082)
+    // 2025.9.22 鏍规嵁闈欏畨鍖虹涓夋柟鎺ュ彛鏂囨。锛屼慨鏀笽P鍦板潃
+    private val httpMethod: HttpMethod = HttpMethod("fmepi.jingan.gov.cn", 8088, true)
 
     @Value("\${imgPath}")
     lateinit var imgPath: String
@@ -85,7 +88,8 @@
         val time = updateTime.replace(" ", "%20")
 //        val time = updateTime
         try {
-            val res = httpMethod.get("/feedback/queryYxfListNew", listOf(Pair("updateTime", time)), headTimeStamp())
+            val res = httpMethod.get("/govProxy/feedback/queryYxfListNew", listOf(Pair("updateTime", time)),
+                headTimeStamp())
             val data = resCheck(res).asJsonArray
             return GsonUtils.parserJsonToArrayBeans(data.toString(), ClueDto::class.java)
         } catch (e: Exception) {
@@ -95,7 +99,7 @@
 
     fun getClueFile(clueId: String): HttpMethod.MyResponse {
         try {
-            return httpMethod.get("/feedback/getPDFNew", listOf(Pair("id", clueId)), headTimeStamp())
+            return httpMethod.get("/govProxy/feedback/getPDFNew", listOf(Pair("id", clueId)), headTimeStamp())
         } catch (e: Exception) {
             throw BizException(e.message, e.cause)
         }
@@ -109,7 +113,7 @@
         val vo = ClueConclusionDto(clueConclusion)
         val dataJson = Gson().toJson(vo)
         try {
-            val res = httpMethod.post("/feedback/thirdReportNew", dataJson, headTimeStamp())
+            val res = httpMethod.post("/govProxy/feedback/thirdReportNew", dataJson, headTimeStamp())
             resCheck(res)
             clueConclusion.ccUploaded = true
             clueConclusion.ccUploadTime = Date()
@@ -145,7 +149,7 @@
 
         val entity = builder.build()
         try {
-            val res = httpMethod.post("/feedback/questionReportNew", entity, headTimeStamp())
+            val res = httpMethod.post("/govProxy/feedback/questionReportNew", entity, headTimeStamp())
             resCheck(res)
             clueQuestion.cqUploaded = true
             clueQuestion.cqUploadTime = Date()
diff --git a/src/main/kotlin/com/flightfeather/grid/service/ClueQuestionService.kt b/src/main/kotlin/com/flightfeather/grid/service/ClueQuestionService.kt
index 73d8b0b..5d30f43 100644
--- a/src/main/kotlin/com/flightfeather/grid/service/ClueQuestionService.kt
+++ b/src/main/kotlin/com/flightfeather/grid/service/ClueQuestionService.kt
@@ -18,7 +18,7 @@
      * @param deleteImg 鍒犻櫎鐨勫浘鐗囪矾寰勬暟缁�
      * @param files 鍥剧墖
      */
-    fun updateQuestionAndImage(question: String, deleteImg: String, files: Array<MultipartFile>): Boolean
+    fun updateQuestionAndImage(question: String, deleteImg: String?, files: Array<MultipartFile>?): Boolean
 
     /**
      * 鍒犻櫎绾跨储闂鍙婂浘鐗�
diff --git a/src/main/kotlin/com/flightfeather/grid/service/ClueTaskService.kt b/src/main/kotlin/com/flightfeather/grid/service/ClueTaskService.kt
index 17e5dc3..5bae0df 100644
--- a/src/main/kotlin/com/flightfeather/grid/service/ClueTaskService.kt
+++ b/src/main/kotlin/com/flightfeather/grid/service/ClueTaskService.kt
@@ -2,6 +2,9 @@
 
 import com.flightfeather.grid.domain.ds1.entity.ClueTask
 import com.flightfeather.grid.vo.ClueInternalTaskVo
+import com.flightfeather.grid.vo.ClueTaskOptions
+import com.flightfeather.grid.vo.ClueTaskSummaryVo
+import com.flightfeather.grid.vo.DataHead
 
 /**
  * 绾跨储浠诲姟鐩稿叧鏈嶅姟
@@ -18,6 +21,12 @@
 
     fun getClueTask(clueTask: ClueTask): List<ClueTask?>
 
+    fun searchClueTask(options: ClueTaskOptions, page: Int?, perPage: Int?): Pair<DataHead, List<ClueTask?>>
+
     fun deleteClueTask(clueTask: ClueTask): Int
 
+    fun getClueTaskSummary(options: ClueTaskOptions): ClueTaskSummaryVo
+
+    fun finishClueTask(clueTaskId: String): Int
+
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/grid/service/impl/ClueConclusionServiceImpl.kt b/src/main/kotlin/com/flightfeather/grid/service/impl/ClueConclusionServiceImpl.kt
index be47c4c..e301854 100644
--- a/src/main/kotlin/com/flightfeather/grid/service/impl/ClueConclusionServiceImpl.kt
+++ b/src/main/kotlin/com/flightfeather/grid/service/impl/ClueConclusionServiceImpl.kt
@@ -24,23 +24,28 @@
         clueConclusion.ccUploaded = false
         clueConclusion.ccCreateTime = Date()
         if (clueConclusion.ccInternal == null) clueConclusion.ccInternal = false
+        val conclusion: ClueConclusion?
         try {
-            val conclusion = clueConclusionMapper.selectOne(ClueConclusion().apply { cId = clueConclusion.cId })
-            // 鏇存柊
-            return if (conclusion != null) {
-                if (conclusion.ccUploaded) throw BizException("绾跨储缁撹宸叉帹閫侊紝鏃犳硶淇敼")
-                clueConclusion.ccId = conclusion.ccId
-                val res = clueConclusionMapper.updateByPrimaryKeySelective(clueConclusion)
-                res == 1
-            }
-            // 鎻掑叆
-            else {
-                val res = clueConclusionMapper.insert(clueConclusion)
-                res == 1
-            }
+            conclusion = clueConclusionMapper.selectOne(ClueConclusion().apply {
+                cId = clueConclusion.cId
+                ccInternal = clueConclusion.ccInternal
+            })
         } catch (e: Exception) {
             throw BizException("姣忔潯绾跨储鏈�澶氳兘鏈変竴鏉$粨璁猴紝璇ョ嚎绱㈢粨璁哄瓨鍦ㄥ鏉★紝璇锋鏌ョ郴缁熼�昏緫")
         }
+        // 鏇存柊
+        return if (conclusion != null) {
+            if (conclusion.ccUploaded) throw BizException("绾跨储缁撹宸叉帹閫侊紝鏃犳硶淇敼")
+            clueConclusion.ccId = conclusion.ccId
+            val res = clueConclusionMapper.updateByPrimaryKeySelective(clueConclusion)
+            res == 1
+        }
+        // 鎻掑叆
+        else {
+            val res = clueConclusionMapper.insert(clueConclusion)
+            res == 1
+        }
+
     }
 
     override fun getClueConclusion(clueId: String, internal: Boolean?): ClueConclusion? {
diff --git a/src/main/kotlin/com/flightfeather/grid/service/impl/ClueQuestionServiceImpl.kt b/src/main/kotlin/com/flightfeather/grid/service/impl/ClueQuestionServiceImpl.kt
index e224ef5..4da2338 100644
--- a/src/main/kotlin/com/flightfeather/grid/service/impl/ClueQuestionServiceImpl.kt
+++ b/src/main/kotlin/com/flightfeather/grid/service/impl/ClueQuestionServiceImpl.kt
@@ -35,16 +35,18 @@
         return res == 1
     }
 
-    override fun updateQuestionAndImage(question: String, deleteImg: String, files: Array<MultipartFile>): Boolean {
+    override fun updateQuestionAndImage(question: String, deleteImg: String?, files: Array<MultipartFile>?): Boolean {
         val questionVo = Gson().fromJson(question, ClueQuestion::class.java)
         val oldOne = clueQuestionMapper.selectByPrimaryKey(questionVo.cqId) ?: throw BizException("闂涓嶅瓨鍦�")
         if (oldOne.cqUploaded) throw BizException("闂宸蹭笂浼狅紝鏃犳硶淇敼")
-        deleteImageFile(questionVo, deleteImg)
-        val picPath = saveImageFile(questionVo, files)
-        if (questionVo.cqFilePath.isEmpty()) {
-            questionVo.cqFilePath = picPath
-        } else {
-            questionVo.cqFilePath += ";${picPath}"
+        if (deleteImg != null) deleteImageFile(questionVo, deleteImg)
+        if (files != null) {
+            val picPath = saveImageFile(questionVo, files)
+            if (questionVo.cqFilePath.isEmpty()) {
+                questionVo.cqFilePath = picPath
+            } else {
+                questionVo.cqFilePath += ";${picPath}"
+            }
         }
         questionVo.cqCreateTime = Date()
         val res = clueQuestionMapper.updateByPrimaryKeySelective(questionVo)
@@ -55,6 +57,20 @@
         val oldOne = clueQuestionMapper.selectByPrimaryKey(questionId) ?: throw BizException("闂涓嶅瓨鍦�")
         if (oldOne.cqUploaded) throw BizException("闂宸蹭笂浼狅紝鏃犳硶鍒犻櫎")
         deleteImageDirectory(oldOne)
+
+        PageHelper.startPage<ClueQuestion>(1, 1)
+        clueQuestionMapper.selectByExample(Example(ClueQuestion::class.java).apply {
+            createCriteria().andEqualTo("cId", oldOne.cId)
+            orderBy("cqUid").desc()
+        })?.takeIf { it.isNotEmpty() }?.let {
+            val q = it[0]
+            if (q?.cqUid != oldOne.cqUid) {
+                q?.cqUid = oldOne.cqUid
+                clueQuestionMapper.updateByPrimaryKeySelective(q)
+            }
+        }
+
+//        clueQuestionMapper.select
         val res = clueQuestionMapper.deleteByPrimaryKey(questionId)
         return res == 1
     }
@@ -147,7 +163,7 @@
                         )
                     }
                 }
-            orderBy("cqId")
+            orderBy("cqUid")
         })
         return res
     }
diff --git a/src/main/kotlin/com/flightfeather/grid/service/impl/ClueTaskServiceImpl.kt b/src/main/kotlin/com/flightfeather/grid/service/impl/ClueTaskServiceImpl.kt
index 114e1db..142f99f 100644
--- a/src/main/kotlin/com/flightfeather/grid/service/impl/ClueTaskServiceImpl.kt
+++ b/src/main/kotlin/com/flightfeather/grid/service/impl/ClueTaskServiceImpl.kt
@@ -1,13 +1,20 @@
 package com.flightfeather.grid.service.impl
 
 import com.flightfeather.grid.config.exception.BizException
+import com.flightfeather.grid.constant.ConstantHttp
 import com.flightfeather.grid.domain.ds1.entity.ClueTask
 import com.flightfeather.grid.domain.ds1.mapper.ClueInternalMapper
 import com.flightfeather.grid.domain.ds1.mapper.ClueTaskMapper
 import com.flightfeather.grid.service.ClueTaskService
 import com.flightfeather.grid.vo.ClueInternalTaskVo
+import com.flightfeather.grid.vo.ClueTaskOptions
+import com.flightfeather.grid.vo.ClueTaskSummaryVo
+import com.flightfeather.grid.vo.DataHead
+import com.flightfeather.grid.web.responsePack
+import com.github.pagehelper.PageHelper
 import org.springframework.stereotype.Service
 import org.springframework.transaction.annotation.Transactional
+import tk.mybatis.mapper.entity.Example
 import java.util.*
 
 /**
@@ -39,6 +46,7 @@
         clueInternalTaskVo.clueTask?.createTime = Date()
         clueInternalTaskVo.clueTask?.updateTime = Date()
         clueInternalTaskVo.clueTask?.internalTask = true
+        clueInternalTaskVo.clueTask?.finished = false
         return clueTaskMapper.insert(clueInternalTaskVo.clueTask)
     }
 
@@ -49,6 +57,7 @@
         clueTask.createTime = Date()
         clueTask.updateTime = Date()
         clueTask.internalTask = false
+        clueTask.finished = false
         return clueTaskMapper.insert(clueTask)
     }
 
@@ -63,8 +72,45 @@
         return clueTaskMapper.select(clueTask)
     }
 
+    override fun searchClueTask(options: ClueTaskOptions, page: Int?, perPage: Int?): Pair<DataHead, List<ClueTask?>> {
+        val p = PageHelper.startPage<ClueTask>(
+            page ?: ConstantHttp.DEFAULT_PAGE_NUM,
+            perPage ?: ConstantHttp.DEFAULT_PAGE_SIZE
+        )
+        clueTaskMapper.selectByExample(Example(ClueTask::class.java).apply {
+            createCriteria().apply {
+                andEqualTo("internalTask", options.internal)
+                andGreaterThanOrEqualTo("taskTime", options.startTime)
+                andLessThanOrEqualTo("taskTime", options.endTime)
+                andEqualTo("provinceCode", options.provinceCode)
+                andEqualTo("provinceName", options.provinceName)
+                andEqualTo("cityCode", options.cityCode)
+                andEqualTo("cityName", options.cityName)
+                andEqualTo("districtCode", options.districtCode)
+                andEqualTo("districtName", options.districtName)
+                andEqualTo("townCode", options.townCode)
+                andEqualTo("townName", options.townName)
+                andEqualTo("finished", options.finished)
+            }
+            orderBy(options.sortBy ?: "taskTime").apply { if (options.sort == "desc") desc() else asc() }
+        })
+
+        return responsePack(p)
+    }
+
     override fun deleteClueTask(clueTask: ClueTask): Int {
         clueTask.guid ?: throw BizException("鍒犻櫎绾跨储浠诲姟澶辫触锛岀己灏戜换鍔′富閿甮uid")
         return clueTaskMapper.delete(clueTask)
     }
+
+    override fun getClueTaskSummary(options: ClueTaskOptions): ClueTaskSummaryVo {
+        return clueTaskMapper.selectSummaryCount(options)
+    }
+
+    override fun finishClueTask(clueTaskId: String): Int {
+        return clueTaskMapper.updateByPrimaryKeySelective(ClueTask().apply {
+            guid = clueTaskId
+            finished = true
+        })
+    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/grid/vo/BaseResponse.kt b/src/main/kotlin/com/flightfeather/grid/vo/BaseResponse.kt
index bdf116d..c415aea 100644
--- a/src/main/kotlin/com/flightfeather/grid/vo/BaseResponse.kt
+++ b/src/main/kotlin/com/flightfeather/grid/vo/BaseResponse.kt
@@ -1,5 +1,6 @@
 package com.flightfeather.grid.vo
 
+import com.google.gson.Gson
 import io.swagger.annotations.ApiModel
 import io.swagger.annotations.ApiModelProperty
 
@@ -19,6 +20,10 @@
             message = if (success) "璇锋眰鎴愬姛" else "璇锋眰澶辫触"
         }
     }
+
+    override fun toString(): String {
+        return Gson().toJson(this)
+    }
 }
 
 data class DataHead(
diff --git a/src/main/kotlin/com/flightfeather/grid/vo/ClueTaskOptions.kt b/src/main/kotlin/com/flightfeather/grid/vo/ClueTaskOptions.kt
new file mode 100644
index 0000000..fba5045
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/grid/vo/ClueTaskOptions.kt
@@ -0,0 +1,35 @@
+package com.flightfeather.grid.vo
+
+import com.fasterxml.jackson.annotation.JsonFormat
+import com.fasterxml.jackson.annotation.JsonInclude
+import java.time.LocalDateTime
+
+/**
+ * 鍖哄煙鏌ヨ鏉′欢
+ */
+@JsonInclude(JsonInclude.Include.NON_NULL)
+open class ClueTaskOptions{
+    // 鏄惁鏄唴閮ㄤ换鍔�
+    var internal: Boolean? = null
+    // 琛屾斂鍖哄垝
+    var provinceCode: String? = null
+    var provinceName: String? = null
+    var cityCode: String? = null
+    var cityName: String? = null
+    var districtCode: String? = null
+    var districtName: String? = null
+    var townCode: String? = null
+    var townName: String? = null
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    var startTime: LocalDateTime? = null
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    var endTime: LocalDateTime? = null
+
+    // 浠诲姟鏄惁瀹屾垚
+    var finished: Boolean? = null
+    // 鎺掑簭鏂瑰紡锛宎sc: 鍗囧簭鎺掑垪锛宒esc锛氶檷搴忔帓鍒�
+    var sort: String = "desc"
+    // 鎺掑簭瀛楁锛岄粯璁ょ敱鎺ュ彛鑷瀹氫箟
+    var sortBy: String? = null
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/grid/vo/ClueTaskSummaryVo.kt b/src/main/kotlin/com/flightfeather/grid/vo/ClueTaskSummaryVo.kt
new file mode 100644
index 0000000..796414a
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/grid/vo/ClueTaskSummaryVo.kt
@@ -0,0 +1,31 @@
+package com.flightfeather.grid.vo
+
+/**
+ * 绾跨储浠诲姟瀹屾垚鎯呭喌缁熻
+ * @date 2025/4/27
+ * @author feiyu02
+ */
+data class ClueTaskSummaryVo(
+    // 浠诲姟鎬昏
+    val totalCount: Int = 0,
+
+    // 鍐呴儴浠诲姟鎬昏
+    val internalTaskCount: Int = 0,
+    // 澶栭儴浠诲姟鎬昏
+    val externalTaskCount: Int = 0,
+
+    // 瀹屾垚浠诲姟鎬昏
+    val finishedCount: Int = 0,
+    // 鏈畬鎴愪换鍔℃�昏
+    val unfinishedCount: Int = 0,
+
+    // 鍐呴儴瀹屾垚浠诲姟鎬昏
+    val internalFinishedCount: Int = 0,
+    // 鍐呴儴鏈畬鎴愪换鍔℃�昏
+    val internalUnFinishedCount: Int = 0,
+
+    // 澶栭儴瀹屾垚浠诲姟鎬昏
+    val externalFinishedCount: Int = 0,
+    // 澶栭儴鏈畬鎴愪换鍔℃�昏
+    val externalUnFinishedCount: Int = 0,
+)
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/grid/web/BaseResPack.kt b/src/main/kotlin/com/flightfeather/grid/web/BaseResPack.kt
index 38f3a53..3ce43d2 100644
--- a/src/main/kotlin/com/flightfeather/grid/web/BaseResPack.kt
+++ b/src/main/kotlin/com/flightfeather/grid/web/BaseResPack.kt
@@ -3,6 +3,7 @@
 import com.flightfeather.grid.config.exception.BizException
 import com.flightfeather.grid.vo.BaseResponse
 import com.flightfeather.grid.vo.DataHead
+import com.github.pagehelper.Page
 
 
 /**
@@ -24,4 +25,11 @@
     } catch (e: BizException) {
         BaseResponse(false, message = e.message ?: "")
     }
+}
+
+/**
+ * 鍖呰甯︽湁鍒嗛〉鐨勮繑鍥炵粨鏋�
+ */
+fun <T> responsePack(p: Page<T>): Pair<DataHead, List<T?>> {
+    return DataHead(p.pageNum, p.pages, p.total) to p.result
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/grid/web/ClueQuestionController.kt b/src/main/kotlin/com/flightfeather/grid/web/ClueQuestionController.kt
index 36bfb6b..ecab051 100644
--- a/src/main/kotlin/com/flightfeather/grid/web/ClueQuestionController.kt
+++ b/src/main/kotlin/com/flightfeather/grid/web/ClueQuestionController.kt
@@ -23,8 +23,8 @@
     @PostMapping("/update")
     fun updateQuestion(
         @ApiParam("绾跨储闂json") @RequestParam("question") question: String,
-        @ApiParam("鍒犻櫎鐨勫浘鐗囪矾寰勬暟缁�") @RequestParam("deleteImg") deleteImg: String,
-        @ApiParam("鏂板鐨勭嚎绱㈠浘鐗�") @RequestPart("images") files: Array<MultipartFile>,
+        @ApiParam("鍒犻櫎鐨勫浘鐗囪矾寰勬暟缁�") @RequestParam("deleteImg", required = false) deleteImg: String?,
+        @ApiParam("鏂板鐨勭嚎绱㈠浘鐗�") @RequestPart("images", required = false) files: Array<MultipartFile>?,
     ) = resPack { clueQuestionService.updateQuestionAndImage(question, deleteImg, files) }
 
     @ApiOperation("鍒犻櫎绾跨储闂鍙婂浘鐗�")
diff --git a/src/main/kotlin/com/flightfeather/grid/web/ClueTaskController.kt b/src/main/kotlin/com/flightfeather/grid/web/ClueTaskController.kt
index c6e1dab..322079e 100644
--- a/src/main/kotlin/com/flightfeather/grid/web/ClueTaskController.kt
+++ b/src/main/kotlin/com/flightfeather/grid/web/ClueTaskController.kt
@@ -3,6 +3,7 @@
 import com.flightfeather.grid.domain.ds1.entity.ClueTask
 import com.flightfeather.grid.service.ClueTaskService
 import com.flightfeather.grid.vo.ClueInternalTaskVo
+import com.flightfeather.grid.vo.ClueTaskOptions
 import io.swagger.annotations.Api
 import io.swagger.annotations.ApiOperation
 import io.swagger.annotations.ApiParam
@@ -37,9 +38,29 @@
         @ApiParam("绾跨储浠诲姟") @RequestBody clueTask: ClueTask,
     ) = resPack { clueTaskService.getClueTask(clueTask) }
 
+    @ApiOperation("鏌ヨ绾跨储浠诲姟")
+    @PostMapping("/search")
+    fun searchClueTask(
+        @RequestParam("page", required = false) page: Int?,
+        @RequestParam("per_page", required = false) perPage: Int?,
+        @ApiParam("绾跨储浠诲姟鏌ヨ鏉′欢") @RequestBody clueTaskOptions: ClueTaskOptions,
+    ) = resPack { clueTaskService.searchClueTask(clueTaskOptions, page, perPage) }
+
     @ApiOperation("鍒犻櫎绾跨储浠诲姟")
     @DeleteMapping("/delete")
     fun deleteClueTask(
         @ApiParam("绾跨储浠诲姟") @RequestBody clueTask: ClueTask,
     ) = resPack { clueTaskService.deleteClueTask(clueTask) }
+
+    @ApiOperation("鏌ヨ绾跨储浠诲姟瀹屾垚鎯呭喌缁熻")
+    @PostMapping("/summary")
+    fun getClueTaskSummary(
+        @ApiParam("绾跨储浠诲姟鏌ヨ鏉′欢") @RequestBody clueTaskOptions: ClueTaskOptions,
+    ) = resPack { clueTaskService.getClueTaskSummary(clueTaskOptions) }
+
+    @ApiOperation("瀹屾垚绾跨储浠诲姟")
+    @PostMapping("/finish")
+    fun finishClueTask(
+        @ApiParam("绾跨储浠诲姟id") @RequestParam clueTaskId: String,
+    ) = resPack { clueTaskService.finishClueTask(clueTaskId) }
 }
\ No newline at end of file
diff --git a/src/main/resources/generator/generatorConfig.xml b/src/main/resources/generator/generatorConfig.xml
index 4053482..9ee6f81 100644
--- a/src/main/resources/generator/generatorConfig.xml
+++ b/src/main/resources/generator/generatorConfig.xml
@@ -56,17 +56,17 @@
 <!--        <table tableName="g_t_clue" domainObjectName="Clue" enableCountByExample="false"-->
 <!--               enableUpdateByExample="false" enableDeleteByExample="false"-->
 <!--               enableSelectByExample="false" selectByExampleQueryId="false"/>-->
-        <table tableName="g_t_clue_conclusion" domainObjectName="ClueConclusion" enableCountByExample="false"
-               enableUpdateByExample="false" enableDeleteByExample="false"
-               enableSelectByExample="false" selectByExampleQueryId="false"/>
-        <table tableName="g_t_clue_question" domainObjectName="ClueQuestion" enableCountByExample="false"
-               enableUpdateByExample="false" enableDeleteByExample="false"
-               enableSelectByExample="false" selectByExampleQueryId="false"/>
-<!--            <table tableName="g_t_clue_task" domainObjectName="ClueTask" enableCountByExample="false"-->
-<!--                   enableUpdateByExample="false" enableDeleteByExample="false"-->
-<!--                   enableSelectByExample="false" selectByExampleQueryId="false"/>-->
-<!--        <table tableName="g_t_clue_internal" domainObjectName="ClueInternal" enableCountByExample="true"-->
-<!--               enableUpdateByExample="true" enableDeleteByExample="true"-->
-<!--               enableSelectByExample="true" selectByExampleQueryId="true"/>-->
+<!--        <table tableName="g_t_clue_conclusion" domainObjectName="ClueConclusion" enableCountByExample="false"-->
+<!--               enableUpdateByExample="false" enableDeleteByExample="false"-->
+<!--               enableSelectByExample="false" selectByExampleQueryId="false"/>-->
+<!--        <table tableName="g_t_clue_question" domainObjectName="ClueQuestion" enableCountByExample="false"-->
+<!--               enableUpdateByExample="false" enableDeleteByExample="false"-->
+<!--               enableSelectByExample="false" selectByExampleQueryId="false"/>-->
+            <table tableName="g_t_clue_task" domainObjectName="ClueTask" enableCountByExample="false"
+                   enableUpdateByExample="false" enableDeleteByExample="false"
+                   enableSelectByExample="false" selectByExampleQueryId="false"/>
+<!--        <table tableName="g_t_clue_internal" domainObjectName="ClueInternal" enableCountByExample="false"-->
+<!--               enableUpdateByExample="false" enableDeleteByExample="false"-->
+<!--               enableSelectByExample="false" selectByExampleQueryId="false"/>-->
     </context>
 </generatorConfiguration>
\ No newline at end of file
diff --git a/src/main/resources/mapper/ds1/ClueInternalMapper.xml b/src/main/resources/mapper/ds1/ClueInternalMapper.xml
new file mode 100644
index 0000000..622cfb4
--- /dev/null
+++ b/src/main/resources/mapper/ds1/ClueInternalMapper.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.flightfeather.grid.domain.ds1.mapper.ClueInternalMapper">
+  <resultMap id="BaseResultMap" type="com.flightfeather.grid.domain.ds1.entity.ClueInternal">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    <id column="C_Id" jdbcType="INTEGER" property="cId" />
+    <result column="C_Clue_Name" jdbcType="VARCHAR" property="cClueName" />
+    <result column="C_Conclusion" jdbcType="VARCHAR" property="cConclusion" />
+    <result column="C_Alarm_Time" jdbcType="TIMESTAMP" property="cAlarmTime" />
+    <result column="C_Site_Name" jdbcType="VARCHAR" property="cSiteName" />
+    <result column="C_Factor" jdbcType="VARCHAR" property="cFactor" />
+    <result column="C_Release_Time" jdbcType="TIMESTAMP" property="cReleaseTime" />
+    <result column="C_Air_Checked_Options" jdbcType="VARCHAR" property="cAirCheckedOptions" />
+    <result column="C_Pollution_Checked_Options" jdbcType="VARCHAR" property="cPollutionCheckedOptions" />
+    <result column="C_Create_Time" jdbcType="TIMESTAMP" property="cCreateTime" />
+    <result column="C_Center" jdbcType="VARCHAR" property="cCenter" />
+    <result column="C_Zoom" jdbcType="VARCHAR" property="cZoom" />
+    <result column="C_Longitude" jdbcType="DOUBLE" property="cLongitude" />
+    <result column="C_Latitude" jdbcType="DOUBLE" property="cLatitude" />
+    <result column="C_Site_Type" jdbcType="VARCHAR" property="cSiteType" />
+    <result column="C_Report_Time" jdbcType="TIMESTAMP" property="cReportTime" />
+    <result column="C_Upload_Time" jdbcType="TIMESTAMP" property="cUploadTime" />
+    <result column="C_Uploaded" jdbcType="BIT" property="cUploaded" />
+    <result column="C_Address" jdbcType="VARCHAR" property="cAddress" />
+  </resultMap>
+  <sql id="Base_Column_List">
+    <!--
+      WARNING - @mbg.generated
+    -->
+    C_Id, C_Clue_Name, C_Conclusion, C_Alarm_Time, C_Site_Name, C_Factor, C_Release_Time, 
+    C_Air_Checked_Options, C_Pollution_Checked_Options, C_Create_Time, C_Center, C_Zoom, 
+    C_Longitude, C_Latitude, C_Site_Type, C_Report_Time, C_Upload_Time, C_Uploaded, C_Address
+  </sql>
+
+  <resultMap extends="BaseResultMap" id="ClueVoMap" type="com.flightfeather.grid.vo.ClueInternalVo">
+    <!--    &amp;lt;result column="questionCount" jdbcType="INTEGER" property="questionCount" /&amp;gt;-->
+    <!--    &amp;lt;result column="conclusionCount" jdbcType="INTEGER" property="conclusionCount" /&amp;gt;-->
+  </resultMap>
+
+  <sql id="selectClueVo">
+    SELECT
+    a.*,
+    COUNT(DISTINCT b.CC_Id) AS conclusionCount,
+    COUNT(DISTINCT c.CQ_Id) AS questionCount,
+    COUNT(DISTINCT d.guid) AS taskCount
+    FROM
+    g_t_clue_internal AS a
+    LEFT JOIN g_t_clue_conclusion AS b ON a.C_Id = b.C_Id and b.CC_Internal = true
+    LEFT JOIN g_t_clue_question AS c ON a.C_Id = c.C_Id and c.CQ_Internal = true
+    LEFT JOIN g_t_clue_task AS d ON a.C_Id = d.clue_id and d.internal_task = true
+  </sql>
+  <sql id="groupClueId">
+    GROUP BY
+    a.C_Id
+    ORDER BY
+    a.C_Id DESC
+  </sql>
+
+  <select id="getClue" resultMap="ClueVoMap">
+    <include refid="selectClueVo" />
+    <where>
+      <if test="sTime != null">
+        AND a.C_Release_Time &gt;= #{sTime}
+      </if>
+      <if test="eTime != null">
+        AND a.C_Release_Time &lt;= #{eTime}
+      </if>
+    </where>
+    <include refid="groupClueId" />
+  </select>
+
+  <select id="getClueById" resultMap="ClueVoMap">
+    <include refid="selectClueVo" />
+    <where>
+      a.C_Id = #{clueId}
+    </where>
+    <include refid="groupClueId" />
+  </select>
+</mapper>
\ No newline at end of file
diff --git a/src/main/resources/mapper/ds1/ClueTaskMapper.xml b/src/main/resources/mapper/ds1/ClueTaskMapper.xml
index 5995d6a..8dd5186 100644
--- a/src/main/resources/mapper/ds1/ClueTaskMapper.xml
+++ b/src/main/resources/mapper/ds1/ClueTaskMapper.xml
@@ -23,6 +23,7 @@
     <result column="update_time" jdbcType="TIMESTAMP" property="updateTime" />
     <result column="executor_ids" jdbcType="VARCHAR" property="executorIds" />
     <result column="internal_task" jdbcType="BIT" property="internalTask" />
+    <result column="finished" jdbcType="BIT" property="finished" />
   </resultMap>
   <sql id="Base_Column_List">
     <!--
@@ -30,6 +31,70 @@
     -->
     guid, clue_id, task_time, province_code, province_name, city_code, city_name, district_code, 
     district_name, town_code, town_name, response_level, travel_mode, has_uav, create_time, 
-    update_time, executor_ids, internal_task
+    update_time, executor_ids, internal_task, finished
   </sql>
+
+<!--  閫氱敤SQL璇彞-->
+  <sql id="Where_Area">
+    <if test="provinceCode != null">
+      AND ${tableAlias}.province_code = #{provinceCode}
+    </if>
+    <if test="provinceName != null">
+      AND ${tableAlias}.province_name = #{provinceName}
+    </if>
+    <if test="cityCode != null">
+      AND ${tableAlias}.city_code = #{cityCode}
+    </if>
+    <if test="cityName != null">
+      AND ${tableAlias}.city_name = #{cityName}
+    </if>
+    <if test="districtCode != null">
+      AND ${tableAlias}.district_code = #{districtCode}
+    </if>
+    <if test="districtName != null">
+      AND ${tableAlias}.district_name = #{districtName}
+    </if>
+    <if test="townCode != null">
+      AND ${tableAlias}.town_code = #{townCode}
+    </if>
+    <if test="townName != null">
+      AND ${tableAlias}.town_name = #{townName}
+    </if>
+  </sql>
+  <sql id="Where_Task_Time">
+    <if test="startTime != null">
+      AND ${tableAlias}.task_time &gt;= #{startTime}
+    </if>
+    <if test="endTime != null">
+      AND ${tableAlias}.task_time &lt;= #{endTime}
+    </if>
+  </sql>
+
+<!--  杩斿洖缁撴灉妯℃澘-->
+  <resultMap extends="BaseResultMap" id="SummaryMap" type="com.flightfeather.grid.vo.ClueTaskSummaryVo">
+  </resultMap>
+
+<!--  鏌ヨ璇彞-->
+  <select id="selectSummaryCount" resultMap="SummaryMap">
+    select
+    count(*) as totalCount,
+    sum(if(internal_task = true, 1, 0)) as internalTaskCount,
+    sum(if(internal_task = false, 1, 0)) as externalTaskCount,
+    sum(if(finished = true, 1, 0)) as finishedCount,
+    sum(if(finished = false, 1, 0)) as unfinishedCount,
+    sum(if(finished = true and internal_task = true, 1, 0)) as internalFinishedCount,
+    sum(if(finished = false and internal_task = true, 1, 0)) as internalUnFinishedCount,
+    sum(if(finished = true and internal_task = false, 1, 0)) as externalFinishedCount,
+    sum(if(finished = false and internal_task = false, 1, 0)) as externalUnFinishedCount
+    from g_t_clue_task as a
+    <where>
+      <include refid="Where_Area">
+        <property name="tableAlias" value="a"/>
+      </include>
+      <include refid="Where_Task_Time">
+        <property name="tableAlias" value="a"/>
+      </include>
+    </where>
+  </select>
+
 </mapper>
\ No newline at end of file
diff --git a/src/test/kotlin/com/flightfeather/grid/external/ClueHttpServiceTest.kt b/src/test/kotlin/com/flightfeather/grid/external/ClueHttpServiceTest.kt
index f36beea..5827303 100644
--- a/src/test/kotlin/com/flightfeather/grid/external/ClueHttpServiceTest.kt
+++ b/src/test/kotlin/com/flightfeather/grid/external/ClueHttpServiceTest.kt
@@ -23,7 +23,7 @@
 
     @Test
     fun getClue() {
-        val res = clueHttpService.getClue("2024-08-04 00:00:00")
+        val res = clueHttpService.getClue("2025-08-01 00:00:00")
         res.forEach {
             println(it.clueName)
         }
diff --git a/src/test/kotlin/com/flightfeather/grid/web/ClueTaskControllerTest.kt b/src/test/kotlin/com/flightfeather/grid/web/ClueTaskControllerTest.kt
index 2260010..255c6e2 100644
--- a/src/test/kotlin/com/flightfeather/grid/web/ClueTaskControllerTest.kt
+++ b/src/test/kotlin/com/flightfeather/grid/web/ClueTaskControllerTest.kt
@@ -1,6 +1,7 @@
 package com.flightfeather.grid.web
 
 import com.flightfeather.grid.domain.ds1.entity.ClueTask
+import com.flightfeather.grid.vo.ClueTaskOptions
 import org.junit.jupiter.api.Test
 
 import org.junit.jupiter.api.Assertions.*
@@ -10,6 +11,7 @@
 import org.springframework.boot.test.context.SpringBootTest
 import org.springframework.test.context.junit.jupiter.SpringExtension
 import org.springframework.test.context.junit4.SpringRunner
+import java.time.LocalDateTime
 
 @RunWith(SpringRunner::class)
 @ExtendWith(SpringExtension::class)
@@ -20,13 +22,23 @@
     lateinit var clueTaskController: ClueTaskController
 
     @Test
-    fun createClueTask() {
-        clueTaskController.createClueTask(ClueTask().apply {
-
+    fun searchClueTask() {
+        val res = clueTaskController.searchClueTask(1, 30, ClueTaskOptions().apply {
+            provinceCode = "31"
+            provinceName = "涓婃捣甯�"
+            cityCode = "3100"
+            cityName = "涓婃捣甯�"
+            startTime = LocalDateTime.of(2025, 4, 22, 14, 35, 0)
+            endTime = LocalDateTime.of(2025, 4, 24, 15, 10, 0)
+            internal
+            finished
         })
+        println(res.toString())
     }
 
     @Test
-    fun getClueTask() {
+    fun getClueTaskSummary() {
+        val res = clueTaskController.getClueTaskSummary(ClueTaskOptions())
+        println(res.toString())
     }
 }
\ No newline at end of file

--
Gitblit v1.9.3