【VUE】RuoYi-Vue3项目结构的分析

news2025/4/6 10:28:29

【VUE】RuoYi-Vue3项目结构的分析

  • 1. 项目地址
  • 2. RuoYi-Vue3项目结构
    • 2.1 整体结构
    • 2.2 package.json
      • 2.2.1 🧾 基本信息
      • 2.2.2 🔧 脚本命令(scripts)
      • 2.2.3 🌍 仓库信息
      • 2.2.4 📦 项目依赖(dependencies)
      • 2.2.5 开发依赖(devDependencies)
      • 2.2.6 🔧 scripts 字段详解
        • 2.2.6.1 🚀 dev: 开发模式启动
          • 🔧 示例:
          • 本质上是运行:
        • 2.2.6.2 🏗️ build:prod: 构建生产环境
          • 🔧 示例:
        • 2.2.6.3 build:stage: 构建预发布环境
          • 🔧 示例:
        • 2.2.6.4 👀 preview: 本地预览构建结果
          • 🔧 步骤:
        • 🧩 补充:环境变量文件示例
      • 2.2.7 ✅ 总结
    • 2.3 env文件
      • 2.3.1🔹 VITE_APP_TITLE
      • 2.3.2 🔹 VITE_APP_ENV
      • 2.3.3 🔹 VITE_APP_BASE_API
    • 2.4 index.html
      • 2.4.1 🧱 基本结构
      • 2.4.2 🔧 `<head>` 区域说明
      • 2.4.3 🎨 加载动画样式说明
      • 2.4.4 🚀 Vue 应用入口加载
      • 📝 总结功能
    • 2.5 vite.config.js
      • 2.5.1 🔧 文件头部
        • 📌 自定义 mode 怎么办?
      • 2.5.2 🧩 主体配置(defineConfig)
      • 2.5.3 📌 base 配置
      • 2.5.3 🔌 plugins 插件配置
      • 2.5.4 🧭 resolve 路径配置
      • 2.5.5 🌐 server 开发服务器配置
      • 2.5.6 🎨 css 配置(PostCSS 处理)
      • 2.5.7 ✅ 总结一下
    • 2.6 main.js
      • 2.6.1 📝 代码结构解析:
        • 2.6.1.1 创建 Vue 应用
        • 2.6.1.2 引入第三方库和插件
        • 2.6.1.3 引入全局样式
        • 2.6.1.4 引入应用所需的功能模块
        • 2.6.1.5 引入全局组件
        • 2.6.1.6 全局方法挂载
        • 2.6.1.7 全局组件注册
        • 2.6.1.8 路由、状态管理、插件注册
        • 2.6.1.9 注册自定义指令
        • 2.6.1.10 ElementPlus 配置
        • 2.6.1.11 挂载应用
        • 2.6.1.12 📚 小结
    • 2.7 settings.js
    • 2.8 App.vue
      • 2.8.1 模板部分` (<template>)`
      • 2.8.2 脚本部分 `(<script setup>)`
      • 2.8.3 整体结构与功能
    • 2.9 permission.js
  • 3. RuoYi-Vue3 api文件夹下的内容

1. 项目地址

见官方文档 https://doc.ruoyi.vip/ruoyi-vue/document/xmkz.html

2. RuoYi-Vue3项目结构

2.1 整体结构

在这里插入图片描述

2.2 package.json

{
  "name": "ruoyi",
  "version": "3.8.9",
  "description": "若依管理系统",
  "author": "若依",
  "license": "MIT",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build:prod": "vite build",
    "build:stage": "vite build --mode staging",
    "preview": "vite preview"
  },
  "repository": {
    "type": "git",
    "url": "https://gitee.com/y_project/RuoYi-Vue.git"
  },
  "dependencies": {
    "@element-plus/icons-vue": "2.3.1",
    "@vueup/vue-quill": "1.2.0",
    "@vueuse/core": "10.11.0",
    "axios": "0.28.1",
    "clipboard": "2.0.11",
    "echarts": "5.5.1",
    "element-plus": "2.7.6",
    "file-saver": "2.0.5",
    "fuse.js": "6.6.2",
    "js-beautify": "1.14.11",
    "js-cookie": "3.0.5",
    "jsencrypt": "3.3.2",
    "nprogress": "0.2.0",
    "pinia": "2.1.7",
    "splitpanes": "3.1.5",
    "vue": "3.4.31",
    "vue-cropper": "1.1.1",
    "vue-router": "4.4.0",
    "vuedraggable": "4.1.0"
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "5.0.5",
    "sass": "1.77.5",
    "unplugin-auto-import": "0.17.6",
    "unplugin-vue-setup-extend-plus": "1.0.1",
    "vite": "5.3.2",
    "vite-plugin-compression": "0.5.1",
    "vite-plugin-svg-icons": "2.0.1"
  }
}

2.2.1 🧾 基本信息

  "name": "ruoyi",
  "version": "3.8.9",
  "description": "若依管理系统",
  "author": "若依",
  "license": "MIT",
  "type": "module",

在这里插入图片描述

2.2.2 🔧 脚本命令(scripts)

"scripts": {
  "dev": "vite",
  "build:prod": "vite build",
  "build:stage": "vite build --mode staging",
  "preview": "vite preview"
}

在这里插入图片描述

2.2.3 🌍 仓库信息

"repository": {
  "type": "git",
  "url": "https://gitee.com/y_project/RuoYi-Vue.git"
}

指向源码托管的 Git 仓库(Gitee 上的 RuoYi-Vue 项目)。

2.2.4 📦 项目依赖(dependencies)

这些是运行时依赖,项目运行时需要用到的库:
在这里插入图片描述
在这里插入图片描述

2.2.5 开发依赖(devDependencies)

这些是开发时用的工具和插件:

在这里插入图片描述

2.2.6 🔧 scripts 字段详解

"scripts": {
  "dev": "vite",
  "build:prod": "vite build",
  "build:stage": "vite build --mode staging",
  "preview": "vite preview"
}

这些命令你可以通过终端运行,比如:

