From d99c0e6e79aac4abf3108f78c4f953d1635a5b94 Mon Sep 17 00:00:00 2001 From: zxj <275873859@qq.com> Date: Tue, 5 Aug 2025 16:51:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=89=A9=E5=93=81=E5=8D=95?= =?UTF-8?q?=E4=BD=8D=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/sw/inbound/di/NetworkModule.kt | 4 +- .../main/java/com/sw/inbound/ext/CommonExt.kt | 2 +- .../model/request/GoodsPurchaseUnitParam.kt | 40 +++ .../model/request/PurchaseWarehouseParam.kt | 5 +- .../com/sw/inbound/network/api/ApiService.kt | 31 +- .../sw/inbound/repository/RemoteRepository.kt | 7 + .../inbound/ui/page/SelfProcurementScreen.kt | 277 +++++++++++------- .../ui/weight/CustomDropdownTextField.kt | 3 +- .../sw/inbound/ui/weight/RowInputLayout.kt | 19 +- .../ui/weight/dialog/AddProductDialog.kt | 101 +++++++ .../ui/weight/dialog/AddPurchaseUnitDialog.kt | 103 +++++++ .../ui/weight/dialog/ReceiptTipDialog.kt | 2 + .../viewmodel/SelfProcurementViewModel.kt | 66 ++++- app/src/main/res/drawable/ic_add.png | Bin 0 -> 875 bytes 14 files changed, 533 insertions(+), 127 deletions(-) create mode 100644 app/src/main/java/com/sw/inbound/model/request/GoodsPurchaseUnitParam.kt create mode 100644 app/src/main/java/com/sw/inbound/ui/weight/dialog/AddProductDialog.kt create mode 100644 app/src/main/java/com/sw/inbound/ui/weight/dialog/AddPurchaseUnitDialog.kt create mode 100644 app/src/main/res/drawable/ic_add.png diff --git a/app/src/main/java/com/sw/inbound/di/NetworkModule.kt b/app/src/main/java/com/sw/inbound/di/NetworkModule.kt index c0d21dc..91cc2d0 100644 --- a/app/src/main/java/com/sw/inbound/di/NetworkModule.kt +++ b/app/src/main/java/com/sw/inbound/di/NetworkModule.kt @@ -21,7 +21,9 @@ object NetworkModule { // private const val BASE_URL = "https://127.0.0.1" // 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 // 超时时间(秒) @Provides diff --git a/app/src/main/java/com/sw/inbound/ext/CommonExt.kt b/app/src/main/java/com/sw/inbound/ext/CommonExt.kt index 15c6e0e..51ea6ec 100644 --- a/app/src/main/java/com/sw/inbound/ext/CommonExt.kt +++ b/app/src/main/java/com/sw/inbound/ext/CommonExt.kt @@ -90,7 +90,7 @@ fun Float?.toSafeFloat(decimalPlaces: Int = 2): Float { */ private fun getDecimalPlaces(unitName: String?): Int { val decimalPlaces = when (unitName) { - "斤", "公斤", "升" -> 2 + "斤", "公斤", "升", "千克" -> 2 else -> 0 } return decimalPlaces diff --git a/app/src/main/java/com/sw/inbound/model/request/GoodsPurchaseUnitParam.kt b/app/src/main/java/com/sw/inbound/model/request/GoodsPurchaseUnitParam.kt new file mode 100644 index 0000000..1122042 --- /dev/null +++ b/app/src/main/java/com/sw/inbound/model/request/GoodsPurchaseUnitParam.kt @@ -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 + } +} diff --git a/app/src/main/java/com/sw/inbound/model/request/PurchaseWarehouseParam.kt b/app/src/main/java/com/sw/inbound/model/request/PurchaseWarehouseParam.kt index d123c62..dc12e2d 100644 --- a/app/src/main/java/com/sw/inbound/model/request/PurchaseWarehouseParam.kt +++ b/app/src/main/java/com/sw/inbound/model/request/PurchaseWarehouseParam.kt @@ -113,13 +113,12 @@ data class PurchaseWarehouseParam( get() { return if (unitList == null) emptyList() else { - unitList!!.map { - DictType(it.businessUnitId!!.toInt(), it.purchaseUnitName!!) + unitList!!.filter { it.businessUnitId != null && it.purchaseUnitName != null }.map { + DictType(it.businessUnitId?.toInt() ?: 0, it.purchaseUnitName ?: "") } } } - val unitNameStr: String get() { if (unitName == null) return "" diff --git a/app/src/main/java/com/sw/inbound/network/api/ApiService.kt b/app/src/main/java/com/sw/inbound/network/api/ApiService.kt index 02ce833..230d808 100644 --- a/app/src/main/java/com/sw/inbound/network/api/ApiService.kt +++ b/app/src/main/java/com/sw/inbound/network/api/ApiService.kt @@ -1,6 +1,7 @@ package com.sw.inbound.network.api 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.PurchaseWarehouseParam 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 /** * 采购单入库-列表 */ - @GET("/pad/receivePage") + @GET("pad/receivePage") suspend fun getReceiveList( @Query("pageNo") pageNo: 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 /** * 部分收货 */ - @POST("/pad/partialReceiptGoods") + @POST("pad/partialReceiptGoods") suspend fun partialReceipt(@Body uploadInfo: UploadInfo): ApiResponse /** * 确认收货 */ - @POST("/pad/saveAndReceiveAndGoWare") + @POST("pad/saveAndReceiveAndGoWare") suspend fun confirmReceipt(@Body uploadInfo: UploadInfo): ApiResponse /** * 存储方式 */ - @GET("/sys/dict/getDictItemByF") + @GET("sys/dict/getDictItemByF") suspend fun getGoodsStorageType(@Query("dictCode") dictCode: String = "goods_storage_type"): ApiResponse> /** * 物品类型 */ - @GET("/pad/notLimitList") + @GET("pad/notLimitList") suspend fun getGoodsType(): ApiResponse /** * 获取字典数据 */ - @GET("/pad/dataList") + @GET("pad/dataList") suspend fun getDictType(@Query("type") type: String): ApiResponse> /** * 上传图片 */ @Multipart - @POST("/fileUpload/fileUpload/") + @POST("sys/common/upload") suspend fun uploadImage( @Part("code") code: RequestBody, @Part file: MultipartBody.Part @@ -86,7 +87,7 @@ interface ApiService { /** * 搜索物品列表 */ - @GET("/pad/goodsInfoList") + @GET("pad/goodsInfoList") suspend fun searchGoodsInfoList( @Query("goodsName") goodsName: String, @Query("pageNo") pageNo: Int, @@ -96,13 +97,19 @@ interface ApiService { /** * 自采添加商品 */ - @POST("/pad/goodsAdd") + @POST("pad/goodsAdd") suspend fun selfPurchaseGoodsAdd(@Body goodsAddParam: GoodsAddParam): ApiResponse + /** + * 添加物品采购单位 + */ + @POST("pad/goodsAddUnit") + suspend fun goodsAddUnit(@Body purchaseUnitParam: GoodsPurchaseUnitParam): ApiResponse + /** * 自采入库 */ - @POST("/pad/SelfPurchasedGoods") + @POST("pad/SelfPurchasedGoods") suspend fun selfPurchaseWarehousing(@Body list: List): ApiResponse } \ No newline at end of file diff --git a/app/src/main/java/com/sw/inbound/repository/RemoteRepository.kt b/app/src/main/java/com/sw/inbound/repository/RemoteRepository.kt index b87cd5a..1cac68c 100644 --- a/app/src/main/java/com/sw/inbound/repository/RemoteRepository.kt +++ b/app/src/main/java/com/sw/inbound/repository/RemoteRepository.kt @@ -2,6 +2,7 @@ package com.sw.inbound.repository import android.net.Uri 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.PurchaseWarehouseParam import com.sw.inbound.model.request.UploadInfo @@ -135,6 +136,12 @@ class RemoteRepository @Inject constructor( } } + suspend fun selfPurchaseGoodsAddUnit(addParam: GoodsPurchaseUnitParam): ApiResponse { + return safeApiCall { + apiService.goodsAddUnit(addParam) + } + } + /** * 自采购-入库 */ diff --git a/app/src/main/java/com/sw/inbound/ui/page/SelfProcurementScreen.kt b/app/src/main/java/com/sw/inbound/ui/page/SelfProcurementScreen.kt index 7339b80..a9d7745 100644 --- a/app/src/main/java/com/sw/inbound/ui/page/SelfProcurementScreen.kt +++ b/app/src/main/java/com/sw/inbound/ui/page/SelfProcurementScreen.kt @@ -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() ) { 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() // 界面中会重新获取 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 = "采购数量", diff --git a/app/src/main/java/com/sw/inbound/ui/weight/CustomDropdownTextField.kt b/app/src/main/java/com/sw/inbound/ui/weight/CustomDropdownTextField.kt index a381882..654de23 100644 --- a/app/src/main/java/com/sw/inbound/ui/weight/CustomDropdownTextField.kt +++ b/app/src/main/java/com/sw/inbound/ui/weight/CustomDropdownTextField.kt @@ -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( diff --git a/app/src/main/java/com/sw/inbound/ui/weight/RowInputLayout.kt b/app/src/main/java/com/sw/inbound/ui/weight/RowInputLayout.kt index dda66d4..5161d02 100644 --- a/app/src/main/java/com/sw/inbound/ui/weight/RowInputLayout.kt +++ b/app/src/main/java/com/sw/inbound/ui/weight/RowInputLayout.kt @@ -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 = "添加") + } } } \ No newline at end of file diff --git a/app/src/main/java/com/sw/inbound/ui/weight/dialog/AddProductDialog.kt b/app/src/main/java/com/sw/inbound/ui/weight/dialog/AddProductDialog.kt new file mode 100644 index 0000000..1c50f83 --- /dev/null +++ b/app/src/main/java/com/sw/inbound/ui/weight/dialog/AddProductDialog.kt @@ -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 + ) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/inbound/ui/weight/dialog/AddPurchaseUnitDialog.kt b/app/src/main/java/com/sw/inbound/ui/weight/dialog/AddPurchaseUnitDialog.kt new file mode 100644 index 0000000..ec4102d --- /dev/null +++ b/app/src/main/java/com/sw/inbound/ui/weight/dialog/AddPurchaseUnitDialog.kt @@ -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 + ) + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/sw/inbound/ui/weight/dialog/ReceiptTipDialog.kt b/app/src/main/java/com/sw/inbound/ui/weight/dialog/ReceiptTipDialog.kt index 4f6e2b7..e0640a6 100644 --- a/app/src/main/java/com/sw/inbound/ui/weight/dialog/ReceiptTipDialog.kt +++ b/app/src/main/java/com/sw/inbound/ui/weight/dialog/ReceiptTipDialog.kt @@ -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() diff --git a/app/src/main/java/com/sw/inbound/viewmodel/SelfProcurementViewModel.kt b/app/src/main/java/com/sw/inbound/viewmodel/SelfProcurementViewModel.kt index eef5263..0576b58 100644 --- a/app/src/main/java/com/sw/inbound/viewmodel/SelfProcurementViewModel.kt +++ b/app/src/main/java/com/sw/inbound/viewmodel/SelfProcurementViewModel.kt @@ -6,6 +6,7 @@ import com.sw.inbound.ext.toFormattedString import com.sw.inbound.ext.toSafeBigDecimal import com.sw.inbound.ext.toSafeDouble 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.response.DictType import com.sw.inbound.model.response.SearchGoodsInfo @@ -34,6 +35,9 @@ class SelfProcurementViewModel @Inject constructor( private val _addGoodsResult = MutableStateFlow(false) val addGoodsResult: StateFlow = _addGoodsResult + private val _addGoodsPurchaseUnitResult = MutableStateFlow(false) + val addGoodsPurchaseUnitResult: StateFlow = _addGoodsPurchaseUnitResult + private val _addToWarehouseResult = MutableStateFlow(false) val addToWarehouseResult: StateFlow = _addToWarehouseResult @@ -52,10 +56,18 @@ class SelfProcurementViewModel @Inject constructor( private val _goodsAddParam = MutableStateFlow(GoodsAddParam()) val goodsAddParam: StateFlow = _goodsAddParam + private val _goodsAddUnitParam = + MutableStateFlow(GoodsPurchaseUnitParam()) + val goodsAddUnitParam: StateFlow = _goodsAddUnitParam + // 快速添加弹窗状态 private val _showAddProductDialog = MutableStateFlow(false) val showAddProductDialog: StateFlow = _showAddProductDialog + // 添加采购单位弹窗状态 + private val _showAddPurchaseUnitDialog = MutableStateFlow(false) + val showAddPurchaseUnitDialog: StateFlow = _showAddPurchaseUnitDialog + // 搜索物品列表 private val _searchListItems = MutableStateFlow>(emptyList()) val searchListItems: StateFlow> = _searchListItems @@ -64,6 +76,10 @@ class SelfProcurementViewModel @Inject constructor( private val _weightInfo = MutableStateFlow(0.0) val weightInfo: StateFlow = _weightInfo + // 是否可以下拉 + private val _dropdownTextChange = MutableStateFlow(false) + val dropdownTextChange: StateFlow = _dropdownTextChange + /** * 数量是否是用户输入的值 */ @@ -172,6 +188,16 @@ class SelfProcurementViewModel @Inject constructor( fun updateAddProductDialog(show: Boolean) { _showAddProductDialog.value = show + if (!show) { + _goodsAddParam.value = GoodsAddParam() + } + } + + fun updateAddPurchaseUnitDialog(show: Boolean) { + _showAddPurchaseUnitDialog.value = show + if (!show) { + _goodsAddUnitParam.value = GoodsPurchaseUnitParam() + } } fun updateSelectedItem(purchaseOrder: PurchaseWarehouseParam?) { @@ -221,7 +247,7 @@ class SelfProcurementViewModel @Inject constructor( // 添加订单 fun addPurchaseItem(purchaseOrder: PurchaseWarehouseParam) { _purchaseList.update { currentList -> - currentList + purchaseOrder + currentList + purchaseOrder } updateSelectedItem(null) } @@ -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 { val response = repository.selfPurchaseWarehousing(_purchaseList.value) - if (parseResponse(response)) { - _addToWarehouseResult.value = true - } else { - _addToWarehouseResult.value = false - } + _addToWarehouseResult.value = parseResponse(response) } } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_add.png b/app/src/main/res/drawable/ic_add.png new file mode 100644 index 0000000000000000000000000000000000000000..ec54716ca386301a951769808dc5a436248f35aa GIT binary patch literal 875 zcmV-x1C;!UP)Px&B}qgsJKde!d(S!deCNBjI3Jm4;2wa(ISM9< zD?b3-Ef%$xjf>X;W@g28{fEpL5fg~;DG2bST3wl1SUBXCO0*KiYFcZir@6hm`uF`aMLXJQp>q>*~O6h4E&GCE)G4{*0(;MWIXNINlp(oDG8DdVl}H z@gz<;>pjCP6Je5U+xrUO2od!ghH7Q)ToU#j$2XbzGk|YoS>CdERCu1+k@u@7>S2g0 zOVj*iW~_(|uUBmNgs)j#}+e9@zLkADKybjSaQyWoA)Oja%Nmw79De}=kToo8I1yk0kfbF^D-mqPLt3rinTWehn?`tw%77!W zw9IfCc#cML64H?%9VMai9*zdlot||(klv|PF<)j_W;hCNwp}A3Em?Y7kVKpyNlTJe zMCfe2Op=x)twey8-KN<=I-{6nz^T=+%y2p<&;V)wFTkC9xiM{amOHw-{H3rlZ6CEB z@^`ZB$|OK%_G0UBSS;(BOI_C=3Ig8K?ZdY1&k)tyhxc8BxJY}W1VB;RPU?Ek$8@+e zSu3tPe>@1P@7GBHLX%A*kK2Z!KHaU|@pX~M6@VYqL>^Q&4E4XrLj)~kJdX2c4B(q$ zEF=K{CIDrsQtA1U_g-po^%M&8M}c4vz;Gzz0qBuo92ngo;|ViuS>Aaf+~4g&t(vHV z?wF?bs9 literal 0 HcmV?d00001