Files
2026-10-25 18:52:36 +08:00

47 lines
23 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import{_ as i,o as a,c as t,a2 as n}from"./chunks/framework.B-QBKwc1.js";const o=JSON.parse('{"title":"权限控制","description":"前端权限控制通过 v-perm / v-perms 指令实现按钮级权限控制。","frontmatter":{},"headers":[],"relativePath":"zh/frontend/permission.md","filePath":"zh/frontend/permission.md"}'),h={name:"zh/frontend/permission.md"};function l(k,s,e,p,r,d){return a(),t("div",null,[...s[0]||(s[0]=[n(`<h1 id="_9-7-权限控制" tabindex="-1">9.7 权限控制 <a class="header-anchor" href="#_9-7-权限控制" aria-label="Permalink to &quot;9.7 权限控制&quot;">​</a></h1><div class="tip custom-block"><p class="custom-block-title">概述</p><p>前端权限控制通过 <code>v-perm</code> / <code>v-perms</code> 指令实现按钮级权限控制。<strong>前端权限只是体验层</strong>(隐藏按钮),真正的安全防线是后端 <code>#[Permission]</code> 注解 + <code>auth.jwt</code> 中间件。</p></div><h2 id="权限指令" tabindex="-1">权限指令 <a class="header-anchor" href="#权限指令" aria-label="Permalink to &quot;权限指令&quot;">​</a></h2><h3 id="v-perm-单权限-" tabindex="-1">v-perm(单权限) <a class="header-anchor" href="#v-perm-单权限-" aria-label="Permalink to &quot;v-perm(单权限)&quot;">​</a></h3><div class="language-vue vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">vue</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&lt;</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">template</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&gt;</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> &lt;!-- 只有拥有 sys:user:add 权限的用户才能看到此按钮 --&gt;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> &lt;</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">el-button</span><span style="--shiki-dark:#62E884;--shiki-dark-font-style:italic;--shiki-light:#B07D48;--shiki-light-font-style:inherit;"> v-perm</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">[&#39;sys:user:add&#39;]</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#62E884;--shiki-dark-font-style:italic;--shiki-light:#B07D48;--shiki-light-font-style:inherit;"> type</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">primary</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">新增</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&lt;/</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">el-button</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&gt;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&lt;/</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">template</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&gt;</span></span></code></pre></div><h3 id="v-perms-多权限-满足任一即可-" tabindex="-1">v-perms(多权限,满足任一即可) <a class="header-anchor" href="#v-perms-多权限-满足任一即可-" aria-label="Permalink to &quot;v-perms(多权限,满足任一即可)&quot;">​</a></h3><div class="language-vue vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">vue</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&lt;</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">template</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&gt;</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> &lt;!-- 拥有 sys:user:add 或 sys:user:update 任一权限即可 --&gt;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> &lt;</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">el-button</span><span style="--shiki-dark:#62E884;--shiki-dark-font-style:italic;--shiki-light:#B07D48;--shiki-light-font-style:inherit;"> v-perms</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">=</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">[&#39;sys:user:add&#39;, &#39;sys:user:update&#39;]</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#393A34;">操作</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&lt;/</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">el-button</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&gt;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&lt;/</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">template</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">&gt;</span></span></code></pre></div><h2 id="指令实现" tabindex="-1">指令实现 <a class="header-anchor" href="#指令实现" aria-label="Permalink to &quot;指令实现&quot;">​</a></h2><div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// ui/src/directives/permission.ts</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">import</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;"> usePermission</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> from</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">@/hooks/web/usePermission</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">export</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> const</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;"> perm</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">:</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#2E8F82;--shiki-light-font-style:inherit;"> ObjectDirective</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> mounted</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#FFB86C;--shiki-dark-font-style:italic;--shiki-light:#B07D48;--shiki-light-font-style:inherit;">el</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">:</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#2E8F82;--shiki-light-font-style:inherit;"> HTMLButtonElement</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">, </span><span style="--shiki-dark:#FFB86C;--shiki-dark-font-style:italic;--shiki-light:#B07D48;--shiki-light-font-style:inherit;">binding</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">) {</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> const</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;"> hasSomePermission</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> usePermission</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">();</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> if</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">!</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">hasSomePermission</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">binding</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">.</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">value</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)) {</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;"> el</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">.</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">parentNode</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">.</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">removeChild</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">el</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">); </span><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// 无权限则移除元素(非隐藏)</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> },</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">};</span></span></code></pre></div><div class="tip custom-block"><p class="custom-block-title">移除而非隐藏</p><p>无权限时元素直接从 DOM <strong>移除</strong>(而非 <code>display:none</code>)——避免通过开发者工具看到&quot;隐藏&quot;的敏感操作按钮。</p></div><h2 id="usePermission-Hook" tabindex="-1">usePermission Hook <a class="header-anchor" href="#usePermission-Hook" aria-label="Permalink to &quot;usePermission Hook&quot;">​</a></h2><div class="tip custom-block"><p class="custom-block-title">超级管理员</p><p>用户权限列表包含 <code>*:*:*</code> 时,表示超级管理员,拥有所有权限。</p></div><div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;">// ui/src/hooks/web/usePermission.ts</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;">export</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> function</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> usePermission</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">()</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> const</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;"> userStore</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> useUserStore</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">();</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> /**</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 检查是否拥有指定权限</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> * 超级管理员(permissions 包含 &#39;*:*:*&#39;)拥有所有权限</span></span>
<span class="line"><span style="--shiki-dark:#7B7F8B;--shiki-light:#A0ADA0;"> */</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> function</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;"> hasSomePermission</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#FFB86C;--shiki-dark-font-style:italic;--shiki-light:#B07D48;--shiki-light-font-style:inherit;">permission</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">:</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#2E8F82;--shiki-light-font-style:inherit;"> string</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> |</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#2E8F82;--shiki-light-font-style:inherit;"> string</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">[])</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">:</span><span style="--shiki-dark:#97E1F1;--shiki-dark-font-style:italic;--shiki-light:#2E8F82;--shiki-light-font-style:inherit;"> boolean</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> const</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;"> perms</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;"> userStore</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">.</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">permissions</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> if</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">perms</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">.</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">includes</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">*:*:*</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">))</span><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#BF9EEE;--shiki-light:#1E754F;"> true</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">;</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> if</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> (</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;">typeof</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;"> permission</span><span style="--shiki-dark:#F286C4;--shiki-light:#AB5959;"> ===</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &#39;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">string</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&#39;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> {</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;"> perms</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">.</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">includes</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">permission</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">);</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;"> permission</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">.</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">some</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">((</span><span style="--shiki-dark:#FFB86C;--shiki-dark-font-style:italic;--shiki-light:#B07D48;--shiki-light-font-style:inherit;">p</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">)</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;"> =&gt;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;"> perms</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">.</span><span style="--shiki-dark:#62E884;--shiki-light:#59873A;">includes</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">(</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">p</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">));</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> }</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-dark:#F286C4;--shiki-light:#1E754F;"> return</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> { </span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">hasSomePermission</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">, </span><span style="--shiki-dark:#F6F6F4;--shiki-light:#B07D48;">hasEveryPermission</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> };</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span></span></code></pre></div><h2 id="权限数据来源" tabindex="-1">权限数据来源 <a class="header-anchor" href="#权限数据来源" aria-label="Permalink to &quot;权限数据来源&quot;">​</a></h2><p>用户登录后,<code>GET /api/index/getUser</code> 接口返回权限列表(<code>IndexService::getUser</code> → <code>JwtService::getUserPermissions</code>,与后端鉴权同一缓存):</p><div class="language-json vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">json</span><pre class="shiki shiki-themes dracula-soft vitesse-light vp-code" tabindex="0"><code><span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">{</span></span>
<span class="line"><span style="--shiki-dark:#97E2F2;--shiki-light:#99841877;"> &quot;</span><span style="--shiki-dark:#97E1F1;--shiki-light:#998418;">permissions</span><span style="--shiki-dark:#97E2F2;--shiki-light:#99841877;">&quot;</span><span style="--shiki-dark:#F286C4;--shiki-light:#999999;">:</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> [</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">sys:user:page</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">sys:user:add</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">sys:user:update</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">sys:user:delete</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">,</span></span>
<span class="line"><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;"> &quot;</span><span style="--shiki-dark:#E7EE98;--shiki-light:#B56959;">sys:role:page</span><span style="--shiki-dark:#DEE492;--shiki-light:#B5695977;">&quot;</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;"> ]</span></span>
<span class="line"><span style="--shiki-dark:#F6F6F4;--shiki-light:#999999;">}</span></span></code></pre></div><p>超级管理员返回 <code>[&quot;*:*:*&quot;]</code>,拥有所有权限。</p><h2 id="权限码对应关系" tabindex="-1">权限码对应关系 <a class="header-anchor" href="#权限码对应关系" aria-label="Permalink to &quot;权限码对应关系&quot;">​</a></h2><table tabindex="0"><thead><tr><th>端</th><th>机制</th><th>示例</th></tr></thead><tbody><tr><td>后端</td><td><code>#[Permission(&#39;sys:user:add&#39;, &#39;添加用户&#39;)]</code> 注解 + 中间件反射鉴权</td><td>403 拦截</td></tr><tr><td>前端</td><td><code>v-perm=&quot;[&#39;sys:user:add&#39;]&quot;</code> 指令</td><td>按钮移除</td></tr><tr><td>菜单</td><td><code>laravel_menu.permission</code> 字段(type=1 权限节点)</td><td>角色树勾选</td></tr></tbody></table><p>三处权限码必须<strong>完全一致</strong>(<code>sys:{模块}:{操作}</code>)。</p><h2 id="常见问题" tabindex="-1">常见问题 <a class="header-anchor" href="#常见问题" aria-label="Permalink to &quot;常见问题&quot;">​</a></h2><table tabindex="0"><thead><tr><th>现象</th><th>原因</th><th>处理</th></tr></thead><tbody><tr><td>按钮不显示但接口可调</td><td>角色有权限码但 <code>getUser</code> 未返回</td><td>重新登录刷新权限缓存</td></tr><tr><td>按钮显示但接口 403</td><td>菜单 permission 与注解不一致</td><td>逐字符比对权限码</td></tr><tr><td>超管按钮仍隐藏</td><td>permissions 未含 <code>*:*:*</code></td><td>检查 <code>getUser</code> 返回(uid=1 应为通配)</td></tr><tr><td>修改角色权限后前端无变化</td><td>前端权限缓存在 Store</td><td>重新登录或刷新页面</td></tr></tbody></table><p>详见 <a href="/zh/core/rbac.html">5.4 权限管理(RBAC)</a>。</p>`,23)])])}const g=i(h,[["render",l]]);export{o as __pageData,g as default};