|
1 | | -# winjs-plugin-example |
| 1 | +# @winner-fed/plugin-access |
2 | 2 |
|
3 | | -Example plugin for WinJS. |
| 3 | +适配 access(权限)的 WinJS 插件,适用于 Vue3。 |
4 | 4 |
|
5 | 5 | <p> |
6 | | - <a href="https://npmjs.com/package/winjs-plugin-example"> |
7 | | - <img src="https://img.shields.io/npm/v/winjs-plugin-example?style=flat-square&colorA=564341&colorB=EDED91" alt="npm version" /> |
| 6 | + <a href="https://npmjs.com/package/@winner-fed/plugin-access"> |
| 7 | + <img src="https://img.shields.io/npm/v/@winner-fed/plugin-access?style=flat-square&colorA=564341&colorB=EDED91" alt="npm version" /> |
8 | 8 | </a> |
9 | 9 | <img src="https://img.shields.io/badge/License-MIT-blue.svg?style=flat-square&colorA=564341&colorB=EDED91" alt="license" /> |
10 | | - <a href="https://npmcharts.com/compare/winjs-plugin-example?minimal=true"><img src="https://img.shields.io/npm/dm/winjs-plugin-example.svg?style=flat-square&colorA=564341&colorB=EDED91" alt="downloads" /></a> |
| 10 | + <a href="https://npmcharts.com/compare/@winner-fed/plugin-access?minimal=true"><img src="https://img.shields.io/npm/dm/@winner-fed/plugin-access.svg?style=flat-square&colorA=564341&colorB=EDED91" alt="downloads" /></a> |
11 | 11 | </p> |
12 | 12 |
|
13 | | -## Usage |
| 13 | +## 功能特性 |
14 | 14 |
|
15 | | -Install: |
| 15 | +- 🔐 基于角色的权限管理系统 (RBAC) |
| 16 | +- 🚀 支持动态设置角色和权限 |
| 17 | +- 🛡️ 提供路由级别的权限控制 |
| 18 | +- 🎯 提供组件级别的权限控制(指令和组件) |
| 19 | +- ⚡ 支持同步和异步权限检查 |
| 20 | +- 🔍 支持路径模式匹配(支持通配符) |
| 21 | +- 📦 开箱即用,零配置启动 |
| 22 | +- 🔧 可配置的权限控制处理器 |
| 23 | + |
| 24 | +## 安装 |
16 | 25 |
|
17 | 26 | ```bash |
18 | | -npm add winjs-plugin-example -D |
| 27 | +npm install @winner-fed/plugin-access |
19 | 28 | ``` |
20 | 29 |
|
21 | | -Add plugin to your `.winrc.ts`: |
| 30 | +## 基本配置 |
22 | 31 |
|
23 | | -```ts |
24 | | -// .winrc.ts |
25 | | -export default { |
26 | | - plugins: ['winjs-plugin-example'], |
27 | | - // 开启配置 |
28 | | - example: {} |
29 | | -}; |
| 32 | +在 `.winrc.ts` 中配置插件: |
| 33 | + |
| 34 | +```typescript |
| 35 | +import { defineConfig } from 'win'; |
| 36 | + |
| 37 | +export default defineConfig({ |
| 38 | + plugins: [require.resolve('@winner-fed/plugin-access')], |
| 39 | + access: { |
| 40 | + roles: { |
| 41 | + admin: ['/', '/admin', '/users/*'], |
| 42 | + normal: ['/normal', '/profile'], |
| 43 | + guest: ['/login', '/register'] |
| 44 | + } |
| 45 | + } |
| 46 | +}); |
30 | 47 | ``` |
31 | 48 |
|
32 | | -## Options |
| 49 | +## 使用方法 |
33 | 50 |
|
34 | | -### foo |
| 51 | +### 1. 路由配置 |
35 | 52 |
|
36 | | -Some description. |
| 53 | +```typescript |
| 54 | +// src/app.ts |
| 55 | +import { access as accessApi } from 'winjs'; |
37 | 56 |
|
38 | | -- Type: `string` |
39 | | -- Default: `undefined` |
40 | | -- Example: |
| 57 | +// 设置默认角色 |
| 58 | +accessApi.setRole('admin'); |
41 | 59 |
|
42 | | -```js |
43 | | -export default { |
44 | | - plugins: ['winjs-plugin-example'], |
45 | | - // 开启配置 |
46 | | - example: { |
47 | | - foo: 'bar' |
48 | | - } |
| 60 | +export const access = { |
| 61 | + noFoundHandler({ next }) { |
| 62 | + // 处理404页面 |
| 63 | + const accessIds = accessApi.getAccess(); |
| 64 | + if (!accessIds.includes('/404')) { |
| 65 | + accessApi.setAccess(accessIds.concat(['/404'])); |
| 66 | + } |
| 67 | + next('/404'); |
| 68 | + }, |
| 69 | + unAccessHandler({ next }) { |
| 70 | + // 处理无权限访问 |
| 71 | + next('/403'); |
| 72 | + }, |
| 73 | + ignoreAccess: ['/login', '/register'] // 忽略权限检查的路由 |
49 | 74 | }; |
50 | 75 | ``` |
51 | 76 |
|
52 | | -## License |
| 77 | +### 2. 组件中使用 |
| 78 | + |
| 79 | +#### 使用 v-access 指令 |
| 80 | + |
| 81 | +```vue |
| 82 | +<template> |
| 83 | + <div> |
| 84 | + <!-- 只有有权限的用户才能看到 --> |
| 85 | + <div v-access="'/admin'">管理员内容</div> |
| 86 | + |
| 87 | + <!-- 支持动态权限 --> |
| 88 | + <div v-access="dynamicPath">动态内容</div> |
| 89 | + |
| 90 | + <!-- 支持通配符 --> |
| 91 | + <div v-access="'/users/*'">用户管理</div> |
| 92 | + </div> |
| 93 | +</template> |
| 94 | +
|
| 95 | +<script setup> |
| 96 | +import { ref } from 'vue'; |
| 97 | +
|
| 98 | +const dynamicPath = ref('/profile'); |
| 99 | +</script> |
| 100 | +``` |
| 101 | + |
| 102 | +#### 使用 Access 组件 |
| 103 | + |
| 104 | +```vue |
| 105 | +<template> |
| 106 | + <div> |
| 107 | + <Access id="/admin"> |
| 108 | + <template #default> |
| 109 | + <div>管理员专用功能</div> |
| 110 | + </template> |
| 111 | + </Access> |
| 112 | + </div> |
| 113 | +</template> |
| 114 | +``` |
| 115 | + |
| 116 | +#### 使用 useAccess Hook |
| 117 | + |
| 118 | +```vue |
| 119 | +<template> |
| 120 | + <div> |
| 121 | + <div v-if="hasAdminAccess">管理员功能</div> |
| 122 | + <div v-if="hasUserAccess">用户功能</div> |
| 123 | + </div> |
| 124 | +</template> |
| 125 | +
|
| 126 | +<script setup> |
| 127 | +import { useAccess } from 'winjs'; |
| 128 | +
|
| 129 | +const hasAdminAccess = useAccess('/admin'); |
| 130 | +const hasUserAccess = useAccess('/users/*'); |
| 131 | +</script> |
| 132 | +``` |
| 133 | + |
| 134 | +### 3. 编程式权限控制 |
| 135 | + |
| 136 | +```typescript |
| 137 | +import { access } from 'winjs'; |
| 138 | + |
| 139 | +// 设置角色 |
| 140 | +access.setRole('admin'); |
| 141 | + |
| 142 | +// 设置权限 |
| 143 | +access.setAccess(['/admin', '/users']); |
| 144 | + |
| 145 | +// 检查权限(异步) |
| 146 | +const hasAccess = await access.hasAccess('/admin'); |
| 147 | + |
| 148 | +// 检查权限(同步) |
| 149 | +const hasAccessSync = access.hasAccessSync('/admin'); |
| 150 | + |
| 151 | +// 获取当前角色 |
| 152 | +const currentRole = access.getRole(); |
| 153 | + |
| 154 | +// 获取当前权限列表 |
| 155 | +const currentAccess = access.getAccess(); |
| 156 | + |
| 157 | +// 路径匹配 |
| 158 | +const isMatch = access.match('/users/profile', ['/users/*']); |
| 159 | + |
| 160 | +// 设置预设权限 |
| 161 | +access.setPresetAccess(['/public', '/common']); |
| 162 | +``` |
| 163 | + |
| 164 | +## API 文档 |
| 165 | + |
| 166 | +### 配置项 |
| 167 | + |
| 168 | +#### access.roles |
| 169 | +- 类型:`Record<string, string[]>` |
| 170 | +- 描述:角色与权限的映射关系 |
| 171 | + |
| 172 | +#### access.noFoundHandler |
| 173 | +- 类型:`(params: { router, to, from, next }) => void` |
| 174 | +- 描述:404页面处理函数 |
| 175 | + |
| 176 | +#### access.unAccessHandler |
| 177 | +- 类型:`(params: { router, to, from, next }) => void` |
| 178 | +- 描述:无权限访问处理函数 |
| 179 | + |
| 180 | +#### access.ignoreAccess |
| 181 | +- 类型:`string[]` |
| 182 | +- 描述:忽略权限检查的路由列表 |
| 183 | + |
| 184 | +### Access 对象方法 |
| 185 | + |
| 186 | +#### setRole(roleId: string | Promise<string>) |
| 187 | +设置当前用户角色。 |
| 188 | + |
| 189 | +#### getRole(): string |
| 190 | +获取当前用户角色。 |
| 191 | + |
| 192 | +#### setAccess(accessIds: string[] | Promise<string[]>) |
| 193 | +设置当前用户权限列表。 |
| 194 | + |
| 195 | +#### getAccess(): string[] |
| 196 | +获取当前用户权限列表。 |
| 197 | + |
| 198 | +#### hasAccess(path: string): Promise<boolean> |
| 199 | +异步检查是否有指定路径的权限。 |
| 200 | + |
| 201 | +#### hasAccessSync(path: string): boolean |
| 202 | +同步检查是否有指定路径的权限。 |
| 203 | + |
| 204 | +#### match(path: string, accessIds: string[]): boolean |
| 205 | +检查路径是否匹配权限列表。 |
| 206 | + |
| 207 | +#### setPresetAccess(accessIds: string | string[]) |
| 208 | +设置预设权限。 |
| 209 | + |
| 210 | +#### isDataReady(): boolean |
| 211 | +检查权限数据是否准备就绪。 |
| 212 | + |
| 213 | +### useAccess Hook |
| 214 | + |
| 215 | +```typescript |
| 216 | +const hasAccess = useAccess(path: string | Ref<string>): Ref<boolean> |
| 217 | +``` |
| 218 | + |
| 219 | +返回一个响应式的权限状态。 |
| 220 | + |
| 221 | +## 高级用法 |
| 222 | + |
| 223 | +### 1. 异步权限设置 |
| 224 | + |
| 225 | +```typescript |
| 226 | +import { access } from 'winjs'; |
| 227 | + |
| 228 | +// 异步设置角色 |
| 229 | +access.setRole(fetch('/api/user/role').then(res => res.json())); |
| 230 | + |
| 231 | +// 异步设置权限 |
| 232 | +access.setAccess(fetch('/api/user/permissions').then(res => res.json())); |
| 233 | +``` |
| 234 | + |
| 235 | +### 2. 动态权限更新 |
| 236 | + |
| 237 | +```typescript |
| 238 | +import { access } from 'winjs'; |
| 239 | + |
| 240 | +// 用户登录后更新权限 |
| 241 | +function onLogin(userInfo) { |
| 242 | + access.setRole(userInfo.role); |
| 243 | + access.setAccess(userInfo.permissions); |
| 244 | +} |
| 245 | + |
| 246 | +// 用户登出后清空权限 |
| 247 | +function onLogout() { |
| 248 | + access.setRole('guest'); |
| 249 | + access.setAccess([]); |
| 250 | +} |
| 251 | +``` |
| 252 | + |
| 253 | +### 3. 权限通配符 |
| 254 | + |
| 255 | +支持以下通配符模式: |
| 256 | +- `/users/*` - 匹配 `/users/` 下的所有路径 |
| 257 | +- `/admin/*/edit` - 匹配 `/admin/任意内容/edit` 格式的路径 |
| 258 | + |
| 259 | +### 4. 权限组合 |
| 260 | + |
| 261 | +```typescript |
| 262 | +// 预设权限 + 角色权限 + 动态权限 |
| 263 | +access.setPresetAccess(['/public', '/common']); |
| 264 | +access.setRole('admin'); // 自动获取 admin 对应的权限 |
| 265 | +access.setAccess(['/special']); // 额外的动态权限 |
| 266 | +``` |
| 267 | + |
| 268 | +## 许可证 |
53 | 269 |
|
54 | 270 | [MIT](./LICENSE). |
0 commit comments