Преглед на файлове

refactor(更新)
- 创建sop完成

周文健 преди 5 месеца
родител
ревизия
e3a4c81c12
променени са 57 файла, в които са добавени 2367 реда и са изтрити 13 реда
  1. BIN
      app/src/main/assets/data.db
  2. 28 0
      app/src/main/java/com/grkj/iscs/common/DataTransferConstants.kt
  3. 13 0
      app/src/main/java/com/grkj/iscs/features/main/activity/MainActivity.kt
  4. 48 0
      app/src/main/java/com/grkj/iscs/features/main/enums/LockModeEnum.kt
  5. 11 0
      app/src/main/java/com/grkj/iscs/features/main/enums/LockStepEnum.kt
  6. 13 0
      app/src/main/java/com/grkj/iscs/features/main/enums/RoleEnums.kt
  7. 198 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/common/SelectMemberFragment.kt
  8. 104 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/common/SelectPointFragment.kt
  9. 7 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/data_manage/DataManageHomeFragment.kt
  10. 1 1
      app/src/main/java/com/grkj/iscs/features/main/fragment/data_manage/UserManageFragment.kt
  11. 7 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/exception_manage/ExceptionManageHomeFragment.kt
  12. 7 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/hardware_manage/HardwareManageHomeFragment.kt
  13. 366 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/CreateSopFragment.kt
  14. 24 1
      app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/JobManageHomeFragment.kt
  15. 32 0
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/common/SelectMemberViewModel.kt
  16. 28 0
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/common/SelectPointViewModel.kt
  17. 2 2
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/data_manage/UserManageViewModel.kt
  18. 51 0
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/job_manage/CreateSopViewModel.kt
  19. 6 0
      app/src/main/res/drawable/bg_point_normal.xml
  20. 5 0
      app/src/main/res/drawable/bg_point_select.xml
  21. 6 0
      app/src/main/res/drawable/bg_point_selected.xml
  22. 9 0
      app/src/main/res/drawable/bg_select_member_btn.xml
  23. 8 0
      app/src/main/res/drawable/card_white_bg.xml
  24. 5 0
      app/src/main/res/drawable/icon_add_box.xml
  25. 5 0
      app/src/main/res/drawable/icon_arrow_right.xml
  26. 11 0
      app/src/main/res/drawable/icon_select_member.xml
  27. 433 0
      app/src/main/res/layout/fragment_create_sop.xml
  28. 220 0
      app/src/main/res/layout/fragment_select_memeber.xml
  29. 169 0
      app/src/main/res/layout/fragment_select_point.xml
  30. 1 1
      app/src/main/res/layout/item_home_text_drop_down.xml
  31. 25 0
      app/src/main/res/layout/item_select_all_member.xml
  32. 26 0
      app/src/main/res/layout/item_select_member.xml
  33. 29 0
      app/src/main/res/layout/item_select_point.xml
  34. 27 1
      app/src/main/res/navigation/nav_job_manage.xml
  35. 25 0
      app/src/main/res/values-en/strings.xml
  36. 25 0
      app/src/main/res/values-zh/strings.xml
  37. 25 0
      app/src/main/res/values/strings.xml
  38. 32 0
      data/src/main/java/com/grkj/data/dao/IsSopDao.kt
  39. 19 0
      data/src/main/java/com/grkj/data/dao/IsolationPointDao.kt
  40. 38 1
      data/src/main/java/com/grkj/data/dao/UserDao.kt
  41. 8 1
      data/src/main/java/com/grkj/data/database/ISCSDatabase.kt
  42. 51 0
      data/src/main/java/com/grkj/data/model/dos/IsSop.kt
  43. 33 0
      data/src/main/java/com/grkj/data/model/dos/IsSopPoints.kt
  44. 33 0
      data/src/main/java/com/grkj/data/model/dos/IsSopUser.kt
  45. 2 0
      data/src/main/java/com/grkj/data/model/vo/UserManageVo.kt
  46. 5 0
      data/src/main/java/com/grkj/data/repository/IIsolationPointRepository.kt
  47. 28 0
      data/src/main/java/com/grkj/data/repository/ISopRepository.kt
  48. 5 1
      data/src/main/java/com/grkj/data/repository/IUserRepository.kt
  49. 4 0
      data/src/main/java/com/grkj/data/repository/impl/IsolationPointRepository.kt
  50. 65 0
      data/src/main/java/com/grkj/data/repository/impl/SopRepository.kt
  51. 4 1
      data/src/main/java/com/grkj/data/repository/impl/UserRepository.kt
  52. 8 3
      ui-base/src/main/java/com/grkj/ui_base/base/BaseFragment.kt
  53. 5 0
      ui-base/src/main/java/com/grkj/ui_base/data/EventConstants.kt
  54. 24 0
      ui-base/src/main/java/com/grkj/ui_base/utils/event/BottomNavVisibilityEvent.kt
  55. 1 0
      ui-base/src/main/res/values-en/strings.xml
  56. 1 0
      ui-base/src/main/res/values-zh/strings.xml
  57. 1 0
      ui-base/src/main/res/values/strings.xml

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


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

@@ -0,0 +1,28 @@
+package com.grkj.iscs.common
+
+/**
+ * 数据传输常量
+ */
+object DataTransferConstants {
+    /**
+     * 已经选择的点位
+     */
+    const val KEY_SELECTED_POINT_DATA = "key_selected_point_data"
+
+    /**
+     * 已经选择的上锁人/共锁人
+     */
+    const val KEY_SELECTED_MEMBER_LOCKER_DATA = "key_selected_member_locker_data"
+    const val KEY_SELECTED_MEMBER_COLOCKER_DATA = "key_selected_member_colocker_data"
+
+    /**
+     * 选择点位区域过滤
+     */
+    const val KEY_SELECT_POINT_WORKSTATION_ID = "KEY_SELECT_POINT_WORKSTATION_ID"
+
+    /**
+     * 上一步标题/图标
+     */
+    const val KEY_PREVIEW_STEP_TITLE_DATA = "key_preview_step_title_data"
+    const val KEY_PREVIEW_STEP_ICON_DATA = "key_preview_step_icon_data"
+}

+ 13 - 0
app/src/main/java/com/grkj/iscs/features/main/activity/MainActivity.kt

@@ -4,11 +4,15 @@ import android.view.Menu
 import android.view.View
 import androidx.core.view.get
 import androidx.core.view.isNotEmpty
+import androidx.core.view.isVisible
 import com.grkj.data.data.MainDomainData
 import com.grkj.data.model.local.TabConfig
 import com.grkj.iscs.R
 import com.grkj.iscs.databinding.ActivityMainBinding
+import com.grkj.shared.model.EventBean
 import com.grkj.ui_base.base.BaseActivity
+import com.grkj.ui_base.data.EventConstants
+import com.grkj.ui_base.utils.event.BottomNavVisibilityEvent
 
 /**
  * 首页
@@ -92,4 +96,13 @@ class MainActivity() : BaseActivity<ActivityMainBinding>() {
             binding.bottomNav.selectedItemId = firstId
         }
     }
+
+    override fun onEvent(event: EventBean<Any>) {
+        super.onEvent(event)
+        when (event.code) {
+            EventConstants.EVENT_BOTTOM_NAV_VISIBILITY -> {
+                binding.bottomNav.isVisible = (event.data as BottomNavVisibilityEvent).show
+            }
+        }
+    }
 }

+ 48 - 0
app/src/main/java/com/grkj/iscs/features/main/enums/LockModeEnum.kt

@@ -0,0 +1,48 @@
+package com.grkj.iscs.features.main.enums
+
+import com.grkj.iscs.R
+import com.grkj.ui_base.utils.CommonUtils
+
+/**
+ * 锁定模式
+ */
+enum class LockModeEnum(val lockMode: List<LockStepEnum>, val description: String) {
+    LOCK_MODE_1(
+        listOf(
+            LockStepEnum.SELECT_MEMBER,
+            LockStepEnum.LOCK,
+            LockStepEnum.COLOCK,
+            LockStepEnum.UNLOCK
+        ), "上锁->共锁->解锁"
+    ),
+    LOCK_MODE_2(
+        listOf(LockStepEnum.SELECT_MEMBER, LockStepEnum.LOCK, LockStepEnum.UNLOCK),
+        "上锁->解锁"
+    ),
+    LOCK_MODE_3(
+        listOf(LockStepEnum.SELECT_MEMBER, LockStepEnum.UNLOCK, LockStepEnum.LOCK),
+        "解锁->上锁"
+    ),
+    LOCK_MODE_4(listOf(LockStepEnum.SELECT_MEMBER, LockStepEnum.LOCK), "上锁"),
+    LOCK_MODE_5(listOf(LockStepEnum.SELECT_MEMBER, LockStepEnum.UNLOCK), "解锁");
+}
+
+/**
+ * 获取锁定模式字符串
+ */
+fun LockModeEnum.getLockModeStr(): String {
+    return when (this) {
+        LockModeEnum.LOCK_MODE_1 -> CommonUtils.getStr(R.string.lock_mode_1).toString()
+        LockModeEnum.LOCK_MODE_2 -> CommonUtils.getStr(R.string.lock_mode_2).toString()
+        LockModeEnum.LOCK_MODE_3 -> CommonUtils.getStr(R.string.lock_mode_3).toString()
+        LockModeEnum.LOCK_MODE_4 -> CommonUtils.getStr(R.string.lock_mode_4).toString()
+        LockModeEnum.LOCK_MODE_5 -> CommonUtils.getStr(R.string.lock_mode_5).toString()
+    }
+}
+
+/**
+ * 获取锁定模式类型
+ */
+fun LockModeEnum.getLockModeType(): String {
+    return this.lockMode.map { it.type }.joinToString(",")
+}

+ 11 - 0
app/src/main/java/com/grkj/iscs/features/main/enums/LockStepEnum.kt

@@ -0,0 +1,11 @@
+package com.grkj.iscs.features.main.enums
+
+/**
+ * 锁定步骤枚举
+ */
+enum class LockStepEnum(val type: Int, val description: String) {
+    SELECT_MEMBER(0, "选择人员"),
+    LOCK(1, "上锁"),
+    COLOCK(2, "共锁"),
+    UNLOCK(3, "解锁");
+}

+ 13 - 0
app/src/main/java/com/grkj/iscs/features/main/enums/RoleEnums.kt

@@ -0,0 +1,13 @@
+package com.grkj.iscs.features.main.enums
+
+/**
+ * 角色枚举
+ */
+enum class RoleEnums(val roleKey: String, val description: String) {
+    ADMIN("admin", "超级管理员"),
+    JTDRAWER("jtdrawer", "作业管理员"),
+    JTLOCKER("jtlocker", "作业负责人"),
+    JTCOLOCKER("jtcolocker", "作业参与人"),
+    JTGUARD("jtguard", "作业观察员"),
+    SYSCONFIG("sysconfig", "系统配置员"),
+}

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

