1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
package com.flightfeather.uav.lightshare.service.impl
 
import com.flightfeather.uav.common.exception.BizException
import com.flightfeather.uav.common.utils.FileExchange
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.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.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
 
/**
 *
 * @date 2024/12/5
 * @author feiyu02
 */
@Service
class SatelliteTelemetryServiceImpl(private val satelliteGridRep: SatelliteGridRep) : 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)
        return DataHead(pageInfo.pageNum, pageInfo.pages) to res
    }
 
    override fun fetchGridCell(groupId: Int): List<GridCell?> {
        return satelliteGridRep.fetchGridCell(groupId)
    }
 
    override fun fetchGridData(groupId: Int, dataTime: LocalDateTime?, type: Int?): List<GridData?> {
        return satelliteGridRep.fetchGridData(groupId, dataTime, type)
    }
 
    override fun fetchGridDataDetail(dataId: Int, groupId: Int?, cellId: Int?): List<GridDataDetail?> {
        return satelliteGridRep.fetchGridDataDetail(dataId, groupId, cellId)
    }
 
    override fun importGridData(groupId: Int, type: Int?, dataTime: LocalDateTime?, update: Int?, file: MultipartFile): GridDataImportResult? {
        val gridData = satelliteGridRep.fetchGridData(groupId, dataTime, type)
        if (!file.contentType!!.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")) {
            throw BizException("文件类型错误,请上传xlsx类型文件")
        }
        if (gridData.isNotEmpty() && update == 0) {
            return GridDataImportResult(false, "数据库对应网格组和日期下已存在遥测数据")
        }
        val exchangeGridDataDetails
                = fileExchange.exchangeGridData(ByteArrayInputStream(file.bytes))
        val gridCellsInDB = satelliteGridRep.fetchGridCell(groupId)
        val setA = gridCellsInDB.asSequence().map { it?.id ?: -1 }.toSet()
        val setB = exchangeGridDataDetails.asSequence().map { it.cellId ?: -1 }.toSet()
        // excel 中缺少的的单元格
        val onlyInA = setA - setB
        // excel 中多出的的单元格
        val onlyInB = setB - setA
        if (onlyInA.isNotEmpty()) {
            throw BizException("导入数据中缺少以下网格单元格:${onlyInA.joinToString(",")}")
        }
        if (onlyInB.isNotEmpty()) {
            throw BizException("导入数据中有多余网格单元格:${onlyInB.joinToString(",")}")
        }
        if (update == 1) {
            exchangeGridDataDetails.forEach {
                it.dataId = gridData[0]?.id
                it.groupId = gridData[0]?.groupId
            }
            satelliteGridRep.updatePM25Batch(exchangeGridDataDetails)
            return GridDataImportResult(true, "覆盖成功")
        }
        val gridDataEntity = GridData()
        gridDataEntity.groupId = groupId
        gridDataEntity.dataTime = dataTime?.atZone(ZoneId.systemDefault())?.toInstant()?.toEpochMilli()
            ?.let { Date(it) }
        gridDataEntity.type = type?.toByte()
        satelliteGridRep.insertGridDataAndDetail(gridDataEntity, exchangeGridDataDetails)
        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
    }
}