瀏覽代碼

refactor(更新)
- 个人信息的权限管理

周文健 5 月之前
父節點
當前提交
a30e85be99

+ 4 - 1
app/src/main/java/com/grkj/iscs/features/main/activity/MainActivity.kt

@@ -89,7 +89,10 @@ class MainActivity() : BaseActivity<ActivityMainBinding>() {
         // 把 BottomNavigationView 和 NavController 绑定
         setupBottomNavigation(binding.bottomNav, graphMap)
         binding.nickname.setOnClickListener {
-            replaceNavGraph(R.navigation.nav_user_info)
+            if (MainDomainData.permissions.contains(RoleFunctionalPermissionsEnum.USER_INFO_HOME.functionalPermission)) {
+                binding.bottomNav.isVisible = true
+                replaceNavGraph(R.navigation.nav_user_info)
+            }
         }
         // 默认选中第一个
         if (binding.bottomNav.menu.isNotEmpty()) {

+ 1 - 0
app/src/main/java/com/grkj/iscs/features/main/dialog/data_manage/UpdateRoleDialog.kt

@@ -221,6 +221,7 @@ class UpdateRoleDialog(context: Context) : BasePopupWindow(context) {
         binding.roleNameEt.setText(updateRoleDataEntity.roleName)
         binding.roleKeyEt.setText(updateRoleDataEntity.roleKeys)
         binding.activateRb.isChecked = updateRoleDataEntity.status == true
+        this.selectedPermission.clear()
         this.selectedPermission.addAll(getSelectedData(updateRoleDataEntity.functionalPermissions))
         setSelectedData(roleManageFunctionalPermissionsData)
         binding.roleListRv.models = roleManageFunctionalPermissionsData

+ 18 - 15
app/src/main/java/com/grkj/iscs/features/main/fragment/user_info/UserInfoHomeFragment.kt

@@ -9,6 +9,7 @@ import com.drake.brv.utils.linear
 import com.drake.brv.utils.models
 import com.drake.brv.utils.setup
 import com.grkj.data.data.MainDomainData
+import com.grkj.data.enums.RoleFunctionalPermissionsEnum
 import com.grkj.iscs.R
 import com.grkj.iscs.databinding.FragmentUserInfoHomeBinding
 import com.grkj.iscs.databinding.ItemHomeMenuBinding
@@ -23,48 +24,48 @@ import dagger.hilt.android.AndroidEntryPoint
  */
 @AndroidEntryPoint
 class UserInfoHomeFragment : BaseFragment<FragmentUserInfoHomeBinding>() {
-    private val menuData: MutableList<MenuItemEntity> = mutableListOf(
+    private var menuData: MutableList<MenuItemEntity> = mutableListOf(
         MenuItemEntity(
             0,
             R.mipmap.icon_data_manage_menu_user_manage,
-            "个人信息",
-            "user_info:user_info"
+            RoleFunctionalPermissionsEnum.USER_INFO.description,
+            RoleFunctionalPermissionsEnum.USER_INFO.functionalPermission
         ),
         MenuItemEntity(
             1,
             R.mipmap.icon_data_manage_menu_role_manage,
-            "重置密码",
-            "user_info:reset_password"
+            RoleFunctionalPermissionsEnum.RESET_PASSWORD.description,
+            RoleFunctionalPermissionsEnum.RESET_PASSWORD.functionalPermission
         ),
         MenuItemEntity(
             2,
             R.mipmap.icon_data_manage_menu_area_manage,
-            "设置指纹",
-            "user_info:fingerprint_setting"
+            RoleFunctionalPermissionsEnum.FINGERPRINT_SETTING.description,
+            RoleFunctionalPermissionsEnum.FINGERPRINT_SETTING.functionalPermission
         ),
         MenuItemEntity(
             3,
             R.mipmap.icon_data_manage_menu_point_manage,
-            "设置人脸",
-            "user_info:face_setting"
+            RoleFunctionalPermissionsEnum.FACE_SETTING.description,
+            RoleFunctionalPermissionsEnum.FACE_SETTING.functionalPermission
         ),
         MenuItemEntity(
             4,
             R.mipmap.icon_data_manage_menu_point_manage,
-            "设置工卡",
-            "user_info:card_setting"
+            RoleFunctionalPermissionsEnum.CARD_SETTING.description,
+            RoleFunctionalPermissionsEnum.CARD_SETTING.functionalPermission
         ),
         MenuItemEntity(
             5,
             R.mipmap.icon_data_manage_menu_point_manage,
-            "更多设置",
-            "user_info:more_setting"
+            RoleFunctionalPermissionsEnum.MORE_SETTING.description,
+            RoleFunctionalPermissionsEnum.MORE_SETTING.functionalPermission
         ),
         MenuItemEntity(
             6,
             R.mipmap.icon_data_manage_menu_point_manage,
-            "退出登录",
-            "user_info:logout"
+            RoleFunctionalPermissionsEnum.LOGOUT.description,
+            RoleFunctionalPermissionsEnum.LOGOUT.functionalPermission
         ),
     )
 
@@ -90,6 +91,8 @@ class UserInfoHomeFragment : BaseFragment<FragmentUserInfoHomeBinding>() {
 
     override fun initData() {
         super.initData()
+        menuData =
+            menuData.filter { MainDomainData.permissions.contains(it.permission) }.toMutableList()
         binding.homeMenuRv.models = menuData
     }
 

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

@@ -57,7 +57,7 @@ interface RoleDao {
       AND (:permissionCharacters       IS NULL OR trim(:permissionCharacters) = '' OR role_key       LIKE '%' || :permissionCharacters       || '%')
       -- 只有当 status 不为 NULL 才做等值匹配
       AND (:status         IS NULL OR status          = :status)
-      order by role_sort asc
+      order by role_id asc
     LIMIT :size
     OFFSET :offset
   """

+ 21 - 0
data/src/main/java/com/grkj/data/enums/RoleFunctionalPermissionsEnum.kt

@@ -31,6 +31,27 @@ enum class RoleFunctionalPermissionsEnum(
     RFID_MANAGE("hardware_manage:rfid_manage", "RFID管理", 1, listOf()),
     EXCEPTION_REPORT("exception_manage:exception_report", "异常上报", 1, listOf()),
     EXCEPTION_MANAGE("exception_manage:exception_manage", "异常管理", 1, listOf()),
+    USER_INFO("user_info:user_info", "个人信息", 1, listOf()),
+    RESET_PASSWORD("user_info:reset_password", "重置密码", 1, listOf()),
+    FINGERPRINT_SETTING("user_info:fingerprint_setting", "设置指纹", 1, listOf()),
+    FACE_SETTING("user_info:face_setting", "设置人脸", 1, listOf()),
+    CARD_SETTING("user_info:card_setting", "设置工卡", 1, listOf()),
+    MORE_SETTING("user_info:more_setting", "更多设置", 1, listOf()),
+    LOGOUT("user_info:logout", "退出登录", 1, listOf()),
+    USER_INFO_HOME(
+        "user_info",
+        "用户信息",
+        0,
+        listOf(
+            USER_INFO,
+            RESET_PASSWORD,
+            FINGERPRINT_SETTING,
+            FACE_SETTING,
+            CARD_SETTING,
+            MORE_SETTING,
+            LOGOUT
+        )
+    ),
     EXCEPTION_HOME_MANAGE(
         "exception_manage",
         "异常管理", 0,

+ 2 - 1
ui-base/src/main/java/com/grkj/ui_base/utils/modbus/DockBean.kt

@@ -24,6 +24,7 @@ class DockBean(
     var isWorking: Boolean = true,
     var deviceList: MutableList<DeviceBean>
 ) {
+
     companion object {
         private val logger: Logger = LoggerFactory.getLogger(DockBean::class.java)
         val dockConfig: List<DockBean> by lazy {
@@ -514,7 +515,7 @@ class DockBean(
     }
 
     override fun toString(): String {
-        return "DockBean(addr=$addr, type=$type, isWorking=$isWorking, deviceList=$deviceList)"
+        return "DockBean(addr=$addr, row=$row, col=$col, type=$type, isWorking=$isWorking, deviceList=$deviceList)"
     }
 
 

+ 18 - 0
ui-base/src/main/java/com/grkj/ui_base/utils/modbus/ModBusCMDHelper.kt

@@ -1,5 +1,7 @@
 package com.grkj.ui_base.utils.modbus
 
+import com.grkj.ui_base.utils.modbus.FRAME_TYPE_READ
+
 /**
  * 通信指令帮助工具
  */
@@ -157,4 +159,20 @@ object ModBusCMDHelper {
             byteArrayOf(addr[0], addr[1], 0x00, 0x01)
         )
     }
+
+    /**
+     * 生成“读保持寄存器(功能码 0x03)”的读设备类型指令
+     *
+     * @param slaveAddr 从机地址(0x01–0x16)
+     * @return 包含 CRC16 的完整报文
+     */
+    fun generateReadDeviceTypeCmd(): MBFrame {
+        // 0x03=读保持寄存器,起始寄存器 0x0000,读取 1 个寄存器
+        val payload = byteArrayOf(
+            0x00, 0x00,
+            0x00, 0x01
+        )
+        // 假设你在 MBFrame 构造或扩展里会自动给 payload 添加 CRC16
+        return MBFrame(FRAME_TYPE_READ, payload)
+    }
 }

+ 1 - 1
ui-base/src/main/java/com/grkj/ui_base/utils/modbus/ModBusController.kt

@@ -73,7 +73,7 @@ object ModBusController {
     @ExperimentalUnsignedTypes
     fun start() {
         modBusManager?.stop()
-        PortManager.Companion.openCtrlBord()?.let { pm ->
+        PortManager.openCtrlBord()?.let { pm ->
             return@let ModBusManager(pm, true)
         }
             // 间隔 1 秒读一遍桶的状态

+ 108 - 11
ui-base/src/main/java/com/grkj/ui_base/utils/modbus/PortManager.kt

@@ -5,6 +5,7 @@ import com.epton.sdk.SerialPort
 import com.grkj.data.data.MMKVConstants
 import com.kongzue.dialogx.dialogs.PopTip
 import com.sik.sikcore.extension.getMMKVData
+import com.sik.sikcore.extension.saveMMKVData
 import com.sik.sikcore.thread.ThreadUtils
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
@@ -87,6 +88,7 @@ class PortManager private constructor(
          * @param port 串口号,从 0 开始
          * @param bps 波特率,正整数
          */
+        @JvmStatic
         @WorkerThread
         fun open(port: Int, bps: Int, usb: Boolean): PortManager? {
             var blocked = true
@@ -118,6 +120,7 @@ class PortManager private constructor(
          * @param port 串口号,从 0 开始
          * @param bps 波特率,正整数
          */
+        @JvmStatic
         @WorkerThread
         fun open(port: String?, bps: Int): PortManager? {
             if (port == null) {
@@ -148,23 +151,117 @@ class PortManager private constructor(
             }
         }
 
+        /**
+         * 自动扫描所有 ttyS/ttyUSB 口,尝试从机地址 1–0x16,找到第一个正确响应的设备。
+         */
+        @WorkerThread
+        @JvmStatic
+        fun detectSlave(baudRate: Int = 115200): String? {
+            val devs = File("/dev").listFiles { _, name ->
+                name.startsWith("ttyS") || name.startsWith("ttyUSB")
+            }?.map { it.absolutePath } ?: return null
+            val dockConfig = mutableListOf<DockBean>()
+            devs.forEach { path ->
+                try {
+                    dockConfig.clear()
+                    SerialPort(File(path), baudRate, 0).let { sp ->
+                        val input = sp.inputStream
+                        val output = sp.outputStream
+                        val slaveInfo = path
+                        for (addrInt in 1..0x16) {
+                            checkSlave(addrInt, input, output, dockConfig)
+                        }
+                        checkSlave(0xA1, input, output, dockConfig)
+                        if (slaveInfo.isNotEmpty() && dockConfig.isNotEmpty()) {
+                            logger.info("扫描到设备:${slaveInfo},从机:${dockConfig}")
+                            return slaveInfo
+                        }
+                    }
+                } catch (e: Exception) {
+                    logger.warn("扫描 $path 失败:${e.message}")
+                }
+            }
+            return null
+        }
 
         /**
-         * 打开主控板
+         * 检查从机
+         */
+        private fun checkSlave(
+            addrInt: Int,
+            input: InputStream,
+            output: OutputStream,
+            dockConfig: MutableList<DockBean>
+        ) {
+            val addr = addrInt.toByte()
+            val cmdFrame = ModBusCMDHelper.generateReadDeviceTypeCmd()
+            val cmdBytes = cmdFrame.compile(addr)
+
+            output.write(cmdBytes)
+            output.flush()
+            // 简单阻塞读 7 字节
+            val buf = ByteArray(7)
+            var received = 0
+            while (received < buf.size) {
+                val n = input.read(buf, received, buf.size - received)
+                if (n <= 0) break
+                received += n
+            }
+            if (received == buf.size && buf[1] == 0x03.toByte()) {
+                val hi = buf[3].toInt() and 0xFF
+                val lo = buf[4].toInt() and 0xFF
+                val deviceType = (hi shl 8) or lo
+                dockConfig.add(
+                    DockBean(
+                        addr,
+                        addrInt,
+                        dockConfig.count { it.type == deviceType.toByte() } + 1,
+                        deviceType.toByte(), deviceList = mutableListOf()
+                    )
+                )
+            }
+        }
+
+        /**
+         * 打开主控板:先自动检测,从机检测到后保存 MMKV,再打开。
+         */
+        /**
+         * 打开主控板:优先用缓存配置,失败后重新扫描并保存新配置
          */
         @WorkerThread
+        @JvmStatic
         fun openCtrlBord(): PortManager? {
-            // TODO 端口号待定:大屏调试设备-1,小屏调试设备-0
-//            val port = 4
-//            val bps = 115200
-//            val usb = true
-//            LogUtil.i("主控板 port = ${port}, bps = ${bps}, usb = $usb")
-//            return open(port, bps, usb)
-            val port = MMKVConstants.KEY_PORT_CONFIG.getMMKVData("")
-            val bps = 115200
-            logger.info("主控板 port = $port, bps = $bps")
-            return open(port, bps)
+            val baud = 115200
+
+            // 1. 先尝试用上次保存的路径打开
+            val savedPort = MMKVConstants.KEY_PORT_CONFIG.getMMKVData("")
+            if (savedPort.isNotEmpty()) {
+                logger.info("尝试打开上次缓存的串口: $savedPort, bps=$baud")
+                val pm = open(savedPort, baud)
+                if (pm != null) {
+                    return pm
+                } else {
+                    // 打开失败,清掉旧配置,提示一下
+                    logger.warn("缓存的串口 $savedPort 打开失败,准备重新扫描")
+                    MMKVConstants.KEY_PORT_CONFIG.saveMMKVData("")
+                    PopTip.tip("主控板串口已变更,正在重新扫描…")
+                }
+            }
+
+            // 2. 缓存无效或打开失败,走自动扫描
+            val newPort = detectSlave(baud)
+            if (newPort != null) {
+                // 3. 扫描到就保存,下次直接用
+                MMKVConstants.KEY_PORT_CONFIG.saveMMKVData(newPort)
+                logger.info("扫描到新主控板串口: $newPort")
+                return open(newPort, baud)
+            } else {
+                PopTip.tip("未找到从机,请检查硬件连接")
+                return null
+            }
         }
+
+
     }
 
 }