添加物品单位功能

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
@@ -21,7 +21,9 @@ object NetworkModule {
// private const val BASE_URL = "https://127.0.0.1" // private const val BASE_URL = "https://127.0.0.1"
// private const val BASE_URL = "https://vip.shuziweidao.com" // private const val BASE_URL = "https://vip.shuziweidao.com"
private const val BASE_URL = "http://192.168.1.237:9002" private const val BASE_URL = "http://192.168.1.237:9002/"
// private const val BASE_URL = "https://vip.shuziweidao.com/gateway/"
private const val TIME_OUT = 30L // 超时时间(秒) private const val TIME_OUT = 30L // 超时时间(秒)
@Provides @Provides
@@ -90,7 +90,7 @@ fun Float?.toSafeFloat(decimalPlaces: Int = 2): Float {
*/ */
private fun getDecimalPlaces(unitName: String?): Int { private fun getDecimalPlaces(unitName: String?): Int {
val decimalPlaces = when (unitName) { val decimalPlaces = when (unitName) {
"", "公斤", "" -> 2 "", "公斤", "", "千克" -> 2
else -> 0 else -> 0
} }
return decimalPlaces return decimalPlaces
@@ -0,0 +1,40 @@
package com.sw.inbound.model.request
import com.sw.inbound.GlobalData
data class GoodsPurchaseUnitParam(
val goodsId: Int = 0,// 物品id integer ,
val purchaseUnit: Int = 0, // 采购单位 integer ,
val unitId: Int = 0, // 库存单位id integer,
val purchaseValue: Float = 0f, // 单位转换值 float
) {
val unitIdStr: String
get() {
if (unitId == 0) return ""
return GlobalData.unitTypeList.find { it.id == unitId }?.value ?: ""
}
val purchaseUnitStr: String
get() {
if (purchaseUnit == 0) {
return ""
}
return GlobalData.unitTypeList.find { it.id == purchaseUnit }?.value ?: ""
}
fun hasNullField(): String? {
if (goodsId == null || goodsId == 0)
return "物品信息异常"
if (unitId == null || unitId == 0) {
return "请选择库存单位"
}
if (purchaseUnit == null || purchaseUnit == 0) {
return "请选择采购单位"
}
if (purchaseValue == null || purchaseValue == 0f) {
return "请输入采购单位对应的库存数量"
}
return null
}
}
@@ -113,13 +113,12 @@ data class PurchaseWarehouseParam(
get() { get() {
return if (unitList == null) emptyList() return if (unitList == null) emptyList()
else { else {
unitList!!.map { unitList!!.filter { it.businessUnitId != null && it.purchaseUnitName != null }.map {
DictType(it.businessUnitId!!.toInt(), it.purchaseUnitName!!) DictType(it.businessUnitId?.toInt() ?: 0, it.purchaseUnitName ?: "")
} }
} }
} }
val unitNameStr: String val unitNameStr: String
get() { get() {
if (unitName == null) return "" if (unitName == null) return ""
@@ -1,6 +1,7 @@
package com.sw.inbound.network.api package com.sw.inbound.network.api
import com.sw.inbound.model.request.GoodsAddParam import com.sw.inbound.model.request.GoodsAddParam
import com.sw.inbound.model.request.GoodsPurchaseUnitParam
import com.sw.inbound.model.request.LoginParam import com.sw.inbound.model.request.LoginParam
import com.sw.inbound.model.request.PurchaseWarehouseParam import com.sw.inbound.model.request.PurchaseWarehouseParam
import com.sw.inbound.model.request.UploadInfo import com.sw.inbound.model.request.UploadInfo
@@ -25,13 +26,13 @@ interface ApiService {
/** /**
* 登录 * 登录
*/ */
@POST("/sys/loginPad") @POST("sys/loginPad")
suspend fun login(@Body body: LoginParam): ApiResponse<User> suspend fun login(@Body body: LoginParam): ApiResponse<User>
/** /**
* 采购单入库-列表 * 采购单入库-列表
*/ */
@GET("/pad/receivePage") @GET("pad/receivePage")
suspend fun getReceiveList( suspend fun getReceiveList(
@Query("pageNo") pageNo: Int, @Query("pageNo") pageNo: Int,
@Query("pageSize") pageSize: Int @Query("pageSize") pageSize: Int
@@ -40,44 +41,44 @@ interface ApiService {
/** /**
* 采购单入库-详情 * 采购单入库-详情
*/ */
@GET("/pad/receiveDetail") @GET("pad/receiveDetail")
suspend fun getReceiveDetail(@Query("id") id: Int): ApiResponse<PurchaseInfo> suspend fun getReceiveDetail(@Query("id") id: Int): ApiResponse<PurchaseInfo>
/** /**
* 部分收货 * 部分收货
*/ */
@POST("/pad/partialReceiptGoods") @POST("pad/partialReceiptGoods")
suspend fun partialReceipt(@Body uploadInfo: UploadInfo): ApiResponse<Boolean> suspend fun partialReceipt(@Body uploadInfo: UploadInfo): ApiResponse<Boolean>
/** /**
* 确认收货 * 确认收货
*/ */
@POST("/pad/saveAndReceiveAndGoWare") @POST("pad/saveAndReceiveAndGoWare")
suspend fun confirmReceipt(@Body uploadInfo: UploadInfo): ApiResponse<Boolean> suspend fun confirmReceipt(@Body uploadInfo: UploadInfo): ApiResponse<Boolean>
/** /**
* 存储方式 * 存储方式
*/ */
@GET("/sys/dict/getDictItemByF") @GET("sys/dict/getDictItemByF")
suspend fun getGoodsStorageType(@Query("dictCode") dictCode: String = "goods_storage_type"): ApiResponse<List<StorageType>> suspend fun getGoodsStorageType(@Query("dictCode") dictCode: String = "goods_storage_type"): ApiResponse<List<StorageType>>
/** /**
* 物品类型 * 物品类型
*/ */
@GET("/pad/notLimitList") @GET("pad/notLimitList")
suspend fun getGoodsType(): ApiResponse<GoodsType> suspend fun getGoodsType(): ApiResponse<GoodsType>
/** /**
* 获取字典数据 * 获取字典数据
*/ */
@GET("/pad/dataList") @GET("pad/dataList")
suspend fun getDictType(@Query("type") type: String): ApiResponse<List<DictType>> suspend fun getDictType(@Query("type") type: String): ApiResponse<List<DictType>>
/** /**
* 上传图片 * 上传图片
*/ */
@Multipart @Multipart
@POST("/fileUpload/fileUpload/") @POST("sys/common/upload")
suspend fun uploadImage( suspend fun uploadImage(
@Part("code") code: RequestBody, @Part("code") code: RequestBody,
@Part file: MultipartBody.Part @Part file: MultipartBody.Part
@@ -86,7 +87,7 @@ interface ApiService {
/** /**
* 搜索物品列表 * 搜索物品列表
*/ */
@GET("/pad/goodsInfoList") @GET("pad/goodsInfoList")
suspend fun searchGoodsInfoList( suspend fun searchGoodsInfoList(
@Query("goodsName") goodsName: String, @Query("goodsName") goodsName: String,
@Query("pageNo") pageNo: Int, @Query("pageNo") pageNo: Int,
@@ -96,13 +97,19 @@ interface ApiService {
/** /**
* 自采添加商品 * 自采添加商品
*/ */
@POST("/pad/goodsAdd") @POST("pad/goodsAdd")
suspend fun selfPurchaseGoodsAdd(@Body goodsAddParam: GoodsAddParam): ApiResponse<SearchGoodsInfo> suspend fun selfPurchaseGoodsAdd(@Body goodsAddParam: GoodsAddParam): ApiResponse<SearchGoodsInfo>
/**
* 添加物品采购单位
*/
@POST("pad/goodsAddUnit")
suspend fun goodsAddUnit(@Body purchaseUnitParam: GoodsPurchaseUnitParam): ApiResponse<Boolean>
/** /**
* 自采入库 * 自采入库
*/ */
@POST("/pad/SelfPurchasedGoods") @POST("pad/SelfPurchasedGoods")
suspend fun selfPurchaseWarehousing(@Body list: List<PurchaseWarehouseParam>): ApiResponse<Boolean> suspend fun selfPurchaseWarehousing(@Body list: List<PurchaseWarehouseParam>): ApiResponse<Boolean>
} }
@@ -2,6 +2,7 @@ package com.sw.inbound.repository
import android.net.Uri import android.net.Uri
import com.sw.inbound.model.request.GoodsAddParam import com.sw.inbound.model.request.GoodsAddParam
import com.sw.inbound.model.request.GoodsPurchaseUnitParam
import com.sw.inbound.model.request.LoginParam import com.sw.inbound.model.request.LoginParam
import com.sw.inbound.model.request.PurchaseWarehouseParam import com.sw.inbound.model.request.PurchaseWarehouseParam
import com.sw.inbound.model.request.UploadInfo import com.sw.inbound.model.request.UploadInfo
@@ -135,6 +136,12 @@ class RemoteRepository @Inject constructor(
} }
} }
suspend fun selfPurchaseGoodsAddUnit(addParam: GoodsPurchaseUnitParam): ApiResponse<Boolean> {
return safeApiCall {
apiService.goodsAddUnit(addParam)
}
}
/** /**
* 自采购-入库 * 自采购-入库
*/ */
@@ -14,12 +14,10 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect 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.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp 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.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.navigation.NavController 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.dashedBorder
import com.sw.inbound.ext.isValidAmount import com.sw.inbound.ext.isValidAmount
import com.sw.inbound.ext.medium import com.sw.inbound.ext.medium
import com.sw.inbound.ext.toFormattedString
import com.sw.inbound.ext.toSafeBigDecimal import com.sw.inbound.ext.toSafeBigDecimal
import com.sw.inbound.ext.toSafeDouble import com.sw.inbound.ext.toSafeDouble
import com.sw.inbound.ext.toSafeFloat import com.sw.inbound.ext.toSafeFloat
import com.sw.inbound.ext.toSafeString
import com.sw.inbound.ext.withColor import com.sw.inbound.ext.withColor
import com.sw.inbound.ext.withSize import com.sw.inbound.ext.withSize
import com.sw.inbound.model.request.PurchaseWarehouseParam 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.RowInputLayout
import com.sw.inbound.ui.weight.SelfProcurementListItem import com.sw.inbound.ui.weight.SelfProcurementListItem
import com.sw.inbound.ui.weight.TopTitleBar 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.InteractionUtils
import com.sw.inbound.utils.ToastUtils import com.sw.inbound.utils.ToastUtils
import com.sw.inbound.viewmodel.SelfProcurementViewModel import com.sw.inbound.viewmodel.SelfProcurementViewModel
@@ -97,6 +95,7 @@ fun SelfProcurementScreen(
viewModel: SelfProcurementViewModel = hiltViewModel<SelfProcurementViewModel>() viewModel: SelfProcurementViewModel = hiltViewModel<SelfProcurementViewModel>()
) { ) {
val showDialog by viewModel.showAddProductDialog.collectAsState() val showDialog by viewModel.showAddProductDialog.collectAsState()
val showPurchaseUnitDialog by viewModel.showAddPurchaseUnitDialog.collectAsState()
val addToWarehouseResult by viewModel.addToWarehouseResult.collectAsState() val addToWarehouseResult by viewModel.addToWarehouseResult.collectAsState()
LaunchedEffect(addToWarehouseResult) { LaunchedEffect(addToWarehouseResult) {
@@ -140,14 +139,28 @@ fun SelfProcurementScreen(
modifier = Modifier, modifier = Modifier,
onCancelClick = { onCancelClick = {
viewModel.updateAddProductDialog(false) viewModel.updateAddProductDialog(false)
viewModel.cleanGoodsAddParam()
}, },
onConfirmClick = { onConfirmClick = {
viewModel.addGoodsInfo() 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 @Composable
private fun DialogContentView( private fun AddProductDialogContentView(
modifier: Modifier, modifier: Modifier,
viewModel: SelfProcurementViewModel viewModel: SelfProcurementViewModel
) { ) {
@@ -445,10 +458,11 @@ private fun DialogRightEditView(viewModel: SelfProcurementViewModel) {
dropdownItems = unitTypeList, dropdownItems = unitTypeList,
placeholderValue = "请选择", placeholderValue = "请选择",
onValueChange = { value -> onValueChange = { value ->
val purchaseUnit = unitTypeList.find { it.value == value }?.id ?: 0
viewModel.updateGoodsAddParam( viewModel.updateGoodsAddParam(
goodsAddParam.copy( goodsAddParam.copy(
purchaseUnit = unitTypeList.find { it.value == value }?.id purchaseUnit = purchaseUnit,
?: 0 purchaseValue = if (goodsAddParam.unitId == purchaseUnit) 1f else 0f
) )
) )
}) })
@@ -457,8 +471,9 @@ private fun DialogRightEditView(viewModel: SelfProcurementViewModel) {
Spacer(modifier = Modifier.width(24.dp)) Spacer(modifier = Modifier.width(24.dp))
CustomTextField( CustomTextField(
modifier = Modifier.width(200.dp), modifier = Modifier.width(200.dp),
value = goodsAddParam.purchaseValue.toFormattedString(), value = goodsAddParam.purchaseValue.toSafeString(goodsAddParam.unitIdStr),
placeholderValue = "请录入", placeholderValue = "请录入",
isInitUpdate = true,
onValueChange = { onValueChange = {
viewModel.updateGoodsAddParam(goodsAddParam.copy(purchaseValue = it.toSafeFloat())) viewModel.updateGoodsAddParam(goodsAddParam.copy(purchaseValue = it.toSafeFloat()))
}, inputType = InputType.Decimal }, 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 @Composable
fun ColumnInputText( fun ColumnInputText(
@@ -516,84 +650,12 @@ fun ColumnInputText(
onValueChange = onValueChange, onValueChange = onValueChange,
dropdownItems = dropdownItems, dropdownItems = dropdownItems,
placeholderValue = placeholder, 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, viewModel: SelfProcurementViewModel,
) { ) {
val selectedItem by viewModel.selectedItem.collectAsState() val selectedItem by viewModel.selectedItem.collectAsState()
val goodsAddUnitParam by viewModel.goodsAddUnitParam.collectAsState()
val storeList = GlobalData.warehouseTypeList val storeList = GlobalData.warehouseTypeList
var unitTypeList = emptyList<DictType>() // 界面中会重新获取 var unitTypeList = emptyList<DictType>() // 界面中会重新获取
val lifecycleOwner = LocalLifecycleOwner.current val lifecycleOwner = LocalLifecycleOwner.current
@@ -660,6 +723,7 @@ private fun SelfProductEditView(
} }
}) })
Row {
RowInputLayout( RowInputLayout(
label = "采购单位", label = "采购单位",
value = selectedItem!!.unitNameStr, value = selectedItem!!.unitNameStr,
@@ -677,7 +741,20 @@ private fun SelfProductEditView(
) )
) )
} }
}, 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( RowInputLayout(
label = "采购数量", label = "采购数量",
@@ -43,6 +43,7 @@ fun CustomDropdownTextField(
placeholderValue: String = "请选择", placeholderValue: String = "请选择",
textAlign: TextAlign = TextAlign.Start, textAlign: TextAlign = TextAlign.Start,
textStyle: TextStyle? = null, textStyle: TextStyle? = null,
enabled: Boolean = true,
) { ) {
var expanded by remember { mutableStateOf(false) } var expanded by remember { mutableStateOf(false) }
var newTextStyle = textStyle var newTextStyle = textStyle
@@ -55,7 +56,7 @@ fun CustomDropdownTextField(
ExposedDropdownMenuBox( ExposedDropdownMenuBox(
modifier = modifier, modifier = modifier,
expanded = expanded, expanded = expanded || !enabled,
onExpandedChange = { expanded = it }, onExpandedChange = { expanded = it },
) { ) {
TextField( TextField(
@@ -1,5 +1,7 @@
package com.sw.inbound.ui.weight 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.Arrangement
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@@ -13,8 +15,10 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.sw.inbound.R
import com.sw.inbound.model.response.DictType import com.sw.inbound.model.response.DictType
import com.sw.inbound.ui.theme.AppTypography import com.sw.inbound.ui.theme.AppTypography
@@ -32,8 +36,11 @@ fun RowInputLayout(
trailingLabel: String? = null, // 尾部文字 trailingLabel: String? = null, // 尾部文字
keyboardOptions: KeyboardOptions? = null, keyboardOptions: KeyboardOptions? = null,
keyboardActions: KeyboardActions? = 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( Row(
modifier = Modifier modifier = Modifier
.height(60.dp) .height(60.dp)
@@ -47,7 +54,7 @@ fun RowInputLayout(
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
if (dropdownItems == null) { if (dropdownItems == null) {
CustomTextField( CustomTextField(
modifier = Modifier.width(290.dp), modifier = Modifier.width(textWidth),
value = value, onValueChange = onValueChange, value = value, onValueChange = onValueChange,
textAlign = TextAlign.End, textAlign = TextAlign.End,
trailingLabel = trailingLabel, trailingLabel = trailingLabel,
@@ -59,12 +66,18 @@ fun RowInputLayout(
) )
} else { } else {
CustomDropdownTextField( CustomDropdownTextField(
modifier = Modifier.width(290.dp), modifier = Modifier.width(textWidth),
value = value, value = value,
dropdownItems = dropdownItems, dropdownItems = dropdownItems,
onValueChange = onValueChange, onValueChange = onValueChange,
textAlign = TextAlign.End 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.CustomButton
import com.sw.inbound.ui.weight.CustomOutlinedButton import com.sw.inbound.ui.weight.CustomOutlinedButton
import com.sw.inbound.ui.weight.CustomSingleRightText import com.sw.inbound.ui.weight.CustomSingleRightText
import com.sw.inbound.utils.ToastUtils
/** /**
* 收货确认弹窗 * 收货确认弹窗
@@ -68,6 +69,7 @@ fun ReceiptTipDialog(
color = Color.White, color = Color.White,
shadowElevation = 0.dp shadowElevation = 0.dp
) { ) {
ToastUtils.ToastComposable()
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@@ -6,6 +6,7 @@ import com.sw.inbound.ext.toFormattedString
import com.sw.inbound.ext.toSafeBigDecimal import com.sw.inbound.ext.toSafeBigDecimal
import com.sw.inbound.ext.toSafeDouble import com.sw.inbound.ext.toSafeDouble
import com.sw.inbound.model.request.GoodsAddParam import com.sw.inbound.model.request.GoodsAddParam
import com.sw.inbound.model.request.GoodsPurchaseUnitParam
import com.sw.inbound.model.request.PurchaseWarehouseParam import com.sw.inbound.model.request.PurchaseWarehouseParam
import com.sw.inbound.model.response.DictType import com.sw.inbound.model.response.DictType
import com.sw.inbound.model.response.SearchGoodsInfo import com.sw.inbound.model.response.SearchGoodsInfo
@@ -34,6 +35,9 @@ class SelfProcurementViewModel @Inject constructor(
private val _addGoodsResult = MutableStateFlow<Boolean>(false) private val _addGoodsResult = MutableStateFlow<Boolean>(false)
val addGoodsResult: StateFlow<Boolean> = _addGoodsResult val addGoodsResult: StateFlow<Boolean> = _addGoodsResult
private val _addGoodsPurchaseUnitResult = MutableStateFlow<Boolean>(false)
val addGoodsPurchaseUnitResult: StateFlow<Boolean> = _addGoodsPurchaseUnitResult
private val _addToWarehouseResult = MutableStateFlow<Boolean>(false) private val _addToWarehouseResult = MutableStateFlow<Boolean>(false)
val addToWarehouseResult: StateFlow<Boolean> = _addToWarehouseResult val addToWarehouseResult: StateFlow<Boolean> = _addToWarehouseResult
@@ -52,10 +56,18 @@ class SelfProcurementViewModel @Inject constructor(
private val _goodsAddParam = MutableStateFlow<GoodsAddParam>(GoodsAddParam()) private val _goodsAddParam = MutableStateFlow<GoodsAddParam>(GoodsAddParam())
val goodsAddParam: StateFlow<GoodsAddParam> = _goodsAddParam val goodsAddParam: StateFlow<GoodsAddParam> = _goodsAddParam
private val _goodsAddUnitParam =
MutableStateFlow<GoodsPurchaseUnitParam>(GoodsPurchaseUnitParam())
val goodsAddUnitParam: StateFlow<GoodsPurchaseUnitParam> = _goodsAddUnitParam
// 快速添加弹窗状态 // 快速添加弹窗状态
private val _showAddProductDialog = MutableStateFlow<Boolean>(false) private val _showAddProductDialog = MutableStateFlow<Boolean>(false)
val showAddProductDialog: StateFlow<Boolean> = _showAddProductDialog val showAddProductDialog: StateFlow<Boolean> = _showAddProductDialog
// 添加采购单位弹窗状态
private val _showAddPurchaseUnitDialog = MutableStateFlow<Boolean>(false)
val showAddPurchaseUnitDialog: StateFlow<Boolean> = _showAddPurchaseUnitDialog
// 搜索物品列表 // 搜索物品列表
private val _searchListItems = MutableStateFlow<List<SearchGoodsInfo.Record>>(emptyList()) private val _searchListItems = MutableStateFlow<List<SearchGoodsInfo.Record>>(emptyList())
val searchListItems: StateFlow<List<SearchGoodsInfo.Record>> = _searchListItems val searchListItems: StateFlow<List<SearchGoodsInfo.Record>> = _searchListItems
@@ -64,6 +76,10 @@ class SelfProcurementViewModel @Inject constructor(
private val _weightInfo = MutableStateFlow<Double?>(0.0) private val _weightInfo = MutableStateFlow<Double?>(0.0)
val weightInfo: StateFlow<Double?> = _weightInfo val weightInfo: StateFlow<Double?> = _weightInfo
// 是否可以下拉
private val _dropdownTextChange = MutableStateFlow<Boolean>(false)
val dropdownTextChange: StateFlow<Boolean> = _dropdownTextChange
/** /**
* 数量是否是用户输入的值 * 数量是否是用户输入的值
*/ */
@@ -172,6 +188,16 @@ class SelfProcurementViewModel @Inject constructor(
fun updateAddProductDialog(show: Boolean) { fun updateAddProductDialog(show: Boolean) {
_showAddProductDialog.value = show _showAddProductDialog.value = show
if (!show) {
_goodsAddParam.value = GoodsAddParam()
}
}
fun updateAddPurchaseUnitDialog(show: Boolean) {
_showAddPurchaseUnitDialog.value = show
if (!show) {
_goodsAddUnitParam.value = GoodsPurchaseUnitParam()
}
} }
fun updateSelectedItem(purchaseOrder: PurchaseWarehouseParam?) { fun updateSelectedItem(purchaseOrder: PurchaseWarehouseParam?) {
@@ -362,6 +388,38 @@ class SelfProcurementViewModel @Inject constructor(
} }
} }
fun updateGoodsPurchaseUnit(goodsPurchaseUnitParam: GoodsPurchaseUnitParam?) {
if (goodsPurchaseUnitParam == null) {
_dropdownTextChange.value = true
_goodsAddUnitParam.value = GoodsPurchaseUnitParam()
} else {
val hasUnitId = GlobalData.unitTypeList.any { it.id == goodsPurchaseUnitParam.unitId }
_dropdownTextChange.value = !hasUnitId
_goodsAddUnitParam.value = goodsPurchaseUnitParam
}
}
fun updateDropdownTextChange(canChange: Boolean) {
_dropdownTextChange.value == canChange
}
fun addGoodsPurchaseUnit() {
val errorInfo = _goodsAddUnitParam.value.hasNullField()
if (errorInfo != null) {
ToastUtils.showToast(errorInfo)
return
}
launchWithLoading {
val response = repository.selfPurchaseGoodsAddUnit(_goodsAddUnitParam.value)
if (parseResponse(response)) {
_showAddPurchaseUnitDialog.value = false
_goodsAddUnitParam.value = GoodsPurchaseUnitParam()
// _addGoodsPurchaseUnitResult.value = true
ToastUtils.showToast("采购单位添加成功")
}
}
}
/** /**
* 物品提交入库 * 物品提交入库
*/ */
@@ -372,11 +430,7 @@ class SelfProcurementViewModel @Inject constructor(
} }
launchWithLoading { launchWithLoading {
val response = repository.selfPurchaseWarehousing(_purchaseList.value) val response = repository.selfPurchaseWarehousing(_purchaseList.value)
if (parseResponse(response)) { _addToWarehouseResult.value = parseResponse(response)
_addToWarehouseResult.value = true
} else {
_addToWarehouseResult.value = false
}
} }
} }
} }
Binary file not shown.

After

Width:  |  Height:  |  Size: 875 B