From 292fdade81655b5be105cb6c54fb47e283e34453 Mon Sep 17 00:00:00 2001 From: lvmeng <848755140@qq.com> Date: Tue, 19 May 2026 11:15:33 +0800 Subject: [PATCH] =?UTF-8?q?feat(ui):=20=E6=B7=BB=E5=8A=A0=E7=94=A8?= =?UTF-8?q?=E6=96=99=E6=98=8E=E7=BB=86=E9=A2=84=E8=A7=88=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=E5=92=8C=E6=B8=85=E7=A9=BA=E6=95=B0=E6=8D=AE=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E5=AF=B9=E8=AF=9D=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在 SubmitFoodActivity 中添加右侧图标显示并实现点击打开用料明细预览弹窗 - 新增 GoodsPreviewDialog 用于展示底部弹出的用料明细列表 - 创建 GoodsPreviewAdapter 和相关布局文件实现用料列表展示 - 添加 ic_list_view 图标用于右上角按钮 - 在 VectorCollectionFragment 中为清空数据按钮添加确认对话框 - 优化 WeightUtil 工具类添加可用性检查避免异常调用 --- .../dish/match/adapter/GoodsPreviewAdapter.kt | 46 +++++++ .../dish/match/dialog/GoodsPreviewDialog.kt | 80 ++++++++++++ .../dish/match/ui/SubmitFoodActivity.kt | 24 +++- .../ui/fragment/VectorCollectionFragment.kt | 10 +- .../com/shuwei/dish/match/utils/WeightUtil.kt | 2 + app/src/main/res/drawable/ic_list_view.xml | 12 ++ .../main/res/layout/dialog_goods_preview.xml | 114 ++++++++++++++++++ .../main/res/layout/item_goods_preview.xml | 69 +++++++++++ 8 files changed, 354 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/shuwei/dish/match/adapter/GoodsPreviewAdapter.kt create mode 100644 app/src/main/java/com/shuwei/dish/match/dialog/GoodsPreviewDialog.kt create mode 100644 app/src/main/res/drawable/ic_list_view.xml create mode 100644 app/src/main/res/layout/dialog_goods_preview.xml create mode 100644 app/src/main/res/layout/item_goods_preview.xml diff --git a/app/src/main/java/com/shuwei/dish/match/adapter/GoodsPreviewAdapter.kt b/app/src/main/java/com/shuwei/dish/match/adapter/GoodsPreviewAdapter.kt new file mode 100644 index 0000000..67e910e --- /dev/null +++ b/app/src/main/java/com/shuwei/dish/match/adapter/GoodsPreviewAdapter.kt @@ -0,0 +1,46 @@ +package com.shuwei.dish.match.adapter + +import android.annotation.SuppressLint +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.shuwei.dish.match.databinding.ItemGoodsPreviewBinding +import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity + +/** + * 用料明细预览列表适配器 + * 显示字段:foodId、goodsId、goodsCode、goodsName、materialType、useWeight + */ +class GoodsPreviewAdapter( + private val list: List +) : RecyclerView.Adapter() { + + inner class VH(val binding: ItemGoodsPreviewBinding) : RecyclerView.ViewHolder(binding.root) + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH { + val binding = ItemGoodsPreviewBinding.inflate( + LayoutInflater.from(parent.context), parent, false + ) + return VH(binding) + } + + @SuppressLint("SetTextI18n") + override fun onBindViewHolder(holder: VH, position: Int) { + val item = list[position] + holder.binding.run { + tvGoodsId.text = item.goodsId + tvGoodsCode.text = item.goodsCode.orEmpty() + tvGoodsName.text = item.goodsName.orEmpty() + // materialType:1主料 2辅料 3调料 + tvMaterialType.text = when (item.materialType) { + 1 -> "主料" + 2 -> "辅料" + 3 -> "调料" + else -> "${item.materialType}" + } + tvUseWeight.text = "${item.useWeight ?: 0.0}g" + } + } + + override fun getItemCount() = list.size +} diff --git a/app/src/main/java/com/shuwei/dish/match/dialog/GoodsPreviewDialog.kt b/app/src/main/java/com/shuwei/dish/match/dialog/GoodsPreviewDialog.kt new file mode 100644 index 0000000..1c3b7bb --- /dev/null +++ b/app/src/main/java/com/shuwei/dish/match/dialog/GoodsPreviewDialog.kt @@ -0,0 +1,80 @@ +package com.shuwei.dish.match.dialog + +import android.graphics.Rect +import android.view.KeyboardShortcutGroup +import android.view.LayoutInflater +import android.view.Menu +import android.view.MotionEvent +import android.view.ViewGroup +import androidx.recyclerview.widget.LinearLayoutManager +import com.google.android.material.bottomsheet.BottomSheetDialog +import com.shuwei.dish.match.R +import com.shuwei.dish.match.adapter.GoodsPreviewAdapter +import com.shuwei.dish.match.databinding.DialogGoodsPreviewBinding +import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity +import com.shuwei.dish.match.utils.ext.gone +import com.shuwei.dish.match.utils.ext.visible + +/** + * 用料明细预览弹窗,以 BottomSheetDialog 形式展示当前 goodsList + * @param context 宿主 Context(Activity) + * @param goodsList 需要展示的物品列表 + */ +class GoodsPreviewDialog( + context: android.content.Context, + private val goodsList: List +) : BottomSheetDialog(context, R.style.BottomSheet) { + + private val binding = DialogGoodsPreviewBinding.inflate(LayoutInflater.from(context)) + + init { + setContentView(binding.root) + setCancelable(true) + window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + + binding.rvGoodsList.run { + layoutManager = LinearLayoutManager(context) + adapter = GoodsPreviewAdapter(goodsList) + } + // foodId 对同一菜品所有条目相同,统一显示在列表上方 + val foodId = goodsList.firstOrNull()?.foodId.orEmpty() + binding.tvFoodId.text = "菜品ID:${foodId.ifEmpty { "-" }}" + if (goodsList.isEmpty()) { + binding.rvGoodsList.gone() + binding.tvEmpty.visible() + } + } + + /** 弹出时注入 Window.Callback,解决 RecyclerView 与 BottomSheet 拖拽的滑动冲突 */ + override fun show() { + super.show() + val originalCallback = window?.callback ?: return + window?.callback = object : android.view.Window.Callback by originalCallback { + override fun dispatchTouchEvent(event: MotionEvent): Boolean { + when (event.actionMasked) { + MotionEvent.ACTION_DOWN -> { + val rect = Rect() + binding.rvGoodsList.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?, + menu: Menu?, + deviceId: Int + ) { + originalCallback.onProvideKeyboardShortcuts(data, menu, deviceId) + } + } + } +} 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 fef7b3e..081e934 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 @@ -18,6 +18,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.dialog.CommonDialog +import com.shuwei.dish.match.dialog.GoodsPreviewDialog import com.shuwei.dish.match.db.entity.CookFoodEntity import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity import com.shuwei.dish.match.model.FoodRecord @@ -30,7 +31,6 @@ import com.shuwei.dish.match.utils.WeightUtil import com.shuwei.dish.match.utils.ext.appendText import com.shuwei.dish.match.utils.ext.buildSpannableString 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 @@ -128,7 +128,14 @@ class SubmitFoodActivity : BaseActivity() { }, titleAction = { it.text = food?.foodName }, rightIconAction = { - it.gone() + it.visible() + it.setImageResource(R.drawable.ic_list_view) + it.setOnClickListener { + lifecycleScope.launch { + val list = buildPreviewGoodsList() + GoodsPreviewDialog(this@SubmitFoodActivity, list).show() + } + } }, backAction = { it.setOnClickListener { remindSaveDataDialog() @@ -492,6 +499,19 @@ class SubmitFoodActivity : BaseActivity() { } + /** + * 构建用于预览弹窗的 goodsList: + * 取 goodsList 中的主辅材,再用 adapter 中最新调料覆盖原有调料数据(materialType==3) + * 调料的完整字段(含 goodsCode)通过 buildSeasoningEntity 从 DB 补全 + */ + private suspend fun buildPreviewGoodsList(): List { + val base = goodsList?.filter { it.materialType != 3 }?.toMutableList() ?: mutableListOf() + seasoningAdapter.items + .filter { it.useWeight > 0.0 } + .forEach { base.add(buildSeasoningEntity(it)) } + return base + } + override fun onDestroy() { WeightUtil.removeWeightListener(TAG) super.onDestroy() diff --git a/app/src/main/java/com/shuwei/dish/match/ui/fragment/VectorCollectionFragment.kt b/app/src/main/java/com/shuwei/dish/match/ui/fragment/VectorCollectionFragment.kt index 244485f..e3d5607 100644 --- a/app/src/main/java/com/shuwei/dish/match/ui/fragment/VectorCollectionFragment.kt +++ b/app/src/main/java/com/shuwei/dish/match/ui/fragment/VectorCollectionFragment.kt @@ -32,6 +32,7 @@ import com.shuwei.dish.match.databinding.FragmentVectorCollectionBinding import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding import com.shuwei.dish.match.dialog.Loading +import com.shuwei.dish.match.dialog.CommonDialog import com.shuwei.dish.match.model.FoodCollectionBean import com.shuwei.dish.match.model.GoodsItem import com.shuwei.dish.match.net.UiState @@ -299,7 +300,14 @@ class VectorCollectionFragment : BaseFragment() } takePhoto() } - binding.btnClearData.setOnClickListener { clearData() } + binding.btnClearData.setOnClickListener { + CommonDialog(requireContext()) + .setTitle("清空确认") + .setContent("确认清空所有已采集的图片数据?") + .setNegativeButton("取消") + .setPositiveButton("确认") { clearData() } + .show() + } binding.rvSearchFood.let { it.layoutManager = GridLayoutManager(context, 2) it.adapter = searchAdapter diff --git a/app/src/main/java/com/shuwei/dish/match/utils/WeightUtil.kt b/app/src/main/java/com/shuwei/dish/match/utils/WeightUtil.kt index 82b84e2..e013221 100644 --- a/app/src/main/java/com/shuwei/dish/match/utils/WeightUtil.kt +++ b/app/src/main/java/com/shuwei/dish/match/utils/WeightUtil.kt @@ -72,6 +72,7 @@ object WeightUtil { } fun getWeight() { + if (!isAvailable) return try { Weigher2.getWeight() } catch (e: Exception) { @@ -95,6 +96,7 @@ object WeightUtil { } fun tareTwo(address: Int) { + if (!isAvailable) return try { Log.d(TAG, "tareTwo,执行清零操作: address=$address") // SDK 内部自动管理总线,直接发送清零命令 diff --git a/app/src/main/res/drawable/ic_list_view.xml b/app/src/main/res/drawable/ic_list_view.xml new file mode 100644 index 0000000..4f3a829 --- /dev/null +++ b/app/src/main/res/drawable/ic_list_view.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/dialog_goods_preview.xml b/app/src/main/res/layout/dialog_goods_preview.xml new file mode 100644 index 0000000..b800bed --- /dev/null +++ b/app/src/main/res/layout/dialog_goods_preview.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/item_goods_preview.xml b/app/src/main/res/layout/item_goods_preview.xml new file mode 100644 index 0000000..cddb6da --- /dev/null +++ b/app/src/main/res/layout/item_goods_preview.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + +