前端开发概述
作者:唐亚峰 | battcn
字数统计:1.7k 字
学习目标
掌握 Wemirr Platform 前端项目结构、开发规范和核心功能
技术栈
| 技术 | 版本 | 说明 |
|---|---|---|
| Vue | 3.x | 渐进式 JavaScript 框架 |
| Vben Admin | 5.x | 企业级中后台前端模板 |
| Fast Crud | 1.x | 快速 CRUD 开发组件 |
| TypeScript | 5.x | JavaScript 超集,提供类型系统 |
| Ant Design Vue | 4.x | 企业级 UI 组件库 |
| Vite | 5.x | 下一代前端构建工具 |
| Pinia | 最新版 | Vue 3 状态管理 |
| Vue Router | 4.x | Vue 官方路由 |
| Axios | 最新版 | HTTP 请求库 |
核心框架介绍
Vben Admin 5.x
https://doc.vben.pro/
核心特性:
- Monorepo 架构 — 基于 pnpm workspace + Turbo,支持多应用共享代码
- 多 UI 组件库 — 支持 Ant Design Vue、Element Plus、Naive UI 等
- 权限系统 — 完善的前端权限控制(路由/按钮/数据)
- 主题定制 — 支持暗黑模式、多主题色、布局切换
- 国际化 — 内置 i18n 多语言支持
- 性能优化 — 按需加载、代码分割、预渲染
官方文档
📖 Vben5 文档:https://doc.vben.pro/
🔗 GitHub:https://github.com/vbenjs/vue-vben-admin
Fast Crud
https://fast-crud.docmirror.cn/
核心特性:
- 配置式开发 — 通过 JSON 配置快速生成完整的 CRUD 页面
- 零代码表格 — 自动生成列表、搜索、分页
- 表单联动 — 支持字段联动、异步字典、级联选择
- 多 UI 支持 — 适配 Ant Design Vue、Element Plus、Naive UI
- 可扩展 — 支持自定义组件、插槽、事件
官方文档
📖 Fast Crud 文档:https://fast-crud.docmirror.cn/
🔗 GitHub:https://github.com/fast-crud/fast-crud
Fast Crud 基础示例:
typescript
import { defineTableCrud } from '@/plugin/fast-crud';
export default defineTableCrud({
// 请求配置
request: {
pageRequest: async (query) => await api.getList(query),
addRequest: async (data) => await api.create(data),
editRequest: async (data) => await api.update(data.id, data),
delRequest: async (data) => await api.delete(data.id),
},
// 列配置
columns: {
username: {
title: '用户名',
type: 'text',
search: { show: true },
form: { rules: [{ required: true, message: '请输入用户名' }] },
},
status: {
title: '状态',
type: 'dict-select',
dict: dict({ url: '/dict/user_status' }),
search: { show: true },
},
createTime: {
title: '创建时间',
type: 'datetime',
column: { width: 180 },
form: { show: false },
},
},
});开发效率对比:
| 功能 | 传统开发 | Fast Crud |
|---|---|---|
| 列表页 | 50+ 行代码 | 10 行配置 |
| 搜索栏 | 手写表单 | 自动生成 |
| 新增/编辑表单 | 手写弹窗 | 自动生成 |
| 字典数据 | 手动请求 | type: 'dict-select' |
| 分页 | 手动处理 | 自动集成 |
项目结构
项目采用 Monorepo 架构,基于 Vben Admin 5.x 构建:
wemirr-platform-ui/
├── apps/ # 📱 应用目录
│ └── web-antd/ # Ant Design Vue 版本
│ ├── src/
│ │ ├── api/ # 🌐 API 接口
│ │ │ ├── core/ # 核心接口
│ │ │ ├── system/ # 系统接口
│ │ │ └── workflow/ # 工作流接口
│ │ ├── views/ # 📄 页面视图
│ │ │ ├── _core/ # 核心页面(登录等)
│ │ │ ├── dashboard/ # 仪表盘
│ │ │ └── wemirr/ # 业务页面
│ │ │ ├── system/ # 系统管理
│ │ │ ├── platform/ # 平台管理
│ │ │ ├── develop/ # 开发工具
│ │ │ ├── workflow/ # 工作流
│ │ │ ├── ai/ # AI 功能
│ │ │ ├── tms/ # 运输管理
│ │ │ └── wms/ # 仓储管理
│ │ ├── adapter/ # 适配器
│ │ ├── components/ # 业务组件
│ │ ├── layouts/ # 布局组件
│ │ ├── locales/ # 国际化
│ │ ├── plugin/ # 插件
│ │ ├── router/ # 路由配置
│ │ ├── store/ # 状态管理
│ │ └── utils/ # 工具函数
│ ├── .env.development # 开发环境配置
│ ├── .env.production # 生产环境配置
│ └── vite.config.mts # Vite 配置
│
├── packages/ # 📦 共享包
│ ├── @core/ # 核心包
│ ├── constants/ # 常量定义
│ ├── effects/ # 副作用
│ ├── hooks/ # 组合式函数
│ ├── icons/ # 图标
│ ├── locales/ # 国际化
│ ├── preferences/ # 偏好设置
│ ├── stores/ # 状态管理
│ ├── styles/ # 样式
│ ├── types/ # 类型定义
│ └── utils/ # 工具函数
│
├── internal/ # 🔧 内部工具
├── scripts/ # 脚本
├── pnpm-workspace.yaml # Monorepo 配置
├── turbo.json # Turbo 配置
└── package.json # 依赖管理开发环境
环境要求
- Node.js >= 18.0
- pnpm >= 8.0
- Git >= 2.0
安装步骤
bash
# 1. 克隆代码
git clone https://gitee.com/battcn/wemirr-platform-ui.git
# 2. 进入目录
cd wemirr-platform-ui
# 3. 安装 pnpm(如果没有)
npm install -g pnpm
# 4. 安装依赖
pnpm install
# 5. 启动开发服务器
pnpm run dev:antd常用命令
| 命令 | 说明 |
|---|---|
pnpm dev:antd | 启动 Ant Design Vue 版本开发服务器 |
pnpm build:antd | 打包 Ant Design Vue 版本 |
pnpm lint | 运行 ESLint 检查 |
pnpm lint:fix | 自动修复 ESLint 问题 |
pnpm type:check | TypeScript 类型检查 |
pnpm clean | 清理构建产物和依赖 |
配置说明
环境变量
项目支持多环境配置,位于 apps/web-antd/ 目录:
bash
.env # 所有环境通用配置
.env.development # 开发环境配置
.env.production # 生产环境配置常用环境变量:
bash
# .env.development
# API 基础路径
VITE_GLOB_API_URL=/api
# 是否开启 Mock
VITE_USE_MOCK=false
# Gitee 授权拦截(开发时关闭)
VITE_GITEE_INTERCEPT=false代理配置
开发环境 API 代理配置在 vite.config.ts:
typescript
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:9000', // 后端网关地址
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
},
},
});核心功能
路由与菜单
路由配置分为两种:
- 静态路由 - 不需要权限的基础路由(登录、404等)
- 动态路由 - 根据用户权限从后端获取
typescript
// 静态路由示例
const staticRoutes = [
{
path: '/login',
name: 'Login',
component: () => import('@/views/login/index.vue'),
meta: { title: '登录' },
},
];权限控制
前端权限控制包括:
- 路由权限 - 控制页面访问
- 按钮权限 - 控制操作按钮显示
- 数据权限 - 配合后端控制数据范围
vue
<!-- 按钮权限示例 -->
<template>
<a-button v-auth="'user:add'">新增用户</a-button>
<a-button v-auth="'user:edit'">编辑</a-button>
<a-button v-auth="'user:delete'">删除</a-button>
</template>状态管理
使用 Pinia 进行状态管理:
typescript
// stores/modules/user.ts
import { defineStore } from 'pinia';
export const useUserStore = defineStore('user', {
state: () => ({
userInfo: null,
token: '',
}),
getters: {
getUserInfo: (state) => state.userInfo,
},
actions: {
async login(params) {
// 登录逻辑
},
async logout() {
// 登出逻辑
},
},
});请求封装
HTTP 请求使用 Axios 封装:
typescript
// api/user.ts
import { request } from '@/utils/request';
// 获取用户列表
export function getUserList(params: UserListParams) {
return request.get<UserListResult>('/iam/users', { params });
}
// 创建用户
export function createUser(data: CreateUserParams) {
return request.post('/iam/users', data);
}
// 更新用户
export function updateUser(id: number, data: UpdateUserParams) {
return request.put(`/iam/users/${id}`, data);
}
// 删除用户
export function deleteUser(id: number) {
return request.delete(`/iam/users/${id}`);
}开发规范
目录规范
views/
└── wemirr/
└── system/ # 系统管理模块
└── user/ # 用户管理页面
├── index.vue # 页面入口
├── api.ts # 页面 API
├── types.ts # 类型定义
└── components/ # 页面组件
├── UserForm.vue
└── UserDetail.vue命名规范
| 类型 | 规范 | 示例 |
|---|---|---|
| 文件夹 | kebab-case | user-manage |
| Vue 组件 | PascalCase | UserForm.vue |
| 工具函数 | camelCase | formatDate.ts |
| 常量 | UPPER_SNAKE_CASE | MAX_COUNT |
| CSS 类名 | kebab-case | .user-form |
代码规范
vue
<script setup lang="ts">
// 1. 导入语句
import { ref, reactive, onMounted } from 'vue';
import { useUserStore } from '@/store/modules/user';
import type { UserInfo } from './types';
// 2. 类型定义
interface Props {
userId: number;
}
// 3. Props / Emits
const props = defineProps<Props>();
const emit = defineEmits<{
(e: 'success'): void;
}>();
// 4. 响应式数据
const loading = ref(false);
const userInfo = ref<UserInfo | null>(null);
// 5. 计算属性
const fullName = computed(() => {
return `${userInfo.value?.firstName} ${userInfo.value?.lastName}`;
});
// 6. 方法
async function fetchUserInfo() {
loading.value = true;
try {
userInfo.value = await getUserInfo(props.userId);
} finally {
loading.value = false;
}
}
// 7. 生命周期
onMounted(() => {
fetchUserInfo();
});
</script>
<template>
<div class="user-detail">
<a-spin :spinning="loading">
<div v-if="userInfo">
{{ fullName }}
</div>
</a-spin>
</div>
</template>
<style scoped lang="less">
.user-detail {
padding: 16px;
}
</style>