From 6c1e7c5ac983301c34f003415cda2ef7c7e176a6 Mon Sep 17 00:00:00 2001 From: feiyu02 <risaku@163.com> Date: 星期四, 09 一月 2025 17:34:11 +0800 Subject: [PATCH] 1. 新增卫星遥测网格4个顶点坐标计算逻辑 --- src/main/kotlin/com/flightfeather/uav/lightshare/service/impl/SatelliteTelemetryServiceImpl.kt | 201 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 199 insertions(+), 2 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..3e24c07 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,5 +1,10 @@ package com.flightfeather.uav.lightshare.service.impl +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.GridAod import com.flightfeather.uav.domain.entity.GridCell import com.flightfeather.uav.domain.entity.GridData import com.flightfeather.uav.domain.entity.GridDataDetail @@ -7,10 +12,19 @@ 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.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,8 +32,12 @@ * @author feiyu02 */ @Service -class SatelliteTelemetryServiceImpl(private val satelliteGridRep: SatelliteGridRep) : SatelliteTelemetryService { +class SatelliteTelemetryServiceImpl( + private val satelliteGridRep: SatelliteGridRep, + private val satelliteDataMix: SatelliteDataMix, +) : SatelliteTelemetryService { + private val fileExchange = FileExchange() override fun fetchGridGroup(areaVo: AreaVo, page: Int?, perPage: Int?): Pair<DataHead, List<GridGroup?>> { val pageInfo = PageHelper.startPage<GridGroup>(page ?: 1, perPage ?: 100) val res = satelliteGridRep.fetchGridGroup(areaVo) @@ -34,7 +52,186 @@ return satelliteGridRep.fetchGridData(groupId, dataTime, type) } + override fun fetchGridAod(groupId: Int, dataTime: LocalDateTime?): List<GridAod?> { + return satelliteGridRep.fetchGridAod(groupId, dataTime) + } + 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 * 100) / 100 + } + } + return res + } + + @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.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 calGridVertex(groupId: Int): List<GridCell?> { + val cellList = satelliteGridRep.fetchGridCell(groupId) + val vertexList = SatelliteGridManage.calGridVertex(cellList.map { + if (it?.longitude == null || it.latitude == null) { + throw BizException("鍗槦閬ユ祴缃戞牸璁$畻椤剁偣鍧愭爣鐐瑰け璐ワ紝瀛樺湪涓績鐐瑰潗鏍囦负绌虹殑鎯呭喌") + } + it.longitude?.toDouble()!! to it.latitude?.toDouble()!! + }) + + cellList.forEachIndexed { i, c -> + val v = vertexList[i] + c?.point1Lon = v.point1Lon.toBigDecimal() + c?.point1Lat = v.point1Lat.toBigDecimal() + + c?.point2Lon = v.point2Lon.toBigDecimal() + c?.point2Lat = v.point2Lat.toBigDecimal() + + c?.point3Lon = v.point3Lon.toBigDecimal() + c?.point3Lat = v.point3Lat.toBigDecimal() + + c?.point4Lon = v.point4Lon.toBigDecimal() + c?.point4Lat = v.point4Lat.toBigDecimal() + } + + satelliteGridRep.updateGridCellBatch(cellList) + + return cellList } } \ No newline at end of file -- Gitblit v1.9.3