Parcourir la source

fix(作业管理):
- 作业和sop的流程步骤单独建表

周文健 il y a 3 mois
Parent
commit
4733c5d44c
29 fichiers modifiés avec 1560 ajouts et 259 suppressions
  1. 308 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/common/EditJobWorkflowSettingFragment.kt
  2. 308 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/common/EditSopWorkflowSettingFragment.kt
  3. 6 1
      app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/EditJobFragment.kt
  4. 6 1
      app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/EditSopFragment.kt
  5. 6 1
      app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/EditSopJobFragment.kt
  6. 19 32
      app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/JobExecuteFragment.kt
  7. 9 7
      app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/MyTodoListFragment.kt
  8. 125 0
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/common/EditJobWorkflowSettingViewModel.kt
  9. 121 0
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/common/EditSopWorkflowSettingViewModel.kt
  10. 21 40
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/job_manage/JobExecuteViewModel.kt
  11. 2 1
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/job_manage/JobViewModel.kt
  12. 11 9
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/job_manage/MyTodoViewModel.kt
  13. 40 0
      app/src/main/res/layout/fragment_my_todo_list.xml
  14. 18 0
      app/src/main/res/navigation/nav_job_manage.xml
  15. 1 0
      app/src/main/res/values-en/strings.xml
  16. 1 0
      app/src/main/res/values-zh/strings.xml
  17. 1 0
      app/src/main/res/values/strings.xml
  18. 26 0
      data/src/main/java/com/grkj/data/dao/IsSopDao.kt
  19. 3 3
      data/src/main/java/com/grkj/data/database/ISCSDatabase.kt
  20. 99 3
      data/src/main/java/com/grkj/data/database/ISCSMigrations.kt
  21. 115 2
      data/src/main/java/com/grkj/data/model/dos/IsJobTicketStep.kt
  22. 131 0
      data/src/main/java/com/grkj/data/model/dos/IsSopWorkflowStep.kt
  23. 17 15
      data/src/main/java/com/grkj/data/model/dos/WorkflowMode.kt
  24. 30 85
      data/src/main/java/com/grkj/data/model/dos/WorkflowStep.kt
  25. 4 5
      data/src/main/java/com/grkj/data/model/local/TodoStepJoin.kt
  26. 16 0
      data/src/main/java/com/grkj/data/repository/ISopRepository.kt
  27. 13 0
      data/src/main/java/com/grkj/data/repository/impl/network/NetworkSopRepository.kt
  28. 74 52
      data/src/main/java/com/grkj/data/repository/impl/standard/JobTicketRepository.kt
  29. 29 2
      data/src/main/java/com/grkj/data/repository/impl/standard/SopRepository.kt

+ 308 - 0
app/src/main/java/com/grkj/iscs/features/main/fragment/common/EditJobWorkflowSettingFragment.kt

@@ -0,0 +1,308 @@
+package com.grkj.iscs.features.main.fragment.common
+
+import android.graphics.drawable.GradientDrawable
+import android.widget.LinearLayout
+import androidx.core.view.isVisible
+import androidx.fragment.app.viewModels
+import com.drake.brv.BindingAdapter
+import com.drake.brv.utils.linear
+import com.drake.brv.utils.models
+import com.drake.brv.utils.setup
+import com.grkj.data.enums.WorkflowStepConfirmTypeEnum
+import com.grkj.data.model.dos.IsJobTicketStep
+import com.grkj.data.model.dos.WorkflowStep
+import com.grkj.iscs.R
+import com.grkj.iscs.common.DataTransferConstants
+import com.grkj.iscs.databinding.FragmentWorkflowSettingBinding
+import com.grkj.iscs.databinding.ItemJobExecuteStepBinding
+import com.grkj.iscs.databinding.ItemWorkFlowStepFunctionBinding
+import com.grkj.iscs.features.main.dialog.TextDropDownDialog
+import com.grkj.iscs.features.main.viewmodel.common.EditJobWorkflowSettingViewModel
+import com.grkj.iscs.features.main.viewmodel.common.WorkflowSettingViewModel
+import com.grkj.ui_base.base.BaseFormFragment
+import com.grkj.ui_base.utils.CommonUtils
+import com.grkj.ui_base.utils.extension.smoothScrollToSmartPosition
+import com.kongzue.dialogx.dialogs.PopTip
+import com.sik.sikcore.data.GlobalDataTempStore
+import com.sik.sikcore.extension.isNullOrEmpty
+import com.sik.sikcore.extension.setDebouncedClickListener
+import dagger.hilt.android.AndroidEntryPoint
+
+/**
+ * 流程模式设置
+ */
+@AndroidEntryPoint
+class EditJobWorkflowSettingFragment : BaseFormFragment<FragmentWorkflowSettingBinding>() {
+    private val viewModel: EditJobWorkflowSettingViewModel by viewModels()
+    override fun getLayoutId(): Int {
+        return R.layout.fragment_workflow_setting
+    }
+
+    override val needInitData: Boolean
+        get() = true
+
+    override val needWatchObject: List<Any?> by lazy {
+        listOf(
+            binding.stepTitleEt,
+            binding.stepTitleShortEt,
+            viewModel.currentConfirmType,
+            viewModel.currentConfirmRole,
+            viewModel.currentConfirmMember,
+            binding.stepDescriptionEt
+        )
+    }
+
+    override fun initView() {
+        binding.back.setDebouncedClickListener {
+            if (isFormDirty) {
+                showUnsavedConfirmDialog()
+            } else {
+                navController.popBackStack()
+            }
+        }
+        binding.cancel.setDebouncedClickListener {
+            if (isFormDirty) {
+                showUnsavedConfirmDialog()
+            } else {
+                navController.popBackStack()
+            }
+        }
+        binding.confirm.setDebouncedClickListener {
+            if (!checkData()) {
+                return@setDebouncedClickListener
+            }
+            viewModel.saveStepsData().observe(this) {
+                PopTip.tip(com.grkj.ui_base.R.string.save_success)
+                resetFormDirty()
+            }
+        }
+        addTextChange(binding.stepTitleEt) {
+            viewModel.currentStep?.stepTitle = it
+        }
+        addTextChange(binding.stepTitleShortEt) {
+            viewModel.currentStep?.stepTitleShort = it
+        }
+        addTextChange(binding.stepDescriptionEt) {
+            viewModel.currentStep?.stepDescription = it
+        }
+        binding.stepConfirmType.setDebouncedClickListener {
+            TextDropDownDialog.showSingle(WorkflowStepConfirmTypeEnum.values().map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataObject = it.type,
+                    dataText = it.description
+                )
+            }, binding.stepConfirmType) { selectedData ->
+                viewModel.currentConfirmType = WorkflowStepConfirmTypeEnum.values()
+                    .find { it.type == selectedData.getData() as Int }
+                    ?: WorkflowStepConfirmTypeEnum.AUTO_CONFIRM
+                binding.stepConfirmType.text = selectedData.getShowText()
+                if (viewModel.currentConfirmType != WorkflowStepConfirmTypeEnum.ROLE_CONFIRM) {
+                    viewModel.currentConfirmRole = null
+                    viewModel.currentConfirmMember = null
+                }
+                viewModel.currentStep?.confirmType =
+                    if (viewModel.currentConfirmType == WorkflowStepConfirmTypeEnum.AUTO_CONFIRM) 1 else 0
+                checkAndSetConfirmData()
+            }
+        }
+        binding.stepConfirmRole.setDebouncedClickListener {
+            TextDropDownDialog.showSingle(viewModel.allRole.map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataTag = it.roleKey,
+                    dataText = it.roleName
+                )
+            }, binding.stepConfirmRole) { selectedData ->
+                viewModel.currentConfirmRole = selectedData.getTag()
+                binding.stepConfirmRole.text = selectedData.getShowText()
+                viewModel.currentConfirmMember = null
+                binding.stepConfirmMember.text = ""
+                viewModel.currentStep?.confirmRoleCode = viewModel.currentConfirmRole
+            }
+        }
+        binding.stepConfirmMember.setDebouncedClickListener {
+            val filterUsers =
+                viewModel.allUser.filter {
+                    viewModel.currentConfirmRole.isNullOrEmpty() || it.roleKeys.contains(
+                        viewModel.currentConfirmRole
+                    )
+                }
+            if (filterUsers.isEmpty()) {
+                PopTip.tip(R.string.current_role_no_user)
+                return@setDebouncedClickListener
+            }
+            TextDropDownDialog.showSingle(filterUsers.map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataId = it.userId,
+                    dataText = it.nickName
+                )
+            }, binding.stepConfirmMember) { selectedData ->
+                viewModel.currentConfirmMember = selectedData.getId()
+                binding.stepConfirmMember.text = selectedData.getShowText()
+                viewModel.currentStep?.confirmUser = viewModel.currentConfirmMember
+            }
+        }
+        binding.workflowModeRv.linear(orientation = LinearLayout.HORIZONTAL).setup {
+            addType<IsJobTicketStep>(R.layout.item_job_execute_step)
+            onBind {
+                onStepRVListBinding(this)
+            }
+        }
+        binding.stepFunctionRv.linear().setup {
+            addType<String>(R.layout.item_work_flow_step_function)
+            onBind {
+                val itemBinding = getBinding<ItemWorkFlowStepFunctionBinding>()
+                val item = getModel<String>()
+                itemBinding.stepFunction.text = item
+            }
+        }
+    }
+
+    private fun checkData(): Boolean {
+//        if (WorkflowStepConfirmTypeEnum.ROLE_CONFIRM == viewModel.currentConfirmType &&
+//            viewModel.currentConfirmRole.isNullOrEmpty()
+//        ) {
+//            PopTip.tip(R.string.please_select_step_confirm_role)
+//            return false
+//        }
+        return true
+    }
+
+    private fun BindingAdapter.BindingViewHolder.onStepRVListBinding(holder: BindingAdapter.BindingViewHolder) {
+        val itemBinding = holder.getBinding<ItemJobExecuteStepBinding>()
+        val item = holder.getModel<IsJobTicketStep>()
+        itemBinding.stepIconIv.setImageResource(getStepIcon(item))
+        itemBinding.stepNameTv.text = item.stepTitleShort
+        itemBinding.stepIndexTv.text = item.stepIndex.toString()
+        itemBinding.dividerIv.isVisible = item.stepIndex != viewModel.workflowSteps.last().stepIndex
+        val bg = itemBinding.stepLayout.background
+        if (item.stepId == viewModel.currentStep?.stepId) {
+            if (bg is GradientDrawable) {
+                bg.mutate()  // 拷贝一份,避免影响到其它引用了同一个 drawable 的 view
+                bg.setColor(requireContext().getColor(R.color.color_ffec99))
+            }
+        } else {
+            if (bg is GradientDrawable) {
+                bg.mutate()  // 拷贝一份,避免影响到其它引用了同一个 drawable 的 view
+                bg.setColor(requireContext().getColor(R.color.color_e9ecf4))
+            }
+        }
+        itemBinding.stepLayout.setDebouncedClickListener {
+            viewModel.currentStep = item
+            adapter.notifyDataSetChanged()
+            binding.workflowModeRv.smoothScrollToSmartPosition(modelPosition)
+            checkCurrentStepData()
+            resetFormDirty()
+        }
+    }
+
+    /**
+     * 获取步骤图标
+     */
+    private fun getStepIcon(workflowStep: IsJobTicketStep): Int {
+        return when {
+            workflowStep.stepTitleShort?.contains(
+                CommonUtils.getStr(com.grkj.ui_base.R.string.recognize_work_content).toString()
+            ) == true -> R.mipmap.icon_loto_step_1
+
+            workflowStep.stepTitleShort?.contains(
+                CommonUtils.getStr(com.grkj.ui_base.R.string.power_isolation_way).toString()
+            ) == true -> R.mipmap.icon_loto_step_2
+
+            workflowStep.stepTitleShort?.contains(
+                CommonUtils.getStr(com.grkj.ui_base.R.string.shutdown).toString()
+            ) == true -> R.mipmap.icon_loto_step_4
+
+            workflowStep.stepTitleShort?.contains(
+                CommonUtils.getStr(com.grkj.ui_base.R.string.ensure_power_isolation).toString()
+            ) == true -> R.mipmap.icon_loto_step_6
+
+            workflowStep.stepTitleShort?.contains(
+                CommonUtils.getStr(com.grkj.ui_base.R.string.check_before_unlocking).toString()
+            ) == true -> R.mipmap.icon_loto_step_7
+
+            workflowStep.stepTitleShort?.contains(
+                CommonUtils.getStr(com.grkj.ui_base.R.string.unlock_and_restore_switch).toString()
+            ) == true -> R.mipmap.icon_loto_step_8
+
+            workflowStep.enableSetLocker || workflowStep.enableSetColocker -> R.mipmap.icon_step_select_member
+            workflowStep.enableLock -> R.mipmap.icon_step_lock
+            workflowStep.enableColock -> R.mipmap.icon_step_colock
+            workflowStep.enableUnlock -> R.mipmap.icon_step_unlock
+            else -> 0
+        }
+    }
+
+    override fun initData() {
+        super.initData()
+        viewModel.modeId = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_WORKFLOW_SETTING_MODE_ID) ?: 0
+        viewModel.ticketId = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_JOB_TICKET_ID) ?: 0
+        val previewStepTitle = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_PREVIEW_STEP_TITLE_DATA) ?: ""
+        val previewStepIcon = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_PREVIEW_STEP_ICON_DATA) ?: 0
+        binding.previewStepTitle.text = previewStepTitle
+        binding.previewStepIv.setImageResource(previewStepIcon)
+        viewModel.getSettingData().observe(this) {
+            viewModel.getWorkflowSteps().observe(this) {
+                if (viewModel.workflowSteps.isEmpty()) {
+                    PopTip.tip(R.string.current_workflow_mode_error)
+                    navController.popBackStack()
+                    return@observe
+                }
+                binding.workflowModeRv.models = viewModel.workflowSteps
+                viewModel.currentStep = viewModel.workflowSteps[0]
+                checkCurrentStepData()
+            }
+        }
+    }
+
+    /**
+     * 检查和设置当前步骤的数据
+     */
+    private fun checkCurrentStepData() {
+        viewModel.currentStep?.let {
+            binding.stepTitleEt.setText(it.stepTitle)
+            binding.stepTitleShortEt.setText(it.stepTitleShort)
+            binding.stepDescriptionEt.setText(it.stepDescription)
+            binding.stepFunctionRv.models = viewModel.checkAndSetStepFunction()
+            if (it.confirmType != 0) {
+                viewModel.currentConfirmType = WorkflowStepConfirmTypeEnum.AUTO_CONFIRM
+            } else {
+                if (it.confirmUser == null) {
+                    viewModel.currentConfirmType = WorkflowStepConfirmTypeEnum.CLICK_CONFIRM
+                } else {
+                    viewModel.currentConfirmType = WorkflowStepConfirmTypeEnum.ROLE_CONFIRM
+                }
+            }
+            viewModel.currentConfirmRole = viewModel.currentStep?.confirmRoleCode
+            viewModel.currentConfirmMember = viewModel.currentStep?.confirmUser
+            checkAndSetConfirmData()
+            initDataComplete()
+        }
+    }
+
+    /**
+     * 检查和设置执行确认数据
+     */
+    private fun checkAndSetConfirmData() {
+        binding.stepConfirmType.text = viewModel.currentConfirmType.description
+        viewModel.currentConfirmRole?.let { roleKey ->
+            binding.stepConfirmRole.text =
+                viewModel.allRole.find { it.roleKey == roleKey }?.roleName
+        }
+        viewModel.currentConfirmMember?.let { userId ->
+            binding.stepConfirmMember.text =
+                viewModel.allUser.find { it.userId == userId }?.nickName
+        }
+        binding.stepConfirmRole.isVisible =
+            viewModel.currentConfirmType == WorkflowStepConfirmTypeEnum.ROLE_CONFIRM
+        binding.stepConfirmRoleTv.isVisible =
+            viewModel.currentConfirmType == WorkflowStepConfirmTypeEnum.ROLE_CONFIRM
+        binding.stepConfirmMember.isVisible =
+            viewModel.currentConfirmType == WorkflowStepConfirmTypeEnum.ROLE_CONFIRM
+        binding.stepConfirmMemberTv.isVisible =
+            viewModel.currentConfirmType == WorkflowStepConfirmTypeEnum.ROLE_CONFIRM
+    }
+}

