添加物品单位功能

This commit is contained in:
zxj
2025-08-05 16:51:11 +08:00
parent 2eec3ec1d4
commit d99c0e6e79
14 changed files with 533 additions and 127 deletions
@@ -14,12 +14,10 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
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.HorizontalDivider
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
@@ -42,8 +40,6 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.navigation.NavController
@@ -54,10 +50,10 @@ import com.sw.inbound.ext.bold
import com.sw.inbound.ext.dashedBorder
import com.sw.inbound.ext.isValidAmount
import com.sw.inbound.ext.medium
import com.sw.inbound.ext.toFormattedString
import com.sw.inbound.ext.toSafeBigDecimal
import com.sw.inbound.ext.toSafeDouble
import com.sw.inbound.ext.toSafeFloat
import com.sw.inbound.ext.toSafeString
import com.sw.inbound.ext.withColor
import com.sw.inbound.ext.withSize
import com.sw.inbound.model.request.PurchaseWarehouseParam
@@ -77,6 +73,8 @@ 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.ui.weight.dialog.AddProductDialog
import com.sw.inbound.ui.weight.dialog.AddPurchaseUnitDialog
import com.sw.inbound.utils.InteractionUtils
import com.sw.inbound.utils.ToastUtils
import com.sw.inbound.viewmodel.SelfProcurementViewModel
@@ -97,6 +95,7 @@ fun SelfProcurementScreen(
viewModel: SelfProcurementViewModel = hiltViewModel<SelfProcurementViewModel>()
) {
val showDialog by viewModel.showAddProductDialog.collectAsState()
val showPurchaseUnitDialog by viewModel.showAddPurchaseUnitDialog.collectAsState()
val addToWarehouseResult by viewModel.addToWarehouseResult.collectAsState()
LaunchedEffect(addToWarehouseResult) {
@@ -140,14 +139,28 @@ fun SelfProcurementScreen(
modifier = Modifier,
onCancelClick = {
viewModel.updateAddProductDialog(false)
viewModel.cleanGoodsAddParam()
},
onConfirmClick = {
viewModel.addGoodsInfo()
}
) {
// 弹窗内容
DialogContentView(modifier, viewModel)
AddProductDialogContentView(modifier, viewModel)
}
}
if (showPurchaseUnitDialog) {
AddPurchaseUnitDialog(
onDismiss = { viewModel.updateAddPurchaseUnitDialog(false) },
modifier = Modifier,
onCancelClick = {
viewModel.updateAddPurchaseUnitDialog(false)
},
onConfirmClick = {
viewModel.addGoodsPurchaseUnit()
}
) {
// 弹窗内容
AddPurchaseUnitDialogContentView(modifier, viewModel)
}
}
}
@@ -295,7 +308,7 @@ fun ProductIdentification(viewModel: SelfProcurementViewModel) {
}
@Composable
private fun DialogContentView(
private fun AddProductDialogContentView(
modifier: Modifier,
viewModel: SelfProcurementViewModel
) {
@@ -445,10 +458,11 @@ private fun DialogRightEditView(viewModel: SelfProcurementViewModel) {
dropdownItems = unitTypeList,
placeholderValue = "请选择",
onValueChange = { value ->
val purchaseUnit = unitTypeList.find { it.value == value }?.id ?: 0
viewModel.updateGoodsAddParam(
goodsAddParam.copy(
purchaseUnit = unitTypeList.find { it.value == value }?.id
?: 0
purchaseUnit = purchaseUnit,
purchaseValue = if (goodsAddParam.unitId == purchaseUnit) 1f else 0f
)
)
})
@@ -457,8 +471,9 @@ private fun DialogRightEditView(viewModel: SelfProcurementViewModel) {
Spacer(modifier = Modifier.width(24.dp))
CustomTextField(
modifier = Modifier.width(200.dp),
value = goodsAddParam.purchaseValue.toFormattedString(),
value = goodsAddParam.purchaseValue.toSafeString(goodsAddParam.unitIdStr),
placeholderValue = "请录入",
isInitUpdate = true,
onValueChange = {
viewModel.updateGoodsAddParam(goodsAddParam.copy(purchaseValue = it.toSafeFloat()))
}, inputType = InputType.Decimal
@@ -486,6 +501,125 @@ private fun DialogRightEditView(viewModel: SelfProcurementViewModel) {
}
}
@Composable
private fun AddPurchaseUnitDialogContentView(
modifier: Modifier,
viewModel: SelfProcurementViewModel
) {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = modifier.fillMaxSize()
) {
Spacer(modifier = Modifier.height(90.dp))
Text(
text = "添加采购单位", style = TextStyle().bold().withSize(36.sp).withColor(
Black_141428
)
)
Spacer(modifier = Modifier.height(56.dp))
HorizontalDivider(thickness = 1.dp, color = colorResource(R.color.divider))
Spacer(modifier = Modifier.height(58.dp))
Row(modifier = Modifier.fillMaxWidth()) {
DialogAddPurchaseUnitEditView(viewModel)
}
Spacer(modifier = Modifier.height(75.dp))
HorizontalDivider(thickness = 1.dp, color = colorResource(R.color.divider))
}
}
// 添加采购单位
@Composable
private fun DialogAddPurchaseUnitEditView(viewModel: SelfProcurementViewModel) {
val unitTypeList = GlobalData.unitTypeList
val goodsAddUnitParam by viewModel.goodsAddUnitParam.collectAsState()
val canChange by viewModel.dropdownTextChange.collectAsState()
Column(
modifier = Modifier
.fillMaxHeight()
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.spacedBy(29.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(60.dp)
) {
ColumnInputText(
modifier = Modifier.fillMaxWidth(),
value = goodsAddUnitParam.unitIdStr,
label = "库存单位",
enabled = canChange,
dropdownItems = unitTypeList,
onValueChange = { value ->
viewModel.updateGoodsPurchaseUnit(
goodsAddUnitParam.copy(
unitId = unitTypeList.find { it.value == value }?.id ?: 0
)
)
},
)
}
Column {
Text(text = "采购单位", style = AppTypography.black141428TextStyle)
Spacer(modifier = Modifier.height(20.dp))
Row(
modifier = Modifier
.height(92.dp)
.fillMaxWidth()
.dashedBorder()
.padding(vertical = 16.dp, horizontal = 26.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Text("1", style = AppTypography.black141428TextStyle.bold())
Spacer(modifier = Modifier.width(24.dp))
CustomDropdownTextField(
modifier = Modifier.width(260.dp),
value = goodsAddUnitParam.purchaseUnitStr,
dropdownItems = unitTypeList,
placeholderValue = "请选择",
onValueChange = { value ->
val purchaseUnit = unitTypeList.find { it.value == value }?.id ?: 0
viewModel.updateGoodsPurchaseUnit(
goodsAddUnitParam.copy(
purchaseUnit = purchaseUnit,
purchaseValue = if (goodsAddUnitParam.unitId == purchaseUnit) 1f else 0f
)
)
})
Spacer(modifier = Modifier.width(24.dp))
Text(text = "=", style = AppTypography.gray96a0aaTextStyle)
Spacer(modifier = Modifier.width(24.dp))
CustomTextField(
modifier = Modifier.width(260.dp),
value = goodsAddUnitParam.purchaseValue.toSafeString(goodsAddUnitParam.unitIdStr),
isInitUpdate = true,
placeholderValue = "请录入",
onValueChange = {
viewModel.updateGoodsPurchaseUnit(goodsAddUnitParam.copy(purchaseValue = it.toSafeFloat()))
}, inputType = InputType.Decimal
)
Spacer(modifier = Modifier.width(24.dp))
Text(goodsAddUnitParam.unitIdStr, style = AppTypography.gray96a0aaTextStyle)
}
}
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize()
) {
Text(
text = "完善更多单位信息请登录后台维护,建议及时操作以确保信息准确",
style = AppTypography.gray999999TextStyle
)
}
}
}
@Composable
fun ColumnInputText(
@@ -516,84 +650,12 @@ fun ColumnInputText(
onValueChange = onValueChange,
dropdownItems = dropdownItems,
placeholderValue = placeholder,
enabled = enabled
)
}
}
}
/**
* 添加物品弹窗
*/
@Composable
fun AddProductDialog(
modifier: Modifier = Modifier,
onCancelClick: () -> Unit,
onConfirmClick: () -> Unit,
onDismiss: () -> Unit,
content: @Composable () -> Unit
) {
Dialog(
onDismissRequest = onDismiss,
properties = DialogProperties(
usePlatformDefaultWidth = false, // 不使用平台默认宽度
decorFitsSystemWindows = false // 允许内容延伸到系统窗口后面
)
) {
Surface(
modifier = Modifier
.padding(start = 60.dp, end = 60.dp, bottom = 40.dp) // 设置弹窗距离边框60dp
.wrapContentSize(),
shape = RoundedCornerShape(30.dp),
color = Color.White,
shadowElevation = 0.dp
) {
ToastUtils.ToastComposable()
Column(
modifier = Modifier
.fillMaxSize()
.padding(start = 152.dp, end = 152.dp, top = 56.dp, bottom = 30.dp),
) {
// 主要内容区域
Box(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
) {
content()
}
Spacer(modifier = Modifier.height(30.dp))
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End
) {
CustomOutlinedButton(
modifier = modifier
.width(300.dp)
.height(100.dp),
text = "取消",
fontSize = 36.sp,
onClick = onCancelClick
)
Spacer(modifier = Modifier.width(20.dp))
CustomButton(
modifier = modifier
.width(300.dp)
.height(100.dp),
text = "确定",
onClick = onConfirmClick,
borderColor = colorResource(R.color.blue),
textColor = colorResource(R.color.white),
fontSize = 36.sp
)
}
}
}
}
}
/**
* 商品编辑
*/
@@ -602,6 +664,7 @@ private fun SelfProductEditView(
viewModel: SelfProcurementViewModel,
) {
val selectedItem by viewModel.selectedItem.collectAsState()
val goodsAddUnitParam by viewModel.goodsAddUnitParam.collectAsState()
val storeList = GlobalData.warehouseTypeList
var unitTypeList = emptyList<DictType>() // 界面中会重新获取
val lifecycleOwner = LocalLifecycleOwner.current
@@ -660,24 +723,38 @@ private fun SelfProductEditView(
}
})
RowInputLayout(
label = "采购单位",
value = selectedItem!!.unitNameStr,
dropdownItems = unitTypeList,
onValueChange = { value ->
val selectUnitType =
selectedItem!!.unitList!!.find { it.purchaseUnitName == value }
if (selectUnitType != null) {
viewModel.updateSelectedItem(
selectedItem!!.copy(
unitName = value,
buyToInventoryValue = selectUnitType.buyToInventoryValue ?: "",
goodPurId = selectUnitType.businessUnitId?.toInt() ?: 0,
selectUnitType = selectUnitType
Row {
RowInputLayout(
label = "采购单位",
value = selectedItem!!.unitNameStr,
dropdownItems = unitTypeList,
onValueChange = { value ->
val selectUnitType =
selectedItem!!.unitList!!.find { it.purchaseUnitName == value }
if (selectUnitType != null) {
viewModel.updateSelectedItem(
selectedItem!!.copy(
unitName = value,
buyToInventoryValue = selectUnitType.buyToInventoryValue ?: "",
goodPurId = selectUnitType.businessUnitId?.toInt() ?: 0,
selectUnitType = selectUnitType
)
)
}
}, showRightButton = true, onRightButtonClick = {
if (selectedItem!!.goodsId == 0) {
ToastUtils.showToast("请先选择物品")
return@RowInputLayout
}
viewModel.updateGoodsPurchaseUnit(
goodsAddUnitParam.copy(
goodsId = selectedItem!!.goodsId,
unitId = selectedItem!!.kcUnitId
)
)
}
})
viewModel.updateAddPurchaseUnitDialog(true)
})
}
RowInputLayout(
label = "采购数量",
@@ -43,6 +43,7 @@ fun CustomDropdownTextField(
placeholderValue: String = "请选择",
textAlign: TextAlign = TextAlign.Start,
textStyle: TextStyle? = null,
enabled: Boolean = true,
) {
var expanded by remember { mutableStateOf(false) }
var newTextStyle = textStyle
@@ -55,7 +56,7 @@ fun CustomDropdownTextField(
ExposedDropdownMenuBox(
modifier = modifier,
expanded = expanded,
expanded = expanded || !enabled,
onExpandedChange = { expanded = it },
) {
TextField(
@@ -1,5 +1,7 @@
package com.sw.inbound.ui.weight
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
@@ -13,8 +15,10 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import com.sw.inbound.R
import com.sw.inbound.model.response.DictType
import com.sw.inbound.ui.theme.AppTypography
@@ -32,8 +36,11 @@ fun RowInputLayout(
trailingLabel: String? = null, // 尾部文字
keyboardOptions: KeyboardOptions? = null,
keyboardActions: KeyboardActions? = null,
isInitUpdate: Boolean = false // 是否根据原始数据更新
isInitUpdate: Boolean = false, // 是否根据原始数据更新
showRightButton: Boolean = false,
onRightButtonClick: () -> Unit = {},
) {
val textWidth = if (showRightButton) 218.dp else 290.dp
Row(
modifier = Modifier
.height(60.dp)
@@ -47,7 +54,7 @@ fun RowInputLayout(
Spacer(modifier = Modifier.weight(1f))
if (dropdownItems == null) {
CustomTextField(
modifier = Modifier.width(290.dp),
modifier = Modifier.width(textWidth),
value = value, onValueChange = onValueChange,
textAlign = TextAlign.End,
trailingLabel = trailingLabel,
@@ -59,12 +66,18 @@ fun RowInputLayout(
)
} else {
CustomDropdownTextField(
modifier = Modifier.width(290.dp),
modifier = Modifier.width(textWidth),
value = value,
dropdownItems = dropdownItems,
onValueChange = onValueChange,
textAlign = TextAlign.End
)
}
if (showRightButton) {
Spacer(modifier = Modifier.width(12.dp))
Image(modifier = Modifier.clickable {
onRightButtonClick()
}, painter = painterResource(R.drawable.ic_add), contentDescription = "添加")
}
}
}
@@ -0,0 +1,101 @@
package com.sw.inbound.ui.weight.dialog
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Surface
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.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import com.sw.inbound.R
import com.sw.inbound.ui.weight.CustomButton
import com.sw.inbound.ui.weight.CustomOutlinedButton
import com.sw.inbound.utils.ToastUtils
/**
* 添加物品弹窗
*/
@Composable
fun AddProductDialog(
modifier: Modifier = Modifier,
onCancelClick: () -> Unit,
onConfirmClick: () -> Unit,
onDismiss: () -> Unit,
content: @Composable () -> Unit
) {
Dialog(
onDismissRequest = onDismiss,
properties = DialogProperties(
usePlatformDefaultWidth = false, // 不使用平台默认宽度
decorFitsSystemWindows = false // 允许内容延伸到系统窗口后面
)
) {
Surface(
modifier = Modifier
.padding(start = 60.dp, end = 60.dp, bottom = 40.dp) // 设置弹窗距离边框60dp
.wrapContentSize(),
shape = RoundedCornerShape(30.dp),
color = Color.White,
shadowElevation = 0.dp
) {
ToastUtils.ToastComposable()
Column(
modifier = Modifier
.fillMaxSize()
.padding(start = 152.dp, end = 152.dp, top = 56.dp, bottom = 30.dp),
) {
// 主要内容区域
Box(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
) {
content()
}
Spacer(modifier = Modifier.height(30.dp))
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End
) {
CustomOutlinedButton(
modifier = modifier
.width(300.dp)
.height(100.dp),
text = "取消",
fontSize = 36.sp,
onClick = onCancelClick
)
Spacer(modifier = Modifier.width(20.dp))
CustomButton(
modifier = modifier
.width(300.dp)
.height(100.dp),
text = "确定",
onClick = onConfirmClick,
borderColor = colorResource(R.color.blue),
textColor = colorResource(R.color.white),
fontSize = 36.sp
)
}
}
}
}
}
@@ -0,0 +1,103 @@
package com.sw.inbound.ui.weight.dialog
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Surface
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.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import com.sw.inbound.R
import com.sw.inbound.ui.weight.CustomButton
import com.sw.inbound.ui.weight.CustomOutlinedButton
import com.sw.inbound.utils.ToastUtils
/**
* 添加物品弹窗
*/
@Composable
fun AddPurchaseUnitDialog(
modifier: Modifier = Modifier,
onCancelClick: () -> Unit,
onConfirmClick: () -> Unit,
onDismiss: () -> Unit,
content: @Composable () -> Unit
) {
Dialog(
onDismissRequest = onDismiss,
properties = DialogProperties(
usePlatformDefaultWidth = false, // 不使用平台默认宽度
decorFitsSystemWindows = false // 允许内容延伸到系统窗口后面
)
) {
Surface(
modifier = Modifier
.width(1190.dp)
.height(840.dp)
.wrapContentSize(),
shape = RoundedCornerShape(30.dp),
color = Color.White,
shadowElevation = 0.dp
) {
ToastUtils.ToastComposable()
Column(
modifier = Modifier
.fillMaxSize()
.padding(30.dp),
) {
// 主要内容区域
Box(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 164.dp)
.weight(1f)
) {
content()
}
Spacer(modifier = Modifier.height(30.dp))
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End
) {
CustomOutlinedButton(
modifier = modifier
.width(300.dp)
.height(100.dp),
text = "取消",
fontSize = 36.sp,
onClick = onCancelClick
)
Spacer(modifier = Modifier.width(20.dp))
CustomButton(
modifier = modifier
.width(300.dp)
.height(100.dp),
text = "确定",
onClick = onConfirmClick,
borderColor = colorResource(R.color.blue),
textColor = colorResource(R.color.white),
fontSize = 36.sp
)
}
}
}
}
}
@@ -39,6 +39,7 @@ import com.sw.inbound.ui.theme.GrayDivider
import com.sw.inbound.ui.weight.CustomButton
import com.sw.inbound.ui.weight.CustomOutlinedButton
import com.sw.inbound.ui.weight.CustomSingleRightText
import com.sw.inbound.utils.ToastUtils
/**
* 收货确认弹窗
@@ -68,6 +69,7 @@ fun ReceiptTipDialog(
color = Color.White,
shadowElevation = 0.dp
) {
ToastUtils.ToastComposable()
Column(
modifier = Modifier
.fillMaxSize()