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.Data 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.ProjectEntity import com.framework.mvvm.model.db.entity.UserEntity 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.Building import com.framework.mvvm.model.vo.Client import com.framework.mvvm.model.vo.Login import com.sybotan.android.demo.DemoApp import com.sybotan.android.demo.tools.LocalDataOperation import com.yuyh.library.imgsel.utils.LogUtils import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.async import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed 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( request: AdmRequest, block: (() -> Unit)? = null, log: ((String, Building?) -> Unit)? = null ) { viewModelScope.launch(Dispatchers.IO) { //val buildings = repository.getBuildings() val buildings = repository.getBuildingByProjectId(request.projectId) if (buildings.isEmpty()) return@launch for (building in buildings) { repository.uploadBuilding( userId = request.userId, groupCode = building.groupCode!!, projectId = building.projectId!!, buildingId = building.id, log = log ) } withContext(Dispatchers.Main) { block?.invoke() } } } /** * 下载建筑数据 */ fun downloadBuilding( request: AdmRequest, sp: SharedPreferences, isProject: Boolean = false, block: (() -> Unit)? = null ) { viewModelScope.launch(Dispatchers.IO) { //val buildings = repository.getBuildings() val buildings = repository.getBuildingByProjectId(request.projectId) 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 = request.userId, 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( param: Map, file: FileInfo ): Response { return request { repository.getFileUploadInfo(param, file) } } /** * 上传文件 */ private suspend fun uploadFile(url: String, file: RequestBody): String { return repository.uploadFile(url, file) } /** * 上传文件 */ fun fileUpload(param: Map, 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(param, 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") if ("success" == result) { //不管是那种情况,只要成功都需要从本地删除该图片¬ file.renameTo(File(LocalDataOperation.getInstance().getOfflineImageFilePath(DemoApp.mContext) + File.separator + "uploaded" + file.name)) } } } else { Log.d("fileUpload", "upload file has something error:$response") } } } /** * 获取服务端生成的客户端Id */ fun getClient(client: Client) { viewModelScope.launch { repository.getClient(client) } } /** * 登录 */ suspend fun login(login: Login): List { val def = viewModelScope.async { repository.login(login) } return def.await() } suspend fun getUser(username: String, password: String): UserEntity? { val def = viewModelScope.async { repository.getUser(username, password) } return def.await() } suspend fun getUsers(): List { return repository.getUsers() } suspend fun getProjects(): List { val user = repository.getUserByState(1) repository.getProjects(user) return repository.getProjectsFromDB() } suspend fun getCurrentUser(): UserEntity { return repository.getUserByState(1) } suspend fun getNoDoneTaskByProjectId(projectId: String): Int { return repository.unUploadTaskByProjectId(projectId) } }