diff --git a/app/src/main/java/com/shuwei/intelligent/shelves/dialog/ChipSelectDialog.kt b/app/src/main/java/com/shuwei/intelligent/shelves/dialog/ChipSelectDialog.kt new file mode 100644 index 0000000..9d2c366 --- /dev/null +++ b/app/src/main/java/com/shuwei/intelligent/shelves/dialog/ChipSelectDialog.kt @@ -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 = 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) + } + } +} diff --git a/app/src/main/java/com/sw/scalefusion/shelf/HomeV3Activity.kt b/app/src/main/java/com/sw/scalefusion/shelf/HomeV3Activity.kt index d8c9157..fc0f1b8 100644 --- a/app/src/main/java/com/sw/scalefusion/shelf/HomeV3Activity.kt +++ b/app/src/main/java/com/sw/scalefusion/shelf/HomeV3Activity.kt @@ -151,8 +151,10 @@ class HomeV3Activity : BaseActivity() { // val columns = if (ProtocolConstants.device3Columns.contains(App.deviceId)) 3 else 2 // val rows = if (slots.size % columns == 0) slots.size / columns else 5 - val columns = record.verticalCount - val rows = record.horizontalRows +// val columns = record.verticalCount +// val rows = record.horizontalRows + val rows = record.verticalCount + val columns = record.horizontalRows log("updateUI: slots=${slots.size}, rows=$rows, columns=$columns") list.clear() @@ -328,7 +330,7 @@ class HomeV3Activity : BaseActivity() { private fun saveGoodsTask() { saveTaskJob = - taskExecutor.startIntervalTaskWithInitialDelay(10 * 1000L, 2 * 60 * 1000L) { + taskExecutor.startIntervalTaskWithInitialDelay(10 * 1000L, 1 * 60 * 1000L) { syncShelfGoodsToServer() } } diff --git a/app/src/main/java/com/sw/scalefusion/shelf/InitActivity.kt b/app/src/main/java/com/sw/scalefusion/shelf/InitActivity.kt index de6260a..d5efabc 100644 --- a/app/src/main/java/com/sw/scalefusion/shelf/InitActivity.kt +++ b/app/src/main/java/com/sw/scalefusion/shelf/InitActivity.kt @@ -39,6 +39,7 @@ class InitActivity : BaseActivity() { App.deviceId = AppUtil.getUDID(this) // TODO: 测试设备号 // App.deviceId = "d369f9b0-1c5b-3066-ba72-988e1449cecc" +// App.deviceId = "25b777a9-6298-30d3-a5f8-3b3eef2a50f7" // App.deviceId = "505ce1b1-facc-3eb2-855a-3dadda5ba358" Log.d(TAG, "onCreate: deviceId = ${App.deviceId}") SpTool.put(SpTool.DEVICE_ID, App.deviceId) @@ -48,7 +49,7 @@ class InitActivity : BaseActivity() { // } else { // GlobalData.appBaseUrl = GlobalData.PROD_BASE_URL // } - GlobalData.appBaseUrl = GlobalData.LOCAL_BASE_URL + GlobalData.appBaseUrl = GlobalData.TEST_BASE_URL App.canteenId = "0" binding.ivQrCode.invisible() diff --git a/app/src/main/java/com/sw/scalefusion/shelf/ShelfV3Activity.kt b/app/src/main/java/com/sw/scalefusion/shelf/ShelfV3Activity.kt index 4505848..aed75ce 100644 --- a/app/src/main/java/com/sw/scalefusion/shelf/ShelfV3Activity.kt +++ b/app/src/main/java/com/sw/scalefusion/shelf/ShelfV3Activity.kt @@ -14,6 +14,8 @@ import com.scwang.smart.refresh.layout.constant.RefreshState import com.shuwei.intelligent.shelves.R import com.shuwei.intelligent.shelves.base.BaseActivity 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.net.Loading 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.visible 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.PendingInboundRequest 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.SlotModel import com.sw.scalefusion.shelf.net.NetViewModelV3 @@ -59,18 +63,43 @@ class ShelfV3Activity : BaseActivity() { private val viewModel: NetViewModelV3 by viewModels() - private val optionList: MutableList = mutableListOf() + private val optionList: MutableList = mutableListOf() private val optionAdapter by lazy { PendingInboundAdapter(optionList).apply { setOnDebouncedItemClick { _, _, position -> - optionList.forEachIndexed { index, option -> option.isSelected = index == position } - notifyDataSetChanged() - binding.tvFoodName.text = optionList[position].materName - KeyboardUtil.hideKeyboard(this@ShelfV3Activity.window.decorView) + 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 } + optionAdapter.notifyDataSetChanged() + 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) + } + private var cabinetType: Int = 0 private var canteenId: Long = 0 private var cabinetId: String = "" @@ -113,6 +142,7 @@ class ShelfV3Activity : BaseActivity() { /** 从 slotDetail 响应更新 UI */ private fun updateUI(model: SlotModel) { binding.tvFoodName.text = if (model.materName.isNullOrBlank()) "-" else model.materName + binding.tvFoodType.text = "" val weightG = model.weight ?: 0.0 realWeight = (weightG * 1000.0).toInt() binding.tvFoodWeight.text = if (weightG >= 1.0) "%.3f千克".format(weightG) @@ -155,7 +185,7 @@ class ShelfV3Activity : BaseActivity() { binding.btnClearEmpty.setOnClickListener { v -> clearZero() binding.tvFoodName.text = "-" - + binding.tvFoodType.text = "" Loading.show(this@ShelfV3Activity) v.postDelayed({ Loading.dismiss() @@ -186,11 +216,12 @@ class ShelfV3Activity : BaseActivity() { cabinetType = cabinetType, cabinetId = cabinetId, slotNo = slotNo, - materId = item.materId , + materId = item.materId, materName = item.materName, - traceCode = item.traceCode, weight = shelfModel?.weight ?: 0.0 - ), + ).also { + it.vegTypeId = item.vegTypeList?.getOrNull(item.typeSelectedIndex)?.vegTypeId + }, onLoading = { showProgress() }, onSuccess = onSuccess@{ inboundNo -> Loading.dismiss() @@ -213,11 +244,10 @@ class ShelfV3Activity : BaseActivity() { } private fun loadList() { - viewModel.pendingInbound( - request = PendingInboundRequest( + viewModel.searchFood( + request = SearchFoodRequest( cabinetType = shelfModel?.cabinetType ?: 0, - cabinetId = shelfModel?.cabinetId ?: "", - canteenId = canteenId + keyword = binding.etInputFood.text.toString().trim() ), onLoading = { showProgress() }, onSuccess = { items -> updateOptionList(items) }, @@ -230,9 +260,9 @@ class ShelfV3Activity : BaseActivity() { } @SuppressLint("NotifyDataSetChanged") - private fun updateOptionList(items: List?) { + private fun updateOptionList(items: List?) { finishRefresh() - binding.include?.root?.gone() + binding.include.root.gone() binding.root.postDelayed({ Loading.dismiss() }, 200) if (items.isNullOrEmpty()) { loadEmptyView(); return @@ -317,4 +347,14 @@ class ShelfV3Activity : BaseActivity() { startTime = System.currentTimeMillis() window.decorView.postDelayed({ Loading.dismiss() }, 1000) } + + private fun showChipSelectDialog(categoryList: List, callback: (Int) -> Unit) { + ChipSelectDialog(this).apply { + dialogTitle = "请选择净菜分类" + items = categoryList + onItemSelected = callback + show() + } + } + } diff --git a/app/src/main/java/com/sw/scalefusion/shelf/adapter/PendingInboundAdapter.kt b/app/src/main/java/com/sw/scalefusion/shelf/adapter/PendingInboundAdapter.kt index ba993e3..4af546e 100644 --- a/app/src/main/java/com/sw/scalefusion/shelf/adapter/PendingInboundAdapter.kt +++ b/app/src/main/java/com/sw/scalefusion/shelf/adapter/PendingInboundAdapter.kt @@ -11,10 +11,10 @@ import com.chad.library.adapter4.BaseQuickAdapter import com.chad.library.adapter4.viewholder.QuickViewHolder import com.shuwei.intelligent.shelves.R 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) : - BaseQuickAdapter(list) { +class PendingInboundAdapter(list: MutableList) : + BaseQuickAdapter(list) { inner class VH(val binding: ListItemSearchBinding) : QuickViewHolder(binding.root) @@ -23,7 +23,7 @@ class PendingInboundAdapter(list: MutableList) : return VH(binding) } - override fun onBindViewHolder(holder: VH, position: Int, item: PendingInboundItem?) { + override fun onBindViewHolder(holder: VH, position: Int, item: FoodItem?) { item ?: return val isSelected = item.isSelected holder.binding.btnFoodName.run { diff --git a/app/src/main/java/com/sw/scalefusion/shelf/model/CommonRequest.kt b/app/src/main/java/com/sw/scalefusion/shelf/model/CommonRequest.kt index 00fc421..95254be 100644 --- a/app/src/main/java/com/sw/scalefusion/shelf/model/CommonRequest.kt +++ b/app/src/main/java/com/sw/scalefusion/shelf/model/CommonRequest.kt @@ -6,14 +6,20 @@ data class PendingInboundRequest( var cabinetId: String ) +data class SearchFoodRequest( + var cabinetType: Int, + var keyword: String? = null +) + data class PutSlotRequest( - val cabinetType: Int, - val cabinetId: String, - val slotNo: String, - val materId: Long, - val materName: String, + val cabinetType: Int? = null, + val cabinetId: String? = null, + val slotNo: String? = null, + val materId: Long? = null, + var vegTypeId: Long? = null, + val materName: String? = null, val traceCode: String? = null, - val weight: Double + val weight: Double? = null, ) data class SlotDetailRequest( diff --git a/app/src/main/java/com/sw/scalefusion/shelf/model/FoodItem.kt b/app/src/main/java/com/sw/scalefusion/shelf/model/FoodItem.kt new file mode 100644 index 0000000..b51a0a1 --- /dev/null +++ b/app/src/main/java/com/sw/scalefusion/shelf/model/FoodItem.kt @@ -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? = 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 +) \ No newline at end of file diff --git a/app/src/main/java/com/sw/scalefusion/shelf/net/ApiServiceV3.kt b/app/src/main/java/com/sw/scalefusion/shelf/net/ApiServiceV3.kt index 65aa6f8..6fade20 100644 --- a/app/src/main/java/com/sw/scalefusion/shelf/net/ApiServiceV3.kt +++ b/app/src/main/java/com/sw/scalefusion/shelf/net/ApiServiceV3.kt @@ -1,9 +1,11 @@ package com.sw.scalefusion.shelf.net 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.PendingInboundRequest 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.SlotModel import com.sw.scalefusion.shelf.model.SlotRecord @@ -23,6 +25,10 @@ interface ApiServiceV3 { @POST("/nutrition/neglect/mater-cabinet/pending-inbound") suspend fun pendingInbound(@Body request: PendingInboundRequest): ApiResponse?> + /** 搜索净菜、毛菜 */ + @POST("/nutrition/neglect/mater-cabinet/ingredients") + suspend fun searchFood(@Body request: SearchFoodRequest): ApiResponse?> + /** 全量同步重量 */ @POST("/nutrition/neglect/mater-cabinet/sync-weight") suspend fun syncWeight(@Body request: SyncWeightRequest): ApiResponse diff --git a/app/src/main/java/com/sw/scalefusion/shelf/net/NetViewModelV3.kt b/app/src/main/java/com/sw/scalefusion/shelf/net/NetViewModelV3.kt index b5387d3..265fc5f 100644 --- a/app/src/main/java/com/sw/scalefusion/shelf/net/NetViewModelV3.kt +++ b/app/src/main/java/com/sw/scalefusion/shelf/net/NetViewModelV3.kt @@ -2,9 +2,11 @@ package com.sw.scalefusion.shelf.net import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.sw.scalefusion.shelf.model.FoodItem import com.sw.scalefusion.shelf.model.PendingInboundItem import com.sw.scalefusion.shelf.model.PendingInboundRequest 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.SlotModel import com.sw.scalefusion.shelf.model.SlotRecord @@ -44,6 +46,16 @@ class NetViewModelV3 : ViewModel() { } } + /** 搜索净菜、毛菜 */ + fun searchFood(request: SearchFoodRequest, onLoading: () -> Unit = {}, onSuccess: (List?) -> Unit, onError: (String) -> Unit = {}) { + viewModelScope.launch { + onLoading() + val response = repository.searchFood(request) + if (response.isSuccess()) onSuccess(response.data) + else onError(response.msg ?: "请求失败") + } + } + /** 格口详情 */ fun slotDetail( request: SlotDetailRequest, diff --git a/app/src/main/java/com/sw/scalefusion/shelf/net/ShelfRepository.kt b/app/src/main/java/com/sw/scalefusion/shelf/net/ShelfRepository.kt index 6f9d420..bf6a44d 100644 --- a/app/src/main/java/com/sw/scalefusion/shelf/net/ShelfRepository.kt +++ b/app/src/main/java/com/sw/scalefusion/shelf/net/ShelfRepository.kt @@ -2,9 +2,11 @@ package com.sw.scalefusion.shelf.net import com.shuwei.intelligent.shelves.App 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.PendingInboundRequest 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.SlotModel import com.sw.scalefusion.shelf.model.SlotRecord @@ -20,6 +22,9 @@ class ShelfRepository : BaseRepository() { suspend fun pendingInbound(request: PendingInboundRequest): ApiResponse?> = safeApiCall { apiServiceV3.pendingInbound(request) } + /** 搜索净菜、毛菜 */ + suspend fun searchFood(request: SearchFoodRequest): ApiResponse?> = + safeApiCall { apiServiceV3.searchFood(request) } /** 全量同步重量 */ suspend fun syncWeight(request: SyncWeightRequest): ApiResponse = safeApiCall { apiServiceV3.syncWeight(request) } diff --git a/app/src/main/res/color/chip_bg_color.xml b/app/src/main/res/color/chip_bg_color.xml new file mode 100644 index 0000000..b384240 --- /dev/null +++ b/app/src/main/res/color/chip_bg_color.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/color/chip_stroke_color.xml b/app/src/main/res/color/chip_stroke_color.xml new file mode 100644 index 0000000..fa9467f --- /dev/null +++ b/app/src/main/res/color/chip_stroke_color.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/color/chip_text_color.xml b/app/src/main/res/color/chip_text_color.xml new file mode 100644 index 0000000..4516fb5 --- /dev/null +++ b/app/src/main/res/color/chip_text_color.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/app/src/main/res/layout/activity_shelf_v3.xml b/app/src/main/res/layout/activity_shelf_v3.xml index 44997d9..b604eb1 100644 --- a/app/src/main/res/layout/activity_shelf_v3.xml +++ b/app/src/main/res/layout/activity_shelf_v3.xml @@ -74,6 +74,16 @@ android:textStyle="bold" tools:text="金针菇" /> + + + android:visibility="visible"> + + + + + + + + + + + + + + + + + + + + + + + + + + +