前端目录结构

项目目录结构

前端项目采用 Vite + Vue3 + TypeScript 技术栈,目录结构清晰,便于开发和维护。

├── src/                          # 源代码目录
│   ├── api/                      # API 接口定义
│   ├── assets/                   # 静态资源
│   ├── components/               # 公共组件
│   ├── directive/                # Vue 自定义指令
│   ├── hooks/                    # Vue Composition API hooks
│   ├── i18n/                     # 国际化相关
│   ├── layout/                   # 布局组件
│   ├── locales/                  # 语言包
│   ├── router/                   # Vue Router 配置
│   ├── stores/                   # Pinia 状态管理
│   ├── theme/                    # 主题相关
│   ├── types/                    # TypeScript 类型定义
│   ├── utils/                    # 工具函数
│   ├── views/                    # 页面组件
│   ├── App.vue                   # 根组件
│   └── main.ts                   # 应用入口文件
├── public/                       # 公共静态资源
├── docker/                       # Docker 相关配置
├── index.html                    # HTML 入口文件
├── vite.config.ts                # Vite 配置
├── tsconfig.json                 # TypeScript 配置
├── tailwind.config.js            # Tailwind CSS 配置
├── postcss.config.js             # PostCSS 配置
├── package.json                  # 项目依赖配置
├── .env                          # 环境变量
├── .env.development              # 开发环境变量
├── .env.development.local        # 本地开发环境变量
├── .env.local                    # 本地环境变量
├── .eslintrc.js                  # ESLint 配置
└── .prettierrc.js                # Prettier 配置

核心目录说明

api 目录

存放所有 API 接口定义,按功能模块划分。

接口管理规范

建议按照后端模块划分文件,如 user.tsrole.ts 等,每个文件导出对应的接口方法。

components 目录

存放全局公共组件,可在任意页面中复用。

layout 目录

存放布局相关组件,包括菜单栏、顶栏、标签页、主内容区等。

布局配置修改

清空浏览器永久缓存或者点击 布局配置 -> 一键恢复默认,前提是修改了 /src/stores/themeConfig.ts 配置文件内容。添加或者修改功能,请前往 /src/layout/navBars/breadcrumb/setings.vue 组件位置修改。

stores 目录

使用 Pinia 进行状态管理,按功能模块划分 store。

theme 目录

存放主题相关样式文件,支持自定义全局主题。

views 目录

存放页面组件,按功能模块划分目录。

布局说明

布局配置方式

可视化操作:左上角 icon 图标点击打开布局配置,所有配置功能都在这个里面。 代码操作:修改 /src/stores/themeConfig.ts 文件。

包含:菜单栏顶栏tagsView 标签页主内容区

全局主题

目录结构

├── theme (页面样式)
  ├── common (基础样式)
  │  ├── transition.scss (页面过渡动画)
  │  └── var.scss (全局主题样式,用于全局改变样式)
  ├── media (媒体查询)
  │  ├── chart.scss (大数据图表)
  │  ├── cityLinkage.scss (Cascader 级联选择器城市选择)
  │  ├── dialog.scss (弹窗)
  │  ├── error.scss (404401界面)
  │  ├── form.scss (表单)
  │  ├── home.scss (首页)
  │  ├── index.scss (媒体查询定义主样式)
  │  ├── layout.scss (框架布局)
  │  ├── login.scss (登录界面)
  │  ├── media.scss (媒体查询主出口)
  │  ├── pagination.scss (分页)
  │  ├── personal.scss (个人中心)
  │  ├── scrollbar.scss (页面滚动条)
  │  └── tagsView.scss (tagsView 标签页)
  ├── mixins (scss混入)
  │  ├── element-mixins.scss (定义重置的element plus混入复用样式)
  │  ├── function.scss (全局主题颜色调用混入函数)
  │  └── mixins.scss (定义一些常用的全局混入样式)
  ├── app.scss (页面主样式,用于重置浏览器默认样式)
  ├── base.scss (基础样式、过渡动画引入等)
  ├── dark.scss (深色主题)
  ├── element.scss (重置的element plus样式,用于改变主题)
  ├── iconSelector.scss (图标选择器)
  ├── index.scss (页面样式主出口)
  ├── loading.scss (loading样式)
  ├── other.scss (其它样式)
  └── waves.scss (按钮波浪样式)

scss 部分函数说明

scss @mixin

定义:scss 官方中文文档,具体请查阅官方文档。使用方法:

