diff --git a/app/src/main/java/com/shuwei/dish/match/adapter/SeasoningWeightAdapter.kt b/app/src/main/java/com/shuwei/dish/match/adapter/SeasoningWeightAdapter.kt index 2625da0..1c239af 100644 --- a/app/src/main/java/com/shuwei/dish/match/adapter/SeasoningWeightAdapter.kt +++ b/app/src/main/java/com/shuwei/dish/match/adapter/SeasoningWeightAdapter.kt @@ -1,8 +1,10 @@ package com.shuwei.dish.match.adapter +import android.content.Context import android.view.LayoutInflater import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView +import com.chad.library.adapter4.BaseQuickAdapter +import com.chad.library.adapter4.viewholder.QuickViewHolder import com.shuwei.dish.match.databinding.ItemSeasoningWeightBinding /** @@ -10,7 +12,7 @@ import com.shuwei.dish.match.databinding.ItemSeasoningWeightBinding * 用于 SubmitFoodActivity 展示各调料槽位的实时用量 * 同名调料已在外部聚合,adapter 按 goodsName 作为唯一标识 */ -class SeasoningWeightAdapter : RecyclerView.Adapter() { +class SeasoningWeightAdapter : BaseQuickAdapter() { /** 调料展示数据项,key = goodsName(同名调料已聚合) */ data class Item( @@ -20,19 +22,15 @@ class SeasoningWeightAdapter : RecyclerView.Adapter() val useWeight: Double ) - val items = mutableListOf() - /** * 更新单个 item,按 goodsName 匹配;不存在则追加 */ fun updateItem(item: Item) { val idx = items.indexOfFirst { it.goodsName == item.goodsName } if (idx >= 0) { - items[idx] = item - notifyItemChanged(idx) + set(idx, item) } else { - items.add(item) - notifyItemInserted(items.lastIndex) + add(item) } } @@ -41,29 +39,20 @@ class SeasoningWeightAdapter : RecyclerView.Adapter() */ fun removeItem(goodsName: String) { val idx = items.indexOfFirst { it.goodsName == goodsName } - if (idx >= 0) { - items.removeAt(idx) - notifyItemRemoved(idx) - } + if (idx >= 0) removeAt(idx) } - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH { - val binding = ItemSeasoningWeightBinding.inflate( - LayoutInflater.from(parent.context), parent, false - ) + override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH { + val binding = ItemSeasoningWeightBinding.inflate(LayoutInflater.from(context), parent, false) return VH(binding) } - override fun onBindViewHolder(holder: VH, position: Int) { - holder.bind(items[position]) + override fun onBindViewHolder(holder: VH, position: Int, item: Item?) { + item ?: return + holder.binding.tvSeasoningName.text = item.goodsName + holder.binding.tvSeasoningWeight.text = "${item.useWeight}g" } - override fun getItemCount() = items.size + inner class VH(var binding: ItemSeasoningWeightBinding) : QuickViewHolder(binding.root) - class VH(private val b: ItemSeasoningWeightBinding) : RecyclerView.ViewHolder(b.root) { - fun bind(item: Item) { - b.tvSeasoningName.text = item.goodsName - b.tvSeasoningWeight.text = "${item.useWeight}g" - } - } } diff --git a/app/src/main/java/com/shuwei/dish/match/ui/SubmitFoodActivity.kt b/app/src/main/java/com/shuwei/dish/match/ui/SubmitFoodActivity.kt index 0e1e2ed..7e5e190 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/SubmitFoodActivity.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/SubmitFoodActivity.kt @@ -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>() + /** + * isCooking=true 时从 goodsList 预填充的历史用量,key = goodsName,value = goodsId to useWeight + * 用于 refreshAdapterByName 时叠加到秤新增用量上 + */ + private val baseSeasoningMap = mutableMapOf>() + @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? + // isCooking=false:从前一页面带入主辅材数据;isCooking=true:从数据库查询 + if (food?.isCooking == false) { + goodsList = getSerializable(GOODS_LIST) as MutableList? + 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() + } } /** 初始化 RecyclerView,2列 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>() {} +// val typeToken = object : TypeToken>() {} 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() + } + } diff --git a/app/src/main/res/layout/activity_submit_food.xml b/app/src/main/res/layout/activity_submit_food.xml index 54be4b1..b188e4e 100644 --- a/app/src/main/res/layout/activity_submit_food.xml +++ b/app/src/main/res/layout/activity_submit_food.xml @@ -32,6 +32,8 @@ android:layout_width="match_parent" android:layout_height="660dp" android:layout_marginTop="10dp" + android:layout_marginBottom="10dp" + android:layout_marginHorizontal="12dp" android:overScrollMode="never" /> @@ -98,7 +100,7 @@ android:layout_height="wrap_content" android:layout_marginTop="20dp" android:includeFontPadding="false" - android:text="千克" + tools:text="千克" android:textColor="@color/black999" android:textSize="32sp" /> diff --git a/app/src/main/res/layout/item_seasoning_weight.xml b/app/src/main/res/layout/item_seasoning_weight.xml index dd9f1bf..b598f84 100644 --- a/app/src/main/res/layout/item_seasoning_weight.xml +++ b/app/src/main/res/layout/item_seasoning_weight.xml @@ -4,8 +4,10 @@ android:layout_height="60dp" android:gravity="center_vertical" android:orientation="horizontal" - android:paddingStart="16dp" - android:paddingEnd="16dp"> + android:background="@drawable/shape_scale_cell" + android:paddingHorizontal="16dp" + android:layout_marginHorizontal="4dp" + android:layout_marginVertical="4dp">