Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05c5fe7932 | ||
|
|
b08a77fc9d | ||
|
|
82a9bd15d9 | ||
|
|
8aa5158b41 | ||
|
|
82960b26a0 | ||
|
|
863cd70118 | ||
|
|
e8037b12b7 | ||
|
|
13390f59dc | ||
|
|
335b56eaea | ||
|
|
2d4f7619aa | ||
|
|
e82fffb40a | ||
|
|
30f6c74a99 |
+12
-4
@@ -18,9 +18,8 @@ android {
|
|||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
ndk {
|
ndk {
|
||||||
//设置支持的SO库架构
|
//设置支持的SO库架构;x86_64 仅用于在 Windows 模拟器上调试(秤功能不可用)
|
||||||
abiFilters.addAll(listOf("armeabi-v7a"))
|
abiFilters.addAll(listOf("armeabi-v7a", "x86_64"))
|
||||||
//, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 设置输出APK文件名格式
|
// 设置输出APK文件名格式
|
||||||
@@ -42,10 +41,13 @@ android {
|
|||||||
"proguard-rules.pro"
|
"proguard-rules.pro"
|
||||||
)
|
)
|
||||||
signingConfig = signingConfigs.getByName("debug_507")
|
signingConfig = signingConfigs.getByName("debug_507")
|
||||||
|
buildConfigField("Boolean", "IS_TEST_DEVICE", "false")
|
||||||
}
|
}
|
||||||
debug {
|
debug {
|
||||||
//507扫码秤主板在android.buildTypes{}内增加
|
//507扫码秤主板在android.buildTypes{}内增加
|
||||||
signingConfig = signingConfigs.getByName("debug_507")
|
signingConfig = signingConfigs.getByName("debug_507")
|
||||||
|
// 调试构建视为测试设备,使用固定的 DEVICE_ID_1 代替真实 UDID
|
||||||
|
buildConfigField("Boolean", "IS_TEST_DEVICE", "false")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
@@ -57,10 +59,11 @@ android {
|
|||||||
}
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
|
buildConfig = true
|
||||||
}
|
}
|
||||||
packagingOptions {
|
packagingOptions {
|
||||||
pickFirst("lib/armeabi-v7a/libserial_port.so")
|
pickFirst("lib/armeabi-v7a/libserial_port.so")
|
||||||
pickFirst("lib/arme64-v8a/libserial_port.so")
|
pickFirst("lib/arm64-v8a/libserial_port.so")
|
||||||
}
|
}
|
||||||
sourceSets {
|
sourceSets {
|
||||||
named("main") {
|
named("main") {
|
||||||
@@ -88,6 +91,9 @@ dependencies {
|
|||||||
androidTestImplementation(libs.androidx.espresso.core)
|
androidTestImplementation(libs.androidx.espresso.core)
|
||||||
|
|
||||||
implementation("com.squareup.okhttp3:okhttp:4.9.1")
|
implementation("com.squareup.okhttp3:okhttp:4.9.1")
|
||||||
|
implementation("com.squareup.okhttp3:logging-interceptor:4.9.1")
|
||||||
|
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
||||||
|
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
||||||
implementation("com.google.code.gson:gson:2.10.1")
|
implementation("com.google.code.gson:gson:2.10.1")
|
||||||
// implementation("com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30")
|
// implementation("com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30")
|
||||||
|
|
||||||
@@ -112,4 +118,6 @@ dependencies {
|
|||||||
//经典加载
|
//经典加载
|
||||||
|
|
||||||
//implementation("com.geyifeng.immersionbar:immersionbar:3.2.2")
|
//implementation("com.geyifeng.immersionbar:immersionbar:3.2.2")
|
||||||
|
|
||||||
|
implementation("com.google.android.flexbox:flexbox:3.0.0")
|
||||||
}
|
}
|
||||||
@@ -8,12 +8,11 @@ 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.ListItemDishCookBinding
|
||||||
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
import com.shuwei.dish.match.model.GoodsItem
|
||||||
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
||||||
import java.text.DecimalFormat
|
|
||||||
|
|
||||||
class DishPartAdapter(list: MutableList<CookFoodGoodsEntity>) :
|
class DishPartAdapter(list: MutableList<GoodsItem>) :
|
||||||
BaseQuickAdapter<CookFoodGoodsEntity, DishPartAdapter.VH>(list) {
|
BaseQuickAdapter<GoodsItem, DishPartAdapter.VH>(list) {
|
||||||
|
|
||||||
inner class VH(var binding: ListItemDishCookBinding) : QuickViewHolder(binding.root)
|
inner class VH(var binding: ListItemDishCookBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
@@ -23,11 +22,10 @@ class DishPartAdapter(list: MutableList<CookFoodGoodsEntity>) :
|
|||||||
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 {
|
||||||
tvDishName.text = item!!.goodsName
|
tvDishName.text = item!!.goodsName
|
||||||
tvDishType.text = if (item.materialType == 1) "主辅材:主材" else if (item.materialType == 2) "主辅材:辅材" else ""
|
tvDishType.text = if (item.materialType == 1) "主辅材:主材" else if (item.materialType == 2) "主辅材:辅材" else ""
|
||||||
//"${DecimalFormat("#").format(item.useWeight)}克"
|
|
||||||
tvDishWeight.text =
|
tvDishWeight.text =
|
||||||
if (item.useWeight == null || item.useWeight == 0.toDouble()) "" else "${item.useWeight!!.roundedOneDecimalPlace()}克"
|
if (item.useWeight == null || item.useWeight == 0.toDouble()) "" else "${item.useWeight!!.roundedOneDecimalPlace()}克"
|
||||||
tvDishWeight.setTextColor(
|
tvDishWeight.setTextColor(
|
||||||
@@ -38,20 +36,16 @@ class DishPartAdapter(list: MutableList<CookFoodGoodsEntity>) :
|
|||||||
)
|
)
|
||||||
ivOperateIcon.setImageResource(
|
ivOperateIcon.setImageResource(
|
||||||
if (item.isSamplingPage)
|
if (item.isSamplingPage)
|
||||||
//采集页面
|
|
||||||
R.drawable.ic_delete
|
R.drawable.ic_delete
|
||||||
else
|
else
|
||||||
//制作页面
|
|
||||||
if (item.isSetFinished) R.drawable.ic_dish_selected
|
if (item.isSetFinished) R.drawable.ic_dish_selected
|
||||||
else R.drawable.ic_dish_unselected
|
else R.drawable.ic_dish_unselected
|
||||||
)
|
)
|
||||||
root.run {
|
root.setBackgroundResource(
|
||||||
setBackgroundResource(
|
if (item.isClicked) R.drawable.shape_item_cook_dish
|
||||||
if (item.isItemClicked) R.drawable.shape_item_cook_dish
|
else R.drawable.shape_white_fb_15_corners
|
||||||
else R.drawable.shape_white_fb_15_corners
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ 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.entity.FoodRecord
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
import com.shuwei.dish.match.databinding.ListItemDishBinding
|
import com.shuwei.dish.match.databinding.ListItemDishBinding
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ 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.ListItemDishRecordBinding
|
||||||
import com.shuwei.dish.match.entity.FoodRecord
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
|
|
||||||
class FoodRecordAdapter(list: MutableList<FoodRecord>) :
|
class FoodRecordAdapter(list: MutableList<FoodRecord>) :
|
||||||
BaseQuickAdapter<FoodRecord, FoodRecordAdapter.VH>(list) {
|
BaseQuickAdapter<FoodRecord, FoodRecordAdapter.VH>(list) {
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ 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.ListItemSearchGoodsInfoBinding
|
||||||
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
import com.shuwei.dish.match.model.GoodsItem
|
||||||
|
|
||||||
class GoodsInfoSearchAdapter(private var list: MutableList<CookFoodGoodsEntity>) :
|
class GoodsInfoSearchAdapter(private var list: MutableList<GoodsItem>) :
|
||||||
BaseQuickAdapter<CookFoodGoodsEntity, GoodsInfoSearchAdapter.VH>(list) {
|
BaseQuickAdapter<GoodsItem, GoodsInfoSearchAdapter.VH>(list) {
|
||||||
|
|
||||||
override fun onBindViewHolder(
|
override fun onBindViewHolder(
|
||||||
holder: VH,
|
holder: VH,
|
||||||
position: Int,
|
position: Int,
|
||||||
item: CookFoodGoodsEntity?
|
item: GoodsItem?
|
||||||
) {
|
) {
|
||||||
holder.binding.tvGoodsInfo.run {
|
holder.binding.tvGoodsInfo.run {
|
||||||
text = item?.goodsName
|
text = item?.goodsName
|
||||||
@@ -46,4 +46,4 @@ class GoodsInfoSearchAdapter(private var list: MutableList<CookFoodGoodsEntity>)
|
|||||||
|
|
||||||
inner class VH(var binding: ListItemSearchGoodsInfoBinding) : QuickViewHolder(binding.root)
|
inner class VH(var binding: ListItemSearchGoodsInfoBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ 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.ListItemHomeModeBinding
|
import com.shuwei.dish.match.databinding.ListItemHomeModeBinding
|
||||||
import com.shuwei.dish.match.entity.HomeModeBean
|
import com.shuwei.dish.match.model.HomeModeBean
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ 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.entity.FoodRecord
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
import com.shuwei.dish.match.databinding.ListItemDishBinding
|
import com.shuwei.dish.match.databinding.ListItemDishBinding
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
//package com.shuwei.dish.match.adapter
|
||||||
|
//
|
||||||
|
//import android.content.Context
|
||||||
|
//import android.view.LayoutInflater
|
||||||
|
//import android.view.ViewGroup
|
||||||
|
//import androidx.core.view.updateLayoutParams
|
||||||
|
//import com.chad.library.adapter4.BaseQuickAdapter
|
||||||
|
//import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
|
//import com.shuwei.dish.match.databinding.ListItemCellBinding
|
||||||
|
//import com.shuwei.dish.match.model.GoodsItem
|
||||||
|
//import com.shuwei.dish.match.utils.ext.dp
|
||||||
|
//
|
||||||
|
///**
|
||||||
|
// * 调料格子列表适配器,使用 list_item_cell 布局展示调料名称与用量
|
||||||
|
// */
|
||||||
|
//class SeasoningAdapter(list: MutableList<GoodsItem>) :
|
||||||
|
// BaseQuickAdapter<GoodsItem, SeasoningAdapter.VH>(list) {
|
||||||
|
//
|
||||||
|
// override fun onCreateViewHolder(context: Context, parent: ViewGroup, viewType: Int): VH {
|
||||||
|
// val binding = ListItemCellBinding.inflate(LayoutInflater.from(context), parent, false)
|
||||||
|
// return VH(binding)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// override fun onBindViewHolder(holder: VH, position: Int, item: GoodsItem?) {
|
||||||
|
// item ?: return
|
||||||
|
// holder.binding.root.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
|
// width = 226.dp
|
||||||
|
// height = 120.dp
|
||||||
|
// leftMargin = 7.dp
|
||||||
|
// rightMargin = 8.dp
|
||||||
|
// topMargin = 7.dp
|
||||||
|
// bottomMargin = 8.dp
|
||||||
|
// }
|
||||||
|
// holder.binding.tvCell.text = TextCellAdapter.getTextSpan(item.toSeasoningEntity())
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// inner class VH(val binding: ListItemCellBinding) : QuickViewHolder(binding.root)
|
||||||
|
//}
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
//import androidx.recyclerview.widget.RecyclerView
|
//import androidx.recyclerview.widget.RecyclerView
|
||||||
//import com.shuwei.dish.match.base.BaseActivity
|
//import com.shuwei.dish.match.base.BaseActivity
|
||||||
//import com.shuwei.dish.match.dialog.BottomDialog2
|
//import com.shuwei.dish.match.dialog.BottomDialog2
|
||||||
//import com.shuwei.dish.match.entity.SeasoningEntity
|
//import com.shuwei.dish.match.db.entity.SeasoningEntity
|
||||||
//import com.shuwei.dish.match.ui.DeviceSettingActivity
|
//import com.shuwei.dish.match.ui.DeviceSettingActivity
|
||||||
//import com.shuwei.dish.match.ui.SubmitDishActivity
|
//import com.shuwei.dish.match.ui.SubmitDishActivity
|
||||||
//import com.shuwei.dish.match.utils.DataUtil
|
//import com.shuwei.dish.match.utils.DataUtil
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ 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.ListItemSearchGoodsInfoBinding
|
||||||
import com.shuwei.dish.match.entity.SeasoningEntity
|
import com.shuwei.dish.match.model.GoodsItem
|
||||||
|
|
||||||
class SeasoningSearchAdapter(private var list: MutableList<SeasoningEntity>) :
|
class SeasoningSearchAdapter(private var list: MutableList<GoodsItem>) :
|
||||||
BaseQuickAdapter<SeasoningEntity, SeasoningSearchAdapter.VH>(list) {
|
BaseQuickAdapter<GoodsItem, SeasoningSearchAdapter.VH>(list) {
|
||||||
|
|
||||||
override fun onBindViewHolder(
|
override fun onBindViewHolder(
|
||||||
holder: VH,
|
holder: VH,
|
||||||
position: Int,
|
position: Int,
|
||||||
item: SeasoningEntity?
|
item: GoodsItem?
|
||||||
) {
|
) {
|
||||||
holder.binding.tvGoodsInfo.run {
|
holder.binding.tvGoodsInfo.run {
|
||||||
text = item?.goodsName
|
text = item?.goodsName
|
||||||
@@ -46,4 +46,4 @@ class SeasoningSearchAdapter(private var list: MutableList<SeasoningEntity>) :
|
|||||||
|
|
||||||
inner class VH(var binding: ListItemSearchGoodsInfoBinding) : QuickViewHolder(binding.root)
|
inner class VH(var binding: ListItemSearchGoodsInfoBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,136 +1,137 @@
|
|||||||
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.db.entity.SeasoningEntity
|
||||||
import com.shuwei.dish.match.utils.ext.appendText
|
//import com.shuwei.dish.match.model.GoodsItem
|
||||||
import com.shuwei.dish.match.utils.ext.buildSpannableString
|
//import com.shuwei.dish.match.utils.ext.appendText
|
||||||
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
//import com.shuwei.dish.match.utils.ext.buildSpannableString
|
||||||
import com.shuwei.dish.match.utils.ext.dp
|
//import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
||||||
import com.shuwei.dish.match.utils.ext.invisible
|
//import com.shuwei.dish.match.utils.ext.dp
|
||||||
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
//import com.shuwei.dish.match.utils.ext.invisible
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
//import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
||||||
|
//import com.shuwei.dish.match.utils.ext.visible
|
||||||
class TextCellAdapter(var list: MutableList<SeasoningEntity>) :
|
//
|
||||||
RecyclerView.Adapter<TextCellAdapter.VH>() {
|
//class TextCellAdapter(var list: MutableList<SeasoningEntity>) :
|
||||||
|
// 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 {
|
//
|
||||||
val inflater = LayoutInflater.from(parent.context)
|
// override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): VH {
|
||||||
val binding = ListItemCellBinding.inflate(inflater, parent, false)
|
// val inflater = LayoutInflater.from(parent.context)
|
||||||
return VH(binding)
|
// val binding = ListItemCellBinding.inflate(inflater, parent, false)
|
||||||
}
|
// return VH(binding)
|
||||||
|
// }
|
||||||
override fun onBindViewHolder(holder: VH, position: Int) {
|
//
|
||||||
val item = list[position]
|
// override fun onBindViewHolder(holder: VH, position: Int) {
|
||||||
holder.binding.run {
|
// val item = list[position]
|
||||||
if (position == 10 || position == 11 || position == 13 || position == 14) {
|
// holder.binding.run {
|
||||||
root.invisible()
|
// if (position == 10 || position == 11 || position == 13 || position == 14) {
|
||||||
} else {
|
// root.invisible()
|
||||||
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)
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//}
|
||||||
@@ -12,13 +12,15 @@ import android.widget.TextView
|
|||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
import androidx.activity.result.ActivityResultLauncher
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
|
import androidx.activity.viewModels
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
import com.shuwei.dish.match.databinding.ActivityBaseBinding
|
import com.shuwei.dish.match.databinding.ActivityBaseBinding
|
||||||
|
import com.shuwei.dish.match.db.DbViewModel
|
||||||
import com.shuwei.dish.match.dialog.Loading
|
import com.shuwei.dish.match.dialog.Loading
|
||||||
import com.shuwei.dish.match.http.HttpUtil
|
import com.shuwei.dish.match.net.NetViewModel
|
||||||
import com.shuwei.dish.match.http.UrlConfig
|
import com.shuwei.dish.match.viewmodel.AppViewModel
|
||||||
import com.shuwei.dish.match.ui.HomeActivity.Companion.TAG
|
import com.shuwei.dish.match.ui.HomeActivity.Companion.TAG
|
||||||
import com.shuwei.dish.match.ui.InitActivity
|
import com.shuwei.dish.match.ui.InitActivity
|
||||||
import com.shuwei.dish.match.utils.ActivityManager
|
import com.shuwei.dish.match.utils.ActivityManager
|
||||||
@@ -35,6 +37,10 @@ import java.util.Locale
|
|||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
open class BaseActivity : AppCompatActivity() {
|
open class BaseActivity : AppCompatActivity() {
|
||||||
|
|
||||||
|
val netViewModel: NetViewModel by viewModels()
|
||||||
|
val dbViewModel: DbViewModel by viewModels()
|
||||||
|
val appViewModel: AppViewModel by viewModels()
|
||||||
|
|
||||||
private lateinit var binding: ActivityBaseBinding
|
private lateinit var binding: ActivityBaseBinding
|
||||||
private var launcher: ActivityResultLauncher<Intent>? = null
|
private var launcher: ActivityResultLauncher<Intent>? = null
|
||||||
private var launchCallback: ((Intent?) -> Unit)? = null
|
private var launchCallback: ((Intent?) -> Unit)? = null
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ class BaseApp : Application() {
|
|||||||
var configUrl = ""
|
var configUrl = ""
|
||||||
|
|
||||||
var token: String? = null
|
var token: String? = null
|
||||||
var deviceId: String? = null
|
|
||||||
var appVersion: String = "1"
|
var appVersion: String = "1"
|
||||||
@Volatile
|
@Volatile
|
||||||
private var sharedPref: SharedPreferences? = null
|
private var sharedPref: SharedPreferences? = null
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.shuwei.dish.match.base
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备角色枚举
|
||||||
|
* MASTER:主设备,负责汇聚所有设备的秤数据并展示大屏界面
|
||||||
|
* SLAVE:子设备,负责推送本机秤数据给主设备
|
||||||
|
*/
|
||||||
|
enum class DeviceRole { MASTER, SLAVE }
|
||||||
|
|
||||||
|
object GlobalData {
|
||||||
|
var appBaseUrl: String = TEST_BASE_URL
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 具体业务 BaseUrl
|
||||||
|
*/
|
||||||
|
const val TEST_BASE_URL = "http://192.168.1.201:14801"
|
||||||
|
const val UAT_BASE_URL = "https://dev.yixiong-tech.com:8083"
|
||||||
|
const val PROD_BASE_URL = "https://api.dm.yixiong-tech.com:8443"
|
||||||
|
|
||||||
|
//临时用于测试
|
||||||
|
const val DEVICE_ID_2 = "8fc2ab34-2137-3112-acca-f884ea8736d4"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备id
|
||||||
|
*/
|
||||||
|
var deviceId: String = ""
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当前设备角色,启动时从 SpTool 读取,默认为 SLAVE
|
||||||
|
*/
|
||||||
|
var deviceRole: DeviceRole = DeviceRole.SLAVE
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
object GlobalKey {
|
||||||
|
const val KEY_EQUIPMENT_INFO = "equipmentInfo"
|
||||||
|
const val KEY_TOKEN = "tokenKey"
|
||||||
|
const val KEY_USER_INFO = "userInfoKey"
|
||||||
|
const val KEY_USER_NAME = "userNameKey"
|
||||||
|
const val KEY_BASE_URL = "baseUrl"
|
||||||
|
}
|
||||||
@@ -6,10 +6,14 @@ import androidx.room.Room
|
|||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import androidx.room.migration.Migration
|
import androidx.room.migration.Migration
|
||||||
import androidx.sqlite.db.SupportSQLiteDatabase
|
import androidx.sqlite.db.SupportSQLiteDatabase
|
||||||
import com.shuwei.dish.match.db.dao.AppDao
|
import com.shuwei.dish.match.db.dao.CookFoodDao
|
||||||
import com.shuwei.dish.match.entity.CookFoodEntity
|
import com.shuwei.dish.match.db.dao.CookFoodGoodsDao
|
||||||
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
import com.shuwei.dish.match.db.dao.SeasoningDao
|
||||||
import com.shuwei.dish.match.entity.SeasoningEntity
|
import com.shuwei.dish.match.db.dao.SeasoningSlotDao
|
||||||
|
import com.shuwei.dish.match.db.entity.CookFoodEntity
|
||||||
|
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
|
import com.shuwei.dish.match.db.entity.SeasoningEntity
|
||||||
|
import com.shuwei.dish.match.db.entity.SeasoningSlotEntity
|
||||||
|
|
||||||
|
|
||||||
// 步骤1:更新版本号
|
// 步骤1:更新版本号
|
||||||
@@ -19,16 +23,20 @@ import com.shuwei.dish.match.entity.SeasoningEntity
|
|||||||
SeasoningEntity::class,
|
SeasoningEntity::class,
|
||||||
CookFoodEntity::class,
|
CookFoodEntity::class,
|
||||||
CookFoodGoodsEntity::class,
|
CookFoodGoodsEntity::class,
|
||||||
|
SeasoningSlotEntity::class,
|
||||||
],
|
],
|
||||||
version = 7,
|
version = 13,
|
||||||
exportSchema = true
|
exportSchema = true
|
||||||
)
|
)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
// abstract fun seasoningDao(): SeasoningDao
|
|
||||||
// abstract fun cookFoodDao(): CookFoodDao
|
|
||||||
// abstract fun cookFoodGoodsDao(): CookFoodGoodsDao
|
|
||||||
|
|
||||||
abstract fun appDao(): AppDao
|
abstract fun cookFoodDao(): CookFoodDao
|
||||||
|
|
||||||
|
abstract fun cookFoodGoodsDao(): CookFoodGoodsDao
|
||||||
|
|
||||||
|
abstract fun seasoningDao(): SeasoningDao
|
||||||
|
|
||||||
|
abstract fun seasoningSlotDao(): SeasoningSlotDao
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -140,6 +148,20 @@ val MIGRATION_5_6 = MigrationImpl(5, 6) { db ->
|
|||||||
db.endTransaction()
|
db.endTransaction()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val MIGRATION_7_8 = MigrationImpl(7, 8) { db ->
|
||||||
|
db.execSQL(
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS `dm_seasoning_slot` (
|
||||||
|
`deviceId` TEXT NOT NULL,
|
||||||
|
`address` INTEGER NOT NULL,
|
||||||
|
`goodsId` TEXT NOT NULL,
|
||||||
|
`goodsName` TEXT NOT NULL,
|
||||||
|
PRIMARY KEY(`deviceId`, `address`)
|
||||||
|
)
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
val MIGRATION_6_7 = MigrationImpl(6, 7) {db ->
|
val MIGRATION_6_7 = MigrationImpl(6, 7) {db ->
|
||||||
runCatching {
|
runCatching {
|
||||||
|
|
||||||
@@ -192,6 +214,48 @@ 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 ''")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 版本9→10:删除 dm_cook_food 表 foodId 唯一索引
|
||||||
|
* 改为由应用层保证同一 foodId 且 isDel=0 只有一条记录,以支持逻辑删除
|
||||||
|
*/
|
||||||
|
val MIGRATION_9_10 = MigrationImpl(9, 10) { db ->
|
||||||
|
db.execSQL("DROP INDEX IF EXISTS dm_cook_food_foodId_IDX")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 版本10→11:为 dm_cook_food_goods 和 dm_seasoning 表新增 goodsCode(物料编码)字段
|
||||||
|
*/
|
||||||
|
val MIGRATION_10_11 = MigrationImpl(10, 11) { db ->
|
||||||
|
db.execSQL("ALTER TABLE dm_cook_food_goods ADD COLUMN goodsCode TEXT DEFAULT ''")
|
||||||
|
db.execSQL("ALTER TABLE dm_seasoning ADD COLUMN goodsCode TEXT DEFAULT ''")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 版本11→12:为 dm_cook_food_goods 和 dm_seasoning 表新增 rawMaterialsType(净材种类)字段
|
||||||
|
*/
|
||||||
|
val MIGRATION_11_12 = MigrationImpl(11, 12) { db ->
|
||||||
|
db.execSQL("ALTER TABLE dm_cook_food_goods ADD COLUMN rawMaterialsType TEXT DEFAULT NULL")
|
||||||
|
db.execSQL("ALTER TABLE dm_seasoning ADD COLUMN rawMaterialsType TEXT DEFAULT NULL")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 版本12→13:为 dm_cook_food 表新增 submitState(接口提交状态)字段
|
||||||
|
* 0-未提交(本地草稿/手动删除),1-接口提交成功后删除
|
||||||
|
*/
|
||||||
|
val MIGRATION_12_13 = MigrationImpl(12, 13) { db ->
|
||||||
|
db.execSQL("ALTER TABLE dm_cook_food ADD COLUMN submitState INTEGER NOT NULL DEFAULT 0")
|
||||||
|
}
|
||||||
|
|
||||||
class DatabaseProvider(private val context: Context) {
|
class DatabaseProvider(private val context: Context) {
|
||||||
// 单例模式确保全局唯一实例
|
// 单例模式确保全局唯一实例
|
||||||
val instance: AppDatabase by lazy {
|
val instance: AppDatabase by lazy {
|
||||||
@@ -210,6 +274,12 @@ class DatabaseProvider(private val context: Context) {
|
|||||||
// .addMigrations(MIGRATION_4_5)
|
// .addMigrations(MIGRATION_4_5)
|
||||||
// .addMigrations(MIGRATION_5_6)
|
// .addMigrations(MIGRATION_5_6)
|
||||||
// .addMigrations(MIGRATION_6_7)
|
// .addMigrations(MIGRATION_6_7)
|
||||||
|
.addMigrations(MIGRATION_7_8)
|
||||||
|
.addMigrations(MIGRATION_8_9)
|
||||||
|
.addMigrations(MIGRATION_9_10)
|
||||||
|
.addMigrations(MIGRATION_10_11)
|
||||||
|
.addMigrations(MIGRATION_11_12)
|
||||||
|
.addMigrations(MIGRATION_12_13)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,142 +0,0 @@
|
|||||||
package com.shuwei.dish.match.db
|
|
||||||
|
|
||||||
import com.shuwei.dish.match.base.BaseApp
|
|
||||||
import com.shuwei.dish.match.db.dao.AppDao
|
|
||||||
import com.shuwei.dish.match.entity.CookFoodEntity
|
|
||||||
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
|
||||||
import com.shuwei.dish.match.entity.SeasoningEntity
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
|
|
||||||
class AppRepository(val appDao: AppDao) {
|
|
||||||
|
|
||||||
suspend fun insertCookFood(item: CookFoodEntity) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.insertCookFood(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun updateCookFood(item: CookFoodEntity) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.updateCookFood(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getCookFoodById(foodId: String, cookMode: Int) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.getCookFoodById(BaseApp.canteenId, foodId, cookMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getCookFoodList(cookMode: Int, dinnerType: String) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.getCookFoodList(BaseApp.canteenId, cookMode, dinnerType)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun countCookFood(cookMode: Int) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.countCookFood(BaseApp.canteenId, cookMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun deleteCookFood(foodId: String, cookMode: Int) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.deleteCookFood(BaseApp.canteenId, foodId, cookMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun deleteCookFoodGoodsList(pid:Long, foodId: String) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.deleteCookFoodGoodsList(pid, foodId)
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// suspend fun insertGoods(item: CookFoodGoodsEntity) = withContext(Dispatchers.IO) {
|
|
||||||
// appDao.insertGoods(item)
|
|
||||||
// }
|
|
||||||
|
|
||||||
suspend fun insertGoodsList(items: MutableList<CookFoodGoodsEntity>) =
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
appDao.insertGoodsList(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
// suspend fun updateGoods(item: CookFoodGoodsEntity) = withContext(Dispatchers.IO) {
|
|
||||||
// appDao.updateGoods(item)
|
|
||||||
// }
|
|
||||||
|
|
||||||
suspend fun getCookFoodGoodsList(pid:Long, foodId: String) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.getCookFoodGoodsList(pid, foodId)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getCookFoodGoodsListByType(
|
|
||||||
foodId: String,
|
|
||||||
materialType: Int
|
|
||||||
) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.getCookFoodGoodsListByType(foodId, materialType)
|
|
||||||
}
|
|
||||||
//--------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
suspend fun getSeasoningById(id: Long) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.getSeasoningById(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getSeasoningBySort(sort:Int) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.getSeasoningBySort(sort)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getSeasoningByGoodsId(goodsId: Int) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.getSeasoningByGoodsId(goodsId)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getAllStream() = withContext(Dispatchers.IO) {
|
|
||||||
appDao.getAllStream()
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun search(query: String) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.search(query)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun clearAllSeasoning() = withContext(Dispatchers.IO) {
|
|
||||||
appDao.clearAllSeasoning()
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun deleteSeasoningBySort(sort: Int) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.deleteSeasoningBySort(sort)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun insertSeasoningList(items: MutableList<SeasoningEntity>) =
|
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
appDao.insertSeasoningList(items)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun updateSeasoning(item: SeasoningEntity) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.updateSeasoning(item)
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun insertSeasoning(item: SeasoningEntity) = withContext(Dispatchers.IO) {
|
|
||||||
appDao.insertSeasoning(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//
|
|
||||||
//class SeasoningRepository(val seasoningDao: SeasoningDao) {
|
|
||||||
// val seasoningList: Flow<List<SeasoningEntity>> = seasoningDao.getAllStream()
|
|
||||||
//
|
|
||||||
// fun addSeasoning(item: SeasoningEntity) = withContext(Dispatchers.IO) {
|
|
||||||
// seasoningDao.insert(item)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun searchSeasoning(query: String) = withContext(Dispatchers.IO) {
|
|
||||||
// seasoningDao.search(query)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//class CookFoodRepository(val cookFoodDao: CookFoodDao) {
|
|
||||||
// fun getCookFood(foodId: String, cookMode:Int = 0) = withContext(Dispatchers.IO) {
|
|
||||||
// cookFoodDao.getCookFoodById(foodId, cookMode)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun getCookFoodByList(cookMode:Int = 0) = withContext(Dispatchers.IO) {
|
|
||||||
// cookFoodDao.getCookFoodList(cookMode)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fun countCookFood(cookMode:Int = 0)= withContext(Dispatchers.IO) {
|
|
||||||
// cookFoodDao.countCookFood(cookMode)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//class CookFoodGoodsRepository(val cookFoodGoodsDao: CookFoodGoodsDao) {
|
|
||||||
// fun getFoodGoodsList(foodId: String) = withContext(Dispatchers.IO) {
|
|
||||||
// cookFoodGoodsDao.getCookFoodGoodsList(foodId)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
|
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
package com.shuwei.dish.match.db
|
||||||
|
|
||||||
|
import com.shuwei.dish.match.base.BaseApp
|
||||||
|
import com.shuwei.dish.match.db.entity.CookFoodEntity
|
||||||
|
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
|
import com.shuwei.dish.match.db.entity.SeasoningEntity
|
||||||
|
import com.shuwei.dish.match.db.entity.SeasoningSlotEntity
|
||||||
|
import androidx.sqlite.db.SupportSQLiteQuery
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
|
||||||
|
class DbRepository {
|
||||||
|
|
||||||
|
private val db = BaseApp.instance!!.database
|
||||||
|
|
||||||
|
suspend fun insertCookFood(item: CookFoodEntity) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodDao().insertCookFood(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun updateCookFood(item: CookFoodEntity) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodDao().updateCookFood(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getCookFoodById(foodId: String, cookMode: Int, dinnerType: String) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodDao().getCookFoodById(BaseApp.canteenId, foodId, cookMode, dinnerType)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getCookFoodList(cookMode: Int, dinnerType: String) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodDao().getCookFoodList(BaseApp.canteenId, cookMode, dinnerType)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun countCookFood(cookMode: Int) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodDao().countCookFood(BaseApp.canteenId, cookMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun deleteCookFood(foodId: String, cookMode: Int, dinnerType: String) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodDao().deleteCookFood(BaseApp.canteenId, foodId, cookMode, dinnerType)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 接口提交成功后逻辑删除菜品,同时把 submitState 置 1 */
|
||||||
|
suspend fun markSubmittedAndDelete(foodId: String, cookMode: Int, dinnerType: String) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodDao().markSubmittedAndDelete(BaseApp.canteenId, foodId, cookMode, dinnerType)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun deleteCookFoodGoodsList(pid: Long, foodId: String) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodGoodsDao().deleteCookFoodGoodsList(pid, foodId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 仅逻辑删除调料行(materialType = 3),主辅材不动 */
|
||||||
|
suspend fun deleteSeasoningOnly(pid: Long, foodId: String) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodGoodsDao().deleteSeasoningOnly(pid, foodId)
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
suspend fun insertGoodsList(items: MutableList<CookFoodGoodsEntity>) =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodGoodsDao().insertGoodsList(items)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getCookFoodGoodsList(pid: Long, foodId: String) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodGoodsDao().getCookFoodGoodsList(pid, foodId)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getCookFoodGoodsListByType(
|
||||||
|
foodId: String,
|
||||||
|
materialType: Int
|
||||||
|
) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodGoodsDao().getCookFoodGoodsListByType(foodId, materialType)
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
suspend fun getSeasoningById(id: Long) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().getSeasoningById(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getSeasoningBySort(sort: Int) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().getSeasoningBySort(sort)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getSeasoningByGoodsId(goodsId: String) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().getSeasoningByGoodsId(goodsId)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getAllStream() = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().getAllStream()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun search(query: String) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().search(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun clearAllSeasoning() = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().clearAllSeasoning()
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun deleteSeasoningBySort(sort: Int) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().deleteSeasoningBySort(sort)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun insertSeasoningList(items: MutableList<SeasoningEntity>) =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().insertSeasoningList(items)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun updateSeasoning(item: SeasoningEntity) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().updateSeasoning(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun insertSeasoning(item: SeasoningEntity) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().insertSeasoning(item)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按 goodsId 查重后 upsert:存在则更新,不存在则插入
|
||||||
|
* 确保同一个 goodsId 在 dm_seasoning 中只有一条记录
|
||||||
|
*/
|
||||||
|
suspend fun upsertSeasoningByGoodsId(item: SeasoningEntity) = withContext(Dispatchers.IO) {
|
||||||
|
val existing = db.seasoningDao().getSeasoningByGoodsId(item.goodsId)
|
||||||
|
if (existing != null) {
|
||||||
|
db.seasoningDao().updateSeasoning(item.also { it.id = existing.id })
|
||||||
|
} else {
|
||||||
|
item.id = 0
|
||||||
|
db.seasoningDao().insertSeasoning(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询指定设备是否已配置调料槽位
|
||||||
|
* @param deviceId 目标设备 ID
|
||||||
|
* @return true 表示已有配置,false 表示未配置
|
||||||
|
*/
|
||||||
|
suspend fun hasSeasoningSlotConfig(deviceId: String) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningSlotDao().queryByDeviceId(deviceId).isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询所有设备的调料槽位配置
|
||||||
|
*/
|
||||||
|
suspend fun getAllSeasoningSlots() = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningSlotDao().queryAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询指定设备的调料槽位配置
|
||||||
|
* @param deviceId 目标设备 ID
|
||||||
|
*/
|
||||||
|
suspend fun getSeasoningSlotsByDeviceId(deviceId: String) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningSlotDao().queryByDeviceId(deviceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入或更新单个调料槽位配置
|
||||||
|
*/
|
||||||
|
suspend fun upsertSeasoningSlot(slot: SeasoningSlotEntity) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningSlotDao().upsert(slot)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量插入或更新调料槽位配置
|
||||||
|
*/
|
||||||
|
suspend fun upsertAllSeasoningSlots(slots: List<SeasoningSlotEntity>) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningSlotDao().upsertAll(slots)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定设备的指定槽位配置
|
||||||
|
* @param deviceId 目标设备 ID
|
||||||
|
* @param address 秤硬件地址
|
||||||
|
*/
|
||||||
|
suspend fun deleteSeasoningSlot(deviceId: String, address: Int) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningSlotDao().deleteByDeviceIdAndAddress(deviceId, address)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定设备的全部槽位配置
|
||||||
|
* @param deviceId 目标设备 ID
|
||||||
|
*/
|
||||||
|
suspend fun deleteAllSlotsByDeviceId(deviceId: String) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningSlotDao().deleteAllByDeviceId(deviceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 调试用:查询各表全量数据(含已删除记录)----
|
||||||
|
|
||||||
|
/** 查询 dm_cook_food 全部记录 */
|
||||||
|
suspend fun getAllCookFood() = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodDao().getAllCookFood()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询 dm_cook_food_goods 全部记录 */
|
||||||
|
suspend fun getAllCookFoodGoods() = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodGoodsDao().getAllCookFoodGoods()
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 查询 dm_seasoning 全部记录 */
|
||||||
|
suspend fun getAllSeasoning() = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().getAllSeasoning()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 调试用:分页查询(含 isDel 过滤)----
|
||||||
|
|
||||||
|
suspend fun getCookFoodPaged(showDel: Boolean, limit: Int, offset: Int) =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodDao().getCookFoodPaged(if (showDel) 1 else 0, limit, offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun countCookFoodAll(showDel: Boolean) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodDao().countCookFoodAll(if (showDel) 1 else 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getCookFoodGoodsPaged(showDel: Boolean, limit: Int, offset: Int) =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodGoodsDao().getCookFoodGoodsPaged(if (showDel) 1 else 0, limit, offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun countCookFoodGoodsAll(showDel: Boolean) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodGoodsDao().countCookFoodGoodsAll(if (showDel) 1 else 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getSeasoningPaged(showDel: Boolean, limit: Int, offset: Int) =
|
||||||
|
withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().getSeasoningPaged(if (showDel) 1 else 0, limit, offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun countSeasoningAll(showDel: Boolean) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().countSeasoningAll(if (showDel) 1 else 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getSlotPaged(limit: Int, offset: Int) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningSlotDao().getSlotPaged(limit, offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun countSlotAll() = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningSlotDao().countSlotAll()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- 调试用:动态条件过滤分页查询 ----
|
||||||
|
|
||||||
|
suspend fun getCookFoodPagedFiltered(query: SupportSQLiteQuery) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodDao().queryPagedFiltered(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun countCookFoodFiltered(query: SupportSQLiteQuery) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodDao().countFiltered(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getCookFoodGoodsPagedFiltered(query: SupportSQLiteQuery) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodGoodsDao().queryPagedFiltered(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun countCookFoodGoodsFiltered(query: SupportSQLiteQuery) = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodGoodsDao().countFiltered(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getSeasoningPagedFiltered(query: SupportSQLiteQuery) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().queryPagedFiltered(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun countSeasoningFiltered(query: SupportSQLiteQuery) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningDao().countFiltered(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getSlotPagedFiltered(query: SupportSQLiteQuery) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningSlotDao().queryPagedFiltered(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun countSlotFiltered(query: SupportSQLiteQuery) = withContext(Dispatchers.IO) {
|
||||||
|
db.seasoningSlotDao().countFiltered(query)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物理清空全部 4 张表的测试数据
|
||||||
|
* 清除顺序:先删子表(食材),再删主表(菜品),最后删配置表(调料、槽位)
|
||||||
|
*/
|
||||||
|
suspend fun clearAllData() = withContext(Dispatchers.IO) {
|
||||||
|
db.cookFoodGoodsDao().deleteAll()
|
||||||
|
db.cookFoodDao().deleteAll()
|
||||||
|
db.seasoningDao().deleteAll()
|
||||||
|
db.seasoningSlotDao().deleteAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//class SeasoningRepository(val seasoningDao: SeasoningDao) {
|
||||||
|
// val seasoningList: Flow<List<SeasoningEntity>> = seasoningDao.getAllStream()
|
||||||
|
//
|
||||||
|
// fun addSeasoning(item: SeasoningEntity) = withContext(Dispatchers.IO) {
|
||||||
|
// seasoningDao.insert(item)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun searchSeasoning(query: String) = withContext(Dispatchers.IO) {
|
||||||
|
// seasoningDao.search(query)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//class CookFoodRepository(val cookFoodDao: CookFoodDao) {
|
||||||
|
// fun getCookFood(foodId: String, cookMode:Int = 0) = withContext(Dispatchers.IO) {
|
||||||
|
// cookFoodDao.getCookFoodById(foodId, cookMode)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun getCookFoodByList(cookMode:Int = 0) = withContext(Dispatchers.IO) {
|
||||||
|
// cookFoodDao.getCookFoodList(cookMode)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// fun countCookFood(cookMode:Int = 0)= withContext(Dispatchers.IO) {
|
||||||
|
// cookFoodDao.countCookFood(cookMode)
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//class CookFoodGoodsRepository(val cookFoodGoodsDao: CookFoodGoodsDao) {
|
||||||
|
// fun getFoodGoodsList(foodId: String) = withContext(Dispatchers.IO) {
|
||||||
|
// cookFoodGoodsDao.getCookFoodGoodsList(foodId)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//}
|
||||||
|
|
||||||
@@ -0,0 +1,623 @@
|
|||||||
|
package com.shuwei.dish.match.db
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.sqlite.db.SimpleSQLiteQuery
|
||||||
|
import com.shuwei.dish.match.model.CollectedFoodItem
|
||||||
|
import com.shuwei.dish.match.db.entity.CookFoodEntity
|
||||||
|
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
|
import com.shuwei.dish.match.db.entity.SeasoningEntity
|
||||||
|
import com.shuwei.dish.match.db.entity.SeasoningSlotEntity
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
|
||||||
|
class DbViewModel : ViewModel() {
|
||||||
|
|
||||||
|
private val rep = DbRepository()
|
||||||
|
|
||||||
|
fun updateCookFood(entity: CookFoodEntity) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
rep.updateCookFood(entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _cookFoodDetailState = MutableStateFlow<CookFoodEntity?>(null)
|
||||||
|
val cookFoodDetailState: StateFlow<CookFoodEntity?> = _cookFoodDetailState.asStateFlow()
|
||||||
|
|
||||||
|
fun getCookFoodById(foodId: String, cookMode: Int, dinnerType: String) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_cookFoodDetailState.value = rep.getCookFoodById(foodId, cookMode, dinnerType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _cookFoodListState = MutableStateFlow<MutableList<CookFoodEntity>?>(null)
|
||||||
|
val cookFoodListState: StateFlow<MutableList<CookFoodEntity>?> = _cookFoodListState.asStateFlow()
|
||||||
|
fun resetCookFoodList() {
|
||||||
|
_cookFoodListState.value = null
|
||||||
|
}
|
||||||
|
fun getCookFoodList(
|
||||||
|
cookMode: Int,
|
||||||
|
dinnerType: String = "0"
|
||||||
|
) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_cookFoodListState.value = rep.getCookFoodList(cookMode, dinnerType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询本地烹饪中数据(回调版本),结果通过 onResult 直接回调,不经过 StateFlow
|
||||||
|
* 适合不需要跨生命周期持续监听的一次性查询场景
|
||||||
|
*/
|
||||||
|
fun getCookFoodListWithCallback(
|
||||||
|
cookMode: Int,
|
||||||
|
dinnerType: String = "0",
|
||||||
|
onResult: (MutableList<CookFoodEntity>?) -> Unit
|
||||||
|
) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
onResult(rep.getCookFoodList(cookMode, dinnerType))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 直接返回本地烹饪中数据,供需要串行等待结果的场景使用(如先查库再发网络请求)
|
||||||
|
*/
|
||||||
|
suspend fun getCookFoodListDirect(
|
||||||
|
cookMode: Int,
|
||||||
|
dinnerType: String = "0"
|
||||||
|
): MutableList<CookFoodEntity>? {
|
||||||
|
return rep.getCookFoodList(cookMode, dinnerType)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun countCookFood(cookMode: Int): Int {
|
||||||
|
return rep.countCookFood(cookMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fun saveCookFood(cookMode: Int, entity: CookFoodEntity) {
|
||||||
|
// viewModelScope.launch {
|
||||||
|
// val data = rep.getCookFoodById(entity.foodId, cookMode)
|
||||||
|
// if (data == null) {
|
||||||
|
// rep.insertCookFood(entity)
|
||||||
|
// return@launch
|
||||||
|
// }
|
||||||
|
// rep.updateCookFood(entity)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
suspend fun saveCookFoodAndGoods(
|
||||||
|
cookMode: Int,
|
||||||
|
entity: CookFoodEntity,
|
||||||
|
list: MutableList<CookFoodGoodsEntity>?
|
||||||
|
) {
|
||||||
|
val data = rep.getCookFoodById(entity.foodId, cookMode, entity.dinnerType ?: "0")
|
||||||
|
if (data == null) {
|
||||||
|
// 首次保存:主表 + 主辅材 + 调料 全量 insert
|
||||||
|
rep.insertCookFood(entity)
|
||||||
|
val newData = rep.getCookFoodById(entity.foodId, cookMode, entity.dinnerType ?: "0")
|
||||||
|
// 回填 id,防止下次调用时 getCookFoodById 查不到而重复插入主辅材
|
||||||
|
newData?.let { entity.id = it.id }
|
||||||
|
list?.let {
|
||||||
|
it.forEach { goods ->
|
||||||
|
goods.id = 0
|
||||||
|
goods.pid = newData?.id ?: 0
|
||||||
|
}
|
||||||
|
rep.insertGoodsList(it)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 已存在:主表与主辅材保持不变,仅重建调料部分,避免主表/主辅材累积逻辑删除脏数据
|
||||||
|
rep.deleteSeasoningOnly(data.id, entity.foodId)
|
||||||
|
val seasoningList = list?.filter { it.materialType == 3 }?.toMutableList()
|
||||||
|
if (!seasoningList.isNullOrEmpty()) {
|
||||||
|
seasoningList.forEach { goods ->
|
||||||
|
goods.id = 0
|
||||||
|
goods.pid = data.id
|
||||||
|
goods.foodId = entity.foodId
|
||||||
|
}
|
||||||
|
rep.insertGoodsList(seasoningList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun deleteCookFoodAndGoods(cookMode: Int, foodId: String, dinnerType: String) {
|
||||||
|
val data = rep.getCookFoodById(foodId, cookMode, dinnerType)
|
||||||
|
if (data != null) {
|
||||||
|
rep.deleteCookFood(foodId = foodId, cookMode = cookMode, dinnerType = dinnerType)
|
||||||
|
rep.deleteCookFoodGoodsList(pid = data.id, foodId = foodId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接口提交成功后删除本地菜品草稿(异步版本,绑定 viewModelScope)
|
||||||
|
* 与 [markSubmittedAndDelete] 的区别:不是 suspend,内部用 viewModelScope 启动协程,
|
||||||
|
* 不受调用方 Activity 生命周期影响,适合 singleTask 跳转前触发删除的场景
|
||||||
|
*/
|
||||||
|
fun markSubmittedAndDeleteAsync(cookMode: Int, foodId: String, dinnerType: String) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
markSubmittedAndDelete(cookMode, foodId, dinnerType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接口提交成功后删除本地菜品草稿
|
||||||
|
* 与 [deleteCookFoodAndGoods] 的区别:主表 submitState 会被置 1,便于审计区分手动删除与接口删除
|
||||||
|
*/
|
||||||
|
suspend fun markSubmittedAndDelete(cookMode: Int, foodId: String, dinnerType: String) {
|
||||||
|
val data = rep.getCookFoodById(foodId, cookMode, dinnerType)
|
||||||
|
if (data != null) {
|
||||||
|
rep.markSubmittedAndDelete(foodId = foodId, cookMode = cookMode, dinnerType = dinnerType)
|
||||||
|
rep.deleteCookFoodGoodsList(pid = data.id, foodId = foodId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
suspend fun getCookFoodGoodsList(
|
||||||
|
foodId: String,
|
||||||
|
cookMode: Int,
|
||||||
|
dinnerType: String
|
||||||
|
): MutableList<CookFoodGoodsEntity> {
|
||||||
|
val cookFood = rep.getCookFoodById(foodId, cookMode, dinnerType)
|
||||||
|
return if (cookFood != null) rep.getCookFoodGoodsList(pid = cookFood.id, foodId = cookFood.foodId)
|
||||||
|
else mutableListOf()
|
||||||
|
}
|
||||||
|
|
||||||
|
// fun updateGoods(entity: CookFoodGoodsEntity) {
|
||||||
|
// viewModelScope.launch {
|
||||||
|
// rep.updateGoods(entity)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fun saveCookFoodGoods(list: MutableList<CookFoodGoodsEntity>) {
|
||||||
|
// viewModelScope.launch {
|
||||||
|
// val foodId = list[0].foodId
|
||||||
|
// val data: MutableList<CookFoodGoodsEntity>? =
|
||||||
|
// rep.getCookFoodGoodsList(foodId!!)
|
||||||
|
// if (data.isNullOrEmpty()) {
|
||||||
|
// rep.insertGoodsList(list)
|
||||||
|
// return@launch
|
||||||
|
// }
|
||||||
|
// val localDbSeasoningList = rep.getCookFoodGoodsListByType(foodId, 3)
|
||||||
|
// localDbSeasoningList.forEach {
|
||||||
|
// it.isDel = 1
|
||||||
|
// //更新本地调料数据为已删除的状态
|
||||||
|
// rep.updateGoods(it)
|
||||||
|
// }
|
||||||
|
// //筛选出调料数据保存,主辅材不会变更不需要再次处理
|
||||||
|
// val saveSeasoningList = list.filter { it.materialType == 3 }
|
||||||
|
// rep.insertGoodsList(saveSeasoningList.toMutableList())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// fun addSeasoning(list: MutableList<SeasoningEntity>, callback: () -> Unit) {
|
||||||
|
// viewModelScope.launch {
|
||||||
|
// rep.deleteBatch()
|
||||||
|
// rep.insertSeasoningList(items = list)
|
||||||
|
// callback()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
private val loadSeasoningMutex = Mutex()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本地调料列表状态流
|
||||||
|
*/
|
||||||
|
private val _seasoningState = MutableStateFlow<MutableList<SeasoningEntity>>(mutableListOf())
|
||||||
|
val seasoningState: StateFlow<MutableList<SeasoningEntity>> = _seasoningState.asStateFlow()
|
||||||
|
|
||||||
|
fun loadSeasoning() {
|
||||||
|
if (loadSeasoningMutex.isLocked) return
|
||||||
|
viewModelScope.launch {
|
||||||
|
loadSeasoningMutex.withLock {
|
||||||
|
_seasoningState.value = rep.getAllStream()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有设备调料槽位配置的 UI 状态流
|
||||||
|
*/
|
||||||
|
private val _seasoningSlotState = MutableStateFlow<List<SeasoningSlotEntity>>(emptyList())
|
||||||
|
val seasoningSlotState: StateFlow<List<SeasoningSlotEntity>> = _seasoningSlotState.asStateFlow()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询所有调料槽位配置,更新 seasoningSlotState 并返回结果
|
||||||
|
* 声明为 suspend,调用方可在同一协程中直接使用返回值,无需等待 StateFlow 更新
|
||||||
|
*/
|
||||||
|
suspend fun loadSeasoningSlot(): List<SeasoningSlotEntity> {
|
||||||
|
val slots = rep.getAllSeasoningSlots()
|
||||||
|
_seasoningSlotState.value = slots
|
||||||
|
return slots
|
||||||
|
}
|
||||||
|
|
||||||
|
fun deleteSeasoningBySort(sort: Int) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
rep.deleteSeasoningBySort(sort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _clearAllSeasoningState = MutableStateFlow(false)
|
||||||
|
val clearAllSeasoningState: StateFlow<Boolean> = _clearAllSeasoningState.asStateFlow()
|
||||||
|
|
||||||
|
fun clearAllSeasoning() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
rep.clearAllSeasoning()
|
||||||
|
_clearAllSeasoningState.value = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val _hasSeasoningSlotConfigState = MutableStateFlow(false)
|
||||||
|
val hasSeasoningSlotConfigState: StateFlow<Boolean> = _hasSeasoningSlotConfigState.asStateFlow()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询指定设备是否已配置调料槽位
|
||||||
|
* @param deviceId 目标设备 ID
|
||||||
|
*/
|
||||||
|
fun hasSeasoningSlotConfig(deviceId: String) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_hasSeasoningSlotConfigState.value = rep.hasSeasoningSlotConfig(deviceId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询指定设备的调料槽位配置
|
||||||
|
*/
|
||||||
|
suspend fun getSeasoningSlotsByDeviceId(deviceId: String) =
|
||||||
|
rep.getSeasoningSlotsByDeviceId(deviceId)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入或更新单个调料槽位配置
|
||||||
|
*/
|
||||||
|
suspend fun upsertSeasoningSlot(slot: SeasoningSlotEntity) =
|
||||||
|
rep.upsertSeasoningSlot(slot)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量插入或更新调料槽位配置
|
||||||
|
*/
|
||||||
|
suspend fun upsertAllSeasoningSlots(slots: List<SeasoningSlotEntity>) =
|
||||||
|
rep.upsertAllSeasoningSlots(slots)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定设备的指定槽位配置
|
||||||
|
* @param deviceId 目标设备 ID
|
||||||
|
* @param address 秤硬件地址
|
||||||
|
*/
|
||||||
|
suspend fun deleteSeasoningSlot(deviceId: String, address: Int) =
|
||||||
|
rep.deleteSeasoningSlot(deviceId, address)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定设备的全部槽位配置(子设备接收全量广播时先清空再写入)
|
||||||
|
* @param deviceId 目标设备 ID
|
||||||
|
*/
|
||||||
|
suspend fun deleteAllSlotsByDeviceId(deviceId: String) =
|
||||||
|
rep.deleteAllSlotsByDeviceId(deviceId)
|
||||||
|
|
||||||
|
// ---- 数据库调试查看 ----
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物理清空全部 4 张表的测试数据,完成后通过回调通知 UI
|
||||||
|
* @param onDone 清除完成后在主线程执行的回调
|
||||||
|
*/
|
||||||
|
fun clearAllData(onDone: () -> Unit) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
rep.clearAllData()
|
||||||
|
onDone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/** 每页加载条数 */
|
||||||
|
const val DB_INSPECT_PAGE_SIZE = 50
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单条数据库记录的展示模型
|
||||||
|
* @param isDel 是否已逻辑删除
|
||||||
|
* @param fields 字段名-值对列表,按顺序排列
|
||||||
|
* @param columnsPerRow 每行显示的列数,默认 3;槽位表传 1 保持单列
|
||||||
|
*/
|
||||||
|
data class DbRecord(
|
||||||
|
val isDel: Boolean,
|
||||||
|
val fields: List<Pair<String, String>>,
|
||||||
|
val columnsPerRow: Int = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库调试页面 UI 状态
|
||||||
|
* @param items 当前已加载的记录列表
|
||||||
|
* @param totalCount 当前过滤条件下的总记录数
|
||||||
|
* @param hasMore 是否还有更多数据可加载
|
||||||
|
* @param isLoading 是否正在加载(首次加载或加载更多)
|
||||||
|
* @param filter 当前生效的筛选条件,供"加载更多"复用
|
||||||
|
*/
|
||||||
|
data class DbInspectUiState(
|
||||||
|
val items: List<DbRecord> = emptyList(),
|
||||||
|
val totalCount: Int = 0,
|
||||||
|
val hasMore: Boolean = false,
|
||||||
|
val isLoading: Boolean = false,
|
||||||
|
val filter: DbInspectFilter = DbInspectFilter()
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据库调试页面筛选条件
|
||||||
|
* @param showDel 是否包含已删除记录
|
||||||
|
* @param exactFields 精确匹配字段:列名 → 值
|
||||||
|
* @param likeFields 模糊匹配字段:列名 → 值(自动加 %value%)
|
||||||
|
*/
|
||||||
|
data class DbInspectFilter(
|
||||||
|
val showDel: Boolean = true,
|
||||||
|
val exactFields: Map<String, String> = emptyMap(),
|
||||||
|
val likeFields: Map<String, String> = emptyMap()
|
||||||
|
)
|
||||||
|
|
||||||
|
private val _dbInspectState = MutableStateFlow(DbInspectUiState())
|
||||||
|
val dbInspectState: StateFlow<DbInspectUiState> = _dbInspectState.asStateFlow()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载指定表的第一页数据(切换 Tab / 修改筛选条件时调用)
|
||||||
|
* @param tableIndex 0=菜品 1=食材 2=调料 3=槽位
|
||||||
|
* @param filter 筛选条件,包含 showDel 和各字段过滤值
|
||||||
|
*/
|
||||||
|
fun loadDbInspect(tableIndex: Int, filter: DbInspectFilter) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
// 立即清空旧数据并显示加载状态,避免切换 Tab 时旧数据闪现
|
||||||
|
_dbInspectState.value = DbInspectUiState(isLoading = true, filter = filter)
|
||||||
|
val (items, total) = queryPage(tableIndex, filter, offset = 0)
|
||||||
|
_dbInspectState.value = DbInspectUiState(
|
||||||
|
items = items,
|
||||||
|
totalCount = total,
|
||||||
|
hasMore = items.size < total,
|
||||||
|
isLoading = false,
|
||||||
|
filter = filter
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 追加加载下一页数据(点击"加载更多"时调用)
|
||||||
|
* 筛选条件从当前 state 中复用,无需重新传入
|
||||||
|
* @param tableIndex 0=菜品 1=食材 2=调料 3=槽位
|
||||||
|
*/
|
||||||
|
fun loadMoreDbInspect(tableIndex: Int) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
val current = _dbInspectState.value
|
||||||
|
// 已在加载中或无更多数据时直接返回,防止重复请求
|
||||||
|
if (!current.hasMore || current.isLoading) return@launch
|
||||||
|
_dbInspectState.value = current.copy(isLoading = true)
|
||||||
|
val (newItems, total) = queryPage(tableIndex, current.filter, offset = current.items.size)
|
||||||
|
val merged = current.items + newItems
|
||||||
|
_dbInspectState.value = DbInspectUiState(
|
||||||
|
items = merged,
|
||||||
|
totalCount = total,
|
||||||
|
hasMore = merged.size < total,
|
||||||
|
isLoading = false,
|
||||||
|
filter = current.filter
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行分页查询,返回 DbRecord 列表和总记录数
|
||||||
|
* 通过 buildQueries 将 filter 转换为动态 SQL
|
||||||
|
*/
|
||||||
|
private suspend fun queryPage(
|
||||||
|
tableIndex: Int,
|
||||||
|
filter: DbInspectFilter,
|
||||||
|
offset: Int
|
||||||
|
): Pair<List<DbRecord>, Int> {
|
||||||
|
val limit = DB_INSPECT_PAGE_SIZE
|
||||||
|
return when (tableIndex) {
|
||||||
|
0 -> {
|
||||||
|
val (pageQ, countQ) = buildQueries("dm_cook_food", "createTime DESC", true, filter, limit, offset)
|
||||||
|
val total = rep.countCookFoodFiltered(countQ)
|
||||||
|
val rows = rep.getCookFoodPagedFiltered(pageQ).map { e ->
|
||||||
|
DbRecord(
|
||||||
|
isDel = e.isDel == 1,
|
||||||
|
fields = listOf(
|
||||||
|
"id" to "${e.id}", "foodId" to "${e.foodId}", "foodName" to "${e.foodName}",
|
||||||
|
"canteenId" to "${e.canteenId}", "foodWeight" to "${e.foodWeight}", "cookMode" to "${e.cookMode}",
|
||||||
|
"dinnerType" to "${e.dinnerType}", "isDel" to "${e.isDel}", "submitState" to "${e.submitState}",
|
||||||
|
"createTime" to "${e.createTime}"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
rows to total
|
||||||
|
}
|
||||||
|
1 -> {
|
||||||
|
val (pageQ, countQ) = buildQueries("dm_cook_food_goods", "createTime DESC", true, filter, limit, offset)
|
||||||
|
val total = rep.countCookFoodGoodsFiltered(countQ)
|
||||||
|
val rows = rep.getCookFoodGoodsPagedFiltered(pageQ).map { e ->
|
||||||
|
DbRecord(
|
||||||
|
isDel = e.isDel == 1,
|
||||||
|
fields = listOf(
|
||||||
|
"id" to "${e.id}", "pid" to "${e.pid}", "goodsId" to "${e.goodsId}",
|
||||||
|
"goodsName" to "${e.goodsName}", "foodId" to "${e.foodId}", "materialType" to "${e.materialType}",
|
||||||
|
"relateionType" to "${e.relateionType}", "allEdible" to "${e.allEdible}", "useWeight" to "${e.useWeight}",
|
||||||
|
"sort" to "${e.sort}", "zjmCode" to "${e.zjmCode}", "materId" to "${e.materId}",
|
||||||
|
"isDel" to "${e.isDel}", "createTime" to "${e.createTime}"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
rows to total
|
||||||
|
}
|
||||||
|
2 -> {
|
||||||
|
val (pageQ, countQ) = buildQueries("dm_seasoning", "sort ASC", true, filter, limit, offset)
|
||||||
|
val total = rep.countSeasoningFiltered(countQ)
|
||||||
|
val rows = rep.getSeasoningPagedFiltered(pageQ).map { e ->
|
||||||
|
DbRecord(
|
||||||
|
isDel = e.isDel == 1,
|
||||||
|
fields = listOf(
|
||||||
|
"id" to "${e.id}", "goodsId" to "${e.goodsId}", "goodsName" to "${e.goodsName}",
|
||||||
|
"sort" to "${e.sort}", "materialType" to "${e.materialType}", "useWeight" to "${e.useWeight}",
|
||||||
|
"zjmCode" to "${e.zjmCode}", "materId" to "${e.materId}", "isDel" to "${e.isDel}",
|
||||||
|
"createTime" to "${e.createTime}"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
rows to total
|
||||||
|
}
|
||||||
|
3 -> {
|
||||||
|
val (pageQ, countQ) = buildQueries("dm_seasoning_slot", "deviceId ASC, address ASC", false, filter, limit, offset)
|
||||||
|
val total = rep.countSlotFiltered(countQ)
|
||||||
|
val rows = rep.getSlotPagedFiltered(pageQ).map { e ->
|
||||||
|
DbRecord(
|
||||||
|
isDel = false,
|
||||||
|
fields = listOf(
|
||||||
|
"deviceId" to e.deviceId, "address" to "${e.address}",
|
||||||
|
"goodsId" to e.goodsId, "goodsName" to e.goodsName
|
||||||
|
),
|
||||||
|
columnsPerRow = 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
rows to total
|
||||||
|
}
|
||||||
|
else -> emptyList<DbRecord>() to 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据筛选条件动态构建分页查询和计数查询的 SQL
|
||||||
|
* @param tableName 表名
|
||||||
|
* @param orderBy ORDER BY 子句(不含关键字)
|
||||||
|
* @param hasIsDel 是否有 isDel 字段,无则忽略 showDel 参数
|
||||||
|
* @param filter 筛选条件
|
||||||
|
* @param limit 分页大小
|
||||||
|
* @param offset 偏移量
|
||||||
|
* @return Pair<分页查询, 计数查询>
|
||||||
|
*/
|
||||||
|
private fun buildQueries(
|
||||||
|
tableName: String,
|
||||||
|
orderBy: String,
|
||||||
|
hasIsDel: Boolean,
|
||||||
|
filter: DbInspectFilter,
|
||||||
|
limit: Int,
|
||||||
|
offset: Int
|
||||||
|
): Pair<SimpleSQLiteQuery, SimpleSQLiteQuery> {
|
||||||
|
val conditions = mutableListOf<String>()
|
||||||
|
val args = mutableListOf<Any>()
|
||||||
|
|
||||||
|
if (hasIsDel && !filter.showDel) {
|
||||||
|
conditions.add("isDel = 0")
|
||||||
|
}
|
||||||
|
filter.exactFields.forEach { (col, value) ->
|
||||||
|
if (value.isNotBlank()) {
|
||||||
|
conditions.add("$col = ?")
|
||||||
|
args.add(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filter.likeFields.forEach { (col, value) ->
|
||||||
|
if (value.isNotBlank()) {
|
||||||
|
conditions.add("$col LIKE ?")
|
||||||
|
args.add("%$value%")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val where = if (conditions.isEmpty()) "" else "WHERE ${conditions.joinToString(" AND ")}"
|
||||||
|
val pageQuery = SimpleSQLiteQuery(
|
||||||
|
"SELECT * FROM $tableName $where ORDER BY $orderBy LIMIT ? OFFSET ?",
|
||||||
|
(args + limit + offset).toTypedArray()
|
||||||
|
)
|
||||||
|
val countQuery = SimpleSQLiteQuery(
|
||||||
|
"SELECT COUNT(*) FROM $tableName $where",
|
||||||
|
args.toTypedArray()
|
||||||
|
)
|
||||||
|
return pageQuery to countQuery
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// viewModelScope.launch {
|
||||||
|
// list.forEach {
|
||||||
|
// rep.updateSeasoning(it)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
fun saveSeasoning(entity: SeasoningEntity, block: () -> Unit) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
val list = rep.getSeasoningBySort(entity.sort)
|
||||||
|
val size = list?.size?:0
|
||||||
|
if (size == 1) {
|
||||||
|
rep.updateSeasoning(entity.also { it.id = list!![0].id })
|
||||||
|
block()
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
if (size > 1) {
|
||||||
|
list?.forEach {
|
||||||
|
rep.deleteSeasoningBySort(it.sort)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entity.id = 0
|
||||||
|
val id = rep.insertSeasoning(entity)
|
||||||
|
entity.id = id
|
||||||
|
block()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按 goodsId 查重后 upsert 调料数据,确保同一 goodsId 只有一条记录
|
||||||
|
*/
|
||||||
|
suspend fun upsertSeasoningByGoodsId(entity: SeasoningEntity) {
|
||||||
|
rep.upsertSeasoningByGoodsId(entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 按 goodsId 查询调料详情
|
||||||
|
*/
|
||||||
|
suspend fun getSeasoningByGoodsId(goodsId: String): SeasoningEntity? {
|
||||||
|
return rep.getSeasoningByGoodsId(goodsId)
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已采集食材列表 UI 状态流
|
||||||
|
* 元素为按名称分组后的(名称,数量)数据
|
||||||
|
*/
|
||||||
|
private val _collectedFoodListState = MutableStateFlow<List<CollectedFoodItem>>(emptyList())
|
||||||
|
val collectedFoodListState: StateFlow<List<CollectedFoodItem>> = _collectedFoodListState.asStateFlow()
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 加载已采集食材列表,按名称分组统计数量
|
||||||
|
// * 使用属性查询只读 name 字段,不加载 foodVector,节省内存
|
||||||
|
// * @param nameFilter 名称过滤关键词,为空时加载全部
|
||||||
|
// */
|
||||||
|
// fun loadCollectedFoodList(nameFilter: String? = null) {
|
||||||
|
// viewModelScope.launch {
|
||||||
|
// val result = ObjectBox.queryFoodNameCounts(nameFilter)
|
||||||
|
// _collectedFoodListState.value = result.map { (name, count) ->
|
||||||
|
// CollectedFoodItem(foodName = name, collectCount = count)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 删除指定名称的所有采集记录,删除完成后刷新列表
|
||||||
|
// * @param foodName 食材名称
|
||||||
|
// * @param nameFilter 当前搜索关键词,用于删除后刷新列表
|
||||||
|
// */
|
||||||
|
// fun removeCollectedFood(foodName: String, nameFilter: String? = null) {
|
||||||
|
// viewModelScope.launch {
|
||||||
|
// ObjectBox.remove(foodName)
|
||||||
|
// loadCollectedFoodList(nameFilter)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 清除所有向量采集数据,完成后刷新列表
|
||||||
|
// * @param onDone 清除完成后在主线程执行的回调
|
||||||
|
// */
|
||||||
|
// fun clearAllCollectedFood(onDone: (() -> Unit)? = null) {
|
||||||
|
// viewModelScope.launch {
|
||||||
|
// ObjectBox.removeAll()
|
||||||
|
// loadCollectedFoodList()
|
||||||
|
// onDone?.invoke()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------------------------------------
|
||||||
|
}
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
package com.shuwei.dish.match.db.dao
|
|
||||||
|
|
||||||
import androidx.room.Dao
|
|
||||||
import androidx.room.Insert
|
|
||||||
import androidx.room.OnConflictStrategy
|
|
||||||
import androidx.room.Query
|
|
||||||
import androidx.room.Update
|
|
||||||
import com.shuwei.dish.match.entity.CookFoodEntity
|
|
||||||
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
|
||||||
import com.shuwei.dish.match.entity.SeasoningEntity
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
interface AppDao {
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
suspend fun insertCookFood(item: CookFoodEntity): Long
|
|
||||||
|
|
||||||
@Update
|
|
||||||
suspend fun updateCookFood(item: CookFoodEntity)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM dm_cook_food WHERE isDel = 0 AND canteenId = :canteenId AND foodId = :foodId AND cookMode = :cookMode")
|
|
||||||
suspend fun getCookFoodById(canteenId:String, foodId: String, cookMode: Int): CookFoodEntity?
|
|
||||||
|
|
||||||
@Query("SELECT * FROM dm_cook_food WHERE isDel = 0 AND canteenId = :canteenId AND cookMode = :cookMode AND dinnerType = :dinnerType ORDER BY createTime DESC")
|
|
||||||
suspend fun getCookFoodList(canteenId:String, cookMode: Int, dinnerType:String): MutableList<CookFoodEntity>?
|
|
||||||
|
|
||||||
@Query("SELECT count(1) FROM dm_cook_food WHERE isDel = 0 AND canteenId = :canteenId AND cookMode = :cookMode")
|
|
||||||
suspend fun countCookFood(canteenId:String, cookMode: Int): Int
|
|
||||||
|
|
||||||
@Query("DELETE FROM dm_cook_food WHERE canteenId = :canteenId AND foodId = :foodId AND cookMode = :cookMode")
|
|
||||||
suspend fun deleteCookFood(canteenId:String, foodId: String, cookMode: Int)
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
suspend fun insertGoods(item: CookFoodGoodsEntity): Long
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
suspend fun insertGoodsList(items: MutableList<CookFoodGoodsEntity>): Array<Long>
|
|
||||||
|
|
||||||
@Update
|
|
||||||
suspend fun updateGoods(item: CookFoodGoodsEntity)
|
|
||||||
|
|
||||||
@Query("SELECT * FROM dm_cook_food_goods WHERE isDel = 0 AND pid = :pid AND foodId = :foodId")
|
|
||||||
suspend fun getCookFoodGoodsList(pid:Long, foodId: String): MutableList<CookFoodGoodsEntity>
|
|
||||||
|
|
||||||
@Query("SELECT * FROM dm_cook_food_goods WHERE isDel = 0 AND foodId = :foodId AND materialType = :materialType")
|
|
||||||
suspend fun getCookFoodGoodsListByType(
|
|
||||||
foodId: String,
|
|
||||||
materialType: Int
|
|
||||||
): MutableList<CookFoodGoodsEntity>
|
|
||||||
|
|
||||||
@Query("DELETE FROM dm_cook_food_goods WHERE pid = :pid AND foodId = :foodId")
|
|
||||||
suspend fun deleteCookFoodGoodsList(pid:Long, foodId: String)
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
@Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND id = :id")
|
|
||||||
suspend fun getSeasoningById(id: Long): SeasoningEntity?
|
|
||||||
|
|
||||||
@Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND sort = :sort")
|
|
||||||
suspend fun getSeasoningBySort(sort: Int): MutableList<SeasoningEntity>?
|
|
||||||
|
|
||||||
@Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND goodsId = :goodsId")
|
|
||||||
suspend fun getSeasoningByGoodsId(goodsId: Int): SeasoningEntity?
|
|
||||||
|
|
||||||
// @Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND goodsId != -1 AND goodsName != '' ORDER BY sort ASC")
|
|
||||||
// fun getAllStream(): Flow<MutableList<SeasoningEntity>>
|
|
||||||
|
|
||||||
@Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND goodsId != -1 AND goodsName != '' ORDER BY sort ASC")
|
|
||||||
fun getAllStream(): MutableList<SeasoningEntity>
|
|
||||||
|
|
||||||
@Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND goodsName LIKE '%' || :query || '%'")
|
|
||||||
suspend fun search(query: String): MutableList<SeasoningEntity>
|
|
||||||
|
|
||||||
@Query("DELETE FROM dm_seasoning WHERE isDel = 0 AND sort = :sort")
|
|
||||||
suspend fun deleteSeasoningBySort(sort:Int): Int
|
|
||||||
|
|
||||||
@Query("DELETE FROM dm_seasoning WHERE isDel = 0")
|
|
||||||
suspend fun clearAllSeasoning(): Int
|
|
||||||
|
|
||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
|
||||||
suspend fun insertSeasoningList(items: MutableList<SeasoningEntity>): Array<Long>
|
|
||||||
|
|
||||||
@Update
|
|
||||||
suspend fun updateSeasoning(item: SeasoningEntity)
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
suspend fun insertSeasoning(item: SeasoningEntity): Long
|
|
||||||
//--------------------------------------------------------------------------------------------
|
|
||||||
}
|
|
||||||
@@ -1,20 +1,61 @@
|
|||||||
//package com.shuwei.dish.match.db.dao
|
package com.shuwei.dish.match.db.dao
|
||||||
//
|
|
||||||
//import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
//import androidx.room.Query
|
import androidx.room.Insert
|
||||||
//import com.shuwei.dish.match.db.BaseDao
|
import androidx.room.OnConflictStrategy
|
||||||
//import com.shuwei.dish.match.entity.CookFoodEntity
|
import androidx.room.Query
|
||||||
//
|
import androidx.room.RawQuery
|
||||||
//@Dao
|
import androidx.room.Update
|
||||||
//interface CookFoodDao : BaseDao<CookFoodEntity> {
|
import androidx.sqlite.db.SupportSQLiteQuery
|
||||||
//
|
import com.shuwei.dish.match.db.entity.CookFoodEntity
|
||||||
// @Query("SELECT * FROM dm_cook_food WHERE isDel = 0 AND foodId = :foodId AND cookMode = :cookMode")
|
|
||||||
// suspend fun getCookFoodById(foodId: String, cookMode:Int): CookFoodEntity?
|
@Dao
|
||||||
//
|
interface CookFoodDao {
|
||||||
// @Query("SELECT * FROM dm_cook_food WHERE isDel = 0 AND cookMode = :cookMode")
|
|
||||||
// suspend fun getCookFoodList(cookMode:Int): MutableList<CookFoodEntity>?
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
//
|
suspend fun insertCookFood(item: CookFoodEntity): Long
|
||||||
// @Query("SELECT count(1) FROM dm_cook_food WHERE isDel = 0 AND cookMode = :cookMode")
|
|
||||||
// suspend fun countCookFood(cookMode:Int): Int
|
@Update
|
||||||
//
|
suspend fun updateCookFood(item: CookFoodEntity)
|
||||||
//}
|
|
||||||
|
@Query("SELECT * FROM dm_cook_food WHERE isDel = 0 AND canteenId = :canteenId AND foodId = :foodId AND cookMode = :cookMode AND dinnerType = :dinnerType")
|
||||||
|
suspend fun getCookFoodById(canteenId: String, foodId: String, cookMode: Int, dinnerType: String): CookFoodEntity?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM dm_cook_food WHERE isDel = 0 AND canteenId = :canteenId AND cookMode = :cookMode AND dinnerType = :dinnerType ORDER BY createTime DESC")
|
||||||
|
suspend fun getCookFoodList(canteenId: String, cookMode: Int, dinnerType: String): MutableList<CookFoodEntity>?
|
||||||
|
|
||||||
|
@Query("SELECT count(1) FROM dm_cook_food WHERE isDel = 0 AND canteenId = :canteenId AND cookMode = :cookMode")
|
||||||
|
suspend fun countCookFood(canteenId: String, cookMode: Int): Int
|
||||||
|
|
||||||
|
// @Query("DELETE FROM dm_cook_food WHERE canteenId = :canteenId AND foodId = :foodId AND cookMode = :cookMode")
|
||||||
|
@Query("UPDATE dm_cook_food SET isDel = 1 WHERE isDel = 0 AND canteenId = :canteenId AND foodId = :foodId AND cookMode = :cookMode AND dinnerType = :dinnerType")
|
||||||
|
suspend fun deleteCookFood(canteenId: String, foodId: String, cookMode: Int, dinnerType: String)
|
||||||
|
|
||||||
|
/** 接口提交成功后逻辑删除菜品,同时把 submitState 置 1 以便在数据库审计中区分手动删除 */
|
||||||
|
@Query("UPDATE dm_cook_food SET isDel = 1, submitState = 1 WHERE isDel = 0 AND canteenId = :canteenId AND foodId = :foodId AND cookMode = :cookMode AND dinnerType = :dinnerType")
|
||||||
|
suspend fun markSubmittedAndDelete(canteenId: String, foodId: String, cookMode: Int, dinnerType: String)
|
||||||
|
|
||||||
|
/** 查询全部菜品记录(含已删除),用于数据库调试查看 */
|
||||||
|
@Query("SELECT * FROM dm_cook_food ORDER BY createTime DESC")
|
||||||
|
suspend fun getAllCookFood(): MutableList<CookFoodEntity>
|
||||||
|
|
||||||
|
/** 分页查询菜品记录,showDel=true 时包含已删除记录 */
|
||||||
|
@Query("SELECT * FROM dm_cook_food WHERE (:showDel = 1 OR isDel = 0) ORDER BY createTime DESC LIMIT :limit OFFSET :offset")
|
||||||
|
suspend fun getCookFoodPaged(showDel: Int, limit: Int, offset: Int): List<CookFoodEntity>
|
||||||
|
|
||||||
|
/** 统计菜品记录总数,showDel=true 时包含已删除记录 */
|
||||||
|
@Query("SELECT COUNT(*) FROM dm_cook_food WHERE (:showDel = 1 OR isDel = 0)")
|
||||||
|
suspend fun countCookFoodAll(showDel: Int): Int
|
||||||
|
|
||||||
|
/** 物理清空全表,用于清除测试数据 */
|
||||||
|
@Query("DELETE FROM dm_cook_food")
|
||||||
|
suspend fun deleteAll()
|
||||||
|
|
||||||
|
/** 动态条件分页查询菜品记录,由 ViewModel 构建 SQL */
|
||||||
|
@RawQuery
|
||||||
|
suspend fun queryPagedFiltered(query: SupportSQLiteQuery): List<CookFoodEntity>
|
||||||
|
|
||||||
|
/** 动态条件统计菜品记录总数,由 ViewModel 构建 SQL */
|
||||||
|
@RawQuery
|
||||||
|
suspend fun countFiltered(query: SupportSQLiteQuery): Int
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,29 +1,61 @@
|
|||||||
//package com.shuwei.dish.match.db.dao
|
package com.shuwei.dish.match.db.dao
|
||||||
//
|
|
||||||
//import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
//import androidx.room.Query
|
import androidx.room.Insert
|
||||||
//import com.shuwei.dish.match.db.BaseDao
|
import androidx.room.OnConflictStrategy
|
||||||
//import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
import androidx.room.Query
|
||||||
//
|
import androidx.room.RawQuery
|
||||||
//@Dao
|
import androidx.room.Update
|
||||||
//interface CookFoodGoodsDao : BaseDao<CookFoodGoodsEntity> {
|
import androidx.sqlite.db.SupportSQLiteQuery
|
||||||
//
|
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
// @Query("SELECT * FROM dm_cook_food_goods WHERE isDel = 0 AND foodId = :foodId")
|
|
||||||
// suspend fun getCookFoodGoodsList(foodId: String): MutableList<CookFoodGoodsEntity>
|
@Dao
|
||||||
//
|
interface CookFoodGoodsDao {
|
||||||
// @Query("SELECT * FROM dm_cook_food_goods WHERE isDel = 0 AND foodId = :foodId AND materialType = :materialType")
|
|
||||||
// suspend fun getCookFoodGoodsListByType(foodId: String, materialType:Int): MutableList<CookFoodGoodsEntity>
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
//
|
suspend fun insertGoods(item: CookFoodGoodsEntity): Long
|
||||||
//// @Query(
|
|
||||||
//// """
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
//// UPDATE dm_cook_food_goods
|
suspend fun insertGoodsList(items: MutableList<CookFoodGoodsEntity>): Array<Long>
|
||||||
//// SET goodsName=:entity.goodsName, foodId=:entity.foodId, relateionType=:entity.relateionType, sort=:entity.sort
|
|
||||||
//// allEdible=:entity.allEdible, useWeight=:entity.useWeight, isDel=:entity.isDel, createTime=:entity.createTime
|
@Update
|
||||||
//// WHERE isDel = 0
|
suspend fun updateGoods(item: CookFoodGoodsEntity)
|
||||||
//// AND foodId=:entity.foodId
|
|
||||||
//// AND goodsId=:goodsId
|
@Query("SELECT * FROM dm_cook_food_goods WHERE isDel = 0 AND pid = :pid AND foodId = :foodId")
|
||||||
//// """
|
suspend fun getCookFoodGoodsList(pid: Long, foodId: String): MutableList<CookFoodGoodsEntity>
|
||||||
//// )
|
|
||||||
//// fun updateByGoodsId(entity: CookFoodGoodsEntity)
|
@Query("SELECT * FROM dm_cook_food_goods WHERE isDel = 0 AND foodId = :foodId AND materialType = :materialType")
|
||||||
//
|
suspend fun getCookFoodGoodsListByType(foodId: String, materialType: Int): MutableList<CookFoodGoodsEntity>
|
||||||
//}
|
|
||||||
|
// @Query("DELETE FROM dm_cook_food_goods WHERE pid = :pid AND foodId = :foodId")
|
||||||
|
@Query("UPDATE dm_cook_food_goods SET isDel = 1 WHERE isDel = 0 AND pid = :pid AND foodId = :foodId")
|
||||||
|
suspend fun deleteCookFoodGoodsList(pid: Long, foodId: String)
|
||||||
|
|
||||||
|
/** 仅逻辑删除调料行(materialType = 3),主辅材不动,用于 cook 时只重建调料部分 */
|
||||||
|
@Query("UPDATE dm_cook_food_goods SET isDel = 1 WHERE isDel = 0 AND pid = :pid AND foodId = :foodId AND materialType = 3")
|
||||||
|
suspend fun deleteSeasoningOnly(pid: Long, foodId: String)
|
||||||
|
|
||||||
|
/** 查询全部食材记录(含已删除),用于数据库调试查看 */
|
||||||
|
@Query("SELECT * FROM dm_cook_food_goods ORDER BY createTime DESC")
|
||||||
|
suspend fun getAllCookFoodGoods(): MutableList<CookFoodGoodsEntity>
|
||||||
|
|
||||||
|
/** 分页查询食材记录,showDel=true 时包含已删除记录 */
|
||||||
|
@Query("SELECT * FROM dm_cook_food_goods WHERE (:showDel = 1 OR isDel = 0) ORDER BY createTime DESC LIMIT :limit OFFSET :offset")
|
||||||
|
suspend fun getCookFoodGoodsPaged(showDel: Int, limit: Int, offset: Int): List<CookFoodGoodsEntity>
|
||||||
|
|
||||||
|
/** 统计食材记录总数,showDel=true 时包含已删除记录 */
|
||||||
|
@Query("SELECT COUNT(*) FROM dm_cook_food_goods WHERE (:showDel = 1 OR isDel = 0)")
|
||||||
|
suspend fun countCookFoodGoodsAll(showDel: Int): Int
|
||||||
|
|
||||||
|
/** 物理清空全表,用于清除测试数据 */
|
||||||
|
@Query("DELETE FROM dm_cook_food_goods")
|
||||||
|
suspend fun deleteAll()
|
||||||
|
|
||||||
|
/** 动态条件分页查询食材记录,由 ViewModel 构建 SQL */
|
||||||
|
@RawQuery
|
||||||
|
suspend fun queryPagedFiltered(query: SupportSQLiteQuery): List<CookFoodGoodsEntity>
|
||||||
|
|
||||||
|
/** 动态条件统计食材记录总数,由 ViewModel 构建 SQL */
|
||||||
|
@RawQuery
|
||||||
|
suspend fun countFiltered(query: SupportSQLiteQuery): Int
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,25 +1,70 @@
|
|||||||
//package com.shuwei.dish.match.db.dao
|
package com.shuwei.dish.match.db.dao
|
||||||
//
|
|
||||||
//import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
//import androidx.room.Query
|
import androidx.room.Insert
|
||||||
//import com.shuwei.dish.match.db.BaseDao
|
import androidx.room.OnConflictStrategy
|
||||||
//import com.shuwei.dish.match.entity.SeasoningEntity
|
import androidx.room.Query
|
||||||
//import kotlinx.coroutines.flow.Flow
|
import androidx.room.RawQuery
|
||||||
//
|
import androidx.room.Update
|
||||||
//@Dao
|
import androidx.sqlite.db.SupportSQLiteQuery
|
||||||
//interface SeasoningDao : BaseDao<SeasoningEntity> {
|
import com.shuwei.dish.match.db.entity.SeasoningEntity
|
||||||
//
|
|
||||||
//// @Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND id = :id")
|
@Dao
|
||||||
//// suspend fun getSeasoningById(id: Long): SeasoningEntity?
|
interface SeasoningDao {
|
||||||
////
|
|
||||||
//// @Query("SELECT * FROM dm_seasoning WHERE isDel = 0 ORDER BY sort ASC")
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
//// fun getAllStream(): Flow<MutableList<SeasoningEntity>>
|
suspend fun insertSeasoning(item: SeasoningEntity): Long
|
||||||
////
|
|
||||||
//// @Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND name LIKE '%' || :query || '%'")
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
//// suspend fun search(query: String): MutableList<SeasoningEntity>
|
suspend fun insertSeasoningList(items: MutableList<SeasoningEntity>): Array<Long>
|
||||||
////
|
|
||||||
//// @Query("DELETE FROM dm_seasoning WHERE rowid IN " +
|
@Update
|
||||||
//// "(SELECT rowid FROM dm_seasoning LIMIT 1000)")
|
suspend fun updateSeasoning(item: SeasoningEntity)
|
||||||
//// suspend fun deleteBatch(): Int
|
|
||||||
//
|
@Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND id = :id")
|
||||||
//}
|
suspend fun getSeasoningById(id: Long): SeasoningEntity?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND sort = :sort")
|
||||||
|
suspend fun getSeasoningBySort(sort: Int): MutableList<SeasoningEntity>?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND goodsId = :goodsId")
|
||||||
|
suspend fun getSeasoningByGoodsId(goodsId: String): SeasoningEntity?
|
||||||
|
|
||||||
|
@Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND goodsId != -1 AND goodsName != '' ORDER BY sort ASC")
|
||||||
|
fun getAllStream(): MutableList<SeasoningEntity>
|
||||||
|
|
||||||
|
@Query("SELECT * FROM dm_seasoning WHERE isDel = 0 AND goodsName LIKE '%' || :query || '%'")
|
||||||
|
suspend fun search(query: String): MutableList<SeasoningEntity>
|
||||||
|
|
||||||
|
// @Query("DELETE FROM dm_seasoning WHERE isDel = 0 AND sort = :sort")
|
||||||
|
@Query("UPDATE dm_seasoning SET isDel = 1 WHERE isDel = 0 AND sort = :sort")
|
||||||
|
suspend fun deleteSeasoningBySort(sort: Int): Int
|
||||||
|
|
||||||
|
// @Query("DELETE FROM dm_seasoning WHERE isDel = 0")
|
||||||
|
@Query("UPDATE dm_seasoning SET isDel = 1 WHERE isDel = 0")
|
||||||
|
suspend fun clearAllSeasoning(): Int
|
||||||
|
|
||||||
|
/** 查询全部调料记录(含已删除),用于数据库调试查看 */
|
||||||
|
@Query("SELECT * FROM dm_seasoning ORDER BY sort ASC")
|
||||||
|
suspend fun getAllSeasoning(): MutableList<SeasoningEntity>
|
||||||
|
|
||||||
|
/** 分页查询调料记录,showDel=true 时包含已删除记录 */
|
||||||
|
@Query("SELECT * FROM dm_seasoning WHERE (:showDel = 1 OR isDel = 0) ORDER BY sort ASC LIMIT :limit OFFSET :offset")
|
||||||
|
suspend fun getSeasoningPaged(showDel: Int, limit: Int, offset: Int): List<SeasoningEntity>
|
||||||
|
|
||||||
|
/** 统计调料记录总数,showDel=true 时包含已删除记录 */
|
||||||
|
@Query("SELECT COUNT(*) FROM dm_seasoning WHERE (:showDel = 1 OR isDel = 0)")
|
||||||
|
suspend fun countSeasoningAll(showDel: Int): Int
|
||||||
|
|
||||||
|
/** 物理清空全表,用于清除测试数据(比 clearAllSeasoning 的逻辑删除更彻底) */
|
||||||
|
@Query("DELETE FROM dm_seasoning")
|
||||||
|
suspend fun deleteAll()
|
||||||
|
|
||||||
|
/** 动态条件分页查询调料记录,由 ViewModel 构建 SQL */
|
||||||
|
@RawQuery
|
||||||
|
suspend fun queryPagedFiltered(query: SupportSQLiteQuery): List<SeasoningEntity>
|
||||||
|
|
||||||
|
/** 动态条件统计调料记录总数,由 ViewModel 构建 SQL */
|
||||||
|
@RawQuery
|
||||||
|
suspend fun countFiltered(query: SupportSQLiteQuery): Int
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.shuwei.dish.match.db.dao
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.RawQuery
|
||||||
|
import androidx.sqlite.db.SupportSQLiteQuery
|
||||||
|
import com.shuwei.dish.match.db.entity.SeasoningSlotEntity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调料槽位配置 DAO
|
||||||
|
* 以 (deviceId, address) 为主键做 upsert,保证同一槽位只保留最新配置
|
||||||
|
*/
|
||||||
|
@Dao
|
||||||
|
interface SeasoningSlotDao {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插入或更新单个槽位配置(主键冲突时覆盖)
|
||||||
|
*/
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun upsert(slot: SeasoningSlotEntity)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量插入或更新槽位配置(主设备广播全量时使用)
|
||||||
|
*/
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun upsertAll(slots: List<SeasoningSlotEntity>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询指定设备的全部槽位配置
|
||||||
|
* @param deviceId 目标设备 ID
|
||||||
|
*/
|
||||||
|
@Query("SELECT * FROM dm_seasoning_slot WHERE deviceId = :deviceId")
|
||||||
|
suspend fun queryByDeviceId(deviceId: String): List<SeasoningSlotEntity>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询所有设备的全部槽位配置(主设备广播时使用)
|
||||||
|
*/
|
||||||
|
@Query("SELECT * FROM dm_seasoning_slot")
|
||||||
|
suspend fun queryAll(): List<SeasoningSlotEntity>
|
||||||
|
|
||||||
|
/** 分页查询槽位记录(槽位表无 isDel,showDel 参数忽略) */
|
||||||
|
@Query("SELECT * FROM dm_seasoning_slot ORDER BY deviceId ASC, address ASC LIMIT :limit OFFSET :offset")
|
||||||
|
suspend fun getSlotPaged(limit: Int, offset: Int): List<SeasoningSlotEntity>
|
||||||
|
|
||||||
|
/** 统计槽位记录总数 */
|
||||||
|
@Query("SELECT COUNT(*) FROM dm_seasoning_slot")
|
||||||
|
suspend fun countSlotAll(): Int
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定设备的指定槽位配置
|
||||||
|
* @param deviceId 目标设备 ID
|
||||||
|
* @param address 秤硬件地址
|
||||||
|
*/
|
||||||
|
@Query("DELETE FROM dm_seasoning_slot WHERE deviceId = :deviceId AND address = :address")
|
||||||
|
suspend fun deleteByDeviceIdAndAddress(deviceId: String, address: Int)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除指定设备的全部槽位配置(子设备接收全量广播时先清空再写入)
|
||||||
|
* @param deviceId 目标设备 ID
|
||||||
|
*/
|
||||||
|
@Query("DELETE FROM dm_seasoning_slot WHERE deviceId = :deviceId")
|
||||||
|
suspend fun deleteAllByDeviceId(deviceId: String)
|
||||||
|
|
||||||
|
/** 物理清空全表,用于清除测试数据 */
|
||||||
|
@Query("DELETE FROM dm_seasoning_slot")
|
||||||
|
suspend fun deleteAll()
|
||||||
|
|
||||||
|
/** 动态条件分页查询槽位记录,由 ViewModel 构建 SQL */
|
||||||
|
@RawQuery
|
||||||
|
suspend fun queryPagedFiltered(query: SupportSQLiteQuery): List<SeasoningSlotEntity>
|
||||||
|
|
||||||
|
/** 动态条件统计槽位记录总数,由 ViewModel 构建 SQL */
|
||||||
|
@RawQuery
|
||||||
|
suspend fun countFiltered(query: SupportSQLiteQuery): Int
|
||||||
|
}
|
||||||
+9
-3
@@ -1,4 +1,4 @@
|
|||||||
package com.shuwei.dish.match.entity
|
package com.shuwei.dish.match.db.entity
|
||||||
|
|
||||||
import androidx.room.Entity
|
import androidx.room.Entity
|
||||||
import androidx.room.Ignore
|
import androidx.room.Ignore
|
||||||
@@ -18,11 +18,17 @@ data class CookFoodEntity(
|
|||||||
//0-制作模式,1-采样模式,2-品控模式
|
//0-制作模式,1-采样模式,2-品控模式
|
||||||
var cookMode:Int = 0,
|
var cookMode:Int = 0,
|
||||||
var isDel: Int = 0,
|
var isDel: Int = 0,
|
||||||
|
/** 接口提交状态:0-未提交(本地草稿或手动删除),1-接口提交成功后删除 */
|
||||||
|
var submitState: Int = 0,
|
||||||
var createTime: String = DateTimeUtil.formatDateTime(LocalDateTime.now()),
|
var createTime: String = DateTimeUtil.formatDateTime(LocalDateTime.now()),
|
||||||
var dinnerType: String? = "0",
|
var dinnerType: String? = "0",
|
||||||
) : BaseEntity {
|
) : BaseEntity {
|
||||||
|
// @Ignore
|
||||||
|
// var stFoodInfoConstituteList: MutableList<CookFoodGoodsEntity>? = null
|
||||||
@Ignore
|
@Ignore
|
||||||
var stFoodInfoConstituteList: MutableList<CookFoodGoodsEntity>? = null
|
var matchingConstituteInfoList: MutableList<CookFoodGoodsEntity>? = null
|
||||||
|
@Ignore
|
||||||
|
var foodConstituteList: MutableList<CookFoodGoodsEntity>? = null
|
||||||
|
|
||||||
constructor() : this(foodId = "") // 必需的空构造
|
constructor() : this(foodId = "") // 必需的空构造
|
||||||
}
|
}
|
||||||
+37
-20
@@ -1,9 +1,9 @@
|
|||||||
package com.shuwei.dish.match.entity
|
package com.shuwei.dish.match.db.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.model.GoodsItem
|
||||||
import com.shuwei.dish.match.utils.DateTimeUtil
|
import com.shuwei.dish.match.utils.DateTimeUtil
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
@@ -43,10 +43,14 @@ class CookFoodGoodsEntity(
|
|||||||
*/
|
*/
|
||||||
var materialType: Int = 0,
|
var materialType: Int = 0,
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 物品 是否全部可食:1-全部可食,0-部分可食,默认全部
|
||||||
|
// */
|
||||||
|
// var allEdible: Int = 1,
|
||||||
/**
|
/**
|
||||||
* 物品 是否全部可食:1-全部可食,0-部分可食,默认全部
|
* 物品 是否全部可食:true-全部可食,false-部分可食,默认全部
|
||||||
*/
|
*/
|
||||||
var allEdible: Int = 1,
|
var allEdible: Boolean = true,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 物品 用料重量
|
* 物品 用料重量
|
||||||
@@ -59,23 +63,36 @@ class CookFoodGoodsEntity(
|
|||||||
|
|
||||||
var relateionType_dictText: String? = "",
|
var relateionType_dictText: String? = "",
|
||||||
|
|
||||||
|
var zjmCode: String? = "",
|
||||||
|
|
||||||
|
var materId: String? = "",
|
||||||
|
|
||||||
|
/** 物料编码 */
|
||||||
|
var goodsCode: String? = "",
|
||||||
|
|
||||||
|
/** 净材种类 */
|
||||||
|
var rawMaterialsType: String? = null,
|
||||||
|
|
||||||
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
|
materCode = goodsCode,
|
||||||
var isNewDishType: Boolean = false
|
materialType = materialType,
|
||||||
|
useWeight = useWeight,
|
||||||
@Ignore
|
relateionType = relateionType,
|
||||||
var isClicked: Boolean = false
|
allEdible = allEdible,
|
||||||
}
|
goodsOrRelationCode = goodsOrRelationCode,
|
||||||
|
rawMaterialsType = rawMaterialsType
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package com.shuwei.dish.match.db.entity
|
||||||
|
|
||||||
|
/** 默认调料配置 JSON 反序列化的包装类 */
|
||||||
|
data class ResetReasoningRecord(
|
||||||
|
val list: MutableList<SeasoningEntity> = mutableListOf()
|
||||||
|
)
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package com.shuwei.dish.match.db.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.model.GoodsItem
|
||||||
|
import com.shuwei.dish.match.utils.DateTimeUtil
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
@Entity(tableName = "dm_seasoning")
|
||||||
|
data class SeasoningEntity(
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
var id: Long = 0,
|
||||||
|
/**
|
||||||
|
* 物品id
|
||||||
|
*/
|
||||||
|
var goodsId: String,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物品名称
|
||||||
|
*/
|
||||||
|
var goodsName: String? = null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 菜品id
|
||||||
|
*/
|
||||||
|
var foodId: String? = "",
|
||||||
|
var goodsOrRelationCode: String? = "",
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 食材原材料:1,预制品:2
|
||||||
|
*/
|
||||||
|
var relateionType: Int = 0,
|
||||||
|
/**
|
||||||
|
* 物品类型:1主料2辅料3调料
|
||||||
|
*/
|
||||||
|
var materialType: Int = 3,
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 物品 是否全部可食:1-全部可食,0-部分可食,默认全部
|
||||||
|
// */
|
||||||
|
// var allEdible: Int = 1,
|
||||||
|
/**
|
||||||
|
* 物品 是否全部可食:true-全部可食,false-部分可食,默认全部
|
||||||
|
*/
|
||||||
|
var allEdible: Boolean = true,
|
||||||
|
/**
|
||||||
|
* 物品 用料重量
|
||||||
|
*/
|
||||||
|
var useWeight: Double? = 0.0,
|
||||||
|
|
||||||
|
var popularName: String? = "",
|
||||||
|
|
||||||
|
var canteenId: String? = "",
|
||||||
|
|
||||||
|
var relateionType_dictText: String? = "",
|
||||||
|
|
||||||
|
var zjmCode: String? = "",
|
||||||
|
|
||||||
|
var materId: String? = "",
|
||||||
|
|
||||||
|
/** 物料编码 */
|
||||||
|
var goodsCode: String? = "",
|
||||||
|
|
||||||
|
/** 净材种类 */
|
||||||
|
var rawMaterialsType: String? = null,
|
||||||
|
|
||||||
|
var sort: Int = 9999,
|
||||||
|
/**
|
||||||
|
* isDel表示数据是否已删除,1-已删除,为无效数据,0-正常使用,有效数据
|
||||||
|
*/
|
||||||
|
var isDel: Int = 0,
|
||||||
|
var createTime: String = DateTimeUtil.formatDateTime(LocalDateTime.now())
|
||||||
|
) : BaseEntity {
|
||||||
|
/** UI 状态:格子类型,非数据库字段 */
|
||||||
|
@Ignore var pageType: Int = 0
|
||||||
|
/** UI 状态:是否选中,非数据库字段 */
|
||||||
|
@Ignore var isClicked: Boolean = false
|
||||||
|
|
||||||
|
constructor() : this(goodsId = "") // 必需的空构造
|
||||||
|
|
||||||
|
/** 转换为 GoodsItem,用于 UI 层展示 */
|
||||||
|
fun toGoodsItem(): GoodsItem = GoodsItem(
|
||||||
|
goodsId = goodsId,
|
||||||
|
goodsName = goodsName,
|
||||||
|
popularName = popularName,
|
||||||
|
zjmCode = zjmCode,
|
||||||
|
materId = materId,
|
||||||
|
materialType = materialType,
|
||||||
|
useWeight = useWeight,
|
||||||
|
relateionType = relateionType,
|
||||||
|
allEdible = allEdible,
|
||||||
|
goodsOrRelationCode = goodsOrRelationCode,
|
||||||
|
rawMaterialsType = rawMaterialsType
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.shuwei.dish.match.db.entity
|
||||||
|
|
||||||
|
import androidx.room.Entity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调料槽位配置表,记录每个格子对应哪种调料
|
||||||
|
* 主键为 (deviceId, address) 组合,唯一标识一个物理秤槽位
|
||||||
|
*
|
||||||
|
* @param deviceId 所属设备 ID,用于区分 22格/18格 设备
|
||||||
|
* @param address 秤硬件地址,对应 ScaleDeviceConfig.SCALE_ORDER_22/18 中的值
|
||||||
|
* @param goodsId 调料 ID
|
||||||
|
* @param goodsName 调料名称,用于 adapter 展示
|
||||||
|
*/
|
||||||
|
@Entity(
|
||||||
|
tableName = "dm_seasoning_slot",
|
||||||
|
primaryKeys = ["deviceId", "address"]
|
||||||
|
)
|
||||||
|
data class SeasoningSlotEntity(
|
||||||
|
val deviceId: String,
|
||||||
|
val address: Int,
|
||||||
|
val goodsId: String,
|
||||||
|
val goodsName: String
|
||||||
|
)
|
||||||
@@ -16,14 +16,13 @@ import com.shuwei.dish.match.adapter.GoodsInfoSearchAdapter
|
|||||||
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.DialogBottomSheetBinding
|
import com.shuwei.dish.match.databinding.DialogBottomSheetBinding
|
||||||
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
import com.shuwei.dish.match.model.GoodsItem
|
||||||
import com.shuwei.dish.match.entity.GoodsRecordBean
|
import com.shuwei.dish.match.net.RemoteRepository
|
||||||
import com.shuwei.dish.match.http.HttpUtil
|
import com.shuwei.dish.match.net.UiState
|
||||||
import com.shuwei.dish.match.http.UrlConfig
|
|
||||||
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.toJsonString
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.shuwei.dish.match.utils.ext.toObject
|
import kotlinx.coroutines.launch
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,7 +36,7 @@ class BottomDialog(
|
|||||||
const val TAG = "BottomDialog"
|
const val TAG = "BottomDialog"
|
||||||
}
|
}
|
||||||
|
|
||||||
private var list = mutableListOf<CookFoodGoodsEntity>()
|
private var list = mutableListOf<GoodsItem>()
|
||||||
|
|
||||||
private lateinit var binding: DialogBottomSheetBinding
|
private lateinit var binding: DialogBottomSheetBinding
|
||||||
private lateinit var goodsInfoSearchAdapter: GoodsInfoSearchAdapter
|
private lateinit var goodsInfoSearchAdapter: GoodsInfoSearchAdapter
|
||||||
@@ -45,7 +44,7 @@ class BottomDialog(
|
|||||||
|
|
||||||
private var activity: BaseActivity? = null
|
private var activity: BaseActivity? = null
|
||||||
|
|
||||||
fun show(activity: BaseActivity, callback: (item: CookFoodGoodsEntity) -> Unit) {
|
fun show(activity: BaseActivity, callback: (item: GoodsItem) -> Unit) {
|
||||||
this.activity = activity
|
this.activity = activity
|
||||||
//直接使用BottomSheetDialog
|
//直接使用BottomSheetDialog
|
||||||
var dialog: BottomSheetDialog? = null
|
var dialog: BottomSheetDialog? = null
|
||||||
@@ -142,59 +141,52 @@ class BottomDialog(
|
|||||||
*/
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun getGoodsList() {
|
private fun getGoodsList() {
|
||||||
// val pathSegmentList = UrlConfig.QUERY_GOODS_LIST.split(delimiters = arrayOf("/"), limit = 1)
|
val param = mutableMapOf<String, Any>(
|
||||||
val queryParams = mutableMapOf(
|
|
||||||
"goodsType" to "$goodsType",
|
"goodsType" to "$goodsType",
|
||||||
"canteenId" to BaseApp.canteenId,
|
"placeId" to BaseApp.canteenId,
|
||||||
"pageNo" to "$pageNo",
|
"pageNum" to pageNo,
|
||||||
"pageSize" to "$pageSize"
|
"pageSize" to pageSize
|
||||||
)
|
)
|
||||||
if (goodsName.isNullOrBlank().not()) {
|
if (goodsName.isNullOrBlank().not()) {
|
||||||
queryParams.put("name", goodsName!!)
|
param["goodsName"] = goodsName!!
|
||||||
}
|
}
|
||||||
val sb = StringBuilder().apply {
|
Log.d(TAG, "getGoodsList: param=$param")
|
||||||
append(UrlConfig.QUERY_GOODS_LIST)
|
activity?.lifecycleScope?.launch {
|
||||||
append("?")
|
val state = RemoteRepository().queryGoodsList(param)
|
||||||
queryParams.forEach { (key, value) ->
|
when (state) {
|
||||||
append("$key=$value&")
|
is UiState.Success -> {
|
||||||
|
val records = state.data
|
||||||
|
if (records.isNullOrEmpty()) {
|
||||||
|
activity?.toast(if (goodsType == 1) "暂未搜索到调料信息" else "暂未搜索到食材信息")
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
if (pageNo == 1) {
|
||||||
|
list.clear()
|
||||||
|
}
|
||||||
|
list.addAll(records)
|
||||||
|
goodsInfoSearchAdapter.notifyDataSetChanged()
|
||||||
|
if (pageNo == 1) {
|
||||||
|
binding.refreshLayout.finishRefresh(1200)
|
||||||
|
} else {
|
||||||
|
binding.refreshLayout.finishLoadMore(1200)
|
||||||
|
}
|
||||||
|
val isLoadMoreEnable = records.size >= pageSize
|
||||||
|
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
||||||
|
if (isLoadMoreEnable) {
|
||||||
|
pageNo++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is UiState.Error -> {
|
||||||
|
activity?.toast(state.msg)
|
||||||
|
if (pageNo == 1) {
|
||||||
|
binding.refreshLayout.finishRefresh(1200)
|
||||||
|
} else {
|
||||||
|
binding.refreshLayout.finishLoadMore(1200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb.deleteCharAt(sb.length - 1)
|
|
||||||
Log.d(TAG, "getGoodsList: url = $sb")
|
|
||||||
HttpUtil.get(
|
|
||||||
url = sb.toString(),
|
|
||||||
doSuccess = {
|
|
||||||
val json = it.toJsonString()
|
|
||||||
Log.d(TAG, "getGoodsList: json=$json")
|
|
||||||
val recordBean: GoodsRecordBean? = json.toObject<GoodsRecordBean>()
|
|
||||||
if (recordBean == null || recordBean.records.isNullOrEmpty()) {
|
|
||||||
activity?.toast(if (goodsType == 1) "暂未搜索到调料信息" else "暂未搜索到食材信息")
|
|
||||||
return@get
|
|
||||||
}
|
|
||||||
val records = recordBean.records
|
|
||||||
if (pageNo == 1) {
|
|
||||||
list.clear()
|
|
||||||
}
|
|
||||||
list.addAll(records!!)
|
|
||||||
goodsInfoSearchAdapter.notifyDataSetChanged()
|
|
||||||
if (pageNo == 1) {
|
|
||||||
binding.refreshLayout.finishRefresh(1200)
|
|
||||||
} else {
|
|
||||||
binding.refreshLayout.finishLoadMore(1200)
|
|
||||||
}
|
|
||||||
val isLoadMoreEnable = records.size >= pageSize
|
|
||||||
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
|
||||||
if (isLoadMoreEnable) {
|
|
||||||
pageNo++
|
|
||||||
}
|
|
||||||
}, doFailure = { code, msg ->
|
|
||||||
activity?.toast(msg)
|
|
||||||
if (pageNo == 1) {
|
|
||||||
binding.refreshLayout.finishRefresh(1200)
|
|
||||||
} else {
|
|
||||||
binding.refreshLayout.finishLoadMore(1200)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,20 +23,19 @@ 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.DialogBottomSheet2Binding
|
import com.shuwei.dish.match.databinding.DialogBottomSheet2Binding
|
||||||
import com.shuwei.dish.match.entity.SeasoningEntity
|
import com.shuwei.dish.match.model.GoodsItem
|
||||||
import com.shuwei.dish.match.entity.SeasoningRecordBean
|
import com.shuwei.dish.match.net.RemoteRepository
|
||||||
import com.shuwei.dish.match.http.HttpUtil
|
import com.shuwei.dish.match.net.UiState
|
||||||
import com.shuwei.dish.match.http.UrlConfig
|
|
||||||
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 androidx.lifecycle.lifecycleScope
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
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.roundedOneDecimalPlace
|
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
||||||
import com.shuwei.dish.match.utils.ext.toJsonString
|
|
||||||
import com.shuwei.dish.match.utils.ext.toObject
|
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,7 +51,7 @@ class BottomDialog2(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val goodsType: Int = 1
|
private val goodsType: Int = 1
|
||||||
private var list = mutableListOf<SeasoningEntity>()
|
private var list = mutableListOf<GoodsItem>()
|
||||||
|
|
||||||
private lateinit var binding: DialogBottomSheet2Binding
|
private lateinit var binding: DialogBottomSheet2Binding
|
||||||
private lateinit var searchAdapter: SeasoningSearchAdapter
|
private lateinit var searchAdapter: SeasoningSearchAdapter
|
||||||
@@ -60,7 +59,7 @@ class BottomDialog2(
|
|||||||
|
|
||||||
private var activity: BaseActivity? = null
|
private var activity: BaseActivity? = null
|
||||||
|
|
||||||
fun show(activity: BaseActivity, callback: (item: SeasoningEntity) -> Unit) {
|
fun show(activity: BaseActivity, callback: (item: GoodsItem) -> Unit) {
|
||||||
this.activity = activity
|
this.activity = activity
|
||||||
//直接使用BottomSheetDialog
|
//直接使用BottomSheetDialog
|
||||||
var dialog: BottomSheetDialog? = null
|
var dialog: BottomSheetDialog? = null
|
||||||
@@ -173,58 +172,52 @@ class BottomDialog2(
|
|||||||
*/
|
*/
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun getGoodsList() {
|
private fun getGoodsList() {
|
||||||
val queryParams = mutableMapOf(
|
val param = mutableMapOf<String, Any>(
|
||||||
"goodsType" to "$goodsType",
|
"goodsType" to "$goodsType",
|
||||||
"canteenId" to BaseApp.canteenId,
|
"placeId" to BaseApp.canteenId,
|
||||||
"pageNo" to "$pageNo",
|
"pageNum" to pageNo,
|
||||||
"pageSize" to "$pageSize"
|
"pageSize" to pageSize
|
||||||
)
|
)
|
||||||
if (goodsName.isNullOrBlank().not()) {
|
if (goodsName.isNullOrBlank().not()) {
|
||||||
queryParams.put("name", goodsName!!)
|
param["goodsName"] = goodsName!!
|
||||||
}
|
}
|
||||||
val sb = StringBuilder().apply {
|
Log.d(TAG, "getGoodsList: param=$param")
|
||||||
append(UrlConfig.QUERY_GOODS_LIST)
|
activity?.lifecycleScope?.launch {
|
||||||
append("?")
|
val state = RemoteRepository().queryGoodsList(param)
|
||||||
queryParams.forEach { (key, value) ->
|
when (state) {
|
||||||
append("$key=$value&")
|
is UiState.Success -> {
|
||||||
|
val records = state.data
|
||||||
|
if (records.isNullOrEmpty()) {
|
||||||
|
activity?.toast(if (goodsType == 1) "暂未搜索到调料信息" else "暂未搜索到食材信息")
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
if (pageNo == 1) {
|
||||||
|
list.clear()
|
||||||
|
}
|
||||||
|
list.addAll(records)
|
||||||
|
searchAdapter.notifyDataSetChanged()
|
||||||
|
if (pageNo == 1) {
|
||||||
|
binding.refreshLayout.finishRefresh(1200)
|
||||||
|
} else {
|
||||||
|
binding.refreshLayout.finishLoadMore(1200)
|
||||||
|
}
|
||||||
|
val isLoadMoreEnable = records.size >= pageSize
|
||||||
|
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
||||||
|
if (isLoadMoreEnable) {
|
||||||
|
pageNo++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is UiState.Error -> {
|
||||||
|
activity?.toast(state.msg)
|
||||||
|
if (pageNo == 1) {
|
||||||
|
binding.refreshLayout.finishRefresh(1200)
|
||||||
|
} else {
|
||||||
|
binding.refreshLayout.finishLoadMore(1200)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sb.deleteCharAt(sb.length - 1)
|
|
||||||
Log.d(TAG, "getGoodsList: url = $sb")
|
|
||||||
HttpUtil.get(
|
|
||||||
url = sb.toString(),
|
|
||||||
doSuccess = {
|
|
||||||
val json = it.toJsonString()
|
|
||||||
Log.d(TAG, "getGoodsList: json=$json")
|
|
||||||
val recordBean: SeasoningRecordBean? = json.toObject<SeasoningRecordBean>()
|
|
||||||
if (recordBean == null || recordBean.records.isNullOrEmpty()) {
|
|
||||||
activity?.toast(if (goodsType == 1) "暂未搜索到调料信息" else "暂未搜索到食材信息")
|
|
||||||
return@get
|
|
||||||
}
|
|
||||||
val records = recordBean.records
|
|
||||||
if (pageNo == 1) {
|
|
||||||
list.clear()
|
|
||||||
}
|
|
||||||
list.addAll(records!!)
|
|
||||||
searchAdapter.notifyDataSetChanged()
|
|
||||||
if (pageNo == 1) {
|
|
||||||
binding.refreshLayout.finishRefresh(1200)
|
|
||||||
} else {
|
|
||||||
binding.refreshLayout.finishLoadMore(1200)
|
|
||||||
}
|
|
||||||
val isLoadMoreEnable = records.size >= pageSize
|
|
||||||
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
|
||||||
if (isLoadMoreEnable) {
|
|
||||||
pageNo++
|
|
||||||
}
|
|
||||||
}, doFailure = { code, msg ->
|
|
||||||
activity?.toast(msg)
|
|
||||||
if (pageNo == 1) {
|
|
||||||
binding.refreshLayout.finishRefresh(1200)
|
|
||||||
} else {
|
|
||||||
binding.refreshLayout.finishLoadMore(1200)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getTextSpan(weight: Double): SpannableStringBuilder {
|
fun getTextSpan(weight: Double): SpannableStringBuilder {
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
package com.shuwei.dish.match.entity
|
|
||||||
|
|
||||||
data class HomeModeBean(
|
|
||||||
|
|
||||||
var modeName: String = "",
|
|
||||||
var modeDesc: String = "",
|
|
||||||
var modeIconId: Int = 0,
|
|
||||||
var isLocked: Boolean = false,
|
|
||||||
|
|
||||||
var onClick: (() -> Unit)? = null
|
|
||||||
)
|
|
||||||
|
|
||||||
data class FoodRecordBean(
|
|
||||||
var records: MutableList<FoodRecord>? = null,
|
|
||||||
var total: Int,
|
|
||||||
var size: Int,
|
|
||||||
var current: Int,
|
|
||||||
var page: Int
|
|
||||||
)
|
|
||||||
|
|
||||||
data class GoodsRecordBean(
|
|
||||||
var records: MutableList<CookFoodGoodsEntity>? = null,
|
|
||||||
var total: Int,
|
|
||||||
var size: Int,
|
|
||||||
var current: Int,
|
|
||||||
var page: Int
|
|
||||||
)
|
|
||||||
|
|
||||||
data class SeasoningRecordBean(
|
|
||||||
var records: MutableList<SeasoningEntity>? = null,
|
|
||||||
var total: Int,
|
|
||||||
var size: Int,
|
|
||||||
var current: Int,
|
|
||||||
var page: Int
|
|
||||||
)
|
|
||||||
|
|
||||||
data class ResetReasoningRecord(
|
|
||||||
val list: MutableList<SeasoningEntity>
|
|
||||||
)
|
|
||||||
|
|
||||||
//data class DishDetailEntity(
|
|
||||||
// var foodId: String? = null,
|
|
||||||
// var foodWeight: Double? = null,
|
|
||||||
// var foodRealWeight: Double? = null,
|
|
||||||
// var voList: List<DishPartEntity>? = null
|
|
||||||
//)
|
|
||||||
|
|
||||||
//data class DishPartEntity(
|
|
||||||
// var foodId: String? = null,
|
|
||||||
// var foodName: String? = null,
|
|
||||||
// var foodWeight: Int? = null,
|
|
||||||
// var useWeight: Int? = null,
|
|
||||||
// var useRealWeight: Int? = null,
|
|
||||||
// var goodsId: Int? = null,
|
|
||||||
// var goodsName: String? = null,
|
|
||||||
// var materialType: Int? = null,
|
|
||||||
// var isSetFinished: Boolean = false,
|
|
||||||
// var isItemClicked: Boolean = false,
|
|
||||||
// var isSamplingPage: Boolean = false
|
|
||||||
//)
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package com.shuwei.dish.match.entity
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo
|
|
||||||
import androidx.room.Entity
|
|
||||||
import androidx.room.PrimaryKey
|
|
||||||
import com.shuwei.dish.match.db.BaseEntity
|
|
||||||
|
|
||||||
//@Entity(tableName = "dm_dish")
|
|
||||||
//data class DishEntity (
|
|
||||||
// /**
|
|
||||||
// * 菜品id
|
|
||||||
// */
|
|
||||||
// @PrimaryKey var id: Long,
|
|
||||||
// /**
|
|
||||||
// * 菜品名称
|
|
||||||
// */
|
|
||||||
// var name: String? = "",
|
|
||||||
// /**
|
|
||||||
// * 菜品重量
|
|
||||||
// */
|
|
||||||
// var weight: Int? = 0,
|
|
||||||
//
|
|
||||||
// var sort: Int = 0,
|
|
||||||
// @ColumnInfo(name = "create_time") val createTime: Long = System.currentTimeMillis()
|
|
||||||
//): BaseEntity
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
//package com.shuwei.dish.match.entity
|
|
||||||
//
|
|
||||||
//import androidx.room.Ignore
|
|
||||||
//import androidx.room.PrimaryKey
|
|
||||||
//import com.shuwei.dish.match.db.BaseEntity
|
|
||||||
//
|
|
||||||
//data class GoodsInfoEntity(
|
|
||||||
// @PrimaryKey(autoGenerate = true) var id: Long = 0,
|
|
||||||
// var goodsId: Int,
|
|
||||||
// var goodsName: String? = "",
|
|
||||||
// var popularName: String? = "",
|
|
||||||
// var canteenId: String? = "",
|
|
||||||
// var goodsOrRelationCode: String? = "",
|
|
||||||
// var relateionType: Int? = -1,
|
|
||||||
// var relateionType_dictText: String? = "",
|
|
||||||
//
|
|
||||||
// var sort: Int = 0,
|
|
||||||
//
|
|
||||||
// var swMaterBaseMaterial: String? = "",
|
|
||||||
// var preMaterClass: String? = "",
|
|
||||||
// var preUseWeight: Int? = 0,
|
|
||||||
// var preWeight: Int? = 0,
|
|
||||||
// var oil: String? = "",
|
|
||||||
// var sugar: String? = "",
|
|
||||||
// /**
|
|
||||||
// * isDel表示数据是否已删除,1-已删除,为无效数据,0-正常使用,有效数据
|
|
||||||
// */
|
|
||||||
// var isDel: Int = 0,
|
|
||||||
// val createTime: Long = System.currentTimeMillis()
|
|
||||||
//) : BaseEntity {
|
|
||||||
// @Ignore
|
|
||||||
// var pageType: Int = 0
|
|
||||||
//
|
|
||||||
// @Ignore
|
|
||||||
// var isClicked: Boolean = false
|
|
||||||
//
|
|
||||||
// constructor() : this(id = -1, goodsId = -1) // 必需的空构造
|
|
||||||
//}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
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
|
|
||||||
import java.time.LocalDateTime
|
|
||||||
|
|
||||||
@Entity(tableName = "dm_seasoning")
|
|
||||||
data class SeasoningEntity(
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
|
||||||
var id: Long = 0,
|
|
||||||
/**
|
|
||||||
* 物品id
|
|
||||||
*/
|
|
||||||
var goodsId: String,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 物品名称
|
|
||||||
*/
|
|
||||||
var goodsName: String? = null,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 菜品id
|
|
||||||
*/
|
|
||||||
var foodId: String? = "",
|
|
||||||
var goodsOrRelationCode: String? = "",
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 食材原材料:1,预制品:2
|
|
||||||
*/
|
|
||||||
var relateionType: Int = 0,
|
|
||||||
/**
|
|
||||||
* 物品类型:1主料2辅料3调料
|
|
||||||
*/
|
|
||||||
var materialType: Int = 3,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 物品 是否全部可食:1-全部可食,0-部分可食,默认全部
|
|
||||||
*/
|
|
||||||
var allEdible: Int = 1,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 物品 用料重量
|
|
||||||
*/
|
|
||||||
var useWeight: Double? = 0.0,
|
|
||||||
|
|
||||||
var popularName: String? = "",
|
|
||||||
|
|
||||||
var canteenId: String? = "",
|
|
||||||
|
|
||||||
var relateionType_dictText: String? = "",
|
|
||||||
|
|
||||||
var sort: Int = 9999,
|
|
||||||
/**
|
|
||||||
* isDel表示数据是否已删除,1-已删除,为无效数据,0-正常使用,有效数据
|
|
||||||
*/
|
|
||||||
var isDel: Int = 0,
|
|
||||||
var createTime: String = DateTimeUtil.formatDateTime(LocalDateTime.now())
|
|
||||||
) : BaseEntity {
|
|
||||||
@Ignore
|
|
||||||
var pageType: Int = 0
|
|
||||||
|
|
||||||
@Ignore
|
|
||||||
var isClicked: Boolean = false
|
|
||||||
|
|
||||||
constructor() : this(goodsId = "") // 必需的空构造
|
|
||||||
}
|
|
||||||
@@ -1,199 +0,0 @@
|
|||||||
package com.shuwei.dish.match.http
|
|
||||||
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.util.Log
|
|
||||||
import com.google.gson.reflect.TypeToken
|
|
||||||
import com.shuwei.dish.match.base.BaseApp
|
|
||||||
import com.shuwei.dish.match.base.BaseReq
|
|
||||||
import com.shuwei.dish.match.utils.SpTool
|
|
||||||
import com.shuwei.dish.match.utils.ext.toType
|
|
||||||
import okhttp3.Call
|
|
||||||
import okhttp3.Callback
|
|
||||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
|
||||||
import okhttp3.Request
|
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
|
||||||
import okhttp3.Response
|
|
||||||
import java.io.IOException
|
|
||||||
import java.util.concurrent.Executors
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
|
|
||||||
object HttpUtil {
|
|
||||||
|
|
||||||
var loopGetToken = true
|
|
||||||
|
|
||||||
fun runMainThread(action: () -> Unit) {
|
|
||||||
Handler(Looper.getMainLooper()).post {
|
|
||||||
action()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// GET请求(HTTPS)
|
|
||||||
fun get(
|
|
||||||
url: String,
|
|
||||||
header: Map<String, String>?=null,
|
|
||||||
doSuccess: (data: Any) -> Unit,
|
|
||||||
doFailure: (code: Int?, msg: String?) -> Unit
|
|
||||||
) {
|
|
||||||
val request = Request.Builder()
|
|
||||||
.url(if (url.isHttpApi()) url else UrlConfig.BASE_URL + url)
|
|
||||||
.apply {
|
|
||||||
if (header != null) {
|
|
||||||
header.forEach {
|
|
||||||
addHeader(it.key, it.value)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
val token = getToken()
|
|
||||||
if (token.isNotBlank()) {
|
|
||||||
addHeader("X-Access-Token", token)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.get()
|
|
||||||
.build()
|
|
||||||
HttpClient.instance.newCall(request).enqueue(CallbackImpl(doSuccess, doFailure))
|
|
||||||
}
|
|
||||||
//
|
|
||||||
// fun get(
|
|
||||||
// isHttps: Boolean = false,
|
|
||||||
// host: String = "vip.shuziweidao.com",
|
|
||||||
// pathSegmentList: List<String>,
|
|
||||||
// queryParams: Map<String, String>,
|
|
||||||
// doSuccess: (data: Any) -> Unit,
|
|
||||||
// doFailure: (code: Int?, msg: String?) -> Unit
|
|
||||||
// ) {
|
|
||||||
// val token = getToken()
|
|
||||||
// val url = HttpUrl.Builder()
|
|
||||||
// .scheme(if (isHttps) "https" else "http")
|
|
||||||
// .host(host)
|
|
||||||
// .apply {
|
|
||||||
// pathSegmentList.forEach { addPathSegment(it) }
|
|
||||||
// queryParams.forEach { (key, value) -> addQueryParameter(key, value) }
|
|
||||||
// }
|
|
||||||
// .build()
|
|
||||||
// val request = Request.Builder()
|
|
||||||
// .url(url)
|
|
||||||
// .apply {
|
|
||||||
// if (token.isNotBlank()) {
|
|
||||||
// addHeader("Authorization", token)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// .get()
|
|
||||||
// .build()
|
|
||||||
// HttpClient.instance.newCall(request).enqueue(CallbackImpl(doSuccess, doFailure))
|
|
||||||
// }
|
|
||||||
|
|
||||||
// POST表单(HTTPS)
|
|
||||||
// fun postForm(url: String, params: Map<String, String>, callback: Callback) {
|
|
||||||
// val formBody = FormBody.Builder().apply {
|
|
||||||
// params.forEach { (k, v) -> add(k, v) }
|
|
||||||
// }.build()
|
|
||||||
//
|
|
||||||
// Request.Builder()
|
|
||||||
// .url(url)
|
|
||||||
// .post(formBody)
|
|
||||||
// .build().let { HttpClient.instance.newCall(it).enqueue(callback) }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// POST JSON(HTTPS)
|
|
||||||
fun postJson(
|
|
||||||
url: String,
|
|
||||||
json: String,
|
|
||||||
doSuccess: (data: Any) -> Unit,
|
|
||||||
doFailure: (code: Int?, msg: String?) -> Unit
|
|
||||||
) {
|
|
||||||
val body = json
|
|
||||||
.toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
|
|
||||||
val token = getToken()
|
|
||||||
Request.Builder()
|
|
||||||
.url(if (url.isHttpApi()) url else UrlConfig.BASE_URL + url)
|
|
||||||
.apply {
|
|
||||||
if (token.isNotBlank()) {
|
|
||||||
addHeader("X-Access-Token", token)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.post(body)
|
|
||||||
.build()
|
|
||||||
.let { HttpClient.instance.newCall(it).enqueue(CallbackImpl(doSuccess, doFailure)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val executor = Executors.newSingleThreadScheduledExecutor()
|
|
||||||
var getTokenIsRunning = false
|
|
||||||
private fun exeTokenThread() {
|
|
||||||
if (getTokenIsRunning.not()) {
|
|
||||||
executor.scheduleWithFixedDelay(
|
|
||||||
task, 0, 1, TimeUnit.MINUTES
|
|
||||||
)
|
|
||||||
getTokenIsRunning = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val task = Runnable {
|
|
||||||
if (BaseApp.token.isNullOrBlank()) {
|
|
||||||
getAppToken()
|
|
||||||
} else {
|
|
||||||
executor.shutdown()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getToken() = SpTool.getString(SpTool.TOKEN)
|
|
||||||
//BaseApp.instance?.token ?:""
|
|
||||||
//BaseApp.getSharedPref()?.getString("token", "") ?: ""
|
|
||||||
|
|
||||||
fun getAppToken() {
|
|
||||||
val url = "${UrlConfig.GET_TOKEN}?qrcodeId=${SpTool.getString(SpTool.DEVICE_ID)}"
|
|
||||||
// Log.d(TAG, "getToken: url = $url")
|
|
||||||
get(url = url, doSuccess = {
|
|
||||||
SpTool.put(SpTool.TOKEN, it)
|
|
||||||
BaseApp.token = it.toString()
|
|
||||||
}) { code, msg ->
|
|
||||||
//toast(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CallbackImpl(
|
|
||||||
private val doSuccess: (data: Any) -> Unit,
|
|
||||||
private val doFailure: (code: Int?, msg: String?) -> Unit
|
|
||||||
) :
|
|
||||||
Callback {
|
|
||||||
override fun onFailure(call: Call, e: IOException) {
|
|
||||||
runMainThread {
|
|
||||||
e.printStackTrace()
|
|
||||||
doFailure(-1, "服务异常,${e.message}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResponse(call: Call, response: Response) {
|
|
||||||
val respData = response.body?.string()
|
|
||||||
runMainThread {
|
|
||||||
Log.d("HttpUtil", respData ?: "")
|
|
||||||
runCatching {
|
|
||||||
val typeToken = object : TypeToken<BaseReq<Any>>() {}
|
|
||||||
val baseReq = respData?.toType<BaseReq<Any>>(typeToken = typeToken)
|
|
||||||
if (baseReq == null) {
|
|
||||||
doFailure(-1, "查询数据失败")
|
|
||||||
return@runCatching
|
|
||||||
}
|
|
||||||
if (baseReq.code != 200) {
|
|
||||||
doFailure(baseReq.code, baseReq.message)
|
|
||||||
//baseReq.code == 500 ||
|
|
||||||
if (baseReq.code == 401 && loopGetToken) {
|
|
||||||
exeTokenThread()
|
|
||||||
}
|
|
||||||
return@runCatching
|
|
||||||
}
|
|
||||||
doSuccess(baseReq.result ?: "")
|
|
||||||
}.onFailure {
|
|
||||||
it.printStackTrace()
|
|
||||||
doFailure(-1, "解析异常")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun String.isHttpApi() = this.startsWith("http://") || this.startsWith("https://")
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package com.shuwei.dish.match.http
|
|
||||||
|
|
||||||
import com.shuwei.dish.match.base.BaseApp
|
|
||||||
|
|
||||||
object UrlConfig {
|
|
||||||
private const val DEVICE_BASE_URL = "http://device.shuziweidao.com:8889"
|
|
||||||
/**
|
|
||||||
* device获取token
|
|
||||||
*/
|
|
||||||
const val DEVICE_TOKEN = "${DEVICE_BASE_URL}/sys/getEquipmentToken"
|
|
||||||
/**
|
|
||||||
*获取配置信息
|
|
||||||
*/
|
|
||||||
const val DEVICE_CONFIG = "${DEVICE_BASE_URL}/equipment/stEquipment/queryByEquipmentCode"
|
|
||||||
|
|
||||||
// const val BASE_URL = "http://vip.shuziweidao.com/shuwei-zhct"
|
|
||||||
// const val DISH_DETAIL = "$BASE_URL/scales/goodsUseList?foodId={foodId}&foodWeight={foodWeight}"
|
|
||||||
// const val DISH_LIST = "$BASE_URL/scales/getRestInfoFoods?eaId=99&type=0&foodName"
|
|
||||||
|
|
||||||
// const val BASE_URL = "http://192.168.1.207:9102"
|
|
||||||
const val BASE_URL = "https://yyjk.shuziweidao.com/gateway"
|
|
||||||
// const val DISH_LIST = "$BASE_URL/scales/getRestInfoFoods?eaId=99&type=0&foodName"
|
|
||||||
|
|
||||||
|
|
||||||
var DISH_DETAIL = "${BaseApp.configUrl}/food/stFoodInfoMatching/queryById"
|
|
||||||
|
|
||||||
// "$BASE_URL/scales/generateToken?deviceId=1111111111111111111111111111"
|
|
||||||
|
|
||||||
var GET_TOKEN = "${BaseApp.configUrl}/restaurant/equipment/stEquipment/getEquipmentToken"
|
|
||||||
var SUBMIT_DISH = "${BaseApp.configUrl}/food/stFoodInfoMatching/saveoredit"
|
|
||||||
|
|
||||||
var QUERY_GOODS_LIST = "${BaseApp.configUrl}/food/stFoodInfoMatching/queryGoodsInfoList"
|
|
||||||
var QUERY_FOOD_LIST = "${BaseApp.configUrl}/food/stFoodInfoMatching/list"
|
|
||||||
var SAMPLING_LIST = "${BaseApp.configUrl}/food/stFoodInfoMatching/queryHistorical/goodsInfoList"
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.shuwei.dish.match.model
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已采集食材列表项数据模型
|
||||||
|
* @param foodName 食材名称
|
||||||
|
* @param collectCount 已采集数量
|
||||||
|
*/
|
||||||
|
data class CollectedFoodItem(
|
||||||
|
val foodName: String = "",
|
||||||
|
val collectCount: Int = 0
|
||||||
|
)
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.shuwei.dish.match.model
|
||||||
|
|
||||||
|
import com.shuwei.dish.match.db.entity.CookFoodEntity
|
||||||
|
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 菜品详情接口传输对象(DTO),不依赖 Room
|
||||||
|
* 对应接口:getConstituteByFoodId / saveConstitute
|
||||||
|
*/
|
||||||
|
data class CookFoodDTO(
|
||||||
|
var foodId: String = "",
|
||||||
|
var foodName: String? = null,
|
||||||
|
var canteenId: String? = null,
|
||||||
|
var foodWeight: Double = 0.0,
|
||||||
|
// 0-制作模式,1-采样模式,2-品控模式
|
||||||
|
var cookMode: Int = 0,
|
||||||
|
var dinnerType: String? = "0",
|
||||||
|
// 接口返回的食材构成列表
|
||||||
|
var matchingConstituteInfoList: MutableList<CookFoodGoodsDTO>? = null,
|
||||||
|
var foodConstituteList: MutableList<CookFoodGoodsDTO>? = null
|
||||||
|
) : Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换为 Room 实体,用于写入本地数据库
|
||||||
|
* id/isDel/createTime 由 Room 自行管理,不从 DTO 携带
|
||||||
|
*/
|
||||||
|
fun toEntity(): CookFoodEntity = CookFoodEntity(
|
||||||
|
foodId = foodId,
|
||||||
|
foodName = foodName,
|
||||||
|
canteenId = canteenId,
|
||||||
|
foodWeight = foodWeight,
|
||||||
|
cookMode = cookMode,
|
||||||
|
dinnerType = dinnerType
|
||||||
|
).also { entity ->
|
||||||
|
entity.matchingConstituteInfoList = matchingConstituteInfoList
|
||||||
|
?.map { it.toEntity() }
|
||||||
|
?.toMutableList()
|
||||||
|
entity.foodConstituteList = foodConstituteList
|
||||||
|
?.map { it.toEntity() }
|
||||||
|
?.toMutableList()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package com.shuwei.dish.match.model
|
||||||
|
|
||||||
|
import com.shuwei.dish.match.db.entity.CookFoodEntity
|
||||||
|
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 菜品构成(主辅料/调料)接口传输对象(DTO),不依赖 Room
|
||||||
|
* 对应 CookFoodDTO 中 foodConstituteList、matchingConstituteInfoList 的元素
|
||||||
|
*/
|
||||||
|
data class CookFoodGoodsDTO(
|
||||||
|
var goodsId: String = "",
|
||||||
|
var goodsName: String? = null,
|
||||||
|
var foodId: String? = "",
|
||||||
|
var goodsOrRelationCode: String? = "",
|
||||||
|
// 调料数据顺序
|
||||||
|
var sort: Int = 0,
|
||||||
|
// 食材原材料:1,预制品:2
|
||||||
|
var relateionType: Int = 0,
|
||||||
|
// 物品类型:1主料 2辅料 3调料
|
||||||
|
var materialType: Int = 0,
|
||||||
|
// 物品 是否全部可食:true-全部可食,false-部分可食
|
||||||
|
var allEdible: Boolean = true,
|
||||||
|
// 物品 用料重量
|
||||||
|
var useWeight: Double? = 0.0,
|
||||||
|
var popularName: String? = "",
|
||||||
|
var canteenId: String? = "",
|
||||||
|
var relateionType_dictText: String? = "",
|
||||||
|
var zjmCode: String? = "",
|
||||||
|
var materId: String? = "",
|
||||||
|
// 物料编码
|
||||||
|
var goodsCode: String? = "",
|
||||||
|
// 净材种类
|
||||||
|
var rawMaterialsType: String? = null
|
||||||
|
) : Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换为 GoodsItem,用于 UI 层
|
||||||
|
*/
|
||||||
|
fun toGoodsItem(): GoodsItem = GoodsItem(
|
||||||
|
goodsId = goodsId,
|
||||||
|
goodsName = goodsName,
|
||||||
|
popularName = popularName,
|
||||||
|
zjmCode = zjmCode,
|
||||||
|
materId = materId,
|
||||||
|
materCode = goodsCode,
|
||||||
|
materialType = materialType,
|
||||||
|
useWeight = useWeight,
|
||||||
|
relateionType = relateionType,
|
||||||
|
allEdible = allEdible,
|
||||||
|
goodsOrRelationCode = goodsOrRelationCode,
|
||||||
|
rawMaterialsType = rawMaterialsType
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换为 Room 实体,用于写入本地数据库
|
||||||
|
* id/pid/isDel/createTime 由 Room 自行管理,不从 DTO 携带
|
||||||
|
*/
|
||||||
|
fun toEntity(): CookFoodGoodsEntity = CookFoodGoodsEntity(
|
||||||
|
goodsId = goodsId,
|
||||||
|
goodsName = goodsName,
|
||||||
|
foodId = foodId,
|
||||||
|
goodsOrRelationCode = goodsOrRelationCode,
|
||||||
|
sort = sort,
|
||||||
|
relateionType = relateionType,
|
||||||
|
materialType = materialType,
|
||||||
|
allEdible = allEdible,
|
||||||
|
useWeight = useWeight,
|
||||||
|
popularName = popularName,
|
||||||
|
canteenId = canteenId,
|
||||||
|
relateionType_dictText = relateionType_dictText,
|
||||||
|
zjmCode = zjmCode,
|
||||||
|
materId = materId,
|
||||||
|
goodsCode = goodsCode,
|
||||||
|
rawMaterialsType = rawMaterialsType
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room 实体 → DTO 反向映射,用于将本地数据转为接口提交格式
|
||||||
|
* id/pid/isDel/createTime 为本地数据库字段,不参与提交
|
||||||
|
*/
|
||||||
|
fun CookFoodGoodsEntity.toDTO(): CookFoodGoodsDTO = CookFoodGoodsDTO(
|
||||||
|
goodsId = goodsId,
|
||||||
|
goodsName = goodsName,
|
||||||
|
foodId = foodId,
|
||||||
|
goodsOrRelationCode = goodsOrRelationCode,
|
||||||
|
sort = sort,
|
||||||
|
relateionType = relateionType,
|
||||||
|
materialType = materialType,
|
||||||
|
allEdible = allEdible,
|
||||||
|
useWeight = useWeight,
|
||||||
|
popularName = popularName,
|
||||||
|
canteenId = canteenId,
|
||||||
|
relateionType_dictText = relateionType_dictText,
|
||||||
|
zjmCode = zjmCode,
|
||||||
|
materId = materId,
|
||||||
|
goodsCode = goodsCode,
|
||||||
|
rawMaterialsType = rawMaterialsType
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room 实体 → DTO 反向映射,用于将本地数据转为接口提交格式
|
||||||
|
* id/isDel/createTime 为本地数据库字段,不参与提交
|
||||||
|
*/
|
||||||
|
fun CookFoodEntity.toDTO(): CookFoodDTO = CookFoodDTO(
|
||||||
|
foodId = foodId,
|
||||||
|
foodName = foodName,
|
||||||
|
canteenId = canteenId,
|
||||||
|
foodWeight = foodWeight,
|
||||||
|
cookMode = cookMode,
|
||||||
|
dinnerType = dinnerType,
|
||||||
|
matchingConstituteInfoList = matchingConstituteInfoList
|
||||||
|
?.map { it.toDTO() }
|
||||||
|
?.toMutableList(),
|
||||||
|
foodConstituteList = foodConstituteList
|
||||||
|
?.map { it.toDTO() }
|
||||||
|
?.toMutableList()
|
||||||
|
)
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.shuwei.dish.match.model
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.net.Uri
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
data class HomeModeBean(
|
||||||
|
var modeName: String = "",
|
||||||
|
var modeDesc: String = "",
|
||||||
|
var modeIconId: Int = 0,
|
||||||
|
var isLocked: Boolean = false,
|
||||||
|
|
||||||
|
var onClick: (() -> Unit)? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
data class FoodCollectionBean(
|
||||||
|
var imageUri: Uri? = null,
|
||||||
|
var bitmap: Bitmap? = null,
|
||||||
|
var imageFile: File? = null,
|
||||||
|
var imageVector: FloatArray? = null,
|
||||||
|
var isShowCamera: Boolean = false,
|
||||||
|
var isFinish:Boolean = false,
|
||||||
|
var uploadSuccess:Boolean = false
|
||||||
|
) {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as FoodCollectionBean
|
||||||
|
|
||||||
|
if (isShowCamera != other.isShowCamera) return false
|
||||||
|
if (isFinish != other.isFinish) return false
|
||||||
|
if (uploadSuccess != other.uploadSuccess) return false
|
||||||
|
if (imageUri != other.imageUri) return false
|
||||||
|
if (bitmap != other.bitmap) return false
|
||||||
|
if (imageFile != other.imageFile) return false
|
||||||
|
if (!imageVector.contentEquals(other.imageVector)) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = isShowCamera.hashCode()
|
||||||
|
result = 31 * result + isFinish.hashCode()
|
||||||
|
result = 31 * result + uploadSuccess.hashCode()
|
||||||
|
result = 31 * result + (imageUri?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (bitmap?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (imageFile?.hashCode() ?: 0)
|
||||||
|
result = 31 * result + (imageVector?.contentHashCode() ?: 0)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-3
@@ -1,4 +1,4 @@
|
|||||||
package com.shuwei.dish.match.entity
|
package com.shuwei.dish.match.model
|
||||||
|
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ data class FoodRecord(
|
|||||||
var cookMode: Int = 0,
|
var cookMode: Int = 0,
|
||||||
//1-早餐,2-午餐,3-晚餐
|
//1-早餐,2-午餐,3-晚餐
|
||||||
var dinnerType: String = "0",
|
var dinnerType: String = "0",
|
||||||
|
//true-原始数据,false-非原始数据
|
||||||
|
var isOriginalData: Boolean = true,
|
||||||
var sort: Int = 0
|
var sort: Int = 0
|
||||||
) : Serializable
|
) : Serializable
|
||||||
|
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package com.shuwei.dish.match.model
|
||||||
|
|
||||||
|
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
|
import com.shuwei.dish.match.db.entity.SeasoningEntity
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物品信息接口返回的数据类(DTO),不依赖 Room,同时承载 UI 状态字段
|
||||||
|
* 对应接口:queryGoodsInfoList,食材(goodsType=0)和调料(goodsType=1)共用此结构
|
||||||
|
*/
|
||||||
|
data class GoodsItem(
|
||||||
|
// 接口返回字段
|
||||||
|
var goodsId: String = "",
|
||||||
|
val goodsName: String? = null,
|
||||||
|
val popularName: String? = null,
|
||||||
|
val zjmCode: String? = null,
|
||||||
|
var materId: String? = null,
|
||||||
|
val materCode: 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,
|
||||||
|
// 净材种类(当前选中值)
|
||||||
|
var rawMaterialsType: String? = null,
|
||||||
|
// 净材种类候选列表(临时字段,逗号分隔,不持久化)
|
||||||
|
var rawMaterialsTypes: String? = null,
|
||||||
|
var oldGoodsId: String? = null
|
||||||
|
) : Serializable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物料编码,与查询接口返回的 materCode 同值,统一对外暴露为 goodsCode 供下游使用
|
||||||
|
*/
|
||||||
|
val goodsCode: String? get() = materCode
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换为 CookFoodGoodsEntity,用于写入数据库或传给 SubmitFoodActivity
|
||||||
|
*/
|
||||||
|
fun toCookFoodGoodsEntity(): CookFoodGoodsEntity = CookFoodGoodsEntity(
|
||||||
|
goodsId = goodsId,
|
||||||
|
goodsName = goodsName,
|
||||||
|
popularName = popularName,
|
||||||
|
zjmCode = zjmCode,
|
||||||
|
materId = materId,
|
||||||
|
goodsCode = goodsCode,
|
||||||
|
materialType = materialType,
|
||||||
|
useWeight = useWeight,
|
||||||
|
relateionType = relateionType,
|
||||||
|
allEdible = allEdible,
|
||||||
|
goodsOrRelationCode = goodsOrRelationCode,
|
||||||
|
rawMaterialsType = rawMaterialsType
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 转换为 SeasoningEntity,用于保存调料完整信息到 dm_seasoning
|
||||||
|
*/
|
||||||
|
fun toSeasoningEntity(): SeasoningEntity = SeasoningEntity(
|
||||||
|
goodsId = goodsId,
|
||||||
|
goodsName = goodsName,
|
||||||
|
popularName = popularName,
|
||||||
|
zjmCode = zjmCode,
|
||||||
|
materId = materId,
|
||||||
|
goodsCode = goodsCode,
|
||||||
|
materialType = materialType,
|
||||||
|
relateionType = relateionType,
|
||||||
|
allEdible = allEdible,
|
||||||
|
goodsOrRelationCode = goodsOrRelationCode,
|
||||||
|
rawMaterialsType = rawMaterialsType
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.shuwei.dish.match.model
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物品名称批量查询入参 DTO
|
||||||
|
* 用于 queryGoodsInfoList 接口 goodsNames 字段的元素类型
|
||||||
|
* @param goodsName 物品名称
|
||||||
|
* @param rawMaterialsType 净材种类
|
||||||
|
*/
|
||||||
|
data class GoodsNameQueryDTO(
|
||||||
|
val goodsName: String,
|
||||||
|
val rawMaterialsType: String
|
||||||
|
)
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.shuwei.dish.match.model
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置页面的列表项实体类
|
||||||
|
*
|
||||||
|
* @param type 菜单项类型,用于唯一标识每一项
|
||||||
|
* @param title 主标题文字
|
||||||
|
* @param subtitle 副标题文字,仅部分项目(如菜品模式)有值
|
||||||
|
* @param isHidden 是否为隐藏项,隐藏项需触发开发者模式后才显示
|
||||||
|
* @param onClick 点击回调,初始化时直接注入对应的业务逻辑
|
||||||
|
*/
|
||||||
|
data class SettingItem(
|
||||||
|
val type: Type,
|
||||||
|
val title: String,
|
||||||
|
val subtitle: String? = null,
|
||||||
|
val isHidden: Boolean = false,
|
||||||
|
val onClick: () -> Unit
|
||||||
|
) {
|
||||||
|
/** 设置菜单项类型枚举 */
|
||||||
|
enum class Type {
|
||||||
|
/** 菜品模式切换 */
|
||||||
|
COOK_MODE,
|
||||||
|
/** 调料区设置 */
|
||||||
|
SEASONING_CONFIG,
|
||||||
|
/** 食材采集 */
|
||||||
|
FOOD_COLLECT,
|
||||||
|
/** 减重配置 */
|
||||||
|
WEIGHT_CONFIG,
|
||||||
|
/** 数据库查看(隐藏项) */
|
||||||
|
DB_INSPECT,
|
||||||
|
/** 秤数据监控(隐藏项) */
|
||||||
|
SCALE_OBSERVE,
|
||||||
|
/** 切换环境(隐藏项) */
|
||||||
|
ENV_SWITCH,
|
||||||
|
/** 数据清除(隐藏项) */
|
||||||
|
CLEAR_DATA,
|
||||||
|
/** 测试调料拿取(隐藏项) */
|
||||||
|
TEST_SEASONING,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package com.shuwei.dish.match.net
|
||||||
|
|
||||||
|
import com.shuwei.dish.match.base.GlobalData
|
||||||
|
import com.shuwei.dish.match.model.CookFoodDTO
|
||||||
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
|
import com.shuwei.dish.match.model.GoodsItem
|
||||||
|
import okhttp3.MultipartBody
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import retrofit2.http.Body
|
||||||
|
import retrofit2.http.GET
|
||||||
|
import retrofit2.http.Multipart
|
||||||
|
import retrofit2.http.POST
|
||||||
|
import retrofit2.http.Part
|
||||||
|
import retrofit2.http.PartMap
|
||||||
|
import retrofit2.http.Query
|
||||||
|
import retrofit2.http.Url
|
||||||
|
|
||||||
|
interface ApiService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询菜品详情
|
||||||
|
*/
|
||||||
|
@GET
|
||||||
|
suspend fun getFoodDetail(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/matching/app/getConstituteByFoodId",
|
||||||
|
@Query("foodId") foodId: String
|
||||||
|
): ApiResponse<CookFoodDTO?>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交制作菜品
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
suspend fun submitCookFood(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/matching/app/saveConstitute",
|
||||||
|
@Body param: CookFoodDTO
|
||||||
|
): ApiResponse<Any?>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索菜品
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
suspend fun searchFoodList(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/matching/app/queryPageList",
|
||||||
|
@Body param: MutableMap<String, Any>
|
||||||
|
): ApiResponse<MutableList<FoodRecord>?>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 采样数据
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
suspend fun getSamplingList(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/matching/app/queryHistoryGoodsInfoList",
|
||||||
|
@Body param: MutableMap<String, Any>
|
||||||
|
): ApiResponse<MutableList<FoodRecord>?>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物品信息(食材 goodsType=0,调料 goodsType=1 共用此接口)
|
||||||
|
*/
|
||||||
|
@POST
|
||||||
|
suspend fun queryGoodsList(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/matching/app/queryGoodsInfoList",
|
||||||
|
@Body param: MutableMap<String, Any>
|
||||||
|
): ApiResponse<MutableList<GoodsItem>?>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交采集图片数据
|
||||||
|
*/
|
||||||
|
@Multipart
|
||||||
|
@POST
|
||||||
|
suspend fun uploadFoodVectorData(
|
||||||
|
@Url url: String = "${GlobalData.appBaseUrl}/terminal/neglect/matching/app/addWeighingCollectionData",
|
||||||
|
@PartMap params: MutableMap<String, RequestBody>,
|
||||||
|
@Part foodPics: List<MultipartBody.Part>
|
||||||
|
): ApiResponse<List<String>?>
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.shuwei.dish.match.net
|
||||||
|
|
||||||
|
import java.io.IOException
|
||||||
|
import java.net.ConnectException
|
||||||
|
import java.net.SocketTimeoutException
|
||||||
|
import java.net.UnknownHostException
|
||||||
|
|
||||||
|
// 1. 网络异常类型枚举
|
||||||
|
enum class ErrorType {
|
||||||
|
NETWORK_ERROR, // 网络错误(无网)
|
||||||
|
TIMEOUT_ERROR, // 超时
|
||||||
|
SERVER_ERROR, // 服务器错误(5xx)
|
||||||
|
CLIENT_ERROR, // 客户端错误(4xx)
|
||||||
|
PARSE_ERROR, // 数据解析错误
|
||||||
|
UNKNOWN_ERROR // 未知错误
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 自定义网络异常类
|
||||||
|
class ApiException(
|
||||||
|
val errorType: ErrorType,
|
||||||
|
val errorCode: Int = -1,
|
||||||
|
val errorMsg: String,
|
||||||
|
val throwable: Throwable? = null
|
||||||
|
) : Exception(errorMsg, throwable)
|
||||||
|
|
||||||
|
/** 将任意异常转换为 ApiException,供 safeApiCall 统一使用 */
|
||||||
|
fun getApiException(e: Exception): ApiException = when (e) {
|
||||||
|
is ApiException -> e
|
||||||
|
is UnknownHostException -> ApiException(ErrorType.NETWORK_ERROR, errorMsg = "网络未连接,请检查网络")
|
||||||
|
is SocketTimeoutException -> ApiException(ErrorType.TIMEOUT_ERROR, errorMsg = "请求超时,请稍后重试")
|
||||||
|
is ConnectException -> ApiException(ErrorType.TIMEOUT_ERROR, errorMsg = "连接超时,请检查网络")
|
||||||
|
is IOException -> ApiException(ErrorType.NETWORK_ERROR, errorMsg = "网络异常:${e.message ?: "未知IO错误"}")
|
||||||
|
else -> ApiException(ErrorType.UNKNOWN_ERROR, errorMsg = "未知错误:${e.message ?: "未知"}", throwable = e)
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
//package com.shuwei.dish.match.net
|
||||||
|
//
|
||||||
|
//import android.annotation.SuppressLint
|
||||||
|
//import okhttp3.Interceptor
|
||||||
|
//import okhttp3.Response
|
||||||
|
//import org.apache.http.conn.ConnectTimeoutException
|
||||||
|
//import java.io.IOException
|
||||||
|
//import java.net.SocketTimeoutException
|
||||||
|
//import java.net.UnknownHostException
|
||||||
|
//
|
||||||
|
//class ExceptionInterceptor : Interceptor {
|
||||||
|
// @SuppressLint("SuspiciousIndentation")
|
||||||
|
// override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
// val request = chain.request()
|
||||||
|
// try {
|
||||||
|
// val response = chain.proceed(request)
|
||||||
|
// // 拦截 HTTP 状态码异常(4xx/5xx)
|
||||||
|
// if (!response.isSuccessful) {
|
||||||
|
// val e = ApiException(
|
||||||
|
// errorType = if (response.code >= 500) ErrorType.SERVER_ERROR else ErrorType.CLIENT_ERROR,
|
||||||
|
// errorCode = response.code,
|
||||||
|
// errorMsg = "HTTP错误:${response.code}"
|
||||||
|
// )
|
||||||
|
// throw e
|
||||||
|
// }
|
||||||
|
// return response
|
||||||
|
// } catch (e: Exception) {
|
||||||
|
// // 捕获各类网络异常并转换为自定义异常
|
||||||
|
// val apiException = when (e) {
|
||||||
|
// is UnknownHostException -> ApiException(ErrorType.NETWORK_ERROR, errorMsg = "网络未连接,请检查网络")
|
||||||
|
// is SocketTimeoutException -> ApiException(ErrorType.TIMEOUT_ERROR, errorMsg = "请求超时,请稍后重试")
|
||||||
|
// is ConnectTimeoutException -> ApiException(ErrorType.TIMEOUT_ERROR, errorMsg = "连接超时,请检查网络")
|
||||||
|
// is IOException -> ApiException(ErrorType.NETWORK_ERROR, errorMsg = "网络异常:${e.message ?: "未知IO错误"}")
|
||||||
|
// is ApiException -> e // 已转换的异常直接抛出
|
||||||
|
// else -> ApiException(ErrorType.UNKNOWN_ERROR, errorMsg = "未知错误:${e.message ?: "未知"}", throwable = e)
|
||||||
|
// }
|
||||||
|
// throw apiException
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
+39
-29
@@ -1,20 +1,38 @@
|
|||||||
package com.shuwei.dish.match.http
|
package com.shuwei.dish.match.net
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import okhttp3.Call
|
import com.shuwei.dish.match.base.GlobalData
|
||||||
import okhttp3.Interceptor
|
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
import okhttp3.Response
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
import javax.net.ssl.*
|
import javax.net.ssl.*
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
import java.security.cert.X509Certificate
|
import java.security.cert.X509Certificate
|
||||||
|
import kotlin.apply
|
||||||
|
import kotlin.jvm.java
|
||||||
|
|
||||||
class HttpClient private constructor() {
|
val apiService: ApiService = Retrofit.Builder()
|
||||||
private val client: OkHttpClient by lazy {
|
.baseUrl(GlobalData.appBaseUrl)
|
||||||
|
// .baseUrl(UrlConfig.DEVICE_BASE_URL)
|
||||||
|
.client(HttpManager.instance.client)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build()
|
||||||
|
.create(ApiService::class.java)
|
||||||
|
|
||||||
|
//val apiService2: ApiService2 = Retrofit.Builder()
|
||||||
|
// .baseUrl(UrlConfig.BASE_URL)
|
||||||
|
//// .baseUrl(UrlConfig.DEVICE_BASE_URL)
|
||||||
|
// .client(HttpManager.instance.client)
|
||||||
|
// .addConverterFactory(GsonConverterFactory.create())
|
||||||
|
// .build()
|
||||||
|
// .create(ApiService2::class.java)
|
||||||
|
|
||||||
|
class HttpManager private constructor() {
|
||||||
|
val client: OkHttpClient by lazy {
|
||||||
OkHttpClient.Builder()
|
OkHttpClient.Builder()
|
||||||
.apply {
|
.apply {
|
||||||
connectTimeout(15, TimeUnit.SECONDS)
|
connectTimeout(15, TimeUnit.SECONDS)
|
||||||
@@ -22,40 +40,32 @@ class HttpClient private constructor() {
|
|||||||
writeTimeout(15, TimeUnit.SECONDS)
|
writeTimeout(15, TimeUnit.SECONDS)
|
||||||
sslSocketFactory(createSSLSocketFactory(), TrustAllCerts())
|
sslSocketFactory(createSSLSocketFactory(), TrustAllCerts())
|
||||||
hostnameVerifier { _, _ -> true }
|
hostnameVerifier { _, _ -> true }
|
||||||
//if (BuildConfig.Debug) {
|
addNetworkInterceptor(HttpLoggingInterceptor(logger = {
|
||||||
addInterceptor(LoggingInterceptor())
|
Log.d("HttpManager", "okhttp logger ==>${it}")
|
||||||
// }
|
}).also {
|
||||||
|
it.level = HttpLoggingInterceptor.Level.BODY
|
||||||
|
})
|
||||||
|
addInterceptor(RequestInterceptor())
|
||||||
|
// addInterceptor(ExceptionInterceptor())
|
||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val instance by lazy { HttpClient() }
|
val instance by lazy { HttpManager() }
|
||||||
}
|
|
||||||
|
|
||||||
fun newCall(request: Request): Call = client.newCall(request)
|
|
||||||
|
|
||||||
inner class LoggingInterceptor : Interceptor {
|
|
||||||
override fun intercept(chain: Interceptor.Chain): Response {
|
|
||||||
val request = chain.request()
|
|
||||||
// 打印请求日志
|
|
||||||
Log.d("OkHttp", "--> ${request.method} ${request.url}")
|
|
||||||
|
|
||||||
val response = chain.proceed(request)
|
|
||||||
// 打印响应日志
|
|
||||||
Log.d("OkHttp", "<-- ${response.code} ${response.request.url}")
|
|
||||||
|
|
||||||
return response
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 信任所有证书的TrustManager实现
|
// 信任所有证书的TrustManager实现
|
||||||
@SuppressLint("CustomX509TrustManager")
|
@SuppressLint("CustomX509TrustManager")
|
||||||
class TrustAllCerts : X509TrustManager {
|
class TrustAllCerts : X509TrustManager {
|
||||||
@SuppressLint("TrustAllX509TrustManager")
|
@SuppressLint("TrustAllX509TrustManager")
|
||||||
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {}
|
override fun checkClientTrusted(chain: Array<X509Certificate>, authType: String) {
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("TrustAllX509TrustManager")
|
@SuppressLint("TrustAllX509TrustManager")
|
||||||
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {}
|
override fun checkServerTrusted(chain: Array<X509Certificate>, authType: String) {
|
||||||
|
}
|
||||||
|
|
||||||
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
|
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,258 @@
|
|||||||
|
package com.shuwei.dish.match.net
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.shuwei.dish.match.base.BaseApp
|
||||||
|
import com.shuwei.dish.match.model.CookFoodDTO
|
||||||
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
|
import com.shuwei.dish.match.model.GoodsItem
|
||||||
|
import com.shuwei.dish.match.model.GoodsNameQueryDTO
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||||
|
import okhttp3.MultipartBody
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.RequestBody.Companion.asRequestBody
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络请求 ViewModel,所有网络操作通过 RemoteRepository 发起,不直接依赖 apiService
|
||||||
|
* @param repository 网络数据仓库,默认使用单例实例
|
||||||
|
*/
|
||||||
|
class NetViewModel(
|
||||||
|
private val repository: RemoteRepository = RemoteRepository()
|
||||||
|
) : ViewModel() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交制作菜品的 UI 状态流,UI 层通过 collect 监听
|
||||||
|
*/
|
||||||
|
private val _submitCookFoodState = MutableStateFlow<UiState<Any?>>(UiState.Idle)
|
||||||
|
val submitCookFoodState: StateFlow<UiState<Any?>> = _submitCookFoodState.asStateFlow()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提交制作菜品
|
||||||
|
*/
|
||||||
|
fun submitCookFood(entity: CookFoodDTO) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_submitCookFoodState.value = UiState.Loading
|
||||||
|
_submitCookFoodState.value = repository.submitCookFood(entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询菜品详情的 UI 状态流,UI 层通过 collect 监听
|
||||||
|
*/
|
||||||
|
private val _foodDetailState = MutableStateFlow<UiState<CookFoodDTO?>>(UiState.Idle)
|
||||||
|
val foodDetailState: StateFlow<UiState<CookFoodDTO?>> = _foodDetailState.asStateFlow()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询菜品详情
|
||||||
|
*/
|
||||||
|
fun getFoodDetail(foodId: String) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_foodDetailState.value = UiState.Loading
|
||||||
|
_foodDetailState.value = repository.getFoodDetail(foodId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resetFoodDetailState() {
|
||||||
|
_foodDetailState.value = UiState.Idle
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索菜品列表的 UI 状态流。
|
||||||
|
* 使用 replay=1 保证 Fragment 重建后能收到最近一次结果;
|
||||||
|
* emit 时包一层 Event wrapper 打破 equals 去重,确保相同数据也能触发 collect。
|
||||||
|
*/
|
||||||
|
private val _searchFoodState = MutableSharedFlow<UiState<MutableList<FoodRecord>?>>(
|
||||||
|
replay = 1,
|
||||||
|
extraBufferCapacity = 1
|
||||||
|
)
|
||||||
|
val searchFoodState: SharedFlow<UiState<MutableList<FoodRecord>?>> = _searchFoodState.asSharedFlow()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索菜品列表
|
||||||
|
*/
|
||||||
|
fun searchFoodList(param: MutableMap<String, Any>) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
// pageNum=1 时先 emit Idle 重置 replay 缓存,防止相同数据导致 SharedFlow 去重不触发
|
||||||
|
if (param["pageNum"] == 1) {
|
||||||
|
_searchFoodState.emit(UiState.Idle)
|
||||||
|
}
|
||||||
|
_searchFoodState.emit(UiState.Loading)
|
||||||
|
_searchFoodState.emit(repository.searchFoodList(param))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 搜索菜品列表(回调版本),结果通过 onResult 直接回调,不经过 StateFlow/SharedFlow
|
||||||
|
* 适合需要每次都能触发的场景(下拉刷新、上拉加载更多)
|
||||||
|
*/
|
||||||
|
fun searchFoodListWithCallback(
|
||||||
|
param: MutableMap<String, Any>,
|
||||||
|
onLoading: () -> Unit = {},
|
||||||
|
onResult: (UiState<MutableList<FoodRecord>?>) -> Unit
|
||||||
|
) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
onLoading()
|
||||||
|
onResult(repository.searchFoodList(param))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
private val _samplingListState = MutableStateFlow<UiState<MutableList<FoodRecord>?>>(UiState.Idle)
|
||||||
|
val samplingListState: StateFlow<UiState<MutableList<FoodRecord>?>> = _samplingListState.asStateFlow()
|
||||||
|
fun resetSamplingListState() {
|
||||||
|
_samplingListState.value = UiState.Idle
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询采样数据列表
|
||||||
|
*/
|
||||||
|
fun getSamplingList(param: MutableMap<String, Any>) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
_samplingListState.value = UiState.Loading
|
||||||
|
_samplingListState.value = repository.getSamplingList(param)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询采样数据列表(回调版本),结果通过 onResult 直接回调,不经过 StateFlow
|
||||||
|
* 适合不需要跨生命周期持续监听的一次性查询场景
|
||||||
|
*/
|
||||||
|
fun getSamplingListWithCallback(
|
||||||
|
param: MutableMap<String, Any>,
|
||||||
|
onLoading: () -> Unit = {},
|
||||||
|
onResult: (UiState<MutableList<FoodRecord>?>) -> Unit
|
||||||
|
) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
onLoading()
|
||||||
|
onResult(repository.getSamplingList(param))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询物品信息列表的 UI 状态流(食材/调料共用),UI 层通过 collect 监听
|
||||||
|
*/
|
||||||
|
private val _goodsListState = MutableStateFlow<UiState<MutableList<GoodsItem>?>>(UiState.Idle)
|
||||||
|
val goodsListState: StateFlow<UiState<MutableList<GoodsItem>?>> = _goodsListState.asStateFlow()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 食材搜索弹窗专用的 UI 状态流,与 goodsListState 隔离,避免弹窗请求影响其他页面
|
||||||
|
*/
|
||||||
|
private val _foodSearchGoodsListState = MutableStateFlow<UiState<MutableList<GoodsItem>?>>(UiState.Idle)
|
||||||
|
val foodSearchGoodsListState: StateFlow<UiState<MutableList<GoodsItem>?>> = _foodSearchGoodsListState.asStateFlow()
|
||||||
|
|
||||||
|
fun resetGoodsListState() {
|
||||||
|
_goodsListState.value = UiState.Idle
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询物品信息列表(食材 goodsType=0,调料 goodsType=1 共用)
|
||||||
|
* @param goodsType 物品类型:0=食材,1=调料
|
||||||
|
* @param placeId 场所 ID,默认取当前食堂 ID
|
||||||
|
* @param pageNum 页码,默认第 1 页
|
||||||
|
* @param pageSize 每页条数,默认 50
|
||||||
|
* @param goodsName 按名称模糊搜索,为 null 时不传该字段
|
||||||
|
* @param goodsNames 按名称+净材种类列表批量查询,为 null 时不传该字段
|
||||||
|
*/
|
||||||
|
fun queryGoodsList(
|
||||||
|
goodsType: String,
|
||||||
|
placeId: String = BaseApp.canteenId,
|
||||||
|
pageNum: Int = 1,
|
||||||
|
pageSize: Int = 50,
|
||||||
|
goodsName: String? = null,
|
||||||
|
goodsNames: List<GoodsNameQueryDTO>? = null
|
||||||
|
) {
|
||||||
|
val param = mutableMapOf<String, Any>(
|
||||||
|
"goodsType" to goodsType,
|
||||||
|
"placeId" to placeId,
|
||||||
|
"pageNum" to pageNum,
|
||||||
|
"pageSize" to pageSize
|
||||||
|
)
|
||||||
|
goodsName?.let { param["goodsName"] = it }
|
||||||
|
goodsNames?.let { param["goodsNames"] = it }
|
||||||
|
viewModelScope.launch {
|
||||||
|
_goodsListState.value = UiState.Loading
|
||||||
|
_goodsListState.value = repository.queryGoodsList(param)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 食材搜索弹窗专用的查询方法,结果写入 foodSearchGoodsListState,不影响 goodsListState
|
||||||
|
* @param goodsType 物品类型:0=食材,1=调料
|
||||||
|
* @param placeId 场所 ID,默认取当前食堂 ID
|
||||||
|
* @param pageNum 页码,默认第 1 页
|
||||||
|
* @param pageSize 每页条数,默认 50
|
||||||
|
* @param goodsName 按名称模糊搜索,为 null 时不传该字段
|
||||||
|
* @param goodsNames 按名称+净材种类列表批量查询,为 null 时不传该字段
|
||||||
|
*/
|
||||||
|
fun queryFoodSearchGoodsList(
|
||||||
|
goodsType: String,
|
||||||
|
placeId: String = BaseApp.canteenId,
|
||||||
|
pageNum: Int = 1,
|
||||||
|
pageSize: Int = 50,
|
||||||
|
goodsName: String? = null,
|
||||||
|
goodsNames: List<GoodsNameQueryDTO>? = null
|
||||||
|
) {
|
||||||
|
val param = mutableMapOf<String, Any>(
|
||||||
|
"goodsType" to goodsType,
|
||||||
|
"placeId" to placeId,
|
||||||
|
"pageNum" to pageNum,
|
||||||
|
"pageSize" to pageSize
|
||||||
|
)
|
||||||
|
goodsName?.let { param["goodsName"] = it }
|
||||||
|
goodsNames?.let { param["goodsNames"] = it }
|
||||||
|
viewModelScope.launch {
|
||||||
|
_foodSearchGoodsListState.value = UiState.Loading
|
||||||
|
_foodSearchGoodsListState.value = repository.queryGoodsList(param)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传采集菜品信息 UI 状态流,UI 层通过 collect 监听
|
||||||
|
*/
|
||||||
|
private val _uploadCollectState = MutableStateFlow<UiState<List<String>?>>(UiState.Idle)
|
||||||
|
val uploadCollectState: StateFlow<UiState<List<String>?>> = _uploadCollectState.asStateFlow()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传采集菜品信息(触发 StateFlow,适合单次上传场景)
|
||||||
|
*/
|
||||||
|
fun uploadFoodVectorData(
|
||||||
|
fileList: List<File>,
|
||||||
|
params: MutableMap<String, RequestBody>
|
||||||
|
) {
|
||||||
|
val fileParts = fileList.map { file ->
|
||||||
|
file.asRequestBody("multipart/form-data".toMediaTypeOrNull())
|
||||||
|
.let { MultipartBody.Part.createFormData("foodPics", file.name, it) }
|
||||||
|
}
|
||||||
|
viewModelScope.launch {
|
||||||
|
_uploadCollectState.value = UiState.Loading
|
||||||
|
_uploadCollectState.value = repository.uploadFoodVectorData(params, fileParts)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传采集菜品信息(直接返回结果,适合分批循环上传场景)
|
||||||
|
* @param fileList 图片文件列表
|
||||||
|
* @param params 附加参数
|
||||||
|
* @return UiState 包装的结果
|
||||||
|
*/
|
||||||
|
suspend fun uploadFoodVectorDataBatch(
|
||||||
|
fileList: List<File>,
|
||||||
|
params: MutableMap<String, RequestBody>
|
||||||
|
): UiState<List<String>?> {
|
||||||
|
val fileParts = fileList.map { file ->
|
||||||
|
//multipart/form-data image/jpeg
|
||||||
|
file.asRequestBody("multipart/form-data".toMediaTypeOrNull())
|
||||||
|
.let { MultipartBody.Part.createFormData("foodPics", file.name, it) }
|
||||||
|
}
|
||||||
|
return repository.uploadFoodVectorData(params, fileParts)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.shuwei.dish.match.net
|
||||||
|
|
||||||
|
import com.shuwei.dish.match.model.CookFoodDTO
|
||||||
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
|
import com.shuwei.dish.match.model.GoodsItem
|
||||||
|
import okhttp3.MultipartBody
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 网络数据仓库,封装所有 ApiService 调用
|
||||||
|
* ViewModel 不直接接触 apiService,统一通过此类发起网络请求
|
||||||
|
*/
|
||||||
|
class RemoteRepository {
|
||||||
|
|
||||||
|
/** 统一封装 API 调用:处理响应映射和异常转换,返回 UiState */
|
||||||
|
private suspend fun <T> safeApiCall(call: suspend () -> ApiResponse<T>): UiState<T?> {
|
||||||
|
return try {
|
||||||
|
val resp = call()
|
||||||
|
if (resp.isSuccess()) UiState.Success(resp.data)
|
||||||
|
else UiState.Error(resp.code, resp.msg ?: "")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
UiState.Error("-1", getApiException(e).errorMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 提交制作菜品 */
|
||||||
|
suspend fun submitCookFood(entity: CookFoodDTO): UiState<Any?> =
|
||||||
|
safeApiCall { apiService.submitCookFood(param = entity) }
|
||||||
|
|
||||||
|
/** 查询菜品详情 */
|
||||||
|
suspend fun getFoodDetail(foodId: String): UiState<CookFoodDTO?> =
|
||||||
|
safeApiCall { apiService.getFoodDetail(foodId = foodId) }
|
||||||
|
|
||||||
|
/** 搜索菜品列表 */
|
||||||
|
suspend fun searchFoodList(param: MutableMap<String, Any>): UiState<MutableList<FoodRecord>?> =
|
||||||
|
safeApiCall { apiService.searchFoodList(param = param) }
|
||||||
|
|
||||||
|
/** 查询采样数据列表 */
|
||||||
|
suspend fun getSamplingList(param: MutableMap<String, Any>): UiState<MutableList<FoodRecord>?> =
|
||||||
|
safeApiCall { apiService.getSamplingList(param = param) }
|
||||||
|
|
||||||
|
/** 查询物品信息列表(食材 goodsType=0,调料 goodsType=1 共用) */
|
||||||
|
suspend fun queryGoodsList(param: MutableMap<String, Any>): UiState<MutableList<GoodsItem>?> =
|
||||||
|
safeApiCall { apiService.queryGoodsList(param = param) }
|
||||||
|
|
||||||
|
/** 上传采集数据 */
|
||||||
|
suspend fun uploadFoodVectorData(
|
||||||
|
params: MutableMap<String, RequestBody>,
|
||||||
|
foodPics: List<MultipartBody.Part>
|
||||||
|
): UiState<List<String>?> =
|
||||||
|
safeApiCall { apiService.uploadFoodVectorData(params = params, foodPics = foodPics) }
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.shuwei.dish.match.net
|
||||||
|
|
||||||
|
import com.shuwei.dish.match.base.GlobalData
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Response
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求拦截器
|
||||||
|
*/
|
||||||
|
class RequestInterceptor : Interceptor {
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val originalRequest = chain.request()
|
||||||
|
val requestBuilder = originalRequest.newBuilder()
|
||||||
|
.header("X-Access-Token", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJjYW50ZWVuSWQiOiJiZTE1NDgzMS0zNDY2LTNiYTItYTJlYS01NzY1MmM5MTlmZWQiLCJ0eXBlIjoiNCIsInVzZXJJZCI6IjAwMDAwMDAwMDAwMDAwMDAwMDEifQ.sN40cOC-O5WQFrF4IDUs8fFlkNdUKLbJt_rHyTsgYYM")
|
||||||
|
.header("X-DEVICE-CODE", GlobalData.deviceId)
|
||||||
|
.header("authorization", "57ee87183f2a4fa59683ec9ef41c8f5d")
|
||||||
|
|
||||||
|
val newRequest = requestBuilder.build()
|
||||||
|
|
||||||
|
return chain.proceed(newRequest)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.shuwei.dish.match.net
|
||||||
|
|
||||||
|
data class ApiResponse<T>(
|
||||||
|
val code: String,
|
||||||
|
val msg: String? = "",
|
||||||
|
val data: T? = null
|
||||||
|
) {
|
||||||
|
fun isSuccess() = code == "00000"
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.shuwei.dish.match.net
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一 UI 状态模型,用于 ViewModel 向 UI 层传递请求状态
|
||||||
|
* Idle — 初始状态,未发起请求
|
||||||
|
* Loading — 请求进行中
|
||||||
|
* Success — 请求成功,携带数据
|
||||||
|
* Error — 请求失败,携带错误码和错误信息
|
||||||
|
*/
|
||||||
|
sealed class UiState<out T> {
|
||||||
|
object Idle : UiState<Nothing>()
|
||||||
|
object Loading : UiState<Nothing>()
|
||||||
|
data class Success<T>(val data: T) : UiState<T>()
|
||||||
|
data class Error(val code: String, val msg: String) : UiState<Nothing>()
|
||||||
|
}
|
||||||
@@ -9,22 +9,14 @@ 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.util.SparseArray
|
import android.util.SparseArray
|
||||||
import android.util.SparseIntArray
|
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.graphics.toColorInt
|
import androidx.core.graphics.toColorInt
|
||||||
import androidx.core.view.forEach
|
import androidx.core.view.forEach
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.core.content.ContextCompat
|
||||||
|
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.base.BaseApp
|
import com.shuwei.dish.match.db.entity.SeasoningEntity
|
||||||
import com.shuwei.dish.match.databinding.LayoutFoodRemindBinding
|
|
||||||
import com.shuwei.dish.match.db.AppRepository
|
|
||||||
import com.shuwei.dish.match.dialog.CommonDialog
|
|
||||||
import com.shuwei.dish.match.entity.SeasoningEntity
|
|
||||||
import com.shuwei.dish.match.entity.ResetReasoningRecord
|
|
||||||
import com.shuwei.dish.match.utils.AddressUtil
|
import com.shuwei.dish.match.utils.AddressUtil
|
||||||
import com.shuwei.dish.match.utils.JsonAssetsLoader
|
|
||||||
import com.shuwei.dish.match.utils.MultiClickDetector
|
|
||||||
import com.shuwei.dish.match.utils.WeightUtil
|
import com.shuwei.dish.match.utils.WeightUtil
|
||||||
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
|
||||||
@@ -32,13 +24,11 @@ import com.shuwei.dish.match.utils.ext.dp
|
|||||||
import com.shuwei.dish.match.utils.ext.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
|
||||||
import com.shuwei.dish.match.viewmodel.factory.AppFactory
|
|
||||||
import com.shuwei.dish.match.R
|
|
||||||
import com.shuwei.dish.match.adapter.TextCellAdapter
|
|
||||||
import com.shuwei.dish.match.databinding.ActivityDeviceConfigBinding
|
import com.shuwei.dish.match.databinding.ActivityDeviceConfigBinding
|
||||||
import com.shuwei.dish.match.dialog.BottomDialog2
|
import com.shuwei.dish.match.dialog.BottomDialog2
|
||||||
|
import com.shuwei.dish.match.model.GoodsItem
|
||||||
import com.shuwei.dish.match.utils.SpTool
|
import com.shuwei.dish.match.utils.SpTool
|
||||||
|
import com.shuwei.dish.match.utils.TextCellTool
|
||||||
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
|
|
||||||
@@ -64,10 +54,9 @@ class DeviceConfigActivity : BaseActivity() {
|
|||||||
|
|
||||||
private lateinit var binding: ActivityDeviceConfigBinding
|
private lateinit var binding: ActivityDeviceConfigBinding
|
||||||
|
|
||||||
private lateinit var appViewModel: AppViewModel
|
|
||||||
|
|
||||||
private var cookMode: Int = 0
|
private var cookMode: Int = 0
|
||||||
// private val weightArray = SparseIntArray()
|
|
||||||
|
// private val weightArray = SparseIntArray()
|
||||||
private val weightArray = SparseArray<Double>()
|
private val weightArray = SparseArray<Double>()
|
||||||
private val addressArray = AddressUtil.getWeighAddressArray()
|
private val addressArray = AddressUtil.getWeighAddressArray()
|
||||||
|
|
||||||
@@ -76,7 +65,6 @@ class DeviceConfigActivity : BaseActivity() {
|
|||||||
binding = ActivityDeviceConfigBinding.inflate(layoutInflater)
|
binding = ActivityDeviceConfigBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
cookMode = intent.getIntExtra(COOK_MODE, 0)
|
cookMode = intent.getIntExtra(COOK_MODE, 0)
|
||||||
initViewModel()
|
|
||||||
setHeaderBackground()
|
setHeaderBackground()
|
||||||
setTitleBar(titleBarAction = {
|
setTitleBar(titleBarAction = {
|
||||||
it.visible()
|
it.visible()
|
||||||
@@ -84,13 +72,6 @@ class DeviceConfigActivity : BaseActivity() {
|
|||||||
it.text = "设备配置"
|
it.text = "设备配置"
|
||||||
}, rightIconActon = {
|
}, rightIconActon = {
|
||||||
it.gone()
|
it.gone()
|
||||||
// it.alpha = 0.0F
|
|
||||||
// it.setImageResource(R.drawable.ic_setting)
|
|
||||||
// it.setOnClickListener {_->
|
|
||||||
// detector.setOnDelayedMultiClickListener(it) {
|
|
||||||
// defaultDataSettingDialog()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
loadQualitySpan(isEnable = false)
|
loadQualitySpan(isEnable = false)
|
||||||
@@ -144,131 +125,84 @@ class DeviceConfigActivity : BaseActivity() {
|
|||||||
WeightUtil.addWeightListener(
|
WeightUtil.addWeightListener(
|
||||||
weightKey = TAG,
|
weightKey = TAG,
|
||||||
getWeight = { address, state, weight ->
|
getWeight = { address, state, weight ->
|
||||||
Log.d(TAG, "addWeighListener: address=$address,stat=$state,weight=$weight")
|
Log.d(TAG, "addWeighListener: address=$address,stat=$state,weight=$weight")
|
||||||
weightArray.put(address, weight)
|
weightArray.put(address, weight)
|
||||||
val item = seasoningItems.firstOrNull { address == addressArray[it.sort] }
|
val item = seasoningItems.firstOrNull { address == addressArray[it.sort] }
|
||||||
item?.let {
|
item?.let {
|
||||||
it.useWeight = weight.toDouble()
|
it.useWeight = weight
|
||||||
updateGridData(it)
|
updateGridData(it)
|
||||||
}
|
// 根据是否量程溢出切换格子背景色
|
||||||
Log.d(TAG, "addWeighListener: update-----------------------")
|
val frameLayout = binding.include.root.findViewWithTag<FrameLayout>(it.sort.toString())
|
||||||
})
|
frameLayout?.background = if (state == WeightUtil.STATE_OVER_WEIGHT) {
|
||||||
|
ContextCompat.getDrawable(this, R.drawable.shape_red_10_corners)
|
||||||
|
} else {
|
||||||
|
ContextCompat.getDrawable(this, R.drawable.selector_text_cell)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.d(TAG, "addWeighListener: update-----------------------")
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private var seasoningItems = mutableListOf<SeasoningEntity>()
|
private var seasoningItems = mutableListOf<SeasoningEntity>()
|
||||||
private fun addGridItemListener() {
|
|
||||||
binding.include.root.forEach { child ->
|
|
||||||
child.clickWithDebounce {
|
|
||||||
val sort = child.tag.toString().toInt()
|
|
||||||
val entity = seasoningItems.firstOrNull { it.sort == sort } ?: SeasoningEntity()
|
|
||||||
clickGridItem(sort, entity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val detector = MultiClickDetector(targetCount = 10, intervalMs = 800)
|
|
||||||
|
|
||||||
private fun defaultDataSettingDialog() {
|
|
||||||
val remindBinding = LayoutFoodRemindBinding.inflate(layoutInflater)
|
|
||||||
remindBinding.tvDialogTitle.text = "温馨提示"
|
|
||||||
remindBinding.tvDialogContent.text =
|
|
||||||
"您好,使用默认配置作为您的调料数据,则已有配置将被清除,确认吗?"
|
|
||||||
CommonDialog(this).apply {
|
|
||||||
messageView = remindBinding.root
|
|
||||||
leftText = "取消"
|
|
||||||
rightText = "确认"
|
|
||||||
onLeftClick = { dismiss() }
|
|
||||||
onRightClick = {
|
|
||||||
dismiss()
|
|
||||||
resetList()
|
|
||||||
}
|
|
||||||
onDismiss = { hideStatusBar() }
|
|
||||||
}.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun resetList() {
|
|
||||||
runCatching {
|
|
||||||
val record = JsonAssetsLoader.parseJsonFromAssets<ResetReasoningRecord>(
|
|
||||||
this,
|
|
||||||
"default_seasoning_list.json"
|
|
||||||
)
|
|
||||||
// val weightArray = WeightUtil.weightArray
|
|
||||||
appViewModel.clearAllSeasoning {
|
|
||||||
record?.list?.forEach { entity ->
|
|
||||||
entity.useWeight = weightArray[addressArray[entity.sort]].toDouble()
|
|
||||||
appViewModel.saveSeasoning(entity) {
|
|
||||||
updateGridData(entity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// loadSeasoning()
|
|
||||||
}
|
|
||||||
}.onFailure { it.printStackTrace() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initViewModel() {
|
|
||||||
val db = BaseApp.instance!!.database
|
|
||||||
val factory =
|
|
||||||
AppFactory(AppRepository(db.appDao()))
|
|
||||||
appViewModel =
|
|
||||||
ViewModelProvider(this, factory)[AppViewModel::class.java]
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun loadSeasoning() {
|
|
||||||
appViewModel.loadSeasoning {
|
|
||||||
seasoningItems.clear()
|
|
||||||
seasoningItems.addAll(it)
|
|
||||||
initConfigData()
|
|
||||||
setGridData(seasoningItems)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initConfigData() {
|
|
||||||
repeat(12) { num ->
|
|
||||||
val firstOne = seasoningItems.firstOrNull { it.sort == num }
|
|
||||||
if (firstOne == null) {
|
|
||||||
seasoningItems.add(SeasoningEntity().also { it.sort = num })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setGridData(list: MutableList<SeasoningEntity>) {
|
|
||||||
val gridLayout = binding.include.root
|
|
||||||
list.forEach { entity ->
|
|
||||||
val tag = entity.sort.toString()
|
|
||||||
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
|
||||||
TextCellAdapter.loadLayout(frameLayout, entity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateGridData(entity: SeasoningEntity) {
|
private fun updateGridData(entity: SeasoningEntity) {
|
||||||
val gridLayout = binding.include.root
|
val gridLayout = binding.include.root
|
||||||
val tag = entity.sort.toString()
|
val tag = entity.sort.toString()
|
||||||
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
||||||
TextCellAdapter.loadLayout(frameLayout, entity)
|
TextCellTool.loadLayout(frameLayout, entity)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addGridItemListener() {
|
||||||
|
binding.include.root.forEach { child ->
|
||||||
|
child.clickWithDebounce {
|
||||||
|
val sort = child.tag.toString().toInt()
|
||||||
|
val entity = seasoningItems.firstOrNull { it.sort == sort }
|
||||||
|
?: SeasoningEntity().also { it.sort = sort }
|
||||||
|
clickGridItem(sort, entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadSeasoning() {
|
||||||
|
Log.d(TAG, "loadSeasoning,start-----------------------")
|
||||||
|
appViewModel.loadSeasoning { list ->
|
||||||
|
Log.d(TAG, "loadSeasoning,list.size=${list.size}-----------------------")
|
||||||
|
seasoningItems.clear()
|
||||||
|
// 补全缺失的格子:对 0~11 中没有对应 sort 的位置,追加空实体
|
||||||
|
val existingSorts = list.map { it.sort }.toSet()
|
||||||
|
for (index in 0 until 12) {
|
||||||
|
if (index !in existingSorts) {
|
||||||
|
list.add(SeasoningEntity().also { it.sort = index })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
seasoningItems.addAll(list)
|
||||||
|
// 按 sort 字段找到对应 FrameLayout,填充数据
|
||||||
|
list.forEach { entity ->
|
||||||
|
val tag = entity.sort.toString()
|
||||||
|
val frameLayout = binding.include.root.findViewWithTag<FrameLayout>(tag)
|
||||||
|
frameLayout?.let { TextCellTool.loadLayout(it, entity) }
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun clickGridItem(sort: Int, entity: SeasoningEntity) {
|
private fun clickGridItem(sort: Int, entity: SeasoningEntity) {
|
||||||
val currentAddress = AddressUtil.getWeighAddressArray().get(sort)
|
val currentAddress = AddressUtil.getWeighAddressArray().get(sort)
|
||||||
// val seasoningEntity = list.first{it.sort == sort}
|
|
||||||
BottomDialog2(
|
BottomDialog2(
|
||||||
weighIndex = sort,
|
weighIndex = sort,
|
||||||
weighAddress = currentAddress,
|
weighAddress = currentAddress,
|
||||||
clickName = entity.goodsName
|
clickName = entity.goodsName
|
||||||
).show(this) { item ->
|
).show(this) { item ->
|
||||||
syncItem(entity, item)
|
syncItem(entity, item)
|
||||||
//3-调料
|
|
||||||
entity.materialType = 3
|
entity.materialType = 3
|
||||||
entity.sort = sort
|
entity.sort = sort
|
||||||
saveSeasoning(entity) {
|
saveSeasoning(entity) {
|
||||||
val tag = sort.toString()
|
val frameLayout = binding.include.root.findViewWithTag<FrameLayout>(sort.toString())
|
||||||
val gridLayout = binding.include.root
|
frameLayout?.let { TextCellTool.loadLayout(it, entity) }
|
||||||
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
|
||||||
TextCellAdapter.loadLayout(frameLayout, entity)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun syncItem(oldItem: SeasoningEntity, newItem: SeasoningEntity) {
|
private fun syncItem(oldItem: SeasoningEntity, newItem: GoodsItem) {
|
||||||
oldItem.run {
|
oldItem.run {
|
||||||
goodsId = newItem.goodsId
|
goodsId = newItem.goodsId
|
||||||
goodsName = newItem.goodsName
|
goodsName = newItem.goodsName
|
||||||
@@ -278,11 +212,6 @@ class DeviceConfigActivity : BaseActivity() {
|
|||||||
allEdible = newItem.allEdible
|
allEdible = newItem.allEdible
|
||||||
useWeight = newItem.useWeight
|
useWeight = newItem.useWeight
|
||||||
popularName = newItem.popularName
|
popularName = newItem.popularName
|
||||||
canteenId = newItem.canteenId
|
|
||||||
relateionType_dictText = newItem.relateionType_dictText
|
|
||||||
|
|
||||||
foodId = newItem.foodId
|
|
||||||
sort = newItem.sort
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,20 +5,18 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
import com.shuwei.dish.match.adapter.DishPartAdapter
|
import com.shuwei.dish.match.adapter.DishPartAdapter
|
||||||
import com.shuwei.dish.match.base.BaseActivity
|
import com.shuwei.dish.match.base.BaseActivity
|
||||||
import com.shuwei.dish.match.base.BaseApp
|
|
||||||
import com.shuwei.dish.match.databinding.ActivityDishSamplingBinding
|
import com.shuwei.dish.match.databinding.ActivityDishSamplingBinding
|
||||||
import com.shuwei.dish.match.databinding.LayoutFoodRemindBinding
|
import com.shuwei.dish.match.databinding.LayoutFoodRemindBinding
|
||||||
import com.shuwei.dish.match.db.AppRepository
|
|
||||||
import com.shuwei.dish.match.dialog.BottomDialog
|
import com.shuwei.dish.match.dialog.BottomDialog
|
||||||
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.db.entity.CookFoodEntity
|
||||||
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
import com.shuwei.dish.match.model.GoodsItem
|
||||||
import com.shuwei.dish.match.entity.FoodRecord
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
import com.shuwei.dish.match.utils.AddressUtil
|
import com.shuwei.dish.match.utils.AddressUtil
|
||||||
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
|
||||||
@@ -29,8 +27,6 @@ import com.shuwei.dish.match.utils.ext.startActivity
|
|||||||
import com.shuwei.dish.match.utils.ext.toJsonString
|
import com.shuwei.dish.match.utils.ext.toJsonString
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
|
||||||
import com.shuwei.dish.match.viewmodel.factory.AppFactory
|
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
class DishSamplingActivity : BaseActivity() {
|
class DishSamplingActivity : BaseActivity() {
|
||||||
@@ -58,7 +54,6 @@ class DishSamplingActivity : BaseActivity() {
|
|||||||
setTitleBar()
|
setTitleBar()
|
||||||
setHeaderBackground()
|
setHeaderBackground()
|
||||||
addViewClickListener()
|
addViewClickListener()
|
||||||
initViewModel()
|
|
||||||
foodName = intent.getStringExtra(FOOD_NAME)
|
foodName = intent.getStringExtra(FOOD_NAME)
|
||||||
binding.etInputDish.setText(foodName)
|
binding.etInputDish.setText(foodName)
|
||||||
|
|
||||||
@@ -92,16 +87,6 @@ class DishSamplingActivity : BaseActivity() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var appViewModel: AppViewModel
|
|
||||||
|
|
||||||
private fun initViewModel() {
|
|
||||||
val db = BaseApp.instance!!.database
|
|
||||||
val factory =
|
|
||||||
AppFactory(AppRepository(db.appDao()))
|
|
||||||
appViewModel =
|
|
||||||
ViewModelProvider(this, factory)[AppViewModel::class.java]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getCookFoodList(action: (MutableList<CookFoodEntity>?) -> Unit) {
|
fun getCookFoodList(action: (MutableList<CookFoodEntity>?) -> Unit) {
|
||||||
appViewModel.getCookFoodList(cookMode = 1) { action(it) }
|
appViewModel.getCookFoodList(cookMode = 1) { action(it) }
|
||||||
}
|
}
|
||||||
@@ -142,9 +127,9 @@ class DishSamplingActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val list: MutableList<CookFoodGoodsEntity> = mutableListOf()
|
val list: MutableList<GoodsItem> = mutableListOf()
|
||||||
|
|
||||||
private var tempDishEntity: CookFoodGoodsEntity? = null
|
private var tempDishEntity: GoodsItem? = null
|
||||||
|
|
||||||
private var dishMaterialType = 1
|
private var dishMaterialType = 1
|
||||||
|
|
||||||
@@ -236,7 +221,7 @@ class DishSamplingActivity : BaseActivity() {
|
|||||||
Log.d(TAG, "goToSubmit: goodsList:${list.toJsonString()}")
|
Log.d(TAG, "goToSubmit: goodsList:${list.toJsonString()}")
|
||||||
// startActivity<SubmitDishActivity> {
|
// startActivity<SubmitDishActivity> {
|
||||||
startActivity<SubmitFoodActivity> {
|
startActivity<SubmitFoodActivity> {
|
||||||
putExtra(SubmitFoodActivity.GOODS_LIST, list as java.io.Serializable)
|
putExtra(SubmitFoodActivity.GOODS_LIST, list.map { it.toCookFoodGoodsEntity() }.toMutableList() as java.io.Serializable)
|
||||||
putExtra(SubmitFoodActivity.FOOD_ITEM, food as Serializable)
|
putExtra(SubmitFoodActivity.FOOD_ITEM, food as Serializable)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -276,16 +261,7 @@ class DishSamplingActivity : BaseActivity() {
|
|||||||
setText(item.goodsName)
|
setText(item.goodsName)
|
||||||
setSelection(length())
|
setSelection(length())
|
||||||
}
|
}
|
||||||
tempDishEntity = CookFoodGoodsEntity().apply {
|
tempDishEntity = item
|
||||||
goodsId = item.goodsId
|
|
||||||
goodsName = item.goodsName
|
|
||||||
|
|
||||||
relateionType = item.relateionType ?: 0
|
|
||||||
goodsOrRelationCode = item.goodsOrRelationCode
|
|
||||||
|
|
||||||
// TODO: 待定
|
|
||||||
//allEdible = item.allEdible
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,16 +12,12 @@ import com.shuwei.dish.match.base.BaseApp
|
|||||||
import com.shuwei.dish.match.databinding.ActivityFoodSearchBinding
|
import com.shuwei.dish.match.databinding.ActivityFoodSearchBinding
|
||||||
import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding
|
import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding
|
||||||
|
|
||||||
import com.shuwei.dish.match.entity.FoodRecord
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
import com.shuwei.dish.match.entity.FoodRecordBean
|
import com.shuwei.dish.match.net.UiState
|
||||||
import com.shuwei.dish.match.http.HttpUtil
|
|
||||||
import com.shuwei.dish.match.http.UrlConfig
|
|
||||||
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
|
||||||
import com.shuwei.dish.match.utils.ext.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
import com.shuwei.dish.match.utils.ext.toJsonString
|
|
||||||
import com.shuwei.dish.match.utils.ext.toObject
|
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
@@ -146,58 +142,51 @@ class FoodSearchActivity : BaseActivity() {
|
|||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun queryListInfo(input: String) {
|
private fun queryListInfo(input: String) {
|
||||||
showLoading()
|
showLoading()
|
||||||
val map = mutableMapOf(
|
val param = mutableMapOf<String, Any>(
|
||||||
"foodName" to input.trim(),
|
"foodName" to input.trim(),
|
||||||
"pageNo" to "$pageNo",
|
"pageNo" to pageNo,
|
||||||
"pageSize" to "$pageSize",
|
"pageSize" to pageSize,
|
||||||
"canteenId" to BaseApp.canteenId
|
"canteenId" to BaseApp.canteenId
|
||||||
)
|
)
|
||||||
if (dinnerType.toInt() > 0) {
|
if (dinnerType.toInt() > 0) {
|
||||||
map["dinnerType"] = getDinnerTypeText()
|
param["dinnerType"] = getDinnerTypeText()
|
||||||
}
|
}
|
||||||
val sb = StringBuilder(UrlConfig.QUERY_FOOD_LIST).apply {
|
netViewModel.searchFoodListWithCallback(
|
||||||
append("?")
|
param = param,
|
||||||
map.forEach { (key, value) -> append("$key=$value&") }
|
onResult = { state ->
|
||||||
}
|
when (state) {
|
||||||
sb.deleteCharAt(sb.length - 1)
|
is UiState.Success -> {
|
||||||
HttpUtil.get(
|
delayDismissLoading()
|
||||||
url = sb.toString(),
|
finishRefresh()
|
||||||
doSuccess = {
|
binding.refreshLayout.setEnableRefresh(true)
|
||||||
delayDismissLoading()
|
val records = state.data
|
||||||
finishRefresh()
|
if (records.isNullOrEmpty()) {
|
||||||
binding.refreshLayout.run {
|
if (pageNo == 1) {
|
||||||
setEnableRefresh(true)
|
loadEmptyView()
|
||||||
}
|
}
|
||||||
val json = it.toJsonString()
|
return@searchFoodListWithCallback
|
||||||
val recordBean: FoodRecordBean? = json.toObject<FoodRecordBean>()
|
}
|
||||||
if (recordBean == null || recordBean.records.isNullOrEmpty()) {
|
if (pageNo == 1) {
|
||||||
// toast("暂未搜索到相关菜品信息")
|
list.clear()
|
||||||
if (pageNo == 1) {
|
}
|
||||||
loadEmptyView()
|
list.addAll(records)
|
||||||
|
recordAdapter.notifyDataSetChanged()
|
||||||
|
val isLoadMoreEnable = records.size >= pageSize
|
||||||
|
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
||||||
|
if (isLoadMoreEnable) {
|
||||||
|
pageNo++
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return@get
|
is UiState.Error -> {
|
||||||
}
|
binding.refreshLayout.setEnableRefresh(true)
|
||||||
val records = recordBean.records
|
toast(state.msg)
|
||||||
if (pageNo == 1) {
|
delayDismissLoading()
|
||||||
list.clear()
|
finishRefresh()
|
||||||
}
|
if (pageNo == 1) {
|
||||||
list.addAll(records!!)
|
loadEmptyView()
|
||||||
recordAdapter.notifyDataSetChanged()
|
}
|
||||||
val isLoadMoreEnable = records.size >= pageSize
|
}
|
||||||
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
else -> {}
|
||||||
if (isLoadMoreEnable) {
|
|
||||||
pageNo++
|
|
||||||
}
|
|
||||||
},
|
|
||||||
doFailure = { code, msg ->
|
|
||||||
binding.refreshLayout.run {
|
|
||||||
setEnableRefresh(true)
|
|
||||||
}
|
|
||||||
toast(msg)
|
|
||||||
delayDismissLoading()
|
|
||||||
finishRefresh()
|
|
||||||
if (pageNo == 1) {
|
|
||||||
loadEmptyView()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,22 +2,18 @@ package com.shuwei.dish.match.ui
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
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.HomeModeAdapter
|
import com.shuwei.dish.match.adapter.HomeModeAdapter
|
||||||
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.ActivityHomeBinding
|
import com.shuwei.dish.match.databinding.ActivityHomeBinding
|
||||||
import com.shuwei.dish.match.db.AppRepository
|
|
||||||
import com.shuwei.dish.match.entity.HomeModeBean
|
import com.shuwei.dish.match.model.HomeModeBean
|
||||||
import com.shuwei.dish.match.http.HttpUtil
|
|
||||||
import com.shuwei.dish.match.utils.SpTool
|
import com.shuwei.dish.match.utils.SpTool
|
||||||
import com.shuwei.dish.match.utils.WeightUtil
|
import com.shuwei.dish.match.utils.WeightUtil
|
||||||
import com.shuwei.dish.match.utils.ext.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
|
||||||
import com.shuwei.dish.match.viewmodel.factory.AppFactory
|
|
||||||
|
|
||||||
class HomeActivity : BaseActivity() {
|
class HomeActivity : BaseActivity() {
|
||||||
|
|
||||||
@@ -33,7 +29,6 @@ class HomeActivity : BaseActivity() {
|
|||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
statusBarDarkFont(enable = true)
|
statusBarDarkFont(enable = true)
|
||||||
initViewModel()
|
|
||||||
// // 获取 ANDROID_ID
|
// // 获取 ANDROID_ID
|
||||||
// val deviceId =
|
// val deviceId =
|
||||||
// Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
|
// Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
|
||||||
@@ -43,7 +38,7 @@ class HomeActivity : BaseActivity() {
|
|||||||
binding = ActivityHomeBinding.inflate(layoutInflater)
|
binding = ActivityHomeBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setHeaderBackground(isHomePage = true)
|
setHeaderBackground(isHomePage = true)
|
||||||
binding.radioGroup.setOnCheckedChangeListener { group, checkedId ->
|
binding.radioGroup.setOnCheckedChangeListener { _, checkedId ->
|
||||||
if (checkedId == R.id.radioSw) {
|
if (checkedId == R.id.radioSw) {
|
||||||
BaseApp.canteenId = "1678234139391512577"
|
BaseApp.canteenId = "1678234139391512577"
|
||||||
} else {
|
} else {
|
||||||
@@ -134,14 +129,6 @@ class HomeActivity : BaseActivity() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var appViewModel: AppViewModel
|
|
||||||
|
|
||||||
private fun initViewModel() {
|
|
||||||
val db = BaseApp.instance!!.database
|
|
||||||
val factory = AppFactory(AppRepository(db.appDao()))
|
|
||||||
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun goSampling() {
|
private fun goSampling() {
|
||||||
appViewModel.loadSeasoning {
|
appViewModel.loadSeasoning {
|
||||||
if (it.isEmpty()) {
|
if (it.isEmpty()) {
|
||||||
|
|||||||
@@ -4,27 +4,19 @@ import android.annotation.SuppressLint
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.provider.Settings
|
import android.provider.Settings
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import com.shuwei.dish.match.BuildConfig
|
||||||
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.ActivityInitBinding
|
import com.shuwei.dish.match.databinding.ActivityInitBinding
|
||||||
import com.shuwei.dish.match.db.AppRepository
|
import com.shuwei.dish.match.base.GlobalData
|
||||||
import com.shuwei.dish.match.http.HttpUtil
|
|
||||||
import com.shuwei.dish.match.http.UrlConfig
|
|
||||||
import com.shuwei.dish.match.utils.AppUtil
|
import com.shuwei.dish.match.utils.AppUtil
|
||||||
import com.shuwei.dish.match.utils.QRCodeUtil
|
|
||||||
import com.shuwei.dish.match.utils.SpTool
|
import com.shuwei.dish.match.utils.SpTool
|
||||||
import com.shuwei.dish.match.utils.WeightUtil
|
import com.shuwei.dish.match.utils.WeightUtil
|
||||||
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.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
import com.shuwei.dish.match.utils.ext.toJsonString
|
|
||||||
import com.shuwei.dish.match.utils.ext.toObject
|
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
|
||||||
import com.shuwei.dish.match.viewmodel.factory.AppFactory
|
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.flow
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -36,8 +28,6 @@ class InitActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var binding: ActivityInitBinding
|
private lateinit var binding: ActivityInitBinding
|
||||||
private lateinit var appViewModel: AppViewModel
|
|
||||||
|
|
||||||
@SuppressLint("HardwareIds")
|
@SuppressLint("HardwareIds")
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -51,12 +41,14 @@ class InitActivity : BaseActivity() {
|
|||||||
BaseApp.appVersion = AppUtil.getAppVersionCode(this).toString()
|
BaseApp.appVersion = AppUtil.getAppVersionCode(this).toString()
|
||||||
|
|
||||||
// 获取 ANDROID_ID
|
// 获取 ANDROID_ID
|
||||||
var androidId =
|
// var androidId =
|
||||||
Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
|
// Settings.Secure.getString(contentResolver, Settings.Secure.ANDROID_ID)
|
||||||
androidId = "39a7abdd06b3c7ab"
|
// androidId = "39a7abdd06b3c7ab"
|
||||||
BaseApp.deviceId = androidId
|
val deviceId = if (BuildConfig.IS_TEST_DEVICE) GlobalData.DEVICE_ID_2 else AppUtil.getUDID(this)
|
||||||
SpTool.put(SpTool.DEVICE_ID, androidId)
|
GlobalData.deviceId = deviceId
|
||||||
BaseApp.configUrl = UrlConfig.BASE_URL
|
SpTool.put(SpTool.DEVICE_ID, deviceId)
|
||||||
|
// GlobalData.appBaseUrl = GlobalData.TEST_BASE_URL
|
||||||
|
GlobalData.appBaseUrl = GlobalData.PROD_BASE_URL
|
||||||
BaseApp.canteenId = "0"
|
BaseApp.canteenId = "0"
|
||||||
// // TODO: 以上保存deviceId用于临时使用,后续改为下面注释方式
|
// // TODO: 以上保存deviceId用于临时使用,后续改为下面注释方式
|
||||||
|
|
||||||
@@ -82,22 +74,12 @@ class InitActivity : BaseActivity() {
|
|||||||
binding.ivQrCode.invisible()
|
binding.ivQrCode.invisible()
|
||||||
binding.btnInit.invisible()
|
binding.btnInit.invisible()
|
||||||
|
|
||||||
initViewModel()
|
|
||||||
WeightUtil.init()
|
WeightUtil.init()
|
||||||
WeightUtil.getWeight()
|
WeightUtil.getWeight()
|
||||||
WeightUtil.startContinuousRead()
|
WeightUtil.startContinuousRead()
|
||||||
HttpUtil.getAppToken()
|
|
||||||
|
|
||||||
HttpUtil.loopGetToken = true
|
|
||||||
countDown()
|
countDown()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initViewModel() {
|
|
||||||
val db = BaseApp.instance!!.database
|
|
||||||
val factory = AppFactory(AppRepository(db.appDao()))
|
|
||||||
appViewModel = ViewModelProvider(this, factory)[AppViewModel::class.java]
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startNextPage() {
|
private fun startNextPage() {
|
||||||
val launchPageType = SpTool.getInt(SpTool.LAUNCH_PAGE_TYPE, -1)
|
val launchPageType = SpTool.getInt(SpTool.LAUNCH_PAGE_TYPE, -1)
|
||||||
when (launchPageType) {
|
when (launchPageType) {
|
||||||
@@ -157,68 +139,6 @@ class InitActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initConfig() {
|
|
||||||
binding.ivQrCode.setImageBitmap(
|
|
||||||
QRCodeUtil.generateQRCode(
|
|
||||||
content = BaseApp.deviceId?:"",
|
|
||||||
size = 200.dp
|
|
||||||
)
|
|
||||||
)
|
|
||||||
binding.btnInit.setOnClickListener {
|
|
||||||
HttpUtil.loopGetToken = false
|
|
||||||
getDeviceConfig()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getDeviceConfig() {
|
|
||||||
val tokenUrl = "${UrlConfig.DEVICE_TOKEN}?qrcodeId=${BaseApp.deviceId}&appVersion=${BaseApp.appVersion}"
|
|
||||||
HttpUtil.get(url = tokenUrl, doSuccess = { token ->
|
|
||||||
Log.d(TAG, "initConfig: $token")
|
|
||||||
getConfig(token.toString())
|
|
||||||
}, doFailure = { code, msg ->
|
|
||||||
Log.d(TAG, "initConfig: $code,$msg")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
private fun getConfig(token: String) {
|
|
||||||
val deviceConfigUrl = "${UrlConfig.DEVICE_CONFIG}?equipmentCode=${BaseApp.deviceId}&&appVersion=${BaseApp.appVersion}"
|
|
||||||
HttpUtil.get(url = deviceConfigUrl, header = mutableMapOf(
|
|
||||||
"X-Access-Token" to token
|
|
||||||
), doSuccess = {
|
|
||||||
Log.d(TAG, "getDeviceConfig: $it")
|
|
||||||
val data = it.toJsonString()
|
|
||||||
val checkResult = checkConfigData(data)
|
|
||||||
if (checkResult.not()) {
|
|
||||||
toast("初始化设备失败,请稍后重试")
|
|
||||||
return@get
|
|
||||||
}
|
|
||||||
HttpUtil.loopGetToken = true
|
|
||||||
SpTool.put(SpTool.DEVICE_CONFIG_CACHE, data)
|
|
||||||
startActivity<HomeActivity>()
|
|
||||||
// finish()
|
|
||||||
}, doFailure = { code, msg ->
|
|
||||||
Log.d(TAG, "getDeviceConfig: $code,$msg")
|
|
||||||
toast("初始化设备失败,请稍后重试,code=${code},msg=${msg}")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
data class DeviceConfigBean(
|
|
||||||
var appPackageUrl:String? = null,
|
|
||||||
var canteenId:String? = null
|
|
||||||
)
|
|
||||||
|
|
||||||
private fun checkConfigData(data: String): Boolean {
|
|
||||||
if (data.isBlank()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
val config = data.toObject<DeviceConfigBean?>()
|
|
||||||
if (config == null) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
BaseApp.configUrl = config.appPackageUrl?:""
|
|
||||||
BaseApp.canteenId = config.canteenId?:""
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
WeightUtil.stopContinuousRead()
|
WeightUtil.stopContinuousRead()
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
|
|||||||
@@ -14,11 +14,15 @@ import com.shuwei.dish.match.databinding.ActivityPrepareCookBinding
|
|||||||
import com.shuwei.dish.match.databinding.LayoutFoodRemindBinding
|
import com.shuwei.dish.match.databinding.LayoutFoodRemindBinding
|
||||||
import com.shuwei.dish.match.dialog.BottomDialog
|
import com.shuwei.dish.match.dialog.BottomDialog
|
||||||
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.model.GoodsItem
|
||||||
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
import com.shuwei.dish.match.entity.FoodRecord
|
import com.shuwei.dish.match.model.CookFoodDTO
|
||||||
import com.shuwei.dish.match.http.HttpUtil
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
import com.shuwei.dish.match.http.UrlConfig
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
|
import com.shuwei.dish.match.net.UiState
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import com.shuwei.dish.match.utils.AddressUtil
|
import com.shuwei.dish.match.utils.AddressUtil
|
||||||
import com.shuwei.dish.match.utils.SwipeCallback
|
import com.shuwei.dish.match.utils.SwipeCallback
|
||||||
import com.shuwei.dish.match.utils.WeightUtil
|
import com.shuwei.dish.match.utils.WeightUtil
|
||||||
@@ -26,7 +30,6 @@ import com.shuwei.dish.match.utils.ext.clickWithDebounce
|
|||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
import com.shuwei.dish.match.utils.ext.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
import com.shuwei.dish.match.utils.ext.toJsonString
|
import com.shuwei.dish.match.utils.ext.toJsonString
|
||||||
import com.shuwei.dish.match.utils.ext.toObject
|
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
@@ -44,8 +47,6 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
private var food: FoodRecord? = null
|
private var food: FoodRecord? = 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)
|
||||||
binding = ActivityPrepareCookBinding.inflate(layoutInflater)
|
binding = ActivityPrepareCookBinding.inflate(layoutInflater)
|
||||||
@@ -69,6 +70,7 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
food = intent.extras?.getSerializable(FOOD_ITEM) as FoodRecord?
|
food = intent.extras?.getSerializable(FOOD_ITEM) as FoodRecord?
|
||||||
binding.tvDishName.text = food?.foodName ?: ""
|
binding.tvDishName.text = food?.foodName ?: ""
|
||||||
addViewClickListener()
|
addViewClickListener()
|
||||||
|
initObserver()
|
||||||
getDishDetail()
|
getDishDetail()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +98,7 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val weight = binding.tvDishPartWeight.text.toString().toDouble()
|
val weight = binding.tvDishPartWeight.text.toString().toDoubleOrNull() ?:0.toDouble()
|
||||||
if (weight <= 0.toDouble()) {
|
if (weight <= 0.toDouble()) {
|
||||||
toast("食材用量需要大于0")
|
toast("食材用量需要大于0")
|
||||||
return@setOnClickListener
|
return@setOnClickListener
|
||||||
@@ -115,12 +117,7 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
toast("不允许重复添加同一食材")
|
toast("不允许重复添加同一食材")
|
||||||
return@show
|
return@show
|
||||||
}
|
}
|
||||||
list.add(CookFoodGoodsEntity().apply {
|
list.add(GoodsItem(goodsId = item.goodsId, goodsName = item.goodsName, isNewDishType = true))
|
||||||
goodsId = item.goodsId
|
|
||||||
goodsName = item.goodsName
|
|
||||||
// materialType =
|
|
||||||
isNewDishType = true
|
|
||||||
})
|
|
||||||
onItemClick(list.size - 1)
|
onItemClick(list.size - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -163,15 +160,8 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
list.forEach {
|
list.forEach {
|
||||||
if (it.isSetFinished) {
|
if (it.isSetFinished) {
|
||||||
goodsList?.add(CookFoodGoodsEntity().apply {
|
goodsList?.add(it.toCookFoodGoodsEntity().also { entity ->
|
||||||
foodId = food!!.foodId
|
entity.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
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -193,35 +183,45 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun getDishDetail() {
|
private fun initObserver() {
|
||||||
//649
|
lifecycleScope.launch {
|
||||||
val url = "${UrlConfig.DISH_DETAIL}?foodId=${food?.foodId}"
|
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
HttpUtil.get(
|
netViewModel.foodDetailState.collect { state ->
|
||||||
url = url,
|
when (state) {
|
||||||
doSuccess = {
|
is UiState.Loading -> showLoading()
|
||||||
val json = it.toJsonString()
|
is UiState.Success -> {
|
||||||
Log.d(TAG, "getDishDetail: json:$json")
|
dismissLoading()
|
||||||
val detail: CookFoodEntity? = json.toObject<CookFoodEntity>()
|
netViewModel.resetFoodDetailState()
|
||||||
if (detail == null) {
|
val detail = state.data
|
||||||
toast("查询菜品信息为空")
|
if (detail == null) {
|
||||||
return@get
|
toast("查询菜品信息为空")
|
||||||
|
return@collect
|
||||||
|
}
|
||||||
|
loadDishDetail(detail)
|
||||||
|
}
|
||||||
|
is UiState.Error -> {
|
||||||
|
dismissLoading()
|
||||||
|
toast(state.msg)
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
loadDishDetail(detail)
|
}
|
||||||
}) { code, msg ->
|
|
||||||
toast(msg)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadDishDetail(detail: CookFoodEntity) {
|
private fun getDishDetail() {
|
||||||
val voList = detail.stFoodInfoConstituteList
|
netViewModel.getFoodDetail(food?.foodId ?: "")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadDishDetail(detail: CookFoodDTO) {
|
||||||
|
val voList = detail.foodConstituteList
|
||||||
if (voList.isNullOrEmpty()) {
|
if (voList.isNullOrEmpty()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//筛选出主材和辅材
|
//筛选出主材和辅材
|
||||||
val tempDate = voList.filter { it.materialType == 1 || it.materialType == 2 }
|
val tempDate = 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()
|
||||||
list.addAll(tempDate)
|
list.addAll(tempDate)
|
||||||
firstReqSize = list.size
|
firstReqSize = list.size
|
||||||
@@ -229,7 +229,7 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private var firstReqSize = 0
|
private var firstReqSize = 0
|
||||||
private val list = mutableListOf<CookFoodGoodsEntity>()
|
private val list = mutableListOf<GoodsItem>()
|
||||||
private val dishPartAdapter by lazy {
|
private val dishPartAdapter by lazy {
|
||||||
DishPartAdapter(list).apply {
|
DishPartAdapter(list).apply {
|
||||||
setOnItemClickListener { _, _, positon ->
|
setOnItemClickListener { _, _, positon ->
|
||||||
@@ -247,8 +247,8 @@ class PrepareCookActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
binding.tvDishType.text =
|
binding.tvDishType.text =
|
||||||
if (it.materialType == 1) "主材" else if (it.materialType == 2) "辅材" else ""
|
if (it.materialType == 1) "主材" else if (it.materialType == 2) "辅材" else ""
|
||||||
list.forEach { bean -> bean.isItemClicked = false }
|
list.forEach { bean -> bean.isClicked = false }
|
||||||
it.isItemClicked = true
|
it.isClicked = true
|
||||||
dishPartAdapter.notifyDataSetChanged()
|
dishPartAdapter.notifyDataSetChanged()
|
||||||
|
|
||||||
if (it.isNewDishType) {
|
if (it.isNewDishType) {
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import android.os.Bundle
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper
|
import androidx.recyclerview.widget.ItemTouchHelper
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
@@ -15,23 +14,17 @@ 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.ActivitySamplingBinding
|
import com.shuwei.dish.match.databinding.ActivitySamplingBinding
|
||||||
import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding
|
import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding
|
||||||
import com.shuwei.dish.match.db.AppRepository
|
|
||||||
import com.shuwei.dish.match.dialog.DialogTool
|
import com.shuwei.dish.match.dialog.DialogTool
|
||||||
import com.shuwei.dish.match.entity.CookFoodEntity
|
import com.shuwei.dish.match.db.entity.CookFoodEntity
|
||||||
import com.shuwei.dish.match.entity.FoodRecord
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
import com.shuwei.dish.match.entity.FoodRecordBean
|
import com.shuwei.dish.match.net.UiState
|
||||||
import com.shuwei.dish.match.http.HttpUtil
|
|
||||||
import com.shuwei.dish.match.http.UrlConfig
|
|
||||||
import com.shuwei.dish.match.utils.DateTimeUtil
|
import com.shuwei.dish.match.utils.DateTimeUtil
|
||||||
import com.shuwei.dish.match.utils.SwipeCallback
|
import com.shuwei.dish.match.utils.SwipeCallback
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
import com.shuwei.dish.match.utils.ext.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
import com.shuwei.dish.match.utils.ext.toJsonString
|
|
||||||
import com.shuwei.dish.match.utils.ext.toObject
|
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
|
||||||
import com.shuwei.dish.match.viewmodel.factory.AppFactory
|
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
class SamplingListActivity : BaseActivity() {
|
class SamplingListActivity : BaseActivity() {
|
||||||
@@ -49,7 +42,6 @@ class SamplingListActivity : BaseActivity() {
|
|||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
setTitleBar()
|
setTitleBar()
|
||||||
setHeaderBackground()
|
setHeaderBackground()
|
||||||
initViewModel()
|
|
||||||
initRecyclerView()
|
initRecyclerView()
|
||||||
addViewListener()
|
addViewListener()
|
||||||
requestData(true)
|
requestData(true)
|
||||||
@@ -76,16 +68,6 @@ class SamplingListActivity : BaseActivity() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var appViewModel: AppViewModel
|
|
||||||
|
|
||||||
private fun initViewModel() {
|
|
||||||
val db = BaseApp.instance!!.database
|
|
||||||
val factory =
|
|
||||||
AppFactory(AppRepository(db.appDao()))
|
|
||||||
appViewModel =
|
|
||||||
ViewModelProvider(this, factory)[AppViewModel::class.java]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getCookFoodList(action: (MutableList<CookFoodEntity>?) -> Unit) {
|
fun getCookFoodList(action: (MutableList<CookFoodEntity>?) -> Unit) {
|
||||||
appViewModel.getCookFoodList(cookMode = 1) { action(it) }
|
appViewModel.getCookFoodList(cookMode = 1) { action(it) }
|
||||||
}
|
}
|
||||||
@@ -204,33 +186,29 @@ class SamplingListActivity : BaseActivity() {
|
|||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
fun getSamplingList() {
|
fun getSamplingList() {
|
||||||
showLoading()
|
showLoading()
|
||||||
val map = mapOf(
|
val param = mutableMapOf<String, Any>(
|
||||||
// "foodName" to input,
|
"pageNo" to pageNo,
|
||||||
"pageNo" to "$pageNo",
|
"pageSize" to pageSize,
|
||||||
"pageSize" to "$pageSize",
|
|
||||||
"canteenId" to BaseApp.canteenId
|
"canteenId" to BaseApp.canteenId
|
||||||
)
|
)
|
||||||
val sb = StringBuilder(UrlConfig.SAMPLING_LIST).apply {
|
netViewModel.getSamplingListWithCallback(
|
||||||
append("?")
|
param = param,
|
||||||
map.forEach { (key, value) -> append("$key=$value&") }
|
onResult = { state ->
|
||||||
}
|
when (state) {
|
||||||
sb.deleteCharAt(sb.length - 1)
|
is UiState.Success -> loadDishList(state.data)
|
||||||
HttpUtil.get(
|
is UiState.Error -> {
|
||||||
url = sb.toString(),
|
binding.refreshLayout.setEnableRefresh(true)
|
||||||
doSuccess = {
|
toast(state.msg)
|
||||||
loadDishList(it)
|
finishRefresh()
|
||||||
}, doFailure = { code, msg ->
|
delayDismissLoading()
|
||||||
binding.refreshLayout.run {
|
if (pageNo == 1) {
|
||||||
setEnableRefresh(true)
|
loadEmptyView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
toast(msg)
|
}
|
||||||
finishRefresh()
|
)
|
||||||
binding.refreshLayout.setEnableRefresh(true)
|
|
||||||
delayDismissLoading()
|
|
||||||
if (pageNo == 1) {
|
|
||||||
loadEmptyView()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun finishRefresh() {
|
private fun finishRefresh() {
|
||||||
@@ -332,26 +310,20 @@ class SamplingListActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun loadDishList(data: Any) {
|
private fun loadDishList(records: MutableList<FoodRecord>?) {
|
||||||
binding.refreshLayout.run {
|
binding.refreshLayout.setEnableRefresh(true)
|
||||||
setEnableRefresh(true)
|
|
||||||
}
|
|
||||||
delayDismissLoading()
|
delayDismissLoading()
|
||||||
finishRefresh()
|
finishRefresh()
|
||||||
val json = data.toJsonString()
|
if (records.isNullOrEmpty()) {
|
||||||
val recordBean: FoodRecordBean? = json.toObject<FoodRecordBean>()
|
|
||||||
if (recordBean == null || recordBean.records.isNullOrEmpty()) {
|
|
||||||
//toast("暂未搜索到相关菜品信息")
|
|
||||||
if (pageNo == 1) {
|
if (pageNo == 1) {
|
||||||
loadEmptyView()
|
loadEmptyView()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val records = recordBean.records
|
|
||||||
if (pageNo == 1) {
|
if (pageNo == 1) {
|
||||||
list.clear()
|
list.clear()
|
||||||
}
|
}
|
||||||
list.addAll(records!!)
|
list.addAll(records)
|
||||||
dishAdapter.notifyDataSetChanged()
|
dishAdapter.notifyDataSetChanged()
|
||||||
val isLoadMoreEnable = records.size >= pageSize
|
val isLoadMoreEnable = records.size >= pageSize
|
||||||
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
||||||
|
|||||||
@@ -5,14 +5,12 @@ import android.app.Dialog
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import com.shuwei.dish.match.R
|
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.base.BaseApp
|
|
||||||
import com.shuwei.dish.match.databinding.ActivitySelectDishBinding
|
import com.shuwei.dish.match.databinding.ActivitySelectDishBinding
|
||||||
import com.shuwei.dish.match.db.AppRepository
|
|
||||||
import com.shuwei.dish.match.dialog.DialogTool
|
import com.shuwei.dish.match.dialog.DialogTool
|
||||||
import com.shuwei.dish.match.entity.CookFoodEntity
|
import com.shuwei.dish.match.db.entity.CookFoodEntity
|
||||||
import com.shuwei.dish.match.ui.fragment.DishListFragment
|
import com.shuwei.dish.match.ui.fragment.DishListFragment
|
||||||
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
|
||||||
@@ -20,8 +18,6 @@ import com.shuwei.dish.match.utils.ext.gone
|
|||||||
import com.shuwei.dish.match.utils.ext.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
|
||||||
import com.shuwei.dish.match.viewmodel.factory.AppFactory
|
|
||||||
|
|
||||||
class SelectDishActivity : BaseActivity() {
|
class SelectDishActivity : BaseActivity() {
|
||||||
|
|
||||||
@@ -32,8 +28,6 @@ class SelectDishActivity : BaseActivity() {
|
|||||||
|
|
||||||
private lateinit var binding: ActivitySelectDishBinding
|
private lateinit var binding: ActivitySelectDishBinding
|
||||||
|
|
||||||
private lateinit var appViewModel: AppViewModel
|
|
||||||
|
|
||||||
private var dinnerType: String = "1"
|
private var dinnerType: String = "1"
|
||||||
|
|
||||||
private val fragmentList = mutableListOf<DishListFragment>().apply {
|
private val fragmentList = mutableListOf<DishListFragment>().apply {
|
||||||
@@ -62,19 +56,10 @@ class SelectDishActivity : BaseActivity() {
|
|||||||
}, backAction = {
|
}, backAction = {
|
||||||
it.gone()
|
it.gone()
|
||||||
})
|
})
|
||||||
initViewModel()
|
|
||||||
addViewListener()
|
addViewListener()
|
||||||
loadFragment()
|
loadFragment()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initViewModel() {
|
|
||||||
val db = BaseApp.instance!!.database
|
|
||||||
val factory =
|
|
||||||
AppFactory(AppRepository(db.appDao()))
|
|
||||||
appViewModel =
|
|
||||||
ViewModelProvider(this, factory)[AppViewModel::class.java]
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getCookFoodList(action: (MutableList<CookFoodEntity>?) -> Unit) {
|
fun getCookFoodList(action: (MutableList<CookFoodEntity>?) -> Unit) {
|
||||||
appViewModel.getCookFoodList(cookMode = 0, dinnerType = dinnerType) { action(it) }
|
appViewModel.getCookFoodList(cookMode = 0, dinnerType = dinnerType) { action(it) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,24 +6,26 @@ import android.util.Log
|
|||||||
import android.util.SparseArray
|
import android.util.SparseArray
|
||||||
import android.util.SparseIntArray
|
import android.util.SparseIntArray
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.util.forEach
|
import androidx.core.util.forEach
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
import com.shuwei.dish.match.R
|
import com.shuwei.dish.match.R
|
||||||
import com.shuwei.dish.match.adapter.TextCellAdapter
|
|
||||||
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.ActivitySubmitFoodBinding
|
import com.shuwei.dish.match.databinding.ActivitySubmitFoodBinding
|
||||||
import com.shuwei.dish.match.db.AppRepository
|
|
||||||
|
|
||||||
import com.shuwei.dish.match.entity.CookFoodEntity
|
|
||||||
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
import com.shuwei.dish.match.db.entity.CookFoodEntity
|
||||||
import com.shuwei.dish.match.entity.FoodRecord
|
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
import com.shuwei.dish.match.entity.SeasoningEntity
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
import com.shuwei.dish.match.http.HttpUtil
|
import com.shuwei.dish.match.db.entity.SeasoningEntity
|
||||||
import com.shuwei.dish.match.http.UrlConfig
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
|
import com.shuwei.dish.match.model.toDTO
|
||||||
|
import com.shuwei.dish.match.net.UiState
|
||||||
import com.shuwei.dish.match.utils.AddressUtil
|
import com.shuwei.dish.match.utils.AddressUtil
|
||||||
|
import com.shuwei.dish.match.utils.TextCellTool
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
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
|
||||||
import com.shuwei.dish.match.utils.ext.gone
|
import com.shuwei.dish.match.utils.ext.gone
|
||||||
@@ -33,8 +35,6 @@ import com.shuwei.dish.match.utils.ext.toJsonString
|
|||||||
import com.shuwei.dish.match.utils.ext.toType
|
import com.shuwei.dish.match.utils.ext.toType
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import com.shuwei.dish.match.utils.ext.visible
|
import com.shuwei.dish.match.utils.ext.visible
|
||||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
|
||||||
import com.shuwei.dish.match.viewmodel.factory.AppFactory
|
|
||||||
|
|
||||||
@SuppressLint("UseSparseArrays")
|
@SuppressLint("UseSparseArrays")
|
||||||
class SubmitFoodActivity : BaseActivity() {
|
class SubmitFoodActivity : BaseActivity() {
|
||||||
@@ -69,7 +69,6 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = ActivitySubmitFoodBinding.inflate(layoutInflater)
|
binding = ActivitySubmitFoodBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
initViewModel()
|
|
||||||
setHeaderBackground()
|
setHeaderBackground()
|
||||||
intent.extras?.apply {
|
intent.extras?.apply {
|
||||||
food = getSerializable(FOOD_ITEM) as FoodRecord?
|
food = getSerializable(FOOD_ITEM) as FoodRecord?
|
||||||
@@ -95,10 +94,11 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
addViewListener()
|
addViewListener()
|
||||||
|
initObserver()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadSeasoningFromLocal() {
|
private fun loadSeasoningFromLocal() {
|
||||||
appViewModel.getCookFoodGoodsList(foodId = food!!.foodId!!, cookMode = food!!.cookMode) { it ->
|
appViewModel.getCookFoodGoodsList(foodId = food!!.foodId!!, cookMode = food!!.cookMode, dinnerType = food!!.dinnerType) { it ->
|
||||||
goodsList = mutableListOf()
|
goodsList = mutableListOf()
|
||||||
val goodsIdList = mutableListOf<String>()
|
val goodsIdList = mutableListOf<String>()
|
||||||
//设置主辅材数据
|
//设置主辅材数据
|
||||||
@@ -221,7 +221,7 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
val gridLayout = binding.include.root
|
val gridLayout = binding.include.root
|
||||||
val tag = entity.sort.toString()
|
val tag = entity.sort.toString()
|
||||||
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
||||||
TextCellAdapter.loadLayout(frameLayout , entity)
|
TextCellTool.loadLayout(frameLayout , entity)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getCookingSeasoning(address: Int): Double {
|
private fun getCookingSeasoning(address: Int): Double {
|
||||||
@@ -265,7 +265,7 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
toast("未获取到调料信息")
|
toast("未获取到调料信息")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (realSeasoningData.isNotEmpty()&&realSeasoningData[0].goodsId.isNullOrBlank()) {
|
if (realSeasoningData.isNotEmpty()&&realSeasoningData[0].goodsId.isBlank()) {
|
||||||
toast("还未设置调料信息,请去设置页面操作")
|
toast("还未设置调料信息,请去设置页面操作")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -316,7 +316,7 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
toast("未获取到调料信息")
|
toast("未获取到调料信息")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (realSeasoningData.isNotEmpty()&&realSeasoningData[0].goodsId.isNullOrBlank()) {
|
if (realSeasoningData.isNotEmpty()&&realSeasoningData[0].goodsId.isBlank()) {
|
||||||
toast("还未设置调料信息,请去设置页面操作")
|
toast("还未设置调料信息,请去设置页面操作")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -335,7 +335,7 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cookFoodEntity.let {
|
cookFoodEntity.let {
|
||||||
it.stFoodInfoConstituteList = this@SubmitFoodActivity.goodsList
|
it.matchingConstituteInfoList = this@SubmitFoodActivity.goodsList
|
||||||
it.dinnerType = when(it.dinnerType) {
|
it.dinnerType = when(it.dinnerType) {
|
||||||
"1" -> "早餐"
|
"1" -> "早餐"
|
||||||
"2" -> "午餐"
|
"2" -> "午餐"
|
||||||
@@ -350,36 +350,20 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
cookFoodEntity.foodId = ""
|
cookFoodEntity.foodId = ""
|
||||||
goodsList?.forEach { it.foodId = "" }
|
goodsList?.forEach { it.foodId = "" }
|
||||||
}
|
}
|
||||||
val json = cookFoodEntity.toJsonString()
|
netViewModel.submitCookFood(entity = cookFoodEntity.toDTO())
|
||||||
Log.d(TAG, "submit: json=$json")
|
|
||||||
HttpUtil.postJson(
|
|
||||||
url = UrlConfig.SUBMIT_DISH,
|
|
||||||
json = json,
|
|
||||||
doSuccess = {
|
|
||||||
Log.d(TAG, "submit: postJson=$it")
|
|
||||||
submitSuccess(isSamplingData)
|
|
||||||
}, doFailure = { code, msg ->
|
|
||||||
Log.d(TAG, "submit: postJson:code=$code,msg=$msg")
|
|
||||||
toast(msg)
|
|
||||||
dismissLoading()
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun submitSuccess(isSamplingData: Boolean) {
|
private fun submitSuccess(isSamplingData: Boolean) {
|
||||||
if (food?.foodId.isNullOrBlank()) {
|
if (food?.foodId.isNullOrBlank().not()) {
|
||||||
//本地无删除数据直接跳转页面
|
//接口提交成功后异步删除本地草稿
|
||||||
dismissLoading()
|
dbViewModel.markSubmittedAndDeleteAsync(
|
||||||
jumpPage(isSamplingData, false)
|
cookMode = food!!.cookMode,
|
||||||
return
|
foodId = food!!.foodId!!,
|
||||||
}
|
dinnerType = food!!.dinnerType ?: "0"
|
||||||
//删除本地数据
|
)
|
||||||
appViewModel.deleteCookFoodAndGoods(
|
|
||||||
cookMode = food!!.cookMode,
|
|
||||||
foodId = food!!.foodId!!
|
|
||||||
) {
|
|
||||||
dismissLoading()
|
|
||||||
jumpPage(isSamplingData, false)
|
|
||||||
}
|
}
|
||||||
|
dismissLoading()
|
||||||
|
jumpPage(isSamplingData, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun jumpPage(isSampling: Boolean, isCooking: Boolean) {
|
private fun jumpPage(isSampling: Boolean, isCooking: Boolean) {
|
||||||
@@ -395,14 +379,26 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var appViewModel: AppViewModel
|
private fun initObserver() {
|
||||||
|
lifecycleScope.launch {
|
||||||
private fun initViewModel() {
|
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
||||||
val db = BaseApp.instance!!.database
|
netViewModel.submitCookFoodState.collect { state ->
|
||||||
val factory =
|
when (state) {
|
||||||
AppFactory(AppRepository(db.appDao()))
|
is UiState.Loading -> showLoading()
|
||||||
appViewModel =
|
is UiState.Success -> {
|
||||||
ViewModelProvider(this, factory)[AppViewModel::class.java]
|
Log.d(TAG, "submit: success")
|
||||||
|
submitSuccess(food?.cookMode == 1)
|
||||||
|
}
|
||||||
|
is UiState.Error -> {
|
||||||
|
Log.d(TAG, "submit: error code=${state.code}, msg=${state.msg}")
|
||||||
|
toast(state.msg)
|
||||||
|
dismissLoading()
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@@ -447,7 +443,7 @@ class SubmitFoodActivity : BaseActivity() {
|
|||||||
list.forEach { entity ->
|
list.forEach { entity ->
|
||||||
val tag = entity.sort.toString()
|
val tag = entity.sort.toString()
|
||||||
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
val frameLayout = gridLayout.findViewWithTag<FrameLayout>(tag)
|
||||||
TextCellAdapter.loadLayout(frameLayout, entity)
|
TextCellTool.loadLayout(frameLayout, entity)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,17 +14,13 @@ import com.shuwei.dish.match.base.BaseFragment
|
|||||||
import com.shuwei.dish.match.databinding.FragmentDishListBinding
|
import com.shuwei.dish.match.databinding.FragmentDishListBinding
|
||||||
import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding
|
import com.shuwei.dish.match.databinding.LayoutEmptyViewBinding
|
||||||
|
|
||||||
import com.shuwei.dish.match.entity.FoodRecord
|
import com.shuwei.dish.match.model.FoodRecord
|
||||||
import com.shuwei.dish.match.entity.FoodRecordBean
|
import com.shuwei.dish.match.net.UiState
|
||||||
import com.shuwei.dish.match.http.HttpUtil
|
|
||||||
import com.shuwei.dish.match.http.UrlConfig
|
|
||||||
import com.shuwei.dish.match.ui.PrepareCookActivity
|
import com.shuwei.dish.match.ui.PrepareCookActivity
|
||||||
import com.shuwei.dish.match.ui.SelectDishActivity
|
import com.shuwei.dish.match.ui.SelectDishActivity
|
||||||
import com.shuwei.dish.match.ui.SubmitFoodActivity
|
import com.shuwei.dish.match.ui.SubmitFoodActivity
|
||||||
import com.shuwei.dish.match.utils.SwipeCallback
|
import com.shuwei.dish.match.utils.SwipeCallback
|
||||||
import com.shuwei.dish.match.utils.ext.startActivity
|
import com.shuwei.dish.match.utils.ext.startActivity
|
||||||
import com.shuwei.dish.match.utils.ext.toJsonString
|
|
||||||
import com.shuwei.dish.match.utils.ext.toObject
|
|
||||||
import com.shuwei.dish.match.utils.ext.toast
|
import com.shuwei.dish.match.utils.ext.toast
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
@@ -153,40 +149,35 @@ class DishListFragment : BaseFragment<FragmentDishListBinding>() {
|
|||||||
@Suppress("unchecked_cast")
|
@Suppress("unchecked_cast")
|
||||||
fun getDishList() {
|
fun getDishList() {
|
||||||
activity.showLoading()
|
activity.showLoading()
|
||||||
val map = mapOf(
|
val param = mutableMapOf<String, Any>(
|
||||||
// "foodName" to input,
|
|
||||||
"dinnerType" to getDinnerTypeText(),
|
"dinnerType" to getDinnerTypeText(),
|
||||||
"pageNo" to "$pageNo",
|
"pageNo" to pageNo,
|
||||||
"pageSize" to "$pageSize",
|
"pageSize" to pageSize,
|
||||||
"canteenId" to BaseApp.canteenId
|
"canteenId" to BaseApp.canteenId
|
||||||
)
|
)
|
||||||
val sb = StringBuilder(UrlConfig.QUERY_FOOD_LIST).apply {
|
activity.netViewModel.searchFoodListWithCallback(
|
||||||
append("?")
|
param = param,
|
||||||
map.forEach { (key, value) -> append("$key=$value&") }
|
onResult = { state ->
|
||||||
}
|
|
||||||
sb.deleteCharAt(sb.length - 1)
|
|
||||||
HttpUtil.get(
|
|
||||||
url = sb.toString(),
|
|
||||||
doSuccess = {
|
|
||||||
loadDishList(it)
|
|
||||||
}, doFailure = { code, msg ->
|
|
||||||
try {
|
try {
|
||||||
if (isAdded.not()) {
|
if (isAdded.not()) return@searchFoodListWithCallback
|
||||||
return@get
|
when (state) {
|
||||||
|
is UiState.Success -> loadDishList(state.data)
|
||||||
|
is UiState.Error -> {
|
||||||
|
binding.refreshLayout.setEnableRefresh(true)
|
||||||
|
toast(state.msg)
|
||||||
|
finishRefresh()
|
||||||
|
if (pageNo == 1) {
|
||||||
|
loadEmptyView()
|
||||||
|
}
|
||||||
|
activity.delayDismissLoading()
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
}
|
}
|
||||||
binding.refreshLayout.run {
|
|
||||||
setEnableRefresh(true)
|
|
||||||
}
|
|
||||||
toast(msg)
|
|
||||||
finishRefresh()
|
|
||||||
if (pageNo == 1) {
|
|
||||||
loadEmptyView()
|
|
||||||
}
|
|
||||||
activity.delayDismissLoading()
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var emptyViewBinding: LayoutEmptyViewBinding? = null
|
private var emptyViewBinding: LayoutEmptyViewBinding? = null
|
||||||
@@ -255,30 +246,22 @@ class DishListFragment : BaseFragment<FragmentDishListBinding>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun loadDishList(data: Any) {
|
private fun loadDishList(records: MutableList<FoodRecord>?) {
|
||||||
try {
|
try {
|
||||||
if (isAdded.not()) {
|
if (isAdded.not()) return
|
||||||
return
|
binding.refreshLayout.setEnableRefresh(true)
|
||||||
}
|
|
||||||
binding.refreshLayout.run {
|
|
||||||
setEnableRefresh(true)
|
|
||||||
}
|
|
||||||
activity.delayDismissLoading()
|
activity.delayDismissLoading()
|
||||||
finishRefresh()
|
finishRefresh()
|
||||||
val json = data.toJsonString()
|
if (records.isNullOrEmpty()) {
|
||||||
val recordBean: FoodRecordBean? = json.toObject<FoodRecordBean>()
|
|
||||||
if (recordBean == null || recordBean.records.isNullOrEmpty()) {
|
|
||||||
//toast("暂未搜索到相关菜品信息")
|
|
||||||
if (pageNo == 1) {
|
if (pageNo == 1) {
|
||||||
loadEmptyView()
|
loadEmptyView()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val records = recordBean.records
|
|
||||||
if (pageNo == 1) {
|
if (pageNo == 1) {
|
||||||
list.clear()
|
list.clear()
|
||||||
}
|
}
|
||||||
list.addAll(records!!)
|
list.addAll(records)
|
||||||
dishAdapter.notifyDataSetChanged()
|
dishAdapter.notifyDataSetChanged()
|
||||||
val isLoadMoreEnable = records.size >= pageSize
|
val isLoadMoreEnable = records.size >= pageSize
|
||||||
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
binding.refreshLayout.setEnableLoadMore(isLoadMoreEnable)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class DecimalAdapter : TypeAdapter<Number>() {
|
|||||||
override fun read(reader: JsonReader): Number {
|
override fun read(reader: JsonReader): Number {
|
||||||
return when (reader.peek()) {
|
return when (reader.peek()) {
|
||||||
JsonToken.NUMBER -> reader.nextDouble()
|
JsonToken.NUMBER -> reader.nextDouble()
|
||||||
JsonToken.STRING -> reader.nextString().toDouble()
|
JsonToken.STRING -> reader.nextString().toDoubleOrNull() ?: 0.0
|
||||||
else -> 0.0
|
else -> 0.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,91 @@
|
|||||||
|
package com.shuwei.dish.match.utils;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.wabon.wbintelligenthardwaresdk.api.SensorScale;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修复 SensorScale 地址编码 bug 的子类。
|
||||||
|
*
|
||||||
|
* 问题根因:SensorScale.zeroTwo / tareTwo 内部使用
|
||||||
|
* String command = address + "630603";
|
||||||
|
* 将 int 地址直接拼接为十进制字符串,再整体按十六进制解析成字节。
|
||||||
|
* 对于地址 1-9,十进制 == 十六进制,偶然正确;
|
||||||
|
* 对于地址 10+,十进制 "10" 被解析为 0x10(=16),命中错误的物理秤。
|
||||||
|
*
|
||||||
|
* 修复方式:重写这两个方法,将地址先格式化为两位十六进制字符串(如 10 → "0A"),
|
||||||
|
* 再拼接命令码,通过反射调用父类私有方法 suspendSendThread 和 sumHex 发送。
|
||||||
|
*/
|
||||||
|
public class FixedSensorScale extends SensorScale {
|
||||||
|
|
||||||
|
private static final String TAG = "FixedSensorScale";
|
||||||
|
|
||||||
|
public FixedSensorScale(OnScaleResult result) {
|
||||||
|
super(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重写清零命令,修复地址编码:十进制地址 → 两位十六进制字符串。
|
||||||
|
* 例:address=10 → "0A630603",发送字节 0x0A(正确),而非原来的 0x10(错误)。
|
||||||
|
*
|
||||||
|
* @param listener 操作成功回调
|
||||||
|
* @param address 秤地址(来自 onGetWeight 回调的十进制值)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void zeroTwo(OperateSuccessListener listener, int address) {
|
||||||
|
sendFixedCommand(listener, address, "630603", "zeroTwo");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重写去皮命令,修复地址编码,逻辑同 zeroTwo。
|
||||||
|
*
|
||||||
|
* @param listener 操作成功回调
|
||||||
|
* @param address 秤地址
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void tareTwo(OperateSuccessListener listener, int address) {
|
||||||
|
sendFixedCommand(listener, address, "630601", "tareTwo");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用发送逻辑:将地址格式化为两位十六进制后拼接命令码,
|
||||||
|
* 通过反射调用父类私有方法 sumHex 计算校验和,再调用 suspendSendThread 发送。
|
||||||
|
*
|
||||||
|
* @param listener 操作成功回调
|
||||||
|
* @param address 秤地址(十进制)
|
||||||
|
* @param commandCode 命令码(十六进制字符串,如 "630603")
|
||||||
|
* @param methodName 调用方名称,仅用于日志
|
||||||
|
*/
|
||||||
|
private void sendFixedCommand(OperateSuccessListener listener, int address,
|
||||||
|
String commandCode, String methodName) {
|
||||||
|
try {
|
||||||
|
// 将十进制地址转为两位十六进制字符串:10 → "0A",1 → "01"
|
||||||
|
String hexAddress = String.format("%02X", address);
|
||||||
|
String command = hexAddress + commandCode;
|
||||||
|
Log.d(TAG, methodName + ", address=" + address
|
||||||
|
+ ", hexAddress=" + hexAddress + ", command=" + command);
|
||||||
|
|
||||||
|
// 反射调用 sumHex(String) 计算校验和
|
||||||
|
Method sumHexMethod = SensorScale.class.getDeclaredMethod("sumHex", String.class);
|
||||||
|
sumHexMethod.setAccessible(true);
|
||||||
|
String checksum = (String) sumHexMethod.invoke(this, command);
|
||||||
|
|
||||||
|
// 反射调用 suspendSendThread(String) 发送完整命令帧
|
||||||
|
Method suspendMethod = SensorScale.class.getDeclaredMethod(
|
||||||
|
"suspendSendThread", String.class);
|
||||||
|
suspendMethod.setAccessible(true);
|
||||||
|
suspendMethod.invoke(this, command + checksum);
|
||||||
|
|
||||||
|
// 保存回调(通过反射写入父类私有字段 mOperateSuccessListener)
|
||||||
|
java.lang.reflect.Field listenerField = SensorScale.class
|
||||||
|
.getDeclaredField("mOperateSuccessListener");
|
||||||
|
listenerField.setAccessible(true);
|
||||||
|
listenerField.set(this, listener);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, methodName + " 反射调用失败: address=" + address, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package com.shuwei.dish.match.utils
|
||||||
|
|
||||||
|
import android.graphics.Typeface
|
||||||
|
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.widget.FrameLayout
|
||||||
|
import android.widget.TextView
|
||||||
|
import androidx.core.graphics.toColorInt
|
||||||
|
import com.shuwei.dish.match.db.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.dp
|
||||||
|
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
||||||
|
|
||||||
|
object TextCellTool {
|
||||||
|
|
||||||
|
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 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.take(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)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -23,14 +23,25 @@ public class Weigher2 {
|
|||||||
public static final int ERR_003 = 1003;
|
public static final int ERR_003 = 1003;
|
||||||
public static final int ERR_004 = 1004;
|
public static final int ERR_004 = 1004;
|
||||||
public static final int ERR_PCB_NOT_SUPPORT = 2000;
|
public static final int ERR_PCB_NOT_SUPPORT = 2000;
|
||||||
private static SensorScale mSensorScale;
|
private static FixedSensorScale mSensorScale;
|
||||||
private static String mDevicePort = "/dev/ttyS4";
|
private static String mDevicePort = "/dev/ttyS4";
|
||||||
|
// private static String mDevicePort = "/dev/ttyS7";
|
||||||
private static boolean mConnect = false;
|
private static boolean mConnect = false;
|
||||||
private static Listener mListener;
|
private static Listener mListener;
|
||||||
|
|
||||||
|
/** 允许外部在 init() 前设置串口路径,用于不同硬件型号的子设备 */
|
||||||
|
public static void setDevicePort(String port) {
|
||||||
|
mDevicePort = port;
|
||||||
|
Log.d(TAG, "串口已设置为: " + port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getDevicePort() {
|
||||||
|
return mDevicePort;
|
||||||
|
}
|
||||||
|
|
||||||
public static void init() {
|
public static void init() {
|
||||||
String var0;
|
String var0 = Build.MODEL;
|
||||||
if ((var0 = Build.MODEL) == "pcb_941") {
|
if ("pcb_941".equals(var0)) {
|
||||||
Log.w(TAG, "pcb not support, " + var0);
|
Log.w(TAG, "pcb not support, " + var0);
|
||||||
Listener var1;
|
Listener var1;
|
||||||
if ((var1 = mListener) != null) {
|
if ((var1 = mListener) != null) {
|
||||||
@@ -40,8 +51,9 @@ public class Weigher2 {
|
|||||||
} else {
|
} else {
|
||||||
System.init();
|
System.init();
|
||||||
initScale();
|
initScale();
|
||||||
if (var0 == "pcb_908") {
|
if ("pcb_908".equals(var0)) {
|
||||||
mDevicePort = "/dev/ttyS4";
|
// mDevicePort = "/dev/ttyS4";
|
||||||
|
mDevicePort = "/dev/ttyS7";
|
||||||
}
|
}
|
||||||
|
|
||||||
mSensorScale.openScale(mDevicePort, 115200, (open) -> {
|
mSensorScale.openScale(mDevicePort, 115200, (open) -> {
|
||||||
@@ -64,8 +76,8 @@ public class Weigher2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void config() {
|
public static void config() {
|
||||||
String var0;
|
String var0 = Build.MODEL;
|
||||||
if ((var0 = Build.MODEL) == "pcb_941") {
|
if ("pcb_941".equals(var0)) {
|
||||||
Log.w(TAG, "pcb not support, " + var0);
|
Log.w(TAG, "pcb not support, " + var0);
|
||||||
Listener var2;
|
Listener var2;
|
||||||
if ((var2 = mListener) != null) {
|
if ((var2 = mListener) != null) {
|
||||||
@@ -390,7 +402,8 @@ public class Weigher2 {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
//.<init>();
|
//.<init>();
|
||||||
mSensorScale = new SensorScale(var0);
|
// 使用修复版子类,解决地址 ≥ 10 时 zeroTwo/tareTwo 编码错误的问题
|
||||||
|
mSensorScale = new FixedSensorScale(var0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setNoPull485Pin(boolean noPull) {
|
public static void setNoPull485Pin(boolean noPull) {
|
||||||
@@ -406,7 +419,7 @@ public class Weigher2 {
|
|||||||
|
|
||||||
void onSetIdentify();
|
void onSetIdentify();
|
||||||
|
|
||||||
// void onGetWeight(int var1, int var2, int var3);
|
// void onGetWeight(int var1, int var2, int var3);
|
||||||
void onGetWeight(int var1, int var2, double var3);
|
void onGetWeight(int var1, int var2, double var3);
|
||||||
|
|
||||||
void onReadIdentify(int var1);
|
void onReadIdentify(int var1);
|
||||||
|
|||||||
@@ -1,33 +1,58 @@
|
|||||||
package com.shuwei.dish.match.utils
|
package com.shuwei.dish.match.utils
|
||||||
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
import com.shuwei.dish.match.utils.ext.roundedOneDecimalPlace
|
||||||
//import com.aithings.Weigher
|
|
||||||
import com.wabon.wbintelligenthardwaresdk.api.SensorScale
|
import com.wabon.wbintelligenthardwaresdk.api.SensorScale
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
typealias WeightCallback = (address: Int, state: Int, weight: Double) -> Unit
|
typealias WeightCallback = (address: Int, state: Int, weight: Double) -> Unit
|
||||||
|
|
||||||
object WeightUtil {
|
object WeightUtil {
|
||||||
private const val TAG = "WeightUtil"
|
private const val TAG = "WeightUtil"
|
||||||
const val STATE_STABLE = SensorScale.STATE_STABLE
|
// 使用字面量常量,避免在非 ARM 设备上触发 SensorScale 类加载
|
||||||
const val STATE_UNSTABLE = SensorScale.STATE_UNSTABLE
|
const val STATE_STABLE = 1
|
||||||
const val STATE_OVER_WEIGHT = SensorScale.STATE_OVER_WEIGHT
|
const val STATE_UNSTABLE = 0
|
||||||
|
const val STATE_OVER_WEIGHT = 2
|
||||||
|
|
||||||
var isConnected = false
|
var isConnected = false
|
||||||
var weightFuncMap: MutableMap<String, WeightCallback?>? =
|
/** 秤 SDK 是否可用;非 ARM 设备上为 false,所有秤操作将静默跳过 */
|
||||||
null
|
var isAvailable = false
|
||||||
|
val weightFuncMap: ConcurrentHashMap<String, WeightCallback?> = ConcurrentHashMap()
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
Weigher2.init()
|
val abi = Build.SUPPORTED_ABIS.firstOrNull() ?: ""
|
||||||
|
if (!abi.startsWith("arm")) {
|
||||||
|
Log.w(TAG, "当前架构 $abi 不支持秤 SDK,已跳过初始化")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
SensorScale.isLog = true
|
||||||
|
Weigher2.init()
|
||||||
|
} catch (e: UnsatisfiedLinkError) {
|
||||||
|
Log.w(TAG, "秤 SDK 加载失败(非 ARM 设备),已跳过: ${e.message}")
|
||||||
|
return
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.w(TAG, "秤 SDK 初始化异常,已跳过: ${e.message}")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
isAvailable = true
|
||||||
Weigher2.setListener(object : WeightListenerImpl() {
|
Weigher2.setListener(object : WeightListenerImpl() {
|
||||||
override fun onInit(connect: Boolean) {
|
override fun onInit(connect: Boolean) {
|
||||||
super.onInit(connect)
|
super.onInit(connect)
|
||||||
isConnected = connect
|
isConnected = connect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onTare() {
|
||||||
|
super.onTare()
|
||||||
|
Log.d(TAG, "tareTwo,onTare 回调触发")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onZero() {
|
||||||
|
super.onZero()
|
||||||
|
Log.d(TAG, "tareTwo,onZero 回调触发")
|
||||||
|
}
|
||||||
|
|
||||||
override fun onGetWeight(address: Int, state: Int, weight: Double) {
|
override fun onGetWeight(address: Int, state: Int, weight: Double) {
|
||||||
super.onGetWeight(address, state, weight)
|
super.onGetWeight(address, state, weight)
|
||||||
val stateStr = when (state) {
|
val stateStr = when (state) {
|
||||||
@@ -38,7 +63,7 @@ object WeightUtil {
|
|||||||
}
|
}
|
||||||
val useWeight = (weight*1000).roundedOneDecimalPlace()
|
val useWeight = (weight*1000).roundedOneDecimalPlace()
|
||||||
Log.d(TAG, "readWeight, address=$address,state=$stateStr, weight=$useWeight")
|
Log.d(TAG, "readWeight, address=$address,state=$stateStr, weight=$useWeight")
|
||||||
weightFuncMap?.forEach { (key, value) ->
|
weightFuncMap.forEach { (key, value) ->
|
||||||
value?.invoke(address, state, useWeight)
|
value?.invoke(address, state, useWeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,10 +80,12 @@ object WeightUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun startContinuousRead() {
|
fun startContinuousRead() {
|
||||||
|
if (!isAvailable) return
|
||||||
Weigher2.startContinuousRead()
|
Weigher2.startContinuousRead()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun stopContinuousRead() {
|
fun stopContinuousRead() {
|
||||||
|
if (!isAvailable) return
|
||||||
try {
|
try {
|
||||||
Weigher2.stopContinuousRead()
|
Weigher2.stopContinuousRead()
|
||||||
Weigher2.unInit()
|
Weigher2.unInit()
|
||||||
@@ -69,26 +96,25 @@ object WeightUtil {
|
|||||||
|
|
||||||
fun tareTwo(address: Int) {
|
fun tareTwo(address: Int) {
|
||||||
try {
|
try {
|
||||||
Weigher2.tareTwo(address)
|
Log.d(TAG, "tareTwo,执行清零操作: address=$address")
|
||||||
|
// SDK 内部自动管理总线,直接发送清零命令
|
||||||
|
Weigher2.zeroTwo(address)
|
||||||
|
// Weigher2.tareTwo(address)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
Log.e(TAG, "tareTwo,执行清零异常: address=$address, error=${e.message}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runOnUiThread(action: () -> Unit) {
|
fun removeWeightListener(weightKey: String) {
|
||||||
Handler(Looper.getMainLooper()).post {
|
weightFuncMap.remove(weightKey)
|
||||||
action()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addWeightListener(
|
fun addWeightListener(
|
||||||
weightKey: String,
|
weightKey: String,
|
||||||
getWeight: WeightCallback = { _, _, _ -> }
|
getWeight: WeightCallback = { _, _, _ -> }
|
||||||
) {
|
) {
|
||||||
if (weightFuncMap == null) {
|
weightFuncMap[weightKey] = getWeight
|
||||||
weightFuncMap = mutableMapOf()
|
|
||||||
}
|
|
||||||
weightFuncMap?.put(weightKey, getWeight)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +124,7 @@ open class WeightListenerImpl : Weigher2.Listener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onZero() {
|
override fun onZero() {
|
||||||
Log.d("WeightUtil", "zero ok")
|
Log.d("WeightUtil", "tareTwo,zero ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onTare() {
|
override fun onTare() {
|
||||||
|
|||||||
@@ -2,14 +2,15 @@ package com.shuwei.dish.match.viewmodel
|
|||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.shuwei.dish.match.db.AppRepository
|
import com.shuwei.dish.match.db.DbRepository
|
||||||
import com.shuwei.dish.match.entity.CookFoodEntity
|
import com.shuwei.dish.match.db.entity.CookFoodEntity
|
||||||
import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
import com.shuwei.dish.match.entity.SeasoningEntity
|
import com.shuwei.dish.match.db.entity.SeasoningEntity
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.collections.forEach
|
|
||||||
|
|
||||||
class AppViewModel(private val rep: AppRepository) : ViewModel() {
|
class AppViewModel : ViewModel() {
|
||||||
|
|
||||||
|
private val rep = DbRepository()
|
||||||
|
|
||||||
fun updateCookFood(entity: CookFoodEntity) {
|
fun updateCookFood(entity: CookFoodEntity) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@@ -17,9 +18,9 @@ class AppViewModel(private val rep: AppRepository) : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getCookFoodById(foodId: String, cookMode: Int, action: (CookFoodEntity?) -> Unit) {
|
fun getCookFoodById(foodId: String, cookMode: Int, dinnerType: String = "0", action: (CookFoodEntity?) -> Unit) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val data = rep.getCookFoodById(foodId, cookMode)
|
val data = rep.getCookFoodById(foodId, cookMode, dinnerType)
|
||||||
action(data)
|
action(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -42,17 +43,6 @@ class AppViewModel(private val rep: AppRepository) : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fun saveCookFood(cookMode: Int, entity: CookFoodEntity) {
|
|
||||||
// viewModelScope.launch {
|
|
||||||
// val data = rep.getCookFoodById(entity.foodId, cookMode)
|
|
||||||
// if (data == null) {
|
|
||||||
// rep.insertCookFood(entity)
|
|
||||||
// return@launch
|
|
||||||
// }
|
|
||||||
// rep.updateCookFood(entity)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fun saveCookFoodAndGoods(
|
fun saveCookFoodAndGoods(
|
||||||
cookMode: Int,
|
cookMode: Int,
|
||||||
entity: CookFoodEntity,
|
entity: CookFoodEntity,
|
||||||
@@ -60,19 +50,17 @@ class AppViewModel(private val rep: AppRepository) : ViewModel() {
|
|||||||
onFinish: () -> Unit
|
onFinish: () -> Unit
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val data = rep.getCookFoodById(entity.foodId, cookMode)
|
val data = rep.getCookFoodById(entity.foodId, cookMode, entity.dinnerType?:"")
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
//存在数据删除
|
rep.deleteCookFood(entity.foodId, cookMode, entity.dinnerType?:"")
|
||||||
rep.deleteCookFood(entity.foodId, cookMode)
|
|
||||||
rep.deleteCookFoodGoodsList(data.id, entity.foodId)
|
rep.deleteCookFoodGoodsList(data.id, entity.foodId)
|
||||||
}
|
}
|
||||||
//重新保存数据
|
|
||||||
rep.insertCookFood(entity)
|
rep.insertCookFood(entity)
|
||||||
val newData = rep.getCookFoodById(entity.foodId, cookMode)
|
val newData = rep.getCookFoodById(entity.foodId, cookMode, entity.dinnerType?:"")
|
||||||
list?.let { it ->
|
list?.let { it ->
|
||||||
it.forEach { goods ->
|
it.forEach { goods ->
|
||||||
goods.id = 0
|
goods.id = 0
|
||||||
goods.pid = newData?.id?:0
|
goods.pid = newData?.id ?: 0
|
||||||
}
|
}
|
||||||
rep.insertGoodsList(it)
|
rep.insertGoodsList(it)
|
||||||
}
|
}
|
||||||
@@ -83,28 +71,27 @@ class AppViewModel(private val rep: AppRepository) : ViewModel() {
|
|||||||
fun deleteCookFoodAndGoods(
|
fun deleteCookFoodAndGoods(
|
||||||
cookMode: Int,
|
cookMode: Int,
|
||||||
foodId: String,
|
foodId: String,
|
||||||
|
dinnerType: String = "0",
|
||||||
onFinish: () -> Unit
|
onFinish: () -> Unit
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val data = rep.getCookFoodById(foodId, cookMode)
|
val data = rep.getCookFoodById(foodId, cookMode, dinnerType)
|
||||||
if (data != null) {
|
if (data != null) {
|
||||||
rep.deleteCookFood(foodId = foodId, cookMode = cookMode)
|
rep.deleteCookFood(foodId = foodId, cookMode = cookMode, dinnerType = dinnerType)
|
||||||
rep.deleteCookFoodGoodsList(pid = data.id, foodId = foodId)
|
rep.deleteCookFoodGoodsList(pid = data.id, foodId = foodId)
|
||||||
}
|
}
|
||||||
onFinish()
|
onFinish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
fun getCookFoodGoodsList(
|
fun getCookFoodGoodsList(
|
||||||
foodId: String,
|
foodId: String,
|
||||||
cookMode: Int,
|
cookMode: Int,
|
||||||
|
dinnerType: String = "0",
|
||||||
action: (list: MutableList<CookFoodGoodsEntity>) -> Unit
|
action: (list: MutableList<CookFoodGoodsEntity>) -> Unit
|
||||||
) {
|
) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val cookFood = rep.getCookFoodById(foodId, cookMode)
|
val cookFood = rep.getCookFoodById(foodId, cookMode, dinnerType)
|
||||||
cookFood?.let {
|
cookFood?.let {
|
||||||
val list = rep.getCookFoodGoodsList(pid = it.id, foodId = it.foodId)
|
val list = rep.getCookFoodGoodsList(pid = it.id, foodId = it.foodId)
|
||||||
action(list)
|
action(list)
|
||||||
@@ -112,43 +99,6 @@ class AppViewModel(private val rep: AppRepository) : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fun updateGoods(entity: CookFoodGoodsEntity) {
|
|
||||||
// viewModelScope.launch {
|
|
||||||
// rep.updateGoods(entity)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fun saveCookFoodGoods(list: MutableList<CookFoodGoodsEntity>) {
|
|
||||||
// viewModelScope.launch {
|
|
||||||
// val foodId = list[0].foodId
|
|
||||||
// val data: MutableList<CookFoodGoodsEntity>? =
|
|
||||||
// rep.getCookFoodGoodsList(foodId!!)
|
|
||||||
// if (data.isNullOrEmpty()) {
|
|
||||||
// rep.insertGoodsList(list)
|
|
||||||
// return@launch
|
|
||||||
// }
|
|
||||||
// val localDbSeasoningList = rep.getCookFoodGoodsListByType(foodId, 3)
|
|
||||||
// localDbSeasoningList.forEach {
|
|
||||||
// it.isDel = 1
|
|
||||||
// //更新本地调料数据为已删除的状态
|
|
||||||
// rep.updateGoods(it)
|
|
||||||
// }
|
|
||||||
// //筛选出调料数据保存,主辅材不会变更不需要再次处理
|
|
||||||
// val saveSeasoningList = list.filter { it.materialType == 3 }
|
|
||||||
// rep.insertGoodsList(saveSeasoningList.toMutableList())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// fun addSeasoning(list: MutableList<SeasoningEntity>, callback: () -> Unit) {
|
|
||||||
// viewModelScope.launch {
|
|
||||||
// rep.deleteBatch()
|
|
||||||
// rep.insertSeasoningList(items = list)
|
|
||||||
// callback()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
private var isProcessing = false
|
private var isProcessing = false
|
||||||
fun loadSeasoning(action: (MutableList<SeasoningEntity>) -> Unit) {
|
fun loadSeasoning(action: (MutableList<SeasoningEntity>) -> Unit) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
@@ -166,25 +116,17 @@ class AppViewModel(private val rep: AppRepository) : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun clearAllSeasoning(action:()->Unit) {
|
fun clearAllSeasoning(action: () -> Unit) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
rep.clearAllSeasoning()
|
rep.clearAllSeasoning()
|
||||||
action()
|
action()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// fun updateAll(list: MutableList<SeasoningEntity>) {
|
|
||||||
// viewModelScope.launch {
|
|
||||||
// list.forEach {
|
|
||||||
// rep.updateSeasoning(it)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fun saveSeasoning(entity: SeasoningEntity, block: () -> Unit) {
|
fun saveSeasoning(entity: SeasoningEntity, block: () -> Unit) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
val list = rep.getSeasoningBySort(entity.sort)
|
val list = rep.getSeasoningBySort(entity.sort)
|
||||||
val size = list?.size?:0
|
val size = list?.size ?: 0
|
||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
rep.updateSeasoning(entity.also { it.id = list!![0].id })
|
rep.updateSeasoning(entity.also { it.id = list!![0].id })
|
||||||
block()
|
block()
|
||||||
@@ -201,6 +143,4 @@ class AppViewModel(private val rep: AppRepository) : ViewModel() {
|
|||||||
block()
|
block()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//--------------------------------------------------------------------------------------------------------
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//import androidx.lifecycle.ViewModel
|
//import androidx.lifecycle.ViewModel
|
||||||
//import androidx.lifecycle.viewModelScope
|
//import androidx.lifecycle.viewModelScope
|
||||||
//import com.shuwei.dish.match.db.CookFoodGoodsRepository
|
//import com.shuwei.dish.match.db.CookFoodGoodsRepository
|
||||||
//import com.shuwei.dish.match.entity.CookFoodGoodsEntity
|
//import com.shuwei.dish.match.db.entity.CookFoodGoodsEntity
|
||||||
//import kotlinx.coroutines.launch
|
//import kotlinx.coroutines.launch
|
||||||
//
|
//
|
||||||
//class CookFoodGoodsViewModel(private val rep: CookFoodGoodsRepository) : ViewModel() {
|
//class CookFoodGoodsViewModel(private val rep: CookFoodGoodsRepository) : ViewModel() {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//import androidx.lifecycle.ViewModel
|
//import androidx.lifecycle.ViewModel
|
||||||
//import androidx.lifecycle.viewModelScope
|
//import androidx.lifecycle.viewModelScope
|
||||||
//import com.shuwei.dish.match.db.CookFoodRepository
|
//import com.shuwei.dish.match.db.CookFoodRepository
|
||||||
//import com.shuwei.dish.match.entity.CookFoodEntity
|
//import com.shuwei.dish.match.db.entity.CookFoodEntity
|
||||||
//import kotlinx.coroutines.launch
|
//import kotlinx.coroutines.launch
|
||||||
//
|
//
|
||||||
//class CookFoodViewModel(private val rep: CookFoodRepository) : ViewModel() {
|
//class CookFoodViewModel(private val rep: CookFoodRepository) : ViewModel() {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
//import androidx.lifecycle.ViewModel
|
//import androidx.lifecycle.ViewModel
|
||||||
//import androidx.lifecycle.viewModelScope
|
//import androidx.lifecycle.viewModelScope
|
||||||
//import com.shuwei.dish.match.db.SeasoningRepository
|
//import com.shuwei.dish.match.db.SeasoningRepository
|
||||||
//import com.shuwei.dish.match.entity.SeasoningEntity
|
//import com.shuwei.dish.match.db.entity.SeasoningEntity
|
||||||
//import kotlinx.coroutines.delay
|
//import kotlinx.coroutines.delay
|
||||||
//import kotlinx.coroutines.launch
|
//import kotlinx.coroutines.launch
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
//import androidx.lifecycle.ViewModel
|
//import androidx.lifecycle.ViewModel
|
||||||
//import androidx.lifecycle.viewModelScope
|
//import androidx.lifecycle.viewModelScope
|
||||||
//import com.shuwei.dish.match.db.SeasoningRepository
|
//import com.shuwei.dish.match.db.SeasoningRepository
|
||||||
//import com.shuwei.dish.match.entity.CookFoodEntity
|
//import com.shuwei.dish.match.db.entity.CookFoodEntity
|
||||||
//import com.shuwei.dish.match.entity.SeasoningEntity
|
//import com.shuwei.dish.match.db.entity.SeasoningEntity
|
||||||
//import kotlinx.coroutines.launch
|
//import kotlinx.coroutines.launch
|
||||||
//
|
//
|
||||||
//class SubmitDishViewModel(private val rep: SeasoningRepository) : ViewModel() {
|
//class SubmitDishViewModel(private val rep: SeasoningRepository) : ViewModel() {
|
||||||
|
|||||||
@@ -1,43 +0,0 @@
|
|||||||
package com.shuwei.dish.match.viewmodel.factory
|
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
|
||||||
import androidx.lifecycle.ViewModelProvider
|
|
||||||
import com.shuwei.dish.match.db.AppRepository
|
|
||||||
import com.shuwei.dish.match.viewmodel.AppViewModel
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
class AppFactory(private val repo: AppRepository) : ViewModelProvider.Factory {
|
|
||||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
return AppViewModel(repo) as T
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
//@Suppress("UNCHECKED_CAST")
|
|
||||||
//class DeviceSettingFactory(private val repo: SeasoningRepository) : ViewModelProvider.Factory {
|
|
||||||
// override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
// return DeviceSettingViewModel(repo) as T
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
////@Suppress("UNCHECKED_CAST")
|
|
||||||
////class SubmitDishFactory(private val repo: SeasoningRepository) : ViewModelProvider.Factory {
|
|
||||||
//// override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
//// return SubmitDishViewModel(repo) as T
|
|
||||||
//// }
|
|
||||||
////}
|
|
||||||
//
|
|
||||||
//@Suppress("UNCHECKED_CAST")
|
|
||||||
//class CookFoodFactory(private val repo: CookFoodRepository) : ViewModelProvider.Factory {
|
|
||||||
// override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
// return CookFoodViewModel(repo) as T
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//@Suppress("UNCHECKED_CAST")
|
|
||||||
//class CookFoodGoodsFactory(private val repo: CookFoodGoodsRepository) : ViewModelProvider.Factory {
|
|
||||||
// override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
|
||||||
// return CookFoodGoodsViewModel(repo) as T
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
Binary file not shown.
@@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<solid android:color="#FFEBEE" />
|
||||||
|
<corners android:radius="10dp" />
|
||||||
|
<stroke
|
||||||
|
android:width="2dp"
|
||||||
|
android:color="#FF5252" />
|
||||||
|
</shape>
|
||||||
@@ -126,19 +126,13 @@
|
|||||||
android:textColor="@color/gray_b4"
|
android:textColor="@color/gray_b4"
|
||||||
android:textSize="28sp" />
|
android:textSize="28sp" />
|
||||||
|
|
||||||
<!-- <View-->
|
|
||||||
<!-- android:id="@+id/viewPoint"-->
|
|
||||||
<!-- android:layout_width="5dp"-->
|
|
||||||
<!-- android:layout_height="5dp"-->
|
|
||||||
<!-- android:layout_gravity="center_vertical"-->
|
|
||||||
<!-- android:background="@drawable/bg_circle_green"/>-->
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/include"
|
android:id="@+id/include"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
layout="@layout/layout_grid"/>
|
layout="@layout/layout_grid" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user