Просмотр исходного кода

feat: Implement materials management and exchange functionalities

- Add MaterialsManageFragment for managing materials, including adding, updating, deleting, and filtering materials.
- Add MaterialsExchangeFragment and MaterialsExchangeWaitAndFinishFragment for handling material exchange process, including scanning, borrowing, and returning materials.
- Add corresponding ViewModels: MaterialsManageViewModel, MaterialExchangeViewModel, and MaterialsExchangeWaitAndFinishViewModel.
- Add dialogs for adding, updating, and filtering materials: AddMaterialsDialog, UpdateMaterialsDialog, and FilterMaterialsDialog.
- Add IsMaterialsEntity for representing materials.
- Update i18n resources with new keys for materials management and exchange.
- Update layouts for materials management and exchange screens.
- Update CanReadyPlugin to adjust scan range for CAN nodes.
- Add CabinetDoorClosedEvent to handle cabinet door closing event.
- Update IHardwareHelper and CanHardwareHelper to include connectAndAddListener method for hardware connection and event listening.
- Add DateTimePickUtils for selecting date and time.
- Update IMaterialsRepository, StandardMaterialsRepository, NetworkMaterialsRepository, and MaterialsDao to support new materials management operations.
- Update IMaterialsLogic and MaterialsLogic to include new business logic for materials management.
- Add JNI libraries and JAR file for ModuleAPI.
- Enable DEBUG mode in ISCSConfig.
- Update build.gradle.kts to include new dependencies.
周文健 2 месяцев назад
Родитель
Сommit
2b5276cd4c
38 измененных файлов с 2026 добавлено и 44 удалено
  1. 115 0
      app/src/main/assets/i18n/zh-CN.json
  2. 4 12
      app/src/main/java/com/grkj/iscs_mc/ISCSMCApplication.kt
  3. 105 0
      app/src/main/java/com/grkj/iscs_mc/features/main/dialog/material_manage/AddMaterialsDialog.kt
  4. 91 0
      app/src/main/java/com/grkj/iscs_mc/features/main/dialog/material_manage/FilterMaterialsDialog.kt
  5. 122 0
      app/src/main/java/com/grkj/iscs_mc/features/main/dialog/material_manage/UpdateMaterialsDialog.kt
  6. 9 0
      app/src/main/java/com/grkj/iscs_mc/features/main/entity/IsMaterialsEntity.kt
  7. 11 0
      app/src/main/java/com/grkj/iscs_mc/features/main/fragment/material_manage/MaterialsExchangeFragment.kt
  8. 126 0
      app/src/main/java/com/grkj/iscs_mc/features/main/fragment/material_manage/MaterialsExchangeWaitAndFinishFragment.kt
  9. 185 0
      app/src/main/java/com/grkj/iscs_mc/features/main/fragment/material_manage/MaterialsManageFragment.kt
  10. 4 0
      app/src/main/java/com/grkj/iscs_mc/features/main/fragment/material_manage/MaterialsTypeManageFragment.kt
  11. 12 0
      app/src/main/java/com/grkj/iscs_mc/features/main/viewmodel/material_manage/MaterialExchangeViewModel.kt
  12. 67 0
      app/src/main/java/com/grkj/iscs_mc/features/main/viewmodel/material_manage/MaterialsExchangeWaitAndFinishViewModel.kt
  13. 89 0
      app/src/main/java/com/grkj/iscs_mc/features/main/viewmodel/material_manage/MaterialsManageViewModel.kt
  14. 1 2
      app/src/main/java/com/grkj/iscs_mc/features/main/viewmodel/material_manage/MaterialsTypeManageViewModel.kt
  15. BIN
      app/src/main/jniLibs/arm64-v8a/libModuleAPIJni.so
  16. BIN
      app/src/main/jniLibs/armeabi-v7a/libModuleAPIJni.so
  17. BIN
      app/src/main/jniLibs/x86_64/libModuleAPIJni.so
  18. 255 0
      app/src/main/res/layout/dialog_filter_materials.xml
  19. 255 0
      app/src/main/res/layout/dialog_materials.xml
  20. 172 0
      app/src/main/res/layout/fragment_materials_exchange_wait_and_finish.xml
  21. 12 17
      app/src/main/res/layout/fragment_materials_manage.xml
  22. 46 0
      app/src/main/res/layout/item_materials_manage.xml
  23. 9 1
      app/src/main/res/navigation/nav_material_manage.xml
  24. 5 0
      data/src/main/java/com/grkj/data/common/EventConstants.kt
  25. 33 1
      data/src/main/java/com/grkj/data/domain/logic/IMaterialsLogic.kt
  26. 28 2
      data/src/main/java/com/grkj/data/domain/logic/impl/MaterialsLogic.kt
  27. 8 0
      data/src/main/java/com/grkj/data/hardware/IHardwareHelper.kt
  28. 20 0
      data/src/main/java/com/grkj/data/hardware/can/CanHardwareHelper.kt
  29. 5 2
      data/src/main/java/com/grkj/data/hardware/can/CanReadyPlugin.kt
  30. 61 2
      data/src/main/java/com/grkj/data/local/dao/MaterialsDao.kt
  31. 43 1
      data/src/main/java/com/grkj/data/repository/IMaterialsRepository.kt
  32. 35 1
      data/src/main/java/com/grkj/data/repository/impl/network/NetworkMaterialsRepository.kt
  33. 36 2
      data/src/main/java/com/grkj/data/repository/impl/standard/StandardMaterialsRepository.kt
  34. 25 0
      data/src/main/java/com/grkj/data/utils/event/CabinetDoorClosedEvent.kt
  35. BIN
      shared/libs/ModuleAPI_J.jar
  36. 2 0
      ui-base/build.gradle.kts
  37. 1 1
      ui-base/src/main/java/com/grkj/ui_base/config/ISCSConfig.kt
  38. 34 0
      ui-base/src/main/java/com/grkj/ui_base/utils/DateTimePickUtils.kt

+ 115 - 0
app/src/main/assets/i18n/zh-CN.json

@@ -449,6 +449,11 @@
     "type": "text",
     "value": "新增"
   },
+  "filter": {
+    "key": "filter",
+    "type": "text",
+    "value": "筛选"
+  },
   "invalid_card": {
     "key": "invalid_card",
     "type": "text",
@@ -1593,5 +1598,115 @@
     "key": "materials_manage_title",
     "type": "text",
     "value": "物资管理"
+  },
+  "add_materials_title": {
+    "key": "add_materials_title",
+    "type": "text",
+    "value": "新增物资"
+  },
+  "update_materials_title": {
+    "key": "update_materials_title",
+    "type": "text",
+    "value": "更新物资"
+  },
+  "materials_name": {
+    "key": "materials_name",
+    "type": "text",
+    "value": "物资名称"
+  },
+  "please_input_materials_name": {
+    "key": "please_input_materials_name",
+    "type": "text",
+    "value": "请输入物资名称"
+  },
+  "please_select_materials_type": {
+    "key": "please_select_materials_type",
+    "type": "text",
+    "value": "请选择物资类型"
+  },
+  "materials_type": {
+    "key": "materials_type",
+    "type": "text",
+    "value": "物资类型"
+  },
+  "rfid": {
+    "key": "rfid",
+    "type": "text",
+    "value": "RFID"
+  },
+  "please_input_materials_rfid": {
+    "key": "please_input_materials_rfid",
+    "type": "text",
+    "value": "请输入物资RFID"
+  },
+  "supplier": {
+    "key": "supplier",
+    "type": "text",
+    "value": "供应商"
+  },
+  "please_input_supplier": {
+    "key": "please_input_supplier",
+    "type": "text",
+    "value": "请输入供应商"
+  },
+  "expiration_date": {
+    "key": "expiration_date",
+    "type": "text",
+    "value": "有效期"
+  },
+  "please_select_expiration_date": {
+    "key": "please_select_expiration_date",
+    "type": "text",
+    "value": "请选择有效期"
+  },
+  "please_select_materials_type_first": {
+    "key": "please_select_materials_type_first",
+    "type": "text",
+    "value": "请先选择物资类型"
+  },
+  "please_select_materials_first": {
+    "key": "please_select_materials_first",
+    "type": "text",
+    "value": "请先选择物资"
+  },
+  "has_materials_in_use": {
+    "key": "has_materials_type_in_use",
+    "type": "text",
+    "value": "存在物资正在使用中,无法删除"
+  },
+  "material_exchange_finish_tip": {
+    "key": "material_exchange_finish_tip",
+    "type": "text",
+    "value": "请确认本次物资取还记录,确认后您的账号将⾃动退出。"
+  },
+  "material_exchange_record": {
+    "key": "material_exchange_record",
+    "type": "text",
+    "value": "物资取还记录"
+  },
+  "material_exchange_loading_tip": {
+    "key": "material_exchange_loading_tip",
+    "type": "text",
+    "value": "正在进⾏物资盘点,请稍后。"
+  },
+  "material_exchange_scan_tip": {
+    "key": "material_exchange_scan_tip",
+    "type": "text",
+    "value": "请等待物资盘点结束后,确认物资领取和归还的记录。"
+  },
+  "material_exchange_loading_count_down": {
+    "key": "material_exchange_loading_tip",
+    "type": "text",
+    "value": "预计还有{0}秒钟。"
+  },
+  "materials_exchange_borrow_tip": {
+    "key": "materials_exchange_borrow_tip",
+    "type": "text",
+    "value": "您于{0}领取了以下{1}件物资:"
+  },
+  "materials_exchange_return_tip": {
+    "key": "materials_exchange_return_tip",
+    "type": "text",
+    "value": "您于{0}归还了以下{1}件物资:"
   }
 }

+ 4 - 12
app/src/main/java/com/grkj/iscs_mc/ISCSMCApplication.kt

@@ -13,9 +13,7 @@ import coil.memory.MemoryCache
 import com.drake.statelayout.StateConfig
 import com.grkj.data.common.EventConstants
 import com.grkj.data.di.LogicManager
-import com.grkj.data.hardware.can.CanHelper
-import com.grkj.data.hardware.can.CanReadyPlugin
-import com.grkj.data.hardware.can.CustomCanConfig
+import com.grkj.data.enums.HardwareMode
 import com.grkj.data.local.database.DbReadyGate
 import com.grkj.iscs_mc.features.splash.activity.SplashActivity
 import com.grkj.shared.model.EventBean
@@ -31,10 +29,6 @@ import com.kongzue.dialogx.DialogX
 import com.scwang.smart.refresh.footer.ClassicsFooter
 import com.scwang.smart.refresh.header.ClassicsHeader
 import com.scwang.smart.refresh.layout.SmartRefreshLayout
-import com.sik.comm.core.protocol.ProtocolManager
-import com.sik.comm.core.protocol.ProtocolType
-import com.sik.comm.impl_can.CanConfig
-import com.sik.comm.impl_can.CanProtocol
 import com.sik.sikcore.SIKCore
 import com.sik.sikcore.crash.GlobalCrashCatch
 import com.sik.sikcore.log.LogUtils
