npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cimom/vben-effects-access

v5.6.9

Published

权限控制工具包,提供了基于角色和权限的访问控制功能,包括指令、组件和钩子函数,用于控制界面元素的显示和功能的访问。

Readme

@cimom/vben-effects-access

权限控制工具包,提供了基于角色和权限的访问控制功能,包括指令、组件和钩子函数,用于控制界面元素的显示和功能的访问。

安装

npm install @cimom/vben-effects-access

基本使用

权限指令

import { createAccessDirective } from '@cimom/vben-effects-access';
import type { App } from 'vue';

// 在应用启动时注册指令
export function setupDirectives(app: App) {
  // 注册权限指令
  app.directive('permission', createAccessDirective());
}
<template>
  <!-- 基于权限控制按钮显示 -->
  <button v-permission="'user:create'">创建用户</button>

  <!-- 基于角色控制按钮显示 -->
  <button v-permission="{ role: 'admin' }">管理员操作</button>

  <!-- 组合权限和角色 -->
  <button
    v-permission="{ permission: 'user:create', role: 'admin', mode: 'or' }"
  >
    创建用户
  </button>
</template>

权限组件

<template>
  <div>
    <!-- 使用权限控制组件包装内容 -->
    <AccessControl permission="user:create">
      <button>创建用户</button>
    </AccessControl>

    <!-- 使用角色控制 -->
    <AccessControl :role="['admin', 'editor']">
      <div>管理员或编辑可见内容</div>
    </AccessControl>

    <!-- 组合权限和角色,使用 AND 逻辑 -->
    <AccessControl permission="user:create" role="admin" mode="and">
      <button>管理员创建用户</button>
    </AccessControl>

    <!-- 自定义未授权时显示的内容 -->
    <AccessControl permission="user:delete">
      <button>删除用户</button>
      <template #fallback>
        <div class="no-permission">您没有删除权限</div>
      </template>
    </AccessControl>
  </div>
</template>

<script setup lang="ts">
import { AccessControl } from '@cimom/vben-effects-access';
</script>

使用钩子函数

import { useAccess } from '@cimom/vben-effects-access';

// 在组件中使用
const { hasPermission, hasRole, accessible } = useAccess();

// 检查是否有特定权限
if (hasPermission('user:create')) {
  // 有创建用户的权限
}

// 检查是否有特定角色
if (hasRole('admin')) {
  // 是管理员角色
}

// 组合检查权限和角色
const canCreateUser = accessible({
  permission: 'user:create',
  role: 'admin',
  mode: 'or', // 'or' 或 'and'
});

API 参考

权限指令 (v-permission)

指令可以接收以下值:

  • string: 权限字符串,如 'user:create'
  • string[]: 权限字符串数组,如 ['user:create', 'user:edit']
  • object: 权限配置对象,包含以下属性:
    • permission: 权限字符串或数组
    • role: 角色字符串或数组
    • mode: 组合模式,'or'(默认)或 'and'

权限组件 (AccessControl)

| 属性名 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | permission | string \| string[] | - | 权限字符串或数组 | | role | string \| string[] | - | 角色字符串或数组 | | mode | 'or' \| 'and' | 'or' | 组合模式,'or' 表示满足任一条件,'and' 表示必须同时满足所有条件 | | fallback | slot | - | 未授权时显示的内容的插槽 |

钩子函数 (useAccess)

| 函数名 | 参数 | 返回值 | 说明 | | --- | --- | --- | --- | | hasPermission | (permission: string \| string[]) => boolean | boolean | 检查是否有特定权限 | | hasRole | (role: string \| string[]) => boolean | boolean | 检查是否有特定角色 | | accessible | (options: AccessOptions) => boolean | boolean | 组合检查权限和角色 |

类型定义

// 访问控制选项
interface AccessOptions {
  // 权限字符串或数组
  permission?: string | string[];
  // 角色字符串或数组
  role?: string | string[];
  // 组合模式: 'or' 表示满足任一条件,'and' 表示必须同时满足所有条件
  mode?: 'or' | 'and';
}

// 权限指令值类型
type PermissionDirectiveValue = string | string[] | AccessOptions;

高级用法

自定义权限检查逻辑

可以通过 createAccessDirective 函数的参数自定义权限检查逻辑:

import { createAccessDirective } from '@cimom/vben-effects-access';
import type { App } from 'vue';

// 自定义权限检查函数
function customPermissionChecker(permission: string | string[]): boolean {
  // 实现自定义的权限检查逻辑
  return true; // 或 false
}

// 自定义角色检查函数
function customRoleChecker(role: string | string[]): boolean {
  // 实现自定义的角色检查逻辑
  return true; // 或 false
}

// 在应用启动时注册指令
export function setupDirectives(app: App) {
  // 注册权限指令,使用自定义检查逻辑
  app.directive(
    'permission',
    createAccessDirective({
      hasPermission: customPermissionChecker,
      hasRole: customRoleChecker,
    }),
  );
}

与状态管理结合使用

import { useAccess } from '@cimom/vben-effects-access';
import { useAccessStore } from '@cimom/vben-stores';
import { storeToRefs } from 'pinia';
import { computed } from 'vue';

// 自定义钩子函数,结合状态管理
export function useCustomAccess() {
  const accessStore = useAccessStore();
  const { permissions, roles } = storeToRefs(accessStore);

  // 使用标准的 useAccess 钩子
  const { hasPermission, hasRole, accessible } = useAccess();

  // 扩展功能
  const isAdmin = computed(() => hasRole('admin'));
  const canManageUsers = computed(() =>
    hasPermission(['user:create', 'user:edit', 'user:delete']),
  );

  // 返回扩展后的钩子
  return {
    hasPermission,
    hasRole,
    accessible,
    isAdmin,
    canManageUsers,
    permissions,
    roles,
  };
}