npm run dev
# 或者
yarn dev
2.2.6.1 🚀 dev: 开发模式启动
"dev": "vite"
  • 启动开发服务器
  • 默认监听 http://localhost:5173(可配置)
  • 实时热更新(HMR)
  • 使用 .env.development 配置文件(如果存在)
🔧 示例:

npm run dev

本质上是运行:

vite

2.2.6.2 🏗️ build:prod: 构建生产环境
"build:prod": "vite build"
  • 打包生成生产环境的静态文件

  • 输出目录:默认是 dist/

  • 使用 .env.production 配置文件

  • 会自动做:

  • Tree Shaking(移除无用代码)

  • 压缩(JS/CSS/html)

  • 资源版本化(加 hash)

🔧 示例:

npm run build:prod

📁 构建完成后,你可以部署 dist/ 到 Nginx、Apache、Node 服务器等。

2.2.6.3 build:stage: 构建预发布环境
"build:stage": "vite build --mode staging"
  • 用于 预发布环境 构建
  • 使用 .env.staging 环境变量文件
  • 可以用于连接测试服务器或 UAT 环境
🔧 示例:
npm run build:stage

注意:Vite 会根据 --mode 参数加载对应.env.[mode]配置文件,例如:

  • .env.staging
  • .env.production
2.2.6.4 👀 preview: 本地预览构建结果
"preview": "vite preview"
  • 用来本地 预览打包后的项目
  • 启动一个本地静态服务器,访问打包结果
  • 不再是开发服务器!是查看最终构建效果。
🔧 步骤:
npm run build:prod
npm run preview

默认访问地址:http://localhost:4173

🧩 补充:环境变量文件示例

你可以在根目录创建多个 .env 文件来支持不同环境:

.env.development   # 开发环境
.env.staging       # 预发布环境
.env.production    # 生产环境

这些文件里可以定义变量,比如:

VITE_APP_TITLE=RuoYi 管理后台
VITE_BASE_API=https://api.example.com

在代码中这样访问:

import.meta.env.VITE_APP_TITLE

2.2.7 ✅ 总结

这个 package.json 是 Vue 3 企业后台管理系统(若依前端)的核心配置文件,结合了:

  • Vue 3 + Vite 的现代构建架构;
  • Element Plus 提供强大的 UI 组件;
  • Pinia 管理状态;
  • 多种工具库(图表、剪贴板、富文本、拖拽等)提升开发效率;
  • Vite 插件自动化构建优化。

2.3 env文件

.env.development

# 页面标题
VITE_APP_TITLE = 若依管理系统

# 开发环境配置
VITE_APP_ENV = 'development'

# 若依管理系统/开发环境
VITE_APP_BASE_API = '/dev-api'

2.3.1🔹 VITE_APP_TITLE

VITE_APP_TITLE = 若依管理系统

  • 用于设置项目标题
  • 可在 index.html 或 Vue 页面中使用,比如动态修改 <title>

在 HTML 中使用(通过 Vite 的 HTML 插值语法):

<title><%= VITE_APP_TITLE %></title>

或者在 JS 中使用:

document.title = import.meta.env.VITE_APP_TITLE;

2.3.2 🔹 VITE_APP_ENV

VITE_APP_ENV = 'development'
  • 表示当前运行的环境(开发、测试、生产等)
  • 通常用于代码中进行环境判断:
if (import.meta.env.VITE_APP_ENV === 'development') {
  console.log('当前是开发环境');
}

⚠️ 注意:值中用的引号 ‘development’ 会被作为字符串一部分保留。更推荐写法是不加引号:

VITE_APP_ENV=development

2.3.3 🔹 VITE_APP_BASE_API

VITE_APP_BASE_API = '/dev-api'
  • 设置请求 API 的基础路径
  • 会用于 axios 或 fetch 等接口请求中

假设你这样配置 axios:

const service = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API,
});

那么访问 /api/user/list,实际发送的请求就是:

http://localhost:5173/dev-api/user/list

这通常结合 Vite 的代理配置 实现跨域转发,比如在 vite.config.js 中:

server: {
  proxy: {
    '/dev-api': {
      target: 'http://localhost:8080',
      changeOrigin: true,
      rewrite: path => path.replace(/^\/dev-api/, '')
    }
  }
}

这样前端写 /dev-api/user/list,Vite 会自动代理请求到后端 /user/list 接口。

在这里插入图片描述

