Jelajahi Sumber

refactor(更新)
- 异常上报和异常处理的逻辑优化
- 数据管理增加重置按钮,修复查询的bug

周文健 4 bulan lalu
induk
melakukan
35d323a803
24 mengubah file dengan 414 tambahan dan 211 penghapusan
  1. 7 4
      app/src/main/java/com/grkj/iscs/features/main/dialog/data_manage/AddUserDialog.kt
  2. 4 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/data_manage/PointMangeFragment.kt
  3. 4 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/data_manage/RoleManageFragment.kt
  4. 4 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/data_manage/UserManageFragment.kt
  5. 136 97
      app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionJobFragment.kt
  6. 18 7
      app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionReportFragment.kt
  7. 35 2
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/exception_manage/ExceptionJobViewModel.kt
  8. 16 54
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/exception_manage/ExceptionViewModel.kt
  9. 12 3
      app/src/main/res/layout-land/fragment_point_manage.xml
  10. 12 2
      app/src/main/res/layout/fragment_point_manage.xml
  11. 10 0
      app/src/main/res/layout/fragment_role_manage.xml
  12. 13 2
      app/src/main/res/layout/fragment_user_manage.xml
  13. 2 2
      app/src/main/res/layout/item_user_manage_user.xml
  14. 4 0
      app/src/main/res/values-en/strings.xml
  15. 4 0
      app/src/main/res/values-zh/strings.xml
  16. 4 0
      app/src/main/res/values/strings.xml
  17. 36 17
      data/src/main/java/com/grkj/data/dao/JobTicketDao.kt
  18. 6 2
      data/src/main/java/com/grkj/data/data/DictConstants.kt
  19. 9 4
      data/src/main/java/com/grkj/data/enums/CommonDictDataEnum.kt
  20. 5 0
      data/src/main/java/com/grkj/data/repository/IJobTicketRepository.kt
  21. 4 0
      data/src/main/java/com/grkj/data/repository/impl/network/NetworkJobTicketRepository.kt
  22. 23 13
      data/src/main/java/com/grkj/data/repository/impl/standard/ExceptionRepository.kt
  23. 45 2
      data/src/main/java/com/grkj/data/repository/impl/standard/JobTicketRepository.kt
  24. 1 0
      ui-base/build.gradle.kts

+ 7 - 4
app/src/main/java/com/grkj/iscs/features/main/dialog/data_manage/AddUserDialog.kt

@@ -2,6 +2,8 @@ package com.grkj.iscs.features.main.dialog.data_manage
 
 import android.view.View
 import androidx.core.view.isVisible
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.findViewTreeLifecycleOwner
 import com.grkj.data.model.vo.AddUserDataVo
 import com.grkj.iscs.R
 import com.grkj.iscs.databinding.DialogAddUserBinding
@@ -12,6 +14,7 @@ import com.grkj.ui_base.utils.extension.tip
 import com.kongzue.dialogx.dialogs.CustomDialog
 import com.kongzue.dialogx.dialogs.PopTip
 import com.kongzue.dialogx.interfaces.OnBindView