动态权限路由

import { useAccess } from '@cimom/vben-effects-access';
import { createRouter, createWebHistory } from 'vue-router';

const { accessible } = useAccess();

// 路由配置
const routes = [
  {
    path: '/dashboard',
    component: () => import('./views/Dashboard.vue'),
    meta: { title: '仪表盘' },
  },
  {
    path: '/users',
    component: () => import('./views/Users.vue'),
    meta: {
      title: '用户管理',
      permission: 'user:view',
      role: 'admin',
    },
  },
  // 其他路由...
];

const router = createRouter({
  history: createWebHistory(),
  routes,
});

// 路由守卫
router.beforeEach((to, from, next) => {
  if (to.meta.permission || to.meta.role) {
    // 检查路由权限
    const hasAccess = accessible({
      permission: to.meta.permission,
      role: to.meta.role,
      mode: 'or',
    });

    if (hasAccess) {
      next();
    } else {
      next('/403'); // 重定向到无权限页面
    }
  } else {
    next();
  }
});

示例

权限菜单

<template>
  <div class="menu">
    <div class="menu-item" @click="navigateTo('/')">首页</div>

    <AccessControl permission="dashboard:view">
      <div class="menu-item" @click="navigateTo('/dashboard')">仪表盘</div>
    </AccessControl>

    <AccessControl permission="user:view">
      <div class="menu-item" @click="navigateTo('/users')">用户管理</div>

      <div class="submenu">
        <AccessControl permission="user:create">
          <div class="menu-item" @click="navigateTo('/users/create')">
            创建用户
          </div>
        </AccessControl>

        <AccessControl permission="user:import">
          <div class="menu-item" @click="navigateTo('/users/import')">
            导入用户
          </div>
        </AccessControl>
      </div>
    </AccessControl>

    <AccessControl role="admin">
      <div class="menu-item" @click="navigateTo('/settings')">系统设置</div>
    </AccessControl>
  </div>
</template>

<script setup lang="ts">
import { AccessControl } from '@cimom/vben-effects-access';
import { useRouter } from 'vue-router';

const router = useRouter();

function navigateTo(path: string) {
  router.push(path);
}
</script>

<style scoped>
.menu {
  width: 200px;
  border-right: 1px solid #eee;
}

.menu-item {
  padding: 12px 16px;
  cursor: pointer;
}

.menu-item:hover {
  background-color: #f5f5f5;
}

.submenu {
  padding-left: 16px;
}

.submenu .menu-item {
  font-size: 14px;
}
</style>

权限按钮组

<template>
  <div class="user-actions">
    <AccessControl permission="user:view">
      <button class="btn view-btn" @click="viewUser">查看</button>
    </AccessControl>

    <AccessControl permission="user:edit">
      <button class="btn edit-btn" @click="editUser">编辑</button>
    </AccessControl>

    <AccessControl permission="user:delete" role="admin" mode="and">
      <button class="btn delete-btn" @click="deleteUser">删除</button>
    </AccessControl>
  </div>
</template>

<script setup lang="ts">
import { AccessControl } from '@cimom/vben-effects-access';

const props = defineProps<{
  userId: string;
}>();

function viewUser() {
  console.log('查看用户:', props.userId);
}

function editUser() {
  console.log('编辑用户:', props.userId);
}

function deleteUser() {
  console.log('删除用户:', props.userId);
}
</script>

<style scoped>
.user-actions {
  display: flex;
  gap: 8px;
}

.btn {
  padding: 6px 12px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.view-btn {
  background-color: #e6f7ff;
  color: #1890ff;
}

.edit-btn {
  background-color: #f6ffed;
  color: #52c41a;
}

.delete-btn {
  background-color: #fff1f0;
  color: #ff4d4f;
}
</style>

权限表单

<template>
  <form @submit.prevent="submitForm" class="user-form">
    <div class="form-item">
      <label>用户名</label>
      <input v-model="form.username" type="text" />
    </div>

    <div class="form-item">
      <label>邮箱</label>
      <input v-model="form.email" type="email" />
    </div>

    <AccessControl permission="user:role:assign" role="admin">
      <div class="form-item">
        <label>角色</label>
        <select v-model="form.role">
          <option value="user">普通用户</option>
          <option value="editor">编辑</option>
          <option value="admin">管理员</option>
        </select>
      </div>
    </AccessControl>

    <div class="form-actions">
      <button type="button" @click="cancel">取消</button>
      <button type="submit" v-permission="'user:edit'">保存</button>
    </div>
  </form>
</template>

<script setup lang="ts">
import { reactive } from 'vue';
import { AccessControl } from '@cimom/vben-effects-access';
import { useAccess } from '@cimom/vben-effects-access';

const { hasPermission } = useAccess();

const form = reactive({
  username: '',
  email: '',
  role: 'user',
});

function submitForm() {
  if (hasPermission('user:edit')) {
    console.log('保存用户:', form);
  }
}

function cancel() {
  console.log('取消编辑');
}
</script>

<style scoped>
.user-form {
  max-width: 500px;
  padding: 16px;
  border: 1px solid #eee;
  border-radius: 8px;
}

.form-item {
  margin-bottom: 16px;
}

.form-item label {
  display: block;
  margin-bottom: 4px;
}

.form-item input,
.form-item select {
  width: 100%;
  padding: 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 16px;
}

.form-actions button {
  padding: 8px 16px;
  border: 1px solid #ddd;
  border-radius: 4px;
  cursor: pointer;
}

.form-actions button[type='submit'] {
  background-color: #1890ff;
  color: white;
  border-color: #1890ff;
}
</style>