@melt-js/docs-bag 2026.11.7 → 2026.11.16

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.
Files changed (125) hide show
  1. package/README.md +15 -3
  2. package/dist/404.html +5 -5
  3. package/dist/README.html +10 -10
  4. package/dist/assets/README.md.D8R8Eb23.js +9 -0
  5. package/dist/assets/README.md.D8R8Eb23.lean.js +1 -0
  6. package/dist/assets/{app.CPZ-gtYR.js → app.B2EI2o4q.js} +1 -1
  7. package/dist/assets/chunks/@localSearchIndexroot.Chqo2dFE.js +1 -0
  8. package/dist/assets/chunks/{VPLocalSearchBox.BVA3GWxn.js → VPLocalSearchBox.DY28kF4x.js} +5 -5
  9. package/dist/assets/chunks/{framework.B3lxS50j.js → framework.Olv9GB1A.js} +1 -1
  10. package/dist/assets/chunks/{theme.C4rSMcmz.js → theme.BJkR0Hu5.js} +2 -2
  11. package/dist/assets/{guide_complete-host-app.md.CDRzLz0E.js → guide_complete-host-app.md.CBuOgyl8.js} +1 -1
  12. package/dist/assets/{guide_complete-host-app.md.CDRzLz0E.lean.js → guide_complete-host-app.md.CBuOgyl8.lean.js} +1 -1
  13. package/dist/assets/{guide_create-project.md.LRNhDD9x.js → guide_create-project.md.B2KkXWnI.js} +1 -1
  14. package/dist/assets/{guide_create-project.md.LRNhDD9x.lean.js → guide_create-project.md.B2KkXWnI.lean.js} +1 -1
  15. package/dist/assets/{guide_deployment.md.B8aEUabm.js → guide_deployment.md.BrvgEFf0.js} +1 -1
  16. package/dist/assets/{guide_deployment.md.B8aEUabm.lean.js → guide_deployment.md.BrvgEFf0.lean.js} +1 -1
  17. package/dist/assets/{guide_dictionary-system.md.Dy0tQYMR.js → guide_dictionary-system.md.hS_2-jYz.js} +1 -1
  18. package/dist/assets/{guide_dictionary-system.md.Dy0tQYMR.lean.js → guide_dictionary-system.md.hS_2-jYz.lean.js} +1 -1
  19. package/dist/assets/{guide_getting-started.md.B-mobXxi.js → guide_getting-started.md.0nvT0khJ.js} +1 -1
  20. package/dist/assets/{guide_getting-started.md.B-mobXxi.lean.js → guide_getting-started.md.0nvT0khJ.lean.js} +1 -1
  21. package/dist/assets/{guide_host_auth-and-permissions.md.DWH3Vape.js → guide_host_auth-and-permissions.md.Pr66-VM-.js} +1 -1
  22. package/dist/assets/{guide_host_auth-and-permissions.md.DWH3Vape.lean.js → guide_host_auth-and-permissions.md.Pr66-VM-.lean.js} +1 -1
  23. package/dist/assets/{guide_host_bootstrap.md.DpbxPIZw.js → guide_host_bootstrap.md.DKFeJyTi.js} +1 -1
  24. package/dist/assets/{guide_host_bootstrap.md.DpbxPIZw.lean.js → guide_host_bootstrap.md.DKFeJyTi.lean.js} +1 -1
  25. package/dist/assets/{guide_host_routing-and-menu.md.BdCMIOxn.js → guide_host_routing-and-menu.md.CQaMO4vj.js} +1 -1
  26. package/dist/assets/{guide_host_routing-and-menu.md.BdCMIOxn.lean.js → guide_host_routing-and-menu.md.CQaMO4vj.lean.js} +1 -1
  27. package/dist/assets/{guide_introduction.md.1MiCcWyO.js → guide_introduction.md.tg6wBrpR.js} +1 -1
  28. package/dist/assets/{guide_introduction.md.1MiCcWyO.lean.js → guide_introduction.md.tg6wBrpR.lean.js} +1 -1
  29. package/dist/assets/{guide_local-debugging.md.CLJoKVb9.js → guide_local-debugging.md.DVHeXzws.js} +1 -1
  30. package/dist/assets/{guide_local-debugging.md.CLJoKVb9.lean.js → guide_local-debugging.md.DVHeXzws.lean.js} +1 -1
  31. package/dist/assets/{guide_network-request.md.DDlA8bc0.js → guide_network-request.md.BlxKmm59.js} +1 -1
  32. package/dist/assets/{guide_network-request.md.DDlA8bc0.lean.js → guide_network-request.md.BlxKmm59.lean.js} +1 -1
  33. package/dist/assets/{guide_official-plugins_index.md.DPwemCGy.js → guide_official-plugins_index.md.BF-gWYVU.js} +1 -1
  34. package/dist/assets/{guide_official-plugins_index.md.DPwemCGy.lean.js → guide_official-plugins_index.md.BF-gWYVU.lean.js} +1 -1
  35. package/dist/assets/{guide_official-plugins_install-and-toggle.md.Eq2hWjYn.js → guide_official-plugins_install-and-toggle.md.B35ne8VL.js} +1 -1
  36. package/dist/assets/{guide_official-plugins_install-and-toggle.md.Eq2hWjYn.lean.js → guide_official-plugins_install-and-toggle.md.B35ne8VL.lean.js} +1 -1
  37. package/dist/assets/{guide_official-plugins_shop.md.yBltEx-o.js → guide_official-plugins_shop.md.BGGP886L.js} +1 -1
  38. package/dist/assets/{guide_official-plugins_shop.md.yBltEx-o.lean.js → guide_official-plugins_shop.md.BGGP886L.lean.js} +1 -1
  39. package/dist/assets/{guide_official-plugins_sys-setting.md.BmkuOqGv.js → guide_official-plugins_sys-setting.md.BwiJzRiL.js} +1 -1
  40. package/dist/assets/{guide_official-plugins_sys-setting.md.BmkuOqGv.lean.js → guide_official-plugins_sys-setting.md.BwiJzRiL.lean.js} +1 -1
  41. package/dist/assets/{guide_package-core.md.-E29SYy8.js → guide_package-core.md.D1xrMRok.js} +1 -1
  42. package/dist/assets/{guide_package-core.md.-E29SYy8.lean.js → guide_package-core.md.D1xrMRok.lean.js} +1 -1
  43. package/dist/assets/{guide_package-ecosystem.md.Di3RcVpF.js → guide_package-ecosystem.md.Dl2r9NSa.js} +1 -1
  44. package/dist/assets/{guide_package-ecosystem.md.Di3RcVpF.lean.js → guide_package-ecosystem.md.Dl2r9NSa.lean.js} +1 -1
  45. package/dist/assets/{guide_package-plugin-shop.md.D-xXN7Yg.js → guide_package-plugin-shop.md.BaIhzPDV.js} +1 -1
  46. package/dist/assets/{guide_package-plugin-shop.md.D-xXN7Yg.lean.js → guide_package-plugin-shop.md.BaIhzPDV.lean.js} +1 -1
  47. package/dist/assets/{guide_package-plugin-sys-setting.md.Dx3nxHVF.js → guide_package-plugin-sys-setting.md.C0ROCk-O.js} +1 -1
  48. package/dist/assets/{guide_package-plugin-sys-setting.md.Dx3nxHVF.lean.js → guide_package-plugin-sys-setting.md.C0ROCk-O.lean.js} +1 -1
  49. package/dist/assets/{guide_package-publishing.md.B7hzTYDH.js → guide_package-publishing.md.De2Y0rte.js} +1 -1
  50. package/dist/assets/{guide_package-publishing.md.B7hzTYDH.lean.js → guide_package-publishing.md.De2Y0rte.lean.js} +1 -1
  51. package/dist/assets/{guide_package-request.md.DxaD65eM.js → guide_package-request.md.DugGGXSX.js} +1 -1
  52. package/dist/assets/{guide_package-request.md.DxaD65eM.lean.js → guide_package-request.md.DugGGXSX.lean.js} +1 -1
  53. package/dist/assets/{guide_package-ui.md.wBZ_iQLb.js → guide_package-ui.md.BPCpNCIF.js} +1 -1
  54. package/dist/assets/{guide_package-ui.md.wBZ_iQLb.lean.js → guide_package-ui.md.BPCpNCIF.lean.js} +1 -1
  55. package/dist/assets/{guide_permissions.md.B_5re4AR.js → guide_permissions.md.DHnKaha_.js} +1 -1
  56. package/dist/assets/{guide_permissions.md.B_5re4AR.lean.js → guide_permissions.md.DHnKaha_.lean.js} +1 -1
  57. package/dist/assets/{guide_plugin-development.md.BQzTwLRr.js → guide_plugin-development.md.DeFWVfLN.js} +1 -1
  58. package/dist/assets/{guide_plugin-development.md.BQzTwLRr.lean.js → guide_plugin-development.md.DeFWVfLN.lean.js} +1 -1
  59. package/dist/assets/{guide_plugins_admin-plugin.md.d_XC5U-4.js → guide_plugins_admin-plugin.md.XLffV1LB.js} +1 -1
  60. package/dist/assets/{guide_plugins_admin-plugin.md.d_XC5U-4.lean.js → guide_plugins_admin-plugin.md.XLffV1LB.lean.js} +1 -1
  61. package/dist/assets/{guide_plugins_create-plugin.md.C-wDq4Un.js → guide_plugins_create-plugin.md.Br3OIR1m.js} +1 -1
  62. package/dist/assets/{guide_plugins_create-plugin.md.C-wDq4Un.lean.js → guide_plugins_create-plugin.md.Br3OIR1m.lean.js} +1 -1
  63. package/dist/assets/{guide_plugins_debug-and-publish.md.CeTc01QN.js → guide_plugins_debug-and-publish.md.C5ZbCito.js} +1 -1
  64. package/dist/assets/{guide_plugins_debug-and-publish.md.CeTc01QN.lean.js → guide_plugins_debug-and-publish.md.C5ZbCito.lean.js} +1 -1
  65. package/dist/assets/{guide_plugins_lifecycle-and-dependencies.md.BtwKS5jY.js → guide_plugins_lifecycle-and-dependencies.md.CV7nFME-.js} +1 -1
  66. package/dist/assets/{guide_plugins_lifecycle-and-dependencies.md.BtwKS5jY.lean.js → guide_plugins_lifecycle-and-dependencies.md.CV7nFME-.lean.js} +1 -1
  67. package/dist/assets/{guide_plugins_permissions-and-settings.md.05CsB1I6.js → guide_plugins_permissions-and-settings.md.B_MrVXY_.js} +1 -1
  68. package/dist/assets/{guide_plugins_permissions-and-settings.md.05CsB1I6.lean.js → guide_plugins_permissions-and-settings.md.B_MrVXY_.lean.js} +1 -1
  69. package/dist/assets/{guide_plugins_routes-menus-locales.md.B2dzO2DN.js → guide_plugins_routes-menus-locales.md.heaL1_wi.js} +1 -1
  70. package/dist/assets/{guide_plugins_routes-menus-locales.md.B2dzO2DN.lean.js → guide_plugins_routes-menus-locales.md.heaL1_wi.lean.js} +1 -1
  71. package/dist/assets/{guide_pro-form.md.DbSHbrMu.js → guide_pro-form.md.L9CKqs5C.js} +1 -1
  72. package/dist/assets/{guide_pro-form.md.DbSHbrMu.lean.js → guide_pro-form.md.L9CKqs5C.lean.js} +1 -1
  73. package/dist/assets/{guide_pro-table.md.DBuYQYgG.js → guide_pro-table.md.DlhJG49R.js} +1 -1
  74. package/dist/assets/{guide_pro-table.md.DBuYQYgG.lean.js → guide_pro-table.md.DlhJG49R.lean.js} +1 -1
  75. package/dist/assets/{guide_request-and-components.md.BQXI_ZxY.js → guide_request-and-components.md.CeEnrOuY.js} +1 -1
  76. package/dist/assets/{guide_request-and-components.md.BQXI_ZxY.lean.js → guide_request-and-components.md.CeEnrOuY.lean.js} +1 -1
  77. package/dist/assets/{guide_routing-and-menu.md.-zrm3BV9.js → guide_routing-and-menu.md.09TL-ILh.js} +1 -1
  78. package/dist/assets/{guide_routing-and-menu.md.-zrm3BV9.lean.js → guide_routing-and-menu.md.09TL-ILh.lean.js} +1 -1
  79. package/dist/assets/{guide_theme-tokens.md.DXpbrOjS.js → guide_theme-tokens.md.Cfn7RM_2.js} +1 -1
  80. package/dist/assets/{guide_theme-tokens.md.DXpbrOjS.lean.js → guide_theme-tokens.md.Cfn7RM_2.lean.js} +1 -1
  81. package/dist/assets/{index.md.BUgI8r98.js → index.md.ClEmxxY1.js} +1 -1
  82. package/dist/assets/{index.md.BUgI8r98.lean.js → index.md.ClEmxxY1.lean.js} +1 -1
  83. package/dist/assets/style.IeUynjWL.css +1 -0
  84. package/dist/guide/complete-host-app.html +10 -10
  85. package/dist/guide/create-project.html +10 -10
  86. package/dist/guide/deployment.html +10 -10
  87. package/dist/guide/dictionary-system.html +10 -10
  88. package/dist/guide/getting-started.html +10 -10
  89. package/dist/guide/host/auth-and-permissions.html +10 -10
  90. package/dist/guide/host/bootstrap.html +10 -10
  91. package/dist/guide/host/routing-and-menu.html +10 -10
  92. package/dist/guide/introduction.html +10 -10
  93. package/dist/guide/local-debugging.html +10 -10
  94. package/dist/guide/network-request.html +10 -10
  95. package/dist/guide/official-plugins/index.html +10 -10
  96. package/dist/guide/official-plugins/install-and-toggle.html +10 -10
  97. package/dist/guide/official-plugins/shop.html +10 -10
  98. package/dist/guide/official-plugins/sys-setting.html +10 -10
  99. package/dist/guide/package-core.html +10 -10
  100. package/dist/guide/package-ecosystem.html +9 -9
  101. package/dist/guide/package-plugin-shop.html +10 -10
  102. package/dist/guide/package-plugin-sys-setting.html +10 -10
  103. package/dist/guide/package-publishing.html +10 -10
  104. package/dist/guide/package-request.html +10 -10
  105. package/dist/guide/package-ui.html +10 -10
  106. package/dist/guide/permissions.html +10 -10
  107. package/dist/guide/plugin-development.html +10 -10
  108. package/dist/guide/plugins/admin-plugin.html +10 -10
  109. package/dist/guide/plugins/create-plugin.html +10 -10
  110. package/dist/guide/plugins/debug-and-publish.html +10 -10
  111. package/dist/guide/plugins/lifecycle-and-dependencies.html +10 -10
  112. package/dist/guide/plugins/permissions-and-settings.html +10 -10
  113. package/dist/guide/plugins/routes-menus-locales.html +10 -10
  114. package/dist/guide/pro-form.html +10 -10
  115. package/dist/guide/pro-table.html +10 -10
  116. package/dist/guide/request-and-components.html +10 -10
  117. package/dist/guide/routing-and-menu.html +10 -10
  118. package/dist/guide/theme-tokens.html +10 -10
  119. package/dist/hashmap.json +1 -1
  120. package/dist/index.html +9 -9
  121. package/package.json +12 -9
  122. package/dist/assets/README.md.BEUJStMI.js +0 -9
  123. package/dist/assets/README.md.BEUJStMI.lean.js +0 -1
  124. package/dist/assets/chunks/@localSearchIndexroot.7ill5i5O.js +0 -1
  125. package/dist/assets/style.0snOvk0r.css +0 -1
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"@melt-js/libs-bag-ui","description":"","frontmatter":{},"headers":[],"relativePath":"guide/package-ui.md","filePath":"guide/package-ui.md","lastUpdated":1794045200000}'),h={name:"guide/package-ui.md"};function k(t,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[l(`<h1 id="melt-js-libs-bag-ui" tabindex="-1">@melt-js/libs-bag-ui <a class="header-anchor" href="#melt-js-libs-bag-ui" aria-label="Permalink to &quot;@melt-js/libs-bag-ui&quot;">​</a></h1><p><code>@melt-js/libs-bag-ui</code> 是组件层,主要干两件事:把后台里最容易重复的列表页和表单页沉下来,然后直接吃 <code>@melt-js/libs-bag-core</code> 里定义的 Schema 和字典协议。</p><h2 id="现在有这些组件" tabindex="-1">现在有这些组件 <a class="header-anchor" href="#现在有这些组件" aria-label="Permalink to &quot;现在有这些组件&quot;">​</a></h2><ul><li><code>PmProTable</code></li><li><code>PmSchemaForm</code></li><li><code>PmProForm</code></li><li><code>PmDictTag</code></li><li><code>BagUiProvider</code></li></ul><h2 id="最常见的用法" tabindex="-1">最常见的用法 <a class="header-anchor" href="#最常见的用法" aria-label="Permalink to &quot;最常见的用法&quot;">​</a></h2><h3 id="用-pmproform-搭表单" tabindex="-1">用 <code>PmProForm</code> 搭表单 <a class="header-anchor" href="#用-pmproform-搭表单" aria-label="Permalink to &quot;用 \`PmProForm\` 搭表单&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 github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">script</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setup</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lang</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;ts&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
1
+ import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"@melt-js/libs-bag-ui","description":"","frontmatter":{},"headers":[],"relativePath":"guide/package-ui.md","filePath":"guide/package-ui.md","lastUpdated":1794045200000}'),h={name:"guide/package-ui.md"};function k(t,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[l(`<h1 id="melt-js-libs-bag-ui" tabindex="-1">@melt-js/libs-bag-ui <a class="header-anchor" href="#melt-js-libs-bag-ui" aria-label="Permalink to &quot;@melt-js/libs-bag-ui&quot;">​</a></h1><p><code>@melt-js/libs-bag-ui</code> 是组件层,主要干两件事:把后台里最容易重复的列表页和表单页沉下来,然后直接吃 <code>@melt-js/libs-bag-core</code> 里定义的 Schema 和字典协议。</p><h2 id="现在有这些组件" tabindex="-1">现在有这些组件 <a class="header-anchor" href="#现在有这些组件" aria-label="Permalink to &quot;现在有这些组件&quot;">​</a></h2><ul><li><code>PmProTable</code></li><li><code>PmSchemaForm</code></li><li><code>PmProForm</code></li><li><code>PmDictTag</code></li><li><code>BagUiProvider</code></li></ul><h2 id="最常见的用法" tabindex="-1">最常见的用法 <a class="header-anchor" href="#最常见的用法" aria-label="Permalink to &quot;最常见的用法&quot;">​</a></h2><h3 id="用-pmproform-搭表单" tabindex="-1">用 <code>PmProForm</code> 搭表单 <a class="header-anchor" href="#用-pmproform-搭表单" aria-label="Permalink to &quot;用 \`PmProForm\` 搭表单&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 github-light github-dark vp-code" tabindex="0"><code><span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">script</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> setup</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> lang</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;ts&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
2
2
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { ref } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;vue&#39;</span></span>
3
3
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { PmProForm } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-ui&#39;</span></span>
4
4
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">import</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { ProFormSchema } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-core&#39;</span></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"@melt-js/libs-bag-ui","description":"","frontmatter":{},"headers":[],"relativePath":"guide/package-ui.md","filePath":"guide/package-ui.md","lastUpdated":1794045200000}'),h={name:"guide/package-ui.md"};function k(t,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[l("",15)])])}const y=i(h,[["render",k]]);export{g as __pageData,y as default};
1
+ import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"@melt-js/libs-bag-ui","description":"","frontmatter":{},"headers":[],"relativePath":"guide/package-ui.md","filePath":"guide/package-ui.md","lastUpdated":1794045200000}'),h={name:"guide/package-ui.md"};function k(t,s,p,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[l("",15)])])}const y=i(h,[["render",k]]);export{g as __pageData,y as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as h}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"权限管理","description":"","frontmatter":{},"headers":[],"relativePath":"guide/permissions.md","filePath":"guide/permissions.md","lastUpdated":1794045200000}'),t={name:"guide/permissions.md"};function l(p,s,k,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h(`<h1 id="权限管理" tabindex="-1">权限管理 <a class="header-anchor" href="#权限管理" aria-label="Permalink to &quot;权限管理&quot;">​</a></h1><p>Vue-Bag-Admin 的权限模型基于 RBAC,覆盖这几块:</p><ul><li>页面级路由权限</li><li>菜单级权限过滤</li><li>按钮和组件级权限控制</li></ul><h2 id="权限数据流转" tabindex="-1">权限数据流转 <a class="header-anchor" href="#权限数据流转" aria-label="Permalink to &quot;权限数据流转&quot;">​</a></h2><p>前端鉴权主要看 <code>userStore</code> 里的两个状态:<code>roles</code>(角色列表)和 <code>permissions</code>(权限标识列表)。</p><p>不管后端怎么写,前端这边通常按这条链路走:</p><ol><li>用户登录成功后,前端请求获取当前用户信息(如 <code>/api/users/me</code> 接口)。</li><li>后端需要在返回信息中,带上该用户的所属角色(如 <code>[&#39;admin&#39;]</code>)以及具体的权限点(如 <code>[&#39;shop.read&#39;, &#39;shop.write&#39;]</code>)。</li><li>前端将这些角色和权限点数据格式化后,存储在 Pinia 的 <code>userStore</code> 中。</li></ol><p>如果你正在使用默认的 Strapi 5 后端,框架已经处理好了这一步的数据适配。</p><h2 id="页面级权限控制-路由鉴权" tabindex="-1">页面级权限控制 (路由鉴权) <a class="header-anchor" href="#页面级权限控制-路由鉴权" aria-label="Permalink to &quot;页面级权限控制 (路由鉴权)&quot;">​</a></h2><p>在路由里配置 <code>meta.roles</code> 或 <code>meta.permissions</code>,就能限制谁可以访问该页面。</p><h3 id="按角色拦截" tabindex="-1">按角色拦截 <a class="header-anchor" href="#按角色拦截" aria-label="Permalink to &quot;按角色拦截&quot;">​</a></h3><div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</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>
1
+ import{_ as i,o as a,c as n,a2 as h}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"权限管理","description":"","frontmatter":{},"headers":[],"relativePath":"guide/permissions.md","filePath":"guide/permissions.md","lastUpdated":1794045200000}'),t={name:"guide/permissions.md"};function l(p,s,k,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h(`<h1 id="权限管理" tabindex="-1">权限管理 <a class="header-anchor" href="#权限管理" aria-label="Permalink to &quot;权限管理&quot;">​</a></h1><p>Vue-Bag-Admin 的权限模型基于 RBAC,覆盖这几块:</p><ul><li>页面级路由权限</li><li>菜单级权限过滤</li><li>按钮和组件级权限控制</li></ul><h2 id="权限数据流转" tabindex="-1">权限数据流转 <a class="header-anchor" href="#权限数据流转" aria-label="Permalink to &quot;权限数据流转&quot;">​</a></h2><p>前端鉴权主要看 <code>userStore</code> 里的两个状态:<code>roles</code>(角色列表)和 <code>permissions</code>(权限标识列表)。</p><p>不管后端怎么写,前端这边通常按这条链路走:</p><ol><li>用户登录成功后,前端请求获取当前用户信息(如 <code>/api/users/me</code> 接口)。</li><li>后端需要在返回信息中,带上该用户的所属角色(如 <code>[&#39;admin&#39;]</code>)以及具体的权限点(如 <code>[&#39;shop.read&#39;, &#39;shop.write&#39;]</code>)。</li><li>前端将这些角色和权限点数据格式化后,存储在 Pinia 的 <code>userStore</code> 中。</li></ol><p>如果你正在使用默认的 Strapi 5 后端,框架已经处理好了这一步的数据适配。</p><h2 id="页面级权限控制-路由鉴权" tabindex="-1">页面级权限控制 (路由鉴权) <a class="header-anchor" href="#页面级权限控制-路由鉴权" aria-label="Permalink to &quot;页面级权限控制 (路由鉴权)&quot;">​</a></h2><p>在路由里配置 <code>meta.roles</code> 或 <code>meta.permissions</code>,就能限制谁可以访问该页面。</p><h3 id="按角色拦截" tabindex="-1">按角色拦截 <a class="header-anchor" href="#按角色拦截" aria-label="Permalink to &quot;按角色拦截&quot;">​</a></h3><div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</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>
2
2
  <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;">&#39;/admin/settings&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
3
3
  <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;">=&gt;</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;">&#39;./views/Settings.vue&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">),</span></span>
4
4
  <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> meta</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">: {</span></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as h}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"权限管理","description":"","frontmatter":{},"headers":[],"relativePath":"guide/permissions.md","filePath":"guide/permissions.md","lastUpdated":1794045200000}'),t={name:"guide/permissions.md"};function l(p,s,k,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h("",53)])])}const o=i(t,[["render",l]]);export{g as __pageData,o as default};
1
+ import{_ as i,o as a,c as n,a2 as h}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"权限管理","description":"","frontmatter":{},"headers":[],"relativePath":"guide/permissions.md","filePath":"guide/permissions.md","lastUpdated":1794045200000}'),t={name:"guide/permissions.md"};function l(p,s,k,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h("",53)])])}const o=i(t,[["render",l]]);export{g as __pageData,o as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"插件化开发","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugin-development.md","filePath":"guide/plugin-development.md","lastUpdated":1794045200000}'),p={name:"guide/plugin-development.md"};function h(t,s,k,e,E,d){return a(),n("div",null,[...s[0]||(s[0]=[l(`<h1 id="插件化开发" tabindex="-1">插件化开发 <a class="header-anchor" href="#插件化开发" aria-label="Permalink to &quot;插件化开发&quot;">​</a></h1><p>Vue-Bag-Admin 把应用拆成两块,宿主应用负责跑起来,业务插件负责放页面和配置。相对独立的业务域,放进 <code>comps-bag-*</code> 包里会更好维护。</p><p>如果你准备把插件单独发到 npm,这篇可以直接当起点。仓库里的插件包已经按发布形态收过一轮,新插件照这个结构走,后面少补很多边角。</p><h2 id="插件能提供什么" tabindex="-1">插件能提供什么 <a class="header-anchor" href="#插件能提供什么" aria-label="Permalink to &quot;插件能提供什么&quot;">​</a></h2><p>一个插件通常会带这些东西:</p><ul><li>业务页面组件</li><li>路由定义</li><li>菜单定义</li><li>多语言词条</li><li>初始化安装钩子</li><li>权限点声明</li><li>插件配置项声明</li><li>扩展点贡献</li><li>插件元信息(启用状态、顺序、依赖)</li></ul><h2 id="adminplugin-结构" tabindex="-1">AdminPlugin 结构 <a class="header-anchor" href="#adminplugin-结构" aria-label="Permalink to &quot;AdminPlugin 结构&quot;">​</a></h2><p>当前插件接口除了基础的 <code>id</code>、<code>name</code>、<code>version</code> 外,还支持这些元信息:</p><ul><li><code>enabled</code>:是否默认启用,设为 <code>false</code> 时不会注册</li><li><code>order</code>:插件排序,值越小越先注册</li><li><code>dependsOn</code>:依赖的插件 <code>id</code> 列表</li><li><code>routes</code>:插件提供的路由</li><li><code>menus</code>:插件提供的菜单</li><li><code>locales</code>:插件提供的语言包</li><li><code>permissions</code>:插件声明的权限点,宿主可以汇总到角色/权限后台</li><li><code>settings</code>:插件声明的配置项,宿主可以生成插件配置页</li><li><code>contributes</code>:插件贡献到宿主扩展点的能力,例如快捷入口、工具栏动作、卡片等</li><li><code>compatibility</code>:插件声明的宿主或 Vue 版本兼容范围</li><li><code>install</code>:安装钩子,能拿到 <code>app</code>、<code>router</code> 和当前已启用插件列表</li><li><code>dispose</code>:卸载或应用重引导前的清理钩子</li></ul><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:#D73A49;--shiki-dark:#F97583;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { AdminPlugin } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-core&#39;</span></span>
1
+ import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"插件化开发","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugin-development.md","filePath":"guide/plugin-development.md","lastUpdated":1794045200000}'),p={name:"guide/plugin-development.md"};function h(t,s,k,e,E,d){return a(),n("div",null,[...s[0]||(s[0]=[l(`<h1 id="插件化开发" tabindex="-1">插件化开发 <a class="header-anchor" href="#插件化开发" aria-label="Permalink to &quot;插件化开发&quot;">​</a></h1><p>Vue-Bag-Admin 把应用拆成两块,宿主应用负责跑起来,业务插件负责放页面和配置。相对独立的业务域,放进 <code>comps-bag-*</code> 包里会更好维护。</p><p>如果你准备把插件单独发到 npm,这篇可以直接当起点。仓库里的插件包已经按发布形态收过一轮,新插件照这个结构走,后面少补很多边角。</p><h2 id="插件能提供什么" tabindex="-1">插件能提供什么 <a class="header-anchor" href="#插件能提供什么" aria-label="Permalink to &quot;插件能提供什么&quot;">​</a></h2><p>一个插件通常会带这些东西:</p><ul><li>业务页面组件</li><li>路由定义</li><li>菜单定义</li><li>多语言词条</li><li>初始化安装钩子</li><li>权限点声明</li><li>插件配置项声明</li><li>扩展点贡献</li><li>插件元信息(启用状态、顺序、依赖)</li></ul><h2 id="adminplugin-结构" tabindex="-1">AdminPlugin 结构 <a class="header-anchor" href="#adminplugin-结构" aria-label="Permalink to &quot;AdminPlugin 结构&quot;">​</a></h2><p>当前插件接口除了基础的 <code>id</code>、<code>name</code>、<code>version</code> 外,还支持这些元信息:</p><ul><li><code>enabled</code>:是否默认启用,设为 <code>false</code> 时不会注册</li><li><code>order</code>:插件排序,值越小越先注册</li><li><code>dependsOn</code>:依赖的插件 <code>id</code> 列表</li><li><code>routes</code>:插件提供的路由</li><li><code>menus</code>:插件提供的菜单</li><li><code>locales</code>:插件提供的语言包</li><li><code>permissions</code>:插件声明的权限点,宿主可以汇总到角色/权限后台</li><li><code>settings</code>:插件声明的配置项,宿主可以生成插件配置页</li><li><code>contributes</code>:插件贡献到宿主扩展点的能力,例如快捷入口、工具栏动作、卡片等</li><li><code>compatibility</code>:插件声明的宿主或 Vue 版本兼容范围</li><li><code>install</code>:安装钩子,能拿到 <code>app</code>、<code>router</code> 和当前已启用插件列表</li><li><code>dispose</code>:卸载或应用重引导前的清理钩子</li></ul><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:#D73A49;--shiki-dark:#F97583;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { AdminPlugin } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-core&#39;</span></span>
2
2
  <span class="line"></span>
3
3
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> plugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AdminPlugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
4
4
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;plugin-report&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"插件化开发","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugin-development.md","filePath":"guide/plugin-development.md","lastUpdated":1794045200000}'),p={name:"guide/plugin-development.md"};function h(t,s,k,e,E,d){return a(),n("div",null,[...s[0]||(s[0]=[l("",75)])])}const o=i(p,[["render",h]]);export{g as __pageData,o as default};
1
+ import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"插件化开发","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugin-development.md","filePath":"guide/plugin-development.md","lastUpdated":1794045200000}'),p={name:"guide/plugin-development.md"};function h(t,s,k,e,E,d){return a(),n("div",null,[...s[0]||(s[0]=[l("",75)])])}const o=i(p,[["render",h]]);export{g as __pageData,o as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B3lxS50j.js";const E=JSON.parse('{"title":"AdminPlugin 配置","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/admin-plugin.md","filePath":"guide/plugins/admin-plugin.md","lastUpdated":1794045200000}'),e={name:"guide/plugins/admin-plugin.md"};function l(p,s,h,d,k,r){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="adminplugin-配置" tabindex="-1">AdminPlugin 配置 <a class="header-anchor" href="#adminplugin-配置" aria-label="Permalink to &quot;AdminPlugin 配置&quot;">​</a></h1><p><code>AdminPlugin</code> 是宿主与业务插件之间的核心协议。宿主不扫描插件目录,而是读取这个对象,决定要注册哪些路由、菜单、语言包和初始化逻辑。</p><h2 id="最小插件" tabindex="-1">最小插件 <a class="header-anchor" href="#最小插件" aria-label="Permalink to &quot;最小插件&quot;">​</a></h2><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:#D73A49;--shiki-dark:#F97583;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { AdminPlugin } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-entry&#39;</span></span>
1
+ import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.Olv9GB1A.js";const E=JSON.parse('{"title":"AdminPlugin 配置","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/admin-plugin.md","filePath":"guide/plugins/admin-plugin.md","lastUpdated":1794045200000}'),e={name:"guide/plugins/admin-plugin.md"};function l(p,s,h,d,k,r){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="adminplugin-配置" tabindex="-1">AdminPlugin 配置 <a class="header-anchor" href="#adminplugin-配置" aria-label="Permalink to &quot;AdminPlugin 配置&quot;">​</a></h1><p><code>AdminPlugin</code> 是宿主与业务插件之间的核心协议。宿主不扫描插件目录,而是读取这个对象,决定要注册哪些路由、菜单、语言包和初始化逻辑。</p><h2 id="最小插件" tabindex="-1">最小插件 <a class="header-anchor" href="#最小插件" aria-label="Permalink to &quot;最小插件&quot;">​</a></h2><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:#D73A49;--shiki-dark:#F97583;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { AdminPlugin } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-entry&#39;</span></span>
2
2
  <span class="line"></span>
3
3
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> reportPlugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AdminPlugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
4
4
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;report-plugin&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">, </span><span style="--shiki-light:#6A737D;--shiki-dark:#6A737D;">// 运行时唯一标识</span></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B3lxS50j.js";const E=JSON.parse('{"title":"AdminPlugin 配置","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/admin-plugin.md","filePath":"guide/plugins/admin-plugin.md","lastUpdated":1794045200000}'),e={name:"guide/plugins/admin-plugin.md"};function l(p,s,h,d,k,r){return a(),n("div",null,[...s[0]||(s[0]=[t("",33)])])}const c=i(e,[["render",l]]);export{E as __pageData,c as default};
1
+ import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.Olv9GB1A.js";const E=JSON.parse('{"title":"AdminPlugin 配置","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/admin-plugin.md","filePath":"guide/plugins/admin-plugin.md","lastUpdated":1794045200000}'),e={name:"guide/plugins/admin-plugin.md"};function l(p,s,h,d,k,r){return a(),n("div",null,[...s[0]||(s[0]=[t("",33)])])}const c=i(e,[["render",l]]);export{E as __pageData,c as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"插件开发","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/create-plugin.md","filePath":"guide/plugins/create-plugin.md","lastUpdated":1794045200000}'),t={name:"guide/plugins/create-plugin.md"};function p(h,s,k,e,E,d){return a(),n("div",null,[...s[0]||(s[0]=[l(`<h1 id="插件开发" tabindex="-1">插件开发 <a class="header-anchor" href="#插件开发" aria-label="Permalink to &quot;插件开发&quot;">​</a></h1><p>插件用来封装一个相对独立的业务域,例如内容、报表、订单或系统设置。一个插件可以同时提供页面、路由、菜单、多语言和初始化逻辑。</p><p>建议先开发本地插件。只有需要跨项目复用时,再把它迁移成独立 npm 包。</p><h2 id="创建页面" tabindex="-1">创建页面 <a class="header-anchor" href="#创建页面" aria-label="Permalink to &quot;创建页面&quot;">​</a></h2><p>先创建 <code>src/views/ReportList.vue</code>:</p><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;">&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
1
+ import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"插件开发","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/create-plugin.md","filePath":"guide/plugins/create-plugin.md","lastUpdated":1794045200000}'),t={name:"guide/plugins/create-plugin.md"};function p(h,s,k,e,E,d){return a(),n("div",null,[...s[0]||(s[0]=[l(`<h1 id="插件开发" tabindex="-1">插件开发 <a class="header-anchor" href="#插件开发" aria-label="Permalink to &quot;插件开发&quot;">​</a></h1><p>插件用来封装一个相对独立的业务域,例如内容、报表、订单或系统设置。一个插件可以同时提供页面、路由、菜单、多语言和初始化逻辑。</p><p>建议先开发本地插件。只有需要跨项目复用时,再把它迁移成独立 npm 包。</p><h2 id="创建页面" tabindex="-1">创建页面 <a class="header-anchor" href="#创建页面" aria-label="Permalink to &quot;创建页面&quot;">​</a></h2><p>先创建 <code>src/views/ReportList.vue</code>:</p><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;">&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
2
2
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">section</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;rounded-xl bg-white p-6&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
3
3
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">h1</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;text-xl font-semibold&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;报表中心&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">h1</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
4
4
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">p</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> class</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;mt-2 text-slate-500&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;这是由本地插件提供的页面。&lt;/</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">p</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"插件开发","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/create-plugin.md","filePath":"guide/plugins/create-plugin.md","lastUpdated":1794045200000}'),t={name:"guide/plugins/create-plugin.md"};function p(h,s,k,e,E,d){return a(),n("div",null,[...s[0]||(s[0]=[l("",41)])])}const y=i(t,[["render",p]]);export{g as __pageData,y as default};
1
+ import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"插件开发","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/create-plugin.md","filePath":"guide/plugins/create-plugin.md","lastUpdated":1794045200000}'),t={name:"guide/plugins/create-plugin.md"};function p(h,s,k,e,E,d){return a(),n("div",null,[...s[0]||(s[0]=[l("",41)])])}const y=i(t,[["render",p]]);export{g as __pageData,y as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B3lxS50j.js";const o=JSON.parse('{"title":"调试与发布","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/debug-and-publish.md","filePath":"guide/plugins/debug-and-publish.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/debug-and-publish.md"};function l(h,s,e,k,d,E){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="调试与发布" tabindex="-1">调试与发布 <a class="header-anchor" href="#调试与发布" aria-label="Permalink to &quot;调试与发布&quot;">​</a></h1><p>本地业务插件可以直接跟随宿主开发。只有插件需要跨项目复用或独立升级时,才需要建立 npm 包、构建产物和发布流程。</p><h2 id="本地插件调试" tabindex="-1">本地插件调试 <a class="header-anchor" href="#本地插件调试" aria-label="Permalink to &quot;本地插件调试&quot;">​</a></h2><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>src/</span></span>
1
+ import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.Olv9GB1A.js";const o=JSON.parse('{"title":"调试与发布","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/debug-and-publish.md","filePath":"guide/plugins/debug-and-publish.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/debug-and-publish.md"};function l(h,s,e,k,d,E){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="调试与发布" tabindex="-1">调试与发布 <a class="header-anchor" href="#调试与发布" aria-label="Permalink to &quot;调试与发布&quot;">​</a></h1><p>本地业务插件可以直接跟随宿主开发。只有插件需要跨项目复用或独立升级时,才需要建立 npm 包、构建产物和发布流程。</p><h2 id="本地插件调试" tabindex="-1">本地插件调试 <a class="header-anchor" href="#本地插件调试" aria-label="Permalink to &quot;本地插件调试&quot;">​</a></h2><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>src/</span></span>
2
2
  <span class="line"><span>├── plugins/</span></span>
3
3
  <span class="line"><span>│ └── report.ts</span></span>
4
4
  <span class="line"><span>└── views/</span></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B3lxS50j.js";const o=JSON.parse('{"title":"调试与发布","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/debug-and-publish.md","filePath":"guide/plugins/debug-and-publish.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/debug-and-publish.md"};function l(h,s,e,k,d,E){return a(),n("div",null,[...s[0]||(s[0]=[t("",51)])])}const g=i(p,[["render",l]]);export{o as __pageData,g as default};
1
+ import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.Olv9GB1A.js";const o=JSON.parse('{"title":"调试与发布","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/debug-and-publish.md","filePath":"guide/plugins/debug-and-publish.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/debug-and-publish.md"};function l(h,s,e,k,d,E){return a(),n("div",null,[...s[0]||(s[0]=[t("",51)])])}const g=i(p,[["render",l]]);export{o as __pageData,g as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.B3lxS50j.js";const o=JSON.parse('{"title":"生命周期与依赖","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/lifecycle-and-dependencies.md","filePath":"guide/plugins/lifecycle-and-dependencies.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/lifecycle-and-dependencies.md"};function h(e,s,t,k,d,E){return a(),n("div",null,[...s[0]||(s[0]=[l(`<h1 id="生命周期与依赖" tabindex="-1">生命周期与依赖 <a class="header-anchor" href="#生命周期与依赖" aria-label="Permalink to &quot;生命周期与依赖&quot;">​</a></h1><p>插件引导不是简单遍历数组。宿主会先确定启用集合、检查依赖和冲突,再按顺序注册能力。</p><h2 id="引导顺序" tabindex="-1">引导顺序 <a class="header-anchor" href="#引导顺序" aria-label="Permalink to &quot;引导顺序&quot;">​</a></h2><p><code>bootstrapPlugins()</code> 当前按下面流程执行:</p><ol><li>设置自定义 <code>pluginStateProvider</code>。</li><li>初始化宿主 UI 配置。</li><li>保存本次传入的运行时插件清单。</li><li>按 <code>order</code> 升序排序。</li><li>过滤 <code>enabled: false</code> 和禁用列表中的插件。</li><li>检查 <code>dependsOn</code> 是否都在启用集合中。</li><li>检查插件、路由和菜单冲突。</li><li>依次注册路由、菜单和语言包。</li><li>依次执行插件 <code>install()</code>。</li><li>把 Router 安装到 Vue 应用。</li></ol><p>任一步抛出错误都会中断应用引导。</p><h2 id="注册顺序" tabindex="-1">注册顺序 <a class="header-anchor" href="#注册顺序" aria-label="Permalink to &quot;注册顺序&quot;">​</a></h2><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;"> corePlugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AdminPlugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
1
+ import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.Olv9GB1A.js";const o=JSON.parse('{"title":"生命周期与依赖","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/lifecycle-and-dependencies.md","filePath":"guide/plugins/lifecycle-and-dependencies.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/lifecycle-and-dependencies.md"};function h(e,s,t,k,d,E){return a(),n("div",null,[...s[0]||(s[0]=[l(`<h1 id="生命周期与依赖" tabindex="-1">生命周期与依赖 <a class="header-anchor" href="#生命周期与依赖" aria-label="Permalink to &quot;生命周期与依赖&quot;">​</a></h1><p>插件引导不是简单遍历数组。宿主会先确定启用集合、检查依赖和冲突,再按顺序注册能力。</p><h2 id="引导顺序" tabindex="-1">引导顺序 <a class="header-anchor" href="#引导顺序" aria-label="Permalink to &quot;引导顺序&quot;">​</a></h2><p><code>bootstrapPlugins()</code> 当前按下面流程执行:</p><ol><li>设置自定义 <code>pluginStateProvider</code>。</li><li>初始化宿主 UI 配置。</li><li>保存本次传入的运行时插件清单。</li><li>按 <code>order</code> 升序排序。</li><li>过滤 <code>enabled: false</code> 和禁用列表中的插件。</li><li>检查 <code>dependsOn</code> 是否都在启用集合中。</li><li>检查插件、路由和菜单冲突。</li><li>依次注册路由、菜单和语言包。</li><li>依次执行插件 <code>install()</code>。</li><li>把 Router 安装到 Vue 应用。</li></ol><p>任一步抛出错误都会中断应用引导。</p><h2 id="注册顺序" tabindex="-1">注册顺序 <a class="header-anchor" href="#注册顺序" aria-label="Permalink to &quot;注册顺序&quot;">​</a></h2><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;"> corePlugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AdminPlugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
2
2
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;report-core&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
3
3
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;报表基础插件&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
4
4
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> version: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;1.0.0&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.B3lxS50j.js";const o=JSON.parse('{"title":"生命周期与依赖","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/lifecycle-and-dependencies.md","filePath":"guide/plugins/lifecycle-and-dependencies.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/lifecycle-and-dependencies.md"};function h(e,s,t,k,d,E){return a(),n("div",null,[...s[0]||(s[0]=[l("",38)])])}const g=i(p,[["render",h]]);export{o as __pageData,g as default};
1
+ import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.Olv9GB1A.js";const o=JSON.parse('{"title":"生命周期与依赖","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/lifecycle-and-dependencies.md","filePath":"guide/plugins/lifecycle-and-dependencies.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/lifecycle-and-dependencies.md"};function h(e,s,t,k,d,E){return a(),n("div",null,[...s[0]||(s[0]=[l("",38)])])}const g=i(p,[["render",h]]);export{o as __pageData,g as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"权限与配置项","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/permissions-and-settings.md","filePath":"guide/plugins/permissions-and-settings.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/permissions-and-settings.md"};function l(h,s,e,k,E,d){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="权限与配置项" tabindex="-1">权限与配置项 <a class="header-anchor" href="#权限与配置项" aria-label="Permalink to &quot;权限与配置项&quot;">​</a></h1><p>插件可以声明权限点、配置项和扩展点。这些声明用于描述插件能力,但是否保护页面、生成设置界面或渲染扩展内容,需要宿主或业务项目明确实现。</p><h2 id="声明权限点" tabindex="-1">声明权限点 <a class="header-anchor" href="#声明权限点" aria-label="Permalink to &quot;声明权限点&quot;">​</a></h2><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;"> reportPlugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AdminPlugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
1
+ import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"权限与配置项","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/permissions-and-settings.md","filePath":"guide/plugins/permissions-and-settings.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/permissions-and-settings.md"};function l(h,s,e,k,E,d){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="权限与配置项" tabindex="-1">权限与配置项 <a class="header-anchor" href="#权限与配置项" aria-label="Permalink to &quot;权限与配置项&quot;">​</a></h1><p>插件可以声明权限点、配置项和扩展点。这些声明用于描述插件能力,但是否保护页面、生成设置界面或渲染扩展内容,需要宿主或业务项目明确实现。</p><h2 id="声明权限点" tabindex="-1">声明权限点 <a class="header-anchor" href="#声明权限点" aria-label="Permalink to &quot;声明权限点&quot;">​</a></h2><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;"> reportPlugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AdminPlugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
2
2
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> id: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;report-plugin&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
3
3
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> name: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;报表插件&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
4
4
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> version: </span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&#39;1.0.0&#39;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">,</span></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"权限与配置项","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/permissions-and-settings.md","filePath":"guide/plugins/permissions-and-settings.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/permissions-and-settings.md"};function l(h,s,e,k,E,d){return a(),n("div",null,[...s[0]||(s[0]=[t("",37)])])}const o=i(p,[["render",l]]);export{g as __pageData,o as default};
1
+ import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"权限与配置项","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/permissions-and-settings.md","filePath":"guide/plugins/permissions-and-settings.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/permissions-and-settings.md"};function l(h,s,e,k,E,d){return a(),n("div",null,[...s[0]||(s[0]=[t("",37)])])}const o=i(p,[["render",l]]);export{g as __pageData,o as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"路由、菜单与多语言","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/routes-menus-locales.md","filePath":"guide/plugins/routes-menus-locales.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/routes-menus-locales.md"};function l(h,s,e,k,E,d){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="路由、菜单与多语言" tabindex="-1">路由、菜单与多语言 <a class="header-anchor" href="#路由、菜单与多语言" aria-label="Permalink to &quot;路由、菜单与多语言&quot;">​</a></h1><p>业务插件通常需要同时声明三部分:</p><ul><li><code>routes</code> 决定哪些页面可以访问。</li><li><code>menus</code> 决定侧边栏显示哪些入口。</li><li><code>locales</code> 为页面标题和菜单提供文案。</li></ul><p>三者通过路径和国际化 key 协作,但彼此不会自动生成。</p><h2 id="插件路由" tabindex="-1">插件路由 <a class="header-anchor" href="#插件路由" aria-label="Permalink to &quot;插件路由&quot;">​</a></h2><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:#D73A49;--shiki-dark:#F97583;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { AdminPlugin, AdminRouteRecordRaw } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-entry&#39;</span></span>
1
+ import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"路由、菜单与多语言","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/routes-menus-locales.md","filePath":"guide/plugins/routes-menus-locales.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/routes-menus-locales.md"};function l(h,s,e,k,E,d){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="路由、菜单与多语言" tabindex="-1">路由、菜单与多语言 <a class="header-anchor" href="#路由、菜单与多语言" aria-label="Permalink to &quot;路由、菜单与多语言&quot;">​</a></h1><p>业务插件通常需要同时声明三部分:</p><ul><li><code>routes</code> 决定哪些页面可以访问。</li><li><code>menus</code> 决定侧边栏显示哪些入口。</li><li><code>locales</code> 为页面标题和菜单提供文案。</li></ul><p>三者通过路径和国际化 key 协作,但彼此不会自动生成。</p><h2 id="插件路由" tabindex="-1">插件路由 <a class="header-anchor" href="#插件路由" aria-label="Permalink to &quot;插件路由&quot;">​</a></h2><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:#D73A49;--shiki-dark:#F97583;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { AdminPlugin, AdminRouteRecordRaw } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-entry&#39;</span></span>
2
2
  <span class="line"></span>
3
3
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> routes</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AdminRouteRecordRaw</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>
4
4
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"路由、菜单与多语言","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/routes-menus-locales.md","filePath":"guide/plugins/routes-menus-locales.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/routes-menus-locales.md"};function l(h,s,e,k,E,d){return a(),n("div",null,[...s[0]||(s[0]=[t("",34)])])}const c=i(p,[["render",l]]);export{g as __pageData,c as default};
1
+ import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"路由、菜单与多语言","description":"","frontmatter":{},"headers":[],"relativePath":"guide/plugins/routes-menus-locales.md","filePath":"guide/plugins/routes-menus-locales.md","lastUpdated":1794045200000}'),p={name:"guide/plugins/routes-menus-locales.md"};function l(h,s,e,k,E,d){return a(),n("div",null,[...s[0]||(s[0]=[t("",34)])])}const c=i(p,[["render",l]]);export{g as __pageData,c as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"PmProForm","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pro-form.md","filePath":"guide/pro-form.md","lastUpdated":1794045200000}'),h={name:"guide/pro-form.md"};function t(k,s,p,e,d,E){return a(),n("div",null,[...s[0]||(s[0]=[l(`<h1 id="pmproform" tabindex="-1">PmProForm <a class="header-anchor" href="#pmproform" aria-label="Permalink to &quot;PmProForm&quot;">​</a></h1><p><code>PmProForm</code> 是框架里内置的通用表单组件,主要处理后台里最常见的几类页面:新增、编辑、搜索和详情展示。</p><p>我做它的出发点很直接,就是把那些反复出现的字段声明、校验、布局和提交动作收起来,别让页面里到处都是重复的 <code>NFormItem</code>。</p><h2 id="适用场景" tabindex="-1">适用场景 <a class="header-anchor" href="#适用场景" aria-label="Permalink to &quot;适用场景&quot;">​</a></h2><p>这些页面很适合优先上 <code>PmProForm</code>:</p><ul><li>个人信息编辑</li><li>商品新增与编辑</li><li>系统配置表单</li><li>查询筛选区</li><li>详情页只读表单</li></ul><h2 id="基础用法" tabindex="-1">基础用法 <a class="header-anchor" href="#基础用法" aria-label="Permalink to &quot;基础用法&quot;">​</a></h2><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;">&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
1
+ import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"PmProForm","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pro-form.md","filePath":"guide/pro-form.md","lastUpdated":1794045200000}'),h={name:"guide/pro-form.md"};function t(k,s,p,e,d,E){return a(),n("div",null,[...s[0]||(s[0]=[l(`<h1 id="pmproform" tabindex="-1">PmProForm <a class="header-anchor" href="#pmproform" aria-label="Permalink to &quot;PmProForm&quot;">​</a></h1><p><code>PmProForm</code> 是框架里内置的通用表单组件,主要处理后台里最常见的几类页面:新增、编辑、搜索和详情展示。</p><p>我做它的出发点很直接,就是把那些反复出现的字段声明、校验、布局和提交动作收起来,别让页面里到处都是重复的 <code>NFormItem</code>。</p><h2 id="适用场景" tabindex="-1">适用场景 <a class="header-anchor" href="#适用场景" aria-label="Permalink to &quot;适用场景&quot;">​</a></h2><p>这些页面很适合优先上 <code>PmProForm</code>:</p><ul><li>个人信息编辑</li><li>商品新增与编辑</li><li>系统配置表单</li><li>查询筛选区</li><li>详情页只读表单</li></ul><h2 id="基础用法" tabindex="-1">基础用法 <a class="header-anchor" href="#基础用法" aria-label="Permalink to &quot;基础用法&quot;">​</a></h2><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;">&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
2
2
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">PmProForm</span></span>
3
3
  <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> v-model</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">formValue</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span></span>
4
4
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> :</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;">schemas</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">schemas</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;</span></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"PmProForm","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pro-form.md","filePath":"guide/pro-form.md","lastUpdated":1794045200000}'),h={name:"guide/pro-form.md"};function t(k,s,p,e,d,E){return a(),n("div",null,[...s[0]||(s[0]=[l("",38)])])}const F=i(h,[["render",t]]);export{g as __pageData,F as default};
1
+ import{_ as i,o as a,c as n,a2 as l}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"PmProForm","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pro-form.md","filePath":"guide/pro-form.md","lastUpdated":1794045200000}'),h={name:"guide/pro-form.md"};function t(k,s,p,e,d,E){return a(),n("div",null,[...s[0]||(s[0]=[l("",38)])])}const F=i(h,[["render",t]]);export{g as __pageData,F as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as t,a2 as l}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"PmProTable","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pro-table.md","filePath":"guide/pro-table.md","lastUpdated":1794045200000}'),h={name:"guide/pro-table.md"};function n(k,s,e,p,E,d){return a(),t("div",null,[...s[0]||(s[0]=[l(`<h1 id="pmprotable" tabindex="-1">PmProTable <a class="header-anchor" href="#pmprotable" aria-label="Permalink to &quot;PmProTable&quot;">​</a></h1><p><code>PmProTable</code> 是框架里内置的通用列表组件,主要拿来解决后台最常见的那类页面:查询、表格、分页,再加一个刷新。</p><h2 id="适用场景" tabindex="-1">适用场景 <a class="header-anchor" href="#适用场景" aria-label="Permalink to &quot;适用场景&quot;">​</a></h2><p>下面这些页面,基本都可以优先考虑它:</p><ul><li>商品列表</li><li>订单列表</li><li>用户列表</li><li>操作日志</li><li>报表明细列表</li></ul><h2 id="基础用法" tabindex="-1">基础用法 <a class="header-anchor" href="#基础用法" aria-label="Permalink to &quot;基础用法&quot;">​</a></h2><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;">&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
1
+ import{_ as i,o as a,c as t,a2 as l}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"PmProTable","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pro-table.md","filePath":"guide/pro-table.md","lastUpdated":1794045200000}'),h={name:"guide/pro-table.md"};function n(k,s,e,p,E,d){return a(),t("div",null,[...s[0]||(s[0]=[l(`<h1 id="pmprotable" tabindex="-1">PmProTable <a class="header-anchor" href="#pmprotable" aria-label="Permalink to &quot;PmProTable&quot;">​</a></h1><p><code>PmProTable</code> 是框架里内置的通用列表组件,主要拿来解决后台最常见的那类页面:查询、表格、分页,再加一个刷新。</p><h2 id="适用场景" tabindex="-1">适用场景 <a class="header-anchor" href="#适用场景" aria-label="Permalink to &quot;适用场景&quot;">​</a></h2><p>下面这些页面,基本都可以优先考虑它:</p><ul><li>商品列表</li><li>订单列表</li><li>用户列表</li><li>操作日志</li><li>报表明细列表</li></ul><h2 id="基础用法" tabindex="-1">基础用法 <a class="header-anchor" href="#基础用法" aria-label="Permalink to &quot;基础用法&quot;">​</a></h2><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;">&lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">template</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">&gt;</span></span>
2
2
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> &lt;</span><span style="--shiki-light:#22863A;--shiki-dark:#85E89D;">PmProTable</span></span>
3
3
  <span class="line"><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> ref</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">=</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;">&quot;tableRef&quot;</span></span>
4
4
  <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;">&quot;商品列表&quot;</span></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as t,a2 as l}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"PmProTable","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pro-table.md","filePath":"guide/pro-table.md","lastUpdated":1794045200000}'),h={name:"guide/pro-table.md"};function n(k,s,e,p,E,d){return a(),t("div",null,[...s[0]||(s[0]=[l("",44)])])}const o=i(h,[["render",n]]);export{g as __pageData,o as default};
1
+ import{_ as i,o as a,c as t,a2 as l}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"PmProTable","description":"","frontmatter":{},"headers":[],"relativePath":"guide/pro-table.md","filePath":"guide/pro-table.md","lastUpdated":1794045200000}'),h={name:"guide/pro-table.md"};function n(k,s,e,p,E,d){return a(),t("div",null,[...s[0]||(s[0]=[l("",44)])])}const o=i(h,[["render",n]]);export{g as __pageData,o as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as h}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"请求与组件","description":"","frontmatter":{},"headers":[],"relativePath":"guide/request-and-components.md","filePath":"guide/request-and-components.md","lastUpdated":1794045200000}'),l={name:"guide/request-and-components.md"};function k(p,s,t,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h(`<h1 id="请求与组件" tabindex="-1">请求与组件 <a class="header-anchor" href="#请求与组件" aria-label="Permalink to &quot;请求与组件&quot;">​</a></h1><p>业务插件最终需要完成两件事:从后端读取数据,并把数据组织成列表或表单。</p><p><code>@melt-js/libs-bag-entry</code> 统一导出了请求能力和基础 UI 组件,业务项目不需要分别安装或导入 <code>@melt-js/libs-bag-request</code>、<code>@melt-js/libs-bag-ui</code>。</p><h2 id="初始化请求" tabindex="-1">初始化请求 <a class="header-anchor" href="#初始化请求" aria-label="Permalink to &quot;初始化请求&quot;">​</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;"> { getHostNavigationConfig, setupHttp, useUserStore } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-entry&#39;</span></span>
1
+ import{_ as i,o as a,c as n,a2 as h}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"请求与组件","description":"","frontmatter":{},"headers":[],"relativePath":"guide/request-and-components.md","filePath":"guide/request-and-components.md","lastUpdated":1794045200000}'),l={name:"guide/request-and-components.md"};function k(p,s,t,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h(`<h1 id="请求与组件" tabindex="-1">请求与组件 <a class="header-anchor" href="#请求与组件" aria-label="Permalink to &quot;请求与组件&quot;">​</a></h1><p>业务插件最终需要完成两件事:从后端读取数据,并把数据组织成列表或表单。</p><p><code>@melt-js/libs-bag-entry</code> 统一导出了请求能力和基础 UI 组件,业务项目不需要分别安装或导入 <code>@melt-js/libs-bag-request</code>、<code>@melt-js/libs-bag-ui</code>。</p><h2 id="初始化请求" tabindex="-1">初始化请求 <a class="header-anchor" href="#初始化请求" aria-label="Permalink to &quot;初始化请求&quot;">​</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;"> { getHostNavigationConfig, setupHttp, useUserStore } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-entry&#39;</span></span>
2
2
  <span class="line"></span>
3
3
  <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>
4
4
  <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>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as h}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"请求与组件","description":"","frontmatter":{},"headers":[],"relativePath":"guide/request-and-components.md","filePath":"guide/request-and-components.md","lastUpdated":1794045200000}'),l={name:"guide/request-and-components.md"};function k(p,s,t,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h("",34)])])}const y=i(l,[["render",k]]);export{g as __pageData,y as default};
1
+ import{_ as i,o as a,c as n,a2 as h}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"请求与组件","description":"","frontmatter":{},"headers":[],"relativePath":"guide/request-and-components.md","filePath":"guide/request-and-components.md","lastUpdated":1794045200000}'),l={name:"guide/request-and-components.md"};function k(p,s,t,e,E,r){return a(),n("div",null,[...s[0]||(s[0]=[h("",34)])])}const y=i(l,[["render",k]]);export{g as __pageData,y as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B3lxS50j.js";const c=JSON.parse('{"title":"路由与菜单","description":"","frontmatter":{},"headers":[],"relativePath":"guide/routing-and-menu.md","filePath":"guide/routing-and-menu.md","lastUpdated":1794045200000}'),e={name:"guide/routing-and-menu.md"};function l(h,s,p,k,d,E){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="路由与菜单" tabindex="-1">路由与菜单 <a class="header-anchor" href="#路由与菜单" aria-label="Permalink to &quot;路由与菜单&quot;">​</a></h1><p>很多后台项目会把路由和菜单塞进一个大配置文件。Vue-Bag-Admin 走插件化路线,路由和菜单分散在各个业务插件里,宿主启动时再收集注册。</p><h2 id="路由配置" tabindex="-1">路由配置 <a class="header-anchor" href="#路由配置" aria-label="Permalink to &quot;路由配置&quot;">​</a></h2><p>路由配置沿用 <a href="https://router.vuejs.org/zh/" target="_blank" rel="noreferrer">Vue Router 4</a> 的写法,只是在 <code>meta</code> 字段里放后台需要的权限、布局、缓存和菜单信息。</p><h3 id="注册路由" tabindex="-1">注册路由 <a class="header-anchor" href="#注册路由" aria-label="Permalink to &quot;注册路由&quot;">​</a></h3><p>在插件入口文件中,通过 <code>routes</code> 导出路由:</p><div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</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:#D73A49;--shiki-dark:#F97583;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { AdminPlugin } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-core&#39;</span></span>
1
+ import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.Olv9GB1A.js";const c=JSON.parse('{"title":"路由与菜单","description":"","frontmatter":{},"headers":[],"relativePath":"guide/routing-and-menu.md","filePath":"guide/routing-and-menu.md","lastUpdated":1794045200000}'),e={name:"guide/routing-and-menu.md"};function l(h,s,p,k,d,E){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="路由与菜单" tabindex="-1">路由与菜单 <a class="header-anchor" href="#路由与菜单" aria-label="Permalink to &quot;路由与菜单&quot;">​</a></h1><p>很多后台项目会把路由和菜单塞进一个大配置文件。Vue-Bag-Admin 走插件化路线,路由和菜单分散在各个业务插件里,宿主启动时再收集注册。</p><h2 id="路由配置" tabindex="-1">路由配置 <a class="header-anchor" href="#路由配置" aria-label="Permalink to &quot;路由配置&quot;">​</a></h2><p>路由配置沿用 <a href="https://router.vuejs.org/zh/" target="_blank" rel="noreferrer">Vue Router 4</a> 的写法,只是在 <code>meta</code> 字段里放后台需要的权限、布局、缓存和菜单信息。</p><h3 id="注册路由" tabindex="-1">注册路由 <a class="header-anchor" href="#注册路由" aria-label="Permalink to &quot;注册路由&quot;">​</a></h3><p>在插件入口文件中,通过 <code>routes</code> 导出路由:</p><div class="language-typescript vp-adaptive-theme"><button title="Copy Code" class="copy"></button><span class="lang">typescript</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:#D73A49;--shiki-dark:#F97583;"> type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> { AdminPlugin } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-core&#39;</span></span>
2
2
  <span class="line"></span>
3
3
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> plugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">:</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> AdminPlugin</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> {</span></span>
4
4
  <span class="line"><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> routes: [</span></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B3lxS50j.js";const c=JSON.parse('{"title":"路由与菜单","description":"","frontmatter":{},"headers":[],"relativePath":"guide/routing-and-menu.md","filePath":"guide/routing-and-menu.md","lastUpdated":1794045200000}'),e={name:"guide/routing-and-menu.md"};function l(h,s,p,k,d,E){return a(),n("div",null,[...s[0]||(s[0]=[t("",36)])])}const o=i(e,[["render",l]]);export{c as __pageData,o as default};
1
+ import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.Olv9GB1A.js";const c=JSON.parse('{"title":"路由与菜单","description":"","frontmatter":{},"headers":[],"relativePath":"guide/routing-and-menu.md","filePath":"guide/routing-and-menu.md","lastUpdated":1794045200000}'),e={name:"guide/routing-and-menu.md"};function l(h,s,p,k,d,E){return a(),n("div",null,[...s[0]||(s[0]=[t("",36)])])}const o=i(e,[["render",l]]);export{c as __pageData,o as default};
@@ -1,4 +1,4 @@
1
- import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"主题与布局 Token","description":"","frontmatter":{},"headers":[],"relativePath":"guide/theme-tokens.md","filePath":"guide/theme-tokens.md","lastUpdated":1794045200000}'),p={name:"guide/theme-tokens.md"};function l(h,s,e,k,E,r){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="主题与布局-token" tabindex="-1">主题与布局 Token <a class="header-anchor" href="#主题与布局-token" aria-label="Permalink to &quot;主题与布局 Token&quot;">​</a></h1><p>宿主的外观配置分两层:</p><ul><li><code>useAppConfigStore()</code> 保存用户选择,比如亮暗色、主题色、内容宽度、标签页、页脚和页面动画。</li><li><code>createThemeTokens()</code> 根据这些选择生成语义 token,并通过 CSS 变量落到 <code>document.documentElement</code>。</li></ul><p>这样设置页只是入口,布局、组件和插件真正消费的是稳定的 token 契约。</p><h2 id="常用-api" tabindex="-1">常用 API <a class="header-anchor" href="#常用-api" aria-label="Permalink to &quot;常用 API&quot;">​</a></h2><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;"> { createThemeTokens, useAppConfigStore, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ThemeTokens } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-entry&#39;</span></span>
1
+ import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"主题与布局 Token","description":"","frontmatter":{},"headers":[],"relativePath":"guide/theme-tokens.md","filePath":"guide/theme-tokens.md","lastUpdated":1794045200000}'),p={name:"guide/theme-tokens.md"};function l(h,s,e,k,E,r){return a(),n("div",null,[...s[0]||(s[0]=[t(`<h1 id="主题与布局-token" tabindex="-1">主题与布局 Token <a class="header-anchor" href="#主题与布局-token" aria-label="Permalink to &quot;主题与布局 Token&quot;">​</a></h1><p>宿主的外观配置分两层:</p><ul><li><code>useAppConfigStore()</code> 保存用户选择,比如亮暗色、主题色、内容宽度、标签页、页脚和页面动画。</li><li><code>createThemeTokens()</code> 根据这些选择生成语义 token,并通过 CSS 变量落到 <code>document.documentElement</code>。</li></ul><p>这样设置页只是入口,布局、组件和插件真正消费的是稳定的 token 契约。</p><h2 id="常用-api" tabindex="-1">常用 API <a class="header-anchor" href="#常用-api" aria-label="Permalink to &quot;常用 API&quot;">​</a></h2><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;"> { createThemeTokens, useAppConfigStore, </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">type</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;"> ThemeTokens } </span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">from</span><span style="--shiki-light:#032F62;--shiki-dark:#9ECBFF;"> &#39;@melt-js/libs-bag-entry&#39;</span></span>
2
2
  <span class="line"></span>
3
3
  <span class="line"><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;">const</span><span style="--shiki-light:#005CC5;--shiki-dark:#79B8FF;"> appConfigStore</span><span style="--shiki-light:#D73A49;--shiki-dark:#F97583;"> =</span><span style="--shiki-light:#6F42C1;--shiki-dark:#B392F0;"> useAppConfigStore</span><span style="--shiki-light:#24292E;--shiki-dark:#E1E4E8;">()</span></span>
4
4
  <span class="line"></span>
@@ -1 +1 @@
1
- import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.B3lxS50j.js";const g=JSON.parse('{"title":"主题与布局 Token","description":"","frontmatter":{},"headers":[],"relativePath":"guide/theme-tokens.md","filePath":"guide/theme-tokens.md","lastUpdated":1794045200000}'),p={name:"guide/theme-tokens.md"};function l(h,s,e,k,E,r){return a(),n("div",null,[...s[0]||(s[0]=[t("",22)])])}const o=i(p,[["render",l]]);export{g as __pageData,o as default};
1
+ import{_ as i,o as a,c as n,a2 as t}from"./chunks/framework.Olv9GB1A.js";const g=JSON.parse('{"title":"主题与布局 Token","description":"","frontmatter":{},"headers":[],"relativePath":"guide/theme-tokens.md","filePath":"guide/theme-tokens.md","lastUpdated":1794045200000}'),p={name:"guide/theme-tokens.md"};function l(h,s,e,k,E,r){return a(),n("div",null,[...s[0]||(s[0]=[t("",22)])])}const o=i(p,[["render",l]]);export{g as __pageData,o as default};
@@ -1 +1 @@
1
- import{d as m,g as r,o as s,c as e,j as t,a2 as n,k as d,E as l}from"./chunks/framework.B3lxS50j.js";const u={id:"community",class:"bag-community"},g={class:"bag-community-grid"},p={class:"bag-community-card bag-community-card--wechat"},b={class:"bag-community-surface bag-community-wechat-surface"},h=["src"],y="https://u.wechat.com/MC3P_4dYw_2FOyOWJvE-Ph0?s=2",_=m({__name:"CommunitySection",setup(c){const i=r("/wechat-group-qr.png");return(o,a)=>(s(),e("section",u,[a[3]||(a[3]=t("span",{class:"bag-community-ghost","aria-hidden":"true"},"CONNECT",-1)),a[4]||(a[4]=t("header",{class:"bag-community-heading"},[t("span",{class:"bag-community-eyebrow"},"COMMUNITY & CONTACT"),t("h2",null,"社区与联系"),t("p",null,"不止交流代码,也分享生活、技术和新的合作想法。")],-1)),t("div",g,[t("article",p,[a[1]||(a[1]=n('<span class="bag-community-card-icon bag-community-card-icon--wechat" aria-hidden="true"><svg viewBox="0 0 48 48"><circle cx="24" cy="15" r="6"></circle><circle cx="11" cy="19" r="4"></circle><circle cx="37" cy="19" r="4"></circle><path d="M13 38v-5c0-7 5-11 11-11s11 4 11 11v5"></path><path d="M3 37v-4c0-5 3-8 8-8 2 0 4 1 5 2"></path><path d="M45 37v-4c0-5-3-8-8-8-2 0-4 1-5 2"></path></svg></span><span class="bag-community-doodle bag-community-doodle--wechat" aria-hidden="true"></span><span class="bag-community-star" aria-hidden="true">✦</span>',3)),t("div",b,[a[0]||(a[0]=n('<div class="bag-community-copy"><h3>微信群</h3><span class="bag-community-title-mark" aria-hidden="true"></span><p class="bag-community-name">Vue-Bag-Admin 社区</p><span class="bag-community-dots" aria-hidden="true"></span><strong class="bag-community-join"><span aria-hidden="true">★</span> 扫码加入交流群 </strong></div>',1)),t("a",{class:"bag-community-qr-card",href:y,target:"_blank",rel:"noopener noreferrer",title:"打开微信邀请链接"},[t("img",{class:"bag-community-qr-image",src:d(i),alt:"Vue-Bag-Admin 微信群邀请二维码"},null,8,h)])])]),a[2]||(a[2]=n('<a class="bag-community-card bag-community-link-card bag-community-link-card--station" href="https://www.itnavs.com/" target="_blank" rel="noopener noreferrer"><div class="bag-community-link-surface"><span class="bag-community-card-icon bag-community-card-icon--station" aria-hidden="true"><svg viewBox="0 0 48 48"><circle cx="24" cy="24" r="15"></circle><path d="m29 17-4 9-8 5 4-9 8-5Z"></path></svg></span><div class="bag-community-link-copy"><h3>知航驿站</h3><span class="bag-community-title-mark" aria-hidden="true"></span><p>记录生活、技术与思考</p><span class="bag-community-dots" aria-hidden="true"></span><strong class="bag-community-action bag-community-action--station"><span aria-hidden="true">→</span> 访问网站 </strong></div><div class="bag-community-station-art" aria-hidden="true"><span class="bag-community-note bag-community-note--life"></span><span class="bag-community-note bag-community-note--tech"></span><span class="bag-community-compass"><i></i></span></div><span class="bag-community-doodle bag-community-doodle--station" aria-hidden="true"></span></div></a><a class="bag-community-card bag-community-link-card bag-community-link-card--contact" href="https://yh.itnavs.com/contact" target="_blank" rel="noopener noreferrer"><div class="bag-community-link-surface"><span class="bag-community-card-icon bag-community-card-icon--contact" aria-hidden="true"><svg viewBox="0 0 48 48"><path d="m8 26 8 8c2 2 5 2 7 0l4-4"></path><path d="m40 26-8 8c-2 2-5 2-7 0L14 23"></path><path d="m20 17 4-4c2-2 5-2 7 0l9 9"></path><path d="m28 17-3 3c-2 2-5 2-7 0l-1-1-9 9"></path></svg></span><div class="bag-community-link-copy"><h3>合作机会</h3><span class="bag-community-title-mark" aria-hidden="true"></span><p>项目合作 / 技术交流</p><span class="bag-community-dots" aria-hidden="true"></span><strong class="bag-community-action bag-community-action--contact"><span aria-hidden="true">→</span> 联系我 </strong></div><div class="bag-community-contact-art" aria-hidden="true"><span class="bag-community-message"><i></i><i></i><i></i></span><span class="bag-community-handshake"><svg viewBox="0 0 64 64"><path d="m7 31 9-11 14 9-8 10c-2 3-6 3-8 1l-7-6c-1-1-1-2 0-3Z"></path><path d="m57 31-9-11-14 9 8 10c2 3 6 3 8 1l7-6c1-1 1-2 0-3Z"></path><path d="m22 30 8-7c2-2 5-2 7 0l8 7-13 13-10-13Z"></path></svg></span></div><span class="bag-community-doodle bag-community-doodle--contact" aria-hidden="true"></span></div></a>',2))])]))}}),k=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"Vue-Bag-Admin","text":"插件化中后台框架","tagline":"基于 Vue3 + Vite6 + Naive UI + Tailwind CSS + Pinia + Strapi5 的宿主式后台框架","image":{"src":"/logo.png","alt":"Vue-Bag-Admin Logo"},"actions":[{"theme":"brand","text":"快速开始","link":"/guide/getting-started"},{"theme":"alt","text":"了解架构","link":"/guide/introduction"},{"theme":"alt","text":"在线预览","link":"https://hangjob.github.io/vue-bag-admin/"}]},"features":[{"title":"🧩 宿主与插件分层","details":"`@melt-js/libs-bag-entry` 跑宿主,`@melt-js/comps-bag-*` 放业务。先装主包,缺哪块业务再补插件。"},{"title":"📦 Monorepo 管理","details":"仓库使用 pnpm workspace 组织 `libs-bag-core`、`libs-bag-request`、`libs-bag-ui`、`libs-bag-host`、插件包和脚手架,便于联调和独立发包。"},{"title":"🛡️ 权限与路由","details":"宿主内置动态路由、菜单、标签页和按钮级权限控制,可以直接接常见后台页面。"},{"title":"🎛️ UI 与请求能力","details":"内置 `PmProTable`、`PmProForm`、字典组件,以及 HTTP / fetch / WebSocket 接入。"},{"title":"🚀 脚手架起步","details":"可以通过 `@melt-js/libs-bag-create` 直接生成宿主项目,再按需挂官方插件或业务插件。"},{"title":"🔧 本地联调","details":"可以直接跑 `tpl-vue3-admin-naive-bag`,也可以在外部项目里用 `link:` 验证主包和插件包。"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1794045200000}'),v={name:"index.md"},f=Object.assign(v,{setup(c){return(i,o)=>(s(),e("div",null,[l(_)]))}});export{k as __pageData,f as default};
1
+ import{d as m,g as r,o as s,c as e,j as t,a2 as n,k as d,E as l}from"./chunks/framework.Olv9GB1A.js";const u={id:"community",class:"bag-community"},g={class:"bag-community-grid"},p={class:"bag-community-card bag-community-card--wechat"},b={class:"bag-community-surface bag-community-wechat-surface"},h=["src"],y="https://u.wechat.com/MC3P_4dYw_2FOyOWJvE-Ph0?s=2",_=m({__name:"CommunitySection",setup(c){const i=r("/wechat-group-qr.png");return(o,a)=>(s(),e("section",u,[a[3]||(a[3]=t("span",{class:"bag-community-ghost","aria-hidden":"true"},"CONNECT",-1)),a[4]||(a[4]=t("header",{class:"bag-community-heading"},[t("span",{class:"bag-community-eyebrow"},"COMMUNITY & CONTACT"),t("h2",null,"社区与联系"),t("p",null,"不止交流代码,也分享生活、技术和新的合作想法。")],-1)),t("div",g,[t("article",p,[a[1]||(a[1]=n('<span class="bag-community-card-icon bag-community-card-icon--wechat" aria-hidden="true"><svg viewBox="0 0 48 48"><circle cx="24" cy="15" r="6"></circle><circle cx="11" cy="19" r="4"></circle><circle cx="37" cy="19" r="4"></circle><path d="M13 38v-5c0-7 5-11 11-11s11 4 11 11v5"></path><path d="M3 37v-4c0-5 3-8 8-8 2 0 4 1 5 2"></path><path d="M45 37v-4c0-5-3-8-8-8-2 0-4 1-5 2"></path></svg></span><span class="bag-community-doodle bag-community-doodle--wechat" aria-hidden="true"></span><span class="bag-community-star" aria-hidden="true">✦</span>',3)),t("div",b,[a[0]||(a[0]=n('<div class="bag-community-copy"><h3>微信群</h3><span class="bag-community-title-mark" aria-hidden="true"></span><p class="bag-community-name">Vue-Bag-Admin 社区</p><span class="bag-community-dots" aria-hidden="true"></span><strong class="bag-community-join"><span aria-hidden="true">★</span> 扫码加入交流群 </strong></div>',1)),t("a",{class:"bag-community-qr-card",href:y,target:"_blank",rel:"noopener noreferrer",title:"打开微信邀请链接"},[t("img",{class:"bag-community-qr-image",src:d(i),alt:"Vue-Bag-Admin 微信群邀请二维码"},null,8,h)])])]),a[2]||(a[2]=n('<a class="bag-community-card bag-community-link-card bag-community-link-card--station" href="https://www.itnavs.com/" target="_blank" rel="noopener noreferrer"><div class="bag-community-link-surface"><span class="bag-community-card-icon bag-community-card-icon--station" aria-hidden="true"><svg viewBox="0 0 48 48"><circle cx="24" cy="24" r="15"></circle><path d="m29 17-4 9-8 5 4-9 8-5Z"></path></svg></span><div class="bag-community-link-copy"><h3>知航驿站</h3><span class="bag-community-title-mark" aria-hidden="true"></span><p>记录生活、技术与思考</p><span class="bag-community-dots" aria-hidden="true"></span><strong class="bag-community-action bag-community-action--station"><span aria-hidden="true">→</span> 访问网站 </strong></div><div class="bag-community-station-art" aria-hidden="true"><span class="bag-community-note bag-community-note--life"></span><span class="bag-community-note bag-community-note--tech"></span><span class="bag-community-compass"><i></i></span></div><span class="bag-community-doodle bag-community-doodle--station" aria-hidden="true"></span></div></a><a class="bag-community-card bag-community-link-card bag-community-link-card--contact" href="https://yh.itnavs.com/contact" target="_blank" rel="noopener noreferrer"><div class="bag-community-link-surface"><span class="bag-community-card-icon bag-community-card-icon--contact" aria-hidden="true"><svg viewBox="0 0 48 48"><path d="m8 26 8 8c2 2 5 2 7 0l4-4"></path><path d="m40 26-8 8c-2 2-5 2-7 0L14 23"></path><path d="m20 17 4-4c2-2 5-2 7 0l9 9"></path><path d="m28 17-3 3c-2 2-5 2-7 0l-1-1-9 9"></path></svg></span><div class="bag-community-link-copy"><h3>合作机会</h3><span class="bag-community-title-mark" aria-hidden="true"></span><p>项目合作 / 技术交流</p><span class="bag-community-dots" aria-hidden="true"></span><strong class="bag-community-action bag-community-action--contact"><span aria-hidden="true">→</span> 联系我 </strong></div><div class="bag-community-contact-art" aria-hidden="true"><span class="bag-community-message"><i></i><i></i><i></i></span><span class="bag-community-handshake"><svg viewBox="0 0 64 64"><path d="m7 31 9-11 14 9-8 10c-2 3-6 3-8 1l-7-6c-1-1-1-2 0-3Z"></path><path d="m57 31-9-11-14 9 8 10c2 3 6 3 8 1l7-6c1-1 1-2 0-3Z"></path><path d="m22 30 8-7c2-2 5-2 7 0l8 7-13 13-10-13Z"></path></svg></span></div><span class="bag-community-doodle bag-community-doodle--contact" aria-hidden="true"></span></div></a>',2))])]))}}),k=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"Vue-Bag-Admin","text":"插件化中后台框架","tagline":"基于 Vue3 + Vite6 + Naive UI + Tailwind CSS + Pinia + Strapi5 的宿主式后台框架","image":{"src":"/logo.png","alt":"Vue-Bag-Admin Logo"},"actions":[{"theme":"brand","text":"快速开始","link":"/guide/getting-started"},{"theme":"alt","text":"了解架构","link":"/guide/introduction"},{"theme":"alt","text":"在线预览","link":"https://hangjob.github.io/vue-bag-admin/"}]},"features":[{"title":"🧩 宿主与插件分层","details":"`@melt-js/libs-bag-entry` 跑宿主,`@melt-js/comps-bag-*` 放业务。先装主包,缺哪块业务再补插件。"},{"title":"📦 Monorepo 管理","details":"仓库使用 pnpm workspace 组织 `libs-bag-core`、`libs-bag-request`、`libs-bag-ui`、`libs-bag-host`、插件包和脚手架,便于联调和独立发包。"},{"title":"🛡️ 权限与路由","details":"宿主内置动态路由、菜单、标签页和按钮级权限控制,可以直接接常见后台页面。"},{"title":"🎛️ UI 与请求能力","details":"内置 `PmProTable`、`PmProForm`、字典组件,以及 HTTP / fetch / WebSocket 接入。"},{"title":"🚀 脚手架起步","details":"可以通过 `@melt-js/libs-bag-create` 直接生成宿主项目,再按需挂官方插件或业务插件。"},{"title":"🔧 本地联调","details":"可以直接跑 `tpl-vue3-admin-naive-bag`,也可以在外部项目里用 `link:` 验证主包和插件包。"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1794045200000}'),v={name:"index.md"},f=Object.assign(v,{setup(c){return(i,o)=>(s(),e("div",null,[l(_)]))}});export{k as __pageData,f as default};
@@ -1 +1 @@
1
- import{d as m,g as r,o as s,c as e,j as t,a2 as n,k as d,E as l}from"./chunks/framework.B3lxS50j.js";const u={id:"community",class:"bag-community"},g={class:"bag-community-grid"},p={class:"bag-community-card bag-community-card--wechat"},b={class:"bag-community-surface bag-community-wechat-surface"},h=["src"],y="https://u.wechat.com/MC3P_4dYw_2FOyOWJvE-Ph0?s=2",_=m({__name:"CommunitySection",setup(c){const i=r("/wechat-group-qr.png");return(o,a)=>(s(),e("section",u,[a[3]||(a[3]=t("span",{class:"bag-community-ghost","aria-hidden":"true"},"CONNECT",-1)),a[4]||(a[4]=t("header",{class:"bag-community-heading"},[t("span",{class:"bag-community-eyebrow"},"COMMUNITY & CONTACT"),t("h2",null,"社区与联系"),t("p",null,"不止交流代码,也分享生活、技术和新的合作想法。")],-1)),t("div",g,[t("article",p,[a[1]||(a[1]=n("",3)),t("div",b,[a[0]||(a[0]=n("",1)),t("a",{class:"bag-community-qr-card",href:y,target:"_blank",rel:"noopener noreferrer",title:"打开微信邀请链接"},[t("img",{class:"bag-community-qr-image",src:d(i),alt:"Vue-Bag-Admin 微信群邀请二维码"},null,8,h)])])]),a[2]||(a[2]=n("",2))])]))}}),k=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"Vue-Bag-Admin","text":"插件化中后台框架","tagline":"基于 Vue3 + Vite6 + Naive UI + Tailwind CSS + Pinia + Strapi5 的宿主式后台框架","image":{"src":"/logo.png","alt":"Vue-Bag-Admin Logo"},"actions":[{"theme":"brand","text":"快速开始","link":"/guide/getting-started"},{"theme":"alt","text":"了解架构","link":"/guide/introduction"},{"theme":"alt","text":"在线预览","link":"https://hangjob.github.io/vue-bag-admin/"}]},"features":[{"title":"🧩 宿主与插件分层","details":"`@melt-js/libs-bag-entry` 跑宿主,`@melt-js/comps-bag-*` 放业务。先装主包,缺哪块业务再补插件。"},{"title":"📦 Monorepo 管理","details":"仓库使用 pnpm workspace 组织 `libs-bag-core`、`libs-bag-request`、`libs-bag-ui`、`libs-bag-host`、插件包和脚手架,便于联调和独立发包。"},{"title":"🛡️ 权限与路由","details":"宿主内置动态路由、菜单、标签页和按钮级权限控制,可以直接接常见后台页面。"},{"title":"🎛️ UI 与请求能力","details":"内置 `PmProTable`、`PmProForm`、字典组件,以及 HTTP / fetch / WebSocket 接入。"},{"title":"🚀 脚手架起步","details":"可以通过 `@melt-js/libs-bag-create` 直接生成宿主项目,再按需挂官方插件或业务插件。"},{"title":"🔧 本地联调","details":"可以直接跑 `tpl-vue3-admin-naive-bag`,也可以在外部项目里用 `link:` 验证主包和插件包。"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1794045200000}'),v={name:"index.md"},f=Object.assign(v,{setup(c){return(i,o)=>(s(),e("div",null,[l(_)]))}});export{k as __pageData,f as default};
1
+ import{d as m,g as r,o as s,c as e,j as t,a2 as n,k as d,E as l}from"./chunks/framework.Olv9GB1A.js";const u={id:"community",class:"bag-community"},g={class:"bag-community-grid"},p={class:"bag-community-card bag-community-card--wechat"},b={class:"bag-community-surface bag-community-wechat-surface"},h=["src"],y="https://u.wechat.com/MC3P_4dYw_2FOyOWJvE-Ph0?s=2",_=m({__name:"CommunitySection",setup(c){const i=r("/wechat-group-qr.png");return(o,a)=>(s(),e("section",u,[a[3]||(a[3]=t("span",{class:"bag-community-ghost","aria-hidden":"true"},"CONNECT",-1)),a[4]||(a[4]=t("header",{class:"bag-community-heading"},[t("span",{class:"bag-community-eyebrow"},"COMMUNITY & CONTACT"),t("h2",null,"社区与联系"),t("p",null,"不止交流代码,也分享生活、技术和新的合作想法。")],-1)),t("div",g,[t("article",p,[a[1]||(a[1]=n("",3)),t("div",b,[a[0]||(a[0]=n("",1)),t("a",{class:"bag-community-qr-card",href:y,target:"_blank",rel:"noopener noreferrer",title:"打开微信邀请链接"},[t("img",{class:"bag-community-qr-image",src:d(i),alt:"Vue-Bag-Admin 微信群邀请二维码"},null,8,h)])])]),a[2]||(a[2]=n("",2))])]))}}),k=JSON.parse('{"title":"","description":"","frontmatter":{"layout":"home","hero":{"name":"Vue-Bag-Admin","text":"插件化中后台框架","tagline":"基于 Vue3 + Vite6 + Naive UI + Tailwind CSS + Pinia + Strapi5 的宿主式后台框架","image":{"src":"/logo.png","alt":"Vue-Bag-Admin Logo"},"actions":[{"theme":"brand","text":"快速开始","link":"/guide/getting-started"},{"theme":"alt","text":"了解架构","link":"/guide/introduction"},{"theme":"alt","text":"在线预览","link":"https://hangjob.github.io/vue-bag-admin/"}]},"features":[{"title":"🧩 宿主与插件分层","details":"`@melt-js/libs-bag-entry` 跑宿主,`@melt-js/comps-bag-*` 放业务。先装主包,缺哪块业务再补插件。"},{"title":"📦 Monorepo 管理","details":"仓库使用 pnpm workspace 组织 `libs-bag-core`、`libs-bag-request`、`libs-bag-ui`、`libs-bag-host`、插件包和脚手架,便于联调和独立发包。"},{"title":"🛡️ 权限与路由","details":"宿主内置动态路由、菜单、标签页和按钮级权限控制,可以直接接常见后台页面。"},{"title":"🎛️ UI 与请求能力","details":"内置 `PmProTable`、`PmProForm`、字典组件,以及 HTTP / fetch / WebSocket 接入。"},{"title":"🚀 脚手架起步","details":"可以通过 `@melt-js/libs-bag-create` 直接生成宿主项目,再按需挂官方插件或业务插件。"},{"title":"🔧 本地联调","details":"可以直接跑 `tpl-vue3-admin-naive-bag`,也可以在外部项目里用 `link:` 验证主包和插件包。"}]},"headers":[],"relativePath":"index.md","filePath":"index.md","lastUpdated":1794045200000}'),v={name:"index.md"},f=Object.assign(v,{setup(c){return(i,o)=>(s(),e("div",null,[l(_)]))}});export{k as __pageData,f as default};