feat(activity): 合并采集功能至 PrepareCookActivity 并优化识别页重量处理逻辑

- 将 DishSamplingActivity 逻辑合并至 PrepareCookActivity,根据 cookMode 区分采集/制作模式
- 布局替换:activity_prepare_cook 第一子 View 改为搜索栏(etInputDish + ivDishSearch),删除第二个子 LinearLayout
- InitActivity / HomeActivity / SamplingListActivity 改用 PrepareCookActivity 替代 DishSamplingActivity
- FoodRecognizeActivity 新增 selectedPosition 字段,避免通过 isClicked 线性查找索引
- 优化重量更新逻辑:重量增加立即同步,重量减少延迟 3 秒更新,防止关页前误覆盖用量
- foodSelectCallback 改为累加同 goodsId 的 useWeight,不再限制重复添加

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-20 18:26:20 +08:00
co-authored by Claude Sonnet 4.6
parent 72ecc8fcd6
commit 82217b4fb1
13 changed files with 312 additions and 405 deletions
@@ -9,7 +9,9 @@ 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.ListItemDishCookBinding import com.shuwei.dish.match.databinding.ListItemDishCookBinding
import com.shuwei.dish.match.entity.CookFoodGoodsEntity import com.shuwei.dish.match.entity.CookFoodGoodsEntity
import com.shuwei.dish.match.utils.ext.gone
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
import com.shuwei.dish.match.utils.ext.visible
import java.text.DecimalFormat import java.text.DecimalFormat
class DishPartAdapter(list: MutableList<CookFoodGoodsEntity>) : class DishPartAdapter(list: MutableList<CookFoodGoodsEntity>) :
@@ -36,12 +38,16 @@ class DishPartAdapter(list: MutableList<CookFoodGoodsEntity>) :
if (item.isSamplingPage) R.color.black999 else R.color.dish_green if (item.isSamplingPage) R.color.black999 else R.color.dish_green
) )
) )
ivOperateIcon.run {
if (item.isSamplingPage) gone() else visible()
}
ivClearIcon.visible()
ivClearIcon.setImageResource(
if (item.isOriginalData) R.drawable.ic_dish_clear
else R.drawable.ic_delete
)
ivOperateIcon.setImageResource( ivOperateIcon.setImageResource(
if (item.isSamplingPage)
//采集页面
R.drawable.ic_delete
else
//制作页面
if (item.isSetFinished) R.drawable.ic_dish_selected if (item.isSetFinished) R.drawable.ic_dish_selected
else R.drawable.ic_dish_unselected else R.drawable.ic_dish_unselected
) )
@@ -53,5 +59,4 @@ class DishPartAdapter(list: MutableList<CookFoodGoodsEntity>) :
} }
} }
} }
} }
@@ -9,6 +9,9 @@ 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.ListItemSearchGoodsInfoBinding import com.shuwei.dish.match.databinding.ListItemSearchGoodsInfoBinding
import com.shuwei.dish.match.entity.CookFoodGoodsEntity import com.shuwei.dish.match.entity.CookFoodGoodsEntity
import com.shuwei.dish.match.utils.ext.gone
import com.shuwei.dish.match.utils.ext.roundedDecimalPlace
import com.shuwei.dish.match.utils.ext.visible
class GoodsInfoSearchAdapter(private var list: MutableList<CookFoodGoodsEntity>) : class GoodsInfoSearchAdapter(private var list: MutableList<CookFoodGoodsEntity>) :
BaseQuickAdapter<CookFoodGoodsEntity, GoodsInfoSearchAdapter.VH>(list) { BaseQuickAdapter<CookFoodGoodsEntity, GoodsInfoSearchAdapter.VH>(list) {
@@ -18,20 +21,29 @@ class GoodsInfoSearchAdapter(private var list: MutableList<CookFoodGoodsEntity>)
position: Int, position: Int,
item: CookFoodGoodsEntity? item: CookFoodGoodsEntity?
) { ) {
item ?: return
holder.binding.tvGoodsInfo.run { holder.binding.tvGoodsInfo.run {
text = item?.goodsName text = item.goodsName
setBackgroundResource( setBackgroundResource(
if (item?.isClicked == true) R.drawable.shape_green_stroke if (item.isClicked == true) R.drawable.shape_green_stroke
else R.drawable.shape_white_12_corners else R.drawable.shape_white_12_corners
) )
setTextColor( setTextColor(
ContextCompat.getColor( ContextCompat.getColor(
context, context,
if (item?.isClicked == true) R.color.dish_green if (item.isClicked == true) R.color.dish_green
else R.color.black666 else R.color.black666
) )
) )
} }
if (item.foodScore == -1){
holder.binding.tvFoodScore.gone()
} else {
holder.binding.tvFoodScore.let {
it.visible()
it.text = "${(item.foodScore / 100.0).roundedDecimalPlace(2)}%"
}
}
} }
override fun onCreateViewHolder( override fun onCreateViewHolder(
@@ -86,4 +86,7 @@ class CookFoodGoodsEntity(
//true-原始数据,false-非原始数据 //true-原始数据,false-非原始数据
@Ignore @Ignore
var isOriginalData: Boolean = true var isOriginalData: Boolean = true
@Ignore
var foodScore: Int = -1
} }
@@ -16,6 +16,7 @@ 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.visible import com.shuwei.dish.match.utils.ext.visible
import androidx.core.net.toUri
/** /**
* 食材识别结果页面 * 食材识别结果页面
@@ -71,12 +72,25 @@ class FoodRecognizeActivity : BaseActivity() {
private val list = mutableListOf<CookFoodGoodsEntity>() private val list = mutableListOf<CookFoodGoodsEntity>()
/** 当前选中的列表位置,-1 表示无选中 */
private var selectedPosition = -1
/** 秤1当前实时重量 */
private var currentWeight = 0.0
/** 重量减少时延迟更新的任务,页面关闭前取消可防止用错误重量 */
private var pendingWeightRunnable: Runnable? = null
/** 当前待延迟更新的目标重量,避免相同重量重复重置计时器 */
private var pendingWeight = 0.0
private val adapter = GoodsInfoSearchAdapter(list).apply { private val adapter = GoodsInfoSearchAdapter(list).apply {
setOnItemClickListener { _, _, position -> setOnItemClickListener { _, _, position ->
// 更新选中状态
list.forEachIndexed { i, item -> item.isClicked = (i == position) } list.forEachIndexed { i, item -> item.isClicked = (i == position) }
// 点击选择时记录当前秤重量
list[position].useWeight = currentWeight
notifyDataSetChanged() notifyDataSetChanged()
// 同步更新选中食材名称 selectedPosition = position
binding.tvSelectedFood.text = list[position].goodsName ?: "-" binding.tvSelectedFood.text = list[position].goodsName ?: "-"
} }
} }
@@ -85,6 +99,7 @@ class FoodRecognizeActivity : BaseActivity() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
binding = ActivityFoodRecognizeBinding.inflate(layoutInflater) binding = ActivityFoodRecognizeBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
registerWeightListener()
setHeaderBackground() setHeaderBackground()
// 显示标题栏 // 显示标题栏
@@ -93,7 +108,6 @@ class FoodRecognizeActivity : BaseActivity() {
initData() initData()
initRecyclerView() initRecyclerView()
initClickListeners() initClickListeners()
registerWeightListener()
} }
/** /**
@@ -103,7 +117,7 @@ class FoodRecognizeActivity : BaseActivity() {
// 加载食材照片 // 加载食材照片
val imageUri = intent.getStringExtra(EXTRA_IMAGE_URI) val imageUri = intent.getStringExtra(EXTRA_IMAGE_URI)
if (!imageUri.isNullOrBlank()) { if (!imageUri.isNullOrBlank()) {
binding.ivFoodPhoto.setImageURI(Uri.parse(imageUri)) binding.ivFoodPhoto.setImageURI(imageUri.toUri())
} }
// 取出内存缓存的食材列表,取用后立即清空 // 取出内存缓存的食材列表,取用后立即清空
@@ -111,6 +125,7 @@ class FoodRecognizeActivity : BaseActivity() {
if (!goodsList.isNullOrEmpty()) { if (!goodsList.isNullOrEmpty()) {
list.addAll(goodsList) list.addAll(goodsList)
// 默认选中第一项 // 默认选中第一项
selectedPosition = 0
list[0].isClicked = true list[0].isClicked = true
binding.tvSelectedFood.text = list[0].goodsName ?: "-" binding.tvSelectedFood.text = list[0].goodsName ?: "-"
} }
@@ -144,14 +159,11 @@ class FoodRecognizeActivity : BaseActivity() {
private fun initClickListeners() { private fun initClickListeners() {
// 更换食材:打开食材搜索弹窗 // 更换食材:打开食材搜索弹窗
binding.btnChangeFood.clickWithDebounce { binding.btnChangeFood.clickWithDebounce {
val currentName = if (list.isNotEmpty()) list.firstOrNull { it.isClicked }?.goodsName else null val currentName = list.getOrNull(selectedPosition)?.goodsName
FoodSearchDialog( FoodSearchDialog(
activity = this, activity = this,
defGoodsName = currentName, defGoodsName = currentName,
onItemSelected = { item -> onItemSelected = { item -> updateSelectedFood(item) }
// 用搜索结果替换当前选中食材
updateSelectedFood(item)
}
).show() ).show()
} }
@@ -164,17 +176,14 @@ class FoodRecognizeActivity : BaseActivity() {
*/ */
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun updateSelectedFood(item: CookFoodGoodsEntity) { private fun updateSelectedFood(item: CookFoodGoodsEntity) {
item.isClicked = true
val clickedIndex = list.indexOfFirst { it.isClicked && it.goodsId != item.goodsId }
if (clickedIndex >= 0) {
list[clickedIndex].isClicked = false
}
// 若列表中已存在则直接选中,否则插入到首位
val existIndex = list.indexOfFirst { it.goodsId == item.goodsId } val existIndex = list.indexOfFirst { it.goodsId == item.goodsId }
if (existIndex >= 0) { if (existIndex >= 0) {
list.forEachIndexed { i, e -> e.isClicked = (i == existIndex) } list.forEachIndexed { i, e -> e.isClicked = (i == existIndex) }
selectedPosition = existIndex
} else { } else {
list.add(0, item) list.add(0, item)
list.forEachIndexed { i, e -> e.isClicked = (i == 0) }
selectedPosition = 0
} }
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
binding.tvSelectedFood.text = item.goodsName ?: "-" binding.tvSelectedFood.text = item.goodsName ?: "-"
@@ -183,22 +192,55 @@ class FoodRecognizeActivity : BaseActivity() {
/** /**
* 注册秤1重量监听 * 注册秤1重量监听
* 只有重量高于识别阈值时才更新选中食材的 useWeight,
* 低于阈值说明食材已被取走,保留上次有效值等待页面关闭
*/ */
private fun registerWeightListener() { private fun registerWeightListener() {
WeightUtil.addWeightListener(TAG) { address, _, weight -> WeightUtil.addWeightListener(TAG) { address, state, weight ->
if (address == AddressUtil.ONE) { if (address == AddressUtil.ONE && state == WeightUtil.STATE_STABLE) {
runOnUiThread { runOnUiThread {
binding.tvWeight.text = "$weight g" currentWeight = weight
binding.tvWeight.run {
if (tag != weight) {
text = "$weight g"
tag = weight
}
}
if (weight >= PrepareCookActivity.WEIGHT_RECOGNIZE_VALUE) {
adapter.items.firstOrNull { it.isClicked }?.let { item ->
if (weight > (item.useWeight ?: 0.0)) {
// 重量增加:立即更新
cancelPendingWeightUpdate()
item.useWeight = currentWeight
} else if (pendingWeight != weight) {
// 重量减少且目标值变化:重置延迟任务,3 秒无新变化后更新
cancelPendingWeightUpdate()
pendingWeight = weight
pendingWeightRunnable = Runnable {
item.useWeight = weight
pendingWeightRunnable = null
}.also { handler.postDelayed(it, 3000) }
}
}
}
} }
} }
} }
} }
/**
* 取消待执行的延迟重量更新任务
*/
private fun cancelPendingWeightUpdate() {
pendingWeightRunnable?.let { handler.removeCallbacks(it) }
pendingWeightRunnable = null
}
/** /**
* 携带当前选中食材关闭页面 * 携带当前选中食材关闭页面
*/ */
private fun finishWithResult() { private fun finishWithResult() {
val selected = list.firstOrNull { it.isClicked } val selected = list.getOrNull(selectedPosition)
val intent = Intent().apply { val intent = Intent().apply {
selected?.let { putExtra(EXTRA_SELECTED_ITEM, it) } selected?.let { putExtra(EXTRA_SELECTED_ITEM, it) }
} }
@@ -208,6 +250,7 @@ class FoodRecognizeActivity : BaseActivity() {
override fun onDestroy() { override fun onDestroy() {
super.onDestroy() super.onDestroy()
WeightUtil.removeWeightListener(TAG) cancelPendingWeightUpdate()
// WeightUtil.removeWeightListener(TAG)
} }
} }
@@ -158,8 +158,8 @@ class HomeActivity : BaseActivity() {
return@countCookFood return@countCookFood
} }
//无烹饪数据打开新增采样页面 //无烹饪数据打开新增采样页面
startActivity<DishSamplingActivity> { startActivity<PrepareCookActivity> {
putExtra(DishSamplingActivity.PAGE_FROM, DishSamplingActivity.HOME) putExtra(PrepareCookActivity.PAGE_FROM, PrepareCookActivity.HOME)
} }
finish() finish()
} }
@@ -113,8 +113,8 @@ class InitActivity : BaseActivity() {
return@countCookFood return@countCookFood
} }
//无烹饪数据打开新增采样页面 //无烹饪数据打开新增采样页面
startActivity<DishSamplingActivity> { startActivity<PrepareCookActivity> {
putExtra(DishSamplingActivity.PAGE_FROM, DishSamplingActivity.HOME) putExtra(PrepareCookActivity.PAGE_FROM, PrepareCookActivity.HOME)
} }
} }
} }
@@ -1,31 +1,35 @@
package com.shuwei.dish.match.ui package com.shuwei.dish.match.ui
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.graphics.Typeface import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.View
import android.view.ViewGroup
import androidx.activity.addCallback
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.shuwei.dish.match.R import com.shuwei.dish.match.R
import com.shuwei.dish.match.adapter.DishPartAdapter import com.shuwei.dish.match.adapter.DishPartAdapter
import com.shuwei.dish.match.base.BaseActivity import com.shuwei.dish.match.base.BaseActivity
import com.shuwei.dish.match.databinding.ActivityPrepareCookBinding import com.shuwei.dish.match.databinding.ActivityPrepareCookBinding
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.dialog.FoodSearchDialog import com.shuwei.dish.match.dialog.FoodSearchDialog
import com.shuwei.dish.match.entity.CookFoodEntity import com.shuwei.dish.match.entity.CookFoodEntity
import com.shuwei.dish.match.entity.CookFoodGoodsEntity import com.shuwei.dish.match.entity.CookFoodGoodsEntity
import com.shuwei.dish.match.entity.FoodRecord import com.shuwei.dish.match.entity.FoodRecord
import android.view.ViewGroup
import androidx.activity.addCallback
import androidx.lifecycle.lifecycleScope
import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding
import com.shuwei.dish.match.objbox.FoodModule import com.shuwei.dish.match.objbox.FoodModule
import com.shuwei.dish.match.utils.AddressUtil import com.shuwei.dish.match.utils.AddressUtil
import com.shuwei.dish.match.utils.CameraUtils import com.shuwei.dish.match.utils.CameraUtils
import com.shuwei.dish.match.utils.ImageUtil import com.shuwei.dish.match.utils.ImageUtil
import com.shuwei.dish.match.utils.KeyboardUtil
import com.shuwei.dish.match.utils.SpTool
import com.shuwei.dish.match.utils.SwipeCallback import com.shuwei.dish.match.utils.SwipeCallback
import com.shuwei.dish.match.utils.WeightUtil import com.shuwei.dish.match.utils.WeightUtil
import com.shuwei.dish.match.utils.ext.addOnActionSearchListener
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.roundedDecimalPlace import com.shuwei.dish.match.utils.ext.roundedDecimalPlace
@@ -46,6 +50,9 @@ class PrepareCookActivity : BaseActivity() {
companion object { companion object {
const val TAG = "CookActivity" const val TAG = "CookActivity"
const val FOOD_ITEM = "foodItem" const val FOOD_ITEM = "foodItem"
const val FOOD_NAME = "foodName"
const val PAGE_FROM = "pageFrom"
const val HOME = "home"
const val WEIGHT_CHANGE_VALUE = 5 const val WEIGHT_CHANGE_VALUE = 5
const val WEIGHT_RECOGNIZE_VALUE = 10 const val WEIGHT_RECOGNIZE_VALUE = 10
} }
@@ -56,6 +63,12 @@ class PrepareCookActivity : BaseActivity() {
private var food: FoodRecord? = null private var food: FoodRecord? = null
/** 采集模式下通过搜索页回填的 foodId */
private var foodId: String? = null
/** 来源页面标识,HOME 时返回跳转 SamplingListActivity */
private var pageFrom: String? = null
private var goodsList: MutableList<CookFoodGoodsEntity>? = null private var goodsList: MutableList<CookFoodGoodsEntity>? = null
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
@@ -64,100 +77,104 @@ class PrepareCookActivity : BaseActivity() {
binding = ActivityPrepareCookBinding.inflate(layoutInflater) binding = ActivityPrepareCookBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
setHeaderBackground() setHeaderBackground()
pageFrom = intent.getStringExtra(PAGE_FROM)
food = intent.extras?.getSerializable(FOOD_ITEM) as FoodRecord?
val isSamplingMode = SpTool.cookMode == 1
val titleText = if (isSamplingMode) "菜品采集" else "菜品制作"
setTitleBar(titleBarAction = { setTitleBar(titleBarAction = {
it.visible() it.visible()
}, titleAction = { }, titleAction = {
it.text = "菜品制作" it.text = titleText
}, rightIconActon = { }, rightIconActon = {
it.gone() it.gone()
it.setImageResource(R.drawable.ic_setting)
it.setOnClickListener {
//startActivity<DeviceSettingActivity>()
}
}, backAction = { }, backAction = {
it.setOnClickListener { it.setOnClickListener {
onBackPressedDispatcher.onBackPressed() onBackPressedDispatcher.onBackPressed()
} }
}) })
food = intent.extras?.getSerializable(FOOD_ITEM) as FoodRecord?
binding.tvDishName.text = food?.foodName ?: "" // 根据 cookMode 设置搜索栏可编辑性
if (isSamplingMode) {
// 采集模式:可编辑,支持搜索
val foodName = intent.getStringExtra(FOOD_NAME)
binding.etInputDish.setText(foodName ?: food?.foodName ?: "")
binding.ivDishSearch.visible()
} else {
// 制作模式:不可编辑,仅展示菜名
binding.etInputDish.setText(food?.foodName ?: "")
binding.etInputDish.isFocusable = false
binding.etInputDish.isFocusableInTouchMode = false
binding.ivDishSearch.gone()
}
addViewClickListener() addViewClickListener()
addBackKeyListener() addBackKeyListener()
initCamera(binding.flCameraContainer) initCamera(binding.flCameraContainer)
initRecyclerView() initRecyclerView()
getDishDetail() if (!isSamplingMode) {
getDishDetail()
}
} }
private fun addViewClickListener() { private fun addViewClickListener() {
WeightUtil.addWeightListener( WeightUtil.addWeightListener(
weightKey = TAG, weightKey = TAG,
getWeight = { address, state, weight -> getWeight = { address, state, weight ->
//Log.d(TAG, "addViewClickListener: address=$address,state=$state,weight=$weight") if (address == AddressUtil.ONE && state == WeightUtil.STATE_STABLE) {
if (address == AddressUtil.ONE) { runOnUiThread {
binding.tvDishPartWeight.text = "${weight}"
if (state == WeightUtil.STATE_STABLE) {
recognizeFood(weight) recognizeFood(weight)
} }
} }
}) })
binding.ivWeightClear.setOnClickListener {
WeightUtil.tareTwo(AddressUtil.ONE) if (SpTool.cookMode == 1) {
// 采集模式:绑定搜索栏交互
binding.ivDishSearch.setOnClickListener { v -> jumpSearch(v) }
binding.etInputDish.addOnActionSearchListener { jumpSearch(binding.etInputDish) }
} }
binding.ivWeightAdd.setOnClickListener { addWeight() }
binding.tvAddFood.clickWithDebounce { addFood() }
binding.btnCook.clickWithDebounce { binding.btnCook.clickWithDebounce {
val count = list.count { it.isSetFinished.not() } if (SpTool.cookMode == 1) {
if (count > 0) { // 采集模式:从输入框创建 FoodRecord
showRemindDialog() val showFoodName = binding.etInputDish.text.toString().trim()
return@clickWithDebounce if (showFoodName.isBlank()) {
toast("菜品名称为空")
return@clickWithDebounce
}
if (list.isEmpty()) {
toast("菜品构成信息未设置")
return@clickWithDebounce
}
val foodRecord = FoodRecord()
binding.etInputDish.let {
if (it.tag != null && it.tag.toString() == it.text.toString()) {
foodRecord.foodId = foodId
}
}
foodRecord.foodName = showFoodName
foodRecord.cookMode = 1
Log.d(TAG, "goToSubmit: goodsList:${list.toJsonString()}")
startActivity<SubmitFoodActivity> {
putExtra(SubmitFoodActivity.GOODS_LIST, list as Serializable)
putExtra(SubmitFoodActivity.FOOD_ITEM, foodRecord as Serializable)
}
} else {
// 制作模式:检查食材是否全部设置完成
val count = list.count { it.isSetFinished.not() }
if (count > 0) {
showRemindDialog()
return@clickWithDebounce
}
openSubmitPage()
} }
openSubmitPage()
}
binding.rgCook.setOnCheckedChangeListener { group, checkedId ->
if (clickIndex < 0 || clickIndex >= list.size) return@setOnCheckedChangeListener
val tempType =
if (checkedId == R.id.rbDishTypeFirst) 1 else if (checkedId == R.id.rbDishTypeSecond) 2 else -1
list[clickIndex].materialType = tempType
dishPartAdapter.notifyItemChanged(clickIndex)
binding.tvDishType.text =
if (tempType == 1) "主材" else if (tempType == 2) "辅材" else ""
}
}
/**
* 添加重量信息到食材数据
*/
private fun addWeight() {
if (clickIndex == -1) {
toast("请选择菜品构成")
return
}
val clickItem = list[clickIndex]
clickItem.run {
if (isNewDishType && materialType != 1 && materialType != 2) {
toast("请选择主辅材类型")
return
}
}
val weight = binding.tvDishPartWeight.text.toString().toDouble()
if (weight <= 0.toDouble()) {
toast("食材用量需要大于0")
return
}
Log.d(TAG, "addViewClickListener->useRealWeight=$weight")
clickItem.run {
useWeight = weight
isOriginalData = false
isSetFinished = true
dishPartAdapter.notifyItemChanged(clickIndex)
} }
} }
private val isTakingPhoto = AtomicBoolean(false) private val isTakingPhoto = AtomicBoolean(false)
private var isRecognizeOpen = false private var isRecognizeOpen = false
// 页面可见时允许识别,onPause 后禁止,onResume 后恢复 // 页面可见时允许识别,onPause 后禁止,onResume 后恢复
private var isRecognizeEnabled = true private var isRecognizeEnabled = true
private var lastPhotoUri: Uri? = null private var lastPhotoUri: Uri? = null
@@ -185,33 +202,24 @@ class PrepareCookActivity : BaseActivity() {
/** /**
* 菜品选择回调 * 菜品选择回调
* - list 中不含该 goodsId:直接新增,isNewDishType = true
* - list 中已含该 goodsId:累加 useWeight
*/ */
private val foodSelectCallback: (CookFoodGoodsEntity) -> Unit = foodSelectCallback@{ item -> private val foodSelectCallback: (CookFoodGoodsEntity) -> Unit = { item ->
val filterResult = list.firstOrNull { it.goodsId == item.goodsId } val existing = list.firstOrNull { it.goodsId == item.goodsId }
if (filterResult != null) { if (existing != null) {
toast("不允许重复添加同一食材") existing.useWeight = (existing.useWeight ?: 0.0) + (item.useWeight ?: 0.0)
return@foodSelectCallback existing.isSetFinished = true
dishPartAdapter.notifyItemChanged(list.indexOf(existing))
} else {
list.add(item.also {
it.isNewDishType = true
it.isSetFinished = true
})
val position = list.size - 1
dishPartAdapter.notifyItemInserted(position)
binding.rvDishPartList.smoothScrollToPosition(position)
} }
list.add(CookFoodGoodsEntity().apply {
goodsId = item.goodsId
goodsName = item.goodsName
// materialType =
isNewDishType = true
isOriginalData = false
useWeight = lastWeight
isSetFinished = true
})
val positon = list.size - 1
dishPartAdapter.notifyItemInserted(positon)
onFoodItemClick(positon)
binding.rvDishPartList.smoothScrollToPosition(positon)
}
/**
* 添加食材
*/
private fun addFood() {
FoodSearchDialog(activity = this, onItemSelected = foodSelectCallback).show()
} }
private fun openSubmitPage() { private fun openSubmitPage() {
@@ -307,9 +315,12 @@ class PrepareCookActivity : BaseActivity() {
private var firstReqSize = 0 private var firstReqSize = 0
private val list = mutableListOf<CookFoodGoodsEntity>() private val list = mutableListOf<CookFoodGoodsEntity>()
private val dishPartAdapter by lazy { private val dishPartAdapter by lazy {
DishPartAdapter(list).apply { DishPartAdapter(list = list).apply {
setOnItemClickListener { _, _, positon -> setOnItemClickListener { _, _, positon ->
onFoodItemClick(positon) list.forEachIndexed { index, entity ->
entity.isItemClicked = index == positon
}
notifyDataSetChanged()
} }
addOnItemChildClickListener(R.id.ivClearIcon) { _, _, positon -> addOnItemChildClickListener(R.id.ivClearIcon) { _, _, positon ->
Log.d(TAG, "onFoodItemClick: ${list[positon].toJsonString()}") Log.d(TAG, "onFoodItemClick: ${list[positon].toJsonString()}")
@@ -327,52 +338,6 @@ class PrepareCookActivity : BaseActivity() {
} }
} }
/**
* 菜品列表item点击
*/
private fun onFoodItemClick(positon: Int) {
this@PrepareCookActivity.clickIndex = positon
list[clickIndex].let { it ->
binding.tvDishShowName.run {
text = it.goodsName
setTypeface(typeface, Typeface.BOLD)
}
var materialType: String
when (it.materialType) {
1 -> {
materialType = "主材"
binding.rgCook.check(R.id.rbDishTypeFirst)
}
2 -> {
materialType = "辅材"
binding.rgCook.check(R.id.rbDishTypeSecond)
}
else -> {
materialType = ""
binding.rgCook.clearCheck()
}
}
binding.tvDishType.text = materialType
list.forEach { bean -> bean.isItemClicked = false }
it.isItemClicked = true
dishPartAdapter.notifyDataSetChanged()
if (it.isNewDishType) {
binding.dividerDishType.visible()
binding.llDishType.visible()
} else {
binding.dividerDishType.gone()
binding.llDishType.gone()
}
}
}
private var clickIndex = -1
/** /**
* RecyclerView初始化 * RecyclerView初始化
*/ */
@@ -387,14 +352,10 @@ class PrepareCookActivity : BaseActivity() {
dishPartAdapter.notifyItemChanged(position) dishPartAdapter.notifyItemChanged(position)
return@SwipeCallback return@SwipeCallback
} }
// dishPartAdapter.removeAt(position)
list.removeAt(position) list.removeAt(position)
dishPartAdapter.notifyItemRemoved(position) dishPartAdapter.notifyItemRemoved(position)
dishPartAdapter.notifyItemRangeChanged(position, list.size - position) dishPartAdapter.notifyItemRangeChanged(position, list.size - position)
toast("已删除") toast("已删除")
if (list.isEmpty()) {
binding.tvDishShowName.text = ""
}
}) })
itemTouchHelper.attachToRecyclerView(this) itemTouchHelper.attachToRecyclerView(this)
} }
@@ -428,10 +389,22 @@ class PrepareCookActivity : BaseActivity() {
*/ */
private fun addBackKeyListener() { private fun addBackKeyListener() {
onBackPressedDispatcher.addCallback(this) { onBackPressedDispatcher.addCallback(this) {
val count = list.count { !it.isOriginalData } if (SpTool.cookMode == 1) {
if (count > 0) { // 采集模式:有新增食材时提示保存
saveDataRemindDialog() if (list.isEmpty().not()) {
return@addCallback saveDataRemindDialog()
return@addCallback
}
if (pageFrom == HOME) {
startActivity<SamplingListActivity>()
}
} else {
// 制作模式:有未保存数据时提示
val count = list.count { !it.isOriginalData }
if (count > 0) {
saveDataRemindDialog()
return@addCallback
}
} }
finish() finish()
} }
@@ -443,9 +416,14 @@ class PrepareCookActivity : BaseActivity() {
private fun saveDataRemindDialog() { private fun saveDataRemindDialog() {
CommonDialog(this) CommonDialog(this)
.setTitle("温馨提示") .setTitle("温馨提示")
.setContent("您好,当前页面存在未保存的数据,确认返回吗?") .setContent("您好,当前页面存在未保存的数据,确认返回吗?")
.setNegativeButton("取消") .setNegativeButton("取消")
.setPositiveButton("确认") { finish() } .setPositiveButton("确认") {
if (SpTool.cookMode == 1 && pageFrom == HOME) {
startActivity<SamplingListActivity>()
}
finish()
}
.setOnDismissCallback { hideStatusBar() } .setOnDismissCallback { hideStatusBar() }
.show() .show()
} }
@@ -496,12 +474,16 @@ class PrepareCookActivity : BaseActivity() {
val foodList = mutableListOf<CookFoodGoodsEntity>() val foodList = mutableListOf<CookFoodGoodsEntity>()
list.forEachIndexed { index, food -> list.forEachIndexed { index, food ->
val foodName = food.name.split("WP").first() val foodName = food.name.split("WP").first()
val foodScore = ((1-food.score) * 100).roundedDecimalPlace(2) foodList.add(
foodList.add(CookFoodGoodsEntity( CookFoodGoodsEntity(
goodsId = index.toString(), goodsId = "${food.id}",
goodsName = "${foodName}-${foodScore}%", goodsName = foodName,
foodId = index.toString() foodId = index.toString()
)) ).also {
it.foodScore = ((1 - food.score) * 10000).toInt()
it.isOriginalData = false
}
)
} }
FoodRecognizeActivity.start( FoodRecognizeActivity.start(
activity = this, activity = this,
@@ -511,7 +493,26 @@ class PrepareCookActivity : BaseActivity() {
) )
isRecognizeOpen = true isRecognizeOpen = true
isTakingPhoto.set(false) isTakingPhoto.set(false)
lastWeight = currentWeight }
/**
* 跳转食物搜索页(采集模式专用)
* @param v 触发搜索的 View,用于收起键盘
*/
private fun jumpSearch(v: View) {
val intent = Intent(this, FoodSearchActivity::class.java).apply {
putExtra(FoodSearchActivity.FOOD_NAME, binding.etInputDish.text.toString().trim())
}
startActivity(intent) {
foodId = it?.getStringExtra(FoodSearchActivity.FOOD_ID)
val name = it?.getStringExtra(FoodSearchActivity.FOOD_NAME)
binding.etInputDish.run {
setText(name)
tag = name
setSelection(text.length)
}
}
KeyboardUtil.hideKeyboard(v.context, v)
} }
} }
@@ -120,8 +120,8 @@ class SamplingListActivity : BaseActivity() {
} }
return return
} }
startActivity<DishSamplingActivity> { startActivity<PrepareCookActivity> {
putExtra(DishSamplingActivity.FOOD_NAME, item.foodName) putExtra(PrepareCookActivity.FOOD_NAME, item.foodName)
} }
} }
@@ -154,7 +154,7 @@ class SamplingListActivity : BaseActivity() {
private fun addViewListener() { private fun addViewListener() {
binding.btnAddSampling.setOnClickListener { binding.btnAddSampling.setOnClickListener {
judgeDeviceConfig { judgeDeviceConfig {
startActivity<DishSamplingActivity>() startActivity<PrepareCookActivity>()
} }
} }
binding.refreshLayout.setOnRefreshListener { binding.refreshLayout.setOnRefreshListener {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 11 KiB

@@ -58,11 +58,12 @@
android:textSize="32sp" /> android:textSize="32sp" />
<!-- 更换食材 --> <!-- 更换食材 -->
<androidx.appcompat.widget.AppCompatButton <TextView
android:id="@+id/btnChangeFood" android:id="@+id/btnChangeFood"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="90dp" android:layout_height="90dp"
android:layout_marginTop="30dp" android:layout_marginTop="30dp"
android:gravity="center"
android:background="@drawable/shape_green_bg" android:background="@drawable/shape_green_bg"
android:text="更换食材" android:text="更换食材"
android:textColor="@color/white" android:textColor="@color/white"
@@ -70,12 +71,13 @@
android:textStyle="bold" /> android:textStyle="bold" />
<!-- 取消 --> <!-- 取消 -->
<androidx.appcompat.widget.AppCompatButton <TextView
android:id="@+id/btnCancel" android:id="@+id/btnCancel"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="90dp" android:layout_height="90dp"
android:layout_marginTop="30dp" android:layout_marginTop="30dp"
android:layout_marginBottom="30dp" android:layout_marginBottom="30dp"
android:gravity="center"
android:background="@drawable/shape_white_12_corners" android:background="@drawable/shape_white_12_corners"
android:text="取消" android:text="取消"
android:textColor="@color/black333" android:textColor="@color/black333"
+35 -208
View File
@@ -7,214 +7,52 @@
android:orientation="vertical" android:orientation="vertical"
tools:background="@drawable/bg_other_page"> tools:background="@drawable/bg_other_page">
<TextView
android:id="@+id/tvDishName"
android:layout_width="match_parent"
android:layout_height="120dp"
android:layout_marginStart="30dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="30dp"
android:background="@drawable/shape_white_30_corners"
android:gravity="center"
android:textColor="@color/black"
android:textSize="40sp"
android:textStyle="bold"
tools:text="雪菜烧豆腐" />
<LinearLayout <LinearLayout
android:id="@+id/llSearchBar"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="100dp"
android:layout_marginStart="30dp" android:layout_margin="30dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="30dp"
android:background="@drawable/shape_white_30_corners" android:background="@drawable/shape_white_30_corners"
android:orientation="vertical"> android:gravity="center_vertical"
android:orientation="horizontal">
<LinearLayout <EditText
android:layout_width="match_parent" android:id="@+id/etInputDish"
android:layout_height="109dp" android:layout_width="0dp"
android:gravity="center_vertical" android:layout_height="80dp"
android:orientation="horizontal"> android:layout_marginHorizontal="28dp"
android:layout_weight="1"
android:autofillHints=""
android:background="@color/white"
android:gravity="center"
android:hint="@string/dish_search_hint"
android:inputType="text"
android:imeOptions="actionSearch"
android:paddingStart="3dp"
android:paddingEnd="3dp"
android:textColor="@color/black333"
android:textColorHint="@color/gray_c8"
android:textSize="40sp"
tools:ignore="TextFields" />
<!-- <TextView--> <ImageView
<!-- android:layout_width="0dp"--> android:id="@+id/ivDishSearch"
<!-- android:layout_weight="1"--> android:layout_width="60dp"
<!-- android:layout_height="wrap_content"--> android:layout_height="60dp"
<!-- android:layout_marginStart="30dp"--> android:layout_marginStart="20dp"
<!-- android:text="食材名称"--> android:layout_marginEnd="20dp"
<!-- android:textColor="@color/black666"--> android:paddingStart="10dp"
<!-- android:textSize="28sp" />--> android:paddingEnd="10dp"
android:visibility="gone"
<TextView android:src="@drawable/ic_search_gray"
android:id="@+id/tvDishShowName" tools:ignore="ContentDescription" />
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:textColor="@color/black"
android:textSize="30sp"
android:textColorHint="@color/black666"
android:hint="食材名称"
tools:text="" />
<TextView
android:id="@+id/tvDishType"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:textColor="@color/black999"
android:textSize="26sp"
android:layout_marginEnd="30dp"
tools:text="" />
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:id="@+id/dividerDishType"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
app:dividerColor="@color/gray_eb"
android:visibility="gone"/>
<LinearLayout
android:id="@+id/llDishType"
android:layout_width="match_parent"
android:layout_height="113dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:text="@string/dish_from_type"
android:textColor="@color/black666"
android:textSize="28sp" />
<RadioGroup
android:id="@+id/rgCook"
android:layout_width="match_parent"
android:layout_height="80dp"
android:gravity="center_vertical|end"
android:orientation="horizontal">
<RadioButton
android:id="@+id/rbDishTypeFirst"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="30dp"
android:background="@color/white"
android:button="@null"
android:drawableStart="@drawable/selector_dish_type"
android:drawablePadding="30dp"
android:gravity="center"
android:paddingStart="30dp"
android:paddingEnd="30dp"
android:text="@string/dish_type_first"
android:textColor="@color/dish_type_font"
android:textSize="30sp"
android:textStyle="bold" />
<RadioButton
android:id="@+id/rbDishTypeSecond"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="30dp"
android:background="@color/white"
android:button="@null"
android:checked="false"
android:drawableStart="@drawable/selector_dish_type"
android:drawablePadding="30dp"
android:gravity="center"
android:paddingStart="30dp"
android:paddingEnd="30dp"
android:text="@string/dish_type_second"
android:textColor="@color/dish_type_font"
android:textSize="30sp"
android:textStyle="bold" />
</RadioGroup>
</LinearLayout>
<com.google.android.material.divider.MaterialDivider
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
app:dividerColor="@color/gray_eb" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginTop="40dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="30dp"
android:text="@string/dish_part_weight_remind"
android:textColor="@color/black666"
android:textSize="26sp" />
<TextView
android:id="@+id/tvDishPartWeight"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginStart="30dp"
android:layout_weight="1"
android:autofillHints=""
android:background="@drawable/shape_white_f6_10_corners"
android:gravity="center"
android:hint="-"
android:maxLines="1"
android:paddingStart="20dp"
android:paddingEnd="20dp"
android:text=""
android:textColor="@color/dish_green"
android:textColorHint="@color/gray_d6"
android:textSize="60sp"
tools:ignore="HardcodedText" />
<ImageView
android:id="@+id/ivWeightClear"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_marginStart="30dp"
android:src="@drawable/ic_weight_clear"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/ivWeightAdd"
android:layout_width="90dp"
android:layout_height="90dp"
android:layout_marginStart="30dp"
android:layout_marginEnd="30dp"
android:src="@drawable/ic_weight_add"
tools:ignore="ContentDescription" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="39dp"
android:layout_marginBottom="39dp"
android:text="@string/dish_weight_set_remind"
android:textColor="@color/black999"
android:textSize="26sp" />
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_marginStart="30dp" android:layout_marginHorizontal="30dp"
android:layout_marginTop="30dp"
android:layout_marginEnd="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">
@@ -237,17 +75,6 @@
android:textColor="@color/black666" android:textColor="@color/black666"
android:textSize="28sp" /> android:textSize="28sp" />
<TextView
android:id="@+id/tvAddFood"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end"
android:drawablePadding="16dp"
android:padding="10dp"
android:text="@string/add_food"
android:textColor="@color/dish_green"
android:textSize="26sp"
app:drawableEndCompat="@drawable/ic_food_add" />
</FrameLayout> </FrameLayout>
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
@@ -59,7 +59,7 @@
android:id="@+id/ivClearIcon" android:id="@+id/ivClearIcon"
android:layout_width="80dp" android:layout_width="80dp"
android:layout_height="60dp" android:layout_height="60dp"
android:src="@drawable/ic_dish_clear" android:src="@drawable/ic_delete"
android:layout_marginEnd="10dp" android:layout_marginEnd="10dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
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">
@@ -18,4 +18,18 @@
android:ellipsize="end" android:ellipsize="end"
android:background="@drawable/shape_white_12_corners"/> android:background="@drawable/shape_white_12_corners"/>
</LinearLayout> <TextView
android:id="@+id/tvFoodScore"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black666"
android:textSize="16sp"
android:layout_marginBottom="20dp"
android:layout_gravity="bottom|center_horizontal"
tools:text="100%"
android:maxLines="1"
android:ellipsize="end"
android:visibility="gone"/>
</FrameLayout>