AdmViewModel.kt 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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.Data
  14. import com.framework.mvvm.model.data.Response
  15. import com.framework.mvvm.model.data.SuccessResponse
  16. import com.framework.mvvm.model.data.request
  17. import com.framework.mvvm.model.db.entity.ProjectEntity
  18. import com.framework.mvvm.model.db.entity.UserEntity
  19. import com.framework.mvvm.model.db.entity.task.ObjectEntity
  20. import com.framework.mvvm.model.repository.AdmRepository
  21. import com.framework.mvvm.model.vo.AdmRequest
  22. import com.framework.mvvm.model.vo.Building
  23. import com.framework.mvvm.model.vo.Client
  24. import com.framework.mvvm.model.vo.Login
  25. import com.sybotan.android.demo.DemoApp
  26. import com.sybotan.android.demo.tools.LocalDataOperation
  27. import com.yuyh.library.imgsel.utils.LogUtils
  28. import kotlinx.coroutines.Dispatchers
  29. import kotlinx.coroutines.async
  30. import kotlinx.coroutines.flow.*
  31. import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
  32. import kotlinx.coroutines.launch
  33. import kotlinx.coroutines.withContext
  34. import okhttp3.RequestBody
  35. import okhttp3.RequestBody.Companion.toRequestBody
  36. import java.io.File
  37. import java.io.FileOutputStream
  38. class AdmViewModel(private val repository: AdmRepository) : ViewModel() {
  39. /**
  40. * 请求字典数据
  41. */
  42. fun requestDict(request: AdmRequest, block: (() -> Unit)? = null) {
  43. viewModelScope.launch {
  44. repository.requestDict(request)
  45. block?.invoke()
  46. }
  47. }
  48. /**
  49. * 请求配置信息
  50. */
  51. fun requestConfig(request: AdmRequest, block: (() -> Unit)? = null) {
  52. viewModelScope.launch {
  53. repository.requestConfig(request)
  54. block?.invoke()
  55. }
  56. }
  57. /**
  58. * 请求框架数据
  59. */
  60. fun requestFrame(request: AdmRequest, block: (() -> Unit)? = null) {
  61. viewModelScope.launch {
  62. repository.requestFrame(request)
  63. block?.invoke()
  64. }
  65. }
  66. /**
  67. * 上传建筑数据
  68. */
  69. fun uploadBuilding(
  70. request: AdmRequest,
  71. block: (() -> Unit)? = null,
  72. log: ((String, Building?) -> Unit)? = null
  73. ) {
  74. viewModelScope.launch(Dispatchers.IO) {
  75. //val buildings = repository.getBuildings()
  76. val buildings = repository.getBuildingByProjectId(request.projectId)
  77. if (buildings.isEmpty()) return@launch
  78. for (building in buildings) {
  79. repository.uploadBuilding(
  80. userId = request.userId,
  81. groupCode = building.groupCode!!,
  82. projectId = building.projectId!!,
  83. buildingId = building.id,
  84. log = log
  85. )
  86. }
  87. withContext(Dispatchers.Main) {
  88. block?.invoke()
  89. }
  90. }
  91. }
  92. /**
  93. * 下载建筑数据
  94. */
  95. fun downloadBuilding(
  96. request: AdmRequest,
  97. sp: SharedPreferences,
  98. isProject: Boolean = false,
  99. block: (() -> Unit)? = null
  100. ) {
  101. viewModelScope.launch(Dispatchers.IO) {
  102. //val buildings = repository.getBuildings()
  103. val buildings = repository.getBuildingByProjectId(request.projectId)
  104. println("downloadBuilding will download : ${buildings.size}")
  105. if (buildings.isEmpty()) {
  106. Log.d("downloadBuilding", "buildings is empty")
  107. return@launch
  108. }
  109. val job = launch { // 启动一个总协程
  110. for (building in buildings) {
  111. launch { // 为每个下载任务启动协程
  112. repository.requestBuilding(
  113. AdmRequest(
  114. userId = request.userId,
  115. projectId = building.projectId!!,
  116. groupCode = building.groupCode!!,
  117. buildingId = if (isProject) "" else building.id,
  118. clientId = sp.getString(CLIENT_ID, "") ?: "",
  119. bdtpDownloadTs = sp.getLong(
  120. "${
  121. if (isProject)
  122. building.projectId
  123. else
  124. building.id
  125. }.$BDTP_TS",
  126. 0L
  127. ),
  128. admDownloadTs = sp.getLong(
  129. "${
  130. if (isProject)
  131. building.projectId
  132. else
  133. building.id
  134. }.$ADM_TS",
  135. 0L
  136. )
  137. )
  138. ) {
  139. Log.e(
  140. "downloadBuilding",
  141. "bdtpDownloadTs:${it.bdtpDownloadTs}, admDownloadTs:${it.admDownloadTs}"
  142. )
  143. sp.edit {
  144. putLong(
  145. "${if (isProject) building.projectId else building.id}.$BDTP_TS",
  146. it.bdtpDownloadTs
  147. )
  148. }
  149. sp.edit {
  150. putLong(
  151. "${if (isProject) building.projectId else building.id}.$ADM_TS",
  152. it.admDownloadTs
  153. )
  154. }
  155. }
  156. }
  157. }
  158. }
  159. job.join()
  160. // 下载地图
  161. val gzipJob = launch {
  162. val floors = repository.getFloors()
  163. floors.forEach {
  164. launch(Dispatchers.IO) {
  165. val json = it.infos?.asJsonObject
  166. val floorMap = json?.get("floorMap")?.asString ?: ""
  167. if (floorMap.isNotEmpty()) {
  168. val mapString = OkhttpUtil.getGzipMap("$IP$pathDownloadMap${floorMap}")
  169. val mapFile =
  170. File(DemoApp.getInstance()?.getExternalFilesDir("floorMap"), it.id)
  171. FileOutputStream(mapFile).use { output -> output.write(mapString.toByteArray()) }
  172. it.floorMap = mapFile.absolutePath
  173. repository.updateObject(it)
  174. }
  175. }
  176. }
  177. }
  178. gzipJob.join()
  179. withContext(Dispatchers.Main) {
  180. block?.invoke()
  181. }
  182. }
  183. }
  184. /**
  185. * 获取建筑数量
  186. */
  187. val buildings: StateFlow<List<ObjectEntity>> = flow {
  188. emit(repository.getBuildings())
  189. }.stateIn(
  190. scope = viewModelScope,
  191. started = WhileSubscribed(5000),
  192. initialValue = arrayListOf()
  193. )
  194. /**
  195. * 获取本地数据中的建筑信息
  196. */
  197. suspend fun getBuildings(): List<ObjectEntity> {
  198. return repository.getBuildings()
  199. }
  200. /**
  201. * 获取文件上传信息
  202. */
  203. private suspend fun getFileUploadInfo(
  204. param: Map<String, String>,
  205. file: FileInfo
  206. ): Response<FileUploadInfo> {
  207. return request { repository.getFileUploadInfo(param, file) }
  208. }
  209. /**
  210. * 上传文件
  211. */
  212. private suspend fun uploadFile(url: String, file: RequestBody): String {
  213. return repository.uploadFile(url, file)
  214. }
  215. /**
  216. * 上传文件
  217. */
  218. fun fileUpload(param: Map<String, String>, file: File) {
  219. val bytes = file.toBytes()
  220. val md5 = md5(bytes)
  221. val info = FileInfo(
  222. fileMd5 = md5,
  223. fileName = file.name,
  224. fileSize = bytes.size
  225. )
  226. viewModelScope.launch(Dispatchers.IO) {
  227. val response = getFileUploadInfo(param, info)
  228. if (response is SuccessResponse) {
  229. val data = response.data
  230. val url = data.content?.get(0)?.uploadUrl ?: ""
  231. if (url.isNotEmpty()) {
  232. val body = bytes.toRequestBody()
  233. val result = uploadFile(url, body)
  234. Log.d("fileUpload", "success: $result")
  235. if ("success" == result) {
  236. //不管是那种情况,只要成功都需要从本地删除该图片¬
  237. file.renameTo(File(LocalDataOperation.getInstance().getOfflineImageFilePath(DemoApp.mContext) + File.separator + "uploaded" + file.name))
  238. }
  239. }
  240. } else {
  241. Log.d("fileUpload", "upload file has something error:$response")
  242. }
  243. }
  244. }
  245. /**
  246. * 获取服务端生成的客户端Id
  247. */
  248. fun getClient(client: Client) {
  249. viewModelScope.launch {
  250. repository.getClient(client)
  251. }
  252. }
  253. /**
  254. * 登录
  255. */
  256. suspend fun login(login: Login): List<Long> {
  257. val def = viewModelScope.async {
  258. repository.login(login)
  259. }
  260. return def.await()
  261. }
  262. suspend fun getUser(username: String, password: String): UserEntity? {
  263. val def = viewModelScope.async {
  264. repository.getUser(username, password)
  265. }
  266. return def.await()
  267. }
  268. suspend fun getUsers(): List<UserEntity> {
  269. return repository.getUsers()
  270. }
  271. suspend fun getProjects(): List<ProjectEntity> {
  272. val user = repository.getUserByState(1)
  273. repository.getProjects(user)
  274. return repository.getProjectsFromDB()
  275. }
  276. suspend fun getCurrentUser(): UserEntity {
  277. return repository.getUserByState(1)
  278. }
  279. suspend fun getNoDoneTaskByProjectId(projectId: String): Int {
  280. return repository.unUploadTaskByProjectId(projectId)
  281. }
  282. }