ソースを参照

refactor(更新)
- 完成异常管理和异常详情

周文健 4 ヶ月 前
コミット
86a7d0640f
29 ファイル変更603 行追加48 行削除
  1. BIN
      app/src/main/assets/data.db
  2. 5 0
      app/src/main/java/com/grkj/iscs/common/DataTransferConstants.kt
  3. 15 8
      app/src/main/java/com/grkj/iscs/features/main/dialog/data_manage/UpdateUserDialog.kt
  4. 59 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionDetailFragment.kt
  5. 53 7
      app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionManageFragment.kt
  6. 4 3
      app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionManageHomeFragment.kt
  7. 2 1
      app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionReportFragment.kt
  8. 11 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/user_info/SetFingerprintFragment.kt
  9. 95 3
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/exception_manage/ExceptionViewModel.kt
  10. 32 0
      app/src/main/res/layout/fragment_exception_manage.xml
  11. 55 1
      app/src/main/res/layout/fragment_exception_report.xml
  12. 39 1
      app/src/main/res/navigation/nav_exception_manage.xml
  13. 9 1
      app/src/main/res/navigation/nav_job_manage.xml
  14. 6 0
      app/src/main/res/values-en/strings.xml
  15. 6 0
      app/src/main/res/values-zh/strings.xml
  16. 6 0
      app/src/main/res/values/strings.xml
  17. 17 0
      data/src/main/java/com/grkj/data/dao/ExceptionDao.kt
  18. 21 15
      data/src/main/java/com/grkj/data/dao/HardwareDao.kt
  19. 9 0
      data/src/main/java/com/grkj/data/dao/JobTicketDao.kt
  20. 5 0
      data/src/main/java/com/grkj/data/data/DictConstants.kt
  21. 9 0
      data/src/main/java/com/grkj/data/enums/CommonDictDataEnum.kt
  22. 6 3
      data/src/main/java/com/grkj/data/model/dos/IsExceptionSourceStandard.kt
  23. 7 0
      data/src/main/java/com/grkj/data/model/dos/IsExceptionStandard.kt
  24. 16 4
      data/src/main/java/com/grkj/data/model/vo/IsExceptionStandardVo.kt
  25. 16 0
      data/src/main/java/com/grkj/data/repository/IExceptionRepository.kt
  26. 15 0
      data/src/main/java/com/grkj/data/repository/IHardwareRepository.kt
  27. 12 0
      data/src/main/java/com/grkj/data/repository/impl/network/NetworkExceptionRepository.kt
  28. 61 1
      data/src/main/java/com/grkj/data/repository/impl/standard/ExceptionRepository.kt
  29. 12 0
      data/src/main/java/com/grkj/data/repository/impl/standard/HardwareRepository.kt

BIN
app/src/main/assets/data.db


+ 5 - 0
app/src/main/java/com/grkj/iscs/common/DataTransferConstants.kt

@@ -47,4 +47,9 @@ object DataTransferConstants {
      * SOP作业需要再携带SopId
      */
     const val KEY_JOB_TICKET_ID = "key_job_ticket_id"
+
+    /**
+     * 异常数据
+     */
+    const val KEY_EXCEPTION_DATA = "key_exception_data"
 }

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