@@ -47,6 +41,7 @@ import org.greenrobot.eventbus.Subscribe
 import org.greenrobot.eventbus.ThreadMode
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
+import java.lang.ref.WeakReference
 
 /**
  * 启动入口
@@ -109,14 +104,11 @@ class ISCSMCApplication : Application() {
             // 5) 数据库/业务/硬件连接(你原来就放 IO,很好)
             DbReadyGate.await()
             LogicManager.init(this@ISCSMCApplication)
-            CanHelper.connect()
-            CanHelper.addDeviceChangeListener(this@ISCSMCApplication) {
-                logger.info("有设备更新: $it")
-            }
+            HardwareMode.getCurrentHardwareMode().connectAndAddListener(WeakReference(this@ISCSMCApplication))
         }
     }
 
-    private fun initImageLoader(){
+    private fun initImageLoader() {
         val loader = ImageLoader.Builder(this)
             .components { add(SvgDecoder.Factory()) }  // 支持 SVG
             .memoryCache {

+ 105 - 0
app/src/main/java/com/grkj/iscs_mc/features/main/dialog/material_manage/AddMaterialsDialog.kt

@@ -0,0 +1,105 @@
+package com.grkj.iscs_mc.features.main.dialog.material_manage
+
+import android.view.View
+import coil.load
+import com.grkj.data.utils.event.ToastEvent
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.DialogMaterialsBinding
+import com.grkj.iscs_mc.features.main.dialog.TextDropDownDialog
+import com.grkj.iscs_mc.features.main.entity.IsMaterialsEntity
+import com.grkj.iscs_mc.features.main.entity.IsMaterialsTypeEntity
+import com.grkj.ui_base.utils.CommonUtils
+import com.grkj.ui_base.utils.DateTimePickUtils
+import com.grkj.ui_base.utils.extension.clearSrcTint
+import com.grkj.ui_base.utils.extension.setSrcTint
+import com.kongzue.dialogx.dialogs.CustomDialog
+import com.kongzue.dialogx.interfaces.OnBindView
+import com.sik.sikcore.extension.setDebouncedClickListener
+
+/**
+ * 添加物资
+ */
+class AddMaterialsDialog(
+    val isMaterialsTypes: List<IsMaterialsTypeEntity>,
+    val onConfirm: (CustomDialog, IsMaterialsEntity) -> Unit
+) :
+    OnBindView<CustomDialog>(R.layout.dialog_materials) {
+    private val isMaterials: IsMaterialsEntity = IsMaterialsEntity()
+    private lateinit var binding: DialogMaterialsBinding
+    override fun onBind(dialog: CustomDialog, contentView: View) {
+        binding = DialogMaterialsBinding.bind(contentView)
+        dialog.isCancelable = false
+        dialog.setMaskColor(CommonUtils.getColor(com.grkj.ui_base.R.attr.scrim))
+        binding.title.text = CommonUtils.getStr("add_materials_title")
+        binding.cancel.setDebouncedClickListener { dialog.dismiss() }
+        binding.closeIv.setDebouncedClickListener { dialog.dismiss() }
+        binding.materialsType.setDebouncedClickListener {
+            TextDropDownDialog.showSingle(isMaterialsTypes.map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataId = it.materialsTypeId,
+                    dataText = it.materialsTypeName
+                )
+            }, binding.materialsType) {
+                binding.materialsType.text = it.getShowText()
+                isMaterials.materialsTypeId = it.getId()
+                val materialsTypePicture =
+                    isMaterialsTypes.find { it.materialsTypeId == isMaterials.materialsTypeId }?.materialsTypePicture
+                materialsTypePicture?.let {
+                    if (it.endsWith("png") || it.endsWith("jpg") || it.endsWith("jpeg") || it.endsWith(
+                            "webp"
+                        )
+                    ) {
+                        binding.materialsTypePicture.clearSrcTint()
+                    } else {
+                        binding.materialsTypePicture.setSrcTint(CommonUtils.getColor(com.grkj.ui_base.R.attr.colorPrimary))
+                    }
+                    binding.materialsTypePicture.load(it)
+                }
+            }
+        }
+        binding.expirationDate.setDebouncedClickListener {
+            DateTimePickUtils.pickDate(
+                CommonUtils.getStr("expiration_date"),
+                binding.expirationDate
+            )
+        }
+        binding.confirm.setDebouncedClickListener {
+            if (checkData()) {
+                isMaterials.materialsName = binding.materialsNameEt.text.toString()
+                isMaterials.supplier = binding.supplierEt.text.toString()
+                isMaterials.expirationDate = binding.expirationDate.text.toString()
+                isMaterials.materialsRfid = binding.materialsRfidEt.text.toString()
+                onConfirm(dialog, isMaterials)
+            }
+        }
+    }
+
+    private fun checkData(): Boolean {
+        if (binding.materialsNameEt.text.toString().isEmpty()) {
+            ToastEvent.sendToastEvent(CommonUtils.getStr("please_input_materials_name"))
+            return false
+        }
+        if (binding.materialsType.text.isEmpty()) {
+            ToastEvent.sendToastEvent(CommonUtils.getStr("please_select_materials_type"))
+            return false
+        }
+        return true
+    }
+
+
+    companion object {
+        /**
+         * 显示对话框并设置确认回调
+         */
+        @JvmStatic
+        fun show(
+            isMaterialsTypes: List<IsMaterialsTypeEntity>,
+            onConfirm: (CustomDialog, IsMaterialsEntity) -> Unit
+        ) {
+            CustomDialog.show(
+                AddMaterialsDialog(isMaterialsTypes, onConfirm),
+                CustomDialog.ALIGN.CENTER
+            )
+        }
+    }
+}

+ 91 - 0
app/src/main/java/com/grkj/iscs_mc/features/main/dialog/material_manage/FilterMaterialsDialog.kt

@@ -0,0 +1,91 @@
+package com.grkj.iscs_mc.features.main.dialog.material_manage
+
+import android.view.View
+import coil.load
+import com.grkj.data.utils.event.ToastEvent
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.DialogFilterMaterialsBinding
+import com.grkj.iscs_mc.databinding.DialogMaterialsBinding
+import com.grkj.iscs_mc.features.main.dialog.TextDropDownDialog
+import com.grkj.iscs_mc.features.main.entity.IsMaterialsEntity
+import com.grkj.iscs_mc.features.main.entity.IsMaterialsTypeEntity
+import com.grkj.ui_base.utils.CommonUtils
+import com.grkj.ui_base.utils.DateTimePickUtils
+import com.grkj.ui_base.utils.extension.clearSrcTint
+import com.grkj.ui_base.utils.extension.setSrcTint
+import com.kongzue.dialogx.dialogs.CustomDialog
+import com.kongzue.dialogx.interfaces.OnBindView
+import com.sik.sikcore.extension.setDebouncedClickListener
+
+/**
+ * 筛选物资
+ */
+class FilterMaterialsDialog(
+    val isMaterialsTypes: List<IsMaterialsTypeEntity>,
+    val onConfirm: (CustomDialog, IsMaterialsEntity) -> Unit
+) :
+    OnBindView<CustomDialog>(R.layout.dialog_filter_materials) {
+    private val isMaterials: IsMaterialsEntity = IsMaterialsEntity()
+    private lateinit var binding: DialogFilterMaterialsBinding
+    override fun onBind(dialog: CustomDialog, contentView: View) {
+        binding = DialogFilterMaterialsBinding.bind(contentView)
+        dialog.isCancelable = false
+        dialog.setMaskColor(CommonUtils.getColor(com.grkj.ui_base.R.attr.scrim))
+        binding.title.text = CommonUtils.getStr("add_materials_title")
+        binding.cancel.setDebouncedClickListener { dialog.dismiss() }
+        binding.closeIv.setDebouncedClickListener { dialog.dismiss() }
+        binding.materialsType.setDebouncedClickListener {
+            TextDropDownDialog.showSingle(isMaterialsTypes.map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataId = it.materialsTypeId,
+                    dataText = it.materialsTypeName
+                )
+            }, binding.materialsType) {
+                binding.materialsType.text = it.getShowText()
+                isMaterials.materialsTypeId = it.getId()
+                val materialsTypePicture =
+                    isMaterialsTypes.find { it.materialsTypeId == isMaterials.materialsTypeId }?.materialsTypePicture
+                materialsTypePicture?.let {
+                    if (it.endsWith("png") || it.endsWith("jpg") || it.endsWith("jpeg") || it.endsWith(
+                            "webp"
+                        )
+                    ) {
+                        binding.materialsTypePicture.clearSrcTint()
+                    } else {
+                        binding.materialsTypePicture.setSrcTint(CommonUtils.getColor(com.grkj.ui_base.R.attr.colorPrimary))
+                    }
+                    binding.materialsTypePicture.load(it)
+                }
+            }
+        }
+        binding.expirationDate.setDebouncedClickListener {
+            DateTimePickUtils.pickDate(
+                CommonUtils.getStr("expiration_date"),
+                binding.expirationDate
+            )
+        }
+        binding.confirm.setDebouncedClickListener {
+            isMaterials.materialsName = binding.materialsNameEt.text.toString()
+            isMaterials.supplier = binding.supplierEt.text.toString()
+            isMaterials.expirationDate = binding.expirationDate.text.toString()
+            isMaterials.materialsRfid = binding.materialsRfidEt.text.toString()
+            onConfirm(dialog, isMaterials)
+        }
+    }
+
+    companion object {
+        /**
+         * 显示对话框并设置确认回调
+         */
+        @JvmStatic
+        fun show(
+            isMaterialsTypes: List<IsMaterialsTypeEntity>,
+            onConfirm: (CustomDialog, IsMaterialsEntity) -> Unit
+        ) {
+            CustomDialog.show(
+                FilterMaterialsDialog(isMaterialsTypes, onConfirm),
+                CustomDialog.ALIGN.CENTER
+            )
+        }
+    }
+}

+ 122 - 0
app/src/main/java/com/grkj/iscs_mc/features/main/dialog/material_manage/UpdateMaterialsDialog.kt

