feat(pack): 添加净菜包装功能和食材追溯界面
- 在activity_pack.xml中新增rvFormList RecyclerView用于表单展示 - 在TaskDetailActivity中实现食材明细的增删改查功能 - 添加InboundIngredientSearchDialog用于食材溯源码搜索 - 更新NetViewModelV2中addComboTask方法参数类型 - 添加NutCleanInboundIngredientVO数据模型用于已入库净菜食材 - 在PackActivity中实现包装表单动态加载和设备选择功能 - 添加用量计算和重量识别相关UI组件 - 优化FormFieldAdapter适配器去除Activity上下文依赖 - 新增formatDecimal扩展函数用于格式化用量字符串 - 实现TaskDetailAdapter中食材项的选中和清除逻辑 - 添加组合约束的API接口定义和数据传输对象修改 - 重构表单字段配置为动态加载模式支持多种输入类型 - 添加删除确认对话框提升用户体验和数据安全性 - 优化布局文件结构调整控件间距和显示效果 - 添加设备选项加载回调机制确保数据实时更新 - 实现重量监听器的生命周期管理防止内存泄漏 - 更新界面跳转逻辑支持餐品选择和详情展示 - 修复多个布局和代码中的空格及格式问题 - 添加必要的依赖导入和常量定义完善功能模块
This commit is contained in:
@@ -32,11 +32,9 @@ import kotlin.math.min
|
|||||||
* 动态表单字段 Adapter,配合 FlexboxLayoutManager 实现两列自动换行布局
|
* 动态表单字段 Adapter,配合 FlexboxLayoutManager 实现两列自动换行布局
|
||||||
* 单一 item 布局,通过 visibility 控制 TEXT/INTEGER/DECIMAL/FIXED/DROPDOWN/DATE_PICKER 六种类型渲染
|
* 单一 item 布局,通过 visibility 控制 TEXT/INTEGER/DECIMAL/FIXED/DROPDOWN/DATE_PICKER 六种类型渲染
|
||||||
*
|
*
|
||||||
* @param activityContext Activity context,用于创建 DatePickerDialog
|
|
||||||
* @param fields 表单字段列表(hidden=false 的字段,由外部过滤后传入)
|
* @param fields 表单字段列表(hidden=false 的字段,由外部过滤后传入)
|
||||||
*/
|
*/
|
||||||
class FormFieldAdapter(
|
class FormFieldAdapter(
|
||||||
private val activityContext: Context,
|
|
||||||
fields: MutableList<FormField>
|
fields: MutableList<FormField>
|
||||||
) : BaseQuickAdapter<FormField, FormFieldAdapter.VH>(fields) {
|
) : BaseQuickAdapter<FormField, FormFieldAdapter.VH>(fields) {
|
||||||
|
|
||||||
@@ -131,7 +129,7 @@ class FormFieldAdapter(
|
|||||||
v.hideKeyboard()
|
v.hideKeyboard()
|
||||||
val popHeight = min(item.options.size.coerceAtLeast(1), 4) * 71.dp
|
val popHeight = min(item.options.size.coerceAtLeast(1), 4) * 71.dp
|
||||||
DropdownPopup(
|
DropdownPopup(
|
||||||
context = activityContext,
|
context = context,
|
||||||
list = item.options.toMutableList(),
|
list = item.options.toMutableList(),
|
||||||
popWidth = v.width,
|
popWidth = v.width,
|
||||||
popHeight = popHeight
|
popHeight = popHeight
|
||||||
@@ -162,7 +160,7 @@ class FormFieldAdapter(
|
|||||||
v.hideKeyboard()
|
v.hideKeyboard()
|
||||||
val cal = Calendar.getInstance()
|
val cal = Calendar.getInstance()
|
||||||
DatePickerDialog(
|
DatePickerDialog(
|
||||||
activityContext,
|
context,
|
||||||
{ _, year, month, dayOfMonth ->
|
{ _, year, month, dayOfMonth ->
|
||||||
val selected = Calendar.getInstance().apply {
|
val selected = Calendar.getInstance().apply {
|
||||||
set(year, month, dayOfMonth, 0, 0, 0)
|
set(year, month, dayOfMonth, 0, 0, 0)
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.shuwei.dish.match.adapter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
import com.shuwei.dish.match.R
|
||||||
|
import com.shuwei.dish.match.databinding.ListItemInboundIngredientBinding
|
||||||
|
import com.shuwei.dish.match.model.NutCleanInboundIngredientVO
|
||||||
|
import com.shuwei.dish.match.utils.ext.formatDecimal
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已入库净菜食材列表适配器
|
||||||
|
*/
|
||||||
|
class InboundIngredientAdapter(list: MutableList<NutCleanInboundIngredientVO>) :
|
||||||
|
BaseQuickAdapter<NutCleanInboundIngredientVO, InboundIngredientAdapter.VH>(list) {
|
||||||
|
|
||||||
|
inner class VH(var binding: ListItemInboundIngredientBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||||
|
val binding = ListItemInboundIngredientBinding.inflate(
|
||||||
|
LayoutInflater.from(context), parent, false
|
||||||
|
)
|
||||||
|
return VH(binding)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: VH, position: Int, item: NutCleanInboundIngredientVO?) {
|
||||||
|
item ?: return
|
||||||
|
holder.binding.run {
|
||||||
|
tvIngredientName.text = item.ingredientName ?: "-"
|
||||||
|
|
||||||
|
val traceCode = item.traceCode.takeUnless { it.isNullOrBlank() } ?: "-"
|
||||||
|
tvTraceCode.text = "溯源码:$traceCode"
|
||||||
|
|
||||||
|
val stock = item.currentStock.takeUnless { it.isNullOrBlank() } ?: "0"
|
||||||
|
tvStock.text = "库存:${stock.formatDecimal()}kg"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,47 +1,50 @@
|
|||||||
package com.shuwei.dish.match.adapter
|
package com.shuwei.dish.match.adapter
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.res.ColorStateList
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.graphics.toColorInt
|
||||||
import com.chad.library.adapter4.BaseQuickAdapter
|
import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
import com.shuwei.dish.match.databinding.ListItemTaskDetailBinding
|
import com.shuwei.dish.match.databinding.ListItemTaskDetailBinding
|
||||||
import com.shuwei.dish.match.model.NutComboTaskItemDetail
|
import com.shuwei.dish.match.model.NutComboTaskItemDetail
|
||||||
|
import com.shuwei.dish.match.utils.ext.formatDecimal
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 组配任务详情食材列表适配器
|
* 组配任务详情食材列表适配器
|
||||||
|
* Adapter for displaying ingredient list in task details
|
||||||
*/
|
*/
|
||||||
class TaskDetailAdapter(list: MutableList<NutComboTaskItemDetail>) :
|
class TaskDetailAdapter(list: MutableList<NutComboTaskItemDetail>) :
|
||||||
BaseQuickAdapter<NutComboTaskItemDetail, TaskDetailAdapter.VH>(list) {
|
BaseQuickAdapter<NutComboTaskItemDetail, TaskDetailAdapter.VH>(list) {
|
||||||
|
|
||||||
|
// ViewHolder class for holding the view bindings
|
||||||
inner class VH(var binding: ListItemTaskDetailBinding) : QuickViewHolder(binding.root)
|
inner class VH(var binding: ListItemTaskDetailBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 格式化用量字符串,去掉小数点后末尾的0
|
* Called by RecyclerView to display the item at the specified position.
|
||||||
|
* This method updates the ViewHolder's contents with the item's data.
|
||||||
|
*
|
||||||
|
* @param holder The ViewHolder to be updated
|
||||||
|
* @param position The position of the item in the adapter
|
||||||
|
* @param item The NutComboTaskItemDetail to be displayed
|
||||||
*/
|
*/
|
||||||
private fun formatQty(value: String?): String {
|
|
||||||
if (value.isNullOrBlank()) return "0"
|
|
||||||
return try {
|
|
||||||
BigDecimal(value).stripTrailingZeros().toPlainString()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(
|
override fun onBindViewHolder(
|
||||||
holder: VH,
|
holder: VH,
|
||||||
position: Int,
|
position: Int,
|
||||||
item: NutComboTaskItemDetail?
|
item: NutComboTaskItemDetail?
|
||||||
) {
|
) {
|
||||||
|
item?:return
|
||||||
holder.binding.apply {
|
holder.binding.apply {
|
||||||
tvIngredientName.text = item?.ingredientName
|
// Set ingredient name
|
||||||
|
tvIngredientName.text = item.ingredientName
|
||||||
|
|
||||||
// 食材类别
|
// 食材类别
|
||||||
val classText = when (item?.ingredientClass) {
|
val classText = when (item.ingredientClass) {
|
||||||
1 -> "主材"
|
1 -> "主材"
|
||||||
2 -> "辅材"
|
2 -> "辅材"
|
||||||
3 -> "调料"
|
3 -> "调料"
|
||||||
@@ -49,16 +52,32 @@ class TaskDetailAdapter(list: MutableList<NutComboTaskItemDetail>) :
|
|||||||
}
|
}
|
||||||
tvIngredientClass.text = classText
|
tvIngredientClass.text = classText
|
||||||
|
|
||||||
val unit = item?.unit ?: "g"
|
val unit = item.unit ?: "g"
|
||||||
tvPerPortionQty.text = "每份用量:${formatQty(item?.perPortionQty)}${unit}"
|
tvPerPortionQty.text = "每份用量:${item.perPortionQty.formatDecimal()}${unit}"
|
||||||
tvActualQty.text = "实际用量:${formatQty(item?.actualQty)}${unit}"
|
tvActualQty.run {
|
||||||
tvTotalQty.text = "合计用量:${formatQty(item?.totalQty)}${unit}"
|
if (item.actualQty.isNullOrBlank()) {
|
||||||
|
setTextColor("#999999".toColorInt())
|
||||||
|
text = "-"
|
||||||
|
} else {
|
||||||
|
setTextColor("#00BC71".toColorInt())
|
||||||
|
text = item.actualQty.formatDecimal() + unit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// tvTotalQty.text = "合计用量:${item?.totalQty.formatDecimal()}${unit}"
|
||||||
|
|
||||||
tvTraceCode.visible()
|
tvTraceCode.visible()
|
||||||
tvTraceCode.text = "溯源码:${(item?.traceCode ?:"").ifBlank { "-" }}"
|
tvTraceCode.text = "溯源码:${(item.traceCode ?:"").ifBlank { "-" }}"
|
||||||
|
|
||||||
|
// val hasWeight = item.actualQty.isNullOrBlank().not()
|
||||||
|
// ivClearIcon.imageTintList = if (hasWeight) null else ColorStateList.valueOf("#BFBFBF".toColorInt())
|
||||||
|
|
||||||
|
ivOperateIcon.setImageResource(
|
||||||
|
if (item.isSetFinished == true) R.drawable.ic_dish_selected
|
||||||
|
else R.drawable.ic_dish_unselected
|
||||||
|
)
|
||||||
|
|
||||||
root.setBackgroundResource(
|
root.setBackgroundResource(
|
||||||
if (item?.isClicked == true) R.drawable.shape_item_cook_dish
|
if (item.isClicked == true) R.drawable.shape_item_cook_dish
|
||||||
else R.drawable.shape_white_fb_15_corners
|
else R.drawable.shape_white_fb_15_corners
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,214 @@
|
|||||||
|
package com.shuwei.dish.match.dialog
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
|
import android.graphics.Rect
|
||||||
|
import android.text.Editable
|
||||||
|
import android.view.KeyboardShortcutGroup
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import android.view.View
|
||||||
|
import android.view.Window
|
||||||
|
import android.widget.FrameLayout
|
||||||
|
import androidx.core.widget.addTextChangedListener
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.chad.library.adapter4.util.setOnDebouncedItemClick
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import com.shuwei.dish.match.R
|
||||||
|
import com.shuwei.dish.match.adapter.InboundIngredientAdapter
|
||||||
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
|
import com.shuwei.dish.match.databinding.DialogInboundIngredientSearchBinding
|
||||||
|
import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding
|
||||||
|
import com.shuwei.dish.match.model.NutCleanInboundIngredientVO
|
||||||
|
import com.shuwei.dish.match.net.NetViewModelV2
|
||||||
|
import com.shuwei.dish.match.net.UiState
|
||||||
|
import com.shuwei.dish.match.utils.KeyboardUtil
|
||||||
|
import com.shuwei.dish.match.utils.ext.addOnActionSearchListener
|
||||||
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已入库净菜食材搜索弹窗
|
||||||
|
* @param activity 宿主 Activity
|
||||||
|
* @param defIngredientName 默认填充的食材名称(可选)
|
||||||
|
* @param onItemSelected 用户点击某项食材时的回调
|
||||||
|
*/
|
||||||
|
class InboundIngredientSearchDialog(
|
||||||
|
private val activity: BaseActivity,
|
||||||
|
private val viewModelV2: NetViewModelV2,
|
||||||
|
private val defIngredientName: String? = null,
|
||||||
|
private val onItemSelected: (item: NutCleanInboundIngredientVO) -> Unit
|
||||||
|
) : BottomSheetDialog(activity, R.style.BottomSheet) {
|
||||||
|
|
||||||
|
private val binding = DialogInboundIngredientSearchBinding.inflate(LayoutInflater.from(activity))
|
||||||
|
private val list = mutableListOf<NutCleanInboundIngredientVO>()
|
||||||
|
private val adapter = InboundIngredientAdapter(list).apply {
|
||||||
|
isStateViewEnable = true
|
||||||
|
setOnDebouncedItemClick { _, _, position ->
|
||||||
|
val item = list.getOrNull(position) ?: return@setOnDebouncedItemClick
|
||||||
|
onItemSelected(item)
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var keyword: String? = null
|
||||||
|
|
||||||
|
init {
|
||||||
|
setContentView(binding.root)
|
||||||
|
setCancelable(true)
|
||||||
|
behavior.skipCollapsed = false
|
||||||
|
setOnDismissListener { activity.hideStatusBar() }
|
||||||
|
|
||||||
|
binding.tvSheetName.text = "已入库净菜检索"
|
||||||
|
|
||||||
|
// 输入框:清空时重置列表
|
||||||
|
binding.etSheetInput.run {
|
||||||
|
hint = "输入食材名称"
|
||||||
|
addTextChangedListener(
|
||||||
|
onTextChanged = { text, _, _, _ -> keyword = text.toString() },
|
||||||
|
afterTextChanged = { it: Editable? ->
|
||||||
|
if (it.isNullOrBlank()) {
|
||||||
|
list.clear()
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
addOnActionSearchListener { searchIngredient(this) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecyclerView 初始化
|
||||||
|
binding.recyclerView.run {
|
||||||
|
layoutManager = GridLayoutManager(activity, 2, GridLayoutManager.VERTICAL, false)
|
||||||
|
adapter = this@InboundIngredientSearchDialog.adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.refreshLayout.run {
|
||||||
|
setEnableRefresh(true)
|
||||||
|
setEnableLoadMore(false)
|
||||||
|
setOnRefreshListener { getIngredientList() }
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.ivSearch.setOnClickListener { searchIngredient(it) }
|
||||||
|
binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it) }
|
||||||
|
|
||||||
|
// 若有默认食材名称,自动填充并触发搜索
|
||||||
|
if (!defIngredientName.isNullOrBlank()) {
|
||||||
|
binding.etSheetInput.setText(defIngredientName)
|
||||||
|
getIngredientList()
|
||||||
|
KeyboardUtil.hideKeyboard(binding.root)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 弹窗显示时在 Window.Callback 层提前拦截触摸,解决 BottomSheet 拖拽与列表滑动的手势冲突 */
|
||||||
|
override fun show() {
|
||||||
|
super.show()
|
||||||
|
val originalCallback = window?.callback ?: return
|
||||||
|
window?.callback = object : Window.Callback by originalCallback {
|
||||||
|
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
||||||
|
when (event.actionMasked) {
|
||||||
|
MotionEvent.ACTION_DOWN -> {
|
||||||
|
val rect = Rect()
|
||||||
|
binding.refreshLayout.getGlobalVisibleRect(rect)
|
||||||
|
behavior.isDraggable = !rect.contains(event.rawX.toInt(), event.rawY.toInt())
|
||||||
|
}
|
||||||
|
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
||||||
|
behavior.isDraggable = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return originalCallback.dispatchTouchEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPointerCaptureChanged(hasCapture: Boolean) {
|
||||||
|
originalCallback.onPointerCaptureChanged(hasCapture)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onProvideKeyboardShortcuts(
|
||||||
|
data: List<KeyboardShortcutGroup?>?,
|
||||||
|
menu: Menu?,
|
||||||
|
deviceId: Int
|
||||||
|
) {
|
||||||
|
originalCallback.onProvideKeyboardShortcuts(data, menu, deviceId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发搜索:校验输入、隐藏键盘、发起请求
|
||||||
|
*/
|
||||||
|
private fun searchIngredient(v: View) {
|
||||||
|
if (keyword.isNullOrBlank()) {
|
||||||
|
activity.toast("请输入食材名称")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
getIngredientList()
|
||||||
|
KeyboardUtil.hideKeyboard(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求食材列表,使用回调方式发起
|
||||||
|
*/
|
||||||
|
private fun getIngredientList() {
|
||||||
|
viewModelV2.getInboundIngredientOptionsWithCallback(
|
||||||
|
keyword = keyword.takeUnless { it.isNullOrBlank() },
|
||||||
|
onLoading = {},
|
||||||
|
onResult = { state ->
|
||||||
|
when (state) {
|
||||||
|
is UiState.Success -> loadIngredientList(state.data)
|
||||||
|
is UiState.Error -> {
|
||||||
|
activity.toast(state.msg)
|
||||||
|
binding.refreshLayout.finishRefresh()
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将返回数据填充到列表
|
||||||
|
*/
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private fun loadIngredientList(records: List<NutCleanInboundIngredientVO>?) {
|
||||||
|
binding.refreshLayout.finishRefresh()
|
||||||
|
if (records.isNullOrEmpty()) {
|
||||||
|
loadEmptyView()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
binding.recyclerView.layoutManager = GridLayoutManager(activity, 2, GridLayoutManager.VERTICAL, false)
|
||||||
|
list.clear()
|
||||||
|
list.addAll(records)
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
}
|
||||||
|
|
||||||
|
private var emptyViewBinding: LayoutEmptyViewBinding? = null
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private fun loadEmptyView() {
|
||||||
|
try {
|
||||||
|
list.clear()
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
if (emptyViewBinding == null) {
|
||||||
|
emptyViewBinding = LayoutEmptyViewBinding.inflate(
|
||||||
|
LayoutInflater.from(activity),
|
||||||
|
binding.recyclerView,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
emptyViewBinding?.let {
|
||||||
|
it.tvContent.text = "暂无数据"
|
||||||
|
it.tvSubContent.text = "未查询到已入库净菜信息"
|
||||||
|
it.root.layoutParams = FrameLayout.LayoutParams(
|
||||||
|
FrameLayout.LayoutParams.MATCH_PARENT,
|
||||||
|
FrameLayout.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
binding.recyclerView.layoutManager = LinearLayoutManager(activity, LinearLayoutManager.VERTICAL, false)
|
||||||
|
binding.recyclerView.post {
|
||||||
|
it.root.minimumHeight = binding.recyclerView.height
|
||||||
|
adapter.stateView = it.root
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -207,18 +207,18 @@ data class NutComboTaskVO(
|
|||||||
*/
|
*/
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class NutComboTaskDetailVO(
|
data class NutComboTaskDetailVO(
|
||||||
val id: Long?,
|
var id: Long? = null,
|
||||||
val taskNo: String?,
|
var taskNo: String? = null,
|
||||||
val planDate: String?,
|
var planDate: String? = null,
|
||||||
val canteenId: Long?,
|
var canteenId: Long? = null,
|
||||||
val mealType: Int?,
|
var mealType: Int? = null,
|
||||||
val foodId: Long?,
|
var foodId: Long? = null,
|
||||||
val targetDish: String?,
|
var targetDish: String? = null,
|
||||||
val spec: String?,
|
var spec: String? = null,
|
||||||
val portions: Int?,
|
var portions: Int? = null,
|
||||||
val comboStatus: Int?,
|
var comboStatus: Int? = null,
|
||||||
val ownerName: String?,
|
var ownerName: String? = null,
|
||||||
val items: List<NutComboTaskItemDetail>?
|
var items: List<NutComboTaskItemDetail>? = null,
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -232,10 +232,23 @@ data class NutComboTaskItemDetail(
|
|||||||
val ingredientClass: Int?,
|
val ingredientClass: Int?,
|
||||||
var traceCode: String?,
|
var traceCode: String?,
|
||||||
val perPortionQty: String?,
|
val perPortionQty: String?,
|
||||||
val actualQty: String?,
|
var actualQty: String?,
|
||||||
val totalQty: String?,
|
val totalQty: String?,
|
||||||
val unit: String?,
|
val unit: String?,
|
||||||
var isClicked: Boolean? = false,
|
var isClicked: Boolean? = false,
|
||||||
|
var isSetFinished: Boolean? = false,
|
||||||
|
) : Parcelable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已入库净菜食材VO - 按食材名称查询已入库有库存的净菜记录
|
||||||
|
*/
|
||||||
|
@Parcelize
|
||||||
|
data class NutCleanInboundIngredientVO(
|
||||||
|
val id: Long?,
|
||||||
|
val materId: Long?,
|
||||||
|
val ingredientName: String?,
|
||||||
|
val traceCode: String?,
|
||||||
|
val currentStock: String?
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import com.shuwei.dish.match.model.NutSupHygieneIngredientOptionVO
|
|||||||
import com.shuwei.dish.match.model.NutProdComboVideoVO
|
import com.shuwei.dish.match.model.NutProdComboVideoVO
|
||||||
import com.shuwei.dish.match.model.NutProdComboTaskDTO
|
import com.shuwei.dish.match.model.NutProdComboTaskDTO
|
||||||
import com.shuwei.dish.match.model.IdDTO
|
import com.shuwei.dish.match.model.IdDTO
|
||||||
|
import com.shuwei.dish.match.model.NutCleanInboundIngredientVO
|
||||||
import com.shuwei.dish.match.model.NutComboTaskDetailVO
|
import com.shuwei.dish.match.model.NutComboTaskDetailVO
|
||||||
import com.shuwei.dish.match.model.NutComboTaskVO
|
import com.shuwei.dish.match.model.NutComboTaskVO
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
@@ -77,6 +78,15 @@ interface ApiServiceV2 {
|
|||||||
@Query("traceCode") traceCode: String
|
@Query("traceCode") traceCode: String
|
||||||
): ApiResponse<List<NutSupHygieneIngredientOptionVO>>
|
): ApiResponse<List<NutSupHygieneIngredientOptionVO>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按食材名称查询已入库有库存的净菜记录
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
suspend fun getInboundIngredientOptions(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/nutrition/neglect/inbound-ingredient-options",
|
||||||
|
@Query("keyword") keyword: String? = null
|
||||||
|
): ApiResponse<List<NutCleanInboundIngredientVO>>
|
||||||
|
|
||||||
// ========== 二、净菜组配接口 ==========
|
// ========== 二、净菜组配接口 ==========
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -85,7 +95,7 @@ interface ApiServiceV2 {
|
|||||||
@POST
|
@POST
|
||||||
suspend fun addComboTask(
|
suspend fun addComboTask(
|
||||||
@Url url: String = "${GlobalData.appBaseUrl}/nutrition/neglect/combo-task/add",
|
@Url url: String = "${GlobalData.appBaseUrl}/nutrition/neglect/combo-task/add",
|
||||||
@Body param: NutProdComboTaskDTO
|
@Body param: NutComboTaskDetailVO
|
||||||
): ApiResponse<Unit>
|
): ApiResponse<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package com.shuwei.dish.match.net
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.shuwei.dish.match.model.NutCanteenVO
|
import com.shuwei.dish.match.model.NutCanteenVO
|
||||||
|
import com.shuwei.dish.match.model.NutCleanInboundIngredientVO
|
||||||
import com.shuwei.dish.match.model.NutComboTaskDetailVO
|
import com.shuwei.dish.match.model.NutComboTaskDetailVO
|
||||||
import com.shuwei.dish.match.model.NutComboTaskVO
|
import com.shuwei.dish.match.model.NutComboTaskVO
|
||||||
import com.shuwei.dish.match.model.NutDictItemVO
|
import com.shuwei.dish.match.model.NutDictItemVO
|
||||||
@@ -28,7 +29,8 @@ class NetViewModelV2(
|
|||||||
|
|
||||||
// 食堂下拉列表
|
// 食堂下拉列表
|
||||||
private val _canteenOptionsState = MutableStateFlow<UiState<List<NutCanteenVO>?>>(UiState.Idle)
|
private val _canteenOptionsState = MutableStateFlow<UiState<List<NutCanteenVO>?>>(UiState.Idle)
|
||||||
val canteenOptionsState: StateFlow<UiState<List<NutCanteenVO>?>> = _canteenOptionsState.asStateFlow()
|
val canteenOptionsState: StateFlow<UiState<List<NutCanteenVO>?>> =
|
||||||
|
_canteenOptionsState.asStateFlow()
|
||||||
|
|
||||||
fun getCanteenOptions(keyword: String? = null) {
|
fun getCanteenOptions(keyword: String? = null) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@@ -49,8 +51,10 @@ class NetViewModelV2(
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// 食材下拉列表
|
// 食材下拉列表
|
||||||
private val _materOptionsState = MutableStateFlow<UiState<List<NutMaterOptionVO>?>>(UiState.Idle)
|
private val _materOptionsState =
|
||||||
val materOptionsState: StateFlow<UiState<List<NutMaterOptionVO>?>> = _materOptionsState.asStateFlow()
|
MutableStateFlow<UiState<List<NutMaterOptionVO>?>>(UiState.Idle)
|
||||||
|
val materOptionsState: StateFlow<UiState<List<NutMaterOptionVO>?>> =
|
||||||
|
_materOptionsState.asStateFlow()
|
||||||
|
|
||||||
fun getMaterOptions(keyword: String? = null) {
|
fun getMaterOptions(keyword: String? = null) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@@ -60,8 +64,10 @@ class NetViewModelV2(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 包装设备下拉
|
// 包装设备下拉
|
||||||
private val _deviceOptionsState = MutableStateFlow<UiState<List<NutSupPkgDeviceVO>?>>(UiState.Idle)
|
private val _deviceOptionsState =
|
||||||
val deviceOptionsState: StateFlow<UiState<List<NutSupPkgDeviceVO>?>> = _deviceOptionsState.asStateFlow()
|
MutableStateFlow<UiState<List<NutSupPkgDeviceVO>?>>(UiState.Idle)
|
||||||
|
val deviceOptionsState: StateFlow<UiState<List<NutSupPkgDeviceVO>?>> =
|
||||||
|
_deviceOptionsState.asStateFlow()
|
||||||
|
|
||||||
fun getDeviceOptions() {
|
fun getDeviceOptions() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@@ -72,7 +78,8 @@ class NetViewModelV2(
|
|||||||
|
|
||||||
// 餐品下拉搜索
|
// 餐品下拉搜索
|
||||||
private val _foodOptionsState = MutableStateFlow<UiState<Page<NutFoodOptionVO>?>>(UiState.Idle)
|
private val _foodOptionsState = MutableStateFlow<UiState<Page<NutFoodOptionVO>?>>(UiState.Idle)
|
||||||
val foodOptionsState: StateFlow<UiState<Page<NutFoodOptionVO>?>> = _foodOptionsState.asStateFlow()
|
val foodOptionsState: StateFlow<UiState<Page<NutFoodOptionVO>?>> =
|
||||||
|
_foodOptionsState.asStateFlow()
|
||||||
|
|
||||||
// fun getFoodOptions(keyword: String? = null, pageNum: Int = 1, pageSize: Int = 10) {
|
// fun getFoodOptions(keyword: String? = null, pageNum: Int = 1, pageSize: Int = 10) {
|
||||||
// viewModelScope.launch {
|
// viewModelScope.launch {
|
||||||
@@ -125,8 +132,10 @@ class NetViewModelV2(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 按溯源码查食材信息
|
// 按溯源码查食材信息
|
||||||
private val _ingredientByTraceState = MutableStateFlow<UiState<List<NutSupHygieneIngredientOptionVO>?>>(UiState.Idle)
|
private val _ingredientByTraceState =
|
||||||
val ingredientByTraceState: StateFlow<UiState<List<NutSupHygieneIngredientOptionVO>?>> = _ingredientByTraceState.asStateFlow()
|
MutableStateFlow<UiState<List<NutSupHygieneIngredientOptionVO>?>>(UiState.Idle)
|
||||||
|
val ingredientByTraceState: StateFlow<UiState<List<NutSupHygieneIngredientOptionVO>?>> =
|
||||||
|
_ingredientByTraceState.asStateFlow()
|
||||||
|
|
||||||
fun getIngredientByTrace(traceCode: String) {
|
fun getIngredientByTrace(traceCode: String) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@@ -141,12 +150,29 @@ class NetViewModelV2(
|
|||||||
private val _addComboTaskState = MutableStateFlow<UiState<Unit?>>(UiState.Idle)
|
private val _addComboTaskState = MutableStateFlow<UiState<Unit?>>(UiState.Idle)
|
||||||
val addComboTaskState: StateFlow<UiState<Unit?>> = _addComboTaskState.asStateFlow()
|
val addComboTaskState: StateFlow<UiState<Unit?>> = _addComboTaskState.asStateFlow()
|
||||||
|
|
||||||
fun addComboTask(param: NutProdComboTaskDTO) {
|
fun addComboTask(param: NutComboTaskDetailVO, block: (Boolean, String) -> Unit) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
_addComboTaskState.value = UiState.Loading
|
val uiState = repository.addComboTask(param)
|
||||||
_addComboTaskState.value = repository.addComboTask(param)
|
when (uiState) {
|
||||||
|
is UiState.Success -> {
|
||||||
|
block(true, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
is UiState.Error -> {
|
||||||
|
block(false, uiState.msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
is UiState.Loading -> {}
|
||||||
|
UiState.Idle -> {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// fun addComboTask(param: NutProdComboTaskDTO) {
|
||||||
|
// viewModelScope.launch {
|
||||||
|
// _addComboTaskState.value = UiState.Loading
|
||||||
|
// _addComboTaskState.value = repository.addComboTask(param)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// 开始组配
|
// 开始组配
|
||||||
private val _startComboTaskState = MutableStateFlow<UiState<Unit?>>(UiState.Idle)
|
private val _startComboTaskState = MutableStateFlow<UiState<Unit?>>(UiState.Idle)
|
||||||
@@ -172,7 +198,8 @@ class NetViewModelV2(
|
|||||||
|
|
||||||
// 获取组配任务视频监控地址
|
// 获取组配任务视频监控地址
|
||||||
private val _comboTaskVideoState = MutableStateFlow<UiState<NutProdComboVideoVO?>>(UiState.Idle)
|
private val _comboTaskVideoState = MutableStateFlow<UiState<NutProdComboVideoVO?>>(UiState.Idle)
|
||||||
val comboTaskVideoState: StateFlow<UiState<NutProdComboVideoVO?>> = _comboTaskVideoState.asStateFlow()
|
val comboTaskVideoState: StateFlow<UiState<NutProdComboVideoVO?>> =
|
||||||
|
_comboTaskVideoState.asStateFlow()
|
||||||
|
|
||||||
fun getComboTaskVideo(taskNo: String) {
|
fun getComboTaskVideo(taskNo: String) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@@ -220,7 +247,14 @@ class NetViewModelV2(
|
|||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
onLoading()
|
onLoading()
|
||||||
onResult(repository.getIncompleteComboTasks(deviceCode = deviceCode, keyword = keyword, pageNum = pageNum, pageSize = pageSize))
|
onResult(
|
||||||
|
repository.getIncompleteComboTasks(
|
||||||
|
deviceCode = deviceCode,
|
||||||
|
keyword = keyword,
|
||||||
|
pageNum = pageNum,
|
||||||
|
pageSize = pageSize
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,4 +272,20 @@ class NetViewModelV2(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========== 已入库净菜食材接口 ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按食材名称查询已入库有库存的净菜记录(回调版本)
|
||||||
|
*/
|
||||||
|
fun getInboundIngredientOptionsWithCallback(
|
||||||
|
keyword: String? = null,
|
||||||
|
onLoading: () -> Unit = {},
|
||||||
|
onResult: (UiState<List<NutCleanInboundIngredientVO>?>) -> Unit
|
||||||
|
) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
onLoading()
|
||||||
|
onResult(repository.getInboundIngredientOptions(keyword))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.shuwei.dish.match.net
|
|||||||
|
|
||||||
import com.shuwei.dish.match.model.IdDTO
|
import com.shuwei.dish.match.model.IdDTO
|
||||||
import com.shuwei.dish.match.model.NutCanteenVO
|
import com.shuwei.dish.match.model.NutCanteenVO
|
||||||
|
import com.shuwei.dish.match.model.NutCleanInboundIngredientVO
|
||||||
import com.shuwei.dish.match.model.NutComboTaskDetailVO
|
import com.shuwei.dish.match.model.NutComboTaskDetailVO
|
||||||
import com.shuwei.dish.match.model.NutComboTaskVO
|
import com.shuwei.dish.match.model.NutComboTaskVO
|
||||||
import com.shuwei.dish.match.model.NutDictItemVO
|
import com.shuwei.dish.match.model.NutDictItemVO
|
||||||
@@ -65,9 +66,12 @@ class RemoteRepositoryV2 {
|
|||||||
suspend fun getIngredientByTrace(traceCode: String): UiState<List<NutSupHygieneIngredientOptionVO>?> =
|
suspend fun getIngredientByTrace(traceCode: String): UiState<List<NutSupHygieneIngredientOptionVO>?> =
|
||||||
safeApiCall { apiService.getIngredientByTrace(traceCode = traceCode) }
|
safeApiCall { apiService.getIngredientByTrace(traceCode = traceCode) }
|
||||||
|
|
||||||
|
suspend fun getInboundIngredientOptions(keyword: String? = null): UiState<List<NutCleanInboundIngredientVO>?> =
|
||||||
|
safeApiCall { apiService.getInboundIngredientOptions(keyword = keyword) }
|
||||||
|
|
||||||
// ========== 净菜组配接口 ==========
|
// ========== 净菜组配接口 ==========
|
||||||
|
|
||||||
suspend fun addComboTask(param: NutProdComboTaskDTO): UiState<Unit?> =
|
suspend fun addComboTask(param: NutComboTaskDetailVO): UiState<Unit?> =
|
||||||
safeApiCall { apiService.addComboTask(param = param) }
|
safeApiCall { apiService.addComboTask(param = param) }
|
||||||
|
|
||||||
suspend fun startComboTask(id: Long): UiState<Unit?> =
|
suspend fun startComboTask(id: Long): UiState<Unit?> =
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class CleanPackActivity : BaseActivity() {
|
|||||||
|
|
||||||
private lateinit var binding: ActivityCleanPackBinding
|
private lateinit var binding: ActivityCleanPackBinding
|
||||||
private val fields = mutableListOf<FormField>()
|
private val fields = mutableListOf<FormField>()
|
||||||
private val formAdapter by lazy { FormFieldAdapter(this, fields) }
|
private val formAdapter by lazy { FormFieldAdapter(fields) }
|
||||||
private val viewModelV2 by lazy { NetViewModelV2() }
|
private val viewModelV2 by lazy { NetViewModelV2() }
|
||||||
private var packType: Int = TYPE_CLEAN
|
private var packType: Int = TYPE_CLEAN
|
||||||
|
|
||||||
@@ -241,17 +241,13 @@ class CleanPackActivity : BaseActivity() {
|
|||||||
fields.add(packagingSpecField!!)
|
fields.add(packagingSpecField!!)
|
||||||
|
|
||||||
// 包装方式(下拉)
|
// 包装方式(下拉)
|
||||||
fields.add(
|
packageMethodField =
|
||||||
FormField(
|
FormField(
|
||||||
label = "包装方式", type = FieldType.DROPDOWN,
|
label = "包装方式", type = FieldType.DROPDOWN,
|
||||||
extraApiKeys = mapOf("packageMethodId" to "id", "packageMethod" to "value"),
|
extraApiKeys = mapOf("packageMethodId" to "id", "packageMethod" to "value"),
|
||||||
required = true,
|
required = true
|
||||||
options = mutableListOf(
|
|
||||||
DictType(id = "1", value = "真空包装", type = "真空包装"),
|
|
||||||
DictType(id = "2", value = "气调包装", type = "气调包装"),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
fields.add(packageMethodField!!)
|
||||||
|
|
||||||
// 包装份数
|
// 包装份数
|
||||||
fields.add(
|
fields.add(
|
||||||
@@ -277,14 +273,15 @@ class CleanPackActivity : BaseActivity() {
|
|||||||
required = true
|
required = true
|
||||||
),
|
),
|
||||||
FormField(
|
FormField(
|
||||||
label = "分类", type = FieldType.DROPDOWN,
|
label = "分类", type = FieldType.FIXED,
|
||||||
extraApiKeys = mapOf("classify" to "value"),
|
// extraApiKeys = mapOf("classify" to "value"),
|
||||||
|
apiKey = "classify",
|
||||||
required = true,
|
required = true,
|
||||||
options = mutableListOf(
|
// options = mutableListOf(
|
||||||
DictType(id = "1", value = "蔬菜类", type = "蔬菜类"),
|
// DictType(id = "1", value = "蔬菜类", type = "蔬菜类"),
|
||||||
DictType(id = "2", value = "肉禽类", type = "肉禽类"),
|
// DictType(id = "2", value = "肉禽类", type = "肉禽类"),
|
||||||
DictType(id = "3", value = "水产类", type = "水产类"),
|
// DictType(id = "3", value = "水产类", type = "水产类"),
|
||||||
)
|
// )
|
||||||
),
|
),
|
||||||
FormField(
|
FormField(
|
||||||
label = "每份用量",
|
label = "每份用量",
|
||||||
@@ -401,6 +398,7 @@ class CleanPackActivity : BaseActivity() {
|
|||||||
|
|
||||||
// 加载下拉选项
|
// 加载下拉选项
|
||||||
loadFoodOptionsWithKeyword()
|
loadFoodOptionsWithKeyword()
|
||||||
|
loadDictItemsWithCallback("sup_package_method", packageMethodField!!)
|
||||||
loadDictItemsWithCallback("sup_package_spec", packagingSpecField!!)
|
loadDictItemsWithCallback("sup_package_spec", packagingSpecField!!)
|
||||||
loadDeviceOptionsWithCallback(deviceField)
|
loadDeviceOptionsWithCallback(deviceField)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,17 +10,23 @@ import android.view.ViewGroup
|
|||||||
import androidx.activity.addCallback
|
import androidx.activity.addCallback
|
||||||
import androidx.core.content.IntentCompat
|
import androidx.core.content.IntentCompat
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
import com.shuwei.dish.match.adapter.FoodMaterialAdapter
|
import com.shuwei.dish.match.adapter.FoodMaterialAdapter
|
||||||
|
import com.shuwei.dish.match.adapter.FormFieldAdapter
|
||||||
import com.shuwei.dish.match.base.BaseActivity
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
import com.shuwei.dish.match.databinding.ActivityPackBinding
|
import com.shuwei.dish.match.databinding.ActivityPackBinding
|
||||||
import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding
|
import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding
|
||||||
import com.shuwei.dish.match.dialog.CommonDialog
|
import com.shuwei.dish.match.dialog.CommonDialog
|
||||||
import com.shuwei.dish.match.model.CookFoodDTO
|
import com.shuwei.dish.match.model.CookFoodDTO
|
||||||
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
|
import com.shuwei.dish.match.dialog.InboundIngredientSearchDialog
|
||||||
|
import com.shuwei.dish.match.model.DictType
|
||||||
|
import com.shuwei.dish.match.model.FieldType
|
||||||
import com.shuwei.dish.match.model.FoodRecord
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
|
import com.shuwei.dish.match.model.FormField
|
||||||
import com.shuwei.dish.match.model.GoodsItem
|
import com.shuwei.dish.match.model.GoodsItem
|
||||||
import com.shuwei.dish.match.model.NutFoodOptionVO
|
import com.shuwei.dish.match.model.NutFoodOptionVO
|
||||||
import com.shuwei.dish.match.net.UiState
|
import com.shuwei.dish.match.net.UiState
|
||||||
@@ -127,6 +133,7 @@ class PackActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var currentWeight = 0.0
|
private var currentWeight = 0.0
|
||||||
private fun addViewClickListener() {
|
private fun addViewClickListener() {
|
||||||
// ========== 重量识别相关功能已注释 ==========
|
// ========== 重量识别相关功能已注释 ==========
|
||||||
@@ -198,7 +205,7 @@ class PackActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
binding.ivAddWeight.clickWithDebounce {
|
binding.ivAddWeight.clickWithDebounce {
|
||||||
if(currentWeight <= 0.0) {
|
if (currentWeight <= 0.0) {
|
||||||
toast("当前秤重量无效")
|
toast("当前秤重量无效")
|
||||||
return@clickWithDebounce
|
return@clickWithDebounce
|
||||||
}
|
}
|
||||||
@@ -209,8 +216,17 @@ class PackActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.btnGetTraceCode.clickWithDebounce {
|
binding.btnGetTraceCode.clickWithDebounce {
|
||||||
val item = list.getOrNull(clickIndex)?:return@clickWithDebounce
|
val item = list.getOrNull(clickIndex) ?: return@clickWithDebounce
|
||||||
//viewModelV2.getCode
|
InboundIngredientSearchDialog(
|
||||||
|
activity = this,
|
||||||
|
viewModelV2 = viewModelV2,
|
||||||
|
defIngredientName = item.goodsName
|
||||||
|
) { vo ->
|
||||||
|
materialAdapter.getItem(clickIndex)?.let {
|
||||||
|
it.materCode = vo.traceCode
|
||||||
|
materialAdapter.notifyItemChanged(clickIndex)
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
}
|
}
|
||||||
binding.btnSubmit.clickWithDebounce {
|
binding.btnSubmit.clickWithDebounce {
|
||||||
|
|
||||||
@@ -316,6 +332,7 @@ class PackActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
loadDishDetail(detail)
|
loadDishDetail(detail)
|
||||||
}
|
}
|
||||||
|
|
||||||
is UiState.Error -> toast(state.msg)
|
is UiState.Error -> toast(state.msg)
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
@@ -367,6 +384,13 @@ class PackActivity : BaseActivity() {
|
|||||||
private var firstReqSize = 0
|
private var firstReqSize = 0
|
||||||
private val list = mutableListOf<GoodsItem>()
|
private val list = mutableListOf<GoodsItem>()
|
||||||
private var clickIndex = -1
|
private var clickIndex = -1
|
||||||
|
|
||||||
|
private val fields = mutableListOf<FormField>()
|
||||||
|
|
||||||
|
private val formAdapter by lazy {
|
||||||
|
FormFieldAdapter(fields)
|
||||||
|
}
|
||||||
|
|
||||||
private val materialAdapter by lazy {
|
private val materialAdapter by lazy {
|
||||||
FoodMaterialAdapter(list).apply {
|
FoodMaterialAdapter(list).apply {
|
||||||
onItemClick = onItemClick@{ positon ->
|
onItemClick = onItemClick@{ positon ->
|
||||||
@@ -409,12 +433,153 @@ class PackActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private var packageMethodField: FormField? = null
|
||||||
|
private var deviceField: FormField? = null
|
||||||
|
private fun initFormList() {
|
||||||
|
packageMethodField =
|
||||||
|
FormField(
|
||||||
|
label = "包装方式", type = FieldType.DROPDOWN,
|
||||||
|
extraApiKeys = mapOf("packageMethodId" to "id", "packageMethod" to "value"),
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
fields.add(packageMethodField!!)
|
||||||
|
fields.add(
|
||||||
|
FormField(
|
||||||
|
label = "包装份数", type = FieldType.INTEGER,
|
||||||
|
apiKey = "quantity", required = true, hint = "请输入份数"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
// fields.add(
|
||||||
|
// FormField(
|
||||||
|
// label = "包装日期",
|
||||||
|
// type = FieldType.DATE_PICKER,
|
||||||
|
// apiKey = "packageDate",
|
||||||
|
// required = true
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
fields.add(
|
||||||
|
FormField(
|
||||||
|
label = "保质期至",
|
||||||
|
type = FieldType.DATE_PICKER,
|
||||||
|
apiKey = "expiryDate",
|
||||||
|
required = true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fields.add(
|
||||||
|
FormField(
|
||||||
|
label = "存放温度(℃)",
|
||||||
|
type = FieldType.DECIMAL,
|
||||||
|
apiKey = "storageTemp",
|
||||||
|
required = false,
|
||||||
|
hint = "请输入小数"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fields.add(
|
||||||
|
FormField(
|
||||||
|
label = "包装人",
|
||||||
|
type = FieldType.TEXT,
|
||||||
|
apiKey = "operator",
|
||||||
|
required = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
deviceField = FormField(
|
||||||
|
label = "终端设备",
|
||||||
|
type = FieldType.DROPDOWN,
|
||||||
|
extraApiKeys = mapOf("deviceId" to "id"),
|
||||||
|
required = false
|
||||||
|
)
|
||||||
|
fields.add(deviceField!!)
|
||||||
|
// fields.add(
|
||||||
|
// FormField(
|
||||||
|
// label = "操作类型", type = FieldType.FIXED,
|
||||||
|
// apiKey = "opType",
|
||||||
|
// required = true,
|
||||||
|
// value = "设备自动"
|
||||||
|
// )
|
||||||
|
// )
|
||||||
|
loadDictItemsWithCallback("sup_package_method", packageMethodField!!)
|
||||||
|
loadDeviceOptionsWithCallback(deviceField)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载字典项下拉(回调版本),适合多次不同 dictType 的场景
|
||||||
|
*/
|
||||||
|
private fun loadDictItemsWithCallback(dictType: String, targetField: FormField) {
|
||||||
|
viewModelV2.getDictItemsWithCallback(
|
||||||
|
dictType = dictType,
|
||||||
|
onLoading = {},
|
||||||
|
onResult = { state ->
|
||||||
|
when (state) {
|
||||||
|
is UiState.Success -> {
|
||||||
|
val options = state.data?.map { vo ->
|
||||||
|
DictType(
|
||||||
|
id = vo.id?.toString() ?: "",
|
||||||
|
value = vo.dictLabel ?: "",
|
||||||
|
type = vo.dictCode ?: ""
|
||||||
|
)
|
||||||
|
} ?: emptyList()
|
||||||
|
targetField.options.clear()
|
||||||
|
targetField.options.addAll(options)
|
||||||
|
val index = fields.indexOf(targetField)
|
||||||
|
if (index >= 0) formAdapter.notifyItemChanged(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
is UiState.Error -> {
|
||||||
|
toast("加载字典项失败:${state.msg}")
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载设备下拉(回调版本),用于餐品净菜包装
|
||||||
|
*/
|
||||||
|
private fun loadDeviceOptionsWithCallback(deviceField: FormField? = null) {
|
||||||
|
val field = deviceField ?: return
|
||||||
|
viewModelV2.getDeviceOptionsWithCallback(
|
||||||
|
onLoading = {},
|
||||||
|
onResult = { state ->
|
||||||
|
when (state) {
|
||||||
|
is UiState.Success -> {
|
||||||
|
val options = state.data?.map { vo ->
|
||||||
|
DictType(
|
||||||
|
id = vo.id?.toString() ?: "",
|
||||||
|
value = vo.deviceName ?: "",
|
||||||
|
type = vo.deviceNo ?: ""
|
||||||
|
)
|
||||||
|
} ?: emptyList()
|
||||||
|
field.options.clear()
|
||||||
|
field.options.addAll(options)
|
||||||
|
val index = fields.indexOf(field)
|
||||||
|
if (index >= 0) formAdapter.notifyItemChanged(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
is UiState.Error -> {
|
||||||
|
toast("加载设备列表失败:${state.msg}")
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RecyclerView初始化
|
* RecyclerView初始化
|
||||||
*/
|
*/
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
private fun initRecyclerView() {
|
private fun initRecyclerView() {
|
||||||
|
initFormList()
|
||||||
|
binding.rvFormList.let {
|
||||||
|
it.layoutManager = GridLayoutManager(this, 2, GridLayoutManager.VERTICAL, false)
|
||||||
|
it.adapter = formAdapter
|
||||||
|
}
|
||||||
|
|
||||||
binding.rvMaterialList.let {
|
binding.rvMaterialList.let {
|
||||||
it.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
it.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
|
||||||
// 仅 isNewDishType=true 的 item 显示侧滑删除菜单(必须在 setAdapter 之前调用)
|
// 仅 isNewDishType=true 的 item 显示侧滑删除菜单(必须在 setAdapter 之前调用)
|
||||||
@@ -570,7 +735,11 @@ class PackActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
startActivity(launchIntent) { resultIntent ->
|
startActivity(launchIntent) { resultIntent ->
|
||||||
if (resultIntent == null) return@startActivity
|
if (resultIntent == null) return@startActivity
|
||||||
val food = IntentCompat.getSerializableExtra(resultIntent, FoodSearchActivity.FOOD_ITEM, FoodRecord::class.java)
|
val food = IntentCompat.getSerializableExtra(
|
||||||
|
resultIntent,
|
||||||
|
FoodSearchActivity.FOOD_ITEM,
|
||||||
|
FoodRecord::class.java
|
||||||
|
)
|
||||||
Log.d(TAG, "jumpSearch: record=$food")
|
Log.d(TAG, "jumpSearch: record=$food")
|
||||||
if (food == null) return@startActivity
|
if (food == null) return@startActivity
|
||||||
binding.etInputDish.run {
|
binding.etInputDish.run {
|
||||||
@@ -583,13 +752,15 @@ class PackActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleRvTouchHideKeyboard() {
|
private fun handleRvTouchHideKeyboard() {
|
||||||
val gestureDetector = GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() {
|
val gestureDetector =
|
||||||
override fun onSingleTapUp(e: MotionEvent): Boolean {
|
GestureDetector(this, object : GestureDetector.SimpleOnGestureListener() {
|
||||||
hideKeyboard()
|
override fun onSingleTapUp(e: MotionEvent): Boolean {
|
||||||
return false
|
hideKeyboard()
|
||||||
}
|
return false
|
||||||
})
|
}
|
||||||
binding.rvMaterialList.addOnItemTouchListener(object : RecyclerView.SimpleOnItemTouchListener() {
|
})
|
||||||
|
binding.rvMaterialList.addOnItemTouchListener(object :
|
||||||
|
RecyclerView.SimpleOnItemTouchListener() {
|
||||||
private var startX = 0f
|
private var startX = 0f
|
||||||
private var startY = 0f
|
private var startY = 0f
|
||||||
|
|
||||||
@@ -599,6 +770,7 @@ class PackActivity : BaseActivity() {
|
|||||||
startX = e.x
|
startX = e.x
|
||||||
startY = e.y
|
startY = e.y
|
||||||
}
|
}
|
||||||
|
|
||||||
MotionEvent.ACTION_MOVE -> {
|
MotionEvent.ACTION_MOVE -> {
|
||||||
val dx = abs(e.x - startX)
|
val dx = abs(e.x - startX)
|
||||||
val dy = abs(e.y - startY)
|
val dy = abs(e.y - startY)
|
||||||
@@ -613,4 +785,9 @@ class PackActivity : BaseActivity() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
WeightUtil.removeWeightListener(TAG)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,28 @@
|
|||||||
package com.shuwei.dish.match.ui
|
package com.shuwei.dish.match.ui
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import androidx.core.content.IntentCompat
|
import androidx.core.content.IntentCompat
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import com.shuwei.dish.match.R
|
||||||
import com.shuwei.dish.match.adapter.TaskDetailAdapter
|
import com.shuwei.dish.match.adapter.TaskDetailAdapter
|
||||||
import com.shuwei.dish.match.base.BaseActivity
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
import com.shuwei.dish.match.databinding.ActivityTaskDetailBinding
|
import com.shuwei.dish.match.databinding.ActivityTaskDetailBinding
|
||||||
|
import com.shuwei.dish.match.dialog.CommonDialog
|
||||||
|
import com.shuwei.dish.match.dialog.InboundIngredientSearchDialog
|
||||||
import com.shuwei.dish.match.model.NutComboTaskDetailVO
|
import com.shuwei.dish.match.model.NutComboTaskDetailVO
|
||||||
|
import com.shuwei.dish.match.model.NutComboTaskItemDetail
|
||||||
import com.shuwei.dish.match.model.NutComboTaskVO
|
import com.shuwei.dish.match.model.NutComboTaskVO
|
||||||
import com.shuwei.dish.match.net.NetViewModelV2
|
import com.shuwei.dish.match.net.NetViewModelV2
|
||||||
import com.shuwei.dish.match.net.UiState
|
import com.shuwei.dish.match.net.UiState
|
||||||
|
import com.shuwei.dish.match.utils.AddressUtil
|
||||||
|
import com.shuwei.dish.match.utils.SpTool
|
||||||
|
import com.shuwei.dish.match.utils.WeightUtil
|
||||||
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
|
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
||||||
|
import com.shuwei.dish.match.utils.ext.toJsonString
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -27,23 +37,60 @@ class TaskDetailActivity : BaseActivity() {
|
|||||||
const val TASK_ITEM = "taskItem"
|
const val TASK_ITEM = "taskItem"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var taskDetailVO: NutComboTaskDetailVO? = null
|
||||||
private val binding by lazy { ActivityTaskDetailBinding.inflate(layoutInflater) }
|
private val binding by lazy { ActivityTaskDetailBinding.inflate(layoutInflater) }
|
||||||
private val viewModelV2 by lazy { NetViewModelV2() }
|
private val viewModelV2 by lazy { NetViewModelV2() }
|
||||||
|
|
||||||
private var taskItem: NutComboTaskVO? = null
|
private var taskItem: NutComboTaskVO? = null
|
||||||
private val itemList = mutableListOf<com.shuwei.dish.match.model.NutComboTaskItemDetail>()
|
private var clickIndex = -1
|
||||||
|
private val comboTaskList = mutableListOf<NutComboTaskItemDetail>()
|
||||||
private val itemAdapter by lazy {
|
private val itemAdapter by lazy {
|
||||||
TaskDetailAdapter(itemList).apply {
|
TaskDetailAdapter(comboTaskList).apply {
|
||||||
setOnItemClickListener { adapter, view, position ->
|
setOnItemClickListener { adapter, view, position ->
|
||||||
getItem(position) ?: return@setOnItemClickListener
|
clickItem(this, position)
|
||||||
itemList.forEachIndexed { index, detail ->
|
}
|
||||||
detail.isClicked = index == position
|
addOnItemChildClickListener(R.id.ivClearIcon) { _, _, position ->
|
||||||
|
val item = getItem(position) ?: return@addOnItemChildClickListener
|
||||||
|
Log.d(PrepareFoodActivity.Companion.TAG, "onFoodItemClick: ${item.toJsonString()}")
|
||||||
|
// 无重量信息时转为 item 整体点击(触发选中效果)
|
||||||
|
if (item.actualQty.isNullOrBlank()) {
|
||||||
|
clickItem(this, position)
|
||||||
|
return@addOnItemChildClickListener
|
||||||
|
}
|
||||||
|
deleteRemindDialog("清除确认", "确定清除食材「${item.ingredientName}」添加的溯源码和重量吗?") {
|
||||||
|
item.run {
|
||||||
|
actualQty = null
|
||||||
|
traceCode = null
|
||||||
|
isSetFinished = false
|
||||||
|
}
|
||||||
|
notifyItemChanged(position)
|
||||||
}
|
}
|
||||||
notifyDataSetChanged()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除提醒
|
||||||
|
*/
|
||||||
|
private fun deleteRemindDialog(title: String, content: String, action: () -> Unit) {
|
||||||
|
CommonDialog(this)
|
||||||
|
.setTitle(title)
|
||||||
|
.setContent(content)
|
||||||
|
.setNegativeButton("取消")
|
||||||
|
.setPositiveButton("确认") {
|
||||||
|
action()
|
||||||
|
}.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun clickItem(adapter: TaskDetailAdapter, position: Int) {
|
||||||
|
adapter.getItem(position) ?: return
|
||||||
|
comboTaskList.forEachIndexed { index, detail ->
|
||||||
|
detail.isClicked = index == position
|
||||||
|
}
|
||||||
|
adapter.notifyDataSetChanged()
|
||||||
|
this@TaskDetailActivity.clickIndex = position
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
@@ -64,8 +111,31 @@ class TaskDetailActivity : BaseActivity() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
initRecyclerView()
|
initRecyclerView()
|
||||||
|
addWeightListener()
|
||||||
initView()
|
initView()
|
||||||
loadDetail()
|
loadDetail()
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
viewModelV2.startComboTaskState.collect { state ->
|
||||||
|
when (state) {
|
||||||
|
is UiState.Success -> {
|
||||||
|
dismissLoading()
|
||||||
|
toast("已开始组配")
|
||||||
|
// 刷新详情
|
||||||
|
loadDetail()
|
||||||
|
// 更新本地状态
|
||||||
|
taskItem?.comboStatus = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
is UiState.Error -> {
|
||||||
|
dismissLoading()
|
||||||
|
toast(state.msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -92,8 +162,59 @@ class TaskDetailActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.btnGetTraceCode.clickWithDebounce {
|
binding.btnGetTraceCode.clickWithDebounce {
|
||||||
|
val item = itemAdapter.getItem(clickIndex) ?: return@clickWithDebounce
|
||||||
|
InboundIngredientSearchDialog(
|
||||||
|
activity = this,
|
||||||
|
viewModelV2 = viewModelV2,
|
||||||
|
defIngredientName = item.ingredientName
|
||||||
|
) { vo ->
|
||||||
|
itemAdapter.getItem(clickIndex)?.let {
|
||||||
|
it.traceCode = vo.traceCode
|
||||||
|
itemAdapter.notifyItemChanged(clickIndex)
|
||||||
|
}
|
||||||
|
}.show()
|
||||||
}
|
}
|
||||||
|
binding.ivAddWeight.clickWithDebounce {
|
||||||
|
if (currentWeight <= 0.0) {
|
||||||
|
toast("当前秤重量无效")
|
||||||
|
return@clickWithDebounce
|
||||||
|
}
|
||||||
|
itemAdapter.getItem(clickIndex)?.let {
|
||||||
|
it.actualQty = currentWeight.toString()
|
||||||
|
it.isSetFinished = true
|
||||||
|
itemAdapter.notifyItemChanged(clickIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.ivClearWeight.clickWithDebounce {
|
||||||
|
initialWeight = 0.0
|
||||||
|
WeightUtil.tareTwo(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var currentWeight: Double = 0.0
|
||||||
|
|
||||||
|
/** 初始秤读数,净重 = 秤读数 - initialWeight,从 SpTool.configWeight 读取 */
|
||||||
|
private var initialWeight = SpTool.configWeight.toDouble()
|
||||||
|
|
||||||
|
private fun addWeightListener() {
|
||||||
|
WeightUtil.addWeightListener(
|
||||||
|
weightKey = TAG,
|
||||||
|
getWeight = { address, state, weight ->
|
||||||
|
if (address == AddressUtil.ONE && state == WeightUtil.STATE_STABLE) {
|
||||||
|
runOnUiThread {
|
||||||
|
currentWeight = weight - initialWeight
|
||||||
|
binding.tvShowWeight.run {
|
||||||
|
if (tag != currentWeight) {
|
||||||
|
// text = "称重:${netWeight}g"
|
||||||
|
val weightText = "${currentWeight.roundedOneDecimalPlace()}g"
|
||||||
|
text = weightText
|
||||||
|
tag = currentWeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//recognizeFood(netWeight)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -118,22 +239,22 @@ class TaskDetailActivity : BaseActivity() {
|
|||||||
dismissLoading()
|
dismissLoading()
|
||||||
when (state) {
|
when (state) {
|
||||||
is UiState.Success -> {
|
is UiState.Success -> {
|
||||||
val detail = state.data
|
taskDetailVO = state.data
|
||||||
if (detail == null) {
|
if (taskDetailVO == null) {
|
||||||
toast("详情为空")
|
toast("详情为空")
|
||||||
return@onResult
|
return@onResult
|
||||||
}
|
}
|
||||||
// 更新状态(可能已被其他设备修改)
|
// 更新状态(可能已被其他设备修改)
|
||||||
binding.tvStatus.text = getStatusText(detail.comboStatus)
|
binding.tvStatus.text = getStatusText(taskDetailVO!!.comboStatus)
|
||||||
if (detail.comboStatus != 0) {
|
if (taskDetailVO!!.comboStatus != 0) {
|
||||||
binding.btnStart.gone()
|
binding.btnStart.gone()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 加载食材列表
|
// 加载食材列表
|
||||||
val items = detail.items
|
val items = taskDetailVO!!.items
|
||||||
if (!items.isNullOrEmpty()) {
|
if (!items.isNullOrEmpty()) {
|
||||||
itemList.clear()
|
comboTaskList.clear()
|
||||||
itemList.addAll(items)
|
comboTaskList.addAll(items)
|
||||||
itemAdapter.notifyDataSetChanged()
|
itemAdapter.notifyDataSetChanged()
|
||||||
} else {
|
} else {
|
||||||
toast("该任务无食材信息")
|
toast("该任务无食材信息")
|
||||||
@@ -151,29 +272,23 @@ class TaskDetailActivity : BaseActivity() {
|
|||||||
* 开始组配
|
* 开始组配
|
||||||
*/
|
*/
|
||||||
private fun startComboTask(taskId: Long) {
|
private fun startComboTask(taskId: Long) {
|
||||||
|
val task = taskDetailVO ?: return
|
||||||
|
val count = comboTaskList.count { it.traceCode.isNullOrBlank() }
|
||||||
|
if (count > 0) {
|
||||||
|
toast("存在未设置的溯源码")
|
||||||
|
return
|
||||||
|
}
|
||||||
showLoading("正在开始组配……")
|
showLoading("正在开始组配……")
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
viewModelV2.startComboTask(taskId)
|
//viewModelV2.startComboTask(taskId)
|
||||||
}
|
task.items = comboTaskList
|
||||||
lifecycleScope.launch {
|
viewModelV2.addComboTask(param = task) { state, msg ->
|
||||||
viewModelV2.startComboTaskState.collect { state ->
|
dismissLoading()
|
||||||
when (state) {
|
if (state.not()) {
|
||||||
is UiState.Success -> {
|
toast(msg)
|
||||||
dismissLoading()
|
return@addComboTask
|
||||||
toast("已开始组配")
|
|
||||||
// 刷新详情
|
|
||||||
loadDetail()
|
|
||||||
// 更新本地状态
|
|
||||||
taskItem?.comboStatus = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
is UiState.Error -> {
|
|
||||||
dismissLoading()
|
|
||||||
toast(state.msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {}
|
|
||||||
}
|
}
|
||||||
|
toast("上报成功")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,4 +304,10 @@ class TaskDetailActivity : BaseActivity() {
|
|||||||
else -> "未知"
|
else -> "未知"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onDestroy() {
|
||||||
|
super.onDestroy()
|
||||||
|
WeightUtil.removeWeightListener(TAG)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -167,4 +167,16 @@ fun View.hideKeyboard() {
|
|||||||
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||||
imm.hideSoftInputFromWindow(this.windowToken, 0)
|
imm.hideSoftInputFromWindow(this.windowToken, 0)
|
||||||
this.clearFocus() // 清除焦点避免键盘再次弹出
|
this.clearFocus() // 清除焦点避免键盘再次弹出
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 格式化用量字符串,去掉小数点后末尾的0
|
||||||
|
*/
|
||||||
|
fun String?.formatDecimal(): String {
|
||||||
|
if (this.isNullOrBlank()) return "0"
|
||||||
|
return try {
|
||||||
|
BigDecimal(this).stripTrailingZeros().toPlainString()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
this
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -88,6 +88,19 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.divider.MaterialDivider
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:layout_marginHorizontal="30dp"
|
||||||
|
app:dividerColor="@color/gray_eb" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvFormList"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="20dp"
|
||||||
|
android:overScrollMode="never"/>
|
||||||
|
|
||||||
<com.google.android.material.divider.MaterialDivider
|
<com.google.android.material.divider.MaterialDivider
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="1dp"
|
android:layout_height="1dp"
|
||||||
|
|||||||
@@ -96,10 +96,121 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="30dp"
|
||||||
|
android:background="@drawable/shape_white_30_corners"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- <LinearLayout-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="90dp"-->
|
||||||
|
<!-- android:gravity="center_vertical">-->
|
||||||
|
|
||||||
|
<!-- <TextView-->
|
||||||
|
<!-- android:id="@+id/tvGoodsName"-->
|
||||||
|
<!-- android:layout_width="wrap_content"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- android:layout_marginStart="30dp"-->
|
||||||
|
<!-- android:textColor="@color/black"-->
|
||||||
|
<!-- android:textSize="30sp"-->
|
||||||
|
<!-- android:maxLines="1"-->
|
||||||
|
<!-- android:ellipsize="end"-->
|
||||||
|
<!-- android:maxLength="12"-->
|
||||||
|
<!-- android:textStyle="bold"-->
|
||||||
|
<!-- tools:text="豆腐" />-->
|
||||||
|
|
||||||
|
<!-- <TextView-->
|
||||||
|
<!-- android:id="@+id/tvMaterialType"-->
|
||||||
|
<!-- android:layout_width="wrap_content"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- android:layout_marginStart="30dp"-->
|
||||||
|
<!-- android:layout_marginEnd="30dp"-->
|
||||||
|
<!-- android:textColor="@color/black999"-->
|
||||||
|
<!-- android:textSize="26sp"-->
|
||||||
|
<!-- tools:text="主材" />-->
|
||||||
|
|
||||||
|
<!-- </LinearLayout>-->
|
||||||
|
|
||||||
|
<!-- <com.google.android.material.divider.MaterialDivider-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="1dp"-->
|
||||||
|
<!-- android:layout_marginHorizontal="30dp"-->
|
||||||
|
<!-- app:dividerColor="@color/gray_eb" />-->
|
||||||
|
|
||||||
|
<!-- <androidx.recyclerview.widget.RecyclerView-->
|
||||||
|
<!-- android:id="@+id/rvFormList"-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="wrap_content"-->
|
||||||
|
<!-- android:layout_marginHorizontal="20dp"-->
|
||||||
|
<!-- android:overScrollMode="never"/>-->
|
||||||
|
|
||||||
|
<!-- <com.google.android.material.divider.MaterialDivider-->
|
||||||
|
<!-- android:layout_width="match_parent"-->
|
||||||
|
<!-- android:layout_height="1dp"-->
|
||||||
|
<!-- android:layout_marginHorizontal="30dp"-->
|
||||||
|
<!-- app:dividerColor="@color/gray_eb" />-->
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="160dp"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:text="用量(克)"
|
||||||
|
android:textColor="@color/black666"
|
||||||
|
android:textSize="26sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvShowWeight"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/shape_white_f6_10_corners"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="-"
|
||||||
|
android:textColor="@color/gray_d6"
|
||||||
|
android:textSize="50sp" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivClearWeight"
|
||||||
|
android:layout_width="90dp"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:src="@drawable/ic_weight_clear" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivAddWeight"
|
||||||
|
android:layout_width="90dp"
|
||||||
|
android:layout_height="90dp"
|
||||||
|
android:layout_marginStart="30dp"
|
||||||
|
android:layout_marginEnd="30dp"
|
||||||
|
android:src="@drawable/ic_weight_add" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginBottom="30dp"
|
||||||
|
android:text="在下方列表中选择食材计重"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="26sp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginHorizontal="30dp"
|
android:layout_marginHorizontal="30dp"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:background="@drawable/shape_white_30_corners"
|
android:background="@drawable/shape_white_30_corners"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
@@ -111,9 +222,9 @@
|
|||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="20dp"
|
android:layout_marginStart="20dp"
|
||||||
android:layout_weight="1"
|
|
||||||
android:padding="10dp"
|
android:padding="10dp"
|
||||||
android:text="食材明细"
|
android:text="食材明细"
|
||||||
android:textColor="@color/black666"
|
android:textColor="@color/black666"
|
||||||
@@ -131,7 +242,6 @@
|
|||||||
android:textColor="@color/dish_green"
|
android:textColor="@color/dish_green"
|
||||||
android:textSize="18sp" />
|
android:textSize="18sp" />
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
@@ -140,6 +250,7 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:layout_marginBottom="20dp"
|
android:layout_marginBottom="20dp"
|
||||||
android:overScrollMode="never"
|
android:overScrollMode="never"
|
||||||
|
android:layout_marginHorizontal="20dp"
|
||||||
android:scrollbars="vertical"
|
android:scrollbars="vertical"
|
||||||
tools:itemCount="3"
|
tools:itemCount="3"
|
||||||
tools:listitem="@layout/list_item_task_detail" />
|
tools:listitem="@layout/list_item_task_detail" />
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
tools:background="@color/white"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/viewLine"
|
||||||
|
android:layout_width="90dp"
|
||||||
|
android:layout_height="10dp"
|
||||||
|
android:layout_marginTop="30dp"
|
||||||
|
android:background="@drawable/shape_gray_dc_5" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvSheetName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="50dp"
|
||||||
|
android:textColor="@color/black333"
|
||||||
|
android:textSize="36sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="已入库净菜检索" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="100dp"
|
||||||
|
android:layout_marginStart="60dp"
|
||||||
|
android:layout_marginTop="50dp"
|
||||||
|
android:layout_marginEnd="60dp"
|
||||||
|
android:background="@drawable/shape_gray_f8_15"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etSheetInput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="start|center_vertical"
|
||||||
|
android:background="@null"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:imeOptions="actionSearch"
|
||||||
|
android:inputType="text"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:paddingStart="30dp"
|
||||||
|
android:paddingEnd="30dp"
|
||||||
|
android:textColor="@color/black666"
|
||||||
|
android:textColorHint="@color/gray_c8"
|
||||||
|
android:textSize="36sp"
|
||||||
|
tools:hint="输入食材名称"
|
||||||
|
tools:ignore="Autofill,LabelFor,TextFields" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivSearch"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:padding="10dp"
|
||||||
|
android:src="@drawable/ic_search_gray"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
|
<com.scwang.smart.refresh.layout.SmartRefreshLayout
|
||||||
|
android:id="@+id/refreshLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="700dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
app:srlEnableOverScrollDrag="false">
|
||||||
|
|
||||||
|
<com.scwang.smart.refresh.header.ClassicsHeader
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recyclerView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginStart="45dp"
|
||||||
|
android:layout_marginTop="15dp"
|
||||||
|
android:layout_marginEnd="45dp"
|
||||||
|
android:layout_marginBottom="15dp"
|
||||||
|
android:minHeight="380dp"
|
||||||
|
android:overScrollMode="never"
|
||||||
|
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
|
||||||
|
app:spanCount="2"
|
||||||
|
tools:itemCount="10"
|
||||||
|
tools:listitem="@layout/list_item_inbound_ingredient" />
|
||||||
|
|
||||||
|
<com.scwang.smart.refresh.footer.ClassicsFooter
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</com.scwang.smart.refresh.layout.SmartRefreshLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
android:layout_width="80dp"
|
android:layout_width="80dp"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginEnd="10dp"
|
||||||
android:src="@drawable/ic_delete"
|
android:src="@drawable/ic_dish_clear"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
|||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/clBlock"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="130dp"
|
||||||
|
android:layout_margin="15dp"
|
||||||
|
android:background="@drawable/shape_white_12_corners"
|
||||||
|
android:foreground="?android:attr/selectableItemBackground"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingStart="20dp"
|
||||||
|
android:paddingEnd="20dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvIngredientName"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="@color/black333"
|
||||||
|
android:textSize="28sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:text="土豆" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvStock"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:textColor="@color/black999"
|
||||||
|
android:textSize="20sp"
|
||||||
|
tools:text="库存:12.5kg" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvTraceCode"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="6dp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:gravity="center"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="@color/dish_green"
|
||||||
|
android:textSize="20sp"
|
||||||
|
tools:text="溯源码:TR20260101001" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -1,17 +1,62 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="15dp"
|
|
||||||
android:layout_marginBottom="15dp"
|
android:layout_marginBottom="15dp"
|
||||||
android:background="@drawable/shape_white_fb_15_corners"
|
android:background="@drawable/shape_white_fb_15_corners"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:padding="15dp">
|
android:paddingVertical="15dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivClearIcon"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:src="@drawable/ic_dish_clear"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivOperateIcon"
|
||||||
|
android:layout_width="80dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/ivClearIcon"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
tools:src="@drawable/ic_dish_selected" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvActualQty"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:hint="-"
|
||||||
|
android:textColor="@color/dish_green"
|
||||||
|
android:textColorHint="@color/gray_d6"
|
||||||
|
android:textSize="32sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/ivOperateIcon"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:text="200g" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/llFoodInfo"
|
||||||
android:layout_height="wrap_content">
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="20dp"
|
||||||
|
android:layout_marginStart="20dp"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/tvActualQty"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintVertical_chainStyle="packed">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvIngredientName"
|
android:id="@+id/tvIngredientName"
|
||||||
@@ -32,49 +77,28 @@
|
|||||||
tools:text="主材" />
|
tools:text="主材" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:id="@+id/tvPerPortionQty"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginVertical="8dp"
|
||||||
android:orientation="horizontal">
|
android:textColor="@color/black666"
|
||||||
|
android:textSize="20sp"
|
||||||
<TextView
|
app:layout_constraintBottom_toTopOf="@+id/tvTraceCode"
|
||||||
android:id="@+id/tvPerPortionQty"
|
app:layout_constraintStart_toStartOf="@id/llFoodInfo"
|
||||||
android:layout_width="wrap_content"
|
app:layout_constraintTop_toBottomOf="@id/llFoodInfo"
|
||||||
android:layout_height="wrap_content"
|
tools:text="每份用量:200g" />
|
||||||
android:textColor="@color/black666"
|
|
||||||
android:textSize="20sp"
|
|
||||||
tools:text="每份用量:200g" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvActualQty"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="20dp"
|
|
||||||
android:textColor="@color/black666"
|
|
||||||
android:textSize="20sp"
|
|
||||||
tools:text="实际用量:200g" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvTotalQty"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="20dp"
|
|
||||||
android:textColor="@color/black666"
|
|
||||||
android:textSize="20sp"
|
|
||||||
tools:text="合计用量:80000g" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvTraceCode"
|
android:id="@+id/tvTraceCode"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="5dp"
|
|
||||||
android:textColor="@color/black999"
|
android:textColor="@color/black999"
|
||||||
android:textSize="18sp"
|
android:textSize="18sp"
|
||||||
android:visibility="gone"
|
app:layout_constraintStart_toStartOf="@id/llFoodInfo"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/tvPerPortionQty"
|
||||||
tools:text="溯源码:TRACE-20260601001"
|
tools:text="溯源码:TRACE-20260601001"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
</LinearLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|||||||
Reference in New Issue
Block a user