道路线索应急巡查系统服务后台
feiyu02
2025-04-22 41548e262362faf603a71e066e01bd4ef46619d2
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package com.flightfeather.grid.external
 
import com.flightfeather.grid.config.exception.BizException
import com.flightfeather.grid.domain.ds1.entity.ClueConclusion
import com.flightfeather.grid.domain.ds1.entity.ClueQuestion
import com.flightfeather.grid.domain.ds1.mapper.ClueConclusionMapper
import com.flightfeather.grid.domain.ds1.mapper.ClueQuestionMapper
import com.flightfeather.grid.external.vo.ClueConclusionDto
import com.flightfeather.grid.external.vo.ClueQuestionDto
import com.flightfeather.grid.external.vo.ClueDto
import com.flightfeather.grid.utils.net.GsonUtils
import com.flightfeather.grid.utils.net.HttpMethod
import com.google.gson.Gson
import com.google.gson.JsonElement
import com.google.gson.JsonParser
import org.apache.commons.codec.digest.DigestUtils
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.MultipartEntityBuilder
import org.apache.http.util.EntityUtils
import org.springframework.beans.factory.annotation.Value
import org.springframework.scheduling.annotation.Async
import org.springframework.stereotype.Component
import java.io.File
import java.nio.charset.Charset
import java.util.*
 
@Component
class ClueHttpService(
    val clueConclusionMapper: ClueConclusionMapper,
    val clueQuestionMapper: ClueQuestionMapper,
) {
 
    companion object {
        private const val TAG = "ClueHttpService"
        private const val TOKEN = "e6dc8bb9e1ff0ce973fb92b4af2e4c3f"
    }
    private val httpMethod: HttpMethod = HttpMethod("101.230.224.80", 8082)
 
    @Value("\${imgPath}")
    lateinit var imgPath: String
 
    data class ClueResponse<T>(
        val code: String,
        val message: String,
        val data: T,
    )
 
    /**
     * 统一请求头
     */
    fun headTimeStamp(): List<Pair<String, String>> {
        val nowS = Date().time / 1000
        val t = nowS - 20
        val now = t.toString()
        val key = "$now$TOKEN"
        val sign = DigestUtils.md5Hex(key)
        return listOf(
            Pair("JA-TIMESTAMP", now),
            Pair("JA-TOKEN", TOKEN),
            Pair("JA-SIGN", sign)
        )
    }
 
    /**
     * 返回校验结果
     */
    private fun resCheck(res: HttpMethod.MyResponse): JsonElement {
        val str = EntityUtils.toString(res.m.entity)
        val json = JsonParser.parseString(str)
        if (!json.isJsonObject) throw IllegalStateException("$TAG: 返回值不是一个object")
        val jo = json.asJsonObject
        return if (res.success) {
            if (jo["code"].asInt != 20000) throw IllegalStateException(jo["message"].asString)
//            if (!jo["data"].isJsonObject) throw IllegalStateException("$TAG: data字段不存在或不是object结构")
            jo["data"]
        } else {
            throw IllegalStateException("第三方接口网路链接错误,状态码:${res.m.statusLine.statusCode},错误:${jo["message"].asString}")
        }
    }
 
    /**
     * 获取下发线索
     */
    fun getClue(updateTime: String): List<ClueDto> {
        val time = updateTime.replace(" ", "%20")
//        val time = updateTime
        try {
            val res = httpMethod.get("/feedback/queryYxfListNew", listOf(Pair("updateTime", time)), headTimeStamp())
            val data = resCheck(res).asJsonArray
            return GsonUtils.parserJsonToArrayBeans(data.toString(), ClueDto::class.java)
        } catch (e: Exception) {
            throw BizException(e.message, e.cause)
        }
    }
 
    fun getClueFile(clueId: String): HttpMethod.MyResponse {
        try {
            return httpMethod.get("/feedback/getPDFNew", listOf(Pair("id", clueId)), headTimeStamp())
        } catch (e: Exception) {
            throw BizException(e.message, e.cause)
        }
    }
 
    /**
     * 上报线索结论
     */
//    @Async
    fun uploadConclusion(clueConclusion: ClueConclusion): Boolean {
        val vo = ClueConclusionDto(clueConclusion)
        val dataJson = Gson().toJson(vo)
        try {
            val res = httpMethod.post("/feedback/thirdReportNew", dataJson, headTimeStamp())
            resCheck(res)
            clueConclusion.ccUploaded = true
            clueConclusion.ccUploadTime = Date()
            clueConclusionMapper.updateByPrimaryKeySelective(clueConclusion)
            return true
        } catch (e: Exception) {
            throw BizException(e.message, e.cause)
        }
    }
 
    /**
     * 上报线索问题
     */
//    @Async
    fun uploadQuestion(clueQuestion: ClueQuestion): Boolean {
        val vo = ClueQuestionDto(clueQuestion, imgPath)
 
        val builder = MultipartEntityBuilder.create()
        builder.setCharset(Charset.forName("utf-8"))
        val contentType = ContentType.create("multipart/form-data", Charset.forName("utf-8"))
 
        builder.addTextBody("clueId", vo.clueId.toString(), contentType)
        builder.addTextBody("questionName", vo.questionName, contentType)
        builder.addTextBody("questionDescription", vo.questionDescription, contentType)
        builder.addTextBody("street", vo.street, contentType)
        builder.addTextBody("address", vo.address, contentType)
        builder.addTextBody("lon", vo.lon.toString(), contentType)
        builder.addTextBody("lat", vo.lat.toString(), contentType)
        vo.filePaths?.forEach {
            val f = File(it)
            builder.addBinaryBody("file", f, contentType, f.name)
        }
 
        val entity = builder.build()
        try {
            val res = httpMethod.post("/feedback/questionReportNew", entity, headTimeStamp())
            resCheck(res)
            clueQuestion.cqUploaded = true
            clueQuestion.cqUploadTime = Date()
            clueQuestionMapper.updateByPrimaryKeySelective(clueQuestion)
            return true
        } catch (e: Exception) {
            throw BizException(e.message, e.cause)
        }
    }
}