Kaynağa Gözat

refactor(更新):
- 优化工位编辑弹窗UI和交互,新增设置默认工位功能
- 优化硬件数据获取和处理逻辑,修复钥匙MAC地址更新问题
- 调整用户特征数据查询,增加软删除用户过滤
- 调整工卡NFC查询用户ID,增加软删除用户过滤
- 修复`SysMenuDao`中`insertRoleMenus`方法冲突策略为`REPLACE`
- 优化`CanHelper`中`getTakeLockMap`方法实现
- 调整`MainActivity`中用户昵称显示长度和字体大小
- 优化`LoginActivity`登录方式文本国际化处理
- 新增`RefreshAvatarEvent`事件,用于刷新用户头像
- 修复`AutoSizeConfig`中`isCustomFragment`配置为`false`
- 优化设备序列号获取方式
- 优化部分UI显示和交互体验
- 更新国际化文本

周文健 2 ay önce
ebeveyn
işleme
c885bf036e
27 değiştirilmiş dosya ile 232 ekleme ve 125 silme
  1. 6 1
      app/src/main/assets/i18n/en-US.json
  2. 6 1
      app/src/main/assets/i18n/zh-CN.json
  3. 1 1
      app/src/main/java/com/grkj/iscs/ISCSApplication.kt
  4. 2 1
      app/src/main/java/com/grkj/iscs/features/init/viewmodel/InitDeviceRegistrationKeyAndLockViewModel.kt
  5. 5 5
      app/src/main/java/com/grkj/iscs/features/login/activity/LoginActivity.kt
  6. 19 11
      app/src/main/java/com/grkj/iscs/features/main/activity/MainActivity.kt
  7. 4 3
      app/src/main/java/com/grkj/iscs/features/main/dialog/data_manage/UpdateWorkstationDialog.kt
  8. 2 0
      app/src/main/java/com/grkj/iscs/features/main/fragment/user_info/UserInfoFragment.kt
  9. 1 1
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/hardware_manage/SlotsManageViewModel.kt
  10. 3 1
      app/src/main/java/com/grkj/iscs/features/main/viewmodel/job_manage/JobExecuteViewModel.kt
  11. 11 8
      app/src/main/java/com/grkj/iscs/features/splash/activity/SplashActivity.kt
  12. 3 3
      app/src/main/res/layout-land/activity_main.xml
  13. 2 2
      app/src/main/res/layout/activity_main.xml
  14. 63 41
      app/src/main/res/layout/dialog_update_workstation.xml
  15. 1 1
      data/src/main/java/com/grkj/data/dao/HardwareDao.kt
  16. 1 1
      data/src/main/java/com/grkj/data/dao/SysMenuDao.kt
  17. 2 2
      data/src/main/java/com/grkj/data/dao/UserDao.kt
  18. 4 0
      data/src/main/java/com/grkj/data/data/EventConstants.kt
  19. 8 0
      data/src/main/java/com/grkj/data/hardware/DockData.kt
  20. 5 0
      data/src/main/java/com/grkj/data/hardware/IHardwareHelper.kt
  21. 6 1
      data/src/main/java/com/grkj/data/hardware/can/CanHardwareHelper.kt
  22. 38 21
      data/src/main/java/com/grkj/data/hardware/can/CanHelper.kt
  23. 9 0
      data/src/main/java/com/grkj/data/hardware/modbus/ModBusHardwareHelper.kt
  24. 1 11
      ui-base/src/main/java/com/grkj/ui_base/base/BaseFragment.kt
  25. 25 0
      ui-base/src/main/java/com/grkj/ui_base/utils/event/RefreshAvatarEvent.kt
  26. 2 7
      ui-base/src/main/java/com/grkj/ui_base/utils/extension/Context.kt
  27. 2 2
      ui-base/src/main/java/com/grkj/ui_base/widget/CustomNavBar.kt

+ 6 - 1
app/src/main/assets/i18n/en-US.json

@@ -1407,7 +1407,7 @@
   "lock_code": {
     "key": "lock_code",
     "type": "text",
-    "value": "Lock Number"
+    "value": "Lock Name"
   },
   "lock_exception_tag": {
     "key": "lock_exception_tag",
@@ -3134,6 +3134,11 @@
     "type": "text",
     "value": "Add Area"
   },
