package com.framework.mvvm.mv import android.content.SharedPreferences import android.util.Log import androidx.core.content.edit import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import cn.sagacloud.cadengine.OkhttpUtil import com.framework.app.* import com.framework.app.http.FileInfo import com.framework.app.http.FileUploadInfo import com.framework.app.tools.md5 import com.framework.app.tools.toBytes import com.framework.mvvm.model.data.Response import com.framework.mvvm.model.data.SuccessResponse import com.framework.mvvm.model.data.request import com.framework.mvvm.model.db.entity.task.ObjectEntity import com.framework.mvvm.model.repository.AdmRepository import com.framework.mvvm.model.vo.AdmRequest import com.framework.mvvm.model.vo.User import com.sybotan.android.demo.DemoApp import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import okhttp3.RequestBody import okhttp3.RequestBody.Companion.toRequestBody import java.io.File import java.io.FileOutputStream class AdmViewModel(private val repository: AdmRepository) : ViewModel() { /** * 请求字典数据 */ fun requestDict(request: AdmRequest, block: (() -> Unit)? = null) { viewModelScope.launch { repository.requestDict(request) block?.invoke() } } /** * 请求配置信息 */ fun requestConfig(request: AdmRequest, block: (() -> Unit)? = null) { viewModelScope.launch { repository.requestConfig(request) block?.invoke() } } /** * 请求框架数据 */ fun requestFrame(request: AdmRequest, block: (() -> Unit)? = null) { viewModelScope.launch { repository.requestFrame(request) block?.invoke() } } /** * 上传建筑数据 */ fun uploadBuilding(block: (() -> Unit)? = null) { viewModelScope.launch(Dispatchers.IO) { val buildings = repository.getBuildings() if (buildings.isEmpty()) return@launch for (building in buildings) { repository.uploadBuilding( userId = "bdtp", groupCode = building.groupCode!!, projectId = building.projectId!!, buildingId = building.id ) } withContext(Dispatchers.Main) { block?.invoke() } } } /** * 下载建筑数据 */ fun downloadBuilding( sp: SharedPreferences, isProject: Boolean = false, block: (() -> Unit)? = null ) { viewModelScope.launch(Dispatchers.IO) { val buildings = repository.getBuildings() println("downloadBuilding will download : ${buildings.size}") if (buildings.isEmpty()) { Log.d("downloadBuilding", "buildings is empty") return@launch } val job = launch { // 启动一个总协程 for (building in buildings) { launch { // 为每个下载任务启动协程 repository.requestBuilding( AdmRequest( userId = "bdtp", projectId = building.projectId!!, groupCode = building.groupCode!!, buildingId = if (isProject) "" else building.id, clientId = sp.getString(CLIENT_ID, "") ?: "", bdtpDownloadTs = sp.getLong( "${ if (isProject) building.projectId else building.id }.$BDTP_TS", 0L ), admDownloadTs = sp.getLong( "${ if (isProject) building.projectId else building.id }.$ADM_TS", 0L ) ) ) { Log.e( "downloadBuilding", "bdtpDownloadTs:${it.bdtpDownloadTs}, admDownloadTs:${it.admDownloadTs}" ) sp.edit { putLong( "${if (isProject) building.projectId else building.id}.$BDTP_TS", it.bdtpDownloadTs ) } sp.edit { putLong( "${if (isProject) building.projectId else building.id}.$ADM_TS", it.admDownloadTs ) } } } } } job.join() // 下载地图 val gzipJob = launch { val floors = repository.getFloors() floors.forEach { launch(Dispatchers.IO) { val json = it.infos?.asJsonObject val floorMap = json?.get("floorMap")?.asString ?: "" if (floorMap.isNotEmpty()) { val mapString = OkhttpUtil.getGzipMap("$IP$pathDownloadMap${floorMap}") val mapFile = File(DemoApp.getInstance()?.getExternalFilesDir("floorMap"), it.id) FileOutputStream(mapFile).use { output -> output.write(mapString.toByteArray()) } it.floorMap = mapFile.absolutePath repository.updateObject(it) } } } } gzipJob.join() withContext(Dispatchers.Main) { block?.invoke() } } } /** * 获取建筑数量 */ val buildings: StateFlow> = flow { emit(repository.getBuildings()) }.stateIn( scope = viewModelScope, started = WhileSubscribed(5000), initialValue = arrayListOf() ) /** * 获取本地数据中的建筑信息 */ suspend fun getBuildings(): List { return repository.getBuildings() } /** * 获取文件上传信息 */ private suspend fun getFileUploadInfo(basic: FileInfo): Response { return request { repository.getFileUploadInfo(basic) } } /** * 上传文件 */ private suspend fun uploadFile(url: String, file: RequestBody): String { return repository.uploadFile(url, file) } /** * 上传文件 */ fun fileUpload(file: File) { val bytes = file.toBytes() val md5 = md5(bytes) val info = FileInfo( fileMd5 = md5, fileName = file.name, fileSize = bytes.size ) viewModelScope.launch(Dispatchers.IO) { val response = getFileUploadInfo(info) if (response is SuccessResponse) { val data = response.data val url = data.content?.get(0)?.uploadUrl ?: "" if (url.isNotEmpty()) { val body = bytes.toRequestBody() val result = uploadFile(url, body) Log.d("fileUpload", "success: $result") } } else { Log.d("fileUpload", "upload file has something error:$response") } } } /** * 获取服务端生成的客户端Id */ fun getClient(user: User) { viewModelScope.launch { repository.getClient(user) } } }