👊 Vue3.4+Element-plus+Vite通用后台管理系统(自用)

网上的后台管理系统模版一大堆,删起来麻烦,xjy_admin是我自己搭建的通用后台管理模板,并不断完善中......

🔥 前言

经过一段时间的打磨(具体忘了),迎来管理系统的第一个版本, 相较于其他后台管理模板,本后台管理模版只包含基本的刷新,全屏以及暗黑模式效果。本模板只供学习使用,难免会存在一些bug,还请见谅。

😀 项目介绍

一个基于Vue3.4+Element-plus+Vite搭建的轻量级后台管理模板,本项目分一个登录接口和一个用户信息接口,并且采用mockjs模拟数据,有简单的权限划分。

✨ 效果展示

在线预览

xjy_admin

仓库地址Gitee

xjy_dmin

首页

🏅 技术栈

技术栈 描述 官网
Vue3 渐进式JavaScript框架 cn.vuejs.org/
Element-plus 基于 Vue 3,面向设计师和开发者的组件库 element-plus.org/zh-CN/
Vite 前端构建工具 vitejs.cn/vite3-cn/
Pinia 符合直觉的 Vue.js 状态管理库 pinia.web3doc.top/
tinymce 功能强大、所见即所得的富文本编辑器 tinymce.ax-z.cn/
Echarts 一个基于 JavaScript 的开源可视化图表库 echarts.apache.org/zh/index.ht...
VueUse 基于Vue组合式API的实用工具集 www.vueusejs.com/
animate.css 一个现成的跨浏览器动画库 animate.style/

🌈 项目基本配置

项目全局配置

代码统一规范

  • Eslint:语法规则和代码风格检查
  • Prettier:美化代码样式
  • Stylelint: CSS 统一规范和代码检测

.eslintrc.cjs

js 复制代码
// @see https://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', // 防止<script setup>使用的变量<template>被标记为未使用
        'vue/no-mutating-props': 'off', // 不允许组件 prop的改变
        'vue/attribute-hyphenation': 'off', // 对模板中的自定义组件强制执行属性命名样式
    },
}

.prettierrc.json

js 复制代码
{
  "singleQuote": false,
  "semi": false,
  "bracketSpacing": true,
  "htmlWhitespaceSensitivity": "ignore",
  "endOfLine": "auto",
  "trailingComma": "all",
  "tabWidth": 2
}

.stylelintrc.cjs

js 复制代码
// @see https://stylelint.bootcss.com/
// 美化css书写的样式
module.exports = {
    extends: [
      'stylelint-config-standard', // 配置stylelint拓展插件
      'stylelint-config-html/vue', // 配置 vue 中 template 样式格式化
      'stylelint-config-standard-scss', // 配置stylelint scss插件
      'stylelint-config-recommended-vue/scss', // 配置 vue 中 scss 样式格式化
      'stylelint-config-recess-order', // 配置stylelint css属性书写顺序插件,
      '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默认样式的时候能使用到
        },
      ],
    },
  }

🏆 功能封装

Svg使用

js 复制代码
// <template>中
<SvgIcon icon="" width="15px" height="15px" color="#fff" />
    
js 复制代码
//vite中自行调整svg图标的储存位置
   createSvgIconsPlugin({
        iconDirs: [path.resolve(process.cwd(), "src/assets/svgs")],
        symbolId: "icon-[dir]-[name]",
    }),

WangEditor编辑器集成

官网

js 复制代码
// 父组件中
<template>
  <WangEditor v-model="editVal" height="calc(100vh - 180px)" />
</template>

<script setup lang="ts">
import { ref, watchEffect } from "vue"
//初始值
const editVal = ref("Hello! WangEditor")
watchEffect(() => {
  console.log(editVal.value)
})
</script>
js 复制代码
<template>
  <div class="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>

<script setup lang="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"
const useSetting = useSettingStore()
const props = withDefaults(
  defineProps<{
    height: string
  }>(),
  {
    height: "560px",
  },
)

const valueHtml = defineModel()
// 编辑器实例,必须用 shallowRef
const editorRef = shallowRef()
const toolbarConfig = {}
const editorConfig = {
  placeholder: "请输入内容...",
  MENU_CONF: {
    uploadImage: {
      // 自定义图片上传
      async customUpload(file: any, insertFn: any) {
        console.log(file, insertFn)
        // 调用后端接口,上传图片
        // 拿到上传路劲插入编辑器
        // insertFn(url)
      },
    },
  },
}

// 组件销毁时,也及时销毁编辑器
onBeforeUnmount(() => {
  const editor = editorRef.value
  if (editor == null) return
  editor.destroy()
})

const handleCreated = (editor: any) => {
  editorRef.value = editor // 记录 editor 实例,重要!
}
</script>

<style scoped lang="scss">
.wang_edit {
  border: 1px var(--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: 1px solid var(--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>

👻 项目运行

项目启动

js 复制代码
# 安装 
pnpm npm install pnpm -g 

# 安装依赖
pnpm install 

# 项目运行
pnpm run dev

项目语法检查

js 复制代码
#语法检查
pnpm run lint

#语法修复
pnpm run fix

#css美化
pnpm run format

项目打包

js 复制代码
pnpm run build

✍️ 写在最后

本篇从项目规范,项目运行,项目打包,详细讲述基于Vue3.4+Element-plus技术栈0到1搭建简洁,易懂的前端后台管理框架。如有问题欢迎指出。

相关推荐
flash俊杰1 分钟前
Electron 桌面应用的进程模型:为什么 fork Next.js standalone
前端
沙蒿同学11 分钟前
我把架构约定编译成了会变红的测试:Wails v2 + Go + Vue3 桌面脚手架实战
前端·后端·github
cpolar技术支持14 分钟前
本地 Playwright 测试报告怎么远程复盘?Trace Viewer 跑起来后,用 cpolar 分享失败现场
前端·自动化测试·测试工具·cpolar·playwright
wordbaby14 分钟前
企业级后台管理系统路由设计与最佳实践指南
前端
胡志辉的博客24 分钟前
【完全开源】IP 纯净度检测 可一键部署到自己的CF
前端·javascript·chrome·ip·chromium
Hilaku1 小时前
作为面试官,我最怕遇到什么样的候选人?
前端·javascript·程序员
TiDi1 小时前
Pinia优化重复请求
前端
web3d5202 小时前
01-用 Leafletjs 10 分钟搭一张水利一张图(Vue3 + Vite 实战)
前端·javascript
晚安日记wanna2 小时前
Vue2 的 defineProperty 差在哪四层追问筛掉九成候选人
前端·vue.js·面试
TiDi2 小时前
吸顶导航交互实现
前端