AdmViewModel.kt 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. package com.framework.mvvm.mv
  2. import android.content.SharedPreferences
  3. import android.util.Log
  4. import androidx.core.content.edit
  5. import androidx.lifecycle.ViewModel
  6. import androidx.lifecycle.viewModelScope
  7. import cn.sagacloud.cadengine.OkhttpUtil
  8. import com.framework.app.*
  9. import com.framework.app.http.FileInfo
  10. import com.framework.app.http.FileUploadInfo
  11. import com.framework.app.tools.md5
  12. import com.framework.app.tools.toBytes
  13. import com.framework.mvvm.model.data.Response
  14. import com.framework.mvvm.model.data.SuccessResponse
  15. import com.framework.mvvm.model.data.request
  16. import com.framework.mvvm.model.db.entity.task.ObjectEntity
  17. import com.framework.mvvm.model.repository.AdmRepository
  18. import com.framework.mvvm.model.vo.AdmRequest
  19. import com.framework.mvvm.model.vo.User
  20. import com.sybotan.android.demo.DemoApp
  21. import kotlinx.coroutines.Dispatchers
  22. import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
  23. import kotlinx.coroutines.flow.StateFlow
  24. import kotlinx.coroutines.flow.flow
  25. import kotlinx.coroutines.flow.stateIn
  26. import kotlinx.coroutines.launch
  27. import kotlinx.coroutines.withContext
  28. import okhttp3.RequestBody
  29. import okhttp3.RequestBody.Companion.toRequestBody
  30. import java.io.File
  31. import java.io.FileOutputStream
  32. class AdmViewModel(private val repository: AdmRepository) : ViewModel() {
  33. /**
  34. * 请求字典数据
  35. */
  36. fun requestDict(request: AdmRequest, block: (() -> Unit)? = null) {
  37. viewModelScope.launch {
  38. repository.requestDict(request)
  39. block?.invoke()
  40. }
  41. }
  42. /**
  43. * 请求配置信息
  44. */
  45. fun requestConfig(request: AdmRequest, block: (() -> Unit)? = null) {
  46. viewModelScope.launch {
  47. repository.requestConfig(request)
  48. block?.invoke()
  49. }
  50. }
  51. /**
  52. * 请求框架数据
  53. */
  54. fun requestFrame(request: AdmRequest, block: (() -> Unit)? = null) {
  55. viewModelScope.launch {
  56. repository.requestFrame(request)
  57. block?.invoke()
  58. }
  59. }
  60. /**
  61. * 上传建筑数据
  62. */
  63. fun uploadBuilding(block: (() -> Unit)? = null) {
  64. viewModelScope.launch(Dispatchers.IO) {
  65. val buildings = repository.getBuildings()
  66. if (buildings.isEmpty()) return@launch
  67. for (building in buildings) {
  68. repository.uploadBuilding(
  69. userId = "bdtp",
  70. groupCode = building.groupCode!!,
  71. projectId = building.projectId!!,
  72. buildingId = building.id
  73. )
  74. }
  75. withContext(Dispatchers.Main) {
  76. block?.invoke()
  77. }
  78. }
  79. }
  80. /**
  81. * 下载建筑数据
  82. */
  83. fun downloadBuilding(
  84. sp: SharedPreferences,
  85. isProject: Boolean = false,
  86. block: (() -> Unit)? = null
  87. ) {
  88. viewModelScope.launch(Dispatchers.IO) {
  89. val buildings = repository.getBuildings()
  90. println("downloadBuilding will download : ${buildings.size}")
  91. if (buildings.isEmpty()) {
  92. Log.d("downloadBuilding", "buildings is empty")
  93. return@launch
  94. }
  95. val job = launch { // 启动一个总协程
  96. for (building in buildings) {
  97. launch { // 为每个下载任务启动协程
  98. repository.requestBuilding(
  99. AdmRequest(
  100. userId = "bdtp",
  101. projectId = building.projectId!!,
  102. groupCode = building.groupCode!!,
  103. buildingId = if (isProject) "" else building.id,
  104. clientId = sp.getString(CLIENT_ID, "") ?: "",
  105. bdtpDownloadTs = sp.getLong(
  106. "${
  107. if (isProject)
  108. building.projectId
  109. else
  110. building.id
  111. }.$BDTP_TS",
  112. 0L
  113. ),
  114. admDownloadTs = sp.getLong(
  115. "${
  116. if (isProject)
  117. building.projectId
  118. else
  119. building.id
  120. }.$ADM_TS",
  121. 0L
  122. )
  123. )
  124. ) {
  125. Log.e(
  126. "downloadBuilding",
  127. "bdtpDownloadTs:${it.bdtpDownloadTs}, admDownloadTs:${it.admDownloadTs}"
  128. )
  129. sp.edit {
  130. putLong(
  131. "${if (isProject) building.projectId else building.id}.$BDTP_TS",
  132. it.bdtpDownloadTs
  133. )
  134. }
  135. sp.edit {
  136. putLong(
  137. "${if (isProject) building.projectId else building.id}.$ADM_TS",
  138. it.admDownloadTs
  139. )
  140. }
  141. }
  142. }
  143. }
  144. }
  145. job.join()
  146. // 下载地图
  147. val gzipJob = launch {
  148. val floors = repository.getFloors()
  149. floors.forEach {
  150. launch(Dispatchers.IO) {
  151. val json = it.infos?.asJsonObject
  152. val floorMap = json?.get("floorMap")?.asString ?: ""
  153. if (floorMap.isNotEmpty()) {
  154. val mapString = OkhttpUtil.getGzipMap("$IP$pathDownloadMap${floorMap}")
  155. val mapFile =
  156. File(DemoApp.getInstance()?.getExternalFilesDir("floorMap"), it.id)
  157. FileOutputStream(mapFile).use { output -> output.write(mapString.toByteArray()) }
  158. it.floorMap = mapFile.absolutePath
  159. repository.updateObject(it)
  160. }
  161. }
  162. }
  163. }
  164. gzipJob.join()
  165. withContext(Dispatchers.Main) {
  166. block?.invoke()
  167. }
  168. }
  169. }
  170. /**
  171. * 获取建筑数量
  172. */
  173. val buildings: StateFlow<List<ObjectEntity>> = flow {
  174. emit(repository.getBuildings())
  175. }.stateIn(
  176. scope = viewModelScope,
  177. started = WhileSubscribed(5000),
  178. initialValue = arrayListOf()
  179. )
  180. /**
  181. * 获取本地数据中的建筑信息
  182. */
  183. suspend fun getBuildings(): List<ObjectEntity> {
  184. return repository.getBuildings()
  185. }
  186. /**
  187. * 获取文件上传信息
  188. */
  189. private suspend fun getFileUploadInfo(basic: FileInfo): Response<FileUploadInfo> {
  190. return request { repository.getFileUploadInfo(basic) }
  191. }
  192. /**
  193. * 上传文件
  194. */
  195. private suspend fun uploadFile(url: String, file: RequestBody): String {
  196. return repository.uploadFile(url, file)
  197. }
  198. /**
  199. * 上传文件
  200. */
  201. fun fileUpload(file: File) {
  202. val bytes = file.toBytes()
  203. val md5 = md5(bytes)
  204. val info = FileInfo(
  205. fileMd5 = md5,
  206. fileName = file.name,
  207. fileSize = bytes.size
  208. )
  209. viewModelScope.launch(Dispatchers.IO) {
  210. val response = getFileUploadInfo(info)
  211. if (response is SuccessResponse) {
  212. val data = response.data
  213. val url = data.content?.get(0)?.uploadUrl ?: ""
  214. if (url.isNotEmpty()) {
  215. val body = bytes.toRequestBody()
  216. val result = uploadFile(url, body)
  217. Log.d("fileUpload", "success: $result")
  218. }
  219. } else {
  220. Log.d("fileUpload", "upload file has something error:$response")
  221. }
  222. }
  223. }
  224. /**
  225. * 获取服务端生成的客户端Id
  226. */
  227. fun getClient(user: User) {
  228. viewModelScope.launch {
  229. repository.getClient(user)
  230. }
  231. }
  232. }