From bde043c8fd1a076f44c402dd56c62d401afbfb16 Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期四, 27 三月 2025 17:29:48 +0800
Subject: [PATCH] 1. 新增卫星遥测网格热力图计算逻辑

---
 src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt     |   59 ++
 src/main/kotlin/com/flightfeather/uav/model/underwaygrid/UnderwayGridModel.kt                          |    8 
 src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridManage.kt                             |   70 +++
 src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellAndData.kt                            |   31 -
 src/main/kotlin/com/flightfeather/uav/biz/satellite/GridGroupOption.kt                                 |    2 
 src/main/kotlin/com/flightfeather/uav/model/BaseSOP.kt                                                 |   20 
 src/main/resources/mapper/GridDataMapper.xml                                                           |   19 +
 src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridUtil.kt                               |  101 +++++
 src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellSop.kt                                |    2 
 src/main/kotlin/com/flightfeather/uav/model/BaseNoSection.kt                                           |   19 +
 src/main/kotlin/com/flightfeather/uav/domain/entity/GridData.java                                      |  303 ++++++++++++++++
 src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteDataCalculateService.kt              |    4 
 src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImplTest.kt |   55 ++
 src/main/resources/generator/generatorConfig.xml                                                       |    4 
 src/test/kotlin/com/flightfeather/uav/Test.kt                                                          |   11 
 src/main/kotlin/com/flightfeather/uav/common/utils/TimeUtil.kt                                         |  156 +++++++-
 src/main/kotlin/com/flightfeather/uav/model/BaseModel.kt                                               |    6 
 src/main/kotlin/com/flightfeather/uav/domain/entity/ExpandFun.kt                                       |  178 +++++++++
 src/main/kotlin/com/flightfeather/uav/lightshare/web/SatelliteTelemetryController.kt                   |    5 
 src/main/kotlin/com/flightfeather/uav/model/epw/NoSection.kt                                           |   12 
 20 files changed, 960 insertions(+), 105 deletions(-)

diff --git a/src/main/kotlin/com/flightfeather/uav/biz/satellite/GridGroupOption.kt b/src/main/kotlin/com/flightfeather/uav/biz/satellite/GridGroupOption.kt
index 83a26c8..0fa7439 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/satellite/GridGroupOption.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/satellite/GridGroupOption.kt
@@ -11,7 +11,7 @@
     // 缃戞牸楂樺害锛屾寚鍗楀寳鏂瑰悜涓婄殑缃戞牸鏁伴噺
     val height: Int,
     // 缁嗗垎缃戞牸瀹藉害锛屽鏋滅綉鏍肩粍鏄粏鍒嗙綉鏍硷紝鍒欒〃绀哄搴斿師濮嬬綉鏍间腑鍗曚釜缃戞牸涓嬬粏鍒嗙殑缃戞牸鏁伴噺
-    val eachWith: Int,
+    val eachWidth: Int,
     // 缁嗗垎缃戞牸楂樺害锛屽鏋滅綉鏍肩粍鏄粏鍒嗙綉鏍硷紝鍒欒〃绀哄搴斿師濮嬬綉鏍间腑鍗曚釜缃戞牸涓嬬粏鍒嗙殑缃戞牸鏁伴噺
     val eachHeight: Int,
 )
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridManage.kt b/src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridManage.kt
index bd61d61..c201a99 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridManage.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridManage.kt
@@ -2,6 +2,10 @@
 
 import com.flightfeather.uav.common.utils.MapUtil
 import com.flightfeather.uav.domain.entity.*
+import com.flightfeather.uav.model.underwaygrid.GridCellAndData
+import com.flightfeather.uav.model.underwaygrid.GridCellSop
+import com.flightfeather.uav.model.underwaygrid.UnderwayGridModel
+import com.flightfeather.uav.socket.eunm.FactorType
 import org.springframework.beans.BeanUtils
 import kotlin.math.PI
 import kotlin.math.sqrt
@@ -258,20 +262,6 @@
                 dataId = gridData?.id
                 groupId = k.groupId
                 cellId = k.cellIndex
-//                no2 = avgData.no2
-//                co = avgData.co
-//                h2s = avgData.h2s
-//                so2 = avgData.so2
-//                o3 = avgData.o3
-//                pm25 = avgData.pm25
-//                pm10 = avgData.pm10
-//                temperature = avgData.temperature
-//                humidity = avgData.humidity
-//                voc = avgData.voc
-//                noi = avgData.noi
-//                no = avgData.no
-//                windSpeed
-//                windDirection
                 rank
             }
             gridDataDetailList.add(dataDetail)
@@ -286,6 +276,58 @@
         return gridDataDetailList
     }
 
+    /**
+     * 璁$畻鐑姏鍥剧綉鏍硷紝鍗崇綉鏍煎懆杈规墿鏁e奖鍝嶆潈閲嶈绠�
+     * @param gridDataDetail 缃戞牸鐩戞祴鏁版嵁
+     * @param gridCellList 鍖哄煙缃戞牸鏁扮粍
+     * @param option 鍖哄煙缃戞牸鍙傛暟淇℃伅
+     * @param searchLength 璁$畻鍛ㄨ竟鍏柟鍚戯紙涓婁笅宸﹀彸鍙婂洓涓瑙掞級缃戞牸鐨勯暱搴�
+     * @return 鍛ㄨ竟缃戞牸鍙婂搴旂殑鐩戞祴鏁版嵁缁撴灉
+     */
+    fun heatMap(
+        gridDataDetail: GridDataDetail, gridCellList: List<GridCell?>,
+        option: GridGroupOption, searchLength: Int,
+    ): List<GridDataDetail> {
+        // 鎵惧埌缃戞牸鏁版嵁瀵瑰簲鐨勭綉鏍间俊鎭�
+        val gridCell = gridCellList.find { it?.cellIndex == gridDataDetail.cellId }
+            ?: throw IllegalArgumentException("缃戞牸鏁版嵁鍜岀粰瀹氱殑鍖哄煙缃戞牸涓嶅尮閰�")
 
+        // 鑾峰彇鍛ㄨ竟缃戞牸
+        val surroundGridCellList =
+            SatelliteGridUtil.searchDiffuseGrid(gridDataDetail.cellId, gridCellList, option, searchLength)
+
+        // 浣跨敤璧拌埅缃戞牸鏉冮噸妯″瀷锛岃绠楀懆杈圭綉鏍肩殑鐩戞祴鏁版嵁鍊�
+        val underwayGridModel = UnderwayGridModel()
+        val dataList = listOf(GridCellAndData(gridCell, gridDataDetail))
+        val gridCellSopList = surroundGridCellList.map {
+            GridCellSop(
+                it,
+                it.id.toString(),
+                it.cellIndex.toString(),
+                it.cellIndex.toString()
+            ) }
+        underwayGridModel.execute(dataList, gridCellSopList)
+        val resMap = underwayGridModel.outputResult()
+
+        // 鏍煎紡鍖栫粨鏋滃苟杩斿洖
+        val result = mutableListOf<GridDataDetail>()
+        gridCellSopList.forEach {
+            val resGridDataDetail = GridDataDetail().apply {
+                dataId = gridDataDetail.dataId
+                groupId = gridDataDetail.groupId
+                cellId = it.gridCell.cellIndex
+            }
+
+            val key = "${it.sourceName};${it.index}"
+            val d = resMap[key]
+            d?.forEach { (t, u) ->
+                val avg = u["缁煎悎(${t})"]?.average ?: .0
+                resGridDataDetail.setFactorValue(FactorType.getByName(t), avg.toFloat())
+            }
+            result.add(resGridDataDetail)
+        }
+
+        return result
+    }
 
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridUtil.kt b/src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridUtil.kt
index 6010859..68b4dd6 100644
--- a/src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridUtil.kt
+++ b/src/main/kotlin/com/flightfeather/uav/biz/satellite/SatelliteGridUtil.kt
@@ -3,6 +3,7 @@
 import com.flightfeather.uav.common.utils.MapUtil
 import com.flightfeather.uav.domain.entity.GridCell
 import kotlin.math.ceil
