377 lines
13 KiB
Kotlin
377 lines
13 KiB
Kotlin
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<Boolean> = _takePhotoState
|
|
|
|
// 称重结果
|
|
private val _weightInfo = MutableStateFlow<Double>(0.0)
|
|
val weightInfo: StateFlow<Double> = _weightInfo
|
|
|
|
// 搜索物品列表
|
|
private val _searchListItems = MutableStateFlow<List<SearchGoodsInfo.Record>>(emptyList())
|
|
val searchListItems: StateFlow<List<SearchGoodsInfo.Record>> = _searchListItems
|
|
|
|
// 识别列表
|
|
private val _identityListItems = MutableStateFlow<List<SearchGoodsInfo.Record>>(emptyList())
|
|
val identityListItems: StateFlow<List<SearchGoodsInfo.Record>> = _identityListItems
|
|
|
|
// 待收货的列表 用于识别时从中获取
|
|
private val _receiptList = MutableStateFlow<List<SearchGoodsInfo.Record>>(emptyList())
|
|
val receiptList: StateFlow<List<SearchGoodsInfo.Record>> = _receiptList
|
|
|
|
// 拍照uri
|
|
private val _lastPhotoUri = MutableStateFlow<Uri?>(null)
|
|
val lastPhotoUri: StateFlow<Uri?> = _lastPhotoUri
|
|
|
|
/**
|
|
* 是否可以加载更多
|
|
*/
|
|
private val _canLoadMore = MutableStateFlow(true)
|
|
val canLoadMore: StateFlow<Boolean> = _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<GoodsInfo>) {
|
|
// _receiptList.value = list.map { goods ->
|
|
// SearchGoodsInfo.Record(
|
|
// goodsId = goods.goodId,
|
|
// goodsName = goods.goodName
|
|
// )
|
|
// }
|
|
// }
|
|
//
|
|
// fun updateIdentityList(list: List<SearchGoodsInfo.Record>) {
|
|
// _identityListItems.value = list
|
|
// }
|
|
|
|
/**
|
|
* 获取识别列表
|
|
*/
|
|
// fun getIdentityList(photoUri: Uri) {
|
|
// Timber.d("getIdentityList")
|
|
// launchWithLoading {
|
|
// _searchListItems.value = emptyList<SearchGoodsInfo.Record>()
|
|
// // 有收货列表,则返回收货列表
|
|
// 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<SearchGoodsInfo.Record> {
|
|
val response = repository.searchGoodsInfoList(goodsName, pageNo, pageSize)
|
|
return if (parseResponse(response)) {
|
|
response.result?.records ?: listOf()
|
|
} else {
|
|
listOf()
|
|
}
|
|
}
|
|
|
|
fun recognizeGoodsList(
|
|
nameList: List<String>? = null,
|
|
scoreList: List<FoodModule.IdNameScore>? = null,
|
|
callback: (List<SearchGoodsInfo.Record>) -> 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<SearchGoodsInfo.Record>) -> Unit)? = null
|
|
// ) {
|
|
// launch {
|
|
// if (pageNo > 1) {
|
|
// _isMoreLoading.value = true
|
|
// }
|
|
// _identityListItems.value = emptyList<SearchGoodsInfo.Record>()
|
|
// 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<SearchGoodsInfo.Record>()
|
|
// 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<DictType> = 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<DictType>()
|
|
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<DictType> = 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<DictType> = 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<DictType> = 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<String>(key)
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
}
|
|
return ""
|
|
}
|
|
|
|
fun getGoodsList(key:String):List<GoodsInfo>? {
|
|
try {
|
|
val jsonData = getGoodsData(key)
|
|
return jsonData?.toType(typeToken=object:TypeToken<List<GoodsInfo>?>(){})
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
}
|
|
return emptyList()
|
|
}
|
|
|
|
fun deleteKey(key:String) {
|
|
try {
|
|
SPUtil.getInstance(spName = goodsKey).remove(key)
|
|
} catch (e: Exception) {
|
|
e.printStackTrace()
|
|
}
|
|
}
|
|
|
|
} |