@@ -0,0 +1,198 @@
+package com.grkj.iscs.features.main.fragment.common
+
+import android.widget.LinearLayout
+import androidx.lifecycle.ViewModelProvider
+import com.drake.brv.BindingAdapter
+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.model.vo.PointManageVo
+import com.grkj.data.model.vo.UserManageVo
+import com.grkj.iscs.R
+import com.grkj.iscs.common.DataTransferConstants
+import com.grkj.iscs.databinding.FragmentSelectMemeberBinding
+import com.grkj.iscs.databinding.ItemSelectAllMemberBinding
+import com.grkj.iscs.databinding.ItemSelectMemberBinding
+import com.grkj.iscs.features.main.enums.RoleEnums
+import com.grkj.iscs.features.main.viewmodel.common.SelectMemberViewModel
+import com.grkj.ui_base.base.BaseFragment
+import com.grkj.ui_base.utils.CommonUtils
+import com.sik.sikcore.data.GlobalDataTempStore
+import com.sik.sikcore.extension.setDebouncedClickListener
+
+/**
+ * 选择人员界面
+ */
+class SelectMemberFragment : BaseFragment<FragmentSelectMemeberBinding>() {
+    private val viewModel: SelectMemberViewModel by lazy { ViewModelProvider(this)[SelectMemberViewModel::class] }
+    private var selectedLockerData: MutableList<UserManageVo> = mutableListOf()
+    private var selectedColockerData: MutableList<UserManageVo> = mutableListOf()
+    private var isLockerSelect = true
+    override fun getLayoutId(): Int {
+        return R.layout.fragment_select_memeber
+    }
+
+    override fun initView() {
+        val previewStepIcon = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_PREVIEW_STEP_ICON_DATA) as Int
+        val previewStepTitle = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_PREVIEW_STEP_TITLE_DATA) as String
+        binding.previewStepTitle.text = previewStepTitle
+        binding.previewStepIv.setImageResource(previewStepIcon)
+        binding.back.setDebouncedClickListener {
+            navController.popBackStack()
+        }
+        binding.cancel.setDebouncedClickListener {
+            navController.popBackStack()
+        }
+        binding.confirm.setDebouncedClickListener {
+            GlobalDataTempStore.getInstance()
+                .saveData(DataTransferConstants.KEY_SELECTED_MEMBER_LOCKER_DATA, selectedLockerData)
+            GlobalDataTempStore.getInstance().saveData(
+                DataTransferConstants.KEY_SELECTED_MEMBER_COLOCKER_DATA,
+                selectedColockerData
+            )
+            navController.popBackStack()
+        }
+        binding.lockerRv.linear(LinearLayout.HORIZONTAL).setup {
+            addType<UserManageVo>(R.layout.item_select_member)
+            onBind {
+                onLockerRVBinding(this)
+            }
+        }
+        binding.colockerRv.linear(LinearLayout.HORIZONTAL).setup {
+            addType<UserManageVo>(R.layout.item_select_member)
+            onBind {
+                onColockerRVBinding(this)
+            }
+        }
+        binding.allUserRv.grid(6).setup {
+            addType<UserManageVo>(R.layout.item_select_all_member)
+            onBind {
+                onAllUserRVBinding(this)
+            }
+        }
+        binding.selectLockerTv.setDebouncedClickListener {
+            setLockerData()
+        }
+        binding.selectColockerTv.setDebouncedClickListener {
+            setColockerData()
+        }
+    }
+
+    private fun BindingAdapter.BindingViewHolder.onAllUserRVBinding(holder: BindingAdapter.BindingViewHolder) {
+        val itemBinding = holder.getBinding<ItemSelectAllMemberBinding>()
+        val item = holder.getModel<UserManageVo>()
+        itemBinding.lockerName.text = item.nickName
+        itemBinding.lockerIcon.isSelected = item.isSelected
+        itemBinding.root.setOnClickListener {
+            if (item.isSelected) {
+                item.isSelected = false
+                if (isLockerSelect) {
+                    selectedLockerData.removeIf { it.userId == item.userId }
+                } else {
+                    selectedColockerData.removeIf { it.userId == item.userId }
+                }
+            } else {
+                item.isSelected = true
+                if (isLockerSelect) {
+                    selectedLockerData.onEach { it.isSelected = false }.clear()
+                    selectedLockerData.add(item)
+                } else {
+                    selectedColockerData.add(item)
+                }
+            }
+            if (isLockerSelect) {
+                binding.lockerRv.adapter?.notifyDataSetChanged()
+            } else {
+                binding.colockerRv.adapter?.notifyDataSetChanged()
+            }
+            adapter.notifyDataSetChanged()
+        }
+    }
+
+    private fun BindingAdapter.BindingViewHolder.onLockerRVBinding(holder: BindingAdapter.BindingViewHolder) {
+        val itemBinding = holder.getBinding<ItemSelectMemberBinding>()
+        val item = holder.getModel<UserManageVo>()
+        itemBinding.lockerName.text = item.nickName
+        itemBinding.lockerIcon.isSelected = true
+        itemBinding.root.setOnClickListener {
+            selectedLockerData.removeIf { it.userId == item.userId }
+            viewModel.userData.find { it.userId == item.userId }?.isSelected = false
+            adapter.notifyDataSetChanged()
+            binding.allUserRv.adapter?.notifyDataSetChanged()
+        }
+    }
+
+    private fun BindingAdapter.BindingViewHolder.onColockerRVBinding(holder: BindingAdapter.BindingViewHolder) {
+        val itemBinding = holder.getBinding<ItemSelectMemberBinding>()
+        val item = holder.getModel<UserManageVo>()
+        itemBinding.lockerName.text = item.nickName
+        itemBinding.lockerIcon.isSelected = true
+        itemBinding.root.setOnClickListener {
+            selectedColockerData.removeIf { it.userId == item.userId }
+            viewModel.userData.find { it.userId == item.userId }?.isSelected = false
+            adapter.notifyDataSetChanged()
+            binding.allUserRv.adapter?.notifyDataSetChanged()
+        }
+    }
+
+    private fun setLockerData() {
+        isLockerSelect = true
+        binding.selectMemberTip.text = CommonUtils.getStr(R.string.select_locker_tip)
+        binding.lockerRv.models = selectedLockerData
+        binding.allUserRv.models =
+            viewModel.userData.filter { it.roleKeys.contains(RoleEnums.JTLOCKER.roleKey) }.apply {
+                forEach {
+                    it.isSelected = it.userId in selectedLockerData.map { it.userId }
+                }
+                sortedBy { it.isSelected }
+            }
+    }
+
+    private fun setColockerData() {
+        isLockerSelect = false
+        binding.selectMemberTip.text = CommonUtils.getStr(R.string.select_colocker_tip)
+        binding.colockerRv.models = selectedColockerData
+        binding.allUserRv.models =
+            viewModel.userData.filter { it.roleKeys.contains(RoleEnums.JTCOLOCKER.roleKey) }.apply {
+                forEach {
+                    it.isSelected = it.userId in selectedColockerData.map { it.userId }
+                }
+                sortedBy { it.isSelected }
+            }
+    }
+
+    override fun initData() {
+        super.initData()
+        viewModel.workstationId = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_SELECT_POINT_WORKSTATION_ID) as Long
+        if (GlobalDataTempStore.getInstance()
+                .hasData(DataTransferConstants.KEY_SELECTED_MEMBER_LOCKER_DATA)
+        ) {
+            val tempSelectedLockerData =
+                GlobalDataTempStore.getInstance()
+                    .getData(DataTransferConstants.KEY_SELECTED_MEMBER_LOCKER_DATA)
+            if (tempSelectedLockerData is List<*>) {
+                selectedLockerData = (tempSelectedLockerData as List<UserManageVo>).toMutableList()
+                binding.lockerRv.models = selectedLockerData
+            }
+        }
+        if (GlobalDataTempStore.getInstance()
+                .hasData(DataTransferConstants.KEY_SELECTED_MEMBER_COLOCKER_DATA)
+        ) {
+            val tempSelectedColockerData =
+                GlobalDataTempStore.getInstance()
+                    .getData(DataTransferConstants.KEY_SELECTED_MEMBER_COLOCKER_DATA)
+            if (tempSelectedColockerData is List<*>) {
+                selectedColockerData =
+                    (tempSelectedColockerData as List<UserManageVo>).toMutableList()
+                binding.colockerRv.models = selectedColockerData
+            }
+        }
+        viewModel.getUserData().observe(this) {
+            setLockerData()
+        }
+    }
+}

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

@@ -0,0 +1,104 @@
+package com.grkj.iscs.features.main.fragment.common
+
+import androidx.lifecycle.ViewModelProvider
+import com.drake.brv.BindingAdapter
+import com.drake.brv.utils.grid
+import com.drake.brv.utils.models
+import com.drake.brv.utils.setup
+import com.grkj.data.model.vo.PointManageVo
+import com.grkj.iscs.R
+import com.grkj.iscs.common.DataTransferConstants
+import com.grkj.iscs.databinding.FragmentSelectPointBinding
+import com.grkj.iscs.databinding.ItemSelectPointBinding
+import com.grkj.iscs.features.main.viewmodel.common.SelectPointViewModel
+import com.grkj.ui_base.base.BaseFragment
+import com.sik.sikcore.data.GlobalDataTempStore
+import com.sik.sikcore.extension.setDebouncedClickListener
+
+/**
+ * 选择点位界面
+ */
+class SelectPointFragment : BaseFragment<FragmentSelectPointBinding>() {
+    private val viewModel: SelectPointViewModel by lazy { ViewModelProvider(this)[SelectPointViewModel::class] }
+    private var selectedPointData: MutableList<PointManageVo> = mutableListOf()
+    override fun getLayoutId(): Int {
+        return R.layout.fragment_select_point
+    }
+
+    override fun initView() {
+        binding.back.setDebouncedClickListener {
+            navController.popBackStack()
+        }
+        binding.cancel.setDebouncedClickListener {
+            navController.popBackStack()
+        }
+        binding.confirm.setDebouncedClickListener {
+            GlobalDataTempStore.getInstance()
+                .saveData(DataTransferConstants.KEY_SELECTED_POINT_DATA, selectedPointData)
+            navController.popBackStack()
+        }
+        binding.unselectedPointRv.grid(6).setup {
+            addType<PointManageVo>(R.layout.item_select_point)
+            onBind {
+                onAllPointRVBinding(this)
+            }
+        }
+        binding.selectedPointRv.grid(6).setup {
+            addType<PointManageVo>(R.layout.item_select_point)
+            onBind {
+                onSelectedPointRVBinding(this)
+            }
+        }
+    }
+
+    private fun BindingAdapter.BindingViewHolder.onSelectedPointRVBinding(holder: BindingAdapter.BindingViewHolder) {
+        val itemBinding = holder.getBinding<ItemSelectPointBinding>()
+        val item = holder.getModel<PointManageVo>()
+        itemBinding.pointName.text = item.pointName
+        itemBinding.pointIcon.isSelected = false
+        itemBinding.root.setOnClickListener {
+            if (item.isSelected) {
+                item.isSelected = false
+                selectedPointData.removeIf { it.pointId == item.pointId }
+            }
+            adapter.notifyDataSetChanged()
+            binding.selectedPointRv.adapter?.notifyDataSetChanged()
+        }
+    }
+
+    private fun BindingAdapter.BindingViewHolder.onAllPointRVBinding(holder: BindingAdapter.BindingViewHolder) {
+        val itemBinding = holder.getBinding<ItemSelectPointBinding>()
+        val item = holder.getModel<PointManageVo>()
+        itemBinding.pointName.text = item.pointName
+        itemBinding.pointIcon.isSelected = item.isSelected
+        itemBinding.root.setOnClickListener {
+            if (item.isSelected) {
+                item.isSelected = false
+                selectedPointData.removeIf { it.pointId == item.pointId }
+            } else {
+                item.isSelected = true
+                selectedPointData.add(item)
+            }
+            adapter.notifyDataSetChanged()
+            binding.selectedPointRv.adapter?.notifyDataSetChanged()
+        }
+    }
+
+    override fun initData() {
+        super.initData()
+        viewModel.workstationId = GlobalDataTempStore.getInstance()
+            .getData(DataTransferConstants.KEY_SELECT_POINT_WORKSTATION_ID) as Long
+        val tempSelectedPointData =
+            GlobalDataTempStore.getInstance().getData(DataTransferConstants.KEY_SELECTED_POINT_DATA)
+        if (tempSelectedPointData is List<*>) {
+            selectedPointData = (tempSelectedPointData as List<PointManageVo>).toMutableList()
+        }
+        viewModel.getPointData().observe(this) {
+            binding.selectedPointRv.models = selectedPointData
+            binding.unselectedPointRv.models = viewModel.pointManageData.apply {
+                forEach { it.isSelected == it.pointId in selectedPointData.map { it.pointId } }
+                sortBy { it.isSelected }
+            }
+        }
+    }
+}

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

@@ -16,6 +16,7 @@ import com.grkj.iscs.databinding.FragmentDataManageHomeBinding
 import com.grkj.iscs.databinding.ItemHomeMenuBinding
 import com.grkj.iscs.features.main.entity.MenuItemEntity
 import com.grkj.ui_base.base.BaseFragment
