library-picturebook-activity/lesingle-creation-frontend/PERMISSION_USAGE.md
En 98e9ad1d28 feat(前端): 测试环境登录框支持自动填充测试账号
通过 VITE_AUTO_FILL_TEST 环境变量控制,在 .env.test 中启用,
使测试环境构建后登录框也能自动填充测试账号,方便测试人员使用。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-11 17:03:22 +08:00

8.3 KiB
Raw Blame History

前端权限控制使用指南

📋 概述

前端权限控制系统已经完善,支持:

  • 自动获取用户信息(刷新页面时)
  • 角色权限检查
  • 权限码检查
  • 路由守卫自动验证

🔧 已修复的问题

1. 认证状态判断

  • 之前: isAuthenticated = !!token && !!user(刷新页面时 user 为 null 导致判断失败)
  • 现在: isAuthenticated = !!token(只要有 token 就认为已认证)

2. 自动获取用户信息

  • 之前: 刷新页面后用户信息丢失
  • 现在:
    • 应用启动时自动获取(main.ts
    • 路由守卫中自动获取(如果 token 存在但 user 不存在)

3. 权限检查

  • 之前: 只检查 requiresAuth,没有角色和权限检查
  • 现在: 支持角色和权限检查

🎯 使用方法

1. 在路由中配置权限

使用角色控制

{
  path: "users",
  name: "SystemUsers",
  component: () => import("@/views/system/users/Index.vue"),
  meta: {
    title: "用户管理",
    requiresAuth: true,
    roles: ["super_admin", "admin"], // 需要 super_admin 或 admin 角色
  },
}

使用权限控制

{
  path: "users",
  name: "SystemUsers",
  component: () => import("@/views/system/users/Index.vue"),
  meta: {
    title: "用户管理",
    requiresAuth: true,
    permissions: ["user:read"], // 需要 user:read 权限
  },
}

同时使用角色和权限

{
  path: "users",
  name: "SystemUsers",
  component: () => import("@/views/system/users/Index.vue"),
  meta: {
    title: "用户管理",
    requiresAuth: true,
    roles: ["admin"], // 需要 admin 角色
    permissions: ["user:read"], // 并且需要 user:read 权限
  },
}

注意: 如果同时设置了 rolespermissions,需要同时满足两者。

2. 在组件中使用权限

<template>
  <div>
    <!-- 根据角色显示 -->
    <a-button v-if="authStore.hasRole('super_admin')" @click="deleteAll">
      删除所有
    </a-button>

    <!-- 根据权限显示 -->
    <a-button v-if="authStore.hasPermission('user:create')" @click="createUser">
      创建用户
    </a-button>

    <!-- 检查多个角色 -->
    <a-button
      v-if="authStore.hasAnyRole(['admin', 'editor'])"
      @click="editUser"
    >
      编辑用户
    </a-button>

    <!-- 检查多个权限 -->
    <a-button
      v-if="authStore.hasAnyPermission(['user:update', 'user:delete'])"
      @click="manageUser"
    >
      管理用户
    </a-button>
  </div>
</template>

<script setup lang="ts">
import { useAuthStore } from "@/stores/auth";

const authStore = useAuthStore();
</script>

3. Store 方法说明

hasRole(role: string): boolean

检查用户是否有指定角色

if (authStore.hasRole("super_admin")) {
  // 用户是超级管理员
}

hasPermission(permission: string): boolean

检查用户是否有指定权限

if (authStore.hasPermission("user:create")) {
  // 用户可以创建用户
}

hasAnyRole(roles: string[]): boolean

检查用户是否有任一指定角色

if (authStore.hasAnyRole(["admin", "editor"])) {
  // 用户是 admin 或 editor
}

hasAnyPermission(permissions: string[]): boolean

检查用户是否有任一指定权限

if (authStore.hasAnyPermission(["user:create", "user:update"])) {
  // 用户可以创建或更新用户
}

🔄 工作流程

1. 应用启动流程

应用启动
  ↓
检查 localStorage 中是否有 token
  ↓
如果有 token调用 fetchUserInfo() 获取用户信息
  ↓
用户信息包含 roles 和 permissions
  ↓
应用挂载完成

2. 路由导航流程

用户访问路由
  ↓
路由守卫 beforeEach
  ↓
检查 token 是否存在
  ↓
如果 token 存在但 user 不存在 → 自动获取用户信息
  ↓
检查 requiresAuth → 是否需要登录
  ↓
检查 roles → 是否有指定角色
  ↓
检查 permissions → 是否有指定权限
  ↓
允许/拒绝访问

3. 登录流程

用户登录
  ↓
调用 authApi.login()
  ↓
返回 token 和 user 信息(包含 roles 和 permissions
  ↓
保存 token 到 localStorage
  ↓
保存 user 到 store
  ↓
跳转到目标页面

📝 路由配置示例

完整的路由配置示例

const routes: RouteRecordRaw[] = [
  {
    path: "/login",
    name: "Login",
    component: () => import("@/views/auth/Login.vue"),
    meta: { requiresAuth: false },
  },
  {
    path: "/",
    component: () => import("@/layouts/BasicLayout.vue"),
    redirect: "/workbench",
    meta: { requiresAuth: true },
    children: [
      {
        path: "workbench",
        name: "workbench",
        component: () => import("@/views/workbench/Index.vue"),
        meta: {
          title: "仪表盘",
          requiresAuth: true,
        },
      },
      {
        path: "system/users",
        name: "SystemUsers",
        component: () => import("@/views/system/users/Index.vue"),
        meta: {
          title: "用户管理",
          requiresAuth: true,
          permissions: ["user:read"], // 需要查看用户权限
        },
      },
      {
        path: "system/roles",
        name: "SystemRoles",
        component: () => import("@/views/system/roles/Index.vue"),
        meta: {
          title: "角色管理",
          requiresAuth: true,
          roles: ["super_admin", "admin"], // 需要管理员角色
        },
      },
    ],
  },
];

🎨 实际应用场景

场景 1: 根据权限显示菜单

<template>
  <a-menu>
    <a-menu-item v-if="authStore.hasPermission('user:read')">
      <router-link to="/system/users">用户管理</router-link>
    </a-menu-item>
    <a-menu-item v-if="authStore.hasRole('admin')">
      <router-link to="/system/roles">角色管理</router-link>
    </a-menu-item>
  </a-menu>
</template>

场景 2: 根据权限显示按钮

<template>
  <a-table>
    <template #action="{ record }">
      <a-space>
        <a-button
          v-if="authStore.hasPermission('user:update')"
          @click="edit(record)"
        >
          编辑
        </a-button>
        <a-button
          v-if="authStore.hasPermission('user:delete')"
          danger
          @click="remove(record)"
        >
          删除
        </a-button>
      </a-space>
    </template>
  </a-table>
</template>

场景 3: 组合权限检查

<template>
  <!-- 需要同时满足角色和权限 -->
  <a-button
    v-if="authStore.hasRole('admin') && authStore.hasPermission('user:delete')"
    @click="deleteAll"
  >
    批量删除
  </a-button>
</template>

⚠️ 注意事项

1. 路由守卫是异步的

路由守卫使用了 async/await,确保在检查权限前用户信息已加载。

2. 权限检查顺序

  1. 认证检查(requiresAuth
  2. 角色检查(roles
  3. 权限检查(permissions

3. 403 页面

如果没有权限,会跳转到 /403 页面。你可以自定义这个页面。

4. 权限更新

如果用户权限发生变化,需要:

  • 重新登录,或
  • 调用 authStore.fetchUserInfo() 刷新用户信息

🔍 调试技巧

1. 查看当前用户信息

import { useAuthStore } from "@/stores/auth";

const authStore = useAuthStore();
console.log("用户信息:", authStore.user);
console.log("角色:", authStore.user?.roles);
console.log("权限:", authStore.user?.permissions);

2. 检查权限

console.log("是否有 admin 角色:", authStore.hasRole("admin"));
console.log("是否有 user:create 权限:", authStore.hasPermission("user:create"));

📚 总结

现在权限控制系统已经完善:

  1. 自动获取用户信息 - 刷新页面不会丢失
  2. 路由权限检查 - 支持角色和权限控制
  3. 组件权限检查 - 可以在组件中使用权限方法
  4. 类型安全 - TypeScript 类型定义完善

可以开始使用权限控制功能了!