@@ -0,0 +1,122 @@
+package com.grkj.iscs_mc.features.main.dialog.material_manage
+
+import android.view.View
+import coil.load
+import com.grkj.data.utils.event.ToastEvent
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.DialogMaterialsBinding
+import com.grkj.iscs_mc.features.main.dialog.TextDropDownDialog
+import com.grkj.iscs_mc.features.main.entity.IsMaterialsEntity
+import com.grkj.iscs_mc.features.main.entity.IsMaterialsTypeEntity
+import com.grkj.ui_base.utils.CommonUtils
+import com.grkj.ui_base.utils.DateTimePickUtils
+import com.grkj.ui_base.utils.extension.clearSrcTint
+import com.grkj.ui_base.utils.extension.setSrcTint
+import com.kongzue.dialogx.dialogs.CustomDialog
+import com.kongzue.dialogx.interfaces.OnBindView
+import com.sik.sikcore.extension.setDebouncedClickListener
+
+/**
+ * 修改物资
+ */
+class UpdateMaterialsDialog(
+    val isMaterialsEntity: IsMaterialsEntity,
+    val isMaterialsTypes: List<IsMaterialsTypeEntity>,
+    val onConfirm: (CustomDialog, IsMaterialsEntity) -> Unit
+) : OnBindView<CustomDialog>(R.layout.dialog_materials) {
+    private lateinit var binding: DialogMaterialsBinding
+    override fun onBind(dialog: CustomDialog, contentView: View) {
+        binding = DialogMaterialsBinding.bind(contentView)
+        dialog.isCancelable = false
+        dialog.setMaskColor(CommonUtils.getColor(com.grkj.ui_base.R.attr.scrim))
+        binding.title.text = CommonUtils.getStr("update_materials_title")
+        binding.cancel.setDebouncedClickListener { dialog.dismiss() }
+        binding.closeIv.setDebouncedClickListener { dialog.dismiss() }
+        binding.materialsType.setDebouncedClickListener {
+            TextDropDownDialog.showSingle(isMaterialsTypes.map {
+                TextDropDownDialog.SimpleTextDropDownEntity(
+                    dataId = it.materialsTypeId, dataText = it.materialsTypeName
+                )
+            }, binding.materialsType) {
+                binding.materialsType.text = it.getShowText()
+                isMaterialsEntity.materialsTypeId = it.getId()
+                val materialsTypePicture =
+                    isMaterialsTypes.find { it.materialsTypeId == isMaterialsEntity.materialsTypeId }?.materialsTypePicture
+                materialsTypePicture?.let {
+                    if (it.endsWith("png") || it.endsWith("jpg") || it.endsWith("jpeg") || it.endsWith(
+                            "webp"
+                        )
+                    ) {
+                        binding.materialsTypePicture.clearSrcTint()
+                    } else {
+                        binding.materialsTypePicture.setSrcTint(CommonUtils.getColor(com.grkj.ui_base.R.attr.colorPrimary))
+                    }
+                    binding.materialsTypePicture.load(it)
+                }
+            }
+        }
+        binding.expirationDate.setDebouncedClickListener {
+            DateTimePickUtils.pickDate(
+                CommonUtils.getStr("expiration_date"), binding.expirationDate
+            )
+        }
+        binding.materialsNameEt.setText(isMaterialsEntity.materialsName)
+        binding.materialsRfidEt.setText(isMaterialsEntity.materialsRfid)
+        binding.supplierEt.setText(isMaterialsEntity.supplier)
+        binding.materialsType.text =
+            isMaterialsTypes.find { it.materialsTypeId == isMaterialsEntity.materialsTypeId }?.materialsTypeName
+        val materialsTypePicture =
+            isMaterialsTypes.find { it.materialsTypeId == isMaterialsEntity.materialsTypeId }?.materialsTypePicture
+        materialsTypePicture?.let {
+            if (it.endsWith("png") || it.endsWith("jpg") || it.endsWith("jpeg") || it.endsWith(
+                    "webp"
+                )
+            ) {
+                binding.materialsTypePicture.clearSrcTint()
+            } else {
+                binding.materialsTypePicture.setSrcTint(CommonUtils.getColor(com.grkj.ui_base.R.attr.colorPrimary))
+            }
+            binding.materialsTypePicture.load(it)
+        }
+        binding.expirationDate.text = isMaterialsEntity.expirationDate
+        binding.confirm.setDebouncedClickListener {
+            if (checkData()) {
+                isMaterialsEntity.materialsName = binding.materialsNameEt.text.toString()
+                isMaterialsEntity.supplier = binding.supplierEt.text.toString()
+                isMaterialsEntity.expirationDate = binding.expirationDate.text.toString()
+                isMaterialsEntity.materialsRfid = binding.materialsRfidEt.text.toString()
+                onConfirm(dialog, isMaterialsEntity)
+            }
+        }
+    }
+
+    private fun checkData(): Boolean {
+        if (binding.materialsNameEt.text.toString().isEmpty()) {
+            ToastEvent.sendToastEvent(CommonUtils.getStr("please_input_materials_name"))
+            return false
+        }
+        if (binding.materialsType.text.isEmpty()) {
+            ToastEvent.sendToastEvent(CommonUtils.getStr("please_select_materials_type"))
+            return false
+        }
+        return true
+    }
+
+
+    companion object {
+        /**
+         * 显示对话框并设置确认回调
+         */
+        @JvmStatic
+        fun show(
+            isMaterialsEntity: IsMaterialsEntity,
+            isMaterialsTypes: List<IsMaterialsTypeEntity>,
+            onConfirm: (CustomDialog, IsMaterialsEntity) -> Unit
+        ) {
+            CustomDialog.show(
+                UpdateMaterialsDialog(isMaterialsEntity, isMaterialsTypes, onConfirm),
+                CustomDialog.ALIGN.CENTER
+            )
+        }
+    }
+}

+ 9 - 0
app/src/main/java/com/grkj/iscs_mc/features/main/entity/IsMaterialsEntity.kt

@@ -0,0 +1,9 @@
+package com.grkj.iscs_mc.features.main.entity
+
+import com.grkj.data.local.dos.IsMaterials
+
+/**
+ * 物资实体
+ */
+class IsMaterialsEntity: IsMaterials() {
+}

+ 11 - 0
app/src/main/java/com/grkj/iscs_mc/features/main/fragment/material_manage/MaterialsExchangeFragment.kt

@@ -17,6 +17,7 @@ import com.google.android.flexbox.FlexWrap
 import com.google.android.flexbox.FlexboxItemDecoration
 import com.google.android.flexbox.FlexboxLayoutManager
 import com.google.android.flexbox.JustifyContent
+import com.grkj.data.common.EventConstants
 import com.grkj.data.local.dos.IsMaterials
 import com.grkj.iscs_mc.R
 import com.grkj.iscs_mc.databinding.FragmentMaterialExchangeBinding
@@ -24,6 +25,7 @@ import com.grkj.iscs_mc.databinding.ItemMaterialExchangeHeaderBinding
 import com.grkj.iscs_mc.databinding.ItemMaterialsBinding
 import com.grkj.iscs_mc.features.main.entity.MaterialExchangeHeaderEntity
 import com.grkj.iscs_mc.features.main.viewmodel.material_manage.MaterialExchangeViewModel
+import com.grkj.shared.model.EventBean
 import com.grkj.ui_base.base.BaseFragment
 import com.grkj.ui_base.skin.loadSkinIcon
 import com.grkj.ui_base.utils.CommonUtils
@@ -99,6 +101,15 @@ class MaterialsExchangeFragment : BaseFragment<FragmentMaterialExchangeBinding>(
         changeTab(currentTabPosition, false)
     }
 
+    override fun onEvent(event: EventBean<Any>) {
+        super.onEvent(event)
+        when (event.code) {
+            EventConstants.EVENT_CABINET_DOOR_CLOSED -> {
+                navController.navigate(R.id.action_materialExchangeFragment_to_materialsExchangeWaitAndFinishFragment)
+            }
+        }
+    }
+
     private fun BindingAdapter.BindingViewHolder.onMaterialsRVListBinding() {
         val item = getModel<IsMaterials>()
         val itemBinding = getBinding<ItemMaterialsBinding>()

+ 126 - 0
app/src/main/java/com/grkj/iscs_mc/features/main/fragment/material_manage/MaterialsExchangeWaitAndFinishFragment.kt

@@ -0,0 +1,126 @@
+package com.grkj.iscs_mc.features.main.fragment.material_manage
+
+import android.widget.LinearLayout
+import androidx.core.view.isVisible
+import androidx.fragment.app.viewModels
+import coil.load
+import com.drake.brv.BindingAdapter
+import com.drake.brv.utils.linear
+import com.drake.brv.utils.models
+import com.drake.brv.utils.setup
+import com.google.android.flexbox.FlexboxLayoutManager
+import com.grkj.data.local.dos.IsMaterials
+import com.grkj.iscs_mc.R
+import com.grkj.iscs_mc.databinding.FragmentMaterialsExchangeWaitAndFinishBinding
+import com.grkj.iscs_mc.databinding.ItemMaterialsBinding
+import com.grkj.iscs_mc.features.main.viewmodel.material_manage.MaterialsExchangeWaitAndFinishViewModel
+import com.grkj.shared.utils.CountdownTimer
+import com.grkj.ui_base.base.BaseFragment
+import com.grkj.ui_base.utils.CommonUtils
+import com.grkj.ui_base.utils.event.BottomTipEvent
+import com.grkj.ui_base.utils.event.LogoutEvent
+import com.sik.sikcore.date.TimeUtils
+import com.sik.sikcore.extension.setDebouncedClickListener
+import dagger.hilt.android.AndroidEntryPoint
+
+/**
+ * 扫描和结束界面
+ */
+@AndroidEntryPoint
+class MaterialsExchangeWaitAndFinishFragment :
+    BaseFragment<FragmentMaterialsExchangeWaitAndFinishBinding>() {
+    private val viewModel: MaterialsExchangeWaitAndFinishViewModel by viewModels()
+    override fun getLayoutId(): Int {
+        return R.layout.fragment_materials_exchange_wait_and_finish
+    }
+
+    override fun initView() {
+        viewModel.getMaterialsData().observe(this) {
+            viewModel.scanMaterialsExchange().observe(this) {
+                binding.borrowMaterialsLayout.isVisible = viewModel.borrowMaterials.isNotEmpty()
+                binding.borrowTip.text = CommonUtils.getStr(
+                    "materials_exchange_borrow_tip",
+                    TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT),
+                    viewModel.borrowMaterials.size
+                )
+                binding.returnMaterialsLayout.isVisible = viewModel.returnMaterials.isNotEmpty()
+                binding.returnTip.text = CommonUtils.getStr(
+                    "materials_exchange_return_tip",
+                    TimeUtils.nowString(TimeUtils.DEFAULT_DATE_HOUR_MIN_SEC_FORMAT),
+                    viewModel.returnMaterials.size
+                )
+                binding.borrowMaterialsRv.models = viewModel.borrowMaterials
+                binding.returnMaterialsRv.models = viewModel.returnMaterials
+            }
+            materialsScanCountDown()
+        }
+        binding.borrowMaterialsRv.apply {
+            if (this@MaterialsExchangeWaitAndFinishFragment.isPortrait()) {
+                linear(LinearLayout.HORIZONTAL)
+            } else {
+                layoutManager = FlexboxLayoutManager(requireContext())
+            }
+        }.setup {
+            addType<IsMaterials>(R.layout.item_materials)
+            onBind {
+                onMaterialsRVListBinding()
+            }
+        }
+        binding.returnMaterialsRv.apply {
+            if (this@MaterialsExchangeWaitAndFinishFragment.isPortrait()) {
+                linear(LinearLayout.HORIZONTAL)
+            } else {
+                layoutManager = FlexboxLayoutManager(requireContext())
+            }
+        }.setup {
+            addType<IsMaterials>(R.layout.item_materials)
+            onBind {
+                onMaterialsRVListBinding()
+            }
+        }
+        BottomTipEvent.sendBottomTipEvent(CommonUtils.getStr("material_exchange_scan_tip"))
+        binding.confirm.setDebouncedClickListener {
+            LogoutEvent.sendLogoutEvent()
+        }
+    }
+
+    private fun BindingAdapter.BindingViewHolder.onMaterialsRVListBinding() {
+        val item = getModel<IsMaterials>()
+        val itemBinding = getBinding<ItemMaterialsBinding>()
+        itemBinding.materialsPicture.load(viewModel.materialsType.find { it.materialsTypeId == item.materialsTypeId }?.materialsTypePicture)
+        itemBinding.materialsName.text = item.materialsName
+        itemBinding.materialsRfid.text = item.materialsRfid
+    }
+
+    /**
+     * 物资盘点倒计时
+     */
+    private fun materialsScanCountDown() {
+        CountdownTimer.start(10_000L, onTick = {
+            binding.timeCountDownTv.text =
+                CommonUtils.getStr("material_exchange_loading_count_down", 10 - it / 1000)
+        }, onFinish = {
+            scanFinishAndShowMaterialsExchangeRecord()
+        })
+    }
+
+    /**
+     * 盘点结束,展示结果
+     */
+    private fun scanFinishAndShowMaterialsExchangeRecord() {
+        binding.loadingLayout.isVisible = false
+        startFinish()
+        BottomTipEvent.sendBottomTipEvent(CommonUtils.getStr("material_exchange_finish_tip"))
+    }
+
+    /**
+     * 开始结束计时
+     */
+    private fun startFinish() {
+        CountdownTimer.start(14_000L, onTick = {
+            binding.confirm.text = "${CommonUtils.getStr("confirm")}(${14 - it / 1000})"
+        }, onFinish = {
+            LogoutEvent.sendLogoutEvent()
+        })
+    }
+}

