Переглянути джерело

refactor(更新)
- 初始化逻辑调整
- 初始化刷卡和点位弹出软键盘的问题处理

周文健 4 місяців тому
батько
коміт
6719c290b5
31 змінених файлів з 776 додано та 221 видалено
  1. 33 2
      app/src/main/java/com/grkj/iscs/features/init/fragment/InitCardRegistrationFragment.kt
  2. 1 0
      app/src/main/java/com/grkj/iscs/features/init/fragment/InitDeviceRegistrationKeyAndLockFragment.kt
  3. 30 4
      app/src/main/java/com/grkj/iscs/features/init/fragment/InitPointRfidRegistrationFragment.kt
  4. 11 9
      app/src/main/java/com/grkj/iscs/features/init/viewmodel/InitDeviceRegistrationKeyAndLockViewModel.kt
  5. 120 24
      app/src/main/java/com/grkj/iscs/features/main/dialog/TextDropDownDialog.kt
  6. 12 2
      app/src/main/java/com/grkj/iscs/features/main/dialog/data_manage/UpdateUserDialog.kt
  7. 40 0
      app/src/main/java/com/grkj/iscs/features/main/entity/ExceptionSourceDataEntity.kt
  8. 112 2
      app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionReportFragment.kt
  9. 7 1
      app/src/main/java/com/grkj/iscs/features/main/fragment/home/HomeFragment.kt
  10. 1 1
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/data_manage/WorkstationManageViewModel.kt
  11. 116 5
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/exception_manage/ExceptionViewModel.kt
  12. 2 1
      app/src/main/res/layout-land/activity_main.xml
  13. 2 1
      app/src/main/res/layout/activity_main.xml
  14. 138 146
      app/src/main/res/layout/fragment_exception_report.xml
  15. 7 0
      app/src/main/res/layout/fragment_init_card_registration.xml
  16. 17 9
      app/src/main/res/layout/fragment_init_point_rfid_registration.xml
  17. 8 0
      app/src/main/res/layout/item_home_text_drop_down.xml
  18. 9 0
      app/src/main/res/values-en/strings.xml
  19. 2 2
      app/src/main/res/values-land/dimens.xml
  20. 9 0
      app/src/main/res/values-zh/strings.xml
  21. 9 0
      app/src/main/res/values/strings.xml
  22. 6 0
      data/src/main/java/com/grkj/data/dao/JobTicketDao.kt
  23. 10 0
      data/src/main/java/com/grkj/data/data/DictConstants.kt
  24. 16 1
      data/src/main/java/com/grkj/data/enums/CommonDictDataEnum.kt
  25. 1 1
      data/src/main/java/com/grkj/data/model/dos/IsLockCabinetSlots.kt
  26. 10 0
      data/src/main/java/com/grkj/data/repository/IHardwareRepository.kt
  27. 8 0
      data/src/main/java/com/grkj/data/repository/impl/network/NetworkHardwareRepository.kt
  28. 9 0
      data/src/main/java/com/grkj/data/repository/impl/network/NetworkJobTicketRepository.kt
  29. 8 0
      data/src/main/java/com/grkj/data/repository/impl/standard/HardwareRepository.kt
  30. 5 1
      ui-base/src/main/java/com/grkj/ui_base/business/BleBusinessManager.kt
  31. 17 9
      ui-base/src/main/java/com/grkj/ui_base/utils/modbus/ModBusController.kt

+ 33 - 2
app/src/main/java/com/grkj/iscs/features/init/fragment/InitCardRegistrationFragment.kt

@@ -1,5 +1,8 @@
 package com.grkj.iscs.features.init.fragment
 
+import android.content.Context
+import android.view.WindowManager
+import android.view.inputmethod.InputMethodManager
 import androidx.fragment.app.viewModels
 import com.drake.brv.BindingAdapter
 import com.drake.brv.utils.linear
@@ -34,7 +37,14 @@ class InitCardRegistrationFragment : BaseFragment<FragmentInitCardRegistrationBi
     }
 
     override fun initView() {
+        binding.root.isFocusable = true
+        binding.root.isFocusableInTouchMode = true
+        binding.root.requestFocus()
+        KeyboardUtils.hideKeyboard(requireActivity())
         (requireActivity() as InitActivity).clearCardNo()
+        binding.emptyFocusView.post {
+            binding.emptyFocusView.requestFocus()
+        }
         binding.previousBtn.setDebouncedClickListener {
             navController.popBackStack()
         }
@@ -53,7 +63,7 @@ class InitCardRegistrationFragment : BaseFragment<FragmentInitCardRegistrationBi
                 onInitHardwareBinding(this)
             }
         }.models = cardRfidData
-        viewModel.removeCardData().observe(this){}
+        viewModel.removeCardData().observe(this) {}
     }
 
     private fun BindingAdapter.BindingViewHolder.onInitHardwareBinding(holder: BindingAdapter.BindingViewHolder) {
@@ -66,12 +76,33 @@ class InitCardRegistrationFragment : BaseFragment<FragmentInitCardRegistrationBi
         }
     }
 