+import kotlin.math.floor
 
 /**
  * 鍗槦缃戞牸璁$畻宸ュ叿
@@ -49,26 +50,118 @@
         option: GridGroupOption,
         searchLength: Int,
     ): List<GridCell> {
-        return emptyList()
+        val hOffset = option.eachWidth;
+        val wOffset = 1;
+
+        val cellIdMin = 1
+        val cellIdMax = option.width * option.height
+
+        val searchWidth = 0 - searchLength
+        val searchHeight = 0 - searchLength
+
+        val result = mutableListOf<GridCell>()
+
+        val eachRange = getCellWidthRange(gridCellIndex, option.eachWidth, option.eachHeight)?: return emptyList()
+        val groupRange = getCellWidthRange(
+            ceil(gridCellIndex.toDouble() / (option.eachWidth * option.eachHeight)).toInt(),
+            option.width / option.eachWidth,
+            option.height / option.eachHeight
+        ) ?: return emptyList()
+
+        for (w in searchWidth..searchLength) {
+            // 鍏堣繘琛屾í鍚戠殑鍧愭爣鍙樻崲
+            var _cellId = gridCellIndex + w * wOffset;
+            if (_cellId < eachRange.first || _cellId > eachRange.second) {
+                val cellOffset = if (_cellId < eachRange.first) _cellId - eachRange.first else _cellId - eachRange.second
+
+                val groupOffset = if (cellOffset / option.eachWidth > 0) {
+                    ceil(cellOffset.toDouble() / option.eachWidth).toInt()
+                } else {
+                    floor(cellOffset.toDouble() / option.eachWidth).toInt()
+                }
+
+                val newEachRange =
+                    (eachRange.first + groupOffset * option.eachWidth * option.eachHeight) to
+                            (eachRange.second + groupOffset * option.eachWidth * option.eachHeight)
+
+                _cellId = if (groupOffset > 0) {
+                    newEachRange.first + cellOffset - wOffset
+                } else {
+                    newEachRange.second + cellOffset + wOffset;
+                }
+
+                val _groupId = ceil(_cellId.toDouble() / (option.eachWidth * option.eachHeight)).toInt()
+
+                if (_groupId < groupRange.first || _groupId > groupRange.second) {
+                    continue;
+                }
+            }
+
+            for (h in searchHeight..searchLength) {
+                if (w == 0 && h == 0) continue;
+
+                val _eachRange = getCellWidthRange(_cellId, option.eachWidth, option.eachHeight) ?: return emptyList()
+
+                val wOffset = _cellId - _eachRange.first;
+                var _resCellId = _cellId + h * hOffset;
+                if (_resCellId < cellIdMin || _resCellId > cellIdMax) continue;
+
+                val total = option.eachWidth * option.eachHeight;
+                val x = ceil(_cellId.toDouble() / total).toInt() - 1;
+                val eachCellIdMin = 1 + x * total;
+                val eachCellIdMax = total + x * total;
+                val topCell = eachCellIdMin + wOffset;
+                val bottomCell = eachCellIdMax - option.eachWidth + 1 + wOffset;
+                if (_resCellId < eachCellIdMin || _resCellId > eachCellIdMax) {
+                    val cellOffset = if (_resCellId < eachCellIdMin) {
+                        _resCellId - topCell
+                    } else {
+                        _resCellId - bottomCell;
+                    }
+
+                    val newTopCell = if (cellOffset > 0) {
+                        topCell + option.width * option.eachHeight
+                    } else {
+                        topCell - option.width * option.eachHeight;
+                    }
+
+                    val newBottomCell = if (cellOffset > 0) {
+                        bottomCell + option.width * option.eachHeight
+                    } else {
+                        bottomCell - option.width * option.eachHeight;
+                    }
+
+                    _resCellId = if (cellOffset > 0) {
+                        newTopCell + cellOffset - hOffset
+                    } else {
+                        newBottomCell + cellOffset + hOffset;
+                    }
+                }
+                gridCellList.find { it?.cellIndex == _resCellId }?.let { result.add(it) }
+            }
+        }
+
+        return result;
     }
 
     /**
+     * Fixme 2025.3.14: 鍛ㄨ竟缃戞牸鐨勬煡鎵撅紝鍚庣画閫氳繃灏嗙綉鏍肩敤鍧愭爣鐐圭殑琛ㄧず鏂瑰紡鏉ョ洿鎺ヨ绠�(x, y)
      * 鏍规嵁缃戞牸绱㈠紩锛岃幏鍙栧叾鎵�鍦ㄤ笢瑗挎柟鍚戠殑缃戞牸绱㈠紩鑼冨洿
      * @param cellIndex 缃戞牸绱㈠紩
      * @param width 缃戞牸瀹藉害锛屾寚涓滆タ鏂瑰悜涓婄殑缃戞牸鏁伴噺
      * @param height 缃戞牸楂樺害锛屾寚鍗楀寳鏂瑰悜涓婄殑缃戞牸鏁伴噺
      * @return 杩斿洖缃戞牸绱㈠紩鍊艰寖鍥�
      */