+ 185 - 0
app/src/main/java/com/grkj/iscs_mc/features/main/fragment/material_manage/MaterialsManageFragment.kt

@@ -1,8 +1,23 @@
 package com.grkj.iscs_mc.features.main.fragment.material_manage
 
+import androidx.fragment.app.viewModels
+import com.drake.brv.BindingAdapter
+import com.drake.brv.utils.models
+import com.drake.brv.utils.setup
+import com.google.android.flexbox.FlexboxLayoutManager
 import com.grkj.iscs_mc.R
 import com.grkj.iscs_mc.databinding.FragmentMaterialsManageBinding
+import com.grkj.iscs_mc.databinding.ItemMaterialsManageBinding
+import com.grkj.iscs_mc.features.main.dialog.material_manage.AddMaterialsDialog
+import com.grkj.iscs_mc.features.main.dialog.material_manage.FilterMaterialsDialog
+import com.grkj.iscs_mc.features.main.dialog.material_manage.UpdateMaterialsDialog
+import com.grkj.iscs_mc.features.main.entity.IsMaterialsEntity
+import com.grkj.iscs_mc.features.main.viewmodel.material_manage.MaterialsManageViewModel
 import com.grkj.ui_base.base.BaseFragment
+import com.grkj.ui_base.dialog.TipDialog
+import com.grkj.ui_base.utils.CommonUtils
+import com.sik.sikcore.extension.isNullOrEmpty
+import com.sik.sikcore.extension.setDebouncedClickListener
 import dagger.hilt.android.AndroidEntryPoint
 
 /**
@@ -10,11 +25,181 @@ import dagger.hilt.android.AndroidEntryPoint
  */
 @AndroidEntryPoint
 class MaterialsManageFragment : BaseFragment<FragmentMaterialsManageBinding>() {
+    private val viewModel: MaterialsManageViewModel by viewModels()
     override fun getLayoutId(): Int {
         return R.layout.fragment_materials_manage
     }
 
     override fun initView() {
+        binding.back.setDebouncedClickListener { navController.popBackStack() }
+        binding.add.setDebouncedClickListener {
+            AddMaterialsDialog.show(viewModel.materialsTypeData) { dialog, entity ->
+                viewModel.addMaterials(entity).observe(this) {
+                    dialog.dismiss()
+                    if (it) {
+                        TipDialog.showSuccess(
+                            CommonUtils.getStr("save_success"),
+                            onConfirmClick = {
+                                getMaterialsData()
+                            },
+                            onCancelClick = {
+                                getMaterialsData()
+                            })
+                    } else {
+                        TipDialog.showError(CommonUtils.getStr("save_failed"))
+                    }
+                }
+            }
+        }
+        binding.reset.setDebouncedClickListener {
+            getMaterialsData()
+        }
+        binding.filter.setDebouncedClickListener {
+            FilterMaterialsDialog.show(viewModel.materialsTypeData) { dialog, entity ->
+                dialog.dismiss()
 
+                val data = viewModel.materialsData.orEmpty()
+
+                val qName = entity.materialsName?.trim().orEmpty()
+                val qTypeId = entity.materialsTypeId
+                val qRfid = entity.materialsRfid?.trim().orEmpty()
+                val qSupplier = entity.supplier?.trim().orEmpty()
+                val qExpire = entity.expirationDate?.trim().orEmpty()
+
+                val filtered = data.filter { m ->
+                    (qName.isEmpty() || (m.materialsName?.contains(
+                        qName,
+                        ignoreCase = true
+                    ) == true)) &&
+                            (qTypeId == null || (m.materialsTypeId == qTypeId)) &&
+                            (qRfid.isEmpty() || (m.materialsRfid?.contains(
+                                qRfid,
+                                ignoreCase = true
+                            ) == true)) &&
+                            (qSupplier.isEmpty() || (m.supplier?.contains(
+                                qSupplier,
+                                ignoreCase = true
+                            ) == true)) &&
+                            (qExpire.isEmpty() || (m.expirationDate == qExpire))
+                }
+
+                if (filtered.isEmpty()) {
+                    binding.state.showEmpty()
+                } else {
+                    binding.state.showContent()
+                }
+                binding.listRv.models = filtered
+            }
+        }
+        binding.delete.setDebouncedClickListener {
+            deleteSelect()
+        }
+        binding.listRv.apply {
+            layoutManager = FlexboxLayoutManager(requireContext())
+        }.setup {
+            addType<IsMaterialsEntity>(R.layout.item_materials_manage)
+            onBind {
+                onRVListBinding()
+            }
+        }
+        checkSelectAllStatus()
+    }
+
+    private fun BindingAdapter.BindingViewHolder.onRVListBinding() {
+        val item = getModel<IsMaterialsEntity>()
+        val itemBinding = getBinding<ItemMaterialsManageBinding>()
+        itemBinding.materialsName.text = item.materialsName
+        itemBinding.materialsRfid.text = item.materialsRfid
+        itemBinding.materialsTypeName.text =
+            viewModel.materialsTypeData.find { it.materialsTypeId == item.materialsTypeId }?.materialsTypeName
+        itemBinding.select.setOnCheckedChangeListener(null)
+        itemBinding.select.isChecked = item.isSelected
+        itemBinding.select.setOnCheckedChangeListener { v, checked ->
+            item.isSelected = checked
+            checkSelectAllStatus()
+        }
+        itemBinding.root.setDebouncedClickListener {
+            UpdateMaterialsDialog.show(
+                item,
+                viewModel.materialsTypeData,
+            ) { dialog, isMaterialsEntity ->
+                viewModel.updateMaterials(isMaterialsEntity)
+                    .observe(this@MaterialsManageFragment) {
+                        dialog.dismiss()
+                        if (it) {
+                            TipDialog.showSuccess(
+                                CommonUtils.getStr("save_success"),
+                                onConfirmClick = {
+                                    getMaterialsData()
+                                },
+                                onCancelClick = {
+                                    getMaterialsData()
+                                })
+                        } else {
+                            TipDialog.showError(CommonUtils.getStr("save_failed"))
+                        }
+                    }
+            }
+        }
+    }
+
+    /**
+     * 检查全选状态
+     */
+    private fun checkSelectAllStatus() {
+        binding.selectAll.setOnCheckedChangeListener(null)
+        binding.selectAll.isChecked =
+            viewModel.materialsTypeData.all { it.isSelected } && viewModel.materialsTypeData.isNotEmpty()
+        binding.selectAll.setOnCheckedChangeListener { v, checked ->
+            viewModel.materialsTypeData.forEach { it.isSelected = checked }
+            binding.listRv.adapter?.notifyDataSetChanged()
+        }
+    }
+
+    /**
+     * 删除选中
+     */
+    private fun deleteSelect() {
+        if (viewModel.materialsData.none { it.isSelected }) {
+            showToast(CommonUtils.getStr("please_select_materials_first"))
+            return
+        }
+        viewModel.checkMaterialsInBorrowed().observe(this) {
+            if (it) {
+                showToast(CommonUtils.getStr("has_materials_in_use"))
+                return@observe
+            }
+            viewModel.deleteMaterials().observe(this) {
+                if (it) {
+                    TipDialog.showSuccess(CommonUtils.getStr("delete_success"), onConfirmClick = {
+                        getMaterialsData()
+                    }, onCancelClick = {
+                        getMaterialsData()
+                    })
+                } else {
+                    TipDialog.showError(CommonUtils.getStr("delete_failed"))
+                }
+            }
+        }
+    }
+
+    override fun initData() {
+        super.initData()
+        viewModel.getMaterialsType().observe(this) {}
+        getMaterialsData()
+    }
+
+    /**
+     * 获取物资数据
+     */
+    private fun getMaterialsData() {
+        viewModel.getMaterials().observe(this) {
+            if (viewModel.materialsData.isEmpty()) {
+                binding.state.showEmpty()
+            } else {
+                binding.state.showContent()
+            }
+            binding.listRv.models = viewModel.materialsData
+        }
     }
 }

+ 4 - 0
app/src/main/java/com/grkj/iscs_mc/features/main/fragment/material_manage/MaterialsTypeManageFragment.kt

@@ -72,6 +72,10 @@ class MaterialsTypeManageFragment : BaseFragment<FragmentMaterialsTypeManageBind
      * 删除选中
      */
     private fun deleteSelect() {
+        if (viewModel.materialsTypeData.none { it.isSelected }){
+            showToast(CommonUtils.getStr("please_select_materials_type_first"))
+            return
+        }
         viewModel.checkMaterialsInBorrowed().observe(this) {
             if (it) {
                 showToast(CommonUtils.getStr("has_materials_type_in_use"))

+ 12 - 0
app/src/main/java/com/grkj/iscs_mc/features/main/viewmodel/material_manage/MaterialExchangeViewModel.kt

@@ -8,6 +8,7 @@ import com.grkj.data.local.dos.IsMaterials
 import com.grkj.data.local.dos.IsMaterialsLoan
 import com.grkj.data.local.dos.IsMaterialsType
 import com.grkj.ui_base.base.BaseViewModel
+import com.sik.sikcore.thread.ThreadUtils
 import dagger.hilt.android.lifecycle.HiltViewModel
 import kotlinx.coroutines.Dispatchers
 import javax.inject.Inject
@@ -37,6 +38,8 @@ class MaterialExchangeViewModel @Inject constructor(
     fun getMaterialsData(): LiveData<Boolean> {
         return liveData(Dispatchers.IO) {
             materialsType = materialsLogic.getMaterialsType()
+            materialsData = materialsLogic.getMaterials()
+            materialsLoan = materialsLogic.getMaterialsLoan()
             emit(true)
         }
     }
@@ -49,4 +52,13 @@ class MaterialExchangeViewModel @Inject constructor(
             emit(HardwareMode.getCurrentHardwareMode().openDoor())
         }
     }
+
+    /**
+     * 注册门状态监听
+     */
+    fun registerDoorStatusListener(){
+        ThreadUtils.runOnIO {
+            HardwareMode.getCurrentHardwareMode()
+        }
+    }
 }

+ 67 - 0
app/src/main/java/com/grkj/iscs_mc/features/main/viewmodel/material_manage/MaterialsExchangeWaitAndFinishViewModel.kt

@@ -0,0 +1,67 @@
+package com.grkj.iscs_mc.features.main.viewmodel.material_manage
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.liveData
+import com.grkj.data.domain.logic.IMaterialsLogic
+import com.grkj.data.local.dos.IsMaterials
+import com.grkj.data.local.dos.IsMaterialsLoan
+import com.grkj.data.local.dos.IsMaterialsType
+import com.grkj.iscs_mc.features.main.entity.IsMaterialsEntity
+import com.grkj.ui_base.base.BaseViewModel
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.Dispatchers
+import javax.inject.Inject
+
+/**
+ * 物资盘点和展示
+ */
+@HiltViewModel
+class MaterialsExchangeWaitAndFinishViewModel @Inject constructor(
+    val materialsLogic: IMaterialsLogic
+) : BaseViewModel() {
+    /**
+     * 领取物资
+     */
+    var borrowMaterials: List<IsMaterialsEntity> = listOf()
+
+    /**
+     * 归还物资
+     */
+    var returnMaterials: List<IsMaterialsEntity> = listOf()
+
+    /**
+     * 物资数据
+     */
+    var materialsData: List<IsMaterials> = listOf()
+
+    /**
+     * 物资类型
+     */
+    var materialsType: List<IsMaterialsType> = listOf()
+
+    /**
+     * 物资借出数据
+     */
+    var materialsLoan: List<IsMaterialsLoan> = listOf()
+
+    /**
+     * 盘点物资
+     */
+    fun scanMaterialsExchange(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            emit(true)
+        }
+    }
+
+    /**
+     * 获取物资数据
+     */
+    fun getMaterialsData(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            materialsType = materialsLogic.getMaterialsType()
+            materialsData = materialsLogic.getMaterials()
+            materialsLoan = materialsLogic.getMaterialsLoan()
+            emit(true)
+        }
+    }
+}

