216 lines
7.5 KiB
Markdown
216 lines
7.5 KiB
Markdown
# 前端环境与结构
|
||
|
||
:::tip 说明
|
||
前端基于 Vue3 + ElementPlus 构建,使用 pnpm 作为包管理工具,Vite 作为构建工具,TypeScript 作为开发语言。
|
||
:::
|
||
|
||
## 技术栈
|
||
|
||
| 技术 | 版本 | 说明 |
|
||
|------|------|------|
|
||
| Vue | 3.x | 渐进式 JavaScript 框架,组合式 API |
|
||
| ElementPlus | 2.x | Vue3 组件库 |
|
||
| Vite | 3.x | 下一代前端构建工具 |
|
||
| Pinia | 2.x | 状态管理(Vuex 替代方案) |
|
||
| Vue Router | 4.x | 路由管理 |
|
||
| Axios | 1.x | HTTP 请求库 |
|
||
| TypeScript | 5.x | 类型安全的 JavaScript 超集 |
|
||
| Tailwind CSS | 3.x | 原子化 CSS 框架 |
|
||
| SCSS | - | CSS 预处理器 |
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
ui/
|
||
├── src/
|
||
│ ├── api/ # API 接口定义
|
||
│ │ ├── common/ # 公共接口(login、menu、user)
|
||
│ │ └── system/ # 系统模块接口(position、user、role 等)
|
||
│ ├── assets/ # 静态资源(图片、字体等)
|
||
│ ├── components/ # 公共组件(Table、Form、Modal 等)
|
||
│ ├── directives/ # 自定义指令(v-perm 权限指令)
|
||
│ ├── hooks/ # 组合式函数
|
||
│ │ ├── event/ # 事件相关(useWindowSizeFn、useBreakpoint)
|
||
│ │ ├── setting/ # 配置相关(useProjectSetting、useDesignSetting)
|
||
│ │ └── web/ # Web 相关(usePermission、useECharts)
|
||
│ ├── layout/ # 布局组件
|
||
│ ├── router/ # 路由配置(generator-routers、router-guards)
|
||
│ ├── store/ # Pinia 状态管理
|
||
│ │ └── modules/ # Store 模块(user、asyncRoute、projectSetting 等)
|
||
│ ├── styles/ # 全局样式(SCSS 变量、Tailwind)
|
||
│ ├── utils/ # 工具函数(http、auth、Storage、dateUtil)
|
||
│ │ └── http/axios/ # Axios 封装(VAxios 类、拦截器、取消请求)
|
||
│ └── views/ # 页面视图
|
||
│ └── system/ # 系统管理页面(position、user、role 等)
|
||
├── build/ # 构建配置(vite 插件、常量、工具函数)
|
||
├── public/ # 公共静态资源
|
||
├── vite.config.ts # Vite 配置
|
||
├── tsconfig.json # TypeScript 配置
|
||
└── package.json # 依赖配置
|
||
```
|
||
|
||
## 启动开发
|
||
|
||
```bash
|
||
# 安装依赖
|
||
pnpm install
|
||
|
||
# 启动开发服务器(默认端口 8001)
|
||
pnpm dev
|
||
|
||
# 构建生产版本
|
||
pnpm build
|
||
```
|
||
|
||
## Vite 配置
|
||
|
||
`vite.config.ts` 是 Vite 的核心配置文件,实际配置如下:
|
||
|
||
```typescript
|
||
import type { UserConfig, ConfigEnv } from 'vite';
|
||
import { loadEnv } from 'vite';
|
||
import { resolve } from 'path';
|
||
import { wrapperEnv } from './build/utils';
|
||
import { createVitePlugins } from './build/vite/plugin';
|
||
import { OUTPUT_DIR } from './build/constant';
|
||
import { createProxy } from './build/vite/proxy';
|
||
|
||
export default ({ command, mode }: ConfigEnv): UserConfig => {
|
||
const root = process.cwd();
|
||
const env = loadEnv(mode, root);
|
||
const viteEnv = wrapperEnv(env);
|
||
const { VITE_PUBLIC_PATH, VITE_PORT, VITE_GLOB_PROD_MOCK } = viteEnv;
|
||
|
||
let VITE_PROXY: any = viteEnv.VITE_PROXY;
|
||
// VITE_PROXY 容错处理
|
||
if (!VITE_PROXY) {
|
||
VITE_PROXY = '[[]]';
|
||
}
|
||
try {
|
||
if (typeof VITE_PROXY === 'string') {
|
||
VITE_PROXY = JSON.parse(VITE_PROXY);
|
||
}
|
||
} catch (e) {
|
||
VITE_PROXY = [[]];
|
||
}
|
||
|
||
const isBuild = command === 'build';
|
||
|
||
return {
|
||
base: VITE_PUBLIC_PATH,
|
||
resolve: {
|
||
alias: [
|
||
{ find: '@', replacement: pathResolve('src') + '/' },
|
||
],
|
||
dedupe: ['vue'],
|
||
},
|
||
plugins: createVitePlugins(viteEnv, isBuild, prodMock),
|
||
css: {
|
||
preprocessorOptions: {
|
||
scss: {
|
||
additionalData: `@import "src/styles/var.scss";`,
|
||
},
|
||
},
|
||
},
|
||
server: {
|
||
host: true,
|
||
port: VITE_PORT,
|
||
proxy: createProxy(VITE_PROXY),
|
||
},
|
||
build: {
|
||
target: 'es2015',
|
||
outDir: OUTPUT_DIR,
|
||
reportCompressedSize: false,
|
||
chunkSizeWarningLimit: 2000,
|
||
},
|
||
};
|
||
};
|
||
```
|
||
|
||
关键配置说明:
|
||
|
||
- `@` 别名指向 `src/` 目录,代码中可用 `@/api/system/position` 引入模块
|
||
- SCSS 全局变量通过 `additionalData` 注入,无需每个文件手动 `@import`
|
||
- 代理配置通过 `VITE_PROXY` 环境变量传入,由 `createProxy()` 工具函数解析
|
||
- 构建产物输出到 `OUTPUT_DIR`(默认 `dist/`)
|
||
|
||
## 应用入口
|
||
|
||
`src/main.ts` 是应用入口,负责初始化所有基础设施:
|
||
|
||
```typescript
|
||
import './styles/tailwindbase.css';
|
||
import 'element-plus/dist/index.css';
|
||
import './styles/index.scss';
|
||
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
|
||
import { createApp } from 'vue';
|
||
import App from './App.vue';
|
||
import router, { setupRouter } from './router';
|
||
import { setupStore } from '@/store';
|
||
import { setupElement, setupDirectives, setupCustomComponents } from '@/plugins';
|
||
|
||
async function bootstrap() {
|
||
const app = createApp(App);
|
||
|
||
// 注册所有 ElementPlus 图标
|
||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||
app.component(key, component);
|
||
}
|
||
|
||
setupElement(app); // 全局引入 ElementPlus 组件
|
||
setupCustomComponents(app); // 注册自定义组件
|
||
setupDirectives(app); // 注册自定义指令(v-perm 等)
|
||
setupStore(app); // 挂载 Pinia 状态管理
|
||
await setupRouter(app); // 挂载路由
|
||
await router.isReady(); // 路由准备就绪
|
||
|
||
app.mount('#app', true);
|
||
}
|
||
|
||
void bootstrap();
|
||
```
|
||
|
||
初始化顺序:样式加载 -> ElementPlus -> 自定义组件 -> 自定义指令 -> Pinia Store -> Router -> 挂载。
|
||
|
||
## 核心目录说明
|
||
|
||
### api/
|
||
|
||
API 接口定义目录,按模块组织文件。公共接口在 `api/common/`(login、menu、user),业务接口在 `api/system/`(position、user、role、dept、level、menu、dictionary 等)。每个文件使用 `http.request()` 发起请求。
|
||
|
||
### components/
|
||
|
||
公共组件目录,基于 ElementPlus 二次封装,包含 `Table`(BasicTable 表格)、`Form`(BasicForm 表单)、`Modal`(BasicModal 弹窗)、`Upload`、`Editor`、`Cropper`、`Select` 等。
|
||
|
||
### directives/
|
||
|
||
自定义指令目录,核心是 `permission.ts` 中的 `v-perm` 和 `v-perms` 指令,用于按钮级别的权限控制。
|
||
|
||
### hooks/
|
||
|
||
组合式函数目录,包括 `usePermission`(权限检查)、`useTime`(实时时钟)、`useAsync`(异步 loading)、`useProjectSetting`(项目配置)、`useDesignSetting`(设计配置)等。
|
||
|
||
### store/
|
||
|
||
Pinia 状态管理目录,核心模块:
|
||
|
||
- `user`:用户登录状态、Token、用户信息、权限列表
|
||
- `asyncRoute`:动态路由生成、菜单管理、组件缓存
|
||
- `projectSetting`:项目配置(权限模式、水印等)
|
||
- `designSetting`:主题色、深色模式
|
||
- `lockscreen`:锁屏状态
|
||
- `tabsView`:标签页管理
|
||
|
||
### utils/
|
||
|
||
工具函数目录:
|
||
|
||
- `http/axios/`:Axios 封装(VAxios 类、请求/响应拦截器、取消重复请求、状态码处理)
|
||
- `auth.ts`:认证工具(token 管理、树结构操作、文件下载)
|
||
- `Storage.ts`:本地存储封装(支持过期时间、cookie)
|
||
- `dateUtil.ts`:日期格式化(基于 dayjs)
|
||
|
||
## 总结
|
||
|
||
前端项目基于 Vue3 + ElementPlus + Vite + TypeScript + Pinia 构建,使用 pnpm 管理依赖,Tailwind CSS + SCSS 提供样式能力。通过 `main.ts` 的 `bootstrap()` 函数按顺序初始化所有基础设施,目录结构按功能分层组织,便于维护和扩展。
|