Преглед изворни кода

refactor(更新)
- 界面优化
- 异常上报数据检查
- 蓝牙钥匙充电和电量检测逻辑优化
- 新增快捷入口配置界面

周文健 пре 10 месеци
родитељ
комит
ad25a46ae8

+ 22 - 0
app/src/main/java/com/grkj/iscs/features/main/dialog/QuickEntranceConfigDialog.kt

@@ -0,0 +1,22 @@
+package com.grkj.iscs.features.main.dialog
+
+import android.graphics.Color
+import android.view.View
+import com.grkj.iscs.R
+import com.grkj.iscs.databinding.DialogQuickEntranceConfigBinding
+import com.kongzue.dialogx.dialogs.FullScreenDialog
+import com.kongzue.dialogx.interfaces.OnBindView
+import com.kongzue.dialogx.util.views.ActivityScreenShotImageView
+
+/**
+ * 快捷入口配置弹窗
+ */
+class QuickEntranceConfigDialog :
+    OnBindView<FullScreenDialog>(R.layout.dialog_quick_entrance_config) {
+    private lateinit var binding: DialogQuickEntranceConfigBinding
+    override fun onBind(dialog: FullScreenDialog, contentView: View) {
+        dialog.setMaskColor(Color.parseColor("#4D000000"))
+        binding = DialogQuickEntranceConfigBinding.bind(contentView)
+        ActivityScreenShotImageView.hideContentView = true
+    }
+}

+ 94 - 30
app/src/main/java/com/grkj/iscs/features/main/fragment/common/SelectMemberFragment.kt

@@ -1,6 +1,7 @@
 package com.grkj.iscs.features.main.fragment.common
 
 import android.widget.LinearLayout
+import androidx.core.content.ContextCompat
 import androidx.core.view.isVisible
 import androidx.fragment.app.viewModels
 import coil.load