+ 89 - 0
app/src/main/java/com/grkj/iscs_mc/features/main/viewmodel/material_manage/MaterialsManageViewModel.kt

@@ -0,0 +1,89 @@
+package com.grkj.iscs_mc.features.main.viewmodel.material_manage
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.liveData
+import com.grkj.data.domain.logic.IMaterialsLogic
+import com.grkj.iscs_mc.features.main.entity.IsMaterialsEntity
+import com.grkj.iscs_mc.features.main.entity.IsMaterialsTypeEntity
+import com.grkj.ui_base.base.BaseViewModel
+import com.sik.sikcore.data.BeanUtils
+import dagger.hilt.android.AndroidEntryPoint
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.Dispatchers
+import javax.inject.Inject
+
+@HiltViewModel
+class MaterialsManageViewModel @Inject constructor(
+    val materialsLogic: IMaterialsLogic
+) : BaseViewModel() {
+
+    var materialsTypeData: List<IsMaterialsTypeEntity> = listOf()
+
+    var materialsData: List<IsMaterialsEntity> = listOf()
+
+    /***
+     * 获取物资类型
+     */
+    fun getMaterialsType(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO) {
+            materialsTypeData = BeanUtils.copyList(
+                materialsLogic.getMaterialsType(),
+                IsMaterialsTypeEntity::class.java
+            )
+            emit(true)
+        }
+    }
+
+    /**
+     * 添加物资
+     */
+    fun addMaterials(entity: IsMaterialsEntity): LiveData<Boolean> {
+        return liveData(Dispatchers.IO){
+            materialsLogic.insertMaterials(entity)
+            emit(true)
+        }
+    }
+
+    /**
+     * 更新物资
+     */
+    fun updateMaterials(entity: IsMaterialsEntity): LiveData<Boolean> {
+        return liveData(Dispatchers.IO){
+            materialsLogic.updateMaterials(entity)
+            emit(true)
+        }
+    }
+
+    /**
+     * 获取物资
+     */
+    fun getMaterials(): LiveData<Boolean> {
+        return liveData(Dispatchers.IO){
+            materialsData = BeanUtils.copyList(
+                materialsLogic.getMaterials(),
+                IsMaterialsEntity::class.java
+            )
+            emit(true)
+        }
+    }
+
+    /**
+     * 删除物资
+     */
+    fun deleteMaterials(): LiveData<Boolean>{
+        return liveData(Dispatchers.IO){
+            materialsLogic.deleteMaterials(materialsData.filter { it.isSelected }.map { it.materialsId })
+            emit(true)
+        }
+    }
+
+    /**
+     * 检查是否有正在使用的物资
+     */
+    fun checkMaterialsInBorrowed(): LiveData<Boolean>{
+        return liveData(Dispatchers.IO){
+            materialsLogic.checkMaterialsInBorrowed(materialsData.filter { it.isSelected }.map { it.materialsId })
+            emit(true)
+        }
+    }
+}

+ 1 - 2
app/src/main/java/com/grkj/iscs_mc/features/main/viewmodel/material_manage/MaterialsTypeManageViewModel.kt

@@ -3,7 +3,6 @@ package com.grkj.iscs_mc.features.main.viewmodel.material_manage
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.liveData
 import com.grkj.data.domain.logic.IMaterialsLogic
-import com.grkj.data.domain.logic.impl.MaterialsLogic
 import com.grkj.data.local.dos.IsMaterialsType
 import com.grkj.iscs_mc.features.main.entity.IsMaterialsTypeEntity
 import com.grkj.ui_base.base.BaseViewModel
@@ -39,7 +38,7 @@ class MaterialsTypeManageViewModel @Inject constructor(
     fun checkMaterialsInBorrowed(): LiveData<Boolean> {
         return liveData(Dispatchers.IO) {
             val hasMaterialsInBorrowed =
-                materialsLogic.checkMaterialsInBorrowed(materialsTypeData.filter { it.isSelected }
+                materialsLogic.checkMaterialsTypeInBorrowed(materialsTypeData.filter { it.isSelected }
                     .map { it.materialsTypeId })
             emit(hasMaterialsInBorrowed)
         }

BIN
app/src/main/jniLibs/arm64-v8a/libModuleAPIJni.so


BIN
app/src/main/jniLibs/armeabi-v7a/libModuleAPIJni.so


BIN
app/src/main/jniLibs/x86_64/libModuleAPIJni.so


+ 255 - 0
app/src/main/res/layout/dialog_filter_materials.xml

@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/dialog_common_root_height_md"
+        android:layout_marginHorizontal="@dimen/iscs_space_5"
+        android:background="@drawable/common_card_bg"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:id="@+id/title_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            android:paddingHorizontal="@dimen/iscs_space_2"
+            android:paddingVertical="@dimen/iscs_title_normal_padding_vertical">
+
+            <TextView
+                android:id="@+id/title"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:i18nKey='@{"filter"}' />
+
+            <ImageView
+                android:id="@+id/close_iv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:src="@drawable/icon_close"
+                android:tint="?attr/colorPrimary" />
+        </LinearLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/divider_line_space"
+            android:background="?attr/colorDivider" />
+
+        <com.grkj.ui_base.widget.FormLayout
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:clipToPadding="false"
+            android:minWidth="0dp"
+            android:orientation="vertical"
+            android:padding="@dimen/dialog_content_normal_padding_horizontal"
+            app:columnSpacing="@dimen/iscs_space_2"
+            app:rowSpacing="@dimen/iscs_space_2">
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/materials_name_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"materials_name"}'
+                app:markPosition="start"
+                app:required="false" />
+
+            <EditText
+                android:id="@+id/materials_name_et"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:layout_marginRight="@dimen/dialog_content_normal_padding_horizontal"
+                android:background="@drawable/bg_common_input"
+                android:maxLines="1"
+                android:minWidth="@dimen/iscs_input_min_width"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:paddingVertical="@dimen/iscs_input_padding_vertical"
+                android:singleLine="true"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="field"
+                app:i18nHint='@{"please_input_materials_name"}' />
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/materials_type_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"materials_type"}'
+                app:markPosition="start"
+                app:required="false" />
+
+            <TextView
+                android:id="@+id/materials_type"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:layout_marginRight="@dimen/dialog_content_normal_padding_horizontal"
+                android:background="@drawable/bg_common_input"
+                android:drawableRight="@mipmap/icon_drop_down"
+                android:maxLines="1"
+                android:minWidth="@dimen/iscs_input_min_width"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:paddingVertical="@dimen/iscs_input_padding_vertical"
+                android:singleLine="true"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="field"
+                app:i18nHint='@{"please_select_materials_type"}' />
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/materials_type_picture_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"materials_type_picture"}'
+                app:markPosition="start"
+                app:required="false" />
+
+            <ImageView
+                android:id="@+id/materials_type_picture"
+                android:layout_width="@dimen/iscs_icon_size_xl"
+                android:layout_height="@dimen/iscs_icon_size_xl"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:scaleType="fitCenter"
+                app:formRole="field" />
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/check_standard_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"rfid"}'
+                app:markPosition="start"
+                app:required="false" />
+
+            <EditText
+                android:id="@+id/materials_rfid_et"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:layout_marginRight="@dimen/dialog_content_normal_padding_horizontal"
+                android:background="@drawable/bg_common_input"
+                android:maxLines="1"
+                android:minWidth="@dimen/iscs_input_min_width"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:paddingVertical="@dimen/iscs_input_padding_vertical"
+                android:singleLine="true"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="field"
+                app:i18nHint='@{"please_input_materials_rfid"}' />
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/supplier_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"supplier"}'
+                app:markPosition="start"
+                app:required="false" />
+
+            <EditText
+                android:id="@+id/supplier_et"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:layout_marginRight="@dimen/dialog_content_normal_padding_horizontal"
+                android:background="@drawable/bg_common_input"
+                android:maxLines="1"
+                android:minWidth="@dimen/iscs_input_min_width"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:paddingVertical="@dimen/iscs_input_padding_vertical"
+                android:singleLine="true"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="field"
+                app:i18nHint='@{"please_input_supplier"}' />
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/expiration_date_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"expiration_date"}'
+                app:markPosition="start"
+                app:required="false" />
+
+            <TextView
+                android:id="@+id/expiration_date"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:layout_marginRight="@dimen/dialog_content_normal_padding_horizontal"
+                android:background="@drawable/bg_common_input"
+                android:maxLines="1"
+                android:minWidth="@dimen/iscs_input_min_width"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:paddingVertical="@dimen/iscs_input_padding_vertical"
+                android:singleLine="true"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="field"
+                app:i18nHint='@{"please_select_expiration_date"}' />
+        </com.grkj.ui_base.widget.FormLayout>
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="right"
+            android:gravity="right"
+            android:orientation="horizontal"
+            android:padding="@dimen/iscs_space_2">
+
+            <TextView
+                android:id="@+id/confirm"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:background="@drawable/common_btn_confirm"
+                android:drawableLeft="@mipmap/icon_confirm"
+                android:drawablePadding="@dimen/iscs_space_2"
+                android:gravity="center"
+                android:minHeight="@dimen/common_btn_height"
+                android:paddingHorizontal="@dimen/iscs_space_4"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:i18nKey='@{"confirm"}' />
+
+            <TextView
+                android:id="@+id/cancel"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:background="@drawable/common_btn_cancel"
+                android:drawableLeft="@mipmap/icon_cancel"
+                android:drawablePadding="@dimen/iscs_space_2"
+                android:gravity="center"
+                android:minHeight="@dimen/common_btn_height"
+                android:paddingHorizontal="@dimen/iscs_space_4"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:i18nKey='@{"cancel"}' />
+        </LinearLayout>
+    </LinearLayout>
+</layout>

+ 255 - 0
app/src/main/res/layout/dialog_materials.xml

