From eb3dd00b0b7fcda477229d518d250f9c842b790b Mon Sep 17 00:00:00 2001
From: feiyu02 <risaku@163.com>
Date: 星期二, 21 十月 2025 17:45:44 +0800
Subject: [PATCH] 2025.10.21 1. 走航季度报告相关数据计算逻辑调整
---
src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt | 236 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 228 insertions(+), 8 deletions(-)
diff --git a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt
index 60ef723..33c310e 100644
--- a/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt
+++ b/src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt
@@ -1,16 +1,27 @@
package com.flightfeather.uav.lightshare.service.impl
-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.biz.satellite.SatelliteDataMix
+import com.flightfeather.uav.biz.satellite.SatelliteGridManage
+import com.flightfeather.uav.common.exception.BizException
+import com.flightfeather.uav.common.utils.FileExchange
+import com.flightfeather.uav.domain.entity.*
import com.flightfeather.uav.domain.repository.SatelliteGridRep
import com.flightfeather.uav.lightshare.bean.AreaVo
import com.flightfeather.uav.lightshare.bean.DataHead
+import com.flightfeather.uav.lightshare.bean.GridDataImportResult
+import com.flightfeather.uav.lightshare.eunm.SatelliteDataType
import com.flightfeather.uav.lightshare.service.SatelliteTelemetryService
import com.github.pagehelper.PageHelper
import org.springframework.stereotype.Service
+import org.springframework.transaction.annotation.Transactional
+import org.springframework.web.multipart.MultipartFile
+import java.io.ByteArrayInputStream
+import java.io.File
import java.time.LocalDateTime
+import java.time.ZoneId
+import java.util.*
+import javax.servlet.http.HttpServletResponse
+import kotlin.math.round
/**
*
@@ -18,12 +29,21 @@
* @author feiyu02
*/
@Service
-class SatelliteTelemetryServiceImpl(private val satelliteGridRep: SatelliteGridRep) : SatelliteTelemetryService {
+class SatelliteTelemetryServiceImpl(
+ private val satelliteGridRep: SatelliteGridRep,
+ private val satelliteDataMix: SatelliteDataMix,
+) : SatelliteTelemetryService {
- override fun fetchGridGroup(areaVo: AreaVo, page: Int?, perPage: Int?): Pair<DataHead, List<GridGroup?>> {
+ private val fileExchange = FileExchange()
+ override fun fetchGridGroup(areaVo: AreaVo, type: String?, page: Int?, perPage: Int?): Pair<DataHead,
+ List<GridGroup?>> {
val pageInfo = PageHelper.startPage<GridGroup>(page ?: 1, perPage ?: 100)
- val res = satelliteGridRep.fetchGridGroup(areaVo)
+ val res = satelliteGridRep.fetchGridGroup(areaVo, type)
return DataHead(pageInfo.pageNum, pageInfo.pages) to res
+ }
+
+ override fun deleteGridGroup(groupId: Int) {
+ satelliteGridRep.deleteGridGroup(groupId)
}
override fun fetchGridCell(groupId: Int): List<GridCell?> {
@@ -34,7 +54,207 @@
return satelliteGridRep.fetchGridData(groupId, dataTime, type)
}
+ override fun fetchGridData(gridData: GridData): List<GridData?> {
+ return satelliteGridRep.fetchGridData(gridData)
+ }
+
+ override fun deleteGridData(dataId: Int): Boolean {
+ try {
+ satelliteGridRep.deleteGridData(dataId)
+ } catch (e: Exception) {
+ // todo: 鍔犲叆鏃ュ織瀛樺偍閫昏緫
+ return false
+ }
+ return true
+ }
+
override fun fetchGridDataDetail(dataId: Int, groupId: Int?, cellId: Int?): List<GridDataDetail?> {
- return satelliteGridRep.fetchGridDataDetail(dataId, groupId, cellId)
+ val res = satelliteGridRep.fetchGridDataDetail(dataId, groupId, cellId)
+ res.forEach {
+ if (it?.pm25 != null) {
+ it.pm25 = round(it.pm25 * 10) / 10
+ }
+ }
+ return res
+ }
+
+ @Transactional
+ override fun createGridDataAndDataDetail(
+ groupId: Int,
+ dataTime: LocalDateTime?,
+ gridDataDetail: List<GridDataDetail>,
+ ): Boolean {
+ // 淇濆瓨鎷熷悎鐨勫崼鏄熼仴娴嬫暟鎹� type濮嬬粓涓�0
+ val type = SatelliteDataType.Original.value
+
+ // 鏌ユ壘鏄惁鏈夊巻鍙茶褰�
+ val gridData = satelliteGridRep.fetchGridData(groupId, dataTime, type)
+ // 鏃犲巻鍙茶褰曞垯鍒涘缓鏁版嵁绱㈠紩GridData锛屼箣鍚庡啀瀛樺叆鎷熷悎鐨勬暟鎹�
+ if (gridData.isEmpty()) {
+ val gridDataEntity = GridData()
+ gridDataEntity.groupId = groupId
+ gridDataEntity.dataTime = dataTime?.atZone(ZoneId.systemDefault())?.toInstant()?.toEpochMilli()
+ ?.let { Date(it) }
+ gridDataEntity.type = type.toByte()
+ satelliteGridRep.insertGridDataAndDetail(gridDataEntity, gridDataDetail)
+ }
+ // 鏇存柊鍘嗗彶鏁版嵁
+ else {
+ gridDataDetail.forEach {
+ it.dataId = gridData[0]?.id
+ it.groupId = gridData[0]?.groupId
+ }
+ satelliteGridRep.updatePM25Batch(gridDataDetail)
+ }
+
+ return true
+ }
+
+ @Transactional
+ override fun mixGridData(dataIdList: List<Int>): List<GridData?> {
+ if (dataIdList.isEmpty()) throw BizException("铻嶅悎鎵�闇�鏁版嵁id涓嶈兘涓虹┖")
+ // 1. 鏍规嵁鏁版嵁涓婚敭id鏁扮粍锛屾煡璇㈣缁勫悎涓嬫槸鍚﹀凡鏈夋暟鎹瀺鍚堣褰�
+ val exist = satelliteGridRep.fetchGridData(GridData().apply {
+ type = 1
+ mixDataId = dataIdList.sorted().joinToString(",")
+ })
+ // 2. 鑻ヨ瀺鍚堟暟鎹凡瀛樺湪锛岀洿鎺ヨ繑鍥�
+ return exist.ifEmpty {
+ listOf(satelliteDataMix.mixData(dataIdList).first)
+ }
+ }
+
+ override fun importGridData(groupId: Int, dataTime: LocalDateTime?, update: Boolean, file: MultipartFile): GridDataImportResult? {
+ // 鍥犱负鏄鍏ュ崼鏄熼仴娴嬫暟鎹� type濮嬬粓涓�0
+ val type = 0
+ // 棣栧厛鍒ゆ柇鏂囦欢绫诲瀷锛屾枃浠剁被鍨嬩笉鏄痻lsx鐩存帴鎶ラ敊
+ if (!file.contentType!!.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
+ throw BizException("鏂囦欢绫诲瀷閿欒锛岃涓婁紶xlsx绫诲瀷鏂囦欢")
+ }
+ // 鏍¢獙 鐢ㄦ埛鏇存柊鎸囦护 鍜� 鏁版嵁搴撲腑缃戞牸鏁版嵁瀛樺湪涓庡惁 鏄惁鍖归厤锛屼笉鍖归厤鎶涘嚭閿欒
+ // 杩欎釜杩囩▼闇�瑕佹煡璇㈡暟鎹簱涓綉鏍肩粍鏁版嵁
+ val gridData = satelliteGridRep.fetchGridData(groupId, dataTime, type)
+ // 灏嗙敤鎴峰鍏ョ殑鏂囦欢杞崲涓烘暟鎹�
+ // 杞崲鐨勮繃绋嬮渶瑕佺綉鏍煎崟鍏冩牸鏁版嵁 浠ュ垽鏂綉鏍煎崟鍏冩牸鏄惁鍦ㄦ纭殑鑼冨洿鍐�
+ val gridCellsInDBSet = satelliteGridRep.fetchGridCell(groupId).asSequence().map { it?.id ?: -1 }.toSet()
+ val importData
+ = fileExchange.exchangeGridData(ByteArrayInputStream(file.bytes), gridCellsInDBSet)
+ if (update) {
+ // 鐢ㄦ埛闇�瑕佹墽琛屾洿鏂�
+ if (gridData.isEmpty()) {
+ throw BizException("鎸囦护閿欒锛屾暟鎹簱瀵瑰簲缃戞牸缁勫拰鏃ユ湡涓嬩笉瀛樺湪閬ユ祴鏁版嵁锛岃鎵ц鎻掑叆鎿嶄綔")
+ }
+ importData.forEach {
+ it.dataId = gridData[0]?.id
+ it.groupId = gridData[0]?.groupId
+ }
+ satelliteGridRep.updatePM25Batch(importData)
+ return GridDataImportResult(true, "瑕嗙洊鎴愬姛")
+ }else {
+ // 鐢ㄦ埛闇�瑕佹墽琛屾彃鍏�
+ if (gridData.isNotEmpty()) {
+ throw BizException("鎸囦护閿欒锛屾暟鎹簱瀵瑰簲缃戞牸缁勫拰鏃ユ湡涓嬪凡瀛樺湪閬ユ祴鏁版嵁锛岃鎵ц鏇存柊鎿嶄綔")
+ }
+ val gridDataEntity = GridData()
+ gridDataEntity.groupId = groupId
+ gridDataEntity.dataTime = dataTime?.atZone(ZoneId.systemDefault())?.toInstant()?.toEpochMilli()
+ ?.let { Date(it) }
+ gridDataEntity.type = type.toByte()
+ satelliteGridRep.insertGridDataAndDetail(gridDataEntity, importData)
+ return GridDataImportResult(true, "瀵煎叆鎴愬姛")
+ }
+ }
+
+ override fun downloadTemplate(response: HttpServletResponse): Boolean {
+ val fileName = "GridData-PM2.5-Template.xlsx"
+ val path = (Thread.currentThread().contextClassLoader?.getResource("/")?.path
+ ?: "src/main/resources") + "/templates/" + fileName
+ val file = File(path)
+ if (file.exists()) {
+ val fName = Base64.getEncoder().encodeToString(fileName.toByteArray())
+ response.apply {
+ setHeader("Content-Disposition", "attachment;filename=$fName")
+ setHeader("fileName", fName)
+ addHeader("Access-Control-Expose-Headers", "fileName")
+ contentType = "application/vnd.ms-excel;charset=UTF-8"
+ setHeader("Pragma", "no-cache")
+ setHeader("Cache-Control", "no-cache")
+ setDateHeader("Expires", 0)
+ }
+ response.outputStream.write(file.readBytes())
+ }
+ return true
+ }
+
+ override fun importGridAOD(
+ groupId: Int,
+ dataTime: LocalDateTime?,
+ update: Boolean,
+ file: MultipartFile
+ ): GridDataImportResult? {
+ // 棣栧厛鍒ゆ柇鏂囦欢绫诲瀷锛屾枃浠剁被鍨嬩笉鏄痻lsx鐩存帴鎶ラ敊
+ if (!file.contentType!!.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
+ throw BizException("鏂囦欢绫诲瀷閿欒锛岃涓婁紶xlsx绫诲瀷鏂囦欢")
+ }
+ // 鏍¢獙 鐢ㄦ埛鏇存柊鎸囦护 鍜� 鏁版嵁搴撲腑缃戞牸鏁版嵁瀛樺湪涓庡惁 鏄惁鍖归厤锛屼笉鍖归厤鎶涘嚭閿欒
+ // 杩欎釜杩囩▼闇�瑕佹煡璇㈡暟鎹簱涓綉鏍肩粍鏁版嵁
+ val gridAod = satelliteGridRep.fetchGridAod(groupId, dataTime)
+ // 灏嗙敤鎴峰鍏ョ殑鏂囦欢杞崲涓烘暟鎹�
+ // 杞崲鐨勮繃绋嬮渶瑕佺綉鏍煎崟鍏冩牸鏁版嵁 浠ュ垽鏂綉鏍煎崟鍏冩牸鏄惁鍦ㄦ纭殑鑼冨洿鍐�
+ val gridCellsInDBSet = satelliteGridRep.fetchGridCell(groupId).asSequence().map { it?.id ?: -1 }.toSet()
+ val importAod
+ = fileExchange.exchangeGridAod(ByteArrayInputStream(file.bytes), gridCellsInDBSet)
+ if (update) {
+ // 鐢ㄦ埛闇�瑕佹墽琛屾洿鏂�
+ if (gridAod.isEmpty()) {
+ throw BizException("鎸囦护閿欒锛屾暟鎹簱瀵瑰簲缃戞牸缁勫拰鏃ユ湡涓嬩笉瀛樺湪AOD鏁版嵁锛岃鎵ц鎻掑叆鎿嶄綔")
+ }
+ importAod.forEach {
+ it.aodId = gridAod[0]?.id
+ it.groupId = gridAod[0]?.groupId
+ }
+ satelliteGridRep.updateGridAodBatch(importAod)
+ return GridDataImportResult(true, "瑕嗙洊鎴愬姛")
+ }else {
+ // 鐢ㄦ埛闇�瑕佹墽琛屾彃鍏�
+ if (gridAod.isNotEmpty()) {
+ throw BizException("鎸囦护閿欒锛屾暟鎹簱瀵瑰簲缃戞牸缁勫拰鏃ユ湡涓嬪凡瀛樺湪AOD鏁版嵁锛岃鎵ц鏇存柊鎿嶄綔")
+ }
+ val gridAodEntity = GridAod()
+ gridAodEntity.groupId = groupId
+ gridAodEntity.dataTime = dataTime?.atZone(ZoneId.systemDefault())?.toInstant()?.toEpochMilli()
+ ?.let { Date(it) }
+ satelliteGridRep.insertGridAodAndDetail(gridAodEntity, importAod)
+ return GridDataImportResult(true, "瀵煎叆鎴愬姛")
+ }
+ }
+
+ override fun downloadAODTemplate(response: HttpServletResponse): Boolean {
+ val fileName = "GridData-AOD-Template.xlsx"
+ val path = (Thread.currentThread().contextClassLoader?.getResource("/")?.path
+ ?: "src/main/resources") + "/templates/" + fileName
+ val file = File(path)
+ if (file.exists()) {
+ val fName = Base64.getEncoder().encodeToString(fileName.toByteArray())
+ response.apply {
+ setHeader("Content-Disposition", "attachment;filename=$fName")
+ setHeader("fileName", fName)
+ addHeader("Access-Control-Expose-Headers", "fileName")
+ contentType = "application/vnd.ms-excel;charset=UTF-8"
+ setHeader("Pragma", "no-cache")
+ setHeader("Cache-Control", "no-cache")
+ setDateHeader("Expires", 0)
+ }
+ response.outputStream.write(file.readBytes())
+ }
+ return true
+ }
+
+ override fun fetchGridAod(groupId: Int, dataTime: LocalDateTime?): List<GridAod?> {
+ return satelliteGridRep.fetchGridAod(groupId, dataTime)
+ }
+
+ override fun fetchGridAODDetail(aodId: Int, groupId: Int?, cellId: Int?): List<GridAodDetail?> {
+ return satelliteGridRep.fetchGridAodDetail(aodId, groupId, cellId)
}
}
\ No newline at end of file
--
Gitblit v1.9.3