

## 运行环境
* node > 16.18.0
* pnpm > 8.6.0 （选用）

## 主要技术栈
| 框架                                                                  | 说明               | 版本     |
|----------------------------------------------------------------------|------------------|--------|
| [Vue3.x](https://staging-cn.vuejs.org/)                              | Vue 框架           | 3.4.21 |
| [Vite](https://cn.vitejs.dev//)                                      | 开发与构建工具          | 5.4.1  |
| [Element Plus](https://element-plus.org/zh-CN/)                      | Element Plus     | 2.6.1 |
| [TypeScript](https://www.typescriptlang.org/docs/)                   | JavaScript 的超集   | 5.3.3  |
| [pinia](https://pinia.vuejs.org/)                                    | Vue 状态管理器 替代 vuex | 2.1.7+ |
| [vueuse](https://vueuse.org/)                                        | 常用工具集            | 10.9.0+ |
| [vue-router](https://router.vuejs.org/)                              | Vue 路由           | 4.3.0+  |
| [unocss](https://uno.antfu.me/)                                      | 原子 css          | 0.58.5+  |

## IDE 推荐插件
| 插件名                           | 功能                       |
|-------------------------------|--------------------------|
| TypeScript Vue Plugin (Volar) | 用于 TypeScript 的 Vue 插件   |
| Vue Language Features (Volar) | Vue3.0 语法支持               |
| unocss                        | unocss for vscode           |
| Stylelint                     | Css    格式化                 |
| Prettier                      | JS 代码格式化                 |
| ESLint                        | JS 代码语法审查                |

## 项目结构简介
- .image // remadme 文件资源
- .vscode
  - extensions.json // 统一该项目的 IDE 适配插件
  - launch.json // VsCode 内命令行启动配置
  - settings.json // 统一 VsCode 的基础配置和代码规范
- build // 打包配置，在 vite.config.js 中被引用
  - vite
    - index.ts // vite 构建插件统一处理文件
    - optimize // vite 预构建配置
- public // 非编译静态文件存放目录
- src
  - api // 业务接口声明文件存放目录
    - infra // 基础设施
      - apiAccessLog // api 日志/访问日志 页面接口
      - apiErrorLog // api 日志/错误日志 页面接口
      - codegen // 代码生成页面接口
      - dataSourceConfig // 代码生成页面接口 
      - config // 配置管理页面接口
      - dbDoc // 数据库文档页面接口
      - demo // 代码生成按钮模块接口
      - file // 文件管理/文件列表页面接口
      - fileConfig // 文件管理/文件配置 页面接口
    - login // 登录
      - config
        - types.ts // 登录模块中使用到的数据类型定义
      - index.ts // 登录模块接口
    - system // 系统管理
      - dept // 部门管理页面接口
      - dict // 字典管理页面接口
      - loginLog // 审计日志/登录日志 页面接口
      - mail // 邮箱管理
        - account // 邮箱账号页面接口
        - log // 邮箱记录页面接口
        - template // 邮箱模板页面接口
      - menu // 菜单管理页面接口
      - message // 站内信管理
        - message // 消息记录页面接口
        - template // 模板管理页面接口
      - oauth2 // OAuth 2.0
        - client.ts // 应用管理页面接口
        - token.ts // 令牌管理页面接口
      - operatelog // 审计日志模块接口
      - permission // 权限模块接口（非页面）
      - post // 岗位管理页面接口
      - role // 角色管理页面接口
      - tenant // 租户管理/租户列表 页面接口
      - tenantPackage // 租户管理/租户套餐 页面接口
      - user // 用户管理
        - index.ts // 用户管理页面接口
        - profile.ts // 个人中心页面接口
        - socialUser.ts // 个人中心页面-社交信息接口
    - assets // 项目资源文件存放目录
    - components // 项目公共组件
      - Backtop // 回到顶部组件
      - ConfigGlobal // element plus 自定义空间命名组件
      - ContentWrap // 卡片容器组件
      - CountTo // 媒体播放控制器组件，提供控制方法
      - Cropper
        - src
          - Cropper.vue // 图片懒加载
          - CopperModal.vue // 自定义头像处理组件（例：个人中心）
          - CropperAvatar.vue // 个人中心个人信息组件
      - Descriptions // table 式详情组件（例：邮件管理-邮箱账号-详情）
      - Dialog // el-dialog 包装后的弹窗组件
      - DictTag // el-tag 包装后的标签组件
      - Echart // 包装好初始化流程的 echart 魔术组件
      - Editor // 包装好初始化流程的富文本组件
      - Error // 系统错误提示组件，包含 403，404，500
      - Form // el-form 包装后的表单组件
      - Highlight // 文字高亮组件（例：首页通知公告）
      - Icon // 基于 el-icon 封装好的，扩展了默认图标数的 Icon 组件
      - IFrame // iframe 简单嵌入封装组件
      - ImageViewer // 基于 el-image-viewer 的图片预览组件
      - InputPassword // 密码输入组件
      - Layout
        - conponents
          - Breadcrumb // 导航路径面包屑
          - Collapse // 折叠按钮
          - ContextMenu // 归属于 TagsView
          - Footer // 主内容区域的统一底部
          - Logo // Logo 组件
          - Menu // 项目主菜单组件
          - LocaleDropdown // 头部中英文切换组件，归属于 ToolHeader
          - Message // 头部未读消息组件，归属于 ToolHeader
          - Screenfull // 头部全屏组件，归属于 ToolHeader
          - SizeDropdown // 头部字体大小设置组件，归属于 ToolHeader
          - ToolHeader.vue // 头部工具栏
          - Setting // 布局自定义调整组件
          - TabMenu // 4 号布局模式下的主菜单组件
          - TagsView // 路由历史组件
          - ThemeSwitch // 黑白模式设置组件（例：设置中使用）
          - UserInfo // 头部用户组件
          - AppView.vue // 项目主布局文件
          - useRenderLayout.tsx // 可设置布局核心实现逻辑
        - Layout.vue // 布局容器
      - Pagination // 基于 el-pagination 封装的分页组件
      - RouterSearch // 用于头部的路由搜索组件
      - Search // 通用的表单条件检索组件
      - Table // 基于 el-table 封装的表格组件（例：邮件管理中使用）
      - Tooltip // 基于 el-tooltip 封装的提示组件（例：菜单管理中使用）
      - UploadFile
        - src
          - UploadFile.vue // 基于 el-upload 的文件上传组件
          - UploadImg.vue // 基于 el-upload 的图片（单）上传组件
          - UploadImgs.vue // 基于 el-upload 的图片（多）上传组件
        - index.ts // 上传组件统一输出口
      - XButton // 基于 el-button 封装的按钮组件
      - index.ts // 全局注册组件的入口文件，在 main.ts 中被使用
    - config
      - axios // http 请求封装文件
      - directives // 自定义指令
      - hooks // 自定义实用工具钩子
      - plugins // 插件集中初始化目录
      - styles // 全局样式定义目录
      - types // 项目中用到的供给 ts 使用的参数类型定义
    - router // 项目前端路由定义目录
    - store
      - modules
        - app.ts // 服务于项目层面的状态管理
        - dict.ts // 服务于数据字典的状态管理
        - locate.ts // 服务于中英文切换功能的状态管理
        - lock.ts // 服务于锁屏功能的状态管理
        - permission.ts // 服务于用户菜单权限的状态管理
        - tagsView.ts // 服务于历史路由的状态管理
        - user.ts // 服务于用户体系的状态管理
      - index.ts // 状态管理初始化
    - utils // 项目工具函数目录
    - views // 主要页面
      - Error // 错误跳转页
        - 403.vue
        - 404.vue
        - 500.vue
      - Home // 首页
      - infra // 基础设施
        - apiAccessLog // API日志-访问日志
        - apiErrorLog // API日志-错误日志
        - codegen // 代码生成
        - config // 配置管理
        - dataSourceConfig // 数据源配置
        - dbDoc // 数据库文档
        - demo // 代码生成案例
        - druid // MySQL 监控
        - file // 文件管理
          - fileConfig // 文件配置
          - 文件列表 // file
        - job // 定时任务
        - redis // Redis 监控
        - server // Java 监控
        - skywalking // 监控平台
        - swagger // API 接口文档
      - Login // 登录
      - Profile // 用户中心
      - Redirect // 重定向中转页
      - system // 系统管理
        - announcement // 通知公告
        - dept // 部门管理
        - dict // 字典管理
        - loginlog // 审计日志-登录日志
        - operatelog // 审计日志-操作日志
        - mail // 邮箱管理
          - account // 邮箱账号
          - template // 邮件模版
          - log // 邮件记录
        - menu // 菜单管理
        - message // 站内信管理
          - message // 消息记录
          - template // 模板管理
        - oauth2 // OAuth 2.0
          - client // 应用管理
          - 令牌管理 // 令牌管理
        - post // 岗位管理
        - role // 角色管理
        - sms // 短信管理
          - channel // 短信渠道
          - template // 短信模板
          - log // 短信日志
        - social // 三方登录
          - client // 三方应用
          - user // 三方用户
        - tenant // 租户管理-租户列表
        - tenantPackage // 租户管理-租户套餐
        - user // 用户管理
      - APP.vue // 项目根容器
      - main.ts // 项目启动入口
      - permission.ts // 菜单权限管控主文件
      - .env // 环境配置目录
      - index.html // html 模板文件
      - package.json // 项目依赖包
        - .eslintignore // js 语法检查忽略目录
        - .eslintrc-auto-import.json // vite 按需导入的 ts 类型支持配置
        - .eslintrc.js // js 语法检查规则配置
        - .gitignore // git 提交忽略
        - .prettierignore // 代码格式校验忽略配置
        - .prettier.config // 代码格式校验配置
        - .stylelintignore // css 语法检查忽略目录
        - .stylelint.config.js // css 语法检查配置
      - postcss.config.js // css 自动补全配置
      - tsconfig.json  // ts 语法检查配置
      - uno.config.ts // unocss 配置
      - vite.config.ts  // 项目开发配置  

### 什么是预构建
vite 通过将项目代码在一开始就区分为 依赖 和 源码 两类，当项目第一次启动时，vite 会利 esbuild 去预构建依赖，esbuild 为 Go 语言编写，比以 JavaScript 编写的打包器预构建依赖快 10-100 倍。

### 目录下应该存放什么类型的文件
- 不会被源码引用
- 必须保持原有文件名（没有经过 hash）
- 不想引入该资源，只是想得到其 URL（比如浏览器 icon）

### vite 中的 assets 目录
与 webpack 不同，vite 构建的项目中，assets 目录下的资源文件依然会被打包

### 什么是自定义空间命名？
Element Plus 提供的默认命名空间为 el， 在特殊情况下，我们需要自定义命名空间，即自定义统一前缀

## 注意事项与高级封装

### 注意事项

#### 路由与路由权限
本项目的路由，采用的是静态路由与动态路由相结合的常规实现方式。静态路由包含了项目的基础路由结构，如登录页面、错误页面等，基础路由的配置位于 /src/router/locate.ts 文件中。而动态路由的实现则放在了 /permission.ts 文件中，动态路由的融合还使配合用了 permissionStore 状态管理器，核心代码如下：

![示例图](/.image/read_01.png)

另外，动态路由需要在系统的菜单管理中进行配置，不能在代码中进行手动注入。

注意：/permission.ts 权限控制文件包含了路由白名单的配置，项目开发过程中，如果需要先垮过鉴权，可以通过向白名单中添加路由的方式达到目的。

### 便捷功能

#### 代码级权限封装
我们依托菜单管理中的按钮按钮级别的权限配置，将权限细粒度化到了具体功能，该功能的载体可以是按钮，也可以是功能模块。

我们在 /src/config/directives/permission 目录下新封装了两个自定义指令 hasPermi 、hasRole，通过向指令中传入相应的功能权限识别码，然后再与项目登录之后获取到的用户权限表进行对别，通过甄别是否拥权来控制功能模块的显示隐藏。

使用示例：

![示例图](/.image/read_02.png)

#### ICON 图标封装
考虑到 icon 的广泛使用场景，我们对 element-plus 的 icon 库进行了扩展，我们通过公共组件的方式在 /src/components/Icon 目录中对通用组件 Icon 进行了进一步的封装。并且，为了使用方便，我们对 Icon 组件进行了全局注册，这样，开发者需要使用时，只需要以如下的方式进行应用即可：

![示例图](/.image/read_03.png)

#### ICON 本地缓存封装

为了方便本地缓存的使用，我们对本地缓存的存取做了一层封装，并以组合式函数的形式向外提供了这部分功能的方法。

其中，我们借助了 web-storage-cache 插件去简化了我们的实现逻辑，使用用例如下

![示例图](/.image/read_04.png)
![示例图](/.image/read_05.png)
![示例图](/.image/read_06.png)

#### 提示弹窗封装
为了简化编码过程中提示信息输出的编码，我们对常规的提示做了一层集中封装，封装代码位于 /config/hooks/web/useMessage.ts 文件中

![示例图](/.image/read_07.png)

## 开发指南

### 命令

package.json 中 scripts 的命令简述

| 命令                           | 功能                       |
|-------------------------------|--------------------------|
| i                             | 以 pnpm 的方式初始化项目   |
| dev                           | 使用 .env.local 环境启动项目              |
| dev-server                    | 使用 .dev.local 环境启动项目          |
| ts:check                      | 使用 vue-tsc 插件对项目进行基于 ts 的变量类型检查                 |
| build:local                   | 使用 .env.local 环境打包项目                 |
| build:prod                    | 使用 .env.prod 环境打包项目               |
| serve:dev                     | 静态项目运行，即在本地启动一个服务支撑打包后文件的访问              |

### 环境
本项目因为采用的是 vue3.x 的技术体系，所以需要 node 版本在 16.18.0 及以上，初始化安装过程中请先检查本机 node 版本。

### 初始化、启动与构建

* 项目初始化：
  * 命令：npm run i  |  yarn i ，及 npm、yarn、pnpm 的自带依赖安装命令
  * 注意：项目中的依赖（package.json）有些采用的是向上依赖，如：（@wangeditor/editor": "^5.1.23），这种依赖方式会默认下载最新的依赖版本，如果项目依赖安装完成后启动报错，请根据提示将相关依赖改为直接依赖（@wangeditor/editor": "5.1.23）后重新初始化即可。
* 项目启动：
  * 命令：npm run dev 开发态启动，npm run preview 静态站点形式启动
  * 注意：默认开发模式会启用 .env.local 环境文件，请开发者在启动项目时，重点注意修改配置文件中的相关参数，尤其是请求路径配置项 VITE_BASE_URL
* 项目构建：
  * 命令：npm run build:(local | dev | test | stage | prod) 

请开发者仔细阅读 package.json 中 scripts 下各命令使用的环境，并在启动项目和构建项目时注意各命令对应环境文件中的配置。

![示例图](/.image/read_08.png)

环境文件配置示例（.env.local）：

![示例图](/.image/read_09.png)

### 开发规范
本节，我们将模拟实际开发场景，对完整的开发流程进行较为细致的说明。下面，我们以新建一个业务页面为例开始讲解：

#### 1 新建业务页面
根据业务需要，我们需要新建一个用来构建页面报表的页面，此时，我们需要在 /src/views 目录下，以首字母大写的形式新建一个 Report 文件夹，并在内部新建一个 index.vue 主页面文件

![示例图](/.image/image_10.png)

规范：通常，我们默认推荐以以首字母大写的形式新建业务页面，如有需要，我们推荐在文件夹内做如下细分

![示例图](/.image/read_11.png)

#### 2 新建业务接口
业务页面新建完成之后，我们需要链接服务端去获取业务数据，此时我们需要现在 /src/api 目录下声明业务接口

![示例图](/.image/read_12.png)

规范：我们需要首先以模块名的首字母小写驼峰形式在  /src/api 目录下新建一个文件夹，在业务不复杂的情况下，我们只需要在该文件夹内新建一个 index.ts 实体声明文件即可，若业务比较繁重，我们可以在该文件夹内做更下级的细分

业务接口声明的格式可以参考下图：

![示例图](/.image/read_13.png)

#### 3 沉淀公共组件
在继续编写业务逻辑的过程中，我们发现其中使用到的一个组件可能会在后续的开发中被频繁使用，此时，我们需要在 /src/components 新建一个文件

![示例图](/.image/read_14.png)

规范：公共组件的文件命名与内部结构规范可以参考 3.1 中业务页面结构的规范

#### 4 配置静动菜单
大家这里要非常注意，本系统采用的是静动态结合的路由方式，静态路由的配置在 /src/router/locale.ts 文件中配置，其中，meta 选项中的 hidden 参数决定了该业务页面是否在导航菜单中展示

![示例图](/.image/read_15.png)

静态路由配置示例：

![示例图](/.image/read_16.png)

需要注意的是，静态路由是无法纳入用户权限管辖范围的。当我们需要当前页面能通过权限分配的形式分配到用户时，我们需要进入系统的内置模块系统管理 下的 菜单管理 中进行动态配置：

![示例图](/.image/read_17.png)

其中，路由地址不能在同级重复，组件地址的根目录为 /src/views ，例如，我们需要将 Report 业务页面的组件地址选项配置为：Report/index.vue

同样，动态菜单也可以通过弹窗中的 显示状态 选项配置是否在导航菜单中显示

#### 5 添加全局状态
根据业务编码需要，我们希望新增一个全局状态管理模块去对外输出一些可能会被使用到的全局状态，此时，我们需要在 /src/store/modules 下新建 report.ts 文件，然后依照 pinia 的语法习惯去进行逻辑编写

![示例图](/.image/read_18.png)

#### 6 添加全局样式
项目的通用元样式存放在 /src/config/styles/ 目录下，新增业务中如果有需要迁移至全局使用的样式，请在该目录下新建业务专用文件

规范：一般，我们不建议将业务代码的样式提升到公共样式区内，因为该区域没有做样式隔离，区域内的样式更改会影响到整个项目的渲染，通常我们业务代码中需要做的特异性更改从全局角度来看是不需要进行跨级提升的。当然，如果我们确实需要用到该区域的统筹能力，我们需要新建一个集中的业务样式编码文件，并通过 import 的方式导入到 /src/config/styles/index.scss 中

#### 7 其他扩展
* 关于进阶扩展，如果我们需要新建应用指令，我们需要在 /src/config/directives/ 目录下进行；
* 如果我们需要有新的插件需要初始化，我们需要在 /src/config/plugins/ 目录下进行；
* 如果我们需要新增钩子，我们需要在/src/config/hooks/ 目录下进行

### 规范原则
项目的开发规范，涉及到各个方面，我们很难从语言上表述全面，这件事情就像武学心法一样，需要由里及表，我们提倡的核心原则是：保持模块独立，坚持松散耦合，我们建议以这样的编码心路去面对开发过程中碰到的各种问题，如果你坚持这样去做了，你会发现编码的过程会越来越顺畅，即使有问题出现，也能非常迅速的定位到源，快速解决

## 内置功能
本项目沉淀了大部分管理系统中频繁使用到的通性功能，真正做到了开箱即用，让开发者切实摆脱了重复搬砖，轻松直面核心业务。

![示例图](/.image/read_19.png)