实现了部分收货UI。替换为张欢测试服务

This commit is contained in:
zxj
2025-07-18 08:49:06 +08:00
parent 5874e4ed9a
commit 4c6fa31787
22 changed files with 282 additions and 137 deletions
@@ -47,4 +47,5 @@ object GlobalData {
object GlobalKey { object GlobalKey {
const val KEY_TOKEN = "tokenKey" const val KEY_TOKEN = "tokenKey"
const val KEY_USER_INFO = "userInfoKey" const val KEY_USER_INFO = "userInfoKey"
const val KEY_USER_NAME = "userNameKey"
} }
@@ -20,9 +20,8 @@ import javax.inject.Singleton
object NetworkModule { 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.8:9092"
private const val TIME_OUT = 30L // 超时时间(秒) private const val TIME_OUT = 30L // 超时时间(秒)
@Provides @Provides
@@ -3,8 +3,9 @@ package com.sw.inbound.model.response
data class ApiResponse<T>( data class ApiResponse<T>(
val code: Int, val code: Int,
val success: Boolean? = false, val success: Boolean? = false,
val msg: String? = "", val message: String? = "",
val data: T? = null val result: T? = null,
val timestamp: Long? = 0
) { ) {
fun isSuccess(): Boolean = code == 200 fun isSuccess(): Boolean = code == 200
} }
@@ -105,6 +105,13 @@ data class GoodsInfo(
return receivedNum?.toFormattedString() ?: "" return receivedNum?.toFormattedString() ?: ""
} }
val receivedNumListStr: String
get() {
if (receivedNum == null)
return "-"
return receivedNum?.toFormattedString() ?: "-"
}
val recUnitPriceTaxInStr: String val recUnitPriceTaxInStr: String
get() { get() {
if (recUnitPriceTaxIn == 0f) return "" if (recUnitPriceTaxIn == 0f) return ""
@@ -38,8 +38,11 @@ data class SupplierInfo(
val pageNum: String? = "", val pageNum: String? = "",
@SerializedName("pageSize") @SerializedName("pageSize")
val pageSize: String? = "", val pageSize: String? = "",
/**
* 采购单位
*/
@SerializedName("purCode") @SerializedName("purCode")
val purCode: String? = "", val purCode: String? = "-",
@SerializedName("purDateStart") @SerializedName("purDateStart")
val purDateStart: String? = "", val purDateStart: String? = "",
@SerializedName("purDateStop") @SerializedName("purDateStop")
@@ -102,7 +105,7 @@ data class SupplierInfo(
* 供应商 * 供应商
*/ */
@SerializedName("supplierName") @SerializedName("supplierName")
val supplierName: String = "", val supplierName: String? = "",
@SerializedName("taxRateAll") @SerializedName("taxRateAll")
val taxRateAll: Double? = 0.0, val taxRateAll: Double? = 0.0,
@SerializedName("updateTime") @SerializedName("updateTime")
@@ -25,13 +25,13 @@ interface ApiService {
/** /**
* 登录 * 登录
*/ */
@POST("/shuwei-user/swuserbase/loginPad") @POST("/sys/loginPad")
suspend fun login(@Body body: LoginParam): ApiResponse<User> suspend fun login(@Body body: LoginParam): ApiResponse<User>
/** /**
* 采购单入库-列表 * 采购单入库-列表
*/ */
@GET("/shuwei-zhct/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 +40,44 @@ interface ApiService {
/** /**
* 采购单入库-详情 * 采购单入库-详情
*/ */
@GET("/shuwei-zhct/pad/receiveDetail") @GET("/pad/receiveDetail")
suspend fun getReceiveDetail(@Query("id") id: Int): ApiResponse<PurchaseInfo> suspend fun getReceiveDetail(@Query("id") id: Int): ApiResponse<PurchaseInfo>
/** /**
* 部分收货 * 部分收货
*/ */
@POST("/shuwei-zhct/pad/partialReceiptGoods") @POST("/pad/partialReceiptGoods")
suspend fun partialReceipt(@Body uploadInfo: UploadInfo): ApiResponse<Boolean> suspend fun partialReceipt(@Body uploadInfo: UploadInfo): ApiResponse<Boolean>
/** /**
* 确认收货 * 确认收货
*/ */
@POST("/shuwei-zhct/pad/saveAndReceiveAndGoWare") @POST("/pad/saveAndReceiveAndGoWare")
suspend fun confirmReceipt(@Body uploadInfo: UploadInfo): ApiResponse<Boolean> suspend fun confirmReceipt(@Body uploadInfo: UploadInfo): ApiResponse<Boolean>
/** /**
* 存储方式 * 存储方式
*/ */
@GET("/shuwei-zhct/swsysdictitem/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("/shuwei-zhct/swkcglgoodstype/notLimitList") @GET("/pad/notLimitList")
suspend fun getGoodsType(): ApiResponse<GoodsType> suspend fun getGoodsType(): ApiResponse<GoodsType>
/** /**
* 获取字典数据 * 获取字典数据
*/ */
@GET("/shuwei-zhct/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("/shuwei-zhct/fileUpload/fileUpload/") @POST("/fileUpload/fileUpload/")
suspend fun uploadImage( suspend fun uploadImage(
@Part("code") code: RequestBody, @Part("code") code: RequestBody,
@Part file: MultipartBody.Part @Part file: MultipartBody.Part
@@ -86,7 +86,7 @@ interface ApiService {
/** /**
* 搜索物品列表 * 搜索物品列表
*/ */
@GET("/shuwei-zhct/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 +96,13 @@ interface ApiService {
/** /**
* 自采添加商品 * 自采添加商品
*/ */
@POST("/shuwei-zhct/pad/goodsAdd") @POST("/pad/goodsAdd")
suspend fun selfPurchaseGoodsAdd(@Body goodsAddParam: GoodsAddParam): ApiResponse<SearchGoodsInfo> suspend fun selfPurchaseGoodsAdd(@Body goodsAddParam: GoodsAddParam): ApiResponse<SearchGoodsInfo>
/** /**
* 自采入库 * 自采入库
*/ */
@POST("/shuwei-zhct/pad/SelfPurchasedGoods") @POST("/pad/SelfPurchasedGoods")
suspend fun selfPurchaseWarehousing(@Body list: List<PurchaseWarehouseParam>): ApiResponse<Boolean> suspend fun selfPurchaseWarehousing(@Body list: List<PurchaseWarehouseParam>): ApiResponse<Boolean>
} }
@@ -16,7 +16,7 @@ class RequestInterceptor : Interceptor {
.header("Content-Type", "application/json") .header("Content-Type", "application/json")
.header("Accept", "application/json") .header("Accept", "application/json")
// .header("Authorization", "Bearer ${getToken()}") // .header("Authorization", "Bearer ${getToken()}")
.header("Authorization", getToken()) .header("x-access-token", getToken())
val newRequest = requestBuilder.build() val newRequest = requestBuilder.build()
@@ -19,37 +19,37 @@ abstract class BaseRepository {
when (e) { when (e) {
is HttpException -> { is HttpException -> {
// 对于HTTP异常,尝试从响应体中获取错误信息 // 对于HTTP异常,尝试从响应体中获取错误信息
val errorBody = e.response()?.errorBody()?.string() // val errorBody = e.response()?.errorBody()?.string()
val errorMsg = if (!errorBody.isNullOrEmpty()) { // val errorMsg = if (!errorBody.isNullOrEmpty()) {
errorBody // errorBody
} else { // } else {
"HTTP Error: ${e.code()} - ${e.message()}" // "HTTP Error: ${e.code()} - ${e.message()}"
} // }
ApiResponse(code = e.code(), msg = errorMsg) ApiResponse(code = e.code(), message = e.message())
} }
is SocketTimeoutException -> { is SocketTimeoutException -> {
ApiResponse(code = -2, msg = "请求超时: ${e.message}") ApiResponse(code = -2, message = "请求超时: ${e.message}")
} }
is ConnectException -> { is ConnectException -> {
ApiResponse(code = -3, msg = "连接失败: ${e.message}") ApiResponse(code = -3, message = "连接失败: ${e.message}")
} }
is SSLHandshakeException -> { is SSLHandshakeException -> {
ApiResponse(code = -4, msg = "SSL握手失败: ${e.message}") ApiResponse(code = -4, message = "SSL握手失败: ${e.message}")
} }
is JsonParseException -> { is JsonParseException -> {
ApiResponse(code = -5, msg = "JSON解析错误: ${e.message}") ApiResponse(code = -5, message = "JSON解析错误: ${e.message}")
} }
is IOException -> { is IOException -> {
ApiResponse(code = -6, msg = "网络IO错误: ${e.message}") ApiResponse(code = -6, message = "网络IO错误: ${e.message}")
} }
else -> { else -> {
ApiResponse(code = -1, msg = "未知错误: ${e.message ?: "无错误信息"}") ApiResponse(code = -1, message = "未知错误: ${e.message ?: "无错误信息"}")
} }
} }
} }
@@ -91,7 +91,7 @@ class RemoteRepository @Inject constructor(
val part = val part =
FileUtils.genRequestPart(context = ContextUtils.getAppContext(), imageUri = uri) FileUtils.genRequestPart(context = ContextUtils.getAppContext(), imageUri = uri)
if (part == null) { if (part == null) {
ApiResponse(code = -1, msg = "解析图片失败", data = "") ApiResponse(code = -1, message = "解析图片失败", result = "")
} else { } else {
apiService.uploadImage(code = codeRequestBody, file = part) apiService.uploadImage(code = codeRequestBody, file = part)
} }
@@ -34,6 +34,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.sw.inbound.GlobalData import com.sw.inbound.GlobalData
import com.sw.inbound.GlobalKey
import com.sw.inbound.R import com.sw.inbound.R
import com.sw.inbound.ext.bold import com.sw.inbound.ext.bold
import com.sw.inbound.ext.textAlign import com.sw.inbound.ext.textAlign
@@ -41,6 +42,7 @@ import com.sw.inbound.ext.withSize
import com.sw.inbound.ui.Screen import com.sw.inbound.ui.Screen
import com.sw.inbound.ui.theme.AppTypography import com.sw.inbound.ui.theme.AppTypography
import com.sw.inbound.ui.weight.CustomButton import com.sw.inbound.ui.weight.CustomButton
import com.sw.inbound.utils.SPUtil
import com.sw.inbound.utils.ToastUtils import com.sw.inbound.utils.ToastUtils
import com.sw.inbound.viewmodel.UserViewModel import com.sw.inbound.viewmodel.UserViewModel
import timber.log.Timber import timber.log.Timber
@@ -51,13 +53,14 @@ fun LoginScreen(
controller: NavController = rememberNavController(), controller: NavController = rememberNavController(),
viewModel: UserViewModel = hiltViewModel<UserViewModel>() viewModel: UserViewModel = hiltViewModel<UserViewModel>()
) { ) {
var username by remember { mutableStateOf<String>("padAdmin") } var username by remember { mutableStateOf<String>("") }
var password by remember { mutableStateOf<String>("123123") } var password by remember { mutableStateOf<String>("") }
// val user by viewModel.user.collectAsState() // val user by viewModel.user.collectAsState()
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
Timber.d(" user =") Timber.d(" user =")
username = SPUtil.getInstance().get(GlobalKey.KEY_USER_NAME, "").toString()
viewModel.user.collect { viewModel.user.collect {
Timber.d(" user collect = ${it}") Timber.d(" user collect = ${it}")
if (it != null) { if (it != null) {
@@ -233,7 +233,7 @@ fun PurchaseOrderItem(product: SupplierInfo, onItemClick: (SupplierInfo) -> Unit
verticalArrangement = Arrangement.spacedBy(0.dp) verticalArrangement = Arrangement.spacedBy(0.dp)
) { ) {
Text( Text(
text = product.supplierName, text = product.supplierName ?: "-",
modifier = Modifier.padding(top = 25.dp), modifier = Modifier.padding(top = 25.dp),
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis, overflow = TextOverflow.Ellipsis,
@@ -245,7 +245,7 @@ fun PurchaseOrderItem(product: SupplierInfo, onItemClick: (SupplierInfo) -> Unit
) )
Spacer(modifier = Modifier.height(itemSpace)) Spacer(modifier = Modifier.height(itemSpace))
Text( Text(
text = "单号 ${product.receiveCode}", text = "单号 ${product.purCode ?: "-"}",
maxLines = 1, maxLines = 1,
style = grayTextStyle style = grayTextStyle
) )
@@ -2,6 +2,7 @@ package com.sw.inbound.ui.page
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -14,9 +15,10 @@ 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.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.Tab import androidx.compose.material3.Tab
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@@ -32,6 +34,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@@ -44,6 +47,7 @@ import com.sw.inbound.GlobalData
import com.sw.inbound.R import com.sw.inbound.R
import com.sw.inbound.ext.bold import com.sw.inbound.ext.bold
import com.sw.inbound.ext.toSafeFloat import com.sw.inbound.ext.toSafeFloat
import com.sw.inbound.ext.withColor
import com.sw.inbound.ext.withSize import com.sw.inbound.ext.withSize
import com.sw.inbound.model.request.UploadInfo import com.sw.inbound.model.request.UploadInfo
import com.sw.inbound.model.response.DictType import com.sw.inbound.model.response.DictType
@@ -52,6 +56,8 @@ import com.sw.inbound.sdk.SensorScaleUtils
import com.sw.inbound.ui.theme.AppTypography import com.sw.inbound.ui.theme.AppTypography
import com.sw.inbound.ui.theme.AppTypography.black141428TextStyle import com.sw.inbound.ui.theme.AppTypography.black141428TextStyle
import com.sw.inbound.ui.theme.AppTypography.gray96a0aaTextStyle import com.sw.inbound.ui.theme.AppTypography.gray96a0aaTextStyle
import com.sw.inbound.ui.theme.Black_141428
import com.sw.inbound.ui.theme.Red_FF3232
import com.sw.inbound.ui.weight.BottomActionBar import com.sw.inbound.ui.weight.BottomActionBar
import com.sw.inbound.ui.weight.CustomDropdownTextField import com.sw.inbound.ui.weight.CustomDropdownTextField
import com.sw.inbound.ui.weight.CustomSpinner import com.sw.inbound.ui.weight.CustomSpinner
@@ -129,23 +135,26 @@ fun ReceiptProductScreen(
} }
if (showDialog) { if (showDialog) {
ReceiptTipDialog(isWarn = viewModel.hasWrongCount(), onCancelClick = { ReceiptTipDialog(
Timber.d("返回") isWarn = viewModel.hasWrongCount(),
viewModel.updateReceiptDialog(false) goodsList = orders.filter { it.receivedNum != it.receiveCount },
}, onConfirmClick = { isFull -> onCancelClick = {
Timber.d(if (isFull) "确认收货" else "部分收货") Timber.d("返回")
viewModel.updateReceiptDialog(false) viewModel.updateReceiptDialog(false)
val uploadInfo = UploadInfo(id = id) },
if (isFull) { onConfirmClick = { isFull ->
uploadInfo.receiveGoodsInfos = orders Timber.d(if (isFull) "确认收货" else "部分收货")
viewModel.confirmReceipt(uploadInfo) viewModel.updateReceiptDialog(false)
} else { val uploadInfo = UploadInfo(id = id)
uploadInfo.receiveGoodsInfoList = orders if (isFull) {
uploadInfo.supplierId = supplierId uploadInfo.receiveGoodsInfos = orders
viewModel.partialReceipt(uploadInfo) viewModel.confirmReceipt(uploadInfo)
} } else {
uploadInfo.receiveGoodsInfoList = orders
}) uploadInfo.supplierId = supplierId
viewModel.partialReceipt(uploadInfo)
}
})
} }
} }
@@ -284,7 +293,7 @@ fun UnadjustedView(purchaseOrderList: List<GoodsInfo>, viewModel: ReceiptViewMod
modifier = Modifier.padding(horizontal = 30.dp), modifier = Modifier.padding(horizontal = 30.dp),
productList = purchaseOrderList, productList = purchaseOrderList,
checkedItem = checkedItem, checkedItem = checkedItem,
onItemCheckedClick = { onItemCheckedClick = { index, it ->
viewModel.updateSelectedItemWithSwitch(it) viewModel.updateSelectedItemWithSwitch(it)
}) })
} }
@@ -294,11 +303,14 @@ fun AdjustedView(viewModel: ReceiptViewModel) {
// 已调整view // 已调整view
val purchaseAdjustList by viewModel.adjustedOrders.collectAsState() val purchaseAdjustList by viewModel.adjustedOrders.collectAsState()
LazyColumn( LazyColumn(
verticalArrangement = Arrangement.spacedBy(0.dp) verticalArrangement = Arrangement.spacedBy(0.dp)
) { ) {
items(items = purchaseAdjustList, key = { it.goodId!! }) { itemsIndexed(
// ReceiptItem(it) items = purchaseAdjustList,
key = { index, it -> it.goodId!! + index }) { index, it ->
AdjustedViewItem(it, viewModel) AdjustedViewItem(it, viewModel)
} }
} }
@@ -306,9 +318,19 @@ fun AdjustedView(viewModel: ReceiptViewModel) {
@Composable @Composable
private fun AdjustedViewItem(purchaseOrder: GoodsInfo, viewModel: ReceiptViewModel) { private fun AdjustedViewItem(purchaseOrder: GoodsInfo, viewModel: ReceiptViewModel) {
val warehouseTypeList = GlobalData.warehouseTypeList // viewModel.getStoreList() val warehouseTypeList = GlobalData.warehouseTypeList
val isWarnItem = purchaseOrder.receivedNum != purchaseOrder.receiveCount
var modifier: Modifier // = Modifier.padding(horizontal = 30.dp)
if (isWarnItem) {
modifier = Modifier
.padding(horizontal = 30.dp)
.background(Color(0xffFAF1F9))
.border(width = 1.dp, color = Color.Red)
} else {
modifier = Modifier.padding(horizontal = 30.dp)
}
Column(modifier = Modifier.padding(horizontal = 30.dp)) { Column(modifier = modifier) {
Spacer(modifier = Modifier.height(30.dp)) Spacer(modifier = Modifier.height(30.dp))
Row( Row(
modifier = Modifier modifier = Modifier
@@ -316,7 +338,10 @@ private fun AdjustedViewItem(purchaseOrder: GoodsInfo, viewModel: ReceiptViewMod
.padding(horizontal = 30.dp), .padding(horizontal = 30.dp),
horizontalArrangement = Arrangement.SpaceBetween horizontalArrangement = Arrangement.SpaceBetween
) { ) {
Text(purchaseOrder.goodNameStr, style = AppTypography.blackTextStyle) Text(
purchaseOrder.goodNameStr,
style = if (isWarnItem) AppTypography.blackTextStyle.withColor(Color.Red) else AppTypography.blackTextStyle
)
Row { Row {
Text("采购量:", style = gray96a0aaTextStyle) Text("采购量:", style = gray96a0aaTextStyle)
Text( Text(
@@ -348,7 +373,8 @@ private fun AdjustedViewItem(purchaseOrder: GoodsInfo, viewModel: ReceiptViewMod
Text(text = "x", style = AppTypography.black141428TextStyle.bold()) Text(text = "x", style = AppTypography.black141428TextStyle.bold())
Spacer(modifier = Modifier.width(50.dp)) Spacer(modifier = Modifier.width(50.dp))
AdjustedRowInputLayout( AdjustedRowInputLayout(
label = "实收", value = purchaseOrder.receivedNumTemp, label = "实收",
value = purchaseOrder.receivedNumTemp,
onValueChange = { onValueChange = {
viewModel.updatePurchaseItem( viewModel.updatePurchaseItem(
purchaseOrder = purchaseOrder.copy( purchaseOrder = purchaseOrder.copy(
@@ -356,7 +382,9 @@ private fun AdjustedViewItem(purchaseOrder: GoodsInfo, viewModel: ReceiptViewMod
receivedNum = it.toSafeFloat() receivedNum = it.toSafeFloat()
) )
) )
}, inputType = InputType.Decimal },
inputType = InputType.Decimal,
inputTextColor = if (isWarnItem) Red_FF3232 else Black_141428
) )
Spacer(modifier = Modifier.width(12.dp)) Spacer(modifier = Modifier.width(12.dp))
Text(text = purchaseOrder.unitNameStr, style = AppTypography.gray96a0aaTextStyle) Text(text = purchaseOrder.unitNameStr, style = AppTypography.gray96a0aaTextStyle)
@@ -407,7 +435,8 @@ private fun AdjustedRowInputLayout(
textAlign: TextAlign = TextAlign.Center, textAlign: TextAlign = TextAlign.Center,
spinnerTextAlign: TextAlign = TextAlign.Start, spinnerTextAlign: TextAlign = TextAlign.Start,
trailingLabel: String? = null, trailingLabel: String? = null,
inputType: InputType = InputType.Text inputType: InputType = InputType.Text,
inputTextColor: Color = Black_141428
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
@@ -426,7 +455,13 @@ private fun AdjustedRowInputLayout(
value = value, value = value,
onValueChange = onValueChange, onValueChange = onValueChange,
textAlign = textAlign, textAlign = textAlign,
trailingLabel = trailingLabel, inputType = inputType trailingLabel = trailingLabel, inputType = inputType,
textStyle = LocalTextStyle.current.copy(
color = inputTextColor,
fontSize = 24.sp,
fontWeight = FontWeight.Bold,
textAlign = textAlign
)
) )
} else { } else {
CustomDropdownTextField( CustomDropdownTextField(
@@ -434,7 +469,7 @@ private fun AdjustedRowInputLayout(
value = value, value = value,
dropdownItems = dropdownItems, dropdownItems = dropdownItems,
onValueChange = onValueChange, onValueChange = onValueChange,
textAlign = spinnerTextAlign textAlign = spinnerTextAlign,
) )
} }
} }
@@ -696,7 +696,7 @@ private fun SelfProductEditView(
) )
} }
}, },
trailingLabel = selectedItem!!.unitName, trailingLabel = selectedItem!!.unitName ?: "-",
) )
RowInputLayout( RowInputLayout(
@@ -16,6 +16,13 @@ object AppTypography {
color = Color(0xFF96A0AA) color = Color(0xFF96A0AA)
) )
val gray999999TextStyle: TextStyle
@Composable get() = TextStyle(
fontSize = 24.sp,
fontWeight = FontWeight.Medium,
color = Color(0xFF999999)
)
val black141428TextStyle: TextStyle val black141428TextStyle: TextStyle
@Composable get() = TextStyle( @Composable get() = TextStyle(
fontSize = 24.sp, fontSize = 24.sp,
@@ -38,6 +45,14 @@ object AppTypography {
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
) )
val blackMediumTextStyle: TextStyle
@Composable
get() = TextStyle(
color = colorResource(R.color.black),
fontSize = 24.sp,
fontWeight = FontWeight.Medium
)
val BlueTextStyle: TextStyle val BlueTextStyle: TextStyle
@Composable @Composable
get() = TextStyle( get() = TextStyle(
@@ -18,4 +18,5 @@ val GrayDivider = Color(0XFFDCDCF0)
val Green_009632 = Color(0xFF009632) val Green_009632 = Color(0xFF009632)
val Blue_0032C8 = Color(0xFF0032C8) val Blue_0032C8 = Color(0xFF0032C8)
val Red_FF3232 = Color(0xFFFF3232)
@@ -12,9 +12,13 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@@ -36,10 +40,12 @@ fun ReceiptUnadjustedListView(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
productList: List<GoodsInfo>, productList: List<GoodsInfo>,
checkedItem: GoodsInfo? = null, checkedItem: GoodsInfo? = null,
onItemCheckedClick: (GoodsInfo) -> Unit = {}, onItemCheckedClick: (Int, GoodsInfo) -> Unit = { _, _ -> },
showClose: Boolean = false, showClose: Boolean = false,
onCloseClick: (GoodsInfo) -> Unit = {}, onCloseClick: (GoodsInfo) -> Unit = {},
) { ) {
var selectIndex by remember { mutableIntStateOf(-1) }
Column( Column(
modifier = modifier modifier = modifier
// .padding(horizontal = 30.dp) // .padding(horizontal = 30.dp)
@@ -85,17 +91,20 @@ fun ReceiptUnadjustedListView(
// Spacer(modifier = Modifier.height(31.dp)) // Spacer(modifier = Modifier.height(31.dp))
// 左侧列表 // 左侧列表
LazyColumn() { LazyColumn() {
items(items = productList, key = { it.goodId!! }) { it -> itemsIndexed(
items = productList,
key = { index, it -> it.goodId!! + index }) { index, it ->
val checkedBg = val checkedBg =
if (it.goodId == checkedItem?.goodId) Gray_DCDCF0 else Color.Transparent if (selectIndex == index) Gray_DCDCF0 else Color.Transparent
Row( Row(
modifier = Modifier modifier = Modifier
.background(color = checkedBg) .background(color = checkedBg)
.height(80.dp) .height(80.dp)
.padding(horizontal = 60.dp) .padding(horizontal = 60.dp)
.clickable { .clickable {
onItemCheckedClick(it) selectIndex = index
onItemCheckedClick(index, it)
}, verticalAlignment = Alignment.CenterVertically }, verticalAlignment = Alignment.CenterVertically
) { ) {
CustomSingleRightText( CustomSingleRightText(
@@ -1,6 +1,7 @@
package com.sw.inbound.ui.weight.dialog package com.sw.inbound.ui.weight.dialog
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@@ -11,6 +12,8 @@ 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.layout.wrapContentSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
@@ -21,6 +24,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.colorResource
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
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.Dialog
@@ -29,9 +33,12 @@ import com.sw.inbound.R
import com.sw.inbound.ext.bold import com.sw.inbound.ext.bold
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.response.GoodsInfo
import com.sw.inbound.ui.theme.AppTypography import com.sw.inbound.ui.theme.AppTypography
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
/** /**
* 收货确认弹窗 * 收货确认弹窗
@@ -40,6 +47,7 @@ import com.sw.inbound.ui.weight.CustomOutlinedButton
fun ReceiptTipDialog( fun ReceiptTipDialog(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
isWarn: Boolean = false, isWarn: Boolean = false,
goodsList: List<GoodsInfo>,
onCancelClick: () -> Unit, onCancelClick: () -> Unit,
onConfirmClick: (Boolean) -> Unit, onConfirmClick: (Boolean) -> Unit,
onDismiss: () -> Unit = {}, onDismiss: () -> Unit = {},
@@ -79,10 +87,83 @@ fun ReceiptTipDialog(
) )
Spacer(modifier = Modifier.height(60.dp)) Spacer(modifier = Modifier.height(60.dp))
Text( Text(
text = if (isWarn) "收货数量与采购量不一致" else "核对无误,确认收货", text = if (isWarn) "收货数量与采购量存在差异" else "核对无误,确认收货",
style = AppTypography.black141428TextStyle.bold().withSize(48.sp) style = AppTypography.black141428TextStyle.bold().withSize(48.sp)
) )
if (isWarn) { if (isWarn) {
Spacer(modifier = Modifier.height(60.dp))
Column(
modifier = Modifier
.height(257.dp)
.width(810.dp)
.border(width = 1.dp, color = GrayDivider)
) {
Row(
modifier = Modifier
.padding(start = 80.dp, top = 20.dp, end = 80.dp)
.height(50.dp),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
CustomSingleRightText(
modifier = Modifier.weight(1f),
text = "名称",
style = AppTypography.gray999999TextStyle,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.width(10.dp))
CustomSingleRightText(
modifier = Modifier.weight(1f),
text = "采购量",
style = AppTypography.gray999999TextStyle,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.width(10.dp))
CustomSingleRightText(
modifier = Modifier.weight(1f),
text = "实收",
style = AppTypography.gray999999TextStyle,
textAlign = TextAlign.Center
)
}
LazyColumn {
itemsIndexed(items = goodsList) { index, goods ->
Row(
modifier = Modifier
.padding(horizontal = 80.dp)
.height(50.dp),
horizontalArrangement = Arrangement.SpaceEvenly,
verticalAlignment = Alignment.CenterVertically
) {
CustomSingleRightText(
modifier = Modifier.weight(1f),
text = goods.goodNameStr,
style = AppTypography.blackMediumTextStyle,
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.width(10.dp))
CustomSingleRightText(
modifier = Modifier.weight(1f),
text = "${goods.receivedNumListStr}${goods.unitNameStr}",
style = AppTypography.blackMediumTextStyle.withColor(
color = Color(0xFF0032C8)
),
textAlign = TextAlign.Center
)
Spacer(modifier = Modifier.width(10.dp))
CustomSingleRightText(
modifier = Modifier.weight(1f),
text = "${goods.receiveCountListStr}${goods.unitNameStr}",
style = AppTypography.blackMediumTextStyle.withColor(
Color.Red
),
textAlign = TextAlign.Center
)
}
}
}
}
Spacer(modifier = Modifier.height(29.dp)) Spacer(modifier = Modifier.height(29.dp))
Text( Text(
text = "请确认实际收货数量,或选择部分收货处理", text = "请确认实际收货数量,或选择部分收货处理",
@@ -52,8 +52,8 @@ abstract class BaseViewModel(
if (response.isSuccess()) { if (response.isSuccess()) {
return true return true
} }
Timber.d("msg = ${response.msg}, code = ${response.code}") Timber.d("msg = ${response.message}, code = ${response.code}")
ToastUtils.showToast("${response.msg}(${response.code})") ToastUtils.showToast("${response.message}(${response.code})")
return false return false
} }
@@ -71,60 +71,60 @@ abstract class BaseViewModel(
Timber.d("获取所有字典列表") Timber.d("获取所有字典列表")
launchWithLoading { launchWithLoading {
val response = repository.getGoodsStorageType() val response = repository.getGoodsStorageType()
if (response.isSuccess()) { if (parseResponse(response)) {
Timber.d("getGoodsStorageType data = ${response.data}") Timber.d("getGoodsStorageType data = ${response.result}")
response.data?.let { response.result?.let {
// val dictType = DictType(response.data) // val dictType = DictType(response.data)
val list = mutableListOf<DictType>() val list = mutableListOf<DictType>()
for (type in response.data) { for (type in response.result) {
list.add(DictType(type.itemValue!!.toInt(), type.itemText!!)) list.add(DictType(type.itemValue!!.toInt(), type.itemText!!))
} }
GlobalData.storageTypeList = list GlobalData.storageTypeList = list
} }
} else { } else {
Timber.e("getGoodsStorageType msg = ${response.msg}, code = ${response.code}") Timber.e("getGoodsStorageType msg = ${response.message}, code = ${response.code}")
} }
val response1 = repository.getGoodsType() val response1 = repository.getGoodsType()
if (response1.isSuccess()) { if (parseResponse(response1)) {
Timber.d("getGoodsType data = ${response1.data?.allType}") Timber.d("getGoodsType data = ${response1.result?.allType}")
response1.data?.let { response1.result?.let {
if (response1.data.allType != null) { if (response1.result.allType != null) {
val list = mutableListOf<DictType>() val list = mutableListOf<DictType>()
for (type in response1.data.allType) { for (type in response1.result.allType) {
list.add(DictType(type!!.id!!, type.typeName!!)) list.add(DictType(type!!.id!!, type.typeName!!))
} }
GlobalData.goodsTypeList = list GlobalData.goodsTypeList = list
} }
} }
} else { } else {
Timber.e("getGoodsType msg = ${response1.msg}, code = ${response1.code}") Timber.e("getGoodsType msg = ${response1.message}, code = ${response1.code}")
} }
val response2 = repository.getDictType(RemoteRepository.TypeEnum.WAREHOUSE) val response2 = repository.getDictType(RemoteRepository.TypeEnum.WAREHOUSE)
if (response2.isSuccess()) { if (parseResponse(response2)) {
Timber.d("getDictType WAREHOUSE data = ${response2.data}") Timber.d("getDictType WAREHOUSE data = ${response2.result}")
response2.data?.let { response2.result?.let {
GlobalData.warehouseTypeList = response2.data GlobalData.warehouseTypeList = response2.result
} }
} else { } else {
Timber.e("getDictType WAREHOUSE msg = ${response2.msg}, code = ${response2.code}") Timber.e("getDictType WAREHOUSE msg = ${response2.message}, code = ${response2.code}")
} }
val response3 = repository.getDictType(RemoteRepository.TypeEnum.SUPPLIER) val response3 = repository.getDictType(RemoteRepository.TypeEnum.SUPPLIER)
if (response3.isSuccess()) { if (parseResponse(response3)) {
Timber.d("getDictType SUPPLIER data = ${response3.data}") Timber.d("getDictType SUPPLIER data = ${response3.result}")
response3.data?.let { response3.result?.let {
GlobalData.supplierTypeList = response3.data GlobalData.supplierTypeList = response3.result
} }
} else { } else {
Timber.e("getDictType SUPPLIER msg = ${response3.msg}, code = ${response3.code}") Timber.e("getDictType SUPPLIER msg = ${response3.message}, code = ${response3.code}")
} }
val response4 = repository.getDictType(RemoteRepository.TypeEnum.UNIT) val response4 = repository.getDictType(RemoteRepository.TypeEnum.UNIT)
if (response4.isSuccess()) { if (parseResponse(response4)) {
Timber.d("getDictType UNIT data = ${response4.data}") Timber.d("getDictType UNIT data = ${response4.result}")
response4.data?.let { response4.result?.let {
GlobalData.unitTypeList = response4.data GlobalData.unitTypeList = response4.result
} }
} else { } else {
Timber.e("getDictType UNIT msg = ${response4.msg}, code = ${response4.code}") Timber.e("getDictType UNIT msg = ${response4.message}, code = ${response4.code}")
} }
} }
} }
@@ -43,8 +43,8 @@ class PurchaseOrderViewModel @Inject constructor(
_isMoreLoading.value = true _isMoreLoading.value = true
val response = repository.getReceiveList(pageNum, pageSize) val response = repository.getReceiveList(pageNum, pageSize)
_isMoreLoading.value = false _isMoreLoading.value = false
if (response.isSuccess()) { if (parseResponse(response)) {
response.data?.records?.let { response.result?.records?.let {
_canLoadMore.value = it.size >= pageSize _canLoadMore.value = it.size >= pageSize
_supplierList.value = _supplierList.value + it _supplierList.value = _supplierList.value + it
} }
@@ -53,8 +53,8 @@ class PurchaseOrderViewModel @Inject constructor(
} else { } else {
launchWithLoading { launchWithLoading {
val response = repository.getReceiveList(pageNum, pageSize) val response = repository.getReceiveList(pageNum, pageSize)
if (response.isSuccess()) { if (parseResponse(response)) {
response.data?.records?.let { response.result?.records?.let {
_supplierList.value = it _supplierList.value = it
} }
} }
@@ -146,8 +146,8 @@ class ReceiptViewModel @Inject constructor(
fun getReceiveDetail(id: Int) { fun getReceiveDetail(id: Int) {
launchWithLoading { launchWithLoading {
val response = repository.getReceiveDetail(id) val response = repository.getReceiveDetail(id)
if (response.isSuccess()) { if (parseResponse(response)) {
_currentPurchaseInfo.value = response.data _currentPurchaseInfo.value = response.result
initOrders() initOrders()
} }
} }
@@ -305,15 +305,9 @@ class ReceiptViewModel @Inject constructor(
fun partialReceipt(uploadInfo: UploadInfo) { fun partialReceipt(uploadInfo: UploadInfo) {
launchWithLoading { launchWithLoading {
val response = repository.partialReceipt(uploadInfo) val response = repository.partialReceipt(uploadInfo)
if (!response.isSuccess()) { if (parseResponse(response)) {
parseResponse(response)
return@launchWithLoading
}
if (response.success == true) {
ToastUtils.showToast("部分收货成功") ToastUtils.showToast("部分收货成功")
_receiptResult.value = true _receiptResult.value = true
} else {
ToastUtils.showToast("部分收货失败")
} }
} }
} }
@@ -321,15 +315,9 @@ class ReceiptViewModel @Inject constructor(
fun confirmReceipt(uploadInfo: UploadInfo) { fun confirmReceipt(uploadInfo: UploadInfo) {
launchWithLoading { launchWithLoading {
val response = repository.confirmReceipt(uploadInfo) val response = repository.confirmReceipt(uploadInfo)
if (!response.isSuccess()) { if (parseResponse(response)) {
parseResponse(response)
return@launchWithLoading
}
if (response.success == true) {
ToastUtils.showToast("收货成功") ToastUtils.showToast("收货成功")
_receiptResult.value = true _receiptResult.value = true
} else {
ToastUtils.showToast("收货失败")
} }
} }
} }
@@ -107,16 +107,17 @@ class SelfProcurementViewModel @Inject constructor(
val currentItem = _selectedItem.value val currentItem = _selectedItem.value
currentItem?.let { info -> currentItem?.let { info ->
val selectUnitType = currentItem.selectUnitType
// 用户输入数量后不再通过重量反算 // 用户输入数量后不再通过重量反算
if (_countUserInput.value) { if (_countUserInput.value || selectUnitType == null) {
_selectedItem.value = info.copy( _selectedItem.value = info.copy(
goodsWeight = weight.toSafeBigDecimal(), goodsWeight = weight.toSafeBigDecimal(),
) )
return@startScale return@startScale
} }
val selectUnitType = currentItem.selectUnitType // val selectUnitType = currentItem.selectUnitType
if (selectUnitType == null) return@startScale // if (selectUnitType == null) return@startScale
val consumeValue = selectUnitType.consumeValue?.toDouble() ?: 1.0 val consumeValue = selectUnitType.consumeValue?.toDouble() ?: 1.0
val purchaseValue = selectUnitType.purchaseValue?.toDouble() ?: 1.0 val purchaseValue = selectUnitType.purchaseValue?.toDouble() ?: 1.0
@@ -265,8 +266,8 @@ class SelfProcurementViewModel @Inject constructor(
} }
val response = repository.searchGoodsInfoList(goodsName, pageNo, pageSize) val response = repository.searchGoodsInfoList(goodsName, pageNo, pageSize)
_isMoreLoading.value = false _isMoreLoading.value = false
if (response.isSuccess()) { if (parseResponse(response)) {
val data = response.data val data = response.result
data?.records?.let { data?.records?.let {
_canLoadMore.value = data.records.size >= pageSize _canLoadMore.value = data.records.size >= pageSize
if (pageNo > 1) { if (pageNo > 1) {
@@ -334,22 +335,20 @@ class SelfProcurementViewModel @Inject constructor(
launchWithLoading { launchWithLoading {
val uploadResponse = repository.uploadImage(imageUri) val uploadResponse = repository.uploadImage(imageUri)
if (!uploadResponse.isSuccess()) { if (!parseResponse(uploadResponse)) {
parseResponse(uploadResponse)
return@launchWithLoading return@launchWithLoading
} }
// ToastUtils.showToast("图片上传成功,${uploadResponse.data}") // ToastUtils.showToast("图片上传成功,${uploadResponse.data}")
GlobalData.imageUri = null GlobalData.imageUri = null
_goodsAddParam.value.relativeUrl = uploadResponse.data _goodsAddParam.value.relativeUrl = uploadResponse.result
val response = repository.selfPurchaseGoodsAdd(_goodsAddParam.value) val response = repository.selfPurchaseGoodsAdd(_goodsAddParam.value)
if (!response.isSuccess()) { if (!parseResponse(response)) {
parseResponse(response)
return@launchWithLoading return@launchWithLoading
} }
FileUtils.deleteFileWithUri(context = ContextUtils.getAppContext(), uri = imageUri) FileUtils.deleteFileWithUri(context = ContextUtils.getAppContext(), uri = imageUri)
_showAddProductDialog.value = false _showAddProductDialog.value = false
_goodsAddParam.value = GoodsAddParam() _goodsAddParam.value = GoodsAddParam()
val searchFirst = response.data!!.records?.get(0) val searchFirst = response.result!!.records?.get(0)
searchFirst?.let { searchFirst?.let {
updateSelectedItemWithSearch(searchFirst) updateSelectedItemWithSearch(searchFirst)
} }
@@ -369,6 +368,8 @@ class SelfProcurementViewModel @Inject constructor(
val response = repository.selfPurchaseWarehousing(_purchaseList.value) val response = repository.selfPurchaseWarehousing(_purchaseList.value)
if (parseResponse(response)) { if (parseResponse(response)) {
_addToWarehouseResult.value = true _addToWarehouseResult.value = true
} else {
_addToWarehouseResult.value = false
} }
} }
} }
@@ -38,10 +38,11 @@ class UserViewModel @Inject constructor(
fun login(userName: String, password: String) = launchWithLoading { fun login(userName: String, password: String) = launchWithLoading {
val loginParam = LoginParam(userName = userName, password = password) val loginParam = LoginParam(userName = userName, password = password)
val response = repo.login(loginParam) val response = repo.login(loginParam)
if (response.isSuccess()) { if (parseResponse(response)) {
_user.value = response.data SPUtil.getInstance().put(GlobalKey.KEY_USER_NAME, userName)
saveToken(response.data) _user.value = response.result
response.data?.token saveToken(response.result)
response.result?.token
} }
} }