包阅导读总结
1. 关键词:Vue3.4、Element-plus、后台管理系统、技术栈、配置
2. 总结:这是一个基于 Vue3.4 + Element-plus + Vite 搭建的通用后台管理模板,作者介绍了项目情况、技术栈、基本配置、按钮主题色配置、集成 mock.js 和 UnoCSS 等,还展示了 canvas 的基本使用案例。
3. 主要内容:
– 项目介绍
– 作者自行搭建的通用后台管理模板,包含基本效果,只供学习,存在 bug 请见谅。
– 技术栈
– 包括 Vue3、Element-plus、Vite 等。
– 项目基本配置
– 代码统一规范:.eslintrc.cjs、.prettierrc.json、.stylelintrc.cjs 配置。
– 按钮主题色配置
– 在 style/element/index.scss 中配置。
– 项目集成
– mock.js:生成随机数据,拦截 Ajax 请求。
– UnoCSS:即时原子 CSS 引擎。
– canvas 基本使用
– 通过案例展示基本使用,提供功能代码。
思维导图:
文章地址:https://mp.weixin.qq.com/s/E8kB3gwhsJk-0Y0KepJnnw
文章来源:mp.weixin.qq.com
作者:the局外人
发布时间:2024/7/20 2:00
语言:中文
总字数:4458字
预计阅读时间:18分钟
评分:82分
标签:Vue3,Element-plus,Vite,后台管理系统,前端开发
以下为原文内容
本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com
网上的后台管理系统模版一大堆,删起来麻烦,
xjy_admin
是我自己搭建的通用后台管理模板,并不断完善中……
🔥 前言
经过一段时间的打磨(具体忘了),迎来管理系统的第一个版本, 相较于其他后台管理模板,本后台管理模版只包含基本的刷新,全屏以及暗黑模式效果。本模板只供学习使用,难免会存在一些bug,还请见谅。
😀 项目介绍
一个基于Vue3.4+Element-plus+Vite
搭建的轻量级后台管理模板,本项目分一个登录接口和一个用户信息接口,并且采用mockjs模拟数据,有简单的权限划分。
✨ 效果展示
在线预览
xjy_admin
仓库地址Gitee
xjy_dmin
首页

🏅 技术栈
技术栈 | 描述 | 官网 |
---|---|---|
Vue3 | 渐进式JavaScript框架 | https://cn.vuejs.org/ |
Element-plus | 基于 Vue 3,面向设计师和开发者的组件库 | https://element-plus.org/zh-CN/ |
Vite | 前端构建工具 | https://vitejs.cn/vite3-cn/ |
Pinia | 符合直觉的 Vue.js 状态管理库 | https://pinia.web3doc.top/ |
Echarts | 一个基于 JavaScript 的开源可视化图表库 | https://echarts.apache.org/zh/index.html |
VueUse | 基于Vue组合式API的实用工具集 | https://www.vueusejs.com/ |
animate.css | 一个现成的跨浏览器动画库 | https://animate.style/ |
wangEditor | 开源 Web 富文本编辑器,开箱即用,配置简单 | https://www.wangeditor.com/ |
🌈 项目基本配置
项目全局配置

