feat(activity): SubmitFoodActivity 支持制作中菜品调料历史数据加载与新增叠加

- SeasoningWeightAdapter 改继承 BaseQuickAdapter
- item_seasoning_weight 左右间距改为 32dp
- isCooking=true 时从数据库查询 goodsList 并预填充调料历史数据
- refreshAdapterByName 叠加历史用量,修复新增用量覆盖历史数据问题
- 返回键拦截,弹窗提示保存数据

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-22 11:47:13 +08:00
co-authored by Claude Sonnet 4.6
parent f25108360b
commit bce9675b0f
4 changed files with 107 additions and 53 deletions
@@ -3,6 +3,7 @@ package com.shuwei.dish.match.ui
import android.annotation.SuppressLint
import android.os.Bundle
import android.util.Log
import androidx.activity.addCallback
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
@@ -13,6 +14,7 @@ import com.shuwei.dish.match.base.BaseActivity
import com.shuwei.dish.match.base.BaseApp
import com.shuwei.dish.match.databinding.ActivitySubmitFoodBinding
import com.shuwei.dish.match.db.AppRepository
import com.shuwei.dish.match.dialog.CommonDialog
import com.shuwei.dish.match.entity.CookFoodEntity
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
import com.shuwei.dish.match.entity.FoodRecord
@@ -23,6 +25,7 @@ import com.shuwei.dish.match.utils.AddressUtil
import com.shuwei.dish.match.utils.WeightUtil
import com.shuwei.dish.match.utils.ext.clickWithDebounce
import com.shuwei.dish.match.utils.ext.gone
import com.shuwei.dish.match.utils.ext.roundedDecimalPlace
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
import com.shuwei.dish.match.utils.ext.startActivity
import com.shuwei.dish.match.utils.ext.toJsonString
@@ -83,6 +86,12 @@ class SubmitFoodActivity : BaseActivity() {
*/
private val rawWeightMap = mutableMapOf<String, Triple<String, String, Double>>()
/**
* isCooking=true 时从 goodsList 预填充的历史用量,key = goodsNamevalue = goodsId to useWeight
* 用于 refreshAdapterByName 时叠加到秤新增用量上
*/
private val baseSeasoningMap = mutableMapOf<String, Pair<String, Double>>()
@Suppress("unchecked_cast", "DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -93,8 +102,11 @@ class SubmitFoodActivity : BaseActivity() {
intent.extras?.apply {
food = getSerializable(FOOD_ITEM) as FoodRecord?
Log.d(TAG, "onCreate: cookMode=${food?.cookMode}")
// 非烹饪中,从菜品主辅材配置页面带入数据
goodsList = getSerializable(GOODS_LIST) as MutableList<CookFoodGoodsEntity>?
// isCooking=false:从前一页面带入主辅材数据;isCooking=true:从数据库查询
if (food?.isCooking == false) {
goodsList = getSerializable(GOODS_LIST) as MutableList<CookFoodGoodsEntity>?
Log.d(TAG, "onCreate: goodsList=${goodsList.toJsonString()}")
}
}
setTitleBar(titleBarAction = {
it.visible()
@@ -102,11 +114,17 @@ class SubmitFoodActivity : BaseActivity() {
it.text = food?.foodName
}, rightIconActon = {
it.gone()
it.setImageResource(R.drawable.ic_setting)
}, backAction = {
it.setOnClickListener {
remindSaveDataDialog()
}
})
setupRecyclerView()
addViewListener()
loadSlotsThenObserveScales()
onBackPressedDispatcher.addCallback(this) {
remindSaveDataDialog()
}
}
/** 初始化 RecyclerView2列 GridLayoutManager */
@@ -118,7 +136,7 @@ class SubmitFoodActivity : BaseActivity() {
/**
* 从 Room 加载槽位配置后,开始订阅子设备秤数据
* 确保 slotMap 就绪后再处理秤数据,避免名称为空
* isCooking=true 时先从数据库查询 goodsList,筛选调料预填充 adapter,再开始观测
*/
private fun loadSlotsThenObserveScales() {
lifecycleScope.launch(Dispatchers.IO) {
@@ -127,7 +145,29 @@ class SubmitFoodActivity : BaseActivity() {
slots.forEach { slot ->
slotMap["${slot.deviceId}#${slot.address}"] = slot.goodsId to slot.goodsName
}
observeScaleData()
if (food?.isCooking == true) {
// 制作中:从数据库查询 goodsList,筛选调料数据预填充 adapter
val foodId = food?.foodId ?: return@withContext
val cookMode = food?.cookMode ?: return@withContext
appViewModel.getCookFoodGoodsList(foodId, cookMode) { list ->
goodsList = list
list.filter { it.materialType == 3 }.forEach { item ->
val name = item.goodsName ?: ""
val weight = item.useWeight ?: 0.0
baseSeasoningMap[name] = (item.goodsId) to weight
seasoningAdapter.updateItem(
SeasoningWeightAdapter.Item(
goodsId = item.goodsId,
goodsName = name,
useWeight = weight
)
)
}
observeScaleData()
}
} else {
observeScaleData()
}
}
}
}
@@ -174,33 +214,34 @@ class SubmitFoodActivity : BaseActivity() {
}
/**
* 按 goodsName 聚合 rawWeightMap将同名调料的用量累加后推给 adapter
* 聚合后总量 < 0.5g 则从 adapter 移除
* 按 goodsName 聚合 rawWeightMap叠加历史用量后推给 adapter
* isCooking=true 时只新增,不移除(历史调料数据不可减少)
*/
private fun refreshAdapterByName(goodsName: String) {
val grouped = rawWeightMap.values.filter { it.second == goodsName }
if (grouped.isEmpty()) {
seasoningAdapter.removeItem(goodsName)
val newWeight = grouped.sumOf { it.third }.roundedOneDecimalPlace()
val (baseGoodsId, baseWeight) = baseSeasoningMap[goodsName] ?: ("" to 0.0)
val totalWeight = (newWeight + baseWeight).roundedOneDecimalPlace()
if (totalWeight < 0.5) {
// 制作中模式:已有历史数据,不允许移除
if (food?.isCooking != true) {
seasoningAdapter.removeItem(goodsName)
}
return
}
val totalWeight = grouped.sumOf { it.third }.roundedOneDecimalPlace()
if (totalWeight < 0.5) {
seasoningAdapter.removeItem(goodsName)
} else {
seasoningAdapter.updateItem(
SeasoningWeightAdapter.Item(
goodsId = grouped.first().first,
goodsName = goodsName,
useWeight = totalWeight
)
val goodsId = grouped.firstOrNull()?.first?.takeIf { it.isNotEmpty() } ?: baseGoodsId
seasoningAdapter.updateItem(
SeasoningWeightAdapter.Item(
goodsId = goodsId,
goodsName = goodsName,
useWeight = totalWeight
)
}
)
}
private fun addViewListener() {
binding.btnCook.clickWithDebounce { cook() }
binding.btnWeightClear.clickWithDebounce { WeightUtil.tareTwo(2) }
binding.btnSubmit.clickWithDebounce {
if (cookFoodEntity.foodWeight <= 0.toDouble()) {
toast("未识别到菜品熟重")
@@ -212,8 +253,14 @@ class SubmitFoodActivity : BaseActivity() {
// 监听主设备 2格秤的熟重
WeightUtil.addWeightListener(TAG) { address, _, weight ->
if (address == AddressUtil.TWO) {
cookFoodEntity.foodWeight = weight.toDouble()
binding.tvTotalWeight.text = "${weight / 1000f}"
cookFoodEntity.foodWeight = weight
if (weight > 1000) {
binding.tvTotalWeight.text = "${(weight / 1000f).roundedDecimalPlace(3)}"
binding.tvWeightUnit.text = "千克"
} else {
binding.tvTotalWeight.text = "$weight"
binding.tvWeightUnit.text = ""
}
}
}
}
@@ -231,7 +278,7 @@ class SubmitFoodActivity : BaseActivity() {
showLoading()
// 将调料数据转为 CookFoodGoodsEntity 追加到 goodsList
val typeToken = object : TypeToken<List<CookFoodGoodsEntity>>() {}
// val typeToken = object : TypeToken<List<CookFoodGoodsEntity>>() {}
val tempSeasoningList = seasoningData.map { item ->
CookFoodGoodsEntity().also { entity ->
entity.goodsId = item.goodsId
@@ -356,4 +403,18 @@ class SubmitFoodActivity : BaseActivity() {
WeightUtil.removeWeightListener(TAG)
super.onDestroy()
}
/**
* 未保存数据提醒dialog
*/
private fun remindSaveDataDialog() {
CommonDialog(this)
.setTitle("温馨提示")
.setContent("请确认是否存在未保存的数据?")
.setNegativeButton("取消,留在页面")
.setNeutralButton("返回上页,不保存") { finish() }
.setPositiveButton("保存为烹饪中菜品") { cook() }
.show()
}
}