2.4 index.html

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="renderer" content="webkit">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  <link rel="icon" href="/favicon.ico">
  <title>若依管理系统</title>
  <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
  <style>
    html,
    body,
    #app {
      height: 100%;
      margin: 0px;
      padding: 0px;
    }

    .chromeframe {
      margin: 0.2em 0;
      background: #ccc;
      color: #000;
      padding: 0.2em 0;
    }

    #loader-wrapper {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      z-index: 999999;
    }

    #loader {
      display: block;
      position: relative;
      left: 50%;
      top: 50%;
      width: 150px;
      height: 150px;
      margin: -75px 0 0 -75px;
      border-radius: 50%;
      border: 3px solid transparent;
      border-top-color: #FFF;
      -webkit-animation: spin 2s linear infinite;
      -ms-animation: spin 2s linear infinite;
      -moz-animation: spin 2s linear infinite;
      -o-animation: spin 2s linear infinite;
      animation: spin 2s linear infinite;
      z-index: 1001;
    }

    #loader:before {
      content: "";
      position: absolute;
      top: 5px;
      left: 5px;
      right: 5px;
      bottom: 5px;
      border-radius: 50%;
      border: 3px solid transparent;
      border-top-color: #FFF;
      -webkit-animation: spin 3s linear infinite;
      -moz-animation: spin 3s linear infinite;
      -o-animation: spin 3s linear infinite;
      -ms-animation: spin 3s linear infinite;
      animation: spin 3s linear infinite;
    }

    #loader:after {
      content: "";
      position: absolute;
      top: 15px;
      left: 15px;
      right: 15px;
      bottom: 15px;
      border-radius: 50%;
      border: 3px solid transparent;
      border-top-color: #FFF;
      -moz-animation: spin 1.5s linear infinite;
      -o-animation: spin 1.5s linear infinite;
      -ms-animation: spin 1.5s linear infinite;
      -webkit-animation: spin 1.5s linear infinite;
      animation: spin 1.5s linear infinite;
    }


    @-webkit-keyframes spin {
      0% {
        -webkit-transform: rotate(0deg);
        -ms-transform: rotate(0deg);
        transform: rotate(0deg);
      }

      100% {
        -webkit-transform: rotate(360deg);
        -ms-transform: rotate(360deg);
        transform: rotate(360deg);
      }
    }

    @keyframes spin {
      0% {
        -webkit-transform: rotate(0deg);
        -ms-transform: rotate(0deg);
        transform: rotate(0deg);
      }

      100% {
        -webkit-transform: rotate(360deg);
        -ms-transform: rotate(360deg);
        transform: rotate(360deg);
      }
    }


    #loader-wrapper .loader-section {
      position: fixed;
      top: 0;
      width: 51%;
      height: 100%;
      background: #7171C6;
      z-index: 1000;
      -webkit-transform: translateX(0);
      -ms-transform: translateX(0);
      transform: translateX(0);
    }

    #loader-wrapper .loader-section.section-left {
      left: 0;
    }

    #loader-wrapper .loader-section.section-right {
      right: 0;
    }


    .loaded #loader-wrapper .loader-section.section-left {
      -webkit-transform: translateX(-100%);
      -ms-transform: translateX(-100%);
      transform: translateX(-100%);
      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
    }

    .loaded #loader-wrapper .loader-section.section-right {
      -webkit-transform: translateX(100%);
      -ms-transform: translateX(100%);
      transform: translateX(100%);
      -webkit-transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
      transition: all 0.7s 0.3s cubic-bezier(0.645, 0.045, 0.355, 1.000);
    }

    .loaded #loader {
      opacity: 0;
      -webkit-transition: all 0.3s ease-out;
      transition: all 0.3s ease-out;
    }

    .loaded #loader-wrapper {
      visibility: hidden;
      -webkit-transform: translateY(-100%);
      -ms-transform: translateY(-100%);
      transform: translateY(-100%);
      -webkit-transition: all 0.3s 1s ease-out;
      transition: all 0.3s 1s ease-out;
    }

    .no-js #loader-wrapper {
      display: none;
    }

    .no-js h1 {
      color: #222222;
    }

    #loader-wrapper .load_title {
      font-family: 'Open Sans';
      color: #FFF;
      font-size: 19px;
      width: 100%;
      text-align: center;
      z-index: 9999999999999;
      position: absolute;
      top: 60%;
      opacity: 1;
      line-height: 30px;
    }

    #loader-wrapper .load_title span {
      font-weight: normal;
      font-style: italic;
      font-size: 13px;
      color: #FFF;
      opacity: 0.5;
    }
  </style>
</head>

<body>
  <div id="app">
    <div id="loader-wrapper">
      <div id="loader"></div>
      <div class="loader-section section-left"></div>
      <div class="loader-section section-right"></div>
      <div class="load_title">正在加载系统资源,请耐心等待</div>
    </div>
  </div>
  <script type="module" src="/src/main.js"></script>
</body>

</html>

index.html 是 Vue3 + Vite 项目的入口 HTML 文件,用于 定义页面结构、加载样式、初始化页面,并最终挂载 Vue 应用。 它是 Vite 应用的基础模板,加载完毕后会将 #app 替换为渲染好的 Vue 内容。

2.4.1 🧱 基本结构

<!DOCTYPE html>
<html>
<head> ... </head>
<body>
  <div id="app"> ... </div>
  <script type="module" src="/src/main.js"></script>
</body>
</html>
  • <!DOCTYPE html>:声明文档类型为 HTML5。
  • <div id="app">:Vue 应用的挂载点,对应 main.js 中的 createApp(App).mount('#app')
  • <script type="module">:使用 ES Module 加载入口文件 src/main.js

2.4.2 🔧 <head> 区域说明

✅ 页面设置相关

<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="/favicon.ico">
<title>若依管理系统</title>
  • 设置页面字符编码、兼容性、渲染方式。
  • <meta viewport> 用于移动端响应式适配。
  • <title> 设置网页标题(可以用环境变量动态设置)。
  • favicon.ico 设置浏览器 tab 图标。

2.4.3 🎨 加载动画样式说明

整个 <style> 块实现了一个 加载中的页面动画效果,在 Vue 内容加载前提供视觉反馈。

<div id="loader-wrapper">
  <div id="loader"></div>
  <div class="loader-section section-left"></div>
  <div class="loader-section section-right"></div>
  <div class="load_title">正在加载系统资源,请耐心等待</div>
</div>

这些元素组合在一起构成了一个炫酷的加载动画,包括:
在这里插入图片描述

样式细节

  • #loader是核心旋转圈,通过多个 :before、:after 层实现三层圈圈动画。
  • .loaded 类会触发消失动画,表示 Vue 应用加载完成。
  • .no-js 是备用样式:如果 JS 不可用,隐藏 loading。

2.4.4 🚀 Vue 应用入口加载

<script type="module" src="/src/main.js"></script>
  • 启动 Vue 应用的入口文件。
  • 一般内容类似于:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

createApp(App).use(router).use(store).mount('#app')

加载完成后,会替换掉 <div id="app"> 内容,把整个 Vue 项目渲染进去。

📝 总结功能

在这里插入图片描述

2.5 vite.config.js

import { defineConfig, loadEnv } from 'vite'
import path from 'path'
import createVitePlugins from './vite/plugins'

