好,这里我按 ruoyi-vue3 官方前端工程的真实结构 ,用「从根到细节 」的方式给你讲一遍,重点放在每个目录存在的意义、什么时候会用、能不能删/改,而不是泛泛而谈。
以下说明基于 RuoYi-Vue3(Vite + Vue3 + Pinia + Element Plus) 标准版本,你现在贴的代码也完全对得上这一套。
一、项目根目录结构(第一层)
text
ruoyi-ui/
├─ public/
├─ src/
├─ .env
├─ .env.development
├─ .env.production
├─ index.html
├─ package.json
├─ vite.config.js
└─ README.md
1️⃣ public/(静态资源原样拷贝)
text
public/
├─ favicon.ico
├─ robots.txt
└─ ...
特点
- 不会被 Vite 处理
- 打包时 原样复制 到
dist/ - 通过
/xxx直接访问
适合放什么
✅ favicon
✅ robots.txt
❌ 不建议放业务图片(无法 hash)
2️⃣ .env*(环境变量)
text
.env
.env.development
.env.production
- 必须
VITE_开头才能在前端使用 - 常见内容:
env
VITE_APP_TITLE=若依后台管理系统
VITE_APP_ENV=development
VITE_APP_BASE_API=/dev-api
3️⃣ index.html
- Vite 入口文件
- 不是 Vue 组件
- 挂载点:
html
<div id="app"></div>
4️⃣ vite.config.js
- Vite 核心配置
- proxy / alias / build 都在这
- 你前面贴的那份就是标准 ruoyi 写法
二、src/ 目录(核心)
text
src/
├─ api/
├─ assets/
├─ components/
├─ directive/
├─ layout/
├─ router/
├─ store/
├─ utils/
├─ views/
├─ App.vue
├─ main.js
└─ settings.js
三、核心启动链路(必须懂)
1️⃣ main.js(程序入口)
ts
createApp(App)
.use(router)
.use(pinia)
.mount('#app')
作用:
- 初始化 Vue
- 注册插件
- 启动整个应用
2️⃣ App.vue(根组件)
- 整个系统的最外层
- 通常只包含:
vue
<router-view />
四、业务核心目录详解
1️⃣ api/ ------ 后端接口封装
text
api/
├─ login.js
├─ system/
│ ├─ user.js
│ ├─ role.js
│ └─ menu.js
特点:
- 一个文件 = 一类接口
- 只做请求,不处理 UI
- 全部走
utils/request.js
2️⃣ router/ ------ 路由系统(非常重要)
text
router/
├─ index.js // 路由实例
├─ routes.js // 静态路由
└─ permission.js // 路由守卫
你刚才贴的代码 👉 就在这里
职责划分:
routes.js:固定页面(登录 / 404)permission.js:登录鉴权、动态路由
3️⃣ store/ ------ Pinia 状态管理
text
store/
├─ modules/
│ ├─ user.js
│ ├─ permission.js
│ └─ settings.js
└─ index.js
各模块职责
| 模块 | 作用 |
|---|---|
| user | token / 用户信息 / roles |
| permission | 动态路由生成 |
| settings | 主题 / 布局 |
👉 ruoyi 强制按模块拆 store
4️⃣ layout/ ------ 页面骨架(后台核心)
text
layout/
├─ index.vue
├─ components/
│ ├─ Sidebar/
│ ├─ Navbar/
│ ├─ TagsView/
│ └─ AppMain.vue
职责
- 左侧菜单
- 顶部导航
- 标签页
- 主内容区
👉 几乎所有业务页面都被包在 layout 里
5️⃣ views/ ------ 页面级组件
text
views/
├─ login/
│ └─ index.vue
├─ dashboard/
│ └─ index.vue
├─ system/
│ ├─ user/
│ ├─ role/
│ └─ menu/
规则:
- 一个路由 = 一个目录
- 只处理页面和交互
- 不直接发请求(走 api)
6️⃣ components/ ------ 公共组件
text
components/
├─ SvgIcon/
├─ Pagination/
├─ DictTag/
特点:
- 高复用
- 无业务耦合
- 可全局注册
7️⃣ utils/ ------ 工具函数
text
utils/
├─ request.js // axios 封装(核心)
├─ auth.js // token 处理
├─ validate.js // 校验工具
├─ dynamicTitle.js
你之前贴的:
getTokenisHttpisPathMatch
👉 都在这里
8️⃣ directive/ ------ 自定义指令
text
directive/
├─ permission.js
└─ index.js
典型用法:
html
<button v-hasPermi="['system:user:add']">
9️⃣ assets/ ------ 需要打包的静态资源
text
assets/
├─ images/
├─ styles/
│ ├─ index.scss
│ └─ variables.scss
与 public/ 的区别:
- 会被 Vite 处理
- 会加 hash
- 推荐放业务资源
🔟 settings.js ------ 系统默认配置
ts
export default {
title: 'RuoYi',
sideTheme: 'dark',
tagsView: true
}
👉 对应你刚才讲的 useSettingsStore
五、你现在这个项目的「整体架构思想」
一句话总结:
前端完全围绕「权限 + 动态路由 + 后台布局」设计
核心三件事:
- 登录态控制
- 后端菜单驱动前端路由
- layout 统一壳 + views 业务页
最后给你一个「记忆口诀」
api 管请求
views 管页面
layout 管框架
store 管状态
router 管权限
utils 管工具
如果你下一步想深入:
- 🔥 动态路由是怎么从菜单变成页面的
- 🧠 permissionStore.generateRoutes 的源码逻辑
- 🧹 精简 ruoyi 目录结构(适合小项目)
直接说你想「拆哪一块」,我给你画流程图级别的解释。