/* Button 按钮
------------------------------- */
@mixin Button($main, $c1, $c2) {
  color: set-color($main);
  background: set-color($c1);
  border-color: set-color($c2);
}

页面中使用,先引入,然后在 css 类中通过 @include 使用:

@import "mixins/element-mixins.scss";

// default
.el-button--default:hover,
.el-button--default:focus {
  @include Button(primary, primary-light-8, primary-light-6);
}

scss @function

定义函数:

/* 颜色调用函数
------------------------------- */
@function set-color($key) {
  @return var(--color-#{$key});
}

不理解?请看这个 css3 :root CSS var() 函数

/* 定义一个名为 "--main-bg-color" 的属性,然后使用 var() 函数调用该属性: */
:root {
  --main-bg-color: red;
}

#div1 {
  background-color: var(--main-bg-color);
}

#div2 {
  background-color: var(--main-bg-color);
}

为什么不使用这种写法放进 :root 中?

scss 嵌套限制

因为 scss 不支持这种嵌套 mix(var(--color-primary), var(--color-success), 10%),lighten / darken / saturate / desaturate 等,从而无法用 document.documentElement.style.setProperty('--color-primary', 'blue'); 改变样式。

$colors: (
  primary: #409eff,
  success: #67c23a,
  info: #909399,
  warning: #e6a23c,
  danger: #f56c6c
)

:root {
  @each $key, $value in $colors {
    --color-#{$key}: #{$value};
  }
}

自定义全局主题

实现方法

以下方法不晓得会不会影响页面渲染性能:

  • 1、定义全局 :root 初始变量,路径:src/theme/common/var.scss
  • 2、编写覆盖 element plus 的样式:路径:src/theme/element.scss
  • 3、页面通过 document.documentElement.style.setProperty 方法改变 :root 中的值

具体实现

实现步骤说明

第 1 第 2 步就不介绍了,直接去路径去看就懂了。接下来我们讲讲第 3 步:

通过 document.documentElement.style.setProperty 改变颜色值 setProperty 文档

<script setup>
  import { reactive } from "vue";

  // 定义变量内容
  const state = reactive({
    color: "",
  });

  // 改变主题颜色
  const onColorChange = () => {
    // 设置颜色
    document.documentElement.style.setProperty("--color-primary", state.color);
    // 设置颜色变浅
    document.documentElement.style.setProperty(
      "--color-primary-light-1",
      getLightColor(state.color1, 0.1)
    );
  };
</script>

getLightColor 颜色变浅方法,路径在:src/utils/theme.ts

// 变浅颜色值,level为加深的程度,限0-1之间
export function getLightColor(color: any, level: number) {
  let reg = /^#?[0-9A-Fa-f]{6}$/;
  if (!reg.test(color)) return ElMessage.warning("输入错误的hex颜色值");
  let rgb = hexToRgb(color);
  for (let i = 0; i < 3; i++)
    rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i]);
  return rgbToHex(rgb[0], rgb[1], rgb[2]);
}

到此就完成了主题的全局变色了。

主题变色原理

总的来说,就是通过重新定义 css 样式,用来覆盖 element-plus 默认的样式,从而实现全局主题变色。其它方法实现全局主题,请自行 百度一下

框架中实现例子

全局主题改变时

主题改变时,会调用 onColorPickerChange 方法进行重新的覆盖 css :root 定义的变量的值:

const onColorPickerChange = (color: string) => {
  document.documentElement.style.setProperty(
    color,
    getThemeConfig.value[color]
  );
};

拿到的值会赋值给根节点上 htmldocument.documentElement.style。刷新的时再设置 document.documentElement.style.cssText = Local.get('themeConfigStyle');,防止数据丢失。

更改主题配置文件路径

修改后不生效,请注意看下列文件顶部文字注释。

vue3.x:/src/stores/themeConfig.ts

配置生效方式

1、需要每次都清理 window.localStorage 浏览器永久缓存 2、或者点击布局配置最底部 一键恢复默认 按钮即可看到效果

菜单 / 顶栏

顶栏

文件路径:/@/layout/navBars/breadcrumb

顶栏背景、顶栏默认字体颜色、顶栏背景渐变

功能说明:设置顶栏的背景颜色、字体颜色、背景渐变

菜单

文件路径:/@/layout/navMenu

菜单背景、菜单默认字体颜色、菜单背景渐变、菜单字体背景高亮

功能说明:设置菜单的背景颜色、字体颜色、背景渐变、字体高亮背景色(颜色跟随全局主题(primary))

分栏

文件路径:/@/layout/component/columnsAside.vue