+import com.grkj.ui_base.utils.event.BottomNavVisibilityEvent
 
 /**
  * 数据管理首页
@@ -84,7 +85,13 @@ class DataManageHomeFragment : BaseFragment<FragmentDataManageHomeBinding>() {
         }
     }
 
+    override fun onResume() {
+        super.onResume()
+        BottomNavVisibilityEvent.sendBottomNavVisibilityEvent()
+    }
+
     private fun onMenuClick(menuType: Int) {
+        BottomNavVisibilityEvent.sendBottomNavVisibilityEvent(false)
         when (menuType) {
             0 -> {
                 navController.navigate(R.id.action_dataManageHomeFragment_to_userManageFragment)

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

@@ -83,7 +83,7 @@ class UserManageFragment : BaseFragment<FragmentUserManageBinding>() {
             deleteSelectUser()
         }
         binding.addUser.setDebouncedClickListener {
-            viewModel.initRoleAndWorkStationData().observe(this) {
+            viewModel.getRoleAndWorkStationData().observe(this) {
                 addUserDialog.setRoleData(viewModel.roleData.map {
                     TextDropDownDialog.SimpleTextDropDownEntity(
                         dataId = it.roleId,

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

@@ -12,6 +12,7 @@ import com.grkj.iscs.databinding.FragmentExceptionManageHomeBinding
 import com.grkj.iscs.databinding.ItemHomeMenuBinding
 import com.grkj.iscs.features.main.entity.MenuItemEntity
 import com.grkj.ui_base.base.BaseFragment
+import com.grkj.ui_base.utils.event.BottomNavVisibilityEvent
 
 /**
  * 异常管理首页
@@ -72,7 +73,13 @@ class ExceptionManageHomeFragment : BaseFragment<FragmentExceptionManageHomeBind
         }
     }
 
+    override fun onResume() {
+        super.onResume()
+        BottomNavVisibilityEvent.sendBottomNavVisibilityEvent()
+    }
+
     private fun onMenuClick(menuType: Int) {
+        BottomNavVisibilityEvent.sendBottomNavVisibilityEvent(false)
         when (menuType) {
             0 -> {
 

+ 7 - 0
app/src/main/java/com/grkj/iscs/features/main/fragment/hardware_manage/HardwareManageHomeFragment.kt

@@ -12,6 +12,7 @@ import com.grkj.iscs.databinding.FragmentHardwareManageHomeBinding
 import com.grkj.iscs.databinding.ItemHomeMenuBinding
 import com.grkj.iscs.features.main.entity.MenuItemEntity
 import com.grkj.ui_base.base.BaseFragment
+import com.grkj.ui_base.utils.event.BottomNavVisibilityEvent
 
 /**
  * 硬件管理首页
@@ -85,7 +86,13 @@ class HardwareManageHomeFragment : BaseFragment<FragmentHardwareManageHomeBindin
         }
     }
 
+    override fun onResume() {
+        super.onResume()
+        BottomNavVisibilityEvent.sendBottomNavVisibilityEvent()
+    }
+
     private fun onMenuClick(menuType: Int) {
+        BottomNavVisibilityEvent.sendBottomNavVisibilityEvent(false)
         when (menuType) {
             0 -> {
 

+ 366 - 0
app/src/main/java/com/grkj/iscs/features/main/fragment/job_manage/CreateSopFragment.kt

@@ -0,0 +1,366 @@
+package com.grkj.iscs.features.main.fragment.job_manage
+
+import android.widget.LinearLayout
+import androidx.core.view.isVisible
+import androidx.lifecycle.ViewModelProvider
+import com.drake.brv.BindingAdapter
+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.model.vo.PointManageVo
+import com.grkj.data.model.vo.UserManageVo
+import com.grkj.iscs.R
+import com.grkj.iscs.common.DataTransferConstants
+import com.grkj.iscs.databinding.FragmentCreateSopBinding
+import com.grkj.iscs.databinding.ItemSelectMemberBinding
+import com.grkj.iscs.databinding.ItemSelectPointBinding
+import com.grkj.iscs.features.main.dialog.TextDropDownDialog
+import com.grkj.iscs.features.main.enums.LockModeEnum
+import com.grkj.iscs.features.main.enums.getLockModeStr
+import com.grkj.iscs.features.main.enums.getLockModeType
+import com.grkj.iscs.features.main.viewmodel.job_manage.CreateSopViewModel
+import com.grkj.ui_base.base.BaseFragment
+import com.grkj.ui_base.dialog.TipDialog
+import com.grkj.ui_base.utils.CommonUtils
+import com.kongzue.dialogx.dialogs.PopTip
+import com.sik.sikcore.data.GlobalDataTempStore
+import com.sik.sikcore.extension.setDebouncedClickListener
+
+/**
+ * 新建SOP
+ */
+class CreateSopFragment : BaseFragment<FragmentCreateSopBinding>() {
+    private val viewModel: CreateSopViewModel by lazy { ViewModelProvider(this)[CreateSopViewModel::class] }
+    private var selectedLockMode: String? = null
+    private var selectedWorkstationId: Long? = null
+    private var selectedPointData: List<PointManageVo> = mutableListOf()
+    private var selectedLockerData: List<UserManageVo> = mutableListOf()
+    private var selectedColockerData: List<UserManageVo> = mutableListOf()
+    private lateinit var textDropDownDialog: TextDropDownDialog
+    override fun getLayoutId(): Int {
+        return R.layout.fragment_create_sop
+    }
+
+    override fun initView() {
+        textDropDownDialog = TextDropDownDialog(requireContext())
+        textDropDownDialog.setWidthAsAnchorView(true)
+        binding.back.setDebouncedClickListener {
+            TipDialog.show(
+                title = CommonUtils.getStr(com.grkj.ui_base.R.string.action_hint).toString(),
+                msg = CommonUtils.getStr(R.string.not_save_tip).toString(),
+                dialogType = TipDialog.DialogType.ERROR,
+                countDownTime = 10,
+                onConfirmClick = {
+                    navController.popBackStack()
+                })
+        }
+        binding.cancel.setDebouncedClickListener {
+            TipDialog.show(
+                title = CommonUtils.getStr(com.grkj.ui_base.R.string.action_hint).toString(),
+                msg = CommonUtils.getStr(R.string.not_save_tip).toString(),
+                dialogType = TipDialog.DialogType.ERROR,
+                countDownTime = 10,
+                onConfirmClick = {
+                    navController.popBackStack()
+                })
+        }
+        binding.confirm.setDebouncedClickListener {
+            if (checkData()) {
+                saveSop()
+            }
+        }
+        binding.workstationTv.setOnClickListener {
+            setWorkstationData()
+        }
+        binding.lockModeTv.setOnClickListener {
+            setLockModeData()
+        }
+        binding.noSelectedPointLayout.setDebouncedClickListener {
+            if (selectedWorkstationId == null) {
+                PopTip.tip(R.string.please_select_sop_workstation)
+                return@setDebouncedClickListener
+            }
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_SELECT_POINT_WORKSTATION_ID,
+                    selectedWorkstationId!!
+                )
+            GlobalDataTempStore.getInstance()
+                .saveData(DataTransferConstants.KEY_SELECTED_POINT_DATA, selectedPointData)
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_PREVIEW_STEP_TITLE_DATA,
+                    CommonUtils.getStr(R.string.create_sop_title).toString()
+                )
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_PREVIEW_STEP_ICON_DATA,
+                    R.mipmap.icon_data_manage_menu_point_manage
+                )
+            navController.navigate(R.id.action_createSopFragment_to_selectPointFragment)
+        }
+        binding.noSelectedMemberLayout.setDebouncedClickListener {
+            if (selectedWorkstationId == null) {
+                PopTip.tip(R.string.please_select_sop_workstation)
+                return@setDebouncedClickListener
+            }
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_SELECT_POINT_WORKSTATION_ID,
+                    selectedWorkstationId!!
+                )
+            GlobalDataTempStore.getInstance()
+                .saveData(DataTransferConstants.KEY_SELECTED_MEMBER_LOCKER_DATA, selectedLockerData)
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_SELECTED_MEMBER_COLOCKER_DATA,
+                    selectedColockerData
+                )
+            GlobalDataTempStore.getInstance().saveData(
+                DataTransferConstants.KEY_SELECTED_MEMBER_COLOCKER_DATA,
+                selectedColockerData
+            )
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_PREVIEW_STEP_TITLE_DATA,
+                    CommonUtils.getStr(R.string.create_sop_title).toString()
+                )
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_PREVIEW_STEP_ICON_DATA,
+                    R.mipmap.icon_data_manage_menu_point_manage
+                )
+            navController.navigate(R.id.action_createSopFragment_to_selectMemberFragment)
+        }
+        binding.selectPointTv.setDebouncedClickListener {
+            if (selectedWorkstationId == null) {
+                PopTip.tip(R.string.please_select_sop_workstation)
+                return@setDebouncedClickListener
+            }
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_SELECT_POINT_WORKSTATION_ID,
+                    selectedWorkstationId!!
+                )
+            GlobalDataTempStore.getInstance()
+                .saveData(DataTransferConstants.KEY_SELECTED_POINT_DATA, selectedPointData)
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_PREVIEW_STEP_TITLE_DATA,
+                    CommonUtils.getStr(R.string.create_sop_title).toString()
+                )
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_PREVIEW_STEP_ICON_DATA,
+                    R.mipmap.icon_data_manage_menu_point_manage
+                )
+            navController.navigate(R.id.action_createSopFragment_to_selectPointFragment)
+        }
+        binding.selectMemberTv.setDebouncedClickListener {
+            if (selectedWorkstationId == null) {
+                PopTip.tip(R.string.please_select_sop_workstation)
+                return@setDebouncedClickListener
+            }
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_SELECT_POINT_WORKSTATION_ID,
+                    selectedWorkstationId!!
+                )
+            GlobalDataTempStore.getInstance()
+                .saveData(DataTransferConstants.KEY_SELECTED_MEMBER_LOCKER_DATA, selectedLockerData)
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_SELECTED_MEMBER_COLOCKER_DATA,
+                    selectedColockerData
+                )
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_PREVIEW_STEP_TITLE_DATA,
+                    CommonUtils.getStr(R.string.create_sop_title).toString()
+                )
+            GlobalDataTempStore.getInstance()
+                .saveData(
+                    DataTransferConstants.KEY_PREVIEW_STEP_ICON_DATA,
+                    R.mipmap.icon_data_manage_menu_point_manage
+                )
+            navController.navigate(R.id.action_createSopFragment_to_selectMemberFragment)
+        }
+        binding.pointRv.grid(6).setup {
+            addType<PointManageVo>(R.layout.item_select_point)
+            onBind {
+                onSelectedPointRVBinding(this)
+            }
+        }
+        binding.colockerRv.linear(orientation = LinearLayout.HORIZONTAL).setup {
+            addType<UserManageVo>(R.layout.item_select_member)
+            onBind {
+                onSelectedMemberRVBinding(this)
+            }
+        }
+    }
+
+    /**
+     * 保存sop
+     */
+    private fun saveSop() {
+        viewModel.saveSop(
+            selectedPointData,
+            selectedLockerData,
+            selectedColockerData,
+            selectedLockMode,
+            selectedWorkstationId,
+            binding.sopNameEt.text.toString()
+        ).observe(this) {
+            if (it) {
+                TipDialog.show(
+                    title = CommonUtils.getStr(com.grkj.ui_base.R.string.action_succeed).toString(),
+                    msg = CommonUtils.getStr(R.string.sop_create_succeed).toString(),
+                    dialogType = TipDialog.DialogType.SUCCESS,
+                    countDownTime = 10,
+                    onConfirmClick = {
+                        clearData()
+                    }
+                )
+            } else {
+                TipDialog.show(
+                    title = CommonUtils.getStr(com.grkj.ui_base.R.string.action_failed).toString(),
+                    msg = CommonUtils.getStr(R.string.sop_create_failed).toString(),
+                    dialogType = TipDialog.DialogType.ERROR,
+                    showConfirm = false,
+                    countDownTime = 10
+                )
+            }
+        }
+    }
+
+    private fun clearData() {
+        binding.sopNameEt.setText("")
+        selectedLockerData = listOf()
+        selectedColockerData = listOf()
+        selectedPointData = listOf()
+        selectedLockMode = null
+        selectedWorkstationId = null
+        binding.lockModeTv.text = ""
+        binding.workstationTv.text = ""
+        binding.noSelectedMemberLayout.isVisible = true
+        binding.noSelectedPointLayout.isVisible = true
+    }
+
+    /**
+     * 检查数据
+     */
+    private fun checkData(): Boolean {
+        if (selectedWorkstationId == null) {
+            PopTip.tip(R.string.please_select_sop_workstation)
+            return false
+        }
+        if (selectedLockMode == null) {
+            PopTip.tip(R.string.please_select_lock_mode)
+            return false
+        }
+        if (binding.sopNameEt.text.isEmpty()) {
+            PopTip.tip(R.string.please_input_sop_name)
+            return false
+        }
+        if (selectedPointData.isEmpty()) {
+            PopTip.tip(R.string.please_must_select_at_least_one_point)
+            return false
+        }
+        if (selectedLockerData.isEmpty()) {
+            PopTip.tip(com.grkj.ui_base.R.string.select_locker)
+            return false
+        }
+        if (selectedColockerData.isEmpty()) {
+            PopTip.tip(com.grkj.ui_base.R.string.select_coloker)
+            return false
+        }
+        return true
+    }
+
+    private fun BindingAdapter.BindingViewHolder.onSelectedMemberRVBinding(holder: BindingAdapter.BindingViewHolder) {
+        val itemBinding = holder.getBinding<ItemSelectMemberBinding>()
+        val item = holder.getModel<UserManageVo>()
+        itemBinding.lockerName.text = item.nickName
+        itemBinding.lockerIcon.isSelected = true
+    }
+
+    private fun BindingAdapter.BindingViewHolder.onSelectedPointRVBinding(holder: BindingAdapter.BindingViewHolder) {
+        val itemBinding = holder.getBinding<ItemSelectPointBinding>()
+        val item = holder.getModel<PointManageVo>()
+        itemBinding.pointName.text = item.pointName.toString()
+        itemBinding.pointIcon.setImageResource(R.mipmap.icon_data_manage_menu_point_manage)
+    }
+
+    override fun onResume() {
+        super.onResume()
+        if (GlobalDataTempStore.getInstance()
+                .hasData(DataTransferConstants.KEY_SELECTED_MEMBER_LOCKER_DATA)
+        ) {
+            selectedLockerData = GlobalDataTempStore.getInstance()
+                .getData(DataTransferConstants.KEY_SELECTED_MEMBER_LOCKER_DATA)
+                ?.let { return@let it as List<UserManageVo> } ?: listOf()
+        }
+
+        if (GlobalDataTempStore.getInstance()
+                .hasData(DataTransferConstants.KEY_SELECTED_MEMBER_COLOCKER_DATA)
+        ) {
+            selectedColockerData = GlobalDataTempStore.getInstance()
+                .getData(DataTransferConstants.KEY_SELECTED_MEMBER_COLOCKER_DATA)
+                ?.let { return@let it as List<UserManageVo> } ?: listOf()
+        }
+
+        if (GlobalDataTempStore.getInstance()
+                .hasData(DataTransferConstants.KEY_SELECTED_POINT_DATA)
+        ) {
+            selectedPointData = GlobalDataTempStore.getInstance()
+                .getData(DataTransferConstants.KEY_SELECTED_POINT_DATA)
+                ?.let { return@let it as List<PointManageVo> } ?: listOf()
+        }
+        binding.noSelectedMemberLayout.isVisible =
+            selectedColockerData.isEmpty() && selectedLockerData.isEmpty()
+        binding.noSelectedPointLayout.isVisible = selectedPointData.isEmpty()
+        if (selectedColockerData.isNotEmpty()) {
+            binding.colockerRv.models = selectedColockerData
+        }
+        if (selectedLockerData.isNotEmpty()) {
+            val userData = selectedLockerData.first()
+            binding.lockerName.text = userData.nickName
+        }
+        if (selectedPointData.isNotEmpty()) {
+            binding.pointRv.models = selectedPointData
+        }
+    }
+
+    private fun setWorkstationData() {
+        viewModel.getWorkstationData().observe(this) {
+            textDropDownDialog.setData(
+                viewModel.workstationData.map {
+                    TextDropDownDialog.SimpleTextDropDownEntity(
+                        dataId = it.workstationId,
+                        dataText = it.workstationName
+                    )
+                })
+            textDropDownDialog.setOnItemSelectListener {
+                binding.workstationTv.text = it.getShowText()
+                selectedWorkstationId = it.getId()
+            }
+            textDropDownDialog.showPopupWindow(binding.workstationTv)
+        }
+    }
+
+    private fun setLockModeData() {
+        textDropDownDialog.setData(
+            LockModeEnum.values().map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataTag = it.getLockModeType(),
+                    dataText = it.getLockModeStr()
+                )
+            })
+        textDropDownDialog.setOnItemSelectListener {
+            binding.lockModeTv.text = it.getShowText()
+            selectedLockMode = it.getTag()
+        }
+        textDropDownDialog.showPopupWindow(binding.lockModeTv)
+    }
+}

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