+import com.sik.sikcore.activity.ActivityTracker
 
 /**
  * 新增用户对话框,基于 DialogX,支持多选角色和岗位
@@ -79,14 +82,14 @@ class AddUserDialog(
     }
 
     private fun checkData(): Boolean {
+        if (binding.usernameEt.text.isNullOrBlank()) {
+            PopTip.build().tip(R.string.please_input_username)
+            return false
+        }
         if (binding.nicknameEt.text.isNullOrBlank()) {
             PopTip.build().tip(R.string.please_input_nickname)
             return false
         }
-//        if (binding.cardcodeEt.text.isNullOrBlank()) {
-//            PopTip.build().tipDialog(R.string.please_input_card_code)
-//            return false
-//        }
         if (selectedRoles.isEmpty()) {
             PopTip.build().tip(R.string.please_select_role)
             return false

+ 4 - 0
app/src/main/java/com/grkj/iscs/features/main/fragment/data_manage/PointMangeFragment.kt

@@ -44,6 +44,10 @@ class PointMangeFragment : BaseFragment<FragmentPointManageBinding>() {
         binding.deletePoint.setDebouncedClickListener {
             deleteSelectPoint()
         }
+        binding.reset.setDebouncedClickListener {
+            viewModel.pointFilterData = null
+            getPointData(false)
+        }
         binding.addPoint.setDebouncedClickListener {
             viewModel.initDialogData().observe(this) {
                 AddPointDialog.show(viewModel.workstationData.map {

+ 4 - 0
app/src/main/java/com/grkj/iscs/features/main/fragment/data_manage/RoleManageFragment.kt

@@ -45,6 +45,10 @@ class RoleManageFragment : BaseFragment<FragmentRoleManageBinding>() {
         binding.delete.setDebouncedClickListener {
             deleteSelect()
         }
+        binding.reset.setDebouncedClickListener {
+            viewModel.roleFilterData = null
+            getRoleData(false)
+        }
         binding.add.setDebouncedClickListener {
             AddRoleDialog.show {
                 if (it.roleKeys in RoleEnum.values().map { it.roleKey }) {

+ 4 - 0
app/src/main/java/com/grkj/iscs/features/main/fragment/data_manage/UserManageFragment.kt

@@ -44,6 +44,10 @@ class UserManageFragment : BaseFragment<FragmentUserManageBinding>() {
         binding.deleteUser.setDebouncedClickListener {
             deleteSelectUser()
         }
+        binding.reset.setDebouncedClickListener {
+            viewModel.userFilterData = null
+            getUserData(false)
+        }
         binding.addUser.setDebouncedClickListener {
             viewModel.getRoleAndWorkStationData().observe(this) {
                 AddUserDialog.show(viewModel.roleData.map {

+ 136 - 97
app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionJobFragment.kt

@@ -86,108 +86,40 @@ class ExceptionJobFragment : BaseFragment<FragmentExceptionJobBinding>() {
             })
         }
         binding.handleException.setDebouncedClickListener {
-            viewModel.checkJobNeedLockOrUnlock().observe(this) {
-                when (it) {
-                    NextJobPrompt.NO_NEW_JOB -> {
-                        TipDialog.showInfo(
-                            getString(R.string.confirm_handle_exception),
-                            onConfirmClick = {
-                                viewModel.handleException().observe(this) {
-                                    if (it.first) {
-                                        TipDialog.showSuccess(
-                                            getString(R.string.handle_exception_success),
-                                            onConfirmClick = {
-                                                navController.popBackStack()
-                                            },
-                                            onCancelClick = {
-                                                navController.popBackStack()
-                                            })
-                                    } else {
-                                        TipDialog.showError(it.second)
-                                    }
-                                }
-                            })
-                    }
-
-                    NextJobPrompt.CREATE_LOCK_JOB -> {
-                        TipDialog.showInfo(
-                            getString(R.string.confirm_handle_exception),
+            if (viewModel.jobApplicationUseMasterKey()) {
+                handleExceptionCheck()
+            } else {
+                viewModel.checkJobHasCoLockAndCrossJob().observe(this) {
+                    if (it.first) {
+                        TipDialog.show(
+                            title = getString(R.string.warn),
+                            msg = getString(R.string.handle_exception_will_release_all_colock),
+                            dialogType = TipDialog.DialogType.ERROR,
                             onConfirmClick = {
-                                viewModel.handleException().observe(this) {
-                                    if (it.first) {
-                                        TipDialog.showInfo(
-                                            getString(R.string.confirm_create_lock_job),
-                                            onConfirmClick = {
-                                                viewModel.createLockJob().observe(this) {
-                                                    if (it) {
-                                                        TipDialog.showSuccess(
-                                                            getString(R.string.handle_exception_success),
-                                                            onConfirmClick = {
-                                                                navController.popBackStack()
-                                                            },
-                                                            onCancelClick = {
-                                                                navController.popBackStack()
-                                                            })
-                                                    } else {
-                                                        TipDialog.showError(getString(R.string.create_job_failed))
-                                                    }
-                                                }
-                                            }, onCancelClick = {
-                                                TipDialog.showSuccess(
-                                                    getString(R.string.handle_exception_success),
-                                                    onConfirmClick = {
-                                                        navController.popBackStack()
-                                                    },
-                                                    onCancelClick = {
-                                                        navController.popBackStack()
-                                                    })
-                                            })
-                                    } else {
-                                        TipDialog.showError(it.second)
-                                    }
+                                if (it.second) {
+                                    TipDialog.show(
+                                        title = getString(R.string.warn),
+                                        msg = getString(R.string.current_job_has_cross_job),
+                                        dialogType = TipDialog.DialogType.ERROR,
+                                        onConfirmClick = {
+                                            handleExceptionCheck()
+                                        })
                                 }
                             })
+                    } else {
+                        if (it.second) {
+                            TipDialog.show(
+                                title = getString(R.string.warn),
+                                msg = getString(R.string.current_job_has_cross_job),
+                                dialogType = TipDialog.DialogType.ERROR,
+                                onConfirmClick = {
+                                    handleExceptionCheck()
+                                })
+                        } else {
+                            handleExceptionCheck()
+                        }
                     }
 
-                    NextJobPrompt.CREATE_UNLOCK_JOB -> {
-                        TipDialog.showInfo(
-                            getString(R.string.confirm_handle_exception),
-                            onConfirmClick = {
-                                viewModel.handleException().observe(this) {
-                                    if (it.first) {
-                                        TipDialog.showInfo(
-                                            getString(R.string.confirm_create_unlock_job),
-                                            onConfirmClick = {
-                                                viewModel.createUnlockJob().observe(this) {
-                                                    if (it) {
-                                                        TipDialog.showSuccess(
-                                                            getString(R.string.handle_exception_success),
-                                                            onConfirmClick = {
-                                                                navController.popBackStack()
-                                                            },
-                                                            onCancelClick = {
-                                                                navController.popBackStack()
-                                                            })
-                                                    } else {
-                                                        TipDialog.showError(getString(R.string.create_job_failed))
-                                                    }
-                                                }
-                                            }, onCancelClick = {
-                                                TipDialog.showSuccess(
-                                                    getString(R.string.handle_exception_success),
-                                                    onConfirmClick = {
-                                                        navController.popBackStack()
-                                                    },
-                                                    onCancelClick = {
-                                                        navController.popBackStack()
-                                                    })
-                                            })
-                                    } else {
-                                        TipDialog.showError(it.second)
-                                    }
-                                }
-                            })
-                    }
                 }
             }
         }
@@ -227,6 +159,113 @@ class ExceptionJobFragment : BaseFragment<FragmentExceptionJobBinding>() {
         }
     }
 
+    private fun handleExceptionCheck() {
+        viewModel.checkJobNeedLockOrUnlock().observe(this) {
+            when (it) {
+                NextJobPrompt.NO_NEW_JOB -> {
+                    TipDialog.showInfo(
+                        getString(R.string.confirm_handle_exception),
+                        onConfirmClick = {
+                            viewModel.handleException().observe(this) {
+                                if (it.first) {
+                                    TipDialog.showSuccess(
+                                        getString(R.string.handle_exception_success),
+                                        onConfirmClick = {
+                                            navController.popBackStack()
+                                        },
+                                        onCancelClick = {
+                                            navController.popBackStack()
+                                        })
+                                } else {
+                                    TipDialog.showError(it.second)
+                                }
+                            }
+                        })
+                }
+
+                NextJobPrompt.CREATE_LOCK_JOB -> {
+                    TipDialog.showInfo(
+                        getString(R.string.confirm_handle_exception),
+                        onConfirmClick = {
+                            viewModel.handleException().observe(this) {
+                                if (it.first) {
+                                    TipDialog.showInfo(
+                                        getString(R.string.confirm_create_lock_job),
+                                        onConfirmClick = {
+                                            viewModel.createLockJob().observe(this) {
+                                                if (it) {
+                                                    TipDialog.showSuccess(
+                                                        getString(R.string.handle_exception_success),
+                                                        onConfirmClick = {
+                                                            navController.popBackStack()
+                                                        },
+                                                        onCancelClick = {
+                                                            navController.popBackStack()
+                                                        })
+                                                } else {
+                                                    TipDialog.showError(getString(R.string.create_job_failed))
+                                                }
+                                            }
+                                        }, onCancelClick = {
+                                            TipDialog.showSuccess(
+                                                getString(R.string.handle_exception_success),
+                                                onConfirmClick = {
+                                                    navController.popBackStack()
+                                                },
+                                                onCancelClick = {
+                                                    navController.popBackStack()
+                                                })
+                                        })
+                                } else {
+                                    TipDialog.showError(it.second)
+                                }
+                            }
+                        })
+                }
+
+                NextJobPrompt.CREATE_UNLOCK_JOB -> {
+                    TipDialog.showInfo(
+                        getString(R.string.confirm_handle_exception),
+                        onConfirmClick = {
+                            viewModel.handleException().observe(this) {
+                                if (it.first) {
+                                    TipDialog.showInfo(
+                                        getString(R.string.confirm_create_unlock_job),
+                                        onConfirmClick = {
+                                            viewModel.createUnlockJob().observe(this) {
+                                                if (it) {
+                                                    TipDialog.showSuccess(
+                                                        getString(R.string.handle_exception_success),
+                                                        onConfirmClick = {
+                                                            navController.popBackStack()
+                                                        },
+                                                        onCancelClick = {
+                                                            navController.popBackStack()
+                                                        })
+                                                } else {
+                                                    TipDialog.showError(getString(R.string.create_job_failed))
+                                                }
+                                            }
+                                        }, onCancelClick = {
+                                            TipDialog.showSuccess(
+                                                getString(R.string.handle_exception_success),
+                                                onConfirmClick = {
+                                                    navController.popBackStack()
+                                                },
+                                                onCancelClick = {
+                                                    navController.popBackStack()
+                                                })
+                                        })
+                                } else {
+                                    TipDialog.showError(it.second)
+                                }
+                            }
+                        })
+                }
+            }
+        }
+    }
+
     /**
      * 检查界面
      */

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