+ 308 - 0
app/src/main/java/com/grkj/iscs/features/main/fragment/common/EditSopWorkflowSettingFragment.kt

@@ -0,0 +1,308 @@
+package com.grkj.iscs.features.main.fragment.common
+
+import android.graphics.drawable.GradientDrawable
+import android.widget.LinearLayout
+import androidx.core.view.isVisible
+import androidx.fragment.app.viewModels
+import com.drake.brv.BindingAdapter
+import com.drake.brv.utils.linear
+import com.drake.brv.utils.models
+import com.drake.brv.utils.setup
+import com.grkj.data.enums.WorkflowStepConfirmTypeEnum
+import com.grkj.data.model.dos.IsSopWorkflowStep
+import com.grkj.data.model.dos.WorkflowStep
+import com.grkj.iscs.R
+import com.grkj.iscs.common.DataTransferConstants
+import com.grkj.iscs.databinding.FragmentWorkflowSettingBinding
+import com.grkj.iscs.databinding.ItemJobExecuteStepBinding
+import com.grkj.iscs.databinding.ItemWorkFlowStepFunctionBinding
+import com.grkj.iscs.features.main.dialog.TextDropDownDialog
+import com.grkj.iscs.features.main.viewmodel.common.EditSopWorkflowSettingViewModel
+import com.grkj.iscs.features.main.viewmodel.common.WorkflowSettingViewModel
+import com.grkj.ui_base.base.BaseFormFragment
+import com.grkj.ui_base.utils.CommonUtils
+import com.grkj.ui_base.utils.extension.smoothScrollToSmartPosition
+import com.kongzue.dialogx.dialogs.PopTip
+import com.sik.sikcore.data.GlobalDataTempStore
+import com.sik.sikcore.extension.isNullOrEmpty
+import com.sik.sikcore.extension.setDebouncedClickListener
+import dagger.hilt.android.AndroidEntryPoint
+
+/**
+ * 流程模式设置
+ */
+@AndroidEntryPoint
+class EditSopWorkflowSettingFragment : BaseFormFragment<FragmentWorkflowSettingBinding>() {
+    private val viewModel: EditSopWorkflowSettingViewModel by viewModels()
+    override fun getLayoutId(): Int {
+        return R.layout.fragment_workflow_setting
+    }
+
+    override val needInitData: Boolean
+        get() = true
+
+    override val needWatchObject: List<Any?> by lazy {
+        listOf(
+            binding.stepTitleEt,
+            binding.stepTitleShortEt,
+            viewModel.currentConfirmType,
+            viewModel.currentConfirmRole,
+            viewModel.currentConfirmMember,
+            binding.stepDescriptionEt
+        )
+    }
+
+    override fun initView() {
+        binding.back.setDebouncedClickListener {
+            if (isFormDirty) {
+                showUnsavedConfirmDialog()
+            } else {
+                navController.popBackStack()
+            }
+        }
+        binding.cancel.setDebouncedClickListener {
+            if (isFormDirty) {
+                showUnsavedConfirmDialog()
+            } else {
+                navController.popBackStack()
+            }
+        }
+        binding.confirm.setDebouncedClickListener {
+            if (!checkData()) {
+                return@setDebouncedClickListener
+            }
+            viewModel.saveStepsData().observe(this) {
+                PopTip.tip(com.grkj.ui_base.R.string.save_success)
+                resetFormDirty()
+            }
+        }
+        addTextChange(binding.stepTitleEt) {
+            viewModel.currentStep?.stepTitle = it
+        }
+        addTextChange(binding.stepTitleShortEt) {
+            viewModel.currentStep?.stepTitleShort = it
+        }
+        addTextChange(binding.stepDescriptionEt) {
+            viewModel.currentStep?.stepDescription = it
+        }
+        binding.stepConfirmType.setDebouncedClickListener {
+            TextDropDownDialog.showSingle(WorkflowStepConfirmTypeEnum.values().map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataObject = it.type,
+                    dataText = it.description
+                )
+            }, binding.stepConfirmType) { selectedData ->
+                viewModel.currentConfirmType = WorkflowStepConfirmTypeEnum.values()
+                    .find { it.type == selectedData.getData() as Int }
+                    ?: WorkflowStepConfirmTypeEnum.AUTO_CONFIRM
+                binding.stepConfirmType.text = selectedData.getShowText()
+                if (viewModel.currentConfirmType != WorkflowStepConfirmTypeEnum.ROLE_CONFIRM) {
+                    viewModel.currentConfirmRole = null
+                    viewModel.currentConfirmMember = null
+                }
+                viewModel.currentStep?.confirmType =
+                    if (viewModel.currentConfirmType == WorkflowStepConfirmTypeEnum.AUTO_CONFIRM) 1 else 0
+                checkAndSetConfirmData()
+            }
+        }
+        binding.stepConfirmRole.setDebouncedClickListener {
+            TextDropDownDialog.showSingle(viewModel.allRole.map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataTag = it.roleKey,
+                    dataText = it.roleName
+                )
+            }, binding.stepConfirmRole) { selectedData ->
+                viewModel.currentConfirmRole = selectedData.getTag()
+                binding.stepConfirmRole.text = selectedData.getShowText()
+                viewModel.currentConfirmMember = null
+                binding.stepConfirmMember.text = ""
+                viewModel.currentStep?.confirmRoleCode = viewModel.currentConfirmRole
+            }
+        }
+        binding.stepConfirmMember.setDebouncedClickListener {
+            val filterUsers =
+                viewModel.allUser.filter {
+                    viewModel.currentConfirmRole.isNullOrEmpty() || it.roleKeys.contains(
+                        viewModel.currentConfirmRole
+                    )
+                }
+            if (filterUsers.isEmpty()) {
+                PopTip.tip(R.string.current_role_no_user)
+                return@setDebouncedClickListener
+            }
+            TextDropDownDialog.showSingle(filterUsers.map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataId = it.userId,
+                    dataText = it.nickName
+                )
+            }, binding.stepConfirmMember) { selectedData ->
+                viewModel.currentConfirmMember = selectedData.getId()
+                binding.stepConfirmMember.text = selectedData.getShowText()
+                viewModel.currentStep?.confirmUser = viewModel.currentConfirmMember
+            }
+        }
+        binding.workflowModeRv.linear(orientation = LinearLayout.HORIZONTAL).setup {
+            addType<IsSopWorkflowStep>(R.layout.item_job_execute_step)
+            onBind {
+                onStepRVListBinding(this)
+            }
+        }
+        binding.stepFunctionRv.linear().setup {
+            addType<String>(R.layout.item_work_flow_step_function)
+            onBind {
+                val itemBinding = getBinding<ItemWorkFlowStepFunctionBinding>()
+                val item = getModel<String>()
+                itemBinding.stepFunction.text = item
+            }
+        }
+    }
+
+    private fun checkData(): Boolean {
+//        if (WorkflowStepConfirmTypeEnum.ROLE_CONFIRM == viewModel.currentConfirmType &&
+//            viewModel.currentConfirmRole.isNullOrEmpty()
+//        ) {
+//            PopTip.tip(R.string.please_select_step_confirm_role)
+//            return false
+//        }
+        return true
+    }
+
+    private fun BindingAdapter.BindingViewHolder.onStepRVListBinding(holder: BindingAdapter.BindingViewHolder) {
+        val itemBinding = holder.getBinding<ItemJobExecuteStepBinding>()
+        val item = holder.getModel<IsSopWorkflowStep>()
+        itemBinding.stepIconIv.setImageResource(getStepIcon(item))
+        itemBinding.stepNameTv.text = item.stepTitleShort
+        itemBinding.stepIndexTv.text = item.stepIndex.toString()
+        itemBinding.dividerIv.isVisible = item.stepIndex != viewModel.workflowSteps.last().stepIndex
+        val bg = itemBinding.stepLayout.background
+        if (item.stepId == viewModel.currentStep?.stepId) {
+            if (bg is GradientDrawable) {
+                bg.mutate()  // 拷贝一份,避免影响到其它引用了同一个 drawable 的 view
+                bg.setColor(requireContext().getColor(R.color.color_ffec99))
+            }
+        } else {
+            if (bg is GradientDrawable) {
+                bg.mutate()  // 拷贝一份,避免影响到其它引用了同一个 drawable 的 view
+                bg.setColor(requireContext().getColor(R.color.color_e9ecf4))
+            }
+        }
+        itemBinding.stepLayout.setDebouncedClickListener {
+            viewModel.currentStep = item
+            adapter.notifyDataSetChanged()
+            binding.workflowModeRv.smoothScrollToSmartPosition(modelPosition)
+            checkCurrentStepData()
+            resetFormDirty()
+        }
+    }
+
+    /**
+     * 获取步骤图标
+     */
+    private fun getStepIcon(workflowStep: IsSopWorkflowStep): Int {
+        return when {
+            workflowStep.stepTitleShort?.contains(
+                CommonUtils.getStr(com.grkj.ui_base.R.string.recognize_work_content).toString()
+            ) == true -> R.mipmap.icon_loto_step_1
+
+            workflowStep.stepTitleShort?.contains(
+                CommonUtils.getStr(com.grkj.ui_base.R.string.power_isolation_way).toString()
+            ) == true -> R.mipmap.icon_loto_step_2
+
+            workflowStep.stepTitleShort?.contains(
+                CommonUtils.getStr(com.grkj.ui_base.R.string.shutdown).toString()
+            ) == true -> R.mipmap.icon_loto_step_4
+
+            workflowStep.stepTitleShort?.contains(
+                CommonUtils.getStr(com.grkj.ui_base.R.string.ensure_power_isolation).toString()
+            ) == true -> R.mipmap.icon_loto_step_6
+
+            workflowStep.stepTitleShort?.contains(
+                CommonUtils.getStr(com.grkj.ui_base.R.string.check_before_unlocking).toString()
+            ) == true -> R.mipmap.icon_loto_step_7
+
+            workflowStep.stepTitleShort?.contains(
+                CommonUtils.getStr(com.grkj.ui_base.R.string.unlock_and_restore_switch).toString()
+            ) == true -> R.mipmap.icon_loto_step_8
+
+            workflowStep.enableSetLocker || workflowStep.enableSetColocker -> R.mipmap.icon_step_select_member
+            workflowStep.enableLock -> R.mipmap.icon_step_lock
+            workflowStep.enableColock -> R.mipmap.icon_step_colock
+            workflowStep.enableUnlock -> R.mipmap.icon_step_unlock
+            else -> 0
+        }
+    }
+
+    override fun initData() {
+        super.initData()
+        viewModel.modeId = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_WORKFLOW_SETTING_MODE_ID) ?: 0
+        viewModel.sopId = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_EDIT_SOP_SOP_ID) ?: 0
+        val previewStepTitle = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_PREVIEW_STEP_TITLE_DATA) ?: ""
+        val previewStepIcon = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_PREVIEW_STEP_ICON_DATA) ?: 0
+        binding.previewStepTitle.text = previewStepTitle
+        binding.previewStepIv.setImageResource(previewStepIcon)
+        viewModel.getSettingData().observe(this) {
+            viewModel.getWorkflowSteps().observe(this) {
+                if (viewModel.workflowSteps.isEmpty()) {
+                    PopTip.tip(R.string.current_workflow_mode_error)
+                    navController.popBackStack()
+                    return@observe
+                }
+                binding.workflowModeRv.models = viewModel.workflowSteps
+                viewModel.currentStep = viewModel.workflowSteps[0]
+                checkCurrentStepData()
+            }
+        }
+    }
+
+    /**
+     * 检查和设置当前步骤的数据
+     */
+    private fun checkCurrentStepData() {
+        viewModel.currentStep?.let {
+            binding.stepTitleEt.setText(it.stepTitle)
+            binding.stepTitleShortEt.setText(it.stepTitleShort)
+            binding.stepDescriptionEt.setText(it.stepDescription)
+            binding.stepFunctionRv.models = viewModel.checkAndSetStepFunction()
+            if (it.confirmType != 0) {
+                viewModel.currentConfirmType = WorkflowStepConfirmTypeEnum.AUTO_CONFIRM
+            } else {
+                if (it.confirmUser == null) {
+                    viewModel.currentConfirmType = WorkflowStepConfirmTypeEnum.CLICK_CONFIRM
+                } else {
+                    viewModel.currentConfirmType = WorkflowStepConfirmTypeEnum.ROLE_CONFIRM
+                }
+            }
+            viewModel.currentConfirmRole = viewModel.currentStep?.confirmRoleCode
+            viewModel.currentConfirmMember = viewModel.currentStep?.confirmUser
+            checkAndSetConfirmData()
+            initDataComplete()
+        }
+    }
+
+    /**
+     * 检查和设置执行确认数据
+     */
+    private fun checkAndSetConfirmData() {
+        binding.stepConfirmType.text = viewModel.currentConfirmType.description
+        viewModel.currentConfirmRole?.let { roleKey ->
+            binding.stepConfirmRole.text =
+                viewModel.allRole.find { it.roleKey == roleKey }?.roleName
+        }
+        viewModel.currentConfirmMember?.let { userId ->
+            binding.stepConfirmMember.text =
+                viewModel.allUser.find { it.userId == userId }?.nickName
+        }
+        binding.stepConfirmRole.isVisible =
+            viewModel.currentConfirmType == WorkflowStepConfirmTypeEnum.ROLE_CONFIRM
+        binding.stepConfirmRoleTv.isVisible =
+            viewModel.currentConfirmType == WorkflowStepConfirmTypeEnum.ROLE_CONFIRM
+        binding.stepConfirmMember.isVisible =
+            viewModel.currentConfirmType == WorkflowStepConfirmTypeEnum.ROLE_CONFIRM
+        binding.stepConfirmMemberTv.isVisible =
+            viewModel.currentConfirmType == WorkflowStepConfirmTypeEnum.ROLE_CONFIRM
+    }
+}

+ 6 - 1
app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/EditJobFragment.kt