@@ -12,6 +12,7 @@ import com.grkj.iscs.databinding.FragmentJobManageHomeBinding
 import com.grkj.iscs.databinding.ItemHomeMenuBinding
 import com.grkj.iscs.features.main.entity.MenuItemEntity
 import com.grkj.ui_base.base.BaseFragment
+import com.grkj.ui_base.utils.event.BottomNavVisibilityEvent
 
 /**
  * 作业管理首页
@@ -103,14 +104,20 @@ class JobManageHomeFragment : BaseFragment<FragmentJobManageHomeBinding>() {
         }
     }
 
+    override fun onResume() {
+        super.onResume()
+        BottomNavVisibilityEvent.sendBottomNavVisibilityEvent()
+    }
+
     private fun onMenuClick(menuType: Int) {
+        BottomNavVisibilityEvent.sendBottomNavVisibilityEvent(false)
         when (menuType) {
             0 -> {
 
             }
 
             1 -> {
-
+                navController.navigate(R.id.action_jobManageHomeFragment_to_createSopFragment)
             }
 
             2 -> {
@@ -120,6 +127,22 @@ class JobManageHomeFragment : BaseFragment<FragmentJobManageHomeBinding>() {
             3 -> {
 
             }
+
+            4 -> {
+                navController.navigate(R.id.action_jobManageHomeFragment_to_createJobFragment)
+            }
+
+            5 -> {
+
+            }
+
+            6 -> {
+
+            }
+
+            7 -> {
+
+            }
         }
     }
 }

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

@@ -0,0 +1,32 @@
+package com.grkj.iscs.features.main.viewmodel.common
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.liveData
+import com.grkj.data.model.vo.UserManageVo
+import com.grkj.data.repository.IUserRepository
+import com.grkj.data.repository.impl.UserRepository
+import com.grkj.ui_base.base.BaseViewModel
+import kotlinx.coroutines.Dispatchers
+
+/**
+ * 选择人员
+ */
+class SelectMemberViewModel : BaseViewModel() {
+    private val userRepository: IUserRepository by lazy { UserRepository.instance }
+    var workstationId: Long = 0
+
+    /**
+     * 用户数据
+     */
+    var userData: List<UserManageVo> = mutableListOf()
+
+    /**
+     * 获取用户数据
+     */
+    fun getUserData(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            userData = userRepository.getAllUserDataWithWorkstation(workstationId)
+            emit(true)
+        }
+    }
+}

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

@@ -0,0 +1,28 @@
+package com.grkj.iscs.features.main.viewmodel.common
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.liveData
+import com.grkj.data.model.vo.PointManageVo
+import com.grkj.data.repository.IIsolationPointRepository
+import com.grkj.data.repository.impl.IsolationPointRepository
+import com.grkj.ui_base.base.BaseViewModel
+import kotlinx.coroutines.Dispatchers
+
+/**
+ * 选择点位
+ */
+class SelectPointViewModel : BaseViewModel() {
+    private val pointRepository: IIsolationPointRepository by lazy { IsolationPointRepository.instance }
+    var pointManageData: MutableList<PointManageVo> = mutableListOf()
+    var workstationId: Long = 0
+
+    /**
+     * 获取点位数据
+     */
+    fun getPointData(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            pointManageData = pointRepository.getAllPointManageDataWithWorkstationId(workstationId)
+            emit(true)
+        }
+    }
+}

+ 2 - 2
app/src/main/java/com/grkj/iscs/features/main/viewmodel/data_manage/UserManageViewModel.kt

@@ -79,9 +79,9 @@ class UserManageViewModel : BaseViewModel() {
     }
 
     /**
-     * 初始化角色和岗位数据
+     * 获取角色和岗位数据
      */
-    fun initRoleAndWorkStationData(): LiveData<Boolean> {
+    fun getRoleAndWorkStationData(): LiveData<Boolean> {
         return liveData(Dispatchers.IO) {
             roleData = roleRepository.getRoleData()
             workstationData = workstationRepository.getWorkStationData()

+ 51 - 0
app/src/main/java/com/grkj/iscs/features/main/viewmodel/job_manage/CreateSopViewModel.kt

@@ -0,0 +1,51 @@
+package com.grkj.iscs.features.main.viewmodel.job_manage
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.liveData
+import com.grkj.data.model.dos.IsWorkstation
+import com.grkj.data.model.vo.PointManageVo
+import com.grkj.data.model.vo.UserManageVo
+import com.grkj.data.repository.ISopRepository
+import com.grkj.data.repository.IWorkstationRepository
+import com.grkj.data.repository.impl.SopRepository
+import com.grkj.data.repository.impl.WorkstationRepository
+import com.grkj.ui_base.base.BaseViewModel
+import kotlinx.coroutines.Dispatchers
+
+/**
+ * 新建sop界面模型
+ */
+class CreateSopViewModel : BaseViewModel() {
+    private val workstationRepository: IWorkstationRepository by lazy { WorkstationRepository.instance }
+    private val sopRepository: ISopRepository by lazy { SopRepository.instance }
+    var workstationData: List<IsWorkstation> = listOf()
+
+    /**
+     * 初始化岗位数据
+     */
+    fun getWorkstationData(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            workstationData = workstationRepository.getWorkStationData()
+            emit(true)
+        }
+    }
+
+    /**
+     * 保存sop
+     */
+    fun saveSop(
+        selectedPointsData: List<PointManageVo>,
+        selectedLockerData: List<UserManageVo>,
+        selectedColockerData: List<UserManageVo>,
+        lockMode: String?,
+        workstationId: Long,
+        sopName: String
+    ): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            val sopId = sopRepository.saveSop(sopName, workstationId, lockMode)
+            sopRepository.saveSopPoint(selectedPointsData, sopId)
+            sopRepository.saveSopUser(selectedLockerData, selectedColockerData, sopId)
+            emit(true)
+        }
+    }
+}

+ 6 - 0
app/src/main/res/drawable/bg_point_normal.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <stroke android:width="1dp" android:color="@color/black"/>
+    <solid android:color="@color/white"/>
+</shape>

+ 5 - 0
app/src/main/res/drawable/bg_point_select.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:drawable="@drawable/bg_point_selected" android:state_selected="true" />
+    <item android:drawable="@drawable/bg_point_normal" />
+</selector>

+ 6 - 0
app/src/main/res/drawable/bg_point_selected.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <stroke android:width="1dp" android:color="@color/black"/>
+    <solid android:color="@color/color_a5d8ff"/>
+</shape>

+ 9 - 0
app/src/main/res/drawable/bg_select_member_btn.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="@color/common_tip_dialog_info" />
+    <stroke
+        android:width="1dp"
+        android:color="@color/black" />
+    <corners android:radius="6dp" />
+</shape>

