--- url: /guide/intro.md --- # 文档说明 ::: tip ⭐⭐⭐⭐⭐ 相信你已经准备或正在使用 Fantastic-admin 进行开发工作了,在此之前,希望可以去 [![star](https://img.shields.io/github/stars/fantastic-admin/basic?style=social)](https://github.com/fantastic-admin/basic) [![star](https://gitee.com/fantastic-admin/basic/badge/star.svg?theme=dark)](https://gitee.com/fantastic-admin/basic) [![star](https://atomgit.com/fantastic-admin/basic/star/badge.svg)](https://atomgit.com/fantastic-admin/basic) 给本产品点个 ⭐ ,这将对本产品的推广有极大帮助。 ::: 文档中标记 的地方,表示该功能仅提供于专业版使用,使用基础版的开发者可直接跳过阅读。 如果你准备好了,那我们就[开始](/guide/ready)吧~ --- --- url: /guide/why.md --- # 为什么选择 Fantastic-admin ? 如果你想找的只是一个“能跑起来”的后台模板,那么市面上的选择其实很多。 但如果你要的是一套**适合长期维护、支持持续扩展、对 AI 友好、并且经过市场验证**的工程底座,那么 Fantastic-admin 想解决的就不是“把页面搭起来”这么简单。 它更像是一套为真实项目准备好的后台开发系统:有统一的工程组织方式,有成体系的导航与路由设计,有可扩展的布局能力,也有让 AI 更懂你项目结构的 Skills 体系。 ## 它适合什么样的团队? Fantastic-admin 尤其适合下面这些场景: * 想快速启动一个中后台项目,但又不想后期越做越乱 * 团队里前端人数有限,希望降低业务页面搭建成本 * 项目需要长期演进,未来可能扩成多应用、多主题、多布局形态 * 希望把 AI 真正引入开发流程,而不是只把 AI 当聊天工具 * 需要兼顾**开发效率、界面质量、工程规范**三者的平衡 ## 长期维护,而不是一次性产物 Fantastic-admin 自 {{ from }} 对外发布以来,截止今天已持续维护 **{{ day }}** 天。 这意味着它不是一个“演示效果很好、真正落地时问题很多”的短期项目,而是一套经过长期迭代、不断打磨后形成的方法论型框架。 对后台系统来说,长期维护能力往往比“第一眼惊艳”更重要。因为后台项目一旦上线,真正的挑战往往不是从 0 到 1,而是之后不断增加页面、角色、权限、菜单、布局和业务模块时,工程是否还能保持清晰。 ## 1. 面向 AI 编程的后台开发方式 Fantastic-admin 的一个非常明显的差异点,是它不是简单地“支持 AI”,而是把后台开发中的高频动作,沉淀成了一套可复用的 **AI Skills**。 你可以把它理解为:不是让 AI 凭空猜你的工程规范,而是直接把框架的目录约定、实现方式和推荐路径告诉 AI。 当前文档里已经收录了多种 Skills,例如: * [fa-crud-page-generator](/guide/skills/fa-crud-page-generator):生成完整 CRUD 模块 * [fa-form-builder](/guide/skills/fa-form-builder):生成独立表单页 * [fa-framework-settings](/guide/skills/fa-framework-settings):修改框架设置 * [fa-i18n-manager](/guide/skills/fa-i18n-manager):管理国际化 * [fa-page-optimizer](/guide/skills/fa-page-optimizer):优化页面并替换为框架组件 * [fa-route-generator](/guide/skills/fa-route-generator):创建或修改路由 * [fa-slot-creator](/guide/skills/fa-slot-creator):创建布局插槽 * [fa-store-generator](/guide/skills/fa-store-generator):生成 Store 模块 * [fa-theme-customizer](/guide/skills/fa-theme-customizer):定制主题配色 这带来的好处不是“多了几个提示词模板”,而是: * AI 更容易理解 Fantastic-admin 的目录结构和工程约定 * AI 生成的代码更接近项目现有风格,而不是通用模板代码 * 从 CRUD、表单到路由、主题、插槽,都可以走同一套协作方式 * 当需求反复修改时,还能进入统一的反馈流程,而不是每次重新来过 更重要的是,项目里的 Skills 采用 `SKILL.md` 这种开放格式统一维护在 `.agents/skills/` 中,不只可用于单一工具,也更适合未来持续演进的 Agent 工作流。详细可阅读:[AI 技能 (Skills)](/guide/skills/) ## 2. 更适合长期项目的 pnpm monorepo 架构 很多后台模板在一开始看起来很轻,但项目一大,目录结构就会逐渐失控:应用代码、公共组件、主题配置、文档、工程脚本全堆在一起,短期方便,长期难维护。 Fantastic-admin 从工程组织上就避免了这个问题。它使用的是 **pnpm monorepo**,并把核心能力按职责拆开: ```text ├── apps/* # 业务应用 ├── packages/* # 可复用能力(组件、设置、主题等) └── docs # 文档站 ``` 这种结构的价值在于: * **业务与框架能力边界清晰**:应用代码不会和公共能力缠在一起 * **更适合多应用扩展**:以后新增 `apps/admin`、`apps/tenant` 这类应用时更自然 * **公共能力可沉淀复用**:组件、设置、主题不必复制粘贴 * **文档可以跟着代码同步演进**:减少“代码更新了,文档还停在旧版本”的割裂感 如果你希望项目不是只服务一个短周期页面,而是能支撑一个产品长期发展,那么 monorepo 带来的收益会非常明显。 ## 3. 技术栈现代,但重点不只是“新” Fantastic-admin 当前采用的核心技术栈包括: * Vue 3.6 * TypeScript * Vite 8 * Vue Router 5 * Pinia * UnoCSS * vue-i18n * Element Plus(默认) * Reka UI(内建组件底层实现) 这些技术栈本身当然足够现代,但更重要的是它们组合在一起后,服务的是后台项目最常见的几个目标: * **开发体验足够顺手**:Vite、TS、Vue 3 的组合已经非常成熟 * **状态与路由体系清晰**:Pinia + Vue Router 更适合中后台场景的组织方式 * **样式迭代效率高**:UnoCSS 让大量界面微调变得更轻,适合高频业务开发 * **国际化与主题能力更容易落地**:不是后期硬补,而是默认具备扩展空间 所以它的价值不只是“用了新技术”,而是这些技术被放进了一个适合后台项目的工程结构里。 ## 4. 布局和导航不是点缀,而是生产力 很多后台框架在首页会展示很多皮肤和主题,但真正落到业务里,往往只能用一种布局、一种导航结构,最后所有项目都长得差不多。 Fantastic-admin 更重视的是:**同一套业务能力,能不能适配不同的信息架构和产品阶段。** ### 页面布局更灵活 围绕内容宽度与页面承载方式,框架支持多种布局形态,例如: * 自适应布局 * 内层居中布局 * 外层居中布局 这意味着你可以根据项目气质、屏幕利用率和内容密度来决定页面风格,而不是被固定模板限制住。相关文档可阅读:[应用设置 / 布局](/guide/settings/app#布局) ### 导航菜单模式更丰富 Fantastic-admin 的导航不是单一的左侧菜单,而是支持按场景切换组织方式。 基础模式包括: * `head` * `side` * `single` 专业版进一步扩展: * `only-side` * `only-head` * `side-panel` * `head-panel` 也就是说,专业版一共提供 **7 种导航菜单模式**。这背后不是为了“看起来花样多”,而是为了适配不同后台产品的真实需求,例如: * 模块特别多时,需要更强的层级承载能力 * 一级入口很重要时,希望顶部导航更突出 * 既要主导航又要次导航时,希望信息组织更清晰 * 面向不同甲方或品牌项目时,希望快速调整视觉与交互结构 相关文档可阅读:[导航菜单](/guide/settings/menu) ## 5. 路由、菜单、权限、缓存不是零散功能,而是一套闭环 Fantastic-admin 的一个核心思路是:**导航本质上应由路由驱动,而不是额外维护两套数据。** 在项目里,路由模块放在 `apps//src/router/modules/` 下,每个文件都是一个独立模块,最后统一在 `routes.ts` 中组织到不同的主导航菜单里。 这带来的好处非常直接: * 路由结构和导航结构天然一致 * 菜单的标题、图标、徽章、权限、高亮、缓存等能力都能通过路由元信息统一管理 * 单个模块的位置可灵活调整,而不影响业务路径 * 更适合多人协作和中大型后台的持续扩展 对开发者来说,这不是“又一套配置”,而是少维护一套系统。 如果你做过复杂后台项目,会知道真正麻烦的不是写一个菜单,而是后面不断叠加: * 哪些页面显示在菜单里 * 哪些页面不显示但要高亮指定菜单 * 哪些页面需要权限控制 * 哪些页面需要保活 * 哪些页面需要标签页合并或特殊跳转行为 Fantastic-admin 把这些问题放进了同一套路由与导航体系中,因此更适合真实业务,而不只是演示页。详细可阅读:[路由(导航菜单)](/guide/router)、[权限](/guide/auth)、[页面缓存](/guide/keep-alive) ## 6. 风格不是简单换色,而是可以塑造产品气质 后台系统当然首先是效率工具,但这并不意味着界面风格不重要。 一个长期使用的后台,视觉系统是否统一、布局是否克制、交互是否舒服,会直接影响团队每天使用它时的感受。 Fantastic-admin 在这方面提供的不是单点配置,而是一整套组合能力: * 明暗模式切换 * 主题体系 * 导航风格定制 * 页面布局切换 * 工具栏与标签栏相关配置 同时,如果你希望进一步做品牌化定制,项目还提供了 [fa-theme-customizer](/guide/skills/fa-theme-customizer) 这类 Skill,让 AI 可以直接帮助你生成和落地主题方案。 ## 7. 可替换、可扩展,而不是“只能按作者方式开发” 一个真正能陪项目走很久的框架,不能只提供默认答案,还要留出足够大的扩展空间。 Fantastic-admin 在这方面给出的能力包括: ### 自由选择 UI 组件库 你可以根据团队偏好选择[三方 UI 组件库](/guide/with-ui-libraries),这意味着你不必因为框架的默认视觉选择,而放弃它的工程能力。 ### 预留插槽能力 框架支持在布局中的多个位置注入自定义内容,例如头部、侧边、工具栏、页面上下方等区域。 这对真实项目特别重要,因为很多后台最终都会遇到: * 在头部加组织切换 * 在布局顶部加公告横幅 * 在底部加自定义信息区 * 在工具栏或导航旁插入业务入口 相关文档可阅读:[预留插槽](/guide/slots) ### 国际化与状态管理能力 对于需要做多语言、跨页面共享状态、页面级配置扩展的项目来说,框架也给出了比较明确的落地路径: * [国际化](/guide/i18n) * [Store](/guide/store) * [资源管理与样式方案](/guide/resources) ## 8. 对后端、全栈和中小团队更友好 Fantastic-admin 一直有一个很实际的优势:它不是只为“纯前端团队”准备的。 对很多后端、全栈或中小团队来说,真正需要的不是一套过于抽象的前端架构,而是一套: * 看得懂 * 改得动 * 能扩展 * 文档能跟上 * 页面和功能都有真实落地参考 Fantastic-admin 在这些维度上更接近“可直接投入业务”的状态。你可以从文档、示例应用、业务页面、内建组件和 Skills 一起开始,而不是先花大量时间把工程骨架重新拼起来。 ## 总结:Fantastic-admin 的价值,不只是“功能多” 很多框架也能做主题、做菜单、做权限、做页面。 Fantastic-admin 更想解决的是另外一个问题:**这些能力能不能组成一套长期可用的后台开发体系。** 它的价值在于: * 用 **AI Skills** 降低后台开发和协作成本 * 用 **pnpm monorepo** 提前解决长期维护问题 * 用 **多布局 + 多导航模式** 适配不同产品形态 * 用 **路由驱动菜单与权限** 保持系统一致性 * 用 **主题、插槽、组件替换能力** 留出足够扩展空间 如果你需要的是一个只演示几张漂亮页面的模板,那么它也许不是最“轻”的那个。 但如果你要的是一套能够陪项目一起成长、并且已经为未来的 AI 协作方式做好准备的后台框架,那么 Fantastic-admin 值得认真看看。 --- --- url: /guide/changelog.md --- # 更新日志 只记录 feat/fix 以及破坏性变更。 ## v6.4.0 :::info [基础版](https://github.com/fantastic-admin/basic/releases/tag/v6.4.0) 🐞 Bug Fixes * 修复 FaSwitch 组件激活样式  -  by @hooray [(09a17)](https://github.com/fantastic-admin/basic/commit/09a179cd) * 修复应用运行时警告  -  by @hooray [(be4a2)](https://github.com/fantastic-admin/basic/commit/be4a274f) ::: :::tip [专业版](https://github.com/fantastic-admin/pro/releases/tag/v6.4.0) 🚀 Features * FaCalendar\* 日历组件增加 `shortcuts` 快捷选择功能  -  by @hooray [(dac61)](https://github.com/fantastic-admin/pro/commit/dac61ea9) * `FaDate` 增加时间选择功能  -  by @hooray [(d83e7)](https://github.com/fantastic-admin/pro/commit/d83e7873) 🐞 Bug Fixes * 修复 FaSwitch 组件激活样式  -  by @hooray [(89955)](https://github.com/fantastic-admin/pro/commit/899558c2) * 修复 FaMention 组件提及样式错位  -  by @hooray [(1833d)](https://github.com/fantastic-admin/pro/commit/1833d989) * 修复应用运行时警告  -  by @hooray [(fc84c)](https://github.com/fantastic-admin/pro/commit/fc84c8cc) ::: ## v6.3.0 :::info [基础版](https://github.com/fantastic-admin/basic/releases/tag/v6.3.0) 🚀 Features * 新增 hotkeys 子包,统一维护全局快捷键  -  by @hooray [(5bbe2)](https://github.com/fantastic-admin/basic/commit/5bbe23df) * 新增 FaForm 表单组件及示例,并更新登录注册相关页面  -  by @hooray [(29193)](https://github.com/fantastic-admin/basic/commit/29193e47) * 增加 core-element-plus 应用,同时 core 应用将不再集成任何第三方组件库  -  by @hooray [(68698)](https://github.com/fantastic-admin/basic/commit/686988cc) 🐞 Bug Fixes * 修复 Antdv Next 应用未和框架主题保持同步  -  by @hooray [(209cb)](https://github.com/fantastic-admin/basic/commit/209cb174) ::: :::tip [专业版](https://github.com/fantastic-admin/pro/releases/tag/v6.3.0) 🚀 Features * 新增 locales 子包,统一维护全局语言包信息  -  by @hooray [(7b48b)](https://github.com/fantastic-admin/pro/commit/7b48bacf) * 新增 hotkeys 子包,统一维护全局快捷键  -  by @hooray [(e5f32)](https://github.com/fantastic-admin/pro/commit/e5f3263a) * 新增 FaForm 表单组件及示例,并更新登录注册相关页面  -  by @hooray [(e8312)](https://github.com/fantastic-admin/pro/commit/e831216d) * 增加 core-element-plus 应用,同时 core 应用将不再集成任何第三方组件库  -  by @hooray [(dc988)](https://github.com/fantastic-admin/pro/commit/dc988a77) ::: ## v6.2.0 :::info [基础版](https://github.com/fantastic-admin/basic/releases/tag/v6.2.0) 🚨 Breaking Changes * 上游 vite-plugin-fake-server 插件问题修复,代码回滚  -  by @hooray [(474c1)](https://github.com/fantastic-admin/basic/commit/474c11d9) * 重构多个子包  -  by @hooray [(749c5)](https://github.com/fantastic-admin/basic/commit/749c55ed) * 回滚 vite-plugin-fake-server 插件配置  -  by @hooray [(f6516)](https://github.com/fantastic-admin/basic/commit/f6516782) 🚀 Features * 内建组件内的固定中文文案,改为可替换  -  by @hooray [(f1c02)](https://github.com/fantastic-admin/basic/commit/f1c02586) * **FaFileUpload**: 增加文件夹上传和自定义上传请求功能  -  by @hooray [(5f9a0)](https://github.com/fantastic-admin/basic/commit/5f9a01fd) * **FaImageUpload**: 增加文件夹上传和自定义上传请求功能  -  by @hooray [(a7741)](https://github.com/fantastic-admin/basic/commit/a77416fb) * **alert**: 添加 FaAlert 组件  -  by @hooray [(40cab)](https://github.com/fantastic-admin/basic/commit/40cab5ef) * **antdv-next**: 添加 AApp 组件  -  by @hooray [(4e5bf)](https://github.com/fantastic-admin/basic/commit/4e5bfb92) * **badge**: 新增徽章组件及示例  -  by @hooray [(410ce)](https://github.com/fantastic-admin/basic/commit/410ce626) * **descriptions**: 新增 FaDescriptions 组件及示例  -  by @hooray [(c0cd2)](https://github.com/fantastic-admin/basic/commit/c0cd2ffc) * **skill**: 更新 fa-crud-page-generator  -  by @hooray [(05e3e)](https://github.com/fantastic-admin/basic/commit/05e3e614) * **table**: 新增表格组件及示例  -  by @hooray [(57f98)](https://github.com/fantastic-admin/basic/commit/57f98e7b) * **tag**: 新增标签组件及示例  -  by @hooray [(574d0)](https://github.com/fantastic-admin/basic/commit/574d0fcc) 🐞 Bug Fixes * 修复 Drawer 和 Modal 组件的 isClosed 状态初始化逻辑  -  by @hooray [(26469)](https://github.com/fantastic-admin/basic/commit/2646930f) ::: :::tip [专业版](https://github.com/fantastic-admin/pro/releases/tag/v6.2.0) 🚨 Breaking Changes * 上游 vite-plugin-fake-server 插件问题修复,代码回滚  -  by @hooray [(e30aa)](https://github.com/fantastic-admin/pro/commit/e30aab22) * 储物箱组件界面重构,移除国际化支持  -  by @hooray [(96601)](https://github.com/fantastic-admin/pro/commit/9660105e) * 重构多个子包  -  by @hooray [(640f8)](https://github.com/fantastic-admin/pro/commit/640f8f3e) * 回滚 vite-plugin-fake-server 插件配置  -  by @hooray [(b6dfa)](https://github.com/fantastic-admin/pro/commit/b6dfa5be) 🚀 Features * 密码强度组件增加自定义规则和颜色阈值配置  -  by @hooray [(06a9a)](https://github.com/fantastic-admin/pro/commit/06a9a302) * 新增 FaTable 组件  -  by @hooray [(9f271)](https://github.com/fantastic-admin/pro/commit/9f271f99) * 添加文件管理示例页面  -  by @hooray [(be872)](https://github.com/fantastic-admin/pro/commit/be8723da) * 内建组件内的固定中文文案,改为可替换  -  by @hooray [(aa7fb)](https://github.com/fantastic-admin/pro/commit/aa7fb4ed) * 新增 FaCalendarDate / FaCalendarDateRange 组件  -  by @hooray [(cdae0)](https://github.com/fantastic-admin/pro/commit/cdae00ef) * 新增 FaCalendarMonth / FaCalendarMonthRange / FaCalendarYear / FaCalendarYearRange 组件  -  by @hooray [(d4f95)](https://github.com/fantastic-admin/pro/commit/d4f95b31) * FaCalendarDate / FaCalendarMonth / FaCalendarYear 增加多选支持  -  by @hooray [(8b7e9)](https://github.com/fantastic-admin/pro/commit/8b7e9d46) * FaCalendarDate / FaCalendarDateRange / FaCalendarMonth / FaCalendarMonthRange / FaCalendarYear / FaCalendarYearRange 增加选择器支持  -  by @hooray [(ac8bd)](https://github.com/fantastic-admin/pro/commit/ac8bdc92) * 移除日期选择器和日期范围选择器中的布局和年份范围属性  -  by @hooray [(7040c)](https://github.com/fantastic-admin/pro/commit/7040cb27) * 新增 FaDate 组件  -  by @hooray [(cefe9)](https://github.com/fantastic-admin/pro/commit/cefe98c0) * **FaFileUpload**: * 移除国际化,增加文件夹上传和自定义上传请求功能  -  by @hooray [(c39a1)](https://github.com/fantastic-admin/pro/commit/c39a1a81) * **FaImageUpload**: * 移除国际化,增加文件夹上传和自定义上传请求功能  -  by @hooray [(50db4)](https://github.com/fantastic-admin/pro/commit/50db4bab) * **alert**: * 添加 FaAlert 组件  -  by @hooray [(4e301)](https://github.com/fantastic-admin/pro/commit/4e301a6b) * **antdv-next**: * 添加 AApp 组件  -  by @hooray [(6c920)](https://github.com/fantastic-admin/pro/commit/6c92088b) * **descriptions**: * 新增 FaDescriptions 组件及示例  -  by @hooray [(db213)](https://github.com/fantastic-admin/pro/commit/db2134a1) * **skill**: * 更新 fa-crud-page-generator  -  by @hooray [(d09bb)](https://github.com/fantastic-admin/pro/commit/d09bba81) * **steps**: * 添加 FaSteps 组件  -  by @hooray [(4582c)](https://github.com/fantastic-admin/pro/commit/4582c740) * **table**: * 添加列可见性功能和示例  -  by @hooray [(3e1a0)](https://github.com/fantastic-admin/pro/commit/3e1a0c4a) * 添加工具栏插槽和列可见性控制,更新文档  -  by @hooray [(aea0a)](https://github.com/fantastic-admin/pro/commit/aea0a0c8) * 添加排序功能及相关示例  -  by @hooray [(9e48d)](https://github.com/fantastic-admin/pro/commit/9e48d460) * 添加树型数据支持及相关示例  -  by @hooray [(4bfca)](https://github.com/fantastic-admin/pro/commit/4bfca62b) * **tag**: * 新增标签组件及示例  -  by @hooray [(07f41)](https://github.com/fantastic-admin/pro/commit/07f415e1) 🐞 Bug Fixes * 修复 Drawer 和 Modal 组件的 isClosed 状态初始化逻辑  -  by @hooray [(02b6d)](https://github.com/fantastic-admin/pro/commit/02b6d30c) * **table**: 修复固定列边框消失的问题  -  by @hooray [(55470)](https://github.com/fantastic-admin/pro/commit/554705a9) ::: ## v6.1.0 :::info [基础版](https://github.com/fantastic-admin/basic/releases/tag/v6.1.0) 🚨 Breaking Changes * 移除 FaRadioGroup 组件的 orientation 属性  -  by @hooray [(c0bc3)](https://github.com/fantastic-admin/basic/commit/c0bc31f7) * 因上游 vite-plugin-fake-server 插件问题,暂时移动 fake 文件目录  -  by @hooray [(1b0dc)](https://github.com/fantastic-admin/basic/commit/1b0dc3b9) 🚀 Features * 增强 dev 脚本匹配逻辑,支持以 'dev:' 开头的脚本名称  -  by @hooray [(e55e9)](https://github.com/fantastic-admin/basic/commit/e55e9474) * FaImageUpload / FaFileUpload 增加粘贴上传功能  -  by @hooray [(1c811)](https://github.com/fantastic-admin/basic/commit/1c811156) * FaImageUpload 组件增加入场、出场、排序动画  -  by @hooray [(38e6a)](https://github.com/fantastic-admin/basic/commit/38e6abab) * 将生成图标脚本提取到公用子包  -  by @hooray [(1ccbd)](https://github.com/fantastic-admin/basic/commit/1ccbd640) * 主题色调整  -  by @hooray and **Copilot** [(1d86e)](https://github.com/fantastic-admin/basic/commit/1d86ef87) * 添加 FaSelect 组件的定位模式支持  -  by @hooray and **Copilot** [(81bed)](https://github.com/fantastic-admin/basic/commit/81beda6e) * 新增 FaRadioGroup 组件  -  by @hooray [(bb3bd)](https://github.com/fantastic-admin/basic/commit/bb3bd479) * 新增 FaCheckboxGrou 组件,并重构 FaCheckbox API  -  by @hooray [(5ba6d)](https://github.com/fantastic-admin/basic/commit/5ba6d08d) * 更新 FaDrawer 和 FaModal 组件,强制关闭自带遮罩  -  by @hooray [(fc2c8)](https://github.com/fantastic-admin/basic/commit/fc2c89fa) * 扩展 FaInput 组件的 type 属性  -  by @hooray [(70b29)](https://github.com/fantastic-admin/basic/commit/70b29edb) 🐞 Bug Fixes * 修复 FaDrawer 和 FaModal 组件开启时警告错误  -  by @hooray [(cf4a7)](https://github.com/fantastic-admin/basic/commit/cf4a7eae) * 修复icon生成脚本错误  -  by @hooray [(84eb9)](https://github.com/fantastic-admin/basic/commit/84eb9b7a) * 修复登录页“记住我”无法勾选  -  by @hooray [(244e6)](https://github.com/fantastic-admin/basic/commit/244e6cb4) ::: :::tip [专业版](https://github.com/fantastic-admin/pro/releases/tag/v6.1.0) 🚨 Breaking Changes * 移除 FaRadioGroup 组件的 orientation 属性  -  by @hooray [(3fc28)](https://github.com/fantastic-admin/pro/commit/3fc28063) * 因上游 vite-plugin-fake-server 插件问题,暂时移动 fake 文件目录  -  by @hooray [(05ade)](https://github.com/fantastic-admin/pro/commit/05ade0cf) 🚀 Features * 增强 dev 脚本匹配逻辑,支持以 'dev:' 开头的脚本名称  -  by @hooray [(7cfaa)](https://github.com/fantastic-admin/pro/commit/7cfaa3bd) * FaImageUpload / FaFileUpload 增加粘贴上传功能  -  by @hooray [(ff29d)](https://github.com/fantastic-admin/pro/commit/ff29de71) * FaImageUpload 组件增加入场、出场、排序动画  -  by @hooray [(57211)](https://github.com/fantastic-admin/pro/commit/57211cf7) * 新增 useTiks 交互音效  -  by @hooray [(1f1b4)](https://github.com/fantastic-admin/pro/commit/1f1b4939) * 多账号弹窗增加自动聚焦  -  by @hooray [(f07e9)](https://github.com/fantastic-admin/pro/commit/f07e9381) * 将生成图标脚本提取到公用子包  -  by @hooray [(5afd0)](https://github.com/fantastic-admin/pro/commit/5afd0ee4) * 重构主题设计,并同步 shadcn-vue 的基础色和主题色  -  by @hooray [(5401b)](https://github.com/fantastic-admin/pro/commit/5401be42) * 添加 FaSelect 组件的定位模式支持  -  by @hooray [(96006)](https://github.com/fantastic-admin/pro/commit/96006daa) * 新增 FaRadioGroup 组件  -  by @hooray [(71b97)](https://github.com/fantastic-admin/pro/commit/71b97063) * 新增 FaCheckboxGrou 组件,并重构 FaCheckbox API  -  by @hooray [(b8ccb)](https://github.com/fantastic-admin/pro/commit/b8ccb1e6) * 更新 FaDrawer 和 FaModal 组件,强制关闭自带遮罩  -  by @hooray [(1dbb3)](https://github.com/fantastic-admin/pro/commit/1dbb3c8e) * 扩展 FaInput 组件的 type 属性  -  by @hooray [(03dd7)](https://github.com/fantastic-admin/pro/commit/03dd7fcc) * 添加 FaTree 组件的虚拟化支持,并使用 reka-ui 重构  -  by @hooray [(bc98d)](https://github.com/fantastic-admin/pro/commit/bc98df00) * 新增 `FaCombobox` 组件  -  by @hooray [(55732)](https://github.com/fantastic-admin/pro/commit/55732fc5) 🐞 Bug Fixes * 修复 FaDrawer 和 FaModal 组件开启时警告错误  -  by @hooray [(691dd)](https://github.com/fantastic-admin/pro/commit/691dd905) * 修复icon生成脚本错误  -  by @hooray [(497fa)](https://github.com/fantastic-admin/pro/commit/497faad0) * 修复 FaScrollingText 向下滚动时鼠标悬停时跳动  -  by @hooray [(34409)](https://github.com/fantastic-admin/pro/commit/34409eee) * 修复工具栏布局条件判断  -  by @hooray [(50695)](https://github.com/fantastic-admin/pro/commit/50695260) * 修复 `VITE_APP_SETTING` 关闭后导致偏好设置无响应  -  by @hooray [(5f286)](https://github.com/fantastic-admin/pro/commit/5f28686f) * 为 FaButton 组件添加 type 属性以确保按钮行为一致  -  by @hooray [(e6abd)](https://github.com/fantastic-admin/pro/commit/e6abd179) * 修复登录页“记住我”无法勾选  -  by @hooray [(af1c9)](https://github.com/fantastic-admin/pro/commit/af1c93ab) * 修复默认语言如果为跟随浏览器语言时,未命中框架内语言包时报错,增加国际化回退语言  -  by @hooray [(5423a)](https://github.com/fantastic-admin/pro/commit/5423af28) ::: ## v6.0.0 ![](/v6-released.png) 如果你是从 v5.x 迁移到 v6.0 ,请先阅读《[从 v5 迁移](./migration-from-v5)》,以下是 v6.0 新特性概览: * 采用 PNPM monorepo 架构 * 内置 AI Skills * UnoCSS 预设从 `presetWind3` 升级为 `presetWind4` * 提供 `setSettingsLegacy` 配置迁移函数,支持从 v5.x 配置快速过渡到 v6 * 偏好设置支持更细粒度的自定义开启方式 * 可以按整个模块开放 * 也可以只开放某几个子项 * 新增路由元信息能力 * 支持 `layout` 路由级布局配置 * 支持 `localeAuth` 区域权限配置 * 新增锁屏功能 * 新增多账号功能 * 工具栏消息通知全新设计 * RTL 模式支持跟随语言设置自动切换 * 新增布局顶部和底部插槽 * 新增内建组件 * `FaEmpty` * `FaKbdGroup` * `FaNumberField` * `FaQrcode` * `FaScrollingText` * `FaCascader` * `FaTextShiny` * `FaMention` * 大量内建组件进行了重构 --- --- url: /guide/skills.md --- # AI 技能 (Skills) 这里收录项目内所有 `fa-*` 技能文档。 ## 说明 * 大多数技能都会先确认目标应用,也就是 `apps//` * 技能会优先遵循 Fantastic-admin 的目录约定和内建能力 * 如果同一目标已经反复修改 3 次及以上仍未达到预期,会自动触发反馈流程 ## 技能列表 * [fa-crud-page-generator](./fa-crud-page-generator) - 生成完整 CRUD 模块 * [fa-form-builder](./fa-form-builder) - 生成独立表单页 * [fa-framework-settings](./fa-framework-settings) - 修改框架设置 * [fa-i18n-manager](./fa-i18n-manager) - 管理国际化 * [fa-page-optimizer](./fa-page-optimizer) - 优化页面并替换为 Fa 组件 * [fa-route-generator](./fa-route-generator) - 创建或修改路由 * [fa-slot-creator](./fa-slot-creator) - 创建布局插槽 * [fa-store-generator](./fa-store-generator) - 生成 Store 模块 * [fa-theme-customizer](./fa-theme-customizer) - 定制主题配色 ## 使用方式 以 Codex 和 Claude Code 为例: ::: tabs \== Codex ![](/skills/codex.png){data-zoomable} \== Claude Code ![](/skills/claude-code.png){data-zoomable} ::: Skill 并不只限于 Codex 和 Claude Code 使用,因为 `SKILL.md` 是一个开放标准,**只要 Agent 工具支持 Agent Skills 标准,通常就可以复用这些 Skill** 。 本框架在 `skills/` 目录下 **统一维护 Skill** ,如果需要使用,可以通过 [skills](https://npmx.dev/package/skills) 包进行安装,在根目录运行下面命令: ```sh pnpx skills add ./skills --skill '*' ``` :::tip 注意 根目录下有个 [`AGENTS.md`](https://agents.md/) 文件,能帮助 AI 更好的理解整个工程,并且大部分 Agent 都遵循这个文件。 但如果你使用的是 Claude Code,你可能需要将 `AGENTS.md` 更名为 `CLAUDE.md` ,或者给 `AGENTS.md` 做一个软链接映射到 `CLAUDE.md` 文件。 ::: --- --- url: /guide/skills/fa-crud-page-generator.md --- # fa-crud-page-generator ## 适用场景 * 需要快速生成一个标准后台 CRUD 模块 * 需要列表、搜索、分页、新增、编辑、删除等基础能力 * 适合商品、订单、用户、角色、文章等管理页面 ## 使用方式 直接说明以下信息即可: * 目标应用,例如 `example` * 模块名与中文名,例如 `product` / `商品` * 存放路径,例如 `mall` * 字段信息 * 详情模式:`router` / `modal` / `drawer` * 是否生成 Mock * 是否同时生成路由 示例: ```text 在 example 应用里生成一个商品管理模块。 模块名 product,中文名 商品,放在 mall 目录下。 字段有 name、status、createdAt。 使用 drawer 模式,生成 mock,并同时生成路由。 ``` ## 结果 通常会新增以下内容: * `apps//src/views/{path}/{name}/list.vue` * `apps//src/views/{path}/{name}/detail.vue`(仅 router 模式) * `apps//src/views/{path}/{name}/components/DetailForm/index.vue` * `apps//src/api/modules/{fileName}.ts` * `apps//src/api/modules/{fileName}.fake.ts`(可选) * 路由配置(可选) --- --- url: /guide/skills/fa-form-builder.md --- # fa-form-builder ## 适用场景 * 只需要独立表单页,不需要列表页 * 适合设置页、资料页、注册页、独立编辑页 * 希望快速得到一个带校验骨架的表单页面 ## 使用方式 直接说明以下信息即可: * 目标应用,例如 `example` * 模块名与中文名 * 存放路径 * 字段信息 * 是否希望单列或双列布局 示例: ```text 在 example 应用里生成一个个人资料表单页。 模块名 profile,中文名 个人资料,放在 account 目录下。 字段有 name、mobile、bio。 使用双列布局。 ``` ## 结果 通常会新增: * `apps//src/views/{path}/{name}/index.vue` 页面中通常会包含: * 表单布局 * 校验骨架 * 初始值 * 提交与取消按钮 --- --- url: /guide/skills/fa-framework-settings.md --- # fa-framework-settings ## 适用场景 * 需要修改 `apps//src/settings.ts` * 例如开关水印、锁屏、更新检查、国际化按钮、全屏按钮 * 例如切换菜单模式、标签栏风格、布局模式、主题模式 * 例如调整 `theme.sync`、`baseColorLight`、`baseColorDark`、`light`、`dark` ## 使用方式 直接说明以下信息即可: * 目标应用,例如 `example` * 要调整哪些设置项 * 期望效果 示例: ```text 在 example 应用里修改框架设置: 打开水印,菜单改为顶部模式,标签栏改成 fashion。 主题改为不同步,亮色基础色用 stone,暗色基础色用 taupe,暗色主题用 blue。 ``` ## 结果 通常会修改: * `apps//src/settings.ts` 必要时会参考但不会直接修改: * `packages/settings/types.ts` * `packages/settings/src/default.ts` * `packages/themes/index.ts` --- --- url: /guide/skills/fa-i18n-manager.md --- # fa-i18n-manager ## 适用场景 * 页面或组件需要支持多语言 * 需要新增翻译 key * 需要检查缺失翻译 * 需要新增语言或启用语言切换器 ## 使用方式 直接说明以下信息即可: * 目标应用,例如 `example` * 需要新增或修改的翻译 key * 需要支持哪些语言 * 是否要检查缺失 key 示例: ```text 在 example 应用里给用户管理页面补齐中英文翻译。 新增 route.system.user、user.form.name、user.form.status。 并检查一下当前语言文件缺了哪些 key。 ``` ## 结果 根据需求,通常会: * 修改 `packages/locales/lang/**/*.json`(公共框架文案) * 修改 `apps//src/locales/lang/**/*.json`(应用路由/业务文案) * 修改 `apps//src/locales/index.ts`(语言元数据) * 修改 `apps//src/settings.ts`(启用语言切换器时) * 输出缺失翻译报告(检查场景) --- --- url: /guide/skills/fa-page-optimizer.md --- # fa-page-optimizer `fa-page-optimizer` 用来重构已经存在的 Vue 页面。它会优先使用 Fantastic-admin 内建的 `Fa*` 组件和工具函数,替换原生 HTML、重复造轮子的自定义实现,以及风格不统一的页面壳层,在尽量不改业务逻辑的前提下,把页面拉回框架统一的交互和视觉体系。 ## 适用场景 * 页面结构太乱、风格不统一 * 页面里有大量原生 HTML 或重复自定义实现 * 希望用框架内建 `Fa*` 组件替换现有实现 * 希望保留现有接口、权限和业务逻辑,只优化视图层与页面结构 ## 使用方式 直接说明以下信息即可: * 目标应用,例如 `example` * 需要优化的页面文件或目录 * 希望替换或优化的内容,例如搜索区、卡片容器、弹窗、分页、空态、加载状态 * 是否允许顺手拆分子组件或整理模板结构 * 是否要求不改业务逻辑 示例: ```text 在 example 应用里优化用户列表页。 文件是 apps/example/src/views/system/user/index.vue。 把原生按钮、搜索区域、分页和删除确认弹窗替换成 Fa 组件,不要改业务逻辑。 ``` ## 常见优化内容 * 用 `FaCard` 收敛页面容器、标题区、操作区和底部区域 * 用 `FaSearchBar` 替换手写搜索表单或零散筛选输入 * 用 `FaButton`、`FaButtonGroup` 统一操作按钮的样式、尺寸和状态 * 用 `FaModal`、`FaDrawer`、`useFaModal()` 替换自定义弹层与确认逻辑 * 用 `FaPagination`、`FaEmpty`、`FaLoading`、`useFaLoading()` 统一列表状态 * 用 `useFaToast()` 替换零散的成功、失败、警告提示调用 ## 结果 通常会修改已有页面文件,例如: * `apps//src/views/.../*.vue` * `apps//src/views/.../components/*.vue`(按需拆分) 常见结果包括: * 用 `FaButton`、`FaCard`、`FaModal`、`FaPagination` 等替换现有实现 * 优化页面结构与样式 * 保留原有业务逻辑、接口调用和权限判断 * 让页面更贴近 Fantastic-admin 已有页面的交互方式与视觉风格 --- --- url: /guide/skills/fa-route-generator.md --- # fa-route-generator ## 适用场景 * 新建页面后需要加路由 * 需要调整菜单显示、权限、徽章、面包屑、保活 * 需要让详情页隐藏菜单或与列表页合并标签 ## 使用方式 直接说明以下信息即可: * 目标应用,例如 `example` * 页面文件位置 * 路由路径 * 页面标题 * 所属主导航分组 * 是否需要权限、保活、隐藏菜单等 meta 配置 示例: ```text 在 example 应用里给商品列表页加路由。 路径用 /mall/product,标题是 商品管理,放到商城主导航下。 详情页不要显示在菜单里,并且返回列表时保留状态。 ``` ## 结果 根据需求,通常会: * 新增 `apps//src/router/modules/*.ts` * 修改 `apps//src/router/routes.ts` * 修改现有路由的 `meta` 配置 * 读取 `apps//src/settings.ts` 判断路由模式 --- --- url: /guide/skills/fa-slot-creator.md --- # fa-slot-creator ## 适用场景 * 想在头部、侧边栏、工具栏、标签栏增加自定义内容 * 想在 logo 旁边加组织信息、切换器、按钮等 * 想加悬浮组件或自由定位内容 ## 使用方式 直接说明以下信息即可: * 目标应用,例如 `example` * 想放置的区域或插槽位置 * 要展示的内容 * 是否有样式或交互要求 示例: ```text 在 example 应用里,给 HeaderAfterLogo 插槽加一个组织切换器。 使用框架内建组件实现,风格和顶部导航保持一致。 ``` ## 结果 通常会新增: * `apps//src/slots//index.vue` 如果是调整已有插槽,也可能会修改现有: * `apps//src/slots//index.vue` --- --- url: /guide/skills/fa-store-generator.md --- # fa-store-generator ## 适用场景 * 需要全局共享数据 * 需要状态持久化 * 适合用户信息、购物车、通知、筛选条件缓存等场景 * 需要在组件外部也能访问状态 ## 使用方式 直接说明以下信息即可: * 目标应用,例如 `example` * Store 用途 * State 字段与初始值 * 是否需要持久化 * 是否需要异步 action 或 computed 示例: ```text 在 example 应用里生成一个购物车 store。 字段有 items、couponCode、checkedIds。 items 和 couponCode 需要持久化。 还需要拉取购物车的异步 action,以及选中数量的 computed。 ``` ## 结果 通常会新增: * `apps//src/store/modules/.ts` 某些场景下也可能新增到: * `apps//src/store/modules/app/.ts` 文件中通常会包含: * state * computed * action * persist 配置 --- --- url: /guide/skills/fa-theme-customizer.md --- # fa-theme-customizer ## 适用场景 * 需要一套新的品牌主题 * 需要新增或调整基础色 * 想做科技感、莫兰迪、北欧极简、赛博朋克等风格主题 * 想把设计稿或品牌色转换成 Fantastic-admin 主题 * 想让亮色和暗色模式使用不同的基础色或主题色 ## 使用方式 直接说明以下信息即可: * 想要的风格 * 品牌主色或参考色 * 是否需要调整基础色基调 * 是否需要在某个应用中启用 * 目标应用,例如 `example` 示例: ```text 帮我做一套新的 Fantastic-admin 主题。 风格偏科技感,品牌主色是 #2563EB。 基础色想要冷灰一点,暗色模式更沉稳。 请同时生成基础色和主题色,并在 example 应用中启用。 ``` ## 结果 通常会: * 修改 `packages/themes/index.ts` * 修改 `apps//src/settings.ts`,启用该主题 主题结果通常会按当前结构分别处理: * `BASE_COLORS`:基础色定义 * `THEMES`:主题色定义 * 必要时调整 `FRAMEWORK_COLORS` * `theme.baseColorLight / baseColorDark` * `theme.light / dark` --- --- url: /guide/ready.md --- # 准备工作 ## 源码 阅读开发文档前,请确保手上已经有 Fantastic-admin 源码,因为文档中提及的内容,都是需要在本地项目中编写或修改代码并运行才能呈现的。 ### 基础版 到 Github [Releases](https://github.com/fantastic-admin/basic/releases) 页面下载最新版本的压缩包,如下图所示: ![](/download.png){data-zoomable} 或者也可以从 Github / Gitee / Gitcode 上拉取源码,但需要注意,直接拉取源码可能会包含未发布的内容,最终发布时可能会有变动,请谨慎使用。 ```sh # 从 Github 拉取 git clone https://github.com/fantastic-admin/basic.git # 从 Gitee 拉取 git clone https://gitee.com/fantastic-admin/basic.git # 从 Gitcode 拉取 git clone https://gitcode.com/fantastic-admin/basic.git ``` ### 专业版 专业版用户会被邀请加入到 [Fantastic-admin](https://github.com/fantastic-admin) Github 官方组织,加入组织后在专业版仓库 [Releases](https://github.com/fantastic-admin/pro/releases) 页面下载最新版本的压缩包。 购买专业版点[这里](../buy)。 ## 开发环境 使用本模板前,需要在本地依次安装好 [Node.js](https://nodejs.org/), [pnpm](https://pnpm.io/zh/), [Git](https://git-scm.com/)(非必须) 和 [Visual Studio Code](https://code.visualstudio.com/)。 ::: warning 注意 * 在 [package.json](https://github.com/fantastic-admin/basic/blob/main/package.json#L6-L9) 文件中有限制 node 要求版本,建议使用最新 LTS 版本。 * 如果你不想使用 VSCode ,我们也强烈建议你使用基于 VSCode 内核的 IDE ,如 [Cursor](https://www.cursor.com/) 。 ::: 然后在 Visual Studio Code 里安装好以下扩展: * [EditorConfig for VS Code](https://marketplace.visualstudio.com/items?itemName=EditorConfig.EditorConfig) * [DotENV](https://marketplace.visualstudio.com/items?itemName=mikestead.dotenv) * [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint) * [stylelint](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint) * [Vue - Official](https://marketplace.visualstudio.com/items?itemName=Vue.volar) * [UnoCSS](https://marketplace.visualstudio.com/items?itemName=antfu.unocss) 在 Visual Studio Code 里打开源码文件夹,右下角会自动提示需要安装的依赖,直接点击安装即可。 ![](/vscode.png){data-zoomable} ::: tip 额外推荐 以上为开发时必备扩展,以下则是作者推荐安装的扩展,安装它们将在一定程度上提升开发效率。 * [Chinese (Simplified) Language Pack for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=MS-CEINTL.vscode-language-pack-zh-hans) 中文语言包 * [Catalog Lens](https://marketplace.visualstudio.com/items?itemName=antfu.pnpm-catalog-lens) 显示PNPM/Yarn/Bun目录的嵌套版本 * [Goto definition alias](https://marketplace.visualstudio.com/items?itemName=antfu.goto-alias) 转到別名重定向后的定义 * [Iconify IntelliSense](https://marketplace.visualstudio.com/items?itemName=antfu.iconify) 在代码中预览 iconify 图标 * [Color Highlight](https://marketplace.visualstudio.com/items?itemName=naumovs.color-highlight) 在代码中高亮颜色 * [Highlight Matching Tag](https://marketplace.visualstudio.com/items?itemName=vincaslt.highlight-matching-tag) 高亮显示匹配的标签 * [Image preview](https://marketplace.visualstudio.com/items?itemName=kisstkondoros.vscode-gutter-preview) 图片预览 * [indent-rainbow](https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow) 彩虹缩进提示 ::: ## 技术栈 了解并熟悉框架使用到的技术栈,能让你使用本框架更得心应手。 * [Vite](https://cn.vitejs.dev/) * [Vue 3](https://cn.vuejs.org/) * [Vue Router](https://router.vuejs.org/zh/) * [Pinia](https://pinia.vuejs.org/zh/) * [UnoCSS](https://unocss.dev/) --- --- url: /guide/start.md --- # 开始 本项目采用 Monorepo(单体仓库)架构,基于 pnpm workspace 管理多个应用和公共包。 Monorepo 的优势: * **代码共享**:多个应用可共享公共代码和依赖 * **统一管理**:统一版本控制和依赖管理 * **开发效率**:一次修改,多处生效 * **原子提交**:跨应用的变更可在一个提交中完成 ## 目录结构 ``` fantastic-admin/ ├── apps/ # 应用目录 │ ├── core # 应用源码(不集成任何三方 UI 组件库) │ ├── core-* # 应用源码(集成三方 UI 组件库) │ └── example # 示例应用 ├── packages/ # 公共包目录 ├── docs/ # 文档站点 ├── scripts/ # 脚本工具 └── package.json # 根目录 package.json ``` ## 应用说明 ### apps/core 和 apps/core-\* 应用源码,不含示例代码,仅保留必要的项目结构,适合直接用于项目开发。 使用时建议从此处复制一份在 `apps/` 目录下,同时修改 `apps//package.json` 中 `name` 属性。 这样做的目的是确保项目内始终保留一份原始应用源码,方便后续扩展更多应用。 搭配 UI 组件库的介绍可以点[这里](/guide/with-ui-libraries)。 ### apps/example 示例应用,包含丰富的示例代码和最佳实践,适合学习和参考。 ## 常用命令 :::tip 建议 在安装依赖前,可以将不需要的应用先删除。假设你已经足够熟悉框架,则可以将 `apps/example` 应用文件夹直接删除,减少无用依赖的安装。 ::: 根目录 `package.json` 提供了统一的命令入口: ```bash # 安装所有依赖 pnpm install # 启动开发服务器(交互式选择应用) pnpm dev # 构建项目(交互式选择应用) pnpm build # 预览构建产物(交互式选择应用) pnpm serve # 代码检查 pnpm lint ``` 其中 `pnpm lint` 会按以下顺序执行: 1. 在各应用目录执行 `vue-tsc` 2. 在根目录执行 `eslint` 3. 在根目录执行 `stylelint` ::: warning 报错 如果无法正常安装依赖,可能是因为 npm 默认源无法访问,可以尝试执行 `pnpm config set registry https://registry.npmmirror.com/` 切换为国内 npmmirror 镜像源(也可以使用 [nrm](https://github.com/Pana/nrm) 一键切换源),然后删除 `node_modules/` 文件夹并重新安装依赖。 ::: ## 应用级命令 如果明确知道要操作哪个应用,也可以直接使用 pnpm filter 命令: ```bash # 运行指定应用 pnpm -F @fantastic-admin/core dev # 构建指定应用 pnpm -F @fantastic-admin/core build # 在指定应用下执行任意命令 pnpm -F @fantastic-admin/core lint ``` 应用目录中的 `lint` 命令仅执行 `vue-tsc` ,用于当前应用的类型检查。 ## 依赖管理 ### 根目录依赖 在根目录安装的依赖为所有应用和包共享,通常是: * ESLint、Stylelint 等代码规范工具 * 脚本工具(如 tsx、taze) * Git 钩子相关依赖 ### 应用/包级依赖 每个应用或包可以拥有自己独立的依赖,安装在各自的 `node_modules/` 目录下。 ### 添加新依赖 ```bash # 为指定应用添加依赖 pnpm add axios -F @fantastic-admin/core # 为根目录添加开发依赖 pnpm add -D typescript -w ``` 你也可以全局安装 [`@rizumu/nai`](https://github.com/LittleSound/nai) ,并通过交互式的 CLI 将依赖包安装到指定应用,如下图: ![](https://github.com/user-attachments/assets/83d164f3-8a13-41f1-a453-23ffd81ed387) --- --- url: /guide/coding-standard.md --- # 代码规范 :::tip 建议 请确保已阅读《[准备工作 - 开发环境](ready#开发环境)》,并且按照文档说明安装好相关软件及扩展。 ::: 为保证代码风格统一,请使用 [Visual Studio Code](https://code.visualstudio.com/) 做为开发 IDE ,框架源码里已提供相关配置文件,可直接测试效果:在保存代码时,会自动对当前文件进行代码格式化操作。 ## IDE 配置 配置文件为 `.editorconfig` ,通常情况下无需做任何修改。 ## ESLint 配置 配置文件为 `eslint.config.js` ,框架使用 [antfu/eslint-config](https://github.com/antfu/eslint-config) 做为基础规范,如果你对默认的规则有异议,可以查阅 [ESLint](https://eslint.org/) 官网规则并在 `eslint.config.js` 文件中进行覆盖。 当你对规则进行修改后,原有的代码可能会因为规则的变动导致编辑器大量提示错误,你可以通过运行 `pnpm run lint:eslint` 进行一次格式校验,如果规则支持自动修复,则会将不符合规则的代码自动进行格式化。 ::: tip 通过修改 `eslint.config.js` 中 `ignores` 配置可忽略无需做代码规范校验的目录或文件,例如在项目中导入了一些第三方的插件代码或组件代码,我们就可以将其进行忽略。 ::: ## StyleLint 配置 配置文件为 `stylelint.config.js` ,如果你对默认的规则有异议,可以查阅 [Stylelint](https://stylelint.io/) 官网规则并在 `stylelint.config.js` 文件中进行修改。 当你对规则进行修改后,原有的代码可能会因为规则的变动导致编辑器大量提示错误,你可以通过运行 `pnpm run lint:stylelint` 进行一次格式校验,如果规则支持自动修复,则会将不符合规则的代码自动进行格式化。 ::: tip 通过修改 `stylelint.config.js` 中 `ignoreFiles` 配置可忽略无需做代码规范校验的文件,例如在项目中导入了一些第三方的插件代码或组件代码,我们就可以将其进行忽略。 ::: ## simple-git-hooks 和 lint-staged 由于 IDE 能做的事比较有限,只能对代码的书写规范进行格式化,对于一些无法自动修复的错误代码,如果没有改正到就被推送到 git 仓库,在多人协作开发时,可能会影响到别人的开发体验。所以框架集成了 [simple-git-hooks](https://github.com/toplenboren/simple-git-hooks) 和 [lint-staged](https://github.com/okonet/lint-staged) 这两个依赖来解决这一问题。 在提交代码时, simple-git-hooks 会通过 lint-staged 对本次提交变更的文件进行分别进行 eslint 和 stylelint 检测,如果有报错,则会阻止本次代码提交,直到开发者修改完所有错误代码后,才允许提交到 git 仓库,这样可以确保 git 仓库里的代码不会有不规范的代码。 ::: tip 注意 请确保在安装依赖前,已经使用 `git init` 对项目进行过 git 环境初始化,如果你在安装依赖后再初始化了 git 环境,请在 git 环境初始化之后再执行一遍 `pnpm install` 安装命令。 此外,如果 git 仓库目录和框架目录并非同一个,则需要在 `package.json` 中修改 `postinstall` 脚本,切换到 git 所在目录。例如 git 目录是 `project/` ,而框架目录是 `project/fantastic-admin/` ,则在 `package.json` 里找到 `simple-git-hooks` 配置并修改: ```json {2} "simple-git-hooks": { "pre-commit": "cd ./fantastic-admin/ && pnpm lint-staged", "preserveUnused": true } ``` 修改后重新执行一下 `pnpm install` 即可。 ::: ### 移除 如果不想在 git 提交时强制进行代码规范校验,可以在 `package.json` 中移除 `simple-git-hooks` 配置: ```json { "scripts": { "postinstall": "simple-git-hooks", // [!code --] }, "simple-git-hooks": { // [!code --] "pre-commit": "pnpm lint-staged", // [!code --] "preserveUnused": true // [!code --] }, // [!code --] } ``` 然后手动删除 `.git/hooks/pre-commit` 文件即可。 ## 规范化 commit ::: info 该特性由 [cz-git](https://github.com/Zhengqbbb/cz-git) 提供技术支持。 ::: 需先全局安装 `pnpm install -g commitizen` ,然后就可以使用 `pnpm run commit` 来规范化 commit 信息。 --- --- url: /guide/term.md --- # 术语 熟悉框架术语,能帮助你轻松阅读文档,同时与其它开发者交流时,也能帮助你准确地表述问题。 ## 头部导航栏 ![](/term-header-1.png){data-zoomable} ## 头部导航菜单 ![](/term-header-2.png){data-zoomable} ## 主导航栏 ![](/term-mainsidebar-1.png){data-zoomable} ## 主导航菜单 ![](/term-mainsidebar-2.png){data-zoomable} ## 次导航栏 ![](/term-subsidebar-1.png){data-zoomable} ## 次导航菜单 ![](/term-subsidebar-1.png){data-zoomable} ### 一级导航菜单(一级路由) ![](/term-menu-level-1.png){data-zoomable} ### 二级导航菜单(二级路由) ![](/term-menu-level-2.png){data-zoomable} ### 三级导航菜单(三级路由) ![](/term-menu-level-3.png){data-zoomable} ## 顶栏 顶栏 = 标签栏 + 工具栏 ### 标签栏 ![](/term-tabbar.png){data-zoomable} ### 工具栏 ![](/term-toolbar.png){data-zoomable} --- --- url: /guide/env.md --- # 环境变量 环境变量配置文件在 `apps//` 根目录,默认提供三套配置,分别为: ::: code-group ```env \[.env.development 开发环境] # 应用配置面板 # Application configuration panel VITE_APP_SETTING = true # 网站标题 # Website title VITE_APP_TITLE = Fantastic-admin # 网络请求地址,应用于 axios 的 baseURL # Network request address, applied to axios's baseURL VITE_APP_API_BASEURL = / # localStorage/sessionStorage 前缀 # localStorage/sessionStorage prefix VITE_APP_STORAGE_PREFIX = fa_dev_ # 调试工具,可设置 eruda 或 vconsole # Debugging tool, can set eruda or vconsole VITE_APP_DEBUG_TOOL = # ===== 以下配置仅在开发环境生效 ===== # ===== The following configuration is only effective in the development environment. ===== # 启用代理 # Enable proxy VITE_ENABLE_PROXY = false # 启用 Vue 开发工具 # Enable Vue DevTools VITE_ENABLE_VUE_DEVTOOLS = false # 启用 turbo console # Enable turbo console VITE_ENABLE_TURBO_CONSOLE = false # 启动编辑器,用于 vite-plugin-vue-devtools 和 unplugin-turbo-console # 支持的编辑器 https://github.com/yyx990803/launch-editor#supported-editors # Launch the editor for vite-plugin-vue-devtools and unplugin-turbo-console # Supported editors https://github.com/yyx990803/launch-editor#supported-editors VITE_LAUNCH_EDITOR = code ``` ```env \[.env.test 测试环境] # 应用配置面板 # Application configuration panel VITE_APP_SETTING = false # 网站标题 # Website title VITE_APP_TITLE = Fantastic-admin # 网络请求地址,应用于 axios 的 baseURL # Network request address, applied to axios's baseURL VITE_APP_API_BASEURL = / # localStorage/sessionStorage 前缀 # localStorage/sessionStorage prefix VITE_APP_STORAGE_PREFIX = fa_test_ # 调试工具,可设置 eruda 或 vconsole # Debugging tool, can set eruda or vconsole VITE_APP_DEBUG_TOOL = # ===== 以下配置仅在测试环境生效 ===== # ===== The following configuration is only effective in the test environment. ===== # 禁用浏览器开发者工具 # Disable browser developer tools VITE_APP_DISABLE_DEVTOOL = false # 启用假数据 # Enable build fake data VITE_BUILD_FAKE = true # 启用 sourcemap # Enable build sourcemap VITE_BUILD_SOURCEMAP = true # 压缩方式,支持 gzip 和 brotli # Build compression method, supports gzip and brotli VITE_BUILD_COMPRESS = # 构建后生成存档,支持 zip 和 tar # Generate archive after build, supports zip and tar VITE_BUILD_ARCHIVE = ``` ```env \[.env.production 生产环境] # 应用配置面板 # Application configuration panel VITE_APP_SETTING = false # 网站标题 # Website title VITE_APP_TITLE = Fantastic-admin # 网络请求地址,应用于 axios 的 baseURL # Network request address, applied to axios's baseURL VITE_APP_API_BASEURL = / # localStorage/sessionStorage 前缀 # localStorage/sessionStorage prefix VITE_APP_STORAGE_PREFIX = fa_ # 调试工具,可设置 eruda 或 vconsole # Debugging tool, can set eruda or vconsole VITE_APP_DEBUG_TOOL = # ===== 以下配置仅在生产环境生效 ===== # ===== The following configuration is only effective in the production environment. ===== # 禁用浏览器开发者工具 # Disable browser developer tools VITE_APP_DISABLE_DEVTOOL = false # 启用假数据 # Enable build fake data VITE_BUILD_FAKE = false # 启用 sourcemap # Enable build sourcemap VITE_BUILD_SOURCEMAP = false # 压缩方式,支持 gzip 和 brotli # Build compression method, supports gzip and brotli VITE_BUILD_COMPRESS = gzip,brotli # 构建后生成存档,支持 zip 和 tar # Generate archive after build, supports zip and tar VITE_BUILD_ARCHIVE = ``` ::: 开发者可根据实际业务需求进行扩展,详细可阅读 [Vite - 环境变量和模式](https://cn.vitejs.dev/guide/env-and-mode.html) 章节。 ## 通用配置项 即不管是在开发、测试,还是生产环境都会使用到。 ### VITE\_APP\_SETTING ![](/env.VITE_APP_SETTING.gif){data-zoomable} 应用配置面板的目的是方便开发者在开发阶段调试框架提供的各类配置参数,生产环境下默认关闭,也建议关闭。 如果希望提供用户一些个性化的能力,可以开启[用户偏好设置](./settings/app#用户偏好设置)。 ### VITE\_APP\_TITLE 网站标题,会在浏览器标题、首屏loading、登录页和导航菜单处显示。 ### VITE\_APP\_API\_BASEURL [扩展阅读](axios) ### VITE\_APP\_STORAGE\_PREFIX [扩展阅读](storage) ### VITE\_APP\_DEBUG\_TOOL 方便在不支持启用浏览器开发者工具的环境,启用一个轻量级的调试工具。 ```env # 调试工具 eruda VITE_APP_DEBUG_TOOL = eruda # 调试工具 vconsole VITE_APP_DEBUG_TOOL = vconsole ``` ## 开发环境配置项 ### VITE\_ENABLE\_PROXY [扩展阅读](axios#跨域处理) ### VITE\_ENABLE\_VUE\_DEVTOOLS [扩展阅读](devtools#vue-开发工具) ### VITE\_ENABLE\_TURBO\_CONSOLE [扩展阅读](devtools#console-工具) ### VITE\_LAUNCH\_EDITOR [扩展阅读](devtools#默认启动-ide) ## 测试/生产环境 ### VITE\_APP\_DISABLE\_DEVTOOL 开启后将禁止通过右键、F12或任意方式打开浏览器开发者工具。 ### VITE\_BUILD\_FAKE [扩展阅读](axios#生产环境) ### VITE\_BUILD\_SOURCEMAP 开启后生成的构建产物里包含 sourcemap 文件 ### VITE\_BUILD\_COMPRESS 可在构建时生成 `.gz` 和 `.br` 文件。 ```env # 单独开启 gzip VITE_BUILD_COMPRESS = gzip # 单独开启 brotli ,brotli 是比 gzip 压缩率更高的算法 VITE_BUILD_COMPRESS = brotli # 也可以都开启,会同时生成 .gz 和 .br 文件 VITE_BUILD_COMPRESS = gzip,brotli ``` 两者均需要 nginx 安装指定模块并开启后才会生效。 ### VITE\_BUILD\_ARCHIVE 在构建完后成生成 `.zip` 或 `.tar.gz` 文件。 ```env # 生成 zip VITE_BUILD_ARCHIVE = zip # 生成 tar.gz VITE_BUILD_ARCHIVE = tar ``` --- --- url: /guide/axios.md --- # 与服务端交互 框架使用 [Axios](https://axios-http.com/zh/) 做为异步请求工具,并进行了简单的封装。 ## 接口请求 ### 设置 baseURL 在 `apps//.env.*` 文件里的 `VITE_APP_API_BASEURL` 这个参数就是配置 axios 的 `baseURL` 。 例如项目的真实接口请求地址为: * `http://api.test.com/news/list` * `http://api.test.com/news/create` * `http://api.test.com/shop/info` 则可设置为 `VITE_APP_API_BASEURL = http://api.test.com/` 。 ### 请求调用 常用的 GET 和 POST 请求可使用以下的方法: ```ts import api from '@/api' // GET 请求 api.get('news/list', { params: { page: 1, size: 10, }, }).then((res) => { // 后续业务代码 }) // POST 请求 api.post('news/create', { title: '新闻标题', content: '新闻内容', }).then((res) => { // 后续业务代码 }) ``` ### 拦截器 在 `apps//src/api/index.ts` 文件里实例化了 axios 对象,并对 `request` 和 `response` 设置了拦截器,拦截器的用处就是拦截每一次的请求和响应,然后做一些全局的处理。例如接口响应报错,可以在拦截器里用统一的报错提示来展示,方便业务开发。但因为每个公司提供的接口标准不同,所以该文件拦截器部分的代码,需要开发者根据实际情况去修改调整。 代码很简单,首先初始化 axios 对象,然后 `axios.interceptors.request.use()` 和 `axios.interceptors.response.use()` 就分别是请求和响应的拦截代码了。 参考代码里只做了简单的拦截处理,例如请求的时候会自动带上 token ,响应的时候会根据错误信息判断是登录失效还是接口报错,并做相应动作。 ### 请求重试 框架扩展了请求配置参数,只需在请求时增加 `retry` 配置项,即可开启请求重试。 ```ts api.get('news/list', { retry: true, }) api.post('news/create', { title: '新闻标题', content: '新闻内容', }, { retry: true, }) ``` 默认请求重试次数为 3 次,请求间隔为 1000 毫秒,可在 `apps//src/api/index.ts` 文件中修改 `MAX_RETRY_COUNT` 和 `RETRY_DELAY` 的默认配置。 ## 模块管理 如果项目里的接口很多,推荐根据模块来统一管理接口,目录为 `apps//src/api/modules/` 。 ## 跨域处理 生产环境的跨域需要服务端去解决,开发环境的跨域问题可在本地设置代理解决。如果本地开发环境请求接口提示跨域,可以设置 `apps//.env.development` 文件里 `VITE_ENABLE_PROXY = true` 开启代理。 ```ts import api from '@/api' api.get('news/list') // http://localhost:9000/proxy/news/list api.post('news/add') // http://localhost:9000/proxy/news/add ``` 开启代理后,原有请求都会被指向到本地 `http://localhost:9000/proxy` ,因为 `/proxy` 匹配到了 vite.config.ts 里代理部分的设置,所以实际是请求依旧是 `VITE_APP_API_BASEURL` 所设置的地址。 ```ts {2-9} server: { // vite.config.ts 中 proxy 配置,该配置即用于代理 API 请求 proxy: { '/proxy': { target: loadEnv(mode, process.cwd()).VITE_APP_API_BASEURL, changeOrigin: command === 'serve' && loadEnv(mode, process.cwd()).VITE_ENABLE_PROXY == 'true', rewrite: path => path.replace(/\/proxy/, ''), }, }, }, ``` ## 多数据源 如果项目里需要从多个不同地址的数据源请求数据,你有两种方式可以实现。 如果只是几个接口需求从其它数据源请求,你可以使用覆盖 `baseURL` 的方式: ```ts import api from '@/api' api.get('/new/list', { baseURL: 'http://baidu.com/', // 直接覆盖 baseURL }) ``` 这种方式的前提是,两个数据源的 `request` 和 `response` 规则要保持一致,因为只是覆盖 `baseURL` ,拦截器还是用的同一套规则。 所以如果两个数据源的请求和响应是完全不同的标准,你需要给第二个数据源单独实例化一个 axios 对象。首先在 `apps//.env.*` 文件里配置第二个数据源的 `baseURL` : ``` # 命名可随意,以 VITE_APP_ 开头即可 VITE_APP_API_BASEURL_2 = 此处填写接口地址 ``` 然后把 `apps//src/api/index.ts` 文件复制一份,例如就叫 `apps//src/api/index2.ts` ,并且将代码中使用到 `VITE_APP_API_BASEURL` 也替换为 `VITE_APP_API_BASEURL_2` ,这样你就可以在页面中通过引入不同的文件分别请求两个数据源了: ```ts import api from '@/api' import api2 from '@/api/index2' // 请求默认数据源 api.get('/new/list') // 请求第 2 个数据源 api2.get('/new/list') ``` 需注意,如果第二个数据源也需要开启跨域处理的话,需要在 `apps//src/api/index2.ts` 里定一个新的 proxy 路径,例如 `/proxy2/` : ```ts {2} const api = axios.create({ baseURL: import.meta.env.DEV && import.meta.env.VITE_ENABLE_PROXY === 'true' ? '/proxy2/' : import.meta.env.VITE_APP_API_BASEURL_2, timeout: 10000, responseType: 'json', }) ``` 同时在 `apps//vite.config.ts` 里增加一段新的 proxy 配置: ```ts {9-13} server: { // vite.config.ts 中 proxy 配置,该配置即用于代理 API 请求 proxy: { '/proxy': { target: loadEnv(mode, process.cwd()).VITE_APP_API_BASEURL, changeOrigin: command === 'serve' && loadEnv(mode, process.cwd()).VITE_ENABLE_PROXY == 'true', rewrite: path => path.replace(/\/proxy/, ''), }, '/proxy2': { target: loadEnv(mode, process.cwd()).VITE_APP_API_BASEURL_2, changeOrigin: command === 'serve' && loadEnv(mode, process.cwd()).VITE_ENABLE_PROXY == 'true', rewrite: path => path.replace(/\/proxy2/, ''), }, }, }, ``` ## 假数据 假数据是前端开发过程中必不可少的一环,是分离前后端开发的关键链路。通过预先跟服务器端约定好的接口,模拟请求数据甚至逻辑,能够让前端开发独立自主,不会被服务端的开发所阻塞。 :::tip 框架使用 [vite-plugin-fake-server](https://github.com/condorheroblog/vite-plugin-fake-server) 提供开发和生产模拟服务。 ::: ### 开发环境 文件存放在 `apps//src/api/modules/` 目录下,并以 `*.fake.ts` 命名。文件新增或修改后会自动更新,不需要手动重启,可以在代码控制台查看日志信息。 以下为示例代码: ```ts import { defineFakeRoute } from 'vite-plugin-fake-server/client' // 管理员 const allList: any[] = [] for (let i = 0; i < 50; i++) { allList.push(i + 1) } export default defineFakeRoute([ { url: '/fake/page/loadmore', method: 'get', response: ({ query }) => { const { from, limit } = query const pageList = allList.filter((_item, index) => { return index >= ~~from && index < (~~from + ~~limit) }) return { error: '', status: 1, data: { list: pageList, total: allList.length, }, } }, }, ]) ``` 参数获取: * GET:`({ query }) => { }` * POST:`({ body }) => { }` 为了让假数据接口与真实接口共存,即项目开发中,部分请求假数据接口,部分请求真实接口。需要在配置假数据接口的时候,给 `url` 参数统一设置 `/fake/` 前缀,并在调用接口的时候,设置 `fake: true` 。 如下所示,其中 `news/list` 会请求本地的假数据接口,而 `news/create` 依旧请求真实接口,即使开启跨域代理也不影响。 ```ts {4} import api from '@/api' api.get('news/list', { fake: true, // <- 区别在这 params: { page: 1, size: 10, }, }).then((res) => { // 后续业务代码 }) api.post('news/create', { title: '新闻标题', content: '新闻内容', }).then((res) => { // 后续业务代码 }) ``` ### 生产环境 :::warning 注意 生产环境一般都是调用真实接口,如果需要使用假数据也只适用于一些简单的示例网站及预览网站。 ::: 框架默认已经配置好生产环境,如果不想让生产环境里的请求走假数据,可在接口调用处删除 `fake: true` 设置。 需要注意一点,如果项目中有涉及到上传功能,请彻底关闭线上环境假数据,在环境配置里设置 `VITE_BUILD_FAKE = false` ,不然线上环境将会报错。 开发环境与生产环境使用假数据差异不大,比较大的区别是生产环境里调用假数据接口,在控制台内看不到接口请求日志。 --- --- url: /guide/login.md --- # 登录相关 登录相关功能包括登录、注册、忘记密码等,所有的表单组件均存放在 `apps//src/components/AppAccountForm/` 目录下。 ## 登录 开发者通常在简单熟悉本框架后,涉及到的第一步业务开发就是修改登录功能,将其替换为自己的登录接口。 但在实践过程中,经常会遇到一些问题,比如: * 替换真实接口后,无法正常登录 * 登录接口请求成功,但是无法跳转到后台主页 * ... 针对这些问题你需要依次检查以下几点: 1. 在 `apps//.env.development` 里检查接口请求地址是否正确。 2. 在 `apps//src/api/index.ts` 里修改响应拦截器里的代码,按照实际情况进行调整。例如什么状态下是请求成功,什么状态下是请求异常,并进行错误提示。 3. 在 `apps//src/api/modules/app.ts` 里修改 `login` 函数,确保接口可以请求成功。 4. 在 `apps//src/store/modules/account.ts` 里修改 `isLogin` 计算属性,这部分需要根据实际存储的用户信息去判断是否登录。 ## 注册、忘记密码 如果不需要注册、忘记密码功能,可以在 `apps//src/views/login.vue` 中删除相关组件使用的代码。 --- --- url: /guide/router.md --- # 路由 (导航菜单) 路由配置存放在 `apps//src/router/modules/` 目录下,每一个 ts 文件被视为一个路由模块,所有路由模块最终会在 `apps//src/router/routes.ts` 文件里引入并放到不同的主导航菜单下。 最终,路由数据会自动生成导航菜单。 ## 基本配置 ### 二级路由 一个最常见的路由模块可参考以下结构: ```ts import type { RouteRecordRaw } from 'vue-router' const routes: RouteRecordRaw = { path: '/example', component: () => import('@/layouts/index.vue'), redirect: '/example/index', name: 'Example', meta: { title: '演示', }, children: [ { path: 'index', name: 'ExampleIndex', component: () => import('@/views/example/index.vue'), meta: { title: '演示页面', }, }, ], } export default routes ``` :::warning 注意 * 所有路由的 `name` 请确保唯一,不能重复 * 一级路由的 `component` 需设置为 `() => import('@/layouts/index.vue')` ,并且 path 前面需要加 `/`,其余子路由都不要以 `/` 开头 ::: ### 多级路由 :::tip 说明 多级路由的中间层级,无需设置 `component` ,其原因可阅读《[关于 KeepAlive 多级路由缓存问题的终极解决方案](https://juejin.cn/post/7471722655933579290)》。 ::: ```ts import type { RouteRecordRaw } from 'vue-router' const routes: RouteRecordRaw = { path: '/example', component: () => import('@/layouts/index.vue'), redirect: '/example/level/index', name: 'Example', meta: { title: '演示', }, children: [ { path: 'level', name: 'ExampleLevel', // 无需设置 componment meta: { title: '中间层级', }, children: [ { path: 'index', name: 'ExampleLevelIndex', component: () => import('@/views/example/index.vue'), meta: { title: '演示页面', }, }, ], }, ], } export default routes ``` ### 主导航菜单 主导航菜单并非路由的一部分,它只是将路由模块进行归类,这样设计的优势在于可以方便调整单个路由模块的展示位置,并且不会影响路由路径。 在 `apps//src/router/routes.ts` 里进行设置: ```ts const asyncRoutes: Route.recordMainRaw[] = [ { meta: { title: '演示', icon: 'menu-default', }, children: [ MultilevelMenuExample, BreadcrumbExample, KeepAliveExample, ], }, { meta: { title: '其它', icon: 'menu-other', }, children: [ ComponentExample, PermissionExample, ], }, ] ``` 主导航菜单只需设置 `meta` 和 `children` 两个参数,其中 `meta` 接受 `auth`、`localeAuth`、`title`、`icon`、`badge` 参数,`children` 则是存放不同的路由模块。 ## 导航菜单配置 框架的核心是通过路由数据生成导航菜单,所以除了路由的基本配置外,框架还提供了针对导航的自定义配置,这些配置都存放在 `meta` 元信息里。 ### auths ```ts /** * 权限池 * @description 对路由本身无实际作用,通常用于角色管理模块,展示路由可配置权限 * @default undefined * @example * [ * { name: '新闻管理(浏览)', value: 'news:view' }, * { name: '新闻管理(编辑)', value: 'news:edit' } * ] */ auths?: { name: string value: string }[] ``` :::tip 注意 * `auths` 里需包含 `auth` 所设置的权限,否则可能会出现无法设置该路由的访问权限。 * `auths` 的存放位置并不固定,可以放在任意一级路由上,但通常建议放在某个模块的入口路由上,表示该模块下所有子路由具备的可配置权限。 ::: 权限池存放了该路由相关的所有权限,包括但不限于:访问权限、按钮权限、颗粒度更细的权限等。以下是一个示例: ```ts {8-15,23,33} import type { RouteRecordRaw } from 'vue-router' const routes: RouteRecordRaw = { path: '/news', component: () => import('@/layouts/index.vue'), meta: { title: '新闻管理', auths: [ { name: '浏览', value: 'browse' }, { name: '新增', value: 'add' }, { name: '编辑', value: 'edit' }, { name: '删除', value: 'delete' }, { name: '导出', value: 'export' }, { name: '导入', value: 'import' }, ], }, children: [ { path: 'list', component: () => import('@/views/news/list.vue'), meta: { title: '新闻列表', auth: 'browse', }, }, { path: 'detail', component: () => import('@/views/news/detail.vue'), meta: { title: '新闻详情', menu: false, activeMenu: '/news/list', auth: 'browse', }, }, ], } export default routes ``` 该配置的具体应用可参考演示站[示例](https://fantastic-admin.hurui.me/pro-example/#/pages_example/general/role)及[源码](https://github.com/fantastic-admin/pro/tree/main/apps/example/src/views/pages_example/role)。 ### auth ```ts /** * 权限 * @description 路由访问权限,配置为数组时,只需满足一个即可进入 * @default undefined * @example * 'news:view' - 访问该路由时,需要具备 news:view 权限 * ['news:view', 'news:edit'] - 访问该路由时,需要具备 news:view 或 news:edit 权限 */ auth?: string | string[] ``` 用户在访问路由时,会判断当前路由是否具备访问权限,不具备访问权限则会显示 403 页面,详细可阅读《[权限 - 路由权限](./auth#路由权限)》。 如果在某个多级路由的多个层级上均设置了 `auth` ,则框架会依次判断,必须每一层级都具备访问权限,才能访问该路由。 ```ts {13,26} import type { RouteRecordRaw } from 'vue-router' const routes: RouteRecordRaw = { path: '/system', meta: { title: '系统管理', }, children: [ { path: 'department', meta: { title: '部门管理', auth: 'a', }, children: [ { path: 'job', meta: { title: '职位管理', }, children: [ { path: 'member', meta: { title: '人员管理', auth: 'b', // 只有当用户权限里同时含有 a 和 b 时,才能访问该路由 }, }, ], }, ], }, ], } export default routes ``` ### localeAuth ```ts /** * 区域权限 * @description 区域语言权限,配置为数组时,只需满足一个即可进入 * @default undefined * @example * 'zh-cn' - 当前区域语言为 zh-cn 允许访问该路由 * ['zh-cn', 'zh-tw'] - 当前区域语言为 zh-cn 或 zh-tw 允许访问该路由 */ localeAuth?: string | string[] ``` 在做国际化业务场景时,可以对某个路由做区域访问限制。 ```ts {6} const asyncRoutes: RouteRecordMainRaw[] = [ { meta: { title: 'UI', icon: 'i-whh:jqueryui', localeAuth: ['zh-cn', 'zh-tw'], }, children: [ ElementPlusExample, ], }, ] ``` ### singleMenu ```ts /** * 单个一级导航 * @description 该配置用于简化只想展示一级,没有二级导航的路由配置。 * @default false */ singleMenu?: boolean ``` ::: tip 注意 该配置只能在一级路由上设置才会生效。 ::: 如果要在次导航菜单里,展示一个没有二级导航菜单的路由配置,通常需要这样: ```ts import type { RouteRecordRaw } from 'vue-router' const routes: RouteRecordRaw = { path: '/test', component: () => import('@/layouts/index.vue'), meta: { title: '测试页面', }, children: [ { path: '', name: 'test', component: () => import('@/views/test/index.vue'), meta: { title: '测试页面', menu: false, breadcrumb: false, }, }, ], } export default routes ``` 而通过该配置项可以大幅简化代码,框架内部会帮你进行转换。 ```ts {9} import type { RouteRecordRaw } from 'vue-router' const routes: RouteRecordRaw = { path: '/test', name: 'test', component: () => import('@/views/test/index.vue'), meta: { title: '测试页面', singleMenu: true, }, } export default routes ``` ### title ```ts /** * 标题 * @description 标题会在导航、标签页、面包屑等需要的展示位置显示 * @default undefined * @example * '新闻管理' - 标题为新闻管理 */ title?: string | (() => string) ``` 支持设置 i18n 对应的 key 值,详细可阅读《[国际化](i18n)》。 ### icon ```ts /** * 图标 * @description 如果配置为数组,则第一个为默认图标,第二个为激活图标 * @default undefined * @example * 'i-ep:lock' - 默认显示 i-ep:lock 图标 * ['i-ep:lock', 'i-ep:unlock'] - 默认显示 i-ep:lock 图标,激活时显示 i-ep:unlock 图标 */ icon?: string | [string, string] ``` ::: tip 注意 激活图标仅在提供支持 ::: 该项配置最终会通过 `FaIcon` 组件进行展示,意味着你可以使用自定义图标,也可使用 Iconify 提供的图标,详细可阅读《[图标](./icon)》。 ### query ```ts /** * 路由 query 参数 * @description 点击导航时进行路由跳转时,携带的参数 * @default undefined * @example * { id: 1, name: 'test' } - 点击导航时,携带 id 参数为 1,name 参数为 test */ query?: Record ``` ### menu ```ts /** * 是否在导航菜单中显示 * @description 当子导航菜单里没有可展示的导航菜单时,会直接显示父导航菜单 * @default true */ menu?: boolean ``` 当子导航菜单里没有可展示的导航菜单时,会直接显示父导航菜单,例如: ```ts {17} import type { RouteRecordRaw } from 'vue-router' const routes: RouteRecordRaw = { path: '/style_example', component: () => import('@/layouts/index.vue'), meta: { title: '风格实验室', icon: 'i-ion:dice', }, children: [ { path: '', name: 'styleExample', component: () => import('@/views/style_example/index.vue'), meta: { title: '风格实验室', menu: false, breadcrumb: false, }, }, ], } export default routes ``` ![](/route-meta-menu.png){data-zoomable} ### activeMenu ```ts /** * 高亮导航菜单 * @description 需要设置完整路由地址 * @default undefined * @example '/news/list' */ activeMenu?: string ``` 需搭配 `menu: false` 一起使用,因为子导航菜单不显示,会导致进入该导航菜单路由后,导航菜单高亮效果失效,所以需要手动指定。 ```ts {22-23} import type { RouteRecordRaw } from 'vue-router' const routes: RouteRecordRaw = { path: '/news', component: () => import('@/layouts/index.vue'), meta: { title: '新闻管理', }, children: [ { path: 'list', component: () => import('@/views/news/list.vue'), meta: { title: '新闻列表', }, }, { path: 'detail', component: () => import('@/views/news/detail.vue'), meta: { title: '新闻详情', menu: false, activeMenu: '/news/list', }, }, ], } export default routes ``` ### expand ```ts /** * 是否默认展开 * @description 如果配置为数组,则第一个为默认展开状态,第二个是否始终展开 * @default undefined * @example * true - 默认展开 * [true, true] - 默认展开,且不允许收起 */ expand?: boolean | [boolean, boolean] ``` ::: tip 注意 是否始终展开仅在提供支持 ::: 该特性仅在 `顶部模式` / `侧边栏模式(含主导航菜单)` / `侧边栏模式(无主导航菜单)` 下生效。 使用该特性时,建议在应用配置中关闭 [`menu.subMenuUniqueExpand`](settings/menu#次导航菜单只保持一个子项的展开) 。 ### badge ```ts /** * 徽章 * @description 如果配置为数组,则第一个为徽章内容,第二个为徽章颜色 * @default undefined * @example * 'PRO' - 显示徽章,内容为 PRO * [true, 'destructive'] - 显示徽章,内容为圆点,颜色为 'destructive' */ badge?: boolean | string | number | (() => boolean | string | number) | [ boolean | string | number | (() => boolean | string | number), 'default' | 'secondary' | 'destructive' | (() => 'default' | 'secondary' | 'destructive'), ] ``` ::: tip 注意 徽章颜色仅在提供支持 ::: 设置不同的类型值,展示效果也会不同: * `boolean` 展示形式为点,当值为 false 时隐藏 * `number` 展示形式为文本,当值小于等于 0 时隐藏 * `string` 展示形式为文本,当值为空时隐藏 如果标记需要动态更新,请设置为箭头函数形式,并返回外部变量,例如搭配 pinia 一起使用。 ```ts badge: () => globalStore.number ``` ### sort ```ts /** * 导航排序 * @description 数字越大越靠前 * @default 0 */ sort?: number ``` ### breadcrumb ```ts /** * 是否在面包屑中显示 * @description 是否在面包屑导航中显示 * @default true */ breadcrumb?: boolean ``` ### tabPermanent ```ts /** * 是否常驻标签页 * @description 请勿在带有参数的路由上设置该特性 * @default false */ tabPermanent?: boolean ``` 使用该特性时,需要在应用配置中开启 `tabbar.enable` 设置,同时需注意,请勿在带有参数的路由上设置该特性。 ### tabMerge ```ts /** * 标签页合并 * @description 根据规则合并标签页 * @default undefined * @example * 'routeName' - 根据路由名称合并 * 'activeMenu' - 根据 activeMenu 属性合并 */ tabMerge?: 'routeName' | 'activeMenu' ``` ::: tabs \== 默认 ```ts const routes: RouteRecordRaw = { path: '/manager', meta: { title: '管理员管理', }, children: [ { path: '', name: 'ManagerList' meta: { title: '管理员列表', }, }, { path: 'detail/:id', name: 'ManagerEdit', meta: { title: '编辑管理员', menu: false, activeMenu: '/manager', }, }, ], } ``` ![](/route-meta-tabmerge-none.gif){data-zoomable} 从列表页进入详情页时,会新增一个**编辑管理员**的标签页,返回列表页并进入其他详情页,会继续新增一个**编辑管理员**的标签页。 \== 'routeName' ```ts {16,21} const routes: RouteRecordRaw = { path: '/manager', meta: { title: '管理员管理', }, children: [ { path: '', name: 'ManagerList' meta: { title: '管理员列表', }, }, { path: 'detail/:id', name: 'ManagerEdit', meta: { title: '编辑管理员', menu: false, activeMenu: '/manager', tabMerge: 'routeName', }, }, ], } ``` ![](/route-meta-tabmerge-routeName.gif){data-zoomable} 从列表页进入详情页时,会新增一个**编辑管理员**的标签页,返回列表页并进入其他详情页,会替换已打开的详情页,始终保持只有一个**编辑管理员**的标签页。 \== 'activeMenu' ```ts {20,21} const routes: RouteRecordRaw = { path: '/manager', meta: { title: '管理员管理', }, children: [ { path: '', name: 'ManagerList' meta: { title: '管理员列表', }, }, { path: 'detail/:id', name: 'ManagerEdit', meta: { title: '编辑管理员', menu: false, activeMenu: '/manager', tabMerge: 'activeMenu', }, }, ], } ``` ![](/route-meta-tabmerge-activeMenu.gif){data-zoomable} 从列表页进入详情页时,会替换当前**管理员列表**的标签页,展示为**编辑管理员**的标签页,并且始终保持只有一个标签页。 ::: ### keepAlive ```ts /** * 保活 * @description 根据规则保活当前路由页面 * @default undefined * @example * true - 始终保活 * 'news' - 访问路由name为news的页面时保活 * ['news', 'user'] - 访问路由name为news或user的页面时保活 */ keepAlive?: boolean | string | string[] ``` 设置不同的类型值,可满足不同场景的保活需求: * `boolean` 设置为 true 时,该路由页面始终保活 * `string` 设置某个目标路由的 name ,表示当前路由跳转到目标路由时,会将当前页面进行保活,否则不保活 * `string[]` 可设置一个目标路由的 name 数组 当类型为 `string` 或 `string[]` 时,可以更精细的去控制页面保活的逻辑。例如从列表页进入详情页,则需要将列表页进行保活;而从列表页进入其它页面,则无需将列表页进行保活。详细可阅读《[页面保活 - 基础用法](keep-alive#基础用法)》。 ### noKeepAlive ```ts /** * 不保活 * @description 根据规则不保活当前路由页面 * @default undefined * @example * 'news' - 访问路由name为news的页面时不保活 * ['news', 'user'] - 访问路由name为news或user的页面时不保活 */ noKeepAlive?: string | string[] ``` 设置不同的类型值,可满足不同场景的保活需求: * `string` 设置某个目标路由的 name ,表示当前路由跳转到目标路由时,则将当前页面清除保活,否则不清除保活 * `string[]` 可设置一个目标路由的 name 数组 该属性通常在启用标签栏合并时会使用到。详细可阅读《[页面保活 - 高级用法](keep-alive#高级用法)》。 ### maximize ```ts /** * 最大化 * @description 如果配置为数组,则第一个为是否开启最大化,第二个为是否允许手动退出最大化 * @default undefined * @example * true - 开启最大化 * [true, false] - 开启最大化,允许手动退出最大化 * [true, true] - 开启最大化,不允许手动退出最大化 */ maximize?: boolean | [boolean, boolean] ``` 访问该路由时,是否最大化业务页面组件展示区。 ### newWindow ```ts /** * 新窗口 * @description 是否在新窗口打开 * @default false */ newWindow?: boolean ``` 该设置仅在导航菜单里点击生效。 ### iframe ```ts /** * iframe * @description 是否在iframe中打开 * @default undefined * @example * 'https://fantastic-admin.hurui.me' - 在iframe中打开 Fantastic-admin 官网 * true - 获取路由query中的iframe属性,并在iframe中打开 */ iframe?: string | boolean ``` 内嵌网页无需设置 `component` ,但需设置 `redirect` 和 `name` 属性,如果同时设置了 `meta.link` 则 `meta.link` 优先级更高。 ```ts {11-19} import type { RouteRecordRaw } from 'vue-router' const routes: RouteRecordRaw = { path: '/xxx', component: () => import('@/layouts/index.vue'), redirect: '/xxx/iframe', meta: { title: '内嵌网页', }, children: [ { path: 'iframe', redirect: '', name: 'Iframe', meta: { title: 'Gitee 仓库', iframe: 'https://gitee.com/fantastic-admin/basic', }, }, ], } export default routes ``` 内嵌网页同样支持使用 `keepAlive` 和 `noKeepAlive` 属性来开启页面保活,但考虑到 `