@@ -137,7 +138,7 @@ class SelectMemberFragment : BaseFragment<FragmentSelectMemeberBinding>() {
                 }
                 if (isLockerSelect) {
                     selectedLockerData.find {
-                        it.jobTicketGroupMemberList.map { it.userId }.contains(item.userId)
+                        it.jobTicketGroupInfo.groupId == viewModel.currentSelectGroup?.groupId
                     }?.jobTicketGroupMemberList?.removeIf { it.userId == item.userId }
                     item.isSelected = false
                 } else {
@@ -161,6 +162,13 @@ class SelectMemberFragment : BaseFragment<FragmentSelectMemeberBinding>() {
                     selectedLockerData.find { it.jobTicketGroupInfo.groupId == viewModel.currentSelectGroup?.groupId }?.jobTicketGroupMemberList?.add(
                         item
                     )
+                    viewModel.userData.forEach {
+                        it.isSelected =
+                            selectedLockerData.find { it.jobTicketGroupInfo.groupId == viewModel.currentSelectGroup?.groupId }
+                                ?.jobTicketGroupMemberList?.map { selectedLocker -> selectedLocker.userId }
+                                ?.contains(it.userId) == true
+                    }
+                    viewModel.userData.sortedBy { it.isSelected }
                 } else {
                     selectedColockerData.add(item)
                     binding.allUserRv.models =
@@ -183,34 +191,25 @@ class SelectMemberFragment : BaseFragment<FragmentSelectMemeberBinding>() {
         val itemBinding = holder.getBinding<ItemLockerGroupBinding>()
         val item = holder.getModel<JobTicketGroupDataVo<JobUserVo>>()
         itemBinding.groupName.text = item.jobTicketGroupInfo.groupName
-        itemBinding.groupLockerRv.setDebouncedClickListener {
+        fun groupSelected() {
             isLockerSelect = true
-            itemBinding.groupName.isSelected = !itemBinding.groupName.isSelected
+            checkSelectArea()
+            itemBinding.groupTitleLayout.isSelected = true
+            itemBinding.groupName.isSelected = true
             viewModel.currentSelectGroup = item.jobTicketGroupInfo
             binding.selectMemberTip.text =
                 getString(R.string.select_locker_tip, viewModel.currentSelectGroup?.groupName ?: "")
             binding.allUserRv.models =
                 viewModel.userData.filter { it.roleKeys.contains(RoleEnum.JTLOCKER.roleKey) }
                     .onEach {
-                        it.isSelected == item.jobTicketGroupMemberList.map { selectedLocker -> selectedLocker.userId }
-                            .contains(it.userId)
-                    }
+                        it.isSelected =
+                            item.jobTicketGroupMemberList.map { selectedLocker -> selectedLocker.userId }
+                                .contains(it.userId)
+                    }.sortedBy { it.isSelected }
             adapter.notifyDataSetChanged()
         }
         itemBinding.groupTitleLayout.setDebouncedClickListener {
-            isLockerSelect = true
-            itemBinding.groupTitleLayout.isSelected = !itemBinding.groupTitleLayout.isSelected
-            itemBinding.groupName.isSelected = itemBinding.groupTitleLayout.isSelected
-            viewModel.currentSelectGroup = item.jobTicketGroupInfo
-            binding.selectMemberTip.text =
-                getString(R.string.select_locker_tip, viewModel.currentSelectGroup?.groupName ?: "")
-            binding.allUserRv.models =
-                viewModel.userData.filter { it.roleKeys.contains(RoleEnum.JTLOCKER.roleKey) }
-                    .onEach {
-                        it.isSelected == item.jobTicketGroupMemberList.map { selectedLocker -> selectedLocker.userId }
-                            .contains(it.userId)
-                    }
-            adapter.notifyDataSetChanged()
+            groupSelected()
         }
         itemBinding.groupTitleLayout.isSelected =
             isLockerSelect && item.jobTicketGroupInfo.groupId == viewModel.currentSelectGroup?.groupId
@@ -219,13 +218,14 @@ class SelectMemberFragment : BaseFragment<FragmentSelectMemeberBinding>() {
         itemBinding.groupLockerRv.linear(LinearLayout.HORIZONTAL).setup {
             addType<JobUserVo>(R.layout.item_select_member)
             onBind {
-                onLockerRVBinding(item.jobTicketGroupInfo, this)
+                onLockerRVBinding(item.jobTicketGroupInfo, item.jobTicketGroupMemberList, this)
             }
         }.models = item.jobTicketGroupMemberList
     }
 
     private fun BindingAdapter.BindingViewHolder.onLockerRVBinding(
         groupData: JobTicketGroupInfoVo,
+        memberData: MutableList<JobUserVo>,
         holder: BindingAdapter.BindingViewHolder
     ) {
         val itemBinding = holder.getBinding<ItemSelectMemberBinding>()
@@ -244,9 +244,37 @@ class SelectMemberFragment : BaseFragment<FragmentSelectMemeberBinding>() {
                 PopTip.build().tip(com.grkj.ui_base.R.string.can_not_remove_current_locker)
                 return@setDebouncedClickListener
             }
-            selectedLockerData.find { it.jobTicketGroupInfo.groupId == groupData.groupId }?.jobTicketGroupMemberList?.removeIf { it.userId == item.userId }
-            viewModel.userData.find { it.userId == item.userId }?.isSelected = false
-            adapter.notifyDataSetChanged()
+            if (isLockerSelect) {
+                selectedLockerData.find { it.jobTicketGroupInfo.groupId == groupData.groupId }?.jobTicketGroupMemberList?.removeIf { it.userId == item.userId }
+                viewModel.userData.find { it.userId == item.userId }?.isSelected = false
+                if (groupData.groupId == viewModel.currentSelectGroup?.groupId) {
+                    binding.allUserRv.adapter?.notifyDataSetChanged()
+                } else {
+                    binding.allUserRv.models =
+                        viewModel.userData.filter { it.roleKeys.contains(RoleEnum.JTLOCKER.roleKey) }
+                            .onEach {
+                                it.isSelected =
+                                    memberData.map { selectedLocker -> selectedLocker.userId }
+                                        .contains(it.userId)
+                            }.sortedBy { it.isSelected }
+                }
+                adapter.notifyDataSetChanged()
+            } else {
+                isLockerSelect = true
+                checkSelectArea()
+                viewModel.currentSelectGroup = groupData
+                selectedLockerData.find { it.jobTicketGroupInfo.groupId == groupData.groupId }?.jobTicketGroupMemberList?.removeIf { it.userId == item.userId }
+                viewModel.userData.find { it.userId == item.userId }?.isSelected = false
+                binding.allUserRv.models =
+                    viewModel.userData.filter { it.roleKeys.contains(RoleEnum.JTLOCKER.roleKey) }
+                        .onEach {
+                            it.isSelected =
+                                selectedLockerData.find { it.jobTicketGroupInfo.groupId == groupData.groupId }?.jobTicketGroupMemberList?.map { selectedLocker -> selectedLocker.userId }
+                                    ?.contains(it.userId) == true
+                        }.sortedBy { it.isSelected }
+                adapter.notifyDataSetChanged()
+            }
+            binding.lockerRv.adapter?.notifyDataSetChanged()
         }
     }
 
@@ -269,17 +297,26 @@ class SelectMemberFragment : BaseFragment<FragmentSelectMemeberBinding>() {
             }
             selectedColockerData.removeIf { it.userId == item.userId }
             viewModel.userData.find { it.userId == item.userId }?.isSelected = false
-            adapter.notifyDataSetChanged()
-            binding.allUserRv.models =
-                viewModel.userData.filter { it.roleKeys.contains(RoleEnum.JTCOLOCKER.roleKey) }
-                    .filter {
-                        it.userId !in selectedColockerData.map { it.userId }
-                    }
+            if (isLockerSelect) {
+                isLockerSelect = false
+                checkSelectArea()
+                viewModel.currentSelectGroup = null
+                binding.lockerRv.adapter?.notifyDataSetChanged()
+                setColockerData()
+            } else {
+                adapter.notifyDataSetChanged()
+                binding.allUserRv.models =
+                    viewModel.userData.filter { it.roleKeys.contains(RoleEnum.JTCOLOCKER.roleKey) }
+                        .filter {
+                            it.userId !in selectedColockerData.map { it.userId }
+                        }
+            }
         }
     }
 
     private fun setLockerData() {
         isLockerSelect = true
+        checkSelectArea()
         binding.selectMemberTip.text =
             getString(R.string.select_locker_tip, viewModel.currentSelectGroup?.groupName ?: "")
         binding.lockerRv.models = selectedLockerData
@@ -298,10 +335,14 @@ class SelectMemberFragment : BaseFragment<FragmentSelectMemeberBinding>() {
 
     private fun setColockerData() {
         isLockerSelect = false
+        checkSelectArea()
         binding.selectMemberTip.text = CommonUtils.getStr(R.string.select_colocker_tip)
         binding.colockerRv.models = selectedColockerData
         binding.allUserRv.models =
-            viewModel.userData.filter { it.roleKeys.contains(RoleEnum.JTCOLOCKER.roleKey) && it.userId in selectedColockerData.map { it.userId } }
+            viewModel.userData.filter { it.roleKeys.contains(RoleEnum.JTCOLOCKER.roleKey) && it.userId !in selectedColockerData.map { it.userId } }
+                .apply {
+                    forEach { it.isSelected = false }
+                }
     }
 
     override fun initData() {
@@ -342,4 +383,27 @@ class SelectMemberFragment : BaseFragment<FragmentSelectMemeberBinding>() {
         viewModel.getTicketUsers(ticketId).observe(this) {}
         viewModel.getTicketData(ticketId).observe(this) {}
     }
+
+    /**
+     * 选择区域
+     */
+    private fun checkSelectArea() {
+        if (isLockerSelect) {
+            binding.lockerRv.setBackgroundColor(
+                ContextCompat.getColor(
+                    requireContext(),
+                    R.color.color_4d2196f3
+                )
+            )
+            binding.colockerRv.background = null
+        } else {
+            binding.colockerRv.setBackgroundColor(
+                ContextCompat.getColor(
+                    requireContext(),
+                    R.color.color_4d2196f3
+                )
+            )
+            binding.lockerRv.background = null
+        }
+    }
 }

+ 1 - 8
app/src/main/java/com/grkj/iscs/features/main/fragment/common/SelectPointFragment.kt

@@ -95,14 +95,7 @@ class SelectPointFragment : BaseFragment<FragmentSelectPointBinding>() {
             viewModel.currentSelectGroupId = item.jobTicketGroupInfo.groupId
             adapter.notifyDataSetChanged()
         }
-        itemBinding.groupName.setDebouncedClickListener {
-            itemBinding.groupTitleLayout.isSelected = !itemBinding.groupTitleLayout.isSelected
-            itemBinding.groupName.isSelected = itemBinding.groupTitleLayout.isSelected
-            itemBinding.deleteGroup.isSelected = itemBinding.groupTitleLayout.isSelected
-            viewModel.currentSelectGroupId = item.jobTicketGroupInfo.groupId
-            adapter.notifyDataSetChanged()
-        }
-        itemBinding.groupPointRv.setDebouncedClickListener {
+        itemBinding.selectedPointInfoLayout.setDebouncedClickListener {
             itemBinding.groupTitleLayout.isSelected = !itemBinding.groupTitleLayout.isSelected
             itemBinding.groupName.isSelected = itemBinding.groupTitleLayout.isSelected
             itemBinding.deleteGroup.isSelected = itemBinding.groupTitleLayout.isSelected

+ 34 - 11
app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionReportFragment.kt

@@ -9,6 +9,7 @@ import com.grkj.iscs.features.main.viewmodel.exception_manage.ExceptionViewModel
 import com.grkj.ui_base.base.BaseFormFragment
 import com.grkj.ui_base.base.BaseFragment
 import com.grkj.ui_base.dialog.TipDialog
+import com.grkj.ui_base.utils.CommonUtils
 import com.sik.sikcore.extension.setDebouncedClickListener
 import com.sik.sikcore.extension.toJson
 import dagger.hilt.android.AndroidEntryPoint
@@ -48,17 +49,19 @@ class ExceptionReportFragment : BaseFormFragment<FragmentExceptionReportBinding>
             }
         }
         binding.confirm.setDebouncedClickListener {
-            viewModel.exceptionReport().observe(this) {
-                TipDialog.showSuccess(
-                    msg = getString(R.string.exception_report_success),
-                    onConfirmClick = {
-                        clearData()
-                        resetFormDirty()
-                    },
-                    onCancelClick = {
-                        clearData()
-                        resetFormDirty()
-                    })
+            if (checkData()){
+                viewModel.exceptionReport().observe(this) {
+                    TipDialog.showSuccess(
+                        msg = getString(R.string.exception_report_success),
+                        onConfirmClick = {
+                            clearData()
+                            resetFormDirty()
+                        },
+                        onCancelClick = {
+                            clearData()
+                            resetFormDirty()
+                        })
+                }
             }
         }
         binding.exceptionType.setDebouncedClickListener {
@@ -149,6 +152,26 @@ class ExceptionReportFragment : BaseFormFragment<FragmentExceptionReportBinding>
         }
     }
 
+    private fun checkData(): Boolean{
+        if (viewModel.selectedExceptionType==null){
+            showToast(CommonUtils.getStr(R.string.please_select_exception_type).toString())
+            return false
+        }
+        if (viewModel.selectedExceptionDescription.isEmpty()){
+            showToast(CommonUtils.getStr(R.string.please_select_exception_description).toString())
+            return false
+        }
+        if (viewModel.selectedSourceData.isEmpty()){
+            showToast(CommonUtils.getStr(R.string.please_select_exception_source).toString())
+            return false
+        }
+        if (viewModel.selectedProcessApplication==null){
+            showToast(CommonUtils.getStr(R.string.please_select_process_application).toString())
+            return false
+        }
+        return true
+    }
+
     private fun clearData(){
         viewModel.selectedExceptionType = null
         viewModel.selectedExceptionDescription.clear()

+ 3 - 2
app/src/main/java/com/grkj/iscs/features/main/fragment/home/HomeFragment.kt

@@ -7,6 +7,7 @@ import com.drake.brv.BindingAdapter
 import com.drake.brv.utils.linear
 import com.drake.brv.utils.models
 import com.drake.brv.utils.setup
+import com.grkj.data.enums.RoleFunctionalPermissionsEnum
 import com.grkj.iscs.R
 import com.grkj.iscs.databinding.FragmentHomeBinding
 import com.grkj.iscs.databinding.ItemHomeQuickEntranceBinding
@@ -36,8 +37,8 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
         MenuItemEntity(
             0,
             R.mipmap.icon_job_manage_create_job,
-            "新建作业",
-            "quick_entrance:create_job"
+            RoleFunctionalPermissionsEnum.CREATE_JOB.description,
+            RoleFunctionalPermissionsEnum.CREATE_JOB.functionalPermission
         )
     )
 

+ 7 - 3
app/src/main/res/layout-land/fragment_select_memeber.xml

@@ -111,9 +111,11 @@
                         android:orientation="vertical">
 
                         <TextView
+                            android:id="@+id/locker_title_tv"
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
                             android:gravity="center"
+                            android:layout_marginVertical="@dimen/common_spacing"
                             android:paddingHorizontal="@dimen/common_spacing_2x"
                             android:paddingVertical="@dimen/common_spacing"
                             android:text="@string/locker"
@@ -124,7 +126,7 @@
 
                     <androidx.recyclerview.widget.RecyclerView
                         android:id="@+id/locker_rv"
-                        android:layout_width="wrap_content"
+                        android:layout_width="match_parent"
                         android:layout_height="match_parent" />
                 </LinearLayout>
 
@@ -145,9 +147,11 @@
                         android:orientation="vertical">
 
                         <TextView
+                            android:id="@+id/colocker_title_tv"
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
                             android:gravity="center"
+                            android:layout_marginVertical="@dimen/common_spacing"
                             android:paddingHorizontal="@dimen/common_spacing_2x"
                             android:paddingVertical="@dimen/common_spacing"
                             android:text="@string/colocker"
@@ -158,7 +162,7 @@
                             android:id="@+id/select_colocker_tv"
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
-                            android:layout_marginBottom="@dimen/common_spacing"
+                            android:layout_marginVertical="@dimen/common_spacing"
                             android:background="@drawable/bg_select_member_btn"
                             android:paddingHorizontal="@dimen/common_spacing_2x"
                             android:paddingVertical="@dimen/common_spacing_small"
@@ -170,7 +174,7 @@
 
                     <androidx.recyclerview.widget.RecyclerView
                         android:id="@+id/colocker_rv"
-                        android:layout_width="wrap_content"
+                        android:layout_width="match_parent"
                         android:layout_height="match_parent" />
                 </LinearLayout>
             </LinearLayout>

+ 24 - 15
app/src/main/res/layout-land/item_locker_group.xml

@@ -9,27 +9,36 @@
         <LinearLayout
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_gravity="center_vertical"
             android:background="@drawable/home_card_bg"
             android:gravity="center_vertical"
             android:minWidth="@dimen/item_locker_group_min_width"
+            android:layout_gravity="center_vertical"
             android:orientation="vertical">
 
-            <TextView
-                android:id="@+id/group_name"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_gravity="center"
+            <LinearLayout
+                android:id="@+id/group_title_layout"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
                 android:background="@drawable/bg_item_group_title_layout"
-                android:enabled="false"
-                android:focusable="false"
-                android:focusableInTouchMode="false"
-                android:gravity="center"
-                android:paddingHorizontal="@dimen/common_spacing"
-                android:paddingVertical="@dimen/common_spacing_small"
-                android:text="@string/selected_point_info_title"
-                android:textColor="@color/text_color_item_group_title_text"
-                android:textSize="@dimen/normal_text_size_18" />
+                android:gravity="center_vertical"
+                android:orientation="horizontal"
+                android:paddingVertical="@dimen/common_spacing_small">
+
+                <TextView
+                    android:id="@+id/group_name"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:enabled="false"
+                    android:focusable="false"
+                    android:layout_gravity="center"
+                    android:focusableInTouchMode="false"
+                    android:gravity="center"
+                    android:paddingHorizontal="@dimen/common_spacing"
+                    android:text="@string/selected_point_info_title"
+                    android:textColor="@color/text_color_item_group_title_text"
+                    android:textSize="@dimen/normal_text_size_18" />
+
+            </LinearLayout>
 
             <View
                 android:layout_width="match_parent"

+ 67 - 0
app/src/main/res/layout/dialog_quick_entrance_config.xml

@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="@color/white"
+        android:orientation="vertical">
+
+        <RelativeLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/common_spacing"
+            android:paddingHorizontal="@dimen/common_spacing">
+
+            <TextView
+                android:id="@+id/cancel"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingHorizontal="@dimen/common_spacing_2x"
+                android:paddingVertical="@dimen/common_spacing"
+                android:text="@string/cancel"
+                android:textColor="@color/main_color"
+                android:textSize="@dimen/common_btn_text_size" />
+
+            <TextView
+                android:id="@+id/title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerHorizontal="true"
+                android:paddingVertical="@dimen/common_spacing"
+                android:text="@string/quick_entrance_title"
+                android:textColor="@color/black"
+                android:textSize="@dimen/common_btn_text_size" />
+
+            <TextView
+                android:id="@+id/save"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_alignParentRight="true"
+                android:background="@drawable/common_btn_blue_bg"
+                android:paddingHorizontal="@dimen/common_spacing_2x"
+                android:paddingVertical="@dimen/common_spacing"
+                android:text="@string/save"
+                android:textColor="@color/white"
+                android:textSize="@dimen/common_btn_text_size" />
+        </RelativeLayout>
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/common_spacing"
+            android:paddingHorizontal="@dimen/common_spacing"
+            android:orientation="vertical">
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerHorizontal="true"
+                android:paddingVertical="@dimen/common_spacing"
+                android:text="@string/quick_entrance_title"
+                android:textColor="@color/black"
+                android:textSize="@dimen/common_btn_text_size" />
+            <androidx.recyclerview.widget.RecyclerView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"/>
+        </LinearLayout>
+    </LinearLayout>
+</layout>

+ 16 - 8
app/src/main/res/layout/fragment_exception_report.xml

@@ -87,7 +87,7 @@
                 android:orientation="vertical"
                 android:paddingHorizontal="@dimen/dialog_content_normal_padding_horizontal">
 
-                <TextView
+                <com.grkj.ui_base.widget.RequiredTextView
                     android:id="@+id/exception_type_tv"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -96,7 +96,9 @@
                     android:textColor="@color/black"
                     android:textSize="@dimen/common_text_size"
                     app:layout_constraintStart_toStartOf="parent"
-                    app:layout_constraintTop_toTopOf="parent" />
+                    app:layout_constraintTop_toTopOf="parent"
+                    app:markPosition="end"
+                    app:required="true" />
 
                 <TextView
                     android:id="@+id/exception_type"
@@ -118,7 +120,7 @@
                     app:layout_constraintTop_toTopOf="@+id/exception_type_tv" />
 
 
-                <TextView
+                <com.grkj.ui_base.widget.RequiredTextView
                     android:id="@+id/exception_source_tv"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -127,7 +129,9 @@
                     android:textColor="@color/black"
                     android:textSize="@dimen/common_text_size"
                     app:layout_constraintEnd_toEndOf="@+id/exception_type_tv"
-                    app:layout_constraintTop_toBottomOf="@+id/exception_type_tv" />
+                    app:layout_constraintTop_toBottomOf="@+id/exception_type_tv"
+                    app:markPosition="end"
+                    app:required="true" />
 
                 <TextView
                     android:id="@+id/exception_source"
@@ -149,7 +153,7 @@
                     app:layout_constraintTop_toTopOf="@+id/exception_source_tv" />
 
 
-                <TextView
+                <com.grkj.ui_base.widget.RequiredTextView
                     android:id="@+id/exception_description_tv"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -158,7 +162,9 @@
                     android:textColor="@color/black"
                     android:textSize="@dimen/common_text_size"
                     app:layout_constraintEnd_toEndOf="@+id/exception_source_tv"
-                    app:layout_constraintTop_toBottomOf="@+id/exception_source_tv" />
+                    app:layout_constraintTop_toBottomOf="@+id/exception_source_tv"
+                    app:markPosition="end"
+                    app:required="true" />
 
                 <TextView
                     android:id="@+id/exception_description"
@@ -178,7 +184,7 @@
                     app:layout_constraintTop_toTopOf="@+id/exception_description_tv" />
 
 
-                <TextView
+                <com.grkj.ui_base.widget.RequiredTextView
                     android:id="@+id/process_application_tv"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
@@ -187,7 +193,9 @@
                     android:textColor="@color/black"
                     android:textSize="@dimen/common_text_size"
                     app:layout_constraintEnd_toEndOf="@+id/exception_description_tv"
-                    app:layout_constraintTop_toBottomOf="@+id/exception_description_tv" />
+                    app:layout_constraintTop_toBottomOf="@+id/exception_description_tv"
+                    app:markPosition="end"
+                    app:required="true" />
 
                 <TextView
                     android:id="@+id/process_application"

+ 4 - 0
app/src/main/res/layout/fragment_select_memeber.xml

@@ -109,9 +109,11 @@
                         android:orientation="vertical">
 
                         <TextView
+                            android:id="@+id/locker_title_tv"
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
                             android:gravity="center"
+                            android:layout_marginVertical="@dimen/common_spacing"
                             android:paddingHorizontal="@dimen/common_spacing_2x"
                             android:paddingVertical="@dimen/common_spacing"
                             android:text="@string/locker"
@@ -143,9 +145,11 @@
                         android:orientation="vertical">
 
                         <TextView
+                            android:id="@+id/colocker_title_tv"
                             android:layout_width="wrap_content"
                             android:layout_height="wrap_content"
                             android:gravity="center"
+                            android:layout_marginVertical="@dimen/common_spacing"
                             android:paddingHorizontal="@dimen/common_spacing_2x"
                             android:paddingVertical="@dimen/common_spacing"
                             android:text="@string/colocker"

+ 20 - 14
app/src/main/res/layout/item_locker_group.xml

@@ -15,21 +15,27 @@
             android:minWidth="@dimen/item_locker_group_min_width"
             android:orientation="vertical">
 
-            <TextView
-                android:id="@+id/group_name"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_gravity="center"
+            <LinearLayout
+                android:id="@+id/group_title_layout"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
                 android:background="@drawable/bg_item_group_title_layout"
-                android:enabled="false"
-                android:focusable="false"
-                android:focusableInTouchMode="false"
-                android:gravity="center"
-                android:paddingHorizontal="@dimen/common_spacing"
-                android:paddingVertical="@dimen/common_spacing_small"
-                android:text="@string/selected_point_info_title"
-                android:textColor="@color/text_color_item_group_title_text"
-                android:textSize="@dimen/normal_text_size_18" />
+                android:gravity="center_vertical"
+                android:orientation="horizontal"
+                android:paddingVertical="@dimen/common_spacing_small">
+
+                <TextView
+                    android:id="@+id/group_name"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:gravity="center"
+                    android:layout_gravity="center"
+                    android:paddingHorizontal="@dimen/common_spacing"
+                    android:text="@string/selected_point_info_title"
+                    android:textColor="@color/text_color_item_group_title_text"
+                    android:textSize="@dimen/normal_text_size_18" />
+
+            </LinearLayout>
 
             <View
                 android:layout_width="match_parent"

+ 1 - 0
app/src/main/res/values-en/strings.xml

@@ -475,5 +475,6 @@
     <string name="not_group_can_lock">There are currently no groups that can be locked</string>
     <string name="not_group_can_unlock">There are currently no groups to unlock</string>
     <string name="select_group_tip">Click on the blank area of the group to select</string>
+    <string name="quick_entrance_title">快捷入口配置</string>
 
 </resources>

+ 1 - 0
app/src/main/res/values-zh/strings.xml

@@ -475,5 +475,6 @@
     <string name="not_group_can_lock">当前无分组可上锁</string>
     <string name="not_group_can_unlock">当前无分组可解锁</string>
     <string name="select_group_tip">点击分组空白区域进行选中</string>
+    <string name="quick_entrance_title">快捷入口配置</string>
 
 </resources>

+ 1 - 0
app/src/main/res/values/colors.xml

@@ -7,6 +7,7 @@
     <color name="color_7b7d7e">#7b7d7e</color>
     <color name="color_b2f2bb">#b2f2bb</color>
     <color name="color_1daeff">#1daeff</color>
+    <color name="color_4d2196f3">#4D2196F3</color>
     <color name="color_d7d2d2">#d7d2d2</color>
     <color name="color_ffec99">#ffec99</color>
     <color name="color_ffc9c9">#ffc9c9</color>

+ 1 - 0
app/src/main/res/values/strings.xml

@@ -478,5 +478,6 @@
     <string name="not_group_can_lock">当前无分组可上锁</string>
     <string name="not_group_can_unlock">当前无分组可解锁</string>
     <string name="select_group_tip">点击分组空白区域选中</string>
+    <string name="quick_entrance_title">快捷入口配置</string>
 
 </resources>

+ 5 - 0
data/src/main/java/com/grkj/data/data/MMKVConstants.kt

@@ -39,4 +39,9 @@ object MMKVConstants {
      * 锁柜id
      */
     const val KEY_LOCK_CABINET_ID = "key_lock_cabinet_id"
+
+    /**
+     * 快捷入口配置
+     */
+    const val KEY_QUICK_ENTRY_CONFIG = "selected_list"
 }

+ 1 - 1
data/src/main/java/com/grkj/data/enums/CommonDictDataEnum.kt

@@ -119,7 +119,7 @@ enum class CommonDictDataEnum(val dictKey: String, val commonDictRes: List<Commo
         )
     ),
     EXCEPTION_PROCESS_APPLICATION_JOB(
-        DictConstants.KEY_EXCEPTION_PROCESS_APPLICATION_HARDWARE, listOf(
+        DictConstants.KEY_EXCEPTION_PROCESS_APPLICATION_JOB, listOf(
             SimpleCommonDictRes("申请万能钥匙", "0"),
             SimpleCommonDictRes("申请结束作业", "1"),
         )

+ 21 - 9
ui-base/src/main/java/com/grkj/ui_base/utils/ble/BleConnectionManager.kt

@@ -37,6 +37,12 @@ object BleConnectionManager {
     // 已连接的蓝牙钥匙集合
     var deviceList: MutableList<BleBean> = mutableListOf()
 
+    /**
+     * 钥匙电量检测
+     */
+    @Volatile
+    var keyPowerDetect: MutableMap<String, Int?> = mutableMapOf()
+
     /**
      * 最大待机连接数,超过则断开最旧设备。
      * 默认为业务常量 MAX_KEY_STAND_BY,可根据需求调整。
@@ -91,6 +97,7 @@ object BleConnectionManager {
                         prepareDoneCallBack?.invoke(true, bleBean)
                         //尝试使用命令作为心跳 ,获取token完成之后就要建立心跳了
                         tryHeartBeatWithCmd(bleBean.bleDevice)
+                        keyPowerDetect.remove(bleBean.bleDevice.mac)
                     }
                 }
 
@@ -99,21 +106,26 @@ object BleConnectionManager {
                     val power = byteArray[4].toInt()
                     ModBusController.updateKeyPower(power, bleBean.bleDevice.mac)
                     logger.info("电量(${bleBean.bleDevice.mac}):${power}")
+                    keyPowerDetect[bleBean.bleDevice.mac]?.let {
+                        if (it == 5) {
+                            if (power < 50) {//如果电量小于50就打开仓位充电
+                                ModBusController.controlKeyCharge(true, bleBean.bleDevice.mac) {
+                                    logger.debug("钥匙: ${bleBean.bleDevice.mac} 开始充电")
+                                }
+                            } else {
+                                ModBusController.controlKeyCharge(false, bleBean.bleDevice.mac) {
+                                    logger.debug("钥匙: ${bleBean.bleDevice.mac} 关闭充电")
+                                }
+                            }
+                            keyPowerDetect[bleBean.bleDevice.mac] = 0
+                        }
+                    } ?: { keyPowerDetect[bleBean.bleDevice.mac] = 0 }
                     ThreadUtils.runOnIODelayed(30 * 1000) {
                         if (BleManager.getInstance().isConnected(bleBean.bleDevice)) {
                             //尝试使用命令作为心跳
                             tryHeartBeatWithCmd(bleBean.bleDevice)
                         }
                     }
-                    if (power < 50) {//如果电量小于50就打开仓位充电
-                        ModBusController.controlKeyCharge(true, bleBean.bleDevice.mac) {
-                            logger.debug("钥匙: ${bleBean.bleDevice.mac} 开始充电")
-                        }
-                    } else {
-                        ModBusController.controlKeyCharge(false, bleBean.bleDevice.mac) {
-                            logger.debug("钥匙: ${bleBean.bleDevice.mac} 关闭充电")
-                        }
-                    }
                 }
             }
         }

+ 0 - 5
ui-base/src/main/java/com/grkj/ui_base/utils/modbus/ModBusController.kt

@@ -237,11 +237,6 @@ object ModBusController {
                                     updateKeyMac(dockBean.addr, key.idx, keyInfo.macAddress!!)
                                     //已经初始化完成才会去连接
                                     if (ISCSConfig.isInit) {
-                                        controlKeyCharge(true, key.idx, dockBean.addr) {
-                                            ThreadUtils.runOnIODelayed(3000) {
-                                                controlKeyCharge(false, key.idx, dockBean.addr)
-                                            }
-                                        }
                                         ThreadUtils.runOnIO {
                                             val isConnect =
                                                 BleConnectionManager.tryConnectWithOptionalCharge(