feat(inbound): 新增入库秤毛菜/净菜入库功能完整实现
- StoreActivity 进入时统一弹出 InboundGoodsSearchDialog,关闭后退出页面 - InboundGoodsStoreDialog 支持 goods 可空,适配无溯源码直接入库场景 - FormField 新增 extraApiKeys/extraValues 支持下拉多字段提交(供应商id+type、区域id+name) - DictType 新增 type 字段,供应商选项携带类型信息 - FormFieldAdapter 下拉选中时按 extraApiKeys 映射写入 extraValues - InboundApiService 使用 @JvmSuppressWildcards 修复 Retrofit Map 泛型通配符异常 - BaseActivity 改为继承 AppCompatActivity,主题切换为 MaterialComponents - 日期格式统一为 yyyy-MM-dd HH:mm:ss(去除 ISO 8601 的 T 分隔符) - 搜索列表选中逻辑修复,改用 notifyDataSetChanged 触发刷新
This commit is contained in:
@@ -173,7 +173,10 @@ abstract class GoodsListActivity : BaseActivity() {
|
|||||||
SensorScaleUtils.tare()
|
SensorScaleUtils.tare()
|
||||||
}
|
}
|
||||||
|
|
||||||
userViewModel.getInitInfo()
|
|
||||||
|
if (this !is StoreActivity) {
|
||||||
|
userViewModel.getInitInfo()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
|||||||
@@ -77,36 +77,36 @@ class HomeActivity : BaseActivity() {
|
|||||||
*/
|
*/
|
||||||
private fun initViews() {
|
private fun initViews() {
|
||||||
// 标题点击:跳转菜品采集页面
|
// 标题点击:跳转菜品采集页面
|
||||||
binding.tvTitle.setOnClickListener {
|
// binding.tvTitle.setOnClickListener {
|
||||||
startActivity<FoodCollectionActivity>()
|
// startActivity<FoodCollectionActivity>()
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
// // 时间点击:打开环境切换弹窗
|
||||||
|
// binding.tvTime.setOnClickListener { v ->
|
||||||
|
// EnvSwitchDialog(context = this, onEnvChanged = {
|
||||||
|
// Loading.show(this)
|
||||||
|
// lifecycleScope.launch {
|
||||||
|
// ObjectBox.removeAll()
|
||||||
|
// FoodModule.init(this@HomeActivity)
|
||||||
|
// v.postDelayed({
|
||||||
|
// Loading.dismiss()
|
||||||
|
// toast("服务重置完成")
|
||||||
|
// }, 500)
|
||||||
|
// }
|
||||||
|
// }).show()
|
||||||
|
// }
|
||||||
|
|
||||||
// 时间点击:打开环境切换弹窗
|
// // 采购单入库入口
|
||||||
binding.tvTime.setOnClickListener { v ->
|
// binding.ivOrderPurchase.setOnClickListener {
|
||||||
EnvSwitchDialog(context = this, onEnvChanged = {
|
// startActivity<PurchaseOrderActivity>()
|
||||||
Loading.show(this)
|
// }
|
||||||
lifecycleScope.launch {
|
//
|
||||||
ObjectBox.removeAll()
|
// // 自采入库入口,传入非采购单标志
|
||||||
FoodModule.init(this@HomeActivity)
|
// binding.ivOrderSelfProcurement.setOnClickListener {
|
||||||
v.postDelayed({
|
// startActivity<SelfProcurementActivity> {
|
||||||
Loading.dismiss()
|
// putExtra(GoodsListActivity.IS_RECEIPT_PAGE, false)
|
||||||
toast("服务重置完成")
|
// }
|
||||||
}, 500)
|
// }
|
||||||
}
|
|
||||||
}).show()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 采购单入库入口
|
|
||||||
binding.ivOrderPurchase.setOnClickListener {
|
|
||||||
startActivity<PurchaseOrderActivity>()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 自采入库入口,传入非采购单标志
|
|
||||||
binding.ivOrderSelfProcurement.setOnClickListener {
|
|
||||||
startActivity<SelfProcurementActivity> {
|
|
||||||
putExtra(GoodsListActivity.IS_RECEIPT_PAGE, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 净菜按钮点击提示
|
// 净菜按钮点击提示
|
||||||
binding.btnCleanDishStore.setOnClickListener {
|
binding.btnCleanDishStore.setOnClickListener {
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import android.os.Bundle
|
|||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import com.sw.inbound.GlobalData
|
import com.sw.inbound.GlobalData
|
||||||
import com.sw.inbound.dialog.InboundGoodsSearchDialog
|
import com.sw.inbound.dialog.InboundGoodsSearchDialog
|
||||||
import com.sw.inbound.dialog.InboundGoodsStoreDialog
|
|
||||||
import com.sw.inbound.model.response.DictType
|
import com.sw.inbound.model.response.DictType
|
||||||
import com.sw.inbound.utils.ext.gone
|
import com.sw.inbound.utils.ext.gone
|
||||||
import com.sw.inbound.viewmodel.StoreViewModel
|
import com.sw.inbound.viewmodel.StoreViewModel
|
||||||
@@ -41,17 +40,11 @@ class StoreActivity : GoodsListActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 根据 storeType 弹出对应入库弹窗,dismiss 时关闭页面 */
|
/** 进入页面统一打开检索弹窗,dismiss 时关闭页面 */
|
||||||
private fun showEntryDialog() {
|
private fun showEntryDialog() {
|
||||||
if (storeType == 1) {
|
InboundGoodsSearchDialog(this).apply {
|
||||||
InboundGoodsStoreDialog(this, null).apply {
|
setOnDismissListener { finish() }
|
||||||
setOnDismissListener { finish() }
|
}.show()
|
||||||
}.show()
|
|
||||||
} else {
|
|
||||||
InboundGoodsSearchDialog(this).apply {
|
|
||||||
setOnDismissListener { finish() }
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 预加载供应商和仓库区域列表到 GlobalData,供弹窗直接使用 */
|
/** 预加载供应商和仓库区域列表到 GlobalData,供弹窗直接使用 */
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class FormFieldAdapter(
|
|||||||
fields: MutableList<FormField>
|
fields: MutableList<FormField>
|
||||||
) : BaseQuickAdapter<FormField, FormFieldAdapter.VH>(fields) {
|
) : BaseQuickAdapter<FormField, FormFieldAdapter.VH>(fields) {
|
||||||
|
|
||||||
private val isoFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault())
|
private val isoFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
||||||
private val displayDateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
|
private val displayDateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
|
||||||
|
|
||||||
inner class VH(val binding: ListItemFormFieldBinding) : QuickViewHolder(binding.root)
|
inner class VH(val binding: ListItemFormFieldBinding) : QuickViewHolder(binding.root)
|
||||||
@@ -125,6 +125,17 @@ class FormFieldAdapter(
|
|||||||
item.value = dictType.value ?: ""
|
item.value = dictType.value ?: ""
|
||||||
item.valueId = dictType.id ?: ""
|
item.valueId = dictType.id ?: ""
|
||||||
b.tvDropdownValue.text = item.value
|
b.tvDropdownValue.text = item.value
|
||||||
|
// 将 extraApiKeys 映射的 DictType 字段值写入 extraValues
|
||||||
|
item.extraValues.clear()
|
||||||
|
item.extraApiKeys.forEach { (apiKey, dictField) ->
|
||||||
|
val fieldValue = when (dictField) {
|
||||||
|
"id" -> dictType.id ?: ""
|
||||||
|
"value" -> dictType.value ?: ""
|
||||||
|
"type" -> dictType.type
|
||||||
|
else -> ""
|
||||||
|
}
|
||||||
|
item.extraValues[apiKey] = fieldValue
|
||||||
|
}
|
||||||
}.also {
|
}.also {
|
||||||
it.bgLayout = b.flDropdown
|
it.bgLayout = b.flDropdown
|
||||||
it.showAsDropDown(v)
|
it.showAsDropDown(v)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
package com.sw.inbound.base
|
package com.sw.inbound.base
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.WindowInsetsControllerCompat
|
import androidx.core.view.WindowInsetsControllerCompat
|
||||||
@@ -12,7 +12,7 @@ import androidx.core.view.WindowInsetsControllerCompat
|
|||||||
* - 自动隐藏状态栏和导航栏,实现全屏沉浸式体验
|
* - 自动隐藏状态栏和导航栏,实现全屏沉浸式体验
|
||||||
* - 在屏幕底部上滑时可临时唤出导航栏,松手后自动收回
|
* - 在屏幕底部上滑时可临时唤出导航栏,松手后自动收回
|
||||||
*/
|
*/
|
||||||
abstract class BaseActivity : ComponentActivity() {
|
abstract class BaseActivity : AppCompatActivity() {
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|||||||
@@ -33,9 +33,15 @@ class InboundGoodsSearchDialog(
|
|||||||
|
|
||||||
override fun initView() {
|
override fun initView() {
|
||||||
storeActivity = getReceiptActivity() as? StoreActivity
|
storeActivity = getReceiptActivity() as? StoreActivity
|
||||||
|
binding.tvDialogTitle.text = if (storeActivity?.storeType == 1) "毛菜检索" else "净菜检索"
|
||||||
binding.ivClose.setOnClickListener { dismiss() }
|
binding.ivClose.setOnClickListener { dismiss() }
|
||||||
binding.ivGoodsSearch.setOnClickListener { searchGoods() }
|
binding.ivGoodsSearch.setOnClickListener { searchGoods() }
|
||||||
binding.etInputGoods.addOnActionSearchListener { searchGoods() }
|
binding.etInputGoods.addOnActionSearchListener { searchGoods() }
|
||||||
|
binding.btnAddGoods.setOnClickListener {
|
||||||
|
InboundGoodsStoreDialog(context = context, goods = null) {
|
||||||
|
dismiss()
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
binding.btnConfirm.setOnClickListener {
|
binding.btnConfirm.setOnClickListener {
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
context.toast("请搜索物品")
|
context.toast("请搜索物品")
|
||||||
@@ -92,9 +98,10 @@ class InboundGoodsSearchDialog(
|
|||||||
if (emptyBinding == null) {
|
if (emptyBinding == null) {
|
||||||
emptyBinding = LayoutEmptySearchBinding.inflate(inflater, binding.rvSearch, false)
|
emptyBinding = LayoutEmptySearchBinding.inflate(inflater, binding.rvSearch, false)
|
||||||
}
|
}
|
||||||
emptyBinding?.root?.let { layout ->
|
emptyBinding?.run {
|
||||||
layout.setOnClickListener { layout.hideKeyboard() }
|
tvContent.text = "请检查溯源码或稍后重试"
|
||||||
searchAdapter.stateView = layout
|
root.setOnClickListener { root.hideKeyboard() }
|
||||||
|
searchAdapter.stateView = root
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +116,7 @@ class InboundGoodsSearchDialog(
|
|||||||
if (list[position].isSelected) return@setOnItemClickListener
|
if (list[position].isSelected) return@setOnItemClickListener
|
||||||
list.forEach { it.isSelected = false }
|
list.forEach { it.isSelected = false }
|
||||||
list[position].isSelected = true
|
list[position].isSelected = true
|
||||||
submitList(list.toList())
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class InboundGoodsStoreDialog(
|
|||||||
|
|
||||||
private var realWeight: Int = 0
|
private var realWeight: Int = 0
|
||||||
|
|
||||||
private val isoFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault())
|
private val isoFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault())
|
||||||
|
|
||||||
/** 当前渲染的表单字段列表 */
|
/** 当前渲染的表单字段列表 */
|
||||||
private lateinit var fields: MutableList<FormField>
|
private lateinit var fields: MutableList<FormField>
|
||||||
@@ -85,7 +85,7 @@ class InboundGoodsStoreDialog(
|
|||||||
private fun buildRawFields(): MutableList<FormField> {
|
private fun buildRawFields(): MutableList<FormField> {
|
||||||
val supplierOptions = GlobalData.inboundSupplierList.mapNotNull { opt ->
|
val supplierOptions = GlobalData.inboundSupplierList.mapNotNull { opt ->
|
||||||
val id = opt.id?.toString() ?: return@mapNotNull null
|
val id = opt.id?.toString() ?: return@mapNotNull null
|
||||||
DictType(id = id, value = opt.name)
|
DictType(id = id, value = opt.name, type = opt.type?.toString() ?: "")
|
||||||
}
|
}
|
||||||
val zoneOptions = GlobalData.inboundZoneList.mapNotNull { zone ->
|
val zoneOptions = GlobalData.inboundZoneList.mapNotNull { zone ->
|
||||||
val id = zone.id?.toString() ?: return@mapNotNull null
|
val id = zone.id?.toString() ?: return@mapNotNull null
|
||||||
@@ -96,26 +96,23 @@ class InboundGoodsStoreDialog(
|
|||||||
"溯源码",
|
"溯源码",
|
||||||
FieldType.TEXT,
|
FieldType.TEXT,
|
||||||
apiKey = "traceCode",
|
apiKey = "traceCode",
|
||||||
value = "",
|
value = goods?.traceCode ?: "",
|
||||||
required = true,
|
required = true,
|
||||||
hint = "请输入溯源码"
|
hint = "请输入溯源码"
|
||||||
),
|
),
|
||||||
FormField(
|
|
||||||
"来源类型", FieldType.DROPDOWN, apiKey = "", options = listOf(
|
|
||||||
DictType("0", "外采"), DictType("1", "自产")
|
|
||||||
)
|
|
||||||
),
|
|
||||||
FormField(
|
FormField(
|
||||||
"食材名称",
|
"食材名称",
|
||||||
FieldType.DROPDOWN,
|
FieldType.TEXT,
|
||||||
apiKey = "materialName",
|
apiKey = "materialName",
|
||||||
required = true,
|
required = true,
|
||||||
value = "",
|
value = goods?.materName ?:"",
|
||||||
hint = "请选择食材名称"
|
hint = "请输入食材名称"
|
||||||
),
|
),
|
||||||
FormField(
|
FormField(
|
||||||
"供应商", FieldType.DROPDOWN, apiKey = "supplierId", required = true,
|
"供应商", FieldType.DROPDOWN,
|
||||||
hint = "请选择供应商", options = supplierOptions, submitValueId = true
|
extraApiKeys = mapOf("supplierId" to "id", "supplierType" to "type"),
|
||||||
|
required = true,
|
||||||
|
hint = "请选择供应商", options = supplierOptions
|
||||||
),
|
),
|
||||||
FormField(
|
FormField(
|
||||||
"入库规格",
|
"入库规格",
|
||||||
@@ -140,13 +137,11 @@ class InboundGoodsStoreDialog(
|
|||||||
submitValueId = true
|
submitValueId = true
|
||||||
),
|
),
|
||||||
FormField(
|
FormField(
|
||||||
"存放区域",
|
"存放区域", FieldType.DROPDOWN,
|
||||||
FieldType.DROPDOWN,
|
extraApiKeys = mapOf("zoneId" to "id", "storageArea" to "value"),
|
||||||
apiKey = "zoneId",
|
|
||||||
required = true,
|
required = true,
|
||||||
hint = "请选择存放区域",
|
hint = "请选择存放区域",
|
||||||
options = zoneOptions,
|
options = zoneOptions
|
||||||
submitValueId = true
|
|
||||||
),
|
),
|
||||||
FormField(
|
FormField(
|
||||||
"操作人",
|
"操作人",
|
||||||
@@ -166,10 +161,6 @@ class InboundGoodsStoreDialog(
|
|||||||
* expiryDate, storageTemp
|
* expiryDate, storageTemp
|
||||||
*/
|
*/
|
||||||
private fun buildCleanFields(): MutableList<FormField> {
|
private fun buildCleanFields(): MutableList<FormField> {
|
||||||
val vegTypes = goods?.vegTypeList() ?: emptyList()
|
|
||||||
val cleanTypeOptions = vegTypes.mapIndexed { index, type ->
|
|
||||||
DictType(id = index.toString(), value = type)
|
|
||||||
}
|
|
||||||
val zoneOptions = GlobalData.inboundZoneList.mapNotNull { zone ->
|
val zoneOptions = GlobalData.inboundZoneList.mapNotNull { zone ->
|
||||||
val id = zone.id?.toString() ?: return@mapNotNull null
|
val id = zone.id?.toString() ?: return@mapNotNull null
|
||||||
DictType(id = id, value = zone.zoneName)
|
DictType(id = id, value = zone.zoneName)
|
||||||
@@ -185,30 +176,23 @@ class InboundGoodsStoreDialog(
|
|||||||
),
|
),
|
||||||
FormField(
|
FormField(
|
||||||
"食材名称",
|
"食材名称",
|
||||||
FieldType.FIXED,
|
type = if (goods?.materName.isNullOrEmpty()) FieldType.TEXT else FieldType.FIXED,
|
||||||
apiKey = "ingredientName",
|
apiKey = "ingredientName",
|
||||||
required = true,
|
required = true,
|
||||||
value = goods?.materName ?: ""
|
value = goods?.materName ?: ""
|
||||||
),
|
),
|
||||||
FormField(
|
FormField(
|
||||||
"净菜类型",
|
"净菜类型",
|
||||||
FieldType.FIXED,
|
type = if (goods?.materName.isNullOrEmpty()) FieldType.TEXT else FieldType.FIXED,
|
||||||
required = true,
|
|
||||||
apiKey = "cleanType",
|
apiKey = "cleanType",
|
||||||
|
value = goods?.vegTypes ?: ""
|
||||||
),
|
),
|
||||||
FormField(
|
FormField(
|
||||||
"入库规格",
|
"入库规格",
|
||||||
FieldType.DROPDOWN,
|
FieldType.TEXT,
|
||||||
apiKey = "spec",
|
apiKey = "spec",
|
||||||
required = true,
|
required = true,
|
||||||
hint = "请选择入库规格",
|
hint = "请输入入库规格"
|
||||||
options = listOf(
|
|
||||||
DictType("0", "袋装/500g"),
|
|
||||||
DictType("1", "袋装/300g"),
|
|
||||||
DictType("1", "瓶装/800ml"),
|
|
||||||
DictType("1", "瓶装/500ml"),
|
|
||||||
DictType("1", "其它"),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
FormField(
|
FormField(
|
||||||
"入库数量",
|
"入库数量",
|
||||||
@@ -217,6 +201,13 @@ class InboundGoodsStoreDialog(
|
|||||||
required = true,
|
required = true,
|
||||||
hint = "请输入入库数量"
|
hint = "请输入入库数量"
|
||||||
),
|
),
|
||||||
|
FormField(
|
||||||
|
"操作时间",
|
||||||
|
FieldType.DATE_PICKER,
|
||||||
|
apiKey = "inboundTime",
|
||||||
|
hint = "请选择操作时间",
|
||||||
|
submitValueId = true
|
||||||
|
),
|
||||||
FormField(
|
FormField(
|
||||||
"保质期至",
|
"保质期至",
|
||||||
FieldType.DATE_PICKER,
|
FieldType.DATE_PICKER,
|
||||||
@@ -225,13 +216,11 @@ class InboundGoodsStoreDialog(
|
|||||||
submitValueId = true
|
submitValueId = true
|
||||||
),
|
),
|
||||||
FormField(
|
FormField(
|
||||||
"存放区域",
|
"存放区域", FieldType.DROPDOWN,
|
||||||
FieldType.DROPDOWN,
|
extraApiKeys = mapOf("zoneId" to "id", "storageArea" to "value"),
|
||||||
apiKey = "zoneId",
|
|
||||||
required = true,
|
required = true,
|
||||||
hint = "请选择存放区域",
|
hint = "请选择存放区域",
|
||||||
options = zoneOptions,
|
options = zoneOptions
|
||||||
submitValueId = true
|
|
||||||
),
|
),
|
||||||
FormField(
|
FormField(
|
||||||
"存放温度(℃)",
|
"存放温度(℃)",
|
||||||
@@ -257,7 +246,10 @@ class InboundGoodsStoreDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupButtons() {
|
private fun setupButtons() {
|
||||||
binding.btnCancel.setOnClickListener { dismiss() }
|
binding.btnCancel.setOnClickListener {
|
||||||
|
dismiss()
|
||||||
|
if (goods == null) storeActivity?.finish()
|
||||||
|
}
|
||||||
binding.btnConfirm.setOnClickListener { confirmInputData() }
|
binding.btnConfirm.setOnClickListener { confirmInputData() }
|
||||||
binding.tvTitle.run {
|
binding.tvTitle.run {
|
||||||
text = if (storeType == 1) "毛菜入库" else "净菜入库"
|
text = if (storeType == 1) "毛菜入库" else "净菜入库"
|
||||||
@@ -304,21 +296,25 @@ class InboundGoodsStoreDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 fields 转为接口 Map,规则:
|
* 将 fields 转为接口 Map:
|
||||||
* - apiKey 为空的字段跳过
|
* - extraApiKeys 非空时从 extraValues 读取多字段值
|
||||||
* - submitValueId=true 时取 valueId,否则取 value
|
* - apiKey 非空时按原逻辑提交单字段值
|
||||||
* - 空字符串跳过(可选字段无值不传)
|
* - quantity → Int,storageTemp → Double,其余 → String
|
||||||
* - quantity → Int,zoneId/supplierId → Long,storageTemp → Double,其余 → String
|
|
||||||
*/
|
*/
|
||||||
private fun buildParamMap(): MutableMap<String, Any> {
|
private fun buildParamMap(): MutableMap<String, Any> {
|
||||||
val map = mutableMapOf<String, Any>()
|
val map = mutableMapOf<String, Any>()
|
||||||
for (field in fields) {
|
for (field in fields) {
|
||||||
|
if (field.extraApiKeys.isNotEmpty()) {
|
||||||
|
field.extraValues.forEach { (apiKey, raw) ->
|
||||||
|
if (raw.isNotBlank()) map[apiKey] = raw
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
if (field.apiKey.isBlank()) continue
|
if (field.apiKey.isBlank()) continue
|
||||||
val raw = if (field.submitValueId) field.valueId else field.value
|
val raw = if (field.submitValueId) field.valueId else field.value
|
||||||
if (raw.isBlank()) continue
|
if (raw.isBlank()) continue
|
||||||
val converted: Any = when (field.apiKey) {
|
val converted: Any = when (field.apiKey) {
|
||||||
"quantity" -> raw.toIntOrNull() ?: continue
|
"quantity" -> raw.toIntOrNull() ?: continue
|
||||||
"zoneId", "supplierId" -> raw.toLongOrNull() ?: continue
|
|
||||||
"storageTemp" -> raw.toDoubleOrNull() ?: continue
|
"storageTemp" -> raw.toDoubleOrNull() ?: continue
|
||||||
else -> raw
|
else -> raw
|
||||||
}
|
}
|
||||||
@@ -331,10 +327,6 @@ class InboundGoodsStoreDialog(
|
|||||||
val param = buildParamMap()
|
val param = buildParamMap()
|
||||||
// weight 来自秤,不在表单中,额外注入
|
// weight 来自秤,不在表单中,额外注入
|
||||||
param["weight"] = realWeight / 1000.0
|
param["weight"] = realWeight / 1000.0
|
||||||
// supplierType 从 GlobalData 查找,不在表单中
|
|
||||||
val supplierId = param["supplierId"]?.toString()
|
|
||||||
val supplierOpt = GlobalData.inboundSupplierList.find { it.id?.toString() == supplierId }
|
|
||||||
param["supplierType"] = (supplierOpt?.type ?: 1)
|
|
||||||
|
|
||||||
Loading.show(storeActivity ?: return)
|
Loading.show(storeActivity ?: return)
|
||||||
storeActivity?.storeViewModel?.submitRawInbound(param) { success, msg ->
|
storeActivity?.storeViewModel?.submitRawInbound(param) { success, msg ->
|
||||||
|
|||||||
@@ -20,24 +20,28 @@ enum class FieldType {
|
|||||||
* 动态表单字段数据模型
|
* 动态表单字段数据模型
|
||||||
* @param label 字段标签名称
|
* @param label 字段标签名称
|
||||||
* @param type 字段类型,决定渲染哪种输入控件
|
* @param type 字段类型,决定渲染哪种输入控件
|
||||||
* @param apiKey 对应接口的字段名,空字符串表示该字段不提交(如来源类型)
|
* @param apiKey 非下拉字段对应的接口参数名,空字符串表示不提交
|
||||||
|
* @param extraApiKeys 下拉字段的多接口参数映射,key=接口参数名,value=DictType 字段名(id/value/type)
|
||||||
* @param required 是否必填,提交时校验
|
* @param required 是否必填,提交时校验
|
||||||
* @param hidden 是否隐藏,hidden=true 时不渲染该字段
|
* @param hidden 是否隐藏,hidden=true 时不渲染该字段
|
||||||
* @param hint 校验失败提示文案,同时作为输入框 hint
|
* @param hint 校验失败提示文案,同时作为输入框 hint
|
||||||
* @param options 下拉框选项列表(DROPDOWN 类型使用)
|
* @param options 下拉框选项列表(DROPDOWN 类型使用)
|
||||||
* @param submitValueId 提交时使用 valueId 而非 value;DROPDOWN 选 id、DATE_PICKER 选 ISO 格式时设为 true
|
* @param submitValueId 提交时使用 valueId 而非 value;DATE_PICKER 选 ISO 格式时设为 true
|
||||||
* @param value 当前显示值/输入值;DATE_PICKER 存 yyyy-MM-dd 显示格式
|
* @param value 当前显示值/输入值;DATE_PICKER 存 yyyy-MM-dd 显示格式
|
||||||
* @param valueId 下拉框选中项的 id;DATE_PICKER 存 ISO 格式 yyyy-MM-dd'T'HH:mm:ss
|
* @param valueId DATE_PICKER 存 ISO 格式 yyyy-MM-dd'T'HH:mm:ss
|
||||||
|
* @param extraValues 下拉选中后按 extraApiKeys 映射存储的提交值,key=接口参数名
|
||||||
*/
|
*/
|
||||||
data class FormField(
|
data class FormField(
|
||||||
val label: String,
|
val label: String,
|
||||||
val type: FieldType,
|
val type: FieldType,
|
||||||
val apiKey: String = "",
|
val apiKey: String = "",
|
||||||
|
val extraApiKeys: Map<String, String> = emptyMap(),
|
||||||
val required: Boolean = false,
|
val required: Boolean = false,
|
||||||
val hidden: Boolean = false,
|
val hidden: Boolean = false,
|
||||||
val hint: String = "",
|
val hint: String = "",
|
||||||
val options: List<DictType> = emptyList(),
|
val options: List<DictType> = emptyList(),
|
||||||
val submitValueId: Boolean = false,
|
val submitValueId: Boolean = false,
|
||||||
var value: String = "",
|
var value: String = "",
|
||||||
var valueId: String = ""
|
var valueId: String = "",
|
||||||
|
val extraValues: MutableMap<String, String> = mutableMapOf()
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import kotlinx.parcelize.Parcelize
|
|||||||
*/
|
*/
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class DictType(
|
data class DictType(
|
||||||
val id: String?=null,
|
val id: String? = null,
|
||||||
val value: String?=null
|
val value: String? = null,
|
||||||
|
val type: String = ""
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|||||||
@@ -39,12 +39,12 @@ interface InboundApiService {
|
|||||||
/** 毛菜入库提交,入参为 Map 以便动态组装字段 */
|
/** 毛菜入库提交,入参为 Map 以便动态组装字段 */
|
||||||
@POST("nutrition/neglect/inbound/raw-inbound")
|
@POST("nutrition/neglect/inbound/raw-inbound")
|
||||||
suspend fun submitRawInbound(
|
suspend fun submitRawInbound(
|
||||||
@Body param: Map<String, Any>
|
@Body param: Map<String, @JvmSuppressWildcards Any>
|
||||||
): InboundApiResponse<Unit>
|
): InboundApiResponse<Unit>
|
||||||
|
|
||||||
/** 净菜入库提交,入参为 Map 以便动态组装字段 */
|
/** 净菜入库提交,入参为 Map 以便动态组装字段 */
|
||||||
@POST("nutrition/neglect/inbound/clean-inbound")
|
@POST("nutrition/neglect/inbound/clean-inbound")
|
||||||
suspend fun submitCleanInbound(
|
suspend fun submitCleanInbound(
|
||||||
@Body param: Map<String, Any>
|
@Body param: Map<String, @JvmSuppressWildcards Any>
|
||||||
): InboundApiResponse<Unit>
|
): InboundApiResponse<Unit>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -116,7 +116,7 @@
|
|||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<!-- 净菜入库入口 -->
|
<!-- 净菜入库入口 -->
|
||||||
<Button
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
android:id="@+id/btnCleanDishStore"
|
android:id="@+id/btnCleanDishStore"
|
||||||
android:layout_width="595dp"
|
android:layout_width="595dp"
|
||||||
android:layout_height="477dp"
|
android:layout_height="477dp"
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
android:layout_height="1dp" />
|
android:layout_height="1dp" />
|
||||||
|
|
||||||
<!-- 毛菜入库入口 -->
|
<!-- 毛菜入库入口 -->
|
||||||
<Button
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
android:id="@+id/btnRawDishStore"
|
android:id="@+id/btnRawDishStore"
|
||||||
android:layout_width="595dp"
|
android:layout_width="595dp"
|
||||||
android:layout_height="477dp"
|
android:layout_height="477dp"
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
android:layout_marginBottom="40dp" />
|
android:layout_marginBottom="40dp" />
|
||||||
|
|
||||||
<!-- 连接网络按钮 -->
|
<!-- 连接网络按钮 -->
|
||||||
<Button
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
android:id="@+id/btnConnectNetwork"
|
android:id="@+id/btnConnectNetwork"
|
||||||
android:layout_width="350dp"
|
android:layout_width="350dp"
|
||||||
android:layout_height="70dp"
|
android:layout_height="70dp"
|
||||||
|
|||||||
@@ -110,24 +110,23 @@
|
|||||||
android:background="#FFDCDCF0"
|
android:background="#FFDCDCF0"
|
||||||
app:layout_constraintBottom_toBottomOf="parent" />
|
app:layout_constraintBottom_toBottomOf="parent" />
|
||||||
|
|
||||||
<!-- btnAddGoods 在入库秤场景下隐藏 -->
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
<Button
|
|
||||||
android:id="@+id/btnAddGoods"
|
android:id="@+id/btnAddGoods"
|
||||||
android:layout_width="240dp"
|
android:layout_width="240dp"
|
||||||
android:layout_height="80dp"
|
android:layout_height="80dp"
|
||||||
android:background="@drawable/bg_white_stroke_blue_ripple"
|
android:background="@drawable/bg_white_stroke_blue_ripple"
|
||||||
android:text="添加物品"
|
android:text="新增入库"
|
||||||
android:textColor="#FF0033CC"
|
android:textColor="#FF0033CC"
|
||||||
android:textSize="30sp"
|
android:textSize="30sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
android:visibility="gone"
|
android:visibility="visible"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/btnConfirm"
|
app:layout_constraintEnd_toStartOf="@+id/btnConfirm"
|
||||||
app:layout_constraintHorizontal_chainStyle="packed"
|
app:layout_constraintHorizontal_chainStyle="packed"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/dividerLine" />
|
app:layout_constraintTop_toTopOf="@id/dividerLine" />
|
||||||
|
|
||||||
<Button
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
android:id="@+id/btnConfirm"
|
android:id="@+id/btnConfirm"
|
||||||
android:layout_width="240dp"
|
android:layout_width="240dp"
|
||||||
android:layout_height="80dp"
|
android:layout_height="80dp"
|
||||||
@@ -136,9 +135,10 @@
|
|||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="30sp"
|
android:textSize="30sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
|
android:layout_marginStart="100dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toEndOf="@id/btnAddGoods"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/dividerLine" />
|
app:layout_constraintTop_toTopOf="@id/dividerLine" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
android:layout_width="1dp"
|
android:layout_width="1dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
app:layout_constraintGuide_percent="0.62" />
|
app:layout_constraintGuide_percent="0.70" />
|
||||||
|
|
||||||
<!-- 左侧:FlexboxLayoutManager 驱动的动态表单,两列自动换行 -->
|
<!-- 左侧:FlexboxLayoutManager 驱动的动态表单,两列自动换行 -->
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
@@ -58,6 +58,7 @@
|
|||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
android:layout_marginHorizontal="20dp"
|
||||||
app:layout_constraintStart_toEndOf="@id/guideline">
|
app:layout_constraintStart_toEndOf="@id/guideline">
|
||||||
|
|
||||||
<!-- 相机预览容器,由代码动态 inflate LayoutTakePhotoBinding -->
|
<!-- 相机预览容器,由代码动态 inflate LayoutTakePhotoBinding -->
|
||||||
@@ -70,7 +71,7 @@
|
|||||||
|
|
||||||
<!-- 秤重显示条 -->
|
<!-- 秤重显示条 -->
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_width="488dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="70dp"
|
android:layout_height="70dp"
|
||||||
android:layout_gravity="center_horizontal"
|
android:layout_gravity="center_horizontal"
|
||||||
android:background="@drawable/bg_gray_radius10">
|
android:background="@drawable/bg_gray_radius10">
|
||||||
@@ -125,9 +126,8 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingHorizontal="50dp">
|
android:paddingHorizontal="50dp">
|
||||||
|
|
||||||
<Button
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
android:id="@+id/btnCancel"
|
android:id="@+id/btnCancel"
|
||||||
style="?android:attr/buttonBarButtonStyle"
|
|
||||||
android:layout_width="240dp"
|
android:layout_width="240dp"
|
||||||
android:layout_height="80dp"
|
android:layout_height="80dp"
|
||||||
android:background="@drawable/bg_white_stroke_blue_ripple"
|
android:background="@drawable/bg_white_stroke_blue_ripple"
|
||||||
@@ -136,9 +136,8 @@
|
|||||||
android:textSize="30sp"
|
android:textSize="30sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
|
|
||||||
<Button
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
android:id="@+id/btnConfirm"
|
android:id="@+id/btnConfirm"
|
||||||
style="?android:attr/buttonBarButtonStyle"
|
|
||||||
android:layout_width="240dp"
|
android:layout_width="240dp"
|
||||||
android:layout_height="80dp"
|
android:layout_height="80dp"
|
||||||
android:layout_marginStart="30dp"
|
android:layout_marginStart="30dp"
|
||||||
|
|||||||
@@ -7,8 +7,10 @@
|
|||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- android:layout_width="488dp"-->
|
||||||
|
<!-- android:layout_height="325dp"-->
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_width="488dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="325dp"
|
android:layout_height="325dp"
|
||||||
android:background="@drawable/bg_white_radius10_stroke2_dash">
|
android:background="@drawable/bg_white_radius10_stroke2_dash">
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
android:layout_height="82dp"
|
android:layout_height="82dp"
|
||||||
android:layout_marginVertical="10dp"
|
android:layout_marginVertical="10dp"
|
||||||
android:layout_marginHorizontal="20dp"
|
android:layout_marginHorizontal="20dp"
|
||||||
tools:background="@drawable/bg_white_stroke_blue_ripple">
|
android:background="@drawable/bg_gray_radius10">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvGoodsName"
|
android:id="@+id/tvGoodsName"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
<style name="Theme.Inbound" parent="android:Theme.Material.Light.NoActionBar">
|
<style name="Theme.Inbound" parent="Theme.MaterialComponents.Light.NoActionBar">
|
||||||
<!-- <item name="android:windowBackground">@drawable/bg_splash</item>-->
|
<!-- <item name="android:windowBackground">@drawable/bg_splash</item>-->
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@@ -41,4 +41,5 @@
|
|||||||
<item name="windowNoTitle">true</item>
|
<item name="windowNoTitle">true</item>
|
||||||
<item name="windowActionBar">false</item>
|
<item name="windowActionBar">false</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user