+ 8 - 0
app/src/main/res/drawable/card_white_bg.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <stroke
+        android:width="1dp"
+        android:color="@color/black" />
+    <solid android:color="@color/white" />
+</shape>

+ 5 - 0
app/src/main/res/drawable/icon_add_box.xml

@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
+      
+    <path android:fillColor="@android:color/white" android:pathData="M19,3L5,3c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM19,19L5,19L5,5h14v14zM11,17h2v-4h4v-2h-4L13,7h-2v4L7,11v2h4z"/>
+    
+</vector>

+ 5 - 0
app/src/main/res/drawable/icon_arrow_right.xml

@@ -0,0 +1,5 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
+      
+    <path android:fillColor="@android:color/white" android:pathData="M6.23,20.23l1.77,1.77l10,-10l-10,-10l-1.77,1.77l8.23,8.23z"/>
+    
+</vector>

+ 11 - 0
app/src/main/res/drawable/icon_select_member.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <!-- 按下(或选中)时 -->
+    <item android:state_selected="true">
+        <bitmap android:gravity="center" android:src="@mipmap/icon_data_manage_menu_user_manage" android:tint="@color/black" android:tintMode="src_in" />
+    </item>
+    <!-- 默认状态 -->
+    <item>
+        <bitmap android:gravity="center" android:src="@mipmap/icon_data_manage_menu_user_manage" android:tintMode="src_in" />
+    </item>
+</selector>

+ 433 - 0
app/src/main/res/layout/fragment_create_sop.xml

@@ -0,0 +1,433 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_margin="20dp"
+        android:background="@drawable/home_card_bg"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:id="@+id/title_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            android:paddingHorizontal="10dp"
+            android:paddingVertical="5dp">
+
+            <ImageView
+                android:layout_width="20dp"
+                android:layout_height="20dp"
+                android:src="@mipmap/icon_data_manage_menu_user_manage" />
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:layout_weight="1"
+                android:text="@string/create_sop_title"
+                android:textColor="@color/black"
+                android:textSize="24sp" />
+
+            <TextView
+                android:id="@+id/back"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:background="@drawable/common_dialog_btn"
+                android:paddingHorizontal="20dp"
+                android:text="@string/back"
+                android:textColor="@color/black"
+                android:textSize="20sp" />
+        </LinearLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="@color/black" />
+
+        <LinearLayout
+            android:id="@+id/base_info_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="20dp"
+            android:layout_marginTop="20dp"
+            android:layout_marginBottom="10dp"
+            android:background="@drawable/home_card_bg"
+            android:gravity="center_vertical"
+            android:orientation="vertical">
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:layout_weight="1"
+                android:text="@string/base_info_title"
+                android:textColor="@color/black"
+                android:textSize="24sp" />
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="1dp"
+                android:background="@color/black" />
+
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="20dp"
+                android:gravity="center_vertical"
+                android:orientation="horizontal"
+                android:paddingHorizontal="16dp">
+
+                <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/sop_workstation"
+                    android:textColor="@color/black"
+                    android:textSize="18sp" />
+
+                <TextView
+                    android:id="@+id/workstation_tv"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dp"
+                    android:background="@drawable/bg_common_input"
+                    android:drawableRight="@drawable/icon_drop_down"
+                    android:hint="@string/please_select_sop_workstation"
+                    android:maxLines="1"
+                    android:paddingHorizontal="10dp"
+                    android:paddingVertical="2dp"
+                    android:singleLine="true"
+                    android:textColor="@color/black"
+                    android:textSize="18sp" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="20dp"
+                android:gravity="center_vertical"
+                android:orientation="horizontal"
+                android:paddingHorizontal="16dp">
+
+                <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/lock_mode"
+                    android:textColor="@color/black"
+                    android:textSize="18sp" />
+
+                <TextView
+                    android:id="@+id/lock_mode_tv"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dp"
+                    android:background="@drawable/bg_common_input"
+                    android:drawableRight="@drawable/icon_drop_down"
+                    android:hint="@string/please_select_lock_mode"
+                    android:maxLines="1"
+                    android:paddingHorizontal="10dp"
+                    android:paddingVertical="2dp"
+                    android:singleLine="true"
+                    android:textColor="@color/black"
+                    android:textSize="18sp" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="20dp"
+                android:layout_marginBottom="20dp"
+                android:gravity="center_vertical"
+                android:orientation="horizontal"
+                android:paddingHorizontal="16dp">
+
+                <TextView
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:text="@string/create_sop_name"
+                    android:textColor="@color/black"
+                    android:textSize="18sp" />
+
+                <EditText
+                    android:id="@+id/sop_name_et"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dp"
+                    android:background="@drawable/bg_common_input"
+                    android:hint="@string/please_input_sop_name"
+                    android:maxLines="1"
+                    android:paddingHorizontal="10dp"
+                    android:paddingVertical="2dp"
+                    android:singleLine="true"
+                    android:textColor="@color/black"
+                    android:textSize="18sp" />
+            </LinearLayout>
+        </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/point_info_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="20dp"
+            android:layout_marginVertical="10dp"
+            android:background="@drawable/home_card_bg"
+            android:gravity="center_vertical"
+            android:orientation="vertical">
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal">
+
+                <TextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dp"
+                    android:layout_weight="1"
+                    android:text="@string/point_info_title"
+                    android:textColor="@color/black"
+                    android:textSize="24sp" />
+
+                <TextView
+                    android:id="@+id/select_point_tv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dp"
+                    android:layout_marginRight="10dp"
+                    android:background="@drawable/common_dialog_btn"
+                    android:paddingHorizontal="20dp"
+                    android:text="@string/select"
+                    android:textColor="@color/black"
+                    android:textSize="20sp" />
+            </LinearLayout>
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="1dp"
+                android:background="@color/black" />
+
+            <FrameLayout
+                android:layout_width="match_parent"
+                android:layout_height="match_parent">
+
+                <androidx.recyclerview.widget.RecyclerView
+                    android:id="@+id/point_rv"
+                    android:layout_width="match_parent"
+                    android:layout_height="240dp"
+                    android:paddingBottom="10dp" />
+
+                <LinearLayout
+                    android:id="@+id/no_selected_point_layout"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:background="@drawable/card_white_bg"
+                    android:gravity="center"
+                    android:orientation="vertical">
+
+                    <ImageView
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:src="@drawable/icon_add_box" />
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:paddingHorizontal="20dp"
+                        android:paddingVertical="10dp"
+                        android:text="@string/please_must_select_at_least_one_point"
+                        android:textColor="@color/black"
+                        android:textSize="24sp" />
+                </LinearLayout>
+            </FrameLayout>
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/member_info_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="20dp"
+            android:layout_marginVertical="10dp"
+            android:background="@drawable/home_card_bg"
+            android:gravity="center_vertical"
+            android:orientation="vertical">
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal">
+
+                <TextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dp"
+                    android:layout_weight="1"
+                    android:text="@string/member_info_title"
+                    android:textColor="@color/black"
+                    android:textSize="24sp" />
+
+                <TextView
+                    android:id="@+id/select_member_tv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="10dp"
+                    android:layout_marginRight="10dp"
+                    android:background="@drawable/common_dialog_btn"
+                    android:paddingHorizontal="20dp"
+                    android:text="@string/select"
+                    android:textColor="@color/black"
+                    android:textSize="20sp" />
+            </LinearLayout>
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="1dp"
+                android:background="@color/black" />
+
+            <FrameLayout
+                android:layout_width="match_parent"
+                android:layout_height="match_parent">
+
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:orientation="horizontal">
+
+                    <LinearLayout
+                        android:layout_width="wrap_content"
+                        android:layout_height="match_parent"
+                        android:background="@drawable/home_card_bg"
+                        android:orientation="vertical">
+
+                        <TextView
+                            android:layout_width="wrap_content"
+                            android:layout_height="wrap_content"
+                            android:gravity="center"
+                            android:paddingHorizontal="20dp"
+                            android:paddingVertical="10dp"
+                            android:text="@string/locker"
+                            android:textColor="@color/black"
+                            android:textSize="24sp" />
+
+                        <View
+                            android:layout_width="match_parent"
+                            android:layout_height="1dp"
+                            android:background="@color/black" />
+
+                        <LinearLayout
+                            android:layout_width="match_parent"
+                            android:layout_height="match_parent"
+                            android:gravity="center"
+                            android:orientation="vertical">
+
+                            <ImageView
+                                android:layout_width="50dp"
+                                android:layout_height="50dp"
+                                android:layout_marginTop="10dp"
+                                android:src="@mipmap/icon_data_manage_menu_user_manage"
+                                android:tint="@color/black" />
+
+                            <TextView
+                                android:id="@+id/locker_name"
+                                android:layout_width="wrap_content"
+                                android:layout_height="wrap_content"
+                                android:gravity="center"
+                                android:paddingHorizontal="20dp"
+                                android:paddingVertical="10dp"
+                                android:textColor="@color/black"
+                                android:textSize="20sp" />
+                        </LinearLayout>
+                    </LinearLayout>
+
+                    <LinearLayout
+                        android:layout_width="match_parent"
+                        android:layout_height="match_parent"
+                        android:layout_weight="1"
+                        android:background="@drawable/home_card_bg"
+                        android:orientation="vertical">
+
+                        <TextView
+                            android:layout_width="match_parent"
+                            android:layout_height="wrap_content"
+                            android:gravity="center"
+                            android:paddingHorizontal="20dp"
+                            android:paddingVertical="10dp"
+                            android:text="@string/colocker"
+                            android:textColor="@color/black"
+                            android:textSize="24sp" />
+
+                        <View
+                            android:layout_width="match_parent"
+                            android:layout_height="1dp"
+                            android:background="@color/black" />
+
+                        <androidx.recyclerview.widget.RecyclerView
+                            android:id="@+id/colocker_rv"
+                            android:layout_width="wrap_content"
+                            android:layout_height="match_parent" />
+                    </LinearLayout>
+
+                </LinearLayout>
+
+                <LinearLayout
+                    android:id="@+id/no_selected_member_layout"
+                    android:layout_width="match_parent"
+                    android:layout_height="match_parent"
+                    android:background="@drawable/card_white_bg"
+                    android:gravity="center"
+                    android:orientation="vertical">
+
+                    <ImageView
+                        android:layout_width="80dp"
+                        android:layout_height="80dp"
+                        android:src="@drawable/icon_add_box" />
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:paddingHorizontal="20dp"
+                        android:paddingVertical="10dp"
+                        android:text="@string/please_select_member"
+                        android:textColor="@color/black"
+                        android:textSize="24sp" />
+                </LinearLayout>
+            </FrameLayout>
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="right"
+            android:orientation="horizontal"
+            android:padding="10dp">
+
+            <TextView
+                android:id="@+id/confirm"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:background="@drawable/common_dialog_btn"
+                android:paddingHorizontal="20dp"
+                android:text="@string/confirm"
+                android:textColor="@color/black"
+                android:textSize="20sp" />
+
+            <TextView
+                android:id="@+id/cancel"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:background="@drawable/common_dialog_btn"
+                android:paddingHorizontal="20dp"
+                android:text="@string/cancel"
+                android:textColor="@color/black"
+                android:textSize="20sp" />
+        </LinearLayout>
+    </LinearLayout>
+</layout>

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

