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