+  "workstation_manage_update_workstation": {
+    "key": "workstation_manage_update_workstation",
+    "type": "text",
+    "value": "Edit Area"
+  },
   "workstation_manage_title": {
     "key": "workstation_manage_title",
     "type": "text",

+ 6 - 1
app/src/main/assets/i18n/zh-CN.json

@@ -412,7 +412,7 @@
   "confirm": {
     "key": "confirm",
     "type": "text",
-    "value": "执行确认"
+    "value": "确认"
   },
   "confirm_cancel_exception": {
     "key": "confirm_cancel_exception",
@@ -3134,6 +3134,11 @@
     "type": "text",
     "value": "新增区域"
   },
+  "workstation_manage_update_workstation": {
+    "key": "workstation_manage_update_workstation",
+    "type": "text",
+    "value": "编辑区域"
+  },
   "workstation_manage_title": {
     "key": "workstation_manage_title",
     "type": "text",

+ 1 - 1
app/src/main/java/com/grkj/iscs/ISCSApplication.kt

@@ -104,7 +104,7 @@ class ISCSApplication : Application() {
         if (ISCSConfig.isInit) {
             BleUtil.instance?.initBle(this)
         }
-        AutoSizeConfig.getInstance().isCustomFragment = true
+        AutoSizeConfig.getInstance().isCustomFragment = false
         StateConfig.emptyLayout = com.grkj.ui_base.R.layout.layout_empty
         ThreadUtils.runOnIO {
             DbReadyGate.await()

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

@@ -161,7 +161,7 @@ class InitDeviceRegistrationKeyAndLockViewModel @Inject constructor(val hardware
                                                 mac
                                             }"
                                         )
-                                        keyBean.mac = mac
+                                        HardwareMode.getCurrentHardwareMode().updateKeyMac(keyBean.rfid,mac)
                                         alreadyUsedMac.add(mac)
                                         if (cont.isActive) {
                                             cont.resume(true)
@@ -281,6 +281,7 @@ class InitDeviceRegistrationKeyAndLockViewModel @Inject constructor(val hardware
             val keyDevice = HardwareMode.getCurrentHardwareMode().getKeyDockData()
                 .flatMap { it.keyData }
                 .filter { it.newHardware && it.rfid.isNotEmpty() && it.mac.isNotEmpty() }
+            logger.info("钥匙信息:${keyDevice}")
             lockDevice.forEach { lockDevice ->
                 val isBind = deviceInputLockSuspend(lockDevice.rfid)
                 if (isBind) {

+ 5 - 5
app/src/main/java/com/grkj/iscs/features/login/activity/LoginActivity.kt

@@ -112,7 +112,7 @@ class LoginActivity : BaseActivity<ActivityLoginBinding>() {
         val itemBinding = holder.getBinding<ItemLoginMethodBinding>()
         val item = holder.getModel<LoginMenuEntity>()
         itemBinding.loginTipV.isVisible = item.needTip
-        itemBinding.loginMethodTv.text = item.menuText
+        itemBinding.loginMethodTv.text = CommonUtils.getStr(item.menuText)
         itemBinding.loginMethodIv.loadSkinIcon(item.menuIcon)
         ImageViewCompat.setImageTintList(
             itemBinding.loginMethodIv,
@@ -193,7 +193,7 @@ class LoginActivity : BaseActivity<ActivityLoginBinding>() {
                     "face-id-svgrepo-com.svg",
                     CommonUtils.getColor(com.grkj.ui_base.R.attr.colorWhite),
                     CommonUtils.getColor(com.grkj.ui_base.R.attr.colorFaceLogin),
-                    CommonUtils.getStr("face_login"),
+                    "face_login",
                     false,
                     0
                 )
@@ -203,7 +203,7 @@ class LoginActivity : BaseActivity<ActivityLoginBinding>() {
                     "icon_login_menu_password.png",
                     CommonUtils.getColor(com.grkj.ui_base.R.attr.colorWhite),
                     CommonUtils.getColor(com.grkj.ui_base.R.attr.colorUserLogin),
-                    CommonUtils.getStr("password_login"),
+                    "password_login",
                     false,
                     3
                 )
@@ -213,7 +213,7 @@ class LoginActivity : BaseActivity<ActivityLoginBinding>() {
                     "fingerprint.svg",
                     CommonUtils.getColor(com.grkj.ui_base.R.attr.colorWhite),
                     CommonUtils.getColor(com.grkj.ui_base.R.attr.colorFingerprint),
-                    CommonUtils.getStr("fingerprint_login"),
+                    "fingerprint_login",
                     true,
                     1
                 )
@@ -223,7 +223,7 @@ class LoginActivity : BaseActivity<ActivityLoginBinding>() {
                     "icon_login_menu_card.png",
                     CommonUtils.getColor(com.grkj.ui_base.R.attr.colorWhite),
                     CommonUtils.getColor(com.grkj.ui_base.R.attr.colorCardLogin),
-                    CommonUtils.getStr("card_login"),
+                    "card_login",
                     true,
                     2
                 )

+ 19 - 11
app/src/main/java/com/grkj/iscs/features/main/activity/MainActivity.kt

@@ -106,17 +106,6 @@ class MainActivity() : BaseActivity<ActivityMainBinding>() {
             logout()
         })
         binding.nickname.text = MainDomainData.userInfo?.nickName ?: ""
-        (MainDomainData.userInfo?.avatar
-            ?: MainDomainData.userBiometricDataVo.find { it.type == "2" }?.content)?.let {
-            if (it.isNotEmpty()) {
-                val faceData = it.file().readText()
-                val avatar = ImageConvertUtils.base64ToBitmap(faceData)
-                binding.avatar.removeTint()
-                binding.avatar.load(avatar) {
-                    transformations(CircleCropTransformation())
-                }
-            }
-        }
         binding.navBar.let {
             it.menu.clear()
             it.setIconData(tabConfigs.associate { it.title to it.icon })
@@ -169,6 +158,10 @@ class MainActivity() : BaseActivity<ActivityMainBinding>() {
                 logout()
             }
 
+            EventConstants.EVENT_REFRESH_AVATAR_CODE -> {
+                loadAvatar()
+            }
+
             EventConstants.EVENT_FLASH_TIP_CODE -> {
                 (event.data as FlashTipEvent).apply {
                     if (isShow) {
@@ -188,6 +181,20 @@ class MainActivity() : BaseActivity<ActivityMainBinding>() {
         }
     }
 
+    private fun loadAvatar() {
+        (MainDomainData.userInfo?.avatar
+            ?: MainDomainData.userBiometricDataVo.find { it.type == "2" }?.content)?.let {
+            if (it.isNotEmpty()) {
+                val faceData = it.file().readText()
+                val avatar = ImageConvertUtils.base64ToBitmap(faceData)
+                binding.avatar.removeTint()
+                binding.avatar.load(avatar) {
+                    transformations(CircleCropTransformation())
+                }
+            }
+        }
+    }
+
     override fun initData() {
         super.initData()
         if (isFirstEnter) {
@@ -202,6 +209,7 @@ class MainActivity() : BaseActivity<ActivityMainBinding>() {
         CountdownTimer.reset()
         return super.dispatchTouchEvent(ev)
     }
+
     override fun dispatchKeyEvent(event: KeyEvent): Boolean {
         if (event.action == KeyEvent.ACTION_UP && event.source == InputDevice.SOURCE_KEYBOARD) {
             // 检测到回车开始处理

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

@@ -5,6 +5,7 @@ import com.grkj.data.data.MMKVConstants
 import com.grkj.data.data.MainDomainData
 import com.grkj.iscs.R
 import com.grkj.iscs.databinding.DialogAddWorkstationBinding
+import com.grkj.iscs.databinding.DialogUpdateWorkstationBinding
 import com.grkj.ui_base.utils.CommonUtils
 import com.grkj.ui_base.utils.extension.tip
 import com.kongzue.dialogx.dialogs.CustomDialog
@@ -22,12 +23,12 @@ class UpdateWorkstationDialog(
     val workstationId: Long,
     val workstationName: String,
     private val onConfirm: (String, Boolean, CustomDialog) -> Unit
-) : OnBindView<CustomDialog>(R.layout.dialog_add_workstation) {
+) : OnBindView<CustomDialog>(R.layout.dialog_update_workstation) {
 
-    private lateinit var binding: DialogAddWorkstationBinding
+    private lateinit var binding: DialogUpdateWorkstationBinding
 
     override fun onBind(dialog: CustomDialog, v: View) {
-        binding = DialogAddWorkstationBinding.bind(v)
+        binding = DialogUpdateWorkstationBinding.bind(v)
         dialog?.isCancelable = false
         dialog?.setMaskColor(CommonUtils.getColor(com.grkj.ui_base.R.attr.scrim))
         binding.workstationNameEt.setText(workstationName)

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

@@ -18,6 +18,7 @@ import com.grkj.ui_base.base.BaseFragment
 import com.grkj.ui_base.dialog.TipDialog
 import com.grkj.ui_base.utils.CommonUtils
 import com.grkj.ui_base.utils.event.LogoutEvent
+import com.grkj.ui_base.utils.event.RefreshAvatarEvent
 import com.kongzue.dialogx.dialogs.PopTip
 import com.sik.sikcore.date.TimeUtils
 import com.sik.sikcore.extension.file
@@ -108,6 +109,7 @@ class UserInfoFragment : BaseFragment<FragmentUserInfoBinding>() {
             )
             viewModel.saveUserAvatar(savePath).observe(this) {
                 getData()
+                RefreshAvatarEvent.sendRefreshAvatarEvent()
             }
         }
         binding.recapture.setDebouncedClickListener {

+ 1 - 1
app/src/main/java/com/grkj/iscs/features/main/viewmodel/hardware_manage/SlotsManageViewModel.kt

@@ -225,7 +225,7 @@ class SlotsManageViewModel @Inject constructor(
                                 mac
                             }"
                         )
-                        keyBean.mac = mac
+                        HardwareMode.getCurrentHardwareMode().updateKeyMac(keyBean.rfid,mac)
                         if (cont.isActive) {
                             cont.resume(mac)
                         }

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

@@ -306,7 +306,9 @@ class JobExecuteViewModel @Inject constructor(
                 lockMap.keys.forEach { lockDockAddr ->
                     lockMap[lockDockAddr]?.let { lockList ->
                         HardwareMode.getCurrentHardwareMode().controlLockBuckle(
-                            true, lockDockAddr as Int?, lockList.map { it.first }.toMutableList()
+                            true,
+                            if (lockDockAddr is Byte) lockDockAddr.toInt() else lockDockAddr as Int?,
+                            lockList.map { it.first }.toMutableList()
                         ) {
                             lockList.forEach { lock ->
                                 HardwareBusinessManager.addDeviceTake(

+ 11 - 8
app/src/main/java/com/grkj/iscs/features/splash/activity/SplashActivity.kt

@@ -30,6 +30,7 @@ import dagger.hilt.android.AndroidEntryPoint
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 import java.util.Locale
 
 @AndroidEntryPoint
@@ -54,16 +55,18 @@ class SplashActivity : BaseActivity<ActivitySplashBinding>() {
                             // 触发构建 + 迁移 + 打开;onOpen 回调里会 DbReadyGate.open()
                             val db = ISCSDatabase.instance
                             //todo 测试用,直接进入,不初始化
-//                            DbReadyGate.await()
+                            DbReadyGate.await()
 //                            withContext(Dispatchers.Main) {
-//                                viewModel.checkSysMenuAndRole().observe(this@SplashActivity) {
-//                                    startActivity(
-//                                        Intent(
-//                                            this@SplashActivity,
-//                                            LoginActivity::class.java
+//                                viewModel.checkPresetData().observe(this@SplashActivity) {
+//                                    viewModel.checkSysMenuAndRole().observe(this@SplashActivity) {
+//                                        startActivity(
+//                                            Intent(
+//                                                this@SplashActivity,
+//                                                LoginActivity::class.java
+//                                            )
 //                                        )
-//                                    )
-//                                    finish()
+//                                        finish()
+//                                    }
 //                                }
 //                            }
                         }

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

@@ -73,11 +73,11 @@
                         android:layout_marginLeft="@dimen/iscs_space_2"
                         android:ellipsize="end"
                         android:gravity="center"
-                        android:maxLength="4"
+                        android:maxLength="13"
                         android:singleLine="true"
                         android:textColor="?attr/colorTextPrimary"
-                        android:textSize="@dimen/iscs_text_md"
-                        tools:text="张三" />
+                        android:textSize="@dimen/iscs_text_xs"
+                        tools:text="Administrator" />
                 </LinearLayout>
             </LinearLayout>
 

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

@@ -73,10 +73,10 @@
                         android:layout_marginLeft="@dimen/iscs_space_2"
                         android:ellipsize="end"
                         android:gravity="center"
-                        android:maxLength="4"
+                        android:maxLength="13"
                         android:singleLine="true"
                         android:textColor="?attr/colorTextPrimary"
-                        android:textSize="@dimen/iscs_text_md"
+                        android:textSize="@dimen/iscs_text_xs"
                         tools:text="张三" />
                 </LinearLayout>
             </LinearLayout>

+ 63 - 41
app/src/main/res/layout/dialog_update_workstation.xml

@@ -22,65 +22,87 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:layout_weight="1"
-                app:i18nKey='@{"workstation_manage_workstation_name"}'
                 android:textColor="?attr/colorTextPrimary"
-                android:textSize="@dimen/iscs_text_md" />
+                android:textSize="@dimen/iscs_text_md"
+                app:i18nKey='@{"workstation_manage_update_workstation"}' />
 
             <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: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/colorBlack" />
+            android:background="?attr/colorDivider" />
 
-        <LinearLayout
-            android:layout_width="match_parent"
+        <com.grkj.ui_base.widget.FormLayout
+            android:layout_width="wrap_content"
             android:layout_height="match_parent"
             android:layout_weight="1"
-            android:orientation="vertical">
+            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">
 
-            <LinearLayout
-                android:layout_width="match_parent"
+
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/workstation_name_tv"
+                android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="@dimen/iscs_space_4"
-                android:gravity="center_vertical"
-                android:orientation="horizontal"
-                android:paddingHorizontal="@dimen/dialog_content_normal_padding_horizontal">
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="label"
+                app:i18nKey='@{"workstation_manage_workstation_name"}'
+                app:markPosition="start"
+                app:required="true" />
 
-                <com.grkj.ui_base.widget.RequiredTextView
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    app:i18nKey='@{"workstation_manage_workstation_name"}'
-                    android:textColor="?attr/colorTextPrimary"
-                    android:textSize="@dimen/iscs_text_md"
-                    app:markPosition="start"
-                    app:required="true" />
+            <EditText
+                android:id="@+id/workstation_name_et"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                android:background="@drawable/bg_common_input"
+                android:maxLines="1"
+                android:minWidth="@dimen/add_to_map_input_min_width"
+                android:paddingHorizontal="@dimen/iscs_space_2"
+                android:paddingVertical="2dp"
+                android:singleLine="true"
+                android:textColor="?attr/colorTextPrimary"
+                android:textSize="@dimen/iscs_text_md"
+                app:formRole="field"
+                app:i18nHint='@{"please_input_workstation_name"}' />
 
-                <EditText
-                    android:id="@+id/workstation_name_et"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    android:layout_marginLeft="@dimen/iscs_space_2"
-                    android:background="@drawable/bg_common_input"
-                    app:i18nHint='@{"please_input_workstation_name"}'
-                    android:maxLines="1"
-                    android:paddingHorizontal="@dimen/iscs_space_2"
-                    android:paddingVertical="2dp"
-                    android:singleLine="true"
-                    android:textColor="?attr/colorTextPrimary"
-                    android:textSize="@dimen/iscs_text_md" />
-            </LinearLayout>
-        </LinearLayout>
+            <com.grkj.ui_base.widget.RequiredTextView
+                android:id="@+id/set_default_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='@{"set_default"}'
+                app:markPosition="start"
+                app:required="false" />
+
+            <com.google.android.material.switchmaterial.SwitchMaterial
+                android:id="@+id/set_default"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_marginLeft="@dimen/iscs_space_2"
+                app:formRole="field" />
+
+        </com.grkj.ui_base.widget.FormLayout>
 
         <LinearLayout
-            android:layout_width="match_parent"
+            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">
@@ -96,9 +118,9 @@
                 android:gravity="center"
                 android:minHeight="@dimen/common_btn_height"
                 android:paddingHorizontal="@dimen/iscs_space_4"
-                app:i18nKey='@{"confirm"}'
                 android:textColor="?attr/colorTextPrimary"
-                android:textSize="@dimen/iscs_text_md" />
+                android:textSize="@dimen/iscs_text_md"
+                app:i18nKey='@{"confirm"}' />
 
             <TextView
                 android:id="@+id/cancel"
@@ -111,9 +133,9 @@
                 android:gravity="center"
                 android:minHeight="@dimen/common_btn_height"
                 android:paddingHorizontal="@dimen/iscs_space_4"
-                app:i18nKey='@{"cancel"}'
                 android:textColor="?attr/colorTextPrimary"
-                android:textSize="@dimen/iscs_text_md" />
+                android:textSize="@dimen/iscs_text_md"
+                app:i18nKey='@{"cancel"}' />
         </LinearLayout>
     </LinearLayout>
 </layout>

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

@@ -27,7 +27,7 @@ interface HardwareDao {
     /**
      * 根据工卡nfc查询用户id
      */
-    @Query("select user_id from is_job_card where card_nfc = :cardNfc")
+    @Query("select user_id from is_job_card where card_nfc = :cardNfc and del_flag = 0")
     fun getUserIdByCardNfc(cardNfc: String): Int?
 
     /**

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

@@ -29,7 +29,7 @@ interface SysMenuDao {
     /**
      * 添加角色菜单关联
      */
-    @Insert(onConflict = OnConflictStrategy.IGNORE)
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
     fun insertRoleMenus(sysRoleMenus: MutableList<SysRoleMenu>)
 
     /**

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

@@ -35,7 +35,7 @@ interface UserDao {
     /**
      * 获取所有指纹数据
      */
-    @Query("select * from sys_user_characteristic where type = 1")
+    @Query("select * from sys_user_characteristic left join sys_user su on su.user_id = sys_user_characteristic.user_id where su.del_flag = 0 and sys_user_characteristic.type = 1 ")
     fun getFingerprintData(): List<SysUserCharacteristicDo>
 
     /**
@@ -47,7 +47,7 @@ interface UserDao {
     /**
      * 获取所有人脸数据
      */
-    @Query("select * from sys_user_characteristic where type = 2")
+    @Query("select * from sys_user_characteristic left join sys_user su on su.user_id = sys_user_characteristic.user_id where su.del_flag = 0 and sys_user_characteristic.type = 2")
     fun getFaceData(): List<SysUserCharacteristicDo>
 
     /**

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

@@ -69,6 +69,10 @@ object EventConstants {
      * 提示代码
      */
     const val EVENT_TOAST_CODE: Int = 100_000_013
+    /**
+     * 刷新头像
+     */
+    const val EVENT_REFRESH_AVATAR_CODE: Int = 100_000_014
 
     //---------------------------作业票------------------------
     const val EVENT_GET_TICKET_STATUS: Int = 100_001_001

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

@@ -21,6 +21,10 @@ open class DockData {
         var rfid: String = ""
         var isReady: Boolean = false
         var newHardware: Boolean = false
+        override fun toString(): String {
+            return "DeviceBean(addr=$addr, idx=$idx, isExist=$isExist, row=$row, type=$type, rfid='$rfid', isReady=$isReady, newHardware=$newHardware)"
+        }
+
     }
 
     /**
@@ -32,6 +36,10 @@ open class DockData {
         class KeyBean : DeviceBean() {
             var mac: String = ""
         }
+
+        override fun toString(): String {
+            return "KeyDock(keyData=$keyData)"
+        }
     }
 
     /**

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

@@ -172,4 +172,9 @@ interface IHardwareHelper {
      * 获取基座数据
      */
     fun getDockData(): List<DockData>
+
+    /**
+     * 更新钥匙mac
+     */
+    fun updateKeyMac(rfid: String, mac: String)
 }

+ 6 - 1
data/src/main/java/com/grkj/data/hardware/can/CanHardwareHelper.kt

@@ -40,7 +40,8 @@ class CanHardwareHelper : IHardwareHelper {
 
     override fun getExistsKeyMac(): List<String> {
         val keyDevices = CanHelper.getDeviceByDeviceType(DeviceConst.DEVICE_TYPE_KEY)
-        return keyDevices.flatMap { it.value }.filterIsInstance<DeviceModel.DeviceKey>().filter { it.isExist }
+        return keyDevices.flatMap { it.value }.filterIsInstance<DeviceModel.DeviceKey>()
+            .filter { it.isExist }
             .map { it.mac }
     }
 
@@ -70,6 +71,10 @@ class CanHardwareHelper : IHardwareHelper {
         return getKeyDockData() + getLockDockData()
     }
 
+    override fun updateKeyMac(rfid: String, mac: String) {
+        CanHelper.getKeyByRfid(rfid)?.mac = mac
+    }
+
     override fun controlKeyBuckle(
         isOpen: Boolean,
         mac: String,

+ 38 - 21
data/src/main/java/com/grkj/data/hardware/can/CanHelper.kt

@@ -224,29 +224,46 @@ object CanHelper {
         exceptionSlots: MutableList<CabinetSlotsRecord>,
         exceptionLocks: MutableList<String>
     ): MutableMap<Any, MutableList<Pair<Int, String>>> {
+
         val map = mutableMapOf<Any, MutableList<Pair<Int, String>>>()
-        logger.info("需要的锁具:${needLockCount}")
-        if (needLockCount == 0) {
-            return map
-        }
-        val lockDockList = deviceData.flatMap { it.value }.filterIsInstance<DeviceModel.DeviceKey>()
-        lockDockList.sortedBy { it.nodeId }
-        var provideCount = 0
-        logger.info("锁具基座列表:${lockDockList}")
-        logger.info("异常锁rfid:${exceptionLocks}")
-        logger.info("异常锁仓位:${exceptionSlots.joinToString(",") { "${it.row},${it.col}" }}")
-        if (provideCount >= needLockCount) return map
-        logger.info("锁具信息:${lockDockList}")
-        val validLocks = lockDockList.filter { it.rfid !in exceptionLocks }.filter { lockBean ->
-            lockBean.isExist && lockBean.id !in exceptionSlots.filter { lockBean.nodeId == it.row?.toInt() }
-                .map { (it.col?.toInt() ?: 1) - 1 }
-        }
-        val toTake = (needLockCount - provideCount).coerceAtMost(validLocks.size)
-        if (toTake > 0) {
-            validLocks.take(toTake).groupBy { it.nodeId }
-                .map { it.key to it.value.map { it.id to it.rfid } }.toMutableList()
+        logger.info("需要的锁具: $needLockCount")
+        if (needLockCount <= 0) return map
+
+        // 1) 拿数据 + 排序(要接收返回值)
+        val lockDockList = deviceData.values
+            .flatten()
+            .filterIsInstance<DeviceModel.DeviceKey>()
+            .sortedBy { it.nodeId }
+
+        logger.info("锁具基座列表: $lockDockList")
+        logger.info("异常锁rfid: $exceptionLocks")
+        logger.info("异常锁仓位: ${exceptionSlots.joinToString(",") { "${it.row},${it.col}" }}")
+
+        // 2) 预先把“该 nodeId 下哪些 id(列) 被禁用”整理成 Map,过滤更清晰
+        val blockedIdsByNode: Map<Int, Set<Int>> =
+            exceptionSlots
+                .filter { it.row != null }
+                .groupBy(
+                    keySelector = { it.row!!.toInt() },                 // nodeId
+                    valueTransform = { (it.col?.toInt() ?: 1) - 1 }      // 被占/异常的列 -> 对应 lock.id
+                )
+                .mapValues { (_, cols) -> cols.toSet() }
+
+        // 3) 过滤合法锁
+        val validLocks = lockDockList.filter { l ->
+            l.isExist &&
+                    l.rfid !in exceptionLocks &&
+                    blockedIdsByNode[l.nodeId]?.contains(l.id) != true
         }
-        logger.info("待取锁:${map}")
+
+        // 4) 取够数量并分组 -> 显式写回 map
+        val selected = validLocks.take(needLockCount)
+        val grouped = selected.groupBy { it.nodeId }
+            .mapValues { (_, list) -> list.map { it.id to it.rfid }.toMutableList() }
+
+        map.putAll(grouped)
+
+        logger.info("待取锁: $map")
         return map
     }
 

+ 9 - 0
data/src/main/java/com/grkj/data/hardware/modbus/ModBusHardwareHelper.kt

@@ -4,11 +4,14 @@ import com.grkj.data.hardware.DockData
 import com.grkj.data.hardware.IHardwareHelper
 import com.grkj.data.model.res.CabinetSlotsRecord
 import com.grkj.shared.utils.i18n.I18nManager
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
 
 /**
  * modbus硬件操作帮助类
  */
 class ModBusHardwareHelper : IHardwareHelper {
+    private val logger: Logger = LoggerFactory.getLogger(ModBusHardwareHelper::class.java)
     override fun getKeyMacByRfid(rfid: String): String? {
         return ModBusController.getKeyByRfid(
             rfid
@@ -64,8 +67,10 @@ class ModBusHardwareHelper : IHardwareHelper {
     override fun getKeyDockData(): List<DockData.KeyDock> {
         val dockData =
             ModBusController.dockList.filter { it.type == DeviceConst.DOCK_TYPE_LOCK || it.type == DeviceConst.DOCK_TYPE_KEY || it.type == DeviceConst.DOCK_TYPE_PORTABLE }
+        logger.info("钥匙基座数据:${dockData}")
         return dockData.filter { it.type == DeviceConst.DOCK_TYPE_KEY }.map {
             DockData.KeyDock().apply {
+                logger.info("钥匙数据:${it.deviceList},${it.deviceList.filterIsInstance<DockBean.KeyBean>()}")
                 keyData.addAll(
                     it.deviceList.filterIsInstance<DockBean.KeyBean>().map {
                         DockData.KeyDock.KeyBean().apply {
@@ -83,6 +88,10 @@ class ModBusHardwareHelper : IHardwareHelper {
         }
     }
 
+    override fun updateKeyMac(rfid: String, mac: String) {
+        ModBusController.getKeyByRfid(rfid)?.mac = mac
+    }
+
     override fun getDockData(): List<DockData> {
         return ModBusController.dockList.mapNotNull { dock ->
             when (dock.type) {

+ 1 - 11
ui-base/src/main/java/com/grkj/ui_base/base/BaseFragment.kt

@@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory
 /**
  * BaseFragment: 支持 ViewBinding, EventBus, 权限管理, 串口 & 蓝牙, 以及 Navigation 切换
  */
-abstract class BaseFragment<V : ViewDataBinding> : Fragment(), CustomAdapt {
+abstract class BaseFragment<V : ViewDataBinding> : Fragment() {
     protected val logger: Logger = LoggerFactory.getLogger(this::class.java)
     protected lateinit var binding: V
     private var isFirstLoad: Boolean = true
@@ -137,16 +137,6 @@ abstract class BaseFragment<V : ViewDataBinding> : Fragment(), CustomAdapt {
         return resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT
     }
 
-    // 是否以“宽度”为基准适配,false 则按“高度”来算缩放比例
-    override fun isBaseOnWidth(): Boolean {
-        return isPortrait()
-    }
-
-    // 设计图的尺寸 dp。竖屏时用 600dp 作为基准宽度;横屏时用 1024dp 作为基准高度
-    override fun getSizeInDp(): Float {
-        return ISCSConfig.designSize
-    }
-
     /** 获取布局资源 ID */
     @LayoutRes
     protected abstract fun getLayoutId(): Int

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

@@ -0,0 +1,25 @@
+package com.grkj.ui_base.utils.event
+
+import com.grkj.data.data.EventConstants
+import com.grkj.shared.model.EventBean
+import com.grkj.shared.utils.event.EventHelper
+
+/**
+ * 刷新头像
+ */
+class RefreshAvatarEvent() {
+
+    companion object {
+        /**
+         * 发送刷新头像事件
+         */
+        @JvmStatic
+        fun sendRefreshAvatarEvent() {
+            val logoutEvent = RefreshAvatarEvent()
+            val logoutEventBean = EventBean(
+                EventConstants.EVENT_REFRESH_AVATAR_CODE, logoutEvent
+            )
+            EventHelper.sendEvent(logoutEventBean)
+        }
+    }
+}

+ 2 - 7
ui-base/src/main/java/com/grkj/ui_base/utils/extension/Context.kt

@@ -9,6 +9,7 @@ import androidx.core.app.ActivityCompat
 import androidx.core.content.ContextCompat
 import androidx.lifecycle.Observer
 import com.grkj.ui_base.utils.NetManager
+import com.sik.sikcore.device.DeviceUtils
 import java.util.Locale
 
 /**
@@ -26,13 +27,7 @@ fun Context.removeNetObserver(observer: Observer<Boolean>) {
 
 @SuppressLint("MissingPermission")
 fun Context.serialNo(): String {
-    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
-        && ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE)
-        == PackageManager.PERMISSION_GRANTED
-    ) {
-        return Build.getSerial().uppercase(Locale.ROOT)
-    }
-    return Build.SERIAL.uppercase(Locale.ROOT)
+    return DeviceUtils.getDeviceId(length = 8)
 }
 
 /**

+ 2 - 2
ui-base/src/main/java/com/grkj/ui_base/widget/CustomNavBar.kt

@@ -80,8 +80,8 @@ class CustomNavBar @JvmOverloads constructor(
         setWillNotDraw(false) // ★ 需要绘制分割线/选中态
         isClickable = true
         isFocusable = true
-        val isLand = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
-        AutoSize.autoConvertDensity(context as Activity, ISCSConfig.designSize, !isLand)
+//        val isLand = resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
+//        AutoSize.autoConvertDensity(context as Activity, ISCSConfig.designSize, !isLand)
         context.obtainStyledAttributes(attrs, R.styleable.CustomNavBar, defStyle, 0).apply {
             navOrientation = getInt(R.styleable.CustomNavBar_navOrientation, 0)
             iconSize =