@@ -0,0 +1,220 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_margin="20dp"
+        android:background="@drawable/home_card_bg"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:id="@+id/title_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            android:paddingHorizontal="10dp"
+            android:paddingVertical="5dp">
+
+            <ImageView
+                android:id="@+id/preview_step_iv"
+                android:layout_width="20dp"
+                android:layout_height="20dp"
+                android:src="@mipmap/icon_data_manage_menu_user_manage" />
+
+            <TextView
+                android:id="@+id/preview_step_title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:text="@string/create_sop_title"
+                android:textColor="@color/black"
+                android:textSize="24sp" />
+
+            <ImageView
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:src="@drawable/icon_arrow_right" />
+
+            <ImageView
+                android:layout_width="20dp"
+                android:layout_height="20dp"
+                android:src="@mipmap/icon_data_manage_menu_role_manage" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:text="@string/select_member_title"
+                android:textColor="@color/black"
+                android:textSize="24sp" />
+
+            <View
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="1" />
+
+            <TextView
+                android:id="@+id/back"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:background="@drawable/common_dialog_btn"
+                android:paddingHorizontal="20dp"
+                android:text="@string/back"
+                android:textColor="@color/black"
+                android:textSize="20sp" />
+        </LinearLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="@color/black" />
+
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="20dp"
+            android:layout_marginTop="20dp"
+            android:background="@drawable/home_card_bg"
+            android:orientation="vertical">
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:background="@drawable/home_card_bg"
+                android:divider="@drawable/divider_table"
+                android:orientation="horizontal"
+                android:showDividers="middle">
+
+                <LinearLayout
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:gravity="center_horizontal"
+                    android:orientation="vertical">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:paddingHorizontal="20dp"
+                        android:paddingVertical="10dp"
+                        android:text="@string/locker"
+                        android:textColor="@color/black"
+                        android:textSize="24sp" />
+
+                    <TextView
+                        android:id="@+id/select_locker_tv"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginBottom="10dp"
+                        android:background="@drawable/bg_select_member_btn"
+                        android:paddingHorizontal="20dp"
+                        android:paddingVertical="5dp"
+                        android:text="@string/select"
+                        android:textColor="@color/white" />
+                </LinearLayout>
+
+                <androidx.recyclerview.widget.RecyclerView
+                    android:id="@+id/locker_rv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content" />
+            </LinearLayout>
+
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:background="@drawable/home_card_bg"
+                android:divider="@drawable/divider_table"
+                android:orientation="horizontal"
+                android:showDividers="middle">
+
+                <LinearLayout
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:gravity="center_horizontal"
+                    android:orientation="vertical">
+
+                    <TextView
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:gravity="center"
+                        android:paddingHorizontal="20dp"
+                        android:paddingVertical="10dp"
+                        android:text="@string/colocker"
+                        android:textColor="@color/black"
+                        android:textSize="24sp" />
+
+                    <TextView
+                        android:id="@+id/select_colocker_tv"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginBottom="10dp"
+                        android:background="@drawable/bg_select_member_btn"
+                        android:paddingHorizontal="20dp"
+                        android:paddingVertical="5dp"
+                        android:text="@string/select"
+                        android:textColor="@color/white" />
+                </LinearLayout>
+
+
+                <androidx.recyclerview.widget.RecyclerView
+                    android:id="@+id/colocker_rv"
+                    android:layout_width="wrap_content"
+                    android:layout_height="match_parent" />
+            </LinearLayout>
+        </LinearLayout>
+
+        <TextView
+            android:id="@+id/select_member_tip"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="20dp"
+            android:layout_marginTop="20dp"
+            android:text="@string/select_colocker_tip"
+            android:textColor="@color/black"
+            android:textSize="18sp" />
+
+        <androidx.recyclerview.widget.RecyclerView
+            android:id="@+id/all_user_rv"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_marginHorizontal="20dp"
+            android:layout_marginTop="10dp"
+            android:layout_weight="1"
+            android:background="@drawable/home_card_bg" />
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="right"
+            android:orientation="horizontal"
+            android:padding="10dp">
+
+            <TextView
+                android:id="@+id/confirm"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:background="@drawable/common_dialog_btn"
+                android:paddingHorizontal="20dp"
+                android:text="@string/confirm"
+                android:textColor="@color/black"
+                android:textSize="20sp" />
+
+            <TextView
+                android:id="@+id/cancel"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:background="@drawable/common_dialog_btn"
+                android:paddingHorizontal="20dp"
+                android:text="@string/cancel"
+                android:textColor="@color/black"
+                android:textSize="20sp" />
+        </LinearLayout>
+    </LinearLayout>
+</layout>

+ 169 - 0
app/src/main/res/layout/fragment_select_point.xml

@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_margin="20dp"
+        android:background="@drawable/home_card_bg"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:id="@+id/title_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            android:paddingHorizontal="10dp"
+            android:paddingVertical="5dp">
+
+            <ImageView
+                android:id="@+id/preview_step_iv"
+                android:layout_width="20dp"
+                android:layout_height="20dp"
+                android:src="@mipmap/icon_data_manage_menu_user_manage" />
+
+            <TextView
+                android:id="@+id/preview_step_title"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:text="@string/create_sop_title"
+                android:textColor="@color/black"
+                android:textSize="24sp" />
+
+            <ImageView
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:src="@drawable/icon_arrow_right" />
+
+            <ImageView
+                android:layout_width="20dp"
+                android:layout_height="20dp"
+                android:src="@mipmap/icon_data_manage_menu_point_manage" />
+
+            <TextView
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:text="@string/select_point_title"
+                android:textColor="@color/black"
+                android:textSize="24sp" />
+
+            <View
+                android:layout_width="0dp"
+                android:layout_height="match_parent"
+                android:layout_weight="1" />
+
+            <TextView
+                android:id="@+id/back"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:background="@drawable/common_dialog_btn"
+                android:paddingHorizontal="20dp"
+                android:text="@string/back"
+                android:textColor="@color/black"
+                android:textSize="20sp" />
+        </LinearLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="1dp"
+            android:background="@color/black" />
+
+        <LinearLayout
+            android:id="@+id/selected_point_info_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="20dp"
+            android:layout_marginVertical="10dp"
+            android:background="@drawable/home_card_bg"
+            android:gravity="center_vertical"
+            android:orientation="vertical">
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:layout_weight="1"
+                android:text="@string/selected_point_info_title"
+                android:textColor="@color/black"
+                android:textSize="24sp" />
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="1dp"
+                android:background="@color/black" />
+
+            <androidx.recyclerview.widget.RecyclerView
+                android:id="@+id/selected_point_rv"
+                android:layout_width="match_parent"
+                android:layout_height="260dp"
+                android:paddingBottom="10dp"/>
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/unselected_point_info_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginHorizontal="20dp"
+            android:layout_marginVertical="10dp"
+            android:background="@drawable/home_card_bg"
+            android:gravity="center_vertical"
+            android:orientation="vertical">
+
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:layout_weight="1"
+                android:text="@string/unselected_point_info_title"
+                android:textColor="@color/black"
+                android:textSize="24sp" />
+
+            <View
+                android:layout_width="match_parent"
+                android:layout_height="1dp"
+                android:background="@color/black" />
+
+            <androidx.recyclerview.widget.RecyclerView
+                android:id="@+id/unselected_point_rv"
+                android:layout_width="match_parent"
+                android:layout_height="450dp"
+                android:paddingBottom="10dp" />
+
+        </LinearLayout>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="right"
+            android:orientation="horizontal"
+            android:padding="10dp">
+
+            <TextView
+                android:id="@+id/confirm"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:background="@drawable/common_dialog_btn"
+                android:paddingHorizontal="20dp"
+                android:text="@string/confirm"
+                android:textColor="@color/black"
+                android:textSize="20sp" />
+
+            <TextView
+                android:id="@+id/cancel"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="10dp"
+                android:background="@drawable/common_dialog_btn"
+                android:paddingHorizontal="20dp"
+                android:text="@string/cancel"
+                android:textColor="@color/black"
+                android:textSize="20sp" />
+        </LinearLayout>
+    </LinearLayout>
+</layout>

+ 1 - 1
app/src/main/res/layout/item_home_text_drop_down.xml

@@ -8,5 +8,5 @@
         android:paddingHorizontal="8dp"
         android:paddingVertical="4dp"
         android:textColor="@color/black"
-        android:textSize="12sp" />
+        android:textSize="24sp" />
 </layout>

+ 25 - 0
app/src/main/res/layout/item_select_all_member.xml

@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        android:gravity="center"
+        android:orientation="vertical">
+
+        <ImageView
+            android:id="@+id/locker_icon"
+            android:layout_width="50dp"
+            android:layout_height="50dp"
+            android:src="@drawable/icon_select_member" />
+
+        <TextView
+            android:id="@+id/locker_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:textColor="@color/black"
+            android:textSize="20sp" />
+    </LinearLayout>
+</layout>

+ 26 - 0
app/src/main/res/layout/item_select_member.xml

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginLeft="10dp"
+        android:layout_marginTop="10dp"
+        android:gravity="center"
+        android:orientation="vertical">
+
+        <ImageView
+            android:id="@+id/locker_icon"
+            android:layout_width="50dp"
+            android:layout_height="50dp"
+            android:src="@drawable/icon_select_member" />
+
+        <TextView
+            android:id="@+id/locker_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:textColor="@color/black"
+            android:textSize="20sp" />
+    </LinearLayout>
+</layout>

+ 29 - 0
app/src/main/res/layout/item_select_point.xml

@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="10dp"
+        android:gravity="center"
+        android:orientation="vertical">
+
+        <ImageView
+            android:id="@+id/point_icon"
+            android:layout_width="50dp"
+            android:layout_height="50dp"
+            android:background="@drawable/bg_point_select"
+            android:padding="5dp"
+            android:src="@drawable/icon_select_member" />
+
+        <TextView
+            android:id="@+id/point_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center"
+            android:textColor="@color/black"
+            android:textSize="20sp"
+            tools:text="E-1" />
+    </LinearLayout>
+</layout>

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

@@ -7,13 +7,39 @@
     <fragment
         android:id="@+id/jobManageHomeFragment"
         android:name="com.grkj.iscs.features.main.fragment.job_manage.JobManageHomeFragment"
-        android:label="JobManageHomeFragment" >
+        android:label="JobManageHomeFragment">
         <action
             android:id="@+id/action_jobManageHomeFragment_to_createJobFragment"
             app:destination="@id/createJobFragment" />
+        <action
+            android:id="@+id/action_jobManageHomeFragment_to_createSopFragment"
+            app:destination="@id/createSopFragment" />
     </fragment>
     <fragment
         android:id="@+id/createJobFragment"
         android:name="com.grkj.iscs.features.main.fragment.job_manage.CreateJobFragment"
         android:label="CreateJobFragment" />
+    <fragment
+        android:id="@+id/createSopFragment"
+        android:name="com.grkj.iscs.features.main.fragment.job_manage.CreateSopFragment"
+        android:label="CreateSopFragment">
+        <action
+            android:id="@+id/action_createSopFragment_to_selectPointFragment"
+            app:destination="@id/selectPointFragment"
+            app:popUpToSaveState="true"
+            app:restoreState="true" />
+        <action
+            android:id="@+id/action_createSopFragment_to_selectMemberFragment"
+            app:destination="@id/selectMemberFragment"
+            app:popUpToSaveState="true"
+            app:restoreState="true" />
+    </fragment>
+    <fragment
+        android:id="@+id/selectMemberFragment"
+        android:name="com.grkj.iscs.features.main.fragment.common.SelectMemberFragment"
+        android:label="SelectMemberFragment" />
+    <fragment
+        android:id="@+id/selectPointFragment"
+        android:name="com.grkj.iscs.features.main.fragment.common.SelectPointFragment"
+        android:label="SelectPointFragment" />
 </navigation>

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

@@ -84,4 +84,29 @@
     <string name="add_point_failed">new point failed</string>
     <string name="add_workstation_succeed">new workstation succeed</string>
     <string name="add_workstation_failed">new workstation failed</string>
+    <string name="create_sop_title">Create SOP</string>
+    <string name="base_info_title">Base info</string>
+    <string name="create_sop_name">SOP name</string>
+    <string name="sop_workstation">SOP workstation</string>
+    <string name="point_info_title">Point info</string>
+    <string name="member_info_title">Member info</string>
+    <string name="please_select_sop_workstation">please select sop workstation</string>
+    <string name="please_select_lock_mode">please select lock mode</string>
+    <string name="please_input_sop_name">please input sop name</string>
+    <string name="please_select_member">please select member</string>
+    <string name="please_must_select_at_least_one_point">You need to add at least one point</string>
+    <string name="select_member_title">select member</string>
+    <string name="select_locker_tip">Please select locker from the following personnel</string>
+    <string name="select_colocker_tip">Please select colocker from the following personnel</string>
+    <string name="select_point_title">Select Point</string>
+    <string name="selected_point_info_title">selected point info</string>
+    <string name="unselected_point_info_title">select/cancel poing</string>
+    <string name="sop_create_succeed">SOP create succeed</string>
+    <string name="sop_create_failed">SOP create failed</string>
+    <string name="not_save_tip">Data not save,Do you want to lost save and leave?</string>
+    <string name="lock_mode_1"><![CDATA[lock->colock->unlock]]></string>
+    <string name="lock_mode_2"><![CDATA[lock->unlock]]></string>
+    <string name="lock_mode_3"><![CDATA[unlock->lock]]></string>
+    <string name="lock_mode_4">lock</string>
+    <string name="lock_mode_5">unlock</string>
 </resources>

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

