@melt-js/docs-bag 0.0.0-stage → 2026.11.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -2
- package/dist/404.html +22 -0
- package/dist/README.html +33 -0
- package/dist/assets/README.md.BEUJStMI.js +9 -0
- package/dist/assets/README.md.BEUJStMI.lean.js +1 -0
- package/dist/assets/app.CPZ-gtYR.js +1 -0
- package/dist/assets/chunks/@localSearchIndexroot.7ill5i5O.js +1 -0
- package/dist/assets/chunks/VPLocalSearchBox.BVA3GWxn.js +9 -0
- package/dist/assets/chunks/framework.B3lxS50j.js +20 -0
- package/dist/assets/chunks/theme.C4rSMcmz.js +2 -0
- package/dist/assets/guide_complete-host-app.md.CDRzLz0E.js +174 -0
- package/dist/assets/guide_complete-host-app.md.CDRzLz0E.lean.js +1 -0
- package/dist/assets/guide_create-project.md.LRNhDD9x.js +34 -0
- package/dist/assets/guide_create-project.md.LRNhDD9x.lean.js +1 -0
- package/dist/assets/guide_deployment.md.B8aEUabm.js +42 -0
- package/dist/assets/guide_deployment.md.B8aEUabm.lean.js +1 -0
- package/dist/assets/guide_dictionary-system.md.Dy0tQYMR.js +32 -0
- package/dist/assets/guide_dictionary-system.md.Dy0tQYMR.lean.js +1 -0
- package/dist/assets/guide_getting-started.md.B-mobXxi.js +9 -0
- package/dist/assets/guide_getting-started.md.B-mobXxi.lean.js +1 -0
- package/dist/assets/guide_host_auth-and-permissions.md.DWH3Vape.js +139 -0
- package/dist/assets/guide_host_auth-and-permissions.md.DWH3Vape.lean.js +1 -0
- package/dist/assets/guide_host_bootstrap.md.DpbxPIZw.js +87 -0
- package/dist/assets/guide_host_bootstrap.md.DpbxPIZw.lean.js +1 -0
- package/dist/assets/guide_host_routing-and-menu.md.BdCMIOxn.js +103 -0
- package/dist/assets/guide_host_routing-and-menu.md.BdCMIOxn.lean.js +1 -0
- package/dist/assets/guide_introduction.md.1MiCcWyO.js +14 -0
- package/dist/assets/guide_introduction.md.1MiCcWyO.lean.js +1 -0
- package/dist/assets/guide_local-debugging.md.CLJoKVb9.js +15 -0
- package/dist/assets/guide_local-debugging.md.CLJoKVb9.lean.js +1 -0
- package/dist/assets/guide_network-request.md.DDlA8bc0.js +256 -0
- package/dist/assets/guide_network-request.md.DDlA8bc0.lean.js +1 -0
- package/dist/assets/guide_official-plugins_index.md.DPwemCGy.js +15 -0
- package/dist/assets/guide_official-plugins_index.md.DPwemCGy.lean.js +1 -0
- package/dist/assets/guide_official-plugins_install-and-toggle.md.Eq2hWjYn.js +45 -0
- package/dist/assets/guide_official-plugins_install-and-toggle.md.Eq2hWjYn.lean.js +1 -0
- package/dist/assets/guide_official-plugins_shop.md.yBltEx-o.js +49 -0
- package/dist/assets/guide_official-plugins_shop.md.yBltEx-o.lean.js +1 -0
- package/dist/assets/guide_official-plugins_sys-setting.md.BmkuOqGv.js +26 -0
- package/dist/assets/guide_official-plugins_sys-setting.md.BmkuOqGv.lean.js +1 -0
- package/dist/assets/guide_package-core.md.-E29SYy8.js +45 -0
- package/dist/assets/guide_package-core.md.-E29SYy8.lean.js +1 -0
- package/dist/assets/guide_package-ecosystem.md.Di3RcVpF.js +1 -0
- package/dist/assets/guide_package-ecosystem.md.Di3RcVpF.lean.js +1 -0
- package/dist/assets/guide_package-plugin-shop.md.D-xXN7Yg.js +9 -0
- package/dist/assets/guide_package-plugin-shop.md.D-xXN7Yg.lean.js +1 -0
- package/dist/assets/guide_package-plugin-sys-setting.md.Dx3nxHVF.js +9 -0
- package/dist/assets/guide_package-plugin-sys-setting.md.Dx3nxHVF.lean.js +1 -0
- package/dist/assets/guide_package-publishing.md.B7hzTYDH.js +7 -0
- package/dist/assets/guide_package-publishing.md.B7hzTYDH.lean.js +1 -0
- package/dist/assets/guide_package-request.md.DxaD65eM.js +195 -0
- package/dist/assets/guide_package-request.md.DxaD65eM.lean.js +1 -0
- package/dist/assets/guide_package-ui.md.wBZ_iQLb.js +50 -0
- package/dist/assets/guide_package-ui.md.wBZ_iQLb.lean.js +1 -0
- package/dist/assets/guide_permissions.md.B_5re4AR.js +83 -0
- package/dist/assets/guide_permissions.md.B_5re4AR.lean.js +1 -0
- package/dist/assets/guide_plugin-development.md.BQzTwLRr.js +226 -0
- package/dist/assets/guide_plugin-development.md.BQzTwLRr.lean.js +1 -0
- package/dist/assets/guide_plugins_admin-plugin.md.d_XC5U-4.js +52 -0
- package/dist/assets/guide_plugins_admin-plugin.md.d_XC5U-4.lean.js +1 -0
- package/dist/assets/guide_plugins_create-plugin.md.C-wDq4Un.js +109 -0
- package/dist/assets/guide_plugins_create-plugin.md.C-wDq4Un.lean.js +1 -0
- package/dist/assets/guide_plugins_debug-and-publish.md.CeTc01QN.js +92 -0
- package/dist/assets/guide_plugins_debug-and-publish.md.CeTc01QN.lean.js +1 -0
- package/dist/assets/guide_plugins_lifecycle-and-dependencies.md.BtwKS5jY.js +45 -0
- package/dist/assets/guide_plugins_lifecycle-and-dependencies.md.BtwKS5jY.lean.js +1 -0
- package/dist/assets/guide_plugins_permissions-and-settings.md.05CsB1I6.js +78 -0
- package/dist/assets/guide_plugins_permissions-and-settings.md.05CsB1I6.lean.js +1 -0
- package/dist/assets/guide_plugins_routes-menus-locales.md.B2dzO2DN.js +100 -0
- package/dist/assets/guide_plugins_routes-menus-locales.md.B2dzO2DN.lean.js +1 -0
- package/dist/assets/guide_pro-form.md.DbSHbrMu.js +116 -0
- package/dist/assets/guide_pro-form.md.DbSHbrMu.lean.js +1 -0
- package/dist/assets/guide_pro-table.md.DBuYQYgG.js +54 -0
- package/dist/assets/guide_pro-table.md.DBuYQYgG.lean.js +1 -0
- package/dist/assets/guide_request-and-components.md.BQXI_ZxY.js +175 -0
- package/dist/assets/guide_request-and-components.md.BQXI_ZxY.lean.js +1 -0
- package/dist/assets/guide_routing-and-menu.md.-zrm3BV9.js +74 -0
- package/dist/assets/guide_routing-and-menu.md.-zrm3BV9.lean.js +1 -0
- package/dist/assets/guide_theme-tokens.md.DXpbrOjS.js +53 -0
- package/dist/assets/guide_theme-tokens.md.DXpbrOjS.lean.js +1 -0
- package/dist/assets/index.md.BUgI8r98.js +1 -0
- package/dist/assets/index.md.BUgI8r98.lean.js +1 -0
- package/dist/assets/inter-italic-cyrillic-ext.r48I6akx.woff2 +0 -0
- package/dist/assets/inter-italic-cyrillic.By2_1cv3.woff2 +0 -0
- package/dist/assets/inter-italic-greek-ext.1u6EdAuj.woff2 +0 -0
- package/dist/assets/inter-italic-greek.DJ8dCoTZ.woff2 +0 -0
- package/dist/assets/inter-italic-latin-ext.CN1xVJS-.woff2 +0 -0
- package/dist/assets/inter-italic-latin.C2AdPX0b.woff2 +0 -0
- package/dist/assets/inter-italic-vietnamese.BSbpV94h.woff2 +0 -0
- package/dist/assets/inter-roman-cyrillic-ext.BBPuwvHQ.woff2 +0 -0
- package/dist/assets/inter-roman-cyrillic.C5lxZ8CY.woff2 +0 -0
- package/dist/assets/inter-roman-greek-ext.CqjqNYQ-.woff2 +0 -0
- package/dist/assets/inter-roman-greek.BBVDIX6e.woff2 +0 -0
- package/dist/assets/inter-roman-latin-ext.4ZJIpNVo.woff2 +0 -0
- package/dist/assets/inter-roman-latin.Di8DUHzh.woff2 +0 -0
- package/dist/assets/inter-roman-vietnamese.BjW4sHH5.woff2 +0 -0
- package/dist/assets/style.0snOvk0r.css +1 -0
- package/dist/guide/complete-host-app.html +198 -0
- package/dist/guide/create-project.html +58 -0
- package/dist/guide/deployment.html +66 -0
- package/dist/guide/dictionary-system.html +56 -0
- package/dist/guide/getting-started.html +33 -0
- package/dist/guide/host/auth-and-permissions.html +163 -0
- package/dist/guide/host/bootstrap.html +111 -0
- package/dist/guide/host/routing-and-menu.html +127 -0
- package/dist/guide/introduction.html +38 -0
- package/dist/guide/local-debugging.html +39 -0
- package/dist/guide/network-request.html +280 -0
- package/dist/guide/official-plugins/index.html +39 -0
- package/dist/guide/official-plugins/install-and-toggle.html +69 -0
- package/dist/guide/official-plugins/shop.html +73 -0
- package/dist/guide/official-plugins/sys-setting.html +50 -0
- package/dist/guide/package-core.html +69 -0
- package/dist/guide/package-ecosystem.html +25 -0
- package/dist/guide/package-plugin-shop.html +33 -0
- package/dist/guide/package-plugin-sys-setting.html +33 -0
- package/dist/guide/package-publishing.html +31 -0
- package/dist/guide/package-request.html +219 -0
- package/dist/guide/package-ui.html +74 -0
- package/dist/guide/permissions.html +107 -0
- package/dist/guide/plugin-development.html +250 -0
- package/dist/guide/plugins/admin-plugin.html +76 -0
- package/dist/guide/plugins/create-plugin.html +133 -0
- package/dist/guide/plugins/debug-and-publish.html +116 -0
- package/dist/guide/plugins/lifecycle-and-dependencies.html +69 -0
- package/dist/guide/plugins/permissions-and-settings.html +102 -0
- package/dist/guide/plugins/routes-menus-locales.html +124 -0
- package/dist/guide/pro-form.html +140 -0
- package/dist/guide/pro-table.html +78 -0
- package/dist/guide/request-and-components.html +199 -0
- package/dist/guide/routing-and-menu.html +98 -0
- package/dist/guide/theme-tokens.html +77 -0
- package/dist/hashmap.json +1 -0
- package/dist/index.html +25 -0
- package/dist/logo.png +0 -0
- package/dist/logo.svg +1 -0
- package/dist/vp-icons.css +1 -0
- package/dist/wechat-group-qr.png +0 -0
- package/package.json +24 -4
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en-US" dir="ltr">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<title>登录与权限 | Vue-Bag-Admin</title>
|
|
7
|
+
<meta name="description" content="基于 Vue3 + Vite6 + Naive UI + Pinia + Strapi5 的中后台系统框架">
|
|
8
|
+
<meta name="generator" content="VitePress v1.6.4">
|
|
9
|
+
<link rel="preload stylesheet" href="/@melt-js/docs-bag@2026.11.7/assets/style.0snOvk0r.css" as="style">
|
|
10
|
+
<link rel="preload stylesheet" href="/@melt-js/docs-bag@2026.11.7/vp-icons.css" as="style">
|
|
11
|
+
|
|
12
|
+
<script type="module" src="/@melt-js/docs-bag@2026.11.7/assets/app.CPZ-gtYR.js"></script>
|
|
13
|
+
<link rel="preload" href="/@melt-js/docs-bag@2026.11.7/assets/inter-roman-latin.Di8DUHzh.woff2" as="font" type="font/woff2" crossorigin="">
|
|
14
|
+
<link rel="modulepreload" href="/@melt-js/docs-bag@2026.11.7/assets/chunks/theme.C4rSMcmz.js">
|
|
15
|
+
<link rel="modulepreload" href="/@melt-js/docs-bag@2026.11.7/assets/chunks/framework.B3lxS50j.js">
|
|
16
|
+
<link rel="modulepreload" href="/@melt-js/docs-bag@2026.11.7/assets/guide_host_auth-and-permissions.md.DWH3Vape.lean.js">
|
|
17
|
+
<script id="check-dark-mode">(()=>{const e=localStorage.getItem("vitepress-theme-appearance")||"dark",a=window.matchMedia("(prefers-color-scheme: dark)").matches;(!e||e==="auto"?a:e==="dark")&&document.documentElement.classList.add("dark")})();</script>
|
|
18
|
+
<script id="check-mac-os">document.documentElement.classList.toggle("mac",/Mac|iPhone|iPod|iPad/i.test(navigator.platform));</script>
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
<div id="app"><div class="Layout" data-v-5d98c3a5><!--[--><!--]--><!--[--><span tabindex="-1" data-v-0b0ada53></span><a href="#VPContent" class="VPSkipLink visually-hidden" data-v-0b0ada53>Skip to content</a><!--]--><!----><header class="VPNav" data-v-5d98c3a5 data-v-ae24b3ad><div class="VPNavBar" data-v-ae24b3ad data-v-6aa21345><div class="wrapper" data-v-6aa21345><div class="container" data-v-6aa21345><div class="title" data-v-6aa21345><div class="VPNavBarTitle has-sidebar" data-v-6aa21345 data-v-1168a8e4><a class="title" href="/@melt-js/docs-bag@2026.11.7/" data-v-1168a8e4><!--[--><!--]--><!--[--><img class="VPImage logo" src="/@melt-js/docs-bag@2026.11.7/logo.png" alt data-v-8426fc1a><!--]--><span data-v-1168a8e4>Vue-Bag-Admin</span><!--[--><!--]--></a></div></div><div class="content" data-v-6aa21345><div class="content-body" data-v-6aa21345><!--[--><!--]--><div class="VPNavBarSearch search" data-v-6aa21345><!--[--><!----><div id="local-search"><button type="button" class="DocSearch DocSearch-Button" aria-label="Search"><span class="DocSearch-Button-Container"><span class="vp-icon DocSearch-Search-Icon"></span><span class="DocSearch-Button-Placeholder">Search</span></span><span class="DocSearch-Button-Keys"><kbd class="DocSearch-Button-Key"></kbd><kbd class="DocSearch-Button-Key">K</kbd></span></button></div><!--]--></div><nav aria-labelledby="main-nav-aria-label" class="VPNavBarMenu menu" data-v-6aa21345 data-v-dc692963><span id="main-nav-aria-label" class="visually-hidden" data-v-dc692963> Main Navigation </span><!--[--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/@melt-js/docs-bag@2026.11.7/" tabindex="0" data-v-dc692963 data-v-e56f3d57><!--[--><span data-v-e56f3d57>首页</span><!--]--></a><!--]--><!--[--><a class="VPLink link VPNavBarMenuLink" href="/@melt-js/docs-bag@2026.11.7/guide/introduction.html" tabindex="0" data-v-dc692963 data-v-e56f3d57><!--[--><span data-v-e56f3d57>指南</span><!--]--></a><!--]--><!--[--><a class="VPLink link vp-external-link-icon VPNavBarMenuLink" href="https://hangjob.github.io/vue-bag-admin/" target="_blank" rel="noreferrer" tabindex="0" data-v-dc692963 data-v-e56f3d57><!--[--><span data-v-e56f3d57>在线预览</span><!--]--></a><!--]--><!--[--><div class="VPFlyout VPNavBarMenuGroup" data-v-dc692963 data-v-cf11d7a2><button type="button" class="button" aria-haspopup="true" aria-expanded="false" data-v-cf11d7a2><span class="text" data-v-cf11d7a2><!----><span data-v-cf11d7a2>社区</span><span class="vpi-chevron-down text-icon" data-v-cf11d7a2></span></span></button><div class="menu" data-v-cf11d7a2><div class="VPMenu" data-v-cf11d7a2 data-v-b98bc113><div class="items" data-v-b98bc113><!--[--><!--[--><div class="VPMenuLink" data-v-b98bc113 data-v-35975db6><a class="VPLink link" href="/@melt-js/docs-bag@2026.11.7/#community" data-v-35975db6><!--[--><span data-v-35975db6>微信群</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-b98bc113 data-v-35975db6><a class="VPLink link vp-external-link-icon" href="https://www.itnavs.com/" target="_blank" rel="noreferrer" data-v-35975db6><!--[--><span data-v-35975db6>知航驿站</span><!--]--></a></div><!--]--><!--[--><div class="VPMenuLink" data-v-b98bc113 data-v-35975db6><a class="VPLink link vp-external-link-icon" href="https://yh.itnavs.com/contact" target="_blank" rel="noreferrer" data-v-35975db6><!--[--><span data-v-35975db6>合作机会</span><!--]--></a></div><!--]--><!--]--></div><!--[--><!--]--></div></div></div><!--]--><!--[--><a class="VPLink link vp-external-link-icon VPNavBarMenuLink" href="https://www.npmjs.com/package/@melt-js/libs-bag-entry" target="_blank" rel="noreferrer" tabindex="0" data-v-dc692963 data-v-e56f3d57><!--[--><span data-v-e56f3d57>v2026.11.7</span><!--]--></a><!--]--><!--]--></nav><!----><div class="VPNavBarAppearance appearance" data-v-6aa21345 data-v-6c893767><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="true" data-v-6c893767 data-v-5337faa4 data-v-1d5665e3><span class="check" data-v-1d5665e3><span class="icon" data-v-1d5665e3><!--[--><span class="vpi-sun sun" data-v-5337faa4></span><span class="vpi-moon moon" data-v-5337faa4></span><!--]--></span></span></button></div><div class="VPSocialLinks VPNavBarSocialLinks social-links" data-v-6aa21345 data-v-0394ad82 data-v-7bc22406><!--[--><a class="VPSocialLink no-icon" href="https://github.com/hangjob/vue-bag-admin/tree/next" aria-label="github" target="_blank" rel="noopener" data-v-7bc22406 data-v-bd121fe5><span class="vpi-social-github"></span></a><!--]--></div><div class="VPFlyout VPNavBarExtra extra" data-v-6aa21345 data-v-bb2aa2f0 data-v-cf11d7a2><button type="button" class="button" aria-haspopup="true" aria-expanded="false" aria-label="extra navigation" data-v-cf11d7a2><span class="vpi-more-horizontal icon" data-v-cf11d7a2></span></button><div class="menu" data-v-cf11d7a2><div class="VPMenu" data-v-cf11d7a2 data-v-b98bc113><!----><!--[--><!--[--><!----><div class="group" data-v-bb2aa2f0><div class="item appearance" data-v-bb2aa2f0><p class="label" data-v-bb2aa2f0>Appearance</p><div class="appearance-action" data-v-bb2aa2f0><button class="VPSwitch VPSwitchAppearance" type="button" role="switch" title aria-checked="true" data-v-bb2aa2f0 data-v-5337faa4 data-v-1d5665e3><span class="check" data-v-1d5665e3><span class="icon" data-v-1d5665e3><!--[--><span class="vpi-sun sun" data-v-5337faa4></span><span class="vpi-moon moon" data-v-5337faa4></span><!--]--></span></span></button></div></div></div><div class="group" data-v-bb2aa2f0><div class="item social-links" data-v-bb2aa2f0><div class="VPSocialLinks social-links-list" data-v-bb2aa2f0 data-v-7bc22406><!--[--><a class="VPSocialLink no-icon" href="https://github.com/hangjob/vue-bag-admin/tree/next" aria-label="github" target="_blank" rel="noopener" data-v-7bc22406 data-v-bd121fe5><span class="vpi-social-github"></span></a><!--]--></div></div></div><!--]--><!--]--></div></div></div><!--[--><!--]--><button type="button" class="VPNavBarHamburger hamburger" aria-label="mobile navigation" aria-expanded="false" aria-controls="VPNavScreen" data-v-6aa21345 data-v-e5dd9c1c><span class="container" data-v-e5dd9c1c><span class="top" data-v-e5dd9c1c></span><span class="middle" data-v-e5dd9c1c></span><span class="bottom" data-v-e5dd9c1c></span></span></button></div></div></div></div><div class="divider" data-v-6aa21345><div class="divider-line" data-v-6aa21345></div></div></div><!----></header><div class="VPLocalNav has-sidebar empty" data-v-5d98c3a5 data-v-a6f0e41e><div class="container" data-v-a6f0e41e><button class="menu" aria-expanded="false" aria-controls="VPSidebarNav" data-v-a6f0e41e><span class="vpi-align-left menu-icon" data-v-a6f0e41e></span><span class="menu-text" data-v-a6f0e41e>Menu</span></button><div class="VPLocalNavOutlineDropdown" style="--vp-vh:0px;" data-v-a6f0e41e data-v-8a42e2b4><button data-v-8a42e2b4>Return to top</button><!----></div></div></div><aside class="VPSidebar" data-v-5d98c3a5 data-v-319d5ca6><div class="curtain" data-v-319d5ca6></div><nav class="nav" id="VPSidebarNav" aria-labelledby="sidebar-aria-label" tabindex="-1" data-v-319d5ca6><span class="visually-hidden" id="sidebar-aria-label" data-v-319d5ca6> Sidebar Navigation </span><!--[--><!--]--><!--[--><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>开始使用</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/introduction.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>项目介绍</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/getting-started.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>快速上手</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/create-project.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>创建项目</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0 has-active" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>核心开发</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/host/bootstrap.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>初始化宿主</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/host/routing-and-menu.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>路由与菜单</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/host/auth-and-permissions.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>登录与权限</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/request-and-components.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>请求与组件</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>官方插件</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/official-plugins/" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>插件总览</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/official-plugins/install-and-toggle.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>安装与启停</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/official-plugins/shop.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>商城插件</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/official-plugins/sys-setting.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>系统设置插件</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><div class="no-transition group" data-v-c40bc020><section class="VPSidebarItem level-0" data-v-c40bc020 data-v-b3fd67f8><div class="item" role="button" tabindex="0" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><h2 class="text" data-v-b3fd67f8>插件开发</h2><!----></div><div class="items" data-v-b3fd67f8><!--[--><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/plugins/create-plugin.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>创建插件</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/plugins/admin-plugin.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>AdminPlugin 配置</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/plugins/routes-menus-locales.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>路由、菜单与多语言</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/plugins/permissions-and-settings.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>权限与配置项</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/plugins/lifecycle-and-dependencies.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>生命周期与依赖</p><!--]--></a><!----></div><!----></div><div class="VPSidebarItem level-1 is-link" data-v-b3fd67f8><div class="item" data-v-b3fd67f8><div class="indicator" data-v-b3fd67f8></div><a class="VPLink link link" href="/@melt-js/docs-bag@2026.11.7/guide/plugins/debug-and-publish.html" data-v-b3fd67f8><!--[--><p class="text" data-v-b3fd67f8>调试与发布</p><!--]--></a><!----></div><!----></div><!--]--></div></section></div><!--]--><!--[--><!--]--></nav></aside><div class="VPContent has-sidebar" id="VPContent" data-v-5d98c3a5 data-v-1428d186><div class="VPDoc has-sidebar has-aside" data-v-1428d186 data-v-39a288b8><!--[--><!--]--><div class="container" data-v-39a288b8><div class="aside" data-v-39a288b8><div class="aside-curtain" data-v-39a288b8></div><div class="aside-container" data-v-39a288b8><div class="aside-content" data-v-39a288b8><div class="VPDocAside" data-v-39a288b8 data-v-3f215769><!--[--><!--]--><!--[--><!--]--><nav aria-labelledby="doc-outline-aria-label" class="VPDocAsideOutline" data-v-3f215769 data-v-a5bbad30><div class="content" data-v-a5bbad30><div class="outline-marker" data-v-a5bbad30></div><div aria-level="2" class="outline-title" id="doc-outline-aria-label" role="heading" data-v-a5bbad30>On this page</div><ul class="VPDocOutlineItem root" data-v-a5bbad30 data-v-b933a997><!--[--><!--]--></ul></div></nav><!--[--><!--]--><div class="spacer" data-v-3f215769></div><!--[--><!--]--><!----><!--[--><!--]--><!--[--><!--]--></div></div></div></div><div class="content" data-v-39a288b8><div class="content-container" data-v-39a288b8><!--[--><!--]--><main class="main" data-v-39a288b8><div style="position:relative;" class="vp-doc _@melt-js_docs-bag@2026_11_7_guide_host_auth-and-permissions" data-v-39a288b8><div><h1 id="登录与权限" tabindex="-1">登录与权限 <a class="header-anchor" href="#登录与权限" aria-label="Permalink to "登录与权限""></a></h1><p>Vue-Bag-Admin 的权限链路分为四层:</p><ol><li><code>AuthProvider</code> 负责登录和获取用户资料。</li><li><code>userStore</code> 保存 token、角色和权限点。</li><li>路由守卫保护页面,菜单根据同一份数据过滤。</li><li>指令、组件和组合函数控制页面内的按钮或区域。</li></ol><p>后端实现可以不同,但最终需要向前端提供统一的角色和权限数据。</p><h2 id="启用路由鉴权" tabindex="-1">启用路由鉴权 <a class="header-anchor" href="#启用路由鉴权" aria-label="Permalink to "启用路由鉴权""></a></h2><p><code>createHostRouter()</code> 支持三种写法。</p><p>关闭鉴权:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">createHostRouter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
22
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> routes: appRoutes,</span></span>
|
|
23
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> auth: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">false</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // 关闭登录和页面权限守卫</span></span>
|
|
24
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">})</span></span></code></pre></div><p>使用默认路径:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">createHostRouter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
25
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> routes: appRoutes,</span></span>
|
|
26
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> auth: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // 启用默认鉴权规则</span></span>
|
|
27
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">})</span></span></code></pre></div><p>默认约定是:</p><div class="language-text vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">text</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span>首页 /dashboard</span></span>
|
|
28
|
+
<span class="line"><span>登录 /login</span></span>
|
|
29
|
+
<span class="line"><span>个人中心 /profile</span></span>
|
|
30
|
+
<span class="line"><span>无权限 /403</span></span>
|
|
31
|
+
<span class="line"><span>未找到 /404</span></span></code></pre></div><p>自定义路径和异常处理:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> router</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> createHostRouter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
32
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> routes: appRoutes,</span></span>
|
|
33
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> auth: {</span></span>
|
|
34
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> enabled: </span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">true</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 启用路由鉴权</span></span>
|
|
35
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> homePath: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/workspace'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 登录后的默认首页</span></span>
|
|
36
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> loginPath: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/sign-in'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 未登录时跳转的登录页</span></span>
|
|
37
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> profilePath: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/account'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 个人中心地址</span></span>
|
|
38
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> forbiddenPath: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/403'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 权限不足时跳转的页面</span></span>
|
|
39
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onProfileError</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() {</span></span>
|
|
40
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'logout'</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // 用户资料加载失败时清空登录态</span></span>
|
|
41
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
42
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
43
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">})</span></span></code></pre></div><p>启用鉴权时,必须存在对应登录路由,并将它标记为 <code>meta.public: true</code>。</p><h2 id="接入认证服务" tabindex="-1">接入认证服务 <a class="header-anchor" href="#接入认证服务" aria-label="Permalink to "接入认证服务""></a></h2><p>认证服务实现 <code>AuthProvider</code>:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { http, setAuthProvider, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> AuthProvider } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '@melt-js/libs-bag-entry'</span></span>
|
|
44
|
+
<span class="line"></span>
|
|
45
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">interface</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> LoginResponse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
46
|
+
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> token</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> string</span></span>
|
|
47
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>
|
|
48
|
+
<span class="line"></span>
|
|
49
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">interface</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> ProfileResponse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
50
|
+
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> id</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> number</span></span>
|
|
51
|
+
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> username</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> string</span></span>
|
|
52
|
+
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> roles</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">[]</span></span>
|
|
53
|
+
<span class="line"><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;"> permissions</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> string</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">[]</span></span>
|
|
54
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>
|
|
55
|
+
<span class="line"></span>
|
|
56
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> authProvider</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AuthProvider</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
57
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> login</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">payload</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) {</span></span>
|
|
58
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> http.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">post</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">any</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">LoginResponse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/login'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, payload)</span></span>
|
|
59
|
+
<span class="line"></span>
|
|
60
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
61
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> token: result.token</span></span>
|
|
62
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
63
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
64
|
+
<span class="line"></span>
|
|
65
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> fetchProfile</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() {</span></span>
|
|
66
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> result</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> http.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">get</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">any</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">ProfileResponse</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">>(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/me'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
67
|
+
<span class="line"></span>
|
|
68
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> return</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
69
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> username: result.username,</span></span>
|
|
70
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> user: result,</span></span>
|
|
71
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> roles: result.roles,</span></span>
|
|
72
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> permissions: result.permissions</span></span>
|
|
73
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
74
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
75
|
+
<span class="line"></span>
|
|
76
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> logout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() {</span></span>
|
|
77
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> http.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">post</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/api/logout'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">)</span></span>
|
|
78
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
79
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span>
|
|
80
|
+
<span class="line"></span>
|
|
81
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">setAuthProvider</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(authProvider) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 将认证实现交给宿主运行时</span></span></code></pre></div><p>如果后端使用仓库提供的 Strapi 参考接口,可以直接使用:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { createStrapiAuthProvider, setAuthProvider } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '@melt-js/libs-bag-entry'</span></span>
|
|
82
|
+
<span class="line"></span>
|
|
83
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">setAuthProvider</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">createStrapiAuthProvider</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 使用框架内置的 Strapi 5 认证适配器</span></span></code></pre></div><p>默认 Strapi 适配器使用 <code>/api/auth/local</code> 登录,并通过 <code>/api/users/me</code> 获取用户资料。</p><h2 id="配置请求-token" tabindex="-1">配置请求 Token <a class="header-anchor" href="#配置请求-token" aria-label="Permalink to "配置请求 Token""></a></h2><p><code>setupHttp()</code> 会在每次请求前读取最新 token:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { getHostNavigationConfig, setupHttp, useUserStore } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '@melt-js/libs-bag-entry'</span></span>
|
|
84
|
+
<span class="line"></span>
|
|
85
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userStore</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> useUserStore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
86
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> navigation</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> getHostNavigationConfig</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">() </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 获取登录页和 403 等导航地址</span></span>
|
|
87
|
+
<span class="line"></span>
|
|
88
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">setupHttp</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
89
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> baseURL: </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">meta</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">.env.</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;">VITE_API_URL</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 后端接口基础地址</span></span>
|
|
90
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> getToken</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> userStore.token, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 每次请求前读取最新 token</span></span>
|
|
91
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onUnauthorized</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
92
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> userStore.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">logout</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
93
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> router.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">replace</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
94
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> path: navigation.loginPath,</span></span>
|
|
95
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> query: {</span></span>
|
|
96
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> redirect: router.currentRoute.value.fullPath </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 记录登录后需要返回的页面</span></span>
|
|
97
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
98
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> })</span></span>
|
|
99
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> },</span></span>
|
|
100
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> onForbidden</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
101
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> router.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">replace</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(navigation.forbiddenPath) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 收到 403 后进入无权限页面</span></span>
|
|
102
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
103
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">})</span></span></code></pre></div><p>用户登录成功后,<code>userStore</code> 会把 token 写入 <code>localStorage</code>,默认键名是 <code>bag.auth.token</code>。</p><h2 id="登录页面" tabindex="-1">登录页面 <a class="header-anchor" href="#登录页面" aria-label="Permalink to "登录页面""></a></h2><p>登录页只需要调用 <code>userStore.login()</code>:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { useRoute, useRouter } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'vue-router'</span></span>
|
|
104
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { useUserStore } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '@melt-js/libs-bag-entry'</span></span>
|
|
105
|
+
<span class="line"></span>
|
|
106
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> route</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> useRoute</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
107
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> router</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> useRouter</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
108
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> userStore</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> useUserStore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
|
|
109
|
+
<span class="line"></span>
|
|
110
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> submitLogin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> async</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
|
|
111
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> userStore.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">login</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
112
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> username: username.value,</span></span>
|
|
113
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> password: password.value</span></span>
|
|
114
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> })</span></span>
|
|
115
|
+
<span class="line"></span>
|
|
116
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> redirect</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> typeof</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> route.query.redirect </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'string'</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> ?</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> route.query.redirect </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '/dashboard'</span></span>
|
|
117
|
+
<span class="line"></span>
|
|
118
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> await</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> router.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">replace</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(redirect)</span></span>
|
|
119
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>路由守卫会在用户带 token 进入受保护页面时自动加载资料。如果资料加载失败,默认清空登录态并返回登录页。</p><h2 id="页面权限" tabindex="-1">页面权限 <a class="header-anchor" href="#页面权限" aria-label="Permalink to "页面权限""></a></h2><p>路由通过角色或权限点限制访问:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">{</span></span>
|
|
120
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> path</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'/finance/audit'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
121
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: () </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'./views/FinanceAudit.vue'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">),</span></span>
|
|
122
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> meta</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
|
|
123
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> title</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'财务审核'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
|
|
124
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> roles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'finance'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'manager'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">], </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 需要检查的角色</span></span>
|
|
125
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> roleMode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'all'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 必须同时拥有 finance 和 manager</span></span>
|
|
126
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> permissions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'finance.read'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'finance.audit'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">], </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 需要检查的权限点</span></span>
|
|
127
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> permissionMode</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'all'</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // 必须同时拥有两个权限点</span></span>
|
|
128
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span></span>
|
|
129
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><p>同一个数组默认是 <code>any</code>,配置 <code>all</code> 后才要求全部满足。</p><p>当 <code>roles</code> 和 <code>permissions</code> 同时存在时,两组条件都必须通过。<code>policy</code> 也是附加条件:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">meta</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
|
|
130
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> permissions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'team.read'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">], </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 先通过基础权限检查</span></span>
|
|
131
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> policy</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: ({ </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">roles</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#E36209;--shiki-dark:#FFAB70;">user</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">=></span></span>
|
|
132
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> roles.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">includes</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'admin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">) </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">||</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> user?.teamId </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">===</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> 'team-1'</span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;"> // 管理员或指定团队成员可访问</span></span>
|
|
133
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">}</span></span></code></pre></div><h2 id="注册页面内权限能力" tabindex="-1">注册页面内权限能力 <a class="header-anchor" href="#注册页面内权限能力" aria-label="Permalink to "注册页面内权限能力""></a></h2><p>在 <code>main.ts</code> 中注册全局组件和指令:</p><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { PermissionAccess, registerPermissionDirective } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '@melt-js/libs-bag-entry'</span></span>
|
|
134
|
+
<span class="line"></span>
|
|
135
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">app.</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">component</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'PermissionAccess'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, PermissionAccess) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 全局注册权限区域组件</span></span>
|
|
136
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">registerPermissionDirective</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">(app) </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 全局注册 v-permission 指令</span></span></code></pre></div><h3 id="控制单个元素" tabindex="-1">控制单个元素 <a class="header-anchor" href="#控制单个元素" aria-label="Permalink to "控制单个元素""></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 github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">button</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> v-permission</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"'product.create'"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
137
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> 新建商品</span></span>
|
|
138
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"></</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">button</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
139
|
+
<span class="line"></span>
|
|
140
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">button</span></span>
|
|
141
|
+
<span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> v-permission</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">{</span></span>
|
|
142
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> roles: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'admin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
|
|
143
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> permissions: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'product.delete'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]</span></span>
|
|
144
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> }</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"</span></span>
|
|
145
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
146
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> 删除商品</span></span>
|
|
147
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"></</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">button</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span></code></pre></div><h3 id="控制一块内容" tabindex="-1">控制一块内容 <a class="header-anchor" href="#控制一块内容" aria-label="Permalink to "控制一块内容""></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 github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"><</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">PermissionAccess</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">permissions</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">[</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'report.export'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">"</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span>
|
|
148
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <ExportButton /></span></span>
|
|
149
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> <ExportHistory /></span></span>
|
|
150
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"></</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">PermissionAccess</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">></span></span></code></pre></div><h3 id="在逻辑中判断" tabindex="-1">在逻辑中判断 <a class="header-anchor" href="#在逻辑中判断" aria-label="Permalink to "在逻辑中判断""></a></h3><div class="language-ts vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">ts</span><pre class="shiki shiki-themes github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { canAccess, useAccess } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> '@melt-js/libs-bag-entry'</span></span>
|
|
151
|
+
<span class="line"></span>
|
|
152
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> canEdit</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> useAccess</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
153
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> permissions: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'product.edit'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]</span></span>
|
|
154
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">})</span></span>
|
|
155
|
+
<span class="line"></span>
|
|
156
|
+
<span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> canManageSystem</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> canAccess</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">({</span></span>
|
|
157
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> roles: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'admin'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">],</span></span>
|
|
158
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> permissions: [</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">'system.manage'</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">]</span></span>
|
|
159
|
+
<span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">})</span></span></code></pre></div><p><code>useAccess()</code> 返回响应式的 <code>ComputedRef<boolean></code>;<code>canAccess()</code> 返回当前时刻的布尔值。</p><h2 id="权限设计建议" tabindex="-1">权限设计建议 <a class="header-anchor" href="#权限设计建议" aria-label="Permalink to "权限设计建议""></a></h2><ul><li>页面安全依赖路由守卫,不能只隐藏菜单或按钮。</li><li>菜单与对应路由使用同一组角色和权限条件。</li><li>角色适合描述身份,权限点适合描述具体动作。</li><li>权限点建议采用 <code>业务域.资源.动作</code>,例如 <code>shop.product.create</code>。</li><li>超级管理员可以返回 <code>*</code> 权限,框架会视为拥有所有权限点。</li><li>前端权限用于交互和路由保护,后端仍必须再次校验接口权限。</li></ul><h2 id="下一步" tabindex="-1">下一步 <a class="header-anchor" href="#下一步" aria-label="Permalink to "下一步""></a></h2><p>继续阅读 <a href="./../request-and-components.html">请求与组件</a>,在页面中接入接口、请求状态、表格和表单。</p></div></div></main><footer class="VPDocFooter" data-v-39a288b8 data-v-e257564d><!--[--><!--]--><div class="edit-info" data-v-e257564d><!----><div class="last-updated" data-v-e257564d><p class="VPLastUpdated" data-v-e257564d data-v-e98dd255>Last updated: <time datetime="2026-11-07T09:53:20.000Z" data-v-e98dd255></time></p></div></div><nav class="prev-next" aria-labelledby="doc-footer-aria-label" data-v-e257564d><span class="visually-hidden" id="doc-footer-aria-label" data-v-e257564d>Pager</span><div class="pager" data-v-e257564d><a class="VPLink link pager-link prev" href="/@melt-js/docs-bag@2026.11.7/guide/host/routing-and-menu.html" data-v-e257564d><!--[--><span class="desc" data-v-e257564d>Previous page</span><span class="title" data-v-e257564d>路由与菜单</span><!--]--></a></div><div class="pager" data-v-e257564d><a class="VPLink link pager-link next" href="/@melt-js/docs-bag@2026.11.7/guide/request-and-components.html" data-v-e257564d><!--[--><span class="desc" data-v-e257564d>Next page</span><span class="title" data-v-e257564d>请求与组件</span><!--]--></a></div></nav></footer><!--[--><!--]--></div></div></div><!--[--><!--]--></div></div><footer class="VPFooter has-sidebar" data-v-5d98c3a5 data-v-e315a0ad><div class="container" data-v-e315a0ad><p class="message" data-v-e315a0ad>Released under the MIT License.</p><p class="copyright" data-v-e315a0ad>Copyright © 2026-present Vue-Bag-Admin</p></div></footer><!--[--><!--]--></div></div>
|
|
160
|
+
<script>window.__VP_HASH_MAP__=JSON.parse("{\"guide_complete-host-app.md\":\"CDRzLz0E\",\"guide_create-project.md\":\"LRNhDD9x\",\"guide_deployment.md\":\"B8aEUabm\",\"guide_dictionary-system.md\":\"Dy0tQYMR\",\"guide_getting-started.md\":\"B-mobXxi\",\"guide_host_auth-and-permissions.md\":\"DWH3Vape\",\"guide_host_bootstrap.md\":\"DpbxPIZw\",\"guide_host_routing-and-menu.md\":\"BdCMIOxn\",\"guide_introduction.md\":\"1MiCcWyO\",\"guide_local-debugging.md\":\"CLJoKVb9\",\"guide_network-request.md\":\"DDlA8bc0\",\"guide_official-plugins_index.md\":\"DPwemCGy\",\"guide_official-plugins_install-and-toggle.md\":\"Eq2hWjYn\",\"guide_official-plugins_shop.md\":\"yBltEx-o\",\"guide_official-plugins_sys-setting.md\":\"BmkuOqGv\",\"guide_package-core.md\":\"-E29SYy8\",\"guide_package-ecosystem.md\":\"Di3RcVpF\",\"guide_package-plugin-shop.md\":\"D-xXN7Yg\",\"guide_package-plugin-sys-setting.md\":\"Dx3nxHVF\",\"guide_package-publishing.md\":\"B7hzTYDH\",\"guide_package-request.md\":\"DxaD65eM\",\"guide_package-ui.md\":\"wBZ_iQLb\",\"guide_permissions.md\":\"B_5re4AR\",\"guide_plugin-development.md\":\"BQzTwLRr\",\"guide_plugins_admin-plugin.md\":\"d_XC5U-4\",\"guide_plugins_create-plugin.md\":\"C-wDq4Un\",\"guide_plugins_debug-and-publish.md\":\"CeTc01QN\",\"guide_plugins_lifecycle-and-dependencies.md\":\"BtwKS5jY\",\"guide_plugins_permissions-and-settings.md\":\"05CsB1I6\",\"guide_plugins_routes-menus-locales.md\":\"B2dzO2DN\",\"guide_pro-form.md\":\"DbSHbrMu\",\"guide_pro-table.md\":\"DBuYQYgG\",\"guide_request-and-components.md\":\"BQXI_ZxY\",\"guide_routing-and-menu.md\":\"-zrm3BV9\",\"guide_theme-tokens.md\":\"DXpbrOjS\",\"index.md\":\"BUgI8r98\",\"readme.md\":\"BEUJStMI\"}");window.__VP_SITE_DATA__=JSON.parse("{\"lang\":\"en-US\",\"dir\":\"ltr\",\"title\":\"Vue-Bag-Admin\",\"description\":\"基于 Vue3 + Vite6 + Naive UI + Pinia + Strapi5 的中后台系统框架\",\"base\":\"/@melt-js/docs-bag@2026.11.7/\",\"head\":[],\"router\":{\"prefetchLinks\":true},\"appearance\":\"dark\",\"themeConfig\":{\"logo\":\"/logo.png\",\"nav\":[{\"text\":\"首页\",\"link\":\"/\"},{\"text\":\"指南\",\"link\":\"/guide/introduction\"},{\"text\":\"在线预览\",\"link\":\"https://hangjob.github.io/vue-bag-admin/\"},{\"text\":\"社区\",\"items\":[{\"text\":\"微信群\",\"link\":\"/#community\"},{\"text\":\"知航驿站\",\"link\":\"https://www.itnavs.com/\"},{\"text\":\"合作机会\",\"link\":\"https://yh.itnavs.com/contact\"}]},{\"text\":\"v2026.11.7\",\"link\":\"https://www.npmjs.com/package/@melt-js/libs-bag-entry\"}],\"sidebar\":{\"/guide/\":[{\"text\":\"开始使用\",\"items\":[{\"text\":\"项目介绍\",\"link\":\"/guide/introduction\"},{\"text\":\"快速上手\",\"link\":\"/guide/getting-started\"},{\"text\":\"创建项目\",\"link\":\"/guide/create-project\"}]},{\"text\":\"核心开发\",\"items\":[{\"text\":\"初始化宿主\",\"link\":\"/guide/host/bootstrap\"},{\"text\":\"路由与菜单\",\"link\":\"/guide/host/routing-and-menu\"},{\"text\":\"登录与权限\",\"link\":\"/guide/host/auth-and-permissions\"},{\"text\":\"请求与组件\",\"link\":\"/guide/request-and-components\"}]},{\"text\":\"官方插件\",\"items\":[{\"text\":\"插件总览\",\"link\":\"/guide/official-plugins/\"},{\"text\":\"安装与启停\",\"link\":\"/guide/official-plugins/install-and-toggle\"},{\"text\":\"商城插件\",\"link\":\"/guide/official-plugins/shop\"},{\"text\":\"系统设置插件\",\"link\":\"/guide/official-plugins/sys-setting\"}]},{\"text\":\"插件开发\",\"items\":[{\"text\":\"创建插件\",\"link\":\"/guide/plugins/create-plugin\"},{\"text\":\"AdminPlugin 配置\",\"link\":\"/guide/plugins/admin-plugin\"},{\"text\":\"路由、菜单与多语言\",\"link\":\"/guide/plugins/routes-menus-locales\"},{\"text\":\"权限与配置项\",\"link\":\"/guide/plugins/permissions-and-settings\"},{\"text\":\"生命周期与依赖\",\"link\":\"/guide/plugins/lifecycle-and-dependencies\"},{\"text\":\"调试与发布\",\"link\":\"/guide/plugins/debug-and-publish\"}]}]},\"socialLinks\":[{\"icon\":\"github\",\"link\":\"https://github.com/hangjob/vue-bag-admin/tree/next\"}],\"footer\":{\"message\":\"Released under the MIT License.\",\"copyright\":\"Copyright © 2026-present Vue-Bag-Admin\"},\"search\":{\"provider\":\"local\"}},\"locales\":{},\"scrollOffset\":134,\"cleanUrls\":false}");</script>
|
|
161
|
+
|
|
162
|
+
</body>
|
|
163
|
+
</html>
|