添加了界面及逻辑

This commit is contained in:
zxj
2025-07-18 17:16:00 +08:00
parent b68c967d82
commit f97ef151c3
74 changed files with 3108 additions and 34 deletions
@@ -0,0 +1,41 @@
package com.sw.platecabinet.fragment
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
import androidx.viewbinding.ViewBinding
abstract class BaseFragment<VB : ViewBinding>(
private val bindingInflater: (inflater: LayoutInflater, parent: ViewGroup?, attachToParent: Boolean) -> VB
) : Fragment() {
private var _binding: VB? = null
protected val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = bindingInflater(inflater, container, false)
initialize()
return binding.root
}
abstract fun initialize()
class ViewModelFactory<T : ViewModel>(private val creator: () -> T) :
ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return creator() as T
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
@@ -0,0 +1,65 @@
package com.sw.platecabinet.fragment
import android.os.Bundle
import com.sw.platecabinet.R
import com.sw.platecabinet.adapter.GenericChildAdapter
import com.sw.platecabinet.databinding.FragmentBindPlateBinding
import com.sw.platecabinet.databinding.ItemSearchUserInfoBinding
import com.sw.platecabinet.model.response.EquipmentUserInfo
import timber.log.Timber
/**
* 餐盘柜绑定
*/
class BindPlateFragment : BaseFragment<FragmentBindPlateBinding>(
FragmentBindPlateBinding::inflate
) {
private lateinit var adapter: GenericChildAdapter<EquipmentUserInfo, ItemSearchUserInfoBinding>
internal val ARG_PARAM1 = "param1"
private var info: EquipmentUserInfo? = null
companion object {
@JvmStatic
fun newInstance(param1: EquipmentUserInfo?) =
BindPlateFragment().apply {
arguments = Bundle().apply {
putParcelable(ARG_PARAM1, param1)
}
}
}
override fun initialize() {
arguments?.let {
info = it.getParcelable(ARG_PARAM1)
info?.let { binding.tvNum.text = "${it.equipmentName}-${it.equipmentBoxCode}" }
}
adapter = createAdapter()
registerDateChange()
binding.tvBack.setOnClickListener { activity?.finish() }
}
private fun registerDateChange() {
}
private fun createAdapter(): GenericChildAdapter<EquipmentUserInfo, ItemSearchUserInfoBinding> {
return GenericChildAdapter(
items = emptyList(),
bindingInflater = ItemSearchUserInfoBinding::inflate,
bindCallback = { item, position ->
this.tvName.text = item.name
this.tvPhone.text = item.phone
if (item.isBound()) {
this.llRoot.setBackgroundResource(R.drawable.grid_item_bind)
} else {
this.llRoot.setBackgroundResource(R.drawable.grid_item_unbind)
}
this.llRoot.setOnClickListener {
Timber.d("itemClick ${item.name}, position = $position")
}
}
)
}
}
@@ -0,0 +1,29 @@
package com.sw.platecabinet.fragment
import android.os.CountDownTimer
import com.sw.platecabinet.databinding.FragmentPlateCabinetFullBinding
/**
* 餐盘柜已满
*/
class PlateCabinetFullFragment :
BaseFragment<FragmentPlateCabinetFullBinding>(FragmentPlateCabinetFullBinding::inflate) {
private var totalTimeInMillis: Long = 5 * 1000
override fun initialize() {
initCountTime()
}
fun initCountTime() {
object : CountDownTimer(totalTimeInMillis, 1000) {
override fun onTick(millisUntilFinished: Long) {
binding.tvAutoClose.text = "${(millisUntilFinished / 1000).toInt()}秒后返回主屏"
}
override fun onFinish() {
activity?.finish()
}
}.start()
}
}
@@ -0,0 +1,28 @@
package com.sw.platecabinet.fragment
import android.os.CountDownTimer
import com.sw.platecabinet.databinding.FragmentPlateOpenBinding
/**
* 餐盘柜打开界面
*/
class PlateOpenFragment :
BaseFragment<FragmentPlateOpenBinding>(FragmentPlateOpenBinding::inflate) {
private var totalTimeInMillis: Long = 5 * 1000
override fun initialize() {
initCountTime()
}
fun initCountTime() {
object : CountDownTimer(totalTimeInMillis, 1000) {
override fun onTick(millisUntilFinished: Long) {
binding.tvAutoClose.text = (millisUntilFinished / 1000).toInt().toString()
}
override fun onFinish() {
activity?.finish()
}
}.start()
}
}
@@ -0,0 +1,135 @@
package com.sw.platecabinet.fragment
import android.view.View
import androidx.fragment.app.viewModels
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.sw.inbound.utils.DateTimeUtils
import com.sw.platecabinet.R
import com.sw.platecabinet.activity.MainActivity
import com.sw.platecabinet.activity.PageType
import com.sw.platecabinet.adapter.GenericPageAdapter
import com.sw.platecabinet.databinding.FragmentSettingListBinding
import com.sw.platecabinet.databinding.ItemBindViewBinding
import com.sw.platecabinet.ext.formatNumber
import com.sw.platecabinet.model.request.EquipmentParam
import com.sw.platecabinet.model.response.EquipmentUserInfo
import com.sw.platecabinet.viewmodel.SettingViewModel
import kotlinx.coroutines.launch
import timber.log.Timber
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 val itemsPerPage = 22 // 每行2个,每列11个,共22个
private fun registerDateChange() {
lifecycleScope.launch {
// 使用 repeatOnLifecycle 确保只在特定生命周期状态收集
// repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.equipmentList.collect { it ->
Timber.d("registerDateChange updateAdapter it = $it")
updateAdapter(it)
}
// }
}
}
override fun initialize() {
binding.mainRecyclerView.apply {
layoutManager = LinearLayoutManager(context)
pageAdapter = createAdapter()
adapter = pageAdapter
}
registerDateChange()
viewModel.getEquipmentList(EquipmentParam(equipmentCode = "202501171634"))
}
private fun createAdapter(): 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
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)
} else {
MainActivity.start(requireContext(), pageType = PageType.BIND_PLATE)
}
}
this.llOpen.setOnClickListener {
Timber.d("itemClick llOpen ${item.equipmentCode}")
MainActivity.start(requireContext(), pageType = PageType.PLATE_OPEN)
}
}
)
}
fun updateAdapter(items: List<EquipmentUserInfo>) {
val pages = if (items.size > itemsPerPage) {
items.chunked(itemsPerPage) {
convertToColumnFirst(it, 11)
}
} else {
listOf(
// 根据条件判断是否需要重新排列
// items
convertToColumnFirst(items, 11)
)
}
pageAdapter.updatePages(pages)
}
/**
* 重新排列数组
*/
private fun convertToColumnFirst(
original: List<EquipmentUserInfo>,
cols: Int
): List<EquipmentUserInfo> {
val rows = ceil(original.size.toDouble() / cols).toInt()
return List(original.size) { pos ->
val row = pos % rows
val col = pos / rows
val originalPos = col + row * cols
original[originalPos]
}
}
}
@@ -0,0 +1,42 @@
package com.sw.platecabinet.fragment
import android.os.Bundle
import com.sw.inbound.utils.DateTimeUtils
import com.sw.platecabinet.databinding.FragmentUnbindPlateBinding
import com.sw.platecabinet.model.response.EquipmentUserInfo
/**
* 餐盘柜绑定
*/
class UnBindPlateFragment private constructor() : BaseFragment<FragmentUnbindPlateBinding>(
FragmentUnbindPlateBinding::inflate
) {
internal val ARG_PARAM1 = "param1"
private var param1: EquipmentUserInfo? = null
private var info: EquipmentUserInfo? = null
companion object {
@JvmStatic
fun newInstance(param1: EquipmentUserInfo?) =
UnBindPlateFragment().apply {
arguments = Bundle().apply {
putParcelable(ARG_PARAM1, param1)
}
}
}
override fun initialize() {
arguments?.let {
info = it.getParcelable(ARG_PARAM1)
info?.let {
binding.tvNum.text = "${it.equipmentName}-${it.equipmentBoxCode}"
binding.tvPlateNumberValue.text = it.plateNumber
binding.tvNameValue.text = it.name
binding.tvPhoneValue.text = it.phone
val timeInfo = DateTimeUtils.parseDateTime(it.updateTime)
val timeAgo = DateTimeUtils.getTimeAgo(timeInfo)
binding.tvUpdateTimeValue.text = timeAgo
}
}
}
}