@@ -84,4 +84,29 @@
     <string name="add_point_failed">新增隔离点失败</string>
     <string name="add_workstation_succeed">新增区域成功</string>
     <string name="add_workstation_failed">新增区域失败</string>
+    <string name="create_sop_title">新建SOP</string>
+    <string name="base_info_title">基本信息</string>
+    <string name="create_sop_name">SOP名称</string>
+    <string name="sop_workstation">SOP区域</string>
+    <string name="point_info_title">点位信息</string>
+    <string name="member_info_title">人员信息</string>
+    <string name="please_select_sop_workstation">请选择SOP区域</string>
+    <string name="please_select_lock_mode">请选择锁定模式</string>
+    <string name="please_input_sop_name">请输入SOP名称</string>
+    <string name="please_select_member">您可以选择添加人员</string>
+    <string name="please_must_select_at_least_one_point">您至少需要添加一个点位</string>
+    <string name="select_member_title">选择人员</string>
+    <string name="select_locker_tip">请在以下人员中选择上锁人</string>
+    <string name="select_colocker_tip">请在以下人员中选择共锁人</string>
+    <string name="select_point_title">选择点位</string>
+    <string name="selected_point_info_title">已选择的点位信息</string>
+    <string name="unselected_point_info_title">选择/取消点位</string>
+    <string name="sop_create_succeed">SOP创建成功</string>
+    <string name="sop_create_failed">SOP创建失败</string>
+    <string name="not_save_tip">数据还没有保存,您确定要放弃保存,离开当前页面吗?</string>
+    <string name="lock_mode_1"><![CDATA[上锁->共锁->解锁]]></string>
+    <string name="lock_mode_2"><![CDATA[上锁->解锁]]></string>
+    <string name="lock_mode_3"><![CDATA[解锁->上锁]]></string>
+    <string name="lock_mode_4">上锁</string>
+    <string name="lock_mode_5">解锁</string>
 </resources>

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

@@ -83,4 +83,29 @@
     <string name="add_point_failed">新增隔离点失败</string>
     <string name="add_workstation_succeed">新增区域成功</string>
     <string name="add_workstation_failed">新增区域失败</string>
+    <string name="create_sop_title">新建SOP</string>
+    <string name="base_info_title">基本信息</string>
+    <string name="create_sop_name">SOP名称</string>
+    <string name="sop_workstation">SOP区域</string>
+    <string name="point_info_title">点位信息</string>
+    <string name="member_info_title">人员信息</string>
+    <string name="please_select_sop_workstation">请选择SOP区域</string>
+    <string name="please_select_lock_mode">请选择锁定模式</string>
+    <string name="please_input_sop_name">请输入SOP名称</string>
+    <string name="please_select_member">您可以选择添加人员</string>
+    <string name="please_must_select_at_least_one_point">您至少需要添加一个点位</string>
+    <string name="select_member_title">选择人员</string>
+    <string name="select_locker_tip">请在以下人员中选择上锁人</string>
+    <string name="select_colocker_tip">请在以下人员中选择共锁人</string>
+    <string name="select_point_title">选择点位</string>
+    <string name="selected_point_info_title">已选择的点位信息</string>
+    <string name="unselected_point_info_title">选择/取消点位</string>
+    <string name="sop_create_succeed">SOP创建成功</string>
+    <string name="sop_create_failed">SOP创建失败</string>
+    <string name="not_save_tip">数据还没有保存,您确定要放弃保存,离开当前页面吗?</string>
+    <string name="lock_mode_1"><![CDATA[上锁->共锁->解锁]]></string>
+    <string name="lock_mode_2"><![CDATA[上锁->解锁]]></string>
+    <string name="lock_mode_3"><![CDATA[解锁->上锁]]></string>
+    <string name="lock_mode_4">上锁</string>
+    <string name="lock_mode_5">解锁</string>
 </resources>

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

@@ -0,0 +1,32 @@
+package com.grkj.data.dao
+
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import com.grkj.data.model.dos.IsSop
+import com.grkj.data.model.dos.IsSopPoints
+import com.grkj.data.model.dos.IsSopUser
+
+/**
+ * sop数据库操作
+ */
+@Dao
+interface IsSopDao {
+    /**
+     * 保存sop
+     */
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    fun saveSop(isSop: IsSop): Long
+
+    /**
+     * 保存sop点位
+     */
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    fun saveSopPoints(isSopPoints: List<IsSopPoints>)
+
+    /**
+     * 保存sop用户
+     */
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    fun saveSopUsers(isSopUsers: List<IsSopUser>)
+}

+ 19 - 0
data/src/main/java/com/grkj/data/dao/IsolationPointDao.kt

@@ -65,4 +65,23 @@ interface IsolationPointDao {
     @Query("delete from is_isolation_point where point_id in (:pointIds)")
     fun deletePointByPointIds(pointIds: List<Long>)
 
+    /**
+     * 获取所有隔离点数据
+     */
+    @Query(
+        """
+        select iip.point_id as pointId,
+        iip.point_name as pointName,
+        iip.remark as pointFunction,
+        iw.workstation_name as workstationName,
+        irt.rfid as rfidToken
+        from is_isolation_point iip
+        left join is_rfid_token irt on iip.rfid_id = irt.rfid_id
+        left join is_workstation iw on iip.workstation_id=iw.workstation_id
+        WHERE iip.del_flag = 0
+        AND iw.workstation_id = :workstationId
+    """
+    )
+    fun getAllPointManageDataWithWorkstationId(workstationId: Long): MutableList<PointManageVo>
+
 }

+ 38 - 1
data/src/main/java/com/grkj/data/dao/UserDao.kt

@@ -1,6 +1,5 @@
 package com.grkj.data.dao
 
-import android.health.connect.ReadRecordsRequestUsingIds
 import androidx.room.Dao
 import androidx.room.Insert
 import androidx.room.OnConflictStrategy
