package com.sw.inbound.viewmodel import android.net.Uri import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.google.gson.reflect.TypeToken import com.sw.inbound.GlobalData import com.sw.inbound.model.response.ApiResponse import com.sw.inbound.model.response.DictType import com.sw.inbound.model.response.EquipmentInfo import com.sw.inbound.model.response.GoodsInfo import com.sw.inbound.model.response.SearchGoodsInfo import com.sw.inbound.network.LoadingState import com.sw.inbound.objbox.FoodModule import com.sw.inbound.repository.RemoteRepository import com.sw.inbound.utils.SPUtil import com.sw.inbound.utils.ToastUtils import com.sw.inbound.utils.ext.toType import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch import retrofit2.HttpException import timber.log.Timber import java.io.IOException import kotlin.collections.List import kotlin.math.roundToInt abstract class BaseViewModel( private val repository: RemoteRepository ) : ViewModel() { // 需要拍照 private val _takePhotoState = MutableStateFlow(false) val takePhotoState: StateFlow = _takePhotoState // 称重结果 private val _weightInfo = MutableStateFlow(0.0) val weightInfo: StateFlow = _weightInfo // 搜索物品列表 private val _searchListItems = MutableStateFlow>(emptyList()) val searchListItems: StateFlow> = _searchListItems // 识别列表 private val _identityListItems = MutableStateFlow>(emptyList()) val identityListItems: StateFlow> = _identityListItems // 待收货的列表 用于识别时从中获取 private val _receiptList = MutableStateFlow>(emptyList()) val receiptList: StateFlow> = _receiptList // 拍照uri private val _lastPhotoUri = MutableStateFlow(null) val lastPhotoUri: StateFlow = _lastPhotoUri /** * 是否可以加载更多 */ private val _canLoadMore = MutableStateFlow(true) val canLoadMore: StateFlow = _canLoadMore /** * 是否显示进度条 */ private val _isMoreLoading = MutableStateFlow(false) val isMoreLoading = _isMoreLoading /** * 带进度条的请求 */ protected fun launchWithLoading(block: suspend () -> Unit) { viewModelScope.launch { try { LoadingState.show() block() } catch (e: Exception) { // 错误处理可被子类重写 handleError(e) } finally { delay(500) LoadingState.hide() } } } /** * 不带进度条的请求 */ protected fun launch(block: suspend () -> Unit) { viewModelScope.launch() { try { block() } catch (e: Exception) { // 错误处理可被子类重写 handleError(e) } } } protected open fun parseResponse(response: ApiResponse<*>): Boolean { if (response.isSuccess()) { return true } Timber.d("msg = ${response.msg}, code = ${response.code}") //ToastUtils.showToast("${response.msg}(${response.code})") return false } protected open fun handleError(e: Exception) = { Timber.e(e) val message = when (e) { is IOException -> "网络连接异常" is HttpException -> "服务器错误: ${e.code()}" else -> "操作失败: ${e.message}" } ToastUtils.showToast(message) } // fun startSensorScale() { // Timber.d("开始称重") // SensorScaleUtils.startScale(callback = { weight -> // _weightInfo.value = weight // handleSensorScale(weight) // }) // } // // fun stopSensorScale() { // Timber.d("关闭称重") // SensorScaleUtils.stopContinuousRead() // } abstract fun handleSensorScale(weight: Double) fun updateCanLoadMore(canLoad: Boolean) { _canLoadMore.value = canLoad } fun updateLastPhotoUri(photoUri: Uri?) { _lastPhotoUri.value = photoUri } // fun updateReceiptList(list: List) { // _receiptList.value = list.map { goods -> // SearchGoodsInfo.Record( // goodsId = goods.goodId, // goodsName = goods.goodName // ) // } // } // // fun updateIdentityList(list: List) { // _identityListItems.value = list // } /** * 获取识别列表 */ // fun getIdentityList(photoUri: Uri) { // Timber.d("getIdentityList") // launchWithLoading { // _searchListItems.value = emptyList() // // 有收货列表,则返回收货列表 // if (_receiptList.value.isNotEmpty()) { // _identityListItems.value = _receiptList.value // if (_identityListItems.value.isNotEmpty()) { // handleIdentityItem(_identityListItems.value[0]) // } // } else { // val response = repository.searchGoodsInfoList("", 1, 10) // if (parseResponse(response)) { // _identityListItems.value = response.result?.records ?: emptyList() // if (_identityListItems.value.isNotEmpty()) { // handleIdentityItem(_identityListItems.value[0]) // } // } // } // } // } /** * 处理识别后要选中的值 */ open fun handleIdentityItem(goodsInfo: SearchGoodsInfo.Record) {} fun updateMoreLoading(moreLoading: Boolean) { _isMoreLoading.value = moreLoading } /** * 搜索物品 */ suspend fun searchGoodsInfoList2( goodsName: String, pageNo: Int = 1, pageSize: Int = 10 ): List { val response = repository.searchGoodsInfoList(goodsName, pageNo, pageSize) return if (parseResponse(response)) { response.result?.records ?: listOf() } else { listOf() } } fun recognizeGoodsList( nameList: List? = null, scoreList: List? = null, callback: (List) -> Unit ) { launch { if (nameList.isNullOrEmpty() && scoreList.isNullOrEmpty()) return@launch val paramList = if (nameList.isNullOrEmpty()) scoreList!!.map { it.name } else nameList val response = repository.recognizeGoodsList(paramList) val list = if (parseResponse(response)) response.data ?: listOf() else listOf() if (scoreList.isNullOrEmpty().not()) { list.forEach { record -> val item = scoreList.firstOrNull { it.name == record.goodsName } record.score = ((1 - (item?.score ?: 0.0)) * 10000).roundToInt() } } callback(list) } } // fun searchGoodsInfoList( // goodsName: String, // pageNo: Int = 1, // pageSize: Int = 10, // searchCallback: ((pageNo: Int, List) -> Unit)? = null // ) { // launch { // if (pageNo > 1) { // _isMoreLoading.value = true // } // _identityListItems.value = emptyList() // val response = repository.searchGoodsInfoList(goodsName, pageNo, pageSize) // _isMoreLoading.value = false // if (parseResponse(response)) { // val data = response.result // data?.records?.let { // _canLoadMore.value = data.records.size >= pageSize // if (pageNo > 1) { // _searchListItems.value = _searchListItems.value + data.records // } else { // _searchListItems.value = data.records // } // searchCallback?.invoke(pageNo, _searchListItems.value) // } // } else { // _searchListItems.value = emptyList() // searchCallback?.invoke(pageNo, _searchListItems.value) // } // } // } fun getDictType() { Timber.d("获取所有字典列表") launchWithLoading { val response = repository.getGoodsStorageType() if (parseResponse(response)) { Timber.d("getGoodsStorageType data = ${response.result}") response.result?.let { val list: MutableList = mutableListOf() response.result ?.filter { it.id.isNullOrBlank().not() && it.title.isNullOrBlank().not() } ?.forEach { list.add(DictType(id = it.value, value = it.title)) } GlobalData.storageTypeList = list } } else { Timber.e("getGoodsStorageType msg = ${response.message}, code = ${response.code}") } val response1 = repository.getGoodsType() if (parseResponse(response1)) { Timber.d("getGoodsType data = ${response1.result?.allType}") val list = mutableListOf() response1.result ?.allType ?.filter { it?.id.isNullOrBlank().not() && it.typeName.isNullOrBlank().not() } ?.forEach { list.add(DictType(it!!.id, it.typeName!!)) } GlobalData.goodsTypeList = list.toList() } else { Timber.e("getGoodsType msg = ${response1.message}, code = ${response1.code}") } val response2 = repository.getDictType(RemoteRepository.TypeEnum.WAREHOUSE) if (parseResponse(response2)) { Timber.d("getDictType WAREHOUSE data = ${response2.result}") val list: MutableList = mutableListOf() response2.result ?.filter { it.id.isNullOrBlank().not() && it.value.isNullOrBlank().not() } ?.forEach { list.add(DictType(id = it.id, value = it.value)) } GlobalData.warehouseTypeList = list.toList() } else { Timber.e("getDictType WAREHOUSE msg = ${response2.message}, code = ${response2.code}") } val response3 = repository.getDictType(RemoteRepository.TypeEnum.SUPPLIER) if (parseResponse(response3)) { Timber.d("getDictType SUPPLIER data = ${response3.result}") val list: MutableList = mutableListOf() response3.result ?.filter { it.id.isNullOrBlank().not() && it.value.isNullOrBlank().not() } ?.forEach { list.add(DictType(id = it.id, value = it.value)) } GlobalData.supplierTypeList = list.toList() } else { Timber.e("getDictType SUPPLIER msg = ${response3.message}, code = ${response3.code}") } val response4 = repository.getDictType(RemoteRepository.TypeEnum.UNIT) if (parseResponse(response4)) { Timber.d("getDictType UNIT data = ${response4.result}") val list: MutableList = mutableListOf() response4.result ?.filter { it.id.isNullOrBlank().not() && it.value.isNullOrBlank().not() } ?.forEach { list.add(DictType(id = it.id, value = it.value)) } GlobalData.unitTypeList = list.toList() } else { Timber.e("getDictType UNIT msg = ${response4.message}, code = ${response4.code}") } } } fun parseEquipmentInfo(equipmentInfo: EquipmentInfo) { GlobalData.appBaseUrl = equipmentInfo.appPackageUrl!! GlobalData.sdkKey = equipmentInfo.arcsoftSdkKey!! GlobalData.appId = equipmentInfo.arcsoftAppId!! // GlobalData.activeKey = equipmentInfo.arcsoftActiveKey!! GlobalData.restId = equipmentInfo.canteenId!! } val goodsKey = "goods" fun putGoodsData(key: String, jsonData: String) { try { SPUtil.getInstance(spName = goodsKey).put(key, jsonData) } catch (e: Exception) { e.printStackTrace() } } fun getGoodsData(key: String):String? { try { return SPUtil.getInstance(spName = goodsKey).get(key) } catch (e: Exception) { e.printStackTrace() } return "" } fun getGoodsList(key:String):List? { try { val jsonData = getGoodsData(key) return jsonData?.toType(typeToken=object:TypeToken?>(){}) } catch (e: Exception) { e.printStackTrace() } return emptyList() } fun deleteKey(key:String) { try { SPUtil.getInstance(spName = goodsKey).remove(key) } catch (e: Exception) { e.printStackTrace() } } }