Commit 7280375ab2835e61221afae92aa5e42e9b7b02f5

Authored by Adam
Exists in master

Merge branch 'master' into 'master'

Master

See merge request !7
Showing 314 changed files   Show diff stats
LICENSE 100644 → 100755
1 MIT License 1 MIT License
2 2
3 Copyright (c) 2017-present PanJiaChen 3 Copyright (c) 2017-present PanJiaChen
4 4
5 Permission is hereby granted, free of charge, to any person obtaining a copy 5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal 6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights 7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is 9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions: 10 furnished to do so, subject to the following conditions:
11 11
12 The above copyright notice and this permission notice shall be included in all 12 The above copyright notice and this permission notice shall be included in all
13 copies or substantial portions of the Software. 13 copies or substantial portions of the Software.
14 14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 SOFTWARE. 21 SOFTWARE.
22 22
File was created 1 <p align="center">
2 <img width="320" src="https://wpimg.wallstcn.com/ecc53a42-d79b-42e2-8852-5126b810a4c8.svg">
3 </p>
4
5 <p align="center">
6 <a href="https://github.com/vuejs/vue">
7 <img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
8 </a>
9 <a href="https://github.com/ElemeFE/element">
10 <img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
11 </a>
12 <a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
13 <img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Estado de Construcción">
14 </a>
15 <a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
16 <img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="Licencia">
17 </a>
18 <a href="https://github.com/PanJiaChen/vue-element-admin/releases">
19 <img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="Liberación Github">
20 </a>
21 <a href="https://gitter.im/vue-element-admin/discuss">
22 <img src="https://badges.gitter.im/Join%20Chat.svg" alt="Gitter">
23 </a>
24 <a href="https://panjiachen.github.io/vue-element-admin-site/donate">
25 <img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="Donación">
26 </a>
27 </p>
28
29 Español | [English](./README.md) | [简体中文](./README.zh-CN.md) | [日本語](./README.ja.md)
30
31 ## Introducción
32
33 [vue-element-admin](https://panjiachen.github.io/vue-element-admin) es una interfáz de administración preparada para producción. Está basada en [vue](https://github.com/vuejs/vue) y usa [element-ui](https://github.com/ElemeFE/element) como conjunto de herramientas de interfáz de usuario.
34
35 Vue Element Admin es una solución práctica basada en la nueva plataforma de desarrollo de vue, construida con soporte a i18 para el manejo de múltiples lenguajes, plantillas estándares para aplicaciones de negocio y un conjunto de asombrosas características. Esta herramienta ayuda a construir largas y complejas Aplicacones de una sola página (SPA). Creo que lo que necesites hacer, este proyecto te ayudará.
36
37 - [Vista Prévia de la Aplicación](https://panjiachen.github.io/vue-element-admin)
38
39 - [Documentación](https://panjiachen.github.io/vue-element-admin-site/)
40
41 - [Canal de Gitter](https://gitter.im/vue-element-admin/discuss)
42
43 - [Para Donaciones](https://panjiachen.github.io/vue-element-admin-site/donate/)
44
45 - [Enlace de Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
46
47 - [Canal de Gitee](https://panjiachen.gitee.io/vue-element-admin/)
48
49 - Plantilla base recomendada para usar: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
50 - Aplicación de Escritorio: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
51 - Plantilla de Typescript: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Créditos: [@Armour](https://github.com/Armour))
52 - [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
53
54 **Después de la versión `v4.1.0+`, la rama por defecto master no tendrá soporte para i18n. Por favor use [i18n](https://github.com/PanJiaChen/vue-element-admin/tree/i18n), los cambios serán incluidos en la rama master**
55
56 **la versión actual es `v4.0+` construida con `vue-cli`. Si encuentra algún problema, por favor coloque un [issue](https://github.com/PanJiaChen/vue-element-admin/issues/new). Si desea usar la versión anterior, puede cambiar de rama a [tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0), no relacionado con `vue-cli`**
57
58 **Este proyecto no está soportado para versiones muy viejas de navegadores (e.g. IE).**
59
60 ## Preparación
61
62 Necesita instalar [node](https://nodejs.org/) y [git](https://git-scm.com/) localmente. El proyecto es basado en [ES2015+](https://es6.ruanyifeng.com/), [vue](https://cn.vuejs.org/index.html), [vuex](https://vuex.vuejs.org/zh-cn/), [vue-router](https://router.vuejs.org/zh-cn/), [vue-cli](https://github.com/vuejs/vue-cli) , [axios](https://github.com/axios/axios) and [element-ui](https://github.com/ElemeFE/element), toda la solicitud de datos simulada se realiza a través de [Mock.js](https://github.com/nuysoft/Mock).
63 Entendiendo y aprendiendo esto pudiera ayudarle con su proyecto.
64
65 <p align="center">
66 <img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
67 </p>
68
69 ## Patrocinantes
70
71 Se un patrocinante y pon tu logo en nuestro README on GitHub con un enlace directo a tu sitio web. [[Se un Patrocinante]](https://www.patreon.com/panjiachen)
72
73 <a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Plantilla de Dashboard de administración hecha con Vue, React y Angular.</p>
74
75 ## Características
76
77 ```
78 - Iniciar / Cerrar Sesión
79
80 - Permisos de Authentication
81 - Página de Permisos
82 - Directivas de permisos
83 - Página de configuración de permisos
84 - Autenticación por dos pasos
85
86 - Construcción Multi-entorno
87 - dev sit stage producción
88
89 - Características Globales
90 - I18n
91 - Temas dinámicos
92 - Dynamic sidebar (soporte a rutas multi-nivel)
93 - Barra de rutas dinámica
94 - Tags-view (Tab page Support right-click operation)
95 - Svg Sprite
96 - Datos de simulación con Mock
97 - Pantalla completa
98 - Responsive Sidebar
99
100 - Editor
101 - Editor de Texto Enriquecido
102 - Editor Markdown
103 - Editor JSON
104
105 - Excel
106 - Exportación a Excel
107 - Carga de Excel
108 - Visualización de Excel
109 - Exportación como zip
110
111 - Tabla
112 - Tabla Dinámica
113 - Tabla con Arrastrar y Soltar
114 - Tabla de edición en línea
115
116 - Páginas de Error
117 - 401
118 - 404
119
120 - Componentes
121 - Carga de Avatar
122 - Botón para subir al inicio
123 - Arrastrar y Soltar (Diaglogo)
124 - Arrastrar y Soltar (Seleccionar)
125 - Arrastrar y Soltar (Kanban)
126 - Arrastrar y Soltar (Lista)
127 - Panel de división
128 - Componente para soltar archivos
129 - Adhesión de objetos
130 - Contador hasta
131
132 - Ejemplo Avanzado
133 - Registro de Errores
134 - Tablero de indicadores
135 - Página de Guías
136 - ECharts (Gráficos)
137 - Portapapeles
138 - Convertidor de Markdown a html
139 ```
140
141 ## Iniciando
142
143 ```bash
144 # clone el proyecto
145 git clone https://github.com/PanJiaChen/vue-element-admin.git
146
147 # vaya al directorio clonado
148 cd vue-element-admin
149
150 # instale las dependencias
151 npm install
152
153 # corra el proyecto como desarrollador
154 npm run dev
155 ```
156
157 Automáticamente se abrirá el siguiente enlace en su navegador http://localhost:9527
158
159 ## Construcción
160
161 ```bash
162 # Construcción para entornos de prueba
163 npm run build:stage
164
165 # Construcción para entornos de producción
166 npm run build:prod
167 ```
168
169 ## Avanzado
170
171 ```bash
172 # Vista previa con efectos de entorno
173 npm run preview
174
175 # Vista previa con efectos + análisis de recursos estáticos
176 npm run preview -- --report
177
178 # Chequeo de formato de código
179 npm run lint
180
181 # Chequeo de formato de código y auto-corrección
182 npm run lint -- --fix
183 ```
184
185 Vaya a [Documentación](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) para mayor información
186
187 ## Registro de Cambios
188
189 Los cambios detallados por cada liberación se encuentran en [notas de liberación](https://github.com/PanJiaChen/vue-element-admin/releases).
190
191 ## Demostración en línea
192
193 [Vista Prévia de la Aplicación](https://panjiachen.github.io/vue-element-admin)
194
195 ## Donación
196
197 Si este proyecto es de mucha ayuda para ti, puedes comprarle al autor un vaso de jugo :tropical_drink:
198
199 ![Donar](https://wpimg.wallstcn.com/bd273f0d-83a0-4ef2-92e1-9ac8ed3746b9.png)
200
201 [dona por Paypal](https://www.paypal.me/panfree23)
202
203 [Comprame un Café](https://www.buymeacoffee.com/Pan)
204
205 ## Navegadores Soportados
206
207 Navegadores modernos e Internet Explorer 10+.
208
209 | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
210 | --------- | --------- | --------- | --------- |
211 | IE10, IE11, Edge| últimas 2 versiones| últimas 2 versiones| últimas 2 versiones
212
213 ## Licencia
214
215 [MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
216
217 Copyright (c) 2017-presente PanJiaChen
218
File was created 1 <p align="center">
2 <img width="320" src="https://wpimg.wallstcn.com/ecc53a42-d79b-42e2-8852-5126b810a4c8.svg">
3 </p>
4
5 <p align="center">
6 <a href="https://github.com/vuejs/vue">
7 <img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
8 </a>
9 <a href="https://github.com/ElemeFE/element">
10 <img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
11 </a>
12 <a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
13 <img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
14 </a>
15 <a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
16 <img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
17 </a>
18 <a href="https://github.com/PanJiaChen/vue-element-admin/releases">
19 <img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
20 </a>
21 <a href="https://gitter.im/vue-element-admin/discuss">
22 <img src="https://badges.gitter.im/Join%20Chat.svg" alt="gitter">
23 </a>
24 <a href="https://panjiachen.gitee.io/vue-element-admin-site/zh/donate">
25 <img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
26 </a>
27 </p>
28
29 日本語 | [English](./README.md) | [简体中文](./README.zh-CN.md) | [Spanish](./README.es.md)
30
31 ## 概要
32
33 [vue-element-admin](https://panjiachen.github.io/vue-element-admin) は管理画面のフロントエンドのインタフェース,[vue](https://github.com/vuejs/vue) と [element-ui](https://github.com/ElemeFE/element)を使っています。i18nの多言語対応、可変ルート、権限、典型的なビジネスアプリテンプレートであり、豊富なコンポーネントを提供しています、素早くビジネス用の管理画面の現型を構築に役立ちます。
34
35 - [デモページ](https://panjiachen.github.io/vue-element-admin)
36
37 - [ドキュメント](https://panjiachen.github.io/vue-element-admin-site/)
38
39 - [Gitter](https://gitter.im/vue-element-admin/discuss)
40
41 - [Donate](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate)
42
43 - [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
44
45 - おすすめシンプルテンプレート: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
46 - デスクトップバージョン: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
47 - Typescriptバージョン: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (鸣谢: [@Armour](https://github.com/Armour))
48 - [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
49
50 **After the `v4.1.0+` version, the default master branch will not support i18n. Please use [i18n Branch](https://github.com/PanJiaChen/vue-element-admin/tree/i18n), it will keep up with the master update**
51
52 **現在のバージョン `v4.0+` は `vue-cli` で構築,バグ報告は[issue](https://github.com/PanJiaChen/vue-element-admin/issues/new)のissueでお願いします。旧バージョン[tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0)もあります。`vue-cli`に依存しないです。**
53
54 **低いバージョンのブラウザはサーポートしないです(例えば ie),必要があれば polyfill を追加してください。 [詳細はこちら](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**
55
56 ## 前準備
57
58 ローカル環境に [node](http://nodejs.org/) と [git](https://git-scm.com/)をインストールが必要です。[ES2015+](http://es6.ruanyifeng.com/)、[vue](https://cn.vuejs.org/index.html)、[vuex](https://vuex.vuejs.org/zh-cn/)、[vue-router](https://router.vuejs.org/zh-cn/) 、[vue-cli](https://github.com/vuejs/vue-cli) 、[axios](https://github.com/axios/axios) 和 [element-ui](https://github.com/ElemeFE/element)で開発しています。Requestは[Mock.js](https://github.com/nuysoft/Mock)のモックデータを使っています。
59
60 **バグ修正や新規機能追加のissue と pull requestは大歓迎です。**
61
62 <p align="center">
63 <img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
64 </p>
65
66 ## Sponsors
67
68 Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
69
70 <a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
71
72 ## 機能一覧
73
74 ```
75 - ログイン / ログアウト
76
77 - Auth認証
78 - ページ権限
79 - 権限パーミッション
80 - 権限設定
81 - 外部IDでログイン
82
83 - 複数環境デプロイ
84 - dev sit stage prod
85
86 - 共通機能
87 - 多言語切替
88 - テーマ切替
89 - サイトメニュー(ルートから生成)
90 - Breadcrumb Navigation
91 - Tag Navigation
92 - Svg Sprite Icon
93 - ローカル/バックエンド モック データ
94 - Screenfull
95
96 - WYSIWYG
97 - TinyMCE
98 - Markdown
99 - JSON
100
101 - Excel
102 - エクスポート
103 - インポート
104 - リード
105 - Zip
106
107 - Table
108 - Dynamic Table
109 - Drag And Drop Table
110 - Inline Edit Table
111
112 - Error Page
113 - 401
114 - 404
115
116 - コンポーネント
117 - Avatar Upload
118 - Back To Top
119 - Drag Dialog
120 - Drag Select
121 - Drag Kanban
122 - Drag List
123 - SplitPane
124 - Dropzone
125 - Sticky
126 - CountTo
127
128 - Advanced Example
129 - Error Log
130 - Dashboard
131 - Guide Page
132 - ECharts
133 - Clipboard
134 - Markdown to html
135 ```
136
137 ## Getting started
138
139 ```bash
140 # clone the project
141 git clone -b i18n git@github.com:PanJiaChen/vue-element-admin.git
142
143 # enter the project directory
144 cd vue-element-admin
145
146 # install dependency
147 npm install
148
149 # develop
150 npm run dev
151 ```
152
153 This will automatically open http://localhost:9527
154
155 ## Build
156
157 ```bash
158 # build for test environment
159 npm run build:stage
160
161 # build for production environment
162 npm run build:prod
163 ```
164
165 ## Advanced
166
167 ```bash
168 # preview the release environment effect
169 npm run preview
170
171 # preview the release environment effect + static resource analysis
172 npm run preview -- --report
173
174 # code format check
175 npm run lint
176
177 # code format check and auto fix
178 npm run lint -- --fix
179 ```
180
181 Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information
182
183 ## Changelog
184
185 Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
186
187 ## Online Demo
188
189 [Preview](https://panjiachen.github.io/vue-element-admin)
190
191 ## Donate
192
193 If you find this project useful, you can buy author a glass of juice :tropical_drink:
194
195 ![donate](https://wpimg.wallstcn.com/bd273f0d-83a0-4ef2-92e1-9ac8ed3746b9.png)
196
197 [Paypal Me](https://www.paypal.me/panfree23)
198
199 [Buy me a coffee](https://www.buymeacoffee.com/Pan)
200
201 ## Browsers support
202
203 Modern browsers and Internet Explorer 10+.
204
205 | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
206 | --------- | --------- | --------- | --------- |
207 | IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
208
209 ## License
210
211 [MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
212
213 Copyright (c) 2017-present PanJiaChen
214
1 <p align="center">
2 <img width="320" src="https://wpimg.wallstcn.com/ecc53a42-d79b-42e2-8852-5126b810a4c8.svg">
3 </p>
1 4
5 <p align="center">
6 <a href="https://github.com/vuejs/vue">
7 <img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
8 </a>
9 <a href="https://github.com/ElemeFE/element">
10 <img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
11 </a>
12 <a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
13 <img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
14 </a>
15 <a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
16 <img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
17 </a>
18 <a href="https://github.com/PanJiaChen/vue-element-admin/releases">
19 <img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
20 </a>
21 <a href="https://gitter.im/vue-element-admin/discuss">
22 <img src="https://badges.gitter.im/Join%20Chat.svg" alt="gitter">
23 </a>
24 <a href="https://panjiachen.github.io/vue-element-admin-site/donate">
25 <img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
26 </a>
27 </p>
2 28
3 ## Build Setup 29 English | [简体中文](./README.zh-CN.md) | [日本語](./README.ja.md) | [Spanish](./README.es.md)
4 30
31 ## Introduction
32
33 [vue-element-admin](https://panjiachen.github.io/vue-element-admin) is a production-ready front-end solution for admin interfaces. It is based on [vue](https://github.com/vuejs/vue) and uses the UI Toolkit [element-ui](https://github.com/ElemeFE/element).
34
35 [vue-element-admin](https://panjiachen.github.io/vue-element-admin) is based on the newest development stack of vue and it has a built-in i18n solution, typical templates for enterprise applications, and lots of awesome features. It helps you build large and complex Single-Page Applications. I believe whatever your needs are, this project will help you.
36
37 - [Preview](https://panjiachen.github.io/vue-element-admin)
38
39 - [Documentation](https://panjiachen.github.io/vue-element-admin-site/)
40
41 - [Gitter](https://gitter.im/vue-element-admin/discuss)
42
43 - [Donate](https://panjiachen.github.io/vue-element-admin-site/donate/)
44
45 - [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
46
47 - [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览
48
49 - Base template recommends using: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
50 - Desktop: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
51 - Typescript: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
52 - [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
53
54 **After the `v4.1.0+` version, the default master branch will not support i18n. Please use [i18n Branch](https://github.com/PanJiaChen/vue-element-admin/tree/i18n), it will keep up with the master update**
55
56 **The current version is `v4.0+` build on `vue-cli`. If you find a problem, please put [issue](https://github.com/PanJiaChen/vue-element-admin/issues/new). If you want to use the old version , you can switch branch to [tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0), it does not rely on `vue-cli`**
57
58 **This project does not support low version browsers (e.g. IE). Please add polyfill by yourself.**
59
60 ## Preparation
61
62 You need to install [node](https://nodejs.org/) and [git](https://git-scm.com/) locally. The project is based on [ES2015+](https://es6.ruanyifeng.com/), [vue](https://cn.vuejs.org/index.html), [vuex](https://vuex.vuejs.org/zh-cn/), [vue-router](https://router.vuejs.org/zh-cn/), [vue-cli](https://github.com/vuejs/vue-cli) , [axios](https://github.com/axios/axios) and [element-ui](https://github.com/ElemeFE/element), all request data is simulated using [Mock.js](https://github.com/nuysoft/Mock).
63 Understanding and learning this knowledge in advance will greatly help the use of this project.
64
65 <p align="center">
66 <img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
67 </p>
68
69 ## Sponsors
70
71 Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
72
73 <a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
74
75 ## Features
76
77 ```
78 - Login / Logout
79
80 - Permission Authentication
81 - Page permission
82 - Directive permission
83 - Permission configuration page
84 - Two-step login
85
86 - Multi-environment build
87 - dev sit stage prod
88
89 - Global Features
90 - I18n
91 - Multiple dynamic themes
92 - Dynamic sidebar (supports multi-level routing)
93 - Dynamic breadcrumb
94 - Tags-view (Tab page Support right-click operation)
95 - Svg Sprite
96 - Mock data
97 - Screenfull
98 - Responsive Sidebar
99
100 - Editor
101 - Rich Text Editor
102 - Markdown Editor
103 - JSON Editor
104
105 - Excel
106 - Export Excel
107 - Upload Excel
108 - Visualization Excel
109 - Export zip
110
111 - Table
112 - Dynamic Table
113 - Drag And Drop Table
114 - Inline Edit Table
115
116 - Error Page
117 - 401
118 - 404
119
120 - Components
121 - Avatar Upload
122 - Back To Top
123 - Drag Dialog
124 - Drag Select
125 - Drag Kanban
126 - Drag List
127 - SplitPane
128 - Dropzone
129 - Sticky
130 - CountTo
131
132 - Advanced Example
133 - Error Log
134 - Dashboard
135 - Guide Page
136 - ECharts
137 - Clipboard
138 - Markdown to html
139 ```
140
141 ## Getting started
5 142
6 ```bash 143 ```bash
144 # clone the project
145 git clone -b i18n git@github.com:PanJiaChen/vue-element-admin.git
7 146
8 # enter the project directory 147 # enter the project directory
9 cd gulu-admin 148 cd vue-element-admin
10 149
11 # install dependency 150 # install dependency
12 npm install 151 npm install
13 152
14 # develop 153 # develop
15 npm run dev 154 npm run dev
16 ``` 155 ```
17 156
18 This will automatically open http://localhost:9528 157 This will automatically open http://localhost:9527
19 158
20 ## Build 159 ## Build
21 160
22 ```bash 161 ```bash
23 # build for test environment 162 # build for test environment
24 npm run build:stage 163 npm run build:stage
25 164
26 # build for production environment 165 # build for production environment
27 npm run build:prod 166 npm run build:prod
28 ``` 167 ```
29 168
30 ## Advanced 169 ## Advanced
31 170
32 ```bash 171 ```bash
33 # preview the release environment effect 172 # preview the release environment effect
34 npm run preview 173 npm run preview
35 174
36 # preview the release environment effect + static resource analysis 175 # preview the release environment effect + static resource analysis
37 npm run preview -- --report 176 npm run preview -- --report
38 177
39 # code format check 178 # code format check
40 npm run lint 179 npm run lint
41 180
42 # code format check and auto fix 181 # code format check and auto fix
43 npm run lint -- --fix 182 npm run lint -- --fix
44 ``` 183 ```
45 184
46 Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information 185 Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information
47 186
48 ## Demo 187 ## Changelog
49 188
50 ![demo](https://github.com/PanJiaChen/PanJiaChen.github.io/blob/master/images/demo.gif) 189 Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
51 190
52 ## Extra 191 ## Online Demo
53 192
54 If you want router permission && generate menu by user roles , you can use this branch [permission-control](https://github.com/PanJiaChen/vue-admin-template/tree/permission-control) 193 [Preview](https://panjiachen.github.io/vue-element-admin)
55 194
56 For `typescript` version, you can use [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour)) 195 ## Donate
57 196
58 ## Related Project 197 If you find this project useful, you can buy author a glass of juice :tropical_drink:
59 198
60 - [vue-element-admin](https://github.com/PanJiaChen/vue-element-admin) 199 ![donate](https://wpimg.wallstcn.com/bd273f0d-83a0-4ef2-92e1-9ac8ed3746b9.png)
61 200
62 - [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin) 201 [Paypal Me](https://www.paypal.me/panfree23)
63 202
64 - [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) 203 [Buy me a coffee](https://www.buymeacoffee.com/Pan)
65 204
66 - [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312) 205 ## Browsers support
206
207 Modern browsers and Internet Explorer 10+.
208
209 | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
210 | --------- | --------- | --------- | --------- |
211 | IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
212
213 ## License
67 214
215 [MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
68 216
217 Copyright (c) 2017-present PanJiaChen
69 218
File was created 1 <p align="center">
2 <img width="320" src="https://wpimg.wallstcn.com/ecc53a42-d79b-42e2-8852-5126b810a4c8.svg">
3 </p>
4
5 <p align="center">
6 <a href="https://github.com/vuejs/vue">
7 <img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
8 </a>
9 <a href="https://github.com/ElemeFE/element">
10 <img src="https://img.shields.io/badge/element--ui-2.7.0-brightgreen.svg" alt="element-ui">
11 </a>
12 <a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
13 <img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
14 </a>
15 <a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
16 <img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
17 </a>
18 <a href="https://github.com/PanJiaChen/vue-element-admin/releases">
19 <img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
20 </a>
21 <a href="https://gitter.im/vue-element-admin/discuss">
22 <img src="https://badges.gitter.im/Join%20Chat.svg" alt="gitter">
23 </a>
24 <a href="https://panjiachen.gitee.io/vue-element-admin-site/zh/donate">
25 <img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
26 </a>
27 </p>
28
29 简体中文 | [English](./README.md) | [日本語](./README.ja.md) | [Spanish](./README.es.md)
30
31 ## 简介
32
33 [vue-element-admin](https://panjiachen.github.io/vue-element-admin) 是一个后台前端解决方案,它基于 [vue](https://github.com/vuejs/vue) 和 [element-ui](https://github.com/ElemeFE/element)实现。它使用了最新的前端技术栈,内置了 i18n 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。
34
35 - [在线预览](https://panjiachen.github.io/vue-element-admin)
36
37 - [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
38
39 - [Gitter 讨论组](https://gitter.im/vue-element-admin/discuss)
40
41 - [Donate](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate)
42
43 - [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
44
45 - [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 在线预览(国内用户可访问该地址)
46
47 - [国内访问文档](https://panjiachen.gitee.io/vue-element-admin-site/zh/) 文档(方便没翻墙的用户查看)
48
49 - 基础模板建议使用: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
50 - 桌面端: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
51 - Typescript 版: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (鸣谢: [@Armour](https://github.com/Armour))
52 - [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
53
54 **`v4.1.0+`版本之后默认 master 分支将不支持国际化,有需要的请使用[i18n](https://github.com/PanJiaChen/vue-element-admin/tree/i18n)分支,它会和 master 保持同步更新**
55
56 **该项目不支持低版本浏览器(如 ie),有需求请自行添加 polyfill [详情](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**
57
58 **目前版本为 `v4.0+` 基于 `vue-cli` 进行构建,若发现问题,欢迎提[issue](https://github.com/PanJiaChen/vue-element-admin/issues/new)。若你想使用旧版本,可以切换分支到[tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0),它不依赖 `vue-cli`**
59
60 群主 **[圈子](https://jianshiapp.com/circles/1209)** 群主会经常分享一些技术相关的东西,或者加入 [qq 群](https://github.com/PanJiaChen/vue-element-admin/issues/602) 或者关注 [微博](https://weibo.com/u/3423485724?is_all=1)
61
62 ## 前序准备
63
64 你需要在本地安装 [node](http://nodejs.org/) 和 [git](https://git-scm.com/)。本项目技术栈基于 [ES2015+](http://es6.ruanyifeng.com/)、[vue](https://cn.vuejs.org/index.html)、[vuex](https://vuex.vuejs.org/zh-cn/)、[vue-router](https://router.vuejs.org/zh-cn/) 、[vue-cli](https://github.com/vuejs/vue-cli) 、[axios](https://github.com/axios/axios) 和 [element-ui](https://github.com/ElemeFE/element),所有的请求数据都使用[Mock.js](https://github.com/nuysoft/Mock)进行模拟,提前了解和学习这些知识会对使用本项目有很大的帮助。
65
66 同时配套了系列教程文章,如何从零构建后一个完整的后台项目,建议大家先看完这些文章再来实践本项目
67
68 - [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
69 - [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
70 - [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
71 - [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
72 - [手摸手,带你用vue撸后台 系列五(v4.0新版本)](https://juejin.im/post/5c92ff94f265da6128275a85)
73 - [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
74 - [手摸手,带你优雅的使用 icon](https://juejin.im/post/59bb864b5188257e7a427c09)
75 - [手摸手,带你用合理的姿势使用 webpack4(上)](https://juejin.im/post/5b56909a518825195f499806)
76 - [手摸手,带你用合理的姿势使用 webpack4(下)](https://juejin.im/post/5b5d6d6f6fb9a04fea58aabc)
77
78 **如有问题请先看上述使用文档和文章,若不能满足,欢迎 issue 和 pr**
79
80 <p align="center">
81 <img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
82 </p>
83
84 ## Sponsors
85
86 Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
87
88 <a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
89
90 ## 功能
91
92 ```
93 - 登录 / 注销
94
95 - 权限验证
96 - 页面权限
97 - 指令权限
98 - 权限配置
99 - 二步登录
100
101 - 多环境发布
102 - dev sit stage prod
103
104 - 全局功能
105 - 国际化多语言
106 - 多种动态换肤
107 - 动态侧边栏(支持多级路由嵌套)
108 - 动态面包屑
109 - 快捷导航(标签页)
110 - Svg Sprite 图标
111 - 本地/后端 mock 数据
112 - Screenfull全屏
113 - 自适应收缩侧边栏
114
115 - 编辑器
116 - 富文本
117 - Markdown
118 - JSON 等多格式
119
120 - Excel
121 - 导出excel
122 - 导入excel
123 - 前端可视化excel
124 - 导出zip
125
126 - 表格
127 - 动态表格
128 - 拖拽表格
129 - 内联编辑
130
131 - 错误页面
132 - 401
133 - 404
134
135 - 組件
136 - 头像上传
137 - 返回顶部
138 - 拖拽Dialog
139 - 拖拽Select
140 - 拖拽看板
141 - 列表拖拽
142 - SplitPane
143 - Dropzone
144 - Sticky
145 - CountTo
146
147 - 综合实例
148 - 错误日志
149 - Dashboard
150 - 引导页
151 - ECharts 图表
152 - Clipboard(剪贴复制)
153 - Markdown2html
154 ```
155
156 ## 开发
157
158 ```bash
159 # 克隆项目
160 git clone -b i18n git@github.com:PanJiaChen/vue-element-admin.git
161
162 # 进入项目目录
163 cd vue-element-admin
164
165 # 安装依赖
166 npm install
167
168 # 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
169 npm install --registry=https://registry.npm.taobao.org
170
171 # 启动服务
172 npm run dev
173 ```
174
175 浏览器访问 http://localhost:9527
176
177 ## 发布
178
179 ```bash
180 # 构建测试环境
181 npm run build:stage
182
183 # 构建生产环境
184 npm run build:prod
185 ```
186
187 ## 其它
188
189 ```bash
190 # 预览发布环境效果
191 npm run preview
192
193 # 预览发布环境效果 + 静态资源分析
194 npm run preview -- --report
195
196 # 代码格式检查
197 npm run lint
198
199 # 代码格式检查并自动修复
200 npm run lint -- --fix
201 ```
202
203 更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
204
205 ## Changelog
206
207 Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
208
209 ## Online Demo
210
211 [在线 Demo](https://panjiachen.github.io/vue-element-admin)
212
213 ## Donate
214
215 如果你觉得这个项目帮助到了你,你可以帮作者买一杯果汁表示鼓励 :tropical_drink:
216 ![donate](https://panjiachen.github.io/donate/donation.png)
217
218 [更多捐赠方式](https://panjiachen.gitee.io/vue-element-admin-site/zh/donate)
219
220 [Paypal Me](https://www.paypal.me/panfree23)
221
222 [Buy me a coffee](https://www.buymeacoffee.com/Pan)
223
224 ## Browsers support
225
226 Modern browsers and Internet Explorer 10+.
227
228 | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
229 | --------- | --------- | --------- | --------- |
230 | IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
231
232 ## License
233
234 [MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
235
236 Copyright (c) 2017-present PanJiaChen
237
1 // module.exports = {
2 // presets: [
3 // '@vue/app'
4 // ]
5 // }
6 // "@babel/preset-env",
7 // {
8 // "modules": false
9 // },
10 module.exports = { 1 module.exports = {
11 "presets": [ 2 presets: [
12 [ 3 '@vue/app'
13 '@vue/app',
14 // '@babel/preset-env',
15 {
16 // "modules": false,
17 // "targets": { // 配置代码的运行环境
18 // "chrome": 64
19 // },
20 // "useBuiltIns": true // 开启对 babel-polyfill 的优化
21 }
22 ]
23 ],
24 "plugins": [
25 [
26 "component",
27 {
28 "libraryName": "element-ui",
29 "styleLibraryName": "theme-chalk"
30 }
31 ]
32 ] 4 ]
33 } 5 }
34 6
build/index.js 100644 → 100755
1 const { run } = require('runjs') 1 const { run } = require('runjs')
2 const chalk = require('chalk') 2 const chalk = require('chalk')
3 const config = require('../vue.config.js') 3 const config = require('../vue.config.js')
4 const rawArgv = process.argv.slice(2) 4 const rawArgv = process.argv.slice(2)
5 const args = rawArgv.join(' ') 5 const args = rawArgv.join(' ')
6 6
7 if (process.env.npm_config_preview || rawArgv.includes('--preview')) { 7 if (process.env.npm_config_preview || rawArgv.includes('--preview')) {
8 const report = rawArgv.includes('--report') 8 const report = rawArgv.includes('--report')
9 9
10 run(`vue-cli-service build ${args}`) 10 run(`vue-cli-service build ${args}`)
11 11
12 const port = 9526 12 const port = 9526
13 const publicPath = config.publicPath 13 const publicPath = config.publicPath
14 14
15 var connect = require('connect') 15 var connect = require('connect')
16 var serveStatic = require('serve-static') 16 var serveStatic = require('serve-static')
17 const app = connect() 17 const app = connect()
18 18
19 app.use( 19 app.use(
20 publicPath, 20 publicPath,
21 serveStatic('./dist', { 21 serveStatic('./dist', {
22 index: ['index.html', '/'] 22 index: ['index.html', '/']
23 }) 23 })
24 ) 24 )
25 25
26 app.listen(port, function () { 26 app.listen(port, function () {
27 console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`)) 27 console.log(chalk.green(`> Preview at http://localhost:${port}${publicPath}`))
28 if (report) { 28 if (report) {
29 console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`)) 29 console.log(chalk.green(`> Report at http://localhost:${port}${publicPath}report.html`))
30 } 30 }
31 31
32 }) 32 })
33 } else { 33 } else {
34 run(`vue-cli-service build ${args}`) 34 run(`vue-cli-service build ${args}`)
35 } 35 }
36 36
jest.config.js 100644 → 100755
1 module.exports = { 1 module.exports = {
2 moduleFileExtensions: ['js', 'jsx', 'json', 'vue'], 2 moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
3 transform: { 3 transform: {
4 '^.+\\.vue$': 'vue-jest', 4 '^.+\\.vue$': 'vue-jest',
5 '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$': 5 '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
6 'jest-transform-stub', 6 'jest-transform-stub',
7 '^.+\\.jsx?$': 'babel-jest' 7 '^.+\\.jsx?$': 'babel-jest'
8 }, 8 },
9 moduleNameMapper: { 9 moduleNameMapper: {
10 '^@/(.*)$': '<rootDir>/src/$1' 10 '^@/(.*)$': '<rootDir>/src/$1'
11 }, 11 },
12 snapshotSerializers: ['jest-serializer-vue'], 12 snapshotSerializers: ['jest-serializer-vue'],
13 testMatch: [ 13 testMatch: [
14 '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)' 14 '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
15 ], 15 ],
16 collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'], 16 collectCoverageFrom: ['src/utils/**/*.{js,vue}', '!src/utils/auth.js', '!src/utils/request.js', 'src/components/**/*.{js,vue}'],
17 coverageDirectory: '<rootDir>/tests/unit/coverage', 17 coverageDirectory: '<rootDir>/tests/unit/coverage',
18 // 'collectCoverage': true, 18 // 'collectCoverage': true,
19 'coverageReporters': [ 19 'coverageReporters': [
20 'lcov', 20 'lcov',
21 'text-summary' 21 'text-summary'
22 ], 22 ],
23 testURL: 'http://localhost/' 23 testURL: 'http://localhost/'
24 } 24 }
25 25
1 { 1 {
2 "compilerOptions": { 2 "compilerOptions": {
3 "baseUrl": "./", 3 "baseUrl": "./",
4 "paths": { 4 "paths": {
5 "@/*": ["src/*"] 5 "@/*": ["src/*"]
6 } 6 }
7 }, 7 },
8 "exclude": ["node_modules", "dist"] 8 "exclude": ["node_modules", "dist"]
9 } 9 }
10
File was created 1 import Mock from 'mockjs'
2
3 const List = []
4 const count = 100
5
6 const baseContent = '<p>I am testing data, I am testing data.</p><p><img src="https://wpimg.wallstcn.com/4c69009c-0fd4-4153-b112-6cb53d1cf943"></p>'
7 const image_uri = 'https://wpimg.wallstcn.com/e4558086-631c-425c-9430-56ffb46e70b3'
8
9 for (let i = 0; i < count; i++) {
10 List.push(Mock.mock({
11 id: '@increment',
12 timestamp: +Mock.Random.date('T'),
13 author: '@first',
14 reviewer: '@first',
15 title: '@title(5, 10)',
16 content_short: 'mock data',
17 content: baseContent,
18 forecast: '@float(0, 100, 2, 2)',
19 importance: '@integer(1, 3)',
20 'type|1': ['CN', 'US', 'JP', 'EU'],
21 'status|1': ['published', 'draft'],
22 display_time: '@datetime',
23 comment_disabled: true,
24 pageviews: '@integer(300, 5000)',
25 image_uri,
26 platforms: ['a-platform']
27 }))
28 }
29
30 export default [
31 {
32 url: '/vue-element-admin/article/list',
33 type: 'get',
34 response: config => {
35 const { importance, type, title, page = 1, limit = 20, sort } = config.query
36
37 let mockList = List.filter(item => {
38 if (importance && item.importance !== +importance) return false
39 if (type && item.type !== type) return false
40 if (title && item.title.indexOf(title) < 0) return false
41 return true
42 })
43
44 if (sort === '-id') {
45 mockList = mockList.reverse()
46 }
47
48 const pageList = mockList.filter((item, index) => index < limit * page && index >= limit * (page - 1))
49
50 return {
51 code: 20000,
52 data: {
53 total: mockList.length,
54 items: pageList
55 }
56 }
57 }
58 },
59
60 {
61 url: '/vue-element-admin/article/detail',
62 type: 'get',
63 response: config => {
64 const { id } = config.query
65 for (const article of List) {
66 if (article.id === +id) {
67 return {
68 code: 20000,
69 data: article
70 }
71 }
72 }
73 }
74 },
75
76 {
77 url: '/vue-element-admin/article/pv',
78 type: 'get',
79 response: _ => {
80 return {
81 code: 20000,
82 data: {
83 pvData: [
84 { key: 'PC', pv: 1024 },
85 { key: 'mobile', pv: 1024 },
86 { key: 'ios', pv: 1024 },
87 { key: 'android', pv: 1024 }
88 ]
89 }
90 }
91 }
92 },
93
94 {
95 url: '/vue-element-admin/article/create',
96 type: 'post',
97 response: _ => {
98 return {
99 code: 20000,
100 data: 'success'
101 }
102 }
103 },
104
105 {
106 url: '/vue-element-admin/article/update',
107 type: 'post',
108 response: _ => {
109 return {
110 code: 20000,
111 data: 'success'
112 }
113 }
114 }
115 ]
116
117
1 import Mock from 'mockjs' 1 import Mock from 'mockjs'
2 import { 2 import { param2Obj } from '../src/utils'
3 param2Obj
4 } from '../src/utils'
5 3
6 import user from './user' 4 import user from './user'
7 import table from './table' 5 import role from './role'
6 import article from './article'
7 import search from './remote-search'
8 8
9 const mocks = [ 9 const mocks = [
10 ...user, 10 ...user,
11 ...table 11 ...role,
12 ...article,
13 ...search
12 ] 14 ]
13 15
14 // for front mock 16 // for front mock
15 // please use it cautiously, it will redefine XMLHttpRequest, 17 // please use it cautiously, it will redefine XMLHttpRequest,
16 // which will cause many of your third-party libraries to be invalidated(like progress event). 18 // which will cause many of your third-party libraries to be invalidated(like progress event).
17 export function mockXHR() { 19 export function mockXHR() {
18 // mock patch 20 // mock patch
19 // https://github.com/nuysoft/Mock/issues/300 21 // https://github.com/nuysoft/Mock/issues/300
20 Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send 22 Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
21 Mock.XHR.prototype.send = function () { 23 Mock.XHR.prototype.send = function() {
22 if (this.custom.xhr) { 24 if (this.custom.xhr) {
23 this.custom.xhr.withCredentials = this.withCredentials || false 25 this.custom.xhr.withCredentials = this.withCredentials || false
24 26
25 if (this.responseType) { 27 if (this.responseType) {
26 this.custom.xhr.responseType = this.responseType 28 this.custom.xhr.responseType = this.responseType
27 } 29 }
28 } 30 }
29 this.proxy_send(...arguments) 31 this.proxy_send(...arguments)
30 } 32 }
31 33
32 function XHR2ExpressReqWrap(respond) { 34 function XHR2ExpressReqWrap(respond) {
33 return function (options) { 35 return function(options) {
34 let result = null 36 let result = null
35 if (respond instanceof Function) { 37 if (respond instanceof Function) {
36 const { 38 const { body, type, url } = options
37 body,
38 type,
39 url
40 } = options
41 // https://expressjs.com/en/4x/api.html#req 39 // https://expressjs.com/en/4x/api.html#req
42 result = respond({ 40 result = respond({
43 method: type, 41 method: type,
44 body: JSON.parse(body), 42 body: JSON.parse(body),
45 query: param2Obj(url) 43 query: param2Obj(url)
46 }) 44 })
47 } else { 45 } else {
48 result = respond 46 result = respond
49 } 47 }
50 return Mock.mock(result) 48 return Mock.mock(result)
51 } 49 }
52 } 50 }
53 51
54 for (const i of mocks) { 52 for (const i of mocks) {
55 Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response)) 53 Mock.mock(new RegExp(i.url), i.type || 'get', XHR2ExpressReqWrap(i.response))
56 } 54 }
57 } 55 }
58 56
59 // for mock server 57 // for mock server
60 const responseFake = (url, type, respond) => { 58 const responseFake = (url, type, respond) => {
61 return { 59 return {
62 url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`), 60 url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
63 type: type || 'get', 61 type: type || 'get',
64 response(req, res) { 62 response(req, res) {
65 console.log('request invoke:' + req.path) 63 console.log('request invoke:' + req.path)
66 res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond)) 64 res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
67 } 65 }
68 } 66 }
69 } 67 }
70 68
mock/mock-server.js
1 const chokidar = require('chokidar') 1 const chokidar = require('chokidar')
2 const bodyParser = require('body-parser') 2 const bodyParser = require('body-parser')
3 const chalk = require('chalk') 3 const chalk = require('chalk')
4 const path = require('path') 4 const path = require('path')
5 5
6 const mockDir = path.join(process.cwd(), 'mock') 6 const mockDir = path.join(process.cwd(), 'mock')
7 7
8 function registerRoutes(app) { 8 function registerRoutes(app) {
9 let mockLastIndex 9 let mockLastIndex
10 const { default: mocks } = require('./index.js') 10 const { default: mocks } = require('./index.js')
11 for (const mock of mocks) { 11 for (const mock of mocks) {
12 app[mock.type](mock.url, mock.response) 12 app[mock.type](mock.url, mock.response)
13 mockLastIndex = app._router.stack.length 13 mockLastIndex = app._router.stack.length
14 } 14 }
15 const mockRoutesLength = Object.keys(mocks).length 15 const mockRoutesLength = Object.keys(mocks).length
16 return { 16 return {
17 mockRoutesLength: mockRoutesLength, 17 mockRoutesLength: mockRoutesLength,
18 mockStartIndex: mockLastIndex - mockRoutesLength 18 mockStartIndex: mockLastIndex - mockRoutesLength
19 } 19 }
20 } 20 }
21 21
22 function unregisterRoutes() { 22 function unregisterRoutes() {
23 Object.keys(require.cache).forEach(i => { 23 Object.keys(require.cache).forEach(i => {
24 if (i.includes(mockDir)) { 24 if (i.includes(mockDir)) {
25 delete require.cache[require.resolve(i)] 25 delete require.cache[require.resolve(i)]
26 } 26 }
27 }) 27 })
28 } 28 }
29 29
30 module.exports = app => { 30 module.exports = app => {
31 // es6 polyfill 31 // es6 polyfill
32 require('@babel/register') 32 require('@babel/register')
33 33
34 // parse app.body 34 // parse app.body
35 // https://expressjs.com/en/4x/api.html#req.body 35 // https://expressjs.com/en/4x/api.html#req.body
36 app.use(bodyParser.json()) 36 app.use(bodyParser.json())
37 app.use(bodyParser.urlencoded({ 37 app.use(bodyParser.urlencoded({
38 extended: true 38 extended: true
39 })) 39 }))
40 40
41 const mockRoutes = registerRoutes(app) 41 const mockRoutes = registerRoutes(app)
42 var mockRoutesLength = mockRoutes.mockRoutesLength 42 var mockRoutesLength = mockRoutes.mockRoutesLength
43 var mockStartIndex = mockRoutes.mockStartIndex 43 var mockStartIndex = mockRoutes.mockStartIndex
44 44
45 // watch files, hot reload mock server 45 // watch files, hot reload mock server
46 chokidar.watch(mockDir, { 46 chokidar.watch(mockDir, {
47 ignored: /mock-server/, 47 ignored: /mock-server/,
48 ignoreInitial: true 48 ignoreInitial: true
49 }).on('all', (event, path) => { 49 }).on('all', (event, path) => {
50 if (event === 'change' || event === 'add') { 50 if (event === 'change' || event === 'add') {
51 try { 51 try {
52 // remove mock routes stack 52 // remove mock routes stack
53 app._router.stack.splice(mockStartIndex, mockRoutesLength) 53 app._router.stack.splice(mockStartIndex, mockRoutesLength)
54 54
55 // clear routes cache 55 // clear routes cache
56 unregisterRoutes() 56 unregisterRoutes()
57 57
58 const mockRoutes = registerRoutes(app) 58 const mockRoutes = registerRoutes(app)
59 mockRoutesLength = mockRoutes.mockRoutesLength 59 mockRoutesLength = mockRoutes.mockRoutesLength
60 mockStartIndex = mockRoutes.mockStartIndex 60 mockStartIndex = mockRoutes.mockStartIndex
61 61
62 console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`)) 62 console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`))
63 } catch (error) { 63 } catch (error) {
64 console.error(chalk.redBright(error)) 64 console.log(chalk.redBright(error))
65 } 65 }
66 } 66 }
67 }) 67 })
68 } 68 }
69 69
mock/remote-search.js
File was created 1 import Mock from 'mockjs'
2
3 const NameList = []
4 const count = 100
5
6 for (let i = 0; i < count; i++) {
7 NameList.push(Mock.mock({
8 name: '@first'
9 }))
10 }
11 NameList.push({ name: 'mock-Pan' })
12
13 export default [
14 // username search
15 {
16 url: '/vue-element-admin/search/user',
17 type: 'get',
18 response: config => {
19 const { name } = config.query
20 const mockNameList = NameList.filter(item => {
21 const lowerCaseName = item.name.toLowerCase()
22 return !(name && lowerCaseName.indexOf(name.toLowerCase()) < 0)
23 })
24 return {
25 code: 20000,
26 data: { items: mockNameList }
27 }
28 }
29 },
30
31 // transaction list
32 {
33 url: '/vue-element-admin/transaction/list',
34 type: 'get',
35 response: _ => {
36 return {
37 code: 20000,
38 data: {
39 total: 20,
40 'items|20': [{
41 order_no: '@guid()',
42 timestamp: +Mock.Random.date('T'),
43 username: '@name()',
44 price: '@float(1000, 15000, 0, 2)',
45 'status|1': ['success', 'pending']
46 }]
47 }
48 }
49 }
50 }
51 ]
52
mock/role/index.js
File was created 1 import Mock from 'mockjs'
2 import { deepClone } from '../../src/utils/index.js'
3 import { asyncRoutes, constantRoutes } from './routes.js'
4
5 const routes = deepClone([...constantRoutes, ...asyncRoutes])
6
7 const roles = [
8 {
9 key: 'admin',
10 name: 'admin',
11 description: 'Super Administrator. Have access to view all pages.',
12 routes: routes
13 },
14 {
15 key: 'editor',
16 name: 'editor',
17 description: 'Normal Editor. Can see all pages except permission page',
18 routes: routes.filter(i => i.path !== '/permission')// just a mock
19 },
20 {
21 key: 'visitor',
22 name: 'visitor',
23 description: 'Just a visitor. Can only see the home page and the document page',
24 routes: [{
25 path: '',
26 redirect: 'dashboard',
27 children: [
28 {
29 path: 'dashboard',
30 name: 'Dashboard',
31 meta: { title: 'dashboard', icon: 'dashboard' }
32 }
33 ]
34 }]
35 }
36 ]
37
38 export default [
39 // mock get all routes form server
40 {
41 url: '/vue-element-admin/routes',
42 type: 'get',
43 response: _ => {
44 return {
45 code: 20000,
46 data: routes
47 }
48 }
49 },
50
51 // mock get all roles form server
52 {
53 url: '/vue-element-admin/roles',
54 type: 'get',
55 response: _ => {
56 return {
57 code: 20000,
58 data: roles
59 }
60 }
61 },
62
63 // add role
64 {
65 url: '/vue-element-admin/role',
66 type: 'post',
67 response: {
68 code: 20000,
69 data: {
70 key: Mock.mock('@integer(300, 5000)')
71 }
72 }
73 },
74
75 // update role
76 {
77 url: '/vue-element-admin/role/[A-Za-z0-9]',
78 type: 'put',
79 response: {
80 code: 20000,
81 data: {
82 status: 'success'
83 }
84 }
85 },
86
87 // delete role
88 {
89 url: '/vue-element-admin/role/[A-Za-z0-9]',
90 type: 'delete',
91 response: {
92 code: 20000,
93 data: {
94 status: 'success'
95 }
96 }
97 }
98 ]
99
mock/role/routes.js
File was created 1 // Just a mock data
2
3 export const constantRoutes = [
4 {
5 path: '/redirect',
6 component: 'layout/Layout',
7 hidden: true,
8 children: [
9 {
10 path: '/redirect/:path*',
11 component: 'views/redirect/index'
12 }
13 ]
14 },
15 {
16 path: '/login',
17 component: 'views/login/index',
18 hidden: true
19 },
20 {
21 path: '/auth-redirect',
22 component: 'views/login/auth-redirect',
23 hidden: true
24 },
25 {
26 path: '/404',
27 component: 'views/error-page/404',
28 hidden: true
29 },
30 {
31 path: '/401',
32 component: 'views/error-page/401',
33 hidden: true
34 },
35 {
36 path: '',
37 component: 'layout/Layout',
38 redirect: 'dashboard',
39 children: [
40 {
41 path: 'dashboard',
42 component: 'views/dashboard/index',
43 name: 'Dashboard',
44 meta: { title: 'dashboard', icon: 'dashboard', affix: true }
45 }
46 ]
47 },
48 {
49 path: '/documentation',
50 component: 'layout/Layout',
51 children: [
52 {
53 path: 'index',
54 component: 'views/documentation/index',
55 name: 'Documentation',
56 meta: { title: 'documentation', icon: 'documentation', affix: true }
57 }
58 ]
59 },
60 {
61 path: '/guide',
62 component: 'layout/Layout',
63 redirect: '/guide/index',
64 children: [
65 {
66 path: 'index',
67 component: 'views/guide/index',
68 name: 'Guide',
69 meta: { title: 'guide', icon: 'guide', noCache: true }
70 }
71 ]
72 }
73 ]
74
75 export const asyncRoutes = [
76 {
77 path: '/permission',
78 component: 'layout/Layout',
79 redirect: '/permission/index',
80 alwaysShow: true,
81 meta: {
82 title: 'permission',
83 icon: 'lock',
84 roles: ['admin', 'editor']
85 },
86 children: [
87 {
88 path: 'page',
89 component: 'views/permission/page',
90 name: 'PagePermission',
91 meta: {
92 title: 'pagePermission',
93 roles: ['admin']
94 }
95 },
96 {
97 path: 'directive',
98 component: 'views/permission/directive',
99 name: 'DirectivePermission',
100 meta: {
101 title: 'directivePermission'
102 }
103 },
104 {
105 path: 'role',
106 component: 'views/permission/role',
107 name: 'RolePermission',
108 meta: {
109 title: 'rolePermission',
110 roles: ['admin']
111 }
112 }
113 ]
114 },
115
116 {
117 path: '/icon',
118 component: 'layout/Layout',
119 children: [
120 {
121 path: 'index',
122 component: 'views/icons/index',
123 name: 'Icons',
124 meta: { title: 'icons', icon: 'icon', noCache: true }
125 }
126 ]
127 },
128
129 {
130 path: '/components',
131 component: 'layout/Layout',
132 redirect: 'noRedirect',
133 name: 'ComponentDemo',
134 meta: {
135 title: 'components',
136 icon: 'component'
137 },
138 children: [
139 {
140 path: 'tinymce',
141 component: 'views/components-demo/tinymce',
142 name: 'TinymceDemo',
143 meta: { title: 'tinymce' }
144 },
145 {
146 path: 'markdown',
147 component: 'views/components-demo/markdown',
148 name: 'MarkdownDemo',
149 meta: { title: 'markdown' }
150 },
151 {
152 path: 'json-editor',
153 component: 'views/components-demo/json-editor',
154 name: 'JsonEditorDemo',
155 meta: { title: 'jsonEditor' }
156 },
157 {
158 path: 'split-pane',
159 component: 'views/components-demo/split-pane',
160 name: 'SplitpaneDemo',
161 meta: { title: 'splitPane' }
162 },
163 {
164 path: 'avatar-upload',
165 component: 'views/components-demo/avatar-upload',
166 name: 'AvatarUploadDemo',
167 meta: { title: 'avatarUpload' }
168 },
169 {
170 path: 'dropzone',
171 component: 'views/components-demo/dropzone',
172 name: 'DropzoneDemo',
173 meta: { title: 'dropzone' }
174 },
175 {
176 path: 'sticky',
177 component: 'views/components-demo/sticky',
178 name: 'StickyDemo',
179 meta: { title: 'sticky' }
180 },
181 {
182 path: 'count-to',
183 component: 'views/components-demo/count-to',
184 name: 'CountToDemo',
185 meta: { title: 'countTo' }
186 },
187 {
188 path: 'mixin',
189 component: 'views/components-demo/mixin',
190 name: 'ComponentMixinDemo',
191 meta: { title: 'componentMixin' }
192 },
193 {
194 path: 'back-to-top',
195 component: 'views/components-demo/back-to-top',
196 name: 'BackToTopDemo',
197 meta: { title: 'backToTop' }
198 },
199 {
200 path: 'drag-dialog',
201 component: 'views/components-demo/drag-dialog',
202 name: 'DragDialogDemo',
203 meta: { title: 'dragDialog' }
204 },
205 {
206 path: 'drag-select',
207 component: 'views/components-demo/drag-select',
208 name: 'DragSelectDemo',
209 meta: { title: 'dragSelect' }
210 },
211 {
212 path: 'dnd-list',
213 component: 'views/components-demo/dnd-list',
214 name: 'DndListDemo',
215 meta: { title: 'dndList' }
216 },
217 {
218 path: 'drag-kanban',
219 component: 'views/components-demo/drag-kanban',
220 name: 'DragKanbanDemo',
221 meta: { title: 'dragKanban' }
222 }
223 ]
224 },
225 {
226 path: '/charts',
227 component: 'layout/Layout',
228 redirect: 'noRedirect',
229 name: 'Charts',
230 meta: {
231 title: 'charts',
232 icon: 'chart'
233 },
234 children: [
235 {
236 path: 'keyboard',
237 component: 'views/charts/keyboard',
238 name: 'KeyboardChart',
239 meta: { title: 'keyboardChart', noCache: true }
240 },
241 {
242 path: 'line',
243 component: 'views/charts/line',
244 name: 'LineChart',
245 meta: { title: 'lineChart', noCache: true }
246 },
247 {
248 path: 'mixchart',
249 component: 'views/charts/mixChart',
250 name: 'MixChart',
251 meta: { title: 'mixChart', noCache: true }
252 }
253 ]
254 },
255 {
256 path: '/nested',
257 component: 'layout/Layout',
258 redirect: '/nested/menu1/menu1-1',
259 name: 'Nested',
260 meta: {
261 title: 'nested',
262 icon: 'nested'
263 },
264 children: [
265 {
266 path: 'menu1',
267 component: 'views/nested/menu1/index',
268 name: 'Menu1',
269 meta: { title: 'menu1' },
270 redirect: '/nested/menu1/menu1-1',
271 children: [
272 {
273 path: 'menu1-1',
274 component: 'views/nested/menu1/menu1-1',
275 name: 'Menu1-1',
276 meta: { title: 'menu1-1' }
277 },
278 {
279 path: 'menu1-2',
280 component: 'views/nested/menu1/menu1-2',
281 name: 'Menu1-2',
282 redirect: '/nested/menu1/menu1-2/menu1-2-1',
283 meta: { title: 'menu1-2' },
284 children: [
285 {
286 path: 'menu1-2-1',
287 component: 'views/nested/menu1/menu1-2/menu1-2-1',
288 name: 'Menu1-2-1',
289 meta: { title: 'menu1-2-1' }
290 },
291 {
292 path: 'menu1-2-2',
293 component: 'views/nested/menu1/menu1-2/menu1-2-2',
294 name: 'Menu1-2-2',
295 meta: { title: 'menu1-2-2' }
296 }
297 ]
298 },
299 {
300 path: 'menu1-3',
301 component: 'views/nested/menu1/menu1-3',
302 name: 'Menu1-3',
303 meta: { title: 'menu1-3' }
304 }
305 ]
306 },
307 {
308 path: 'menu2',
309 name: 'Menu2',
310 component: 'views/nested/menu2/index',
311 meta: { title: 'menu2' }
312 }
313 ]
314 },
315
316 {
317 path: '/example',
318 component: 'layout/Layout',
319 redirect: '/example/list',
320 name: 'Example',
321 meta: {
322 title: 'example',
323 icon: 'example'
324 },
325 children: [
326 {
327 path: 'create',
328 component: 'views/example/create',
329 name: 'CreateArticle',
330 meta: { title: 'createArticle', icon: 'edit' }
331 },
332 {
333 path: 'edit/:id(\\d+)',
334 component: 'views/example/edit',
335 name: 'EditArticle',
336 meta: { title: 'editArticle', noCache: true },
337 hidden: true
338 },
339 {
340 path: 'list',
341 component: 'views/example/list',
342 name: 'ArticleList',
343 meta: { title: 'articleList', icon: 'list' }
344 }
345 ]
346 },
347
348 {
349 path: '/tab',
350 component: 'layout/Layout',
351 children: [
352 {
353 path: 'index',
354 component: 'views/tab/index',
355 name: 'Tab',
356 meta: { title: 'tab', icon: 'tab' }
357 }
358 ]
359 },
360
361 {
362 path: '/error',
363 component: 'layout/Layout',
364 redirect: 'noRedirect',
365 name: 'ErrorPages',
366 meta: {
367 title: 'errorPages',
368 icon: '404'
369 },
370 children: [
371 {
372 path: '401',
373 component: 'views/error-page/401',
374 name: 'Page401',
375 meta: { title: 'page401', noCache: true }
376 },
377 {
378 path: '404',
379 component: 'views/error-page/404',
380 name: 'Page404',
381 meta: { title: 'page404', noCache: true }
382 }
383 ]
384 },
385
386 {
387 path: '/error-log',
388 component: 'layout/Layout',
389 redirect: 'noRedirect',
390 children: [
391 {
392 path: 'log',
393 component: 'views/error-log/index',
394 name: 'ErrorLog',
395 meta: { title: 'errorLog', icon: 'bug' }
396 }
397 ]
398 },
399
400 {
401 path: '/excel',
402 component: 'layout/Layout',
403 redirect: '/excel/export-excel',
404 name: 'Excel',
405 meta: {
406 title: 'excel',
407 icon: 'excel'
408 },
409 children: [
410 {
411 path: 'export-excel',
412 component: 'views/excel/export-excel',
413 name: 'ExportExcel',
414 meta: { title: 'exportExcel' }
415 },
416 {
417 path: 'export-selected-excel',
418 component: 'views/excel/select-excel',
419 name: 'SelectExcel',
420 meta: { title: 'selectExcel' }
421 },
422 {
423 path: 'export-merge-header',
424 component: 'views/excel/merge-header',
425 name: 'MergeHeader',
426 meta: { title: 'mergeHeader' }
427 },
428 {
429 path: 'upload-excel',
430 component: 'views/excel/upload-excel',
431 name: 'UploadExcel',
432 meta: { title: 'uploadExcel' }
433 }
434 ]
435 },
436
437 {
438 path: '/zip',
439 component: 'layout/Layout',
440 redirect: '/zip/download',
441 alwaysShow: true,
442 meta: { title: 'zip', icon: 'zip' },
443 children: [
444 {
445 path: 'download',
446 component: 'views/zip/index',
447 name: 'ExportZip',
448 meta: { title: 'exportZip' }
449 }
450 ]
451 },
452
453 {
454 path: '/pdf',
455 component: 'layout/Layout',
456 redirect: '/pdf/index',
457 children: [
458 {
459 path: 'index',
460 component: 'views/pdf/index',
461 name: 'PDF',
462 meta: { title: 'pdf', icon: 'pdf' }
463 }
464 ]
465 },
466 {
467 path: '/pdf/download',
468 component: 'views/pdf/download',
469 hidden: true
470 },
471
472 {
473 path: '/theme',
474 component: 'layout/Layout',
475 redirect: 'noRedirect',
476 children: [
477 {
478 path: 'index',
479 component: 'views/theme/index',
480 name: 'Theme',
481 meta: { title: 'theme', icon: 'theme' }
482 }
483 ]
484 },
485
486 {
487 path: '/clipboard',
488 component: 'layout/Layout',
489 redirect: 'noRedirect',
490 children: [
491 {
492 path: 'index',
493 component: 'views/clipboard/index',
494 name: 'ClipboardDemo',
495 meta: { title: 'clipboardDemo', icon: 'clipboard' }
496 }
497 ]
498 },
499
500 {
501 path: '/i18n',
502 component: 'layout/Layout',
503 children: [
504 {
505 path: 'index',
506 component: 'views/i18n-demo/index',
507 name: 'I18n',
508 meta: { title: 'i18n', icon: 'international' }
509 }
510 ]
511 },
512
513 {
514 path: 'external-link',
515 component: 'layout/Layout',
516 children: [
517 {
518 path: 'https://github.com/PanJiaChen/vue-element-admin',
519 meta: { title: 'externalLink', icon: 'link' }
520 }
521 ]
522 },
523
524 { path: '*', redirect: '/404', hidden: true }
525 ]
526
1
1 const tokens = { 2 const tokens = {
2 admin: { 3 admin: {
3 token: 'admin-token' 4 token: 'admin-token'
4 }, 5 },
5 assistant: { 6 editor: {
6 token: 'assistant-token' 7 token: 'editor-token'
7 },
8 runner: {
9 token: 'runner-token'
10 },
11 shoper: {
12 token: 'shoper-token'
13 } 8 }
14 } 9 }
15 10
16 const users = { 11 const users = {
17 'admin-token': { //管理员 12 'admin-token': {
18 roles: ['admin'], 13 roles: ['admin'],
19 introduction: 'I am a super administrator', 14 introduction: 'I am a super administrator',
20 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', 15 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
21 name: 'Super Admin' 16 name: 'Super Admin'
22 }, 17 },
23 'assistant-token': { //管理员助理 18 'editor-token': {
24 roles: ['assistant'], 19 roles: ['editor'],
25 introduction: 'I am a assistant of administrator', 20 introduction: 'I am an editor',
26 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
27 name: 'assistant Admin'
28 },
29 'runner-token': { //运营人员
30 roles: ['runner'],
31 introduction: 'I am an runner',
32 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
33 name: 'Normal runner'
34 },
35 'shoper-token': { //供应商
36 roles: ['shoper'],
37 introduction: 'I am an shoper',
38 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif', 21 avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
39 name: 'Normal shoper' 22 name: 'Normal Editor'
40 } 23 }
41 } 24 }
42 25
43 export default [{ // user login 26 export default [
44 url: '/yp/user/login', 27 // user login
28 {
29 url: '/vue-element-admin/user/login',
45 type: 'post', 30 type: 'post',
46 response: config => { 31 response: config => {
47 console.log('config-----111--->', config.body); 32 const { username } = config.body
48 const { 33 const token = tokens[username]
49 username, 34
50 password 35 // mock error
51 } = config.body; 36 if (!token) {
52 if (username == 'admin' && password == '111111') {
53 const token = tokens[username];
54 if (!token) {
55 return {
56 code: 60204,
57 message: 'Account and password are incorrect.'
58 }
59 } else {
60 return {
61 code: 20000,
62 data: token
63 }
64 }
65 } else {
66 console.log('passwordpasswordpassword', username, password);
67 return { 37 return {
68 code: 60204, 38 code: 60204,
69 message: 'Account and password are incorrect///.' 39 message: 'Account and password are incorrect.'
70 } 40 }
71 } 41 }
42
43 return {
44 code: 20000,
45 data: token
46 }
72 } 47 }
73 }, 48 },
74 49
75 // get user info 50 // get user info
76 { 51 {
77 url: '/yp/user/info\.*', 52 url: '/vue-element-admin/user/info\.*',
78 type: 'get', 53 type: 'get',
79 response: config => { 54 response: config => {
80 const { 55 const { token } = config.query
81 token
82 } = config.query
83 const info = users[token] 56 const info = users[token]
84 57
85 // mock error 58 // mock error
86 if (!info) { 59 if (!info) {
87 return { 60 return {
88 code: 50008, 61 code: 50008,
89 message: 'Login failed, unable to get user details.' 62 message: 'Login failed, unable to get user details.'
90 } 63 }
91 } 64 }
92 65
93 return { 66 return {
94 code: 20000, 67 code: 20000,
95 data: info 68 data: info
96 } 69 }
97 } 70 }
98 }, 71 },
99 72
100 // user logout 73 // user logout
101 { 74 {
102 url: '/yp/user/logout', 75 url: '/vue-element-admin/user/logout',
103 type: 'post', 76 type: 'post',
104 response: _ => { 77 response: _ => {
1 { 1 {
2 "name": "yp-plan", 2 "name": "vue-element-admin",
3 "version": "4.2.1", 3 "version": "4.2.1",
4 "description": "A vue admin template with Element UI & axios & iconfont & permission control & lint", 4 "description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features",
5 "author": "XYT==admin@xiuyetang.com", 5 "author": "Pan <panfree23@gmail.com>",
6 "license": "MIT", 6 "license": "MIT",
7 "scripts": { 7 "scripts": {
8 "dev": "vue-cli-service serve", 8 "dev": "vue-cli-service serve",
9 "build:prod": "vue-cli-service build", 9 "build:prod": "vue-cli-service build",
10 "build:stage": "vue-cli-service build --mode staging", 10 "build:stage": "vue-cli-service build --mode staging",
11 "preview": "node build/index.js --preview", 11 "preview": "node build/index.js --preview",
12 "lint": "eslint --ext .js,.vue src", 12 "lint": "eslint --ext .js,.vue src",
13 "test:unit": "jest --clearCache && vue-cli-service test:unit", 13 "test:unit": "jest --clearCache && vue-cli-service test:unit",
14 "test:ci": "npm run lint && npm run test:unit", 14 "test:ci": "npm run lint && npm run test:unit",
15 "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml" 15 "svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
16 "new": "plop"
17 },
18 "husky": {
19 "hooks": {
20 "pre-commit": "lint-staged"
21 }
22 },
23 "lint-staged": {
24 "src/**/*.{js,vue}": [
25 "eslint --fix",
26 "git add"
27 ]
28 },
29 "keywords": [
30 "vue",
31 "admin",
32 "dashboard",
33 "element-ui",
34 "boilerplate",
35 "admin-template",
36 "management-system"
37 ],
38 "repository": {
39 "type": "git",
40 "url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
41 },
42 "bugs": {
43 "url": "https://github.com/PanJiaChen/vue-element-admin/issues"
16 }, 44 },
17 "dependencies": { 45 "dependencies": {
18 "axios": "0.18.1", 46 "axios": "0.18.1",
19 "babel-polyfill": "^6.26.0", 47 "clipboard": "2.0.4",
20 "echarts": "^4.7.0", 48 "codemirror": "5.45.0",
49 "driver.js": "0.9.5",
50 "dropzone": "5.5.1",
51 "echarts": "4.2.1",
21 "element-ui": "2.13.0", 52 "element-ui": "2.13.0",
53 "file-saver": "2.0.1",
54 "fuse.js": "3.4.4",
22 "js-cookie": "2.2.0", 55 "js-cookie": "2.2.0",
56 "jsonlint": "1.6.3",
57 "jszip": "3.2.1",
23 "normalize.css": "7.0.0", 58 "normalize.css": "7.0.0",
24 "nprogress": "0.2.0", 59 "nprogress": "0.2.0",
25 "path-to-regexp": "2.4.0", 60 "path-to-regexp": "2.4.0",
26 "plop": "^2.6.0", 61 "pinyin": "2.9.0",
62 "screenfull": "4.2.0",
63 "showdown": "1.9.0",
64 "sortablejs": "1.8.4",
65 "tui-editor": "1.3.3",
27 "vue": "2.6.10", 66 "vue": "2.6.10",
28 "vue-router": "3.0.6", 67 "vue-count-to": "1.0.13",
29 "vuex": "3.1.0" 68 "vue-i18n": "7.3.2",
69 "vue-router": "3.0.2",
70 "vue-splitpane": "1.0.4",
71 "vuedraggable": "2.20.0",
72 "vuex": "3.1.0",
73 "xlsx": "0.14.1"
30 }, 74 },
31 "devDependencies": { 75 "devDependencies": {
32 "@babel/core": "7.0.0", 76 "@babel/core": "7.0.0",
33 "@babel/preset-env": "^7.9.6",
34 "@babel/register": "7.0.0", 77 "@babel/register": "7.0.0",
35 "@vue/cli-plugin-babel": "3.6.0", 78 "@vue/cli-plugin-babel": "3.5.3",
36 "@vue/cli-plugin-eslint": "^3.9.1", 79 "@vue/cli-plugin-eslint": "^3.9.1",
37 "@vue/cli-plugin-unit-jest": "3.6.3", 80 "@vue/cli-plugin-unit-jest": "3.5.3",
38 "@vue/cli-service": "3.6.0", 81 "@vue/cli-service": "3.5.3",
39 "@vue/test-utils": "1.0.0-beta.29", 82 "@vue/test-utils": "1.0.0-beta.29",
40 "autoprefixer": "^9.5.1", 83 "autoprefixer": "^9.5.1",
41 "babel-cli": "^6.26.0",
42 "babel-core": "7.0.0-bridge.0", 84 "babel-core": "7.0.0-bridge.0",
43 "babel-eslint": "10.0.1", 85 "babel-eslint": "10.0.1",
44 "babel-jest": "23.6.0", 86 "babel-jest": "23.6.0",
45 "babel-plugin-component": "^1.1.1",
46 "babel-preset-env": "^1.7.0",
47 "chalk": "2.4.2", 87 "chalk": "2.4.2",
88 "chokidar": "2.1.5",
48 "connect": "3.6.6", 89 "connect": "3.6.6",
49 "eslint": "5.15.3", 90 "eslint": "5.15.3",
50 "eslint-plugin-vue": "5.2.2", 91 "eslint-plugin-vue": "5.2.2",
51 "html-webpack-plugin": "3.2.0", 92 "html-webpack-plugin": "3.2.0",
93 "husky": "1.3.1",
94 "lint-staged": "8.1.5",
52 "mockjs": "1.0.1-beta3", 95 "mockjs": "1.0.1-beta3",
53 "node-sass": "^4.9.0", 96 "node-sass": "^4.9.0",
97 "plop": "2.3.0",
54 "runjs": "^4.3.2", 98 "runjs": "^4.3.2",
55 "sass-loader": "^7.1.0", 99 "sass-loader": "^7.1.0",
56 "script-ext-html-webpack-plugin": "2.1.3", 100 "script-ext-html-webpack-plugin": "2.1.3",
57 "script-loader": "0.7.2", 101 "script-loader": "0.7.2",
58 "serve-static": "^1.13.2", 102 "serve-static": "^1.13.2",
59 "svg-sprite-loader": "4.1.3", 103 "svg-sprite-loader": "4.1.3",
60 "svgo": "1.2.2", 104 "svgo": "1.2.0",
61 "vue-schart": "^2.0.0",
62 "vue-template-compiler": "2.6.10" 105 "vue-template-compiler": "2.6.10"
63 }, 106 },
64 "engines": { 107 "engines": {
65 "node": ">=8.9", 108 "node": ">=8.9",
66 "npm": ">= 3.0.0" 109 "npm": ">= 3.0.0"
67 }, 110 },
68 "browserslist": [ 111 "browserslist": [
plop-templates/component/index.hbs
File was created 1 {{#if template}}
2 <template>
3 <div />
4 </template>
5 {{/if}}
6
7 {{#if script}}
8 <script>
9 export default {
10 name: '{{ properCase name }}',
11 props: {},
12 data() {
13 return {}
14 },
15 created() {},
16 mounted() {},
17 methods: {}
18 }
19 </script>
20 {{/if}}
21
22 {{#if style}}
23 <style lang="scss" scoped>
24
25 </style>
26 {{/if}}
27
plop-templates/component/prompt.js
File was created 1 const { notEmpty } = require('../utils.js')
2
3 module.exports = {
4 description: 'generate vue component',
5 prompts: [{
6 type: 'input',
7 name: 'name',
8 message: 'component name please',
9 validate: notEmpty('name')
10 },
11 {
12 type: 'checkbox',
13 name: 'blocks',
14 message: 'Blocks:',
15 choices: [{
16 name: '<template>',
17 value: 'template',
18 checked: true
19 },
20 {
21 name: '<script>',
22 value: 'script',
23 checked: true
24 },
25 {
26 name: 'style',
27 value: 'style',
28 checked: true
29 }
30 ],
31 validate(value) {
32 if (value.indexOf('script') === -1 && value.indexOf('template') === -1) {
33 return 'Components require at least a <script> or <template> tag.'
34 }
35 return true
36 }
37 }
38 ],
39 actions: data => {
40 const name = '{{properCase name}}'
41 const actions = [{
42 type: 'add',
43 path: `src/components/${name}/index.vue`,
44 templateFile: 'plop-templates/component/index.hbs',
45 data: {
46 name: name,
47 template: data.blocks.includes('template'),
48 script: data.blocks.includes('script'),
49 style: data.blocks.includes('style')
50 }
51 }]
52
53 return actions
54 }
55 }
56
plop-templates/store/index.hbs
File was created 1 {{#if state}}
2 const state = {}
3 {{/if}}
4
5 {{#if mutations}}
6 const mutations = {}
7 {{/if}}
8
9 {{#if actions}}
10 const actions = {}
11 {{/if}}
12
13 export default {
14 namespaced: true,
15 {{options}}
16 }
17
plop-templates/store/prompt.js
File was created 1 const { notEmpty } = require('../utils.js')
2
3 module.exports = {
4 description: 'generate store',
5 prompts: [{
6 type: 'input',
7 name: 'name',
8 message: 'store name please',
9 validate: notEmpty('name')
10 },
11 {
12 type: 'checkbox',
13 name: 'blocks',
14 message: 'Blocks:',
15 choices: [{
16 name: 'state',
17 value: 'state',
18 checked: true
19 },
20 {
21 name: 'mutations',
22 value: 'mutations',
23 checked: true
24 },
25 {
26 name: 'actions',
27 value: 'actions',
28 checked: true
29 }
30 ],
31 validate(value) {
32 if (!value.includes('state') || !value.includes('mutations')) {
33 return 'store require at least state and mutations'
34 }
35 return true
36 }
37 }
38 ],
39 actions(data) {
40 const name = '{{name}}'
41 const { blocks } = data
42 const options = ['state', 'mutations']
43 const joinFlag = `,
44 `
45 if (blocks.length === 3) {
46 options.push('actions')
47 }
48
49 const actions = [{
50 type: 'add',
51 path: `src/store/modules/${name}.js`,
52 templateFile: 'plop-templates/store/index.hbs',
53 data: {
54 options: options.join(joinFlag),
55 state: blocks.includes('state'),
56 mutations: blocks.includes('mutations'),
57 actions: blocks.includes('actions')
58 }
59 }]
60 return actions
61 }
62 }
63
plop-templates/utils.js
File was created 1 exports.notEmpty = name => {
2 return v => {
3 if (!v || v.trim === '') {
4 return `${name} is required`
5 } else {
6 return true
7 }
8 }
9 }
10
plop-templates/view/index.hbs
File was created 1 {{#if template}}
2 <template>
3 <div />
4 </template>
5 {{/if}}
6
7 {{#if script}}
8 <script>
9 export default {
10 name: '{{ properCase name }}',
11 props: {},
12 data() {
13 return {}
14 },
15 created() {},
16 mounted() {},
17 methods: {}
18 }
19 </script>
20 {{/if}}
21
22 {{#if style}}
23 <style lang="scss" scoped>
24
25 </style>
26 {{/if}}
27
plop-templates/view/prompt.js
File was created 1 const { notEmpty } = require('../utils.js')
2
3 module.exports = {
4 description: 'generate a view',
5 prompts: [{
6 type: 'input',
7 name: 'name',
8 message: 'view name please',
9 validate: notEmpty('name')
10 },
11 {
12 type: 'checkbox',
13 name: 'blocks',
14 message: 'Blocks:',
15 choices: [{
16 name: '<template>',
17 value: 'template',
18 checked: true
19 },
20 {
21 name: '<script>',
22 value: 'script',
23 checked: true
24 },
25 {
26 name: 'style',
27 value: 'style',
28 checked: true
29 }
30 ],
31 validate(value) {
32 if (value.indexOf('script') === -1 && value.indexOf('template') === -1) {
33 return 'View require at least a <script> or <template> tag.'
34 }
35 return true
36 }
37 }
38 ],
39 actions: data => {
40 const name = '{{name}}'
41 const actions = [{
42 type: 'add',
43 path: `src/views/${name}/index.vue`,
44 templateFile: 'plop-templates/view/index.hbs',
45 data: {
46 name: name,
47 template: data.blocks.includes('template'),
48 script: data.blocks.includes('script'),
49 style: data.blocks.includes('style')
50 }
51 }]
52
53 return actions
54 }
55 }
56
File was created 1 const viewGenerator = require('./plop-templates/view/prompt')
2 const componentGenerator = require('./plop-templates/component/prompt')
3 const storeGenerator = require('./plop-templates/store/prompt.js')
4
5 module.exports = function(plop) {
6 plop.setGenerator('view', viewGenerator)
7 plop.setGenerator('component', componentGenerator)
8 plop.setGenerator('store', storeGenerator)
9 }
10
postcss.config.js
1 // https://github.com/michael-ciniawsky/postcss-load-config
2
3 module.exports = { 1 module.exports = {
4 'plugins': { 2 plugins: {
5 // to edit target browsers: use "browserslist" field in package.json 3 autoprefixer: {}
6 'autoprefixer': {}
7 } 4 }
8 } 5 }
9 6
public/favicon.ico 100644 → 100755
No preview for this file type
public/index.html
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 <html> 2 <html>
3 <head> 3 <head>
4 <meta charset="utf-8"> 4 <meta charset="utf-8">
5 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
6 <meta name="renderer" content="webkit">
6 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> 7 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
7 <link rel="icon" href="<%= BASE_URL %>favicon.ico"> 8 <link rel="icon" href="<%= BASE_URL %>favicon.ico">
8 <title><%= webpackConfig.name %></title> 9 <title><%= webpackConfig.name %></title>
9 </head> 10 </head>
10 <body> 11 <body>
11 <noscript>
12 <strong>We're sorry but <%= webpackConfig.name %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
13 </noscript>
14 <div id="app"></div> 12 <div id="app"></div>
15 <!-- built files will be auto injected --> 13 <!-- built files will be auto injected -->
16 </body> 14 </body>
17 </html> 15 </html>
1 <template> 1 <template>
2 <div id="app"> 2 <div id="app">
3 <router-view /> 3 <router-view />
4 </div> 4 </div>
5 </template> 5 </template>
6 6
7
8 <script> 7 <script>
9 export default { 8 export default {
10 name: "App" 9 name: 'App'
11 };
12 </script>
13
14
15 <style>
16 @import "//at.alicdn.com/t/font_1075796_5kpx2vwkmq3.css";
17
18 [class^="el-icon-mo"],
19 [class^=" el-icon-mo"] {
20 font-family: "iconfont", serif !important;
21 font-size: 16px;
22 font-style: normal;
23 -webkit-font-smoothing: antialiased;
24 -moz-osx-font-smoothing: grayscale;
25 } 10 }
26 </style>
src/api/article.js
File was created 1 import request from '@/utils/request'
2
3 export function fetchList(query) {
4 return request({
5 url: '/vue-element-admin/article/list',
6 method: 'get',
7 params: query
8 })
9 }
10
11 export function fetchArticle(id) {
12 return request({
13 url: '/vue-element-admin/article/detail',
14 method: 'get',
15 params: { id }
16 })
17 }
18
19 export function fetchPv(pv) {
20 return request({
21 url: '/vue-element-admin/article/pv',
22 method: 'get',
23 params: { pv }
24 })
25 }
26
27 export function createArticle(data) {
28 return request({
29 url: '/vue-element-admin/article/create',
30 method: 'post',
31 data
32 })
33 }
34
35 export function updateArticle(data) {
36 return request({
37 url: '/vue-element-admin/article/update',
38 method: 'post',
39 data
40 })
41 }
42
File was created 1 import request from '@/utils/request'
2
3 export function getToken() {
4 return request({
5 url: '/qiniu/upload/token', // 假地址 自行替换
6 method: 'get'
7 })
8 }
9
src/api/remote-search.js
File was created 1 import request from '@/utils/request'
2
3 export function searchUser(name) {
4 return request({
5 url: '/vue-element-admin/search/user',
6 method: 'get',
7 params: { name }
8 })
9 }
10
11 export function transactionList(query) {
12 return request({
13 url: '/vue-element-admin/transaction/list',
14 method: 'get',
15 params: query
16 })
17 }
18
File was created 1 import request from '@/utils/request'
2
3 export function getRoutes() {
4 return request({
5 url: '/vue-element-admin/routes',
6 method: 'get'
7 })
8 }
9
10 export function getRoles() {
11 return request({
12 url: '/vue-element-admin/roles',
13 method: 'get'
14 })
15 }
16
17 export function addRole(data) {
18 return request({
19 url: '/vue-element-admin/role',
20 method: 'post',
21 data
22 })
23 }
24
25 export function updateRole(id, data) {
26 return request({
27 url: `/vue-element-admin/role/${id}`,
28 method: 'put',
29 data
30 })
31 }
32
33 export function deleteRole(id) {
34 return request({
35 url: `/vue-element-admin/role/${id}`,
36 method: 'delete'
37 })
38 }
39
1 import request from '@/utils/request' 1 import request from '@/utils/request'
2 // var qs = require('Qs');
3 2
4 export function login(data) { 3 export function login(data) {
5 console.log('login.1111...', data)
6 return request({ 4 return request({
7 url: '/yp/user/login', 5 url: '/vue-element-admin/user/login',
8 // url: '/yp.user.login.php',
9 method: 'post', 6 method: 'post',
10 // headers: { 7 data
11 // 'Content-type': 'application/x-www-form-urlencoded'
12 // },
13 data,
14 // responseType: 'text/plain',
15 // onDownloadProgress: false,
16 // onUploadProgress: true,
17 // proxy: {}
18 });
19 }
20
21 export function getInfo(token) {
22 console.log('getInfo....', token)
23 return request({
24 url: '/yp/user/info',
25 // url: '/yp.user.info.php',
26 method: 'get',
27 params: {
28 token
29 }
30 // ,
31 // headers: {
32 // 'Content-type': 'application/x-www-form-urlencoded'
33 // },
34 }) 8 })
35 } 9 }
36 10
37 export function list(token) { 11 export function getInfo(token) {
38 console.log('listUser....', token)
39 return request({ 12 return request({
40 url: '/yp/user/list', 13 url: '/vue-element-admin/user/info',
41 method: 'get', 14 method: 'get',
42 params: { 15 params: { token }
43 token
44 }
45 }) 16 })
46 } 17 }
47 18
48 export function add(token) { 19 export function logout() {
49 console.log('addUser....', token)
50 return request({ 20 return request({
51 url: '/yp/user/add', 21 url: '/vue-element-admin/user/logout',
52 method: 'post', 22 method: 'post'
53 params: {
54 token
55 }
56 })
57 }
58
59 export function modi(token) {
60 console.log('modiUser....', token)
61 return request({
62 url: '/yp/user/modi',
63 method: 'post',
64 params: {
65 token
66 }
67 })
68 }
69
70 export function logout(token) {
71 console.log('logout....', token)
72 return request({
73 url: '/yp/user/logout',
74 // url: '/yp.user.logout.php',
75 method: 'post',
76 }) 23 })
77 } 24 }
78 25
src/assets/401_images/401.gif

160 KB

src/assets/404_images/404.png 100644 → 100755

95.8 KB | W: | H:

95.8 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/404_images/404_cloud.png 100644 → 100755

4.65 KB | W: | H:

4.65 KB | W: | H:

  • 2-up
  • Swipe
  • Onion skin
src/assets/custom-theme/fonts/element-icons.ttf
No preview for this file type
src/assets/custom-theme/fonts/element-icons.woff
No preview for this file type
src/assets/custom-theme/index.css
File was created 1 @charset "UTF-8";.custom-theme .fade-in-linear-enter-active,.custom-theme .fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.custom-theme .fade-in-linear-enter,.custom-theme .fade-in-linear-leave,.custom-theme .fade-in-linear-leave-active{opacity:0}.custom-theme .el-fade-in-linear-enter-active,.custom-theme .el-fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.custom-theme .el-fade-in-linear-enter,.custom-theme .el-fade-in-linear-leave,.custom-theme .el-fade-in-linear-leave-active{opacity:0}.custom-theme .el-fade-in-enter-active,.custom-theme .el-fade-in-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.custom-theme .el-fade-in-enter,.custom-theme .el-fade-in-leave-active{opacity:0}.custom-theme .el-zoom-in-center-enter-active,.custom-theme .el-zoom-in-center-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.custom-theme .el-zoom-in-center-enter,.custom-theme .el-zoom-in-center-leave-active{opacity:0;-webkit-transform:scaleX(0);transform:scaleX(0)}.custom-theme .el-zoom-in-top-enter-active,.custom-theme .el-zoom-in-top-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;-webkit-transform-origin:center top;transform-origin:center top}.custom-theme .el-zoom-in-top-enter,.custom-theme .el-zoom-in-top-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.custom-theme .el-zoom-in-bottom-enter-active,.custom-theme .el-zoom-in-bottom-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;-webkit-transform-origin:center bottom;transform-origin:center bottom}.custom-theme .el-zoom-in-bottom-enter,.custom-theme .el-zoom-in-bottom-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.custom-theme .el-zoom-in-left-enter-active,.custom-theme .el-zoom-in-left-leave-active{opacity:1;-webkit-transform:scale(1,1);transform:scale(1,1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;-webkit-transform-origin:top left;transform-origin:top left}.custom-theme .el-zoom-in-left-enter,.custom-theme .el-zoom-in-left-leave-active{opacity:0;-webkit-transform:scale(.45,.45);transform:scale(.45,.45)}.custom-theme .collapse-transition{-webkit-transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out;transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out}.custom-theme .horizontal-collapse-transition{-webkit-transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out;transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out}.custom-theme .el-list-enter-active,.custom-theme .el-list-leave-active{-webkit-transition:all 1s;transition:all 1s}.custom-theme .el-list-enter,.custom-theme .el-list-leave-active{opacity:0;-webkit-transform:translateY(-30px);transform:translateY(-30px)}.custom-theme .el-opacity-transition{-webkit-transition:opacity .3s cubic-bezier(.55,0,.1,1);transition:opacity .3s cubic-bezier(.55,0,.1,1)}@font-face{font-family:element-icons;src:url(fonts/element-icons.woff?t=1508751886602) format("woff"),url(fonts/element-icons.ttf?t=1508751886602) format("truetype");font-weight:400;font-style:normal}.custom-theme [class*=" el-icon-"],.custom-theme [class^=el-icon-]{font-family:element-icons!important;speak:none;font-style:normal;font-weight:400;font-variant:normal;text-transform:none;line-height:1;vertical-align:baseline;display:inline-block;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.custom-theme .el-icon-upload:before{content:"\e60d"}.custom-theme .el-icon-error:before{content:"\e62c"}.custom-theme .el-icon-success:before{content:"\e62d"}.custom-theme .el-icon-warning:before{content:"\e62e"}.custom-theme .el-icon-sort-down:before{content:"\e630"}.custom-theme .el-icon-sort-up:before{content:"\e631"}.custom-theme .el-icon-arrow-left:before{content:"\e600"}.custom-theme .el-icon-circle-plus:before{content:"\e601"}.custom-theme .el-icon-circle-plus-outline:before{content:"\e602"}.custom-theme .el-icon-arrow-down:before{content:"\e603"}.custom-theme .el-icon-arrow-right:before{content:"\e604"}.custom-theme .el-icon-arrow-up:before{content:"\e605"}.custom-theme .el-icon-back:before{content:"\e606"}.custom-theme .el-icon-circle-close:before{content:"\e607"}.custom-theme .el-icon-date:before{content:"\e608"}.custom-theme .el-icon-circle-close-outline:before{content:"\e609"}.custom-theme .el-icon-caret-left:before{content:"\e60a"}.custom-theme .el-icon-caret-bottom:before{content:"\e60b"}.custom-theme .el-icon-caret-top:before{content:"\e60c"}.custom-theme .el-icon-caret-right:before{content:"\e60e"}.custom-theme .el-icon-close:before{content:"\e60f"}.custom-theme .el-icon-d-arrow-left:before{content:"\e610"}.custom-theme .el-icon-check:before{content:"\e611"}.custom-theme .el-icon-delete:before{content:"\e612"}.custom-theme .el-icon-d-arrow-right:before{content:"\e613"}.custom-theme .el-icon-document:before{content:"\e614"}.custom-theme .el-icon-d-caret:before{content:"\e615"}.custom-theme .el-icon-edit-outline:before{content:"\e616"}.custom-theme .el-icon-download:before{content:"\e617"}.custom-theme .el-icon-goods:before{content:"\e618"}.custom-theme .el-icon-search:before{content:"\e619"}.custom-theme .el-icon-info:before{content:"\e61a"}.custom-theme .el-icon-message:before{content:"\e61b"}.custom-theme .el-icon-edit:before{content:"\e61c"}.custom-theme .el-icon-location:before{content:"\e61d"}.custom-theme .el-icon-loading:before{content:"\e61e"}.custom-theme .el-icon-location-outline:before{content:"\e61f"}.custom-theme .el-icon-menu:before{content:"\e620"}.custom-theme .el-icon-minus:before{content:"\e621"}.custom-theme .el-icon-bell:before{content:"\e622"}.custom-theme .el-icon-mobile-phone:before{content:"\e624"}.custom-theme .el-icon-news:before{content:"\e625"}.custom-theme .el-icon-more:before{content:"\e646"}.custom-theme .el-icon-more-outline:before{content:"\e626"}.custom-theme .el-icon-phone:before{content:"\e627"}.custom-theme .el-icon-phone-outline:before{content:"\e628"}.custom-theme .el-icon-picture:before{content:"\e629"}.custom-theme .el-icon-picture-outline:before{content:"\e62a"}.custom-theme .el-icon-plus:before{content:"\e62b"}.custom-theme .el-icon-printer:before{content:"\e62f"}.custom-theme .el-icon-rank:before{content:"\e632"}.custom-theme .el-icon-refresh:before{content:"\e633"}.custom-theme .el-icon-question:before{content:"\e634"}.custom-theme .el-icon-remove:before{content:"\e635"}.custom-theme .el-icon-share:before{content:"\e636"}.custom-theme .el-icon-star-on:before{content:"\e637"}.custom-theme .el-icon-setting:before{content:"\e638"}.custom-theme .el-icon-circle-check:before{content:"\e639"}.custom-theme .el-icon-service:before{content:"\e63a"}.custom-theme .el-icon-sold-out:before{content:"\e63b"}.custom-theme .el-icon-remove-outline:before{content:"\e63c"}.custom-theme .el-icon-star-off:before{content:"\e63d"}.custom-theme .el-icon-circle-check-outline:before{content:"\e63e"}.custom-theme .el-icon-tickets:before{content:"\e63f"}.custom-theme .el-icon-sort:before{content:"\e640"}.custom-theme .el-icon-zoom-in:before{content:"\e641"}.custom-theme .el-icon-time:before{content:"\e642"}.custom-theme .el-icon-view:before{content:"\e643"}.custom-theme .el-icon-upload2:before{content:"\e644"}.custom-theme .el-icon-zoom-out:before{content:"\e645"}.custom-theme .el-icon-loading{-webkit-animation:rotating 2s linear infinite;animation:rotating 2s linear infinite}.custom-theme .el-icon--right{margin-left:5px}.custom-theme .el-icon--left{margin-right:5px}@-webkit-keyframes rotating{0%{-webkit-transform:rotateZ(0);transform:rotateZ(0)}100%{-webkit-transform:rotateZ(360deg);transform:rotateZ(360deg)}}@keyframes rotating{0%{-webkit-transform:rotateZ(0);transform:rotateZ(0)}100%{-webkit-transform:rotateZ(360deg);transform:rotateZ(360deg)}}.custom-theme .el-popper .popper__arrow,.custom-theme .el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.custom-theme .el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.custom-theme .el-popper .popper__arrow::after{content:" ";border-width:6px}.custom-theme .el-popper[x-placement^=top]{margin-bottom:12px}.custom-theme .el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#e6ebf5;border-bottom-width:0}.custom-theme .el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.custom-theme .el-popper[x-placement^=bottom]{margin-top:12px}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#e6ebf5}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.custom-theme .el-popper[x-placement^=right]{margin-left:12px}.custom-theme .el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#e6ebf5;border-left-width:0}.custom-theme .el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.custom-theme .el-popper[x-placement^=left]{margin-right:12px}.custom-theme .el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#e6ebf5}.custom-theme .el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.custom-theme .el-select-dropdown{position:absolute;z-index:1001;border:solid 1px #dfe4ed;border-radius:4px;background-color:#fff;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-box-sizing:border-box;box-sizing:border-box;margin:5px 0}.custom-theme .el-select-dropdown.is-multiple .el-select-dropdown__item.selected{color:#262729;background-color:#fff}.custom-theme .el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover{background-color:#f5f7fa}.custom-theme .el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after{position:absolute;right:20px;font-family:element-icons;content:"\E611";font-size:12px;font-weight:700;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.custom-theme .el-select-dropdown .el-scrollbar.is-empty .el-select-dropdown__list{padding:0}.custom-theme .el-select-dropdown .popper__arrow{-webkit-transform:translateX(-400%);transform:translateX(-400%)}.custom-theme .el-select-dropdown.is-arrow-fixed .popper__arrow{-webkit-transform:translateX(-200%);transform:translateX(-200%)}.custom-theme .el-select-dropdown__empty{padding:10px 0;margin:0;text-align:center;color:#999;font-size:14px}.custom-theme .el-select-dropdown__wrap{max-height:274px}.custom-theme .el-select-dropdown__list{list-style:none;padding:6px 0;margin:0;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-input{position:relative;font-size:14px;display:inline-block;width:100%}.custom-theme .el-input::-webkit-scrollbar{z-index:11;width:6px}.custom-theme .el-input::-webkit-scrollbar:horizontal{height:6px}.custom-theme .el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.custom-theme .el-input::-webkit-scrollbar-corner{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.custom-theme .el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #d8dce5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#5a5e66;display:inline-block;font-size:inherit;height:40px;line-height:1;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.custom-theme .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input__inner:hover{border-color:#b4bccc}.custom-theme .el-input__inner:focus{outline:0;border-color:#262729}.custom-theme .el-input__suffix{position:absolute;height:100%;right:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s;pointer-events:none}.custom-theme .el-input__suffix-inner{pointer-events:all}.custom-theme .el-input__prefix{position:absolute;height:100%;left:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s}.custom-theme .el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.custom-theme .el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.custom-theme .el-input__validateIcon{pointer-events:none}.custom-theme .el-input.is-active .el-input__inner{outline:0;border-color:#262729}.custom-theme .el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__icon{cursor:not-allowed}.custom-theme .el-input--suffix .el-input__inner{padding-right:30px}.custom-theme .el-input--prefix .el-input__inner{padding-left:30px}.custom-theme .el-input--medium{font-size:14px}.custom-theme .el-input--medium .el-input__inner{height:36px}.custom-theme .el-input--medium .el-input__icon{line-height:36px}.custom-theme .el-input--small{font-size:13px}.custom-theme .el-input--small .el-input__inner{height:32px}.custom-theme .el-input--small .el-input__icon{line-height:32px}.custom-theme .el-input--mini{font-size:12px}.custom-theme .el-input--mini .el-input__inner{height:28px}.custom-theme .el-input--mini .el-input__icon{line-height:28px}.custom-theme .el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.custom-theme .el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.custom-theme .el-input-group__append,.custom-theme .el-input-group__prepend{background-color:#f5f7fa;color:#0a76a4;vertical-align:middle;display:table-cell;position:relative;border:1px solid #d8dce5;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.custom-theme .el-input-group__append:focus,.custom-theme .el-input-group__prepend:focus{outline:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-select,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-select{display:inline-block;margin:-20px}.custom-theme .el-input-group__append button.el-button,.custom-theme .el-input-group__append div.el-select .el-input__inner,.custom-theme .el-input-group__append div.el-select:hover .el-input__inner,.custom-theme .el-input-group__prepend button.el-button,.custom-theme .el-input-group__prepend div.el-select .el-input__inner,.custom-theme .el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-input,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-input{font-size:inherit}.custom-theme .el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-input-group__append{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--prepend .el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--append .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-textarea{display:inline-block;width:100%;vertical-align:bottom}.custom-theme .el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:14px;color:#5a5e66;background-color:#fff;background-image:none;border:1px solid #d8dce5;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:hover{border-color:#b4bccc}.custom-theme .el-textarea__inner:focus{outline:0;border-color:#262729}.custom-theme .el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-tag{background-color:rgba(38,39,41,.1);display:inline-block;padding:0 10px;height:32px;line-height:30px;font-size:12px;color:#262729;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid rgba(38,39,41,.2);white-space:nowrap}.custom-theme .el-tag .el-icon-close{border-radius:50%;text-align:center;position:relative;cursor:pointer;font-size:12px;height:18px;width:18px;line-height:18px;vertical-align:middle;top:-1px;right:-5px;color:#262729}.custom-theme .el-tag .el-icon-close::before{display:block}.custom-theme .el-tag .el-icon-close:hover{background-color:#262729;color:#fff}.custom-theme .el-tag--info{background-color:rgba(10,118,164,.1);border-color:rgba(10,118,164,.2);color:#0a76a4}.custom-theme .el-tag--info.is-hit{border-color:#0a76a4}.custom-theme .el-tag--info .el-tag__close{color:#0a76a4}.custom-theme .el-tag--info .el-tag__close:hover{background-color:#0a76a4;color:#fff}.custom-theme .el-tag--success{background-color:rgba(64,145,103,.1);border-color:rgba(64,145,103,.2);color:#409167}.custom-theme .el-tag--success.is-hit{border-color:#409167}.custom-theme .el-tag--success .el-tag__close{color:#409167}.custom-theme .el-tag--success .el-tag__close:hover{background-color:#409167;color:#fff}.custom-theme .el-tag--warning{background-color:rgba(157,164,8,.1);border-color:rgba(157,164,8,.2);color:#9da408}.custom-theme .el-tag--warning.is-hit{border-color:#9da408}.custom-theme .el-tag--warning .el-tag__close{color:#9da408}.custom-theme .el-tag--warning .el-tag__close:hover{background-color:#9da408;color:#fff}.custom-theme .el-tag--danger{background-color:rgba(179,69,14,.1);border-color:rgba(179,69,14,.2);color:#b3450e}.custom-theme .el-tag--danger.is-hit{border-color:#b3450e}.custom-theme .el-tag--danger .el-tag__close{color:#b3450e}.custom-theme .el-tag--danger .el-tag__close:hover{background-color:#b3450e;color:#fff}.custom-theme .el-tag--medium{height:28px;line-height:26px}.custom-theme .el-tag--medium .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-tag--small{height:24px;padding:0 8px;line-height:22px}.custom-theme .el-tag--small .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-tag--mini{height:20px;padding:0 5px;line-height:19px}.custom-theme .el-tag--mini .el-icon-close{margin-left:-3px;-webkit-transform:scale(.7);transform:scale(.7)}.custom-theme .el-select-dropdown__item{font-size:14px;padding:0 20px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#5a5e66;height:34px;line-height:34px;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:pointer}.custom-theme .el-select-dropdown__item.is-disabled{color:#b4bccc;cursor:not-allowed}.custom-theme .el-select-dropdown__item.is-disabled:hover{background-color:#fff}.custom-theme .el-select-dropdown__item.hover,.custom-theme .el-select-dropdown__item:hover{background-color:#f5f7fa}.custom-theme .el-select-dropdown__item.selected{color:#262729;font-weight:700}.custom-theme .el-select-dropdown__item span{line-height:34px!important}.custom-theme .el-select-group{margin:0;padding:0}.custom-theme .el-select-group__wrap{position:relative;list-style:none;margin:0;padding:0}.custom-theme .el-select-group__wrap:not(:last-of-type){padding-bottom:24px}.custom-theme .el-select-group__wrap:not(:last-of-type)::after{content:'';position:absolute;display:block;left:20px;right:20px;bottom:12px;height:1px;background:#dfe4ed}.custom-theme .el-select-group__title{padding-left:20px;font-size:12px;color:#0a76a4;line-height:30px}.custom-theme .el-select-group .el-select-dropdown__item{padding-left:20px}.custom-theme .el-scrollbar{overflow:hidden;position:relative}.custom-theme .el-scrollbar:active>.el-scrollbar__bar,.custom-theme .el-scrollbar:focus>.el-scrollbar__bar,.custom-theme .el-scrollbar:hover>.el-scrollbar__bar{opacity:1;-webkit-transition:opacity 340ms ease-out;transition:opacity 340ms ease-out}.custom-theme .el-scrollbar__wrap{overflow:scroll;height:100%}.custom-theme .el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.custom-theme .el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:rgba(135,141,153,.3);-webkit-transition:.3s background-color;transition:.3s background-color}.custom-theme .el-scrollbar__thumb:hover{background-color:rgba(135,141,153,.5)}.custom-theme .el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;-webkit-transition:opacity 120ms ease-out;transition:opacity 120ms ease-out}.custom-theme .el-scrollbar__bar.is-vertical{width:6px;top:2px}.custom-theme .el-scrollbar__bar.is-vertical>div{width:100%}.custom-theme .el-scrollbar__bar.is-horizontal{height:6px;left:2px}.custom-theme .el-scrollbar__bar.is-horizontal>div{height:100%}.custom-theme .el-select{display:inline-block;position:relative}.custom-theme .el-select:hover .el-input__inner{border-color:#b4bccc}.custom-theme .el-select .el-input__inner{cursor:pointer;padding-right:35px}.custom-theme .el-select .el-input__inner:focus{border-color:#262729}.custom-theme .el-select .el-input .el-select__caret{color:#b4bccc;font-size:14px;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg);line-height:16px;cursor:pointer}.custom-theme .el-select .el-input .el-select__caret.is-reverse{-webkit-transform:rotateZ(0);transform:rotateZ(0)}.custom-theme .el-select .el-input .el-select__caret.is-show-close{font-size:14px;text-align:center;-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg);border-radius:100%;color:#b4bccc;-webkit-transition:color .2s cubic-bezier(.645,.045,.355,1);transition:color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-select .el-input .el-select__caret.is-show-close:hover{color:#878d99}.custom-theme .el-select .el-input.is-disabled .el-input__inner{cursor:not-allowed}.custom-theme .el-select .el-input.is-disabled .el-input__inner:hover{border-color:#dfe4ed}.custom-theme .el-select>.el-input{display:block}.custom-theme .el-select__input{border:none;outline:0;padding:0;margin-left:15px;color:#666;font-size:14px;vertical-align:baseline;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:28px;background-color:transparent}.custom-theme .el-select__input.is-mini{height:14px}.custom-theme .el-select__close{cursor:pointer;position:absolute;top:8px;z-index:1000;right:25px;color:#b4bccc;line-height:18px;font-size:14px}.custom-theme .el-select__close:hover{color:#878d99}.custom-theme .el-select__tags{position:absolute;line-height:normal;white-space:normal;z-index:1;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.custom-theme .el-select .el-tag__close{margin-top:-2px}.custom-theme .el-select .el-tag{-webkit-box-sizing:border-box;box-sizing:border-box;border-color:transparent;margin:3px 0 3px 6px;background-color:#f0f2f5}.custom-theme .el-select .el-tag__close.el-icon-close{background-color:#b4bccc;right:-7px;color:#fff}.custom-theme .el-select .el-tag__close.el-icon-close:hover{background-color:#878d99}.custom-theme .el-select .el-tag__close.el-icon-close::before{display:block;-webkit-transform:translate(0,.5px);transform:translate(0,.5px)}.custom-theme .el-select__tag{display:inline-block;height:24px;line-height:24px;font-size:14px;border-radius:4px;color:#fff;background-color:#262729}.custom-theme .el-select__tag .el-icon-close{font-size:14px}.custom-theme .el-pagination{white-space:nowrap;padding:2px 5px;color:#2d2f33;font-weight:700}.custom-theme .el-pagination::after,.custom-theme .el-pagination::before{display:table;content:""}.custom-theme .el-pagination::after{clear:both}.custom-theme .el-pagination button,.custom-theme .el-pagination span:not([class*=suffix]){display:inline-block;font-size:13px;min-width:35.5px;height:28px;line-height:28px;vertical-align:top;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-pagination .el-input__inner{text-align:center}.custom-theme .el-pagination .el-input__suffix{right:0;-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-pagination .el-select .el-input{width:100px;margin:0 5px}.custom-theme .el-pagination .el-select .el-input .el-input__inner{padding-right:25px;border-radius:3px;height:28px}.custom-theme .el-pagination button{border:none;padding:0 6px;background:0 0}.custom-theme .el-pagination button:focus{outline:0}.custom-theme .el-pagination button:hover{color:#262729}.custom-theme .el-pagination button.disabled{color:#b4bccc;background-color:#fff;cursor:not-allowed}.custom-theme .el-pagination .btn-next,.custom-theme .el-pagination .btn-prev{background:center center no-repeat;background-size:16px;background-color:#fff;cursor:pointer;margin:0;color:#2d2f33}.custom-theme .el-pagination .btn-next .el-icon,.custom-theme .el-pagination .btn-prev .el-icon{display:block;font-size:12px}.custom-theme .el-pagination .btn-prev{padding-right:12px}.custom-theme .el-pagination .btn-next{padding-left:12px}.custom-theme .el-pagination--small .btn-next,.custom-theme .el-pagination--small .btn-prev,.custom-theme .el-pagination--small .el-pager li,.custom-theme .el-pagination--small .el-pager li:last-child{border-color:transparent;font-size:12px;line-height:22px;height:22px;min-width:22px}.custom-theme .el-pagination--small .arrow.disabled{visibility:hidden}.custom-theme .el-pagination__sizes{margin:0 10px 0 0;font-weight:400;color:#5a5e66}.custom-theme .el-pagination__sizes .el-input .el-input__inner{font-size:13px;padding-left:8px}.custom-theme .el-pagination__sizes .el-input .el-input__inner:hover{border-color:#262729}.custom-theme .el-pagination__total{margin-right:10px;font-weight:400;color:#5a5e66}.custom-theme .el-pagination__jump{margin-left:24px;font-weight:400;color:#5a5e66}.custom-theme .el-pagination__jump .el-input__inner{padding:0 3px}.custom-theme .el-pagination__rightwrapper{float:right}.custom-theme .el-pagination__editor{line-height:18px;padding:0 2px;height:28px;text-align:center;margin:0 2px;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:3px;-moz-appearance:textfield}.custom-theme .el-pagination__editor.el-input{width:50px}.custom-theme .el-pagination__editor.el-input .el-input__inner{height:28px}.custom-theme .el-pagination__editor .el-input__inner::-webkit-inner-spin-button,.custom-theme .el-pagination__editor .el-input__inner::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.custom-theme .el-pager{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;list-style:none;display:inline-block;vertical-align:top;font-size:0;padding:0;margin:0}.custom-theme .el-pager .el-icon-more::before{vertical-align:-4px}.custom-theme .el-pager li{padding:0 4px;background:#fff;vertical-align:top;display:inline-block;font-size:13px;min-width:35.5px;height:28px;line-height:28px;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box;text-align:center;margin:0}.custom-theme .el-pager li.btn-quicknext,.custom-theme .el-pager li.btn-quickprev{line-height:28px;color:#2d2f33}.custom-theme .el-pager li.btn-quickprev:hover{cursor:pointer}.custom-theme .el-pager li.btn-quicknext:hover{cursor:pointer}.custom-theme .el-pager li.active+li{border-left:0}.custom-theme .el-pager li:hover{color:#262729}.custom-theme .el-pager li.active{color:#262729;cursor:default}.custom-theme .v-modal-enter{-webkit-animation:v-modal-in .2s ease;animation:v-modal-in .2s ease}.custom-theme .v-modal-leave{-webkit-animation:v-modal-out .2s ease forwards;animation:v-modal-out .2s ease forwards}@-webkit-keyframes v-modal-in{0%{opacity:0}}@keyframes v-modal-in{0%{opacity:0}}@-webkit-keyframes v-modal-out{100%{opacity:0}}@keyframes v-modal-out{100%{opacity:0}}.custom-theme .v-modal{position:fixed;left:0;top:0;width:100%;height:100%;opacity:.5;background:#000}.custom-theme .el-dialog{position:relative;margin:0 auto 50px;background:#fff;border-radius:2px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.3);box-shadow:0 1px 3px rgba(0,0,0,.3);-webkit-box-sizing:border-box;box-sizing:border-box;width:50%}.custom-theme .el-dialog.is-fullscreen{width:100%;margin-top:0;margin-bottom:0;height:100%;overflow:auto}.custom-theme .el-dialog__wrapper{position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto;margin:0}.custom-theme .el-dialog__header{padding:15px;padding-bottom:10px}.custom-theme .el-dialog__headerbtn{position:absolute;top:15px;right:15px;padding:0;background:0 0;border:none;outline:0;cursor:pointer;font-size:16px}.custom-theme .el-dialog__headerbtn .el-dialog__close{color:#0a76a4}.custom-theme .el-dialog__headerbtn:focus .el-dialog__close,.custom-theme .el-dialog__headerbtn:hover .el-dialog__close{color:#262729}.custom-theme .el-dialog__title{line-height:24px;font-size:18px;color:#2d2f33}.custom-theme .el-dialog__body{padding:30px 20px;color:#5a5e66;line-height:24px;font-size:14px}.custom-theme .el-dialog__footer{padding:15px;padding-top:10px;text-align:right;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-dialog--center{text-align:center}.custom-theme .el-dialog--center .el-dialog__header{padding-top:30px}.custom-theme .el-dialog--center .el-dialog__body{text-align:initial;padding:25px 27px 30px}.custom-theme .el-dialog--center .el-dialog__footer{text-align:inherit;padding-bottom:30px}.custom-theme .dialog-fade-enter-active{-webkit-animation:dialog-fade-in .3s;animation:dialog-fade-in .3s}.custom-theme .dialog-fade-leave-active{-webkit-animation:dialog-fade-out .3s;animation:dialog-fade-out .3s}@-webkit-keyframes dialog-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes dialog-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes dialog-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}@keyframes dialog-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}.custom-theme .el-input{position:relative;font-size:14px;display:inline-block;width:100%}.custom-theme .el-input::-webkit-scrollbar{z-index:11;width:6px}.custom-theme .el-input::-webkit-scrollbar:horizontal{height:6px}.custom-theme .el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.custom-theme .el-input::-webkit-scrollbar-corner{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.custom-theme .el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #d8dce5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#5a5e66;display:inline-block;font-size:inherit;height:40px;line-height:1;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.custom-theme .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input__inner:hover{border-color:#b4bccc}.custom-theme .el-input__inner:focus{outline:0;border-color:#262729}.custom-theme .el-input__suffix{position:absolute;height:100%;right:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s;pointer-events:none}.custom-theme .el-input__suffix-inner{pointer-events:all}.custom-theme .el-input__prefix{position:absolute;height:100%;left:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s}.custom-theme .el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.custom-theme .el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.custom-theme .el-input__validateIcon{pointer-events:none}.custom-theme .el-input.is-active .el-input__inner{outline:0;border-color:#262729}.custom-theme .el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__icon{cursor:not-allowed}.custom-theme .el-input--suffix .el-input__inner{padding-right:30px}.custom-theme .el-input--prefix .el-input__inner{padding-left:30px}.custom-theme .el-input--medium{font-size:14px}.custom-theme .el-input--medium .el-input__inner{height:36px}.custom-theme .el-input--medium .el-input__icon{line-height:36px}.custom-theme .el-input--small{font-size:13px}.custom-theme .el-input--small .el-input__inner{height:32px}.custom-theme .el-input--small .el-input__icon{line-height:32px}.custom-theme .el-input--mini{font-size:12px}.custom-theme .el-input--mini .el-input__inner{height:28px}.custom-theme .el-input--mini .el-input__icon{line-height:28px}.custom-theme .el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.custom-theme .el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.custom-theme .el-input-group__append,.custom-theme .el-input-group__prepend{background-color:#f5f7fa;color:#0a76a4;vertical-align:middle;display:table-cell;position:relative;border:1px solid #d8dce5;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.custom-theme .el-input-group__append:focus,.custom-theme .el-input-group__prepend:focus{outline:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-select,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-select{display:inline-block;margin:-20px}.custom-theme .el-input-group__append button.el-button,.custom-theme .el-input-group__append div.el-select .el-input__inner,.custom-theme .el-input-group__append div.el-select:hover .el-input__inner,.custom-theme .el-input-group__prepend button.el-button,.custom-theme .el-input-group__prepend div.el-select .el-input__inner,.custom-theme .el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-input,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-input{font-size:inherit}.custom-theme .el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-input-group__append{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--prepend .el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--append .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-textarea{display:inline-block;width:100%;vertical-align:bottom}.custom-theme .el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:14px;color:#5a5e66;background-color:#fff;background-image:none;border:1px solid #d8dce5;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:hover{border-color:#b4bccc}.custom-theme .el-textarea__inner:focus{outline:0;border-color:#262729}.custom-theme .el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-scrollbar{overflow:hidden;position:relative}.custom-theme .el-scrollbar:active>.el-scrollbar__bar,.custom-theme .el-scrollbar:focus>.el-scrollbar__bar,.custom-theme .el-scrollbar:hover>.el-scrollbar__bar{opacity:1;-webkit-transition:opacity 340ms ease-out;transition:opacity 340ms ease-out}.custom-theme .el-scrollbar__wrap{overflow:scroll;height:100%}.custom-theme .el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.custom-theme .el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:rgba(135,141,153,.3);-webkit-transition:.3s background-color;transition:.3s background-color}.custom-theme .el-scrollbar__thumb:hover{background-color:rgba(135,141,153,.5)}.custom-theme .el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;-webkit-transition:opacity 120ms ease-out;transition:opacity 120ms ease-out}.custom-theme .el-scrollbar__bar.is-vertical{width:6px;top:2px}.custom-theme .el-scrollbar__bar.is-vertical>div{width:100%}.custom-theme .el-scrollbar__bar.is-horizontal{height:6px;left:2px}.custom-theme .el-scrollbar__bar.is-horizontal>div{height:100%}.custom-theme .el-popper .popper__arrow,.custom-theme .el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.custom-theme .el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.custom-theme .el-popper .popper__arrow::after{content:" ";border-width:6px}.custom-theme .el-popper[x-placement^=top]{margin-bottom:12px}.custom-theme .el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#e6ebf5;border-bottom-width:0}.custom-theme .el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.custom-theme .el-popper[x-placement^=bottom]{margin-top:12px}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#e6ebf5}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.custom-theme .el-popper[x-placement^=right]{margin-left:12px}.custom-theme .el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#e6ebf5;border-left-width:0}.custom-theme .el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.custom-theme .el-popper[x-placement^=left]{margin-right:12px}.custom-theme .el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#e6ebf5}.custom-theme .el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.custom-theme .el-autocomplete{position:relative;display:inline-block}.custom-theme .el-autocomplete-suggestion{margin:5px 0;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);border-radius:4px}.custom-theme .el-autocomplete-suggestion.el-popper .popper__arrow{left:24px!important}.custom-theme .el-autocomplete-suggestion__wrap{max-height:280px;padding:10px 0;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:auto;background-color:#fff;border:1px solid #dfe4ed;border-radius:4px}.custom-theme .el-autocomplete-suggestion__list{margin:0;padding:0}.custom-theme .el-autocomplete-suggestion li{padding:0 20px;margin:0;line-height:34px;cursor:pointer;color:#5a5e66;font-size:14px;list-style:none;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.custom-theme .el-autocomplete-suggestion li:hover{background-color:#f5f7fa}.custom-theme .el-autocomplete-suggestion li.highlighted{background-color:#f5f7fa}.custom-theme .el-autocomplete-suggestion li.divider{margin-top:6px;border-top:1px solid #000}.custom-theme .el-autocomplete-suggestion li.divider:last-child{margin-bottom:-6px}.custom-theme .el-autocomplete-suggestion.is-loading li{text-align:center;height:100px;line-height:100px;font-size:20px;color:#999}.custom-theme .el-autocomplete-suggestion.is-loading li::after{display:inline-block;content:"";height:100%;vertical-align:middle}.custom-theme .el-autocomplete-suggestion.is-loading li:hover{background-color:#fff}.custom-theme .el-autocomplete-suggestion.is-loading .el-icon-loading{vertical-align:middle}.custom-theme .el-button{display:inline-block;line-height:1;white-space:nowrap;cursor:pointer;background:#fff;border:1px solid #d8dce5;border-color:#d8dce5;color:#5a5e66;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;-webkit-transition:.1s;transition:.1s;font-weight:500;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;padding:12px 20px;font-size:14px;border-radius:4px}.custom-theme .el-button+.el-button{margin-left:10px}.custom-theme .el-button.is-round{padding:12px 20px}.custom-theme .el-button:focus,.custom-theme .el-button:hover{color:#262729;border-color:#bebebf;background-color:#e9e9ea}.custom-theme .el-button:active{color:#222325;border-color:#222325;outline:0}.custom-theme .el-button::-moz-focus-inner{border:0}.custom-theme .el-button [class*=el-icon-]+span{margin-left:5px}.custom-theme .el-button.is-plain:focus,.custom-theme .el-button.is-plain:hover{background:#fff;border-color:#262729;color:#262729}.custom-theme .el-button.is-plain:active{background:#fff;border-color:#222325;color:#222325;outline:0}.custom-theme .el-button.is-active{color:#222325;border-color:#222325}.custom-theme .el-button.is-disabled,.custom-theme .el-button.is-disabled:focus,.custom-theme .el-button.is-disabled:hover{color:#b4bccc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#e6ebf5}.custom-theme .el-button.is-disabled.el-button--text{background-color:transparent}.custom-theme .el-button.is-disabled.is-plain,.custom-theme .el-button.is-disabled.is-plain:focus,.custom-theme .el-button.is-disabled.is-plain:hover{background-color:#fff;border-color:#e6ebf5;color:#b4bccc}.custom-theme .el-button.is-loading{position:relative;pointer-events:none}.custom-theme .el-button.is-loading:before{pointer-events:none;content:'';position:absolute;left:-1px;top:-1px;right:-1px;bottom:-1px;border-radius:inherit;background-color:rgba(255,255,255,.35)}.custom-theme .el-button.is-round{border-radius:20px;padding:12px 23px}.custom-theme .el-button--primary{color:#fff;background-color:#262729;border-color:#262729}.custom-theme .el-button--primary:focus,.custom-theme .el-button--primary:hover{background:#515254;border-color:#515254;color:#fff}.custom-theme .el-button--primary:active{background:#222325;border-color:#222325;color:#fff;outline:0}.custom-theme .el-button--primary.is-active{background:#222325;border-color:#222325;color:#fff}.custom-theme .el-button--primary.is-disabled,.custom-theme .el-button--primary.is-disabled:active,.custom-theme .el-button--primary.is-disabled:focus,.custom-theme .el-button--primary.is-disabled:hover{color:#fff;background-color:#939394;border-color:#939394}.custom-theme .el-button--primary.is-plain{color:#262729;background:#e9e9ea;border-color:#a8a9a9}.custom-theme .el-button--primary.is-plain:focus,.custom-theme .el-button--primary.is-plain:hover{background:#262729;border-color:#262729;color:#fff}.custom-theme .el-button--primary.is-plain:active{background:#222325;border-color:#222325;color:#fff;outline:0}.custom-theme .el-button--primary.is-plain.is-disabled,.custom-theme .el-button--primary.is-plain.is-disabled:active,.custom-theme .el-button--primary.is-plain.is-disabled:focus,.custom-theme .el-button--primary.is-plain.is-disabled:hover{color:#7d7d7f;background-color:#e9e9ea;border-color:#d4d4d4}.custom-theme .el-button--success{color:#fff;background-color:#409167;border-color:#409167}.custom-theme .el-button--success:focus,.custom-theme .el-button--success:hover{background:#66a785;border-color:#66a785;color:#fff}.custom-theme .el-button--success:active{background:#3a835d;border-color:#3a835d;color:#fff;outline:0}.custom-theme .el-button--success.is-active{background:#3a835d;border-color:#3a835d;color:#fff}.custom-theme .el-button--success.is-disabled,.custom-theme .el-button--success.is-disabled:active,.custom-theme .el-button--success.is-disabled:focus,.custom-theme .el-button--success.is-disabled:hover{color:#fff;background-color:#a0c8b3;border-color:#a0c8b3}.custom-theme .el-button--success.is-plain{color:#409167;background:#ecf4f0;border-color:#b3d3c2}.custom-theme .el-button--success.is-plain:focus,.custom-theme .el-button--success.is-plain:hover{background:#409167;border-color:#409167;color:#fff}.custom-theme .el-button--success.is-plain:active{background:#3a835d;border-color:#3a835d;color:#fff;outline:0}.custom-theme .el-button--success.is-plain.is-disabled,.custom-theme .el-button--success.is-plain.is-disabled:active,.custom-theme .el-button--success.is-plain.is-disabled:focus,.custom-theme .el-button--success.is-plain.is-disabled:hover{color:#8cbda4;background-color:#ecf4f0;border-color:#d9e9e1}.custom-theme .el-button--warning{color:#fff;background-color:#9da408;border-color:#9da408}.custom-theme .el-button--warning:focus,.custom-theme .el-button--warning:hover{background:#b1b639;border-color:#b1b639;color:#fff}.custom-theme .el-button--warning:active{background:#8d9407;border-color:#8d9407;color:#fff;outline:0}.custom-theme .el-button--warning.is-active{background:#8d9407;border-color:#8d9407;color:#fff}.custom-theme .el-button--warning.is-disabled,.custom-theme .el-button--warning.is-disabled:active,.custom-theme .el-button--warning.is-disabled:focus,.custom-theme .el-button--warning.is-disabled:hover{color:#fff;background-color:#ced284;border-color:#ced284}.custom-theme .el-button--warning.is-plain{color:#9da408;background:#f5f6e6;border-color:#d8db9c}.custom-theme .el-button--warning.is-plain:focus,.custom-theme .el-button--warning.is-plain:hover{background:#9da408;border-color:#9da408;color:#fff}.custom-theme .el-button--warning.is-plain:active{background:#8d9407;border-color:#8d9407;color:#fff;outline:0}.custom-theme .el-button--warning.is-plain.is-disabled,.custom-theme .el-button--warning.is-plain.is-disabled:active,.custom-theme .el-button--warning.is-plain.is-disabled:focus,.custom-theme .el-button--warning.is-plain.is-disabled:hover{color:#c4c86b;background-color:#f5f6e6;border-color:#ebedce}.custom-theme .el-button--danger{color:#fff;background-color:#b3450e;border-color:#b3450e}.custom-theme .el-button--danger:focus,.custom-theme .el-button--danger:hover{background:#c26a3e;border-color:#c26a3e;color:#fff}.custom-theme .el-button--danger:active{background:#a13e0d;border-color:#a13e0d;color:#fff;outline:0}.custom-theme .el-button--danger.is-active{background:#a13e0d;border-color:#a13e0d;color:#fff}.custom-theme .el-button--danger.is-disabled,.custom-theme .el-button--danger.is-disabled:active,.custom-theme .el-button--danger.is-disabled:focus,.custom-theme .el-button--danger.is-disabled:hover{color:#fff;background-color:#d9a287;border-color:#d9a287}.custom-theme .el-button--danger.is-plain{color:#b3450e;background:#f7ece7;border-color:#e1b59f}.custom-theme .el-button--danger.is-plain:focus,.custom-theme .el-button--danger.is-plain:hover{background:#b3450e;border-color:#b3450e;color:#fff}.custom-theme .el-button--danger.is-plain:active{background:#a13e0d;border-color:#a13e0d;color:#fff;outline:0}.custom-theme .el-button--danger.is-plain.is-disabled,.custom-theme .el-button--danger.is-plain.is-disabled:active,.custom-theme .el-button--danger.is-plain.is-disabled:focus,.custom-theme .el-button--danger.is-plain.is-disabled:hover{color:#d18f6e;background-color:#f7ece7;border-color:#f0dacf}.custom-theme .el-button--info{color:#fff;background-color:#0a76a4;border-color:#0a76a4}.custom-theme .el-button--info:focus,.custom-theme .el-button--info:hover{background:#3b91b6;border-color:#3b91b6;color:#fff}.custom-theme .el-button--info:active{background:#096a94;border-color:#096a94;color:#fff;outline:0}.custom-theme .el-button--info.is-active{background:#096a94;border-color:#096a94;color:#fff}.custom-theme .el-button--info.is-disabled,.custom-theme .el-button--info.is-disabled:active,.custom-theme .el-button--info.is-disabled:focus,.custom-theme .el-button--info.is-disabled:hover{color:#fff;background-color:#85bbd2;border-color:#85bbd2}.custom-theme .el-button--info.is-plain{color:#0a76a4;background:#e7f1f6;border-color:#9dc8db}.custom-theme .el-button--info.is-plain:focus,.custom-theme .el-button--info.is-plain:hover{background:#0a76a4;border-color:#0a76a4;color:#fff}.custom-theme .el-button--info.is-plain:active{background:#096a94;border-color:#096a94;color:#fff;outline:0}.custom-theme .el-button--info.is-plain.is-disabled,.custom-theme .el-button--info.is-plain.is-disabled:active,.custom-theme .el-button--info.is-plain.is-disabled:focus,.custom-theme .el-button--info.is-plain.is-disabled:hover{color:#6cadc8;background-color:#e7f1f6;border-color:#cee4ed}.custom-theme .el-button--medium{padding:10px 20px;font-size:14px;border-radius:4px}.custom-theme .el-button--medium.is-round{padding:10px 20px}.custom-theme .el-button--small{padding:9px 15px;font-size:12px;border-radius:3px}.custom-theme .el-button--small.is-round{padding:9px 15px}.custom-theme .el-button--mini{padding:7px 15px;font-size:12px;border-radius:3px}.custom-theme .el-button--mini.is-round{padding:7px 15px}.custom-theme .el-button--text{border:none;color:#262729;background:0 0;padding-left:0;padding-right:0}.custom-theme .el-button--text:focus,.custom-theme .el-button--text:hover{color:#515254;border-color:transparent;background-color:transparent}.custom-theme .el-button--text:active{color:#222325;border-color:transparent;background-color:transparent}.custom-theme .el-button-group{display:inline-block;vertical-align:middle}.custom-theme .el-button-group::after,.custom-theme .el-button-group::before{display:table;content:""}.custom-theme .el-button-group::after{clear:both}.custom-theme .el-button-group .el-button{float:left;position:relative}.custom-theme .el-button-group .el-button+.el-button{margin-left:0}.custom-theme .el-button-group .el-button:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-button-group .el-button:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-button-group .el-button:not(:first-child):not(:last-child){border-radius:0}.custom-theme .el-button-group .el-button:not(:last-child){margin-right:-1px}.custom-theme .el-button-group .el-button:active,.custom-theme .el-button-group .el-button:focus,.custom-theme .el-button-group .el-button:hover{z-index:1}.custom-theme .el-button-group .el-button.is-active{z-index:1}.custom-theme .el-button-group .el-button--primary:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--primary:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--primary:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--success:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--success:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--success:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--warning:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--warning:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--warning:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--danger:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--danger:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--danger:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--info:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--info:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--info:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-popper .popper__arrow,.custom-theme .el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.custom-theme .el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.custom-theme .el-popper .popper__arrow::after{content:" ";border-width:6px}.custom-theme .el-popper[x-placement^=top]{margin-bottom:12px}.custom-theme .el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#e6ebf5;border-bottom-width:0}.custom-theme .el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.custom-theme .el-popper[x-placement^=bottom]{margin-top:12px}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#e6ebf5}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.custom-theme .el-popper[x-placement^=right]{margin-left:12px}.custom-theme .el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#e6ebf5;border-left-width:0}.custom-theme .el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.custom-theme .el-popper[x-placement^=left]{margin-right:12px}.custom-theme .el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#e6ebf5}.custom-theme .el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.custom-theme .el-dropdown{display:inline-block;position:relative;color:#5a5e66;font-size:14px}.custom-theme .el-dropdown .el-button-group{display:block}.custom-theme .el-dropdown .el-button-group .el-button{float:none}.custom-theme .el-dropdown .el-dropdown__caret-button{padding-left:5px;padding-right:5px;position:relative;border-left:none}.custom-theme .el-dropdown .el-dropdown__caret-button::before{content:'';position:absolute;display:block;width:1px;top:5px;bottom:5px;left:0;background:rgba(255,255,255,.5)}.custom-theme .el-dropdown .el-dropdown__caret-button:hover::before{top:0;bottom:0}.custom-theme .el-dropdown .el-dropdown__caret-button .el-dropdown__icon{padding-left:0}.custom-theme .el-dropdown__icon{font-size:12px;margin:0 3px}.custom-theme .el-dropdown-menu{position:absolute;top:0;left:0;z-index:10;padding:10px 0;margin:5px 0;background-color:#fff;border:1px solid #e6ebf5;border-radius:4px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.custom-theme .el-dropdown-menu__item{list-style:none;line-height:36px;padding:0 20px;margin:0;font-size:14px;color:#5a5e66;cursor:pointer}.custom-theme .el-dropdown-menu__item:not(.is-disabled):hover{background-color:#e9e9ea;color:#515254}.custom-theme .el-dropdown-menu__item--divided{position:relative;margin-top:6px;border-top:1px solid #e6ebf5}.custom-theme .el-dropdown-menu__item--divided:before{content:'';height:6px;display:block;margin:0 -20px;background-color:#fff}.custom-theme .el-dropdown-menu__item.is-disabled{cursor:default;color:#bbb;pointer-events:none}.custom-theme .el-dropdown-menu--medium{padding:6px 0}.custom-theme .el-dropdown-menu--medium .el-dropdown-menu__item{line-height:30px;padding:0 17px;font-size:14px}.custom-theme .el-dropdown-menu--medium .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:6px}.custom-theme .el-dropdown-menu--medium .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:6px;margin:0 -17px}.custom-theme .el-dropdown-menu--small{padding:6px 0}.custom-theme .el-dropdown-menu--small .el-dropdown-menu__item{line-height:27px;padding:0 15px;font-size:13px}.custom-theme .el-dropdown-menu--small .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:4px}.custom-theme .el-dropdown-menu--small .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:4px;margin:0 -15px}.custom-theme .el-dropdown-menu--mini{padding:3px 0}.custom-theme .el-dropdown-menu--mini .el-dropdown-menu__item{line-height:24px;padding:0 10px;font-size:12px}.custom-theme .el-dropdown-menu--mini .el-dropdown-menu__item.el-dropdown-menu__item--divided{margin-top:3px}.custom-theme .el-dropdown-menu--mini .el-dropdown-menu__item.el-dropdown-menu__item--divided:before{height:3px;margin:0 -10px}.custom-theme .el-menu{border-right:solid 1px #e6e6e6;list-style:none;position:relative;margin:0;padding-left:0;background-color:#fff}.custom-theme .el-menu::after,.custom-theme .el-menu::before{display:table;content:""}.custom-theme .el-menu::after{clear:both}.custom-theme .el-menu li{list-style:none}.custom-theme .el-menu--horizontal{border-right:none;border-bottom:solid 1px #e6e6e6}.custom-theme .el-menu--horizontal .el-menu-item{float:left;height:60px;line-height:60px;margin:0;cursor:pointer;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;border-bottom:2px solid transparent;color:#878d99}.custom-theme .el-menu--horizontal .el-menu-item a,.custom-theme .el-menu--horizontal .el-menu-item a:hover{color:inherit}.custom-theme .el-menu--horizontal .el-menu-item:focus,.custom-theme .el-menu--horizontal .el-menu-item:hover{background-color:#fff}.custom-theme .el-menu--horizontal .el-submenu{float:left;position:relative}.custom-theme .el-menu--horizontal .el-submenu:focus{outline:0}.custom-theme .el-menu--horizontal .el-submenu:focus>.el-submenu__title{color:#2d2f33}.custom-theme .el-menu--horizontal .el-submenu>.el-menu{position:absolute;top:65px;left:0;border:none;padding:5px 0;background-color:#fff;z-index:100;min-width:100%;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);border-radius:2px}.custom-theme .el-menu--horizontal .el-submenu .el-submenu__title{height:60px;line-height:60px;border-bottom:2px solid transparent;color:#878d99}.custom-theme .el-menu--horizontal .el-submenu .el-submenu__title:hover{background-color:#fff}.custom-theme .el-menu--horizontal .el-submenu .el-menu-item{background-color:#fff;float:none;height:36px;line-height:36px;padding:0 10px}.custom-theme .el-menu--horizontal .el-submenu .el-submenu__icon-arrow{position:static;vertical-align:middle;margin-left:8px;margin-top:-3px}.custom-theme .el-menu--horizontal .el-menu-item:focus,.custom-theme .el-menu--horizontal .el-menu-item:hover,.custom-theme .el-menu--horizontal .el-submenu__title:hover{outline:0;color:#2d2f33}.custom-theme .el-menu--horizontal>.el-menu-item.is-active,.custom-theme .el-menu--horizontal>.el-submenu.is-active .el-submenu__title{border-bottom:2px solid #262729;color:#2d2f33}.custom-theme .el-menu--collapse{width:64px}.custom-theme .el-menu--collapse>.el-menu-item [class^=el-icon-],.custom-theme .el-menu--collapse>.el-submenu>.el-submenu__title [class^=el-icon-]{margin:0;vertical-align:middle;width:24px;text-align:center}.custom-theme .el-menu--collapse>.el-menu-item .el-submenu__icon-arrow,.custom-theme .el-menu--collapse>.el-submenu>.el-submenu__title .el-submenu__icon-arrow{display:none}.custom-theme .el-menu--collapse>.el-menu-item span,.custom-theme .el-menu--collapse>.el-submenu>.el-submenu__title span{height:0;width:0;overflow:hidden;visibility:hidden;display:inline-block}.custom-theme .el-menu--collapse>.el-menu-item.is-active i{color:inherit}.custom-theme .el-menu--collapse .el-menu .el-submenu{min-width:200px}.custom-theme .el-menu--collapse .el-submenu{position:relative}.custom-theme .el-menu--collapse .el-submenu .el-menu{position:absolute;margin-left:5px;top:0;left:100%;z-index:10;border:1px solid #dfe4ed;border-radius:2px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.custom-theme .el-menu--collapse .el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{-webkit-transform:none;transform:none}.custom-theme .el-menu-item{height:56px;line-height:56px;font-size:14px;color:#2d2f33;padding:0 20px;cursor:pointer;position:relative;-webkit-transition:border-color .3s,background-color .3s,color .3s;transition:border-color .3s,background-color .3s,color .3s;-webkit-box-sizing:border-box;box-sizing:border-box;white-space:nowrap}.custom-theme .el-menu-item [class^=el-icon-]{margin-right:5px;width:24px;text-align:center;font-size:18px}.custom-theme .el-menu-item *{vertical-align:middle}.custom-theme .el-menu-item:first-child{margin-left:0}.custom-theme .el-menu-item:last-child{margin-right:0}.custom-theme .el-menu-item:focus,.custom-theme .el-menu-item:hover{outline:0;background-color:#e9e9ea}.custom-theme .el-menu-item i{color:#878d99}.custom-theme .el-menu-item.is-active{color:#262729}.custom-theme .el-menu-item.is-active i{color:inherit}.custom-theme .el-submenu__title{position:relative;height:56px;line-height:56px;font-size:14px;color:#2d2f33;padding:0 20px;cursor:pointer;position:relative;-webkit-transition:border-color .3s,background-color .3s,color .3s;transition:border-color .3s,background-color .3s,color .3s;-webkit-box-sizing:border-box;box-sizing:border-box;white-space:nowrap}.custom-theme .el-submenu__title *{vertical-align:middle}.custom-theme .el-submenu__title i{color:#878d99}.custom-theme .el-submenu__title:hover{background-color:#e9e9ea}.custom-theme .el-submenu .el-menu{border:none}.custom-theme .el-submenu .el-menu-item{height:50px;line-height:50px;padding:0 45px;min-width:200px}.custom-theme .el-submenu__icon-arrow{position:absolute;top:50%;right:20px;margin-top:-7px;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;font-size:12px}.custom-theme .el-submenu.is-active .el-submenu__title{border-bottom-color:#262729}.custom-theme .el-submenu.is-opened>.el-submenu__title .el-submenu__icon-arrow{-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg)}.custom-theme .el-submenu [class^=el-icon-]{vertical-align:middle;margin-right:5px;width:24px;text-align:center;font-size:18px}.custom-theme .el-menu-item-group>ul{padding:0}.custom-theme .el-menu-item-group__title{padding:7px 0 7px 20px;line-height:normal;font-size:12px;color:#878d99}.custom-theme .horizontal-collapse-transition .el-submenu__title .el-submenu__icon-arrow{-webkit-transition:.2s;transition:.2s;opacity:0}.custom-theme .el-input{position:relative;font-size:14px;display:inline-block;width:100%}.custom-theme .el-input::-webkit-scrollbar{z-index:11;width:6px}.custom-theme .el-input::-webkit-scrollbar:horizontal{height:6px}.custom-theme .el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.custom-theme .el-input::-webkit-scrollbar-corner{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.custom-theme .el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #d8dce5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#5a5e66;display:inline-block;font-size:inherit;height:40px;line-height:1;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.custom-theme .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input__inner:hover{border-color:#b4bccc}.custom-theme .el-input__inner:focus{outline:0;border-color:#262729}.custom-theme .el-input__suffix{position:absolute;height:100%;right:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s;pointer-events:none}.custom-theme .el-input__suffix-inner{pointer-events:all}.custom-theme .el-input__prefix{position:absolute;height:100%;left:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s}.custom-theme .el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.custom-theme .el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.custom-theme .el-input__validateIcon{pointer-events:none}.custom-theme .el-input.is-active .el-input__inner{outline:0;border-color:#262729}.custom-theme .el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__icon{cursor:not-allowed}.custom-theme .el-input--suffix .el-input__inner{padding-right:30px}.custom-theme .el-input--prefix .el-input__inner{padding-left:30px}.custom-theme .el-input--medium{font-size:14px}.custom-theme .el-input--medium .el-input__inner{height:36px}.custom-theme .el-input--medium .el-input__icon{line-height:36px}.custom-theme .el-input--small{font-size:13px}.custom-theme .el-input--small .el-input__inner{height:32px}.custom-theme .el-input--small .el-input__icon{line-height:32px}.custom-theme .el-input--mini{font-size:12px}.custom-theme .el-input--mini .el-input__inner{height:28px}.custom-theme .el-input--mini .el-input__icon{line-height:28px}.custom-theme .el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.custom-theme .el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.custom-theme .el-input-group__append,.custom-theme .el-input-group__prepend{background-color:#f5f7fa;color:#0a76a4;vertical-align:middle;display:table-cell;position:relative;border:1px solid #d8dce5;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.custom-theme .el-input-group__append:focus,.custom-theme .el-input-group__prepend:focus{outline:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-select,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-select{display:inline-block;margin:-20px}.custom-theme .el-input-group__append button.el-button,.custom-theme .el-input-group__append div.el-select .el-input__inner,.custom-theme .el-input-group__append div.el-select:hover .el-input__inner,.custom-theme .el-input-group__prepend button.el-button,.custom-theme .el-input-group__prepend div.el-select .el-input__inner,.custom-theme .el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-input,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-input{font-size:inherit}.custom-theme .el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-input-group__append{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--prepend .el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--append .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-textarea{display:inline-block;width:100%;vertical-align:bottom}.custom-theme .el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:14px;color:#5a5e66;background-color:#fff;background-image:none;border:1px solid #d8dce5;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:hover{border-color:#b4bccc}.custom-theme .el-textarea__inner:focus{outline:0;border-color:#262729}.custom-theme .el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-input{position:relative;font-size:14px;display:inline-block;width:100%}.custom-theme .el-input::-webkit-scrollbar{z-index:11;width:6px}.custom-theme .el-input::-webkit-scrollbar:horizontal{height:6px}.custom-theme .el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.custom-theme .el-input::-webkit-scrollbar-corner{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.custom-theme .el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #d8dce5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#5a5e66;display:inline-block;font-size:inherit;height:40px;line-height:1;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.custom-theme .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input__inner:hover{border-color:#b4bccc}.custom-theme .el-input__inner:focus{outline:0;border-color:#262729}.custom-theme .el-input__suffix{position:absolute;height:100%;right:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s;pointer-events:none}.custom-theme .el-input__suffix-inner{pointer-events:all}.custom-theme .el-input__prefix{position:absolute;height:100%;left:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s}.custom-theme .el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.custom-theme .el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.custom-theme .el-input__validateIcon{pointer-events:none}.custom-theme .el-input.is-active .el-input__inner{outline:0;border-color:#262729}.custom-theme .el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__icon{cursor:not-allowed}.custom-theme .el-input--suffix .el-input__inner{padding-right:30px}.custom-theme .el-input--prefix .el-input__inner{padding-left:30px}.custom-theme .el-input--medium{font-size:14px}.custom-theme .el-input--medium .el-input__inner{height:36px}.custom-theme .el-input--medium .el-input__icon{line-height:36px}.custom-theme .el-input--small{font-size:13px}.custom-theme .el-input--small .el-input__inner{height:32px}.custom-theme .el-input--small .el-input__icon{line-height:32px}.custom-theme .el-input--mini{font-size:12px}.custom-theme .el-input--mini .el-input__inner{height:28px}.custom-theme .el-input--mini .el-input__icon{line-height:28px}.custom-theme .el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.custom-theme .el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.custom-theme .el-input-group__append,.custom-theme .el-input-group__prepend{background-color:#f5f7fa;color:#0a76a4;vertical-align:middle;display:table-cell;position:relative;border:1px solid #d8dce5;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.custom-theme .el-input-group__append:focus,.custom-theme .el-input-group__prepend:focus{outline:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-select,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-select{display:inline-block;margin:-20px}.custom-theme .el-input-group__append button.el-button,.custom-theme .el-input-group__append div.el-select .el-input__inner,.custom-theme .el-input-group__append div.el-select:hover .el-input__inner,.custom-theme .el-input-group__prepend button.el-button,.custom-theme .el-input-group__prepend div.el-select .el-input__inner,.custom-theme .el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-input,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-input{font-size:inherit}.custom-theme .el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-input-group__append{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--prepend .el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--append .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-textarea{display:inline-block;width:100%;vertical-align:bottom}.custom-theme .el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:14px;color:#5a5e66;background-color:#fff;background-image:none;border:1px solid #d8dce5;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:hover{border-color:#b4bccc}.custom-theme .el-textarea__inner:focus{outline:0;border-color:#262729}.custom-theme .el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-input-number{position:relative;display:inline-block;width:180px;line-height:38px}.custom-theme .el-input-number .el-input{display:block}.custom-theme .el-input-number .el-input__inner{-webkit-appearance:none;padding-left:50px;padding-right:50px;text-align:center}.custom-theme .el-input-number__decrease,.custom-theme .el-input-number__increase{position:absolute;z-index:1;top:1px;width:40px;height:auto;text-align:center;background:#f5f7fa;color:#5a5e66;cursor:pointer;font-size:13px}.custom-theme .el-input-number__decrease:hover,.custom-theme .el-input-number__increase:hover{color:#262729}.custom-theme .el-input-number__decrease:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled),.custom-theme .el-input-number__increase:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled){border-color:#262729}.custom-theme .el-input-number__decrease.is-disabled,.custom-theme .el-input-number__increase.is-disabled{color:#b4bccc;cursor:not-allowed}.custom-theme .el-input-number__increase{right:1px;border-radius:0 4px 4px 0;border-left:1px solid #d8dce5}.custom-theme .el-input-number__decrease{left:1px;border-radius:4px 0 0 4px;border-right:1px solid #d8dce5}.custom-theme .el-input-number.is-disabled .el-input-number__decrease,.custom-theme .el-input-number.is-disabled .el-input-number__increase{border-color:#dfe4ed;color:#dfe4ed}.custom-theme .el-input-number.is-disabled .el-input-number__decrease:hover,.custom-theme .el-input-number.is-disabled .el-input-number__increase:hover{color:#dfe4ed;cursor:not-allowed}.custom-theme .el-input-number--medium{width:200px;line-height:34px}.custom-theme .el-input-number--medium .el-input-number__decrease,.custom-theme .el-input-number--medium .el-input-number__increase{width:36px;font-size:14px}.custom-theme .el-input-number--medium .el-input__inner{padding-left:43px;padding-right:43px}.custom-theme .el-input-number--small{width:130px;line-height:30px}.custom-theme .el-input-number--small .el-input-number__decrease,.custom-theme .el-input-number--small .el-input-number__increase{width:32px;font-size:13px}.custom-theme .el-input-number--small .el-input-number__decrease [class*=el-icon],.custom-theme .el-input-number--small .el-input-number__increase [class*=el-icon]{-webkit-transform:scale(.9);transform:scale(.9)}.custom-theme .el-input-number--small .el-input__inner{padding-left:39px;padding-right:39px}.custom-theme .el-input-number--mini{width:130px;line-height:26px}.custom-theme .el-input-number--mini .el-input-number__decrease,.custom-theme .el-input-number--mini .el-input-number__increase{width:28px;font-size:12px}.custom-theme .el-input-number--mini .el-input-number__decrease [class*=el-icon],.custom-theme .el-input-number--mini .el-input-number__increase [class*=el-icon]{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-input-number--mini .el-input__inner{padding-left:35px;padding-right:35px}.custom-theme .el-input-number.is-without-controls .el-input__inner{padding-left:15px;padding-right:15px}.custom-theme .el-input-number.is-controls-right .el-input__inner{padding-left:15px;padding-right:50px}.custom-theme .el-input-number.is-controls-right .el-input-number__decrease,.custom-theme .el-input-number.is-controls-right .el-input-number__increase{height:auto;line-height:19px}.custom-theme .el-input-number.is-controls-right .el-input-number__decrease [class*=el-icon],.custom-theme .el-input-number.is-controls-right .el-input-number__increase [class*=el-icon]{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-input-number.is-controls-right .el-input-number__increase{border-radius:0 4px 0 0;border-bottom:1px solid #d8dce5}.custom-theme .el-input-number.is-controls-right .el-input-number__decrease{right:1px;bottom:1px;top:auto;left:auto;border-right:none;border-left:1px solid #d8dce5;border-radius:0 0 4px 0}.custom-theme .el-input-number.is-controls-right[class*=medium] [class*=decrease],.custom-theme .el-input-number.is-controls-right[class*=medium] [class*=increase]{line-height:17px}.custom-theme .el-input-number.is-controls-right[class*=small] [class*=decrease],.custom-theme .el-input-number.is-controls-right[class*=small] [class*=increase]{line-height:15px}.custom-theme .el-input-number.is-controls-right[class*=mini] [class*=decrease],.custom-theme .el-input-number.is-controls-right[class*=mini] [class*=increase]{line-height:13px}.custom-theme .el-radio{color:#5a5e66;font-weight:500;line-height:1;position:relative;cursor:pointer;display:inline-block;white-space:nowrap;outline:0;font-size:14px;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none}.custom-theme .el-radio.is-bordered{padding:10px 20px 10px 10px;border-radius:4px;border:1px solid #d8dce5}.custom-theme .el-radio.is-bordered.is-checked{border-color:#262729}.custom-theme .el-radio.is-bordered.is-disabled{cursor:not-allowed;border-color:#e6ebf5}.custom-theme .el-radio.is-bordered+.el-radio.is-bordered{margin-left:10px}.custom-theme .el-radio--medium.is-bordered{padding:8px 20px 8px 10px;border-radius:4px}.custom-theme .el-radio--medium.is-bordered .el-radio__label{font-size:14px}.custom-theme .el-radio--medium.is-bordered .el-radio__inner{height:14px;width:14px}.custom-theme .el-radio--small.is-bordered{padding:6px 15px 6px 10px;border-radius:3px}.custom-theme .el-radio--small.is-bordered .el-radio__label{font-size:12px}.custom-theme .el-radio--small.is-bordered .el-radio__inner{height:12px;width:12px}.custom-theme .el-radio--mini.is-bordered{padding:4px 15px 4px 10px;border-radius:3px}.custom-theme .el-radio--mini.is-bordered .el-radio__label{font-size:12px}.custom-theme .el-radio--mini.is-bordered .el-radio__inner{height:12px;width:12px}.custom-theme .el-radio+.el-radio{margin-left:30px}.custom-theme .el-radio__input{white-space:nowrap;cursor:pointer;outline:0;display:inline-block;line-height:1;position:relative;vertical-align:middle}.custom-theme .el-radio__input.is-disabled .el-radio__inner{background-color:#f5f7fa;border-color:#dfe4ed;cursor:not-allowed}.custom-theme .el-radio__input.is-disabled .el-radio__inner::after{cursor:not-allowed;background-color:#f5f7fa}.custom-theme .el-radio__input.is-disabled .el-radio__inner+.el-radio__label{cursor:not-allowed}.custom-theme .el-radio__input.is-disabled.is-checked .el-radio__inner{background-color:#f5f7fa;border-color:#dfe4ed}.custom-theme .el-radio__input.is-disabled.is-checked .el-radio__inner::after{background-color:#b4bccc}.custom-theme .el-radio__input.is-disabled+span.el-radio__label{color:#b4bccc;cursor:not-allowed}.custom-theme .el-radio__input.is-checked .el-radio__inner{border-color:#262729;background:#262729}.custom-theme .el-radio__input.is-checked .el-radio__inner::after{-webkit-transform:translate(-50%,-50%) scale(1);transform:translate(-50%,-50%) scale(1)}.custom-theme .el-radio__input.is-checked+.el-radio__label{color:#262729}.custom-theme .el-radio__input.is-focus .el-radio__inner{border-color:#262729}.custom-theme .el-radio__inner{border:1px solid #d8dce5;border-radius:100%;width:14px;height:14px;background-color:#fff;position:relative;cursor:pointer;display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-radio__inner:hover{border-color:#262729}.custom-theme .el-radio__inner::after{width:4px;height:4px;border-radius:100%;background-color:#fff;content:"";position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%) scale(0);transform:translate(-50%,-50%) scale(0);-webkit-transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6);transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6);transition:transform .15s cubic-bezier(.71,-.46,.88,.6);transition:transform .15s cubic-bezier(.71,-.46,.88,.6),-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6)}.custom-theme .el-radio__original{opacity:0;outline:0;position:absolute;z-index:-1;top:0;left:0;right:0;bottom:0;margin:0}.custom-theme .el-radio:focus:not(.is-focus):not(:active) .el-radio__inner{-webkit-box-shadow:0 0 2px 2px #262729;box-shadow:0 0 2px 2px #262729}.custom-theme .el-radio__label{font-size:14px;padding-left:10px}.custom-theme .el-radio-group{display:inline-block;line-height:1;vertical-align:middle;font-size:0}.custom-theme .el-radio-button{position:relative;display:inline-block;outline:0}.custom-theme .el-radio-button__inner{display:inline-block;line-height:1;white-space:nowrap;vertical-align:middle;background:#fff;border:1px solid #d8dce5;font-weight:500;border-left:0;color:#5a5e66;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;position:relative;cursor:pointer;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);padding:12px 20px;font-size:14px;border-radius:0}.custom-theme .el-radio-button__inner.is-round{padding:12px 20px}.custom-theme .el-radio-button__inner:hover{color:#262729}.custom-theme .el-radio-button__inner [class*=el-icon-]{line-height:.9}.custom-theme .el-radio-button__inner [class*=el-icon-]+span{margin-left:5px}.custom-theme .el-radio-button__orig-radio{opacity:0;outline:0;position:absolute;z-index:-1;left:-999px}.custom-theme .el-radio-button__orig-radio:checked+.el-radio-button__inner{color:#fff;background-color:#262729;border-color:#262729;-webkit-box-shadow:-1px 0 0 0 #262729;box-shadow:-1px 0 0 0 #262729}.custom-theme .el-radio-button__orig-radio:disabled+.el-radio-button__inner{color:#b4bccc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#e6ebf5;-webkit-box-shadow:none;box-shadow:none}.custom-theme .el-radio-button__orig-radio:disabled:checked+.el-radio-button__inner{background-color:#edf2fc}.custom-theme .el-radio-button:first-child .el-radio-button__inner{border-left:1px solid #d8dce5;border-radius:4px 0 0 4px;-webkit-box-shadow:none!important;box-shadow:none!important}.custom-theme .el-radio-button:last-child .el-radio-button__inner{border-radius:0 4px 4px 0}.custom-theme .el-radio-button:first-child:last-child .el-radio-button__inner{border-radius:4px}.custom-theme .el-radio-button--medium .el-radio-button__inner{padding:10px 20px;font-size:14px;border-radius:0}.custom-theme .el-radio-button--medium .el-radio-button__inner.is-round{padding:10px 20px}.custom-theme .el-radio-button--small .el-radio-button__inner{padding:9px 15px;font-size:12px;border-radius:0}.custom-theme .el-radio-button--small .el-radio-button__inner.is-round{padding:9px 15px}.custom-theme .el-radio-button--mini .el-radio-button__inner{padding:7px 15px;font-size:12px;border-radius:0}.custom-theme .el-radio-button--mini .el-radio-button__inner.is-round{padding:7px 15px}.custom-theme .el-radio-button:focus:not(.is-focus):not(:active){-webkit-box-shadow:0 0 2px 2px #262729;box-shadow:0 0 2px 2px #262729}.custom-theme .el-checkbox{color:#5a5e66;font-weight:500;font-size:14px;position:relative;cursor:pointer;display:inline-block;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.custom-theme .el-checkbox.is-bordered{padding:9px 20px 9px 10px;border-radius:4px;border:1px solid #d8dce5}.custom-theme .el-checkbox.is-bordered.is-checked{border-color:#262729}.custom-theme .el-checkbox.is-bordered.is-disabled{border-color:#e6ebf5;cursor:not-allowed}.custom-theme .el-checkbox.is-bordered+.el-checkbox.is-bordered{margin-left:10px}.custom-theme .el-checkbox.is-bordered.el-checkbox--medium{padding:7px 20px 7px 10px;border-radius:4px}.custom-theme .el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__label{line-height:17px;font-size:14px}.custom-theme .el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__inner{height:14px;width:14px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small{padding:3px 15px 7px 10px;border-radius:3px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small .el-checkbox__label{line-height:15px;font-size:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner{height:12px;width:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner::after{height:6px;width:2px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini{padding:1px 15px 5px 10px;border-radius:3px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__label{line-height:12px;font-size:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner{height:12px;width:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner::after{height:6px;width:2px}.custom-theme .el-checkbox__input{white-space:nowrap;cursor:pointer;outline:0;display:inline-block;line-height:1;position:relative;vertical-align:middle}.custom-theme .el-checkbox__input.is-disabled .el-checkbox__inner{background-color:#edf2fc;border-color:#d8dce5;cursor:not-allowed}.custom-theme .el-checkbox__input.is-disabled .el-checkbox__inner::after{cursor:not-allowed;border-color:#b4bccc}.custom-theme .el-checkbox__input.is-disabled .el-checkbox__inner+.el-checkbox__label{cursor:not-allowed}.custom-theme .el-checkbox__input.is-disabled.is-checked .el-checkbox__inner{background-color:#edf2fc;border-color:#d8dce5}.custom-theme .el-checkbox__input.is-disabled.is-checked .el-checkbox__inner::after{border-color:#b4bccc}.custom-theme .el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner{background-color:#edf2fc;border-color:#d8dce5}.custom-theme .el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner::before{background-color:#b4bccc;border-color:#b4bccc}.custom-theme .el-checkbox__input.is-disabled+span.el-checkbox__label{color:#b4bccc;cursor:not-allowed}.custom-theme .el-checkbox__input.is-checked .el-checkbox__inner{background-color:#262729;border-color:#262729}.custom-theme .el-checkbox__input.is-checked .el-checkbox__inner::after{-webkit-transform:rotate(45deg) scaleY(1);transform:rotate(45deg) scaleY(1)}.custom-theme .el-checkbox__input.is-checked+.el-checkbox__label{color:#262729}.custom-theme .el-checkbox__input.is-focus .el-checkbox__inner{border-color:#262729}.custom-theme .el-checkbox__input.is-indeterminate .el-checkbox__inner{background-color:#262729;border-color:#262729}.custom-theme .el-checkbox__input.is-indeterminate .el-checkbox__inner::before{content:'';position:absolute;display:block;background-color:#fff;height:2px;-webkit-transform:scale(.5);transform:scale(.5);left:0;right:0;top:5px}.custom-theme .el-checkbox__input.is-indeterminate .el-checkbox__inner::after{display:none}.custom-theme .el-checkbox__inner{display:inline-block;position:relative;border:1px solid #d8dce5;border-radius:2px;-webkit-box-sizing:border-box;box-sizing:border-box;width:14px;height:14px;background-color:#fff;z-index:1;-webkit-transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.custom-theme .el-checkbox__inner:hover{border-color:#262729}.custom-theme .el-checkbox__inner::after{-webkit-box-sizing:content-box;box-sizing:content-box;content:"";border:1px solid #fff;border-left:0;border-top:0;height:7px;left:4px;position:absolute;top:1px;-webkit-transform:rotate(45deg) scaleY(0);transform:rotate(45deg) scaleY(0);width:3px;-webkit-transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms,-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;-webkit-transform-origin:center;transform-origin:center}.custom-theme .el-checkbox__original{opacity:0;outline:0;position:absolute;margin:0;width:0;height:0;left:-999px}.custom-theme .el-checkbox__label{display:inline-block;padding-left:10px;line-height:19px;font-size:14px}.custom-theme .el-checkbox+.el-checkbox{margin-left:30px}.custom-theme .el-checkbox-button{position:relative;display:inline-block}.custom-theme .el-checkbox-button__inner{display:inline-block;line-height:1;font-weight:500;white-space:nowrap;vertical-align:middle;cursor:pointer;background:#fff;border:1px solid #d8dce5;border-left:0;color:#5a5e66;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;position:relative;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;padding:12px 20px;font-size:14px;border-radius:0}.custom-theme .el-checkbox-button__inner.is-round{padding:12px 20px}.custom-theme .el-checkbox-button__inner:hover{color:#262729}.custom-theme .el-checkbox-button__inner [class*=el-icon-]{line-height:.9}.custom-theme .el-checkbox-button__inner [class*=el-icon-]+span{margin-left:5px}.custom-theme .el-checkbox-button__original{opacity:0;outline:0;position:absolute;margin:0;left:-999px}.custom-theme .el-checkbox-button.is-checked .el-checkbox-button__inner{color:#fff;background-color:#262729;border-color:#262729;-webkit-box-shadow:-1px 0 0 0 #7d7d7f;box-shadow:-1px 0 0 0 #7d7d7f}.custom-theme .el-checkbox-button.is-disabled .el-checkbox-button__inner{color:#b4bccc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#e6ebf5;-webkit-box-shadow:none;box-shadow:none}.custom-theme .el-checkbox-button:first-child .el-checkbox-button__inner{border-left:1px solid #d8dce5;border-radius:4px 0 0 4px;-webkit-box-shadow:none!important;box-shadow:none!important}.custom-theme .el-checkbox-button.is-focus .el-checkbox-button__inner{border-color:#262729}.custom-theme .el-checkbox-button:last-child .el-checkbox-button__inner{border-radius:0 4px 4px 0}.custom-theme .el-checkbox-button--medium .el-checkbox-button__inner{padding:10px 20px;font-size:14px;border-radius:0}.custom-theme .el-checkbox-button--medium .el-checkbox-button__inner.is-round{padding:10px 20px}.custom-theme .el-checkbox-button--small .el-checkbox-button__inner{padding:9px 15px;font-size:12px;border-radius:0}.custom-theme .el-checkbox-button--small .el-checkbox-button__inner.is-round{padding:9px 15px}.custom-theme .el-checkbox-button--mini .el-checkbox-button__inner{padding:7px 15px;font-size:12px;border-radius:0}.custom-theme .el-checkbox-button--mini .el-checkbox-button__inner.is-round{padding:7px 15px}.custom-theme .el-checkbox-group{font-size:0}.custom-theme .el-switch{display:inline-block;position:relative;font-size:14px;line-height:20px;height:20px;vertical-align:middle}.custom-theme .el-switch.is-disabled .el-switch__core,.custom-theme .el-switch.is-disabled .el-switch__label{cursor:not-allowed}.custom-theme .el-switch__label{-webkit-transition:.2s;transition:.2s;height:20px;display:inline-block;font-size:14px;font-weight:500;cursor:pointer;vertical-align:middle;color:#2d2f33}.custom-theme .el-switch__label.is-active{color:#262729}.custom-theme .el-switch__label--left{margin-right:10px}.custom-theme .el-switch__label--right{margin-left:10px}.custom-theme .el-switch__label *{line-height:1;font-size:14px;display:inline-block}.custom-theme .el-switch__input{position:absolute;width:0;height:0;opacity:0;margin:0}.custom-theme .el-switch__input:focus~.el-switch__core{outline:1px solid #262729}.custom-theme .el-switch__core{margin:0;display:inline-block;position:relative;width:40px;height:20px;border:1px solid #d8dce5;outline:0;border-radius:10px;-webkit-box-sizing:border-box;box-sizing:border-box;background:#d8dce5;cursor:pointer;-webkit-transition:border-color .3s,background-color .3s;transition:border-color .3s,background-color .3s;vertical-align:middle}.custom-theme .el-switch__core .el-switch__button{position:absolute;top:1px;left:1px;border-radius:100%;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;width:16px;height:16px;background-color:#fff}.custom-theme .el-switch.is-checked .el-switch__core{border-color:#262729;background-color:#262729}.custom-theme .el-switch.is-disabled{opacity:.6}.custom-theme .el-switch--wide .el-switch__label.el-switch__label--left span{left:10px}.custom-theme .el-switch--wide .el-switch__label.el-switch__label--right span{right:10px}.custom-theme .el-switch .label-fade-enter,.custom-theme .el-switch .label-fade-leave-active{opacity:0}.custom-theme .el-popper .popper__arrow,.custom-theme .el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.custom-theme .el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.custom-theme .el-popper .popper__arrow::after{content:" ";border-width:6px}.custom-theme .el-popper[x-placement^=top]{margin-bottom:12px}.custom-theme .el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#e6ebf5;border-bottom-width:0}.custom-theme .el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.custom-theme .el-popper[x-placement^=bottom]{margin-top:12px}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#e6ebf5}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.custom-theme .el-popper[x-placement^=right]{margin-left:12px}.custom-theme .el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#e6ebf5;border-left-width:0}.custom-theme .el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.custom-theme .el-popper[x-placement^=left]{margin-right:12px}.custom-theme .el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#e6ebf5}.custom-theme .el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.custom-theme .el-select-dropdown{position:absolute;z-index:1001;border:solid 1px #dfe4ed;border-radius:4px;background-color:#fff;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-box-sizing:border-box;box-sizing:border-box;margin:5px 0}.custom-theme .el-select-dropdown.is-multiple .el-select-dropdown__item.selected{color:#262729;background-color:#fff}.custom-theme .el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover{background-color:#f5f7fa}.custom-theme .el-select-dropdown.is-multiple .el-select-dropdown__item.selected::after{position:absolute;right:20px;font-family:element-icons;content:"\E611";font-size:12px;font-weight:700;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.custom-theme .el-select-dropdown .el-scrollbar.is-empty .el-select-dropdown__list{padding:0}.custom-theme .el-select-dropdown .popper__arrow{-webkit-transform:translateX(-400%);transform:translateX(-400%)}.custom-theme .el-select-dropdown.is-arrow-fixed .popper__arrow{-webkit-transform:translateX(-200%);transform:translateX(-200%)}.custom-theme .el-select-dropdown__empty{padding:10px 0;margin:0;text-align:center;color:#999;font-size:14px}.custom-theme .el-select-dropdown__wrap{max-height:274px}.custom-theme .el-select-dropdown__list{list-style:none;padding:6px 0;margin:0;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-input{position:relative;font-size:14px;display:inline-block;width:100%}.custom-theme .el-input::-webkit-scrollbar{z-index:11;width:6px}.custom-theme .el-input::-webkit-scrollbar:horizontal{height:6px}.custom-theme .el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.custom-theme .el-input::-webkit-scrollbar-corner{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.custom-theme .el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #d8dce5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#5a5e66;display:inline-block;font-size:inherit;height:40px;line-height:1;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.custom-theme .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input__inner:hover{border-color:#b4bccc}.custom-theme .el-input__inner:focus{outline:0;border-color:#262729}.custom-theme .el-input__suffix{position:absolute;height:100%;right:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s;pointer-events:none}.custom-theme .el-input__suffix-inner{pointer-events:all}.custom-theme .el-input__prefix{position:absolute;height:100%;left:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s}.custom-theme .el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.custom-theme .el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.custom-theme .el-input__validateIcon{pointer-events:none}.custom-theme .el-input.is-active .el-input__inner{outline:0;border-color:#262729}.custom-theme .el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__icon{cursor:not-allowed}.custom-theme .el-input--suffix .el-input__inner{padding-right:30px}.custom-theme .el-input--prefix .el-input__inner{padding-left:30px}.custom-theme .el-input--medium{font-size:14px}.custom-theme .el-input--medium .el-input__inner{height:36px}.custom-theme .el-input--medium .el-input__icon{line-height:36px}.custom-theme .el-input--small{font-size:13px}.custom-theme .el-input--small .el-input__inner{height:32px}.custom-theme .el-input--small .el-input__icon{line-height:32px}.custom-theme .el-input--mini{font-size:12px}.custom-theme .el-input--mini .el-input__inner{height:28px}.custom-theme .el-input--mini .el-input__icon{line-height:28px}.custom-theme .el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.custom-theme .el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.custom-theme .el-input-group__append,.custom-theme .el-input-group__prepend{background-color:#f5f7fa;color:#0a76a4;vertical-align:middle;display:table-cell;position:relative;border:1px solid #d8dce5;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.custom-theme .el-input-group__append:focus,.custom-theme .el-input-group__prepend:focus{outline:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-select,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-select{display:inline-block;margin:-20px}.custom-theme .el-input-group__append button.el-button,.custom-theme .el-input-group__append div.el-select .el-input__inner,.custom-theme .el-input-group__append div.el-select:hover .el-input__inner,.custom-theme .el-input-group__prepend button.el-button,.custom-theme .el-input-group__prepend div.el-select .el-input__inner,.custom-theme .el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-input,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-input{font-size:inherit}.custom-theme .el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-input-group__append{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--prepend .el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--append .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-textarea{display:inline-block;width:100%;vertical-align:bottom}.custom-theme .el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:14px;color:#5a5e66;background-color:#fff;background-image:none;border:1px solid #d8dce5;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:hover{border-color:#b4bccc}.custom-theme .el-textarea__inner:focus{outline:0;border-color:#262729}.custom-theme .el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-tag{background-color:rgba(38,39,41,.1);display:inline-block;padding:0 10px;height:32px;line-height:30px;font-size:12px;color:#262729;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid rgba(38,39,41,.2);white-space:nowrap}.custom-theme .el-tag .el-icon-close{border-radius:50%;text-align:center;position:relative;cursor:pointer;font-size:12px;height:18px;width:18px;line-height:18px;vertical-align:middle;top:-1px;right:-5px;color:#262729}.custom-theme .el-tag .el-icon-close::before{display:block}.custom-theme .el-tag .el-icon-close:hover{background-color:#262729;color:#fff}.custom-theme .el-tag--info{background-color:rgba(10,118,164,.1);border-color:rgba(10,118,164,.2);color:#0a76a4}.custom-theme .el-tag--info.is-hit{border-color:#0a76a4}.custom-theme .el-tag--info .el-tag__close{color:#0a76a4}.custom-theme .el-tag--info .el-tag__close:hover{background-color:#0a76a4;color:#fff}.custom-theme .el-tag--success{background-color:rgba(64,145,103,.1);border-color:rgba(64,145,103,.2);color:#409167}.custom-theme .el-tag--success.is-hit{border-color:#409167}.custom-theme .el-tag--success .el-tag__close{color:#409167}.custom-theme .el-tag--success .el-tag__close:hover{background-color:#409167;color:#fff}.custom-theme .el-tag--warning{background-color:rgba(157,164,8,.1);border-color:rgba(157,164,8,.2);color:#9da408}.custom-theme .el-tag--warning.is-hit{border-color:#9da408}.custom-theme .el-tag--warning .el-tag__close{color:#9da408}.custom-theme .el-tag--warning .el-tag__close:hover{background-color:#9da408;color:#fff}.custom-theme .el-tag--danger{background-color:rgba(179,69,14,.1);border-color:rgba(179,69,14,.2);color:#b3450e}.custom-theme .el-tag--danger.is-hit{border-color:#b3450e}.custom-theme .el-tag--danger .el-tag__close{color:#b3450e}.custom-theme .el-tag--danger .el-tag__close:hover{background-color:#b3450e;color:#fff}.custom-theme .el-tag--medium{height:28px;line-height:26px}.custom-theme .el-tag--medium .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-tag--small{height:24px;padding:0 8px;line-height:22px}.custom-theme .el-tag--small .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-tag--mini{height:20px;padding:0 5px;line-height:19px}.custom-theme .el-tag--mini .el-icon-close{margin-left:-3px;-webkit-transform:scale(.7);transform:scale(.7)}.custom-theme .el-select-dropdown__item{font-size:14px;padding:0 20px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#5a5e66;height:34px;line-height:34px;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:pointer}.custom-theme .el-select-dropdown__item.is-disabled{color:#b4bccc;cursor:not-allowed}.custom-theme .el-select-dropdown__item.is-disabled:hover{background-color:#fff}.custom-theme .el-select-dropdown__item.hover,.custom-theme .el-select-dropdown__item:hover{background-color:#f5f7fa}.custom-theme .el-select-dropdown__item.selected{color:#262729;font-weight:700}.custom-theme .el-select-dropdown__item span{line-height:34px!important}.custom-theme .el-select-group{margin:0;padding:0}.custom-theme .el-select-group__wrap{position:relative;list-style:none;margin:0;padding:0}.custom-theme .el-select-group__wrap:not(:last-of-type){padding-bottom:24px}.custom-theme .el-select-group__wrap:not(:last-of-type)::after{content:'';position:absolute;display:block;left:20px;right:20px;bottom:12px;height:1px;background:#dfe4ed}.custom-theme .el-select-group__title{padding-left:20px;font-size:12px;color:#0a76a4;line-height:30px}.custom-theme .el-select-group .el-select-dropdown__item{padding-left:20px}.custom-theme .el-scrollbar{overflow:hidden;position:relative}.custom-theme .el-scrollbar:active>.el-scrollbar__bar,.custom-theme .el-scrollbar:focus>.el-scrollbar__bar,.custom-theme .el-scrollbar:hover>.el-scrollbar__bar{opacity:1;-webkit-transition:opacity 340ms ease-out;transition:opacity 340ms ease-out}.custom-theme .el-scrollbar__wrap{overflow:scroll;height:100%}.custom-theme .el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.custom-theme .el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:rgba(135,141,153,.3);-webkit-transition:.3s background-color;transition:.3s background-color}.custom-theme .el-scrollbar__thumb:hover{background-color:rgba(135,141,153,.5)}.custom-theme .el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;-webkit-transition:opacity 120ms ease-out;transition:opacity 120ms ease-out}.custom-theme .el-scrollbar__bar.is-vertical{width:6px;top:2px}.custom-theme .el-scrollbar__bar.is-vertical>div{width:100%}.custom-theme .el-scrollbar__bar.is-horizontal{height:6px;left:2px}.custom-theme .el-scrollbar__bar.is-horizontal>div{height:100%}.custom-theme .el-select{display:inline-block;position:relative}.custom-theme .el-select:hover .el-input__inner{border-color:#b4bccc}.custom-theme .el-select .el-input__inner{cursor:pointer;padding-right:35px}.custom-theme .el-select .el-input__inner:focus{border-color:#262729}.custom-theme .el-select .el-input .el-select__caret{color:#b4bccc;font-size:14px;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg);line-height:16px;cursor:pointer}.custom-theme .el-select .el-input .el-select__caret.is-reverse{-webkit-transform:rotateZ(0);transform:rotateZ(0)}.custom-theme .el-select .el-input .el-select__caret.is-show-close{font-size:14px;text-align:center;-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg);border-radius:100%;color:#b4bccc;-webkit-transition:color .2s cubic-bezier(.645,.045,.355,1);transition:color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-select .el-input .el-select__caret.is-show-close:hover{color:#878d99}.custom-theme .el-select .el-input.is-disabled .el-input__inner{cursor:not-allowed}.custom-theme .el-select .el-input.is-disabled .el-input__inner:hover{border-color:#dfe4ed}.custom-theme .el-select>.el-input{display:block}.custom-theme .el-select__input{border:none;outline:0;padding:0;margin-left:15px;color:#666;font-size:14px;vertical-align:baseline;-webkit-appearance:none;-moz-appearance:none;appearance:none;height:28px;background-color:transparent}.custom-theme .el-select__input.is-mini{height:14px}.custom-theme .el-select__close{cursor:pointer;position:absolute;top:8px;z-index:1000;right:25px;color:#b4bccc;line-height:18px;font-size:14px}.custom-theme .el-select__close:hover{color:#878d99}.custom-theme .el-select__tags{position:absolute;line-height:normal;white-space:normal;z-index:1;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.custom-theme .el-select .el-tag__close{margin-top:-2px}.custom-theme .el-select .el-tag{-webkit-box-sizing:border-box;box-sizing:border-box;border-color:transparent;margin:3px 0 3px 6px;background-color:#f0f2f5}.custom-theme .el-select .el-tag__close.el-icon-close{background-color:#b4bccc;right:-7px;color:#fff}.custom-theme .el-select .el-tag__close.el-icon-close:hover{background-color:#878d99}.custom-theme .el-select .el-tag__close.el-icon-close::before{display:block;-webkit-transform:translate(0,.5px);transform:translate(0,.5px)}.custom-theme .el-select__tag{display:inline-block;height:24px;line-height:24px;font-size:14px;border-radius:4px;color:#fff;background-color:#262729}.custom-theme .el-select__tag .el-icon-close{font-size:14px}.custom-theme .el-button{display:inline-block;line-height:1;white-space:nowrap;cursor:pointer;background:#fff;border:1px solid #d8dce5;border-color:#d8dce5;color:#5a5e66;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;-webkit-transition:.1s;transition:.1s;font-weight:500;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;padding:12px 20px;font-size:14px;border-radius:4px}.custom-theme .el-button+.el-button{margin-left:10px}.custom-theme .el-button.is-round{padding:12px 20px}.custom-theme .el-button:focus,.custom-theme .el-button:hover{color:#262729;border-color:#bebebf;background-color:#e9e9ea}.custom-theme .el-button:active{color:#222325;border-color:#222325;outline:0}.custom-theme .el-button::-moz-focus-inner{border:0}.custom-theme .el-button [class*=el-icon-]+span{margin-left:5px}.custom-theme .el-button.is-plain:focus,.custom-theme .el-button.is-plain:hover{background:#fff;border-color:#262729;color:#262729}.custom-theme .el-button.is-plain:active{background:#fff;border-color:#222325;color:#222325;outline:0}.custom-theme .el-button.is-active{color:#222325;border-color:#222325}.custom-theme .el-button.is-disabled,.custom-theme .el-button.is-disabled:focus,.custom-theme .el-button.is-disabled:hover{color:#b4bccc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#e6ebf5}.custom-theme .el-button.is-disabled.el-button--text{background-color:transparent}.custom-theme .el-button.is-disabled.is-plain,.custom-theme .el-button.is-disabled.is-plain:focus,.custom-theme .el-button.is-disabled.is-plain:hover{background-color:#fff;border-color:#e6ebf5;color:#b4bccc}.custom-theme .el-button.is-loading{position:relative;pointer-events:none}.custom-theme .el-button.is-loading:before{pointer-events:none;content:'';position:absolute;left:-1px;top:-1px;right:-1px;bottom:-1px;border-radius:inherit;background-color:rgba(255,255,255,.35)}.custom-theme .el-button.is-round{border-radius:20px;padding:12px 23px}.custom-theme .el-button--primary{color:#fff;background-color:#262729;border-color:#262729}.custom-theme .el-button--primary:focus,.custom-theme .el-button--primary:hover{background:#515254;border-color:#515254;color:#fff}.custom-theme .el-button--primary:active{background:#222325;border-color:#222325;color:#fff;outline:0}.custom-theme .el-button--primary.is-active{background:#222325;border-color:#222325;color:#fff}.custom-theme .el-button--primary.is-disabled,.custom-theme .el-button--primary.is-disabled:active,.custom-theme .el-button--primary.is-disabled:focus,.custom-theme .el-button--primary.is-disabled:hover{color:#fff;background-color:#939394;border-color:#939394}.custom-theme .el-button--primary.is-plain{color:#262729;background:#e9e9ea;border-color:#a8a9a9}.custom-theme .el-button--primary.is-plain:focus,.custom-theme .el-button--primary.is-plain:hover{background:#262729;border-color:#262729;color:#fff}.custom-theme .el-button--primary.is-plain:active{background:#222325;border-color:#222325;color:#fff;outline:0}.custom-theme .el-button--primary.is-plain.is-disabled,.custom-theme .el-button--primary.is-plain.is-disabled:active,.custom-theme .el-button--primary.is-plain.is-disabled:focus,.custom-theme .el-button--primary.is-plain.is-disabled:hover{color:#7d7d7f;background-color:#e9e9ea;border-color:#d4d4d4}.custom-theme .el-button--success{color:#fff;background-color:#409167;border-color:#409167}.custom-theme .el-button--success:focus,.custom-theme .el-button--success:hover{background:#66a785;border-color:#66a785;color:#fff}.custom-theme .el-button--success:active{background:#3a835d;border-color:#3a835d;color:#fff;outline:0}.custom-theme .el-button--success.is-active{background:#3a835d;border-color:#3a835d;color:#fff}.custom-theme .el-button--success.is-disabled,.custom-theme .el-button--success.is-disabled:active,.custom-theme .el-button--success.is-disabled:focus,.custom-theme .el-button--success.is-disabled:hover{color:#fff;background-color:#a0c8b3;border-color:#a0c8b3}.custom-theme .el-button--success.is-plain{color:#409167;background:#ecf4f0;border-color:#b3d3c2}.custom-theme .el-button--success.is-plain:focus,.custom-theme .el-button--success.is-plain:hover{background:#409167;border-color:#409167;color:#fff}.custom-theme .el-button--success.is-plain:active{background:#3a835d;border-color:#3a835d;color:#fff;outline:0}.custom-theme .el-button--success.is-plain.is-disabled,.custom-theme .el-button--success.is-plain.is-disabled:active,.custom-theme .el-button--success.is-plain.is-disabled:focus,.custom-theme .el-button--success.is-plain.is-disabled:hover{color:#8cbda4;background-color:#ecf4f0;border-color:#d9e9e1}.custom-theme .el-button--warning{color:#fff;background-color:#9da408;border-color:#9da408}.custom-theme .el-button--warning:focus,.custom-theme .el-button--warning:hover{background:#b1b639;border-color:#b1b639;color:#fff}.custom-theme .el-button--warning:active{background:#8d9407;border-color:#8d9407;color:#fff;outline:0}.custom-theme .el-button--warning.is-active{background:#8d9407;border-color:#8d9407;color:#fff}.custom-theme .el-button--warning.is-disabled,.custom-theme .el-button--warning.is-disabled:active,.custom-theme .el-button--warning.is-disabled:focus,.custom-theme .el-button--warning.is-disabled:hover{color:#fff;background-color:#ced284;border-color:#ced284}.custom-theme .el-button--warning.is-plain{color:#9da408;background:#f5f6e6;border-color:#d8db9c}.custom-theme .el-button--warning.is-plain:focus,.custom-theme .el-button--warning.is-plain:hover{background:#9da408;border-color:#9da408;color:#fff}.custom-theme .el-button--warning.is-plain:active{background:#8d9407;border-color:#8d9407;color:#fff;outline:0}.custom-theme .el-button--warning.is-plain.is-disabled,.custom-theme .el-button--warning.is-plain.is-disabled:active,.custom-theme .el-button--warning.is-plain.is-disabled:focus,.custom-theme .el-button--warning.is-plain.is-disabled:hover{color:#c4c86b;background-color:#f5f6e6;border-color:#ebedce}.custom-theme .el-button--danger{color:#fff;background-color:#b3450e;border-color:#b3450e}.custom-theme .el-button--danger:focus,.custom-theme .el-button--danger:hover{background:#c26a3e;border-color:#c26a3e;color:#fff}.custom-theme .el-button--danger:active{background:#a13e0d;border-color:#a13e0d;color:#fff;outline:0}.custom-theme .el-button--danger.is-active{background:#a13e0d;border-color:#a13e0d;color:#fff}.custom-theme .el-button--danger.is-disabled,.custom-theme .el-button--danger.is-disabled:active,.custom-theme .el-button--danger.is-disabled:focus,.custom-theme .el-button--danger.is-disabled:hover{color:#fff;background-color:#d9a287;border-color:#d9a287}.custom-theme .el-button--danger.is-plain{color:#b3450e;background:#f7ece7;border-color:#e1b59f}.custom-theme .el-button--danger.is-plain:focus,.custom-theme .el-button--danger.is-plain:hover{background:#b3450e;border-color:#b3450e;color:#fff}.custom-theme .el-button--danger.is-plain:active{background:#a13e0d;border-color:#a13e0d;color:#fff;outline:0}.custom-theme .el-button--danger.is-plain.is-disabled,.custom-theme .el-button--danger.is-plain.is-disabled:active,.custom-theme .el-button--danger.is-plain.is-disabled:focus,.custom-theme .el-button--danger.is-plain.is-disabled:hover{color:#d18f6e;background-color:#f7ece7;border-color:#f0dacf}.custom-theme .el-button--info{color:#fff;background-color:#0a76a4;border-color:#0a76a4}.custom-theme .el-button--info:focus,.custom-theme .el-button--info:hover{background:#3b91b6;border-color:#3b91b6;color:#fff}.custom-theme .el-button--info:active{background:#096a94;border-color:#096a94;color:#fff;outline:0}.custom-theme .el-button--info.is-active{background:#096a94;border-color:#096a94;color:#fff}.custom-theme .el-button--info.is-disabled,.custom-theme .el-button--info.is-disabled:active,.custom-theme .el-button--info.is-disabled:focus,.custom-theme .el-button--info.is-disabled:hover{color:#fff;background-color:#85bbd2;border-color:#85bbd2}.custom-theme .el-button--info.is-plain{color:#0a76a4;background:#e7f1f6;border-color:#9dc8db}.custom-theme .el-button--info.is-plain:focus,.custom-theme .el-button--info.is-plain:hover{background:#0a76a4;border-color:#0a76a4;color:#fff}.custom-theme .el-button--info.is-plain:active{background:#096a94;border-color:#096a94;color:#fff;outline:0}.custom-theme .el-button--info.is-plain.is-disabled,.custom-theme .el-button--info.is-plain.is-disabled:active,.custom-theme .el-button--info.is-plain.is-disabled:focus,.custom-theme .el-button--info.is-plain.is-disabled:hover{color:#6cadc8;background-color:#e7f1f6;border-color:#cee4ed}.custom-theme .el-button--medium{padding:10px 20px;font-size:14px;border-radius:4px}.custom-theme .el-button--medium.is-round{padding:10px 20px}.custom-theme .el-button--small{padding:9px 15px;font-size:12px;border-radius:3px}.custom-theme .el-button--small.is-round{padding:9px 15px}.custom-theme .el-button--mini{padding:7px 15px;font-size:12px;border-radius:3px}.custom-theme .el-button--mini.is-round{padding:7px 15px}.custom-theme .el-button--text{border:none;color:#262729;background:0 0;padding-left:0;padding-right:0}.custom-theme .el-button--text:focus,.custom-theme .el-button--text:hover{color:#515254;border-color:transparent;background-color:transparent}.custom-theme .el-button--text:active{color:#222325;border-color:transparent;background-color:transparent}.custom-theme .el-button-group{display:inline-block;vertical-align:middle}.custom-theme .el-button-group::after,.custom-theme .el-button-group::before{display:table;content:""}.custom-theme .el-button-group::after{clear:both}.custom-theme .el-button-group .el-button{float:left;position:relative}.custom-theme .el-button-group .el-button+.el-button{margin-left:0}.custom-theme .el-button-group .el-button:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-button-group .el-button:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-button-group .el-button:not(:first-child):not(:last-child){border-radius:0}.custom-theme .el-button-group .el-button:not(:last-child){margin-right:-1px}.custom-theme .el-button-group .el-button:active,.custom-theme .el-button-group .el-button:focus,.custom-theme .el-button-group .el-button:hover{z-index:1}.custom-theme .el-button-group .el-button.is-active{z-index:1}.custom-theme .el-button-group .el-button--primary:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--primary:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--primary:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--success:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--success:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--success:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--warning:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--warning:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--warning:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--danger:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--danger:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--danger:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--info:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--info:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--info:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-checkbox{color:#5a5e66;font-weight:500;font-size:14px;position:relative;cursor:pointer;display:inline-block;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.custom-theme .el-checkbox.is-bordered{padding:9px 20px 9px 10px;border-radius:4px;border:1px solid #d8dce5}.custom-theme .el-checkbox.is-bordered.is-checked{border-color:#262729}.custom-theme .el-checkbox.is-bordered.is-disabled{border-color:#e6ebf5;cursor:not-allowed}.custom-theme .el-checkbox.is-bordered+.el-checkbox.is-bordered{margin-left:10px}.custom-theme .el-checkbox.is-bordered.el-checkbox--medium{padding:7px 20px 7px 10px;border-radius:4px}.custom-theme .el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__label{line-height:17px;font-size:14px}.custom-theme .el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__inner{height:14px;width:14px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small{padding:3px 15px 7px 10px;border-radius:3px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small .el-checkbox__label{line-height:15px;font-size:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner{height:12px;width:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner::after{height:6px;width:2px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini{padding:1px 15px 5px 10px;border-radius:3px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__label{line-height:12px;font-size:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner{height:12px;width:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner::after{height:6px;width:2px}.custom-theme .el-checkbox__input{white-space:nowrap;cursor:pointer;outline:0;display:inline-block;line-height:1;position:relative;vertical-align:middle}.custom-theme .el-checkbox__input.is-disabled .el-checkbox__inner{background-color:#edf2fc;border-color:#d8dce5;cursor:not-allowed}.custom-theme .el-checkbox__input.is-disabled .el-checkbox__inner::after{cursor:not-allowed;border-color:#b4bccc}.custom-theme .el-checkbox__input.is-disabled .el-checkbox__inner+.el-checkbox__label{cursor:not-allowed}.custom-theme .el-checkbox__input.is-disabled.is-checked .el-checkbox__inner{background-color:#edf2fc;border-color:#d8dce5}.custom-theme .el-checkbox__input.is-disabled.is-checked .el-checkbox__inner::after{border-color:#b4bccc}.custom-theme .el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner{background-color:#edf2fc;border-color:#d8dce5}.custom-theme .el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner::before{background-color:#b4bccc;border-color:#b4bccc}.custom-theme .el-checkbox__input.is-disabled+span.el-checkbox__label{color:#b4bccc;cursor:not-allowed}.custom-theme .el-checkbox__input.is-checked .el-checkbox__inner{background-color:#262729;border-color:#262729}.custom-theme .el-checkbox__input.is-checked .el-checkbox__inner::after{-webkit-transform:rotate(45deg) scaleY(1);transform:rotate(45deg) scaleY(1)}.custom-theme .el-checkbox__input.is-checked+.el-checkbox__label{color:#262729}.custom-theme .el-checkbox__input.is-focus .el-checkbox__inner{border-color:#262729}.custom-theme .el-checkbox__input.is-indeterminate .el-checkbox__inner{background-color:#262729;border-color:#262729}.custom-theme .el-checkbox__input.is-indeterminate .el-checkbox__inner::before{content:'';position:absolute;display:block;background-color:#fff;height:2px;-webkit-transform:scale(.5);transform:scale(.5);left:0;right:0;top:5px}.custom-theme .el-checkbox__input.is-indeterminate .el-checkbox__inner::after{display:none}.custom-theme .el-checkbox__inner{display:inline-block;position:relative;border:1px solid #d8dce5;border-radius:2px;-webkit-box-sizing:border-box;box-sizing:border-box;width:14px;height:14px;background-color:#fff;z-index:1;-webkit-transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.custom-theme .el-checkbox__inner:hover{border-color:#262729}.custom-theme .el-checkbox__inner::after{-webkit-box-sizing:content-box;box-sizing:content-box;content:"";border:1px solid #fff;border-left:0;border-top:0;height:7px;left:4px;position:absolute;top:1px;-webkit-transform:rotate(45deg) scaleY(0);transform:rotate(45deg) scaleY(0);width:3px;-webkit-transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms,-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;-webkit-transform-origin:center;transform-origin:center}.custom-theme .el-checkbox__original{opacity:0;outline:0;position:absolute;margin:0;width:0;height:0;left:-999px}.custom-theme .el-checkbox__label{display:inline-block;padding-left:10px;line-height:19px;font-size:14px}.custom-theme .el-checkbox+.el-checkbox{margin-left:30px}.custom-theme .el-checkbox-button{position:relative;display:inline-block}.custom-theme .el-checkbox-button__inner{display:inline-block;line-height:1;font-weight:500;white-space:nowrap;vertical-align:middle;cursor:pointer;background:#fff;border:1px solid #d8dce5;border-left:0;color:#5a5e66;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;position:relative;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;padding:12px 20px;font-size:14px;border-radius:0}.custom-theme .el-checkbox-button__inner.is-round{padding:12px 20px}.custom-theme .el-checkbox-button__inner:hover{color:#262729}.custom-theme .el-checkbox-button__inner [class*=el-icon-]{line-height:.9}.custom-theme .el-checkbox-button__inner [class*=el-icon-]+span{margin-left:5px}.custom-theme .el-checkbox-button__original{opacity:0;outline:0;position:absolute;margin:0;left:-999px}.custom-theme .el-checkbox-button.is-checked .el-checkbox-button__inner{color:#fff;background-color:#262729;border-color:#262729;-webkit-box-shadow:-1px 0 0 0 #7d7d7f;box-shadow:-1px 0 0 0 #7d7d7f}.custom-theme .el-checkbox-button.is-disabled .el-checkbox-button__inner{color:#b4bccc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#e6ebf5;-webkit-box-shadow:none;box-shadow:none}.custom-theme .el-checkbox-button:first-child .el-checkbox-button__inner{border-left:1px solid #d8dce5;border-radius:4px 0 0 4px;-webkit-box-shadow:none!important;box-shadow:none!important}.custom-theme .el-checkbox-button.is-focus .el-checkbox-button__inner{border-color:#262729}.custom-theme .el-checkbox-button:last-child .el-checkbox-button__inner{border-radius:0 4px 4px 0}.custom-theme .el-checkbox-button--medium .el-checkbox-button__inner{padding:10px 20px;font-size:14px;border-radius:0}.custom-theme .el-checkbox-button--medium .el-checkbox-button__inner.is-round{padding:10px 20px}.custom-theme .el-checkbox-button--small .el-checkbox-button__inner{padding:9px 15px;font-size:12px;border-radius:0}.custom-theme .el-checkbox-button--small .el-checkbox-button__inner.is-round{padding:9px 15px}.custom-theme .el-checkbox-button--mini .el-checkbox-button__inner{padding:7px 15px;font-size:12px;border-radius:0}.custom-theme .el-checkbox-button--mini .el-checkbox-button__inner.is-round{padding:7px 15px}.custom-theme .el-checkbox-group{font-size:0}.custom-theme .el-tag{background-color:rgba(38,39,41,.1);display:inline-block;padding:0 10px;height:32px;line-height:30px;font-size:12px;color:#262729;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid rgba(38,39,41,.2);white-space:nowrap}.custom-theme .el-tag .el-icon-close{border-radius:50%;text-align:center;position:relative;cursor:pointer;font-size:12px;height:18px;width:18px;line-height:18px;vertical-align:middle;top:-1px;right:-5px;color:#262729}.custom-theme .el-tag .el-icon-close::before{display:block}.custom-theme .el-tag .el-icon-close:hover{background-color:#262729;color:#fff}.custom-theme .el-tag--info{background-color:rgba(10,118,164,.1);border-color:rgba(10,118,164,.2);color:#0a76a4}.custom-theme .el-tag--info.is-hit{border-color:#0a76a4}.custom-theme .el-tag--info .el-tag__close{color:#0a76a4}.custom-theme .el-tag--info .el-tag__close:hover{background-color:#0a76a4;color:#fff}.custom-theme .el-tag--success{background-color:rgba(64,145,103,.1);border-color:rgba(64,145,103,.2);color:#409167}.custom-theme .el-tag--success.is-hit{border-color:#409167}.custom-theme .el-tag--success .el-tag__close{color:#409167}.custom-theme .el-tag--success .el-tag__close:hover{background-color:#409167;color:#fff}.custom-theme .el-tag--warning{background-color:rgba(157,164,8,.1);border-color:rgba(157,164,8,.2);color:#9da408}.custom-theme .el-tag--warning.is-hit{border-color:#9da408}.custom-theme .el-tag--warning .el-tag__close{color:#9da408}.custom-theme .el-tag--warning .el-tag__close:hover{background-color:#9da408;color:#fff}.custom-theme .el-tag--danger{background-color:rgba(179,69,14,.1);border-color:rgba(179,69,14,.2);color:#b3450e}.custom-theme .el-tag--danger.is-hit{border-color:#b3450e}.custom-theme .el-tag--danger .el-tag__close{color:#b3450e}.custom-theme .el-tag--danger .el-tag__close:hover{background-color:#b3450e;color:#fff}.custom-theme .el-tag--medium{height:28px;line-height:26px}.custom-theme .el-tag--medium .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-tag--small{height:24px;padding:0 8px;line-height:22px}.custom-theme .el-tag--small .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-tag--mini{height:20px;padding:0 5px;line-height:19px}.custom-theme .el-tag--mini .el-icon-close{margin-left:-3px;-webkit-transform:scale(.7);transform:scale(.7)}.custom-theme .el-table{position:relative;overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-box-flex:1;-ms-flex:1;flex:1;width:100%;max-width:100%;background-color:#fff;font-size:14px;color:#5a5e66}.custom-theme .el-table__empty-block{position:relative;min-height:60px;text-align:center;width:100%;height:100%}.custom-theme .el-table__empty-text{position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:color(#262729 s(16%) l(44%))}.custom-theme .el-table__expand-column .cell{padding:0;text-align:center}.custom-theme .el-table__expand-icon{position:relative;cursor:pointer;color:#666;font-size:12px;-webkit-transition:-webkit-transform .2s ease-in-out;transition:-webkit-transform .2s ease-in-out;transition:transform .2s ease-in-out;transition:transform .2s ease-in-out,-webkit-transform .2s ease-in-out;height:20px}.custom-theme .el-table__expand-icon--expanded{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.custom-theme .el-table__expand-icon>.el-icon{position:absolute;left:50%;top:50%;margin-left:-5px;margin-top:-5px}.custom-theme .el-table__expanded-cell{background-color:#fff}.custom-theme .el-table__expanded-cell[class*=cell]{padding:20px 50px}.custom-theme .el-table__expanded-cell:hover{background-color:#f5f7fa!important}.custom-theme .el-table--fit{border-right:0;border-bottom:0}.custom-theme .el-table--fit td.gutter,.custom-theme .el-table--fit th.gutter{border-right-width:1px}.custom-theme .el-table thead{color:#878d99;font-weight:500}.custom-theme .el-table thead.is-group th{background:#f5f7fa}.custom-theme .el-table td,.custom-theme .el-table th{padding:12px 0;min-width:0;-webkit-box-sizing:border-box;box-sizing:border-box;text-overflow:ellipsis;vertical-align:middle;position:relative}.custom-theme .el-table td.is-center,.custom-theme .el-table th.is-center{text-align:center}.custom-theme .el-table td.is-left,.custom-theme .el-table th.is-left{text-align:left}.custom-theme .el-table td.is-right,.custom-theme .el-table th.is-right{text-align:right}.custom-theme .el-table td.gutter,.custom-theme .el-table th.gutter{width:15px;border-right-width:0;border-bottom-width:0;padding:0}.custom-theme .el-table td.is-hidden>*,.custom-theme .el-table th.is-hidden>*{visibility:hidden}.custom-theme .el-table--medium td,.custom-theme .el-table--medium th{padding:10px 0}.custom-theme .el-table--small{font-size:12px}.custom-theme .el-table--small td,.custom-theme .el-table--small th{padding:8px 0}.custom-theme .el-table--mini{font-size:12px}.custom-theme .el-table--mini td,.custom-theme .el-table--mini th{padding:6px 0}.custom-theme .el-table tr{background-color:#fff}.custom-theme .el-table tr input[type=checkbox]{margin:0}.custom-theme .el-table td,.custom-theme .el-table th.is-leaf{border-bottom:1px solid #e6ebf5}.custom-theme .el-table th.is-sortable{cursor:pointer}.custom-theme .el-table th{white-space:nowrap;overflow:hidden;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:left}.custom-theme .el-table th div{display:inline-block;padding-left:10px;padding-right:10px;line-height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.custom-theme .el-table th>.cell{position:relative;word-wrap:normal;text-overflow:ellipsis;display:inline-block;vertical-align:middle;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-table th>.cell.highlight{color:#262729}.custom-theme .el-table th.required>div::before{display:inline-block;content:"";width:8px;height:8px;border-radius:50%;background:#ff4d51;margin-right:5px;vertical-align:middle}.custom-theme .el-table td div{-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-table td.gutter{width:0}.custom-theme .el-table .cell{-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden;text-overflow:ellipsis;white-space:normal;word-break:break-all;line-height:23px;padding-left:10px;padding-right:10px}.custom-theme .el-table .cell.el-tooltip{white-space:nowrap;min-width:50px}.custom-theme .el-table td:first-child .cell,.custom-theme .el-table th:first-child .cell{padding-left:0}.custom-theme .el-table--border,.custom-theme .el-table--group{border:1px solid #e6ebf5}.custom-theme .el-table--border::after,.custom-theme .el-table--group::after,.custom-theme .el-table::before{content:'';position:absolute;background-color:#e6ebf5;z-index:1}.custom-theme .el-table--border::after,.custom-theme .el-table--group::after{top:0;right:0;width:1px;height:100%}.custom-theme .el-table::before{left:0;bottom:0;width:100%;height:1px}.custom-theme .el-table--border{border-right:none;border-bottom:none}.custom-theme .el-table--border td,.custom-theme .el-table--border th{border-right:1px solid #e6ebf5}.custom-theme .el-table--border td:first-child .cell,.custom-theme .el-table--border th:first-child .cell{padding-left:10px}.custom-theme .el-table--border .has-gutter td:nth-last-of-type(2),.custom-theme .el-table--border .has-gutter th:nth-last-of-type(2){border-right:none}.custom-theme .el-table--border th.gutter:last-of-type{border-bottom:1px solid #e6ebf5;border-bottom-width:1px}.custom-theme .el-table--border th{border-bottom:1px solid #e6ebf5}.custom-theme .el-table--hidden{visibility:hidden}.custom-theme .el-table__fixed,.custom-theme .el-table__fixed-right{position:absolute;top:0;left:0;overflow-x:hidden;-webkit-box-shadow:0 0 10px rgba(0,0,0,.12);box-shadow:0 0 10px rgba(0,0,0,.12)}.custom-theme .el-table__fixed-right::before,.custom-theme .el-table__fixed::before{content:'';position:absolute;left:0;bottom:0;width:100%;height:1px;background-color:#e6ebf5;z-index:4}.custom-theme .el-table__fixed-right-patch{position:absolute;top:-1px;right:0;background-color:#fff;border-bottom:1px solid #e6ebf5}.custom-theme .el-table__fixed-right{top:0;left:auto;right:0}.custom-theme .el-table__fixed-right .el-table__fixed-body-wrapper,.custom-theme .el-table__fixed-right .el-table__fixed-footer-wrapper,.custom-theme .el-table__fixed-right .el-table__fixed-header-wrapper{left:auto;right:0}.custom-theme .el-table__fixed-header-wrapper{position:absolute;left:0;top:0;z-index:3}.custom-theme .el-table__fixed-footer-wrapper{position:absolute;left:0;bottom:0;z-index:3}.custom-theme .el-table__fixed-footer-wrapper tbody td{border-top:1px solid #e6ebf5;background-color:#f5f7fa;color:#5a5e66}.custom-theme .el-table__fixed-body-wrapper{position:absolute;left:0;top:37px;overflow:hidden;z-index:3}.custom-theme .el-table__body-wrapper,.custom-theme .el-table__footer-wrapper,.custom-theme .el-table__header-wrapper{width:100%}.custom-theme .el-table__footer-wrapper{margin-top:-1px}.custom-theme .el-table__footer-wrapper td{border-top:1px solid #e6ebf5}.custom-theme .el-table__body,.custom-theme .el-table__footer,.custom-theme .el-table__header{table-layout:fixed}.custom-theme .el-table__footer-wrapper,.custom-theme .el-table__header-wrapper{overflow:hidden}.custom-theme .el-table__footer-wrapper tbody td,.custom-theme .el-table__header-wrapper tbody td{background-color:#f5f7fa;color:#5a5e66}.custom-theme .el-table__body-wrapper{overflow:auto;position:relative}.custom-theme .el-table__body-wrapper.is-scroll-none~.el-table__fixed,.custom-theme .el-table__body-wrapper.is-scroll-none~.el-table__fixed-right{-webkit-box-shadow:none;box-shadow:none}.custom-theme .el-table__body-wrapper.is-scroll-left~.el-table__fixed{-webkit-box-shadow:none;box-shadow:none}.custom-theme .el-table__body-wrapper.is-scroll-right~.el-table__fixed-right{-webkit-box-shadow:none;box-shadow:none}.custom-theme .el-table__body-wrapper .el-table--border.is-scroll-right~.el-table__fixed-right{border-left:1px solid #e6ebf5}.custom-theme .el-table__body-wrapper .el-table--border.is-scroll-left~.el-table__fixed{border-right:1px solid #e6ebf5}.custom-theme .el-table .caret-wrapper{position:relative;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:13px;width:24px;cursor:pointer;overflow:initial}.custom-theme .el-table .sort-caret{color:#0a76a4;width:14px;overflow:hidden;font-size:13px}.custom-theme .el-table .ascending .sort-caret.ascending{color:#262729}.custom-theme .el-table .descending .sort-caret.descending{color:#262729}.custom-theme .el-table .hidden-columns{visibility:hidden;position:absolute;z-index:-1}.custom-theme .el-table--striped .el-table__body tr.el-table__row--striped td{background:#fafafa}.custom-theme .el-table--striped .el-table__body tr.el-table__row--striped.current-row td{background-color:#e9e9ea}.custom-theme .el-table__body tr.hover-row.current-row>td,.custom-theme .el-table__body tr.hover-row.el-table__row--striped.current-row>td,.custom-theme .el-table__body tr.hover-row.el-table__row--striped>td,.custom-theme .el-table__body tr.hover-row>td{background-color:#e9e9ea}.custom-theme .el-table__body tr.current-row>td{background-color:#e9e9ea}.custom-theme .el-table__column-resize-proxy{position:absolute;left:200px;top:0;bottom:0;width:0;border-left:1px solid #e6ebf5;z-index:10}.custom-theme .el-table__column-filter-trigger{display:inline-block;line-height:34px;cursor:pointer}.custom-theme .el-table__column-filter-trigger i{color:#0a76a4;font-size:12px;-webkit-transform:scale(.75);transform:scale(.75)}.custom-theme .el-table--enable-row-transition .el-table__body td{-webkit-transition:background-color .25s ease;transition:background-color .25s ease}.custom-theme .el-table--enable-row-hover .el-table__body tr:hover>td{background-color:#f5f7fa}.custom-theme .el-table--fluid-height .el-table__fixed,.custom-theme .el-table--fluid-height .el-table__fixed-right{bottom:0;overflow:hidden}.custom-theme .el-checkbox{color:#5a5e66;font-weight:500;font-size:14px;position:relative;cursor:pointer;display:inline-block;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.custom-theme .el-checkbox.is-bordered{padding:9px 20px 9px 10px;border-radius:4px;border:1px solid #d8dce5}.custom-theme .el-checkbox.is-bordered.is-checked{border-color:#262729}.custom-theme .el-checkbox.is-bordered.is-disabled{border-color:#e6ebf5;cursor:not-allowed}.custom-theme .el-checkbox.is-bordered+.el-checkbox.is-bordered{margin-left:10px}.custom-theme .el-checkbox.is-bordered.el-checkbox--medium{padding:7px 20px 7px 10px;border-radius:4px}.custom-theme .el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__label{line-height:17px;font-size:14px}.custom-theme .el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__inner{height:14px;width:14px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small{padding:3px 15px 7px 10px;border-radius:3px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small .el-checkbox__label{line-height:15px;font-size:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner{height:12px;width:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner::after{height:6px;width:2px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini{padding:1px 15px 5px 10px;border-radius:3px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__label{line-height:12px;font-size:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner{height:12px;width:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner::after{height:6px;width:2px}.custom-theme .el-checkbox__input{white-space:nowrap;cursor:pointer;outline:0;display:inline-block;line-height:1;position:relative;vertical-align:middle}.custom-theme .el-checkbox__input.is-disabled .el-checkbox__inner{background-color:#edf2fc;border-color:#d8dce5;cursor:not-allowed}.custom-theme .el-checkbox__input.is-disabled .el-checkbox__inner::after{cursor:not-allowed;border-color:#b4bccc}.custom-theme .el-checkbox__input.is-disabled .el-checkbox__inner+.el-checkbox__label{cursor:not-allowed}.custom-theme .el-checkbox__input.is-disabled.is-checked .el-checkbox__inner{background-color:#edf2fc;border-color:#d8dce5}.custom-theme .el-checkbox__input.is-disabled.is-checked .el-checkbox__inner::after{border-color:#b4bccc}.custom-theme .el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner{background-color:#edf2fc;border-color:#d8dce5}.custom-theme .el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner::before{background-color:#b4bccc;border-color:#b4bccc}.custom-theme .el-checkbox__input.is-disabled+span.el-checkbox__label{color:#b4bccc;cursor:not-allowed}.custom-theme .el-checkbox__input.is-checked .el-checkbox__inner{background-color:#262729;border-color:#262729}.custom-theme .el-checkbox__input.is-checked .el-checkbox__inner::after{-webkit-transform:rotate(45deg) scaleY(1);transform:rotate(45deg) scaleY(1)}.custom-theme .el-checkbox__input.is-checked+.el-checkbox__label{color:#262729}.custom-theme .el-checkbox__input.is-focus .el-checkbox__inner{border-color:#262729}.custom-theme .el-checkbox__input.is-indeterminate .el-checkbox__inner{background-color:#262729;border-color:#262729}.custom-theme .el-checkbox__input.is-indeterminate .el-checkbox__inner::before{content:'';position:absolute;display:block;background-color:#fff;height:2px;-webkit-transform:scale(.5);transform:scale(.5);left:0;right:0;top:5px}.custom-theme .el-checkbox__input.is-indeterminate .el-checkbox__inner::after{display:none}.custom-theme .el-checkbox__inner{display:inline-block;position:relative;border:1px solid #d8dce5;border-radius:2px;-webkit-box-sizing:border-box;box-sizing:border-box;width:14px;height:14px;background-color:#fff;z-index:1;-webkit-transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.custom-theme .el-checkbox__inner:hover{border-color:#262729}.custom-theme .el-checkbox__inner::after{-webkit-box-sizing:content-box;box-sizing:content-box;content:"";border:1px solid #fff;border-left:0;border-top:0;height:7px;left:4px;position:absolute;top:1px;-webkit-transform:rotate(45deg) scaleY(0);transform:rotate(45deg) scaleY(0);width:3px;-webkit-transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms,-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;-webkit-transform-origin:center;transform-origin:center}.custom-theme .el-checkbox__original{opacity:0;outline:0;position:absolute;margin:0;width:0;height:0;left:-999px}.custom-theme .el-checkbox__label{display:inline-block;padding-left:10px;line-height:19px;font-size:14px}.custom-theme .el-checkbox+.el-checkbox{margin-left:30px}.custom-theme .el-checkbox-button{position:relative;display:inline-block}.custom-theme .el-checkbox-button__inner{display:inline-block;line-height:1;font-weight:500;white-space:nowrap;vertical-align:middle;cursor:pointer;background:#fff;border:1px solid #d8dce5;border-left:0;color:#5a5e66;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;position:relative;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;padding:12px 20px;font-size:14px;border-radius:0}.custom-theme .el-checkbox-button__inner.is-round{padding:12px 20px}.custom-theme .el-checkbox-button__inner:hover{color:#262729}.custom-theme .el-checkbox-button__inner [class*=el-icon-]{line-height:.9}.custom-theme .el-checkbox-button__inner [class*=el-icon-]+span{margin-left:5px}.custom-theme .el-checkbox-button__original{opacity:0;outline:0;position:absolute;margin:0;left:-999px}.custom-theme .el-checkbox-button.is-checked .el-checkbox-button__inner{color:#fff;background-color:#262729;border-color:#262729;-webkit-box-shadow:-1px 0 0 0 #7d7d7f;box-shadow:-1px 0 0 0 #7d7d7f}.custom-theme .el-checkbox-button.is-disabled .el-checkbox-button__inner{color:#b4bccc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#e6ebf5;-webkit-box-shadow:none;box-shadow:none}.custom-theme .el-checkbox-button:first-child .el-checkbox-button__inner{border-left:1px solid #d8dce5;border-radius:4px 0 0 4px;-webkit-box-shadow:none!important;box-shadow:none!important}.custom-theme .el-checkbox-button.is-focus .el-checkbox-button__inner{border-color:#262729}.custom-theme .el-checkbox-button:last-child .el-checkbox-button__inner{border-radius:0 4px 4px 0}.custom-theme .el-checkbox-button--medium .el-checkbox-button__inner{padding:10px 20px;font-size:14px;border-radius:0}.custom-theme .el-checkbox-button--medium .el-checkbox-button__inner.is-round{padding:10px 20px}.custom-theme .el-checkbox-button--small .el-checkbox-button__inner{padding:9px 15px;font-size:12px;border-radius:0}.custom-theme .el-checkbox-button--small .el-checkbox-button__inner.is-round{padding:9px 15px}.custom-theme .el-checkbox-button--mini .el-checkbox-button__inner{padding:7px 15px;font-size:12px;border-radius:0}.custom-theme .el-checkbox-button--mini .el-checkbox-button__inner.is-round{padding:7px 15px}.custom-theme .el-checkbox-group{font-size:0}.custom-theme .el-tag{background-color:rgba(38,39,41,.1);display:inline-block;padding:0 10px;height:32px;line-height:30px;font-size:12px;color:#262729;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid rgba(38,39,41,.2);white-space:nowrap}.custom-theme .el-tag .el-icon-close{border-radius:50%;text-align:center;position:relative;cursor:pointer;font-size:12px;height:18px;width:18px;line-height:18px;vertical-align:middle;top:-1px;right:-5px;color:#262729}.custom-theme .el-tag .el-icon-close::before{display:block}.custom-theme .el-tag .el-icon-close:hover{background-color:#262729;color:#fff}.custom-theme .el-tag--info{background-color:rgba(10,118,164,.1);border-color:rgba(10,118,164,.2);color:#0a76a4}.custom-theme .el-tag--info.is-hit{border-color:#0a76a4}.custom-theme .el-tag--info .el-tag__close{color:#0a76a4}.custom-theme .el-tag--info .el-tag__close:hover{background-color:#0a76a4;color:#fff}.custom-theme .el-tag--success{background-color:rgba(64,145,103,.1);border-color:rgba(64,145,103,.2);color:#409167}.custom-theme .el-tag--success.is-hit{border-color:#409167}.custom-theme .el-tag--success .el-tag__close{color:#409167}.custom-theme .el-tag--success .el-tag__close:hover{background-color:#409167;color:#fff}.custom-theme .el-tag--warning{background-color:rgba(157,164,8,.1);border-color:rgba(157,164,8,.2);color:#9da408}.custom-theme .el-tag--warning.is-hit{border-color:#9da408}.custom-theme .el-tag--warning .el-tag__close{color:#9da408}.custom-theme .el-tag--warning .el-tag__close:hover{background-color:#9da408;color:#fff}.custom-theme .el-tag--danger{background-color:rgba(179,69,14,.1);border-color:rgba(179,69,14,.2);color:#b3450e}.custom-theme .el-tag--danger.is-hit{border-color:#b3450e}.custom-theme .el-tag--danger .el-tag__close{color:#b3450e}.custom-theme .el-tag--danger .el-tag__close:hover{background-color:#b3450e;color:#fff}.custom-theme .el-tag--medium{height:28px;line-height:26px}.custom-theme .el-tag--medium .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-tag--small{height:24px;padding:0 8px;line-height:22px}.custom-theme .el-tag--small .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-tag--mini{height:20px;padding:0 5px;line-height:19px}.custom-theme .el-tag--mini .el-icon-close{margin-left:-3px;-webkit-transform:scale(.7);transform:scale(.7)}.custom-theme .el-table-column--selection .cell{padding-left:14px;padding-right:14px}.custom-theme .el-table-filter{border:solid 1px #e6ebf5;border-radius:2px;background-color:#fff;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-box-sizing:border-box;box-sizing:border-box;margin:2px 0}.custom-theme .el-table-filter__list{padding:5px 0;margin:0;list-style:none;min-width:100px}.custom-theme .el-table-filter__list-item{line-height:36px;padding:0 10px;cursor:pointer;font-size:14px}.custom-theme .el-table-filter__list-item:hover{background-color:#e9e9ea;color:#515254}.custom-theme .el-table-filter__list-item.is-active{background-color:#262729;color:#fff}.custom-theme .el-table-filter__content{min-width:100px}.custom-theme .el-table-filter__bottom{border-top:1px solid #e6ebf5;padding:8px}.custom-theme .el-table-filter__bottom button{background:0 0;border:none;color:#5a5e66;cursor:pointer;font-size:13px;padding:0 3px}.custom-theme .el-table-filter__bottom button:hover{color:#262729}.custom-theme .el-table-filter__bottom button:focus{outline:0}.custom-theme .el-table-filter__bottom button.is-disabled{color:#b4bccc;cursor:not-allowed}.custom-theme .el-table-filter__checkbox-group{padding:10px}.custom-theme .el-table-filter__checkbox-group label.el-checkbox{display:block;margin-bottom:8px;margin-left:5px}.custom-theme .el-table-filter__checkbox-group .el-checkbox:last-child{margin-bottom:0}.custom-theme .el-date-table{font-size:12px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.custom-theme .el-date-table.is-week-mode .el-date-table__row:hover div{background-color:#edf2fc}.custom-theme .el-date-table.is-week-mode .el-date-table__row:hover td.available:hover{color:#5a5e66}.custom-theme .el-date-table.is-week-mode .el-date-table__row:hover td:first-child div{margin-left:5px;border-top-left-radius:15px;border-bottom-left-radius:15px}.custom-theme .el-date-table.is-week-mode .el-date-table__row:hover td:last-child div{margin-right:5px;border-top-right-radius:15px;border-bottom-right-radius:15px}.custom-theme .el-date-table.is-week-mode .el-date-table__row.current div{background-color:#edf2fc}.custom-theme .el-date-table td{width:32px;height:30px;padding:4px 0;-webkit-box-sizing:border-box;box-sizing:border-box;text-align:center;cursor:pointer;position:relative}.custom-theme .el-date-table td div{height:30px;padding:3px 0;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-date-table td span{width:24px;height:24px;display:block;margin:0 auto;line-height:24px;position:absolute;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);border-radius:50%}.custom-theme .el-date-table td.next-month,.custom-theme .el-date-table td.prev-month{color:#b4bccc}.custom-theme .el-date-table td.today{position:relative}.custom-theme .el-date-table td.today span{color:#262729}.custom-theme .el-date-table td.today.end-date span,.custom-theme .el-date-table td.today.start-date span{color:#fff}.custom-theme .el-date-table td.available:hover{color:#262729}.custom-theme .el-date-table td.in-range div{background-color:#edf2fc}.custom-theme .el-date-table td.in-range div:hover{background-color:#edf2fc}.custom-theme .el-date-table td.current:not(.disabled) span{color:#fff;background-color:#262729}.custom-theme .el-date-table td.end-date div,.custom-theme .el-date-table td.start-date div{color:#fff}.custom-theme .el-date-table td.end-date span,.custom-theme .el-date-table td.start-date span{background-color:#262729}.custom-theme .el-date-table td.start-date div{margin-left:5px;border-top-left-radius:15px;border-bottom-left-radius:15px}.custom-theme .el-date-table td.end-date div{margin-right:5px;border-top-right-radius:15px;border-bottom-right-radius:15px}.custom-theme .el-date-table td.disabled div{background-color:#f5f7fa;opacity:1;cursor:not-allowed;color:#b4bccc}.custom-theme .el-date-table td.week{font-size:80%;color:#5a5e66}.custom-theme .el-date-table th{padding:5px;color:#5a5e66;font-weight:400;border-bottom:solid 1px #e6ebf5}.custom-theme .el-month-table{font-size:12px;margin:-1px;border-collapse:collapse}.custom-theme .el-month-table td{text-align:center;padding:20px 3px;cursor:pointer}.custom-theme .el-month-table td.disabled .cell{background-color:#f5f7fa;cursor:not-allowed;color:#b4bccc}.custom-theme .el-month-table td.disabled .cell:hover{color:#b4bccc}.custom-theme .el-month-table td .cell{width:48px;height:32px;display:block;line-height:32px;color:#5a5e66;margin:0 auto}.custom-theme .el-month-table td .cell:hover{color:#262729}.custom-theme .el-month-table td.current:not(.disabled) .cell{color:#262729}.custom-theme .el-year-table{font-size:12px;margin:-1px;border-collapse:collapse}.custom-theme .el-year-table .el-icon{color:#2d2f33}.custom-theme .el-year-table td{text-align:center;padding:20px 3px;cursor:pointer}.custom-theme .el-year-table td.disabled .cell{background-color:#f5f7fa;cursor:not-allowed;color:#b4bccc}.custom-theme .el-year-table td.disabled .cell:hover{color:#b4bccc}.custom-theme .el-year-table td .cell{width:48px;height:32px;display:block;line-height:32px;color:#5a5e66;margin:0 auto}.custom-theme .el-year-table td .cell:hover{color:#262729}.custom-theme .el-year-table td.current:not(.disabled) .cell{color:#262729}.custom-theme .el-time-spinner.has-seconds .el-time-spinner__wrapper{width:33.3%}.custom-theme .el-time-spinner.has-seconds .el-time-spinner__wrapper:nth-child(2){margin-left:1%}.custom-theme .el-time-spinner__wrapper{max-height:190px;overflow:auto;display:inline-block;width:50%;vertical-align:top;position:relative}.custom-theme .el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default){padding-bottom:15px}.custom-theme .el-time-spinner__wrapper.is-arrow{-webkit-box-sizing:border-box;box-sizing:border-box;text-align:center;overflow:hidden}.custom-theme .el-time-spinner__wrapper.is-arrow .el-time-spinner__list{-webkit-transform:translateY(-32px);transform:translateY(-32px)}.custom-theme .el-time-spinner__wrapper.is-arrow .el-time-spinner__item:hover:not(.disabled):not(.active){background:#fff;cursor:default}.custom-theme .el-time-spinner__arrow{font-size:12px;color:#878d99;position:absolute;left:0;width:100%;z-index:1;text-align:center;height:30px;line-height:30px;cursor:pointer}.custom-theme .el-time-spinner__arrow:hover{color:#262729}.custom-theme .el-time-spinner__arrow.el-icon-arrow-up{top:10px}.custom-theme .el-time-spinner__arrow.el-icon-arrow-down{bottom:10px}.custom-theme .el-time-spinner__input.el-input{width:70%}.custom-theme .el-time-spinner__input.el-input .el-input__inner{padding:0;text-align:center}.custom-theme .el-time-spinner__list{padding:0;margin:0;list-style:none;text-align:center}.custom-theme .el-time-spinner__list::after,.custom-theme .el-time-spinner__list::before{content:'';display:block;width:100%;height:80px}.custom-theme .el-time-spinner__item{height:32px;line-height:32px;font-size:12px;color:#5a5e66}.custom-theme .el-time-spinner__item:hover:not(.disabled):not(.active){background:#f5f7fa;cursor:pointer}.custom-theme .el-time-spinner__item.active:not(.disabled){color:#2d2f33;font-weight:700}.custom-theme .el-time-spinner__item.disabled{color:#b4bccc;cursor:not-allowed}.custom-theme .fade-in-linear-enter-active,.custom-theme .fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.custom-theme .fade-in-linear-enter,.custom-theme .fade-in-linear-leave,.custom-theme .fade-in-linear-leave-active{opacity:0}.custom-theme .el-fade-in-linear-enter-active,.custom-theme .el-fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.custom-theme .el-fade-in-linear-enter,.custom-theme .el-fade-in-linear-leave,.custom-theme .el-fade-in-linear-leave-active{opacity:0}.custom-theme .el-fade-in-enter-active,.custom-theme .el-fade-in-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.custom-theme .el-fade-in-enter,.custom-theme .el-fade-in-leave-active{opacity:0}.custom-theme .el-zoom-in-center-enter-active,.custom-theme .el-zoom-in-center-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.custom-theme .el-zoom-in-center-enter,.custom-theme .el-zoom-in-center-leave-active{opacity:0;-webkit-transform:scaleX(0);transform:scaleX(0)}.custom-theme .el-zoom-in-top-enter-active,.custom-theme .el-zoom-in-top-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;-webkit-transform-origin:center top;transform-origin:center top}.custom-theme .el-zoom-in-top-enter,.custom-theme .el-zoom-in-top-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.custom-theme .el-zoom-in-bottom-enter-active,.custom-theme .el-zoom-in-bottom-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;-webkit-transform-origin:center bottom;transform-origin:center bottom}.custom-theme .el-zoom-in-bottom-enter,.custom-theme .el-zoom-in-bottom-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.custom-theme .el-zoom-in-left-enter-active,.custom-theme .el-zoom-in-left-leave-active{opacity:1;-webkit-transform:scale(1,1);transform:scale(1,1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;-webkit-transform-origin:top left;transform-origin:top left}.custom-theme .el-zoom-in-left-enter,.custom-theme .el-zoom-in-left-leave-active{opacity:0;-webkit-transform:scale(.45,.45);transform:scale(.45,.45)}.custom-theme .collapse-transition{-webkit-transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out;transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out}.custom-theme .horizontal-collapse-transition{-webkit-transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out;transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out}.custom-theme .el-list-enter-active,.custom-theme .el-list-leave-active{-webkit-transition:all 1s;transition:all 1s}.custom-theme .el-list-enter,.custom-theme .el-list-leave-active{opacity:0;-webkit-transform:translateY(-30px);transform:translateY(-30px)}.custom-theme .el-opacity-transition{-webkit-transition:opacity .3s cubic-bezier(.55,0,.1,1);transition:opacity .3s cubic-bezier(.55,0,.1,1)}.custom-theme .el-date-editor{position:relative;display:inline-block;text-align:left}.custom-theme .el-date-editor.el-input,.custom-theme .el-date-editor.el-input__inner{width:220px}.custom-theme .el-date-editor--daterange.el-input,.custom-theme .el-date-editor--daterange.el-input__inner,.custom-theme .el-date-editor--timerange.el-input,.custom-theme .el-date-editor--timerange.el-input__inner{width:350px}.custom-theme .el-date-editor--datetimerange.el-input,.custom-theme .el-date-editor--datetimerange.el-input__inner{width:400px}.custom-theme .el-date-editor .el-range__icon{font-size:14px;margin-left:-5px;color:#b4bccc;float:left;line-height:32px}.custom-theme .el-date-editor .el-range-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;outline:0;display:inline-block;height:100%;margin:0;padding:0;width:39%;text-align:center;font-size:14px;color:#5a5e66}.custom-theme .el-date-editor .el-range-input::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-date-editor .el-range-input:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-date-editor .el-range-input::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-date-editor .el-range-input::placeholder{color:#b4bccc}.custom-theme .el-date-editor .el-range-separator{display:inline-block;height:100%;padding:0 5px;margin:0;text-align:center;line-height:32px;font-size:14px;width:5%;color:#2d2f33}.custom-theme .el-date-editor .el-range__close-icon{font-size:14px;color:#b4bccc;width:25px;display:inline-block;float:right;line-height:32px}.custom-theme .el-range-editor.el-input__inner{padding:3px 10px}.custom-theme .el-range-editor.is-active{border-color:#262729}.custom-theme .el-range-editor.is-active:hover{border-color:#262729}.custom-theme .el-range-editor--medium.el-input__inner{height:36px}.custom-theme .el-range-editor--medium .el-range-separator{line-height:28px;font-size:14px}.custom-theme .el-range-editor--medium .el-range-input{font-size:14px}.custom-theme .el-range-editor--medium .el-range__close-icon,.custom-theme .el-range-editor--medium .el-range__icon{line-height:28px}.custom-theme .el-range-editor--small.el-input__inner{height:32px}.custom-theme .el-range-editor--small .el-range-separator{line-height:24px;font-size:13px}.custom-theme .el-range-editor--small .el-range-input{font-size:13px}.custom-theme .el-range-editor--small .el-range__close-icon,.custom-theme .el-range-editor--small .el-range__icon{line-height:24px}.custom-theme .el-range-editor--mini.el-input__inner{height:28px}.custom-theme .el-range-editor--mini .el-range-separator{line-height:20px;font-size:12px}.custom-theme .el-range-editor--mini .el-range-input{font-size:12px}.custom-theme .el-range-editor--mini .el-range__close-icon,.custom-theme .el-range-editor--mini .el-range__icon{line-height:20px}.custom-theme .el-range-editor.is-disabled{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-range-editor.is-disabled:focus,.custom-theme .el-range-editor.is-disabled:hover{border-color:#dfe4ed}.custom-theme .el-range-editor.is-disabled input{background-color:#f5f7fa;color:#b4bccc;cursor:not-allowed}.custom-theme .el-range-editor.is-disabled input::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-range-editor.is-disabled input:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-range-editor.is-disabled input::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-range-editor.is-disabled input::placeholder{color:#b4bccc}.custom-theme .el-range-editor.is-disabled .el-range-separator{color:#b4bccc}.custom-theme .el-picker-panel{color:#5a5e66;border:1px solid #dfe4ed;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);background:#fff;border-radius:4px;line-height:30px;margin:5px 0}.custom-theme .el-picker-panel__body-wrapper::after,.custom-theme .el-picker-panel__body::after{content:"";display:table;clear:both}.custom-theme .el-picker-panel__content{position:relative;margin:15px}.custom-theme .el-picker-panel__footer{border-top:1px solid #e4e4e4;padding:4px;text-align:right;background-color:#fff;position:relative;font-size:0}.custom-theme .el-picker-panel__shortcut{display:block;width:100%;border:0;background-color:transparent;line-height:28px;font-size:14px;color:#5a5e66;padding-left:12px;text-align:left;outline:0;cursor:pointer}.custom-theme .el-picker-panel__shortcut:hover{color:#262729}.custom-theme .el-picker-panel__shortcut.active{background-color:#e6f1fe;color:#262729}.custom-theme .el-picker-panel__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:0;font-size:12px}.custom-theme .el-picker-panel__btn[disabled]{color:#ccc;cursor:not-allowed}.custom-theme .el-picker-panel__icon-btn{font-size:12px;color:#2d2f33;border:0;background:0 0;cursor:pointer;outline:0;margin-top:8px}.custom-theme .el-picker-panel__icon-btn:hover{color:#262729}.custom-theme .el-picker-panel__icon-btn.is-disabled{color:#bbb}.custom-theme .el-picker-panel__icon-btn.is-disabled:hover{cursor:not-allowed}.custom-theme .el-picker-panel__link-btn{vertical-align:middle}.custom-theme .el-picker-panel .popper__arrow{-webkit-transform:translateX(-400%);transform:translateX(-400%)}.custom-theme .el-picker-panel [slot=sidebar],.custom-theme .el-picker-panel__sidebar{position:absolute;top:0;bottom:0;width:110px;border-right:1px solid #e4e4e4;-webkit-box-sizing:border-box;box-sizing:border-box;padding-top:6px;background-color:#fff;overflow:auto}.custom-theme .el-picker-panel [slot=sidebar]+.el-picker-panel__body,.custom-theme .el-picker-panel__sidebar+.el-picker-panel__body{margin-left:110px}.custom-theme .el-date-picker{width:322px}.custom-theme .el-date-picker.has-sidebar.has-time{width:434px}.custom-theme .el-date-picker.has-sidebar{width:438px}.custom-theme .el-date-picker.has-time .el-picker-panel__body-wrapper{position:relative}.custom-theme .el-date-picker .el-picker-panel__content{width:292px}.custom-theme .el-date-picker table{table-layout:fixed;width:100%}.custom-theme .el-date-picker__editor-wrap{position:relative;display:table-cell;padding:0 5px}.custom-theme .el-date-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px 5px;display:table;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-date-picker__header{margin:12px;text-align:center}.custom-theme .el-date-picker__header--bordered{margin-bottom:0;padding-bottom:12px;border-bottom:solid 1px #e6ebf5}.custom-theme .el-date-picker__header--bordered+.el-picker-panel__content{margin-top:0}.custom-theme .el-date-picker__header-label{font-size:16px;font-weight:500;padding:0 5px;line-height:22px;text-align:center;cursor:pointer;color:#5a5e66}.custom-theme .el-date-picker__header-label:hover{color:#262729}.custom-theme .el-date-picker__header-label.active{color:#262729}.custom-theme .el-date-picker__prev-btn{float:left}.custom-theme .el-date-picker__next-btn{float:right}.custom-theme .el-date-picker__time-wrap{padding:10px;text-align:center}.custom-theme .el-date-picker__time-label{float:left;cursor:pointer;line-height:30px;margin-left:10px}.custom-theme .el-date-range-picker{width:646px}.custom-theme .el-date-range-picker.has-sidebar{width:756px}.custom-theme .el-date-range-picker table{table-layout:fixed;width:100%}.custom-theme .el-date-range-picker .el-picker-panel__body{min-width:513px}.custom-theme .el-date-range-picker .el-picker-panel__content{margin:0}.custom-theme .el-date-range-picker__header{position:relative;text-align:center;height:28px}.custom-theme .el-date-range-picker__header [class*=arrow-left]{float:left}.custom-theme .el-date-range-picker__header [class*=arrow-right]{float:right}.custom-theme .el-date-range-picker__header div{font-size:16px;font-weight:500;margin-right:50px}.custom-theme .el-date-range-picker__content{float:left;width:50%;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:16px}.custom-theme .el-date-range-picker__content.is-left{border-right:1px solid #e4e4e4}.custom-theme .el-date-range-picker__content.is-right .el-date-range-picker__header div{margin-left:50px;margin-right:50px}.custom-theme .el-date-range-picker__editors-wrap{-webkit-box-sizing:border-box;box-sizing:border-box;display:table-cell}.custom-theme .el-date-range-picker__editors-wrap.is-right{text-align:right}.custom-theme .el-date-range-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px 5px;display:table;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-date-range-picker__time-header>.el-icon-arrow-right{font-size:20px;vertical-align:middle;display:table-cell;color:#2d2f33}.custom-theme .el-date-range-picker__time-picker-wrap{position:relative;display:table-cell;padding:0 5px}.custom-theme .el-date-range-picker__time-picker-wrap .el-picker-panel{position:absolute;top:13px;right:0;z-index:1;background:#fff}.custom-theme .el-time-range-picker{width:354px;overflow:visible}.custom-theme .el-time-range-picker__content{position:relative;text-align:center;padding:10px}.custom-theme .el-time-range-picker__cell{-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:4px 7px 7px;width:50%;display:inline-block}.custom-theme .el-time-range-picker__header{margin-bottom:5px;text-align:center;font-size:14px}.custom-theme .el-time-range-picker__body{border-radius:2px;border:1px solid #dfe4ed}.custom-theme .el-time-panel{margin:5px 0;border:solid 1px #dfe4ed;background-color:#fff;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);border-radius:2px;position:absolute;width:180px;left:0;z-index:1000;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.custom-theme .el-time-panel__content{font-size:0;position:relative;overflow:hidden}.custom-theme .el-time-panel__content::after,.custom-theme .el-time-panel__content::before{content:"";top:50%;position:absolute;margin-top:-15px;height:32px;z-index:-1;left:0;right:0;-webkit-box-sizing:border-box;box-sizing:border-box;padding-top:6px;text-align:left;border-top:1px solid #dfe4ed;border-bottom:1px solid #dfe4ed}.custom-theme .el-time-panel__content::after{left:50%;margin-left:12%;margin-right:12%}.custom-theme .el-time-panel__content::before{padding-left:50%;margin-right:12%;margin-left:12%}.custom-theme .el-time-panel__content.has-seconds::after{left:calc(100% / 3 * 2)}.custom-theme .el-time-panel__content.has-seconds::before{padding-left:calc(100% / 3)}.custom-theme .el-time-panel__footer{border-top:1px solid #e4e4e4;padding:4px;height:36px;line-height:25px;text-align:right;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-time-panel__btn{border:none;line-height:28px;padding:0 5px;margin:0 5px;cursor:pointer;background-color:transparent;outline:0;font-size:12px;color:#2d2f33}.custom-theme .el-time-panel__btn.confirm{font-weight:800;color:#262729}.custom-theme .el-time-panel .popper__arrow{-webkit-transform:translateX(-400%);transform:translateX(-400%)}.custom-theme .el-input{position:relative;font-size:14px;display:inline-block;width:100%}.custom-theme .el-input::-webkit-scrollbar{z-index:11;width:6px}.custom-theme .el-input::-webkit-scrollbar:horizontal{height:6px}.custom-theme .el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.custom-theme .el-input::-webkit-scrollbar-corner{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.custom-theme .el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #d8dce5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#5a5e66;display:inline-block;font-size:inherit;height:40px;line-height:1;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.custom-theme .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input__inner:hover{border-color:#b4bccc}.custom-theme .el-input__inner:focus{outline:0;border-color:#262729}.custom-theme .el-input__suffix{position:absolute;height:100%;right:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s;pointer-events:none}.custom-theme .el-input__suffix-inner{pointer-events:all}.custom-theme .el-input__prefix{position:absolute;height:100%;left:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s}.custom-theme .el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.custom-theme .el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.custom-theme .el-input__validateIcon{pointer-events:none}.custom-theme .el-input.is-active .el-input__inner{outline:0;border-color:#262729}.custom-theme .el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__icon{cursor:not-allowed}.custom-theme .el-input--suffix .el-input__inner{padding-right:30px}.custom-theme .el-input--prefix .el-input__inner{padding-left:30px}.custom-theme .el-input--medium{font-size:14px}.custom-theme .el-input--medium .el-input__inner{height:36px}.custom-theme .el-input--medium .el-input__icon{line-height:36px}.custom-theme .el-input--small{font-size:13px}.custom-theme .el-input--small .el-input__inner{height:32px}.custom-theme .el-input--small .el-input__icon{line-height:32px}.custom-theme .el-input--mini{font-size:12px}.custom-theme .el-input--mini .el-input__inner{height:28px}.custom-theme .el-input--mini .el-input__icon{line-height:28px}.custom-theme .el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.custom-theme .el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.custom-theme .el-input-group__append,.custom-theme .el-input-group__prepend{background-color:#f5f7fa;color:#0a76a4;vertical-align:middle;display:table-cell;position:relative;border:1px solid #d8dce5;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.custom-theme .el-input-group__append:focus,.custom-theme .el-input-group__prepend:focus{outline:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-select,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-select{display:inline-block;margin:-20px}.custom-theme .el-input-group__append button.el-button,.custom-theme .el-input-group__append div.el-select .el-input__inner,.custom-theme .el-input-group__append div.el-select:hover .el-input__inner,.custom-theme .el-input-group__prepend button.el-button,.custom-theme .el-input-group__prepend div.el-select .el-input__inner,.custom-theme .el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-input,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-input{font-size:inherit}.custom-theme .el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-input-group__append{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--prepend .el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--append .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-textarea{display:inline-block;width:100%;vertical-align:bottom}.custom-theme .el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:14px;color:#5a5e66;background-color:#fff;background-image:none;border:1px solid #d8dce5;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:hover{border-color:#b4bccc}.custom-theme .el-textarea__inner:focus{outline:0;border-color:#262729}.custom-theme .el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-scrollbar{overflow:hidden;position:relative}.custom-theme .el-scrollbar:active>.el-scrollbar__bar,.custom-theme .el-scrollbar:focus>.el-scrollbar__bar,.custom-theme .el-scrollbar:hover>.el-scrollbar__bar{opacity:1;-webkit-transition:opacity 340ms ease-out;transition:opacity 340ms ease-out}.custom-theme .el-scrollbar__wrap{overflow:scroll;height:100%}.custom-theme .el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.custom-theme .el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:rgba(135,141,153,.3);-webkit-transition:.3s background-color;transition:.3s background-color}.custom-theme .el-scrollbar__thumb:hover{background-color:rgba(135,141,153,.5)}.custom-theme .el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;-webkit-transition:opacity 120ms ease-out;transition:opacity 120ms ease-out}.custom-theme .el-scrollbar__bar.is-vertical{width:6px;top:2px}.custom-theme .el-scrollbar__bar.is-vertical>div{width:100%}.custom-theme .el-scrollbar__bar.is-horizontal{height:6px;left:2px}.custom-theme .el-scrollbar__bar.is-horizontal>div{height:100%}.custom-theme .el-popper .popper__arrow,.custom-theme .el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.custom-theme .el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.custom-theme .el-popper .popper__arrow::after{content:" ";border-width:6px}.custom-theme .el-popper[x-placement^=top]{margin-bottom:12px}.custom-theme .el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#e6ebf5;border-bottom-width:0}.custom-theme .el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.custom-theme .el-popper[x-placement^=bottom]{margin-top:12px}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#e6ebf5}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.custom-theme .el-popper[x-placement^=right]{margin-left:12px}.custom-theme .el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#e6ebf5;border-left-width:0}.custom-theme .el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.custom-theme .el-popper[x-placement^=left]{margin-right:12px}.custom-theme .el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#e6ebf5}.custom-theme .el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.custom-theme .fade-in-linear-enter-active,.custom-theme .fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.custom-theme .fade-in-linear-enter,.custom-theme .fade-in-linear-leave,.custom-theme .fade-in-linear-leave-active{opacity:0}.custom-theme .el-fade-in-linear-enter-active,.custom-theme .el-fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.custom-theme .el-fade-in-linear-enter,.custom-theme .el-fade-in-linear-leave,.custom-theme .el-fade-in-linear-leave-active{opacity:0}.custom-theme .el-fade-in-enter-active,.custom-theme .el-fade-in-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.custom-theme .el-fade-in-enter,.custom-theme .el-fade-in-leave-active{opacity:0}.custom-theme .el-zoom-in-center-enter-active,.custom-theme .el-zoom-in-center-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.custom-theme .el-zoom-in-center-enter,.custom-theme .el-zoom-in-center-leave-active{opacity:0;-webkit-transform:scaleX(0);transform:scaleX(0)}.custom-theme .el-zoom-in-top-enter-active,.custom-theme .el-zoom-in-top-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;-webkit-transform-origin:center top;transform-origin:center top}.custom-theme .el-zoom-in-top-enter,.custom-theme .el-zoom-in-top-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.custom-theme .el-zoom-in-bottom-enter-active,.custom-theme .el-zoom-in-bottom-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;-webkit-transform-origin:center bottom;transform-origin:center bottom}.custom-theme .el-zoom-in-bottom-enter,.custom-theme .el-zoom-in-bottom-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.custom-theme .el-zoom-in-left-enter-active,.custom-theme .el-zoom-in-left-leave-active{opacity:1;-webkit-transform:scale(1,1);transform:scale(1,1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;-webkit-transform-origin:top left;transform-origin:top left}.custom-theme .el-zoom-in-left-enter,.custom-theme .el-zoom-in-left-leave-active{opacity:0;-webkit-transform:scale(.45,.45);transform:scale(.45,.45)}.custom-theme .collapse-transition{-webkit-transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out;transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out}.custom-theme .horizontal-collapse-transition{-webkit-transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out;transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out}.custom-theme .el-list-enter-active,.custom-theme .el-list-leave-active{-webkit-transition:all 1s;transition:all 1s}.custom-theme .el-list-enter,.custom-theme .el-list-leave-active{opacity:0;-webkit-transform:translateY(-30px);transform:translateY(-30px)}.custom-theme .el-opacity-transition{-webkit-transition:opacity .3s cubic-bezier(.55,0,.1,1);transition:opacity .3s cubic-bezier(.55,0,.1,1)}.custom-theme .el-date-editor{position:relative;display:inline-block;text-align:left}.custom-theme .el-date-editor.el-input,.custom-theme .el-date-editor.el-input__inner{width:220px}.custom-theme .el-date-editor--daterange.el-input,.custom-theme .el-date-editor--daterange.el-input__inner,.custom-theme .el-date-editor--timerange.el-input,.custom-theme .el-date-editor--timerange.el-input__inner{width:350px}.custom-theme .el-date-editor--datetimerange.el-input,.custom-theme .el-date-editor--datetimerange.el-input__inner{width:400px}.custom-theme .el-date-editor .el-range__icon{font-size:14px;margin-left:-5px;color:#b4bccc;float:left;line-height:32px}.custom-theme .el-date-editor .el-range-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;outline:0;display:inline-block;height:100%;margin:0;padding:0;width:39%;text-align:center;font-size:14px;color:#5a5e66}.custom-theme .el-date-editor .el-range-input::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-date-editor .el-range-input:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-date-editor .el-range-input::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-date-editor .el-range-input::placeholder{color:#b4bccc}.custom-theme .el-date-editor .el-range-separator{display:inline-block;height:100%;padding:0 5px;margin:0;text-align:center;line-height:32px;font-size:14px;width:5%;color:#2d2f33}.custom-theme .el-date-editor .el-range__close-icon{font-size:14px;color:#b4bccc;width:25px;display:inline-block;float:right;line-height:32px}.custom-theme .el-range-editor.el-input__inner{padding:3px 10px}.custom-theme .el-range-editor.is-active{border-color:#262729}.custom-theme .el-range-editor.is-active:hover{border-color:#262729}.custom-theme .el-range-editor--medium.el-input__inner{height:36px}.custom-theme .el-range-editor--medium .el-range-separator{line-height:28px;font-size:14px}.custom-theme .el-range-editor--medium .el-range-input{font-size:14px}.custom-theme .el-range-editor--medium .el-range__close-icon,.custom-theme .el-range-editor--medium .el-range__icon{line-height:28px}.custom-theme .el-range-editor--small.el-input__inner{height:32px}.custom-theme .el-range-editor--small .el-range-separator{line-height:24px;font-size:13px}.custom-theme .el-range-editor--small .el-range-input{font-size:13px}.custom-theme .el-range-editor--small .el-range__close-icon,.custom-theme .el-range-editor--small .el-range__icon{line-height:24px}.custom-theme .el-range-editor--mini.el-input__inner{height:28px}.custom-theme .el-range-editor--mini .el-range-separator{line-height:20px;font-size:12px}.custom-theme .el-range-editor--mini .el-range-input{font-size:12px}.custom-theme .el-range-editor--mini .el-range__close-icon,.custom-theme .el-range-editor--mini .el-range__icon{line-height:20px}.custom-theme .el-range-editor.is-disabled{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-range-editor.is-disabled:focus,.custom-theme .el-range-editor.is-disabled:hover{border-color:#dfe4ed}.custom-theme .el-range-editor.is-disabled input{background-color:#f5f7fa;color:#b4bccc;cursor:not-allowed}.custom-theme .el-range-editor.is-disabled input::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-range-editor.is-disabled input:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-range-editor.is-disabled input::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-range-editor.is-disabled input::placeholder{color:#b4bccc}.custom-theme .el-range-editor.is-disabled .el-range-separator{color:#b4bccc}.custom-theme .el-picker-panel{color:#5a5e66;border:1px solid #dfe4ed;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);background:#fff;border-radius:4px;line-height:30px;margin:5px 0}.custom-theme .el-picker-panel__body-wrapper::after,.custom-theme .el-picker-panel__body::after{content:"";display:table;clear:both}.custom-theme .el-picker-panel__content{position:relative;margin:15px}.custom-theme .el-picker-panel__footer{border-top:1px solid #e4e4e4;padding:4px;text-align:right;background-color:#fff;position:relative;font-size:0}.custom-theme .el-picker-panel__shortcut{display:block;width:100%;border:0;background-color:transparent;line-height:28px;font-size:14px;color:#5a5e66;padding-left:12px;text-align:left;outline:0;cursor:pointer}.custom-theme .el-picker-panel__shortcut:hover{color:#262729}.custom-theme .el-picker-panel__shortcut.active{background-color:#e6f1fe;color:#262729}.custom-theme .el-picker-panel__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:0;font-size:12px}.custom-theme .el-picker-panel__btn[disabled]{color:#ccc;cursor:not-allowed}.custom-theme .el-picker-panel__icon-btn{font-size:12px;color:#2d2f33;border:0;background:0 0;cursor:pointer;outline:0;margin-top:8px}.custom-theme .el-picker-panel__icon-btn:hover{color:#262729}.custom-theme .el-picker-panel__icon-btn.is-disabled{color:#bbb}.custom-theme .el-picker-panel__icon-btn.is-disabled:hover{cursor:not-allowed}.custom-theme .el-picker-panel__link-btn{vertical-align:middle}.custom-theme .el-picker-panel .popper__arrow{-webkit-transform:translateX(-400%);transform:translateX(-400%)}.custom-theme .el-picker-panel [slot=sidebar],.custom-theme .el-picker-panel__sidebar{position:absolute;top:0;bottom:0;width:110px;border-right:1px solid #e4e4e4;-webkit-box-sizing:border-box;box-sizing:border-box;padding-top:6px;background-color:#fff;overflow:auto}.custom-theme .el-picker-panel [slot=sidebar]+.el-picker-panel__body,.custom-theme .el-picker-panel__sidebar+.el-picker-panel__body{margin-left:110px}.custom-theme .el-date-picker{width:322px}.custom-theme .el-date-picker.has-sidebar.has-time{width:434px}.custom-theme .el-date-picker.has-sidebar{width:438px}.custom-theme .el-date-picker.has-time .el-picker-panel__body-wrapper{position:relative}.custom-theme .el-date-picker .el-picker-panel__content{width:292px}.custom-theme .el-date-picker table{table-layout:fixed;width:100%}.custom-theme .el-date-picker__editor-wrap{position:relative;display:table-cell;padding:0 5px}.custom-theme .el-date-picker__time-header{position:relative;border-bottom:1px solid #e4e4e4;font-size:12px;padding:8px 5px 5px 5px;display:table;width:100%;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-date-picker__header{margin:12px;text-align:center}.custom-theme .el-date-picker__header--bordered{margin-bottom:0;padding-bottom:12px;border-bottom:solid 1px #e6ebf5}.custom-theme .el-date-picker__header--bordered+.el-picker-panel__content{margin-top:0}.custom-theme .el-date-picker__header-label{font-size:16px;font-weight:500;padding:0 5px;line-height:22px;text-align:center;cursor:pointer;color:#5a5e66}.custom-theme .el-date-picker__header-label:hover{color:#262729}.custom-theme .el-date-picker__header-label.active{color:#262729}.custom-theme .el-date-picker__prev-btn{float:left}.custom-theme .el-date-picker__next-btn{float:right}.custom-theme .el-date-picker__time-wrap{padding:10px;text-align:center}.custom-theme .el-date-picker__time-label{float:left;cursor:pointer;line-height:30px;margin-left:10px}.custom-theme .el-scrollbar{overflow:hidden;position:relative}.custom-theme .el-scrollbar:active>.el-scrollbar__bar,.custom-theme .el-scrollbar:focus>.el-scrollbar__bar,.custom-theme .el-scrollbar:hover>.el-scrollbar__bar{opacity:1;-webkit-transition:opacity 340ms ease-out;transition:opacity 340ms ease-out}.custom-theme .el-scrollbar__wrap{overflow:scroll;height:100%}.custom-theme .el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.custom-theme .el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:rgba(135,141,153,.3);-webkit-transition:.3s background-color;transition:.3s background-color}.custom-theme .el-scrollbar__thumb:hover{background-color:rgba(135,141,153,.5)}.custom-theme .el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;-webkit-transition:opacity 120ms ease-out;transition:opacity 120ms ease-out}.custom-theme .el-scrollbar__bar.is-vertical{width:6px;top:2px}.custom-theme .el-scrollbar__bar.is-vertical>div{width:100%}.custom-theme .el-scrollbar__bar.is-horizontal{height:6px;left:2px}.custom-theme .el-scrollbar__bar.is-horizontal>div{height:100%}.custom-theme .el-popper .popper__arrow,.custom-theme .el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.custom-theme .el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.custom-theme .el-popper .popper__arrow::after{content:" ";border-width:6px}.custom-theme .el-popper[x-placement^=top]{margin-bottom:12px}.custom-theme .el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#e6ebf5;border-bottom-width:0}.custom-theme .el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.custom-theme .el-popper[x-placement^=bottom]{margin-top:12px}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#e6ebf5}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.custom-theme .el-popper[x-placement^=right]{margin-left:12px}.custom-theme .el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#e6ebf5;border-left-width:0}.custom-theme .el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.custom-theme .el-popper[x-placement^=left]{margin-right:12px}.custom-theme .el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#e6ebf5}.custom-theme .el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.custom-theme .time-select{margin:5px 0;min-width:0}.custom-theme .time-select .el-picker-panel__content{max-height:200px;margin:0}.custom-theme .time-select-item{padding:8px 10px;font-size:14px;line-height:20px}.custom-theme .time-select-item.selected:not(.disabled){color:#262729;font-weight:700}.custom-theme .time-select-item.disabled{color:#dfe4ed;cursor:not-allowed}.custom-theme .time-select-item:hover{background-color:#f5f7fa;font-weight:700;cursor:pointer}.custom-theme .fade-in-linear-enter-active,.custom-theme .fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.custom-theme .fade-in-linear-enter,.custom-theme .fade-in-linear-leave,.custom-theme .fade-in-linear-leave-active{opacity:0}.custom-theme .el-fade-in-linear-enter-active,.custom-theme .el-fade-in-linear-leave-active{-webkit-transition:opacity .2s linear;transition:opacity .2s linear}.custom-theme .el-fade-in-linear-enter,.custom-theme .el-fade-in-linear-leave,.custom-theme .el-fade-in-linear-leave-active{opacity:0}.custom-theme .el-fade-in-enter-active,.custom-theme .el-fade-in-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.custom-theme .el-fade-in-enter,.custom-theme .el-fade-in-leave-active{opacity:0}.custom-theme .el-zoom-in-center-enter-active,.custom-theme .el-zoom-in-center-leave-active{-webkit-transition:all .3s cubic-bezier(.55,0,.1,1);transition:all .3s cubic-bezier(.55,0,.1,1)}.custom-theme .el-zoom-in-center-enter,.custom-theme .el-zoom-in-center-leave-active{opacity:0;-webkit-transform:scaleX(0);transform:scaleX(0)}.custom-theme .el-zoom-in-top-enter-active,.custom-theme .el-zoom-in-top-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;-webkit-transform-origin:center top;transform-origin:center top}.custom-theme .el-zoom-in-top-enter,.custom-theme .el-zoom-in-top-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.custom-theme .el-zoom-in-bottom-enter-active,.custom-theme .el-zoom-in-bottom-leave-active{opacity:1;-webkit-transform:scaleY(1);transform:scaleY(1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;-webkit-transform-origin:center bottom;transform-origin:center bottom}.custom-theme .el-zoom-in-bottom-enter,.custom-theme .el-zoom-in-bottom-leave-active{opacity:0;-webkit-transform:scaleY(0);transform:scaleY(0)}.custom-theme .el-zoom-in-left-enter-active,.custom-theme .el-zoom-in-left-leave-active{opacity:1;-webkit-transform:scale(1,1);transform:scale(1,1);-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;-webkit-transform-origin:top left;transform-origin:top left}.custom-theme .el-zoom-in-left-enter,.custom-theme .el-zoom-in-left-leave-active{opacity:0;-webkit-transform:scale(.45,.45);transform:scale(.45,.45)}.custom-theme .collapse-transition{-webkit-transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out;transition:.3s height ease-in-out,.3s padding-top ease-in-out,.3s padding-bottom ease-in-out}.custom-theme .horizontal-collapse-transition{-webkit-transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out;transition:.3s width ease-in-out,.3s padding-left ease-in-out,.3s padding-right ease-in-out}.custom-theme .el-list-enter-active,.custom-theme .el-list-leave-active{-webkit-transition:all 1s;transition:all 1s}.custom-theme .el-list-enter,.custom-theme .el-list-leave-active{opacity:0;-webkit-transform:translateY(-30px);transform:translateY(-30px)}.custom-theme .el-opacity-transition{-webkit-transition:opacity .3s cubic-bezier(.55,0,.1,1);transition:opacity .3s cubic-bezier(.55,0,.1,1)}.custom-theme .el-date-editor{position:relative;display:inline-block;text-align:left}.custom-theme .el-date-editor.el-input,.custom-theme .el-date-editor.el-input__inner{width:220px}.custom-theme .el-date-editor--daterange.el-input,.custom-theme .el-date-editor--daterange.el-input__inner,.custom-theme .el-date-editor--timerange.el-input,.custom-theme .el-date-editor--timerange.el-input__inner{width:350px}.custom-theme .el-date-editor--datetimerange.el-input,.custom-theme .el-date-editor--datetimerange.el-input__inner{width:400px}.custom-theme .el-date-editor .el-range__icon{font-size:14px;margin-left:-5px;color:#b4bccc;float:left;line-height:32px}.custom-theme .el-date-editor .el-range-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;border:none;outline:0;display:inline-block;height:100%;margin:0;padding:0;width:39%;text-align:center;font-size:14px;color:#5a5e66}.custom-theme .el-date-editor .el-range-input::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-date-editor .el-range-input:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-date-editor .el-range-input::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-date-editor .el-range-input::placeholder{color:#b4bccc}.custom-theme .el-date-editor .el-range-separator{display:inline-block;height:100%;padding:0 5px;margin:0;text-align:center;line-height:32px;font-size:14px;width:5%;color:#2d2f33}.custom-theme .el-date-editor .el-range__close-icon{font-size:14px;color:#b4bccc;width:25px;display:inline-block;float:right;line-height:32px}.custom-theme .el-range-editor.el-input__inner{padding:3px 10px}.custom-theme .el-range-editor.is-active{border-color:#262729}.custom-theme .el-range-editor.is-active:hover{border-color:#262729}.custom-theme .el-range-editor--medium.el-input__inner{height:36px}.custom-theme .el-range-editor--medium .el-range-separator{line-height:28px;font-size:14px}.custom-theme .el-range-editor--medium .el-range-input{font-size:14px}.custom-theme .el-range-editor--medium .el-range__close-icon,.custom-theme .el-range-editor--medium .el-range__icon{line-height:28px}.custom-theme .el-range-editor--small.el-input__inner{height:32px}.custom-theme .el-range-editor--small .el-range-separator{line-height:24px;font-size:13px}.custom-theme .el-range-editor--small .el-range-input{font-size:13px}.custom-theme .el-range-editor--small .el-range__close-icon,.custom-theme .el-range-editor--small .el-range__icon{line-height:24px}.custom-theme .el-range-editor--mini.el-input__inner{height:28px}.custom-theme .el-range-editor--mini .el-range-separator{line-height:20px;font-size:12px}.custom-theme .el-range-editor--mini .el-range-input{font-size:12px}.custom-theme .el-range-editor--mini .el-range__close-icon,.custom-theme .el-range-editor--mini .el-range__icon{line-height:20px}.custom-theme .el-range-editor.is-disabled{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-range-editor.is-disabled:focus,.custom-theme .el-range-editor.is-disabled:hover{border-color:#dfe4ed}.custom-theme .el-range-editor.is-disabled input{background-color:#f5f7fa;color:#b4bccc;cursor:not-allowed}.custom-theme .el-range-editor.is-disabled input::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-range-editor.is-disabled input:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-range-editor.is-disabled input::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-range-editor.is-disabled input::placeholder{color:#b4bccc}.custom-theme .el-range-editor.is-disabled .el-range-separator{color:#b4bccc}.custom-theme .el-time-spinner.has-seconds .el-time-spinner__wrapper{width:33.3%}.custom-theme .el-time-spinner.has-seconds .el-time-spinner__wrapper:nth-child(2){margin-left:1%}.custom-theme .el-time-spinner__wrapper{max-height:190px;overflow:auto;display:inline-block;width:50%;vertical-align:top;position:relative}.custom-theme .el-time-spinner__wrapper .el-scrollbar__wrap:not(.el-scrollbar__wrap--hidden-default){padding-bottom:15px}.custom-theme .el-time-spinner__wrapper.is-arrow{-webkit-box-sizing:border-box;box-sizing:border-box;text-align:center;overflow:hidden}.custom-theme .el-time-spinner__wrapper.is-arrow .el-time-spinner__list{-webkit-transform:translateY(-32px);transform:translateY(-32px)}.custom-theme .el-time-spinner__wrapper.is-arrow .el-time-spinner__item:hover:not(.disabled):not(.active){background:#fff;cursor:default}.custom-theme .el-time-spinner__arrow{font-size:12px;color:#878d99;position:absolute;left:0;width:100%;z-index:1;text-align:center;height:30px;line-height:30px;cursor:pointer}.custom-theme .el-time-spinner__arrow:hover{color:#262729}.custom-theme .el-time-spinner__arrow.el-icon-arrow-up{top:10px}.custom-theme .el-time-spinner__arrow.el-icon-arrow-down{bottom:10px}.custom-theme .el-time-spinner__input.el-input{width:70%}.custom-theme .el-time-spinner__input.el-input .el-input__inner{padding:0;text-align:center}.custom-theme .el-time-spinner__list{padding:0;margin:0;list-style:none;text-align:center}.custom-theme .el-time-spinner__list::after,.custom-theme .el-time-spinner__list::before{content:'';display:block;width:100%;height:80px}.custom-theme .el-time-spinner__item{height:32px;line-height:32px;font-size:12px;color:#5a5e66}.custom-theme .el-time-spinner__item:hover:not(.disabled):not(.active){background:#f5f7fa;cursor:pointer}.custom-theme .el-time-spinner__item.active:not(.disabled){color:#2d2f33;font-weight:700}.custom-theme .el-time-spinner__item.disabled{color:#b4bccc;cursor:not-allowed}.custom-theme .el-time-panel{margin:5px 0;border:solid 1px #dfe4ed;background-color:#fff;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);border-radius:2px;position:absolute;width:180px;left:0;z-index:1000;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.custom-theme .el-time-panel__content{font-size:0;position:relative;overflow:hidden}.custom-theme .el-time-panel__content::after,.custom-theme .el-time-panel__content::before{content:"";top:50%;position:absolute;margin-top:-15px;height:32px;z-index:-1;left:0;right:0;-webkit-box-sizing:border-box;box-sizing:border-box;padding-top:6px;text-align:left;border-top:1px solid #dfe4ed;border-bottom:1px solid #dfe4ed}.custom-theme .el-time-panel__content::after{left:50%;margin-left:12%;margin-right:12%}.custom-theme .el-time-panel__content::before{padding-left:50%;margin-right:12%;margin-left:12%}.custom-theme .el-time-panel__content.has-seconds::after{left:calc(100% / 3 * 2)}.custom-theme .el-time-panel__content.has-seconds::before{padding-left:calc(100% / 3)}.custom-theme .el-time-panel__footer{border-top:1px solid #e4e4e4;padding:4px;height:36px;line-height:25px;text-align:right;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-time-panel__btn{border:none;line-height:28px;padding:0 5px;margin:0 5px;cursor:pointer;background-color:transparent;outline:0;font-size:12px;color:#2d2f33}.custom-theme .el-time-panel__btn.confirm{font-weight:800;color:#262729}.custom-theme .el-time-panel .popper__arrow{-webkit-transform:translateX(-400%);transform:translateX(-400%)}.custom-theme .el-input{position:relative;font-size:14px;display:inline-block;width:100%}.custom-theme .el-input::-webkit-scrollbar{z-index:11;width:6px}.custom-theme .el-input::-webkit-scrollbar:horizontal{height:6px}.custom-theme .el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.custom-theme .el-input::-webkit-scrollbar-corner{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.custom-theme .el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #d8dce5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#5a5e66;display:inline-block;font-size:inherit;height:40px;line-height:1;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.custom-theme .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input__inner:hover{border-color:#b4bccc}.custom-theme .el-input__inner:focus{outline:0;border-color:#262729}.custom-theme .el-input__suffix{position:absolute;height:100%;right:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s;pointer-events:none}.custom-theme .el-input__suffix-inner{pointer-events:all}.custom-theme .el-input__prefix{position:absolute;height:100%;left:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s}.custom-theme .el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.custom-theme .el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.custom-theme .el-input__validateIcon{pointer-events:none}.custom-theme .el-input.is-active .el-input__inner{outline:0;border-color:#262729}.custom-theme .el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__icon{cursor:not-allowed}.custom-theme .el-input--suffix .el-input__inner{padding-right:30px}.custom-theme .el-input--prefix .el-input__inner{padding-left:30px}.custom-theme .el-input--medium{font-size:14px}.custom-theme .el-input--medium .el-input__inner{height:36px}.custom-theme .el-input--medium .el-input__icon{line-height:36px}.custom-theme .el-input--small{font-size:13px}.custom-theme .el-input--small .el-input__inner{height:32px}.custom-theme .el-input--small .el-input__icon{line-height:32px}.custom-theme .el-input--mini{font-size:12px}.custom-theme .el-input--mini .el-input__inner{height:28px}.custom-theme .el-input--mini .el-input__icon{line-height:28px}.custom-theme .el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.custom-theme .el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.custom-theme .el-input-group__append,.custom-theme .el-input-group__prepend{background-color:#f5f7fa;color:#0a76a4;vertical-align:middle;display:table-cell;position:relative;border:1px solid #d8dce5;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.custom-theme .el-input-group__append:focus,.custom-theme .el-input-group__prepend:focus{outline:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-select,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-select{display:inline-block;margin:-20px}.custom-theme .el-input-group__append button.el-button,.custom-theme .el-input-group__append div.el-select .el-input__inner,.custom-theme .el-input-group__append div.el-select:hover .el-input__inner,.custom-theme .el-input-group__prepend button.el-button,.custom-theme .el-input-group__prepend div.el-select .el-input__inner,.custom-theme .el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-input,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-input{font-size:inherit}.custom-theme .el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-input-group__append{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--prepend .el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--append .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-textarea{display:inline-block;width:100%;vertical-align:bottom}.custom-theme .el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:14px;color:#5a5e66;background-color:#fff;background-image:none;border:1px solid #d8dce5;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:hover{border-color:#b4bccc}.custom-theme .el-textarea__inner:focus{outline:0;border-color:#262729}.custom-theme .el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-scrollbar{overflow:hidden;position:relative}.custom-theme .el-scrollbar:active>.el-scrollbar__bar,.custom-theme .el-scrollbar:focus>.el-scrollbar__bar,.custom-theme .el-scrollbar:hover>.el-scrollbar__bar{opacity:1;-webkit-transition:opacity 340ms ease-out;transition:opacity 340ms ease-out}.custom-theme .el-scrollbar__wrap{overflow:scroll;height:100%}.custom-theme .el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.custom-theme .el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:rgba(135,141,153,.3);-webkit-transition:.3s background-color;transition:.3s background-color}.custom-theme .el-scrollbar__thumb:hover{background-color:rgba(135,141,153,.5)}.custom-theme .el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;-webkit-transition:opacity 120ms ease-out;transition:opacity 120ms ease-out}.custom-theme .el-scrollbar__bar.is-vertical{width:6px;top:2px}.custom-theme .el-scrollbar__bar.is-vertical>div{width:100%}.custom-theme .el-scrollbar__bar.is-horizontal{height:6px;left:2px}.custom-theme .el-scrollbar__bar.is-horizontal>div{height:100%}.custom-theme .el-popper .popper__arrow,.custom-theme .el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.custom-theme .el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.custom-theme .el-popper .popper__arrow::after{content:" ";border-width:6px}.custom-theme .el-popper[x-placement^=top]{margin-bottom:12px}.custom-theme .el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#e6ebf5;border-bottom-width:0}.custom-theme .el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.custom-theme .el-popper[x-placement^=bottom]{margin-top:12px}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#e6ebf5}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.custom-theme .el-popper[x-placement^=right]{margin-left:12px}.custom-theme .el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#e6ebf5;border-left-width:0}.custom-theme .el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.custom-theme .el-popper[x-placement^=left]{margin-right:12px}.custom-theme .el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#e6ebf5}.custom-theme .el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.custom-theme .el-popper .popper__arrow,.custom-theme .el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.custom-theme .el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.custom-theme .el-popper .popper__arrow::after{content:" ";border-width:6px}.custom-theme .el-popper[x-placement^=top]{margin-bottom:12px}.custom-theme .el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#e6ebf5;border-bottom-width:0}.custom-theme .el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.custom-theme .el-popper[x-placement^=bottom]{margin-top:12px}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#e6ebf5}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.custom-theme .el-popper[x-placement^=right]{margin-left:12px}.custom-theme .el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#e6ebf5;border-left-width:0}.custom-theme .el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.custom-theme .el-popper[x-placement^=left]{margin-right:12px}.custom-theme .el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#e6ebf5}.custom-theme .el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.custom-theme .el-popover{position:absolute;background:#fff;min-width:150px;border-radius:4px;border:1px solid #e6ebf5;padding:12px;z-index:2000;color:#5a5e66;line-height:1.4;text-align:justify;word-break:break-all;font-size:14px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.custom-theme .el-popover--plain{padding:18px 20px}.custom-theme .el-popover__title{color:#2d2f33;font-size:16px;line-height:1;margin-bottom:12px}.custom-theme .el-tooltip__popper{position:absolute;border-radius:4px;padding:10px;z-index:2000;font-size:12px;line-height:1.2}.custom-theme .el-tooltip__popper .popper__arrow,.custom-theme .el-tooltip__popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.custom-theme .el-tooltip__popper .popper__arrow{border-width:6px}.custom-theme .el-tooltip__popper .popper__arrow::after{content:" ";border-width:5px}.custom-theme .el-tooltip__popper[x-placement^=top]{margin-bottom:12px}.custom-theme .el-tooltip__popper[x-placement^=top] .popper__arrow{bottom:-6px;border-top-color:#2d2f33;border-bottom-width:0}.custom-theme .el-tooltip__popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-5px;border-top-color:#2d2f33;border-bottom-width:0}.custom-theme .el-tooltip__popper[x-placement^=bottom]{margin-top:12px}.custom-theme .el-tooltip__popper[x-placement^=bottom] .popper__arrow{top:-6px;border-top-width:0;border-bottom-color:#2d2f33}.custom-theme .el-tooltip__popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-5px;border-top-width:0;border-bottom-color:#2d2f33}.custom-theme .el-tooltip__popper[x-placement^=right]{margin-left:12px}.custom-theme .el-tooltip__popper[x-placement^=right] .popper__arrow{left:-6px;border-right-color:#2d2f33;border-left-width:0}.custom-theme .el-tooltip__popper[x-placement^=right] .popper__arrow::after{bottom:-5px;left:1px;border-right-color:#2d2f33;border-left-width:0}.custom-theme .el-tooltip__popper[x-placement^=left]{margin-right:12px}.custom-theme .el-tooltip__popper[x-placement^=left] .popper__arrow{right:-6px;border-right-width:0;border-left-color:#2d2f33}.custom-theme .el-tooltip__popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-5px;margin-left:-5px;border-right-width:0;border-left-color:#2d2f33}.custom-theme .el-tooltip__popper.is-dark{background:#2d2f33;color:#fff}.custom-theme .el-tooltip__popper.is-light{background:#fff;border:1px solid #2d2f33}.custom-theme .el-tooltip__popper.is-light[x-placement^=top] .popper__arrow{border-top-color:#2d2f33}.custom-theme .el-tooltip__popper.is-light[x-placement^=top] .popper__arrow::after{border-top-color:#fff}.custom-theme .el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow{border-bottom-color:#2d2f33}.custom-theme .el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow::after{border-bottom-color:#fff}.custom-theme .el-tooltip__popper.is-light[x-placement^=left] .popper__arrow{border-left-color:#2d2f33}.custom-theme .el-tooltip__popper.is-light[x-placement^=left] .popper__arrow::after{border-left-color:#fff}.custom-theme .el-tooltip__popper.is-light[x-placement^=right] .popper__arrow{border-right-color:#2d2f33}.custom-theme .el-tooltip__popper.is-light[x-placement^=right] .popper__arrow::after{border-right-color:#fff}.custom-theme .v-modal-enter{-webkit-animation:v-modal-in .2s ease;animation:v-modal-in .2s ease}.custom-theme .v-modal-leave{-webkit-animation:v-modal-out .2s ease forwards;animation:v-modal-out .2s ease forwards}@keyframes v-modal-in{0%{opacity:0}}@keyframes v-modal-out{100%{opacity:0}}.custom-theme .v-modal{position:fixed;left:0;top:0;width:100%;height:100%;opacity:.5;background:#000}.custom-theme .el-button{display:inline-block;line-height:1;white-space:nowrap;cursor:pointer;background:#fff;border:1px solid #d8dce5;border-color:#d8dce5;color:#5a5e66;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;-webkit-transition:.1s;transition:.1s;font-weight:500;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;padding:12px 20px;font-size:14px;border-radius:4px}.custom-theme .el-button+.el-button{margin-left:10px}.custom-theme .el-button.is-round{padding:12px 20px}.custom-theme .el-button:focus,.custom-theme .el-button:hover{color:#262729;border-color:#bebebf;background-color:#e9e9ea}.custom-theme .el-button:active{color:#222325;border-color:#222325;outline:0}.custom-theme .el-button::-moz-focus-inner{border:0}.custom-theme .el-button [class*=el-icon-]+span{margin-left:5px}.custom-theme .el-button.is-plain:focus,.custom-theme .el-button.is-plain:hover{background:#fff;border-color:#262729;color:#262729}.custom-theme .el-button.is-plain:active{background:#fff;border-color:#222325;color:#222325;outline:0}.custom-theme .el-button.is-active{color:#222325;border-color:#222325}.custom-theme .el-button.is-disabled,.custom-theme .el-button.is-disabled:focus,.custom-theme .el-button.is-disabled:hover{color:#b4bccc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#e6ebf5}.custom-theme .el-button.is-disabled.el-button--text{background-color:transparent}.custom-theme .el-button.is-disabled.is-plain,.custom-theme .el-button.is-disabled.is-plain:focus,.custom-theme .el-button.is-disabled.is-plain:hover{background-color:#fff;border-color:#e6ebf5;color:#b4bccc}.custom-theme .el-button.is-loading{position:relative;pointer-events:none}.custom-theme .el-button.is-loading:before{pointer-events:none;content:'';position:absolute;left:-1px;top:-1px;right:-1px;bottom:-1px;border-radius:inherit;background-color:rgba(255,255,255,.35)}.custom-theme .el-button.is-round{border-radius:20px;padding:12px 23px}.custom-theme .el-button--primary{color:#fff;background-color:#262729;border-color:#262729}.custom-theme .el-button--primary:focus,.custom-theme .el-button--primary:hover{background:#515254;border-color:#515254;color:#fff}.custom-theme .el-button--primary:active{background:#222325;border-color:#222325;color:#fff;outline:0}.custom-theme .el-button--primary.is-active{background:#222325;border-color:#222325;color:#fff}.custom-theme .el-button--primary.is-disabled,.custom-theme .el-button--primary.is-disabled:active,.custom-theme .el-button--primary.is-disabled:focus,.custom-theme .el-button--primary.is-disabled:hover{color:#fff;background-color:#939394;border-color:#939394}.custom-theme .el-button--primary.is-plain{color:#262729;background:#e9e9ea;border-color:#a8a9a9}.custom-theme .el-button--primary.is-plain:focus,.custom-theme .el-button--primary.is-plain:hover{background:#262729;border-color:#262729;color:#fff}.custom-theme .el-button--primary.is-plain:active{background:#222325;border-color:#222325;color:#fff;outline:0}.custom-theme .el-button--primary.is-plain.is-disabled,.custom-theme .el-button--primary.is-plain.is-disabled:active,.custom-theme .el-button--primary.is-plain.is-disabled:focus,.custom-theme .el-button--primary.is-plain.is-disabled:hover{color:#7d7d7f;background-color:#e9e9ea;border-color:#d4d4d4}.custom-theme .el-button--success{color:#fff;background-color:#409167;border-color:#409167}.custom-theme .el-button--success:focus,.custom-theme .el-button--success:hover{background:#66a785;border-color:#66a785;color:#fff}.custom-theme .el-button--success:active{background:#3a835d;border-color:#3a835d;color:#fff;outline:0}.custom-theme .el-button--success.is-active{background:#3a835d;border-color:#3a835d;color:#fff}.custom-theme .el-button--success.is-disabled,.custom-theme .el-button--success.is-disabled:active,.custom-theme .el-button--success.is-disabled:focus,.custom-theme .el-button--success.is-disabled:hover{color:#fff;background-color:#a0c8b3;border-color:#a0c8b3}.custom-theme .el-button--success.is-plain{color:#409167;background:#ecf4f0;border-color:#b3d3c2}.custom-theme .el-button--success.is-plain:focus,.custom-theme .el-button--success.is-plain:hover{background:#409167;border-color:#409167;color:#fff}.custom-theme .el-button--success.is-plain:active{background:#3a835d;border-color:#3a835d;color:#fff;outline:0}.custom-theme .el-button--success.is-plain.is-disabled,.custom-theme .el-button--success.is-plain.is-disabled:active,.custom-theme .el-button--success.is-plain.is-disabled:focus,.custom-theme .el-button--success.is-plain.is-disabled:hover{color:#8cbda4;background-color:#ecf4f0;border-color:#d9e9e1}.custom-theme .el-button--warning{color:#fff;background-color:#9da408;border-color:#9da408}.custom-theme .el-button--warning:focus,.custom-theme .el-button--warning:hover{background:#b1b639;border-color:#b1b639;color:#fff}.custom-theme .el-button--warning:active{background:#8d9407;border-color:#8d9407;color:#fff;outline:0}.custom-theme .el-button--warning.is-active{background:#8d9407;border-color:#8d9407;color:#fff}.custom-theme .el-button--warning.is-disabled,.custom-theme .el-button--warning.is-disabled:active,.custom-theme .el-button--warning.is-disabled:focus,.custom-theme .el-button--warning.is-disabled:hover{color:#fff;background-color:#ced284;border-color:#ced284}.custom-theme .el-button--warning.is-plain{color:#9da408;background:#f5f6e6;border-color:#d8db9c}.custom-theme .el-button--warning.is-plain:focus,.custom-theme .el-button--warning.is-plain:hover{background:#9da408;border-color:#9da408;color:#fff}.custom-theme .el-button--warning.is-plain:active{background:#8d9407;border-color:#8d9407;color:#fff;outline:0}.custom-theme .el-button--warning.is-plain.is-disabled,.custom-theme .el-button--warning.is-plain.is-disabled:active,.custom-theme .el-button--warning.is-plain.is-disabled:focus,.custom-theme .el-button--warning.is-plain.is-disabled:hover{color:#c4c86b;background-color:#f5f6e6;border-color:#ebedce}.custom-theme .el-button--danger{color:#fff;background-color:#b3450e;border-color:#b3450e}.custom-theme .el-button--danger:focus,.custom-theme .el-button--danger:hover{background:#c26a3e;border-color:#c26a3e;color:#fff}.custom-theme .el-button--danger:active{background:#a13e0d;border-color:#a13e0d;color:#fff;outline:0}.custom-theme .el-button--danger.is-active{background:#a13e0d;border-color:#a13e0d;color:#fff}.custom-theme .el-button--danger.is-disabled,.custom-theme .el-button--danger.is-disabled:active,.custom-theme .el-button--danger.is-disabled:focus,.custom-theme .el-button--danger.is-disabled:hover{color:#fff;background-color:#d9a287;border-color:#d9a287}.custom-theme .el-button--danger.is-plain{color:#b3450e;background:#f7ece7;border-color:#e1b59f}.custom-theme .el-button--danger.is-plain:focus,.custom-theme .el-button--danger.is-plain:hover{background:#b3450e;border-color:#b3450e;color:#fff}.custom-theme .el-button--danger.is-plain:active{background:#a13e0d;border-color:#a13e0d;color:#fff;outline:0}.custom-theme .el-button--danger.is-plain.is-disabled,.custom-theme .el-button--danger.is-plain.is-disabled:active,.custom-theme .el-button--danger.is-plain.is-disabled:focus,.custom-theme .el-button--danger.is-plain.is-disabled:hover{color:#d18f6e;background-color:#f7ece7;border-color:#f0dacf}.custom-theme .el-button--info{color:#fff;background-color:#0a76a4;border-color:#0a76a4}.custom-theme .el-button--info:focus,.custom-theme .el-button--info:hover{background:#3b91b6;border-color:#3b91b6;color:#fff}.custom-theme .el-button--info:active{background:#096a94;border-color:#096a94;color:#fff;outline:0}.custom-theme .el-button--info.is-active{background:#096a94;border-color:#096a94;color:#fff}.custom-theme .el-button--info.is-disabled,.custom-theme .el-button--info.is-disabled:active,.custom-theme .el-button--info.is-disabled:focus,.custom-theme .el-button--info.is-disabled:hover{color:#fff;background-color:#85bbd2;border-color:#85bbd2}.custom-theme .el-button--info.is-plain{color:#0a76a4;background:#e7f1f6;border-color:#9dc8db}.custom-theme .el-button--info.is-plain:focus,.custom-theme .el-button--info.is-plain:hover{background:#0a76a4;border-color:#0a76a4;color:#fff}.custom-theme .el-button--info.is-plain:active{background:#096a94;border-color:#096a94;color:#fff;outline:0}.custom-theme .el-button--info.is-plain.is-disabled,.custom-theme .el-button--info.is-plain.is-disabled:active,.custom-theme .el-button--info.is-plain.is-disabled:focus,.custom-theme .el-button--info.is-plain.is-disabled:hover{color:#6cadc8;background-color:#e7f1f6;border-color:#cee4ed}.custom-theme .el-button--medium{padding:10px 20px;font-size:14px;border-radius:4px}.custom-theme .el-button--medium.is-round{padding:10px 20px}.custom-theme .el-button--small{padding:9px 15px;font-size:12px;border-radius:3px}.custom-theme .el-button--small.is-round{padding:9px 15px}.custom-theme .el-button--mini{padding:7px 15px;font-size:12px;border-radius:3px}.custom-theme .el-button--mini.is-round{padding:7px 15px}.custom-theme .el-button--text{border:none;color:#262729;background:0 0;padding-left:0;padding-right:0}.custom-theme .el-button--text:focus,.custom-theme .el-button--text:hover{color:#515254;border-color:transparent;background-color:transparent}.custom-theme .el-button--text:active{color:#222325;border-color:transparent;background-color:transparent}.custom-theme .el-button-group{display:inline-block;vertical-align:middle}.custom-theme .el-button-group::after,.custom-theme .el-button-group::before{display:table;content:""}.custom-theme .el-button-group::after{clear:both}.custom-theme .el-button-group .el-button{float:left;position:relative}.custom-theme .el-button-group .el-button+.el-button{margin-left:0}.custom-theme .el-button-group .el-button:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-button-group .el-button:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-button-group .el-button:not(:first-child):not(:last-child){border-radius:0}.custom-theme .el-button-group .el-button:not(:last-child){margin-right:-1px}.custom-theme .el-button-group .el-button:active,.custom-theme .el-button-group .el-button:focus,.custom-theme .el-button-group .el-button:hover{z-index:1}.custom-theme .el-button-group .el-button.is-active{z-index:1}.custom-theme .el-button-group .el-button--primary:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--primary:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--primary:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--success:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--success:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--success:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--warning:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--warning:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--warning:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--danger:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--danger:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--danger:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--info:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--info:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--info:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-input{position:relative;font-size:14px;display:inline-block;width:100%}.custom-theme .el-input::-webkit-scrollbar{z-index:11;width:6px}.custom-theme .el-input::-webkit-scrollbar:horizontal{height:6px}.custom-theme .el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.custom-theme .el-input::-webkit-scrollbar-corner{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.custom-theme .el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #d8dce5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#5a5e66;display:inline-block;font-size:inherit;height:40px;line-height:1;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.custom-theme .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input__inner:hover{border-color:#b4bccc}.custom-theme .el-input__inner:focus{outline:0;border-color:#262729}.custom-theme .el-input__suffix{position:absolute;height:100%;right:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s;pointer-events:none}.custom-theme .el-input__suffix-inner{pointer-events:all}.custom-theme .el-input__prefix{position:absolute;height:100%;left:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s}.custom-theme .el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.custom-theme .el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.custom-theme .el-input__validateIcon{pointer-events:none}.custom-theme .el-input.is-active .el-input__inner{outline:0;border-color:#262729}.custom-theme .el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__icon{cursor:not-allowed}.custom-theme .el-input--suffix .el-input__inner{padding-right:30px}.custom-theme .el-input--prefix .el-input__inner{padding-left:30px}.custom-theme .el-input--medium{font-size:14px}.custom-theme .el-input--medium .el-input__inner{height:36px}.custom-theme .el-input--medium .el-input__icon{line-height:36px}.custom-theme .el-input--small{font-size:13px}.custom-theme .el-input--small .el-input__inner{height:32px}.custom-theme .el-input--small .el-input__icon{line-height:32px}.custom-theme .el-input--mini{font-size:12px}.custom-theme .el-input--mini .el-input__inner{height:28px}.custom-theme .el-input--mini .el-input__icon{line-height:28px}.custom-theme .el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.custom-theme .el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.custom-theme .el-input-group__append,.custom-theme .el-input-group__prepend{background-color:#f5f7fa;color:#0a76a4;vertical-align:middle;display:table-cell;position:relative;border:1px solid #d8dce5;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.custom-theme .el-input-group__append:focus,.custom-theme .el-input-group__prepend:focus{outline:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-select,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-select{display:inline-block;margin:-20px}.custom-theme .el-input-group__append button.el-button,.custom-theme .el-input-group__append div.el-select .el-input__inner,.custom-theme .el-input-group__append div.el-select:hover .el-input__inner,.custom-theme .el-input-group__prepend button.el-button,.custom-theme .el-input-group__prepend div.el-select .el-input__inner,.custom-theme .el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-input,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-input{font-size:inherit}.custom-theme .el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-input-group__append{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--prepend .el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--append .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-textarea{display:inline-block;width:100%;vertical-align:bottom}.custom-theme .el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:14px;color:#5a5e66;background-color:#fff;background-image:none;border:1px solid #d8dce5;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:hover{border-color:#b4bccc}.custom-theme .el-textarea__inner:focus{outline:0;border-color:#262729}.custom-theme .el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-message-box{display:inline-block;width:420px;padding-bottom:10px;vertical-align:middle;background-color:#fff;border-radius:4px;border:1px solid #e6ebf5;font-size:18px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);text-align:left;overflow:hidden;-webkit-backface-visibility:hidden;backface-visibility:hidden}.custom-theme .el-message-box__wrapper{position:fixed;top:0;bottom:0;left:0;right:0;text-align:center}.custom-theme .el-message-box__wrapper::after{content:"";display:inline-block;height:100%;width:0;vertical-align:middle}.custom-theme .el-message-box__header{position:relative;padding:15px;padding-bottom:10px}.custom-theme .el-message-box__title{padding-left:0;margin-bottom:0;font-size:18px;line-height:1;color:#2d2f33}.custom-theme .el-message-box__headerbtn{position:absolute;top:15px;right:15px;padding:0;border:none;outline:0;background:0 0;font-size:16px;cursor:pointer}.custom-theme .el-message-box__headerbtn .el-message-box__close{color:#0a76a4}.custom-theme .el-message-box__headerbtn:focus .el-message-box__close,.custom-theme .el-message-box__headerbtn:hover .el-message-box__close{color:#262729}.custom-theme .el-message-box__content{position:relative;padding:10px 15px;color:#5a5e66;font-size:14px}.custom-theme .el-message-box__input{padding-top:15px}.custom-theme .el-message-box__input input.invalid{border-color:#b3450e}.custom-theme .el-message-box__input input.invalid:focus{border-color:#b3450e}.custom-theme .el-message-box__status{position:absolute;top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%);font-size:24px!important}.custom-theme .el-message-box__status::before{padding-left:1px}.custom-theme .el-message-box__status+.el-message-box__message{padding-left:36px;padding-right:12px}.custom-theme .el-message-box__status.el-icon-success{color:#409167}.custom-theme .el-message-box__status.el-icon-info{color:#0a76a4}.custom-theme .el-message-box__status.el-icon-warning{color:#9da408}.custom-theme .el-message-box__status.el-icon-error{color:#b3450e}.custom-theme .el-message-box__message{margin:0}.custom-theme .el-message-box__message p{margin:0;line-height:24px}.custom-theme .el-message-box__errormsg{color:#b3450e;font-size:12px;min-height:18px;margin-top:2px}.custom-theme .el-message-box__btns{padding:5px 15px 0;text-align:right}.custom-theme .el-message-box__btns button:nth-child(2){margin-left:10px}.custom-theme .el-message-box__btns-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.custom-theme .el-message-box--center{padding-bottom:30px}.custom-theme .el-message-box--center .el-message-box__header{padding-top:30px}.custom-theme .el-message-box--center .el-message-box__title{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.custom-theme .el-message-box--center .el-message-box__status{position:relative;top:auto;padding-right:5px;text-align:center;-webkit-transform:translateY(-1px);transform:translateY(-1px)}.custom-theme .el-message-box--center .el-message-box__message{margin-left:0}.custom-theme .el-message-box--center .el-message-box__btns,.custom-theme .el-message-box--center .el-message-box__content{text-align:center}.custom-theme .el-message-box--center .el-message-box__content{padding-left:27px;padding-right:27px}.custom-theme .msgbox-fade-enter-active{-webkit-animation:msgbox-fade-in .3s;animation:msgbox-fade-in .3s}.custom-theme .msgbox-fade-leave-active{-webkit-animation:msgbox-fade-out .3s;animation:msgbox-fade-out .3s}@-webkit-keyframes msgbox-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@keyframes msgbox-fade-in{0%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}100%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}}@-webkit-keyframes msgbox-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}@keyframes msgbox-fade-out{0%{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);opacity:1}100%{-webkit-transform:translate3d(0,-20px,0);transform:translate3d(0,-20px,0);opacity:0}}.custom-theme .el-breadcrumb{font-size:14px;line-height:1}.custom-theme .el-breadcrumb::after,.custom-theme .el-breadcrumb::before{display:table;content:""}.custom-theme .el-breadcrumb::after{clear:both}.custom-theme .el-breadcrumb__separator{margin:0 9px;font-weight:700;color:#b4bccc}.custom-theme .el-breadcrumb__separator[class*=icon]{margin:0 6px;font-weight:400}.custom-theme .el-breadcrumb__item{float:left}.custom-theme .el-breadcrumb__inner,.custom-theme .el-breadcrumb__inner a{font-weight:700;-webkit-transition:color .2s cubic-bezier(.645,.045,.355,1);transition:color .2s cubic-bezier(.645,.045,.355,1);color:#2d2f33}.custom-theme .el-breadcrumb__inner a:hover,.custom-theme .el-breadcrumb__inner:hover{color:#262729;cursor:pointer}.custom-theme .el-breadcrumb__item:last-child .el-breadcrumb__inner,.custom-theme .el-breadcrumb__item:last-child .el-breadcrumb__inner a,.custom-theme .el-breadcrumb__item:last-child .el-breadcrumb__inner a:hover,.custom-theme .el-breadcrumb__item:last-child .el-breadcrumb__inner:hover{font-weight:400;color:#5a5e66;cursor:text}.custom-theme .el-breadcrumb__item:last-child .el-breadcrumb__separator{display:none}.custom-theme .el-form--label-left .el-form-item__label{text-align:left}.custom-theme .el-form--label-top .el-form-item__label{float:none;display:inline-block;text-align:left;padding:0 0 10px 0}.custom-theme .el-form--inline .el-form-item{display:inline-block;margin-right:10px;vertical-align:top}.custom-theme .el-form--inline .el-form-item__label{float:none;display:inline-block}.custom-theme .el-form--inline .el-form-item__content{display:inline-block;vertical-align:top}.custom-theme .el-form--inline.el-form--label-top .el-form-item__content{display:block}.custom-theme .el-form-item{margin-bottom:22px}.custom-theme .el-form-item::after,.custom-theme .el-form-item::before{display:table;content:""}.custom-theme .el-form-item::after{clear:both}.custom-theme .el-form-item .el-form-item{margin-bottom:0}.custom-theme .el-form-item .el-input__validateIcon{display:none}.custom-theme .el-form-item--medium .el-form-item__label{line-height:36px}.custom-theme .el-form-item--medium .el-form-item__content{line-height:36px}.custom-theme .el-form-item--small .el-form-item__label{line-height:32px}.custom-theme .el-form-item--small .el-form-item__content{line-height:32px}.custom-theme .el-form-item--small.el-form-item{margin-bottom:18px}.custom-theme .el-form-item--small .el-form-item__error{padding-top:2px}.custom-theme .el-form-item--mini .el-form-item__label{line-height:28px}.custom-theme .el-form-item--mini .el-form-item__content{line-height:28px}.custom-theme .el-form-item--mini.el-form-item{margin-bottom:18px}.custom-theme .el-form-item--mini .el-form-item__error{padding-top:1px}.custom-theme .el-form-item__label{text-align:right;vertical-align:middle;float:left;font-size:14px;color:#5a5e66;line-height:40px;padding:0 12px 0 0;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-form-item__content{line-height:40px;position:relative;font-size:14px}.custom-theme .el-form-item__content::after,.custom-theme .el-form-item__content::before{display:table;content:""}.custom-theme .el-form-item__content::after{clear:both}.custom-theme .el-form-item__error{color:#b3450e;font-size:12px;line-height:1;padding-top:4px;position:absolute;top:100%;left:0}.custom-theme .el-form-item__error--inline{position:relative;top:auto;left:auto;display:inline-block;margin-left:10px}.custom-theme .el-form-item.is-required .el-form-item__label:before{content:'*';color:#b3450e;margin-right:4px}.custom-theme .el-form-item.is-error .el-input__inner,.custom-theme .el-form-item.is-error .el-input__inner:focus,.custom-theme .el-form-item.is-error .el-textarea__inner,.custom-theme .el-form-item.is-error .el-textarea__inner:focus{border-color:#b3450e}.custom-theme .el-form-item.is-error .el-input-group__append .el-input__inner,.custom-theme .el-form-item.is-error .el-input-group__prepend .el-input__inner{border-color:transparent}.custom-theme .el-form-item.is-error .el-input__validateIcon{color:#b3450e}.custom-theme .el-form-item.is-success .el-input__inner,.custom-theme .el-form-item.is-success .el-input__inner:focus,.custom-theme .el-form-item.is-success .el-textarea__inner,.custom-theme .el-form-item.is-success .el-textarea__inner:focus{border-color:#409167}.custom-theme .el-form-item.is-success .el-input-group__append .el-input__inner,.custom-theme .el-form-item.is-success .el-input-group__prepend .el-input__inner{border-color:transparent}.custom-theme .el-form-item.is-success .el-input__validateIcon{color:#409167}.custom-theme .el-form-item--feedback .el-input__validateIcon{display:inline-block}.custom-theme .el-tabs__header{padding:0;position:relative;margin:0 0 15px}.custom-theme .el-tabs__active-bar{position:absolute;bottom:0;left:0;height:2px;background-color:#262729;z-index:1;-webkit-transition:-webkit-transform .3s cubic-bezier(.645,.045,.355,1);transition:-webkit-transform .3s cubic-bezier(.645,.045,.355,1);transition:transform .3s cubic-bezier(.645,.045,.355,1);transition:transform .3s cubic-bezier(.645,.045,.355,1),-webkit-transform .3s cubic-bezier(.645,.045,.355,1);list-style:none}.custom-theme .el-tabs__new-tab{float:right;border:1px solid #d3dce6;height:18px;width:18px;line-height:18px;margin:12px 0 9px 10px;border-radius:3px;text-align:center;font-size:12px;color:#d3dce6;cursor:pointer;-webkit-transition:all .15s;transition:all .15s}.custom-theme .el-tabs__new-tab .el-icon-plus{-webkit-transform:scale(.8,.8);transform:scale(.8,.8)}.custom-theme .el-tabs__new-tab:hover{color:#262729}.custom-theme .el-tabs__nav-wrap{overflow:hidden;margin-bottom:-1px;position:relative}.custom-theme .el-tabs__nav-wrap::after{content:"";position:absolute;left:0;bottom:0;width:100%;height:2px;background-color:#dfe4ed;z-index:1}.custom-theme .el-tabs__nav-wrap.is-scrollable{padding:0 20px;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-tabs__nav-scroll{overflow:hidden}.custom-theme .el-tabs__nav-next,.custom-theme .el-tabs__nav-prev{position:absolute;cursor:pointer;line-height:44px;font-size:12px;color:#878d99}.custom-theme .el-tabs__nav-next{right:0}.custom-theme .el-tabs__nav-prev{left:0}.custom-theme .el-tabs__nav{white-space:nowrap;position:relative;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;float:left;z-index:2}.custom-theme .el-tabs__item{padding:0 20px;height:40px;-webkit-box-sizing:border-box;box-sizing:border-box;line-height:40px;display:inline-block;list-style:none;font-size:14px;font-weight:500;color:#2d2f33;position:relative}.custom-theme .el-tabs__item:focus,.custom-theme .el-tabs__item:focus:active{outline:0}.custom-theme .el-tabs__item .el-icon-close{border-radius:50%;text-align:center;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);margin-left:5px}.custom-theme .el-tabs__item .el-icon-close:before{-webkit-transform:scale(.9);transform:scale(.9);display:inline-block}.custom-theme .el-tabs__item .el-icon-close:hover{background-color:#b4bccc;color:#fff}.custom-theme .el-tabs__item.is-active{color:#262729}.custom-theme .el-tabs__item:hover{color:#262729;cursor:pointer}.custom-theme .el-tabs__item.is-disabled{color:#b4bccc;cursor:default}.custom-theme .el-tabs__content{overflow:hidden;position:relative}.custom-theme .el-tabs--card>.el-tabs__header{border-bottom:1px solid #dfe4ed}.custom-theme .el-tabs--card>.el-tabs__header .el-tabs__nav-wrap::after{content:none}.custom-theme .el-tabs--card>.el-tabs__header .el-tabs__nav{border:1px solid #dfe4ed;border-bottom:none;border-radius:4px 4px 0 0}.custom-theme .el-tabs--card>.el-tabs__header .el-tabs__active-bar{display:none}.custom-theme .el-tabs--card>.el-tabs__header .el-tabs__item .el-icon-close{position:relative;font-size:12px;width:0;height:14px;vertical-align:middle;line-height:15px;overflow:hidden;top:-1px;right:-2px;-webkit-transform-origin:100% 50%;transform-origin:100% 50%}.custom-theme .el-tabs--card>.el-tabs__header .el-tabs__item{border-bottom:1px solid transparent;border-left:1px solid #dfe4ed;-webkit-transition:color .3s cubic-bezier(.645,.045,.355,1),padding .3s cubic-bezier(.645,.045,.355,1);transition:color .3s cubic-bezier(.645,.045,.355,1),padding .3s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-tabs--card>.el-tabs__header .el-tabs__item:first-child{border-left:none}.custom-theme .el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover{padding-left:13px;padding-right:13px}.custom-theme .el-tabs--card>.el-tabs__header .el-tabs__item.is-closable:hover .el-icon-close{width:14px}.custom-theme .el-tabs--card>.el-tabs__header .el-tabs__item.is-active{border-bottom-color:#fff}.custom-theme .el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable{padding-left:20px;padding-right:20px}.custom-theme .el-tabs--card>.el-tabs__header .el-tabs__item.is-active.is-closable .el-icon-close{width:14px}.custom-theme .el-tabs--border-card{background:#fff;border:1px solid #d8dce5;-webkit-box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04);box-shadow:0 2px 4px 0 rgba(0,0,0,.12),0 0 6px 0 rgba(0,0,0,.04)}.custom-theme .el-tabs--border-card>.el-tabs__content{padding:15px}.custom-theme .el-tabs--border-card>.el-tabs__header{background-color:#f5f7fa;border-bottom:1px solid #dfe4ed;margin:0}.custom-theme .el-tabs--border-card>.el-tabs__header .el-tabs__nav-wrap::after{content:none}.custom-theme .el-tabs--border-card>.el-tabs__header .el-tabs__item{-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);border:1px solid transparent;margin:-1px -1px 0;color:#878d99}.custom-theme .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active{color:#262729;background-color:#fff;border-right-color:#d8dce5;border-left-color:#d8dce5}.custom-theme .el-tabs--border-card>.el-tabs__header .el-tabs__item:hover{color:#262729}.custom-theme .el-tabs--bottom:not(.el-tabs--border-card):not(.el-tabs--card) .el-tabs__item:nth-child(2),.custom-theme .el-tabs--top:not(.el-tabs--border-card):not(.el-tabs--card) .el-tabs__item:nth-child(2){padding-left:0}.custom-theme .el-tabs--bottom .el-tabs__header{margin-bottom:0;margin-top:10px}.custom-theme .el-tabs--bottom.el-tabs--border-card .el-tabs__header{border-bottom:0;border-top:1px solid #d8dce5}.custom-theme .el-tabs--bottom.el-tabs--border-card .el-tabs__nav-wrap{margin-top:-1px;margin-bottom:0}.custom-theme .el-tabs--bottom.el-tabs--border-card .el-tabs__item{border:1px solid transparent;margin:0 -1px -1px -1px}.custom-theme .el-tabs--left,.custom-theme .el-tabs--right{overflow:hidden}.custom-theme .el-tabs--left .el-tabs__header,.custom-theme .el-tabs--left .el-tabs__nav-scroll,.custom-theme .el-tabs--left .el-tabs__nav-wrap,.custom-theme .el-tabs--right .el-tabs__header,.custom-theme .el-tabs--right .el-tabs__nav-scroll,.custom-theme .el-tabs--right .el-tabs__nav-wrap{height:100%}.custom-theme .el-tabs--left .el-tabs__active-bar,.custom-theme .el-tabs--right .el-tabs__active-bar{top:0;bottom:auto;width:2px;height:auto}.custom-theme .el-tabs--left .el-tabs__nav-wrap,.custom-theme .el-tabs--right .el-tabs__nav-wrap{margin-bottom:0}.custom-theme .el-tabs--left .el-tabs__nav-wrap.is-scrollable,.custom-theme .el-tabs--right .el-tabs__nav-wrap.is-scrollable{padding:30px 0}.custom-theme .el-tabs--left .el-tabs__nav-wrap::after,.custom-theme .el-tabs--right .el-tabs__nav-wrap::after{height:100%;width:2px;bottom:auto;top:0}.custom-theme .el-tabs--left .el-tabs__nav,.custom-theme .el-tabs--right .el-tabs__nav{float:none}.custom-theme .el-tabs--left .el-tabs__item,.custom-theme .el-tabs--right .el-tabs__item{display:block}.custom-theme .el-tabs--left .el-tabs__nav-next,.custom-theme .el-tabs--left .el-tabs__nav-prev,.custom-theme .el-tabs--right .el-tabs__nav-next,.custom-theme .el-tabs--right .el-tabs__nav-prev{height:30px;line-height:30px;width:100%;text-align:center;cursor:pointer}.custom-theme .el-tabs--left .el-tabs__nav-next i,.custom-theme .el-tabs--left .el-tabs__nav-prev i,.custom-theme .el-tabs--right .el-tabs__nav-next i,.custom-theme .el-tabs--right .el-tabs__nav-prev i{-webkit-transform:rotateZ(90deg);transform:rotateZ(90deg)}.custom-theme .el-tabs--left .el-tabs__nav-prev,.custom-theme .el-tabs--right .el-tabs__nav-prev{left:auto;top:0}.custom-theme .el-tabs--left .el-tabs__nav-next,.custom-theme .el-tabs--right .el-tabs__nav-next{right:auto;bottom:0}.custom-theme .el-tabs--left .el-tabs__header{float:left;margin-bottom:0;margin-right:10px}.custom-theme .el-tabs--left .el-tabs__nav-wrap{margin-right:-1px}.custom-theme .el-tabs--left .el-tabs__nav-wrap::after{left:auto;right:0}.custom-theme .el-tabs--left .el-tabs__active-bar{right:0;left:auto}.custom-theme .el-tabs--left .el-tabs__item{text-align:right}.custom-theme .el-tabs--left.el-tabs--card .el-tabs__active-bar{display:none}.custom-theme .el-tabs--left.el-tabs--card .el-tabs__item{border-left:none;border-right:1px solid #dfe4ed;border-bottom:none;border-top:1px solid #dfe4ed}.custom-theme .el-tabs--left.el-tabs--card .el-tabs__item:first-child{border-right:1px solid #dfe4ed;border-top:none}.custom-theme .el-tabs--left.el-tabs--card .el-tabs__item.is-active{border:1px solid #dfe4ed;border-right-color:#fff;border-left:none;border-bottom:none}.custom-theme .el-tabs--left.el-tabs--card .el-tabs__item.is-active:first-child{border-top:none}.custom-theme .el-tabs--left.el-tabs--card .el-tabs__item.is-active:last-child{border-bottom:none}.custom-theme .el-tabs--left.el-tabs--card .el-tabs__nav{border-radius:4px 0 0 4px;border-bottom:1px solid #dfe4ed;border-right:none}.custom-theme .el-tabs--left.el-tabs--card .el-tabs__new-tab{float:none}.custom-theme .el-tabs--left.el-tabs--border-card .el-tabs__header{border-right:1px solid #dfe4ed}.custom-theme .el-tabs--left.el-tabs--border-card .el-tabs__item{border:1px solid transparent;margin:-1px 0 -1px -1px}.custom-theme .el-tabs--left.el-tabs--border-card .el-tabs__item.is-active{border-color:transparent;border-top-color:#d1dbe5;border-bottom-color:#d1dbe5}.custom-theme .el-tabs--right .el-tabs__header{float:right;margin-bottom:0;margin-left:10px}.custom-theme .el-tabs--right .el-tabs__nav-wrap{margin-left:-1px}.custom-theme .el-tabs--right .el-tabs__nav-wrap::after{left:0;right:auto}.custom-theme .el-tabs--right .el-tabs__active-bar{left:0}.custom-theme .el-tabs--right.el-tabs--card .el-tabs__active-bar{display:none}.custom-theme .el-tabs--right.el-tabs--card .el-tabs__item{border-bottom:none;border-top:1px solid #dfe4ed}.custom-theme .el-tabs--right.el-tabs--card .el-tabs__item:first-child{border-left:1px solid #dfe4ed;border-top:none}.custom-theme .el-tabs--right.el-tabs--card .el-tabs__item.is-active{border:1px solid #dfe4ed;border-left-color:#fff;border-right:none;border-bottom:none}.custom-theme .el-tabs--right.el-tabs--card .el-tabs__item.is-active:first-child{border-top:none}.custom-theme .el-tabs--right.el-tabs--card .el-tabs__item.is-active:last-child{border-bottom:none}.custom-theme .el-tabs--right.el-tabs--card .el-tabs__nav{border-radius:0 4px 4px 0;border-bottom:1px solid #dfe4ed;border-left:none}.custom-theme .el-tabs--right.el-tabs--border-card .el-tabs__header{border-left:1px solid #dfe4ed}.custom-theme .el-tabs--right.el-tabs--border-card .el-tabs__item{border:1px solid transparent;margin:-1px -1px -1px 0}.custom-theme .el-tabs--right.el-tabs--border-card .el-tabs__item.is-active{border-color:transparent;border-top-color:#d1dbe5;border-bottom-color:#d1dbe5}.custom-theme .slideInLeft-transition,.custom-theme .slideInRight-transition{display:inline-block}.custom-theme .slideInRight-enter{-webkit-animation:slideInRight-enter .3s;animation:slideInRight-enter .3s}.custom-theme .slideInRight-leave{position:absolute;left:0;right:0;-webkit-animation:slideInRight-leave .3s;animation:slideInRight-leave .3s}.custom-theme .slideInLeft-enter{-webkit-animation:slideInLeft-enter .3s;animation:slideInLeft-enter .3s}.custom-theme .slideInLeft-leave{position:absolute;left:0;right:0;-webkit-animation:slideInLeft-leave .3s;animation:slideInLeft-leave .3s}@-webkit-keyframes slideInRight-enter{0%{opacity:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(100%);transform:translateX(100%)}to{opacity:1;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes slideInRight-enter{0%{opacity:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(100%);transform:translateX(100%)}to{opacity:1;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes slideInRight-leave{0%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0);opacity:1}100%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(100%);transform:translateX(100%);opacity:0}}@keyframes slideInRight-leave{0%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0);opacity:1}100%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(100%);transform:translateX(100%);opacity:0}}@-webkit-keyframes slideInLeft-enter{0%{opacity:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}to{opacity:1;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0)}}@keyframes slideInLeft-enter{0%{opacity:0;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}to{opacity:1;-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0)}}@-webkit-keyframes slideInLeft-leave{0%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0);opacity:1}100%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(-100%);transform:translateX(-100%);opacity:0}}@keyframes slideInLeft-leave{0%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(0);transform:translateX(0);opacity:1}100%{-webkit-transform-origin:0 0;transform-origin:0 0;-webkit-transform:translateX(-100%);transform:translateX(-100%);opacity:0}}.custom-theme .el-tag{background-color:rgba(38,39,41,.1);display:inline-block;padding:0 10px;height:32px;line-height:30px;font-size:12px;color:#262729;border-radius:4px;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid rgba(38,39,41,.2);white-space:nowrap}.custom-theme .el-tag .el-icon-close{border-radius:50%;text-align:center;position:relative;cursor:pointer;font-size:12px;height:18px;width:18px;line-height:18px;vertical-align:middle;top:-1px;right:-5px;color:#262729}.custom-theme .el-tag .el-icon-close::before{display:block}.custom-theme .el-tag .el-icon-close:hover{background-color:#262729;color:#fff}.custom-theme .el-tag--info{background-color:rgba(10,118,164,.1);border-color:rgba(10,118,164,.2);color:#0a76a4}.custom-theme .el-tag--info.is-hit{border-color:#0a76a4}.custom-theme .el-tag--info .el-tag__close{color:#0a76a4}.custom-theme .el-tag--info .el-tag__close:hover{background-color:#0a76a4;color:#fff}.custom-theme .el-tag--success{background-color:rgba(64,145,103,.1);border-color:rgba(64,145,103,.2);color:#409167}.custom-theme .el-tag--success.is-hit{border-color:#409167}.custom-theme .el-tag--success .el-tag__close{color:#409167}.custom-theme .el-tag--success .el-tag__close:hover{background-color:#409167;color:#fff}.custom-theme .el-tag--warning{background-color:rgba(157,164,8,.1);border-color:rgba(157,164,8,.2);color:#9da408}.custom-theme .el-tag--warning.is-hit{border-color:#9da408}.custom-theme .el-tag--warning .el-tag__close{color:#9da408}.custom-theme .el-tag--warning .el-tag__close:hover{background-color:#9da408;color:#fff}.custom-theme .el-tag--danger{background-color:rgba(179,69,14,.1);border-color:rgba(179,69,14,.2);color:#b3450e}.custom-theme .el-tag--danger.is-hit{border-color:#b3450e}.custom-theme .el-tag--danger .el-tag__close{color:#b3450e}.custom-theme .el-tag--danger .el-tag__close:hover{background-color:#b3450e;color:#fff}.custom-theme .el-tag--medium{height:28px;line-height:26px}.custom-theme .el-tag--medium .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-tag--small{height:24px;padding:0 8px;line-height:22px}.custom-theme .el-tag--small .el-icon-close{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-tag--mini{height:20px;padding:0 5px;line-height:19px}.custom-theme .el-tag--mini .el-icon-close{margin-left:-3px;-webkit-transform:scale(.7);transform:scale(.7)}.custom-theme .el-tree{cursor:default;background:#fff;color:#5a5e66}.custom-theme .el-tree__empty-block{position:relative;min-height:60px;text-align:center;width:100%;height:100%}.custom-theme .el-tree__empty-text{position:absolute;left:50%;top:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);color:#623615}.custom-theme .el-tree-node{white-space:nowrap}.custom-theme .el-tree-node__content{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:26px;cursor:pointer}.custom-theme .el-tree-node__content>.el-tree-node__expand-icon{padding:6px}.custom-theme .el-tree-node__content>.el-checkbox{margin-right:8px}.custom-theme .el-tree-node__content:hover{background-color:#f5f7fa}.custom-theme .el-tree-node__expand-icon{cursor:pointer;color:#b4bccc;font-size:12px;-webkit-transform:rotate(0);transform:rotate(0);-webkit-transition:-webkit-transform .3s ease-in-out;transition:-webkit-transform .3s ease-in-out;transition:transform .3s ease-in-out;transition:transform .3s ease-in-out,-webkit-transform .3s ease-in-out}.custom-theme .el-tree-node__expand-icon.expanded{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.custom-theme .el-tree-node__expand-icon.is-leaf{color:transparent;cursor:default}.custom-theme .el-tree-node__label{font-size:14px}.custom-theme .el-tree-node__loading-icon{margin-right:8px;font-size:14px;color:#b4bccc}.custom-theme .el-tree-node>.el-tree-node__children{overflow:hidden;background-color:transparent}.custom-theme .el-tree-node.is-expanded>.el-tree-node__children{display:block}.custom-theme .el-tree--highlight-current .el-tree-node.is-current>.el-tree-node__content{background-color:#eee}.custom-theme .el-alert{width:100%;padding:8px 16px;margin:0;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px;position:relative;background-color:#fff;overflow:hidden;opacity:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-transition:opacity .2s;transition:opacity .2s}.custom-theme .el-alert.is-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.custom-theme .el-alert--success{background-color:#ecf4f0;color:#409167}.custom-theme .el-alert--success .el-alert__description{color:#409167}.custom-theme .el-alert--info{background-color:#e7f1f6;color:#0a76a4}.custom-theme .el-alert--info .el-alert__description{color:#0a76a4}.custom-theme .el-alert--warning{background-color:#f5f6e6;color:#9da408}.custom-theme .el-alert--warning .el-alert__description{color:#9da408}.custom-theme .el-alert--error{background-color:#f7ece7;color:#b3450e}.custom-theme .el-alert--error .el-alert__description{color:#b3450e}.custom-theme .el-alert__content{display:table-cell;padding:0 8px}.custom-theme .el-alert__icon{font-size:16px;width:16px}.custom-theme .el-alert__icon.is-big{font-size:28px;width:28px}.custom-theme .el-alert__title{font-size:13px;line-height:18px}.custom-theme .el-alert__title.is-bold{font-weight:700}.custom-theme .el-alert .el-alert__description{font-size:12px;margin:5px 0 0 0}.custom-theme .el-alert__closebtn{font-size:12px;color:#b4bccc;opacity:1;position:absolute;top:12px;right:15px;cursor:pointer}.custom-theme .el-alert__closebtn.is-customed{font-style:normal;font-size:13px;top:9px}.custom-theme .el-alert-fade-enter,.custom-theme .el-alert-fade-leave-active{opacity:0}.custom-theme .el-notification{display:-webkit-box;display:-ms-flexbox;display:flex;width:330px;padding:14px 26px 14px 13px;border-radius:8px;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #e6ebf5;position:fixed;background-color:#fff;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);-webkit-transition:opacity .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;transition:opacity .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;transition:opacity .3s,transform .3s,left .3s,right .3s,top .4s,bottom .3s;transition:opacity .3s,transform .3s,left .3s,right .3s,top .4s,bottom .3s,-webkit-transform .3s;overflow:hidden}.custom-theme .el-notification.right{right:16px}.custom-theme .el-notification.left{left:16px}.custom-theme .el-notification__group{margin-left:13px}.custom-theme .el-notification__title{font-weight:700;font-size:16px;color:#2d2f33;margin:0}.custom-theme .el-notification__content{font-size:14px;line-height:21px;margin:6px 0 0 0;color:#5a5e66;text-align:justify}.custom-theme .el-notification__content p{margin:0}.custom-theme .el-notification__icon{height:24px;width:24px;font-size:24px;-webkit-transform:translateY(4px);transform:translateY(4px)}.custom-theme .el-notification__closeBtn{position:absolute;top:15px;right:15px;cursor:pointer;color:#878d99;font-size:16px}.custom-theme .el-notification__closeBtn:hover{color:#5a5e66}.custom-theme .el-notification .el-icon-success{color:#409167}.custom-theme .el-notification .el-icon-error{color:#b3450e}.custom-theme .el-notification .el-icon-info{color:#0a76a4}.custom-theme .el-notification .el-icon-warning{color:#9da408}.custom-theme .el-notification-fade-enter.right{right:0;-webkit-transform:translateX(100%);transform:translateX(100%)}.custom-theme .el-notification-fade-enter.left{left:0;-webkit-transform:translateX(-100%);transform:translateX(-100%)}.custom-theme .el-notification-fade-leave-active{opacity:0}.custom-theme .el-input{position:relative;font-size:14px;display:inline-block;width:100%}.custom-theme .el-input::-webkit-scrollbar{z-index:11;width:6px}.custom-theme .el-input::-webkit-scrollbar:horizontal{height:6px}.custom-theme .el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.custom-theme .el-input::-webkit-scrollbar-corner{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.custom-theme .el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #d8dce5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#5a5e66;display:inline-block;font-size:inherit;height:40px;line-height:1;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.custom-theme .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input__inner:hover{border-color:#b4bccc}.custom-theme .el-input__inner:focus{outline:0;border-color:#262729}.custom-theme .el-input__suffix{position:absolute;height:100%;right:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s;pointer-events:none}.custom-theme .el-input__suffix-inner{pointer-events:all}.custom-theme .el-input__prefix{position:absolute;height:100%;left:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s}.custom-theme .el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.custom-theme .el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.custom-theme .el-input__validateIcon{pointer-events:none}.custom-theme .el-input.is-active .el-input__inner{outline:0;border-color:#262729}.custom-theme .el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__icon{cursor:not-allowed}.custom-theme .el-input--suffix .el-input__inner{padding-right:30px}.custom-theme .el-input--prefix .el-input__inner{padding-left:30px}.custom-theme .el-input--medium{font-size:14px}.custom-theme .el-input--medium .el-input__inner{height:36px}.custom-theme .el-input--medium .el-input__icon{line-height:36px}.custom-theme .el-input--small{font-size:13px}.custom-theme .el-input--small .el-input__inner{height:32px}.custom-theme .el-input--small .el-input__icon{line-height:32px}.custom-theme .el-input--mini{font-size:12px}.custom-theme .el-input--mini .el-input__inner{height:28px}.custom-theme .el-input--mini .el-input__icon{line-height:28px}.custom-theme .el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.custom-theme .el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.custom-theme .el-input-group__append,.custom-theme .el-input-group__prepend{background-color:#f5f7fa;color:#0a76a4;vertical-align:middle;display:table-cell;position:relative;border:1px solid #d8dce5;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.custom-theme .el-input-group__append:focus,.custom-theme .el-input-group__prepend:focus{outline:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-select,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-select{display:inline-block;margin:-20px}.custom-theme .el-input-group__append button.el-button,.custom-theme .el-input-group__append div.el-select .el-input__inner,.custom-theme .el-input-group__append div.el-select:hover .el-input__inner,.custom-theme .el-input-group__prepend button.el-button,.custom-theme .el-input-group__prepend div.el-select .el-input__inner,.custom-theme .el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-input,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-input{font-size:inherit}.custom-theme .el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-input-group__append{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--prepend .el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--append .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-textarea{display:inline-block;width:100%;vertical-align:bottom}.custom-theme .el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:14px;color:#5a5e66;background-color:#fff;background-image:none;border:1px solid #d8dce5;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:hover{border-color:#b4bccc}.custom-theme .el-textarea__inner:focus{outline:0;border-color:#262729}.custom-theme .el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-input-number{position:relative;display:inline-block;width:180px;line-height:38px}.custom-theme .el-input-number .el-input{display:block}.custom-theme .el-input-number .el-input__inner{-webkit-appearance:none;padding-left:50px;padding-right:50px;text-align:center}.custom-theme .el-input-number__decrease,.custom-theme .el-input-number__increase{position:absolute;z-index:1;top:1px;width:40px;height:auto;text-align:center;background:#f5f7fa;color:#5a5e66;cursor:pointer;font-size:13px}.custom-theme .el-input-number__decrease:hover,.custom-theme .el-input-number__increase:hover{color:#262729}.custom-theme .el-input-number__decrease:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled),.custom-theme .el-input-number__increase:hover:not(.is-disabled)~.el-input .el-input__inner:not(.is-disabled){border-color:#262729}.custom-theme .el-input-number__decrease.is-disabled,.custom-theme .el-input-number__increase.is-disabled{color:#b4bccc;cursor:not-allowed}.custom-theme .el-input-number__increase{right:1px;border-radius:0 4px 4px 0;border-left:1px solid #d8dce5}.custom-theme .el-input-number__decrease{left:1px;border-radius:4px 0 0 4px;border-right:1px solid #d8dce5}.custom-theme .el-input-number.is-disabled .el-input-number__decrease,.custom-theme .el-input-number.is-disabled .el-input-number__increase{border-color:#dfe4ed;color:#dfe4ed}.custom-theme .el-input-number.is-disabled .el-input-number__decrease:hover,.custom-theme .el-input-number.is-disabled .el-input-number__increase:hover{color:#dfe4ed;cursor:not-allowed}.custom-theme .el-input-number--medium{width:200px;line-height:34px}.custom-theme .el-input-number--medium .el-input-number__decrease,.custom-theme .el-input-number--medium .el-input-number__increase{width:36px;font-size:14px}.custom-theme .el-input-number--medium .el-input__inner{padding-left:43px;padding-right:43px}.custom-theme .el-input-number--small{width:130px;line-height:30px}.custom-theme .el-input-number--small .el-input-number__decrease,.custom-theme .el-input-number--small .el-input-number__increase{width:32px;font-size:13px}.custom-theme .el-input-number--small .el-input-number__decrease [class*=el-icon],.custom-theme .el-input-number--small .el-input-number__increase [class*=el-icon]{-webkit-transform:scale(.9);transform:scale(.9)}.custom-theme .el-input-number--small .el-input__inner{padding-left:39px;padding-right:39px}.custom-theme .el-input-number--mini{width:130px;line-height:26px}.custom-theme .el-input-number--mini .el-input-number__decrease,.custom-theme .el-input-number--mini .el-input-number__increase{width:28px;font-size:12px}.custom-theme .el-input-number--mini .el-input-number__decrease [class*=el-icon],.custom-theme .el-input-number--mini .el-input-number__increase [class*=el-icon]{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-input-number--mini .el-input__inner{padding-left:35px;padding-right:35px}.custom-theme .el-input-number.is-without-controls .el-input__inner{padding-left:15px;padding-right:15px}.custom-theme .el-input-number.is-controls-right .el-input__inner{padding-left:15px;padding-right:50px}.custom-theme .el-input-number.is-controls-right .el-input-number__decrease,.custom-theme .el-input-number.is-controls-right .el-input-number__increase{height:auto;line-height:19px}.custom-theme .el-input-number.is-controls-right .el-input-number__decrease [class*=el-icon],.custom-theme .el-input-number.is-controls-right .el-input-number__increase [class*=el-icon]{-webkit-transform:scale(.8);transform:scale(.8)}.custom-theme .el-input-number.is-controls-right .el-input-number__increase{border-radius:0 4px 0 0;border-bottom:1px solid #d8dce5}.custom-theme .el-input-number.is-controls-right .el-input-number__decrease{right:1px;bottom:1px;top:auto;left:auto;border-right:none;border-left:1px solid #d8dce5;border-radius:0 0 4px 0}.custom-theme .el-input-number.is-controls-right[class*=medium] [class*=decrease],.custom-theme .el-input-number.is-controls-right[class*=medium] [class*=increase]{line-height:17px}.custom-theme .el-input-number.is-controls-right[class*=small] [class*=decrease],.custom-theme .el-input-number.is-controls-right[class*=small] [class*=increase]{line-height:15px}.custom-theme .el-input-number.is-controls-right[class*=mini] [class*=decrease],.custom-theme .el-input-number.is-controls-right[class*=mini] [class*=increase]{line-height:13px}.custom-theme .el-tooltip__popper{position:absolute;border-radius:4px;padding:10px;z-index:2000;font-size:12px;line-height:1.2}.custom-theme .el-tooltip__popper .popper__arrow,.custom-theme .el-tooltip__popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.custom-theme .el-tooltip__popper .popper__arrow{border-width:6px}.custom-theme .el-tooltip__popper .popper__arrow::after{content:" ";border-width:5px}.custom-theme .el-tooltip__popper[x-placement^=top]{margin-bottom:12px}.custom-theme .el-tooltip__popper[x-placement^=top] .popper__arrow{bottom:-6px;border-top-color:#2d2f33;border-bottom-width:0}.custom-theme .el-tooltip__popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-5px;border-top-color:#2d2f33;border-bottom-width:0}.custom-theme .el-tooltip__popper[x-placement^=bottom]{margin-top:12px}.custom-theme .el-tooltip__popper[x-placement^=bottom] .popper__arrow{top:-6px;border-top-width:0;border-bottom-color:#2d2f33}.custom-theme .el-tooltip__popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-5px;border-top-width:0;border-bottom-color:#2d2f33}.custom-theme .el-tooltip__popper[x-placement^=right]{margin-left:12px}.custom-theme .el-tooltip__popper[x-placement^=right] .popper__arrow{left:-6px;border-right-color:#2d2f33;border-left-width:0}.custom-theme .el-tooltip__popper[x-placement^=right] .popper__arrow::after{bottom:-5px;left:1px;border-right-color:#2d2f33;border-left-width:0}.custom-theme .el-tooltip__popper[x-placement^=left]{margin-right:12px}.custom-theme .el-tooltip__popper[x-placement^=left] .popper__arrow{right:-6px;border-right-width:0;border-left-color:#2d2f33}.custom-theme .el-tooltip__popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-5px;margin-left:-5px;border-right-width:0;border-left-color:#2d2f33}.custom-theme .el-tooltip__popper.is-dark{background:#2d2f33;color:#fff}.custom-theme .el-tooltip__popper.is-light{background:#fff;border:1px solid #2d2f33}.custom-theme .el-tooltip__popper.is-light[x-placement^=top] .popper__arrow{border-top-color:#2d2f33}.custom-theme .el-tooltip__popper.is-light[x-placement^=top] .popper__arrow::after{border-top-color:#fff}.custom-theme .el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow{border-bottom-color:#2d2f33}.custom-theme .el-tooltip__popper.is-light[x-placement^=bottom] .popper__arrow::after{border-bottom-color:#fff}.custom-theme .el-tooltip__popper.is-light[x-placement^=left] .popper__arrow{border-left-color:#2d2f33}.custom-theme .el-tooltip__popper.is-light[x-placement^=left] .popper__arrow::after{border-left-color:#fff}.custom-theme .el-tooltip__popper.is-light[x-placement^=right] .popper__arrow{border-right-color:#2d2f33}.custom-theme .el-tooltip__popper.is-light[x-placement^=right] .popper__arrow::after{border-right-color:#fff}.custom-theme .el-slider::after,.custom-theme .el-slider::before{display:table;content:""}.custom-theme .el-slider::after{clear:both}.custom-theme .el-slider__runway{width:100%;height:6px;margin:16px 0;background-color:#dfe4ed;border-radius:3px;position:relative;cursor:pointer;vertical-align:middle}.custom-theme .el-slider__runway.show-input{margin-right:160px;width:auto}.custom-theme .el-slider__runway.disabled{cursor:default}.custom-theme .el-slider__runway.disabled .el-slider__bar{background-color:#b4bccc}.custom-theme .el-slider__runway.disabled .el-slider__button{border-color:#b4bccc}.custom-theme .el-slider__runway.disabled .el-slider__button-wrapper.hover,.custom-theme .el-slider__runway.disabled .el-slider__button-wrapper:hover{cursor:not-allowed}.custom-theme .el-slider__runway.disabled .el-slider__button-wrapper.dragging{cursor:not-allowed}.custom-theme .el-slider__runway.disabled .el-slider__button.dragging,.custom-theme .el-slider__runway.disabled .el-slider__button.hover,.custom-theme .el-slider__runway.disabled .el-slider__button:hover{-webkit-transform:scale(1);transform:scale(1)}.custom-theme .el-slider__runway.disabled .el-slider__button.hover,.custom-theme .el-slider__runway.disabled .el-slider__button:hover{cursor:not-allowed}.custom-theme .el-slider__runway.disabled .el-slider__button.dragging{cursor:not-allowed}.custom-theme .el-slider__input{float:right;margin-top:3px}.custom-theme .el-slider__bar{height:6px;background-color:#262729;border-top-left-radius:3px;border-bottom-left-radius:3px;position:absolute}.custom-theme .el-slider__button-wrapper{height:36px;width:36px;position:absolute;z-index:1001;top:-15px;-webkit-transform:translateX(-50%);transform:translateX(-50%);background-color:transparent;text-align:center;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.custom-theme .el-slider__button-wrapper::after{display:inline-block;content:"";height:100%;vertical-align:middle}.custom-theme .el-slider__button-wrapper .el-tooltip{vertical-align:middle;display:inline-block}.custom-theme .el-slider__button-wrapper.hover,.custom-theme .el-slider__button-wrapper:hover{cursor:-webkit-grab;cursor:grab}.custom-theme .el-slider__button-wrapper.dragging{cursor:-webkit-grabbing;cursor:grabbing}.custom-theme .el-slider__button{width:16px;height:16px;border:solid 2px #262729;background-color:#fff;border-radius:50%;-webkit-transition:.2s;transition:.2s;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.custom-theme .el-slider__button.dragging,.custom-theme .el-slider__button.hover,.custom-theme .el-slider__button:hover{-webkit-transform:scale(1.2);transform:scale(1.2)}.custom-theme .el-slider__button.hover,.custom-theme .el-slider__button:hover{cursor:-webkit-grab;cursor:grab}.custom-theme .el-slider__button.dragging{cursor:-webkit-grabbing;cursor:grabbing}.custom-theme .el-slider__stop{position:absolute;height:6px;width:6px;border-radius:100%;background-color:#fff;-webkit-transform:translateX(-50%);transform:translateX(-50%)}.custom-theme .el-slider.is-vertical{position:relative}.custom-theme .el-slider.is-vertical .el-slider__runway{width:4px;height:100%;margin:0 16px}.custom-theme .el-slider.is-vertical .el-slider__bar{width:4px;height:auto;border-radius:0 0 3px 3px}.custom-theme .el-slider.is-vertical .el-slider__button-wrapper{top:auto;left:-15px;-webkit-transform:translateY(50%);transform:translateY(50%)}.custom-theme .el-slider.is-vertical .el-slider__stop{-webkit-transform:translateY(50%);transform:translateY(50%)}.custom-theme .el-slider.is-vertical.el-slider--with-input{padding-bottom:58px}.custom-theme .el-slider.is-vertical.el-slider--with-input .el-slider__input{overflow:visible;float:none;position:absolute;bottom:22px;width:36px;margin-top:15px}.custom-theme .el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input__inner{text-align:center;padding-left:5px;padding-right:5px}.custom-theme .el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease,.custom-theme .el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{top:32px;margin-top:-1px;border:1px solid #d8dce5;line-height:20px;-webkit-box-sizing:border-box;box-sizing:border-box;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__decrease{width:18px;right:18px;border-bottom-left-radius:4px}.custom-theme .el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase{width:19px;border-bottom-right-radius:4px}.custom-theme .el-slider.is-vertical.el-slider--with-input .el-slider__input .el-input-number__increase~.el-input .el-input__inner{border-bottom-left-radius:0;border-bottom-right-radius:0}.custom-theme .el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__decrease,.custom-theme .el-slider.is-vertical.el-slider--with-input .el-slider__input:hover .el-input-number__increase{border-color:#b4bccc}.custom-theme .el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__decrease,.custom-theme .el-slider.is-vertical.el-slider--with-input .el-slider__input:active .el-input-number__increase{border-color:#262729}.custom-theme .el-loading-parent--relative{position:relative!important}.custom-theme .el-loading-parent--hidden{overflow:hidden!important}.custom-theme .el-loading-mask{position:absolute;z-index:10000;background-color:rgba(255,255,255,.9);margin:0;top:0;right:0;bottom:0;left:0;-webkit-transition:opacity .3s;transition:opacity .3s}.custom-theme .el-loading-mask.is-fullscreen{position:fixed}.custom-theme .el-loading-mask.is-fullscreen .el-loading-spinner{margin-top:-25px}.custom-theme .el-loading-mask.is-fullscreen .el-loading-spinner .circular{height:50px;width:50px}.custom-theme .el-loading-spinner{top:50%;margin-top:-21px;width:100%;text-align:center;position:absolute}.custom-theme .el-loading-spinner .el-loading-text{color:#262729;margin:3px 0;font-size:14px}.custom-theme .el-loading-spinner .circular{height:42px;width:42px;-webkit-animation:loading-rotate 2s linear infinite;animation:loading-rotate 2s linear infinite}.custom-theme .el-loading-spinner .path{-webkit-animation:loading-dash 1.5s ease-in-out infinite;animation:loading-dash 1.5s ease-in-out infinite;stroke-dasharray:90,150;stroke-dashoffset:0;stroke-width:2;stroke:#262729;stroke-linecap:round}.custom-theme .el-loading-spinner i{color:#262729}.custom-theme .el-loading-fade-enter,.custom-theme .el-loading-fade-leave-active{opacity:0}@-webkit-keyframes loading-rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes loading-rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}100%{stroke-dasharray:90,150;stroke-dashoffset:-120px}}@keyframes loading-dash{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-40px}100%{stroke-dasharray:90,150;stroke-dashoffset:-120px}}.custom-theme .el-row{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-row::after,.custom-theme .el-row::before{display:table;content:""}.custom-theme .el-row::after{clear:both}.custom-theme .el-row--flex{display:-webkit-box;display:-ms-flexbox;display:flex}.custom-theme .el-row--flex:after,.custom-theme .el-row--flex:before{display:none}.custom-theme .el-row--flex.is-justify-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.custom-theme .el-row--flex.is-justify-end{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.custom-theme .el-row--flex.is-justify-space-between{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.custom-theme .el-row--flex.is-justify-space-around{-ms-flex-pack:distribute;justify-content:space-around}.custom-theme .el-row--flex.is-align-middle{-webkit-box-align:center;-ms-flex-align:center;align-items:center}.custom-theme .el-row--flex.is-align-bottom{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.custom-theme [class*=el-col-]{float:left;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-col-0{display:none}.custom-theme .el-col-1{width:4.16667%}.custom-theme .el-col-offset-1{margin-left:4.16667%}.custom-theme .el-col-pull-1{position:relative;right:4.16667%}.custom-theme .el-col-push-1{position:relative;left:4.16667%}.custom-theme .el-col-2{width:8.33333%}.custom-theme .el-col-offset-2{margin-left:8.33333%}.custom-theme .el-col-pull-2{position:relative;right:8.33333%}.custom-theme .el-col-push-2{position:relative;left:8.33333%}.custom-theme .el-col-3{width:12.5%}.custom-theme .el-col-offset-3{margin-left:12.5%}.custom-theme .el-col-pull-3{position:relative;right:12.5%}.custom-theme .el-col-push-3{position:relative;left:12.5%}.custom-theme .el-col-4{width:16.66667%}.custom-theme .el-col-offset-4{margin-left:16.66667%}.custom-theme .el-col-pull-4{position:relative;right:16.66667%}.custom-theme .el-col-push-4{position:relative;left:16.66667%}.custom-theme .el-col-5{width:20.83333%}.custom-theme .el-col-offset-5{margin-left:20.83333%}.custom-theme .el-col-pull-5{position:relative;right:20.83333%}.custom-theme .el-col-push-5{position:relative;left:20.83333%}.custom-theme .el-col-6{width:25%}.custom-theme .el-col-offset-6{margin-left:25%}.custom-theme .el-col-pull-6{position:relative;right:25%}.custom-theme .el-col-push-6{position:relative;left:25%}.custom-theme .el-col-7{width:29.16667%}.custom-theme .el-col-offset-7{margin-left:29.16667%}.custom-theme .el-col-pull-7{position:relative;right:29.16667%}.custom-theme .el-col-push-7{position:relative;left:29.16667%}.custom-theme .el-col-8{width:33.33333%}.custom-theme .el-col-offset-8{margin-left:33.33333%}.custom-theme .el-col-pull-8{position:relative;right:33.33333%}.custom-theme .el-col-push-8{position:relative;left:33.33333%}.custom-theme .el-col-9{width:37.5%}.custom-theme .el-col-offset-9{margin-left:37.5%}.custom-theme .el-col-pull-9{position:relative;right:37.5%}.custom-theme .el-col-push-9{position:relative;left:37.5%}.custom-theme .el-col-10{width:41.66667%}.custom-theme .el-col-offset-10{margin-left:41.66667%}.custom-theme .el-col-pull-10{position:relative;right:41.66667%}.custom-theme .el-col-push-10{position:relative;left:41.66667%}.custom-theme .el-col-11{width:45.83333%}.custom-theme .el-col-offset-11{margin-left:45.83333%}.custom-theme .el-col-pull-11{position:relative;right:45.83333%}.custom-theme .el-col-push-11{position:relative;left:45.83333%}.custom-theme .el-col-12{width:50%}.custom-theme .el-col-offset-12{margin-left:50%}.custom-theme .el-col-pull-12{position:relative;right:50%}.custom-theme .el-col-push-12{position:relative;left:50%}.custom-theme .el-col-13{width:54.16667%}.custom-theme .el-col-offset-13{margin-left:54.16667%}.custom-theme .el-col-pull-13{position:relative;right:54.16667%}.custom-theme .el-col-push-13{position:relative;left:54.16667%}.custom-theme .el-col-14{width:58.33333%}.custom-theme .el-col-offset-14{margin-left:58.33333%}.custom-theme .el-col-pull-14{position:relative;right:58.33333%}.custom-theme .el-col-push-14{position:relative;left:58.33333%}.custom-theme .el-col-15{width:62.5%}.custom-theme .el-col-offset-15{margin-left:62.5%}.custom-theme .el-col-pull-15{position:relative;right:62.5%}.custom-theme .el-col-push-15{position:relative;left:62.5%}.custom-theme .el-col-16{width:66.66667%}.custom-theme .el-col-offset-16{margin-left:66.66667%}.custom-theme .el-col-pull-16{position:relative;right:66.66667%}.custom-theme .el-col-push-16{position:relative;left:66.66667%}.custom-theme .el-col-17{width:70.83333%}.custom-theme .el-col-offset-17{margin-left:70.83333%}.custom-theme .el-col-pull-17{position:relative;right:70.83333%}.custom-theme .el-col-push-17{position:relative;left:70.83333%}.custom-theme .el-col-18{width:75%}.custom-theme .el-col-offset-18{margin-left:75%}.custom-theme .el-col-pull-18{position:relative;right:75%}.custom-theme .el-col-push-18{position:relative;left:75%}.custom-theme .el-col-19{width:79.16667%}.custom-theme .el-col-offset-19{margin-left:79.16667%}.custom-theme .el-col-pull-19{position:relative;right:79.16667%}.custom-theme .el-col-push-19{position:relative;left:79.16667%}.custom-theme .el-col-20{width:83.33333%}.custom-theme .el-col-offset-20{margin-left:83.33333%}.custom-theme .el-col-pull-20{position:relative;right:83.33333%}.custom-theme .el-col-push-20{position:relative;left:83.33333%}.custom-theme .el-col-21{width:87.5%}.custom-theme .el-col-offset-21{margin-left:87.5%}.custom-theme .el-col-pull-21{position:relative;right:87.5%}.custom-theme .el-col-push-21{position:relative;left:87.5%}.custom-theme .el-col-22{width:91.66667%}.custom-theme .el-col-offset-22{margin-left:91.66667%}.custom-theme .el-col-pull-22{position:relative;right:91.66667%}.custom-theme .el-col-push-22{position:relative;left:91.66667%}.custom-theme .el-col-23{width:95.83333%}.custom-theme .el-col-offset-23{margin-left:95.83333%}.custom-theme .el-col-pull-23{position:relative;right:95.83333%}.custom-theme .el-col-push-23{position:relative;left:95.83333%}.custom-theme .el-col-24{width:100%}.custom-theme .el-col-offset-24{margin-left:100%}.custom-theme .el-col-pull-24{position:relative;right:100%}.custom-theme .el-col-push-24{position:relative;left:100%}@media only screen and (max-width:768px){.custom-theme .el-col-xs-0{display:none}.custom-theme .el-col-xs-1{width:4.16667%}.custom-theme .el-col-xs-offset-1{margin-left:4.16667%}.custom-theme .el-col-xs-pull-1{position:relative;right:4.16667%}.custom-theme .el-col-xs-push-1{position:relative;left:4.16667%}.custom-theme .el-col-xs-2{width:8.33333%}.custom-theme .el-col-xs-offset-2{margin-left:8.33333%}.custom-theme .el-col-xs-pull-2{position:relative;right:8.33333%}.custom-theme .el-col-xs-push-2{position:relative;left:8.33333%}.custom-theme .el-col-xs-3{width:12.5%}.custom-theme .el-col-xs-offset-3{margin-left:12.5%}.custom-theme .el-col-xs-pull-3{position:relative;right:12.5%}.custom-theme .el-col-xs-push-3{position:relative;left:12.5%}.custom-theme .el-col-xs-4{width:16.66667%}.custom-theme .el-col-xs-offset-4{margin-left:16.66667%}.custom-theme .el-col-xs-pull-4{position:relative;right:16.66667%}.custom-theme .el-col-xs-push-4{position:relative;left:16.66667%}.custom-theme .el-col-xs-5{width:20.83333%}.custom-theme .el-col-xs-offset-5{margin-left:20.83333%}.custom-theme .el-col-xs-pull-5{position:relative;right:20.83333%}.custom-theme .el-col-xs-push-5{position:relative;left:20.83333%}.custom-theme .el-col-xs-6{width:25%}.custom-theme .el-col-xs-offset-6{margin-left:25%}.custom-theme .el-col-xs-pull-6{position:relative;right:25%}.custom-theme .el-col-xs-push-6{position:relative;left:25%}.custom-theme .el-col-xs-7{width:29.16667%}.custom-theme .el-col-xs-offset-7{margin-left:29.16667%}.custom-theme .el-col-xs-pull-7{position:relative;right:29.16667%}.custom-theme .el-col-xs-push-7{position:relative;left:29.16667%}.custom-theme .el-col-xs-8{width:33.33333%}.custom-theme .el-col-xs-offset-8{margin-left:33.33333%}.custom-theme .el-col-xs-pull-8{position:relative;right:33.33333%}.custom-theme .el-col-xs-push-8{position:relative;left:33.33333%}.custom-theme .el-col-xs-9{width:37.5%}.custom-theme .el-col-xs-offset-9{margin-left:37.5%}.custom-theme .el-col-xs-pull-9{position:relative;right:37.5%}.custom-theme .el-col-xs-push-9{position:relative;left:37.5%}.custom-theme .el-col-xs-10{width:41.66667%}.custom-theme .el-col-xs-offset-10{margin-left:41.66667%}.custom-theme .el-col-xs-pull-10{position:relative;right:41.66667%}.custom-theme .el-col-xs-push-10{position:relative;left:41.66667%}.custom-theme .el-col-xs-11{width:45.83333%}.custom-theme .el-col-xs-offset-11{margin-left:45.83333%}.custom-theme .el-col-xs-pull-11{position:relative;right:45.83333%}.custom-theme .el-col-xs-push-11{position:relative;left:45.83333%}.custom-theme .el-col-xs-12{width:50%}.custom-theme .el-col-xs-offset-12{margin-left:50%}.custom-theme .el-col-xs-pull-12{position:relative;right:50%}.custom-theme .el-col-xs-push-12{position:relative;left:50%}.custom-theme .el-col-xs-13{width:54.16667%}.custom-theme .el-col-xs-offset-13{margin-left:54.16667%}.custom-theme .el-col-xs-pull-13{position:relative;right:54.16667%}.custom-theme .el-col-xs-push-13{position:relative;left:54.16667%}.custom-theme .el-col-xs-14{width:58.33333%}.custom-theme .el-col-xs-offset-14{margin-left:58.33333%}.custom-theme .el-col-xs-pull-14{position:relative;right:58.33333%}.custom-theme .el-col-xs-push-14{position:relative;left:58.33333%}.custom-theme .el-col-xs-15{width:62.5%}.custom-theme .el-col-xs-offset-15{margin-left:62.5%}.custom-theme .el-col-xs-pull-15{position:relative;right:62.5%}.custom-theme .el-col-xs-push-15{position:relative;left:62.5%}.custom-theme .el-col-xs-16{width:66.66667%}.custom-theme .el-col-xs-offset-16{margin-left:66.66667%}.custom-theme .el-col-xs-pull-16{position:relative;right:66.66667%}.custom-theme .el-col-xs-push-16{position:relative;left:66.66667%}.custom-theme .el-col-xs-17{width:70.83333%}.custom-theme .el-col-xs-offset-17{margin-left:70.83333%}.custom-theme .el-col-xs-pull-17{position:relative;right:70.83333%}.custom-theme .el-col-xs-push-17{position:relative;left:70.83333%}.custom-theme .el-col-xs-18{width:75%}.custom-theme .el-col-xs-offset-18{margin-left:75%}.custom-theme .el-col-xs-pull-18{position:relative;right:75%}.custom-theme .el-col-xs-push-18{position:relative;left:75%}.custom-theme .el-col-xs-19{width:79.16667%}.custom-theme .el-col-xs-offset-19{margin-left:79.16667%}.custom-theme .el-col-xs-pull-19{position:relative;right:79.16667%}.custom-theme .el-col-xs-push-19{position:relative;left:79.16667%}.custom-theme .el-col-xs-20{width:83.33333%}.custom-theme .el-col-xs-offset-20{margin-left:83.33333%}.custom-theme .el-col-xs-pull-20{position:relative;right:83.33333%}.custom-theme .el-col-xs-push-20{position:relative;left:83.33333%}.custom-theme .el-col-xs-21{width:87.5%}.custom-theme .el-col-xs-offset-21{margin-left:87.5%}.custom-theme .el-col-xs-pull-21{position:relative;right:87.5%}.custom-theme .el-col-xs-push-21{position:relative;left:87.5%}.custom-theme .el-col-xs-22{width:91.66667%}.custom-theme .el-col-xs-offset-22{margin-left:91.66667%}.custom-theme .el-col-xs-pull-22{position:relative;right:91.66667%}.custom-theme .el-col-xs-push-22{position:relative;left:91.66667%}.custom-theme .el-col-xs-23{width:95.83333%}.custom-theme .el-col-xs-offset-23{margin-left:95.83333%}.custom-theme .el-col-xs-pull-23{position:relative;right:95.83333%}.custom-theme .el-col-xs-push-23{position:relative;left:95.83333%}.custom-theme .el-col-xs-24{width:100%}.custom-theme .el-col-xs-offset-24{margin-left:100%}.custom-theme .el-col-xs-pull-24{position:relative;right:100%}.custom-theme .el-col-xs-push-24{position:relative;left:100%}}@media only screen and (min-width:768px){.custom-theme .el-col-sm-0{display:none}.custom-theme .el-col-sm-1{width:4.16667%}.custom-theme .el-col-sm-offset-1{margin-left:4.16667%}.custom-theme .el-col-sm-pull-1{position:relative;right:4.16667%}.custom-theme .el-col-sm-push-1{position:relative;left:4.16667%}.custom-theme .el-col-sm-2{width:8.33333%}.custom-theme .el-col-sm-offset-2{margin-left:8.33333%}.custom-theme .el-col-sm-pull-2{position:relative;right:8.33333%}.custom-theme .el-col-sm-push-2{position:relative;left:8.33333%}.custom-theme .el-col-sm-3{width:12.5%}.custom-theme .el-col-sm-offset-3{margin-left:12.5%}.custom-theme .el-col-sm-pull-3{position:relative;right:12.5%}.custom-theme .el-col-sm-push-3{position:relative;left:12.5%}.custom-theme .el-col-sm-4{width:16.66667%}.custom-theme .el-col-sm-offset-4{margin-left:16.66667%}.custom-theme .el-col-sm-pull-4{position:relative;right:16.66667%}.custom-theme .el-col-sm-push-4{position:relative;left:16.66667%}.custom-theme .el-col-sm-5{width:20.83333%}.custom-theme .el-col-sm-offset-5{margin-left:20.83333%}.custom-theme .el-col-sm-pull-5{position:relative;right:20.83333%}.custom-theme .el-col-sm-push-5{position:relative;left:20.83333%}.custom-theme .el-col-sm-6{width:25%}.custom-theme .el-col-sm-offset-6{margin-left:25%}.custom-theme .el-col-sm-pull-6{position:relative;right:25%}.custom-theme .el-col-sm-push-6{position:relative;left:25%}.custom-theme .el-col-sm-7{width:29.16667%}.custom-theme .el-col-sm-offset-7{margin-left:29.16667%}.custom-theme .el-col-sm-pull-7{position:relative;right:29.16667%}.custom-theme .el-col-sm-push-7{position:relative;left:29.16667%}.custom-theme .el-col-sm-8{width:33.33333%}.custom-theme .el-col-sm-offset-8{margin-left:33.33333%}.custom-theme .el-col-sm-pull-8{position:relative;right:33.33333%}.custom-theme .el-col-sm-push-8{position:relative;left:33.33333%}.custom-theme .el-col-sm-9{width:37.5%}.custom-theme .el-col-sm-offset-9{margin-left:37.5%}.custom-theme .el-col-sm-pull-9{position:relative;right:37.5%}.custom-theme .el-col-sm-push-9{position:relative;left:37.5%}.custom-theme .el-col-sm-10{width:41.66667%}.custom-theme .el-col-sm-offset-10{margin-left:41.66667%}.custom-theme .el-col-sm-pull-10{position:relative;right:41.66667%}.custom-theme .el-col-sm-push-10{position:relative;left:41.66667%}.custom-theme .el-col-sm-11{width:45.83333%}.custom-theme .el-col-sm-offset-11{margin-left:45.83333%}.custom-theme .el-col-sm-pull-11{position:relative;right:45.83333%}.custom-theme .el-col-sm-push-11{position:relative;left:45.83333%}.custom-theme .el-col-sm-12{width:50%}.custom-theme .el-col-sm-offset-12{margin-left:50%}.custom-theme .el-col-sm-pull-12{position:relative;right:50%}.custom-theme .el-col-sm-push-12{position:relative;left:50%}.custom-theme .el-col-sm-13{width:54.16667%}.custom-theme .el-col-sm-offset-13{margin-left:54.16667%}.custom-theme .el-col-sm-pull-13{position:relative;right:54.16667%}.custom-theme .el-col-sm-push-13{position:relative;left:54.16667%}.custom-theme .el-col-sm-14{width:58.33333%}.custom-theme .el-col-sm-offset-14{margin-left:58.33333%}.custom-theme .el-col-sm-pull-14{position:relative;right:58.33333%}.custom-theme .el-col-sm-push-14{position:relative;left:58.33333%}.custom-theme .el-col-sm-15{width:62.5%}.custom-theme .el-col-sm-offset-15{margin-left:62.5%}.custom-theme .el-col-sm-pull-15{position:relative;right:62.5%}.custom-theme .el-col-sm-push-15{position:relative;left:62.5%}.custom-theme .el-col-sm-16{width:66.66667%}.custom-theme .el-col-sm-offset-16{margin-left:66.66667%}.custom-theme .el-col-sm-pull-16{position:relative;right:66.66667%}.custom-theme .el-col-sm-push-16{position:relative;left:66.66667%}.custom-theme .el-col-sm-17{width:70.83333%}.custom-theme .el-col-sm-offset-17{margin-left:70.83333%}.custom-theme .el-col-sm-pull-17{position:relative;right:70.83333%}.custom-theme .el-col-sm-push-17{position:relative;left:70.83333%}.custom-theme .el-col-sm-18{width:75%}.custom-theme .el-col-sm-offset-18{margin-left:75%}.custom-theme .el-col-sm-pull-18{position:relative;right:75%}.custom-theme .el-col-sm-push-18{position:relative;left:75%}.custom-theme .el-col-sm-19{width:79.16667%}.custom-theme .el-col-sm-offset-19{margin-left:79.16667%}.custom-theme .el-col-sm-pull-19{position:relative;right:79.16667%}.custom-theme .el-col-sm-push-19{position:relative;left:79.16667%}.custom-theme .el-col-sm-20{width:83.33333%}.custom-theme .el-col-sm-offset-20{margin-left:83.33333%}.custom-theme .el-col-sm-pull-20{position:relative;right:83.33333%}.custom-theme .el-col-sm-push-20{position:relative;left:83.33333%}.custom-theme .el-col-sm-21{width:87.5%}.custom-theme .el-col-sm-offset-21{margin-left:87.5%}.custom-theme .el-col-sm-pull-21{position:relative;right:87.5%}.custom-theme .el-col-sm-push-21{position:relative;left:87.5%}.custom-theme .el-col-sm-22{width:91.66667%}.custom-theme .el-col-sm-offset-22{margin-left:91.66667%}.custom-theme .el-col-sm-pull-22{position:relative;right:91.66667%}.custom-theme .el-col-sm-push-22{position:relative;left:91.66667%}.custom-theme .el-col-sm-23{width:95.83333%}.custom-theme .el-col-sm-offset-23{margin-left:95.83333%}.custom-theme .el-col-sm-pull-23{position:relative;right:95.83333%}.custom-theme .el-col-sm-push-23{position:relative;left:95.83333%}.custom-theme .el-col-sm-24{width:100%}.custom-theme .el-col-sm-offset-24{margin-left:100%}.custom-theme .el-col-sm-pull-24{position:relative;right:100%}.custom-theme .el-col-sm-push-24{position:relative;left:100%}}@media only screen and (min-width:992px){.custom-theme .el-col-md-0{display:none}.custom-theme .el-col-md-1{width:4.16667%}.custom-theme .el-col-md-offset-1{margin-left:4.16667%}.custom-theme .el-col-md-pull-1{position:relative;right:4.16667%}.custom-theme .el-col-md-push-1{position:relative;left:4.16667%}.custom-theme .el-col-md-2{width:8.33333%}.custom-theme .el-col-md-offset-2{margin-left:8.33333%}.custom-theme .el-col-md-pull-2{position:relative;right:8.33333%}.custom-theme .el-col-md-push-2{position:relative;left:8.33333%}.custom-theme .el-col-md-3{width:12.5%}.custom-theme .el-col-md-offset-3{margin-left:12.5%}.custom-theme .el-col-md-pull-3{position:relative;right:12.5%}.custom-theme .el-col-md-push-3{position:relative;left:12.5%}.custom-theme .el-col-md-4{width:16.66667%}.custom-theme .el-col-md-offset-4{margin-left:16.66667%}.custom-theme .el-col-md-pull-4{position:relative;right:16.66667%}.custom-theme .el-col-md-push-4{position:relative;left:16.66667%}.custom-theme .el-col-md-5{width:20.83333%}.custom-theme .el-col-md-offset-5{margin-left:20.83333%}.custom-theme .el-col-md-pull-5{position:relative;right:20.83333%}.custom-theme .el-col-md-push-5{position:relative;left:20.83333%}.custom-theme .el-col-md-6{width:25%}.custom-theme .el-col-md-offset-6{margin-left:25%}.custom-theme .el-col-md-pull-6{position:relative;right:25%}.custom-theme .el-col-md-push-6{position:relative;left:25%}.custom-theme .el-col-md-7{width:29.16667%}.custom-theme .el-col-md-offset-7{margin-left:29.16667%}.custom-theme .el-col-md-pull-7{position:relative;right:29.16667%}.custom-theme .el-col-md-push-7{position:relative;left:29.16667%}.custom-theme .el-col-md-8{width:33.33333%}.custom-theme .el-col-md-offset-8{margin-left:33.33333%}.custom-theme .el-col-md-pull-8{position:relative;right:33.33333%}.custom-theme .el-col-md-push-8{position:relative;left:33.33333%}.custom-theme .el-col-md-9{width:37.5%}.custom-theme .el-col-md-offset-9{margin-left:37.5%}.custom-theme .el-col-md-pull-9{position:relative;right:37.5%}.custom-theme .el-col-md-push-9{position:relative;left:37.5%}.custom-theme .el-col-md-10{width:41.66667%}.custom-theme .el-col-md-offset-10{margin-left:41.66667%}.custom-theme .el-col-md-pull-10{position:relative;right:41.66667%}.custom-theme .el-col-md-push-10{position:relative;left:41.66667%}.custom-theme .el-col-md-11{width:45.83333%}.custom-theme .el-col-md-offset-11{margin-left:45.83333%}.custom-theme .el-col-md-pull-11{position:relative;right:45.83333%}.custom-theme .el-col-md-push-11{position:relative;left:45.83333%}.custom-theme .el-col-md-12{width:50%}.custom-theme .el-col-md-offset-12{margin-left:50%}.custom-theme .el-col-md-pull-12{position:relative;right:50%}.custom-theme .el-col-md-push-12{position:relative;left:50%}.custom-theme .el-col-md-13{width:54.16667%}.custom-theme .el-col-md-offset-13{margin-left:54.16667%}.custom-theme .el-col-md-pull-13{position:relative;right:54.16667%}.custom-theme .el-col-md-push-13{position:relative;left:54.16667%}.custom-theme .el-col-md-14{width:58.33333%}.custom-theme .el-col-md-offset-14{margin-left:58.33333%}.custom-theme .el-col-md-pull-14{position:relative;right:58.33333%}.custom-theme .el-col-md-push-14{position:relative;left:58.33333%}.custom-theme .el-col-md-15{width:62.5%}.custom-theme .el-col-md-offset-15{margin-left:62.5%}.custom-theme .el-col-md-pull-15{position:relative;right:62.5%}.custom-theme .el-col-md-push-15{position:relative;left:62.5%}.custom-theme .el-col-md-16{width:66.66667%}.custom-theme .el-col-md-offset-16{margin-left:66.66667%}.custom-theme .el-col-md-pull-16{position:relative;right:66.66667%}.custom-theme .el-col-md-push-16{position:relative;left:66.66667%}.custom-theme .el-col-md-17{width:70.83333%}.custom-theme .el-col-md-offset-17{margin-left:70.83333%}.custom-theme .el-col-md-pull-17{position:relative;right:70.83333%}.custom-theme .el-col-md-push-17{position:relative;left:70.83333%}.custom-theme .el-col-md-18{width:75%}.custom-theme .el-col-md-offset-18{margin-left:75%}.custom-theme .el-col-md-pull-18{position:relative;right:75%}.custom-theme .el-col-md-push-18{position:relative;left:75%}.custom-theme .el-col-md-19{width:79.16667%}.custom-theme .el-col-md-offset-19{margin-left:79.16667%}.custom-theme .el-col-md-pull-19{position:relative;right:79.16667%}.custom-theme .el-col-md-push-19{position:relative;left:79.16667%}.custom-theme .el-col-md-20{width:83.33333%}.custom-theme .el-col-md-offset-20{margin-left:83.33333%}.custom-theme .el-col-md-pull-20{position:relative;right:83.33333%}.custom-theme .el-col-md-push-20{position:relative;left:83.33333%}.custom-theme .el-col-md-21{width:87.5%}.custom-theme .el-col-md-offset-21{margin-left:87.5%}.custom-theme .el-col-md-pull-21{position:relative;right:87.5%}.custom-theme .el-col-md-push-21{position:relative;left:87.5%}.custom-theme .el-col-md-22{width:91.66667%}.custom-theme .el-col-md-offset-22{margin-left:91.66667%}.custom-theme .el-col-md-pull-22{position:relative;right:91.66667%}.custom-theme .el-col-md-push-22{position:relative;left:91.66667%}.custom-theme .el-col-md-23{width:95.83333%}.custom-theme .el-col-md-offset-23{margin-left:95.83333%}.custom-theme .el-col-md-pull-23{position:relative;right:95.83333%}.custom-theme .el-col-md-push-23{position:relative;left:95.83333%}.custom-theme .el-col-md-24{width:100%}.custom-theme .el-col-md-offset-24{margin-left:100%}.custom-theme .el-col-md-pull-24{position:relative;right:100%}.custom-theme .el-col-md-push-24{position:relative;left:100%}}@media only screen and (min-width:1200px){.custom-theme .el-col-lg-0{display:none}.custom-theme .el-col-lg-1{width:4.16667%}.custom-theme .el-col-lg-offset-1{margin-left:4.16667%}.custom-theme .el-col-lg-pull-1{position:relative;right:4.16667%}.custom-theme .el-col-lg-push-1{position:relative;left:4.16667%}.custom-theme .el-col-lg-2{width:8.33333%}.custom-theme .el-col-lg-offset-2{margin-left:8.33333%}.custom-theme .el-col-lg-pull-2{position:relative;right:8.33333%}.custom-theme .el-col-lg-push-2{position:relative;left:8.33333%}.custom-theme .el-col-lg-3{width:12.5%}.custom-theme .el-col-lg-offset-3{margin-left:12.5%}.custom-theme .el-col-lg-pull-3{position:relative;right:12.5%}.custom-theme .el-col-lg-push-3{position:relative;left:12.5%}.custom-theme .el-col-lg-4{width:16.66667%}.custom-theme .el-col-lg-offset-4{margin-left:16.66667%}.custom-theme .el-col-lg-pull-4{position:relative;right:16.66667%}.custom-theme .el-col-lg-push-4{position:relative;left:16.66667%}.custom-theme .el-col-lg-5{width:20.83333%}.custom-theme .el-col-lg-offset-5{margin-left:20.83333%}.custom-theme .el-col-lg-pull-5{position:relative;right:20.83333%}.custom-theme .el-col-lg-push-5{position:relative;left:20.83333%}.custom-theme .el-col-lg-6{width:25%}.custom-theme .el-col-lg-offset-6{margin-left:25%}.custom-theme .el-col-lg-pull-6{position:relative;right:25%}.custom-theme .el-col-lg-push-6{position:relative;left:25%}.custom-theme .el-col-lg-7{width:29.16667%}.custom-theme .el-col-lg-offset-7{margin-left:29.16667%}.custom-theme .el-col-lg-pull-7{position:relative;right:29.16667%}.custom-theme .el-col-lg-push-7{position:relative;left:29.16667%}.custom-theme .el-col-lg-8{width:33.33333%}.custom-theme .el-col-lg-offset-8{margin-left:33.33333%}.custom-theme .el-col-lg-pull-8{position:relative;right:33.33333%}.custom-theme .el-col-lg-push-8{position:relative;left:33.33333%}.custom-theme .el-col-lg-9{width:37.5%}.custom-theme .el-col-lg-offset-9{margin-left:37.5%}.custom-theme .el-col-lg-pull-9{position:relative;right:37.5%}.custom-theme .el-col-lg-push-9{position:relative;left:37.5%}.custom-theme .el-col-lg-10{width:41.66667%}.custom-theme .el-col-lg-offset-10{margin-left:41.66667%}.custom-theme .el-col-lg-pull-10{position:relative;right:41.66667%}.custom-theme .el-col-lg-push-10{position:relative;left:41.66667%}.custom-theme .el-col-lg-11{width:45.83333%}.custom-theme .el-col-lg-offset-11{margin-left:45.83333%}.custom-theme .el-col-lg-pull-11{position:relative;right:45.83333%}.custom-theme .el-col-lg-push-11{position:relative;left:45.83333%}.custom-theme .el-col-lg-12{width:50%}.custom-theme .el-col-lg-offset-12{margin-left:50%}.custom-theme .el-col-lg-pull-12{position:relative;right:50%}.custom-theme .el-col-lg-push-12{position:relative;left:50%}.custom-theme .el-col-lg-13{width:54.16667%}.custom-theme .el-col-lg-offset-13{margin-left:54.16667%}.custom-theme .el-col-lg-pull-13{position:relative;right:54.16667%}.custom-theme .el-col-lg-push-13{position:relative;left:54.16667%}.custom-theme .el-col-lg-14{width:58.33333%}.custom-theme .el-col-lg-offset-14{margin-left:58.33333%}.custom-theme .el-col-lg-pull-14{position:relative;right:58.33333%}.custom-theme .el-col-lg-push-14{position:relative;left:58.33333%}.custom-theme .el-col-lg-15{width:62.5%}.custom-theme .el-col-lg-offset-15{margin-left:62.5%}.custom-theme .el-col-lg-pull-15{position:relative;right:62.5%}.custom-theme .el-col-lg-push-15{position:relative;left:62.5%}.custom-theme .el-col-lg-16{width:66.66667%}.custom-theme .el-col-lg-offset-16{margin-left:66.66667%}.custom-theme .el-col-lg-pull-16{position:relative;right:66.66667%}.custom-theme .el-col-lg-push-16{position:relative;left:66.66667%}.custom-theme .el-col-lg-17{width:70.83333%}.custom-theme .el-col-lg-offset-17{margin-left:70.83333%}.custom-theme .el-col-lg-pull-17{position:relative;right:70.83333%}.custom-theme .el-col-lg-push-17{position:relative;left:70.83333%}.custom-theme .el-col-lg-18{width:75%}.custom-theme .el-col-lg-offset-18{margin-left:75%}.custom-theme .el-col-lg-pull-18{position:relative;right:75%}.custom-theme .el-col-lg-push-18{position:relative;left:75%}.custom-theme .el-col-lg-19{width:79.16667%}.custom-theme .el-col-lg-offset-19{margin-left:79.16667%}.custom-theme .el-col-lg-pull-19{position:relative;right:79.16667%}.custom-theme .el-col-lg-push-19{position:relative;left:79.16667%}.custom-theme .el-col-lg-20{width:83.33333%}.custom-theme .el-col-lg-offset-20{margin-left:83.33333%}.custom-theme .el-col-lg-pull-20{position:relative;right:83.33333%}.custom-theme .el-col-lg-push-20{position:relative;left:83.33333%}.custom-theme .el-col-lg-21{width:87.5%}.custom-theme .el-col-lg-offset-21{margin-left:87.5%}.custom-theme .el-col-lg-pull-21{position:relative;right:87.5%}.custom-theme .el-col-lg-push-21{position:relative;left:87.5%}.custom-theme .el-col-lg-22{width:91.66667%}.custom-theme .el-col-lg-offset-22{margin-left:91.66667%}.custom-theme .el-col-lg-pull-22{position:relative;right:91.66667%}.custom-theme .el-col-lg-push-22{position:relative;left:91.66667%}.custom-theme .el-col-lg-23{width:95.83333%}.custom-theme .el-col-lg-offset-23{margin-left:95.83333%}.custom-theme .el-col-lg-pull-23{position:relative;right:95.83333%}.custom-theme .el-col-lg-push-23{position:relative;left:95.83333%}.custom-theme .el-col-lg-24{width:100%}.custom-theme .el-col-lg-offset-24{margin-left:100%}.custom-theme .el-col-lg-pull-24{position:relative;right:100%}.custom-theme .el-col-lg-push-24{position:relative;left:100%}}@media only screen and (min-width:1920px){.custom-theme .el-col-xl-0{display:none}.custom-theme .el-col-xl-1{width:4.16667%}.custom-theme .el-col-xl-offset-1{margin-left:4.16667%}.custom-theme .el-col-xl-pull-1{position:relative;right:4.16667%}.custom-theme .el-col-xl-push-1{position:relative;left:4.16667%}.custom-theme .el-col-xl-2{width:8.33333%}.custom-theme .el-col-xl-offset-2{margin-left:8.33333%}.custom-theme .el-col-xl-pull-2{position:relative;right:8.33333%}.custom-theme .el-col-xl-push-2{position:relative;left:8.33333%}.custom-theme .el-col-xl-3{width:12.5%}.custom-theme .el-col-xl-offset-3{margin-left:12.5%}.custom-theme .el-col-xl-pull-3{position:relative;right:12.5%}.custom-theme .el-col-xl-push-3{position:relative;left:12.5%}.custom-theme .el-col-xl-4{width:16.66667%}.custom-theme .el-col-xl-offset-4{margin-left:16.66667%}.custom-theme .el-col-xl-pull-4{position:relative;right:16.66667%}.custom-theme .el-col-xl-push-4{position:relative;left:16.66667%}.custom-theme .el-col-xl-5{width:20.83333%}.custom-theme .el-col-xl-offset-5{margin-left:20.83333%}.custom-theme .el-col-xl-pull-5{position:relative;right:20.83333%}.custom-theme .el-col-xl-push-5{position:relative;left:20.83333%}.custom-theme .el-col-xl-6{width:25%}.custom-theme .el-col-xl-offset-6{margin-left:25%}.custom-theme .el-col-xl-pull-6{position:relative;right:25%}.custom-theme .el-col-xl-push-6{position:relative;left:25%}.custom-theme .el-col-xl-7{width:29.16667%}.custom-theme .el-col-xl-offset-7{margin-left:29.16667%}.custom-theme .el-col-xl-pull-7{position:relative;right:29.16667%}.custom-theme .el-col-xl-push-7{position:relative;left:29.16667%}.custom-theme .el-col-xl-8{width:33.33333%}.custom-theme .el-col-xl-offset-8{margin-left:33.33333%}.custom-theme .el-col-xl-pull-8{position:relative;right:33.33333%}.custom-theme .el-col-xl-push-8{position:relative;left:33.33333%}.custom-theme .el-col-xl-9{width:37.5%}.custom-theme .el-col-xl-offset-9{margin-left:37.5%}.custom-theme .el-col-xl-pull-9{position:relative;right:37.5%}.custom-theme .el-col-xl-push-9{position:relative;left:37.5%}.custom-theme .el-col-xl-10{width:41.66667%}.custom-theme .el-col-xl-offset-10{margin-left:41.66667%}.custom-theme .el-col-xl-pull-10{position:relative;right:41.66667%}.custom-theme .el-col-xl-push-10{position:relative;left:41.66667%}.custom-theme .el-col-xl-11{width:45.83333%}.custom-theme .el-col-xl-offset-11{margin-left:45.83333%}.custom-theme .el-col-xl-pull-11{position:relative;right:45.83333%}.custom-theme .el-col-xl-push-11{position:relative;left:45.83333%}.custom-theme .el-col-xl-12{width:50%}.custom-theme .el-col-xl-offset-12{margin-left:50%}.custom-theme .el-col-xl-pull-12{position:relative;right:50%}.custom-theme .el-col-xl-push-12{position:relative;left:50%}.custom-theme .el-col-xl-13{width:54.16667%}.custom-theme .el-col-xl-offset-13{margin-left:54.16667%}.custom-theme .el-col-xl-pull-13{position:relative;right:54.16667%}.custom-theme .el-col-xl-push-13{position:relative;left:54.16667%}.custom-theme .el-col-xl-14{width:58.33333%}.custom-theme .el-col-xl-offset-14{margin-left:58.33333%}.custom-theme .el-col-xl-pull-14{position:relative;right:58.33333%}.custom-theme .el-col-xl-push-14{position:relative;left:58.33333%}.custom-theme .el-col-xl-15{width:62.5%}.custom-theme .el-col-xl-offset-15{margin-left:62.5%}.custom-theme .el-col-xl-pull-15{position:relative;right:62.5%}.custom-theme .el-col-xl-push-15{position:relative;left:62.5%}.custom-theme .el-col-xl-16{width:66.66667%}.custom-theme .el-col-xl-offset-16{margin-left:66.66667%}.custom-theme .el-col-xl-pull-16{position:relative;right:66.66667%}.custom-theme .el-col-xl-push-16{position:relative;left:66.66667%}.custom-theme .el-col-xl-17{width:70.83333%}.custom-theme .el-col-xl-offset-17{margin-left:70.83333%}.custom-theme .el-col-xl-pull-17{position:relative;right:70.83333%}.custom-theme .el-col-xl-push-17{position:relative;left:70.83333%}.custom-theme .el-col-xl-18{width:75%}.custom-theme .el-col-xl-offset-18{margin-left:75%}.custom-theme .el-col-xl-pull-18{position:relative;right:75%}.custom-theme .el-col-xl-push-18{position:relative;left:75%}.custom-theme .el-col-xl-19{width:79.16667%}.custom-theme .el-col-xl-offset-19{margin-left:79.16667%}.custom-theme .el-col-xl-pull-19{position:relative;right:79.16667%}.custom-theme .el-col-xl-push-19{position:relative;left:79.16667%}.custom-theme .el-col-xl-20{width:83.33333%}.custom-theme .el-col-xl-offset-20{margin-left:83.33333%}.custom-theme .el-col-xl-pull-20{position:relative;right:83.33333%}.custom-theme .el-col-xl-push-20{position:relative;left:83.33333%}.custom-theme .el-col-xl-21{width:87.5%}.custom-theme .el-col-xl-offset-21{margin-left:87.5%}.custom-theme .el-col-xl-pull-21{position:relative;right:87.5%}.custom-theme .el-col-xl-push-21{position:relative;left:87.5%}.custom-theme .el-col-xl-22{width:91.66667%}.custom-theme .el-col-xl-offset-22{margin-left:91.66667%}.custom-theme .el-col-xl-pull-22{position:relative;right:91.66667%}.custom-theme .el-col-xl-push-22{position:relative;left:91.66667%}.custom-theme .el-col-xl-23{width:95.83333%}.custom-theme .el-col-xl-offset-23{margin-left:95.83333%}.custom-theme .el-col-xl-pull-23{position:relative;right:95.83333%}.custom-theme .el-col-xl-push-23{position:relative;left:95.83333%}.custom-theme .el-col-xl-24{width:100%}.custom-theme .el-col-xl-offset-24{margin-left:100%}.custom-theme .el-col-xl-pull-24{position:relative;right:100%}.custom-theme .el-col-xl-push-24{position:relative;left:100%}}.custom-theme .el-progress{position:relative;line-height:1}.custom-theme .el-progress__text{font-size:14px;color:#5a5e66;display:inline-block;vertical-align:middle;margin-left:10px;line-height:1}.custom-theme .el-progress__text i{vertical-align:middle;display:block}.custom-theme .el-progress--circle{display:inline-block}.custom-theme .el-progress--circle .el-progress__text{position:absolute;top:50%;left:0;width:100%;text-align:center;margin:0;-webkit-transform:translate(0,-50%);transform:translate(0,-50%)}.custom-theme .el-progress--circle .el-progress__text i{vertical-align:middle;display:inline-block}.custom-theme .el-progress--without-text .el-progress__text{display:none}.custom-theme .el-progress--without-text .el-progress-bar{padding-right:0;margin-right:0;display:block}.custom-theme .el-progress--text-inside .el-progress-bar{padding-right:0;margin-right:0}.custom-theme .el-progress.is-success .el-progress-bar__inner{background-color:#409167}.custom-theme .el-progress.is-success .el-progress__text{color:#409167}.custom-theme .el-progress.is-exception .el-progress-bar__inner{background-color:#b3450e}.custom-theme .el-progress.is-exception .el-progress__text{color:#b3450e}.custom-theme .el-progress-bar{padding-right:50px;display:inline-block;vertical-align:middle;width:100%;margin-right:-55px;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-progress-bar__outer{height:6px;border-radius:100px;background-color:#e6ebf5;overflow:hidden;position:relative;vertical-align:middle}.custom-theme .el-progress-bar__inner{position:absolute;left:0;top:0;height:100%;background-color:#262729;text-align:right;border-radius:100px;line-height:1;white-space:nowrap}.custom-theme .el-progress-bar__inner::after{display:inline-block;content:"";height:100%;vertical-align:middle}.custom-theme .el-progress-bar__innerText{display:inline-block;vertical-align:middle;color:#fff;font-size:12px;margin:0 5px}@-webkit-keyframes progress{0%{background-position:0 0}100%{background-position:32px 0}}@keyframes progress{0%{background-position:0 0}100%{background-position:32px 0}}.custom-theme .el-upload{display:inline-block;text-align:center;cursor:pointer}.custom-theme .el-upload__input{display:none}.custom-theme .el-upload__tip{font-size:12px;color:#5a5e66;margin-top:7px}.custom-theme .el-upload iframe{position:absolute;z-index:-1;top:0;left:0;opacity:0}.custom-theme .el-upload--picture-card{background-color:#fbfdff;border:1px dashed #c0ccda;border-radius:6px;-webkit-box-sizing:border-box;box-sizing:border-box;width:148px;height:148px;cursor:pointer;line-height:146px;vertical-align:top}.custom-theme .el-upload--picture-card i{font-size:28px;color:#8c939d}.custom-theme .el-upload--picture-card:hover{border-color:#262729;color:#262729}.custom-theme .el-upload-dragger{background-color:#fff;border:1px dashed #d9d9d9;border-radius:6px;-webkit-box-sizing:border-box;box-sizing:border-box;width:360px;height:180px;text-align:center;cursor:pointer;position:relative;overflow:hidden}.custom-theme .el-upload-dragger .el-icon-upload{font-size:67px;color:#b4bccc;margin:40px 0 16px;line-height:50px}.custom-theme .el-upload-dragger+.el-upload__tip{text-align:center}.custom-theme .el-upload-dragger~.el-upload__files{border-top:1px solid #d8dce5;margin-top:7px;padding-top:5px}.custom-theme .el-upload-dragger .el-upload__text{color:#5a5e66;font-size:14px;text-align:center}.custom-theme .el-upload-dragger .el-upload__text em{color:#262729;font-style:normal}.custom-theme .el-upload-dragger:hover{border-color:#262729}.custom-theme .el-upload-dragger.is-dragover{background-color:rgba(32,159,255,.06);border:2px dashed #262729}.custom-theme .el-upload-list{margin:0;padding:0;list-style:none}.custom-theme .el-upload-list__item{-webkit-transition:all .5s cubic-bezier(.55,0,.1,1);transition:all .5s cubic-bezier(.55,0,.1,1);font-size:14px;color:#5a5e66;line-height:1.8;margin-top:5px;position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px;width:100%}.custom-theme .el-upload-list__item .el-progress{position:absolute;top:20px;width:100%}.custom-theme .el-upload-list__item .el-progress__text{position:absolute;right:0;top:-13px}.custom-theme .el-upload-list__item .el-progress-bar{margin-right:0;padding-right:0}.custom-theme .el-upload-list__item:first-child{margin-top:10px}.custom-theme .el-upload-list__item .el-icon-upload-success{color:#409167}.custom-theme .el-upload-list__item .el-icon-close{display:none;position:absolute;top:5px;right:5px;cursor:pointer;opacity:.75;color:#5a5e66}.custom-theme .el-upload-list__item .el-icon-close:hover{opacity:1}.custom-theme .el-upload-list__item .el-icon-close-tip{display:none;position:absolute;top:5px;right:0;cursor:pointer;opacity:1;color:#262729;-webkit-transform:translate(15%,0);transform:translate(15%,0)}.custom-theme .el-upload-list__item:hover{background-color:#f5f7fa}.custom-theme .el-upload-list__item:hover .el-icon-close{display:inline-block}.custom-theme .el-upload-list__item:hover .el-progress__text{display:none}.custom-theme .el-upload-list__item.is-success .el-upload-list__item-status-label{display:block}.custom-theme .el-upload-list__item.is-success .el-upload-list__item-name:focus,.custom-theme .el-upload-list__item.is-success .el-upload-list__item-name:hover{color:#262729;cursor:pointer}.custom-theme .el-upload-list__item.is-success:focus .el-icon-close-tip{display:inline-block}.custom-theme .el-upload-list__item.is-success:active,.custom-theme .el-upload-list__item.is-success:focus:not(.focusing){outline-width:0}.custom-theme .el-upload-list__item.is-success:active .el-icon-close-tip,.custom-theme .el-upload-list__item.is-success:focus:not(.focusing) .el-icon-close-tip{display:none}.custom-theme .el-upload-list__item.is-success:focus .el-upload-list__item-status-label,.custom-theme .el-upload-list__item.is-success:hover .el-upload-list__item-status-label{display:none}.custom-theme .el-upload-list.is-disabled .el-upload-list__item:hover .el-upload-list__item-status-label{display:block}.custom-theme .el-upload-list__item-name{color:#5a5e66;display:block;margin-right:40px;overflow:hidden;padding-left:4px;text-overflow:ellipsis;-webkit-transition:color .3s;transition:color .3s;white-space:nowrap}.custom-theme .el-upload-list__item-name [class^=el-icon]{height:100%;margin-right:7px;color:#878d99;line-height:inherit}.custom-theme .el-upload-list__item-status-label{position:absolute;right:5px;top:0;line-height:inherit;display:none}.custom-theme .el-upload-list__item-delete{position:absolute;right:10px;top:0;font-size:12px;color:#5a5e66;display:none}.custom-theme .el-upload-list__item-delete:hover{color:#262729}.custom-theme .el-upload-list--picture-card{margin:0;display:inline;vertical-align:top}.custom-theme .el-upload-list--picture-card .el-upload-list__item{overflow:hidden;background-color:#fff;border:1px solid #c0ccda;border-radius:6px;-webkit-box-sizing:border-box;box-sizing:border-box;width:148px;height:148px;margin:0 8px 8px 0;display:inline-block}.custom-theme .el-upload-list--picture-card .el-upload-list__item .el-icon-check,.custom-theme .el-upload-list--picture-card .el-upload-list__item .el-icon-circle-check{color:#fff}.custom-theme .el-upload-list--picture-card .el-upload-list__item .el-icon-close{display:none}.custom-theme .el-upload-list--picture-card .el-upload-list__item:hover .el-upload-list__item-status-label{display:none}.custom-theme .el-upload-list--picture-card .el-upload-list__item:hover .el-progress__text{display:block}.custom-theme .el-upload-list--picture-card .el-upload-list__item-name{display:none}.custom-theme .el-upload-list--picture-card .el-upload-list__item-thumbnail{width:100%;height:100%}.custom-theme .el-upload-list--picture-card .el-upload-list__item-status-label{position:absolute;right:-15px;top:-6px;width:40px;height:24px;background:#13ce66;text-align:center;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-box-shadow:0 0 1pc 1px rgba(0,0,0,.2);box-shadow:0 0 1pc 1px rgba(0,0,0,.2)}.custom-theme .el-upload-list--picture-card .el-upload-list__item-status-label i{font-size:12px;margin-top:11px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.custom-theme .el-upload-list--picture-card .el-upload-list__item-actions{position:absolute;width:100%;height:100%;left:0;top:0;cursor:default;text-align:center;color:#fff;opacity:0;font-size:20px;background-color:rgba(0,0,0,.5);-webkit-transition:opacity .3s;transition:opacity .3s}.custom-theme .el-upload-list--picture-card .el-upload-list__item-actions::after{display:inline-block;content:"";height:100%;vertical-align:middle}.custom-theme .el-upload-list--picture-card .el-upload-list__item-actions span{display:none;cursor:pointer}.custom-theme .el-upload-list--picture-card .el-upload-list__item-actions span+span{margin-left:15px}.custom-theme .el-upload-list--picture-card .el-upload-list__item-actions .el-upload-list__item-delete{position:static;font-size:inherit;color:inherit}.custom-theme .el-upload-list--picture-card .el-upload-list__item-actions:hover{opacity:1}.custom-theme .el-upload-list--picture-card .el-upload-list__item-actions:hover span{display:inline-block}.custom-theme .el-upload-list--picture-card .el-progress{top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);bottom:auto;width:126px}.custom-theme .el-upload-list--picture-card .el-progress .el-progress__text{top:50%}.custom-theme .el-upload-list--picture .el-upload-list__item{overflow:hidden;background-color:#fff;border:1px solid #c0ccda;border-radius:6px;-webkit-box-sizing:border-box;box-sizing:border-box;margin-top:10px;padding:10px 10px 10px 90px;height:92px}.custom-theme .el-upload-list--picture .el-upload-list__item .el-icon-check,.custom-theme .el-upload-list--picture .el-upload-list__item .el-icon-circle-check{color:#fff}.custom-theme .el-upload-list--picture .el-upload-list__item:hover .el-upload-list__item-status-label{background:0 0;-webkit-box-shadow:none;box-shadow:none;top:-2px;right:-12px}.custom-theme .el-upload-list--picture .el-upload-list__item:hover .el-progress__text{display:block}.custom-theme .el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name{line-height:70px;margin-top:0}.custom-theme .el-upload-list--picture .el-upload-list__item.is-success .el-upload-list__item-name i{display:none}.custom-theme .el-upload-list--picture .el-upload-list__item-thumbnail{vertical-align:middle;display:inline-block;width:70px;height:70px;float:left;position:relative;z-index:1;margin-left:-80px}.custom-theme .el-upload-list--picture .el-upload-list__item-name{display:block;margin-top:20px}.custom-theme .el-upload-list--picture .el-upload-list__item-name i{font-size:70px;line-height:1;position:absolute;left:9px;top:10px}.custom-theme .el-upload-list--picture .el-upload-list__item-status-label{position:absolute;right:-17px;top:-7px;width:46px;height:26px;background:#13ce66;text-align:center;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-box-shadow:0 1px 1px #ccc;box-shadow:0 1px 1px #ccc}.custom-theme .el-upload-list--picture .el-upload-list__item-status-label i{font-size:12px;margin-top:12px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg)}.custom-theme .el-upload-list--picture .el-progress{position:relative;top:-7px}.custom-theme .el-upload-cover{position:absolute;left:0;top:0;width:100%;height:100%;overflow:hidden;z-index:10;cursor:default}.custom-theme .el-upload-cover::after{display:inline-block;content:"";height:100%;vertical-align:middle}.custom-theme .el-upload-cover img{display:block;width:100%;height:100%}.custom-theme .el-upload-cover__label{position:absolute;right:-15px;top:-6px;width:40px;height:24px;background:#13ce66;text-align:center;-webkit-transform:rotate(45deg);transform:rotate(45deg);-webkit-box-shadow:0 0 1pc 1px rgba(0,0,0,.2);box-shadow:0 0 1pc 1px rgba(0,0,0,.2)}.custom-theme .el-upload-cover__label i{font-size:12px;margin-top:11px;-webkit-transform:rotate(-45deg);transform:rotate(-45deg);color:#fff}.custom-theme .el-upload-cover__progress{display:inline-block;vertical-align:middle;position:static;width:243px}.custom-theme .el-upload-cover__progress+.el-upload__inner{opacity:0}.custom-theme .el-upload-cover__content{position:absolute;top:0;left:0;width:100%;height:100%}.custom-theme .el-upload-cover__interact{position:absolute;bottom:0;left:0;width:100%;height:100%;background-color:rgba(0,0,0,.72);text-align:center}.custom-theme .el-upload-cover__interact .btn{display:inline-block;color:#fff;font-size:14px;cursor:pointer;vertical-align:middle;-webkit-transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s;transition:transform .3s cubic-bezier(.23,1,.32,1) .1s,opacity .3s cubic-bezier(.23,1,.32,1) .1s,-webkit-transform .3s cubic-bezier(.23,1,.32,1) .1s;margin-top:60px}.custom-theme .el-upload-cover__interact .btn i{margin-top:0}.custom-theme .el-upload-cover__interact .btn span{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.custom-theme .el-upload-cover__interact .btn:not(:first-child){margin-left:35px}.custom-theme .el-upload-cover__interact .btn:hover{-webkit-transform:translateY(-13px);transform:translateY(-13px)}.custom-theme .el-upload-cover__interact .btn:hover span{opacity:1}.custom-theme .el-upload-cover__interact .btn i{color:#fff;display:block;font-size:24px;line-height:inherit;margin:0 auto 5px}.custom-theme .el-upload-cover__title{position:absolute;bottom:0;left:0;background-color:#fff;height:36px;width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:400;text-align:left;padding:0 10px;margin:0;line-height:36px;font-size:14px;color:#2d2f33}.custom-theme .el-upload-cover+.el-upload__inner{opacity:0;position:relative;z-index:1}.custom-theme .el-progress{position:relative;line-height:1}.custom-theme .el-progress__text{font-size:14px;color:#5a5e66;display:inline-block;vertical-align:middle;margin-left:10px;line-height:1}.custom-theme .el-progress__text i{vertical-align:middle;display:block}.custom-theme .el-progress--circle{display:inline-block}.custom-theme .el-progress--circle .el-progress__text{position:absolute;top:50%;left:0;width:100%;text-align:center;margin:0;-webkit-transform:translate(0,-50%);transform:translate(0,-50%)}.custom-theme .el-progress--circle .el-progress__text i{vertical-align:middle;display:inline-block}.custom-theme .el-progress--without-text .el-progress__text{display:none}.custom-theme .el-progress--without-text .el-progress-bar{padding-right:0;margin-right:0;display:block}.custom-theme .el-progress--text-inside .el-progress-bar{padding-right:0;margin-right:0}.custom-theme .el-progress.is-success .el-progress-bar__inner{background-color:#409167}.custom-theme .el-progress.is-success .el-progress__text{color:#409167}.custom-theme .el-progress.is-exception .el-progress-bar__inner{background-color:#b3450e}.custom-theme .el-progress.is-exception .el-progress__text{color:#b3450e}.custom-theme .el-progress-bar{padding-right:50px;display:inline-block;vertical-align:middle;width:100%;margin-right:-55px;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-progress-bar__outer{height:6px;border-radius:100px;background-color:#e6ebf5;overflow:hidden;position:relative;vertical-align:middle}.custom-theme .el-progress-bar__inner{position:absolute;left:0;top:0;height:100%;background-color:#262729;text-align:right;border-radius:100px;line-height:1;white-space:nowrap}.custom-theme .el-progress-bar__inner::after{display:inline-block;content:"";height:100%;vertical-align:middle}.custom-theme .el-progress-bar__innerText{display:inline-block;vertical-align:middle;color:#fff;font-size:12px;margin:0 5px}@keyframes progress{0%{background-position:0 0}100%{background-position:32px 0}}.custom-theme .el-time-spinner{width:100%;white-space:nowrap}.custom-theme .el-spinner{display:inline-block;vertical-align:middle}.custom-theme .el-spinner-inner{-webkit-animation:rotate 2s linear infinite;animation:rotate 2s linear infinite;width:50px;height:50px}.custom-theme .el-spinner-inner .path{stroke:#ececec;stroke-linecap:round;-webkit-animation:dash 1.5s ease-in-out infinite;animation:dash 1.5s ease-in-out infinite}@-webkit-keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes rotate{100%{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@-webkit-keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}100%{stroke-dasharray:90,150;stroke-dashoffset:-124}}@keyframes dash{0%{stroke-dasharray:1,150;stroke-dashoffset:0}50%{stroke-dasharray:90,150;stroke-dashoffset:-35}100%{stroke-dasharray:90,150;stroke-dashoffset:-124}}.custom-theme .el-message{min-width:380px;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:4px;border-width:1px;border-style:solid;border-color:#e6ebf5;position:fixed;left:50%;top:20px;-webkit-transform:translateX(-50%);transform:translateX(-50%);background-color:#edf2fc;-webkit-transition:opacity .3s,-webkit-transform .4s;transition:opacity .3s,-webkit-transform .4s;transition:opacity .3s,transform .4s;transition:opacity .3s,transform .4s,-webkit-transform .4s;overflow:hidden;padding:15px 15px 15px 20px;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.custom-theme .el-message.is-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.custom-theme .el-message p{margin:0}.custom-theme .el-message--info .el-message__content{color:#0a76a4}.custom-theme .el-message--success{background-color:#ecf4f0;border-color:#d9e9e1}.custom-theme .el-message--success .el-message__content{color:#409167}.custom-theme .el-message--warning{background-color:#f5f6e6;border-color:#ebedce}.custom-theme .el-message--warning .el-message__content{color:#9da408}.custom-theme .el-message--error{background-color:#f7ece7;border-color:#f0dacf}.custom-theme .el-message--error .el-message__content{color:#b3450e}.custom-theme .el-message__icon{margin-right:10px}.custom-theme .el-message__content{padding:0;font-size:14px;line-height:1}.custom-theme .el-message__content:focus{outline-width:0}.custom-theme .el-message__closeBtn{position:absolute;top:50%;right:15px;-webkit-transform:translateY(-50%);transform:translateY(-50%);cursor:pointer;color:#b4bccc;font-size:16px}.custom-theme .el-message__closeBtn:focus{outline-width:0}.custom-theme .el-message__closeBtn:hover{color:#878d99}.custom-theme .el-message .el-icon-success{color:#409167}.custom-theme .el-message .el-icon-error{color:#b3450e}.custom-theme .el-message .el-icon-info{color:#0a76a4}.custom-theme .el-message .el-icon-warning{color:#9da408}.custom-theme .el-message-fade-enter,.custom-theme .el-message-fade-leave-active{opacity:0;-webkit-transform:translate(-50%,-100%);transform:translate(-50%,-100%)}.custom-theme .el-badge{position:relative;vertical-align:middle;display:inline-block}.custom-theme .el-badge__content{background-color:#b3450e;border-radius:10px;color:#fff;display:inline-block;font-size:12px;height:18px;line-height:18px;padding:0 6px;text-align:center;white-space:nowrap;border:1px solid #fff}.custom-theme .el-badge__content.is-fixed{position:absolute;top:0;right:10px;-webkit-transform:translateY(-50%) translateX(100%);transform:translateY(-50%) translateX(100%)}.custom-theme .el-badge__content.is-fixed.is-dot{right:5px}.custom-theme .el-badge__content.is-dot{height:8px;width:8px;padding:0;right:0;border-radius:50%}.custom-theme .el-card{border-radius:4px;border:1px solid #e6ebf5;background-color:#fff;overflow:hidden;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1);color:#2d2f33}.custom-theme .el-card__header{padding:18px 20px;border-bottom:1px solid #e6ebf5;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-card__body{padding:20px}.custom-theme .el-rate{height:20px;line-height:1}.custom-theme .el-rate:active,.custom-theme .el-rate:focus{outline-width:0}.custom-theme .el-rate__item{display:inline-block;position:relative;font-size:0;vertical-align:middle}.custom-theme .el-rate__icon{position:relative;display:inline-block;font-size:18px;margin-right:6px;color:#b4bccc;-webkit-transition:.3s;transition:.3s}.custom-theme .el-rate__icon.hover{-webkit-transform:scale(1.15);transform:scale(1.15)}.custom-theme .el-rate__icon .path2{position:absolute;left:0;top:0}.custom-theme .el-rate__decimal{position:absolute;top:0;left:0;display:inline-block;overflow:hidden}.custom-theme .el-rate__text{font-size:14px;vertical-align:middle}.custom-theme .el-steps{display:-webkit-box;display:-ms-flexbox;display:flex}.custom-theme .el-steps--simple{padding:13px 8%;border-radius:4px;background:#f5f7fa}.custom-theme .el-steps--horizontal{white-space:nowrap}.custom-theme .el-steps--vertical{height:100%;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-flow:column;flex-flow:column}.custom-theme .el-step{position:relative;-ms-flex-negative:1;flex-shrink:1}.custom-theme .el-step:last-of-type .el-step__line{display:none}.custom-theme .el-step:last-of-type.is-flex{-ms-flex-preferred-size:auto!important;flex-basis:auto!important;-ms-flex-negative:0;flex-shrink:0;-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0}.custom-theme .el-step:last-of-type .el-step__description,.custom-theme .el-step:last-of-type .el-step__main{padding-right:0}.custom-theme .el-step__head{position:relative;width:100%}.custom-theme .el-step__head.is-process{color:#2d2f33;border-color:#2d2f33}.custom-theme .el-step__head.is-wait{color:#b4bccc;border-color:#b4bccc}.custom-theme .el-step__head.is-success{color:#409167;border-color:#409167}.custom-theme .el-step__head.is-error{color:#b3450e;border-color:#b3450e}.custom-theme .el-step__head.is-finish{color:#262729;border-color:#262729}.custom-theme .el-step__icon{position:relative;z-index:1;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;width:24px;height:24px;font-size:14px;-webkit-box-sizing:border-box;box-sizing:border-box;background:#fff;-webkit-transition:.15s ease-out;transition:.15s ease-out}.custom-theme .el-step__icon.is-text{border-radius:50%;border:2px solid;border-color:inherit}.custom-theme .el-step__icon.is-icon{width:40px}.custom-theme .el-step__icon-inner{display:inline-block;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;text-align:center;font-weight:700;line-height:1;color:inherit}.custom-theme .el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:25px;font-weight:400}.custom-theme .el-step__icon-inner.is-status{-webkit-transform:translateY(1px);transform:translateY(1px)}.custom-theme .el-step__line{position:absolute;border-color:inherit;background-color:#b4bccc}.custom-theme .el-step__line-inner{display:block;border-width:1px;border-style:solid;border-color:inherit;-webkit-transition:.15s ease-out;transition:.15s ease-out;-webkit-box-sizing:border-box;box-sizing:border-box;width:0;height:0}.custom-theme .el-step__main{white-space:normal;text-align:left}.custom-theme .el-step__title{font-size:16px;line-height:38px}.custom-theme .el-step__title.is-process{font-weight:700;color:#2d2f33}.custom-theme .el-step__title.is-wait{color:#b4bccc}.custom-theme .el-step__title.is-success{color:#409167}.custom-theme .el-step__title.is-error{color:#b3450e}.custom-theme .el-step__title.is-finish{color:#262729}.custom-theme .el-step__description{padding-right:10%;margin-top:-5px;font-size:12px;line-height:20px;font-weight:400}.custom-theme .el-step__description.is-process{color:#2d2f33}.custom-theme .el-step__description.is-wait{color:#b4bccc}.custom-theme .el-step__description.is-success{color:#409167}.custom-theme .el-step__description.is-error{color:#b3450e}.custom-theme .el-step__description.is-finish{color:#262729}.custom-theme .el-step.is-horizontal{display:inline-block}.custom-theme .el-step.is-horizontal .el-step__line{height:2px;top:11px;left:0;right:0}.custom-theme .el-step.is-vertical{display:-webkit-box;display:-ms-flexbox;display:flex}.custom-theme .el-step.is-vertical .el-step__head{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;width:24px}.custom-theme .el-step.is-vertical .el-step__main{padding-left:10px;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.custom-theme .el-step.is-vertical .el-step__title{line-height:24px;padding-bottom:8px}.custom-theme .el-step.is-vertical .el-step__line{width:2px;top:0;bottom:0;left:11px}.custom-theme .el-step.is-vertical .el-step__icon.is-icon{width:24px}.custom-theme .el-step.is-center .el-step__head{text-align:center}.custom-theme .el-step.is-center .el-step__main{text-align:center}.custom-theme .el-step.is-center .el-step__description{padding-left:20%;padding-right:20%}.custom-theme .el-step.is-center .el-step__line{left:50%;right:-50%}.custom-theme .el-step.is-simple{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.custom-theme .el-step.is-simple .el-step__head{width:auto;font-size:0;padding-right:10px}.custom-theme .el-step.is-simple .el-step__icon{background:0 0;width:16px;height:16px;font-size:12px}.custom-theme .el-step.is-simple .el-step__icon-inner[class*=el-icon]:not(.is-status){font-size:18px}.custom-theme .el-step.is-simple .el-step__icon-inner.is-status{-webkit-transform:scale(.8) translateY(1px);transform:scale(.8) translateY(1px)}.custom-theme .el-step.is-simple .el-step__main{position:relative;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.custom-theme .el-step.is-simple .el-step__title{font-size:16px;line-height:20px}.custom-theme .el-step.is-simple:not(:last-of-type) .el-step__title{max-width:50%;word-break:break-all}.custom-theme .el-step.is-simple .el-step__arrow{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.custom-theme .el-step.is-simple .el-step__arrow::after,.custom-theme .el-step.is-simple .el-step__arrow::before{content:'';display:inline-block;position:absolute;height:15px;width:1px;background:#b4bccc}.custom-theme .el-step.is-simple .el-step__arrow::before{-webkit-transform:rotate(-45deg) translateY(-4px);transform:rotate(-45deg) translateY(-4px);-webkit-transform-origin:0 0;transform-origin:0 0}.custom-theme .el-step.is-simple .el-step__arrow::after{-webkit-transform:rotate(45deg) translateY(4px);transform:rotate(45deg) translateY(4px);-webkit-transform-origin:100% 100%;transform-origin:100% 100%}.custom-theme .el-step.is-simple:last-of-type .el-step__arrow{display:none}.custom-theme .el-carousel{overflow-x:hidden;position:relative}.custom-theme .el-carousel__container{position:relative;height:300px}.custom-theme .el-carousel__arrow{border:none;outline:0;padding:0;margin:0;height:36px;width:36px;cursor:pointer;-webkit-transition:.3s;transition:.3s;border-radius:50%;background-color:rgba(31,45,61,.11);color:#fff;position:absolute;top:50%;z-index:10;-webkit-transform:translateY(-50%);transform:translateY(-50%);text-align:center;font-size:12px}.custom-theme .el-carousel__arrow--left{left:16px}.custom-theme .el-carousel__arrow--right{right:16px}.custom-theme .el-carousel__arrow:hover{background-color:rgba(31,45,61,.23)}.custom-theme .el-carousel__arrow i{cursor:pointer}.custom-theme .el-carousel__indicators{position:absolute;list-style:none;bottom:0;left:50%;-webkit-transform:translateX(-50%);transform:translateX(-50%);margin:0;padding:0;z-index:2}.custom-theme .el-carousel__indicators--outside{bottom:26px;text-align:center;position:static;-webkit-transform:none;transform:none}.custom-theme .el-carousel__indicators--outside .el-carousel__indicator:hover button{opacity:.64}.custom-theme .el-carousel__indicators--outside button{background-color:#b4bccc;opacity:.24}.custom-theme .el-carousel__indicators--labels{left:0;right:0;-webkit-transform:none;transform:none;text-align:center}.custom-theme .el-carousel__indicators--labels .el-carousel__button{height:auto;width:auto;padding:2px 18px;font-size:12px}.custom-theme .el-carousel__indicators--labels .el-carousel__indicator{padding:6px 4px}.custom-theme .el-carousel__indicator{display:inline-block;background-color:transparent;padding:12px 4px;cursor:pointer}.custom-theme .el-carousel__indicator:hover button{opacity:.72}.custom-theme .el-carousel__indicator.is-active button{opacity:1}.custom-theme .el-carousel__button{display:block;opacity:.48;width:30px;height:2px;background-color:#fff;border:none;outline:0;padding:0;margin:0;cursor:pointer;-webkit-transition:.3s;transition:.3s}.custom-theme .carousel-arrow-left-enter,.custom-theme .carousel-arrow-left-leave-active{-webkit-transform:translateY(-50%) translateX(-10px);transform:translateY(-50%) translateX(-10px);opacity:0}.custom-theme .carousel-arrow-right-enter,.custom-theme .carousel-arrow-right-leave-active{-webkit-transform:translateY(-50%) translateX(10px);transform:translateY(-50%) translateX(10px);opacity:0}.custom-theme .el-scrollbar{overflow:hidden;position:relative}.custom-theme .el-scrollbar:active>.el-scrollbar__bar,.custom-theme .el-scrollbar:focus>.el-scrollbar__bar,.custom-theme .el-scrollbar:hover>.el-scrollbar__bar{opacity:1;-webkit-transition:opacity 340ms ease-out;transition:opacity 340ms ease-out}.custom-theme .el-scrollbar__wrap{overflow:scroll;height:100%}.custom-theme .el-scrollbar__wrap--hidden-default::-webkit-scrollbar{width:0;height:0}.custom-theme .el-scrollbar__thumb{position:relative;display:block;width:0;height:0;cursor:pointer;border-radius:inherit;background-color:rgba(135,141,153,.3);-webkit-transition:.3s background-color;transition:.3s background-color}.custom-theme .el-scrollbar__thumb:hover{background-color:rgba(135,141,153,.5)}.custom-theme .el-scrollbar__bar{position:absolute;right:2px;bottom:2px;z-index:1;border-radius:4px;opacity:0;-webkit-transition:opacity 120ms ease-out;transition:opacity 120ms ease-out}.custom-theme .el-scrollbar__bar.is-vertical{width:6px;top:2px}.custom-theme .el-scrollbar__bar.is-vertical>div{width:100%}.custom-theme .el-scrollbar__bar.is-horizontal{height:6px;left:2px}.custom-theme .el-scrollbar__bar.is-horizontal>div{height:100%}.custom-theme .el-carousel__item{position:absolute;top:0;left:0;width:100%;height:100%;display:inline-block;overflow:hidden;z-index:0}.custom-theme .el-carousel__item.is-active{z-index:2}.custom-theme .el-carousel__item.is-animating{-webkit-transition:-webkit-transform .4s ease-in-out;transition:-webkit-transform .4s ease-in-out;transition:transform .4s ease-in-out;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out}.custom-theme .el-carousel__item--card{width:50%;-webkit-transition:-webkit-transform .4s ease-in-out;transition:-webkit-transform .4s ease-in-out;transition:transform .4s ease-in-out;transition:transform .4s ease-in-out,-webkit-transform .4s ease-in-out}.custom-theme .el-carousel__item--card.is-in-stage{cursor:pointer;z-index:1}.custom-theme .el-carousel__item--card.is-in-stage.is-hover .el-carousel__mask,.custom-theme .el-carousel__item--card.is-in-stage:hover .el-carousel__mask{opacity:.12}.custom-theme .el-carousel__item--card.is-active{z-index:2}.custom-theme .el-carousel__mask{position:absolute;width:100%;height:100%;top:0;left:0;background-color:#fff;opacity:.24;-webkit-transition:.2s;transition:.2s}.custom-theme .el-collapse{border-top:1px solid #e6ebf5;border-bottom:1px solid #e6ebf5}.custom-theme .el-collapse-item__header{height:48px;line-height:48px;background-color:#fff;color:#2d2f33;cursor:pointer;border-bottom:1px solid #e6ebf5;font-size:13px;font-weight:500;-webkit-transition:border-bottom-color .3s;transition:border-bottom-color .3s}.custom-theme .el-collapse-item__header:active,.custom-theme .el-collapse-item__header:focus:not(.focusing){outline-width:0}.custom-theme .el-collapse-item__arrow{margin-right:8px;-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;float:right;line-height:48px;font-weight:300}.custom-theme .el-collapse-item__wrap{will-change:height;background-color:#fff;overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;border-bottom:1px solid #e6ebf5}.custom-theme .el-collapse-item__content{padding-bottom:25px;font-size:13px;color:#2d2f33;line-height:1.769230769230769}.custom-theme .el-collapse-item.is-active .el-collapse-item__header{border-bottom-color:transparent}.custom-theme .el-collapse-item.is-active .el-collapse-item__header .el-collapse-item__arrow{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.custom-theme .el-collapse-item:last-child{margin-bottom:-1px}.custom-theme .el-input{position:relative;font-size:14px;display:inline-block;width:100%}.custom-theme .el-input::-webkit-scrollbar{z-index:11;width:6px}.custom-theme .el-input::-webkit-scrollbar:horizontal{height:6px}.custom-theme .el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.custom-theme .el-input::-webkit-scrollbar-corner{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.custom-theme .el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #d8dce5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#5a5e66;display:inline-block;font-size:inherit;height:40px;line-height:1;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.custom-theme .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input__inner:hover{border-color:#b4bccc}.custom-theme .el-input__inner:focus{outline:0;border-color:#262729}.custom-theme .el-input__suffix{position:absolute;height:100%;right:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s;pointer-events:none}.custom-theme .el-input__suffix-inner{pointer-events:all}.custom-theme .el-input__prefix{position:absolute;height:100%;left:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s}.custom-theme .el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.custom-theme .el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.custom-theme .el-input__validateIcon{pointer-events:none}.custom-theme .el-input.is-active .el-input__inner{outline:0;border-color:#262729}.custom-theme .el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__icon{cursor:not-allowed}.custom-theme .el-input--suffix .el-input__inner{padding-right:30px}.custom-theme .el-input--prefix .el-input__inner{padding-left:30px}.custom-theme .el-input--medium{font-size:14px}.custom-theme .el-input--medium .el-input__inner{height:36px}.custom-theme .el-input--medium .el-input__icon{line-height:36px}.custom-theme .el-input--small{font-size:13px}.custom-theme .el-input--small .el-input__inner{height:32px}.custom-theme .el-input--small .el-input__icon{line-height:32px}.custom-theme .el-input--mini{font-size:12px}.custom-theme .el-input--mini .el-input__inner{height:28px}.custom-theme .el-input--mini .el-input__icon{line-height:28px}.custom-theme .el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.custom-theme .el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.custom-theme .el-input-group__append,.custom-theme .el-input-group__prepend{background-color:#f5f7fa;color:#0a76a4;vertical-align:middle;display:table-cell;position:relative;border:1px solid #d8dce5;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.custom-theme .el-input-group__append:focus,.custom-theme .el-input-group__prepend:focus{outline:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-select,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-select{display:inline-block;margin:-20px}.custom-theme .el-input-group__append button.el-button,.custom-theme .el-input-group__append div.el-select .el-input__inner,.custom-theme .el-input-group__append div.el-select:hover .el-input__inner,.custom-theme .el-input-group__prepend button.el-button,.custom-theme .el-input-group__prepend div.el-select .el-input__inner,.custom-theme .el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-input,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-input{font-size:inherit}.custom-theme .el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-input-group__append{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--prepend .el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--append .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-textarea{display:inline-block;width:100%;vertical-align:bottom}.custom-theme .el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:14px;color:#5a5e66;background-color:#fff;background-image:none;border:1px solid #d8dce5;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:hover{border-color:#b4bccc}.custom-theme .el-textarea__inner:focus{outline:0;border-color:#262729}.custom-theme .el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-popper .popper__arrow,.custom-theme .el-popper .popper__arrow::after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.custom-theme .el-popper .popper__arrow{border-width:6px;-webkit-filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03));filter:drop-shadow(0 2px 12px rgba(0, 0, 0, .03))}.custom-theme .el-popper .popper__arrow::after{content:" ";border-width:6px}.custom-theme .el-popper[x-placement^=top]{margin-bottom:12px}.custom-theme .el-popper[x-placement^=top] .popper__arrow{bottom:-6px;left:50%;margin-right:3px;border-top-color:#e6ebf5;border-bottom-width:0}.custom-theme .el-popper[x-placement^=top] .popper__arrow::after{bottom:1px;margin-left:-6px;border-top-color:#fff;border-bottom-width:0}.custom-theme .el-popper[x-placement^=bottom]{margin-top:12px}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow{top:-6px;left:50%;margin-right:3px;border-top-width:0;border-bottom-color:#e6ebf5}.custom-theme .el-popper[x-placement^=bottom] .popper__arrow::after{top:1px;margin-left:-6px;border-top-width:0;border-bottom-color:#fff}.custom-theme .el-popper[x-placement^=right]{margin-left:12px}.custom-theme .el-popper[x-placement^=right] .popper__arrow{top:50%;left:-6px;margin-bottom:3px;border-right-color:#e6ebf5;border-left-width:0}.custom-theme .el-popper[x-placement^=right] .popper__arrow::after{bottom:-6px;left:1px;border-right-color:#fff;border-left-width:0}.custom-theme .el-popper[x-placement^=left]{margin-right:12px}.custom-theme .el-popper[x-placement^=left] .popper__arrow{top:50%;right:-6px;margin-bottom:3px;border-right-width:0;border-left-color:#e6ebf5}.custom-theme .el-popper[x-placement^=left] .popper__arrow::after{right:1px;bottom:-6px;margin-left:-6px;border-right-width:0;border-left-color:#fff}.custom-theme .el-cascader{display:inline-block;position:relative;font-size:14px;line-height:40px}.custom-theme .el-cascader .el-input,.custom-theme .el-cascader .el-input__inner{cursor:pointer}.custom-theme .el-cascader .el-input__icon{-webkit-transition:none;transition:none}.custom-theme .el-cascader .el-icon-arrow-down{-webkit-transition:-webkit-transform .3s;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;font-size:14px}.custom-theme .el-cascader .el-icon-arrow-down.is-reverse{-webkit-transform:rotateZ(180deg);transform:rotateZ(180deg)}.custom-theme .el-cascader .el-icon-circle-close{z-index:2;-webkit-transition:color .2s cubic-bezier(.645,.045,.355,1);transition:color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-cascader .el-icon-circle-close:hover{color:#878d99}.custom-theme .el-cascader__clearIcon{z-index:2;position:relative}.custom-theme .el-cascader__label{position:absolute;left:0;top:0;height:100%;padding:0 25px 0 15px;color:#5a5e66;width:100%;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:pointer;text-align:left;font-size:inherit}.custom-theme .el-cascader__label span{color:#000}.custom-theme .el-cascader--medium{font-size:14px;line-height:36px}.custom-theme .el-cascader--small{font-size:13px;line-height:32px}.custom-theme .el-cascader--mini{font-size:12px;line-height:28px}.custom-theme .el-cascader.is-disabled .el-cascader__label{z-index:2;color:#b4bccc}.custom-theme .el-cascader-menus{white-space:nowrap;background:#fff;position:absolute;margin:5px 0;z-index:2;border:solid 1px #dfe4ed;border-radius:2px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.custom-theme .el-cascader-menus .popper__arrow{-webkit-transform:translateX(-400%);transform:translateX(-400%)}.custom-theme .el-cascader-menu{display:inline-block;vertical-align:top;height:204px;overflow:auto;border-right:solid 1px #dfe4ed;background-color:#fff;-webkit-box-sizing:border-box;box-sizing:border-box;margin:0;padding:6px 0;min-width:160px}.custom-theme .el-cascader-menu:last-child{border-right:0}.custom-theme .el-cascader-menu__item{font-size:14px;padding:8px 20px;position:relative;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color:#5a5e66;height:34px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:pointer}.custom-theme .el-cascader-menu__item--extensible:after{font-family:element-icons;content:"\e604";font-size:14px;color:#bfcbd9;position:absolute;right:15px}.custom-theme .el-cascader-menu__item.is-disabled{color:#b4bccc;background-color:#fff;cursor:not-allowed}.custom-theme .el-cascader-menu__item.is-disabled:hover{background-color:#fff}.custom-theme .el-cascader-menu__item.is-active{color:#262729}.custom-theme .el-cascader-menu__item:hover{background-color:#f5f7fa}.custom-theme .el-cascader-menu__item.selected{color:#fff;background-color:#f5f7fa}.custom-theme .el-cascader-menu__item__keyword{font-weight:700}.custom-theme .el-cascader-menu--flexible{height:auto;max-height:180px;overflow:auto}.custom-theme .el-cascader-menu--flexible .el-cascader-menu__item{overflow:visible}.custom-theme .el-color-hue-slider{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;width:280px;height:12px;background-color:red;padding:0 2px}.custom-theme .el-color-hue-slider__bar{position:relative;background:-webkit-gradient(linear,left top,right top,from(red),color-stop(17%,#ff0),color-stop(33%,#0f0),color-stop(50%,#0ff),color-stop(67%,#00f),color-stop(83%,#f0f),to(red));background:linear-gradient(to right,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%);height:100%}.custom-theme .el-color-hue-slider__thumb{position:absolute;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid #f0f0f0;-webkit-box-shadow:0 0 2px rgba(0,0,0,.6);box-shadow:0 0 2px rgba(0,0,0,.6);z-index:1}.custom-theme .el-color-hue-slider.is-vertical{width:12px;height:180px;padding:2px 0}.custom-theme .el-color-hue-slider.is-vertical .el-color-hue-slider__bar{background:-webkit-gradient(linear,left top,left bottom,from(red),color-stop(17%,#ff0),color-stop(33%,#0f0),color-stop(50%,#0ff),color-stop(67%,#00f),color-stop(83%,#f0f),to(red));background:linear-gradient(to bottom,red 0,#ff0 17%,#0f0 33%,#0ff 50%,#00f 67%,#f0f 83%,red 100%)}.custom-theme .el-color-hue-slider.is-vertical .el-color-hue-slider__thumb{left:0;top:0;width:100%;height:4px}.custom-theme .el-color-svpanel{position:relative;width:280px;height:180px}.custom-theme .el-color-svpanel__black,.custom-theme .el-color-svpanel__white{position:absolute;top:0;left:0;right:0;bottom:0}.custom-theme .el-color-svpanel__white{background:-webkit-gradient(linear,left top,right top,from(#fff),to(rgba(255,255,255,0)));background:linear-gradient(to right,#fff,rgba(255,255,255,0))}.custom-theme .el-color-svpanel__black{background:-webkit-gradient(linear,left bottom,left top,from(#000),to(transparent));background:linear-gradient(to top,#000,transparent)}.custom-theme .el-color-svpanel__cursor{position:absolute}.custom-theme .el-color-svpanel__cursor>div{cursor:head;width:4px;height:4px;-webkit-box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px rgba(0,0,0,.3),0 0 1px 2px rgba(0,0,0,.4);box-shadow:0 0 0 1.5px #fff,inset 0 0 1px 1px rgba(0,0,0,.3),0 0 1px 2px rgba(0,0,0,.4);border-radius:50%;-webkit-transform:translate(-2px,-2px);transform:translate(-2px,-2px)}.custom-theme .el-color-alpha-slider{position:relative;-webkit-box-sizing:border-box;box-sizing:border-box;width:280px;height:12px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.custom-theme .el-color-alpha-slider__bar{position:relative;background:-webkit-gradient(linear,left top,right top,from(rgba(255,255,255,0)),to(white));background:linear-gradient(to right,rgba(255,255,255,0) 0,#fff 100%);height:100%}.custom-theme .el-color-alpha-slider__thumb{position:absolute;cursor:pointer;-webkit-box-sizing:border-box;box-sizing:border-box;left:0;top:0;width:4px;height:100%;border-radius:1px;background:#fff;border:1px solid #f0f0f0;-webkit-box-shadow:0 0 2px rgba(0,0,0,.6);box-shadow:0 0 2px rgba(0,0,0,.6);z-index:1}.custom-theme .el-color-alpha-slider.is-vertical{width:20px;height:180px}.custom-theme .el-color-alpha-slider.is-vertical .el-color-alpha-slider__bar{background:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,0)),to(white));background:linear-gradient(to bottom,rgba(255,255,255,0) 0,#fff 100%)}.custom-theme .el-color-alpha-slider.is-vertical .el-color-alpha-slider__thumb{left:0;top:0;width:100%;height:4px}.custom-theme .el-color-dropdown{width:300px}.custom-theme .el-color-dropdown__main-wrapper{margin-bottom:6px}.custom-theme .el-color-dropdown__main-wrapper::after{content:"";display:table;clear:both}.custom-theme .el-color-dropdown__btns{margin-top:6px;text-align:right}.custom-theme .el-color-dropdown__value{float:left;line-height:26px;font-size:12px;color:#000;width:160px}.custom-theme .el-color-dropdown__btn{border:1px solid #dcdcdc;color:#333;line-height:24px;border-radius:2px;padding:0 20px;cursor:pointer;background-color:transparent;outline:0;font-size:12px}.custom-theme .el-color-dropdown__btn[disabled]{color:#ccc;cursor:not-allowed}.custom-theme .el-color-dropdown__btn:hover{color:#262729;border-color:#262729}.custom-theme .el-color-dropdown__link-btn{cursor:pointer;color:#262729;text-decoration:none;padding:15px;font-size:12px}.custom-theme .el-color-dropdown__link-btn:hover{color:tint(#262729,20%)}.custom-theme .el-color-picker{display:inline-block;position:relative;line-height:normal;height:40px}.custom-theme .el-color-picker.is-disabled .el-color-picker__trigger{cursor:not-allowed}.custom-theme .el-color-picker--medium{height:36px}.custom-theme .el-color-picker--medium .el-color-picker__trigger{height:36px;width:36px}.custom-theme .el-color-picker--medium .el-color-picker__mask{height:34px;width:34px}.custom-theme .el-color-picker--small{height:32px}.custom-theme .el-color-picker--small .el-color-picker__trigger{height:32px;width:32px}.custom-theme .el-color-picker--small .el-color-picker__mask{height:30px;width:30px}.custom-theme .el-color-picker--small .el-color-picker__empty,.custom-theme .el-color-picker--small .el-color-picker__icon{-webkit-transform:translate3d(-50%,-50%,0) scale(.8);transform:translate3d(-50%,-50%,0) scale(.8)}.custom-theme .el-color-picker--mini{height:28px}.custom-theme .el-color-picker--mini .el-color-picker__trigger{height:28px;width:28px}.custom-theme .el-color-picker--mini .el-color-picker__mask{height:26px;width:26px}.custom-theme .el-color-picker--mini .el-color-picker__empty,.custom-theme .el-color-picker--mini .el-color-picker__icon{-webkit-transform:translate3d(-50%,-50%,0) scale(.8);transform:translate3d(-50%,-50%,0) scale(.8)}.custom-theme .el-color-picker__mask{height:38px;width:38px;border-radius:4px;position:absolute;top:1px;left:1px;z-index:1;cursor:not-allowed;background-color:rgba(255,255,255,.7)}.custom-theme .el-color-picker__trigger{display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;height:40px;width:40px;padding:4px;border:1px solid #e6e6e6;border-radius:4px;font-size:0;position:relative;cursor:pointer}.custom-theme .el-color-picker__color{position:relative;display:block;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #999;border-radius:2px;width:100%;height:100%;text-align:center}.custom-theme .el-color-picker__color.is-alpha{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAIAAADZF8uwAAAAGUlEQVQYV2M4gwH+YwCGIasIUwhT25BVBADtzYNYrHvv4gAAAABJRU5ErkJggg==)}.custom-theme .el-color-picker__color-inner{position:absolute;left:0;top:0;right:0;bottom:0}.custom-theme .el-color-picker__empty{font-size:12px;color:#999;position:absolute;top:50%;left:50%;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0)}.custom-theme .el-color-picker__icon{display:inline-block;position:absolute;width:100%;top:50%;left:50%;-webkit-transform:translate3d(-50%,-50%,0);transform:translate3d(-50%,-50%,0);color:#fff;text-align:center;font-size:12px}.custom-theme .el-color-picker__panel{position:absolute;z-index:10;padding:6px;background-color:#fff;border:1px solid #e6ebf5;border-radius:4px;-webkit-box-shadow:0 2px 12px 0 rgba(0,0,0,.1);box-shadow:0 2px 12px 0 rgba(0,0,0,.1)}.custom-theme .el-input{position:relative;font-size:14px;display:inline-block;width:100%}.custom-theme .el-input::-webkit-scrollbar{z-index:11;width:6px}.custom-theme .el-input::-webkit-scrollbar:horizontal{height:6px}.custom-theme .el-input::-webkit-scrollbar-thumb{border-radius:5px;width:6px;background:#b4bccc}.custom-theme .el-input::-webkit-scrollbar-corner{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track{background:#fff}.custom-theme .el-input::-webkit-scrollbar-track-piece{background:#fff;width:6px}.custom-theme .el-input__inner{-webkit-appearance:none;background-color:#fff;background-image:none;border-radius:4px;border:1px solid #d8dce5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#5a5e66;display:inline-block;font-size:inherit;height:40px;line-height:1;outline:0;padding:0 15px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1);width:100%}.custom-theme .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input__inner:hover{border-color:#b4bccc}.custom-theme .el-input__inner:focus{outline:0;border-color:#262729}.custom-theme .el-input__suffix{position:absolute;height:100%;right:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s;pointer-events:none}.custom-theme .el-input__suffix-inner{pointer-events:all}.custom-theme .el-input__prefix{position:absolute;height:100%;left:5px;top:0;text-align:center;color:#b4bccc;-webkit-transition:all .3s;transition:all .3s}.custom-theme .el-input__icon{height:100%;width:25px;text-align:center;-webkit-transition:all .3s;transition:all .3s;line-height:40px}.custom-theme .el-input__icon:after{content:'';height:100%;width:0;display:inline-block;vertical-align:middle}.custom-theme .el-input__validateIcon{pointer-events:none}.custom-theme .el-input.is-active .el-input__inner{outline:0;border-color:#262729}.custom-theme .el-input.is-disabled .el-input__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-input.is-disabled .el-input__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__inner::placeholder{color:#b4bccc}.custom-theme .el-input.is-disabled .el-input__icon{cursor:not-allowed}.custom-theme .el-input--suffix .el-input__inner{padding-right:30px}.custom-theme .el-input--prefix .el-input__inner{padding-left:30px}.custom-theme .el-input--medium{font-size:14px}.custom-theme .el-input--medium .el-input__inner{height:36px}.custom-theme .el-input--medium .el-input__icon{line-height:36px}.custom-theme .el-input--small{font-size:13px}.custom-theme .el-input--small .el-input__inner{height:32px}.custom-theme .el-input--small .el-input__icon{line-height:32px}.custom-theme .el-input--mini{font-size:12px}.custom-theme .el-input--mini .el-input__inner{height:28px}.custom-theme .el-input--mini .el-input__icon{line-height:28px}.custom-theme .el-input-group{line-height:normal;display:inline-table;width:100%;border-collapse:separate}.custom-theme .el-input-group>.el-input__inner{vertical-align:middle;display:table-cell}.custom-theme .el-input-group__append,.custom-theme .el-input-group__prepend{background-color:#f5f7fa;color:#0a76a4;vertical-align:middle;display:table-cell;position:relative;border:1px solid #d8dce5;border-radius:4px;padding:0 20px;width:1px;white-space:nowrap}.custom-theme .el-input-group__append:focus,.custom-theme .el-input-group__prepend:focus{outline:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-select,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-select{display:inline-block;margin:-20px}.custom-theme .el-input-group__append button.el-button,.custom-theme .el-input-group__append div.el-select .el-input__inner,.custom-theme .el-input-group__append div.el-select:hover .el-input__inner,.custom-theme .el-input-group__prepend button.el-button,.custom-theme .el-input-group__prepend div.el-select .el-input__inner,.custom-theme .el-input-group__prepend div.el-select:hover .el-input__inner{border-color:transparent;background-color:transparent;color:inherit;border-top:0;border-bottom:0}.custom-theme .el-input-group__append .el-button,.custom-theme .el-input-group__append .el-input,.custom-theme .el-input-group__prepend .el-button,.custom-theme .el-input-group__prepend .el-input{font-size:inherit}.custom-theme .el-input-group__prepend{border-right:0;border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-input-group__append{border-left:0;border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--prepend .el-input__inner{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-input-group--append .el-input__inner{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-textarea{display:inline-block;width:100%;vertical-align:bottom}.custom-theme .el-textarea__inner{display:block;resize:vertical;padding:5px 15px;line-height:1.5;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;font-size:14px;color:#5a5e66;background-color:#fff;background-image:none;border:1px solid #d8dce5;border-radius:4px;-webkit-transition:border-color .2s cubic-bezier(.645,.045,.355,1);transition:border-color .2s cubic-bezier(.645,.045,.355,1)}.custom-theme .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-textarea__inner:hover{border-color:#b4bccc}.custom-theme .el-textarea__inner:focus{outline:0;border-color:#262729}.custom-theme .el-textarea.is-disabled .el-textarea__inner{background-color:#f5f7fa;border-color:#dfe4ed;color:#b4bccc;cursor:not-allowed}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-webkit-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner:-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::-ms-input-placeholder{color:#b4bccc}.custom-theme .el-textarea.is-disabled .el-textarea__inner::placeholder{color:#b4bccc}.custom-theme .el-button{display:inline-block;line-height:1;white-space:nowrap;cursor:pointer;background:#fff;border:1px solid #d8dce5;border-color:#d8dce5;color:#5a5e66;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;-webkit-transition:.1s;transition:.1s;font-weight:500;-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;padding:12px 20px;font-size:14px;border-radius:4px}.custom-theme .el-button+.el-button{margin-left:10px}.custom-theme .el-button.is-round{padding:12px 20px}.custom-theme .el-button:focus,.custom-theme .el-button:hover{color:#262729;border-color:#bebebf;background-color:#e9e9ea}.custom-theme .el-button:active{color:#222325;border-color:#222325;outline:0}.custom-theme .el-button::-moz-focus-inner{border:0}.custom-theme .el-button [class*=el-icon-]+span{margin-left:5px}.custom-theme .el-button.is-plain:focus,.custom-theme .el-button.is-plain:hover{background:#fff;border-color:#262729;color:#262729}.custom-theme .el-button.is-plain:active{background:#fff;border-color:#222325;color:#222325;outline:0}.custom-theme .el-button.is-active{color:#222325;border-color:#222325}.custom-theme .el-button.is-disabled,.custom-theme .el-button.is-disabled:focus,.custom-theme .el-button.is-disabled:hover{color:#b4bccc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#e6ebf5}.custom-theme .el-button.is-disabled.el-button--text{background-color:transparent}.custom-theme .el-button.is-disabled.is-plain,.custom-theme .el-button.is-disabled.is-plain:focus,.custom-theme .el-button.is-disabled.is-plain:hover{background-color:#fff;border-color:#e6ebf5;color:#b4bccc}.custom-theme .el-button.is-loading{position:relative;pointer-events:none}.custom-theme .el-button.is-loading:before{pointer-events:none;content:'';position:absolute;left:-1px;top:-1px;right:-1px;bottom:-1px;border-radius:inherit;background-color:rgba(255,255,255,.35)}.custom-theme .el-button.is-round{border-radius:20px;padding:12px 23px}.custom-theme .el-button--primary{color:#fff;background-color:#262729;border-color:#262729}.custom-theme .el-button--primary:focus,.custom-theme .el-button--primary:hover{background:#515254;border-color:#515254;color:#fff}.custom-theme .el-button--primary:active{background:#222325;border-color:#222325;color:#fff;outline:0}.custom-theme .el-button--primary.is-active{background:#222325;border-color:#222325;color:#fff}.custom-theme .el-button--primary.is-disabled,.custom-theme .el-button--primary.is-disabled:active,.custom-theme .el-button--primary.is-disabled:focus,.custom-theme .el-button--primary.is-disabled:hover{color:#fff;background-color:#939394;border-color:#939394}.custom-theme .el-button--primary.is-plain{color:#262729;background:#e9e9ea;border-color:#a8a9a9}.custom-theme .el-button--primary.is-plain:focus,.custom-theme .el-button--primary.is-plain:hover{background:#262729;border-color:#262729;color:#fff}.custom-theme .el-button--primary.is-plain:active{background:#222325;border-color:#222325;color:#fff;outline:0}.custom-theme .el-button--primary.is-plain.is-disabled,.custom-theme .el-button--primary.is-plain.is-disabled:active,.custom-theme .el-button--primary.is-plain.is-disabled:focus,.custom-theme .el-button--primary.is-plain.is-disabled:hover{color:#7d7d7f;background-color:#e9e9ea;border-color:#d4d4d4}.custom-theme .el-button--success{color:#fff;background-color:#409167;border-color:#409167}.custom-theme .el-button--success:focus,.custom-theme .el-button--success:hover{background:#66a785;border-color:#66a785;color:#fff}.custom-theme .el-button--success:active{background:#3a835d;border-color:#3a835d;color:#fff;outline:0}.custom-theme .el-button--success.is-active{background:#3a835d;border-color:#3a835d;color:#fff}.custom-theme .el-button--success.is-disabled,.custom-theme .el-button--success.is-disabled:active,.custom-theme .el-button--success.is-disabled:focus,.custom-theme .el-button--success.is-disabled:hover{color:#fff;background-color:#a0c8b3;border-color:#a0c8b3}.custom-theme .el-button--success.is-plain{color:#409167;background:#ecf4f0;border-color:#b3d3c2}.custom-theme .el-button--success.is-plain:focus,.custom-theme .el-button--success.is-plain:hover{background:#409167;border-color:#409167;color:#fff}.custom-theme .el-button--success.is-plain:active{background:#3a835d;border-color:#3a835d;color:#fff;outline:0}.custom-theme .el-button--success.is-plain.is-disabled,.custom-theme .el-button--success.is-plain.is-disabled:active,.custom-theme .el-button--success.is-plain.is-disabled:focus,.custom-theme .el-button--success.is-plain.is-disabled:hover{color:#8cbda4;background-color:#ecf4f0;border-color:#d9e9e1}.custom-theme .el-button--warning{color:#fff;background-color:#9da408;border-color:#9da408}.custom-theme .el-button--warning:focus,.custom-theme .el-button--warning:hover{background:#b1b639;border-color:#b1b639;color:#fff}.custom-theme .el-button--warning:active{background:#8d9407;border-color:#8d9407;color:#fff;outline:0}.custom-theme .el-button--warning.is-active{background:#8d9407;border-color:#8d9407;color:#fff}.custom-theme .el-button--warning.is-disabled,.custom-theme .el-button--warning.is-disabled:active,.custom-theme .el-button--warning.is-disabled:focus,.custom-theme .el-button--warning.is-disabled:hover{color:#fff;background-color:#ced284;border-color:#ced284}.custom-theme .el-button--warning.is-plain{color:#9da408;background:#f5f6e6;border-color:#d8db9c}.custom-theme .el-button--warning.is-plain:focus,.custom-theme .el-button--warning.is-plain:hover{background:#9da408;border-color:#9da408;color:#fff}.custom-theme .el-button--warning.is-plain:active{background:#8d9407;border-color:#8d9407;color:#fff;outline:0}.custom-theme .el-button--warning.is-plain.is-disabled,.custom-theme .el-button--warning.is-plain.is-disabled:active,.custom-theme .el-button--warning.is-plain.is-disabled:focus,.custom-theme .el-button--warning.is-plain.is-disabled:hover{color:#c4c86b;background-color:#f5f6e6;border-color:#ebedce}.custom-theme .el-button--danger{color:#fff;background-color:#b3450e;border-color:#b3450e}.custom-theme .el-button--danger:focus,.custom-theme .el-button--danger:hover{background:#c26a3e;border-color:#c26a3e;color:#fff}.custom-theme .el-button--danger:active{background:#a13e0d;border-color:#a13e0d;color:#fff;outline:0}.custom-theme .el-button--danger.is-active{background:#a13e0d;border-color:#a13e0d;color:#fff}.custom-theme .el-button--danger.is-disabled,.custom-theme .el-button--danger.is-disabled:active,.custom-theme .el-button--danger.is-disabled:focus,.custom-theme .el-button--danger.is-disabled:hover{color:#fff;background-color:#d9a287;border-color:#d9a287}.custom-theme .el-button--danger.is-plain{color:#b3450e;background:#f7ece7;border-color:#e1b59f}.custom-theme .el-button--danger.is-plain:focus,.custom-theme .el-button--danger.is-plain:hover{background:#b3450e;border-color:#b3450e;color:#fff}.custom-theme .el-button--danger.is-plain:active{background:#a13e0d;border-color:#a13e0d;color:#fff;outline:0}.custom-theme .el-button--danger.is-plain.is-disabled,.custom-theme .el-button--danger.is-plain.is-disabled:active,.custom-theme .el-button--danger.is-plain.is-disabled:focus,.custom-theme .el-button--danger.is-plain.is-disabled:hover{color:#d18f6e;background-color:#f7ece7;border-color:#f0dacf}.custom-theme .el-button--info{color:#fff;background-color:#0a76a4;border-color:#0a76a4}.custom-theme .el-button--info:focus,.custom-theme .el-button--info:hover{background:#3b91b6;border-color:#3b91b6;color:#fff}.custom-theme .el-button--info:active{background:#096a94;border-color:#096a94;color:#fff;outline:0}.custom-theme .el-button--info.is-active{background:#096a94;border-color:#096a94;color:#fff}.custom-theme .el-button--info.is-disabled,.custom-theme .el-button--info.is-disabled:active,.custom-theme .el-button--info.is-disabled:focus,.custom-theme .el-button--info.is-disabled:hover{color:#fff;background-color:#85bbd2;border-color:#85bbd2}.custom-theme .el-button--info.is-plain{color:#0a76a4;background:#e7f1f6;border-color:#9dc8db}.custom-theme .el-button--info.is-plain:focus,.custom-theme .el-button--info.is-plain:hover{background:#0a76a4;border-color:#0a76a4;color:#fff}.custom-theme .el-button--info.is-plain:active{background:#096a94;border-color:#096a94;color:#fff;outline:0}.custom-theme .el-button--info.is-plain.is-disabled,.custom-theme .el-button--info.is-plain.is-disabled:active,.custom-theme .el-button--info.is-plain.is-disabled:focus,.custom-theme .el-button--info.is-plain.is-disabled:hover{color:#6cadc8;background-color:#e7f1f6;border-color:#cee4ed}.custom-theme .el-button--medium{padding:10px 20px;font-size:14px;border-radius:4px}.custom-theme .el-button--medium.is-round{padding:10px 20px}.custom-theme .el-button--small{padding:9px 15px;font-size:12px;border-radius:3px}.custom-theme .el-button--small.is-round{padding:9px 15px}.custom-theme .el-button--mini{padding:7px 15px;font-size:12px;border-radius:3px}.custom-theme .el-button--mini.is-round{padding:7px 15px}.custom-theme .el-button--text{border:none;color:#262729;background:0 0;padding-left:0;padding-right:0}.custom-theme .el-button--text:focus,.custom-theme .el-button--text:hover{color:#515254;border-color:transparent;background-color:transparent}.custom-theme .el-button--text:active{color:#222325;border-color:transparent;background-color:transparent}.custom-theme .el-button-group{display:inline-block;vertical-align:middle}.custom-theme .el-button-group::after,.custom-theme .el-button-group::before{display:table;content:""}.custom-theme .el-button-group::after{clear:both}.custom-theme .el-button-group .el-button{float:left;position:relative}.custom-theme .el-button-group .el-button+.el-button{margin-left:0}.custom-theme .el-button-group .el-button:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.custom-theme .el-button-group .el-button:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.custom-theme .el-button-group .el-button:not(:first-child):not(:last-child){border-radius:0}.custom-theme .el-button-group .el-button:not(:last-child){margin-right:-1px}.custom-theme .el-button-group .el-button:active,.custom-theme .el-button-group .el-button:focus,.custom-theme .el-button-group .el-button:hover{z-index:1}.custom-theme .el-button-group .el-button.is-active{z-index:1}.custom-theme .el-button-group .el-button--primary:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--primary:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--primary:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--success:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--success:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--success:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--warning:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--warning:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--warning:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--danger:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--danger:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--danger:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--info:first-child{border-right-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--info:last-child{border-left-color:rgba(255,255,255,.5)}.custom-theme .el-button-group .el-button--info:not(:first-child):not(:last-child){border-left-color:rgba(255,255,255,.5);border-right-color:rgba(255,255,255,.5)}.custom-theme .el-checkbox{color:#5a5e66;font-weight:500;font-size:14px;position:relative;cursor:pointer;display:inline-block;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.custom-theme .el-checkbox.is-bordered{padding:9px 20px 9px 10px;border-radius:4px;border:1px solid #d8dce5}.custom-theme .el-checkbox.is-bordered.is-checked{border-color:#262729}.custom-theme .el-checkbox.is-bordered.is-disabled{border-color:#e6ebf5;cursor:not-allowed}.custom-theme .el-checkbox.is-bordered+.el-checkbox.is-bordered{margin-left:10px}.custom-theme .el-checkbox.is-bordered.el-checkbox--medium{padding:7px 20px 7px 10px;border-radius:4px}.custom-theme .el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__label{line-height:17px;font-size:14px}.custom-theme .el-checkbox.is-bordered.el-checkbox--medium .el-checkbox__inner{height:14px;width:14px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small{padding:3px 15px 7px 10px;border-radius:3px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small .el-checkbox__label{line-height:15px;font-size:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner{height:12px;width:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--small .el-checkbox__inner::after{height:6px;width:2px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini{padding:1px 15px 5px 10px;border-radius:3px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__label{line-height:12px;font-size:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner{height:12px;width:12px}.custom-theme .el-checkbox.is-bordered.el-checkbox--mini .el-checkbox__inner::after{height:6px;width:2px}.custom-theme .el-checkbox__input{white-space:nowrap;cursor:pointer;outline:0;display:inline-block;line-height:1;position:relative;vertical-align:middle}.custom-theme .el-checkbox__input.is-disabled .el-checkbox__inner{background-color:#edf2fc;border-color:#d8dce5;cursor:not-allowed}.custom-theme .el-checkbox__input.is-disabled .el-checkbox__inner::after{cursor:not-allowed;border-color:#b4bccc}.custom-theme .el-checkbox__input.is-disabled .el-checkbox__inner+.el-checkbox__label{cursor:not-allowed}.custom-theme .el-checkbox__input.is-disabled.is-checked .el-checkbox__inner{background-color:#edf2fc;border-color:#d8dce5}.custom-theme .el-checkbox__input.is-disabled.is-checked .el-checkbox__inner::after{border-color:#b4bccc}.custom-theme .el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner{background-color:#edf2fc;border-color:#d8dce5}.custom-theme .el-checkbox__input.is-disabled.is-indeterminate .el-checkbox__inner::before{background-color:#b4bccc;border-color:#b4bccc}.custom-theme .el-checkbox__input.is-disabled+span.el-checkbox__label{color:#b4bccc;cursor:not-allowed}.custom-theme .el-checkbox__input.is-checked .el-checkbox__inner{background-color:#262729;border-color:#262729}.custom-theme .el-checkbox__input.is-checked .el-checkbox__inner::after{-webkit-transform:rotate(45deg) scaleY(1);transform:rotate(45deg) scaleY(1)}.custom-theme .el-checkbox__input.is-checked+.el-checkbox__label{color:#262729}.custom-theme .el-checkbox__input.is-focus .el-checkbox__inner{border-color:#262729}.custom-theme .el-checkbox__input.is-indeterminate .el-checkbox__inner{background-color:#262729;border-color:#262729}.custom-theme .el-checkbox__input.is-indeterminate .el-checkbox__inner::before{content:'';position:absolute;display:block;background-color:#fff;height:2px;-webkit-transform:scale(.5);transform:scale(.5);left:0;right:0;top:5px}.custom-theme .el-checkbox__input.is-indeterminate .el-checkbox__inner::after{display:none}.custom-theme .el-checkbox__inner{display:inline-block;position:relative;border:1px solid #d8dce5;border-radius:2px;-webkit-box-sizing:border-box;box-sizing:border-box;width:14px;height:14px;background-color:#fff;z-index:1;-webkit-transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46);transition:border-color .25s cubic-bezier(.71,-.46,.29,1.46),background-color .25s cubic-bezier(.71,-.46,.29,1.46)}.custom-theme .el-checkbox__inner:hover{border-color:#262729}.custom-theme .el-checkbox__inner::after{-webkit-box-sizing:content-box;box-sizing:content-box;content:"";border:1px solid #fff;border-left:0;border-top:0;height:7px;left:4px;position:absolute;top:1px;-webkit-transform:rotate(45deg) scaleY(0);transform:rotate(45deg) scaleY(0);width:3px;-webkit-transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;transition:-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;transition:transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms,-webkit-transform .15s cubic-bezier(.71,-.46,.88,.6) 50ms;-webkit-transform-origin:center;transform-origin:center}.custom-theme .el-checkbox__original{opacity:0;outline:0;position:absolute;margin:0;width:0;height:0;left:-999px}.custom-theme .el-checkbox__label{display:inline-block;padding-left:10px;line-height:19px;font-size:14px}.custom-theme .el-checkbox+.el-checkbox{margin-left:30px}.custom-theme .el-checkbox-button{position:relative;display:inline-block}.custom-theme .el-checkbox-button__inner{display:inline-block;line-height:1;font-weight:500;white-space:nowrap;vertical-align:middle;cursor:pointer;background:#fff;border:1px solid #d8dce5;border-left:0;color:#5a5e66;-webkit-appearance:none;text-align:center;-webkit-box-sizing:border-box;box-sizing:border-box;outline:0;margin:0;position:relative;-webkit-transition:all .3s cubic-bezier(.645,.045,.355,1);transition:all .3s cubic-bezier(.645,.045,.355,1);-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;padding:12px 20px;font-size:14px;border-radius:0}.custom-theme .el-checkbox-button__inner.is-round{padding:12px 20px}.custom-theme .el-checkbox-button__inner:hover{color:#262729}.custom-theme .el-checkbox-button__inner [class*=el-icon-]{line-height:.9}.custom-theme .el-checkbox-button__inner [class*=el-icon-]+span{margin-left:5px}.custom-theme .el-checkbox-button__original{opacity:0;outline:0;position:absolute;margin:0;left:-999px}.custom-theme .el-checkbox-button.is-checked .el-checkbox-button__inner{color:#fff;background-color:#262729;border-color:#262729;-webkit-box-shadow:-1px 0 0 0 #7d7d7f;box-shadow:-1px 0 0 0 #7d7d7f}.custom-theme .el-checkbox-button.is-disabled .el-checkbox-button__inner{color:#b4bccc;cursor:not-allowed;background-image:none;background-color:#fff;border-color:#e6ebf5;-webkit-box-shadow:none;box-shadow:none}.custom-theme .el-checkbox-button:first-child .el-checkbox-button__inner{border-left:1px solid #d8dce5;border-radius:4px 0 0 4px;-webkit-box-shadow:none!important;box-shadow:none!important}.custom-theme .el-checkbox-button.is-focus .el-checkbox-button__inner{border-color:#262729}.custom-theme .el-checkbox-button:last-child .el-checkbox-button__inner{border-radius:0 4px 4px 0}.custom-theme .el-checkbox-button--medium .el-checkbox-button__inner{padding:10px 20px;font-size:14px;border-radius:0}.custom-theme .el-checkbox-button--medium .el-checkbox-button__inner.is-round{padding:10px 20px}.custom-theme .el-checkbox-button--small .el-checkbox-button__inner{padding:9px 15px;font-size:12px;border-radius:0}.custom-theme .el-checkbox-button--small .el-checkbox-button__inner.is-round{padding:9px 15px}.custom-theme .el-checkbox-button--mini .el-checkbox-button__inner{padding:7px 15px;font-size:12px;border-radius:0}.custom-theme .el-checkbox-button--mini .el-checkbox-button__inner.is-round{padding:7px 15px}.custom-theme .el-checkbox-group{font-size:0}.custom-theme .el-transfer{font-size:14px}.custom-theme .el-transfer__buttons{display:inline-block;vertical-align:middle;padding:0 30px}.custom-theme .el-transfer__button{display:block;margin:0 auto;padding:10px;border-radius:50%;color:#fff;background-color:#262729;font-size:0}.custom-theme .el-transfer__button.is-with-texts{border-radius:4px}.custom-theme .el-transfer__button.is-disabled{border:1px solid #d8dce5;background-color:#f5f7fa;color:#b4bccc}.custom-theme .el-transfer__button.is-disabled:hover{border:1px solid #d8dce5;background-color:#f5f7fa;color:#b4bccc}.custom-theme .el-transfer__button:first-child{margin-bottom:10px}.custom-theme .el-transfer__button:nth-child(2){margin:0}.custom-theme .el-transfer__button i,.custom-theme .el-transfer__button span{font-size:14px}.custom-theme .el-transfer__button [class*=el-icon-]+span{margin-left:0}.custom-theme .el-transfer-panel{border:1px solid #e6ebf5;border-radius:4px;overflow:hidden;background:#fff;display:inline-block;vertical-align:middle;width:200px;-webkit-box-sizing:border-box;box-sizing:border-box;position:relative}.custom-theme .el-transfer-panel__body{height:246px}.custom-theme .el-transfer-panel__body.is-with-footer{padding-bottom:40px}.custom-theme .el-transfer-panel__list{margin:0;padding:6px 0;list-style:none;height:246px;overflow:auto;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-transfer-panel__list.is-filterable{height:194px;padding-top:0}.custom-theme .el-transfer-panel__item{height:30px;line-height:30px;padding-left:15px;display:block}.custom-theme .el-transfer-panel__item+.el-transfer-panel__item{margin-left:0}.custom-theme .el-transfer-panel__item.el-checkbox{color:#5a5e66}.custom-theme .el-transfer-panel__item:hover{color:#262729}.custom-theme .el-transfer-panel__item.el-checkbox .el-checkbox__label{width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;display:block;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:24px;line-height:30px}.custom-theme .el-transfer-panel__item .el-checkbox__input{position:absolute;top:8px}.custom-theme .el-transfer-panel__filter{text-align:center;margin:15px;-webkit-box-sizing:border-box;box-sizing:border-box;display:block;width:auto}.custom-theme .el-transfer-panel__filter .el-input__inner{height:32px;width:100%;font-size:12px;display:inline-block;-webkit-box-sizing:border-box;box-sizing:border-box;border-radius:16px;padding-right:10px;padding-left:30px}.custom-theme .el-transfer-panel__filter .el-input__icon{margin-left:5px}.custom-theme .el-transfer-panel__filter .el-icon-circle-close{cursor:pointer}.custom-theme .el-transfer-panel .el-transfer-panel__header{height:40px;line-height:40px;background:#f5f7fa;margin:0;padding-left:15px;border-bottom:1px solid #e6ebf5;-webkit-box-sizing:border-box;box-sizing:border-box;color:#000}.custom-theme .el-transfer-panel .el-transfer-panel__header .el-checkbox{display:block;line-height:40px}.custom-theme .el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label{font-size:16px;color:#2d2f33;font-weight:400}.custom-theme .el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label span{position:absolute;right:15px;color:#878d99;font-size:12px;font-weight:400}.custom-theme .el-transfer-panel .el-transfer-panel__footer{height:40px;background:#fff;margin:0;padding:0;border-top:1px solid #e6ebf5;position:absolute;bottom:0;left:0;width:100%;z-index:1}.custom-theme .el-transfer-panel .el-transfer-panel__footer::after{display:inline-block;content:"";height:100%;vertical-align:middle}.custom-theme .el-transfer-panel .el-transfer-panel__footer .el-checkbox{padding-left:20px;color:#5a5e66}.custom-theme .el-transfer-panel .el-transfer-panel__empty{margin:0;height:30px;line-height:30px;padding:6px 15px 0;color:#878d99}.custom-theme .el-transfer-panel .el-checkbox__label{padding-left:8px}.custom-theme .el-transfer-panel .el-checkbox__inner{height:14px;width:14px;border-radius:3px}.custom-theme .el-transfer-panel .el-checkbox__inner::after{height:6px;width:3px;left:4px}.custom-theme .el-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-container.is-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.custom-theme .el-header{padding:0 20px;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-aside{overflow:auto;-webkit-box-sizing:border-box;box-sizing:border-box}.custom-theme .el-main{-webkit-box-flex:1;-ms-flex:1;flex:1;overflow:auto;-webkit-box-sizing:border-box;box-sizing:border-box;padding:20px}.custom-theme .el-footer{padding:0 20px;-webkit-box-sizing:border-box;box-sizing:border-box}
src/common/Header.vue
1 <template> File was deleted
2 <div class="header">
3 <!-- 折叠按钮 -->
4 <div class="collapse-btn" @click="collapseChage">
5 <i v-if="!collapse" class="el-icon-s-fold"></i>
6 <i v-else class="el-icon-s-unfold"></i>
7 </div>
8 <div class="logo">后台管理系统</div>
9 <div class="header-right">
10 <div class="header-user-con">
11 <!-- 全屏显示 -->
12 <div class="btn-fullscreen" @click="handleFullScreen">
13 <el-tooltip effect="dark" :content="fullscreen?`取消全屏`:`全屏`" placement="bottom">
14 <i class="el-icon-rank"></i>
15 </el-tooltip>
16 </div>
17 <!-- 消息中心 -->
18 <div class="btn-bell">
19 <el-tooltip
20 effect="dark"
21 :content="message?`有${message}条未读消息`:`消息中心`"
22 placement="bottom"
23 >
24 <router-link to="/tabs">
25 <i class="el-icon-bell"></i>
26 </router-link>
27 </el-tooltip>
28 <span class="btn-bell-badge" v-if="message"></span>
29 </div>
30 <!-- 用户头像 -->
31 <div class="user-avator">
32 <img src="../assets/img/img.jpg" />
33 </div>
34 <!-- 用户名下拉菜单 -->
35 <el-dropdown class="user-name" trigger="click" @command="handleCommand">
36 <span class="el-dropdown-link">
37 {{username}}
38 <i class="el-icon-caret-bottom"></i>
39 </span>
40 <el-dropdown-menu slot="dropdown">
41 <a href="https://github.com/lin-xin/vue-manage-system" target="_blank">
42 <el-dropdown-item>项目仓库</el-dropdown-item>
43 </a>
44 <el-dropdown-item divided command="loginout">退出登录</el-dropdown-item>
45 </el-dropdown-menu>
46 </el-dropdown>
47 </div>
48 </div>
49 </div>
50 </template>
51 <script>
52 import bus from './bus';
53 export default {
54 data() {
55 return {
56 collapse: false,
57 fullscreen: false,
58 name: 'linxin',
59 message: 2
60 };
61 },
62 computed: {
63 username() {
64 let username = localStorage.getItem('ms_username');
65 return username ? username : this.name;
66 }
67 },
68 methods: {
69 // 用户名下拉菜单选择事件
70 handleCommand(command) {
71 if (command == 'loginout') {
72 localStorage.removeItem('ms_username');
73 this.$router.push('/login');
74 }
75 },
76 // 侧边栏折叠
77 collapseChage() {
78 this.collapse = !this.collapse;
79 bus.$emit('collapse', this.collapse);
80 },
81 // 全屏事件
82 handleFullScreen() {
83 let element = document.documentElement;
84 if (this.fullscreen) {
85 if (document.exitFullscreen) {
86 document.exitFullscreen();
87 } else if (document.webkitCancelFullScreen) {
88 document.webkitCancelFullScreen();
89 } else if (document.mozCancelFullScreen) {
90 document.mozCancelFullScreen();
91 } else if (document.msExitFullscreen) {
92 document.msExitFullscreen();
93 }
94 } else {
95 if (element.requestFullscreen) {
96 element.requestFullscreen();
97 } else if (element.webkitRequestFullScreen) {
98 element.webkitRequestFullScreen();
99 } else if (element.mozRequestFullScreen) {
100 element.mozRequestFullScreen();
101 } else if (element.msRequestFullscreen) {
102 // IE11
103 element.msRequestFullscreen();
104 }
105 }
106 this.fullscreen = !this.fullscreen;
107 }
108 },
109 mounted() {
110 if (document.body.clientWidth < 1500) {
111 this.collapseChage();
112 }
113 }
114 };
115 </script>
116 <style scoped>
117 .header {
118 position: relative;
119 box-sizing: border-box;
120 width: 100%;
121 height: 70px;
122 font-size: 22px;
123 color: #fff;
124 }
125 .collapse-btn {
126 float: left;
127 padding: 0 21px;
128 cursor: pointer;
129 line-height: 70px;
130 }
131 .header .logo {
132 float: left;
133 width: 250px;
134 line-height: 70px;
135 }
136 .header-right {
137 float: right;
138 padding-right: 50px;
139 }
140 .header-user-con {
141 display: flex;
142 height: 70px;
143 align-items: center;
144 }
145 .btn-fullscreen {
146 transform: rotate(45deg);
147 margin-right: 5px;
148 font-size: 24px;
149 }
150 .btn-bell,
151 .btn-fullscreen {
152 position: relative;
153 width: 30px;
154 height: 30px;
155 text-align: center;
156 border-radius: 15px;
157 cursor: pointer;
158 }
159 .btn-bell-badge {
160 position: absolute;
161 right: 0;
162 top: -2px;
163 width: 8px;
164 height: 8px;
165 border-radius: 4px;
166 background: #f56c6c;
167 color: #fff;
168 }
169 .btn-bell .el-icon-bell {
170 color: #fff;
171 }
172 .user-name {
173 margin-left: 10px;
174 }
175 .user-avator {
176 margin-left: 20px;
177 }
178 .user-avator img {
179 display: block;
180 width: 40px;
181 height: 40px;
182 border-radius: 50%;
183 }
184 .el-dropdown-link {
185 color: #fff;
186 cursor: pointer;
187 }
188 .el-dropdown-menu__item {
189 text-align: center;
190 }
191 </style>
src/common/Home.vue
1 <template> File was deleted
2 <div class="wrapper">
3 <v-head></v-head>
4 <v-sidebar></v-sidebar>
5 <div class="content-box" :class="{'content-collapse':collapse}">
6 <v-tags></v-tags>
7 <div class="content">
8 <transition name="move" mode="out-in">
9 <keep-alive :include="tagsList">
10 <router-view></router-view>
11 </keep-alive>
12 </transition>
13 <el-backtop target=".content"></el-backtop>
14 </div>
15 </div>
16 </div>
17 </template>
18
19 <script>
20 import vHead from './Header.vue';
21 import vSidebar from './Sidebar.vue';
22 import vTags from './Tags.vue';
23 import bus from './bus';
24 export default {
25 data() {
26 return {
27 tagsList: [],
28 collapse: false
29 };
30 },
31 components: {
32 vHead,
33 vSidebar,
34 vTags
35 },
36 created() {
37 bus.$on('collapse-content', msg => {
38 this.collapse = msg;
39 });
40 // 只有在标签页列表里的页面才使用keep-alive,即关闭标签之后就不保存到内存中了。
41 bus.$on('tags', msg => {
42 let arr = [];
43 for (let i = 0, len = msg.length; i < len; i++) {
44 msg[i].name && arr.push(msg[i].name);
45 }
46 this.tagsList = arr;
47 });
48 }
49 };
50 </script>
src/common/Sidebar.vue
1 <template> File was deleted
2 <div class="sidebar">
3 <el-menu
4 class="sidebar-el-menu"
5 :default-active="onRoutes"
6 :collapse="collapse"
7 background-color="#324157"
8 text-color="#bfcbd9"
9 active-text-color="#20a0ff"
10 unique-opened
11 router
12 >
13 <template v-for="item in items">
14 <template v-if="item.subs">
15 <el-submenu :index="item.index" :key="item.index">
16 <template slot="title">
17 <i :class="item.icon"></i>
18 <span slot="title">{{ item.title }}</span>
19 </template>
20 <template v-for="subItem in item.subs">
21 <el-submenu
22 v-if="subItem.subs"
23 :index="subItem.index"
24 :key="subItem.index"
25 >
26 <template slot="title">{{ subItem.title }}</template>
27 <el-menu-item
28 v-for="(threeItem,i) in subItem.subs"
29 :key="i"
30 :index="threeItem.index"
31 >{{ threeItem.title }}</el-menu-item>
32 </el-submenu>
33 <el-menu-item
34 v-else
35 :index="subItem.index"
36 :key="subItem.index"
37 >{{ subItem.title }}</el-menu-item>
38 </template>
39 </el-submenu>
40 </template>
41 <template v-else>
42 <el-menu-item :index="item.index" :key="item.index">
43 <i :class="item.icon"></i>
44 <span slot="title">{{ item.title }}</span>
45 </el-menu-item>
46 </template>
47 </template>
48 </el-menu>
49 </div>
50 </template>
51
52 <script>
53 import bus from './bus';
54 export default {
55 data() {
56 return {
57 collapse: false,
58 items: [
59 {
60 icon: 'el-icon-lx-home',
61 index: 'dashboard',
62 title: '系统首页'
63 },
64 {
65 icon: 'el-icon-lx-cascades',
66 index: 'table',
67 title: '基础表格'
68 },
69 {
70 icon: 'el-icon-lx-copy',
71 index: 'tabs',
72 title: 'tab选项卡'
73 },
74 {
75 icon: 'el-icon-lx-calendar',
76 index: '3',
77 title: '表单相关',
78 subs: [
79 {
80 index: 'form',
81 title: '基本表单'
82 },
83 {
84 index: '3-2',
85 title: '三级菜单',
86 subs: [
87 {
88 index: 'editor',
89 title: '富文本编辑器'
90 },
91 {
92 index: 'markdown',
93 title: 'markdown编辑器'
94 }
95 ]
96 },
97 {
98 index: 'upload',
99 title: '文件上传'
100 }
101 ]
102 },
103 {
104 icon: 'el-icon-lx-emoji',
105 index: 'icon',
106 title: '自定义图标'
107 },
108 {
109 icon: 'el-icon-pie-chart',
110 index: 'charts',
111 title: 'schart图表'
112 },
113 {
114 icon: 'el-icon-rank',
115 index: '6',
116 title: '拖拽组件',
117 subs: [
118 {
119 index: 'drag',
120 title: '拖拽列表'
121 },
122 {
123 index: 'dialog',
124 title: '拖拽弹框'
125 }
126 ]
127 },
128 {
129 icon: 'el-icon-lx-global',
130 index: 'i18n',
131 title: '国际化功能'
132 },
133 {
134 icon: 'el-icon-lx-warn',
135 index: '7',
136 title: '错误处理',
137 subs: [
138 {
139 index: 'permission',
140 title: '权限测试'
141 },
142 {
143 index: '404',
144 title: '404页面'
145 }
146 ]
147 },
148 {
149 icon: 'el-icon-lx-redpacket_fill',
150 index: '/donate',
151 title: '支持作者'
152 }
153 ]
154 };
155 },
156 computed: {
157 onRoutes() {
158 return this.$route.path.replace('/', '');
159 }
160 },
161 created() {
162 // 通过 Event Bus 进行组件间通信,来折叠侧边栏
163 bus.$on('collapse', msg => {
164 this.collapse = msg;
165 bus.$emit('collapse-content', msg);
166 });
167 }
168 };
169 </script>
170
171 <style scoped>
172 .sidebar {
173 display: block;
174 position: absolute;
175 left: 0;
176 top: 70px;
177 bottom: 0;
178 overflow-y: scroll;
179 }
180 .sidebar::-webkit-scrollbar {
181 width: 0;
182 }
183 .sidebar-el-menu:not(.el-menu--collapse) {
184 width: 250px;
185 }
186 .sidebar > ul {
187 height: 100%;
188 }
189 </style>
src/common/Tags.vue
1 <template> File was deleted
2 <div class="tags" v-if="showTags">
3 <ul>
4 <li class="tags-li" v-for="(item,index) in tagsList" :class="{'active': isActive(item.path)}" :key="index">
5 <router-link :to="item.path" class="tags-li-title">
6 {{item.title}}
7 </router-link>
8 <span class="tags-li-icon" @click="closeTags(index)"><i class="el-icon-close"></i></span>
9 </li>
10 </ul>
11 <div class="tags-close-box">
12 <el-dropdown @command="handleTags">
13 <el-button size="mini" type="primary">
14 标签选项<i class="el-icon-arrow-down el-icon--right"></i>
15 </el-button>
16 <el-dropdown-menu size="small" slot="dropdown">
17 <el-dropdown-item command="other">关闭其他</el-dropdown-item>
18 <el-dropdown-item command="all">关闭所有</el-dropdown-item>
19 </el-dropdown-menu>
20 </el-dropdown>
21 </div>
22 </div>
23 </template>
24
25 <script>
26 import bus from './bus';
27 export default {
28 data() {
29 return {
30 tagsList: []
31 }
32 },
33 methods: {
34 isActive(path) {
35 return path === this.$route.fullPath;
36 },
37 // 关闭单个标签
38 closeTags(index) {
39 const delItem = this.tagsList.splice(index, 1)[0];
40 const item = this.tagsList[index] ? this.tagsList[index] : this.tagsList[index - 1];
41 if (item) {
42 delItem.path === this.$route.fullPath && this.$router.push(item.path);
43 }else{
44 this.$router.push('/');
45 }
46 },
47 // 关闭全部标签
48 closeAll(){
49 this.tagsList = [];
50 this.$router.push('/');
51 },
52 // 关闭其他标签
53 closeOther(){
54 const curItem = this.tagsList.filter(item => {
55 return item.path === this.$route.fullPath;
56 })
57 this.tagsList = curItem;
58 },
59 // 设置标签
60 setTags(route){
61 const isExist = this.tagsList.some(item => {
62 return item.path === route.fullPath;
63 })
64 if(!isExist){
65 if(this.tagsList.length >= 8){
66 this.tagsList.shift();
67 }
68 this.tagsList.push({
69 title: route.meta.title,
70 path: route.fullPath,
71 name: route.matched[1].components.default.name
72 })
73 }
74 bus.$emit('tags', this.tagsList);
75 },
76 handleTags(command){
77 command === 'other' ? this.closeOther() : this.closeAll();
78 }
79 },
80 computed: {
81 showTags() {
82 return this.tagsList.length > 0;
83 }
84 },
85 watch:{
86 $route(newValue, oldValue){
87 this.setTags(newValue);
88 }
89 },
90 created(){
91 this.setTags(this.$route);
92 // 监听关闭当前页面的标签页
93 bus.$on('close_current_tags', () => {
94 for (let i = 0, len = this.tagsList.length; i < len; i++) {
95 const item = this.tagsList[i];
96 if(item.path === this.$route.fullPath){
97 if(i < len - 1){
98 this.$router.push(this.tagsList[i+1].path);
99 }else if(i > 0){
100 this.$router.push(this.tagsList[i-1].path);
101 }else{
102 this.$router.push('/');
103 }
104 this.tagsList.splice(i, 1);
105 break;
106 }
107 }
108 })
109 }
110 }
111 </script>
112
113
114 <style>
115 .tags {
116 position: relative;
117 height: 30px;
118 overflow: hidden;
119 background: #fff;
120 padding-right: 120px;
121 box-shadow: 0 5px 10px #ddd;
122 }
123 .tags ul {
124 box-sizing: border-box;
125 width: 100%;
126 height: 100%;
127 }
128 .tags-li {
129 float: left;
130 margin: 3px 5px 2px 3px;
131 border-radius: 3px;
132 font-size: 12px;
133 overflow: hidden;
134 cursor: pointer;
135 height: 23px;
136 line-height: 23px;
137 border: 1px solid #e9eaec;
138 background: #fff;
139 padding: 0 5px 0 12px;
140 vertical-align: middle;
141 color: #666;
142 -webkit-transition: all .3s ease-in;
143 -moz-transition: all .3s ease-in;
144 transition: all .3s ease-in;
145 }
146 .tags-li:not(.active):hover {
147 background: #f8f8f8;
148 }
149 .tags-li.active {
150 color: #fff;
151 }
152 .tags-li-title {
153 float: left;
154 max-width: 80px;
155 overflow: hidden;
156 white-space: nowrap;
157 text-overflow: ellipsis;
158 margin-right: 5px;
159 color: #666;
160 }
161 .tags-li.active .tags-li-title {
162 color: #fff;
163 }
164 .tags-close-box {
165 position: absolute;
166 right: 0;
167 top: 0;
168 box-sizing: border-box;
169 padding-top: 1px;
170 text-align: center;
171 width: 110px;
172 height: 30px;
173 background: #fff;
174 box-shadow: -3px 0 15px 3px rgba(0, 0, 0, .1);
175 z-index: 10;
176 }
177 </style>
src/common/bus.js
1 import Vue from 'vue'; File was deleted
2
3 // 使用 Event Bus
4 const bus = new Vue();
5
6 export default bus;
7 1 import Vue from 'vue';
src/common/directives.js
1 import Vue from 'vue'; File was deleted
2
3 // v-dialogDrag: 弹窗拖拽属性
4 Vue.directive('dialogDrag', {
5 bind(el, binding, vnode, oldVnode) {
6 const dialogHeaderEl = el.querySelector('.el-dialog__header');
7 const dragDom = el.querySelector('.el-dialog');
8
9 dialogHeaderEl.style.cssText += ';cursor:move;'
10 dragDom.style.cssText += ';top:0px;'
11
12 // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
13 const sty = (() => {
14 if (window.document.currentStyle) {
15 return (dom, attr) => dom.currentStyle[attr];
16 } else {
17 return (dom, attr) => getComputedStyle(dom, false)[attr];
18 }
19 })()
20
21 dialogHeaderEl.onmousedown = (e) => {
22 // 鼠标按下,计算当前元素距离可视区的距离
23 const disX = e.clientX - dialogHeaderEl.offsetLeft;
24 const disY = e.clientY - dialogHeaderEl.offsetTop;
25
26 const screenWidth = document.body.clientWidth; // body当前宽度
27 const screenHeight = document.documentElement.clientHeight; // 可见区域高度(应为body高度,可某些环境下无法获取)
28
29 const dragDomWidth = dragDom.offsetWidth; // 对话框宽度
30 const dragDomheight = dragDom.offsetHeight; // 对话框高度
31
32 const minDragDomLeft = dragDom.offsetLeft;
33 const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth;
34
35 const minDragDomTop = dragDom.offsetTop;
36 const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomheight;
37
38
39 // 获取到的值带px 正则匹配替换
40 let styL = sty(dragDom, 'left');
41 let styT = sty(dragDom, 'top');
42
43 // 注意在ie中 第一次获取到的值为组件自带50% 移动之后赋值为px
44 if (styL.includes('%')) {
45 styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100);
46 styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100);
47 } else {
48 styL = +styL.replace(/\px/g, '');
49 styT = +styT.replace(/\px/g, '');
50 };
51
52 document.onmousemove = function (e) {
53 // 通过事件委托,计算移动的距离
54 let left = e.clientX - disX;
55 let top = e.clientY - disY;
56
57 // 边界处理
58 if (-(left) > minDragDomLeft) {
59 left = -(minDragDomLeft);
60 } else if (left > maxDragDomLeft) {
61 left = maxDragDomLeft;
62 }
63
64 if (-(top) > minDragDomTop) {
65 top = -(minDragDomTop);
66 } else if (top > maxDragDomTop) {
67 top = maxDragDomTop;
68 }
69
70 // 移动当前元素
71 dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`;
72 };
73
74 document.onmouseup = function (e) {
75 document.onmousemove = null;
76 document.onmouseup = null;
77 };
78 }
79 }
80 })
src/common/i18n.js
1 export const messages = { File was deleted
2 'zh': {
3 i18n: {
4 breadcrumb: '国际化产品',
5 tips: '通过切换语言按钮,来改变当前内容的语言。',
6 btn: '切换英文',
7 title1: '常用用法',
8 p1: '要是你把你的秘密告诉了风,那就别怪风把它带给树。',
9 p2: '没有什么比信念更能支撑我们度过艰难的时光了。',
10 p3: '只要能把自己的事做好,并让自己快乐,你就领先于大多数人了。',
11 title2: '组件插值',
12 info: 'Element组件需要国际化,请参考 {action}。',
13 value: '文档'
14 }
15 },
16 'en': {
17 i18n: {
18 breadcrumb: 'International Products',
19 tips: 'Click on the button to change the current language. ',
20 btn: 'Switch Chinese',
21 title1: 'Common usage',
22 p1: "If you reveal your secrets to the wind you should not blame the wind for revealing them to the trees.",
23 p2: "Nothing can help us endure dark times better than our faith. ",
24 p3: "If you can do what you do best and be happy, you're further along in life than most people.",
25 title2: 'Component interpolation',
26 info: 'The default language of Element is Chinese. If you wish to use another language, please refer to the {action}.',
27 value: 'documentation'
28 }
29 }
30 }
src/components/BackToTop/index.vue
File was created 1 <template>
2 <transition :name="transitionName">
3 <div v-show="visible" :style="customStyle" class="back-to-ceiling" @click="backToTop">
4 <svg width="16" height="16" viewBox="0 0 17 17" xmlns="http://www.w3.org/2000/svg" class="Icon Icon--backToTopArrow" aria-hidden="true" style="height:16px;width:16px"><path d="M12.036 15.59a1 1 0 0 1-.997.995H5.032a.996.996 0 0 1-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29a1.003 1.003 0 0 1 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" /></svg>
5 </div>
6 </transition>
7 </template>
8
9 <script>
10 export default {
11 name: 'BackToTop',
12 props: {
13 visibilityHeight: {
14 type: Number,
15 default: 400
16 },
17 backPosition: {
18 type: Number,
19 default: 0
20 },
21 customStyle: {
22 type: Object,
23 default: function() {
24 return {
25 right: '50px',
26 bottom: '50px',
27 width: '40px',
28 height: '40px',
29 'border-radius': '4px',
30 'line-height': '45px',
31 background: '#e7eaf1'
32 }
33 }
34 },
35 transitionName: {
36 type: String,
37 default: 'fade'
38 }
39 },
40 data() {
41 return {
42 visible: false,
43 interval: null,
44 isMoving: false
45 }
46 },
47 mounted() {
48 window.addEventListener('scroll', this.handleScroll)
49 },
50 beforeDestroy() {
51 window.removeEventListener('scroll', this.handleScroll)
52 if (this.interval) {
53 clearInterval(this.interval)
54 }
55 },
56 methods: {
57 handleScroll() {
58 this.visible = window.pageYOffset > this.visibilityHeight
59 },
60 backToTop() {
61 if (this.isMoving) return
62 const start = window.pageYOffset
63 let i = 0
64 this.isMoving = true
65 this.interval = setInterval(() => {
66 const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
67 if (next <= this.backPosition) {
68 window.scrollTo(0, this.backPosition)
69 clearInterval(this.interval)
70 this.isMoving = false
71 } else {
72 window.scrollTo(0, next)
73 }
74 i++
75 }, 16.7)
76 },
77 easeInOutQuad(t, b, c, d) {
78 if ((t /= d / 2) < 1) return c / 2 * t * t + b
79 return -c / 2 * (--t * (t - 2) - 1) + b
80 }
81 }
82 }
83 </script>
84
85 <style scoped>
86 .back-to-ceiling {
87 position: fixed;
88 display: inline-block;
89 text-align: center;
90 cursor: pointer;
91 }
92
93 .back-to-ceiling:hover {
94 background: #d5dbe7;
95 }
96
97 .fade-enter-active,
98 .fade-leave-active {
99 transition: opacity .5s;
100 }
101
102 .fade-enter,
103 .fade-leave-to {
104 opacity: 0
105 }
106
107 .back-to-ceiling .Icon {
108 fill: #9aaabf;
109 background: none;
110 }
111 </style>
112
src/components/Breadcrumb/index.vue
1 <template> 1 <template>
2 <el-breadcrumb class="app-breadcrumb" separator="/"> 2 <el-breadcrumb class="app-breadcrumb" separator="/">
3 <transition-group name="breadcrumb"> 3 <transition-group name="breadcrumb">
4 <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path"> 4 <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
5 <span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span> 5 <span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">
6 <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a> 6 {{ generateTitle(item.meta.title) }}
7 </span>
8 <a v-else @click.prevent="handleLink(item)">{{ generateTitle(item.meta.title) }}</a>
7 </el-breadcrumb-item> 9 </el-breadcrumb-item>
8 </transition-group> 10 </transition-group>
9 </el-breadcrumb> 11 </el-breadcrumb>
10 </template> 12 </template>
11 13
12 <script> 14 <script>
15 import { generateTitle } from '@/utils/i18n'
13 import pathToRegexp from 'path-to-regexp' 16 import pathToRegexp from 'path-to-regexp'
14 17
15 export default { 18 export default {
16 data() { 19 data() {
17 return { 20 return {
18 levelList: null 21 levelList: null
19 } 22 }
20 }, 23 },
21 watch: { 24 watch: {
22 $route() { 25 $route(route) {
26 // if you go to the redirect page, do not update the breadcrumbs
27 if (route.path.startsWith('/redirect/')) {
28 return
29 }
23 this.getBreadcrumb() 30 this.getBreadcrumb()
24 } 31 }
25 }, 32 },
26 created() { 33 created() {
27 this.getBreadcrumb() 34 this.getBreadcrumb()
28 }, 35 },
29 methods: { 36 methods: {
37 generateTitle,
30 getBreadcrumb() { 38 getBreadcrumb() {
31 // only show routes with meta.title 39 // only show routes with meta.title
32 let matched = this.$route.matched.filter(item => item.meta && item.meta.title) 40 let matched = this.$route.matched.filter(item => item.meta && item.meta.title)
33 const first = matched[0] 41 const first = matched[0]
34 42
35 if (!this.isDashboard(first)) { 43 if (!this.isDashboard(first)) {
36 matched = [{ path: '/dashboard', meta: { title: 'Dashboard' }}].concat(matched) 44 matched = [{ path: '/dashboard', meta: { title: 'dashboard' }}].concat(matched)
37 } 45 }
38 46
39 this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) 47 this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
40 }, 48 },
41 isDashboard(route) { 49 isDashboard(route) {
42 const name = route && route.name 50 const name = route && route.name
43 if (!name) { 51 if (!name) {
44 return false 52 return false
45 } 53 }
46 return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase() 54 return name.trim().toLocaleLowerCase() === 'Dashboard'.toLocaleLowerCase()
47 }, 55 },
48 pathCompile(path) { 56 pathCompile(path) {
49 // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561 57 // To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
50 const { params } = this.$route 58 const { params } = this.$route
51 var toPath = pathToRegexp.compile(path) 59 var toPath = pathToRegexp.compile(path)
52 return toPath(params) 60 return toPath(params)
53 }, 61 },
54 handleLink(item) { 62 handleLink(item) {
55 const { redirect, path } = item 63 const { redirect, path } = item
56 if (redirect) { 64 if (redirect) {
57 this.$router.push(redirect) 65 this.$router.push(redirect)
58 return 66 return
59 } 67 }
60 this.$router.push(this.pathCompile(path)) 68 this.$router.push(this.pathCompile(path))
61 } 69 }
62 } 70 }
63 } 71 }
64 </script> 72 </script>
65 73
66 <style lang="scss" scoped> 74 <style lang="scss" scoped>
67 .app-breadcrumb.el-breadcrumb { 75 .app-breadcrumb.el-breadcrumb {
68 display: inline-block; 76 display: inline-block;
69 font-size: 14px; 77 font-size: 14px;
70 line-height: 50px; 78 line-height: 50px;
71 margin-left: 8px; 79 margin-left: 8px;
72 80
73 .no-redirect { 81 .no-redirect {
74 color: #97a8be; 82 color: #97a8be;
75 cursor: text; 83 cursor: text;
76 } 84 }
77 } 85 }
78 </style> 86 </style>
79 87
src/components/Charts/Keyboard.vue
File was created 1 <template>
2 <div :id="id" :class="className" :style="{height:height,width:width}" />
3 </template>
4
5 <script>
6 import echarts from 'echarts'
7 import resize from './mixins/resize'
8
9 export default {
10 mixins: [resize],
11 props: {
12 className: {
13 type: String,
14 default: 'chart'
15 },
16 id: {
17 type: String,
18 default: 'chart'
19 },
20 width: {
21 type: String,
22 default: '200px'
23 },
24 height: {
25 type: String,
26 default: '200px'
27 }
28 },
29 data() {
30 return {
31 chart: null
32 }
33 },
34 mounted() {
35 this.initChart()
36 },
37 beforeDestroy() {
38 if (!this.chart) {
39 return
40 }
41 this.chart.dispose()
42 this.chart = null
43 },
44 methods: {
45 initChart() {
46 this.chart = echarts.init(document.getElementById(this.id))
47
48 const xAxisData = []
49 const data = []
50 const data2 = []
51 for (let i = 0; i < 50; i++) {
52 xAxisData.push(i)
53 data.push((Math.sin(i / 5) * (i / 5 - 10) + i / 6) * 5)
54 data2.push((Math.sin(i / 5) * (i / 5 + 10) + i / 6) * 3)
55 }
56 this.chart.setOption({
57 backgroundColor: '#08263a',
58 grid: {
59 left: '5%',
60 right: '5%'
61 },
62 xAxis: [{
63 show: false,
64 data: xAxisData
65 }, {
66 show: false,
67 data: xAxisData
68 }],
69 visualMap: {
70 show: false,
71 min: 0,
72 max: 50,
73 dimension: 0,
74 inRange: {
75 color: ['#4a657a', '#308e92', '#b1cfa5', '#f5d69f', '#f5898b', '#ef5055']
76 }
77 },
78 yAxis: {
79 axisLine: {
80 show: false
81 },
82 axisLabel: {
83 textStyle: {
84 color: '#4a657a'
85 }
86 },
87 splitLine: {
88 show: true,
89 lineStyle: {
90 color: '#08263f'
91 }
92 },
93 axisTick: {
94 show: false
95 }
96 },
97 series: [{
98 name: 'back',
99 type: 'bar',
100 data: data2,
101 z: 1,
102 itemStyle: {
103 normal: {
104 opacity: 0.4,
105 barBorderRadius: 5,
106 shadowBlur: 3,
107 shadowColor: '#111'
108 }
109 }
110 }, {
111 name: 'Simulate Shadow',
112 type: 'line',
113 data,
114 z: 2,
115 showSymbol: false,
116 animationDelay: 0,
117 animationEasing: 'linear',
118 animationDuration: 1200,
119 lineStyle: {
120 normal: {
121 color: 'transparent'
122 }
123 },
124 areaStyle: {
125 normal: {
126 color: '#08263a',
127 shadowBlur: 50,
128 shadowColor: '#000'
129 }
130 }
131 }, {
132 name: 'front',
133 type: 'bar',
134 data,
135 xAxisIndex: 1,
136 z: 3,
137 itemStyle: {
138 normal: {
139 barBorderRadius: 5
140 }
141 }
142 }],
143 animationEasing: 'elasticOut',
144 animationEasingUpdate: 'elasticOut',
145 animationDelay(idx) {
146 return idx * 20
147 },
148 animationDelayUpdate(idx) {
149 return idx * 20
150 }
151 })
152 }
153 }
154 }
155 </script>
156
src/components/Charts/LineMarker.vue
File was created 1 <template>
2 <div :id="id" :class="className" :style="{height:height,width:width}" />
3 </template>
4
5 <script>
6 import echarts from 'echarts'
7 import resize from './mixins/resize'
8
9 export default {
10 mixins: [resize],
11 props: {
12 className: {
13 type: String,
14 default: 'chart'
15 },
16 id: {
17 type: String,
18 default: 'chart'
19 },
20 width: {
21 type: String,
22 default: '200px'
23 },
24 height: {
25 type: String,
26 default: '200px'
27 }
28 },
29 data() {
30 return {
31 chart: null
32 }
33 },
34 mounted() {
35 this.initChart()
36 },
37 beforeDestroy() {
38 if (!this.chart) {
39 return
40 }
41 this.chart.dispose()
42 this.chart = null
43 },
44 methods: {
45 initChart() {
46 this.chart = echarts.init(document.getElementById(this.id))
47
48 this.chart.setOption({
49 backgroundColor: '#394056',
50 title: {
51 top: 20,
52 text: 'Requests',
53 textStyle: {
54 fontWeight: 'normal',
55 fontSize: 16,
56 color: '#F1F1F3'
57 },
58 left: '1%'
59 },
60 tooltip: {
61 trigger: 'axis',
62 axisPointer: {
63 lineStyle: {
64 color: '#57617B'
65 }
66 }
67 },
68 legend: {
69 top: 20,
70 icon: 'rect',
71 itemWidth: 14,
72 itemHeight: 5,
73 itemGap: 13,
74 data: ['CMCC', 'CTCC', 'CUCC'],
75 right: '4%',
76 textStyle: {
77 fontSize: 12,
78 color: '#F1F1F3'
79 }
80 },
81 grid: {
82 top: 100,
83 left: '2%',
84 right: '2%',
85 bottom: '2%',
86 containLabel: true
87 },
88 xAxis: [{
89 type: 'category',
90 boundaryGap: false,
91 axisLine: {
92 lineStyle: {
93 color: '#57617B'
94 }
95 },
96 data: ['13:00', '13:05', '13:10', '13:15', '13:20', '13:25', '13:30', '13:35', '13:40', '13:45', '13:50', '13:55']
97 }],
98 yAxis: [{
99 type: 'value',
100 name: '(%)',
101 axisTick: {
102 show: false
103 },
104 axisLine: {
105 lineStyle: {
106 color: '#57617B'
107 }
108 },
109 axisLabel: {
110 margin: 10,
111 textStyle: {
112 fontSize: 14
113 }
114 },
115 splitLine: {
116 lineStyle: {
117 color: '#57617B'
118 }
119 }
120 }],
121 series: [{
122 name: 'CMCC',
123 type: 'line',
124 smooth: true,
125 symbol: 'circle',
126 symbolSize: 5,
127 showSymbol: false,
128 lineStyle: {
129 normal: {
130 width: 1
131 }
132 },
133 areaStyle: {
134 normal: {
135 color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
136 offset: 0,
137 color: 'rgba(137, 189, 27, 0.3)'
138 }, {
139 offset: 0.8,
140 color: 'rgba(137, 189, 27, 0)'
141 }], false),
142 shadowColor: 'rgba(0, 0, 0, 0.1)',
143 shadowBlur: 10
144 }
145 },
146 itemStyle: {
147 normal: {
148 color: 'rgb(137,189,27)',
149 borderColor: 'rgba(137,189,2,0.27)',
150 borderWidth: 12
151
152 }
153 },
154 data: [220, 182, 191, 134, 150, 120, 110, 125, 145, 122, 165, 122]
155 }, {
156 name: 'CTCC',
157 type: 'line',
158 smooth: true,
159 symbol: 'circle',
160 symbolSize: 5,
161 showSymbol: false,
162 lineStyle: {
163 normal: {
164 width: 1
165 }
166 },
167 areaStyle: {
168 normal: {
169 color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
170 offset: 0,
171 color: 'rgba(0, 136, 212, 0.3)'
172 }, {
173 offset: 0.8,
174 color: 'rgba(0, 136, 212, 0)'
175 }], false),
176 shadowColor: 'rgba(0, 0, 0, 0.1)',
177 shadowBlur: 10
178 }
179 },
180 itemStyle: {
181 normal: {
182 color: 'rgb(0,136,212)',
183 borderColor: 'rgba(0,136,212,0.2)',
184 borderWidth: 12
185
186 }
187 },
188 data: [120, 110, 125, 145, 122, 165, 122, 220, 182, 191, 134, 150]
189 }, {
190 name: 'CUCC',
191 type: 'line',
192 smooth: true,
193 symbol: 'circle',
194 symbolSize: 5,
195 showSymbol: false,
196 lineStyle: {
197 normal: {
198 width: 1
199 }
200 },
201 areaStyle: {
202 normal: {
203 color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
204 offset: 0,
205 color: 'rgba(219, 50, 51, 0.3)'
206 }, {
207 offset: 0.8,
208 color: 'rgba(219, 50, 51, 0)'
209 }], false),
210 shadowColor: 'rgba(0, 0, 0, 0.1)',
211 shadowBlur: 10
212 }
213 },
214 itemStyle: {
215 normal: {
216 color: 'rgb(219,50,51)',
217 borderColor: 'rgba(219,50,51,0.2)',
218 borderWidth: 12
219 }
220 },
221 data: [220, 182, 125, 145, 122, 191, 134, 150, 120, 110, 165, 122]
222 }]
223 })
224 }
225 }
226 }
227 </script>
228
src/components/Charts/MixChart.vue
File was created 1 <template>
2 <div :id="id" :class="className" :style="{height:height,width:width}" />
3 </template>
4
5 <script>
6 import echarts from 'echarts'
7 import resize from './mixins/resize'
8
9 export default {
10 mixins: [resize],
11 props: {
12 className: {
13 type: String,
14 default: 'chart'
15 },
16 id: {
17 type: String,
18 default: 'chart'
19 },
20 width: {
21 type: String,
22 default: '200px'
23 },
24 height: {
25 type: String,
26 default: '200px'
27 }
28 },
29 data() {
30 return {
31 chart: null
32 }
33 },
34 mounted() {
35 this.initChart()
36 },
37 beforeDestroy() {
38 if (!this.chart) {
39 return
40 }
41 this.chart.dispose()
42 this.chart = null
43 },
44 methods: {
45 initChart() {
46 this.chart = echarts.init(document.getElementById(this.id))
47 const xData = (function() {
48 const data = []
49 for (let i = 1; i < 13; i++) {
50 data.push(i + 'month')
51 }
52 return data
53 }())
54 this.chart.setOption({
55 backgroundColor: '#344b58',
56 title: {
57 text: 'statistics',
58 x: '20',
59 top: '20',
60 textStyle: {
61 color: '#fff',
62 fontSize: '22'
63 },
64 subtextStyle: {
65 color: '#90979c',
66 fontSize: '16'
67 }
68 },
69 tooltip: {
70 trigger: 'axis',
71 axisPointer: {
72 textStyle: {
73 color: '#fff'
74 }
75 }
76 },
77 grid: {
78 left: '5%',
79 right: '5%',
80 borderWidth: 0,
81 top: 150,
82 bottom: 95,
83 textStyle: {
84 color: '#fff'
85 }
86 },
87 legend: {
88 x: '5%',
89 top: '10%',
90 textStyle: {
91 color: '#90979c'
92 },
93 data: ['female', 'male', 'average']
94 },
95 calculable: true,
96 xAxis: [{
97 type: 'category',
98 axisLine: {
99 lineStyle: {
100 color: '#90979c'
101 }
102 },
103 splitLine: {
104 show: false
105 },
106 axisTick: {
107 show: false
108 },
109 splitArea: {
110 show: false
111 },
112 axisLabel: {
113 interval: 0
114
115 },
116 data: xData
117 }],
118 yAxis: [{
119 type: 'value',
120 splitLine: {
121 show: false
122 },
123 axisLine: {
124 lineStyle: {
125 color: '#90979c'
126 }
127 },
128 axisTick: {
129 show: false
130 },
131 axisLabel: {
132 interval: 0
133 },
134 splitArea: {
135 show: false
136 }
137 }],
138 dataZoom: [{
139 show: true,
140 height: 30,
141 xAxisIndex: [
142 0
143 ],
144 bottom: 30,
145 start: 10,
146 end: 80,
147 handleIcon: 'path://M306.1,413c0,2.2-1.8,4-4,4h-59.8c-2.2,0-4-1.8-4-4V200.8c0-2.2,1.8-4,4-4h59.8c2.2,0,4,1.8,4,4V413z',
148 handleSize: '110%',
149 handleStyle: {
150 color: '#d3dee5'
151
152 },
153 textStyle: {
154 color: '#fff' },
155 borderColor: '#90979c'
156
157 }, {
158 type: 'inside',
159 show: true,
160 height: 15,
161 start: 1,
162 end: 35
163 }],
164 series: [{
165 name: 'female',
166 type: 'bar',
167 stack: 'total',
168 barMaxWidth: 35,
169 barGap: '10%',
170 itemStyle: {
171 normal: {
172 color: 'rgba(255,144,128,1)',
173 label: {
174 show: true,
175 textStyle: {
176 color: '#fff'
177 },
178 position: 'insideTop',
179 formatter(p) {
180 return p.value > 0 ? p.value : ''
181 }
182 }
183 }
184 },
185 data: [
186 709,
187 1917,
188 2455,
189 2610,
190 1719,
191 1433,
192 1544,
193 3285,
194 5208,
195 3372,
196 2484,
197 4078
198 ]
199 },
200
201 {
202 name: 'male',
203 type: 'bar',
204 stack: 'total',
205 itemStyle: {
206 normal: {
207 color: 'rgba(0,191,183,1)',
208 barBorderRadius: 0,
209 label: {
210 show: true,
211 position: 'top',
212 formatter(p) {
213 return p.value > 0 ? p.value : ''
214 }
215 }
216 }
217 },
218 data: [
219 327,
220 1776,
221 507,
222 1200,
223 800,
224 482,
225 204,
226 1390,
227 1001,
228 951,
229 381,
230 220
231 ]
232 }, {
233 name: 'average',
234 type: 'line',
235 stack: 'total',
236 symbolSize: 10,
237 symbol: 'circle',
238 itemStyle: {
239 normal: {
240 color: 'rgba(252,230,48,1)',
241 barBorderRadius: 0,
242 label: {
243 show: true,
244 position: 'top',
245 formatter(p) {
246 return p.value > 0 ? p.value : ''
247 }
248 }
249 }
250 },
251 data: [
252 1036,
253 3693,
254 2962,
255 3810,
256 2519,
257 1915,
258 1748,
259 4675,
260 6209,
261 4323,
262 2865,
263 4298
264 ]
265 }
266 ]
267 })
268 }
269 }
270 }
271 </script>
272
src/components/Charts/mixins/resize.js
File was created 1 import { debounce } from '@/utils'
2
3 export default {
4 data() {
5 return {
6 $_sidebarElm: null,
7 $_resizeHandler: null
8 }
9 },
10 mounted() {
11 this.initListener()
12 },
13 activated() {
14 if (!this.$_resizeHandler) {
15 // avoid duplication init
16 this.initListener()
17 }
18
19 // when keep-alive chart activated, auto resize
20 this.resize()
21 },
22 beforeDestroy() {
23 this.destroyListener()
24 },
25 deactivated() {
26 this.destroyListener()
27 },
28 methods: {
29 // use $_ for mixins properties
30 // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
31 $_sidebarResizeHandler(e) {
32 if (e.propertyName === 'width') {
33 this.$_resizeHandler()
34 }
35 },
36 initListener() {
37 this.$_resizeHandler = debounce(() => {
38 this.resize()
39 }, 100)
40 window.addEventListener('resize', this.$_resizeHandler)
41
42 this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
43 this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
44 },
45 destroyListener() {
46 window.removeEventListener('resize', this.$_resizeHandler)
47 this.$_resizeHandler = null
48
49 this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
50 },
51 resize() {
52 const { chart } = this
53 chart && chart.resize()
54 }
55 }
56 }
57
src/components/DndList/index.vue
File was created 1 <template>
2 <div class="dndList">
3 <div :style="{width:width1}" class="dndList-list">
4 <h3>{{ list1Title }}</h3>
5 <draggable :set-data="setData" :list="list1" group="article" class="dragArea">
6 <div v-for="element in list1" :key="element.id" class="list-complete-item">
7 <div class="list-complete-item-handle">
8 {{ element.id }}[{{ element.author }}] {{ element.title }}
9 </div>
10 <div style="position:absolute;right:0px;">
11 <span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)">
12 <i style="color:#ff4949" class="el-icon-delete" />
13 </span>
14 </div>
15 </div>
16 </draggable>
17 </div>
18 <div :style="{width:width2}" class="dndList-list">
19 <h3>{{ list2Title }}</h3>
20 <draggable :list="list2" group="article" class="dragArea">
21 <div v-for="element in list2" :key="element.id" class="list-complete-item">
22 <div class="list-complete-item-handle2" @click="pushEle(element)">
23 {{ element.id }} [{{ element.author }}] {{ element.title }}
24 </div>
25 </div>
26 </draggable>
27 </div>
28 </div>
29 </template>
30
31 <script>
32 import draggable from 'vuedraggable'
33
34 export default {
35 name: 'DndList',
36 components: { draggable },
37 props: {
38 list1: {
39 type: Array,
40 default() {
41 return []
42 }
43 },
44 list2: {
45 type: Array,
46 default() {
47 return []
48 }
49 },
50 list1Title: {
51 type: String,
52 default: 'list1'
53 },
54 list2Title: {
55 type: String,
56 default: 'list2'
57 },
58 width1: {
59 type: String,
60 default: '48%'
61 },
62 width2: {
63 type: String,
64 default: '48%'
65 }
66 },
67 methods: {
68 isNotInList1(v) {
69 return this.list1.every(k => v.id !== k.id)
70 },
71 isNotInList2(v) {
72 return this.list2.every(k => v.id !== k.id)
73 },
74 deleteEle(ele) {
75 for (const item of this.list1) {
76 if (item.id === ele.id) {
77 const index = this.list1.indexOf(item)
78 this.list1.splice(index, 1)
79 break
80 }
81 }
82 if (this.isNotInList2(ele)) {
83 this.list2.unshift(ele)
84 }
85 },
86 pushEle(ele) {
87 for (const item of this.list2) {
88 if (item.id === ele.id) {
89 const index = this.list2.indexOf(item)
90 this.list2.splice(index, 1)
91 break
92 }
93 }
94 if (this.isNotInList1(ele)) {
95 this.list1.push(ele)
96 }
97 },
98 setData(dataTransfer) {
99 // to avoid Firefox bug
100 // Detail see : https://github.com/RubaXa/Sortable/issues/1012
101 dataTransfer.setData('Text', '')
102 }
103 }
104 }
105 </script>
106
107 <style lang="scss" scoped>
108 .dndList {
109 background: #fff;
110 padding-bottom: 40px;
111 &:after {
112 content: "";
113 display: table;
114 clear: both;
115 }
116 .dndList-list {
117 float: left;
118 padding-bottom: 30px;
119 &:first-of-type {
120 margin-right: 2%;
121 }
122 .dragArea {
123 margin-top: 15px;
124 min-height: 50px;
125 padding-bottom: 30px;
126 }
127 }
128 }
129
130 .list-complete-item {
131 cursor: pointer;
132 position: relative;
133 font-size: 14px;
134 padding: 5px 12px;
135 margin-top: 4px;
136 border: 1px solid #bfcbd9;
137 transition: all 1s;
138 }
139
140 .list-complete-item-handle {
141 overflow: hidden;
142 text-overflow: ellipsis;
143 white-space: nowrap;
144 margin-right: 50px;
145 }
146
147 .list-complete-item-handle2 {
148 overflow: hidden;
149 text-overflow: ellipsis;
150 white-space: nowrap;
151 margin-right: 20px;
152 }
153
154 .list-complete-item.sortable-chosen {
155 background: #4AB7BD;
156 }
157
158 .list-complete-item.sortable-ghost {
159 background: #30B08F;
160 }
161
162 .list-complete-enter,
163 .list-complete-leave-active {
164 opacity: 0;
165 }
166 </style>
167
src/components/DragSelect/index.vue
File was created 1 <template>
2 <el-select ref="dragSelect" v-model="selectVal" v-bind="$attrs" class="drag-select" multiple v-on="$listeners">
3 <slot />
4 </el-select>
5 </template>
6
7 <script>
8 import Sortable from 'sortablejs'
9
10 export default {
11 name: 'DragSelect',
12 props: {
13 value: {
14 type: Array,
15 required: true
16 }
17 },
18 computed: {
19 selectVal: {
20 get() {
21 return [...this.value]
22 },
23 set(val) {
24 this.$emit('input', [...val])
25 }
26 }
27 },
28 mounted() {
29 this.setSort()
30 },
31 methods: {
32 setSort() {
33 const el = this.$refs.dragSelect.$el.querySelectorAll('.el-select__tags > span')[0]
34 this.sortable = Sortable.create(el, {
35 ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
36 setData: function(dataTransfer) {
37 dataTransfer.setData('Text', '')
38 // to avoid Firefox bug
39 // Detail see : https://github.com/RubaXa/Sortable/issues/1012
40 },
41 onEnd: evt => {
42 const targetRow = this.value.splice(evt.oldIndex, 1)[0]
43 this.value.splice(evt.newIndex, 0, targetRow)
44 }
45 })
46 }
47 }
48 }
49 </script>
50
51 <style scoped>
52 .drag-select >>> .sortable-ghost {
53 opacity: .8;
54 color: #fff!important;
55 background: #42b983!important;
56 }
57
58 .drag-select >>> .el-tag {
59 cursor: pointer;
60 }
61 </style>
62
src/components/Dropzone/index.vue
File was created 1 <template>
2 <div :id="id" :ref="id" :action="url" class="dropzone">
3 <input type="file" name="file">
4 </div>
5 </template>
6
7 <script>
8 import Dropzone from 'dropzone'
9 import 'dropzone/dist/dropzone.css'
10 // import { getToken } from 'api/qiniu';
11
12 Dropzone.autoDiscover = false
13
14 export default {
15 props: {
16 id: {
17 type: String,
18 required: true
19 },
20 url: {
21 type: String,
22 required: true
23 },
24 clickable: {
25 type: Boolean,
26 default: true
27 },
28 defaultMsg: {
29 type: String,
30 default: '上传图片'
31 },
32 acceptedFiles: {
33 type: String,
34 default: ''
35 },
36 thumbnailHeight: {
37 type: Number,
38 default: 200
39 },
40 thumbnailWidth: {
41 type: Number,
42 default: 200
43 },
44 showRemoveLink: {
45 type: Boolean,
46 default: true
47 },
48 maxFilesize: {
49 type: Number,
50 default: 2
51 },
52 maxFiles: {
53 type: Number,
54 default: 3
55 },
56 autoProcessQueue: {
57 type: Boolean,
58 default: true
59 },
60 useCustomDropzoneOptions: {
61 type: Boolean,
62 default: false
63 },
64 defaultImg: {
65 default: '',
66 type: [String, Array]
67 },
68 couldPaste: {
69 type: Boolean,
70 default: false
71 }
72 },
73 data() {
74 return {
75 dropzone: '',
76 initOnce: true
77 }
78 },
79 watch: {
80 defaultImg(val) {
81 if (val.length === 0) {
82 this.initOnce = false
83 return
84 }
85 if (!this.initOnce) return
86 this.initImages(val)
87 this.initOnce = false
88 }
89 },
90 mounted() {
91 const element = document.getElementById(this.id)
92 const vm = this
93 this.dropzone = new Dropzone(element, {
94 clickable: this.clickable,
95 thumbnailWidth: this.thumbnailWidth,
96 thumbnailHeight: this.thumbnailHeight,
97 maxFiles: this.maxFiles,
98 maxFilesize: this.maxFilesize,
99 dictRemoveFile: 'Remove',
100 addRemoveLinks: this.showRemoveLink,
101 acceptedFiles: this.acceptedFiles,
102 autoProcessQueue: this.autoProcessQueue,
103 dictDefaultMessage: '<i style="margin-top: 3em;display: inline-block" class="material-icons">' + this.defaultMsg + '</i><br>Drop files here to upload',
104 dictMaxFilesExceeded: '只能一个图',
105 previewTemplate: '<div class="dz-preview dz-file-preview"> <div class="dz-image" style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" ><img style="width:' + this.thumbnailWidth + 'px;height:' + this.thumbnailHeight + 'px" data-dz-thumbnail /></div> <div class="dz-details"><div class="dz-size"><span data-dz-size></span></div> <div class="dz-progress"><span class="dz-upload" data-dz-uploadprogress></span></div> <div class="dz-error-message"><span data-dz-errormessage></span></div> <div class="dz-success-mark"> <i class="material-icons">done</i> </div> <div class="dz-error-mark"><i class="material-icons">error</i></div></div>',
106 init() {
107 const val = vm.defaultImg
108 if (!val) return
109 if (Array.isArray(val)) {
110 if (val.length === 0) return
111 val.map((v, i) => {
112 const mockFile = { name: 'name' + i, size: 12345, url: v }
113 this.options.addedfile.call(this, mockFile)
114 this.options.thumbnail.call(this, mockFile, v)
115 mockFile.previewElement.classList.add('dz-success')
116 mockFile.previewElement.classList.add('dz-complete')
117 vm.initOnce = false
118 return true
119 })
120 } else {
121 const mockFile = { name: 'name', size: 12345, url: val }
122 this.options.addedfile.call(this, mockFile)
123 this.options.thumbnail.call(this, mockFile, val)
124 mockFile.previewElement.classList.add('dz-success')
125 mockFile.previewElement.classList.add('dz-complete')
126 vm.initOnce = false
127 }
128 },
129 accept: (file, done) => {
130 /* 七牛*/
131 // const token = this.$store.getters.token;
132 // getToken(token).then(response => {
133 // file.token = response.data.qiniu_token;
134 // file.key = response.data.qiniu_key;
135 // file.url = response.data.qiniu_url;
136 // done();
137 // })
138 done()
139 },
140 sending: (file, xhr, formData) => {
141 // formData.append('token', file.token);
142 // formData.append('key', file.key);
143 vm.initOnce = false
144 }
145 })
146
147 if (this.couldPaste) {
148 document.addEventListener('paste', this.pasteImg)
149 }
150
151 this.dropzone.on('success', file => {
152 vm.$emit('dropzone-success', file, vm.dropzone.element)
153 })
154 this.dropzone.on('addedfile', file => {
155 vm.$emit('dropzone-fileAdded', file)
156 })
157 this.dropzone.on('removedfile', file => {
158 vm.$emit('dropzone-removedFile', file)
159 })
160 this.dropzone.on('error', (file, error, xhr) => {
161 vm.$emit('dropzone-error', file, error, xhr)
162 })
163 this.dropzone.on('successmultiple', (file, error, xhr) => {
164 vm.$emit('dropzone-successmultiple', file, error, xhr)
165 })
166 },
167 destroyed() {
168 document.removeEventListener('paste', this.pasteImg)
169 this.dropzone.destroy()
170 },
171 methods: {
172 removeAllFiles() {
173 this.dropzone.removeAllFiles(true)
174 },
175 processQueue() {
176 this.dropzone.processQueue()
177 },
178 pasteImg(event) {
179 const items = (event.clipboardData || event.originalEvent.clipboardData).items
180 if (items[0].kind === 'file') {
181 this.dropzone.addFile(items[0].getAsFile())
182 }
183 },
184 initImages(val) {
185 if (!val) return
186 if (Array.isArray(val)) {
187 val.map((v, i) => {
188 const mockFile = { name: 'name' + i, size: 12345, url: v }
189 this.dropzone.options.addedfile.call(this.dropzone, mockFile)
190 this.dropzone.options.thumbnail.call(this.dropzone, mockFile, v)
191 mockFile.previewElement.classList.add('dz-success')
192 mockFile.previewElement.classList.add('dz-complete')
193 return true
194 })
195 } else {
196 const mockFile = { name: 'name', size: 12345, url: val }
197 this.dropzone.options.addedfile.call(this.dropzone, mockFile)
198 this.dropzone.options.thumbnail.call(this.dropzone, mockFile, val)
199 mockFile.previewElement.classList.add('dz-success')
200 mockFile.previewElement.classList.add('dz-complete')
201 }
202 }
203
204 }
205 }
206 </script>
207
208 <style scoped>
209 .dropzone {
210 border: 2px solid #E5E5E5;
211 font-family: 'Roboto', sans-serif;
212 color: #777;
213 transition: background-color .2s linear;
214 padding: 5px;
215 }
216
217 .dropzone:hover {
218 background-color: #F6F6F6;
219 }
220
221 i {
222 color: #CCC;
223 }
224
225 .dropzone .dz-image img {
226 width: 100%;
227 height: 100%;
228 }
229
230 .dropzone input[name='file'] {
231 display: none;
232 }
233
234 .dropzone .dz-preview .dz-image {
235 border-radius: 0px;
236 }
237
238 .dropzone .dz-preview:hover .dz-image img {
239 transform: none;
240 filter: none;
241 width: 100%;
242 height: 100%;
243 }
244
245 .dropzone .dz-preview .dz-details {
246 bottom: 0px;
247 top: 0px;
248 color: white;
249 background-color: rgba(33, 150, 243, 0.8);
250 transition: opacity .2s linear;
251 text-align: left;
252 }
253
254 .dropzone .dz-preview .dz-details .dz-filename span, .dropzone .dz-preview .dz-details .dz-size span {
255 background-color: transparent;
256 }
257
258 .dropzone .dz-preview .dz-details .dz-filename:not(:hover) span {
259 border: none;
260 }
261
262 .dropzone .dz-preview .dz-details .dz-filename:hover span {
263 background-color: transparent;
264 border: none;
265 }
266
267 .dropzone .dz-preview .dz-remove {
268 position: absolute;
269 z-index: 30;
270 color: white;
271 margin-left: 15px;
272 padding: 10px;
273 top: inherit;
274 bottom: 15px;
275 border: 2px white solid;
276 text-decoration: none;
277 text-transform: uppercase;
278 font-size: 0.8rem;
279 font-weight: 800;
280 letter-spacing: 1.1px;
281 opacity: 0;
282 }
283
284 .dropzone .dz-preview:hover .dz-remove {
285 opacity: 1;
286 }
287
288 .dropzone .dz-preview .dz-success-mark, .dropzone .dz-preview .dz-error-mark {
289 margin-left: -40px;
290 margin-top: -50px;
291 }
292
293 .dropzone .dz-preview .dz-success-mark i, .dropzone .dz-preview .dz-error-mark i {
294 color: white;
295 font-size: 5rem;
296 }
297 </style>
298
src/components/ErrorLog/index.vue
File was created 1 <template>
2 <div v-if="errorLogs.length>0">
3 <el-badge :is-dot="true" style="line-height: 25px;margin-top: -5px;" @click.native="dialogTableVisible=true">
4 <el-button style="padding: 8px 10px;" size="small" type="danger">
5 <svg-icon icon-class="bug" />
6 </el-button>
7 </el-badge>
8
9 <el-dialog :visible.sync="dialogTableVisible" width="80%" append-to-body>
10 <div slot="title">
11 <span style="padding-right: 10px;">Error Log</span>
12 <el-button size="mini" type="primary" icon="el-icon-delete" @click="clearAll">Clear All</el-button>
13 </div>
14 <el-table :data="errorLogs" border>
15 <el-table-column label="Message">
16 <template slot-scope="{row}">
17 <div>
18 <span class="message-title">Msg:</span>
19 <el-tag type="danger">
20 {{ row.err.message }}
21 </el-tag>
22 </div>
23 <br>
24 <div>
25 <span class="message-title" style="padding-right: 10px;">Info: </span>
26 <el-tag type="warning">
27 {{ row.vm.$vnode.tag }} error in {{ row.info }}
28 </el-tag>
29 </div>
30 <br>
31 <div>
32 <span class="message-title" style="padding-right: 16px;">Url: </span>
33 <el-tag type="success">
34 {{ row.url }}
35 </el-tag>
36 </div>
37 </template>
38 </el-table-column>
39 <el-table-column label="Stack">
40 <template slot-scope="scope">
41 {{ scope.row.err.stack }}
42 </template>
43 </el-table-column>
44 </el-table>
45 </el-dialog>
46 </div>
47 </template>
48
49 <script>
50 export default {
51 name: 'ErrorLog',
52 data() {
53 return {
54 dialogTableVisible: false
55 }
56 },
57 computed: {
58 errorLogs() {
59 return this.$store.getters.errorLogs
60 }
61 },
62 methods: {
63 clearAll() {
64 this.dialogTableVisible = false
65 this.$store.dispatch('errorLog/clearErrorLog')
66 }
67 }
68 }
69 </script>
70
71 <style scoped>
72 .message-title {
73 font-size: 16px;
74 color: #333;
75 font-weight: bold;
76 padding-right: 8px;
77 }
78 </style>
79
src/components/GithubCorner/index.vue
File was created 1 <template>
2 <a href="https://github.com/PanJiaChen/vue-element-admin" target="_blank" class="github-corner" aria-label="View source on Github">
3 <svg
4 width="80"
5 height="80"
6 viewBox="0 0 250 250"
7 style="fill:#40c9c6; color:#fff;"
8 aria-hidden="true"
9 >
10 <path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z" />
11 <path
12 d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2"
13 fill="currentColor"
14 style="transform-origin: 130px 106px;"
15 class="octo-arm"
16 />
17 <path
18 d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z"
19 fill="currentColor"
20 class="octo-body"
21 />
22 </svg>
23 </a>
24 </template>
25
26 <style scoped>
27 .github-corner:hover .octo-arm {
28 animation: octocat-wave 560ms ease-in-out
29 }
30
31 @keyframes octocat-wave {
32 0%,
33 100% {
34 transform: rotate(0)
35 }
36 20%,
37 60% {
38 transform: rotate(-25deg)
39 }
40 40%,
41 80% {
42 transform: rotate(10deg)
43 }
44 }
45
46 @media (max-width:500px) {
47 .github-corner:hover .octo-arm {
48 animation: none
49 }
50 .github-corner .octo-arm {
51 animation: octocat-wave 560ms ease-in-out
52 }
53 }
54 </style>
55
src/components/Hamburger/index.vue 100644 → 100755
1 <template> 1 <template>
2 <div style="padding: 0 15px;" @click="toggleClick"> 2 <div style="padding: 0 15px;" @click="toggleClick">
3 <svg 3 <svg
4 :class="{'is-active':isActive}" 4 :class="{'is-active':isActive}"
5 class="hamburger" 5 class="hamburger"
6 viewBox="0 0 1024 1024" 6 viewBox="0 0 1024 1024"
7 xmlns="http://www.w3.org/2000/svg" 7 xmlns="http://www.w3.org/2000/svg"
8 width="64" 8 width="64"
9 height="64" 9 height="64"
10 > 10 >
11 <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" /> 11 <path d="M408 442h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8zm-8 204c0 4.4 3.6 8 8 8h480c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8H408c-4.4 0-8 3.6-8 8v56zm504-486H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zm0 632H120c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h784c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM142.4 642.1L298.7 519a8.84 8.84 0 0 0 0-13.9L142.4 381.9c-5.8-4.6-14.4-.5-14.4 6.9v246.3a8.9 8.9 0 0 0 14.4 7z" />
12 </svg> 12 </svg>
13 </div> 13 </div>
14 </template> 14 </template>
15 15
16 <script> 16 <script>
17 export default { 17 export default {
18 name: 'Hamburger', 18 name: 'Hamburger',
19 props: { 19 props: {
20 isActive: { 20 isActive: {
21 type: Boolean, 21 type: Boolean,
22 default: false 22 default: false
23 } 23 }
24 }, 24 },
25 methods: { 25 methods: {
26 toggleClick() { 26 toggleClick() {
27 this.$emit('toggleClick') 27 this.$emit('toggleClick')
28 } 28 }
29 } 29 }
30 } 30 }
31 </script> 31 </script>
32 32
33 <style scoped> 33 <style scoped>
34 .hamburger { 34 .hamburger {
35 display: inline-block; 35 display: inline-block;
36 vertical-align: middle; 36 vertical-align: middle;
37 width: 20px; 37 width: 20px;
38 height: 20px; 38 height: 20px;
39 } 39 }
40 40
41 .hamburger.is-active { 41 .hamburger.is-active {
42 transform: rotate(180deg); 42 transform: rotate(180deg);
43 } 43 }
44 </style> 44 </style>
45 45
src/components/HeaderSearch/index.vue
File was created 1 <template>
2 <div :class="{'show':show}" class="header-search">
3 <svg-icon class-name="search-icon" icon-class="search" @click.stop="click" />
4 <el-select
5 ref="headerSearchSelect"
6 v-model="search"
7 :remote-method="querySearch"
8 filterable
9 default-first-option
10 remote
11 placeholder="Search"
12 class="header-search-select"
13 @change="change"
14 >
15 <el-option v-for="item in options" :key="item.path" :value="item" :label="item.title.join(' > ')" />
16 </el-select>
17 </div>
18 </template>
19
20 <script>
21 // fuse is a lightweight fuzzy-search module
22 // make search results more in line with expectations
23 import Fuse from 'fuse.js'
24 import path from 'path'
25 import i18n from '@/lang'
26
27 export default {
28 name: 'HeaderSearch',
29 data() {
30 return {
31 search: '',
32 options: [],
33 searchPool: [],
34 show: false,
35 fuse: undefined
36 }
37 },
38 computed: {
39 routes() {
40 return this.$store.getters.permission_routes
41 },
42 lang() {
43 return this.$store.getters.language
44 },
45 supportPinyinSearch() {
46 return this.$store.state.settings.supportPinyinSearch
47 }
48 },
49 watch: {
50 lang() {
51 this.searchPool = this.generateRoutes(this.routes)
52 },
53 routes() {
54 this.searchPool = this.generateRoutes(this.routes)
55 },
56 searchPool(list) {
57 // Support pinyin search
58 if (this.lang === 'zh' && this.supportPinyinSearch) {
59 this.addPinyinField(list)
60 }
61 this.initFuse(list)
62 },
63 show(value) {
64 if (value) {
65 document.body.addEventListener('click', this.close)
66 } else {
67 document.body.removeEventListener('click', this.close)
68 }
69 }
70 },
71 mounted() {
72 this.searchPool = this.generateRoutes(this.routes)
73 },
74 methods: {
75 async addPinyinField(list) {
76 const { default: pinyin } = await import('pinyin')
77 if (Array.isArray(list)) {
78 list.forEach(element => {
79 const title = element.title
80 if (Array.isArray(title)) {
81 title.forEach(v => {
82 v = pinyin(v, {
83 style: pinyin.STYLE_NORMAL
84 }).join('')
85 element.pinyinTitle = v
86 })
87 }
88 })
89 return list
90 }
91 },
92 click() {
93 this.show = !this.show
94 if (this.show) {
95 this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.focus()
96 }
97 },
98 close() {
99 this.$refs.headerSearchSelect && this.$refs.headerSearchSelect.blur()
100 this.options = []
101 this.show = false
102 },
103 change(val) {
104 this.$router.push(val.path)
105 this.search = ''
106 this.options = []
107 this.$nextTick(() => {
108 this.show = false
109 })
110 },
111 initFuse(list) {
112 this.fuse = new Fuse(list, {
113 shouldSort: true,
114 threshold: 0.4,
115 location: 0,
116 distance: 100,
117 maxPatternLength: 32,
118 minMatchCharLength: 1,
119 keys: [{
120 name: 'title',
121 weight: 0.7
122 }, {
123 name: 'pinyinTitle',
124 weight: 0.3
125 }, {
126 name: 'path',
127 weight: 0.3
128 }]
129 })
130 },
131 // Filter out the routes that can be displayed in the sidebar
132 // And generate the internationalized title
133 generateRoutes(routes, basePath = '/', prefixTitle = []) {
134 let res = []
135 for (const router of routes) {
136 // skip hidden router
137 if (router.hidden) { continue }
138 const data = {
139 path: path.resolve(basePath, router.path),
140 title: [...prefixTitle]
141 }
142 if (router.meta && router.meta.title) {
143 // generate internationalized title
144 const i18ntitle = i18n.t(`route.${router.meta.title}`)
145 data.title = [...data.title, i18ntitle]
146 if (router.redirect !== 'noRedirect') {
147 // only push the routes with title
148 // special case: need to exclude parent router without redirect
149 res.push(data)
150 }
151 }
152 // recursive child routes
153 if (router.children) {
154 const tempRoutes = this.generateRoutes(router.children, data.path, data.title)
155 if (tempRoutes.length >= 1) {
156 res = [...res, ...tempRoutes]
157 }
158 }
159 }
160 return res
161 },
162 querySearch(query) {
163 if (query !== '') {
164 this.options = this.fuse.search(query)
165 } else {
166 this.options = []
167 }
168 }
169 }
170 }
171 </script>
172
173 <style lang="scss" scoped>
174 .header-search {
175 font-size: 0 !important;
176 .search-icon {
177 cursor: pointer;
178 font-size: 18px;
179 vertical-align: middle;
180 }
181 .header-search-select {
182 font-size: 18px;
183 transition: width 0.2s;
184 width: 0;
185 overflow: hidden;
186 background: transparent;
187 border-radius: 0;
188 display: inline-block;
189 vertical-align: middle;
190 /deep/ .el-input__inner {
191 border-radius: 0;
192 border: 0;
193 padding-left: 0;
194 padding-right: 0;
195 box-shadow: none !important;
196 border-bottom: 1px solid #d9d9d9;
197 vertical-align: middle;
198 }
199 }
200 &.show {
201 .header-search-select {
202 width: 210px;
203 margin-left: 10px;
204 }
205 }
206 }
207 </style>
208
src/components/ImageCropper/index.vue
File was created 1 <template>
2 <div v-show="value" class="vue-image-crop-upload">
3 <div class="vicp-wrap">
4 <div class="vicp-close" @click="off">
5 <i class="vicp-icon4" />
6 </div>
7
8 <div v-show="step == 1" class="vicp-step1">
9 <div
10 class="vicp-drop-area"
11 @dragleave="preventDefault"
12 @dragover="preventDefault"
13 @dragenter="preventDefault"
14 @click="handleClick"
15 @drop="handleChange"
16 >
17 <i v-show="loading != 1" class="vicp-icon1">
18 <i class="vicp-icon1-arrow" />
19 <i class="vicp-icon1-body" />
20 <i class="vicp-icon1-bottom" />
21 </i>
22 <span v-show="loading !== 1" class="vicp-hint">{{ lang.hint }}</span>
23 <span v-show="!isSupported" class="vicp-no-supported-hint">{{ lang.noSupported }}</span>
24 <input v-show="false" v-if="step == 1" ref="fileinput" type="file" @change="handleChange">
25 </div>
26 <div v-show="hasError" class="vicp-error">
27 <i class="vicp-icon2" />
28 {{ errorMsg }}
29 </div>
30 <div class="vicp-operate">
31 <a @click="off" @mousedown="ripple">{{ lang.btn.off }}</a>
32 </div>
33 </div>
34
35 <div v-if="step == 2" class="vicp-step2">
36 <div class="vicp-crop">
37 <div v-show="true" class="vicp-crop-left">
38 <div class="vicp-img-container">
39 <img
40 ref="img"
41 :src="sourceImgUrl"
42 :style="sourceImgStyle"
43 class="vicp-img"
44 draggable="false"
45 @drag="preventDefault"
46 @dragstart="preventDefault"
47 @dragend="preventDefault"
48 @dragleave="preventDefault"
49 @dragover="preventDefault"
50 @dragenter="preventDefault"
51 @drop="preventDefault"
52 @touchstart="imgStartMove"
53 @touchmove="imgMove"
54 @touchend="createImg"
55 @touchcancel="createImg"
56 @mousedown="imgStartMove"
57 @mousemove="imgMove"
58 @mouseup="createImg"
59 @mouseout="createImg"
60 >
61 <div :style="sourceImgShadeStyle" class="vicp-img-shade vicp-img-shade-1" />
62 <div :style="sourceImgShadeStyle" class="vicp-img-shade vicp-img-shade-2" />
63 </div>
64
65 <div class="vicp-range">
66 <input
67 :value="scale.range"
68 type="range"
69 step="1"
70 min="0"
71 max="100"
72 @input="zoomChange"
73 >
74 <i
75 class="vicp-icon5"
76 @mousedown="startZoomSub"
77 @mouseout="endZoomSub"
78 @mouseup="endZoomSub"
79 />
80 <i
81 class="vicp-icon6"
82 @mousedown="startZoomAdd"
83 @mouseout="endZoomAdd"
84 @mouseup="endZoomAdd"
85 />
86 </div>
87
88 <div v-if="!noRotate" class="vicp-rotate">
89 <i @mousedown="startRotateLeft" @mouseout="endRotate" @mouseup="endRotate">↺</i>
90 <i @mousedown="startRotateRight" @mouseout="endRotate" @mouseup="endRotate">↻</i>
91 </div>
92 </div>
93 <div v-show="true" class="vicp-crop-right">
94 <div class="vicp-preview">
95 <div v-if="!noSquare" class="vicp-preview-item">
96 <img :src="createImgUrl" :style="previewStyle">
97 <span>{{ lang.preview }}</span>
98 </div>
99 <div v-if="!noCircle" class="vicp-preview-item vicp-preview-item-circle">
100 <img :src="createImgUrl" :style="previewStyle">
101 <span>{{ lang.preview }}</span>
102 </div>
103 </div>
104 </div>
105 </div>
106 <div class="vicp-operate">
107 <a @click="setStep(1)" @mousedown="ripple">{{ lang.btn.back }}</a>
108 <a class="vicp-operate-btn" @click="prepareUpload" @mousedown="ripple">{{ lang.btn.save }}</a>
109 </div>
110 </div>
111
112 <div v-if="step == 3" class="vicp-step3">
113 <div class="vicp-upload">
114 <span v-show="loading === 1" class="vicp-loading">{{ lang.loading }}</span>
115 <div class="vicp-progress-wrap">
116 <span v-show="loading === 1" :style="progressStyle" class="vicp-progress" />
117 </div>
118 <div v-show="hasError" class="vicp-error">
119 <i class="vicp-icon2" />
120 {{ errorMsg }}
121 </div>
122 <div v-show="loading === 2" class="vicp-success">
123 <i class="vicp-icon3" />
124 {{ lang.success }}
125 </div>
126 </div>
127 <div class="vicp-operate">
128 <a @click="setStep(2)" @mousedown="ripple">{{ lang.btn.back }}</a>
129 <a @click="off" @mousedown="ripple">{{ lang.btn.close }}</a>
130 </div>
131 </div>
132 <canvas v-show="false" ref="canvas" :width="width" :height="height" />
133 </div>
134 </div>
135 </template>
136
137 <script>
138 'use strict'
139 import request from '@/utils/request'
140 import language from './utils/language.js'
141 import mimes from './utils/mimes.js'
142 import data2blob from './utils/data2blob.js'
143 import effectRipple from './utils/effectRipple.js'
144 export default {
145 props: {
146 // 域,上传文件name,触发事件会带上(如果一个页面多个图片上传控件,可以做区分
147 field: {
148 type: String,
149 default: 'avatar'
150 },
151 // 原名key,类似于id,触发事件会带上(如果一个页面多个图片上传控件,可以做区分
152 ki: {
153 type: Number,
154 default: 0
155 },
156 // 显示该控件与否
157 value: {
158 type: Boolean,
159 default: true
160 },
161 // 上传地址
162 url: {
163 type: String,
164 default: ''
165 },
166 // 其他要上传文件附带的数据,对象格式
167 params: {
168 type: Object,
169 default: null
170 },
171 // Add custom headers
172 headers: {
173 type: Object,
174 default: null
175 },
176 // 剪裁图片的宽
177 width: {
178 type: Number,
179 default: 200
180 },
181 // 剪裁图片的高
182 height: {
183 type: Number,
184 default: 200
185 },
186 // 不显示旋转功能
187 noRotate: {
188 type: Boolean,
189 default: true
190 },
191 // 不预览圆形图片
192 noCircle: {
193 type: Boolean,
194 default: false
195 },
196 // 不预览方形图片
197 noSquare: {
198 type: Boolean,
199 default: false
200 },
201 // 单文件大小限制
202 maxSize: {
203 type: Number,
204 default: 10240
205 },
206 // 语言类型
207 langType: {
208 type: String,
209 default: 'zh'
210 },
211 // 语言包
212 langExt: {
213 type: Object,
214 default: null
215 },
216 // 图片上传格式
217 imgFormat: {
218 type: String,
219 default: 'png'
220 },
221 // 是否支持跨域
222 withCredentials: {
223 type: Boolean,
224 default: false
225 }
226 },
227 data() {
228 const { imgFormat, langType, langExt, width, height } = this
229 let isSupported = true
230 const allowImgFormat = ['jpg', 'png']
231 const tempImgFormat =
232 allowImgFormat.indexOf(imgFormat) === -1 ? 'jpg' : imgFormat
233 const lang = language[langType] ? language[langType] : language['en']
234 const mime = mimes[tempImgFormat]
235 // 规范图片格式
236 this.imgFormat = tempImgFormat
237 if (langExt) {
238 Object.assign(lang, langExt)
239 }
240 if (typeof FormData !== 'function') {
241 isSupported = false
242 }
243 return {
244 // 图片的mime
245 mime,
246 // 语言包
247 lang,
248 // 浏览器是否支持该控件
249 isSupported,
250 // 浏览器是否支持触屏事件
251 isSupportTouch: document.hasOwnProperty('ontouchstart'),
252 // 步骤
253 step: 1, // 1选择文件 2剪裁 3上传
254 // 上传状态及进度
255 loading: 0, // 0未开始 1正在 2成功 3错误
256 progress: 0,
257 // 是否有错误及错误信息
258 hasError: false,
259 errorMsg: '',
260 // 需求图宽高比
261 ratio: width / height,
262 // 原图地址、生成图片地址
263 sourceImg: null,
264 sourceImgUrl: '',
265 createImgUrl: '',
266 // 原图片拖动事件初始值
267 sourceImgMouseDown: {
268 on: false,
269 mX: 0, // 鼠标按下的坐标
270 mY: 0,
271 x: 0, // scale原图坐标
272 y: 0
273 },
274 // 生成图片预览的容器大小
275 previewContainer: {
276 width: 100,
277 height: 100
278 },
279 // 原图容器宽高
280 sourceImgContainer: {
281 // sic
282 width: 240,
283 height: 184 // 如果生成图比例与此一致会出现bug,先改成特殊的格式吧,哈哈哈
284 },
285 // 原图展示属性
286 scale: {
287 zoomAddOn: false, // 按钮缩放事件开启
288 zoomSubOn: false, // 按钮缩放事件开启
289 range: 1, // 最大100
290 rotateLeft: false, // 按钮向左旋转事件开启
291 rotateRight: false, // 按钮向右旋转事件开启
292 degree: 0, // 旋转度数
293 x: 0,
294 y: 0,
295 width: 0,
296 height: 0,
297 maxWidth: 0,
298 maxHeight: 0,
299 minWidth: 0, // 最宽
300 minHeight: 0,
301 naturalWidth: 0, // 原宽
302 naturalHeight: 0
303 }
304 }
305 },
306 computed: {
307 // 进度条样式
308 progressStyle() {
309 const { progress } = this
310 return {
311 width: progress + '%'
312 }
313 },
314 // 原图样式
315 sourceImgStyle() {
316 const { scale, sourceImgMasking } = this
317 const top = scale.y + sourceImgMasking.y + 'px'
318 const left = scale.x + sourceImgMasking.x + 'px'
319 return {
320 top,
321 left,
322 width: scale.width + 'px',
323 height: scale.height + 'px',
324 transform: 'rotate(' + scale.degree + 'deg)', // 旋转时 左侧原始图旋转样式
325 '-ms-transform': 'rotate(' + scale.degree + 'deg)', // 兼容IE9
326 '-moz-transform': 'rotate(' + scale.degree + 'deg)', // 兼容FireFox
327 '-webkit-transform': 'rotate(' + scale.degree + 'deg)', // 兼容Safari 和 chrome
328 '-o-transform': 'rotate(' + scale.degree + 'deg)' // 兼容 Opera
329 }
330 },
331 // 原图蒙版属性
332 sourceImgMasking() {
333 const { width, height, ratio, sourceImgContainer } = this
334 const sic = sourceImgContainer
335 const sicRatio = sic.width / sic.height // 原图容器宽高比
336 let x = 0
337 let y = 0
338 let w = sic.width
339 let h = sic.height
340 let scale = 1
341 if (ratio < sicRatio) {
342 scale = sic.height / height
343 w = sic.height * ratio
344 x = (sic.width - w) / 2
345 }
346 if (ratio > sicRatio) {
347 scale = sic.width / width
348 h = sic.width / ratio
349 y = (sic.height - h) / 2
350 }
351 return {
352 scale, // 蒙版相对需求宽高的缩放
353 x,
354 y,
355 width: w,
356 height: h
357 }
358 },
359 // 原图遮罩样式
360 sourceImgShadeStyle() {
361 const { sourceImgMasking, sourceImgContainer } = this
362 const sic = sourceImgContainer
363 const sim = sourceImgMasking
364 const w =
365 sim.width === sic.width ? sim.width : (sic.width - sim.width) / 2
366 const h =
367 sim.height === sic.height ? sim.height : (sic.height - sim.height) / 2
368 return {
369 width: w + 'px',
370 height: h + 'px'
371 }
372 },
373 previewStyle() {
374 const { ratio, previewContainer } = this
375 const pc = previewContainer
376 let w = pc.width
377 let h = pc.height
378 const pcRatio = w / h
379 if (ratio < pcRatio) {
380 w = pc.height * ratio
381 }
382 if (ratio > pcRatio) {
383 h = pc.width / ratio
384 }
385 return {
386 width: w + 'px',
387 height: h + 'px'
388 }
389 }
390 },
391 watch: {
392 value(newValue) {
393 if (newValue && this.loading !== 1) {
394 this.reset()
395 }
396 }
397 },
398 created() {
399 // 绑定按键esc隐藏此插件事件
400 document.addEventListener('keyup', this.closeHandler)
401 },
402 destroyed() {
403 document.removeEventListener('keyup', this.closeHandler)
404 },
405 methods: {
406 // 点击波纹效果
407 ripple(e) {
408 effectRipple(e)
409 },
410 // 关闭控件
411 off() {
412 setTimeout(() => {
413 this.$emit('input', false)
414 this.$emit('close')
415 if (this.step === 3 && this.loading === 2) {
416 this.setStep(1)
417 }
418 }, 200)
419 },
420 // 设置步骤
421 setStep(no) {
422 // 延时是为了显示动画效果呢,哈哈哈
423 setTimeout(() => {
424 this.step = no
425 }, 200)
426 },
427 /* 图片选择区域函数绑定
428 ---------------------------------------------------------------*/
429 preventDefault(e) {
430 e.preventDefault()
431 return false
432 },
433 handleClick(e) {
434 if (this.loading !== 1) {
435 if (e.target !== this.$refs.fileinput) {
436 e.preventDefault()
437 if (document.activeElement !== this.$refs) {
438 this.$refs.fileinput.click()
439 }
440 }
441 }
442 },
443 handleChange(e) {
444 e.preventDefault()
445 if (this.loading !== 1) {
446 const files = e.target.files || e.dataTransfer.files
447 this.reset()
448 if (this.checkFile(files[0])) {
449 this.setSourceImg(files[0])
450 }
451 }
452 },
453 /* ---------------------------------------------------------------*/
454 // 检测选择的文件是否合适
455 checkFile(file) {
456 const { lang, maxSize } = this
457 // 仅限图片
458 if (file.type.indexOf('image') === -1) {
459 this.hasError = true
460 this.errorMsg = lang.error.onlyImg
461 return false
462 }
463 // 超出大小
464 if (file.size / 1024 > maxSize) {
465 this.hasError = true
466 this.errorMsg = lang.error.outOfSize + maxSize + 'kb'
467 return false
468 }
469 return true
470 },
471 // 重置控件
472 reset() {
473 this.loading = 0
474 this.hasError = false
475 this.errorMsg = ''
476 this.progress = 0
477 },
478 // 设置图片源
479 setSourceImg(file) {
480 const fr = new FileReader()
481 fr.onload = e => {
482 this.sourceImgUrl = fr.result
483 this.startCrop()
484 }
485 fr.readAsDataURL(file)
486 },
487 // 剪裁前准备工作
488 startCrop() {
489 const {
490 width,
491 height,
492 ratio,
493 scale,
494 sourceImgUrl,
495 sourceImgMasking,
496 lang
497 } = this
498 const sim = sourceImgMasking
499 const img = new Image()
500 img.src = sourceImgUrl
501 img.onload = () => {
502 const nWidth = img.naturalWidth
503 const nHeight = img.naturalHeight
504 const nRatio = nWidth / nHeight
505 let w = sim.width
506 let h = sim.height
507 let x = 0
508 let y = 0
509 // 图片像素不达标
510 if (nWidth < width || nHeight < height) {
511 this.hasError = true
512 this.errorMsg = lang.error.lowestPx + width + '*' + height
513 return false
514 }
515 if (ratio > nRatio) {
516 h = w / nRatio
517 y = (sim.height - h) / 2
518 }
519 if (ratio < nRatio) {
520 w = h * nRatio
521 x = (sim.width - w) / 2
522 }
523 scale.range = 0
524 scale.x = x
525 scale.y = y
526 scale.width = w
527 scale.height = h
528 scale.degree = 0
529 scale.minWidth = w
530 scale.minHeight = h
531 scale.maxWidth = nWidth * sim.scale
532 scale.maxHeight = nHeight * sim.scale
533 scale.naturalWidth = nWidth
534 scale.naturalHeight = nHeight
535 this.sourceImg = img
536 this.createImg()
537 this.setStep(2)
538 }
539 },
540 // 鼠标按下图片准备移动
541 imgStartMove(e) {
542 e.preventDefault()
543 // 支持触摸事件,则鼠标事件无效
544 if (this.isSupportTouch && !e.targetTouches) {
545 return false
546 }
547 const et = e.targetTouches ? e.targetTouches[0] : e
548 const { sourceImgMouseDown, scale } = this
549 const simd = sourceImgMouseDown
550 simd.mX = et.screenX
551 simd.mY = et.screenY
552 simd.x = scale.x
553 simd.y = scale.y
554 simd.on = true
555 },
556 // 鼠标按下状态下移动,图片移动
557 imgMove(e) {
558 e.preventDefault()
559 // 支持触摸事件,则鼠标事件无效
560 if (this.isSupportTouch && !e.targetTouches) {
561 return false
562 }
563 const et = e.targetTouches ? e.targetTouches[0] : e
564 const {
565 sourceImgMouseDown: { on, mX, mY, x, y },
566 scale,
567 sourceImgMasking
568 } = this
569 const sim = sourceImgMasking
570 const nX = et.screenX
571 const nY = et.screenY
572 const dX = nX - mX
573 const dY = nY - mY
574 let rX = x + dX
575 let rY = y + dY
576 if (!on) return
577 if (rX > 0) {
578 rX = 0
579 }
580 if (rY > 0) {
581 rY = 0
582 }
583 if (rX < sim.width - scale.width) {
584 rX = sim.width - scale.width
585 }
586 if (rY < sim.height - scale.height) {
587 rY = sim.height - scale.height
588 }
589 scale.x = rX
590 scale.y = rY
591 },
592 // 按钮按下开始向右旋转
593 startRotateRight(e) {
594 const { scale } = this
595 scale.rotateRight = true
596 const rotate = () => {
597 if (scale.rotateRight) {
598 const degree = ++scale.degree
599 this.createImg(degree)
600 setTimeout(function() {
601 rotate()
602 }, 60)
603 }
604 }
605 rotate()
606 },
607 // 按钮按下开始向左旋转
608 startRotateLeft(e) {
609 const { scale } = this
610 scale.rotateLeft = true
611 const rotate = () => {
612 if (scale.rotateLeft) {
613 const degree = --scale.degree
614 this.createImg(degree)
615 setTimeout(function() {
616 rotate()
617 }, 60)
618 }
619 }
620 rotate()
621 },
622 // 停止旋转
623 endRotate() {
624 const { scale } = this
625 scale.rotateLeft = false
626 scale.rotateRight = false
627 },
628 // 按钮按下开始放大
629 startZoomAdd(e) {
630 const { scale } = this
631 scale.zoomAddOn = true
632 const zoom = () => {
633 if (scale.zoomAddOn) {
634 const range = scale.range >= 100 ? 100 : ++scale.range
635 this.zoomImg(range)
636 setTimeout(function() {
637 zoom()
638 }, 60)
639 }
640 }
641 zoom()
642 },
643 // 按钮松开或移开取消放大
644 endZoomAdd(e) {
645 this.scale.zoomAddOn = false
646 },
647 // 按钮按下开始缩小
648 startZoomSub(e) {
649 const { scale } = this
650 scale.zoomSubOn = true
651 const zoom = () => {
652 if (scale.zoomSubOn) {
653 const range = scale.range <= 0 ? 0 : --scale.range
654 this.zoomImg(range)
655 setTimeout(function() {
656 zoom()
657 }, 60)
658 }
659 }
660 zoom()
661 },
662 // 按钮松开或移开取消缩小
663 endZoomSub(e) {
664 const { scale } = this
665 scale.zoomSubOn = false
666 },
667 zoomChange(e) {
668 this.zoomImg(e.target.value)
669 },
670 // 缩放原图
671 zoomImg(newRange) {
672 const { sourceImgMasking, scale } = this
673 const {
674 maxWidth,
675 maxHeight,
676 minWidth,
677 minHeight,
678 width,
679 height,
680 x,
681 y
682 } = scale
683 const sim = sourceImgMasking
684 // 蒙版宽高
685 const sWidth = sim.width
686 const sHeight = sim.height
687 // 新宽高
688 const nWidth = minWidth + ((maxWidth - minWidth) * newRange) / 100
689 const nHeight = minHeight + ((maxHeight - minHeight) * newRange) / 100
690 // 新坐标(根据蒙版中心点缩放)
691 let nX = sWidth / 2 - (nWidth / width) * (sWidth / 2 - x)
692 let nY = sHeight / 2 - (nHeight / height) * (sHeight / 2 - y)
693 // 判断新坐标是否超过蒙版限制
694 if (nX > 0) {
695 nX = 0
696 }
697 if (nY > 0) {
698 nY = 0
699 }
700 if (nX < sWidth - nWidth) {
701 nX = sWidth - nWidth
702 }
703 if (nY < sHeight - nHeight) {
704 nY = sHeight - nHeight
705 }
706 // 赋值处理
707 scale.x = nX
708 scale.y = nY
709 scale.width = nWidth
710 scale.height = nHeight
711 scale.range = newRange
712 setTimeout(() => {
713 if (scale.range === newRange) {
714 this.createImg()
715 }
716 }, 300)
717 },
718 // 生成需求图片
719 createImg(e) {
720 const {
721 mime,
722 sourceImg,
723 scale: { x, y, width, height, degree },
724 sourceImgMasking: { scale }
725 } = this
726 const canvas = this.$refs.canvas
727 const ctx = canvas.getContext('2d')
728 if (e) {
729 // 取消鼠标按下移动状态
730 this.sourceImgMouseDown.on = false
731 }
732 canvas.width = this.width
733 canvas.height = this.height
734 ctx.clearRect(0, 0, this.width, this.height)
735 // 将透明区域设置为白色底边
736 ctx.fillStyle = '#fff'
737 ctx.fillRect(0, 0, this.width, this.height)
738 ctx.translate(this.width * 0.5, this.height * 0.5)
739 ctx.rotate((Math.PI * degree) / 180)
740 ctx.translate(-this.width * 0.5, -this.height * 0.5)
741 ctx.drawImage(
742 sourceImg,
743 x / scale,
744 y / scale,
745 width / scale,
746 height / scale
747 )
748 this.createImgUrl = canvas.toDataURL(mime)
749 },
750 prepareUpload() {
751 const { url, createImgUrl, field, ki } = this
752 this.$emit('crop-success', createImgUrl, field, ki)
753 if (typeof url === 'string' && url) {
754 this.upload()
755 } else {
756 this.off()
757 }
758 },
759 // 上传图片
760 upload() {
761 const {
762 lang,
763 imgFormat,
764 mime,
765 url,
766 params,
767 field,
768 ki,
769 createImgUrl
770 } = this
771 const fmData = new FormData()
772 fmData.append(
773 field,
774 data2blob(createImgUrl, mime),
775 field + '.' + imgFormat
776 )
777 // 添加其他参数
778 if (typeof params === 'object' && params) {
779 Object.keys(params).forEach(k => {
780 fmData.append(k, params[k])
781 })
782 }
783 // 监听进度回调
784 // const uploadProgress = (event) => {
785 // if (event.lengthComputable) {
786 // this.progress = 100 * Math.round(event.loaded) / event.total
787 // }
788 // }
789 // 上传文件
790 this.reset()
791 this.loading = 1
792 this.setStep(3)
793 request({
794 url,
795 method: 'post',
796 data: fmData
797 })
798 .then(resData => {
799 this.loading = 2
800 this.$emit('crop-upload-success', resData.data)
801 })
802 .catch(err => {
803 if (this.value) {
804 this.loading = 3
805 this.hasError = true
806 this.errorMsg = lang.fail
807 this.$emit('crop-upload-fail', err, field, ki)
808 }
809 })
810 },
811 closeHandler(e) {
812 if (this.value && (e.key === 'Escape' || e.keyCode === 27)) {
813 this.off()
814 }
815 }
816 }
817 }
818 </script>
819
820 <style lang="scss">
821 @charset "UTF-8";
822 @-webkit-keyframes vicp_progress {
823 0% {
824 background-position-y: 0;
825 }
826 100% {
827 background-position-y: 40px;
828 }
829 }
830 @keyframes vicp_progress {
831 0% {
832 background-position-y: 0;
833 }
834 100% {
835 background-position-y: 40px;
836 }
837 }
838 @-webkit-keyframes vicp {
839 0% {
840 opacity: 0;
841 -webkit-transform: scale(0) translatey(-60px);
842 transform: scale(0) translatey(-60px);
843 }
844 100% {
845 opacity: 1;
846 -webkit-transform: scale(1) translatey(0);
847 transform: scale(1) translatey(0);
848 }
849 }
850 @keyframes vicp {
851 0% {
852 opacity: 0;
853 -webkit-transform: scale(0) translatey(-60px);
854 transform: scale(0) translatey(-60px);
855 }
856 100% {
857 opacity: 1;
858 -webkit-transform: scale(1) translatey(0);
859 transform: scale(1) translatey(0);
860 }
861 }
862 .vue-image-crop-upload {
863 position: fixed;
864 display: block;
865 -webkit-box-sizing: border-box;
866 box-sizing: border-box;
867 z-index: 10000;
868 top: 0;
869 bottom: 0;
870 left: 0;
871 right: 0;
872 width: 100%;
873 height: 100%;
874 background-color: rgba(0, 0, 0, 0.65);
875 -webkit-tap-highlight-color: transparent;
876 -moz-tap-highlight-color: transparent;
877 }
878 .vue-image-crop-upload .vicp-wrap {
879 -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
880 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
881 position: fixed;
882 display: block;
883 -webkit-box-sizing: border-box;
884 box-sizing: border-box;
885 z-index: 10000;
886 top: 0;
887 bottom: 0;
888 left: 0;
889 right: 0;
890 margin: auto;
891 width: 600px;
892 height: 330px;
893 padding: 25px;
894 background-color: #fff;
895 border-radius: 2px;
896 -webkit-animation: vicp 0.12s ease-in;
897 animation: vicp 0.12s ease-in;
898 }
899 .vue-image-crop-upload .vicp-wrap .vicp-close {
900 position: absolute;
901 right: -30px;
902 top: -30px;
903 }
904 .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4 {
905 position: relative;
906 display: block;
907 width: 30px;
908 height: 30px;
909 cursor: pointer;
910 -webkit-transition: -webkit-transform 0.18s;
911 transition: -webkit-transform 0.18s;
912 transition: transform 0.18s;
913 transition: transform 0.18s, -webkit-transform 0.18s;
914 -webkit-transform: rotate(0);
915 -ms-transform: rotate(0);
916 transform: rotate(0);
917 }
918 .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::after,
919 .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::before {
920 -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
921 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
922 content: "";
923 position: absolute;
924 top: 12px;
925 left: 4px;
926 width: 20px;
927 height: 3px;
928 -webkit-transform: rotate(45deg);
929 -ms-transform: rotate(45deg);
930 transform: rotate(45deg);
931 background-color: #fff;
932 }
933 .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::after {
934 -webkit-transform: rotate(-45deg);
935 -ms-transform: rotate(-45deg);
936 transform: rotate(-45deg);
937 }
938 .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4:hover {
939 -webkit-transform: rotate(90deg);
940 -ms-transform: rotate(90deg);
941 transform: rotate(90deg);
942 }
943 .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area {
944 position: relative;
945 -webkit-box-sizing: border-box;
946 box-sizing: border-box;
947 padding: 35px;
948 height: 170px;
949 background-color: rgba(0, 0, 0, 0.03);
950 text-align: center;
951 border: 1px dashed rgba(0, 0, 0, 0.08);
952 overflow: hidden;
953 }
954 .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 {
955 display: block;
956 margin: 0 auto 6px;
957 width: 42px;
958 height: 42px;
959 overflow: hidden;
960 }
961 .vue-image-crop-upload
962 .vicp-wrap
963 .vicp-step1
964 .vicp-drop-area
965 .vicp-icon1
966 .vicp-icon1-arrow {
967 display: block;
968 margin: 0 auto;
969 width: 0;
970 height: 0;
971 border-bottom: 14.7px solid rgba(0, 0, 0, 0.3);
972 border-left: 14.7px solid transparent;
973 border-right: 14.7px solid transparent;
974 }
975 .vue-image-crop-upload
976 .vicp-wrap
977 .vicp-step1
978 .vicp-drop-area
979 .vicp-icon1
980 .vicp-icon1-body {
981 display: block;
982 width: 12.6px;
983 height: 14.7px;
984 margin: 0 auto;
985 background-color: rgba(0, 0, 0, 0.3);
986 }
987 .vue-image-crop-upload
988 .vicp-wrap
989 .vicp-step1
990 .vicp-drop-area
991 .vicp-icon1
992 .vicp-icon1-bottom {
993 -webkit-box-sizing: border-box;
994 box-sizing: border-box;
995 display: block;
996 height: 12.6px;
997 border: 6px solid rgba(0, 0, 0, 0.3);
998 border-top: none;
999 }
1000 .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-hint {
1001 display: block;
1002 padding: 15px;
1003 font-size: 14px;
1004 color: #666;
1005 line-height: 30px;
1006 }
1007 .vue-image-crop-upload
1008 .vicp-wrap
1009 .vicp-step1
1010 .vicp-drop-area
1011 .vicp-no-supported-hint {
1012 display: block;
1013 position: absolute;
1014 top: 0;
1015 left: 0;
1016 padding: 30px;
1017 width: 100%;
1018 height: 60px;
1019 line-height: 30px;
1020 background-color: #eee;
1021 text-align: center;
1022 color: #666;
1023 font-size: 14px;
1024 }
1025 .vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area:hover {
1026 cursor: pointer;
1027 border-color: rgba(0, 0, 0, 0.1);
1028 background-color: rgba(0, 0, 0, 0.05);
1029 }
1030 .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop {
1031 overflow: hidden;
1032 }
1033 .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left {
1034 float: left;
1035 }
1036 .vue-image-crop-upload
1037 .vicp-wrap
1038 .vicp-step2
1039 .vicp-crop
1040 .vicp-crop-left
1041 .vicp-img-container {
1042 position: relative;
1043 display: block;
1044 width: 240px;
1045 height: 180px;
1046 background-color: #e5e5e0;
1047 overflow: hidden;
1048 }
1049 .vue-image-crop-upload
1050 .vicp-wrap
1051 .vicp-step2
1052 .vicp-crop
1053 .vicp-crop-left
1054 .vicp-img-container
1055 .vicp-img {
1056 position: absolute;
1057 display: block;
1058 cursor: move;
1059 -webkit-user-select: none;
1060 -moz-user-select: none;
1061 -ms-user-select: none;
1062 user-select: none;
1063 }
1064 .vue-image-crop-upload
1065 .vicp-wrap
1066 .vicp-step2
1067 .vicp-crop
1068 .vicp-crop-left
1069 .vicp-img-container
1070 .vicp-img-shade {
1071 -webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
1072 box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
1073 position: absolute;
1074 background-color: rgba(241, 242, 243, 0.8);
1075 }
1076 .vue-image-crop-upload
1077 .vicp-wrap
1078 .vicp-step2
1079 .vicp-crop
1080 .vicp-crop-left
1081 .vicp-img-container
1082 .vicp-img-shade.vicp-img-shade-1 {
1083 top: 0;
1084 left: 0;
1085 }
1086 .vue-image-crop-upload
1087 .vicp-wrap
1088 .vicp-step2
1089 .vicp-crop
1090 .vicp-crop-left
1091 .vicp-img-container
1092 .vicp-img-shade.vicp-img-shade-2 {
1093 bottom: 0;
1094 right: 0;
1095 }
1096 .vue-image-crop-upload
1097 .vicp-wrap
1098 .vicp-step2
1099 .vicp-crop
1100 .vicp-crop-left
1101 .vicp-rotate {
1102 position: relative;
1103 width: 240px;
1104 height: 18px;
1105 }
1106 .vue-image-crop-upload
1107 .vicp-wrap
1108 .vicp-step2
1109 .vicp-crop
1110 .vicp-crop-left
1111 .vicp-rotate
1112 i {
1113 display: block;
1114 width: 18px;
1115 height: 18px;
1116 border-radius: 100%;
1117 line-height: 18px;
1118 text-align: center;
1119 font-size: 12px;
1120 font-weight: bold;
1121 background-color: rgba(0, 0, 0, 0.08);
1122 color: #fff;
1123 overflow: hidden;
1124 }
1125 .vue-image-crop-upload
1126 .vicp-wrap
1127 .vicp-step2
1128 .vicp-crop
1129 .vicp-crop-left
1130 .vicp-rotate
1131 i:hover {
1132 -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
1133 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
1134 cursor: pointer;
1135 background-color: rgba(0, 0, 0, 0.14);
1136 }
1137 .vue-image-crop-upload
1138 .vicp-wrap
1139 .vicp-step2
1140 .vicp-crop
1141 .vicp-crop-left
1142 .vicp-rotate
1143 i:first-child {
1144 float: left;
1145 }
1146 .vue-image-crop-upload
1147 .vicp-wrap
1148 .vicp-step2
1149 .vicp-crop
1150 .vicp-crop-left
1151 .vicp-rotate
1152 i:last-child {
1153 float: right;
1154 }
1155 .vue-image-crop-upload
1156 .vicp-wrap
1157 .vicp-step2
1158 .vicp-crop
1159 .vicp-crop-left
1160 .vicp-range {
1161 position: relative;
1162 margin: 30px 0 10px 0;
1163 width: 240px;
1164 height: 18px;
1165 }
1166 .vue-image-crop-upload
1167 .vicp-wrap
1168 .vicp-step2
1169 .vicp-crop
1170 .vicp-crop-left
1171 .vicp-range
1172 .vicp-icon5,
1173 .vue-image-crop-upload
1174 .vicp-wrap
1175 .vicp-step2
1176 .vicp-crop
1177 .vicp-crop-left
1178 .vicp-range
1179 .vicp-icon6 {
1180 position: absolute;
1181 top: 0;
1182 width: 18px;
1183 height: 18px;
1184 border-radius: 100%;
1185 background-color: rgba(0, 0, 0, 0.08);
1186 }
1187 .vue-image-crop-upload
1188 .vicp-wrap
1189 .vicp-step2
1190 .vicp-crop
1191 .vicp-crop-left
1192 .vicp-range
1193 .vicp-icon5:hover,
1194 .vue-image-crop-upload
1195 .vicp-wrap
1196 .vicp-step2
1197 .vicp-crop
1198 .vicp-crop-left
1199 .vicp-range
1200 .vicp-icon6:hover {
1201 -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
1202 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
1203 cursor: pointer;
1204 background-color: rgba(0, 0, 0, 0.14);
1205 }
1206 .vue-image-crop-upload
1207 .vicp-wrap
1208 .vicp-step2
1209 .vicp-crop
1210 .vicp-crop-left
1211 .vicp-range
1212 .vicp-icon5 {
1213 left: 0;
1214 }
1215 .vue-image-crop-upload
1216 .vicp-wrap
1217 .vicp-step2
1218 .vicp-crop
1219 .vicp-crop-left
1220 .vicp-range
1221 .vicp-icon5::before {
1222 position: absolute;
1223 content: "";
1224 display: block;
1225 left: 3px;
1226 top: 8px;
1227 width: 12px;
1228 height: 2px;
1229 background-color: #fff;
1230 }
1231 .vue-image-crop-upload
1232 .vicp-wrap
1233 .vicp-step2
1234 .vicp-crop
1235 .vicp-crop-left
1236 .vicp-range
1237 .vicp-icon6 {
1238 right: 0;
1239 }
1240 .vue-image-crop-upload
1241 .vicp-wrap
1242 .vicp-step2
1243 .vicp-crop
1244 .vicp-crop-left
1245 .vicp-range
1246 .vicp-icon6::before {
1247 position: absolute;
1248 content: "";
1249 display: block;
1250 left: 3px;
1251 top: 8px;
1252 width: 12px;
1253 height: 2px;
1254 background-color: #fff;
1255 }
1256 .vue-image-crop-upload
1257 .vicp-wrap
1258 .vicp-step2
1259 .vicp-crop
1260 .vicp-crop-left
1261 .vicp-range
1262 .vicp-icon6::after {
1263 position: absolute;
1264 content: "";
1265 display: block;
1266 top: 3px;
1267 left: 8px;
1268 width: 2px;
1269 height: 12px;
1270 background-color: #fff;
1271 }
1272 .vue-image-crop-upload
1273 .vicp-wrap
1274 .vicp-step2
1275 .vicp-crop
1276 .vicp-crop-left
1277 .vicp-range
1278 input[type="range"] {
1279 display: block;
1280 padding-top: 5px;
1281 margin: 0 auto;
1282 width: 180px;
1283 height: 8px;
1284 vertical-align: top;
1285 background: transparent;
1286 -webkit-appearance: none;
1287 -moz-appearance: none;
1288 appearance: none;
1289 cursor: pointer;
1290 /* 滑块
1291 ---------------------------------------------------------------*/
1292 /* 轨道
1293 ---------------------------------------------------------------*/
1294 }
1295 .vue-image-crop-upload
1296 .vicp-wrap
1297 .vicp-step2
1298 .vicp-crop
1299 .vicp-crop-left
1300 .vicp-range
1301 input[type="range"]:focus {
1302 outline: none;
1303 }
1304 .vue-image-crop-upload
1305 .vicp-wrap
1306 .vicp-step2
1307 .vicp-crop
1308 .vicp-crop-left
1309 .vicp-range
1310 input[type="range"]::-webkit-slider-thumb {
1311 -webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
1312 box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
1313 -webkit-appearance: none;
1314 appearance: none;
1315 margin-top: -3px;
1316 width: 12px;
1317 height: 12px;
1318 background-color: #61c091;
1319 border-radius: 100%;
1320 border: none;
1321 -webkit-transition: 0.2s;
1322 transition: 0.2s;
1323 }
1324 .vue-image-crop-upload
1325 .vicp-wrap
1326 .vicp-step2
1327 .vicp-crop
1328 .vicp-crop-left
1329 .vicp-range
1330 input[type="range"]::-moz-range-thumb {
1331 box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
1332 -moz-appearance: none;
1333 appearance: none;
1334 width: 12px;
1335 height: 12px;
1336 background-color: #61c091;
1337 border-radius: 100%;
1338 border: none;
1339 -webkit-transition: 0.2s;
1340 transition: 0.2s;
1341 }
1342 .vue-image-crop-upload
1343 .vicp-wrap
1344 .vicp-step2
1345 .vicp-crop
1346 .vicp-crop-left
1347 .vicp-range
1348 input[type="range"]::-ms-thumb {
1349 box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
1350 appearance: none;
1351 width: 12px;
1352 height: 12px;
1353 background-color: #61c091;
1354 border: none;
1355 border-radius: 100%;
1356 -webkit-transition: 0.2s;
1357 transition: 0.2s;
1358 }
1359 .vue-image-crop-upload
1360 .vicp-wrap
1361 .vicp-step2
1362 .vicp-crop
1363 .vicp-crop-left
1364 .vicp-range
1365 input[type="range"]:active::-moz-range-thumb {
1366 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
1367 width: 14px;
1368 height: 14px;
1369 }
1370 .vue-image-crop-upload
1371 .vicp-wrap
1372 .vicp-step2
1373 .vicp-crop
1374 .vicp-crop-left
1375 .vicp-range
1376 input[type="range"]:active::-ms-thumb {
1377 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
1378 width: 14px;
1379 height: 14px;
1380 }
1381 .vue-image-crop-upload
1382 .vicp-wrap
1383 .vicp-step2
1384 .vicp-crop
1385 .vicp-crop-left
1386 .vicp-range
1387 input[type="range"]:active::-webkit-slider-thumb {
1388 -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
1389 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
1390 margin-top: -4px;
1391 width: 14px;
1392 height: 14px;
1393 }
1394 .vue-image-crop-upload
1395 .vicp-wrap
1396 .vicp-step2
1397 .vicp-crop
1398 .vicp-crop-left
1399 .vicp-range
1400 input[type="range"]::-webkit-slider-runnable-track {
1401 -webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
1402 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
1403 width: 100%;
1404 height: 6px;
1405 cursor: pointer;
1406 border-radius: 2px;
1407 border: none;
1408 background-color: rgba(68, 170, 119, 0.3);
1409 }
1410 .vue-image-crop-upload
1411 .vicp-wrap
1412 .vicp-step2
1413 .vicp-crop
1414 .vicp-crop-left
1415 .vicp-range
1416 input[type="range"]::-moz-range-track {
1417 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
1418 width: 100%;
1419 height: 6px;
1420 cursor: pointer;
1421 border-radius: 2px;
1422 border: none;
1423 background-color: rgba(68, 170, 119, 0.3);
1424 }
1425 .vue-image-crop-upload
1426 .vicp-wrap
1427 .vicp-step2
1428 .vicp-crop
1429 .vicp-crop-left
1430 .vicp-range
1431 input[type="range"]::-ms-track {
1432 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
1433 width: 100%;
1434 cursor: pointer;
1435 background: transparent;
1436 border-color: transparent;
1437 color: transparent;
1438 height: 6px;
1439 border-radius: 2px;
1440 border: none;
1441 }
1442 .vue-image-crop-upload
1443 .vicp-wrap
1444 .vicp-step2
1445 .vicp-crop
1446 .vicp-crop-left
1447 .vicp-range
1448 input[type="range"]::-ms-fill-lower {
1449 background-color: rgba(68, 170, 119, 0.3);
1450 }
1451 .vue-image-crop-upload
1452 .vicp-wrap
1453 .vicp-step2
1454 .vicp-crop
1455 .vicp-crop-left
1456 .vicp-range
1457 input[type="range"]::-ms-fill-upper {
1458 background-color: rgba(68, 170, 119, 0.15);
1459 }
1460 .vue-image-crop-upload
1461 .vicp-wrap
1462 .vicp-step2
1463 .vicp-crop
1464 .vicp-crop-left
1465 .vicp-range
1466 input[type="range"]:focus::-webkit-slider-runnable-track {
1467 background-color: rgba(68, 170, 119, 0.5);
1468 }
1469 .vue-image-crop-upload
1470 .vicp-wrap
1471 .vicp-step2
1472 .vicp-crop
1473 .vicp-crop-left
1474 .vicp-range
1475 input[type="range"]:focus::-moz-range-track {
1476 background-color: rgba(68, 170, 119, 0.5);
1477 }
1478 .vue-image-crop-upload
1479 .vicp-wrap
1480 .vicp-step2
1481 .vicp-crop
1482 .vicp-crop-left
1483 .vicp-range
1484 input[type="range"]:focus::-ms-fill-lower {
1485 background-color: rgba(68, 170, 119, 0.45);
1486 }
1487 .vue-image-crop-upload
1488 .vicp-wrap
1489 .vicp-step2
1490 .vicp-crop
1491 .vicp-crop-left
1492 .vicp-range
1493 input[type="range"]:focus::-ms-fill-upper {
1494 background-color: rgba(68, 170, 119, 0.25);
1495 }
1496 .vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right {
1497 float: right;
1498 }
1499 .vue-image-crop-upload
1500 .vicp-wrap
1501 .vicp-step2
1502 .vicp-crop
1503 .vicp-crop-right
1504 .vicp-preview {
1505 height: 150px;
1506 overflow: hidden;
1507 }
1508 .vue-image-crop-upload
1509 .vicp-wrap
1510 .vicp-step2
1511 .vicp-crop
1512 .vicp-crop-right
1513 .vicp-preview
1514 .vicp-preview-item {
1515 position: relative;
1516 padding: 5px;
1517 width: 100px;
1518 height: 100px;
1519 float: left;
1520 margin-right: 16px;
1521 }
1522 .vue-image-crop-upload
1523 .vicp-wrap
1524 .vicp-step2
1525 .vicp-crop
1526 .vicp-crop-right
1527 .vicp-preview
1528 .vicp-preview-item
1529 span {
1530 position: absolute;
1531 bottom: -30px;
1532 width: 100%;
1533 font-size: 14px;
1534 color: #bbb;
1535 display: block;
1536 text-align: center;
1537 }
1538 .vue-image-crop-upload
1539 .vicp-wrap
1540 .vicp-step2
1541 .vicp-crop
1542 .vicp-crop-right
1543 .vicp-preview
1544 .vicp-preview-item
1545 img {
1546 position: absolute;
1547 display: block;
1548 top: 0;
1549 bottom: 0;
1550 left: 0;
1551 right: 0;
1552 margin: auto;
1553 padding: 3px;
1554 background-color: #fff;
1555 border: 1px solid rgba(0, 0, 0, 0.15);
1556 overflow: hidden;
1557 -webkit-user-select: none;
1558 -moz-user-select: none;
1559 -ms-user-select: none;
1560 user-select: none;
1561 }
1562 .vue-image-crop-upload
1563 .vicp-wrap
1564 .vicp-step2
1565 .vicp-crop
1566 .vicp-crop-right
1567 .vicp-preview
1568 .vicp-preview-item.vicp-preview-item-circle {
1569 margin-right: 0;
1570 }
1571 .vue-image-crop-upload
1572 .vicp-wrap
1573 .vicp-step2
1574 .vicp-crop
1575 .vicp-crop-right
1576 .vicp-preview
1577 .vicp-preview-item.vicp-preview-item-circle
1578 img {
1579 border-radius: 100%;
1580 }
1581 .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload {
1582 position: relative;
1583 -webkit-box-sizing: border-box;
1584 box-sizing: border-box;
1585 padding: 35px;
1586 height: 170px;
1587 background-color: rgba(0, 0, 0, 0.03);
1588 text-align: center;
1589 border: 1px dashed #ddd;
1590 }
1591 .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-loading {
1592 display: block;
1593 padding: 15px;
1594 font-size: 16px;
1595 color: #999;
1596 line-height: 30px;
1597 }
1598 .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap {
1599 margin-top: 12px;
1600 background-color: rgba(0, 0, 0, 0.08);
1601 border-radius: 3px;
1602 }
1603 .vue-image-crop-upload
1604 .vicp-wrap
1605 .vicp-step3
1606 .vicp-upload
1607 .vicp-progress-wrap
1608 .vicp-progress {
1609 position: relative;
1610 display: block;
1611 height: 5px;
1612 border-radius: 3px;
1613 background-color: #4a7;
1614 -webkit-box-shadow: 0 2px 6px 0 rgba(68, 170, 119, 0.3);
1615 box-shadow: 0 2px 6px 0 rgba(68, 170, 119, 0.3);
1616 -webkit-transition: width 0.15s linear;
1617 transition: width 0.15s linear;
1618 background-image: -webkit-linear-gradient(
1619 135deg,
1620 rgba(255, 255, 255, 0.2) 25%,
1621 transparent 25%,
1622 transparent 50%,
1623 rgba(255, 255, 255, 0.2) 50%,
1624 rgba(255, 255, 255, 0.2) 75%,
1625 transparent 75%,
1626 transparent
1627 );
1628 background-image: linear-gradient(
1629 -45deg,
1630 rgba(255, 255, 255, 0.2) 25%,
1631 transparent 25%,
1632 transparent 50%,
1633 rgba(255, 255, 255, 0.2) 50%,
1634 rgba(255, 255, 255, 0.2) 75%,
1635 transparent 75%,
1636 transparent
1637 );
1638 background-size: 40px 40px;
1639 -webkit-animation: vicp_progress 0.5s linear infinite;
1640 animation: vicp_progress 0.5s linear infinite;
1641 }
1642 .vue-image-crop-upload
1643 .vicp-wrap
1644 .vicp-step3
1645 .vicp-upload
1646 .vicp-progress-wrap
1647 .vicp-progress::after {
1648 content: "";
1649 position: absolute;
1650 display: block;
1651 top: -3px;
1652 right: -3px;
1653 width: 9px;
1654 height: 9px;
1655 border: 1px solid rgba(245, 246, 247, 0.7);
1656 -webkit-box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7);
1657 box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7);
1658 border-radius: 100%;
1659 background-color: #4a7;
1660 }
1661 .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-error,
1662 .vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-success {
1663 height: 100px;
1664 line-height: 100px;
1665 }
1666 .vue-image-crop-upload .vicp-wrap .vicp-operate {
1667 position: absolute;
1668 right: 20px;
1669 bottom: 20px;
1670 }
1671 .vue-image-crop-upload .vicp-wrap .vicp-operate a {
1672 position: relative;
1673 float: left;
1674 display: block;
1675 margin-left: 10px;
1676 width: 100px;
1677 height: 36px;
1678 line-height: 36px;
1679 text-align: center;
1680 cursor: pointer;
1681 font-size: 14px;
1682 color: #4a7;
1683 border-radius: 2px;
1684 overflow: hidden;
1685 -webkit-user-select: none;
1686 -moz-user-select: none;
1687 -ms-user-select: none;
1688 user-select: none;
1689 }
1690 .vue-image-crop-upload .vicp-wrap .vicp-operate a:hover {
1691 background-color: rgba(0, 0, 0, 0.03);
1692 }
1693 .vue-image-crop-upload .vicp-wrap .vicp-error,
1694 .vue-image-crop-upload .vicp-wrap .vicp-success {
1695 display: block;
1696 font-size: 14px;
1697 line-height: 24px;
1698 height: 24px;
1699 color: #d10;
1700 text-align: center;
1701 vertical-align: top;
1702 }
1703 .vue-image-crop-upload .vicp-wrap .vicp-success {
1704 color: #4a7;
1705 }
1706 .vue-image-crop-upload .vicp-wrap .vicp-icon3 {
1707 position: relative;
1708 display: inline-block;
1709 width: 20px;
1710 height: 20px;
1711 top: 4px;
1712 }
1713 .vue-image-crop-upload .vicp-wrap .vicp-icon3::after {
1714 position: absolute;
1715 top: 3px;
1716 left: 6px;
1717 width: 6px;
1718 height: 10px;
1719 border-width: 0 2px 2px 0;
1720 border-color: #4a7;
1721 border-style: solid;
1722 -webkit-transform: rotate(45deg);
1723 -ms-transform: rotate(45deg);
1724 transform: rotate(45deg);
1725 content: "";
1726 }
1727 .vue-image-crop-upload .vicp-wrap .vicp-icon2 {
1728 position: relative;
1729 display: inline-block;
1730 width: 20px;
1731 height: 20px;
1732 top: 4px;
1733 }
1734 .vue-image-crop-upload .vicp-wrap .vicp-icon2::after,
1735 .vue-image-crop-upload .vicp-wrap .vicp-icon2::before {
1736 content: "";
1737 position: absolute;
1738 top: 9px;
1739 left: 4px;
1740 width: 13px;
1741 height: 2px;
1742 background-color: #d10;
1743 -webkit-transform: rotate(45deg);
1744 -ms-transform: rotate(45deg);
1745 transform: rotate(45deg);
1746 }
1747 .vue-image-crop-upload .vicp-wrap .vicp-icon2::after {
1748 -webkit-transform: rotate(-45deg);
1749 -ms-transform: rotate(-45deg);
1750 transform: rotate(-45deg);
1751 }
1752 .e-ripple {
1753 position: absolute;
1754 border-radius: 100%;
1755 background-color: rgba(0, 0, 0, 0.15);
1756 background-clip: padding-box;
1757 pointer-events: none;
1758 -webkit-user-select: none;
1759 -moz-user-select: none;
1760 -ms-user-select: none;
1761 user-select: none;
1762 -webkit-transform: scale(0);
1763 -ms-transform: scale(0);
1764 transform: scale(0);
1765 opacity: 1;
1766 }
1767 .e-ripple.z-active {
1768 opacity: 0;
1769 -webkit-transform: scale(2);
1770 -ms-transform: scale(2);
1771 transform: scale(2);
1772 -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
1773 transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
1774 transition: opacity 1.2s ease-out, transform 0.6s ease-out;
1775 transition: opacity 1.2s ease-out, transform 0.6s ease-out,
1776 -webkit-transform 0.6s ease-out;
1777 }
1778 </style>
1779
src/components/ImageCropper/utils/data2blob.js
File was created 1 /**
2 * database64文件格式转换为2进制
3 *
4 * @param {[String]} data dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了
5 * @param {[String]} mime [description]
6 * @return {[blob]} [description]
7 */
8 export default function(data, mime) {
9 data = data.split(',')[1]
10 data = window.atob(data)
11 var ia = new Uint8Array(data.length)
12 for (var i = 0; i < data.length; i++) {
13 ia[i] = data.charCodeAt(i)
14 }
15 // canvas.toDataURL 返回的默认格式就是 image/png
16 return new Blob([ia], {
17 type: mime
18 })
19 }
20
src/components/ImageCropper/utils/effectRipple.js
File was created 1 /**
2 * 点击波纹效果
3 *
4 * @param {[event]} e [description]
5 * @param {[Object]} arg_opts [description]
6 * @return {[bollean]} [description]
7 */
8 export default function(e, arg_opts) {
9 var opts = Object.assign({
10 ele: e.target, // 波纹作用元素
11 type: 'hit', // hit点击位置扩散center中心点扩展
12 bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
13 }, arg_opts)
14 var target = opts.ele
15 if (target) {
16 var rect = target.getBoundingClientRect()
17 var ripple = target.querySelector('.e-ripple')
18 if (!ripple) {
19 ripple = document.createElement('span')
20 ripple.className = 'e-ripple'
21 ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
22 target.appendChild(ripple)
23 } else {
24 ripple.className = 'e-ripple'
25 }
26 switch (opts.type) {
27 case 'center':
28 ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px'
29 ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'
30 break
31 default:
32 ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px'
33 ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px'
34 }
35 ripple.style.backgroundColor = opts.bgc
36 ripple.className = 'e-ripple z-active'
37 return false
38 }
39 }
40
src/components/ImageCropper/utils/language.js
File was created 1 export default {
2 zh: {
3 hint: '点击,或拖动图片至此处',
4 loading: '正在上传……',
5 noSupported: '浏览器不支持该功能,请使用IE10以上或其他现在浏览器!',
6 success: '上传成功',
7 fail: '图片上传失败',
8 preview: '头像预览',
9 btn: {
10 off: '取消',
11 close: '关闭',
12 back: '上一步',
13 save: '保存'
14 },
15 error: {
16 onlyImg: '仅限图片格式',
17 outOfSize: '单文件大小不能超过 ',
18 lowestPx: '图片最低像素为(宽*高):'
19 }
20 },
21 'zh-tw': {
22 hint: '點擊,或拖動圖片至此處',
23 loading: '正在上傳……',
24 noSupported: '瀏覽器不支持該功能,請使用IE10以上或其他現代瀏覽器!',
25 success: '上傳成功',
26 fail: '圖片上傳失敗',
27 preview: '頭像預覽',
28 btn: {
29 off: '取消',
30 close: '關閉',
31 back: '上一步',
32 save: '保存'
33 },
34 error: {
35 onlyImg: '僅限圖片格式',
36 outOfSize: '單文件大小不能超過 ',
37 lowestPx: '圖片最低像素為(寬*高):'
38 }
39 },
40 en: {
41 hint: 'Click or drag the file here to upload',
42 loading: 'Uploading…',
43 noSupported: 'Browser is not supported, please use IE10+ or other browsers',
44 success: 'Upload success',
45 fail: 'Upload failed',
46 preview: 'Preview',
47 btn: {
48 off: 'Cancel',
49 close: 'Close',
50 back: 'Back',
51 save: 'Save'
52 },
53 error: {
54 onlyImg: 'Image only',
55 outOfSize: 'Image exceeds size limit: ',
56 lowestPx: 'Image\'s size is too low. Expected at least: '
57 }
58 },
59 ro: {
60 hint: 'Atinge sau trage fișierul aici',
61 loading: 'Se încarcă',
62 noSupported: 'Browser-ul tău nu suportă acest feature. Te rugăm încearcă cu alt browser.',
63 success: 'S-a încărcat cu succes',
64 fail: 'A apărut o problemă la încărcare',
65 preview: 'Previzualizează',
66
67 btn: {
68 off: 'Anulează',
69 close: 'Închide',
70 back: 'Înapoi',
71 save: 'Salvează'
72 },
73
74 error: {
75 onlyImg: 'Doar imagini',
76 outOfSize: 'Imaginea depășește limita de: ',
77 loewstPx: 'Imaginea este prea mică; Minim: '
78 }
79 },
80 ru: {
81 hint: 'Нажмите, или перетащите файл в это окно',
82 loading: 'Загружаю……',
83 noSupported: 'Ваш браузер не поддерживается, пожалуйста, используйте IE10 + или другие браузеры',
84 success: 'Загрузка выполнена успешно',
85 fail: 'Ошибка загрузки',
86 preview: 'Предпросмотр',
87 btn: {
88 off: 'Отменить',
89 close: 'Закрыть',
90 back: 'Назад',
91 save: 'Сохранить'
92 },
93 error: {
94 onlyImg: 'Только изображения',
95 outOfSize: 'Изображение превышает предельный размер: ',
96 lowestPx: 'Минимальный размер изображения: '
97 }
98 },
99 'pt-br': {
100 hint: 'Clique ou arraste o arquivo aqui para carregar',
101 loading: 'Carregando…',
102 noSupported: 'Browser não suportado, use o IE10+ ou outro browser',
103 success: 'Sucesso ao carregar imagem',
104 fail: 'Falha ao carregar imagem',
105 preview: 'Pré-visualizar',
106 btn: {
107 off: 'Cancelar',
108 close: 'Fechar',
109 back: 'Voltar',
110 save: 'Salvar'
111 },
112 error: {
113 onlyImg: 'Apenas imagens',
114 outOfSize: 'A imagem excede o limite de tamanho: ',
115 lowestPx: 'O tamanho da imagem é muito pequeno. Tamanho mínimo: '
116 }
117 },
118 fr: {
119 hint: 'Cliquez ou glissez le fichier ici.',
120 loading: 'Téléchargement…',
121 noSupported: 'Votre navigateur n\'est pas supporté. Utilisez IE10 + ou un autre navigateur s\'il vous plaît.',
122 success: 'Téléchargement réussit',
123 fail: 'Téléchargement echoué',
124 preview: 'Aperçu',
125 btn: {
126 off: 'Annuler',
127 close: 'Fermer',
128 back: 'Retour',
129 save: 'Enregistrer'
130 },
131 error: {
132 onlyImg: 'Image uniquement',
133 outOfSize: 'L\'image sélectionnée dépasse la taille maximum: ',
134 lowestPx: 'L\'image sélectionnée est trop petite. Dimensions attendues: '
135 }
136 },
137 nl: {
138 hint: 'Klik hier of sleep een afbeelding in dit vlak',
139 loading: 'Uploaden…',
140 noSupported: 'Je browser wordt helaas niet ondersteund. Gebruik IE10+ of een andere browser.',
141 success: 'Upload succesvol',
142 fail: 'Upload mislukt',
143 preview: 'Voorbeeld',
144 btn: {
145 off: 'Annuleren',
146 close: 'Sluiten',
147 back: 'Terug',
148 save: 'Opslaan'
149 },
150 error: {
151 onlyImg: 'Alleen afbeeldingen',
152 outOfSize: 'De afbeelding is groter dan: ',
153 lowestPx: 'De afbeelding is te klein! Minimale afmetingen: '
154 }
155 },
156 tr: {
157 hint: 'Tıkla veya yüklemek istediğini buraya sürükle',
158 loading: 'Yükleniyor…',
159 noSupported: 'Tarayıcı desteklenmiyor, lütfen IE10+ veya farklı tarayıcı kullanın',
160 success: 'Yükleme başarılı',
161 fail: 'Yüklemede hata oluştu',
162 preview: 'Önizle',
163 btn: {
164 off: 'İptal',
165 close: 'Kapat',
166 back: 'Geri',
167 save: 'Kaydet'
168 },
169 error: {
170 onlyImg: 'Sadece resim',
171 outOfSize: 'Resim yükleme limitini aşıyor: ',
172 lowestPx: 'Resmin boyutu çok küçük. En az olması gereken: '
173 }
174 },
175 'es-MX': {
176 hint: 'Selecciona o arrastra una imagen',
177 loading: 'Subiendo...',
178 noSupported: 'Tu navegador no es soportado, porfavor usa IE10+ u otros navegadores mas recientes',
179 success: 'Subido exitosamente',
180 fail: 'Sucedió un error',
181 preview: 'Vista previa',
182 btn: {
183 off: 'Cancelar',
184 close: 'Cerrar',
185 back: 'Atras',
186 save: 'Guardar'
187 },
188 error: {
189 onlyImg: 'Unicamente imagenes',
190 outOfSize: 'La imagen excede el tamaño maximo:',
191 lowestPx: 'La imagen es demasiado pequeño. Se espera por lo menos:'
192 }
193 },
194 de: {
195 hint: 'Klick hier oder zieh eine Datei hier rein zum Hochladen',
196 loading: 'Hochladen…',
197 noSupported: 'Browser wird nicht unterstützt, bitte verwende IE10+ oder andere Browser',
198 success: 'Upload erfolgreich',
199 fail: 'Upload fehlgeschlagen',
200 preview: 'Vorschau',
201 btn: {
202 off: 'Abbrechen',
203 close: 'Schließen',
204 back: 'Zurück',
205 save: 'Speichern'
206 },
207 error: {
208 onlyImg: 'Nur Bilder',
209 outOfSize: 'Das Bild ist zu groß: ',
210 lowestPx: 'Das Bild ist zu klein. Mindestens: '
211 }
212 },
213 ja: {
214 hint: 'クリック・ドラッグしてファイルをアップロード',
215 loading: 'アップロード中...',
216 noSupported: 'このブラウザは対応されていません。IE10+かその他の主要ブラウザをお使いください。',
217 success: 'アップロード成功',
218 fail: 'アップロード失敗',
219 preview: 'プレビュー',
220 btn: {
221 off: 'キャンセル',
222 close: '閉じる',
223 back: '戻る',
224 save: '保存'
225 },
226 error: {
227 onlyImg: '画像のみ',
228 outOfSize: '画像サイズが上限を超えています。上限: ',
229 lowestPx: '画像が小さすぎます。最小サイズ: '
230 }
231 }
232 }
233
src/components/ImageCropper/utils/mimes.js
File was created 1 export default {
2 'jpg': 'image/jpeg',
3 'png': 'image/png',
4 'gif': 'image/gif',
5 'svg': 'image/svg+xml',
6 'psd': 'image/photoshop'
7 }
8
src/components/JsonEditor/index.vue
File was created 1 <template>
2 <div class="json-editor">
3 <textarea ref="textarea" />
4 </div>
5 </template>
6
7 <script>
8 import CodeMirror from 'codemirror'
9 import 'codemirror/addon/lint/lint.css'
10 import 'codemirror/lib/codemirror.css'
11 import 'codemirror/theme/rubyblue.css'
12 require('script-loader!jsonlint')
13 import 'codemirror/mode/javascript/javascript'
14 import 'codemirror/addon/lint/lint'
15 import 'codemirror/addon/lint/json-lint'
16
17 export default {
18 name: 'JsonEditor',
19 /* eslint-disable vue/require-prop-types */
20 props: ['value'],
21 data() {
22 return {
23 jsonEditor: false
24 }
25 },
26 watch: {
27 value(value) {
28 const editorValue = this.jsonEditor.getValue()
29 if (value !== editorValue) {
30 this.jsonEditor.setValue(JSON.stringify(this.value, null, 2))
31 }
32 }
33 },
34 mounted() {
35 this.jsonEditor = CodeMirror.fromTextArea(this.$refs.textarea, {
36 lineNumbers: true,
37 mode: 'application/json',
38 gutters: ['CodeMirror-lint-markers'],
39 theme: 'rubyblue',
40 lint: true
41 })
42
43 this.jsonEditor.setValue(JSON.stringify(this.value, null, 2))
44 this.jsonEditor.on('change', cm => {
45 this.$emit('changed', cm.getValue())
46 this.$emit('input', cm.getValue())
47 })
48 },
49 methods: {
50 getValue() {
51 return this.jsonEditor.getValue()
52 }
53 }
54 }
55 </script>
56
57 <style scoped>
58 .json-editor{
59 height: 100%;
60 position: relative;
61 }
62 .json-editor >>> .CodeMirror {
63 height: auto;
64 min-height: 300px;
65 }
66 .json-editor >>> .CodeMirror-scroll{
67 min-height: 300px;
68 }
69 .json-editor >>> .cm-s-rubyblue span.cm-string {
70 color: #F08047;
71 }
72 </style>
73
src/components/Kanban/index.vue
File was created 1 <template>
2 <div class="board-column">
3 <div class="board-column-header">
4 {{ headerText }}
5 </div>
6 <draggable
7 :list="list"
8 v-bind="$attrs"
9 class="board-column-content"
10 :set-data="setData"
11 >
12 <div v-for="element in list" :key="element.id" class="board-item">
13 {{ element.name }} {{ element.id }}
14 </div>
15 </draggable>
16 </div>
17 </template>
18
19 <script>
20 import draggable from 'vuedraggable'
21
22 export default {
23 name: 'DragKanbanDemo',
24 components: {
25 draggable
26 },
27 props: {
28 headerText: {
29 type: String,
30 default: 'Header'
31 },
32 options: {
33 type: Object,
34 default() {
35 return {}
36 }
37 },
38 list: {
39 type: Array,
40 default() {
41 return []
42 }
43 }
44 },
45 methods: {
46 setData(dataTransfer) {
47 // to avoid Firefox bug
48 // Detail see : https://github.com/RubaXa/Sortable/issues/1012
49 dataTransfer.setData('Text', '')
50 }
51 }
52 }
53 </script>
54 <style lang="scss" scoped>
55 .board-column {
56 min-width: 300px;
57 min-height: 100px;
58 height: auto;
59 overflow: hidden;
60 background: #f0f0f0;
61 border-radius: 3px;
62
63 .board-column-header {
64 height: 50px;
65 line-height: 50px;
66 overflow: hidden;
67 padding: 0 20px;
68 text-align: center;
69 background: #333;
70 color: #fff;
71 border-radius: 3px 3px 0 0;
72 }
73
74 .board-column-content {
75 height: auto;
76 overflow: hidden;
77 border: 10px solid transparent;
78 min-height: 60px;
79 display: flex;
80 justify-content: flex-start;
81 flex-direction: column;
82 align-items: center;
83
84 .board-item {
85 cursor: pointer;
86 width: 100%;
87 height: 64px;
88 margin: 5px 0;
89 background-color: #fff;
90 text-align: left;
91 line-height: 54px;
92 padding: 5px 10px;
93 box-sizing: border-box;
94 box-shadow: 0px 1px 3px 0 rgba(0, 0, 0, 0.2);
95 }
96 }
97 }
98 </style>
99
100
src/components/LangSelect/index.vue
File was created 1 <template>
2 <el-dropdown trigger="click" class="international" @command="handleSetLanguage">
3 <div>
4 <svg-icon class-name="international-icon" icon-class="language" />
5 </div>
6 <el-dropdown-menu slot="dropdown">
7 <el-dropdown-item :disabled="language==='zh'" command="zh">
8 中文
9 </el-dropdown-item>
10 <el-dropdown-item :disabled="language==='en'" command="en">
11 English
12 </el-dropdown-item>
13 <el-dropdown-item :disabled="language==='es'" command="es">
14 Español
15 </el-dropdown-item>
16 <el-dropdown-item :disabled="language==='ja'" command="ja">
17 日本語
18 </el-dropdown-item>
19 </el-dropdown-menu>
20 </el-dropdown>
21 </template>
22
23 <script>
24 export default {
25 computed: {
26 language() {
27 return this.$store.getters.language
28 }
29 },
30 methods: {
31 handleSetLanguage(lang) {
32 this.$i18n.locale = lang
33 this.$store.dispatch('app/setLanguage', lang)
34 this.$message({
35 message: 'Switch Language Success',
36 type: 'success'
37 })
38 }
39 }
40 }
41 </script>
42
src/components/MDinput/index.vue
File was created 1 <template>
2 <div :class="computedClasses" class="material-input__component">
3 <div :class="{iconClass:icon}">
4 <i v-if="icon" :class="['el-icon-' + icon]" class="el-input__icon material-input__icon" />
5 <input
6 v-if="type === 'email'"
7 v-model="currentValue"
8 :name="name"
9 :placeholder="fillPlaceHolder"
10 :readonly="readonly"
11 :disabled="disabled"
12 :autocomplete="autoComplete"
13 :required="required"
14 type="email"
15 class="material-input"
16 @focus="handleMdFocus"
17 @blur="handleMdBlur"
18 @input="handleModelInput"
19 >
20 <input
21 v-if="type === 'url'"
22 v-model="currentValue"
23 :name="name"
24 :placeholder="fillPlaceHolder"
25 :readonly="readonly"
26 :disabled="disabled"
27 :autocomplete="autoComplete"
28 :required="required"
29 type="url"
30 class="material-input"
31 @focus="handleMdFocus"
32 @blur="handleMdBlur"
33 @input="handleModelInput"
34 >
35 <input
36 v-if="type === 'number'"
37 v-model="currentValue"
38 :name="name"
39 :placeholder="fillPlaceHolder"
40 :step="step"
41 :readonly="readonly"
42 :disabled="disabled"
43 :autocomplete="autoComplete"
44 :max="max"
45 :min="min"
46 :minlength="minlength"
47 :maxlength="maxlength"
48 :required="required"
49 type="number"
50 class="material-input"
51 @focus="handleMdFocus"
52 @blur="handleMdBlur"
53 @input="handleModelInput"
54 >
55 <input
56 v-if="type === 'password'"
57 v-model="currentValue"
58 :name="name"
59 :placeholder="fillPlaceHolder"
60 :readonly="readonly"
61 :disabled="disabled"
62 :autocomplete="autoComplete"
63 :max="max"
64 :min="min"
65 :required="required"
66 type="password"
67 class="material-input"
68 @focus="handleMdFocus"
69 @blur="handleMdBlur"
70 @input="handleModelInput"
71 >
72 <input
73 v-if="type === 'tel'"
74 v-model="currentValue"
75 :name="name"
76 :placeholder="fillPlaceHolder"
77 :readonly="readonly"
78 :disabled="disabled"
79 :autocomplete="autoComplete"
80 :required="required"
81 type="tel"
82 class="material-input"
83 @focus="handleMdFocus"
84 @blur="handleMdBlur"
85 @input="handleModelInput"
86 >
87 <input
88 v-if="type === 'text'"
89 v-model="currentValue"
90 :name="name"
91 :placeholder="fillPlaceHolder"
92 :readonly="readonly"
93 :disabled="disabled"
94 :autocomplete="autoComplete"
95 :minlength="minlength"
96 :maxlength="maxlength"
97 :required="required"
98 type="text"
99 class="material-input"
100 @focus="handleMdFocus"
101 @blur="handleMdBlur"
102 @input="handleModelInput"
103 >
104 <span class="material-input-bar" />
105 <label class="material-label">
106 <slot />
107 </label>
108 </div>
109 </div>
110 </template>
111
112 <script>
113 // source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue
114
115 export default {
116 name: 'MdInput',
117 props: {
118 /* eslint-disable */
119 icon: String,
120 name: String,
121 type: {
122 type: String,
123 default: 'text'
124 },
125 value: [String, Number],
126 placeholder: String,
127 readonly: Boolean,
128 disabled: Boolean,
129 min: String,
130 max: String,
131 step: String,
132 minlength: Number,
133 maxlength: Number,
134 required: {
135 type: Boolean,
136 default: true
137 },
138 autoComplete: {
139 type: String,
140 default: 'off'
141 },
142 validateEvent: {
143 type: Boolean,
144 default: true
145 }
146 },
147 data() {
148 return {
149 currentValue: this.value,
150 focus: false,
151 fillPlaceHolder: null
152 }
153 },
154 computed: {
155 computedClasses() {
156 return {
157 'material--active': this.focus,
158 'material--disabled': this.disabled,
159 'material--raised': Boolean(this.focus || this.currentValue) // has value
160 }
161 }
162 },
163 watch: {
164 value(newValue) {
165 this.currentValue = newValue
166 }
167 },
168 methods: {
169 handleModelInput(event) {
170 const value = event.target.value
171 this.$emit('input', value)
172 if (this.$parent.$options.componentName === 'ElFormItem') {
173 if (this.validateEvent) {
174 this.$parent.$emit('el.form.change', [value])
175 }
176 }
177 this.$emit('change', value)
178 },
179 handleMdFocus(event) {
180 this.focus = true
181 this.$emit('focus', event)
182 if (this.placeholder && this.placeholder !== '') {
183 this.fillPlaceHolder = this.placeholder
184 }
185 },
186 handleMdBlur(event) {
187 this.focus = false
188 this.$emit('blur', event)
189 this.fillPlaceHolder = null
190 if (this.$parent.$options.componentName === 'ElFormItem') {
191 if (this.validateEvent) {
192 this.$parent.$emit('el.form.blur', [this.currentValue])
193 }
194 }
195 }
196 }
197 }
198 </script>
199
200 <style lang="scss" scoped>
201 // Fonts:
202 $font-size-base: 16px;
203 $font-size-small: 18px;
204 $font-size-smallest: 12px;
205 $font-weight-normal: normal;
206 $font-weight-bold: bold;
207 $apixel: 1px;
208 // Utils
209 $spacer: 12px;
210 $transition: 0.2s ease all;
211 $index: 0px;
212 $index-has-icon: 30px;
213 // Theme:
214 $color-white: white;
215 $color-grey: #9E9E9E;
216 $color-grey-light: #E0E0E0;
217 $color-blue: #2196F3;
218 $color-red: #F44336;
219 $color-black: black;
220 // Base clases:
221 %base-bar-pseudo {
222 content: '';
223 height: 1px;
224 width: 0;
225 bottom: 0;
226 position: absolute;
227 transition: $transition;
228 }
229
230 // Mixins:
231 @mixin slided-top() {
232 top: - ($font-size-base + $spacer);
233 left: 0;
234 font-size: $font-size-base;
235 font-weight: $font-weight-bold;
236 }
237
238 // Component:
239 .material-input__component {
240 margin-top: 36px;
241 position: relative;
242 * {
243 box-sizing: border-box;
244 }
245 .iconClass {
246 .material-input__icon {
247 position: absolute;
248 left: 0;
249 line-height: $font-size-base;
250 color: $color-blue;
251 top: $spacer;
252 width: $index-has-icon;
253 height: $font-size-base;
254 font-size: $font-size-base;
255 font-weight: $font-weight-normal;
256 pointer-events: none;
257 }
258 .material-label {
259 left: $index-has-icon;
260 }
261 .material-input {
262 text-indent: $index-has-icon;
263 }
264 }
265 .material-input {
266 font-size: $font-size-base;
267 padding: $spacer $spacer $spacer - $apixel * 10 $spacer / 2;
268 display: block;
269 width: 100%;
270 border: none;
271 line-height: 1;
272 border-radius: 0;
273 &:focus {
274 outline: none;
275 border: none;
276 border-bottom: 1px solid transparent; // fixes the height issue
277 }
278 }
279 .material-label {
280 font-weight: $font-weight-normal;
281 position: absolute;
282 pointer-events: none;
283 left: $index;
284 top: 0;
285 transition: $transition;
286 font-size: $font-size-small;
287 }
288 .material-input-bar {
289 position: relative;
290 display: block;
291 width: 100%;
292 &:before {
293 @extend %base-bar-pseudo;
294 left: 50%;
295 }
296 &:after {
297 @extend %base-bar-pseudo;
298 right: 50%;
299 }
300 }
301 // Disabled state:
302 &.material--disabled {
303 .material-input {
304 border-bottom-style: dashed;
305 }
306 }
307 // Raised state:
308 &.material--raised {
309 .material-label {
310 @include slided-top();
311 }
312 }
313 // Active state:
314 &.material--active {
315 .material-input-bar {
316 &:before,
317 &:after {
318 width: 50%;
319 }
320 }
321 }
322 }
323
324 .material-input__component {
325 background: $color-white;
326 .material-input {
327 background: none;
328 color: $color-black;
329 text-indent: $index;
330 border-bottom: 1px solid $color-grey-light;
331 }
332 .material-label {
333 color: $color-grey;
334 }
335 .material-input-bar {
336 &:before,
337 &:after {
338 background: $color-blue;
339 }
340 }
341 // Active state:
342 &.material--active {
343 .material-label {
344 color: $color-blue;
345 }
346 }
347 // Errors:
348 &.material--has-errors {
349 &.material--active .material-label {
350 color: $color-red;
351 }
352 .material-input-bar {
353 &:before,
354 &:after {
355 background: transparent;
356 }
357 }
358 }
359 }
360 </style>
361
src/components/MarkdownEditor/default-options.js
File was created 1 // doc: https://nhnent.github.io/tui.editor/api/latest/ToastUIEditor.html#ToastUIEditor
2 export default {
3 minHeight: '200px',
4 previewStyle: 'vertical',
5 useCommandShortcut: true,
6 useDefaultHTMLSanitizer: true,
7 usageStatistics: false,
8 hideModeSwitch: false,
9 toolbarItems: [
10 'heading',
11 'bold',
12 'italic',
13 'strike',
14 'divider',
15 'hr',
16 'quote',
17 'divider',
18 'ul',
19 'ol',
20 'task',
21 'indent',
22 'outdent',
23 'divider',
24 'table',
25 'image',
26 'link',
27 'divider',
28 'code',
29 'codeblock'
30 ]
31 }
32
src/components/MarkdownEditor/index.vue
File was created 1 <template>
2 <div :id="id" />
3 </template>
4
5 <script>
6 // deps for editor
7 import 'codemirror/lib/codemirror.css' // codemirror
8 import 'tui-editor/dist/tui-editor.css' // editor ui
9 import 'tui-editor/dist/tui-editor-contents.css' // editor content
10
11 import Editor from 'tui-editor'
12 import defaultOptions from './default-options'
13
14 export default {
15 name: 'MarkdownEditor',
16 props: {
17 value: {
18 type: String,
19 default: ''
20 },
21 id: {
22 type: String,
23 required: false,
24 default() {
25 return 'markdown-editor-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
26 }
27 },
28 options: {
29 type: Object,
30 default() {
31 return defaultOptions
32 }
33 },
34 mode: {
35 type: String,
36 default: 'markdown'
37 },
38 height: {
39 type: String,
40 required: false,
41 default: '300px'
42 },
43 language: {
44 type: String,
45 required: false,
46 default: 'en_US' // https://github.com/nhnent/tui.editor/tree/master/src/js/langs
47 }
48 },
49 data() {
50 return {
51 editor: null
52 }
53 },
54 computed: {
55 editorOptions() {
56 const options = Object.assign({}, defaultOptions, this.options)
57 options.initialEditType = this.mode
58 options.height = this.height
59 options.language = this.language
60 return options
61 }
62 },
63 watch: {
64 value(newValue, preValue) {
65 if (newValue !== preValue && newValue !== this.editor.getValue()) {
66 this.editor.setValue(newValue)
67 }
68 },
69 language(val) {
70 this.destroyEditor()
71 this.initEditor()
72 },
73 height(newValue) {
74 this.editor.height(newValue)
75 },
76 mode(newValue) {
77 this.editor.changeMode(newValue)
78 }
79 },
80 mounted() {
81 this.initEditor()
82 },
83 destroyed() {
84 this.destroyEditor()
85 },
86 methods: {
87 initEditor() {
88 this.editor = new Editor({
89 el: document.getElementById(this.id),
90 ...this.editorOptions
91 })
92 if (this.value) {
93 this.editor.setValue(this.value)
94 }
95 this.editor.on('change', () => {
96 this.$emit('input', this.editor.getValue())
97 })
98 },
99 destroyEditor() {
100 if (!this.editor) return
101 this.editor.off('change')
102 this.editor.remove()
103 },
104 setValue(value) {
105 this.editor.setValue(value)
106 },
107 getValue() {
108 return this.editor.getValue()
109 },
110 setHtml(value) {
111 this.editor.setHtml(value)
112 },
113 getHtml() {
114 return this.editor.getHtml()
115 }
116 }
117 }
118 </script>
119
src/components/Pagination/index.vue
File was created 1 <template>
2 <div :class="{'hidden':hidden}" class="pagination-container">
3 <el-pagination
4 :background="background"
5 :current-page.sync="currentPage"
6 :page-size.sync="pageSize"
7 :layout="layout"
8 :page-sizes="pageSizes"
9 :total="total"
10 v-bind="$attrs"
11 @size-change="handleSizeChange"
12 @current-change="handleCurrentChange"
13 />
14 </div>
15 </template>
16
17 <script>
18 import { scrollTo } from '@/utils/scroll-to'
19
20 export default {
21 name: 'Pagination',
22 props: {
23 total: {
24 required: true,
25 type: Number
26 },
27 page: {
28 type: Number,
29 default: 1
30 },
31 limit: {
32 type: Number,
33 default: 20
34 },
35 pageSizes: {
36 type: Array,
37 default() {
38 return [10, 20, 30, 50]
39 }
40 },
41 layout: {
42 type: String,
43 default: 'total, sizes, prev, pager, next, jumper'
44 },
45 background: {
46 type: Boolean,
47 default: true
48 },
49 autoScroll: {
50 type: Boolean,
51 default: true
52 },
53 hidden: {
54 type: Boolean,
55 default: false
56 }
57 },
58 computed: {
59 currentPage: {
60 get() {
61 return this.page
62 },
63 set(val) {
64 this.$emit('update:page', val)
65 }
66 },
67 pageSize: {
68 get() {
69 return this.limit
70 },
71 set(val) {
72 this.$emit('update:limit', val)
73 }
74 }
75 },
76 methods: {
77 handleSizeChange(val) {
78 this.$emit('pagination', { page: this.currentPage, limit: val })
79 if (this.autoScroll) {
80 scrollTo(0, 800)
81 }
82 },
83 handleCurrentChange(val) {
84 this.$emit('pagination', { page: val, limit: this.pageSize })
85 if (this.autoScroll) {
86 scrollTo(0, 800)
87 }
88 }
89 }
90 }
91 </script>
92
93 <style scoped>
94 .pagination-container {
95 background: #fff;
96 padding: 32px 16px;
97 }
98 .pagination-container.hidden {
99 display: none;
100 }
101 </style>
102
src/components/PanThumb/index.vue
File was created 1 <template>
2 <div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
3 <div class="pan-info">
4 <div class="pan-info-roles-container">
5 <slot />
6 </div>
7 </div>
8 <!-- eslint-disable-next-line -->
9 <div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div>
10 </div>
11 </template>
12
13 <script>
14 export default {
15 name: 'PanThumb',
16 props: {
17 image: {
18 type: String,
19 required: true
20 },
21 zIndex: {
22 type: Number,
23 default: 1
24 },
25 width: {
26 type: String,
27 default: '150px'
28 },
29 height: {
30 type: String,
31 default: '150px'
32 }
33 }
34 }
35 </script>
36
37 <style scoped>
38 .pan-item {
39 width: 200px;
40 height: 200px;
41 border-radius: 50%;
42 display: inline-block;
43 position: relative;
44 cursor: default;
45 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
46 }
47
48 .pan-info-roles-container {
49 padding: 20px;
50 text-align: center;
51 }
52
53 .pan-thumb {
54 width: 100%;
55 height: 100%;
56 background-position: center center;
57 background-size: cover;
58 border-radius: 50%;
59 overflow: hidden;
60 position: absolute;
61 transform-origin: 95% 40%;
62 transition: all 0.3s ease-in-out;
63 }
64
65 /* .pan-thumb:after {
66 content: '';
67 width: 8px;
68 height: 8px;
69 position: absolute;
70 border-radius: 50%;
71 top: 40%;
72 left: 95%;
73 margin: -4px 0 0 -4px;
74 background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
75 box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
76 } */
77
78 .pan-info {
79 position: absolute;
80 width: inherit;
81 height: inherit;
82 border-radius: 50%;
83 overflow: hidden;
84 box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
85 }
86
87 .pan-info h3 {
88 color: #fff;
89 text-transform: uppercase;
90 position: relative;
91 letter-spacing: 2px;
92 font-size: 18px;
93 margin: 0 60px;
94 padding: 22px 0 0 0;
95 height: 85px;
96 font-family: 'Open Sans', Arial, sans-serif;
97 text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
98 }
99
100 .pan-info p {
101 color: #fff;
102 padding: 10px 5px;
103 font-style: italic;
104 margin: 0 30px;
105 font-size: 12px;
106 border-top: 1px solid rgba(255, 255, 255, 0.5);
107 }
108
109 .pan-info p a {
110 display: block;
111 color: #333;
112 width: 80px;
113 height: 80px;
114 background: rgba(255, 255, 255, 0.3);
115 border-radius: 50%;
116 color: #fff;
117 font-style: normal;
118 font-weight: 700;
119 text-transform: uppercase;
120 font-size: 9px;
121 letter-spacing: 1px;
122 padding-top: 24px;
123 margin: 7px auto 0;
124 font-family: 'Open Sans', Arial, sans-serif;
125 opacity: 0;
126 transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
127 transform: translateX(60px) rotate(90deg);
128 }
129
130 .pan-info p a:hover {
131 background: rgba(255, 255, 255, 0.5);
132 }
133
134 .pan-item:hover .pan-thumb {
135 transform: rotate(-110deg);
136 }
137
138 .pan-item:hover .pan-info p a {
139 opacity: 1;
140 transform: translateX(0px) rotate(0deg);
141 }
142 </style>
143
src/components/RightPanel/index.vue
File was created 1 <template>
2 <div ref="rightPanel" :class="{show:show}" class="rightPanel-container">
3 <div class="rightPanel-background" />
4 <div class="rightPanel">
5 <div class="handle-button" :style="{'top':buttonTop+'px','background-color':theme}" @click="show=!show">
6 <i :class="show?'el-icon-close':'el-icon-setting'" />
7 </div>
8 <div class="rightPanel-items">
9 <slot />
10 </div>
11 </div>
12 </div>
13 </template>
14
15 <script>
16 import { addClass, removeClass } from '@/utils'
17
18 export default {
19 name: 'RightPanel',
20 props: {
21 clickNotClose: {
22 default: false,
23 type: Boolean
24 },
25 buttonTop: {
26 default: 250,
27 type: Number
28 }
29 },
30 data() {
31 return {
32 show: false
33 }
34 },
35 computed: {
36 theme() {
37 return this.$store.state.settings.theme
38 }
39 },
40 watch: {
41 show(value) {
42 if (value && !this.clickNotClose) {
43 this.addEventClick()
44 }
45 if (value) {
46 addClass(document.body, 'showRightPanel')
47 } else {
48 removeClass(document.body, 'showRightPanel')
49 }
50 }
51 },
52 mounted() {
53 this.insertToBody()
54 },
55 beforeDestroy() {
56 const elx = this.$refs.rightPanel
57 elx.remove()
58 },
59 methods: {
60 addEventClick() {
61 window.addEventListener('click', this.closeSidebar)
62 },
63 closeSidebar(evt) {
64 const parent = evt.target.closest('.rightPanel')
65 if (!parent) {
66 this.show = false
67 window.removeEventListener('click', this.closeSidebar)
68 }
69 },
70 insertToBody() {
71 const elx = this.$refs.rightPanel
72 const body = document.querySelector('body')
73 body.insertBefore(elx, body.firstChild)
74 }
75 }
76 }
77 </script>
78
79 <style>
80 .showRightPanel {
81 overflow: hidden;
82 position: relative;
83 width: calc(100% - 15px);
84 }
85 </style>
86
87 <style lang="scss" scoped>
88 .rightPanel-background {
89 position: fixed;
90 top: 0;
91 left: 0;
92 opacity: 0;
93 transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
94 background: rgba(0, 0, 0, .2);
95 z-index: -1;
96 }
97
98 .rightPanel {
99 width: 100%;
100 max-width: 260px;
101 height: 100vh;
102 position: fixed;
103 top: 0;
104 right: 0;
105 box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
106 transition: all .25s cubic-bezier(.7, .3, .1, 1);
107 transform: translate(100%);
108 background: #fff;
109 z-index: 40000;
110 }
111
112 .show {
113 transition: all .3s cubic-bezier(.7, .3, .1, 1);
114
115 .rightPanel-background {
116 z-index: 20000;
117 opacity: 1;
118 width: 100%;
119 height: 100%;
120 }
121
122 .rightPanel {
123 transform: translate(0);
124 }
125 }
126
127 .handle-button {
128 width: 48px;
129 height: 48px;
130 position: absolute;
131 left: -48px;
132 text-align: center;
133 font-size: 24px;
134 border-radius: 6px 0 0 6px !important;
135 z-index: 0;
136 pointer-events: auto;
137 cursor: pointer;
138 color: #fff;
139 line-height: 48px;
140 i {
141 font-size: 24px;
142 line-height: 48px;
143 }
144 }
145 </style>
146
src/components/Screenfull/index.vue
File was created 1 <template>
2 <div>
3 <svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" @click="click" />
4 </div>
5 </template>
6
7 <script>
8 import screenfull from 'screenfull'
9
10 export default {
11 name: 'Screenfull',
12 data() {
13 return {
14 isFullscreen: false
15 }
16 },
17 mounted() {
18 this.init()
19 },
20 beforeDestroy() {
21 this.destroy()
22 },
23 methods: {
24 click() {
25 if (!screenfull.enabled) {
26 this.$message({
27 message: 'you browser can not work',
28 type: 'warning'
29 })
30 return false
31 }
32 screenfull.toggle()
33 },
34 change() {
35 this.isFullscreen = screenfull.isFullscreen
36 },
37 init() {
38 if (screenfull.enabled) {
39 screenfull.on('change', this.change)
40 }
41 },
42 destroy() {
43 if (screenfull.enabled) {
44 screenfull.off('change', this.change)
45 }
46 }
47 }
48 }
49 </script>
50
51 <style scoped>
52 .screenfull-svg {
53 display: inline-block;
54 cursor: pointer;
55 fill: #5a5e66;;
56 width: 20px;
57 height: 20px;
58 vertical-align: 10px;
59 }
60 </style>
61
src/components/Share/DropdownMenu.vue
File was created 1 <template>
2 <div :class="{active:isActive}" class="share-dropdown-menu">
3 <div class="share-dropdown-menu-wrapper">
4 <span class="share-dropdown-menu-title" @click.self="clickTitle">{{ title }}</span>
5 <div v-for="(item,index) of items" :key="index" class="share-dropdown-menu-item">
6 <a v-if="item.href" :href="item.href" target="_blank">{{ item.title }}</a>
7 <span v-else>{{ item.title }}</span>
8 </div>
9 </div>
10 </div>
11 </template>
12
13 <script>
14 export default {
15 props: {
16 items: {
17 type: Array,
18 default: function() {
19 return []
20 }
21 },
22 title: {
23 type: String,
24 default: 'vue'
25 }
26 },
27 data() {
28 return {
29 isActive: false
30 }
31 },
32 methods: {
33 clickTitle() {
34 this.isActive = !this.isActive
35 }
36 }
37 }
38 </script>
39
40 <style lang="scss" >
41 $n: 9; //和items.length 相同
42 $t: .1s;
43 .share-dropdown-menu {
44 width: 250px;
45 position: relative;
46 z-index: 1;
47 height: auto!important;
48 &-title {
49 width: 100%;
50 display: block;
51 cursor: pointer;
52 background: black;
53 color: white;
54 height: 60px;
55 line-height: 60px;
56 font-size: 20px;
57 text-align: center;
58 z-index: 2;
59 transform: translate3d(0,0,0);
60 }
61 &-wrapper {
62 position: relative;
63 }
64 &-item {
65 text-align: center;
66 position: absolute;
67 width: 100%;
68 background: #e0e0e0;
69 color: #000;
70 line-height: 60px;
71 height: 60px;
72 cursor: pointer;
73 font-size: 18px;
74 overflow: hidden;
75 opacity: 1;
76 transition: transform 0.28s ease;
77 &:hover {
78 background: black;
79 color: white;
80 }
81 @for $i from 1 through $n {
82 &:nth-of-type(#{$i}) {
83 z-index: -1;
84 transition-delay: $i*$t;
85 transform: translate3d(0, -60px, 0);
86 }
87 }
88 }
89 &.active {
90 .share-dropdown-menu-wrapper {
91 z-index: 1;
92 }
93 .share-dropdown-menu-item {
94 @for $i from 1 through $n {
95 &:nth-of-type(#{$i}) {
96 transition-delay: ($n - $i)*$t;
97 transform: translate3d(0, ($i - 1)*60px, 0);
98 }
99 }
100 }
101 }
102 }
103 </style>
104
src/components/SizeSelect/index.vue
File was created 1 <template>
2 <el-dropdown trigger="click" @command="handleSetSize">
3 <div>
4 <svg-icon class-name="size-icon" icon-class="size" />
5 </div>
6 <el-dropdown-menu slot="dropdown">
7 <el-dropdown-item v-for="item of sizeOptions" :key="item.value" :disabled="size===item.value" :command="item.value">
8 {{
9 item.label }}
10 </el-dropdown-item>
11 </el-dropdown-menu>
12 </el-dropdown>
13 </template>
14
15 <script>
16 export default {
17 data() {
18 return {
19 sizeOptions: [
20 { label: 'Default', value: 'default' },
21 { label: 'Medium', value: 'medium' },
22 { label: 'Small', value: 'small' },
23 { label: 'Mini', value: 'mini' }
24 ]
25 }
26 },
27 computed: {
28 size() {
29 return this.$store.getters.size
30 }
31 },
32 methods: {
33 handleSetSize(size) {
34 this.$ELEMENT.size = size
35 this.$store.dispatch('app/setSize', size)
36 this.refreshView()
37 this.$message({
38 message: 'Switch Size Success',
39 type: 'success'
40 })
41 },
42 refreshView() {
43 // In order to make the cached page re-rendered
44 this.$store.dispatch('tagsView/delAllCachedViews', this.$route)
45
46 const { fullPath } = this.$route
47
48 this.$nextTick(() => {
49 this.$router.replace({
50 path: '/redirect' + fullPath
51 })
52 })
53 }
54 }
55
56 }
57 </script>
58
src/components/Sticky/index.vue
File was created 1 <template>
2 <div :style="{height:height+'px',zIndex:zIndex}">
3 <div
4 :class="className"
5 :style="{top:(isSticky ? stickyTop +'px' : ''),zIndex:zIndex,position:position,width:width,height:height+'px'}"
6 >
7 <slot>
8 <div>sticky</div>
9 </slot>
10 </div>
11 </div>
12 </template>
13
14 <script>
15 export default {
16 name: 'Sticky',
17 props: {
18 stickyTop: {
19 type: Number,
20 default: 0
21 },
22 zIndex: {
23 type: Number,
24 default: 1
25 },
26 className: {
27 type: String,
28 default: ''
29 }
30 },
31 data() {
32 return {
33 active: false,
34 position: '',
35 width: undefined,
36 height: undefined,
37 isSticky: false
38 }
39 },
40 mounted() {
41 this.height = this.$el.getBoundingClientRect().height
42 window.addEventListener('scroll', this.handleScroll)
43 window.addEventListener('resize', this.handleResize)
44 },
45 activated() {
46 this.handleScroll()
47 },
48 destroyed() {
49 window.removeEventListener('scroll', this.handleScroll)
50 window.removeEventListener('resize', this.handleResize)
51 },
52 methods: {
53 sticky() {
54 if (this.active) {
55 return
56 }
57 this.position = 'fixed'
58 this.active = true
59 this.width = this.width + 'px'
60 this.isSticky = true
61 },
62 handleReset() {
63 if (!this.active) {
64 return
65 }
66 this.reset()
67 },
68 reset() {
69 this.position = ''
70 this.width = 'auto'
71 this.active = false
72 this.isSticky = false
73 },
74 handleScroll() {
75 const width = this.$el.getBoundingClientRect().width
76 this.width = width || 'auto'
77 const offsetTop = this.$el.getBoundingClientRect().top
78 if (offsetTop < this.stickyTop) {
79 this.sticky()
80 return
81 }
82 this.handleReset()
83 },
84 handleResize() {
85 if (this.isSticky) {
86 this.width = this.$el.getBoundingClientRect().width + 'px'
87 }
88 }
89 }
90 }
91 </script>
92
src/components/SvgIcon/index.vue 100644 → 100755
1 <template> 1 <template>
2 <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" /> 2 <div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
3 <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners"> 3 <svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
4 <use :href="iconName" /> 4 <use :href="iconName" />
5 </svg> 5 </svg>
6 </template> 6 </template>
7 7
8 <script> 8 <script>
9 // doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage 9 // doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
10 import { isExternal } from '@/utils/validate' 10 import { isExternal } from '@/utils/validate'
11 11
12 export default { 12 export default {
13 name: 'SvgIcon', 13 name: 'SvgIcon',
14 props: { 14 props: {
15 iconClass: { 15 iconClass: {
16 type: String, 16 type: String,
17 required: true 17 required: true
18 }, 18 },
19 className: { 19 className: {
20 type: String, 20 type: String,
21 default: '' 21 default: ''
22 } 22 }
23 }, 23 },
24 computed: { 24 computed: {
25 isExternal() { 25 isExternal() {
26 return isExternal(this.iconClass) 26 return isExternal(this.iconClass)
27 }, 27 },
28 iconName() { 28 iconName() {
29 return `#icon-${this.iconClass}` 29 return `#icon-${this.iconClass}`
30 }, 30 },
31 svgClass() { 31 svgClass() {
32 if (this.className) { 32 if (this.className) {
33 return 'svg-icon ' + this.className 33 return 'svg-icon ' + this.className
34 } else { 34 } else {
35 return 'svg-icon' 35 return 'svg-icon'
36 } 36 }
37 }, 37 },
38 styleExternalIcon() { 38 styleExternalIcon() {
39 return { 39 return {
40 mask: `url(${this.iconClass}) no-repeat 50% 50%`, 40 mask: `url(${this.iconClass}) no-repeat 50% 50%`,
41 '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%` 41 '-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
42 } 42 }
43 } 43 }
44 } 44 }
45 } 45 }
46 </script> 46 </script>
47 47
48 <style scoped> 48 <style scoped>
49 .svg-icon { 49 .svg-icon {
50 width: 1em; 50 width: 1em;
51 height: 1em; 51 height: 1em;
52 vertical-align: -0.15em; 52 vertical-align: -0.15em;
53 fill: currentColor; 53 fill: currentColor;
54 overflow: hidden; 54 overflow: hidden;
55 } 55 }
56 56
57 .svg-external-icon { 57 .svg-external-icon {
58 background-color: currentColor; 58 background-color: currentColor;
59 mask-size: cover!important; 59 mask-size: cover!important;
60 display: inline-block; 60 display: inline-block;
61 } 61 }
62 </style> 62 </style>
63 63
src/components/TextHoverEffect/Mallki.vue
File was created 1 <template>
2 <a :class="className" class="link--mallki" href="#">
3 {{ text }}
4 <span :data-letters="text" />
5 <span :data-letters="text" />
6 </a>
7 </template>
8
9 <script>
10 export default {
11 props: {
12 className: {
13 type: String,
14 default: ''
15 },
16 text: {
17 type: String,
18 default: 'vue-element-admin'
19 }
20 }
21 }
22 </script>
23
24 <style>
25 /* Mallki */
26
27 .link--mallki {
28 font-weight: 800;
29 color: #4dd9d5;
30 font-family: 'Dosis', sans-serif;
31 -webkit-transition: color 0.5s 0.25s;
32 transition: color 0.5s 0.25s;
33 overflow: hidden;
34 position: relative;
35 display: inline-block;
36 line-height: 1;
37 outline: none;
38 text-decoration: none;
39 }
40
41 .link--mallki:hover {
42 -webkit-transition: none;
43 transition: none;
44 color: transparent;
45 }
46
47 .link--mallki::before {
48 content: '';
49 width: 100%;
50 height: 6px;
51 margin: -3px 0 0 0;
52 background: #3888fa;
53 position: absolute;
54 left: 0;
55 top: 50%;
56 -webkit-transform: translate3d(-100%, 0, 0);
57 transform: translate3d(-100%, 0, 0);
58 -webkit-transition: -webkit-transform 0.4s;
59 transition: transform 0.4s;
60 -webkit-transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
61 transition-timing-function: cubic-bezier(0.7, 0, 0.3, 1);
62 }
63
64 .link--mallki:hover::before {
65 -webkit-transform: translate3d(100%, 0, 0);
66 transform: translate3d(100%, 0, 0);
67 }
68
69 .link--mallki span {
70 position: absolute;
71 height: 50%;
72 width: 100%;
73 left: 0;
74 top: 0;
75 overflow: hidden;
76 }
77
78 .link--mallki span::before {
79 content: attr(data-letters);
80 color: red;
81 position: absolute;
82 left: 0;
83 width: 100%;
84 color: #3888fa;
85 -webkit-transition: -webkit-transform 0.5s;
86 transition: transform 0.5s;
87 }
88
89 .link--mallki span:nth-child(2) {
90 top: 50%;
91 }
92
93 .link--mallki span:first-child::before {
94 top: 0;
95 -webkit-transform: translate3d(0, 100%, 0);
96 transform: translate3d(0, 100%, 0);
97 }
98
99 .link--mallki span:nth-child(2)::before {
100 bottom: 0;
101 -webkit-transform: translate3d(0, -100%, 0);
102 transform: translate3d(0, -100%, 0);
103 }
104
105 .link--mallki:hover span::before {
106 -webkit-transition-delay: 0.3s;
107 transition-delay: 0.3s;
108 -webkit-transform: translate3d(0, 0, 0);
109 transform: translate3d(0, 0, 0);
110 -webkit-transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
111 transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
112 }
113 </style>
114
src/components/ThemePicker/index.vue
File was created 1 <template>
2 <el-color-picker
3 v-model="theme"
4 :predefine="['#409EFF', '#1890ff', '#304156','#212121','#11a983', '#13c2c2', '#6959CD', '#f5222d', ]"
5 class="theme-picker"
6 popper-class="theme-picker-dropdown"
7 />
8 </template>
9
10 <script>
11 const version = require('element-ui/package.json').version // element-ui version from node_modules
12 const ORIGINAL_THEME = '#409EFF' // default color
13
14 export default {
15 data() {
16 return {
17 chalk: '', // content of theme-chalk css
18 theme: ''
19 }
20 },
21 computed: {
22 defaultTheme() {
23 return this.$store.state.settings.theme
24 }
25 },
26 watch: {
27 defaultTheme: {
28 handler: function(val, oldVal) {
29 this.theme = val
30 },
31 immediate: true
32 },
33 async theme(val) {
34 const oldVal = this.chalk ? this.theme : ORIGINAL_THEME
35 if (typeof val !== 'string') return
36 const themeCluster = this.getThemeCluster(val.replace('#', ''))
37 const originalCluster = this.getThemeCluster(oldVal.replace('#', ''))
38 console.log(themeCluster, originalCluster)
39
40 const $message = this.$message({
41 message: ' Compiling the theme',
42 customClass: 'theme-message',
43 type: 'success',
44 duration: 0,
45 iconClass: 'el-icon-loading'
46 })
47
48 const getHandler = (variable, id) => {
49 return () => {
50 const originalCluster = this.getThemeCluster(ORIGINAL_THEME.replace('#', ''))
51 const newStyle = this.updateStyle(this[variable], originalCluster, themeCluster)
52
53 let styleTag = document.getElementById(id)
54 if (!styleTag) {
55 styleTag = document.createElement('style')
56 styleTag.setAttribute('id', id)
57 document.head.appendChild(styleTag)
58 }
59 styleTag.innerText = newStyle
60 }
61 }
62
63 if (!this.chalk) {
64 const url = `https://unpkg.com/element-ui@${version}/lib/theme-chalk/index.css`
65 await this.getCSSString(url, 'chalk')
66 }
67
68 const chalkHandler = getHandler('chalk', 'chalk-style')
69
70 chalkHandler()
71
72 const styles = [].slice.call(document.querySelectorAll('style'))
73 .filter(style => {
74 const text = style.innerText
75 return new RegExp(oldVal, 'i').test(text) && !/Chalk Variables/.test(text)
76 })
77 styles.forEach(style => {
78 const { innerText } = style
79 if (typeof innerText !== 'string') return
80 style.innerText = this.updateStyle(innerText, originalCluster, themeCluster)
81 })
82
83 this.$emit('change', val)
84
85 $message.close()
86 }
87 },
88
89 methods: {
90 updateStyle(style, oldCluster, newCluster) {
91 let newStyle = style
92 oldCluster.forEach((color, index) => {
93 newStyle = newStyle.replace(new RegExp(color, 'ig'), newCluster[index])
94 })
95 return newStyle
96 },
97
98 getCSSString(url, variable) {
99 return new Promise(resolve => {
100 const xhr = new XMLHttpRequest()
101 xhr.onreadystatechange = () => {
102 if (xhr.readyState === 4 && xhr.status === 200) {
103 this[variable] = xhr.responseText.replace(/@font-face{[^}]+}/, '')
104 resolve()
105 }
106 }
107 xhr.open('GET', url)
108 xhr.send()
109 })
110 },
111
112 getThemeCluster(theme) {
113 const tintColor = (color, tint) => {
114 let red = parseInt(color.slice(0, 2), 16)
115 let green = parseInt(color.slice(2, 4), 16)
116 let blue = parseInt(color.slice(4, 6), 16)
117
118 if (tint === 0) { // when primary color is in its rgb space
119 return [red, green, blue].join(',')
120 } else {
121 red += Math.round(tint * (255 - red))
122 green += Math.round(tint * (255 - green))
123 blue += Math.round(tint * (255 - blue))
124
125 red = red.toString(16)
126 green = green.toString(16)
127 blue = blue.toString(16)
128
129 return `#${red}${green}${blue}`
130 }
131 }
132
133 const shadeColor = (color, shade) => {
134 let red = parseInt(color.slice(0, 2), 16)
135 let green = parseInt(color.slice(2, 4), 16)
136 let blue = parseInt(color.slice(4, 6), 16)
137
138 red = Math.round((1 - shade) * red)
139 green = Math.round((1 - shade) * green)
140 blue = Math.round((1 - shade) * blue)
141
142 red = red.toString(16)
143 green = green.toString(16)
144 blue = blue.toString(16)
145
146 return `#${red}${green}${blue}`
147 }
148
149 const clusters = [theme]
150 for (let i = 0; i <= 9; i++) {
151 clusters.push(tintColor(theme, Number((i / 10).toFixed(2))))
152 }
153 clusters.push(shadeColor(theme, 0.1))
154 return clusters
155 }
156 }
157 }
158 </script>
159
160 <style>
161 .theme-message,
162 .theme-picker-dropdown {
163 z-index: 99999 !important;
164 }
165
166 .theme-picker .el-color-picker__trigger {
167 height: 26px !important;
168 width: 26px !important;
169 padding: 2px;
170 }
171
172 .theme-picker-dropdown .el-color-dropdown__link-btn {
173 display: none;
174 }
175 </style>
176
src/components/Tinymce/components/EditorImage.vue
File was created 1 <template>
2 <div class="upload-container">
3 <el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">
4 upload
5 </el-button>
6 <el-dialog :visible.sync="dialogVisible">
7 <el-upload
8 :multiple="true"
9 :file-list="fileList"
10 :show-file-list="true"
11 :on-remove="handleRemove"
12 :on-success="handleSuccess"
13 :before-upload="beforeUpload"
14 class="editor-slide-upload"
15 action="https://httpbin.org/post"
16 list-type="picture-card"
17 >
18 <el-button size="small" type="primary">
19 Click upload
20 </el-button>
21 </el-upload>
22 <el-button @click="dialogVisible = false">
23 Cancel
24 </el-button>
25 <el-button type="primary" @click="handleSubmit">
26 Confirm
27 </el-button>
28 </el-dialog>
29 </div>
30 </template>
31
32 <script>
33 // import { getToken } from 'api/qiniu'
34
35 export default {
36 name: 'EditorSlideUpload',
37 props: {
38 color: {
39 type: String,
40 default: '#1890ff'
41 }
42 },
43 data() {
44 return {
45 dialogVisible: false,
46 listObj: {},
47 fileList: []
48 }
49 },
50 methods: {
51 checkAllSuccess() {
52 return Object.keys(this.listObj).every(item => this.listObj[item].hasSuccess)
53 },
54 handleSubmit() {
55 const arr = Object.keys(this.listObj).map(v => this.listObj[v])
56 if (!this.checkAllSuccess()) {
57 this.$message('Please wait for all images to be uploaded successfully. If there is a network problem, please refresh the page and upload again!')
58 return
59 }
60 this.$emit('successCBK', arr)
61 this.listObj = {}
62 this.fileList = []
63 this.dialogVisible = false
64 },
65 handleSuccess(response, file) {
66 const uid = file.uid
67 const objKeyArr = Object.keys(this.listObj)
68 for (let i = 0, len = objKeyArr.length; i < len; i++) {
69 if (this.listObj[objKeyArr[i]].uid === uid) {
70 this.listObj[objKeyArr[i]].url = response.files.file
71 this.listObj[objKeyArr[i]].hasSuccess = true
72 return
73 }
74 }
75 },
76 handleRemove(file) {
77 const uid = file.uid
78 const objKeyArr = Object.keys(this.listObj)
79 for (let i = 0, len = objKeyArr.length; i < len; i++) {
80 if (this.listObj[objKeyArr[i]].uid === uid) {
81 delete this.listObj[objKeyArr[i]]
82 return
83 }
84 }
85 },
86 beforeUpload(file) {
87 const _self = this
88 const _URL = window.URL || window.webkitURL
89 const fileName = file.uid
90 this.listObj[fileName] = {}
91 return new Promise((resolve, reject) => {
92 const img = new Image()
93 img.src = _URL.createObjectURL(file)
94 img.onload = function() {
95 _self.listObj[fileName] = { hasSuccess: false, uid: file.uid, width: this.width, height: this.height }
96 }
97 resolve(true)
98 })
99 }
100 }
101 }
102 </script>
103
104 <style lang="scss" scoped>
105 .editor-slide-upload {
106 margin-bottom: 20px;
107 /deep/ .el-upload--picture-card {
108 width: 100%;
109 }
110 }
111 </style>
112
src/components/Tinymce/dynamicLoadScript.js
File was created 1 let callbacks = []
2
3 function loadedTinymce() {
4 // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
5 // check is successfully downloaded script
6 return window.tinymce
7 }
8
9 const dynamicLoadScript = (src, callback) => {
10 const existingScript = document.getElementById(src)
11 const cb = callback || function() {}
12
13 if (!existingScript) {
14 const script = document.createElement('script')
15 script.src = src // src url for the third-party library being loaded.
16 script.id = src
17 document.body.appendChild(script)
18 callbacks.push(cb)
19 const onEnd = 'onload' in script ? stdOnEnd : ieOnEnd
20 onEnd(script)
21 }
22
23 if (existingScript && cb) {
24 if (loadedTinymce()) {
25 cb(null, existingScript)
26 } else {
27 callbacks.push(cb)
28 }
29 }
30
31 function stdOnEnd(script) {
32 script.onload = function() {
33 // this.onload = null here is necessary
34 // because even IE9 works not like others
35 this.onerror = this.onload = null
36 for (const cb of callbacks) {
37 cb(null, script)
38 }
39 callbacks = null
40 }
41 script.onerror = function() {
42 this.onerror = this.onload = null
43 cb(new Error('Failed to load ' + src), script)
44 }
45 }
46
47 function ieOnEnd(script) {
48 script.onreadystatechange = function() {
49 if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
50 this.onreadystatechange = null
51 for (const cb of callbacks) {
52 cb(null, script) // there is no way to catch loading errors in IE8
53 }
54 callbacks = null
55 }
56 }
57 }
58
59 export default dynamicLoadScript
60
src/components/Tinymce/index.vue
File was created 1 <template>
2 <div :class="{fullscreen:fullscreen}" class="tinymce-container" :style="{width:containerWidth}">
3 <textarea :id="tinymceId" class="tinymce-textarea" />
4 <div class="editor-custom-btn-container">
5 <editorImage color="#1890ff" class="editor-upload-btn" @successCBK="imageSuccessCBK" />
6 </div>
7 </div>
8 </template>
9
10 <script>
11 /**
12 * docs:
13 * https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html#tinymce
14 */
15 import editorImage from './components/EditorImage'
16 import plugins from './plugins'
17 import toolbar from './toolbar'
18 import load from './dynamicLoadScript'
19
20 // why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
21 const tinymceCDN = 'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js'
22
23 export default {
24 name: 'Tinymce',
25 components: { editorImage },
26 props: {
27 id: {
28 type: String,
29 default: function() {
30 return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
31 }
32 },
33 value: {
34 type: String,
35 default: ''
36 },
37 toolbar: {
38 type: Array,
39 required: false,
40 default() {
41 return []
42 }
43 },
44 menubar: {
45 type: String,
46 default: 'file edit insert view format table'
47 },
48 height: {
49 type: [Number, String],
50 required: false,
51 default: 360
52 },
53 width: {
54 type: [Number, String],
55 required: false,
56 default: 'auto'
57 }
58 },
59 data() {
60 return {
61 hasChange: false,
62 hasInit: false,
63 tinymceId: this.id,
64 fullscreen: false,
65 languageTypeList: {
66 'en': 'en',
67 'zh': 'zh_CN',
68 'es': 'es_MX',
69 'ja': 'ja'
70 }
71 }
72 },
73 computed: {
74 language() {
75 return this.languageTypeList[this.$store.getters.language]
76 },
77 containerWidth() {
78 const width = this.width
79 if (/^[\d]+(\.[\d]+)?$/.test(width)) { // matches `100`, `'100'`
80 return `${width}px`
81 }
82 return width
83 }
84 },
85 watch: {
86 value(val) {
87 if (!this.hasChange && this.hasInit) {
88 this.$nextTick(() =>
89 window.tinymce.get(this.tinymceId).setContent(val || ''))
90 }
91 },
92 language() {
93 this.destroyTinymce()
94 this.$nextTick(() => this.initTinymce())
95 }
96 },
97 mounted() {
98 this.init()
99 },
100 activated() {
101 if (window.tinymce) {
102 this.initTinymce()
103 }
104 },
105 deactivated() {
106 this.destroyTinymce()
107 },
108 destroyed() {
109 this.destroyTinymce()
110 },
111 methods: {
112 init() {
113 // dynamic load tinymce from cdn
114 load(tinymceCDN, (err) => {
115 if (err) {
116 this.$message.error(err.message)
117 return
118 }
119 this.initTinymce()
120 })
121 },
122 initTinymce() {
123 const _this = this
124 window.tinymce.init({
125 language: this.language,
126 selector: `#${this.tinymceId}`,
127 height: this.height,
128 body_class: 'panel-body ',
129 object_resizing: false,
130 toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
131 menubar: this.menubar,
132 plugins: plugins,
133 end_container_on_empty_block: true,
134 powerpaste_word_import: 'clean',
135 code_dialog_height: 450,
136 code_dialog_width: 1000,
137 advlist_bullet_styles: 'square',
138 advlist_number_styles: 'default',
139 imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
140 default_link_target: '_blank',
141 link_title: false,
142 nonbreaking_force_tab: true, // inserting nonbreaking space &nbsp; need Nonbreaking Space Plugin
143 init_instance_callback: editor => {
144 if (_this.value) {
145 editor.setContent(_this.value)
146 }
147 _this.hasInit = true
148 editor.on('NodeChange Change KeyUp SetContent', () => {
149 this.hasChange = true
150 this.$emit('input', editor.getContent())
151 })
152 },
153 setup(editor) {
154 editor.on('FullscreenStateChanged', (e) => {
155 _this.fullscreen = e.state
156 })
157 }
158 // 整合七牛上传
159 // images_dataimg_filter(img) {
160 // setTimeout(() => {
161 // const $image = $(img);
162 // $image.removeAttr('width');
163 // $image.removeAttr('height');
164 // if ($image[0].height && $image[0].width) {
165 // $image.attr('data-wscntype', 'image');
166 // $image.attr('data-wscnh', $image[0].height);
167 // $image.attr('data-wscnw', $image[0].width);
168 // $image.addClass('wscnph');
169 // }
170 // }, 0);
171 // return img
172 // },
173 // images_upload_handler(blobInfo, success, failure, progress) {
174 // progress(0);
175 // const token = _this.$store.getters.token;
176 // getToken(token).then(response => {
177 // const url = response.data.qiniu_url;
178 // const formData = new FormData();
179 // formData.append('token', response.data.qiniu_token);
180 // formData.append('key', response.data.qiniu_key);
181 // formData.append('file', blobInfo.blob(), url);
182 // upload(formData).then(() => {
183 // success(url);
184 // progress(100);
185 // })
186 // }).catch(err => {
187 // failure('出现未知问题,刷新页面,或者联系程序员')
188 // console.log(err);
189 // });
190 // },
191 })
192 },
193 destroyTinymce() {
194 const tinymce = window.tinymce.get(this.tinymceId)
195 if (this.fullscreen) {
196 tinymce.execCommand('mceFullScreen')
197 }
198
199 if (tinymce) {
200 tinymce.destroy()
201 }
202 },
203 setContent(value) {
204 window.tinymce.get(this.tinymceId).setContent(value)
205 },
206 getContent() {
207 window.tinymce.get(this.tinymceId).getContent()
208 },
209 imageSuccessCBK(arr) {
210 const _this = this
211 arr.forEach(v => {
212 window.tinymce.get(_this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`)
213 })
214 }
215 }
216 }
217 </script>
218
219 <style scoped>
220 .tinymce-container {
221 position: relative;
222 line-height: normal;
223 }
224 .tinymce-container>>>.mce-fullscreen {
225 z-index: 10000;
226 }
227 .tinymce-textarea {
228 visibility: hidden;
229 z-index: -1;
230 }
231 .editor-custom-btn-container {
232 position: absolute;
233 right: 4px;
234 top: 4px;
235 /*z-index: 2005;*/
236 }
237 .fullscreen .editor-custom-btn-container {
238 z-index: 10000;
239 position: fixed;
240 }
241 .editor-upload-btn {
242 display: inline-block;
243 }
244 </style>
245
src/components/Tinymce/plugins.js
File was created 1 // Any plugins you want to use has to be imported
2 // Detail plugins list see https://www.tinymce.com/docs/plugins/
3 // Custom builds see https://www.tinymce.com/download/custom-builds/
4
5 const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
6
7 export default plugins
8
src/components/Tinymce/toolbar.js
File was created 1 // Here is a list of the toolbar
2 // Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
3
4 const toolbar = ['searchreplace bold italic underline strikethrough alignleft aligncenter alignright outdent indent blockquote undo redo removeformat subscript superscript code codesample', 'hr bullist numlist link image charmap preview anchor pagebreak insertdatetime media table emoticons forecolor backcolor fullscreen']
5
6 export default toolbar
7
src/components/Upload/SingleImage.vue
File was created 1 <template>
2 <div class="upload-container">
3 <el-upload
4 :data="dataObj"
5 :multiple="false"
6 :show-file-list="false"
7 :on-success="handleImageSuccess"
8 class="image-uploader"
9 drag
10 action="https://httpbin.org/post"
11 >
12 <i class="el-icon-upload" />
13 <div class="el-upload__text">
14 将文件拖到此处,或<em>点击上传</em>
15 </div>
16 </el-upload>
17 <div class="image-preview">
18 <div v-show="imageUrl.length>1" class="image-preview-wrapper">
19 <img :src="imageUrl+'?imageView2/1/w/200/h/200'">
20 <div class="image-preview-action">
21 <i class="el-icon-delete" @click="rmImage" />
22 </div>
23 </div>
24 </div>
25 </div>
26 </template>
27
28 <script>
29 import { getToken } from '@/api/qiniu'
30
31 export default {
32 name: 'SingleImageUpload',
33 props: {
34 value: {
35 type: String,
36 default: ''
37 }
38 },
39 data() {
40 return {
41 tempUrl: '',
42 dataObj: { token: '', key: '' }
43 }
44 },
45 computed: {
46 imageUrl() {
47 return this.value
48 }
49 },
50 methods: {
51 rmImage() {
52 this.emitInput('')
53 },
54 emitInput(val) {
55 this.$emit('input', val)
56 },
57 handleImageSuccess() {
58 this.emitInput(this.tempUrl)
59 },
60 beforeUpload() {
61 const _self = this
62 return new Promise((resolve, reject) => {
63 getToken().then(response => {
64 const key = response.data.qiniu_key
65 const token = response.data.qiniu_token
66 _self._data.dataObj.token = token
67 _self._data.dataObj.key = key
68 this.tempUrl = response.data.qiniu_url
69 resolve(true)
70 }).catch(err => {
71 console.log(err)
72 reject(false)
73 })
74 })
75 }
76 }
77 }
78 </script>
79
80 <style lang="scss" scoped>
81 @import "~@/styles/mixin.scss";
82 .upload-container {
83 width: 100%;
84 position: relative;
85 @include clearfix;
86 .image-uploader {
87 width: 60%;
88 float: left;
89 }
90 .image-preview {
91 width: 200px;
92 height: 200px;
93 position: relative;
94 border: 1px dashed #d9d9d9;
95 float: left;
96 margin-left: 50px;
97 .image-preview-wrapper {
98 position: relative;
99 width: 100%;
100 height: 100%;
101 img {
102 width: 100%;
103 height: 100%;
104 }
105 }
106 .image-preview-action {
107 position: absolute;
108 width: 100%;
109 height: 100%;
110 left: 0;
111 top: 0;
112 cursor: default;
113 text-align: center;
114 color: #fff;
115 opacity: 0;
116 font-size: 20px;
117 background-color: rgba(0, 0, 0, .5);
118 transition: opacity .3s;
119 cursor: pointer;
120 text-align: center;
121 line-height: 200px;
122 .el-icon-delete {
123 font-size: 36px;
124 }
125 }
126 &:hover {
127 .image-preview-action {
128 opacity: 1;
129 }
130 }
131 }
132 }
133
134 </style>
135
src/components/Upload/SingleImage2.vue
File was created 1 <template>
2 <div class="singleImageUpload2 upload-container">
3 <el-upload
4 :data="dataObj"
5 :multiple="false"
6 :show-file-list="false"
7 :on-success="handleImageSuccess"
8 class="image-uploader"
9 drag
10 action="https://httpbin.org/post"
11 >
12 <i class="el-icon-upload" />
13 <div class="el-upload__text">
14 Drag或<em>点击上传</em>
15 </div>
16 </el-upload>
17 <div v-show="imageUrl.length>0" class="image-preview">
18 <div v-show="imageUrl.length>1" class="image-preview-wrapper">
19 <img :src="imageUrl">
20 <div class="image-preview-action">
21 <i class="el-icon-delete" @click="rmImage" />
22 </div>
23 </div>
24 </div>
25 </div>
26 </template>
27
28 <script>
29 import { getToken } from '@/api/qiniu'
30
31 export default {
32 name: 'SingleImageUpload2',
33 props: {
34 value: {
35 type: String,
36 default: ''
37 }
38 },
39 data() {
40 return {
41 tempUrl: '',
42 dataObj: { token: '', key: '' }
43 }
44 },
45 computed: {
46 imageUrl() {
47 return this.value
48 }
49 },
50 methods: {
51 rmImage() {
52 this.emitInput('')
53 },
54 emitInput(val) {
55 this.$emit('input', val)
56 },
57 handleImageSuccess() {
58 this.emitInput(this.tempUrl)
59 },
60 beforeUpload() {
61 const _self = this
62 return new Promise((resolve, reject) => {
63 getToken().then(response => {
64 const key = response.data.qiniu_key
65 const token = response.data.qiniu_token
66 _self._data.dataObj.token = token
67 _self._data.dataObj.key = key
68 this.tempUrl = response.data.qiniu_url
69 resolve(true)
70 }).catch(() => {
71 reject(false)
72 })
73 })
74 }
75 }
76 }
77 </script>
78
79 <style lang="scss" scoped>
80 .upload-container {
81 width: 100%;
82 height: 100%;
83 position: relative;
84 .image-uploader {
85 height: 100%;
86 }
87 .image-preview {
88 width: 100%;
89 height: 100%;
90 position: absolute;
91 left: 0px;
92 top: 0px;
93 border: 1px dashed #d9d9d9;
94 .image-preview-wrapper {
95 position: relative;
96 width: 100%;
97 height: 100%;
98 img {
99 width: 100%;
100 height: 100%;
101 }
102 }
103 .image-preview-action {
104 position: absolute;
105 width: 100%;
106 height: 100%;
107 left: 0;
108 top: 0;
109 cursor: default;
110 text-align: center;
111 color: #fff;
112 opacity: 0;
113 font-size: 20px;
114 background-color: rgba(0, 0, 0, .5);
115 transition: opacity .3s;
116 cursor: pointer;
117 text-align: center;
118 line-height: 200px;
119 .el-icon-delete {
120 font-size: 36px;
121 }
122 }
123 &:hover {
124 .image-preview-action {
125 opacity: 1;
126 }
127 }
128 }
129 }
130 </style>
131
src/components/Upload/SingleImage3.vue
File was created 1 <template>
2 <div class="upload-container">
3 <el-upload
4 :data="dataObj"
5 :multiple="false"
6 :show-file-list="false"
7 :on-success="handleImageSuccess"
8 class="image-uploader"
9 drag
10 action="https://httpbin.org/post"
11 >
12 <i class="el-icon-upload" />
13 <div class="el-upload__text">
14 将文件拖到此处,或<em>点击上传</em>
15 </div>
16 </el-upload>
17 <div class="image-preview image-app-preview">
18 <div v-show="imageUrl.length>1" class="image-preview-wrapper">
19 <img :src="imageUrl">
20 <div class="image-preview-action">
21 <i class="el-icon-delete" @click="rmImage" />
22 </div>
23 </div>
24 </div>
25 <div class="image-preview">
26 <div v-show="imageUrl.length>1" class="image-preview-wrapper">
27 <img :src="imageUrl">
28 <div class="image-preview-action">
29 <i class="el-icon-delete" @click="rmImage" />
30 </div>
31 </div>
32 </div>
33 </div>
34 </template>
35
36 <script>
37 import { getToken } from '@/api/qiniu'
38
39 export default {
40 name: 'SingleImageUpload3',
41 props: {
42 value: {
43 type: String,
44 default: ''
45 }
46 },
47 data() {
48 return {
49 tempUrl: '',
50 dataObj: { token: '', key: '' }
51 }
52 },
53 computed: {
54 imageUrl() {
55 return this.value
56 }
57 },
58 methods: {
59 rmImage() {
60 this.emitInput('')
61 },
62 emitInput(val) {
63 this.$emit('input', val)
64 },
65 handleImageSuccess(file) {
66 this.emitInput(file.files.file)
67 },
68 beforeUpload() {
69 const _self = this
70 return new Promise((resolve, reject) => {
71 getToken().then(response => {
72 const key = response.data.qiniu_key
73 const token = response.data.qiniu_token
74 _self._data.dataObj.token = token
75 _self._data.dataObj.key = key
76 this.tempUrl = response.data.qiniu_url
77 resolve(true)
78 }).catch(err => {
79 console.log(err)
80 reject(false)
81 })
82 })
83 }
84 }
85 }
86 </script>
87
88 <style lang="scss" scoped>
89 @import "~@/styles/mixin.scss";
90 .upload-container {
91 width: 100%;
92 position: relative;
93 @include clearfix;
94 .image-uploader {
95 width: 35%;
96 float: left;
97 }
98 .image-preview {
99 width: 200px;
100 height: 200px;
101 position: relative;
102 border: 1px dashed #d9d9d9;
103 float: left;
104 margin-left: 50px;
105 .image-preview-wrapper {
106 position: relative;
107 width: 100%;
108 height: 100%;
109 img {
110 width: 100%;
111 height: 100%;
112 }
113 }
114 .image-preview-action {
115 position: absolute;
116 width: 100%;
117 height: 100%;
118 left: 0;
119 top: 0;
120 cursor: default;
121 text-align: center;
122 color: #fff;
123 opacity: 0;
124 font-size: 20px;
125 background-color: rgba(0, 0, 0, .5);
126 transition: opacity .3s;
127 cursor: pointer;
128 text-align: center;
129 line-height: 200px;
130 .el-icon-delete {
131 font-size: 36px;
132 }
133 }
134 &:hover {
135 .image-preview-action {
136 opacity: 1;
137 }
138 }
139 }
140 .image-app-preview {
141 width: 320px;
142 height: 180px;
143 position: relative;
144 border: 1px dashed #d9d9d9;
145 float: left;
146 margin-left: 50px;
147 .app-fake-conver {
148 height: 44px;
149 position: absolute;
150 width: 100%; // background: rgba(0, 0, 0, .1);
151 text-align: center;
152 line-height: 64px;
153 color: #fff;
154 }
155 }
156 }
157 </style>
158
src/components/UploadExcel/index.vue
File was created 1 <template>
2 <div>
3 <input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick">
4 <div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover">
5 Drop excel file here or
6 <el-button :loading="loading" style="margin-left:16px;" size="mini" type="primary" @click="handleUpload">
7 Browse
8 </el-button>
9 </div>
10 </div>
11 </template>
12
13 <script>
14 import XLSX from 'xlsx'
15
16 export default {
17 props: {
18 beforeUpload: Function, // eslint-disable-line
19 onSuccess: Function// eslint-disable-line
20 },
21 data() {
22 return {
23 loading: false,
24 excelData: {
25 header: null,
26 results: null
27 }
28 }
29 },
30 methods: {
31 generateData({ header, results }) {
32 this.excelData.header = header
33 this.excelData.results = results
34 this.onSuccess && this.onSuccess(this.excelData)
35 },
36 handleDrop(e) {
37 e.stopPropagation()
38 e.preventDefault()
39 if (this.loading) return
40 const files = e.dataTransfer.files
41 if (files.length !== 1) {
42 this.$message.error('Only support uploading one file!')
43 return
44 }
45 const rawFile = files[0] // only use files[0]
46
47 if (!this.isExcel(rawFile)) {
48 this.$message.error('Only supports upload .xlsx, .xls, .csv suffix files')
49 return false
50 }
51 this.upload(rawFile)
52 e.stopPropagation()
53 e.preventDefault()
54 },
55 handleDragover(e) {
56 e.stopPropagation()
57 e.preventDefault()
58 e.dataTransfer.dropEffect = 'copy'
59 },
60 handleUpload() {
61 this.$refs['excel-upload-input'].click()
62 },
63 handleClick(e) {
64 const files = e.target.files
65 const rawFile = files[0] // only use files[0]
66 if (!rawFile) return
67 this.upload(rawFile)
68 },
69 upload(rawFile) {
70 this.$refs['excel-upload-input'].value = null // fix can't select the same excel
71
72 if (!this.beforeUpload) {
73 this.readerData(rawFile)
74 return
75 }
76 const before = this.beforeUpload(rawFile)
77 if (before) {
78 this.readerData(rawFile)
79 }
80 },
81 readerData(rawFile) {
82 this.loading = true
83 return new Promise((resolve, reject) => {
84 const reader = new FileReader()
85 reader.onload = e => {
86 const data = e.target.result
87 const workbook = XLSX.read(data, { type: 'array' })
88 const firstSheetName = workbook.SheetNames[0]
89 const worksheet = workbook.Sheets[firstSheetName]
90 const header = this.getHeaderRow(worksheet)
91 const results = XLSX.utils.sheet_to_json(worksheet)
92 this.generateData({ header, results })
93 this.loading = false
94 resolve()
95 }
96 reader.readAsArrayBuffer(rawFile)
97 })
98 },
99 getHeaderRow(sheet) {
100 const headers = []
101 const range = XLSX.utils.decode_range(sheet['!ref'])
102 let C
103 const R = range.s.r
104 /* start in the first row */
105 for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
106 const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
107 /* find the cell in the first row */
108 let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
109 if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
110 headers.push(hdr)
111 }
112 return headers
113 },
114 isExcel(file) {
115 return /\.(xlsx|xls|csv)$/.test(file.name)
116 }
117 }
118 }
119 </script>
120
121 <style scoped>
122 .excel-upload-input{
123 display: none;
124 z-index: -9999;
125 }
126 .drop{
127 border: 2px dashed #bbb;
128 width: 600px;
129 height: 160px;
130 line-height: 160px;
131 margin: 0 auto;
132 font-size: 24px;
133 border-radius: 5px;
134 text-align: center;
135 color: #bbb;
136 position: relative;
137 }
138 </style>
139
src/directive/clipboard/clipboard.js
File was created 1 // Inspired by https://github.com/Inndy/vue-clipboard2
2 const Clipboard = require('clipboard')
3 if (!Clipboard) {
4 throw new Error('you should npm install `clipboard` --save at first ')
5 }
6
7 export default {
8 bind(el, binding) {
9 if (binding.arg === 'success') {
10 el._v_clipboard_success = binding.value
11 } else if (binding.arg === 'error') {
12 el._v_clipboard_error = binding.value
13 } else {
14 const clipboard = new Clipboard(el, {
15 text() { return binding.value },
16 action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
17 })
18 clipboard.on('success', e => {
19 const callback = el._v_clipboard_success
20 callback && callback(e) // eslint-disable-line
21 })
22 clipboard.on('error', e => {
23 const callback = el._v_clipboard_error
24 callback && callback(e) // eslint-disable-line
25 })
26 el._v_clipboard = clipboard
27 }
28 },
29 update(el, binding) {
30 if (binding.arg === 'success') {
31 el._v_clipboard_success = binding.value
32 } else if (binding.arg === 'error') {
33 el._v_clipboard_error = binding.value
34 } else {
35 el._v_clipboard.text = function() { return binding.value }
36 el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' }
37 }
38 },
39 unbind(el, binding) {
40 if (binding.arg === 'success') {
41 delete el._v_clipboard_success
42 } else if (binding.arg === 'error') {
43 delete el._v_clipboard_error
44 } else {
45 el._v_clipboard.destroy()
46 delete el._v_clipboard
47 }
48 }
49 }
50
src/directive/clipboard/index.js
File was created 1 import Clipboard from './clipboard'
2
3 const install = function(Vue) {
4 Vue.directive('Clipboard', Clipboard)
5 }
6
7 if (window.Vue) {
8 window.clipboard = Clipboard
9 Vue.use(install); // eslint-disable-line
10 }
11
12 Clipboard.install = install
13 export default Clipboard
14
src/directive/el-drag-dialog/drag.js
File was created 1 export default {
2 bind(el, binding, vnode) {
3 const dialogHeaderEl = el.querySelector('.el-dialog__header')
4 const dragDom = el.querySelector('.el-dialog')
5 dialogHeaderEl.style.cssText += ';cursor:move;'
6 dragDom.style.cssText += ';top:0px;'
7
8 // 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
9 const getStyle = (function() {
10 if (window.document.currentStyle) {
11 return (dom, attr) => dom.currentStyle[attr]
12 } else {
13 return (dom, attr) => getComputedStyle(dom, false)[attr]
14 }
15 })()
16
17 dialogHeaderEl.onmousedown = (e) => {
18 // 鼠标按下,计算当前元素距离可视区的距离
19 const disX = e.clientX - dialogHeaderEl.offsetLeft
20 const disY = e.clientY - dialogHeaderEl.offsetTop
21
22 const dragDomWidth = dragDom.offsetWidth
23 const dragDomHeight = dragDom.offsetHeight
24
25 const screenWidth = document.body.clientWidth
26 const screenHeight = document.body.clientHeight
27
28 const minDragDomLeft = dragDom.offsetLeft
29 const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
30
31 const minDragDomTop = dragDom.offsetTop
32 const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
33
34 // 获取到的值带px 正则匹配替换
35 let styL = getStyle(dragDom, 'left')
36 let styT = getStyle(dragDom, 'top')
37
38 if (styL.includes('%')) {
39 styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
40 styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
41 } else {
42 styL = +styL.replace(/\px/g, '')
43 styT = +styT.replace(/\px/g, '')
44 }
45
46 document.onmousemove = function(e) {
47 // 通过事件委托,计算移动的距离
48 let left = e.clientX - disX
49 let top = e.clientY - disY
50
51 // 边界处理
52 if (-(left) > minDragDomLeft) {
53 left = -minDragDomLeft
54 } else if (left > maxDragDomLeft) {
55 left = maxDragDomLeft
56 }
57
58 if (-(top) > minDragDomTop) {
59 top = -minDragDomTop
60 } else if (top > maxDragDomTop) {
61 top = maxDragDomTop
62 }
63
64 // 移动当前元素
65 dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
66
67 // emit onDrag event
68 vnode.child.$emit('dragDialog')
69 }
70
71 document.onmouseup = function(e) {
72 document.onmousemove = null
73 document.onmouseup = null
74 }
75 }
76 }
77 }
78
src/directive/el-drag-dialog/index.js
File was created 1 import drag from './drag'
2
3 const install = function(Vue) {
4 Vue.directive('el-drag-dialog', drag)
5 }
6
7 if (window.Vue) {
8 window['el-drag-dialog'] = drag
9 Vue.use(install); // eslint-disable-line
10 }
11
12 drag.install = install
13 export default drag
14
src/directive/el-table/adaptive.js
File was created 1 import { addResizeListener, removeResizeListener } from 'element-ui/src/utils/resize-event'
2
3 /**
4 * How to use
5 * <el-table height="100px" v-el-height-adaptive-table="{bottomOffset: 30}">...</el-table>
6 * el-table height is must be set
7 * bottomOffset: 30(default) // The height of the table from the bottom of the page.
8 */
9
10 const doResize = (el, binding, vnode) => {
11 const { componentInstance: $table } = vnode
12
13 const { value } = binding
14
15 if (!$table.height) {
16 throw new Error(`el-$table must set the height. Such as height='100px'`)
17 }
18 const bottomOffset = (value && value.bottomOffset) || 30
19
20 if (!$table) return
21
22 const height = window.innerHeight - el.getBoundingClientRect().top - bottomOffset
23 $table.layout.setHeight(height)
24 $table.doLayout()
25 }
26
27 export default {
28 bind(el, binding, vnode) {
29 el.resizeListener = () => {
30 doResize(el, binding, vnode)
31 }
32 // parameter 1 is must be "Element" type
33 addResizeListener(window.document.body, el.resizeListener)
34 },
35 inserted(el, binding, vnode) {
36 doResize(el, binding, vnode)
37 },
38 unbind(el) {
39 removeResizeListener(window.document.body, el.resizeListener)
40 }
41 }
42
src/directive/el-table/index.js
File was created 1 import adaptive from './adaptive'
2
3 const install = function(Vue) {
4 Vue.directive('el-height-adaptive-table', adaptive)
5 }
6
7 if (window.Vue) {
8 window['el-height-adaptive-table'] = adaptive
9 Vue.use(install); // eslint-disable-line
10 }
11
12 adaptive.install = install
13 export default adaptive
14
src/directive/permission/index.js
File was created 1 import permission from './permission'
2
3 const install = function(Vue) {
4 Vue.directive('permission', permission)
5 }
6
7 if (window.Vue) {
8 window['permission'] = permission
9 Vue.use(install); // eslint-disable-line
10 }
11
12 permission.install = install
13 export default permission
14
src/directive/permission/permission.js
File was created 1 import store from '@/store'
2
3 export default {
4 inserted(el, binding, vnode) {
5 const { value } = binding
6 const roles = store.getters && store.getters.roles
7
8 if (value && value instanceof Array && value.length > 0) {
9 const permissionRoles = value
10
11 const hasPermission = roles.some(role => {
12 return permissionRoles.includes(role)
13 })
14
15 if (!hasPermission) {
16 el.parentNode && el.parentNode.removeChild(el)
17 }
18 } else {
19 throw new Error(`need roles! Like v-permission="['admin','editor']"`)
20 }
21 }
22 }
23
src/directive/sticky.js
File was created 1 const vueSticky = {}
2 let listenAction
3 vueSticky.install = Vue => {
4 Vue.directive('sticky', {
5 inserted(el, binding) {
6 const params = binding.value || {}
7 const stickyTop = params.stickyTop || 0
8 const zIndex = params.zIndex || 1000
9 const elStyle = el.style
10
11 elStyle.position = '-webkit-sticky'
12 elStyle.position = 'sticky'
13 // if the browser support css sticky(Currently Safari, Firefox and Chrome Canary)
14 // if (~elStyle.position.indexOf('sticky')) {
15 // elStyle.top = `${stickyTop}px`;
16 // elStyle.zIndex = zIndex;
17 // return
18 // }
19 const elHeight = el.getBoundingClientRect().height
20 const elWidth = el.getBoundingClientRect().width
21 elStyle.cssText = `top: ${stickyTop}px; z-index: ${zIndex}`
22
23 const parentElm = el.parentNode || document.documentElement
24 const placeholder = document.createElement('div')
25 placeholder.style.display = 'none'
26 placeholder.style.width = `${elWidth}px`
27 placeholder.style.height = `${elHeight}px`
28 parentElm.insertBefore(placeholder, el)
29
30 let active = false
31
32 const getScroll = (target, top) => {
33 const prop = top ? 'pageYOffset' : 'pageXOffset'
34 const method = top ? 'scrollTop' : 'scrollLeft'
35 let ret = target[prop]
36 if (typeof ret !== 'number') {
37 ret = window.document.documentElement[method]
38 }
39 return ret
40 }
41
42 const sticky = () => {
43 if (active) {
44 return
45 }
46 if (!elStyle.height) {
47 elStyle.height = `${el.offsetHeight}px`
48 }
49
50 elStyle.position = 'fixed'
51 elStyle.width = `${elWidth}px`
52 placeholder.style.display = 'inline-block'
53 active = true
54 }
55
56 const reset = () => {
57 if (!active) {
58 return
59 }
60
61 elStyle.position = ''
62 placeholder.style.display = 'none'
63 active = false
64 }
65
66 const check = () => {
67 const scrollTop = getScroll(window, true)
68 const offsetTop = el.getBoundingClientRect().top
69 if (offsetTop < stickyTop) {
70 sticky()
71 } else {
72 if (scrollTop < elHeight + stickyTop) {
73 reset()
74 }
75 }
76 }
77 listenAction = () => {
78 check()
79 }
80
81 window.addEventListener('scroll', listenAction)
82 },
83
84 unbind() {
85 window.removeEventListener('scroll', listenAction)
86 }
87 })
88 }
89
90 export default vueSticky
91
92
src/directive/waves/index.js
File was created 1 import waves from './waves'
2
3 const install = function(Vue) {
4 Vue.directive('waves', waves)
5 }
6
7 if (window.Vue) {
8 window.waves = waves
9 Vue.use(install); // eslint-disable-line
10 }
11
12 waves.install = install
13 export default waves
14
src/directive/waves/waves.css
File was created 1 .waves-ripple {
2 position: absolute;
3 border-radius: 100%;
4 background-color: rgba(0, 0, 0, 0.15);
5 background-clip: padding-box;
6 pointer-events: none;
7 -webkit-user-select: none;
8 -moz-user-select: none;
9 -ms-user-select: none;
10 user-select: none;
11 -webkit-transform: scale(0);
12 -ms-transform: scale(0);
13 transform: scale(0);
14 opacity: 1;
15 }
16
17 .waves-ripple.z-active {
18 opacity: 0;
19 -webkit-transform: scale(2);
20 -ms-transform: scale(2);
21 transform: scale(2);
22 -webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
23 transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
24 transition: opacity 1.2s ease-out, transform 0.6s ease-out;
25 transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out;
26 }
src/directive/waves/waves.js
File was created 1 import './waves.css'
2
3 const context = '@@wavesContext'
4
5 function handleClick(el, binding) {
6 function handle(e) {
7 const customOpts = Object.assign({}, binding.value)
8 const opts = Object.assign({
9 ele: el, // 波纹作用元素
10 type: 'hit', // hit 点击位置扩散 center中心点扩展
11 color: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
12 },
13 customOpts
14 )
15 const target = opts.ele
16 if (target) {
17 target.style.position = 'relative'
18 target.style.overflow = 'hidden'
19 const rect = target.getBoundingClientRect()
20 let ripple = target.querySelector('.waves-ripple')
21 if (!ripple) {
22 ripple = document.createElement('span')
23 ripple.className = 'waves-ripple'
24 ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
25 target.appendChild(ripple)
26 } else {
27 ripple.className = 'waves-ripple'
28 }
29 switch (opts.type) {
30 case 'center':
31 ripple.style.top = rect.height / 2 - ripple.offsetHeight / 2 + 'px'
32 ripple.style.left = rect.width / 2 - ripple.offsetWidth / 2 + 'px'
33 break
34 default:
35 ripple.style.top =
36 (e.pageY - rect.top - ripple.offsetHeight / 2 - document.documentElement.scrollTop ||
37 document.body.scrollTop) + 'px'
38 ripple.style.left =
39 (e.pageX - rect.left - ripple.offsetWidth / 2 - document.documentElement.scrollLeft ||
40 document.body.scrollLeft) + 'px'
41 }
42 ripple.style.backgroundColor = opts.color
43 ripple.className = 'waves-ripple z-active'
44 return false
45 }
46 }
47
48 if (!el[context]) {
49 el[context] = {
50 removeHandle: handle
51 }
52 } else {
53 el[context].removeHandle = handle
54 }
55
56 return handle
57 }
58
59 export default {
60 bind(el, binding) {
61 el.addEventListener('click', handleClick(el, binding), false)
62 },
63 update(el, binding) {
64 el.removeEventListener('click', el[context].removeHandle, false)
65 el.addEventListener('click', handleClick(el, binding), false)
66 },
67 unbind(el) {
68 el.removeEventListener('click', el[context].removeHandle, false)
69 el[context] = null
70 delete el[context]
71 }
72 }
73
src/filters/index.js
File was created 1 // import parseTime, formatTime and set to filter
2 export { parseTime, formatTime } from '@/utils'
3
4 /**
5 * Show plural label if time is plural number
6 * @param {number} time
7 * @param {string} label
8 * @return {string}
9 */
10 function pluralize(time, label) {
11 if (time === 1) {
12 return time + label
13 }
14 return time + label + 's'
15 }
16
17 /**
18 * @param {number} time
19 */
20 export function timeAgo(time) {
21 const between = Date.now() / 1000 - Number(time)
22 if (between < 3600) {
23 return pluralize(~~(between / 60), ' minute')
24 } else if (between < 86400) {
25 return pluralize(~~(between / 3600), ' hour')
26 } else {
27 return pluralize(~~(between / 86400), ' day')
28 }
29 }
30
31 /**
32 * Number formatting
33 * like 10000 => 10k
34 * @param {number} num
35 * @param {number} digits
36 */
37 export function numberFormatter(num, digits) {
38 const si = [
39 { value: 1E18, symbol: 'E' },
40 { value: 1E15, symbol: 'P' },
41 { value: 1E12, symbol: 'T' },
42 { value: 1E9, symbol: 'G' },
43 { value: 1E6, symbol: 'M' },
44 { value: 1E3, symbol: 'k' }
45 ]
46 for (let i = 0; i < si.length; i++) {
47 if (num >= si[i].value) {
48 return (num / si[i].value).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
49 }
50 }
51 return num.toString()
52 }
53
54 /**
55 * 10000 => "10,000"
56 * @param {number} num
57 */
58 export function toThousandFilter(num) {
59 return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','))
60 }
61
62 /**
63 * Upper case first char
64 * @param {String} string
65 */
66 export function uppercaseFirst(string) {
67 return string.charAt(0).toUpperCase() + string.slice(1)
68 }
69
src/icons/index.js 100644 → 100755
1 import Vue from 'vue' 1 import Vue from 'vue'
2 import SvgIcon from '@/components/SvgIcon'// svg component 2 import SvgIcon from '@/components/SvgIcon'// svg component
3 3
4 // register globally 4 // register globally
5 Vue.component('svg-icon', SvgIcon) 5 Vue.component('svg-icon', SvgIcon)
6 6
7 const req = require.context('./svg', false, /\.svg$/) 7 const req = require.context('./svg', false, /\.svg$/)
8 const requireAll = requireContext => requireContext.keys().map(requireContext) 8 const requireAll = requireContext => requireContext.keys().map(requireContext)
9 requireAll(req) 9 requireAll(req)
10 10
src/icons/svg/404.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M121.718 73.272v9.953c3.957-7.584 6.199-16.05 6.199-24.995C127.917 26.079 99.273 0 63.958 0 28.644 0 0 26.079 0 58.23c0 .403.028.806.028 1.21l22.97-25.953h13.34l-19.76 27.187h6.42V53.77l13.728-19.477v49.361H22.998V73.272H2.158c5.951 20.284 23.608 36.208 45.998 41.399-1.44 3.3-5.618 11.263-12.565 12.674-8.607 1.764 23.358.428 46.163-13.178 17.519-4.611 31.938-15.849 39.77-30.513h-13.506V73.272H85.02V59.464l22.998-25.977h13.008l-19.429 27.187h6.421v-7.433l13.727-19.402v39.433h-.027zm-78.24 2.822a10.516 10.516 0 0 1-.996-4.535V44.548c0-1.613.332-3.124.996-4.535a11.66 11.66 0 0 1 2.713-3.68c1.134-1.032 2.49-1.864 4.04-2.468 1.55-.605 3.21-.908 4.982-.908h11.292c1.77 0 3.431.303 4.981.908 1.522.604 2.85 1.41 3.986 2.418l-12.26 16.303v-2.898a1.96 1.96 0 0 0-.665-1.512c-.443-.403-.996-.604-1.66-.604-.665 0-1.218.201-1.661.604a1.96 1.96 0 0 0-.664 1.512v9.071L44.364 77.606a10.556 10.556 0 0 1-.886-1.512zm35.73-4.535c0 1.613-.332 3.124-.997 4.535a11.66 11.66 0 0 1-2.712 3.68c-1.134 1.032-2.49 1.864-4.04 2.469-1.55.604-3.21.907-4.982.907H55.185c-1.77 0-3.431-.303-4.981-.907-1.55-.605-2.906-1.437-4.041-2.47a12.49 12.49 0 0 1-1.384-1.512l13.727-18.217v6.375c0 .605.222 1.109.665 1.512.442.403.996.604 1.66.604.664 0 1.218-.201 1.66-.604a1.96 1.96 0 0 0 .665-1.512V53.87L75.97 36.838c.913.932 1.66 1.99 2.214 3.175.664 1.41.996 2.922.996 4.535v27.011h.028z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M121.718 73.272v9.953c3.957-7.584 6.199-16.05 6.199-24.995C127.917 26.079 99.273 0 63.958 0 28.644 0 0 26.079 0 58.23c0 .403.028.806.028 1.21l22.97-25.953h13.34l-19.76 27.187h6.42V53.77l13.728-19.477v49.361H22.998V73.272H2.158c5.951 20.284 23.608 36.208 45.998 41.399-1.44 3.3-5.618 11.263-12.565 12.674-8.607 1.764 23.358.428 46.163-13.178 17.519-4.611 31.938-15.849 39.77-30.513h-13.506V73.272H85.02V59.464l22.998-25.977h13.008l-19.429 27.187h6.421v-7.433l13.727-19.402v39.433h-.027zm-78.24 2.822a10.516 10.516 0 0 1-.996-4.535V44.548c0-1.613.332-3.124.996-4.535a11.66 11.66 0 0 1 2.713-3.68c1.134-1.032 2.49-1.864 4.04-2.468 1.55-.605 3.21-.908 4.982-.908h11.292c1.77 0 3.431.303 4.981.908 1.522.604 2.85 1.41 3.986 2.418l-12.26 16.303v-2.898a1.96 1.96 0 0 0-.665-1.512c-.443-.403-.996-.604-1.66-.604-.665 0-1.218.201-1.661.604a1.96 1.96 0 0 0-.664 1.512v9.071L44.364 77.606a10.556 10.556 0 0 1-.886-1.512zm35.73-4.535c0 1.613-.332 3.124-.997 4.535a11.66 11.66 0 0 1-2.712 3.68c-1.134 1.032-2.49 1.864-4.04 2.469-1.55.604-3.21.907-4.982.907H55.185c-1.77 0-3.431-.303-4.981-.907-1.55-.605-2.906-1.437-4.041-2.47a12.49 12.49 0 0 1-1.384-1.512l13.727-18.217v6.375c0 .605.222 1.109.665 1.512.442.403.996.604 1.66.604.664 0 1.218-.201 1.66-.604a1.96 1.96 0 0 0 .665-1.512V53.87L75.97 36.838c.913.932 1.66 1.99 2.214 3.175.664 1.41.996 2.922.996 4.535v27.011h.028z"/></svg>
src/icons/svg/bug.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M127.88 73.143c0 1.412-.506 2.635-1.518 3.669-1.011 1.033-2.209 1.55-3.592 1.55h-17.887c0 9.296-1.783 17.178-5.35 23.645l16.609 17.044c1.011 1.034 1.517 2.257 1.517 3.67 0 1.412-.506 2.635-1.517 3.668-.958 1.033-2.155 1.55-3.593 1.55-1.438 0-2.635-.517-3.593-1.55l-15.811-16.063a15.49 15.49 0 0 1-1.196 1.06c-.532.434-1.65 1.208-3.353 2.322a50.104 50.104 0 0 1-5.192 2.974c-1.758.87-3.94 1.658-6.546 2.364-2.607.706-5.189 1.06-7.748 1.06V47.044H58.89v73.062c-2.716 0-5.417-.367-8.106-1.102-2.688-.734-5.003-1.631-6.945-2.692a66.769 66.769 0 0 1-5.268-3.179c-1.571-1.057-2.73-1.94-3.476-2.65L33.9 109.34l-14.611 16.877c-1.066 1.14-2.344 1.711-3.833 1.711-1.277 0-2.422-.434-3.434-1.304-1.012-.978-1.557-2.187-1.635-3.627-.079-1.44.333-2.705 1.236-3.794l16.129-18.51c-3.087-6.197-4.63-13.644-4.63-22.342H5.235c-1.383 0-2.58-.517-3.592-1.55S.125 74.545.125 73.132c0-1.412.506-2.635 1.518-3.668 1.012-1.034 2.21-1.55 3.592-1.55h17.887V43.939L9.308 29.833c-1.012-1.033-1.517-2.256-1.517-3.669 0-1.412.505-2.635 1.517-3.668 1.012-1.034 2.21-1.55 3.593-1.55s2.58.516 3.593 1.55l13.813 14.106h67.396l13.814-14.106c1.012-1.034 2.21-1.55 3.592-1.55 1.384 0 2.581.516 3.593 1.55 1.012 1.033 1.518 2.256 1.518 3.668 0 1.413-.506 2.636-1.518 3.67l-13.814 14.105v23.975h17.887c1.383 0 2.58.516 3.593 1.55 1.011 1.033 1.517 2.256 1.517 3.668l-.005.01zM89.552 26.175H38.448c0-7.23 2.489-13.386 7.466-18.469C50.892 2.623 56.92.082 64 .082c7.08 0 13.108 2.541 18.086 7.624 4.977 5.083 7.466 11.24 7.466 18.469z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M127.88 73.143c0 1.412-.506 2.635-1.518 3.669-1.011 1.033-2.209 1.55-3.592 1.55h-17.887c0 9.296-1.783 17.178-5.35 23.645l16.609 17.044c1.011 1.034 1.517 2.257 1.517 3.67 0 1.412-.506 2.635-1.517 3.668-.958 1.033-2.155 1.55-3.593 1.55-1.438 0-2.635-.517-3.593-1.55l-15.811-16.063a15.49 15.49 0 0 1-1.196 1.06c-.532.434-1.65 1.208-3.353 2.322a50.104 50.104 0 0 1-5.192 2.974c-1.758.87-3.94 1.658-6.546 2.364-2.607.706-5.189 1.06-7.748 1.06V47.044H58.89v73.062c-2.716 0-5.417-.367-8.106-1.102-2.688-.734-5.003-1.631-6.945-2.692a66.769 66.769 0 0 1-5.268-3.179c-1.571-1.057-2.73-1.94-3.476-2.65L33.9 109.34l-14.611 16.877c-1.066 1.14-2.344 1.711-3.833 1.711-1.277 0-2.422-.434-3.434-1.304-1.012-.978-1.557-2.187-1.635-3.627-.079-1.44.333-2.705 1.236-3.794l16.129-18.51c-3.087-6.197-4.63-13.644-4.63-22.342H5.235c-1.383 0-2.58-.517-3.592-1.55S.125 74.545.125 73.132c0-1.412.506-2.635 1.518-3.668 1.012-1.034 2.21-1.55 3.592-1.55h17.887V43.939L9.308 29.833c-1.012-1.033-1.517-2.256-1.517-3.669 0-1.412.505-2.635 1.517-3.668 1.012-1.034 2.21-1.55 3.593-1.55s2.58.516 3.593 1.55l13.813 14.106h67.396l13.814-14.106c1.012-1.034 2.21-1.55 3.592-1.55 1.384 0 2.581.516 3.593 1.55 1.012 1.033 1.518 2.256 1.518 3.668 0 1.413-.506 2.636-1.518 3.67l-13.814 14.105v23.975h17.887c1.383 0 2.58.516 3.593 1.55 1.011 1.033 1.517 2.256 1.517 3.668l-.005.01zM89.552 26.175H38.448c0-7.23 2.489-13.386 7.466-18.469C50.892 2.623 56.92.082 64 .082c7.08 0 13.108 2.541 18.086 7.624 4.977 5.083 7.466 11.24 7.466 18.469z"/></svg>
src/icons/svg/chart.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h36.571V128H0V54.857zM91.429 27.43H128V128H91.429V27.429zM45.714 0h36.572v128H45.714V0z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h36.571V128H0V54.857zM91.429 27.43H128V128H91.429V27.429zM45.714 0h36.572v128H45.714V0z"/></svg>
src/icons/svg/clipboard.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.857 118.857h64V73.143H89.143c-1.902 0-3.52-.668-4.855-2.002-1.335-1.335-2.002-2.954-2.002-4.855V36.57H54.857v82.286zM73.143 16v-4.571a2.2 2.2 0 0 0-.677-1.61 2.198 2.198 0 0 0-1.609-.676H20.571c-.621 0-1.158.225-1.609.676a2.198 2.198 0 0 0-.676 1.61V16a2.2 2.2 0 0 0 .676 1.61c.451.45.988.676 1.61.676h50.285c.622 0 1.158-.226 1.61-.677.45-.45.676-.987.676-1.609zm18.286 48h21.357L91.43 42.642V64zM128 73.143v48c0 1.902-.667 3.52-2.002 4.855-1.335 1.335-2.953 2.002-4.855 2.002H52.57c-1.901 0-3.52-.667-4.854-2.002-1.335-1.335-2.003-2.953-2.003-4.855v-11.429H6.857c-1.902 0-3.52-.667-4.855-2.002C.667 106.377 0 104.759 0 102.857v-96c0-1.902.667-3.52 2.002-4.855C3.337.667 4.955 0 6.857 0h77.714c1.902 0 3.52.667 4.855 2.002 1.335 1.335 2.003 2.953 2.003 4.855V30.29c1 .622 1.856 1.29 2.569 2.003l29.147 29.147c1.335 1.335 2.478 3.145 3.429 5.43.95 2.287 1.426 4.383 1.426 6.291v-.018z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.857 118.857h64V73.143H89.143c-1.902 0-3.52-.668-4.855-2.002-1.335-1.335-2.002-2.954-2.002-4.855V36.57H54.857v82.286zM73.143 16v-4.571a2.2 2.2 0 0 0-.677-1.61 2.198 2.198 0 0 0-1.609-.676H20.571c-.621 0-1.158.225-1.609.676a2.198 2.198 0 0 0-.676 1.61V16a2.2 2.2 0 0 0 .676 1.61c.451.45.988.676 1.61.676h50.285c.622 0 1.158-.226 1.61-.677.45-.45.676-.987.676-1.609zm18.286 48h21.357L91.43 42.642V64zM128 73.143v48c0 1.902-.667 3.52-2.002 4.855-1.335 1.335-2.953 2.002-4.855 2.002H52.57c-1.901 0-3.52-.667-4.854-2.002-1.335-1.335-2.003-2.953-2.003-4.855v-11.429H6.857c-1.902 0-3.52-.667-4.855-2.002C.667 106.377 0 104.759 0 102.857v-96c0-1.902.667-3.52 2.002-4.855C3.337.667 4.955 0 6.857 0h77.714c1.902 0 3.52.667 4.855 2.002 1.335 1.335 2.003 2.953 2.003 4.855V30.29c1 .622 1.856 1.29 2.569 2.003l29.147 29.147c1.335 1.335 2.478 3.145 3.429 5.43.95 2.287 1.426 4.383 1.426 6.291v-.018z"/></svg>
src/icons/svg/component.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h54.857v54.857H0V0zm0 73.143h54.857V128H0V73.143zm73.143 0H128V128H73.143V73.143zm27.428-18.286C115.72 54.857 128 42.577 128 27.43 128 12.28 115.72 0 100.571 0 85.423 0 73.143 12.28 73.143 27.429c0 15.148 12.28 27.428 27.428 27.428z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 0h54.857v54.857H0V0zm0 73.143h54.857V128H0V73.143zm73.143 0H128V128H73.143V73.143zm27.428-18.286C115.72 54.857 128 42.577 128 27.43 128 12.28 115.72 0 100.571 0 85.423 0 73.143 12.28 73.143 27.429c0 15.148 12.28 27.428 27.428 27.428z"/></svg>
src/icons/svg/dashboard.svg 100644 → 100755
1 <svg width="128" height="100" xmlns="http://www.w3.org/2000/svg"><path d="M27.429 63.638c0-2.508-.893-4.65-2.679-6.424-1.786-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.465 2.662-1.785 1.774-2.678 3.916-2.678 6.424 0 2.508.893 4.65 2.678 6.424 1.786 1.775 3.94 2.662 6.465 2.662 2.524 0 4.678-.887 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm13.714-31.801c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM71.714 65.98l7.215-27.116c.285-1.23.107-2.378-.536-3.443-.643-1.064-1.56-1.762-2.75-2.094-1.19-.33-2.333-.177-3.429.462-1.095.639-1.81 1.573-2.143 2.804l-7.214 27.116c-2.857.237-5.405 1.266-7.643 3.088-2.238 1.822-3.738 4.152-4.5 6.992-.952 3.644-.476 7.098 1.429 10.364 1.905 3.265 4.69 5.37 8.357 6.317 3.667.947 7.143.474 10.429-1.42 3.285-1.892 5.404-4.66 6.357-8.305.762-2.84.619-5.607-.429-8.305-1.047-2.697-2.762-4.85-5.143-6.46zm47.143-2.342c0-2.508-.893-4.65-2.678-6.424-1.786-1.775-3.94-2.662-6.465-2.662-2.524 0-4.678.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.786 1.775 3.94 2.662 6.464 2.662 2.524 0 4.679-.887 6.465-2.662 1.785-1.775 2.678-3.916 2.678-6.424zm-45.714-45.43c0-2.509-.893-4.65-2.679-6.425C68.68 10.01 66.524 9.122 64 9.122c-2.524 0-4.679.887-6.464 2.661-1.786 1.775-2.679 3.916-2.679 6.425 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm32 13.629c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM128 63.638c0 12.351-3.357 23.78-10.071 34.286-.905 1.372-2.19 2.058-3.858 2.058H13.93c-1.667 0-2.953-.686-3.858-2.058C3.357 87.465 0 76.037 0 63.638c0-8.613 1.69-16.847 5.071-24.703C8.452 31.08 13 24.312 18.714 18.634c5.715-5.68 12.524-10.199 20.429-13.559C47.048 1.715 55.333.035 64 .035c8.667 0 16.952 1.68 24.857 5.04 7.905 3.36 14.714 7.88 20.429 13.559 5.714 5.678 10.262 12.446 13.643 20.301 3.38 7.856 5.071 16.09 5.071 24.703z"/></svg> 1 <svg width="128" height="100" xmlns="http://www.w3.org/2000/svg"><path d="M27.429 63.638c0-2.508-.893-4.65-2.679-6.424-1.786-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.465 2.662-1.785 1.774-2.678 3.916-2.678 6.424 0 2.508.893 4.65 2.678 6.424 1.786 1.775 3.94 2.662 6.465 2.662 2.524 0 4.678-.887 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm13.714-31.801c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM71.714 65.98l7.215-27.116c.285-1.23.107-2.378-.536-3.443-.643-1.064-1.56-1.762-2.75-2.094-1.19-.33-2.333-.177-3.429.462-1.095.639-1.81 1.573-2.143 2.804l-7.214 27.116c-2.857.237-5.405 1.266-7.643 3.088-2.238 1.822-3.738 4.152-4.5 6.992-.952 3.644-.476 7.098 1.429 10.364 1.905 3.265 4.69 5.37 8.357 6.317 3.667.947 7.143.474 10.429-1.42 3.285-1.892 5.404-4.66 6.357-8.305.762-2.84.619-5.607-.429-8.305-1.047-2.697-2.762-4.85-5.143-6.46zm47.143-2.342c0-2.508-.893-4.65-2.678-6.424-1.786-1.775-3.94-2.662-6.465-2.662-2.524 0-4.678.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.786 1.775 3.94 2.662 6.464 2.662 2.524 0 4.679-.887 6.465-2.662 1.785-1.775 2.678-3.916 2.678-6.424zm-45.714-45.43c0-2.509-.893-4.65-2.679-6.425C68.68 10.01 66.524 9.122 64 9.122c-2.524 0-4.679.887-6.464 2.661-1.786 1.775-2.679 3.916-2.679 6.425 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm32 13.629c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM128 63.638c0 12.351-3.357 23.78-10.071 34.286-.905 1.372-2.19 2.058-3.858 2.058H13.93c-1.667 0-2.953-.686-3.858-2.058C3.357 87.465 0 76.037 0 63.638c0-8.613 1.69-16.847 5.071-24.703C8.452 31.08 13 24.312 18.714 18.634c5.715-5.68 12.524-10.199 20.429-13.559C47.048 1.715 55.333.035 64 .035c8.667 0 16.952 1.68 24.857 5.04 7.905 3.36 14.714 7.88 20.429 13.559 5.714 5.678 10.262 12.446 13.643 20.301 3.38 7.856 5.071 16.09 5.071 24.703z"/></svg>
src/icons/svg/documentation.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M71.984 44.815H115.9L71.984 9.642v35.173zM16.094.05h63.875l47.906 38.37v76.74c0 3.392-1.682 6.645-4.677 9.044-2.995 2.399-7.056 3.746-11.292 3.746H16.094c-4.236 0-8.297-1.347-11.292-3.746-2.995-2.399-4.677-5.652-4.677-9.044V12.84C.125 5.742 7.23.05 16.094.05zm71.86 102.32V89.58h-71.86v12.79h71.86zm23.952-25.58V64H16.094v12.79h95.812z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M71.984 44.815H115.9L71.984 9.642v35.173zM16.094.05h63.875l47.906 38.37v76.74c0 3.392-1.682 6.645-4.677 9.044-2.995 2.399-7.056 3.746-11.292 3.746H16.094c-4.236 0-8.297-1.347-11.292-3.746-2.995-2.399-4.677-5.652-4.677-9.044V12.84C.125 5.742 7.23.05 16.094.05zm71.86 102.32V89.58h-71.86v12.79h71.86zm23.952-25.58V64H16.094v12.79h95.812z"/></svg>
src/icons/svg/drag.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M73.137 29.08h-9.209 29.7L63.886.093 34.373 29.08h20.49v27.035H27.238v17.948h27.625v27.133h18.274V74.063h27.41V56.115h-27.41V29.08zm-9.245 98.827l27.518-26.711H36.59l27.302 26.71zM.042 64.982l27.196 27.029V38.167L.042 64.982zm100.505-26.815V92.01l27.41-27.029-27.41-26.815z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M73.137 29.08h-9.209 29.7L63.886.093 34.373 29.08h20.49v27.035H27.238v17.948h27.625v27.133h18.274V74.063h27.41V56.115h-27.41V29.08zm-9.245 98.827l27.518-26.711H36.59l27.302 26.71zM.042 64.982l27.196 27.029V38.167L.042 64.982zm100.505-26.815V92.01l27.41-27.029-27.41-26.815z"/></svg>
src/icons/svg/edit.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M106.133 67.2a4.797 4.797 0 0 0-4.8 4.8c0 .187.014.36.027.533h-.027V118.4H9.6V26.667h50.133c2.654 0 4.8-2.147 4.8-4.8 0-2.654-2.146-4.8-4.8-4.8H9.6a9.594 9.594 0 0 0-9.6 9.6V118.4c0 5.307 4.293 9.6 9.6 9.6h91.733c5.307 0 9.6-4.293 9.6-9.6V72.533h-.026c.013-.173.026-.346.026-.533 0-2.653-2.146-4.8-4.8-4.8z"/><path d="M125.16 13.373L114.587 2.8c-3.747-3.747-9.854-3.72-13.6.027l-52.96 52.96a4.264 4.264 0 0 0-.907 1.36L33.813 88.533c-.746 1.76-.226 3.534.907 4.68 1.133 1.147 2.92 1.667 4.693.92l31.4-13.293c.507-.213.96-.52 1.36-.907l52.96-52.96c3.747-3.746 3.774-9.853.027-13.6zM66.107 72.4l-18.32 7.76 7.76-18.32L92.72 24.667l10.56 10.56L66.107 72.4zm52.226-52.227l-8.266 8.267-10.56-10.56 8.266-8.267.027-.026 10.56 10.56-.027.026z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M106.133 67.2a4.797 4.797 0 0 0-4.8 4.8c0 .187.014.36.027.533h-.027V118.4H9.6V26.667h50.133c2.654 0 4.8-2.147 4.8-4.8 0-2.654-2.146-4.8-4.8-4.8H9.6a9.594 9.594 0 0 0-9.6 9.6V118.4c0 5.307 4.293 9.6 9.6 9.6h91.733c5.307 0 9.6-4.293 9.6-9.6V72.533h-.026c.013-.173.026-.346.026-.533 0-2.653-2.146-4.8-4.8-4.8z"/><path d="M125.16 13.373L114.587 2.8c-3.747-3.747-9.854-3.72-13.6.027l-52.96 52.96a4.264 4.264 0 0 0-.907 1.36L33.813 88.533c-.746 1.76-.226 3.534.907 4.68 1.133 1.147 2.92 1.667 4.693.92l31.4-13.293c.507-.213.96-.52 1.36-.907l52.96-52.96c3.747-3.746 3.774-9.853.027-13.6zM66.107 72.4l-18.32 7.76 7.76-18.32L92.72 24.667l10.56 10.56L66.107 72.4zm52.226-52.227l-8.266 8.267-10.56-10.56 8.266-8.267.027-.026 10.56 10.56-.027.026z"/></svg>
src/icons/svg/education.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M88.883 119.565c-7.284 0-19.434 2.495-21.333 8.25v.127c-4.232.13-5.222 0-7.108 0-1.895-5.76-14.045-8.256-21.333-8.256H0V0h42.523c9.179 0 17.109 5.47 21.47 13.551C68.352 5.475 76.295 0 85.478 0H128v119.57l-39.113-.005h-.004zM60.442 24.763c0-9.651-8.978-16.507-17.777-16.507H7.108V111.43H39.11c7.054-.14 18.177.082 21.333 6.12v-4.628c-.134-5.722-.004-13.522 0-13.832V27.413l.004-2.655-.004.005zm60.442-16.517h-35.55c-8.802 0-17.78 6.856-17.78 16.493v74.259c.004.32.138 8.115 0 13.813v4.627c3.155-6.022 14.279-6.26 21.333-6.114h32V8.25l-.003-.005z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M88.883 119.565c-7.284 0-19.434 2.495-21.333 8.25v.127c-4.232.13-5.222 0-7.108 0-1.895-5.76-14.045-8.256-21.333-8.256H0V0h42.523c9.179 0 17.109 5.47 21.47 13.551C68.352 5.475 76.295 0 85.478 0H128v119.57l-39.113-.005h-.004zM60.442 24.763c0-9.651-8.978-16.507-17.777-16.507H7.108V111.43H39.11c7.054-.14 18.177.082 21.333 6.12v-4.628c-.134-5.722-.004-13.522 0-13.832V27.413l.004-2.655-.004.005zm60.442-16.517h-35.55c-8.802 0-17.78 6.856-17.78 16.493v74.259c.004.32.138 8.115 0 13.813v4.627c3.155-6.022 14.279-6.26 21.333-6.114h32V8.25l-.003-.005z"/></svg>
src/icons/svg/email.svg 100644 → 100755
1 <svg width="128" height="96" xmlns="http://www.w3.org/2000/svg"><path d="M64.125 56.975L120.188.912A12.476 12.476 0 0 0 115.5 0h-103c-1.588 0-3.113.3-4.513.838l56.138 56.137z"/><path d="M64.125 68.287l-62.3-62.3A12.42 12.42 0 0 0 0 12.5v71C0 90.4 5.6 96 12.5 96h103c6.9 0 12.5-5.6 12.5-12.5v-71a12.47 12.47 0 0 0-1.737-6.35L64.125 68.287z"/></svg> 1 <svg width="128" height="96" xmlns="http://www.w3.org/2000/svg"><path d="M64.125 56.975L120.188.912A12.476 12.476 0 0 0 115.5 0h-103c-1.588 0-3.113.3-4.513.838l56.138 56.137z"/><path d="M64.125 68.287l-62.3-62.3A12.42 12.42 0 0 0 0 12.5v71C0 90.4 5.6 96 12.5 96h103c6.9 0 12.5-5.6 12.5-12.5v-71a12.47 12.47 0 0 0-1.737-6.35L64.125 68.287z"/></svg>
src/icons/svg/example.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M96.258 57.462h31.421C124.794 27.323 100.426 2.956 70.287.07v31.422a32.856 32.856 0 0 1 25.971 25.97zm-38.796-25.97V.07C27.323 2.956 2.956 27.323.07 57.462h31.422a32.856 32.856 0 0 1 25.97-25.97zm12.825 64.766v31.421c30.46-2.885 54.507-27.253 57.713-57.712H96.579c-2.886 13.466-13.146 23.726-26.292 26.291zM31.492 70.287H.07c2.886 30.46 27.253 54.507 57.713 57.713V96.579c-13.466-2.886-23.726-13.146-26.291-26.292z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M96.258 57.462h31.421C124.794 27.323 100.426 2.956 70.287.07v31.422a32.856 32.856 0 0 1 25.971 25.97zm-38.796-25.97V.07C27.323 2.956 2.956 27.323.07 57.462h31.422a32.856 32.856 0 0 1 25.97-25.97zm12.825 64.766v31.421c30.46-2.885 54.507-27.253 57.713-57.712H96.579c-2.886 13.466-13.146 23.726-26.292 26.291zM31.492 70.287H.07c2.886 30.46 27.253 54.507 57.713 57.713V96.579c-13.466-2.886-23.726-13.146-26.291-26.292z"/></svg>
src/icons/svg/excel.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.208 16.576v8.384h38.72v5.376h-38.72v8.704h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.512h38.72v5.376h-38.72v11.136H128v-94.72H78.208zM0 114.368L72.128 128V0L0 13.632v100.736z"/><path d="M28.672 82.56h-11.2l14.784-23.488-14.08-22.592h11.52l8.192 14.976 8.448-14.976h11.136l-14.08 22.208L58.368 82.56H46.656l-8.768-15.68z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.208 16.576v8.384h38.72v5.376h-38.72v8.704h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.576h38.72v5.376h-38.72v8.512h38.72v5.376h-38.72v11.136H128v-94.72H78.208zM0 114.368L72.128 128V0L0 13.632v100.736z"/><path d="M28.672 82.56h-11.2l14.784-23.488-14.08-22.592h11.52l8.192 14.976 8.448-14.976h11.136l-14.08 22.208L58.368 82.56H46.656l-8.768-15.68z"/></svg>
src/icons/svg/exit-fullscreen.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M49.217 41.329l-.136-35.24c-.06-2.715-2.302-4.345-5.022-4.405h-3.65c-2.712-.06-4.866 2.303-4.806 5.016l.152 19.164-24.151-23.79a6.698 6.698 0 0 0-9.499 0 6.76 6.76 0 0 0 0 9.526l23.93 23.713-18.345.074c-2.712-.069-5.228 1.813-5.64 5.02v3.462c.069 2.721 2.31 4.97 5.022 5.03l35.028-.207c.052.005.087.025.133.025l2.457.054a4.626 4.626 0 0 0 3.436-1.38c.88-.874 1.205-2.096 1.169-3.462l-.262-2.465c0-.048.182-.081.182-.136h.002zm52.523 51.212l18.32-.073c2.713.06 5.224-1.609 5.64-4.815v-3.462c-.068-2.722-2.317-4.97-5.021-5.04l-34.58.21c-.053 0-.086-.021-.138-.021l-2.451-.06a4.64 4.64 0 0 0-3.445 1.381c-.885.868-1.201 2.094-1.174 3.46l.27 2.46c.005.06-.177.095-.177.141l.141 34.697c.069 2.713 2.31 4.338 5.022 4.397l3.45.006c2.705.062 4.867-2.31 4.8-5.026l-.153-18.752 24.151 23.946a6.69 6.69 0 0 0 9.494 0 6.747 6.747 0 0 0 0-9.523L101.74 92.54v.001zM48.125 80.662a4.636 4.636 0 0 0-3.437-1.382l-2.457.06c-.05 0-.082.022-.137.022l-35.025-.21c-2.712.07-4.957 2.318-5.022 5.04v3.462c.409 3.206 2.925 4.874 5.633 4.814l18.554.06-24.132 23.928c-2.62 2.626-2.62 6.89 0 9.524a6.694 6.694 0 0 0 9.496 0l24.155-23.79-.155 18.866c-.06 2.722 2.094 5.093 4.801 5.025h3.65c2.72-.069 4.962-1.685 5.022-4.406l.141-34.956c0-.05-.182-.082-.182-.136l.262-2.46c.03-1.366-.286-2.592-1.166-3.46h-.001zM80.08 47.397a4.62 4.62 0 0 0 3.443 1.374l2.45-.054c.055 0 .088-.02.143-.028l35.08.21c2.712-.062 4.953-2.312 5.021-5.033l.009-3.463c-.417-3.211-2.937-5.084-5.64-5.025l-18.615-.073 23.917-23.715c2.63-2.623 2.63-6.879.008-9.513a6.691 6.691 0 0 0-9.494 0L92.251 26.016l.155-19.312c.065-2.713-2.097-5.085-4.802-5.025h-3.45c-2.713.069-4.954 1.693-5.022 4.406l-.139 35.247c0 .054.18.088.18.136l-.267 2.465c-.028 1.366.288 2.588 1.174 3.463v.001z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M49.217 41.329l-.136-35.24c-.06-2.715-2.302-4.345-5.022-4.405h-3.65c-2.712-.06-4.866 2.303-4.806 5.016l.152 19.164-24.151-23.79a6.698 6.698 0 0 0-9.499 0 6.76 6.76 0 0 0 0 9.526l23.93 23.713-18.345.074c-2.712-.069-5.228 1.813-5.64 5.02v3.462c.069 2.721 2.31 4.97 5.022 5.03l35.028-.207c.052.005.087.025.133.025l2.457.054a4.626 4.626 0 0 0 3.436-1.38c.88-.874 1.205-2.096 1.169-3.462l-.262-2.465c0-.048.182-.081.182-.136h.002zm52.523 51.212l18.32-.073c2.713.06 5.224-1.609 5.64-4.815v-3.462c-.068-2.722-2.317-4.97-5.021-5.04l-34.58.21c-.053 0-.086-.021-.138-.021l-2.451-.06a4.64 4.64 0 0 0-3.445 1.381c-.885.868-1.201 2.094-1.174 3.46l.27 2.46c.005.06-.177.095-.177.141l.141 34.697c.069 2.713 2.31 4.338 5.022 4.397l3.45.006c2.705.062 4.867-2.31 4.8-5.026l-.153-18.752 24.151 23.946a6.69 6.69 0 0 0 9.494 0 6.747 6.747 0 0 0 0-9.523L101.74 92.54v.001zM48.125 80.662a4.636 4.636 0 0 0-3.437-1.382l-2.457.06c-.05 0-.082.022-.137.022l-35.025-.21c-2.712.07-4.957 2.318-5.022 5.04v3.462c.409 3.206 2.925 4.874 5.633 4.814l18.554.06-24.132 23.928c-2.62 2.626-2.62 6.89 0 9.524a6.694 6.694 0 0 0 9.496 0l24.155-23.79-.155 18.866c-.06 2.722 2.094 5.093 4.801 5.025h3.65c2.72-.069 4.962-1.685 5.022-4.406l.141-34.956c0-.05-.182-.082-.182-.136l.262-2.46c.03-1.366-.286-2.592-1.166-3.46h-.001zM80.08 47.397a4.62 4.62 0 0 0 3.443 1.374l2.45-.054c.055 0 .088-.02.143-.028l35.08.21c2.712-.062 4.953-2.312 5.021-5.033l.009-3.463c-.417-3.211-2.937-5.084-5.64-5.025l-18.615-.073 23.917-23.715c2.63-2.623 2.63-6.879.008-9.513a6.691 6.691 0 0 0-9.494 0L92.251 26.016l.155-19.312c.065-2.713-2.097-5.085-4.802-5.025h-3.45c-2.713.069-4.954 1.693-5.022 4.406l-.139 35.247c0 .054.18.088.18.136l-.267 2.465c-.028 1.366.288 2.588 1.174 3.463v.001z"/></svg>
src/icons/svg/eye-open.svg 100644 → 100755
1 <svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><defs><style/></defs><path d="M512 128q69.675 0 135.51 21.163t115.498 54.997 93.483 74.837 73.685 82.006 51.67 74.837 32.17 54.827L1024 512q-2.347 4.992-6.315 13.483T998.87 560.17t-31.658 51.669-44.331 59.99-56.832 64.34-69.504 60.16-82.347 51.5-94.848 34.687T512 896q-69.675 0-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0 513.707q2.347-4.992 6.315-13.483t18.816-34.816 31.658-51.84 44.331-60.33 56.832-64.683 69.504-60.331 82.347-51.84 94.848-34.816T512 128.085zm0 85.333q-46.677 0-91.648 12.331t-81.152 31.83-70.656 47.146-59.648 54.485-48.853 57.686-37.675 52.821-26.325 43.99q12.33 21.674 26.325 43.52t37.675 52.351 48.853 57.003 59.648 53.845T339.2 767.02t81.152 31.488T512 810.667t91.648-12.331 81.152-31.659 70.656-46.848 59.648-54.186 48.853-57.344 37.675-52.651T927.957 512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512 213.334zm0 128q70.656 0 120.661 50.006T682.667 512 632.66 632.661 512 682.667 391.339 632.66 341.333 512t50.006-120.661T512 341.333zm0 85.334q-35.328 0-60.33 25.002T426.666 512t25.002 60.33T512 597.334t60.33-25.002T597.334 512t-25.002-60.33T512 426.666z"/></svg> 1 <svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><defs><style/></defs><path d="M512 128q69.675 0 135.51 21.163t115.498 54.997 93.483 74.837 73.685 82.006 51.67 74.837 32.17 54.827L1024 512q-2.347 4.992-6.315 13.483T998.87 560.17t-31.658 51.669-44.331 59.99-56.832 64.34-69.504 60.16-82.347 51.5-94.848 34.687T512 896q-69.675 0-135.51-21.163t-115.498-54.826-93.483-74.326-73.685-81.493-51.67-74.496-32.17-54.997L0 513.707q2.347-4.992 6.315-13.483t18.816-34.816 31.658-51.84 44.331-60.33 56.832-64.683 69.504-60.331 82.347-51.84 94.848-34.816T512 128.085zm0 85.333q-46.677 0-91.648 12.331t-81.152 31.83-70.656 47.146-59.648 54.485-48.853 57.686-37.675 52.821-26.325 43.99q12.33 21.674 26.325 43.52t37.675 52.351 48.853 57.003 59.648 53.845T339.2 767.02t81.152 31.488T512 810.667t91.648-12.331 81.152-31.659 70.656-46.848 59.648-54.186 48.853-57.344 37.675-52.651T927.957 512q-12.33-21.675-26.325-43.648t-37.675-52.65-48.853-57.345-59.648-54.186-70.656-46.848-81.152-31.659T512 213.334zm0 128q70.656 0 120.661 50.006T682.667 512 632.66 632.661 512 682.667 391.339 632.66 341.333 512t50.006-120.661T512 341.333zm0 85.334q-35.328 0-60.33 25.002T426.666 512t25.002 60.33T512 597.334t60.33-25.002T597.334 512t-25.002-60.33T512 426.666z"/></svg>
src/icons/svg/eye.svg 100644 → 100755
1 <svg width="128" height="64" xmlns="http://www.w3.org/2000/svg"><path d="M127.072 7.994c1.37-2.208.914-5.152-.914-6.87-2.056-1.717-4.797-1.226-6.396.982-.229.245-25.586 32.382-55.74 32.382-29.24 0-55.74-32.382-55.968-32.627-1.6-1.963-4.57-2.208-6.397-.49C-.17 3.086-.399 6.275 1.2 8.238c.457.736 5.94 7.36 14.62 14.72L4.17 35.96c-1.828 1.963-1.6 5.152.228 6.87.457.98 1.6 1.471 2.742 1.471s2.284-.49 3.198-1.472l12.564-13.983c5.94 4.416 13.021 8.587 20.788 11.53l-4.797 17.418c-.685 2.699.686 5.397 3.198 6.133h1.37c2.057 0 3.884-1.472 4.341-3.68L52.6 42.83c3.655.736 7.538 1.227 11.422 1.227 3.883 0 7.767-.49 11.422-1.227l4.797 17.173c.457 2.208 2.513 3.68 4.34 3.68.457 0 .914 0 1.143-.246 2.513-.736 3.883-3.434 3.198-6.133l-4.797-17.172c7.767-2.944 14.848-7.114 20.788-11.53l12.336 13.738c.913.981 2.056 1.472 3.198 1.472s2.284-.49 3.198-1.472c1.828-1.963 1.828-4.906.228-6.87l-11.65-13.001c9.366-7.36 14.849-14.474 14.849-14.474z"/></svg> 1 <svg width="128" height="64" xmlns="http://www.w3.org/2000/svg"><path d="M127.072 7.994c1.37-2.208.914-5.152-.914-6.87-2.056-1.717-4.797-1.226-6.396.982-.229.245-25.586 32.382-55.74 32.382-29.24 0-55.74-32.382-55.968-32.627-1.6-1.963-4.57-2.208-6.397-.49C-.17 3.086-.399 6.275 1.2 8.238c.457.736 5.94 7.36 14.62 14.72L4.17 35.96c-1.828 1.963-1.6 5.152.228 6.87.457.98 1.6 1.471 2.742 1.471s2.284-.49 3.198-1.472l12.564-13.983c5.94 4.416 13.021 8.587 20.788 11.53l-4.797 17.418c-.685 2.699.686 5.397 3.198 6.133h1.37c2.057 0 3.884-1.472 4.341-3.68L52.6 42.83c3.655.736 7.538 1.227 11.422 1.227 3.883 0 7.767-.49 11.422-1.227l4.797 17.173c.457 2.208 2.513 3.68 4.34 3.68.457 0 .914 0 1.143-.246 2.513-.736 3.883-3.434 3.198-6.133l-4.797-17.172c7.767-2.944 14.848-7.114 20.788-11.53l12.336 13.738c.913.981 2.056 1.472 3.198 1.472s2.284-.49 3.198-1.472c1.828-1.963 1.828-4.906.228-6.87l-11.65-13.001c9.366-7.36 14.849-14.474 14.849-14.474z"/></svg>
src/icons/svg/form.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.068 23.784c-1.02 0-1.877-.32-2.572-.96a8.588 8.588 0 0 1-1.738-2.237 11.524 11.524 0 0 1-1.042-2.621c-.232-.895-.348-1.641-.348-2.238V0h.278c.834 0 1.622.085 2.363.256.742.17 1.645.575 2.711 1.214 1.066.64 2.363 1.535 3.892 2.686 1.53 1.15 3.453 2.664 5.77 4.54 2.502 2.045 4.494 3.771 5.977 5.178 1.483 1.406 2.618 2.6 3.406 3.58.787.98 1.274 1.812 1.46 2.494.185.682.277 1.278.277 1.79v2.046H84.068zM127.3 84.01c.278.682.464 1.535.556 2.558.093 1.023-.37 2.003-1.39 2.94-.463.427-.88.832-1.25 1.215-.372.384-.696.704-.974.96a6.69 6.69 0 0 1-.973.767l-11.816-10.741a44.331 44.331 0 0 0 1.877-1.535 31.028 31.028 0 0 1 1.737-1.406c1.112-.938 2.317-1.343 3.615-1.215 1.297.128 2.363.405 3.197.83.927.427 1.923 1.173 2.989 2.239 1.065 1.065 1.876 2.195 2.432 3.388zM78.23 95.902c2.038 0 3.752-.511 5.143-1.534l-26.969 25.83H18.037c-1.761 0-3.684-.47-5.77-1.407a24.549 24.549 0 0 1-5.838-3.709 21.373 21.373 0 0 1-4.518-5.306c-1.204-2.003-1.807-4.07-1.807-6.202V16.495c0-1.79.44-3.665 1.32-5.626A18.41 18.41 0 0 1 5.04 5.562a21.798 21.798 0 0 1 5.213-3.964C12.198.533 14.237 0 16.37 0h53.24v15.984c0 1.62.278 3.367.834 5.242a16.704 16.704 0 0 0 2.572 5.179c1.159 1.577 2.665 2.898 4.518 3.964 1.853 1.066 4.078 1.598 6.673 1.598h20.295v42.325L85.458 92.45c1.02-1.364 1.529-2.856 1.529-4.476 0-2.216-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1c-2.409 0-4.448.789-6.116 2.366-1.668 1.577-2.502 3.474-2.502 5.69 0 2.217.834 4.092 2.502 5.626 1.668 1.535 3.707 2.302 6.117 2.302h52.13zM26.1 47.951c-2.41 0-4.449.789-6.117 2.366-1.668 1.577-2.502 3.473-2.502 5.69 0 2.216.834 4.092 2.502 5.626 1.668 1.534 3.707 2.302 6.117 2.302h52.13c2.409 0 4.47-.768 6.185-2.302 1.715-1.534 2.572-3.41 2.572-5.626 0-2.217-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1zm52.407 64.063l1.807-1.663 3.476-3.196a479.75 479.75 0 0 0 4.587-4.284 500.757 500.757 0 0 1 5.004-4.667c3.985-3.666 8.48-7.758 13.485-12.276l11.677 10.741-13.485 12.404-5.004 4.603-4.587 4.22a179.46 179.46 0 0 0-3.267 3.068c-.88.853-1.367 1.322-1.46 1.407-.463.341-.973.703-1.529 1.087-.556.383-1.112.703-1.668.959-.556.256-1.413.575-2.572.959a83.5 83.5 0 0 1-3.545 1.087 72.2 72.2 0 0 1-3.475.895c-1.112.256-1.946.426-2.502.511-1.112.17-1.854.043-2.224-.383-.371-.426-.464-1.151-.278-2.174.092-.511.278-1.279.556-2.302.278-1.023.602-2.067.973-3.132l1.042-3.005c.325-.938.58-1.577.765-1.918a10.157 10.157 0 0 1 2.224-2.941z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.068 23.784c-1.02 0-1.877-.32-2.572-.96a8.588 8.588 0 0 1-1.738-2.237 11.524 11.524 0 0 1-1.042-2.621c-.232-.895-.348-1.641-.348-2.238V0h.278c.834 0 1.622.085 2.363.256.742.17 1.645.575 2.711 1.214 1.066.64 2.363 1.535 3.892 2.686 1.53 1.15 3.453 2.664 5.77 4.54 2.502 2.045 4.494 3.771 5.977 5.178 1.483 1.406 2.618 2.6 3.406 3.58.787.98 1.274 1.812 1.46 2.494.185.682.277 1.278.277 1.79v2.046H84.068zM127.3 84.01c.278.682.464 1.535.556 2.558.093 1.023-.37 2.003-1.39 2.94-.463.427-.88.832-1.25 1.215-.372.384-.696.704-.974.96a6.69 6.69 0 0 1-.973.767l-11.816-10.741a44.331 44.331 0 0 0 1.877-1.535 31.028 31.028 0 0 1 1.737-1.406c1.112-.938 2.317-1.343 3.615-1.215 1.297.128 2.363.405 3.197.83.927.427 1.923 1.173 2.989 2.239 1.065 1.065 1.876 2.195 2.432 3.388zM78.23 95.902c2.038 0 3.752-.511 5.143-1.534l-26.969 25.83H18.037c-1.761 0-3.684-.47-5.77-1.407a24.549 24.549 0 0 1-5.838-3.709 21.373 21.373 0 0 1-4.518-5.306c-1.204-2.003-1.807-4.07-1.807-6.202V16.495c0-1.79.44-3.665 1.32-5.626A18.41 18.41 0 0 1 5.04 5.562a21.798 21.798 0 0 1 5.213-3.964C12.198.533 14.237 0 16.37 0h53.24v15.984c0 1.62.278 3.367.834 5.242a16.704 16.704 0 0 0 2.572 5.179c1.159 1.577 2.665 2.898 4.518 3.964 1.853 1.066 4.078 1.598 6.673 1.598h20.295v42.325L85.458 92.45c1.02-1.364 1.529-2.856 1.529-4.476 0-2.216-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1c-2.409 0-4.448.789-6.116 2.366-1.668 1.577-2.502 3.474-2.502 5.69 0 2.217.834 4.092 2.502 5.626 1.668 1.535 3.707 2.302 6.117 2.302h52.13zM26.1 47.951c-2.41 0-4.449.789-6.117 2.366-1.668 1.577-2.502 3.473-2.502 5.69 0 2.216.834 4.092 2.502 5.626 1.668 1.534 3.707 2.302 6.117 2.302h52.13c2.409 0 4.47-.768 6.185-2.302 1.715-1.534 2.572-3.41 2.572-5.626 0-2.217-.857-4.113-2.572-5.69-1.714-1.577-3.776-2.366-6.186-2.366H26.1zm52.407 64.063l1.807-1.663 3.476-3.196a479.75 479.75 0 0 0 4.587-4.284 500.757 500.757 0 0 1 5.004-4.667c3.985-3.666 8.48-7.758 13.485-12.276l11.677 10.741-13.485 12.404-5.004 4.603-4.587 4.22a179.46 179.46 0 0 0-3.267 3.068c-.88.853-1.367 1.322-1.46 1.407-.463.341-.973.703-1.529 1.087-.556.383-1.112.703-1.668.959-.556.256-1.413.575-2.572.959a83.5 83.5 0 0 1-3.545 1.087 72.2 72.2 0 0 1-3.475.895c-1.112.256-1.946.426-2.502.511-1.112.17-1.854.043-2.224-.383-.371-.426-.464-1.151-.278-2.174.092-.511.278-1.279.556-2.302.278-1.023.602-2.067.973-3.132l1.042-3.005c.325-.938.58-1.577.765-1.918a10.157 10.157 0 0 1 2.224-2.941z"/></svg>
src/icons/svg/fullscreen.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M38.47 52L52 38.462l-23.648-23.67L43.209 0H.035L0 43.137l14.757-14.865L38.47 52zm74.773 47.726L89.526 76 76 89.536l23.648 23.672L84.795 128h43.174L128 84.863l-14.757 14.863zM89.538 52l23.668-23.648L128 43.207V.038L84.866 0 99.73 14.76 76 38.472 89.538 52zM38.46 76L14.792 99.651 0 84.794v43.173l43.137.033-14.865-14.757L52 89.53 38.46 76z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M38.47 52L52 38.462l-23.648-23.67L43.209 0H.035L0 43.137l14.757-14.865L38.47 52zm74.773 47.726L89.526 76 76 89.536l23.648 23.672L84.795 128h43.174L128 84.863l-14.757 14.863zM89.538 52l23.668-23.648L128 43.207V.038L84.866 0 99.73 14.76 76 38.472 89.538 52zM38.46 76L14.792 99.651 0 84.794v43.173l43.137.033-14.865-14.757L52 89.53 38.46 76z"/></svg>
src/icons/svg/guide.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M1.482 70.131l36.204 16.18 69.932-65.485-61.38 70.594 46.435 18.735c1.119.425 2.397-.17 2.797-1.363v-.085L127.998.047 1.322 65.874c-1.12.597-1.519 1.959-1.04 3.151.32.511.72.937 1.2 1.107zm44.676 57.821L64.22 107.26l-18.062-7.834v28.527z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M1.482 70.131l36.204 16.18 69.932-65.485-61.38 70.594 46.435 18.735c1.119.425 2.397-.17 2.797-1.363v-.085L127.998.047 1.322 65.874c-1.12.597-1.519 1.959-1.04 3.151.32.511.72.937 1.2 1.107zm44.676 57.821L64.22 107.26l-18.062-7.834v28.527z"/></svg>
src/icons/svg/icon.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.147.062a13 13 0 0 1 4.94.945c1.55.63 2.907 1.526 4.069 2.688a13.148 13.148 0 0 1 2.761 4.069c.678 1.55 1.017 3.245 1.017 5.086v102.3c0 3.681-1.187 6.733-3.56 9.155-2.373 2.422-5.352 3.633-8.937 3.633H12.992c-3.875 0-7-1.26-9.373-3.779-2.373-2.518-3.56-5.667-3.56-9.445V12.704c0-3.39 1.163-6.345 3.488-8.863C5.872 1.32 8.972.062 12.847.062h102.3zM81.434 109.047c1.744 0 3.003-.412 3.778-1.235.775-.824 1.163-1.914 1.163-3.27 0-1.26-.388-2.325-1.163-3.197-.775-.872-2.034-1.307-3.778-1.307H72.57c.097-.194.145-.485.145-.872V27.09h9.01c1.743 0 2.954-.436 3.633-1.308.678-.872 1.017-1.938 1.017-3.197 0-1.26-.34-2.325-1.017-3.197-.679-.872-1.89-1.308-3.633-1.308H46.268c-1.743 0-2.954.436-3.632 1.308-.678.872-1.018 1.938-1.018 3.197 0 1.26.34 2.325 1.018 3.197.678.872 1.889 1.308 3.632 1.308h8.138v72.075c0 .193.024.339.073.436.048.096.072.242.072.436H46.56c-1.744 0-3.003.435-3.778 1.307-.775.872-1.163 1.938-1.163 3.197 0 1.356.388 2.446 1.163 3.27.775.823 2.034 1.235 3.778 1.235h34.875z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.147.062a13 13 0 0 1 4.94.945c1.55.63 2.907 1.526 4.069 2.688a13.148 13.148 0 0 1 2.761 4.069c.678 1.55 1.017 3.245 1.017 5.086v102.3c0 3.681-1.187 6.733-3.56 9.155-2.373 2.422-5.352 3.633-8.937 3.633H12.992c-3.875 0-7-1.26-9.373-3.779-2.373-2.518-3.56-5.667-3.56-9.445V12.704c0-3.39 1.163-6.345 3.488-8.863C5.872 1.32 8.972.062 12.847.062h102.3zM81.434 109.047c1.744 0 3.003-.412 3.778-1.235.775-.824 1.163-1.914 1.163-3.27 0-1.26-.388-2.325-1.163-3.197-.775-.872-2.034-1.307-3.778-1.307H72.57c.097-.194.145-.485.145-.872V27.09h9.01c1.743 0 2.954-.436 3.633-1.308.678-.872 1.017-1.938 1.017-3.197 0-1.26-.34-2.325-1.017-3.197-.679-.872-1.89-1.308-3.633-1.308H46.268c-1.743 0-2.954.436-3.632 1.308-.678.872-1.018 1.938-1.018 3.197 0 1.26.34 2.325 1.018 3.197.678.872 1.889 1.308 3.632 1.308h8.138v72.075c0 .193.024.339.073.436.048.096.072.242.072.436H46.56c-1.744 0-3.003.435-3.778 1.307-.775.872-1.163 1.938-1.163 3.197 0 1.356.388 2.446 1.163 3.27.775.823 2.034 1.235 3.778 1.235h34.875z"/></svg>
src/icons/svg/international.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M83.287 103.01c-1.57-3.84-6.778-10.414-15.447-19.548-2.327-2.444-2.182-4.306-1.338-9.862v-.64c.553-3.81 1.513-6.05 14.313-8.087 6.516-1.018 8.203 1.57 10.589 5.178l.785 1.193a12.625 12.625 0 0 0 6.43 5.207c1.134.524 2.53 1.164 4.421 2.24 4.596 2.53 4.596 5.41 4.596 11.753v.727a26.91 26.91 0 0 1-5.178 17.454 59.055 59.055 0 0 1-19.025 11.026c3.49-6.546.814-14.313 0-16.553l-.146-.087zM64 5.12a58.502 58.502 0 0 1 25.484 5.818 54.313 54.313 0 0 0-12.859 10.327c-.93 1.28-1.716 2.473-2.472 3.579-2.444 3.694-3.637 5.352-5.818 5.614a25.105 25.105 0 0 1-4.219 0c-4.276-.29-10.094-.64-11.956 4.422-1.193 3.23-1.396 11.956 2.444 16.495.66 1.077.778 2.4.32 3.578a7.01 7.01 0 0 1-2.066 3.229 18.938 18.938 0 0 1-2.909-2.91 18.91 18.91 0 0 0-8.32-6.603c-1.25-.349-2.647-.64-3.985-.93-3.782-.786-8.03-1.688-9.019-3.812a14.895 14.895 0 0 1-.727-5.818 21.935 21.935 0 0 0-1.396-9.25 8.873 8.873 0 0 0-5.557-4.946A58.705 58.705 0 0 1 64 5.12zM0 64c0 35.346 28.654 64 64 64 35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M83.287 103.01c-1.57-3.84-6.778-10.414-15.447-19.548-2.327-2.444-2.182-4.306-1.338-9.862v-.64c.553-3.81 1.513-6.05 14.313-8.087 6.516-1.018 8.203 1.57 10.589 5.178l.785 1.193a12.625 12.625 0 0 0 6.43 5.207c1.134.524 2.53 1.164 4.421 2.24 4.596 2.53 4.596 5.41 4.596 11.753v.727a26.91 26.91 0 0 1-5.178 17.454 59.055 59.055 0 0 1-19.025 11.026c3.49-6.546.814-14.313 0-16.553l-.146-.087zM64 5.12a58.502 58.502 0 0 1 25.484 5.818 54.313 54.313 0 0 0-12.859 10.327c-.93 1.28-1.716 2.473-2.472 3.579-2.444 3.694-3.637 5.352-5.818 5.614a25.105 25.105 0 0 1-4.219 0c-4.276-.29-10.094-.64-11.956 4.422-1.193 3.23-1.396 11.956 2.444 16.495.66 1.077.778 2.4.32 3.578a7.01 7.01 0 0 1-2.066 3.229 18.938 18.938 0 0 1-2.909-2.91 18.91 18.91 0 0 0-8.32-6.603c-1.25-.349-2.647-.64-3.985-.93-3.782-.786-8.03-1.688-9.019-3.812a14.895 14.895 0 0 1-.727-5.818 21.935 21.935 0 0 0-1.396-9.25 8.873 8.873 0 0 0-5.557-4.946A58.705 58.705 0 0 1 64 5.12zM0 64c0 35.346 28.654 64 64 64 35.346 0 64-28.654 64-64 0-35.346-28.654-64-64-64C28.654 0 0 28.654 0 64z"/></svg>
src/icons/svg/language.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.742 36.8c2.398 7.2 5.595 12.8 11.19 18.4 4.795-4.8 7.992-11.2 10.39-18.4h-21.58zm-52.748 40h20.78l-10.39-28-10.39 28z"/><path d="M111.916 0H16.009C7.218 0 .025 7.2.025 16v96c0 8.8 7.193 16 15.984 16h95.907c8.791 0 15.984-7.2 15.984-16V16c0-8.8-6.394-16-15.984-16zM72.754 103.2c-1.598 1.6-3.197 1.6-4.795 1.6-.8 0-2.398 0-3.197-.8-.8-.8-1.599 0-1.599-.8s-.799-1.6-1.598-3.2c-.8-1.6-.8-2.4-1.599-4l-3.196-8.8H28.797L25.6 96c-1.598 3.2-2.398 5.6-3.197 7.2-.8 1.6-2.398 1.6-4.795 1.6-1.599 0-3.197-.8-4.796-1.6-1.598-1.6-2.397-2.4-2.397-4 0-.8 0-1.6.799-3.2.8-1.6.8-2.4 1.598-4l17.583-44.8c.8-1.6.8-3.2 1.599-4.8.799-1.6 1.598-3.2 2.397-4 .8-.8 1.599-2.4 3.197-3.2 1.599-.8 3.197-.8 4.796-.8 1.598 0 3.196 0 4.795.8 1.598.8 2.398 1.6 3.197 3.2.799.8 1.598 2.4 2.397 4 .8 1.6 1.599 3.2 2.398 5.6l17.583 44c1.598 3.2 2.398 5.6 2.398 7.2-.8.8-1.599 2.4-2.398 4zM116.711 72c-8.791-3.2-15.185-7.2-20.78-12-5.594 5.6-12.787 9.6-21.579 12l-2.397-4c8.791-2.4 15.984-5.6 21.579-11.2C87.939 51.2 83.144 44 81.545 36h-7.992v-3.2h21.58c-1.6-2.4-3.198-5.6-4.796-8l2.397-.8c1.599 2.4 3.997 5.6 5.595 8.8h19.98v4h-7.992c-2.397 8-6.393 15.2-11.189 20 5.595 4.8 11.988 8.8 20.78 11.2l-3.197 4z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M84.742 36.8c2.398 7.2 5.595 12.8 11.19 18.4 4.795-4.8 7.992-11.2 10.39-18.4h-21.58zm-52.748 40h20.78l-10.39-28-10.39 28z"/><path d="M111.916 0H16.009C7.218 0 .025 7.2.025 16v96c0 8.8 7.193 16 15.984 16h95.907c8.791 0 15.984-7.2 15.984-16V16c0-8.8-6.394-16-15.984-16zM72.754 103.2c-1.598 1.6-3.197 1.6-4.795 1.6-.8 0-2.398 0-3.197-.8-.8-.8-1.599 0-1.599-.8s-.799-1.6-1.598-3.2c-.8-1.6-.8-2.4-1.599-4l-3.196-8.8H28.797L25.6 96c-1.598 3.2-2.398 5.6-3.197 7.2-.8 1.6-2.398 1.6-4.795 1.6-1.599 0-3.197-.8-4.796-1.6-1.598-1.6-2.397-2.4-2.397-4 0-.8 0-1.6.799-3.2.8-1.6.8-2.4 1.598-4l17.583-44.8c.8-1.6.8-3.2 1.599-4.8.799-1.6 1.598-3.2 2.397-4 .8-.8 1.599-2.4 3.197-3.2 1.599-.8 3.197-.8 4.796-.8 1.598 0 3.196 0 4.795.8 1.598.8 2.398 1.6 3.197 3.2.799.8 1.598 2.4 2.397 4 .8 1.6 1.599 3.2 2.398 5.6l17.583 44c1.598 3.2 2.398 5.6 2.398 7.2-.8.8-1.599 2.4-2.398 4zM116.711 72c-8.791-3.2-15.185-7.2-20.78-12-5.594 5.6-12.787 9.6-21.579 12l-2.397-4c8.791-2.4 15.984-5.6 21.579-11.2C87.939 51.2 83.144 44 81.545 36h-7.992v-3.2h21.58c-1.6-2.4-3.198-5.6-4.796-8l2.397-.8c1.599 2.4 3.997 5.6 5.595 8.8h19.98v4h-7.992c-2.397 8-6.393 15.2-11.189 20 5.595 4.8 11.988 8.8 20.78 11.2l-3.197 4z"/></svg>
src/icons/svg/link.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.625 127.937H.063V12.375h57.781v12.374H12.438v90.813h90.813V70.156h12.374z"/><path d="M116.426 2.821l8.753 8.753-56.734 56.734-8.753-8.745z"/><path d="M127.893 37.982h-12.375V12.375H88.706V0h39.187z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M115.625 127.937H.063V12.375h57.781v12.374H12.438v90.813h90.813V70.156h12.374z"/><path d="M116.426 2.821l8.753 8.753-56.734 56.734-8.753-8.745z"/><path d="M127.893 37.982h-12.375V12.375H88.706V0h39.187z"/></svg>
src/icons/svg/list.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M1.585 12.087c0 6.616 3.974 11.98 8.877 11.98 4.902 0 8.877-5.364 8.877-11.98 0-6.616-3.975-11.98-8.877-11.98-4.903 0-8.877 5.364-8.877 11.98zM125.86.107H35.613c-1.268 0-2.114 1.426-2.114 2.852v18.255c0 1.712 1.057 2.853 2.114 2.853h90.247c1.268 0 2.114-1.426 2.114-2.853V2.96c0-1.711-1.057-2.852-2.114-2.852zM.106 62.86c0 6.615 3.974 11.979 8.876 11.979 4.903 0 8.877-5.364 8.877-11.98 0-6.616-3.974-11.98-8.877-11.98-4.902 0-8.876 5.364-8.876 11.98zM124.17 50.88H33.921c-1.268 0-2.114 1.425-2.114 2.851v18.256c0 1.711 1.057 2.852 2.114 2.852h90.247c1.268 0 2.114-1.426 2.114-2.852V53.73c0-1.426-.846-2.852-2.114-2.852zM.106 115.913c0 6.616 3.974 11.98 8.876 11.98 4.903 0 8.877-5.364 8.877-11.98 0-6.616-3.974-11.98-8.877-11.98-4.902 0-8.876 5.364-8.876 11.98zm124.064-11.98H33.921c-1.268 0-2.114 1.426-2.114 2.853v18.255c0 1.711 1.057 2.852 2.114 2.852h90.247c1.268 0 2.114-1.426 2.114-2.852v-18.255c0-1.427-.846-2.853-2.114-2.853z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M1.585 12.087c0 6.616 3.974 11.98 8.877 11.98 4.902 0 8.877-5.364 8.877-11.98 0-6.616-3.975-11.98-8.877-11.98-4.903 0-8.877 5.364-8.877 11.98zM125.86.107H35.613c-1.268 0-2.114 1.426-2.114 2.852v18.255c0 1.712 1.057 2.853 2.114 2.853h90.247c1.268 0 2.114-1.426 2.114-2.853V2.96c0-1.711-1.057-2.852-2.114-2.852zM.106 62.86c0 6.615 3.974 11.979 8.876 11.979 4.903 0 8.877-5.364 8.877-11.98 0-6.616-3.974-11.98-8.877-11.98-4.902 0-8.876 5.364-8.876 11.98zM124.17 50.88H33.921c-1.268 0-2.114 1.425-2.114 2.851v18.256c0 1.711 1.057 2.852 2.114 2.852h90.247c1.268 0 2.114-1.426 2.114-2.852V53.73c0-1.426-.846-2.852-2.114-2.852zM.106 115.913c0 6.616 3.974 11.98 8.876 11.98 4.903 0 8.877-5.364 8.877-11.98 0-6.616-3.974-11.98-8.877-11.98-4.902 0-8.876 5.364-8.876 11.98zm124.064-11.98H33.921c-1.268 0-2.114 1.426-2.114 2.853v18.255c0 1.711 1.057 2.852 2.114 2.852h90.247c1.268 0 2.114-1.426 2.114-2.852v-18.255c0-1.427-.846-2.853-2.114-2.853z"/></svg>
src/icons/svg/lock.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M119.88 49.674h-7.987V39.52C111.893 17.738 90.45.08 63.996.08 37.543.08 16.1 17.738 16.1 39.52v10.154H8.113c-4.408 0-7.987 2.94-7.987 6.577v65.13c0 3.637 3.57 6.577 7.987 6.577H119.88c4.407 0 7.987-2.94 7.987-6.577v-65.13c-.008-3.636-3.58-6.577-7.987-6.577zm-23.953 0H32.065V39.52c0-14.524 14.301-26.295 31.931-26.295 17.63 0 31.932 11.777 31.932 26.295v10.153z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M119.88 49.674h-7.987V39.52C111.893 17.738 90.45.08 63.996.08 37.543.08 16.1 17.738 16.1 39.52v10.154H8.113c-4.408 0-7.987 2.94-7.987 6.577v65.13c0 3.637 3.57 6.577 7.987 6.577H119.88c4.407 0 7.987-2.94 7.987-6.577v-65.13c-.008-3.636-3.58-6.577-7.987-6.577zm-23.953 0H32.065V39.52c0-14.524 14.301-26.295 31.931-26.295 17.63 0 31.932 11.777 31.932 26.295v10.153z"/></svg>
src/icons/svg/message.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 20.967v59.59c0 11.59 8.537 20.966 19.075 20.966h28.613l1 26.477L76.8 101.523h32.125c10.538 0 19.075-9.377 19.075-20.966v-59.59C128 9.377 119.463 0 108.925 0h-89.85C8.538 0 0 9.377 0 20.967zm82.325 33.1c0-5.524 4.013-9.935 9.037-9.935 5.026 0 9.038 4.41 9.038 9.934 0 5.524-4.025 9.934-9.038 9.934-5.024 0-9.037-4.41-9.037-9.934zm-27.613 0c0-5.524 4.013-9.935 9.038-9.935s9.037 4.41 9.037 9.934c0 5.524-4.025 9.934-9.037 9.934-5.025 0-9.038-4.41-9.038-9.934zm-27.1 0c0-5.524 4.013-9.935 9.038-9.935s9.038 4.41 9.038 9.934c0 5.524-4.026 9.934-9.05 9.934-5.013 0-9.025-4.41-9.025-9.934z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 20.967v59.59c0 11.59 8.537 20.966 19.075 20.966h28.613l1 26.477L76.8 101.523h32.125c10.538 0 19.075-9.377 19.075-20.966v-59.59C128 9.377 119.463 0 108.925 0h-89.85C8.538 0 0 9.377 0 20.967zm82.325 33.1c0-5.524 4.013-9.935 9.037-9.935 5.026 0 9.038 4.41 9.038 9.934 0 5.524-4.025 9.934-9.038 9.934-5.024 0-9.037-4.41-9.037-9.934zm-27.613 0c0-5.524 4.013-9.935 9.038-9.935s9.037 4.41 9.037 9.934c0 5.524-4.025 9.934-9.037 9.934-5.025 0-9.038-4.41-9.038-9.934zm-27.1 0c0-5.524 4.013-9.935 9.038-9.935s9.038 4.41 9.038 9.934c0 5.524-4.026 9.934-9.05 9.934-5.013 0-9.025-4.41-9.025-9.934z"/></svg>
src/icons/svg/money.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.122 127.892v-28.68H7.513V87.274h46.609v-12.4H7.513v-12.86h38.003L.099 0h22.6l32.556 45.07c3.617 5.144 6.44 9.611 8.487 13.385 1.788-3.05 4.89-7.779 9.301-14.186L103.93 0h24.01L82.385 62.013h38.34v12.862h-46.41v12.4h46.41v11.937h-46.41v28.68H54.123z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M54.122 127.892v-28.68H7.513V87.274h46.609v-12.4H7.513v-12.86h38.003L.099 0h22.6l32.556 45.07c3.617 5.144 6.44 9.611 8.487 13.385 1.788-3.05 4.89-7.779 9.301-14.186L103.93 0h24.01L82.385 62.013h38.34v12.862h-46.41v12.4h46.41v11.937h-46.41v28.68H54.123z"/></svg>
src/icons/svg/nested.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.002 9.2c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-5.043-3.58-9.132-7.997-9.132S.002 4.157.002 9.2zM31.997.066h95.981V18.33H31.997V.066zm0 45.669c0 5.044 3.58 9.132 7.998 9.132 4.417 0 7.997-4.088 7.997-9.132 0-3.263-1.524-6.278-3.998-7.91-2.475-1.63-5.524-1.63-7.998 0-2.475 1.632-4 4.647-4 7.91zM63.992 36.6h63.986v18.265H63.992V36.6zm-31.995 82.2c0 5.043 3.58 9.132 7.998 9.132 4.417 0 7.997-4.089 7.997-9.132 0-5.044-3.58-9.133-7.997-9.133s-7.998 4.089-7.998 9.133zm31.995-9.131h63.986v18.265H63.992V109.67zm0-27.404c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-3.263-1.524-6.277-3.998-7.909-2.475-1.631-5.524-1.631-7.998 0-2.475 1.632-4 4.646-4 7.91zm31.995-9.13h31.991V91.4H95.987V73.135z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.002 9.2c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-5.043-3.58-9.132-7.997-9.132S.002 4.157.002 9.2zM31.997.066h95.981V18.33H31.997V.066zm0 45.669c0 5.044 3.58 9.132 7.998 9.132 4.417 0 7.997-4.088 7.997-9.132 0-3.263-1.524-6.278-3.998-7.91-2.475-1.63-5.524-1.63-7.998 0-2.475 1.632-4 4.647-4 7.91zM63.992 36.6h63.986v18.265H63.992V36.6zm-31.995 82.2c0 5.043 3.58 9.132 7.998 9.132 4.417 0 7.997-4.089 7.997-9.132 0-5.044-3.58-9.133-7.997-9.133s-7.998 4.089-7.998 9.133zm31.995-9.131h63.986v18.265H63.992V109.67zm0-27.404c0 5.044 3.58 9.133 7.998 9.133 4.417 0 7.997-4.089 7.997-9.133 0-3.263-1.524-6.277-3.998-7.909-2.475-1.631-5.524-1.631-7.998 0-2.475 1.632-4 4.646-4 7.91zm31.995-9.13h31.991V91.4H95.987V73.135z"/></svg>
src/icons/svg/password.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M108.8 44.322H89.6v-5.36c0-9.04-3.308-24.163-25.6-24.163-23.145 0-25.6 16.881-25.6 24.162v5.361H19.2v-5.36C19.2 15.281 36.798 0 64 0c27.202 0 44.8 15.281 44.8 38.961v5.361zm-32 39.356c0-5.44-5.763-9.832-12.8-9.832-7.037 0-12.8 4.392-12.8 9.832 0 3.682 2.567 6.808 6.407 8.477v11.205c0 2.718 2.875 4.962 6.4 4.962 3.524 0 6.4-2.244 6.4-4.962V92.155c3.833-1.669 6.393-4.795 6.393-8.477zM128 64v49.201c0 8.158-8.645 14.799-19.2 14.799H19.2C8.651 128 0 121.359 0 113.201V64c0-8.153 8.645-14.799 19.2-14.799h89.6c10.555 0 19.2 6.646 19.2 14.799z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M108.8 44.322H89.6v-5.36c0-9.04-3.308-24.163-25.6-24.163-23.145 0-25.6 16.881-25.6 24.162v5.361H19.2v-5.36C19.2 15.281 36.798 0 64 0c27.202 0 44.8 15.281 44.8 38.961v5.361zm-32 39.356c0-5.44-5.763-9.832-12.8-9.832-7.037 0-12.8 4.392-12.8 9.832 0 3.682 2.567 6.808 6.407 8.477v11.205c0 2.718 2.875 4.962 6.4 4.962 3.524 0 6.4-2.244 6.4-4.962V92.155c3.833-1.669 6.393-4.795 6.393-8.477zM128 64v49.201c0 8.158-8.645 14.799-19.2 14.799H19.2C8.651 128 0 121.359 0 113.201V64c0-8.153 8.645-14.799 19.2-14.799h89.6c10.555 0 19.2 6.646 19.2 14.799z"/></svg>
src/icons/svg/pdf.svg 100644 → 100755
1 <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="M869.073 277.307H657.111V65.344l211.962 211.963zm-238.232 26.27V65.344l-476.498-.054v416.957h714.73v-178.67H630.841zm-335.836 360.57c-5.07-3.064-10.944-5.133-17.61-6.201-6.67-1.064-13.603-1.6-20.81-1.6h-48.821v85.641h48.822c7.206 0 14.14-.532 20.81-1.6 6.665-1.065 12.54-3.133 17.609-6.202 5.064-3.063 9.134-7.406 12.208-13.007 3.065-5.602 4.6-12.937 4.6-22.011 0-9.07-1.535-16.408-4.6-22.01-3.074-5.603-7.144-9.94-12.208-13.01zM35.82 541.805v416.904h952.358V541.805H35.821zm331.421 191.179c-3.6 11.071-9.343 20.879-17.209 29.413-7.874 8.542-18.078 15.408-30.617 20.61-12.544 5.206-27.747 7.807-45.621 7.807h-66.036v102.45h-62.831V607.517h128.867c17.874 0 33.077 2.6 45.62 7.802 12.541 5.207 22.745 12.076 30.618 20.615 7.866 8.538 13.604 18.277 17.21 29.212 3.6 10.943 5.401 22.278 5.401 34.018 0 11.477-1.8 22.752-5.402 33.819zM644.9 806.417c-5.343 17.61-13.408 32.818-24.212 45.627-10.807 12.803-24.283 22.879-40.423 30.213-16.146 7.343-35.155 11.007-57.03 11.007h-123.26V607.518h123.26c18.41 0 35.552 2.941 51.428 8.808 15.873 5.869 29.618 14.671 41.22 26.412 11.608 11.744 20.674 26.411 27.217 44.02 6.535 17.61 9.803 38.288 9.803 62.035 0 20.81-2.67 40.02-8.003 57.624zm245.362-146.07h-138.07v66.03h119.66v48.829h-119.66v118.058h-62.83V607.518h200.9v52.829h-.001zm-318.2 25.611c-6.402-8.266-14.877-14.604-25.412-19.01-10.544-4.402-23.551-6.602-39.019-6.602h-44.825v180.088h56.029c9.07 0 17.872-1.463 26.415-4.401 8.535-2.932 16.14-7.802 22.812-14.609 6.665-6.8 12.007-15.667 16.007-26.61 4.003-10.94 6.003-24.275 6.003-40.021 0-14.408-1.4-27.416-4.202-39.019-2.8-11.607-7.406-21.542-13.808-29.816zm0 0"/></svg> 1 <svg viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="128" height="128"><path d="M869.073 277.307H657.111V65.344l211.962 211.963zm-238.232 26.27V65.344l-476.498-.054v416.957h714.73v-178.67H630.841zm-335.836 360.57c-5.07-3.064-10.944-5.133-17.61-6.201-6.67-1.064-13.603-1.6-20.81-1.6h-48.821v85.641h48.822c7.206 0 14.14-.532 20.81-1.6 6.665-1.065 12.54-3.133 17.609-6.202 5.064-3.063 9.134-7.406 12.208-13.007 3.065-5.602 4.6-12.937 4.6-22.011 0-9.07-1.535-16.408-4.6-22.01-3.074-5.603-7.144-9.94-12.208-13.01zM35.82 541.805v416.904h952.358V541.805H35.821zm331.421 191.179c-3.6 11.071-9.343 20.879-17.209 29.413-7.874 8.542-18.078 15.408-30.617 20.61-12.544 5.206-27.747 7.807-45.621 7.807h-66.036v102.45h-62.831V607.517h128.867c17.874 0 33.077 2.6 45.62 7.802 12.541 5.207 22.745 12.076 30.618 20.615 7.866 8.538 13.604 18.277 17.21 29.212 3.6 10.943 5.401 22.278 5.401 34.018 0 11.477-1.8 22.752-5.402 33.819zM644.9 806.417c-5.343 17.61-13.408 32.818-24.212 45.627-10.807 12.803-24.283 22.879-40.423 30.213-16.146 7.343-35.155 11.007-57.03 11.007h-123.26V607.518h123.26c18.41 0 35.552 2.941 51.428 8.808 15.873 5.869 29.618 14.671 41.22 26.412 11.608 11.744 20.674 26.411 27.217 44.02 6.535 17.61 9.803 38.288 9.803 62.035 0 20.81-2.67 40.02-8.003 57.624zm245.362-146.07h-138.07v66.03h119.66v48.829h-119.66v118.058h-62.83V607.518h200.9v52.829h-.001zm-318.2 25.611c-6.402-8.266-14.877-14.604-25.412-19.01-10.544-4.402-23.551-6.602-39.019-6.602h-44.825v180.088h56.029c9.07 0 17.872-1.463 26.415-4.401 8.535-2.932 16.14-7.802 22.812-14.609 6.665-6.8 12.007-15.667 16.007-26.61 4.003-10.94 6.003-24.275 6.003-40.021 0-14.408-1.4-27.416-4.202-39.019-2.8-11.607-7.406-21.542-13.808-29.816zm0 0"/></svg>
src/icons/svg/people.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M104.185 95.254c8.161 7.574 13.145 17.441 13.145 28.28 0 1.508-.098 2.998-.285 4.466h-10.784c.238-1.465.403-2.948.403-4.465 0-8.983-4.36-17.115-11.419-23.216C86 104.66 75.355 107.162 64 107.162c-11.344 0-21.98-2.495-31.22-6.83-7.064 6.099-11.444 14.218-11.444 23.203 0 1.517.165 3 .403 4.465H10.955a35.444 35.444 0 0 1-.285-4.465c0-10.838 4.974-20.713 13.127-28.291C9.294 85.42.003 70.417.003 53.58.003 23.99 28.656.001 64 .001s63.997 23.988 63.997 53.58c0 16.842-9.299 31.85-23.812 41.673zM64 36.867c-29.454 0-53.33-10.077-53.33 15.342 0 25.418 23.876 46.023 53.33 46.023 29.454 0 53.33-20.605 53.33-46.023 0-25.419-23.876-15.342-53.33-15.342zm24.888 25.644c-3.927 0-7.111-2.665-7.111-5.953 0-3.288 3.184-5.954 7.11-5.954 3.928 0 7.111 2.666 7.111 5.954s-3.183 5.953-7.11 5.953zm-3.556 16.372c0 4.11-9.55 7.442-21.332 7.442-11.781 0-21.332-3.332-21.332-7.442 0-1.06.656-2.064 1.8-2.976 3.295 2.626 10.79 4.465 19.532 4.465 8.743 0 16.237-1.84 19.531-4.465 1.145.912 1.801 1.916 1.801 2.976zm-46.22-16.372c-3.927 0-7.11-2.665-7.11-5.953 0-3.288 3.183-5.954 7.11-5.954 3.927 0 7.111 2.666 7.111 5.954s-3.184 5.953-7.11 5.953z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M104.185 95.254c8.161 7.574 13.145 17.441 13.145 28.28 0 1.508-.098 2.998-.285 4.466h-10.784c.238-1.465.403-2.948.403-4.465 0-8.983-4.36-17.115-11.419-23.216C86 104.66 75.355 107.162 64 107.162c-11.344 0-21.98-2.495-31.22-6.83-7.064 6.099-11.444 14.218-11.444 23.203 0 1.517.165 3 .403 4.465H10.955a35.444 35.444 0 0 1-.285-4.465c0-10.838 4.974-20.713 13.127-28.291C9.294 85.42.003 70.417.003 53.58.003 23.99 28.656.001 64 .001s63.997 23.988 63.997 53.58c0 16.842-9.299 31.85-23.812 41.673zM64 36.867c-29.454 0-53.33-10.077-53.33 15.342 0 25.418 23.876 46.023 53.33 46.023 29.454 0 53.33-20.605 53.33-46.023 0-25.419-23.876-15.342-53.33-15.342zm24.888 25.644c-3.927 0-7.111-2.665-7.111-5.953 0-3.288 3.184-5.954 7.11-5.954 3.928 0 7.111 2.666 7.111 5.954s-3.183 5.953-7.11 5.953zm-3.556 16.372c0 4.11-9.55 7.442-21.332 7.442-11.781 0-21.332-3.332-21.332-7.442 0-1.06.656-2.064 1.8-2.976 3.295 2.626 10.79 4.465 19.532 4.465 8.743 0 16.237-1.84 19.531-4.465 1.145.912 1.801 1.916 1.801 2.976zm-46.22-16.372c-3.927 0-7.11-2.665-7.11-5.953 0-3.288 3.183-5.954 7.11-5.954 3.927 0 7.111 2.666 7.111 5.954s-3.184 5.953-7.11 5.953z"/></svg>
src/icons/svg/peoples.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M95.648 118.762c0 5.035-3.563 9.121-7.979 9.121H7.98c-4.416 0-7.979-4.086-7.979-9.121C0 100.519 15.408 83.47 31.152 76.75c-9.099-6.43-15.216-17.863-15.216-30.987v-9.128c0-20.16 14.293-36.518 31.893-36.518s31.894 16.358 31.894 36.518v9.122c0 13.137-6.123 24.556-15.216 30.993 15.738 6.726 31.141 23.769 31.141 42.012z"/><path d="M106.032 118.252h15.867c3.376 0 6.101-3.125 6.101-6.972 0-13.957-11.787-26.984-23.819-32.123 6.955-4.919 11.638-13.66 11.638-23.704v-6.985c0-15.416-10.928-27.926-24.39-27.926-1.674 0-3.306.193-4.89.561 1.936 4.713 3.018 9.974 3.018 15.526v9.121c0 13.137-3.056 23.111-11.066 30.993 14.842 4.41 27.312 23.42 27.541 41.509z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M95.648 118.762c0 5.035-3.563 9.121-7.979 9.121H7.98c-4.416 0-7.979-4.086-7.979-9.121C0 100.519 15.408 83.47 31.152 76.75c-9.099-6.43-15.216-17.863-15.216-30.987v-9.128c0-20.16 14.293-36.518 31.893-36.518s31.894 16.358 31.894 36.518v9.122c0 13.137-6.123 24.556-15.216 30.993 15.738 6.726 31.141 23.769 31.141 42.012z"/><path d="M106.032 118.252h15.867c3.376 0 6.101-3.125 6.101-6.972 0-13.957-11.787-26.984-23.819-32.123 6.955-4.919 11.638-13.66 11.638-23.704v-6.985c0-15.416-10.928-27.926-24.39-27.926-1.674 0-3.306.193-4.89.561 1.936 4.713 3.018 9.974 3.018 15.526v9.121c0 13.137-3.056 23.111-11.066 30.993 14.842 4.41 27.312 23.42 27.541 41.509z"/></svg>
src/icons/svg/qq.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M18.448 57.545l-.244-.744-.198-.968-.132-.53v-2.181l.236-.859.24-.908.317-.953.428-1.06.561-1.103.794-1.104v-.773l.077-.724.123-.984.34-1.106.313-1.194.25-.548.289-.511.371-.569.405-.423v-2.73l.234-1.407.236-1.633.42-1.955.577-2.035.43-1.118.426-1.217.468-1.135.559-1.216.57-1.332.655-1.247.737-1.331.929-1.33.43-.762.457-.624.995-1.406 1.025-1.403 1.163-1.444 1.246-1.405 1.352-1.384 1.41-1.423 1.708-1.536 1.083-.934 1.322-1.008 1.34-.89 1.448-.855 1.392-.76 1.57-.63 1.667-.775 1.657-.532 1.653-.552 1.787-.548 1.785-.417 1.876-.347L59.128.68l1.879-.245 1.876-.252 2.002-.106h5.912l1.97.243 1.981.231 2.019.207 1.874.441 1.979.413 1.857.475 2.035.53 1.862.646 1.782.738 1.904.78 1.736.853 1.689.95 1.655 1.044 1.425.971.662.548.693.401 1.323 1.1 1.115 1.064 1.112 1.1 1.083 1.214.894 1.178 1.064 1.217.74 1.306.752 1.162.798 1.352.661 1.175 1.113 2.489.546 1.286.428 1.192.428 1.294.384 1.217.267 1.047.347 1.231.607 2.198.388 1.924.253 1.861.217 1.497.342 2.28.077.362.274.41.737 1.18.473.8.42.832.534.892.472 1.07.307 1.093.334 1.2.252 1.232.115.605.106.746v.648l-.106.643v.8l-.192.774-.35 1.5-.403.76-.299.852v.213l.142.264.4.623 1.746 2.53 1.377 1.9.66 1.267.889 1.389.774 1.52.893 1.627.894 1.828 1.006 2.069.567 1.268.518 1.239.447 1.307.44 1.175.336 1.235.342 1.16.432 2.261.343 2.31.235 2.05v2.891l-.158 1.025-.226 1.768-.308 1.59-.48 1.44-.18.588-.336.707-.28.493-.375.607-.33.383-.42.494-.375.4-.401.34-.48.207-.432.207-.355.114h-.543l-.346-.114-.66-.32-.302-.212-.317-.223-.347-.304-.35-.342-.579-.63-.684-.89-.539-.917-.538-.734-.526-.855-.741-1.517-.833-1.579-.098-.055h-.138l-.338.247-.196.415-.326.516-.567 1.533-.856 2.182-1.096 2.626-.824 1.308-.864 1.366-1.027 1.536-1.09 1.503-.557.68-.676.743-1.555 1.497.136.135.21.214.777.446 3.235 1.524 1.41.779 1.347.756 1.332.953 1.187.982.574.443.432.511.445.593.367.643.198.533.242.64.105.554.115.647-.115.433v.44l-.105.454-.242.415-.092.325-.22.394-.587.784-.543.627-.42.47-.35.348-.893.638-1.01.556-1.077.532-1.155.511-1.287.495-.693.207-.608.167-1.496.342-1.545.325-1.552.323-1.689.27-1.74.072-1.785.21h-5.539l-1.998-.114-1.86-.168-2.005-.27-1.99-.209-2.095-.286-2.03-.495-1.981-.374-1.968-.552-2.019-.707-1.98-.585-1.044-.342-.927-.323-.586-.223-.582-.12h-1.647l-1.904-.131-.962-.096-1.24-.135-.795.705-1.085.665-1.471.701-1.628.875-.99.475-1.033.376-2.281.914-1.24.305-1.3.343-1.803.344-1.13.086-1.193.1-1.246.135-1.45.053h-5.926l-3.346-.053-3.25-.321-1.644-.23-1.589-.23-1.546-.227-1.547-.305-1.442-.456-1.434-.325-1.294-.51-1.223-.474-1.142-.533-.99-.583-.984-.71-.336-.343-.44-.415-.334-.362-.3-.417-.278-.415-.215-.42-.311-.89-.109-.46-.138-.51v-.473l.138-.533v-.53l.109-.53v-1.069l.052-.564.259-.647.215-.646.39-.779.286-.3.236-.348.615-.738.49-.38.464-.266.428-.338.676-.21.543-.324.676-.341.77-.227.775-.231.897-.192.85-.11 1.008-.13 1.093-.081.284-.092h.063l.137-.115v-.13l-.2-.266-.58-.27-1.45-1.231-.975-.761-1.127-.967-1.136-1.082-1.181-1.382-1.36-1.558-.508-.843-.672-.87-.58-1.007-.522-1.1-.704-1.047-.459-1.194-.547-1.192-.546-1.33-.397-1.273-.378-1.575-.112-.057h-.115l-.059-.113h-.14l-.23.113-.114.057-.158.264-.057.321-.119.286-.206.477-.664 1.157-.345.701-.546.612-.58.736-.641.816-.677.724-.795.701-.734.658-.814.524-.89.546-.855.325-1.008.247-.99.095h-.233l-.228-.095-.18-.384-.29-.188-.38-.912-.237-.493-.255-.707-.21-.734-.113-.724-.313-1.648-.12-.972v-3.185l.12-2.379.196-1.214.23-1.252.21-1.347.374-1.254.42-1.443.431-1.407.578-1.448.545-1.38.754-1.4.699-1.52.855-1.425 1.006-1.538 1.023-1.382 1.069-1.538.891-1.071 1.142-1.227 1.202-1.237.56-.59.678-.662.985-.836 1.012-.853 1.647-1.446 1.242-.889z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M18.448 57.545l-.244-.744-.198-.968-.132-.53v-2.181l.236-.859.24-.908.317-.953.428-1.06.561-1.103.794-1.104v-.773l.077-.724.123-.984.34-1.106.313-1.194.25-.548.289-.511.371-.569.405-.423v-2.73l.234-1.407.236-1.633.42-1.955.577-2.035.43-1.118.426-1.217.468-1.135.559-1.216.57-1.332.655-1.247.737-1.331.929-1.33.43-.762.457-.624.995-1.406 1.025-1.403 1.163-1.444 1.246-1.405 1.352-1.384 1.41-1.423 1.708-1.536 1.083-.934 1.322-1.008 1.34-.89 1.448-.855 1.392-.76 1.57-.63 1.667-.775 1.657-.532 1.653-.552 1.787-.548 1.785-.417 1.876-.347L59.128.68l1.879-.245 1.876-.252 2.002-.106h5.912l1.97.243 1.981.231 2.019.207 1.874.441 1.979.413 1.857.475 2.035.53 1.862.646 1.782.738 1.904.78 1.736.853 1.689.95 1.655 1.044 1.425.971.662.548.693.401 1.323 1.1 1.115 1.064 1.112 1.1 1.083 1.214.894 1.178 1.064 1.217.74 1.306.752 1.162.798 1.352.661 1.175 1.113 2.489.546 1.286.428 1.192.428 1.294.384 1.217.267 1.047.347 1.231.607 2.198.388 1.924.253 1.861.217 1.497.342 2.28.077.362.274.41.737 1.18.473.8.42.832.534.892.472 1.07.307 1.093.334 1.2.252 1.232.115.605.106.746v.648l-.106.643v.8l-.192.774-.35 1.5-.403.76-.299.852v.213l.142.264.4.623 1.746 2.53 1.377 1.9.66 1.267.889 1.389.774 1.52.893 1.627.894 1.828 1.006 2.069.567 1.268.518 1.239.447 1.307.44 1.175.336 1.235.342 1.16.432 2.261.343 2.31.235 2.05v2.891l-.158 1.025-.226 1.768-.308 1.59-.48 1.44-.18.588-.336.707-.28.493-.375.607-.33.383-.42.494-.375.4-.401.34-.48.207-.432.207-.355.114h-.543l-.346-.114-.66-.32-.302-.212-.317-.223-.347-.304-.35-.342-.579-.63-.684-.89-.539-.917-.538-.734-.526-.855-.741-1.517-.833-1.579-.098-.055h-.138l-.338.247-.196.415-.326.516-.567 1.533-.856 2.182-1.096 2.626-.824 1.308-.864 1.366-1.027 1.536-1.09 1.503-.557.68-.676.743-1.555 1.497.136.135.21.214.777.446 3.235 1.524 1.41.779 1.347.756 1.332.953 1.187.982.574.443.432.511.445.593.367.643.198.533.242.64.105.554.115.647-.115.433v.44l-.105.454-.242.415-.092.325-.22.394-.587.784-.543.627-.42.47-.35.348-.893.638-1.01.556-1.077.532-1.155.511-1.287.495-.693.207-.608.167-1.496.342-1.545.325-1.552.323-1.689.27-1.74.072-1.785.21h-5.539l-1.998-.114-1.86-.168-2.005-.27-1.99-.209-2.095-.286-2.03-.495-1.981-.374-1.968-.552-2.019-.707-1.98-.585-1.044-.342-.927-.323-.586-.223-.582-.12h-1.647l-1.904-.131-.962-.096-1.24-.135-.795.705-1.085.665-1.471.701-1.628.875-.99.475-1.033.376-2.281.914-1.24.305-1.3.343-1.803.344-1.13.086-1.193.1-1.246.135-1.45.053h-5.926l-3.346-.053-3.25-.321-1.644-.23-1.589-.23-1.546-.227-1.547-.305-1.442-.456-1.434-.325-1.294-.51-1.223-.474-1.142-.533-.99-.583-.984-.71-.336-.343-.44-.415-.334-.362-.3-.417-.278-.415-.215-.42-.311-.89-.109-.46-.138-.51v-.473l.138-.533v-.53l.109-.53v-1.069l.052-.564.259-.647.215-.646.39-.779.286-.3.236-.348.615-.738.49-.38.464-.266.428-.338.676-.21.543-.324.676-.341.77-.227.775-.231.897-.192.85-.11 1.008-.13 1.093-.081.284-.092h.063l.137-.115v-.13l-.2-.266-.58-.27-1.45-1.231-.975-.761-1.127-.967-1.136-1.082-1.181-1.382-1.36-1.558-.508-.843-.672-.87-.58-1.007-.522-1.1-.704-1.047-.459-1.194-.547-1.192-.546-1.33-.397-1.273-.378-1.575-.112-.057h-.115l-.059-.113h-.14l-.23.113-.114.057-.158.264-.057.321-.119.286-.206.477-.664 1.157-.345.701-.546.612-.58.736-.641.816-.677.724-.795.701-.734.658-.814.524-.89.546-.855.325-1.008.247-.99.095h-.233l-.228-.095-.18-.384-.29-.188-.38-.912-.237-.493-.255-.707-.21-.734-.113-.724-.313-1.648-.12-.972v-3.185l.12-2.379.196-1.214.23-1.252.21-1.347.374-1.254.42-1.443.431-1.407.578-1.448.545-1.38.754-1.4.699-1.52.855-1.425 1.006-1.538 1.023-1.382 1.069-1.538.891-1.071 1.142-1.227 1.202-1.237.56-.59.678-.662.985-.836 1.012-.853 1.647-1.446 1.242-.889z"/></svg>
src/icons/svg/search.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M124.884 109.812L94.256 79.166c-.357-.357-.757-.629-1.129-.914a50.366 50.366 0 0 0 8.186-27.59C101.327 22.689 78.656 0 50.67 0 22.685 0 0 22.688 0 50.663c0 27.989 22.685 50.663 50.656 50.663 10.186 0 19.643-3.03 27.6-8.201.286.385.557.771.9 1.114l30.628 30.632a10.633 10.633 0 0 0 7.543 3.129c2.728 0 5.457-1.043 7.543-3.115 4.171-4.157 4.171-10.915.014-15.073M50.671 85.338C31.557 85.338 16 69.78 16 50.663c0-19.102 15.557-34.661 34.67-34.661 19.115 0 34.657 15.559 34.657 34.675 0 19.102-15.557 34.661-34.656 34.661"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M124.884 109.812L94.256 79.166c-.357-.357-.757-.629-1.129-.914a50.366 50.366 0 0 0 8.186-27.59C101.327 22.689 78.656 0 50.67 0 22.685 0 0 22.688 0 50.663c0 27.989 22.685 50.663 50.656 50.663 10.186 0 19.643-3.03 27.6-8.201.286.385.557.771.9 1.114l30.628 30.632a10.633 10.633 0 0 0 7.543 3.129c2.728 0 5.457-1.043 7.543-3.115 4.171-4.157 4.171-10.915.014-15.073M50.671 85.338C31.557 85.338 16 69.78 16 50.663c0-19.102 15.557-34.661 34.67-34.661 19.115 0 34.657 15.559 34.657 34.675 0 19.102-15.557 34.661-34.656 34.661"/></svg>
src/icons/svg/shopping.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M42.913 101.36c1.642 0 3.198.332 4.667.996a12.28 12.28 0 0 1 3.89 2.772c1.123 1.184 1.987 2.582 2.592 4.193.605 1.612.908 3.318.908 5.118 0 1.8-.303 3.507-.908 5.118-.605 1.611-1.469 3.01-2.593 4.194a13.3 13.3 0 0 1-3.889 2.843 10.582 10.582 0 0 1-4.667 1.066c-1.729 0-3.306-.355-4.732-1.066a13.604 13.604 0 0 1-3.825-2.843c-1.123-1.185-1.988-2.583-2.593-4.194a14.437 14.437 0 0 1-.907-5.118c0-1.8.302-3.506.907-5.118.605-1.61 1.47-3.009 2.593-4.193a12.515 12.515 0 0 1 3.825-2.772c1.426-.664 3.003-.996 4.732-.996zm53.932.285c1.643 0 3.22.331 4.733.995a11.386 11.386 0 0 1 3.889 2.772c1.08 1.185 1.945 2.583 2.593 4.194.648 1.61.972 3.317.972 5.118 0 1.8-.324 3.506-.972 5.117-.648 1.611-1.513 3.01-2.593 4.194a12.253 12.253 0 0 1-3.89 2.843 11 11 0 0 1-4.732 1.066 10.58 10.58 0 0 1-4.667-1.066 12.478 12.478 0 0 1-3.824-2.843c-1.08-1.185-1.945-2.583-2.593-4.194a13.581 13.581 0 0 1-.973-5.117c0-1.801.325-3.507.973-5.118.648-1.611 1.512-3.01 2.593-4.194a11.559 11.559 0 0 1 3.824-2.772 11.212 11.212 0 0 1 4.667-.995zm21.781-80.747c2.42 0 4.3.355 5.64 1.066 1.34.71 2.29 1.587 2.852 2.63a6.427 6.427 0 0 1 .778 3.34c-.044 1.185-.195 2.204-.454 3.057-.26.853-.8 2.606-1.62 5.26a589.268 589.268 0 0 1-2.788 8.743 1236.373 1236.373 0 0 0-3.047 9.453c-.994 3.128-1.75 5.592-2.269 7.393-1.123 3.79-2.55 6.42-4.278 7.89-1.728 1.469-3.846 2.203-6.352 2.203H39.023l1.945 12.795h65.342c4.148 0 6.223 1.943 6.223 5.828 0 1.896-.41 3.53-1.232 4.905-.821 1.374-2.442 2.061-4.862 2.061H38.505c-1.729 0-3.176-.426-4.343-1.28-1.167-.852-2.14-1.966-2.917-3.34a21.277 21.277 0 0 1-1.88-4.478 44.128 44.128 0 0 1-1.102-4.55c-.087-.568-.324-1.942-.713-4.122-.39-2.18-.865-4.904-1.426-8.174l-1.88-10.947c-.692-4.027-1.383-8.079-2.075-12.154-1.642-9.572-3.5-20.234-5.574-31.986H6.87c-1.296 0-2.377-.356-3.24-1.067a9.024 9.024 0 0 1-2.14-2.558 10.416 10.416 0 0 1-1.167-3.2C.108 8.53 0 7.488 0 6.54c0-1.896.583-3.46 1.75-4.69C2.917.615 4.494 0 6.482 0h13.095c1.728 0 3.111.284 4.148.853 1.037.569 1.858 1.28 2.463 2.132a8.548 8.548 0 0 1 1.297 2.701c.26.948.475 1.754.648 2.417.173.758.346 1.825.519 3.199.173 1.374.345 2.772.518 4.193.26 1.706.519 3.507.778 5.403h88.678z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M42.913 101.36c1.642 0 3.198.332 4.667.996a12.28 12.28 0 0 1 3.89 2.772c1.123 1.184 1.987 2.582 2.592 4.193.605 1.612.908 3.318.908 5.118 0 1.8-.303 3.507-.908 5.118-.605 1.611-1.469 3.01-2.593 4.194a13.3 13.3 0 0 1-3.889 2.843 10.582 10.582 0 0 1-4.667 1.066c-1.729 0-3.306-.355-4.732-1.066a13.604 13.604 0 0 1-3.825-2.843c-1.123-1.185-1.988-2.583-2.593-4.194a14.437 14.437 0 0 1-.907-5.118c0-1.8.302-3.506.907-5.118.605-1.61 1.47-3.009 2.593-4.193a12.515 12.515 0 0 1 3.825-2.772c1.426-.664 3.003-.996 4.732-.996zm53.932.285c1.643 0 3.22.331 4.733.995a11.386 11.386 0 0 1 3.889 2.772c1.08 1.185 1.945 2.583 2.593 4.194.648 1.61.972 3.317.972 5.118 0 1.8-.324 3.506-.972 5.117-.648 1.611-1.513 3.01-2.593 4.194a12.253 12.253 0 0 1-3.89 2.843 11 11 0 0 1-4.732 1.066 10.58 10.58 0 0 1-4.667-1.066 12.478 12.478 0 0 1-3.824-2.843c-1.08-1.185-1.945-2.583-2.593-4.194a13.581 13.581 0 0 1-.973-5.117c0-1.801.325-3.507.973-5.118.648-1.611 1.512-3.01 2.593-4.194a11.559 11.559 0 0 1 3.824-2.772 11.212 11.212 0 0 1 4.667-.995zm21.781-80.747c2.42 0 4.3.355 5.64 1.066 1.34.71 2.29 1.587 2.852 2.63a6.427 6.427 0 0 1 .778 3.34c-.044 1.185-.195 2.204-.454 3.057-.26.853-.8 2.606-1.62 5.26a589.268 589.268 0 0 1-2.788 8.743 1236.373 1236.373 0 0 0-3.047 9.453c-.994 3.128-1.75 5.592-2.269 7.393-1.123 3.79-2.55 6.42-4.278 7.89-1.728 1.469-3.846 2.203-6.352 2.203H39.023l1.945 12.795h65.342c4.148 0 6.223 1.943 6.223 5.828 0 1.896-.41 3.53-1.232 4.905-.821 1.374-2.442 2.061-4.862 2.061H38.505c-1.729 0-3.176-.426-4.343-1.28-1.167-.852-2.14-1.966-2.917-3.34a21.277 21.277 0 0 1-1.88-4.478 44.128 44.128 0 0 1-1.102-4.55c-.087-.568-.324-1.942-.713-4.122-.39-2.18-.865-4.904-1.426-8.174l-1.88-10.947c-.692-4.027-1.383-8.079-2.075-12.154-1.642-9.572-3.5-20.234-5.574-31.986H6.87c-1.296 0-2.377-.356-3.24-1.067a9.024 9.024 0 0 1-2.14-2.558 10.416 10.416 0 0 1-1.167-3.2C.108 8.53 0 7.488 0 6.54c0-1.896.583-3.46 1.75-4.69C2.917.615 4.494 0 6.482 0h13.095c1.728 0 3.111.284 4.148.853 1.037.569 1.858 1.28 2.463 2.132a8.548 8.548 0 0 1 1.297 2.701c.26.948.475 1.754.648 2.417.173.758.346 1.825.519 3.199.173 1.374.345 2.772.518 4.193.26 1.706.519 3.507.778 5.403h88.678z"/></svg>
src/icons/svg/size.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h54.796v18.286H36.531V128H18.265V73.143H0V54.857zm127.857-36.571H91.935V128H72.456V18.286H36.534V0h91.326l-.003 18.286z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M0 54.857h54.796v18.286H36.531V128H18.265V73.143H0V54.857zm127.857-36.571H91.935V128H72.456V18.286H36.534V0h91.326l-.003 18.286z"/></svg>
src/icons/svg/skill.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M31.652 93.206h33.401c1.44 2.418 3.077 4.663 4.93 6.692h-38.33v-6.692zm0-10.586h28.914a44.8 44.8 0 0 1-1.264-6.688h-27.65v6.688zm0-17.27H59.39c.288-2.286.714-4.532 1.34-6.687H31.65v6.687h.003zm53.913 44.84v5.85c0 2.798-2.095 5.075-4.667 5.075h-70.07c-2.576 0-4.663-2.277-4.663-5.075V31.26l23.22-20.96v22.25H17.16v6.688h18.39V6.688h45.348c2.576 0 4.667 2.277 4.667 5.066v20.009c1.987-.675 4.053-1.128 6.17-1.445v-18.56C91.738 5.28 86.874 0 80.902 0H31.15L0 28.118v87.917c0 6.48 4.859 11.759 10.832 11.759h70.07c5.974 0 10.837-5.27 10.837-11.759v-4.41c-2.117-.312-4.183-.765-6.17-1.435h-.004zM23.279 58.667h-7.96v6.688h7.96v-6.688zm-7.956 41.23h7.96v-6.691h-7.96v6.692zm7.956-23.96h-7.96v6.687h7.96v-6.688zm89.718-15.042l-4.896-4.07-12.447 17.613-11.19-9.305-3.762 5.311 16.091 13.38 16.204-22.929zM128 70.978c0-18.632-13.97-33.782-31.147-33.782-17.168 0-31.135 15.155-31.135 33.782 0 18.628 13.97 33.783 31.135 33.783 17.172 0 31.143-15.15 31.143-33.783H128zm-6.17 0c0 14.933-11.203 27.1-24.981 27.1-13.77 0-24.987-12.158-24.987-27.1 0-14.941 11.195-27.099 24.987-27.099 13.778 0 24.982 12.158 24.982 27.1z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M31.652 93.206h33.401c1.44 2.418 3.077 4.663 4.93 6.692h-38.33v-6.692zm0-10.586h28.914a44.8 44.8 0 0 1-1.264-6.688h-27.65v6.688zm0-17.27H59.39c.288-2.286.714-4.532 1.34-6.687H31.65v6.687h.003zm53.913 44.84v5.85c0 2.798-2.095 5.075-4.667 5.075h-70.07c-2.576 0-4.663-2.277-4.663-5.075V31.26l23.22-20.96v22.25H17.16v6.688h18.39V6.688h45.348c2.576 0 4.667 2.277 4.667 5.066v20.009c1.987-.675 4.053-1.128 6.17-1.445v-18.56C91.738 5.28 86.874 0 80.902 0H31.15L0 28.118v87.917c0 6.48 4.859 11.759 10.832 11.759h70.07c5.974 0 10.837-5.27 10.837-11.759v-4.41c-2.117-.312-4.183-.765-6.17-1.435h-.004zM23.279 58.667h-7.96v6.688h7.96v-6.688zm-7.956 41.23h7.96v-6.691h-7.96v6.692zm7.956-23.96h-7.96v6.687h7.96v-6.688zm89.718-15.042l-4.896-4.07-12.447 17.613-11.19-9.305-3.762 5.311 16.091 13.38 16.204-22.929zM128 70.978c0-18.632-13.97-33.782-31.147-33.782-17.168 0-31.135 15.155-31.135 33.782 0 18.628 13.97 33.783 31.135 33.783 17.172 0 31.143-15.15 31.143-33.783H128zm-6.17 0c0 14.933-11.203 27.1-24.981 27.1-13.77 0-24.987-12.158-24.987-27.1 0-14.941 11.195-27.099 24.987-27.099 13.778 0 24.982 12.158 24.982 27.1z"/></svg>
src/icons/svg/star.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M70.66 4.328l14.01 29.693c1.088 2.29 3.177 3.882 5.603 4.25l31.347 4.76c6.087.926 8.528 8.756 4.117 13.247L103.05 79.395c-1.75 1.78-2.544 4.352-2.132 6.867l5.352 32.641c1.043 6.337-5.33 11.182-10.778 8.19l-28.039-15.409a7.13 7.13 0 0 0-6.91 0l-28.039 15.41c-5.448 2.99-11.821-1.854-10.777-8.19l5.352-32.642c.415-2.515-.387-5.088-2.136-6.867L2.264 56.278C-2.146 51.787.286 43.957 6.38 43.031l31.343-4.76c2.419-.368 4.51-1.96 5.595-4.25L57.334 4.328c2.728-5.77 10.605-5.77 13.325 0z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M70.66 4.328l14.01 29.693c1.088 2.29 3.177 3.882 5.603 4.25l31.347 4.76c6.087.926 8.528 8.756 4.117 13.247L103.05 79.395c-1.75 1.78-2.544 4.352-2.132 6.867l5.352 32.641c1.043 6.337-5.33 11.182-10.778 8.19l-28.039-15.409a7.13 7.13 0 0 0-6.91 0l-28.039 15.41c-5.448 2.99-11.821-1.854-10.777-8.19l5.352-32.642c.415-2.515-.387-5.088-2.136-6.867L2.264 56.278C-2.146 51.787.286 43.957 6.38 43.031l31.343-4.76c2.419-.368 4.51-1.96 5.595-4.25L57.334 4.328c2.728-5.77 10.605-5.77 13.325 0z"/></svg>
src/icons/svg/tab.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.921.052H49.08c-1.865 0-3.198 1.599-3.198 3.464v6.661c0 1.865 1.6 3.464 3.198 3.464h29.84c1.865 0 3.198-1.599 3.198-3.464V3.516C82.385 1.65 80.786.052 78.92.052zm45.563 0H94.642c-1.865 0-3.464 1.599-3.464 3.464v6.661c0 1.865 1.599 3.464 3.464 3.464h29.842c1.865-.266 3.464-1.599 3.464-3.464V3.516c0-1.865-1.599-3.464-3.464-3.464zm0 22.382H40.02c-1.866 0-3.464-1.599-3.464-3.464V3.516c0-1.865-1.599-3.464-3.464-3.464H3.516C1.65.052.052 1.651.052 3.516V124.75c0 1.598 1.599 3.197 3.464 3.197h120.968c1.865 0 3.464-1.599 3.464-3.464V25.898c0-1.865-1.599-3.464-3.464-3.464z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.921.052H49.08c-1.865 0-3.198 1.599-3.198 3.464v6.661c0 1.865 1.6 3.464 3.198 3.464h29.84c1.865 0 3.198-1.599 3.198-3.464V3.516C82.385 1.65 80.786.052 78.92.052zm45.563 0H94.642c-1.865 0-3.464 1.599-3.464 3.464v6.661c0 1.865 1.599 3.464 3.464 3.464h29.842c1.865-.266 3.464-1.599 3.464-3.464V3.516c0-1.865-1.599-3.464-3.464-3.464zm0 22.382H40.02c-1.866 0-3.464-1.599-3.464-3.464V3.516c0-1.865-1.599-3.464-3.464-3.464H3.516C1.65.052.052 1.651.052 3.516V124.75c0 1.598 1.599 3.197 3.464 3.197h120.968c1.865 0 3.464-1.599 3.464-3.464V25.898c0-1.865-1.599-3.464-3.464-3.464z"/></svg>
src/icons/svg/table.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/><path d="M.006.064h127.988v31.104H.006V.064zm0 38.016h38.396v41.472H.006V38.08zm0 48.384h38.396v41.472H.006V86.464zM44.802 38.08h38.396v41.472H44.802V38.08zm0 48.384h38.396v41.472H44.802V86.464zM89.598 38.08h38.396v41.472H89.598zm0 48.384h38.396v41.472H89.598z"/></svg>
src/icons/svg/theme.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M125.5 36.984L95.336 2.83C93.735 1.018 91.565 0 89.3 0c-2.263 0-4.433 1.018-6.033 2.83l-3.786 4.286c-1.6 1.812-3.77 2.83-6.032 2.831H54.553c-2.263 0-4.434-1.018-6.033-2.83L44.734 2.83C43.134 1.018 40.964 0 38.701 0c-2.263 0-4.434 1.018-6.034 2.83L2.5 36.984C.9 38.796 0 41.254 0 43.815c0 2.562.899 5.02 2.5 6.831L14.565 64.31c2.178 2.468 5.367 3.403 8.33 2.444 1.35-.435 2.709.592 2.709 2.18v49.407c0 5.313 3.84 9.66 8.532 9.66h59.726c4.693 0 8.532-4.347 8.532-9.66V68.934c0-1.59 1.36-2.616 2.71-2.181 2.962.96 6.15.024 8.329-2.444L125.5 50.646c1.6-1.811 2.499-4.269 2.499-6.83 0-2.563-.899-5.02-2.5-6.832z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M125.5 36.984L95.336 2.83C93.735 1.018 91.565 0 89.3 0c-2.263 0-4.433 1.018-6.033 2.83l-3.786 4.286c-1.6 1.812-3.77 2.83-6.032 2.831H54.553c-2.263 0-4.434-1.018-6.033-2.83L44.734 2.83C43.134 1.018 40.964 0 38.701 0c-2.263 0-4.434 1.018-6.034 2.83L2.5 36.984C.9 38.796 0 41.254 0 43.815c0 2.562.899 5.02 2.5 6.831L14.565 64.31c2.178 2.468 5.367 3.403 8.33 2.444 1.35-.435 2.709.592 2.709 2.18v49.407c0 5.313 3.84 9.66 8.532 9.66h59.726c4.693 0 8.532-4.347 8.532-9.66V68.934c0-1.59 1.36-2.616 2.71-2.181 2.962.96 6.15.024 8.329-2.444L125.5 50.646c1.6-1.811 2.499-4.269 2.499-6.83 0-2.563-.899-5.02-2.5-6.832z"/></svg>
src/icons/svg/tree-table.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M44.8 0h79.543C126.78 0 128 1.422 128 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H44.8c-2.438 0-3.657-1.422-3.657-4.267V4.267C41.143 1.422 42.362 0 44.8 0zm22.857 48h56.686c2.438 0 3.657 1.422 3.657 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H67.657C65.22 80 64 78.578 64 75.733V52.267C64 49.422 65.219 48 67.657 48zm0 48h56.686c2.438 0 3.657 1.422 3.657 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H67.657C65.22 128 64 126.578 64 123.733v-23.466C64 97.422 65.219 96 67.657 96zM50.286 68.267c2.02 0 3.657-1.91 3.657-4.267 0-2.356-1.638-4.267-3.657-4.267H17.37V32h6.4c2.02 0 3.658-1.91 3.658-4.267V4.267C27.429 1.91 25.79 0 23.77 0H3.657C1.637 0 0 1.91 0 4.267v23.466C0 30.09 1.637 32 3.657 32h6.4v80c0 2.356 1.638 4.267 3.657 4.267h36.572c2.02 0 3.657-1.91 3.657-4.267 0-2.356-1.638-4.267-3.657-4.267H17.37V68.267h32.915z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M44.8 0h79.543C126.78 0 128 1.422 128 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H44.8c-2.438 0-3.657-1.422-3.657-4.267V4.267C41.143 1.422 42.362 0 44.8 0zm22.857 48h56.686c2.438 0 3.657 1.422 3.657 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H67.657C65.22 80 64 78.578 64 75.733V52.267C64 49.422 65.219 48 67.657 48zm0 48h56.686c2.438 0 3.657 1.422 3.657 4.267v23.466c0 2.845-1.219 4.267-3.657 4.267H67.657C65.22 128 64 126.578 64 123.733v-23.466C64 97.422 65.219 96 67.657 96zM50.286 68.267c2.02 0 3.657-1.91 3.657-4.267 0-2.356-1.638-4.267-3.657-4.267H17.37V32h6.4c2.02 0 3.658-1.91 3.658-4.267V4.267C27.429 1.91 25.79 0 23.77 0H3.657C1.637 0 0 1.91 0 4.267v23.466C0 30.09 1.637 32 3.657 32h6.4v80c0 2.356 1.638 4.267 3.657 4.267h36.572c2.02 0 3.657-1.91 3.657-4.267 0-2.356-1.638-4.267-3.657-4.267H17.37V68.267h32.915z"/></svg>
src/icons/svg/tree.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M126.713 90.023c.858.985 1.287 2.134 1.287 3.447v29.553c0 1.423-.429 2.6-1.287 3.53-.858.93-1.907 1.395-3.146 1.395H97.824c-1.145 0-2.146-.465-3.004-1.395-.858-.93-1.287-2.107-1.287-3.53V93.47c0-.875.19-1.696.572-2.462.382-.766.906-1.368 1.573-1.806a3.84 3.84 0 0 1 2.146-.657h9.725V69.007a3.84 3.84 0 0 0-.43-1.806 3.569 3.569 0 0 0-1.143-1.313 2.714 2.714 0 0 0-1.573-.492h-36.47v23.149h9.725c1.144 0 2.145.492 3.004 1.478.858.985 1.287 2.134 1.287 3.447v29.553c0 .876-.191 1.696-.573 2.463-.38.766-.905 1.368-1.573 1.806a3.84 3.84 0 0 1-2.145.656H51.915a3.84 3.84 0 0 1-2.145-.656c-.668-.438-1.216-1.04-1.645-1.806a4.96 4.96 0 0 1-.644-2.463V93.47c0-1.313.43-2.462 1.288-3.447.858-.986 1.907-1.478 3.146-1.478h9.582v-23.15h-37.9c-.953 0-1.74.356-2.359 1.068-.62.711-.93 1.56-.93 2.544v19.538h9.726c1.239 0 2.264.492 3.074 1.478.81.985 1.216 2.134 1.216 3.447v29.553c0 1.423-.405 2.6-1.216 3.53-.81.93-1.835 1.395-3.074 1.395H4.29c-.476 0-.93-.082-1.358-.246a4.1 4.1 0 0 1-1.144-.657 4.658 4.658 0 0 1-.93-1.067 5.186 5.186 0 0 1-.643-1.395 5.566 5.566 0 0 1-.215-1.56V93.47c0-.437.048-.875.143-1.313a3.95 3.95 0 0 1 .429-1.15c.19-.328.429-.656.715-.984.286-.329.572-.602.858-.821.286-.22.62-.383 1.001-.493.382-.11.763-.164 1.144-.164h9.726V61.619c0-.985.31-1.833.93-2.544.619-.712 1.358-1.068 2.216-1.068h44.335V39.62h-9.582c-1.24 0-2.288-.492-3.146-1.477a5.09 5.09 0 0 1-1.287-3.448V5.14c0-1.423.429-2.627 1.287-3.612.858-.985 1.907-1.477 3.146-1.477h25.743c.763 0 1.478.246 2.145.739a5.17 5.17 0 0 1 1.573 1.888c.382.766.573 1.587.573 2.462v29.553c0 1.313-.43 2.463-1.287 3.448-.859.985-1.86 1.477-3.004 1.477h-9.725v18.389h42.762c.954 0 1.74.355 2.36 1.067.62.711.93 1.56.93 2.545v26.925h9.582c1.239 0 2.288.492 3.146 1.478z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M126.713 90.023c.858.985 1.287 2.134 1.287 3.447v29.553c0 1.423-.429 2.6-1.287 3.53-.858.93-1.907 1.395-3.146 1.395H97.824c-1.145 0-2.146-.465-3.004-1.395-.858-.93-1.287-2.107-1.287-3.53V93.47c0-.875.19-1.696.572-2.462.382-.766.906-1.368 1.573-1.806a3.84 3.84 0 0 1 2.146-.657h9.725V69.007a3.84 3.84 0 0 0-.43-1.806 3.569 3.569 0 0 0-1.143-1.313 2.714 2.714 0 0 0-1.573-.492h-36.47v23.149h9.725c1.144 0 2.145.492 3.004 1.478.858.985 1.287 2.134 1.287 3.447v29.553c0 .876-.191 1.696-.573 2.463-.38.766-.905 1.368-1.573 1.806a3.84 3.84 0 0 1-2.145.656H51.915a3.84 3.84 0 0 1-2.145-.656c-.668-.438-1.216-1.04-1.645-1.806a4.96 4.96 0 0 1-.644-2.463V93.47c0-1.313.43-2.462 1.288-3.447.858-.986 1.907-1.478 3.146-1.478h9.582v-23.15h-37.9c-.953 0-1.74.356-2.359 1.068-.62.711-.93 1.56-.93 2.544v19.538h9.726c1.239 0 2.264.492 3.074 1.478.81.985 1.216 2.134 1.216 3.447v29.553c0 1.423-.405 2.6-1.216 3.53-.81.93-1.835 1.395-3.074 1.395H4.29c-.476 0-.93-.082-1.358-.246a4.1 4.1 0 0 1-1.144-.657 4.658 4.658 0 0 1-.93-1.067 5.186 5.186 0 0 1-.643-1.395 5.566 5.566 0 0 1-.215-1.56V93.47c0-.437.048-.875.143-1.313a3.95 3.95 0 0 1 .429-1.15c.19-.328.429-.656.715-.984.286-.329.572-.602.858-.821.286-.22.62-.383 1.001-.493.382-.11.763-.164 1.144-.164h9.726V61.619c0-.985.31-1.833.93-2.544.619-.712 1.358-1.068 2.216-1.068h44.335V39.62h-9.582c-1.24 0-2.288-.492-3.146-1.477a5.09 5.09 0 0 1-1.287-3.448V5.14c0-1.423.429-2.627 1.287-3.612.858-.985 1.907-1.477 3.146-1.477h25.743c.763 0 1.478.246 2.145.739a5.17 5.17 0 0 1 1.573 1.888c.382.766.573 1.587.573 2.462v29.553c0 1.313-.43 2.463-1.287 3.448-.859.985-1.86 1.477-3.004 1.477h-9.725v18.389h42.762c.954 0 1.74.355 2.36 1.067.62.711.93 1.56.93 2.545v26.925h9.582c1.239 0 2.288.492 3.146 1.478z"/></svg>
src/icons/svg/user.svg 100644 → 100755
1 <svg width="130" height="130" xmlns="http://www.w3.org/2000/svg"><path d="M63.444 64.996c20.633 0 37.359-14.308 37.359-31.953 0-17.649-16.726-31.952-37.359-31.952-20.631 0-37.36 14.303-37.358 31.952 0 17.645 16.727 31.953 37.359 31.953zM80.57 75.65H49.434c-26.652 0-48.26 18.477-48.26 41.27v2.664c0 9.316 21.608 9.325 48.26 9.325H80.57c26.649 0 48.256-.344 48.256-9.325v-2.663c0-22.794-21.605-41.271-48.256-41.271z" stroke="#979797"/></svg> 1 <svg width="130" height="130" xmlns="http://www.w3.org/2000/svg"><path d="M63.444 64.996c20.633 0 37.359-14.308 37.359-31.953 0-17.649-16.726-31.952-37.359-31.952-20.631 0-37.36 14.303-37.358 31.952 0 17.645 16.727 31.953 37.359 31.953zM80.57 75.65H49.434c-26.652 0-48.26 18.477-48.26 41.27v2.664c0 9.316 21.608 9.325 48.26 9.325H80.57c26.649 0 48.256-.344 48.256-9.325v-2.663c0-22.794-21.605-41.271-48.256-41.271z" stroke="#979797"/></svg>
src/icons/svg/wechat.svg 100644 → 100755
1 <svg width="128" height="110" xmlns="http://www.w3.org/2000/svg"><path d="M86.635 33.334c1.467 0 2.917.113 4.358.283C87.078 14.392 67.58.111 45.321.111 20.44.111.055 17.987.055 40.687c0 13.104 6.781 23.863 18.115 32.209l-4.527 14.352 15.82-8.364c5.666 1.182 10.207 2.395 15.858 2.395 1.42 0 2.829-.073 4.227-.189-.886-3.19-1.398-6.53-1.398-9.996 0-20.845 16.98-37.76 38.485-37.76zm-24.34-12.936c3.407 0 5.665 2.363 5.665 5.954 0 3.576-2.258 5.97-5.666 5.97-3.392 0-6.795-2.395-6.795-5.97 0-3.591 3.403-5.954 6.795-5.954zM30.616 32.323c-3.393 0-6.818-2.395-6.818-5.971 0-3.591 3.425-5.954 6.818-5.954 3.392 0 5.65 2.363 5.65 5.954 0 3.576-2.258 5.97-5.65 5.97z"/><path d="M127.945 70.52c0-19.075-18.108-34.623-38.448-34.623-21.537 0-38.5 15.548-38.5 34.623 0 19.108 16.963 34.622 38.5 34.622 4.508 0 9.058-1.2 13.584-2.395l12.414 7.167-3.404-11.923c9.087-7.184 15.854-16.712 15.854-27.471zm-50.928-5.97c-2.254 0-4.53-2.362-4.53-4.773 0-2.378 2.276-4.771 4.53-4.771 3.422 0 5.665 2.393 5.665 4.771 0 2.41-2.243 4.773-5.665 4.773zm24.897 0c-2.24 0-4.498-2.362-4.498-4.773 0-2.378 2.258-4.771 4.498-4.771 3.392 0 5.665 2.393 5.665 4.771 0 2.41-2.273 4.773-5.665 4.773z"/></svg> 1 <svg width="128" height="110" xmlns="http://www.w3.org/2000/svg"><path d="M86.635 33.334c1.467 0 2.917.113 4.358.283C87.078 14.392 67.58.111 45.321.111 20.44.111.055 17.987.055 40.687c0 13.104 6.781 23.863 18.115 32.209l-4.527 14.352 15.82-8.364c5.666 1.182 10.207 2.395 15.858 2.395 1.42 0 2.829-.073 4.227-.189-.886-3.19-1.398-6.53-1.398-9.996 0-20.845 16.98-37.76 38.485-37.76zm-24.34-12.936c3.407 0 5.665 2.363 5.665 5.954 0 3.576-2.258 5.97-5.666 5.97-3.392 0-6.795-2.395-6.795-5.97 0-3.591 3.403-5.954 6.795-5.954zM30.616 32.323c-3.393 0-6.818-2.395-6.818-5.971 0-3.591 3.425-5.954 6.818-5.954 3.392 0 5.65 2.363 5.65 5.954 0 3.576-2.258 5.97-5.65 5.97z"/><path d="M127.945 70.52c0-19.075-18.108-34.623-38.448-34.623-21.537 0-38.5 15.548-38.5 34.623 0 19.108 16.963 34.622 38.5 34.622 4.508 0 9.058-1.2 13.584-2.395l12.414 7.167-3.404-11.923c9.087-7.184 15.854-16.712 15.854-27.471zm-50.928-5.97c-2.254 0-4.53-2.362-4.53-4.773 0-2.378 2.276-4.771 4.53-4.771 3.422 0 5.665 2.393 5.665 4.771 0 2.41-2.243 4.773-5.665 4.773zm24.897 0c-2.24 0-4.498-2.362-4.498-4.773 0-2.378 2.258-4.771 4.498-4.771 3.392 0 5.665 2.393 5.665 4.771 0 2.41-2.273 4.773-5.665 4.773z"/></svg>
src/icons/svg/zip.svg 100644 → 100755
1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.527 116.793c.178.008.348.024.527.024h40.233c4.711-.005 8.53-3.677 8.534-8.21V18.895c-.004-4.532-3.823-8.204-8.534-8.209H79.054c-.179 0-.353.016-.527.024V0L0 10.082v107.406l78.527 10.342v-11.037zm0-101.362c.174-.024.348-.052.527-.052h40.233c2.018 0 3.659 1.578 3.659 3.52v89.713c-.003 1.942-1.64 3.517-3.659 3.519H79.054c-.179 0-.353-.028-.527-.052V15.431zM30.262 75.757l-18.721-.46V72.37l11.3-16.673v-.148l-10.266.164v-4.51l17.504-.44v3.264L18.696 70.76v.144l11.566.176v4.678zm9.419.231l-5.823-.144V50.671l5.823-.144v25.461zm22.255-11.632c-2.168 1.922-5.353 2.76-9.02 2.736-.702.004-1.402-.04-2.097-.131v9.303l-5.997-.148V50.743c1.852-.352 4.473-.647 8.218-.743 3.838-.096 6.608.539 8.48 1.913 1.807 1.306 3.032 3.5 3.032 6.112s-.926 4.833-2.612 6.331h-.004zM53.36 54.45c-.856-.01-1.71.083-2.541.275v7.682c.523.116 1.167.152 2.06.152 3.301-.004 5.36-1.614 5.36-4.314 0-2.425-1.772-3.843-4.875-3.791l-.004-.004zm39.847-37.066h9.564v3.795h-9.564v-3.795zm-9.568 5.68h9.564v3.8h-9.564v-3.8zm9.568 6.216h9.564v3.799h-9.564V29.28zm0 12h9.564v3.794h-9.564V41.28zm-9.568-6.096h9.564v3.795h-9.564v-3.795zm9.472 47.064c2.512 0 4.921-.96 6.697-2.67 1.776-1.708 2.773-4.026 2.772-6.442l-1.748-15.263c0-5.033-2.492-9.112-7.725-9.112-5.232 0-7.72 4.079-7.72 9.112l-1.752 15.263c-.001 2.417.996 4.735 2.773 6.444 1.777 1.71 4.187 2.669 6.7 2.668h.003zm-3.135-16.75h6.27v12.743h-6.27V65.5z"/></svg> 1 <svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M78.527 116.793c.178.008.348.024.527.024h40.233c4.711-.005 8.53-3.677 8.534-8.21V18.895c-.004-4.532-3.823-8.204-8.534-8.209H79.054c-.179 0-.353.016-.527.024V0L0 10.082v107.406l78.527 10.342v-11.037zm0-101.362c.174-.024.348-.052.527-.052h40.233c2.018 0 3.659 1.578 3.659 3.52v89.713c-.003 1.942-1.64 3.517-3.659 3.519H79.054c-.179 0-.353-.028-.527-.052V15.431zM30.262 75.757l-18.721-.46V72.37l11.3-16.673v-.148l-10.266.164v-4.51l17.504-.44v3.264L18.696 70.76v.144l11.566.176v4.678zm9.419.231l-5.823-.144V50.671l5.823-.144v25.461zm22.255-11.632c-2.168 1.922-5.353 2.76-9.02 2.736-.702.004-1.402-.04-2.097-.131v9.303l-5.997-.148V50.743c1.852-.352 4.473-.647 8.218-.743 3.838-.096 6.608.539 8.48 1.913 1.807 1.306 3.032 3.5 3.032 6.112s-.926 4.833-2.612 6.331h-.004zM53.36 54.45c-.856-.01-1.71.083-2.541.275v7.682c.523.116 1.167.152 2.06.152 3.301-.004 5.36-1.614 5.36-4.314 0-2.425-1.772-3.843-4.875-3.791l-.004-.004zm39.847-37.066h9.564v3.795h-9.564v-3.795zm-9.568 5.68h9.564v3.8h-9.564v-3.8zm9.568 6.216h9.564v3.799h-9.564V29.28zm0 12h9.564v3.794h-9.564V41.28zm-9.568-6.096h9.564v3.795h-9.564v-3.795zm9.472 47.064c2.512 0 4.921-.96 6.697-2.67 1.776-1.708 2.773-4.026 2.772-6.442l-1.748-15.263c0-5.033-2.492-9.112-7.725-9.112-5.232 0-7.72 4.079-7.72 9.112l-1.752 15.263c-.001 2.417.996 4.735 2.773 6.444 1.777 1.71 4.187 2.669 6.7 2.668h.003zm-3.135-16.75h6.27v12.743h-6.27V65.5z"/></svg>
src/icons/svgo.yml 100644 → 100755
1 # replace default config 1 # replace default config
2 2
3 # multipass: true 3 # multipass: true
4 # full: true 4 # full: true
5 5
6 plugins: 6 plugins:
7 7
8 # - name 8 # - name
9 # 9 #
10 # or: 10 # or:
11 # - name: false 11 # - name: false
12 # - name: true 12 # - name: true
13 # 13 #
14 # or: 14 # or:
15 # - name: 15 # - name:
16 # param1: 1 16 # param1: 1
17 # param2: 2 17 # param2: 2
18 18
19 - removeAttrs: 19 - removeAttrs:
20 attrs: 20 attrs:
21 - 'fill' 21 - 'fill'
22 - 'fill-rule' 22 - 'fill-rule'
23 23
File was created 1 export default {
2 route: {
3 dashboard: 'Dashboard',
4 documentation: 'Documentation',
5 guide: 'Guide',
6 permission: 'Permission',
7 pagePermission: 'Page Permission',
8 rolePermission: 'Role Permission',
9 directivePermission: 'Directive Permission',
10 icons: 'Icons',
11 components: 'Components',
12 tinymce: 'Tinymce',
13 markdown: 'Markdown',
14 jsonEditor: 'JSON Editor',
15 dndList: 'Dnd List',
16 splitPane: 'SplitPane',
17 avatarUpload: 'Avatar Upload',
18 dropzone: 'Dropzone',
19 sticky: 'Sticky',
20 countTo: 'Count To',
21 componentMixin: 'Mixin',
22 backToTop: 'Back To Top',
23 dragDialog: 'Drag Dialog',
24 dragSelect: 'Drag Select',
25 dragKanban: 'Drag Kanban',
26 charts: 'Charts',
27 keyboardChart: 'Keyboard Chart',
28 lineChart: 'Line Chart',
29 mixChart: 'Mix Chart',
30 example: 'Example',
31 nested: 'Nested Routes',
32 menu1: 'Menu 1',
33 'menu1-1': 'Menu 1-1',
34 'menu1-2': 'Menu 1-2',
35 'menu1-2-1': 'Menu 1-2-1',
36 'menu1-2-2': 'Menu 1-2-2',
37 'menu1-3': 'Menu 1-3',
38 menu2: 'Menu 2',
39 Table: 'Table',
40 dynamicTable: 'Dynamic Table',
41 dragTable: 'Drag Table',
42 inlineEditTable: 'Inline Edit',
43 complexTable: 'Complex Table',
44 tab: 'Tab',
45 form: 'Form',
46 createArticle: 'Create Article',
47 editArticle: 'Edit Article',
48 articleList: 'Article List',
49 errorPages: 'Error Pages',
50 page401: '401',
51 page404: '404',
52 errorLog: 'Error Log',
53 excel: 'Excel',
54 exportExcel: 'Export Excel',
55 selectExcel: 'Export Selected',
56 mergeHeader: 'Merge Header',
57 uploadExcel: 'Upload Excel',
58 zip: 'Zip',
59 pdf: 'PDF',
60 exportZip: 'Export Zip',
61 theme: 'Theme',
62 clipboardDemo: 'Clipboard',
63 i18n: 'I18n',
64 externalLink: 'External Link',
65 profile: 'Profile'
66 },
67 navbar: {
68 dashboard: 'Dashboard',
69 github: 'Github',
70 logOut: 'Log Out',
71 profile: 'Profile',
72 theme: 'Theme',
73 size: 'Global Size'
74 },
75 login: {
76 title: 'Login Form',
77 logIn: 'Login',
78 username: 'Username',
79 password: 'Password',
80 any: 'any',
81 thirdparty: 'Or connect with',
82 thirdpartyTips: 'Can not be simulated on local, so please combine you own business simulation! ! !'
83 },
84 documentation: {
85 documentation: 'Documentation',
86 github: 'Github Repository'
87 },
88 permission: {
89 addRole: 'New Role',
90 editPermission: 'Edit',
91 roles: 'Your roles',
92 switchRoles: 'Switch roles',
93 tips: 'In some cases, using v-permission will have no effect. For example: Element-UI el-tab or el-table-column and other scenes that dynamically render dom. You can only do this with v-if.',
94 delete: 'Delete',
95 confirm: 'Confirm',
96 cancel: 'Cancel'
97 },
98 guide: {
99 description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ',
100 button: 'Show Guide'
101 },
102 components: {
103 documentation: 'Documentation',
104 tinymceTips: 'Rich text is a core feature of the management backend, but at the same time it is a place with lots of pits. In the process of selecting rich texts, I also took a lot of detours. The common rich texts on the market have been basically used, and I finally chose Tinymce. See the more detailed rich text comparison and introduction.',
105 dropzoneTips: 'Because my business has special needs, and has to upload images to qiniu, so instead of a third party, I chose encapsulate it by myself. It is very simple, you can see the detail code in @/components/Dropzone.',
106 stickyTips: 'when the page is scrolled to the preset position will be sticky on the top.',
107 backToTopTips1: 'When the page is scrolled to the specified position, the Back to Top button appears in the lower right corner',
108 backToTopTips2: 'You can customize the style of the button, show / hide, height of appearance, height of the return. If you need a text prompt, you can use element-ui el-tooltip elements externally',
109 imageUploadTips: 'Since I was using only the vue@1 version, and it is not compatible with mockjs at the moment, I modified it myself, and if you are going to use it, it is better to use official version.'
110 },
111 table: {
112 dynamicTips1: 'Fixed header, sorted by header order',
113 dynamicTips2: 'Not fixed header, sorted by click order',
114 dragTips1: 'The default order',
115 dragTips2: 'The after dragging order',
116 title: 'Title',
117 importance: 'Imp',
118 type: 'Type',
119 remark: 'Remark',
120 search: 'Search',
121 add: 'Add',
122 export: 'Export',
123 reviewer: 'reviewer',
124 id: 'ID',
125 date: 'Date',
126 author: 'Author',
127 readings: 'Readings',
128 status: 'Status',
129 actions: 'Actions',
130 edit: 'Edit',
131 publish: 'Publish',
132 draft: 'Draft',
133 delete: 'Delete',
134 cancel: 'Cancel',
135 confirm: 'Confirm'
136 },
137 example: {
138 warning: 'Creating and editing pages cannot be cached by keep-alive because keep-alive include does not currently support caching based on routes, so it is currently cached based on component name. If you want to achieve a similar caching effect, you can use a browser caching scheme such as localStorage. Or do not use keep-alive include to cache all pages directly. See details'
139 },
140 errorLog: {
141 tips: 'Please click the bug icon in the upper right corner',
142 description: 'Now the management system are basically the form of the spa, it enhances the user experience, but it also increases the possibility of page problems, a small negligence may lead to the entire page deadlock. Fortunately Vue provides a way to catch handling exceptions, where you can handle errors or report exceptions.',
143 documentation: 'Document introduction'
144 },
145 excel: {
146 export: 'Export',
147 selectedExport: 'Export Selected Items',
148 placeholder: 'Please enter the file name (default excel-list)'
149 },
150 zip: {
151 export: 'Export',
152 placeholder: 'Please enter the file name (default file)'
153 },
154 pdf: {
155 tips: 'Here we use window.print() to implement the feature of downloading PDF.'
156 },
157 theme: {
158 change: 'Change Theme',
159 documentation: 'Theme documentation',
160 tips: 'Tips: It is different from the theme-pick on the navbar is two different skinning methods, each with different application scenarios. Refer to the documentation for details.'
161 },
162 tagsView: {
163 refresh: 'Refresh',
164 close: 'Close',
165 closeOthers: 'Close Others',
166 closeAll: 'Close All'
167 },
168 settings: {
169 title: 'Page style setting',
170 theme: 'Theme Color',
171 tagsView: 'Open Tags-View',
172 fixedHeader: 'Fixed Header',
173 sidebarLogo: 'Sidebar Logo'
174 }
175 }
176
File was created 1 export default {
2 route: {
3 dashboard: 'Panel de control',
4 documentation: 'Documentación',
5 guide: 'Guía',
6 permission: 'Permisos',
7 rolePermission: 'Permisos de rol',
8 pagePermission: 'Permisos de la página',
9 directivePermission: 'Permisos de la directiva',
10 icons: 'Iconos',
11 components: 'Componentes',
12 tinymce: 'Tinymce',
13 markdown: 'Markdown',
14 jsonEditor: 'Editor JSON',
15 dndList: 'Lista Dnd',
16 splitPane: 'Panel dividido',
17 avatarUpload: 'Subir avatar',
18 dropzone: 'Subir ficheros',
19 sticky: 'Sticky',
20 countTo: 'CountTo',
21 componentMixin: 'Mixin',
22 backToTop: 'Ir arriba',
23 dragDialog: 'Drag Dialog',
24 dragSelect: 'Drag Select',
25 dragKanban: 'Drag Kanban',
26 charts: 'Gráficos',
27 keyboardChart: 'Keyboard Chart',
28 lineChart: 'Gráfico de líneas',
29 mixChart: 'Mix Chart',
30 example: 'Ejemplo',
31 nested: 'Rutas anidadass',
32 menu1: 'Menu 1',
33 'menu1-1': 'Menu 1-1',
34 'menu1-2': 'Menu 1-2',
35 'menu1-2-1': 'Menu 1-2-1',
36 'menu1-2-2': 'Menu 1-2-2',
37 'menu1-3': 'Menu 1-3',
38 menu2: 'Menu 2',
39 Table: 'Tabla',
40 dynamicTable: 'Tabla dinámica',
41 dragTable: 'Arrastrar tabla',
42 inlineEditTable: 'Editor',
43 complexTable: 'Complex Table',
44 tab: 'Pestaña',
45 form: 'Formulario',
46 createArticle: 'Crear artículo',
47 editArticle: 'Editar artículo',
48 articleList: 'Listado de artículos',
49 errorPages: 'Páginas de error',
50 page401: '401',
51 page404: '404',
52 errorLog: 'Registro de errores',
53 excel: 'Excel',
54 exportExcel: 'Exportar a Excel',
55 selectExcel: 'Export seleccionado',
56 mergeHeader: 'Merge Header',
57 uploadExcel: 'Subir Excel',
58 zip: 'Zip',
59 pdf: 'PDF',
60 exportZip: 'Exportar a Zip',
61 theme: 'Tema',
62 clipboardDemo: 'Clipboard',
63 i18n: 'I18n',
64 externalLink: 'Enlace externo',
65 profile: 'Profile'
66 },
67 navbar: {
68 logOut: 'Salir',
69 dashboard: 'Panel de control',
70 github: 'Github',
71 theme: 'Tema',
72 size: 'Tamaño global',
73 profile: 'Profile'
74 },
75 login: {
76 title: 'Formulario de acceso',
77 logIn: 'Acceso',
78 username: 'Usuario',
79 password: 'Contraseña',
80 any: 'nada',
81 thirdparty: 'Conectar con',
82 thirdpartyTips: 'No se puede simular en local, así que combine su propia simulación de negocios. ! !'
83 },
84 documentation: {
85 documentation: 'Documentación',
86 github: 'Repositorio Github'
87 },
88 permission: {
89 addRole: 'Nuevo rol',
90 editPermission: 'Permiso de edición',
91 roles: 'Tus permisos',
92 switchRoles: 'Cambiar permisos',
93 tips: 'In some cases it is not suitable to use v-permission, such as element Tab component or el-table-column and other asynchronous rendering dom cases which can only be achieved by manually setting the v-if.',
94 delete: 'Borrar',
95 confirm: 'Confirmar',
96 cancel: 'Cancelar'
97 },
98 guide: {
99 description: 'The guide page is useful for some people who entered the project for the first time. You can briefly introduce the features of the project. Demo is based on ',
100 button: 'Ver guía'
101 },
102 components: {
103 documentation: 'Documentación',
104 tinymceTips: 'Rich text editor is a core part of management system, but at the same time is a place with lots of problems. In the process of selecting rich texts, I also walked a lot of detours. The common rich text editors in the market are basically used, and the finally chose Tinymce. See documentation for more detailed rich text editor comparisons and introductions.',
105 dropzoneTips: 'Because my business has special needs, and has to upload images to qiniu, so instead of a third party, I chose encapsulate it by myself. It is very simple, you can see the detail code in @/components/Dropzone.',
106 stickyTips: 'when the page is scrolled to the preset position will be sticky on the top.',
107 backToTopTips1: 'When the page is scrolled to the specified position, the Back to Top button appears in the lower right corner',
108 backToTopTips2: 'You can customize the style of the button, show / hide, height of appearance, height of the return. If you need a text prompt, you can use element-ui el-tooltip elements externally',
109 imageUploadTips: 'Since I was using only the vue@1 version, and it is not compatible with mockjs at the moment, I modified it myself, and if you are going to use it, it is better to use official version.'
110 },
111 table: {
112 dynamicTips1: 'Fixed header, sorted by header order',
113 dynamicTips2: 'Not fixed header, sorted by click order',
114 dragTips1: 'Orden por defecto',
115 dragTips2: 'The after dragging order',
116 title: 'Título',
117 importance: 'Importancia',
118 type: 'Tipo',
119 remark: 'Remark',
120 search: 'Buscar',
121 add: 'Añadir',
122 export: 'Exportar',
123 reviewer: 'reviewer',
124 id: 'ID',
125 date: 'Fecha',
126 author: 'Autor',
127 readings: 'Lector',
128 status: 'Estado',
129 actions: 'Acciones',
130 edit: 'Editar',
131 publish: 'Publicar',
132 draft: 'Draft',
133 delete: 'Eliminar',
134 cancel: 'Cancelar',
135 confirm: 'Confirmar'
136 },
137 example: {
138 warning: 'Creating and editing pages cannot be cached by keep-alive because keep-alive include does not currently support caching based on routes, so it is currently cached based on component name. If you want to achieve a similar caching effect, you can use a browser caching scheme such as localStorage. Or do not use keep-alive include to cache all pages directly. See details'
139 },
140 errorLog: {
141 tips: 'Please click the bug icon in the upper right corner',
142 description: 'Now the management system are basically the form of the spa, it enhances the user experience, but it also increases the possibility of page problems, a small negligence may lead to the entire page deadlock. Fortunately Vue provides a way to catch handling exceptions, where you can handle errors or report exceptions.',
143 documentation: 'Documento de introducción'
144 },
145 excel: {
146 export: 'Exportar',
147 selectedExport: 'Exportar seleccionados',
148 placeholder: 'Por favor escribe un nombre de fichero'
149 },
150 zip: {
151 export: 'Exportar',
152 placeholder: 'Por favor escribe un nombre de fichero'
153 },
154 pdf: {
155 tips: 'Here we use window.print() to implement the feature of downloading pdf.'
156 },
157 theme: {
158 change: 'Cambiar tema',
159 documentation: 'Documentación del tema',
160 tips: 'Tips: It is different from the theme-pick on the navbar is two different skinning methods, each with different application scenarios. Refer to the documentation for details.'
161 },
162 tagsView: {
163 refresh: 'Actualizar',
164 close: 'Cerrar',
165 closeOthers: 'Cerrar otros',
166 closeAll: 'Cerrar todos'
167 },
168 settings: {
169 title: 'Page style setting',
170 theme: 'Theme Color',
171 tagsView: 'Open Tags-View',
172 fixedHeader: 'Fixed Header',
173 sidebarLogo: 'Sidebar Logo'
174 }
175 }
176
src/lang/index.js
File was created 1 import Vue from 'vue'
2 import VueI18n from 'vue-i18n'
3 import Cookies from 'js-cookie'
4 import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui lang
5 import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui lang
6 import elementEsLocale from 'element-ui/lib/locale/lang/es'// element-ui lang
7 import elementJaLocale from 'element-ui/lib/locale/lang/ja'// element-ui lang
8 import enLocale from './en'
9 import zhLocale from './zh'
10 import esLocale from './es'
11 import jaLocale from './ja'
12
13 Vue.use(VueI18n)
14
15 const messages = {
16 en: {
17 ...enLocale,
18 ...elementEnLocale
19 },
20 zh: {
21 ...zhLocale,
22 ...elementZhLocale
23 },
24 es: {
25 ...esLocale,
26 ...elementEsLocale
27 },
28 ja: {
29 ...jaLocale,
30 ...elementJaLocale
31 }
32 }
33 export function getLanguage() {
34 const chooseLanguage = Cookies.get('language')
35 if (chooseLanguage) return chooseLanguage
36
37 // if has not choose language
38 const language = (navigator.language || navigator.browserLanguage).toLowerCase()
39 const locales = Object.keys(messages)
40 for (const locale of locales) {
41 if (language.indexOf(locale) > -1) {
42 return locale
43 }
44 }
45 return 'en'
46 }
47 const i18n = new VueI18n({
48 // set locale
49 // options: en | zh | es
50 locale: getLanguage(),
51 // set locale messages
52 messages
53 })
54
55 export default i18n
56
File was created 1 export default {
2 route: {
3 dashboard: 'トップ',
4 documentation: 'ドキュメント',
5 guide: 'ガイド',
6 permission: '権限',
7 rolePermission: '権限ロール',
8 pagePermission: 'ページ権限',
9 directivePermission: 'ディレクティブ権限',
10 icons: 'アイコン',
11 components: 'コンポーネント',
12 tinymce: 'TinyMCE',
13 markdown: 'Markdown',
14 jsonEditor: 'JSON Editor',
15 dndList: 'Drag-And-Drop',
16 splitPane: 'パネル',
17 avatarUpload: 'アバターアップロード',
18 dropzone: 'Dropzone',
19 sticky: 'Sticky',
20 countTo: 'Count To',
21 componentMixin: 'コンポーネントMixin',
22 backToTop: 'BackToTop',
23 dragDialog: 'Drag Dialog',
24 dragSelect: 'Drag Select',
25 dragKanban: 'Drag 看板',
26 charts: 'チャート',
27 keyboardChart: 'Keyboardチャート',
28 lineChart: 'Lineチャート',
29 mixChart: 'Mixチャート',
30 example: 'Example',
31 nested: 'Nested Routes',
32 menu1: 'メニュー1',
33 'menu1-1': 'メニュー 1-1',
34 'menu1-2': 'メニュー 1-2',
35 'menu1-2-1': 'メニュー 1-2-1',
36 'menu1-2-2': 'メニュー 1-2-2',
37 'menu1-3': 'メニュー 1-3',
38 menu2: 'メニュー 2',
39 Table: 'Table',
40 dynamicTable: '可変 Table',
41 dragTable: 'Drag Table',
42 inlineEditTable: 'Inline Edit Table',
43 complexTable: 'Complex Table',
44 tab: 'Tab',
45 form: 'フォーム',
46 createArticle: '投稿作成',
47 editArticle: '投稿編集',
48 articleList: '投稿リスト',
49 errorPages: 'エラーページ',
50 page401: '401',
51 page404: '404',
52 errorLog: 'エラーログ',
53 excel: 'Excel',
54 exportExcel: '一括エクスポート',
55 selectExcel: '複数選択エクスポート',
56 mergeHeader: 'ヘッダーマージ',
57 uploadExcel: 'アップロード',
58 zip: 'Zip',
59 pdf: 'PDF',
60 exportZip: 'Export Zip',
61 theme: 'テーマ変更',
62 clipboardDemo: 'Clipboard',
63 i18n: '多言語',
64 externalLink: '外部リンク',
65 profile: 'プロフィール'
66 },
67 navbar: {
68 dashboard: 'トップ',
69 github: 'GitHub',
70 logOut: 'ログアウト',
71 profile: 'プロフィール',
72 theme: 'テーマ変更',
73 size: '画面サイズ'
74 },
75 login: {
76 title: 'ユーザログイン',
77 logIn: 'ログイン',
78 username: 'ユーザ名',
79 password: 'パスワード',
80 any: 'password',
81 thirdparty: '外部IDでログイン',
82 thirdpartyTips: 'ローカル環境ではログインできません。実装が必要です。'
83 },
84 documentation: {
85 documentation: 'ドキュメント',
86 github: 'Github Link'
87 },
88 permission: {
89 addRole: 'ロール追加',
90 editPermission: 'ロール変更',
91 roles: 'ロール',
92 switchRoles: 'ロール切替',
93 tips: 'v-permissionは使えない時があります。例えば: Element-UI の el-tab、 el-table-column 及び他の dom。v-ifを使う必要があります。',
94 delete: '削除',
95 confirm: '確認',
96 cancel: 'キャンセル'
97 },
98 guide: {
99 description: 'ガイドは各機能の説明です。',
100 button: 'ガイドを見る'
101 },
102 components: {
103 documentation: 'ドキュメント',
104 tinymceTips: 'tinymceは管理画面に重要な機能ですが、その同時に落とし穴がありあす。tinymceを使う道のりが大変でした。Tinymceを使う時に各自のプロジェクト状況で判断が必要です。ドキュメントはこちら',
105 dropzoneTips: 'Third partyのパッケージを使わず、独自の実装しています。詳細は @/components/Dropzone',
106 stickyTips: 'ページの指定位置へスクロールした場合、表示されます。',
107 backToTopTips1: 'トップへスクロールが表示されます。',
108 backToTopTips2: 'ボタンのスタイルはカスタマイズできます。例えば、show/hide、height、position。 またはElementのel-tooltipを使って、ツールチップを実装できます。',
109 imageUploadTips: 'mockjsは使えないため、カスタマイズしています。公式の最新バージョンを使ってください。'
110 },
111 table: {
112 dynamicTips1: '先頭は固定、最後に追加',
113 dynamicTips2: '戦後に追加せず、指定列に追加',
114 dragTips1: 'デフォルト順番',
115 dragTips2: 'Drag後の順番',
116 title: 'タイトル',
117 importance: '重要',
118 type: 'タイプ',
119 remark: '評価',
120 search: '検索',
121 add: '追加',
122 export: 'エクスポート',
123 reviewer: 'レビュアー',
124 id: '番号',
125 date: '日時',
126 author: '作成者',
127 readings: '閲覧数',
128 status: 'ステータス',
129 actions: '操作',
130 edit: '編集',
131 publish: '公開',
132 draft: '下書き',
133 delete: 'キャンセル',
134 cancel: 'キャンセル',
135 confirm: '確認'
136 },
137 example: {
138 warning: '新規作成と編集画面は keep-alive を使えないです。keep-alive の include はrouteのキャッシュは使えないです。そのため、component name を使ってキャッシュさせるようにします。このようなキャッシュ機能を作りたい場合,localStorageを使う手があります。もしくは keep-alive の includeを使って、全ページキャッシュする方法はあります。'
139 },
140 errorLog: {
141 tips: '右上のbugアイコンをクリックしてください。',
142 description: '管理画面はspaを使う場合が多い、ユーザ体現向上はできますが、想定外エラーが発生する場合があります。Vueはそのエラーハンドリング機能を提供し、エラーレポートができます。',
143 documentation: 'ドキュメント'
144 },
145 excel: {
146 export: 'エクスポート',
147 selectedExport: 'エクスポート対象を選択してください。',
148 placeholder: 'ファイル名を入力してください。'
149 },
150 zip: {
151 export: 'エクスポート',
152 placeholder: 'ファイル名を入力してください。'
153 },
154 pdf: {
155 tips: 'window.print() を使ってPDFダウンロードしています。'
156 },
157 theme: {
158 change: 'テーマ切替',
159 documentation: 'ドキュメント',
160 tips: 'Tips: テーマの切り替え方法はnavbarのtheme-pickと異なります、使い方はドキュメントを確認してください。'
161 },
162 tagsView: {
163 refresh: '更新',
164 close: '閉じる',
165 closeOthers: 'その他閉じる',
166 closeAll: 'すべて閉じる'
167 },
168 settings: {
169 title: 'システムテーマ',
170 theme: 'テーマ色',
171 tagsView: 'Tags-View 開く',
172 fixedHeader: 'Fixed Header',
173 sidebarLogo: 'Sidebar Logo'
174 }
175 }
176
File was created 1 export default {
2 route: {
3 dashboard: '首页',
4 documentation: '文档',
5 guide: '引导页',
6 permission: '权限测试页',
7 rolePermission: '角色权限',
8 pagePermission: '页面权限',
9 directivePermission: '指令权限',
10 icons: '图标',
11 components: '组件',
12 tinymce: '富文本编辑器',
13 markdown: 'Markdown',
14 jsonEditor: 'JSON 编辑器',
15 dndList: '列表拖拽',
16 splitPane: 'Splitpane',
17 avatarUpload: '头像上传',
18 dropzone: 'Dropzone',
19 sticky: 'Sticky',
20 countTo: 'Count To',
21 componentMixin: '小组件',
22 backToTop: '返回顶部',
23 dragDialog: '拖拽 Dialog',
24 dragSelect: '拖拽 Select',
25 dragKanban: '可拖拽看板',
26 charts: '图表',
27 keyboardChart: '键盘图表',
28 lineChart: '折线图',
29 mixChart: '混合图表',
30 example: '综合实例',
31 nested: '路由嵌套',
32 menu1: '菜单1',
33 'menu1-1': '菜单 1-1',
34 'menu1-2': '菜单 1-2',
35 'menu1-2-1': '菜单 1-2-1',
36 'menu1-2-2': '菜单 1-2-2',
37 'menu1-3': '菜单 1-3',
38 menu2: '菜单 2',
39 Table: 'Table',
40 dynamicTable: '动态 Table',
41 dragTable: '拖拽 Table',
42 inlineEditTable: 'Table 内编辑',
43 complexTable: '综合 Table',
44 tab: 'Tab',
45 form: '表单',
46 createArticle: '创建文章',
47 editArticle: '编辑文章',
48 articleList: '文章列表',
49 errorPages: '错误页面',
50 page401: '401',
51 page404: '404',
52 errorLog: '错误日志',
53 excel: 'Excel',
54 exportExcel: '导出 Excel',
55 selectExcel: '导出 已选择项',
56 mergeHeader: '导出 多级表头',
57 uploadExcel: '上传 Excel',
58 zip: 'Zip',
59 pdf: 'PDF',
60 exportZip: 'Export Zip',
61 theme: '换肤',
62 clipboardDemo: 'Clipboard',
63 i18n: '国际化',
64 externalLink: '外链',
65 profile: '个人中心'
66 },
67 navbar: {
68 dashboard: '首页',
69 github: '项目地址',
70 logOut: '退出登录',
71 profile: '个人中心',
72 theme: '换肤',
73 size: '布局大小'
74 },
75 login: {
76 title: '系统登录',
77 logIn: '登录',
78 username: '账号',
79 password: '密码',
80 any: '随便填',
81 thirdparty: '第三方登录',
82 thirdpartyTips: '本地不能模拟,请结合自己业务进行模拟!!!'
83 },
84 documentation: {
85 documentation: '文档',
86 github: 'Github 地址'
87 },
88 permission: {
89 addRole: '新增角色',
90 editPermission: '编辑权限',
91 roles: '你的权限',
92 switchRoles: '切换权限',
93 tips: '在某些情况下,不适合使用 v-permission。例如:Element-UI 的 el-tab 或 el-table-column 以及其它动态渲染 dom 的场景。你只能通过手动设置 v-if 来实现。',
94 delete: '删除',
95 confirm: '确定',
96 cancel: '取消'
97 },
98 guide: {
99 description: '引导页对于一些第一次进入项目的人很有用,你可以简单介绍下项目的功能。本 Demo 是基于',
100 button: '打开引导'
101 },
102 components: {
103 documentation: '文档',
104 tinymceTips: '富文本是管理后台一个核心的功能,但同时又是一个有很多坑的地方。在选择富文本的过程中我也走了不少的弯路,市面上常见的富文本都基本用过了,最终权衡了一下选择了Tinymce。更详细的富文本比较和介绍见',
105 dropzoneTips: '由于我司业务有特殊需求,而且要传七牛 所以没用第三方,选择了自己封装。代码非常的简单,具体代码你可以在这里看到 @/components/Dropzone',
106 stickyTips: '当页面滚动到预设的位置会吸附在顶部',
107 backToTopTips1: '页面滚动到指定位置会在右下角出现返回顶部按钮',
108 backToTopTips2: '可自定义按钮的样式、show/hide、出现的高度、返回的位置 如需文字提示,可在外部使用Element的el-tooltip元素',
109 imageUploadTips: '由于我在使用时它只有vue@1版本,而且和mockjs不兼容,所以自己改造了一下,如果大家要使用的话,优先还是使用官方版本。'
110 },
111 table: {
112 dynamicTips1: '固定表头, 按照表头顺序排序',
113 dynamicTips2: '不固定表头, 按照点击顺序排序',
114 dragTips1: '默认顺序',
115 dragTips2: '拖拽后顺序',
116 title: '标题',
117 importance: '重要性',
118 type: '类型',
119 remark: '点评',
120 search: '搜索',
121 add: '添加',
122 export: '导出',
123 reviewer: '审核人',
124 id: '序号',
125 date: '时间',
126 author: '作者',
127 readings: '阅读数',
128 status: '状态',
129 actions: '操作',
130 edit: '编辑',
131 publish: '发布',
132 draft: '草稿',
133 delete: '删除',
134 cancel: '取 消',
135 confirm: '确 定'
136 },
137 example: {
138 warning: '创建和编辑页面是不能被 keep-alive 缓存的,因为keep-alive 的 include 目前不支持根据路由来缓存,所以目前都是基于 component name 来进行缓存的。如果你想类似的实现缓存效果,可以使用 localStorage 等浏览器缓存方案。或者不要使用 keep-alive 的 include,直接缓存所有页面。详情见'
139 },
140 errorLog: {
141 tips: '请点击右上角bug小图标',
142 description: '现在的管理后台基本都是spa的形式了,它增强了用户体验,但同时也会增加页面出问题的可能性,可能一个小小的疏忽就导致整个页面的死锁。好在 Vue 官网提供了一个方法来捕获处理异常,你可以在其中进行错误处理或者异常上报。',
143 documentation: '文档介绍'
144 },
145 excel: {
146 export: '导出',
147 selectedExport: '导出已选择项',
148 placeholder: '请输入文件名(默认excel-list)'
149 },
150 zip: {
151 export: '导出',
152 placeholder: '请输入文件名(默认file)'
153 },
154 pdf: {
155 tips: '这里使用 window.print() 来实现下载pdf的功能'
156 },
157 theme: {
158 change: '换肤',
159 documentation: '换肤文档',
160 tips: 'Tips: 它区别于 navbar 上的 theme-pick, 是两种不同的换肤方法,各自有不同的应用场景,具体请参考文档。'
161 },
162 tagsView: {
163 refresh: '刷新',
164 close: '关闭',
165 closeOthers: '关闭其它',
166 closeAll: '关闭所有'
167 },
168 settings: {
169 title: '系统布局配置',
170 theme: '主题色',
171 tagsView: '开启 Tags-View',
172 fixedHeader: '固定 Header',
173 sidebarLogo: '侧边栏 Logo'
174 }
175 }
176
src/layout/components/AppMain.vue
1 <template> 1 <template>
2 <section class="app-main"> 2 <section class="app-main">
3 <transition name="fade-transform" mode="out-in"> 3 <transition name="fade-transform" mode="out-in">
4 <router-view :key="key" /> 4 <keep-alive :include="cachedViews">
5 <router-view :key="key" />
6 </keep-alive>
5 </transition> 7 </transition>
6 </section> 8 </section>
7 </template> 9 </template>
8 10
9 <script> 11 <script>
10 export default { 12 export default {
11 name: 'AppMain', 13 name: 'AppMain',
12 computed: { 14 computed: {
13 // key() { 15 cachedViews() {
14 // return this.$route.name !== undefined? this.$route.name + +new Date(): this.$route + +new Date() 16 return this.$store.state.tagsView.cachedViews
15 // } 17 },
16 key() { 18 key() {
17 return this.$route.path 19 return this.$route.path
18 } 20 }
19 } 21 }
20 } 22 }
21 </script> 23 </script>
22 24
23 <style scoped> 25 <style lang="scss" scoped>
24 .app-main { 26 .app-main {
25 /*50 = navbar */ 27 /* 50= navbar 50 */
26 min-height: calc(100vh - 50px); 28 min-height: calc(100vh - 50px);
27 width: 100%; 29 width: 100%;
28 position: relative; 30 position: relative;
29 overflow: hidden; 31 overflow: hidden;
30 } 32 }
33
31 .fixed-header+.app-main { 34 .fixed-header+.app-main {
32 padding-top: 50px; 35 padding-top: 50px;
33 } 36 }
37
38 .hasTagsView {
39 .app-main {
40 /* 84 = navbar + tags-view = 50 + 34 */
41 min-height: calc(100vh - 84px);
42 }
43
44 .fixed-header+.app-main {
45 padding-top: 84px;
46 }
47 }
34 </style> 48 </style>
35 49
36 <style lang="scss"> 50 <style lang="scss">
37 // fix css style bug in open el-dialog 51 // fix css style bug in open el-dialog
38 .el-popup-parent--hidden { 52 .el-popup-parent--hidden {
39 .fixed-header { 53 .fixed-header {
40 padding-right: 15px; 54 padding-right: 15px;
41 } 55 }
42 } 56 }
43 </style> 57 </style>
44 58
src/layout/components/Navbar.vue
1 <template> 1 <template>
2 <div class="navbar"> 2 <div class="navbar">
3 <hamburger 3 <hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
4 :is-active="sidebar.opened"
5 class="hamburger-container"
6 @toggleClick="toggleSideBar"
7 />
8 4
9 <breadcrumb class="breadcrumb-container" /> 5 <breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
10 6
11 <div class="right-menu"> 7 <div class="right-menu">
12 <el-menu 8 <template v-if="device!=='mobile'">
13 :default-active="activeIndex" 9 <search id="header-search" class="right-menu-item" />
14 class="el-menu-demo" 10
15 mode="horizontal" 11 <error-log class="errLog-container right-menu-item hover-effect" />
16 @select="handleSelect" 12
17 > 13 <screenfull id="screenfull" class="right-menu-item hover-effect" />
18 <el-menu-item index="1"> 14
19 <i class="el-icon-bell"></i>通知中心 15 <el-tooltip :content="$t('navbar.size')" effect="dark" placement="bottom">
20 <el-badge class="mark" :value="12" /> 16 <size-select id="size-select" class="right-menu-item hover-effect" />
21 </el-menu-item> 17 </el-tooltip>
22 <el-submenu index="2"> 18
23 <template slot="title"> 19 <lang-select class="right-menu-item hover-effect" />
24 <i class="el-icon-custom"></i>个人设置 20
25 </template> 21 </template>
26 <el-menu-item index="2-1">选项1</el-menu-item> 22
27 <el-menu-item index="2-2">选项2</el-menu-item> 23 <el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
28 <el-menu-item index="2-3">选项3</el-menu-item> 24 <div class="avatar-wrapper">
29 </el-submenu> 25 <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar">
30 <el-dropdown class="avatar-container" trigger="click"> 26 <i class="el-icon-caret-bottom" />
31 <div class="avatar-wrapper"> 27 </div>
32 <img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar" /> 28 <el-dropdown-menu slot="dropdown">
33 <i class="el-icon-caret-bottom" /> 29 <router-link to="/profile/index">
34 </div> 30 <el-dropdown-item>
35 <el-dropdown-menu slot="dropdown" class="user-dropdown"> 31 {{ $t('navbar.profile') }}
36 <router-link to="/">
37 <el-dropdown-item>Home</el-dropdown-item>
38 </router-link>
39 <router-link to="/seting">
40 <el-dropdown-item>个人设置</el-dropdown-item>
41 </router-link>
42 <!-- <a target="_blank" href="https://github.com/PanJiaChen/vue-admin-template/">
43 <el-dropdown-item>Github</el-dropdown-item>
44 </a>-->
45 <!-- <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
46 <el-dropdown-item>Docs</el-dropdown-item>
47 </a>-->
48 <el-dropdown-item divided @click.native="logout">
49 <span style="display:block;">退出系统</span>
50 </el-dropdown-item> 32 </el-dropdown-item>
51 </el-dropdown-menu> 33 </router-link>
52 </el-dropdown> 34 <router-link to="/">
53 <el-menu-item index="3" disabled>ddd</el-menu-item> 35 <el-dropdown-item>
54 <el-menu-item index="4"> 36 {{ $t('navbar.dashboard') }}
55 <a href="https://glass.xiuyetang.com" target="_blank">跳到外部链接</a> 37 </el-dropdown-item>
56 </el-menu-item> 38 </router-link>
57 </el-menu> 39 <a target="_blank" href="https://github.com/PanJiaChen/vue-element-admin/">
40 <el-dropdown-item>
41 {{ $t('navbar.github') }}
42 </el-dropdown-item>
43 </a>
44 <a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
45 <el-dropdown-item>Docs</el-dropdown-item>
46 </a>
47 <el-dropdown-item divided @click.native="logout">
48 <span style="display:block;">{{ $t('navbar.logOut') }}</span>
49 </el-dropdown-item>
50 </el-dropdown-menu>
51 </el-dropdown>
58 </div> 52 </div>
59 </div> 53 </div>
60 </template> 54 </template>
61 55
62 <script> 56 <script>
63 import { mapGetters } from "vuex"; 57 import { mapGetters } from 'vuex'
64 import Breadcrumb from "@/components/Breadcrumb"; 58 import Breadcrumb from '@/components/Breadcrumb'
65 import Hamburger from "@/components/Hamburger"; 59 import Hamburger from '@/components/Hamburger'
60 import ErrorLog from '@/components/ErrorLog'
61 import Screenfull from '@/components/Screenfull'
62 import SizeSelect from '@/components/SizeSelect'
63 import LangSelect from '@/components/LangSelect'
64 import Search from '@/components/HeaderSearch'
66 65
67 export default { 66 export default {
68 components: { 67 components: {
69 Breadcrumb, 68 Breadcrumb,
70 Hamburger 69 Hamburger,
70 ErrorLog,
71 Screenfull,
72 SizeSelect,
73 LangSelect,
74 Search
71 }, 75 },
72 computed: { 76 computed: {
73 ...mapGetters(["sidebar", "avatar"]) 77 ...mapGetters([
78 'sidebar',
79 'avatar',
80 'device'
81 ])
74 }, 82 },
75 methods: { 83 methods: {
76 toggleSideBar() { 84 toggleSideBar() {
77 this.$store.dispatch("app/toggleSideBar"); 85 this.$store.dispatch('app/toggleSideBar')
78 }, 86 },
79 async logout() { 87 async logout() {
80 await this.$store.dispatch("user/logout"); 88 await this.$store.dispatch('user/logout')
81 this.$router.push(`/login?redirect=${this.$route.fullPath}`); 89 this.$router.push(`/login?redirect=${this.$route.fullPath}`)
82 } 90 }
83 } 91 }
84 }; 92 }
85 </script> 93 </script>
86 94
87 <style lang="scss" scoped> 95 <style lang="scss" scoped>
88 .item {
89 margin-top: 10px;
90 margin-right: 20px;
91 }
92 .navbar { 96 .navbar {
93 height: 50px; 97 height: 50px;
94 overflow: hidden; 98 overflow: hidden;
95 position: relative; 99 position: relative;
96 background: #fff; 100 background: #fff;
97 box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); 101 box-shadow: 0 1px 4px rgba(0,21,41,.08);
98 102
99 .hamburger-container { 103 .hamburger-container {
100 line-height: 46px; 104 line-height: 46px;
101 height: 100%; 105 height: 100%;
102 float: left; 106 float: left;
103 cursor: pointer; 107 cursor: pointer;
104 transition: background 0.3s; 108 transition: background .3s;
105 -webkit-tap-highlight-color: transparent; 109 -webkit-tap-highlight-color:transparent;
106 110
107 &:hover { 111 &:hover {
108 background: rgba(0, 0, 0, 0.025); 112 background: rgba(0, 0, 0, .025)
109 } 113 }
110 } 114 }
111 115
112 .breadcrumb-container { 116 .breadcrumb-container {
113 float: left; 117 float: left;
114 } 118 }
115 119
120 .errLog-container {
121 display: inline-block;
122 vertical-align: top;
123 }
124
116 .right-menu { 125 .right-menu {
117 float: right; 126 float: right;
118 height: 100%; 127 height: 100%;
119 line-height: 50px; 128 line-height: 50px;
120 129
121 &:focus { 130 &:focus {
122 outline: none; 131 outline: none;
123 } 132 }
124 133
125 .right-menu-item { 134 .right-menu-item {
126 display: inline-block; 135 display: inline-block;
127 padding: 0 8px; 136 padding: 0 8px;
128 height: 100%; 137 height: 100%;
129 font-size: 18px; 138 font-size: 18px;
130 color: #5a5e66; 139 color: #5a5e66;
131 vertical-align: text-bottom; 140 vertical-align: text-bottom;
132 141
133 &.hover-effect { 142 &.hover-effect {
134 cursor: pointer; 143 cursor: pointer;
135 transition: background 0.3s; 144 transition: background .3s;
136 145
137 &:hover { 146 &:hover {
138 background: rgba(0, 0, 0, 0.025); 147 background: rgba(0, 0, 0, .025)
139 } 148 }
140 } 149 }
141 } 150 }
142 151
143 .avatar-container { 152 .avatar-container {
144 margin-right: 30px; 153 margin-right: 30px;
145 154
146 .avatar-wrapper { 155 .avatar-wrapper {
147 margin-top: 5px; 156 margin-top: 5px;
src/layout/components/Settings/index.vue
File was created 1 <template>
2 <div class="drawer-container">
3 <div>
4 <h3 class="drawer-title">{{ $t('settings.title') }}</h3>
5
6 <div class="drawer-item">
7 <span>{{ $t('settings.theme') }}</span>
8 <theme-picker style="float: right;height: 26px;margin: -3px 8px 0 0;" @change="themeChange" />
9 </div>
10
11 <div class="drawer-item">
12 <span>{{ $t('settings.tagsView') }}</span>
13 <el-switch v-model="tagsView" class="drawer-switch" />
14 </div>
15
16 <div class="drawer-item">
17 <span>{{ $t('settings.fixedHeader') }}</span>
18 <el-switch v-model="fixedHeader" class="drawer-switch" />
19 </div>
20
21 <div class="drawer-item">
22 <span>{{ $t('settings.sidebarLogo') }}</span>
23 <el-switch v-model="sidebarLogo" class="drawer-switch" />
24 </div>
25 <a v-if="isShowJob" href="https://panjiachen.github.io/vue-element-admin-site/zh/job/" target="_blank" class="job-link">
26 <el-alert
27 title="部门目前非常缺人!有兴趣的可以点击了解详情。坐标: 字节跳动"
28 type="success"
29 :closable="false"
30 />
31 </a>
32
33 <div v-if="lang === 'zh'" class="drawer-item">
34 <span>菜单支持拼音搜索</span>
35 <el-switch v-model="supportPinyinSearch" class="drawer-switch" />
36 </div>
37
38 </div>
39 </div>
40 </template>
41
42 <script>
43 import ThemePicker from '@/components/ThemePicker'
44
45 export default {
46 components: { ThemePicker },
47 data() {
48 return {}
49 },
50 computed: {
51 isShowJob() {
52 return this.$store.getters.language === 'zh'
53 },
54 fixedHeader: {
55 get() {
56 return this.$store.state.settings.fixedHeader
57 },
58 set(val) {
59 this.$store.dispatch('settings/changeSetting', {
60 key: 'fixedHeader',
61 value: val
62 })
63 }
64 },
65 tagsView: {
66 get() {
67 return this.$store.state.settings.tagsView
68 },
69 set(val) {
70 this.$store.dispatch('settings/changeSetting', {
71 key: 'tagsView',
72 value: val
73 })
74 }
75 },
76 sidebarLogo: {
77 get() {
78 return this.$store.state.settings.sidebarLogo
79 },
80 set(val) {
81 this.$store.dispatch('settings/changeSetting', {
82 key: 'sidebarLogo',
83 value: val
84 })
85 }
86 },
87 supportPinyinSearch: {
88 get() {
89 return this.$store.state.settings.supportPinyinSearch
90 },
91 set(val) {
92 this.$store.dispatch('settings/changeSetting', {
93 key: 'supportPinyinSearch',
94 value: val
95 })
96 }
97 },
98 lang() {
99 return this.$store.getters.language
100 }
101 },
102 methods: {
103 themeChange(val) {
104 this.$store.dispatch('settings/changeSetting', {
105 key: 'theme',
106 value: val
107 })
108 }
109 }
110 }
111 </script>
112
113 <style lang="scss" scoped>
114 .drawer-container {
115 padding: 24px;
116 font-size: 14px;
117 line-height: 1.5;
118 word-wrap: break-word;
119
120 .drawer-title {
121 margin-bottom: 12px;
122 color: rgba(0, 0, 0, .85);
123 font-size: 14px;
124 line-height: 22px;
125 }
126
127 .drawer-item {
128 color: rgba(0, 0, 0, .65);
129 font-size: 14px;
130 padding: 12px 0;
131 }
132
133 .drawer-switch {
134 float: right
135 }
136
137 .job-link{
138 display: block;
139 position: absolute;
140 width: 100%;
141 left: 0;
142 bottom: 0;
143 }
144 }
145 </style>
146
src/layout/components/Sidebar/FixiOSBug.js 100644 → 100755
1 export default { 1 export default {
2 computed: { 2 computed: {
3 device() { 3 device() {
4 return this.$store.state.app.device 4 return this.$store.state.app.device
5 } 5 }
6 }, 6 },
7 mounted() { 7 mounted() {
8 // In order to fix the click on menu on the ios device will trigger the mouseleave bug 8 // In order to fix the click on menu on the ios device will trigger the mouseleave bug
9 // https://github.com/PanJiaChen/vue-element-admin/issues/1135 9 // https://github.com/PanJiaChen/vue-element-admin/issues/1135
10 this.fixBugIniOS() 10 this.fixBugIniOS()
11 }, 11 },
12 methods: { 12 methods: {
13 fixBugIniOS() { 13 fixBugIniOS() {
14 const $subMenu = this.$refs.subMenu 14 const $subMenu = this.$refs.subMenu
15 if ($subMenu) { 15 if ($subMenu) {
16 const handleMouseleave = $subMenu.handleMouseleave 16 const handleMouseleave = $subMenu.handleMouseleave
17 $subMenu.handleMouseleave = (e) => { 17 $subMenu.handleMouseleave = (e) => {
18 if (this.device === 'mobile') { 18 if (this.device === 'mobile') {
19 return 19 return
20 } 20 }
21 handleMouseleave(e) 21 handleMouseleave(e)
22 } 22 }
23 } 23 }
24 } 24 }
25 } 25 }
26 } 26 }
27 27
src/layout/components/Sidebar/Item.vue 100644 → 100755
1 <script> 1 <script>
2 export default { 2 export default {
3 name: 'MenuItem', 3 name: 'MenuItem',
4 functional: true, 4 functional: true,
5 props: { 5 props: {
6 icon: { 6 icon: {
7 type: String, 7 type: String,
8 default: '' 8 default: ''
9 }, 9 },
10 title: { 10 title: {
11 type: String, 11 type: String,
12 default: '' 12 default: ''
13 } 13 }
14 }, 14 },
15 render(h, context) { 15 render(h, context) {
16 const { icon, title } = context.props 16 const { icon, title } = context.props
17 const vnodes = [] 17 const vnodes = []
18 18
19 if (icon) { 19 if (icon) {
20 vnodes.push(<svg-icon icon-class={icon}/>) 20 vnodes.push(<svg-icon icon-class={icon}/>)
21 } 21 }
22 22
23 if (title) { 23 if (title) {
24 vnodes.push(<span slot='title'>{(title)}</span>) 24 vnodes.push(<span slot='title'>{(title)}</span>)
25 } 25 }
26 return vnodes 26 return vnodes
27 } 27 }
28 } 28 }
29 </script> 29 </script>
30 30
src/layout/components/Sidebar/Link.vue 100644 → 100755
1 1
2 <template> 2 <template>
3 <!-- eslint-disable vue/require-component-is --> 3 <!-- eslint-disable vue/require-component-is -->
4 <component v-bind="linkProps(to)"> 4 <component v-bind="linkProps(to)">
5 <slot /> 5 <slot />
6 </component> 6 </component>
7 </template> 7 </template>
8 8
9 <script> 9 <script>
10 import { isExternal } from '@/utils/validate' 10 import { isExternal } from '@/utils/validate'
11 11
12 export default { 12 export default {
13 props: { 13 props: {
14 to: { 14 to: {
15 type: String, 15 type: String,
16 required: true 16 required: true
17 } 17 }
18 }, 18 },
19 methods: { 19 methods: {
20 linkProps(url) { 20 linkProps(url) {
21 if (isExternal(url)) { 21 if (isExternal(url)) {
22 return { 22 return {
23 is: 'a', 23 is: 'a',
24 href: url, 24 href: url,
25 target: '_blank', 25 target: '_blank',
26 rel: 'noopener' 26 rel: 'noopener'
27 } 27 }
28 } 28 }
29 return { 29 return {
30 is: 'router-link', 30 is: 'router-link',
31 to: url 31 to: url
32 } 32 }
33 } 33 }
34 } 34 }
35 } 35 }
36 </script> 36 </script>
37 37
src/layout/components/Sidebar/Logo.vue
1 <template> 1 <template>
2 <div class="sidebar-logo-container" :class="{'collapse':collapse}"> 2 <div class="sidebar-logo-container" :class="{'collapse':collapse}">
3 <transition name="sidebarLogoFade"> 3 <transition name="sidebarLogoFade">
4 <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/"> 4 <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
5 <img v-if="logo" :src="logo" class="sidebar-logo"> 5 <img v-if="logo" :src="logo" class="sidebar-logo">
6 <h1 v-else class="sidebar-title">{{ title }} </h1> 6 <h1 v-else class="sidebar-title">{{ title }} </h1>
7 </router-link> 7 </router-link>
8 <router-link v-else key="expand" class="sidebar-logo-link" to="/"> 8 <router-link v-else key="expand" class="sidebar-logo-link" to="/">
9 <img v-if="logo" :src="logo" class="sidebar-logo"> 9 <img v-if="logo" :src="logo" class="sidebar-logo">
10 <h1 class="sidebar-title">{{ title }} </h1> 10 <h1 class="sidebar-title">{{ title }} </h1>
11 </router-link> 11 </router-link>
12 </transition> 12 </transition>
13 </div> 13 </div>
14 </template> 14 </template>
15 15
16 <script> 16 <script>
17 export default { 17 export default {
18 name: 'SidebarLogo', 18 name: 'SidebarLogo',
19 props: { 19 props: {
20 collapse: { 20 collapse: {
21 type: Boolean, 21 type: Boolean,
22 required: true 22 required: true
23 } 23 }
24 }, 24 },
25 data() { 25 data() {
26 return { 26 return {
27 title: '鱼皮出海', 27 title: 'Vue Element Admin',
28 logo: 'https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png' 28 logo: 'https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png'
29 } 29 }
30 } 30 }
31 } 31 }
32 </script> 32 </script>
33 33
34 <style lang="scss" scoped> 34 <style lang="scss" scoped>
35 .sidebarLogoFade-enter-active { 35 .sidebarLogoFade-enter-active {
36 transition: opacity 1.5s; 36 transition: opacity 1.5s;
37 } 37 }
38 38
39 .sidebarLogoFade-enter, 39 .sidebarLogoFade-enter,
40 .sidebarLogoFade-leave-to { 40 .sidebarLogoFade-leave-to {
41 opacity: 0; 41 opacity: 0;
42 } 42 }
43 43
44 .sidebar-logo-container { 44 .sidebar-logo-container {
45 position: relative; 45 position: relative;
46 width: 100%; 46 width: 100%;
47 height: 50px; 47 height: 50px;
48 line-height: 50px; 48 line-height: 50px;
49 background: #2b2f3a; 49 background: #2b2f3a;
50 text-align: center; 50 text-align: center;
51 overflow: hidden; 51 overflow: hidden;
52 52
53 & .sidebar-logo-link { 53 & .sidebar-logo-link {
54 height: 100%; 54 height: 100%;
55 width: 100%; 55 width: 100%;
56 56
57 & .sidebar-logo { 57 & .sidebar-logo {
58 width: 32px; 58 width: 32px;
59 height: 32px; 59 height: 32px;
60 vertical-align: middle; 60 vertical-align: middle;
61 margin-right: 12px; 61 margin-right: 12px;
62 } 62 }
63 63
64 & .sidebar-title { 64 & .sidebar-title {
65 display: inline-block; 65 display: inline-block;
66 margin: 0; 66 margin: 0;
67 color: #fff; 67 color: #fff;
68 font-weight: 600; 68 font-weight: 600;
69 line-height: 50px; 69 line-height: 50px;
70 font-size: 14px; 70 font-size: 14px;
71 font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif; 71 font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif;
72 vertical-align: middle; 72 vertical-align: middle;
73 } 73 }
74 } 74 }
75 75
76 &.collapse { 76 &.collapse {
77 .sidebar-logo { 77 .sidebar-logo {
78 margin-right: 0px; 78 margin-right: 0px;
79 } 79 }
80 } 80 }
81 } 81 }
82 </style> 82 </style>
83 83
src/layout/components/Sidebar/SidebarItem.vue
1 <template> 1 <template>
2 <div v-if="!item.hidden"> 2 <div v-if="!item.hidden">
3 <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow"> 3 <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
4 <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)"> 4 <app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
5 <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}"> 5 <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
6 <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="onlyOneChild.meta.title" /> 6 <item :icon="onlyOneChild.meta.icon||(item.meta&&item.meta.icon)" :title="generateTitle(onlyOneChild.meta.title)" />
7 </el-menu-item> 7 </el-menu-item>
8 </app-link> 8 </app-link>
9 </template> 9 </template>
10 10
11 <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body> 11 <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
12 <template slot="title"> 12 <template slot="title">
13 <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" /> 13 <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="generateTitle(item.meta.title)" />
14 </template> 14 </template>
15 <sidebar-item 15 <sidebar-item
16 v-for="child in item.children" 16 v-for="child in item.children"
17 :key="child.path" 17 :key="child.path"
18 :is-nest="true" 18 :is-nest="true"
19 :item="child" 19 :item="child"
20 :base-path="resolvePath(child.path)" 20 :base-path="resolvePath(child.path)"
21 class="nest-menu" 21 class="nest-menu"
22 /> 22 />
23 </el-submenu> 23 </el-submenu>
24 </div> 24 </div>
25 </template> 25 </template>
26 26
27 <script> 27 <script>
28 import path from 'path' 28 import path from 'path'
29 import { generateTitle } from '@/utils/i18n'
29 import { isExternal } from '@/utils/validate' 30 import { isExternal } from '@/utils/validate'
30 import Item from './Item' 31 import Item from './Item'
31 import AppLink from './Link' 32 import AppLink from './Link'
32 import FixiOSBug from './FixiOSBug' 33 import FixiOSBug from './FixiOSBug'
33 34
34 export default { 35 export default {
35 name: 'SidebarItem', 36 name: 'SidebarItem',
36 components: { Item, AppLink }, 37 components: { Item, AppLink },
37 mixins: [FixiOSBug], 38 mixins: [FixiOSBug],
38 props: { 39 props: {
39 // route object 40 // route object
40 item: { 41 item: {
41 type: Object, 42 type: Object,
42 required: true 43 required: true
43 }, 44 },
44 isNest: { 45 isNest: {
45 type: Boolean, 46 type: Boolean,
46 default: false 47 default: false
47 }, 48 },
48 basePath: { 49 basePath: {
49 type: String, 50 type: String,
50 default: '' 51 default: ''
51 } 52 }
52 }, 53 },
53 data() { 54 data() {
54 // To fix https://github.com/PanJiaChen/vue-admin-template/issues/237 55 // To fix https://github.com/PanJiaChen/vue-admin-template/issues/237
55 // TODO: refactor with render function 56 // TODO: refactor with render function
56 this.onlyOneChild = null 57 this.onlyOneChild = null
57 return {} 58 return {}
58 }, 59 },
59 methods: { 60 methods: {
60 hasOneShowingChild(children = [], parent) { 61 hasOneShowingChild(children = [], parent) {
61 const showingChildren = children.filter(item => { 62 const showingChildren = children.filter(item => {
62 if (item.hidden) { 63 if (item.hidden) {
63 return false 64 return false
64 } else { 65 } else {
65 // Temp set(will be used if only has one showing child) 66 // Temp set(will be used if only has one showing child)
66 this.onlyOneChild = item 67 this.onlyOneChild = item
67 return true 68 return true
68 } 69 }
69 }) 70 })
70 71
71 // When there is only one child router, the child router is displayed by default 72 // When there is only one child router, the child router is displayed by default
72 if (showingChildren.length === 1) { 73 if (showingChildren.length === 1) {
73 return true 74 return true
74 } 75 }
75 76
76 // Show parent if there are no child router to display 77 // Show parent if there are no child router to display
77 if (showingChildren.length === 0) { 78 if (showingChildren.length === 0) {
78 this.onlyOneChild = { ... parent, path: '', noShowingChildren: true } 79 this.onlyOneChild = { ... parent, path: '', noShowingChildren: true }
79 return true 80 return true
80 } 81 }
81 82
82 return false 83 return false
83 }, 84 },
84 resolvePath(routePath) { 85 resolvePath(routePath) {
85 if (isExternal(routePath)) { 86 if (isExternal(routePath)) {
86 return routePath 87 return routePath
87 } 88 }
88 if (isExternal(this.basePath)) { 89 if (isExternal(this.basePath)) {
89 return this.basePath 90 return this.basePath
90 } 91 }
91 return path.resolve(this.basePath, routePath) 92 return path.resolve(this.basePath, routePath)
92 } 93 },
94
95 generateTitle
93 } 96 }
94 } 97 }
95 </script> 98 </script>
96 99
src/layout/components/Sidebar/index.vue 100644 → 100755
1 <template> 1 <template>
2 <div :class="{'has-logo':showLogo}"> 2 <div :class="{'has-logo':showLogo}">
3 <logo v-if="showLogo" :collapse="isCollapse" /> 3 <logo v-if="showLogo" :collapse="isCollapse" />
4 <el-scrollbar wrap-class="scrollbar-wrapper"> 4 <el-scrollbar wrap-class="scrollbar-wrapper">
5 <el-menu 5 <el-menu
6 :default-active="activeMenu" 6 :default-active="activeMenu"
7 :collapse="isCollapse" 7 :collapse="isCollapse"
8 :background-color="variables.menuBg" 8 :background-color="variables.menuBg"
9 :text-color="variables.menuText" 9 :text-color="variables.menuText"
10 :unique-opened="false" 10 :unique-opened="false"
11 :active-text-color="variables.menuActiveText" 11 :active-text-color="variables.menuActiveText"
12 :collapse-transition="false" 12 :collapse-transition="false"
13 mode="vertical" 13 mode="vertical"
14 > 14 >
15 <sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" /> 15 <sidebar-item v-for="route in permission_routes" :key="route.path" :item="route" :base-path="route.path" />
16 </el-menu> 16 </el-menu>
17 </el-scrollbar> 17 </el-scrollbar>
18 </div> 18 </div>
19 </template> 19 </template>
20 20
21 <script> 21 <script>
22 import { mapGetters } from 'vuex' 22 import { mapGetters } from 'vuex'
23 import Logo from './Logo' 23 import Logo from './Logo'
24 import SidebarItem from './SidebarItem' 24 import SidebarItem from './SidebarItem'
25 import variables from '@/styles/variables.scss' 25 import variables from '@/styles/variables.scss'
26 26
27 export default { 27 export default {
28 components: { SidebarItem, Logo }, 28 components: { SidebarItem, Logo },
29 computed: { 29 computed: {
30 ...mapGetters([ 30 ...mapGetters([
31 'permission_routes', 31 'permission_routes',
32 'sidebar' 32 'sidebar'
33 ]), 33 ]),
34 activeMenu() { 34 activeMenu() {
35 const route = this.$route 35 const route = this.$route
36 const { meta, path } = route 36 const { meta, path } = route
37 // if set path, the sidebar will highlight the path you set 37 // if set path, the sidebar will highlight the path you set
38 if (meta.activeMenu) { 38 if (meta.activeMenu) {
39 return meta.activeMenu 39 return meta.activeMenu
40 } 40 }
41 return path 41 return path
42 }, 42 },
43 showLogo() { 43 showLogo() {
44 return this.$store.state.settings.sidebarLogo 44 return this.$store.state.settings.sidebarLogo
45 }, 45 },
46 variables() { 46 variables() {
47 return variables 47 return variables
48 }, 48 },
49 isCollapse() { 49 isCollapse() {
50 return !this.sidebar.opened 50 return !this.sidebar.opened
51 } 51 }
52 } 52 }
53 } 53 }
54 </script> 54 </script>
55 55
src/layout/components/TagsView/ScrollPane.vue
File was created 1 <template>
2 <el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
3 <slot />
4 </el-scrollbar>
5 </template>
6
7 <script>
8 const tagAndTagSpacing = 4 // tagAndTagSpacing
9
10 export default {
11 name: 'ScrollPane',
12 data() {
13 return {
14 left: 0
15 }
16 },
17 computed: {
18 scrollWrapper() {
19 return this.$refs.scrollContainer.$refs.wrap
20 }
21 },
22 methods: {
23 handleScroll(e) {
24 const eventDelta = e.wheelDelta || -e.deltaY * 40
25 const $scrollWrapper = this.scrollWrapper
26 $scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
27 },
28 moveToTarget(currentTag) {
29 const $container = this.$refs.scrollContainer.$el
30 const $containerWidth = $container.offsetWidth
31 const $scrollWrapper = this.scrollWrapper
32 const tagList = this.$parent.$refs.tag
33
34 let firstTag = null
35 let lastTag = null
36
37 // find first tag and last tag
38 if (tagList.length > 0) {
39 firstTag = tagList[0]
40 lastTag = tagList[tagList.length - 1]
41 }
42
43 if (firstTag === currentTag) {
44 $scrollWrapper.scrollLeft = 0
45 } else if (lastTag === currentTag) {
46 $scrollWrapper.scrollLeft = $scrollWrapper.scrollWidth - $containerWidth
47 } else {
48 // find preTag and nextTag
49 const currentIndex = tagList.findIndex(item => item === currentTag)
50 const prevTag = tagList[currentIndex - 1]
51 const nextTag = tagList[currentIndex + 1]
52
53 // the tag's offsetLeft after of nextTag
54 const afterNextTagOffsetLeft = nextTag.$el.offsetLeft + nextTag.$el.offsetWidth + tagAndTagSpacing
55
56 // the tag's offsetLeft before of prevTag
57 const beforePrevTagOffsetLeft = prevTag.$el.offsetLeft - tagAndTagSpacing
58
59 if (afterNextTagOffsetLeft > $scrollWrapper.scrollLeft + $containerWidth) {
60 $scrollWrapper.scrollLeft = afterNextTagOffsetLeft - $containerWidth
61 } else if (beforePrevTagOffsetLeft < $scrollWrapper.scrollLeft) {
62 $scrollWrapper.scrollLeft = beforePrevTagOffsetLeft
63 }
64 }
65 }
66 }
67 }
68 </script>
69
70 <style lang="scss" scoped>
71 .scroll-container {
72 white-space: nowrap;
73 position: relative;
74 overflow: hidden;
75 width: 100%;
76 /deep/ {
77 .el-scrollbar__bar {
78 bottom: 0px;
79 }
80 .el-scrollbar__wrap {
81 height: 49px;
82 }
83 }
84 }
85 </style>
86
src/layout/components/TagsView/index.vue
File was created 1 <template>
2 <div id="tags-view-container" class="tags-view-container">
3 <scroll-pane ref="scrollPane" class="tags-view-wrapper">
4 <router-link
5 v-for="tag in visitedViews"
6 ref="tag"
7 :key="tag.path"
8 :class="isActive(tag)?'active':''"
9 :to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
10 tag="span"
11 class="tags-view-item"
12 @click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''"
13 @contextmenu.prevent.native="openMenu(tag,$event)"
14 >
15 {{ generateTitle(tag.title) }}
16 <span v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
17 </router-link>
18 </scroll-pane>
19 <ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
20 <li @click="refreshSelectedTag(selectedTag)">{{ $t('tagsView.refresh') }}</li>
21 <li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">{{ $t('tagsView.close') }}</li>
22 <li @click="closeOthersTags">{{ $t('tagsView.closeOthers') }}</li>
23 <li @click="closeAllTags(selectedTag)">{{ $t('tagsView.closeAll') }}</li>
24 </ul>
25 </div>
26 </template>
27
28 <script>
29 import ScrollPane from './ScrollPane'
30 import { generateTitle } from '@/utils/i18n'
31 import path from 'path'
32
33 export default {
34 components: { ScrollPane },
35 data() {
36 return {
37 visible: false,
38 top: 0,
39 left: 0,
40 selectedTag: {},
41 affixTags: []
42 }
43 },
44 computed: {
45 visitedViews() {
46 return this.$store.state.tagsView.visitedViews
47 },
48 routes() {
49 return this.$store.state.permission.routes
50 }
51 },
52 watch: {
53 $route() {
54 this.addTags()
55 this.moveToCurrentTag()
56 },
57 visible(value) {
58 if (value) {
59 document.body.addEventListener('click', this.closeMenu)
60 } else {
61 document.body.removeEventListener('click', this.closeMenu)
62 }
63 }
64 },
65 mounted() {
66 this.initTags()
67 this.addTags()
68 },
69 methods: {
70 generateTitle, // generateTitle by vue-i18n
71 isActive(route) {
72 return route.path === this.$route.path
73 },
74 isAffix(tag) {
75 return tag.meta && tag.meta.affix
76 },
77 filterAffixTags(routes, basePath = '/') {
78 let tags = []
79 routes.forEach(route => {
80 if (route.meta && route.meta.affix) {
81 const tagPath = path.resolve(basePath, route.path)
82 tags.push({
83 fullPath: tagPath,
84 path: tagPath,
85 name: route.name,
86 meta: { ...route.meta }
87 })
88 }
89 if (route.children) {
90 const tempTags = this.filterAffixTags(route.children, route.path)
91 if (tempTags.length >= 1) {
92 tags = [...tags, ...tempTags]
93 }
94 }
95 })
96 return tags
97 },
98 initTags() {
99 const affixTags = this.affixTags = this.filterAffixTags(this.routes)
100 for (const tag of affixTags) {
101 // Must have tag name
102 if (tag.name) {
103 this.$store.dispatch('tagsView/addVisitedView', tag)
104 }
105 }
106 },
107 addTags() {
108 const { name } = this.$route
109 if (name) {
110 this.$store.dispatch('tagsView/addView', this.$route)
111 }
112 return false
113 },
114 moveToCurrentTag() {
115 const tags = this.$refs.tag
116 this.$nextTick(() => {
117 for (const tag of tags) {
118 if (tag.to.path === this.$route.path) {
119 this.$refs.scrollPane.moveToTarget(tag)
120 // when query is different then update
121 if (tag.to.fullPath !== this.$route.fullPath) {
122 this.$store.dispatch('tagsView/updateVisitedView', this.$route)
123 }
124 break
125 }
126 }
127 })
128 },
129 refreshSelectedTag(view) {
130 this.$store.dispatch('tagsView/delCachedView', view).then(() => {
131 const { fullPath } = view
132 this.$nextTick(() => {
133 this.$router.replace({
134 path: '/redirect' + fullPath
135 })
136 })
137 })
138 },
139 closeSelectedTag(view) {
140 this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
141 if (this.isActive(view)) {
142 this.toLastView(visitedViews, view)
143 }
144 })
145 },
146 closeOthersTags() {
147 this.$router.push(this.selectedTag)
148 this.$store.dispatch('tagsView/delOthersViews', this.selectedTag).then(() => {
149 this.moveToCurrentTag()
150 })
151 },
152 closeAllTags(view) {
153 this.$store.dispatch('tagsView/delAllViews').then(({ visitedViews }) => {
154 if (this.affixTags.some(tag => tag.path === view.path)) {
155 return
156 }
157 this.toLastView(visitedViews, view)
158 })
159 },
160 toLastView(visitedViews, view) {
161 const latestView = visitedViews.slice(-1)[0]
162 if (latestView) {
163 this.$router.push(latestView.fullPath)
164 } else {
165 // now the default is to redirect to the home page if there is no tags-view,
166 // you can adjust it according to your needs.
167 if (view.name === 'Dashboard') {
168 // to reload home page
169 this.$router.replace({ path: '/redirect' + view.fullPath })
170 } else {
171 this.$router.push('/')
172 }
173 }
174 },
175 openMenu(tag, e) {
176 const menuMinWidth = 105
177 const offsetLeft = this.$el.getBoundingClientRect().left // container margin left
178 const offsetWidth = this.$el.offsetWidth // container width
179 const maxLeft = offsetWidth - menuMinWidth // left boundary
180 const left = e.clientX - offsetLeft + 15 // 15: margin right
181
182 if (left > maxLeft) {
183 this.left = maxLeft
184 } else {
185 this.left = left
186 }
187
188 this.top = e.clientY
189 this.visible = true
190 this.selectedTag = tag
191 },
192 closeMenu() {
193 this.visible = false
194 }
195 }
196 }
197 </script>
198
199 <style lang="scss" scoped>
200 .tags-view-container {
201 height: 34px;
202 width: 100%;
203 background: #fff;
204 border-bottom: 1px solid #d8dce5;
205 box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
206 .tags-view-wrapper {
207 .tags-view-item {
208 display: inline-block;
209 position: relative;
210 cursor: pointer;
211 height: 26px;
212 line-height: 26px;
213 border: 1px solid #d8dce5;
214 color: #495060;
215 background: #fff;
216 padding: 0 8px;
217 font-size: 12px;
218 margin-left: 5px;
219 margin-top: 4px;
220 &:first-of-type {
221 margin-left: 15px;
222 }
223 &:last-of-type {
224 margin-right: 15px;
225 }
226 &.active {
227 background-color: #42b983;
228 color: #fff;
229 border-color: #42b983;
230 &::before {
231 content: '';
232 background: #fff;
233 display: inline-block;
234 width: 8px;
235 height: 8px;
236 border-radius: 50%;
237 position: relative;
238 margin-right: 2px;
239 }
240 }
241 }
242 }
243 .contextmenu {
244 margin: 0;
245 background: #fff;
246 z-index: 3000;
247 position: absolute;
248 list-style-type: none;
249 padding: 5px 0;
250 border-radius: 4px;
251 font-size: 12px;
252 font-weight: 400;
253 color: #333;
254 box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
255 li {
256 margin: 0;
257 padding: 7px 16px;
258 cursor: pointer;
259 &:hover {
260 background: #eee;
261 }
262 }
263 }
264 }
265 </style>
266
267 <style lang="scss">
268 //reset element css of el-icon-close
269 .tags-view-wrapper {
270 .tags-view-item {
271 .el-icon-close {
272 width: 16px;
273 height: 16px;
274 vertical-align: 2px;
275 border-radius: 50%;
276 text-align: center;
277 transition: all .3s cubic-bezier(.645, .045, .355, 1);
278 transform-origin: 100% 50%;
279 &:before {
280 transform: scale(.6);
281 display: inline-block;
282 vertical-align: -3px;
283 }
284 &:hover {
285 background-color: #b4bccc;
286 color: #fff;
287 }
288 }
289 }
290 }
291 </style>
292
src/layout/components/index.js
1 // export { default as Navbar } from '../../common/Header'
2 export { default as Navbar } from './Navbar'
3 export { default as Sidebar } from './Sidebar'
4 export { default as AppMain } from './AppMain' 1 export { default as AppMain } from './AppMain'
2 export { default as Navbar } from './Navbar'
3 export { default as Settings } from './Settings'
src/layout/index.vue
1 <template> 1 <template>
2 <div :class="classObj" class="app-wrapper"> 2 <div :class="classObj" class="app-wrapper">
3 <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" /> 3 <div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside" />
4 <sidebar class="sidebar-container" /> 4 <sidebar class="sidebar-container" />
5 <div class="main-container"> 5 <div :class="{hasTagsView:needTagsView}" class="main-container">
6 <div :class="{'fixed-header':fixedHeader}"> 6 <div :class="{'fixed-header':fixedHeader}">
7 <navbar /> 7 <navbar />
8 <tags-view v-if="needTagsView" />
8 </div> 9 </div>
9 <app-main /> 10 <app-main />
11 <right-panel v-if="showSettings">
12 <settings />
13 </right-panel>
10 </div> 14 </div>
11 </div> 15 </div>
12 </template> 16 </template>
13 17
14 <script> 18 <script>
15 import { Navbar, Sidebar, AppMain } from './components' 19 import RightPanel from '@/components/RightPanel'
20 import { AppMain, Navbar, Settings, Sidebar, TagsView } from './components'
16 import ResizeMixin from './mixin/ResizeHandler' 21 import ResizeMixin from './mixin/ResizeHandler'
22 import { mapState } from 'vuex'
17 23
18 export default { 24 export default {
19 name: 'Layout', 25 name: 'Layout',
20 components: { 26 components: {
27 AppMain,
21 Navbar, 28 Navbar,
29 RightPanel,
30 Settings,
22 Sidebar, 31 Sidebar,
23 AppMain 32 TagsView
24 }, 33 },
25 mixins: [ResizeMixin], 34 mixins: [ResizeMixin],
26 computed: { 35 computed: {
27 sidebar() { 36 ...mapState({
28 return this.$store.state.app.sidebar 37 sidebar: state => state.app.sidebar,
29 }, 38 device: state => state.app.device,
30 device() { 39 showSettings: state => state.settings.showSettings,
31 return this.$store.state.app.device 40 needTagsView: state => state.settings.tagsView,
32 }, 41 fixedHeader: state => state.settings.fixedHeader
33 fixedHeader() { 42 }),
34 return this.$store.state.settings.fixedHeader
35 },
36 classObj() { 43 classObj() {
37 return { 44 return {
38 hideSidebar: !this.sidebar.opened, 45 hideSidebar: !this.sidebar.opened,
39 openSidebar: this.sidebar.opened, 46 openSidebar: this.sidebar.opened,
40 withoutAnimation: this.sidebar.withoutAnimation, 47 withoutAnimation: this.sidebar.withoutAnimation,
41 mobile: this.device === 'mobile' 48 mobile: this.device === 'mobile'
42 } 49 }
43 } 50 }
44 }, 51 },
45 methods: { 52 methods: {
46 handleClickOutside() { 53 handleClickOutside() {
47 this.$store.dispatch('app/closeSideBar', { withoutAnimation: false }) 54 this.$store.dispatch('app/closeSideBar', { withoutAnimation: false })
48 } 55 }
49 } 56 }
50 } 57 }
51 </script> 58 </script>
52 59
53 <style lang="scss" scoped> 60 <style lang="scss" scoped>
54 @import "~@/styles/mixin.scss"; 61 @import "~@/styles/mixin.scss";
55 @import "~@/styles/variables.scss"; 62 @import "~@/styles/variables.scss";
56 63
57 .app-wrapper { 64 .app-wrapper {
58 @include clearfix; 65 @include clearfix;
59 position: relative; 66 position: relative;
60 height: 100%; 67 height: 100%;
61 width: 100%; 68 width: 100%;
62 &.mobile.openSidebar{ 69
70 &.mobile.openSidebar {
63 position: fixed; 71 position: fixed;
64 top: 0; 72 top: 0;
65 } 73 }
66 } 74 }
75
67 .drawer-bg { 76 .drawer-bg {
68 background: #000; 77 background: #000;
69 opacity: 0.3; 78 opacity: 0.3;
70 width: 100%; 79 width: 100%;
71 top: 0; 80 top: 0;
72 height: 100%; 81 height: 100%;
73 position: absolute; 82 position: absolute;
74 z-index: 999; 83 z-index: 999;
75 } 84 }
76 85
77 .fixed-header { 86 .fixed-header {
78 position: fixed; 87 position: fixed;
79 top: 0; 88 top: 0;
80 right: 0; 89 right: 0;
81 z-index: 9; 90 z-index: 9;
82 width: calc(100% - #{$sideBarWidth}); 91 width: calc(100% - #{$sideBarWidth});
83 transition: width 0.28s; 92 transition: width 0.28s;
84 } 93 }
85 94
86 .hideSidebar .fixed-header { 95 .hideSidebar .fixed-header {
87 width: calc(100% - 54px) 96 width: calc(100% - 54px)
88 } 97 }
89 98
90 .mobile .fixed-header { 99 .mobile .fixed-header {
91 width: 100%; 100 width: 100%;
92 } 101 }
src/layout/mixin/ResizeHandler.js 100644 → 100755
1 import store from '@/store' 1 import store from '@/store'
2 2
3 const { body } = document 3 const { body } = document
4 const WIDTH = 992 // refer to Bootstrap's responsive design 4 const WIDTH = 992 // refer to Bootstrap's responsive design
5 5
6 export default { 6 export default {
7 watch: { 7 watch: {
8 $route(route) { 8 $route(route) {
9 if (this.device === 'mobile' && this.sidebar.opened) { 9 if (this.device === 'mobile' && this.sidebar.opened) {
10 store.dispatch('app/closeSideBar', { withoutAnimation: false }) 10 store.dispatch('app/closeSideBar', { withoutAnimation: false })
11 } 11 }
12 } 12 }
13 }, 13 },
14 beforeMount() { 14 beforeMount() {
15 window.addEventListener('resize', this.$_resizeHandler) 15 window.addEventListener('resize', this.$_resizeHandler)
16 }, 16 },
17 beforeDestroy() { 17 beforeDestroy() {
18 window.removeEventListener('resize', this.$_resizeHandler) 18 window.removeEventListener('resize', this.$_resizeHandler)
19 }, 19 },
20 mounted() { 20 mounted() {
21 const isMobile = this.$_isMobile() 21 const isMobile = this.$_isMobile()
22 if (isMobile) { 22 if (isMobile) {
23 store.dispatch('app/toggleDevice', 'mobile') 23 store.dispatch('app/toggleDevice', 'mobile')
24 store.dispatch('app/closeSideBar', { withoutAnimation: true }) 24 store.dispatch('app/closeSideBar', { withoutAnimation: true })
25 } 25 }
26 }, 26 },
27 methods: { 27 methods: {
28 // use $_ for mixins properties 28 // use $_ for mixins properties
29 // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential 29 // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
30 $_isMobile() { 30 $_isMobile() {
31 const rect = body.getBoundingClientRect() 31 const rect = body.getBoundingClientRect()
32 return rect.width - 1 < WIDTH 32 return rect.width - 1 < WIDTH
33 }, 33 },
34 $_resizeHandler() { 34 $_resizeHandler() {
35 if (!document.hidden) { 35 if (!document.hidden) {
36 const isMobile = this.$_isMobile() 36 const isMobile = this.$_isMobile()
37 store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop') 37 store.dispatch('app/toggleDevice', isMobile ? 'mobile' : 'desktop')
38 38
39 if (isMobile) { 39 if (isMobile) {
40 store.dispatch('app/closeSideBar', { withoutAnimation: true }) 40 store.dispatch('app/closeSideBar', { withoutAnimation: true })
41 } 41 }
42 } 42 }
43 } 43 }
44 } 44 }
45 } 45 }
46 46
1 import Vue from 'vue' 1 import Vue from 'vue'
2 2
3 import 'normalize.css/normalize.css' // A modern alternative to CSS resets 3 import Cookies from 'js-cookie'
4 4
5 import ElementUI from 'element-ui' 5 import 'normalize.css/normalize.css' // a modern alternative to CSS resets
6 import 'element-ui/lib/theme-chalk/index.css' 6
7 // import locale from 'element-ui/lib/locale/lang/en' // lang i18n 7 import Element from 'element-ui'
8 // import local_zh from 'element-ui/lib/locale/lang/zh-CN' // 在node_module里面 8 import './styles/element-variables.scss'
9 9
10 import '@/styles/index.scss' // global css 10 import '@/styles/index.scss' // global css
11 11
12 import App from './App' 12 import App from './App'
13 import store from './store' 13 import store from './store'
14 import router from './router' 14 import router from './router'
15 15
16 import '@/icons' // icon 16 import i18n from './lang' // internationalization
17 import '@/permission' // permission control 17 import './icons' // icon
18 import './permission' // permission control
19 import './utils/error-log' // error log
20
21 import * as filters from './filters' // global filters
18 22
19 /** 23 /**
20 * If you don't want to use mock-server 24 * If you don't want to use mock-server
21 * you want to use MockJs for mock api 25 * you want to use MockJs for mock api
22 * you can execute: mockXHR() 26 * you can execute: mockXHR()
23 * 27 *
24 * Currently MockJs will be used in the production environment, 28 * Currently MockJs will be used in the production environment,
25 * please remove it before going online ! ! ! 29 * please remove it before going online ! ! !
26 */ 30 */
27 if (process.env.NODE_ENV === 'production') { 31 if (process.env.NODE_ENV === 'production') {
28 const { mockXHR } = require('../mock') 32 const { mockXHR } = require('../mock')
29 mockXHR() 33 mockXHR()
30 } 34 }
31 35
32 Vue.use(ElementUI, { size: 'small', zIndex: 3000 }) 36 Vue.use(Element, {
33 // set ElementUI lang to EN 37 size: Cookies.get('size') || 'medium', // set element-ui default size
34 // Vue.use(ElementUI, { locale }) 38 i18n: (key, value) => i18n.t(key, value)
35 // 如果想要中文版 element-ui,按如下方式声明 39 })
36 // Vue.use(ElementUI, {local_zh}) 40
41 // register global utility filters
42 Object.keys(filters).forEach(key => {
43 Vue.filter(key, filters[key])
44 })
45
37 Vue.config.productionTip = false 46 Vue.config.productionTip = false
38 47
39 new Vue({ 48 new Vue({
40 el: '#app', 49 el: '#app',
41 router, 50 router,
42 store, 51 store,
52 i18n,
43 render: h => h(App) 53 render: h => h(App)
44 }) 54 })
45 55
src/permission.js
1 import router from './router' 1 import router from './router'
2 import store from './store' 2 import store from './store'
3 import { Message } from 'element-ui' 3 import { Message } from 'element-ui'
4 import NProgress from 'nprogress' // progress bar 4 import NProgress from 'nprogress' // progress bar
5 import 'nprogress/nprogress.css' // progress bar style 5 import 'nprogress/nprogress.css' // progress bar style
6 import { getToken } from '@/utils/auth' // get token from cookie 6 import { getToken } from '@/utils/auth' // get token from cookie
7 import getPageTitle from '@/utils/get-page-title' 7 import getPageTitle from '@/utils/get-page-title'
8 8
9 NProgress.configure({ showSpinner: false }) // NProgress Configuration 9 NProgress.configure({ showSpinner: false }) // NProgress Configuration
10 10
11 const whiteList = ['/login'] // no redirect whitelist 11 const whiteList = ['/login', '/auth-redirect'] // no redirect whitelist
12 12
13 router.beforeEach(async(to, from, next) => { 13 router.beforeEach(async(to, from, next) => {
14 // start progress bar 14 // start progress bar
15 NProgress.start() 15 NProgress.start()
16 16
17 // set page title 17 // set page title
18 document.title = getPageTitle(to.meta.title) 18 document.title = getPageTitle(to.meta.title)
19 19
20 // determine whether the user has logged in 20 // determine whether the user has logged in
21 const hasToken = getToken() 21 const hasToken = getToken()
22 22
23 if (hasToken) { 23 if (hasToken) {
24 if (to.path === '/login') { 24 if (to.path === '/login') {
25 // if is logged in, redirect to the home page 25 // if is logged in, redirect to the home page
26 next({ path: '/' }) 26 next({ path: '/' })
27 NProgress.done() 27 NProgress.done()
28 } else { 28 } else {
29 // determine whether the user has obtained his permission roles through getInfo 29 // determine whether the user has obtained his permission roles through getInfo
30 const hasRoles = store.getters.roles && store.getters.roles.length > 0 30 const hasRoles = store.getters.roles && store.getters.roles.length > 0
31 if (hasRoles) { 31 if (hasRoles) {
32 next() 32 next()
33 } else { 33 } else {
34 try { 34 try {
35 // get user info 35 // get user info
36 // note: roles must be a object array! such as: ['admin'] or ,['developer','editor'] 36 // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
37 const { roles } = await store.dispatch('user/getInfo') 37 const { roles } = await store.dispatch('user/getInfo')
38 38
39 // generate accessible routes map based on roles 39 // generate accessible routes map based on roles
40 const accessRoutes = await store.dispatch('permission/generateRoutes', roles) 40 const accessRoutes = await store.dispatch('permission/generateRoutes', roles)
41 41
42 // dynamically add accessible routes 42 // dynamically add accessible routes
43 router.addRoutes(accessRoutes) 43 router.addRoutes(accessRoutes)
44 44
45 // hack method to ensure that addRoutes is complete 45 // hack method to ensure that addRoutes is complete
46 // set the replace: true, so the navigation will not leave a history record 46 // set the replace: true, so the navigation will not leave a history record
47 next({ ...to, replace: true }) 47 next({ ...to, replace: true })
48 } catch (error) { 48 } catch (error) {
49 // remove token and go to login page to re-login 49 // remove token and go to login page to re-login
50 await store.dispatch('user/resetToken') 50 await store.dispatch('user/resetToken')
51 Message.error(error || 'Has Error') 51 Message.error(error || 'Has Error')
52 next(`/login?redirect=${to.path}`) 52 next(`/login?redirect=${to.path}`)
53 NProgress.done() 53 NProgress.done()
54 } 54 }
55 } 55 }
56 } 56 }
57 } else { 57 } else {
58 /* has no token*/ 58 /* has no token*/
59 59
60 if (whiteList.indexOf(to.path) !== -1) { 60 if (whiteList.indexOf(to.path) !== -1) {
61 // in the free login whitelist, go directly 61 // in the free login whitelist, go directly
62 next() 62 next()
63 } else { 63 } else {
64 // other pages that do not have permission to access are redirected to the login page. 64 // other pages that do not have permission to access are redirected to the login page.
65 next(`/login?redirect=${to.path}`) 65 next(`/login?redirect=${to.path}`)
66 NProgress.done() 66 NProgress.done()
67 } 67 }
68 } 68 }
69 }) 69 })
70 70
71 router.afterEach(() => { 71 router.afterEach(() => {
72 // finish progress bar 72 // finish progress bar
73 NProgress.done() 73 NProgress.done()
74 }) 74 })
75 75
src/router/index.js
1 import Vue from 'vue' 1 import Vue from 'vue'
2 import Router from 'vue-router' 2 import Router from 'vue-router'
3 3
4 Vue.use(Router) 4 Vue.use(Router)
5 5
6 /* Layout */ 6 /* Layout */
7 import Layout from '@/layout' 7 import Layout from '@/layout'
8 8
9 /* Router Modules */
10 import componentsRouter from './modules/components'
11 import chartsRouter from './modules/charts'
12 import tableRouter from './modules/table'
13 import nestedRouter from './modules/nested'
14
9 /** 15 /**
10 * Note: sub-menu only appear when route children.length >= 1 16 * Note: sub-menu only appear when route children.length >= 1
11 * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html 17 * Detail see: https://panjiachen.github.io/vue-element-admin-site/guide/essentials/router-and-nav.html
12 * 18 *
13 * hidden: true if set true, item will not show in the sidebar(default is false) 19 * hidden: true if set true, item will not show in the sidebar(default is false)
14 * alwaysShow: true if set true, will always show the root menu 20 * alwaysShow: true if set true, will always show the root menu
15 * if not set alwaysShow, when item has more than one children route, 21 * if not set alwaysShow, when item has more than one children route,
16 * it will becomes nested mode, otherwise not show the root menu 22 * it will becomes nested mode, otherwise not show the root menu
17 * redirect: noRedirect if set noRedirect will no redirect in the breadcrumb 23 * redirect: noRedirect if set noRedirect will no redirect in the breadcrumb
18 * name:'router-name' the name is used by <keep-alive> (must set!!!) 24 * name:'router-name' the name is used by <keep-alive> (must set!!!)
19 * meta : { 25 * meta : {
20 roles: ['admin','editor'] control the page roles (you can set multiple roles) 26 roles: ['admin','editor'] control the page roles (you can set multiple roles)
21 title: 'title' the name show in sidebar and breadcrumb (recommend set) 27 title: 'title' the name show in sidebar and breadcrumb (recommend set)
22 icon: 'svg-name' the icon show in the sidebar 28 icon: 'svg-name' the icon show in the sidebar
29 noCache: true if set true, the page will no be cached(default is false)
30 affix: true if set true, the tag will affix in the tags-view
23 breadcrumb: false if set false, the item will hidden in breadcrumb(default is true) 31 breadcrumb: false if set false, the item will hidden in breadcrumb(default is true)
24 activeMenu: '/example/list' if set path, the sidebar will highlight the path you set 32 activeMenu: '/example/list' if set path, the sidebar will highlight the path you set
25 } 33 }
26 */ 34 */
27 35
28 /** 36 /**
29 * constantRoutes 37 * constantRoutes
30 * a base page that does not have permission requirements 38 * a base page that does not have permission requirements
31 * all roles can be accessed 39 * all roles can be accessed
32 */ 40 */
33 export const constantRoutes = [{ 41 export const constantRoutes = [
42 {
43 path: '/redirect',
44 component: Layout,
45 hidden: true,
46 children: [
47 {
48 path: '/redirect/:path*',
49 component: () => import('@/views/redirect/index')
50 }
51 ]
52 },
53 {
34 path: '/login', 54 path: '/login',
35 component: () => import('@/views/login/index'), 55 component: () => import('@/views/login/index'),
36 hidden: true 56 hidden: true
37 }, 57 },
38 { 58 {
59 path: '/auth-redirect',
60 component: () => import('@/views/login/auth-redirect'),
61 hidden: true
62 },
63 {
39 path: '/404', 64 path: '/404',
40 component: () => import('@/views/404'), 65 component: () => import('@/views/error-page/404'),
66 hidden: true
67 },
68 {
69 path: '/401',
70 component: () => import('@/views/error-page/401'),
41 hidden: true 71 hidden: true
42 }, 72 },
43 { 73 {
44 path: '/', 74 path: '/',
45 component: Layout, 75 component: Layout,
46 redirect: '/dashboard', 76 redirect: '/dashboard',
47 children: [{ 77 children: [
48 path: 'dashboard', 78 {
49 name: 'Dashboard', 79 path: 'dashboard',
50 component: () => import('@/views/dashboard/index'), 80 component: () => import('@/views/dashboard/index'),
51 meta: { 81 name: 'Dashboard',
52 title: '中控台', 82 meta: { title: 'dashboard', icon: 'dashboard', affix: true }
53 icon: 'dashboard'
54 } 83 }
55 }] 84 ]
56 }, 85 },
86 // {
87 // path: '/documentation',
88 // component: Layout,
89 // children: [
90 // {
91 // path: 'index',
92 // component: () => import('@/views/documentation/index'),
93 // name: 'Documentation',
94 // meta: { title: 'documentation', icon: 'documentation', affix: true }
95 // }
96 // ]
97 // },
98 // {
99 // path: '/guide',
100 // component: Layout,
101 // redirect: '/guide/index',
102 // children: [
103 // {
104 // path: 'index',
105 // component: () => import('@/views/guide/index'),
106 // name: 'Guide',
107 // meta: { title: 'guide', icon: 'guide', noCache: true }
108 // }
109 // ]
110 // },
57 { 111 {
58 path: '/user', //用户管理 112 path: '/profile',
59 component: Layout, 113 component: Layout,
60 redirect: '/user/list', 114 redirect: '/profile/index',
61 name: 'user', 115 hidden: true,
62 meta: { 116 children: [
63 title: '用户管理', 117 {
64 icon: 'people' 118 path: 'index',
65 }, 119 component: () => import('@/views/profile/index'),
66 children: [{ 120 name: 'Profile',
67 path: 'user', 121 meta: { title: 'profile', icon: 'user', noCache: true }
68 name: 'User',
69 component: () => import('@/views/table/index'),
70 meta: {
71 title: '用户列表',
72 icon: 'peoples'
73 }
74 } 122 }
75 // ,
76 // {
77 // path: 'tree',
78 // name: '',
79 // component: () => import('@/views/tree/index'),
80 // meta: {
81 // title: '权限控制',
82 // icon: 'lock'
83 // }
84 // }
85 ] 123 ]
86 }, 124 }
125 ]
126
127 /**
128 * asyncRoutes
129 * the routes that need to be dynamically loaded based on user roles
130 */
131 export const asyncRoutes = [
87 { 132 {
88 path: '/shop', 133 path: '/permission',
89 component: Layout, 134 component: Layout,
135 redirect: '/permission/page',
136 alwaysShow: true, // will always show the root menu
137 name: 'Permission',
90 meta: { 138 meta: {
91 title: '商家管理', 139 title: 'permission',
92 icon: 'shopping' 140 icon: 'lock',
141 roles: ['admin', 'editor'] // you can set roles in root nav
93 }, 142 },
94 children: [{ 143 children: [
95 path: 'shop', 144 {
96 name: 'Shop', 145 path: 'page',
97 component: () => import('@/views/table/index'), 146 component: () => import('@/views/permission/page'),
147 name: 'PagePermission',
98 meta: { 148 meta: {
99 title: '商家列表', 149 title: 'pagePermission',
100 icon: 'table' 150 roles: ['admin'] // or you can only set roles in sub nav
101 } 151 }
102 }, 152 },
103 { 153 {
104 path: 'tree', 154 path: 'directive',
105 name: 'Tree', 155 component: () => import('@/views/permission/directive'),
106 component: () => import('@/views/tree/index'), 156 name: 'DirectivePermission',
107 meta: { 157 meta: {
108 title: '图片分析', 158 title: 'directivePermission'
109 icon: 'chart' 159 // if do not set roles, means: this page does not require permission
110 } 160 }
111 }
112 ]
113 },
114 {
115 path: '/prod',
116 component: Layout,
117 redirect: '/prod/table',
118 name: 'Prod',
119 meta: {
120 title: '产品管理',
121 icon: 'tree'
122 },
123 children: [{
124 path: 'table',
125 name: 'Tree',
126 meta: {
127 title: '成镜',
128 icon: 'tree-table'
129 },
130 children: [{
131 path: 'table',
132 name: 'tree',
133 component: () => import('@/views/tree/index'),
134 meta: {
135 title: '款式索引',
136 icon: 'tree-table'
137 },
138 children: [{
139 path: 'table',
140 name: 'Table1',
141 component: () => import('@/views/table/index'),
142 meta: {
143 title: '青春学子风',
144 icon: 'guide'
145 }
146 },{
147 path: 'table',
148 name: 'Table1',
149 component: () => import('@/views/table/index'),
150 meta: {
151 title: '质感哥特风',
152 icon: 'guide'
153 }
154 }]
155 },{
156 path: 'table',
157 name: 'tree',
158 component: () => import('@/views/table/index'),
159 meta: {
160 title: '颜色索引',
161 icon: 'tree-table'
162 }
163 }]
164 }, 161 },
165 { 162 {
166 path: 'tree', 163 path: 'role',
167 name: 'Tree', 164 component: () => import('@/views/permission/role'),
168 component: () => import('@/views/table/index'), 165 name: 'RolePermission',
169 meta: { 166 meta: {
170 title: '镜片', 167 title: 'rolePermission',
171 icon: 'tree-table' 168 roles: ['admin', 'editor']
172 } 169 }
173 } 170 }
174 ] 171 ]
175 }, 172 },
173
176 { 174 {
177 path: '/Meta', 175 path: '/icon',
178 component: Layout, 176 component: Layout,
179 redirect: '/meta/table', 177 children: [
180 name: 'Meta',
181 meta: {
182 title: '元管理',
183 icon: 'guide'
184 },
185 children: [{
186 path: 'table',
187 name: 'Table',
188 component: () => import('@/views/table/index'),
189 meta: {
190 title: 'Table',
191 icon: 'table'
192 }
193 },
194 { 178 {
195 path: 'tree', 179 path: 'index',
196 name: 'Tree', 180 component: () => import('@/views/icons/index'),
197 component: () => import('@/views/tree/index'), 181 name: 'Icons',
198 meta: { 182 meta: { title: 'icons', icon: 'icon', noCache: true }
199 title: 'Tree',
200 icon: 'tree'
201 }
202 } 183 }
203 ] 184 ]
204 }, 185 },
186
187 /** when your routing map is too long, you can split it into small modules **/
188 componentsRouter,
189 chartsRouter,
190 nestedRouter,
191 tableRouter,
192
193 // {
194 // path: '/example',
195 // component: Layout,
196 // redirect: '/example/list',
197 // name: 'Example',
198 // meta: {
199 // title: 'example',
200 // icon: 'example'
201 // },
202 // children: [
203 // {
204 // path: 'create',
205 // component: () => import('@/views/example/create'),
206 // name: 'CreateArticle',
207 // meta: { title: 'createArticle', icon: 'edit' }
208 // },
209 // {
210 // path: 'edit/:id(\\d+)',
211 // component: () => import('@/views/example/edit'),
212 // name: 'EditArticle',
213 // meta: { title: 'editArticle', noCache: true, activeMenu: '/example/list' },
214 // hidden: true
215 // },
216 // {
217 // path: 'list',
218 // component: () => import('@/views/example/list'),
219 // name: 'ArticleList',
220 // meta: { title: 'articleList', icon: 'list' }
221 // }
222 // ]
223 // },
224
205 { 225 {
206 path: '/trade', 226 path: '/tab',
207 component: Layout, 227 component: Layout,
208 redirect: '/example/table', 228 children: [
209 name: 'Trade',
210 meta: {
211 title: '交易管理',
212 icon: 'money'
213 },
214 children: [{
215 path: 'table',
216 name: 'Table',
217 component: () => import('@/views/table/index'),
218 meta: {
219 title: '成交清单',
220 icon: 'table'
221 }
222 },
223 { 229 {
224 path: 'tree', 230 path: 'index',
225 name: 'Tree', 231 component: () => import('@/views/tab/index'),
226 component: () => import('@/views/tree/index'), 232 name: 'Tab',
227 meta: { 233 meta: { title: 'tab', icon: 'tab' }
228 title: '未成交清单',
229 icon: 'table'
230 }
231 } 234 }
232 ] 235 ]
233 }, { 236 },
234 path: '/recommand', 237
235 component: Layout, 238 // {
236 redirect: '/recommand/table', 239 // path: '/error',
237 name: 'Recommand', 240 // component: Layout,
238 meta: { 241 // redirect: 'noRedirect',
239 title: '推荐系统', 242 // name: 'ErrorPages',
240 icon: 'size' 243 // meta: {
241 }, 244 // title: 'errorPages',
242 children: [{ 245 // icon: '404'
243 path: 'table', 246 // },
244 name: 'Table', 247 // children: [
245 component: () => import('@/views/table/index'), 248 // {
246 meta: { 249 // path: '401',
247 title: '推荐系统教学', 250 // component: () => import('@/views/error-page/401'),
248 icon: 'table' 251 // name: 'Page401',
249 } 252 // meta: { title: 'page401', noCache: true }
250 }] 253 // },
251 }, { 254 // {
252 path: '/system', 255 // path: '404',
256 // component: () => import('@/views/error-page/404'),
257 // name: 'Page404',
258 // meta: { title: 'page404', noCache: true }
259 // }
260 // ]
261 // },
262
263 // {
264 // path: '/error-log',
265 // component: Layout,
266 // children: [
267 // {
268 // path: 'log',
269 // component: () => import('@/views/error-log/index'),
270 // name: 'ErrorLog',
271 // meta: { title: 'errorLog', icon: 'bug' }
272 // }
273 // ]
274 // },
275
276 // {
277 // path: '/excel',
278 // component: Layout,
279 // redirect: '/excel/export-excel',
280 // name: 'Excel',
281 // meta: {
282 // title: 'excel',
283 // icon: 'excel'
284 // },
285 // children: [
286 // {
287 // path: 'export-excel',
288 // component: () => import('@/views/excel/export-excel'),
289 // name: 'ExportExcel',
290 // meta: { title: 'exportExcel' }
291 // },
292 // {
293 // path: 'export-selected-excel',
294 // component: () => import('@/views/excel/select-excel'),
295 // name: 'SelectExcel',
296 // meta: { title: 'selectExcel' }
297 // },
298 // {
299 // path: 'export-merge-header',
300 // component: () => import('@/views/excel/merge-header'),
301 // name: 'MergeHeader',
302 // meta: { title: 'mergeHeader' }
303 // },
304 // {
305 // path: 'upload-excel',
306 // component: () => import('@/views/excel/upload-excel'),
307 // name: 'UploadExcel',
308 // meta: { title: 'uploadExcel' }
309 // }
310 // ]
311 // },
312
313 // {
314 // path: '/zip',
src/router/modules/charts.js
File was created 1 /** When your routing table is too long, you can split it into small modules**/
2
3 import Layout from '@/layout'
4
5 const chartsRouter = {
6 path: '/charts',
7 component: Layout,
8 redirect: 'noRedirect',
9 name: 'Charts',
10 meta: {
11 title: 'charts',
12 icon: 'chart'
13 },
14 children: [
15 {
16 path: 'keyboard',
17 component: () => import('@/views/charts/keyboard'),
18 name: 'KeyboardChart',
19 meta: { title: 'keyboardChart', noCache: true }
20 },
21 {
22 path: 'line',
23 component: () => import('@/views/charts/line'),
24 name: 'LineChart',
25 meta: { title: 'lineChart', noCache: true }
26 },
27 {
28 path: 'mix-chart',
29 component: () => import('@/views/charts/mix-chart'),
30 name: 'MixChart',
31 meta: { title: 'mixChart', noCache: true }
32 }
33 ]
34 }
35
36 export default chartsRouter
37
src/router/modules/components.js
File was created 1 /** When your routing table is too long, you can split it into small modules **/
2
3 import Layout from '@/layout'
4
5 const componentsRouter = {
6 path: '/components',
7 component: Layout,
8 redirect: 'noRedirect',
9 name: 'ComponentDemo',
10 meta: {
11 title: 'components',
12 icon: 'component'
13 },
14 children: [
15 {
16 path: 'tinymce',
17 component: () => import('@/views/components-demo/tinymce'),
18 name: 'TinymceDemo',
19 meta: { title: 'tinymce' }
20 },
21 {
22 path: 'markdown',
23 component: () => import('@/views/components-demo/markdown'),
24 name: 'MarkdownDemo',
25 meta: { title: 'markdown' }
26 },
27 {
28 path: 'json-editor',
29 component: () => import('@/views/components-demo/json-editor'),
30 name: 'JsonEditorDemo',
31 meta: { title: 'jsonEditor' }
32 },
33 {
34 path: 'split-pane',
35 component: () => import('@/views/components-demo/split-pane'),
36 name: 'SplitpaneDemo',
37 meta: { title: 'splitPane' }
38 },
39 {
40 path: 'avatar-upload',
41 component: () => import('@/views/components-demo/avatar-upload'),
42 name: 'AvatarUploadDemo',
43 meta: { title: 'avatarUpload' }
44 },
45 {
46 path: 'dropzone',
47 component: () => import('@/views/components-demo/dropzone'),
48 name: 'DropzoneDemo',
49 meta: { title: 'dropzone' }
50 },
51 {
52 path: 'sticky',
53 component: () => import('@/views/components-demo/sticky'),
54 name: 'StickyDemo',
55 meta: { title: 'sticky' }
56 },
57 {
58 path: 'count-to',
59 component: () => import('@/views/components-demo/count-to'),
60 name: 'CountToDemo',
61 meta: { title: 'countTo' }
62 },
63 {
64 path: 'mixin',
65 component: () => import('@/views/components-demo/mixin'),
66 name: 'ComponentMixinDemo',
67 meta: { title: 'componentMixin' }
68 },
69 {
70 path: 'back-to-top',
71 component: () => import('@/views/components-demo/back-to-top'),
72 name: 'BackToTopDemo',
73 meta: { title: 'backToTop' }
74 },
75 {
76 path: 'drag-dialog',
77 component: () => import('@/views/components-demo/drag-dialog'),
78 name: 'DragDialogDemo',
79 meta: { title: 'dragDialog' }
80 },
81 {
82 path: 'drag-select',
83 component: () => import('@/views/components-demo/drag-select'),
84 name: 'DragSelectDemo',
85 meta: { title: 'dragSelect' }
86 },
87 {
88 path: 'dnd-list',
89 component: () => import('@/views/components-demo/dnd-list'),
90 name: 'DndListDemo',
91 meta: { title: 'dndList' }
92 },
93 {
94 path: 'drag-kanban',
95 component: () => import('@/views/components-demo/drag-kanban'),
96 name: 'DragKanbanDemo',
97 meta: { title: 'dragKanban' }
98 }
99 ]
100 }
101
102 export default componentsRouter
103
src/router/modules/nested.js
File was created 1 /** When your routing table is too long, you can split it into small modules **/
2
3 import Layout from '@/layout'
4
5 const nestedRouter = {
6 path: '/nested',
7 component: Layout,
8 redirect: '/nested/menu1/menu1-1',
9 name: 'Nested',
10 meta: {
11 title: 'nested',
12 icon: 'nested'
13 },
14 children: [
15 {
16 path: 'menu1',
17 component: () => import('@/views/nested/menu1/index'), // Parent router-view
18 name: 'Menu1',
19 meta: { title: 'menu1' },
20 redirect: '/nested/menu1/menu1-1',
21 children: [
22 {
23 path: 'menu1-1',
24 component: () => import('@/views/nested/menu1/menu1-1'),
25 name: 'Menu1-1',
26 meta: { title: 'menu1-1' }
27 },
28 {
29 path: 'menu1-2',
30 component: () => import('@/views/nested/menu1/menu1-2'),
31 name: 'Menu1-2',
32 redirect: '/nested/menu1/menu1-2/menu1-2-1',
33 meta: { title: 'menu1-2' },
34 children: [
35 {
36 path: 'menu1-2-1',
37 component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'),
38 name: 'Menu1-2-1',
39 meta: { title: 'menu1-2-1' }
40 },
41 {
42 path: 'menu1-2-2',
43 component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'),
44 name: 'Menu1-2-2',
45 meta: { title: 'menu1-2-2' }
46 }
47 ]
48 },
49 {
50 path: 'menu1-3',
51 component: () => import('@/views/nested/menu1/menu1-3'),
52 name: 'Menu1-3',
53 meta: { title: 'menu1-3' }
54 }
55 ]
56 },
57 {
58 path: 'menu2',
59 name: 'Menu2',
60 component: () => import('@/views/nested/menu2/index'),
61 meta: { title: 'menu2' }
62 }
63 ]
64 }
65
66 export default nestedRouter
67
src/router/modules/table.js
File was created 1 /** When your routing table is too long, you can split it into small modules **/
2
3 import Layout from '@/layout'
4
5 const tableRouter = {
6 path: '/table',
7 component: Layout,
8 redirect: '/table/complex-table',
9 name: 'Table',
10 meta: {
11 title: 'Table',
12 icon: 'table'
13 },
14 children: [
15 {
16 path: 'dynamic-table',
17 component: () => import('@/views/table/dynamic-table/index'),
18 name: 'DynamicTable',
19 meta: { title: 'dynamicTable' }
20 },
21 {
22 path: 'drag-table',
23 component: () => import('@/views/table/drag-table'),
24 name: 'DragTable',
25 meta: { title: 'dragTable' }
26 },
27 {
28 path: 'inline-edit-table',
29 component: () => import('@/views/table/inline-edit-table'),
30 name: 'InlineEditTable',
31 meta: { title: 'inlineEditTable' }
32 },
33 {
34 path: 'complex-table',
35 component: () => import('@/views/table/complex-table'),
36 name: 'ComplexTable',
37 meta: { title: 'complexTable' }
38 }
39 ]
40 }
41 export default tableRouter
42
1 module.exports = { 1 module.exports = {
2 title: 'Vue Element Admin',
2 3
3 title: '鱼皮出海', 4 /**
5 * @type {boolean} true | false
6 * @description Whether show the settings right-panel
7 */
8 showSettings: true,
9
10 /**
11 * @type {boolean} true | false
12 * @description Whether need tagsView
13 */
14 tagsView: true,
4 15
5 /** 16 /**
6 * @type {boolean} true | false 17 * @type {boolean} true | false
7 * @description Whether fix the header 18 * @description Whether fix the header
8 */ 19 */
9 fixedHeader: true, 20 fixedHeader: false,
10 21
11 /** 22 /**
12 * @type {boolean} true | false 23 * @type {boolean} true | false
13 * @description Whether show the logo in sidebar 24 * @description Whether show the logo in sidebar
14 */ 25 */
15 sidebarLogo: true 26 sidebarLogo: false,
27
28 /**
29 * @type {boolean} true | false
30 * @description Whether support pinyin search in headerSearch
31 * Bundle size minified 47.3kb,minified + gzipped 63kb
32 */
33 supportPinyinSearch: true,
34
35 /**
36 * @type {string | array} 'production' | ['production', 'development']
37 * @description Need show err logs component.
38 * The default is only used in the production env
39 * If you want to also use it in dev, you can pass ['production', 'development']
40 */
41 errorLog: 'production'
16 } 42 }
17 43
src/store/getters.js
1 const getters = { 1 const getters = {
2 sidebar: state => state.app.sidebar, 2 sidebar: state => state.app.sidebar,
3 language: state => state.app.language,
4 size: state => state.app.size,
3 device: state => state.app.device, 5 device: state => state.app.device,
6 visitedViews: state => state.tagsView.visitedViews,
7 cachedViews: state => state.tagsView.cachedViews,
4 token: state => state.user.token, 8 token: state => state.user.token,
5 avatar: state => state.user.avatar, 9 avatar: state => state.user.avatar,
6 name: state => state.user.name, 10 name: state => state.user.name,
11 introduction: state => state.user.introduction,
7 roles: state => state.user.roles, 12 roles: state => state.user.roles,
8 permission_routes: state => state.permission.routes 13 permission_routes: state => state.permission.routes,
14 errorLogs: state => state.errorLog.logs
9 } 15 }
10 export default getters 16 export default getters
11 17
src/store/index.js
1 import Vue from 'vue' 1 import Vue from 'vue'
2 import Vuex from 'vuex' 2 import Vuex from 'vuex'
3 import getters from './getters' 3 import getters from './getters'
4 import app from './modules/app'
5 import permission from './modules/permission'
6 import settings from './modules/settings'
7 import user from './modules/user'
8 4
9 Vue.use(Vuex) 5 Vue.use(Vuex)
10 6
7 // https://webpack.js.org/guides/dependency-management/#requirecontext
8 const modulesFiles = require.context('./modules', true, /\.js$/)
9
10 // you do not need `import app from './modules/app'`
11 // it will auto require all vuex module from modules file
12 const modules = modulesFiles.keys().reduce((modules, modulePath) => {
13 // set './app.js' => 'app'
14 const moduleName = modulePath.replace(/^\.\/(.*)\.\w+$/, '$1')
15 const value = modulesFiles(modulePath)
16 modules[moduleName] = value.default
17 return modules
18 }, {})
19
11 const store = new Vuex.Store({ 20 const store = new Vuex.Store({
12 modules: { 21 modules,
13 app,
src/store/modules/app.js
1 import Cookies from 'js-cookie' 1 import Cookies from 'js-cookie'
2 import { getLanguage } from '@/lang/index'
2 3
3 //state
4 const state = { 4 const state = {
5 sidebar: { 5 sidebar: {
6 opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true, 6 opened: Cookies.get('sidebarStatus') ? !!+Cookies.get('sidebarStatus') : true,
7 withoutAnimation: false 7 withoutAnimation: false
8 }, 8 },
9 device: 'desktop' 9 device: 'desktop',
10 language: getLanguage(),
11 size: Cookies.get('size') || 'medium'
10 } 12 }
11 13
12 //mutations
13 const mutations = { 14 const mutations = {
14 TOGGLE_SIDEBAR: state => { 15 TOGGLE_SIDEBAR: state => {
15 state.sidebar.opened = !state.sidebar.opened 16 state.sidebar.opened = !state.sidebar.opened
16 state.sidebar.withoutAnimation = false 17 state.sidebar.withoutAnimation = false
17 if (state.sidebar.opened) { 18 if (state.sidebar.opened) {
18 Cookies.set('sidebarStatus', 1) 19 Cookies.set('sidebarStatus', 1)
19 } else { 20 } else {
20 Cookies.set('sidebarStatus', 0) 21 Cookies.set('sidebarStatus', 0)
21 } 22 }
22 }, 23 },
23 CLOSE_SIDEBAR: (state, withoutAnimation) => { 24 CLOSE_SIDEBAR: (state, withoutAnimation) => {
24 Cookies.set('sidebarStatus', 0) 25 Cookies.set('sidebarStatus', 0)
25 state.sidebar.opened = false 26 state.sidebar.opened = false
26 state.sidebar.withoutAnimation = withoutAnimation 27 state.sidebar.withoutAnimation = withoutAnimation
27 }, 28 },
28 TOGGLE_DEVICE: (state, device) => { 29 TOGGLE_DEVICE: (state, device) => {
29 state.device = device 30 state.device = device
31 },
32 SET_LANGUAGE: (state, language) => {
33 state.language = language
34 Cookies.set('language', language)
35 },
36 SET_SIZE: (state, size) => {
37 state.size = size
38 Cookies.set('size', size)
30 } 39 }
31 } 40 }
32 41
33 //actions
34 const actions = { 42 const actions = {
35 toggleSideBar({ commit }) { 43 toggleSideBar({ commit }) {
36 commit('TOGGLE_SIDEBAR') 44 commit('TOGGLE_SIDEBAR')
37 }, 45 },
38 closeSideBar({ commit }, { withoutAnimation }) { 46 closeSideBar({ commit }, { withoutAnimation }) {
39 commit('CLOSE_SIDEBAR', withoutAnimation) 47 commit('CLOSE_SIDEBAR', withoutAnimation)
40 }, 48 },
41 toggleDevice({ commit }, device) { 49 toggleDevice({ commit }, device) {
42 commit('TOGGLE_DEVICE', device) 50 commit('TOGGLE_DEVICE', device)
51 },
52 setLanguage({ commit }, language) {
53 commit('SET_LANGUAGE', language)
54 },
55 setSize({ commit }, size) {
56 commit('SET_SIZE', size)
43 } 57 }
44 } 58 }
45 59
46 export default { 60 export default {
47 namespaced: true, 61 namespaced: true,
48 state, 62 state,
49 mutations, 63 mutations,
src/store/modules/errorLog.js
File was created 1 const state = {
2 logs: []
3 }
4
5 const mutations = {
6 ADD_ERROR_LOG: (state, log) => {
7 state.logs.push(log)
8 },
9 CLEAR_ERROR_LOG: (state) => {
10 state.logs.splice(0)
11 }
12 }
13
14 const actions = {
15 addErrorLog({ commit }, log) {
16 commit('ADD_ERROR_LOG', log)
17 },
18 clearErrorLog({ commit }) {
19 commit('CLEAR_ERROR_LOG')
20 }
21 }
22
23 export default {
24 namespaced: true,
25 state,
26 mutations,
27 actions
28 }
29
src/store/modules/permission.js
1 import { asyncRoutes, constantRoutes } from '@/router' 1 import { asyncRoutes, constantRoutes } from '@/router'
2 2
3 /** 3 /**
4 * Use meta.role to determine if the current user has permission 4 * Use meta.role to determine if the current user has permission
5 * @param roles 5 * @param roles
6 * @param route 6 * @param route
7 */ 7 */
8 function hasPermission(roles, route) { 8 function hasPermission(roles, route) {
9 if (route.meta && route.meta.roles) { 9 if (route.meta && route.meta.roles) {
10 return roles.some(role => route.meta.roles.includes(role)) 10 return roles.some(role => route.meta.roles.includes(role))
11 } else { 11 } else {
12 return true 12 return true
13 } 13 }
14 } 14 }
15 15
16 /** 16 /**
17 * Filter asynchronous routing tables by recursion 17 * Filter asynchronous routing tables by recursion
18 * @param routes asyncRoutes 18 * @param routes asyncRoutes
19 * @param roles 19 * @param roles
20 */ 20 */
21 export function filterAsyncRoutes(routes, roles) { 21 export function filterAsyncRoutes(routes, roles) {
22 const res = [] 22 const res = []
23
23 routes.forEach(route => { 24 routes.forEach(route => {
24 const tmp = { ...route } 25 const tmp = { ...route }
25 if (hasPermission(roles, tmp)) { 26 if (hasPermission(roles, tmp)) {
26 if (tmp.children) { 27 if (tmp.children) {
27 tmp.children = filterAsyncRoutes(tmp.children, roles) 28 tmp.children = filterAsyncRoutes(tmp.children, roles)
28 } 29 }
29 res.push(tmp) 30 res.push(tmp)
30 } 31 }
31 }) 32 })
32 33
33 return res 34 return res
34 } 35 }
35 36
36 const state = { 37 const state = {
37 routes: [], 38 routes: [],
38 addRoutes: [] 39 addRoutes: []
39 } 40 }
40 41
41 const mutations = { 42 const mutations = {
42 SET_ROUTES: (state, routes) => { 43 SET_ROUTES: (state, routes) => {
43 state.addRoutes = routes 44 state.addRoutes = routes
44 state.routes = constantRoutes.concat(routes) 45 state.routes = constantRoutes.concat(routes)
45 } 46 }
46 } 47 }
47 //根据动作进行判断 48
48 const actions = { 49 const actions = {
49 generateRoutes({ commit }, roles) { 50 generateRoutes({ commit }, roles) {
50 return new Promise(resolve => { 51 return new Promise(resolve => {
51 let accessedRoutes 52 let accessedRoutes
52 if (roles.includes('admin')) { 53 if (roles.includes('admin')) {
53 console.log('------------generateRoutes----asyncRoutes-----------', asyncRoutes, roles);
54 accessedRoutes = asyncRoutes || [] 54 accessedRoutes = asyncRoutes || []
55 } else { 55 } else {
56 accessedRoutes = filterAsyncRoutes(asyncRoutes, roles) 56 accessedRoutes = filterAsyncRoutes(asyncRoutes, roles)
57 accessedRoutes.push({});
58 } 57 }
59 commit('SET_ROUTES', accessedRoutes) 58 commit('SET_ROUTES', accessedRoutes)
60 resolve(accessedRoutes) 59 resolve(accessedRoutes)
61 }) 60 })
62 } 61 }
63 } 62 }
64 63
65 export default { 64 export default {
66 namespaced: true, 65 namespaced: true,
67 state, 66 state,
68 mutations, 67 mutations,
69 actions 68 actions
70 } 69 }
src/store/modules/settings.js
1 import variables from '@/styles/element-variables.scss'
1 import defaultSettings from '@/settings' 2 import defaultSettings from '@/settings'
2 3
3 const { showSettings, fixedHeader, sidebarLogo } = defaultSettings 4 const { showSettings, tagsView, fixedHeader, sidebarLogo, supportPinyinSearch } = defaultSettings
4 5
5 const state = { 6 const state = {
6 showSettings: showSettings, 7 theme: variables.theme,
7 fixedHeader: fixedHeader, 8 showSettings,
8 sidebarLogo: sidebarLogo 9 tagsView,
10 fixedHeader,
11 sidebarLogo,
12 supportPinyinSearch
9 } 13 }
10 14
11 const mutations = { 15 const mutations = {
12 CHANGE_SETTING: (state, { key, value }) => { 16 CHANGE_SETTING: (state, { key, value }) => {
13 if (state.hasOwnProperty(key)) { 17 if (state.hasOwnProperty(key)) {
14 state[key] = value 18 state[key] = value
15 } 19 }
16 } 20 }
17 } 21 }
18 22
19 const actions = { 23 const actions = {
20 changeSetting({ commit }, data) { 24 changeSetting({ commit }, data) {
21 commit('CHANGE_SETTING', data) 25 commit('CHANGE_SETTING', data)
22 } 26 }
23 } 27 }
24 28
25 export default { 29 export default {
26 namespaced: true, 30 namespaced: true,
27 state, 31 state,
28 mutations, 32 mutations,
29 actions 33 actions
30 } 34 }
31 35
32 36
src/store/modules/tagsView.js
File was created 1 const state = {
2 visitedViews: [],
3 cachedViews: []
4 }
5
6 const mutations = {
7 ADD_VISITED_VIEW: (state, view) => {
8 if (state.visitedViews.some(v => v.path === view.path)) return
9 state.visitedViews.push(
10 Object.assign({}, view, {
11 title: view.meta.title || 'no-name'
12 })
13 )
14 },
15 ADD_CACHED_VIEW: (state, view) => {
16 if (state.cachedViews.includes(view.name)) return
17 if (!view.meta.noCache) {
18 state.cachedViews.push(view.name)
19 }
20 },
21
22 DEL_VISITED_VIEW: (state, view) => {
23 for (const [i, v] of state.visitedViews.entries()) {
24 if (v.path === view.path) {
25 state.visitedViews.splice(i, 1)
26 break
27 }
28 }
29 },
30 DEL_CACHED_VIEW: (state, view) => {
31 const index = state.cachedViews.indexOf(view.name)
32 index > -1 && state.cachedViews.splice(index, 1)
33 },
34
35 DEL_OTHERS_VISITED_VIEWS: (state, view) => {
36 state.visitedViews = state.visitedViews.filter(v => {
37 return v.meta.affix || v.path === view.path
38 })
39 },
40 DEL_OTHERS_CACHED_VIEWS: (state, view) => {
41 const index = state.cachedViews.indexOf(view.name)
42 if (index > -1) {
43 state.cachedViews = state.cachedViews.slice(index, index + 1)
44 } else {
45 // if index = -1, there is no cached tags
46 state.cachedViews = []
47 }
48 },
49
50 DEL_ALL_VISITED_VIEWS: state => {
51 // keep affix tags
52 const affixTags = state.visitedViews.filter(tag => tag.meta.affix)
53 state.visitedViews = affixTags
54 },
55 DEL_ALL_CACHED_VIEWS: state => {
56 state.cachedViews = []
57 },
58
59 UPDATE_VISITED_VIEW: (state, view) => {
60 for (let v of state.visitedViews) {
61 if (v.path === view.path) {
62 v = Object.assign(v, view)
63 break
64 }
65 }
66 }
67 }
68
69 const actions = {
70 addView({ dispatch }, view) {
71 dispatch('addVisitedView', view)
72 dispatch('addCachedView', view)
73 },
74 addVisitedView({ commit }, view) {
75 commit('ADD_VISITED_VIEW', view)
76 },
77 addCachedView({ commit }, view) {
78 commit('ADD_CACHED_VIEW', view)
79 },
80
81 delView({ dispatch, state }, view) {
82 return new Promise(resolve => {
83 dispatch('delVisitedView', view)
84 dispatch('delCachedView', view)
85 resolve({
86 visitedViews: [...state.visitedViews],
87 cachedViews: [...state.cachedViews]
88 })
89 })
90 },
91 delVisitedView({ commit, state }, view) {
92 return new Promise(resolve => {
93 commit('DEL_VISITED_VIEW', view)
94 resolve([...state.visitedViews])
95 })
96 },
97 delCachedView({ commit, state }, view) {
98 return new Promise(resolve => {
99 commit('DEL_CACHED_VIEW', view)
100 resolve([...state.cachedViews])
101 })
102 },
103
104 delOthersViews({ dispatch, state }, view) {
105 return new Promise(resolve => {
106 dispatch('delOthersVisitedViews', view)
107 dispatch('delOthersCachedViews', view)
108 resolve({
109 visitedViews: [...state.visitedViews],
110 cachedViews: [...state.cachedViews]
111 })
112 })
113 },
114 delOthersVisitedViews({ commit, state }, view) {
115 return new Promise(resolve => {
116 commit('DEL_OTHERS_VISITED_VIEWS', view)
117 resolve([...state.visitedViews])
118 })
119 },
120 delOthersCachedViews({ commit, state }, view) {
121 return new Promise(resolve => {
122 commit('DEL_OTHERS_CACHED_VIEWS', view)
123 resolve([...state.cachedViews])
124 })
125 },
126
127 delAllViews({ dispatch, state }, view) {
128 return new Promise(resolve => {
129 dispatch('delAllVisitedViews', view)
130 dispatch('delAllCachedViews', view)
131 resolve({
132 visitedViews: [...state.visitedViews],
133 cachedViews: [...state.cachedViews]
134 })
135 })
136 },
137 delAllVisitedViews({ commit, state }) {
138 return new Promise(resolve => {
139 commit('DEL_ALL_VISITED_VIEWS')
140 resolve([...state.visitedViews])
141 })
142 },
143 delAllCachedViews({ commit, state }) {
144 return new Promise(resolve => {
145 commit('DEL_ALL_CACHED_VIEWS')
146 resolve([...state.cachedViews])
147 })
148 },
149
150 updateVisitedView({ commit }, view) {
151 commit('UPDATE_VISITED_VIEW', view)
152 }
153 }
154
155 export default {
156 namespaced: true,
157 state,
158 mutations,
159 actions
160 }
161
src/store/modules/user.js
1 import { 1 import { login, logout, getInfo } from '@/api/user'
2 login, 2 import { getToken, setToken, removeToken } from '@/utils/auth'
3 logout, 3 import router, { resetRouter } from '@/router'
4 getInfo
5 } from '@/api/user'
6 import {
7 getToken,
8 setToken,
9 removeToken
10 } from '@/utils/auth'
11 import {
12 resetRouter
13 } from '@/router'
14
15 const getDefaultState = () => {
16 return {
17 token: getToken(),
18 name: '',
19 avatar: '',
20 roles: []
21 }
22 }
23 4
24 const state = getDefaultState() 5 const state = {
6 token: getToken(),
7 name: '',
8 avatar: '',
9 introduction: '',
10 roles: []
11 }
25 12
26 const mutations = { 13 const mutations = {
27 RESET_STATE: (state) => {
28 Object.assign(state, getDefaultState())
29 },
30 SET_TOKEN: (state, token) => { 14 SET_TOKEN: (state, token) => {
31 state.token = token 15 state.token = token
32 }, 16 },
17 SET_INTRODUCTION: (state, introduction) => {
18 state.introduction = introduction
19 },
33 SET_NAME: (state, name) => { 20 SET_NAME: (state, name) => {
34 state.name = name 21 state.name = name
35 }, 22 },
36 SET_AVATAR: (state, avatar) => { 23 SET_AVATAR: (state, avatar) => {
37 state.avatar = avatar 24 state.avatar = avatar
38 }, 25 },
39 SET_ROLES: (state, roles) => { 26 SET_ROLES: (state, roles) => {
40 state.roles = roles 27 state.roles = roles
41 } 28 }
42 } 29 }
43 30
44 const actions = { 31 const actions = {
45 // user login 32 // user login
46 login({ 33 login({ commit }, userInfo) {
47 commit 34 const { username, password } = userInfo
48 }, userInfo) {
49 const {
50 username,
51 password
52 } = userInfo
53 return new Promise((resolve, reject) => { 35 return new Promise((resolve, reject) => {
54 login({ 36 login({ username: username.trim(), password: password }).then(response => {
55 username: username.trim(), 37 const { data } = response
56 password: password 38 commit('SET_TOKEN', data.token)
57 }).then(response => { 39 setToken(data.token)
58 console.log('返回的数据-- step 3------>', response);
59 // const { token, name, id, password } = response
60 const {
61 token,
62 name
63 } = response
64 console.log('返回的数据-- step 4------>', response);
65 commit('SET_TOKEN', token)
66 setToken(token)
67 resolve() 40 resolve()
68 }).catch(error => { 41 }).catch(error => {
69 console.log('返回的数据-- step 4.1------>', error);
70 reject(error) 42 reject(error)
71 }) 43 })
72 }) 44 })
73 }, 45 },
74 46
75 // get user info 47 // get user info
76 getInfo({ 48 getInfo({ commit, state }) {
77 commit,
78 state
79 }) {
80 return new Promise((resolve, reject) => { 49 return new Promise((resolve, reject) => {
81 getInfo(state.token).then(response => { 50 getInfo(state.token).then(response => {
82 console.log('返回的数据-- step 5------>', state); 51 const { data } = response
83 console.log('返回的数据-- step 5.1------>', response); 52
84 const { 53 if (!data) {
85 avatar,
86 id,
87 name,
88 password,
89 roles,
90 token
91 } = response
92 if (!roles) {
93 reject('Verification failed, please Login again.') 54 reject('Verification failed, please Login again.')
94 } 55 }
95 console.error('返回的数据-- step 5.2------>', response); 56
57 const { roles, name, avatar, introduction } = data
58
96 // roles must be a non-empty array 59 // roles must be a non-empty array
97 if (!roles || roles.length <= 0) { 60 if (!roles || roles.length <= 0) {
98 reject('getInfo: roles must be a non-null array!') 61 reject('getInfo: roles must be a non-null array!')
99 } 62 }
63
100 commit('SET_ROLES', roles) 64 commit('SET_ROLES', roles)
101 commit('SET_NAME', name) 65 commit('SET_NAME', name)
102 commit('SET_AVATAR', avatar) 66 commit('SET_AVATAR', avatar)
103 resolve(response) 67 commit('SET_INTRODUCTION', introduction)
68 resolve(data)
104 }).catch(error => { 69 }).catch(error => {
105 console.log('返回的数据-- step 5.3------>', error);
106 reject(error) 70 reject(error)
107 }) 71 })
108 }) 72 })
109 }, 73 },
110 74
111 // user logout 75 // user logout
112 logout({ 76 logout({ commit, state, dispatch }) {
113 commit,
114 state
115 }) {
116 return new Promise((resolve, reject) => { 77 return new Promise((resolve, reject) => {
117 logout(state.token).then(() => { 78 logout(state.token).then(() => {
118 removeToken() // must remove token first 79 commit('SET_TOKEN', '')
80 commit('SET_ROLES', [])
81 removeToken()
119 resetRouter() 82 resetRouter()
120 commit('RESET_STATE') 83
84 // reset visited views and cached views
85 // to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
86 dispatch('tagsView/delAllViews', null, { root: true })
87
121 resolve() 88 resolve()
122 }).catch(error => { 89 }).catch(error => {
123 reject(error) 90 reject(error)
124 }) 91 })
125 }) 92 })
126 }, 93 },
127 94
src/styles/btn.scss
File was created 1 @import './variables.scss';
2
3 @mixin colorBtn($color) {
4 background: $color;
5
6 &:hover {
7 color: $color;
8
9 &:before,
10 &:after {
11 background: $color;
12 }
13 }
14 }
15
16 .blue-btn {
17 @include colorBtn($blue)
18 }
19
20 .light-blue-btn {
21 @include colorBtn($light-blue)
22 }
23
24 .red-btn {
25 @include colorBtn($red)
26 }
27
28 .pink-btn {
29 @include colorBtn($pink)
30 }
31
32 .green-btn {
33 @include colorBtn($green)
34 }
35
36 .tiffany-btn {
37 @include colorBtn($tiffany)
38 }
39
40 .yellow-btn {
41 @include colorBtn($yellow)
42 }
43
44 .pan-btn {
45 font-size: 14px;
46 color: #fff;
47 padding: 14px 36px;
48 border-radius: 8px;
49 border: none;
50 outline: none;
51 transition: 600ms ease all;
52 position: relative;
53 display: inline-block;
54
55 &:hover {
56 background: #fff;
57
58 &:before,
59 &:after {
60 width: 100%;
61 transition: 600ms ease all;
62 }
63 }
64
65 &:before,
66 &:after {
67 content: '';
68 position: absolute;
69 top: 0;
70 right: 0;
71 height: 2px;
72 width: 0;
73 transition: 400ms ease all;
74 }
75
76 &::after {
77 right: inherit;
78 top: inherit;
79 left: 0;
80 bottom: 0;
81 }
82 }
83
84 .custom-button {
85 display: inline-block;
86 line-height: 1;
87 white-space: nowrap;
88 cursor: pointer;
89 background: #fff;
90 color: #fff;
91 -webkit-appearance: none;
92 text-align: center;
93 box-sizing: border-box;
94 outline: 0;
95 margin: 0;
96 padding: 10px 15px;
97 font-size: 14px;
98 border-radius: 4px;
99 }
100
src/styles/element-ui.scss
1 // cover some element-ui styles 1 // cover some element-ui styles
2 2
3 .el-breadcrumb__inner, 3 .el-breadcrumb__inner,
4 .el-breadcrumb__inner a { 4 .el-breadcrumb__inner a {
5 font-weight: 400 !important; 5 font-weight: 400 !important;
6 } 6 }
7 7
8 .el-upload { 8 .el-upload {
9 input[type="file"] { 9 input[type="file"] {
10 display: none !important; 10 display: none !important;
11 } 11 }
12 } 12 }
13 13
14 .el-upload__input { 14 .el-upload__input {
15 display: none; 15 display: none;
16 } 16 }
17 17
18 .cell {
19 .el-tag {
20 margin-right: 0px;
21 }
22 }
23
24 .small-padding {
25 .cell {
26 padding-left: 5px;
27 padding-right: 5px;
28 }
29 }
30
31 .fixed-width {
32 .el-button--mini {
33 padding: 7px 10px;
34 width: 60px;
35 }
36 }
37
38 .status-col {
39 .cell {
40 padding: 0 10px;
41 text-align: center;
42
43 .el-tag {
44 margin-right: 0px;
45 }
46 }
47 }
18 48
19 // to fixed https://github.com/ElemeFE/element/issues/2461 49 // to fixed https://github.com/ElemeFE/element/issues/2461
20 .el-dialog { 50 .el-dialog {
21 transform: none; 51 transform: none;
22 left: 0; 52 left: 0;
23 position: relative; 53 position: relative;
24 margin: 0 auto; 54 margin: 0 auto;
25 } 55 }
26 56
27 // refine element ui upload 57 // refine element ui upload
28 .upload-container { 58 .upload-container {
29 .el-upload { 59 .el-upload {
30 width: 100%; 60 width: 100%;
31 61
32 .el-upload-dragger { 62 .el-upload-dragger {
33 width: 100%; 63 width: 100%;
34 height: 200px; 64 height: 200px;
35 } 65 }
36 } 66 }
37 } 67 }
38 68
39 // dropdown 69 // dropdown
40 .el-dropdown-menu { 70 .el-dropdown-menu {
41 a { 71 a {
42 display: block 72 display: block
43 } 73 }
44 } 74 }
45 75
76 // fix date-picker ui bug in filter-item
77 .el-range-editor.el-input__inner {
78 display: inline-flex !important;
79 }
80
46 // to fix el-date-picker css style 81 // to fix el-date-picker css style
47 .el-range-separator { 82 .el-range-separator {
48 box-sizing: content-box; 83 box-sizing: content-box;
49 } 84 }
50 85
src/styles/element-variables.scss
File was created 1 /**
2 * I think element-ui's default theme color is too light for long-term use.
3 * So I modified the default color and you can modify it to your liking.
4 **/
5
6 /* theme color */
7 $--color-primary: #1890ff;
8 $--color-success: #13ce66;
9 $--color-warning: #FFBA00;
10 $--color-danger: #ff4949;
11 // $--color-info: #1E1E1E;
12
13 $--button-font-weight: 400;
14
15 // $--color-text-regular: #1f2d3d;
16
17 $--border-color-light: #dfe4ed;
18 $--border-color-lighter: #e6ebf5;
19
20 $--table-border:1px solid#dfe6ec;
21
22 /* icon font path, required */
23 $--font-path: '~element-ui/lib/theme-chalk/fonts';
24
25 @import "~element-ui/packages/theme-chalk/src/index";
26
27 // the :export directive is the magic sauce for webpack
28 // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
29 :export {
30 theme: $--color-primary;
31 }
32
src/styles/index.scss
1 @import './variables.scss'; 1 @import './variables.scss';
2 @import './mixin.scss'; 2 @import './mixin.scss';
3 @import './transition.scss'; 3 @import './transition.scss';
4 @import './element-ui.scss'; 4 @import './element-ui.scss';
5 @import './sidebar.scss'; 5 @import './sidebar.scss';
6 @import './btn.scss';
6 7
7 body { 8 body {
8 height: 100%; 9 height: 100%;
9 -moz-osx-font-smoothing: grayscale; 10 -moz-osx-font-smoothing: grayscale;
10 -webkit-font-smoothing: antialiased; 11 -webkit-font-smoothing: antialiased;
11 text-rendering: optimizeLegibility; 12 text-rendering: optimizeLegibility;
12 font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif; 13 font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
13 } 14 }
14 15
15 label { 16 label {
16 font-weight: 700; 17 font-weight: 700;
17 } 18 }
18 19
19 html { 20 html {
20 height: 100%; 21 height: 100%;
21 box-sizing: border-box; 22 box-sizing: border-box;
22 } 23 }
23 24
24 #app { 25 #app {
25 height: 100%; 26 height: 100%;
26 } 27 }
27 28
28 *, 29 *,
29 *:before, 30 *:before,
30 *:after { 31 *:after {
31 box-sizing: inherit; 32 box-sizing: inherit;
32 } 33 }
33 34
35 .no-padding {
36 padding: 0px !important;
37 }
38
39 .padding-content {
40 padding: 4px 0;
41 }
42
34 a:focus, 43 a:focus,
35 a:active { 44 a:active {
36 outline: none; 45 outline: none;
37 } 46 }
38 47
39 a, 48 a,
40 a:focus, 49 a:focus,
41 a:hover { 50 a:hover {
42 cursor: pointer; 51 cursor: pointer;
43 color: inherit; 52 color: inherit;
44 text-decoration: none; 53 text-decoration: none;
45 } 54 }
46 55
47 div:focus { 56 div:focus {
48 outline: none; 57 outline: none;
49 } 58 }
50 59
60 .fr {
61 float: right;
62 }
63
64 .fl {
65 float: left;
66 }
67
68 .pr-5 {
69 padding-right: 5px;
70 }
71
72 .pl-5 {
73 padding-left: 5px;
74 }
75
76 .block {
77 display: block;
78 }
79
80 .pointer {
81 cursor: pointer;
82 }
83
84 .inlineBlock {
85 display: block;
86 }
87
51 .clearfix { 88 .clearfix {
52 &:after { 89 &:after {
53 visibility: hidden; 90 visibility: hidden;
54 display: block; 91 display: block;
55 font-size: 0; 92 font-size: 0;
56 content: " "; 93 content: " ";
57 clear: both; 94 clear: both;
58 height: 0; 95 height: 0;
59 } 96 }
60 } 97 }
61 98
62 // main-container global css 99 aside {
100 background: #eef1f6;
101 padding: 8px 24px;
102 margin-bottom: 20px;
103 border-radius: 2px;
104 display: block;
105 line-height: 32px;
106 font-size: 16px;
107 font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
108 color: #2c3e50;
109 -webkit-font-smoothing: antialiased;
110 -moz-osx-font-smoothing: grayscale;
111
112 a {
113 color: #337ab7;
114 cursor: pointer;
115
116 &:hover {
117 color: rgb(32, 160, 255);
118 }
119 }
120 }
121
122 //main-container全局样式
63 .app-container { 123 .app-container {
64 padding: 20px; 124 padding: 20px;
65 } 125 }
126
127 .components-container {
128 margin: 30px 50px;
129 position: relative;
130 }
131
132 .pagination-container {
133 margin-top: 30px;
134 }
135
136 .text-center {
137 text-align: center
138 }
139
140 .sub-navbar {
141 height: 50px;
142 line-height: 50px;
143 position: relative;
144 width: 100%;
145 text-align: right;
146 padding-right: 20px;
147 transition: 600ms ease position;
148 background: linear-gradient(90deg, rgba(32, 182, 249, 1) 0%, rgba(32, 182, 249, 1) 0%, rgba(33, 120, 241, 1) 100%, rgba(33, 120, 241, 1) 100%);
149
150 .subtitle {
151 font-size: 20px;
152 color: #fff;
153 }
154
155 &.draft {
156 background: #d0d0d0;
157 }
158
159 &.deleted {
160 background: #d0d0d0;
161 }
162 }
163
164 .link-type,
165 .link-type:focus {
166 color: #337ab7;
167 cursor: pointer;
168
169 &:hover {
170 color: rgb(32, 160, 255);
171 }
172 }
173
174 .filter-container {
175 padding-bottom: 10px;
176
177 .filter-item {
178 display: inline-block;
179 vertical-align: middle;
180 margin-bottom: 10px;
181 }
182 }
183
184 //refine vue-multiselect plugin
185 .multiselect {
186 line-height: 16px;
187 }
188
189 .multiselect--active {
190 z-index: 1000 !important;
191 }
66 192
src/styles/mixin.scss
1 @mixin clearfix { 1 @mixin clearfix {
2 &:after { 2 &:after {
3 content: ""; 3 content: "";
4 display: table; 4 display: table;
5 clear: both; 5 clear: both;
6 } 6 }
7 } 7 }
8 8
9 @mixin scrollBar { 9 @mixin scrollBar {
10 &::-webkit-scrollbar-track-piece { 10 &::-webkit-scrollbar-track-piece {
11 background: #d3dce6; 11 background: #d3dce6;
12 } 12 }
13 13
14 &::-webkit-scrollbar { 14 &::-webkit-scrollbar {
15 width: 6px; 15 width: 6px;
16 } 16 }
17 17
18 &::-webkit-scrollbar-thumb { 18 &::-webkit-scrollbar-thumb {
19 background: #99a9bf; 19 background: #99a9bf;
20 border-radius: 20px; 20 border-radius: 20px;
21 } 21 }
22 } 22 }
23 23
24 @mixin relative { 24 @mixin relative {
25 position: relative; 25 position: relative;
26 width: 100%; 26 width: 100%;
27 height: 100%; 27 height: 100%;
28 } 28 }
29
30 @mixin pct($pct) {
31 width: #{$pct};
32 position: relative;
33 margin: 0 auto;
34 }
35
36 @mixin triangle($width, $height, $color, $direction) {
37 $width: $width/2;
38 $color-border-style: $height solid $color;
39 $transparent-border-style: $width solid transparent;
40 height: 0;
41 width: 0;
42
43 @if $direction==up {
44 border-bottom: $color-border-style;
45 border-left: $transparent-border-style;
46 border-right: $transparent-border-style;
47 }
48
49 @else if $direction==right {
50 border-left: $color-border-style;
51 border-top: $transparent-border-style;
52 border-bottom: $transparent-border-style;
53 }
54
55 @else if $direction==down {
56 border-top: $color-border-style;
57 border-left: $transparent-border-style;
58 border-right: $transparent-border-style;
59 }
60
61 @else if $direction==left {
62 border-right: $color-border-style;
63 border-top: $transparent-border-style;
64 border-bottom: $transparent-border-style;
65 }
66 }
29 67
src/styles/sidebar.scss 100644 → 100755
1 #app { 1 #app {
2 2
3 .main-container { 3 .main-container {
4 min-height: 100%; 4 min-height: 100%;
5 transition: margin-left .28s; 5 transition: margin-left .28s;
6 margin-left: $sideBarWidth; 6 margin-left: $sideBarWidth;
7 position: relative; 7 position: relative;
8 } 8 }
9 9
10 .sidebar-container { 10 .sidebar-container {
11 transition: width 0.28s; 11 transition: width 0.28s;
12 width: $sideBarWidth !important; 12 width: $sideBarWidth !important;
13 background-color: $menuBg; 13 background-color: $menuBg;
14 height: 100%; 14 height: 100%;
15 position: fixed; 15 position: fixed;
16 font-size: 0px; 16 font-size: 0px;
17 top: 0; 17 top: 0;
18 bottom: 0; 18 bottom: 0;
19 left: 0; 19 left: 0;
20 z-index: 1001; 20 z-index: 1001;
21 overflow: hidden; 21 overflow: hidden;
22 22
23 // reset element-ui css 23 // reset element-ui css
24 .horizontal-collapse-transition { 24 .horizontal-collapse-transition {
25 transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out; 25 transition: 0s width ease-in-out, 0s padding-left ease-in-out, 0s padding-right ease-in-out;
26 } 26 }
27 27
28 .scrollbar-wrapper { 28 .scrollbar-wrapper {
29 overflow-x: hidden !important; 29 overflow-x: hidden !important;
30 } 30 }
31 31
32 .el-scrollbar__bar.is-vertical { 32 .el-scrollbar__bar.is-vertical {
33 right: 0px; 33 right: 0px;
34 } 34 }
35 35
36 .el-scrollbar { 36 .el-scrollbar {
37 height: 100%; 37 height: 100%;
38 } 38 }
39 39
40 &.has-logo { 40 &.has-logo {
41 .el-scrollbar { 41 .el-scrollbar {
42 height: calc(100% - 50px); 42 height: calc(100% - 50px);
43 } 43 }
44 } 44 }
45 45
46 .is-horizontal { 46 .is-horizontal {
47 display: none; 47 display: none;
48 } 48 }
49 49
50 a { 50 a {
51 display: inline-block; 51 display: inline-block;
52 width: 100%; 52 width: 100%;
53 overflow: hidden; 53 overflow: hidden;
54 } 54 }
55 55
56 .svg-icon { 56 .svg-icon {
57 margin-right: 16px; 57 margin-right: 16px;
58 } 58 }
59 59
60 .el-menu { 60 .el-menu {
61 border: none; 61 border: none;
62 height: 100%; 62 height: 100%;
63 width: 100% !important; 63 width: 100% !important;
64 } 64 }
65 65
66 // menu hover 66 // menu hover
67 .submenu-title-noDropdown, 67 .submenu-title-noDropdown,
68 .el-submenu__title { 68 .el-submenu__title {
69 &:hover { 69 &:hover {
70 background-color: $menuHover !important; 70 background-color: $menuHover !important;
71 } 71 }
72 } 72 }
73 73
74 .is-active>.el-submenu__title { 74 .is-active>.el-submenu__title {
75 color: $subMenuActiveText !important; 75 color: $subMenuActiveText !important;
76 } 76 }
77 77
78 & .nest-menu .el-submenu>.el-submenu__title, 78 & .nest-menu .el-submenu>.el-submenu__title,
79 & .el-submenu .el-menu-item { 79 & .el-submenu .el-menu-item {
80 min-width: $sideBarWidth !important; 80 min-width: $sideBarWidth !important;
81 background-color: $subMenuBg !important; 81 background-color: $subMenuBg !important;
82 82
83 &:hover { 83 &:hover {
84 background-color: $subMenuHover !important; 84 background-color: $subMenuHover !important;
85 } 85 }
86 } 86 }
87 } 87 }
88 88
89 .hideSidebar { 89 .hideSidebar {
90 .sidebar-container { 90 .sidebar-container {
91 width: 54px !important; 91 width: 54px !important;
92 } 92 }
93 93
94 .main-container { 94 .main-container {
95 margin-left: 54px; 95 margin-left: 54px;
96 } 96 }
97 97
98 .submenu-title-noDropdown { 98 .submenu-title-noDropdown {
99 padding: 0 !important; 99 padding: 0 !important;
100 position: relative; 100 position: relative;
101 101
102 .el-tooltip { 102 .el-tooltip {
103 padding: 0 !important; 103 padding: 0 !important;
104 104
105 .svg-icon { 105 .svg-icon {
106 margin-left: 20px; 106 margin-left: 20px;
107 } 107 }
108 } 108 }
109 } 109 }
110 110
111 .el-submenu { 111 .el-submenu {
112 overflow: hidden; 112 overflow: hidden;
113 113
114 &>.el-submenu__title { 114 &>.el-submenu__title {
115 padding: 0 !important; 115 padding: 0 !important;
116 116
117 .svg-icon { 117 .svg-icon {
118 margin-left: 20px; 118 margin-left: 20px;
119 } 119 }
120 120
121 .el-submenu__icon-arrow { 121 .el-submenu__icon-arrow {
122 display: none; 122 display: none;
123 } 123 }
124 } 124 }
125 } 125 }
126 126
127 .el-menu--collapse { 127 .el-menu--collapse {
128 .el-submenu { 128 .el-submenu {
129 &>.el-submenu__title { 129 &>.el-submenu__title {
130 &>span { 130 &>span {
131 height: 0; 131 height: 0;
132 width: 0; 132 width: 0;
133 overflow: hidden; 133 overflow: hidden;
134 visibility: hidden; 134 visibility: hidden;
135 display: inline-block; 135 display: inline-block;
136 } 136 }
137 } 137 }
138 } 138 }
139 } 139 }
140 } 140 }
141 141
142 .el-menu--collapse .el-menu .el-submenu { 142 .el-menu--collapse .el-menu .el-submenu {
143 min-width: $sideBarWidth !important; 143 min-width: $sideBarWidth !important;
144 } 144 }
145 145
146 // mobile responsive 146 // mobile responsive
147 .mobile { 147 .mobile {
148 .main-container { 148 .main-container {
149 margin-left: 0px; 149 margin-left: 0px;
150 } 150 }
151 151
152 .sidebar-container { 152 .sidebar-container {
153 transition: transform .28s; 153 transition: transform .28s;
154 width: $sideBarWidth !important; 154 width: $sideBarWidth !important;
155 } 155 }
156 156
157 &.hideSidebar { 157 &.hideSidebar {
158 .sidebar-container { 158 .sidebar-container {
159 pointer-events: none; 159 pointer-events: none;
160 transition-duration: 0.3s; 160 transition-duration: 0.3s;
161 transform: translate3d(-$sideBarWidth, 0, 0); 161 transform: translate3d(-$sideBarWidth, 0, 0);
162 } 162 }
163 } 163 }
164 } 164 }
165 165
166 .withoutAnimation { 166 .withoutAnimation {
167 167
168 .main-container, 168 .main-container,
169 .sidebar-container { 169 .sidebar-container {
170 transition: none; 170 transition: none;
171 } 171 }
172 } 172 }
173 } 173 }
174 174
175 // when menu collapsed 175 // when menu collapsed
176 .el-menu--vertical { 176 .el-menu--vertical {
177 &>.el-menu { 177 &>.el-menu {
178 .svg-icon { 178 .svg-icon {
179 margin-right: 16px; 179 margin-right: 16px;
180 } 180 }
181 } 181 }
182 182
183 .nest-menu .el-submenu>.el-submenu__title, 183 .nest-menu .el-submenu>.el-submenu__title,
184 .el-menu-item { 184 .el-menu-item {
185 &:hover { 185 &:hover {
186 // you can use $subMenuHover 186 // you can use $subMenuHover
187 background-color: $menuHover !important; 187 background-color: $menuHover !important;
188 } 188 }
189 } 189 }
190 190
191 // the scroll bar appears when the subMenu is too long 191 // the scroll bar appears when the subMenu is too long
192 >.el-menu--popup { 192 >.el-menu--popup {
193 max-height: 100vh; 193 max-height: 100vh;
194 overflow-y: auto; 194 overflow-y: auto;
195 195
196 &::-webkit-scrollbar-track-piece { 196 &::-webkit-scrollbar-track-piece {
197 background: #d3dce6; 197 background: #d3dce6;
198 } 198 }
199 199
200 &::-webkit-scrollbar { 200 &::-webkit-scrollbar {
201 width: 6px; 201 width: 6px;
202 } 202 }
203 203
204 &::-webkit-scrollbar-thumb { 204 &::-webkit-scrollbar-thumb {
205 background: #99a9bf; 205 background: #99a9bf;
206 border-radius: 20px; 206 border-radius: 20px;
207 } 207 }
208 } 208 }
209 } 209 }
210 210
src/styles/transition.scss 100644 → 100755
1 // global transition css 1 // global transition css
2 2
3 /* fade */ 3 /* fade */
4 .fade-enter-active, 4 .fade-enter-active,
5 .fade-leave-active { 5 .fade-leave-active {
6 transition: opacity 0.28s; 6 transition: opacity 0.28s;
7 } 7 }
8 8
9 .fade-enter, 9 .fade-enter,
10 .fade-leave-active { 10 .fade-leave-active {
11 opacity: 0; 11 opacity: 0;
12 } 12 }
13 13
14 /* fade-transform */ 14 /* fade-transform */
15 .fade-transform-leave-active, 15 .fade-transform-leave-active,
16 .fade-transform-enter-active { 16 .fade-transform-enter-active {
17 transition: all .5s; 17 transition: all .5s;
18 } 18 }
19 19
20 .fade-transform-enter { 20 .fade-transform-enter {
21 opacity: 0; 21 opacity: 0;
22 transform: translateX(-30px); 22 transform: translateX(-30px);
23 } 23 }
24 24
25 .fade-transform-leave-to { 25 .fade-transform-leave-to {
26 opacity: 0; 26 opacity: 0;
27 transform: translateX(30px); 27 transform: translateX(30px);
28 } 28 }
29 29
30 /* breadcrumb transition */ 30 /* breadcrumb transition */
31 .breadcrumb-enter-active, 31 .breadcrumb-enter-active,
32 .breadcrumb-leave-active { 32 .breadcrumb-leave-active {
33 transition: all .5s; 33 transition: all .5s;
34 } 34 }
35 35
36 .breadcrumb-enter, 36 .breadcrumb-enter,
37 .breadcrumb-leave-active { 37 .breadcrumb-leave-active {
38 opacity: 0; 38 opacity: 0;
39 transform: translateX(20px); 39 transform: translateX(20px);
40 } 40 }
41 41
42 .breadcrumb-move { 42 .breadcrumb-move {
43 transition: all .5s; 43 transition: all .5s;
44 } 44 }
45 45
46 .breadcrumb-leave-active { 46 .breadcrumb-leave-active {
47 position: absolute; 47 position: absolute;
48 } 48 }
49 49
src/styles/variables.scss
1 // base color
2 $blue:#324157;
3 $light-blue:#3A71A8;
4 $red:#C03639;
5 $pink: #E65D6E;
6 $green: #30B08F;
7 $tiffany: #4AB7BD;
8 $yellow:#FEC171;
9 $panGreen: #30B08F;
10
1 // sidebar 11 // sidebar
2 $menuText:#bfcbd9; 12 $menuText:#bfcbd9;
3 $menuActiveText:#409EFF; 13 $menuActiveText:#409EFF;
4 $subMenuActiveText:#f4f4f5; //https://github.com/ElemeFE/element/issues/12951 14 $subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951
5 15
6 $menuBg:#304156; 16 $menuBg:#304156;
7 $menuHover:#263445; 17 $menuHover:#263445;
8 18
9 $subMenuBg:#1f2d3d; 19 $subMenuBg:#1f2d3d;
10 $subMenuHover:#001528; 20 $subMenuHover:#001528;
11 21
12 $sideBarWidth: 210px; 22 $sideBarWidth: 210px;
13 23
14 // the :export directive is the magic sauce for webpack 24 // the :export directive is the magic sauce for webpack
15 // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass 25 // https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
16 :export { 26 :export {
17 menuText: $menuText; 27 menuText: $menuText;
18 menuActiveText: $menuActiveText; 28 menuActiveText: $menuActiveText;
19 subMenuActiveText: $subMenuActiveText; 29 subMenuActiveText: $subMenuActiveText;
20 menuBg: $menuBg; 30 menuBg: $menuBg;
21 menuHover: $menuHover; 31 menuHover: $menuHover;
22 subMenuBg: $subMenuBg; 32 subMenuBg: $subMenuBg;
23 subMenuHover: $subMenuHover; 33 subMenuHover: $subMenuHover;
24 sideBarWidth: $sideBarWidth; 34 sideBarWidth: $sideBarWidth;
25 } 35 }
26 36
src/utils/auth.js
1 import Cookies from 'js-cookie' 1 import Cookies from 'js-cookie'
2 2
3 const TokenKey = 'vue_admin_template_token' 3 const TokenKey = 'Admin-Token'
4 4
5 export function getToken() { 5 export function getToken() {
6 return Cookies.get(TokenKey) 6 return Cookies.get(TokenKey)
7 } 7 }
8 8
9 export function setToken(token) { 9 export function setToken(token) {
10 return Cookies.set(TokenKey, token) 10 return Cookies.set(TokenKey, token)
11 } 11 }
12 12
13 export function removeToken() { 13 export function removeToken() {
14 return Cookies.remove(TokenKey) 14 return Cookies.remove(TokenKey)
15 } 15 }
16 16
src/utils/clipboard.js
File was created 1 import Vue from 'vue'
2 import Clipboard from 'clipboard'
3
4 function clipboardSuccess() {
5 Vue.prototype.$message({
6 message: 'Copy successfully',
7 type: 'success',
8 duration: 1500
9 })
10 }
11
12 function clipboardError() {
13 Vue.prototype.$message({
14 message: 'Copy failed',
15 type: 'error'
16 })
17 }
18
19 export default function handleClipboard(text, event) {
20 const clipboard = new Clipboard(event.target, {
21 text: () => text
22 })
23 clipboard.on('success', () => {
24 clipboardSuccess()
25 clipboard.destroy()
26 })
27 clipboard.on('error', () => {
28 clipboardError()
29 clipboard.destroy()
30 })
31 clipboard.onClick(event)
32 }
33
src/utils/error-log.js
File was created 1 import Vue from 'vue'
2 import store from '@/store'
3 import { isString, isArray } from '@/utils/validate'
4 import settings from '@/settings'
5
6 // you can set in settings.js
7 // errorLog:'production' | ['production', 'development']
8 const { errorLog: needErrorLog } = settings
9
10 function checkNeed() {
11 const env = process.env.NODE_ENV
12 if (isString(needErrorLog)) {
13 return env === needErrorLog
14 }
15 if (isArray(needErrorLog)) {
16 return needErrorLog.includes(env)
17 }
18 return false
19 }
20
21 if (checkNeed()) {
22 Vue.config.errorHandler = function(err, vm, info, a) {
23 // Don't ask me why I use Vue.nextTick, it just a hack.
24 // detail see https://forum.vuejs.org/t/dispatch-in-vue-config-errorhandler-has-some-problem/23500
25 Vue.nextTick(() => {
26 store.dispatch('errorLog/addErrorLog', {
27 err,
28 vm,
29 info,
30 url: window.location.href
31 })
32 console.error(err, info)
33 })
34 }
35 }
36
src/utils/get-page-title.js
1 import defaultSettings from '@/settings' 1 import defaultSettings from '@/settings'
2 import i18n from '@/lang'
2 3
3 const title = defaultSettings.title || 'Vue Admin Template' 4 const title = defaultSettings.title || 'Vue Element Admin'
4 5
5 export default function getPageTitle(pageTitle) { 6 export default function getPageTitle(key) {
6 if (pageTitle) { 7 const hasKey = i18n.te(`route.${key}`)
7 return `${pageTitle} - ${title}` 8 if (hasKey) {
9 const pageName = i18n.t(`route.${key}`)
10 return `${pageName} - ${title}`
8 } 11 }
9 return `${title}` 12 return `${title}`
10 } 13 }
11 14
src/utils/i18n.js
File was created 1 // translate router.meta.title, be used in breadcrumb sidebar tagsview
2 export function generateTitle(title) {
3 const hasKey = this.$te('route.' + title)
4
5 if (hasKey) {
6 // $t :this method from vue-i18n, inject in @/lang/index.js
7 const translatedTitle = this.$t('route.' + title)
8
9 return translatedTitle
10 }
11 return title
12 }
13
src/utils/index.js
1 /** 1 /**
2 * Created by PanJiaChen on 16/11/18. 2 * Created by PanJiaChen on 16/11/18.
3 */ 3 */
4 4
5 /** 5 /**
6 * Parse the time to string 6 * Parse the time to string
7 * @param {(Object|string|number)} time 7 * @param {(Object|string|number)} time
8 * @param {string} cFormat 8 * @param {string} cFormat
9 * @returns {string | null} 9 * @returns {string | null}
10 */ 10 */
11 export function parseTime(time, cFormat) { 11 export function parseTime(time, cFormat) {
12 if (arguments.length === 0) { 12 if (arguments.length === 0) {
13 return null 13 return null
14 } 14 }
15 const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}' 15 const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
16 let date 16 let date
17 if (typeof time === 'object') { 17 if (typeof time === 'object') {
18 date = time 18 date = time
19 } else { 19 } else {
20 if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) { 20 if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
21 time = parseInt(time) 21 time = parseInt(time)
22 } 22 }
23 if ((typeof time === 'number') && (time.toString().length === 10)) { 23 if ((typeof time === 'number') && (time.toString().length === 10)) {
24 time = time * 1000 24 time = time * 1000
25 } 25 }
26 date = new Date(time) 26 date = new Date(time)
27 } 27 }
28 const formatObj = { 28 const formatObj = {
29 y: date.getFullYear(), 29 y: date.getFullYear(),
30 m: date.getMonth() + 1, 30 m: date.getMonth() + 1,
31 d: date.getDate(), 31 d: date.getDate(),
32 h: date.getHours(), 32 h: date.getHours(),
33 i: date.getMinutes(), 33 i: date.getMinutes(),
34 s: date.getSeconds(), 34 s: date.getSeconds(),
35 a: date.getDay() 35 a: date.getDay()
36 } 36 }
37 const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => { 37 const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
38 const value = formatObj[key] 38 const value = formatObj[key]
39 // Note: getDay() returns 0 on Sunday 39 // Note: getDay() returns 0 on Sunday
40 if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] } 40 if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
41 return value.toString().padStart(2, '0') 41 return value.toString().padStart(2, '0')
42 }) 42 })
43 return time_str 43 return time_str
44 } 44 }
45 45
46 /** 46 /**
47 * @param {number} time 47 * @param {number} time
48 * @param {string} option 48 * @param {string} option
49 * @returns {string} 49 * @returns {string}
50 */ 50 */
51 export function formatTime(time, option) { 51 export function formatTime(time, option) {
52 if (('' + time).length === 10) { 52 if (('' + time).length === 10) {
53 time = parseInt(time) * 1000 53 time = parseInt(time) * 1000
54 } else { 54 } else {
55 time = +time 55 time = +time
56 } 56 }
57 const d = new Date(time) 57 const d = new Date(time)
58 const now = Date.now() 58 const now = Date.now()
59 59
60 const diff = (now - d) / 1000 60 const diff = (now - d) / 1000
61 61
62 if (diff < 30) { 62 if (diff < 30) {
63 return '刚刚' 63 return '刚刚'
64 } else if (diff < 3600) { 64 } else if (diff < 3600) {
65 // less 1 hour 65 // less 1 hour
66 return Math.ceil(diff / 60) + '分钟前' 66 return Math.ceil(diff / 60) + '分钟前'
67 } else if (diff < 3600 * 24) { 67 } else if (diff < 3600 * 24) {
68 return Math.ceil(diff / 3600) + '小时前' 68 return Math.ceil(diff / 3600) + '小时前'
69 } else if (diff < 3600 * 24 * 2) { 69 } else if (diff < 3600 * 24 * 2) {
70 return '1天前' 70 return '1天前'
71 } 71 }
72 if (option) { 72 if (option) {
73 return parseTime(time, option) 73 return parseTime(time, option)
74 } else { 74 } else {
75 return ( 75 return (
76 d.getMonth() + 76 d.getMonth() +
77 1 + 77 1 +
78 '月' + 78 '月' +
79 d.getDate() + 79 d.getDate() +
80 '日' + 80 '日' +
81 d.getHours() + 81 d.getHours() +
82 '时' + 82 '时' +
83 d.getMinutes() + 83 d.getMinutes() +
84 '分' 84 '分'
85 ) 85 )
86 } 86 }
87 } 87 }
88 88
89 /** 89 /**
90 * @param {string} url 90 * @param {string} url
91 * @returns {Object} 91 * @returns {Object}
92 */ 92 */
93 export function getQueryObject(url) {
94 url = url == null ? window.location.href : url
95 const search = url.substring(url.lastIndexOf('?') + 1)
96 const obj = {}
97 const reg = /([^?&=]+)=([^?&=]*)/g
98 search.replace(reg, (rs, $1, $2) => {
99 const name = decodeURIComponent($1)
100 let val = decodeURIComponent($2)
101 val = String(val)
102 obj[name] = val
103 return rs
104 })
105 return obj
106 }
107
108 /**
109 * @param {string} input value
110 * @returns {number} output value
111 */
112 export function byteLength(str) {
113 // returns the byte length of an utf8 string
114 let s = str.length
115 for (var i = str.length - 1; i >= 0; i--) {
116 const code = str.charCodeAt(i)
117 if (code > 0x7f && code <= 0x7ff) s++
118 else if (code > 0x7ff && code <= 0xffff) s += 2
119 if (code >= 0xDC00 && code <= 0xDFFF) i--
120 }
121 return s
122 }
123
124 /**
125 * @param {Array} actual
126 * @returns {Array}
127 */
128 export function cleanArray(actual) {
129 const newArray = []
130 for (let i = 0; i < actual.length; i++) {
131 if (actual[i]) {
132 newArray.push(actual[i])
133 }
134 }
135 return newArray
136 }
137
138 /**
139 * @param {Object} json
140 * @returns {Array}
141 */
142 export function param(json) {
143 if (!json) return ''
144 return cleanArray(
145 Object.keys(json).map(key => {
146 if (json[key] === undefined) return ''
147 return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
148 })
149 ).join('&')
150 }
151
152 /**
153 * @param {string} url
154 * @returns {Object}
155 */
93 export function param2Obj(url) { 156 export function param2Obj(url) {
94 const search = url.split('?')[1] 157 const search = url.split('?')[1]
95 if (!search) { 158 if (!search) {
96 return {} 159 return {}
97 } 160 }
98 return JSON.parse( 161 return JSON.parse(
99 '{"' + 162 '{"' +
100 decodeURIComponent(search) 163 decodeURIComponent(search)
101 .replace(/"/g, '\\"') 164 .replace(/"/g, '\\"')
102 .replace(/&/g, '","') 165 .replace(/&/g, '","')
103 .replace(/=/g, '":"') 166 .replace(/=/g, '":"')
104 .replace(/\+/g, ' ') + 167 .replace(/\+/g, ' ') +
105 '"}' 168 '"}'
106 ) 169 )
107 } 170 }
171
172 /**
173 * @param {string} val
174 * @returns {string}
175 */
176 export function html2Text(val) {
177 const div = document.createElement('div')
178 div.innerHTML = val
179 return div.textContent || div.innerText
180 }
181
182 /**
183 * Merges two objects, giving the last one precedence
184 * @param {Object} target
185 * @param {(Object|Array)} source
186 * @returns {Object}
187 */
188 export function objectMerge(target, source) {
189 if (typeof target !== 'object') {
190 target = {}
191 }
192 if (Array.isArray(source)) {
193 return source.slice()
194 }
195 Object.keys(source).forEach(property => {
196 const sourceProperty = source[property]
197 if (typeof sourceProperty === 'object') {
198 target[property] = objectMerge(target[property], sourceProperty)
199 } else {
200 target[property] = sourceProperty
201 }
202 })
203 return target
204 }
205
206 /**
207 * @param {HTMLElement} element
208 * @param {string} className
209 */
210 export function toggleClass(element, className) {
211 if (!element || !className) {
212 return
213 }
214 let classString = element.className
215 const nameIndex = classString.indexOf(className)
216 if (nameIndex === -1) {
217 classString += '' + className
218 } else {
219 classString =
220 classString.substr(0, nameIndex) +
221 classString.substr(nameIndex + className.length)
222 }
223 element.className = classString
224 }
225
226 /**
227 * @param {string} type
228 * @returns {Date}
229 */
230 export function getTime(type) {
231 if (type === 'start') {
232 return new Date().getTime() - 3600 * 1000 * 24 * 90
233 } else {
234 return new Date(new Date().toDateString())
235 }
236 }
237
238 /**
239 * @param {Function} func
240 * @param {number} wait
241 * @param {boolean} immediate
242 * @return {*}
243 */
244 export function debounce(func, wait, immediate) {
245 let timeout, args, context, timestamp, result
246
247 const later = function() {
248 // 据上一次触发时间间隔
249 const last = +new Date() - timestamp
250
251 // 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
252 if (last < wait && last > 0) {
253 timeout = setTimeout(later, wait - last)
254 } else {
255 timeout = null
256 // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
257 if (!immediate) {
258 result = func.apply(context, args)
259 if (!timeout) context = args = null
260 }
261 }
262 }
263
264 return function(...args) {
265 context = this
266 timestamp = +new Date()
267 const callNow = immediate && !timeout
268 // 如果延时不存在,重新设定延时
269 if (!timeout) timeout = setTimeout(later, wait)
270 if (callNow) {
271 result = func.apply(context, args)
272 context = args = null
273 }
274
275 return result
276 }
277 }
278
279 /**
280 * This is just a simple version of deep copy
281 * Has a lot of edge cases bug
282 * If you want to use a perfect deep copy, use lodash's _.cloneDeep
283 * @param {Object} source
284 * @returns {Object}
285 */
286 export function deepClone(source) {
287 if (!source && typeof source !== 'object') {
288 throw new Error('error arguments', 'deepClone')
289 }
290 const targetObj = source.constructor === Array ? [] : {}
291 Object.keys(source).forEach(keys => {
292 if (source[keys] && typeof source[keys] === 'object') {
293 targetObj[keys] = deepClone(source[keys])
294 } else {
295 targetObj[keys] = source[keys]
296 }
297 })
298 return targetObj
299 }
300
301 /**
302 * @param {Array} arr
303 * @returns {Array}
304 */
305 export function uniqueArr(arr) {
306 return Array.from(new Set(arr))
307 }
308
309 /**
310 * @returns {string}
311 */
312 export function createUniqueString() {
313 const timestamp = +new Date() + ''
314 const randomNum = parseInt((1 + Math.random()) * 65536) + ''
315 return (+(randomNum + timestamp)).toString(32)
316 }
317
318 /**
319 * Check if an element has a class
320 * @param {HTMLElement} elm
321 * @param {string} cls
322 * @returns {boolean}
323 */
324 export function hasClass(ele, cls) {
325 return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
326 }
327
328 /**
329 * Add class to element
330 * @param {HTMLElement} elm
331 * @param {string} cls
332 */
333 export function addClass(ele, cls) {
334 if (!hasClass(ele, cls)) ele.className += ' ' + cls
335 }
336
337 /**
338 * Remove class from element
339 * @param {HTMLElement} elm
340 * @param {string} cls
341 */
342 export function removeClass(ele, cls) {
343 if (hasClass(ele, cls)) {
344 const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
345 ele.className = ele.className.replace(reg, ' ')
346 }
347 }
108 348
src/utils/open-window.js
File was created 1 /**
2 *Created by PanJiaChen on 16/11/29.
3 * @param {Sting} url
4 * @param {Sting} title
5 * @param {Number} w
6 * @param {Number} h
7 */
8 export default function openWindow(url, title, w, h) {
9 // Fixes dual-screen position Most browsers Firefox
10 const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left
11 const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top
12
13 const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width
14 const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height
15
16 const left = ((width / 2) - (w / 2)) + dualScreenLeft
17 const top = ((height / 2) - (h / 2)) + dualScreenTop
18 const newWindow = window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left)
19
20 // Puts focus on the newWindow
21 if (window.focus) {
22 newWindow.focus()
23 }
24 }
25
26
src/utils/permission.js
File was created 1 import store from '@/store'
2
3 /**
4 * @param {Array} value
5 * @returns {Boolean}
6 * @example see @/views/permission/directive.vue
7 */
8 export default function checkPermission(value) {
9 if (value && value instanceof Array && value.length > 0) {
10 const roles = store.getters && store.getters.roles
11 const permissionRoles = value
12
13 const hasPermission = roles.some(role => {
14 return permissionRoles.includes(role)
15 })
16
17 if (!hasPermission) {
18 return false
19 }
20 return true
21 } else {
22 console.error(`need roles! Like v-permission="['admin','editor']"`)
23 return false
24 }
25 }
26
src/utils/request.js
1 import axios from 'axios' 1 import axios from 'axios'
2 import { 2 import { MessageBox, Message } from 'element-ui'
3 MessageBox,
4 Message
5 } from 'element-ui'
6 import store from '@/store' 3 import store from '@/store'
7 import { 4 import { getToken } from '@/utils/auth'
8 getToken
9 } from '@/utils/auth'
10 5
11 // create an axios instance 6 // create an axios instance
12 // 创建axios实例
13 const service = axios.create({ 7 const service = axios.create({
14 // baseURL: '', // url = base url + request url
15 baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url 8 baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
16 // withCredentials: true, // send cookies when cross-domain requests 9 // withCredentials: true, // send cookies when cross-domain requests
17 timeout: 5000, // request timeout 10 timeout: 5000 // request timeout
18 // headers: {
19 // 'Content-Type': 'application/x-www-form-urlencoded'
20 // }
21 }) 11 })
22 12
23 // request interceptor 13 // request interceptor
24 // request拦截器
25 service.interceptors.request.use( 14 service.interceptors.request.use(
26 config => { 15 config => {
27 // do something before request is sent 16 // do something before request is sent
28 // console.log('do something before request is sent') 17
29 if (store.getters.token) { 18 if (store.getters.token) {
30 // console.log('[X-Token] is a custom headers key')
31 // let each request carry token 19 // let each request carry token
32 // ['X-Token'] is a custom headers key 20 // ['X-Token'] is a custom headers key
33 // please modify it according to the actual situation 21 // please modify it according to the actual situation
34 config.headers['X-Token'] = getToken(); 22 config.headers['X-Token'] = getToken()
35 // config.headers['Content-Type'] = 'application/x-www-form-urlencoded';
36 // var token = getToken()
37 // Object.assign(config.headers, { 'token': token })
38 } 23 }
39 return config 24 return config
40 }, 25 },
41 error => { 26 error => {
42 // console.log('do something with request error')
43 // do something with request error 27 // do something with request error
44 console.error('出现错误。在use里。======>', error) // for debug 28 console.log(error) // for debug
45 return Promise.reject(error) 29 return Promise.reject(error)
46 } 30 }
47 ) 31 )
48 32
49 // response interceptor 33 // response interceptor
50 // respone拦截器
51 service.interceptors.response.use( 34 service.interceptors.response.use(
52 /** 35 /**
53 * If you want to get http information such as headers or status 36 * If you want to get http information such as headers or status
54 * Please return response => response 37 * Please return response => response
55 */ 38 */
56 39
57 /** 40 /**
58 * Determine the request status by custom code 41 * Determine the request status by custom code
59 * Here is just an example 42 * Here is just an example
60 * You can also judge the status by HTTP Status Code 43 * You can also judge the status by HTTP Status Code
61 */ 44 */
62 response => { 45 response => {
63 const res = response.data 46 const res = response.data
64 console.log('返回的数据-- step 1------>', res); 47
65 /** 48 // if the custom code is not 20000, it is judged as an error.
66 * 下面的注释为通过response自定义code来标示请求状态,当code返回如下情况为权限有问题,登出并返回到登录页
67 * 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中
68 */
69 // console.log('if the custom code is not 20000, it is judged as an error.')
70 if (res.code !== 20000) { 49 if (res.code !== 20000) {
71 Message({ 50 Message({
72 message: res.message || 'Error', 51 message: res.message || 'Error',
73 type: 'error', 52 type: 'error',
74 duration: 5 * 1000 53 duration: 5 * 1000
75 }) 54 })
76 55
77 // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了; 56 // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
78 if (res.code === 50008 || res.code === 50012 || res.code === 50014) { 57 if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
79 // to re-login 58 // to re-login
80 // MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { 59 MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
81 MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', { 60 confirmButtonText: 'Re-Login',
82 // confirmButtonText: 'Re-Login', 61 cancelButtonText: 'Cancel',
83 confirmButtonText: '重新登录',
84 // cancelButtonText: 'Cancel',
85 cancelButtonText: '取消',
86 type: 'warning' 62 type: 'warning'
87 }).then(() => { 63 }).then(() => {
88 store.dispatch('user/resetToken').then(() => { 64 store.dispatch('user/resetToken').then(() => {
89 location.reload() // 为了重新实例化vue-router对象 避免bug 65 location.reload()
90 }) 66 })
91 }) 67 })
92 } 68 }
93 return Promise.reject(new Error(res.message || 'Error')) 69 return Promise.reject(new Error(res.message || 'Error'))
94 } else { 70 } else {
95 // const token = res.data.token; 71 return res
96 console.log('进入20000号判断- step 2------->', res.data);
97 const data = res.data;
98 return data;
99 } 72 }
100 }, 73 },
101 error => { 74 error => {
102 console.error('===============发生错误!!!!!===============' + error.message); // for debug 75 console.log('err' + error) // for debug
103 // Message({ 76 Message({
104 // message: error.message, 77 message: error.message,
105 // type: 'error', 78 type: 'error',
106 // duration: 5 * 1000 79 duration: 5 * 1000
107 // }) 80 })
108 return Promise.reject(error) 81 return Promise.reject(error)
109 } 82 }
110 ) 83 )
111 84
112 export default service 85 export default service
113 86
src/utils/scroll-to.js
File was created 1 Math.easeInOutQuad = function(t, b, c, d) {
2 t /= d / 2
3 if (t < 1) {
4 return c / 2 * t * t + b
5 }
6 t--
7 return -c / 2 * (t * (t - 2) - 1) + b
8 }
9
10 // requestAnimationFrame for Smart Animating http://goo.gl/sx5sts
11 var requestAnimFrame = (function() {
12 return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function(callback) { window.setTimeout(callback, 1000 / 60) }
13 })()
14
15 /**
16 * Because it's so fucking difficult to detect the scrolling element, just move them all
17 * @param {number} amount
18 */
19 function move(amount) {
20 document.documentElement.scrollTop = amount
21 document.body.parentNode.scrollTop = amount
22 document.body.scrollTop = amount
23 }
24
25 function position() {
26 return document.documentElement.scrollTop || document.body.parentNode.scrollTop || document.body.scrollTop
27 }
28
29 /**
30 * @param {number} to
31 * @param {number} duration
32 * @param {Function} callback
33 */
34 export function scrollTo(to, duration, callback) {
35 const start = position()
36 const change = to - start
37 const increment = 20
38 let currentTime = 0
39 duration = (typeof (duration) === 'undefined') ? 500 : duration
40 var animateScroll = function() {
41 // increment the time
42 currentTime += increment
43 // find the value with the quadratic in-out easing function
44 var val = Math.easeInOutQuad(currentTime, start, change, duration)
45 // move the document.body
46 move(val)
47 // do the animation unless its over
48 if (currentTime < duration) {
49 requestAnimFrame(animateScroll)
50 } else {
51 if (callback && typeof (callback) === 'function') {
52 // the animation is done so lets callback
53 callback()
54 }
55 }
56 }
57 animateScroll()
58 }
59
src/utils/validate.js
1 /** 1 /**
2 * Created by PanJiaChen on 16/11/18. 2 * Created by PanJiaChen on 16/11/18.
3 */ 3 */
4 4
5 /** 5 /**
6 * @param {string} path 6 * @param {string} path
7 * @returns {Boolean} 7 * @returns {Boolean}
8 */ 8 */
9 export function isExternal(path) { 9 export function isExternal(path) {
10 return /^(https?:|mailto:|tel:)/.test(path) 10 return /^(https?:|mailto:|tel:)/.test(path)
11 } 11 }
12 12
13 /** 13 /**
14 * @param {string} str 14 * @param {string} str
15 * @returns {Boolean} 15 * @returns {Boolean}
16 */ 16 */
17 export function validUsername(str) { 17 export function validUsername(str) {
18 const valid_map = ['admin', 'editor'] 18 const valid_map = ['admin', 'editor']
19 return valid_map.indexOf(str.trim()) >= 0 19 return valid_map.indexOf(str.trim()) >= 0
20 } 20 }
21
22 /**
23 * @param {string} url
24 * @returns {Boolean}
25 */
26 export function validURL(url) {
27 const reg = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/
28 return reg.test(url)
29 }
30
31 /**
32 * @param {string} str
33 * @returns {Boolean}
34 */
35 export function validLowerCase(str) {
36 const reg = /^[a-z]+$/
37 return reg.test(str)
38 }
39
40 /**
41 * @param {string} str
42 * @returns {Boolean}
43 */
44 export function validUpperCase(str) {
45 const reg = /^[A-Z]+$/
46 return reg.test(str)
47 }
48
49 /**
50 * @param {string} str
51 * @returns {Boolean}
52 */
53 export function validAlphabets(str) {
54 const reg = /^[A-Za-z]+$/
55 return reg.test(str)
56 }
57
58 /**
59 * @param {string} email
60 * @returns {Boolean}
61 */
62 export function validEmail(email) {
63 const reg = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
64 return reg.test(email)
65 }
66
67 /**
68 * @param {string} str
69 * @returns {Boolean}
70 */
71 export function isString(str) {
72 if (typeof str === 'string' || str instanceof String) {
73 return true
74 }
75 return false
76 }
77
78 /**
79 * @param {Array} arg
80 * @returns {Boolean}
81 */
82 export function isArray(arg) {
83 if (typeof Array.isArray === 'undefined') {
84 return Object.prototype.toString.call(arg) === '[object Array]'
85 }
86 return Array.isArray(arg)
87 }
21 88
src/vendor/Export2Excel.js
File was created 1 /* eslint-disable */
2 import { saveAs } from 'file-saver'
3 import XLSX from 'xlsx'
4
5 function generateArray(table) {
6 var out = [];
7 var rows = table.querySelectorAll('tr');
8 var ranges = [];
9 for (var R = 0; R < rows.length; ++R) {
10 var outRow = [];
11 var row = rows[R];
12 var columns = row.querySelectorAll('td');
13 for (var C = 0; C < columns.length; ++C) {
14 var cell = columns[C];
15 var colspan = cell.getAttribute('colspan');
16 var rowspan = cell.getAttribute('rowspan');
17 var cellValue = cell.innerText;
18 if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;
19
20 //Skip ranges
21 ranges.forEach(function (range) {
22 if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
23 for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
24 }
25 });
26
27 //Handle Row Span
28 if (rowspan || colspan) {
29 rowspan = rowspan || 1;
30 colspan = colspan || 1;
31 ranges.push({
32 s: {
33 r: R,
34 c: outRow.length
35 },
36 e: {
37 r: R + rowspan - 1,
38 c: outRow.length + colspan - 1
39 }
40 });
41 };
42
43 //Handle Value
44 outRow.push(cellValue !== "" ? cellValue : null);
45
46 //Handle Colspan
47 if (colspan)
48 for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
49 }
50 out.push(outRow);
51 }
52 return [out, ranges];
53 };
54
55 function datenum(v, date1904) {
56 if (date1904) v += 1462;
57 var epoch = Date.parse(v);
58 return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
59 }
60
61 function sheet_from_array_of_arrays(data, opts) {
62 var ws = {};
63 var range = {
64 s: {
65 c: 10000000,
66 r: 10000000
67 },
68 e: {
69 c: 0,
70 r: 0
71 }
72 };
73 for (var R = 0; R != data.length; ++R) {
74 for (var C = 0; C != data[R].length; ++C) {
75 if (range.s.r > R) range.s.r = R;
76 if (range.s.c > C) range.s.c = C;
77 if (range.e.r < R) range.e.r = R;
78 if (range.e.c < C) range.e.c = C;
79 var cell = {
80 v: data[R][C]
81 };
82 if (cell.v == null) continue;
83 var cell_ref = XLSX.utils.encode_cell({
84 c: C,
85 r: R
86 });
87
88 if (typeof cell.v === 'number') cell.t = 'n';
89 else if (typeof cell.v === 'boolean') cell.t = 'b';
90 else if (cell.v instanceof Date) {
91 cell.t = 'n';
92 cell.z = XLSX.SSF._table[14];
93 cell.v = datenum(cell.v);
94 } else cell.t = 's';
95
96 ws[cell_ref] = cell;
97 }
98 }
99 if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
100 return ws;
101 }
102
103 function Workbook() {
104 if (!(this instanceof Workbook)) return new Workbook();
105 this.SheetNames = [];
106 this.Sheets = {};
107 }
108
109 function s2ab(s) {
110 var buf = new ArrayBuffer(s.length);
111 var view = new Uint8Array(buf);
112 for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
113 return buf;
114 }
115
116 export function export_table_to_excel(id) {
117 var theTable = document.getElementById(id);
118 var oo = generateArray(theTable);
119 var ranges = oo[1];
120
121 /* original data */
122 var data = oo[0];
123 var ws_name = "SheetJS";
124
125 var wb = new Workbook(),
126 ws = sheet_from_array_of_arrays(data);
127
128 /* add ranges to worksheet */
129 // ws['!cols'] = ['apple', 'banan'];
130 ws['!merges'] = ranges;
131
132 /* add worksheet to workbook */
133 wb.SheetNames.push(ws_name);
134 wb.Sheets[ws_name] = ws;
135
136 var wbout = XLSX.write(wb, {
137 bookType: 'xlsx',
138 bookSST: false,
139 type: 'binary'
140 });
141
142 saveAs(new Blob([s2ab(wbout)], {
143 type: "application/octet-stream"
144 }), "test.xlsx")
145 }
146
147 export function export_json_to_excel({
148 multiHeader = [],
149 header,
150 data,
151 filename,
152 merges = [],
153 autoWidth = true,
154 bookType = 'xlsx'
155 } = {}) {
156 /* original data */
157 filename = filename || 'excel-list'
158 data = [...data]
159 data.unshift(header);
160
161 for (let i = multiHeader.length - 1; i > -1; i--) {
162 data.unshift(multiHeader[i])
163 }
164
165 var ws_name = "SheetJS";
166 var wb = new Workbook(),
167 ws = sheet_from_array_of_arrays(data);
168
169 if (merges.length > 0) {
170 if (!ws['!merges']) ws['!merges'] = [];
171 merges.forEach(item => {
172 ws['!merges'].push(XLSX.utils.decode_range(item))
173 })
174 }
175
176 if (autoWidth) {
177 /*设置worksheet每列的最大宽度*/
178 const colWidth = data.map(row => row.map(val => {
179 /*先判断是否为null/undefined*/
180 if (val == null) {
181 return {
182 'wch': 10
183 };
184 }
185 /*再判断是否为中文*/
186 else if (val.toString().charCodeAt(0) > 255) {
187 return {
188 'wch': val.toString().length * 2
189 };
190 } else {
191 return {
192 'wch': val.toString().length
193 };
194 }
195 }))
196 /*以第一行为初始值*/
197 let result = colWidth[0];
198 for (let i = 1; i < colWidth.length; i++) {
199 for (let j = 0; j < colWidth[i].length; j++) {
200 if (result[j]['wch'] < colWidth[i][j]['wch']) {
201 result[j]['wch'] = colWidth[i][j]['wch'];
202 }
203 }
204 }
205 ws['!cols'] = result;
206 }
207
208 /* add worksheet to workbook */
209 wb.SheetNames.push(ws_name);
210 wb.Sheets[ws_name] = ws;
211
212 var wbout = XLSX.write(wb, {
213 bookType: bookType,
214 bookSST: false,
215 type: 'binary'
216 });
217 saveAs(new Blob([s2ab(wbout)], {
218 type: "application/octet-stream"
219 }), `${filename}.${bookType}`);
220 }
221
src/vendor/Export2Zip.js
File was created 1 /* eslint-disable */
2 import { saveAs } from 'file-saver'
3 import JSZip from 'jszip'
4
5 export function export_txt_to_zip(th, jsonData, txtName, zipName) {
6 const zip = new JSZip()
7 const txt_name = txtName || 'file'
8 const zip_name = zipName || 'file'
9 const data = jsonData
10 let txtData = `${th}\r\n`
11 data.forEach((row) => {
12 let tempStr = ''
13 tempStr = row.toString()
14 txtData += `${tempStr}\r\n`
15 })
16 zip.file(`${txt_name}.txt`, txtData)
17 zip.generateAsync({
18 type: "blob"
19 }).then((blob) => {
20 saveAs(blob, `${zip_name}.zip`)
21 }, (err) => {
22 alert('导出失败')
23 })
24 }
25
src/views/404.vue
1 <template> File was deleted
2 <div class="wscn-http404-container">
3 <div class="wscn-http404">
4 <div class="pic-404">
5 <img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404" />
6 <img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404" />
7 <img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404" />
8 <img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404" />
9 </div>
10 <div class="bullshit">
11 <div class="bullshit__oops">OOPS!</div>
12 <div class="bullshit__info">
13 All rights reserved
14 <a
15 style="color:#20a0ff"
16 href="https://wallstreetcn.com"
17 target="_blank"
18 >wallstreetcn</a>
19 </div>
20 <div class="bullshit__headline">{{ message }}</div>
21 <div
22 class="bullshit__info"
23 >Please check that the URL you entered is correct, or click the button below to return to the homepage.</div>
24 <a href class="bullshit__return-home">Back to home</a>
25 </div>
26 </div>
27 </div>
28 </template>
29
30 <script>
31 export default {
32 name: "Page404",
33 computed: {
34 message() {
35 return "The webmaster said that you can not enter this page...";
36 }
37 }
38 };
39 </script>
40
41 <style lang="scss" scoped>
42 .wscn-http404-container {
43 transform: translate(-50%, -50%);
44 position: absolute;
45 top: 40%;
46 left: 50%;
47 }
48 .wscn-http404 {
49 position: relative;
50 width: 1200px;
51 padding: 0 50px;
52 overflow: hidden;
53 .pic-404 {
54 position: relative;
55 float: left;
56 width: 600px;
57 overflow: hidden;
58 &__parent {
59 width: 100%;
60 }
61 &__child {
62 position: absolute;
63 &.left {
64 width: 80px;
65 top: 17px;
66 left: 220px;
67 opacity: 0;
68 animation-name: cloudLeft;
69 animation-duration: 2s;
70 animation-timing-function: linear;
71 animation-fill-mode: forwards;
72 animation-delay: 1s;
73 }
74 &.mid {
75 width: 46px;
76 top: 10px;
77 left: 420px;
78 opacity: 0;
79 animation-name: cloudMid;
80 animation-duration: 2s;
81 animation-timing-function: linear;
82 animation-fill-mode: forwards;
83 animation-delay: 1.2s;
84 }
85 &.right {
86 width: 62px;
87 top: 100px;
88 left: 500px;
89 opacity: 0;
90 animation-name: cloudRight;
91 animation-duration: 2s;
92 animation-timing-function: linear;
93 animation-fill-mode: forwards;
94 animation-delay: 1s;
95 }
96 @keyframes cloudLeft {
97 0% {
98 top: 17px;
99 left: 220px;
100 opacity: 0;
101 }
102 20% {
103 top: 33px;
104 left: 188px;
105 opacity: 1;
106 }
107 80% {
108 top: 81px;
109 left: 92px;
110 opacity: 1;
111 }
112 100% {
113 top: 97px;
114 left: 60px;
115 opacity: 0;
116 }
117 }
118 @keyframes cloudMid {
119 0% {
120 top: 10px;
121 left: 420px;
122 opacity: 0;
123 }
124 20% {
125 top: 40px;
126 left: 360px;
127 opacity: 1;
128 }
129 70% {
130 top: 130px;
131 left: 180px;
132 opacity: 1;
133 }
134 100% {
135 top: 160px;
136 left: 120px;
137 opacity: 0;
138 }
139 }
140 @keyframes cloudRight {
141 0% {
142 top: 100px;
143 left: 500px;
144 opacity: 0;
145 }
146 20% {
147 top: 120px;
148 left: 460px;
149 opacity: 1;
150 }
151 80% {
152 top: 180px;
153 left: 340px;
154 opacity: 1;
155 }
156 100% {
157 top: 200px;
158 left: 300px;
159 opacity: 0;
160 }
161 }
162 }
163 }
164 .bullshit {
165 position: relative;
166 float: left;
167 width: 300px;
168 padding: 30px 0;
169 overflow: hidden;
170 &__oops {
171 font-size: 32px;
172 font-weight: bold;
173 line-height: 40px;
174 color: #1482f0;
175 opacity: 0;
176 margin-bottom: 20px;
177 animation-name: slideUp;
178 animation-duration: 0.5s;
179 animation-fill-mode: forwards;
180 }
181 &__headline {
182 font-size: 20px;
183 line-height: 24px;
184 color: #222;
185 font-weight: bold;
186 opacity: 0;
187 margin-bottom: 10px;
188 animation-name: slideUp;
189 animation-duration: 0.5s;
190 animation-delay: 0.1s;
191 animation-fill-mode: forwards;
192 }
193 &__info {
194 font-size: 13px;
195 line-height: 21px;
196 color: grey;
197 opacity: 0;
198 margin-bottom: 30px;
199 animation-name: slideUp;
200 animation-duration: 0.5s;
201 animation-delay: 0.2s;
202 animation-fill-mode: forwards;
203 }
204 &__return-home {
205 display: block;
206 float: left;
207 width: 110px;
208 height: 36px;
209 background: #1482f0;
210 border-radius: 100px;
211 text-align: center;
212 color: #ffffff;
213 opacity: 0;
214 font-size: 14px;
215 line-height: 36px;
216 cursor: pointer;
217 animation-name: slideUp;
218 animation-duration: 0.5s;
219 animation-delay: 0.3s;
220 animation-fill-mode: forwards;
221 }
222 @keyframes slideUp {
223 0% {
224 transform: translateY(60px);
225 opacity: 0;
226 }
227 100% {
228 transform: translateY(0);
229 opacity: 1;
230 }
231 }
232 }
233 }
234 </style>
235 1 <template>
src/views/charts/keyboard.vue
File was created 1 <template>
2 <div class="chart-container">
3 <chart height="100%" width="100%" />
4 </div>
5 </template>
6
7 <script>
8 import Chart from '@/components/Charts/Keyboard'
9
10 export default {
11 name: 'KeyboardChart',
12 components: { Chart }
13 }
14 </script>
15
16 <style scoped>
17 .chart-container{
18 position: relative;
19 width: 100%;
20 height: calc(100vh - 84px);
21 }
22 </style>
23
24
src/views/charts/line.vue
File was created 1 <template>
2 <div class="chart-container">
3 <chart height="100%" width="100%" />
4 </div>
5 </template>
6
7 <script>
8 import Chart from '@/components/Charts/LineMarker'
9
10 export default {
11 name: 'LineChart',
12 components: { Chart }
13 }
14 </script>
15
16 <style scoped>
17 .chart-container{
18 position: relative;
19 width: 100%;
20 height: calc(100vh - 84px);
21 }
22 </style>
23
24
src/views/charts/mix-chart.vue
File was created 1 <template>
2 <div class="chart-container">
3 <chart height="100%" width="100%" />
4 </div>
5 </template>
6
7 <script>
8 import Chart from '@/components/Charts/MixChart'
9
10 export default {
11 name: 'MixChart',
12 components: { Chart }
13 }
14 </script>
15
16 <style scoped>
17 .chart-container{
18 position: relative;
19 width: 100%;
20 height: calc(100vh - 84px);
21 }
22 </style>
23
24
src/views/clipboard/index.vue
File was created 1 <template>
2 <div class="app-container">
3 <el-tabs v-model="activeName">
4 <el-tab-pane label="use clipboard directly" name="directly">
5 <el-input v-model="inputData" placeholder="Please input" style="width:400px;max-width:100%;" />
6 <el-button type="primary" icon="el-icon-document" @click="handleCopy(inputData,$event)">
7 copy
8 </el-button>
9 </el-tab-pane>
10 <el-tab-pane label="use clipboard by v-directive" name="v-directive">
11 <el-input v-model="inputData" placeholder="Please input" style="width:400px;max-width:100%;" />
12 <el-button v-clipboard:copy="inputData" v-clipboard:success="clipboardSuccess" type="primary" icon="el-icon-document">
13 copy
14 </el-button>
15 </el-tab-pane>
16 </el-tabs>
17 </div>
18 </template>
19
20 <script>
21 import clip from '@/utils/clipboard' // use clipboard directly
22 import clipboard from '@/directive/clipboard/index.js' // use clipboard by v-directive
23
24 export default {
25 name: 'ClipboardDemo',
26 directives: {
27 clipboard
28 },
29 data() {
30 return {
31 activeName: 'directly',
32 inputData: 'https://github.com/PanJiaChen/vue-element-admin'
33 }
34 },
35 methods: {
36 handleCopy(text, event) {
37 clip(text, event)
38 },
39 clipboardSuccess() {
40 this.$message({
41 message: 'Copy successfully',
42 type: 'success',
43 duration: 1500
44 })
45 }
46 }
47 }
48 </script>
49
50
src/views/components-demo/avatar-upload.vue
File was created 1 <template>
2 <div class="components-container">
3 <aside>This is based on
4 <a class="link-type" href="//github.com/dai-siki/vue-image-crop-upload"> vue-image-crop-upload</a>.
5 {{ $t('components.imageUploadTips') }}
6 </aside>
7
8 <pan-thumb :image="image" />
9
10 <el-button type="primary" icon="el-icon-upload" style="position: absolute;bottom: 15px;margin-left: 40px;" @click="imagecropperShow=true">
11 Change Avatar
12 </el-button>
13
14 <image-cropper
15 v-show="imagecropperShow"
16 :key="imagecropperKey"
17 :width="300"
18 :height="300"
19 url="https://httpbin.org/post"
20 lang-type="en"
21 @close="close"
22 @crop-upload-success="cropSuccess"
23 />
24 </div>
25 </template>
26
27 <script>
28 import ImageCropper from '@/components/ImageCropper'
29 import PanThumb from '@/components/PanThumb'
30
31 export default {
32 name: 'AvatarUploadDemo',
33 components: { ImageCropper, PanThumb },
34 data() {
35 return {
36 imagecropperShow: false,
37 imagecropperKey: 0,
38 image: 'https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191'
39 }
40 },
41 methods: {
42 cropSuccess(resData) {
43 this.imagecropperShow = false
44 this.imagecropperKey = this.imagecropperKey + 1
45 this.image = resData.files.avatar
46 },
47 close() {
48 this.imagecropperShow = false
49 }
50 }
51 }
52 </script>
53
54 <style scoped>
55 .avatar{
56 width: 200px;
57 height: 200px;
58 border-radius: 50%;
59 }
60 </style>
61
62
src/views/components-demo/back-to-top.vue
File was created 1 <template>
2 <div class="components-container">
3 <aside>{{ $t('components.backToTopTips1') }}</aside>
4 <aside>{{ $t('components.backToTopTips2') }}</aside>
5 <div class="placeholder-container">
6 <div>placeholder</div>
7 <div>placeholder</div>
8 <div>placeholder</div>
9 <div>placeholder</div>
10 <div>placeholder</div>
11 <div>placeholder</div>
12 <div>placeholder</div>
13 <div>placeholder</div>
14 <div>placeholder</div>
15 <div>placeholder</div>
16 <div>placeholder</div>
17 <div>placeholder</div>
18 <div>placeholder</div>
19 <div>placeholder</div>
20 <div>placeholder</div>
21 <div>placeholder</div>
22 <div>placeholder</div>
23 <div>placeholder</div>
24 <div>placeholder</div>
25 <div>placeholder</div>
26 <div>placeholder</div>
27 <div>placeholder</div>
28 <div>placeholder</div>
29 <div>placeholder</div>
30 <div>placeholder</div>
31 <div>placeholder</div>
32 <div>placeholder</div>
33 <div>placeholder</div>
34 <div>placeholder</div>
35 <div>placeholder</div>
36 <div>placeholder</div>
37 <div>placeholder</div>
38 <div>placeholder</div>
39 <div>placeholder</div>
40 <div>placeholder</div>
41 <div>placeholder</div>
42 <div>placeholder</div>
43 <div>placeholder</div>
44 <div>placeholder</div>
45 <div>placeholder</div>
46 <div>placeholder</div>
47 <div>placeholder</div>
48 <div>placeholder</div>
49 <div>placeholder</div>
50 <div>placeholder</div>
51 <div>placeholder</div>
52 <div>placeholder</div>
53 <div>placeholder</div>
54 <div>placeholder</div>
55 <div>placeholder</div>
56 <div>placeholder</div>
57 <div>placeholder</div>
58 <div>placeholder</div>
59 <div>placeholder</div>
60 <div>placeholder</div>
61 <div>placeholder</div>
62 <div>placeholder</div>
63 <div>placeholder</div>
64 <div>placeholder</div>
65 <div>placeholder</div>
66 <div>placeholder</div>
67 <div>placeholder</div>
68 <div>placeholder</div>
69 <div>placeholder</div>
70 <div>placeholder</div>
71 <div>placeholder</div>
72 <div>placeholder</div>
73 <div>placeholder</div>
74 <div>placeholder</div>
75 <div>placeholder</div>
76 <div>placeholder</div>
77 <div>placeholder</div>
78 <div>placeholder</div>
79 <div>placeholder</div>
80 <div>placeholder</div>
81 <div>placeholder</div>
82 <div>placeholder</div>
83 <div>placeholder</div>
84 <div>placeholder</div>
85 <div>placeholder</div>
86 <div>placeholder</div>
87 <div>placeholder</div>
88 <div>placeholder</div>
89 <div>placeholder</div>
90 <div>placeholder</div>
91 <div>placeholder</div>
92 <div>placeholder</div>
93 <div>placeholder</div>
94 <div>placeholder</div>
95 <div>placeholder</div>
96 <div>placeholder</div>
97 <div>placeholder</div>
98 <div>placeholder</div>
99 <div>placeholder</div>
100 <div>placeholder</div>
101 <div>placeholder</div>
102 <div>placeholder</div>
103 <div>placeholder</div>
104 <div>placeholder</div>
105 <div>placeholder</div>
106 <div>placeholder</div>
107 <div>placeholder</div>
108 <div>placeholder</div>
109 <div>placeholder</div>
110 <div>placeholder</div>
111 <div>placeholder</div>
112 <div>placeholder</div>
113 <div>placeholder</div>
114 <div>placeholder</div>
115 </div>
116 <!-- you can add element-ui's tooltip -->
117 <el-tooltip placement="top" content="tooltip">
118 <back-to-top :custom-style="myBackToTopStyle" :visibility-height="300" :back-position="50" transition-name="fade" />
119 </el-tooltip>
120 </div>
121 </template>
122
123 <script>
124 import BackToTop from '@/components/BackToTop'
125
126 export default {
127 name: 'BackToTopDemo',
128 components: { BackToTop },
129 data() {
130 return {
131 // customizable button style, show/hide critical point, return position
132 myBackToTopStyle: {
133 right: '50px',
134 bottom: '50px',
135 width: '40px',
136 height: '40px',
137 'border-radius': '4px',
138 'line-height': '45px', // 请保持与高度一致以垂直居中 Please keep consistent with height to center vertically
139 background: '#e7eaf1'// 按钮的背景颜色 The background color of the button
140 }
141 }
142 }
143 }
144 </script>
145
146 <style scoped>
147 .placeholder-container div {
148 margin: 10px;
149 }
150 </style>
151
src/views/components-demo/count-to.vue
File was created 1 <template>
2 <div class="components-container">
3 <aside>
4 <a href="https://github.com/PanJiaChen/vue-countTo" target="_blank">countTo-component</a>
5 </aside>
6 <count-to
7 ref="example"
8 :start-val="_startVal"
9 :end-val="_endVal"
10 :duration="_duration"
11 :decimals="_decimals"
12 :separator="_separator"
13 :prefix="_prefix"
14 :suffix="_suffix"
15 :autoplay="false"
16 class="example"
17 />
18 <div style="margin-left: 25%;margin-top: 40px;">
19 <label class="label" for="startValInput">startVal:
20 <input v-model.number="setStartVal" type="number" name="startValInput">
21 </label>
22 <label class="label" for="endValInput">endVal:
23 <input v-model.number="setEndVal" type="number" name="endVaInput">
24 </label>
25 <label class="label" for="durationInput">duration:
26 <input v-model.number="setDuration" type="number" name="durationInput">
27 </label>
28 <div class="startBtn example-btn" @click="start">
29 Start
30 </div>
31 <div class="pause-resume-btn example-btn" @click="pauseResume">
32 pause/resume
33 </div>
34 <br>
35 <label class="label" for="decimalsInput">decimals:
36 <input v-model.number="setDecimals" type="number" name="decimalsInput">
37 </label>
38 <label class="label" for="separatorInput">separator:
39 <input v-model="setSeparator" name="separatorInput">
40 </label>
41 <label class="label" for="prefixInput">prefix:
42 <input v-model="setPrefix" name="prefixInput">
43 </label>
44 <label class="label" for="suffixInput">suffix:
45 <input v-model="setSuffix" name="suffixInput">
46 </label>
47 </div>
48 <aside>&lt;count-to :start-val=&#x27;{{ _startVal }}&#x27; :end-val=&#x27;{{ _endVal }}&#x27; :duration=&#x27;{{ _duration }}&#x27;
49 :decimals=&#x27;{{ _decimals }}&#x27; :separator=&#x27;{{ _separator }}&#x27; :prefix=&#x27;{{ _prefix }}&#x27; :suffix=&#x27;{{ _suffix }}&#x27;
50 :autoplay=false&gt;</aside>
51 </div>
52 </template>
53
54 <script>
55 import countTo from 'vue-count-to'
56
57 export default {
58 name: 'CountToDemo',
59 components: { countTo },
60 data() {
61 return {
62 setStartVal: 0,
63 setEndVal: 2017,
64 setDuration: 4000,
65 setDecimals: 0,
66 setSeparator: ',',
67 setSuffix: ' rmb',
68 setPrefix: '¥ '
69 }
70 },
71 computed: {
72 _startVal() {
73 if (this.setStartVal) {
74 return this.setStartVal
75 } else {
76 return 0
77 }
78 },
79 _endVal() {
80 if (this.setEndVal) {
81 return this.setEndVal
82 } else {
83 return 0
84 }
85 },
86 _duration() {
87 if (this.setDuration) {
88 return this.setDuration
89 } else {
90 return 100
91 }
92 },
93 _decimals() {
94 if (this.setDecimals) {
95 if (this.setDecimals < 0 || this.setDecimals > 20) {
96 alert('digits argument must be between 0 and 20')
97 return 0
98 }
99 return this.setDecimals
100 } else {
101 return 0
102 }
103 },
104 _separator() {
105 return this.setSeparator
106 },
107 _suffix() {
108 return this.setSuffix
109 },
110 _prefix() {
111 return this.setPrefix
112 }
113 },
114 methods: {
115 start() {
116 this.$refs.example.start()
117 },
118 pauseResume() {
119 this.$refs.example.pauseResume()
120 }
121 }
122 }
123 </script>
124
125 <style scoped>
126 .example-btn {
127 display: inline-block;
128 margin-bottom: 0;
129 font-weight: 500;
130 text-align: center;
131 -ms-touch-action: manipulation;
132 touch-action: manipulation;
133 cursor: pointer;
134 background-image: none;
135 border: 1px solid transparent;
136 white-space: nowrap;
137 line-height: 1.5;
138 padding: 4px 15px;
139 font-size: 12px;
140 border-radius: 4px;
141 -webkit-user-select: none;
142 -moz-user-select: none;
143 -ms-user-select: none;
144 user-select: none;
145 -webkit-transition: all .3s cubic-bezier(.645, .045, .355, 1);
146 transition: all .3s cubic-bezier(.645, .045, .355, 1);
147 position: relative;
148 color: rgba(0, 0, 0, .65);
149 background-color: #fff;
150 border-color: #d9d9d9;
151 }
152
153 .example-btn:hover {
154 color: #4AB7BD;
155 background-color: #fff;
156 border-color: #4AB7BD;
157 }
158 .example {
159 font-size: 50px;
160 color: #F6416C;
161 display: block;
162 margin: 10px 0;
163 text-align: center;
164 font-size: 80px;
165 font-weight: 500;
166 }
167
168 .label {
169 color: #2f4f4f;
170 font-size: 16px;
171 display: inline-block;
172 margin: 15px 30px 15px 0;
173 }
174
175 input {
176 position: relative;
177 display: inline-block;
178 padding: 4px 7px;
179 width: 70px;
180 height: 28px;
181 cursor: text;
182 font-size: 12px;
183 line-height: 1.5;
184 color: rgba(0, 0, 0, .65);
185 background-color: #fff;
186 background-image: none;
187 border: 1px solid #d9d9d9;
188 border-radius: 4px;
189 -webkit-transition: all .3s;
190 transition: all .3s;
191 }
192
193 .startBtn {
194 margin-left: 20px;
195 font-size: 20px;
196 color: #30B08F;
197 background-color: #fff;
198 }
199
200 .startBtn:hover {
201 background-color: #30B08F;
202 color: #fff;
203 border-color: #30B08F;
204 }
205
206 .pause-resume-btn {
207 font-size: 20px;
208 color: #E65D6E;
209 background-color: #fff;
210 }
211
212 .pause-resume-btn:hover {
213 background-color: #E65D6E;
214 color: #fff;
215 border-color: #E65D6E;
216 }
217 </style>
218
219
src/views/components-demo/dnd-list.vue
File was created 1 <template>
2 <div class="components-container">
3 <aside>drag-list base on
4 <a href="https://github.com/SortableJS/Vue.Draggable" target="_blank">Vue.Draggable</a>
5 </aside>
6 <div class="editor-container">
7 <dnd-list :list1="list1" :list2="list2" list1-title="List" list2-title="Article pool" />
8 </div>
9 </div>
10 </template>
11
12 <script>
13 import DndList from '@/components/DndList'
14 import { fetchList } from '@/api/article'
15
16 export default {
17 name: 'DndListDemo',
18 components: { DndList },
19 data() {
20 return {
21 list1: [],
22 list2: []
23 }
24 },
25 created() {
26 this.getData()
27 },
28 methods: {
29 getData() {
30 this.listLoading = true
31 fetchList().then(response => {
32 this.list1 = response.data.items.splice(0, 5)
33 this.list2 = response.data.items
34 })
35 }
36 }
37 }
38 </script>
39
40
src/views/components-demo/drag-dialog.vue
File was created 1 <template>
2 <div class="components-container">
3 <el-button type="primary" @click="dialogTableVisible = true">
4 open a Drag Dialog
5 </el-button>
6 <el-dialog v-el-drag-dialog :visible.sync="dialogTableVisible" title="Shipping address" @dragDialog="handleDrag">
7 <el-select ref="select" v-model="value" placeholder="请选择">
8 <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
9 </el-select>
10 <el-table :data="gridData">
11 <el-table-column property="date" label="Date" width="150" />
12 <el-table-column property="name" label="Name" width="200" />
13 <el-table-column property="address" label="Address" />
14 </el-table>
15 </el-dialog>
16 </div>
17 </template>
18
19 <script>
20 import elDragDialog from '@/directive/el-drag-dialog' // base on element-ui
21
22 export default {
23 name: 'DragDialogDemo',
24 directives: { elDragDialog },
25 data() {
26 return {
27 dialogTableVisible: false,
28 options: [
29 { value: '选项1', label: '黄金糕' },
30 { value: '选项2', label: '双皮奶' },
31 { value: '选项3', label: '蚵仔煎' },
32 { value: '选项4', label: '龙须面' }
33 ],
34 value: '',
35 gridData: [{
36 date: '2016-05-02',
37 name: 'John Smith',
38 address: 'No.1518, Jinshajiang Road, Putuo District'
39 }, {
40 date: '2016-05-04',
41 name: 'John Smith',
42 address: 'No.1518, Jinshajiang Road, Putuo District'
43 }, {
44 date: '2016-05-01',
45 name: 'John Smith',
46 address: 'No.1518, Jinshajiang Road, Putuo District'
47 }, {
48 date: '2016-05-03',
49 name: 'John Smith',
50 address: 'No.1518, Jinshajiang Road, Putuo District'
51 }]
52 }
53 },
54 methods: {
55 // v-el-drag-dialog onDrag callback function
56 handleDrag() {
57 this.$refs.select.blur()
58 }
59 }
60 }
61 </script>
62
src/views/components-demo/drag-kanban.vue
File was created 1 <template>
2 <div class="components-container board">
3 <Kanban :key="1" :list="list1" :group="group" class="kanban todo" header-text="Todo" />
4 <Kanban :key="2" :list="list2" :group="group" class="kanban working" header-text="Working" />
5 <Kanban :key="3" :list="list3" :group="group" class="kanban done" header-text="Done" />
6 </div>
7 </template>
8 <script>
9 import Kanban from '@/components/Kanban'
10
11 export default {
12 name: 'DragKanbanDemo',
13 components: {
14 Kanban
15 },
16 data() {
17 return {
18 group: 'mission',
19 list1: [
20 { name: 'Mission', id: 1 },
21 { name: 'Mission', id: 2 },
22 { name: 'Mission', id: 3 },
23 { name: 'Mission', id: 4 }
24 ],
25 list2: [
26 { name: 'Mission', id: 5 },
27 { name: 'Mission', id: 6 },
28 { name: 'Mission', id: 7 }
29 ],
30 list3: [
31 { name: 'Mission', id: 8 },
32 { name: 'Mission', id: 9 },
33 { name: 'Mission', id: 10 }
34 ]
35 }
36 }
37 }
38 </script>
39 <style lang="scss">
40 .board {
41 width: 1000px;
42 margin-left: 20px;
43 display: flex;
44 justify-content: space-around;
45 flex-direction: row;
46 align-items: flex-start;
47 }
48 .kanban {
49 &.todo {
50 .board-column-header {
51 background: #4A9FF9;
52 }
53 }
54 &.working {
55 .board-column-header {
56 background: #f9944a;
57 }
58 }
59 &.done {
60 .board-column-header {
61 background: #2ac06d;
62 }
63 }
64 }
65 </style>
66
67
src/views/components-demo/drag-select.vue
File was created 1 <template>
2 <div class="components-container">
3 <el-drag-select v-model="value" style="width:500px;" multiple placeholder="请选择">
4 <el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
5 </el-drag-select>
6
7 <div style="margin-top:30px;">
8 <el-tag v-for="item of value" :key="item" style="margin-right:15px;">
9 {{ item }}
10 </el-tag>
11 </div>
12 </div>
13 </template>
14
15 <script>
16 import ElDragSelect from '@/components/DragSelect' // base on element-ui
17
18 export default {
19 name: 'DragSelectDemo',
20 components: { ElDragSelect },
21 data() {
22 return {
23 value: ['Apple', 'Banana', 'Orange'],
24 options: [{
25 value: 'Apple',
26 label: 'Apple'
27 }, {
28 value: 'Banana',
29 label: 'Banana'
30 }, {
31 value: 'Orange',
32 label: 'Orange'
33 }, {
34 value: 'Pear',
35 label: 'Pear'
36 }, {
37 value: 'Strawberry',
38 label: 'Strawberry'
39 }]
40 }
41 }
42 }
43 </script>
44
src/views/components-demo/dropzone.vue
File was created 1 <template>
2 <div class="components-container">
3 <aside>
4 Based on <a class="link-type" href="https://github.com/rowanwins/vue-dropzone"> dropzone </a>.
5 {{ $t('components.dropzoneTips') }}
6 </aside>
7 <div class="editor-container">
8 <dropzone id="myVueDropzone" url="https://httpbin.org/post" @dropzone-removedFile="dropzoneR" @dropzone-success="dropzoneS" />
9 </div>
10 </div>
11 </template>
12
13 <script>
14 import Dropzone from '@/components/Dropzone'
15
16 export default {
17 name: 'DropzoneDemo',
18 components: { Dropzone },
19 methods: {
20 dropzoneS(file) {
21 console.log(file)
22 this.$message({ message: 'Upload success', type: 'success' })
23 },
24 dropzoneR(file) {
25 console.log(file)
26 this.$message({ message: 'Delete success', type: 'success' })
27 }
28 }
29 }
30 </script>
31
32
src/views/components-demo/json-editor.vue
File was created 1 <template>
2 <div class="components-container">
3 <aside>Json-Editor is base on <a href="https://github.com/codemirror/CodeMirror" target="_blank">CodeMirrorr</a>. Lint
4 base on <a
5 href="https://github.com/codemirror/CodeMirror/blob/master/addon/lint/json-lint.js"
6 target="_blank"
7 >json-lint</a>.</aside>
8 <div class="editor-container">
9 <json-editor ref="jsonEditor" v-model="value" />
10 </div>
11 </div>
12 </template>
13
14 <script>
15 import JsonEditor from '@/components/JsonEditor'
16
17 const jsonData = '[{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"CORN"}],"name":""},{"items":[{"market_type":"forexdata","symbol":"XAUUSD"},{"market_type":"forexdata","symbol":"XAGUSD"},{"market_type":"forexdata","symbol":"AUTD"},{"market_type":"forexdata","symbol":"AGTD"}],"name":"贵金属"},{"items":[{"market_type":"forexdata","symbol":"CORN"},{"market_type":"forexdata","symbol":"WHEAT"},{"market_type":"forexdata","symbol":"SOYBEAN"},{"market_type":"forexdata","symbol":"SUGAR"}],"name":"农产品"},{"items":[{"market_type":"forexdata","symbol":"UKOIL"},{"market_type":"forexdata","symbol":"USOIL"},{"market_type":"forexdata","symbol":"NGAS"}],"name":"能源化工"}]'
18
19 export default {
20 name: 'JsonEditorDemo',
21 components: { JsonEditor },
22 data() {
23 return {
24 value: JSON.parse(jsonData)
25 }
26 }
27 }
28 </script>
29
30 <style scoped>
31 .editor-container{
32 position: relative;
33 height: 100%;
34 }
35 </style>
36
37
src/views/components-demo/markdown.vue
File was created 1 <template>
2 <div class="components-container">
3 <aside>Markdown is based on
4 <a href="https://github.com/nhnent/tui.editor" target="_blank">tui.editor</a> ,simply wrapped with Vue.
5 <a
6 target="_blank"
7 href="https://panjiachen.github.io/vue-element-admin-site/feature/component/markdown-editor.html"
8 >
9 Documentation </a>
10 </aside>
11
12 <div class="editor-container">
13 <el-tag class="tag-title">
14 Basic:
15 </el-tag>
16 <markdown-editor v-model="content1" height="300px" />
17 </div>
18
19 <div class="editor-container">
20 <el-tag class="tag-title">
21 Markdown Mode:
22 </el-tag>
23 <markdown-editor ref="markdownEditor" v-model="content2" :options="{hideModeSwitch:true,previewStyle:'tab'}" height="200px" />
24 </div>
25
26 <div class="editor-container">
27 <el-tag class="tag-title">
28 Customize Toolbar:
29 </el-tag>
30 <markdown-editor v-model="content3" :options="{ toolbarItems: ['heading','bold','italic']}" />
31 </div>
32
33 <div class="editor-container">
34 <el-tag class="tag-title">
35 I18n:
36 </el-tag>
37 <el-alert
38 :closable="false"
39 title="You can change the language of the admin system to see the effect"
40 type="success"
41 />
42 <markdown-editor ref="markdownEditor" v-model="content4" :language="language" height="300px" />
43 </div>
44
45 <el-button style="margin-top:80px;" type="primary" icon="el-icon-document" @click="getHtml">
46 Get HTML
47 </el-button>
48 <div v-html="html" />
49 </div>
50 </template>
51
52 <script>
53 import MarkdownEditor from '@/components/MarkdownEditor'
54
55 const content = `
56 **This is test**
57
58 * vue
59 * element
60 * webpack
61
62 `
63 export default {
64 name: 'MarkdownDemo',
65 components: { MarkdownEditor },
66 data() {
67 return {
68 content1: content,
69 content2: content,
70 content3: content,
71 content4: content,
72 html: '',
73 languageTypeList: {
74 'en': 'en_US',
75 'zh': 'zh_CN',
76 'es': 'es_ES'
77 }
78 }
79 },
80 computed: {
81 language() {
82 return this.languageTypeList[this.$store.getters.language]
83 }
84 },
85 methods: {
86 getHtml() {
87 this.html = this.$refs.markdownEditor.getHtml()
88 console.log(this.html)
89 }
90 }
91 }
92 </script>
93
94 <style scoped>
95 .editor-container{
96 margin-bottom: 30px;
97 }
98 .tag-title{
99 margin-bottom: 5px;
100 }
101 </style>
102
src/views/components-demo/mixin.vue
File was created 1 <template>
2 <div class="mixin-components-container">
3 <el-row>
4 <el-card class="box-card">
5 <div slot="header" class="clearfix">
6 <span>Buttons</span>
7 </div>
8 <div style="margin-bottom:50px;">
9 <el-col :span="4" class="text-center">
10 <router-link class="pan-btn blue-btn" to="/documentation/index">
11 Documentation
12 </router-link>
13 </el-col>
14 <el-col :span="4" class="text-center">
15 <router-link class="pan-btn light-blue-btn" to="/icon/index">
16 Icons
17 </router-link>
18 </el-col>
19 <el-col :span="4" class="text-center">
20 <router-link class="pan-btn pink-btn" to="/excel/export-excel">
21 Excel
22 </router-link>
23 </el-col>
24 <el-col :span="4" class="text-center">
25 <router-link class="pan-btn green-btn" to="/table/complex-table">
26 Table
27 </router-link>
28 </el-col>
29 <el-col :span="4" class="text-center">
30 <router-link class="pan-btn tiffany-btn" to="/example/create">
31 Form
32 </router-link>
33 </el-col>
34 <el-col :span="4" class="text-center">
35 <router-link class="pan-btn yellow-btn" to="/theme/index">
36 Theme
37 </router-link>
38 </el-col>
39 </div>
40 </el-card>
41 </el-row>
42
43 <el-row :gutter="20" style="margin-top:50px;">
44 <el-col :span="6">
45 <el-card class="box-card">
46 <div slot="header" class="clearfix">
47 <span>Material Design 的input</span>
48 </div>
49 <div style="height:100px;">
50 <el-form :model="demo" :rules="demoRules">
51 <el-form-item prop="title">
52 <md-input v-model="demo.title" icon="el-icon-search" name="title" placeholder="输入标题">
53 标题
54 </md-input>
55 </el-form-item>
56 </el-form>
57 </div>
58 </el-card>
59 </el-col>
60
61 <el-col :span="6">
62 <el-card class="box-card">
63 <div slot="header" class="clearfix">
64 <span>图片hover效果</span>
65 </div>
66 <div class="component-item">
67 <pan-thumb width="100px" height="100px" image="https://wpimg.wallstcn.com/577965b9-bb9e-4e02-9f0c-095b41417191">
68 vue-element-admin
69 </pan-thumb>
70 </div>
71 </el-card>
72 </el-col>
73
74 <el-col :span="6">
75 <el-card class="box-card">
76 <div slot="header" class="clearfix">
77 <span>水波纹 waves v-directive</span>
78 </div>
79 <div class="component-item">
80 <el-button v-waves type="primary">
81 水波纹效果
82 </el-button>
83 </div>
84 </el-card>
85 </el-col>
86
87 <el-col :span="6">
88 <el-card class="box-card">
89 <div slot="header" class="clearfix">
90 <span>hover text</span>
91 </div>
92 <div class="component-item">
93 <mallki class-name="mallki-text" text="vue-element-admin" />
94 </div>
95 </el-card>
96 </el-col>
97 </el-row>
98
99 <el-row :gutter="20" style="margin-top:50px;">
100 <el-col :span="8">
101 <el-card class="box-card">
102 <div slot="header" class="clearfix">
103 <span>Share</span>
104 </div>
105 <div class="component-item" style="height:420px;">
106 <dropdown-menu :items="articleList" style="margin:0 auto;" title="系列文章" />
107 </div>
108 </el-card>
109 </el-col>
110 </el-row>
111 </div>
112 </template>
113
114 <script>
115 import PanThumb from '@/components/PanThumb'
116 import MdInput from '@/components/MDinput'
117 import Mallki from '@/components/TextHoverEffect/Mallki'
118 import DropdownMenu from '@/components/Share/DropdownMenu'
119 import waves from '@/directive/waves/index.js' // 水波纹指令
120
121 export default {
122 name: 'ComponentMixinDemo',
123 components: {
124 PanThumb,
125 MdInput,
126 Mallki,
127 DropdownMenu
128 },
129 directives: {
130 waves
131 },
132 data() {
133 const validate = (rule, value, callback) => {
134 if (value.length !== 6) {
135 callback(new Error('请输入六个字符'))
136 } else {
137 callback()
138 }
139 }
140 return {
141 demo: {
142 title: ''
143 },
144 demoRules: {
145 title: [{ required: true, trigger: 'change', validator: validate }]
146 },
147 articleList: [
148 { title: '基础篇', href: 'https://juejin.im/post/59097cd7a22b9d0065fb61d2' },
149 { title: '登录权限篇', href: 'https://juejin.im/post/591aa14f570c35006961acac' },
150 { title: '实战篇', href: 'https://juejin.im/post/593121aa0ce4630057f70d35' },
151 { title: 'vue-admin-template 篇', href: 'https://juejin.im/post/595b4d776fb9a06bbe7dba56' },
152 { title: 'v4.0 篇', href: 'https://juejin.im/post/5c92ff94f265da6128275a85' },
153 { title: '优雅的使用 icon', href: 'https://juejin.im/post/59bb864b5188257e7a427c09' }
154 ]
155 }
156 }
157 }
158 </script>
159
160 <style scoped>
161 .mixin-components-container {
162 background-color: #f0f2f5;
163 padding: 30px;
164 min-height: calc(100vh - 84px);
165 }
166 .component-item{
167 min-height: 100px;
168 }
169 </style>
170
src/views/components-demo/split-pane.vue
File was created 1 <template>
2 <div class="components-container">
3 <aside><strong>SplitPane</strong> If you've used
4 <a href="https://codepen.io/" target="_blank"> codepen</a>,
5 <a href="https://jsfiddle.net/" target="_blank"> jsfiddle </a>will not be unfamiliar.
6 <a href="https://github.com/PanJiaChen/vue-split-pane" target="_blank"> Github repository</a>
7 </aside>
8 <split-pane split="vertical" @resize="resize">
9 <template slot="paneL">
10 <div class="left-container" />
11 </template>
12 <template slot="paneR">
13 <split-pane split="horizontal">
14 <template slot="paneL">
15 <div class="top-container" />
16 </template>
17 <template slot="paneR">
18 <div class="bottom-container" />
19 </template>
20 </split-pane>
21 </template>
22 </split-pane>
23 </div>
24 </template>
25
26 <script>
27 import splitPane from 'vue-splitpane'
28
29 export default {
30 name: 'SplitpaneDemo',
31 components: { splitPane },
32 methods: {
33 resize() {
34 console.log('resize')
35 }
36 }
37 }
38 </script>
39
40 <style scoped>
41 .components-container {
42 position: relative;
43 height: 100vh;
44 }
45
46 .left-container {
47 background-color: #F38181;
48 height: 100%;
49 }
50
51 .right-container {
52 background-color: #FCE38A;
53 height: 200px;
54 }
55
56 .top-container {
57 background-color: #FCE38A;
58 width: 100%;
59 height: 100%;
60 }
61
62 .bottom-container {
63 width: 100%;
64 background-color: #95E1D3;
65 height: 100%;
66 }
67 </style>
68
src/views/components-demo/sticky.vue
File was created 1 <template>
2 <div>
3 <sticky :z-index="10" class-name="sub-navbar">
4 <el-dropdown trigger="click">
5 <el-button plain>
6 Platform<i class="el-icon-caret-bottom el-icon--right" />
7 </el-button>
8 <el-dropdown-menu slot="dropdown" class="no-border">
9 <el-checkbox-group v-model="platforms" style="padding: 5px 15px;">
10 <el-checkbox v-for="item in platformsOptions" :key="item.key" :label="item.key">
11 {{ item.name }}
12 </el-checkbox>
13 </el-checkbox-group>
14 </el-dropdown-menu>
15 </el-dropdown>
16
17 <el-dropdown trigger="click">
18 <el-button plain>
19 Link<i class="el-icon-caret-bottom el-icon--right" />
20 </el-button>
21 <el-dropdown-menu slot="dropdown" class="no-padding no-border" style="width:300px">
22 <el-input v-model="url" placeholder="Please enter the content">
23 <template slot="prepend">
24 Url
25 </template>
26 </el-input>
27 </el-dropdown-menu>
28 </el-dropdown>
29
30 <div class="time-container">
31 <el-date-picker v-model="time" type="datetime" format="yyyy-MM-dd HH:mm:ss" placeholder="Release time" />
32 </div>
33
34 <el-button style="margin-left: 10px;" type="success">
35 publish
36 </el-button>
37 </sticky>
38
39 <div class="components-container">
40 <aside>Sticky header, {{ $t('components.stickyTips') }}</aside>
41 <div>placeholder</div>
42 <div>placeholder</div>
43 <div>placeholder</div>
44 <div>placeholder</div>
45 <div>placeholder</div>
46 <div>placeholder</div>
47 <div>placeholder</div>
48 <div>placeholder</div>
49 <div>placeholder</div>
50 <div>placeholder</div>
51 <div>placeholder</div>
52 <div>placeholder</div>
53 <div>placeholder</div>
54 <sticky :sticky-top="200">
55 <el-button type="primary"> placeholder</el-button>
56 </sticky>
57 <div>placeholder</div>
58 <div>placeholder</div>
59 <div>placeholder</div>
60 <div>placeholder</div>
61 <div>placeholder</div>
62 <div>placeholder</div>
63 <div>placeholder</div>
64 <div>placeholder</div>
65 <div>placeholder</div>
66 <div>placeholder</div>
67 <div>placeholder</div>
68 <div>placeholder</div>
69 <div>placeholder</div>
70 <div>placeholder</div>
71 <div>placeholder</div>
72 <div>placeholder</div>
73 <div>placeholder</div>
74 <div>placeholder</div>
75 <div>placeholder</div>
76 <div>placeholder</div>
77 <div>placeholder</div>
78 <div>placeholder</div>
79 <div>placeholder</div>
80 <div>placeholder</div>
81 <div>placeholder</div>
82 <div>placeholder</div>
83 <div>placeholder</div>
84 <div>placeholder</div>
85 <div>placeholder</div>
86 <div>placeholder</div>
87 <div>placeholder</div>
88 <div>placeholder</div>
89 <div>placeholder</div>
90 <div>placeholder</div>
91 <div>placeholder</div>
92 <div>placeholder</div>
93 <div>placeholder</div>
94 <div>placeholder</div>
95 </div>
96 </div>
97 </template>
98
99 <script>
100 import Sticky from '@/components/Sticky'
101
102 export default {
103 name: 'StickyDemo',
104 components: { Sticky },
105 data() {
106 return {
107 time: '',
108 url: '',
109 platforms: ['a-platform'],
110 platformsOptions: [
111 { key: 'a-platform', name: 'platformA' },
112 { key: 'b-platform', name: 'platformB' },
113 { key: 'c-platform', name: 'platformC' }
114 ],
115 pickerOptions: {
116 disabledDate(time) {
117 return time.getTime() > Date.now()
118 }
119 }
120 }
121 }
122 }
123 </script>
124
125 <style scoped>
126 .components-container div {
127 margin: 10px;
128 }
129
130 .time-container {
131 display: inline-block;
132 }
133 </style>
134
src/views/components-demo/tinymce.vue
File was created 1 <template>
2 <div class="components-container">
3 <aside>
4 {{ $t('components.tinymceTips') }}
5 <a target="_blank" class="link-type" href="https://panjiachen.github.io/vue-element-admin-site/component/rich-editor.html"> {{ $t('components.documentation') }}</a>
6 </aside>
7 <div>
8 <tinymce v-model="content" :height="300" />
9 </div>
10 <div class="editor-content" v-html="content" />
11 </div>
12 </template>
13
14 <script>
15 import Tinymce from '@/components/Tinymce'
16
17 export default {
18 name: 'TinymceDemo',
19 components: { Tinymce },
20 data() {
21 return {
22 content:
23 `<h1 style="text-align: center;">Welcome to the TinyMCE demo!</h1><p style="text-align: center; font-size: 15px;"><img title="TinyMCE Logo" src="//www.tinymce.com/images/glyph-tinymce@2x.png" alt="TinyMCE Logo" width="110" height="97" /><ul>
24 <li>Our <a href="//www.tinymce.com/docs/">documentation</a> is a great resource for learning how to configure TinyMCE.</li><li>Have a specific question? Visit the <a href="https://community.tinymce.com/forum/">Community Forum</a>.</li><li>We also offer enterprise grade support as part of <a href="https://tinymce.com/pricing">TinyMCE premium subscriptions</a>.</li>
25 </ul>`
26 }
27 }
28 }
29 </script>
30
31 <style scoped>
32 .editor-content{
33 margin-top: 20px;
34 }
35 </style>
36
37
src/views/dashboard/admin/components/BarChart.vue
File was created 1 <template>
2 <div :class="className" :style="{height:height,width:width}" />
3 </template>
4
5 <script>
6 import echarts from 'echarts'
7 require('echarts/theme/macarons') // echarts theme
8 import resize from './mixins/resize'
9
10 const animationDuration = 6000
11
12 export default {
13 mixins: [resize],
14 props: {
15 className: {
16 type: String,
17 default: 'chart'
18 },
19 width: {
20 type: String,
21 default: '100%'
22 },
23 height: {
24 type: String,
25 default: '300px'
26 }
27 },
28 data() {
29 return {
30 chart: null
31 }
32 },
33 mounted() {
34 this.$nextTick(() => {
35 this.initChart()
36 })
37 },
38 beforeDestroy() {
39 if (!this.chart) {
40 return
41 }
42 this.chart.dispose()
43 this.chart = null
44 },
45 methods: {
46 initChart() {
47 this.chart = echarts.init(this.$el, 'macarons')
48
49 this.chart.setOption({
50 tooltip: {
51 trigger: 'axis',
52 axisPointer: { // 坐标轴指示器,坐标轴触发有效
53 type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
54 }
55 },
56 grid: {
57 top: 10,
58 left: '2%',
59 right: '2%',
60 bottom: '3%',
61 containLabel: true
62 },
63 xAxis: [{
64 type: 'category',
65 data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
66 axisTick: {
67 alignWithLabel: true
68 }
69 }],
70 yAxis: [{
71 type: 'value',
72 axisTick: {
73 show: false
74 }
75 }],
76 series: [{
77 name: 'pageA',
78 type: 'bar',
79 stack: 'vistors',
80 barWidth: '60%',
81 data: [79, 52, 200, 334, 390, 330, 220],
82 animationDuration
83 }, {
84 name: 'pageB',
85 type: 'bar',
86 stack: 'vistors',
87 barWidth: '60%',
88 data: [80, 52, 200, 334, 390, 330, 220],
89 animationDuration
90 }, {
91 name: 'pageC',
92 type: 'bar',
93 stack: 'vistors',
94 barWidth: '60%',
95 data: [30, 52, 200, 334, 390, 330, 220],
96 animationDuration
97 }]
98 })
99 }
100 }
101 }
102 </script>
103
src/views/dashboard/admin/components/BoxCard.vue
File was created 1 <template>
2 <el-card class="box-card-component" style="margin-left:8px;">
3 <div slot="header" class="box-card-header">
4 <img src="https://wpimg.wallstcn.com/e7d23d71-cf19-4b90-a1cc-f56af8c0903d.png">
5 </div>
6 <div style="position:relative;">
7 <pan-thumb :image="avatar" class="panThumb" />
8 <mallki class-name="mallki-text" text="vue-element-admin" />
9 <div style="padding-top:35px;" class="progress-item">
10 <span>Vue</span>
11 <el-progress :percentage="70" />
12 </div>
13 <div class="progress-item">
14 <span>JavaScript</span>
15 <el-progress :percentage="18" />
16 </div>
17 <div class="progress-item">
18 <span>Css</span>
19 <el-progress :percentage="12" />
20 </div>
21 <div class="progress-item">
22 <span>ESLint</span>
23 <el-progress :percentage="100" status="success" />
24 </div>
25 </div>
26 </el-card>
27 </template>
28
29 <script>
30 import { mapGetters } from 'vuex'
31 import PanThumb from '@/components/PanThumb'
32 import Mallki from '@/components/TextHoverEffect/Mallki'
33
34 export default {
35 components: { PanThumb, Mallki },
36
37 filters: {
38 statusFilter(status) {
39 const statusMap = {
40 success: 'success',
41 pending: 'danger'
42 }
43 return statusMap[status]
44 }
45 },
46 data() {
47 return {
48 statisticsData: {
49 article_count: 1024,
50 pageviews_count: 1024
51 }
52 }
53 },
54 computed: {
55 ...mapGetters([
56 'name',
57 'avatar',
58 'roles'
59 ])
60 }
61 }
62 </script>
63
64 <style lang="scss" >
65 .box-card-component{
66 .el-card__header {
67 padding: 0px!important;
68 }
69 }
70 </style>
71 <style lang="scss" scoped>
72 .box-card-component {
73 .box-card-header {
74 position: relative;
75 height: 220px;
76 img {
77 width: 100%;
78 height: 100%;
79 transition: all 0.2s linear;
80 &:hover {
81 transform: scale(1.1, 1.1);
82 filter: contrast(130%);
83 }
84 }
85 }
86 .mallki-text {
87 position: absolute;
88 top: 0px;
89 right: 0px;
90 font-size: 20px;
91 font-weight: bold;
92 }
93 .panThumb {
94 z-index: 100;
95 height: 70px!important;
96 width: 70px!important;
97 position: absolute!important;
98 top: -45px;
99 left: 0px;
100 border: 5px solid #ffffff;
101 background-color: #fff;
102 margin: auto;
103 box-shadow: none!important;
104 /deep/ .pan-info {
105 box-shadow: none!important;
106 }
107 }
108 .progress-item {
109 margin-bottom: 10px;
110 font-size: 14px;
111 }
112 @media only screen and (max-width: 1510px){
113 .mallki-text{
114 display: none;
115 }
116 }
117 }
118 </style>
119
src/views/dashboard/admin/components/LineChart.vue
File was created 1 <template>
2 <div :class="className" :style="{height:height,width:width}" />
3 </template>
4
5 <script>
6 import echarts from 'echarts'
7 require('echarts/theme/macarons') // echarts theme
8 import resize from './mixins/resize'
9
10 export default {
11 mixins: [resize],
12 props: {
13 className: {
14 type: String,
15 default: 'chart'
16 },
17 width: {
18 type: String,
19 default: '100%'
20 },
21 height: {
22 type: String,
23 default: '350px'
24 },
25 autoResize: {
26 type: Boolean,
27 default: true
28 },
29 chartData: {
30 type: Object,
31 required: true
32 }
33 },
34 data() {
35 return {
36 chart: null
37 }
38 },
39 watch: {
40 chartData: {
41 deep: true,
42 handler(val) {
43 this.setOptions(val)
44 }
45 }
46 },
47 mounted() {
48 this.$nextTick(() => {
49 this.initChart()
50 })
51 },
52 beforeDestroy() {
53 if (!this.chart) {
54 return
55 }
56 this.chart.dispose()
57 this.chart = null
58 },
59 methods: {
60 initChart() {
61 this.chart = echarts.init(this.$el, 'macarons')
62 this.setOptions(this.chartData)
63 },
64 setOptions({ expectedData, actualData } = {}) {
65 this.chart.setOption({
66 xAxis: {
67 data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
68 boundaryGap: false,
69 axisTick: {
70 show: false
71 }
72 },
73 grid: {
74 left: 10,
75 right: 10,
76 bottom: 20,
77 top: 30,
78 containLabel: true
79 },
80 tooltip: {
81 trigger: 'axis',
82 axisPointer: {
83 type: 'cross'
84 },
85 padding: [5, 10]
86 },
87 yAxis: {
88 axisTick: {
89 show: false
90 }
91 },
92 legend: {
93 data: ['expected', 'actual']
94 },
95 series: [{
96 name: 'expected', itemStyle: {
97 normal: {
98 color: '#FF005A',
99 lineStyle: {
100 color: '#FF005A',
101 width: 2
102 }
103 }
104 },
105 smooth: true,
106 type: 'line',
107 data: expectedData,
108 animationDuration: 2800,
109 animationEasing: 'cubicInOut'
110 },
111 {
112 name: 'actual',
113 smooth: true,
114 type: 'line',
115 itemStyle: {
116 normal: {
117 color: '#3888fa',
118 lineStyle: {
119 color: '#3888fa',
120 width: 2
121 },
122 areaStyle: {
123 color: '#f3f8ff'
124 }
125 }
126 },
127 data: actualData,
128 animationDuration: 2800,
129 animationEasing: 'quadraticOut'
130 }]
131 })
132 }
133 }
134 }
135 </script>
136
src/views/dashboard/admin/components/PanelGroup.vue
File was created 1 <template>
2 <el-row :gutter="40" class="panel-group">
3 <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
4 <div class="card-panel" @click="handleSetLineChartData('newVisitis')">
5 <div class="card-panel-icon-wrapper icon-people">
6 <svg-icon icon-class="peoples" class-name="card-panel-icon" />
7 </div>
8 <div class="card-panel-description">
9 <div class="card-panel-text">
10 New Visits
11 </div>
12 <count-to :start-val="0" :end-val="102400" :duration="2600" class="card-panel-num" />
13 </div>
14 </div>
15 </el-col>
16 <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
17 <div class="card-panel" @click="handleSetLineChartData('messages')">
18 <div class="card-panel-icon-wrapper icon-message">
19 <svg-icon icon-class="message" class-name="card-panel-icon" />
20 </div>
21 <div class="card-panel-description">
22 <div class="card-panel-text">
23 Messages
24 </div>
25 <count-to :start-val="0" :end-val="81212" :duration="3000" class="card-panel-num" />
26 </div>
27 </div>
28 </el-col>
29 <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
30 <div class="card-panel" @click="handleSetLineChartData('purchases')">
31 <div class="card-panel-icon-wrapper icon-money">
32 <svg-icon icon-class="money" class-name="card-panel-icon" />
33 </div>
34 <div class="card-panel-description">
35 <div class="card-panel-text">
36 Purchases
37 </div>
38 <count-to :start-val="0" :end-val="9280" :duration="3200" class="card-panel-num" />
39 </div>
40 </div>
41 </el-col>
42 <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
43 <div class="card-panel" @click="handleSetLineChartData('shoppings')">
44 <div class="card-panel-icon-wrapper icon-shopping">
45 <svg-icon icon-class="shopping" class-name="card-panel-icon" />
46 </div>
47 <div class="card-panel-description">
48 <div class="card-panel-text">
49 Shoppings
50 </div>
51 <count-to :start-val="0" :end-val="13600" :duration="3600" class="card-panel-num" />
52 </div>
53 </div>
54 </el-col>
55 </el-row>
56 </template>
57
58 <script>
59 import CountTo from 'vue-count-to'
60
61 export default {
62 components: {
63 CountTo
64 },
65 methods: {
66 handleSetLineChartData(type) {
67 this.$emit('handleSetLineChartData', type)
68 }
69 }
70 }
71 </script>
72
73 <style lang="scss" scoped>
74 .panel-group {
75 margin-top: 18px;
76
77 .card-panel-col {
78 margin-bottom: 32px;
79 }
80
81 .card-panel {
82 height: 108px;
83 cursor: pointer;
84 font-size: 12px;
85 position: relative;
86 overflow: hidden;
87 color: #666;
88 background: #fff;
89 box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
90 border-color: rgba(0, 0, 0, .05);
91
92 &:hover {
93 .card-panel-icon-wrapper {
94 color: #fff;
95 }
96
97 .icon-people {
98 background: #40c9c6;
99 }
100
101 .icon-message {
102 background: #36a3f7;
103 }
104
105 .icon-money {
106 background: #f4516c;
107 }
108
109 .icon-shopping {
110 background: #34bfa3
111 }
112 }
113
114 .icon-people {
115 color: #40c9c6;
116 }
117
118 .icon-message {
119 color: #36a3f7;
120 }
121
122 .icon-money {
123 color: #f4516c;
124 }
125
126 .icon-shopping {
127 color: #34bfa3
128 }
129
130 .card-panel-icon-wrapper {
131 float: left;
132 margin: 14px 0 0 14px;
133 padding: 16px;
134 transition: all 0.38s ease-out;
135 border-radius: 6px;
136 }
137
138 .card-panel-icon {
139 float: left;
140 font-size: 48px;
141 }
142
143 .card-panel-description {
144 float: right;
145 font-weight: bold;
146 margin: 26px;
147 margin-left: 0px;
148
149 .card-panel-text {
150 line-height: 18px;
151 color: rgba(0, 0, 0, 0.45);
152 font-size: 16px;
153 margin-bottom: 12px;
154 }
155
156 .card-panel-num {
157 font-size: 20px;
158 }
159 }
160 }
161 }
162
163 @media (max-width:550px) {
164 .card-panel-description {
165 display: none;
166 }
167
168 .card-panel-icon-wrapper {
169 float: none !important;
170 width: 100%;
171 height: 100%;
172 margin: 0 !important;
173
174 .svg-icon {
175 display: block;
176 margin: 14px auto !important;
177 float: none !important;
178 }
179 }
180 }
181 </style>
182
src/views/dashboard/admin/components/PieChart.vue
File was created 1 <template>
2 <div :class="className" :style="{height:height,width:width}" />
3 </template>
4
5 <script>
6 import echarts from 'echarts'
7 require('echarts/theme/macarons') // echarts theme
8 import resize from './mixins/resize'
9
10 export default {
11 mixins: [resize],
12 props: {
13 className: {
14 type: String,
15 default: 'chart'
16 },
17 width: {
18 type: String,
19 default: '100%'
20 },
21 height: {
22 type: String,
23 default: '300px'
24 }
25 },
26 data() {
27 return {
28 chart: null
29 }
30 },
31 mounted() {
32 this.$nextTick(() => {
33 this.initChart()
34 })
35 },
36 beforeDestroy() {
37 if (!this.chart) {
38 return
39 }
40 this.chart.dispose()
41 this.chart = null
42 },
43 methods: {
44 initChart() {
45 this.chart = echarts.init(this.$el, 'macarons')
46
47 this.chart.setOption({
48 tooltip: {
49 trigger: 'item',
50 formatter: '{a} <br/>{b} : {c} ({d}%)'
51 },
52 legend: {
53 left: 'center',
54 bottom: '10',
55 data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts']
56 },
57 series: [
58 {
59 name: 'WEEKLY WRITE ARTICLES',
60 type: 'pie',
61 roseType: 'radius',
62 radius: [15, 95],
63 center: ['50%', '38%'],
64 data: [
65 { value: 320, name: 'Industries' },
66 { value: 240, name: 'Technology' },
67 { value: 149, name: 'Forex' },
68 { value: 100, name: 'Gold' },
69 { value: 59, name: 'Forecasts' }
70 ],
71 animationEasing: 'cubicInOut',
72 animationDuration: 2600
73 }
74 ]
75 })
76 }
77 }
78 }
79 </script>
80
src/views/dashboard/admin/components/RaddarChart.vue
File was created 1 <template>
2 <div :class="className" :style="{height:height,width:width}" />
3 </template>
4
5 <script>
6 import echarts from 'echarts'
7 require('echarts/theme/macarons') // echarts theme
8 import resize from './mixins/resize'
9
10 const animationDuration = 3000
11
12 export default {
13 mixins: [resize],
14 props: {
15 className: {
16 type: String,
17 default: 'chart'
18 },
19 width: {
20 type: String,
21 default: '100%'
22 },
23 height: {
24 type: String,
25 default: '300px'
26 }
27 },
28 data() {
29 return {
30 chart: null
31 }
32 },
33 mounted() {
34 this.$nextTick(() => {
35 this.initChart()
36 })
37 },
38 beforeDestroy() {
39 if (!this.chart) {
40 return
41 }
42 this.chart.dispose()
43 this.chart = null
44 },
45 methods: {
46 initChart() {
47 this.chart = echarts.init(this.$el, 'macarons')
48
49 this.chart.setOption({
50 tooltip: {
51 trigger: 'axis',
52 axisPointer: { // 坐标轴指示器,坐标轴触发有效
53 type: 'shadow' // 默认为直线,可选为:'line' | 'shadow'
54 }
55 },
56 radar: {
57 radius: '66%',
58 center: ['50%', '42%'],
59 splitNumber: 8,
60 splitArea: {
61 areaStyle: {
62 color: 'rgba(127,95,132,.3)',
63 opacity: 1,
64 shadowBlur: 45,
65 shadowColor: 'rgba(0,0,0,.5)',
66 shadowOffsetX: 0,
67 shadowOffsetY: 15
68 }
69 },
70 indicator: [
71 { name: 'Sales', max: 10000 },
72 { name: 'Administration', max: 20000 },
73 { name: 'Information Techology', max: 20000 },
74 { name: 'Customer Support', max: 20000 },
75 { name: 'Development', max: 20000 },
76 { name: 'Marketing', max: 20000 }
77 ]
78 },
79 legend: {
80 left: 'center',
81 bottom: '10',
82 data: ['Allocated Budget', 'Expected Spending', 'Actual Spending']
83 },
84 series: [{
85 type: 'radar',
86 symbolSize: 0,
87 areaStyle: {
88 normal: {
89 shadowBlur: 13,
90 shadowColor: 'rgba(0,0,0,.2)',
91 shadowOffsetX: 0,
92 shadowOffsetY: 10,
93 opacity: 1
94 }
95 },
96 data: [
97 {
98 value: [5000, 7000, 12000, 11000, 15000, 14000],
99 name: 'Allocated Budget'
100 },
101 {
102 value: [4000, 9000, 15000, 15000, 13000, 11000],
103 name: 'Expected Spending'
104 },
105 {
106 value: [5500, 11000, 12000, 15000, 12000, 12000],
107 name: 'Actual Spending'
108 }
109 ],
110 animationDuration: animationDuration
111 }]
112 })
113 }
114 }
115 }
116 </script>
117
src/views/dashboard/admin/components/TodoList/Todo.vue
File was created 1 <template>
2 <li :class="{ completed: todo.done, editing: editing }" class="todo">
3 <div class="view">
4 <input
5 :checked="todo.done"
6 class="toggle"
7 type="checkbox"
8 @change="toggleTodo( todo)"
9 >
10 <label @dblclick="editing = true" v-text="todo.text" />
11 <button class="destroy" @click="deleteTodo( todo )" />
12 </div>
13 <input
14 v-show="editing"
15 v-focus="editing"
16 :value="todo.text"
17 class="edit"
18 @keyup.enter="doneEdit"
19 @keyup.esc="cancelEdit"
20 @blur="doneEdit"
21 >
22 </li>
23 </template>
24
25 <script>
26 export default {
27 name: 'Todo',
28 directives: {
29 focus(el, { value }, { context }) {
30 if (value) {
31 context.$nextTick(() => {
32 el.focus()
33 })
34 }
35 }
36 },
37 props: {
38 todo: {
39 type: Object,
40 default: function() {
41 return {}
42 }
43 }
44 },
45 data() {
46 return {
47 editing: false
48 }
49 },
50 methods: {
51 deleteTodo(todo) {
52 this.$emit('deleteTodo', todo)
53 },
54 editTodo({ todo, value }) {
55 this.$emit('editTodo', { todo, value })
56 },
57 toggleTodo(todo) {
58 this.$emit('toggleTodo', todo)
59 },
60 doneEdit(e) {
61 const value = e.target.value.trim()
62 const { todo } = this
63 if (!value) {
64 this.deleteTodo({
65 todo
66 })
67 } else if (this.editing) {
68 this.editTodo({
69 todo,
70 value
71 })
72 this.editing = false
73 }
74 },
75 cancelEdit(e) {
76 e.target.value = this.todo.text
77 this.editing = false
78 }
79 }
80 }
81 </script>
82
src/views/dashboard/admin/components/TodoList/index.scss
File was created 1 .todoapp {
2 font: 14px 'Helvetica Neue', Helvetica, Arial, sans-serif;
3 line-height: 1.4em;
4 color: #4d4d4d;
5 min-width: 230px;
6 max-width: 550px;
7 margin: 0 auto ;
8 -webkit-font-smoothing: antialiased;
9 -moz-osx-font-smoothing: grayscale;
10 font-weight: 300;
11 background: #fff;
12 z-index: 1;
13 position: relative;
14 button {
15 margin: 0;
16 padding: 0;
17 border: 0;
18 background: none;
19 font-size: 100%;
20 vertical-align: baseline;
21 font-family: inherit;
22 font-weight: inherit;
23 color: inherit;
24 -webkit-appearance: none;
25 appearance: none;
26 -webkit-font-smoothing: antialiased;
27 -moz-osx-font-smoothing: grayscale;
28 }
29 :focus {
30 outline: 0;
31 }
32 .hidden {
33 display: none;
34 }
35 .todoapp {
36 background: #fff;
37 margin: 130px 0 40px 0;
38 position: relative;
39 box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1);
40 }
41 .todoapp input::-webkit-input-placeholder {
42 font-style: italic;
43 font-weight: 300;
44 color: #e6e6e6;
45 }
46 .todoapp input::-moz-placeholder {
47 font-style: italic;
48 font-weight: 300;
49 color: #e6e6e6;
50 }
51 .todoapp input::input-placeholder {
52 font-style: italic;
53 font-weight: 300;
54 color: #e6e6e6;
55 }
56 .todoapp h1 {
57 position: absolute;
58 top: -155px;
59 width: 100%;
60 font-size: 100px;
61 font-weight: 100;
62 text-align: center;
63 color: rgba(175, 47, 47, 0.15);
64 -webkit-text-rendering: optimizeLegibility;
65 -moz-text-rendering: optimizeLegibility;
66 text-rendering: optimizeLegibility;
67 }
68 .new-todo,
69 .edit {
70 position: relative;
71 margin: 0;
72 width: 100%;
73 font-size: 18px;
74 font-family: inherit;
75 font-weight: inherit;
76 line-height: 1.4em;
77 border: 0;
78 color: inherit;
79 padding: 6px;
80 border: 1px solid #999;
81 box-shadow: inset 0 -1px 5px 0 rgba(0, 0, 0, 0.2);
82 box-sizing: border-box;
83 -webkit-font-smoothing: antialiased;
84 -moz-osx-font-smoothing: grayscale;
85 }
86 .new-todo {
87 padding: 10px 16px 16px 60px;
88 border: none;
89 background: rgba(0, 0, 0, 0.003);
90 box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
91 }
92 .main {
93 position: relative;
94 z-index: 2;
95 border-top: 1px solid #e6e6e6;
96 }
97 .toggle-all {
98 text-align: center;
99 border: none;
100 /* Mobile Safari */
101 opacity: 0;
102 position: absolute;
103 }
104 .toggle-all+label {
105 width: 60px;
106 height: 34px;
107 font-size: 0;
108 position: absolute;
109 top: -52px;
110 left: -13px;
111 -webkit-transform: rotate(90deg);
112 transform: rotate(90deg);
113 }
114 .toggle-all+label:before {
115 content: '❯';
116 font-size: 22px;
117 color: #e6e6e6;
118 padding: 10px 27px 10px 27px;
119 }
120 .toggle-all:checked+label:before {
121 color: #737373;
122 }
123 .todo-list {
124 margin: 0;
125 padding: 0;
126 list-style: none;
127 }
128 .todo-list li {
129 position: relative;
130 font-size: 24px;
131 border-bottom: 1px solid #ededed;
132 }
133 .todo-list li:last-child {
134 border-bottom: none;
135 }
136 .todo-list li.editing {
137 border-bottom: none;
138 padding: 0;
139 }
140 .todo-list li.editing .edit {
141 display: block;
142 width: 506px;
143 padding: 12px 16px;
144 margin: 0 0 0 43px;
145 }
146 .todo-list li.editing .view {
147 display: none;
148 }
149 .todo-list li .toggle {
150 text-align: center;
151 width: 40px;
152 /* auto, since non-WebKit browsers doesn't support input styling */
153 height: auto;
154 position: absolute;
155 top: 0;
156 bottom: 0;
157 margin: auto 0;
158 border: none;
159 /* Mobile Safari */
160 -webkit-appearance: none;
161 appearance: none;
162 }
163 .todo-list li .toggle {
164 opacity: 0;
165 }
166 .todo-list li .toggle+label {
167 /*
168 Firefox requires `#` to be escaped - https://bugzilla.mozilla.org/show_bug.cgi?id=922433
169 IE and Edge requires *everything* to be escaped to render, so we do that instead of just the `#` - https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/7157459/
170 */
171 background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23ededed%22%20stroke-width%3D%223%22/%3E%3C/svg%3E');
172 background-repeat: no-repeat;
173 background-position: center left;
174 background-size: 36px;
175 }
176 .todo-list li .toggle:checked+label {
177 background-size: 36px;
178 background-image: url('data:image/svg+xml;utf8,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20width%3D%2240%22%20height%3D%2240%22%20viewBox%3D%22-10%20-18%20100%20135%22%3E%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2250%22%20fill%3D%22none%22%20stroke%3D%22%23bddad5%22%20stroke-width%3D%223%22/%3E%3Cpath%20fill%3D%22%235dc2af%22%20d%3D%22M72%2025L42%2071%2027%2056l-4%204%2020%2020%2034-52z%22/%3E%3C/svg%3E');
179 }
180 .todo-list li label {
181 word-break: break-all;
182 padding: 15px 15px 15px 50px;
183 display: block;
184 line-height: 1.0;
185 font-size: 14px;
186 transition: color 0.4s;
187 }
188 .todo-list li.completed label {
189 color: #d9d9d9;
190 text-decoration: line-through;
191 }
192 .todo-list li .destroy {
193 display: none;
194 position: absolute;
195 top: 0;
196 right: 10px;
197 bottom: 0;
198 width: 40px;
199 height: 40px;
200 margin: auto 0;
201 font-size: 30px;
202 color: #cc9a9a;
203 transition: color 0.2s ease-out;
204 cursor: pointer;
205 }
206 .todo-list li .destroy:hover {
207 color: #af5b5e;
208 }
209 .todo-list li .destroy:after {
210 content: '×';
211 }
212 .todo-list li:hover .destroy {
213 display: block;
214 }
215 .todo-list li .edit {
216 display: none;
217 }
218 .todo-list li.editing:last-child {
219 margin-bottom: -1px;
220 }
221 .footer {
222 color: #777;
223 position: relative;
224 padding: 10px 15px;
225 height: 40px;
226 text-align: center;
227 border-top: 1px solid #e6e6e6;
228 }
229 .footer:before {
230 content: '';
231 position: absolute;
232 right: 0;
233 bottom: 0;
234 left: 0;
235 height: 40px;
236 overflow: hidden;
237 box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6, 0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6, 0 17px 2px -6px rgba(0, 0, 0, 0.2);
238 }
239 .todo-count {
240 float: left;
241 text-align: left;
242 }
243 .todo-count strong {
244 font-weight: 300;
245 }
246 .filters {
247 margin: 0;
248 padding: 0;
249 position: relative;
250 z-index: 1;
251 list-style: none;
252 }
253 .filters li {
254 display: inline;
255 }
256 .filters li a {
257 color: inherit;
258 font-size: 12px;
259 padding: 3px 7px;
260 text-decoration: none;
261 border: 1px solid transparent;
262 border-radius: 3px;
263 }
264 .filters li a:hover {
265 border-color: rgba(175, 47, 47, 0.1);
266 }
267 .filters li a.selected {
268 border-color: rgba(175, 47, 47, 0.2);
269 }
270 .clear-completed,
271 html .clear-completed:active {
272 float: right;
273 position: relative;
274 line-height: 20px;
275 text-decoration: none;
276 cursor: pointer;
277 }
278 .clear-completed:hover {
279 text-decoration: underline;
280 }
281 .info {
282 margin: 65px auto 0;
283 color: #bfbfbf;
284 font-size: 10px;
285 text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
286 text-align: center;
287 }
288 .info p {
289 line-height: 1;
290 }
291 .info a {
292 color: inherit;
293 text-decoration: none;
294 font-weight: 400;
295 }
296 .info a:hover {
297 text-decoration: underline;
298 }
299 /*
300 Hack to remove background from Mobile Safari.
301 Can't use it globally since it destroys checkboxes in Firefox
302 */
303 @media screen and (-webkit-min-device-pixel-ratio:0) {
304 .toggle-all,
305 .todo-list li .toggle {
306 background: none;
307 }
308 .todo-list li .toggle {
309 height: 40px;
310 }
311 }
312 @media (max-width: 430px) {
313 .footer {
314 height: 50px;
315 }
316 .filters {
317 bottom: 10px;
318 }
319 }
320 }
321
src/views/dashboard/admin/components/TodoList/index.vue
File was created 1 <template>
2 <section class="todoapp">
3 <!-- header -->
4 <header class="header">
5 <input class="new-todo" autocomplete="off" placeholder="Todo List" @keyup.enter="addTodo">
6 </header>
7 <!-- main section -->
8 <section v-show="todos.length" class="main">
9 <input id="toggle-all" :checked="allChecked" class="toggle-all" type="checkbox" @change="toggleAll({ done: !allChecked })">
10 <label for="toggle-all" />
11 <ul class="todo-list">
12 <todo
13 v-for="(todo, index) in filteredTodos"
14 :key="index"
15 :todo="todo"
16 @toggleTodo="toggleTodo"
17 @editTodo="editTodo"
18 @deleteTodo="deleteTodo"
19 />
20 </ul>
21 </section>
22 <!-- footer -->
23 <footer v-show="todos.length" class="footer">
24 <span class="todo-count">
25 <strong>{{ remaining }}</strong>
26 {{ remaining | pluralize('item') }} left
27 </span>
28 <ul class="filters">
29 <li v-for="(val, key) in filters" :key="key">
30 <a :class="{ selected: visibility === key }" @click.prevent="visibility = key">{{ key | capitalize }}</a>
31 </li>
32 </ul>
33 <!-- <button class="clear-completed" v-show="todos.length > remaining" @click="clearCompleted">
34 Clear completed
35 </button> -->
36 </footer>
37 </section>
38 </template>
39
40 <script>
41 import Todo from './Todo.vue'
42
43 const STORAGE_KEY = 'todos'
44 const filters = {
45 all: todos => todos,
46 active: todos => todos.filter(todo => !todo.done),
47 completed: todos => todos.filter(todo => todo.done)
48 }
49 const defalutList = [
50 { text: 'star this repository', done: false },
51 { text: 'fork this repository', done: false },
52 { text: 'follow author', done: false },
53 { text: 'vue-element-admin', done: true },
54 { text: 'vue', done: true },
55 { text: 'element-ui', done: true },
56 { text: 'axios', done: true },
57 { text: 'webpack', done: true }
58 ]
59 export default {
60 components: { Todo },
61 filters: {
62 pluralize: (n, w) => n === 1 ? w : w + 's',
63 capitalize: s => s.charAt(0).toUpperCase() + s.slice(1)
64 },
65 data() {
66 return {
67 visibility: 'all',
68 filters,
69 // todos: JSON.parse(window.localStorage.getItem(STORAGE_KEY)) || defalutList
70 todos: defalutList
71 }
72 },
73 computed: {
74 allChecked() {
75 return this.todos.every(todo => todo.done)
76 },
77 filteredTodos() {
78 return filters[this.visibility](this.todos)
79 },
80 remaining() {
81 return this.todos.filter(todo => !todo.done).length
82 }
83 },
84 methods: {
85 setLocalStorage() {
86 window.localStorage.setItem(STORAGE_KEY, JSON.stringify(this.todos))
87 },
88 addTodo(e) {
89 const text = e.target.value
90 if (text.trim()) {
91 this.todos.push({
92 text,
93 done: false
94 })
95 this.setLocalStorage()
96 }
97 e.target.value = ''
98 },
99 toggleTodo(val) {
100 val.done = !val.done
101 this.setLocalStorage()
102 },
103 deleteTodo(todo) {
104 this.todos.splice(this.todos.indexOf(todo), 1)
105 this.setLocalStorage()
106 },
107 editTodo({ todo, value }) {
108 todo.text = value
109 this.setLocalStorage()
110 },
111 clearCompleted() {
112 this.todos = this.todos.filter(todo => !todo.done)
113 this.setLocalStorage()
114 },
115 toggleAll({ done }) {
116 this.todos.forEach(todo => {
117 todo.done = done
118 this.setLocalStorage()
119 })
120 }
121 }
122 }
123 </script>
124
125 <style lang="scss">
126 @import './index.scss';
127 </style>
128
src/views/dashboard/admin/components/TransactionTable.vue
File was created 1 <template>
2 <el-table :data="list" style="width: 100%;padding-top: 15px;">
3 <el-table-column label="Order_No" min-width="200">
4 <template slot-scope="scope">
5 {{ scope.row.order_no | orderNoFilter }}
6 </template>
7 </el-table-column>
8 <el-table-column label="Price" width="195" align="center">
9 <template slot-scope="scope">
10 ¥{{ scope.row.price | toThousandFilter }}
11 </template>
12 </el-table-column>
13 <el-table-column label="Status" width="100" align="center">
14 <template slot-scope="{row}">
15 <el-tag :type="row.status | statusFilter">
16 {{ row.status }}
17 </el-tag>
18 </template>
19 </el-table-column>
20 </el-table>
21 </template>
22
23 <script>
24 import { transactionList } from '@/api/remote-search'
25
26 export default {
27 filters: {
28 statusFilter(status) {
29 const statusMap = {
30 success: 'success',
31 pending: 'danger'
32 }
33 return statusMap[status]
34 },
35 orderNoFilter(str) {
36 return str.substring(0, 30)
37 }
38 },
39 data() {
40 return {
41 list: null
42 }
43 },
44 created() {
45 this.fetchData()
46 },
47 methods: {
48 fetchData() {
49 transactionList().then(response => {
50 this.list = response.data.items.slice(0, 8)
51 })
52 }
53 }
54 }
55 </script>
56
src/views/dashboard/admin/components/mixins/resize.js
File was created 1 import { debounce } from '@/utils'
2
3 export default {
4 data() {
5 return {
6 $_sidebarElm: null,
7 $_resizeHandler: null
8 }
9 },
10 mounted() {
11 this.$_resizeHandler = debounce(() => {
12 if (this.chart) {
13 this.chart.resize()
14 }
15 }, 100)
16 this.$_initResizeEvent()
17 this.$_initSidebarResizeEvent()
18 },
19 beforeDestroy() {
20 this.$_destroyResizeEvent()
21 this.$_destroySidebarResizeEvent()
22 },
23 // to fixed bug when cached by keep-alive
24 // https://github.com/PanJiaChen/vue-element-admin/issues/2116
25 activated() {
26 this.$_initResizeEvent()
27 this.$_initSidebarResizeEvent()
28 },
29 deactivated() {
30 this.$_destroyResizeEvent()
31 this.$_destroySidebarResizeEvent()
32 },
33 methods: {
34 // use $_ for mixins properties
35 // https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
36 $_initResizeEvent() {
37 window.addEventListener('resize', this.$_resizeHandler)
38 },
39 $_destroyResizeEvent() {
40 window.removeEventListener('resize', this.$_resizeHandler)
41 },
42 $_sidebarResizeHandler(e) {
43 if (e.propertyName === 'width') {
44 this.$_resizeHandler()
45 }
46 },
47 $_initSidebarResizeEvent() {
48 this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
49 this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
50 },
51 $_destroySidebarResizeEvent() {
52 this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
53 }
54 }
55 }
56
src/views/dashboard/admin/index.vue
File was created 1 <template>
2 <div class="dashboard-editor-container">
3 <github-corner class="github-corner" />
4
5 <panel-group @handleSetLineChartData="handleSetLineChartData" />
6
7 <el-row style="background:#fff;padding:16px 16px 0;margin-bottom:32px;">
8 <line-chart :chart-data="lineChartData" />
9 </el-row>
10
11 <el-row :gutter="32">
12 <el-col :xs="24" :sm="24" :lg="8">
13 <div class="chart-wrapper">
14 <raddar-chart />
15 </div>
16 </el-col>
17 <el-col :xs="24" :sm="24" :lg="8">
18 <div class="chart-wrapper">
19 <pie-chart />
20 </div>
21 </el-col>
22 <el-col :xs="24" :sm="24" :lg="8">
23 <div class="chart-wrapper">
24 <bar-chart />
25 </div>
26 </el-col>
27 </el-row>
28
29 <el-row :gutter="8">
30 <el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 12}" :xl="{span: 12}" style="padding-right:8px;margin-bottom:30px;">
31 <transaction-table />
32 </el-col>
33 <el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;">
34 <todo-list />
35 </el-col>
36 <el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;">
37 <box-card />
38 </el-col>
39 </el-row>
40 </div>
41 </template>
42
43 <script>
44 import GithubCorner from '@/components/GithubCorner'
45 import PanelGroup from './components/PanelGroup'
46 import LineChart from './components/LineChart'
47 import RaddarChart from './components/RaddarChart'
48 import PieChart from './components/PieChart'
49 import BarChart from './components/BarChart'
50 import TransactionTable from './components/TransactionTable'
51 import TodoList from './components/TodoList'
52 import BoxCard from './components/BoxCard'
53
54 const lineChartData = {
55 newVisitis: {
56 expectedData: [100, 120, 161, 134, 105, 160, 165],
57 actualData: [120, 82, 91, 154, 162, 140, 145]
58 },
59 messages: {
60 expectedData: [200, 192, 120, 144, 160, 130, 140],
61 actualData: [180, 160, 151, 106, 145, 150, 130]
62 },
63 purchases: {
64 expectedData: [80, 100, 121, 104, 105, 90, 100],
65 actualData: [120, 90, 100, 138, 142, 130, 130]
66 },
67 shoppings: {
68 expectedData: [130, 140, 141, 142, 145, 150, 160],
69 actualData: [120, 82, 91, 154, 162, 140, 130]
70 }
71 }
72
73 export default {
74 name: 'DashboardAdmin',
75 components: {
76 GithubCorner,
77 PanelGroup,
78 LineChart,
79 RaddarChart,
80 PieChart,
81 BarChart,
82 TransactionTable,
83 TodoList,
84 BoxCard
85 },
86 data() {
87 return {
88 lineChartData: lineChartData.newVisitis
89 }
90 },
91 methods: {
92 handleSetLineChartData(type) {
93 this.lineChartData = lineChartData[type]
94 }
95 }
96 }
97 </script>
98
99 <style lang="scss" scoped>
100 .dashboard-editor-container {
101 padding: 32px;
102 background-color: rgb(240, 242, 245);
103 position: relative;
104
105 .github-corner {
106 position: absolute;
107 top: 0px;
108 border: 0;
109 right: 0;
110 }
111
112 .chart-wrapper {
113 background: #fff;
114 padding: 16px 16px 0;
115 margin-bottom: 32px;
116 }
117 }
118
119 @media (max-width:1024px) {
120 .chart-wrapper {
121 padding: 8px;
122 }
123 }
124 </style>
125
src/views/dashboard/editor/index.vue
File was created 1 <template>
2 <div class="dashboard-editor-container">
3 <div class=" clearfix">
4 <pan-thumb :image="avatar" style="float: left">
5 Your roles:
6 <span v-for="item in roles" :key="item" class="pan-info-roles">{{ item }}</span>
7 </pan-thumb>
8 <github-corner style="position: absolute; top: 0px; border: 0; right: 0;" />
9 <div class="info-container">
10 <span class="display_name">{{ name }}</span>
11 <span style="font-size:20px;padding-top:20px;display:inline-block;">Editor's Dashboard</span>
12 </div>
13 </div>
14 <div>
15 <img :src="emptyGif" class="emptyGif">
16 </div>
17 </div>
18 </template>
19
20 <script>
21 import { mapGetters } from 'vuex'
22 import PanThumb from '@/components/PanThumb'
23 import GithubCorner from '@/components/GithubCorner'
24
25 export default {
26 name: 'DashboardEditor',
27 components: { PanThumb, GithubCorner },
28 data() {
29 return {
30 emptyGif: 'https://wpimg.wallstcn.com/0e03b7da-db9e-4819-ba10-9016ddfdaed3'
31 }
32 },
33 computed: {
34 ...mapGetters([
35 'name',
36 'avatar',
37 'roles'
38 ])
39 }
40 }
41 </script>
42
43 <style lang="scss" scoped>
44 .emptyGif {
45 display: block;
46 width: 45%;
47 margin: 0 auto;
48 }
49
50 .dashboard-editor-container {
51 background-color: #e3e3e3;
52 min-height: 100vh;
53 padding: 50px 60px 0px;
54 .pan-info-roles {
55 font-size: 12px;
56 font-weight: 700;
57 color: #333;
58 display: block;
59 }
60 .info-container {
61 position: relative;
62 margin-left: 190px;
63 height: 150px;
64 line-height: 200px;
65 .display_name {
66 font-size: 48px;
67 line-height: 48px;
68 color: #212121;
69 position: absolute;
70 top: 25px;
71 }
72 }
73 }
74 </style>
75
src/views/dashboard/index.vue
1 <template> 1 <template>
2 <div> 2 <div class="dashboard-container">
3 <el-row :gutter="20"> 3 <component :is="currentRole" />
4 <el-col :span="8">
5 <el-card shadow="hover" class="mgb20" style="height:252px;">
6 <div class="user-info">
7 <img src="../../assets/img/img.jpg" class="user-avator" alt />
8 <div class="user-info-cont">
9 <div class="user-info-name">{{name}}</div>
10 <div>{{role}}</div>
11 </div>
12 </div>
13 <div class="user-info-list">
14 上次登录时间:
15 <span>2019-11-01</span>
16 </div>
17 <div class="user-info-list">
18 上次登录地点:
19 <span>东莞</span>
20 </div>
21 </el-card>
22 <el-card shadow="hover" style="height:252px;">
23 <div slot="header" class="clearfix">
24 <span>语言详情</span>
25 </div>Vue
26 <el-progress :percentage="71.3" color="#42b983"></el-progress>JavaScript
27 <el-progress :percentage="24.1" color="#f1e05a"></el-progress>CSS
28 <el-progress :percentage="13.7"></el-progress>HTML
29 <el-progress :percentage="5.9" color="#f56c6c"></el-progress>
30 </el-card>
31 </el-col>
32 <el-col :span="16">
33 <el-row :gutter="20" class="mgb20">
34 <el-col :span="8">
35 <el-card shadow="hover" :body-style="{padding: '0px'}">
36 <div class="grid-content grid-con-1">
37 <i class="el-icon-lx-people grid-con-icon"></i>
38 <div class="grid-cont-right">
39 <div class="grid-num">1234</div>
40 <div>用户访问量</div>
41 </div>
42 </div>
43 </el-card>
44 </el-col>
45 <el-col :span="8">
46 <el-card shadow="hover" :body-style="{padding: '0px'}">
47 <div class="grid-content grid-con-2">
48 <i class="el-icon-lx-notice grid-con-icon"></i>
49 <div class="grid-cont-right">
50 <div class="grid-num">321</div>
51 <div>系统消息</div>
52 </div>
53 </div>
54 </el-card>
55 </el-col>
56 <el-col :span="8">
57 <el-card shadow="hover" :body-style="{padding: '0px'}">
58 <div class="grid-content grid-con-3">
59 <i class="el-icon-lx-goods grid-con-icon"></i>
60 <div class="grid-cont-right">
61 <div class="grid-num">5000</div>
62 <div>数量</div>
63 </div>
64 </div>
65 </el-card>
66 </el-col>
67 </el-row>
68 <el-card shadow="hover" style="height:403px;">
69 <div slot="header" class="clearfix">
70 <span>待办事项</span>
71 <el-button style="float: right; padding: 3px 0" type="text" @click="addAction">添加</el-button>
72 </div>
73 <el-table :show-header="false" :data="todoList" style="width:100%;">
74 <el-table-column width="40">
75 <template slot-scope="scope">
76 <el-checkbox v-model="scope.row.status"></el-checkbox>
77 </template>
78 </el-table-column>
79 <el-table-column>
80 <template slot-scope="scope">
81 <div
82 class="todo-item"
83 :class="{'todo-item-del': scope.row.status}"
84 >{{scope.row.title}}</div>
85 </template>
86 </el-table-column>
87 <el-table-column width="60">
88 <template>
89 <i class="el-icon-edit" @click="modiAction"></i>
90 <i class="el-icon-delete" @click="delAction"></i>
91 </template>
92 </el-table-column>
93 </el-table>
94 </el-card>
95 </el-col>
96 </el-row>
97 <el-row :gutter="20">
98 <el-col :span="12">
99 <el-card shadow="hover">
100 <schart ref="bar" class="schart" canvasId="bar" :options="options"></schart>
101 </el-card>
102 </el-col>
103 <el-col :span="12">
104 <el-card shadow="hover">
105 <schart ref="line" class="schart" canvasId="line" :options="options2"></schart>
106 </el-card>
107 </el-col>
108 </el-row>
109 </div> 4 </div>
110 </template> 5 </template>
111 6
112 <script> 7 <script>
113 import { mapGetters } from "vuex"; 8 import { mapGetters } from 'vuex'
114 import Vue from "vue"; 9 import adminDashboard from './admin'
115 import { 10 import editorDashboard from './editor'
116 Pagination,
117 Dialog,
118 Autocomplete,
119 Dropdown,
120 DropdownMenu,
121 DropdownItem,
122 Menu,
123 Submenu,
124 MenuItem,
125 MenuItemGroup,
126 Input,
127 InputNumber,
128 Radio,
129 RadioGroup,
130 RadioButton,
131 Checkbox,
132 CheckboxButton,
133 CheckboxGroup,
134 Switch,
135 Select,
136 Option,
137 OptionGroup,
138 Button,
139 ButtonGroup,
140 Table,
141 TableColumn,
142 DatePicker,
143 TimeSelect,
144 TimePicker,
145 Popover,
146 Tooltip,
147 Breadcrumb,
148 BreadcrumbItem,
149 Form,
150 FormItem,
151 Tabs,
152 TabPane,
153 Tag,
154 Tree,
155 Alert,
156 Slider,
157 Icon,
158 Row,
159 Col,
160 Upload,
161 Progress,
162 Spinner,
163 Badge,
164 Card,
165 Rate,
166 Steps,
167 Step,
168 Carousel,
169 CarouselItem,
170 Collapse,
171 CollapseItem,
172 Cascader,
173 ColorPicker,
174 Transfer,
175 Container,
176 Header,
177 Aside,
178 Main,
179 Footer,
180 Timeline,
181 TimelineItem,
182 Link,
183 Divider,
184 Image,
185 Calendar,
186 Backtop,
187 PageHeader,
188 CascaderPanel,
189 Loading,
190 MessageBox,
191 Message,
192 Notification
193 } from "element-ui";
194 // import ElementUI from 'element-ui'
195 Vue.prototype.$ELEMENT = { size: "small", zIndex: 3000 };
196 Vue.use(Pagination);
197 Vue.use(Dialog);
198 Vue.use(Autocomplete);
199 Vue.use(Dropdown);
200 Vue.use(DropdownMenu);
201 Vue.use(DropdownItem);
202 Vue.use(Menu);
203 Vue.use(Submenu);
204 Vue.use(MenuItem);
205 Vue.use(MenuItemGroup);
206 Vue.use(Input);
207 Vue.use(InputNumber);
208 Vue.use(Radio);
209 Vue.use(RadioGroup);
210 Vue.use(RadioButton);
211 Vue.use(Checkbox);
212 Vue.use(CheckboxButton);
213 Vue.use(CheckboxGroup);
214 Vue.use(Switch);
215 Vue.use(Select);
216 Vue.use(Option);
217 Vue.use(OptionGroup);
218 Vue.use(Button);
219 Vue.use(ButtonGroup);
220 Vue.use(Table);
221 Vue.use(TableColumn);
222 Vue.use(DatePicker);
223 Vue.use(TimeSelect);
224 Vue.use(TimePicker);
225 Vue.use(Popover);
226 Vue.use(Tooltip);
227 Vue.use(Breadcrumb);
228 Vue.use(BreadcrumbItem);
229 Vue.use(Form);
230 Vue.use(FormItem);
231 Vue.use(Tabs);
232 Vue.use(TabPane);
233 Vue.use(Tag);
234 Vue.use(Tree);
235 Vue.use(Alert);
236 Vue.use(Slider);
237 Vue.use(Icon);
238 Vue.use(Row);
239 Vue.use(Col);
240 Vue.use(Upload);
241 Vue.use(Progress);
242 Vue.use(Spinner);
243 Vue.use(Badge);
244 Vue.use(Card);
245 Vue.use(Rate);
246 Vue.use(Steps);
247 Vue.use(Step);
248 Vue.use(Carousel);
249 Vue.use(CarouselItem);
250 Vue.use(Collapse);
251 Vue.use(CollapseItem);
252 Vue.use(Cascader);
253 Vue.use(ColorPicker);
254 Vue.use(Transfer);
255 Vue.use(Container);
256 Vue.use(Header);
257 Vue.use(Aside);
258 Vue.use(Main);
259 Vue.use(Footer);
260 Vue.use(Timeline);
261 Vue.use(TimelineItem);
262 Vue.use(Link);
263 Vue.use(Divider);
264 Vue.use(Image);
265 Vue.use(Calendar);
266 Vue.use(Backtop);
267 Vue.use(PageHeader);
268 Vue.use(CascaderPanel);
269 Vue.use(Loading.directive);
270
271 import Schart from "vue-schart";
272 import bus from "../../common/bus";
273
274 // 按需引入 引入 ECharts 主模块
275 // var echarts = require('echarts/lib/echarts')
276 // 引入柱状图
277 // require('echarts/lib/chart/bar')
278 // 引入提示框和标题组件
279 // require('echarts/lib/component/tooltip')
280 // require('echarts/lib/component/title')
281 // 全部引入
282 // var echarts = require('echarts')
283 11
284 export default { 12 export default {
285 name: "Dashboard", 13 name: 'Dashboard',
14 components: { adminDashboard, editorDashboard },
286 data() { 15 data() {
287 return { 16 return {
288 name: localStorage.getItem("ms_username"), 17 currentRole: 'adminDashboard'
289 todoList: [ 18 }
290 {
291 title: "今天要修复100个bug",
292 status: true
293 },
294 {
295 title: "今天要写100行代码加几个bug吧",
296 status: true
297 }
298 ],
299 data: [
300 {
301 name: "2018/09/04",
302 value: 1083
303 },
304 {
305 name: "2018/09/10",
306 value: 1065
307 }
308 ],
309 options: {
310 type: "bar",
311 title: {
312 text: "最近一周各品类销售图"
313 },
314 xRorate: 25,
315 labels: ["周一", "周二", "周三", "周四", "周五"],
316 datasets: [
317 {
318 label: "百货",
319 data: [164, 178, 190, 135, 160]
320 },
321 {
322 label: "食品",
323 data: [144, 198, 150, 235, 120]
324 }
325 ]
326 },
327 options2: {
328 type: "line",
329 title: {
330 text: "最近几个月各品类销售趋势图"
331 },
332 labels: ["6月", "7月", "8月", "9月", "10月"],
333 datasets: [
334 {
335 label: "百货",
336 data: [164, 178, 150, 135, 160]
337 },
338 {
339 label: "食品",
340 data: [74, 118, 200, 235, 90]
341 }
342 ]
343 }
344 };
345 },
346 components: {
347 Schart
348 }, 19 },
349 computed: { 20 computed: {
350 // ...mapGetters(["name", "roles"]) 21 ...mapGetters([
351 role() { 22 'roles'
352 return this.name === "admin" ? "超级管理员" : "普通用户"; 23 ])
353 }
354 }, 24 },
355 methods: { 25 created() {
356 addAction(){ 26 if (!this.roles.includes('admin')) {
357 this.$prompt("请输入内容", "提示", { 27 this.currentRole = 'editorDashboard'
358 confirmButtonText: "确定",
359 cancelButtonText: "取消",
360 inputErrorMessage: "内容不能为空"
361 })
362 .then(({ value }) => {
363 this.$message({
364 type: "success",
365 message: "你的邮箱是: " + value
366 });
367 })
368 .catch(() => {
369 this.$message({
370 type: "info",
371 message: "取消输入"
372 });
373 });
374 },
375 modiAction() {
376 // this.$prompt("请输入邮箱", "提示", {
377 // confirmButtonText: "确定",
378 // cancelButtonText: "取消",
379 // inputPattern: /[\w!#$%&'*+/=?^_`{|}~-]+(?:\.[\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\w](?:[\w-]*[\w])?\.)+[\w](?:[\w-]*[\w])?/,
380 // inputErrorMessage: "邮箱格式不正确"
381 // })
382 this.$prompt("请输入内容", "提示", {
383 confirmButtonText: "确定",
384 cancelButtonText: "取消",
385 inputErrorMessage: "内容不能为空"
386 })
387 .then(({ value }) => {
388 this.$message({
389 type: "success",
390 message: "你的邮箱是: " + value
391 });
392 })
393 .catch(() => {
394 this.$message({
395 type: "info",
396 message: "取消输入"
397 });
398 });
399 },
400 delAction() {
401 this.$confirm("此操作将永久删除该文件, 是否继续?", "提示", {
402 confirmButtonText: "确定",
403 cancelButtonText: "取消",
404 type: "warning"
405 })
406 .then(() => {
407 this.$message({
408 type: "success",
409 message: "删除成功!"
410 });
411 })
412 .catch(() => {
413 this.$message({
414 type: "info",
415 message: "已取消删除"
416 });
417 });
418 },
419 changeDate() {
420 const now = new Date().getTime();
421 this.data.forEach((item, index) => {
422 const date = new Date(now - (6 - index) * 86400000);
423 item.name = `${date.getFullYear()}/${date.getMonth() +
424 1}/${date.getDate()}`;
425 });
426 } 28 }
427 } 29 }
428 };
429 </script>
430
431 <style scoped>
432 .el-row {
433 margin-bottom: 20px;
434 }
435 .grid-content {
436 display: flex;
437 align-items: center;
438 height: 100px;
439 }
440 .grid-cont-right {
441 flex: 1;
442 text-align: center;
443 font-size: 14px;
444 color: #999;
445 }
446 .grid-num {
447 font-size: 30px;
448 font-weight: bold;
449 }
450 .grid-con-icon {
451 font-size: 50px;
452 width: 100px;
453 height: 100px;
454 text-align: center;
455 line-height: 100px;
456 color: #fff;
457 }
458 .grid-con-1 .grid-con-icon {
459 background: rgb(45, 140, 240);
460 }
461 .grid-con-1 .grid-num {
462 color: rgb(45, 140, 240);
463 }
464 .grid-con-2 .grid-con-icon {
465 background: rgb(100, 213, 114);
466 } 30 }
467 .grid-con-2 .grid-num { 31 </script>
468 color: rgb(45, 140, 240);
469 }
470 .grid-con-3 .grid-con-icon {
471 background: rgb(242, 94, 67);
472 }
473 .grid-con-3 .grid-num {
474 color: rgb(242, 94, 67);
475 }
476 .user-info {
477 display: flex;
478 align-items: center;
479 padding-bottom: 20px;
480 border-bottom: 2px solid #ccc;
481 margin-bottom: 20px;
482 }
483 .user-avator {
484 width: 120px;
485 height: 120px;
486 border-radius: 50%;
487 }
488 .user-info-cont {
489 padding-left: 50px;
490 flex: 1;
491 font-size: 14px;
492 color: #999;
493 }
494 .user-info-cont div:first-child {
495 font-size: 30px;
496 color: #222;
497 }
498 .user-info-list {
499 font-size: 14px;
500 color: #999;
501 line-height: 25px;
502 }
503 .user-info-list span {
504 margin-left: 70px;
505 }
506 .mgb20 {
507 margin-bottom: 20px;
508 }
509 .todo-item {
510 font-size: 14px;
511 }
512 .todo-item-del {
513 text-decoration: line-through;
514 color: #999;
515 }
516 .schart {
517 width: 100%;
518 height: 300px;
519 }
520 </style>
src/views/documentation/index.vue
File was created 1 <template>
2 <div class="app-container documentation-container">
3 <a class="document-btn" target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/">Documentation</a>
4 <a class="document-btn" target="_blank" href="https://github.com/PanJiaChen/vue-element-admin/">Github Repository</a>
5 <a class="document-btn" target="_blank" href="https://panjiachen.gitee.io/vue-element-admin-site/zh/">国内文档</a>
6 <dropdown-menu class="document-btn" :items="articleList" title="系列文章" />
7 <a class="document-btn" target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/zh/job/">内推招聘</a>
8 </div>
9 </template>
10
11 <script>
12 import DropdownMenu from '@/components/Share/DropdownMenu'
13
14 export default {
15 name: 'Documentation',
16 components: { DropdownMenu },
17 data() {
18 return {
19 articleList: [
20 { title: '基础篇', href: 'https://juejin.im/post/59097cd7a22b9d0065fb61d2' },
21 { title: '登录权限篇', href: 'https://juejin.im/post/591aa14f570c35006961acac' },
22 { title: '实战篇', href: 'https://juejin.im/post/593121aa0ce4630057f70d35' },
23 { title: 'vue-admin-template 篇', href: 'https://juejin.im/post/595b4d776fb9a06bbe7dba56' },
24 { title: 'v4.0 篇', href: 'https://juejin.im/post/5c92ff94f265da6128275a85' },
25 { title: '自行封装 component', href: 'https://segmentfault.com/a/1190000009090836' },
26 { title: '优雅的使用 icon', href: 'https://juejin.im/post/59bb864b5188257e7a427c09' },
27 { title: 'webpack4(上)', href: 'https://juejin.im/post/59bb864b5188257e7a427c09' },
28 { title: 'webpack4(下)', href: 'https://juejin.im/post/5b5d6d6f6fb9a04fea58aabc' }
29 ]
30 }
31 }
32 }
33 </script>
34
35 <style lang="scss" scoped>
36 .documentation-container {
37 margin: 50px;
38 display: flex;
39 flex-wrap: wrap;
40 justify-content: space-evenly;
41
42 .document-btn {
43 flex-shrink: 0;
44 display: block;
45 cursor: pointer;
46 background: black;
47 color: white;
48 height: 60px;
49 width: 200px;
50 margin-bottom: 16px;
51 line-height: 60px;
52 font-size: 20px;
53 text-align: center;
54 }
55 }
56 </style>
57
src/views/error-log/components/ErrorTestA.vue
File was created 1 <template>
2 <div>
3 <!--error code-->
4 {{ a.a }}
5 <!--error code-->
6 </div>
7 </template>
8
9 <script>
10 export default {
11 name: 'ErrorTestA'
12 }
13 </script>
14
src/views/error-log/components/ErrorTestB.vue
File was created 1 <template>
2 <div />
3 </template>
4
5 <script>
6 export default {
7 created() {
8 this.b = b // eslint-disable-line
9 }
10 }
11 </script>
12
src/views/error-log/index.vue
File was created 1 <template>
2 <div class="errPage-container">
3 <ErrorA />
4 <ErrorB />
5 <!-- $t is vue-i18n global function to translate lang -->
6 <h3>{{ $t('errorLog.tips') }}</h3>
7 <aside>
8 {{ $t('errorLog.description') }}
9 <a target="_blank" class="link-type" href="https://panjiachen.github.io/vue-element-admin-site/guide/advanced/error.html">
10 {{ $t('errorLog.documentation') }}
11 </a>
12 </aside>
13 <a href="#">
14 <img src="https://wpimg.wallstcn.com/360e4842-4db5-42d0-b078-f9a84a825546.gif">
15 </a>
16 </div>
17 </template>
18
19 <script>
20 import ErrorA from './components/ErrorTestA'
21 import ErrorB from './components/ErrorTestB'
22
23 export default {
24 name: 'ErrorLog',
25 components: { ErrorA, ErrorB }
26 }
27 </script>
28
29 <style scoped>
30 .errPage-container {
31 padding: 30px;
32 }
33 </style>
34
src/views/error-page/401.vue
File was created 1 <template>
2 <div class="errPage-container">
3 <el-button icon="el-icon-arrow-left" class="pan-back-btn" @click="back">
4 返回
5 </el-button>
6 <el-row>
7 <el-col :span="12">
8 <h1 class="text-jumbo text-ginormous">
9 Oops!
10 </h1>
11 gif来源<a href="https://zh.airbnb.com/" target="_blank">airbnb</a> 页面
12 <h2>你没有权限去该页面</h2>
13 <h6>如有不满请联系你领导</h6>
14 <ul class="list-unstyled">
15 <li>或者你可以去:</li>
16 <li class="link-type">
17 <router-link to="/dashboard">
18 回首页
19 </router-link>
20 </li>
21 <li class="link-type">
22 <a href="https://www.taobao.com/">随便看看</a>
23 </li>
24 <li><a href="#" @click.prevent="dialogVisible=true">点我看图</a></li>
25 </ul>
26 </el-col>
27 <el-col :span="12">
28 <img :src="errGif" width="313" height="428" alt="Girl has dropped her ice cream.">
29 </el-col>
30 </el-row>
31 <el-dialog :visible.sync="dialogVisible" title="随便看">
32 <img :src="ewizardClap" class="pan-img">
33 </el-dialog>
34 </div>
35 </template>
36
37 <script>
38 import errGif from '@/assets/401_images/401.gif'
39
40 export default {
41 name: 'Page401',
42 data() {
43 return {
44 errGif: errGif + '?' + +new Date(),
45 ewizardClap: 'https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646',
46 dialogVisible: false
47 }
48 },
49 methods: {
50 back() {
51 if (this.$route.query.noGoBack) {
52 this.$router.push({ path: '/dashboard' })
53 } else {
54 this.$router.go(-1)
55 }
56 }
57 }
58 }
59 </script>
60
61 <style lang="scss" scoped>
62 .errPage-container {
63 width: 800px;
64 max-width: 100%;
65 margin: 100px auto;
66 .pan-back-btn {
67 background: #008489;
68 color: #fff;
69 border: none!important;
70 }
71 .pan-gif {
72 margin: 0 auto;
73 display: block;
74 }
75 .pan-img {
76 display: block;
77 margin: 0 auto;
78 width: 100%;
79 }
80 .text-jumbo {
81 font-size: 60px;
82 font-weight: 700;
83 color: #484848;
84 }
85 .list-unstyled {
86 font-size: 14px;
87 li {
88 padding-bottom: 5px;
89 }
90 a {
91 color: #008489;
92 text-decoration: none;
93 &:hover {
94 text-decoration: underline;
95 }
96 }
97 }
98 }
99 </style>
100
src/views/error-page/404.vue
File was created 1 <template>
2 <div class="wscn-http404-container">
3 <div class="wscn-http404">
4 <div class="pic-404">
5 <img class="pic-404__parent" src="@/assets/404_images/404.png" alt="404">
6 <img class="pic-404__child left" src="@/assets/404_images/404_cloud.png" alt="404">
7 <img class="pic-404__child mid" src="@/assets/404_images/404_cloud.png" alt="404">
8 <img class="pic-404__child right" src="@/assets/404_images/404_cloud.png" alt="404">
9 </div>
10 <div class="bullshit">
11 <div class="bullshit__oops">OOPS!</div>
12 <div class="bullshit__info">All rights reserved
13 <a style="color:#20a0ff" href="https://wallstreetcn.com" target="_blank">wallstreetcn</a>
14 </div>
15 <div class="bullshit__headline">{{ message }}</div>
16 <div class="bullshit__info">Please check that the URL you entered is correct, or click the button below to return to the homepage.</div>
17 <a href="" class="bullshit__return-home">Back to home</a>
18 </div>
19 </div>
20 </div>
21 </template>
22
23 <script>
24
25 export default {
26 name: 'Page404',
27 computed: {
28 message() {
29 return 'The webmaster said that you can not enter this page...'
30 }
31 }
32 }
33 </script>
34
35 <style lang="scss" scoped>
36 .wscn-http404-container{
37 transform: translate(-50%,-50%);
38 position: absolute;
39 top: 40%;
40 left: 50%;
41 }
42 .wscn-http404 {
43 position: relative;
44 width: 1200px;
45 padding: 0 50px;
46 overflow: hidden;
47 .pic-404 {
48 position: relative;
49 float: left;
50 width: 600px;
51 overflow: hidden;
52 &__parent {
53 width: 100%;
54 }
55 &__child {
56 position: absolute;
57 &.left {
58 width: 80px;
59 top: 17px;
60 left: 220px;
61 opacity: 0;
62 animation-name: cloudLeft;
63 animation-duration: 2s;
64 animation-timing-function: linear;
65 animation-fill-mode: forwards;
66 animation-delay: 1s;
67 }
68 &.mid {
69 width: 46px;
70 top: 10px;
71 left: 420px;
72 opacity: 0;
73 animation-name: cloudMid;
74 animation-duration: 2s;
75 animation-timing-function: linear;
76 animation-fill-mode: forwards;
77 animation-delay: 1.2s;
78 }
79 &.right {
80 width: 62px;
81 top: 100px;
82 left: 500px;
83 opacity: 0;
84 animation-name: cloudRight;
85 animation-duration: 2s;
86 animation-timing-function: linear;
87 animation-fill-mode: forwards;
88 animation-delay: 1s;
89 }
90 @keyframes cloudLeft {
91 0% {
92 top: 17px;
93 left: 220px;
94 opacity: 0;
95 }
96 20% {
97 top: 33px;
98 left: 188px;
99 opacity: 1;
100 }
101 80% {
102 top: 81px;
103 left: 92px;
104 opacity: 1;
105 }
106 100% {
107 top: 97px;
108 left: 60px;
109 opacity: 0;
110 }
111 }
112 @keyframes cloudMid {
113 0% {
114 top: 10px;
115 left: 420px;
116 opacity: 0;
117 }
118 20% {
119 top: 40px;
120 left: 360px;
121 opacity: 1;
122 }
123 70% {
124 top: 130px;
125 left: 180px;
126 opacity: 1;
127 }
128 100% {
129 top: 160px;
130 left: 120px;
131 opacity: 0;
132 }
133 }
134 @keyframes cloudRight {
135 0% {
136 top: 100px;
137 left: 500px;
138 opacity: 0;
139 }
140 20% {
141 top: 120px;
142 left: 460px;
143 opacity: 1;
144 }
145 80% {
146 top: 180px;
147 left: 340px;
148 opacity: 1;
149 }
150 100% {
151 top: 200px;
152 left: 300px;
153 opacity: 0;
154 }
155 }
156 }
157 }
158 .bullshit {
159 position: relative;
160 float: left;
161 width: 300px;
162 padding: 30px 0;
163 overflow: hidden;
164 &__oops {
165 font-size: 32px;
166 font-weight: bold;
167 line-height: 40px;
168 color: #1482f0;
169 opacity: 0;
170 margin-bottom: 20px;
171 animation-name: slideUp;
172 animation-duration: 0.5s;
173 animation-fill-mode: forwards;
174 }
175 &__headline {
176 font-size: 20px;
177 line-height: 24px;
178 color: #222;
179 font-weight: bold;
180 opacity: 0;
181 margin-bottom: 10px;
182 animation-name: slideUp;
183 animation-duration: 0.5s;
184 animation-delay: 0.1s;
185 animation-fill-mode: forwards;
186 }
187 &__info {
188 font-size: 13px;
189 line-height: 21px;
190 color: grey;
191 opacity: 0;
192 margin-bottom: 30px;
193 animation-name: slideUp;
194 animation-duration: 0.5s;
195 animation-delay: 0.2s;
196 animation-fill-mode: forwards;
197 }
198 &__return-home {
199 display: block;
200 float: left;
201 width: 110px;
202 height: 36px;
203 background: #1482f0;
204 border-radius: 100px;
205 text-align: center;
206 color: #ffffff;
207 opacity: 0;
208 font-size: 14px;
209 line-height: 36px;
210 cursor: pointer;
211 animation-name: slideUp;
212 animation-duration: 0.5s;
213 animation-delay: 0.3s;
214 animation-fill-mode: forwards;
215 }
216 @keyframes slideUp {
217 0% {
218 transform: translateY(60px);
219 opacity: 0;
220 }
221 100% {
222 transform: translateY(0);
223 opacity: 1;
224 }
225 }
226 }
227 }
228 </style>
229
src/views/example/components/ArticleDetail.vue
File was created 1 <template>
2 <div class="createPost-container">
3 <el-form ref="postForm" :model="postForm" :rules="rules" class="form-container">
4 <sticky :z-index="10" :class-name="'sub-navbar '+postForm.status">
5 <CommentDropdown v-model="postForm.comment_disabled" />
6 <PlatformDropdown v-model="postForm.platforms" />
7 <SourceUrlDropdown v-model="postForm.source_uri" />
8 <el-button v-loading="loading" style="margin-left: 10px;" type="success" @click="submitForm">
9 Publish
10 </el-button>
11 <el-button v-loading="loading" type="warning" @click="draftForm">
12 Draft
13 </el-button>
14 </sticky>
15
16 <div class="createPost-main-container">
17 <el-row>
18 <Warning />
19
20 <el-col :span="24">
21 <el-form-item style="margin-bottom: 40px;" prop="title">
22 <MDinput v-model="postForm.title" :maxlength="100" name="name" required>
23 Title
24 </MDinput>
25 </el-form-item>
26
27 <div class="postInfo-container">
28 <el-row>
29 <el-col :span="8">
30 <el-form-item label-width="60px" label="Author:" class="postInfo-container-item">
31 <el-select v-model="postForm.author" :remote-method="getRemoteUserList" filterable default-first-option remote placeholder="Search user">
32 <el-option v-for="(item,index) in userListOptions" :key="item+index" :label="item" :value="item" />
33 </el-select>
34 </el-form-item>
35 </el-col>
36
37 <el-col :span="10">
38 <el-form-item label-width="120px" label="Publish Time:" class="postInfo-container-item">
39 <el-date-picker v-model="displayTime" type="datetime" format="yyyy-MM-dd HH:mm:ss" placeholder="Select date and time" />
40 </el-form-item>
41 </el-col>
42
43 <el-col :span="6">
44 <el-form-item label-width="90px" label="Importance:" class="postInfo-container-item">
45 <el-rate
46 v-model="postForm.importance"
47 :max="3"
48 :colors="['#99A9BF', '#F7BA2A', '#FF9900']"
49 :low-threshold="1"
50 :high-threshold="3"
51 style="display:inline-block"
52 />
53 </el-form-item>
54 </el-col>
55 </el-row>
56 </div>
57 </el-col>
58 </el-row>
59
60 <el-form-item style="margin-bottom: 40px;" label-width="70px" label="Summary:">
61 <el-input v-model="postForm.content_short" :rows="1" type="textarea" class="article-textarea" autosize placeholder="Please enter the content" />
62 <span v-show="contentShortLength" class="word-counter">{{ contentShortLength }}words</span>
63 </el-form-item>
64
65 <el-form-item prop="content" style="margin-bottom: 30px;">
66 <Tinymce ref="editor" v-model="postForm.content" :height="400" />
67 </el-form-item>
68
69 <el-form-item prop="image_uri" style="margin-bottom: 30px;">
70 <Upload v-model="postForm.image_uri" />
71 </el-form-item>
72 </div>
73 </el-form>
74 </div>
75 </template>
76
77 <script>
78 import Tinymce from '@/components/Tinymce'
79 import Upload from '@/components/Upload/SingleImage3'
80 import MDinput from '@/components/MDinput'
81 import Sticky from '@/components/Sticky' // 粘性header组件
82 import { validURL } from '@/utils/validate'
83 import { fetchArticle } from '@/api/article'
84 import { searchUser } from '@/api/remote-search'
85 import Warning from './Warning'
86 import { CommentDropdown, PlatformDropdown, SourceUrlDropdown } from './Dropdown'
87
88 const defaultForm = {
89 status: 'draft',
90 title: '', // 文章题目
91 content: '', // 文章内容
92 content_short: '', // 文章摘要
93 source_uri: '', // 文章外链
94 image_uri: '', // 文章图片
95 display_time: undefined, // 前台展示时间
96 id: undefined,
97 platforms: ['a-platform'],
98 comment_disabled: false,
99 importance: 0
100 }
101
102 export default {
103 name: 'ArticleDetail',
104 components: { Tinymce, MDinput, Upload, Sticky, Warning, CommentDropdown, PlatformDropdown, SourceUrlDropdown },
105 props: {
106 isEdit: {
107 type: Boolean,
108 default: false
109 }
110 },
111 data() {
112 const validateRequire = (rule, value, callback) => {
113 if (value === '') {
114 this.$message({
115 message: rule.field + '为必传项',
116 type: 'error'
117 })
118 callback(new Error(rule.field + '为必传项'))
119 } else {
120 callback()
121 }
122 }
123 const validateSourceUri = (rule, value, callback) => {
124 if (value) {
125 if (validURL(value)) {
126 callback()
127 } else {
128 this.$message({
129 message: '外链url填写不正确',
130 type: 'error'
131 })
132 callback(new Error('外链url填写不正确'))
133 }
134 } else {
135 callback()
136 }
137 }
138 return {
139 postForm: Object.assign({}, defaultForm),
140 loading: false,
141 userListOptions: [],
142 rules: {
143 image_uri: [{ validator: validateRequire }],
144 title: [{ validator: validateRequire }],
145 content: [{ validator: validateRequire }],
146 source_uri: [{ validator: validateSourceUri, trigger: 'blur' }]
147 },
148 tempRoute: {}
149 }
150 },
151 computed: {
152 contentShortLength() {
153 return this.postForm.content_short.length
154 },
155 lang() {
156 return this.$store.getters.language
157 },
158 displayTime: {
159 // set and get is useful when the data
160 // returned by the back end api is different from the front end
161 // back end return => "2013-06-25 06:59:25"
162 // front end need timestamp => 1372114765000
163 get() {
164 return (+new Date(this.postForm.display_time))
165 },
166 set(val) {
167 this.postForm.display_time = new Date(val)
168 }
169 }
170 },
171 created() {
172 if (this.isEdit) {
173 const id = this.$route.params && this.$route.params.id
174 this.fetchData(id)
175 }
176
177 // Why need to make a copy of this.$route here?
178 // Because if you enter this page and quickly switch tag, may be in the execution of the setTagsViewTitle function, this.$route is no longer pointing to the current page
179 // https://github.com/PanJiaChen/vue-element-admin/issues/1221
180 this.tempRoute = Object.assign({}, this.$route)
181 },
182 methods: {
183 fetchData(id) {
184 fetchArticle(id).then(response => {
185 this.postForm = response.data
186
187 // just for test
188 this.postForm.title += ` Article Id:${this.postForm.id}`
189 this.postForm.content_short += ` Article Id:${this.postForm.id}`
190
191 // set tagsview title
192 this.setTagsViewTitle()
193
194 // set page title
195 this.setPageTitle()
196 }).catch(err => {
197 console.log(err)
198 })
199 },
200 setTagsViewTitle() {
201 const title = this.lang === 'zh' ? '编辑文章' : 'Edit Article'
202 const route = Object.assign({}, this.tempRoute, { title: `${title}-${this.postForm.id}` })
203 this.$store.dispatch('tagsView/updateVisitedView', route)
204 },
205 setPageTitle() {
206 const title = 'Edit Article'
207 document.title = `${title} - ${this.postForm.id}`
208 },
209 submitForm() {
210 console.log(this.postForm)
211 this.$refs.postForm.validate(valid => {
212 if (valid) {
213 this.loading = true
214 this.$notify({
215 title: '成功',
216 message: '发布文章成功',
217 type: 'success',
218 duration: 2000
219 })
220 this.postForm.status = 'published'
221 this.loading = false
222 } else {
223 console.log('error submit!!')
224 return false
225 }
226 })
227 },
228 draftForm() {
229 if (this.postForm.content.length === 0 || this.postForm.title.length === 0) {
230 this.$message({
231 message: '请填写必要的标题和内容',
232 type: 'warning'
233 })
234 return
235 }
236 this.$message({
237 message: '保存成功',
238 type: 'success',
239 showClose: true,
240 duration: 1000
241 })
242 this.postForm.status = 'draft'
243 },
244 getRemoteUserList(query) {
245 searchUser(query).then(response => {
246 if (!response.data.items) return
247 this.userListOptions = response.data.items.map(v => v.name)
248 })
249 }
250 }
251 }
252 </script>
253
254 <style lang="scss" scoped>
255 @import "~@/styles/mixin.scss";
256
257 .createPost-container {
258 position: relative;
259
260 .createPost-main-container {
261 padding: 40px 45px 20px 50px;
262
263 .postInfo-container {
264 position: relative;
265 @include clearfix;
266 margin-bottom: 10px;
267
268 .postInfo-container-item {
269 float: left;
270 }
271 }
272 }
273
274 .word-counter {
275 width: 40px;
276 position: absolute;
277 right: 10px;
278 top: 0px;
279 }
280 }
281
282 .article-textarea /deep/ {
283 textarea {
284 padding-right: 40px;
285 resize: none;
286 border: none;
287 border-radius: 0px;
288 border-bottom: 1px solid #bfcbd9;
289 }
290 }
291 </style>
292
src/views/example/components/Dropdown/Comment.vue
File was created 1 <template>
2 <el-dropdown :show-timeout="100" trigger="click">
3 <el-button plain>
4 {{ !comment_disabled?'Comment: opened':'Comment: closed' }}
5 <i class="el-icon-caret-bottom el-icon--right" />
6 </el-button>
7 <el-dropdown-menu slot="dropdown" class="no-padding">
8 <el-dropdown-item>
9 <el-radio-group v-model="comment_disabled" style="padding: 10px;">
10 <el-radio :label="true">
11 Close comment
12 </el-radio>
13 <el-radio :label="false">
14 Open comment
15 </el-radio>
16 </el-radio-group>
17 </el-dropdown-item>
18 </el-dropdown-menu>
19 </el-dropdown>
20 </template>
21
22 <script>
23 export default {
24 props: {
25 value: {
26 type: Boolean,
27 default: false
28 }
29 },
30 computed: {
31 comment_disabled: {
32 get() {
33 return this.value
34 },
35 set(val) {
36 this.$emit('input', val)
37 }
38 }
39 }
40 }
41 </script>
42
src/views/example/components/Dropdown/Platform.vue
File was created 1 <template>
2 <el-dropdown :hide-on-click="false" :show-timeout="100" trigger="click">
3 <el-button plain>
4 Platfroms({{ platforms.length }})
5 <i class="el-icon-caret-bottom el-icon--right" />
6 </el-button>
7 <el-dropdown-menu slot="dropdown" class="no-border">
8 <el-checkbox-group v-model="platforms" style="padding: 5px 15px;">
9 <el-checkbox v-for="item in platformsOptions" :key="item.key" :label="item.key">
10 {{ item.name }}
11 </el-checkbox>
12 </el-checkbox-group>
13 </el-dropdown-menu>
14 </el-dropdown>
15 </template>
16
17 <script>
18 export default {
19 props: {
20 value: {
21 required: true,
22 default: () => [],
23 type: Array
24 }
25 },
26 data() {
27 return {
28 platformsOptions: [
29 { key: 'a-platform', name: 'a-platform' },
30 { key: 'b-platform', name: 'b-platform' },
31 { key: 'c-platform', name: 'c-platform' }
32 ]
33 }
34 },
35 computed: {
36 platforms: {
37 get() {
38 return this.value
39 },
40 set(val) {
41 this.$emit('input', val)
42 }
43 }
44 }
45 }
46 </script>
47
src/views/example/components/Dropdown/SourceUrl.vue
File was created 1 <template>
2 <el-dropdown :show-timeout="100" trigger="click">
3 <el-button plain>
4 Link
5 <i class="el-icon-caret-bottom el-icon--right" />
6 </el-button>
7 <el-dropdown-menu slot="dropdown" class="no-padding no-border" style="width:400px">
8 <el-form-item label-width="0px" style="margin-bottom: 0px" prop="source_uri">
9 <el-input v-model="source_uri" placeholder="Please enter the content">
10 <template slot="prepend">
11 URL
12 </template>
13 </el-input>
14 </el-form-item>
15 </el-dropdown-menu>
16 </el-dropdown>
17 </template>
18
19 <script>
20 export default {
21 props: {
22 value: {
23 type: String,
24 default: ''
25 }
26 },
27 computed: {
28 source_uri: {
29 get() {
30 return this.value
31 },
32 set(val) {
33 this.$emit('input', val)
34 }
35 }
36 }
37 }
38 </script>
39
src/views/example/components/Dropdown/index.js
File was created 1 export { default as CommentDropdown } from './Comment'
2 export { default as PlatformDropdown } from './Platform'
3 export { default as SourceUrlDropdown } from './SourceUrl'
4
src/views/example/components/Warning.vue
File was created 1 <template>
2 <aside>
3 {{ $t('example.warning') }}
4 <a
5 href="https://panjiachen.github.io/vue-element-admin-site/guide/essentials/tags-view.html"
6 target="_blank"
7 >Document</a>
8 </aside>
9 </template>
10
11
src/views/example/create.vue
File was created 1 <template>
2 <article-detail :is-edit="false" />
3 </template>
4
5 <script>
6 import ArticleDetail from './components/ArticleDetail'
7
8 export default {
9 name: 'CreateArticle',
10 components: { ArticleDetail }
11 }
12 </script>
13
14
src/views/example/edit.vue
File was created 1 <template>
2 <article-detail :is-edit="true" />
3 </template>
4
5 <script>
6 import ArticleDetail from './components/ArticleDetail'
7
8 export default {
9 name: 'EditForm',
10 components: { ArticleDetail }
11 }
12 </script>
13
14
src/views/example/list.vue
File was created 1 <template>
2 <div class="app-container">
3 <el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%">
4 <el-table-column align="center" label="ID" width="80">
5 <template slot-scope="scope">
6 <span>{{ scope.row.id }}</span>
7 </template>
8 </el-table-column>
9
10 <el-table-column width="180px" align="center" label="Date">
11 <template slot-scope="scope">
12 <span>{{ scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
13 </template>
14 </el-table-column>
15
16 <el-table-column width="120px" align="center" label="Author">
17 <template slot-scope="scope">
18 <span>{{ scope.row.author }}</span>
19 </template>
20 </el-table-column>
21
22 <el-table-column width="100px" label="Importance">
23 <template slot-scope="scope">
24 <svg-icon v-for="n in +scope.row.importance" :key="n" icon-class="star" class="meta-item__icon" />
25 </template>
26 </el-table-column>
27
28 <el-table-column class-name="status-col" label="Status" width="110">
29 <template slot-scope="{row}">
30 <el-tag :type="row.status | statusFilter">
31 {{ row.status }}
32 </el-tag>
33 </template>
34 </el-table-column>
35
36 <el-table-column min-width="300px" label="Title">
37 <template slot-scope="{row}">
38 <router-link :to="'/example/edit/'+row.id" class="link-type">
39 <span>{{ row.title }}</span>
40 </router-link>
41 </template>
42 </el-table-column>
43
44 <el-table-column align="center" label="Actions" width="120">
45 <template slot-scope="scope">
46 <router-link :to="'/example/edit/'+scope.row.id">
47 <el-button type="primary" size="small" icon="el-icon-edit">
48 Edit
49 </el-button>
50 </router-link>
51 </template>
52 </el-table-column>
53 </el-table>
54
55 <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
56 </div>
57 </template>
58
59 <script>
60 import { fetchList } from '@/api/article'
61 import Pagination from '@/components/Pagination' // Secondary package based on el-pagination
62
63 export default {
64 name: 'ArticleList',
65 components: { Pagination },
66 filters: {
67 statusFilter(status) {
68 const statusMap = {
69 published: 'success',
70 draft: 'info',
71 deleted: 'danger'
72 }
73 return statusMap[status]
74 }
75 },
76 data() {
77 return {
78 list: null,
79 total: 0,
80 listLoading: true,
81 listQuery: {
82 page: 1,
83 limit: 20
84 }
85 }
86 },
87 created() {
88 this.getList()
89 },
90 methods: {
91 getList() {
92 this.listLoading = true
93 fetchList(this.listQuery).then(response => {
94 this.list = response.data.items
95 this.total = response.data.total
96 this.listLoading = false
97 })
98 }
99 }
100 }
101 </script>
102
103 <style scoped>
104 .edit-input {
105 padding-right: 100px;
106 }
107 .cancel-btn {
108 position: absolute;
109 right: 15px;
110 top: 10px;
111 }
112 </style>
113
src/views/excel/components/AutoWidthOption.vue
File was created 1 <template>
2 <div style="display:inline-block;">
3 <label class="radio-label">Cell Auto-Width: </label>
4 <el-radio-group v-model="autoWidth">
5 <el-radio :label="true" border>
6 True
7 </el-radio>
8 <el-radio :label="false" border>
9 False
10 </el-radio>
11 </el-radio-group>
12 </div>
13 </template>
14
15 <script>
16 export default {
17 props: {
18 value: {
19 type: Boolean,
20 default: true
21 }
22 },
23 computed: {
24 autoWidth: {
25 get() {
26 return this.value
27 },
28 set(val) {
29 this.$emit('input', val)
30 }
31 }
32 }
33 }
34 </script>
35
src/views/excel/components/BookTypeOption.vue
File was created 1 <template>
2 <div style="display:inline-block;">
3 <label class="radio-label">Book Type: </label>
4 <el-select v-model="bookType" style="width:120px;">
5 <el-option
6 v-for="item in options"
7 :key="item"
8 :label="item"
9 :value="item"
10 />
11 </el-select>
12 </div>
13 </template>
14
15 <script>
16 export default {
17 props: {
18 value: {
19 type: String,
20 default: 'xlsx'
21 }
22 },
23 data() {
24 return {
25 options: ['xlsx', 'csv', 'txt']
26 }
27 },
28 computed: {
29 bookType: {
30 get() {
31 return this.value
32 },
33 set(val) {
34 this.$emit('input', val)
35 }
36 }
37 }
38 }
39 </script>
40
src/views/excel/components/FilenameOption.vue
File was created 1 <template>
2 <div style="display:inline-block;">
3 <!-- $t is vue-i18n global function to translate lang -->
4 <label class="radio-label" style="padding-left:0;">Filename: </label>
5 <el-input v-model="filename" :placeholder="$t('excel.placeholder')" style="width:350px;" prefix-icon="el-icon-document" />
6 </div>
7 </template>
8
9 <script>
10 export default {
11 props: {
12 value: {
13 type: String,
14 default: ''
15 }
16 },
17 computed: {
18 filename: {
19 get() {
20 return this.value
21 },
22 set(val) {
23 this.$emit('input', val)
24 }
25 }
26 }
27 }
28 </script>
29
src/views/excel/export-excel.vue
File was created 1 <template>
2 <!-- $t is vue-i18n global function to translate lang -->
3 <div class="app-container">
4 <div>
5 <FilenameOption v-model="filename" />
6 <AutoWidthOption v-model="autoWidth" />
7 <BookTypeOption v-model="bookType" />
8 <el-button :loading="downloadLoading" style="margin:0 0 20px 20px;" type="primary" icon="el-icon-document" @click="handleDownload">
9 {{ $t('excel.export') }} Excel
10 </el-button>
11 <a href="https://panjiachen.github.io/vue-element-admin-site/feature/component/excel.html" target="_blank" style="margin-left:15px;">
12 <el-tag type="info">Documentation</el-tag>
13 </a>
14 </div>
15
16 <el-table v-loading="listLoading" :data="list" element-loading-text="Loading..." border fit highlight-current-row>
17 <el-table-column align="center" label="Id" width="95">
18 <template slot-scope="scope">
19 {{ scope.$index }}
20 </template>
21 </el-table-column>
22 <el-table-column label="Title">
23 <template slot-scope="scope">
24 {{ scope.row.title }}
25 </template>
26 </el-table-column>
27 <el-table-column label="Author" width="110" align="center">
28 <template slot-scope="scope">
29 <el-tag>{{ scope.row.author }}</el-tag>
30 </template>
31 </el-table-column>
32 <el-table-column label="Readings" width="115" align="center">
33 <template slot-scope="scope">
34 {{ scope.row.pageviews }}
35 </template>
36 </el-table-column>
37 <el-table-column align="center" label="Date" width="220">
38 <template slot-scope="scope">
39 <i class="el-icon-time" />
40 <span>{{ scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
41 </template>
42 </el-table-column>
43 </el-table>
44 </div>
45 </template>
46
47 <script>
48 import { fetchList } from '@/api/article'
49 import { parseTime } from '@/utils'
50 // options components
51 import FilenameOption from './components/FilenameOption'
52 import AutoWidthOption from './components/AutoWidthOption'
53 import BookTypeOption from './components/BookTypeOption'
54 export default {
55 name: 'ExportExcel',
56 components: { FilenameOption, AutoWidthOption, BookTypeOption },
57 data() {
58 return {
59 list: null,
60 listLoading: true,
61 downloadLoading: false,
62 filename: '',
63 autoWidth: true,
64 bookType: 'xlsx'
65 }
66 },
67 created() {
68 this.fetchData()
69 },
70 methods: {
71 fetchData() {
72 this.listLoading = true
73 fetchList().then(response => {
74 this.list = response.data.items
75 this.listLoading = false
76 })
77 },
78 handleDownload() {
79 this.downloadLoading = true
80 import('@/vendor/Export2Excel').then(excel => {
81 const tHeader = ['Id', 'Title', 'Author', 'Readings', 'Date']
82 const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
83 const list = this.list
84 const data = this.formatJson(filterVal, list)
85 excel.export_json_to_excel({
86 header: tHeader,
87 data,
88 filename: this.filename,
89 autoWidth: this.autoWidth,
90 bookType: this.bookType
91 })
92 this.downloadLoading = false
93 })
94 },
95 formatJson(filterVal, jsonData) {
96 return jsonData.map(v => filterVal.map(j => {
97 if (j === 'timestamp') {
98 return parseTime(v[j])
99 } else {
100 return v[j]
101 }
102 }))
103 }
104 }
105 }
106 </script>
107
108 <style>
109 .radio-label {
110 font-size: 14px;
111 color: #606266;
112 line-height: 40px;
113 padding: 0 12px 0 30px;
114 }
115 </style>
116
src/views/excel/merge-header.vue
File was created 1 <template>
2 <div class="app-container">
3
4 <el-button :loading="downloadLoading" style="margin-bottom:20px" type="primary" icon="el-icon-document" @click="handleDownload">Export</el-button>
5
6 <el-table
7 ref="multipleTable"
8 v-loading="listLoading"
9 :data="list"
10 element-loading-text="Loading"
11 border
12 fit
13 highlight-current-row
14 >
15 <el-table-column align="center" label="Id" width="95">
16 <template slot-scope="scope">
17 {{ scope.$index }}
18 </template>
19 </el-table-column>
20 <el-table-column label="Main Information" align="center">
21 <el-table-column label="Title">
22 <template slot-scope="scope">
23 {{ scope.row.title }}
24 </template>
25 </el-table-column>
26 <el-table-column label="Author" width="110" align="center">
27 <template slot-scope="scope">
28 <el-tag>{{ scope.row.author }}</el-tag>
29 </template>
30 </el-table-column>
31 <el-table-column label="Readings" width="115" align="center">
32 <template slot-scope="scope">
33 {{ scope.row.pageviews }}
34 </template>
35 </el-table-column>
36 </el-table-column>
37 <el-table-column align="center" label="Date" width="220">
38 <template slot-scope="scope">
39 <i class="el-icon-time" />
40 <span>{{ scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
41 </template>
42 </el-table-column>
43 </el-table>
44
45 </div>
46 </template>
47
48 <script>
49 import { fetchList } from '@/api/article'
50 import { parseTime } from '@/utils'
51
52 export default {
53 name: 'MergeHeader',
54 data() {
55 return {
56 list: null,
57 listLoading: true,
58 downloadLoading: false
59 }
60 },
61 created() {
62 this.fetchData()
63 },
64 methods: {
65 fetchData() {
66 this.listLoading = true
67 fetchList(this.listQuery).then(response => {
68 this.list = response.data.items
69 this.listLoading = false
70 })
71 },
72 handleDownload() {
73 this.downloadLoading = true
74 import('@/vendor/Export2Excel').then(excel => {
75 const multiHeader = [['Id', 'Main Information', '', '', 'Date']]
76 const header = ['', 'Title', 'Author', 'Readings', '']
77 const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
78 const list = this.list
79 const data = this.formatJson(filterVal, list)
80 const merges = ['A1:A2', 'B1:D1', 'E1:E2']
81 excel.export_json_to_excel({
82 multiHeader,
83 header,
84 merges,
85 data
86 })
87 this.downloadLoading = false
88 })
89 },
90 formatJson(filterVal, jsonData) {
91 return jsonData.map(v => filterVal.map(j => {
92 if (j === 'timestamp') {
93 return parseTime(v[j])
94 } else {
95 return v[j]
96 }
97 }))
98 }
99 }
100 }
101 </script>
102
src/views/excel/select-excel.vue
File was created 1 <template>
2 <div class="app-container">
3 <!-- $t is vue-i18n global function to translate lang -->
4 <el-input v-model="filename" :placeholder="$t('excel.placeholder')" style="width:350px;" prefix-icon="el-icon-document" />
5 <el-button :loading="downloadLoading" style="margin-bottom:20px" type="primary" icon="el-icon-document" @click="handleDownload">
6 {{ $t('excel.selectedExport') }}
7 </el-button>
8 <a href="https://panjiachen.github.io/vue-element-admin-site/feature/component/excel.html" target="_blank" style="margin-left:15px;">
9 <el-tag type="info">Documentation</el-tag>
10 </a>
11 <el-table
12 ref="multipleTable"
13 v-loading="listLoading"
14 :data="list"
15 element-loading-text="拼命加载中"
16 border
17 fit
18 highlight-current-row
19 @selection-change="handleSelectionChange"
20 >
21 <el-table-column type="selection" align="center" />
22 <el-table-column align="center" label="Id" width="95">
23 <template slot-scope="scope">
24 {{ scope.$index }}
25 </template>
26 </el-table-column>
27 <el-table-column label="Title">
28 <template slot-scope="scope">
29 {{ scope.row.title }}
30 </template>
31 </el-table-column>
32 <el-table-column label="Author" width="110" align="center">
33 <template slot-scope="scope">
34 <el-tag>{{ scope.row.author }}</el-tag>
35 </template>
36 </el-table-column>
37 <el-table-column label="Readings" width="115" align="center">
38 <template slot-scope="scope">
39 {{ scope.row.pageviews }}
40 </template>
41 </el-table-column>
42 <el-table-column align="center" label="PDate" width="220">
43 <template slot-scope="scope">
44 <i class="el-icon-time" />
45 <span>{{ scope.row.display_time }}</span>
46 </template>
47 </el-table-column>
48 </el-table>
49 </div>
50 </template>
51
52 <script>
53 import { fetchList } from '@/api/article'
54
55 export default {
56 name: 'SelectExcel',
57 data() {
58 return {
59 list: null,
60 listLoading: true,
61 multipleSelection: [],
62 downloadLoading: false,
63 filename: ''
64 }
65 },
66 created() {
67 this.fetchData()
68 },
69 methods: {
70 fetchData() {
71 this.listLoading = true
72 fetchList(this.listQuery).then(response => {
73 this.list = response.data.items
74 this.listLoading = false
75 })
76 },
77 handleSelectionChange(val) {
78 this.multipleSelection = val
79 },
80 handleDownload() {
81 if (this.multipleSelection.length) {
82 this.downloadLoading = true
83 import('@/vendor/Export2Excel').then(excel => {
84 const tHeader = ['Id', 'Title', 'Author', 'Readings', 'Date']
85 const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
86 const list = this.multipleSelection
87 const data = this.formatJson(filterVal, list)
88 excel.export_json_to_excel({
89 header: tHeader,
90 data,
91 filename: this.filename
92 })
93 this.$refs.multipleTable.clearSelection()
94 this.downloadLoading = false
95 })
96 } else {
97 this.$message({
98 message: 'Please select at least one item',
99 type: 'warning'
100 })
101 }
102 },
103 formatJson(filterVal, jsonData) {
104 return jsonData.map(v => filterVal.map(j => v[j]))
105 }
106 }
107 }
108 </script>
109
src/views/excel/upload-excel.vue
File was created 1 <template>
2 <div class="app-container">
3 <upload-excel-component :on-success="handleSuccess" :before-upload="beforeUpload" />
4 <el-table :data="tableData" border highlight-current-row style="width: 100%;margin-top:20px;">
5 <el-table-column v-for="item of tableHeader" :key="item" :prop="item" :label="item" />
6 </el-table>
7 </div>
8 </template>
9
10 <script>
11 import UploadExcelComponent from '@/components/UploadExcel/index.vue'
12
13 export default {
14 name: 'UploadExcel',
15 components: { UploadExcelComponent },
16 data() {
17 return {
18 tableData: [],
19 tableHeader: []
20 }
21 },
22 methods: {
23 beforeUpload(file) {
24 const isLt1M = file.size / 1024 / 1024 < 1
25
26 if (isLt1M) {
27 return true
28 }
29
30 this.$message({
31 message: 'Please do not upload files larger than 1m in size.',
32 type: 'warning'
33 })
34 return false
35 },
36 handleSuccess({ results, header }) {
37 this.tableData = results
38 this.tableHeader = header
39 }
40 }
41 }
42 </script>
43
src/views/form/index.vue
1 <template> File was deleted
2 <div class="app-container">
3 <el-form ref="form" :model="form" label-width="120px">
4 <el-form-item label="Activity name">
5 <el-input v-model="form.name" />
6 </el-form-item>
7 <el-form-item label="Activity zone">
8 <el-select v-model="form.region" placeholder="please select your zone">
9 <el-option label="Zone one" value="shanghai" />
10 <el-option label="Zone two" value="beijing" />
11 </el-select>
12 </el-form-item>
13 <el-form-item label="Activity time">
14 <el-col :span="11">
15 <el-date-picker
16 v-model="form.date1"
17 type="date"
18 placeholder="Pick a date"
19 style="width: 100%;"
20 />
21 </el-col>
22 <el-col :span="2" class="line">-</el-col>
23 <el-col :span="11">
24 <el-time-picker
25 v-model="form.date2"
26 type="fixed-time"
27 placeholder="Pick a time"
28 style="width: 100%;"
29 />
30 </el-col>
31 </el-form-item>
32 <el-form-item label="Instant delivery">
33 <el-switch v-model="form.delivery" />
34 </el-form-item>
35 <el-form-item label="Activity type">
36 <el-checkbox-group v-model="form.type">
37 <el-checkbox label="Online activities" name="type" />
38 <el-checkbox label="Promotion activities" name="type" />
39 <el-checkbox label="Offline activities" name="type" />
40 <el-checkbox label="Simple brand exposure" name="type" />
41 </el-checkbox-group>
42 </el-form-item>
43 <el-form-item label="Resources">
44 <el-radio-group v-model="form.resource">
45 <el-radio label="Sponsor" />
46 <el-radio label="Venue" />
47 </el-radio-group>
48 </el-form-item>
49 <el-form-item label="Activity form">
50 <el-input v-model="form.desc" type="textarea" />
51 </el-form-item>
52 <el-form-item>
53 <el-button type="primary" @click="onSubmit">Create</el-button>
54 <el-button @click="onCancel">Cancel</el-button>
55 </el-form-item>
56 </el-form>
57 </div>
58 </template>
59
60 <script>
61 export default {
62 data() {
63 return {
64 form: {
65 name: "",
66 region: "",
67 date1: "",
68 date2: "",
69 delivery: false,
70 type: [],
71 resource: "",
72 desc: ""
73 }
74 };
75 },
76 methods: {
77 onSubmit() {
78 this.$message("submit!");
79 },
80 onCancel() {
81 this.$message({
82 message: "cancel!",
83 type: "warning"
84 });
85 }
86 }
87 };
88 </script>
89
90 <style scoped>
91 .line {
92 text-align: center;
93 }
94 </style>
95
96 1 <template>
src/views/guide/index.vue
File was created 1 <template>
2 <div class="app-container">
3 <aside>
4 {{ $t('guide.description') }}
5 <a href="https://github.com/kamranahmedse/driver.js" target="_blank">driver.js.</a>
6 </aside>
7 <el-button icon="el-icon-question" type="primary" @click.prevent.stop="guide">
8 {{ $t('guide.button') }}
9 </el-button>
10 </div>
11 </template>
12
13 <script>
14 import Driver from 'driver.js' // import driver.js
15 import 'driver.js/dist/driver.min.css' // import driver.js css
16 import steps from './steps'
17
18 export default {
19 name: 'Guide',
20 data() {
21 return {
22 driver: null
23 }
24 },
25 mounted() {
26 this.driver = new Driver()
27 },
28 methods: {
29 guide() {
30 this.driver.defineSteps(steps)
31 this.driver.start()
32 }
33 }
34 }
35 </script>
36
src/views/guide/steps.js
File was created 1 const steps = [
2 {
3 element: '#hamburger-container',
4 popover: {
5 title: 'Hamburger',
6 description: 'Open && Close sidebar',
7 position: 'bottom'
8 }
9 },
10 {
11 element: '#breadcrumb-container',
12 popover: {
13 title: 'Breadcrumb',
14 description: 'Indicate the current page location',
15 position: 'bottom'
16 }
17 },
18 {
19 element: '#header-search',
20 popover: {
21 title: 'Page Search',
22 description: 'Page search, quick navigation',
23 position: 'left'
24 }
25 },
26 {
27 element: '#screenfull',
28 popover: {
29 title: 'Screenfull',
30 description: 'Set the page into fullscreen',
31 position: 'left'
32 }
33 },
34 {
35 element: '#size-select',
36 popover: {
37 title: 'Switch Size',
38 description: 'Switch the system size',
39 position: 'left'
40 }
41 },
42 {
43 element: '#tags-view-container',
44 popover: {
45 title: 'Tags view',
46 description: 'The history of the page you visited',
47 position: 'bottom'
48 },
49 padding: 0
50 }
51 ]
52
53 export default steps
54
src/views/i18n-demo/index.vue
File was created 1 <template>
2 <div>
3 <el-card class="box-card" style="margin-top:40px;">
4 <div slot="header" class="clearfix">
5 <svg-icon icon-class="international" />
6 <span style="margin-left:10px;">{{ $t('i18nView.title') }}</span>
7 </div>
8 <div>
9 <el-radio-group v-model="lang" size="small">
10 <el-radio label="zh" border>
11 简体中文
12 </el-radio>
13 <el-radio label="en" border>
14 English
15 </el-radio>
16 <el-radio label="es" border>
17 Español
18 </el-radio>
19 <el-radio label="ja" border>
20 日本語
21 </el-radio>
22 </el-radio-group>
23 <el-tag style="margin-top:15px;display:block;" type="info">
24 {{ $t('i18nView.note') }}
25 </el-tag>
26 </div>
27 </el-card>
28
29 <el-row :gutter="20" style="margin:100px 15px 50px;">
30 <el-col :span="12" :xs="24">
31 <div class="block">
32 <el-date-picker v-model="date" :placeholder="$t('i18nView.datePlaceholder')" type="date" />
33 </div>
34 <div class="block">
35 <el-select v-model="value" :placeholder="$t('i18nView.selectPlaceholder')">
36 <el-option
37 v-for="item in options"
38 :key="item.value"
39 :label="item.label"
40 :value="item.value"
41 />
42 </el-select>
43 </div>
44 <div class="block">
45 <el-button class="item-btn" size="small">
46 {{ $t('i18nView.default') }}
47 </el-button>
48 <el-button class="item-btn" size="small" type="primary">
49 {{ $t('i18nView.primary') }}
50 </el-button>
51 <el-button class="item-btn" size="small" type="success">
52 {{ $t('i18nView.success') }}
53 </el-button>
54 <el-button class="item-btn" size="small" type="info">
55 {{ $t('i18nView.info') }}
56 </el-button>
57 <el-button class="item-btn" size="small" type="warning">
58 {{ $t('i18nView.warning') }}
59 </el-button>
60 <el-button class="item-btn" size="small" type="danger">
61 {{ $t('i18nView.danger') }}
62 </el-button>
63 </div>
64 </el-col>
65 <el-col :span="12" :xs="24">
66 <el-table :data="tableData" fit highlight-current-row border style="width: 100%">
67 <el-table-column :label="$t('i18nView.tableName')" prop="name" width="100" align="center" />
68 <el-table-column :label="$t('i18nView.tableDate')" prop="date" width="120" align="center" />
69 <el-table-column :label="$t('i18nView.tableAddress')" prop="address" />
70 </el-table>
71 </el-col>
72 </el-row>
73 </div>
74 </template>
75
76 <script>
77 import local from './local'
78 const viewName = 'i18nView'
79
80 export default {
81 name: 'I18n',
82 data() {
83 return {
84 date: '',
85 tableData: [{
86 date: '2016-05-03',
87 name: 'Tom',
88 address: 'No. 189, Grove St, Los Angeles'
89 },
90 {
91 date: '2016-05-02',
92 name: 'Tom',
93 address: 'No. 189, Grove St, Los Angeles'
94 },
95 {
96 date: '2016-05-04',
97 name: 'Tom',
98 address: 'No. 189, Grove St, Los Angeles'
99 },
100 {
101 date: '2016-05-01',
102 name: 'Tom',
103 address: 'No. 189, Grove St, Los Angeles'
104 }],
105 options: [],
106 value: ''
107 }
108 },
109 computed: {
110 lang: {
111 get() {
112 return this.$store.state.app.language
113 },
114 set(lang) {
115 this.$i18n.locale = lang
116 this.$store.dispatch('app/setLanguage', lang)
117 }
118 }
119 },
120 watch: {
121 lang() {
122 this.setOptions()
123 }
124 },
125 created() {
126 if (!this.$i18n.getLocaleMessage('en')[viewName]) {
127 this.$i18n.mergeLocaleMessage('en', local.en)
128 this.$i18n.mergeLocaleMessage('zh', local.zh)
129 this.$i18n.mergeLocaleMessage('es', local.es)
130 this.$i18n.mergeLocaleMessage('ja', local.ja)
131 }
132 this.setOptions() // set default select options
133 },
134 methods: {
135 setOptions() {
136 this.options = [
137 {
138 value: '1',
139 label: this.$t('i18nView.one')
140 },
141 {
142 value: '2',
143 label: this.$t('i18nView.two')
144 },
145 {
146 value: '3',
147 label: this.$t('i18nView.three')
148 }
149 ]
150 }
151 }
152 }
153 </script>
154
155 <style scoped>
156 .box-card {
157 width: 600px;
158 max-width: 100%;
159 margin: 20px auto;
160 }
161 .item-btn{
162 margin-bottom: 15px;
163 margin-left: 0px;
164 }
165 .block {
166 padding: 25px;
167 }
168 </style>
169
src/views/i18n-demo/local.js
File was created 1
2 export default {
3 zh: {
4 i18nView: {
5 title: '切换语言',
6 note: '本项目国际化基于 vue-i18n',
7 datePlaceholder: '请选择日期',
8 selectPlaceholder: '请选择',
9 tableDate: '日期',
10 tableName: '姓名',
11 tableAddress: '地址',
12 default: '默认按钮',
13 primary: '主要按钮',
14 success: '成功按钮',
15 info: '信息按钮',
16 warning: '警告按钮',
17 danger: '危险按钮',
18 one: '一',
19 two: '二',
20 three: '三'
21 }
22 },
23 en: {
24 i18nView: {
25 title: 'Switch Language',
26 note: 'The internationalization of this project is based on vue-i18n',
27 datePlaceholder: 'Pick a day',
28 selectPlaceholder: 'Select',
29 tableDate: 'tableDate',
30 tableName: 'tableName',
31 tableAddress: 'tableAddress',
32 default: 'default:',
33 primary: 'primary',
34 success: 'success',
35 info: 'info',
36 warning: 'warning',
37 danger: 'danger',
38 one: 'One',
39 two: 'Two',
40 three: 'Three'
41 }
42 },
43 es: {
44 i18nView: {
45 title: 'Switch Language',
46 note: 'The internationalization of this project is based on vue-i18n',
47 datePlaceholder: 'Pick a day',
48 selectPlaceholder: 'Select',
49 tableDate: 'tableDate',
50 tableName: 'tableName',
51 tableAddress: 'tableAddress',
52 default: 'default:',
53 primary: 'primary',
54 success: 'success',
55 info: 'info',
56 warning: 'warning',
57 danger: 'danger',
58 one: 'One',
59 two: 'Two',
60 three: 'Three'
61 }
62 },
63 ja: {
64 i18nView: {
65 title: '言語切替',
66 note: 'vue-i18nを使っています',
67 datePlaceholder: '日時選択',
68 selectPlaceholder: '選択してください',
69 tableDate: '日時',
70 tableName: '姓名',
71 tableAddress: '住所',
72 default: 'default',
73 primary: 'primary',
74 success: 'success',
75 info: 'info',
76 warning: 'warning',
77 danger: 'danger',
78 one: '1',
79 two: '2',
80 three: '3'
81 }
82 }
83 }
84
src/views/icons/element-icons.js
File was created 1 const elementIcons = ['platform-eleme', 'eleme', 'delete-solid', 'delete', 's-tools', 'setting', 'user-solid', 'user', 'phone', 'phone-outline', 'more', 'more-outline', 'star-on', 'star-off', 's-goods', 'goods', 'warning', 'warning-outline', 'question', 'info', 'remove', 'circle-plus', 'success', 'error', 'zoom-in', 'zoom-out', 'remove-outline', 'circle-plus-outline', 'circle-check', 'circle-close', 's-help', 'help', 'minus', 'plus', 'check', 'close', 'picture', 'picture-outline', 'picture-outline-round', 'upload', 'upload2', 'download', 'camera-solid', 'camera', 'video-camera-solid', 'video-camera', 'message-solid', 'bell', 's-cooperation', 's-order', 's-platform', 's-fold', 's-unfold', 's-operation', 's-promotion', 's-home', 's-release', 's-ticket', 's-management', 's-open', 's-shop', 's-marketing', 's-flag', 's-comment', 's-finance', 's-claim', 's-custom', 's-opportunity', 's-data', 's-check', 's-grid', 'menu', 'share', 'd-caret', 'caret-left', 'caret-right', 'caret-bottom', 'caret-top', 'bottom-left', 'bottom-right', 'back', 'right', 'bottom', 'top', 'top-left', 'top-right', 'arrow-left', 'arrow-right', 'arrow-down', 'arrow-up', 'd-arrow-left', 'd-arrow-right', 'video-pause', 'video-play', 'refresh', 'refresh-right', 'refresh-left', 'finished', 'sort', 'sort-up', 'sort-down', 'rank', 'loading', 'view', 'c-scale-to-original', 'date', 'edit', 'edit-outline', 'folder', 'folder-opened', 'folder-add', 'folder-remove', 'folder-delete', 'folder-checked', 'tickets', 'document-remove', 'document-delete', 'document-copy', 'document-checked', 'document', 'document-add', 'printer', 'paperclip', 'takeaway-box', 'search', 'monitor', 'attract', 'mobile', 'scissors', 'umbrella', 'headset', 'brush', 'mouse', 'coordinate', 'magic-stick', 'reading', 'data-line', 'data-board', 'pie-chart', 'data-analysis', 'collection-tag', 'film', 'suitcase', 'suitcase-1', 'receiving', 'collection', 'files', 'notebook-1', 'notebook-2', 'toilet-paper', 'office-building', 'school', 'table-lamp', 'house', 'no-smoking', 'smoking', 'shopping-cart-full', 'shopping-cart-1', 'shopping-cart-2', 'shopping-bag-1', 'shopping-bag-2', 'sold-out', 'sell', 'present', 'box', 'bank-card', 'money', 'coin', 'wallet', 'discount', 'price-tag', 'news', 'guide', 'male', 'female', 'thumb', 'cpu', 'link', 'connection', 'open', 'turn-off', 'set-up', 'chat-round', 'chat-line-round', 'chat-square', 'chat-dot-round', 'chat-dot-square', 'chat-line-square', 'message', 'postcard', 'position', 'turn-off-microphone', 'microphone', 'close-notification', 'bangzhu', 'time', 'odometer', 'crop', 'aim', 'switch-button', 'full-screen', 'copy-document', 'mic', 'stopwatch', 'medal-1', 'medal', 'trophy', 'trophy-1', 'first-aid-kit', 'discover', 'place', 'location', 'location-outline', 'location-information', 'add-location', 'delete-location', 'map-location', 'alarm-clock', 'timer', 'watch-1', 'watch', 'lock', 'unlock', 'key', 'service', 'mobile-phone', 'bicycle', 'truck', 'ship', 'basketball', 'football', 'soccer', 'baseball', 'wind-power', 'light-rain', 'lightning', 'heavy-rain', 'sunrise', 'sunrise-1', 'sunset', 'sunny', 'cloudy', 'partly-cloudy', 'cloudy-and-sunny', 'moon', 'moon-night', 'dish', 'dish-1', 'food', 'chicken', 'fork-spoon', 'knife-fork', 'burger', 'tableware', 'sugar', 'dessert', 'ice-cream', 'hot-water', 'water-cup', 'coffee-cup', 'cold-drink', 'goblet', 'goblet-full', 'goblet-square', 'goblet-square-full', 'refrigerator', 'grape', 'watermelon', 'cherry', 'apple', 'pear', 'orange', 'coffee', 'ice-tea', 'ice-drink', 'milk-tea', 'potato-strips', 'lollipop', 'ice-cream-square', 'ice-cream-round']
2
3 export default elementIcons
4
src/views/icons/index.vue
File was created 1 <template>
2 <div class="icons-container">
3 <aside>
4 <a href="https://panjiachen.github.io/vue-element-admin-site/guide/advanced/icon.html" target="_blank">Add and use
5 </a>
6 </aside>
7 <el-tabs type="border-card">
8 <el-tab-pane label="Icons">
9 <div class="grid">
10 <div v-for="item of svgIcons" :key="item" @click="handleClipboard(generateIconCode(item),$event)">
11 <el-tooltip placement="top">
12 <div slot="content">
13 {{ generateIconCode(item) }}
14 </div>
15 <div class="icon-item">
16 <svg-icon :icon-class="item" class-name="disabled" />
17 <span>{{ item }}</span>
18 </div>
19 </el-tooltip>
20 </div>
21 </div>
22 </el-tab-pane>
23 <el-tab-pane label="Element-UI Icons">
24 <div class="grid">
25 <div v-for="item of elementIcons" :key="item" @click="handleClipboard(generateElementIconCode(item),$event)">
26 <el-tooltip placement="top">
27 <div slot="content">
28 {{ generateElementIconCode(item) }}
29 </div>
30 <div class="icon-item">
31 <i :class="'el-icon-' + item" />
32 <span>{{ item }}</span>
33 </div>
34 </el-tooltip>
35 </div>
36 </div>
37 </el-tab-pane>
38 </el-tabs>
39 </div>
40 </template>
41
42 <script>
43 import clipboard from '@/utils/clipboard'
44 import svgIcons from './svg-icons'
45 import elementIcons from './element-icons'
46
47 export default {
48 name: 'Icons',
49 data() {
50 return {
51 svgIcons,
52 elementIcons
53 }
54 },
55 methods: {
56 generateIconCode(symbol) {
57 return `<svg-icon icon-class="${symbol}" />`
58 },
59 generateElementIconCode(symbol) {
60 return `<i class="el-icon-${symbol}" />`
61 },
62 handleClipboard(text, event) {
63 clipboard(text, event)
64 }
65 }
66 }
67 </script>
68
69 <style lang="scss" scoped>
70 .icons-container {
71 margin: 10px 20px 0;
72 overflow: hidden;
73
74 .grid {
75 position: relative;
76 display: grid;
77 grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
78 }
79
80 .icon-item {
81 margin: 20px;
82 height: 85px;
83 text-align: center;
84 width: 100px;
85 float: left;
86 font-size: 30px;
87 color: #24292e;
88 cursor: pointer;
89 }
90
91 span {
92 display: block;
93 font-size: 16px;
94 margin-top: 10px;
95 }
96
97 .disabled {
98 pointer-events: none;
99 }
100 }
101 </style>
102
src/views/icons/svg-icons.js
File was created 1 const req = require.context('../../icons/svg', false, /\.svg$/)
2 const requireAll = requireContext => requireContext.keys()
3
4 const re = /\.\/(.*)\.svg/
5
6 const svgIcons = requireAll(req).map(i => {
7 return i.match(re)[1]
8 })
9
10 export default svgIcons
11
src/views/login/auth-redirect.vue
File was created 1 <script>
2 export default {
3 name: 'AuthRedirect',
4 created() {
5 const hash = window.location.search.slice(1)
6 if (window.localStorage) {
7 window.localStorage.setItem('x-admin-oauth-code', hash)
8 window.close()
9 }
10 },
11 render: function(h) {
12 return h() // avoid warning message
13 }
14 }
15 </script>
16
src/views/login/components/SocialSignin.vue
File was created 1 <template>
2 <div class="social-signup-container">
3 <div class="sign-btn" @click="wechatHandleClick('wechat')">
4 <span class="wx-svg-container"><svg-icon icon-class="wechat" class="icon" /></span>
5 WeChat
6 </div>
7 <div class="sign-btn" @click="tencentHandleClick('tencent')">
8 <span class="qq-svg-container"><svg-icon icon-class="qq" class="icon" /></span>
9 QQ
10 </div>
11 </div>
12 </template>
13
14 <script>
15 // import openWindow from '@/utils/open-window'
16
17 export default {
18 name: 'SocialSignin',
19 methods: {
20 wechatHandleClick(thirdpart) {
21 alert('ok')
22 // this.$store.commit('SET_AUTH_TYPE', thirdpart)
23 // const appid = 'xxxxx'
24 // const redirect_uri = encodeURIComponent('xxx/redirect?redirect=' + window.location.origin + '/auth-redirect')
25 // const url = 'https://open.weixin.qq.com/connect/qrconnect?appid=' + appid + '&redirect_uri=' + redirect_uri + '&response_type=code&scope=snsapi_login#wechat_redirect'
26 // openWindow(url, thirdpart, 540, 540)
27 },
28 tencentHandleClick(thirdpart) {
29 alert('ok')
30 // this.$store.commit('SET_AUTH_TYPE', thirdpart)
31 // const client_id = 'xxxxx'
32 // const redirect_uri = encodeURIComponent('xxx/redirect?redirect=' + window.location.origin + '/auth-redirect')
33 // const url = 'https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id=' + client_id + '&redirect_uri=' + redirect_uri
34 // openWindow(url, thirdpart, 540, 540)
35 }
36 }
37 }
38 </script>
39
40 <style lang="scss" scoped>
41 .social-signup-container {
42 margin: 20px 0;
43 .sign-btn {
44 display: inline-block;
45 cursor: pointer;
46 }
47 .icon {
48 color: #fff;
49 font-size: 24px;
50 margin-top: 8px;
51 }
52 .wx-svg-container,
53 .qq-svg-container {
54 display: inline-block;
55 width: 40px;
56 height: 40px;
57 line-height: 40px;
58 text-align: center;
59 padding-top: 1px;
60 border-radius: 4px;
61 margin-bottom: 20px;
62 margin-right: 5px;
63 }
64 .wx-svg-container {
65 background-color: #24da70;
66 }
67 .qq-svg-container {
68 background-color: #6BA2D6;
69 margin-left: 50px;
70 }
71 }
72 </style>
73
src/views/login/index.vue
1 <template> 1 <template>
2 <div class="login-container"> 2 <div class="login-container">
3 <el-form 3 <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="on" label-position="left">
4 ref="loginForm" 4
5 :model="loginForm"
6 :rules="loginRules"
7 class="login-form"
8 auto-complete="on"
9 label-position="left"
10 >
11 <div class="title-container"> 5 <div class="title-container">
12 <h3 class="title">鱼皮系统</h3> 6 <h3 class="title">
7 {{ $t('login.title') }}
8 </h3>
9 <lang-select class="set-language" />
13 </div> 10 </div>
14 11
15 <el-form-item prop="username"> 12 <el-form-item prop="username">
16 <span class="svg-container"> 13 <span class="svg-container">
17 <svg-icon icon-class="user" /> 14 <svg-icon icon-class="user" />
18 </span> 15 </span>
19 <el-input 16 <el-input
20 ref="username" 17 ref="username"
21 v-model="loginForm.username" 18 v-model="loginForm.username"
22 placeholder="Username" 19 :placeholder="$t('login.username')"
23 name="username" 20 name="username"
24 type="text" 21 type="text"
25 tabindex="1" 22 tabindex="1"
26 auto-complete="on" 23 autocomplete="on"
27 /> 24 />
28 </el-form-item> 25 </el-form-item>
29 26
30 <el-form-item prop="password"> 27 <el-tooltip v-model="capsTooltip" content="Caps lock is On" placement="right" manual>
31 <span class="svg-container"> 28 <el-form-item prop="password">
32 <svg-icon icon-class="password" /> 29 <span class="svg-container">
33 </span> 30 <svg-icon icon-class="password" />
34 <el-input 31 </span>
35 :key="passwordType" 32 <el-input
36 ref="password" 33 :key="passwordType"
37 v-model="loginForm.password" 34 ref="password"
38 :type="passwordType" 35 v-model="loginForm.password"
39 placeholder="Password" 36 :type="passwordType"
40 name="password" 37 :placeholder="$t('login.password')"
41 tabindex="2" 38 name="password"
42 auto-complete="on" 39 tabindex="2"
43 @keyup.enter.native="handleLogin" 40 autocomplete="on"
44 /> 41 @keyup.native="checkCapslock"
45 <span class="show-pwd" @click="showPwd"> 42 @blur="capsTooltip = false"
46 <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" /> 43 @keyup.enter.native="handleLogin"
47 </span> 44 />
48 </el-form-item> 45 <span class="show-pwd" @click="showPwd">
49 <!-- <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">reg</el-button> --> 46 <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
50 <el-button 47 </span>
51 :loading="loading" 48 </el-form-item>
52 type="primary" 49 </el-tooltip>
53 style="width:100%;margin-bottom:30px;" 50
54 @click.native.prevent="handleLogin" 51 <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">
55 >Login</el-button> 52 {{ $t('login.logIn') }}
53 </el-button>
56 54
57 <div class="tips"> 55 <div style="position:relative">
58 <span style="margin-right:20px;">username: admin</span> 56 <div class="tips">
59 <span>password: any</span> 57 <span>{{ $t('login.username') }} : admin</span>
58 <span>{{ $t('login.password') }} : {{ $t('login.any') }}</span>
59 </div>
60 <div class="tips">
61 <span style="margin-right:18px;">
62 {{ $t('login.username') }} : editor
63 </span>
64 <span>{{ $t('login.password') }} : {{ $t('login.any') }}</span>
65 </div>
66
67 <el-button class="thirdparty-button" type="primary" @click="showDialog=true">
68 {{ $t('login.thirdparty') }}
69 </el-button>
60 </div> 70 </div>
61 </el-form> 71 </el-form>
72
73 <el-dialog :title="$t('login.thirdparty')" :visible.sync="showDialog">
74 {{ $t('login.thirdpartyTips') }}
75 <br>
76 <br>
77 <br>
78 <social-sign />
79 </el-dialog>
62 </div> 80 </div>
63 </template> 81 </template>
64 82
65 <script> 83 <script>
66 import { validUsername } from "@/utils/validate"; 84 import { validUsername } from '@/utils/validate'
85 import LangSelect from '@/components/LangSelect'
86 import SocialSign from './components/SocialSignin'
67 87
68 export default { 88 export default {
69 name: "Login", 89 name: 'Login',
90 components: { LangSelect, SocialSign },
70 data() { 91 data() {
71 const validateUsername = (rule, value, callback) => { 92 const validateUsername = (rule, value, callback) => {
72 if (!validUsername(value)) { 93 if (!validUsername(value)) {
73 callback(new Error("Please enter the correct user name")); 94 callback(new Error('Please enter the correct user name'))
74 } else { 95 } else {
75 callback(); 96 callback()
76 } 97 }
77 }; 98 }
78 const validatePassword = (rule, value, callback) => { 99 const validatePassword = (rule, value, callback) => {
79 if (value.length < 6) { 100 if (value.length < 6) {
80 callback(new Error("The password can not be less than 6 digits")); 101 callback(new Error('The password can not be less than 6 digits'))
81 } else { 102 } else {
82 callback(); 103 callback()
83 } 104 }
84 }; 105 }
85 return { 106 return {
86 loginForm: { 107 loginForm: {
87 username: "admin", 108 username: 'admin',
88 password: "111111" 109 password: '111111'
89 }, 110 },
90 loginRules: { 111 loginRules: {
91 username: [ 112 username: [{ required: true, trigger: 'blur', validator: validateUsername }],
92 { required: true, trigger: "blur", validator: validateUsername } 113 password: [{ required: true, trigger: 'blur', validator: validatePassword }]
93 ],
94 password: [
95 { required: true, trigger: "blur", validator: validatePassword }
96 ]
97 }, 114 },
115 passwordType: 'password',
116 capsTooltip: false,
98 loading: false, 117 loading: false,
99 passwordType: "password", 118 showDialog: false,
100 redirect: undefined 119 redirect: undefined,
101 }; 120 otherQuery: {}
121 }
102 }, 122 },
103 watch: { 123 watch: {
104 $route: { 124 $route: {
105 handler: function(route) { 125 handler: function(route) {
106 this.redirect = route.query && route.query.redirect; 126 const query = route.query
127 if (query) {
128 this.redirect = query.redirect
129 this.otherQuery = this.getOtherQuery(query)
130 }
107 }, 131 },
108 immediate: true 132 immediate: true
109 } 133 }
110 }, 134 },
135 created() {
136 // window.addEventListener('storage', this.afterQRScan)
137 },
138 mounted() {
139 if (this.loginForm.username === '') {
140 this.$refs.username.focus()
141 } else if (this.loginForm.password === '') {
142 this.$refs.password.focus()
143 }
144 },
145 destroyed() {
146 // window.removeEventListener('storage', this.afterQRScan)
147 },
111 methods: { 148 methods: {
149 checkCapslock(e) {
150 const { key } = e
151 this.capsTooltip = key && key.length === 1 && (key >= 'A' && key <= 'Z')
152 },
112 showPwd() { 153 showPwd() {
113 if (this.passwordType === "password") { 154 if (this.passwordType === 'password') {
114 this.passwordType = ""; 155 this.passwordType = ''
115 } else { 156 } else {
116 this.passwordType = "password"; 157 this.passwordType = 'password'
117 } 158 }
118 this.$nextTick(() => { 159 this.$nextTick(() => {
119 this.$refs.password.focus(); 160 this.$refs.password.focus()
120 }); 161 })
121 }, 162 },
122 handleLogin() { 163 handleLogin() {
123 this.$refs.loginForm.validate(valid => { 164 this.$refs.loginForm.validate(valid => {
124 if (valid) { 165 if (valid) {
125 this.loading = true; 166 this.loading = true
126 this.$store 167 this.$store.dispatch('user/login', this.loginForm)
127 .dispatch("user/login", this.loginForm)
128 .then(() => { 168 .then(() => {
129 this.$router.push({ path: this.redirect || "/" }); 169 this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
130 this.loading = false; 170 this.loading = false
131 console.log('this.redirect', this.$router); 171 })
172 .catch(() => {
173 this.loading = false
132 }) 174 })
133 .catch(res => {
134 console.log("res error------------>", res);
135 this.loading = false;
136 });
137 } else { 175 } else {
138 console.log("error submit!!"); 176 console.log('error submit!!')
139 return false; 177 return false
140 } 178 }
141 }); 179 })
180 },
181 getOtherQuery(query) {
182 return Object.keys(query).reduce((acc, cur) => {
183 if (cur !== 'redirect') {
184 acc[cur] = query[cur]
185 }
186 return acc
187 }, {})
142 } 188 }
189 // afterQRScan() {
190 // if (e.key === 'x-admin-oauth-code') {
191 // const code = getQueryObject(e.newValue)
192 // const codeMap = {
193 // wechat: 'code',
194 // tencent: 'code'
195 // }
196 // const type = codeMap[this.auth_type]
197 // const codeName = code[type]
198 // if (codeName) {
199 // this.$store.dispatch('LoginByThirdparty', codeName).then(() => {
200 // this.$router.push({ path: this.redirect || '/' })
201 // })
202 // } else {
203 // alert('第三方登录失败')
204 // }
205 // }
206 // }
143 } 207 }
144 }; 208 }
145 </script> 209 </script>
146 210
147 <style lang="scss"> 211 <style lang="scss">
148 /* 修复input 背景不协调 和光标变色 */ 212 /* 修复input 背景不协调 和光标变色 */
149 /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */ 213 /* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */
150 214
151 $bg: #283443; 215 $bg:#283443;
152 $light_gray: #fff; 216 $light_gray:#fff;
153 $cursor: #fff; 217 $cursor: #fff;
154 218
155 @supports (-webkit-mask: none) and (not (cater-color: $cursor)) { 219 @supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
156 .login-container .el-input input { 220 .login-container .el-input input {
157 color: $cursor; 221 color: $cursor;
158 } 222 }
159 } 223 }
160 224
161 /* reset element-ui css */ 225 /* reset element-ui css */
162 .login-container { 226 .login-container {
163 .el-input { 227 .el-input {
164 display: inline-block; 228 display: inline-block;
165 height: 47px; 229 height: 47px;
166 width: 85%; 230 width: 85%;
167 231
168 input { 232 input {
169 background: transparent; 233 background: transparent;
170 border: 0px; 234 border: 0px;
171 -webkit-appearance: none; 235 -webkit-appearance: none;
172 border-radius: 0px; 236 border-radius: 0px;
173 padding: 12px 5px 12px 15px; 237 padding: 12px 5px 12px 15px;
174 color: $light_gray; 238 color: $light_gray;
175 height: 47px; 239 height: 47px;
176 caret-color: $cursor; 240 caret-color: $cursor;
177 241
178 &:-webkit-autofill { 242 &:-webkit-autofill {
179 box-shadow: 0 0 0px 1000px $bg inset !important; 243 box-shadow: 0 0 0px 1000px $bg inset !important;
180 -webkit-text-fill-color: $cursor !important; 244 -webkit-text-fill-color: $cursor !important;
181 } 245 }
182 } 246 }
183 } 247 }
184 248
185 .el-form-item { 249 .el-form-item {
186 border: 1px solid rgba(255, 255, 255, 0.1); 250 border: 1px solid rgba(255, 255, 255, 0.1);
187 background: rgba(0, 0, 0, 0.1); 251 background: rgba(0, 0, 0, 0.1);
188 border-radius: 5px; 252 border-radius: 5px;
189 color: #454545; 253 color: #454545;
190 } 254 }
191 } 255 }
192 </style> 256 </style>
193 257
194 <style lang="scss" scoped> 258 <style lang="scss" scoped>
195 $bg: #2d3a4b; 259 $bg:#2d3a4b;
196 $dark_gray: #889aa4; 260 $dark_gray:#889aa4;
197 $light_gray: #eee; 261 $light_gray:#eee;
198 262
199 .login-container { 263 .login-container {
200 min-height: 100%; 264 min-height: 100%;
201 width: 100%; 265 width: 100%;
202 background-color: $bg; 266 background-color: $bg;
203 overflow: hidden; 267 overflow: hidden;
204 268
205 .login-form { 269 .login-form {
206 position: relative; 270 position: relative;
207 width: 520px; 271 width: 520px;
208 max-width: 100%; 272 max-width: 100%;
209 padding: 160px 35px 0; 273 padding: 160px 35px 0;
210 margin: 0 auto; 274 margin: 0 auto;
211 overflow: hidden; 275 overflow: hidden;
212 } 276 }
213 277
214 .tips { 278 .tips {
215 font-size: 14px; 279 font-size: 14px;
216 color: #fff; 280 color: #fff;
217 margin-bottom: 10px; 281 margin-bottom: 10px;
218 282
219 span { 283 span {
220 &:first-of-type { 284 &:first-of-type {
221 margin-right: 16px; 285 margin-right: 16px;
222 } 286 }
223 } 287 }
224 } 288 }
225 289
226 .svg-container { 290 .svg-container {
227 padding: 6px 5px 6px 15px; 291 padding: 6px 5px 6px 15px;
228 color: $dark_gray; 292 color: $dark_gray;
229 vertical-align: middle; 293 vertical-align: middle;
230 width: 30px; 294 width: 30px;
231 display: inline-block; 295 display: inline-block;
232 } 296 }
233 297
234 .title-container { 298 .title-container {
235 position: relative; 299 position: relative;
236 300
237 .title { 301 .title {
238 font-size: 26px; 302 font-size: 26px;
239 color: $light_gray; 303 color: $light_gray;
240 margin: 0px auto 40px auto; 304 margin: 0px auto 40px auto;
241 text-align: center; 305 text-align: center;
242 font-weight: bold; 306 font-weight: bold;
243 } 307 }
308
309 .set-language {
310 color: #fff;
311 position: absolute;
312 top: 3px;
313 font-size: 18px;
314 right: 0px;
315 cursor: pointer;
316 }
244 } 317 }
245 318
246 .show-pwd { 319 .show-pwd {
247 position: absolute; 320 position: absolute;
248 right: 10px; 321 right: 10px;
249 top: 7px; 322 top: 7px;
250 font-size: 16px; 323 font-size: 16px;
251 color: $dark_gray; 324 color: $dark_gray;
252 cursor: pointer; 325 cursor: pointer;
253 user-select: none; 326 user-select: none;
254 } 327 }
src/views/nested/menu1/index.vue 100644 → 100755
1 <template> 1 <template>
2 <div style="padding:30px;"> 2 <div style="padding:30px;">
3 <el-alert :closable="false" title="menu 1"> 3 <el-alert :closable="false" title="menu 1">
4 <router-view /> 4 <router-view />
5 </el-alert> 5 </el-alert>
6 </div> 6 </div>
7 </template> 7 </template>
8 8
src/views/nested/menu1/menu1-1/index.vue
1 <template> 1 <template>
2 <div style="padding:30px;"> 2 <div style="padding:30px;">
3 <el-alert :closable="false" title="menu 1-1" type="success"> 3 <el-alert :closable="false" title="menu 1-1" type="success">
4 <router-view /> 4 <router-view />
5 </el-alert> 5 </el-alert>
6 </div> 6 </div>
7 </template> 7 </template>
8 <template functional>
9 <div style="padding:30px;">
10 <el-alert :closable="false" title="menu 1-2-1" type="warning" />
11 </div>
12 </template>
src/views/nested/menu1/menu1-2/index.vue 100644 → 100755
1 <template> 1 <template>
2 <div style="padding:30px;"> 2 <div style="padding:30px;">
3 <el-alert :closable="false" title="menu 1-2" type="success"> 3 <el-alert :closable="false" title="menu 1-2" type="success">
4 <router-view /> 4 <router-view />
5 </el-alert> 5 </el-alert>
6 </div> 6 </div>
7 </template> 7 </template>
8 8
src/views/nested/menu1/menu1-2/menu1-2-1/index.vue 100644 → 100755
1 <template functional> 1 <template functional>
2 <div style="padding:30px;"> 2 <div style="padding:30px;">
3 <el-alert :closable="false" title="menu 1-2-1" type="warning" /> 3 <el-alert :closable="false" title="menu 1-2-1" type="warning" />
4 </div> 4 </div>
5 </template> 5 </template>
6 6
src/views/nested/menu1/menu1-2/menu1-2-2/index.vue 100644 → 100755
1 <template functional> 1 <template functional>
2 <div style="padding:30px;"> 2 <div style="padding:30px;">
3 <el-alert :closable="false" title="menu 1-2-2" type="warning" /> 3 <el-alert :closable="false" title="menu 1-2-2" type="warning" />
4 </div> 4 </div>
5 </template> 5 </template>
6 6
src/views/nested/menu1/menu1-3/index.vue 100644 → 100755
1 <template functional> 1 <template functional>
2 <div style="padding:30px;"> 2 <div style="padding:30px;">
3 <el-alert :closable="false" title="menu 1-3" type="success" /> 3 <el-alert :closable="false" title="menu 1-3" type="success" />
4 </div> 4 </div>
5 </template> 5 </template>
6 6
src/views/nested/menu2/index.vue 100644 → 100755
1 <template> 1 <template>
2 <div style="padding:30px;"> 2 <div style="padding:30px;">
3 <el-alert :closable="false" title="menu 2" /> 3 <el-alert :closable="false" title="menu 2" />
4 </div> 4 </div>
5 </template> 5 </template>
6 6
src/views/pdf/content.js
File was created 1 const title = 'Plans for the Next Iteration of Vue.js'
2
3 const content = `<p>Last week at<a href="https://vuejs.london/summary" rel="nofollow">Vue.js London</a>I gave a brief sneak peek of what’s coming in the next major version of Vue. This post provides an in-depth overview of the plan.</p>
4 <p><img class=" wscnph" src="https://wpimg.wallstcn.com/b8a1d7be-0b73-41b8-be8c-7c01c93cab66.png" data-wscntype="image" data-wscnh="742" data-wscnw="692" /></p>
5 <h3>Why a new majorversion?</h3>
6 <p>Vue 2.0 was released<a href="https://medium.com/the-vue-point/vue-2-0-is-here-ef1f26acf4b8" rel="nofollow">exactly two years ago</a>(how time flies!). During this period, the core has remained backwards compatible with five minor releases. We’ve accumulated a number of ideas that would bring improvements, but they were held off because they would result in breaking changes. At the same time, the JavaScript ecosystem and the language itself has been evolving rapidly. There are greatly improved tools that could enhance our workflow, and many new language features that could unlock simpler, more complete, and more efficient solutions to the problems Vue is trying to solve. What’s more exciting is that we are seeing ES2015 support becoming a baseline for all major evergreen browsers. Vue 3.0 aims to leverage these new language features to make Vue core smaller, faster, and more powerful.</p>
7 <p>Vue 3.0 is currently in prototyping phase, and we have already implemented a runtime close to feature-parity with 2.x.<strong>Many of the items listed below are either already implemented, or confirmed to be feasible. Ones that are not yet implemented or still in exploration phase are marked with a *.</strong></p>
8 <h3>The Details</h3>
9 <h4>High-Level APIChanges</h4>
10 <blockquote>TL;DR: Everything except render function API and scoped-slots syntax will either remain the same or can be made 2.x compatible via a compatibility build.</blockquote>
11 <p>Since it’s a new major, there is going to be some breaking changes. However, we take backwards compatibility seriously, so we want to start communicating these changes as soon as possible. Here’s the currently planned public API changes:</p>
12 <ul><li>Template syntax will remain 99% the same. There may be small tweaks in scoped slots syntax, but other than that we have no plans to change anything else for templates.</li><li>3.0 will support class-based components natively, with the aim to provide an API that is pleasant to use in native ES2015 without requiring any transpilation or stage-x features. Most current options will have a reasonable mapping in the class-based API. Stage-x features such as class fields and decorators can still be used optionally to enhance the authoring experience. In addition, the API is designed with TypeScript type inference in mind. The 3.x codebase will itself be written in TypeScript, and providing improved TypeScript support. (That said, usage of TypeScript in an application is still entirely optional.)</li><li>The 2.x object-based component format will still be supported by internally transforming the object to a corresponding class.</li><li>Mixins will still be supported.*</li><li>Top level APIs will likely receive an overhaul to avoid globally mutating the Vue runtime when installing plugins. Instead, plugins will be applied and scoped to a component tree. This will make it easier to test components that rely on specific plugins, and also make it possible to mount multiple Vue applications on the same page with different plugins, but using the same Vue runtime.*</li><li>Functional components can finally be plain functions —however, async components will now need to be explicitly created via a helper function.</li><li>The part that will receive the most changes is the Virtual DOM format used in render functions. We are currently collecting feedback from major library authors and will be sharing more details as we are more confident of the changes, but as long as you don’t heavily rely on hand-written (non-JSX) render functions in your app, upgrading should be a reasonably straightforward process.</li></ul>
13 <h4>Source Code Architecture</h4>
14 <blockquote>TL;DR: better decoupled internal modules, TypeScript, and a codebase that is easier to contribute to.</blockquote>
15 <p>We are re-writing 3.0 from the ground up for a cleaner and more maintainable architecture, in particular trying to make it easier to contribute to. We are breaking some internal functionalities into individual packages in order to isolate the scope of complexity. For example, the observer module will become its own package, with its own public API and tests. Note this does not affect framework-level API— you will not have to manually import individual bits from multiple packages in order to use Vue. Instead, the final Vue package is assembled using these internal packages.</p>
16 <p>The codebase is also now written in TypeScript. Although this will make proficiency in TypeScript a pre-requisite for contributing to the new codebase, we believe the type information and IDE support will actually make it easier for a new contributor to make meaningful contributions.</p>
17 <p>Decoupling the observer and scheduler into separate packages also allows us to easily experiment with alternative implementations of these parts. For example, we can implement an IE11 compatible observer implementation with the same API, or an alternative scheduler that leverages<code>requestIdleCallback</code>to yield to the browser during long updates.*</p>
18 <p><img class=" wscnph" src="https://wpimg.wallstcn.com/4d0b5fb2-d7f9-48fd-8f1b-03362b534dd9.png" data-wscntype="image" data-wscnh="716" data-wscnw="460" /></p>
19 <h4>Observation Mechanism</h4>
20 <blockquote>TL;DR: more complete, precise, efficient and debuggable reactivity tracking &amp; API for creating observables.</blockquote>
21 <p>3.0 will ship with a Proxy-based observer implementation that provides reactivity tracking with full language coverage. This eliminates a number of limitations of Vue 2’s current implementation based on<code>Object.defineProperty</code>:</p>
22 <p>The new observer also features the following:</p>
23 <p>Easily understand why a component is re-rendering</p>
24 <p><img class=" wscnph" src="https://wpimg.wallstcn.com/a0c9d811-1ef9-4628-8976-f7c1aaa66da0.png" data-wscntype="image" data-wscnh="540" data-wscnw="789" /></p>
25 <h4>Other Runtime Improvements</h4>
26 <blockquote>TL;DR: smaller, faster, tree-shakable features, fragments &amp; portals, custom renderer API.</blockquote>
27 <h4>Compiler Improvements*</h4>
28 <blockquote>TL;DR: tree-shaking friendly output, more AOT optimizations, parser with better error info and source map support.</blockquote>
29 <h4>IE11 Support*</h4>
30 <blockquote>TL;DR: it will be supported, but in a separate build with the same reactivity limitations of Vue 2.x.</blockquote>
31 <p>The new codebase currently targets evergreen browsers only and assumes baseline native ES2015 support. But alas, we know a lot of our users still need to support IE11 for the foreseeable future. Most of the ES2015 features used can be transpiled / polyfilled for IE11, with the exception for Proxies. Our plan is to implement an alternative observer with the same API, but using the good old ES5<code>Object.defineProperty</code>API. A separate build of Vue 3.x will be distributed using this observer implementation. However, this build will be subject to the same change detection caveats of Vue 2.x and thus not fully compatible with the “modern” build of 3.x. We are aware that this imposes some inconvenience for library authors as they will need to be aware of compatibility for two different builds, but we will make sure to provide clear guidelines on this when we reach that stage.</p>
32 <h3>How Do We GetThere</h3>
33 <p>First of all, although we are announcing it today, we do not have a definitive timeline yet. What we do know at the moment is the steps we will be taking to get there:</p>
34 <h4>1. Internal Feedback for the Runtime Prototype</h4>
35 <p>This is the phase we are in right now. Currently, we already have a working runtime prototype that includes the new observer, Virtual DOM and component implementation. We have invited a group of authors of influential community projects to provide feedback for the internal changes, and would like to make sure they are comfortable with the changes before moving forward. We want to ensure that important libraries in the ecosystem will be ready at the same time when we release 3.0, so that users relying on those projects can upgrade easily.</p>
36 <h4>2. Public Feedback viaRFCs</h4>
37 <p>Once we gain a certain level of confidence in the new design, for each breaking change we will be opening a dedicated RFC issue which includes:</p>
38 <p>We will anticipate public feedback from the wider community to help us consolidate these ideas.</p>
39 <h4>3. Introduce Compatible Features in 2.x &amp;2.x-next</h4>
40 <p>We are not forgetting about 2.x! In fact, we plan to use 2.x to progressively accustom users to the new changes. We will be gradually introducing confirmed API changes into 2.x via opt-in adaptors, and 2.x-next will allow users to try out the new Proxy-based observer.</p>
41 <p>The last minor release in 2.x will become LTS and continue to receive bug and security fixes for 18 months when 3.0 is released.</p>
42 <h4>4. AlphaPhase</h4>
43 <p>Next, we will finish up the compiler and server-side rendering parts of 3.0 and start making alpha releases. These will mostly be for stability testing purposes in small greenfield apps.</p>
44 <h4>5. BetaPhase</h4>
45 <p>During beta phase, our main goal is updating support libraries and tools like Vue Router, Vuex, Vue CLI, Vue DevTools and make sure they work smoothly with the new core. We will also be working with major library authors from the community to help them get ready for 3.0.</p>
46 <h4>6. RCPhase</h4>
47 <p>Once we consider the API and codebase stable, we will enter RC phase with API freeze. During this phase we will also work on a “compat build”: a build of 3.0 that includes compatibility layers for 2.x API. This build will also ship with a flag you can turn on to emit deprecation warnings for 2.x API usage in your app. The compat build can be used as a guide to upgrade your app to 3.0.</p>
48 <h4>7. IE11build</h4>
49 <p>The last task before the final release will be the IE11 compatibility build as mentioned above.</p>
50 <h4>8. FinalRelease</h4>
51 <p>In all honesty, we don’t know when this will happen yet, but likely in 2019. Again, we care more about shipping something that is solid and stable rather than hitting specific dates. There is a lot of work to be done, but we are excited for what’s coming next!</p>`
52
53 const data = {
54 title,
55 content
56 }
57
58 export default data
59
src/views/pdf/download.vue
File was created 1 <template>
2 <div v-loading.fullscreen.lock="fullscreenLoading" class="main-article" element-loading-text="Efforts to generate PDF">
3 <div class="article__heading">
4 <div class="article__heading__title">
5 {{ article.title }}
6 </div>
7 </div>
8 <div style="color: #ccc;">
9 This article is from Evan You on <a target="_blank" href="https://medium.com/the-vue-point/plans-for-the-next-iteration-of-vue-js-777ffea6fabf">medium</a>
10 </div>
11 <div ref="content" class="node-article-content" v-html="article.content" />
12 </div>
13 </template>
14
15 <script>
16
17 export default {
18 data() {
19 return {
20 article: '',
21 fullscreenLoading: true
22 }
23 },
24 mounted() {
25 this.fetchData()
26 },
27 methods: {
28 fetchData() {
29 import('./content.js').then(data => {
30 const { title } = data.default
31 document.title = title
32 this.article = data.default
33 setTimeout(() => {
34 this.fullscreenLoading = false
35 this.$nextTick(() => {
36 window.print()
37 })
38 }, 3000)
39 })
40 }
41 }
42 }
43 </script>
44
45 <style lang="scss">
46 @mixin clearfix {
47 &:before {
48 display: table;
49 content: '';
50 clear: both;
51 }
52
53 &:after {
54 display: table;
55 content: '';
56 clear: both;
57 }
58 }
59
60 .main-article {
61 padding: 20px;
62 margin: 0 auto;
63 display: block;
64 width: 740px;
65 background: #fff;
66 }
67
68 .article__heading {
69 position: relative;
70 padding: 0 0 20px;
71 overflow: hidden;
72 }
73
74 .article__heading__title {
75 display: block;
76 display: -webkit-box;
77 -webkit-box-orient: vertical;
78 -webkit-line-clamp: 2;
79 line-clamp: 2;
80 word-wrap: break-word;
81 overflow-wrap: break-word;
82 font-size: 32px;
83 line-height: 48px;
84 font-weight: 600;
85 color: #333;
86 overflow: hidden;
87 }
88
89 .node-article-content {
90 margin: 20px 0 0;
91 @include clearfix;
92 font-size: 16px;
93 color: #333;
94 letter-spacing: 0.5px;
95 line-height: 28px;
96 margin-bottom: 30px;
97 font-family: medium-content-serif-font, Georgia, Cambria, "Times New Roman", Times, serif;
98
99 &> :last-child {
100 margin-bottom: 0;
101 }
102
103 b,
104 strong {
105 font-weight: inherit;
106 font-weight: bolder;
107 }
108
109 img {
110 max-width: 100%;
111 display: block;
112 margin: 0 auto;
113 }
114
115 p {
116 font-weight: 400;
117 font-style: normal;
118 font-size: 21px;
119 line-height: 1.58;
120 letter-spacing: -.003em;
121
122 }
123
124 ul {
125 margin-bottom: 30px;
126 }
127
128 li {
129 --x-height-multiplier: 0.375;
130 --baseline-multiplier: 0.17;
131
132 letter-spacing: .01rem;
133 font-weight: 400;
134 font-style: normal;
135 font-size: 21px;
136 line-height: 1.58;
137 letter-spacing: -.003em;
138 margin-left: 30px;
139 margin-bottom: 14px;
140 }
141
142 a {
143 text-decoration: none;
144 background-repeat: repeat-x;
145 background-image: linear-gradient(to right, rgba(0, 0, 0, .84) 100%, rgba(0, 0, 0, 0) 0);
146 background-size: 1px 1px;
147 background-position: 0 calc(1em + 1px);
148 padding: 0 6px;
149 }
150
151 code {
152 background: rgba(0, 0, 0, .05);
153 padding: 3px 4px;
154 margin: 0 2px;
155 font-size: 16px;
156 display: inline-block;
157 }
158
159 img {
160 border: 0;
161 }
162
163 /* 解决 IE6-7 图片缩放锯齿问题 */
164 img {
165 -ms-interpolation-mode: bicubic;
166 }
167
168 blockquote {
169 --x-height-multiplier: 0.375;
170 --baseline-multiplier: 0.17;
171 font-family: medium-content-serif-font, Georgia, Cambria, "Times New Roman", Times, serif;
172 letter-spacing: .01rem;
173 font-weight: 400;
174 font-style: italic;
175 font-size: 21px;
176 line-height: 1.58;
177 letter-spacing: -.003em;
178 border-left: 3px solid rgba(0, 0, 0, .84);
179 padding-left: 20px;
180 margin-left: -23px;
181 padding-bottom: 2px;
182 }
183
184 a {
185 text-decoration: none;
186 }
187
188 h2,
189 h3,
190 h4 {
191 font-size: 34px;
192 line-height: 1.15;
193 letter-spacing: -.015em;
194 margin: 53px 0 0;
195 }
196
197 h4 {
198 font-size: 26px;
199 }
200 }
201 </style>
202
src/views/pdf/index.vue
File was created 1 <template>
2 <div class="app-container">
3 <aside style="margin-top:15px;">{{ $t('pdf.tips') }}</aside>
4 <router-link target="_blank" to="/pdf/download">
5 <el-button type="primary">
6 Click to download PDF
7 </el-button>
8 </router-link>
9 </div>
10 </template>
11
12
src/views/permission/components/SwitchRoles.vue
File was created 1 <template>
2 <div>
3 <div style="margin-bottom:15px;">
4 {{ $t('permission.roles') }}: {{ roles }}
5 </div>
6 {{ $t('permission.switchRoles') }}:
7 <el-radio-group v-model="switchRoles">
8 <el-radio-button label="editor" />
9 <el-radio-button label="admin" />
10 </el-radio-group>
11 </div>
12 </template>
13
14 <script>
15 export default {
16 computed: {
17 roles() {
18 return this.$store.getters.roles
19 },
20 switchRoles: {
21 get() {
22 return this.roles[0]
23 },
24 set(val) {
25 this.$store.dispatch('user/changeRoles', val).then(() => {
26 this.$emit('change')
27 })
28 }
29 }
30 }
31 }
32 </script>
33
src/views/permission/directive.vue
File was created 1 <template>
2 <div class="app-container">
3 <switch-roles @change="handleRolesChange" />
4 <div :key="key" style="margin-top:30px;">
5 <div>
6 <span v-permission="['admin']" class="permission-alert">
7 Only
8 <el-tag class="permission-tag" size="small">admin</el-tag> can see this
9 </span>
10 <el-tag v-permission="['admin']" class="permission-sourceCode" type="info">
11 v-permission="['admin']"
12 </el-tag>
13 </div>
14
15 <div>
16 <span v-permission="['editor']" class="permission-alert">
17 Only
18 <el-tag class="permission-tag" size="small">editor</el-tag> can see this
19 </span>
20 <el-tag v-permission="['editor']" class="permission-sourceCode" type="info">
21 v-permission="['editor']"
22 </el-tag>
23 </div>
24
25 <div>
26 <span v-permission="['admin','editor']" class="permission-alert">
27 Both
28 <el-tag class="permission-tag" size="small">admin</el-tag> and
29 <el-tag class="permission-tag" size="small">editor</el-tag> can see this
30 </span>
31 <el-tag v-permission="['admin','editor']" class="permission-sourceCode" type="info">
32 v-permission="['admin','editor']"
33 </el-tag>
34 </div>
35 </div>
36
37 <div :key="'checkPermission'+key" style="margin-top:60px;">
38 <aside>
39 {{ $t('permission.tips') }}
40 <br> e.g.
41 </aside>
42
43 <el-tabs type="border-card" style="width:550px;">
44 <el-tab-pane v-if="checkPermission(['admin'])" label="Admin">
45 Admin can see this
46 <el-tag class="permission-sourceCode" type="info">
47 v-if="checkPermission(['admin'])"
48 </el-tag>
49 </el-tab-pane>
50
51 <el-tab-pane v-if="checkPermission(['editor'])" label="Editor">
52 Editor can see this
53 <el-tag class="permission-sourceCode" type="info">
54 v-if="checkPermission(['editor'])"
55 </el-tag>
56 </el-tab-pane>
57
58 <el-tab-pane v-if="checkPermission(['admin','editor'])" label="Admin-OR-Editor">
59 Both admin or editor can see this
60 <el-tag class="permission-sourceCode" type="info">
61 v-if="checkPermission(['admin','editor'])"
62 </el-tag>
63 </el-tab-pane>
64 </el-tabs>
65 </div>
66 </div>
67 </template>
68
69 <script>
70 import permission from '@/directive/permission/index.js' // 权限判断指令
71 import checkPermission from '@/utils/permission' // 权限判断函数
72 import SwitchRoles from './components/SwitchRoles'
73
74 export default {
75 name: 'DirectivePermission',
76 components: { SwitchRoles },
77 directives: { permission },
78 data() {
79 return {
80 key: 1 // 为了能每次切换权限的时候重新初始化指令
81 }
82 },
83 methods: {
84 checkPermission,
85 handleRolesChange() {
86 this.key++
87 }
88 }
89 }
90 </script>
91
92 <style lang="scss" scoped>
93 .app-container {
94 /deep/ .permission-alert {
95 width: 320px;
96 margin-top: 15px;
97 background-color: #f0f9eb;
98 color: #67c23a;
99 padding: 8px 16px;
100 border-radius: 4px;
101 display: inline-block;
102 }
103 /deep/ .permission-sourceCode {
104 margin-left: 15px;
105 }
106 /deep/ .permission-tag {
107 background-color: #ecf5ff;
108 }
109 }
110 </style>
111
112
src/views/permission/page.vue
File was created 1 <template>
2 <div class="app-container">
3 <switch-roles @change="handleRolesChange" />
4 </div>
5 </template>
6
7 <script>
8 import SwitchRoles from './components/SwitchRoles'
9
10 export default {
11 name: 'PagePermission',
12 components: { SwitchRoles },
13 methods: {
14 handleRolesChange() {
15 this.$router.push({ path: '/permission/index?' + +new Date() })
16 }
17 }
18 }
19 </script>
20
src/views/permission/role.vue
File was created 1 <template>
2 <div class="app-container">
3 <el-button type="primary" @click="handleAddRole">
4 {{ $t('permission.addRole') }}
5 </el-button>
6
7 <el-table :data="rolesList" style="width: 100%;margin-top:30px;" border>
8 <el-table-column align="center" label="Role Key" width="220">
9 <template slot-scope="scope">
10 {{ scope.row.key }}
11 </template>
12 </el-table-column>
13 <el-table-column align="center" label="Role Name" width="220">
14 <template slot-scope="scope">
15 {{ scope.row.name }}
16 </template>
17 </el-table-column>
18 <el-table-column align="header-center" label="Description">
19 <template slot-scope="scope">
20 {{ scope.row.description }}
21 </template>
22 </el-table-column>
23 <el-table-column align="center" label="Operations">
24 <template slot-scope="scope">
25 <el-button type="primary" size="small" @click="handleEdit(scope)">
26 {{ $t('permission.editPermission') }}
27 </el-button>
28 <el-button type="danger" size="small" @click="handleDelete(scope)">
29 {{ $t('permission.delete') }}
30 </el-button>
31 </template>
32 </el-table-column>
33 </el-table>
34
35 <el-dialog :visible.sync="dialogVisible" :title="dialogType==='edit'?'Edit Role':'New Role'">
36 <el-form :model="role" label-width="80px" label-position="left">
37 <el-form-item label="Name">
38 <el-input v-model="role.name" placeholder="Role Name" />
39 </el-form-item>
40 <el-form-item label="Desc">
41 <el-input
42 v-model="role.description"
43 :autosize="{ minRows: 2, maxRows: 4}"
44 type="textarea"
45 placeholder="Role Description"
46 />
47 </el-form-item>
48 <el-form-item label="Menus">
49 <el-tree ref="tree" :check-strictly="checkStrictly" :data="routesData" :props="defaultProps" show-checkbox node-key="path" class="permission-tree" />
50 </el-form-item>
51 </el-form>
52 <div style="text-align:right;">
53 <el-button type="danger" @click="dialogVisible=false">
54 {{ $t('permission.cancel') }}
55 </el-button>
56 <el-button type="primary" @click="confirmRole">
57 {{ $t('permission.confirm') }}
58 </el-button>
59 </div>
60 </el-dialog>
61 </div>
62 </template>
63
64 <script>
65 import path from 'path'
66 import { deepClone } from '@/utils'
67 import { getRoutes, getRoles, addRole, deleteRole, updateRole } from '@/api/role'
68 import i18n from '@/lang'
69
70 const defaultRole = {
71 key: '',
72 name: '',
73 description: '',
74 routes: []
75 }
76
77 export default {
78 data() {
79 return {
80 role: Object.assign({}, defaultRole),
81 routes: [],
82 rolesList: [],
83 dialogVisible: false,
84 dialogType: 'new',
85 checkStrictly: false,
86 defaultProps: {
87 children: 'children',
88 label: 'title'
89 }
90 }
91 },
92 computed: {
93 routesData() {
94 return this.routes
95 }
96 },
97 created() {
98 // Mock: get all routes and roles list from server
99 this.getRoutes()
100 this.getRoles()
101 },
102 methods: {
103 async getRoutes() {
104 const res = await getRoutes()
105 this.serviceRoutes = res.data
106 const routes = this.generateRoutes(res.data)
107 this.routes = this.i18n(routes)
108 },
109 async getRoles() {
110 const res = await getRoles()
111 this.rolesList = res.data
112 },
113 i18n(routes) {
114 const app = routes.map(route => {
115 route.title = i18n.t(`route.${route.title}`)
116 if (route.children) {
117 route.children = this.i18n(route.children)
118 }
119 return route
120 })
121 return app
122 },
123 // Reshape the routes structure so that it looks the same as the sidebar
124 generateRoutes(routes, basePath = '/') {
125 const res = []
126
127 for (let route of routes) {
128 // skip some route
129 if (route.hidden) { continue }
130
131 const onlyOneShowingChild = this.onlyOneShowingChild(route.children, route)
132
133 if (route.children && onlyOneShowingChild && !route.alwaysShow) {
134 route = onlyOneShowingChild
135 }
136
137 const data = {
138 path: path.resolve(basePath, route.path),
139 title: route.meta && route.meta.title
140
141 }
142
143 // recursive child routes
144 if (route.children) {
145 data.children = this.generateRoutes(route.children, data.path)
146 }
147 res.push(data)
148 }
149 return res
150 },
151 generateArr(routes) {
152 let data = []
153 routes.forEach(route => {
154 data.push(route)
155 if (route.children) {
156 const temp = this.generateArr(route.children)
157 if (temp.length > 0) {
158 data = [...data, ...temp]
159 }
160 }
161 })
162 return data
163 },
164 handleAddRole() {
165 this.role = Object.assign({}, defaultRole)
166 if (this.$refs.tree) {
167 this.$refs.tree.setCheckedNodes([])
168 }
169 this.dialogType = 'new'
170 this.dialogVisible = true
171 },
172 handleEdit(scope) {
173 this.dialogType = 'edit'
174 this.dialogVisible = true
175 this.checkStrictly = true
176 this.role = deepClone(scope.row)
177 this.$nextTick(() => {
178 const routes = this.generateRoutes(this.role.routes)
179 this.$refs.tree.setCheckedNodes(this.generateArr(routes))
180 // set checked state of a node not affects its father and child nodes
181 this.checkStrictly = false
182 })
183 },
184 handleDelete({ $index, row }) {
185 this.$confirm('Confirm to remove the role?', 'Warning', {
186 confirmButtonText: 'Confirm',
187 cancelButtonText: 'Cancel',
188 type: 'warning'
189 })
190 .then(async() => {
191 await deleteRole(row.key)
192 this.rolesList.splice($index, 1)
193 this.$message({
194 type: 'success',
195 message: 'Delete succed!'
196 })
197 })
198 .catch(err => { console.error(err) })
199 },
200 generateTree(routes, basePath = '/', checkedKeys) {
201 const res = []
202
203 for (const route of routes) {
204 const routePath = path.resolve(basePath, route.path)
205
206 // recursive child routes
207 if (route.children) {
208 route.children = this.generateTree(route.children, routePath, checkedKeys)
209 }
210
211 if (checkedKeys.includes(routePath) || (route.children && route.children.length >= 1)) {
212 res.push(route)
213 }
214 }
215 return res
216 },
217 async confirmRole() {
218 const isEdit = this.dialogType === 'edit'
219
220 const checkedKeys = this.$refs.tree.getCheckedKeys()
221 this.role.routes = this.generateTree(deepClone(this.serviceRoutes), '/', checkedKeys)
222
223 if (isEdit) {
224 await updateRole(this.role.key, this.role)
225 for (let index = 0; index < this.rolesList.length; index++) {
226 if (this.rolesList[index].key === this.role.key) {
227 this.rolesList.splice(index, 1, Object.assign({}, this.role))
228 break
229 }
230 }
231 } else {
232 const { data } = await addRole(this.role)
233 this.role.key = data.key
234 this.rolesList.push(this.role)
235 }
236
237 const { description, key, name } = this.role
238 this.dialogVisible = false
239 this.$notify({
240 title: 'Success',
241 dangerouslyUseHTMLString: true,
242 message: `
243 <div>Role Key: ${key}</div>
244 <div>Role Name: ${name}</div>
245 <div>Description: ${description}</div>
246 `,
247 type: 'success'
248 })
249 },
250 // reference: src/view/layout/components/Sidebar/SidebarItem.vue
251 onlyOneShowingChild(children = [], parent) {
252 let onlyOneChild = null
253 const showingChildren = children.filter(item => !item.hidden)
254
255 // When there is only one child route, the child route is displayed by default
256 if (showingChildren.length === 1) {
257 onlyOneChild = showingChildren[0]
258 onlyOneChild.path = path.resolve(parent.path, onlyOneChild.path)
259 return onlyOneChild
260 }
261
262 // Show parent if there are no child route to display
263 if (showingChildren.length === 0) {
264 onlyOneChild = { ... parent, path: '', noShowingChildren: true }
265 return onlyOneChild
266 }
267
268 return false
269 }
270 }
271 }
272 </script>
273
274 <style lang="scss" scoped>
275 .app-container {
276 .roles-table {
277 margin-top: 30px;
278 }
279 .permission-tree {
280 margin-bottom: 30px;
281 }
282 }
283 </style>
284
src/views/profile/components/Account.vue
File was created 1 <template>
2 <el-form>
3 <el-form-item label="Name">
4 <el-input v-model.trim="user.name" />
5 </el-form-item>
6 <el-form-item label="Email">
7 <el-input v-model.trim="user.email" />
8 </el-form-item>
9 <el-form-item>
10 <el-button type="primary" @click="submit">Update</el-button>
11 </el-form-item>
12 </el-form>
13 </template>
14
15 <script>
16 export default {
17 props: {
18 user: {
19 type: Object,
20 default: () => {
21 return {
22 name: '',
23 email: ''
24 }
25 }
26 }
27 },
28 methods: {
29 submit() {
30 this.$message({
31 message: 'User information has been updated successfully',
32 type: 'success',
33 duration: 5 * 1000
34 })
35 }
36 }
37 }
38 </script>
39
src/views/profile/components/Activity.vue
File was created 1 <template>
2 <div class="user-activity">
3 <div class="post">
4 <div class="user-block">
5 <img class="img-circle" :src="'https://wpimg.wallstcn.com/57ed425a-c71e-4201-9428-68760c0537c4.jpg'+avatarPrefix">
6 <span class="username text-muted">Iron Man</span>
7 <span class="description">Shared publicly - 7:30 PM today</span>
8 </div>
9 <p>
10 Lorem ipsum represents a long-held tradition for designers,
11 typographers and the like. Some people hate it and argue for
12 its demise, but others ignore the hate as they create awesome
13 tools to help create filler text for everyone from bacon lovers
14 to Charlie Sheen fans.
15 </p>
16 <ul class="list-inline">
17 <li>
18 <span class="link-black text-sm">
19 <i class="el-icon-share" />
20 Share
21 </span>
22 </li>
23 <li>
24 <span class="link-black text-sm">
25 <svg-icon icon-class="like" />
26 Like
27 </span>
28 </li>
29 </ul>
30 </div>
31 <div class="post">
32 <div class="user-block">
33 <img class="img-circle" :src="'https://wpimg.wallstcn.com/9e2a5d0a-bd5b-457f-ac8e-86554616c87b.jpg'+avatarPrefix">
34 <span class="username text-muted">Captain American</span>
35 <span class="description">Sent you a message - yesterday</span>
36 </div>
37 <p>
38 Lorem ipsum represents a long-held tradition for designers,
39 typographers and the like. Some people hate it and argue for
40 its demise, but others ignore the hate as they create awesome
41 tools to help create filler text for everyone from bacon lovers
42 to Charlie Sheen fans.
43 </p>
44 <ul class="list-inline">
45 <li>
46 <span class="link-black text-sm">
47 <i class="el-icon-share" />
48 Share
49 </span>
50 </li>
51 <li>
52 <span class="link-black text-sm">
53 <svg-icon icon-class="like" />
54 Like
55 </span>
56 </li>
57 </ul>
58 </div>
59 <div class="post">
60 <div class="user-block">
61 <img class="img-circle" :src="'https://wpimg.wallstcn.com/fb57f689-e1ab-443c-af12-8d4066e202e2.jpg'+avatarPrefix">
62 <span class="username">Spider Man</span>
63 <span class="description">Posted 4 photos - 2 days ago</span>
64 </div>
65 <div class="user-images">
66 <el-carousel :interval="6000" type="card" height="220px">
67 <el-carousel-item v-for="item in carouselImages" :key="item">
68 <img :src="item+carouselPrefix" class="image">
69 </el-carousel-item>
70 </el-carousel>
71 </div>
72 <ul class="list-inline">
73 <li><span class="link-black text-sm"><i class="el-icon-share" /> Share</span></li>
74 <li>
75 <span class="link-black text-sm">
76 <svg-icon icon-class="like" /> Like</span>
77 </li>
78 </ul>
79 </div>
80 </div>
81 </template>
82
83 <script>
84 const avatarPrefix = '?imageView2/1/w/80/h/80'
85 const carouselPrefix = '?imageView2/2/h/440'
86
87 export default {
88 data() {
89 return {
90 carouselImages: [
91 'https://wpimg.wallstcn.com/9679ffb0-9e0b-4451-9916-e21992218054.jpg',
92 'https://wpimg.wallstcn.com/bcce3734-0837-4b9f-9261-351ef384f75a.jpg',
93 'https://wpimg.wallstcn.com/d1d7b033-d75e-4cd6-ae39-fcd5f1c0a7c5.jpg',
94 'https://wpimg.wallstcn.com/50530061-851b-4ca5-9dc5-2fead928a939.jpg'
95 ],
96 avatarPrefix,
97 carouselPrefix
98 }
99 }
100 }
101 </script>
102
103 <style lang="scss" scoped>
104 .user-activity {
105 .user-block {
106
107 .username,
108 .description {
109 display: block;
110 margin-left: 50px;
111 padding: 2px 0;
112 }
113
114 .username{
115 font-size: 16px;
116 color: #000;
117 }
118
119 :after {
120 clear: both;
121 }
122
123 .img-circle {
124 border-radius: 50%;
125 width: 40px;
126 height: 40px;
127 float: left;
128 }
129
130 span {
131 font-weight: 500;
132 font-size: 12px;
133 }
134 }
135
136 .post {
137 font-size: 14px;
138 border-bottom: 1px solid #d2d6de;
139 margin-bottom: 15px;
140 padding-bottom: 15px;
141 color: #666;
142
143 .image {
144 width: 100%;
145 height: 100%;
146
147 }
148
149 .user-images {
150 padding-top: 20px;
151 }
152 }
153
154 .list-inline {
155 padding-left: 0;
156 margin-left: -5px;
157 list-style: none;
158
159 li {
160 display: inline-block;
161 padding-right: 5px;
162 padding-left: 5px;
163 font-size: 13px;
164 }
165
166 .link-black {
167
168 &:hover,
169 &:focus {
170 color: #999;
171 }
172 }
173 }
174
175 }
176
177 .box-center {
178 margin: 0 auto;
179 display: table;
180 }
181
182 .text-muted {
183 color: #777;
184 }
185 </style>
186
src/views/profile/components/Timeline.vue
File was created 1 <template>
2 <div class="block">
3 <el-timeline>
4 <el-timeline-item v-for="(item,index) of timeline" :key="index" :timestamp="item.timestamp" placement="top">
5 <el-card>
6 <h4>{{ item.title }}</h4>
7 <p>{{ item.content }}</p>
8 </el-card>
9 </el-timeline-item>
10 </el-timeline>
11 </div>
12 </template>
13
14 <script>
15 export default {
16 data() {
17 return {
18 timeline: [
19 {
20 timestamp: '2019/4/20',
21 title: 'Update Github template',
22 content: 'PanJiaChen committed 2019/4/20 20:46'
23 },
24 {
25 timestamp: '2019/4/21',
26 title: 'Update Github template',
27 content: 'PanJiaChen committed 2019/4/21 20:46'
28 },
29 {
30 timestamp: '2019/4/22',
31 title: 'Build Template',
32 content: 'PanJiaChen committed 2019/4/22 20:46'
33 },
34 {
35 timestamp: '2019/4/23',
36 title: 'Release New Version',
37 content: 'PanJiaChen committed 2019/4/23 20:46'
38 }
39 ]
40 }
41 }
42 }
43 </script>
44
src/views/profile/components/UserCard.vue
File was created 1 <template>
2 <el-card style="margin-bottom:20px;">
3 <div slot="header" class="clearfix">
4 <span>About me</span>
5 </div>
6
7 <div class="user-profile">
8 <div class="box-center">
9 <pan-thumb :image="user.avatar" :height="'100px'" :width="'100px'" :hoverable="false">
10 <div>Hello</div>
11 {{ user.role }}
12 </pan-thumb>
13 </div>
14 <div class="box-center">
15 <div class="user-name text-center">{{ user.name }}</div>
16 <div class="user-role text-center text-muted">{{ user.role | uppercaseFirst }}</div>
17 </div>
18 </div>
19
20 <div class="user-bio">
21 <div class="user-education user-bio-section">
22 <div class="user-bio-section-header"><svg-icon icon-class="education" /><span>Education</span></div>
23 <div class="user-bio-section-body">
24 <div class="text-muted">
25 JS in Computer Science from the University of Technology
26 </div>
27 </div>
28 </div>
29
30 <div class="user-skills user-bio-section">
31 <div class="user-bio-section-header"><svg-icon icon-class="skill" /><span>Skills</span></div>
32 <div class="user-bio-section-body">
33 <div class="progress-item">
34 <span>Vue</span>
35 <el-progress :percentage="70" />
36 </div>
37 <div class="progress-item">
38 <span>JavaScript</span>
39 <el-progress :percentage="18" />
40 </div>
41 <div class="progress-item">
42 <span>Css</span>
43 <el-progress :percentage="12" />
44 </div>
45 <div class="progress-item">
46 <span>ESLint</span>
47 <el-progress :percentage="100" status="success" />
48 </div>
49 </div>
50 </div>
51 </div>
52 </el-card>
53 </template>
54
55 <script>
56 import PanThumb from '@/components/PanThumb'
57
58 export default {
59 components: { PanThumb },
60 props: {
61 user: {
62 type: Object,
63 default: () => {
64 return {
65 name: '',
66 email: '',
67 avatar: '',
68 roles: ''
69 }
70 }
71 }
72 }
73 }
74 </script>
75
76 <style lang="scss" scoped>
77 .box-center {
78 margin: 0 auto;
79 display: table;
80 }
81
82 .text-muted {
83 color: #777;
84 }
85
86 .user-profile {
87 .user-name {
88 font-weight: bold;
89 }
90
91 .box-center {
92 padding-top: 10px;
93 }
94
95 .user-role {
96 padding-top: 10px;
97 font-weight: 400;
98 font-size: 14px;
99 }
100
101 .box-social {
102 padding-top: 30px;
103
104 .el-table {
105 border-top: 1px solid #dfe6ec;
106 }
107 }
108
109 .user-follow {
110 padding-top: 20px;
111 }
112 }
113
114 .user-bio {
115 margin-top: 20px;
116 color: #606266;
117
118 span {
119 padding-left: 4px;
120 }
121
122 .user-bio-section {
123 font-size: 14px;
124 padding: 15px 0;
125
126 .user-bio-section-header {
127 border-bottom: 1px solid #dfe6ec;
128 padding-bottom: 10px;
129 margin-bottom: 10px;
130 font-weight: bold;
131 }
132 }
133 }
134 </style>
135
src/views/profile/index.vue
File was created 1 <template>
2 <div class="app-container">
3 <div v-if="user">
4 <el-row :gutter="20">
5
6 <el-col :span="6" :xs="24">
7 <user-card :user="user" />
8 </el-col>
9
10 <el-col :span="18" :xs="24">
11 <el-card>
12 <el-tabs v-model="activeTab">
13 <el-tab-pane label="Activity" name="activity">
14 <activity />
15 </el-tab-pane>
16 <el-tab-pane label="Timeline" name="timeline">
17 <timeline />
18 </el-tab-pane>
19 <el-tab-pane label="Account" name="account">
20 <account :user="user" />
21 </el-tab-pane>
22 </el-tabs>
23 </el-card>
24 </el-col>
25
26 </el-row>
27 </div>
28 </div>
29 </template>
30
31 <script>
32 import { mapGetters } from 'vuex'
33 import UserCard from './components/UserCard'
34 import Activity from './components/Activity'
35 import Timeline from './components/Timeline'
36 import Account from './components/Account'
37
38 export default {
39 name: 'Profile',
40 components: { UserCard, Activity, Timeline, Account },
41 data() {
42 return {
43 user: {},
44 activeTab: 'activity'
45 }
46 },
47 computed: {
48 ...mapGetters([
49 'name',
50 'avatar',
51 'roles'
52 ])
53 },
54 created() {
55 this.getUser()
56 },
57 methods: {
58 getUser() {
59 this.user = {
60 name: this.name,
61 role: this.roles.join(' | '),
62 email: 'admin@test.com',
63 avatar: this.avatar
64 }
65 }
66 }
67 }
68 </script>
69
src/views/qiniu/upload.vue
File was created 1 <template>
2 <el-upload :data="dataObj" :multiple="true" :before-upload="beforeUpload" action="https://upload.qbox.me" drag>
3 <i class="el-icon-upload" />
4 <div class="el-upload__text">
5 将文件拖到此处,或<em>点击上传</em>
6 </div>
7 </el-upload>
8 </template>
9
10 <script>
11 import { getToken } from '@/api/qiniu'
12 // 获取七牛token 后端通过Access Key,Secret Key,bucket等生成token
13 // 七牛官方sdk https://developer.qiniu.com/sdk#official-sdk
14
15 export default {
16 data() {
17 return {
18 dataObj: { token: '', key: '' },
19 image_uri: [],
20 fileList: []
21 }
22 },
23 methods: {
24 beforeUpload() {
25 const _self = this
26 return new Promise((resolve, reject) => {
27 getToken().then(response => {
28 const key = response.data.qiniu_key
29 const token = response.data.qiniu_token
30 _self._data.dataObj.token = token
31 _self._data.dataObj.key = key
32 resolve(true)
33 }).catch(err => {
34 console.log(err)
35 reject(false)
36 })
37 })
38 }
39 }
40 }
41 </script>
42
src/views/redirect/index.vue
File was created 1 <script>
2 export default {
3 created() {
4 const { params, query } = this.$route
5 const { path } = params
6 this.$router.replace({ path: '/' + path, query })
7 },
8 render: function(h) {
9 return h() // avoid warning message
10 }
11 }
12 </script>
13
src/views/tab/components/TabPane.vue
File was created 1 <template>
2 <el-table :data="list" border fit highlight-current-row style="width: 100%">
3 <el-table-column
4 v-loading="loading"
5 align="center"
6 label="ID"
7 width="65"
8 element-loading-text="请给我点时间!"
9 >
10 <template slot-scope="scope">
11 <span>{{ scope.row.id }}</span>
12 </template>
13 </el-table-column>
14
15 <el-table-column width="180px" align="center" label="Date">
16 <template slot-scope="scope">
17 <span>{{ scope.row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
18 </template>
19 </el-table-column>
20
21 <el-table-column min-width="300px" label="Title">
22 <template slot-scope="{row}">
23 <span>{{ row.title }}</span>
24 <el-tag>{{ row.type }}</el-tag>
25 </template>
26 </el-table-column>
27
28 <el-table-column width="110px" align="center" label="Author">
29 <template slot-scope="scope">
30 <span>{{ scope.row.author }}</span>
31 </template>
32 </el-table-column>
33
34 <el-table-column width="120px" label="Importance">
35 <template slot-scope="scope">
36 <svg-icon v-for="n in +scope.row.importance" :key="n" icon-class="star" />
37 </template>
38 </el-table-column>
39
40 <el-table-column align="center" label="Readings" width="95">
41 <template slot-scope="scope">
42 <span>{{ scope.row.pageviews }}</span>
43 </template>
44 </el-table-column>
45
46 <el-table-column class-name="status-col" label="Status" width="110">
47 <template slot-scope="{row}">
48 <el-tag :type="row.status | statusFilter">
49 {{ row.status }}
50 </el-tag>
51 </template>
52 </el-table-column>
53 </el-table>
54 </template>
55
56 <script>
57 import { fetchList } from '@/api/article'
58
59 export default {
60 filters: {
61 statusFilter(status) {
62 const statusMap = {
63 published: 'success',
64 draft: 'info',
65 deleted: 'danger'
66 }
67 return statusMap[status]
68 }
69 },
70 props: {
71 type: {
72 type: String,
73 default: 'CN'
74 }
75 },
76 data() {
77 return {
78 list: null,
79 listQuery: {
80 page: 1,
81 limit: 5,
82 type: this.type,
83 sort: '+id'
84 },
85 loading: false
86 }
87 },
88 created() {
89 this.getList()
90 },
91 methods: {
92 getList() {
93 this.loading = true
94 this.$emit('create') // for test
95 fetchList(this.listQuery).then(response => {
96 this.list = response.data.items
97 this.loading = false
98 })
99 }
100 }
101 }
102 </script>
103
104
src/views/tab/index.vue
File was created 1 <template>
2 <div class="tab-container">
3 <el-tag>mounted times :{{ createdTimes }}</el-tag>
4 <el-alert :closable="false" style="width:200px;display:inline-block;vertical-align: middle;margin-left:30px;" title="Tab with keep-alive" type="success" />
5 <el-tabs v-model="activeName" style="margin-top:15px;" type="border-card">
6 <el-tab-pane v-for="item in tabMapOptions" :key="item.key" :label="item.label" :name="item.key">
7 <keep-alive>
8 <tab-pane v-if="activeName==item.key" :type="item.key" @create="showCreatedTimes" />
9 </keep-alive>
10 </el-tab-pane>
11 </el-tabs>
12 </div>
13 </template>
14
15 <script>
16 import tabPane from './components/TabPane'
17
18 export default {
19 name: 'Tab',
20 components: { tabPane },
21 data() {
22 return {
23 tabMapOptions: [
24 { label: 'China', key: 'CN' },
25 { label: 'USA', key: 'US' },
26 { label: 'Japan', key: 'JP' },
27 { label: 'Eurozone', key: 'EU' }
28 ],
29 activeName: 'CN',
30 createdTimes: 0
31 }
32 },
33 watch: {
34 activeName(val) {
35 this.$router.push(`${this.$route.path}?tab=${val}`)
36 }
37 },
38 created() {
39 // init the default selected tab
40 const tab = this.$route.query.tab
41 if (tab) {
42 this.activeName = tab
43 }
44 },
45 methods: {
46 showCreatedTimes() {
47 this.createdTimes = this.createdTimes + 1
48 }
49 }
50 }
51 </script>
52
53 <style scoped>
54 .tab-container {
55 margin: 30px;
56 }
57 </style>
58
src/views/table/complex-table.vue
File was created 1 <template>
2 <div class="app-container">
3 <div class="filter-container">
4 <el-input v-model="listQuery.title" :placeholder="$t('table.title')" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
5 <el-select v-model="listQuery.importance" :placeholder="$t('table.importance')" clearable style="width: 90px" class="filter-item">
6 <el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" />
7 </el-select>
8 <el-select v-model="listQuery.type" :placeholder="$t('table.type')" clearable class="filter-item" style="width: 130px">
9 <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" />
10 </el-select>
11 <el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter">
12 <el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" />
13 </el-select>
14 <el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
15 {{ $t('table.search') }}
16 </el-button>
17 <el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
18 {{ $t('table.add') }}
19 </el-button>
20 <el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">
21 {{ $t('table.export') }}
22 </el-button>
23 <el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
24 {{ $t('table.reviewer') }}
25 </el-checkbox>
26 </div>
27
28 <el-table
29 :key="tableKey"
30 v-loading="listLoading"
31 :data="list"
32 border
33 fit
34 highlight-current-row
35 style="width: 100%;"
36 @sort-change="sortChange"
37 >
38 <el-table-column :label="$t('table.id')" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')">
39 <template slot-scope="{row}">
40 <span>{{ row.id }}</span>
41 </template>
42 </el-table-column>
43 <el-table-column :label="$t('table.date')" width="150px" align="center">
44 <template slot-scope="{row}">
45 <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
46 </template>
47 </el-table-column>
48 <el-table-column :label="$t('table.title')" min-width="150px">
49 <template slot-scope="{row}">
50 <span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span>
51 <el-tag>{{ row.type | typeFilter }}</el-tag>
52 </template>
53 </el-table-column>
54 <el-table-column :label="$t('table.author')" width="110px" align="center">
55 <template slot-scope="{row}">
56 <span>{{ row.author }}</span>
57 </template>
58 </el-table-column>
59 <el-table-column v-if="showReviewer" :label="$t('table.reviewer')" width="110px" align="center">
60 <template slot-scope="{row}">
61 <span style="color:red;">{{ row.reviewer }}</span>
62 </template>
63 </el-table-column>
64 <el-table-column :label="$t('table.importance')" width="80px">
65 <template slot-scope="{row}">
66 <svg-icon v-for="n in +row.importance" :key="n" icon-class="star" class="meta-item__icon" />
67 </template>
68 </el-table-column>
69 <el-table-column :label="$t('table.readings')" align="center" width="95">
70 <template slot-scope="{row}">
71 <span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span>
72 <span v-else>0</span>
73 </template>
74 </el-table-column>
75 <el-table-column :label="$t('table.status')" class-name="status-col" width="100">
76 <template slot-scope="{row}">
77 <el-tag :type="row.status | statusFilter">
78 {{ row.status }}
79 </el-tag>
80 </template>
81 </el-table-column>
82 <el-table-column :label="$t('table.actions')" align="center" width="230" class-name="small-padding fixed-width">
83 <template slot-scope="{row,$index}">
84 <el-button type="primary" size="mini" @click="handleUpdate(row)">
85 {{ $t('table.edit') }}
86 </el-button>
87 <el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')">
88 {{ $t('table.publish') }}
89 </el-button>
90 <el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')">
91 {{ $t('table.draft') }}
92 </el-button>
93 <el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)">
94 {{ $t('table.delete') }}
95 </el-button>
96 </template>
97 </el-table-column>
98 </el-table>
99
100 <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
101
102 <el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
103 <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;">
104 <el-form-item :label="$t('table.type')" prop="type">
105 <el-select v-model="temp.type" class="filter-item" placeholder="Please select">
106 <el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" />
107 </el-select>
108 </el-form-item>
109 <el-form-item :label="$t('table.date')" prop="timestamp">
110 <el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" />
111 </el-form-item>
112 <el-form-item :label="$t('table.title')" prop="title">
113 <el-input v-model="temp.title" />
114 </el-form-item>
115 <el-form-item :label="$t('table.status')">
116 <el-select v-model="temp.status" class="filter-item" placeholder="Please select">
117 <el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" />
118 </el-select>
119 </el-form-item>
120 <el-form-item :label="$t('table.importance')">
121 <el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" />
122 </el-form-item>
123 <el-form-item :label="$t('table.remark')">
124 <el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" />
125 </el-form-item>
126 </el-form>
127 <div slot="footer" class="dialog-footer">
128 <el-button @click="dialogFormVisible = false">
129 {{ $t('table.cancel') }}
130 </el-button>
131 <el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
132 {{ $t('table.confirm') }}
133 </el-button>
134 </div>
135 </el-dialog>
136
137 <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics">
138 <el-table :data="pvData" border fit highlight-current-row style="width: 100%">
139 <el-table-column prop="key" label="Channel" />
140 <el-table-column prop="pv" label="Pv" />
141 </el-table>
142 <span slot="footer" class="dialog-footer">
143 <el-button type="primary" @click="dialogPvVisible = false">{{ $t('table.confirm') }}</el-button>
144 </span>
145 </el-dialog>
146 </div>
147 </template>
148
149 <script>
150 import { fetchList, fetchPv, createArticle, updateArticle } from '@/api/article'
151 import waves from '@/directive/waves' // waves directive
152 import { parseTime } from '@/utils'
153 import Pagination from '@/components/Pagination' // secondary package based on el-pagination
154
155 const calendarTypeOptions = [
156 { key: 'CN', display_name: 'China' },
157 { key: 'US', display_name: 'USA' },
158 { key: 'JP', display_name: 'Japan' },
159 { key: 'EU', display_name: 'Eurozone' }
160 ]
161
162 // arr to obj, such as { CN : "China", US : "USA" }
163 const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => {
164 acc[cur.key] = cur.display_name
165 return acc
166 }, {})
167
168 export default {
169 name: 'ComplexTable',
170 components: { Pagination },
171 directives: { waves },
172 filters: {
173 statusFilter(status) {
174 const statusMap = {
175 published: 'success',
176 draft: 'info',
177 deleted: 'danger'
178 }
179 return statusMap[status]
180 },
181 typeFilter(type) {
182 return calendarTypeKeyValue[type]
183 }
184 },
185 data() {
186 return {
187 tableKey: 0,
188 list: null,
189 total: 0,
190 listLoading: true,
191 listQuery: {
192 page: 1,
193 limit: 20,
194 importance: undefined,
195 title: undefined,
196 type: undefined,
197 sort: '+id'
198 },
199 importanceOptions: [1, 2, 3],
200 calendarTypeOptions,
201 sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }],
202 statusOptions: ['published', 'draft', 'deleted'],
203 showReviewer: false,
204 temp: {
205 id: undefined,
206 importance: 1,
207 remark: '',
208 timestamp: new Date(),
209 title: '',
210 type: '',
211 status: 'published'
212 },
213 dialogFormVisible: false,
214 dialogStatus: '',
215 textMap: {
216 update: 'Edit',
217 create: 'Create'
218 },
219 dialogPvVisible: false,
220 pvData: [],
221 rules: {
222 type: [{ required: true, message: 'type is required', trigger: 'change' }],
223 timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }],
224 title: [{ required: true, message: 'title is required', trigger: 'blur' }]
225 },
226 downloadLoading: false
227 }
228 },
229 created() {
230 this.getList()
231 },
232 methods: {
233 getList() {
234 this.listLoading = true
235 fetchList(this.listQuery).then(response => {
236 this.list = response.data.items
237 this.total = response.data.total
238
239 // Just to simulate the time of the request
240 setTimeout(() => {
241 this.listLoading = false
242 }, 1.5 * 1000)
243 })
244 },
245 handleFilter() {
246 this.listQuery.page = 1
247 this.getList()
248 },
249 handleModifyStatus(row, status) {
250 this.$message({
251 message: '操作成功',
252 type: 'success'
253 })
254 row.status = status
255 },
256 sortChange(data) {
257 const { prop, order } = data
258 if (prop === 'id') {
259 this.sortByID(order)
260 }
261 },
262 sortByID(order) {
263 if (order === 'ascending') {
264 this.listQuery.sort = '+id'
265 } else {
266 this.listQuery.sort = '-id'
267 }
268 this.handleFilter()
269 },
270 resetTemp() {
271 this.temp = {
272 id: undefined,
273 importance: 1,
274 remark: '',
275 timestamp: new Date(),
276 title: '',
277 status: 'published',
278 type: ''
279 }
280 },
281 handleCreate() {
282 this.resetTemp()
283 this.dialogStatus = 'create'
284 this.dialogFormVisible = true
285 this.$nextTick(() => {
286 this.$refs['dataForm'].clearValidate()
287 })
288 },
289 createData() {
290 this.$refs['dataForm'].validate((valid) => {
291 if (valid) {
292 this.temp.id = parseInt(Math.random() * 100) + 1024 // mock a id
293 this.temp.author = 'vue-element-admin'
294 createArticle(this.temp).then(() => {
295 this.list.unshift(this.temp)
296 this.dialogFormVisible = false
297 this.$notify({
298 title: '成功',
299 message: '创建成功',
300 type: 'success',
301 duration: 2000
302 })
303 })
304 }
305 })
306 },
307 handleUpdate(row) {
308 this.temp = Object.assign({}, row) // copy obj
309 this.temp.timestamp = new Date(this.temp.timestamp)
310 this.dialogStatus = 'update'
311 this.dialogFormVisible = true
312 this.$nextTick(() => {
313 this.$refs['dataForm'].clearValidate()
314 })
315 },
316 updateData() {
317 this.$refs['dataForm'].validate((valid) => {
318 if (valid) {
319 const tempData = Object.assign({}, this.temp)
320 tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464
321 updateArticle(tempData).then(() => {
322 const index = this.list.findIndex(v => v.id === this.temp.id)
323 this.list.splice(index, 1, this.temp)
324 this.dialogFormVisible = false
325 this.$notify({
326 title: '成功',
327 message: '更新成功',
328 type: 'success',
329 duration: 2000
330 })
331 })
332 }
333 })
334 },
335 handleDelete(row, index) {
336 this.$notify({
337 title: '成功',
338 message: '删除成功',
339 type: 'success',
340 duration: 2000
341 })
342 this.list.splice(index, 1)
343 },
344 handleFetchPv(pv) {
345 fetchPv(pv).then(response => {
346 this.pvData = response.data.pvData
347 this.dialogPvVisible = true
348 })
349 },
350 handleDownload() {
351 this.downloadLoading = true
352 import('@/vendor/Export2Excel').then(excel => {
353 const tHeader = ['timestamp', 'title', 'type', 'importance', 'status']
354 const filterVal = ['timestamp', 'title', 'type', 'importance', 'status']
355 const data = this.formatJson(filterVal)
356 excel.export_json_to_excel({
357 header: tHeader,
358 data,
359 filename: 'table-list'
360 })
361 this.downloadLoading = false
362 })
363 },
364 formatJson(filterVal) {
365 return this.list.map(v => filterVal.map(j => {
366 if (j === 'timestamp') {
367 return parseTime(v[j])
368 } else {
369 return v[j]
370 }
371 }))
372 },
373 getSortClass: function(key) {
374 const sort = this.listQuery.sort
375 return sort === `+${key}` ? 'ascending' : 'descending'
376 }
377 }
378 }
379 </script>
380
src/views/table/drag-table.vue
File was created 1 <template>
2 <div class="app-container">
3 <!-- Note that row-key is necessary to get a correct row order. -->
4 <el-table ref="dragTable" v-loading="listLoading" :data="list" row-key="id" border fit highlight-current-row style="width: 100%">
5 <el-table-column align="center" label="ID" width="65">
6 <template slot-scope="{row}">
7 <span>{{ row.id }}</span>
8 </template>
9 </el-table-column>
10
11 <el-table-column width="180px" align="center" label="Date">
12 <template slot-scope="{row}">
13 <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
14 </template>
15 </el-table-column>
16
17 <el-table-column min-width="300px" label="Title">
18 <template slot-scope="{row}">
19 <span>{{ row.title }}</span>
20 </template>
21 </el-table-column>
22
23 <el-table-column width="110px" align="center" label="Author">
24 <template slot-scope="{row}">
25 <span>{{ row.author }}</span>
26 </template>
27 </el-table-column>
28
29 <el-table-column width="100px" label="Importance">
30 <template slot-scope="{row}">
31 <svg-icon v-for="n in + row.importance" :key="n" icon-class="star" class="icon-star" />
32 </template>
33 </el-table-column>
34
35 <el-table-column align="center" label="Readings" width="95">
36 <template slot-scope="{row}">
37 <span>{{ row.pageviews }}</span>
38 </template>
39 </el-table-column>
40
41 <el-table-column class-name="status-col" label="Status" width="110">
42 <template slot-scope="{row}">
43 <el-tag :type="row.status | statusFilter">
44 {{ row.status }}
45 </el-tag>
46 </template>
47 </el-table-column>
48
49 <el-table-column align="center" label="Drag" width="80">
50 <template slot-scope="{}">
51 <svg-icon class="drag-handler" icon-class="drag" />
52 </template>
53 </el-table-column>
54 </el-table>
55 <!-- $t is vue-i18n global function to translate lang (lang in @/lang) -->
56 <div class="show-d">
57 <el-tag style="margin-right:12px;">{{ $t('table.dragTips1') }} :</el-tag> {{ oldList }}
58 </div>
59 <div class="show-d">
60 <el-tag>{{ $t('table.dragTips2') }} :</el-tag> {{ newList }}
61 </div>
62 </div>
63 </template>
64
65 <script>
66 import { fetchList } from '@/api/article'
67 import Sortable from 'sortablejs'
68
69 export default {
70 name: 'DragTable',
71 filters: {
72 statusFilter(status) {
73 const statusMap = {
74 published: 'success',
75 draft: 'info',
76 deleted: 'danger'
77 }
78 return statusMap[status]
79 }
80 },
81 data() {
82 return {
83 list: null,
84 total: null,
85 listLoading: true,
86 listQuery: {
87 page: 1,
88 limit: 10
89 },
90 sortable: null,
91 oldList: [],
92 newList: []
93 }
94 },
95 created() {
96 this.getList()
97 },
98 methods: {
99 async getList() {
100 this.listLoading = true
101 const { data } = await fetchList(this.listQuery)
102 this.list = data.items
103 this.total = data.total
104 this.listLoading = false
105 this.oldList = this.list.map(v => v.id)
106 this.newList = this.oldList.slice()
107 this.$nextTick(() => {
108 this.setSort()
109 })
110 },
111 setSort() {
112 const el = this.$refs.dragTable.$el.querySelectorAll('.el-table__body-wrapper > table > tbody')[0]
113 this.sortable = Sortable.create(el, {
114 ghostClass: 'sortable-ghost', // Class name for the drop placeholder,
115 setData: function(dataTransfer) {
116 // to avoid Firefox bug
117 // Detail see : https://github.com/RubaXa/Sortable/issues/1012
118 dataTransfer.setData('Text', '')
119 },
120 onEnd: evt => {
121 const targetRow = this.list.splice(evt.oldIndex, 1)[0]
122 this.list.splice(evt.newIndex, 0, targetRow)
123
124 // for show the changes, you can delete in you code
125 const tempIndex = this.newList.splice(evt.oldIndex, 1)[0]
126 this.newList.splice(evt.newIndex, 0, tempIndex)
127 }
128 })
129 }
130 }
131 }
132 </script>
133
134 <style>
135 .sortable-ghost{
136 opacity: .8;
137 color: #fff!important;
138 background: #42b983!important;
139 }
140 </style>
141
142 <style scoped>
143 .icon-star{
144 margin-right:2px;
145 }
146 .drag-handler{
147 width: 20px;
148 height: 20px;
149 cursor: pointer;
150 }
151 .show-d{
152 margin-top: 15px;
153 }
154 </style>
155
src/views/table/dynamic-table/components/FixedThead.vue
File was created 1 <template>
2 <div class="app-container">
3 <div class="filter-container">
4 <el-checkbox-group v-model="checkboxVal">
5 <el-checkbox label="apple">
6 apple
7 </el-checkbox>
8 <el-checkbox label="banana">
9 banana
10 </el-checkbox>
11 <el-checkbox label="orange">
12 orange
13 </el-checkbox>
14 </el-checkbox-group>
15 </div>
16
17 <el-table :key="key" :data="tableData" border fit highlight-current-row style="width: 100%">
18 <el-table-column prop="name" label="fruitName" width="180" />
19 <el-table-column v-for="fruit in formThead" :key="fruit" :label="fruit">
20 <template slot-scope="scope">
21 {{ scope.row[fruit] }}
22 </template>
23 </el-table-column>
24 </el-table>
25 </div>
26 </template>
27
28 <script>
29 const defaultFormThead = ['apple', 'banana']
30
31 export default {
32 data() {
33 return {
34 tableData: [
35 {
36 name: 'fruit-1',
37 apple: 'apple-10',
38 banana: 'banana-10',
39 orange: 'orange-10'
40 },
41 {
42 name: 'fruit-2',
43 apple: 'apple-20',
44 banana: 'banana-20',
45 orange: 'orange-20'
46 }
47 ],
48 key: 1, // table key
49 formTheadOptions: ['apple', 'banana', 'orange'],
50 checkboxVal: defaultFormThead, // checkboxVal
51 formThead: defaultFormThead // 默认表头 Default header
52 }
53 },
54 watch: {
55 checkboxVal(valArr) {
56 this.formThead = this.formTheadOptions.filter(i => valArr.indexOf(i) >= 0)
57 this.key = this.key + 1// 为了保证table 每次都会重渲 In order to ensure the table will be re-rendered each time
58 }
59 }
60 }
61 </script>
62
63
src/views/table/dynamic-table/components/UnfixedThead.vue
File was created 1 <template>
2 <div class="app-container">
3 <div class="filter-container">
4 <el-checkbox-group v-model="formThead">
5 <el-checkbox label="apple">
6 apple
7 </el-checkbox>
8 <el-checkbox label="banana">
9 banana
10 </el-checkbox>
11 <el-checkbox label="orange">
12 orange
13 </el-checkbox>
14 </el-checkbox-group>
15 </div>
16
17 <el-table :data="tableData" border fit highlight-current-row style="width: 100%">
18 <el-table-column prop="name" label="fruitName" width="180" />
19 <el-table-column v-for="fruit in formThead" :key="fruit" :label="fruit">
20 <template slot-scope="scope">
21 {{ scope.row[fruit] }}
22 </template>
23 </el-table-column>
24 </el-table>
25 </div>
26 </template>
27
28 <script>
29 export default {
30 data() {
31 return {
32 tableData: [
33 {
34 name: 'fruit-1',
35 apple: 'apple-10',
36 banana: 'banana-10',
37 orange: 'orange-10'
38 },
39 {
40 name: 'fruit-2',
41 apple: 'apple-20',
42 banana: 'banana-20',
43 orange: 'orange-20'
44 }
45 ],
46 formThead: ['apple', 'banana']
47 }
48 }
49 }
50 </script>
51
src/views/table/dynamic-table/index.vue
File was created 1 <template>
2 <div class="app-container">
3 <div style="margin:0 0 5px 20px">
4 {{ $t('table.dynamicTips1') }}
5 </div>
6 <fixed-thead />
7
8 <div style="margin:30px 0 5px 20px">
9 {{ $t('table.dynamicTips2') }}
10 </div>
11 <unfixed-thead />
12 </div>
13 </template>
14
15 <script>
16 import FixedThead from './components/FixedThead'
17 import UnfixedThead from './components/UnfixedThead'
18
19 export default {
20 name: 'DynamicTable',
21 components: { FixedThead, UnfixedThead }
22 }
23 </script>
24
25
src/views/table/index.vue
1 <template> File was deleted
2 <div class="app-container">
3 <el-table
4 v-loading="listLoading"
5 :data="list"
6 element-loading-text="Loading"
7 border
8 fit
9 highlight-current-row
10 >
11 <el-table-column align="center" label="用户id">
12 <template slot-scope="scope">{{ scope.$index }}</template>
13 </el-table-column>
14
15 <el-table-column label="openid">
16 <template slot-scope="scope">{{ scope.row.openid }}</template>
17 </el-table-column>
18
19 <el-table-column label="昵称" width="110" align="center">
20 <template slot-scope="scope">
21 <span>{{ scope.row.username }}</span>
22 </template>
23 </el-table-column>
24
25 <el-table-column label="头像" width="110" align="center">
26 <template slot-scope="scope">{{ scope.row.avatar }}</template>
27 </el-table-column>
28
29 <el-table-column class-name="status-col" label="状态" align="center">
30 <template slot-scope="scope">
31 <el-tag :type="scope.row.status | statusFilter">{{ scope.row.status }}</el-tag>
32 </template>
33 </el-table-column>
34
35 <el-table-column align="center" prop="created_at" label="注册时间">
36 <template slot-scope="scope">
37 <i class="el-icon-time" />
38 <span>{{ scope.row.create_at }}</span>
39 </template>
40 </el-table-column>
41 <el-table-column align="center" prop="created_at" label="成交记录">
42 <template slot-scope="scope">
43 <i class="el-icon-time" />
44 <span>{{ scope.row.pageviews }}</span>
45 </template>
46 </el-table-column>
47 <el-table-column align="center" prop="created_at" label="引流图">
48 <template slot-scope="scope">
49 <span>
50 <el-button type="primary">子用户{{scope.row.pageviews}}</el-button>
51 </span>
52 </template>
53 </el-table-column>
54 </el-table>
55 <el-pagination background layout="prev, pager, next" :total="100"></el-pagination>
56 </div>
57 </template>
58
59 <script>
60 import { getList } from "@/api/table";
61
62 export default {
63 filters: {
64 statusFilter(status) {
65 const statusMap = {
66 published: "success",
67 draft: "gray",
68 deleted: "danger"
69 };
70 return statusMap[status];
71 }
72 },
73 data() {
74 return {
75 list: null,
76 listLoading: true
77 };
78 },
79 created() {
80 this.fetchData();
81 },
82 methods: {
83 fetchData() {
84 this.listLoading = true;
85 getList().then(response => {
86 console.log("----getList---", response);
87 this.list = response.items;
88 this.listLoading = false;
89 });
90 }
91 }
92 };
93 </script>
94 1 <template>
src/views/table/inline-edit-table.vue
File was created 1 <template>
2 <div class="app-container">
3 <el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%">
4 <el-table-column align="center" label="ID" width="80">
5 <template slot-scope="{row}">
6 <span>{{ row.id }}</span>
7 </template>
8 </el-table-column>
9
10 <el-table-column width="180px" align="center" label="Date">
11 <template slot-scope="{row}">
12 <span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
13 </template>
14 </el-table-column>
15
16 <el-table-column width="120px" align="center" label="Author">
17 <template slot-scope="{row}">
18 <span>{{ row.author }}</span>
19 </template>
20 </el-table-column>
21
22 <el-table-column width="100px" label="Importance">
23 <template slot-scope="{row}">
24 <svg-icon v-for="n in + row.importance" :key="n" icon-class="star" class="meta-item__icon" />
25 </template>
26 </el-table-column>
27
28 <el-table-column class-name="status-col" label="Status" width="110">
29 <template slot-scope="{row}">
30 <el-tag :type="row.status | statusFilter">
31 {{ row.status }}
32 </el-tag>
33 </template>
34 </el-table-column>
35
36 <el-table-column min-width="300px" label="Title">
37 <template slot-scope="{row}">
38 <template v-if="row.edit">
39 <el-input v-model="row.title" class="edit-input" size="small" />
40 <el-button
41 class="cancel-btn"
42 size="small"
43 icon="el-icon-refresh"
44 type="warning"
45 @click="cancelEdit(row)"
46 >
47 cancel
48 </el-button>
49 </template>
50 <span v-else>{{ row.title }}</span>
51 </template>
52 </el-table-column>
53
54 <el-table-column align="center" label="Actions" width="120">
55 <template slot-scope="{row}">
56 <el-button
57 v-if="row.edit"
58 type="success"
59 size="small"
60 icon="el-icon-circle-check-outline"
61 @click="confirmEdit(row)"
62 >
63 Ok
64 </el-button>
65 <el-button
66 v-else
67 type="primary"
68 size="small"
69 icon="el-icon-edit"
70 @click="row.edit=!row.edit"
71 >
72 Edit
73 </el-button>
74 </template>
75 </el-table-column>
76 </el-table>
77 </div>
78 </template>
79
80 <script>
81 import { fetchList } from '@/api/article'
82
83 export default {
84 name: 'InlineEditTable',
85 filters: {
86 statusFilter(status) {
87 const statusMap = {
88 published: 'success',
89 draft: 'info',
90 deleted: 'danger'
91 }
92 return statusMap[status]
93 }
94 },
95 data() {
96 return {
97 list: null,
98 listLoading: true,
99 listQuery: {
100 page: 1,
101 limit: 10
102 }
103 }
104 },
105 created() {
106 this.getList()
107 },
108 methods: {
109 async getList() {
110 this.listLoading = true
111 const { data } = await fetchList(this.listQuery)
112 const items = data.items
113 this.list = items.map(v => {
114 this.$set(v, 'edit', false) // https://vuejs.org/v2/guide/reactivity.html
115 v.originalTitle = v.title // will be used when user click the cancel botton
116 return v
117 })
118 this.listLoading = false
119 },
120 cancelEdit(row) {
121 row.title = row.originalTitle
122 row.edit = false
123 this.$message({
124 message: 'The title has been restored to the original value',
125 type: 'warning'
126 })
127 },
128 confirmEdit(row) {
129 row.edit = false
130 row.originalTitle = row.title
131 this.$message({
132 message: 'The title has been edited',
133 type: 'success'
134 })
135 }
136 }
137 }
138 </script>
139
140 <style scoped>
141 .edit-input {
142 padding-right: 100px;
143 }
144 .cancel-btn {
145 position: absolute;
146 right: 15px;
147 top: 10px;
148 }
149 </style>
150
src/views/theme/index.vue
File was created 1 <template>
2 <div class="app-container">
3 <el-card class="box-card">
4 <div slot="header">
5 <a class="link-type link-title" target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/guide/advanced/theme.html">
6 {{ $t('theme.documentation') }}
7 </a>
8 </div>
9 <div class="box-item">
10 <span class="field-label">{{ $t('theme.change') }} : </span>
11 <el-switch v-model="theme" />
12 <aside style="margin-top:15px;">{{ $t('theme.tips') }}</aside>
13 </div>
14 </el-card>
15
16 <div class="block">
17 <el-button type="primary">
18 Primary
19 </el-button>
20 <el-button type="success">
21 Success
22 </el-button>
23 <el-button type="info">
24 Info
25 </el-button>
26 <el-button type="warning">
27 Warning
28 </el-button>
29 <el-button type="danger">
30 Danger
31 </el-button>
32 </div>
33
34 <div class="block">
35 <el-button type="primary" icon="el-icon-edit" />
36 <el-button type="primary" icon="el-icon-share" />
37 <el-button type="primary" icon="el-icon-delete" />
38 <el-button type="primary" icon="el-icon-search">
39 Search
40 </el-button>
41 <el-button type="primary">
42 Upload
43 <i class="el-icon-upload el-icon-right" />
44 </el-button>
45 </div>
46
47 <div class="block">
48 <el-tag v-for="tag in tags" :key="tag.type" :type="tag.type" class="tag-item">
49 {{ tag.name }}
50 </el-tag>
51 </div>
52
53 <div class="block">
54 <el-radio-group v-model="radio">
55 <el-radio :label="3">
56 Option A
57 </el-radio>
58 <el-radio :label="6">
59 Option B
60 </el-radio>
61 <el-radio :label="9">
62 Option C
63 </el-radio>
64 </el-radio-group>
65 </div>
66
67 <div class="block">
68 <el-slider v-model="slideValue" />
69 </div>
70 </div>
71 </template>
72
73 <script>
74 import { toggleClass } from '@/utils'
75 import '@/assets/custom-theme/index.css' // the theme changed version element-ui css
76
77 export default {
78 name: 'Theme',
79 data() {
80 return {
81 theme: false,
82 tags: [
83 { name: 'Tag One', type: '' },
84 { name: 'Tag Two', type: 'info' },
85 { name: 'Tag Three', type: 'success' },
86 { name: 'Tag Four', type: 'warning' },
87 { name: 'Tag Five', type: 'danger' }
88 ],
89 slideValue: 50,
90 radio: 3
91 }
92 },
93 watch: {
94 theme() {
95 toggleClass(document.body, 'custom-theme')
96 }
97 }
98 }
99 </script>
100
101 <style scoped>
102 .field-label{
103 vertical-align: middle;
104 }
105 .box-card {
106 width: 400px;
107 max-width: 100%;
108 margin: 20px auto;
109 }
110
111 .block {
112 padding: 30px 24px;
113 }
114
115 .tag-item {
116 margin-right: 15px;
117 }
118 </style>
119
src/views/tree/index.vue
1 <template> File was deleted
2 <div class="app-container">
3 <el-input v-model="filterText" placeholder="Filter keyword" style="margin-bottom:30px;" />
4
5 <el-tree
6 ref="tree2"
7 :data="data2"
8 :props="defaultProps"
9 :filter-node-method="filterNode"
10 class="filter-tree"
11 default-expand-all
12 />
13
14 </div>
15 </template>
16
17 <script>
18 export default {
19
20 data() {
21 return {
22 filterText: '',
23 data2: [{
24 id: 1,
25 label: 'Level one 1',
26 children: [{
27 id: 4,
28 label: 'Level two 1-1',
29 children: [{
30 id: 9,
31 label: 'Level three 1-1-1'
32 }, {
33 id: 10,
34 label: 'Level three 1-1-2'
35 }]
36 }]
37 }, {
38 id: 2,
39 label: 'Level one 2',
40 children: [{
41 id: 5,
42 label: 'Level two 2-1'
43 }, {
44 id: 6,
45 label: 'Level two 2-2'
46 }]
47 }, {
48 id: 3,
49 label: 'Level one 3',
50 children: [{
51 id: 7,
52 label: 'Level two 3-1'
53 }, {
54 id: 8,
55 label: 'Level two 3-2'
56 }]
57 }],
58 defaultProps: {
59 children: 'children',
60 label: 'label'
61 }
62 }
63 },
64 watch: {
65 filterText(val) {
66 this.$refs.tree2.filter(val)
67 }
68 },
69
70 methods: {
71 filterNode(value, data) {
72 if (!value) return true
73 return data.label.indexOf(value) !== -1
74 }
75 }
76 }
77 </script>
78
79 1 <template>
src/views/zip/index.vue
File was created 1 <template>
2 <div class="app-container">
3 <!-- $t is vue-i18n global function to translate lang -->
4 <el-input v-model="filename" :placeholder="$t('zip.placeholder')" style="width:300px;" prefix-icon="el-icon-document" />
5 <el-button :loading="downloadLoading" style="margin-bottom:20px;" type="primary" icon="el-icon-document" @click="handleDownload">
6 {{ $t('zip.export') }} Zip
7 </el-button>
8 <el-table v-loading="listLoading" :data="list" element-loading-text="拼命加载中" border fit highlight-current-row>
9 <el-table-column align="center" label="ID" width="95">
10 <template slot-scope="scope">
11 {{ scope.$index }}
12 </template>
13 </el-table-column>
14 <el-table-column label="Title">
15 <template slot-scope="scope">
16 {{ scope.row.title }}
17 </template>
18 </el-table-column>
19 <el-table-column label="Author" width="95" align="center">
20 <template slot-scope="scope">
21 <el-tag>{{ scope.row.author }}</el-tag>
22 </template>
23 </el-table-column>
24 <el-table-column label="Readings" width="115" align="center">
25 <template slot-scope="scope">
26 {{ scope.row.pageviews }}
27 </template>
28 </el-table-column>
29 <el-table-column align="center" label="Date" width="220">
30 <template slot-scope="scope">
31 <i class="el-icon-time" />
32 <span>{{ scope.row.display_time }}</span>
33 </template>
34 </el-table-column>
35 </el-table>
36 </div>
37 </template>
38
39 <script>
40 import { fetchList } from '@/api/article'
41
42 export default {
43 name: 'ExportZip',
44 data() {
45 return {
46 list: null,
47 listLoading: true,
48 downloadLoading: false,
49 filename: ''
50 }
51 },
52 created() {
53 this.fetchData()
54 },
55 methods: {
56 async fetchData() {
57 this.listLoading = true
58 const { data } = await fetchList()
59 this.list = data.items
60 this.listLoading = false
61 },
62 handleDownload() {
63 this.downloadLoading = true
64 import('@/vendor/Export2Zip').then(zip => {
65 const tHeader = ['Id', 'Title', 'Author', 'Readings', 'Date']
66 const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
67 const list = this.list
68 const data = this.formatJson(filterVal, list)
69 zip.export_txt_to_zip(tHeader, data, this.filename, this.filename)
70 this.downloadLoading = false
71 })
72 },
73 formatJson(filterVal, jsonData) {
74 return jsonData.map(v => filterVal.map(j => v[j]))
75 }
76 }
77 }
78 </script>
79
tests/unit/.eslintrc.js 100644 → 100755
1 module.exports = { 1 module.exports = {
2 env: { 2 env: {
3 jest: true 3 jest: true
4 } 4 }
5 } 5 }
6 6
tests/unit/components/Breadcrumb.spec.js
1 import { mount, createLocalVue } from '@vue/test-utils' File was deleted
2 import VueRouter from 'vue-router'
3 import ElementUI from 'element-ui'
4 import Breadcrumb from '@/components/Breadcrumb/index.vue'
5
6 const localVue = createLocalVue()
7 localVue.use(VueRouter)
8 localVue.use(ElementUI)
9
10 const routes = [
11 {
12 path: '/',
13 name: 'home',
14 children: [{
15 path: 'dashboard',
16 name: 'dashboard'
17 }]
18 },
19 {
20 path: '/menu',
21 name: 'menu',
22 children: [{
23 path: 'menu1',
24 name: 'menu1',
25 meta: { title: 'menu1' },
26 children: [{
27 path: 'menu1-1',
28 name: 'menu1-1',
29 meta: { title: 'menu1-1' }
30 },
31 {
32 path: 'menu1-2',
33 name: 'menu1-2',
34 redirect: 'noredirect',
35 meta: { title: 'menu1-2' },
36 children: [{
37 path: 'menu1-2-1',
38 name: 'menu1-2-1',
39 meta: { title: 'menu1-2-1' }
40 },
41 {
42 path: 'menu1-2-2',
43 name: 'menu1-2-2'
44 }]
45 }]
46 }]
47 }]
48
49 const router = new VueRouter({
50 routes
51 })
52
53 describe('Breadcrumb.vue', () => {
54 const wrapper = mount(Breadcrumb, {
55 localVue,
56 router
57 })
58 it('dashboard', () => {
59 router.push('/dashboard')
60 const len = wrapper.findAll('.el-breadcrumb__inner').length
61 expect(len).toBe(1)
62 })
63 it('normal route', () => {
64 router.push('/menu/menu1')
65 const len = wrapper.findAll('.el-breadcrumb__inner').length
66 expect(len).toBe(2)
67 })
68 it('nested route', () => {
69 router.push('/menu/menu1/menu1-2/menu1-2-1')
70 const len = wrapper.findAll('.el-breadcrumb__inner').length
71 expect(len).toBe(4)
72 })
73 it('no meta.title', () => {
74 router.push('/menu/menu1/menu1-2/menu1-2-2')
75 const len = wrapper.findAll('.el-breadcrumb__inner').length
76 expect(len).toBe(3)
77 })
78 // it('click link', () => {
79 // router.push('/menu/menu1/menu1-2/menu1-2-2')
80 // const breadcrumbArray = wrapper.findAll('.el-breadcrumb__inner')
81 // const second = breadcrumbArray.at(1)
82 // console.log(breadcrumbArray)
83 // const href = second.find('a').attributes().href
84 // expect(href).toBe('#/menu/menu1')
85 // })
86 // it('noRedirect', () => {
87 // router.push('/menu/menu1/menu1-2/menu1-2-1')
88 // const breadcrumbArray = wrapper.findAll('.el-breadcrumb__inner')
89 // const redirectBreadcrumb = breadcrumbArray.at(2)
90 // expect(redirectBreadcrumb.contains('a')).toBe(false)
91 // })
92 it('last breadcrumb', () => {
93 router.push('/menu/menu1/menu1-2/menu1-2-1')
94 const breadcrumbArray = wrapper.findAll('.el-breadcrumb__inner')
95 const redirectBreadcrumb = breadcrumbArray.at(3)
96 expect(redirectBreadcrumb.contains('a')).toBe(false)
97 })
98 })
99 1 import { mount, createLocalVue } from '@vue/test-utils'
tests/unit/components/Hamburger.spec.js 100644 → 100755
1 import { shallowMount } from '@vue/test-utils' 1 import { shallowMount } from '@vue/test-utils'
2 import Hamburger from '@/components/Hamburger/index.vue' 2 import Hamburger from '@/components/Hamburger/index.vue'
3 describe('Hamburger.vue', () => { 3 describe('Hamburger.vue', () => {
4 it('toggle click', () => { 4 it('toggle click', () => {
5 const wrapper = shallowMount(Hamburger) 5 const wrapper = shallowMount(Hamburger)
6 const mockFn = jest.fn() 6 const mockFn = jest.fn()
7 wrapper.vm.$on('toggleClick', mockFn) 7 wrapper.vm.$on('toggleClick', mockFn)
8 wrapper.find('.hamburger').trigger('click') 8 wrapper.find('.hamburger').trigger('click')
9 expect(mockFn).toBeCalled() 9 expect(mockFn).toBeCalled()
10 }) 10 })
11 it('prop isActive', () => { 11 it('prop isActive', () => {
12 const wrapper = shallowMount(Hamburger) 12 const wrapper = shallowMount(Hamburger)
13 wrapper.setProps({ isActive: true }) 13 wrapper.setProps({ isActive: true })
14 expect(wrapper.contains('.is-active')).toBe(true) 14 expect(wrapper.contains('.is-active')).toBe(true)
15 wrapper.setProps({ isActive: false }) 15 wrapper.setProps({ isActive: false })
16 expect(wrapper.contains('.is-active')).toBe(false) 16 expect(wrapper.contains('.is-active')).toBe(false)
17 }) 17 })
18 }) 18 })
19 19
tests/unit/components/SvgIcon.spec.js 100644 → 100755
1 import { shallowMount } from '@vue/test-utils' 1 import { shallowMount } from '@vue/test-utils'
2 import SvgIcon from '@/components/SvgIcon/index.vue' 2 import SvgIcon from '@/components/SvgIcon/index.vue'
3 describe('SvgIcon.vue', () => { 3 describe('SvgIcon.vue', () => {
4 it('iconClass', () => { 4 it('iconClass', () => {
5 const wrapper = shallowMount(SvgIcon, { 5 const wrapper = shallowMount(SvgIcon, {
6 propsData: { 6 propsData: {
7 iconClass: 'test' 7 iconClass: 'test'
8 } 8 }
9 }) 9 })
10 expect(wrapper.find('use').attributes().href).toBe('#icon-test') 10 expect(wrapper.find('use').attributes().href).toBe('#icon-test')
11 }) 11 })
12 it('className', () => { 12 it('className', () => {
13 const wrapper = shallowMount(SvgIcon, { 13 const wrapper = shallowMount(SvgIcon, {
14 propsData: { 14 propsData: {
15 iconClass: 'test' 15 iconClass: 'test'
16 } 16 }
17 }) 17 })
18 expect(wrapper.classes().length).toBe(1) 18 expect(wrapper.classes().length).toBe(1)
19 wrapper.setProps({ className: 'test' }) 19 wrapper.setProps({ className: 'test' })
20 expect(wrapper.classes().includes('test')).toBe(true) 20 expect(wrapper.classes().includes('test')).toBe(true)
21 }) 21 })
22 }) 22 })
23 23
tests/unit/utils/formatTime.spec.js
1 import { formatTime } from '@/utils/index.js' 1 import { formatTime } from '@/utils/index.js'
2
3 describe('Utils:formatTime', () => { 2 describe('Utils:formatTime', () => {
4 const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01" 3 const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01"
5 const retrofit = 5 * 1000 4 const retrofit = 5 * 1000
6 5
7 it('ten digits timestamp', () => { 6 it('ten digits timestamp', () => {
8 expect(formatTime((d / 1000).toFixed(0))).toBe('7月13日17时54分') 7 expect(formatTime((d / 1000).toFixed(0))).toBe('7月13日17时54分')
9 }) 8 })
10 it('test now', () => { 9 it('test now', () => {
11 expect(formatTime(+new Date() - 1)).toBe('刚刚') 10 expect(formatTime(+new Date() - 1)).toBe('刚刚')
12 }) 11 })
13 it('less two minute', () => { 12 it('less two minute', () => {
14 expect(formatTime(+new Date() - 60 * 2 * 1000 + retrofit)).toBe('2分钟前') 13 expect(formatTime(+new Date() - 60 * 2 * 1000 + retrofit)).toBe('2分钟前')
15 }) 14 })
16 it('less two hour', () => { 15 it('less two hour', () => {
17 expect(formatTime(+new Date() - 60 * 60 * 2 * 1000 + retrofit)).toBe('2小时前') 16 expect(formatTime(+new Date() - 60 * 60 * 2 * 1000 + retrofit)).toBe('2小时前')
18 }) 17 })
19 it('less one day', () => { 18 it('less one day', () => {
20 expect(formatTime(+new Date() - 60 * 60 * 24 * 1 * 1000)).toBe('1天前') 19 expect(formatTime(+new Date() - 60 * 60 * 24 * 1 * 1000)).toBe('1天前')
21 }) 20 })
22 it('more than one day', () => { 21 it('more than one day', () => {
23 expect(formatTime(d)).toBe('7月13日17时54分') 22 expect(formatTime(d)).toBe('7月13日17时54分')
24 }) 23 })
25 it('format', () => { 24 it('format', () => {
26 expect(formatTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54') 25 expect(formatTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54')
27 expect(formatTime(d, '{y}-{m}-{d}')).toBe('2018-07-13') 26 expect(formatTime(d, '{y}-{m}-{d}')).toBe('2018-07-13')
28 expect(formatTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54') 27 expect(formatTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54')
29 }) 28 })
30 }) 29 })
31 30
tests/unit/utils/parseTime.spec.js
1 import { parseTime } from '@/utils/index.js' 1 import { parseTime } from '@/utils/index.js'
2
3 describe('Utils:parseTime', () => { 2 describe('Utils:parseTime', () => {
4 const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01" 3 const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01"
5 it('timestamp', () => { 4 it('timestamp', () => {
6 expect(parseTime(d)).toBe('2018-07-13 17:54:01') 5 expect(parseTime(d)).toBe('2018-07-13 17:54:01')
7 }) 6 })
8 it('ten digits timestamp', () => { 7 it('ten digits timestamp', () => {
9 expect(parseTime((d / 1000).toFixed(0))).toBe('2018-07-13 17:54:01') 8 expect(parseTime((d / 1000).toFixed(0))).toBe('2018-07-13 17:54:01')
10 }) 9 })
11 it('new Date', () => { 10 it('new Date', () => {
12 expect(parseTime(new Date(d))).toBe('2018-07-13 17:54:01') 11 expect(parseTime(new Date(d))).toBe('2018-07-13 17:54:01')
13 }) 12 })
14 it('format', () => { 13 it('format', () => {
15 expect(parseTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54') 14 expect(parseTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54')
16 expect(parseTime(d, '{y}-{m}-{d}')).toBe('2018-07-13') 15 expect(parseTime(d, '{y}-{m}-{d}')).toBe('2018-07-13')
17 expect(parseTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54') 16 expect(parseTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54')
18 }) 17 })
19 it('get the day of the week', () => { 18 it('get the day of the week', () => {
20 expect(parseTime(d, '{a}')).toBe('五') // 星期五 19 expect(parseTime(d, '{a}')).toBe('五') // 星期五
21 }) 20 })
22 it('get the day of the week', () => { 21 it('get the day of the week', () => {
23 expect(parseTime(+d + 1000 * 60 * 60 * 24 * 2, '{a}')).toBe('日') // 星期日 22 expect(parseTime(+d + 1000 * 60 * 60 * 24 * 2, '{a}')).toBe('日') // 星期日
24 }) 23 })
25 it('empty argument', () => { 24 it('empty argument', () => {
26 expect(parseTime()).toBeNull() 25 expect(parseTime()).toBeNull()
27 }) 26 })
28 }) 27 })
29 28
tests/unit/utils/validate.spec.js
1 import { validUsername, isExternal } from '@/utils/validate.js' 1 import { validUsername, validURL, validLowerCase, validUpperCase, validAlphabets } from '@/utils/validate.js'
2
3 describe('Utils:validate', () => { 2 describe('Utils:validate', () => {
4 it('validUsername', () => { 3 it('validUsername', () => {
5 expect(validUsername('admin')).toBe(true) 4 expect(validUsername('admin')).toBe(true)
6 expect(validUsername('editor')).toBe(true) 5 expect(validUsername('editor')).toBe(true)
7 expect(validUsername('xxxx')).toBe(false) 6 expect(validUsername('xxxx')).toBe(false)
8 }) 7 })
9 it('isExternal', () => { 8 it('validURL', () => {
10 expect(isExternal('https://github.com/PanJiaChen/vue-element-admin')).toBe(true) 9 expect(validURL('https://github.com/PanJiaChen/vue-element-admin')).toBe(true)
11 expect(isExternal('http://github.com/PanJiaChen/vue-element-admin')).toBe(true) 10 expect(validURL('http://github.com/PanJiaChen/vue-element-admin')).toBe(true)
12 expect(isExternal('github.com/PanJiaChen/vue-element-admin')).toBe(false) 11 expect(validURL('github.com/PanJiaChen/vue-element-admin')).toBe(false)
13 expect(isExternal('/dashboard')).toBe(false) 12 })
14 expect(isExternal('./dashboard')).toBe(false) 13 it('validLowerCase', () => {
15 expect(isExternal('dashboard')).toBe(false) 14 expect(validLowerCase('abc')).toBe(true)
15 expect(validLowerCase('Abc')).toBe(false)
16 expect(validLowerCase('123abc')).toBe(false)
17 })
18 it('validUpperCase', () => {
19 expect(validUpperCase('ABC')).toBe(true)
20 expect(validUpperCase('Abc')).toBe(false)
21 expect(validUpperCase('123ABC')).toBe(false)
22 })
23 it('validAlphabets', () => {
24 expect(validAlphabets('ABC')).toBe(true)
25 expect(validAlphabets('Abc')).toBe(true)
26 expect(validAlphabets('123aBC')).toBe(false)
16 }) 27 })
17 }) 28 })
1 'use strict' 1 'use strict'
2 const path = require('path') 2 const path = require('path')
3 const defaultSettings = require('./src/settings.js') 3 const defaultSettings = require('./src/settings.js')
4 4
5 function resolve(dir) { 5 function resolve(dir) {
6 return path.join(__dirname, dir) 6 return path.join(__dirname, dir)
7 } 7 }
8 8
9 const name = defaultSettings.title || 'vue Admin Template' // page title 9 const name = defaultSettings.title || 'vue Element Admin' // page title
10 10
11 // If your port is set to 80, 11 // If your port is set to 80,
12 // use administrator privileges to execute the command line. 12 // use administrator privileges to execute the command line.
13 // For example, Mac: sudo npm run 13 // For example, Mac: sudo npm run
14 // You can change the port by the following methods: 14 // You can change the port by the following method:
15 // port = 9528 npm run dev OR npm run dev --port = 9528 15 // port = 9527 npm run dev OR npm run dev --port = 9527
16 const port = process.env.port || process.env.npm_config_port || 9528 // dev port 16 const port = process.env.port || process.env.npm_config_port || 9527 // dev port
17 17
18 // All configuration item explanations can be find in https://cli.vuejs.org/config/ 18 // All configuration item explanations can be find in https://cli.vuejs.org/config/
19 module.exports = { 19 module.exports = {
20 /** 20 /**
21 * You will need to set publicPath if you plan to deploy your site under a sub path, 21 * You will need to set publicPath if you plan to deploy your site under a sub path,
22 * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/, 22 * for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
23 * then publicPath should be set to "/bar/". 23 * then publicPath should be set to "/bar/".
24 * In most cases please use '/' !!! 24 * In most cases please use '/' !!!
25 * Detail: https://cli.vuejs.org/config/#publicpath 25 * Detail: https://cli.vuejs.org/config/#publicpath
26 */ 26 */
27 publicPath: '/', 27 publicPath: '/',
28 outputDir: 'dist', 28 outputDir: 'dist',
29 assetsDir: 'static', 29 assetsDir: 'static',
30 lintOnSave: process.env.NODE_ENV === 'development', 30 lintOnSave: process.env.NODE_ENV === 'development',
31 productionSourceMap: false, 31 productionSourceMap: false,
32 devServer: { 32 devServer: {
33 port: port, 33 port: port,
34 open: true, 34 open: true,
35 overlay: { 35 overlay: {
36 warnings: false, 36 warnings: false,
37 errors: true 37 errors: true
38 }, 38 },
39 //线下API测试时,可以去掉这个Mock数据。
40 before: require('./mock/mock-server.js') 39 before: require('./mock/mock-server.js')
41 }, 40 },
42 configureWebpack: { 41 configureWebpack: {
43 // provide the app's title in webpack's name field, so that 42 // provide the app's title in webpack's name field, so that
44 // it can be accessed in index.html to inject the correct title. 43 // it can be accessed in index.html to inject the correct title.
45 name: name, 44 name: name,
46 resolve: { 45 resolve: {
47 alias: { 46 alias: {
48 '@': resolve('src') 47 '@': resolve('src')
49 } 48 }
50 } 49 }
51 }, 50 },
52 chainWebpack(config) { 51 chainWebpack(config) {
53 config.plugins.delete('preload') // TODO: need test 52 config.plugins.delete('preload') // TODO: need test
54 config.plugins.delete('prefetch') // TODO: need test 53 config.plugins.delete('prefetch') // TODO: need test
55 54
56 // set svg-sprite-loader 55 // set svg-sprite-loader
57 config.module 56 config.module
58 .rule('svg') 57 .rule('svg')
59 .exclude.add(resolve('src/icons')) 58 .exclude.add(resolve('src/icons'))
60 .end() 59 .end()
61 config.module 60 config.module
62 .rule('icons') 61 .rule('icons')
63 .test(/\.svg$/) 62 .test(/\.svg$/)
64 .include.add(resolve('src/icons')) 63 .include.add(resolve('src/icons'))
65 .end() 64 .end()
66 .use('svg-sprite-loader') 65 .use('svg-sprite-loader')
67 .loader('svg-sprite-loader') 66 .loader('svg-sprite-loader')
68 .options({ 67 .options({
69 symbolId: 'icon-[name]' 68 symbolId: 'icon-[name]'
70 }) 69 })
71 .end() 70 .end()
72 71
73 // set preserveWhitespace 72 // set preserveWhitespace
74 config.module 73 config.module
75 .rule('vue') 74 .rule('vue')
76 .use('vue-loader') 75 .use('vue-loader')
77 .loader('vue-loader') 76 .loader('vue-loader')
78 .tap(options => { 77 .tap(options => {
79 options.compilerOptions.preserveWhitespace = true 78 options.compilerOptions.preserveWhitespace = true
80 return options 79 return options
81 }) 80 })
82 .end() 81 .end()
83 82
84 config 83 config
85 // https://webpack.js.org/configuration/devtool/#development 84 // https://webpack.js.org/configuration/devtool/#development
86 .when(process.env.NODE_ENV === 'development', 85 .when(process.env.NODE_ENV === 'development',
87 config => config.devtool('cheap-source-map') 86 config => config.devtool('cheap-source-map')
88 ) 87 )
89 88
90 config 89 config
91 .when(process.env.NODE_ENV !== 'development', 90 .when(process.env.NODE_ENV !== 'development',
92 config => { 91 config => {
93 config 92 config
94 .plugin('ScriptExtHtmlWebpackPlugin') 93 .plugin('ScriptExtHtmlWebpackPlugin')
95 .after('html') 94 .after('html')
96 .use('script-ext-html-webpack-plugin', [{ 95 .use('script-ext-html-webpack-plugin', [{
97 // `runtime` must same as runtimeChunk name. default is `runtime` 96 // `runtime` must same as runtimeChunk name. default is `runtime`
98 inline: /runtime\..*\.js$/ 97 inline: /runtime\..*\.js$/
99 }]) 98 }])
100 .end() 99 .end()
101 config 100 config
102 .optimization.splitChunks({ 101 .optimization.splitChunks({
103 chunks: 'all', 102 chunks: 'all',
104 cacheGroups: { 103 cacheGroups: {
105 libs: { 104 libs: {
106 name: 'chunk-libs', 105 name: 'chunk-libs',
107 test: /[\\/]node_modules[\\/]/, 106 test: /[\\/]node_modules[\\/]/,
108 priority: 10, 107 priority: 10,
109 chunks: 'initial' // only package third parties that are initially dependent 108 chunks: 'initial' // only package third parties that are initially dependent
110 }, 109 },
111 elementUI: { 110 elementUI: {
112 name: 'chunk-elementUI', // split elementUI into a single package 111 name: 'chunk-elementUI', // split elementUI into a single package
113 priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app 112 priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
114 test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm 113 test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
115 }, 114 },
116 commons: { 115 commons: {
117 name: 'chunk-commons', 116 name: 'chunk-commons',
118 test: resolve('src/components'), // can customize your rules 117 test: resolve('src/components'), // can customize your rules
119 minChunks: 3, // minimum common number 118 minChunks: 3, // minimum common number
120 priority: 5, 119 priority: 5,
121 reuseExistingChunk: true 120 reuseExistingChunk: true
122 } 121 }
123 } 122 }
124 }) 123 })
125 config.optimization.runtimeChunk('single') 124 config.optimization.runtimeChunk('single')
126 } 125 }
127 ) 126 )
128 } 127 }
129 } 128 }
130 129