@@ -41,6 +41,7 @@ class UpdateUserDialog(
         binding.workstationNameTv.isVisible = ISCSConfig.isWorkstationOn
 
         binding.cardcodeEt.isEnabled = false
+        binding.usernameEt.isEnabled = false
 
         // 预填数据
         binding.nicknameEt.setText(userVo.nickName)
@@ -52,11 +53,12 @@ class UpdateUserDialog(
 
         // 标记已选
         selectedRoles = roleData.filter { it.getShowText() in userVo.roleNames }.toMutableList()
-        selectedWorkstations = workstationData.filter { it.getShowText() in userVo.workstationNames }.toMutableList()
+        selectedWorkstations =
+            workstationData.filter { it.getShowText() in userVo.workstationNames }.toMutableList()
 
         // 角色多选
         binding.roleTv.setOnClickListener {
-            TextDropDownDialog.showMulti(roleData,binding.roleTv) { list ->
+            TextDropDownDialog.showMulti(roleData, binding.roleTv) { list ->
                 selectedRoles = list.orEmpty().toMutableList()
                 binding.roleTv.text = selectedRoles.joinToString(",") { it.getShowText() }
             }
@@ -64,9 +66,10 @@ class UpdateUserDialog(
 
         // 工作站多选
         binding.workstationNameTv.setOnClickListener {
-            TextDropDownDialog.showMulti(workstationData,binding.workstationNameTv) { list ->
+            TextDropDownDialog.showMulti(workstationData, binding.workstationNameTv) { list ->
                 selectedWorkstations = list.orEmpty().toMutableList()
-                binding.workstationNameTv.text = selectedWorkstations.joinToString(",") { it.getShowText() }
+                binding.workstationNameTv.text =
+                    selectedWorkstations.joinToString(",") { it.getShowText() }
             }
         }
 
@@ -79,10 +82,14 @@ class UpdateUserDialog(
             val username = binding.usernameEt.text.trim().toString()
             val name = binding.nicknameEt.text.trim().toString()
             val card = binding.cardcodeEt.text.trim().toString()
-            if (name.isBlank()) return@setOnClickListener PopTip.build().tipDialog(R.string.please_input_nickname)
-            if (card.isBlank()) return@setOnClickListener PopTip.build().tipDialog(R.string.please_input_card_code)
-            if (selectedRoles.isEmpty()) return@setOnClickListener PopTip.build().tipDialog(R.string.please_select_role)
-            if (ISCSConfig.isWorkstationOn && selectedWorkstations.isEmpty()) return@setOnClickListener PopTip.build().tipDialog(R.string.please_select_area)
+            if (name.isBlank()) return@setOnClickListener PopTip.build()
+                .tipDialog(R.string.please_input_nickname)
+            if (card.isBlank()) return@setOnClickListener PopTip.build()
+                .tipDialog(R.string.please_input_card_code)
+            if (selectedRoles.isEmpty()) return@setOnClickListener PopTip.build()
+                .tipDialog(R.string.please_select_role)
+            if (ISCSConfig.isWorkstationOn && selectedWorkstations.isEmpty()) return@setOnClickListener PopTip.build()
+                .tipDialog(R.string.please_select_area)
             val isActive = binding.statusRg.checkedRadioButtonId == binding.activateRb.id
             val updateVo = UpdateUserDataVo(
                 userVo.userId,

+ 59 - 0
app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionDetailFragment.kt

@@ -1,10 +1,16 @@
 package com.grkj.iscs.features.main.fragment.exception_manage
 
+import androidx.core.view.isVisible
 import androidx.fragment.app.viewModels
+import com.grkj.data.model.vo.IsExceptionStandardVo
 import com.grkj.iscs.R
+import com.grkj.iscs.common.DataTransferConstants
 import com.grkj.iscs.databinding.FragmentExceptionDetailBinding
 import com.grkj.iscs.features.main.viewmodel.exception_manage.ExceptionViewModel
 import com.grkj.ui_base.base.BaseFragment
+import com.grkj.ui_base.dialog.TipDialog
+import com.sik.sikcore.data.GlobalDataTempStore
+import com.sik.sikcore.extension.setDebouncedClickListener
 import dagger.hilt.android.AndroidEntryPoint
 
 /**
@@ -18,6 +24,59 @@ class ExceptionDetailFragment : BaseFragment<FragmentExceptionDetailBinding>() {
     }
 
     override fun initView() {
+        binding.back.setDebouncedClickListener { navController.popBackStack() }
+        binding.handleException.setDebouncedClickListener {
+            viewModel.handleException().observe(this) {
+                if (it.first) {
+                    TipDialog.showSuccess(
+                        getString(R.string.handle_exception_success),
+                        onConfirmClick = {
+                            binding.handleException.isVisible = false
+                            binding.cancelException.isVisible = false
+                        },
+                        onCancelClick = {
+                            binding.handleException.isVisible = false
+                            binding.cancelException.isVisible = false
+                        })
+                } else {
+                    TipDialog.showError(it.second)
+                }
+            }
+        }
+        binding.cancelException.setDebouncedClickListener {
+            viewModel.cancelException().observe(this) {
+                if (it) {
+                    TipDialog.showSuccess(
+                        getString(R.string.cancel_exception_success),
+                        onConfirmClick = {
+                            binding.handleException.isVisible = false
+                            binding.cancelException.isVisible = false
+                        },
+                        onCancelClick = {
+                            binding.handleException.isVisible = false
+                            binding.cancelException.isVisible = false
+                        })
+                } else {
+                    TipDialog.showError(getString(R.string.cancel_exception_failed))
+                }
+            }
+        }
+    }
 
+    override fun initData() {
+        super.initData()
+        viewModel.exceptionData = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_EXCEPTION_DATA) as IsExceptionStandardVo
+        viewModel.getDictData().observe(this) {
+            viewModel.getExceptionSourceName().observe(this) {
+                binding.exceptionType.text =
+                    viewModel.exceptionType.find { it.dictValue == viewModel.exceptionData?.exceptionType.toString() }?.dictLabel
+                binding.exceptionSource.text = it
+                binding.exceptionReporter.text = viewModel.exceptionData?.userData?.nickName
+                binding.exceptionOccurrenceTime.text = viewModel.exceptionData?.occurrenceTime
+                binding.exceptionReleaseTime.text = viewModel.exceptionData?.releaseTime
+                binding.exceptionDescription.text = viewModel.exceptionData?.exceptionDescription?.joinToString(",")
+            }
+        }
     }
 }

+ 53 - 7
app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionManageFragment.kt

@@ -6,15 +6,19 @@ import com.drake.brv.BindingAdapter
 import com.drake.brv.annotaion.DividerOrientation
 import com.drake.brv.utils.divider
 import com.drake.brv.utils.linear
+import com.drake.brv.utils.models
 import com.drake.brv.utils.setup
-import com.grkj.data.data.DictConstants
 import com.grkj.data.model.vo.IsExceptionStandardVo
 import com.grkj.iscs.R
+import com.grkj.iscs.common.DataTransferConstants
 import com.grkj.iscs.databinding.FragmentExceptionManageBinding
 import com.grkj.iscs.databinding.ItemExceptionManageBinding
 import com.grkj.iscs.features.main.viewmodel.exception_manage.ExceptionViewModel
 import com.grkj.ui_base.base.BaseFragment
-import com.grkj.ui_base.business.DataBusiness
+import com.grkj.ui_base.dialog.TipDialog
+import com.kongzue.dialogx.dialogs.PopTip
+import com.sik.sikcore.data.GlobalDataTempStore
+import com.sik.sikcore.extension.setDebouncedClickListener
 
 /**
  * 异常管理界面
@@ -26,6 +30,21 @@ class ExceptionManageFragment : BaseFragment<FragmentExceptionManageBinding>() {
     }
 
     override fun initView() {
+        binding.back.setDebouncedClickListener { navController.popBackStack() }
+        binding.oneKeyHandle.setDebouncedClickListener {
+            viewModel.handleSelectedException().observe(this) {
+                if (it.first) {
+                    TipDialog.showSuccess(getString(R.string.handle_exception_success))
+                } else {
+                    TipDialog.showError(it.second)
+                }
+            }
+        }
+        binding.oneKeyCancel.setDebouncedClickListener {
+            viewModel.cancelSelectedException().observe(this) {
+                TipDialog.showSuccess(getString(R.string.cancel_exception_success))
+            }
+        }
         binding.listRv.linear().divider {
             this.setColor(Color.BLACK)
             this.startVisible = false
@@ -37,23 +56,50 @@ class ExceptionManageFragment : BaseFragment<FragmentExceptionManageBinding>() {
                 onRVListBinding(this)
             }
         }
+        setSelectAllListener()
     }
 
-    override fun initData() {
-        super.initData()
-
+    override fun onResume() {
+        super.onResume()
+        getData()
     }
 
     private fun getData() {
+        viewModel.getDictData().observe(this) {
+            viewModel.getExceptionData().observe(this) {
+                binding.listRv.models = viewModel.exceptionDataList
+            }
+        }
+    }
 
+    private fun setSelectAllListener() {
+        binding.selectAll.setOnCheckedChangeListener { v, checked ->
+            viewModel.exceptionDataList.forEach { it.isSelected = checked }
+            binding.listRv.adapter?.notifyDataSetChanged()
+        }
     }
 
     private fun onRVListBinding(holder: BindingAdapter.BindingViewHolder) {
         val itemBinding = holder.getBinding<ItemExceptionManageBinding>()
         val item = holder.getModel<IsExceptionStandardVo>()
-        itemBinding.exceptionType.text = DataBusiness.fetchDict(DictConstants.KEY_EXCEPTION_TYPE)
+        itemBinding.exceptionType.text = viewModel.exceptionType
             .find { it.dictValue == item.exceptionType.toString() }?.dictLabel
 
-
+        itemBinding.exceptionStatus.text =
+            viewModel.exceptionStatus.find { it.dictValue == item.exceptionStatus.toString() }?.dictLabel
+        itemBinding.exceptionOccurrenceTime.text = item.createTime
+        itemBinding.select.setOnCheckedChangeListener(null)
+        itemBinding.select.isSelected = item.isSelected
+        itemBinding.select.setOnCheckedChangeListener { _, checked ->
+            item.isSelected = checked
+            binding.selectAll.setOnCheckedChangeListener(null)
+            binding.selectAll.isChecked = viewModel.exceptionDataList.all { it.isSelected }
+            setSelectAllListener()
+        }
+        itemBinding.root.setDebouncedClickListener {
+            GlobalDataTempStore.getInstance()
+                .saveData(DataTransferConstants.KEY_EXCEPTION_DATA, item)
+            navController.navigate(R.id.action_exceptionManageFragment_to_exceptionDetailFragment)
+        }
     }
 }

+ 4 - 3
app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionManageHomeFragment.kt

@@ -43,6 +43,7 @@ class ExceptionManageHomeFragment : BaseFragment<FragmentExceptionManageHomeBind
             RoleFunctionalPermissionsEnum.EXCEPTION_JOB.functionalPermission
         ),
     )
+
     override fun getLayoutId(): Int {
         return R.layout.fragment_exception_manage_home
     }
@@ -89,15 +90,15 @@ class ExceptionManageHomeFragment : BaseFragment<FragmentExceptionManageHomeBind
         BottomNavVisibilityEvent.sendBottomNavVisibilityEvent(false)
         when (menuType) {
             0 -> {
-
+                navController.navigate(R.id.action_exceptionManageHomeFragment_to_exceptionReportFragment)
             }
 
             1 -> {
-
+                navController.navigate(R.id.action_exceptionManageHomeFragment_to_exceptionManageFragment)
             }
 
             2 -> {
-
+                navController.navigate(R.id.action_exceptionManageHomeFragment_to_exceptionJobManageFragment2)
             }
         }
     }

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

@@ -3,6 +3,7 @@ package com.grkj.iscs.features.main.fragment.exception_manage
 import com.grkj.iscs.R
 import com.grkj.iscs.databinding.FragmentExceptionReportBinding
 import com.grkj.ui_base.base.BaseFragment
+import com.sik.sikcore.extension.setDebouncedClickListener
 
 /**
  * 异常上报界面
@@ -13,6 +14,6 @@ class ExceptionReportFragment : BaseFragment<FragmentExceptionReportBinding>() {
     }
 
     override fun initView() {
-
+        binding.back.setDebouncedClickListener { navController.popBackStack() }
     }
 }

+ 11 - 0
app/src/main/java/com/grkj/iscs/features/main/fragment/user_info/SetFingerprintFragment.kt

@@ -131,9 +131,20 @@ class SetFingerprintFragment : BaseFragment<FragmentSetFingerprintBinding>() {
                 itemBinding.select.isChecked = item.isSelected
                 itemBinding.select.setOnCheckedChangeListener { _, checked ->
                     item.isSelected = checked
+                    binding.selectAll.setOnCheckedChangeListener(null)
+                    binding.selectAll.isChecked = viewModel.sysBiometricDataVo.all { it.isSelected }
+                    setSelectAllListener()
                 }
             }
         }
+        setSelectAllListener()
+    }
+
+    private fun setSelectAllListener() {
+        binding.selectAll.setOnCheckedChangeListener { v, checked ->
+            viewModel.sysBiometricDataVo.forEach { it.isSelected = checked }
+            binding.listRv.adapter?.notifyDataSetChanged()
+        }
     }
 
     override fun initData() {

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

@@ -2,11 +2,20 @@ 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.data.model.vo.IsExceptionStandardVo
+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
+import com.grkj.ui_base.utils.CommonUtils
 import dagger.hilt.android.lifecycle.HiltViewModel
 import kotlinx.coroutines.Dispatchers
 import javax.inject.Inject
@@ -16,7 +25,9 @@ import javax.inject.Inject
  */
 @HiltViewModel
 class ExceptionViewModel @Inject constructor(
-
+    val exceptionRepository: IExceptionRepository,
+    val hardwareRepository: IHardwareRepository,
+    val jobTicketRepository: IJobTicketRepository
 ) : BaseViewModel() {
     /**
      * 异常类型
@@ -33,6 +44,11 @@ class ExceptionViewModel @Inject constructor(
      */
     var exceptionDataList: List<IsExceptionStandardVo> = listOf()
 
+    /**
+     * 异常数据
+     */
+    var exceptionData: IsExceptionStandardVo? = null
+
     /**
      * 获取字典数据
      */
@@ -47,9 +63,85 @@ class ExceptionViewModel @Inject constructor(
     /**
      * 获取异常数据
      */
-    fun getExceptionData(): LiveData<Boolean>{
-        return liveData(Dispatchers.IO){
+    fun getExceptionData(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            exceptionDataList = exceptionRepository.getExceptionData()
+            emit(true)
+        }
+    }
 
+    /**
+     * 处理选中异常
+     */
+    fun handleSelectedException(): LiveData<Pair<Boolean, String>> {
+        return liveData(Dispatchers.IO) {
+            exceptionRepository.handleException(exceptionDataList.filter { it.isSelected })
+            emit(true to "")
+        }
+    }
+
+    /**
+     * 处理选中异常
+     */
+    fun handleException(): LiveData<Pair<Boolean, String>> {
+        return liveData(Dispatchers.IO) {
+            exceptionData?.let {
+                exceptionRepository.handleException(listOf(it))
+                emit(true to "")
+            } ?: emit(false to CommonUtils.getStr(R.string.exception_data_not_exists).toString())
+        }
+    }
+
+    /**
+     * 取消选中异常
+     */
+    fun cancelSelectedException(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            exceptionRepository.cancelException(exceptionDataList.filter { it.isSelected })
+            emit(true)
+        }
+    }
+
+    /**
+     * 取消选中异常
+     */
+    fun cancelException(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            exceptionData?.let {
+                exceptionRepository.cancelException(listOf(it))
+                emit(true)
+            } ?: emit(false)
+        }
+    }
+
+    /**
+     * 获取异常源名称
+     */
+    fun getExceptionSourceName(): LiveData<String> {
+        return liveData(Dispatchers.IO) {
+            val sourceName = exceptionData?.sourceData?.map {
+                when (it.sourceDataType) {
+                    //钥匙
+                    0 -> {
+                        "钥匙:${hardwareRepository.getKeyInfoByKeyId(it.sourceDataId)?.keyNfc}"
+                    }
+                    //挂锁
+                    1 -> {
+                        "挂锁:${hardwareRepository.getLockInfoByLockId(it.sourceDataId)?.lockNfc}"
+                    }
+                    //仓位
+                    2 -> {
+                        val slotData =
+                            hardwareRepository.getIsLockCabinetSlotBySlotId(it.sourceDataId)
+                        "仓位:${slotData?.row}-${slotData?.col}"
+                    }
+                    //作业
+                    3 -> {
+                        "作业:${jobTicketRepository.getTicketDataByTicketId(it.sourceDataId)?.ticketName}"
+                    }
+                }
+            }?.joinToString(",")
+            emit(sourceName.toString())
         }
     }
 }

+ 32 - 0
app/src/main/res/layout/fragment_exception_manage.xml

@@ -54,6 +54,38 @@
             android:layout_height="@dimen/divider_line_space"
             android:background="@color/black" />
 
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:paddingHorizontal="@dimen/common_spacing"
+            android:paddingVertical="@dimen/common_spacing">
+
+
+            <TextView
+                android:id="@+id/one_key_handle"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/common_spacing"
+                android:background="@drawable/common_btn"
+                android:paddingHorizontal="@dimen/common_spacing_2x"
+                android:text="@string/one_key_handle"
+                android:textColor="@color/black"
+                android:textSize="@dimen/common_btn_text_size" />
+
+
+            <TextView
+                android:id="@+id/one_key_cancel"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/common_spacing"
+                android:background="@drawable/common_btn"
+                android:paddingHorizontal="@dimen/common_spacing_2x"
+                android:text="@string/one_key_cancel"
+                android:textColor="@color/black"
+                android:textSize="@dimen/common_btn_text_size" />
+        </LinearLayout>
+
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"

+ 55 - 1
app/src/main/res/layout/fragment_exception_report.xml

@@ -1,4 +1,58 @@
 <?xml version="1.0" encoding="utf-8"?>
-<layout xmlns:android="http://schemas.android.com/apk/res/android">
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools">
 
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_margin="@dimen/common_spacing_2x"
+        android:background="@drawable/home_card_bg"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:id="@+id/title_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            android:paddingHorizontal="@dimen/common_spacing">
+
+            <ImageView
+                android:layout_width="@dimen/title_icon_size"
+                android:layout_height="@dimen/title_icon_size"
+                android:src="@mipmap/icon_data_manage_menu_user_manage" />
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/common_spacing"
+                android:layout_weight="1"
+                android:text="@string/exception_report"
+                android:textColor="@color/black"
+                android:textSize="@dimen/normal_text_size_25"
+                android:textStyle="bold" />
+
+            <TextView
+                android:id="@+id/back"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginVertical="5dp"
+                android:layout_marginLeft="@dimen/common_spacing"
+                android:background="@drawable/common_btn"
+                android:drawableLeft="@mipmap/icon_back"
+                android:drawablePadding="@dimen/common_spacing"
+                android:gravity="center"
+                android:minHeight="@dimen/common_btn_height"
+                android:paddingHorizontal="@dimen/common_spacing_2x"
+                android:text="@string/back"
+                android:textColor="@color/black"
+                android:textSize="@dimen/common_btn_text_size" />
+        </LinearLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/divider_line_space"
+            android:background="@color/black" />
+
+    </LinearLayout>
 </layout>

+ 39 - 1
app/src/main/res/navigation/nav_exception_manage.xml

@@ -7,5 +7,43 @@
     <fragment
         android:id="@+id/exceptionManageHomeFragment"
         android:name="com.grkj.iscs.features.main.fragment.exception_manage.ExceptionManageHomeFragment"
-        android:label="ExceptionManageHomeFragment" />
+        android:label="ExceptionManageHomeFragment" >
+        <action
+            android:id="@+id/action_exceptionManageHomeFragment_to_exceptionManageFragment"
+            app:destination="@id/exceptionManageFragment" />
+        <action
+            android:id="@+id/action_exceptionManageHomeFragment_to_exceptionReportFragment"
+            app:destination="@id/exceptionReportFragment" />
+        <action
+            android:id="@+id/action_exceptionManageHomeFragment_to_exceptionJobManageFragment2"
+            app:destination="@id/exceptionJobManageFragment2" />
+    </fragment>
+    <fragment
+        android:id="@+id/exceptionManageFragment"
+        android:name="com.grkj.iscs.features.main.fragment.exception_manage.ExceptionManageFragment"
+        android:label="ExceptionManageFragment" >
+        <action
+            android:id="@+id/action_exceptionManageFragment_to_exceptionDetailFragment"
+            app:destination="@id/exceptionDetailFragment" />
+    </fragment>
+    <fragment
+        android:id="@+id/exceptionReportFragment"
+        android:name="com.grkj.iscs.features.main.fragment.exception_manage.ExceptionReportFragment"
+        android:label="ExceptionReportFragment" />
+    <fragment
+        android:id="@+id/exceptionDetailFragment"
+        android:name="com.grkj.iscs.features.main.fragment.exception_manage.ExceptionDetailFragment"
+        android:label="ExceptionDetailFragment" />
+    <fragment
+        android:id="@+id/exceptionJobFragment"
+        android:name="com.grkj.iscs.features.main.fragment.exception_manage.ExceptionJobFragment"
+        android:label="ExceptionJobFragment" />
+    <fragment
+        android:id="@+id/exceptionJobManageFragment2"
+        android:name="com.grkj.iscs.features.main.fragment.job_manage.ExceptionJobManageFragment"
+        android:label="ExceptionJobManageFragment" >
+        <action
+            android:id="@+id/action_exceptionJobManageFragment2_to_exceptionJobFragment"
+            app:destination="@id/exceptionJobFragment" />
+    </fragment>
 </navigation>

+ 9 - 1
app/src/main/res/navigation/nav_job_manage.xml

@@ -184,9 +184,17 @@
     <fragment
         android:id="@+id/exceptionJobManageFragment"
         android:name="com.grkj.iscs.features.main.fragment.job_manage.ExceptionJobManageFragment"
-        android:label="ExceptionJobManageFragment" />
+        android:label="ExceptionJobManageFragment" >
+        <action
+            android:id="@+id/action_exceptionJobManageFragment_to_exceptionJobFragment2"
+            app:destination="@id/exceptionJobFragment2" />
+    </fragment>
     <fragment
         android:id="@+id/workflowSettingFragment"
         android:name="com.grkj.iscs.features.main.fragment.common.WorkflowSettingFragment"
         android:label="WorkflowSettingFragment" />
+    <fragment
+        android:id="@+id/exceptionJobFragment2"
+        android:name="com.grkj.iscs.features.main.fragment.exception_manage.ExceptionJobFragment"
+        android:label="ExceptionJobFragment" />
 </navigation>

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

@@ -424,5 +424,11 @@
     <string name="exception_type_header">Exception type</string>
     <string name="exception_status_header">Exception status</string>
     <string name="exception_occurrence_time_header">Occurrence time</string>
+    <string name="one_key_handle">Processing</string>
+    <string name="one_key_cancel">Cancel</string>
+    <string name="cancel_exception_success">Cancel exception success</string>
+    <string name="handle_exception_success">Handle exception success</string>
+    <string name="exception_data_not_exists">Exception data not exists</string>
+    <string name="cancel_exception_failed">Cancel exception failed</string>
 
 </resources>

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

@@ -424,5 +424,11 @@
     <string name="exception_type_header">异常类型</string>
     <string name="exception_status_header">异常状态</string>
     <string name="exception_occurrence_time_header">发生时间</string>
+    <string name="one_key_handle">一键处理</string>
+    <string name="one_key_cancel">一键取消</string>
+    <string name="cancel_exception_success">异常取消成功</string>
+    <string name="handle_exception_success">异常处理成功</string>
+    <string name="exception_data_not_exists">异常数据不存在</string>
+    <string name="cancel_exception_failed">取消异常失败</string>
 
 </resources>

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

@@ -427,5 +427,11 @@
     <string name="exception_type_header">异常类型</string>
     <string name="exception_status_header">异常状态</string>
     <string name="exception_occurrence_time_header">发生时间</string>
+    <string name="one_key_handle">一键处理</string>
+    <string name="one_key_cancel">一键取消</string>
+    <string name="cancel_exception_success">异常取消成功</string>
+    <string name="handle_exception_success">异常处理成功</string>
+    <string name="exception_data_not_exists">异常数据不存在</string>
+    <string name="cancel_exception_failed">取消异常失败</string>
 
 </resources>

+ 17 - 0
data/src/main/java/com/grkj/data/dao/ExceptionDao.kt

@@ -1,10 +1,27 @@
 package com.grkj.data.dao
 
 import androidx.room.Dao
+import androidx.room.Query
+import androidx.room.Transaction
+import androidx.room.Update
+import com.grkj.data.model.dos.IsExceptionStandard
+import com.grkj.data.model.vo.IsExceptionStandardVo
 
 /**
  * 异常数据库
  */
 @Dao
 interface ExceptionDao {
+    /**
+     * 更新异常数据
+     */
+    @Update
+    fun updateException(exceptionData: List<IsExceptionStandard>?)
+
+    /**
+     * 获取异常数据
+     */
+    @Transaction
+    @Query("select * from is_exception_standard")
+    fun getExceptionData(): List<IsExceptionStandardVo>
 }

+ 21 - 15
data/src/main/java/com/grkj/data/dao/HardwareDao.kt

@@ -319,11 +319,7 @@ interface HardwareDao {
     """
     )
     fun getLockInfoPage(
-        lockCode: String?,
-        lockNfc: String?,
-        exStatus: Int?,
-        size: Int,
-        offset: Int
+        lockCode: String?, lockNfc: String?, exStatus: Int?, size: Int, offset: Int
     ): List<IsLock>
 
     /**
@@ -341,11 +337,7 @@ interface HardwareDao {
     """
     )
     fun getCardInfoPage(
-        cardNfc: String?,
-        nickname: String?,
-        exStatus: Int?,
-        size: Int,
-        offset: Int
+        cardNfc: String?, nickname: String?, exStatus: Int?, size: Int, offset: Int
     ): List<IsJobCard>
 
     /**
@@ -362,11 +354,7 @@ interface HardwareDao {
     """
     )
     fun getRfidTokenInfoPage(
-        rfidTokenCode: String?,
-        rfid: String?,
-        status: Int?,
-        size: Int,
-        offset: Int
+        rfidTokenCode: String?, rfid: String?, status: Int?, size: Int, offset: Int
     ): List<IsRfidToken>
 
     /**
@@ -471,4 +459,22 @@ interface HardwareDao {
     @Query("update is_lock set ex_status = :exStatus,remark = null where lock_nfc = :rfid")
     fun removeLockException(rfid: String?, exStatus: String?)
 
+    /**
+     * 根据钥匙id获取钥匙信息
+     */
+    @Query("select * from is_key where key_id = :keyId")
+    fun getKeyInfoById(keyId: Long): IsKey?
+
+    /**
+     * 根据挂锁id获取挂锁信息
+     */
+    @Query("select * from is_lock where lock_id = :lockId")
+    fun getLockInfoById(lockId: Long): IsLock?
+
+    /**
+     * 根据仓位id获取仓位数据
+     */
+    @Query("select * from is_lock_cabinet_slots where slot_id = :slotId")
+    fun getIsLockCabinetSlotBySlotId(slotId: Long): IsLockCabinetSlots?
+
 }

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

@@ -431,6 +431,15 @@ interface JobTicketDao {
         ticketId: Long
     ): List<IsJobTicketPoints>
 
+    /**
+     * 更新作业票步骤数据
+     */
     @Update
     fun updateTicketStepData(step: IsJobTicketStep)
+
+    /**
+     * 更新作业票异常
+     */
+    @Query("update is_job_ticket set ticket_status = :ticketStatus,ex_status = :exStatus where ticket_id = :sourceDataId")
+    fun updateJobTicketExceptionData(sourceDataId: Long, ticketStatus: String, exStatus: Int?)
 }

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

@@ -73,4 +73,9 @@ object DictConstants {
      * 异常类型
      */
     const val KEY_EXCEPTION_TYPE = "exception_type"
+
+    /**
+     * 异常源类型
+     */
+    const val KEY_EXCEPTION_SOURCE_TYPE = "exception_source_type"
 }

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

@@ -88,10 +88,19 @@ enum class CommonDictDataEnum(val dictKey: String, val commonDictRes: List<Commo
             SimpleCommonDictRes("作业异常", "1"),
         )
     ),
+    EXCEPTION_SOURCE_TYPE(
+        DictConstants.KEY_EXCEPTION_SOURCE_TYPE, listOf(
+            SimpleCommonDictRes("钥匙", "0"),
+            SimpleCommonDictRes("挂锁", "1"),
+            SimpleCommonDictRes("锁仓", "2"),
+            SimpleCommonDictRes("作业", "3"),
+        )
+    ),
     EXCEPTION_STATUS(
         DictConstants.KEY_JOB_TICKET_STATUS, listOf(
             SimpleCommonDictRes("待处理", "0"),
             SimpleCommonDictRes("已处理", "1"),
+            SimpleCommonDictRes("已取消", "2"),
         )
     ),
     ;

+ 6 - 3
data/src/main/java/com/grkj/data/model/dos/IsExceptionSourceStandard.kt

@@ -7,12 +7,15 @@ class IsExceptionSourceStandard : BaseBean() {
 
     @PrimaryKey(autoGenerate = true)
     @ColumnInfo(name = "source_id")
-    var sourceId: Int = 0
+    var sourceId: Long = 0
 
     @ColumnInfo(name = "exception_id")
     var exceptionId: Int? = null
 
-    @ColumnInfo(name = "source_ids")
-    var sourceIds: List<Long> = listOf()
+    @ColumnInfo(name = "source_data_id")
+    var sourceDataId: Long = 0
+
+    @ColumnInfo(name = "source_data_type")
+    var sourceDataType: Int? = null
 
 }

+ 7 - 0
data/src/main/java/com/grkj/data/model/dos/IsExceptionStandard.kt

@@ -1,6 +1,7 @@
 package com.grkj.data.model.dos
 
 import androidx.room.*
+import com.sik.sikcore.date.TimeUtils
 
 @Entity(tableName = "is_exception_standard")
 class IsExceptionStandard : BaseBean() {
@@ -21,4 +22,10 @@ class IsExceptionStandard : BaseBean() {
     @ColumnInfo(name = "process_application")
     var processApplication: String? = null
 
+    @ColumnInfo(name = "occurrence_time")
+    var occurrenceTime: String? = TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT)
+
+    @ColumnInfo(name = "release_time")
+    var releaseTime: String? = null
+
 }

+ 16 - 4
data/src/main/java/com/grkj/data/model/vo/IsExceptionStandardVo.kt

@@ -3,8 +3,11 @@ package com.grkj.data.model.vo
 import androidx.room.ColumnInfo
 import androidx.room.Ignore
 import androidx.room.Relation
+import com.grkj.data.data.MainDomainData
 import com.grkj.data.model.dos.IsExceptionSourceStandard
+import com.grkj.data.model.dos.SysUserDo
 import com.grkj.data.model.dos.WorkflowStep
+import com.sik.sikcore.date.TimeUtils
 
 /**
  * 异常数据
@@ -20,18 +23,27 @@ class IsExceptionStandardVo {
     var exceptionStatus: Int? = null
 
     @ColumnInfo(name = "exception_description")
-    var exceptionDescription: String? = null
+    var exceptionDescription: List<String>? = null
 
     @ColumnInfo(name = "process_application")
     var processApplication: String? = null
 
-
     @Relation(
-        parentColumn = "exception_id",
-        entityColumn = "exception_id"
+        parentColumn = "exception_id", entityColumn = "exception_id"
     )
     var sourceData: List<IsExceptionSourceStandard> = listOf()
 
+    @Relation(
+        parentColumn = "reporter_id", entityColumn = "user_id"
+    )
+    var userData: SysUserDo? = null
+
+    @ColumnInfo(name = "occurrence_time")
+    var occurrenceTime: String? = TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT)
+
+    @ColumnInfo(name = "release_time")
+    var releaseTime: String? = null
+
     @Ignore
     var isSelected: Boolean = false
 }

+ 16 - 0
data/src/main/java/com/grkj/data/repository/IExceptionRepository.kt

@@ -1,7 +1,23 @@
 package com.grkj.data.repository
 
+import com.grkj.data.model.vo.IsExceptionStandardVo
+
 /**
  * 异常仓储层
  */
 interface IExceptionRepository {
+    /**
+     * 取消异常
+     */
+    fun cancelException(exceptionData: List<IsExceptionStandardVo>)
+
+    /**
+     * 获取异常数据
+     */
+    fun getExceptionData(): List<IsExceptionStandardVo>
+
+    /**
+     * 处理异常
+     */
+    fun handleException(exceptionData: List<IsExceptionStandardVo>)
 }

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

@@ -315,4 +315,19 @@ interface IHardwareRepository {
      * 移除挂锁异常
      */
     fun removeLockException(rfid: String?)
+
+    /**
+     * 根据钥匙id获取钥匙信息
+     */
+    fun getKeyInfoByKeyId(keyId: Long): IsKey?
+
+    /**
+     * 根据挂锁id获取挂锁信息
+     */
+    fun getLockInfoByLockId(lockId: Long): IsLock?
+
+    /**
+     * 根据仓位id获取仓位数据
+     */
+    fun getIsLockCabinetSlotBySlotId(slotId: Long): IsLockCabinetSlots?
 }

+ 12 - 0
data/src/main/java/com/grkj/data/repository/impl/network/NetworkExceptionRepository.kt

@@ -1,5 +1,6 @@
 package com.grkj.data.repository.impl.network
 
+import com.grkj.data.model.vo.IsExceptionStandardVo
 import com.grkj.data.repository.BaseRepository
 import com.grkj.data.repository.IExceptionRepository
 import javax.inject.Singleton
@@ -9,4 +10,15 @@ import javax.inject.Singleton
  */
 @Singleton
 class NetworkExceptionRepository : BaseRepository(), IExceptionRepository {
+    override fun cancelException(exceptionData: List<IsExceptionStandardVo>) {
+        TODO("Not yet implemented")
+    }
+
+    override fun getExceptionData(): List<IsExceptionStandardVo> {
+        TODO("Not yet implemented")
+    }
+
+    override fun handleException(exceptionData: List<IsExceptionStandardVo>) {
+        TODO("Not yet implemented")
+    }
 }

+ 61 - 1
data/src/main/java/com/grkj/data/repository/impl/standard/ExceptionRepository.kt

@@ -1,12 +1,72 @@
 package com.grkj.data.repository.impl.standard
 
+import com.grkj.data.dao.ExceptionDao
+import com.grkj.data.dao.JobTicketDao
+import com.grkj.data.enums.CommonDictDataEnum
+import com.grkj.data.enums.JobTicketStatusEnum
+import com.grkj.data.model.dos.IsExceptionStandard
+import com.grkj.data.model.vo.IsExceptionStandardVo
 import com.grkj.data.repository.BaseRepository
 import com.grkj.data.repository.IExceptionRepository
+import com.sik.sikcore.data.BeanUtils
+import com.sik.sikcore.date.TimeUtils
+import javax.inject.Inject
 import javax.inject.Singleton
 
 /**
  * 异常仓储实现
  */
 @Singleton
-class ExceptionRepository : BaseRepository(), IExceptionRepository {
+class ExceptionRepository @Inject constructor(
+    val exceptionDao: ExceptionDao,
+    val jobTicketDao: JobTicketDao
+) : BaseRepository(),
+    IExceptionRepository {
+    override fun cancelException(exceptionData: List<IsExceptionStandardVo>) {
+        exceptionData.forEach {
+            it.exceptionStatus =
+                CommonDictDataEnum.EXCEPTION_STATUS.commonDictRes.find { it.dictLabel == "已取消" }?.dictValue?.toInt()
+        }
+        exceptionData.flatMap { it.sourceData }
+            .filter { it.sourceDataType == CommonDictDataEnum.EXCEPTION_SOURCE_TYPE.commonDictRes.find { it.dictLabel == "作业" }?.dictValue?.toInt() }
+            .forEach {
+                jobTicketDao.updateJobTicketExceptionData(
+                    it.sourceDataId,
+                    JobTicketStatusEnum.CANCELED.status,
+                    CommonDictDataEnum.EXCEPTION_STATUS.commonDictRes.find { it.dictLabel == "已取消" }?.dictValue?.toInt()
+                )
+            }
+        val isExceptionData =
+            BeanUtils.copyList(exceptionData, IsExceptionStandard::class.java)?.filterNotNull()
+        isExceptionData?.forEach {
+            it.releaseTime = TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT)
+        }
+        exceptionDao.updateException(isExceptionData)
+    }
+
+    override fun getExceptionData(): List<IsExceptionStandardVo> {
+        return exceptionDao.getExceptionData()
+    }
+
+    override fun handleException(exceptionData: List<IsExceptionStandardVo>) {
+        exceptionData.forEach {
+            it.exceptionStatus =
+                CommonDictDataEnum.EXCEPTION_STATUS.commonDictRes.find { it.dictLabel == "已处理" }?.dictValue?.toInt()
+        }
+        exceptionData.flatMap { it.sourceData }
+            .filter { it.sourceDataType == CommonDictDataEnum.EXCEPTION_SOURCE_TYPE.commonDictRes.find { it.dictLabel == "作业" }?.dictValue?.toInt() }
+            .forEach {
+                jobTicketDao.updateJobTicketExceptionData(
+                    it.sourceDataId,
+                    JobTicketStatusEnum.FINISHED.status,
+                    CommonDictDataEnum.EXCEPTION_STATUS.commonDictRes.find { it.dictLabel == "已处理" }?.dictValue?.toInt()
+                )
+            }
+        val isExceptionData =
+            BeanUtils.copyList(exceptionData, IsExceptionStandard::class.java)?.filterNotNull()
+        isExceptionData?.forEach {
+            it.releaseTime = TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT)
+        }
+        exceptionDao.updateException(isExceptionData)
+    }
 }

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

@@ -486,4 +486,16 @@ class HardwareRepository @Inject constructor(
             CommonDictDataEnum.PADLOCK_STATUS.commonDictRes.find { it.dictLabel == "正常" }?.dictValue
         )
     }
+
+    override fun getKeyInfoByKeyId(keyId: Long): IsKey? {
+        return hardwareDao.getKeyInfoById(keyId)
+    }
+
+    override fun getLockInfoByLockId(lockId: Long): IsLock? {
+        return hardwareDao.getLockInfoById(lockId)
+    }
+
+    override fun getIsLockCabinetSlotBySlotId(slotId: Long): IsLockCabinetSlots? {
+        return hardwareDao.getIsLockCabinetSlotBySlotId(slotId)
+    }
 }