代码统一规范
.eslintrc.cjs
//@seehttps://eslint.bootcss.com/docs/rules/
module.exports={
env:{
browser:true,
es2021:true,
node:true,
jest:true,
},
/*指定如何解析语法*/
parser:'vue-eslint-parser',
/**优先级低于parse的语法解析配置*/
parserOptions:{
ecmaVersion:'latest',
sourceType:'module',
parser:'@typescript-eslint/parser',
jsxPragma:'React',
ecmaFeatures:{
jsx:true,
},
},
/*继承已有的规则*/
extends:[
'eslint:recommended',
'plugin:vue/vue3-essential',
'plugin:@typescript-eslint/recommended',
'plugin:prettier/recommended',
],
plugins:['vue','@typescript-eslint'],
/*
*"off"或0==>关闭规则
*"warn"或1==>打开的规则作为警告(不影响代码执行)
*"error"或2==>规则作为一个错误(代码不能执行,界面报错)
*/
rules:{
//eslint(https://eslint.bootcss.com/docs/rules/)
'no-var':'error',//要求使用let或const而不是var
'no-multiple-empty-lines':['warn',{max:1}],//不允许多个空行
'no-console':process.env.NODE_ENV==='production'?'error':'off',
'no-debugger':process.env.NODE_ENV==='production'?'error':'off',
'no-unexpected-multiline':'error',//禁止空余的多行
'no-useless-escape':'off',//禁止不必要的转义字符
//typeScript(https://typescript-eslint.io/rules)
'@typescript-eslint/no-unused-vars':'off',//禁止定义未使用的变量
'@typescript-eslint/prefer-ts-expect-error':'off',//禁止使用@ts-ignore
'@typescript-eslint/no-explicit-any':'off',//禁止使用any类型
'@typescript-eslint/no-non-null-assertion':'off',
'@typescript-eslint/no-namespace':'off',//禁止使用自定义TypeScript模块和命名空间。
'@typescript-eslint/semi':'off',
//eslint-plugin-vue(https://eslint.vuejs.org/rules/)
'vue/multi-word-component-names':'off',//要求组件名称始终为“-”链接的单词
'vue/script-setup-uses-vars':'error',//防止<scriptsetup>使用的变量<template>被标记为未使用
'vue/no-mutating-props':'off',//不允许组件prop的改变
'vue/attribute-hyphenation':'off',//对模板中的自定义组件强制执行属性命名样式
},
}
.prettierrc.json
{
"singleQuote":false,
"semi":false,
"bracketSpacing":true,
"htmlWhitespaceSensitivity":"ignore",
"endOfLine":"auto",
"trailingComma":"all",
"tabWidth":2
}
.stylelintrc.cjs
//@seehttps://stylelint.bootcss.com/
//美化css书写的样式
module.exports={
extends:[
'stylelint-config-standard',//配置stylelint拓展插件
'stylelint-config-html/vue',//配置vue中template样式格式化
'stylelint-config-standard-scss',//配置stylelintscss插件
'stylelint-config-recommended-vue/scss',//配置vue中scss样式格式化
'stylelint-config-recess-order',//配置stylelintcss属性书写顺序插件,
'stylelint-config-prettier',//配置stylelint和prettier兼容
],
overrides:[
{
files:['**/*.(scss|css|vue|html)'],
customSyntax:'postcss-scss',
},
{
files:['**/*.(html|vue)'],
customSyntax:'postcss-html',
},
],
ignoreFiles:[
'**/*.js',
'**/*.jsx',
'**/*.tsx',
'**/*.ts',
'**/*.json',
'**/*.md',
'**/*.yaml',
],
/**
*null=>关闭该规则
*always=>必须
*/
rules:{
'value-keyword-case':null,//在css中使用v-bind,不报错
'no-descending-specificity':null,//禁止在具有较高优先级的选择器后出现被其覆盖的较低优先级的选择器
'function-url-quotes':'always',//要求或禁止URL的引号"always(必须加上引号)"|"never(没有引号)"
'no-empty-source':null,//关闭禁止空源码
'selector-class-pattern':null,//关闭强制选择器类名的格式
'property-no-unknown':null,//禁止未知的属性(true为不允许)
'block-opening-brace-space-before':'always',//大括号之前必须有一个空格或不能有空白符
'value-no-vendor-prefix':null,//关闭属性值前缀--webkit-box
'property-no-vendor-prefix':null,//关闭属性前缀-webkit-mask
'selector-pseudo-class-no-unknown':[
//不允许未知的选择器
true,
{
ignorePseudoClasses:['global','v-deep','deep'],//忽略属性,修改element默认样式的时候能使用到
},
],
},
}
🎈 按钮主题色
在style/element/index.scss
中配置
/*只需要重写你需要的即可*/
@forward'element-plus/theme-chalk/src/common/var.scss'with($colors:(
'primary':(//主色
'base':#0F5197,
),
'success':(//成功色
'base':#199D33,
),
'info':('base':#4e4f51,
),
'warning':(//警告色
'base':#e26f03,
),
'danger':(//危险色
'base':#de2e06,
),
'error':(//危险色
'base':#de2e06,
),
));
vite.config.ts 配置
css:{
preprocessorOptions:{
scss:{
javascriptEnabled:true,
//自动导入定制化样式文件进行样式覆盖
additionalData:`
@use"@/styles/element/index.scss"as*;
@use"@/config/public.scss"as*;
`,
},
},
},
🔑 项目集成
mock.js
mock.js 生成随机数据,拦截 Ajax 请求
参考:mock.js 官网
安装
pnpminstall-Dvite-plugin-mockmockjs
vite.config.ts 配置
import{viteMockServe}from'vite-plugin-mock'
plugins:[
viteMockServe({
mockPath:"./src/mock",
//localEnabled:true,
})
]
UnoCSS
UnoCSS 是即时原子 CSS 引擎,通俗易懂的讲,就是在
template
模版中书写css
参考:UnoCSS中文文档
安装
pnpminstall-Dunocss
vite.config.ts 配置
复制代码
//vite.config.ts
importUnoCSSfrom'unocss/vite'
exportdefault{
plugins:[
UnoCSS({/*options*/}),
],
}
main.js中
//main.js
import"virtual:uno.css"
uno.config.js中可自行配置
//uno.config.ts
import{
defineConfig,
presetAttributify,
presetIcons,
presetTypography,
presetUno,
presetWebFonts,
transformerDirectives,
transformerVariantGroup,
}from"unocss"
exportdefaultdefineConfig({
shortcuts:{
"flex-center":"flexjustify-centeritems-center",
"flex-x-center":"flexjustify-center",
"flex-y-center":"flexitems-center",
"wh-full":"w-fullh-full",
"flex-x-between":"flexitems-centerjustify-between",
"flex-x-end":"flexitems-centerjustify-end",
"absolute-lt":"absoluteleft-0top-0",
"absolute-rt":"absoluteright-0top-0",
"fixed-lt":"fixedleft-0top-0",
"b1-red":"b-1border-solidb-red",
},
theme:{
colors:{
primary:"var(--el-color-primary)",
primary_dark:"var(--el-color-primary-light-5)",
},
},
presets:[
presetUno(),
presetAttributify(),
presetIcons(),
presetTypography(),
presetWebFonts({
fonts:{
//...
},
}),
],
transformers:[transformerDirectives(),transformerVariantGroup()],
})
VsCode
安装提示插件

