调整了部分问题

This commit is contained in:
zxj
2025-07-23 14:22:11 +08:00
parent 5ad82eb224
commit 7fd2ccb960
28 changed files with 486 additions and 210 deletions
@@ -8,9 +8,13 @@ import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.viewbinding.ViewBinding
import com.sw.platecabinet.R
import com.sw.platecabinet.view.CustomDialog
import com.sw.platecabinet.viewmodel.SettingViewModel
import kotlinx.coroutines.launch
abstract class BaseFragment<VB : ViewBinding>(
private val bindingInflater: (inflater: LayoutInflater, parent: ViewGroup?, attachToParent: Boolean) -> VB
@@ -18,6 +22,7 @@ abstract class BaseFragment<VB : ViewBinding>(
private var _binding: VB? = null
protected val binding get() = _binding!!
private var mDialogWaiting: CustomDialog? = null
protected val viewModel by viewModels<SettingViewModel>()
override fun onCreateView(
inflater: LayoutInflater,
@@ -33,7 +38,17 @@ abstract class BaseFragment<VB : ViewBinding>(
/**
* 注册数据变化监听
*/
open fun registerDataChange() {}
open fun registerDataChange() {
lifecycleScope.launch {
viewModel.showLoading.collect {
if (it) {
showWaitingDialog("")
} else {
hideWaitingDialog()
}
}
}
}
abstract fun initialize()
@@ -4,14 +4,15 @@ import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.text.Editable
import android.text.TextUtils
import android.text.TextWatcher
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.sw.plate.utils.ToastUtils
import com.sw.platecabinet.R
import com.sw.platecabinet.activity.MainActivity
import com.sw.platecabinet.adapter.GenericItemAdapter
import com.sw.platecabinet.adapter.GridSpacingItemDecoration
import com.sw.platecabinet.adapter.dpToPx
@@ -21,7 +22,7 @@ import com.sw.platecabinet.ext.maskName
import com.sw.platecabinet.ext.maskPhone
import com.sw.platecabinet.model.response.EquipmentUserInfo
import com.sw.platecabinet.model.response.SearchResult
import com.sw.platecabinet.viewmodel.SettingViewModel
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.launch
import timber.log.Timber
@@ -32,7 +33,6 @@ class BindPlateFragment : BaseFragment<FragmentBindPlateBinding>(
FragmentBindPlateBinding::inflate
) {
private lateinit var adapter: GenericItemAdapter<SearchResult.Member, ItemSearchUserInfoBinding>
private val viewModel by viewModels<SettingViewModel>()
internal val ARG_PARAM1 = "param1"
private var info: EquipmentUserInfo? = null
private var checkedItem: SearchResult.Member? = null
@@ -53,6 +53,9 @@ class BindPlateFragment : BaseFragment<FragmentBindPlateBinding>(
info = it.getParcelable(ARG_PARAM1)
info?.let {
binding.tvNum.text = "${it.equipmentName}-${it.equipmentBoxCode}"
if (!TextUtils.isEmpty(it.plateNumber)) {
binding.etCode.text = Editable.Factory.getInstance().newEditable(it.plateNumber)
}
}
}
initView()
@@ -88,6 +91,12 @@ class BindPlateFragment : BaseFragment<FragmentBindPlateBinding>(
}
}
})
(activity as MainActivity).registerKeyEventInfo {
binding.etCode.text = Editable.Factory.getInstance().newEditable(it)
}
}
private fun initListener() {
binding.etUserInfo.addTextChangedListener(object : TextWatcher {
private val handler = Handler(Looper.getMainLooper())
private val debounceDelay = 500L // 延迟 500 毫秒
@@ -120,9 +129,6 @@ class BindPlateFragment : BaseFragment<FragmentBindPlateBinding>(
}, debounceDelay)
}
})
}
private fun initListener() {
binding.llBind.setOnClickListener {
if (info == null || info!!.equipmentCode?.isEmpty() == true || info!!.equipmentBoxCode?.isEmpty() == true) {
ToastUtils.showToast("传入的设备信息异常")
@@ -156,13 +162,14 @@ class BindPlateFragment : BaseFragment<FragmentBindPlateBinding>(
* 监听数据变化
*/
override fun registerDataChange() {
super.registerDataChange()
lifecycleScope.launch {
viewModel.searchMemberList.collect {
viewModel.searchMemberList.drop(1).collect {
adapter.updateData(it)
}
}
lifecycleScope.launch {
viewModel.bindStateChange.collect {
viewModel.bindStateChange.drop(1).collect {
if (it.first == null) return@collect // 解绑状态过滤
val errorInfo = it.second
if (errorInfo.isSuccess()) {
@@ -173,15 +180,6 @@ class BindPlateFragment : BaseFragment<FragmentBindPlateBinding>(
}
}
}
lifecycleScope.launch {
viewModel.showLoading.collect {
if (it) {
showWaitingDialog("")
} else {
hideWaitingDialog()
}
}
}
}
private fun createAdapter(): GenericItemAdapter<SearchResult.Member, ItemSearchUserInfoBinding> {
@@ -1,24 +1,28 @@
package com.sw.platecabinet.fragment
import android.view.View
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.sw.inbound.utils.DateTimeUtils
import com.sw.plate.utils.ToastUtils
import com.sw.plate.utils.comn.SerialApi
import com.sw.plate.utils.comn.SerialPortManager
import com.sw.platecabinet.GlobalData
import com.sw.platecabinet.R
import com.sw.platecabinet.activity.MainActivity
import com.sw.platecabinet.activity.PageType
import com.sw.platecabinet.adapter.GenericItemAdapter
import com.sw.platecabinet.adapter.GenericPageAdapter
import com.sw.platecabinet.adapter.GridSpacingItemDecoration
import com.sw.platecabinet.adapter.dpToPx
import com.sw.platecabinet.databinding.FragmentSettingListBinding
import com.sw.platecabinet.databinding.ItemBindViewBinding
import com.sw.platecabinet.ext.formatNumber
import com.sw.platecabinet.ext.maskName
import com.sw.platecabinet.model.response.EquipmentUserInfo
import com.sw.platecabinet.viewmodel.SettingViewModel
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.launch
import timber.log.Timber
import kotlin.math.ceil
@@ -28,35 +32,47 @@ import kotlin.math.ceil
*/
class SettingListFragment :
BaseFragment<FragmentSettingListBinding>(FragmentSettingListBinding::inflate) {
private val viewModel: SettingViewModel by viewModels<SettingViewModel>()
private lateinit var pageAdapter: GenericPageAdapter<EquipmentUserInfo, ItemBindViewBinding>
private lateinit var itemAdapter: GenericItemAdapter<EquipmentUserInfo, ItemBindViewBinding>
private val itemsPerPage = 22 // 每行2个,每列11个,共22个
/**
* 需要横向滚动的adapter
*/
private var pageAdapter: GenericPageAdapter<EquipmentUserInfo, ItemBindViewBinding>? = null
/**
* 垂直滚动的adapter
*/
private var itemAdapter: GenericItemAdapter<EquipmentUserInfo, ItemBindViewBinding>? = null
private val itemsPerPage = GlobalData.arrayCross * GlobalData.arrayVertical // 每行2个,每列11个,共22个
override fun registerDataChange() {
super.registerDataChange()
lifecycleScope.launch {
viewModel.equipmentList.collect { it ->
viewModel.equipmentList.drop(1).collect { it ->
Timber.d("registerDateChange updateAdapter it = $it")
updateAdapter(it)
}
}
lifecycleScope.launch {
viewModel.showLoading.collect {
if (it) {
showWaitingDialog("")
} else {
hideWaitingDialog()
}
}
}
}
override fun initialize() {
binding.mainRecyclerView.apply {
layoutManager = LinearLayoutManager(context)
pageAdapter = createAdapter()
adapter = pageAdapter
if (GlobalData.arrayCross > 2) {
layoutManager = LinearLayoutManager(context, RecyclerView.HORIZONTAL, false)
pageAdapter = createPageAdapter()
adapter = pageAdapter
} else {
layoutManager = GridLayoutManager(context, 2)
// 添加间距装饰(12dp)
addItemDecoration(
GridSpacingItemDecoration(
spanCount = 2,
spacing = requireContext().dpToPx(12),
includeEdge = true // 包含边缘间距
)
)
itemAdapter = createItemAdapter()
adapter = itemAdapter
}
}
}
@@ -66,94 +82,115 @@ class SettingListFragment :
viewModel.getEquipmentList()
}
private fun createAdapter(): GenericPageAdapter<EquipmentUserInfo, ItemBindViewBinding> {
private fun createItemAdapter(): GenericItemAdapter<EquipmentUserInfo, ItemBindViewBinding> {
return GenericItemAdapter(
items = emptyList(),
bindingInflater = ItemBindViewBinding::inflate,
bindCallback = { item, position ->
setItemInfo(item, position)
}
)
}
private fun createPageAdapter(): GenericPageAdapter<EquipmentUserInfo, ItemBindViewBinding> {
return GenericPageAdapter(
pages = emptyList(),
pageLayoutId = R.layout.page_item_layout,
itemBindingInflater = ItemBindViewBinding::inflate,
itemBindCallback = { item, position ->
this.tvNum.text = formatNumber(item.equipmentBoxCode ?: "")
if (item.isBound()) {
val date = DateTimeUtils.parseDateTime(item.updateTime)
val timeInMillis = date?.time ?: 0L
val isOldTime = DateTimeUtils.isMoreThan36HoursFromNow(timeInMillis)
this.llRoot.setBackgroundResource(R.drawable.grid_item_bind)
this.tvNum.setTextColor(resources.getColor(R.color.bind_4E535D))
this.tvLastTime.setTextColor(
if (isOldTime) resources.getColor(R.color.bind_time_old) else resources.getColor(
R.color.bind_585868
)
)
this.llOpen.setBackgroundResource(R.drawable.grid_button_bind)
this.tvOpen.setTextColor(resources.getColor(R.color.bind_F0C8B4))
this.llBindInfo.visibility = View.VISIBLE
this.tvUnbind.visibility = View.GONE
this.tvName.text = item.name.maskName()
this.tvLastTime.text = DateTimeUtils.getTimeAgo(date)
} else {
this.llRoot.setBackgroundResource(R.drawable.grid_item_unbind)
this.tvNum.setTextColor(resources.getColor(R.color.bind_F0C8B4))
this.llOpen.setBackgroundResource(R.drawable.grid_button_unbind)
this.tvOpen.setTextColor(resources.getColor(R.color.unbind_32283C))
this.llBindInfo.visibility = View.GONE
this.tvUnbind.visibility = View.VISIBLE
}
this.llRoot.setOnClickListener {
Timber.d("itemClick llRoot ${item.name}, position = $position")
if (item.isBound()) {
MainActivity.start(
requireContext(),
pageType = PageType.UNBIND_PLATE,
equipmentUserInfo = item
)
} else {
MainActivity.start(
requireContext(),
pageType = PageType.BIND_PLATE,
equipmentUserInfo = item
)
}
}
this.llOpen.setOnClickListener {
Timber.d("itemClick llOpen equipmentBoxCode = ${item.equipmentBoxCode}")
val equipmentBoxCode: Int = item.equipmentBoxCode?.toInt() ?: -1
if (equipmentBoxCode < 0) {
ToastUtils.showToast("餐盘柜编号错误")
return@setOnClickListener
}
SerialApi.openPlate(equipmentBoxCode, object : SerialPortManager.SendCallback {
override fun onSuccess() {
MainActivity.start(requireContext(), pageType = PageType.PLATE_OPEN)
}
override fun onFail(e: Exception?) {
ToastUtils.showToast("柜门打开失败")
}
})
}
setItemInfo(item, position)
}
)
}
fun updateAdapter(items: List<EquipmentUserInfo>) {
// if (GlobalData.arrayCross > 2) {
var pages = if (items.size > itemsPerPage) {
items.chunked(itemsPerPage) {
convertToColumnFirst(it, 11)
}
} else {
listOf(
// 根据条件判断是否需要重新排列
// items
convertToColumnFirst(items, 11)
private fun ItemBindViewBinding.setItemInfo(
item: EquipmentUserInfo,
position: Int
) {
this.tvNum.text = formatNumber(item.equipmentBoxCode ?: "")
if (item.isBound()) {
val date = DateTimeUtils.parseDateTime(item.updateTime)
val timeInMillis = date?.time ?: 0L
val isOldTime = DateTimeUtils.isMoreThan36HoursFromNow(timeInMillis)
this.llRoot.setBackgroundResource(R.drawable.grid_item_bind)
this.tvNum.setTextColor(resources.getColor(R.color.bind_4E535D))
this.tvLastTime.setTextColor(
if (isOldTime) resources.getColor(R.color.bind_time_old) else resources.getColor(
R.color.bind_585868
)
)
this.llOpen.setBackgroundResource(R.drawable.grid_button_bind)
this.tvOpen.setTextColor(resources.getColor(R.color.bind_F0C8B4))
this.llBindInfo.visibility = View.VISIBLE
this.tvUnbind.visibility = View.GONE
this.tvName.text = item.name.maskName()
this.tvLastTime.text = DateTimeUtils.getTimeAgo(date)
} else {
this.llRoot.setBackgroundResource(R.drawable.grid_item_unbind)
this.tvNum.setTextColor(resources.getColor(R.color.bind_F0C8B4))
this.llOpen.setBackgroundResource(R.drawable.grid_button_unbind)
this.tvOpen.setTextColor(resources.getColor(R.color.unbind_32283C))
this.llBindInfo.visibility = View.GONE
this.tvUnbind.visibility = View.VISIBLE
}
pageAdapter.updatePages(pages)
// }else{
//
// }
this.llRoot.setOnClickListener {
Timber.d("itemClick llRoot ${item.name}, position = $position")
if (item.isBound()) {
MainActivity.start(
requireContext(),
pageType = PageType.UNBIND_PLATE,
equipmentUserInfo = item
)
} else {
MainActivity.start(
requireContext(),
pageType = PageType.BIND_PLATE,
equipmentUserInfo = item
)
}
}
this.llOpen.setOnClickListener {
Timber.d("itemClick llOpen equipmentBoxCode = ${item.equipmentBoxCode}")
val equipmentBoxCode: Int = item.equipmentBoxCode?.toInt() ?: -1
if (equipmentBoxCode < 0) {
ToastUtils.showToast("餐盘柜编号错误")
return@setOnClickListener
}
showWaitingDialog("请稍等")
SerialApi.openPlate(equipmentBoxCode, object : SerialPortManager.SendCallback {
override fun onSuccess() {
hideWaitingDialog()
MainActivity.start(requireContext(), pageType = PageType.PLATE_OPEN)
}
override fun onFail(e: Exception?) {
hideWaitingDialog()
ToastUtils.showToast("柜门打开失败")
}
})
}
}
fun updateAdapter(items: List<EquipmentUserInfo>) {
if (GlobalData.arrayCross > 2) {
var pages = if (items.size > itemsPerPage) {
items.chunked(itemsPerPage) {
convertToColumnFirst(it, 11)
}
} else {
listOf(
// 根据条件判断是否需要重新排列
// items
convertToColumnFirst(items, 11)
)
}
pageAdapter?.updatePages(pages)
} else {
itemAdapter?.updateData(items)
}
binding.mainRecyclerView.scrollToPosition(0)
}
/**
@@ -1,7 +1,6 @@
package com.sw.platecabinet.fragment
import android.os.Bundle
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import com.sw.inbound.utils.DateTimeUtils
import com.sw.plate.utils.ToastUtils
@@ -9,7 +8,7 @@ import com.sw.platecabinet.databinding.FragmentUnbindPlateBinding
import com.sw.platecabinet.ext.maskName
import com.sw.platecabinet.ext.maskPhone
import com.sw.platecabinet.model.response.EquipmentUserInfo
import com.sw.platecabinet.viewmodel.SettingViewModel
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.launch
/**
@@ -20,7 +19,6 @@ class UnBindPlateFragment private constructor() : BaseFragment<FragmentUnbindPla
) {
internal val ARG_PARAM1 = "param1"
private var info: EquipmentUserInfo? = null
private val viewModel by viewModels<SettingViewModel>()
companion object {
@JvmStatic
@@ -58,8 +56,9 @@ class UnBindPlateFragment private constructor() : BaseFragment<FragmentUnbindPla
}
override fun registerDataChange() {
super.registerDataChange()
lifecycleScope.launch {
viewModel.bindStateChange.collect {
viewModel.bindStateChange.drop(1).collect {
if (it.first == null) return@collect // 绑定状态过滤
val errorInfo = it.second
if (errorInfo.isSuccess()) {
@@ -70,14 +69,5 @@ class UnBindPlateFragment private constructor() : BaseFragment<FragmentUnbindPla
}
}
}
lifecycleScope.launch {
viewModel.showLoading.collect {
if (it) {
showWaitingDialog("")
} else {
hideWaitingDialog()
}
}
}
}
}