YLSG新框架
项目概述
框架简介与背景
YLSG后台管理系统是基于Avue 3.0框架的二次开发版本,旨在解决传统后台管理系统开发中的痛点问题。这个框架就像是一个"代码充电宝",为开发者提供了强大的CRUD功能和灵活的配置系统。
背景故事
一晃用老框架已经5年了,五年之痒也是时候换个新欢了!毕竟,和老框架的"甜蜜期"早过了 现在它动不动就给我们脸色看:运行像老牛拉破车、打开速度堪比树懒、依赖动不动玩失踪️、富文本加载看心情、表格排版自由奔放、菜单权限随心所欲...最要命的是,安全问题就像个定时炸弹!早就想换个新欢,但一直没想好理想型该长啥样 —— 简单好上手、效率爆表、能屈能伸、加密传参要稳、权限管理得像乐高一样灵活拼装
这次终于遇到真爱了!我用AVUE3 CLI打底,经过我的深度美颜 基本把上面的痛点一网打尽!菜单权限和加密传输被我调教得服服帖帖,再用mixins大法把代码量压缩到极致 —— 现在的开发体验,丝滑得像是德芙广告
但最炸裂的还得是可视化生成工具 新建菜单?目录?页面?API?连按钮和权限都能一条龙服务!直接和服务端无缝对接不说,最丧心病狂的是 —— 连自定义事件都能一键生成!规范精准又高效,这感觉简直比连续吃鸡还爽 现在的开发速度,那真的是,咻~...
核心优势与特性
开发效率优势
页面生成器
- 一键生成:新建页面时菜单、按钮、权限一并生成
- 可视化操作:通过可视化界面配置页面信息
- 模板驱动:基于模板系统,确保代码一致性
CRUD混入模块
- 代码复用:通过混入机制,大幅减少重复代码
- 配置驱动:页面基本只需修改option配置文件,主要调整column配置
- 权限集成:自动集成权限控制,无需手动处理
系统架构设计
技术栈架构图
YLSG后台管理系统采用了现代化的前端技术栈,就像搭建一座"数字大厦",每一层都有其特定的职责和优势。
技术栈优势分析
Vue 3 + Composition API
- 响应式系统:基于Proxy的响应式系统,性能更优
- 组合式API:更好的逻辑复用和类型推导
- Tree Shaking:更好的打包优化,减少包体积
Element Plus
- 设计一致性:统一的设计语言和交互规范
- 组件丰富:覆盖90%以上的后台管理需求
- 主题定制:支持多主题切换和自定义主题色样式
Vite构建工具
- 极速启动:基于ES模块的快速冷启动
- 热更新:毫秒级的模块热更新
- 按需加载:支持组件的按需加载和代码分割
路由特性
动态路由
- 根据用户权限动态生成路由
- 支持路由懒加载和代码分割
- 路由参数自动解析和验证
️ 权限控制
- 路由级别的权限控制
- 支持路由守卫和导航拦截
- 未授权访问自动重定向
响应式路由
- 支持移动端路由适配
- 路由历史记录管理
- 支持路由参数和查询参数
路由配置示例
// 路由配置结构
const routes = [
{
path: '/login',
component: () => import('@/page/login/login.vue'),
meta: { title: '登录', hidden: true }
},
{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [
{
path: 'dashboard',
component: () => import('@/page/wel/index.vue'),
meta: { title: '首页', icon: 'dashboard' }
}
]
},
{
path: '/user',
component: Layout,
meta: { title: '用户管理', icon: 'user' },
children: [
{
path: 'list',
component: () => import('@/page/user/user.vue'),
meta: { title: '用户列表', permission: 'user:list' }
}
]
}
]
技术栈依赖分析
"dependencies": {
"@element-plus/icons-vue": "^2.3.1", // Element Plus 图标库
"@fortawesome/fontawesome-free": "^6.4.0", // FontAwesome 免费图标库
"@smallwei/avue": "^3.7.0", // 基于Element Plus的CRUD框架
"animate.css": "^4.1.1", // CSS动画库
"avue-plugin-ueditor": "^1.0.4", // Avue集成的UEditor富文本插件
"axios": "^0.21.1", // HTTP客户端
"cnpm": "^9.4.0", // 淘宝NPM镜像客户端
"crypto-js": "^4.1.1", // 加密库
"dayjs": "^1.10.6", // 轻量级日期处理库
"element-plus": "^2.7.3", // Vue 3 UI组件库
"js-cookie": "^3.0.0", // Cookie操作库
"mockjs": "^1.1.0", // 数据模拟库
"nprogress": "^0.2.0", // 页面加载进度条
"vite-plugin-mock": "^2.9.4", // Vite的Mock插件
"vue": "^3.4.27", // 渐进式JavaScript框架
"vue-i18n": "^9.1.9", // 国际化插件
"vue-router": "^4.3.2", // 路由管理器
"vuex": "^4.1.0" // 状态管理模式
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.4", // Vite的Vue 3插件
"@vue/compiler-sfc": "^3.4.27", // Vue单文件组件编译器
"acorn": "^8.15.0", // JavaScript解析器
"acorn-walk": "^8.3.4", // AST遍历工具
"astring": "^1.9.0", // JavaScript代码生成器
"sass": "^1.37.5", // CSS预处理器
"unplugin-auto-import": "^0.11.2", // 自动导入插件
"vite": "^5.2.12", // 前端构建工具
"vite-plugin-compression": "^0.5.1", // 生产环境代码压缩插件
"vite-plugin-vue-setup-extend": "^0.4.0" // Vue setup语法扩展插件
}
目录结构详解
YLSG后台管理系统的目录结构就像一座"数字城市"的规划图,每个区域都有其特定的功能和职责。这种组织方式让代码管理变得井井有条,再也不用在"代码迷宫"里迷路了!️
src/
├── api/ # API接口封装
│ └── baseInterface.js # 基础接口(登录、用户信息等)
├── components/ # 公共组件
│ ├── basic-block/ # 基础块级组件
│ ├── basic-container/ # 基础容器组件
│ ├── basic-video/ # 视频组件
│ ├── error-page/ # 错误页面组件
│ ├── file-manager/ # 文件管理组件
│ ├── iframe/ # 内嵌框架组件
│ ├── loginBase/ # 登录相关组件
│ └── Userinfo/ # 用户信息组件(头像,姓名,手机号)
├── config/ # 系统配置
│ ├── settings.js # 全局系统配置
│ ├── avue_cofig.js # Avue框架配置
│ └── loader.js # 动态加载器配置
├── lang/ # 国际化语言包
│ ├── index.js # 语言配置
│ ├── zh.js # 中文语言包
│ ├── en.js # 英文语言包
│ └── ja.js # 日文语言包
├── mac/ # Mac风格界面
│ └── mode/ # 模式配置
├── mixins/ # 混入模块
│ ├── crud.js # CRUD通用混入
│ └── index.js # 混入入口
├── page/ # 基础框架页面
│ ├── admin_user/ # 管理员用户管理
│ ├── applets_page/ # 小程序页面管理
│ ├── dev/ # 开发工具页面(可视化添加页面cli工具入口)
│ ├── index/ # 首页相关
│ │ ├── sidebar/ # 侧边栏组件
│ │ └── top/ # 顶部组件
│ ├── lock/ # 锁屏页面
│ ├── login/ # 登录页面
│ ├── menu/ # 菜单管理
│ ├── role/ # 角色管理
│ ├── share_img/ # 图片分享管理
│ ├── swiper/ # 轮播图管理
│ ├── sys_settings/ # 系统参数设置(只有超级管理员可见)
│ ├── user/ # 管理员信息管理
│ └── wel/ # 欢迎页面/首页
├── router/ # 路由配置
│ ├── avue-router.js # Avue路由配置
│ ├── index.js # 路由入口
│ ├── page/ # 基础路由
│ └── views/ # 业务路由(增加页面默认存放目录)
├── store/ # 状态管理
│ ├── getters.js # 全局getters
│ ├── index.js # store入口
│ └── modules/ # 模块化状态
│ ├── common.js # 公共状态
│ ├── logs.js # 日志状态
│ ├── tags.js # 标签状态
│ └── user.js # 用户状态
├── styles/ # 样式文件
│ ├── common.scss # 公共样式
│ ├── element-ui.scss # Element UI样式
│ ├── iconfont.scss # 图标字体样式
│ ├── login.scss # 登录页样式
│ ├── media.scss # 媒体查询样式
│ ├── mixin.scss # 样式混入
│ ├── normalize.scss # 样式重置
│ ├── sidebar.scss # 侧边栏样式
│ ├── tags.scss # 标签样式
│ ├── theme/ # 主题样式
│ │ ├── beautiful.scss # 美丽主题
│ │ ├── dark.scss # 暗黑主题
│ │ ├── index.scss # 主题入口
│ │ ├── vip.scss # VIP主题
│ │ └── white.scss # 白色主题
│ ├── top.scss # 顶部样式
│ └── variables.scss # 样式变量
├── template/ # 模板文件
│ └── page/ # 页面模板
│ ├── api_template.js # API模板(未使用)
│ ├── template.js # 配置模板
│ └── template.vue # Vue模板
├── utils/ # 工具函数
│ ├── auth.js # 认证工具
│ ├── captcha.js # 验证码工具
│ ├── fileSaver.js # 文件保存工具
│ ├── store.js # 存储工具
│ ├── util.js # 通用工具
│ ├── validate.js # 验证工具
│ └── xlsx.full.min.js # Excel处理工具
├── views/ # 业务页面
│ ├── article/ # 文章管理
│ ├── goods/ # 商品管理
│ └── util/ # 工具页面
├── App.vue # 根组件
├── axios.js # Axios配置
├── error.js # 错误处理
├── main.js # 应用入口
├── mockProdServer.js # 生产环境Mock服务
└── permission.js # 权限控制
快速开始
环境准备
开发环境要求
基础环境
- Node.js: 版本 >= 16.0.0(推荐使用 LTS 版本)
- 包管理器: npm/yarn/pnpm(推荐使用 pnpm,速度更快)
- 浏览器: Chrome 87+, Firefox 78+, Safari 14+, Edge 88+
开发工具推荐
- IDE: VS Code(推荐安装 Vue 3 插件)
- 调试工具: Vue DevTools
- API测试: Postman 或 Insomnia
项目安装与启动
项目获取
# 克隆项目(请替换为实际的项目地址)
git clone https://gitee.com/ylsg_1/avue3-template.git
cd 后台框架
安装依赖
# 安装依赖(推荐使用 cnpm)
cnpm install
# 或使用 npm
npm install
# 或使用 yarn
yarn install
启动开发服务器
# 启动开发服务器
cnpm dev
# 或
npm run dev
# 或
yarn dev
访问地址
http://localhost:5173
系统配置
全局配置管理
系统参数配置文件
️ 核心配置文件 项目的所有配置都集中在 src/config/settings.js 文件中,就像一个"控制面板",所有开关都在这里!
配置结构全览
// 主要配置项包括:
// - 系统基本信息(标题、描述、关键词)
// - 接口配置(加密开关、超时时间、基础URL)
// - 上传配置(文件大小限制、上传接口)
// - 认证配置(Token过期时间、认证头字段)
// - 菜单配置(图标、路径、权限字段)
// - 系统设置(侧边栏模式、主题、调试模式)
// - 登录配置(多种登录方式开关)
// - 国际化配置(多语言支持)
export default {
// 系统标题
title: 'YLSG后台管理系统',
// 系统描述
description: 'YLSG后台管理系统',
// 系统关键词
keywords: 'YLSG后台管理系统',
// 是否启用网络异步路由
asyncRoutes: true,
// 接口配置
api: {
// 是否开启接口数据加密
enableEncryption: false,
// 加密密钥
encryptionKey: 'HSTebjXJRNpnKGh7',
// 接口超时时间(ms)
timeout: 10000,
// 开发环境接口地址
devBaseUrl: 'https://avue3base.xxxyin.cn',
// 是否开启mock数据
enableMock: false,
},
// 上传配置
upload: {
// 图片上传接口
imageUrl: '/base/upload_img',
// 文件上传接口
fileUrl: '/base/upload_file',
// 上传大小限制(MB)
maxSize: 10
},
// 系统Logo
logo: "A",
// 系统标识
storeKey: 'key',
// token配置
tokenTime: 60,
Authorization: 'Key',
// http错误码白名单
statusWhiteList: {
'401': '认证失败,无法访问系统资源',
'403': '当前操作没有权限',
'404': '访问资源不存在',
'500': '系统错误',
'601': '操作失败',
'default': '系统未知错误,请反馈给管理员'
},
// 首页配置
fistPage: {
name: "首页",
path: "/"
},
// 菜单配置
menu: {
iconDefault: 'icon-caidan', // 默认菜单图标
label: 'label', // 菜单标题字段名
path: 'path', // 菜单路由路径字段名
icon: 'icon', // 菜单图标字段名
children: 'children', // 子菜单字段名
query: 'query', // 路由参数字段名
href: 'href', // 外链字段名
meta: 'meta', // 路由元信息字段名
showIcon: true, // 是否显示菜单图标
},
// 系统设置
setting: {
sidebar: 'vertical', // 侧边栏模式,可选 vertical/horizontal/category
tag: true, // 是否显示标签页
debug: false, // 是否启用调试模式
collapse: true, // 是否允许折叠侧边栏
search: true, // 是否显示搜索框
lock: true, // 是否显示锁屏按钮
color: true, // 是否显示主题色设置
screenshot: true, // 是否显示截图按钮
fullscren: true, // 是否显示全屏按钮
theme: true, // 是否显示主题设置
menu: true // 是否显示菜单设置
},
// 登录配置
login: {
// 是否开启账号密码登录
enableUserLogin: true,
// 是否开启手机验证码登录
enablePhoneLogin: false,
// 是否开启人脸识别登录
enableFaceLogin: false,
// 是否开启第三方登录
enableThirdLogin: false,
// 是否开启图形验证码
enableCaptcha: true
},
// 国际化配置
i18n: {
// 是否开启多语言
enable: true,
// 默认语言
defaultLanguage: 'zh-CN',
// 支持的语言列表
languages: ['zh-CN', 'en-US']
},
}
Avue框架配置详解
Avue配置中心 Avue框架的配置位于 src/config/avue_cofig.js,这里定义了所有Avue组件的默认行为,配置参数说明可参考全局配置:
注意
以下为第三方云存储配置说明:
- Avue 支持对接腾讯云 COS、七牛云、阿里云 OSS 等第三方云存储服务。
- 配置项位于
src/config/avue_cofig.js,默认是注释状态。 - 如需启用第三方云存储,请取消对应配置的注释,并填写相关参数。
- 重要提示:一旦启用第三方云存储,原有的图片上传和文件上传接口将失效,务必确保云存储配置正确。
// 主要配置包括:
// - 组件尺寸设置
// - CRUD操作配置(增删改查按钮)
// - 表格样式配置(边框、斑马纹、对齐方式)
// - 表单配置(栅格间距、标签位置)
// - 对话框配置(拖拽、遮罩关闭)
// Avue全局配置对象
export const avueConfig = {
// 组件默认尺寸,可选值:'medium' | 'small' | 'mini' | 'default'
size: 'default',
// axios实例,所有Avue的请求会走这里
axios,
// CRUD(增删改查)相关的全局默认配置
crudOption: {
// 是否显示编辑按钮
editBtn: true,
// 是否显示删除按钮
delBtn: true,
// 是否显示新增按钮
addBtn: true,
// 是否显示表格边框
border: true,
// 是否显示斑马纹
stripe: true,
// 是否显示序号列
index: false,
// 搜索表单菜单所占栅格数(24栅格制)
searchMenuSpan: 8,
// 表格内容对齐方式
align: 'center',
// 表头对齐方式
headerAlign: 'center',
// 是否显示操作栏
menu: true,
// 操作栏按钮类型,可选:'button' | 'text' | 'icon'
menuType: 'text',
// 表格高度,'auto'为自适应
height: 'auto',
// 表格栅格间距
gutter: 30,
// 自动计算表格高度时的偏移量
calcHeight: 65,
// 操作栏宽度
menuWidth: 200,
// 操作栏标题
menuTitle: '可操作',
// 操作栏内容对齐方式
menuAlign: 'center',
// 操作栏是否固定在右侧
menuFixed: 'right',
// 是否显示打印按钮
printBtn: true,
// 是否显示导出Excel按钮
excelBtn: true,
// 是否显示列设置按钮
columnBtn: false,
// 是否显示复制按钮
copyBtn: false,
// 对话框是否可拖拽
dialogDrag: true,
// 点击遮罩是否可关闭对话框
dialogClickModal: true,
// 搜索表单标签位置,可选:'left' | 'top'
searchLabelPosition: 'left',
},
// 表单相关的全局默认配置
formOption: {
// 表单项之间的栅格间距
gutter: 30,
// 表单标签位置,可选:'left' | 'right' | 'top'
labelPosition: 'top',
// labelWidth: 110, // 可自定义标签宽度(如有需要可取消注释)
},
// 弹窗内容是否挂载到body(防止被父容器样式影响)
appendToBody: true,
// 模态框内容是否挂载到body
modalAppendToBody: true,
// 以下为第三方云存储配置(如需使用请取消注释并填写相关参数,注意,一旦取消注释第三方云存储,原来的图片上传,文件上传就会出错,非常重要)
/*
// 腾讯云COS配置
cos: {
SecretId: '',
SecretKey: '',
Bucket: '',
Region: ''
},
// 七牛云配置
qiniu: {
AK: '',
SK: '',
scope: '',
url: '',
deadline: 1
},
// 阿里云OSS配置
ali: {
region: '',
endpoint: '',
accessKeyId: '',
accessKeySecret: '',
bucket: '',
},
*/
// 水印画布配置(用于表格/图片等水印功能)
/*
canvas: {
text: 'avuejs.com', // 水印文字
fontFamily: 'microsoft yahei',// 字体
color: "#999", // 颜色
fontSize: 16, // 字号
opacity: 100, // 透明度
bottom: 10, // 距离底部距离
right: 10, // 距离右侧距离
ratio: 1 // 缩放比例
}
*/
}
动态加载器配置
智能加载系统 动态加载器就像项目的"智能管家",根据实际需要加载相应的功能模块:
// 参考文件:src/config/loader.js 第1-20行
// 主要功能:
// - 按需加载组件和配置
// - 性能优化,减少初始加载时间
// - 智能缓存管理,避免重复加载
export function initConfig() {
// (可选)保存配置到本地存储,可根据需要启用
// setStore({ name: CONFIG_KEY, content: settings })
// 如果启用API加密,则将加密/解密方法挂载到window全局对象
if (settings.api.enableEncryption) {
window.encryption = (data) => encryption(data)
window.decryption = (data) => decryption(data)
}
// 设置页面标题
if (settings.title) {
document.title = settings.title;
}
// 设置meta description
if (settings.description) {
const metaDesc = document.querySelector('meta[name="description"]');
if (metaDesc) {
metaDesc.setAttribute('content', settings.description);
}
}
// 设置meta keywords
if (settings.keywords) {
const metaKeywords = document.querySelector('meta[name="keywords"]');
if (metaKeywords) {
metaKeywords.setAttribute('content', settings.keywords);
}
}
return settings
}
/**
* 更新系统配置
* @param {Object} newConfig - 新的配置对象
* @returns {Object} 更新后的配置
*/
export function updateConfig(newConfig) {
// 合并新配置到settings对象
Object.assign(settings, newConfig)
// 保存到本地存储
setStore({ name: CONFIG_KEY, content: settings })
return settings
}
/**
* 重置系统配置为初始状态
* @returns {Object} 重置后的配置
*/
export function resetConfig() {
// 清空本地存储中的配置
setStore({ name: CONFIG_KEY, content: null })
// 重新初始化配置
return initConfig()
}
核心功能
CRUD混入模块
原理与作用机制
CRUD混入模块是YLSG框架的"核心引擎",就像给每个页面组件装了一个"智能助手",让开发者从繁琐的增删改查代码中解放出来。它通过Vue混入机制实现代码复用,将通用的CRUD逻辑封装成可配置的模块。
混入模块的优势
- 代码复用:一次编写,多处使用,告别"复制粘贴地狱"
- 配置驱动:通过配置文件控制页面行为,无需修改核心逻辑
- 权限集成:自动处理常见按钮权限显示,无需手动判断
- 钩子灵活:提供丰富的生命周期钩子,事件钩子,满足个性化需求
动态配置加载机制
混入模块会在组件初始化时自动检测当前组件路径,然后动态加载对应的配置文件。就像"智能管家"一样,它会:
- 自动识别组件所在目录结构
- 动态导入
{module}.js配置文件 - 动态导入
api_{module}.jsAPI文件 - 根据用户权限设置按钮显示状态
created() {
const componentName = this.crudOption.name;
// 动态检测组件所在目录
const componentPath = this.$options.__file || '';
// 尝试从组件路径中提取目录信息
let componentDir = '';
if (componentPath) {
const srcIndex = componentPath.indexOf('src/');
if (srcIndex !== -1) {
const relativePath = componentPath.substring(srcIndex + 4); // 去掉 'src/'
const lastSlashIndex = relativePath.lastIndexOf('/');
if (lastSlashIndex !== -1) {
componentDir = relativePath.substring(0, lastSlashIndex);
}
}
}
// 如果无法从路径获取,使用默认的page目录
if (!componentDir) {
componentDir = `page/${componentName}`;
}
// 构建文件路径 - 修正:确保包含/src前缀
const optionPath = `src/${componentDir}/${componentName}.js`;
const apiPath = `src/${componentDir}/api_${componentName}.js`;
// 动态导入所有JS文件
const modules = import.meta.glob('/src/**/*.js', { eager: false });
// 加载配置文件
const optionModulePath = `/${optionPath}`;
if (modules[optionModulePath]) {
modules[optionModulePath]().then((mode) => {
this.option = mode.default ? mode.default(this) : mode(this);
this.key = Math.random();
// 配置加载完成后,如果API也已加载,则获取数据
if (this.api && Object.keys(this.api).length > 0) {
this.getList();
}
}).catch((error) => {
});
}
// 加载API文件
const apiModulePath = `/${apiPath}`;
if (modules[apiModulePath]) {
modules[apiModulePath]().then((mode) => {
this.api = mode;
// API加载完成后,如果配置也已加载,则获取数据
if (this.option && Object.keys(this.option).length > 0) {
this.getList();
}
})
}
// 自定义按钮权限钩子
if (this.createdBefore) {
this.createdBefore(this.BtnPermission, permission);
}
if (debug) console.log(`[页面][${componentName}] 按钮权限设置完成:`, this.BtnPermission);
}
权限控制机制
混入模块内置了完整的权限控制逻辑,它会:
- 根据用户权限自动显示/隐藏操作按钮
- 支持菜单权限、按钮权限、路由权限一体化管理
- 提供权限验证的钩子函数,支持自定义权限逻辑
// 按钮权限钩子函数
<template>
<!-- 表格组件-->
<avue-crud >
<!-- 自定义操作按钮 -->
<template #menu="scope">
<el-button :type="menuType !== 'text' ? menuType : ''" :text="menuType == 'text'" icon="el-icon-view" class="el-button--primary"
@click="handle_see(scope.row, scope.index)" v-if="BtnPermission.article_see">
自定义
</el-button>
</template>
</avue-crud>
</template>
<script>
import crudMixin from '@/mixins/crud.js'
export default {
name: 'article',
mixins: [crudMixin({
name: 'article'
})],
methods: {
// 【自定义】事件处理
handle_see(row, index) {
console.log('自定义', row, index)
},
// 权限初始化
createdBefore(BtnPermission, permission) {
//createdBefore初始化后处理,这个钩子运行在页面生命周期初始化created中
// 它可以在获取到BtnPermission,当然你还能做一些其他的处理,比如你希望页面初始化的时候处理一些数据
// 自定义按钮权限配置
if (permission) {
BtnPermission.article_see = permission?.article_see;
}
},
},
}
</script>
数据封装处理
混入模块统一处理所有的数据操作,包括:
- 数据过滤:自动清理表单中的临时字段(如
$cellEdit,$index等) - 错误处理:统一的错误处理机制,避免重复代码
- 响应处理:标准化的响应数据处理,支持自定义处理逻辑
// 公共方法:会递归过滤对象中所有以$开头的key,支持多级嵌套,
function filterDollarKeys(obj) {
if (Array.isArray(obj)) {
return obj.map(item => filterDollarKeys(item));
} else if (obj && typeof obj === 'object') {
const result = {};
Object.keys(obj).forEach(key => {
if (!key.startsWith('$')) {
result[key] = filterDollarKeys(obj[key]);
}
});
return result;
}
return obj;
}
事件处理机制
混入模块提供了完整的事件处理体系:
- 生命周期钩子:支持
createdBefore,listBefore,addBefore等钩子 - 数据操作钩子:支持
addAfter,updateAfter,delAfter等钩子 - 自定义事件:支持自定义事件处理,满足特殊业务需求
created() {
// ...动态载入配置
// 自定义按钮权限钩子
if (this.createdBefore) {
this.createdBefore(this.BtnPermission, permission);
}
},
methods: {
/**
* 获取数据列表
*/
getList() {
const callback = () => {
// ...数据获取逻辑...
apiMethod(data).then((res) => {
// 列表获取后的回调处理
if (this.listAfter) {
data = this.listAfter(data);
} else {
this.$message.success("获取成功");
}
this.data = data;
});
};
// 列表获取前的钩子
if (this.listBefore) {
this.listBefore();
}
callback();
},
/**
* 保存新行数据
*/
rowSave(row, done, loading) {
const callback = () => {
this.api[this.option.add || "add"](this.form).then((data) => {
if (this.addAfter) {
this.addAfter(data);
} else {
this.$message.success("新增成功");
}
});
};
if (this.addBefore) {
this.addBefore();
}
callback();
},
/**
* 更新行数据
*/
rowUpdate(row, index, done, loading) {
const callback = () => {
this.api[this.option.update || "update"](this.form).then((data) => {
if (this.updateAfter) {
this.updateAfter(data);
} else {
this.$message.success("更新成功");
}
});
};
if (this.updateBefore) {
this.updateBefore();
}
callback();
},
/**
* 删除行数据
*/
rowDel(row, index) {
const callback = () => {
this.api[this.option.del || "del"]({ id: row.id }).then((data) => {
if (this.delAfter) {
this.delAfter(data, row, index);
} else {
this.$message.success("删除成功");
}
});
};
if (this.delBefore) {
this.delBefore();
callback();
}
},
/**
* 搜索条件变化处理
*/
searchChange(params, done) {
// 搜索前钩子处理
if (this.searchBefore) {
const processedParams = this.searchBefore(params);
if (processedParams === false) return;
params = processedParams || params;
}
this.getList();
}
}
灵活钩子函数
混入模块提供了丰富的钩子函数,就像给开发者提供了"自定义工具箱"️:
生命周期钩子
createdBefore(BtnPermission, permission)- 组件初始化后执行listBefore()- 获取列表数据前执行listAfter(data)- 获取列表数据后执行
数据操作钩子
addBefore()- 新增数据前执行addAfter(data)- 新增数据后执行updateBefore()- 更新数据前执行updateAfter(data)- 更新数据后执行delBefore()- 删除数据前执行delAfter(data, row, index)- 删除数据后执行
搜索和导入导出钩子
searchBefore(params)- 搜索前执行beforeImportData()- 导入前执行(必须返回表单配置)beforeExportData(params)- 导出前执行afterExportData(res, error)- 导出后执行
下载模板钩子
beforeDownloadTemplate()- 下载模板前afterDownloadTemplate(res, error)- 下载模板后
钩子函数返回值规则
- 返回
false:阻止后续操作执行 - 返回其他值或无返回值:继续执行后续操作
钩子实际使用示例:
// 参考文件:src/page/user/user.vue 第20-40行
// 主要功能:用户管理页面的钩子函数示例
export default {
mixins: [crud({ name: 'user' })],
methods: {
// 新增前:添加默认值
addBefore() {
this.form.create_time = this.$dayjs().format('YYYY-MM-DD HH:mm:ss')
this.form.status = 1 // 默认启用状态
},
// 更新前:添加更新时间
updateBefore() {
this.form.update_time = this.$dayjs().format('YYYY-MM-DD HH:mm:ss')
},
// 搜索前:预处理搜索参数
searchBefore(params) {
if (params.username) {
params.username = params.username.trim()
}
return params
}
}
}
小技巧
- 钩子函数应该保持简洁,复杂的业务逻辑建议封装成独立方法
- 充分利用钩子函数的返回值控制流程,避免不必要的API调用
- 在钩子函数中添加必要的日志记录,便于问题排查
用户认证与权限管理
Token管理策略
Token管理就像"数字身份证",系统采用了一套完整的Token生命周期管理策略:
1. Token生成与存储
- 自动生成:登录成功后自动获取JWT Token
- 安全存储:Token存储在本地存储中
- 过期时间:可灵活配置Token过期时间,默认60分钟
2. Token自动刷新
- 智能刷新:Token即将过期时自动刷新
- 无缝体验:用户无感知的Token更新
- 失败处理:刷新失败时自动跳转登录页
3. Token验证机制
- 请求拦截:每个API请求头自动携带Token(这次放到了headers中)
- 响应拦截:自动处理Token过期情况
- 权限验证:结合Token进行权限验证
Token安全注意事项
- Token存储在本地存储中,建议在生产环境启用HTTPS
- Token过期时间不宜设置过长,建议30-60分钟
- 支持Token黑名单机制,登出时自动加入黑名单
用户信息管理
用户信息管理就像"个人档案室",系统提供了完整的用户信息管理功能:
用户信息存储
- Vuex状态管理:用户信息存储在Vuex中,全局共享
- 本地缓存:关键信息本地缓存,提升访问速度
- 实时同步:用户信息变更时实时更新
用户信息获取
- 自动获取:登录成功后自动获取用户详细信息
- 权限信息:同时获取用户权限列表
- 角色信息:获取用户角色和权限范围
getMemberInfo({ commit }) {
return new Promise((resolve, reject) => {
getMemberInfo().then((res) => {
const data = res;
//用户信息存储
commit('SET_USERIFNO', data.userInfo);
commit('SET_ROLES', data.roles);
commit('SET_PERMISSION', data.permission)
resolve(data);
}).catch(err => {
reject(err);
})
})
用户信息使用示例
// 在组件中获取用户信息
export default {
computed: {
userInfo() {
return this.$store.state.user.userInfo
},
userPermissions() {
return this.$store.state.user.permission
}
},
methods: {
// 检查用户权限
hasPermission(permission) {
return this.userPermissions[permission] || false
}
}
}
全局缓存参数详解与使用
src/store/modules/user.js 缓存参数说明
| 参数名 | 用途 | 存入时机 | 可用场景 | 使用方法 |
|---|---|---|---|---|
userInfo | 用户基本信息 | 登录成功后 | 显示用户信息、权限判断 | this.$store.state.user.userInfo |
permission | 用户权限列表 | 获取用户信息后 | 按钮权限控制 | this.$store.state.user.permission |
roles | 用户角色列表 | 获取用户信息后 | 角色权限判断 | this.$store.state.user.roles |
menuId | 菜单ID映射 | 获取菜单后 | 菜单权限控制 | this.$store.state.user.menuId |
menu | 用户菜单列表 | 登录后获取 | 侧边栏菜单显示 | this.$store.state.user.menu |
menuAll | 所有菜单列表 | 获取菜单后 | 菜单管理功能 | this.$store.state.user.menuAll |
token | 访问令牌 | 登录成功后 | API请求认证 | this.$store.state.user.token |
refreshToken | 刷新令牌 | 登录成功后 | Token刷新 | this.$store.state.user.refreshToken |
使用示例
// 在组件中使用
export default {
computed: {
userInfo() {
return this.$store.state.user.userInfo
},
hasEditPermission() {
return this.$store.state.user.permission['user_edit']
}
},
methods: {
checkPermission(permission) {
return this.$store.state.user.permission[permission]
}
}
}
权限管理体系
YLSG后台管理系统的权限体系就像"数字门禁系统",通过多层权限控制确保系统安全。它采用路由权限、菜单权限、按钮权限三位一体的控制机制,配合角色管理和动态菜单配置,构建了完整的权限管理体系。
路由权限控制
路由权限控制就像"交通管制",通过全局路由守卫确保用户只能访问有权限的页面:
运行逻辑:
- 全局前置守卫:在
src/permission.js中配置路由守卫 - Token验证:检查用户是否已登录,未登录跳转登录页
- 用户信息获取:登录后自动获取用户角色和权限信息(最新后端接口全放在了获取用户信息中)
- 路由匹配:根据用户权限过滤可访问的路由
- 动态路由:支持异步路由加载,按需生成路由配置
参考文件:src/permission.js 第1-131行
核心流程:
// 路由守卫核心逻辑
router.beforeEach((to, from, next) => {
// 1. 检查Token
if (getToken()) {
// 2. 获取用户信息
if (store.getters.roles.length === 0) {
store.dispatch('getMemberInfo').then(() => {
next({ ...to, replace: true })
})
} else {
// 3. 权限验证通过,允许访问
next()
}
} else {
// 4. 无Token,跳转登录页
next('/login')
}
})
路由权限特点
- 支持异步路由加载,提升系统性能
- 自动处理Token过期情况
- 支持外部链接和标签页管理
- 框架已集成进度条显示,提升用户体验
菜单权限控制
菜单权限控制就像"菜单管家",通过远程菜单配置限制用户可见的菜单项:
运行逻辑:
- 远程菜单获取:从后端获取用户有权限的菜单列表
- 菜单数据过滤:根据用户权限过滤菜单项
- 动态菜单渲染:只显示用户有权限的菜单
- 菜单配置适配:通过
menu配置 适配不同后端菜单结构
菜单权限重要说明
- 远程菜单:通过后端接口获取,可以精确控制用户菜单权限
- 本地菜单:无法控制权限,仅用于开发调试
按钮权限管理
按钮权限管理就像"操作开关",通过权限标识控制页面按钮的显示和功能:
运行逻辑:
- 权限标识获取:从用户权限列表中获取按钮权限标识
- 按钮权限设置:根据权限标识设置按钮显示状态
- 动态权限控制:支持自定义按钮权限钩子
- 权限回退机制:当启用本地菜单时,默认显示所有按钮
页面权限标识基础规则
页面名_edit:编辑按钮权限页面名_del:删除按钮权限页面名_add:新增按钮权限页面名_import:导入按钮权限页面名_export:导出按钮权限页面名_down:下载模板按钮权限
按钮权限特点
- 支持自定义权限钩子,灵活扩展权限控制
- 权限标识采用"页面名_操作"的命名规则
- 支持权限回退,本地菜单模式下默认显示所有按钮
- 实时权限验证,确保操作安全性
角色管理功能
角色管理功能就像"权限分配中心",超级管理员可以在系统管理菜单组下的角色管理中,在操作栏中点击权限设置,勾选菜单权限即可。
操作流程:
- 进入系统管理 → 角色管理
- 在角色列表的操作栏中点击"权限设置"
- 在弹出的权限设置对话框中勾选相应的菜单权限
- 保存设置,权限立即生效
权限设置界面:
[此处需附图:角色权限设置界面,显示菜单权限勾选界面]
角色管理说明
- 只有超级管理员可以管理角色权限
- 权限设置实时生效,无需重启系统
- 支持批量权限设置,提高管理效率
动态菜单配置
动态菜单配置就像"菜单开关",通过全局配置控制菜单的加载方式:
配置说明: 在 src/config/settings.js 中通过 asyncRoutes 配置控制菜单加载方式:
// 是否启用网络异步路由
asyncRoutes: true, // true: 远程菜单,false: 本地菜单
两种模式对比:
| 配置项 | 本地菜单模式 | 远程菜单模式 |
|---|---|---|
asyncRoutes: false | 启用 | 禁用 |
asyncRoutes: true | 禁用 | 启用 |
| 权限控制 | 无法控制权限 | 精确权限控制 |
| 菜单来源 | 本地路由配置 | 后端接口返回 |
| 适用场景 | 开发调试 | 生产环境 |
菜单模式重要提醒
- 本地菜单:无法控制权限,仅用于开发调试
- 远程菜单:可以精确控制用户菜单权限,推荐生产环境使用
- 切换菜单模式需要重启应用才能生效
分店权限管理
分店权限管理机制已做出重要调整,现行逻辑如下:
1. 分店与管理员账号绑定
- 分店表不再单独存储账号密码,分店管理员账号直接与系统管理员表(
ylsg_sys_member)绑定。 - 分店管理员的超级管理员角色ID固定为2,且管理员表中新增
branch_id字段用于标识所属分店。 - 新增分店时,通过一个接口同时创建分店信息和分店管理员账号(含账号、密码),分别在分店表和管理员表建立记录,并自动建立关联关系。
2. 分店管理员账号保护
- 当全局配置
settings.js中enableBranchStore设置为true时,角色ID为2的分店管理员账号不可被删除,保障分店管理的完整性。
3. 分店管理员登录与信息获取
- 分店管理员登录后台后,
/member/get_member_info接口会直接返回其对应的分店信息,便于前端根据分店上下文进行业务处理。
4. 分店权限配置与角色管理
- 分店代码无需独立分包,所有分店权限均可在总后台通过角色权限配置灵活分配。
- 分店可在自身权限范围内独立设置分店下属角色,分店自定义角色的权限上限受总后台为该分店分配的权限范围限制,实现权限下放与隔离。
5. 分店与管理员禁用逻辑
- 分店被禁用后,所有属于该分店的管理员账号将无法登录系统,实现分店级别的统一禁用。
- 若仅禁用某个分店管理员账号,则仅该账号无法登录,其他同分店管理员账号不受影响。
分店权限管理小结
- 分店与管理员强绑定,权限分配灵活,支持分店独立角色管理
- 分店禁用与管理员禁用互不干扰,保障系统安全与灵活性
- 相关配置与逻辑详见
settings.js及后台接口文档
API接口设计
Axios配置与拦截器
Axios配置就像"HTTP请求管家",提供了完整的请求生命周期管理,包括安全防护、错误处理、调试支持等功能。
基础配置
- baseURL:根据Mock模式动态设置,Mock模式下为空,否则为
/admin - timeout:请求默认超时时间10秒
- withCredentials:允许跨域请求携带cookie
请求拦截器
- 时间戳防重放: 每个请求自动添加当前时间戳,POST/PUT请求添加到请求体,GET请求添加到URL参数
- Token自动注入: 自动从localStorage获取Token并添加到请求头,可通过
isToken: false禁用 - 数据清洗: 自动过滤空值(null、undefined、空字符串、空数组、空对象等),只对非FormData类型请求体处理
- 数据加密: 通过
settings.api.enableEncryption控制,使用全局window.encryption方法加密 - 防重复提交: 1秒内相同URL和数据的POST/PUT请求会被拦截,可通过
repeatSubmit: false禁用
响应拦截器
- 二进制数据处理: 文件下载等二进制数据直接返回原始数据,不进行业务逻辑处理
- 业务状态码处理:
- 200: 成功状态,上传和选择接口返回原始response,其他接口返回
res.data.datas - 400: 业务错误,显示错误信息
- 555: 系统错误,显示错误信息
- 777: 警告信息,显示警告提示
- 999: Token过期,弹出重新登录确认框
- 200: 成功状态,上传和选择接口返回原始response,其他接口返回
错误处理
- HTTP状态码白名单: 401认证失败、403权限不足、404资源不存在、500系统错误、601操作失败,在全局配置中可修改。
- Token过期处理: 使用全局标志防止重复弹窗,用户确认后执行登出并跳转首页
- 错误提示策略: 500错误显示error类型消息,其他错误显示warning类型消息
调试功能
- 请求数据调试: 通过全局配置
settings.setting.debug控制,GET请求打印params,其他请求打印data - 响应数据调试: 打印完整的响应数据结构
接口使用方式
// 先引入
import request from '@/axios';
// 基础使用示例
export const getUsers = (params) => {
return request({
url: '/api/users',
method: 'get',
params
})
}
// 创建用户
export const createUser = (data) => {
return request({
url: '/api/users',
method: 'post',
data
})
}
// 禁用Token
export const login = (data) => {
return request({
url: '/api/login',
method: 'post',
data,
headers: {
isToken: false
}
})
}
// (禁用防重复提交)
export const submitForm = (data) => {
return request({
url: '/api/submit',
method: 'post',
data,
headers: {
repeatSubmit: false
}
})
}
// 页面使用示例
// 以获取用户列表为例,页面中可这样调用API方法:
// curd混入默认已经全部引入,直接可以用this.api.方法名调用
import { getUsers, createUser } from '@/views/user/api_user' // 假设API文件路径
export default {
data() {
return {
userList: [],
loading: false,
form: {
name: '',
age: ''
}
}
},
methods: {
// 获取用户列表
fetchUsers() {
this.loading = true
getUsers({ page: 1, size: 10 }).then(res => {
this.userList = res.data.list
}).finally(() => {
this.loading = false
})
},
// 新建用户
handleCreate() {
createUser(this.form).then(res => {
this.$message.success('创建成功')
this.fetchUsers()
})
}
},
mounted() {
this.fetchUsers()
}
}
全局配置项说明:
api.enableEncryption: 是否启用数据加密api.enableMock: 是否启用Mock模式api.timeout: 请求超时时间setting.debug: 是否启用调试模式Authorization: Token字段名statusWhiteList: HTTP状态码错误信息映射
这个axios配置提供了完整的HTTP请求生命周期管理,包括安全防护、错误处理、调试支持等功能,是一个企业级的HTTP客户端配置。
框架基础接口
登录接口
接口描述:用户登录验证 接口地址:/login/login
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| username | admin | string | 用户名 |
| password | 123 | string | 密码 |
| code | bT26 | string | 验证码 |
| requeTime | 1754117616 | number | 时间戳验证条件 |
返回示例:
{
"code": 200,
"datas": {
"id": 1,
"username": "admin",
"nickname": "超级管理员",
"avatar": "http://avue3base.xxxyin.cn/uploads/base/admin.jpg",
"state": 1,
"role_id": 1,
"type": 1,
"key": "3705e45463f667ab7f3fbe182779e458",
"key_time": 1754117618,
"add_time": 0,
"update_time": 1649231810,
"last_login_time": 1754117618,
"last_login_ip": "183.226.112.242",
"p_id": 0,
"client_id": ""
}
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas.id | number | 用户ID |
| datas.username | string | 用户名 |
| datas.nickname | string | 用户昵称 |
| datas.avatar | string | 用户头像URL |
| datas.state | number | 用户状态 |
| datas.role_id | number | 角色ID |
| datas.type | number | 用户类型 |
| datas.key | string | 登录凭证token |
| datas.key_time | number | token生成时间 |
| datas.last_login_time | number | 最后登录时间 |
| datas.last_login_ip | string | 最后登录IP |
获取用户信息接口
接口描述:获取当前登录用户信息 接口地址:/member/get_member_info
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": {
"userInfo": {
"id": 1,
"username": "admin",
"password": "cd33c6223e01d512b6462f00c40fdf02",
"nickname": "超级管理员",
"avatar": "http://avue3base.xxxyin.cn/uploads/base/admin.jpg",
"state": 1,
"role_id": 1,
"type": 1,
"key": "3705e45463f667ab7f3fbe182779e458",
"key_time": "2025-08-02 14:53:38",
"add_time": "",
"update_time": "2022-04-06 15:56:50",
"last_login_time": "2025-08-02 14:53:38",
"last_login_ip": "183.226.112.242",
"p_id": 0,
"client_id": "",
"role_weight": 1
},
"roles": {
"role_id": 1,
"role_name": "超级管理员",
"weight": 1
},
"permission": [
"index_import",
"index_export",
"index_del",
"index_edit",
"index_add",
"MenuManagement_import",
"MenuManagement_export",
"MenuManagement_del",
"MenuManagement_edit",
"MenuManagement_add",
"role_import",
"role_export",
"role_del",
"role_edit",
"role_add",
"admin_user_import",
"admin_user_export",
"admin_user_del",
"admin_user_edit",
"admin_user_add",
"applets_page_del",
"applets_page_detail",
"applets_page_edit",
"applets_page_add",
"share_img_del",
"share_img_detail",
"share_img_edit",
"share_img_add",
"swiper_del",
"swiper_detail",
"swiper_edit",
"swiper_add"
]
}
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas.userInfo | object | 用户信息对象 |
| datas.userInfo.id | number | 用户ID |
| datas.userInfo.username | string | 用户名 |
| datas.userInfo.nickname | string | 用户昵称 |
| datas.userInfo.avatar | string | 用户头像 |
| datas.userInfo.state | number | 用户状态 |
| datas.userInfo.role_id | number | 角色ID |
| datas.userInfo.role_weight | number | 角色权重 |
| datas.roles | object | 角色信息 |
| datas.roles.role_id | number | 角色ID |
| datas.roles.role_name | string | 角色名称 |
| datas.roles.weight | number | 角色权重 |
| datas.permission | array | 权限列表 |
菜单获取接口
接口描述:获取用户菜单权限信息 接口地址:/member/get_menu_role_info
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": [
{
"id": 1,
"p_id": 0,
"sort": 0,
"label": "首页",
"icon": "fa-solid fa-desktop",
"is_show": 0,
"is_top": 2,
"query": "",
"path": "/wel",
"href": "",
"type": 1,
"meta": {
"title": "首页",
"icon": "fa-solid fa-desktop"
},
"add_time": 1752054402,
"update_time": 1753452378,
"hidden": 0,
"children": [
{
"id": 2,
"p_id": 1,
"sort": 0,
"label": "首页",
"icon": "fa-solid fa-desktop",
"is_show": 0,
"is_top": 2,
"query": "",
"path": "index",
"href": "",
"type": 2,
"meta": {
"title": "首页",
"icon": "fa-solid fa-desktop"
},
"add_time": 1752054402,
"update_time": 1753452508,
"hidden": 0,
"children": [
{
"id": 11,
"p_id": 2,
"sort": 0,
"label": "首页导入数据",
"icon": "",
"is_show": 0,
"is_top": 2,
"query": "",
"path": "index_import",
"href": "",
"type": 3,
"meta": {
"title": "首页导入数据",
"icon": "",
"i18n": "i18n"
},
"add_time": 1752054402,
"update_time": 1752054402,
"hidden": 0,
"children": []
}
]
}
]
}
]
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | array | 菜单列表 |
| datas[].id | number | 菜单ID |
| datas[].p_id | number | 父级菜单ID |
| datas[].sort | number | 排序值 |
| datas[].label | string | 菜单标签 |
| datas[].icon | string | 菜单图标 |
| datas[].is_show | number | 是否显示 |
| datas[].is_top | number | 是否置顶 |
| datas[].path | string | 路由路径 |
| datas[].type | number | 菜单类型 |
| datas[].meta | object | 菜单元信息 |
| datas[].children | array | 子菜单列表 |
登出接口
接口描述:用户退出登录 接口地址:/login/logout
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": "操作成功"
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | string | 操作结果信息 |
Token刷新接口
接口描述:刷新用户登录凭证 接口地址:/member/refresh
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": "a97dd07246eb37d85ef61f917e3e7ae2"
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | string | 新的token凭证 |
获取备案信息接口
接口描述:获取系统底部备案信息 接口地址:/login/record_info
请求方式:POST
请求参数:无
返回示例:
{
"code": 200,
"datas": {
"record_number": "",
"record_url": "https://beian.miit.gov.cn"
}
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas.record_number | string | 备案号 |
| datas.record_url | string | 备案链接 |
获取菜单列表接口
接口描述:获取菜单列表数据 接口地址:/menu/get_menu_list
请求方式:GET
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": [
{
"id": 1,
"p_id": 0,
"sort": 0,
"label": "首页",
"icon": "fa-solid fa-desktop",
"is_show": 0,
"is_top": 2,
"query": "",
"path": "/wel",
"href": "",
"type": 1,
"meta": {
"title": "首页",
"icon": "fa-solid fa-desktop"
},
"add_time": "2025-07-09 17:46:42",
"update_time": "2025-07-25 22:06:18",
"children": [
{
"id": 2,
"p_id": 1,
"sort": 0,
"label": "首页",
"icon": "fa-solid fa-desktop",
"is_show": 0,
"is_top": 2,
"query": "",
"path": "index",
"href": "",
"type": 2,
"meta": {
"title": "首页",
"icon": "fa-solid fa-desktop"
},
"add_time": "2025-07-09 17:46:42",
"update_time": "2025-07-25 22:08:28",
"children": [
{
"id": 11,
"p_id": 2,
"sort": 0,
"label": "首页导入数据",
"icon": "",
"is_show": 0,
"is_top": 2,
"query": "",
"path": "index_import",
"href": "",
"type": 3,
"meta": {
"title": "首页导入数据",
"icon": "",
"i18n": "i18n"
},
"add_time": "2025-07-09 17:46:42",
"update_time": "2025-07-09 17:46:42",
"children": []
}
]
}
]
}
]
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | array | 菜单列表数据 |
批量添加菜单接口
接口描述:批量添加菜单数据 接口地址:/menu/all_add
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| json_all | 菜单json字符串 | string | 菜单json字符串,系统会自行处理view中的路由 |
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": "操作成功"
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | string | 操作结果信息 |
获取菜单详情接口
接口描述:获取单个菜单详情信息 接口地址:/menu/get_menu_info
请求方式:GET
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| id | 1 | number | 菜单ID |
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": {
"id": 6,
"p_id": 0,
"sort": 1,
"label": "运营管理",
"icon": "",
"is_show": 0,
"is_top": 2,
"query": "",
"path": "/operation",
"href": "",
"type": 1,
"meta": {
"title": "运营管理"
},
"add_time": "2025-08-02 15:39:34",
"update_time": "2025-08-02 15:39:34"
}
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | object | 菜单详情数据 |
更新菜单接口
接口描述:更新菜单信息 接口地址:/menu/edit
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| id | 1 | number | 菜单ID |
| label | 系统管理 | string | 菜单标签 |
| meta | {"title":"系统管理"} | string | 菜单元信息JSON字符串 |
| type | 1 | string | 菜单类型 |
| sort | 3 | number | 排序值 |
| path | /system | string | 路由路径 |
| p_id | 0 | number | 父级菜单ID |
| is_show | 0 | number | 是否显示 |
| is_top | 2 | number | 是否置顶 |
| requeTime | 1754120718 | number | 时间戳验证条件 |
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": "操作成功"
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | string | 操作结果信息 |
创建菜单接口
接口描述:创建新菜单 接口地址:/menu/add
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| label | ceshi | string | 菜单标签 |
| meta | {"title":"测试","icon":"fa-solid fa-store"} | string | 菜单元信息JSON字符串 |
| type | 2 | string | 菜单类型 |
| sort | 0 | number | 排序值 |
| path | ceshi | string | 路由路径 |
| query | ceshi | string | 查询参数 |
| p_id | 6 | number | 父级菜单ID |
| is_show | 0 | number | 是否显示 |
| is_top | 2 | number | 是否置顶 |
| requeTime | 1754121306 | number | 时间戳验证条件 |
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": "操作成功"
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | string | 操作结果信息 |
删除菜单接口
接口描述:删除指定菜单 接口地址:/menu/del
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| id | 55 | number | 菜单ID |
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": "操作成功"
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | string | 操作结果信息 |
清空菜单接口
接口描述:清空所有菜单数据 接口地址:/menu/clear_menu
请求方式:GET
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": "菜单已清空,自增ID已重置"
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | string | 操作结果信息 |
获取角色列表接口
接口描述:获取角色列表(分页) 接口地址:/role/get_role_list
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| pageNum | 1 | number | 页码 |
| pageSize | 10 | number | 每页数量 |
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": {
"num": 4,
"data": [
{
"id": 1,
"role_name": "超级管理员",
"state": 1,
"sort": 0,
"roleval": "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54",
"cmark": "最高权限管理员",
"add_time": 1598587433,
"update_time": 1753869363,
"weight": 1
}
]
}
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas.num | number | 总数量 |
| datas.data | array | 角色列表数据 |
| datas.data.id | number | 角色ID |
| datas.data.role_name | string | 角色名称 |
| datas.data.state | number | 角色状态 |
| datas.data.sort | number | 排序值 |
| datas.data.roleval | string | 角色权限值 |
| datas.data.cmark | string | 角色备注 |
| datas.data.weight | number | 角色权重 |
获取所有角色接口
接口描述:获取所有角色数据 接口地址:/role/show_role_list
请求方式:GET
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": [
{
"id": 1,
"role_name": "超级管理员",
"state": 1,
"weight": 1
}
]
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | array | 角色列表数据 |
删除角色接口
接口描述:删除指定角色 接口地址:/role/del
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| id | 55 | number | 角色ID |
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": "操作成功"
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | string | 操作结果信息 |
新增角色接口
接口描述:创建新角色 接口地址:/role/add
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| role_name | 新框架 | string | 角色名称 |
| cmark | 测试新框架 | string | 角色备注 |
| weight | 1 | number | 角色权重 |
| state | 1 | number | 角色状态 |
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": "操作成功"
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | string | 操作结果信息 |
更新角色接口
接口描述:更新角色信息 接口地址:/role/edit
请求方式:POST
请求参数:
| 参数名 | 示例值 | 类型 | 说明 |
|---|---|---|---|
| id | 1 | number | 角色ID |
| role_name | 新框架 | string | 角色名称 |
| cmark | 测试新框架 | string | 角色备注 |
| weight | 1 | number | 角色权重 |
| state | 1 | number | 角色状态 |
| token | 3705e45463f667ab7f3fbe182779e458 | string | token凭证,放在headers中 |
返回示例:
{
"code": 200,
"datas": "操作成功"
}
返回参数说明::
| 参数名 | 类型 | 说明 |
|---|---|---|
| code | number | 状态码,200表示成功 |
| datas | string | 操作结果信息 |
基础组件
组件使用指南
框架提供了一套完整的基础组件库,涵盖了常见的页面布局和交互需求。这些组件都经过精心设计,支持主题定制和响应式布局。
容器组件系统
basic-container - 页面容器组件
组件描述:提供标准化的页面容器布局,自动处理内边距和背景样式。
Props:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| padding | String | '20px' | 内边距 |
| background | String | '#fff' | 背景色 |
| height | String | 'auto' | 容器高度 |
使用示例:
<template>
<basic-container>
<el-card>
<div>页面内容</div>
</el-card>
</basic-container>
</template>
最佳实践
建议在页面根元素使用 basic-container,可以确保页面布局的一致性和美观性。
basic-block - 块级组件
组件描述:提供可折叠的内容块容器,支持标题显示和折叠功能。
Props:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| title | String | - | 块标题 |
| collapsible | Boolean | false | 是否可折叠 |
| collapsed | Boolean | false | 是否默认折叠 |
使用示例:
<template>
<basic-block title="数据统计" :collapsible="true">
<div>统计内容</div>
</basic-block>
</template>
块级组件功能
basic-video - 视频组件
组件描述:基于 Video.js 封装的视频播放组件,支持多种视频格式和自定义控制。
Props:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| src | String | - | 视频源地址 |
| width | String/Number | '100%' | 视频宽度 |
| height | String/Number | '300px' | 视频高度 |
| controls | Boolean | true | 是否显示控制条 |
| autoplay | Boolean | false | 是否自动播放 |
| loop | Boolean | false | 是否循环播放 |
使用示例:
<template>
<basic-video
:src="videoUrl"
:width="800"
:height="450"
:controls="true"
/>
</template>
<script>
export default {
data() {
return {
videoUrl: 'https://example.com/video.mp4'
}
}
}
</script>
浏览器兼容性
视频组件支持 MP4、WebM、Ogg 等主流格式,建议提供多种格式以确保兼容性。
视频组件配置
自定义视频配置
// 在 src/components/basic-video/plugin.js 中配置
export default {
// 视频播放器配置
videojs: {
controls: true,
fluid: true,
responsive: true,
preload: 'metadata'
},
// 自定义控制按钮
customControls: {
play: true,
pause: true,
fullscreen: true,
volume: true
}
}
内嵌框架组件
iframe - 内嵌框架组件
组件描述:提供安全的内嵌框架功能,支持跨域页面嵌入和通信。
Props:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| src | String | - | 源地址 |
| width | String/Number | '100%' | 框架宽度 |
| height | String/Number | '400px' | 框架高度 |
| frameborder | String | '0' | 边框样式 |
| allowfullscreen | Boolean | false | 是否允许全屏 |
使用示例:
<template>
<iframe
:src="externalUrl"
:width="800"
:height="600"
frameborder="0"
allowfullscreen
/>
</template>
安全提醒
使用 iframe 组件时,请确保嵌入的页面来源可信,避免 XSS 攻击风险。
用户信息组件
Userinfo - 用户信息展示组件
组件描述:专门用于展示用户头像、昵称和手机号的信息容器组件。
Props:
| 参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| avatar | String | 是 | 用户头像URL |
| nickname | String | 是 | 用户昵称 |
| phone | String | 是 | 用户手机号 |
组件功能:
- 显示用户头像(48x48px 圆形头像)
- 显示用户昵称(15px 字体,加粗样式)
- 显示用户手机号(12px 字体,灰色样式)
样式预览:
使用示例:
<template>
<Userinfo
avatar="https://example.com/avatar.jpg"
nickname="张三"
phone="138****8888"
/>
</template>
<script>
import Userinfo from '@/components/Userinfo/Userinfo.vue'
export default {
components: {
Userinfo
}
}
</script>
样式定制
组件支持通过 CSS 变量自定义样式,可在全局样式中覆盖默认样式。
文件管理组件
FileManagerDialog - 文件管理对话框组件
组件描述:提供完整的文件上传、预览、删除功能,支持多种文件类型和批量操作。
Props:
| 参数名 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| fileList | Array | [] | 文件列表 |
| accept | String | '*' | 接受的文件类型 |
| maxSize | Number | 10 | 最大文件大小(MB) |
| multiple | Boolean | false | 是否支持多选 |
| showPreview | Boolean | true | 是否显示预览 |
Events:
| 事件名 | 参数 | 说明 |
|---|---|---|
| upload | file | 文件上传事件 |
| delete | file | 文件删除事件 |
| preview | file | 文件预览事件 |
使用示例:
<template>
<file-manager
:file-list="files"
accept=".jpg,.png,.pdf"
:max-size="5"
:multiple="true"
@upload="handleUpload"
@delete="handleDelete"
@preview="handlePreview"
/>
</template>
<script>
export default {
data() {
return {
files: []
}
},
methods: {
handleUpload(file) {
console.log('上传文件:', file)
},
handleDelete(file) {
console.log('删除文件:', file)
},
handlePreview(file) {
console.log('预览文件:', file)
}
}
}
</script>
文件管理组件源码实现
// src/components/file-manager/file.js
export default {
// 文件上传处理
uploadFile(file) {
const formData = new FormData()
formData.append('file', file)
return this.$http.post('/upload', formData)
},
// 文件预览处理
previewFile(file) {
if (file.type.startsWith('image/')) {
return this.previewImage(file)
}
return this.previewDocument(file)
}
}
富文本编辑器
avue-plugin-ueditor - 富文本编辑器组件
组件描述:基于 UEditor编辑器 封装的富文本编辑组件,支持图片/视频上传和复制粘贴功能。
配置说明:
- 支持富文本编辑和格式化
- 支持图片/视频上传功能
- 支持复制粘贴内容
- 可自定义工具栏配置
使用示例:
<template>
<avue-form :option="option" v-model="form">
<template #content>
<avue-ueditor
v-model="form.content"
:config="editorConfig"
@ready="onEditorReady"
/>
</template>
</avue-form>
</template>
<script>
export default {
data() {
return {
form: {
content: ''
},
option: {
column: [
{
label: '内容',
prop: 'content',
type: 'ueditor'
}
]
},
editorConfig: {
// 编辑器配置
toolbars: [
'fullscreen', 'source', '|', 'undo', 'redo', '|',
'bold', 'italic', 'underline', 'fontborder', 'strikethrough', 'superscript', 'subscript', 'removeformat', 'formatmatch', 'autotypeset', 'blockquote', 'pasteplain', '|', 'forecolor', 'backcolor', 'insertorderedlist', 'insertunorderedlist', 'selectall', 'cleardoc', '|',
'rowspacingtop', 'rowspacingbottom', 'lineheight', '|',
'customstyle', 'paragraph', 'fontfamily', 'fontsize', '|',
'directionalityltr', 'directionalityrtl', 'indent', '|',
'justifyleft', 'justifycenter', 'justifyright', 'justifyjustify', '|', 'touppercase', 'tolowercase', '|',
'link', 'unlink', 'anchor', '|', 'imagenone', 'imageleft', 'imageright', 'imagecenter', '|',
'simpleupload', 'insertimage', 'emotion', 'scrawl', 'insertvideo', 'music', 'attachment', 'map', 'gmap', 'insertframe', 'insertcode', 'webapp', 'pagebreak', 'template', 'background', '|',
'horizontal', 'date', 'time', 'spechars', 'snapscreen', 'wordimage', '|',
'inserttable', 'deletetable', 'insertparagraphbeforetable', 'insertrow', 'deleterow', 'insertcol', 'deletecol', 'mergecells', 'mergeright', 'mergedown', 'splittocells', 'splittorows', 'splittocols', 'charts', '|',
'print', 'preview', 'searchreplace', 'drafts', 'help'
],
initialFrameHeight: 400,
autoHeightEnabled: false
}
}
},
methods: {
onEditorReady(editor) {
console.log('编辑器初始化完成:', editor)
}
}
}
</script>
编辑器优化建议
- 建议设置合适的
initialFrameHeight避免页面跳动 - 可根据业务需求自定义工具栏按钮
- 注意图片上传路径配置,确保上传功能正常
错误页面组件
错误页面组件系统
框架提供了完整的错误页面组件,包括 403、404、500 等常见错误状态页面。
组件列表:
403.vue- 权限不足页面404.vue- 页面不存在页面500.vue- 服务器错误页面
使用示例:
<template>
<div>
<!-- 403 权限不足 -->
<error-403 v-if="errorCode === 403" />
<!-- 404 页面不存在 -->
<error-404 v-if="errorCode === 404" />
<!-- 500 服务器错误 -->
<error-500 v-if="errorCode === 500" />
</div>
</template>
<script>
import Error403 from '@/components/error-page/403.vue'
import Error404 from '@/components/error-page/404.vue'
import Error500 from '@/components/error-page/500.vue'
export default {
components: {
Error403,
Error404,
Error500
},
data() {
return {
errorCode: 404
}
}
}
</script>
错误页面样式:
错误页面定制
所有错误页面组件都支持自定义样式和文案,可在 src/components/error-page/ 目录下进行修改。
组件注册规范
全局组件注册:
// src/main.js
import BasicContainer from '@/components/basic-container/main.vue'
import BasicBlock from '@/components/basic-block/main.vue'
import BasicVideo from '@/components/basic-video/main.vue'
// 注册全局组件
Vue.component('basic-container', BasicContainer)
Vue.component('basic-block', BasicBlock)
Vue.component('basic-video', BasicVideo)
局部组件注册:
<template>
<div>
<Userinfo :avatar="user.avatar" :nickname="user.nickname" />
</div>
</template>
<script>
import Userinfo from '@/components/Userinfo/Userinfo.vue'
export default {
components: {
Userinfo
}
}
</script>
组件使用提醒
- 全局组件无需手动引入,可直接使用
- 业务组件建议使用局部注册,避免全局污染
- 组件命名遵循 kebab-case 规范
页面生成系统
页面生成器简介
框架提供了一套强大的页面生成系统,支持一键生成完整的业务模块,包括目录结构、页面文件、API接口、路由配置等。通过可视化的配置界面,开发者可以快速创建标准化的业务页面,大幅提升开发效率。
一键生成功能
系统入口与配置
访问方式:项目本地运行(npm run dev)开发环境成功后,可进入页面生成系统,支持一键生成目录、菜单、路由、按钮权限、自定义API等功能的生成,并可以在线可视化管理。
功能特点:
- 一键生成:支持完整的业务模块生成
- 可视化配置:基于 Avue 表单组件的友好界面
- 灵活定制:支持自定义API接口和按钮权限
- 智能分类:自动区分业务页面和基础页面
- 权限集成:自动生成按钮权限标识
- 自定义按钮:支持一键生成自定义按钮事件和API功能
- 模板代码:自动生成页面模板代码和事件处理方法
目录结构生成
生成流程:
开启目录模式:首先打开"是否为目录"开关
填写基础信息:
- 目录名称:显示在菜单中的名称
- 路由标识:英文标识,作为路由path使用
- 重定向路径:默认为
/${route}/${route},可自定义修改 - 选择图标:从常用目录图标库中选择
生成操作:点击生成按钮,一键生成目录结构
技术说明:
- 生成的是网络目录和路由目录,并非本地实际目录
- 所有生成的目录都默认为业务页面,放在
views下 - 框架限制目录只能一级,即目录下只能是菜单,无法嵌套目录
目录层级限制
当前框架设计为单级目录结构,目录下只能包含菜单页面,不支持多级目录嵌套。这是为了保持系统结构的简洁性。
菜单页面生成
生成流程:
关闭目录模式:默认"是否为目录"为关闭状态(页面模式)
填写页面信息:
- 页面名称:显示在菜单中的名称
- 父级目录:选择所属的目录
- 是否隐藏:控制路由是否显示到菜单中(如商品详情页)
- 路由标识:英文标识,自动同步API前缀
- 菜单图标:选择对应的图标
API配置同步:
- 路由标识填写时,自动同步API前缀(如
member) - 根据API前缀生成基础接口(增删改查、修改字段、下载模板、导入、导出)
- 支持自定义修改API配置
- 路由标识填写时,自动同步API前缀(如
按钮权限生成:
- 自动生成标准按钮(增删改查、下载模板、导入、导出)
- 自动生成按钮权限标识(如:
member_add)
文件生成:
- 生成本地目录结构
- 生成页面Vue文件
- 生成API接口文件
- 生成JS配置文件
- 在网络菜单中添加正确路由和按钮权限
- 在本地路由中添加对应页面路由
文件分类规则:
- 基础页面:放在
page目录下 - 业务页面:放在
views目录下 - 分类依据:根据选择的目录判断是否为业务路由
智能文件分类
系统会根据选择的父级目录自动判断页面类型,业务相关页面放在 views 目录,基础功能页面放在 page 目录,确保项目结构清晰。
重要注意事项
关键限制说明
- 路由标识唯一性:新增目录时,如果路由标识一致,则视为修改操作(传path不传id)
- 功能按钮同步:如果页面不包含下载模板、导入、导出功能,需要在按钮配置中取消,API配置会同步取消
- 路由修改限制:路由本地修改功能不可用,如需修改路由,需要本地同步修改
- 多余文件清理:如果生成了多余的路由和页面,需要本地删除代码和路由,网络菜单中可通过"管理"按钮进行管理
模板系统架构
模板系统说明
框架采用模板引擎机制,通过变量替换生成标准化的页面文件。目前API接口模板已被启用,采用直接文件生成方式,未依赖模板系统。
Vue页面模板
模板位置:src/template/page/template.vue
模板参数说明:
| 参数名 | 说明 | 示例 |
|---|---|---|
{{route}} | 路由标识,用于组件名称和路由路径 | member |
{{templatecode}} | 自定义模板代码,支持插槽定制 | 表格列配置等 |
{{methodscode}} | 自定义方法代码,支持业务逻辑扩展 | 自定义事件处理等 |
模板特点:
- 基于 Avue-crud 组件构建
- 支持自定义插槽(如用户信息展示)
- 集成状态切换功能
- 支持权限按钮控制
- 包含完整的CRUD操作
JavaScript配置模板
模板位置:src/template/page/template.js
配置参数说明:
公共参数:
// 默认页面配置
//默认页面列表请求参数
defaultParams: {
//用于默认请求列表getlist()时的请求参数
},
editBtn: true,
delBtn: true,
addBtn: true,
// 表格配置,如果是标准列表,则不需要配置
index: true, // 显示序号
// 表格列配置
column: [
{
label: '添加时间',
prop: 'add_time',
width: 180,
display: false,
type: 'datetime',
searchRange: true,
searchSpan: 6,
defaultTime: ['00:00:00', '23:59:59'],
search: true
},
{
label: 'ID',
prop: 'id',
width: 80,
disabled: true, // 不可编辑
addDisplay: false, // 新增时不显示
editDisplay: false, // 编辑时不显示
hide: true // 列表隐藏(如需显示可去掉)
},{
label: '状态',
prop: 'state',
type: 'select',
width: 80,
value:true,
addDisplay:false,
dicData: [
{ label: '启用', value: 1 },
{ label: '禁用', value: 0 }
],
search: true,
searchSpan: 6
},]
自定义参数(已注释,可在页面生成器中配置):
表格显示配置:
indexLabel: 序号标题(默认:'序号')stripe: 斑马纹(默认:true)border: 边框(默认:true)size: 表格大小(默认:'default')align: 对齐方式(默认:'center')headerAlign: 表头对齐(默认:'center')
分页参数配置:
pageNumber: 页码参数名(默认:'page')pageSize: 页大小参数名(默认:'limit')
数据响应配置:
res: 数据响应结构处理函数defaultParams: 默认请求参数对象,用于请求getList时自行默认带入的
字段配置: 表格和表单字段的详细配置项较多,建议参考 Avue 官方文档-表格列配置(column) 以及 Avue 官方文档-表单配置(form) 获取最新和最全的参数说明。一些要求见表格配置规范
API方法映射(可选):
list: 列表接口方法名(默认:'getList')add: 新增接口方法名(默认:'add')update: 更新接口方法名(默认:'update')del: 删除接口方法名(默认:'del')import: 导入接口方法名(默认:'importData')export: 导出接口方法名(默认:'exportData')down: 下载模板接口方法名(默认:'downTemplate')
配置优先级说明
- 页面生成器配置> 模板默认值
- 自定义参数> 公共参数
- 开发者可以根据业务需求在页面生成器中覆盖默认配置
配置示例:
自定义配置示例
// 在页面生成器中配置的自定义参数
{
defaultParams: {//将在请求列表时默认带入参数
status: 1,
type: 'active'
},
index: false, // 不显示序号
stripe: false, // 不显示斑马纹
size: 'small', // 小型表格
align: 'left', // 左对齐
pageNumber: 'page', // 自定义页码参数名
pageSize: 'limit', // 自定义页大小参数名
res: (res) => ({ // 自定义响应数据处理
data: res.data,
total: res.total
})
}
API接口模板
API模板弃用说明
API接口模板已被弃用,目前采用 直接生成API文件内容,不再依赖模板系统。
API文件生成规则:
生成逻辑:
- 文件头部:自动添加注释和导入语句
- 接口遍历:遍历配置的API数组
- 参数处理:根据请求方法自动选择参数名
- GET请求:使用
params参数 - POST请求:使用
data参数
- GET请求:使用
- 方法生成:生成标准化的请求函数
生成的标准接口:
getList: 获取列表数据add: 新增数据update: 更新数据del: 删除数据modify_field: 修改字段importData: 导入数据exportData: 导出数据downTemplate: 下载模板
API文件生成示例
// 自动生成的API文件结构
import request from '@/axios';
// 获取列表
export const getList = (params) => {
return request({
url: '/member/get_list',
method: 'get',
params
})
}
// 新增数据
export const add = (data) => {
return request({
url: '/member/add',
method: 'post',
data
})
}
自定义按钮生成功能
自定义按钮功能
页面生成器支持一键生成自定义按钮事件、API功能和权限配置,大幅提升开发效率。
功能特点:
- 智能按钮生成:根据按钮配置自动生成自定义操作按钮
- 事件处理生成:自动生成对应的事件处理方法
- 权限集成:自动生成按钮权限配置
- 模板代码生成:自动生成页面模板代码
- 方法命名规范:遵循驼峰命名规范
命名规则:
事件方法命名规范:
- 格式:
handle_${操作类型} - 示例:
handle_export、handle_import、handle_download
权限命名规范:
- 格式:
${模块名}_${操作类型} - 示例:
member_export、member_import、member_download
生成示例:自定义按钮
注意事项:
手动自定义按钮注意事项
- 权限配置:自定义按钮需要配置对应的权限标识
- 方法命名:自动生成的方法名遵循驼峰命名规范
- 模板集成:生成的代码会自动集成到页面模板中
- 权限验证:按钮显示会根据用户权限自动控制
- 事件处理:生成的方法需要根据业务需求进行完善
开发规范
开发规范说明
为了确保项目代码的一致性和可维护性,框架制定了一套完整的开发规范。遵循这些规范可以提升开发效率,减少代码错误,便于团队协作。
代码规范检查清单
接口命名与URL规范
标准接口命名
- 列表接口:
getList- 获取数据列表 - 新增接口:
add- 新增数据 - 编辑接口:
update- 更新数据 - 删除接口:
del- 删除数据 - 导入接口:
importData- 导入数据 - 导出接口:
exportData- 导出数据 - 下载模板:
downTemplate- 下载模板文件
GET /admin/{module}/get_list # 获取列表
POST /admin/{module}/add # 新增数据
POST /admin/{module}/edit # 编辑数据
POST /admin/{module}/del # 删除数据
POST /admin/{module}/import # 导入数据
POST /admin/{module}/export # 导出数据
GET /admin/{module}/template # 下载模板
GET /admin/{module}/get_select # 下拉选择接口
HTTP方法使用规范
- GET: 获取数据,参数通过query传递
- POST: 提交数据,参数通过body传递
- POST: 更新数据,参数通过body传递
- POST: 删除数据,参数通过body传递
响应数据结构
// 成功响应格式
{
"code": 200,
"datas": {
// 具体数据
}
}
分页数据格式
//分页数据格式
{
"code": 200,
"datas": {
'num': 100, // 总条数
'data': [] // 数据列表
}
}
下拉选择接口
//下拉选择接口格式
{
"code": 200,
'datas': [] // 数据列表
}
加密的使用
在 src/config/settings.js 中配置:
api: {
enableEncryption: true, // 开启加密
encryptionKey: 'your-key' // 加密密匙推荐为数据库密码
}
服务端加密配置
- 在数据库
database.php中关闭 debug 模式 encryptionKey必须与后端数据库密码一致- 确保前后端加密算法一致
API命名注意事项
- 接口名称必须使用驼峰命名法
- URL路径使用小写字母和连字符
- 保持接口命名的一致性和语义化
- 避免使用缩写,确保接口名称清晰易懂
按钮命名规范
标准按钮权限命名:
- 新增按钮:
${route}_add - 编辑按钮:
${route}_edit - 删除按钮:
${route}_del - 详情按钮:
${route}_detail - 导入按钮:
${route}_import - 导出按钮:
${route}_export - 下载模板:
${route}_down
自定义按钮命名:
- 格式:
${模块名}_${操作类型} - 示例:
member_export、article_publish、user_reset
按钮权限命名规范
按钮权限标识采用 模块名_操作类型 的命名方式,确保权限管理的规范性和可维护性。
字段命名规范
数据库字段命名:
- 使用下划线命名法(snake_case)
- 主键统一使用
id - 创建时间使用
add_time - 更新时间使用
update_time - 状态控制字段使用
state - 删除标记使用
is_del - 排序标识使用
sort - 外连表id使用
table_id
前端字段命名:
- 使用驼峰命名法(camelCase)
- 与后端字段对应,如:
addTime、updateTime - 布尔值字段使用
is前缀,如:isVisible、isEnabled
字段命名最佳实践
- 保持前后端字段命名的一致性
- 使用语义化的字段名称
- 避免使用缩写,确保字段名称清晰易懂
- 遵循框架的命名约定
文件组织规范
目录结构规范:
src/
├── page/ # 基础页面
│ ├── {module}/ # 模块目录
│ │ ├── {module}.vue # 页面文件
│ │ ├── {module}.js # 配置文件
│ │ └── api_{module}.js # API接口文件
├── views/ # 业务页面
│ ├── {module}/ # 模块目录
│ │ ├── {module}.vue # 页面文件
│ │ ├── {module}.js # 配置文件
│ │ └── api_{module}.js # API接口文件
└── components/ # 公共组件
├── basic-* # 基础组件
└── {module}/ # 业务组件
文件命名规范:
- 页面文件:
{module}.vue - 配置文件:
{module}.js - API文件:
api_{module}.js - 组件文件:
{ComponentName}.vue
文件组织最佳实践
- 按功能模块组织文件
- 保持目录结构的清晰性
- 遵循框架的目录约定
- 避免文件命名冲突
样式编写规范
CSS类命名规范:
- 使用 BEM 命名法(Block-Element-Modifier)
- 使用 kebab-case 命名
- 保持类名的语义化
样式组织规范:
// 组件样式
.component-name {
// 基础样式
&__element {
// 元素样式
}
&--modifier {
// 修饰符样式
}
}
// 全局样式
.global-class {
// 全局样式定义
}
样式编写原则:
- 模块化:样式按模块组织
- 可维护性:样式结构清晰
- 可扩展性:样式易于扩展
- 性能优化:避免样式冲突
样式编写最佳实践
- 使用 scoped 样式避免全局污染
- 合理使用 CSS 变量
- 遵循移动优先的响应式设计
- 保持样式的可读性和可维护性
字段合并展示规范
重要提醒
如果页面展示需要合并多个字段到一个表格单元格,一定要使用HTML转义,避免XSS攻击风险。
正确的合并字段方式:
// 表格列配置示例
{
label: '时间范围',
prop: 'time_range',
width: 200,
html: true, // 启用HTML渲染
formatter: (row, column, cellValue, index) => {
// 使用模板字符串安全地合并字段
return `<div>开始:${row.start_time}<br/>结束:${row.end_time}</div>`
}
}
错误的合并方式(存在安全风险):
// 错误示例 - 直接拼接字符串
formatter: (row, column, cellValue, index) => {
return '开始:' + row.start_time + '<br/>结束:' + row.end_time
}
// 错误示例 - 未启用HTML渲染
formatter: (row, column, cellValue, index) => {
return `<div>开始:${row.start_time}<br/>结束:${row.end_time}</div>`
}
安全合并字段的最佳实践:
- 启用HTML渲染:
{
html: true, // 必须设置为true
formatter: (row, column, cellValue, index) => {
// 格式化逻辑
}
}
- 使用模板字符串:
formatter: (row, column, cellValue, index) => {
return `<div class="time-range">
<span class="start">开始: ${row.start_time}</span>
<br/>
<span class="end">结束: ${row.end_time}</span>
</div>`
}
- 复杂字段合并示例:
formatter: (row, column, cellValue, index) => {
return `<div class="user-info">
<div class="name">姓名: ${row.name}</div>
<div class="phone">电话: ${row.phone}</div>
<div class="email">邮箱: ${row.email}</div>
</div>`
}
字段合并安全提示
- 必须设置
html: true:否则HTML标签会被转义显示 - 使用模板字符串:避免字符串拼接的安全风险
- 注意数据来源:确保字段数据来自可信源
- 避免用户输入:不要在formatter中直接使用用户输入的数据
安全警告
如果字段数据来自用户输入,必须进行HTML转义处理:
import { escape } from 'lodash-es'
formatter: (row, column, cellValue, index) => {
const safeStartTime = escape(row.start_time)
const safeEndTime = escape(row.end_time)
return `<div>开始:${safeStartTime}<br/>结束:${safeEndTime}</div>`
}