@@ -49,12 +48,14 @@ interface UserDao {
     SELECT
       su.user_id                         AS userId,
       su.nick_name                       AS nickName,
+      su.user_name                       AS userName,
 
       -- 聚合所有卡号(如果没卡则结果里 cardCodes 会是 NULL 或空)
       GROUP_CONCAT(DISTINCT ijc.card_code)       AS cardCodes,
 
       GROUP_CONCAT(DISTINCT sr.role_id)           AS roleIds,
       GROUP_CONCAT(DISTINCT sr.role_name)         AS roleNames,
+      GROUP_CONCAT(DISTINCT sr.role_key)          AS roleKeys,
       GROUP_CONCAT(DISTINCT iw.workstation_id)    AS workstationIds,
       GROUP_CONCAT(DISTINCT iw.workstation_name)  AS workstationNames,
 
@@ -108,4 +109,40 @@ interface UserDao {
      */
     @Query("delete from sys_user where user_id in (:userIds)")
     fun deleteUserByIds(userIds: List<Long>)
+
+    /**
+     * 获取所有用户数据
+     */
+    @Query(
+        """
+        SELECT
+          su.user_id                         AS userId,
+          su.nick_name                       AS nickName,
+          su.user_name                       AS userName,
+    
+          -- 聚合所有卡号(如果没卡则结果里 cardCodes 会是 NULL 或空)
+          GROUP_CONCAT(DISTINCT ijc.card_code)       AS cardCodes,
+    
+          GROUP_CONCAT(DISTINCT sr.role_id)           AS roleIds,
+          GROUP_CONCAT(DISTINCT sr.role_name)         AS roleNames,
+          GROUP_CONCAT(DISTINCT sr.role_key)          AS roleKeys,
+          GROUP_CONCAT(DISTINCT iw.workstation_id)    AS workstationIds,
+          GROUP_CONCAT(DISTINCT iw.workstation_name)  AS workstationNames,
+    
+          su.status                            AS status
+        FROM sys_user su
+        LEFT JOIN sys_user_role sur ON su.user_id = sur.user_id
+        LEFT JOIN sys_role sr       ON sur.role_id = sr.role_id
+        LEFT JOIN is_job_card ijc   ON ijc.user_id = su.user_id
+        LEFT JOIN is_user_workstation iuw ON iuw.user_id = su.user_id
+        LEFT JOIN is_workstation iw ON iw.workstation_id = iuw.workstation_id
+        WHERE su.del_flag = 0
+        AND iw.workstation_id = :workstationId
+        GROUP BY
+          su.user_id,
+          su.nick_name,
+          su.status
+    """
+    )
+    fun getAllUserDataWithWorkstationId(workstationId: Long): List<UserManageVo>
 }

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

@@ -5,6 +5,7 @@ import androidx.room.Database
 import androidx.room.Room
 import androidx.room.RoomDatabase
 import com.grkj.data.dao.HardwareDao
+import com.grkj.data.dao.IsSopDao
 import com.grkj.data.dao.IsolationPointDao
 import com.grkj.data.dao.RfidTokenDao
 import com.grkj.data.dao.RoleDao
@@ -13,6 +14,9 @@ import com.grkj.data.dao.WorkstationDao
 import com.grkj.data.model.dos.IsIsolationPoint
 import com.grkj.data.model.dos.IsJobCardDo
 import com.grkj.data.model.dos.IsRfidToken
+import com.grkj.data.model.dos.IsSop
+import com.grkj.data.model.dos.IsSopPoints
+import com.grkj.data.model.dos.IsSopUser
 import com.grkj.data.model.dos.IsUserWorkstation
 import com.grkj.data.model.dos.IsWorkstation
 import com.grkj.data.model.dos.SysRole
@@ -26,7 +30,8 @@ import com.sik.sikcore.SIKCore
  */
 @Database(
     entities = [IsJobCardDo::class, SysUserDo::class, SysUserCharacteristicDo::class,
-        SysRole::class, SysUserRole::class, IsUserWorkstation::class, IsWorkstation::class, IsIsolationPoint::class, IsRfidToken::class],
+        SysRole::class, SysUserRole::class, IsUserWorkstation::class, IsWorkstation::class, IsIsolationPoint::class, IsRfidToken::class,
+        IsSop::class, IsSopUser::class, IsSopPoints::class],
     version = ISCSMigrations.VERSION
 )
 abstract class ISCSDatabase : RoomDatabase() {
@@ -57,4 +62,6 @@ abstract class ISCSDatabase : RoomDatabase() {
     abstract fun isolationPointDao(): IsolationPointDao
 
     abstract fun rfidTokenDao(): RfidTokenDao
+
+    abstract fun isSopDao(): IsSopDao
 }

+ 51 - 0
data/src/main/java/com/grkj/data/model/dos/IsSop.kt

@@ -0,0 +1,51 @@
+package com.grkj.data.model.dos
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+/**
+ * SOP
+ */
+@Entity(tableName = "is_sop")
+class IsSop : BaseBean() {
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo("sop_id")
+    var sopId: Long = 0
+
+    @ColumnInfo("sop_code")
+    var sopCode: String? = null
+
+    @ColumnInfo("sop_name")
+    var sopName: String? = null
+
+    @ColumnInfo("sop_type")
+    var sopType: String? = null
+
+    @ColumnInfo("lock_mode")
+    var lockMode: String? = null
+
+    @ColumnInfo("workshop_id")
+    var workshopId: Long? = null
+
+    @ColumnInfo("workarea_id")
+    var workareaId: Long? = null
+
+    @ColumnInfo("workstation_id")
+    var workstationId: Long = 0
+
+    @ColumnInfo("machinery_id")
+    var machineryId: Long? = null
+
+    @ColumnInfo("sop_content")
+    var sopContent: String? = null
+
+    @ColumnInfo("sop_status")
+    var sopStatus: String? = null
+
+    @ColumnInfo("sop_index")
+    var sopIndex: Long? = null
+
+    @ColumnInfo("del_flag")
+    var delFlag: String? = "0"
+}

+ 33 - 0
data/src/main/java/com/grkj/data/model/dos/IsSopPoints.kt

@@ -0,0 +1,33 @@
+package com.grkj.data.model.dos
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+/**
+ * SOP点位
+ */
+@Entity(tableName = "is_sop_points")
+class IsSopPoints : BaseBean() {
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo("record_id")
+    var recordId: Long = 0
+
+    @ColumnInfo("sop_id")
+    var sopId: Long = 0
+
+    @ColumnInfo("workshop_id")
+    var workshopId: Long? = null
+
+    @ColumnInfo("workarea_id")
+    var workareaId: Long? = null
+
+    @ColumnInfo("point_id")
+    var pointId: Long? = null
+
+    @ColumnInfo("pre_point_id")
+    var prePointId: Long? = null
+
+    @ColumnInfo("del_flag")
+    var delFlag: String? = "0"
+}

+ 33 - 0
data/src/main/java/com/grkj/data/model/dos/IsSopUser.kt

@@ -0,0 +1,33 @@
+package com.grkj.data.model.dos
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+/**
+ * SOP用户
+ */
+@Entity(tableName = "is_sop_user")
+class IsSopUser : BaseBean() {
+    @PrimaryKey(autoGenerate = true)
+    @ColumnInfo("record_id")
+    var recordId: Long = 0
+
+    @ColumnInfo("sop_id")
+    var sopId: Long = 0
+
+    @ColumnInfo("user_id")
+    var userId: Long = 0
+
+    @ColumnInfo("user_name")
+    var userName: String? = null
+
+    @ColumnInfo("user_type")
+    var userType: String? = null
+
+    @ColumnInfo("user_role")
+    var userRole: String? = null
+
+    @ColumnInfo("del_flag")
+    var delFlag: String? = "0"
+}

+ 2 - 0
data/src/main/java/com/grkj/data/model/vo/UserManageVo.kt

@@ -8,9 +8,11 @@ import androidx.room.Ignore
 class UserManageVo {
     var userId: Long = 0
     var nickName: String = ""
+    var userName: String = ""
     var cardCodes: List<String?> = listOf()
     var roleIds: List<Long?> = listOf()
     var roleNames: List<String?> = listOf()
+    var roleKeys: List<String?> = listOf()
     var workstationIds: List<Long?> = listOf()
     var workstationNames: List<String?> = listOf()
     var status: String? = null

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

@@ -27,4 +27,9 @@ interface IIsolationPointRepository {
      */
     fun addIsolationPoint(addPointManageVo: AddPointManageVo, rfidId: Long)
 
+    /**
+     * 获取所有隔离点数据
+     */
+    fun getAllPointManageDataWithWorkstationId(workstationId: Long): MutableList<PointManageVo>
+
 }

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

@@ -0,0 +1,28 @@
+package com.grkj.data.repository
+
+import com.grkj.data.model.vo.PointManageVo
+import com.grkj.data.model.vo.UserManageVo
+
+/**
+ * sop仓储层
+ */
+interface ISopRepository {
+    /**
+     * 保存sop
+     */
+    fun saveSop(sopName: String, workstationId: Long, lockMode: String?): Long
+
+    /**
+     * 保存sop点位
+     */
+    fun saveSopPoint(selectedSopPint: List<PointManageVo>, sopId: Long)
+
+    /**
+     * 保存sop人员
+     */
+    fun saveSopUser(
+        selectedLockerData: List<UserManageVo>,
+        selectedColockerData: List<UserManageVo>,
+        sopId: Long
+    )
+}

+ 5 - 1
data/src/main/java/com/grkj/data/repository/IUserRepository.kt

@@ -1,6 +1,5 @@
 package com.grkj.data.repository
 
-import android.health.connect.ReadRecordsRequestUsingIds
 import com.grkj.data.model.vo.AddUserDataVo
 import com.grkj.data.model.vo.UserManageVo
 import com.grkj.data.model.vo.UserManageFilterVo
@@ -43,6 +42,11 @@ interface IUserRepository {
         size: Int
     ): List<UserManageVo>
 
+    /**
+     * 获取所有用户数据
+     */
+    fun getAllUserDataWithWorkstation(workstationId: Long): List<UserManageVo>
+
     /**
      * 添加用户
      */

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

@@ -47,6 +47,10 @@ class IsolationPointRepository : IIsolationPointRepository {
         isolationPointDao.addIsolationPoint(isIsolationPoint)
     }
 
+    override fun getAllPointManageDataWithWorkstationId(workstationId: Long): MutableList<PointManageVo> {
+        return isolationPointDao.getAllPointManageDataWithWorkstationId(workstationId)
+    }
+
     companion object {
         /**
          * 单例

+ 65 - 0
data/src/main/java/com/grkj/data/repository/impl/SopRepository.kt

@@ -0,0 +1,65 @@
+package com.grkj.data.repository.impl
+
+import com.grkj.data.dao.IsSopDao
+import com.grkj.data.database.ISCSDatabase
+import com.grkj.data.model.dos.IsSop
+import com.grkj.data.model.dos.IsSopPoints
+import com.grkj.data.model.dos.IsSopUser
+import com.grkj.data.model.vo.PointManageVo
+import com.grkj.data.model.vo.UserManageVo
+import com.grkj.data.repository.ISopRepository
+
+/**
+ * sop仓储实现
+ */
+class SopRepository : ISopRepository {
+    private val isSopDao: IsSopDao by lazy { ISCSDatabase.instance.isSopDao() }
+
+    override fun saveSop(
+        sopName: String,
+        workstationId: Long,
+        lockMode: String?
+    ): Long {
+        val isSop = IsSop()
+        isSop.sopName = sopName
+        isSop.workstationId = workstationId
+        isSop.lockMode = lockMode
+        return isSopDao.saveSop(isSop)
+    }
+
+    override fun saveSopPoint(selectedSopPint: List<PointManageVo>, sopId: Long) {
+        val isSopPoints = selectedSopPint.map {
+            val isSopPoint = IsSopPoints()
+            isSopPoint.sopId = sopId
+            isSopPoint.pointId = it.pointId
+            isSopPoint
+        }
+        isSopDao.saveSopPoints(isSopPoints)
+    }
+
+    override fun saveSopUser(
+        selectedLockerData: List<UserManageVo>,
+        selectedColockerData: List<UserManageVo>,
+        sopId: Long
+    ) {
+        val isSopUsers = (selectedLockerData + selectedColockerData).map {
+            val isSopUser = IsSopUser()
+            isSopUser.userId = it.userId
+            isSopUser.userName = it.userName
+            isSopUser.userRole = it.roleKeys.joinToString(",")
+            isSopUser.sopId = sopId
+            isSopUser
+        }
+        isSopDao.saveSopUsers(isSopUsers)
+    }
+
+    companion object {
+        /**
+         * 单例
+         */
+        @JvmStatic
+        val instance: SopRepository by lazy {
+            SopRepository()
+        }
+    }
+}

+ 4 - 1
data/src/main/java/com/grkj/data/repository/impl/UserRepository.kt

@@ -12,7 +12,6 @@ import com.grkj.data.repository.IUserRepository
 import com.grkj.shared.utils.BCryptUtils
 import com.grkj.shared.utils.BiometricVerifier
 import com.grkj.shared.utils.Pinyin4jUtil
-import org.slf4j.LoggerFactory
 
 /**
  * 用户仓储层
@@ -142,6 +141,10 @@ class UserRepository : IUserRepository {
         )
     }
 
+    override fun getAllUserDataWithWorkstation(workstationId: Long): List<UserManageVo> {
+        return userDao.getAllUserDataWithWorkstationId(workstationId)
+    }
+
     override fun addUserData(addUserDataVo: AddUserDataVo): Long {
         val sysUserDo = SysUserDo()
         sysUserDo.userName = Pinyin4jUtil.toInitials(addUserDataVo.nickname)

+ 8 - 3
ui-base/src/main/java/com/grkj/ui_base/base/BaseFragment.kt

@@ -19,12 +19,14 @@ import com.sik.sikandroid.permission.PermissionUtils
 import org.greenrobot.eventbus.EventBus
 import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
 
 /**
  * BaseFragment: 支持 ViewBinding, EventBus, 权限管理, 串口 & 蓝牙, 以及 Navigation 切换
  */
 abstract class BaseFragment<V : ViewDataBinding> : Fragment() {
-
+    protected val logger: Logger = LoggerFactory.getLogger(this::class.java)
     protected lateinit var binding: V
 
     protected val navController: NavController get() = findNavController()
@@ -34,8 +36,10 @@ abstract class BaseFragment<V : ViewDataBinding> : Fragment() {
         container: ViewGroup?,
         savedInstanceState: Bundle?
     ): View {
-        binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false)
-        binding.lifecycleOwner = viewLifecycleOwner
+        if (!::binding.isInitialized) {
+            binding = DataBindingUtil.inflate(inflater, getLayoutId(), container, false)
+            binding.lifecycleOwner = viewLifecycleOwner
+        }
         return binding.root
     }
 
@@ -73,6 +77,7 @@ abstract class BaseFragment<V : ViewDataBinding> : Fragment() {
         if (EventBus.getDefault().isRegistered(this)) {
             EventBus.getDefault().unregister(this)
         }
+        logger.info("销毁当前页")
         super.onDestroyView()
     }
 

+ 5 - 0
ui-base/src/main/java/com/grkj/ui_base/data/EventConstants.kt

@@ -20,6 +20,11 @@ object EventConstants {
      */
     const val EVENT_JUMP_TO: Int = 100_000_003
 
+    /**
+     * 显示隐藏底部栏
+     */
+    const val EVENT_BOTTOM_NAV_VISIBILITY: Int = 100_000_004
+
     //---------------------------作业票------------------------
     const val EVENT_GET_TICKET_STATUS: Int = 100_001_001
 

+ 24 - 0
ui-base/src/main/java/com/grkj/ui_base/utils/event/BottomNavVisibilityEvent.kt

@@ -0,0 +1,24 @@
+package com.grkj.ui_base.utils.event
+
+import com.grkj.shared.model.EventBean
+import com.grkj.ui_base.data.EventConstants
+
+/**
+ * 底部栏显隐
+ */
+class BottomNavVisibilityEvent(val show: Boolean = true) {
+
+    companion object {
+        /**
+         * 发送是否显示底部栏事件
+         */
+        @JvmStatic
+        fun sendBottomNavVisibilityEvent(show: Boolean = true) {
+            val bottomNavVisibilityEvent = BottomNavVisibilityEvent(show)
+            val bottomNavVisibilityEventBean = EventBean<BottomNavVisibilityEvent>(
+                EventConstants.EVENT_BOTTOM_NAV_VISIBILITY, bottomNavVisibilityEvent
+            )
+            EventHelper.sendEvent(bottomNavVisibilityEventBean)
+        }
+    }
+}

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

@@ -360,4 +360,5 @@
     <string name="lock_exception_tag">Lock is tag for exception</string>
     <string name="action_succeed">action succeed</string>
     <string name="action_failed">action failed</string>
+    <string name="select_coloker">select colocker</string>
 </resources>

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

@@ -360,4 +360,5 @@
     <string name="lock_exception_tag">该挂锁已被标记异常</string>
     <string name="action_succeed">操作成功</string>
     <string name="action_failed">操作失败</string>
+    <string name="select_coloker">请选择共锁人</string>
 </resources>

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

@@ -360,4 +360,5 @@
     <string name="lock_exception_tag">该挂锁已被标记异常</string>
     <string name="action_succeed">操作成功</string>
     <string name="action_failed">操作失败</string>
+    <string name="select_coloker">请选择共锁人</string>
 </resources>