@@ -0,0 +1,255 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <LinearLayout
+        android:layout_width="wrap_content"
+        android:layout_height="@dimen/dialog_common_root_height_md"
+        android:layout_marginHorizontal="@dimen/iscs_space_5"
+        android:background="@drawable/common_card_bg"
+        android:orientation="vertical">
+
+        <LinearLayout
+            android:id="@+id/title_layout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:orientation="horizontal"
+            android:paddingHorizontal="@dimen/iscs_space_2"
+            android:paddingVertical="@dimen/iscs_title_normal_padding_vertical">
+
+            <TextView
+                android:id="@+id/title"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:i18nKey='@{"materials_type_manage_add_title"}' />
+
+            <ImageView
+                android:id="@+id/close_iv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:src="@drawable/icon_close"
+                android:tint="?attr/colorPrimary" />
+        </LinearLayout>
+
+        <View
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/divider_line_space"
+            android:background="?attr/colorDivider" />
+
+        <com.grkj.ui_base.widget.FormLayout
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:clipToPadding="false"
+            android:minWidth="0dp"
+            android:orientation="vertical"
+            android:padding="@dimen/dialog_content_normal_padding_horizontal"
+            app:columnSpacing="@dimen/iscs_space_2"
+            app:rowSpacing="@dimen/iscs_space_2">
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/materials_name_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"materials_name"}'
+                app:markPosition="start"
+                app:required="true" />
+
+            <EditText
+                android:id="@+id/materials_name_et"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:layout_marginRight="@dimen/dialog_content_normal_padding_horizontal"
+                android:background="@drawable/bg_common_input"
+                android:maxLines="1"
+                android:minWidth="@dimen/iscs_input_min_width"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:paddingVertical="@dimen/iscs_input_padding_vertical"
+                android:singleLine="true"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="field"
+                app:i18nHint='@{"please_input_materials_name"}' />
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/materials_type_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"materials_type"}'
+                app:markPosition="start"
+                app:required="true" />
+
+            <TextView
+                android:id="@+id/materials_type"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:layout_marginRight="@dimen/dialog_content_normal_padding_horizontal"
+                android:background="@drawable/bg_common_input"
+                android:drawableRight="@mipmap/icon_drop_down"
+                android:maxLines="1"
+                android:minWidth="@dimen/iscs_input_min_width"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:paddingVertical="@dimen/iscs_input_padding_vertical"
+                android:singleLine="true"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="field"
+                app:i18nHint='@{"please_select_materials_type"}' />
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/materials_type_picture_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"materials_type_picture"}'
+                app:markPosition="start"
+                app:required="false" />
+
+            <ImageView
+                android:id="@+id/materials_type_picture"
+                android:layout_width="@dimen/iscs_icon_size_xl"
+                android:layout_height="@dimen/iscs_icon_size_xl"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:scaleType="fitCenter"
+                app:formRole="field" />
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/check_standard_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"rfid"}'
+                app:markPosition="start"
+                app:required="false" />
+
+            <EditText
+                android:id="@+id/materials_rfid_et"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:layout_marginRight="@dimen/dialog_content_normal_padding_horizontal"
+                android:background="@drawable/bg_common_input"
+                android:maxLines="1"
+                android:minWidth="@dimen/iscs_input_min_width"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:paddingVertical="@dimen/iscs_input_padding_vertical"
+                android:singleLine="true"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="field"
+                app:i18nHint='@{"please_input_materials_rfid"}' />
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/supplier_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"supplier"}'
+                app:markPosition="start"
+                app:required="false" />
+
+            <EditText
+                android:id="@+id/supplier_et"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:layout_marginRight="@dimen/dialog_content_normal_padding_horizontal"
+                android:background="@drawable/bg_common_input"
+                android:maxLines="1"
+                android:minWidth="@dimen/iscs_input_min_width"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:paddingVertical="@dimen/iscs_input_padding_vertical"
+                android:singleLine="true"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="field"
+                app:i18nHint='@{"please_input_supplier"}' />
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/expiration_date_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"expiration_date"}'
+                app:markPosition="start"
+                app:required="false" />
+
+            <TextView
+                android:id="@+id/expiration_date"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:layout_marginRight="@dimen/dialog_content_normal_padding_horizontal"
+                android:background="@drawable/bg_common_input"
+                android:maxLines="1"
+                android:minWidth="@dimen/iscs_input_min_width"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:paddingVertical="@dimen/iscs_input_padding_vertical"
+                android:singleLine="true"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="field"
+                app:i18nHint='@{"please_select_expiration_date"}' />
+        </com.grkj.ui_base.widget.FormLayout>
+
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="right"
+            android:gravity="right"
+            android:orientation="horizontal"
+            android:padding="@dimen/iscs_space_2">
+
+            <TextView
+                android:id="@+id/confirm"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:background="@drawable/common_btn_confirm"
+                android:drawableLeft="@mipmap/icon_confirm"
+                android:drawablePadding="@dimen/iscs_space_2"
+                android:gravity="center"
+                android:minHeight="@dimen/common_btn_height"
+                android:paddingHorizontal="@dimen/iscs_space_4"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:i18nKey='@{"confirm"}' />
+
+            <TextView
+                android:id="@+id/cancel"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:background="@drawable/common_btn_cancel"
+                android:drawableLeft="@mipmap/icon_cancel"
+                android:drawablePadding="@dimen/iscs_space_2"
+                android:gravity="center"
+                android:minHeight="@dimen/common_btn_height"
+                android:paddingHorizontal="@dimen/iscs_space_4"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:i18nKey='@{"cancel"}' />
+        </LinearLayout>
+    </LinearLayout>
+</layout>

+ 172 - 0
app/src/main/res/layout/fragment_materials_exchange_wait_and_finish.xml

@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <FrameLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_margin="@dimen/iscs_space_2">
+
+        <LinearLayout
+            android:id="@+id/record_layout"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:orientation="vertical">
+
+            <LinearLayout
+                android:id="@+id/title_layout"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_vertical"
+                android:orientation="horizontal"
+                android:paddingHorizontal="@dimen/iscs_space_2">
+
+                <ImageView
+                    android:layout_width="@dimen/title_icon_size"
+                    android:layout_height="@dimen/title_icon_size"
+                    android:tint="?attr/colorPrimary"
+                    app:skinSrc='@{"box-loading.svg"}' />
+
+                <TextView
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="@dimen/iscs_space_2"
+                    android:layout_weight="1"
+                    android:textColor="?attr/colorTextPrimary"
+                    android:textSize="@dimen/iscs_text_md"
+                    android:textStyle="bold"
+                    app:i18nKey='@{"material_exchange_record"}' />
+
+                <LinearLayout
+                    android:id="@+id/confirm_layout"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_marginLeft="@dimen/iscs_space_2"
+                    android:background="@drawable/bg_tab_container_selector"
+                    android:gravity="center"
+                    android:orientation="horizontal"
+                    android:paddingHorizontal="@dimen/iscs_space_4">
+
+                    <TextView
+                        android:id="@+id/confirm"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:textColor="?attr/colorTextPrimary"
+                        android:textSize="@dimen/iscs_text_md"
+                        app:i18nKey='@{"confirm"}' />
+
+                </LinearLayout>
+
+
+            </LinearLayout>
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_marginHorizontal="@dimen/iscs_space_2"
+                android:layout_marginTop="@dimen/iscs_space_2"
+                android:layout_weight="1"
+                android:background="@drawable/home_card_bg"
+                android:orientation="vertical">
+
+                <LinearLayout
+                    android:id="@+id/borrow_materials_layout"
+                    android:layout_width="match_parent"
+                    android:layout_height="0dp"
+                    android:layout_margin="@dimen/iscs_space_2"
+                    android:layout_weight="1"
+                    android:visibility="gone"
+                    android:orientation="horizontal"
+                    android:showDividers="middle">
+
+                    <TextView
+                        android:id="@+id/borrow_tip"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="@dimen/iscs_text_md"
+                        android:drawablePadding="@dimen/iscs_space_2"
+                        android:textColor="?attr/colorTextPrimary"
+                        android:textSize="@dimen/iscs_text_md" />
+
+                    <View
+                        android:layout_width="match_parent"
+                        android:layout_height="@dimen/divider_line_space"
+                        android:layout_marginVertical="@dimen/iscs_space_2"
+                        android:background="?attr/colorPrimary" />
+
+                    <androidx.recyclerview.widget.RecyclerView
+                        android:id="@+id/borrow_materials_rv"
+                        android:layout_width="match_parent"
+                        android:layout_height="match_parent" />
+                </LinearLayout>
+
+                <LinearLayout
+                    android:id="@+id/return_materials_layout"
+                    android:layout_width="match_parent"
+                    android:layout_height="0dp"
+                    android:layout_margin="@dimen/iscs_space_2"
+                    android:layout_weight="1"
+                    android:visibility="gone"
+                    android:orientation="horizontal"
+                    android:showDividers="middle">
+
+                    <TextView
+                        android:id="@+id/return_tip"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginTop="@dimen/iscs_text_md"
+                        android:drawablePadding="@dimen/iscs_space_2"
+                        android:textColor="?attr/colorTextPrimary"
+                        android:textSize="@dimen/iscs_text_md" />
+
+                    <View
+                        android:layout_width="match_parent"
+                        android:layout_height="@dimen/divider_line_space"
+                        android:layout_marginVertical="@dimen/iscs_space_2"
+                        android:background="?attr/colorPrimary" />
+
+                    <androidx.recyclerview.widget.RecyclerView
+                        android:id="@+id/return_materials_rv"
+                        android:layout_width="match_parent"
+                        android:layout_height="match_parent" />
+                </LinearLayout>
+            </LinearLayout>
+        </LinearLayout>
+
+        <LinearLayout
+            android:id="@+id/loading_layout"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="@drawable/common_card_bg"
+            android:gravity="center"
+            android:orientation="vertical"
+            android:visibility="gone">
+
+            <com.github.ybq.android.spinkit.SpinKitView
+                style="@style/SpinKitView.FadingCircle"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                app:SpinKit_Color="?attr/colorPrimary" />
+
+            <TextView
+                android:id="@+id/loading_tip"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/iscs_text_md"
+                android:drawablePadding="@dimen/iscs_space_2"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:i18nKey='@{"materials_exchange_loading_tip"}' />
+
+            <TextView
+                android:id="@+id/time_count_down_tv"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginTop="@dimen/iscs_text_md"
+                android:drawablePadding="@dimen/iscs_space_2"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                android:visibility="gone" />
+        </LinearLayout>
+    </FrameLayout>
+</layout>

+ 12 - 17
app/src/main/res/layout/fragment_materials_manage.xml

@@ -138,7 +138,7 @@
                 android:gravity="center"
                 android:textColor="?attr/colorTextPrimary"
                 android:textSize="@dimen/iscs_text_md"
-                app:i18nKey='@{"role_manage_role_num"}' />
+                app:i18nKey='@{"materials_name"}' />
 
             <TextView
                 android:layout_width="0dp"
@@ -147,7 +147,7 @@
                 android:gravity="center"
                 android:textColor="?attr/colorTextPrimary"
                 android:textSize="@dimen/iscs_text_md"
-                app:i18nKey='@{"role_manage_role_name"}' />
+                app:i18nKey='@{"materials_type_name"}' />
 
             <TextView
                 android:layout_width="0dp"
@@ -156,28 +156,23 @@
                 android:gravity="center"
                 android:textColor="?attr/colorTextPrimary"
                 android:textSize="@dimen/iscs_text_md"
-                app:i18nKey='@{"role_manage_permission_string"}' />
+                app:i18nKey='@{"rfid"}' />
         </LinearLayout>
 