@@ -127,13 +127,24 @@ class ExceptionReportFragment : BaseFormFragment<FragmentExceptionReportBinding>
             }
         }
         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()
+            if (viewModel.selectedExceptionType == viewModel.exceptionType.find { it.dictLabel == "硬件异常" }?.dictValue) {
+                TextDropDownDialog.showSingle(viewModel.processApplicationHardware.map {
+                    TextDropDownDialog.SimpleTextDropDownEntity(
+                        dataTag = it.dictValue, dataText = it.dictLabel
+                    )
+                }, binding.processApplication) {
+                    binding.processApplication.text = it.getShowText()
+                    viewModel.selectedProcessApplication = it.getTag()
+                }
+            }else{
+                TextDropDownDialog.showSingle(viewModel.processApplicationJob.map {
+                    TextDropDownDialog.SimpleTextDropDownEntity(
+                        dataTag = it.dictValue, dataText = it.dictLabel
+                    )
+                }, binding.processApplication) {
+                    binding.processApplication.text = it.getShowText()
+                    viewModel.selectedProcessApplication = it.getTag()
+                }
             }
         }
     }

+ 35 - 2
app/src/main/java/com/grkj/iscs/features/main/viewmodel/exception_manage/ExceptionJobViewModel.kt

@@ -56,6 +56,11 @@ class ExceptionJobViewModel @Inject constructor(
     var workflowSteps: List<WorkflowStep> = mutableListOf()
     var isUnlockFirst: Boolean = false
 
+    /**
+     * 处理申请(作业)
+     */
+    var processApplicationJob: List<CommonDictRes> = mutableListOf()
+
     /**
      * 异常数据
      */
@@ -178,6 +183,8 @@ class ExceptionJobViewModel @Inject constructor(
         return liveData(Dispatchers.IO) {
             exceptionStatus = DataBusiness.fetchDict(DictConstants.KEY_EXCEPTION_STATUS)
             exceptionData = exceptionRepository.getExceptionDataById(exceptionId)
+            processApplicationJob =
+                DataBusiness.fetchDict(DictConstants.KEY_EXCEPTION_PROCESS_APPLICATION_JOB)
             emit(true)
         }
     }
@@ -187,11 +194,26 @@ class ExceptionJobViewModel @Inject constructor(
      */
     fun checkJobNeedLockOrUnlock(): LiveData<NextJobPrompt> {
         return liveData(Dispatchers.IO) {
-            val nextJobPrompt = jobTicketRepository.isNextLockOrUnLock(ticketId)
-            emit(nextJobPrompt)
+            if (jobApplicationUseMasterKey()) {
+                emit(NextJobPrompt.NO_NEW_JOB)
+            } else {
+                val nextJobPrompt = jobTicketRepository.isNextLockOrUnLock(ticketId)
+                emit(nextJobPrompt)
+            }
         }
     }
 
+    /**
+     * 作业申请使用万能钥匙
+     */
+    fun jobApplicationUseMasterKey(): Boolean {
+        return exceptionData?.exceptionDescription?.contains(processApplicationJob.find {
+            it.dictLabel.contains(
+                "万能钥匙"
+            )
+        }?.dictLabel) == true
+    }
+
     /**
      * 创建上锁作业
      */
@@ -257,4 +279,15 @@ class ExceptionJobViewModel @Inject constructor(
             emit(true)
         }
     }
+
+    /**
+     * 检查是否有共锁和交叉作业
+     */
+    fun checkJobHasCoLockAndCrossJob(): LiveData<Pair<Boolean, Boolean>> {
+        return liveData(Dispatchers.IO) {
+            val hasCoLock = workflowSteps.any { it.enableColock }
+            val isJobCross = jobTicketRepository.hasJobCross(ticketId)
+            emit(hasCoLock to isJobCross)
+        }
+    }
 }

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

