VJSP Vue3 Framework 主文档
项目概述
VJSP Vue3 Framework 是一个基于 Vue 3.5 + TypeScript 5.7 + Element Plus 的企业级中后台前端解决方案。框架提供了一套完整的开发工具和组件库,帮助开发者快速构建现代化的 Web 应用。
技术栈架构
基于项目的实际配置,框架采用以下核心技术栈:
- 前端框架: Vue 3.5.13 + Composition API
- 构建工具: Vite 6.0.7
- 类型系统: TypeScript 5.7.3
- UI 组件库: Element Plus 2.11.7
- 状态管理: Pinia 3.0.0 + 持久化插件
- 路由管理: Vue Router 4.5.0
- 国际化: Vue I18n 11.0.1
- HTTP 客户端: Axios 1.12.0
项目结构
项目采用模块化架构设计,主要目录结构如下:
src/
├── api/ # API 接口层
│ ├── login/ # 登录相关接口
│ ├── user/ # 用户管理接口
│ └── system/ # 系统管理接口
├── components/ # 组件层
│ ├── SvgIcon/ # SVG 图标组件
│ └── dict/ # 字典组件
├── stores/ # 状态管理
│ ├── app.ts # 应用状态
│ ├── user.ts # 用户状态
│ └── modules/ # 模块化状态
├── utils/ # 工具函数
│ ├── cache.ts # 缓存管理
│ ├── encryption.ts # 加密工具
│ └── tree.ts # 树形数据处理
├── views/ # 页面组件
│ ├── system/ # 系统管理页面
│ └── dashboard/ # 仪表板页面
└── main.ts # 应用入口核心功能机制
1. 应用启动机制
框架采用异步启动机制,确保所有依赖正确初始化:
// src/main.ts 中的启动流程
async function bootstrap() {
const app = createApp(App)
// 1. 注册 Element Plus 图标
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
// 2. 初始化 Pinia 状态管理
app.use(createPinia())
// 3. 初始化国际化
await setupI18n(app)
// 4. 配置 Element Plus
app.use(ElementPlus, {
locale: currentLocale.elLocale,
})
// 5. 设置路由(等待动态路由加载)
await setupRouter(app)
app.mount('#app')
}2. 权限管理机制
框架实现基于角色的权限控制系统:
- 菜单权限: 动态路由过滤,只显示有权限的菜单
- 按钮权限: 通过自定义指令控制按钮显示
- 数据权限: 基于用户角色过滤数据访问范围
权限验证通过路由守卫和自定义指令实现:
// 路由守卫权限检查
router.beforeEach(async (to, from, next) => {
// 检查用户登录状态
if (to.meta.requiresAuth && !isAuthenticated()) {
next('/login')
return
}
// 检查路由权限
if (to.meta.permission && !hasPermission(to.meta.permission)) {
next('/403')
return
}
next()
})3. 国际化机制
框架支持多语言切换,基于 vue-i18n 实现:
- 语言包管理: 按模块组织语言包文件
- 动态切换: 支持运行时语言切换
- 组件集成: Element Plus 组件自动适配当前语言
语言配置通过独立的插件模块管理:
// src/plugins/vueI18n 中的配置
export async function setupI18n(app: App) {
const options = await createI18nOptions()
const i18n = createI18n(options)
app.use(i18n)
}4. 状态管理机制
采用 Pinia 进行状态管理,支持模块化组织和持久化:
- 模块化设计: 按功能模块划分 Store
- 类型安全: 完整的 TypeScript 类型支持
- 持久化: 关键状态自动持久化到本地存储
状态持久化通过 pinia-plugin-persistedstate 实现:
// Store 配置示例
const useUserStore = defineStore('user', {
state: () => ({
token: '',
userInfo: {},
permissions: [],
}),
persist: {
key: 'user-store',
storage: localStorage,
},
})5. 构建优化机制
Vite 构建工具提供以下优化机制:
- 依赖预构建: 第三方依赖预构建提升加载速度
- 代码分割: 自动分割 vendor 包和业务代码
- Tree Shaking: 自动移除未使用的代码
- 压缩优化: 生产环境自动启用压缩
构建配置通过 vite.config.ts 文件管理:
// 构建优化配置
export default defineConfig({
build: {
// 代码分割配置
rollupOptions: {
output: {
manualChunks: {
vue: ['vue'],
'element-plus': ['element-plus'],
},
},
},
},
})Product 模块开发示例
1. 创建 Product 模块结构
假设开发 Product 模块,按照项目统一规范创建目录结构:
src/
├── api/ # API 接口层(统一管理)
│ └── product/ # Product 相关接口
│ └── index.ts # Product API 服务
├── types/ # 类型定义(统一管理)
│ └── api/ # API 相关类型
│ └── product.ts # Product 相关类型定义
├── locales/ # 国际化文案
│ └── module/ # 模块文案
│ └── product/ # Product 模块文案
│ └── zh-CN.ts
└── views/modules/product/ # Product 页面组件
├── components/ # Product 相关组件(如有需要)
│ ├── ProductForm.vue # 产品表单组件
│ └── ProductTable.vue # 产品表格组件
└── index.vue # 产品管理主页面2. 定义 Product 类型
在统一类型定义目录中创建产品相关的 TypeScript 类型定义:
// src/types/api/product.ts
export interface Product {
id: number
name: string
price: number
description: string
category: string
status: 'active' | 'inactive'
createdAt: string
updatedAt: string
}
export interface ProductForm {
name: string
price: number
description?: string
category: string
}
export interface ProductFilters {
category?: string
status?: string
search?: string
page: number
pageSize: number
}
export interface ProductListResponse {
list: Product[]
total: number
}3. 实现 Product API 服务
在统一API目录中封装产品相关的 API 接口:
// src/api/product/index.ts
import request from '@/axios'
import type { Product, ProductForm, ProductFilters, ProductListResponse } from '@/types/api/product'
export class ProductApiService {
// 获取产品列表
static async getProducts(params: ProductFilters) {
return request.get<ProductListResponse>({
url: '/api/products',
params,
})
}
// 获取产品详情
static async getProduct(id: number) {
return request.get<Product>({
url: `/api/products/${id}`,
})
}
// 创建产品
static async createProduct(data: ProductForm) {
return request.post<Product>({
url: '/api/products',
data,
})
}
// 更新产品
static async updateProduct(id: number, data: ProductForm) {
return request.put<Product>({
url: `/api/products/${id}`,
data,
})
}
// 删除产品
static async deleteProduct(id: number) {
return request.delete({
url: `/api/products/${id}`,
})
}
}
export default ProductApiService4. 创建 Product 国际化文案
在统一国际化目录中创建产品模块的文案:
// src/locales/module/product/zh-CN.ts
export default {
product: {
title: '产品管理',
list: '产品列表',
name: '产品名称',
category: '产品分类',
price: '价格',
status: '状态',
createdAt: '创建时间',
operation: '操作',
search: '查询',
reset: '重置',
add: '新增产品',
edit: '编辑',
delete: '删除',
export: '导出数据',
placeholder: {
name: '请输入产品名称',
category: '请选择分类',
},
statusText: {
active: '激活',
inactive: '停用',
},
message: {
loadFailed: '获取产品列表失败',
deleteSuccess: '删除成功',
deleteFailed: '删除失败',
exportSuccess: '导出功能开发中',
exportFailed: '导出失败',
confirmDelete: '确定要删除产品"{name}"吗?此操作不可恢复。',
},
categories: {
electronics: '电子产品',
home: '家居用品',
clothing: '服装服饰',
food: '食品饮料',
},
},
}5. 创建 Product 管理页面
实现产品管理的主页面,采用响应式设计,支持桌面端和移动端,集成国际化、权限控制和数据管理功能:
页面结构
产品管理页面采用卡片式布局,包含以下主要区域:
- 筛选条件区域 - 支持产品名称、产品编码、分类、状态等条件筛选
- 数据展示区域 - 桌面端表格视图和移动端卡片视图
- 操作按钮区域 - 新增、批量删除、导出等功能
- 表单对话框 - 产品新增/编辑表单
- 导出对话框 - 数据导出配置
样式已集成src\styles\components\tables.less,如无特殊需求,无需额外配置
核心功能特性
- 响应式设计:自动适配桌面端和移动端显示
- 国际化支持:使用
t('product.xxx')语法调用多语言文案 - 权限控制:通过
v-permission指令控制按钮显示 - 数据管理:支持分页、筛选、排序、状态切换
- 批量操作:支持批量删除和导出
- 表单验证:完整的表单验证规则
主要组件结构
<template>
<div class="product-container query-container">
<!-- 筛选条件区域 -->
<el-card class="filter-container">
<!-- 移动端展开收起功能 -->
<template #header v-if="isMobile">
<div class="filter-header">
<span>{{ t('common.filter') }}</span>
<el-button @click="filterExpanded = !filterExpanded">
{{ filterExpanded ? t('common.collapse') : t('common.expand') }}
</el-button>
</div>
</template>
<!-- 筛选表单 -->
<el-form :inline="!isMobile" :model="queryParams">
<el-row>
<el-col :xs="24" :sm="12" :md="8" :lg="8">
<el-form-item :label="t('product.productName')">
<el-input v-model="queryParams.productName" />
</el-form-item>
</el-col>
<!-- 其他筛选条件 -->
</el-row>
</el-form>
</el-card>
<!-- 数据展示区域 -->
<el-card class="table-container">
<template #header>
<div class="card-header">
<span v-if="!isMobile">{{ t('product.list') }}</span>
<div class="header-actions">
<el-button type="primary" @click="handleAdd">
{{ t('common.add') }}
</el-button>
<!-- 其他操作按钮 -->
</div>
</div>
</template>
<!-- 桌面端表格视图 -->
<div v-if="!isMobile" class="desktop-view">
<el-table :data="productList" v-loading="loading">
<!-- 表格列定义 -->
</el-table>
</div>
<!-- 移动端卡片视图 -->
<div v-else class="mobile-view">
<div v-loading="loading" class="mobile-cards-container">
<!-- 卡片列表 -->
</div>
</div>
<!-- 分页和加载提示 -->
</el-card>
<!-- 导出对话框 -->
<el-dialog :title="t('product.exportTitle')" v-model="exportVisible">
<!-- 导出配置表单 -->
</el-dialog>
<!-- 产品编辑对话框 -->
<el-dialog :title="dialog.title" v-model="dialog.visible">
<!-- 产品表单 -->
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted, computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { ElMessage, ElMessageBox } from 'element-plus'
import ProductFormDialog from './components/ProductFormDialog.vue'
import ProductApiService from '@/api/product'
import type { Product, ProductFilters } from '@/types/api/product'
const { t } = useI18n()
// 响应式数据
const loading = ref(false)
const productList = ref<Product[]>([])
// 搜索表单
const searchForm = reactive({
name: '',
category: '',
})
// 分页配置
const pagination = reactive({
current: 1,
size: 10,
total: 0,
})
// 表单对话框配置
const formDialog = reactive({
visible: false,
data: null as Product | null,
mode: 'add' as 'add' | 'edit',
})
// 产品分类选项(基于国际化文案)
const categories = computed(() => {
return Object.entries(t('product.categories', {}, { returnObjects: true })).map(
([value, label]) => ({
value,
label,
})
)
})
// 加载产品列表
const loadProductList = async () => {
loading.value = true
try {
const params: ProductFilters = {
...searchForm,
page: pagination.current,
pageSize: pagination.size,
}
const response = await ProductApiService.getProducts(params)
productList.value = response.data.list
pagination.total = response.data.total
} catch (error) {
ElMessage.error(t('product.message.loadFailed'))
console.error('加载产品列表错误:', error)
} finally {
loading.value = false
}
}
// 搜索处理
const handleSearch = () => {
pagination.current = 1
loadProductList()
}
// 重置搜索
const handleReset = () => {
Object.assign(searchForm, { name: '', category: '' })
handleSearch()
}
// 分页处理
const handleSizeChange = (size: number) => {
pagination.size = size
pagination.current = 1
loadProductList()
}
const handleCurrentChange = (current: number) => {
pagination.current = current
loadProductList()
}
// 新增产品
const handleAdd = () => {
formDialog.mode = 'add'
formDialog.data = null
formDialog.visible = true
}
// 编辑产品
const handleEdit = (product: Product) => {
formDialog.mode = 'edit'
formDialog.data = product
formDialog.visible = true
}
// 删除产品
const handleDelete = async (product: Product) => {
try {
await ElMessageBox.confirm(
t('product.message.confirmDelete', { name: product.name }),
t('product.delete'),
{
type: 'warning',
confirmButtonText: t('common.confirm'),
cancelButtonText: t('common.cancel'),
}
)
await ProductApiService.deleteProduct(product.id)
ElMessage.success(t('product.message.deleteSuccess'))
loadProductList()
} catch (error) {
if (error !== 'cancel') {
ElMessage.error(t('product.message.deleteFailed'))
console.error('删除产品错误:', error)
}
}
}
// 导出数据
const handleExport = async () => {
try {
// 实现导出逻辑
ElMessage.success(t('product.message.exportSuccess'))
} catch (error) {
ElMessage.error(t('product.message.exportFailed'))
console.error('导出产品数据错误:', error)
}
}
// 表单提交成功处理
const handleFormSuccess = () => {
formDialog.visible = false
loadProductList()
}
// 页面加载时初始化数据
onMounted(() => {
loadProductList()
})
</script>6. 配置 Product 模块路由
在路由配置中添加产品管理模块:
前端控制模式
// src/router/modules/product.ts
import type { RouteRecordRaw } from 'vue-router'
const productRoutes: RouteRecordRaw[] = [
{
path: '/product',
name: 'Product',
component: () => import('@/views/modules/product/index.vue'),
meta: {
title: 'product.title', // 使用国际化key
icon: 'shopping-bag',
requiresAuth: true,
permissions: ['product:view'],
},
children: [
{
path: 'list',
name: 'ProductList',
component: () => import('@/views/modules/product/index.vue'),
meta: {
title: 'product.list', // 使用国际化key
requiresAuth: true,
permissions: ['product:view'],
},
},
],
},
]
export default productRoutes然后在主路由文件中导入:
// src/router/index.ts
import { createRouter, createWebHistory } from 'vue-router'
import productRoutes from './modules/product'
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
// ... 其他路由
...productRoutes,
// ... 更多路由
],
})
export default router后端控制模式
在预制的系统管理-菜单管理下配置产品模块的路由,包括列表、新增、编辑、删除等操作。
框架核心优势
1. 开发效率提升
- 组件化开发: 基于 Element Plus 组件库,提供丰富的 UI 组件
- 类型安全: 完整的 TypeScript 支持,减少运行时错误
- 热重载: Vite 开发服务器支持实时预览
- 代码规范: ESLint + Prettier 确保代码质量
2. 性能优化
- 构建优化: Vite 提供快速的冷启动和热更新
- 代码分割: 自动分割 vendor 包,优化加载性能
- 缓存策略: 多级缓存机制提升应用响应速度
- 懒加载: 路由和组件懒加载减少初始包大小
3. 企业级功能
- 权限管理: 完整的 RBAC 权限控制系统
- 国际化: 多语言支持,适应全球化需求
- 数据字典: 统一的数据管理机制
- 错误处理: 完善的错误捕获和处理机制
4. 可维护性
- 模块化架构: 清晰的目录结构和模块划分
- 类型定义: 完整的接口和类型定义
- 文档完善: 详细的开发文档和示例
- 工具集成: 与开发工具深度集成
总结
VJSP Vue3 Framework 提供了一个完整的企业级前端解决方案,基于现代化的技术栈和最佳实践。框架的核心优势在于其完善的权限管理、国际化支持、性能优化和开发效率提升。通过 Product 模块的开发示例,展示了如何在框架基础上快速构建业务功能模块。
框架的设计理念是"约定优于配置",通过合理的默认配置和模块化设计,降低开发复杂度,提升开发效率。同时,框架保持了良好的扩展性,可以根据具体业务需求进行定制和扩展。