分栏菜单背景、分栏菜单默认字体颜色、分栏菜单背景渐变

功能说明:设置分栏菜单的背景颜色、字体颜色、背景渐变

界面设置

菜单设置

文件路径:/@/layout/navMenu

菜单水平折叠、菜单手风琴、经典布局分割菜单

功能说明:菜单水平折叠、手风琴(开启一个展开)、经典布局分割菜单(顶级在顶栏处,子级在菜单栏)

固定 Header

文件路径:/@/layout/main

固定 Header

功能说明:固定 Header(主内容区滚动,顶栏不跟随滚动)

锁屏

文件路径:/@/layout/lockScreen

开启锁屏、自动锁屏(s/秒)

功能说明:开启锁屏(类似于电脑屏保)、自动锁屏(s/秒)

界面显示

文件路径:/@/layout/logo

侧边栏 Logo

功能说明:显示/隐藏侧边栏 Logo

文件路径:/@/layout/navBars/Breadcrumb/breadcrumb.vue

开启 Breadcrumb、开启 Breadcrumb 图标

功能说明:开启 Breadcrumb、Breadcrumb 图标

Tagsview 标签页

文件路径:/@/layout/navBars/tagsView

开启 Tagsview、开启 Tagsview 图标、开启 TagsView 缓存、开启 TagsView 拖拽、开启 TagsView 共用

功能说明:开启 Tagsview、Tagsview 图标、TagsView 缓存、TagsView 拖拽、TagsView 共用(共用详情界面:tagsView只会出现一个;非共用详情界面:tagsView会出现多个)

文件路径:/@/layout/footer

开启 Footer 版权

功能说明:显示/隐藏底部版权

颜色模式

文件路径:/@/layout/navBars/breadcrumb/setings.vue

灰色模式、色弱模式、深色模式

功能说明:开启灰色模式、色弱模式、深色模式

前端水印

文件路径:/@/utils/wartermark.ts

开启水印、水印文案

功能说明:开启开启水印、设置水印文案,可通过修改前端配置项解决。

其它设置

配置查找方法

可使用 el-option 的 value 值去对应的 文件路径 里搜索查看。

Tagsview 风格

文件路径:/@/layout/navBars/tagsView

需注意 value 值需与定义的 css 类名 一致:

<el-select v-model="getThemeConfig.tagsStyle">
  <el-option label="风格1" value="tags-style-one"></el-option>
  <el-option label="风格2" value="tags-style-two"></el-option>
  <el-option label="风格3" value="tags-style-three"></el-option>
  <el-option label="风格4" value="tags-style-four"></el-option>
  <!-- 新增的风格 -->
  <el-option label="风格xx" value="tags-style-xxx"></el-option>
  <!-- 继续添加 -->
  ...
</el-select>

主页面切换动画

文件路径:/@/theme/common/transition.scss,内置 slide-rightslide-leftopacitys 切换风格。

你可能需要了解 进入过渡 & 离开过渡。新增动画时,需要在 /@/layout/navBars/breadcrumb/setings.vue 其它设置中添加如下:

<el-select v-model="getThemeConfig.animation">
  <el-option label="slide-right" value="slide-right"></el-option>
  <el-option label="slide-left" value="slide-left"></el-option>
  <el-option label="opacitys" value="opacitys"></el-option>
  <!-- 新增的动画名 -->
  <el-option label="xxx" value="xxx"></el-option>
  <!-- 继续添加 -->
  ...
</el-select>

分栏高亮风格

文件路径:/@/layout/component/columnsAside.vue

需注意 value 值需与定义的 css 类名 一致:

<el-select v-model="getThemeConfig.columnsAsideStyle">
  <el-option label="圆角" value="columns-round"></el-option>
  <el-option label="卡片" value="columns-card"></el-option>
  <!-- 新增的高亮风格 -->
  <el-option label="xxx" value="xxx"></el-option>
  <!-- 继续添加 -->
  ...
</el-select>

分栏布局风格

文件路径:/@/layout/component/columnsAside.vue

需注意 value 值需与定义的 css 类名 一致:

<el-select v-model="getThemeConfig.columnsAsideLayout">
  <el-option label="水平" value="columns-horizontal"></el-option>
  <el-option label="垂直" value="columns-vertical"></el-option>
  <!-- 新增的分栏布局风格 -->
  <el-option label="xxx" value="xxx"></el-option>
  <!-- 继续添加 -->
  ...
</el-select>

布局切换

此项目包含四个布局:默认、经典、横向、分栏。