From e9283ffe6822b12ec5dd2ccf4dc13a369b227a61 Mon Sep 17 00:00:00 2001
From: zhou zhou <3272660260@qq.com>
Date: 星期一, 30 三月 2026 08:32:06 +0800
Subject: [PATCH] chore: sync rsf-design from isolated worktree

---
 rsf-design/src/hooks/core/useAuth.js |  103 +++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 94 insertions(+), 9 deletions(-)

diff --git a/rsf-design/src/hooks/core/useAuth.js b/rsf-design/src/hooks/core/useAuth.js
index 5a4949c..b222810 100644
--- a/rsf-design/src/hooks/core/useAuth.js
+++ b/rsf-design/src/hooks/core/useAuth.js
@@ -2,21 +2,106 @@
 import { storeToRefs } from 'pinia'
 import { useUserStore } from '@/store/modules/user'
 import { useAppMode } from '@/hooks/core/useAppMode'
-const userStore = useUserStore()
+
+function extractRouteAuthMarks(authList) {
+  if (!Array.isArray(authList)) {
+    return []
+  }
+
+  return authList
+    .map((item) => {
+      if (typeof item === 'string') {
+        return item
+      }
+      if (item && typeof item === 'object') {
+        return item.authMark || ''
+      }
+      return ''
+    })
+    .filter(Boolean)
+}
+
+function extractUserButtons(info) {
+  return Array.isArray(info?.buttons) ? info.buttons : []
+}
+
+const BUTTON_ACTION_MAP = {
+  query: 'list',
+  add: 'save',
+  edit: 'update',
+  delete: 'remove'
+}
+
+function resolveRouteResourceKey(routePath) {
+  const pathSegments = String(routePath || '')
+    .split('/')
+    .filter(Boolean)
+
+  const rawSegment = pathSegments[pathSegments.length - 1]
+  if (!rawSegment) {
+    return ''
+  }
+
+  return rawSegment.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase())
+}
+
+function matchesBackendButton(requiredAuth, buttons, routePath) {
+  if (buttons.includes(requiredAuth)) {
+    return true
+  }
+
+  const action = BUTTON_ACTION_MAP[requiredAuth]
+  const resourceKey = resolveRouteResourceKey(routePath)
+  if (!action || !resourceKey) {
+    return false
+  }
+
+  return buttons.some(
+    (item) =>
+      typeof item === 'string' && item.includes(`:${resourceKey}:`) && item.endsWith(`:${action}`)
+  )
+}
+
+function hasAuthPermission(
+  requiredAuth,
+  { authList = [], buttons = [], isBackendMode = false, routePath = '' } = {}
+) {
+  const requiredList = Array.isArray(requiredAuth) ? requiredAuth : [requiredAuth]
+
+  if (!requiredList.length) {
+    return true
+  }
+
+  if (isBackendMode) {
+    return requiredList.some((item) => matchesBackendButton(item, buttons, routePath))
+  }
+
+  return requiredList.some((item) => authList.includes(item))
+}
+
 const useAuth = () => {
+  const userStore = useUserStore()
   const route = useRoute()
-  const { isFrontendMode } = useAppMode()
+  const { isBackendMode } = useAppMode()
   const { info } = storeToRefs(userStore)
-  const frontendAuthList = info.value?.buttons ?? []
-  const backendAuthList = Array.isArray(route.meta.authList) ? route.meta.authList : []
+  const authList = computed(() => extractRouteAuthMarks(route.meta.authList))
+  const buttons = computed(() => extractUserButtons(info.value))
   const hasAuth = (auth) => {
-    if (isFrontendMode.value) {
-      return frontendAuthList.includes(auth)
-    }
-    return backendAuthList.some((item) => item?.authMark === auth)
+    return hasAuthPermission(auth, {
+      authList: authList.value,
+      buttons: buttons.value,
+      isBackendMode: isBackendMode.value,
+      routePath: route.path
+    })
   }
   return {
     hasAuth
   }
 }
-export { useAuth }
+export {
+  extractRouteAuthMarks,
+  extractUserButtons,
+  hasAuthPermission,
+  resolveRouteResourceKey,
+  useAuth
+}

--
Gitblit v1.9.1