diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 0000000..929eb65
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,22 @@
+.DS_Store
+node_modules
+/dist
+/test
+
+# local env files
+.env.local
+.env.*.local
+
+# Log files
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Editor directories and files
+.idea
+.vscode
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js
new file mode 100644
index 0000000..9864f8b
--- /dev/null
+++ b/docs/.vuepress/config.js
@@ -0,0 +1,69 @@
+module.exports = {
+ title: 'jxc-admin',
+
+ description: "jxc-admin后台管理系统文档",
+
+ host: 'localhost',
+
+ // 输出目录
+ dest: 'dist',
+
+ // 主题配置
+ themeConfig: {
+ smoothScroll: true,
+
+ lastUpdated: '上次更新:',
+
+ nav: [
+ {text: '在线预览', link: 'https://toesbieya.cn'},
+ {text: 'GitHub', link: 'https://github.com/toesbieya/jxc-admin'}
+ ],
+
+ sidebar: [
+ 'installation',
+ {
+ title: '前端',
+ collapsable: false,
+ children: [
+ '/frontend/',
+ '/frontend/layout',
+ '/frontend/router',
+ '/frontend/permission',
+ '/frontend/new',
+ '/frontend/deploy',
+ {
+ title: '组件',
+ collapsable: false,
+ children: [
+ '/frontend/components/abstract-table',
+ '/frontend/components/region-selector',
+ '/frontend/components/search-form',
+ '/frontend/components/upload-file',
+ ]
+ },
+ {
+ title: '全局方法',
+ collapsable: false,
+ children: [
+ '/frontend/global-methods/bottom-tip',
+ '/frontend/global-methods/guide',
+ '/frontend/global-methods/image-viewer',
+ '/frontend/global-methods/puzzle-verify',
+ '/frontend/global-methods/signature',
+ ]
+ },
+ '/frontend/utils',
+ '/frontend/plugins'
+ ]
+ },
+ ]
+ },
+
+ plugins: {
+ '@vuepress/pwa': {
+ serviceWorker: true,
+ updatePopup: true
+ },
+ '@vuepress/back-to-top': true
+ }
+}
diff --git a/docs/.vuepress/public/abstract-table.png b/docs/.vuepress/public/abstract-table.png
new file mode 100644
index 0000000..eb6ed2b
Binary files /dev/null and b/docs/.vuepress/public/abstract-table.png differ
diff --git a/docs/.vuepress/public/puzzle-verify.png b/docs/.vuepress/public/puzzle-verify.png
new file mode 100644
index 0000000..52c0ac1
Binary files /dev/null and b/docs/.vuepress/public/puzzle-verify.png differ
diff --git a/docs/.vuepress/public/region-selector_tab.png b/docs/.vuepress/public/region-selector_tab.png
new file mode 100644
index 0000000..772af8b
Binary files /dev/null and b/docs/.vuepress/public/region-selector_tab.png differ
diff --git a/docs/.vuepress/public/search-form_1.png b/docs/.vuepress/public/search-form_1.png
new file mode 100644
index 0000000..ddf656c
Binary files /dev/null and b/docs/.vuepress/public/search-form_1.png differ
diff --git a/docs/.vuepress/public/search-form_2.png b/docs/.vuepress/public/search-form_2.png
new file mode 100644
index 0000000..2d198e6
Binary files /dev/null and b/docs/.vuepress/public/search-form_2.png differ
diff --git a/docs/.vuepress/public/upload-file.png b/docs/.vuepress/public/upload-file.png
new file mode 100644
index 0000000..fae8447
Binary files /dev/null and b/docs/.vuepress/public/upload-file.png differ
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 0000000..4e4e7f4
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,9 @@
+---
+home: true
+heroImage: https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png
+heroText: jxc-admin
+tagline: 前后端分离的简易进销存后台管理系统。
+actionText: 快速上手 →
+actionLink: ./installation/
+footer: MIT Licensed | Copyright © 2020-present toesbieya
+---
diff --git a/docs/frontend/README.md b/docs/frontend/README.md
new file mode 100644
index 0000000..4189b7b
--- /dev/null
+++ b/docs/frontend/README.md
@@ -0,0 +1,69 @@
+# 介绍
+
+## 功能
+
+```
+- 首屏加载动画
+
+- 登录 \ 注册
+ - 集成多种canvas背景动画
+ - 仿极验滑动验证
+
+- 布局功能
+ - 异步路由组件loading骨架屏
+ - 动态侧边栏(支持多级路由嵌套)
+ - 动态面包屑
+ - 多页签(支持详情页缓存)
+ - 支持移动端
+ - 导航栏、侧边栏可隐藏
+ - 侧边栏折叠时可显示上级
+
+- Excel导出,支持多级表头、合并行
+
+- 错误页面
+ - 403
+ - 404
+
+- 组件
+ - 用户导航
+ - 行政区划选择器,支持树形和选项卡型
+ - 封装的上传组件,整合七牛云,支持多种格式的文件预览
+ - 封装了antd风格的dialog,可拖拽、超出可滚动
+ - 手写签名
+
+- element-ui增强
+ - message支持分组、进度条功能
+ - select重写,分别使用了popperjs的v1和v2版本
+```
+
+## 目录结构
+```
+├── element-ui-personal # element-ui增强
+├── mock # 项目mock,需打开devServer.before的注释
+├── public # 静态资源文件夹
+├── src
+│ ├── api # 数据请求集合
+│ ├── assets
+│ │ │── icons # 项目所有svg icons
+│ │ └── styles # 样式集合
+│ ├── bizComponents # 公用业务组件
+│ ├── components # 公用组件
+│ ├── config
+│ │ │── index.js # 基础配置项
+│ │ └── request.js # axios封装
+│ ├── directive # 自定义指令集合
+│ ├── filters # 自定义过滤器集合
+│ ├── layout # 布局文件夹,包含了导航栏、侧边栏、多页签、全局页脚、页面
+│ ├── mixins # 公用混入
+│ ├── plugin # 一些插件,均使用import()来动态引入
+│ ├── router
+│ │ │── authority # 需要鉴权的路由集合
+│ │ │── constant # 不需要鉴权的路由集合
+│ │ │── index.js
+│ │ └── util.js
+│ ├── store # vuex配置
+│ ├── utils # 工具类
+│ ├── views # 路由页面集合
+│ ├── App.vue
+│ └── main.js
+```
diff --git a/docs/frontend/components/abstract-table.md b/docs/frontend/components/abstract-table.md
new file mode 100644
index 0000000..b8dbb0f
--- /dev/null
+++ b/docs/frontend/components/abstract-table.md
@@ -0,0 +1,26 @@
+# Abstract Table
+
+
+
+给``设置了一些默认属性,设置了`empty`插槽。
+```html
+
+ {children}
+
+
+```
+
+### 引入:
+
+`@/components/AbstractTable`。
+
+### 使用:
+
+照着官方文档,当成 `` 用就行。
+
diff --git a/docs/frontend/components/region-selector.md b/docs/frontend/components/region-selector.md
new file mode 100644
index 0000000..d00bf7f
--- /dev/null
+++ b/docs/frontend/components/region-selector.md
@@ -0,0 +1,46 @@
+# 行政区划选择器
+
+目前分 `树型` 和 `选项卡型` 两种,由于 `树型` 不完善,所以这里只介绍 `选项卡型`,有兴趣的可以查看源码`@/components/RegionSelector/Tree`。
+
+
+
+由于行政区划数据在本项目中是公共数据,所以使用了`vuex`来存放,如果不想用`vuex`但又想拿到别的项目里用,可以自己改造一下。
+
+### 引入:
+
+`@/components/RegionSelector`
+
+### 使用:
+```html
+
+```
+
+行政区划的数据模型可以查看`public/static/json/region-pcas.json`,这是精确到街道的数据,[由此获取](https://github.com/modood/Administrative-divisions-of-China)。
+
+### RegionSelector Attributes:
+
+| 参数 | 说明 | 类型 | 默认 |
+| :-----------------: | :-------------------------------------: | :--------------: | :-----: |
+| type | 选择器类型,`tab / tree` | `string` | `'tab'` |
+| value / v-model | 绑定值 | `string / array` | - |
+| readonly | 是否只读,等同于`el-select`的`disabled` | `boolean` | - |
+| size | 大小,等同于`el-select`的`size` | `string` | - |
+| getChildrenOnSelect | 在确认选择时是否连同子级一起获取 | `boolean` | - |
+| limit | 是否需要剪枝 | `boolean` | - |
+| limitApi | 获取剪枝数据的api | `function` | - |
+| separation | 分隔号 | `string` | `','` |
+
+### RegionSelector Events:
+
+| 事件名称 | 说明 | 回调参数 |
+| :------: | :------------------------: | :--------------: |
+| clear | 等同于`el-select`的`clear` | - |
+| select | 确定选择时触发 | `(node,idArray)` |
+
+
+::: tip
+`value` 为 `string` 时支持被 `separation` 所连接的汉字或者数字,比如可以是 `北京市,东城区` ,也可以是 `北京市,110101`。
+为 `array` 时,数组里的每一项除了支持上面的形式外,还支持 `{id:'11',...}、{name:'北京市',...}` 这两种。
+
+使用 `v-model` 时,不管初始传入的数据是什么样的,最终都会返回 `北京市,东城区` 这样的字符串。
+:::
diff --git a/docs/frontend/components/search-form.md b/docs/frontend/components/search-form.md
new file mode 100644
index 0000000..42063f0
--- /dev/null
+++ b/docs/frontend/components/search-form.md
@@ -0,0 +1,59 @@
+# Search Form
+
+一个自适应的表单容器,根据父元素的内宽来确定一行渲染多少个表单控件,同时确定是否需要折叠。
+
+
+
+
+### 引入:
+
+`@/components/SearchForm`,`@/components/SearchFormItem`
+
+### 使用:
+```html
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+### SearchForm Attributes:
+
+| 参数 | 说明 | 类型 | 默认 |
+| :-----------------: | :----------------------------------: | :------: | :-------: |
+| label-width | 等同于`el-form`的`label-width` | `string` | `'120px'` |
+| xs | 父元素内宽<768px时,每行渲染多少空间 | `number` | `1` |
+| sm | >=768px | `number` | `2` |
+| md | >=998px | `number` | `3` |
+| lg | >=1200px | `number` | `4` |
+
+### SearchForm Slots:
+
+| 名称 | 说明 |
+| :------: | :---------------------------------------------------------------------: |
+| collapse | 折叠按钮,参数为 `{collapse:展开为true否则false,handle:展开折叠的方法}` |
+
+### SearchFormItem Attributes:
+
+| 参数 | 说明 | 类型 | 默认 |
+| :---: | :---------------------------: | :------: | :-------: |
+| label | 等同于`el-form-item`的`label` | `string` | - |
diff --git a/docs/frontend/components/upload-file.md b/docs/frontend/components/upload-file.md
new file mode 100644
index 0000000..cdbc1e0
--- /dev/null
+++ b/docs/frontend/components/upload-file.md
@@ -0,0 +1,31 @@
+# Upload File
+
+集成七牛云直传,需要配合后端使用。支持图片、word、pdf、ppt、rar、excel、txt、zip类型的文件预览(使用kkFileView)。
+
+
+
+### 引入:
+
+`@/components/UploadFile`
+
+### 使用:
+```html
+
+```
+
+### UploadFile Attributes:
+
+| 参数 | 说明 | 类型 | 默认 |
+| :------: | :--------------------: | :---------------: | :------: |
+| disabled | 等同于`el-upload` | `boolean` | - |
+| multiple | 等同于`el-upload` | `boolean` | `true` |
+| fileList | 等同于`el-upload` | `array` | `[]` |
+| limit | 等同于`el-upload` | `number` | `10` |
+| maxSize | 单次上传文件的最大大小 | `number / string` | `'10MB'` |
+
+### UploadFile Events:
+
+| 事件名称 | 说明 | 回调参数 |
+| :------: | :--------------------------: | :---------------: |
+| remove | 移出不是本次上传的文件时触发 | `{url}` |
+| success | 上传成功后触发 | `(file,response)` |
diff --git a/docs/frontend/deploy.md b/docs/frontend/deploy.md
new file mode 100644
index 0000000..887df37
--- /dev/null
+++ b/docs/frontend/deploy.md
@@ -0,0 +1,34 @@
+# 构建和发布
+
+## 构建
+
+当项目开发完毕,只需要运行一行命令就可以打包你的应用:
+```shell script
+# 默认环境为 production
+npm run build
+```
+
+构建打包成功之后,会在根目录生成`dist`文件夹,里面就是构建打包好的静态文件。
+
+如果需要指定`dist`目录等,则需要通过`vue.config.js`的`outputDir`进行配置。
+
+## 发布
+
+如果静态文件不是部署在根目录下,比如想部署在 `/app` 下,那么需要将 `@/config/index.js` 中的 `contextPath` 改为 `/app/`。
+
+想在 `js`中引入的话,可以直接使用 `process.env.BASE_URL` 拿到`contextPath`。
+
+如果是在 `html` 中引入的话,是 `<%= BASE_URL %>` 的形式,这是 `ejs` 的语法。
+
+::: warning 注意
+`contextPath` 应始终以 `/` 开头,以 `/` 结束。
+:::
+
+## 路由模式
+
+项目提供了动态修改路由模式的功能,只需要修改 `@/config/index.js` 中的 `routerMode` 即可。
+
+当路由模式为 `'history'` 时,需要服务器提供支持。以 `nginx` 为例,需要在配置中补上:
+```shell script
+try_files $uri $uri/ /index.html;
+```
diff --git a/docs/frontend/global-methods/bottom-tip.md b/docs/frontend/global-methods/bottom-tip.md
new file mode 100644
index 0000000..fd78756
--- /dev/null
+++ b/docs/frontend/global-methods/bottom-tip.md
@@ -0,0 +1,6 @@
+# 底部警告信息弹框
+
+### 使用:
+```js
+this.$bottomTip('hello')
+```
diff --git a/docs/frontend/global-methods/guide.md b/docs/frontend/global-methods/guide.md
new file mode 100644
index 0000000..6804d19
--- /dev/null
+++ b/docs/frontend/global-methods/guide.md
@@ -0,0 +1,56 @@
+# 用户导航
+
+这是在driver.js的基础上改造来的。
+
+### 使用:
+
+- 在 `@/mixins/guide/data` 下创建导航步骤,例如 `test.js`。
+
+- 在需要导航的路由页面里引入 `@/mixins/guide`,并混入 `mixins: [guide.test]`
+
+```js
+//配置导航
+this.$guide.config(config)
+
+//开始一个导航
+this.$guide(start,steps,[,beforeExist])
+
+//退出导航
+this.$guide.exit()
+```
+
+### $guide.config(config)
+
+- config,所有可配置项如下:
+```js
+{
+ stageBackground: "#ffffff",//弹框背景颜色
+ doneBtnText: "完成", //完成按钮的文字
+ closeBtnText: "关闭", //关闭按钮的文字
+ nextBtnText: "下一步", //下一步按钮的文字
+ prevBtnText: "上一步", //上一步按钮的文字
+}
+```
+
+### $guide(start,steps,[,beforeExist])
+
+- `start` : `number / string`,从第几个步骤开始,`number` 型从0开始,`string` 型可以为 `'first'` 或 `'last'`。
+
+- `step` : `array`,导航步骤数组,所有可配置项如下:
+```js
+{
+ ...config,
+ element: string, 用于querySelector,
+ content: string, 弹框内容,可以使用html,
+ forceShowPrevBtn: boolean, 是否强制显示上一步按钮
+ forceShowNextBtn: boolean, 是否强制显示下一步按钮
+ onPrevious: function, 跳转到上一个导航步骤前触发,返回false或Promise.reject()来阻止跳转
+ onNext: function, 跳转到下一个导航步骤前触发,返回false或Promise.reject()来阻止跳转
+}
+```
+
+- `beforeExist` : `function`,退出导航前触发,回调参数是一个 `boolean`,表示当前是否是最后一个步骤,返回 `false` 或 `Promise.reject()` 来阻止退出。
+
+### $guide.exit()
+
+退出导航,会触发 `beforeExist` 钩子
diff --git a/docs/frontend/global-methods/image-viewer.md b/docs/frontend/global-methods/image-viewer.md
new file mode 100644
index 0000000..b4c5f6e
--- /dev/null
+++ b/docs/frontend/global-methods/image-viewer.md
@@ -0,0 +1,17 @@
+# 图片预览
+
+### 使用:
+
+```js
+//开始预览
+this.$image({index, urlList})
+
+//退出预览
+this.$image.close()
+```
+
+### $image({index, urlList})
+
+- `index` : `number`,当前图片在图片数组中的下标。
+
+- `urlList` : `array`,需要预览的图片的url数组
diff --git a/docs/frontend/global-methods/puzzle-verify.md b/docs/frontend/global-methods/puzzle-verify.md
new file mode 100644
index 0000000..21df8a4
--- /dev/null
+++ b/docs/frontend/global-methods/puzzle-verify.md
@@ -0,0 +1,11 @@
+# 拼图滑块验证
+
+
+
+### 使用:
+
+```js
+this.$puzzleVerify().then(...).catch(...)
+```
+
+返回一个 `promise`,如果验证失败会 `reject`,否则 `resolve`
diff --git a/docs/frontend/global-methods/signature.md b/docs/frontend/global-methods/signature.md
new file mode 100644
index 0000000..5aac4d7
--- /dev/null
+++ b/docs/frontend/global-methods/signature.md
@@ -0,0 +1,21 @@
+# 手写签名
+
+### 使用:
+
+```js
+//开始签名
+this.$signature({image, lineWidth, lineColor, onConfirm)
+
+//退出签名
+this.$signature.close()
+```
+
+### $signature({image, lineWidth, lineColor, onConfirm)
+
+- `image` : `string`,需要回显的签名图片的src。
+
+- `lineWidth` : `number`,线的宽度,默认 `6`
+
+- `lineColor` : `string`,线的颜色,默认 `'#000000'`
+
+- `onConfirm` : `function`,签名完毕后触发,回调参数为签名图片的base64
diff --git a/docs/frontend/layout.md b/docs/frontend/layout.md
new file mode 100644
index 0000000..ae37047
--- /dev/null
+++ b/docs/frontend/layout.md
@@ -0,0 +1,52 @@
+# 布局
+
+此布局是在vue-element-admin的基础上改造而来。
+
+实际上这个布局算是二级路由,一级路由是App.vue,这就是为什么经常会看到路由会这么写的原因:
+```json
+{
+ "path": "/",
+ "component": Layout,
+ "children": [
+ {
+ "path": "index",
+ "name": "index",
+ "component": Page,
+ "meta": {"title": "首页"}
+ }
+ ]
+}
+```
+`Layout` 填充到 `App.vue` 里的 ``,而真正的路由页面 `@/views/index` 则填充到 `Layout` 里的 ``。
+
+项目中没有用到 `Layout` 的页面只有 `@/router/constant/modules/app.js` 里的 `login`、`403`、`404` 这三个。
+
+另外可以发现 `App.vue` 使用了 ``,这是为了从 `403`、`404` 返回时能保存之前打开的标签页。
+
+## 多页签
+
+增加了平滑滚动功能,增加了快捷键功能:`ctrl + → 下一个页签`、`ctrl + ← 上一个页签`
+
+::: warning 注意
+多页签在 启用 / 停用 之间切换时,之前缓存的页签实例会清空,也就是说再次打开时会是新的页面
+:::
+
+## 侧边栏
+
+重复点击菜单可刷新路由,折叠时可以选择是否在折叠菜单上显示父级。
+
+侧边栏的滚动分两种情况,一种是整体的滚动,这是用 `` 做的,不过缺点就是移动端体验不好。
+另一种是弹出菜单的滚动,这是用 `css` 做的,不用 `` 是因为没办法避免bug,具体原因可以去看element-ui的 `submenu #handleMouseleave`。
+
+## 全局页脚
+
+只有使用了 `Layout` 组件的路由页面才会有这个页脚。
+这里的实现比较特别,由于路由页面被 `` 包裹,需要将页脚的dom插入到 `` 的dom中,所以使用了这种方法:
+```javascript
+const FooterConstructor = Vue.extend(Footer)
+const footerInstance = new FooterConstructor().$mount()
+this.$refs.scrollbar.$refs.wrap.appendChild(footerInstance.$el)
+```
+至于为什么不用函数式组件,是因为我还不知道怎么样拿到一个函数式组件的dom
+
+
diff --git a/docs/frontend/new.md b/docs/frontend/new.md
new file mode 100644
index 0000000..2ef5755
--- /dev/null
+++ b/docs/frontend/new.md
@@ -0,0 +1,15 @@
+# 新增页面
+
+1. 把数据请求api创建出来,建议在 `@/api`下根据模块区分。
+
+2. 创建路由页面,建议在 `@/views` 下根据模块区分。
+
+3. 如果页面过大过复杂,建议按功能拆分,放在当前页面的文件夹里。
+
+4. 独有的样式同样放在当前页面的文件夹里,能公用的提取到 `@/assets/styles` 里。
+
+5. 创建路由,根据是否需要鉴权,在 `@/router/authority/modules` 或 `@/router/constant/modules` 下创建,这两个文件夹下的js会被自动导出。
+
+6. 如果需要创建vuex模块,请在 `@/store/modules` 下创建,同样的,该文件夹下的js会被自动导出。
+
+7. 如果页面之间存在公共组件,建议抽取出来,根据业务耦合度拆分至 `@/components` 或 `@/bizComponents`
diff --git a/docs/frontend/permission.md b/docs/frontend/permission.md
new file mode 100644
index 0000000..09b1f8a
--- /dev/null
+++ b/docs/frontend/permission.md
@@ -0,0 +1,16 @@
+# 权限
+
+项目使用基于资源url的形式来实现权限控制,说白点就是用户的所有操作都可以用一个url来标识。
+
+鉴权方法为 `@/util/auth.js #auth`。
+
+鉴权流程:
+1. 如果用户的`admin` 字段为1,那么直接放行。
+
+2. 如果访问的 `url` 不在总权限树内,说明该操作无需权限,放行。
+
+3. 如果访问的 `url` 在用户的权限树内,说明有权限,放行。
+
+4. 否则拦截,跳转至403页面。
+
+当然前端的权限控制只是过滤一小部分,真正的工作还是由后端完成。
diff --git a/docs/frontend/plugins.md b/docs/frontend/plugins.md
new file mode 100644
index 0000000..5b8a0ec
--- /dev/null
+++ b/docs/frontend/plugins.md
@@ -0,0 +1,18 @@
+# 插件
+
+## canvas动画
+
+所有动画位于 `@/plugin/canvasAnimation`下,使用 `new Animation(canvas)`的方式来创建一个动画。
+想停止的话调用 `Animation.stop()` 即可。
+
+## 图片压缩
+
+支持 `png`、`jpg` 两种格式的图片,使用方法参考 `@/views/example/developingTest/components/ImageCompressTest.vue`。
+
+::: tip
+由于是以 `worker` 的形式调用,所以需要准备 `cjpeg.min.js` 和 `pngquant.min.js`,这两个文件都放在项目的 `public`下。
+:::
+
+## 其他
+
+此外项目中还有 `live2d` 和 `webgl` 两个插件,有兴趣的可以自行查看。
diff --git a/docs/frontend/router.md b/docs/frontend/router.md
new file mode 100644
index 0000000..ace3536
--- /dev/null
+++ b/docs/frontend/router.md
@@ -0,0 +1,158 @@
+# 路由
+
+## 路由配置项
+
+路由配置项不光参与路由的生成,也参与侧边栏、搜索结果的生成。
+
+### Route Attributes:
+
+| 参数 | 说明 | 类型 | 默认 |
+| ---------- | ---------------------------------------------------- | ------------------- | ----- |
+| hidden | 是否在侧边栏中显示 | `boolean` | - |
+| alwaysShow | 是否总是把只有一个子级的菜单以嵌套模式在侧边栏中展示 | `boolean` | - |
+| sort | 侧边栏的排序值,值越小越靠前 | `number` | 10000 |
+
+### Route.meta Attributes:
+
+| 参数 | 说明 | 类型 | 默认 |
+| ------------ | ------------------------------------------------ | --------- | ----------------------- |
+| title | 路由在侧边栏、面包屑、页签、搜索结果中的显示名称 | `string` | - |
+| icon | 图标名,支持svg-icon、el-icon | `string` | - |
+| affix | 是否在多页签中固定显示 | `boolean` | - |
+| noCache | true时缓存页面 | `boolean` | - |
+| activeMenu | 侧边栏当前激活菜单的index | `string` | - |
+| noAuth | true时路由不需要鉴权 | `boolean` | router/constant下为true |
+| iframe | 需要打开的iframe的地址 | `string` | - |
+| isDetailPage | 是否是详情页 | `boolean` | - |
+
+::: tip 注意
+路由meta上的affix、noAuth、noCache会被子路由继承,优先使用子路由的值
+:::
+
+## 页面缓存
+
+先总结一下路由页面被缓存的条件:
+- 启用了多页签
+- `(route.name || route.meta.isDetailPage) && route.meta.noCache && !route.meta.iframe`
+
+通常情况路由想做缓存都是通过 ``,但是如果是像 `/edit/1`、`/edit/2` 这样的共用路由页面的详情页的话,
+`` 就满足不了需求,因为它是通过组件的 `name` 来区分组件的。
+所以项目中仿照 `` 写了 ``,可以根据当前路由的路径来区分组件。
+
+除此之外还有个问题,在共用了同一个组件的路由之间跳转的话,组件会被复用,假如有以下路由:
+```js
+const component={template:``, data: ()=> ({data:1})}
+
+const routes = [
+ { path: '/foo', component },
+ { path: '/bar', component }
+]
+```
+先访问 `/foo`,然后将输入框的值改为100,再访问 `/bar` ,会发现输入框的值还是100。
+所以在 `router.beforeEach` 中做了判断,如果跳转前后的路由的 `meta.isDetailPage` 均为 `true` 的话,那么借助 `/redirect` 跳转一次,从而避免组件复用的问题
+
+::: warning 注意
+如果不使用meta.isDetailPage的话,需要缓存的页面的 `name` 必须和路由的 `name` 一致
+:::
+
+## 路由白名单
+
+在 `@/router/index.js` 中有这么一句:
+```js
+const whiteList = transformWhiteList(['/login', '/register', '/404', '/403'])
+```
+这个 `whiteList` 就是白名单,里面的值会被转为正则表达式,详细请查看[path-to-regexp文档](https://github.com/pillarjs/path-to-regexp)。
+被`whiteList` 匹配的路由不需要验证,直接放行。
+
+## 首屏加载效果
+
+想体验的可以把 `network` 设为 `slow 3g` 就可以在在线实例看到效果。
+
+原理很简单,在 `index.html` 里有这么一段:
+```html
+
+
+
![]()
+
资源加载中......
+
+
+```
+在 `vuejs` 初始化完成后,`app` 里的内容会被替换,从而实现加载效果。
+
+## 骨架屏
+
+通常情况下,路由组件都是以 `import(...)` 的形式异步引入,
+如果想让路由在加载异步组件时显示,可以使用以下方式:
+```js
+function lazyLoadView(component) {
+ const AsyncHandler = () => ({component, loading: Skeleton})
+ return Promise.resolve({
+ functional: true,
+ render(h, {data, children}) {
+ return h(AsyncHandler, data, children)
+ }
+ })
+}
+
+//将路由配置中的component项改为以下形式
+component: () => lazyLoadView(import(...))
+```
+
+关于 `AsyncHandler` 的更多选项,可以查看[官方文档](https://cn.vuejs.org/v2/guide/components-dynamic-async.html#%E5%A4%84%E7%90%86%E5%8A%A0%E8%BD%BD%E7%8A%B6%E6%80%81)
+
+## 过渡动画
+
+正常 `` 使用过渡动画的方法应该是这样的:
+```html
+
+
+
+
+
+```
+
+但是由于项目中使用了自定义的 ``,所以就变成这样的:
+```html
+
+
+
+
+
+```
+
+具体原因是 `` 中的代码硬编码了 ``,导致如果按照往常写法的话,过渡动画不会生效。
+
+项目中是根据页签的前后位置来决定路由动画的,比如从前面的页签跳转到后面的,那么动画是从左滑出,反之是从右滑出。
+
+::: warning 注意
+只有在启用了多页签的时候才会有上面的效果,否则默认是 `el-fade-in-linear` 动画。
+:::
+
+## iframe
+
+只需要按如下配置即可打开一个iframe:
+```json
+{
+ "path":"/baidu",
+ "meta":{
+ "iframe":"https://www.baidu.com"
+ }
+}
+```
+
+当向上面的路由跳转时,会隐藏路由页面,展示 `