@@ -3,6 +3,7 @@ package com.grkj.iscs.features.main.viewmodel.exception_manage
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.liveData
 import com.grkj.data.data.DictConstants
+import com.grkj.data.enums.CommonDictDataEnum
 import com.grkj.data.model.dos.IsExceptionSourceStandard
 import com.grkj.data.model.dos.IsExceptionStandard
 import com.grkj.data.model.res.CommonDictRes
@@ -70,9 +71,13 @@ class ExceptionViewModel @Inject constructor(
     var exceptionDescription: List<CommonDictRes> = mutableListOf()
 
     /**
-     * 处理申请
+     * 处理申请(硬件)
      */
-    var processApplication: List<CommonDictRes> = mutableListOf()
+    var processApplicationHardware: List<CommonDictRes> = mutableListOf()
+    /**
+     * 处理申请(作业)
+     */
+    var processApplicationJob: List<CommonDictRes> = mutableListOf()
 
     /**
      * 异常数据
@@ -112,8 +117,10 @@ class ExceptionViewModel @Inject constructor(
             exceptionSourceDataType =
                 DataBusiness.fetchDict(DictConstants.KEY_EXCEPTION_SOURCE_TYPE)
             exceptionDescription = DataBusiness.fetchDict(DictConstants.KEY_EXCEPTION_DESCRIPTION)
-            processApplication =
-                DataBusiness.fetchDict(DictConstants.KEY_EXCEPTION_PROCESS_APPLICATION)
+            processApplicationHardware =
+                DataBusiness.fetchDict(DictConstants.KEY_EXCEPTION_PROCESS_APPLICATION_HARDWARE)
+            processApplicationJob =
+                DataBusiness.fetchDict(DictConstants.KEY_EXCEPTION_PROCESS_APPLICATION_JOB)
             emit(true)
         }
     }
@@ -243,6 +250,7 @@ class ExceptionViewModel @Inject constructor(
                 //异常硬件
                 exceptionType.find { it.dictLabel == "硬件异常" }?.dictValue -> {
                     val keyData = hardwareRepository.getAllKeyInfo()
+                        .filter { it.exStatus.toString() != keyStatus.find { it.dictLabel == "异常" }?.dictValue }
                     keyData.map {
                         val exceptionSourceDataEntity =
                             ExceptionSourceDataEntity(itemGroupPosition = 1)
@@ -263,6 +271,7 @@ class ExceptionViewModel @Inject constructor(
                         exceptionSourceData.add(exceptionSourceDataEntity)
                     }
                     val lockData = hardwareRepository.getAllLockInfo()
+                        .filter { it.exStatus.toString() != lockStatus.find { it.dictLabel == "异常" }?.dictValue }
                     lockData.map {
                         val exceptionSourceDataEntity =
                             ExceptionSourceDataEntity(itemGroupPosition = 1)
@@ -283,6 +292,7 @@ class ExceptionViewModel @Inject constructor(
                         exceptionSourceData.add(exceptionSourceDataEntity)
                     }
                     val slotsData = hardwareRepository.getAllSlotsData()
+                        .filter { it.status.toString() != slotsStatus.find { it.dictLabel == "异常" }?.dictValue }
                     slotsData.map {
                         val exceptionSourceDataEntity =
                             ExceptionSourceDataEntity(itemGroupPosition = 1)
@@ -307,6 +317,7 @@ class ExceptionViewModel @Inject constructor(
                 //异常作业
                 exceptionType.find { it.dictLabel == "作业异常" }?.dictValue -> {
                     val jobTicketData = jobTicketRepository.getAllInProgressJob()
+                        .filter { it.exStatus.toString() != jobTicketStatus.find { it.dictLabel == "异常" }?.dictValue }
                     exceptionSourceData = jobTicketData.map {
                         val exceptionSourceDataEntity =
                             ExceptionSourceDataEntity(itemGroupPosition = 0)
@@ -333,56 +344,7 @@ class ExceptionViewModel @Inject constructor(
             exceptionData.exceptionType = selectedExceptionType?.toInt() ?: 0
             exceptionData.exceptionDescription = selectedExceptionDescription
             exceptionData.processApplication = selectedProcessApplication
-            val exceptionId = exceptionRepository.reportException(exceptionData)
-            for (exceptionSource in selectedSourceData) {
-                when (exceptionSource.sourceDataType) {
-                    exceptionSourceDataType.find { it.dictLabel == "钥匙" }?.dictValue?.toInt() -> {
-                        val keyInfo =
-                            hardwareRepository.getKeyInfoByKeyId(exceptionSource.sourceDataId)
-                        keyInfo?.exStatus = keyStatus.find { it.dictLabel == "异常" }?.dictValue
-                        keyInfo?.remark = selectedExceptionDescription.joinToString(",")
-                        keyInfo?.let {
-                            hardwareRepository.updateKeyInfo(it)
-                        }
-                    }
-
-                    exceptionSourceDataType.find { it.dictLabel == "挂锁" }?.dictValue?.toInt() -> {
-                        val lockInfo =
-                            hardwareRepository.getLockInfoByLockId(exceptionSource.sourceDataId)
-                        lockInfo?.exStatus = lockStatus.find { it.dictLabel == "异常" }?.dictValue
-                        lockInfo?.remark = selectedExceptionDescription.joinToString(",")
-                        lockInfo?.let {
-                            hardwareRepository.updateLockInfo(it)
-                        }
-                    }
-
-                    exceptionSourceDataType.find { it.dictLabel == "仓位" }?.dictValue?.toInt() -> {
-                        val slotsInfo =
-                            hardwareRepository.getIsLockCabinetSlotBySlotId(exceptionSource.sourceDataId)
-                        slotsInfo?.status = slotsStatus.find { it.dictLabel == "异常" }?.dictValue
-                        slotsInfo?.remark = selectedExceptionDescription.joinToString(",")
-                        slotsInfo?.let {
-                            hardwareRepository.updateSlotsInfo(it)
-                        }
-                    }
-
-                    exceptionSourceDataType.find { it.dictLabel == "作业" }?.dictValue?.toInt() -> {
-                        val jobTicketData =
-                            jobTicketRepository.getTicketRawDataByTicketId(exceptionSource.sourceDataId)
-                        jobTicketData?.exStatus =
-                            jobTicketStatus.find { it.dictLabel == "异常" }?.dictValue?.toInt()
-                        jobTicketData?.remark = selectedExceptionDescription.joinToString(",")
-                        jobTicketData?.let {
-                            jobTicketRepository.updateTicketData(it)
-                        }
-                    }
-                }
-                val exceptionSourceData = IsExceptionSourceStandard()
-                exceptionSourceData.exceptionId = exceptionId
-                exceptionSourceData.sourceDataId = exceptionSource.sourceDataId
-                exceptionSourceData.sourceDataType = exceptionSource.sourceDataType
-                exceptionRepository.saveExceptionSourceData(exceptionSourceData)
-            }
+            exceptionRepository.reportException(exceptionData)
             emit(true)
         }
     }

+ 12 - 3
app/src/main/res/layout-land/fragment_point_manage.xml

@@ -28,8 +28,8 @@
                 android:layout_weight="1"
                 android:text="@string/point_manage_title"
                 android:textColor="@color/black"
-                android:textStyle="bold"
-                android:textSize="@dimen/normal_text_size_25" />
+                android:textSize="@dimen/normal_text_size_25"
+                android:textStyle="bold" />
 
             <TextView
                 android:id="@+id/back"
@@ -72,7 +72,6 @@
                 android:textColor="@color/black"
                 android:textSize="@dimen/common_btn_text_size" />
 
-
             <TextView
                 android:id="@+id/delete_point"
                 android:layout_width="wrap_content"
@@ -84,6 +83,16 @@
                 android:textColor="@color/black"
                 android:textSize="@dimen/common_btn_text_size" />
 
+            <TextView
+                android:id="@+id/reset"
+                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/reset"
+                android:textColor="@color/black"
+                android:textSize="@dimen/common_btn_text_size" />
 
             <View
                 android:layout_width="0dp"

+ 12 - 2
app/src/main/res/layout/fragment_point_manage.xml

@@ -27,9 +27,9 @@
                 android:layout_marginLeft="@dimen/common_spacing"
                 android:layout_weight="1"
                 android:text="@string/point_manage_title"
-                android:textStyle="bold"
                 android:textColor="@color/black"
-                android:textSize="@dimen/normal_text_size_25" />
+                android:textSize="@dimen/normal_text_size_25"
+                android:textStyle="bold" />
 
             <TextView
                 android:id="@+id/back"
@@ -84,6 +84,16 @@
                 android:textColor="@color/black"
                 android:textSize="@dimen/common_btn_text_size" />
 
+            <TextView
+                android:id="@+id/reset"
+                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/reset"
+                android:textColor="@color/black"
+                android:textSize="@dimen/common_btn_text_size" />
 
             <View
                 android:layout_width="0dp"

+ 10 - 0
app/src/main/res/layout/fragment_role_manage.xml

@@ -84,6 +84,16 @@
                 android:textColor="@color/black"
                 android:textSize="@dimen/common_btn_text_size" />
 
+            <TextView
+                android:id="@+id/reset"
+                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/reset"
+                android:textColor="@color/black"
+                android:textSize="@dimen/common_btn_text_size" />
 
             <View
                 android:layout_width="0dp"

+ 13 - 2
app/src/main/res/layout/fragment_user_manage.xml

@@ -28,8 +28,8 @@
                 android:layout_weight="1"
                 android:text="@string/user_manage_title"
                 android:textColor="@color/black"
-                android:textStyle="bold"
-                android:textSize="@dimen/normal_text_size_25" />
+                android:textSize="@dimen/normal_text_size_25"
+                android:textStyle="bold" />
 
             <TextView
                 android:id="@+id/back"
@@ -85,6 +85,17 @@
                 android:textSize="@dimen/common_btn_text_size" />
 
 
+            <TextView
+                android:id="@+id/reset"
+                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/reset"
+                android:textColor="@color/black"
+                android:textSize="@dimen/common_btn_text_size" />
+
             <View
                 android:layout_width="0dp"
                 android:layout_height="0dp"

+ 2 - 2
app/src/main/res/layout/item_user_manage_user.xml

@@ -8,8 +8,8 @@
 
         <CheckBox
             android:id="@+id/select"
-            android:layout_width="30dp"
-            android:layout_height="30dp"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
             android:layout_gravity="center"
             android:layout_margin="@dimen/common_spacing" />
 

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

@@ -457,5 +457,9 @@
     <string name="loading_device">Loading hardware .....</string>
     <string name="confirm_create_unlock_job">Confirm whether to create a unlock job</string>
     <string name="user_already_exists">User already exists</string>
+    <string name="handle_exception_will_release_all_colock">Warning! Handling exceptions will remove all Co-Lock. Please confirm if you want to continue</string>
+    <string name="warn">Warn</string>
+    <string name="current_job_has_cross_job">Warning! There are cross assignments in the current assignment. Do you want to continue handling exceptions</string>
+    <string name="reset">重置</string>
 
 </resources>

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

@@ -457,5 +457,9 @@
     <string name="loading_device">正在加载硬件......</string>
     <string name="confirm_create_unlock_job">是否创建解锁作业</string>
     <string name="user_already_exists">用户已存在</string>
+    <string name="handle_exception_will_release_all_colock">警告!处理异常将移除所有共锁,请确认是否继续</string>
+    <string name="warn">警告</string>
+    <string name="current_job_has_cross_job">警告!当前作业存在交叉作业,是否继续处理异常</string>
+    <string name="reset">重置</string>
 
 </resources>

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

@@ -460,5 +460,9 @@
     <string name="loading_device">正在加载硬件......</string>
     <string name="confirm_create_unlock_job">是否创建解锁作业</string>
     <string name="user_already_exists">用户已存在</string>
+    <string name="handle_exception_will_release_all_colock">警告!处理异常将移除所有共锁,请确认是否继续</string>
+    <string name="warn">警告</string>
+    <string name="current_job_has_cross_job">警告!当前作业存在交叉作业,是否继续处理异常</string>
+    <string name="reset">重置</string>
 
 </resources>

+ 36 - 17
data/src/main/java/com/grkj/data/dao/JobTicketDao.kt

@@ -117,20 +117,26 @@ interface JobTicketDao {
     @Transaction
     @Query(
         """
-        select ticket_id as ticketId,
-        ticket_name as ticketName,
-        ticket_status as ticketStatus,
-        workstation_id as workstationId,
-        sop_id as sopId,
-        mode_id,
-        ex_status,
-        remark
-        from is_job_ticket ijt
-        order by update_time desc 
-        limit :size offset :offset
+    SELECT
+      ticket_id     AS ticketId,
+      ticket_name   AS ticketName,
+      ticket_status AS ticketStatus,
+      workstation_id AS workstationId,
+      sop_id        AS sopId,
+      mode_id,
+      ex_status,
+      remark
+        FROM is_job_ticket ijt
+        WHERE (:exStatusList IS NULL OR ex_status IN (:exStatusList))
+        ORDER BY update_time DESC
+        LIMIT :size OFFSET :offset
     """
     )
-    fun getTicketDataPage(size: Int, offset: Int): List<JobTicketManageVo>
+    fun getTicketDataPage(
+        size: Int,
+        offset: Int,
+        exStatusList: List<String>?
+    ): List<JobTicketManageVo>
 
     /**
      * 开始作业
@@ -306,7 +312,7 @@ interface JobTicketDao {
      * 获取工作中的作业数量
      */
     @Query(
-        "select count(1) from is_job_ticket where ticket_status in ('1','2','3','4') " + "AND (:workstationId IS NULL OR trim(:workstationId) = '' OR workstation_id = :workstationId) " + "AND (:modeId IS NULL OR trim(:modeId) = '' OR mode_id = :modeId) "
+        "select count(1) from is_job_ticket where ticket_status in ('1','2','3','4','7') " + "AND (:workstationId IS NULL OR trim(:workstationId) = '' OR workstation_id = :workstationId) " + "AND (:modeId IS NULL OR trim(:modeId) = '' OR mode_id = :modeId) "
     )
     fun getInProgressJobSize(workstationId: Long?, modeId: Long?): Int
 
@@ -314,9 +320,9 @@ interface JobTicketDao {
      * 获取工作中的作业数量
      */
     @Query(
-        "select count(1) from is_job_ticket ijt where ijt.ticket_status in (1,2,3,4,7)"
+        "select count(1) from is_job_ticket ijt where ijt.ticket_status in (1,2,3,4,7) and (:exStatusList IS NULL OR ex_status IN (:exStatusList))"
     )
-    fun getInProgressJobSize(): Int
+    fun getInProgressJobSize(exStatusList: List<String>?): Int
 
     /**
      * 获取所有作业数量
@@ -365,7 +371,7 @@ interface JobTicketDao {
         LEFT JOIN is_job_ticket_points p ON p.ticket_id = j.ticket_id
         LEFT JOIN is_job_ticket_key k ON k.ticket_id = j.ticket_id
         WHERE
-        j.ticket_status < 5
+        (j.ticket_status < 5 or j.ticket_status = 7)
         AND p.point_id IN (:pointIds)
         AND k.collect_time is not null
         and k.give_back_time is null
@@ -410,7 +416,7 @@ interface JobTicketDao {
                 LEFT JOIN is_job_ticket t ON t.ticket_id = p.ticket_id
                 LEFT JOIN is_job_ticket_key k ON k.ticket_id = p.ticket_id and k.ticket_type = "1"
         WHERE
-            t.ticket_status < 5
+            (t.ticket_status < 5 or t.ticket_status = 7)
           AND p.point_status = "1"
           AND p.unlocked_by_key_id IS NULL
           AND p.point_id =:pointId
@@ -546,4 +552,17 @@ interface JobTicketDao {
      */
     @Query("select * from is_job_ticket where sop_id in (:sopIds)")
     fun getTicketBySopIds(sopIds: List<Long>): List<IsJobTicket>
+
+    /**
+     * 获取进行中的作业根据点位
+     */
+    @Query(
+        """
+        select ijt.ticket_id
+        from is_job_ticket ijt
+        left join is_job_ticket_points ijtp on ijt.ticket_id = ijtp.ticket_id
+        where ijtp.point_id in (:pointIds)
+    """
+    )
+    fun getProgressTicketIdsByPoints(pointIds: List<Long?>): List<Long>
 }

+ 6 - 2
data/src/main/java/com/grkj/data/data/DictConstants.kt

@@ -85,7 +85,11 @@ object DictConstants {
     const val KEY_EXCEPTION_DESCRIPTION = "exception_description"
 
     /**
-     * 处理申请
+     * 处理申请(硬件)
      */
-    const val KEY_EXCEPTION_PROCESS_APPLICATION = "exception_process_application"
+    const val KEY_EXCEPTION_PROCESS_APPLICATION_HARDWARE = "exception_process_application_hardware"
+    /**
+     * 处理申请(作业)
+     */
+    const val KEY_EXCEPTION_PROCESS_APPLICATION_JOB = "exception_process_application_job"
 }

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

@@ -111,12 +111,17 @@ enum class CommonDictDataEnum(val dictKey: String, val commonDictRes: List<Commo
             SimpleCommonDictRes("仓位损坏", "3"),
         )
     ),