@@ -131,6 +131,11 @@ class EditJobFragment : BaseFormFragment<FragmentEditJobBinding>() {
                     DataTransferConstants.KEY_WORKFLOW_SETTING_MODE_ID,
                     selectedModeId ?: 0
                 )
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_JOB_TICKET_ID,
+                    viewModel.jobTicketData?.ticketId ?: 0
+                )
             GlobalDataTempStore.getInstance()
                 .saveData(
                     DataTransferConstants.KEY_PREVIEW_STEP_TITLE_DATA,
@@ -141,7 +146,7 @@ class EditJobFragment : BaseFormFragment<FragmentEditJobBinding>() {
                     DataTransferConstants.KEY_PREVIEW_STEP_ICON_DATA,
                     R.mipmap.icon_job_manage_create_job
                 )
-            navController.navigate(R.id.action_editJobFragment_to_workflowSettingFragment)
+            navController.navigate(R.id.action_editJobFragment_to_editJobWorkflowSettingFragment)
         }
         binding.selectPointTv.setDebouncedClickListener {
             if (selectedWorkstationId == null) {

+ 6 - 1
app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/EditSopFragment.kt

@@ -118,6 +118,11 @@ class EditSopFragment : BaseFormFragment<FragmentEditSopBinding>() {
                     DataTransferConstants.KEY_WORKFLOW_SETTING_MODE_ID,
                     selectedModeId ?: 0
                 )
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_EDIT_SOP_SOP_ID,
+                    viewModel.selectedSopData?.sopId ?: 0
+                )
             GlobalDataTempStore.getInstance()
                 .saveData(
                     DataTransferConstants.KEY_PREVIEW_STEP_TITLE_DATA,
@@ -128,7 +133,7 @@ class EditSopFragment : BaseFormFragment<FragmentEditSopBinding>() {
                     DataTransferConstants.KEY_PREVIEW_STEP_ICON_DATA,
                     R.mipmap.icon_job_manage_create_sop
                 )
-            navController.navigate(R.id.action_editSopFragment_to_workflowSettingFragment)
+            navController.navigate(R.id.action_editSopFragment_to_editSopWorkflowSettingFragment)
         }
         binding.selectPointTv.setDebouncedClickListener {
             if (selectedWorkstationId == null) {

+ 6 - 1
app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/EditSopJobFragment.kt

@@ -142,6 +142,11 @@ class EditSopJobFragment : BaseFormFragment<FragmentEditSopJobBinding>() {
                     DataTransferConstants.KEY_WORKFLOW_SETTING_MODE_ID,
                     selectedSop?.modeId ?: 0
                 )
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_JOB_TICKET_ID,
+                    viewModel.jobTicketData?.ticketId ?: 0
+                )
             GlobalDataTempStore.getInstance()
                 .saveData(
                     DataTransferConstants.KEY_PREVIEW_STEP_TITLE_DATA,
@@ -152,7 +157,7 @@ class EditSopJobFragment : BaseFormFragment<FragmentEditSopJobBinding>() {
                     DataTransferConstants.KEY_PREVIEW_STEP_ICON_DATA,
                     R.mipmap.icon_job_manage_create_job
                 )
-            navController.navigate(R.id.action_editSopJobFragment_to_workflowSettingFragment)
+            navController.navigate(R.id.action_editSopJobFragment_to_editJobWorkflowSettingFragment)
         }
         binding.selectMemberTv.setDebouncedClickListener {
             if (selectedWorkstationId == null) {

+ 19 - 32
app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/JobExecuteFragment.kt

@@ -1,7 +1,6 @@
 package com.grkj.iscs.features.main.fragment.job_manage
 
 import android.graphics.drawable.GradientDrawable
-import android.view.Gravity
 import android.view.ViewGroup
 import android.widget.LinearLayout
 import androidx.core.content.ContextCompat
@@ -16,26 +15,24 @@ import com.drake.brv.utils.grid
 import com.drake.brv.utils.linear
 import com.drake.brv.utils.models
 import com.drake.brv.utils.setup
+import com.grkj.data.data.EventConstants
+import com.grkj.data.data.MainDomainData
+import com.grkj.data.data.Type
 import com.grkj.data.enums.RoleEnum
 import com.grkj.data.model.vo.IsJobTicketPointsDataVo
 import com.grkj.data.model.vo.IsJobTicketStepDataVo
 import com.grkj.data.model.vo.IsJobTicketUserDataVo
+import com.grkj.data.model.vo.JobTicketGroupInfoVo
 import com.grkj.iscs.R
 import com.grkj.iscs.common.DataTransferConstants
 import com.grkj.iscs.databinding.FragmentJobExecuteBinding
 import com.grkj.iscs.databinding.ItemJobExecuteColockBinding
 import com.grkj.iscs.databinding.ItemJobExecutePointBinding
 import com.grkj.iscs.databinding.ItemJobExecuteStepBinding
+import com.grkj.iscs.features.main.dialog.CheckFaceDialog
 import com.grkj.iscs.features.main.viewmodel.job_manage.JobExecuteViewModel
 import com.grkj.shared.model.EventBean
 import com.grkj.ui_base.base.BaseFragment
-import com.grkj.data.data.EventConstants
-import com.grkj.data.data.MainDomainData
-import com.grkj.data.data.Type
-import com.grkj.data.model.dos.WorkflowStep
-import com.grkj.data.model.vo.JobTicketGroupInfoVo
-import com.grkj.iscs.features.main.dialog.CheckFaceDialog
-import com.grkj.iscs.features.main.dialog.TextDropDownDialog
 import com.grkj.ui_base.dialog.TipDialog
 import com.grkj.ui_base.utils.CommonUtils
 import com.grkj.ui_base.utils.event.FlashTipEvent
@@ -44,12 +41,10 @@ import com.grkj.ui_base.utils.event.UiEvent
 import com.grkj.ui_base.utils.extension.tip
 import com.grkj.ui_base.utils.extension.toggleExpandView
 import com.kongzue.dialogx.dialogs.BottomMenu
-import com.kongzue.dialogx.dialogs.PopMenu
 import com.kongzue.dialogx.dialogs.PopTip
 import com.sik.sikcore.data.GlobalDataTempStore
 import com.sik.sikcore.extension.setDebouncedClickListener
 import dagger.hilt.android.AndroidEntryPoint
-import kotlin.getValue
 
 /**
  * 作业执行界面
@@ -208,9 +203,7 @@ class JobExecuteFragment : BaseFragment<FragmentJobExecuteBinding>() {
         binding.colockerLayout.isVisible = index == 2
         binding.dataTitleTv.text = when (index) {
             0 -> CommonUtils.getStr(
-                R.string.job_execute_step_description,
-                viewModel.workflowSteps.find { it.stepId == viewModel.currentStepData?.workflowStepId }?.stepTitle
-                    ?: ""
+                R.string.job_execute_step_description, viewModel.currentStepData?.stepTitle ?: ""
             ).toString()
 
             1 -> CommonUtils.getStr(R.string.job_execute_lock_status_title).toString()
@@ -222,9 +215,8 @@ class JobExecuteFragment : BaseFragment<FragmentJobExecuteBinding>() {
     private fun BindingAdapter.BindingViewHolder.onStepRVListBinding(holder: BindingAdapter.BindingViewHolder) {
         val itemBinding = holder.getBinding<ItemJobExecuteStepBinding>()
         val item = holder.getModel<IsJobTicketStepDataVo>()
-        itemBinding.stepIconIv.setImageResource(getStepIcon(viewModel.workflowSteps.find { it.stepId == item.workflowStepId }))
-        itemBinding.stepNameTv.text =
-            viewModel.workflowSteps.find { it.stepId == item.workflowStepId }?.stepTitleShort
+        itemBinding.stepIconIv.setImageResource(getStepIcon(viewModel.currentStepData))
+        itemBinding.stepNameTv.text = viewModel.currentStepData?.stepTitleShort
         itemBinding.stepIndexTv.text = item.stepIndex.toString()
         itemBinding.dividerIv.isVisible = item.stepId != viewModel.ticketStep.last().stepId
         val bg = itemBinding.stepLayout.background
@@ -249,7 +241,7 @@ class JobExecuteFragment : BaseFragment<FragmentJobExecuteBinding>() {
         }
         //点击确认的时候需要
         itemBinding.stepLayout.setDebouncedClickListener {
-            val workflowStep = viewModel.workflowSteps.find { it.stepId == item.workflowStepId }
+            val workflowStep = viewModel.currentStepData
             viewModel.canCheckStep().observe(this@JobExecuteFragment) {
                 if (it) {
                     if (item.stepIndex < viewModel.currentStepData?.stepIndex!!) {
@@ -285,7 +277,7 @@ class JobExecuteFragment : BaseFragment<FragmentJobExecuteBinding>() {
      * 点击确认
      */
     private fun stepClickConfirm(
-        adapter: BindingAdapter, item: IsJobTicketStepDataVo, workflowStep: WorkflowStep?
+        adapter: BindingAdapter, item: IsJobTicketStepDataVo, workflowStep: IsJobTicketStepDataVo?
     ) {
         if (!checkSelectMember(workflowStep)) {
             if (viewModel.stepConditionsComplete(workflowStep)) {
@@ -320,9 +312,9 @@ class JobExecuteFragment : BaseFragment<FragmentJobExecuteBinding>() {
      * 检查是否是选择人员
      */
     private fun checkSelectMember(
-        workflowStep: WorkflowStep?
+        workflowStep: IsJobTicketStepDataVo?
     ): Boolean {
-        val currentWorkflowStep = viewModel.getCurrentWorkflowStep()
+        val currentWorkflowStep = viewModel.currentStepData
         if (workflowStep?.enableSetLocker == true || workflowStep?.enableSetColocker == true && (currentWorkflowStep?.enableAddColocker == true || currentWorkflowStep?.enableReduceColocker == true)) {
             GlobalDataTempStore.getInstance().saveData(
                 DataTransferConstants.KEY_CAN_SELECT_COLOCKER,
@@ -360,7 +352,7 @@ class JobExecuteFragment : BaseFragment<FragmentJobExecuteBinding>() {
         itemBinding.name.text = item.nickName
     }
 
-    private fun getStepIcon(workflowStep: WorkflowStep?): Int {
+    private fun getStepIcon(workflowStep: IsJobTicketStepDataVo?): Int {
         if (workflowStep == null) {
             return 0
         }
@@ -451,8 +443,7 @@ class JobExecuteFragment : BaseFragment<FragmentJobExecuteBinding>() {
                 }
                 checkLayout(2)
                 (event.data as RFIDCardReadEvent).let {
-                    val currentWorkflowStep =
-                        viewModel.workflowSteps.find { it.stepId == viewModel.currentStepData?.workflowStepId }
+                    val currentWorkflowStep = viewModel.currentStepData
                     //当前步骤能加共锁并且锁已经上锁或者当前步骤能解共锁并且锁已经上锁
                     if ((currentWorkflowStep?.enableColock == true || currentWorkflowStep?.enableReleaseColock == true) && viewModel.ticketPoints.all { it.pointStatus == "1" }) {
                         viewModel.getUserIdByCardRfid(it.rfidNo).observe(this) { userId ->
@@ -540,8 +531,7 @@ class JobExecuteFragment : BaseFragment<FragmentJobExecuteBinding>() {
      * 检查流程是否完成
      */
     private fun checkStepComplete() {
-        val workflowStep =
-            viewModel.workflowSteps.find { it.stepId == viewModel.currentStepData?.workflowStepId }
+        val workflowStep = viewModel.currentStepData
         if (viewModel.stepConditionsComplete(workflowStep) && workflowStep?.confirmType != 0) {
             viewModel.currentStepData = viewModel.ticketStep.firstOrNull { it.stepStatus == "0" }
             logger.info("当前步骤数据:${viewModel.currentStepData}")
@@ -582,8 +572,7 @@ class JobExecuteFragment : BaseFragment<FragmentJobExecuteBinding>() {
         binding.colockInfo.text =
             "${viewModel.ticketUser.filter { it.userRole == RoleEnum.JTCOLOCKER.roleKey }.size}/${viewModel.ticketUser.count { it.userRole == RoleEnum.JTCOLOCKER.roleKey && it.jobStatus?.toInt() ?: 0 >= 1 }}/${viewModel.ticketUser.count { it.userRole == RoleEnum.JTCOLOCKER.roleKey && it.jobStatus == "2" }}"
         viewModel.groupInfo = viewModel.ticketPoints.groupBy { it.groupId to it.groupName }.filter {
-            val currentWorkflowStep =
-                viewModel.workflowSteps.find { it.stepId == viewModel.currentStepData?.workflowStepId }
+            val currentWorkflowStep = viewModel.currentStepData
             if (currentWorkflowStep?.enableLock == true) {
                 logger.info("当前步骤上锁:${it.value.all { it.pointStatus == "0" }}")
                 it.value.all { it.pointStatus == "0" }
@@ -597,8 +586,7 @@ class JobExecuteFragment : BaseFragment<FragmentJobExecuteBinding>() {
         if (viewModel.currentStepData?.stepIndex == null) {
             binding.finishJob.isVisible = true
         } else {
-            val currentStep =
-                viewModel.workflowSteps.find { it.stepId == viewModel.currentStepData?.workflowStepId }
+            val currentStep = viewModel.currentStepData
             //步骤开启取消作业,并且点位还没有上锁,显示取消作业按钮
             binding.cancelJob.isVisible =
                 currentStep?.enableCancelJob == true && (viewModel.ticketPoints.all { it.pointStatus == "0" } || (viewModel.isUnlockFirst && currentStep?.enableCancelJob == true && viewModel.ticketPoints.all { it.pointStatus == "1" }))
@@ -640,7 +628,7 @@ class JobExecuteFragment : BaseFragment<FragmentJobExecuteBinding>() {
                     viewModel.currentStepData =
                         viewModel.ticketStep.firstOrNull { it.stepStatus == "0" }
                     binding.stepDescriptionTv.text =
-                        viewModel.workflowSteps.find { it.stepId == viewModel.currentStepData?.workflowStepId }?.stepDescription
+                        viewModel.currentStepData?.stepDescription
                     refreshTicketUser()
                     checkCurrentStep()
                     checkLayout(currentTab)
@@ -697,8 +685,7 @@ class JobExecuteFragment : BaseFragment<FragmentJobExecuteBinding>() {
         }
         if (viewModel.checkMemberFinish) {
             viewModel.updateLockerAndColockerData().observe(this) {
-                val workflowStep =
-                    viewModel.workflowSteps.find { it.stepId == viewModel.currentStepData?.workflowStepId }
+                val workflowStep = viewModel.currentStepData
                 if (workflowStep?.confirmType != 0 ||//自动确认
                     (viewModel.ticketData?.createBy == MainDomainData.userInfo?.userName || workflowStep.currentUserCanConfirm())
                 ) {

+ 9 - 7
app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/MyTodoListFragment.kt

@@ -15,7 +15,6 @@ import com.grkj.data.data.MainDomainData
 import com.grkj.data.data.Type
 import com.grkj.data.enums.OperationTypeEnum
 import com.grkj.data.enums.RoleEnum
-import com.grkj.data.model.dos.WorkflowStep
 import com.grkj.data.model.vo.IsJobTicketStepDataVo
 import com.grkj.data.model.vo.TodoItemVo
 import com.grkj.iscs.R
@@ -163,7 +162,7 @@ class MyTodoListFragment : BaseFragment<FragmentMyTodoListBinding>() {
             item.todoType == OperationTypeEnum.LOCK_TAKE_KEY || item.todoType == OperationTypeEnum.UNLOCK_TAKE_KEY || item.todoType == OperationTypeEnum.LOCK_RETURN_KEY || item.todoType == OperationTypeEnum.UNLOCK_RETURN_KEY
         itemBinding.btnHandle.isVisible = if (item.todoType == OperationTypeEnum.UNLOCK_TAKE_KEY) {
             val currentStep =
-                jobExecuteViewModel.workflowSteps.find { it.stepId == jobExecuteViewModel.currentStepData?.workflowStepId }
+                jobExecuteViewModel.currentStepData
             val canUnLock = currentStep?.enableUnlock == true &&
                     jobExecuteViewModel.ticketPoints.any { it.pointStatus == "1" } &&
                     (jobExecuteViewModel.workflowModes.find { it.modeId == jobExecuteViewModel.ticketData?.modeId }?.isColockSupport == false ||
@@ -202,7 +201,7 @@ class MyTodoListFragment : BaseFragment<FragmentMyTodoListBinding>() {
                                     ?.let { stepVo ->
                                         stepClickConfirm(
                                             stepVo,
-                                            jobExecuteViewModel.workflowSteps.find { it.stepId == stepVo.workflowStepId }
+                                            jobExecuteViewModel.currentStepData
                                         )
                                     }
                             }
@@ -263,7 +262,10 @@ class MyTodoListFragment : BaseFragment<FragmentMyTodoListBinding>() {
     /**
      * 点击确认
      */
-    private fun stepClickConfirm(item: IsJobTicketStepDataVo, workflowStep: WorkflowStep?) {
+    private fun stepClickConfirm(
+        item: IsJobTicketStepDataVo,
+        workflowStep: IsJobTicketStepDataVo?
+    ) {
         if (!checkSelectMember(workflowStep)) {
             if (jobExecuteViewModel.stepConditionsComplete(workflowStep)) {
                 item.stepStatus = "1"
@@ -285,9 +287,9 @@ class MyTodoListFragment : BaseFragment<FragmentMyTodoListBinding>() {
      * 检查是否是选择人员
      */
     private fun checkSelectMember(
-        workflowStep: WorkflowStep?
+        workflowStep: IsJobTicketStepDataVo?
     ): Boolean {
-        val currentWorkflowStep = jobExecuteViewModel.getCurrentWorkflowStep()
+        val currentWorkflowStep = jobExecuteViewModel.currentStepData
         if (workflowStep?.enableSetLocker == true || workflowStep?.enableSetColocker == true && (currentWorkflowStep?.enableAddColocker == true || currentWorkflowStep?.enableReduceColocker == true)) {
             GlobalDataTempStore.getInstance().saveData(
                 DataTransferConstants.KEY_CAN_SELECT_COLOCKER,
@@ -365,7 +367,7 @@ class MyTodoListFragment : BaseFragment<FragmentMyTodoListBinding>() {
             if (jobExecuteViewModel.checkMemberFinish) {
                 jobExecuteViewModel.updateLockerAndColockerData().observe(this) {
                     val workflowStep =
-                        jobExecuteViewModel.workflowSteps.find { it.stepId == jobExecuteViewModel.currentStepData?.workflowStepId }
+                        jobExecuteViewModel.currentStepData
                     if (workflowStep?.confirmType != 0 ||//自动确认
                         (jobExecuteViewModel.ticketData?.createBy == MainDomainData.userInfo?.userName || workflowStep.currentUserCanConfirm())
                     ) {

+ 125 - 0
app/src/main/java/com/grkj/iscs/features/main/viewmodel/common/EditJobWorkflowSettingViewModel.kt

@@ -0,0 +1,125 @@
+package com.grkj.iscs.features.main.viewmodel.common
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.liveData
+import com.grkj.data.enums.WorkflowStepConfirmTypeEnum
+import com.grkj.data.model.dos.IsJobTicketStep
+import com.grkj.data.model.dos.SysRole
+import com.grkj.data.model.dos.WorkflowStep
+import com.grkj.data.model.vo.SysUserVo
+import com.grkj.data.repository.IJobTicketRepository
+import com.grkj.data.repository.IRoleRepository
+import com.grkj.data.repository.IUserRepository
+import com.grkj.data.repository.IWorkflowRepository
+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.utils.CommonUtils
+import com.sik.sikcore.SIKCore
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.Dispatchers
+import javax.inject.Inject
+
+/**
+ * 流程设置
+ */
+@HiltViewModel
+class EditJobWorkflowSettingViewModel @Inject constructor(
+    val workflowRepository: IWorkflowRepository,
+    val jobTicketRepository: IJobTicketRepository,
+    override val userRepository: IUserRepository,
+    val roleRepository: IRoleRepository
+) : BaseViewModel(userRepository) {
+    var modeId: Long = 0
+    var ticketId: Long = 0
+    var workflowSteps: List<IsJobTicketStep> = mutableListOf()
+    var currentStep: IsJobTicketStep? = null
+    var currentConfirmType: WorkflowStepConfirmTypeEnum = WorkflowStepConfirmTypeEnum.AUTO_CONFIRM
+    var currentConfirmRole: String? = null
+    var currentConfirmMember: Long? = null
+    var allUser: List<SysUserVo> = listOf()
+    var allRole: List<SysRole> = listOf()
+    val stepFunction: MutableList<String> = mutableListOf()
+
+
+    /**
+     * 获取流程模式步骤
+     */
+    fun getWorkflowSteps(modeId: Long = this.modeId): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            workflowSteps = jobTicketRepository.getJobTicketStepDataByTicketId(ticketId)
+            emit(true)
+        }
+    }
+
+    /**
+     * 获取设置需要的数据比如角色,用户什么的
+     */
+    fun getSettingData(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            allUser = userRepository.getAllUsersWithRole()
+            allRole = roleRepository.getRoleData()
+            emit(true)
+        }
+    }
+
+    /**
+     * 检查并设置步骤功能
+     */
+    fun checkAndSetStepFunction(): List<String> {
+        stepFunction.clear()
+        if (currentStep?.enableCancelJob == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.cancel_job).toString())
+        }
+        if (currentStep?.enableSetLocker == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.set_locker).toString())
+        }
+        if (currentStep?.enableSetColocker == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.set_colocker).toString())
+        }
+        if (currentStep?.enableLock == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.lock).toString())
+        }
+        if (currentStep?.enableColock == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.colock).toString())
+        }
+        if (currentStep?.enableAddColocker == true) {
+            val str = SIKCore.getApplication().getString(
+                R.string.add_colocker,
+                if (currentStep?.gotoStepAfterAddingColocker == null) CommonUtils.getStr(R.string.no_goto_step) else SIKCore.getApplication()
+                    .getString(R.string.navigate_to_step, currentStep?.gotoStepAfterAddingColocker)
+            )
+            stepFunction.add(str)
+        }
+        if (currentStep?.enableReduceColocker == true) {
+            val str = SIKCore.getApplication().getString(
+                R.string.reduce_colocker,
+                if (currentStep?.gotoStepAfterAddingColocker == null) CommonUtils.getStr(R.string.no_goto_step) else SIKCore.getApplication()
+                    .getString(R.string.navigate_to_step, currentStep?.gotoStepAfterAddingColocker)
+            )
+            stepFunction.add(str)
+        }
+        if (currentStep?.enableReleaseColock == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.release_colocker).toString())
+        }
+        if (currentStep?.enableUnlock == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.unlock).toString())
+        }
+        if (currentStep?.enableEndJob == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.end_job).toString())
+        }
+        return stepFunction
+    }
+
+    /**
+     * 保存滁州数据
+     */
+    fun saveStepsData(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            workflowSteps.forEach {
+                jobTicketRepository.updateTicketStepData(it)
+            }
+            emit(true)
+        }
+    }
+}

+ 121 - 0
app/src/main/java/com/grkj/iscs/features/main/viewmodel/common/EditSopWorkflowSettingViewModel.kt

@@ -0,0 +1,121 @@
+package com.grkj.iscs.features.main.viewmodel.common
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.liveData
+import com.grkj.data.enums.WorkflowStepConfirmTypeEnum
+import com.grkj.data.model.dos.IsSopWorkflowStep
+import com.grkj.data.model.dos.SysRole
+import com.grkj.data.model.vo.SysUserVo
+import com.grkj.data.repository.IRoleRepository
+import com.grkj.data.repository.ISopRepository
+import com.grkj.data.repository.IUserRepository
+import com.grkj.data.repository.IWorkflowRepository
+import com.grkj.iscs.R
+import com.grkj.ui_base.base.BaseViewModel
+import com.grkj.ui_base.utils.CommonUtils
+import com.sik.sikcore.SIKCore
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.Dispatchers
+import javax.inject.Inject
+
+/**
+ * 流程设置
+ */
+@HiltViewModel
+class EditSopWorkflowSettingViewModel @Inject constructor(
+    val workflowRepository: IWorkflowRepository,
+    val sopRepository: ISopRepository,
+    override val userRepository: IUserRepository,
+    val roleRepository: IRoleRepository
+) : BaseViewModel(userRepository) {
+    var modeId: Long = 0
+    var sopId: Long = 0
+    var workflowSteps: List<IsSopWorkflowStep> = mutableListOf()
+    var currentStep: IsSopWorkflowStep? = null
+    var currentConfirmType: WorkflowStepConfirmTypeEnum = WorkflowStepConfirmTypeEnum.AUTO_CONFIRM
+    var currentConfirmRole: String? = null
+    var currentConfirmMember: Long? = null
+    var allUser: List<SysUserVo> = listOf()
+    var allRole: List<SysRole> = listOf()
+    val stepFunction: MutableList<String> = mutableListOf()
+
+
+    /**
+     * 获取流程模式步骤
+     */
+    fun getWorkflowSteps(modeId: Long = this.modeId): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            workflowSteps = sopRepository.getSopWorkflowSteps(sopId)
+            emit(true)
+        }
+    }
+
+    /**
+     * 获取设置需要的数据比如角色,用户什么的
+     */
+    fun getSettingData(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            allUser = userRepository.getAllUsersWithRole()
+            allRole = roleRepository.getRoleData()
+            emit(true)
+        }
+    }
+
+    /**
+     * 检查并设置步骤功能
+     */
+    fun checkAndSetStepFunction(): List<String> {
+        stepFunction.clear()
+        if (currentStep?.enableCancelJob == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.cancel_job).toString())
+        }
+        if (currentStep?.enableSetLocker == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.set_locker).toString())
+        }
+        if (currentStep?.enableSetColocker == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.set_colocker).toString())
+        }
+        if (currentStep?.enableLock == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.lock).toString())
+        }
+        if (currentStep?.enableColock == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.colock).toString())
+        }
+        if (currentStep?.enableAddColocker == true) {
+            val str = SIKCore.getApplication().getString(
+                R.string.add_colocker,
+                if (currentStep?.gotoStepAfterAddingColocker == null) CommonUtils.getStr(R.string.no_goto_step) else SIKCore.getApplication()
+                    .getString(R.string.navigate_to_step, currentStep?.gotoStepAfterAddingColocker)
+            )
+            stepFunction.add(str)
+        }
+        if (currentStep?.enableReduceColocker == true) {
+            val str = SIKCore.getApplication().getString(
+                R.string.reduce_colocker,
+                if (currentStep?.gotoStepAfterAddingColocker == null) CommonUtils.getStr(R.string.no_goto_step) else SIKCore.getApplication()
+                    .getString(R.string.navigate_to_step, currentStep?.gotoStepAfterAddingColocker)
+            )
+            stepFunction.add(str)
+        }
+        if (currentStep?.enableReleaseColock == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.release_colocker).toString())
+        }
+        if (currentStep?.enableUnlock == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.unlock).toString())
+        }
+        if (currentStep?.enableEndJob == true) {
+            stepFunction.add(CommonUtils.getStr(R.string.end_job).toString())
+        }
+        return stepFunction
+    }
+
+    /**
+     * 保存滁州数据
+     */
+    fun saveStepsData(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            sopRepository.updateStep(workflowSteps)
+            emit(true)
+        }
+    }
+}

+ 21 - 40
app/src/main/java/com/grkj/iscs/features/main/viewmodel/job_manage/JobExecuteViewModel.kt

@@ -64,17 +64,9 @@ class JobExecuteViewModel @Inject constructor(
     var checkMemberFinish: Boolean = false
     var currentStepData: IsJobTicketStepDataVo? = null
     var workflowModes: List<WorkflowMode> = mutableListOf()
-    var workflowSteps: List<WorkflowStep> = mutableListOf()
     var isUnlockFirst: Boolean = false
     var userBiometricDataVo: List<SysBiometricDataVo> = mutableListOf()
 
-    /**
-     * 获取当前流程步骤数据
-     */
-    fun getCurrentWorkflowStep(): WorkflowStep? {
-        return workflowSteps.find { it.stepId == currentStepData?.workflowStepId }
-    }
-
     /**
      * 获取作业数据
      */
@@ -195,7 +187,6 @@ class JobExecuteViewModel @Inject constructor(
                 }
             }
             val ticketDetail = RepositoryManager.jobTicketRepo.getTicketDetail(ticketId)
-            val workflowStep = workflowSteps.find { it.stepId == currentStepData?.workflowStepId }
             val role =
                 ticketDetail?.ticketUserVOList?.filter { it.userRole == RoleEnum.JTLOCKER.roleKey }
                     ?.find {
@@ -209,7 +200,7 @@ class JobExecuteViewModel @Inject constructor(
                 return@liveData
             }
             var verifySuccess = false
-            if (workflowStep?.needCheckFace() == true) {
+            if (currentStepData?.needCheckFace() == true) {
                 _uiEvents.send(UiEvent.FaceCheck)
                 val checkResult = _paramResponse.receive() as Boolean
                 verifySuccess = checkResult
@@ -316,7 +307,6 @@ class JobExecuteViewModel @Inject constructor(
                 }
             }
             val ticketDetail = RepositoryManager.jobTicketRepo.getTicketDetail(ticketId)
-            val workflowStep = workflowSteps.find { it.stepId == currentStepData?.workflowStepId }
             val role =
                 ticketDetail?.ticketUserVOList?.filter { it.userRole == RoleEnum.JTLOCKER.roleKey }
                     ?.find {
@@ -330,7 +320,7 @@ class JobExecuteViewModel @Inject constructor(
                 return@liveData
             }
             var verifySuccess = false
-            if (workflowStep?.needCheckFace() == true) {
+            if (currentStepData?.needCheckFace() == true) {
                 _uiEvents.send(UiEvent.FaceCheck)
                 val checkResult = _paramResponse.receive() as Boolean
                 verifySuccess = checkResult
@@ -432,11 +422,9 @@ class JobExecuteViewModel @Inject constructor(
      */
     fun getWorkflowSteps(modeId: Long): LiveData<Boolean> {
         return liveData(Dispatchers.IO) {
-            workflowSteps = workflowRepository.getStepsByMode(modeId)
             for (stepDataVo in ticketStep) {
-                val workflowStep = workflowSteps.find { it.stepId == stepDataVo.workflowStepId }
                 //如果是自动确认并且没有操作的功能,则更新步骤
-                if (workflowStep?.confirmType != 0 && workflowStep?.hasAnyOperationFunction() == false) {
+                if (stepDataVo.confirmType != 0 && stepDataVo.hasAnyOperationFunction() == false) {
                     stepDataVo.stepStatus = "1"
                     BeanUtils.copyProperties(
                         stepDataVo, IsJobTicketStep::class.java
@@ -444,13 +432,10 @@ class JobExecuteViewModel @Inject constructor(
                         jobTicketRepository.updateTicketStepData(jobTicketStep)
                         currentStepData =
                             ticketStep.find { it.stepIndex == jobTicketStep.stepIndex + 1 }
-                        val currentWorkflowStep = workflowSteps.find {
-                            it.stepId == ticketStep.firstOrNull { it.stepStatus == "0" }?.workflowStepId
-                        }
-                        ticketData?.ticketStatus = currentWorkflowStep?.getTicketStatus() ?: ""
+                        ticketData?.ticketStatus = currentStepData?.getTicketStatus() ?: ""
                         jobTicketRepository.updateTicketDataStatus(
                             ticketId,
-                            currentWorkflowStep?.getTicketStatus()?.toInt()
+                            currentStepData?.getTicketStatus()?.toInt()
                                 ?: JobTicketStatusEnum.PROGRESSING.status.toInt()
                         )
                     }
@@ -483,12 +468,9 @@ class JobExecuteViewModel @Inject constructor(
             ticketStepData?.let {
                 jobTicketRepository.updateTicketStepData(it)
                 currentStepData = ticketStep.find { it.stepIndex == ticketStepData.stepIndex + 1 }
-                val currentWorkflowStep = workflowSteps.find {
-                    it.stepId == currentStepData?.workflowStepId
-                }
                 jobTicketRepository.updateTicketDataStatus(
                     ticketId,
-                    currentWorkflowStep?.getTicketStatus()?.toInt()
+                    currentStepData?.getTicketStatus()?.toInt()
                         ?: JobTicketStatusEnum.PROGRESSING.status.toInt()
                 )
                 emit(true)
@@ -506,12 +488,9 @@ class JobExecuteViewModel @Inject constructor(
             )
             ticketStepData?.let {
                 jobTicketRepository.updateTicketStepData(it)
-                val currentWorkflowStep = workflowSteps.find {
-                    it.stepId == currentStepData?.workflowStepId
-                }
                 jobTicketRepository.updateTicketDataStatus(
                     ticketId,
-                    currentWorkflowStep?.getTicketStatus()?.toInt()
+                    currentStepData?.getTicketStatus()?.toInt()
                         ?: JobTicketStatusEnum.PROGRESSING.status.toInt()
                 )
                 emit(true)
@@ -522,7 +501,7 @@ class JobExecuteViewModel @Inject constructor(
     /**
      * 上锁步骤是否上锁完成
      */
-    private fun lockStepLocked(workflowStep: WorkflowStep?): Boolean {
+    private fun lockStepLocked(workflowStep: IsJobTicketStepDataVo?): Boolean {
         logger.info("上锁条件:${workflowStep?.enableLock},${ticketPoints.all { it.pointStatus == "1" }}")
         return workflowStep?.enableLock == true && ticketPoints.all { it.pointStatus == "1" }
     }
@@ -530,7 +509,7 @@ class JobExecuteViewModel @Inject constructor(
     /**
      * 共锁步骤是否共锁完成
      */
-    private fun coLockStepLocked(workflowStep: WorkflowStep?): Boolean {
+    private fun coLockStepLocked(workflowStep: IsJobTicketStepDataVo?): Boolean {
         logger.info(
             "共锁条件:${workflowStep?.enableColock},${
                 ticketUser.filter {
@@ -549,7 +528,7 @@ class JobExecuteViewModel @Inject constructor(
     /**
      * 解除共锁步骤是否解锁完成
      */
-    private fun releaseCoLockStepUnLocked(workflowStep: WorkflowStep?): Boolean {
+    private fun releaseCoLockStepUnLocked(workflowStep: IsJobTicketStepDataVo?): Boolean {
         logger.info(
             "解除共锁条件:${workflowStep?.enableReleaseColock},${
                 ticketUser.filter {
@@ -568,7 +547,7 @@ class JobExecuteViewModel @Inject constructor(
     /**
      * 解锁步骤是否解锁完成
      */
-    private fun unLockStepLocked(workflowStep: WorkflowStep?): Boolean {
+    private fun unLockStepLocked(workflowStep: IsJobTicketStepDataVo?): Boolean {
         logger.info("解锁条件:${workflowStep?.enableUnlock},${ticketPoints.all { it.pointStatus == "2" }}")
         return workflowStep?.enableUnlock == true && ticketPoints.all { it.pointStatus == "2" }
     }
@@ -576,7 +555,7 @@ class JobExecuteViewModel @Inject constructor(
     /**
      * 步骤条件是否完成
      */
-    fun stepConditionsComplete(workflowStep: WorkflowStep?): Boolean {
+    fun stepConditionsComplete(workflowStep: IsJobTicketStepDataVo?): Boolean {
         return when {
             //一个步骤4个状态
             workflowStep?.enableLock == true && workflowStep.enableColock && workflowStep.enableUnlock && workflowStep.enableReleaseColock -> lockStepLocked(
@@ -626,7 +605,7 @@ class JobExecuteViewModel @Inject constructor(
     /**
      * 获取步骤错误提示
      */
-    fun getStepErrorTip(workflowStep: WorkflowStep?): Pair<String, Int?> {
+    fun getStepErrorTip(workflowStep: IsJobTicketStepDataVo?): Pair<String, Int?> {
         return when {
             workflowStep?.enableSetLocker == true || workflowStep?.enableSetColocker == true -> {
                 CommonUtils.getStr(R.string.please_select_member).toString() to null
@@ -685,17 +664,19 @@ class JobExecuteViewModel @Inject constructor(
      * 是否需要显示提示
      */
     fun needShowTip(): Boolean {
-        val currentWorkflowStep =
-            workflowSteps.find { it.stepId == currentStepData?.workflowStepId }
-        return currentWorkflowStep?.enableSetLocker == true || currentWorkflowStep?.enableSetColocker == true || currentWorkflowStep?.enableLock == true || currentWorkflowStep?.enableColock == true || currentWorkflowStep?.enableReleaseColock == true || currentWorkflowStep?.enableUnlock == true
+        return currentStepData?.enableSetLocker == true ||
+                currentStepData?.enableSetColocker == true ||
+                currentStepData?.enableLock == true ||
+                currentStepData?.enableColock == true ||
+                currentStepData?.enableReleaseColock == true ||
+                currentStepData?.enableUnlock == true
     }
 
     /**
      * 获取当前步骤的提示
      */
     fun getCurrentStepTip(): String {
-        val currentWorkflowStep =
-            workflowSteps.find { it.stepId == currentStepData?.workflowStepId }
+        val currentWorkflowStep = currentStepData
         return when {
             currentWorkflowStep?.enableSetLocker == true || currentWorkflowStep?.enableSetColocker == true -> {
                 CommonUtils.getStr(R.string.please_select_member).toString()
@@ -747,7 +728,7 @@ class JobExecuteViewModel @Inject constructor(
      */
     fun canCheckStep(): LiveData<Boolean> {
         return liveData(Dispatchers.IO) {
-            val workflowStep = workflowSteps.find { it.stepId == currentStepData?.workflowStepId }
+            val workflowStep = currentStepData
             logger.info("检查是否可以确认步骤:${ticketData?.createBy != MainDomainData.userInfo?.userName},${workflowStep?.currentUserCanConfirm() == false}")
             if (ticketData?.createBy != MainDomainData.userInfo?.userName || workflowStep?.currentUserCanConfirm() == false) {
                 ThreadUtils.runOnMain {

+ 2 - 1
app/src/main/java/com/grkj/iscs/features/main/viewmodel/job_manage/JobViewModel.kt

@@ -55,7 +55,7 @@ class JobViewModel @Inject constructor(
     }
 
     /**
-     * 保存作
+     * 保存作SOP
      */
     fun saveSop(
         selectedPointsData: List<JobTicketGroupDataVo<JobPointVo>>,
@@ -70,6 +70,7 @@ class JobViewModel @Inject constructor(
             sopRepository.deleteSopPointsBySopId(listOf(sopId))
             sopRepository.deleteSopUsersBySopId(listOf(sopId))
             sopRepository.deleteSopGroupBySopId(listOf(sopId))
+            sopRepository.deleteSopWorkflowStepBySopId(listOf(sopId))
             val sopId = sopRepository.saveSop(sopId, sopName, workstationId, workflowModeId)
             selectedPointsData.forEach {
                 val isSopGroup = IsSopGroup()

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

@@ -87,26 +87,28 @@ class MyTodoViewModel @Inject constructor(
         // 1. 先按 ticketId 分组
         val grouped = all.groupBy { it.ticketId }
 
-        grouped.forEach { (_, steps) ->
+        for ((_, steps) in grouped) {
             val doneSteps = steps.filter { it.stepStatus == "1" }
             val pendingSteps = steps.filter { it.stepStatus == "0" }
 
-            // 当前步骤 = 最小 stepIndex 的 pending
+            // 当前步骤:isCurrentStep = true
             val todoStep = pendingSteps.filter { it.isCurrentStep }
             todoStep.let { tempTodo.addAll(it) }
 
-            // 剩下的就是 wait
-            pendingSteps.filter { it !in todoStep }.let {
-                tempWait.addAll(it)
-            }
+            // 剩余非当前步骤的 wait 步骤,最多 waitLimit 条
+            val waitSteps =
+                pendingSteps.filter { it !in todoStep }.sortedBy { it.stepIndex } // 可选:stepIndex小的优先
+                    .take(waitLimit)
+
+            tempWait.addAll(waitSteps)
 
             tempDone.addAll(doneSteps)
         }
 
         // 应用 limit 到 waitData
-        waitData = tempWait.take(waitLimit).toMutableList()
-        todoData = tempTodo
-        doneData = tempDone
+        todoData = tempTodo.sortedBy { it.ticketId }.toMutableList()
+        waitData = tempWait.sortedBy { it.ticketId }.toMutableList()
+        doneData = tempDone.sortedByDescending { it.stepUpdateTime }.toMutableList()
     }
 
 

+ 40 - 0
app/src/main/res/layout/fragment_my_todo_list.xml

@@ -72,10 +72,50 @@
                 app:tabMode="fixed"
                 app:tabTextAppearance="@style/TabTextStyle" />
 
+            <androidx.constraintlayout.widget.ConstraintLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal">
+
+                <com.grkj.ui_base.widget.RequiredTextView
+                    android:id="@+id/handle_time_tv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/handle_time"
+                    android:textColor="@color/black"
+                    android:textSize="@dimen/common_text_size"
+                    android:layout_marginTop="@dimen/common_spacing"
+                    app:layout_constraintTop_toTopOf="parent"
+                    app:layout_constraintLeft_toLeftOf="parent"
+                    app:markPosition="end"
+                    app:required="false" />
+
+                <TextView
+                    android:id="@+id/handle_time"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="@dimen/common_spacing"
+                    android:layout_marginRight="@dimen/dialog_content_normal_padding_horizontal"
+                    android:background="@drawable/bg_common_input"
+                    android:drawableRight="@mipmap/icon_drop_down"
+                    android:hint="@string/please_select_power_type"
+                    android:maxLines="1"
+                    android:paddingHorizontal="@dimen/common_spacing"
+                    android:paddingVertical="2dp"
+                    android:singleLine="true"
+                    android:textColor="@color/black"
+                    android:textSize="@dimen/common_text_size"
+                    app:layout_constraintBottom_toBottomOf="@+id/handle_time_tv"
+                    app:layout_constraintEnd_toEndOf="parent"
+                    app:layout_constraintStart_toEndOf="@+id/handle_time_tv"
+                    app:layout_constraintTop_toTopOf="@+id/handle_time_tv" />
+            </androidx.constraintlayout.widget.ConstraintLayout>
+
             <com.drake.statelayout.StateLayout
                 android:id="@+id/state"
                 android:layout_width="match_parent"
                 android:layout_height="0dp"
+                android:layout_marginTop="@dimen/common_spacing"
                 android:layout_weight="1">
 
                 <androidx.recyclerview.widget.RecyclerView

+ 18 - 0
app/src/main/res/navigation/nav_job_manage.xml

@@ -109,6 +109,9 @@
         <action
             android:id="@+id/action_editSopFragment_to_workflowSettingFragment"
             app:destination="@id/workflowSettingFragment" />
+        <action
+            android:id="@+id/action_editSopFragment_to_editSopWorkflowSettingFragment"
+            app:destination="@id/editSopWorkflowSettingFragment" />
     </fragment>
     <fragment
         android:id="@+id/jobManageFragment"
@@ -151,6 +154,9 @@
         <action
             android:id="@+id/action_editJobFragment_to_workflowSettingFragment"
             app:destination="@id/workflowSettingFragment" />
+        <action
+            android:id="@+id/action_editJobFragment_to_editJobWorkflowSettingFragment"
+            app:destination="@id/editJobWorkflowSettingFragment" />
     </fragment>
     <fragment
         android:id="@+id/editSopJobFragment"
@@ -167,6 +173,9 @@
         <action
             android:id="@+id/action_editSopJobFragment_to_workflowSettingFragment"
             app:destination="@id/workflowSettingFragment" />
+        <action
+            android:id="@+id/action_editSopJobFragment_to_editJobWorkflowSettingFragment"
+            app:destination="@id/editJobWorkflowSettingFragment" />
     </fragment>
     <fragment
         android:id="@+id/jobExecuteFragment"
@@ -195,6 +204,7 @@
         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"
@@ -213,4 +223,12 @@
             android:id="@+id/action_myTodoListFragment_to_selectMemberFragment"
             app:destination="@id/selectMemberFragment" />
     </fragment>
+    <fragment
+        android:id="@+id/editJobWorkflowSettingFragment"
+        android:name="com.grkj.iscs.features.main.fragment.common.EditJobWorkflowSettingFragment"
+        android:label="EditJobWorkflowSettingFragment" />
+    <fragment
+        android:id="@+id/editSopWorkflowSettingFragment"
+        android:name="com.grkj.iscs.features.main.fragment.common.EditSopWorkflowSettingFragment"
+        android:label="EditSopWorkflowSettingFragment" />
 </navigation>

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

@@ -503,5 +503,6 @@
     <string name="point_detail">Point Detail</string>
     <string name="close">Close</string>
     <string name="handle_failed">Handle failed</string>
+    <string name="handle_time">Handle Time:</string>
 
 </resources>

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

@@ -503,5 +503,6 @@
     <string name="point_detail">点位明细</string>
     <string name="close">关闭</string>
     <string name="handle_failed">处理失败</string>
+    <string name="handle_time">处理时间:</string>
 
 </resources>

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

@@ -506,5 +506,6 @@
     <string name="point_detail">点位明细</string>
     <string name="close">关闭</string>
     <string name="handle_failed">处理失败</string>
+    <string name="handle_time">处理时间:</string>
 
 </resources>

+ 26 - 0
data/src/main/java/com/grkj/data/dao/IsSopDao.kt

@@ -5,11 +5,13 @@ import androidx.room.Insert
 import androidx.room.OnConflictStrategy
 import androidx.room.Query
 import androidx.room.TypeConverters
+import androidx.room.Update
 import com.grkj.data.converters.Converters
 import com.grkj.data.model.dos.IsSop
 import com.grkj.data.model.dos.IsSopGroup
 import com.grkj.data.model.dos.IsSopPoints
 import com.grkj.data.model.dos.IsSopUser
+import com.grkj.data.model.dos.IsSopWorkflowStep
 import com.grkj.data.model.vo.JobPointVo
 import com.grkj.data.model.vo.JobUserVo
 import com.grkj.data.model.vo.PointManageVo
@@ -198,4 +200,28 @@ interface IsSopDao {
      */
     @Query("delete from is_sop_group where sop_id in (:sopIds)")
     fun deleteSopGroupBySopId(sopIds: List<Long>)
+
+    /**
+     * 根据sopId删除sop流程步骤
+     */
+    @Query("delete from is_sop_workflow_step where sop_id in (:sopIds)")
+    fun deleteSopWorkflowStepBySopId(sopIds: List<Long>)
+
+    /**
+     * 保存sop流程步骤
+     */
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    fun saveSopWorkflowStep(sopWorkflowStep: List<IsSopWorkflowStep>)
+
+    /**
+     * 获取sop流程分组
+     */
+    @Query("select * from is_sop_workflow_step where sop_id = :sopId")
+    fun getSopWorkflowSteps(sopId: Long): List<IsSopWorkflowStep>
+
+    /**
+     * 更新流程步骤
+     */
+    @Update
+    fun updateStep(sopWorkflowStep: List<IsSopWorkflowStep>)
 }

+ 3 - 3
data/src/main/java/com/grkj/data/database/ISCSDatabase.kt

@@ -29,7 +29,7 @@ import java.io.FileOutputStream
         IsKey::class, IsLock::class, IsLockCabinet::class, IsLockCabinetSlots::class, IsLocksetType::class, IsLockset::class,
         SysMenu::class, SysRoleMenu::class,
         WorkflowStep::class, WorkflowMode::class, WorkflowStepTemplate::class,
-        IsExceptionStandard::class, IsExceptionSourceStandard::class, IsSopGroup::class, IsJobTicketGroup::class
+        IsExceptionStandard::class, IsExceptionSourceStandard::class, IsSopGroup::class, IsJobTicketGroup::class, IsSopWorkflowStep::class
     ],
     version = ISCSMigrations.VERSION,
     exportSchema = true
@@ -94,9 +94,9 @@ abstract class ISCSDatabase : RoomDatabase() {
                 context,
                 ISCSDatabase::class.java,
                 EXTERNAL_DB_FILE.absolutePath
-            )
+            ).addMigrations(*ISCSMigrations.migrationData)
             if (Constants.DEBUG) {
-                builder.setQueryCallback( Dispatchers.IO,{ sql, args ->
+                builder.setQueryCallback(Dispatchers.IO, { sql, args ->
                     logger.debug("SQL: $sql, args: $args")
                 })
                 // 不要使用 fallbackToDestructiveMigration()

+ 99 - 3
data/src/main/java/com/grkj/data/database/ISCSMigrations.kt

@@ -1,7 +1,5 @@
 package com.grkj.data.database
 
-import android.util.Log
-import androidx.annotation.NonNull
 import androidx.room.migration.Migration
 import androidx.sqlite.db.SupportSQLiteDatabase
 
@@ -13,5 +11,103 @@ object ISCSMigrations {
     /**
      * 版本号
      */
-    const val VERSION = 1
+    const val VERSION = 2
+
+    /**
+     * 升级数据
+     */
+    val migrationData: Array<Migration> by lazy { arrayOf(migration1To2) }
+
+    /**
+     * 数据库升级
+     */
+    val migration1To2 = object : Migration(1, 2) {
+        override fun migrate(database: SupportSQLiteDatabase) {
+
+            // 1. 创建新表(不包含 workflow_step_id,加入新字段)
+            database.execSQL("""
+            CREATE TABLE IF NOT EXISTS is_job_ticket_step_new (
+                step_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+                ticket_id INTEGER NOT NULL,
+                step_index INTEGER NOT NULL,
+                step_status TEXT NOT NULL,
+                step_content TEXT,
+                android_step_content TEXT,
+                del_flag TEXT,
+                
+                -- 以下为新增字段(来自 workflow_step)
+                step_template_id INTEGER,
+                step_name TEXT,
+                step_title TEXT,
+                step_title_short TEXT,
+                step_description TEXT,
+                confirm_type INTEGER DEFAULT 0,
+                confirm_role_code TEXT,
+                confirm_user INTEGER,
+                enable_cancel_job INTEGER DEFAULT 0,
+                enable_set_locker INTEGER DEFAULT 0,
+                enable_set_colocker INTEGER DEFAULT 0,
+                enable_add_colocker INTEGER DEFAULT 0,
+                goto_step_after_adding_colocker INTEGER,
+                enable_reduce_colocker INTEGER DEFAULT 0,
+                enable_lock INTEGER DEFAULT 0,
+                enable_colock INTEGER DEFAULT 0,
+                enable_release_colock INTEGER DEFAULT 0,
+                enable_unlock INTEGER DEFAULT 0,
+                enable_end_job INTEGER DEFAULT 0
+            );
+        """.trimIndent())
+
+            // 2. 拷贝旧数据(workflow_step_id 不再迁移)
+            database.execSQL("""
+            INSERT INTO is_job_ticket_step_new (
+                step_id, ticket_id, step_index, step_status,
+                step_content, android_step_content, del_flag
+            )
+            SELECT
+                step_id, ticket_id, step_index, step_status,
+                step_content, android_step_content, del_flag
+            FROM is_job_ticket_step;
+        """.trimIndent())
+
+            // 3. 删除旧表
+            database.execSQL("DROP TABLE is_job_ticket_step;")
+
+            // 4. 重命名新表为旧表名
+            database.execSQL("ALTER TABLE is_job_ticket_step_new RENAME TO is_job_ticket_step;")
+            // 5. 增加 is_sop_workflow_step 表
+            database.execSQL("""
+            CREATE TABLE IF NOT EXISTS is_sop_workflow_step (
+                step_id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
+                mode_id INTEGER NOT NULL,
+                step_template_id INTEGER,
+                step_index INTEGER NOT NULL,
+                step_name TEXT,
+                step_title TEXT,
+                step_title_short TEXT,
+                step_description TEXT,
+                confirm_type INTEGER NOT NULL DEFAULT 0,
+                confirm_role_code TEXT,
+                confirm_user INTEGER,
+                enable_cancel_job INTEGER NOT NULL DEFAULT 0,
+                enable_set_locker INTEGER NOT NULL DEFAULT 0,
+                enable_set_colocker INTEGER NOT NULL DEFAULT 0,
+                enable_add_colocker INTEGER NOT NULL DEFAULT 0,
+                goto_step_after_adding_colocker INTEGER,
+                enable_reduce_colocker INTEGER NOT NULL DEFAULT 0,
+                enable_lock INTEGER NOT NULL DEFAULT 0,
+                enable_colock INTEGER NOT NULL DEFAULT 0,
+                enable_release_colock INTEGER NOT NULL DEFAULT 0,
+                enable_unlock INTEGER NOT NULL DEFAULT 0,
+                enable_end_job INTEGER NOT NULL DEFAULT 0,
+                creator TEXT,
+                create_time TEXT NOT NULL,
+                updater TEXT NOT NULL,
+                update_time TEXT NOT NULL,
+                deleted INTEGER NOT NULL DEFAULT 0,
+                tenant_id INTEGER NOT NULL DEFAULT 0
+            );
+        """.trimIndent())
+        }
+    }
 }

+ 115 - 2
data/src/main/java/com/grkj/data/model/dos/IsJobTicketStep.kt

@@ -2,7 +2,10 @@ package com.grkj.data.model.dos
 
 import androidx.room.ColumnInfo
 import androidx.room.Entity
+import androidx.room.Ignore
 import androidx.room.PrimaryKey
+import com.grkj.data.data.MainDomainData
+import com.grkj.data.enums.JobTicketStatusEnum
 
 /**
  * is_job_ticket_step
@@ -31,7 +34,117 @@ open class IsJobTicketStep : BaseBean() {
     @ColumnInfo("del_flag")
     var delFlag: String? = "0"
 
-    @ColumnInfo("workflow_step_id")
-    var workflowStepId: Long = 0
+    @ColumnInfo("step_template_id")
+    var stepTemplateId: Long? = null
 
+    @ColumnInfo("step_name")
+    var stepName: String? = null
+
+    @ColumnInfo("step_title")
+    var stepTitle: String? = null
+
+    @ColumnInfo("step_title_short")
+    var stepTitleShort: String? = null
+
+    @ColumnInfo("step_description")
+    var stepDescription: String? = null
+
+    @ColumnInfo("confirm_type")
+    var confirmType: Int = 0
+
+    @ColumnInfo("confirm_role_code")
+    var confirmRoleCode: String? = null
+
+    @ColumnInfo("confirm_user")
+    var confirmUser: Long? = null
+
+    @ColumnInfo("enable_cancel_job")
+    var enableCancelJob: Boolean = false
+
+    @ColumnInfo("enable_set_locker")
+    var enableSetLocker: Boolean = false
+
+    @ColumnInfo("enable_set_colocker")
+    var enableSetColocker: Boolean = false
+
+    @ColumnInfo("enable_add_colocker")
+    var enableAddColocker: Boolean = false
+
+    @ColumnInfo("goto_step_after_adding_colocker")
+    var gotoStepAfterAddingColocker: Int? = null
+
+    @ColumnInfo("enable_reduce_colocker")
+    var enableReduceColocker: Boolean = false
+
+    @ColumnInfo("enable_lock")
+    var enableLock: Boolean = false
+
+    @ColumnInfo("enable_colock")
+    var enableColock: Boolean = false
+
+    @ColumnInfo("enable_release_colock")
+    var enableReleaseColock: Boolean = false
+
+    @ColumnInfo("enable_unlock")
+    var enableUnlock: Boolean = false
+
+    @ColumnInfo("enable_end_job")
+    var enableEndJob: Boolean = false
+
+    /**
+     * 根据参数判断作业票状态
+     */
+    @Ignore
+    fun getTicketStatus(): String {
+        return when {
+            enableSetLocker || enableSetColocker -> JobTicketStatusEnum.SELECT_MEMBER.status
+            enableLock -> JobTicketStatusEnum.LOCKING.status
+            enableColock || enableReleaseColock -> JobTicketStatusEnum.COLOCKING.status
+            enableUnlock -> JobTicketStatusEnum.UNLOCKING.status
+            else -> JobTicketStatusEnum.PROGRESSING.status
+        }
+    }
+
+    /**
+     * 是否有任何需要操作的功能
+     */
+    @Ignore
+    fun hasAnyOperationFunction(): Boolean {
+        return enableSetLocker || enableSetColocker || enableLock || enableColock || enableAddColocker || enableReduceColocker || enableReleaseColock || enableUnlock || enableEndJob
+    }
+
+    /**
+     * 是否有任何需要硬件操作的功能
+     */
+    @Ignore
+    fun hasAnyHardwareOperationFunction(): Boolean {
+        return enableLock || enableColock || enableReleaseColock || enableUnlock
+    }
+
+    /**
+     * 当前用户是否可以确认
+     */
+    @Ignore
+    fun currentUserCanConfirm(): Boolean {
+        if (confirmUser == null || MainDomainData.userInfo?.userId == confirmUser) {
+            return true
+        }
+//        if (confirmRoleCode != null && confirmUser == null && MainDomainData.roleKeys?.contains(
+//                confirmRoleCode!!
+//            ) == true
+//        ) {
+//            return true
+//        }
+        return false
+    }
+
+    /**
+     * 是否需要验证人脸
+     */
+    @Ignore
+    fun needCheckFace(): Boolean {
+        return confirmRoleCode != null && confirmUser != null && MainDomainData.roleKeys?.contains(
+            confirmRoleCode!!
+        ) == true && MainDomainData.userInfo?.userId == confirmUser
+    }
 }

+ 131 - 0
data/src/main/java/com/grkj/data/model/dos/IsSopWorkflowStep.kt

@@ -0,0 +1,131 @@
+package com.grkj.data.model.dos
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.Ignore
+import androidx.room.PrimaryKey
+import com.grkj.data.data.MainDomainData
+import com.grkj.data.enums.JobTicketStatusEnum
+import com.sik.sikcore.date.TimeUtils
+
+/**
+ * sop工作流步骤表实体
+ */
+@Entity(tableName = "is_sop_workflow_step")
+class IsSopWorkflowStep {
+    /** 自增主键,步骤 ID */
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo(name = "step_id")
+    var stepId: Long = 0L
+
+    @ColumnInfo(name = "sop_id")
+    var sopId: Long = 0L
+
+    /** 所属模式 ID */
+    @ColumnInfo(name = "mode_id")
+    var modeId: Long = 0L
+
+    /** 步骤模板 ID */
+    @ColumnInfo(name = "step_template_id")
+    var stepTemplateId: Long? = null
+
+    /** 步骤序号 */
+    @ColumnInfo(name = "step_index")
+    var stepIndex: Int = 0
+
+    /** 步骤名称 */
+    @ColumnInfo(name = "step_name")
+    var stepName: String? = null
+
+    /** 步骤标题 */
+    @ColumnInfo(name = "step_title")
+    var stepTitle: String? = null
+
+    /** 步骤短标题 */
+    @ColumnInfo(name = "step_title_short")
+    var stepTitleShort: String? = null
+
+    /** 步骤描述信息 */
+    @ColumnInfo(name = "step_description")
+    var stepDescription: String? = null
+
+    /** 确认类型,0=手动 */
+    @ColumnInfo(name = "confirm_type")
+    var confirmType: Int = 0
+
+    /** 确认角色编码 */
+    @ColumnInfo(name = "confirm_role_code")
+    var confirmRoleCode: String? = null
+
+    /** 确认人员 ID */
+    @ColumnInfo(name = "confirm_user")
+    var confirmUser: Long? = null
+
+    /** 是否可取消作业 */
+    @ColumnInfo(name = "enable_cancel_job")
+    var enableCancelJob: Boolean = false
+
+    /** 是否可设置锁定人 */
+    @ColumnInfo(name = "enable_set_locker")
+    var enableSetLocker: Boolean = false
+
+    /** 是否可设置共锁人 */
+    @ColumnInfo(name = "enable_set_colocker")
+    var enableSetColocker: Boolean = false
+
+    /** 是否可添加共锁人 */
+    @ColumnInfo(name = "enable_add_colocker")
+    var enableAddColocker: Boolean = false
+
+    /** 添加共锁人后跳转步骤序号 */
+    @ColumnInfo(name = "goto_step_after_adding_colocker")
+    var gotoStepAfterAddingColocker: Int? = null
+
+    /** 是否可减少共锁人 */
+    @ColumnInfo(name = "enable_reduce_colocker")
+    var enableReduceColocker: Boolean = false
+
+    /** 是否可上锁 */
+    @ColumnInfo(name = "enable_lock")
+    var enableLock: Boolean = false
+
+    /** 是否可共锁 */
+    @ColumnInfo(name = "enable_colock")
+    var enableColock: Boolean = false
+
+    /** 是否可解除共锁 */
+    @ColumnInfo(name = "enable_release_colock")
+    var enableReleaseColock: Boolean = false
+
+    /** 是否可解锁 */
+    @ColumnInfo(name = "enable_unlock")
+    var enableUnlock: Boolean = false
+
+    /** 是否可结束作业 */
+    @ColumnInfo(name = "enable_end_job")
+    var enableEndJob: Boolean = false
+
+    /** 创建者 */
+    @ColumnInfo(name = "creator")
+    var creator: String? = MainDomainData.userInfo?.userName
+
+    /** 创建时间,格式 yyyy-MM-dd HH:mm:ss */
+    @ColumnInfo(name = "create_time")
+    var createTime: String = TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT)
+
+    /** 更新者 */
+    @ColumnInfo(name = "updater")
+    var updater: String = MainDomainData.userInfo?.userName ?: ""
+
+    /** 更新时间,格式 yyyy-MM-dd HH:mm:ss */
+    @ColumnInfo(name = "update_time")
+    var updateTime: String = TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT)
+
+    /** 是否删除 */
+    @ColumnInfo(name = "deleted")
+    var deleted: Boolean = false
+
+    /** 租户编号 */
+    @ColumnInfo(name = "tenant_id")
+    var tenantId: Long = 0
+}

+ 17 - 15
data/src/main/java/com/grkj/data/model/dos/WorkflowMode.kt

@@ -4,63 +4,65 @@ package com.grkj.data.model.dos
 import androidx.room.ColumnInfo
 import androidx.room.Entity
 import androidx.room.PrimaryKey
+import com.grkj.data.data.MainDomainData
+import com.sik.sikcore.date.TimeUtils
 
 
 /**
  * 工作流模式表实体
  */
 @Entity(tableName = "is_workflow_mode")
-data class WorkflowMode(
+class WorkflowMode {
     /** 自增主键,模式 ID */
     @PrimaryKey(autoGenerate = true)
     @ColumnInfo(name = "mode_id")
-    var modeId: Long = 0L,
+    var modeId: Long = 0L
 
     /** 模式编码 */
     @ColumnInfo(name = "mode_code")
-    var modeCode: String? = null,
+    var modeCode: String? = null
 
     /** 是否预置 */
     @ColumnInfo(name = "is_preset")
-    var isPreset: Boolean = false,
+    var isPreset: Boolean = false
 
     /** 模式名称 */
     @ColumnInfo(name = "mode_name")
-    var modeName: String? = null,
+    var modeName: String? = null
 
     /** 模式标题 */
     @ColumnInfo(name = "mode_title")
-    var modeTitle: String? = null,
+    var modeTitle: String? = null
 
     /** 模式描述信息 */
     @ColumnInfo(name = "mode_description")
-    var modeDescription: String? = null,
+    var modeDescription: String? = null
 
     /** 是否支持共锁 */
     @ColumnInfo(name = "is_colock_support")
-    var isColockSupport: Boolean = false,
+    var isColockSupport: Boolean = false
 
     /** 创建者 */
     @ColumnInfo(name = "creator")
-    var creator: String? = null,
+    var creator: String? = MainDomainData.userInfo?.userName
 
     /** 创建时间,格式 yyyy-MM-dd HH:mm:ss */
     @ColumnInfo(name = "create_time")
-    var createTime: String,
+    var createTime: String = TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT)
 
     /** 更新者 */
     @ColumnInfo(name = "updater")
-    var updater: String,
+    var updater: String = MainDomainData.userInfo?.userName ?: ""
 
     /** 更新时间,格式 yyyy-MM-dd HH:mm:ss */
     @ColumnInfo(name = "update_time")
-    var updateTime: String,
+    var updateTime: String = TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT)
 
     /** 是否删除 */
     @ColumnInfo(name = "deleted")
-    var deleted: Boolean = false,
+    var deleted: Boolean = false
 
     /** 租户编号 */
     @ColumnInfo(name = "tenant_id")
-    var tenantId: Long
-)
+    var tenantId: Long = 0L
+}

+ 30 - 85
data/src/main/java/com/grkj/data/model/dos/WorkflowStep.kt

@@ -6,179 +6,124 @@ import androidx.room.Ignore
 import androidx.room.PrimaryKey
 import com.grkj.data.data.MainDomainData
 import com.grkj.data.enums.JobTicketStatusEnum
+import com.sik.sikcore.date.TimeUtils
 
 /**
  * 工作流步骤表实体
  */
 @Entity(tableName = "is_workflow_step")
-data class WorkflowStep(
+class WorkflowStep {
+
     /** 自增主键,步骤 ID */
     @PrimaryKey(autoGenerate = true)
     @ColumnInfo(name = "step_id")
-    var stepId: Long = 0L,
+    var stepId: Long = 0L
 
     /** 所属模式 ID */
     @ColumnInfo(name = "mode_id")
-    var modeId: Long,
+    var modeId: Long = 0L
 
     /** 步骤模板 ID */
     @ColumnInfo(name = "step_template_id")
-    var stepTemplateId: Long? = null,
+    var stepTemplateId: Long? = null
 
     /** 步骤序号 */
     @ColumnInfo(name = "step_index")
-    var stepIndex: Int = 0,
+    var stepIndex: Int = 0
 
     /** 步骤名称 */
     @ColumnInfo(name = "step_name")
-    var stepName: String? = null,
+    var stepName: String? = null
 
     /** 步骤标题 */
     @ColumnInfo(name = "step_title")
-    var stepTitle: String? = null,
+    var stepTitle: String? = null
 
     /** 步骤短标题 */
     @ColumnInfo(name = "step_title_short")
-    var stepTitleShort: String? = null,
+    var stepTitleShort: String? = null
 
     /** 步骤描述信息 */
     @ColumnInfo(name = "step_description")
-    var stepDescription: String? = null,
+    var stepDescription: String? = null
 
     /** 确认类型,0=手动 */
     @ColumnInfo(name = "confirm_type")
-    var confirmType: Int = 0,
+    var confirmType: Int = 0
 
     /** 确认角色编码 */
     @ColumnInfo(name = "confirm_role_code")
-    var confirmRoleCode: String? = null,
+    var confirmRoleCode: String? = null
 
     /** 确认人员 ID */
     @ColumnInfo(name = "confirm_user")
-    var confirmUser: Long? = null,
+    var confirmUser: Long? = null
 
     /** 是否可取消作业 */
     @ColumnInfo(name = "enable_cancel_job")
-    var enableCancelJob: Boolean = false,
+    var enableCancelJob: Boolean = false
 
     /** 是否可设置锁定人 */
     @ColumnInfo(name = "enable_set_locker")
-    var enableSetLocker: Boolean = false,
+    var enableSetLocker: Boolean = false
 
     /** 是否可设置共锁人 */
     @ColumnInfo(name = "enable_set_colocker")
-    var enableSetColocker: Boolean = false,
+    var enableSetColocker: Boolean = false
 
     /** 是否可添加共锁人 */
     @ColumnInfo(name = "enable_add_colocker")
-    var enableAddColocker: Boolean = false,
+    var enableAddColocker: Boolean = false
 
     /** 添加共锁人后跳转步骤序号 */
     @ColumnInfo(name = "goto_step_after_adding_colocker")
-    var gotoStepAfterAddingColocker: Int? = null,
+    var gotoStepAfterAddingColocker: Int? = null
 
     /** 是否可减少共锁人 */
     @ColumnInfo(name = "enable_reduce_colocker")
-    var enableReduceColocker: Boolean = false,
+    var enableReduceColocker: Boolean = false
 
     /** 是否可上锁 */
     @ColumnInfo(name = "enable_lock")
-    var enableLock: Boolean = false,
+    var enableLock: Boolean = false
 
     /** 是否可共锁 */
     @ColumnInfo(name = "enable_colock")
-    var enableColock: Boolean = false,
+    var enableColock: Boolean = false
 
     /** 是否可解除共锁 */
     @ColumnInfo(name = "enable_release_colock")
-    var enableReleaseColock: Boolean = false,
+    var enableReleaseColock: Boolean = false
 
     /** 是否可解锁 */
     @ColumnInfo(name = "enable_unlock")
-    var enableUnlock: Boolean = false,
+    var enableUnlock: Boolean = false
 
     /** 是否可结束作业 */
     @ColumnInfo(name = "enable_end_job")
-    var enableEndJob: Boolean = false,
+    var enableEndJob: Boolean = false
 
     /** 创建者 */
     @ColumnInfo(name = "creator")
-    var creator: String? = null,
+    var creator: String? = MainDomainData.userInfo?.userName
 
     /** 创建时间,格式 yyyy-MM-dd HH:mm:ss */
     @ColumnInfo(name = "create_time")
-    var createTime: String,
+    var createTime: String = TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT)
 
     /** 更新者 */
     @ColumnInfo(name = "updater")
-    var updater: String,
+    var updater: String = MainDomainData.userInfo?.userName ?: ""
 
     /** 更新时间,格式 yyyy-MM-dd HH:mm:ss */
     @ColumnInfo(name = "update_time")
-    var updateTime: String,
+    var updateTime: String = TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT)
 
     /** 是否删除 */
     @ColumnInfo(name = "deleted")
-    var deleted: Boolean = false,
+    var deleted: Boolean = false
 
     /** 租户编号 */
     @ColumnInfo(name = "tenant_id")
     var tenantId: Long = 0
-) {
-    /**
-     * 根据参数判断作业票状态
-     */
-    @Ignore
-    fun getTicketStatus(): String {
-        return when {
-            enableSetLocker || enableSetColocker -> JobTicketStatusEnum.SELECT_MEMBER.status
-            enableLock -> JobTicketStatusEnum.LOCKING.status
-            enableColock || enableReleaseColock -> JobTicketStatusEnum.COLOCKING.status
-            enableUnlock -> JobTicketStatusEnum.UNLOCKING.status
-            else -> JobTicketStatusEnum.PROGRESSING.status
-        }
-    }
-
-    /**
-     * 是否有任何需要操作的功能
-     */
-    @Ignore
-    fun hasAnyOperationFunction(): Boolean {
-        return enableSetLocker || enableSetColocker || enableLock || enableColock || enableAddColocker || enableReduceColocker || enableReleaseColock || enableUnlock || enableEndJob
-    }
-
-    /**
-     * 是否有任何需要硬件操作的功能
-     */
-    @Ignore
-    fun hasAnyHardwareOperationFunction(): Boolean {
-        return enableLock || enableColock || enableReleaseColock || enableUnlock
-    }
-
-    /**
-     * 当前用户是否可以确认
-     */
-    @Ignore
-    fun currentUserCanConfirm(): Boolean {
-        if (confirmUser == null || MainDomainData.userInfo?.userId == confirmUser) {
-            return true
-        }
-//        if (confirmRoleCode != null && confirmUser == null && MainDomainData.roleKeys?.contains(
-//                confirmRoleCode!!
-//            ) == true
-//        ) {
-//            return true
-//        }
-        return false
-    }
-
-    /**
-     * 是否需要验证人脸
-     */
-    @Ignore
-    fun needCheckFace(): Boolean {
-        return confirmRoleCode != null && confirmUser != null && MainDomainData.roleKeys?.contains(
-            confirmRoleCode!!
-        ) == true && MainDomainData.userInfo?.userId == confirmUser
-    }
 }

+ 4 - 5
data/src/main/java/com/grkj/data/model/local/TodoStepJoin.kt

@@ -35,6 +35,7 @@ data class TodoStepJoin(
     // ----- User 表(锁/共锁人员) -----
     val userRole: String?,   // JTLOCKER/JTCOLOCKER
     val lockerUserId: Long?, //上锁人id
+    val colockerUserId: List<Long> = mutableListOf(), //共锁人id
     val keyStatus: String?,   // 0/1/2 未取 已取 已还
 
     var groupId: Long? = null,
@@ -52,8 +53,8 @@ fun TodoStepJoin.isMyTodo(currentUserId: Long, currentUserName: String): Boolean
     if (enableUnlock && userRole == RoleEnum.JTLOCKER.roleKey && lockerUserId == currentUserId) return true
 
     // ---- 判定共锁/解除共锁(由创建者) ----
-//    if (enableColock && isCreator) return true
-//    if (enableReleaseColock && isCreator) return true
+    if (enableColock && currentUserId in colockerUserId) return true
+    if (enableReleaseColock && currentUserId in colockerUserId) return true
 
     // ---- 判定结束作业(由创建者) ----
     if (enableEndJob && isCreator) return true
@@ -67,7 +68,5 @@ fun TodoStepJoin.isMyTodo(currentUserId: Long, currentUserName: String): Boolean
 
 // WorkflowStep 扩展:判定是否包含任何硬件相关动作
 fun TodoStepJoin.hasAnyHardwareOperationFunction(): Boolean =
-    enableLock ||
-//            enableColock || enableReleaseColock ||
-            enableUnlock
+    enableLock || enableColock || enableReleaseColock || enableUnlock
 

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

@@ -1,6 +1,7 @@
 package com.grkj.data.repository
 
 import com.grkj.data.model.dos.IsSopGroup
+import com.grkj.data.model.dos.IsSopWorkflowStep
 import com.grkj.data.model.vo.JobPointVo
 import com.grkj.data.model.vo.JobTicketGroupDataVo
 import com.grkj.data.model.vo.JobUserVo
@@ -81,4 +82,19 @@ interface ISopRepository {
      * 根据sopId列表删除sop分组
      */
     fun deleteSopGroupBySopId(sopIds: List<Long>)
+
+    /**
+     * 根据sopId列表删除sop流程步骤
+     */
+    fun deleteSopWorkflowStepBySopId(sopIds: List<Long>)
+
+    /**
+     * 获取sop流程分组
+     */
+    fun getSopWorkflowSteps(sopId: Long): List<IsSopWorkflowStep>
+
+    /**
+     * 更新流程步骤
+     */
+    fun updateStep(isSopWorkflowStep: List<IsSopWorkflowStep>)
 }

+ 13 - 0
data/src/main/java/com/grkj/data/repository/impl/network/NetworkSopRepository.kt

@@ -1,6 +1,7 @@
 package com.grkj.data.repository.impl.network
 
 import com.grkj.data.model.dos.IsSopGroup
+import com.grkj.data.model.dos.IsSopWorkflowStep
 import com.grkj.data.model.vo.JobPointVo
 import com.grkj.data.model.vo.JobTicketGroupDataVo
 import com.grkj.data.model.vo.JobUserVo
@@ -32,6 +33,18 @@ class NetworkSopRepository @Inject constructor()  : BaseRepository(), ISopReposi
         TODO("Not yet implemented")
     }
 
+    override fun deleteSopWorkflowStepBySopId(sopIds: List<Long>) {
+        TODO("Not yet implemented")
+    }
+
+    override fun getSopWorkflowSteps(sopId: Long): List<IsSopWorkflowStep> {
+        TODO("Not yet implemented")
+    }
+
+    override fun updateStep(isSopWorkflowStep: List<IsSopWorkflowStep>) {
+        TODO("Not yet implemented")
+    }
+
     override fun saveSopPoint(
         selectedSopPint: List<JobTicketGroupDataVo<JobPointVo>>,
         sopId: Long

+ 74 - 52
data/src/main/java/com/grkj/data/repository/impl/standard/JobTicketRepository.kt

@@ -125,12 +125,13 @@ class JobTicketRepository @Inject constructor(
         val workflowStepList = workflowStepDao.getStepsByMode(modeId)
         val ticketStep = mutableListOf<IsJobTicketStep>().apply {
             workflowStepList.forEach { workflowStep ->
-                val isJobTicketStep = IsJobTicketStep()
+                val isJobTicketStep =
+                    BeanUtils.copyProperties(workflowStep, IsJobTicketStep::class.java)
+                        ?: IsJobTicketStep()
                 isJobTicketStep.ticketId = ticketId
                 isJobTicketStep.stepIndex = workflowStep.stepIndex
                 isJobTicketStep.stepContent = workflowStep.stepTitle
                 isJobTicketStep.androidStepContent = workflowStep.stepTitleShort
-                isJobTicketStep.workflowStepId = workflowStep.stepId
                 add(isJobTicketStep)
             }
         }
@@ -222,12 +223,13 @@ class JobTicketRepository @Inject constructor(
         val workflowStepList = workflowStepDao.getStepsByMode(modeId)
         val ticketStep = mutableListOf<IsJobTicketStep>().apply {
             workflowStepList.forEach { workflowStep ->
-                val isJobTicketStep = IsJobTicketStep()
+                val isJobTicketStep =
+                    BeanUtils.copyProperties(workflowStep, IsJobTicketStep::class.java)
+                        ?: IsJobTicketStep()
                 isJobTicketStep.ticketId = ticketId
                 isJobTicketStep.stepIndex = workflowStep.stepIndex
                 isJobTicketStep.stepContent = workflowStep.stepTitle
                 isJobTicketStep.androidStepContent = workflowStep.stepTitleShort
-                isJobTicketStep.workflowStepId = workflowStep.stepId
                 add(isJobTicketStep)
             }
         }
@@ -251,9 +253,21 @@ class JobTicketRepository @Inject constructor(
         val groups = jobTicketDao.getGroupsByTicketIds(tickets.map { it.ticketId })
         // 6. 获取作业票的上锁人数据
         val lockers = jobTicketDao.getTicketUsersByTicketIds(tickets.map { it.ticketId })
-        // 7. 构建待办项 TodoStepJoin
+            .filter { it.userRole == RoleEnum.JTLOCKER.roleKey }
+        // 7. 获取作业票的共锁人数据
+        var colockers = jobTicketDao.getTicketUsersByTicketIds(tickets.map { it.ticketId })
+            .filter { it.userRole == RoleEnum.JTCOLOCKER.roleKey }
+        // 8. 构建待办项 TodoStepJoin
         val todoList = assembleTodoStepJoins(
-            tickets, modeIdToSteps, stepInstances, keyRecords, groups, lockers, userId, userName
+            tickets,
+            modeIdToSteps,
+            stepInstances,
+            keyRecords,
+            groups,
+            lockers,
+            colockers,
+            userId,
+            userName
         )
         // 7. 当前用户真正需要处理的
         return todoList
@@ -269,6 +283,7 @@ class JobTicketRepository @Inject constructor(
         keyRecords: List<IsJobTicketKey>,
         groups: List<IsJobTicketGroup>,
         lockers: List<IsJobTicketUserDataVo>,
+        colockers: List<IsJobTicketUserDataVo>,
         userId: Long,
         userName: String
     ): List<TodoStepJoin> {
@@ -278,6 +293,7 @@ class JobTicketRepository @Inject constructor(
             val ticketId = ticket.ticketId
             val groupList = groups.filter { it.ticketId == ticketId }
             val lockerList = lockers.filter { it.ticketId == ticketId }
+            val colockerList = colockers.filter { it.ticketId == ticketId }
             val ticketSteps = stepInstances.filter { it.ticketId == ticketId }
             val workflowSteps = modeSteps[ticket.modeId] ?: emptyList()
             val previousStepJoin: MutableList<TodoStepJoin> = mutableListOf()
@@ -285,13 +301,10 @@ class JobTicketRepository @Inject constructor(
                 ticketSteps.filter { isJobTicketStep -> isJobTicketStep.stepStatus == "0" }
                     .minByOrNull { isJobTicketStep -> isJobTicketStep.stepIndex }?.stepId
             ticketSteps.sortedBy { it.stepIndex }.forEach { step ->
-                val workflowStep =
-                    workflowSteps.firstOrNull { it.stepId == step.workflowStepId } ?: return@forEach
-
                 when {
                     // 🔐 JTLOCKER 处理:上锁 or 解锁 ➜ 必须按 group 拆
-                    workflowStep.enableLock || workflowStep.enableUnlock -> {
-                        val type = if (workflowStep.enableLock) 0 else 1
+                    step.enableLock || step.enableUnlock -> {
+                        val type = if (step.enableLock) 0 else 1
                         val keys = keyRecords.filter {
                             it.ticketId == ticketId && it.ticketType == type && it.delFlag == "0"
                         }
@@ -302,8 +315,9 @@ class JobTicketRepository @Inject constructor(
                                 buildTodoStepJoin(
                                     step,
                                     ticket,
-                                    workflowStep,
+                                    step,
                                     lockerList,
+                                    colockerList,
                                     it.id,
                                     it.groupName,
                                     null
@@ -323,7 +337,9 @@ class JobTicketRepository @Inject constructor(
                                 buildTodoStepJoin(
                                     step,
                                     ticket,
-                                    workflowStep, lockerList,
+                                    step,
+                                    lockerList,
+                                    colockerList,
                                     key.groupId,
                                     groupList.find { group -> group.id == key.groupId }?.groupName,
                                     key
@@ -341,18 +357,27 @@ class JobTicketRepository @Inject constructor(
                         }
                     }
 
-                    // 🤝 JTCOLOCKER / RELEASE_COLOCK(不拆 group) todo 目前不需要添加共锁
-                    workflowStep.enableColock || workflowStep.enableReleaseColock -> {
-//                        val temp =buildTodoStepJoin(step, ticket, workflowStep, lockerList,null, null)
-//                        if (!previousStepJoin.isEmpty()) {
-//                            temp.previousTodoStepJoin = previousStepJoin.toList()
-//                        }
-//                        previousStepJoin.clear()
-//                        result +=temp
-//                        if (currentStepId == step.stepId) {
-//                            previousStepJoin.add(temp)
-//                        }
-
+                    // 🤝 JTCOLOCKER / RELEASE_COLOCK(不拆 group)
+                    step.enableColock || step.enableReleaseColock -> {
+                        val temp =
+                            buildTodoStepJoin(
+                                step,
+                                ticket,
+                                step,
+                                lockerList,
+                                colockerList,
+                                null,
+                                "",
+                                null
+                            )
+                        if (!previousStepJoin.isEmpty()) {
+                            temp.previousTodoStepJoin = previousStepJoin.toList()
+                        }
+                        previousStepJoin.clear()
+                        result += temp
+                        if (currentStepId == step.stepId) {
+                            previousStepJoin.add(temp)
+                        }
                     }
 
                     // 除了特殊的剩下的都是步骤确认
@@ -360,8 +385,9 @@ class JobTicketRepository @Inject constructor(
                         val temp = buildTodoStepJoin(
                             step,
                             ticket,
-                            workflowStep,
+                            step,
                             lockerList,
+                            colockerList,
                             null,
                             "",
                             null
@@ -389,8 +415,9 @@ class JobTicketRepository @Inject constructor(
     private fun buildTodoStepJoin(
         step: IsJobTicketStep,
         ticket: IsJobTicket,
-        workflowStep: WorkflowStep,
+        workflowStep: IsJobTicketStep,
         lockers: List<IsJobTicketUserDataVo>,
+        colockers: List<IsJobTicketUserDataVo>,
         groupId: Long?,
         groupName: String?,
         key: IsJobTicketKey?,
@@ -425,6 +452,7 @@ class JobTicketRepository @Inject constructor(
 
             userRole = getUserRole(workflowStep),
             lockerUserId = lockers.find { it.groupId == groupId }?.userId,
+            colockerUserId = colockers.map { it.userId },
             keyStatus = getKeyStatusFromKey(key),
             previousTodoStepJoin = previousTodoStepJoin
         ).also {
@@ -450,7 +478,7 @@ class JobTicketRepository @Inject constructor(
     /**
      * 根据用户组获取角色
      */
-    private fun getUserRole(step: WorkflowStep): String? {
+    private fun getUserRole(step: IsJobTicketStep): String? {
         return when {
             step.enableLock || step.enableUnlock -> RoleEnum.JTLOCKER.roleKey
             step.enableColock || step.enableReleaseColock -> RoleEnum.JTCOLOCKER.roleKey
@@ -487,13 +515,13 @@ class JobTicketRepository @Inject constructor(
             todoStep.let { tempTodo.addAll(it) }
 
             // 剩下的就是 wait
-            pendingSteps.filter { it !in todoStep }.let {
-                tempWait.addAll(it)
-            }
-
+            val waitSteps = pendingSteps.filter { it !in todoStep }
+                .sortedBy { it.stepIndex } // 可选:stepIndex小的优先
+                .take(waitLimit)
+            tempWait.addAll(waitSteps)
             tempDone.addAll(doneSteps)
         }
-        return tempTodo.size + tempWait.take(waitLimit).toMutableList().size
+        return tempTodo.size + tempWait.size
     }
 
     override fun updateCoincideToUnLock(ticketDetail: TicketDetailRes, groupId: Long) {
@@ -623,23 +651,19 @@ class JobTicketRepository @Inject constructor(
         jobTicketDao.startJob(jobTicketId, "1")
         val ticketStep = jobTicketDao.getJobTicketStepDataByTicketId(jobTicketId ?: 0)
         val ticketData = jobTicketDao.getTicketDataByTicketId(jobTicketId ?: 0)
-        val workflowSteps = workflowStepDao.getStepsByMode(ticketData?.modeId ?: 0)
         for (stepDataVo in ticketStep) {
-            val workflowStep = workflowSteps.find { it.stepId == stepDataVo.workflowStepId }
             //如果是自动确认并且没有操作的功能,则更新步骤
-            if (workflowStep?.confirmType != 0 && workflowStep?.hasAnyOperationFunction() == false) {
+            if (stepDataVo?.confirmType != 0 && stepDataVo?.hasAnyOperationFunction() == false) {
                 stepDataVo.stepStatus = "1"
                 BeanUtils.copyProperties(
                     stepDataVo, IsJobTicketStep::class.java
                 )?.let { jobTicketStep ->
                     updateTicketStepData(jobTicketStep)
-                    val currentWorkflowStep = workflowSteps.find {
-                        it.stepId == ticketStep.firstOrNull { it.stepStatus == "0" }?.workflowStepId
-                    }
-                    ticketData?.ticketStatus = currentWorkflowStep?.getTicketStatus() ?: ""
+                    ticketData?.ticketStatus =
+                        ticketStep.firstOrNull { it.stepStatus == "0" }?.getTicketStatus() ?: ""
                     updateTicketDataStatus(
                         jobTicketId ?: 0,
-                        currentWorkflowStep?.getTicketStatus()?.toInt()
+                        ticketStep.firstOrNull { it.stepStatus == "0" }?.getTicketStatus()?.toInt()
                             ?: JobTicketStatusEnum.PROGRESSING.status.toInt()
                     )
                 }
@@ -890,8 +914,7 @@ class JobTicketRepository @Inject constructor(
         isJobTicketKey.groupId = MainDomainData.deviceTakeTicketGroupBound[ticketId]
         val workflowSteps = workflowStepDao.getStepsByMode(jobTicketData.modeId!!)
         val ticketSteps = jobTicketDao.getJobTicketStepDataByTicketId(ticketId)
-        val currentStep =
-            workflowSteps.find { it.stepId == ticketSteps.firstOrNull { it.stepStatus == "0" }?.workflowStepId }
+        val currentStep = ticketSteps.firstOrNull { it.stepStatus == "0" }
         if (currentStep?.enableLock == true) {
             isJobTicketKey.ticketType = 0
         } else if (currentStep?.enableUnlock == true) {
@@ -944,8 +967,7 @@ class JobTicketRepository @Inject constructor(
         logger.info("作业票钥匙信息:${isJobTicketKeys}")
         val workflowSteps = workflowStepDao.getStepsByMode(jobTicketData.modeId!!)
         val ticketSteps = jobTicketDao.getJobTicketStepDataByTicketId(ticketId)
-        val currentStep =
-            workflowSteps.find { it.stepId == ticketSteps.firstOrNull { it.stepStatus == "0" }?.workflowStepId }
+        val currentStep = ticketSteps.firstOrNull { it.stepStatus == "0" }
         val isJobTicketKey = BeanUtils.copyProperties(
             isJobTicketKeys.firstOrNull {
                 it.keyId == keyId && it.groupId == groupId && ((currentStep?.enableLock == true && it.ticketType == 0) || (currentStep?.enableUnlock == true && it.ticketType == 1))
@@ -980,10 +1002,9 @@ class JobTicketRepository @Inject constructor(
         // 1. 取工单与模式
         val ticketData =
             jobTicketDao.getTicketDataByTicketId(ticketId) ?: return NextJobPrompt.NO_NEW_JOB
-        val modeId = ticketData.modeId ?: return NextJobPrompt.NO_NEW_JOB
 
         // 2. 取流程定义,只考虑同时含“上锁”和“解锁”的模式
-        val stepDefs = workflowStepDao.getStepsByMode(modeId)
+        val stepDefs = getJobTicketStepDataByTicketId(ticketId)
         if (stepDefs.none { it.enableLock } || stepDefs.none { it.enableUnlock }) {
             // 纯上锁或纯解锁,不在本逻辑范围内
             return NextJobPrompt.NO_NEW_JOB
@@ -996,7 +1017,7 @@ class JobTicketRepository @Inject constructor(
         // 4. 取已完成的步骤(stepStatus == "1" 表示已做过)
         val doneStepIds =
             jobTicketDao.getJobTicketStepDataByTicketId(ticketId).filter { it.stepStatus == "1" }
-                .map { it.workflowStepId }.toSet()
+                .map { it.stepId }.toSet()
         logger.info("当前已经完成的步骤:${doneStepIds}")
         // 5. 判断“上锁”/“解锁”哪一步已执行过
         val hasDoneLock = stepDefs.any { it.enableLock && doneStepIds.contains(it.stepId) }
@@ -1080,12 +1101,13 @@ class JobTicketRepository @Inject constructor(
         val workflowStepList = workflowStepDao.getStepsByMode(modeId)
         val ticketStep = mutableListOf<IsJobTicketStep>().apply {
             workflowStepList.forEach { workflowStep ->
-                val isJobTicketStep = IsJobTicketStep()
+                val isJobTicketStep =
+                    BeanUtils.copyProperties(workflowStep, IsJobTicketStep::class.java)
+                        ?: IsJobTicketStep()
                 isJobTicketStep.ticketId = ticketId
                 isJobTicketStep.stepIndex = workflowStep.stepIndex
                 isJobTicketStep.stepContent = workflowStep.stepTitle
                 isJobTicketStep.androidStepContent = workflowStep.stepTitleShort
-                isJobTicketStep.workflowStepId = workflowStep.stepId
                 add(isJobTicketStep)
             }
         }
@@ -1161,12 +1183,12 @@ class JobTicketRepository @Inject constructor(
         val workflowStepList = workflowStepDao.getStepsByMode(modeId)
         val ticketStep = mutableListOf<IsJobTicketStep>().apply {
             workflowStepList.forEach { workflowStep ->
-                val isJobTicketStep = IsJobTicketStep()
+                val isJobTicketStep = BeanUtils.copyProperties(workflowStep, IsJobTicketStep::class.java)
+                        ?: IsJobTicketStep()
                 isJobTicketStep.ticketId = ticketId
                 isJobTicketStep.stepIndex = workflowStep.stepIndex
                 isJobTicketStep.stepContent = workflowStep.stepTitle
                 isJobTicketStep.androidStepContent = workflowStep.stepTitleShort
-                isJobTicketStep.workflowStepId = workflowStep.stepId
                 add(isJobTicketStep)
             }
         }

+ 29 - 2
data/src/main/java/com/grkj/data/repository/impl/standard/SopRepository.kt

@@ -1,17 +1,20 @@
 package com.grkj.data.repository.impl.standard
 
 import com.grkj.data.dao.IsSopDao
+import com.grkj.data.dao.WorkflowStepDao
 import com.grkj.data.enums.RoleEnum
 import com.grkj.data.model.dos.IsSop
 import com.grkj.data.model.dos.IsSopGroup
 import com.grkj.data.model.dos.IsSopPoints
 import com.grkj.data.model.dos.IsSopUser
+import com.grkj.data.model.dos.IsSopWorkflowStep
 import com.grkj.data.model.vo.JobPointVo
 import com.grkj.data.model.vo.JobTicketGroupDataVo
 import com.grkj.data.model.vo.JobUserVo
 import com.grkj.data.model.vo.SopManageVo
 import com.grkj.data.repository.BaseRepository
 import com.grkj.data.repository.ISopRepository
+import com.sik.sikcore.data.BeanUtils
 import javax.inject.Inject
 import javax.inject.Singleton
 
@@ -19,7 +22,10 @@ import javax.inject.Singleton
  * sop仓储实现
  */
 @Singleton
-class SopRepository @Inject constructor(val isSopDao: IsSopDao) : BaseRepository(), ISopRepository {
+class SopRepository @Inject constructor(
+    val isSopDao: IsSopDao,
+    val workflowStepDao: WorkflowStepDao
+) : BaseRepository(), ISopRepository {
 
     override fun saveSop(
         sopId: Long,
@@ -32,7 +38,16 @@ class SopRepository @Inject constructor(val isSopDao: IsSopDao) : BaseRepository
         isSop.sopName = sopName
         isSop.workstationId = workstationId
         isSop.modeId = workflowModeId
-        return isSopDao.saveSop(isSop)
+        val sopId = isSopDao.saveSop(isSop)
+        val workflowStep = workflowStepDao.getStepsByMode(workflowModeId)
+        val isSopWorkflowStep = workflowStep.map {
+            val isSopWorkflowStep =
+                BeanUtils.copyProperties(it, IsSopWorkflowStep::class.java) ?: IsSopWorkflowStep()
+            isSopWorkflowStep.sopId = sopId
+            isSopWorkflowStep
+        }
+        isSopDao.saveSopWorkflowStep(isSopWorkflowStep)
+        return sopId
     }
 
     override fun saveSopPoint(
@@ -51,10 +66,22 @@ class SopRepository @Inject constructor(val isSopDao: IsSopDao) : BaseRepository
         isSopDao.saveSopPoints(isSopPoints.flatten())
     }
 
+    override fun updateStep(isSopWorkflowStep: List<IsSopWorkflowStep>) {
+        isSopDao.updateStep(isSopWorkflowStep)
+    }
+
+    override fun getSopWorkflowSteps(sopId: Long): List<IsSopWorkflowStep> {
+        return isSopDao.getSopWorkflowSteps(sopId)
+    }
+
     override fun saveSopGroup(group: IsSopGroup): Long {
         return isSopDao.saveSopGroup(group)
     }
 
+    override fun deleteSopWorkflowStepBySopId(sopIds: List<Long>) {
+        return isSopDao.deleteSopWorkflowStepBySopId(sopIds)
+    }
+
     override fun deleteSopGroupBySopId(sopIds: List<Long>) {
         isSopDao.deleteSopGroupBySopId(sopIds)
     }