// https://vitejs.dev/config/
export default defineConfig(({ mode, command }) => {
  const env = loadEnv(mode, process.cwd())
  const { VITE_APP_ENV } = env
  return {
    // 部署生产环境和开发环境下的URL。
    // 默认情况下,vite 会假设你的应用是被部署在一个域名的根路径上
    // 例如 https://www.ruoyi.vip/。如果应用被部署在一个子路径上,你就需要用这个选项指定这个子路径。例如,如果你的应用被部署在 https://www.ruoyi.vip/admin/,则设置 baseUrl 为 /admin/。
    base: VITE_APP_ENV === 'production' ? '/' : '/',
    plugins: createVitePlugins(env, command === 'build'),
    resolve: {
      // https://cn.vitejs.dev/config/#resolve-alias
      alias: {
        // 设置路径
        '~': path.resolve(__dirname, './'),
        // 设置别名
        '@': path.resolve(__dirname, './src')
      },
      // https://cn.vitejs.dev/config/#resolve-extensions
      extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
    },
    // vite 相关配置
    server: {
      port: 80,
      host: true,
      open: true,
      proxy: {
        // https://cn.vitejs.dev/config/#server-proxy
        '/dev-api': {
          target: 'http://localhost:8080',
          changeOrigin: true,
          rewrite: (p) => p.replace(/^\/dev-api/, '')
        }
      }
    },
    //fix:error:stdin>:7356:1: warning: "@charset" must be the first rule in the file
    css: {
      postcss: {
        plugins: [
          {
            postcssPlugin: 'internal:charset-removal',
            AtRule: {
              charset: (atRule) => {
                if (atRule.name === 'charset') {
                  atRule.remove();
                }
              }
            }
          }
        ]
      }
    }
  }
})

这份 vite.config.js 是 Vite 项目的核心配置文件,它配置了构建、开发服务器、路径别名、插件、代理、CSS处理等行为。 这个文件是 若依管理系统 Vue3 + Vite 版本 中的重要组成部分。

2.5.1 🔧 文件头部

import { defineConfig, loadEnv } from 'vite'
import path from 'path'
import createVitePlugins from './vite/plugins'
  • defineConfig:Vite 提供的辅助函数,可以获得类型提示。
  • loadEnv(mode, root):根据当前模式加载 .env.[mode] 文件内容。 loadEnv 是 Vite 官方提供的函数,不是你自己写的,也不是第三方包,它来自于 vite 包本身。执行npm run dev 那么mode === ‘development’
    vite 命令(开发模式) ⇒ mode = ‘development’
    vite build 命令(生产构建) ⇒ mode = ‘production’
  • path:Node.js 内置模块,用于路径拼接。
  • createVitePlugins:引入封装好的插件函数(如 AutoImport、SVG 图标、压缩等)。
📌 自定义 mode 怎么办?

如果你想用别的环境变量文件,比如 .env.staging,你可以这样写:

vite --mode staging

或者:

"scripts": {
  "build:stage": "vite build --mode staging"
}

对应的执行命令就是
npm run build:stage

2.5.2 🧩 主体配置(defineConfig)

