refactor(entity): 新增 GoodsItem 统一物品数据模型,合并查询接口并迁移 UI 状态字段

- 新增 GoodsItem 纯数据类(DTO),整合接口字段与原 CookFoodGoodsEntity @Ignore UI 状态字段
- ApiService/RemoteRepository/NetViewModel 合并 queryGoodsList 与 querySeasoningList 为统一接口
- GoodsInfoSearchAdapter/FoodSearchAdapter/DishPartAdapter 实体类改为 GoodsItem
- FoodSearchDialog/FoodRecognizeDialog/FoodRecognizeActivity/VectorCollectionFragment 改用 GoodsItem
- PrepareFoodActivity.list 改为 GoodsItem,loadDishDetail 加 toGoodsItem() 转换,采集模式传 SubmitFoodActivity 前转回 CookFoodGoodsEntity
- CookFoodGoodsEntity 删除所有 @Ignore 字段,新增 toGoodsItem() 转换方法

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-06 15:00:32 +08:00
co-authored by Claude Sonnet 4.6
parent 05063ee9de
commit e5fc0c265d
38 changed files with 846 additions and 819 deletions
@@ -5,13 +5,16 @@ import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import com.chad.library.adapter4.BaseQuickAdapter import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.shuwei.dish.match.databinding.ListItemDishRecordBinding import com.shuwei.dish.match.databinding.ListItemFood2Binding
import com.shuwei.dish.match.entity.FoodRecord import com.shuwei.dish.match.entity.FoodRecord
class FoodRecordAdapter(list: MutableList<FoodRecord>) : /**
BaseQuickAdapter<FoodRecord, FoodRecordAdapter.VH>(list) { * 菜品搜索页面的适配器
*/
class Food2Adapter(list: MutableList<FoodRecord>) :
BaseQuickAdapter<FoodRecord, Food2Adapter.VH>(list) {
inner class VH(var binding: ListItemDishRecordBinding) : QuickViewHolder(binding.root) inner class VH(var binding: ListItemFood2Binding) : QuickViewHolder(binding.root)
override fun onBindViewHolder( override fun onBindViewHolder(
holder: VH, holder: VH,
@@ -27,7 +30,7 @@ class FoodRecordAdapter(list: MutableList<FoodRecord>) :
viewType: Int viewType: Int
): VH { ): VH {
val inflater = LayoutInflater.from(context) val inflater = LayoutInflater.from(context)
val binding = ListItemDishRecordBinding.inflate(inflater, parent, false) val binding = ListItemFood2Binding.inflate(inflater, parent, false)
return VH(binding) return VH(binding)
} }
} }
@@ -0,0 +1,40 @@
package com.shuwei.dish.match.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.shuwei.dish.match.databinding.ListItemFood3Binding
import com.shuwei.dish.match.entity.GoodsItem
/**
* 向量采集页面的适配器
*/
class Food3Adapter(list: MutableList<GoodsItem>) :
BaseQuickAdapter<GoodsItem, Food3Adapter.VH>(list) {
override fun onBindViewHolder(
holder: VH,
position: Int,
item: GoodsItem?
) {
item ?: return
holder.binding.tvFoodName.run {
text = item.goodsName
isChecked = item.isClicked
}
}
override fun onCreateViewHolder(
context: Context,
parent: ViewGroup,
viewType: Int
): VH {
val binding = ListItemFood3Binding.inflate(LayoutInflater.from(context), parent, false)
return VH(binding)
}
inner class VH(var binding: ListItemFood3Binding) : QuickViewHolder(binding.root)
}
@@ -7,41 +7,45 @@ import androidx.core.content.ContextCompat
import com.chad.library.adapter4.BaseQuickAdapter import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder 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.ListItemFoodBinding
import com.shuwei.dish.match.entity.CookFoodGoodsEntity import com.shuwei.dish.match.entity.GoodsItem
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
import com.shuwei.dish.match.utils.ext.visible import com.shuwei.dish.match.utils.ext.visible
class GoodsInfoSearchAdapter(private var list: MutableList<CookFoodGoodsEntity>) : /**
BaseQuickAdapter<CookFoodGoodsEntity, GoodsInfoSearchAdapter.VH>(list) { * 识别页面和搜索弹窗的适配器
*/
class FoodAdapter(list: MutableList<GoodsItem>) :
BaseQuickAdapter<GoodsItem, FoodAdapter.VH>(list) {
override fun onBindViewHolder( override fun onBindViewHolder(
holder: VH, holder: VH,
position: Int, position: Int,
item: CookFoodGoodsEntity? item: GoodsItem?
) { ) {
item ?: return 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) 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) R.color.dish_green
else R.color.black666 else R.color.black666
) )
) )
} }
if (item.foodScore == -1){ if (item.foodScore == -1) {
holder.binding.tvFoodScore.gone() holder.binding.tvFoodScore.gone()
} else { } else {
holder.binding.tvFoodScore.let { holder.binding.tvFoodScore.let {
it.visible() it.visible()
it.text = "${(item.foodScore / 100.0).roundedDecimalPlace(2)}%" val foodScoreText = "${(item.foodScore / 100.0).roundedDecimalPlace(2)}%"
it.text = foodScoreText
} }
} }
} }
@@ -52,11 +56,10 @@ class GoodsInfoSearchAdapter(private var list: MutableList<CookFoodGoodsEntity>)
viewType: Int viewType: Int
): VH { ): VH {
val binding = val binding =
ListItemSearchGoodsInfoBinding.inflate(LayoutInflater.from(context), parent, false) ListItemFoodBinding.inflate(LayoutInflater.from(context), parent, false)
return VH(binding) return VH(binding)
} }
inner class VH(var binding: ListItemSearchGoodsInfoBinding) : QuickViewHolder(binding.root) inner class VH(var binding: ListItemFoodBinding) : QuickViewHolder(binding.root)
} }
@@ -7,27 +7,27 @@ import androidx.core.content.ContextCompat
import com.chad.library.adapter4.BaseQuickAdapter import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder 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.ListItemFoodMaterialBinding
import com.shuwei.dish.match.entity.CookFoodGoodsEntity import com.shuwei.dish.match.entity.GoodsItem
import com.shuwei.dish.match.utils.ext.gone 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 com.shuwei.dish.match.utils.ext.visible
class DishPartAdapter(list: MutableList<CookFoodGoodsEntity>) : class FoodMaterialAdapter(list: MutableList<GoodsItem>) :
BaseQuickAdapter<CookFoodGoodsEntity, DishPartAdapter.VH>(list) { BaseQuickAdapter<GoodsItem, FoodMaterialAdapter.VH>(list) {
/** item 主体点击回调 */ /** item 主体点击回调 */
var onItemClick: ((position: Int) -> Unit)? = null var onItemClick: ((position: Int) -> Unit)? = null
inner class VH(var binding: ListItemDishCookBinding) : QuickViewHolder(binding.root) inner class VH(var binding: ListItemFoodMaterialBinding) : QuickViewHolder(binding.root)
override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH { override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
val inflater = LayoutInflater.from(context) val inflater = LayoutInflater.from(context)
val binding = ListItemDishCookBinding.inflate(inflater, parent, false) val binding = ListItemFoodMaterialBinding.inflate(inflater, parent, false)
return VH(binding) return VH(binding)
} }
override fun onBindViewHolder(holder: VH, position: Int, item: CookFoodGoodsEntity?) { override fun onBindViewHolder(holder: VH, position: Int, item: GoodsItem?) {
holder.binding.run { holder.binding.run {
val data = item ?: return val data = item ?: return
@@ -1,43 +0,0 @@
package com.shuwei.dish.match.adapter
import android.content.Context
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.shuwei.dish.match.R
import com.shuwei.dish.match.databinding.ListItemSearchFoodBinding
import com.shuwei.dish.match.databinding.ListItemSearchGoodsInfoBinding
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 FoodSearchAdapter(private var list: MutableList<CookFoodGoodsEntity>) :
BaseQuickAdapter<CookFoodGoodsEntity, FoodSearchAdapter.VH>(list) {
override fun onBindViewHolder(
holder: VH,
position: Int,
item: CookFoodGoodsEntity?
) {
item ?: return
holder.binding.tvFoodName.run {
text = item.goodsName
isChecked = item.isClicked
}
}
override fun onCreateViewHolder(
context: Context,
parent: ViewGroup,
viewType: Int
): VH {
val binding = ListItemSearchFoodBinding.inflate(LayoutInflater.from(context), parent, false)
return VH(binding)
}
inner class VH(var binding: ListItemSearchFoodBinding) : QuickViewHolder(binding.root)
}
@@ -7,9 +7,12 @@ import androidx.core.content.ContextCompat
import com.chad.library.adapter4.BaseQuickAdapter import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder 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.ListItemFoodBinding
import com.shuwei.dish.match.entity.SeasoningEntity import com.shuwei.dish.match.entity.SeasoningEntity
/**
* 调料搜索弹窗适配器
*/
class SeasoningSearchAdapter(private var list: MutableList<SeasoningEntity>) : class SeasoningSearchAdapter(private var list: MutableList<SeasoningEntity>) :
BaseQuickAdapter<SeasoningEntity, SeasoningSearchAdapter.VH>(list) { BaseQuickAdapter<SeasoningEntity, SeasoningSearchAdapter.VH>(list) {
@@ -40,10 +43,10 @@ class SeasoningSearchAdapter(private var list: MutableList<SeasoningEntity>) :
viewType: Int viewType: Int
): VH { ): VH {
val binding = val binding =
ListItemSearchGoodsInfoBinding.inflate(LayoutInflater.from(context), parent, false) ListItemFoodBinding.inflate(LayoutInflater.from(context), parent, false)
return VH(binding) return VH(binding)
} }
inner class VH(var binding: ListItemSearchGoodsInfoBinding) : QuickViewHolder(binding.root) inner class VH(var binding: ListItemFoodBinding) : QuickViewHolder(binding.root)
} }
@@ -1,136 +1,136 @@
package com.shuwei.dish.match.adapter //package com.shuwei.dish.match.adapter
//
import android.graphics.Typeface //import android.graphics.Typeface
import android.icu.text.DecimalFormat //import android.icu.text.DecimalFormat
import android.text.SpannableStringBuilder //import android.text.SpannableStringBuilder
import android.text.style.AbsoluteSizeSpan //import android.text.style.AbsoluteSizeSpan
import android.text.style.ForegroundColorSpan //import android.text.style.ForegroundColorSpan
import android.text.style.LineHeightSpan //import android.text.style.LineHeightSpan
import android.text.style.StyleSpan //import android.text.style.StyleSpan
import android.view.LayoutInflater //import android.view.LayoutInflater
import android.view.ViewGroup //import android.view.ViewGroup
import android.widget.FrameLayout //import android.widget.FrameLayout
import android.widget.TextView //import android.widget.TextView
import androidx.core.content.ContextCompat //import androidx.core.content.ContextCompat
import androidx.core.graphics.toColorInt //import androidx.core.graphics.toColorInt
import androidx.recyclerview.widget.RecyclerView //import androidx.recyclerview.widget.RecyclerView
import com.chad.library.adapter4.viewholder.QuickViewHolder //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.ListItemCellBinding //import com.shuwei.dish.match.databinding.ListItemCellBinding
import com.shuwei.dish.match.entity.SeasoningEntity //import com.shuwei.dish.match.entity.SeasoningEntity
import com.shuwei.dish.match.utils.ext.appendText //import com.shuwei.dish.match.utils.ext.appendText
import com.shuwei.dish.match.utils.ext.buildSpannableString //import com.shuwei.dish.match.utils.ext.buildSpannableString
import com.shuwei.dish.match.utils.ext.clickWithDebounce //import com.shuwei.dish.match.utils.ext.clickWithDebounce
import com.shuwei.dish.match.utils.ext.dp //import com.shuwei.dish.match.utils.ext.dp
import com.shuwei.dish.match.utils.ext.invisible //import com.shuwei.dish.match.utils.ext.invisible
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 com.shuwei.dish.match.utils.ext.visible
//
class TextCellAdapter(var list: MutableList<SeasoningEntity>) : //class TextCellAdapter(var list: MutableList<SeasoningEntity>) :
RecyclerView.Adapter<TextCellAdapter.VH>() { // RecyclerView.Adapter<TextCellAdapter.VH>() {
//
inner class VH(var binding: ListItemCellBinding) : QuickViewHolder(binding.root) // inner class VH(var binding: ListItemCellBinding) : QuickViewHolder(binding.root)
//
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH { // override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
val inflater = LayoutInflater.from(parent.context) // val inflater = LayoutInflater.from(parent.context)
val binding = ListItemCellBinding.inflate(inflater, parent, false) // val binding = ListItemCellBinding.inflate(inflater, parent, false)
return VH(binding) // return VH(binding)
} // }
//
override fun onBindViewHolder(holder: VH, position: Int) { // override fun onBindViewHolder(holder: VH, position: Int) {
val item = list[position] // val item = list[position]
holder.binding.run { // holder.binding.run {
if (position == 10 || position == 11 || position == 13 || position == 14) { // if (position == 10 || position == 11 || position == 13 || position == 14) {
root.invisible() // root.invisible()
} else {
root.visible()
}
loadCell(tvCell, item)
//root.setBackgroundResource(R.color.dish_green)
(root.layoutParams as RecyclerView.LayoutParams).let {
// it.bottomMargin = 15.dp
it.width = 226.dp
it.height = 120.dp
// it.rightMargin = 0
// it.leftMargin = if (position % 3 == 0) 0 else 15.dp
it.leftMargin = 7.dp
it.rightMargin = 8.dp
it.topMargin = 7.dp
it.bottomMargin = 8.dp
}
if (item.pageType == 1) {
root.clickWithDebounce { onCellClick?.invoke(position) }
}
}
}
override fun getItemCount() = list.size
var onCellClick: ((positon: Int) -> Unit)? = null
companion object {
fun loadLayout(frameLayout: FrameLayout, item: SeasoningEntity) {
val child: TextView = frameLayout.getChildAt(0) as TextView
child.text = getTextSpan(item)
}
fun loadCell(tvCell: TextView, item: SeasoningEntity) {
tvCell.text = getTextSpan(item)
}
// fun loadCell2(tvCell: TextView, item: SeasoningEntity) {
// if (item.goodsName.isNullOrBlank()) {
// tvCell.run {
// text = buildSpannableString {
// appendText(
// "未配置",
// ForegroundColorSpan("#999999".toColorInt()),
// StyleSpan(Typeface.BOLD),
// AbsoluteSizeSpan(28, true),
// LineHeightSpan { text, start, end, spanstartv, v, fm ->
// fm.descent += 10.dp // 增加行间距
// }
// )}
// //setTextColor(ContextCompat.getColor(context, R.color.black999))
// }
// } else { // } else {
//// if (item.pageType == 1) { // root.visible()
//// tvCell.run { // }
//// text = item.goodsName // loadCell(tvCell, item)
//// setTextColor(ContextCompat.getColor(context, R.color.black)) // //root.setBackgroundResource(R.color.dish_green)
//// } // (root.layoutParams as RecyclerView.LayoutParams).let {
//// } else { //// it.bottomMargin = 15.dp
// tvCell.text = getTextSpan(item) // it.width = 226.dp
//// } // it.height = 120.dp
//// it.rightMargin = 0
//// it.leftMargin = if (position % 3 == 0) 0 else 15.dp
//
// it.leftMargin = 7.dp
// it.rightMargin = 8.dp
// it.topMargin = 7.dp
// it.bottomMargin = 8.dp
// }
// if (item.pageType == 1) {
// root.clickWithDebounce { onCellClick?.invoke(position) }
// } // }
// } // }
// }
fun getTextSpan(item: SeasoningEntity): SpannableStringBuilder { //
val endIndex = if (item.sort == 9) 10 else 6 // override fun getItemCount() = list.size
var name = if (item.goodsName.isNullOrBlank()) "未配置" else item.goodsName!! //
if (name.length > endIndex) { // var onCellClick: ((positon: Int) -> Unit)? = null
name = "${name.substring(0, endIndex)}" //
} // companion object {
return buildSpannableString { // fun loadLayout(frameLayout: FrameLayout, item: SeasoningEntity) {
appendText( // val child: TextView = frameLayout.getChildAt(0) as TextView
name, // child.text = getTextSpan(item)
ForegroundColorSpan(if (item.goodsName.isNullOrBlank()) "#999999".toColorInt() else "#000000".toColorInt()), // }
StyleSpan(Typeface.BOLD), // fun loadCell(tvCell: TextView, item: SeasoningEntity) {
AbsoluteSizeSpan(28, true), // tvCell.text = getTextSpan(item)
LineHeightSpan { text, start, end, spanstartv, v, fm -> // }
fm.descent += 10.dp // 增加行间距 //// fun loadCell2(tvCell: TextView, item: SeasoningEntity) {
} //// if (item.goodsName.isNullOrBlank()) {
) //// tvCell.run {
append("\n") //// text = buildSpannableString {
val weight = item.useWeight ?: 0.toDouble() //// appendText(
val weightColor = if (weight == 0.toDouble()) "#999999" else "#00BC71" //// "未配置",
appendText( //// ForegroundColorSpan("#999999".toColorInt()),
// "${DecimalFormat("#").format(weight)}g", //// StyleSpan(Typeface.BOLD),
"${weight.roundedOneDecimalPlace()}g", //// AbsoluteSizeSpan(28, true),
ForegroundColorSpan(weightColor.toColorInt()), //// LineHeightSpan { text, start, end, spanstartv, v, fm ->
AbsoluteSizeSpan(30, true) //// fm.descent += 10.dp // 增加行间距
) //// }
} //// )}
} //// //setTextColor(ContextCompat.getColor(context, R.color.black999))
} //// }
//// } else {
} ////// if (item.pageType == 1) {
////// tvCell.run {
////// text = item.goodsName
////// setTextColor(ContextCompat.getColor(context, R.color.black))
////// }
////// } else {
//// tvCell.text = getTextSpan(item)
////// }
//// }
//// }
//
// fun getTextSpan(item: SeasoningEntity): SpannableStringBuilder {
// val endIndex = if (item.sort == 9) 10 else 6
// var name = if (item.goodsName.isNullOrBlank()) "未配置" else item.goodsName!!
// if (name.length > endIndex) {
// name = "${name.substring(0, endIndex)}…"
// }
// return buildSpannableString {
// appendText(
// name,
// ForegroundColorSpan(if (item.goodsName.isNullOrBlank()) "#999999".toColorInt() else "#000000".toColorInt()),
// StyleSpan(Typeface.BOLD),
// AbsoluteSizeSpan(28, true),
// LineHeightSpan { text, start, end, spanstartv, v, fm ->
// fm.descent += 10.dp // 增加行间距
// }
// )
// append("\n")
// val weight = item.useWeight ?: 0.toDouble()
// val weightColor = if (weight == 0.toDouble()) "#999999" else "#00BC71"
// appendText(
//// "${DecimalFormat("#").format(weight)}g",
// "${weight.roundedOneDecimalPlace()}g",
// ForegroundColorSpan(weightColor.toColorInt()),
// AbsoluteSizeSpan(30, true)
// )
// }
// }
// }
//
//}
@@ -25,7 +25,7 @@ import com.shuwei.dish.match.entity.SeasoningSlotEntity
CookFoodGoodsEntity::class, CookFoodGoodsEntity::class,
SeasoningSlotEntity::class, SeasoningSlotEntity::class,
], ],
version = 8, version = 9,
exportSchema = true exportSchema = true
) )
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
@@ -214,6 +214,16 @@ val MIGRATION_6_7 = MigrationImpl(6, 7) {db ->
} }
} }
/**
* 版本8→9:为 dm_cook_food_goods 和 dm_seasoning 表新增 zjmCode、materId 字段
*/
val MIGRATION_8_9 = MigrationImpl(8, 9) { db ->
db.execSQL("ALTER TABLE dm_cook_food_goods ADD COLUMN zjmCode TEXT DEFAULT ''")
db.execSQL("ALTER TABLE dm_cook_food_goods ADD COLUMN materId TEXT DEFAULT ''")
db.execSQL("ALTER TABLE dm_seasoning ADD COLUMN zjmCode TEXT DEFAULT ''")
db.execSQL("ALTER TABLE dm_seasoning ADD COLUMN materId TEXT DEFAULT ''")
}
class DatabaseProvider(private val context: Context) { class DatabaseProvider(private val context: Context) {
// 单例模式确保全局唯一实例‌ // 单例模式确保全局唯一实例‌
val instance: AppDatabase by lazy { val instance: AppDatabase by lazy {
@@ -233,6 +243,7 @@ class DatabaseProvider(private val context: Context) {
// .addMigrations(MIGRATION_5_6) // .addMigrations(MIGRATION_5_6)
// .addMigrations(MIGRATION_6_7) // .addMigrations(MIGRATION_6_7)
.addMigrations(MIGRATION_7_8) .addMigrations(MIGRATION_7_8)
.addMigrations(MIGRATION_8_9)
.build() .build()
} }
} }
@@ -1,62 +1,62 @@
package com.shuwei.dish.match.dialog //package com.shuwei.dish.match.dialog
//
import android.annotation.SuppressLint //import android.annotation.SuppressLint
import android.os.Handler //import android.os.Handler
import android.os.Looper //import android.os.Looper
import android.view.LayoutInflater //import android.view.LayoutInflater
import androidx.recyclerview.widget.GridLayoutManager //import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.bottomsheet.BottomSheetDialog //import com.google.android.material.bottomsheet.BottomSheetDialog
import com.shuwei.dish.match.R //import com.shuwei.dish.match.R
import com.shuwei.dish.match.adapter.GoodsInfoSearchAdapter //import com.shuwei.dish.match.adapter.FoodAdapter
import com.shuwei.dish.match.base.BaseActivity //import com.shuwei.dish.match.base.BaseActivity
import com.shuwei.dish.match.databinding.DialogFoodRecognizeBinding //import com.shuwei.dish.match.databinding.DialogFoodRecognizeBinding
import com.shuwei.dish.match.entity.CookFoodGoodsEntity //import com.shuwei.dish.match.entity.GoodsItem
//
/** ///**
* 菜品识别结果弹窗,继承 BottomSheetDialog 确保只初始化一次 // * 菜品识别结果弹窗,继承 BottomSheetDialog 确保只初始化一次
* @param activity 宿主 Activity // * @param activity 宿主 Activity
* @param onDismiss 弹窗关闭时的额外回调(可选) // * @param onDismiss 弹窗关闭时的额外回调(可选)
* @param onItemSelected 用户点击某一菜品时的回调 // * @param onItemSelected 用户点击某一菜品时的回调
*/ // */
class FoodRecognizeDialog( //class FoodRecognizeDialog(
private val activity: BaseActivity, // private val activity: BaseActivity,
private val onDismiss: (() -> Unit)? = null, // private val onDismiss: (() -> Unit)? = null,
private val onItemSelected: (item: CookFoodGoodsEntity) -> Unit // private val onItemSelected: (item: GoodsItem) -> Unit
) : BottomSheetDialog(activity, R.style.BottomSheet) { //) : BottomSheetDialog(activity, R.style.BottomSheet) {
//
private val binding = DialogFoodRecognizeBinding.inflate(LayoutInflater.from(activity)) // private val binding = DialogFoodRecognizeBinding.inflate(LayoutInflater.from(activity))
private val list = mutableListOf<CookFoodGoodsEntity>() // private val list = mutableListOf<GoodsItem>()
private val adapter = GoodsInfoSearchAdapter(list).apply { // private val adapter = FoodAdapter(list).apply {
setOnItemClickListener { _, _, position -> // setOnItemClickListener { _, _, position ->
list[position].isClicked = true // list[position].isClicked = true
notifyItemChanged(position) // notifyItemChanged(position)
Handler(Looper.getMainLooper()).postDelayed({ // Handler(Looper.getMainLooper()).postDelayed({
onItemSelected(list[position]) // onItemSelected(list[position])
dismiss() // dismiss()
}, 300) // }, 300)
} // }
} // }
//
init { // init {
setContentView(binding.root) // setContentView(binding.root)
setCancelable(true) // setCancelable(true)
behavior.skipCollapsed = false // behavior.skipCollapsed = false
setOnDismissListener { activity.hideStatusBar(); onDismiss?.invoke() } // setOnDismissListener { activity.hideStatusBar(); onDismiss?.invoke() }
binding.recyclerView.run { // binding.recyclerView.run {
layoutManager = GridLayoutManager(activity, 2, GridLayoutManager.VERTICAL, false) // layoutManager = GridLayoutManager(activity, 2, GridLayoutManager.VERTICAL, false)
adapter = this@FoodRecognizeDialog.adapter // adapter = this@FoodRecognizeDialog.adapter
} // }
} // }
//
/** // /**
* 加载识别结果数据并显示弹窗 // * 加载识别结果数据并显示弹窗
* @param items 识别到的菜品列表 // * @param items 识别到的菜品列表
*/ // */
@SuppressLint("NotifyDataSetChanged") // @SuppressLint("NotifyDataSetChanged")
fun loadData(items: List<CookFoodGoodsEntity>) { // fun loadData(items: List<GoodsItem>) {
list.clear() // list.clear()
list.addAll(items) // list.addAll(items)
adapter.notifyDataSetChanged() // adapter.notifyDataSetChanged()
if (!isShowing) show() // if (!isShowing) show()
} // }
} //}
@@ -1,8 +1,6 @@
package com.shuwei.dish.match.dialog package com.shuwei.dish.match.dialog
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.os.Handler
import android.os.Looper
import android.text.Editable import android.text.Editable
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
@@ -15,16 +13,15 @@ import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.shuwei.dish.match.R import com.shuwei.dish.match.R
import com.shuwei.dish.match.adapter.GoodsInfoSearchAdapter import com.shuwei.dish.match.adapter.FoodAdapter
import com.shuwei.dish.match.base.BaseActivity import com.shuwei.dish.match.base.BaseActivity
import com.shuwei.dish.match.base.BaseApp import com.shuwei.dish.match.base.BaseApp
import com.shuwei.dish.match.databinding.DialogFoodSearchBinding import com.shuwei.dish.match.databinding.DialogFoodSearchBinding
import com.shuwei.dish.match.entity.CookFoodGoodsEntity import com.shuwei.dish.match.entity.GoodsItem
import com.shuwei.dish.match.net.UiState import com.shuwei.dish.match.net.UiState
import com.shuwei.dish.match.utils.KeyboardUtil import com.shuwei.dish.match.utils.KeyboardUtil
import com.shuwei.dish.match.utils.ext.addOnActionSearchListener import com.shuwei.dish.match.utils.ext.addOnActionSearchListener
import com.shuwei.dish.match.utils.ext.toast import com.shuwei.dish.match.utils.ext.toast
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
/** /**
@@ -36,24 +33,24 @@ import kotlinx.coroutines.launch
class FoodSearchDialog( class FoodSearchDialog(
private val activity: BaseActivity, private val activity: BaseActivity,
private val defGoodsName: String? = null, private val defGoodsName: String? = null,
private val onItemSelected: (item: CookFoodGoodsEntity) -> Unit private val onItemSelected: (item: GoodsItem) -> Unit
) : BottomSheetDialog(activity, R.style.BottomSheet) { ) : BottomSheetDialog(activity, R.style.BottomSheet) {
private val binding = DialogFoodSearchBinding.inflate(LayoutInflater.from(activity)) private val binding = DialogFoodSearchBinding.inflate(LayoutInflater.from(activity))
private val list = mutableListOf<CookFoodGoodsEntity>().apply { private val list = mutableListOf<GoodsItem>().apply {
add(CookFoodGoodsEntity(goodsId = "200001", goodsName = "土豆丝")) add(GoodsItem(goodsId = "200001", goodsName = "土豆丝"))
add(CookFoodGoodsEntity(goodsId = "200002", goodsName = "土豆片")) add(GoodsItem(goodsId = "200002", goodsName = "土豆片"))
add(CookFoodGoodsEntity(goodsId = "200003", goodsName = "土豆丁")) add(GoodsItem(goodsId = "200003", goodsName = "土豆丁"))
add(CookFoodGoodsEntity(goodsId = "200004", goodsName = "胡萝卜丝")) add(GoodsItem(goodsId = "200004", goodsName = "胡萝卜丝"))
add(CookFoodGoodsEntity(goodsId = "200005", goodsName = "胡萝卜片")) add(GoodsItem(goodsId = "200005", goodsName = "胡萝卜片"))
add(CookFoodGoodsEntity(goodsId = "200006", goodsName = "胡萝卜丁")) add(GoodsItem(goodsId = "200006", goodsName = "胡萝卜丁"))
add(CookFoodGoodsEntity(goodsId = "200007", goodsName = "黄瓜丝")) add(GoodsItem(goodsId = "200007", goodsName = "黄瓜丝"))
add(CookFoodGoodsEntity(goodsId = "200008", goodsName = "黄瓜片")) add(GoodsItem(goodsId = "200008", goodsName = "黄瓜片"))
add(CookFoodGoodsEntity(goodsId = "200009", goodsName = "黄瓜丁")) add(GoodsItem(goodsId = "200009", goodsName = "黄瓜丁"))
add(CookFoodGoodsEntity(goodsId = "200010", goodsName = "洋葱丝")) add(GoodsItem(goodsId = "200010", goodsName = "洋葱丝"))
add(CookFoodGoodsEntity(goodsId = "200011", goodsName = "洋葱丁")) add(GoodsItem(goodsId = "200011", goodsName = "洋葱丁"))
} }
private val adapter = GoodsInfoSearchAdapter(list).apply { private val adapter = FoodAdapter(list).apply {
setOnItemClickListener { _, _, position -> setOnItemClickListener { _, _, position ->
list[position].isClicked = true list[position].isClicked = true
notifyItemChanged(position) notifyItemChanged(position)
@@ -118,10 +115,12 @@ class FoodSearchDialog(
initObserver() initObserver()
// 若有默认食材名称,自动填充并触发搜索 // 若有默认食材名称,自动填充并触发搜索
if (!defGoodsName.isNullOrBlank()) { //if (!defGoodsName.isNullOrBlank()) {
binding.etSheetInput.setText(defGoodsName) binding.etSheetInput.setText(defGoodsName)
searchGoods(binding.etSheetInput) pageNo = 1
} getGoodsList()
KeyboardUtil.hideKeyboard(binding.root)
//}
} }
/** /**
@@ -177,7 +176,7 @@ class FoodSearchDialog(
* 将返回数据填充到列表 * 将返回数据填充到列表
*/ */
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun loadGoodsList(records: MutableList<CookFoodGoodsEntity>?) { private fun loadGoodsList(records: MutableList<GoodsItem>?) {
finishRefresh() finishRefresh()
if (records.isNullOrEmpty()) { if (records.isNullOrEmpty()) {
activity.toast("暂未搜索到食材信息") activity.toast("暂未搜索到食材信息")
@@ -1,259 +1,259 @@
package com.shuwei.dish.match.dialog //package com.shuwei.dish.match.dialog
//
import android.annotation.SuppressLint //import android.annotation.SuppressLint
import android.graphics.Typeface //import android.graphics.Typeface
import android.os.Handler //import android.os.Handler
import android.os.Looper //import android.os.Looper
import android.text.SpannableStringBuilder //import android.text.SpannableStringBuilder
import android.text.style.AbsoluteSizeSpan //import android.text.style.AbsoluteSizeSpan
import android.text.style.ForegroundColorSpan //import android.text.style.ForegroundColorSpan
import android.text.style.LineHeightSpan //import android.text.style.LineHeightSpan
import android.text.style.StyleSpan //import android.text.style.StyleSpan
import android.util.Log //import android.util.Log
import android.view.Gravity //import android.view.Gravity
import android.view.LayoutInflater //import android.view.LayoutInflater
import android.view.View //import android.view.View
import android.view.ViewGroup //import android.view.ViewGroup
import android.view.WindowManager //import android.view.WindowManager
import androidx.core.graphics.toColorInt //import androidx.core.graphics.toColorInt
import androidx.core.view.isEmpty //import androidx.core.view.isEmpty
import androidx.core.widget.addTextChangedListener //import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.Lifecycle //import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope //import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle //import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager //import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView //import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetDialog //import com.google.android.material.bottomsheet.BottomSheetDialog
import com.shuwei.dish.match.R //import com.shuwei.dish.match.R
import com.shuwei.dish.match.adapter.SeasoningSearchAdapter //import com.shuwei.dish.match.adapter.SeasoningSearchAdapter
import com.shuwei.dish.match.base.BaseActivity //import com.shuwei.dish.match.base.BaseActivity
import com.shuwei.dish.match.base.BaseApp //import com.shuwei.dish.match.base.BaseApp
import com.shuwei.dish.match.databinding.DialogSeasoningSearchBinding //import com.shuwei.dish.match.databinding.DialogSeasoningSearchBinding
import com.shuwei.dish.match.entity.SeasoningEntity //import com.shuwei.dish.match.entity.SeasoningEntity
import com.shuwei.dish.match.net.UiState //import com.shuwei.dish.match.net.UiState
import com.shuwei.dish.match.utils.KeyboardUtil //import com.shuwei.dish.match.utils.KeyboardUtil
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.addOnActionSearchListener
import com.shuwei.dish.match.utils.ext.appendText //import com.shuwei.dish.match.utils.ext.appendText
import com.shuwei.dish.match.utils.ext.buildSpannableString //import com.shuwei.dish.match.utils.ext.buildSpannableString
import com.shuwei.dish.match.utils.ext.dp //import com.shuwei.dish.match.utils.ext.dp
import com.shuwei.dish.match.utils.ext.roundedDecimalPlace //import com.shuwei.dish.match.utils.ext.roundedDecimalPlace
import com.shuwei.dish.match.utils.ext.toast //import com.shuwei.dish.match.utils.ext.toast
import kotlinx.coroutines.launch //import kotlinx.coroutines.launch
//
/** ///**
* 调料搜索弹窗,继承 BottomSheetDialog 确保只初始化一次 // * 调料搜索弹窗,继承 BottomSheetDialog 确保只初始化一次
* @param activity 宿主 Activity // * @param activity 宿主 Activity
* @param weighIndex 秤的索引 // * @param weighIndex 秤的索引
* @param weighAddress 秤的地址,用于监听重量和去皮 // * @param weighAddress 秤的地址,用于监听重量和去皮
* @param clickName 默认填充的调料名称(可选) // * @param clickName 默认填充的调料名称(可选)
* @param onItemSelected 用户点击某一调料时的回调,携带当前重量 // * @param onItemSelected 用户点击某一调料时的回调,携带当前重量
*/ // */
class SeasoningSearchDialog( //class SeasoningSearchDialog(
private val activity: BaseActivity, // private val activity: BaseActivity,
private val weighIndex: Int, // private val weighIndex: Int,
private val weighAddress: Int, // private val weighAddress: Int,
private val clickName: String? = null, // private val clickName: String? = null,
private val onItemSelected: (item: SeasoningEntity) -> Unit // private val onItemSelected: (item: SeasoningEntity) -> Unit
) : BottomSheetDialog(activity, R.style.BottomSheet) { //) : BottomSheetDialog(activity, R.style.BottomSheet) {
//
companion object { // companion object {
const val TAG = "BottomDialog2" // const val TAG = "BottomDialog2"
} // }
//
private val binding = DialogSeasoningSearchBinding.inflate(LayoutInflater.from(activity)) // private val binding = DialogSeasoningSearchBinding.inflate(LayoutInflater.from(activity))
private val list = mutableListOf<SeasoningEntity>() // private val list = mutableListOf<SeasoningEntity>()
private val adapter = SeasoningSearchAdapter(list).apply { // private val adapter = SeasoningSearchAdapter(list).apply {
setOnItemClickListener { _, _, position -> // setOnItemClickListener { _, _, position ->
list[position].isClicked = true // list[position].isClicked = true
notifyItemChanged(position) // notifyItemChanged(position)
Handler(Looper.getMainLooper()).postDelayed({ // Handler(Looper.getMainLooper()).postDelayed({
onItemSelected(list[position].also { it.useWeight = currentWeight }) // onItemSelected(list[position].also { it.useWeight = currentWeight })
dismiss() // dismiss()
}, 300) // }, 300)
} // }
} // }
//
private var goodsName: String? = null // private var goodsName: String? = null
private var currentWeight = 0.0 // private var currentWeight = 0.0
private var pageNo = 1 // private var pageNo = 1
private val pageSize = 50 // private val pageSize = 50
//
init { // init {
setContentView(binding.root) // setContentView(binding.root)
setCancelable(true) // setCancelable(true)
behavior.skipCollapsed = false // behavior.skipCollapsed = false
window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN) // window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)
window?.setGravity(Gravity.BOTTOM) // window?.setGravity(Gravity.BOTTOM)
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) // window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
window?.setWindowAnimations(R.style.DialogSoftInputAnimation) // window?.setWindowAnimations(R.style.DialogSoftInputAnimation)
window?.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) // window?.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
//
setOnDismissListener { // setOnDismissListener {
// 弹窗关闭时移除重量监听,避免内存泄漏 // // 弹窗关闭时移除重量监听,避免内存泄漏
WeightUtil.removeWeightListener(TAG) // WeightUtil.removeWeightListener(TAG)
activity.hideStatusBar() // activity.hideStatusBar()
} // }
//
// 输入框:清空时重置列表 // // 输入框:清空时重置列表
binding.etSheetInput.run { // binding.etSheetInput.run {
hint = "输入调料名称" // hint = "输入调料名称"
addTextChangedListener( // addTextChangedListener(
onTextChanged = { text, _, _, _ -> goodsName = text.toString() }, // onTextChanged = { text, _, _, _ -> goodsName = text.toString() },
afterTextChanged = { // afterTextChanged = {
if (it.isNullOrBlank()) { // if (it.isNullOrBlank()) {
list.clear() // list.clear()
adapter.notifyDataSetChanged() // adapter.notifyDataSetChanged()
} // }
} // }
) // )
addOnActionSearchListener { searchGoods(this) } // addOnActionSearchListener { searchGoods(this) }
} // }
//
// RecyclerView 初始化及滑动冲突处理 // // RecyclerView 初始化及滑动冲突处理
binding.recyclerView.let { // binding.recyclerView.let {
it.layoutManager = GridLayoutManager(activity, 2, GridLayoutManager.VERTICAL, false) // it.layoutManager = GridLayoutManager(activity, 2, GridLayoutManager.VERTICAL, false)
it.adapter = adapter // it.adapter = adapter
it.addOnScrollListener(object : RecyclerView.OnScrollListener() { // it.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(rv: RecyclerView, dx: Int, dy: Int) { // override fun onScrolled(rv: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(rv, dx, dy) // super.onScrolled(rv, dx, dy)
// 解决 RecyclerView 与 SmartRefreshLayout 滑动冲突 // // 解决 RecyclerView 与 SmartRefreshLayout 滑动冲突
val topRowVerticalPosition = if (rv.isEmpty()) 0 else rv.getChildAt(0).top // val topRowVerticalPosition = if (rv.isEmpty()) 0 else rv.getChildAt(0).top
binding.refreshLayout.setNestedScrollingEnabled(topRowVerticalPosition >= 0) // binding.refreshLayout.setNestedScrollingEnabled(topRowVerticalPosition >= 0)
} // }
}) // })
} // }
//
binding.refreshLayout.run { // binding.refreshLayout.run {
setEnableRefresh(false) // setEnableRefresh(false)
setEnableLoadMore(false) // setEnableLoadMore(false)
setOnRefreshListener { pageNo = 1; getGoodsList() } // setOnRefreshListener { pageNo = 1; getGoodsList() }
setOnLoadMoreListener { getGoodsList() } // setOnLoadMoreListener { getGoodsList() }
} // }
//
binding.ivSearch.setOnClickListener { searchGoods(it) } // binding.ivSearch.setOnClickListener { searchGoods(it) }
binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it) } // binding.root.setOnClickListener { KeyboardUtil.hideKeyboard(it) }
//
// 去皮按钮 // // 去皮按钮
binding.tvClear.setOnClickListener { // binding.tvClear.setOnClickListener {
Log.d(TAG, "tareTwo: weighAddress=$weighAddress") // Log.d(TAG, "tareTwo: weighAddress=$weighAddress")
WeightUtil.tareTwo(weighAddress) // WeightUtil.tareTwo(weighAddress)
} // }
//
// 监听对应秤的重量变化 // // 监听对应秤的重量变化
WeightUtil.addWeightListener( // WeightUtil.addWeightListener(
weightKey = TAG, // weightKey = TAG,
getWeight = { address, _, weight -> // getWeight = { address, _, weight ->
if (weighAddress == address) { // if (weighAddress == address) {
currentWeight = weight.toDouble() // currentWeight = weight.toDouble()
binding.tvWeight.text = getTextSpan(weight) // binding.tvWeight.text = getTextSpan(weight)
} // }
} // }
) // )
binding.tvWeight.text = getTextSpan(0.0) // binding.tvWeight.text = getTextSpan(0.0)
//
initObserver() // initObserver()
//
// 若有默认调料名称,自动填充并触发搜索 // // 若有默认调料名称,自动填充并触发搜索
if (!clickName.isNullOrBlank()) { // if (!clickName.isNullOrBlank()) {
binding.etSheetInput.setText(clickName.trim()) // binding.etSheetInput.setText(clickName.trim())
pageNo = 1 // pageNo = 1
getGoodsList() // getGoodsList()
} // }
} // }
//
/** // /**
* 收集 seasoningListState,统一处理 Loading / Success / Error 状态 // * 收集 seasoningListState,统一处理 Loading / Success / Error 状态
*/ // */
private fun initObserver() { // private fun initObserver() {
activity.lifecycleScope.launch { // activity.lifecycleScope.launch {
activity.repeatOnLifecycle(Lifecycle.State.STARTED) { // activity.repeatOnLifecycle(Lifecycle.State.STARTED) {
activity.netViewModel.seasoningListState.collect { state -> // activity.netViewModel.seasoningListState.collect { state ->
when (state) { // when (state) {
is UiState.Success -> loadGoodsList(state.data) // is UiState.Success -> loadGoodsList(state.data)
is UiState.Error -> { // is UiState.Error -> {
activity.toast(state.msg) // activity.toast(state.msg)
finishRefresh() // finishRefresh()
} // }
else -> {} // else -> {}
} // }
} // }
} // }
} // }
} // }
//
/** // /**
* 触发搜索:校验输入、隐藏键盘、发起请求 // * 触发搜索:校验输入、隐藏键盘、发起请求
*/ // */
private fun searchGoods(v: View) { // private fun searchGoods(v: View) {
if (goodsName.isNullOrBlank()) { // if (goodsName.isNullOrBlank()) {
activity.toast("${binding.etSheetInput.hint}") // activity.toast("请${binding.etSheetInput.hint}")
return // return
} // }
pageNo = 1 // pageNo = 1
getGoodsList() // getGoodsList()
KeyboardUtil.hideKeyboard(v) // KeyboardUtil.hideKeyboard(v)
} // }
//
/** // /**
* 请求调料列表 // * 请求调料列表
*/ // */
private fun getGoodsList() { // private fun getGoodsList() {
val param = mutableMapOf<String, Any>( // val param = mutableMapOf<String, Any>(
"goodsType" to "1", // "goodsType" to "1",
"placeId" to BaseApp.canteenId, // "placeId" to BaseApp.canteenId,
"pageNum" to pageNo, // "pageNum" to pageNo,
"pageSize" to pageSize // "pageSize" to pageSize
) // )
if (!goodsName.isNullOrBlank()) { // if (!goodsName.isNullOrBlank()) {
param["goodsName"] = goodsName!! // param["goodsName"] = goodsName!!
} // }
activity.netViewModel.querySeasoningList(param) // activity.netViewModel.querySeasoningList(param)
} // }
//
/** // /**
* 将返回数据填充到列表 // * 将返回数据填充到列表
*/ // */
@SuppressLint("NotifyDataSetChanged") // @SuppressLint("NotifyDataSetChanged")
private fun loadGoodsList(records: MutableList<SeasoningEntity>?) { // private fun loadGoodsList(records: MutableList<SeasoningEntity>?) {
finishRefresh() // finishRefresh()
if (records.isNullOrEmpty()) { // if (records.isNullOrEmpty()) {
activity.toast("暂未搜索到调料信息") // activity.toast("暂未搜索到调料信息")
return // return
} // }
if (pageNo == 1) list.clear() // if (pageNo == 1) list.clear()
list.addAll(records) // list.addAll(records)
adapter.notifyDataSetChanged() // adapter.notifyDataSetChanged()
val isLoadMoreEnable = records.size >= pageSize // val isLoadMoreEnable = records.size >= pageSize
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable) // binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
if (isLoadMoreEnable) pageNo++ // if (isLoadMoreEnable) pageNo++
} // }
//
private fun finishRefresh() { // private fun finishRefresh() {
if (pageNo == 1) binding.refreshLayout.finishRefresh() // if (pageNo == 1) binding.refreshLayout.finishRefresh()
else binding.refreshLayout.finishLoadMore() // else binding.refreshLayout.finishLoadMore()
} // }
//
/** // /**
* 生成重量显示的富文本:数值大字加粗,单位小字灰色 // * 生成重量显示的富文本:数值大字加粗,单位小字灰色
*/ // */
fun getTextSpan(weight: Double): SpannableStringBuilder { // fun getTextSpan(weight: Double): SpannableStringBuilder {
val topWeight = if (weight >= 1000) "${(weight / 1000).roundedDecimalPlace(3)}" else "$weight" // val topWeight = if (weight >= 1000) "${(weight / 1000).roundedDecimalPlace(3)}" else "$weight"
val bottomUnit = if (weight >= 1000) "千克" else "" // val bottomUnit = if (weight >= 1000) "千克" else "克"
return buildSpannableString { // return buildSpannableString {
appendText( // appendText(
topWeight, // topWeight,
ForegroundColorSpan("#000000".toColorInt()), // ForegroundColorSpan("#000000".toColorInt()),
StyleSpan(Typeface.BOLD), // StyleSpan(Typeface.BOLD),
AbsoluteSizeSpan(72, true), // AbsoluteSizeSpan(72, true),
LineHeightSpan { _, _, _, _, _, fm -> fm.descent += 10.dp } // LineHeightSpan { _, _, _, _, _, fm -> fm.descent += 10.dp }
) // )
append("\n") // append("\n")
appendText( // appendText(
bottomUnit, // bottomUnit,
ForegroundColorSpan("#999999".toColorInt()), // ForegroundColorSpan("#999999".toColorInt()),
AbsoluteSizeSpan(30, true) // AbsoluteSizeSpan(30, true)
) // )
} // }
} // }
} //}
@@ -5,28 +5,35 @@ import android.graphics.Rect
import android.os.Handler import android.os.Handler
import android.os.Looper import android.os.Looper
import android.view.Gravity import android.view.Gravity
import android.view.KeyboardShortcutGroup
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu
import android.view.MotionEvent import android.view.MotionEvent
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.Window import android.view.Window
import android.view.WindowManager import android.view.WindowManager
import androidx.core.widget.addTextChangedListener import androidx.core.widget.addTextChangedListener
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.shuwei.dish.match.R import com.shuwei.dish.match.R
import com.shuwei.dish.match.adapter.SeasoningSearchAdapter import com.shuwei.dish.match.adapter.SeasoningSearchAdapter
import com.shuwei.dish.match.base.BaseActivity import com.shuwei.dish.match.base.BaseActivity
import com.shuwei.dish.match.base.BaseApp
import com.shuwei.dish.match.databinding.DialogSeasoningSelectBinding import com.shuwei.dish.match.databinding.DialogSeasoningSelectBinding
import com.shuwei.dish.match.entity.GoodsItem
import com.shuwei.dish.match.entity.SeasoningEntity import com.shuwei.dish.match.entity.SeasoningEntity
import com.shuwei.dish.match.net.UiState
import com.shuwei.dish.match.utils.KeyboardUtil import com.shuwei.dish.match.utils.KeyboardUtil
import com.shuwei.dish.match.utils.ext.addOnActionSearchListener import com.shuwei.dish.match.utils.ext.addOnActionSearchListener
import com.shuwei.dish.match.utils.ext.toast import com.shuwei.dish.match.utils.ext.toast
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
/** /**
* 调料选择弹窗,不含重量显示,继承 BottomSheetDialog 确保只初始化一次 * 调料选择弹窗,不含重量显示,继承 BottomSheetDialog 确保只初始化一次
* @param activity 宿主 Activity * @param activity 宿主 Activity
* @param clickIndex 点击的调料槽位索引
* @param onItemSelected 用户点击某一调料时的回调 * @param onItemSelected 用户点击某一调料时的回调
*/ */
class SeasoningSelectDialog( class SeasoningSelectDialog(
@@ -54,6 +61,7 @@ class SeasoningSelectDialog(
private var goodsName: String? = null private var goodsName: String? = null
private var pageNo = 1 private var pageNo = 1
private val pageSize = 50 private val pageSize = 50
private var collectJob: Job? = null
init { init {
setContentView(binding.root) setContentView(binding.root)
@@ -66,6 +74,7 @@ class SeasoningSelectDialog(
window?.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN) window?.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
setOnDismissListener { setOnDismissListener {
collectJob?.cancel()
activity.hideStatusBar() activity.hideStatusBar()
} }
@@ -104,6 +113,20 @@ class SeasoningSelectDialog(
/** 弹窗显示时自动加载默认调料列表,并在 Window.Callback 层提前拦截触摸以解决滑动冲突 */ /** 弹窗显示时自动加载默认调料列表,并在 Window.Callback 层提前拦截触摸以解决滑动冲突 */
override fun show() { override fun show() {
super.show() super.show()
// 启动 StateFlow 收集,弹窗关闭时由 setOnDismissListener 取消
collectJob = activity.lifecycleScope.launch {
activity.netViewModel.goodsListState.collect { state ->
when (state) {
is UiState.Loading -> {}
is UiState.Success -> loadGoodsList(state.data)
is UiState.Error -> {
activity.toast(state.msg)
finishRefresh()
}
is UiState.Idle -> {}
}
}
}
pageNo = 1 pageNo = 1
getGoodsList() getGoodsList()
// Window.Callback.dispatchTouchEvent 在整个 View 树的 onInterceptTouchEvent 之前执行, // Window.Callback.dispatchTouchEvent 在整个 View 树的 onInterceptTouchEvent 之前执行,
@@ -126,6 +149,18 @@ class SeasoningSelectDialog(
} }
return originalCallback.dispatchTouchEvent(event) return originalCallback.dispatchTouchEvent(event)
} }
override fun onPointerCaptureChanged(hasCapture: Boolean) {
originalCallback.onPointerCaptureChanged(hasCapture)
}
override fun onProvideKeyboardShortcuts(
data: List<KeyboardShortcutGroup?>?,
menu: Menu?,
deviceId: Int
) {
originalCallback.onProvideKeyboardShortcuts(data, menu, deviceId)
}
} }
} }
@@ -143,50 +178,33 @@ class SeasoningSelectDialog(
} }
/** /**
* 请求调料列表(临时使用本地模拟数据,正式联调时替换为真实接口) * 请求调料列表
*/ */
private fun getGoodsList() { private fun getGoodsList() {
// TODO: 联调时注释掉下方模拟数据,取消注释真实接口调用 val param = mutableMapOf<String, Any>(
val nameList = listOf( "goodsType" to "1",
"", "白砂糖","冰糖", "鸡精", "味精", "陈醋", "老抽", "生抽", "番茄酱", "胡椒粉", "孜然", "十三香", "placeId" to BaseApp.canteenId,
"料酒", "白醋", "蚝油", "辣椒面", "辣椒酱", "豆瓣酱", "淀粉", "", "", "", "香菜", "" "pageNum" to pageNo,
"pageSize" to pageSize
) )
val mockData = mutableListOf<SeasoningEntity>() if (!goodsName.isNullOrBlank()) {
nameList.forEachIndexed { index, name -> param["goodsName"] = goodsName!!
val padString = "${index + 1}".padStart(2, '0')
mockData.add(SeasoningEntity(goodsId = "1000$padString", goodsName = name))
} }
loadGoodsList(mockData) activity.netViewModel.queryGoodsList(param)
// val param = mutableMapOf<String, Any>(
// "goodsType" to "1",
// "placeId" to BaseApp.canteenId,
// "pageNum" to pageNo,
// "pageSize" to pageSize
// )
// if (!goodsName.isNullOrBlank()) {
// param["goodsName"] = goodsName!!
// }
// activity.querySeasoningList(param = param, onSuccess = {
// loadGoodsList(it)
// }, onFailure = { _, msg ->
// activity.toast(msg)
// finishRefresh()
// })
} }
/** /**
* 将返回数据填充到列表 * 将返回数据转换并填充到列表
*/ */
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun loadGoodsList(records: MutableList<SeasoningEntity>?) { private fun loadGoodsList(records: MutableList<GoodsItem>?) {
finishRefresh() finishRefresh()
if (records.isNullOrEmpty()) { if (records.isNullOrEmpty()) {
activity.toast("暂未搜索到调料信息") activity.toast("暂未搜索到调料信息")
return return
} }
if (pageNo == 1) list.clear() if (pageNo == 1) list.clear()
list.addAll(records) list.addAll(records.map { it.toSeasoningEntity() })
adapter.notifyDataSetChanged() adapter.notifyDataSetChanged()
val isLoadMoreEnable = records.size >= pageSize val isLoadMoreEnable = records.size >= pageSize
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable) binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
@@ -1,7 +1,6 @@
package com.shuwei.dish.match.entity package com.shuwei.dish.match.entity
import androidx.room.Entity import androidx.room.Entity
import androidx.room.Ignore
import androidx.room.PrimaryKey import androidx.room.PrimaryKey
import com.shuwei.dish.match.db.BaseEntity import com.shuwei.dish.match.db.BaseEntity
import com.shuwei.dish.match.utils.DateTimeUtil import com.shuwei.dish.match.utils.DateTimeUtil
@@ -63,30 +62,28 @@ class CookFoodGoodsEntity(
var relateionType_dictText: String? = "", var relateionType_dictText: String? = "",
var zjmCode: String? = "",
var materId: String? = "",
var isDel: Int = 0, var isDel: Int = 0,
var createTime: String = DateTimeUtil.formatDateTime(LocalDateTime.now()) var createTime: String = DateTimeUtil.formatDateTime(LocalDateTime.now())
) : BaseEntity, Serializable { ) : BaseEntity, Serializable {
constructor() : this(goodsId = "") // 必需的空构造, constructor() : this(goodsId = "") // 必需的空构造
@Ignore /**
var isSetFinished: Boolean = false * 转换为 GoodsItem,用于 UI 层(DishPartAdapter、PrepareFoodActivity 等)
*/
@Ignore fun toGoodsItem(): GoodsItem = GoodsItem(
var isItemClicked: Boolean = false goodsId = goodsId,
goodsName = goodsName,
@Ignore popularName = popularName,
var isSamplingPage: Boolean = false zjmCode = zjmCode,
materId = materId,
@Ignore materialType = materialType,
var isNewDishType: Boolean = false useWeight = useWeight,
relateionType = relateionType,
@Ignore allEdible = allEdible,
var isClicked: Boolean = false goodsOrRelationCode = goodsOrRelationCode
)
//true-原始数据,false-非原始数据
@Ignore
var isOriginalData: Boolean = true
@Ignore
var foodScore: Int = -1
} }
@@ -0,0 +1,62 @@
package com.shuwei.dish.match.entity
import java.io.Serializable
/**
* 物品信息接口返回的数据类(DTO),不依赖 Room,同时承载 UI 状态字段
* 对应接口:queryGoodsInfoList,食材(goodsType=0)和调料(goodsType=1)共用此结构
*/
data class GoodsItem(
// 接口返回字段
val goodsId: String = "",
val goodsName: String? = null,
val popularName: String? = null,
val zjmCode: String? = null,
val materId: String? = null,
// 从 CookFoodGoodsEntity 迁移的数据字段(DishPartAdapter 显示及转换用)
var materialType: Int = 0,
var useWeight: Double? = 0.0,
var relateionType: Int = 0,
var allEdible: Boolean = true,
var goodsOrRelationCode: String? = "",
// 从 CookFoodGoodsEntity @Ignore 迁移的 UI 状态字段
var isSetFinished: Boolean = false,
var isItemClicked: Boolean = false,
var isSamplingPage: Boolean = false,
var isNewDishType: Boolean = false,
var isClicked: Boolean = false,
// true-原始数据,false-非原始数据(识图新增)
var isOriginalData: Boolean = true,
// 识图匹配分数,-1 表示不显示
var foodScore: Int = -1
) : Serializable {
/**
* 转换为 CookFoodGoodsEntity,用于写入数据库或传给 SubmitFoodActivity
*/
fun toCookFoodGoodsEntity(): CookFoodGoodsEntity = CookFoodGoodsEntity(
goodsId = goodsId,
goodsName = goodsName,
popularName = popularName,
zjmCode = zjmCode,
materId = materId,
materialType = materialType,
useWeight = useWeight,
relateionType = relateionType,
allEdible = allEdible,
goodsOrRelationCode = goodsOrRelationCode
)
/**
* 转换为 SeasoningEntity,用于调料选择弹窗
*/
fun toSeasoningEntity(): SeasoningEntity = SeasoningEntity(
goodsId = goodsId,
goodsName = goodsName,
popularName = popularName,
zjmCode = zjmCode,
materId = materId
)
}
@@ -55,6 +55,10 @@ data class SeasoningEntity(
var relateionType_dictText: String? = "", var relateionType_dictText: String? = "",
var zjmCode: String? = "",
var materId: String? = "",
var sort: Int = 9999, var sort: Int = 9999,
/** /**
* isDel表示数据是否已删除,1-已删除,为无效数据,0-正常使用,有效数据 * isDel表示数据是否已删除,1-已删除,为无效数据,0-正常使用,有效数据
@@ -2,9 +2,8 @@ package com.shuwei.dish.match.net
import com.shuwei.dish.match.base.GlobalData import com.shuwei.dish.match.base.GlobalData
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.FoodRecord import com.shuwei.dish.match.entity.FoodRecord
import com.shuwei.dish.match.entity.SeasoningEntity import com.shuwei.dish.match.entity.GoodsItem
import retrofit2.http.Body import retrofit2.http.Body
import retrofit2.http.GET import retrofit2.http.GET
import retrofit2.http.POST import retrofit2.http.POST
@@ -51,21 +50,12 @@ interface ApiService {
): ApiResponse<MutableList<FoodRecord>?> ): ApiResponse<MutableList<FoodRecord>?>
/** /**
* 物品信息 * 物品信息(食材 goodsType=0,调料 goodsType=1 共用此接口)
*/ */
@POST @POST
suspend fun queryGoodsList( suspend fun queryGoodsList(
@Url url:String = "${GlobalData.appBaseUrl}/terminal/neglect/matching/app/queryGoodsInfoList", @Url url:String = "${GlobalData.appBaseUrl}/terminal/neglect/matching/app/queryGoodsInfoList",
@Body param: MutableMap<String, Any> @Body param: MutableMap<String, Any>
): ApiResponse<MutableList<CookFoodGoodsEntity>?> ): ApiResponse<MutableList<GoodsItem>?>
/**
* 调料信息
*/
@POST
suspend fun querySeasoningList(
@Url url:String = "${GlobalData.appBaseUrl}/terminal/neglect/matching/app/queryGoodsInfoList",
@Body param: MutableMap<String, Any>
): ApiResponse<MutableList<SeasoningEntity>?>
} }
@@ -3,9 +3,8 @@ package com.shuwei.dish.match.net
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
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.FoodRecord import com.shuwei.dish.match.entity.FoodRecord
import com.shuwei.dish.match.entity.SeasoningEntity import com.shuwei.dish.match.entity.GoodsItem
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow
@@ -87,13 +86,13 @@ class NetViewModel(
} }
/** /**
* 查询物品信息列表的 UI 状态流,UI 层通过 collect 监听 * 查询物品信息列表的 UI 状态流(食材/调料共用)UI 层通过 collect 监听
*/ */
private val _goodsListState = MutableStateFlow<UiState<MutableList<CookFoodGoodsEntity>?>>(UiState.Idle) private val _goodsListState = MutableStateFlow<UiState<MutableList<GoodsItem>?>>(UiState.Idle)
val goodsListState: StateFlow<UiState<MutableList<CookFoodGoodsEntity>?>> = _goodsListState.asStateFlow() val goodsListState: StateFlow<UiState<MutableList<GoodsItem>?>> = _goodsListState.asStateFlow()
/** /**
* 查询物品信息列表 * 查询物品信息列表(食材 goodsType=0,调料 goodsType=1 共用)
*/ */
fun queryGoodsList(param: MutableMap<String, Any>) { fun queryGoodsList(param: MutableMap<String, Any>) {
viewModelScope.launch { viewModelScope.launch {
@@ -101,20 +100,4 @@ class NetViewModel(
_goodsListState.value = repository.queryGoodsList(param) _goodsListState.value = repository.queryGoodsList(param)
} }
} }
/**
* 查询调料信息列表的 UI 状态流,UI 层通过 collect 监听
*/
private val _seasoningListState = MutableStateFlow<UiState<MutableList<SeasoningEntity>?>>(UiState.Idle)
val seasoningListState: StateFlow<UiState<MutableList<SeasoningEntity>?>> = _seasoningListState.asStateFlow()
/**
* 查询调料信息列表
*/
fun querySeasoningList(param: MutableMap<String, Any>) {
viewModelScope.launch {
_seasoningListState.value = UiState.Loading
_seasoningListState.value = repository.querySeasoningList(param)
}
}
} }
@@ -1,9 +1,8 @@
package com.shuwei.dish.match.net package com.shuwei.dish.match.net
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.FoodRecord import com.shuwei.dish.match.entity.FoodRecord
import com.shuwei.dish.match.entity.SeasoningEntity import com.shuwei.dish.match.entity.GoodsItem
/** /**
* 网络数据仓库,封装所有 ApiService 调用 * 网络数据仓库,封装所有 ApiService 调用
@@ -76,11 +75,11 @@ class RemoteRepository {
} }
/** /**
* 查询物品信息列表 * 查询物品信息列表(食材 goodsType=0,调料 goodsType=1 共用)
* @param param 查询参数 * @param param 查询参数
* @return UiState 包装的结果,Success 携带列表数据,Error 携带错误信息 * @return UiState 包装的结果,Success 携带列表数据,Error 携带错误信息
*/ */
suspend fun queryGoodsList(param: MutableMap<String, Any>): UiState<MutableList<CookFoodGoodsEntity>?> { suspend fun queryGoodsList(param: MutableMap<String, Any>): UiState<MutableList<GoodsItem>?> {
return try { return try {
val resp = apiService.queryGoodsList(param = param) val resp = apiService.queryGoodsList(param = param)
if (resp.isSuccess()) UiState.Success(resp.data) if (resp.isSuccess()) UiState.Success(resp.data)
@@ -91,21 +90,4 @@ class RemoteRepository {
} }
} }
/**
* 查询调料信息列表
* @param param 查询参数
* @return UiState 包装的结果,Success 携带列表数据,Error 携带错误信息
*/
suspend fun querySeasoningList(param: MutableMap<String, Any>): UiState<MutableList<SeasoningEntity>?> {
return try {
val resp = apiService.querySeasoningList(param = param)
if (resp.isSuccess()) UiState.Success(resp.data)
else UiState.Error(resp.code, resp.msg ?: "")
} catch (e: Exception) {
val ex = getApiException(e)
UiState.Error("-1", ex.errorMsg)
}
}
} }
@@ -9,7 +9,7 @@ import com.shuwei.dish.match.R
import com.shuwei.dish.match.base.BaseActivity import com.shuwei.dish.match.base.BaseActivity
import com.shuwei.dish.match.databinding.ActivityCookingModeBinding import com.shuwei.dish.match.databinding.ActivityCookingModeBinding
import com.shuwei.dish.match.dialog.CommonDialog import com.shuwei.dish.match.dialog.CommonDialog
import com.shuwei.dish.match.ui.fragment.DishListFragment import com.shuwei.dish.match.ui.fragment.FoodListFragment
import com.shuwei.dish.match.utils.KeyboardUtil import com.shuwei.dish.match.utils.KeyboardUtil
import com.shuwei.dish.match.utils.ext.addOnActionSearchListener import com.shuwei.dish.match.utils.ext.addOnActionSearchListener
import com.shuwei.dish.match.utils.ext.gone import com.shuwei.dish.match.utils.ext.gone
@@ -32,10 +32,10 @@ class CookingModeActivity : BaseActivity() {
private var dinnerType: String = "1" private var dinnerType: String = "1"
private val fragmentList = mutableListOf<DishListFragment>().apply { private val fragmentList = mutableListOf<FoodListFragment>().apply {
add(DishListFragment.instance("1")) add(FoodListFragment.instance("1"))
add(DishListFragment.instance("2")) add(FoodListFragment.instance("2"))
add(DishListFragment.instance("3")) add(FoodListFragment.instance("3"))
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@@ -7,11 +7,11 @@ import androidx.activity.addCallback
import androidx.core.content.IntentCompat import androidx.core.content.IntentCompat
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.shuwei.dish.match.adapter.GoodsInfoSearchAdapter import com.shuwei.dish.match.adapter.FoodAdapter
import com.shuwei.dish.match.base.BaseActivity import com.shuwei.dish.match.base.BaseActivity
import com.shuwei.dish.match.databinding.ActivityFoodRecognizeBinding import com.shuwei.dish.match.databinding.ActivityFoodRecognizeBinding
import com.shuwei.dish.match.dialog.FoodSearchDialog import com.shuwei.dish.match.dialog.FoodSearchDialog
import com.shuwei.dish.match.entity.CookFoodGoodsEntity import com.shuwei.dish.match.entity.GoodsItem
import com.shuwei.dish.match.utils.ActivityManager import com.shuwei.dish.match.utils.ActivityManager
import com.shuwei.dish.match.utils.WeightUtil import com.shuwei.dish.match.utils.WeightUtil
import com.shuwei.dish.match.utils.ext.clickWithDebounce import com.shuwei.dish.match.utils.ext.clickWithDebounce
@@ -35,7 +35,7 @@ class FoodRecognizeActivity : BaseActivity() {
const val IS_MANUAL_CANCEL = "isManualCancel" const val IS_MANUAL_CANCEL = "isManualCancel"
/** 内存缓存食材列表,避免通过 Intent 序列化传递大数据 */ /** 内存缓存食材列表,避免通过 Intent 序列化传递大数据 */
private var pendingGoodsList: ArrayList<CookFoodGoodsEntity>? = null private var pendingGoodsList: ArrayList<GoodsItem>? = null
/** /**
* 启动本页面,通过 onResult 回调返回用户选中的食材 * 启动本页面,通过 onResult 回调返回用户选中的食材
@@ -48,8 +48,8 @@ class FoodRecognizeActivity : BaseActivity() {
activity: BaseActivity, activity: BaseActivity,
imageUri: String? = null, imageUri: String? = null,
currentWeight: Double = 0.0, currentWeight: Double = 0.0,
goodsList: ArrayList<CookFoodGoodsEntity> = arrayListOf(), goodsList: ArrayList<GoodsItem> = arrayListOf(),
finishCallback: (Boolean, CookFoodGoodsEntity?) -> Unit = { _, _ -> } finishCallback: (Boolean, GoodsItem?) -> Unit = { _, _ -> }
) { ) {
pendingGoodsList = goodsList pendingGoodsList = goodsList
val launchIntent = Intent(activity, FoodRecognizeActivity::class.java).apply { val launchIntent = Intent(activity, FoodRecognizeActivity::class.java).apply {
@@ -62,7 +62,7 @@ class FoodRecognizeActivity : BaseActivity() {
IntentCompat.getSerializableExtra( IntentCompat.getSerializableExtra(
it, it,
EXTRA_SELECTED_ITEM, EXTRA_SELECTED_ITEM,
CookFoodGoodsEntity::class.java) GoodsItem::class.java)
} }
finishCallback(isManualCancel, entity) finishCallback(isManualCancel, entity)
} }
@@ -82,7 +82,7 @@ class FoodRecognizeActivity : BaseActivity() {
private lateinit var binding: ActivityFoodRecognizeBinding private lateinit var binding: ActivityFoodRecognizeBinding
private val list = mutableListOf<CookFoodGoodsEntity>() private val list = mutableListOf<GoodsItem>()
/** 当前选中的列表位置,-1 表示无选中 */ /** 当前选中的列表位置,-1 表示无选中 */
private var selectedPosition = -1 private var selectedPosition = -1
@@ -108,7 +108,7 @@ class FoodRecognizeActivity : BaseActivity() {
} }
} }
private val adapter = GoodsInfoSearchAdapter(list).apply { private val adapter = FoodAdapter(list).apply {
setOnItemClickListener { _, _, position -> setOnItemClickListener { _, _, position ->
list.forEachIndexed { i, item -> item.isClicked = (i == position) } list.forEachIndexed { i, item -> item.isClicked = (i == position) }
// 点击选择时记录当前秤重量 // 点击选择时记录当前秤重量
@@ -281,7 +281,7 @@ class FoodRecognizeActivity : BaseActivity() {
* 用新食材替换当前选中项(或追加到列表首位) * 用新食材替换当前选中项(或追加到列表首位)
*/ */
@SuppressLint("NotifyDataSetChanged") @SuppressLint("NotifyDataSetChanged")
private fun updateSelectedFood(item: CookFoodGoodsEntity) { private fun updateSelectedFood(item: GoodsItem) {
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) }
@@ -9,7 +9,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
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.FoodRecordAdapter import com.shuwei.dish.match.adapter.Food2Adapter
import com.shuwei.dish.match.base.BaseActivity import com.shuwei.dish.match.base.BaseActivity
import com.shuwei.dish.match.base.BaseApp import com.shuwei.dish.match.base.BaseApp
import com.shuwei.dish.match.databinding.ActivityFoodSearchBinding import com.shuwei.dish.match.databinding.ActivityFoodSearchBinding
@@ -44,7 +44,7 @@ class FoodSearchActivity : BaseActivity() {
private var pageType = 0 private var pageType = 0
private var dinnerType = "1" private var dinnerType = "1"
private val recordAdapter by lazy { private val recordAdapter by lazy {
FoodRecordAdapter(list).apply { Food2Adapter(list).apply {
isStateViewEnable = true isStateViewEnable = true
setOnItemClickListener { adapter, view, position -> setOnItemClickListener { adapter, view, position ->
if (pageType == 1) { if (pageType == 1) {
@@ -13,7 +13,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
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.FoodMaterialAdapter
import com.shuwei.dish.match.base.BaseActivity import com.shuwei.dish.match.base.BaseActivity
import com.shuwei.dish.match.databinding.ActivityPrepareFoodBinding import com.shuwei.dish.match.databinding.ActivityPrepareFoodBinding
import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding
@@ -21,6 +21,7 @@ import com.shuwei.dish.match.dialog.CommonDialog
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 com.shuwei.dish.match.entity.GoodsItem
import com.shuwei.dish.match.net.UiState import com.shuwei.dish.match.net.UiState
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
@@ -72,8 +73,6 @@ class PrepareFoodActivity : BaseActivity() {
private var pageFrom: String? = null private var pageFrom: String? = null
private var goodsList: MutableList<CookFoodGoodsEntity>? = null private var goodsList: MutableList<CookFoodGoodsEntity>? = null
@Suppress("DEPRECATION")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContentView(binding.root) setContentView(binding.root)
@@ -169,8 +168,10 @@ class PrepareFoodActivity : BaseActivity() {
foodRecord.foodName = showFoodName foodRecord.foodName = showFoodName
foodRecord.cookMode = 1 foodRecord.cookMode = 1
Log.d(TAG, "goToSubmit: goodsList:${list.toJsonString()}") Log.d(TAG, "goToSubmit: goodsList:${list.toJsonString()}")
// 采集模式传给 SubmitFoodActivity 时转换为 CookFoodGoodsEntity
val submitList = list.map { it.toCookFoodGoodsEntity() }.toMutableList()
startActivity<SubmitFoodActivity> { startActivity<SubmitFoodActivity> {
putExtra(SubmitFoodActivity.GOODS_LIST, list as Serializable) putExtra(SubmitFoodActivity.GOODS_LIST, submitList as Serializable)
putExtra(SubmitFoodActivity.FOOD_ITEM, foodRecord as Serializable) putExtra(SubmitFoodActivity.FOOD_ITEM, foodRecord as Serializable)
} }
} else { } else {
@@ -227,14 +228,14 @@ class PrepareFoodActivity : BaseActivity() {
* - list 中不含该 goodsId:直接新增,isNewDishType = true * - list 中不含该 goodsId:直接新增,isNewDishType = true
* - list 中已含该 goodsId:累加 useWeight * - list 中已含该 goodsId:累加 useWeight
*/ */
private val foodSelectCallback: (CookFoodGoodsEntity) -> Unit = { entity -> private val foodSelectCallback: (GoodsItem) -> Unit = { entity ->
val existing = list.firstOrNull { it.goodsId == entity.goodsId } val existing = list.firstOrNull { it.goodsId == entity.goodsId }
if (existing != null) { if (existing != null) {
existing.useWeight = (existing.useWeight ?: 0.0) + (entity.useWeight ?: 0.0) existing.useWeight = (existing.useWeight ?: 0.0) + (entity.useWeight ?: 0.0)
existing.isSetFinished = true existing.isSetFinished = true
dishPartAdapter.notifyItemChanged(list.indexOf(existing)) materialAdapter.notifyItemChanged(list.indexOf(existing))
} else { } else {
dishPartAdapter.add(entity.also { materialAdapter.add(entity.also {
it.isNewDishType = true it.isNewDishType = true
it.isSetFinished = true it.isSetFinished = true
}) })
@@ -260,16 +261,10 @@ class PrepareFoodActivity : BaseActivity() {
if (goodsList == null) { if (goodsList == null) {
goodsList = mutableListOf() goodsList = mutableListOf()
} }
// 将 GoodsItem 转换为 CookFoodGoodsEntity 并补充菜品相关字段
list.filter { it.isSetFinished }.forEach { list.filter { it.isSetFinished }.forEach {
goodsList?.add(CookFoodGoodsEntity().apply { goodsList?.add(it.toCookFoodGoodsEntity().apply {
foodId = food!!.foodId foodId = food!!.foodId
goodsId = it.goodsId
relateionType = it.relateionType
allEdible = it.allEdible
goodsName = it.goodsName
materialType = it.materialType
useWeight = it.useWeight ?: 0.toDouble()
goodsOrRelationCode = it.goodsOrRelationCode
}) })
} }
} }
@@ -311,23 +306,6 @@ class PrepareFoodActivity : BaseActivity() {
} }
private fun getDishDetail() { private fun getDishDetail() {
// //649
// val url = "${UrlConfig.DISH_DETAIL}?foodId=${food?.foodId}"
// HttpUtil.get(
// url = url,
// doSuccess = {
// val json = it.toJsonString()
// Log.d(TAG, "getDishDetail: json:$json")
// val detail: CookFoodEntity? = json.toObject<CookFoodEntity>()
// if (detail == null) {
// toast("查询菜品信息为空")
// return@get
// }
// loadDishDetail(detail)
// }) { code, msg ->
// toast(msg)
// }
netViewModel.getFoodDetail(food?.foodId ?: "") netViewModel.getFoodDetail(food?.foodId ?: "")
} }
@@ -338,22 +316,20 @@ class PrepareFoodActivity : BaseActivity() {
if (voList.isNullOrEmpty()) { if (voList.isNullOrEmpty()) {
return return
} }
//筛选出主材和辅材 // 筛选出主材和辅材,转换为 GoodsItemuseWeight 置零)
val tempData = voList.filter { it.materialType == 1 || it.materialType == 2 } val tempData = voList.filter { it.materialType == 1 || it.materialType == 2 }
.apply { .map { it.toGoodsItem().also { item -> item.useWeight = 0.0 } }
forEach { it.useWeight = 0.toDouble() }
}
list.clear() list.clear()
firstReqSize = list.size firstReqSize = list.size
list.addAll(tempData) list.addAll(tempData)
dishPartAdapter.notifyDataSetChanged() materialAdapter.notifyDataSetChanged()
} }
private var firstReqSize = 0 private var firstReqSize = 0
private var isDetailLoaded = false private var isDetailLoaded = false
private val list = mutableListOf<CookFoodGoodsEntity>() private val list = mutableListOf<GoodsItem>()
private val dishPartAdapter by lazy { private val materialAdapter by lazy {
DishPartAdapter(list = list).apply { FoodMaterialAdapter(list = list).apply {
val adapter = this val adapter = this
onItemClick = { positon -> onItemClick = { positon ->
list.forEachIndexed { index, entity -> list.forEachIndexed { index, entity ->
@@ -399,15 +375,15 @@ class PrepareFoodActivity : BaseActivity() {
.setContent("确定删除食材「${item.goodsName}」吗?") .setContent("确定删除食材「${item.goodsName}」吗?")
.setNegativeButton("取消") .setNegativeButton("取消")
.setPositiveButton("删除") { .setPositiveButton("删除") {
dishPartAdapter.removeAt(position) materialAdapter.removeAt(position)
toast("已删除") toast("已删除")
}.show() }.show()
} }
// item 点击事件 // item 点击事件
setOnItemClickListener { _, position -> setOnItemClickListener { _, position ->
dishPartAdapter.onItemClick?.invoke(position) materialAdapter.onItemClick?.invoke(position)
} }
adapter = dishPartAdapter adapter = materialAdapter
} }
} }
@@ -536,7 +512,7 @@ class PrepareFoodActivity : BaseActivity() {
private fun queryFood(list: List<FoodModule.IdNameScore>) { private fun queryFood(list: List<FoodModule.IdNameScore>) {
Log.d(TAG, "takePhoto queryFood, list=$list") Log.d(TAG, "takePhoto queryFood, list=$list")
//调用接口成功,返回食材列表设置isTakingPhoto.set(false),暂时写死数据 //调用接口成功,返回食材列表设置isTakingPhoto.set(false),暂时写死数据
val foodList = mutableListOf<CookFoodGoodsEntity>() val foodList = mutableListOf<GoodsItem>()
list.forEachIndexed { index, food -> list.forEachIndexed { index, food ->
Log.d(TAG, "takePhoto queryFood, index=${index},food=$food") Log.d(TAG, "takePhoto queryFood, index=${index},food=$food")
var foodName = "" var foodName = ""
@@ -550,10 +526,9 @@ class PrepareFoodActivity : BaseActivity() {
} }
} }
foodList.add( foodList.add(
CookFoodGoodsEntity( GoodsItem(
goodsId = foodId, goodsId = foodId,
goodsName = foodName, goodsName = foodName
foodId = index.toString()
).also { ).also {
it.foodScore = ((1 - food.score) * 10000).toInt() it.foodScore = ((1 - food.score) * 10000).toInt()
it.isOriginalData = false it.isOriginalData = false
@@ -570,7 +545,7 @@ class PrepareFoodActivity : BaseActivity() {
/** /**
* 加载识别结果页面 * 加载识别结果页面
*/ */
private fun loadRecognizeResultPage(foodList: List<CookFoodGoodsEntity>) { private fun loadRecognizeResultPage(foodList: List<GoodsItem>) {
if (currentWeight < WEIGHT_RECOGNIZE_VALUE) { if (currentWeight < WEIGHT_RECOGNIZE_VALUE) {
Log.d(TAG, "takePhoto queryFood, 已取消") Log.d(TAG, "takePhoto queryFood, 已取消")
toast("已取消") toast("已取消")
@@ -14,7 +14,7 @@ import com.shuwei.dish.match.R
import com.shuwei.dish.match.adapter.FoodListAdapter import com.shuwei.dish.match.adapter.FoodListAdapter
import com.shuwei.dish.match.base.BaseApp import com.shuwei.dish.match.base.BaseApp
import com.shuwei.dish.match.base.BaseFragment import com.shuwei.dish.match.base.BaseFragment
import com.shuwei.dish.match.databinding.FragmentDishListBinding import com.shuwei.dish.match.databinding.FragmentFoodListBinding
import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding
import com.shuwei.dish.match.dialog.CommonDialog import com.shuwei.dish.match.dialog.CommonDialog
import com.shuwei.dish.match.entity.CookFoodEntity import com.shuwei.dish.match.entity.CookFoodEntity
@@ -31,14 +31,14 @@ import java.io.Serializable
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class DishListFragment : BaseFragment<FragmentDishListBinding>() { class FoodListFragment : BaseFragment<FragmentFoodListBinding>() {
companion object { companion object {
private const val TAG = "DishListFragment" private const val TAG = "DishListFragment"
const val DINNER_TYPE = "dinnerType" const val DINNER_TYPE = "dinnerType"
public fun instance(dinnerType: String): DishListFragment { public fun instance(dinnerType: String): FoodListFragment {
return DishListFragment().apply { return FoodListFragment().apply {
arguments = Bundle().apply { arguments = Bundle().apply {
putString(DINNER_TYPE, dinnerType) putString(DINNER_TYPE, dinnerType)
} }
@@ -85,8 +85,8 @@ class DishListFragment : BaseFragment<FragmentDishListBinding>() {
override fun inflateBinding( override fun inflateBinding(
inflater: LayoutInflater, inflater: LayoutInflater,
container: ViewGroup? container: ViewGroup?
): FragmentDishListBinding { ): FragmentFoodListBinding {
return FragmentDishListBinding.inflate(inflater, container, false) return FragmentFoodListBinding.inflate(inflater, container, false)
} }
override fun initialize() { override fun initialize() {
@@ -17,13 +17,13 @@ import androidx.core.view.updateLayoutParams
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import com.shuwei.dish.match.R import com.shuwei.dish.match.R
import com.shuwei.dish.match.adapter.VectorCollectionAdapter import com.shuwei.dish.match.adapter.VectorCollectionAdapter
import com.shuwei.dish.match.adapter.FoodSearchAdapter import com.shuwei.dish.match.adapter.Food3Adapter
import com.shuwei.dish.match.base.BaseFragment import com.shuwei.dish.match.base.BaseFragment
import com.shuwei.dish.match.databinding.FragmentVectorCollectionBinding import com.shuwei.dish.match.databinding.FragmentVectorCollectionBinding
import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding import com.shuwei.dish.match.databinding.LayoutCameraPreviewBinding
import com.shuwei.dish.match.dialog.Loading import com.shuwei.dish.match.dialog.Loading
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
import com.shuwei.dish.match.entity.FoodCollectionBean import com.shuwei.dish.match.entity.FoodCollectionBean
import com.shuwei.dish.match.entity.GoodsItem
import com.shuwei.dish.match.objbox.FoodModule import com.shuwei.dish.match.objbox.FoodModule
import com.shuwei.dish.match.ui.CollectedFoodActivity import com.shuwei.dish.match.ui.CollectedFoodActivity
import com.shuwei.dish.match.ui.SingleFragmentActivity import com.shuwei.dish.match.ui.SingleFragmentActivity
@@ -53,28 +53,28 @@ class VectorCollectionFragment : BaseFragment<FragmentVectorCollectionBinding>()
} }
} }
private val searchList = mutableListOf<CookFoodGoodsEntity>().apply { private val searchList = mutableListOf<GoodsItem>().apply {
add(CookFoodGoodsEntity(goodsId = "200001", goodsName = "土豆丝")) add(GoodsItem(goodsId = "200001", goodsName = "土豆丝"))
add(CookFoodGoodsEntity(goodsId = "200002", goodsName = "土豆片")) add(GoodsItem(goodsId = "200002", goodsName = "土豆片"))
add(CookFoodGoodsEntity(goodsId = "200003", goodsName = "土豆丁")) add(GoodsItem(goodsId = "200003", goodsName = "土豆丁"))
add(CookFoodGoodsEntity(goodsId = "200004", goodsName = "胡萝卜丝")) add(GoodsItem(goodsId = "200004", goodsName = "胡萝卜丝"))
add(CookFoodGoodsEntity(goodsId = "200005", goodsName = "胡萝卜片")) add(GoodsItem(goodsId = "200005", goodsName = "胡萝卜片"))
add(CookFoodGoodsEntity(goodsId = "200006", goodsName = "胡萝卜丁")) add(GoodsItem(goodsId = "200006", goodsName = "胡萝卜丁"))
add(CookFoodGoodsEntity(goodsId = "200007", goodsName = "黄瓜丝")) add(GoodsItem(goodsId = "200007", goodsName = "黄瓜丝"))
add(CookFoodGoodsEntity(goodsId = "200008", goodsName = "黄瓜片")) add(GoodsItem(goodsId = "200008", goodsName = "黄瓜片"))
add(CookFoodGoodsEntity(goodsId = "200009", goodsName = "黄瓜丁")) add(GoodsItem(goodsId = "200009", goodsName = "黄瓜丁"))
add(CookFoodGoodsEntity(goodsId = "200010", goodsName = "洋葱丝")) add(GoodsItem(goodsId = "200010", goodsName = "洋葱丝"))
add(CookFoodGoodsEntity(goodsId = "200011", goodsName = "洋葱丁")) add(GoodsItem(goodsId = "200011", goodsName = "洋葱丁"))
} }
private var checkedItem: CookFoodGoodsEntity? = null private var checkedItem: GoodsItem? = null
private val searchAdapter by lazy { private val searchAdapter by lazy {
FoodSearchAdapter(searchList).apply { Food3Adapter(searchList).apply {
setOnItemClickListener { adapter, view, position -> setOnItemClickListener { adapter, view, position ->
searchList.forEachIndexed { index, item -> item.isClicked = index == position } searchList.forEachIndexed { index, item -> item.isClicked = index == position }
checkedItem = searchList[position] checkedItem = searchList[position]
notifyDataSetChanged() notifyDataSetChanged()
checkedItem?.let { checkedItem?.let {
selectedFoodId = it.foodId selectedFoodId = it.goodsId
selectedFoodName = it.goodsName selectedFoodName = it.goodsName
} }
} }
@@ -1,66 +1,66 @@
package com.shuwei.dish.match.utils //package com.shuwei.dish.match.utils
//
import androidx.recyclerview.widget.ItemTouchHelper //import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.RecyclerView //import androidx.recyclerview.widget.RecyclerView
import com.chad.library.adapter4.BaseQuickAdapter //import com.chad.library.adapter4.BaseQuickAdapter
import com.chad.library.adapter4.viewholder.QuickViewHolder //import com.chad.library.adapter4.viewholder.QuickViewHolder
import com.shuwei.dish.match.adapter.DishPartAdapter //import com.shuwei.dish.match.adapter.DishPartAdapter
import com.shuwei.dish.match.adapter.FoodListAdapter //import com.shuwei.dish.match.adapter.FoodListAdapter
//
class SwipeCallback( //class SwipeCallback(
private val adapter: BaseQuickAdapter<*,*>, // private val adapter: BaseQuickAdapter<*,*>,
private val callback: (position: Int) -> Unit = {} // private val callback: (position: Int) -> Unit = {}
) : //) :
ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) { // ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) {
override fun onMove( // override fun onMove(
recyclerView: RecyclerView, // recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder, // viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder // target: RecyclerView.ViewHolder
): Boolean { // ): Boolean {
return false // 不允许拖动,只允许滑动删除 // return false // 不允许拖动,只允许滑动删除
} // }
//
override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { // override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
val position = viewHolder.getBindingAdapterPosition() // val position = viewHolder.getBindingAdapterPosition()
callback(position) // callback(position)
} // }
//
override fun getMovementFlags( // override fun getMovementFlags(
recyclerView: RecyclerView, // recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder // viewHolder: RecyclerView.ViewHolder
): Int { // ): Int {
val position = viewHolder.getBindingAdapterPosition() // val position = viewHolder.getBindingAdapterPosition()
if (position < 0) { // if (position < 0) {
return makeMovementFlags(0, 0) // return makeMovementFlags(0, 0)
} // }
// 默认的拖动和滑动方向 // // 默认的拖动和滑动方向
val dragFlags = 0 // val dragFlags = 0
// ItemTouchHelper.UP or ItemTouchHelper.DOWN // // ItemTouchHelper.UP or ItemTouchHelper.DOWN
var swipeFlags = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT // var swipeFlags = ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT
//
if (adapter is FoodListAdapter) { // if (adapter is FoodListAdapter) {
if (adapter.items.isEmpty()) { // if (adapter.items.isEmpty()) {
return makeMovementFlags(0, 0) // return makeMovementFlags(0, 0)
} // }
if (!adapter.items[position].isCooking) { // if (!adapter.items[position].isCooking) {
swipeFlags = 0 // swipeFlags = 0
} // }
} else if (adapter is DishPartAdapter) { // } else if (adapter is DishPartAdapter) {
if (adapter.items.isEmpty()) { // if (adapter.items.isEmpty()) {
return makeMovementFlags(0, 0) // return makeMovementFlags(0, 0)
} // }
if (!adapter.items[position].isNewDishType) { // if (!adapter.items[position].isNewDishType) {
swipeFlags = 0 // swipeFlags = 0
} // }
} // }
//
// 根据viewHolder的逻辑判断是否允许滑动 // // 根据viewHolder的逻辑判断是否允许滑动
val count = recyclerView.adapter?.itemCount ?:0 // val count = recyclerView.adapter?.itemCount ?:0
//BaseQuickAdapter中空布局使用的ViewHolder是这个import com.chad.library.adapter4.viewholder.StateLayoutVH // //BaseQuickAdapter中空布局使用的ViewHolder是这个import com.chad.library.adapter4.viewholder.StateLayoutVH
if (count == 1 && viewHolder !is QuickViewHolder) { // if (count == 1 && viewHolder !is QuickViewHolder) {
swipeFlags = 0 // 不允许滑动 // swipeFlags = 0 // 不允许滑动
} // }
return makeMovementFlags(dragFlags, swipeFlags) // return makeMovementFlags(dragFlags, swipeFlags)
} // }
//
} //}
@@ -46,7 +46,7 @@
app:spanCount="2" app:spanCount="2"
tools:itemCount="4" tools:itemCount="4"
android:background="@drawable/shape_white_12_corners" android:background="@drawable/shape_white_12_corners"
tools:listitem="@layout/list_item_search_goods_info" tools:listitem="@layout/list_item_food"
tools:visibility="visible" /> tools:visibility="visible" />
<View <View
@@ -82,7 +82,7 @@
android:layout_marginBottom="20dp" android:layout_marginBottom="20dp"
android:overScrollMode="never" android:overScrollMode="never"
tools:itemCount="3" tools:itemCount="3"
tools:listitem="@layout/list_item_dish_record" /> tools:listitem="@layout/list_item_food2" />
<com.scwang.smart.refresh.footer.ClassicsFooter <com.scwang.smart.refresh.footer.ClassicsFooter
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -100,7 +100,7 @@
android:overScrollMode="never" android:overScrollMode="never"
android:scrollbars="vertical" android:scrollbars="vertical"
tools:itemCount="3" tools:itemCount="3"
tools:listitem="@layout/list_item_dish_cook" /> tools:listitem="@layout/list_item_food_material" />
</LinearLayout> </LinearLayout>
@@ -39,6 +39,6 @@
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2" app:spanCount="2"
tools:itemCount="10" tools:itemCount="10"
tools:listitem="@layout/list_item_search_goods_info" /> tools:listitem="@layout/list_item_food" />
</LinearLayout> </LinearLayout>
@@ -89,7 +89,7 @@
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2" app:spanCount="2"
tools:itemCount="10" tools:itemCount="10"
tools:listitem="@layout/list_item_search_goods_info" /> tools:listitem="@layout/list_item_food" />
<com.scwang.smart.refresh.footer.ClassicsFooter <com.scwang.smart.refresh.footer.ClassicsFooter
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -122,7 +122,7 @@
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2" app:spanCount="2"
tools:itemCount="10" tools:itemCount="10"
tools:listitem="@layout/list_item_search_goods_info" /> tools:listitem="@layout/list_item_food" />
<com.scwang.smart.refresh.footer.ClassicsFooter <com.scwang.smart.refresh.footer.ClassicsFooter
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -88,7 +88,7 @@
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="2" app:spanCount="2"
tools:itemCount="10" tools:itemCount="10"
tools:listitem="@layout/list_item_search_goods_info" /> tools:listitem="@layout/list_item_food" />
<com.scwang.smart.refresh.footer.ClassicsFooter <com.scwang.smart.refresh.footer.ClassicsFooter
android:layout_width="match_parent" android:layout_width="match_parent"
@@ -189,7 +189,7 @@
tools:itemCount="10" tools:itemCount="10"
android:overScrollMode="never" android:overScrollMode="never"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
tools:listitem="@layout/list_item_search_food"/> tools:listitem="@layout/list_item_food3"/>
<TextView <TextView
android:id="@+id/btnSave" android:id="@+id/btnSave"