-        <com.scwang.smart.refresh.layout.SmartRefreshLayout
-            android:id="@+id/refresh_layout"
+
+        <com.drake.statelayout.StateLayout
+            android:id="@+id/state"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_marginHorizontal="@dimen/iscs_space_4"
-            android:layout_marginBottom="@dimen/iscs_space_2">
+            android:layout_marginBottom="@dimen/iscs_space_2"
+            android:background="@drawable/common_card_bg">
 
-            <com.drake.statelayout.StateLayout
-                android:id="@+id/state"
+            <androidx.recyclerview.widget.RecyclerView
+                android:id="@+id/list_rv"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
-                android:background="@drawable/common_card_bg">
-
-                <androidx.recyclerview.widget.RecyclerView
-                    android:id="@+id/role_list_rv"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:background="@drawable/common_card_bg" />
-            </com.drake.statelayout.StateLayout>
-        </com.scwang.smart.refresh.layout.SmartRefreshLayout>
+                android:background="@drawable/common_card_bg" />
+        </com.drake.statelayout.StateLayout>
     </LinearLayout>
 </layout>

+ 46 - 0
app/src/main/res/layout/item_materials_manage.xml

@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:divider="@drawable/divider_table"
+        android:showDividers="middle">
+
+        <com.google.android.material.checkbox.MaterialCheckBox
+            android:id="@+id/select"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center"
+            app:useMaterialThemeColors="true" />
+
+        <TextView
+            android:id="@+id/materials_name"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:textColor="?attr/colorTextPrimary"
+            android:textSize="@dimen/iscs_text_md" />
+
+
+        <TextView
+            android:id="@+id/materials_type_name"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:textColor="?attr/colorTextPrimary"
+            android:textSize="@dimen/iscs_text_md" />
+
+        <TextView
+            android:id="@+id/materials_rfid"
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:gravity="center"
+            android:textColor="?attr/colorTextPrimary"
+            android:textSize="@dimen/iscs_text_md" />
+    </LinearLayout>
+</layout>

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

@@ -21,7 +21,11 @@
     <fragment
         android:id="@+id/materialExchangeFragment"
         android:name="com.grkj.iscs_mc.features.main.fragment.material_manage.MaterialsExchangeFragment"
-        android:label="MaterialExchangeFragment" />
+        android:label="MaterialExchangeFragment" >
+        <action
+            android:id="@+id/action_materialExchangeFragment_to_materialsExchangeWaitAndFinishFragment"
+            app:destination="@id/materialsExchangeWaitAndFinishFragment" />
+    </fragment>
     <fragment
         android:id="@+id/materialsTypeManageFragment"
         android:name="com.grkj.iscs_mc.features.main.fragment.material_manage.MaterialsTypeManageFragment"
@@ -30,4 +34,8 @@
         android:id="@+id/materialsManageFragment"
         android:name="com.grkj.iscs_mc.features.main.fragment.material_manage.MaterialsManageFragment"
         android:label="MaterialsManageFragment" />
+    <fragment
+        android:id="@+id/materialsExchangeWaitAndFinishFragment"
+        android:name="com.grkj.iscs_mc.features.main.fragment.material_manage.MaterialsExchangeWaitAndFinishFragment"
+        android:label="MaterialsExchangeWaitAndFinishFragment" />
 </navigation>

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

@@ -37,6 +37,11 @@ object EventConstants {
      * 弹窗事件
      */
     const val EVENT_TOAST_CODE: Int = 100_000_007
+
+    /**
+     * 物资柜关门事件
+     */
+    const val EVENT_CABINET_DOOR_CLOSED: Int = 100_000_008
     //---------------------------硬件通知------------------------
     /**
      * RFID读卡事件

+ 33 - 1
data/src/main/java/com/grkj/data/domain/logic/IMaterialsLogic.kt

@@ -1,5 +1,7 @@
 package com.grkj.data.domain.logic
 
+import com.grkj.data.local.dos.IsMaterials
+import com.grkj.data.local.dos.IsMaterialsLoan
 import com.grkj.data.local.dos.IsMaterialsType
 
 /**
@@ -29,5 +31,35 @@ interface IMaterialsLogic {
     /**
      * 检查是否有正在使用的物资类型
      */
-    fun checkMaterialsInBorrowed(materialsTypeId: List<Long>): Boolean
+    fun checkMaterialsTypeInBorrowed(materialsTypeId: List<Long>): Boolean
+
+    /**
+     * 新增物资
+     */
+    fun insertMaterials(isMaterials: IsMaterials)
+
+    /**
+     * 更新物资
+     */
+    fun updateMaterials(isMaterials: IsMaterials)
+
+    /**
+     * 获取物资
+     */
+    fun getMaterials(): List<IsMaterials>
+
+    /**
+     * 删除物资
+     */
+    fun deleteMaterials(materialsId: List<Long>)
+
+    /**
+     * 检查是否有正在使用的物资
+     */
+    fun checkMaterialsInBorrowed(materialsId: List<Long>): Boolean
+
+    /**
+     * 获取借出物资
+     */
+    fun getMaterialsLoan(): List<IsMaterialsLoan>
 }

+ 28 - 2
data/src/main/java/com/grkj/data/domain/logic/impl/MaterialsLogic.kt

@@ -2,6 +2,8 @@ package com.grkj.data.domain.logic.impl
 
 import com.grkj.data.domain.logic.BaseLogic
 import com.grkj.data.domain.logic.IMaterialsLogic
+import com.grkj.data.local.dos.IsMaterials
+import com.grkj.data.local.dos.IsMaterialsLoan
 import com.grkj.data.local.dos.IsMaterialsType
 import com.grkj.data.repository.IMaterialsRepository
 import javax.inject.Inject
@@ -22,6 +24,30 @@ class MaterialsLogic @Inject constructor(
         materialsRepository.insertMaterialsType(materialsType)
     }
 
+    override fun insertMaterials(isMaterials: IsMaterials) {
+        materialsRepository.insertMaterials(isMaterials)
+    }
+
+    override fun getMaterials(): List<IsMaterials> {
+        return materialsRepository.getMaterials()
+    }
+
+    override fun deleteMaterials(materialsId: List<Long>) {
+        materialsRepository.deleteMaterials(materialsId)
+    }
+
+    override fun checkMaterialsInBorrowed(materialsId: List<Long>): Boolean {
+        return materialsRepository.checkMaterialsInBorrowed(materialsId)
+    }
+
+    override fun getMaterialsLoan(): List<IsMaterialsLoan> {
+        return materialsRepository.getMaterialsLoan()
+    }
+
+    override fun updateMaterials(isMaterials: IsMaterials) {
+        materialsRepository.updateMaterials(isMaterials)
+    }
+
     override fun updateMaterialsType(materialsType: IsMaterialsType) {
         materialsRepository.updateMaterialsType(materialsType)
     }
@@ -30,7 +56,7 @@ class MaterialsLogic @Inject constructor(
         materialsRepository.deleteMaterialsType(materialTypeIds)
     }
 
-    override fun checkMaterialsInBorrowed(materialsTypeId: List<Long>): Boolean {
-        return materialsRepository.checkMaterialsInBorrowed(materialsTypeId)
+    override fun checkMaterialsTypeInBorrowed(materialsTypeId: List<Long>): Boolean {
+        return materialsRepository.checkMaterialsTypeInBorrowed(materialsTypeId)
     }
 }

+ 8 - 0
data/src/main/java/com/grkj/data/hardware/IHardwareHelper.kt

@@ -1,5 +1,8 @@
 package com.grkj.data.hardware
 
+import android.app.Application
+import java.lang.ref.WeakReference
+
 /**
  * 硬件帮助抽象
  */
@@ -8,4 +11,9 @@ interface IHardwareHelper {
      * 开柜门
      */
     suspend fun openDoor(left: Boolean? = null, right: Boolean? = null): Boolean
+
+    /**
+     * 连接并监听
+     */
+    fun connectAndAddListener(application: WeakReference<Application>)
 }

+ 20 - 0
data/src/main/java/com/grkj/data/hardware/can/CanHardwareHelper.kt

@@ -1,12 +1,19 @@
 package com.grkj.data.hardware.can
 
+import android.app.Application
 import com.grkj.data.hardware.IHardwareHelper
+import com.grkj.data.utils.event.CabinetDoorClosedEvent
 import com.sik.comm.impl_can.SdoOp
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+import java.lang.ref.WeakReference
 
 /**
  * Can 硬件帮助接口实现
  */
 class CanHardwareHelper : IHardwareHelper {
+    private val logger: Logger = LoggerFactory.getLogger(CanHardwareHelper::class.java)
+
     override suspend fun openDoor(left: Boolean?, right: Boolean?): Boolean {
         val materialCabinets =
             CanHelper.getDeviceByDeviceType(CanDeviceConst.DEVICE_MATERIAL_CABINET_CONTROL_BOARD)
@@ -18,4 +25,17 @@ class CanHardwareHelper : IHardwareHelper {
             false
         }
     }
+
+    override fun connectAndAddListener(application: WeakReference<Application>) {
+        CanHelper.connect()
+        CanHelper.addDeviceChangeListener(application) {
+            it.forEach {
+                if (it.deviceType == CanDeviceConst.DEVICE_KEY_CABINET_CONTROL_BOARD && it.deviceChange) {
+                    if (it.locked){
+                        CabinetDoorClosedEvent.sendCabinetDoorClosedEvent()
+                    }
+                }
+            }
+        }
+    }
 }

+ 5 - 2
data/src/main/java/com/grkj/data/hardware/can/CanReadyPlugin.kt

@@ -10,12 +10,13 @@ import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 import kotlin.coroutines.resume
 import kotlin.coroutines.suspendCoroutine