+    override fun onResume() {
+        super.onResume()
+        // 2. 切到 “永远隐藏 + 不调整布局” 模式
+        requireActivity().window.setSoftInputMode(
+            WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
+                    or WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
+        )
+        // 3. 若键盘意外已弹,强制收起
+        (requireContext()
+            .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager)
+            .hideSoftInputFromWindow(requireActivity().window.decorView.windowToken, 0)
+    }
+
+    override fun onPause() {
+        super.onPause()
+        // 可选:离开时恢复默认(如果下一个 Fragment 需要正常键盘弹出)
+        requireActivity().window.setSoftInputMode(
+            WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED
+        )
+    }
+
     override fun onEvent(event: EventBean<Any>) {
         super.onEvent(event)
         when (event.code) {
             EventConstants.EVENT_CARD_SWIPE -> {
                 val cardSwipeEvent = (event.data as CardSwipeEvent)
-                if (cardRfidData.contains(cardSwipeEvent.cardNo)){
+                if (cardRfidData.contains(cardSwipeEvent.cardNo)) {
                     PopTip.tip(R.string.card_already_registration)
                     return
                 }

+ 1 - 0
app/src/main/java/com/grkj/iscs/features/init/fragment/InitDeviceRegistrationKeyAndLockFragment.kt

@@ -49,6 +49,7 @@ class InitDeviceRegistrationKeyAndLockFragment :
         }
         binding.reRecognize.setDebouncedClickListener {
             viewModel.isInDeviceInit = false
+            viewModel.isLoadComplete.postValue(false)
         }
         binding.previousBtn.setDebouncedClickListener {
             navController.popBackStack()

+ 30 - 4
app/src/main/java/com/grkj/iscs/features/init/fragment/InitPointRfidRegistrationFragment.kt

@@ -1,6 +1,9 @@
 package com.grkj.iscs.features.init.fragment
 
+import android.content.Context
 import android.content.Intent
+import android.view.WindowManager
+import android.view.inputmethod.InputMethodManager
 import androidx.fragment.app.viewModels
 import com.drake.brv.BindingAdapter
 import com.drake.brv.utils.linear
@@ -16,13 +19,11 @@ import com.grkj.iscs.features.login.activity.LoginActivity
 import com.grkj.shared.model.EventBean
 import com.grkj.shared.utils.KeyboardUtils
 import com.grkj.ui_base.base.BaseFragment
-import com.grkj.ui_base.config.ISCSConfig
 import com.grkj.ui_base.utils.event.CardSwipeEvent
 import com.kongzue.dialogx.dialogs.PopTip
 import com.sik.sikcore.extension.saveMMKVData
 import com.sik.sikcore.extension.setDebouncedClickListener
 import dagger.hilt.android.AndroidEntryPoint
-import kotlin.getValue
 
 /**
  * 点位rfid录入
@@ -40,7 +41,11 @@ class InitPointRfidRegistrationFragment : BaseFragment<FragmentInitPointRfidRegi
     }
 
     override fun initView() {
+        KeyboardUtils.hideKeyboard(requireActivity())
         (requireActivity() as InitActivity).clearCardNo()
+        binding.emptyFocusView.post {
+            binding.emptyFocusView.requestFocus()
+        }
         binding.previousBtn.setDebouncedClickListener {
             navController.popBackStack()
         }
@@ -67,7 +72,7 @@ class InitPointRfidRegistrationFragment : BaseFragment<FragmentInitPointRfidRegi
                 onInitHardwareBinding(this)
             }
         }.models = pointRfidData
-        viewModel.removeRfidTokenData().observe(this){}
+        viewModel.removeRfidTokenData().observe(this) {}
     }
 
     private fun BindingAdapter.BindingViewHolder.onInitHardwareBinding(holder: BindingAdapter.BindingViewHolder) {
@@ -80,12 +85,33 @@ class InitPointRfidRegistrationFragment : BaseFragment<FragmentInitPointRfidRegi
         }
     }
 
+    override fun onResume() {
+        super.onResume()
+        // 2. 切到 “永远隐藏 + 不调整布局” 模式
+        requireActivity().window.setSoftInputMode(
+            WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN
+                    or WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
+        )
+        // 3. 若键盘意外已弹,强制收起
+        (requireContext()
+            .getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager)
+            .hideSoftInputFromWindow(requireActivity().window.decorView.windowToken, 0)
+    }
+
+    override fun onPause() {
+        super.onPause()
+        // 可选:离开时恢复默认(如果下一个 Fragment 需要正常键盘弹出)
+        requireActivity().window.setSoftInputMode(
+            WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED
+        )
+    }
+
     override fun onEvent(event: EventBean<Any>) {
         super.onEvent(event)
         when (event.code) {
             EventConstants.EVENT_CARD_SWIPE -> {
                 val cardSwipeEvent = (event.data as CardSwipeEvent)
-                if (pointRfidData.contains(cardSwipeEvent.cardNo)){
+                if (pointRfidData.contains(cardSwipeEvent.cardNo)) {
                     PopTip.tip(R.string.rfid_already_registration)
                     return
                 }

+ 11 - 9
app/src/main/java/com/grkj/iscs/features/init/viewmodel/InitDeviceRegistrationKeyAndLockViewModel.kt

@@ -76,15 +76,15 @@ class InitDeviceRegistrationKeyAndLockViewModel @Inject constructor(val hardware
                         .filter { it.newHardware && it.isExist }
                         .toMutableList()
                 })
+            if (newHardwareKeyBean.isNotEmpty()) {
+                BleManager.getInstance().disconnectAllDevice()
+                logger.info("断开所有蓝牙设备")
+            }
             alreadyUsedMac.addAll(
                 dockList.filter { it.type == DeviceConst.DOCK_TYPE_KEY || it.type == DeviceConst.DOCK_TYPE_PORTABLE }
                     .map { it.deviceList }.flatten().filterIsInstance<DockBean.KeyBean>()
                     .filter { it.mac?.isNotEmpty() == true }.mapNotNull { it.mac }
             )
-            if (newHardwareKeyBean.isNotEmpty()) {
-                BleManager.getInstance().disconnectAllDevice()
-                logger.info("断开所有蓝牙设备")
-            }
             logger.debug("设备录入-新设备:${newHardwareKeyBean}")
             for ((addr, keyBeans) in newHardwareKeyBean) {
                 for (keyBean in keyBeans) {
@@ -267,17 +267,18 @@ class InitDeviceRegistrationKeyAndLockViewModel @Inject constructor(val hardware
                 startIndex = deviceInputSlotsSuspend(index, dock, startIndex)
             }
             val lockDevice = deviceList.filter { it.type == DeviceConst.DEVICE_TYPE_LOCK }
-                .filterIsInstance<DockBean.LockBean>().filter { it.newHardware == true }
+                .filterIsInstance<DockBean.LockBean>()
+                .filter { it.newHardware == true && it.rfid != null }
             val keyDevice = deviceList.filter { it.type == DeviceConst.DEVICE_TYPE_KEY }
-                .filterIsInstance<DockBean.KeyBean>().filter { it.newHardware == true }
-            lockDevice.filter { it.rfid?.isNotEmpty() == true }.forEach { lockDevice ->
+                .filterIsInstance<DockBean.KeyBean>()
+                .filter { it.newHardware == true && it.rfid != null && it.mac != null }
+            lockDevice.forEach { lockDevice ->
                 val isBind = deviceInputLockSuspend(lockDevice.rfid.toString())
                 if (isBind) {
                     lockDevice.newHardware = false
                 }
             }
-            keyDevice.filter { it.rfid?.isNotEmpty() == true && it.mac?.isNotEmpty() == true }
-                .forEach { keyDevice ->
+            keyDevice.forEach { keyDevice ->
                     val isBind =
                         deviceInputKeySuspend(keyDevice.rfid.toString(), keyDevice.mac.toString())
                     if (isBind) {
@@ -298,6 +299,7 @@ class InitDeviceRegistrationKeyAndLockViewModel @Inject constructor(val hardware
      */
     fun clearKeyAndLock(): LiveData<Boolean> {
         return liveData(Dispatchers.IO) {
+            alreadyUsedMac.clear()
             hardwareRepository.clearKeyAndLock()
             emit(true)
         }

+ 120 - 24
app/src/main/java/com/grkj/iscs/features/main/dialog/TextDropDownDialog.kt

@@ -4,32 +4,37 @@ import android.view.Gravity
 import android.view.View
 import androidx.core.view.isVisible
 import androidx.core.widget.addTextChangedListener
-import com.drake.brv.BindingAdapter
+import com.drake.brv.item.ItemExpand
 import com.drake.brv.utils.linear
 import com.drake.brv.utils.models
 import com.drake.brv.utils.setup
 import com.grkj.iscs.R
 import com.grkj.iscs.databinding.DialogDropDownListBinding
 import com.grkj.iscs.databinding.ItemHomeTextDropDownBinding
-import com.grkj.ui_base.utils.CommonUtils
 import com.kongzue.dialogx.dialogs.CustomDialog
 import com.kongzue.dialogx.interfaces.OnBindView
+import com.sik.sikcore.extension.setDebouncedClickListener
+import me.jessyan.autosize.utils.AutoSizeUtils
 
 /**
  * 通用下拉文本选择框,支持单选和多选
  * 使用方式:
  * 1. 单选:TextDropDownDialog.showSingle(dataList) { selected -> ... }
+ * 1. 单选树形:TextDropDownDialog.showSingleTree(dataList) { selected -> ... }
  * 2. 多选:TextDropDownDialog.showMulti(dataList) { selectedList -> ... }
+ * 2. 多选树形:TextDropDownDialog.showMultiTree(dataList) { selectedList -> ... }
  */
 class TextDropDownDialog(
     private val dataList: List<TextDropDownEntity>,
     private val multiSelect: Boolean,
+    private val treeSelect: Boolean,
     private val showSearchView: Boolean = false,
     private val onSelect: (TextDropDownEntity) -> Unit,
     private val onMultiSelect: (List<TextDropDownEntity>?) -> Unit
 ) : OnBindView<CustomDialog>(R.layout.dialog_drop_down_list) {
 
     private lateinit var binding: DialogDropDownListBinding
+    private val indentPx: Int by lazy { AutoSizeUtils.dp2px(binding.root.context, 20f) }
 
     override fun onBind(dialog: CustomDialog?, v: View) {
         binding = DialogDropDownListBinding.bind(v)
@@ -38,24 +43,60 @@ class TextDropDownDialog(
             binding.dropDownRv.models =
                 dataList.filter { it.getShowText().contains(text.toString()) }
         })
-        binding.dropDownRv.linear().setup {
-            addType<TextDropDownEntity>(R.layout.item_home_text_drop_down)
-            onBind {
-                val item = getModel<TextDropDownEntity>()
-                val itemBinding = getBinding<ItemHomeTextDropDownBinding>()
-                itemBinding.dropDownText.text = item.getShowText()
-                itemBinding.checkIv.isVisible = item.isSelected()
-                itemBinding.root.setOnClickListener {
-                    if (multiSelect) {
-                        item.setSelected(!item.isSelected())
-                        itemBinding.checkIv.isVisible = item.isSelected()
-                        val selected = binding.dropDownRv.models
-                            ?.filterIsInstance<TextDropDownEntity>()
-                            ?.filter { it.isSelected() }
-                        onMultiSelect(selected)
-                    } else {
-                        onSelect(item)
-                        dialog?.dismiss()
+        if (treeSelect) {
+            binding.dropDownRv.linear().setup {
+                addType<TextDropDownEntity>(R.layout.item_home_text_drop_down)
+                onBind {
+                    val item = getModel<TextDropDownEntity>()
+                    val itemBinding = getBinding<ItemHomeTextDropDownBinding>()
+                    // 缩进
+                    itemBinding.rootLayout.setPadding(indentPx * item.getLevel(), 0, 0, 0)
+                    // 展开/收起
+                    itemBinding.rootLayout.setOnClickListener {
+                        if (item.getChildren().isEmpty()) {
+                            return@setOnClickListener
+                        }
+                        if (item.itemExpand) collapse() else expand()
+                        itemBinding.arrowIv.rotation = if (item.itemExpand) 90f else 0f
+                    }
+                    itemBinding.arrowIv.rotation = if (item.itemExpand) 90f else 0f
+                    // 文本和选中
+                    itemBinding.dropDownText.text = item.getShowText()
+                    itemBinding.root.setDebouncedClickListener {
+                        if (multiSelect && item.getChildren().isEmpty()) {
+                            item.setSelected(!item.isSelected())
+                            itemBinding.checkIv.isVisible = item.isSelected()
+                            val selected = binding.dropDownRv.models
+                                ?.filterIsInstance<TextDropDownEntity>()
+                                ?.filter { it.isSelected() }
+                            onMultiSelect(selected)
+                        } else {
+                            onSelect(item)
+                            dialog?.dismiss()
+                        }
+                    }
+                }
+            }
+        } else {
+            binding.dropDownRv.linear().setup {
+                addType<TextDropDownEntity>(R.layout.item_home_text_drop_down)
+                onBind {
+                    val item = getModel<TextDropDownEntity>()
+                    val itemBinding = getBinding<ItemHomeTextDropDownBinding>()
+                    itemBinding.dropDownText.text = item.getShowText()
+                    itemBinding.checkIv.isVisible = item.isSelected()
+                    itemBinding.root.setDebouncedClickListener {
+                        if (multiSelect) {
+                            item.setSelected(!item.isSelected())
+                            itemBinding.checkIv.isVisible = item.isSelected()
+                            val selected = binding.dropDownRv.models
+                                ?.filterIsInstance<TextDropDownEntity>()
+                                ?.filter { it.isSelected() }
+                            onMultiSelect(selected)
+                        } else {
+                            onSelect(item)
+                            dialog?.dismiss()
+                        }
                     }
                 }
             }
@@ -75,7 +116,7 @@ class TextDropDownDialog(
             onSelect: (TextDropDownEntity) -> Unit
         ) {
             CustomDialog.show(
-                TextDropDownDialog(data, false, showSearchView, onSelect) { }
+                TextDropDownDialog(data, false, false, showSearchView, onSelect) { }
             ).setAlignBaseViewGravity(view, Gravity.BOTTOM or Gravity.CENTER).setWidth(view.width)
         }
 
@@ -90,7 +131,41 @@ class TextDropDownDialog(
             onMultiSelect: (List<TextDropDownEntity>?) -> Unit
         ) {
             CustomDialog.show(
-                TextDropDownDialog(data, true, showSearchView, {}) { selected ->
+                TextDropDownDialog(data, true, false, showSearchView, {}) { selected ->
+                    onMultiSelect(
+                        selected
+                    )
+                }
+            ).setAlignBaseViewGravity(view, Gravity.BOTTOM or Gravity.CENTER).setWidth(view.width)
+        }
+
+        /**
+         * 显示单选树形弹窗
+         */
+        @JvmStatic
+        fun showSingleTree(
+            data: List<TextDropDownEntity>,
+            view: View,
+            showSearchView: Boolean = false,
+            onSelect: (TextDropDownEntity) -> Unit
+        ) {
+            CustomDialog.show(
+                TextDropDownDialog(data, false, true, showSearchView, onSelect) { }
+            ).setAlignBaseViewGravity(view, Gravity.BOTTOM or Gravity.CENTER).setWidth(view.width)
+        }
+
+        /**
+         * 显示多选树形弹窗
+         */
+        @JvmStatic
+        fun showMultiTree(
+            data: List<TextDropDownEntity>,
+            view: View,
+            showSearchView: Boolean = false,
+            onMultiSelect: (List<TextDropDownEntity>?) -> Unit
+        ) {
+            CustomDialog.show(
+                TextDropDownDialog(data, true, true, showSearchView, {}) { selected ->
                     onMultiSelect(
                         selected
                     )
@@ -102,13 +177,16 @@ class TextDropDownDialog(
     /**
      * 下拉弹窗数据实体接口
      */
-    interface TextDropDownEntity {
+    interface TextDropDownEntity : ItemExpand {
         fun getId(): Long?
         fun getTag(): String
         fun getShowText(): String
         fun getData(): Any?
         fun isSelected(): Boolean
         fun setSelected(isSelect: Boolean)
+        fun getChildren(): List<TextDropDownEntity>
+        fun setChildren(children: List<TextDropDownEntity>)
+        fun getLevel(): Int
     }
 
     /**
@@ -118,9 +196,13 @@ class TextDropDownDialog(
         var dataId: Long? = null,
         var dataObject: Any? = null,
         val dataTag: String = "",
-        var dataText: String = ""
+        var dataText: String = "",
+        var dataLevel: Int = 0,
+        override var itemExpand: Boolean = false,
+        override var itemGroupPosition: Int = 0
     ) : TextDropDownEntity {
         private var selected = false
+        private var children: List<TextDropDownEntity> = emptyList<TextDropDownEntity>()
         override fun getId() = dataId
         override fun getTag() = dataTag
         override fun getShowText() = dataText
@@ -129,5 +211,19 @@ class TextDropDownDialog(
         override fun setSelected(isSelect: Boolean) {
             selected = isSelect
         }
+
+        override fun getChildren(): List<TextDropDownEntity> {
+            return children
+        }
+
+        override fun setChildren(children: List<TextDropDownEntity>) {
+            this.children = children
+        }
+
+        override fun getItemSublist(): List<Any?>? {
+            return children
+        }
+
+        override fun getLevel() = dataLevel
     }
 }

+ 12 - 2
app/src/main/java/com/grkj/iscs/features/main/dialog/data_manage/UpdateUserDialog.kt

@@ -58,7 +58,12 @@ class UpdateUserDialog(
 
         // 角色多选
         binding.roleTv.setOnClickListener {
-            TextDropDownDialog.showMulti(roleData, binding.roleTv) { list ->
+            TextDropDownDialog.showMulti(roleData.apply {
+                forEach {
+                    it.setSelected(selectedRoles.map { it.getShowText() }
+                        .contains(it.getShowText()))
+                }
+            }, binding.roleTv) { list ->
                 selectedRoles = list.orEmpty().toMutableList()
                 binding.roleTv.text = selectedRoles.joinToString(",") { it.getShowText() }
             }
@@ -66,7 +71,12 @@ class UpdateUserDialog(
 
         // 工作站多选
         binding.workstationNameTv.setOnClickListener {
-            TextDropDownDialog.showMulti(workstationData, binding.workstationNameTv) { list ->
+            TextDropDownDialog.showMulti(workstationData.apply {
+                forEach {
+                    it.setSelected(selectedWorkstations.map { it.getShowText() }
+                        .contains(it.getShowText()))
+                }
+            }, binding.workstationNameTv) { list ->
                 selectedWorkstations = list.orEmpty().toMutableList()
                 binding.workstationNameTv.text =
                     selectedWorkstations.joinToString(",") { it.getShowText() }

+ 40 - 0
app/src/main/java/com/grkj/iscs/features/main/entity/ExceptionSourceDataEntity.kt

@@ -0,0 +1,40 @@
+package com.grkj.iscs.features.main.entity
+
+import com.drake.brv.item.ItemExpand
+
+/**
+ * 异常数据源实体
+ */
+class ExceptionSourceDataEntity(
+    override var itemExpand: Boolean = false,
+    override var itemGroupPosition: Int = 0
+) : ItemExpand {
+    /**
+     * 数据源id
+     */
+    var sourceDataId: Long = 0L
+
+    /**
+     * 数据源类型
+     */
+    var sourceDataType: Int = 0
+
+    /**
+     * 异常源文本
+     */
+    var sourceDataText: String = ""
+
+    /**
+     * 子类
+     */
+    var children: MutableList<ExceptionSourceDataEntity> = mutableListOf()
+
+    /**
+     * 是否选中
+     */
+    var isSelected: Boolean = false
+
+    override fun getItemSublist(): List<Any?>? {
+        return children
+    }
+}

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

@@ -1,19 +1,129 @@
 package com.grkj.iscs.features.main.fragment.exception_manage
 
+import androidx.fragment.app.viewModels
+import com.grkj.iscs.features.main.entity.ExceptionSourceDataEntity
 import com.grkj.iscs.R
 import com.grkj.iscs.databinding.FragmentExceptionReportBinding
+import com.grkj.iscs.features.main.dialog.TextDropDownDialog
+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.sik.sikcore.extension.setDebouncedClickListener
+import dagger.hilt.android.AndroidEntryPoint
 
 /**
  * 异常上报界面
  */
-class ExceptionReportFragment : BaseFragment<FragmentExceptionReportBinding>() {
+@AndroidEntryPoint
+class ExceptionReportFragment : BaseFormFragment<FragmentExceptionReportBinding>() {
+    private val viewModel: ExceptionViewModel by viewModels()
     override fun getLayoutId(): Int {
         return R.layout.fragment_exception_report
     }
 
+    override val needWatchObject: List<Any?> by lazy {
+        listOf(
+            binding.exceptionType,
+            binding.exceptionSource,
+            binding.exceptionDescription,
+            binding.processApplication
+        )
+    }
+
     override fun initView() {
-        binding.back.setDebouncedClickListener { navController.popBackStack() }
+        binding.back.setDebouncedClickListener {
+            if (isFormDirty) {
+                showUnsavedConfirmDialog()
+            } else {
+                navController.popBackStack()
+            }
+        }
+        binding.cancel.setDebouncedClickListener {
+            if (isFormDirty) {
+                showUnsavedConfirmDialog()
+            } else {
+                navController.popBackStack()
+            }
+        }
+        binding.exceptionType.setDebouncedClickListener {
+            TextDropDownDialog.showSingle(viewModel.exceptionType.map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataTag = it.dictValue, dataText = it.dictLabel
+                )
+            }, binding.exceptionType) {
+                binding.exceptionType.text = it.getShowText()
+                viewModel.selectedExceptionType = it.getTag()
+                viewModel.getExceptionSourceData().observe(this) {}
+            }
+        }
+        binding.exceptionSource.setDebouncedClickListener {
+            if (viewModel.selectedExceptionType == viewModel.exceptionType.find { it.dictLabel == "硬件异常" }?.dictValue) {
+                viewModel.getExceptionSourceData().observe(this) {
+                    TextDropDownDialog.showMultiTree(viewModel.exceptionSourceData.map {
+                        TextDropDownDialog.SimpleTextDropDownEntity(
+                            dataText = it.sourceDataText,
+                            dataObject = it
+                        )
+                            .apply {
+                                setChildren(it.children.map {
+                                    TextDropDownDialog.SimpleTextDropDownEntity(
+                                        dataId = it.sourceDataId,
+                                        dataText = it.sourceDataText,
+                                        dataObject = it
+                                    ).apply {
+                                        setSelected(viewModel.selectedSourceData.map { it.sourceDataText }
+                                            .contains(it.sourceDataText))
+                                    }
+                                })
+                            }
+                    }, binding.exceptionSource) { selectedData ->
+                        binding.exceptionType.text =
+                            selectedData?.joinToString(",") { it.getShowText() }
+                        selectedData?.let {
+                            viewModel.selectedSourceData =
+                                it.map { it.getData() as ExceptionSourceDataEntity } as MutableList<ExceptionSourceDataEntity>
+                        }
+                    }
+                }
+            } else {
+                TextDropDownDialog.showSingle(viewModel.exceptionSourceData.map {
+                    TextDropDownDialog.SimpleTextDropDownEntity(
+                        dataObject = it, dataText = it.sourceDataText
+                    )
+                }, binding.exceptionSource) {
+                    binding.exceptionSource.text = it.getShowText()
+                    viewModel.selectedSourceData =
+                        mutableListOf(it.getData() as ExceptionSourceDataEntity)
+                }
+            }
+        }
+        binding.exceptionDescription.setDebouncedClickListener {
+            TextDropDownDialog.showMulti(viewModel.exceptionDescription.map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataTag = it.dictValue, dataText = it.dictLabel
+                ).apply {
+                    setSelected(viewModel.selectedExceptionDescription.contains(getShowText()))
+                }
+            }, binding.exceptionDescription) {
+                binding.exceptionDescription.text = it?.joinToString(",") { it.getShowText() }
+                viewModel.selectedExceptionDescription =
+                    it?.map { it.getShowText() }?.toMutableList() ?: mutableListOf()
+            }
+        }
+        binding.processApplication.setDebouncedClickListener {
+            TextDropDownDialog.showSingle(viewModel.processApplication.map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataTag = it.dictValue, dataText = it.dictLabel
+                )
+            }, binding.processApplication) {
+                binding.processApplication.text = it.getShowText()
+                viewModel.selectedProcessApplication = it.getTag()
+            }
+        }
+    }
+
+    override fun initData() {
+        super.initData()
+        viewModel.getDictData().observe(this) {}
     }
 }

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

@@ -136,10 +136,16 @@ class HomeFragment : BaseFragment<FragmentHomeBinding>() {
                         return@setOnChoose
                     }
                 }
-                timeView.text = TimeUtils.formatDate(
+                val timeStr = TimeUtils.formatDate(
                     Date(millisecond),
                     TimeUtils.DEFAULT_DATE_HOUR_MIN_FORMAT
                 )
+                timeView.text = timeStr
+                if (startTime) {
+                    viewModel.startTime = timeStr
+                } else {
+                    viewModel.endTime = timeStr
+                }
                 getHomeData()
             }.build().show()
     }

+ 1 - 1
app/src/main/java/com/grkj/iscs/features/main/viewmodel/data_manage/WorkstationManageViewModel.kt

@@ -63,7 +63,7 @@ class WorkstationManageViewModel @Inject constructor(val workstationRepository:
             val selectedItem = workstationManageData.firstOrNull { it.isSelected }
             val orderNum = selectedItem?.let {
                 return@let workstationManageData.count { it.parentId == selectedItem.workstationId } + 1
-            } ?: 0
+            } ?: workstationManageData.count { it.parentId == 0L }
             workstationRepository.insertWorkstation(
                 workstationManageData.firstOrNull { it.isSelected },
                 orderNum,

+ 116 - 5
app/src/main/java/com/grkj/iscs/features/main/viewmodel/exception_manage/ExceptionViewModel.kt

@@ -2,17 +2,13 @@ package com.grkj.iscs.features.main.viewmodel.exception_manage
 
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.liveData
-import androidx.lifecycle.viewModelScope
-import com.grkj.data.dao.JobTicketDao
 import com.grkj.data.data.DictConstants
 import com.grkj.data.model.res.CommonDictRes
+import com.grkj.iscs.features.main.entity.ExceptionSourceDataEntity
 import com.grkj.data.model.vo.IsExceptionStandardVo
-import com.grkj.data.model.vo.JobTicketManageVo
 import com.grkj.data.repository.IExceptionRepository
 import com.grkj.data.repository.IHardwareRepository
 import com.grkj.data.repository.IJobTicketRepository
-import com.grkj.data.repository.impl.standard.HardwareRepository
-import com.grkj.data.repository.impl.standard.JobTicketRepository
 import com.grkj.iscs.R
 import com.grkj.ui_base.base.BaseViewModel
 import com.grkj.ui_base.business.DataBusiness
@@ -45,6 +41,16 @@ class ExceptionViewModel @Inject constructor(
      */
     var exceptionStatus: List<CommonDictRes> = mutableListOf()
 
+    /**
+     * 异常描述
+     */
+    var exceptionDescription: List<CommonDictRes> = mutableListOf()
+
+    /**
+     * 处理申请
+     */
+    var processApplication: List<CommonDictRes> = mutableListOf()
+
     /**
      * 异常数据
      */
@@ -55,6 +61,20 @@ class ExceptionViewModel @Inject constructor(
      */
     var exceptionData: IsExceptionStandardVo? = null
 
+    /**
+     * 异常源数据集合
+     */
+    var exceptionSourceData: MutableList<ExceptionSourceDataEntity> = mutableListOf()
+
+    /**
+     * 选择的数据
+     */
+    var selectedExceptionType: String? = null
+    var selectedSourceData: MutableList<ExceptionSourceDataEntity> =
+        mutableListOf()
+    var selectedExceptionDescription: MutableList<String> = mutableListOf()
+    var selectedProcessApplication: String? = null
+
     /**
      * 获取字典数据
      */
@@ -64,6 +84,9 @@ class ExceptionViewModel @Inject constructor(
             exceptionStatus = DataBusiness.fetchDict(DictConstants.KEY_EXCEPTION_STATUS)
             exceptionSourceDataType =
                 DataBusiness.fetchDict(DictConstants.KEY_EXCEPTION_SOURCE_TYPE)
+            exceptionDescription = DataBusiness.fetchDict(DictConstants.KEY_EXCEPTION_DESCRIPTION)
+            processApplication =
+                DataBusiness.fetchDict(DictConstants.KEY_EXCEPTION_PROCESS_APPLICATION)
             emit(true)
         }
     }
@@ -162,4 +185,92 @@ class ExceptionViewModel @Inject constructor(
             emit(sourceName.toString())
         }
     }
+
+    /**
+     * 获取数据源数据
+     */
+    fun getExceptionSourceData(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            exceptionSourceData.clear()
+            when (selectedExceptionType) {
+                //异常硬件
+                "0" -> {
+                    val keyData = hardwareRepository.getAllKeyInfo()
+                    keyData.map {
+                        val exceptionSourceDataEntity =
+                            ExceptionSourceDataEntity(itemGroupPosition = 1)
+                        exceptionSourceDataEntity.sourceDataText = "钥匙${it.keyNfc}"
+                        exceptionSourceDataEntity.sourceDataId = it.keyId
+                        exceptionSourceDataEntity.sourceDataType =
+                            exceptionSourceDataType.find { it.dictLabel == "钥匙" }?.dictValue?.toInt()
+                                ?: 2
+                        exceptionSourceDataEntity
+                    }.toMutableList().let {
+                        val exceptionSourceDataEntity =
+                            ExceptionSourceDataEntity(itemGroupPosition = 0)
+                        exceptionSourceDataEntity.sourceDataText = "钥匙"
+                        exceptionSourceDataEntity.sourceDataType =
+                            exceptionSourceDataType.find { it.dictLabel == "钥匙" }?.dictValue?.toInt()
+                                ?: 2
+                        exceptionSourceDataEntity.children = it
+                        exceptionSourceData.add(exceptionSourceDataEntity)
+                    }
+                    val lockData = hardwareRepository.getAllLockInfo()
+                    lockData.map {
+                        val exceptionSourceDataEntity =
+                            ExceptionSourceDataEntity(itemGroupPosition = 1)
+                        exceptionSourceDataEntity.sourceDataText = "挂锁${it.lockNfc}"
+                        exceptionSourceDataEntity.sourceDataId = it.lockId
+                        exceptionSourceDataEntity.sourceDataType =
+                            exceptionSourceDataType.find { it.dictLabel == "挂锁" }?.dictValue?.toInt()
+                                ?: 2
+                        exceptionSourceDataEntity
+                    }.toMutableList().let {
+                        val exceptionSourceDataEntity =
+                            ExceptionSourceDataEntity(itemGroupPosition = 0)
+                        exceptionSourceDataEntity.sourceDataText = "挂锁"
+                        exceptionSourceDataEntity.sourceDataType =
+                            exceptionSourceDataType.find { it.dictLabel == "挂锁" }?.dictValue?.toInt()
+                                ?: 2
+                        exceptionSourceDataEntity.children = it
+                        exceptionSourceData.add(exceptionSourceDataEntity)
+                    }
+                    val slotsData = hardwareRepository.getAllSlotsData()
+                    slotsData.map {
+                        val exceptionSourceDataEntity =
+                            ExceptionSourceDataEntity(itemGroupPosition = 1)
+                        exceptionSourceDataEntity.sourceDataText = "仓位${it.row + 1}-${it.col}"
+                        exceptionSourceDataEntity.sourceDataId = it.slotId
+                        exceptionSourceDataEntity.sourceDataType =
+                            exceptionSourceDataType.find { it.dictLabel == "仓位" }?.dictValue?.toInt()
+                                ?: 2
+                        exceptionSourceDataEntity
+                    }.toMutableList().let {
+                        val exceptionSourceDataEntity =
+                            ExceptionSourceDataEntity(itemGroupPosition = 0)
+                        exceptionSourceDataEntity.sourceDataText = "仓位"
+                        exceptionSourceDataEntity.sourceDataType =
+                            exceptionSourceDataType.find { it.dictLabel == "仓位" }?.dictValue?.toInt()
+                                ?: 2
+                        exceptionSourceDataEntity.children = it
+                        exceptionSourceData.add(exceptionSourceDataEntity)
+                    }
+                }
+                //异常作业
+                "1" -> {
+                    val jobTicketData = jobTicketRepository.getAllInProgressJob()
+                    exceptionSourceData = jobTicketData.map {
+                        val exceptionSourceDataEntity =
+                            ExceptionSourceDataEntity(itemGroupPosition = 0)
+                        exceptionSourceDataEntity.sourceDataText = it.ticketName
+                        exceptionSourceDataEntity.sourceDataId = it.ticketId
+                        exceptionSourceDataEntity.sourceDataType =
+                            exceptionSourceDataType.find { it.dictLabel == "作业" }?.dictValue?.toInt()
+                                ?: 3
+                        exceptionSourceDataEntity
+                    }.toMutableList()
+                }
+            }
+        }
+    }
 }

+ 2 - 1
app/src/main/res/layout-land/activity_main.xml

@@ -48,9 +48,10 @@
                 <TextView
                     android:id="@+id/nickname"
                     android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
+                    android:layout_height="match_parent"
                     android:layout_marginLeft="@dimen/home_nickname_margin"
                     android:textColor="@color/white"
+                    android:gravity="center"
                     android:textSize="@dimen/home_nickname_text_size" />
             </LinearLayout>
         </FrameLayout>

+ 2 - 1
app/src/main/res/layout/activity_main.xml

@@ -48,7 +48,8 @@
                 <TextView
                     android:id="@+id/nickname"
                     android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
+                    android:layout_height="match_parent"
+                    android:gravity="center"
                     android:layout_marginLeft="@dimen/home_nickname_margin"
                     android:textColor="@color/white"
                     android:textSize="@dimen/home_nickname_text_size" />

+ 138 - 146
app/src/main/res/layout/fragment_exception_report.xml

@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    xmlns:app="http://schemas.android.com/apk/res-auto">
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools">
 
     <LinearLayout
         android:layout_width="match_parent"
@@ -54,167 +54,159 @@
             android:layout_width="match_parent"
             android:layout_height="@dimen/divider_line_space"
             android:background="@color/black" />
-        <androidx.constraintlayout.widget.ConstraintLayout
+
+        <LinearLayout
+            android:id="@+id/base_info_layout"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
+            android:layout_marginHorizontal="@dimen/common_spacing_2x"
+            android:layout_marginTop="@dimen/common_spacing_2x"
             android:layout_weight="1"
-            android:orientation="vertical"
-            android:paddingHorizontal="@dimen/dialog_content_normal_padding_horizontal">
-
-            <TextView
-                android:id="@+id/key_code_tv"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/common_spacing_2x"
-                android:text="@string/key_name"
-                android:textColor="@color/black"
-                android:textSize="@dimen/common_text_size"
-                app:layout_constraintStart_toStartOf="parent"
-                app:layout_constraintTop_toTopOf="parent" />
-
-            <EditText
-                android:id="@+id/key_code_et"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginLeft="@dimen/common_spacing"
-                android:background="@drawable/bg_common_input"
-                android:hint="@string/please_input_key_name"
-                android:maxLines="1"
-                android:paddingHorizontal="@dimen/common_spacing"
-                android:paddingVertical="2dp"
-                android:singleLine="true"
-                android:textColor="@color/black"
-                android:textSize="@dimen/common_text_size"
-                app:layout_constraintBottom_toBottomOf="@+id/key_code_tv"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toEndOf="@+id/key_code_tv"
-                app:layout_constraintTop_toTopOf="@+id/key_code_tv" />
-
-
-            <TextView
-                android:id="@+id/key_nfc_tv"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/common_spacing_2x"
-                android:text="@string/key_nfc"
-                android:textColor="@color/black"
-                android:textSize="@dimen/common_text_size"
-                app:layout_constraintEnd_toEndOf="@+id/key_code_tv"
-                app:layout_constraintTop_toBottomOf="@+id/key_code_tv" />
-
-            <EditText
-                android:id="@+id/key_nfc_et"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginLeft="@dimen/common_spacing"
-                android:background="@drawable/bg_common_input"
-                android:hint="@string/please_input_key_nfc"
-                android:maxLines="1"
-                android:paddingHorizontal="@dimen/common_spacing"
-                android:paddingVertical="2dp"
-                android:singleLine="true"
-                android:textColor="@color/black"
-                android:textSize="@dimen/common_text_size"
-                app:layout_constraintBottom_toBottomOf="@+id/key_nfc_tv"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toEndOf="@+id/key_nfc_tv"
-                app:layout_constraintTop_toTopOf="@+id/key_nfc_tv" />
-
+            android:background="@drawable/home_card_bg"
+            android:gravity="center_vertical"
+            android:orientation="vertical">
 
             <TextView
-                android:id="@+id/key_mac_tv"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/common_spacing_2x"
-                android:text="@string/key_mac"
-                android:textColor="@color/black"
-                android:textSize="@dimen/common_text_size"
-                app:layout_constraintEnd_toEndOf="@+id/key_nfc_tv"
-                app:layout_constraintTop_toBottomOf="@+id/key_nfc_tv" />
-
-            <EditText
-                android:id="@+id/key_mac_et"
-                android:layout_width="0dp"
+                android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_marginLeft="@dimen/common_spacing"
-                android:background="@drawable/bg_common_input"
-                android:hint="@string/please_input_key_mac"
-                android:paddingHorizontal="@dimen/common_spacing"
-                android:paddingVertical="2dp"
+                android:paddingVertical="@dimen/common_spacing_small"
+                android:text="@string/exception_info"
                 android:textColor="@color/black"
-                android:textSize="@dimen/common_text_size"
-                app:layout_constraintBottom_toBottomOf="@+id/key_mac_tv"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toEndOf="@+id/key_mac_tv"
-                app:layout_constraintTop_toTopOf="@+id/key_mac_tv" />
-
+                android:textSize="@dimen/normal_text_size_18" />
 
-            <TextView
-                android:id="@+id/status_tv"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/common_spacing_2x"
-                android:text="@string/manage_filter_status"
-                android:textColor="@color/black"
-                android:textSize="@dimen/common_text_size"
-                app:layout_constraintEnd_toEndOf="@+id/key_mac_tv"
-                app:layout_constraintTop_toBottomOf="@+id/key_mac_tv" />
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="@dimen/divider_line_space"
+                android:background="@color/black" />
 
-            <RadioGroup
-                android:id="@+id/status_rg"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:orientation="horizontal"
-                app:layout_constraintBottom_toBottomOf="@+id/status_tv"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toEndOf="@+id/status_tv"
-                app:layout_constraintTop_toTopOf="@+id/status_tv">
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_weight="1"
+                android:orientation="vertical"
+                android:paddingHorizontal="@dimen/dialog_content_normal_padding_horizontal">
 
-                <RadioButton
-                    android:id="@+id/activate_rb"
+                <TextView
+                    android:id="@+id/exception_type_tv"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/common_spacing_2x"
+                    android:text="@string/exception_type_tv"
+                    android:textColor="@color/black"
+                    android:textSize="@dimen/common_text_size"
+                    app:layout_constraintStart_toStartOf="parent"
+                    app:layout_constraintTop_toTopOf="parent" />
+
+                <TextView
+                    android:id="@+id/exception_type"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
                     android:layout_marginLeft="@dimen/common_spacing"
-                    android:text="@string/normal"
-                    android:textSize="@dimen/common_text_size" />
-
-                <RadioButton
-                    android:id="@+id/deactivate_rb"
+                    android:background="@drawable/bg_common_input"
+                    android:drawableRight="@mipmap/icon_drop_down"
+                    android:hint="@string/please_select_exception_type"
+                    android:maxLines="1"
+                    android:paddingHorizontal="@dimen/common_spacing"
+                    android:paddingVertical="@dimen/common_spacing_small"
+                    android:singleLine="true"
+                    android:textColor="@color/black"
+                    android:textSize="@dimen/common_text_size"
+                    app:layout_constraintBottom_toBottomOf="@+id/exception_type_tv"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toEndOf="@+id/exception_type_tv"
+                    app:layout_constraintTop_toTopOf="@+id/exception_type_tv" />
+
+
+                <TextView
+                    android:id="@+id/exception_source_tv"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/common_spacing_2x"
+                    android:text="@string/exception_source_tv"
+                    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" />
+
+                <TextView
+                    android:id="@+id/exception_source"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
                     android:layout_marginLeft="@dimen/common_spacing"
-                    android:text="@string/abnormal"
-                    android:textSize="@dimen/common_text_size" />
-            </RadioGroup>
-
-
-            <TextView
-                android:id="@+id/remark_tv"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/common_spacing_2x"
-                android:text="@string/remark"
-                android:textColor="@color/black"
-                android:textSize="@dimen/common_text_size"
-                app:layout_constraintEnd_toEndOf="@+id/status_tv"
-                app:layout_constraintTop_toBottomOf="@+id/status_tv" />
-
-            <EditText
-                android:id="@+id/remark_et"
-                android:layout_width="0dp"
-                android:layout_height="wrap_content"
-                android:layout_marginLeft="@dimen/common_spacing"
-                android:background="@drawable/bg_common_input"
-                android:hint="@string/please_input_remark"
-                android:paddingHorizontal="@dimen/common_spacing"
-                android:paddingVertical="2dp"
-                android:textColor="@color/black"
-                android:textSize="@dimen/common_text_size"
-                app:layout_constraintBottom_toBottomOf="@+id/remark_tv"
-                app:layout_constraintEnd_toEndOf="parent"
-                app:layout_constraintStart_toEndOf="@+id/remark_tv"
-                app:layout_constraintTop_toTopOf="@+id/remark_tv" />
-        </androidx.constraintlayout.widget.ConstraintLayout>
+                    android:background="@drawable/bg_common_input"
+                    android:drawableRight="@mipmap/icon_drop_down"
+                    android:hint="@string/please_select_exception_source"
+                    android:maxLines="1"
+                    android:paddingHorizontal="@dimen/common_spacing"
+                    android:paddingVertical="@dimen/common_spacing_small"
+                    android:singleLine="true"
+                    android:textColor="@color/black"
+                    android:textSize="@dimen/common_text_size"
+                    app:layout_constraintBottom_toBottomOf="@+id/exception_source_tv"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toEndOf="@+id/exception_source_tv"
+                    app:layout_constraintTop_toTopOf="@+id/exception_source_tv" />
+
+
+                <TextView
+                    android:id="@+id/exception_description_tv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/common_spacing_2x"
+                    android:text="@string/exception_description_tv"
+                    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" />
+
+                <TextView
+                    android:id="@+id/exception_description"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="@dimen/common_spacing"
+                    android:background="@drawable/bg_common_input"
+                    android:drawableRight="@mipmap/icon_drop_down"
+                    android:hint="@string/please_select_exception_description"
+                    android:paddingHorizontal="@dimen/common_spacing"
+                    android:paddingVertical="@dimen/common_spacing_small"
+                    android:textColor="@color/black"
+                    android:textSize="@dimen/common_text_size"
+                    app:layout_constraintBottom_toBottomOf="@+id/exception_description_tv"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toEndOf="@+id/exception_description_tv"
+                    app:layout_constraintTop_toTopOf="@+id/exception_description_tv" />
+
+
+                <TextView
+                    android:id="@+id/process_application_tv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginTop="@dimen/common_spacing_2x"
+                    android:text="@string/process_application_tv"
+                    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" />
+
+                <TextView
+                    android:id="@+id/process_application"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="@dimen/common_spacing"
+                    android:background="@drawable/bg_common_input"
+                    android:drawableRight="@mipmap/icon_drop_down"
+                    android:hint="@string/please_select_process_application"
+                    android:paddingHorizontal="@dimen/common_spacing"
+                    android:paddingVertical="@dimen/common_spacing_small"
+                    android:textColor="@color/black"
+                    android:textSize="@dimen/common_text_size"
+                    app:layout_constraintBottom_toBottomOf="@+id/process_application_tv"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toEndOf="@+id/process_application_tv"
+                    app:layout_constraintTop_toTopOf="@+id/process_application_tv" />
+            </androidx.constraintlayout.widget.ConstraintLayout>
+        </LinearLayout>
 
         <LinearLayout
             android:layout_width="match_parent"

+ 7 - 0
app/src/main/res/layout/fragment_init_card_registration.xml

@@ -8,6 +8,13 @@
         android:background="@drawable/bg_card_white_r8"
         android:orientation="vertical">
 
+        <View
+            android:id="@+id/empty_focus_view"
+            android:layout_width="1dp"
+            android:layout_height="1dp"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
         <LinearLayout
             android:id="@+id/step_title_layout"
             android:layout_width="wrap_content"

+ 17 - 9
app/src/main/res/layout/fragment_init_point_rfid_registration.xml

@@ -8,6 +8,13 @@
         android:background="@drawable/bg_card_white_r8"
         android:orientation="vertical">
 
+        <View
+            android:id="@+id/empty_focus_view"
+            android:layout_width="1dp"
+            android:layout_height="1dp"
+            app:layout_constraintStart_toStartOf="parent"
+            app:layout_constraintTop_toTopOf="parent" />
+
         <LinearLayout
             android:id="@+id/step_title_layout"
             android:layout_width="wrap_content"
@@ -55,13 +62,13 @@
             android:id="@+id/rv_header_layout"
             android:layout_width="match_parent"
             android:layout_height="40dp"
+            android:layout_marginHorizontal="100dp"
             android:layout_marginTop="@dimen/common_spacing"
             android:background="@drawable/common_card_bg"
             android:divider="@drawable/divider_table"
-            android:layout_marginHorizontal="100dp"
-            app:layout_constraintTop_toBottomOf="@+id/step_hint"
+            android:showDividers="middle"
             app:layout_constraintStart_toStartOf="parent"
-            android:showDividers="middle">
+            app:layout_constraintTop_toBottomOf="@+id/step_hint">
 
             <TextView
                 android:layout_width="0dp"
@@ -79,16 +86,17 @@
                 android:text="@string/operation"
                 android:textSize="@dimen/common_text_size" />
         </LinearLayout>
+
         <androidx.recyclerview.widget.RecyclerView
             android:id="@+id/point_rfid_rv"
             android:layout_width="0dp"
             android:layout_height="0dp"
-            android:layout_marginBottom="@dimen/common_spacing"
             android:layout_marginHorizontal="100dp"
-            app:layout_constraintTop_toBottomOf="@+id/rv_header_layout"
+            android:layout_marginBottom="@dimen/common_spacing"
             app:layout_constraintBottom_toTopOf="@+id/previous_btn"
+            app:layout_constraintEnd_toEndOf="parent"
             app:layout_constraintStart_toStartOf="parent"
-            app:layout_constraintEnd_toEndOf="parent"/>
+            app:layout_constraintTop_toBottomOf="@+id/rv_header_layout" />
 
         <TextView
             android:id="@+id/previous_btn"
@@ -134,14 +142,14 @@
             android:layout_height="wrap_content"
             android:layout_alignParentBottom="true"
             android:layout_centerHorizontal="true"
+            android:layout_marginTop="@dimen/common_spacing"
             android:layout_marginBottom="100dp"
             android:paddingHorizontal="@dimen/common_spacing_2x"
             android:text="@string/skip_and_complete"
             android:textColor="@color/black"
             android:textSize="@dimen/common_btn_text_size"
-            app:layout_constraintTop_toBottomOf="@+id/next_btn"
-            app:layout_constraintStart_toStartOf="@+id/previous_btn"
             app:layout_constraintEnd_toEndOf="@+id/next_btn"
-            android:layout_marginTop="@dimen/common_spacing"/>
+            app:layout_constraintStart_toStartOf="@+id/previous_btn"
+            app:layout_constraintTop_toBottomOf="@+id/next_btn" />
     </androidx.constraintlayout.widget.ConstraintLayout>
 </layout>

+ 8 - 0
app/src/main/res/layout/item_home_text_drop_down.xml

@@ -2,11 +2,19 @@
 <layout xmlns:android="http://schemas.android.com/apk/res/android">
 
     <LinearLayout
+        android:id="@+id/root_layout"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:gravity="center_vertical"
         android:orientation="horizontal">
 
+        <ImageView
+            android:id="@+id/arrow_iv"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/icon_arrow_right"
+            android:visibility="gone" />
+
         <TextView
             android:id="@+id/drop_down_text"
             android:layout_width="0dp"

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

@@ -433,5 +433,14 @@
     <string name="job_execute_title">Job execute</string>
     <string name="exception_lost">Exception lost</string>
     <string name="exception_job">Exception job:</string>
+    <string name="exception_info">Exception info</string>
+    <string name="exception_type_tv">Exception type</string>
+    <string name="please_select_exception_type">Please select exception type</string>
+    <string name="exception_source_tv">Exception source</string>
+    <string name="please_select_exception_source">please exception source</string>
+    <string name="exception_description_tv">Exception description</string>
+    <string name="please_select_exception_description">please select exception description</string>
+    <string name="process_application_tv">Process application</string>
+    <string name="please_select_process_application">please select process application</string>
 
 </resources>

+ 2 - 2
app/src/main/res/values-land/dimens.xml

@@ -4,7 +4,7 @@
     <dimen name="header_padding">10dp</dimen>
     <dimen name="header_logo_width">194dp</dimen>
     <dimen name="header_logo_height">35dp</dimen>
-    <dimen name="header_time_text_size">20sp</dimen>
+    <dimen name="header_time_text_size">28sp</dimen>
     <dimen name="line_height">3dp</dimen>
     <dimen name="login_version_margin">17dp</dimen>
     <dimen name="login_version_text_size">23.8sp</dimen>
@@ -21,7 +21,7 @@
     <dimen name="home_user_icon_size">25dp</dimen>
     <dimen name="home_user_icon_margin">3dp</dimen>
     <dimen name="home_nickname_margin">10dp</dimen>
-    <dimen name="home_nickname_text_size">20sp</dimen>
+    <dimen name="home_nickname_text_size">28sp</dimen>
     <dimen name="home_bottom_nav_size">52dp</dimen>
     <dimen name="home_bottom_nav_text_size">11sp</dimen>
     <dimen name="home_bottom_nav_icon_size">23dp</dimen>

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

@@ -433,5 +433,14 @@
     <string name="job_execute_title">作业执行</string>
     <string name="exception_lost">异常丢失</string>
     <string name="exception_job">异常作业:</string>
+    <string name="exception_info">异常信息</string>
+    <string name="exception_type_tv">异常类型</string>
+    <string name="please_select_exception_type">请选择异常类型</string>
+    <string name="exception_source_tv">异常源</string>
+    <string name="please_select_exception_source">请选择异常源</string>
+    <string name="exception_description_tv">异常描述</string>
+    <string name="please_select_exception_description">请选择异常描述</string>
+    <string name="process_application_tv">处理申请</string>
+    <string name="please_select_process_application">请选择处理申请</string>
 
 </resources>

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

@@ -436,5 +436,14 @@
     <string name="job_execute_title">作业执行</string>
     <string name="exception_lost">异常丢失</string>
     <string name="exception_job">异常作业:</string>
+    <string name="exception_info">异常信息</string>
+    <string name="exception_type_tv">异常类型</string>
+    <string name="please_select_exception_type">请选择异常类型</string>
+    <string name="exception_source_tv">异常源</string>
+    <string name="please_select_exception_source">请选择异常源</string>
+    <string name="exception_description_tv">异常描述</string>
+    <string name="please_select_exception_description">请选择异常描述</string>
+    <string name="process_application_tv">处理申请</string>
+    <string name="please_select_process_application">请选择处理申请</string>
 
 </resources>

+ 6 - 0
data/src/main/java/com/grkj/data/dao/JobTicketDao.kt

@@ -446,4 +446,10 @@ interface JobTicketDao {
      */
     @Query("update is_job_ticket set ticket_status = :ticketStatus,ex_status = :exStatus where ticket_id = :sourceDataId")
     fun updateJobTicketExceptionData(sourceDataId: Long, ticketStatus: String, exStatus: Int?)
+
+    /**
+     * 获取所有进行中的作业
+     */
+    @Query("select * from is_job_ticket where ticket_status in ('1','2','3','4','7')")
+    fun getAllInProgressJob(): List<IsJobTicket>
 }

+ 10 - 0
data/src/main/java/com/grkj/data/data/DictConstants.kt

@@ -78,4 +78,14 @@ object DictConstants {
      * 异常源类型
      */
     const val KEY_EXCEPTION_SOURCE_TYPE = "exception_source_type"
+
+    /**
+     * 异常描述
+     */
+    const val KEY_EXCEPTION_DESCRIPTION = "exception_description"
+
+    /**
+     * 处理申请
+     */
+    const val KEY_EXCEPTION_PROCESS_APPLICATION = "exception_process_application"
 }

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

@@ -92,7 +92,7 @@ enum class CommonDictDataEnum(val dictKey: String, val commonDictRes: List<Commo
         DictConstants.KEY_EXCEPTION_SOURCE_TYPE, listOf(
             SimpleCommonDictRes("钥匙", "0"),
             SimpleCommonDictRes("挂锁", "1"),
-            SimpleCommonDictRes("仓", "2"),
+            SimpleCommonDictRes("仓", "2"),
             SimpleCommonDictRes("作业", "3"),
         )
     ),
@@ -103,6 +103,21 @@ enum class CommonDictDataEnum(val dictKey: String, val commonDictRes: List<Commo
             SimpleCommonDictRes("已取消", "2"),
         )
     ),
+    EXCEPTION_DESCRIPTION(
+        DictConstants.KEY_EXCEPTION_DESCRIPTION, listOf(
+            SimpleCommonDictRes("作业票无法执行", "0"),
+            SimpleCommonDictRes("钥匙损坏", "1"),
+            SimpleCommonDictRes("挂锁损坏", "2"),
+        )
+    ),
+    EXCEPTION_PROCESS_APPLICATION(
+        DictConstants.KEY_EXCEPTION_PROCESS_APPLICATION, listOf(
+            SimpleCommonDictRes("申请万能钥匙", "0"),
+            SimpleCommonDictRes("申请解除作业", "1"),
+            SimpleCommonDictRes("申请报废钥匙", "2"),
+            SimpleCommonDictRes("申请报废挂锁", "3"),
+        )
+    ),
     ;
 
     companion object {

+ 1 - 1
data/src/main/java/com/grkj/data/model/dos/IsLockCabinetSlots.kt

@@ -7,7 +7,7 @@ class IsLockCabinetSlots : BaseBean() {
 
     @PrimaryKey(autoGenerate = true)
     @ColumnInfo(name = "slot_id")
-    var slotId: Int = 0
+    var slotId: Long = 0
 
     @ColumnInfo(name = "slot_code")
     var slotCode: String? = null

+ 10 - 0
data/src/main/java/com/grkj/data/repository/IHardwareRepository.kt

@@ -330,4 +330,14 @@ interface IHardwareRepository {
      * 根据仓位id获取仓位数据
      */
     fun getIsLockCabinetSlotBySlotId(slotId: Long): IsLockCabinetSlots?
+
+    /**
+     * 获取所有锁仓数据
+     */
+    fun getAllSlotsData(): List<IsLockCabinetSlots>
+
+    /**
+     * 获取所有挂锁数据
+     */
+    fun getAllLockInfo(): List<IsLock>
 }

+ 8 - 0
data/src/main/java/com/grkj/data/repository/impl/network/NetworkHardwareRepository.kt

@@ -299,4 +299,12 @@ class NetworkHardwareRepository  @Inject constructor() : BaseRepository(), IHard
     override fun getIsLockCabinetSlotBySlotId(slotId: Long): IsLockCabinetSlots? {
         TODO("Not yet implemented")
     }
+
+    override fun getAllSlotsData(): List<IsLockCabinetSlots> {
+        TODO("Not yet implemented")
+    }
+
+    override fun getAllLockInfo(): List<IsLock> {
+        TODO("Not yet implemented")
+    }
 }

+ 9 - 0
data/src/main/java/com/grkj/data/repository/impl/network/NetworkJobTicketRepository.kt

@@ -1,5 +1,6 @@
 package com.grkj.data.repository.impl.network
 
+import com.grkj.data.model.dos.IsJobTicket
 import com.grkj.data.model.dos.IsJobTicketStep
 import com.grkj.data.model.req.LockPointUpdateReq
 import com.grkj.data.model.res.StepDetailRes
@@ -55,6 +56,10 @@ class NetworkJobTicketRepository  @Inject constructor() : BaseRepository(), IJob
         TODO("Not yet implemented")
     }
 
+    override fun getTicketDetail(ticketId: Long): TicketDetailRes? {
+        TODO("Not yet implemented")
+    }
+
     override fun deleteTicketByTicketIds(ticketIds: List<Long>) {
         TODO("Not yet implemented")
     }
@@ -152,6 +157,10 @@ class NetworkJobTicketRepository  @Inject constructor() : BaseRepository(), IJob
         TODO("Not yet implemented")
     }
 
+    override fun getAllInProgressJob(): List<IsJobTicket> {
+        TODO("Not yet implemented")
+    }
+
     override fun getLockedPointsData(
         current: Int,
         size: Int

+ 8 - 0
data/src/main/java/com/grkj/data/repository/impl/standard/HardwareRepository.kt

@@ -498,4 +498,12 @@ class HardwareRepository @Inject constructor(
     override fun getIsLockCabinetSlotBySlotId(slotId: Long): IsLockCabinetSlots? {
         return hardwareDao.getIsLockCabinetSlotBySlotId(slotId)
     }
+
+    override fun getAllSlotsData(): List<IsLockCabinetSlots> {
+        return hardwareDao.getAllLockCabinetSlots()
+    }
+
+    override fun getAllLockInfo(): List<IsLock> {
+        return hardwareDao.getAllLockData()
+    }
 }

+ 5 - 1
ui-base/src/main/java/com/grkj/ui_base/business/BleBusinessManager.kt

@@ -749,7 +749,11 @@ object BleBusinessManager {
                     ModbusBusinessManager.removeDeviceTake(
                         DeviceConst.DEVICE_TYPE_KEY, deviceTakeUpdateBO.nfc
                     )
-                    ModbusBusinessManager.checkEquipCount(0, true) { keyPair, lockMap ->
+                    ModbusBusinessManager.checkEquipCount(
+                        deviceTakeUpdateBO.ticketId,
+                        0,
+                        true
+                    ) { keyPair, lockMap ->
                         if (keyPair == null) {
                             TipDialog.show(
                                 msg = CommonUtils.getStr(R.string.key_take_error_tip).toString(),

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

@@ -4,23 +4,20 @@ import com.clj.fastble.BleManager
 import com.grkj.data.di.RepositoryManager
 import com.grkj.data.model.res.CabinetSlotsRecord
 import com.grkj.shared.utils.extension.isPureZero
+import com.grkj.shared.utils.extension.removeLeadingZeros
+import com.grkj.shared.utils.extension.toHexStrings
 import com.grkj.ui_base.R
 import com.grkj.ui_base.config.ISCSConfig
 import com.grkj.ui_base.utils.CommonUtils
 import com.grkj.ui_base.utils.Executor
 import com.grkj.ui_base.utils.ble.BleConnectionManager
 import com.grkj.ui_base.utils.event.ModbusInitCompleteEvent
-import com.grkj.shared.utils.extension.removeLeadingZeros
-import com.grkj.shared.utils.extension.toHexStrings
-import com.grkj.ui_base.business.ModbusBusinessManager
-import com.grkj.ui_base.utils.event.StartModbusEvent
 import com.kongzue.dialogx.dialogs.PopTip
 import com.sik.sikcore.thread.ThreadUtils
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 import java.util.concurrent.atomic.AtomicInteger
 import java.util.stream.Collectors
-import kotlin.collections.copyOfRange
 
 
 /**
@@ -269,6 +266,21 @@ object ModBusController {
                                     }
                                     controlKeyBuckle(true, key.idx, dockBean.addr)
                                 }
+                                val isKeyReady =
+                                    dockList.filter { it.type == DeviceConst.DOCK_TYPE_KEY || it.type == DeviceConst.DOCK_TYPE_PORTABLE }
+                                        .all {
+                                            it.deviceList.filter { it.type == DeviceConst.DEVICE_TYPE_KEY }
+                                                .filterIsInstance<DockBean.KeyBean>()
+                                                .filter { it.isExist }
+                                                .all {
+                                                    logger.info("钥匙否是准备完毕:${it.rfid}")
+                                                    it.rfid != null
+                                                }
+                                        }
+                                if (isKeyReady && !ISCSConfig.isInit) {
+                                    ISCSConfig.canInitDevice = true
+                                    ModbusInitCompleteEvent.sendModbusInitCompleteEvent()
+                                }
                             }
                         }
                     } else {
@@ -276,10 +288,6 @@ object ModBusController {
                     }
                 }
             }
-        if (!ISCSConfig.isInit) {
-            ISCSConfig.canInitDevice = true
-            ModbusInitCompleteEvent.sendModbusInitCompleteEvent()
-        }
     }
 
     /**