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