+import kotlin.math.log
 
 class CanReadyPlugin : CommPlugin {
     private val logger: Logger = LoggerFactory.getLogger(CanReadyPlugin::class.java)
 
     /** 轮询哪些节点 */
-    private val scanRange: IntRange = 1..6
+    private val scanRange: IntRange = 0..2
     private val activeNodes = mutableSetOf<Int>()
 
     /** 周期 */
@@ -64,7 +65,9 @@ class CanReadyPlugin : CommPlugin {
             // 每个节点独立的 RFID 读取节流时间戳
             val lastRfidAt = LongArray(scanRange.last + 1) { 0L }
 
-            for (nodeId in scanRange) {
+            for (size in scanRange) {
+                val nodeId = 1 shl size
+                logger.info("扫描NodeId:${nodeId}")
                 safeRead(CanCommands.Common.getDeviceType(nodeId))?.let {
                     activeNodes.add(nodeId)
                     CanHelper.addNode(nodeId, it.payload[0].toInt())

+ 61 - 2
data/src/main/java/com/grkj/data/local/dao/MaterialsDao.kt

@@ -5,6 +5,8 @@ import androidx.room.Insert
 import androidx.room.OnConflictStrategy
 import androidx.room.Query
 import androidx.room.Update
+import com.grkj.data.local.dos.IsMaterials
+import com.grkj.data.local.dos.IsMaterialsLoan
 import com.grkj.data.local.dos.IsMaterialsType
 
 /**
@@ -40,11 +42,68 @@ interface MaterialsDao {
     /**
      * 检查是否有正在使用的物资类型
      */
-    @Query("""
+    @Query(
+        """
         select count(*) from is_materials_loan iml
         left join is_materials im on iml.materials_id = im.materials_id
         left join is_materials_type imt on im.materials_type_id = imt.materials_type_id
         where iml.status = 0 and iml.del_flag = 0 and imt.materials_type_id in (:materialsTypeId)
+    """
+    )
+    fun checkMaterialsTypeInBorrowed(materialsTypeId: List<Long>): Int
+
+    /**
+     * 新增物资
+     */
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    fun insertMaterials(materials: IsMaterials)
+
+    /**
+     * 更新物资
+     */
+    @Update(onConflict = OnConflictStrategy.REPLACE)
+    fun updateMaterials(materials: IsMaterials)
+
+    /**
+     * 查询物资
+     */
+    @Query("select * from is_materials where del_flag = 0")
+    fun getMaterials(): List<IsMaterials>
+
+    /**
+     * 删除物资
+     */
+    @Query("update is_materials set del_flag = 1 where materials_id in (:materialIds)")
+    fun deleteMaterials(materialIds: List<Long>)
+
+    /**
+     * 检查是否有正在使用的物资
+     */
+    @Query("""
+        select count(*) from is_materials_loan iml
+        left join is_materials im on iml.materials_id = im.materials_id
+        where iml.status = 0 and iml.del_flag = 0 and im.materials_id in (:materialsId)
+    """)
+    fun checkMaterialsInBorrowed(materialsId: List<Long>): Int
+
+    /**
+     * 新增领取物资
+     */
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    fun addMaterialsLoan(materialsLoan: List<IsMaterialsLoan>)
+
+    /**
+     * 更新领取物资
+     */
+    @Update(onConflict = OnConflictStrategy.REPLACE)
+    fun updateMaterialsLoan(materialsLoan: List<IsMaterialsLoan>)
+
+    /**
+     * 获取借出物资
+     */
+    @Query("""
+        select * from is_materials_loan iml
+        where del_flag = 0 and iml.restitution_required = 0 and iml.status = 0
     """)
-    fun checkMaterialsInBorrowed(materialsTypeId: List<Long>): Int
+    fun getMaterialsLoan(): List<IsMaterialsLoan>
 }

+ 43 - 1
data/src/main/java/com/grkj/data/repository/IMaterialsRepository.kt

@@ -1,5 +1,7 @@
 package com.grkj.data.repository
 
+import com.grkj.data.local.dos.IsMaterials
+import com.grkj.data.local.dos.IsMaterialsLoan
 import com.grkj.data.local.dos.IsMaterialsType
 
 /**
@@ -29,5 +31,45 @@ interface IMaterialsRepository {
     /**
      * 检查是否有正在使用的物资类型
      */
-    fun checkMaterialsInBorrowed(materialsTypeId: List<Long>): Boolean
+    fun checkMaterialsTypeInBorrowed(materialsTypeId: List<Long>): Boolean
+
+    /**
+     * 新增物资
+     */
+    fun insertMaterials(materials: IsMaterials)
+
+    /**
+     * 更新物资
+     */
+    fun updateMaterials(materials: IsMaterials)
+
+    /**
+     * 获取物资
+     */
+    fun getMaterials(): List<IsMaterials>
+
+    /**
+     * 删除物资
+     */
+    fun deleteMaterials(materialsId: List<Long>)
+
+    /**
+     * 检查是否有正在使用的物资
+     */
+    fun checkMaterialsInBorrowed(materialsId: List<Long>): Boolean
+
+    /**
+     * 获取借出物资
+     */
+    fun getMaterialsLoan(): List<IsMaterialsLoan>
+
+    /**
+     * 新增领取物资
+     */
+    fun addMaterialsLoan(materialsLoan: List<IsMaterialsLoan>)
+
+    /**
+     * 更新领取物资
+     */
+    fun updateMaterialsLoan(materialsLoan: List<IsMaterialsLoan>)
 }

+ 35 - 1
data/src/main/java/com/grkj/data/repository/impl/network/NetworkMaterialsRepository.kt

@@ -1,5 +1,7 @@
 package com.grkj.data.repository.impl.network
 
+import com.grkj.data.local.dos.IsMaterials
+import com.grkj.data.local.dos.IsMaterialsLoan
 import com.grkj.data.local.dos.IsMaterialsType
 import com.grkj.data.repository.BaseRepository
 import com.grkj.data.repository.IMaterialsRepository
@@ -27,7 +29,39 @@ class NetworkMaterialsRepository @Inject constructor(): BaseRepository(), IMater
         TODO("Not yet implemented")
     }
 
-    override fun checkMaterialsInBorrowed(materialsTypeId: List<Long>): Boolean {
+    override fun checkMaterialsTypeInBorrowed(materialsTypeId: List<Long>): Boolean {
+        TODO("Not yet implemented")
+    }
+
+    override fun insertMaterials(materials: IsMaterials) {
+        TODO("Not yet implemented")
+    }
+
+    override fun updateMaterials(materials: IsMaterials) {
+        TODO("Not yet implemented")
+    }
+
+    override fun getMaterials(): List<IsMaterials> {
+        TODO("Not yet implemented")
+    }
+
+    override fun deleteMaterials(materialsId: List<Long>) {
+        TODO("Not yet implemented")
+    }
+
+    override fun checkMaterialsInBorrowed(materialsId: List<Long>): Boolean {
+        TODO("Not yet implemented")
+    }
+
+    override fun getMaterialsLoan(): List<IsMaterialsLoan> {
+        TODO("Not yet implemented")
+    }
+
+    override fun addMaterialsLoan(materialsLoan: List<IsMaterialsLoan>) {
+        TODO("Not yet implemented")
+    }
+
+    override fun updateMaterialsLoan(materialsLoan: List<IsMaterialsLoan>) {
         TODO("Not yet implemented")
     }
 }

+ 36 - 2
data/src/main/java/com/grkj/data/repository/impl/standard/StandardMaterialsRepository.kt

@@ -1,6 +1,8 @@
 package com.grkj.data.repository.impl.standard
 
 import com.grkj.data.local.dao.MaterialsDao
+import com.grkj.data.local.dos.IsMaterials
+import com.grkj.data.local.dos.IsMaterialsLoan
 import com.grkj.data.local.dos.IsMaterialsType
 import com.grkj.data.repository.BaseRepository
 import com.grkj.data.repository.IMaterialsRepository
@@ -18,8 +20,40 @@ class StandardMaterialsRepository @Inject constructor(
         return materialsDao.getMaterialsType()
     }
 
-    override fun checkMaterialsInBorrowed(materialsTypeId: List<Long>): Boolean {
-        return materialsDao.checkMaterialsInBorrowed(materialsTypeId) > 0
+    override fun checkMaterialsTypeInBorrowed(materialsTypeId: List<Long>): Boolean {
+        return materialsDao.checkMaterialsTypeInBorrowed(materialsTypeId) > 0
+    }
+
+    override fun updateMaterials(materials: IsMaterials) {
+        materialsDao.updateMaterials(materials)
+    }
+
+    override fun deleteMaterials(materialsId: List<Long>) {
+        return materialsDao.deleteMaterials(materialsId)
+    }
+
+    override fun checkMaterialsInBorrowed(materialsId: List<Long>): Boolean {
+        return materialsDao.checkMaterialsInBorrowed(materialsId) > 0
+    }
+
+    override fun addMaterialsLoan(materialsLoan: List<IsMaterialsLoan>) {
+        materialsDao.addMaterialsLoan(materialsLoan)
+    }
+
+    override fun updateMaterialsLoan(materialsLoan: List<IsMaterialsLoan>) {
+        materialsDao.updateMaterialsLoan(materialsLoan)
+    }
+
+    override fun getMaterialsLoan(): List<IsMaterialsLoan> {
+        return materialsDao.getMaterialsLoan()
+    }
+
+    override fun getMaterials(): List<IsMaterials> {
+        return materialsDao.getMaterials()
+    }
+
+    override fun insertMaterials(materials: IsMaterials) {
+        materialsDao.insertMaterials(materials)
     }
 
     override fun insertMaterialsType(materialsType: IsMaterialsType) {

+ 25 - 0
data/src/main/java/com/grkj/data/utils/event/CabinetDoorClosedEvent.kt

@@ -0,0 +1,25 @@
+package com.grkj.data.utils.event
+
+import com.grkj.data.common.EventConstants
+import com.grkj.shared.model.EventBean
+import com.grkj.shared.utils.event.EventHelper
+
+/**
+ * 物资柜关门事件
+ */
+class CabinetDoorClosedEvent() {
+
+    companion object {
+        /**
+         * 发送物资柜关门事件
+         */
+        @JvmStatic
+        fun sendCabinetDoorClosedEvent() {
+            val cabinetDoorClosedEvent = CabinetDoorClosedEvent()
+            val cabinetDoorClosedEventBean = EventBean<CabinetDoorClosedEvent>(
+                EventConstants.EVENT_CABINET_DOOR_CLOSED, cabinetDoorClosedEvent
+            )
+            EventHelper.sendEvent(cabinetDoorClosedEventBean)
+        }
+    }
+}

BIN
shared/libs/ModuleAPI_J.jar


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

@@ -69,6 +69,8 @@ dependencies {
     api("com.github.ycuwq:DatePicker:1.3.4")
     api("com.github.bingoogolapple.BGABadgeView-Android:api:1.2.0")
     kapt("com.github.bingoogolapple.BGABadgeView-Android:compiler:1.2.0")
+    api("com.github.loper7:DateTimePicker:0.6.3")
+    api("com.github.ybq:Android-SpinKit:1.4.0")
 //    api("com.licheedev:android-serialport:2.1.5")
     implementation(project(":data"))
     implementation(project(":shared"))

+ 1 - 1
ui-base/src/main/java/com/grkj/ui_base/config/ISCSConfig.kt

@@ -10,7 +10,7 @@ object ISCSConfig {
     /**
      * 是否是DEBUG模式
      */
-    val DEBUG: Boolean = false
+    val DEBUG: Boolean = true
 
     /**
      * 是否是联网版

+ 34 - 0
ui-base/src/main/java/com/grkj/ui_base/utils/DateTimePickUtils.kt

@@ -0,0 +1,34 @@
+package com.grkj.ui_base.utils
+
+import android.widget.TextView
+import com.loper7.date_time_picker.dialog.CardDatePickerDialog
+import com.sik.sikandroid.activity.ActivityTracker
+import com.sik.sikcore.SIKCore
+import com.sik.sikcore.date.TimeUtils
+import me.jessyan.autosize.AutoSize
+import java.util.Date
+
+/**
+ * 时间日期选择工具
+ */
+object DateTimePickUtils {
+    /**
+     * 选择日期
+     */
+    fun pickDate(title: String, timeView: TextView) {
+        ActivityTracker.getCurrentActivity()?.let {
+            AutoSize.autoConvertDensity(it, 600f, false)
+        }
+        CardDatePickerDialog.builder(SIKCore.getApplication()).setTitle(title).showBackNow(false)
+            .setLabelText(
+                CommonUtils.getStr("year"),
+                CommonUtils.getStr("month"),
+                CommonUtils.getStr("day"),
+            ).showFocusDateInfo(false).setOnChoose(CommonUtils.getStr("confirm")) { millisecond ->
+                val chooseTime = TimeUtils.formatDate(
+                    Date(millisecond), TimeUtils.DEFAULT_DATE_FORMAT
+                )
+                timeView.text = chooseTime
+            }.setOnCancel(CommonUtils.getStr("cancel")).build().show()
+    }
+}