插件效果预览

canvas 基本使用
这里通过一个案例对canvas展示了一个基本使用,仅供参考,以业务为主。

功能代码附上
<scriptsetuplang="ts">
importdebouncefrom"lodash/debounce"
import{message}from"@/Hooks/Element-plus"
import{nextTick,onMounted,ref,watch}from"vue"
importcat1from"../../assets/image/cat1.png"
importcat2from"../../assets/image/cat2.png"
importdog1from"../../assets/image/dog1.png"
importdog2from"../../assets/image/dog2.png"
importcanvaas_bgfrom"../../assets/image/canvas.webp"
constpicList=[dog1,cat2,dog2,cat1]asstring[]
constcolorList=[
"#fbd04f",
"#a8a1dc",
"#83b6da",
"#92c7ba",
"#f6a356",
"#5e5f61",
"#f98787",
]asstring[]
//canvas实例
constcanvas=ref()
//画布
constctx=ref()
//初始化背景图片
constinitCanvas_bg=async()=>{
awaitnewPromise((resolve,reject)=>{
//初始化画布
ctx.value=canvas.value.getContext("2d")!
constwidth=700
constheight=800
canvas.value.width=width
canvas.value.height=height
constimg=newImage()
img.onload=()=>{
ctx.value.drawImage(img,0,0,canvas.value.width,canvas.value.height)//绘制第一张图片
resolve("ok")
}
img.src=canvaas_bg
img.onerror=()=>{
reject("失败")
}
})
}
onMounted(async()=>{
try{
//初始化背景canvas
awaitinitCanvas_bg()
}catch(err:any){
message("error","初始化背景失败")
}
})
//选择图片
constpic_val=ref("")
constimgIndex=ref<number>()
constselectImg=async(pic:string,i:number)=>{
pic_val.value=pic
imgIndex.value=i
}
//选择背景色
constcolor_val=ref("")
constcolorIndex=ref<number>()
constselectBg=async(color:string,i:number)=>{
color_val.value=color
colorIndex.value=i
}
//输入值改变
constinput_val=ref("")
watch(
[()=>pic_val.value,()=>color_val.value,()=>input_val.value],
debounce(async(newVal)=>{
try{
//初始化背景canvas
awaitinitCanvas_bg()
let[newPic_val,newColor_val,newInut_val]=newVal
//先看背景颜色有没有
if(newColor_val){
//设置填充色
ctx.value.fillStyle=newColor_val
//绘制正方形
ctx.value.fillRect(99,75,342,477)
//再看文本
if(newInut_val){
ctx.value.fillStyle="black"
ctx.value.font=`35px隶书`
ctx.value.fillText("名:"+newInut_val,190,180)
}
//先铺背景在画图片
if(newPic_val){
constimg=newImage()
img.src=newPic_val
img.onload=()=>{
ctx.value.drawImage(img,100,202,350,350)//绘制选择的图片
}
}
}else{
//再看文本
if(newInut_val){
ctx.value.fillStyle="black"
ctx.value.font=`35px隶书`
ctx.value.fillText("名:"+newInut_val,190,180)
}
//先铺背景在画图片
if(newPic_val){
constimg=newImage()
img.src=newPic_val
img.onload=()=>{
ctx.value.drawImage(img,100,202,350,350)//绘制选择的图片
}
}
}
}catch(err:any){
message("error","初始化背景失败")
}
},100),
)
//导出图片
constoutPic=()=>{
letbase64=canvas.value.toDataURL()
letlink=document.createElement("a")
link.textContent="downloadimage"
link.href=base64
link.download="mypainting.jpeg"
link.click()
}
</script>
🏆 功能封装
Svg使用
//<template>中
<SvgIconicon=""width="15px"height="15px"color="#fff"/>
//vite中自行调整svg图标的储存位置
createSvgIconsPlugin({
iconDirs:[path.resolve(process.cwd(),"src/assets/svgs")],
symbolId:"icon-[dir]-[name]",
}),

