feat(activity): 新增同名调料用量聚合合并展示逻辑

- SubmitFoodActivity 新增 rawWeightMap 记录各秤槽位原始用量
- 每次秤数据更新后按 goodsName 聚合求和,同名调料只展示一条
- SeasoningWeightAdapter 改为按 goodsName 作为唯一标识匹配更新/移除
- SlaveActivity 简化高亮触发条件判断
This commit is contained in:
2026-04-21 17:50:02 +08:00
parent 0a90a8b368
commit bbdebc0c9c
3 changed files with 43 additions and 26 deletions
@@ -8,28 +8,25 @@ import com.shuwei.dish.match.databinding.ItemSeasoningWeightBinding
/** /**
* 调料使用重量列表 Adapter * 调料使用重量列表 Adapter
* 用于 SubmitFoodActivity 展示各调料槽位的实时用量 * 用于 SubmitFoodActivity 展示各调料槽位的实时用量
* * 同名调料已在外部聚合,adapter 按 goodsName 作为唯一标识
* @param items 调料数据列表,外部直接操作后调用 notifyDataSetChanged
*/ */
class SeasoningWeightAdapter : RecyclerView.Adapter<SeasoningWeightAdapter.VH>() { class SeasoningWeightAdapter : RecyclerView.Adapter<SeasoningWeightAdapter.VH>() {
/** 调料展示数据项 */ /** 调料展示数据项key = goodsName(同名调料已聚合) */
data class Item( data class Item(
/** 唯一标识:deviceId#address */
val key: String,
val goodsId: String, val goodsId: String,
val goodsName: String, val goodsName: String,
/** 使用重量(克),= 初始重量 - 当前重量,≥0 */ /** 使用重量(克),同名调料已累加 */
val useWeight: Double val useWeight: Double
) )
val items = mutableListOf<Item>() val items = mutableListOf<Item>()
/** /**
* 更新单个 item 的重量,若 key 不存在则追加 * 更新单个 item,按 goodsName 匹配;不存在则追加
*/ */
fun updateItem(item: Item) { fun updateItem(item: Item) {
val idx = items.indexOfFirst { it.key == item.key } val idx = items.indexOfFirst { it.goodsName == item.goodsName }
if (idx >= 0) { if (idx >= 0) {
items[idx] = item items[idx] = item
notifyItemChanged(idx) notifyItemChanged(idx)
@@ -40,10 +37,10 @@ class SeasoningWeightAdapter : RecyclerView.Adapter<SeasoningWeightAdapter.VH>()
} }
/** /**
* 移除指定 key 的 item(用量不足阈值时调用) * 移除指定 goodsName 的 item聚合后用量不足阈值时调用)
*/ */
fun removeItem(key: String) { fun removeItem(goodsName: String) {
val idx = items.indexOfFirst { it.key == key } val idx = items.indexOfFirst { it.goodsName == goodsName }
if (idx >= 0) { if (idx >= 0) {
items.removeAt(idx) items.removeAt(idx)
notifyItemRemoved(idx) notifyItemRemoved(idx)
@@ -209,9 +209,7 @@ class SlaveActivity : BaseActivity() {
// 重量快照与高亮判断(在回调线程计算,不涉及 UI) // 重量快照与高亮判断(在回调线程计算,不涉及 UI)
val baseline = weightSnapshot[address] val baseline = weightSnapshot[address]
val shouldHighlight = baseline != null val shouldHighlight = baseline != null
&& baseline >= 0.0
&& state == WeightUtil.STATE_STABLE && state == WeightUtil.STATE_STABLE
&& weight > WEIGHT_DELTA_THRESHOLD
&& (weight - baseline) > WEIGHT_DELTA_THRESHOLD && (weight - baseline) > WEIGHT_DELTA_THRESHOLD
if (baseline == null || state == WeightUtil.STATE_STABLE) { if (baseline == null || state == WeightUtil.STATE_STABLE) {
weightSnapshot[address] = weight weightSnapshot[address] = weight
@@ -77,6 +77,12 @@ class SubmitFoodActivity : BaseActivity() {
*/ */
private val slotMap = mutableMapOf<String, Pair<String, String>>() private val slotMap = mutableMapOf<String, Pair<String, String>>()
/**
* 各秤原始用量,key = "deviceId#address"value = Triple(goodsId, goodsName, useWeight)
* 每次秤数据变化后更新,再按 goodsName 聚合推给 adapter
*/
private val rawWeightMap = mutableMapOf<String, Triple<String, String, Double>>()
@Suppress("unchecked_cast", "DEPRECATION") @Suppress("unchecked_cast", "DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@@ -159,27 +165,43 @@ class SubmitFoodActivity : BaseActivity() {
.coerceAtLeast(0.0) .coerceAtLeast(0.0)
.roundedOneDecimalPlace() .roundedOneDecimalPlace()
// 用量不足 0.5g 时从列表移除(或不添加) // 更新原始用量 map,再按 goodsName 聚合刷新 adapter
if (useWeight < 0.5) { if (useWeight < 0.5) {
seasoningAdapter.removeItem(key) rawWeightMap.remove(key)
return@forEach } else {
rawWeightMap[key] = Triple(goodsId, goodsName, useWeight)
} }
refreshAdapterByName(goodsName)
seasoningAdapter.updateItem(
SeasoningWeightAdapter.Item(
key = key,
goodsId = goodsId,
goodsName = goodsName,
useWeight = useWeight
)
)
} }
} }
} }
} }
/**
* 按 goodsName 聚合 rawWeightMap,将同名调料的用量累加后推给 adapter
* 聚合后总量 < 0.5g 则从 adapter 移除
*/
private fun refreshAdapterByName(goodsName: String) {
val grouped = rawWeightMap.values.filter { it.second == goodsName }
if (grouped.isEmpty()) {
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
)
)
}
}
private fun addViewListener() { private fun addViewListener() {
binding.btnWeightClear.setOnClickListener { WeightUtil.tareTwo(AddressUtil.TWO) }
binding.btnCook.clickWithDebounce { cook() } binding.btnCook.clickWithDebounce { cook() }