feat(shelf): 添加净菜毛菜搜索和分类选择功能
- 新增 tvFoodType TextView 显示食品分类 - 将搜索框可见性从 gone 改为 visible - 添加 FoodItem 和 FoodType 数据模型 - 添加 SearchFoodRequest 请求模型 - 在 ApiServiceV3 中新增 searchFood 接口 - 在 NetViewModelV3 中新增 searchFood 方法 - 修改 PutSlotRequest 模型字段为可空类型并添加 vegTypeId - 更新 HomeV3Activity 中行列计算逻辑 - 缩短商品数据同步间隔时间 - 修改 InitActivity 中的基础URL配置 - 将 PendingInboundAdapter 适配器改为使用 FoodItem 类型 - 在 ShelfV3Activity 中实现净菜分类选择对话框功能 - 添加 ChipSelectDialog 自定义对话框组件 - 添加 chip 相关的颜色资源文件 - 实现搜索功能替换原有的待入库查询逻辑
This commit is contained in:
@@ -0,0 +1,100 @@
|
|||||||
|
package com.shuwei.intelligent.shelves.dialog
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.Gravity
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import com.google.android.material.chip.Chip
|
||||||
|
import com.shuwei.intelligent.shelves.R
|
||||||
|
import com.shuwei.intelligent.shelves.base.BaseDialog
|
||||||
|
import com.shuwei.intelligent.shelves.databinding.DialogChipSelectBinding
|
||||||
|
import com.shuwei.intelligent.shelves.utils.ext.dp
|
||||||
|
import com.shuwei.intelligent.shelves.utils.ext.hideKeyboard
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 带ChipGroup选择的弹窗,支持传入选项列表,回调返回选中索引
|
||||||
|
*/
|
||||||
|
class ChipSelectDialog(context: Context) : Dialog(context, R.style.DialogTheme) {
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
binding = DialogChipSelectBinding.inflate(LayoutInflater.from(context))
|
||||||
|
setContentView(binding.root)
|
||||||
|
setCancelable(false)
|
||||||
|
setCanceledOnTouchOutside(false)
|
||||||
|
window?.apply {
|
||||||
|
//setLayout(defWidth, defHeight)
|
||||||
|
setBackgroundDrawable(ColorDrawable())
|
||||||
|
setGravity(Gravity.CENTER)
|
||||||
|
}
|
||||||
|
binding.root.setOnClickListener { it.hideKeyboard() }
|
||||||
|
initView()
|
||||||
|
}
|
||||||
|
|
||||||
|
private lateinit var binding: DialogChipSelectBinding
|
||||||
|
|
||||||
|
/** 弹窗标题 */
|
||||||
|
var dialogTitle: String? = null
|
||||||
|
|
||||||
|
/** 选项列表 */
|
||||||
|
var items: List<String?> = emptyList()
|
||||||
|
|
||||||
|
/** 选中回调,返回选中的索引,取消时不触发 */
|
||||||
|
var onItemSelected: ((Int) -> Unit)? = null
|
||||||
|
|
||||||
|
/** 当前选中的索引,默认-1表示未选中 */
|
||||||
|
private var selectedIndex: Int = -1
|
||||||
|
|
||||||
|
|
||||||
|
fun initView() {
|
||||||
|
binding.btnCancel.setOnClickListener {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.btnConfirm.setOnClickListener {
|
||||||
|
if (selectedIndex >= 0) {
|
||||||
|
onItemSelected?.invoke(selectedIndex)
|
||||||
|
}
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun show() {
|
||||||
|
super.show()
|
||||||
|
binding.tvDialogTitle.text = dialogTitle
|
||||||
|
setupChips()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态创建Chip并添加到ChipGroup中
|
||||||
|
*/
|
||||||
|
private fun setupChips() {
|
||||||
|
binding.chipGroup.removeAllViews()
|
||||||
|
selectedIndex = -1
|
||||||
|
|
||||||
|
items.forEachIndexed { index, label ->
|
||||||
|
val chip = Chip(context).apply {
|
||||||
|
text = label
|
||||||
|
isCheckable = true
|
||||||
|
isCheckedIconVisible = false
|
||||||
|
textSize = 20f
|
||||||
|
chipStartPadding = 15.dp.toFloat()
|
||||||
|
chipEndPadding = 15.dp.toFloat()
|
||||||
|
textStartPadding = 8.dp.toFloat()
|
||||||
|
textEndPadding = 8.dp.toFloat()
|
||||||
|
chipMinHeight = 50.dp.toFloat()
|
||||||
|
setTextColor(resources.getColorStateList(R.color.chip_text_color, null))
|
||||||
|
chipBackgroundColor = resources.getColorStateList(R.color.chip_bg_color, null)
|
||||||
|
chipStrokeWidth = 1f
|
||||||
|
chipStrokeColor = resources.getColorStateList(R.color.chip_stroke_color, null)
|
||||||
|
setOnClickListener {
|
||||||
|
selectedIndex = index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.chipGroup.addView(chip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -151,8 +151,10 @@ class HomeV3Activity : BaseActivity() {
|
|||||||
|
|
||||||
// val columns = if (ProtocolConstants.device3Columns.contains(App.deviceId)) 3 else 2
|
// val columns = if (ProtocolConstants.device3Columns.contains(App.deviceId)) 3 else 2
|
||||||
// val rows = if (slots.size % columns == 0) slots.size / columns else 5
|
// val rows = if (slots.size % columns == 0) slots.size / columns else 5
|
||||||
val columns = record.verticalCount
|
// val columns = record.verticalCount
|
||||||
val rows = record.horizontalRows
|
// val rows = record.horizontalRows
|
||||||
|
val rows = record.verticalCount
|
||||||
|
val columns = record.horizontalRows
|
||||||
log("updateUI: slots=${slots.size}, rows=$rows, columns=$columns")
|
log("updateUI: slots=${slots.size}, rows=$rows, columns=$columns")
|
||||||
|
|
||||||
list.clear()
|
list.clear()
|
||||||
@@ -328,7 +330,7 @@ class HomeV3Activity : BaseActivity() {
|
|||||||
|
|
||||||
private fun saveGoodsTask() {
|
private fun saveGoodsTask() {
|
||||||
saveTaskJob =
|
saveTaskJob =
|
||||||
taskExecutor.startIntervalTaskWithInitialDelay(10 * 1000L, 2 * 60 * 1000L) {
|
taskExecutor.startIntervalTaskWithInitialDelay(10 * 1000L, 1 * 60 * 1000L) {
|
||||||
syncShelfGoodsToServer()
|
syncShelfGoodsToServer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ class InitActivity : BaseActivity() {
|
|||||||
App.deviceId = AppUtil.getUDID(this)
|
App.deviceId = AppUtil.getUDID(this)
|
||||||
// TODO: 测试设备号
|
// TODO: 测试设备号
|
||||||
// App.deviceId = "d369f9b0-1c5b-3066-ba72-988e1449cecc"
|
// App.deviceId = "d369f9b0-1c5b-3066-ba72-988e1449cecc"
|
||||||
|
// App.deviceId = "25b777a9-6298-30d3-a5f8-3b3eef2a50f7"
|
||||||
// App.deviceId = "505ce1b1-facc-3eb2-855a-3dadda5ba358"
|
// App.deviceId = "505ce1b1-facc-3eb2-855a-3dadda5ba358"
|
||||||
Log.d(TAG, "onCreate: deviceId = ${App.deviceId}")
|
Log.d(TAG, "onCreate: deviceId = ${App.deviceId}")
|
||||||
SpTool.put(SpTool.DEVICE_ID, App.deviceId)
|
SpTool.put(SpTool.DEVICE_ID, App.deviceId)
|
||||||
@@ -48,7 +49,7 @@ class InitActivity : BaseActivity() {
|
|||||||
// } else {
|
// } else {
|
||||||
// GlobalData.appBaseUrl = GlobalData.PROD_BASE_URL
|
// GlobalData.appBaseUrl = GlobalData.PROD_BASE_URL
|
||||||
// }
|
// }
|
||||||
GlobalData.appBaseUrl = GlobalData.LOCAL_BASE_URL
|
GlobalData.appBaseUrl = GlobalData.TEST_BASE_URL
|
||||||
App.canteenId = "0"
|
App.canteenId = "0"
|
||||||
|
|
||||||
binding.ivQrCode.invisible()
|
binding.ivQrCode.invisible()
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ import com.scwang.smart.refresh.layout.constant.RefreshState
|
|||||||
import com.shuwei.intelligent.shelves.R
|
import com.shuwei.intelligent.shelves.R
|
||||||
import com.shuwei.intelligent.shelves.base.BaseActivity
|
import com.shuwei.intelligent.shelves.base.BaseActivity
|
||||||
import com.shuwei.intelligent.shelves.databinding.ActivityShelfV3Binding
|
import com.shuwei.intelligent.shelves.databinding.ActivityShelfV3Binding
|
||||||
|
import com.shuwei.intelligent.shelves.dialog.ChipSelectDialog
|
||||||
|
import com.shuwei.intelligent.shelves.dialog.CommonDialog
|
||||||
import com.shuwei.intelligent.shelves.model.SendWeightEvent
|
import com.shuwei.intelligent.shelves.model.SendWeightEvent
|
||||||
import com.shuwei.intelligent.shelves.net.Loading
|
import com.shuwei.intelligent.shelves.net.Loading
|
||||||
import com.shuwei.intelligent.shelves.serial.ScaleManager
|
import com.shuwei.intelligent.shelves.serial.ScaleManager
|
||||||
@@ -25,9 +27,11 @@ import com.shuwei.intelligent.shelves.utils.ext.gone
|
|||||||
import com.shuwei.intelligent.shelves.utils.ext.toast
|
import com.shuwei.intelligent.shelves.utils.ext.toast
|
||||||
import com.shuwei.intelligent.shelves.utils.ext.visible
|
import com.shuwei.intelligent.shelves.utils.ext.visible
|
||||||
import com.sw.scalefusion.shelf.adapter.PendingInboundAdapter
|
import com.sw.scalefusion.shelf.adapter.PendingInboundAdapter
|
||||||
|
import com.sw.scalefusion.shelf.model.FoodItem
|
||||||
import com.sw.scalefusion.shelf.model.PendingInboundItem
|
import com.sw.scalefusion.shelf.model.PendingInboundItem
|
||||||
import com.sw.scalefusion.shelf.model.PendingInboundRequest
|
import com.sw.scalefusion.shelf.model.PendingInboundRequest
|
||||||
import com.sw.scalefusion.shelf.model.PutSlotRequest
|
import com.sw.scalefusion.shelf.model.PutSlotRequest
|
||||||
|
import com.sw.scalefusion.shelf.model.SearchFoodRequest
|
||||||
import com.sw.scalefusion.shelf.model.SlotDetailRequest
|
import com.sw.scalefusion.shelf.model.SlotDetailRequest
|
||||||
import com.sw.scalefusion.shelf.model.SlotModel
|
import com.sw.scalefusion.shelf.model.SlotModel
|
||||||
import com.sw.scalefusion.shelf.net.NetViewModelV3
|
import com.sw.scalefusion.shelf.net.NetViewModelV3
|
||||||
@@ -59,17 +63,42 @@ class ShelfV3Activity : BaseActivity() {
|
|||||||
|
|
||||||
private val viewModel: NetViewModelV3 by viewModels()
|
private val viewModel: NetViewModelV3 by viewModels()
|
||||||
|
|
||||||
private val optionList: MutableList<PendingInboundItem> = mutableListOf()
|
private val optionList: MutableList<FoodItem> = mutableListOf()
|
||||||
private val optionAdapter by lazy {
|
private val optionAdapter by lazy {
|
||||||
PendingInboundAdapter(optionList).apply {
|
PendingInboundAdapter(optionList).apply {
|
||||||
setOnDebouncedItemClick { _, _, position ->
|
setOnDebouncedItemClick { _, _, position ->
|
||||||
|
val vegTypeList = getItem(position)?.vegTypeList ?: emptyList()
|
||||||
|
if (vegTypeList.isEmpty()) {
|
||||||
|
selectCategory(position)
|
||||||
|
return@setOnDebouncedItemClick
|
||||||
|
}
|
||||||
|
val categoryList = vegTypeList.map { it.vegTypeName }
|
||||||
|
if (categoryList.isEmpty()) {
|
||||||
|
CommonDialog(this@ShelfV3Activity).apply {
|
||||||
|
dialogTitle = "净菜选择"
|
||||||
|
dialogContent = "暂无净菜类别,请联系管理员添加,或稍后重试"
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
return@setOnDebouncedItemClick
|
||||||
|
}
|
||||||
|
showChipSelectDialog(categoryList) { index ->
|
||||||
|
getItem(position)?.typeSelectedIndex = index
|
||||||
|
selectCategory(position)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun selectCategory(position: Int) {
|
||||||
optionList.forEachIndexed { index, option -> option.isSelected = index == position }
|
optionList.forEachIndexed { index, option -> option.isSelected = index == position }
|
||||||
notifyDataSetChanged()
|
optionAdapter.notifyDataSetChanged()
|
||||||
binding.tvFoodName.text = optionList[position].materName
|
binding.tvFoodName.text = optionList[position].materName
|
||||||
|
val index = optionList[position].typeSelectedIndex
|
||||||
|
val typeList = optionList[position].vegTypeList ?: emptyList()
|
||||||
|
val selectType = typeList.getOrNull(index)?.vegTypeName ?: ""
|
||||||
|
binding.tvFoodType.text = selectType
|
||||||
KeyboardUtil.hideKeyboard(this@ShelfV3Activity.window.decorView)
|
KeyboardUtil.hideKeyboard(this@ShelfV3Activity.window.decorView)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private var cabinetType: Int = 0
|
private var cabinetType: Int = 0
|
||||||
private var canteenId: Long = 0
|
private var canteenId: Long = 0
|
||||||
@@ -113,6 +142,7 @@ class ShelfV3Activity : BaseActivity() {
|
|||||||
/** 从 slotDetail 响应更新 UI */
|
/** 从 slotDetail 响应更新 UI */
|
||||||
private fun updateUI(model: SlotModel) {
|
private fun updateUI(model: SlotModel) {
|
||||||
binding.tvFoodName.text = if (model.materName.isNullOrBlank()) "-" else model.materName
|
binding.tvFoodName.text = if (model.materName.isNullOrBlank()) "-" else model.materName
|
||||||
|
binding.tvFoodType.text = ""
|
||||||
val weightG = model.weight ?: 0.0
|
val weightG = model.weight ?: 0.0
|
||||||
realWeight = (weightG * 1000.0).toInt()
|
realWeight = (weightG * 1000.0).toInt()
|
||||||
binding.tvFoodWeight.text = if (weightG >= 1.0) "%.3f千克".format(weightG)
|
binding.tvFoodWeight.text = if (weightG >= 1.0) "%.3f千克".format(weightG)
|
||||||
@@ -155,7 +185,7 @@ class ShelfV3Activity : BaseActivity() {
|
|||||||
binding.btnClearEmpty.setOnClickListener { v ->
|
binding.btnClearEmpty.setOnClickListener { v ->
|
||||||
clearZero()
|
clearZero()
|
||||||
binding.tvFoodName.text = "-"
|
binding.tvFoodName.text = "-"
|
||||||
|
binding.tvFoodType.text = ""
|
||||||
Loading.show(this@ShelfV3Activity)
|
Loading.show(this@ShelfV3Activity)
|
||||||
v.postDelayed({
|
v.postDelayed({
|
||||||
Loading.dismiss()
|
Loading.dismiss()
|
||||||
@@ -188,9 +218,10 @@ class ShelfV3Activity : BaseActivity() {
|
|||||||
slotNo = slotNo,
|
slotNo = slotNo,
|
||||||
materId = item.materId,
|
materId = item.materId,
|
||||||
materName = item.materName,
|
materName = item.materName,
|
||||||
traceCode = item.traceCode,
|
|
||||||
weight = shelfModel?.weight ?: 0.0
|
weight = shelfModel?.weight ?: 0.0
|
||||||
),
|
).also {
|
||||||
|
it.vegTypeId = item.vegTypeList?.getOrNull(item.typeSelectedIndex)?.vegTypeId
|
||||||
|
},
|
||||||
onLoading = { showProgress() },
|
onLoading = { showProgress() },
|
||||||
onSuccess = onSuccess@{ inboundNo ->
|
onSuccess = onSuccess@{ inboundNo ->
|
||||||
Loading.dismiss()
|
Loading.dismiss()
|
||||||
@@ -213,11 +244,10 @@ class ShelfV3Activity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadList() {
|
private fun loadList() {
|
||||||
viewModel.pendingInbound(
|
viewModel.searchFood(
|
||||||
request = PendingInboundRequest(
|
request = SearchFoodRequest(
|
||||||
cabinetType = shelfModel?.cabinetType ?: 0,
|
cabinetType = shelfModel?.cabinetType ?: 0,
|
||||||
cabinetId = shelfModel?.cabinetId ?: "",
|
keyword = binding.etInputFood.text.toString().trim()
|
||||||
canteenId = canteenId
|
|
||||||
),
|
),
|
||||||
onLoading = { showProgress() },
|
onLoading = { showProgress() },
|
||||||
onSuccess = { items -> updateOptionList(items) },
|
onSuccess = { items -> updateOptionList(items) },
|
||||||
@@ -230,9 +260,9 @@ class ShelfV3Activity : BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("NotifyDataSetChanged")
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
private fun updateOptionList(items: List<PendingInboundItem>?) {
|
private fun updateOptionList(items: List<FoodItem>?) {
|
||||||
finishRefresh()
|
finishRefresh()
|
||||||
binding.include?.root?.gone()
|
binding.include.root.gone()
|
||||||
binding.root.postDelayed({ Loading.dismiss() }, 200)
|
binding.root.postDelayed({ Loading.dismiss() }, 200)
|
||||||
if (items.isNullOrEmpty()) {
|
if (items.isNullOrEmpty()) {
|
||||||
loadEmptyView(); return
|
loadEmptyView(); return
|
||||||
@@ -317,4 +347,14 @@ class ShelfV3Activity : BaseActivity() {
|
|||||||
startTime = System.currentTimeMillis()
|
startTime = System.currentTimeMillis()
|
||||||
window.decorView.postDelayed({ Loading.dismiss() }, 1000)
|
window.decorView.postDelayed({ Loading.dismiss() }, 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showChipSelectDialog(categoryList: List<String?>, callback: (Int) -> Unit) {
|
||||||
|
ChipSelectDialog(this).apply {
|
||||||
|
dialogTitle = "请选择净菜分类"
|
||||||
|
items = categoryList
|
||||||
|
onItemSelected = callback
|
||||||
|
show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,10 @@ import com.chad.library.adapter4.BaseQuickAdapter
|
|||||||
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
import com.chad.library.adapter4.viewholder.QuickViewHolder
|
||||||
import com.shuwei.intelligent.shelves.R
|
import com.shuwei.intelligent.shelves.R
|
||||||
import com.shuwei.intelligent.shelves.databinding.ListItemSearchBinding
|
import com.shuwei.intelligent.shelves.databinding.ListItemSearchBinding
|
||||||
import com.sw.scalefusion.shelf.model.PendingInboundItem
|
import com.sw.scalefusion.shelf.model.FoodItem
|
||||||
|
|
||||||
class PendingInboundAdapter(list: MutableList<PendingInboundItem>) :
|
class PendingInboundAdapter(list: MutableList<FoodItem>) :
|
||||||
BaseQuickAdapter<PendingInboundItem, PendingInboundAdapter.VH>(list) {
|
BaseQuickAdapter<FoodItem, PendingInboundAdapter.VH>(list) {
|
||||||
|
|
||||||
inner class VH(val binding: ListItemSearchBinding) : QuickViewHolder(binding.root)
|
inner class VH(val binding: ListItemSearchBinding) : QuickViewHolder(binding.root)
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ class PendingInboundAdapter(list: MutableList<PendingInboundItem>) :
|
|||||||
return VH(binding)
|
return VH(binding)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: VH, position: Int, item: PendingInboundItem?) {
|
override fun onBindViewHolder(holder: VH, position: Int, item: FoodItem?) {
|
||||||
item ?: return
|
item ?: return
|
||||||
val isSelected = item.isSelected
|
val isSelected = item.isSelected
|
||||||
holder.binding.btnFoodName.run {
|
holder.binding.btnFoodName.run {
|
||||||
|
|||||||
@@ -6,14 +6,20 @@ data class PendingInboundRequest(
|
|||||||
var cabinetId: String
|
var cabinetId: String
|
||||||
)
|
)
|
||||||
|
|
||||||
|
data class SearchFoodRequest(
|
||||||
|
var cabinetType: Int,
|
||||||
|
var keyword: String? = null
|
||||||
|
)
|
||||||
|
|
||||||
data class PutSlotRequest(
|
data class PutSlotRequest(
|
||||||
val cabinetType: Int,
|
val cabinetType: Int? = null,
|
||||||
val cabinetId: String,
|
val cabinetId: String? = null,
|
||||||
val slotNo: String,
|
val slotNo: String? = null,
|
||||||
val materId: Long,
|
val materId: Long? = null,
|
||||||
val materName: String,
|
var vegTypeId: Long? = null,
|
||||||
|
val materName: String? = null,
|
||||||
val traceCode: String? = null,
|
val traceCode: String? = null,
|
||||||
val weight: Double
|
val weight: Double? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
data class SlotDetailRequest(
|
data class SlotDetailRequest(
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.sw.scalefusion.shelf.model
|
||||||
|
|
||||||
|
import com.shuwei.intelligent.shelves.utils.DateTimeUtil
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
|
data class FoodItem(
|
||||||
|
var materId:Long? = null,
|
||||||
|
var materName:String? = null,
|
||||||
|
var materUrl:String? = null,
|
||||||
|
var vegTypeList:List<FoodType>? = null,
|
||||||
|
var isSelected:Boolean = false,
|
||||||
|
var typeSelectedIndex:Int = -1
|
||||||
|
) {
|
||||||
|
/** 转换为 SlotModel,保留原格口的 slotNo/cabinetId 等 */
|
||||||
|
fun toSlotModel(model: SlotModel) = model.copy(
|
||||||
|
materId = materId ,
|
||||||
|
materName = materName,
|
||||||
|
storeTime = DateTimeUtil.formatDateTime(dateTime = Date()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class FoodType(
|
||||||
|
var vegTypeId:Long? = null,
|
||||||
|
var vegTypeName:String? = null
|
||||||
|
)
|
||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.sw.scalefusion.shelf.net
|
package com.sw.scalefusion.shelf.net
|
||||||
|
|
||||||
import com.shuwei.intelligent.shelves.App
|
import com.shuwei.intelligent.shelves.App
|
||||||
|
import com.sw.scalefusion.shelf.model.FoodItem
|
||||||
import com.sw.scalefusion.shelf.model.PendingInboundItem
|
import com.sw.scalefusion.shelf.model.PendingInboundItem
|
||||||
import com.sw.scalefusion.shelf.model.PendingInboundRequest
|
import com.sw.scalefusion.shelf.model.PendingInboundRequest
|
||||||
import com.sw.scalefusion.shelf.model.PutSlotRequest
|
import com.sw.scalefusion.shelf.model.PutSlotRequest
|
||||||
|
import com.sw.scalefusion.shelf.model.SearchFoodRequest
|
||||||
import com.sw.scalefusion.shelf.model.SlotDetailRequest
|
import com.sw.scalefusion.shelf.model.SlotDetailRequest
|
||||||
import com.sw.scalefusion.shelf.model.SlotModel
|
import com.sw.scalefusion.shelf.model.SlotModel
|
||||||
import com.sw.scalefusion.shelf.model.SlotRecord
|
import com.sw.scalefusion.shelf.model.SlotRecord
|
||||||
@@ -23,6 +25,10 @@ interface ApiServiceV3 {
|
|||||||
@POST("/nutrition/neglect/mater-cabinet/pending-inbound")
|
@POST("/nutrition/neglect/mater-cabinet/pending-inbound")
|
||||||
suspend fun pendingInbound(@Body request: PendingInboundRequest): ApiResponse<List<PendingInboundItem>?>
|
suspend fun pendingInbound(@Body request: PendingInboundRequest): ApiResponse<List<PendingInboundItem>?>
|
||||||
|
|
||||||
|
/** 搜索净菜、毛菜 */
|
||||||
|
@POST("/nutrition/neglect/mater-cabinet/ingredients")
|
||||||
|
suspend fun searchFood(@Body request: SearchFoodRequest): ApiResponse<List<FoodItem>?>
|
||||||
|
|
||||||
/** 全量同步重量 */
|
/** 全量同步重量 */
|
||||||
@POST("/nutrition/neglect/mater-cabinet/sync-weight")
|
@POST("/nutrition/neglect/mater-cabinet/sync-weight")
|
||||||
suspend fun syncWeight(@Body request: SyncWeightRequest): ApiResponse<Any?>
|
suspend fun syncWeight(@Body request: SyncWeightRequest): ApiResponse<Any?>
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ package com.sw.scalefusion.shelf.net
|
|||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.sw.scalefusion.shelf.model.FoodItem
|
||||||
import com.sw.scalefusion.shelf.model.PendingInboundItem
|
import com.sw.scalefusion.shelf.model.PendingInboundItem
|
||||||
import com.sw.scalefusion.shelf.model.PendingInboundRequest
|
import com.sw.scalefusion.shelf.model.PendingInboundRequest
|
||||||
import com.sw.scalefusion.shelf.model.PutSlotRequest
|
import com.sw.scalefusion.shelf.model.PutSlotRequest
|
||||||
|
import com.sw.scalefusion.shelf.model.SearchFoodRequest
|
||||||
import com.sw.scalefusion.shelf.model.SlotDetailRequest
|
import com.sw.scalefusion.shelf.model.SlotDetailRequest
|
||||||
import com.sw.scalefusion.shelf.model.SlotModel
|
import com.sw.scalefusion.shelf.model.SlotModel
|
||||||
import com.sw.scalefusion.shelf.model.SlotRecord
|
import com.sw.scalefusion.shelf.model.SlotRecord
|
||||||
@@ -44,6 +46,16 @@ class NetViewModelV3 : ViewModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 搜索净菜、毛菜 */
|
||||||
|
fun searchFood(request: SearchFoodRequest, onLoading: () -> Unit = {}, onSuccess: (List<FoodItem>?) -> Unit, onError: (String) -> Unit = {}) {
|
||||||
|
viewModelScope.launch {
|
||||||
|
onLoading()
|
||||||
|
val response = repository.searchFood(request)
|
||||||
|
if (response.isSuccess()) onSuccess(response.data)
|
||||||
|
else onError(response.msg ?: "请求失败")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** 格口详情 */
|
/** 格口详情 */
|
||||||
fun slotDetail(
|
fun slotDetail(
|
||||||
request: SlotDetailRequest,
|
request: SlotDetailRequest,
|
||||||
|
|||||||
@@ -2,9 +2,11 @@ package com.sw.scalefusion.shelf.net
|
|||||||
|
|
||||||
import com.shuwei.intelligent.shelves.App
|
import com.shuwei.intelligent.shelves.App
|
||||||
import com.shuwei.intelligent.shelves.net.apiServiceV3
|
import com.shuwei.intelligent.shelves.net.apiServiceV3
|
||||||
|
import com.sw.scalefusion.shelf.model.FoodItem
|
||||||
import com.sw.scalefusion.shelf.model.PendingInboundItem
|
import com.sw.scalefusion.shelf.model.PendingInboundItem
|
||||||
import com.sw.scalefusion.shelf.model.PendingInboundRequest
|
import com.sw.scalefusion.shelf.model.PendingInboundRequest
|
||||||
import com.sw.scalefusion.shelf.model.PutSlotRequest
|
import com.sw.scalefusion.shelf.model.PutSlotRequest
|
||||||
|
import com.sw.scalefusion.shelf.model.SearchFoodRequest
|
||||||
import com.sw.scalefusion.shelf.model.SlotDetailRequest
|
import com.sw.scalefusion.shelf.model.SlotDetailRequest
|
||||||
import com.sw.scalefusion.shelf.model.SlotModel
|
import com.sw.scalefusion.shelf.model.SlotModel
|
||||||
import com.sw.scalefusion.shelf.model.SlotRecord
|
import com.sw.scalefusion.shelf.model.SlotRecord
|
||||||
@@ -20,6 +22,9 @@ class ShelfRepository : BaseRepository() {
|
|||||||
suspend fun pendingInbound(request: PendingInboundRequest): ApiResponse<List<PendingInboundItem>?> =
|
suspend fun pendingInbound(request: PendingInboundRequest): ApiResponse<List<PendingInboundItem>?> =
|
||||||
safeApiCall { apiServiceV3.pendingInbound(request) }
|
safeApiCall { apiServiceV3.pendingInbound(request) }
|
||||||
|
|
||||||
|
/** 搜索净菜、毛菜 */
|
||||||
|
suspend fun searchFood(request: SearchFoodRequest): ApiResponse<List<FoodItem>?> =
|
||||||
|
safeApiCall { apiServiceV3.searchFood(request) }
|
||||||
/** 全量同步重量 */
|
/** 全量同步重量 */
|
||||||
suspend fun syncWeight(request: SyncWeightRequest): ApiResponse<Any?> =
|
suspend fun syncWeight(request: SyncWeightRequest): ApiResponse<Any?> =
|
||||||
safeApiCall { apiServiceV3.syncWeight(request) }
|
safeApiCall { apiServiceV3.syncWeight(request) }
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:color="@color/bg_card_blue" android:state_checked="true" />
|
||||||
|
<item android:color="@color/white" android:state_checked="false" />
|
||||||
|
</selector>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:color="@color/bg_card_blue" android:state_checked="false" />
|
||||||
|
<item android:color="@android:color/transparent" android:state_checked="true" />
|
||||||
|
</selector>
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:color="@color/white" android:state_checked="true" />
|
||||||
|
<item android:color="@color/bg_card_blue" android:state_checked="false" />
|
||||||
|
</selector>
|
||||||
@@ -74,6 +74,16 @@
|
|||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
tools:text="金针菇" />
|
tools:text="金针菇" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvFoodType"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:textColor="@color/food_name_black"
|
||||||
|
android:textSize="22sp"
|
||||||
|
tools:text="金针菇" />
|
||||||
|
|
||||||
<Space
|
<Space
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
@@ -139,7 +149,7 @@
|
|||||||
android:background="@drawable/shape_search"
|
android:background="@drawable/shape_search"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:visibility="gone">
|
android:visibility="visible">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="32dp"
|
android:layout_width="32dp"
|
||||||
|
|||||||
@@ -0,0 +1,79 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:cardBackgroundColor="@color/white"
|
||||||
|
app:cardCornerRadius="12dp"
|
||||||
|
app:cardElevation="0dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="600dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- 标题 -->
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvDialogTitle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:layout_marginTop="40dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:textColor="#ff141428"
|
||||||
|
android:textSize="32sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<!-- ChipGroup 选择区域 -->
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/chipGroup"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="30dp"
|
||||||
|
android:layout_marginVertical="40dp"
|
||||||
|
app:selectionRequired="false"
|
||||||
|
app:singleSelection="true" />
|
||||||
|
|
||||||
|
<!-- 分割线 -->
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="#FFDCDCF0" />
|
||||||
|
|
||||||
|
<!-- 底部按钮 -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="72dp"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnCancel"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@color/white"
|
||||||
|
android:text="取消"
|
||||||
|
android:textColor="@android:color/darker_gray"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="1dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="#FFDCDCF0" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnConfirm"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@color/white"
|
||||||
|
android:text="确定"
|
||||||
|
android:textColor="@color/bg_card_blue"
|
||||||
|
android:textSize="24sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.cardview.widget.CardView>
|
||||||
Reference in New Issue
Block a user