-    fun getCellWidthRange(cellIndex: Int, width: Int, height: Int): Pair<Double, Double>? {
+    fun getCellWidthRange(cellIndex: Int, width: Int, height: Int): Pair<Int, Int>? {
         val total = width * height;
-        val x = ceil(cellIndex.toDouble() / total) - 1;
+        val x = (ceil(cellIndex.toDouble() / total) - 1).toInt()
         val first = 1 + x * total
         val last = width + x * total;
         var scale = 0;
         while (scale < height) {
             val min = first + scale * width;
             val max = last + scale * width;
-            if (cellIndex >= min && cellIndex <= max) {
+            if (cellIndex in min..max) {
                 return min to max
             }
             scale++;
diff --git a/src/main/kotlin/com/flightfeather/uav/common/utils/TimeUtil.kt b/src/main/kotlin/com/flightfeather/uav/common/utils/TimeUtil.kt
index c02eb83..aa189e6 100644
--- a/src/main/kotlin/com/flightfeather/uav/common/utils/TimeUtil.kt
+++ b/src/main/kotlin/com/flightfeather/uav/common/utils/TimeUtil.kt
@@ -1,34 +1,152 @@
 package com.flightfeather.uav.common.utils
 
-import java.text.DateFormat
-import java.text.SimpleDateFormat
+import java.time.Duration
+import java.time.LocalDateTime
+import java.time.ZoneId
 import java.util.*
+import kotlin.math.max
+import kotlin.math.min
 
 /**
  * @author riku
  * Date: 2019/9/16
  */
-class TimeUtil {
+object TimeUtil {
 
-    companion object {
 
-        /**
-         * 鏄惁鏄浜屽ぉ鎴栨洿鏂扮殑鏃堕棿
-         */
-        fun isNextDay(oldTime: Date, newTime: Date): Boolean {
-            val oldC = Calendar.getInstance().apply {
-                time = oldTime
-            }
-            val newC = Calendar.getInstance().apply {
-                time = newTime
-            }
+    /**
+     * 鏄惁鏄浜屽ぉ鎴栨洿鏂扮殑鏃堕棿
+     */
+    fun isNextDay(oldTime: Date, newTime: Date): Boolean {
+        val oldC = Calendar.getInstance().apply {
+            time = oldTime
+        }
+        val newC = Calendar.getInstance().apply {
+            time = newTime
+        }
 
-            return when {
-                newC[Calendar.YEAR] > oldC[Calendar.YEAR] -> true
-                newC[Calendar.YEAR] == oldC[Calendar.YEAR] -> newC[Calendar.DAY_OF_YEAR] > oldC[Calendar.DAY_OF_YEAR]
-                else -> false
-            }
+        return when {
+            newC[Calendar.YEAR] > oldC[Calendar.YEAR] -> true
+            newC[Calendar.YEAR] == oldC[Calendar.YEAR] -> newC[Calendar.DAY_OF_YEAR] > oldC[Calendar.DAY_OF_YEAR]
+            else -> false
         }
     }
 
+    /**
+     * 鑾峰彇鏌愭鏃堕棿鍦ㄦ瘡鏃ヤ腑鐨勬椂娈�
+     * "鍑屾櫒 0 - 6", "鏃╀笂 6 - 9", "涓婂崍 9 - 12", "涓崍 12 - 14", "涓嬪崍 14 - 17", "鍌嶆櫄 17 - 20", "澶滈棿 20 - 0"
+     * 褰撹繖娈垫椂闂磋法瓒婁簡鏃舵鏃讹紝鎸夌収60%鐨勬椂闂存墍鍦ㄦ椂娈典负鏈�缁堟椂娈碉紝鍚﹀垯閲囩敤鍚庝竴涓椂娈�
+     * @return 鏃舵鍜屾椂娈电殑璧锋鏃堕棿 <鏃舵, 寮�濮嬫椂闂�, 缁撴潫鏃堕棿>
+     */
+    fun getDayTimeTag(start: Date, end: Date): Triple<String, Date, Date>? {
+        var sLocal = LocalDateTime.ofInstant(start.toInstant(), ZoneId.systemDefault())
+        var eLocal = LocalDateTime.ofInstant(end.toInstant(), ZoneId.systemDefault())
+        val duration = Duration.between(sLocal, eLocal)
+        if (duration.toDays() > 1) return null
+        if (duration.isNegative) {
+            val temp = sLocal
+            sLocal = eLocal
+            eLocal = temp
+        }
+
+        val sDay = sLocal.dayOfMonth
+        val eDay = eLocal.dayOfMonth
+        val ranges = listOf(
+            Triple(0, 6, "鍑屾櫒"), Triple(6, 9, "鏃╀笂"),
+            Triple(9, 12, "涓婂崍"), Triple(12, 14, "涓崍"),
+            Triple(14, 17, "涓嬪崍"), Triple(17, 20, "鍌嶆櫄"), Triple(20, 24, "澶滈棿")
+        )
+        val periodList = mutableListOf<Pair<Triple<String, Date, Date>, Long>>()
+
+        if (sDay < eDay) {
+            val dayStart = sLocal.plusDays(1).withHour(0).withMinute(0).withSecond(0)
+            val firstRange = sLocal to dayStart
+            val secondRange = dayStart to eLocal
+            ranges.forEachIndexed { i, r ->
+                // 鍒ゆ柇鏃堕棿鑼冨洿鏄惁鍜岃鏃舵鏈変氦闆�
+                checkPeriodTime(firstRange.first, firstRange.second, r.first to r.second)?.let {
+                    val t = firstRange.first.withMinute(0).withSecond(0)
+                    periodList.add(
+                        Triple(
+                            r.third,
+                            Date.from(t.withHour(r.first).atZone(ZoneId.systemDefault()).toInstant()),
+                            if (r.second == 24) {
+                                Date.from(
+                                    t.withHour(0).plusDays(1).minusSeconds(1)
+                                        .atZone(ZoneId.systemDefault()).toInstant()
+                                )
+                            } else {
+                                Date.from(t.withHour(r.second).atZone(ZoneId.systemDefault()).toInstant())
+                            }
+                        ) to it.toMinutes()
+                    )
+                }
+                checkPeriodTime(secondRange.first, secondRange.second, r.first to r.second)?.let {
+                    val t = secondRange.first.withMinute(0).withSecond(0)
+                    periodList.add(
+                        Triple(
+                            r.third,
+                            Date.from(t.withHour(r.first).atZone(ZoneId.systemDefault()).toInstant()),
+                            if (r.second == 24) {
+                                Date.from(
+                                    t.withHour(0).plusDays(1).minusSeconds(1)
+                                        .atZone(ZoneId.systemDefault()).toInstant()
+                                )
+                            } else {
+                                Date.from(t.withHour(r.second).atZone(ZoneId.systemDefault()).toInstant())
+                            }
+                        ) to it.toMinutes()
+                    )
+                }
+            }
+        } else {
+            val range = sLocal to eLocal
+            ranges.forEachIndexed { i, r ->
+                // 鍒ゆ柇鏃堕棿鑼冨洿鏄惁鍜岃鏃舵鏈変氦闆�
+                checkPeriodTime(range.first, range.second, r.first to r.second)?.let {
+                    val t = range.first.withMinute(0).withSecond(0)
+                    periodList.add(
+                        Triple(
+                            r.third,
+                            Date.from(t.withHour(r.first).atZone(ZoneId.systemDefault()).toInstant()),
+                            if (r.second == 24) {
+                                Date.from(
+                                    t.withHour(0).plusDays(1).minusSeconds(1)
+                                        .atZone(ZoneId.systemDefault()).toInstant()
+                                )
+                            } else {
+                                Date.from(t.withHour(r.second).atZone(ZoneId.systemDefault()).toInstant())
+                            }
+                        ) to it.toMinutes()
+                    )
+                }
+            }
+        }
+        if (periodList.isEmpty()) return null
+
+        periodList.sortByDescending { it.second }
+        val maxOne = periodList.first()
+        return maxOne.first
+    }
+
+    private fun checkPeriodTime(start: LocalDateTime, end: LocalDateTime, hourRange: Pair<Int, Int>): Duration? {
+        return if (start.hour in hourRange.first..hourRange.second) {
+            Duration.between(
+                start,
+                end.withHour(min(hourRange.second, end.hour)).withMinute(0).withSecond(0)
+            )
+        } else if (start.hour < hourRange.first && end.hour > hourRange.second) {
+            Duration.between(
+                start.withHour(hourRange.first).withMinute(0).withSecond(0),
+                end.withHour(hourRange.second).withMinute(0).withSecond(0),
+            )
+        } else if (end.hour in hourRange.first..hourRange.second) {
+            Duration.between(
+                start.withHour(max(hourRange.first, start.hour)).withMinute(0).withSecond(0),
+                end,
+            )
+        } else {
+            null
+        }
+    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/domain/entity/ExpandFun.kt b/src/main/kotlin/com/flightfeather/uav/domain/entity/ExpandFun.kt
index eb613f4..c0bf033 100644
--- a/src/main/kotlin/com/flightfeather/uav/domain/entity/ExpandFun.kt
+++ b/src/main/kotlin/com/flightfeather/uav/domain/entity/ExpandFun.kt
@@ -1,10 +1,19 @@
 package com.flightfeather.uav.domain.entity
 
+import com.flightfeather.uav.biz.dataprocess.AvgPair
 import com.flightfeather.uav.common.utils.DateUtil
 import com.flightfeather.uav.common.utils.GsonUtils
 import com.flightfeather.uav.lightshare.bean.DataVo
 import com.flightfeather.uav.socket.bean.AirData
 import com.flightfeather.uav.socket.eunm.FactorType
+import com.flightfeather.uav.socket.eunm.FactorType.*
+import java.time.LocalDateTime
+import java.time.ZoneId
+import java.util.*
+import kotlin.math.atan
+import kotlin.math.cos
+import kotlin.math.round
+import kotlin.math.sin
 
 /**
  * 鏁版嵁搴撹〃瀹炰綋鎵╁睍鏂规硶
@@ -105,4 +114,171 @@
             factorData = mvPowerC
         },
     )
-}
\ No newline at end of file
+}
+
+
+/** GridDataDetail-start ********************************************************************/
+/**
+ * 鏍规嵁鐩戞祴鍥犲瓙绫诲瀷璧嬪��
+ */
+fun GridDataDetail.setFactorValue(type: FactorType?, value: Float) {
+    when (type) {
+        NO -> no = value
+        NO2 -> no2 = value
+        CO -> co = value
+        H2S -> h2s = value
+        SO2 -> so2 = value
+        O3 -> o3 = value
+        PM25 -> pm25 = value
+        PM10 -> pm10 = value
+        TEMPERATURE -> temperature = value
+        HUMIDITY -> humidity = value
+        VOC -> voc = value
+        NOI -> noi = value
+        WIND_SPEED -> windSpeed = value
+        WIND_DIRECTION -> windDirection = value
+        LNG -> TODO("no such factor")
+        LAT -> TODO("no such factor")
+        VELOCITY -> TODO("no such factor")
+        TIME -> TODO("no such factor")
+        HEIGHT -> TODO("no such factor")
+    }
+}
+
+fun List<GridDataDetail>.avg(): GridDataDetail {
+    //椋庡悜閲囩敤鍗曚綅鐭㈤噺娉曟眰鍙栧潎鍊�
+    var u = .0//涓滆タ鏂逛綅鍒嗛噺鎬诲拰
+    var v = .0//鍗楀寳鏂逛綅鍒嗛噺鎬诲拰
+    var c = 0//椋庡悜鏁版嵁璁℃暟
+
+    //闄ら鍚戝鐨勫叾浠栧洜瀛愰噰鐢ㄧ畻鏈钩鍧囨硶姹傚彇鍧囧��
+    val tmpList = mutableListOf<AvgPair>()
+    repeat(18) {
+        tmpList.add(AvgPair(0f, 0))
+    }
+
+    forEach { f ->
+        //椋庡悜
+        f.windDirection?.let { w ->
+            val r = Math.toRadians(w.toDouble())
+            u += sin(r)
+            v += cos(r)
+            c++
+        }
+        //鍏朵綑鍥犲瓙
+        tmpList[0].apply {
+            f.no2?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[1].apply {
+            f.co?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[2].apply {
+            f.h2s?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[3].apply {
+            f.so2?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[4].apply {
+            f.o3?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[5].apply {
+            f.pm25?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[6].apply {
+            f.pm10?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[7].apply {
+            f.temperature?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[8].apply {
+            f.humidity?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[9].apply {
+            f.voc?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[10].apply {
+            f.noi?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[11].apply {
+            f.windSpeed?.let {
+                t += it
+                this.c++
+            }
+        }
+        tmpList[12].apply {
+            f.no?.let {
+                t += it
+                this.c++
+            }
+        }
+    }
+
+    return GridDataDetail().apply {
+        no2 = tmpList[0].avg()
+        co = tmpList[1].avg()
+        h2s = tmpList[2].avg()
+        so2 = tmpList[3].avg()
+        o3 = tmpList[4].avg()
+        pm25 = tmpList[5].avg()
+        pm10 = tmpList[6].avg()
+        temperature = tmpList[7].avg()
+        humidity = tmpList[8].avg()
+        voc = tmpList[9].avg()
+        noi = tmpList[10].avg()
+        windSpeed = tmpList[11].avg()
+        no = tmpList[12].avg()
+
+        if (c != 0) {
+            val avgU = u / c
+            val avgV = v / c
+            var a = atan(avgU / avgV)
+            a = Math.toDegrees(a)
+            /**
+             * avgU>0;avgV>0: 鐪熷疄瑙掑害澶勪簬绗竴璞¢檺锛屼慨姝e�间负+0掳
+             * avgU>0;avgV<0: 鐪熷疄瑙掑害澶勪簬绗簩璞¢檺锛屼慨姝e�间负+180掳
+             * avgU<0;avgV<0: 鐪熷疄瑙掑害澶勪簬绗笁璞¢檺锛屼慨姝e�间负+180掳
+             * avgU<0;avgV>0: 鐪熷疄瑙掑害澶勪簬绗洓璞¢檺锛屼慨姝e�间负+360掳
+             */
+            a += if (avgV > 0) {
+                if (avgU > 0) 0 else 360
+            } else {
+                180
+            }
+            windDirection = round(a.toFloat())
+        }
+    }
+}
+/** GridDataDetail-over ********************************************************************/
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/domain/entity/GridData.java b/src/main/kotlin/com/flightfeather/uav/domain/entity/GridData.java
index 2273b64..49f150b 100644
--- a/src/main/kotlin/com/flightfeather/uav/domain/entity/GridData.java
+++ b/src/main/kotlin/com/flightfeather/uav/domain/entity/GridData.java
@@ -33,6 +33,71 @@
     private String mixDataId;
 
     /**
+     * 鎵�灞炲尯鍩燂紙璧拌埅鐩戞祴铻嶅悎缃戞牸锛�
+     */
+    private String zone;
+
+    /**
+     * 澶ф皵姹℃煋绛夌骇锛堜紭銆佽壇銆佽交搴︽薄鏌撱�佷腑搴︽薄鏌撱�侀噸搴︽薄鏌擄級
+     */
+    @Column(name = "pollution_degree")
+    private String pollutionDegree;
+
+    /**
+     * 澶ф皵姹℃煋绛夌骇缂栧彿锛堜紭銆佽壇銆佽交搴︽薄鏌撱�佷腑搴︽薄鏌撱�侀噸搴︽薄鏌擄級
+     */
+    @Column(name = "pollution_degree_index")
+    private Integer pollutionDegreeIndex;
+
+    /**
+     * 璧拌埅浠诲姟缂栧彿
+     */
+    @Column(name = "mission_code")
+    private String missionCode;
+
+    @Column(name = "province_code")
+    private String provinceCode;
+
+    @Column(name = "province_name")
+    private String provinceName;
+
+    @Column(name = "city_code")
+    private String cityCode;
+
+    @Column(name = "city_name")
+    private String cityName;
+
+    @Column(name = "district_code")
+    private String districtCode;
+
+    @Column(name = "district_name")
+    private String districtName;
+
+    @Column(name = "town_code")
+    private String townCode;
+
+    @Column(name = "town_name")
+    private String townName;
+
+    /**
+     * 鎵�澶勬瘡鏃ョ殑鏃舵锛�"鍑屾櫒 0 - 6", "鏃╀笂 6 - 9", "涓婂崍 9 - 12", "涓崍 12 - 14", "涓嬪崍 14 - 17", "鍌嶆櫄 17 - 20", "澶滈棿 20 - 0"
+     */
+    @Column(name = "day_time_period")
+    private String dayTimePeriod;
+
+    /**
+     * 鏃ユ椂娈靛紑濮嬫椂闂�
+     */
+    @Column(name = "day_time_period_start")
+    private Date dayTimePeriodStart;
+
+    /**
+     * 鏃ユ椂娈电粨鏉熸椂闂�
+     */
+    @Column(name = "day_time_period_end")
+    private Date dayTimePeriodEnd;
+
+    /**
      * @return id
      */
     public Integer getId() {
@@ -117,4 +182,242 @@
     public void setMixDataId(String mixDataId) {
         this.mixDataId = mixDataId == null ? null : mixDataId.trim();
     }
+
+    /**
+     * 鑾峰彇鎵�灞炲尯鍩燂紙璧拌埅鐩戞祴铻嶅悎缃戞牸锛�
+     *
+     * @return zone - 鎵�灞炲尯鍩燂紙璧拌埅鐩戞祴铻嶅悎缃戞牸锛�
+     */
+    public String getZone() {
+        return zone;
+    }
+
+    /**
+     * 璁剧疆鎵�灞炲尯鍩燂紙璧拌埅鐩戞祴铻嶅悎缃戞牸锛�
+     *
+     * @param zone 鎵�灞炲尯鍩燂紙璧拌埅鐩戞祴铻嶅悎缃戞牸锛�
+     */
+    public void setZone(String zone) {
+        this.zone = zone == null ? null : zone.trim();
+    }
+
+    /**
+     * 鑾峰彇澶ф皵姹℃煋绛夌骇锛堜紭銆佽壇銆佽交搴︽薄鏌撱�佷腑搴︽薄鏌撱�侀噸搴︽薄鏌擄級
+     *
+     * @return pollution_degree - 澶ф皵姹℃煋绛夌骇锛堜紭銆佽壇銆佽交搴︽薄鏌撱�佷腑搴︽薄鏌撱�侀噸搴︽薄鏌擄級
+     */
+    public String getPollutionDegree() {
+        return pollutionDegree;
+    }
+
+    /**
+     * 璁剧疆澶ф皵姹℃煋绛夌骇锛堜紭銆佽壇銆佽交搴︽薄鏌撱�佷腑搴︽薄鏌撱�侀噸搴︽薄鏌擄級
+     *
+     * @param pollutionDegree 澶ф皵姹℃煋绛夌骇锛堜紭銆佽壇銆佽交搴︽薄鏌撱�佷腑搴︽薄鏌撱�侀噸搴︽薄鏌擄級
+     */
+    public void setPollutionDegree(String pollutionDegree) {
+        this.pollutionDegree = pollutionDegree == null ? null : pollutionDegree.trim();
+    }
+
+    /**
+     * 鑾峰彇澶ф皵姹℃煋绛夌骇缂栧彿锛堜紭銆佽壇銆佽交搴︽薄鏌撱�佷腑搴︽薄鏌撱�侀噸搴︽薄鏌擄級
+     *
+     * @return pollution_degree_index - 澶ф皵姹℃煋绛夌骇缂栧彿锛堜紭銆佽壇銆佽交搴︽薄鏌撱�佷腑搴︽薄鏌撱�侀噸搴︽薄鏌擄級
+     */
+    public Integer getPollutionDegreeIndex() {
+        return pollutionDegreeIndex;
+    }
+
+    /**
+     * 璁剧疆澶ф皵姹℃煋绛夌骇缂栧彿锛堜紭銆佽壇銆佽交搴︽薄鏌撱�佷腑搴︽薄鏌撱�侀噸搴︽薄鏌擄級
+     *
+     * @param pollutionDegreeIndex 澶ф皵姹℃煋绛夌骇缂栧彿锛堜紭銆佽壇銆佽交搴︽薄鏌撱�佷腑搴︽薄鏌撱�侀噸搴︽薄鏌擄級
+     */
+    public void setPollutionDegreeIndex(Integer pollutionDegreeIndex) {
+        this.pollutionDegreeIndex = pollutionDegreeIndex;
+    }
+
+    /**
+     * 鑾峰彇璧拌埅浠诲姟缂栧彿
+     *
+     * @return mission_code - 璧拌埅浠诲姟缂栧彿
+     */
+    public String getMissionCode() {
+        return missionCode;
+    }
+
+    /**
+     * 璁剧疆璧拌埅浠诲姟缂栧彿
+     *
+     * @param missionCode 璧拌埅浠诲姟缂栧彿
+     */
+    public void setMissionCode(String missionCode) {
+        this.missionCode = missionCode == null ? null : missionCode.trim();
+    }
+
+    /**
+     * @return province_code
+     */
+    public String getProvinceCode() {
+        return provinceCode;
+    }
+
+    /**
+     * @param provinceCode
+     */
+    public void setProvinceCode(String provinceCode) {
+        this.provinceCode = provinceCode == null ? null : provinceCode.trim();
+    }
+
+    /**
+     * @return province_name
+     */
+    public String getProvinceName() {
+        return provinceName;
+    }
+
+    /**
+     * @param provinceName
+     */
+    public void setProvinceName(String provinceName) {
+        this.provinceName = provinceName == null ? null : provinceName.trim();
+    }
+
+    /**
+     * @return city_code
+     */
+    public String getCityCode() {
+        return cityCode;
+    }
+
+    /**
+     * @param cityCode
+     */
+    public void setCityCode(String cityCode) {
+        this.cityCode = cityCode == null ? null : cityCode.trim();
+    }
+
+    /**
+     * @return city_name
+     */
+    public String getCityName() {
+        return cityName;
+    }
+
+    /**
+     * @param cityName
+     */
+    public void setCityName(String cityName) {
+        this.cityName = cityName == null ? null : cityName.trim();
+    }
+
+    /**
+     * @return district_code
+     */
+    public String getDistrictCode() {
+        return districtCode;
+    }
+
+    /**
+     * @param districtCode
+     */
+    public void setDistrictCode(String districtCode) {
+        this.districtCode = districtCode == null ? null : districtCode.trim();
+    }
+
+    /**
+     * @return district_name
+     */
+    public String getDistrictName() {
+        return districtName;
+    }
+
+    /**
+     * @param districtName
+     */
+    public void setDistrictName(String districtName) {
+        this.districtName = districtName == null ? null : districtName.trim();
+    }
+
+    /**
+     * @return town_code
+     */
+    public String getTownCode() {
+        return townCode;
+    }
+
+    /**
+     * @param townCode
+     */
+    public void setTownCode(String townCode) {
+        this.townCode = townCode == null ? null : townCode.trim();
+    }
+
+    /**
+     * @return town_name
+     */
+    public String getTownName() {
+        return townName;
+    }
+
+    /**
+     * @param townName
+     */
+    public void setTownName(String townName) {
+        this.townName = townName == null ? null : townName.trim();
+    }
+
+    /**
+     * 鑾峰彇鎵�澶勬瘡鏃ョ殑鏃舵锛�"鍑屾櫒 0 - 6", "鏃╀笂 6 - 9", "涓婂崍 9 - 12", "涓崍 12 - 14", "涓嬪崍 14 - 17", "鍌嶆櫄 17 - 20", "澶滈棿 20 - 0"
+     *
+     * @return day_time_period - 鎵�澶勬瘡鏃ョ殑鏃舵锛�"鍑屾櫒 0 - 6", "鏃╀笂 6 - 9", "涓婂崍 9 - 12", "涓崍 12 - 14", "涓嬪崍 14 - 17", "鍌嶆櫄 17 - 20", "澶滈棿 20 - 0"
+     */
+    public String getDayTimePeriod() {
+        return dayTimePeriod;
+    }
+
+    /**
+     * 璁剧疆鎵�澶勬瘡鏃ョ殑鏃舵锛�"鍑屾櫒 0 - 6", "鏃╀笂 6 - 9", "涓婂崍 9 - 12", "涓崍 12 - 14", "涓嬪崍 14 - 17", "鍌嶆櫄 17 - 20", "澶滈棿 20 - 0"
+     *
+     * @param dayTimePeriod 鎵�澶勬瘡鏃ョ殑鏃舵锛�"鍑屾櫒 0 - 6", "鏃╀笂 6 - 9", "涓婂崍 9 - 12", "涓崍 12 - 14", "涓嬪崍 14 - 17", "鍌嶆櫄 17 - 20", "澶滈棿 20 - 0"
+     */
+    public void setDayTimePeriod(String dayTimePeriod) {
+        this.dayTimePeriod = dayTimePeriod == null ? null : dayTimePeriod.trim();
+    }
+
+    /**
+     * 鑾峰彇鏃ユ椂娈靛紑濮嬫椂闂�
+     *
+     * @return day_time_period_start - 鏃ユ椂娈靛紑濮嬫椂闂�
+     */
+    public Date getDayTimePeriodStart() {
+        return dayTimePeriodStart;
+    }
+
+    /**
+     * 璁剧疆鏃ユ椂娈靛紑濮嬫椂闂�
+     *
+     * @param dayTimePeriodStart 鏃ユ椂娈靛紑濮嬫椂闂�
+     */
+    public void setDayTimePeriodStart(Date dayTimePeriodStart) {
+        this.dayTimePeriodStart = dayTimePeriodStart;
+    }
+
+    /**
+     * 鑾峰彇鏃ユ椂娈电粨鏉熸椂闂�
+     *
+     * @return day_time_period_end - 鏃ユ椂娈电粨鏉熸椂闂�
+     */
+    public Date getDayTimePeriodEnd() {
+        return dayTimePeriodEnd;
+    }
+
+    /**
+     * 璁剧疆鏃ユ椂娈电粨鏉熸椂闂�
+     *
+     * @param dayTimePeriodEnd 鏃ユ椂娈电粨鏉熸椂闂�
+     */
+    public void setDayTimePeriodEnd(Date dayTimePeriodEnd) {
+        this.dayTimePeriodEnd = dayTimePeriodEnd;
+    }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteDataCalculateService.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteDataCalculateService.kt
index 494fcaa..88eb303 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteDataCalculateService.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/SatelliteDataCalculateService.kt
@@ -40,7 +40,7 @@
     /**
      * 灏嗚蛋鑸綉鏍兼暟鎹敓鎴愬搴旂殑鐑姏缃戞牸鍥�
      * @param groupId 浣跨敤鐨勭綉鏍肩粍id
-     * @param gridDataDetail 浣跨敤鐨勮蛋鑸綉鏍兼暟鎹�
+     * @param gridDataDetailList 浣跨敤鐨勮蛋鑸綉鏍兼暟鎹�
      */
-    fun buildHeatmap(groupId: Int, gridDataDetail: List<GridDataDetail>): List<GridDataDetail>
+    fun buildHeatmap(groupId: Int, gridDataDetailList: List<GridDataDetail>, searchLength:Int): List<GridDataDetail>
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt
index a765aa6..c260d11 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImpl.kt
@@ -1,11 +1,11 @@
 package com.flightfeather.uav.lightshare.service.impl
 
+import com.flightfeather.uav.biz.satellite.GridGroupOption
 import com.flightfeather.uav.biz.satellite.SatelliteGridManage
+import com.flightfeather.uav.biz.satellite.SatelliteGridUtil
 import com.flightfeather.uav.common.exception.BizException
-import com.flightfeather.uav.domain.entity.GridCell
-import com.flightfeather.uav.domain.entity.GridData
-import com.flightfeather.uav.domain.entity.GridDataDetail
-import com.flightfeather.uav.domain.entity.GridGroup
+import com.flightfeather.uav.common.utils.TimeUtil
+import com.flightfeather.uav.domain.entity.*
 import com.flightfeather.uav.domain.repository.MissionRep
 import com.flightfeather.uav.domain.repository.RealTimeDataRep
 import com.flightfeather.uav.domain.repository.SatelliteGridRep
@@ -138,9 +138,11 @@
         val mission = missionRep.findOne(missionCode) ?: throw BizException("浠诲姟涓嶅瓨鍦�")
         val data = realTimeDataRep.fetchData(mission)
 
+        // 鏌ユ壘鏄惁宸叉湁璧拌埅铻嶅悎璁板綍
         val oldGridDataList = satelliteGridRep.fetchGridData(GridData().apply {
             this.groupId = groupId
             mixDataId = missionCode
+            this.type = SatelliteDataType.Monitor.value.toByte()
         })
 
         if (oldGridDataList.isEmpty()) {
@@ -149,7 +151,23 @@
                 this.groupId = groupId
                 dataTime = mission.startTime
                 type = SatelliteDataType.Monitor.value.toByte()
-                mixDataId = mission.missionCode
+                this.missionCode = mission.missionCode
+                // Fixme 2025.3.27: 琛屾斂鍖哄垝鍦ㄨ蛋鑸换鍔℃坊鍔犲搴斿瓧娈靛悗杩涜璧嬪��
+                provinceCode
+                provinceName
+                cityCode
+                cityName
+                districtCode
+                districtName = mission.districtName
+                // Fixme 2025.3.27: 鎵�灞炵洃娴嬬偣鍖哄煙鐩墠闇�瑕侀�氳繃鐢ㄦ埛閫夋嫨纭畾
+                zone
+                pollutionDegreeIndex
+                pollutionDegree
+
+                val period = TimeUtil.getDayTimeTag(mission.startTime, mission.endTime)
+                dayTimePeriod = period?.first
+                dayTimePeriodStart = period?.second
+                dayTimePeriodEnd = period?.third
             }
             satelliteGridRep.insertGridData(newGridData)
 
@@ -181,8 +199,37 @@
         }
     }
 
-    override fun buildHeatmap(groupId: Int, gridDataDetail: List<GridDataDetail>): List<GridDataDetail> {
+    override fun buildHeatmap(groupId: Int, gridDataDetailList: List<GridDataDetail>, searchLength:Int): List<GridDataDetail> {
         val gridCellList = satelliteGridRep.fetchGridCell(groupId)
+        val originCellIdList = gridDataDetailList.map { it.cellId }
+        // Fixme 2025.3.24: 姝ゅ鏍规嵁鐜版湁鐨勭綉鏍间俊鎭璁℃柟寮忥紝浣跨敤涓存椂鐨勫弬鏁帮紝鍚庣画灏嗙綉鏍奸�氳繃浜岀淮鍧愭爣褰㈠紡琛ㄧず锛屾澶勫弬鏁板幓闄�
+        val option = GridGroupOption(120, 90, 10, 10)
 
+        val resMap = mutableMapOf<Int, MutableList<GridDataDetail>>()
+
+        // 寰幆璁$畻姣忎釜缃戞牸鐨勫懆杈规墿鏁g綉鏍肩粨鏋�
+        gridDataDetailList.forEach {gdd ->
+            SatelliteGridManage.heatMap(gdd, gridCellList, option, searchLength).forEach {r ->
+                if (!originCellIdList.contains(r.cellId)) {
+                    if (!resMap.containsKey(r.cellId)) {
+                        resMap[r.cellId] = mutableListOf()
+                    }
+                    resMap[r.cellId]?.add(r)
+                }
+            }
+        }
+
+        // 灏嗘墍鏈夌粨鏋滄牸寮忓寲锛屽悓鏃堕噸鍙犵綉鏍艰繘琛岀洃娴嬫暟鎹潎鍊艰绠�
+        val result = mutableListOf<GridDataDetail>()
+        resMap.forEach { (_, v) ->
+            result.add(v.avg().apply {
+                this.dataId = v.first().dataId
+                this.groupId = v.first().groupId
+                this.cellId = v.first().cellId
+            })
+        }
+        result.addAll(gridDataDetailList)
+
+        return result
     }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/web/SatelliteTelemetryController.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/web/SatelliteTelemetryController.kt
index 8187d15..c431269 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/web/SatelliteTelemetryController.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/web/SatelliteTelemetryController.kt
@@ -149,6 +149,7 @@
     @PostMapping("/product/underway/heatmap/build")
     fun buildUnderwayHeatmap(
         @ApiParam("浣跨敤鐨勭綉鏍肩粍id") @RequestParam groupId: Int,
-        @ApiParam("浣跨敤鐨勮蛋鑸綉鏍兼暟鎹�") @RequestBody gridDataDetail: List<GridDataDetail>
-    ) = resPack { satelliteDataCalculateService.buildHeatmap(groupId, gridDataDetail) }
+        @ApiParam("鎼滅储缃戞牸璺濈") @RequestParam searchLength:Int,
+        @ApiParam("浣跨敤鐨勮蛋鑸綉鏍兼暟鎹�") @RequestBody gridDataDetailList: List<GridDataDetail>
+    ) = resPack { satelliteDataCalculateService.buildHeatmap(groupId, gridDataDetailList, searchLength) }
 }
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/model/BaseModel.kt b/src/main/kotlin/com/flightfeather/uav/model/BaseModel.kt
index 1ac2269..7e0c3ea 100644
--- a/src/main/kotlin/com/flightfeather/uav/model/BaseModel.kt
+++ b/src/main/kotlin/com/flightfeather/uav/model/BaseModel.kt
@@ -198,6 +198,12 @@
         return rMap
     }
 
+    /**
+     * 灏嗚绠楃粨鏋滄牸寮忓寲涓哄灞傜骇鐨勯敭瀵瑰�肩粨鏋�
+     * 绗竴灞傛寜鐓т笉鍚屾薄鏌撴簮鐨勭储寮曞�艰繘琛屽垎绫�
+     * 绗簩灞傛寜鐓х洃娴嬪洜瀛愮被鍨嬭繘琛屽垎绫�
+     * 绗笁灞傛寜鐓ц嚜瀹氫箟鐨勬爣绛捐繘琛屽垎绫�
+     */
     private fun formatConversion2(e: BaseEffect) {
         val rKey = "${e.sourceName};${e.index}"
         if (!rMap.containsKey(rKey)) {
diff --git a/src/main/kotlin/com/flightfeather/uav/model/BaseNoSection.kt b/src/main/kotlin/com/flightfeather/uav/model/BaseNoSection.kt
new file mode 100644
index 0000000..27c2d73
--- /dev/null
+++ b/src/main/kotlin/com/flightfeather/uav/model/BaseNoSection.kt
@@ -0,0 +1,19 @@
+package com.flightfeather.uav.model
+
+/**
+ *
+ * @date 2025/3/24
+ * @author feiyu02
+ */
+open class BaseNoSection<M : BaseMData, S : BaseSOP> : BaseSection<M, S>() {
+
+    override val sectionValues: List<Double> = listOf(1.0)
+
+    override val sectionType: List<String> = listOf("缁煎悎")
+
+    override val tagClz: Class<out BaseTag> = NoTag::class.java
+
+    override fun onSectionValue(mData: M, sop: S, effect: BaseEffect): Double {
+        return .0
+    }
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/model/BaseSOP.kt b/src/main/kotlin/com/flightfeather/uav/model/BaseSOP.kt
index d593b94..206f480 100644
--- a/src/main/kotlin/com/flightfeather/uav/model/BaseSOP.kt
+++ b/src/main/kotlin/com/flightfeather/uav/model/BaseSOP.kt
@@ -6,18 +6,18 @@
  * Source of pollution
  * 姹℃煋婧� 鍩虹被
  */
-open class BaseSOP() {
+open class BaseSOP(val sourceId: String, val sourceName: String, val index: String) {
 
     // 姹℃煋婧愭爣璇�
-    lateinit var sourceId: String
-    lateinit var sourceName: String
-    lateinit var index: String
-
-    constructor(sourceId: String, sourceName: String, index: String) : this() {
-        this.sourceId = sourceId
-        this.sourceName = sourceName
-        this.index = index
-    }
+//    lateinit var sourceId: String
+//    lateinit var sourceName: String
+//    lateinit var index: String
+//
+//    constructor() : this() {
+//        this.sourceId = sourceId
+//        this.sourceName = sourceName
+//        this.index = index
+//    }
     /**
      * 涓績缁忓害
      */
diff --git a/src/main/kotlin/com/flightfeather/uav/model/epw/NoSection.kt b/src/main/kotlin/com/flightfeather/uav/model/epw/NoSection.kt
index 4441f33..7820787 100644
--- a/src/main/kotlin/com/flightfeather/uav/model/epw/NoSection.kt
+++ b/src/main/kotlin/com/flightfeather/uav/model/epw/NoSection.kt
@@ -6,14 +6,4 @@
 /**
  * 涓嶅仛鍒嗙被缁熻
  */
-class NoSection : BaseSection<DataVo, BaseSOP>() {
-    override val sectionValues: List<Double> = listOf(1.0)
-
-    override val sectionType: List<String> = listOf("缁煎悎")
-
-    override val tagClz: Class<out BaseTag> = NoTag::class.java
-
-    override fun onSectionValue(mData: DataVo, sop: BaseSOP, effect: BaseEffect): Double {
-        return .0
-    }
-}
\ No newline at end of file
+class NoSection : BaseNoSection<DataVo, BaseSOP>()
\ No newline at end of file
diff --git a/src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellAndData.kt b/src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellAndData.kt
index 75f6439..e62065c 100644
--- a/src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellAndData.kt
+++ b/src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellAndData.kt
@@ -15,25 +15,20 @@
 
     override fun getFactorData(type: FactorType): Double? {
         return when (type) {
-//            NO2 -> NO2
-//            CO -> CO
-//            H2S -> H2S
-//            SO2 -> SO2
-//            O3 -> O3
+            NO2 -> gridDataDetail.no2.toDouble()
+            CO -> gridDataDetail.co.toDouble()
+            H2S -> gridDataDetail.h2s.toDouble()
+            SO2 -> gridDataDetail.so2.toDouble()
+            O3 -> gridDataDetail.o3.toDouble()
             PM25 -> gridDataDetail.pm25.toDouble()
-//            PM10 -> PM10
-//            TEMPERATURE -> TEMPERATURE
-//            HUMIDITY -> HUMIDITY
-//            VOC -> VOC
-//            NOI -> NOI
-//            LNG -> LNG
-//            LAT -> LAT
-//            VELOCITY -> VELOCITY
-//            TIME -> TIME
-//            WIND_SPEED -> WIND_SPEED
-//            WIND_DIRECTION -> WIND_DIRECTION
-//            HEIGHT -> HEIGHT
-//            NO -> NO
+            PM10 -> gridDataDetail.pm10.toDouble()
+            TEMPERATURE -> gridDataDetail.temperature.toDouble()
+            HUMIDITY -> gridDataDetail.humidity.toDouble()
+            VOC -> gridDataDetail.voc.toDouble()
+            NOI -> gridDataDetail.noi.toDouble()
+            WIND_SPEED -> gridDataDetail.windSpeed.toDouble()
+            WIND_DIRECTION -> gridDataDetail.windDirection.toDouble()
+            NO -> gridDataDetail.no.toDouble()
             else -> null
         }
     }
diff --git a/src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellSop.kt b/src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellSop.kt
index 3c21f36..bae316b 100644
--- a/src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellSop.kt
+++ b/src/main/kotlin/com/flightfeather/uav/model/underwaygrid/GridCellSop.kt
@@ -11,7 +11,7 @@
 class GridCellSop : BaseSOP {
     val gridCell:GridCell
 
-    constructor(gridCell: GridCell) : super(){
+    constructor(gridCell: GridCell) : super("", "", "") {
         this.gridCell = gridCell
     }
     constructor(gridCell: GridCell, sourceId: String, sourceName: String, index: String) : super(
diff --git a/src/main/kotlin/com/flightfeather/uav/model/underwaygrid/UnderwayGridModel.kt b/src/main/kotlin/com/flightfeather/uav/model/underwaygrid/UnderwayGridModel.kt
index 5ff8e3f..57008a3 100644
--- a/src/main/kotlin/com/flightfeather/uav/model/underwaygrid/UnderwayGridModel.kt
+++ b/src/main/kotlin/com/flightfeather/uav/model/underwaygrid/UnderwayGridModel.kt
@@ -1,9 +1,7 @@
 package com.flightfeather.uav.model.underwaygrid
 
-import com.flightfeather.uav.model.BaseDataPrep
-import com.flightfeather.uav.model.BaseModel
-import com.flightfeather.uav.model.BaseSection
-import com.flightfeather.uav.model.BaseWeight
+import com.flightfeather.uav.model.*
+import com.flightfeather.uav.model.epw.NoSection
 import com.flightfeather.uav.model.epw.WeightType
 import com.flightfeather.uav.socket.eunm.FactorType
 
@@ -19,7 +17,7 @@
 
     override var weights: List<BaseWeight<GridCellAndData, GridCellSop>> = listOf(GridWindDirWeight(), GridWindDisWeight())
 
-    override var sections: List<BaseSection<GridCellAndData, GridCellSop>> = emptyList()
+    override var sections: List<BaseSection<GridCellAndData, GridCellSop>> = listOf(BaseNoSection())
 
     override fun mDataCheck(m: GridCellAndData): Boolean {
         return m.gridDataDetail.pm25 != null
diff --git a/src/main/resources/generator/generatorConfig.xml b/src/main/resources/generator/generatorConfig.xml
index ce7dc0e..c188146 100644
--- a/src/main/resources/generator/generatorConfig.xml
+++ b/src/main/resources/generator/generatorConfig.xml
@@ -68,7 +68,7 @@
 <!--        <table tableName="segment_info" domainObjectName="SegmentInfo" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
 <!--        <table tableName="grid_group" domainObjectName="GridGroup" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
 <!--        <table tableName="grid_cell" domainObjectName="GridCell" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
-<!--        <table tableName="grid_data" domainObjectName="GridData" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>-->
-        <table tableName="grid_data_detail" domainObjectName="GridDataDetail" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>
+        <table tableName="grid_data" domainObjectName="GridData" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"/>
+<!--        <table tableName="grid_data_detail" domainObjectName="GridDataDetail" 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/GridDataMapper.xml b/src/main/resources/mapper/GridDataMapper.xml
index 188f9d0..aba0c00 100644
--- a/src/main/resources/mapper/GridDataMapper.xml
+++ b/src/main/resources/mapper/GridDataMapper.xml
@@ -10,11 +10,28 @@
     <result column="data_time" jdbcType="TIMESTAMP" property="dataTime" />
     <result column="type" jdbcType="TINYINT" property="type" />
     <result column="mix_data_id" jdbcType="VARCHAR" property="mixDataId" />
+    <result column="zone" jdbcType="VARCHAR" property="zone" />
+    <result column="pollution_degree" jdbcType="VARCHAR" property="pollutionDegree" />
+    <result column="pollution_degree_index" jdbcType="INTEGER" property="pollutionDegreeIndex" />
+    <result column="mission_code" jdbcType="VARCHAR" property="missionCode" />
+    <result column="province_code" jdbcType="VARCHAR" property="provinceCode" />
+    <result column="province_name" jdbcType="VARCHAR" property="provinceName" />
+    <result column="city_code" jdbcType="VARCHAR" property="cityCode" />
+    <result column="city_name" jdbcType="VARCHAR" property="cityName" />
+    <result column="district_code" jdbcType="VARCHAR" property="districtCode" />
+    <result column="district_name" jdbcType="VARCHAR" property="districtName" />
+    <result column="town_code" jdbcType="VARCHAR" property="townCode" />
+    <result column="town_name" jdbcType="VARCHAR" property="townName" />
+    <result column="day_time_period" jdbcType="VARCHAR" property="dayTimePeriod" />
+    <result column="day_time_period_start" jdbcType="TIMESTAMP" property="dayTimePeriodStart" />
+    <result column="day_time_period_end" jdbcType="TIMESTAMP" property="dayTimePeriodEnd" />
   </resultMap>
   <sql id="Base_Column_List">
     <!--
       WARNING - @mbg.generated
     -->
-    id, group_id, data_time, type, mix_data_id
+    id, group_id, data_time, type, mix_data_id, zone, pollution_degree, pollution_degree_index, 
+    mission_code, province_code, province_name, city_code, city_name, district_code, 
+    district_name, town_code, town_name, day_time_period, day_time_period_start, day_time_period_end
   </sql>
 </mapper>
\ No newline at end of file
diff --git a/src/test/kotlin/com/flightfeather/uav/Test.kt b/src/test/kotlin/com/flightfeather/uav/Test.kt
index ead18b4..eca3219 100644
--- a/src/test/kotlin/com/flightfeather/uav/Test.kt
+++ b/src/test/kotlin/com/flightfeather/uav/Test.kt
@@ -3,6 +3,7 @@
 import com.flightfeather.uav.common.utils.DateUtil
 import com.flightfeather.uav.common.utils.FileExchange
 import com.flightfeather.uav.common.utils.FileUtil
+import com.flightfeather.uav.common.utils.TimeUtil
 import com.flightfeather.uav.domain.entity.BaseRealTimeData
 import com.flightfeather.uav.domain.entity.Company
 import com.flightfeather.uav.domain.entity.GridDataDetail
@@ -152,4 +153,14 @@
 
         println(dataDetail)
     }
+
+    @Test
+    fun getDayTimeTag() {
+        val period = TimeUtil.getDayTimeTag(
+            Date(2024, 10, 10, 10, 25, 0),
+            Date(2024, 10, 10, 14, 40, 0)
+        )
+
+        println("${period?.first};${period?.second};${period?.third}")
+    }
 }
\ No newline at end of file
diff --git a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImplTest.kt b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImplTest.kt
index 151383a..3e11665 100644
--- a/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImplTest.kt
+++ b/src/test/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteDataCalculateServiceImplTest.kt
@@ -1,7 +1,12 @@
 package com.flightfeather.uav.lightshare.service.impl
 
+import com.flightfeather.uav.common.utils.TimeUtil
+import com.flightfeather.uav.domain.entity.GridData
 import com.flightfeather.uav.domain.entity.GridDataDetail
 import com.flightfeather.uav.domain.mapper.GridDataDetailMapper
+import com.flightfeather.uav.domain.mapper.GridDataMapper
+import com.flightfeather.uav.domain.mapper.MissionMapper
+import com.flightfeather.uav.lightshare.eunm.SatelliteDataType
 import com.flightfeather.uav.lightshare.service.SatelliteDataCalculateService
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -19,7 +24,13 @@
     lateinit var satelliteDataCalculateService: SatelliteDataCalculateService
 
     @Autowired
+    lateinit var gridDataMapper: GridDataMapper
+
+    @Autowired
     lateinit var gridDataDetailMapper: GridDataDetailMapper
+
+    @Autowired
+    lateinit var missionMapper: MissionMapper
 
     /**
      * 鍒锋柊姣忕粍鏁版嵁鐨勬暟鎹帓鍚�
@@ -62,13 +73,31 @@
     fun dataFusion() {
         val missionList =
             listOf(
-                "SH-CN-20241216",
-                "SH-CN-20241202",
-                "SH-CN-20241127",
-                "SH-CN-20241126-1",
-                "SH-CN-20241126-2",
-                "SH-CN-20241108",
-                "SH-CN-20240823"
+//                "SH-CN-20241216",
+//                "SH-CN-20241202",
+//                "SH-CN-20241127",
+//                "SH-CN-20241126-1",
+//                "SH-CN-20241126-2",
+//                "SH-CN-20241108",
+//                "SH-CN-20240823"
+                "SH-CN-20240723-01",
+                "SH-CN-20240723-02",
+                "SH-CN-20240830",
+                "SH-CN-20240906",
+                "SH-CN-20241204",
+                "SH-CN-20241210",
+                "SH-CN-20241213",
+                "SH-CN-20241218",
+                "SH-CN-20241220",
+                "SH-CN-20241224",
+                "SH-CN-20241226",
+                "SH-CN-20241227",
+                "SH-CN-20241231",
+                "SH-CN-20250106",
+                "SH-CN-20250108",
+                "SH-CN-20250113",
+                "SH-CN-20250116",
+                "SH-CN-20250120"
             )
         missionList.forEach { m ->
             satelliteDataCalculateService.dataFusion(m, 3)
@@ -77,7 +106,17 @@
     }
 
     @Test
-    fun splitDataAndDataFusion() {
+    fun refreshDayTimePeriod() {
+        gridDataMapper.select(GridData().apply { type = SatelliteDataType.Monitor.value.toByte() }).forEach { gd ->
+            missionMapper.selectByPrimaryKey(gd?.missionCode)?.let { m ->
+                TimeUtil.getDayTimeTag(m.startTime, m.endTime)?.let { p ->
+                    gd?.dayTimePeriod = p.first
+                    gd?.dayTimePeriodStart = p.second
+                    gd?.dayTimePeriodEnd = p.third
 
+                    gridDataMapper.updateByPrimaryKey(gd)
+                }
+            }
+        }
     }
 }
\ No newline at end of file

--
Gitblit v1.9.3