export default defineConfig(({ mode, command }) => {
  const env = loadEnv(mode, process.cwd()) // 加载环境变量
  const { VITE_APP_ENV } = env
  • mode:当前环境(如 development、production)。
  • command:当前操作(如 serve 或 build)。
  • 使用 loadEnv() 加载 .env.* 文件内容并解构出 VITE_APP_ENV

2.5.3 📌 base 配置

base: VITE_APP_ENV === 'production' ? '/' : '/',
  • 设置打包后资源的 公共路径
  • 如果部署在子目录下,这里应该设置成 /子目录名/
  • 若依项目默认设置为根路径 /

2.5.3 🔌 plugins 插件配置

plugins: createVitePlugins(env, command === 'build'),
  • 使用封装好的插件加载器,传入环境变量和是否是构建命令
  • 常见插件可能包括:
unplugin-auto-import 自动导入
vite-plugin-svg-icons SVG 图标支持
vite-plugin-compression gzip 压缩等

2.5.4 🧭 resolve 路径配置

resolve: {
  alias: {
    '~': path.resolve(__dirname, './'),
    '@': path.resolve(__dirname, './src')
  },
  extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
}

设置路径别名:

  • ~ 代表根路径
  • @ 代表 src/ 目录,方便引用文件
  • extensions:导入文件时可省略的后缀名(默认已经包含大部分常用的)

2.5.5 🌐 server 开发服务器配置

server: {
  port: 80,
  host: true,
  open: true,
  proxy: {
    '/dev-api': {
      target: 'http://localhost:8080',
      changeOrigin: true,
      rewrite: (p) => p.replace(/^\/dev-api/, '')
    }
  }
}
  • port: 80:开发服务器端口,设置为 80
  • host: true:支持使用 IP 访问(0.0.0.0)
  • open: true:自动打开浏览器
  • proxy:配置代理,解决开发环境跨域问题
    • 请求 /dev-api/xxx 会被代理到 http://localhost:8080/xxx

2.5.6 🎨 css 配置(PostCSS 处理)

css: {
  postcss: {
    plugins: [
      {
        postcssPlugin: 'internal:charset-removal',
        AtRule: {
          charset: (atRule) => {
            if (atRule.name === 'charset') {
              atRule.remove()
            }
          }
        }
      }
    ]
  }
}
  • 作用:去除 CSS 中多余的@charset规则,避免构建时出现警告或错误:
warning: "@charset" must be the first rule in the file
  • 些插件(比如 element-plus 的样式)可能导致这个问题,所以主动清理。

2.5.7 ✅ 总结一下

在这里插入图片描述

2.6 main.js

import { createApp } from 'vue'

import Cookies from 'js-cookie'

import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import 'element-plus/theme-chalk/dark/css-vars.css'
import locale from 'element-plus/es/locale/lang/zh-cn'

import '@/assets/styles/index.scss' // global css

import App from './App'
import store from './store'
import router from './router'
import directive from './directive' // directive

// 注册指令
import plugins from './plugins' // plugins
import { download } from '@/utils/request'

// svg图标
import 'virtual:svg-icons-register'
import SvgIcon from '@/components/SvgIcon'
import elementIcons from '@/components/SvgIcon/svgicon'

import './permission' // permission control

import { useDict } from '@/utils/dict'
import { parseTime, resetForm, addDateRange, handleTree, selectDictLabel, selectDictLabels } from '@/utils/ruoyi'

// 分页组件
import Pagination from '@/components/Pagination'
// 自定义表格工具组件
import RightToolbar from '@/components/RightToolbar'
// 富文本组件
import Editor from "@/components/Editor"
// 文件上传组件
import FileUpload from "@/components/FileUpload"
// 图片上传组件
import ImageUpload from "@/components/ImageUpload"
// 图片预览组件
import ImagePreview from "@/components/ImagePreview"
// 字典标签组件
import DictTag from '@/components/DictTag'

const app = createApp(App)

// 全局方法挂载
app.config.globalProperties.useDict = useDict
app.config.globalProperties.download = download
app.config.globalProperties.parseTime = parseTime
app.config.globalProperties.resetForm = resetForm
app.config.globalProperties.handleTree = handleTree
app.config.globalProperties.addDateRange = addDateRange
app.config.globalProperties.selectDictLabel = selectDictLabel
app.config.globalProperties.selectDictLabels = selectDictLabels

// 全局组件挂载
app.component('DictTag', DictTag)
app.component('Pagination', Pagination)
app.component('FileUpload', FileUpload)
app.component('ImageUpload', ImageUpload)
app.component('ImagePreview', ImagePreview)
app.component('RightToolbar', RightToolbar)
app.component('Editor', Editor)

app.use(router)
app.use(store)
app.use(plugins)
app.use(elementIcons)
app.component('svg-icon', SvgIcon)

directive(app)

// 使用element-plus 并且设置全局的大小
app.use(ElementPlus, {
  locale: locale,
  // 支持 large、default、small
  size: Cookies.get('size') || 'default'
})

app.mount('#app')

2.6.1 📝 代码结构解析:

2.6.1.1 创建 Vue 应用
import { createApp } from 'vue'
const app = createApp(App)
  • createApp 是 Vue3 中用来创建应用实例的函数。
  • App 是根组件,通常是 src/App.vue,它是整个应用的起始点。
2.6.1.2 引入第三方库和插件
import Cookies from 'js-cookie'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import 'element-plus/theme-chalk/dark/css-vars.css'
import locale from 'element-plus/es/locale/lang/zh-cn'
  • Cookies:用于管理 cookies,例如获取当前主题、界面大小等。
  • ElementPlus:UI 组件库,提供丰富的组件和样式,支持主题、国际化等功能。
  • 通过 import 加载了 ElementPlus 的样式以及中文语言包。
2.6.1.3 引入全局样式
import '@/assets/styles/index.scss' // global css
  • 这行代码引入了全局的样式文件,通常是用来定义应用级别的样式。
2.6.1.4 引入应用所需的功能模块
import store from './store'
import router from './router'
import directive from './directive' // directive
import plugins from './plugins' // plugins
import { download } from '@/utils/request'
import './permission' // permission control
  • store:Vuex 的状态管理(假设应用中使用了 Vuex)。
  • router:Vue Router 路由配置。
  • directive:自定义指令。
  • plugins:应用的插件,如全局功能的注册(如事件总线等)。
  • download:可能是封装好的下载方法,用于下载文件等。
2.6.1.5 引入全局组件
import SvgIcon from '@/components/SvgIcon'
import Pagination from '@/components/Pagination'
import RightToolbar from '@/components/RightToolbar'
import Editor from "@/components/Editor"
import FileUpload from "@/components/FileUpload"
import ImageUpload from "@/components/ImageUpload"
import ImagePreview from "@/components/ImagePreview"
import DictTag from '@/components/DictTag'
  • 引入了一些自定义的全局组件,例如分页、富文本、文件上传、图片上传、字典标签等组件。
2.6.1.6 全局方法挂载
app.config.globalProperties.useDict = useDict
app.config.globalProperties.download = download
app.config.globalProperties.parseTime = parseTime
app.config.globalProperties.resetForm = resetForm
app.config.globalProperties.handleTree = handleTree
app.config.globalProperties.addDateRange = addDateRange
app.config.globalProperties.selectDictLabel = selectDictLabel
app.config.globalProperties.selectDictLabels = selectDictLabels
  • 将一些工具函数挂载到 Vue 应用的全局属性上,方便在任何组件中访问。例如,useDict 是处理字典标签的方法,download 是下载方法等。
2.6.1.7 全局组件注册
app.component('DictTag', DictTag)
app.component('Pagination', Pagination)
app.component('FileUpload', FileUpload)
app.component('ImageUpload', ImageUpload)
app.component('ImagePreview', ImagePreview)
app.component('RightToolbar', RightToolbar)
app.component('Editor', Editor)
  • 通过 app.component 注册全局组件,这样在整个应用中可以直接使用这些组件,而无需在每个单独的组件中引入。
2.6.1.8 路由、状态管理、插件注册
app.use(router)
app.use(store)
app.use(plugins)
app.use(elementIcons)
app.component('svg-icon', SvgIcon)
  • app.use(router):注册路由,所有页面的导航和路由逻辑都通过 Vue Router 进行。
  • app.use(store):注册 Vuex 状态管理,管理整个应用的状态。
  • app.use(plugins):注册自定义插件(如应用的全局功能、插件等)。
  • app.component(‘svg-icon’, SvgIcon):注册 SvgIcon 作为全局组件,以便在任何地方使用。
2.6.1.9 注册自定义指令
directive(app)
  • directive 函数用于注册应用中的自定义指令。这些指令可以在整个项目中复用。
2.6.1.10 ElementPlus 配置
app.use(ElementPlus, {
  locale: locale,
  size: Cookies.get('size') || 'default'
})
  • 通过 app.use(ElementPlus) 安装 ElementPlus UI 组件库,并配置语言和大小。
  • 默认的界面大小是从 Cookies 中获取的,如果没有设置则使用 ‘default’。
2.6.1.11 挂载应用
  • 最后,应用会被挂载到 HTML 中的 #app 元素上,表示 Vue 实例已经成功启动并渲染。
2.6.1.12 📚 小结
  • main.js 主要是 Vue 3 应用的初始化文件,涉及到全局插件、组件、方法的注册和配置。
  • 核心流程是:创建 Vue 应用 → 挂载全局资源(如路由、状态管理、UI 组件等) → 启动应用。

2.7 settings.js

settings.js 是一个配置文件,通常用于 Vue.js 或其他前端应用中, 集中管理一些全局的应用设置,如主题、显示的组件、错误日志等。 它的目的是使应用的配置更加灵活和易于管理。

export default {
  /**
   * 网页标题
   */
  title: import.meta.env.VITE_APP_TITLE,
  
  /**
   * 侧边栏主题 深色主题theme-dark,浅色主题theme-light
   */
  sideTheme: 'theme-dark',
  
  /**
   * 是否系统布局配置
   */
  showSettings: true,

  /**
   * 是否显示顶部导航
   */
  topNav: false,

  /**
   * 是否显示 tagsView
   */
  tagsView: true,

  /**
   * 是否固定头部
   */
  fixedHeader: false,

  /**
   * 是否显示logo
   */
  sidebarLogo: true,

  /**
   * 是否显示动态标题
   */
  dynamicTitle: false,

  /**
   * @type {string | array} 'production' | ['production', 'development']
   * @description Need show err logs component.
   * The default is only used in the production env
   * If you want to also use it in dev, you can pass ['production', 'development']
   */
  errorLog: 'production'
}

2.8 App.vue

App.vue 是 Vue 3 应用的根组件,通常作为整个应用的入口。这个文件负责渲染主要的视图和组件,同时处理一些全局设置,如主题、布局等。

<template>
  <router-view />
</template>

<script setup>
import useSettingsStore from '@/store/modules/settings'
import { handleThemeStyle } from '@/utils/theme'

onMounted(() => {
  nextTick(() => {
    // 初始化主题样式
    handleThemeStyle(useSettingsStore().theme)
  })
})
</script>

2.8.1 模板部分 (<template>)

<template>
  <router-view />
</template>
  • <router-view /> 是 Vue Router 提供的一个占位符组件,它会渲染与当前路由匹配的组件。在单页面应用(SPA)中,router-view 就是路由展示的地方。每当路由变化时,router-view 会根据新的路径自动加载相应的组件。
  • 例如,假设路由是 /home,当你导航到这个路径时,router-view 就会显示与 /home 路径相关联的组件。

2.8.2 脚本部分 (<script setup>)

<script setup>
import useSettingsStore from '@/store/modules/settings'
import { handleThemeStyle } from '@/utils/theme'

onMounted(() => {
  nextTick(() => {
    // 初始化主题样式
    handleThemeStyle(useSettingsStore().theme)
  })
})
</script>
  • import useSettingsStore from '@/store/modules/settings':

    • 这里导入了一个自定义的 Vuex store 模块 settings,通过它来获取应用的设置,比如主题(theme)。
  • import { handleThemeStyle } from '@/utils/theme':

    • 导入了一个工具函数 handleThemeStyle,它负责处理主题样式(如深色或浅色主题)。该函数会应用选定的主题样式。
  • onMounted():

    • onMounted 是 Vue 3 中的生命周期钩子,表示组件挂载到 DOM 后会执行这个回调函数。在这个函数中,使用了 nextTick 来确保 DOM 更新完成后再执行初始化操作。
  • nextTick():

    • nextTick 是 Vue 提供的一个方法,用来在下次 DOM 更新循环结束后执行延迟回调。在这里,它确保在组件挂载完成并且 DOM 已经更新后,才去初始化主题样式。
  • handleThemeStyle(useSettingsStore().theme):

    • 这行代码获取 settings store 中的 theme 值,并通过 handleThemeStyle函数来设置页面的主题样式。这是应用的主题初始化逻辑,确保页面在加载时使用正确的样式(如深色或浅色模式)。

2.8.3 整体结构与功能

  • 根组件:App.vue 是整个应用的根组件,它通过 <router-view /> 加载并显示与当前路由匹配的组件。路由配置和组件内容的切换都由 Vue Router 来管理。

  • 主题初始化:在 onMounted 钩子中,应用会读取 Vuex store 中的主题设置,并通过 handleThemeStyle 函数动态加载和应用相应的主题样式。这个过程确保了用户在使用应用时能够体验到一致的界面风格。

2.9 permission.js

import router from './router'
import { ElMessage } from 'element-plus'
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
import { getToken } from '@/utils/auth'
import { isHttp, isPathMatch } from '@/utils/validate'
import { isRelogin } from '@/utils/request'
import useUserStore from '@/store/modules/user'
import useSettingsStore from '@/store/modules/settings'
import usePermissionStore from '@/store/modules/permission'

NProgress.configure({ showSpinner: false })

const whiteList = ['/login', '/register']

const isWhiteList = (path) => {
  return whiteList.some(pattern => isPathMatch(pattern, path))
}

router.beforeEach((to, from, next) => {
  NProgress.start()
  if (getToken()) {
    to.meta.title && useSettingsStore().setTitle(to.meta.title)
    /* has token*/
    if (to.path === '/login') {
      next({ path: '/' })
      NProgress.done()
    } else if (isWhiteList(to.path)) {
      next()
    } else {
      if (useUserStore().roles.length === 0) {
        isRelogin.show = true
        // 判断当前用户是否已拉取完user_info信息
        useUserStore().getInfo().then(() => {
          isRelogin.show = false
          usePermissionStore().generateRoutes().then(accessRoutes => {
            // 根据roles权限生成可访问的路由表
            accessRoutes.forEach(route => {
              if (!isHttp(route.path)) {
                router.addRoute(route) // 动态添加可访问路由表
              }
            })
            next({ ...to, replace: true }) // hack方法 确保addRoutes已完成
          })
        }).catch(err => {
          useUserStore().logOut().then(() => {
            ElMessage.error(err)
            next({ path: '/' })
          })
        })
      } else {
        next()
      }
    }
  } else {
    // 没有token
    if (isWhiteList(to.path)) {
      // 在免登录白名单,直接进入
      next()
    } else {
      next(`/login?redirect=${to.fullPath}`) // 否则全部重定向到登录页
      NProgress.done()
    }
  }
})

router.afterEach(() => {
  NProgress.done()
})

这个 permission.js 文件的主要作用是处理应用的路由权限控制。它确保:

  • 未登录用户只能访问白名单中的路由。
  • 已登录用户可以根据角色动态生成可访问的路由。
  • 如果用户的角色信息尚未加载,会先拉取用户信息并根据角色生成动态路由。
  • 页面加载时展示进度条,增强用户体验。

工作流:

  1. 有 Token:检查路由权限并动态加载角色相关的路由。
  2. 无 Token:引导用户进入登录页面,并在登录后重定向回原本访问的路径。

3. RuoYi-Vue3 api文件夹下的内容

在这里插入图片描述

api文件夹下都是访问后端服务的文件。比如

import request from '@/utils/request'

// 查询缓存详细
export function getCache() {
  return request({
    url: '/monitor/cache',
    method: 'get'
  })
}

// 查询缓存名称列表
export function listCacheName() {
  return request({
    url: '/monitor/cache/getNames',
    method: 'get'
  })
}

// 查询缓存键名列表
export function listCacheKey(cacheName) {
  return request({
    url: '/monitor/cache/getKeys/' + cacheName,
    method: 'get'
  })
}

// 查询缓存内容
export function getCacheValue(cacheName, cacheKey) {
  return request({
    url: '/monitor/cache/getValue/' + cacheName + '/' + cacheKey,
    method: 'get'
  })
}

// 清理指定名称缓存
export function clearCacheName(cacheName) {
  return request({
    url: '/monitor/cache/clearCacheName/' + cacheName,
    method: 'delete'
  })
}

// 清理指定键名缓存
export function clearCacheKey(cacheKey) {
  return request({
    url: '/monitor/cache/clearCacheKey/' + cacheKey,
    method: 'delete'
  })
}

// 清理全部缓存
export function clearCacheAll() {
  return request({
    url: '/monitor/cache/clearCacheAll',
    method: 'delete'
  })
}

这个代码片段是使用 request 模块来进行缓存管理操作的 API 请求方法。它通过 HTTP 请求与后端服务器进行交互,以便对缓存数据进行查询和清理。下面是每个方法的解释:

  1. getCache:通过 GET 请求获取缓存的详细信息,访问 /monitor/cache 路径。
  2. listCacheName:通过 GET 请求获取缓存名称列表,访问 /monitor/cache/getNames 路径。
  3. listCacheKey:通过 GET 请求获取指定缓存名称下的键名列表。cacheName 是动态参数,传递给 URL 中,路径是 /monitor/cache/getKeys/{cacheName}。
  4. getCacheValue:通过 GET 请求获取指定缓存名称和缓存键名的内容。cacheName 和 cacheKey 是动态参数,路径是 /monitor/cache/getValue/{cacheName}/{cacheKey}。
  5. clearCacheName:通过 DELETE 请求清理指定缓存名称的缓存。cacheName 是动态参数,路径是 /monitor/cache/clearCacheName/{cacheName}。
  6. clearCacheKey:通过 DELETE 请求清理指定缓存键名的缓存。cacheKey 是动态参数,路径是 /monitor/cache/clearCacheKey/{cacheKey}。
  7. clearCacheAll:通过 DELETE 请求清理所有缓存,访问 /monitor/cache/clearCacheAll 路径。
  8. 这些方法为应用程序提供了对缓存的基本管理功能,包括查询缓存内容和清理缓存。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2329153.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

智能体和RPA都需要程序思维,如何使用影刀的变量?

欢迎来到涛涛聊AI&#xff0c; 不管AI还是RPA&#xff0c;都需要用到编程思想才能完成批量工作。今天研究了下影刀的变量。 变量类型 根据变量值选择相应的类型&#xff0c;可选择任意一种影刀所支持的数据类型 变量值 指定变量中保存的值&#xff0c;会根据不同的类型设置…

论文笔记(七十五)Auto-Encoding Variational Bayes

Auto-Encoding Variational Bayes 文章概括摘要1 引言2 方法2.1 问题场景2.2 变分下界2.3 SGVB估计器与AEVB算法2.4 重参数化技巧 3 示例&#xff1a;变分自编码器&#xff08;Variational Auto-Encoder&#xff09;4 相关工作5 实验6 结论7 未来工作 文章概括 引用&#xff1…

Sentinel[超详细讲解]-7 -之 -熔断降级[异常比例阈值]

&#x1f4d6; 主要讲解熔断降级之 --- 异常比例阈值 &#x1f680; 1️⃣ 背景 Sentinel 以流量作为切入点&#xff0c;提供了很多的丰富的功能&#xff0c;例如&#x1f917;&#xff1a; 流量控制&#xff0c;熔断降级等&#xff0c;它能够有效的适用各个复杂的业务场景&am…

C++11观察者模式示例

该示例代码采用C11标准&#xff0c;解决以下问题&#xff1a; 消除了类继承的强耦合方式&#xff1b;通知接口使用可变参数模板&#xff0c;支持任意参数&#xff1b; 示例代码 .h文件如下&#xff1a; #include <functional> #include <string> #include <…

win10 笔记本电脑安装 pytorch+cuda+gpu 大模型开发环境过程记录

win10 笔记本电脑安装 pytorchcudagpu 大模型开发环境过程记录 文章部分内容参考 deepseek。 以下使用命令行工具 mingw64。 安装 Anaconda 安装位置&#xff1a; /c/DEVPACK/Anaconda3 然后安装 Python 3.10.16 &#xff08;略&#xff09; $ conda create -n pytorch_…

Layout Inspector平替跨平台布局分析器のAppium Inspector

引言 因为我有一个api为26的设备&#xff0c;因为 Layout Inspector 无法在 API 26 以下设备上使用&#xff0c;并且现在AS的 Hierarchy Viewer 和Android Device Monitor 均已经在SDK中剔除&#xff0c;故想再搜一个pc版的布局查看器&#xff0c;发现Appium Inspector学习成本…

常见NLP指标PPL,F1,Rouge-L,Accuracy (CLS),Accuracy (EM)总结

常见NLP指标PPL&#xff0c;F1&#xff0c;Rouge-L总结 1.PPL 2.F1 3.Rouge-L 4.Accuracy (CLS) 5.Accuracy (EM)

Redis数据结构之ZSet

目录 1.概述2.常见操作2.1 ZADD2.2 ZRANGE2.3 ZREVRANGE2.4 ZRANGEBYSCORE2.5 ZSCORE2.6 ZCARD2.6 ZREM2.7 ZINCRBY2.8 ZCOUNT2.9 ZMPOP2.10 ZRANK2.11 ZREVRANK 3.总结 1.概述 ZSet和Set一样也是String类型元素的集合&#xff0c;且不允许重复的成员&#xff0c;不同的是ZSet…

磁盘分析工具合集:告别C盘焦虑!

今天李师傅带大家盘点五款硬盘空间分析利器&#xff0c;帮你精准定位那些"吃空间"的元凶&#xff0c;让C盘告别臃肿烦恼&#xff01; 一、WizTree 这款NTFS磁盘的"透视眼"堪称效率典范。它通过直接读取硬盘主文件表(MFT)实现秒级扫描&#xff0c;1TB机械…

20250405在荣品的PRO-RK3566开发板使用Rockchip原厂的buildroot系统来适配gmac1

【暂时还没有解决让PRO-RK3566的eth0/gmac1开机就启动】 PRO-RK3566作为iperf服务器&#xff1a; rootrk3566-buildroot:/# ifconfig rootrk3566-buildroot:/# ifconfig -a rootrk3566-buildroot:/# ifconfig eth0 up rootrk3566-buildroot:/# ifconfig rootrk3566-buildroot:/…

每日一题(小白)模拟娱乐篇14

直接理解题意&#xff0c;一分钟扩散一次&#xff0c;那么2020分钟也就是需要循环2020次&#xff0c;然后加入扩散后的条件&#xff0c;每一个次扩散使方格子的总量1&#xff08;只要有一个点扩散就无需看其他的点&#xff09;&#xff0c;若干次循环过后总数之和即所有黑色格子…

使用 Python 爬取并打印双色球近期 5 场开奖数据

使用 Python 爬取并打印双色球近期 5 场开奖数据 前期准备安装所需库 完整代码代码解析 1. 导入必要的库2. 定义函数 get_recent_five_ssq 3. 设置请求的 URL 和 Headers 4. 发送请求并处理响应5. 解析 HTML 内容6. 提取并打印数据7. 错误处理 首先看下运行的效果图&#xff1a…

再见VS Code!Google IDE 正颠覆传统开发体验

云端开发的革命&#xff1a;Google Project IDX 如何颠覆传统开发体验 在软件开发领域&#xff0c;Google 最新推出的 Project IDX 绝非仅仅是另一个“基于浏览器的 VS Code”——它是一次真正的范式转变。与 VS Code、Cursor 等传统工具不同&#xff0c;IDX 是一个完全云原生的…

AI+自动化测试:如何让测试编写效率提升10倍?

文章目录 摘要传统自动化测试的痛点编写测试用例太费时间测试覆盖率难以保证UI 测试维护成本高 AI 如何优化自动化测试&#xff1f;AI 生成单元测试&#xff1a;减少重复工作&#xff0c;提高覆盖率传统方法 VS AI 方法 使用 AI 生成 Python 单元测试自动补全边界情况传统方法 …

01-STM32(介绍、工具准备、新建工程)p1-4

文章目录 工具准备和介绍硬件设备stm32简介和arm简介stm32简介STM32命名规则STM32选型STM32F103C8T6最小系统板引脚定义STM32启动配置STM32最小系统电路ARM简介 软件安装注册器件支持包安装ST-LINK驱动安装USB转串口驱动 新建工程创建stm32工程STM32工程编译和下载型号分类及缩…

Win10定时任务计划无法显示要执行的EXE任务程序界面,问题解决办法

用C#开发的一款WINFORM程序&#xff0c;在电脑测试一切顺利&#xff0c;运行结果正确。但用电脑的定时任务执行时&#xff0c;程序界面不显示&#xff0c;重启电脑、各种试都不行&#xff0c;最终问题解决。 解决办法&#xff1a; 要选“只在用户登陆时运行”&#xff0c;才能执…

STM32CubeMX-H7-12-IIC读写MPU6050模块(中)-MPU6050模块详解以及软件IIC驱动

前言 上一篇我们已经完成对IIC代码基本框架的编写&#xff0c;以及获取MPU6050的ID&#xff0c;接下来我们逐一分析这个模块的功能&#xff0c;并用IIC驱动 建议看完上一篇再来看这篇 MPU6050寄存器介绍 1.电源管理寄存器&#xff08;PWR_MGMT_1&#xff0c;地址&#xff1a;0…

springboot2.7.x整合nacos+seata

1、nacos及seata下载地址 Nacos Server 下载 | Nacos 官网 Seata Java Download | Apache Seata 这里的seata版本用2.1.0版本。 2、启动nacos D:\本地-seata-nacos\nacos-server\bin>startup.cmd -m standalone 3、修改seata的conf下的application的内容 这里的数据库…

为 IDEA 设置管理员权限

IDEA 安装目录 兼容性选择管理员身份运行程序 之后 IDEA 中的操作&#xff08;包括终端中的操作&#xff09;都是管理员权限的了

单片机学习笔记8.定时器

IAP15W4K58S4定时/计数器结构工作原理 定时器工作方式控制寄存器TMOD 不能进行位寻址&#xff0c;只能对整个寄存器进行赋值 寄存器地址D7D6D5D4D3D2D1D0复位值TMOD89HGATEC/(T低电平有效)M1M0GATEC/(T低电平有效)M1M000000000B D0-D3为T0控制&#xff0c;D4-D7为T1控制 GAT…