-    EXCEPTION_PROCESS_APPLICATION(
-        DictConstants.KEY_EXCEPTION_PROCESS_APPLICATION, listOf(
+    EXCEPTION_PROCESS_APPLICATION_HARDWARE(
+        DictConstants.KEY_EXCEPTION_PROCESS_APPLICATION_HARDWARE, listOf(
+            SimpleCommonDictRes("申请报废钥匙", "1"),
+            SimpleCommonDictRes("申请报废挂锁", "2"),
+            SimpleCommonDictRes("申请报废仓位", "3"),
+        )
+    ),
+    EXCEPTION_PROCESS_APPLICATION_JOB(
+        DictConstants.KEY_EXCEPTION_PROCESS_APPLICATION_HARDWARE, listOf(
             SimpleCommonDictRes("申请万能钥匙", "0"),
             SimpleCommonDictRes("申请解除作业", "1"),
-            SimpleCommonDictRes("申请报废钥匙", "2"),
-            SimpleCommonDictRes("申请报废挂锁", "3"),
         )
     ),
     ;

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

@@ -279,4 +279,9 @@ interface IJobTicketRepository {
      * 根据sopid获取作业
      */
     fun getJobTicketBySopIds(sopIds: List<Long>): List<IsJobTicket>
+
+    /**
+     * 是否有交叉作业
+     */
+    fun hasJobCross(ticketId: Long): Boolean
 }

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

@@ -268,4 +268,8 @@ class NetworkJobTicketRepository  @Inject constructor() : BaseRepository(), IJob
     override fun getJobTicketBySopIds(sopIds: List<Long>): List<IsJobTicket> {
         TODO("Not yet implemented")
     }
+
+    override fun hasJobCross(ticketId: Long): Boolean {
+        TODO("Not yet implemented")
+    }
 }

+ 23 - 13
data/src/main/java/com/grkj/data/repository/impl/standard/ExceptionRepository.kt

@@ -3,6 +3,7 @@ package com.grkj.data.repository.impl.standard
 import com.grkj.data.dao.ExceptionDao
 import com.grkj.data.dao.HardwareDao
 import com.grkj.data.dao.JobTicketDao
+import com.grkj.data.dao.WorkflowStepDao
 import com.grkj.data.enums.CommonDictDataEnum
 import com.grkj.data.enums.JobTicketStatusEnum
 import com.grkj.data.model.dos.IsExceptionSourceStandard
@@ -10,6 +11,7 @@ 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.grkj.data.repository.IHardwareRepository
 import com.sik.sikcore.data.BeanUtils
 import com.sik.sikcore.date.TimeUtils
 import javax.inject.Inject
@@ -22,7 +24,8 @@ import javax.inject.Singleton
 class ExceptionRepository @Inject constructor(
     val exceptionDao: ExceptionDao,
     val jobTicketDao: JobTicketDao,
-    val hardwareDao: HardwareDao
+    val hardwareDao: HardwareDao,
+    val workflowStepDao: WorkflowStepDao
 ) : BaseRepository(),
     IExceptionRepository {
     override fun cancelException(exceptionData: List<IsExceptionStandardVo>) {
@@ -91,9 +94,11 @@ class ExceptionRepository @Inject constructor(
             .forEach { exceptionSource ->
                 when (exceptionSource.sourceDataType) {
                     CommonDictDataEnum.EXCEPTION_SOURCE_TYPE.commonDictRes.find { it.dictLabel == "钥匙" }?.dictValue?.toInt() -> {
-                        val keyInfo = hardwareDao.getKeyInfoById(exceptionSource.sourceDataId)
-                        keyInfo?.exStatus = null
-                        keyInfo?.remark = null
+                        val keyInfo =
+                            hardwareDao.getKeyInfoById(exceptionSource.sourceDataId)
+                        keyInfo?.exStatus =
+                            CommonDictDataEnum.KEY_STATUS.commonDictRes.find { it.dictLabel == "异常" }?.dictValue
+                        keyInfo?.remark = exceptionSource.remark
                         keyInfo?.let {
                             hardwareDao.updateKeyInfo(it)
                         }
@@ -102,8 +107,9 @@ class ExceptionRepository @Inject constructor(
                     CommonDictDataEnum.EXCEPTION_SOURCE_TYPE.commonDictRes.find { it.dictLabel == "挂锁" }?.dictValue?.toInt() -> {
                         val lockInfo =
                             hardwareDao.getLockInfoById(exceptionSource.sourceDataId)
-                        lockInfo?.exStatus = null
-                        lockInfo?.remark = null
+                        lockInfo?.exStatus =
+                            CommonDictDataEnum.PADLOCK_STATUS.commonDictRes.find { it.dictLabel == "异常" }?.dictValue
+                        lockInfo?.remark = exceptionSource.remark
                         lockInfo?.let {
                             hardwareDao.updateLockInfo(it)
                         }
@@ -112,19 +118,23 @@ class ExceptionRepository @Inject constructor(
                     CommonDictDataEnum.EXCEPTION_SOURCE_TYPE.commonDictRes.find { it.dictLabel == "仓位" }?.dictValue?.toInt() -> {
                         val slotsInfo =
                             hardwareDao.getIsLockCabinetSlotBySlotId(exceptionSource.sourceDataId)
-                        slotsInfo?.status = null
-                        slotsInfo?.remark = null
+                        slotsInfo?.status =
+                            CommonDictDataEnum.SLOT_STATUS.commonDictRes.find { it.dictLabel == "异常" }?.dictValue
+                        slotsInfo?.remark = exceptionSource.remark
                         slotsInfo?.let {
                             hardwareDao.updateSlotsInfo(it)
                         }
                     }
 
                     CommonDictDataEnum.EXCEPTION_SOURCE_TYPE.commonDictRes.find { it.dictLabel == "作业" }?.dictValue?.toInt() -> {
-                        jobTicketDao.updateJobTicketExceptionData(
-                            exceptionSource.sourceDataId,
-                            JobTicketStatusEnum.FINISHED.status,
-                            CommonDictDataEnum.EXCEPTION_STATUS.commonDictRes.find { it.dictLabel == "已处理" }?.dictValue?.toInt()
-                        )
+                        val jobTicketData =
+                            jobTicketDao.getTicketRawDataByTicketId(exceptionSource.sourceDataId)
+                        jobTicketData?.exStatus =
+                            CommonDictDataEnum.JOB_TICKET_STATUS.commonDictRes.find { it.dictLabel == "异常" }?.dictValue?.toInt()
+                        jobTicketData?.remark = exceptionSource.remark
+                        jobTicketData?.let {
+                            jobTicketDao.updateTicketData(it)
+                        }
                     }
                 }
             }

+ 45 - 2
data/src/main/java/com/grkj/data/repository/impl/standard/JobTicketRepository.kt

@@ -6,6 +6,8 @@ import com.grkj.data.dao.HardwareDao
 import com.grkj.data.dao.IsolationPointDao
 import com.grkj.data.dao.JobTicketDao
 import com.grkj.data.dao.WorkflowStepDao
+import com.grkj.data.data.MainDomainData
+import com.grkj.data.enums.CommonDictDataEnum
 import com.grkj.data.enums.IsolationPointPowerTypeEnum
 import com.grkj.data.enums.JobTicketStatusEnum
 import com.grkj.data.enums.NextJobPrompt
@@ -263,6 +265,7 @@ class JobTicketRepository @Inject constructor(
         }
         ticketDetailRes?.ticketPointsVOList =
             jobTicketPointDataList?.filterNotNull() as MutableList<TicketDetailRes.JobTicketPointsVO>
+        //填充不可解锁点位
         ticketDetailRes?.noUnlockTicketPointsVOSet =
             ticketDetailRes.ticketPointsVOList?.mapNotNull {
                 jobTicketDao.getVirtualLockConflictPoint(it.pointId, it.lockId, ticketId)
@@ -271,6 +274,12 @@ class JobTicketRepository @Inject constructor(
         return ticketDetailRes
     }
 
+    override fun hasJobCross(ticketId: Long): Boolean {
+        val points = jobTicketDao.getJobTicketPointsDataByTicketId(ticketId)
+        val ticketIds = jobTicketDao.getProgressTicketIdsByPoints(points.map { it.pointId })
+        return ticketIds.size > 1
+    }
+
     override fun deleteTicketByTicketIds(ticketIds: List<Long>) {
         jobTicketDao.deleteJobTicketByTicketIds(ticketIds)
         jobTicketDao.deleteJobTicketKeyByTicketIds(ticketIds)
@@ -283,7 +292,24 @@ class JobTicketRepository @Inject constructor(
     override fun getJobDataPage(
         current: Int, size: Int
     ): List<JobTicketManageVo> {
-        return jobTicketDao.getTicketDataPage(size, current * size)
+        val exStatusList: List<String>? = if (
+            MainDomainData.roleKeys
+                ?.contains(RoleEnum.ADMIN.roleKey) == true
+        ) {
+            // 管理员:不做过滤
+            null
+        } else {
+            // 非管理员:取出所有 dictLabel != "异常" 的那一组值
+            CommonDictDataEnum.JOB_TICKET_STATUS
+                .commonDictRes
+                .filter { it.dictLabel != "异常" }
+                .mapNotNull { it.dictValue }
+                .takeIf { it.isNotEmpty() }
+            // 如果结果正好全为空,也会变成空列表,
+            // 但由于 SQL 写了 ":exStatusList IS NULL",这里必须用
+            // null 代表“不过滤”,而空列表会让 IN () 永远不匹配。
+        }
+        return jobTicketDao.getTicketDataPage(size, current * size, exStatusList)
     }
 
     override fun startJob(jobTicketId: Long?) {
@@ -400,7 +426,24 @@ class JobTicketRepository @Inject constructor(
     }
 
     override fun getInProgressJobSize(): Int {
-        return jobTicketDao.getInProgressJobSize()
+        val exStatusList: List<String>? = if (
+            MainDomainData.roleKeys
+                ?.contains(RoleEnum.ADMIN.roleKey) == true
+        ) {
+            // 管理员:不做过滤
+            null
+        } else {
+            // 非管理员:取出所有 dictLabel != "异常" 的那一组值
+            CommonDictDataEnum.JOB_TICKET_STATUS
+                .commonDictRes
+                .filter { it.dictLabel != "异常" }
+                .mapNotNull { it.dictValue }
+                .takeIf { it.isNotEmpty() }
+            // 如果结果正好全为空,也会变成空列表,
+            // 但由于 SQL 写了 ":exStatusList IS NULL",这里必须用
+            // null 代表“不过滤”,而空列表会让 IN () 永远不匹配。
+        }
+        return jobTicketDao.getInProgressJobSize(exStatusList)
     }
 
     override fun getAllInProgressJob(): List<IsJobTicket> {

+ 1 - 0
ui-base/build.gradle.kts

@@ -66,6 +66,7 @@ dependencies {
     api("io.github.scwang90:refresh-header-classics:3.0.0-alpha")
     api("io.github.scwang90:refresh-footer-classics:3.0.0-alpha")
     api("com.google.android.flexbox:flexbox:3.0.0")
+    api("com.github.liangjingkanji:StateLayout:1.4.2")
     api("com.github.bingoogolapple.BGABadgeView-Android:api:1.2.0")
     kapt("com.github.bingoogolapple.BGABadgeView-Android:compiler:1.2.0")
 //    api("com.licheedev:android-serialport:2.1.5")