svg图标存放位置为 assets/svgs
WangEditor编辑器集成
官网
//父组件中
<template>
<WangEditorv-model="editVal"height="calc(100vh-180px)"/>
</template>
<scriptsetuplang="ts">
import{ref,watchEffect}from"vue"
//初始值
consteditVal=ref("Hello!WangEditor")
watchEffect(()=>{
console.log(editVal.value)
})
</script>
<template>
<divclass="wang_edit":class="{dark:useSetting.dark}">
<Toolbar
id="toolbar-container"
:editor="editorRef"
:defaultConfig="toolbarConfig"
mode="default"
/>
<Editor
id="editor-container"
v-model="valueHtml"
:defaultConfig="editorConfig"
mode="default"
@onCreated="handleCreated"
/>
</div>
</template>
<scriptsetuplang="ts">
import{useSettingStore}from"@/stores/modules/setting"
import"@wangeditor/editor/dist/css/style.css"//引入css
import{onBeforeUnmount,ref,shallowRef,onMounted}from"vue"
import{Editor,Toolbar}from"@wangeditor/editor-for-vue"
constuseSetting=useSettingStore()
constprops=withDefaults(
defineProps<{
height:string
}>(),
{
height:"560px",
},
)
constvalueHtml=defineModel()
//编辑器实例,必须用shallowRef
consteditorRef=shallowRef()
consttoolbarConfig={}
consteditorConfig={
placeholder:"请输入内容...",
MENU_CONF:{
uploadImage:{
//自定义图片上传
asynccustomUpload(file:any,insertFn:any){
console.log(file,insertFn)
//调用后端接口,上传图片
//拿到上传路劲插入编辑器
//insertFn(url)
},
},
},
}
//组件销毁时,也及时销毁编辑器
onBeforeUnmount(()=>{
consteditor=editorRef.value
if(editor==null)return
editor.destroy()
})
consthandleCreated=(editor:any)=>{
editorRef.value=editor//记录editor实例,重要!
}
</script>
<stylescopedlang="scss">
.wang_edit{
border:1pxvar(--el-border-color-dark)solid;
border-radius:5px;
&.dark{
--w-e-textarea-bg-color:#333;
--w-e-toolbar-bg-color:#333;
--w-e-toolbar-color:gray;
--w-e-textarea-color:#fff;
}
#toolbar-container{
border-bottom:1pxsolidvar(--el-border-color-dark);
border-top-right-radius:5px;
border-top-left-radius:5px;
}
#editor-container{
height:v-bind("props.height")!important;
overflow:hidden;
border-bottom-right-radius:5px;
border-bottom-left-radius:5px;
}
}
</style>
👻 项目运行
项目启动
#安装
pnpmnpminstallpnpm-g
#安装依赖
pnpminstall
#项目运行
pnpmrundev
项目语法检查
#语法检查
pnpmrunlint
#语法修复
pnpmrunfix
#css美化
pnpmrunformat
项目打包
pnpmrunbuild
✍️ 写在最后
本篇从项目规范,项目运行,项目打包,详细讲述基于Vue3.4+Element-plus技术栈0到1搭建简洁,易懂的前端后台管理框架。如有问题欢迎指出。