添加了注释,完善了参数校验及空值处理
This commit is contained in:
@@ -23,6 +23,9 @@ android {
|
||||
ndk {
|
||||
abiFilters.addAll(listOf("armeabi-v7a"/*, "arm64-v8a"*/))
|
||||
}
|
||||
|
||||
// 设置输出APK文件名格式
|
||||
setProperty("archivesBaseName", "入库客户端_${versionName}")
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
||||
@@ -20,26 +20,6 @@ object GlobalData {
|
||||
var warehouseTypeList: List<DictType> = arrayListOf()
|
||||
var supplierTypeList: List<DictType> = arrayListOf()
|
||||
var unitTypeList: List<DictType> = arrayListOf()
|
||||
|
||||
fun getStorageType(id: Int): String {
|
||||
return storageTypeList.find { it.id == id }?.value ?: "默认"
|
||||
}
|
||||
|
||||
fun getGoodsType(id: Int): String {
|
||||
return goodsTypeList.find { it.id == id }?.value ?: "-"
|
||||
}
|
||||
|
||||
fun getWarehouseType(id: Int): String {
|
||||
return warehouseTypeList.find { it.id == id }?.value ?: "-"
|
||||
}
|
||||
|
||||
fun getSupplierType(id: Int): String {
|
||||
return supplierTypeList.find { it.id == id }?.value ?: "-"
|
||||
}
|
||||
|
||||
fun getUnitType(id: Int): String {
|
||||
return unitTypeList.find { it.id == id }?.value ?: "-"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@ import androidx.activity.compose.setContent
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import com.sw.inbound.sdk.SensorScaleUtils
|
||||
import com.sw.inbound.ui.AppScreen
|
||||
import com.sw.inbound.utils.ThreadUtils
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
|
||||
@AndroidEntryPoint
|
||||
@@ -22,6 +23,7 @@ class MainActivity : ComponentActivity() {
|
||||
|
||||
override fun onDestroy() {
|
||||
SensorScaleUtils.closeScale()
|
||||
ThreadUtils.release()
|
||||
super.onDestroy()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,26 +33,35 @@ private fun Double.roundToDouble(decimalPlaces: Int): Double {
|
||||
return kotlin.math.round(this * factor) / factor
|
||||
}
|
||||
|
||||
fun Double?.toSafeString(unitName: String?): String {
|
||||
if (this == null || this == 0.0) return ""
|
||||
val decimalPlaces = getDecimalPlaces(unitName)
|
||||
return "%.${decimalPlaces}f".format(this)
|
||||
}
|
||||
|
||||
fun Double?.toSafeDouble(unitName: String?): Double {
|
||||
if (this == null || this == 0.0) return 0.0
|
||||
|
||||
val decimalPlaces = when (unitName) {
|
||||
"斤", "克", "公斤", "升" -> 2
|
||||
else -> 0
|
||||
}
|
||||
|
||||
val decimalPlaces = getDecimalPlaces(unitName)
|
||||
return roundToDouble(decimalPlaces)
|
||||
}
|
||||
|
||||
fun Double?.toSafeFloat(unitName: String?): Float {
|
||||
if (this == null || this == 0.0) return 0f
|
||||
|
||||
val decimalPlaces = getDecimalPlaces(unitName)
|
||||
return roundToDouble(decimalPlaces).toFloat()
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过单位判断小数
|
||||
*/
|
||||
private fun getDecimalPlaces(unitName: String?): Int {
|
||||
val decimalPlaces = when (unitName) {
|
||||
"斤", "克", "公斤", "升" -> 2
|
||||
else -> 0
|
||||
}
|
||||
|
||||
return roundToDouble(decimalPlaces).toFloat()
|
||||
return decimalPlaces
|
||||
}
|
||||
|
||||
fun BigDecimal.toFormattedString(): String {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.sw.inbound.model.exception
|
||||
|
||||
class ApiException {
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
package com.sw.inbound.model.exception
|
||||
|
||||
|
||||
class NetException(val code: Int, override val message: String) : Exception(message)
|
||||
@@ -3,6 +3,7 @@ package com.sw.inbound.model.request
|
||||
import android.os.Parcelable
|
||||
import com.sw.inbound.GlobalData
|
||||
import com.sw.inbound.ext.toFormattedString
|
||||
import com.sw.inbound.ext.toSafeString
|
||||
import com.sw.inbound.model.response.DictType
|
||||
import com.sw.inbound.model.response.SearchGoodsInfo.Record.UnitVo
|
||||
import kotlinx.parcelize.Parcelize
|
||||
@@ -25,6 +26,9 @@ data class PurchaseWarehouseParam(
|
||||
* 入库数量
|
||||
*/
|
||||
var goodsCount: Double = 0.0,
|
||||
|
||||
// 用于数量输入框显示
|
||||
var goodsCountTemp: String = "",
|
||||
/**
|
||||
* 入库单价
|
||||
*/
|
||||
@@ -122,7 +126,7 @@ data class PurchaseWarehouseParam(
|
||||
if (goodsCount == null || goodsCount == 0.0) {
|
||||
return ""
|
||||
}
|
||||
return goodsCount.toFormattedString()
|
||||
return goodsCount.toSafeString(unitName)
|
||||
}
|
||||
|
||||
val goodsUnitPriceStr: String
|
||||
|
||||
+3
@@ -3,6 +3,9 @@ package com.sw.inbound.model.response
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
/**
|
||||
* 字典类型 如仓库列表 物品类型 存储方式等
|
||||
*/
|
||||
@Parcelize
|
||||
data class DictType(
|
||||
val id: Int,
|
||||
@@ -75,12 +75,15 @@ data class GoodsInfo(
|
||||
|
||||
// 收货数量 收货入参
|
||||
var receivedNum: Float? = null,
|
||||
// 收货数量显示
|
||||
var receivedNumTemp: String = "",
|
||||
// 重量 收货入参
|
||||
var goodsWeight: BigDecimal? = null,
|
||||
|
||||
// 已调整
|
||||
var isAdjusted: Boolean = false,
|
||||
|
||||
// 选中物品的可选单位
|
||||
var unitList: List<UnitVo> = emptyList<UnitVo>()
|
||||
) : Parcelable, BaseBean() {
|
||||
|
||||
@@ -173,9 +176,25 @@ data class GoodsInfo(
|
||||
return warehouseName!!
|
||||
}
|
||||
|
||||
fun hasNull(): Boolean {
|
||||
return goodName == null || warehouseId == null ||
|
||||
purchaseUnitId == null || recUnitPriceTaxIn == null
|
||||
|| receiveCount == null || recPriceExItem == null
|
||||
fun hasNullField(): String? {
|
||||
if (warehouseId == null) {
|
||||
return "请选择仓库"
|
||||
}
|
||||
if (receivedNum == null || receivedNum == 0f) {
|
||||
return "请输入收货数量或进行称重"
|
||||
}
|
||||
if (recUnitPriceTaxIn == null || recUnitPriceTaxIn == 0f) {
|
||||
return "请输入收货单价"
|
||||
}
|
||||
if (recPriceExItem == null || recPriceExItem == 0f) {
|
||||
return "请输入收货金额"
|
||||
}
|
||||
if (goodsWeight == null || goodsWeight == BigDecimal(0)) {
|
||||
return "请放入要称重的物品"
|
||||
}
|
||||
return null
|
||||
// return goodName == null || warehouseId == null ||
|
||||
// purchaseUnitId == null || recUnitPriceTaxIn == null
|
||||
// || receiveCount == null || recPriceExItem == null
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,9 @@ import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
/**
|
||||
* 物品类型
|
||||
*/
|
||||
@Parcelize
|
||||
data class GoodsType(
|
||||
@SerializedName("allType")
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.sw.inbound.model.response
|
||||
|
||||
/**
|
||||
* 采购详情
|
||||
*/
|
||||
data class PurchaseInfo(
|
||||
/**
|
||||
* 单据id
|
||||
@@ -12,21 +15,22 @@ data class PurchaseInfo(
|
||||
/**
|
||||
* 供应商名称
|
||||
*/
|
||||
var supplierName: String = "",
|
||||
var supplierName: String? = "",
|
||||
/**
|
||||
* 采购单号
|
||||
*/
|
||||
var purCode: String = "",
|
||||
var purCode: String? = "",
|
||||
/**
|
||||
* 收货单号
|
||||
*/
|
||||
var receiveCode: String = "",
|
||||
var receiveCode: String? = "",
|
||||
|
||||
/**
|
||||
* 物品信息
|
||||
*/
|
||||
var receiveGoodsInfoList: List<GoodsInfo> = emptyList<GoodsInfo>()
|
||||
) : BaseBean() {
|
||||
var receiveGoodsInfoList: List<GoodsInfo> = emptyList<GoodsInfo>(),
|
||||
// 自用
|
||||
var warehouseName: String = "选择仓库"
|
||||
) : BaseBean() {
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@ import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
/**
|
||||
* 搜索商品结果
|
||||
*/
|
||||
@Parcelize
|
||||
data class SearchGoodsInfo(
|
||||
@SerializedName("current")
|
||||
@@ -60,7 +63,7 @@ data class SearchGoodsInfo(
|
||||
* 采购单位列表
|
||||
*/
|
||||
@SerializedName("unitVoList")
|
||||
val unitVoList: List<UnitVo>? = listOf(),
|
||||
val unitVoList: List<UnitVo>? = null,
|
||||
@SerializedName("zjmCode")
|
||||
val zjmCode: String? = ""
|
||||
) : Parcelable {
|
||||
|
||||
@@ -5,6 +5,9 @@ import android.os.Parcelable
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
/**
|
||||
* 采购信息
|
||||
*/
|
||||
@Parcelize
|
||||
data class SupplierInfo(
|
||||
@SerializedName("createTime")
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.sw.inbound.network.interceptor
|
||||
|
||||
import com.google.gson.JsonParseException
|
||||
import com.sw.inbound.model.exception.NetException
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
import retrofit2.HttpException
|
||||
import timber.log.Timber
|
||||
import java.io.IOException
|
||||
|
||||
class ErrorInterceptor : Interceptor {
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
try {
|
||||
val response = chain.proceed(chain.request())
|
||||
if (!response.isSuccessful) {
|
||||
throw NetException(response.code, "HTTP Error ${response.code}")
|
||||
}
|
||||
return response
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
throw when (e) {
|
||||
is IOException -> NetException(-1, "Network error: ${e.message}")
|
||||
is JsonParseException -> NetException(-2, "Data parse error")
|
||||
is HttpException -> NetException(-3, e.message ?: "未知错误")
|
||||
else -> NetException(-100, e.message ?: "未知错误")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,9 @@ import com.sw.inbound.utils.SPUtil
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
|
||||
/**
|
||||
* 请求拦截器
|
||||
*/
|
||||
class RequestInterceptor : Interceptor {
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val originalRequest = chain.request()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.sw.inbound.sdk
|
||||
|
||||
import com.sw.inbound.utils.ThreadUtils
|
||||
import com.sw.inbound.utils.ToastUtils
|
||||
import com.wabon.wbintelligenthardwaresdk.api.SensorScale
|
||||
import com.wabon.wbintelligenthardwaresdk.api.SensorScale.OnScaleResult
|
||||
import kotlinx.coroutines.delay
|
||||
@@ -48,6 +49,10 @@ object SensorScaleUtils {
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启称重
|
||||
* @param autoScale 是否开启自动读取
|
||||
*/
|
||||
fun startScale(autoScale: Boolean = true, callback: Callback?) {
|
||||
if (isOpened) {
|
||||
startContinuousRead(callback = callback)
|
||||
@@ -70,15 +75,21 @@ object SensorScaleUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开启自动读取重量
|
||||
*/
|
||||
fun startContinuousRead(callback: Callback?) {
|
||||
this.callback = callback
|
||||
Timber.d("isOpened = $isOpened")
|
||||
Timber.d("开启自动读取 = $isOpened")
|
||||
if (!isOpened) {
|
||||
return
|
||||
}
|
||||
mSensorScale?.startContinuousRead()
|
||||
}
|
||||
|
||||
/**
|
||||
* 手动读取重量
|
||||
*/
|
||||
fun readWeight(callback: Callback?) {
|
||||
this.callback = callback
|
||||
Timber.d("isOpened = $isOpened")
|
||||
@@ -88,6 +99,30 @@ object SensorScaleUtils {
|
||||
mSensorScale?.readWeight()
|
||||
}
|
||||
|
||||
/**
|
||||
* 零位标定
|
||||
*/
|
||||
fun zero() {
|
||||
if (!isOpened) return
|
||||
mSensorScale?.zero {
|
||||
Timber.d("零位标定操作成功")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 去皮置零
|
||||
*/
|
||||
fun tare() {
|
||||
if (!isOpened) return
|
||||
mSensorScale?.tare {
|
||||
Timber.d("去皮置零操作成功")
|
||||
ToastUtils.showToast("去皮置零操作成功")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止自动读取重量
|
||||
*/
|
||||
fun stopContinuousRead() {
|
||||
Timber.d("isOpened = $isOpened")
|
||||
if (!isOpened) {
|
||||
@@ -96,6 +131,9 @@ object SensorScaleUtils {
|
||||
mSensorScale?.stopContinuousRead()
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭称重
|
||||
*/
|
||||
fun closeScale() {
|
||||
isOpened = false
|
||||
mSensorScale?.closeScale()
|
||||
|
||||
@@ -91,6 +91,9 @@ fun AppScreen(
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 导航
|
||||
*/
|
||||
@Composable
|
||||
private fun NavHost(
|
||||
padding: PaddingValues,
|
||||
|
||||
@@ -30,6 +30,9 @@ import com.sw.inbound.ui.weight.TopTitleBar
|
||||
import com.sw.inbound.viewmodel.UserViewModel
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* 首页
|
||||
*/
|
||||
@Composable
|
||||
fun HomeScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
|
||||
@@ -49,18 +49,21 @@ import com.sw.inbound.ui.theme.AppTypography.blackTextStyle
|
||||
import com.sw.inbound.ui.theme.AppTypography.grayTextStyle
|
||||
import com.sw.inbound.ui.weight.BottomActionBar
|
||||
import com.sw.inbound.ui.weight.TopTitleBar
|
||||
import com.sw.inbound.viewmodel.ProductViewModel
|
||||
import com.sw.inbound.viewmodel.PurchaseOrderViewModel
|
||||
|
||||
@Preview(
|
||||
widthDp = 1920,
|
||||
heightDp = 1080,
|
||||
showBackground = true
|
||||
)
|
||||
/**
|
||||
* 采购订单-供应商列表
|
||||
*/
|
||||
@Composable
|
||||
fun PurchaseOrderScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
navController: NavHostController = rememberNavController(),
|
||||
viewModel: ProductViewModel = hiltViewModel<ProductViewModel>()
|
||||
viewModel: PurchaseOrderViewModel = hiltViewModel<PurchaseOrderViewModel>()
|
||||
) {
|
||||
val products by viewModel.supplierList.collectAsState()
|
||||
|
||||
@@ -97,12 +100,6 @@ fun PurchaseOrderScreen(
|
||||
} else {
|
||||
LazyRow(
|
||||
modifier = modifier
|
||||
// .paint(painterResource(R.mipmap.bg_listview))
|
||||
// .fillMaxSize()
|
||||
// .background(
|
||||
// color = Color(0x80FFFFFF),
|
||||
// shape = RoundedCornerShape(12.dp) // 圆角背景
|
||||
// )
|
||||
.padding(10.dp),
|
||||
contentPadding = PaddingValues(16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(30.dp)
|
||||
@@ -131,6 +128,9 @@ fun PurchaseOrderScreen(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 采购单缺省
|
||||
*/
|
||||
@Composable
|
||||
fun PurchaseEmptyItem() {
|
||||
Column(
|
||||
@@ -149,6 +149,9 @@ fun PurchaseEmptyItem() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表item
|
||||
*/
|
||||
@Composable
|
||||
fun PurchaseOrderItem(product: SupplierInfo, onItemClick: (SupplierInfo) -> Unit) {
|
||||
|
||||
@@ -235,7 +238,7 @@ fun PurchaseOrderItem(product: SupplierInfo, onItemClick: (SupplierInfo) -> Unit
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text(text = "采购日期", style = grayTextStyle)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(text = product.purchaseDate ?: "", style = blackTextStyle)
|
||||
Text(text = product.purchaseDate ?: "-", style = blackTextStyle)
|
||||
}
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text(text = "到货日期", style = grayTextStyle)
|
||||
|
||||
@@ -48,6 +48,7 @@ import com.sw.inbound.ext.withSize
|
||||
import com.sw.inbound.model.request.UploadInfo
|
||||
import com.sw.inbound.model.response.DictType
|
||||
import com.sw.inbound.model.response.GoodsInfo
|
||||
import com.sw.inbound.sdk.SensorScaleUtils
|
||||
import com.sw.inbound.ui.theme.AppTypography
|
||||
import com.sw.inbound.ui.theme.AppTypography.black141428TextStyle
|
||||
import com.sw.inbound.ui.theme.AppTypography.gray96a0aaTextStyle
|
||||
@@ -57,13 +58,18 @@ import com.sw.inbound.ui.weight.CustomSpinner
|
||||
import com.sw.inbound.ui.weight.CustomTextField
|
||||
import com.sw.inbound.ui.weight.IdentityView
|
||||
import com.sw.inbound.ui.weight.InputType
|
||||
import com.sw.inbound.ui.weight.ProductListView
|
||||
import com.sw.inbound.ui.weight.ReceiptUnadjustedListView
|
||||
import com.sw.inbound.ui.weight.RowInputLayout
|
||||
import com.sw.inbound.ui.weight.TopTitleBar
|
||||
import com.sw.inbound.ui.weight.dialog.ReceiptTipDialog
|
||||
import com.sw.inbound.utils.InteractionUtils
|
||||
import com.sw.inbound.utils.ToastUtils
|
||||
import com.sw.inbound.viewmodel.ReceiptViewModel
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* 收货界面
|
||||
*/
|
||||
@Composable
|
||||
fun ReceiptProductScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -79,6 +85,7 @@ fun ReceiptProductScreen(
|
||||
|
||||
LaunchedEffect(receiptResult) {
|
||||
if (receiptResult) {
|
||||
ToastUtils.showToast("收货成功")
|
||||
controller.popBackStack()
|
||||
}
|
||||
}
|
||||
@@ -94,7 +101,7 @@ fun ReceiptProductScreen(
|
||||
modifier = modifier
|
||||
.background(
|
||||
color = Color(0x80FFFFFF),
|
||||
shape = RoundedCornerShape(12.dp)
|
||||
shape = RoundedCornerShape(10.dp)
|
||||
)
|
||||
.fillMaxWidth()
|
||||
.padding(30.dp)
|
||||
@@ -140,6 +147,9 @@ fun ReceiptProductScreen(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 左侧列表
|
||||
*/
|
||||
@Composable
|
||||
fun ReceiptLeftView(
|
||||
modifier: Modifier,
|
||||
@@ -161,18 +171,18 @@ fun ReceiptLeftView(
|
||||
) {
|
||||
Column {
|
||||
Text(
|
||||
"供应商:${currentPurchaseInfo?.supplierName}",
|
||||
"供应商:${currentPurchaseInfo?.supplierName ?: "-"}",
|
||||
style = black141428TextStyle.bold()
|
||||
)
|
||||
Spacer(modifier = Modifier.height(18.dp))
|
||||
Row {
|
||||
Text(
|
||||
"采购单号:${currentPurchaseInfo?.purCode}",
|
||||
"采购单号:${currentPurchaseInfo?.purCode ?: "-"}",
|
||||
style = gray96a0aaTextStyle.copy(fontSize = 20.sp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(120.dp))
|
||||
Text(
|
||||
"收货单号:${currentPurchaseInfo?.receiveCode}",
|
||||
"收货单号:${currentPurchaseInfo?.receiveCode ?: "-"}",
|
||||
style = gray96a0aaTextStyle.copy(fontSize = 20.sp)
|
||||
)
|
||||
}
|
||||
@@ -181,22 +191,15 @@ fun ReceiptLeftView(
|
||||
items = warehouseTypeList,
|
||||
selectedItem = currentPurchaseInfo!!.warehouseName,
|
||||
onItemSelected = { value ->
|
||||
val currentPurchaseInfo1 = currentPurchaseInfo!!.copy()
|
||||
currentPurchaseInfo1.warehouseName = value.value
|
||||
val currentPurchaseInfo1 =
|
||||
currentPurchaseInfo!!.copy(warehouseName = value.value)
|
||||
viewModel.updateCurrentPurchaseInfo(currentPurchaseInfo1)
|
||||
viewModel.updateAllPurchaseStore(store = value)
|
||||
viewModel.updateAllPurchaseStore(warehouse = value)
|
||||
})
|
||||
}
|
||||
Spacer(modifier = Modifier.height(30.dp))
|
||||
|
||||
TabScreen(viewModel)
|
||||
// LazyColumn(
|
||||
// verticalArrangement = Arrangement.spacedBy(30.dp)
|
||||
// ) {
|
||||
// items(items = purchaseOrderList, key = { it.id }) {
|
||||
// ReceiptItem(it, modifier)
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -275,7 +278,7 @@ fun TabScreen(viewModel: ReceiptViewModel) {
|
||||
fun UnadjustedView(purchaseOrderList: List<GoodsInfo>, viewModel: ReceiptViewModel) {
|
||||
val checkedItem by viewModel.selectedItem.collectAsState()
|
||||
// 未调整view
|
||||
ProductListView(
|
||||
ReceiptUnadjustedListView(
|
||||
modifier = Modifier.padding(horizontal = 30.dp),
|
||||
productList = purchaseOrderList,
|
||||
checkedItem = checkedItem,
|
||||
@@ -343,10 +346,11 @@ private fun AdjustedViewItem(purchaseOrder: GoodsInfo, viewModel: ReceiptViewMod
|
||||
Text(text = "x", style = AppTypography.black141428TextStyle.bold())
|
||||
Spacer(modifier = Modifier.width(50.dp))
|
||||
AdjustedRowInputLayout(
|
||||
label = "实收", value = purchaseOrder.receivedNumStr,
|
||||
label = "实收", value = purchaseOrder.receivedNumTemp,
|
||||
onValueChange = {
|
||||
viewModel.updatePurchaseItem(
|
||||
purchaseOrder = purchaseOrder.copy(
|
||||
receivedNumTemp = it,
|
||||
receivedNum = it.toSafeFloat()
|
||||
)
|
||||
)
|
||||
@@ -532,11 +536,16 @@ private fun ReceiptProductEditView(
|
||||
|
||||
RowInputLayout(
|
||||
label = "收货数量",
|
||||
value = selectedItem!!.receivedNumStr,
|
||||
value = selectedItem!!.receivedNumTemp,
|
||||
onValueChange = { value ->
|
||||
viewModel.updateCountInputState(value.isNotEmpty())
|
||||
selectedItem?.let {
|
||||
viewModel.updateSelectedItem(selectedItem!!.copy(receivedNum = value.toSafeFloat()))
|
||||
viewModel.updateSelectedItem(
|
||||
selectedItem!!.copy(
|
||||
receivedNumTemp = value,
|
||||
receivedNum = value.toSafeFloat()
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
trailingLabel = selectedItem?.unitName,
|
||||
@@ -582,7 +591,11 @@ private fun ReceiptProductEditView(
|
||||
isInitUpdate = true,
|
||||
textAlign = TextAlign.End,
|
||||
trailingLabel = selectedItem!!.goodsWeightUnitStr,
|
||||
inputType = InputType.Decimal
|
||||
inputType = InputType.Decimal,
|
||||
onClick = InteractionUtils.rememberDoubleClickDetector {
|
||||
Timber.d("物品重量 双击")
|
||||
SensorScaleUtils.tare()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -593,7 +606,7 @@ private fun ReceiptProductEditView(
|
||||
thickness = 1.dp,
|
||||
color = colorResource(R.color.divider)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(30.dp))
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceAround,
|
||||
modifier = Modifier
|
||||
@@ -604,6 +617,11 @@ private fun ReceiptProductEditView(
|
||||
viewModel.updateSelectedItem(null)
|
||||
}, painter = painterResource(R.mipmap.ic_btn_back), contentDescription = "返回")
|
||||
Image(modifier = Modifier.clickable {
|
||||
val errorInfo = selectedItem!!.hasNullField()
|
||||
if (errorInfo != null) {
|
||||
ToastUtils.showToast(errorInfo)
|
||||
return@clickable
|
||||
}
|
||||
viewModel.updatePurchaseItem(purchaseOrder = selectedItem!!.copy(isAdjusted = true))
|
||||
viewModel.updateSelectedItem(null)
|
||||
}, painter = painterResource(R.mipmap.ic_btn_confirm), contentDescription = "确定")
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.sw.inbound.ui.page
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
@@ -19,8 +18,6 @@ import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
@@ -60,6 +57,7 @@ import com.sw.inbound.ext.withColor
|
||||
import com.sw.inbound.ext.withSize
|
||||
import com.sw.inbound.model.request.PurchaseWarehouseParam
|
||||
import com.sw.inbound.model.response.DictType
|
||||
import com.sw.inbound.sdk.SensorScaleUtils
|
||||
import com.sw.inbound.ui.theme.AppTypography
|
||||
import com.sw.inbound.ui.theme.Black_141428
|
||||
import com.sw.inbound.ui.weight.BottomActionBar
|
||||
@@ -74,6 +72,7 @@ import com.sw.inbound.ui.weight.InputType
|
||||
import com.sw.inbound.ui.weight.RowInputLayout
|
||||
import com.sw.inbound.ui.weight.SelfProcurementListItem
|
||||
import com.sw.inbound.ui.weight.TopTitleBar
|
||||
import com.sw.inbound.utils.InteractionUtils
|
||||
import com.sw.inbound.utils.ToastUtils
|
||||
import com.sw.inbound.viewmodel.SelfProcurementViewModel
|
||||
import timber.log.Timber
|
||||
@@ -83,6 +82,9 @@ import timber.log.Timber
|
||||
heightDp = 1080,
|
||||
showBackground = true
|
||||
)
|
||||
/**
|
||||
* 自采购
|
||||
*/
|
||||
@Composable
|
||||
fun SelfProcurementScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -94,6 +96,7 @@ fun SelfProcurementScreen(
|
||||
|
||||
LaunchedEffect(addToWarehouseResult) {
|
||||
if (addToWarehouseResult) {
|
||||
ToastUtils.showToast("提交入库成功")
|
||||
controller.popBackStack()
|
||||
}
|
||||
}
|
||||
@@ -120,6 +123,7 @@ fun SelfProcurementScreen(
|
||||
controller.popBackStack()
|
||||
}, showRight1Button = true, right1ButtonText = "清空物品", onRight1ButtonClick = {
|
||||
viewModel.clearPurchaseOrders()
|
||||
ToastUtils.showToast("物品清空成功")
|
||||
}, right2ButtonText = "提交入库", onRight2ButtonClick = {
|
||||
viewModel.addToWarehouse()
|
||||
})
|
||||
@@ -288,11 +292,7 @@ private fun DialogContentView(
|
||||
Spacer(modifier = Modifier.height(58.dp))
|
||||
Row(modifier = Modifier.fillMaxWidth()) {
|
||||
// 采集窗口
|
||||
CameraCaptureLayout(modifier = Modifier.width(428.dp), onCancelClick = {
|
||||
|
||||
}, onConfirmClick = {
|
||||
|
||||
})
|
||||
CameraCaptureLayout(modifier = Modifier.width(428.dp))
|
||||
Spacer(modifier = Modifier.width(60.dp))
|
||||
// 右侧输入窗口
|
||||
|
||||
@@ -331,8 +331,9 @@ private fun DialogRightEditView(viewModel: SelfProcurementViewModel) {
|
||||
})
|
||||
ColumnInputText(
|
||||
modifier = Modifier.width(474.dp),
|
||||
label = "物品编码(服务生成)",
|
||||
label = "物品编码(系统生成)",
|
||||
value = "",
|
||||
enabled = false,
|
||||
onValueChange = {
|
||||
// viewModel.updateFormState(formState.copy(goodCode = it))
|
||||
})
|
||||
@@ -470,7 +471,8 @@ fun ColumnInputText(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit = {},
|
||||
dropdownItems: List<DictType> = emptyList(),
|
||||
trailingLabel: String? = null, inputType: InputType = InputType.Text
|
||||
trailingLabel: String? = null, inputType: InputType = InputType.Text,
|
||||
enabled: Boolean = true
|
||||
) {
|
||||
val placeholder = if (dropdownItems.isEmpty()) "请录入" else "请选择"
|
||||
Column(modifier = modifier) {
|
||||
@@ -482,7 +484,8 @@ fun ColumnInputText(
|
||||
onValueChange = onValueChange,
|
||||
placeholderValue = placeholder,
|
||||
trailingLabel = trailingLabel,
|
||||
inputType = inputType
|
||||
inputType = inputType,
|
||||
enabled = enabled
|
||||
)
|
||||
} else {
|
||||
CustomDropdownTextField(
|
||||
@@ -647,14 +650,19 @@ private fun SelfProductEditView(
|
||||
|
||||
RowInputLayout(
|
||||
label = "采购数量",
|
||||
value = selectedItem!!.goodsCountStr,
|
||||
value = selectedItem!!.goodsCountTemp,
|
||||
inputType = InputType.Decimal,
|
||||
isInitUpdate = true,
|
||||
onValueChange = { value ->
|
||||
Timber.d("采购数量 onValueChange value = $value")
|
||||
viewModel.updateCountInputState(value.isNotEmpty())
|
||||
selectedItem.let {
|
||||
viewModel.updateSelectedItem(selectedItem!!.copy(goodsCount = value.toSafeDouble()))
|
||||
viewModel.updateSelectedItem(
|
||||
selectedItem!!.copy(
|
||||
goodsCountTemp = value,
|
||||
goodsCount = value.toSafeDouble()
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
trailingLabel = selectedItem!!.unitName,
|
||||
@@ -699,19 +707,23 @@ private fun SelfProductEditView(
|
||||
isInitUpdate = true,
|
||||
textAlign = TextAlign.End,
|
||||
trailingLabel = selectedItem!!.goodsWeightUnitStr,
|
||||
onClick = InteractionUtils.rememberDoubleClickDetector {
|
||||
Timber.d("物品重量 双击")
|
||||
SensorScaleUtils.tare()
|
||||
},
|
||||
leadingIcon = {
|
||||
Button(
|
||||
onClick = {},
|
||||
modifier = Modifier
|
||||
.padding(0.dp)
|
||||
.fillMaxHeight(),
|
||||
shape = RoundedCornerShape(10.dp),
|
||||
border = BorderStroke(2.dp, color = Color.White),
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color.White,
|
||||
contentColor = Black_141428
|
||||
),
|
||||
) { Text(text = "累计", style = AppTypography.black141428TextStyle) }
|
||||
// Button(
|
||||
// onClick = {},
|
||||
// modifier = Modifier
|
||||
// .padding(0.dp)
|
||||
// .fillMaxHeight(),
|
||||
// shape = RoundedCornerShape(10.dp),
|
||||
// border = BorderStroke(2.dp, color = Color.White),
|
||||
// colors = ButtonDefaults.buttonColors(
|
||||
// containerColor = Color.White,
|
||||
// contentColor = Black_141428
|
||||
// ),
|
||||
// ) { Text(text = "累计", style = AppTypography.black141428TextStyle) }
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -748,6 +760,7 @@ private fun SelfProductEditView(
|
||||
ToastUtils.showToast(errInfo)
|
||||
return@CustomButton
|
||||
}
|
||||
|
||||
viewModel.addPurchaseItem(selectedItem!!)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -50,11 +50,12 @@ import com.sw.inbound.utils.ToastUtils
|
||||
import timber.log.Timber
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* 相机预览 -默认不预览,支持拍照
|
||||
*/
|
||||
@Composable
|
||||
fun CameraCaptureLayout(
|
||||
modifier: Modifier = Modifier,
|
||||
onCancelClick: () -> Unit = {},
|
||||
onConfirmClick: () -> Unit = {}
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
var showCamera by remember { mutableStateOf(false) }
|
||||
@@ -79,7 +80,6 @@ fun CameraCaptureLayout(
|
||||
verticalArrangement = Arrangement.spacedBy(24.dp)
|
||||
) {
|
||||
if (showCamera) {
|
||||
// CameraPreview()
|
||||
// 摄像头预览
|
||||
CameraPreview(
|
||||
modifier = Modifier
|
||||
@@ -183,7 +183,7 @@ fun CameraCaptureLayout(
|
||||
val savedUri = outputFileResults.savedUri ?: Uri.fromFile(photoFile)
|
||||
photoUri = savedUri
|
||||
Timber.d("photoUri = $photoUri")
|
||||
Toast.makeText(context, "照片已保存", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(context, "图片已保存", Toast.LENGTH_SHORT).show()
|
||||
showCamera = false
|
||||
GlobalData.imageUri = photoUri
|
||||
}
|
||||
@@ -208,7 +208,7 @@ fun CameraCaptureLayout(
|
||||
|
||||
// 生命周期管理
|
||||
DisposableEffect(lifecycleOwner) {
|
||||
Timber.d("cameraController 释放")
|
||||
Timber.d("cameraController")
|
||||
cameraController.bindToLifecycle(lifecycleOwner)
|
||||
onDispose { }
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import com.sw.inbound.R
|
||||
|
||||
/**
|
||||
* 相机预览
|
||||
*/
|
||||
@Composable
|
||||
fun CameraPreview(
|
||||
controller: LifecycleCameraController,
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package com.sw.inbound.ui.weight
|
||||
|
||||
import android.Manifest
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.PermissionState
|
||||
import com.google.accompanist.permissions.isGranted
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import com.google.accompanist.permissions.shouldShowRationale
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Preview
|
||||
@Composable
|
||||
fun CameraScreen() {
|
||||
val cameraPermissionState =
|
||||
rememberPermissionState(permission = Manifest.permission.CAMERA)
|
||||
LaunchedEffect(key1 = Unit) {
|
||||
if (!cameraPermissionState.status.isGranted && !cameraPermissionState.status.shouldShowRationale) {
|
||||
cameraPermissionState.launchPermissionRequest()
|
||||
}
|
||||
}
|
||||
|
||||
if (cameraPermissionState.status.isGranted) {
|
||||
//接受拍照的授权
|
||||
// CameraContent()
|
||||
} else {
|
||||
//未授权,显示未授权的界面
|
||||
NoPermissionScreen(cameraPermissionState)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalPermissionsApi::class)
|
||||
@Composable
|
||||
fun NoPermissionScreen(cameraPermissionState: PermissionState) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
val message = if (cameraPermissionState.status.shouldShowRationale) {
|
||||
"未获取照相机权限导致无法使用照相机功能"
|
||||
} else {
|
||||
"请授权照相机的权限"
|
||||
}
|
||||
Text(message)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Button(onClick = {
|
||||
cameraPermissionState.launchPermissionRequest()
|
||||
}) {
|
||||
Text("请求授权")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ import com.sw.inbound.model.response.DictType
|
||||
import com.sw.inbound.ui.theme.AppTypography
|
||||
import com.sw.inbound.ui.theme.Black_141428
|
||||
|
||||
/**
|
||||
* 表单中的下拉菜单
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CustomDropdownTextField(
|
||||
|
||||
@@ -30,6 +30,9 @@ import com.sw.inbound.R
|
||||
import com.sw.inbound.ui.theme.AppTypography
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* 搜索框
|
||||
*/
|
||||
@Composable
|
||||
fun CustomSearchView(onValueChange: (String) -> Unit = {}, onSearchClick: (String) -> Unit) {
|
||||
var searchText by remember { mutableStateOf("") }
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.sw.inbound.ui.weight
|
||||
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import com.sw.inbound.ui.theme.AppTypography
|
||||
|
||||
/**
|
||||
* 自定义单行文本
|
||||
*/
|
||||
@Composable
|
||||
fun CustomSingleRightText(
|
||||
modifier: Modifier,
|
||||
text: String,
|
||||
style: TextStyle = AppTypography.blackTextStyle,
|
||||
textAlign: TextAlign = TextAlign.End
|
||||
) {
|
||||
Text(
|
||||
modifier = modifier,
|
||||
text = text,
|
||||
textAlign = textAlign,
|
||||
style = style,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
@@ -24,6 +24,9 @@ import androidx.compose.ui.unit.sp
|
||||
import com.sw.inbound.R
|
||||
import com.sw.inbound.model.response.DictType
|
||||
|
||||
/**
|
||||
* 自定义顶部仓库下拉
|
||||
*/
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun CustomSpinner(
|
||||
|
||||
@@ -2,10 +2,12 @@ package com.sw.inbound.ui.weight
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentHeight
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.KeyboardActions
|
||||
@@ -84,22 +86,26 @@ enum class InputType {
|
||||
Decimal // 浮点
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义输入框
|
||||
*/
|
||||
@Composable
|
||||
fun CustomTextField(
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
modifier: Modifier = Modifier.height(60.dp),
|
||||
placeholderValue: String = "请录入",
|
||||
trailingLabel: String? = null,
|
||||
placeholderValue: String = "请录入", // 占位文本
|
||||
trailingLabel: String? = null, // 右侧文字
|
||||
textAlign: TextAlign = TextAlign.Start,
|
||||
textStyle: TextStyle? = null,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
leadingIcon: @Composable (() -> Unit)? = null, // 左侧布局
|
||||
enabled: Boolean = true,
|
||||
inputType: InputType = InputType.Text,
|
||||
hasNext: Boolean = true,
|
||||
isInitUpdate: Boolean = false,
|
||||
inputType: InputType = InputType.Text, // 输入类型
|
||||
hasNext: Boolean = true, // 键盘显示下一个
|
||||
isInitUpdate: Boolean = false, // 是否需要根据原始数据变动
|
||||
keyboardOptions: KeyboardOptions? = null,
|
||||
keyboardActions: KeyboardActions? = null
|
||||
keyboardActions: KeyboardActions? = null,
|
||||
onClick: () -> Unit = {}, // 点击
|
||||
) {
|
||||
val containerColor = if (enabled) Color.Transparent else Gray_DCDCF0
|
||||
// var inputValue by remember { mutableStateOf(value) }
|
||||
@@ -109,8 +115,8 @@ fun CustomTextField(
|
||||
}
|
||||
val focusManager = LocalFocusManager.current
|
||||
|
||||
fun onEditingComplete() {
|
||||
Timber.d("onEditingComplete inputValue = $inputValue")
|
||||
fun onEditingComplete(isFocus: Boolean) {
|
||||
Timber.d("onEditingComplete inputValue = $inputValue, isFocus = $isFocus")
|
||||
onValueChange(inputValue)
|
||||
}
|
||||
|
||||
@@ -133,20 +139,20 @@ fun CustomTextField(
|
||||
InputType.Number -> {
|
||||
if (newValue.isEmpty() || newValue.isValidNumber()) {
|
||||
inputValue = newValue
|
||||
onEditingComplete()
|
||||
onEditingComplete(true)
|
||||
}
|
||||
}
|
||||
|
||||
InputType.Decimal -> {
|
||||
if (newValue.isEmpty() || newValue.isValidFloat()) {
|
||||
inputValue = newValue
|
||||
onEditingComplete()
|
||||
onEditingComplete(true)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
inputValue = newValue
|
||||
onEditingComplete()
|
||||
onEditingComplete(true)
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -159,9 +165,11 @@ fun CustomTextField(
|
||||
color = Gray_DCDCF0,
|
||||
shape = RoundedCornerShape(10.dp)
|
||||
)
|
||||
.clickable(onClick = onClick)
|
||||
// .focusable()
|
||||
.onFocusChanged(onFocusChanged = { focusState ->
|
||||
{
|
||||
onEditingComplete()
|
||||
onEditingComplete(focusState.isFocused)
|
||||
}
|
||||
}),
|
||||
colors = TextFieldDefaults.colors(
|
||||
@@ -187,23 +195,25 @@ fun CustomTextField(
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingLabel?.let { label ->
|
||||
{
|
||||
Text(
|
||||
text = trailingLabel,
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.wrapContentHeight(Alignment.CenterVertically),
|
||||
style = AppTypography.gray96a0aaTextStyle
|
||||
)
|
||||
Box(modifier = Modifier.padding(start = 10.dp, end = 20.dp)) {
|
||||
Text(
|
||||
text = trailingLabel,
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.wrapContentHeight(Alignment.CenterVertically),
|
||||
style = AppTypography.gray96a0aaTextStyle
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
keyboardOptions = keyboardOptions
|
||||
?: KeyboardOptions.Default.copy(imeAction = if (hasNext) ImeAction.Next else ImeAction.Done),
|
||||
keyboardActions = keyboardActions ?: KeyboardActions(onNext = {
|
||||
focusManager.moveFocus(focusDirection = FocusDirection.Next)
|
||||
onEditingComplete()
|
||||
onEditingComplete(false)
|
||||
}, onDone = {
|
||||
focusManager.clearFocus()
|
||||
onEditingComplete()
|
||||
onEditingComplete(false)
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
package com.sw.inbound.ui.weight
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.material3.CircularProgressIndicator
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import com.sw.inbound.ext.withColor
|
||||
import com.sw.inbound.network.LoadingState
|
||||
import com.sw.inbound.ui.theme.AppTypography
|
||||
|
||||
@Composable
|
||||
fun GlobalLoading() {
|
||||
@@ -22,10 +27,16 @@ fun GlobalLoading() {
|
||||
dismissOnClickOutside = false
|
||||
)
|
||||
) {
|
||||
Column {
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
CircularProgressIndicator(modifier = Modifier)
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Text(text = "请稍等...")
|
||||
Text(
|
||||
text = "请稍等...",
|
||||
style = AppTypography.grayTextStyle.withColor(color = Color.White)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-22
@@ -13,16 +13,13 @@ import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.sw.inbound.R
|
||||
import com.sw.inbound.ext.bold
|
||||
@@ -30,9 +27,11 @@ import com.sw.inbound.model.response.GoodsInfo
|
||||
import com.sw.inbound.ui.theme.AppTypography
|
||||
import com.sw.inbound.ui.theme.Gray_DCDCF0
|
||||
|
||||
|
||||
/**
|
||||
* 收货-未调整列表
|
||||
*/
|
||||
@Composable
|
||||
fun ProductListView(
|
||||
fun ReceiptUnadjustedListView(
|
||||
modifier: Modifier = Modifier,
|
||||
productList: List<GoodsInfo>,
|
||||
checkedItem: GoodsInfo? = null,
|
||||
@@ -141,21 +140,4 @@ fun ProductListView(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CustomSingleRightText(
|
||||
modifier: Modifier,
|
||||
text: String,
|
||||
style: TextStyle = AppTypography.blackTextStyle,
|
||||
textAlign: TextAlign = TextAlign.End
|
||||
) {
|
||||
Text(
|
||||
modifier = modifier,
|
||||
text = text,
|
||||
textAlign = textAlign,
|
||||
style = style,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
+5
-5
@@ -23,16 +23,16 @@ import com.sw.inbound.ui.theme.AppTypography
|
||||
*/
|
||||
@Composable
|
||||
fun RowInputLayout(
|
||||
label: String,
|
||||
label: String, // 左侧文字
|
||||
value: String,
|
||||
onValueChange: (String) -> Unit,
|
||||
dropdownItems: List<DictType>? = null,
|
||||
hasNext: Boolean = true,
|
||||
dropdownItems: List<DictType>? = null, // 下拉列表
|
||||
hasNext: Boolean = true, // 键盘显示下一步
|
||||
inputType: InputType = InputType.Text,
|
||||
trailingLabel: String? = null,
|
||||
trailingLabel: String? = null, // 尾部文字
|
||||
keyboardOptions: KeyboardOptions? = null,
|
||||
keyboardActions: KeyboardActions? = null,
|
||||
isInitUpdate: Boolean = false
|
||||
isInitUpdate: Boolean = false // 是否根据原始数据更新
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
@@ -13,16 +13,13 @@ import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.sw.inbound.R
|
||||
import com.sw.inbound.ext.bold
|
||||
@@ -30,7 +27,9 @@ import com.sw.inbound.model.request.PurchaseWarehouseParam
|
||||
import com.sw.inbound.ui.theme.AppTypography
|
||||
import com.sw.inbound.ui.theme.Gray_DCDCF0
|
||||
|
||||
|
||||
/**
|
||||
* 自采购 左侧列表
|
||||
*/
|
||||
@Composable
|
||||
fun SelfProcurementListItem(
|
||||
modifier: Modifier = Modifier,
|
||||
@@ -141,21 +140,4 @@ fun SelfProcurementListItem(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CustomSingleRightText(
|
||||
modifier: Modifier,
|
||||
text: String,
|
||||
style: TextStyle = AppTypography.blackTextStyle,
|
||||
textAlign: TextAlign = TextAlign.End
|
||||
) {
|
||||
Text(
|
||||
modifier = modifier,
|
||||
text = text,
|
||||
textAlign = textAlign,
|
||||
style = style,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
}
|
||||
@@ -52,6 +52,9 @@ fun testSingleGroup() {
|
||||
// SingleSelectButtonGroup(list)
|
||||
}
|
||||
|
||||
/**
|
||||
* 搜索结果列表,可选中
|
||||
*/
|
||||
@Composable
|
||||
fun SingleSelectButtonGroup(
|
||||
options: List<SearchGoodsInfo.Record>,
|
||||
@@ -65,15 +68,15 @@ fun SingleSelectButtonGroup(
|
||||
var selectedOption by remember { mutableStateOf(options.firstOrNull() ?: "") }
|
||||
|
||||
// 定义颜色
|
||||
val selectedColor = Color(0xFFD9E3F9) // 选中颜色 #D9E3F9
|
||||
val unselectedColor = Color(0xFFDCDCF0) // 未选中颜色 #DCDCF0
|
||||
val selectedColor = Color(0xFFD9E3F9)
|
||||
val unselectedColor = Color(0xFFDCDCF0)
|
||||
|
||||
LazyVerticalGrid(
|
||||
columns = GridCells.Fixed(2), // 每行2列
|
||||
modifier = Modifier
|
||||
.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.spacedBy(horizontalSpacing), // 水平间距13dp
|
||||
verticalArrangement = Arrangement.spacedBy(verticalSpacing) // 垂直间距13dp
|
||||
horizontalArrangement = Arrangement.spacedBy(horizontalSpacing),
|
||||
verticalArrangement = Arrangement.spacedBy(verticalSpacing)
|
||||
) {
|
||||
items(items = options) { option ->
|
||||
Box(
|
||||
@@ -90,7 +93,7 @@ fun SingleSelectButtonGroup(
|
||||
onOptionSelected(option)
|
||||
},
|
||||
contentAlignment = Alignment.Center
|
||||
// .padding(vertical = 20.dp) // 垂直内边距
|
||||
// .padding(vertical = 20.dp)
|
||||
) {
|
||||
Text(
|
||||
text = option.goodsNameStr,
|
||||
|
||||
@@ -42,6 +42,9 @@ import kotlinx.coroutines.delay
|
||||
heightDp = 1080,
|
||||
showBackground = true
|
||||
)
|
||||
/**
|
||||
* 标题
|
||||
*/
|
||||
@Composable
|
||||
fun TopTitleBar(
|
||||
modifier: Modifier = Modifier,
|
||||
|
||||
@@ -33,6 +33,9 @@ import com.sw.inbound.ui.theme.AppTypography
|
||||
import com.sw.inbound.ui.weight.CustomButton
|
||||
import com.sw.inbound.ui.weight.CustomOutlinedButton
|
||||
|
||||
/**
|
||||
* 收货确认弹窗
|
||||
*/
|
||||
@Composable
|
||||
fun ReceiptTipDialog(
|
||||
modifier: Modifier = Modifier,
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.sw.inbound.utils
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableLongStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
@@ -126,12 +128,12 @@ object InteractionUtils {
|
||||
* 双击检测器
|
||||
*/
|
||||
class DoubleClickDetector(
|
||||
private val timeout: Long = 300L,
|
||||
private val timeout: Long = 500L,
|
||||
private val onSingleClick: () -> Unit = {},
|
||||
private val onDoubleClick: () -> Unit
|
||||
) {
|
||||
private var clickCount by mutableStateOf(0)
|
||||
private var lastClickTime by mutableStateOf(0L)
|
||||
private var clickCount by mutableIntStateOf(0)
|
||||
private var lastClickTime by mutableLongStateOf(0L)
|
||||
|
||||
/**
|
||||
* 处理点击事件
|
||||
|
||||
@@ -121,31 +121,4 @@ abstract class BaseViewModel(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getStoreList(): ArrayList<String> {
|
||||
return arrayListOf(
|
||||
"默认仓库",
|
||||
"仓库1",
|
||||
"仓库2",
|
||||
"仓库3",
|
||||
)
|
||||
}
|
||||
|
||||
fun getPurchasingUnit(): ArrayList<String> {
|
||||
return arrayListOf(
|
||||
"斤",
|
||||
"瓶",
|
||||
"箱"
|
||||
)
|
||||
}
|
||||
|
||||
fun getProductList(): ArrayList<String> {
|
||||
return arrayListOf<String>(
|
||||
"胶东大白菜",
|
||||
"玉田尖白菜1",
|
||||
"玉田尖白菜2",
|
||||
"玉田尖白菜3",
|
||||
"玉田尖白菜4"
|
||||
)
|
||||
}
|
||||
}
|
||||
+7
-1
@@ -7,11 +7,17 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* 采购订单
|
||||
*/
|
||||
@HiltViewModel
|
||||
class ProductViewModel @Inject constructor(
|
||||
class PurchaseOrderViewModel @Inject constructor(
|
||||
private val repository: RemoteRepository
|
||||
) : BaseViewModel(repository) {
|
||||
|
||||
/**
|
||||
* 采购订单-供应商列表
|
||||
*/
|
||||
private val _supplierList = MutableStateFlow<List<SupplierInfo?>>(emptyList())
|
||||
val supplierList: StateFlow<List<SupplierInfo?>> = _supplierList
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.sw.inbound.viewmodel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.sw.inbound.ext.toSafeBigDecimal
|
||||
import com.sw.inbound.ext.toSafeFloat
|
||||
import com.sw.inbound.ext.toSafeString
|
||||
import com.sw.inbound.model.request.UploadInfo
|
||||
import com.sw.inbound.model.response.DictType
|
||||
import com.sw.inbound.model.response.GoodsInfo
|
||||
@@ -22,6 +23,9 @@ import kotlinx.coroutines.flow.update
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* 收货
|
||||
*/
|
||||
@HiltViewModel
|
||||
class ReceiptViewModel @Inject constructor(
|
||||
private val repository: RemoteRepository
|
||||
@@ -37,16 +41,6 @@ class ReceiptViewModel @Inject constructor(
|
||||
private val _currentPurchaseInfo = MutableStateFlow<PurchaseInfo?>(null)
|
||||
val currentPurchaseInfo: StateFlow<PurchaseInfo?> = _currentPurchaseInfo
|
||||
|
||||
// 自动从 currentPurchaseInfo 派生 orders
|
||||
// private val _orders: StateFlow<List<GoodsInfo>> = currentPurchaseInfo
|
||||
// .map { purchaseInfo ->
|
||||
// purchaseInfo?.receiveGoodsInfoList ?: emptyList()
|
||||
// }
|
||||
// .stateIn(
|
||||
// viewModelScope,
|
||||
// SharingStarted.WhileSubscribed(5000), // 或者使用 Lazily/Eagerly 根据需求
|
||||
// emptyList()
|
||||
// )
|
||||
private val _orders = MutableStateFlow<List<GoodsInfo>>(emptyList())
|
||||
val orders: StateFlow<List<GoodsInfo>> = _orders.asStateFlow()
|
||||
|
||||
@@ -64,9 +58,7 @@ class ReceiptViewModel @Inject constructor(
|
||||
.map { orders -> orders.filter { !it.isAdjusted && it.goodId != null } }
|
||||
.stateIn(viewModelScope, SharingStarted.Lazily, emptyList())
|
||||
|
||||
val mergedOrders: StateFlow<List<GoodsInfo>> = _orders
|
||||
|
||||
//
|
||||
// 选中的商品
|
||||
private val _selectedItem = MutableStateFlow<GoodsInfo?>(null)
|
||||
val selectedItem: StateFlow<GoodsInfo?> = _selectedItem
|
||||
|
||||
@@ -74,9 +66,11 @@ class ReceiptViewModel @Inject constructor(
|
||||
private val _searchListItems = MutableStateFlow<List<SearchGoodsInfo.Record>>(emptyList())
|
||||
val searchListItems: StateFlow<List<SearchGoodsInfo.Record>> = _searchListItems
|
||||
|
||||
// 收货请求结果
|
||||
private val _receiptResult = MutableStateFlow<Boolean>(false)
|
||||
val receiptResult: StateFlow<Boolean> = _receiptResult
|
||||
|
||||
// 物品数量 是否由用户输入
|
||||
private val _countUserInput = MutableStateFlow<Boolean>(false)
|
||||
|
||||
/**
|
||||
@@ -87,10 +81,21 @@ class ReceiptViewModel @Inject constructor(
|
||||
_adjustState.value = isAdjustState
|
||||
}
|
||||
|
||||
fun StateFlow<List<GoodsInfo>>.getValidOrders(): List<GoodsInfo> {
|
||||
return this.value.filter { it.goodId != null }
|
||||
}
|
||||
/**
|
||||
* 更新收货提示弹窗
|
||||
*/
|
||||
fun updateReceiptDialog(showDialog: Boolean) {
|
||||
if (_orders.getValidOrders().isEmpty()) {
|
||||
ToastUtils.showToast("订单为空或包含异常数据")
|
||||
return
|
||||
}
|
||||
if (!unadjustedOrders.value.isEmpty()) {
|
||||
ToastUtils.showToast("请先调整物品信息")
|
||||
return
|
||||
}
|
||||
_showReceiptDialog.value = showDialog
|
||||
}
|
||||
|
||||
@@ -151,12 +156,12 @@ class ReceiptViewModel @Inject constructor(
|
||||
/**
|
||||
* 更新所有商品仓库
|
||||
*/
|
||||
fun updateAllPurchaseStore(store: DictType, predicate: (GoodsInfo) -> Boolean = { true }) {
|
||||
fun updateAllPurchaseStore(warehouse: DictType, predicate: (GoodsInfo) -> Boolean = { true }) {
|
||||
_orders.update { currentList ->
|
||||
currentList.map { order ->
|
||||
if (predicate(order)) order.copy(
|
||||
warehouseId = store.id,
|
||||
warehouseName = store.value
|
||||
warehouseId = warehouse.id,
|
||||
warehouseName = warehouse.value
|
||||
) else order
|
||||
}
|
||||
}
|
||||
@@ -192,6 +197,9 @@ class ReceiptViewModel @Inject constructor(
|
||||
Timber.d("startSensorScale weight = $weight, count = $count, finalCount = $finalCount, consumeValue = $consumeValue, purchaseValue = $purchaseValue")
|
||||
_selectedItem.value = info.copy(
|
||||
goodsWeight = weight.toSafeBigDecimal(),
|
||||
receivedNumTemp = if (_countUserInput.value) info.receivedNumTemp else count.toSafeString(
|
||||
currentItem.unitName
|
||||
),
|
||||
receivedNum = if (_countUserInput.value) info.receivedNum else finalCount
|
||||
)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import com.sw.inbound.GlobalData
|
||||
import com.sw.inbound.ext.toSafeBigDecimal
|
||||
import com.sw.inbound.ext.toSafeDouble
|
||||
import com.sw.inbound.ext.toSafeString
|
||||
import com.sw.inbound.model.request.GoodsAddParam
|
||||
import com.sw.inbound.model.request.PurchaseWarehouseParam
|
||||
import com.sw.inbound.model.response.DictType
|
||||
@@ -15,12 +16,14 @@ import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* 自采购
|
||||
*/
|
||||
@HiltViewModel
|
||||
class SelfProcurementViewModel @Inject constructor(
|
||||
private val repository: RemoteRepository
|
||||
@@ -39,6 +42,7 @@ class SelfProcurementViewModel @Inject constructor(
|
||||
private val _globalWarehouse = MutableStateFlow<DictType>(DictType(-1, "选择仓库"))
|
||||
val globalWarehouse: StateFlow<DictType> = _globalWarehouse
|
||||
|
||||
// 采购列表
|
||||
private val _purchaseList = MutableStateFlow<List<PurchaseWarehouseParam>>(emptyList())
|
||||
val purchaseList: StateFlow<List<PurchaseWarehouseParam>> = _purchaseList
|
||||
|
||||
@@ -58,14 +62,6 @@ class SelfProcurementViewModel @Inject constructor(
|
||||
private val _weightInfo = MutableStateFlow<Double?>(0.0)
|
||||
val weightInfo: StateFlow<Double?> = _weightInfo
|
||||
|
||||
|
||||
private val _showCameraPreview = MutableStateFlow(true)
|
||||
val showCameraPreview = _showCameraPreview.asStateFlow()
|
||||
|
||||
fun updateCameraPreviewShow(show: Boolean) {
|
||||
_showCameraPreview.value = show
|
||||
}
|
||||
|
||||
/**
|
||||
* 数量是否是用户输入的值
|
||||
*/
|
||||
@@ -95,6 +91,9 @@ class SelfProcurementViewModel @Inject constructor(
|
||||
Timber.d("startSensorScale weight = $weight, count = $count, finalCount = $finalCount, consumeValue = $consumeValue, purchaseValue = $purchaseValue")
|
||||
_selectedItem.value = info.copy(
|
||||
goodsWeight = weight.toSafeBigDecimal(),
|
||||
goodsCountTemp = if (_countUserInput.value) info.goodsCountTemp else count.toSafeString(
|
||||
currentItem.unitName
|
||||
),
|
||||
goodsCount = if (_countUserInput.value) info.goodsCount else finalCount
|
||||
)
|
||||
}
|
||||
@@ -124,6 +123,10 @@ class SelfProcurementViewModel @Inject constructor(
|
||||
|
||||
// 添加订单
|
||||
fun addPurchaseItem(purchaseOrder: PurchaseWarehouseParam) {
|
||||
if (_purchaseList.value.any { it.goodsId == purchaseOrder.goodsId }) {
|
||||
ToastUtils.showToast("添加失败,当前物品已添加")
|
||||
return
|
||||
}
|
||||
_purchaseList.update { currentList ->
|
||||
// 当已经添加过则忽略
|
||||
if (currentList.any { it.goodsId == purchaseOrder.goodsId }) {
|
||||
@@ -181,9 +184,9 @@ class SelfProcurementViewModel @Inject constructor(
|
||||
delay(50)
|
||||
_selectedItem.value = PurchaseWarehouseParam(
|
||||
warehouseId = warehouse.id,
|
||||
goodsId = searchFirst.goodsId!!,
|
||||
goodsId = searchFirst.goodsId ?: 0,
|
||||
goodsName = searchFirst.goodsName,
|
||||
kcUnitId = searchFirst.kcUnitId!!,
|
||||
kcUnitId = searchFirst.kcUnitId ?: 0,
|
||||
unitList = searchFirst.unitVoList,
|
||||
)
|
||||
}
|
||||
@@ -220,6 +223,7 @@ class SelfProcurementViewModel @Inject constructor(
|
||||
return@launchWithLoading
|
||||
}
|
||||
_showAddProductDialog.value = false
|
||||
_goodsAddParam.value = GoodsAddParam()
|
||||
val searchFirst = response.data!!.records?.get(0)
|
||||
searchFirst?.let {
|
||||
updateSelectedItemWithSearch(searchFirst)
|
||||
@@ -229,7 +233,10 @@ class SelfProcurementViewModel @Inject constructor(
|
||||
}
|
||||
|
||||
fun addToWarehouse() {
|
||||
if (_purchaseList.value.isEmpty()) return
|
||||
if (_purchaseList.value.isEmpty()) {
|
||||
ToastUtils.showToast("采购列表为空")
|
||||
return
|
||||
}
|
||||
launchWithLoading {
|
||||
val response = repository.selfPurchaseWarehousing(_purchaseList.value)
|
||||
if (parseResponse(response)) {
|
||||
|
||||
Reference in New Issue
Block a user