Compare commits
204 Commits
perf/keep-
...
v3.9.1
Author | SHA1 | Date | |
---|---|---|---|
|
90d3e314c0 | ||
|
4780ac334f | ||
|
b0bd91cd0f | ||
|
ae2754a568 | ||
|
6e07d18b1d | ||
|
f58db95be5 | ||
|
616b65c238 | ||
|
68cd051bb6 | ||
|
935d9aaba8 | ||
|
616f173aab | ||
|
d1cceb69b7 | ||
|
ff13ee1f27 | ||
|
dc84e7b9fb | ||
|
b82e8e860d | ||
|
98a8277a37 | ||
|
63ff44f8e5 | ||
|
dd5646ffbc | ||
|
371c8504c2 | ||
|
87b319d96a | ||
|
4c49259c92 | ||
|
83516aeb17 | ||
|
24602755cd | ||
|
11163146c0 | ||
|
3277343804 | ||
|
0740bb36f7 | ||
|
9c03dd3514 | ||
|
fbb3641406 | ||
|
f85b044ff8 | ||
|
ed4427243d | ||
|
9c5352ecd6 | ||
|
62fb5d1e14 | ||
|
14e693339c | ||
|
c58bce603b | ||
|
fa54b927f7 | ||
|
ba6bf3e217 | ||
|
6ecf8b820a | ||
|
a5dd905b46 | ||
|
676aaf3485 | ||
|
44e4bddc21 | ||
|
a03d1edac6 | ||
|
2938e33d0e | ||
|
2fb26525fa | ||
|
d0d1addba8 | ||
|
0fe3f181ad | ||
|
68de01e828 | ||
|
6e569c4f4a | ||
|
0fbda3c8c7 | ||
|
5bbb4abe21 | ||
|
1e50d4a93b | ||
|
ccf1791fca | ||
|
325120b653 | ||
|
2e1f36fe00 | ||
|
00d292f67e | ||
|
0e75dcc42a | ||
|
189e645b23 | ||
|
d5a8fb1e71 | ||
|
b2570f891d | ||
|
4035bf58f2 | ||
|
e5d4290938 | ||
|
8f58baf617 | ||
|
fded36c990 | ||
|
53f3e7d5e6 | ||
|
93e01b64d4 | ||
|
a871e147d6 | ||
|
378ca2c217 | ||
|
1df59cc4b6 | ||
|
312a2ca8ed | ||
|
f3733c0b37 | ||
|
0ef14ff5c6 | ||
|
c57c6045c9 | ||
|
fe190b6188 | ||
|
48a966fe1c | ||
|
63d39727ac | ||
|
1e0b9c0055 | ||
|
5f20bfc780 | ||
|
8851a68066 | ||
|
878628b0ed | ||
|
e254fc6c1a | ||
|
513eb66d97 | ||
|
62e1c851c8 | ||
|
f0a01f0fd1 | ||
|
aa7eab58f9 | ||
|
77cb6b1f43 | ||
|
5fbf1cf5da | ||
|
6a5197ad51 | ||
|
9b7a9a64e5 | ||
|
89ce53e185 | ||
|
9e04f58163 | ||
|
d98c5032f8 | ||
|
a575670cef | ||
|
44fa96f142 | ||
|
e4481a9d34 | ||
|
572a2d9c34 | ||
|
5070e20dea | ||
|
59789d92cf | ||
|
775f6f5f3a | ||
|
2687b2eb3c | ||
|
76327a8f26 | ||
|
03b708870b | ||
|
bdc31cea1a | ||
|
ae2ca072f5 | ||
|
d995cdb332 | ||
|
cbc3ddd827 | ||
|
9cf00fd63a | ||
|
03691739e1 | ||
|
3f479664b6 | ||
|
cbee7b6f20 | ||
|
2a590a2087 | ||
|
c93fcefe54 | ||
|
9f8ac37497 | ||
|
8c685cc4c6 | ||
|
e40fd27775 | ||
|
f3ccd9f04e | ||
|
914a4ec62c | ||
|
739aef4387 | ||
|
a7942636c6 | ||
|
31d9da8b9f | ||
|
600e75d0a2 | ||
|
9ba1ea6933 | ||
|
320e941d9a | ||
|
d0f6d3f1f6 | ||
|
0375542009 | ||
|
03e5f762b3 | ||
|
bd0227feed | ||
|
20aad46416 | ||
|
4fc25241fe | ||
|
6327869106 | ||
|
c861dd10cf | ||
|
0a196f79ba | ||
|
d2d323bb02 | ||
|
66613f0373 | ||
|
6795c26d02 | ||
|
597df4844a | ||
|
1e103cf151 | ||
|
99d53ee0ca | ||
|
f9d510ea78 | ||
|
9fbb028124 | ||
|
9b5f0160af | ||
|
0e4ea0871c | ||
|
88429bd809 | ||
|
62a9565f86 | ||
|
f663b23b29 | ||
|
afd255d5ba | ||
|
b7c8079350 | ||
|
543a9928cf | ||
|
8f37950589 | ||
|
6821eac35b | ||
|
cc5e62d5f5 | ||
|
0cccc636b8 | ||
|
563ce873bd | ||
|
44e94b2d16 | ||
|
a160848367 | ||
|
7099e6a3eb | ||
|
14fee27a92 | ||
|
7003a79ef6 | ||
|
c5faa63ee5 | ||
|
d29a9486a2 | ||
|
01442ce4d7 | ||
|
f28a7149fb | ||
|
51ad902d8f | ||
|
3cff6dcf4c | ||
|
afe975b3c2 | ||
|
d0eebf83c4 | ||
|
a55b149b27 | ||
|
fc19121311 | ||
|
de06619266 | ||
|
88c28f5d7e | ||
|
26b84847dd | ||
|
3cc3e134c2 | ||
|
2afb1dfabb | ||
|
5fe3d70246 | ||
|
4aa9345d90 | ||
|
0fcbf4b53b | ||
|
8142c06a99 | ||
|
c398ee0ddc | ||
|
a633729215 | ||
|
f9c4dd7af3 | ||
|
5f4ce7fc71 | ||
|
01928cd4ec | ||
|
27effcc54c | ||
|
7cacd5a4ac | ||
|
31b7fa6f55 | ||
|
2cb6211cd6 | ||
|
ebb0b4a0ff | ||
|
c356695f2e | ||
|
112e3b977c | ||
|
ae41459cb1 | ||
|
aa592cfb69 | ||
|
9205a85c2d | ||
|
6938dd3caf | ||
|
398d59d78a | ||
|
dc35d1ae92 | ||
|
2f411b870c | ||
|
305d659431 | ||
|
55c08ab666 | ||
|
09e613b33a | ||
|
c0ed44932e | ||
|
a48a1bd8be | ||
|
55e8cd5306 | ||
|
dc9e27e4b1 | ||
|
d754eae662 | ||
|
94ae1f8719 | ||
|
48070e5abf | ||
|
eef99d3d14 |
7
.babelrc
@@ -8,5 +8,10 @@
|
||||
}],
|
||||
"stage-2"
|
||||
],
|
||||
"plugins": ["transform-vue-jsx", "transform-runtime"]
|
||||
"plugins": ["transform-vue-jsx", "transform-runtime"],
|
||||
"env": {
|
||||
"development":{
|
||||
"plugins": ["dynamic-import-node"]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
28
.eslintrc.js
@@ -1,7 +1,7 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
parser: 'babel-eslint',
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint',
|
||||
sourceType: 'module'
|
||||
},
|
||||
env: {
|
||||
@@ -9,22 +9,19 @@ module.exports = {
|
||||
node: true,
|
||||
es6: true,
|
||||
},
|
||||
extends: 'eslint:recommended',
|
||||
// required to lint *.vue files
|
||||
plugins: [
|
||||
'html'
|
||||
],
|
||||
// check if imports actually resolve
|
||||
'settings': {
|
||||
'import/resolver': {
|
||||
'webpack': {
|
||||
'config': 'build/webpack.base.conf.js'
|
||||
}
|
||||
}
|
||||
},
|
||||
extends: ['plugin:vue/recommended', 'eslint:recommended'],
|
||||
|
||||
// add your custom rules here
|
||||
//it is base on https://github.com/vuejs/eslint-config-vue
|
||||
'rules': {
|
||||
rules: {
|
||||
"vue/max-attributes-per-line": [2, {
|
||||
"singleline": 10,
|
||||
"multiline": {
|
||||
"max": 1,
|
||||
"allowFirstLine": false
|
||||
}
|
||||
}],
|
||||
"vue/name-property-casing": ["error", "PascalCase"],
|
||||
'accessor-pairs': 2,
|
||||
'arrow-spacing': [2, {
|
||||
'before': true,
|
||||
@@ -196,4 +193,3 @@ module.exports = {
|
||||
'array-bracket-spacing': [2, 'never']
|
||||
}
|
||||
}
|
||||
|
||||
|
2
.gitignore
vendored
@@ -1,10 +1,10 @@
|
||||
.DS_Store
|
||||
node_modules/
|
||||
dist/
|
||||
gifs/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
**/*.log
|
||||
|
||||
test/unit/coverage
|
||||
test/e2e/reports
|
||||
|
170
README.md
@@ -3,99 +3,141 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/vuejs/vue">
|
||||
<img src="https://img.shields.io/badge/vue-2.5.10-brightgreen.svg" alt="vue">
|
||||
</a>
|
||||
<a href="https://github.com/ElemeFE/element">
|
||||
<img src="https://img.shields.io/badge/element--ui-2.0.8-brightgreen.svg" alt="element-ui">
|
||||
</a>
|
||||
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
|
||||
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
|
||||
</a>
|
||||
<a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
|
||||
</a>
|
||||
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
|
||||
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
|
||||
</a>
|
||||
<a href="https://github.com/vuejs/vue">
|
||||
<img src="https://img.shields.io/badge/vue-2.5.17-brightgreen.svg" alt="vue">
|
||||
</a>
|
||||
<a href="https://github.com/ElemeFE/element">
|
||||
<img src="https://img.shields.io/badge/element--ui-2.4.6-brightgreen.svg" alt="element-ui">
|
||||
</a>
|
||||
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
|
||||
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
|
||||
</a>
|
||||
<a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
|
||||
</a>
|
||||
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
|
||||
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
|
||||
</a>
|
||||
<a href="https://gitter.im/vue-element-admin/discuss">
|
||||
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="gitter">
|
||||
</a>
|
||||
<a href="https://panjiachen.github.io/vue-element-admin-site/donate">
|
||||
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
English | [简体中文](./README.zh-CN.md)
|
||||
|
||||
## Introduction
|
||||
|
||||
`vue-element-admin` is a production-ready solution for admin interfaces. Based on [Vue.js](https://github.com/vuejs/vue) and use the UI Toolkit -- [element](https://github.com/ElemeFE/element). `vue-element-admin` is a magical vue admin, it based on the newest development stack of vue, built-in i18n solution, typical templates for enterprise applications, lots of awesome features. It helps you build a large complex Single-Page Applications. I believe whatever your needs are, this project will help you.
|
||||
[vue-element-admin](http://panjiachen.github.io/vue-element-admin) is a front-end management background integration solution. It based on [vue](https://github.com/vuejs/vue) and use the UI Toolkit [element](https://github.com/ElemeFE/element).
|
||||
|
||||
It is a magical vue admin based on the newest development stack of vue, built-in i18n solution, typical templates for enterprise applications, lots of awesome features. It helps you build a large complex Single-Page Applications. I believe whatever your needs are, this project will help you.
|
||||
|
||||
- [Preview](http://panjiachen.github.io/vue-element-admin)
|
||||
|
||||
- [Documentation](https://panjiachen.github.io/vue-element-admin-site/#/)
|
||||
- [Documentation](https://panjiachen.github.io/vue-element-admin-site/)
|
||||
|
||||
- [wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
||||
- [Gitter](https://gitter.im/vue-element-admin/discuss)
|
||||
|
||||
- [donate](https://panjiachen.github.io/vue-element-admin-site/#/donate)
|
||||
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
||||
|
||||
**vue-element-admin is a admin interfaces integration solution, which is not suitable for secondary development as a base template.**
|
||||
- [Donate](https://panjiachen.github.io/vue-element-admin-site/donate/)
|
||||
|
||||
- Base template recommends using: [vueAdmin-template](https://github.com/PanJiaChen/vueAdmin-template)
|
||||
- Desktop: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
||||
- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览
|
||||
|
||||
**Note: This project uses element-ui@2.0.0+ version, so the minimum compatible vue@2.5.0**
|
||||
**This project is positioned as a background integration solution and is not suitable for secondary development as a basic template.**
|
||||
|
||||
- Base template recommends using: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
|
||||
- Desktop: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
||||
- Typescript: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Credits: [@Armour](https://github.com/Armour))
|
||||
|
||||
**This project does not support low version browsers (e.g. IE). Please add polyfill yourself if you need them.**
|
||||
|
||||
**Note: This project uses element-ui@2.3.0+ version, so the minimum compatible vue@2.5.0+**
|
||||
|
||||
**Start using `webpack4` from `v3.8.0`. If you still want to continue using `webpack3`, please use this branch [webpack3](https://github.com/PanJiaChen/vue-element-admin/tree/webpack3)**
|
||||
|
||||
## Preparation
|
||||
|
||||
You need to install [node](http://nodejs.org/) and [git](https://git-scm.com/) locally. The project is based on [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/) 和 [element-ui](https://github.com/ElemeFE/element). All data requests for this project are simulated using [Mock.js](https://github.com/nuysoft/Mock). It would be helpful if you have pre-existing knowledge on those.
|
||||
You need to install [node](http://nodejs.org/) and [git](https://git-scm.com/) locally. The project is based on [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/), [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).
|
||||
Understanding and learning this knowledge in advance will greatly help the use of this project.
|
||||
|
||||
**This project is not a scaffolding and is more of an integrated solution.**
|
||||
|
||||
**This project does not support low version browsers (e.g. IE). Please add polyfill yourself if you need them.**
|
||||
---
|
||||
|
||||
<p align="center">
|
||||
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
|
||||
</p>
|
||||
|
||||
## Features
|
||||
|
||||
```
|
||||
- Login / Logout
|
||||
- Permission authentication
|
||||
|
||||
- Permission Authentication
|
||||
- Page permission
|
||||
- Directive permission
|
||||
- Two-step login
|
||||
|
||||
- Multi-environment build
|
||||
- Dynamic sidebar (supports multi-level routing)
|
||||
- Dynamic breadcrumb
|
||||
- I18n
|
||||
- Customizable theme
|
||||
- Tags-view(Tab page Support right-click operation)
|
||||
- Rich text editor
|
||||
- Markdown editor
|
||||
- JSON editor
|
||||
- Screenfull
|
||||
- Drag and drop list
|
||||
- Svg Sprite
|
||||
- dev sit stage prod
|
||||
|
||||
- Global Features
|
||||
- I18n
|
||||
- Multiple dynamic themes
|
||||
- Dynamic sidebar (supports multi-level routing)
|
||||
- Dynamic breadcrumb
|
||||
- Tags-view(Tab page Support right-click operation)
|
||||
- Svg Sprite
|
||||
- Mock data
|
||||
- Screenfull
|
||||
- Responsive Sidebar
|
||||
|
||||
- Editor
|
||||
- Rich Text Editor
|
||||
- Markdown Editor
|
||||
- JSON Editor
|
||||
|
||||
- Excel
|
||||
- Export Excel
|
||||
- Export zip
|
||||
- Upload Excel
|
||||
- Visualization Excel
|
||||
|
||||
- Table
|
||||
- Dynamic Table
|
||||
- Drag And Drop Table
|
||||
- Tree Table
|
||||
- Inline Edit Table
|
||||
|
||||
- Error Page
|
||||
- 401
|
||||
- 404
|
||||
|
||||
- Components
|
||||
- Avatar Upload
|
||||
- Back To Top
|
||||
- Drag Dialog
|
||||
- Drag Kanban
|
||||
- Drag List
|
||||
- SplitPane
|
||||
- Dropzone
|
||||
- Sticky
|
||||
- CountTo
|
||||
|
||||
- Advanced Example
|
||||
- Error Log
|
||||
- Dashboard
|
||||
- Mock data
|
||||
- Echarts
|
||||
- Guide Page
|
||||
- ECharts
|
||||
- Clipboard
|
||||
- 401/404 error page
|
||||
- Error log
|
||||
- Export excel
|
||||
- Export zip
|
||||
- Front-end visualization excel
|
||||
- Tree Table
|
||||
- Table example
|
||||
- Dynamictable example
|
||||
- Drag and drop table example
|
||||
- Inline edit table example
|
||||
- Form example
|
||||
- Two-step login
|
||||
- SplitPane
|
||||
- Dropzone
|
||||
- Sticky
|
||||
- CountTo
|
||||
- Markdown to html
|
||||
```
|
||||
|
||||
## Getting started
|
||||
|
||||
```bash
|
||||
# clone the projice
|
||||
# clone the project
|
||||
git clone https://github.com/PanJiaChen/vue-element-admin.git
|
||||
|
||||
# install dependency
|
||||
@@ -108,6 +150,7 @@ npm run dev
|
||||
This will automatically open http://localhost:9527.
|
||||
|
||||
## Build
|
||||
|
||||
```bash
|
||||
# build for test environment
|
||||
npm run build:sit
|
||||
@@ -117,10 +160,14 @@ npm run build:prod
|
||||
```
|
||||
|
||||
## Advanced
|
||||
|
||||
```bash
|
||||
# --report to build with bundle size analytics
|
||||
npm run build:prod --report
|
||||
|
||||
# --generate a bundle size analytics. default: bundle-report.html
|
||||
npm run build:prod --generate_report
|
||||
|
||||
# --preview to start a server in local to preview
|
||||
npm run build:prod --preview
|
||||
|
||||
@@ -131,21 +178,26 @@ npm run lint
|
||||
npm run lint -- --fix
|
||||
```
|
||||
|
||||
Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/#/deploy) for more information
|
||||
Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information
|
||||
|
||||
## Changelog
|
||||
|
||||
Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
|
||||
|
||||
## Online Demo
|
||||
|
||||
[Preview](http://panjiachen.github.io/vue-element-admin)
|
||||
|
||||
## Donate
|
||||
|
||||
If you find this project useful, you can buy author a glass of juice :tropical_drink:
|
||||
|
||||

|
||||
|
||||
[Paypal Me](https://www.paypal.me/panfree23)
|
||||
|
||||
[Buy me a coffee](https://www.buymeacoffee.com/Pan)
|
||||
|
||||
## License
|
||||
|
||||
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
|
||||
|
197
README.zh-CN.md
@@ -3,137 +3,185 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/vuejs/vue">
|
||||
<img src="https://img.shields.io/badge/vue-2.5.10-brightgreen.svg" alt="vue">
|
||||
</a>
|
||||
<a href="https://github.com/ElemeFE/element">
|
||||
<img src="https://img.shields.io/badge/element--ui-2.0.8-brightgreen.svg" alt="element-ui">
|
||||
</a>
|
||||
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
|
||||
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
|
||||
</a>
|
||||
<a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
|
||||
</a>
|
||||
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
|
||||
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
|
||||
</a>
|
||||
<a href="https://github.com/vuejs/vue">
|
||||
<img src="https://img.shields.io/badge/vue-2.5.10-brightgreen.svg" alt="vue">
|
||||
</a>
|
||||
<a href="https://github.com/ElemeFE/element">
|
||||
<img src="https://img.shields.io/badge/element--ui-2.3.2-brightgreen.svg" alt="element-ui">
|
||||
</a>
|
||||
<a href="https://travis-ci.org/PanJiaChen/vue-element-admin" rel="nofollow">
|
||||
<img src="https://travis-ci.org/PanJiaChen/vue-element-admin.svg?branch=master" alt="Build Status">
|
||||
</a>
|
||||
<a href="https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/mashape/apistatus.svg" alt="license">
|
||||
</a>
|
||||
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
|
||||
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
|
||||
</a>
|
||||
<a href="https://gitter.im/vue-element-admin/discuss">
|
||||
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="gitter">
|
||||
</a>
|
||||
<a href="https://panjiachen.gitee.io/vue-element-admin-site/zh/donate">
|
||||
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
简体中文 | [English](./README.md)
|
||||
|
||||
## 简介
|
||||
|
||||
`vue-element-admin` 是一个后台集成解决方案,它基于 [Vue.js](https://github.com/vuejs/vue) 和 [element](https://github.com/ElemeFE/element)。它使用了最新的前端技术栈,内置了i18国际化解决方案,动态路由,权限验证等很多功能特性,相信不管你的需求是什么,本项目都能帮助到你。
|
||||
[vue-element-admin](http://panjiachen.github.io/vue-element-admin) 是一个后台集成解决方案,它基于 [vue](https://github.com/vuejs/vue) 和 [element](https://github.com/ElemeFE/element)。它使用了最新的前端技术栈,内置了 i18 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。
|
||||
|
||||
- [在线访问](http://panjiachen.github.io/vue-element-admin)
|
||||
|
||||
- [使用文档](https://panjiachen.github.io/vue-element-admin-site/#/)
|
||||
- [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
|
||||
|
||||
- [wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
||||
- [Gitter 讨论组](https://gitter.im/vue-element-admin/discuss)
|
||||
|
||||
- [donate](https://panjiachen.github.io/vue-element-admin-site/#/donate)
|
||||
- [Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
|
||||
|
||||
- [Donate](https://panjiachen.github.io/vue-element-admin-site/zh/donate/)
|
||||
|
||||
- [Gitee](https://panjiachen.gitee.io/vue-element-admin/) 国内用户可访问该地址在线预览
|
||||
|
||||
- [国内访问文档](https://panjiachen.gitee.io/vue-element-admin-site/zh/) 方便没翻墙的用户查看文档
|
||||
|
||||
**本项目的定位是后台集成方案,不适合当基础模板来开发。**
|
||||
- 模板建议使用: [vueAdmin-template](https://github.com/PanJiaChen/vueAdmin-template)
|
||||
- 桌面端: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
||||
|
||||
**注意:该项目使用 element-ui@2.0.0+ 版本,所以最低兼容 vue@2.5.0**
|
||||
- 模板建议使用: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
|
||||
- 桌面端: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
|
||||
- Typescript版: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (鸣谢: [@Armour](https://github.com/Armour))
|
||||
|
||||
群主 **[圈子](https://jianshiapp.com/circles/1209)** 楼主会经常分享一些技术相关的东西,或者加入[qq 群](https://github.com/PanJiaChen/vue-element-admin/issues/602)
|
||||
|
||||
**注意:该项目使用 element-ui@2.3.0+ 版本,所以最低兼容 vue@2.5.0+**
|
||||
|
||||
**从`v3.8.0`开始使用`webpack4`。所以若还想使用`webpack3`开发,请使用该分支[webpack3](https://github.com/PanJiaChen/vue-element-admin/tree/webpack3)**
|
||||
|
||||
**该项目不支持低版本浏览器(如 ie),有需求请自行添加 polyfill [详情](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**
|
||||
|
||||
## 前序准备
|
||||
|
||||
你的本地环境需要安装 [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/) and [element-ui](https://github.com/ElemeFE/element),所有的请求数据都使用[Mock.js](https://github.com/nuysoft/Mock)模拟,提前了解和学习这些知识会对使用本项目有很大的帮助。
|
||||
你需要在本地安装 [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/) 、[axios](https://github.com/axios/axios) 和 [element-ui](https://github.com/ElemeFE/element),所有的请求数据都使用[Mock.js](https://github.com/nuysoft/Mock)模拟,提前了解和学习这些知识会对使用本项目有很大的帮助。
|
||||
|
||||
同时配套一个系列的教程文章,如何从零构建后一个完整的后台项目,建议大家先看完这些文章再来实践本项目
|
||||
- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
|
||||
- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
|
||||
- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
|
||||
- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
|
||||
- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
|
||||
- [手摸手,带你优雅的使用 icon](https://juejin.im/post/59bb864b5188257e7a427c09)
|
||||
|
||||
响应需求,开了一个qq群 `591724180` 方便大家交流
|
||||
- [手摸手,带你用 vue 撸后台 系列一(基础篇)](https://juejin.im/post/59097cd7a22b9d0065fb61d2)
|
||||
- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
|
||||
- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
|
||||
- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
|
||||
- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
|
||||
- [手摸手,带你优雅的使用 icon](https://juejin.im/post/59bb864b5188257e7a427c09)
|
||||
- [手摸手,带你用合理的姿势使用 webpack4(上)](https://juejin.im/post/5b56909a518825195f499806)
|
||||
- [手摸手,带你用合理的姿势使用 webpack4(下)](https://juejin.im/post/5b5d6d6f6fb9a04fea58aabc)
|
||||
|
||||
或者加入该群主 **[圈子](https://jianshiapp.com/circles/1209)** 楼主会经常分享一些技术相关的东西
|
||||
|
||||
**如有问题请先看上述使用文档和文章,若不能满足,欢迎 issue 和 pr**
|
||||
|
||||
**本项目并不是一个脚手架,更倾向于是一个集成解决方案**
|
||||
|
||||
**该项目不支持低版本浏览器(如ie),有需求请自行添加polyfill [详情](https://github.com/PanJiaChen/vue-element-admin/wiki#babel-polyfill)**
|
||||
**如有问题请先看上述使用文档和文章,若不能满足,欢迎 issue 和 pr**
|
||||
|
||||
<p align="center">
|
||||
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
|
||||
</p>
|
||||
|
||||
## 功能
|
||||
|
||||
```
|
||||
- 登录/注销
|
||||
- 登录 / 注销
|
||||
|
||||
- 权限验证
|
||||
- 页面权限
|
||||
- 指令权限
|
||||
- 二步登录
|
||||
|
||||
- 多环境发布
|
||||
- 动态侧边栏(支持多级路由)
|
||||
- 动态面包屑
|
||||
- 国际化多语言
|
||||
- 多种动态换肤
|
||||
- 快捷导航(标签页)
|
||||
- 富文本编辑器
|
||||
- Markdown编辑器
|
||||
- JSON编辑器
|
||||
- Screenfull全屏
|
||||
- 列表拖拽
|
||||
- Svg Sprite 图标
|
||||
- Dashboard
|
||||
- 本地mock数据
|
||||
- Echarts 图表
|
||||
- Clipboard(剪贴复制)
|
||||
- 401/404错误页面
|
||||
- dev sit stage prod
|
||||
|
||||
- 全局功能
|
||||
- 国际化多语言
|
||||
- 多种动态换肤
|
||||
- 动态侧边栏(支持多级路由嵌套)
|
||||
- 动态面包屑
|
||||
- 快捷导航(标签页)
|
||||
- Svg Sprite 图标
|
||||
- 本地mock数据
|
||||
- Screenfull全屏
|
||||
- 自适应收缩侧边栏
|
||||
|
||||
- 编辑器
|
||||
- 富文本
|
||||
- Markdown
|
||||
- JSON 等多格式
|
||||
|
||||
- Excel
|
||||
- 导出excel
|
||||
- 导出zip
|
||||
- 导入excel
|
||||
- 前端可视化excel
|
||||
|
||||
- 表格
|
||||
- 动态表格
|
||||
- 拖拽表格
|
||||
- 树形表格
|
||||
- 内联编辑
|
||||
|
||||
- 错误页面
|
||||
- 401
|
||||
- 404
|
||||
|
||||
- 組件
|
||||
- 头像上传
|
||||
- 返回顶部
|
||||
- 拖拽Dialog
|
||||
- 拖拽看板
|
||||
- 列表拖拽
|
||||
- SplitPane
|
||||
- Dropzone
|
||||
- Sticky
|
||||
- CountTo
|
||||
|
||||
- 综合实例
|
||||
- 错误日志
|
||||
- 导出excel
|
||||
- 导出zip
|
||||
- 前端可视化excel
|
||||
- 树形table
|
||||
- Table example
|
||||
- 动态table example
|
||||
- 拖拽table example
|
||||
- 内联编辑table example
|
||||
- Form example
|
||||
- 二步登录
|
||||
- SplitPane
|
||||
- Dropzone
|
||||
- Sticky
|
||||
- CountTo
|
||||
- Dashboard
|
||||
- 引导页
|
||||
- ECharts 图表
|
||||
- Clipboard(剪贴复制)
|
||||
- Markdown2html
|
||||
```
|
||||
|
||||
## 开发
|
||||
|
||||
```bash
|
||||
# 克隆项目
|
||||
git clone https://github.com/PanJiaChen/vue-element-admin.git
|
||||
|
||||
# 安装依赖
|
||||
npm install
|
||||
|
||||
# 建议不要用cnpm安装 会有各种诡异的bug 可以通过如下操作解决 npm 下载速度慢的问题
|
||||
|
||||
# 建议不要用 cnpm 安装 会有各种诡异的bug 可以通过如下操作解决 npm 下载速度慢的问题
|
||||
npm install --registry=https://registry.npm.taobao.org
|
||||
|
||||
# 启动服务
|
||||
npm run dev
|
||||
```
|
||||
|
||||
浏览器访问 http://localhost:9527
|
||||
|
||||
## 发布
|
||||
|
||||
```bash
|
||||
# 构建测试环境
|
||||
npm run build:sit
|
||||
|
||||
# 构建生成环境
|
||||
# 构建生产环境
|
||||
npm run build:prod
|
||||
```
|
||||
|
||||
## 其它
|
||||
|
||||
```bash
|
||||
# --report to build with bundle size analytics
|
||||
npm run build:prod --report
|
||||
npm run build:prod
|
||||
|
||||
# --generate a bundle size analytics. default: bundle-report.html
|
||||
npm run build:prod --generate_report
|
||||
|
||||
# --preview to start a server in local to preview
|
||||
npm run build:prod --preview
|
||||
@@ -145,15 +193,18 @@ npm run lint
|
||||
npm run lint -- --fix
|
||||
```
|
||||
|
||||
更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/#/deploy)
|
||||
更多信息请参考 [使用文档](https://panjiachen.github.io/vue-element-admin-site/zh/)
|
||||
|
||||
## Changelog
|
||||
|
||||
Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
|
||||
|
||||
## Online Demo
|
||||
|
||||
[在线 Demo](http://panjiachen.github.io/vue-element-admin)
|
||||
|
||||
## Donate
|
||||
|
||||
如果你觉得这个项目帮助到了你,你可以帮作者买一杯果汁表示鼓励 :tropical_drink:
|
||||

|
||||
|
||||
|
@@ -8,9 +8,12 @@ const chalk = require('chalk')
|
||||
const webpack = require('webpack')
|
||||
const config = require('../config')
|
||||
const webpackConfig = require('./webpack.prod.conf')
|
||||
const server = require('pushstate-server')
|
||||
var connect = require('connect')
|
||||
var serveStatic = require('serve-static')
|
||||
|
||||
var spinner = ora('building for '+ process.env.env_config+ ' environment...' )
|
||||
const spinner = ora(
|
||||
'building for ' + process.env.env_config + ' environment...'
|
||||
)
|
||||
spinner.start()
|
||||
|
||||
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
|
||||
@@ -18,31 +21,47 @@ rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
|
||||
webpack(webpackConfig, (err, stats) => {
|
||||
spinner.stop()
|
||||
if (err) throw err
|
||||
process.stdout.write(stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false,
|
||||
chunks: false,
|
||||
chunkModules: false
|
||||
}) + '\n\n')
|
||||
process.stdout.write(
|
||||
stats.toString({
|
||||
colors: true,
|
||||
modules: false,
|
||||
children: false,
|
||||
chunks: false,
|
||||
chunkModules: false
|
||||
}) + '\n\n'
|
||||
)
|
||||
|
||||
if (stats.hasErrors()) {
|
||||
console.log(chalk.red(' Build failed with errors.\n'))
|
||||
console.log(chalk.red(' Build failed with errors.\n'))
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(chalk.cyan(' Build complete.\n'))
|
||||
console.log(chalk.yellow(
|
||||
' Tip: built files are meant to be served over an HTTP server.\n' +
|
||||
' Opening index.html over file:// won\'t work.\n'
|
||||
))
|
||||
if(process.env.npm_config_preview){
|
||||
server.start({
|
||||
port: 9526,
|
||||
directory: './dist',
|
||||
file: '/index.html'
|
||||
});
|
||||
console.log('> Listening at ' + 'http://localhost:9526' + '\n')
|
||||
console.log(chalk.cyan(' Build complete.\n'))
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
' Tip: built files are meant to be served over an HTTP server.\n' +
|
||||
" Opening index.html over file:// won't work.\n"
|
||||
)
|
||||
)
|
||||
|
||||
if (process.env.npm_config_preview) {
|
||||
const port = 9526
|
||||
const host = 'http://localhost:' + port
|
||||
const basePath = config.build.assetsPublicPath
|
||||
const app = connect()
|
||||
|
||||
app.use(
|
||||
basePath,
|
||||
serveStatic('./dist', {
|
||||
index: ['index.html', '/']
|
||||
})
|
||||
)
|
||||
|
||||
app.listen(port, function() {
|
||||
console.log(
|
||||
chalk.green(`> Listening at http://localhost:${port}${basePath}`)
|
||||
)
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
@@ -4,8 +4,11 @@ const semver = require('semver')
|
||||
const packageConfig = require('../package.json')
|
||||
const shell = require('shelljs')
|
||||
|
||||
function exec (cmd) {
|
||||
return require('child_process').execSync(cmd).toString().trim()
|
||||
function exec(cmd) {
|
||||
return require('child_process')
|
||||
.execSync(cmd)
|
||||
.toString()
|
||||
.trim()
|
||||
}
|
||||
|
||||
const versionRequirements = [
|
||||
@@ -24,23 +27,30 @@ if (shell.which('npm')) {
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = function () {
|
||||
module.exports = function() {
|
||||
const warnings = []
|
||||
|
||||
for (let i = 0; i < versionRequirements.length; i++) {
|
||||
const mod = versionRequirements[i]
|
||||
|
||||
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
|
||||
warnings.push(mod.name + ': ' +
|
||||
chalk.red(mod.currentVersion) + ' should be ' +
|
||||
chalk.green(mod.versionRequirement)
|
||||
warnings.push(
|
||||
mod.name +
|
||||
': ' +
|
||||
chalk.red(mod.currentVersion) +
|
||||
' should be ' +
|
||||
chalk.green(mod.versionRequirement)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if (warnings.length) {
|
||||
console.log('')
|
||||
console.log(chalk.yellow('To use this template, you must update following to modules:'))
|
||||
console.log(
|
||||
chalk.yellow(
|
||||
'To use this template, you must update following to modules:'
|
||||
)
|
||||
)
|
||||
console.log()
|
||||
|
||||
for (let i = 0; i < warnings.length; i++) {
|
||||
|
@@ -1,18 +1,19 @@
|
||||
'use strict'
|
||||
const path = require('path')
|
||||
const config = require('../config')
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||
const packageConfig = require('../package.json')
|
||||
|
||||
exports.assetsPath = function (_path) {
|
||||
const assetsSubDirectory = process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsSubDirectory
|
||||
: config.dev.assetsSubDirectory
|
||||
exports.assetsPath = function(_path) {
|
||||
const assetsSubDirectory =
|
||||
process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsSubDirectory
|
||||
: config.dev.assetsSubDirectory
|
||||
|
||||
return path.posix.join(assetsSubDirectory, _path)
|
||||
}
|
||||
|
||||
exports.cssLoaders = function (options) {
|
||||
exports.cssLoaders = function(options) {
|
||||
options = options || {}
|
||||
|
||||
const cssLoader = {
|
||||
@@ -30,8 +31,22 @@ exports.cssLoaders = function (options) {
|
||||
}
|
||||
|
||||
// generate loader string to be used with extract text plugin
|
||||
function generateLoaders (loader, loaderOptions) {
|
||||
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
|
||||
function generateLoaders(loader, loaderOptions) {
|
||||
const loaders = []
|
||||
|
||||
// Extract CSS when that option is specified
|
||||
// (which is the case during production build)
|
||||
if (options.extract) {
|
||||
loaders.push(MiniCssExtractPlugin.loader)
|
||||
} else {
|
||||
loaders.push('vue-style-loader')
|
||||
}
|
||||
|
||||
loaders.push(cssLoader)
|
||||
|
||||
if (options.usePostCSS) {
|
||||
loaders.push(postcssLoader)
|
||||
}
|
||||
|
||||
if (loader) {
|
||||
loaders.push({
|
||||
@@ -42,24 +57,16 @@ exports.cssLoaders = function (options) {
|
||||
})
|
||||
}
|
||||
|
||||
// Extract CSS when that option is specified
|
||||
// (which is the case during production build)
|
||||
if (options.extract) {
|
||||
return ExtractTextPlugin.extract({
|
||||
use: loaders,
|
||||
fallback: 'vue-style-loader'
|
||||
})
|
||||
} else {
|
||||
return ['vue-style-loader'].concat(loaders)
|
||||
}
|
||||
return loaders
|
||||
}
|
||||
|
||||
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
|
||||
return {
|
||||
css: generateLoaders(),
|
||||
postcss: generateLoaders(),
|
||||
less: generateLoaders('less'),
|
||||
sass: generateLoaders('sass', { indentedSyntax: true }),
|
||||
sass: generateLoaders('sass', {
|
||||
indentedSyntax: true
|
||||
}),
|
||||
scss: generateLoaders('sass'),
|
||||
stylus: generateLoaders('stylus'),
|
||||
styl: generateLoaders('stylus')
|
||||
@@ -67,7 +74,7 @@ exports.cssLoaders = function (options) {
|
||||
}
|
||||
|
||||
// Generate loaders for standalone style files (outside of .vue)
|
||||
exports.styleLoaders = function (options) {
|
||||
exports.styleLoaders = function(options) {
|
||||
const output = []
|
||||
const loaders = exports.cssLoaders(options)
|
||||
|
||||
|
@@ -1,22 +1,5 @@
|
||||
'use strict'
|
||||
const utils = require('./utils')
|
||||
const config = require('../config')
|
||||
const isProduction = process.env.NODE_ENV === 'production'
|
||||
const sourceMapEnabled = isProduction
|
||||
? config.build.productionSourceMap
|
||||
: config.dev.cssSourceMap
|
||||
|
||||
module.exports = {
|
||||
loaders: utils.cssLoaders({
|
||||
sourceMap: sourceMapEnabled,
|
||||
extract: isProduction
|
||||
}),
|
||||
cssSourceMap: sourceMapEnabled,
|
||||
cacheBusting: config.dev.cacheBusting,
|
||||
transformToRequire: {
|
||||
video: ['src', 'poster'],
|
||||
source: 'src',
|
||||
img: 'src',
|
||||
image: 'xlink:href'
|
||||
}
|
||||
//You can set the vue-loader configuration by yourself.
|
||||
}
|
||||
|
@@ -2,9 +2,10 @@
|
||||
const path = require('path')
|
||||
const utils = require('./utils')
|
||||
const config = require('../config')
|
||||
const { VueLoaderPlugin } = require('vue-loader')
|
||||
const vueLoaderConfig = require('./vue-loader.conf')
|
||||
|
||||
function resolve (dir) {
|
||||
function resolve(dir) {
|
||||
return path.join(__dirname, '..', dir)
|
||||
}
|
||||
|
||||
@@ -27,15 +28,15 @@ module.exports = {
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
filename: '[name].js',
|
||||
publicPath: process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsPublicPath
|
||||
: config.dev.assetsPublicPath
|
||||
publicPath:
|
||||
process.env.NODE_ENV === 'production'
|
||||
? config.build.assetsPublicPath
|
||||
: config.dev.assetsPublicPath
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.js', '.vue', '.json'],
|
||||
alias: {
|
||||
'vue$': 'vue/dist/vue.esm.js',
|
||||
'@': resolve('src'),
|
||||
'@': resolve('src')
|
||||
}
|
||||
},
|
||||
module: {
|
||||
@@ -49,7 +50,11 @@ module.exports = {
|
||||
{
|
||||
test: /\.js$/,
|
||||
loader: 'babel-loader?cacheDirectory',
|
||||
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
|
||||
include: [
|
||||
resolve('src'),
|
||||
resolve('test'),
|
||||
resolve('node_modules/webpack-dev-server/client')
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
@@ -86,6 +91,7 @@ module.exports = {
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [new VueLoaderPlugin()],
|
||||
node: {
|
||||
// prevent webpack from injecting useless setImmediate polyfill because Vue
|
||||
// source contains it (although only uses it if it's native).
|
||||
|
@@ -9,7 +9,7 @@ const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
|
||||
const portfinder = require('portfinder')
|
||||
|
||||
function resolve (dir) {
|
||||
function resolve(dir) {
|
||||
return path.join(__dirname, '..', dir)
|
||||
}
|
||||
|
||||
@@ -17,8 +17,12 @@ const HOST = process.env.HOST
|
||||
const PORT = process.env.PORT && Number(process.env.PORT)
|
||||
|
||||
const devWebpackConfig = merge(baseWebpackConfig, {
|
||||
mode: 'development',
|
||||
module: {
|
||||
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
|
||||
rules: utils.styleLoaders({
|
||||
sourceMap: config.dev.cssSourceMap,
|
||||
usePostCSS: true
|
||||
})
|
||||
},
|
||||
// cheap-module-eval-source-map is faster for development
|
||||
devtool: config.dev.devtool,
|
||||
@@ -39,7 +43,7 @@ const devWebpackConfig = merge(baseWebpackConfig, {
|
||||
proxy: config.dev.proxyTable,
|
||||
quiet: true, // necessary for FriendlyErrorsPlugin
|
||||
watchOptions: {
|
||||
poll: config.dev.poll,
|
||||
poll: config.dev.poll
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
@@ -47,8 +51,6 @@ const devWebpackConfig = merge(baseWebpackConfig, {
|
||||
'process.env': require('../config/dev.env')
|
||||
}),
|
||||
new webpack.HotModuleReplacementPlugin(),
|
||||
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
// https://github.com/ampedandwired/html-webpack-plugin
|
||||
new HtmlWebpackPlugin({
|
||||
filename: 'index.html',
|
||||
@@ -56,7 +58,9 @@ const devWebpackConfig = merge(baseWebpackConfig, {
|
||||
inject: true,
|
||||
favicon: resolve('favicon.ico'),
|
||||
title: 'vue-element-admin',
|
||||
path: config.dev.assetsPublicPath + config.dev.assetsSubDirectory
|
||||
templateParameters: {
|
||||
BASE_URL: config.dev.assetsPublicPath + config.dev.assetsSubDirectory,
|
||||
},
|
||||
}),
|
||||
]
|
||||
})
|
||||
@@ -73,14 +77,20 @@ module.exports = new Promise((resolve, reject) => {
|
||||
devWebpackConfig.devServer.port = port
|
||||
|
||||
// Add FriendlyErrorsPlugin
|
||||
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
|
||||
compilationSuccessInfo: {
|
||||
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
|
||||
},
|
||||
onErrors: config.dev.notifyOnErrors
|
||||
? utils.createNotifierCallback()
|
||||
: undefined
|
||||
}))
|
||||
devWebpackConfig.plugins.push(
|
||||
new FriendlyErrorsPlugin({
|
||||
compilationSuccessInfo: {
|
||||
messages: [
|
||||
`Your application is running here: http://${
|
||||
devWebpackConfig.devServer.host
|
||||
}:${port}`
|
||||
]
|
||||
},
|
||||
onErrors: config.dev.notifyOnErrors
|
||||
? utils.createNotifierCallback()
|
||||
: undefined
|
||||
})
|
||||
)
|
||||
|
||||
resolve(devWebpackConfig)
|
||||
}
|
||||
|
@@ -7,17 +7,23 @@ const merge = require('webpack-merge')
|
||||
const baseWebpackConfig = require('./webpack.base.conf')
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin')
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin')
|
||||
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
|
||||
const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
|
||||
|
||||
function resolve (dir) {
|
||||
function resolve(dir) {
|
||||
return path.join(__dirname, '..', dir)
|
||||
}
|
||||
|
||||
const env = require('../config/'+process.env.env_config+'.env')
|
||||
const env = require('../config/' + process.env.env_config + '.env')
|
||||
|
||||
// For NamedChunksPlugin
|
||||
const seen = new Set()
|
||||
const nameLength = 4
|
||||
|
||||
const webpackConfig = merge(baseWebpackConfig, {
|
||||
mode: 'production',
|
||||
module: {
|
||||
rules: utils.styleLoaders({
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
@@ -28,37 +34,18 @@ const webpackConfig = merge(baseWebpackConfig, {
|
||||
devtool: config.build.productionSourceMap ? config.build.devtool : false,
|
||||
output: {
|
||||
path: config.build.assetsRoot,
|
||||
filename: utils.assetsPath('js/[name].[chunkhash].js'),
|
||||
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
|
||||
filename: utils.assetsPath('js/[name].[chunkhash:8].js'),
|
||||
chunkFilename: utils.assetsPath('js/[name].[chunkhash:8].js')
|
||||
},
|
||||
plugins: [
|
||||
// http://vuejs.github.io/vue-loader/en/workflow/production.html
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': env
|
||||
}),
|
||||
new UglifyJsPlugin({
|
||||
uglifyOptions: {
|
||||
compress: {
|
||||
warnings: false
|
||||
}
|
||||
},
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
parallel: true
|
||||
}),
|
||||
// extract css into its own file
|
||||
new ExtractTextPlugin({
|
||||
filename: utils.assetsPath('css/[name].[contenthash].css'),
|
||||
// Setting the following option to `false` will not extract CSS from codesplit chunks.
|
||||
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
|
||||
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
|
||||
allChunks: false,
|
||||
}),
|
||||
// Compress extracted CSS. We are using this plugin so that possible
|
||||
// duplicated CSS from different components can be deduped.
|
||||
new OptimizeCSSPlugin({
|
||||
cssProcessorOptions: config.build.productionSourceMap
|
||||
? { safe: true, map: { inline: false } }
|
||||
: { safe: true }
|
||||
new MiniCssExtractPlugin({
|
||||
filename: utils.assetsPath('css/[name].[contenthash:8].css'),
|
||||
chunkFilename: utils.assetsPath('css/[name].[contenthash:8].css')
|
||||
}),
|
||||
// generate dist index.html with correct asset hash for caching.
|
||||
// you can customize output by editing /index.html
|
||||
@@ -69,75 +56,43 @@ const webpackConfig = merge(baseWebpackConfig, {
|
||||
inject: true,
|
||||
favicon: resolve('favicon.ico'),
|
||||
title: 'vue-element-admin',
|
||||
path: config.build.assetsPublicPath + config.build.assetsSubDirectory,
|
||||
templateParameters: {
|
||||
BASE_URL: config.build.assetsPublicPath + config.build.assetsSubDirectory,
|
||||
},
|
||||
minify: {
|
||||
removeComments: true,
|
||||
collapseWhitespace: true,
|
||||
removeAttributeQuotes: true
|
||||
// more options:
|
||||
// https://github.com/kangax/html-minifier#options-quick-reference
|
||||
},
|
||||
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
|
||||
chunksSortMode: 'dependency'
|
||||
}
|
||||
// default sort mode uses toposort which cannot handle cyclic deps
|
||||
// in certain cases, and in webpack 4, chunk order in HTML doesn't
|
||||
// matter anyway
|
||||
}),
|
||||
new ScriptExtHtmlWebpackPlugin({
|
||||
//`runtime` must same as runtimeChunk name. default is `runtime`
|
||||
inline: /runtime\..*\.js$/
|
||||
}),
|
||||
// keep chunk.id stable when chunk has no name
|
||||
new webpack.NamedChunksPlugin(chunk => {
|
||||
if (chunk.name) {
|
||||
return chunk.name
|
||||
}
|
||||
const modules = Array.from(chunk.modulesIterable)
|
||||
if (modules.length > 1) {
|
||||
const hash = require('hash-sum')
|
||||
const joinedHash = hash(modules.map(m => m.id).join('_'))
|
||||
let len = nameLength
|
||||
while (seen.has(joinedHash.substr(0, len))) len++
|
||||
seen.add(joinedHash.substr(0, len))
|
||||
return `chunk-${joinedHash.substr(0, len)}`
|
||||
} else {
|
||||
return modules[0].id
|
||||
}
|
||||
}),
|
||||
// keep module.id stable when vender modules does not change
|
||||
new webpack.HashedModuleIdsPlugin(),
|
||||
// enable scope hoisting
|
||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||
// split vendor js into its own file
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'vendor',
|
||||
minChunks (module) {
|
||||
// any required modules inside node_modules are extracted to vendor
|
||||
return (
|
||||
module.resource &&
|
||||
/\.js$/.test(module.resource) &&
|
||||
module.resource.indexOf(
|
||||
path.join(__dirname, '../node_modules')
|
||||
) === 0
|
||||
)
|
||||
}
|
||||
}),
|
||||
// extract webpack runtime and module manifest to its own file in order to
|
||||
// prevent vendor hash from being updated whenever app bundle is updated
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'manifest',
|
||||
minChunks: Infinity
|
||||
}),
|
||||
// This instance extracts shared chunks from code splitted chunks and bundles them
|
||||
// in a separate chunk, similar to the vendor chunk
|
||||
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
name: 'app',
|
||||
async: 'vendor-async',
|
||||
children: true,
|
||||
minChunks: 3
|
||||
}),
|
||||
// split echarts into its own file
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
async: 'echarts',
|
||||
minChunks(module) {
|
||||
var context = module.context;
|
||||
return context && (context.indexOf('echarts') >= 0 || context.indexOf('zrender') >= 0);
|
||||
}
|
||||
}),
|
||||
// split xlsx into its own file
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
async: 'xlsx',
|
||||
minChunks(module) {
|
||||
var context = module.context;
|
||||
return context && (context.indexOf('xlsx') >= 0);
|
||||
}
|
||||
}),
|
||||
// split codemirror into its own file
|
||||
new webpack.optimize.CommonsChunkPlugin({
|
||||
async: 'codemirror',
|
||||
minChunks(module) {
|
||||
var context = module.context;
|
||||
return context && (context.indexOf('codemirror') >= 0);
|
||||
}
|
||||
}),
|
||||
|
||||
// copy custom static assets
|
||||
new CopyWebpackPlugin([
|
||||
{
|
||||
@@ -146,7 +101,48 @@ const webpackConfig = merge(baseWebpackConfig, {
|
||||
ignore: ['.*']
|
||||
}
|
||||
])
|
||||
]
|
||||
],
|
||||
optimization: {
|
||||
splitChunks: {
|
||||
chunks: 'all',
|
||||
cacheGroups: {
|
||||
libs: {
|
||||
name: 'chunk-libs',
|
||||
test: /[\\/]node_modules[\\/]/,
|
||||
priority: 10,
|
||||
chunks: 'initial' // 只打包初始时依赖的第三方
|
||||
},
|
||||
elementUI: {
|
||||
name: 'chunk-elementUI', // 单独将 elementUI 拆包
|
||||
priority: 20, // 权重要大于 libs 和 app 不然会被打包进 libs 或者 app
|
||||
test: /[\\/]node_modules[\\/]element-ui[\\/]/
|
||||
},
|
||||
commons: {
|
||||
name: 'chunk-commons',
|
||||
test: resolve('src/components'), // 可自定义拓展你的规则
|
||||
minChunks: 3, // 最小公用次数
|
||||
priority: 5,
|
||||
reuseExistingChunk: true
|
||||
}
|
||||
}
|
||||
},
|
||||
runtimeChunk: 'single',
|
||||
minimizer: [
|
||||
new UglifyJsPlugin({
|
||||
uglifyOptions: {
|
||||
mangle: {
|
||||
safari10: true
|
||||
}
|
||||
},
|
||||
sourceMap: config.build.productionSourceMap,
|
||||
cache: true,
|
||||
parallel: true
|
||||
}),
|
||||
// Compress extracted CSS. We are using this plugin so that possible
|
||||
// duplicated CSS from different components can be deduped.
|
||||
new OptimizeCSSAssetsPlugin()
|
||||
]
|
||||
}
|
||||
})
|
||||
|
||||
if (config.build.productionGzip) {
|
||||
@@ -157,9 +153,7 @@ if (config.build.productionGzip) {
|
||||
asset: '[path].gz[query]',
|
||||
algorithm: 'gzip',
|
||||
test: new RegExp(
|
||||
'\\.(' +
|
||||
config.build.productionGzipExtensions.join('|') +
|
||||
')$'
|
||||
'\\.(' + config.build.productionGzipExtensions.join('|') + ')$'
|
||||
),
|
||||
threshold: 10240,
|
||||
minRatio: 0.8
|
||||
@@ -167,9 +161,28 @@ if (config.build.productionGzip) {
|
||||
)
|
||||
}
|
||||
|
||||
if (config.build.bundleAnalyzerReport) {
|
||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
||||
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
|
||||
if (config.build.generateAnalyzerReport || config.build.bundleAnalyzerReport) {
|
||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
|
||||
.BundleAnalyzerPlugin
|
||||
|
||||
if (config.build.bundleAnalyzerReport) {
|
||||
webpackConfig.plugins.push(
|
||||
new BundleAnalyzerPlugin({
|
||||
analyzerPort: 8080,
|
||||
generateStatsFile: false
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
if (config.build.generateAnalyzerReport) {
|
||||
webpackConfig.plugins.push(
|
||||
new BundleAnalyzerPlugin({
|
||||
analyzerMode: 'static',
|
||||
reportFilename: 'bundle-report.html',
|
||||
openAnalyzer: false
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = webpackConfig
|
||||
|
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
NODE_ENV: '"development"',
|
||||
ENV_CONFIG: '"dev"',
|
||||
BASE_API: '"https://api-dev"'
|
||||
NODE_ENV: '"development"',
|
||||
ENV_CONFIG: '"dev"',
|
||||
BASE_API: '"https://api-dev"'
|
||||
}
|
||||
|
@@ -6,14 +6,16 @@ const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
dev: {
|
||||
|
||||
// Paths
|
||||
assetsSubDirectory: 'static',
|
||||
assetsPublicPath: '/',
|
||||
proxyTable: {},
|
||||
|
||||
// Various Dev Server settings
|
||||
host: 'localhost', // can be overwritten by process.env.HOST
|
||||
|
||||
// can be overwritten by process.env.HOST
|
||||
// if you want dev by ip, please set host: '0.0.0.0'
|
||||
host: 'localhost',
|
||||
port: 9527, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
|
||||
autoOpenBrowser: true,
|
||||
errorOverlay: true,
|
||||
@@ -33,19 +35,14 @@ module.exports = {
|
||||
*/
|
||||
|
||||
// https://webpack.js.org/configuration/devtool/#development
|
||||
devtool: '#cheap-source-map',
|
||||
|
||||
// If you have problems debugging vue-files in devtools,
|
||||
// set this to false - it *may* help
|
||||
// https://vue-loader.vuejs.org/en/options.html#cachebusting
|
||||
cacheBusting: true,
|
||||
devtool: 'cheap-source-map',
|
||||
|
||||
// CSS Sourcemaps off by default because relative paths are "buggy"
|
||||
// with this option, according to the CSS-Loader README
|
||||
// (https://github.com/webpack/css-loader#sourcemaps)
|
||||
// In our experience, they generally work as expected,
|
||||
// just be aware of this issue when enabling this option.
|
||||
cssSourceMap: false,
|
||||
cssSourceMap: false
|
||||
},
|
||||
|
||||
build: {
|
||||
@@ -56,16 +53,21 @@ module.exports = {
|
||||
assetsRoot: path.resolve(__dirname, '../dist'),
|
||||
assetsSubDirectory: 'static',
|
||||
|
||||
// you can set by youself according to actual condition
|
||||
assetsPublicPath: './',
|
||||
/**
|
||||
* You can set by youself according to actual condition
|
||||
* You will need to set this if you plan to deploy your site under a sub path,
|
||||
* for example GitHub pages. If you plan to deploy your site to https://foo.github.io/bar/,
|
||||
* then assetsPublicPath should be set to "/bar/".
|
||||
* In most cases please use '/' !!!
|
||||
*/
|
||||
assetsPublicPath: '/',
|
||||
|
||||
/**
|
||||
* Source Maps
|
||||
*/
|
||||
|
||||
productionSourceMap: false,
|
||||
// https://webpack.js.org/configuration/devtool/#production
|
||||
devtool: '#source-map',
|
||||
devtool: 'source-map',
|
||||
|
||||
// Gzip off by default as many popular static hosts such as
|
||||
// Surge or Netlify already gzip all static assets for you.
|
||||
@@ -76,8 +78,11 @@ module.exports = {
|
||||
|
||||
// Run the build command with an extra argument to
|
||||
// View the bundle analyzer report after build finishes:
|
||||
// `npm run build --report`
|
||||
// `npm run build:prod --report`
|
||||
// Set to `true` or `false` to always turn it on or off
|
||||
bundleAnalyzerReport: process.env.npm_config_report
|
||||
bundleAnalyzerReport: process.env.npm_config_report || false,
|
||||
|
||||
// `npm run build:prod --generate_report`
|
||||
generateAnalyzerReport: process.env.npm_config_generate_report || false
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
NODE_ENV: '"production"',
|
||||
ENV_CONFIG: '"prod"',
|
||||
BASE_API: '"https://api-prod"'
|
||||
NODE_ENV: '"production"',
|
||||
ENV_CONFIG: '"prod"',
|
||||
BASE_API: '"https://api-prod"'
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
module.exports = {
|
||||
NODE_ENV: '"production"',
|
||||
ENV_CONFIG: '"sit"',
|
||||
BASE_API: '"https://api-sit"'
|
||||
NODE_ENV: '"production"',
|
||||
ENV_CONFIG: '"sit"',
|
||||
BASE_API: '"https://api-sit"'
|
||||
}
|
||||
|
BIN
gifs/2login.gif
Before Width: | Height: | Size: 275 KiB |
Before Width: | Height: | Size: 41 KiB |
BIN
gifs/echarts.gif
Before Width: | Height: | Size: 229 KiB |
BIN
gifs/editor.gif
Before Width: | Height: | Size: 435 KiB |
Before Width: | Height: | Size: 532 KiB |
BIN
gifs/excel.png
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 601 KiB |
BIN
gifs/login.png
Before Width: | Height: | Size: 51 KiB |
BIN
gifs/order.gif
Before Width: | Height: | Size: 1.1 MiB |
BIN
gifs/table.gif
Before Width: | Height: | Size: 390 KiB |
BIN
gifs/tabs.gif
Before Width: | Height: | Size: 1.2 MiB |
BIN
gifs/theme.gif
Before Width: | Height: | Size: 265 KiB |
BIN
gifs/upload1.gif
Before Width: | Height: | Size: 148 KiB |
Before Width: | Height: | Size: 330 KiB |
24
index.html
@@ -1,15 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<title>vue-element-admin</title>
|
||||
</head>
|
||||
<script src=<%= htmlWebpackPlugin.options.path %>/tinymce/tinymce.min.js></script>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<title>vue-element-admin</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src=<%= BASE_URL %>/tinymce4.7.5/tinymce.min.js></script>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
|
138
package.json
@@ -1,96 +1,126 @@
|
||||
{
|
||||
"name": "vue-element-admin",
|
||||
"version": "3.6.1",
|
||||
"version": "3.9.1",
|
||||
"description": "A magical vue admin. Typical templates for enterprise applications. Newest development stack of vue. Lots of awesome features",
|
||||
"author": "Pan <panfree23@gmail.com>",
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
|
||||
"dev": "cross-env BABEL_ENV=development webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
|
||||
"build:prod": "cross-env NODE_ENV=production env_config=prod node build/build.js",
|
||||
"build:sit": "cross-env NODE_ENV=production env_config=sit node build/build.js",
|
||||
"lint": "eslint --ext .js,.vue src",
|
||||
"test": "npm run lint"
|
||||
"test": "npm run lint",
|
||||
"precommit": "lint-staged",
|
||||
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml"
|
||||
},
|
||||
"lint-staged": {
|
||||
"src/**/*.{js,vue}": [
|
||||
"eslint --fix",
|
||||
"git add"
|
||||
]
|
||||
},
|
||||
"keywords": [
|
||||
"vue",
|
||||
"element-ui",
|
||||
"admin",
|
||||
"management-system",
|
||||
"admin-template"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/PanJiaChen/vue-element-admin/issues"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "0.17.1",
|
||||
"axios": "0.18.0",
|
||||
"clipboard": "1.7.1",
|
||||
"codemirror": "5.32.0",
|
||||
"codemirror": "5.39.2",
|
||||
"connect": "3.6.6",
|
||||
"driver.js": "0.5.2",
|
||||
"dropzone": "5.2.0",
|
||||
"echarts": "3.8.5",
|
||||
"element-ui": "2.0.8",
|
||||
"file-saver": "1.3.3",
|
||||
"echarts": "4.1.0",
|
||||
"element-ui": "2.4.6",
|
||||
"file-saver": "1.3.8",
|
||||
"font-awesome": "4.7.0",
|
||||
"js-cookie": "2.2.0",
|
||||
"jsonlint": "1.6.2",
|
||||
"jsonlint": "1.6.3",
|
||||
"jszip": "3.1.5",
|
||||
"mockjs": "1.0.1-beta3",
|
||||
"normalize.css": "7.0.0",
|
||||
"nprogress": "0.2.0",
|
||||
"screenfull": "3.3.2",
|
||||
"showdown": "1.8.5",
|
||||
"screenfull": "3.3.3",
|
||||
"showdown": "1.8.6",
|
||||
"simplemde": "1.11.2",
|
||||
"sortablejs": "1.7.0",
|
||||
"vue": "2.5.10",
|
||||
"vue": "2.5.17",
|
||||
"vue-count-to": "1.0.13",
|
||||
"vue-i18n": "7.3.2",
|
||||
"vue-multiselect": "2.0.8",
|
||||
"vue-router": "3.0.1",
|
||||
"vue-splitpane": "1.0.2",
|
||||
"vuedraggable": "2.15.0",
|
||||
"vuedraggable": "^2.16.0",
|
||||
"vuex": "3.0.1",
|
||||
"xlsx": "^0.11.16"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "7.2.3",
|
||||
"babel-core": "6.26.0",
|
||||
"babel-eslint": "8.0.3",
|
||||
"autoprefixer": "8.5.0",
|
||||
"babel-core": "6.26.3",
|
||||
"babel-eslint": "8.2.6",
|
||||
"babel-helper-vue-jsx-merge-props": "2.0.3",
|
||||
"babel-loader": "7.1.2",
|
||||
"babel-loader": "7.1.5",
|
||||
"babel-plugin-dynamic-import-node": "2.0.0",
|
||||
"babel-plugin-syntax-jsx": "6.18.0",
|
||||
"babel-plugin-transform-runtime": "6.23.0",
|
||||
"babel-plugin-transform-vue-jsx": "3.5.0",
|
||||
"babel-preset-env": "1.6.1",
|
||||
"babel-plugin-transform-vue-jsx": "3.7.0",
|
||||
"babel-preset-env": "1.7.0",
|
||||
"babel-preset-stage-2": "6.24.1",
|
||||
"chalk": "2.3.0",
|
||||
"copy-webpack-plugin": "4.3.0",
|
||||
"cross-env": "5.1.1",
|
||||
"css-loader": "0.28.7",
|
||||
"eslint": "4.13.1",
|
||||
"eslint-friendly-formatter": "3.0.0",
|
||||
"eslint-loader": "1.9.0",
|
||||
"eslint-plugin-html": "4.0.1",
|
||||
"extract-text-webpack-plugin": "3.0.2",
|
||||
"file-loader": "1.1.5",
|
||||
"friendly-errors-webpack-plugin": "1.6.1",
|
||||
"html-webpack-plugin": "2.30.1",
|
||||
"node-notifier": "5.1.2",
|
||||
"chalk": "2.4.1",
|
||||
"copy-webpack-plugin": "4.5.2",
|
||||
"cross-env": "5.2.0",
|
||||
"css-loader": "1.0.0",
|
||||
"eslint": "4.19.1",
|
||||
"eslint-friendly-formatter": "4.0.1",
|
||||
"eslint-loader": "2.0.0",
|
||||
"eslint-plugin-vue": "4.7.1",
|
||||
"file-loader": "1.1.11",
|
||||
"friendly-errors-webpack-plugin": "1.7.0",
|
||||
"hash-sum": "1.0.2",
|
||||
"html-webpack-plugin": "4.0.0-alpha",
|
||||
"husky": "0.14.3",
|
||||
"lint-staged": "7.2.2",
|
||||
"mini-css-extract-plugin": "0.4.1",
|
||||
"node-notifier": "5.2.1",
|
||||
"node-sass": "^4.7.2",
|
||||
"optimize-css-assets-webpack-plugin": "3.2.0",
|
||||
"ora": "1.3.0",
|
||||
"optimize-css-assets-webpack-plugin": "5.0.0",
|
||||
"ora": "3.0.0",
|
||||
"path-to-regexp": "2.4.0",
|
||||
"portfinder": "1.0.13",
|
||||
"postcss-import": "11.0.0",
|
||||
"postcss-loader": "2.0.9",
|
||||
"postcss-url": "7.3.0",
|
||||
"pushstate-server": "3.0.1",
|
||||
"postcss-import": "11.1.0",
|
||||
"postcss-loader": "2.1.6",
|
||||
"postcss-url": "7.3.2",
|
||||
"rimraf": "2.6.2",
|
||||
"sass-loader": "6.0.6",
|
||||
"sass-loader": "7.0.3",
|
||||
"script-ext-html-webpack-plugin": "2.0.1",
|
||||
"script-loader": "0.7.2",
|
||||
"semver": "5.4.1",
|
||||
"shelljs": "0.7.8",
|
||||
"svg-sprite-loader": "3.5.2",
|
||||
"uglifyjs-webpack-plugin": "1.1.3",
|
||||
"url-loader": "0.6.2",
|
||||
"vue-loader": "13.5.0",
|
||||
"vue-style-loader": "3.0.3",
|
||||
"vue-template-compiler": "2.5.10",
|
||||
"webpack": "3.10.0",
|
||||
"webpack-bundle-analyzer": "2.9.1",
|
||||
"webpack-dev-server": "2.9.7",
|
||||
"webpack-merge": "4.1.1"
|
||||
"semver": "5.5.0",
|
||||
"serve-static": "1.13.2",
|
||||
"shelljs": "0.8.2",
|
||||
"svg-sprite-loader": "3.8.0",
|
||||
"svgo": "1.0.5",
|
||||
"uglifyjs-webpack-plugin": "1.2.7",
|
||||
"url-loader": "1.0.1",
|
||||
"vue-loader": "15.3.0",
|
||||
"vue-style-loader": "4.1.2",
|
||||
"vue-template-compiler": "2.5.17",
|
||||
"webpack": "4.16.5",
|
||||
"webpack-bundle-analyzer": "2.13.1",
|
||||
"webpack-cli": "3.1.0",
|
||||
"webpack-dev-server": "3.1.5",
|
||||
"webpack-merge": "4.1.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4.0.0",
|
||||
"node": ">= 6.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
},
|
||||
"browserslist": [
|
||||
|
12
src/App.vue
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<router-view></router-view>
|
||||
</div>
|
||||
<div id="app">
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default{
|
||||
name: 'APP'
|
||||
}
|
||||
export default{
|
||||
name: 'App'
|
||||
}
|
||||
</script>
|
||||
|
@@ -8,10 +8,11 @@ export function fetchList(query) {
|
||||
})
|
||||
}
|
||||
|
||||
export function fetchArticle() {
|
||||
export function fetchArticle(id) {
|
||||
return request({
|
||||
url: '/article/detail',
|
||||
method: 'get'
|
||||
method: 'get',
|
||||
params: { id }
|
||||
})
|
||||
}
|
||||
|
||||
|
@@ -1,199 +0,0 @@
|
||||
/* eslint-disable */
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['exports', 'echarts'], factory);
|
||||
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
|
||||
// CommonJS
|
||||
factory(exports, require('echarts'));
|
||||
} else {
|
||||
// Browser globals
|
||||
factory({}, root.echarts);
|
||||
}
|
||||
}(this, function (exports, echarts) {
|
||||
var log = function (msg) {
|
||||
if (typeof console !== 'undefined') {
|
||||
console && console.error && console.error(msg);
|
||||
}
|
||||
};
|
||||
if (!echarts) {
|
||||
log('ECharts is not Loaded');
|
||||
return;
|
||||
}
|
||||
|
||||
var colorPalette = [
|
||||
'#2ec7c9','#b6a2de','#5ab1ef','#ffb980','#d87a80',
|
||||
'#8d98b3','#e5cf0d','#97b552','#95706d','#dc69aa',
|
||||
'#07a2a4','#9a7fd1','#588dd5','#f5994e','#c05050',
|
||||
'#59678c','#c9ab00','#7eb00a','#6f5553','#c14089'
|
||||
];
|
||||
|
||||
|
||||
var theme = {
|
||||
color: colorPalette,
|
||||
|
||||
title: {
|
||||
textStyle: {
|
||||
fontWeight: 'normal',
|
||||
color: '#008acd'
|
||||
}
|
||||
},
|
||||
|
||||
visualMap: {
|
||||
itemWidth: 15,
|
||||
color: ['#5ab1ef','#e0ffff']
|
||||
},
|
||||
|
||||
toolbox: {
|
||||
iconStyle: {
|
||||
normal: {
|
||||
borderColor: colorPalette[0]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(50,50,50,0.5)',
|
||||
axisPointer : {
|
||||
type : 'line',
|
||||
lineStyle : {
|
||||
color: '#008acd'
|
||||
},
|
||||
crossStyle: {
|
||||
color: '#008acd'
|
||||
},
|
||||
shadowStyle : {
|
||||
color: 'rgba(200,200,200,0.2)'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
dataZoom: {
|
||||
dataBackgroundColor: '#efefff',
|
||||
fillerColor: 'rgba(182,162,222,0.2)',
|
||||
handleColor: '#008acd'
|
||||
},
|
||||
|
||||
grid: {
|
||||
borderColor: '#eee'
|
||||
},
|
||||
|
||||
categoryAxis: {
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#008acd'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: ['#eee']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
valueAxis: {
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#008acd'
|
||||
}
|
||||
},
|
||||
splitArea : {
|
||||
show : true,
|
||||
areaStyle : {
|
||||
color: ['rgba(250,250,250,0.1)','rgba(200,200,200,0.1)']
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: ['#eee']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
timeline : {
|
||||
lineStyle : {
|
||||
color : '#008acd'
|
||||
},
|
||||
controlStyle : {
|
||||
normal : { color : '#008acd'},
|
||||
emphasis : { color : '#008acd'}
|
||||
},
|
||||
symbol : 'emptyCircle',
|
||||
symbolSize : 3
|
||||
},
|
||||
|
||||
line: {
|
||||
smooth : true,
|
||||
symbol: 'emptyCircle',
|
||||
symbolSize: 3
|
||||
},
|
||||
|
||||
candlestick: {
|
||||
itemStyle: {
|
||||
normal: {
|
||||
color: '#d87a80',
|
||||
color0: '#2ec7c9',
|
||||
lineStyle: {
|
||||
color: '#d87a80',
|
||||
color0: '#2ec7c9'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
scatter: {
|
||||
symbol: 'circle',
|
||||
symbolSize: 4
|
||||
},
|
||||
|
||||
map: {
|
||||
label: {
|
||||
normal: {
|
||||
textStyle: {
|
||||
color: '#d87a80'
|
||||
}
|
||||
}
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
borderColor: '#eee',
|
||||
areaColor: '#ddd'
|
||||
},
|
||||
emphasis: {
|
||||
areaColor: '#fe994e'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
graph: {
|
||||
color: colorPalette
|
||||
},
|
||||
|
||||
gauge : {
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: [[0.2, '#2ec7c9'],[0.8, '#5ab1ef'],[1, '#d87a80']],
|
||||
width: 10
|
||||
}
|
||||
},
|
||||
axisTick: {
|
||||
splitNumber: 10,
|
||||
length :15,
|
||||
lineStyle: {
|
||||
color: 'auto'
|
||||
}
|
||||
},
|
||||
splitLine: {
|
||||
length :22,
|
||||
lineStyle: {
|
||||
color: 'auto'
|
||||
}
|
||||
},
|
||||
pointer : {
|
||||
width : 5
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
echarts.registerTheme('macarons', theme);
|
||||
}));
|
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<transition :name="transitionName">
|
||||
<div class="back-to-ceiling" @click="backToTop" v-show="visible" :style="customStyle">
|
||||
<div v-show="visible" :style="customStyle" class="back-to-ceiling" @click="backToTop">
|
||||
<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;">
|
||||
<title>回到顶部</title>
|
||||
<g>
|
||||
<path d="M12.036 15.59c0 .55-.453.995-.997.995H5.032c-.55 0-.997-.445-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29c.39-.39 1.026-.385 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" fill-rule="evenodd"></path>
|
||||
<path d="M12.036 15.59c0 .55-.453.995-.997.995H5.032c-.55 0-.997-.445-.997-.996V8.584H1.03c-1.1 0-1.36-.633-.578-1.416L7.33.29c.39-.39 1.026-.385 1.412 0l6.878 6.88c.782.78.523 1.415-.58 1.415h-3.004v7.004z" fill-rule="evenodd"/>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
@@ -25,14 +25,16 @@ export default {
|
||||
},
|
||||
customStyle: {
|
||||
type: Object,
|
||||
default: {
|
||||
right: '50px',
|
||||
bottom: '50px',
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
'border-radius': '4px',
|
||||
'line-height': '45px',
|
||||
background: '#e7eaf1'
|
||||
default: function() {
|
||||
return {
|
||||
right: '50px',
|
||||
bottom: '50px',
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
'border-radius': '4px',
|
||||
'line-height': '45px',
|
||||
background: '#e7eaf1'
|
||||
}
|
||||
}
|
||||
},
|
||||
transitionName: {
|
||||
@@ -43,7 +45,8 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
interval: null
|
||||
interval: null,
|
||||
isMoving: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -60,13 +63,16 @@ export default {
|
||||
this.visible = window.pageYOffset > this.visibilityHeight
|
||||
},
|
||||
backToTop() {
|
||||
if (this.isMoving) return
|
||||
const start = window.pageYOffset
|
||||
let i = 0
|
||||
this.isMoving = true
|
||||
this.interval = setInterval(() => {
|
||||
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
|
||||
if (next <= this.backPosition) {
|
||||
window.scrollTo(0, this.backPosition)
|
||||
clearInterval(this.interval)
|
||||
this.isMoving = false
|
||||
} else {
|
||||
window.scrollTo(0, next)
|
||||
}
|
||||
|
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<el-breadcrumb class="app-breadcrumb" separator="/">
|
||||
<transition-group name="breadcrumb">
|
||||
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path" v-if='item.meta.title'>
|
||||
<span v-if='item.redirect==="noredirect"||index==levelList.length-1' class="no-redirect">{{generateTitle(item.meta.title)}}</span>
|
||||
<router-link v-else :to="item.redirect||item.path">{{generateTitle(item.meta.title)}}</router-link>
|
||||
<el-breadcrumb-item v-for="(item,index) in levelList" v-if="item.meta.title" :key="item.path">
|
||||
<span v-if="item.redirect==='noredirect'||index==levelList.length-1" class="no-redirect">{{ generateTitle(item.meta.title) }}</span>
|
||||
<router-link v-else :to="item.redirect||item.path">{{ generateTitle(item.meta.title) }}</router-link>
|
||||
</el-breadcrumb-item>
|
||||
</transition-group>
|
||||
</el-breadcrumb>
|
||||
@@ -11,11 +11,9 @@
|
||||
|
||||
<script>
|
||||
import { generateTitle } from '@/utils/i18n'
|
||||
import pathToRegexp from 'path-to-regexp'
|
||||
|
||||
export default {
|
||||
created() {
|
||||
this.getBreadcrumb()
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
levelList: null
|
||||
@@ -26,12 +24,23 @@ export default {
|
||||
this.getBreadcrumb()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getBreadcrumb()
|
||||
},
|
||||
methods: {
|
||||
generateTitle,
|
||||
getBreadcrumb() {
|
||||
let matched = this.$route.matched.filter(item => item.name)
|
||||
const { params } = this.$route
|
||||
let matched = this.$route.matched.filter(item => {
|
||||
if (item.name) {
|
||||
// To solve this problem https://github.com/PanJiaChen/vue-element-admin/issues/561
|
||||
var toPath = pathToRegexp.compile(item.path)
|
||||
item.path = toPath(params)
|
||||
return true
|
||||
}
|
||||
})
|
||||
const first = matched[0]
|
||||
if (first && first.name !== 'dashboard') {
|
||||
if (first && first.name.trim().toLocaleLowerCase() !== 'Dashboard'.toLocaleLowerCase()) {
|
||||
matched = [{ path: '/dashboard', meta: { title: 'dashboard' }}].concat(matched)
|
||||
}
|
||||
this.levelList = matched
|
||||
|
@@ -1,11 +1,13 @@
|
||||
<template>
|
||||
<div :class="className" :id="id" :style="{height:height,width:width}"></div>
|
||||
<div :class="className" :id="id" :style="{height:height,width:width}"/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import resize from './mixins/resize'
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
@@ -54,6 +56,10 @@ export default {
|
||||
this.chart.setOption(
|
||||
{
|
||||
backgroundColor: '#08263a',
|
||||
grid: {
|
||||
left: '5%',
|
||||
right: '5%'
|
||||
},
|
||||
xAxis: [{
|
||||
show: false,
|
||||
data: xAxisData
|
||||
|
@@ -1,11 +1,13 @@
|
||||
<template>
|
||||
<div :class="className" :id="id" :style="{height:height,width:width}"></div>
|
||||
<div :class="className" :id="id" :style="{height:height,width:width}"/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import resize from './mixins/resize'
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
@@ -78,8 +80,8 @@ export default {
|
||||
},
|
||||
grid: {
|
||||
top: 100,
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
left: '2%',
|
||||
right: '2%',
|
||||
bottom: '2%',
|
||||
containLabel: true
|
||||
},
|
||||
|
@@ -1,11 +1,13 @@
|
||||
<template>
|
||||
<div :class="className" :id="id" :style="{height:height,width:width}"></div>
|
||||
<div :class="className" :id="id" :style="{height:height,width:width}"/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import echarts from 'echarts'
|
||||
import resize from './mixins/resize'
|
||||
|
||||
export default {
|
||||
mixins: [resize],
|
||||
props: {
|
||||
className: {
|
||||
type: String,
|
||||
@@ -31,7 +33,6 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.initChart()
|
||||
this.chart = null
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (!this.chart) {
|
||||
@@ -74,8 +75,10 @@ export default {
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
borderWidth: 0,
|
||||
top: 110,
|
||||
top: 150,
|
||||
bottom: 95,
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
|
28
src/components/Charts/mixins/resize.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import { debounce } from '@/utils'
|
||||
|
||||
export default {
|
||||
mounted() {
|
||||
this.__resizeHandler = debounce(() => {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
}, 100)
|
||||
window.addEventListener('resize', this.__resizeHandler)
|
||||
|
||||
const sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
||||
sidebarElm.addEventListener('transitionend', this.sidebarResizeHandler)
|
||||
},
|
||||
beforeDestroy() {
|
||||
window.removeEventListener('resize', this.__resizeHandler)
|
||||
|
||||
const sidebarElm = document.getElementsByClassName('sidebar-container')[0]
|
||||
sidebarElm.removeEventListener('transitionend', this.sidebarResizeHandler)
|
||||
},
|
||||
methods: {
|
||||
sidebarResizeHandler(e) {
|
||||
if (e.propertyName === 'width') {
|
||||
this.__resizeHandler()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,23 +1,23 @@
|
||||
<template>
|
||||
<div class="dndList">
|
||||
<div class="dndList-list" :style="{width:width1}">
|
||||
<h3>{{list1Title}}</h3>
|
||||
<draggable :list="list1" class="dragArea" :options="{group:'article'}">
|
||||
<div class="list-complete-item" v-for="element in list1" :key='element.id'>
|
||||
<div class="list-complete-item-handle">[{{element.author}}] {{element.title}}</div>
|
||||
<div :style="{width:width1}" class="dndList-list">
|
||||
<h3>{{ list1Title }}</h3>
|
||||
<draggable :list="list1" :options="{group:'article'}" class="dragArea">
|
||||
<div v-for="element in list1" :key="element.id" class="list-complete-item">
|
||||
<div class="list-complete-item-handle">[{{ element.author }}] {{ element.title }}</div>
|
||||
<div style="position:absolute;right:0px;">
|
||||
<span style="float: right ;margin-top: -20px;margin-right:5px;" @click="deleteEle(element)">
|
||||
<i style="color:#ff4949" class="el-icon-delete"></i>
|
||||
<i style="color:#ff4949" class="el-icon-delete"/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</draggable>
|
||||
</div>
|
||||
<div class="dndList-list" :style="{width:width2}">
|
||||
<h3>{{list2Title}}</h3>
|
||||
<draggable :list="filterList2" class="dragArea" :options="{group:'article'}">
|
||||
<div class="list-complete-item" v-for="element in filterList2" :key='element.id'>
|
||||
<div class='list-complete-item-handle2' @click="pushEle(element)"> [{{element.author}}] {{element.title}}</div>
|
||||
<div :style="{width:width2}" class="dndList-list">
|
||||
<h3>{{ list2Title }}</h3>
|
||||
<draggable :list="filterList2" :options="{group:'article'}" class="dragArea">
|
||||
<div v-for="element in filterList2" :key="element.id" class="list-complete-item">
|
||||
<div class="list-complete-item-handle2" @click="pushEle(element)"> [{{ element.author }}] {{ element.title }}</div>
|
||||
</div>
|
||||
</draggable>
|
||||
</div>
|
||||
@@ -30,16 +30,6 @@ import draggable from 'vuedraggable'
|
||||
export default {
|
||||
name: 'DndList',
|
||||
components: { draggable },
|
||||
computed: {
|
||||
filterList2() {
|
||||
return this.list2.filter(v => {
|
||||
if (this.isNotInList1(v)) {
|
||||
return v
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
},
|
||||
props: {
|
||||
list1: {
|
||||
type: Array,
|
||||
@@ -70,6 +60,16 @@ export default {
|
||||
default: '48%'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
filterList2() {
|
||||
return this.list2.filter(v => {
|
||||
if (this.isNotInList1(v)) {
|
||||
return v
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isNotInList1(v) {
|
||||
return this.list1.every(k => v.id !== k.id)
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div :ref="id" :action="url" class="dropzone" :id="id">
|
||||
<div :ref="id" :action="url" :id="id" class="dropzone">
|
||||
<input type="file" name="file">
|
||||
</div>
|
||||
</template>
|
||||
@@ -12,12 +12,81 @@ import 'dropzone/dist/dropzone.css'
|
||||
Dropzone.autoDiscover = false
|
||||
|
||||
export default {
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
clickable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
defaultMsg: {
|
||||
type: String,
|
||||
default: '上传图片'
|
||||
},
|
||||
acceptedFiles: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
thumbnailHeight: {
|
||||
type: Number,
|
||||
default: 200
|
||||
},
|
||||
thumbnailWidth: {
|
||||
type: Number,
|
||||
default: 200
|
||||
},
|
||||
showRemoveLink: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
maxFilesize: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
maxFiles: {
|
||||
type: Number,
|
||||
default: 3
|
||||
},
|
||||
autoProcessQueue: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
useCustomDropzoneOptions: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
defaultImg: {
|
||||
default: '',
|
||||
type: [String, Array]
|
||||
},
|
||||
couldPaste: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dropzone: '',
|
||||
initOnce: true
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
defaultImg(val) {
|
||||
if (val.length === 0) {
|
||||
this.initOnce = false
|
||||
return
|
||||
}
|
||||
if (!this.initOnce) return
|
||||
this.initImages(val)
|
||||
this.initOnce = false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const element = document.getElementById(this.id)
|
||||
const vm = this
|
||||
@@ -95,6 +164,10 @@ export default {
|
||||
vm.$emit('dropzone-successmultiple', file, error, xhr)
|
||||
})
|
||||
},
|
||||
destroyed() {
|
||||
document.removeEventListener('paste', this.pasteImg)
|
||||
this.dropzone.destroy()
|
||||
},
|
||||
methods: {
|
||||
removeAllFiles() {
|
||||
this.dropzone.removeAllFiles(true)
|
||||
@@ -128,76 +201,6 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
destroyed() {
|
||||
document.removeEventListener('paste', this.pasteImg)
|
||||
this.dropzone.destroy()
|
||||
},
|
||||
watch: {
|
||||
defaultImg(val) {
|
||||
if (val.length === 0) {
|
||||
this.initOnce = false
|
||||
return
|
||||
}
|
||||
if (!this.initOnce) return
|
||||
this.initImages(val)
|
||||
this.initOnce = false
|
||||
}
|
||||
},
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
clickable: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
defaultMsg: {
|
||||
type: String,
|
||||
default: '上传图片'
|
||||
},
|
||||
acceptedFiles: {
|
||||
type: String
|
||||
},
|
||||
thumbnailHeight: {
|
||||
type: Number,
|
||||
default: 200
|
||||
},
|
||||
thumbnailWidth: {
|
||||
type: Number,
|
||||
default: 200
|
||||
},
|
||||
showRemoveLink: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
maxFilesize: {
|
||||
type: Number,
|
||||
default: 2
|
||||
},
|
||||
maxFiles: {
|
||||
type: Number,
|
||||
default: 3
|
||||
},
|
||||
autoProcessQueue: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
useCustomDropzoneOptions: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
defaultImg: {
|
||||
default: false
|
||||
},
|
||||
couldPaste: {
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@@ -2,15 +2,24 @@
|
||||
<div v-if="errorLogs.length>0">
|
||||
<el-badge :is-dot="true" style="line-height: 30px;" @click.native="dialogTableVisible=true">
|
||||
<el-button size="small" type="danger" class="bug-btn">
|
||||
<svg t="1492682037685" class="bug-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1863"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128">
|
||||
<path d="M969.142857 548.571429q0 14.848-10.861714 25.709714t-25.709714 10.861714l-128 0q0 97.718857-38.290286 165.705143l118.857143 119.442286q10.861714 10.861714 10.861714 25.709714t-10.861714 25.709714q-10.276571 10.861714-25.709714 10.861714t-25.709714-10.861714l-113.152-112.566857q-2.852571 2.852571-8.557714 7.424t-23.990857 16.274286-37.156571 20.845714-46.848 16.566857-55.442286 7.424l0-512-73.142857 0 0 512q-29.147429 0-58.002286-7.716571t-49.700571-18.870857-37.705143-22.272-24.868571-18.578286l-8.557714-8.009143-104.557714 118.272q-11.446857 11.995429-27.428571 11.995429-13.714286 0-24.576-9.142857-10.861714-10.276571-11.702857-25.417143t8.850286-26.587429l115.419429-129.718857q-33.133714-65.133714-33.133714-156.562286l-128 0q-14.848 0-25.709714-10.861714t-10.861714-25.709714 10.861714-25.709714 25.709714-10.861714l128 0 0-168.009143-98.852571-98.852571q-10.861714-10.861714-10.861714-25.709714t10.861714-25.709714 25.709714-10.861714 25.709714 10.861714l98.852571 98.852571 482.304 0 98.852571-98.852571q10.861714-10.861714 25.709714-10.861714t25.709714 10.861714 10.861714 25.709714-10.861714 25.709714l-98.852571 98.852571 0 168.009143 128 0q14.848 0 25.709714 10.861714t10.861714 25.709714zM694.857143 219.428571l-365.714286 0q0-75.995429 53.430857-129.426286t129.426286-53.430857 129.426286 53.430857 53.430857 129.426286z"
|
||||
p-id="1864"></path>
|
||||
<svg
|
||||
t="1492682037685"
|
||||
class="bug-svg"
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="1863"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="128"
|
||||
height="128">
|
||||
<path
|
||||
d="M969.142857 548.571429q0 14.848-10.861714 25.709714t-25.709714 10.861714l-128 0q0 97.718857-38.290286 165.705143l118.857143 119.442286q10.861714 10.861714 10.861714 25.709714t-10.861714 25.709714q-10.276571 10.861714-25.709714 10.861714t-25.709714-10.861714l-113.152-112.566857q-2.852571 2.852571-8.557714 7.424t-23.990857 16.274286-37.156571 20.845714-46.848 16.566857-55.442286 7.424l0-512-73.142857 0 0 512q-29.147429 0-58.002286-7.716571t-49.700571-18.870857-37.705143-22.272-24.868571-18.578286l-8.557714-8.009143-104.557714 118.272q-11.446857 11.995429-27.428571 11.995429-13.714286 0-24.576-9.142857-10.861714-10.276571-11.702857-25.417143t8.850286-26.587429l115.419429-129.718857q-33.133714-65.133714-33.133714-156.562286l-128 0q-14.848 0-25.709714-10.861714t-10.861714-25.709714 10.861714-25.709714 25.709714-10.861714l128 0 0-168.009143-98.852571-98.852571q-10.861714-10.861714-10.861714-25.709714t10.861714-25.709714 25.709714-10.861714 25.709714 10.861714l98.852571 98.852571 482.304 0 98.852571-98.852571q10.861714-10.861714 25.709714-10.861714t25.709714 10.861714 10.861714 25.709714-10.861714 25.709714l-98.852571 98.852571 0 168.009143 128 0q14.848 0 25.709714 10.861714t10.861714 25.709714zM694.857143 219.428571l-365.714286 0q0-75.995429 53.430857-129.426286t129.426286-53.430857 129.426286 53.430857 53.430857 129.426286z"
|
||||
p-id="1864"/>
|
||||
</svg>
|
||||
</el-button>
|
||||
</el-badge>
|
||||
|
||||
<el-dialog title="Error Log" :visible.sync="dialogTableVisible" width="80%">
|
||||
<el-dialog :visible.sync="dialogTableVisible" title="Error Log" width="80%">
|
||||
<el-table :data="errorLogs" border>
|
||||
<el-table-column label="Message">
|
||||
<template slot-scope="scope">
|
||||
@@ -18,21 +27,21 @@
|
||||
<span class="message-title">Msg:</span>
|
||||
<el-tag type="danger">{{ scope.row.err.message }}</el-tag>
|
||||
</div>
|
||||
<br/>
|
||||
<br>
|
||||
<div>
|
||||
<span class="message-title" style="padding-right: 10px;">Info: </span>
|
||||
<el-tag type="warning">{{scope.row.vm.$vnode.tag}} error in {{scope.row.info}}</el-tag>
|
||||
<el-tag type="warning">{{ scope.row.vm.$vnode.tag }} error in {{ scope.row.info }}</el-tag>
|
||||
</div>
|
||||
<br/>
|
||||
<br>
|
||||
<div>
|
||||
<span class="message-title" style="padding-right: 16px;">Url: </span>
|
||||
<el-tag type="success">{{scope.row.url}}</el-tag>
|
||||
<el-tag type="success">{{ scope.row.url }}</el-tag>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="Stack">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.err.stack}}
|
||||
{{ scope.row.err.stack }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -43,7 +52,7 @@
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'errorLog',
|
||||
name: 'ErrorLog',
|
||||
data() {
|
||||
return {
|
||||
dialogTableVisible: false
|
||||
|
@@ -1,12 +1,21 @@
|
||||
<template>
|
||||
<a href="https://github.com/PanJiaChen/vue-element-admin" target="_blank" class="github-corner" aria-label="View source on Github">
|
||||
<svg width="80" height="80" viewBox="0 0 250 250" style="fill:#40c9c6; color:#fff; position: absolute; top: 84px; border: 0; right: 0;"
|
||||
<svg
|
||||
width="80"
|
||||
height="80"
|
||||
viewBox="0 0 250 250"
|
||||
style="fill:#40c9c6; color:#fff;"
|
||||
aria-hidden="true">
|
||||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path>
|
||||
<path 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"
|
||||
fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path>
|
||||
<path 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"
|
||||
fill="currentColor" class="octo-body"></path>
|
||||
<path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"/>
|
||||
<path
|
||||
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"
|
||||
fill="currentColor"
|
||||
style="transform-origin: 130px 106px;"
|
||||
class="octo-arm"/>
|
||||
<path
|
||||
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"
|
||||
fill="currentColor"
|
||||
class="octo-body"/>
|
||||
</svg>
|
||||
</a>
|
||||
</template>
|
||||
|
@@ -1,20 +1,34 @@
|
||||
<template>
|
||||
<div>
|
||||
<svg t="1492500959545" @click="toggleClick" class="wscn-icon hamburger" :class="{'is-active':isActive}" style="" viewBox="0 0 1024 1024"
|
||||
version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1691" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
|
||||
<path d="M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
|
||||
p-id="1692"></path>
|
||||
<path d="M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
|
||||
p-id="1693"></path>
|
||||
<path d="M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
|
||||
p-id="1694"></path>
|
||||
<svg
|
||||
:class="{'is-active':isActive}"
|
||||
t="1492500959545"
|
||||
class="hamburger"
|
||||
style=""
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="1691"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="64"
|
||||
height="64"
|
||||
@click="toggleClick">
|
||||
<path
|
||||
d="M966.8023 568.849776 57.196677 568.849776c-31.397081 0-56.850799-25.452695-56.850799-56.850799l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 543.397081 998.200404 568.849776 966.8023 568.849776z"
|
||||
p-id="1692"/>
|
||||
<path
|
||||
d="M966.8023 881.527125 57.196677 881.527125c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.849776 56.850799-56.849776l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.849776l0 0C1023.653099 856.07443 998.200404 881.527125 966.8023 881.527125z"
|
||||
p-id="1693"/>
|
||||
<path
|
||||
d="M966.8023 256.17345 57.196677 256.17345c-31.397081 0-56.850799-25.452695-56.850799-56.849776l0 0c0-31.397081 25.452695-56.850799 56.850799-56.850799l909.605623 0c31.397081 0 56.849776 25.452695 56.849776 56.850799l0 0C1023.653099 230.720755 998.200404 256.17345 966.8023 256.17345z"
|
||||
p-id="1694"/>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'hamburger',
|
||||
name: 'Hamburger',
|
||||
props: {
|
||||
isActive: {
|
||||
type: Boolean,
|
||||
@@ -30,16 +44,16 @@ export default {
|
||||
|
||||
<style scoped>
|
||||
.hamburger {
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
transform: rotate(90deg);
|
||||
transition: .38s;
|
||||
transform-origin: 50% 50%;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
transform: rotate(90deg);
|
||||
transition: .38s;
|
||||
transform-origin: 50% 50%;
|
||||
}
|
||||
|
||||
.hamburger.is-active {
|
||||
transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,41 +0,0 @@
|
||||
const langBag = {
|
||||
zh: {
|
||||
hint: '点击,或拖动图片至此处',
|
||||
loading: '正在上传……',
|
||||
noSupported: '浏览器不支持该功能,请使用IE10以上或其他现在浏览器!',
|
||||
success: '上传成功',
|
||||
fail: '图片上传失败',
|
||||
preview: '头像预览',
|
||||
btn: {
|
||||
off: '取消',
|
||||
close: '关闭',
|
||||
back: '上一步',
|
||||
save: '保存'
|
||||
},
|
||||
error: {
|
||||
onlyImg: '仅限图片格式',
|
||||
outOfSize: '单文件大小不能超过 ',
|
||||
lowestPx: '图片最低像素为(宽*高):'
|
||||
}
|
||||
},
|
||||
en: {
|
||||
hint: 'Click, or drag the file here',
|
||||
loading: 'Uploading……',
|
||||
noSupported: 'Browser does not support, please use IE10+ or other browsers',
|
||||
success: 'Upload success',
|
||||
fail: 'Upload failed',
|
||||
preview: 'Preview',
|
||||
btn: {
|
||||
off: 'Cancel',
|
||||
close: 'Close',
|
||||
back: 'Back',
|
||||
save: 'Save'
|
||||
},
|
||||
error: {
|
||||
onlyImg: 'Image only',
|
||||
outOfSize: 'Image exceeds size limit: ',
|
||||
lowestPx: 'The lowest pixel in the image: '
|
||||
}
|
||||
}
|
||||
}
|
||||
export default langBag
|
@@ -1,691 +0,0 @@
|
||||
@charset "UTF-8";
|
||||
@-webkit-keyframes vicp_progress {
|
||||
0% {
|
||||
background-position-y: 0;
|
||||
}
|
||||
100% {
|
||||
background-position-y: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes vicp_progress {
|
||||
0% {
|
||||
background-position-y: 0;
|
||||
}
|
||||
100% {
|
||||
background-position-y: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
@-webkit-keyframes vicp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale(0) translatey(-60px);
|
||||
transform: scale(0) translatey(-60px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale(1) translatey(0);
|
||||
transform: scale(1) translatey(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes vicp {
|
||||
0% {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale(0) translatey(-60px);
|
||||
transform: scale(0) translatey(-60px);
|
||||
}
|
||||
100% {
|
||||
opacity: 1;
|
||||
-webkit-transform: scale(1) translatey(0);
|
||||
transform: scale(1) translatey(0);
|
||||
}
|
||||
}
|
||||
|
||||
.vue-image-crop-upload {
|
||||
position: fixed;
|
||||
display: block;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
z-index: 10000;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.65);
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-moz-tap-highlight-color: transparent;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap {
|
||||
-webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
||||
position: fixed;
|
||||
display: block;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
z-index: 10000;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
width: 600px;
|
||||
height: 330px;
|
||||
padding: 25px;
|
||||
background-color: #fff;
|
||||
border-radius: 2px;
|
||||
-webkit-animation: vicp 0.12s ease-in;
|
||||
animation: vicp 0.12s ease-in;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-close {
|
||||
position: absolute;
|
||||
right: -30px;
|
||||
top: -30px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4 {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
cursor: pointer;
|
||||
-webkit-transition: -webkit-transform 0.18s;
|
||||
transition: -webkit-transform 0.18s;
|
||||
transition: transform 0.18s;
|
||||
transition: transform 0.18s, -webkit-transform 0.18s;
|
||||
-webkit-transform: rotate(0);
|
||||
-ms-transform: rotate(0);
|
||||
transform: rotate(0);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::after, .vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::before {
|
||||
-webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 12px;
|
||||
left: 4px;
|
||||
width: 20px;
|
||||
height: 3px;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4::after {
|
||||
-webkit-transform: rotate(-45deg);
|
||||
-ms-transform: rotate(-45deg);
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-close .vicp-icon4:hover {
|
||||
-webkit-transform: rotate(90deg);
|
||||
-ms-transform: rotate(90deg);
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area {
|
||||
position: relative;
|
||||
padding: 35px;
|
||||
height: 200px;
|
||||
background-color: rgba(0, 0, 0, 0.03);
|
||||
text-align: center;
|
||||
border: 1px dashed rgba(0, 0, 0, 0.08);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 {
|
||||
display: block;
|
||||
margin: 0 auto 6px;
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 .vicp-icon1-arrow {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-bottom: 14.7px solid rgba(0, 0, 0, 0.3);
|
||||
border-left: 14.7px solid transparent;
|
||||
border-right: 14.7px solid transparent;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 .vicp-icon1-body {
|
||||
display: block;
|
||||
width: 12.6px;
|
||||
height: 14.7px;
|
||||
margin: 0 auto;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-icon1 .vicp-icon1-bottom {
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
height: 12.6px;
|
||||
border: 6px solid rgba(0, 0, 0, 0.3);
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-hint {
|
||||
display: block;
|
||||
padding: 15px;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area .vicp-no-supported-hint {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 30px;
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
line-height: 30px;
|
||||
background-color: #eee;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step1 .vicp-drop-area:hover {
|
||||
cursor: pointer;
|
||||
border-color: rgba(0, 0, 0, 0.1);
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 240px;
|
||||
height: 180px;
|
||||
background-color: #e5e5e0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img {
|
||||
position: absolute;
|
||||
display: block;
|
||||
cursor: move;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img-shade {
|
||||
-webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
|
||||
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
|
||||
position: absolute;
|
||||
background-color: rgba(241, 242, 243, 0.8);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img-shade.vicp-img-shade-1 {
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-img-container .vicp-img-shade.vicp-img-shade-2 {
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range {
|
||||
position: relative;
|
||||
margin: 30px 0;
|
||||
width: 240px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5,
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5:hover,
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6:hover {
|
||||
-webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
||||
cursor: pointer;
|
||||
background-color: rgba(0, 0, 0, 0.14);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5 {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon5::before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
display: block;
|
||||
left: 3px;
|
||||
top: 8px;
|
||||
width: 12px;
|
||||
height: 2px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6 {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6::before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
display: block;
|
||||
left: 3px;
|
||||
top: 8px;
|
||||
width: 12px;
|
||||
height: 2px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range .vicp-icon6::after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
display: block;
|
||||
top: 3px;
|
||||
left: 8px;
|
||||
width: 2px;
|
||||
height: 12px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range] {
|
||||
display: block;
|
||||
padding-top: 5px;
|
||||
margin: 0 auto;
|
||||
width: 180px;
|
||||
height: 8px;
|
||||
vertical-align: top;
|
||||
background: transparent;
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
cursor: pointer;
|
||||
/* 滑块
|
||||
---------------------------------------------------------------*/
|
||||
/* 轨道
|
||||
---------------------------------------------------------------*/
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-webkit-slider-thumb {
|
||||
-webkit-box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
|
||||
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
margin-top: -3px;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background-color: #61c091;
|
||||
border-radius: 100%;
|
||||
border: none;
|
||||
-webkit-transition: 0.2s;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-moz-range-thumb {
|
||||
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
|
||||
-moz-appearance: none;
|
||||
appearance: none;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background-color: #61c091;
|
||||
border-radius: 100%;
|
||||
border: none;
|
||||
-webkit-transition: 0.2s;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-thumb {
|
||||
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.18);
|
||||
appearance: none;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background-color: #61c091;
|
||||
border: none;
|
||||
border-radius: 100%;
|
||||
-webkit-transition: 0.2s;
|
||||
transition: 0.2s;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:active::-moz-range-thumb {
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:active::-ms-thumb {
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:active::-webkit-slider-thumb {
|
||||
-webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.23);
|
||||
margin-top: -4px;
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-webkit-slider-runnable-track {
|
||||
-webkit-box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
cursor: pointer;
|
||||
border-radius: 2px;
|
||||
border: none;
|
||||
background-color: rgba(68, 170, 119, 0.3);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-moz-range-track {
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
cursor: pointer;
|
||||
border-radius: 2px;
|
||||
border: none;
|
||||
background-color: rgba(68, 170, 119, 0.3);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-track {
|
||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.12);
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
background: transparent;
|
||||
border-color: transparent;
|
||||
color: transparent;
|
||||
height: 6px;
|
||||
border-radius: 2px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-fill-lower {
|
||||
background-color: rgba(68, 170, 119, 0.3);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]::-ms-fill-upper {
|
||||
background-color: rgba(68, 170, 119, 0.15);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-webkit-slider-runnable-track {
|
||||
background-color: rgba(68, 170, 119, 0.5);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-moz-range-track {
|
||||
background-color: rgba(68, 170, 119, 0.5);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-ms-fill-lower {
|
||||
background-color: rgba(68, 170, 119, 0.45);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-left .vicp-range input[type=range]:focus::-ms-fill-upper {
|
||||
background-color: rgba(68, 170, 119, 0.25);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview {
|
||||
height: 150px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item {
|
||||
position: relative;
|
||||
padding: 5px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
float: left;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item span {
|
||||
position: absolute;
|
||||
bottom: -30px;
|
||||
width: 100%;
|
||||
font-size: 14px;
|
||||
color: #bbb;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item img {
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
margin: auto;
|
||||
padding: 3px;
|
||||
background-color: #fff;
|
||||
border: 1px solid rgba(0, 0, 0, 0.15);
|
||||
overflow: hidden;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step2 .vicp-crop .vicp-crop-right .vicp-preview .vicp-preview-item:last-child img {
|
||||
border-radius: 100%;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload {
|
||||
position: relative;
|
||||
padding: 35px;
|
||||
height: 200px;
|
||||
background-color: rgba(0, 0, 0, 0.03);
|
||||
text-align: center;
|
||||
border: 1px dashed #ddd;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-loading {
|
||||
display: block;
|
||||
padding: 15px;
|
||||
font-size: 16px;
|
||||
color: #999;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap {
|
||||
margin-top: 12px;
|
||||
background-color: rgba(0, 0, 0, 0.08);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap .vicp-progress {
|
||||
position: relative;
|
||||
display: block;
|
||||
height: 5px;
|
||||
border-radius: 3px;
|
||||
background-color: #4a7;
|
||||
-webkit-box-shadow: 0 2px 6px 0 rgba(68, 170, 119, 0.3);
|
||||
box-shadow: 0 2px 6px 0 rgba(68, 170, 119, 0.3);
|
||||
-webkit-transition: width 0.15s linear;
|
||||
transition: width 0.15s linear;
|
||||
background-image: -webkit-linear-gradient(135deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent);
|
||||
background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.2) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, transparent 75%, transparent);
|
||||
background-size: 40px 40px;
|
||||
-webkit-animation: vicp_progress 0.5s linear infinite;
|
||||
animation: vicp_progress 0.5s linear infinite;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-progress-wrap .vicp-progress::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: -3px;
|
||||
right: -3px;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border: 1px solid rgba(245, 246, 247, 0.7);
|
||||
-webkit-box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7);
|
||||
box-shadow: 0 1px 4px 0 rgba(68, 170, 119, 0.7);
|
||||
border-radius: 100%;
|
||||
background-color: #4a7;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-error,
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-step3 .vicp-upload .vicp-success {
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-operate {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
bottom: 20px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-operate a {
|
||||
position: relative;
|
||||
float: left;
|
||||
display: block;
|
||||
margin-left: 10px;
|
||||
width: 100px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: #4a7;
|
||||
border-radius: 2px;
|
||||
overflow: hidden;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-operate a:hover {
|
||||
background-color: rgba(0, 0, 0, 0.03);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-error,
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-success {
|
||||
display: block;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
height: 24px;
|
||||
color: #d10;
|
||||
text-align: center;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-success {
|
||||
color: #4a7;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-icon3 {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
top: 4px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-icon3::after {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: 6px;
|
||||
width: 6px;
|
||||
height: 10px;
|
||||
border-width: 0 2px 2px 0;
|
||||
border-color: #4a7;
|
||||
border-style: solid;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
content: '';
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-icon2 {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
top: 4px;
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-icon2::after, .vue-image-crop-upload .vicp-wrap .vicp-icon2::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
left: 4px;
|
||||
width: 13px;
|
||||
height: 2px;
|
||||
background-color: #d10;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.vue-image-crop-upload .vicp-wrap .vicp-icon2::after {
|
||||
-webkit-transform: rotate(-45deg);
|
||||
-ms-transform: rotate(-45deg);
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.e-ripple {
|
||||
position: absolute;
|
||||
border-radius: 100%;
|
||||
background-color: rgba(0, 0, 0, 0.15);
|
||||
background-clip: padding-box;
|
||||
pointer-events: none;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-transform: scale(0);
|
||||
-ms-transform: scale(0);
|
||||
transform: scale(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.e-ripple.z-active {
|
||||
opacity: 0;
|
||||
-webkit-transform: scale(2);
|
||||
-ms-transform: scale(2);
|
||||
transform: scale(2);
|
||||
-webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
|
||||
transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
|
||||
transition: opacity 1.2s ease-out, transform 0.6s ease-out;
|
||||
transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out;
|
||||
}
|
@@ -1,58 +0,0 @@
|
||||
/* eslint-disable */
|
||||
|
||||
/**
|
||||
*
|
||||
* @param e
|
||||
* @param arg_opts
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function effectRipple(e, arg_opts) {
|
||||
let opts = Object.assign({
|
||||
ele: e.target, // 波纹作用元素
|
||||
type: 'hit', // hit点击位置扩散 center中心点扩展
|
||||
bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
|
||||
}, arg_opts),
|
||||
target = opts.ele;
|
||||
if (target) {
|
||||
let rect = target.getBoundingClientRect(),
|
||||
ripple = target.querySelector('.e-ripple');
|
||||
if (!ripple) {
|
||||
ripple = document.createElement('span');
|
||||
ripple.className = 'e-ripple';
|
||||
ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px';
|
||||
target.appendChild(ripple);
|
||||
} else {
|
||||
ripple.className = 'e-ripple';
|
||||
}
|
||||
switch (opts.type) {
|
||||
case 'center':
|
||||
ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px';
|
||||
ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px';
|
||||
break;
|
||||
default:
|
||||
ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px';
|
||||
ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px';
|
||||
}
|
||||
ripple.style.backgroundColor = opts.bgc;
|
||||
ripple.className = 'e-ripple z-active';
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// database64文件格式转换为2进制
|
||||
/**
|
||||
*
|
||||
* @param data
|
||||
* @param mime
|
||||
* @returns {*}
|
||||
*/
|
||||
export function data2blob(data, mime) {
|
||||
// dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了
|
||||
data = data.split(',')[1];
|
||||
data = window.atob(data);
|
||||
var ia = new Uint8Array(data.length);
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
ia[i] = data.charCodeAt(i);
|
||||
}
|
||||
// canvas.toDataURL 返回的默认格式就是 image/png
|
||||
return new Blob([ia], {type: mime});
|
||||
};
|
19
src/components/ImageCropper/utils/data2blob.js
Executable file
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* database64文件格式转换为2进制
|
||||
*
|
||||
* @param {[String]} data dataURL 的格式为 “data:image/png;base64,****”,逗号之前都是一些说明性的文字,我们只需要逗号之后的就行了
|
||||
* @param {[String]} mime [description]
|
||||
* @return {[blob]} [description]
|
||||
*/
|
||||
export default function(data, mime) {
|
||||
data = data.split(',')[1]
|
||||
data = window.atob(data)
|
||||
var ia = new Uint8Array(data.length)
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
ia[i] = data.charCodeAt(i)
|
||||
}
|
||||
// canvas.toDataURL 返回的默认格式就是 image/png
|
||||
return new Blob([ia], {
|
||||
type: mime
|
||||
})
|
||||
}
|
39
src/components/ImageCropper/utils/effectRipple.js
Executable file
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 点击波纹效果
|
||||
*
|
||||
* @param {[event]} e [description]
|
||||
* @param {[Object]} arg_opts [description]
|
||||
* @return {[bollean]} [description]
|
||||
*/
|
||||
export default function(e, arg_opts) {
|
||||
var opts = Object.assign({
|
||||
ele: e.target, // 波纹作用元素
|
||||
type: 'hit', // hit点击位置扩散center中心点扩展
|
||||
bgc: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
|
||||
}, arg_opts)
|
||||
var target = opts.ele
|
||||
if (target) {
|
||||
var rect = target.getBoundingClientRect()
|
||||
var ripple = target.querySelector('.e-ripple')
|
||||
if (!ripple) {
|
||||
ripple = document.createElement('span')
|
||||
ripple.className = 'e-ripple'
|
||||
ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
|
||||
target.appendChild(ripple)
|
||||
} else {
|
||||
ripple.className = 'e-ripple'
|
||||
}
|
||||
switch (opts.type) {
|
||||
case 'center':
|
||||
ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px'
|
||||
ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'
|
||||
break
|
||||
default:
|
||||
ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px'
|
||||
ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px'
|
||||
}
|
||||
ripple.style.backgroundColor = opts.bgc
|
||||
ripple.className = 'e-ripple z-active'
|
||||
return false
|
||||
}
|
||||
}
|
232
src/components/ImageCropper/utils/language.js
Executable file
@@ -0,0 +1,232 @@
|
||||
export default {
|
||||
zh: {
|
||||
hint: '点击,或拖动图片至此处',
|
||||
loading: '正在上传……',
|
||||
noSupported: '浏览器不支持该功能,请使用IE10以上或其他现在浏览器!',
|
||||
success: '上传成功',
|
||||
fail: '图片上传失败',
|
||||
preview: '头像预览',
|
||||
btn: {
|
||||
off: '取消',
|
||||
close: '关闭',
|
||||
back: '上一步',
|
||||
save: '保存'
|
||||
},
|
||||
error: {
|
||||
onlyImg: '仅限图片格式',
|
||||
outOfSize: '单文件大小不能超过 ',
|
||||
lowestPx: '图片最低像素为(宽*高):'
|
||||
}
|
||||
},
|
||||
'zh-tw': {
|
||||
hint: '點擊,或拖動圖片至此處',
|
||||
loading: '正在上傳……',
|
||||
noSupported: '瀏覽器不支持該功能,請使用IE10以上或其他現代瀏覽器!',
|
||||
success: '上傳成功',
|
||||
fail: '圖片上傳失敗',
|
||||
preview: '頭像預覽',
|
||||
btn: {
|
||||
off: '取消',
|
||||
close: '關閉',
|
||||
back: '上一步',
|
||||
save: '保存'
|
||||
},
|
||||
error: {
|
||||
onlyImg: '僅限圖片格式',
|
||||
outOfSize: '單文件大小不能超過 ',
|
||||
lowestPx: '圖片最低像素為(寬*高):'
|
||||
}
|
||||
},
|
||||
en: {
|
||||
hint: 'Click or drag the file here to upload',
|
||||
loading: 'Uploading…',
|
||||
noSupported: 'Browser is not supported, please use IE10+ or other browsers',
|
||||
success: 'Upload success',
|
||||
fail: 'Upload failed',
|
||||
preview: 'Preview',
|
||||
btn: {
|
||||
off: 'Cancel',
|
||||
close: 'Close',
|
||||
back: 'Back',
|
||||
save: 'Save'
|
||||
},
|
||||
error: {
|
||||
onlyImg: 'Image only',
|
||||
outOfSize: 'Image exceeds size limit: ',
|
||||
lowestPx: 'Image\'s size is too low. Expected at least: '
|
||||
}
|
||||
},
|
||||
ro: {
|
||||
hint: 'Atinge sau trage fișierul aici',
|
||||
loading: 'Se încarcă',
|
||||
noSupported: 'Browser-ul tău nu suportă acest feature. Te rugăm încearcă cu alt browser.',
|
||||
success: 'S-a încărcat cu succes',
|
||||
fail: 'A apărut o problemă la încărcare',
|
||||
preview: 'Previzualizează',
|
||||
|
||||
btn: {
|
||||
off: 'Anulează',
|
||||
close: 'Închide',
|
||||
back: 'Înapoi',
|
||||
save: 'Salvează'
|
||||
},
|
||||
|
||||
error: {
|
||||
onlyImg: 'Doar imagini',
|
||||
outOfSize: 'Imaginea depășește limita de: ',
|
||||
loewstPx: 'Imaginea este prea mică; Minim: '
|
||||
}
|
||||
},
|
||||
ru: {
|
||||
hint: 'Нажмите, или перетащите файл в это окно',
|
||||
loading: 'Загружаю……',
|
||||
noSupported: 'Ваш браузер не поддерживается, пожалуйста, используйте IE10 + или другие браузеры',
|
||||
success: 'Загрузка выполнена успешно',
|
||||
fail: 'Ошибка загрузки',
|
||||
preview: 'Предпросмотр',
|
||||
btn: {
|
||||
off: 'Отменить',
|
||||
close: 'Закрыть',
|
||||
back: 'Назад',
|
||||
save: 'Сохранить'
|
||||
},
|
||||
error: {
|
||||
onlyImg: 'Только изображения',
|
||||
outOfSize: 'Изображение превышает предельный размер: ',
|
||||
lowestPx: 'Минимальный размер изображения: '
|
||||
}
|
||||
},
|
||||
'pt-br': {
|
||||
hint: 'Clique ou arraste o arquivo aqui para carregar',
|
||||
loading: 'Carregando…',
|
||||
noSupported: 'Browser não suportado, use o IE10+ ou outro browser',
|
||||
success: 'Sucesso ao carregar imagem',
|
||||
fail: 'Falha ao carregar imagem',
|
||||
preview: 'Pré-visualizar',
|
||||
btn: {
|
||||
off: 'Cancelar',
|
||||
close: 'Fechar',
|
||||
back: 'Voltar',
|
||||
save: 'Salvar'
|
||||
},
|
||||
error: {
|
||||
onlyImg: 'Apenas imagens',
|
||||
outOfSize: 'A imagem excede o limite de tamanho: ',
|
||||
lowestPx: 'O tamanho da imagem é muito pequeno. Tamanho mínimo: '
|
||||
}
|
||||
},
|
||||
fr: {
|
||||
hint: 'Cliquez ou glissez le fichier ici.',
|
||||
loading: 'Téléchargement…',
|
||||
noSupported: 'Votre navigateur n\'est pas supporté. Utilisez IE10 + ou un autre navigateur s\'il vous plaît.',
|
||||
success: 'Téléchargement réussit',
|
||||
fail: 'Téléchargement echoué',
|
||||
preview: 'Aperçu',
|
||||
btn: {
|
||||
off: 'Annuler',
|
||||
close: 'Fermer',
|
||||
back: 'Retour',
|
||||
save: 'Enregistrer'
|
||||
},
|
||||
error: {
|
||||
onlyImg: 'Image uniquement',
|
||||
outOfSize: 'L\'image sélectionnée dépasse la taille maximum: ',
|
||||
lowestPx: 'L\'image sélectionnée est trop petite. Dimensions attendues: '
|
||||
}
|
||||
},
|
||||
nl: {
|
||||
hint: 'Klik hier of sleep een afbeelding in dit vlak',
|
||||
loading: 'Uploaden…',
|
||||
noSupported: 'Je browser wordt helaas niet ondersteund. Gebruik IE10+ of een andere browser.',
|
||||
success: 'Upload succesvol',
|
||||
fail: 'Upload mislukt',
|
||||
preview: 'Voorbeeld',
|
||||
btn: {
|
||||
off: 'Annuleren',
|
||||
close: 'Sluiten',
|
||||
back: 'Terug',
|
||||
save: 'Opslaan'
|
||||
},
|
||||
error: {
|
||||
onlyImg: 'Alleen afbeeldingen',
|
||||
outOfSize: 'De afbeelding is groter dan: ',
|
||||
lowestPx: 'De afbeelding is te klein! Minimale afmetingen: '
|
||||
}
|
||||
},
|
||||
tr: {
|
||||
hint: 'Tıkla veya yüklemek istediğini buraya sürükle',
|
||||
loading: 'Yükleniyor…',
|
||||
noSupported: 'Tarayıcı desteklenmiyor, lütfen IE10+ veya farklı tarayıcı kullanın',
|
||||
success: 'Yükleme başarılı',
|
||||
fail: 'Yüklemede hata oluştu',
|
||||
preview: 'Önizle',
|
||||
btn: {
|
||||
off: 'İptal',
|
||||
close: 'Kapat',
|
||||
back: 'Geri',
|
||||
save: 'Kaydet'
|
||||
},
|
||||
error: {
|
||||
onlyImg: 'Sadece resim',
|
||||
outOfSize: 'Resim yükleme limitini aşıyor: ',
|
||||
lowestPx: 'Resmin boyutu çok küçük. En az olması gereken: '
|
||||
}
|
||||
},
|
||||
'es-MX': {
|
||||
hint: 'Selecciona o arrastra una imagen',
|
||||
loading: 'Subiendo...',
|
||||
noSupported: 'Tu navegador no es soportado, porfavor usa IE10+ u otros navegadores mas recientes',
|
||||
success: 'Subido exitosamente',
|
||||
fail: 'Sucedió un error',
|
||||
preview: 'Vista previa',
|
||||
btn: {
|
||||
off: 'Cancelar',
|
||||
close: 'Cerrar',
|
||||
back: 'Atras',
|
||||
save: 'Guardar'
|
||||
},
|
||||
error: {
|
||||
onlyImg: 'Unicamente imagenes',
|
||||
outOfSize: 'La imagen excede el tamaño maximo:',
|
||||
lowestPx: 'La imagen es demasiado pequeño. Se espera por lo menos:'
|
||||
}
|
||||
},
|
||||
de: {
|
||||
hint: 'Klick hier oder zieh eine Datei hier rein zum Hochladen',
|
||||
loading: 'Hochladen…',
|
||||
noSupported: 'Browser wird nicht unterstützt, bitte verwende IE10+ oder andere Browser',
|
||||
success: 'Upload erfolgreich',
|
||||
fail: 'Upload fehlgeschlagen',
|
||||
preview: 'Vorschau',
|
||||
btn: {
|
||||
off: 'Abbrechen',
|
||||
close: 'Schließen',
|
||||
back: 'Zurück',
|
||||
save: 'Speichern'
|
||||
},
|
||||
error: {
|
||||
onlyImg: 'Nur Bilder',
|
||||
outOfSize: 'Das Bild ist zu groß: ',
|
||||
lowestPx: 'Das Bild ist zu klein. Mindestens: '
|
||||
}
|
||||
},
|
||||
ja: {
|
||||
hint: 'クリック・ドラッグしてファイルをアップロード',
|
||||
loading: 'アップロード中...',
|
||||
noSupported: 'このブラウザは対応されていません。IE10+かその他の主要ブラウザをお使いください。',
|
||||
success: 'アップロード成功',
|
||||
fail: 'アップロード失敗',
|
||||
preview: 'プレビュー',
|
||||
btn: {
|
||||
off: 'キャンセル',
|
||||
close: '閉じる',
|
||||
back: '戻る',
|
||||
save: '保存'
|
||||
},
|
||||
error: {
|
||||
onlyImg: '画像のみ',
|
||||
outOfSize: '画像サイズが上限を超えています。上限: ',
|
||||
lowestPx: '画像が小さすぎます。最小サイズ: '
|
||||
}
|
||||
}
|
||||
}
|
7
src/components/ImageCropper/utils/mimes.js
Executable file
@@ -0,0 +1,7 @@
|
||||
export default {
|
||||
'jpg': 'image/jpeg',
|
||||
'png': 'image/png',
|
||||
'gif': 'image/gif',
|
||||
'svg': 'image/svg+xml',
|
||||
'psd': 'image/photoshop'
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="json-editor">
|
||||
<textarea ref="textarea"></textarea>
|
||||
<textarea ref="textarea"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -15,13 +15,14 @@ import 'codemirror/addon/lint/lint'
|
||||
import 'codemirror/addon/lint/json-lint'
|
||||
|
||||
export default {
|
||||
name: 'jsonEditor',
|
||||
name: 'JsonEditor',
|
||||
/* eslint-disable vue/require-prop-types */
|
||||
props: ['value'],
|
||||
data() {
|
||||
return {
|
||||
jsonEditor: false
|
||||
}
|
||||
},
|
||||
props: ['value'],
|
||||
watch: {
|
||||
value(value) {
|
||||
const editor_value = this.jsonEditor.getValue()
|
||||
|
89
src/components/Kanban/index.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template>
|
||||
<div class="board-column">
|
||||
<div class="board-column-header">
|
||||
{{ headerText }}
|
||||
</div>
|
||||
<draggable
|
||||
:list="list"
|
||||
:options="options"
|
||||
class="board-column-content">
|
||||
<div v-for="element in list" :key="element.id" class="board-item">
|
||||
{{ element.name }} {{ element.id }}
|
||||
</div>
|
||||
</draggable>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import draggable from 'vuedraggable'
|
||||
|
||||
export default {
|
||||
name: 'DragKanbanDemo',
|
||||
components: {
|
||||
draggable
|
||||
},
|
||||
props: {
|
||||
headerText: {
|
||||
type: String,
|
||||
default: 'Header'
|
||||
},
|
||||
options: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.board-column {
|
||||
min-width: 300px;
|
||||
min-height: 100px;
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
background: #f0f0f0;
|
||||
border-radius: 3px;
|
||||
|
||||
.board-column-header {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
overflow: hidden;
|
||||
padding: 0 20px;
|
||||
text-align: center;
|
||||
background: #333;
|
||||
color: #fff;
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
|
||||
.board-column-content {
|
||||
height: auto;
|
||||
overflow: hidden;
|
||||
border: 10px solid transparent;
|
||||
min-height: 60px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
.board-item {
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
height: 64px;
|
||||
margin: 5px 0;
|
||||
background-color: #fff;
|
||||
text-align: left;
|
||||
line-height: 54px;
|
||||
padding: 5px 10px;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0px 1px 3px 0 rgba(0,0,0,0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<el-dropdown trigger="click" class='international' @command="handleSetLanguage">
|
||||
<el-dropdown trigger="click" class="international" @command="handleSetLanguage">
|
||||
<div>
|
||||
<svg-icon class-name='international-icon' icon-class="language" />
|
||||
<svg-icon class-name="international-icon" icon-class="language" />
|
||||
</div>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item command="zh" :disabled="language==='zh'">中文</el-dropdown-item>
|
||||
<el-dropdown-item command="en" :disabled="language==='en'">English</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="language==='zh'" command="zh">中文</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="language==='en'" command="en">English</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
@@ -22,7 +22,7 @@ export default {
|
||||
this.$i18n.locale = lang
|
||||
this.$store.dispatch('setLanguage', lang)
|
||||
this.$message({
|
||||
message: 'switch language success',
|
||||
message: 'Switch Language Success',
|
||||
type: 'success'
|
||||
})
|
||||
}
|
||||
@@ -38,4 +38,3 @@ export default {
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
@@ -1,28 +1,103 @@
|
||||
<template>
|
||||
<div class="material-input__component" :class="computedClasses">
|
||||
<div :class="computedClasses" class="material-input__component">
|
||||
<div :class="{iconClass:icon}">
|
||||
<i class="el-input__icon material-input__icon" :class="['el-icon-' + icon]" v-if="icon"></i>
|
||||
<input v-if="type === 'email'" type="email" class="material-input" :name="name" :placeholder="fillPlaceHolder" v-model="currentValue"
|
||||
:readonly="readonly" :disabled="disabled" :autoComplete="autoComplete" :required="required" @focus="handleMdFocus"
|
||||
@blur="handleMdBlur" @input="handleModelInput">
|
||||
<input v-if="type === 'url'" type="url" class="material-input" :name="name" :placeholder="fillPlaceHolder" v-model="currentValue"
|
||||
:readonly="readonly" :disabled="disabled" :autoComplete="autoComplete" :required="required" @focus="handleMdFocus"
|
||||
@blur="handleMdBlur" @input="handleModelInput">
|
||||
<input v-if="type === 'number'" type="number" class="material-input" :name="name" :placeholder="fillPlaceHolder" v-model="currentValue"
|
||||
:step="step" :readonly="readonly" :disabled="disabled" :autoComplete="autoComplete" :max="max" :min="min" :minlength="minlength"
|
||||
:maxlength="maxlength" :required="required" @focus="handleMdFocus" @blur="handleMdBlur" @input="handleModelInput">
|
||||
<input v-if="type === 'password'" type="password" class="material-input" :name="name" :placeholder="fillPlaceHolder" v-model="currentValue"
|
||||
:readonly="readonly" :disabled="disabled" :autoComplete="autoComplete" :max="max" :min="min" :required="required" @focus="handleMdFocus"
|
||||
@blur="handleMdBlur" @input="handleModelInput">
|
||||
<input v-if="type === 'tel'" type="tel" class="material-input" :name="name" :placeholder="fillPlaceHolder" v-model="currentValue"
|
||||
:readonly="readonly" :disabled="disabled" :autoComplete="autoComplete" :required="required" @focus="handleMdFocus"
|
||||
@blur="handleMdBlur" @input="handleModelInput">
|
||||
<input v-if="type === 'text'" type="text" class="material-input" :name="name" :placeholder="fillPlaceHolder" v-model="currentValue"
|
||||
:readonly="readonly" :disabled="disabled" :autoComplete="autoComplete" :minlength="minlength" :maxlength="maxlength"
|
||||
:required="required" @focus="handleMdFocus" @blur="handleMdBlur" @input="handleModelInput">
|
||||
<span class="material-input-bar"></span>
|
||||
<i v-if="icon" :class="['el-icon-' + icon]" class="el-input__icon material-input__icon"/>
|
||||
<input
|
||||
v-if="type === 'email'"
|
||||
:name="name"
|
||||
:placeholder="fillPlaceHolder"
|
||||
v-model="currentValue"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
:autoComplete="autoComplete"
|
||||
:required="required"
|
||||
type="email"
|
||||
class="material-input"
|
||||
@focus="handleMdFocus"
|
||||
@blur="handleMdBlur"
|
||||
@input="handleModelInput">
|
||||
<input
|
||||
v-if="type === 'url'"
|
||||
:name="name"
|
||||
:placeholder="fillPlaceHolder"
|
||||
v-model="currentValue"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
:autoComplete="autoComplete"
|
||||
:required="required"
|
||||
type="url"
|
||||
class="material-input"
|
||||
@focus="handleMdFocus"
|
||||
@blur="handleMdBlur"
|
||||
@input="handleModelInput">
|
||||
<input
|
||||
v-if="type === 'number'"
|
||||
:name="name"
|
||||
:placeholder="fillPlaceHolder"
|
||||
v-model="currentValue"
|
||||
:step="step"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
:autoComplete="autoComplete"
|
||||
:max="max"
|
||||
:min="min"
|
||||
:minlength="minlength"
|
||||
:maxlength="maxlength"
|
||||
:required="required"
|
||||
type="number"
|
||||
class="material-input"
|
||||
@focus="handleMdFocus"
|
||||
@blur="handleMdBlur"
|
||||
@input="handleModelInput">
|
||||
<input
|
||||
v-if="type === 'password'"
|
||||
:name="name"
|
||||
:placeholder="fillPlaceHolder"
|
||||
v-model="currentValue"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
:autoComplete="autoComplete"
|
||||
:max="max"
|
||||
:min="min"
|
||||
:required="required"
|
||||
type="password"
|
||||
class="material-input"
|
||||
@focus="handleMdFocus"
|
||||
@blur="handleMdBlur"
|
||||
@input="handleModelInput">
|
||||
<input
|
||||
v-if="type === 'tel'"
|
||||
:name="name"
|
||||
:placeholder="fillPlaceHolder"
|
||||
v-model="currentValue"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
:autoComplete="autoComplete"
|
||||
:required="required"
|
||||
type="tel"
|
||||
class="material-input"
|
||||
@focus="handleMdFocus"
|
||||
@blur="handleMdBlur"
|
||||
@input="handleModelInput">
|
||||
<input
|
||||
v-if="type === 'text'"
|
||||
:name="name"
|
||||
:placeholder="fillPlaceHolder"
|
||||
v-model="currentValue"
|
||||
:readonly="readonly"
|
||||
:disabled="disabled"
|
||||
:autoComplete="autoComplete"
|
||||
:minlength="minlength"
|
||||
:maxlength="maxlength"
|
||||
:required="required"
|
||||
type="text"
|
||||
class="material-input"
|
||||
@focus="handleMdFocus"
|
||||
@blur="handleMdBlur"
|
||||
@input="handleModelInput">
|
||||
<span class="material-input-bar"/>
|
||||
<label class="material-label">
|
||||
<slot></slot>
|
||||
<slot/>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -32,8 +107,9 @@
|
||||
// source:https://github.com/wemake-services/vue-material-input/blob/master/src/components/MaterialInput.vue
|
||||
|
||||
export default {
|
||||
name: 'md-input',
|
||||
name: 'MdInput',
|
||||
props: {
|
||||
/* eslint-disable */
|
||||
icon: String,
|
||||
name: String,
|
||||
type: {
|
||||
@@ -62,6 +138,13 @@ export default {
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentValue: this.value,
|
||||
focus: false,
|
||||
fillPlaceHolder: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
computedClasses() {
|
||||
return {
|
||||
@@ -76,13 +159,6 @@ export default {
|
||||
this.currentValue = newValue
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentValue: this.value,
|
||||
focus: false,
|
||||
fillPlaceHolder: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleModelInput(event) {
|
||||
const value = event.target.value
|
||||
|
@@ -1,7 +1,6 @@
|
||||
<template>
|
||||
<div class="simplemde-container" :style="{height:height+'px',zIndex:zIndex}">
|
||||
<textarea :id="id">
|
||||
</textarea>
|
||||
<div :style="{height:height+'px',zIndex:zIndex}" class="simplemde-container">
|
||||
<textarea :id="id"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -11,11 +10,16 @@ import 'simplemde/dist/simplemde.min.css'
|
||||
import SimpleMDE from 'simplemde'
|
||||
|
||||
export default {
|
||||
name: 'simplemde-md',
|
||||
name: 'SimplemdeMd',
|
||||
props: {
|
||||
value: String,
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
id: {
|
||||
type: String
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'markdown-editor-' + +new Date()
|
||||
},
|
||||
autofocus: {
|
||||
type: Boolean,
|
||||
@@ -34,7 +38,10 @@ export default {
|
||||
default: 10
|
||||
},
|
||||
toolbar: {
|
||||
type: Array
|
||||
type: Array,
|
||||
default: function() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -51,10 +58,10 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.simplemde = new SimpleMDE({
|
||||
element: document.getElementById(this.id || 'markdown-editor-' + +new Date()),
|
||||
element: document.getElementById(this.id),
|
||||
autoDownloadFontAwesome: false,
|
||||
autofocus: this.autofocus,
|
||||
toolbar: this.toolbar,
|
||||
toolbar: this.toolbar.length > 0 ? this.toolbar : undefined,
|
||||
spellChecker: false,
|
||||
insertTexts: {
|
||||
link: ['[', ']( )']
|
||||
@@ -73,47 +80,44 @@ export default {
|
||||
})
|
||||
},
|
||||
destroyed() {
|
||||
this.simplemde.toTextArea()
|
||||
this.simplemde = null
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.simplemde-container .CodeMirror {
|
||||
<style scoped>
|
||||
.simplemde-container>>>.CodeMirror {
|
||||
min-height: 150px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.simplemde-container>>>.CodeMirror-scroll {
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
.simplemde-container .CodeMirror-scroll {
|
||||
min-height: 150px;
|
||||
}
|
||||
|
||||
.simplemde-container .CodeMirror-code {
|
||||
.simplemde-container>>>.CodeMirror-code {
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.simplemde-container .editor-statusbar {
|
||||
.simplemde-container>>>.editor-statusbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.simplemde-container .CodeMirror .CodeMirror-code .cm-link {
|
||||
color: #1482F0;
|
||||
.simplemde-container>>>.CodeMirror .CodeMirror-code .cm-link {
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.simplemde-container .CodeMirror .CodeMirror-code .cm-string.cm-url {
|
||||
.simplemde-container>>>.CodeMirror .CodeMirror-code .cm-string.cm-url {
|
||||
color: #2d3b4d;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.simplemde-container .CodeMirror .CodeMirror-code .cm-formatting-link-string.cm-url {
|
||||
.simplemde-container>>>.CodeMirror .CodeMirror-code .cm-formatting-link-string.cm-url {
|
||||
padding: 0 2px;
|
||||
font-weight: bold;
|
||||
color: #E61E1E;
|
||||
}
|
||||
|
||||
.simplemde-container .editor-toolbar.fullscreen,
|
||||
.simplemde-container .CodeMirror-fullscreen {
|
||||
.simplemde-container >>> .editor-toolbar.fullscreen,
|
||||
.simplemde-container >>> .CodeMirror-fullscreen {
|
||||
z-index: 1003;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div class="pan-item" :style="{zIndex:zIndex,height:height,width:width}">
|
||||
<div class="pan-info">
|
||||
<div class="pan-info-roles-container">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
<img class="pan-thumb" :src="image">
|
||||
</div>
|
||||
<div :style="{zIndex:zIndex,height:height,width:width}" class="pan-item">
|
||||
<div class="pan-info">
|
||||
<div class="pan-info-roles-container">
|
||||
<slot/>
|
||||
</div>
|
||||
</div>
|
||||
<img :src="image" class="pan-thumb">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -19,7 +19,7 @@ export default {
|
||||
},
|
||||
zIndex: {
|
||||
type: Number,
|
||||
default: 100
|
||||
default: 1
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
@@ -35,106 +35,106 @@ export default {
|
||||
|
||||
<style scoped>
|
||||
.pan-item {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: default;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: default;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.pan-info-roles-container {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.pan-thumb {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: 100%;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
transform-origin: 95% 40%;
|
||||
transition: all 0.3s ease-in-out;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-size: 100%;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
transform-origin: 95% 40%;
|
||||
transition: all 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.pan-thumb:after {
|
||||
content: '';
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
top: 40%;
|
||||
left: 95%;
|
||||
margin: -4px 0 0 -4px;
|
||||
background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
|
||||
box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
|
||||
content: '';
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
top: 40%;
|
||||
left: 95%;
|
||||
margin: -4px 0 0 -4px;
|
||||
background: radial-gradient(ellipse at center, rgba(14, 14, 14, 1) 0%, rgba(125, 126, 125, 1) 100%);
|
||||
box-shadow: 0 0 1px rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
|
||||
.pan-info {
|
||||
position: absolute;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
|
||||
position: absolute;
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
box-shadow: inset 0 0 0 5px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.pan-info h3 {
|
||||
color: #fff;
|
||||
text-transform: uppercase;
|
||||
position: relative;
|
||||
letter-spacing: 2px;
|
||||
font-size: 18px;
|
||||
margin: 0 60px;
|
||||
padding: 22px 0 0 0;
|
||||
height: 85px;
|
||||
font-family: 'Open Sans', Arial, sans-serif;
|
||||
text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||
color: #fff;
|
||||
text-transform: uppercase;
|
||||
position: relative;
|
||||
letter-spacing: 2px;
|
||||
font-size: 18px;
|
||||
margin: 0 60px;
|
||||
padding: 22px 0 0 0;
|
||||
height: 85px;
|
||||
font-family: 'Open Sans', Arial, sans-serif;
|
||||
text-shadow: 0 0 1px #fff, 0 1px 2px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.pan-info p {
|
||||
color: #fff;
|
||||
padding: 10px 5px;
|
||||
font-style: italic;
|
||||
margin: 0 30px;
|
||||
font-size: 12px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.5);
|
||||
color: #fff;
|
||||
padding: 10px 5px;
|
||||
font-style: italic;
|
||||
margin: 0 30px;
|
||||
font-size: 12px;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.pan-info p a {
|
||||
display: block;
|
||||
color: #333;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
font-size: 9px;
|
||||
letter-spacing: 1px;
|
||||
padding-top: 24px;
|
||||
margin: 7px auto 0;
|
||||
font-family: 'Open Sans', Arial, sans-serif;
|
||||
opacity: 0;
|
||||
transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
|
||||
transform: translateX(60px) rotate(90deg);
|
||||
display: block;
|
||||
color: #333;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
font-size: 9px;
|
||||
letter-spacing: 1px;
|
||||
padding-top: 24px;
|
||||
margin: 7px auto 0;
|
||||
font-family: 'Open Sans', Arial, sans-serif;
|
||||
opacity: 0;
|
||||
transition: transform 0.3s ease-in-out 0.2s, opacity 0.3s ease-in-out 0.2s, background 0.2s linear 0s;
|
||||
transform: translateX(60px) rotate(90deg);
|
||||
}
|
||||
|
||||
.pan-info p a:hover {
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
background: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.pan-item:hover .pan-thumb {
|
||||
transform: rotate(-110deg);
|
||||
transform: rotate(-110deg);
|
||||
}
|
||||
|
||||
.pan-item:hover .pan-info p a {
|
||||
opacity: 1;
|
||||
transform: translateX(0px) rotate(0deg);
|
||||
opacity: 1;
|
||||
transform: translateX(0px) rotate(0deg);
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,15 +1,28 @@
|
||||
<template>
|
||||
<div>
|
||||
<svg t="1508738709248" @click='click' class="screenfull-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="2069" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32">
|
||||
<path d="M333.493443 428.647617 428.322206 333.832158 262.572184 168.045297 366.707916 64.444754 64.09683 64.444754 63.853283 366.570793 167.283957 262.460644Z"
|
||||
p-id="2070"></path>
|
||||
<path d="M854.845439 760.133334 688.61037 593.95864 593.805144 688.764889 759.554142 854.56096 655.44604 958.161503 958.055079 958.161503 958.274066 656.035464Z"
|
||||
p-id="2071"></path>
|
||||
<path d="M688.535669 428.550403 854.31025 262.801405 957.935352 366.921787 957.935352 64.34754 655.809313 64.081481 759.919463 167.535691 593.70793 333.731874Z"
|
||||
p-id="2072"></path>
|
||||
<path d="M333.590658 594.033341 167.8171 759.804852 64.218604 655.67219 64.218604 958.270996 366.342596 958.502263 262.234493 855.071589 428.421466 688.86108Z"
|
||||
p-id="2073"></path>
|
||||
<svg
|
||||
t="1508738709248"
|
||||
class="screenfull-svg"
|
||||
viewBox="0 0 1024 1024"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
p-id="2069"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
width="32"
|
||||
height="32"
|
||||
@click="click">
|
||||
<path
|
||||
d="M333.493443 428.647617 428.322206 333.832158 262.572184 168.045297 366.707916 64.444754 64.09683 64.444754 63.853283 366.570793 167.283957 262.460644Z"
|
||||
p-id="2070"/>
|
||||
<path
|
||||
d="M854.845439 760.133334 688.61037 593.95864 593.805144 688.764889 759.554142 854.56096 655.44604 958.161503 958.055079 958.161503 958.274066 656.035464Z"
|
||||
p-id="2071"/>
|
||||
<path
|
||||
d="M688.535669 428.550403 854.31025 262.801405 957.935352 366.921787 957.935352 64.34754 655.809313 64.081481 759.919463 167.535691 593.70793 333.731874Z"
|
||||
p-id="2072"/>
|
||||
<path
|
||||
d="M333.590658 594.033341 167.8171 759.804852 64.218604 655.67219 64.218604 958.270996 366.342596 958.502263 262.234493 855.071589 428.421466 688.86108Z"
|
||||
p-id="2073"/>
|
||||
</svg>
|
||||
</div>
|
||||
</template>
|
||||
@@ -18,7 +31,7 @@
|
||||
import screenfull from 'screenfull'
|
||||
|
||||
export default {
|
||||
name: 'screenfull',
|
||||
name: 'Screenfull',
|
||||
props: {
|
||||
width: {
|
||||
type: Number,
|
||||
|
@@ -1,57 +0,0 @@
|
||||
<template>
|
||||
<div class="scroll-container" ref="scrollContainer" @wheel.prevent="handleScroll" >
|
||||
<div class="scroll-wrapper" ref="scrollWrapper" :style="{top: top + 'px'}">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const delta = 15
|
||||
|
||||
export default {
|
||||
name: 'scrollBar',
|
||||
data() {
|
||||
return {
|
||||
top: 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleScroll(e) {
|
||||
const eventDelta = e.wheelDelta || -e.deltaY * 3
|
||||
const $container = this.$refs.scrollContainer
|
||||
const $containerHeight = $container.offsetHeight
|
||||
const $wrapper = this.$refs.scrollWrapper
|
||||
const $wrapperHeight = $wrapper.offsetHeight
|
||||
if (eventDelta > 0) {
|
||||
this.top = Math.min(0, this.top + eventDelta)
|
||||
} else {
|
||||
if ($containerHeight - delta < $wrapperHeight) {
|
||||
if (this.top < -($wrapperHeight - $containerHeight + delta)) {
|
||||
this.top = this.top
|
||||
} else {
|
||||
this.top = Math.max(this.top + eventDelta, $containerHeight - $wrapperHeight - delta)
|
||||
}
|
||||
} else {
|
||||
this.top = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
@import '../../styles/variables.scss';
|
||||
|
||||
.scroll-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: $menuBg;
|
||||
.scroll-wrapper {
|
||||
position: absolute;
|
||||
width: 100%!important;
|
||||
}
|
||||
}
|
||||
</style>
|
@@ -1,16 +1,14 @@
|
||||
<template>
|
||||
<div class="scroll-container" ref="scrollContainer" @wheel.prevent="handleScroll">
|
||||
<div class="scroll-wrapper" ref="scrollWrapper" :style="{left: left + 'px'}">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
<el-scrollbar ref="scrollContainer" :vertical="false" class="scroll-container" @wheel.native.prevent="handleScroll">
|
||||
<slot/>
|
||||
</el-scrollbar>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const padding = 15 // tag's padding
|
||||
|
||||
export default {
|
||||
name: 'scrollPane',
|
||||
name: 'ScrollPane',
|
||||
data() {
|
||||
return {
|
||||
left: 0
|
||||
@@ -18,41 +16,22 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
handleScroll(e) {
|
||||
const eventDelta = e.wheelDelta || -e.deltaY * 3
|
||||
const $container = this.$refs.scrollContainer
|
||||
const $containerWidth = $container.offsetWidth
|
||||
const $wrapper = this.$refs.scrollWrapper
|
||||
const $wrapperWidth = $wrapper.offsetWidth
|
||||
|
||||
if (eventDelta > 0) {
|
||||
this.left = Math.min(0, this.left + eventDelta)
|
||||
} else {
|
||||
if ($containerWidth - padding < $wrapperWidth) {
|
||||
if (this.left < -($wrapperWidth - $containerWidth + padding)) {
|
||||
this.left = this.left
|
||||
} else {
|
||||
this.left = Math.max(this.left + eventDelta, $containerWidth - $wrapperWidth - padding)
|
||||
}
|
||||
} else {
|
||||
this.left = 0
|
||||
}
|
||||
}
|
||||
const eventDelta = e.wheelDelta || -e.deltaY * 40
|
||||
const $scrollWrapper = this.$refs.scrollContainer.$refs.wrap
|
||||
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
|
||||
},
|
||||
moveToTarget($target) {
|
||||
const $container = this.$refs.scrollContainer
|
||||
const $container = this.$refs.scrollContainer.$el
|
||||
const $containerWidth = $container.offsetWidth
|
||||
const $scrollWrapper = this.$refs.scrollContainer.$refs.wrap
|
||||
const $targetLeft = $target.offsetLeft
|
||||
const $targetWidth = $target.offsetWidth
|
||||
|
||||
if ($targetLeft < -this.left) {
|
||||
// tag in the left
|
||||
this.left = -$targetLeft + padding
|
||||
} else if ($targetLeft + padding > -this.left && $targetLeft + $targetWidth < -this.left + $containerWidth - padding) {
|
||||
// tag in the current view
|
||||
// eslint-disable-line
|
||||
} else {
|
||||
if ($targetLeft > $containerWidth) {
|
||||
// tag in the right
|
||||
this.left = -($targetLeft - ($containerWidth - $targetWidth) + padding)
|
||||
$scrollWrapper.scrollLeft = $targetLeft - $containerWidth + $targetWidth + padding
|
||||
} else {
|
||||
// tag in the left
|
||||
$scrollWrapper.scrollLeft = $targetLeft - padding
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,8 +44,13 @@ export default {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
.scroll-wrapper {
|
||||
position: absolute;
|
||||
/deep/ {
|
||||
.el-scrollbar__bar {
|
||||
bottom: 0px;
|
||||
}
|
||||
.el-scrollbar__wrap {
|
||||
height: 49px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div class="share-dropdown-menu" :class="{active:isActive}">
|
||||
<div :class="{active:isActive}" class="share-dropdown-menu">
|
||||
<div class="share-dropdown-menu-wrapper">
|
||||
<span class="share-dropdown-menu-title" @click.self="clickTitle">{{title}}</span>
|
||||
<div class="share-dropdown-menu-item" v-for="(item,index) of items" :key='index'>
|
||||
<a v-if="item.href" :href="item.href" target="_blank">{{item.title}}</a>
|
||||
<span v-else>{{item.title}}</span>
|
||||
<span class="share-dropdown-menu-title" @click.self="clickTitle">{{ title }}</span>
|
||||
<div v-for="(item,index) of items" :key="index" class="share-dropdown-menu-item">
|
||||
<a v-if="item.href" :href="item.href" target="_blank">{{ item.title }}</a>
|
||||
<span v-else>{{ item.title }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -14,7 +14,10 @@
|
||||
export default {
|
||||
props: {
|
||||
items: {
|
||||
type: Array
|
||||
type: Array,
|
||||
default: function() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
@@ -35,7 +38,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" >
|
||||
$n: 6; //和items.length 相同
|
||||
$n: 8; //和items.length 相同
|
||||
$t: .1s;
|
||||
.share-dropdown-menu {
|
||||
width: 250px;
|
||||
|
55
src/components/SizeSelect/index.vue
Normal file
@@ -0,0 +1,55 @@
|
||||
<template>
|
||||
<el-dropdown trigger="click" @command="handleSetSize">
|
||||
<div>
|
||||
<svg-icon class-name="size-icon" icon-class="size" />
|
||||
</div>
|
||||
<el-dropdown-menu slot="dropdown">
|
||||
<el-dropdown-item :disabled="size==='medium'" command="medium">Medium</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="size==='small'" command="small">Small</el-dropdown-item>
|
||||
<el-dropdown-item :disabled="size==='mini'" command="mini">Mini</el-dropdown-item>
|
||||
</el-dropdown-menu>
|
||||
</el-dropdown>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
size() {
|
||||
return this.$store.getters.size
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleSetSize(size) {
|
||||
this.$ELEMENT.size = size
|
||||
this.$store.dispatch('setSize', size)
|
||||
this.refreshView()
|
||||
this.$message({
|
||||
message: 'Switch Size Success',
|
||||
type: 'success'
|
||||
})
|
||||
},
|
||||
refreshView() {
|
||||
// In order to make the cached page re-rendered
|
||||
this.$store.dispatch('delAllCachedViews', this.$route)
|
||||
|
||||
const { fullPath } = this.$route
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.$router.replace({
|
||||
path: '/redirect' + fullPath
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.size-icon {
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
vertical-align: -4px!important;
|
||||
}
|
||||
</style>
|
||||
|
@@ -21,29 +21,30 @@ export default {
|
||||
default: 1
|
||||
},
|
||||
className: {
|
||||
type: String
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
active: false,
|
||||
position: '',
|
||||
currentTop: '',
|
||||
width: undefined,
|
||||
height: undefined,
|
||||
child: null,
|
||||
stickyHeight: 0
|
||||
isSticky: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.height = this.$el.getBoundingClientRect().height
|
||||
window.addEventListener('scroll', this.handleScroll)
|
||||
window.addEventListener('resize', this.handleReize)
|
||||
},
|
||||
activated() {
|
||||
this.handleScroll()
|
||||
},
|
||||
destroyed() {
|
||||
window.removeEventListener('scroll', this.handleScroll)
|
||||
window.removeEventListener('resize', this.handleReize)
|
||||
},
|
||||
methods: {
|
||||
sticky() {
|
||||
@@ -53,6 +54,7 @@ export default {
|
||||
this.position = 'fixed'
|
||||
this.active = true
|
||||
this.width = this.width + 'px'
|
||||
this.isSticky = true
|
||||
},
|
||||
reset() {
|
||||
if (!this.active) {
|
||||
@@ -61,15 +63,21 @@ export default {
|
||||
this.position = ''
|
||||
this.width = 'auto'
|
||||
this.active = false
|
||||
this.isSticky = false
|
||||
},
|
||||
handleScroll() {
|
||||
this.width = this.$el.getBoundingClientRect().width
|
||||
const offsetTop = this.$el.getBoundingClientRect().top
|
||||
if (offsetTop <= this.stickyTop) {
|
||||
if (offsetTop < this.stickyTop) {
|
||||
this.sticky()
|
||||
return
|
||||
}
|
||||
this.reset()
|
||||
},
|
||||
handleReize() {
|
||||
if (this.isSticky) {
|
||||
this.width = this.$el.getBoundingClientRect().width + 'px'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,19 +1,20 @@
|
||||
<template>
|
||||
<svg :class="svgClass" aria-hidden="true">
|
||||
<use :xlink:href="iconName"></use>
|
||||
<use :xlink:href="iconName"/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'svg-icon',
|
||||
name: 'SvgIcon',
|
||||
props: {
|
||||
iconClass: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
className: {
|
||||
type: String
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<a class="link--mallki" :class="className" href="#">
|
||||
{{text}}
|
||||
<span :data-letters="text"></span>
|
||||
<span :data-letters="text"></span>
|
||||
<a :class="className" class="link--mallki" href="#">
|
||||
{{ text }}
|
||||
<span :data-letters="text"/>
|
||||
<span :data-letters="text"/>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
export default {
|
||||
props: {
|
||||
className: {
|
||||
type: String
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
@@ -20,9 +21,9 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
/* Mallki */
|
||||
|
||||
.link--mallki {
|
||||
font-weight: 800;
|
||||
color: #4dd9d5;
|
||||
@@ -31,10 +32,10 @@ export default {
|
||||
transition: color 0.5s 0.25s;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
outline: none;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.link--mallki:hover {
|
||||
@@ -109,5 +110,4 @@ display: inline-block;
|
||||
-webkit-transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
|
||||
transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
|
||||
}
|
||||
|
||||
</style>
|
||||
|
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<el-color-picker
|
||||
v-model="theme"
|
||||
class="theme-picker"
|
||||
popper-class="theme-picker-dropdown"
|
||||
v-model="theme"></el-color-picker>
|
||||
popper-class="theme-picker-dropdown"/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
@@ -1,10 +1,18 @@
|
||||
<template>
|
||||
<div class="upload-container">
|
||||
<el-button icon='upload' :style="{background:color,borderColor:color}" @click=" dialogVisible=true" type="primary">上传图片
|
||||
<el-button :style="{background:color,borderColor:color}" icon="el-icon-upload" size="mini" type="primary" @click=" dialogVisible=true">上传图片
|
||||
</el-button>
|
||||
<el-dialog :visible.sync="dialogVisible">
|
||||
<el-upload class="editor-slide-upload" action="https://httpbin.org/post" :multiple="true" :file-list="fileList" :show-file-list="true"
|
||||
list-type="picture-card" :on-remove="handleRemove" :on-success="handleSuccess" :before-upload="beforeUpload">
|
||||
<el-upload
|
||||
:multiple="true"
|
||||
:file-list="fileList"
|
||||
:show-file-list="true"
|
||||
:on-remove="handleRemove"
|
||||
:on-success="handleSuccess"
|
||||
:before-upload="beforeUpload"
|
||||
class="editor-slide-upload"
|
||||
action="https://httpbin.org/post"
|
||||
list-type="picture-card">
|
||||
<el-button size="small" type="primary">点击上传</el-button>
|
||||
</el-upload>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
@@ -17,11 +25,11 @@
|
||||
// import { getToken } from 'api/qiniu'
|
||||
|
||||
export default {
|
||||
name: 'editorSlideUpload',
|
||||
name: 'EditorSlideUpload',
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
default: '#20a0ff'
|
||||
default: '#1890ff'
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -41,7 +49,6 @@ export default {
|
||||
this.$message('请等待所有图片上传成功 或 出现了网络问题,请刷新页面重新上传!')
|
||||
return
|
||||
}
|
||||
console.log(arr)
|
||||
this.$emit('successCBK', arr)
|
||||
this.listObj = {}
|
||||
this.fileList = []
|
||||
@@ -87,9 +94,10 @@ export default {
|
||||
</script>
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.upload-container {
|
||||
.editor-slide-upload {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
.editor-slide-upload {
|
||||
margin-bottom: 20px;
|
||||
/deep/ .el-upload--picture-card {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,21 +1,26 @@
|
||||
<template>
|
||||
<div class="tinymce-container editor-container">
|
||||
<textarea class="tinymce-textarea" :id="tinymceId"></textarea>
|
||||
<div :class="{fullscreen:fullscreen}" class="tinymce-container editor-container">
|
||||
<textarea :id="tinymceId" class="tinymce-textarea"/>
|
||||
<div class="editor-custom-btn-container">
|
||||
<editorImage color="#20a0ff" class="editor-upload-btn" @successCBK="imageSuccessCBK"></editorImage>
|
||||
</div>
|
||||
<editorImage color="#1890ff" class="editor-upload-btn" @successCBK="imageSuccessCBK"/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import editorImage from './components/editorImage'
|
||||
import plugins from './plugins'
|
||||
import toolbar from './toolbar'
|
||||
|
||||
export default {
|
||||
name: 'tinymce',
|
||||
name: 'Tinymce',
|
||||
components: { editorImage },
|
||||
props: {
|
||||
id: {
|
||||
type: String
|
||||
type: String,
|
||||
default: function() {
|
||||
return 'vue-tinymce-' + +new Date() + ((Math.random() * 1000).toFixed(0) + '')
|
||||
}
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
@@ -25,11 +30,12 @@ export default {
|
||||
type: Array,
|
||||
required: false,
|
||||
default() {
|
||||
return ['removeformat undo redo | bullist numlist | outdent indent | forecolor | fullscreen code', 'bold italic blockquote | h2 p media link | alignleft aligncenter alignright']
|
||||
return []
|
||||
}
|
||||
},
|
||||
menubar: {
|
||||
default: ''
|
||||
type: String,
|
||||
default: 'file edit insert view format table'
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
@@ -41,14 +47,29 @@ export default {
|
||||
return {
|
||||
hasChange: false,
|
||||
hasInit: false,
|
||||
tinymceId: this.id || 'vue-tinymce-' + +new Date()
|
||||
tinymceId: this.id,
|
||||
fullscreen: false,
|
||||
languageTypeList: {
|
||||
'en': 'en',
|
||||
'zh': 'zh_CN'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
language() {
|
||||
return this.languageTypeList[this.$store.getters.language]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value(val) {
|
||||
if (!this.hasChange && this.hasInit) {
|
||||
this.$nextTick(() => window.tinymce.get(this.tinymceId).setContent(val))
|
||||
this.$nextTick(() =>
|
||||
window.tinymce.get(this.tinymceId).setContent(val || ''))
|
||||
}
|
||||
},
|
||||
language() {
|
||||
this.destroyTinymce()
|
||||
this.$nextTick(() => this.initTinymce())
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -60,35 +81,44 @@ export default {
|
||||
deactivated() {
|
||||
this.destroyTinymce()
|
||||
},
|
||||
destroyed() {
|
||||
this.destroyTinymce()
|
||||
},
|
||||
methods: {
|
||||
initTinymce() {
|
||||
const _this = this
|
||||
window.tinymce.init({
|
||||
language: this.language,
|
||||
selector: `#${this.tinymceId}`,
|
||||
height: this.height,
|
||||
body_class: 'panel-body ',
|
||||
object_resizing: false,
|
||||
toolbar: this.toolbar,
|
||||
toolbar: this.toolbar.length > 0 ? this.toolbar : toolbar,
|
||||
menubar: this.menubar,
|
||||
plugins: 'advlist,autolink,code,paste,textcolor, colorpicker,fullscreen,link,lists,media,wordcount, imagetools',
|
||||
plugins: plugins,
|
||||
end_container_on_empty_block: true,
|
||||
powerpaste_word_import: 'clean',
|
||||
code_dialog_height: 450,
|
||||
code_dialog_width: 1000,
|
||||
advlist_bullet_styles: 'square',
|
||||
advlist_number_styles: 'default',
|
||||
imagetools_cors_hosts: ['wpimg.wallstcn.com', 'wallstreetcn.com'],
|
||||
imagetools_toolbar: 'watermark',
|
||||
imagetools_cors_hosts: ['www.tinymce.com', 'codepen.io'],
|
||||
default_link_target: '_blank',
|
||||
link_title: false,
|
||||
nonbreaking_force_tab: true, // inserting nonbreaking space need Nonbreaking Space Plugin
|
||||
init_instance_callback: editor => {
|
||||
if (_this.value) {
|
||||
editor.setContent(_this.value)
|
||||
}
|
||||
_this.hasInit = true
|
||||
editor.on('NodeChange Change KeyUp', () => {
|
||||
editor.on('NodeChange Change KeyUp SetContent', () => {
|
||||
this.hasChange = true
|
||||
this.$emit('input', editor.getContent({ format: 'raw' }))
|
||||
this.$emit('input', editor.getContent())
|
||||
})
|
||||
},
|
||||
setup(editor) {
|
||||
editor.on('FullscreenStateChanged', (e) => {
|
||||
_this.fullscreen = e.state
|
||||
})
|
||||
}
|
||||
// 整合七牛上传
|
||||
@@ -143,16 +173,16 @@ export default {
|
||||
window.tinymce.get(_this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`)
|
||||
})
|
||||
}
|
||||
},
|
||||
destroyed() {
|
||||
this.destroyTinymce()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.tinymce-container {
|
||||
position: relative
|
||||
position: relative;
|
||||
}
|
||||
.tinymce-container>>>.mce-fullscreen {
|
||||
z-index: 10000;
|
||||
}
|
||||
.tinymce-textarea {
|
||||
visibility: hidden;
|
||||
@@ -160,9 +190,13 @@ export default {
|
||||
}
|
||||
.editor-custom-btn-container {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
right: 4px;
|
||||
top: 4px;
|
||||
/*z-index: 2005;*/
|
||||
top: 18px;
|
||||
}
|
||||
.fullscreen .editor-custom-btn-container {
|
||||
z-index: 10000;
|
||||
position: fixed;
|
||||
}
|
||||
.editor-upload-btn {
|
||||
display: inline-block;
|
||||
|
7
src/components/Tinymce/plugins.js
Normal file
@@ -0,0 +1,7 @@
|
||||
// Any plugins you want to use has to be imported
|
||||
// Detail plugins list see https://www.tinymce.com/docs/plugins/
|
||||
// Custom builds see https://www.tinymce.com/download/custom-builds/
|
||||
|
||||
const plugins = ['advlist anchor autolink autosave code codesample colorpicker colorpicker contextmenu directionality emoticons fullscreen hr image imagetools importcss insertdatetime link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor textpattern visualblocks visualchars wordcount']
|
||||
|
||||
export default plugins
|
6
src/components/Tinymce/toolbar.js
Normal file
@@ -0,0 +1,6 @@
|
||||
// Here is a list of the toolbar
|
||||
// Detail list see https://www.tinymce.com/docs/advanced/editor-control-identifiers/#toolbarcontrols
|
||||
|
||||
const toolbar = ['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']
|
||||
|
||||
export default toolbar
|
@@ -4,11 +4,11 @@
|
||||
*/
|
||||
'use strict'
|
||||
import Vue from 'vue'
|
||||
export default function treeToArray(data, expandedAll, parent = null, level = null) {
|
||||
export default function treeToArray(data, expandAll, parent = null, level = null) {
|
||||
let tmp = []
|
||||
Array.from(data).forEach(function(record) {
|
||||
if (record._expanded === undefined) {
|
||||
Vue.set(record, '_expanded', expandedAll)
|
||||
Vue.set(record, '_expanded', expandAll)
|
||||
}
|
||||
let _level = 1
|
||||
if (level !== undefined && level !== null) {
|
||||
@@ -21,7 +21,7 @@ export default function treeToArray(data, expandedAll, parent = null, level = nu
|
||||
}
|
||||
tmp.push(record)
|
||||
if (record.children && record.children.length > 0) {
|
||||
const children = treeToArray(record.children, expandedAll, record, _level)
|
||||
const children = treeToArray(record.children, expandAll, record, _level)
|
||||
tmp = tmp.concat(children)
|
||||
}
|
||||
})
|
||||
|
@@ -2,25 +2,27 @@
|
||||
<el-table :data="formatData" :row-style="showRow" v-bind="$attrs">
|
||||
<el-table-column v-if="columns.length===0" width="150">
|
||||
<template slot-scope="scope">
|
||||
<span v-for="space in scope.row._level" class="ms-tree-space" :key="space"></span>
|
||||
<span class="tree-ctrl" v-if="iconShow(0,scope.row)" @click="toggleExpanded(scope.$index)">
|
||||
<i v-if="!scope.row._expanded" class="el-icon-plus"></i>
|
||||
<i v-else class="el-icon-minus"></i>
|
||||
<span v-for="space in scope.row._level" :key="space" class="ms-tree-space"/>
|
||||
<span v-if="iconShow(0,scope.row)" class="tree-ctrl" @click="toggleExpanded(scope.$index)">
|
||||
<i v-if="!scope.row._expanded" class="el-icon-plus"/>
|
||||
<i v-else class="el-icon-minus"/>
|
||||
</span>
|
||||
{{scope.$index}}
|
||||
{{ scope.$index }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-else v-for="(column, index) in columns" :key="column.value" :label="column.text" :width="column.width">
|
||||
<el-table-column v-for="(column, index) in columns" v-else :key="column.value" :label="column.text" :width="column.width">
|
||||
<template slot-scope="scope">
|
||||
<span v-if="index === 0" v-for="space in scope.row._level" class="ms-tree-space" :key="space"></span>
|
||||
<span class="tree-ctrl" v-if="iconShow(index,scope.row)" @click="toggleExpanded(scope.$index)">
|
||||
<i v-if="!scope.row._expanded" class="el-icon-plus"></i>
|
||||
<i v-else class="el-icon-minus"></i>
|
||||
<!-- Todo -->
|
||||
<!-- eslint-disable-next-line vue/no-confusing-v-for-v-if -->
|
||||
<span v-for="space in scope.row._level" v-if="index === 0" :key="space" class="ms-tree-space"/>
|
||||
<span v-if="iconShow(index,scope.row)" class="tree-ctrl" @click="toggleExpanded(scope.$index)">
|
||||
<i v-if="!scope.row._expanded" class="el-icon-plus"/>
|
||||
<i v-else class="el-icon-minus"/>
|
||||
</span>
|
||||
{{scope.row[column.value]}}
|
||||
{{ scope.row[column.value] }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<slot></slot>
|
||||
<slot/>
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
@@ -31,8 +33,9 @@
|
||||
*/
|
||||
import treeToArray from './eval'
|
||||
export default {
|
||||
name: 'treeTable',
|
||||
name: 'TreeTable',
|
||||
props: {
|
||||
/* eslint-disable */
|
||||
data: {
|
||||
type: [Array, Object],
|
||||
required: true
|
||||
@@ -58,7 +61,7 @@ export default {
|
||||
tmp = this.data
|
||||
}
|
||||
const func = this.evalFunc || treeToArray
|
||||
const args = this.evalArgs ? Array.concat([tmp], this.evalArgs) : [tmp, this.expandAll]
|
||||
const args = this.evalArgs ? Array.concat([tmp, this.expandAll], this.evalArgs) : [tmp, this.expandAll]
|
||||
return func.apply(null, args)
|
||||
}
|
||||
},
|
||||
@@ -66,7 +69,7 @@ export default {
|
||||
showRow: function(row) {
|
||||
const show = (row.row.parent ? (row.row.parent._expanded && row.row.parent._show) : true)
|
||||
row.row._show = show
|
||||
return show ? '' : 'display:none;'
|
||||
return show ? 'animation:treeTableShow 1s;-webkit-animation:treeTableShow 1s;' : 'display:none;'
|
||||
},
|
||||
// 切换下级是否展开
|
||||
toggleExpanded: function(trIndex) {
|
||||
@@ -80,6 +83,16 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style rel="stylesheet/css">
|
||||
@keyframes treeTableShow {
|
||||
from {opacity: 0;}
|
||||
to {opacity: 1;}
|
||||
}
|
||||
@-webkit-keyframes treeTableShow {
|
||||
from {opacity: 0;}
|
||||
to {opacity: 1;}
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss" rel="stylesheet/scss" scoped>
|
||||
$color-blue: #2196F3;
|
||||
|
@@ -70,11 +70,11 @@
|
||||
#### evalArgs
|
||||
解析函数的参数,是一个数组
|
||||
|
||||
**请注意,自定义的解析函数参数第一个为this.data,你不需要在evalArgs填写。** *this.data为需要解析的数据*
|
||||
**请注意,自定义的解析函数参数第一个为this.data,第二个参数为, this.expandAll,你不需要在evalArgs填写。一定记住,这两个参数是强制性的,并且位置不可颠倒** *this.data为需要解析的数据,this.expandAll为是否默认展开*
|
||||
|
||||
如你的解析函数需要的参数为`(this.data,1,2,3,4)`,那么你只需要将`[1,2,3,4]`赋值给`evalArgs`就可以了
|
||||
如你的解析函数需要的参数为`(this.data, this.expandAll,1,2,3,4)`,那么你只需要将`[1,2,3,4]`赋值给`evalArgs`就可以了
|
||||
|
||||
如果你的解析函数参数只有一个`(this.data)`,那么就可以不用填写evalArgs了
|
||||
如果你的解析函数参数只有`(this.data, this.expandAll)`,那么就可以不用填写evalArgs了
|
||||
|
||||
具体可参考[*customEval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customEval.js)的函数参数和[customTreeTable](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/example/table/treeTable/customTreeTable.vue)的`evalArgs`属性值
|
||||
|
||||
|
@@ -1,19 +1,25 @@
|
||||
<template>
|
||||
<div class="upload-container">
|
||||
<el-upload class="image-uploader" :data="dataObj" drag :multiple="false" :show-file-list="false" action="https://httpbin.org/post"
|
||||
:on-success="handleImageScucess">
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
</el-upload>
|
||||
<div class="image-preview">
|
||||
<div class="image-preview-wrapper" v-show="imageUrl.length>1">
|
||||
<img :src="imageUrl+'?imageView2/1/w/200/h/200'">
|
||||
<div class="image-preview-action">
|
||||
<i @click="rmImage" class="el-icon-delete"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upload-container">
|
||||
<el-upload
|
||||
:data="dataObj"
|
||||
:multiple="false"
|
||||
:show-file-list="false"
|
||||
:on-success="handleImageSuccess"
|
||||
class="image-uploader"
|
||||
drag
|
||||
action="https://httpbin.org/post">
|
||||
<i class="el-icon-upload"/>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
</el-upload>
|
||||
<div class="image-preview">
|
||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
||||
<img :src="imageUrl+'?imageView2/1/w/200/h/200'">
|
||||
<div class="image-preview-action">
|
||||
<i class="el-icon-delete" @click="rmImage"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -21,13 +27,11 @@
|
||||
import { getToken } from '@/api/qiniu'
|
||||
|
||||
export default {
|
||||
name: 'singleImageUpload',
|
||||
name: 'SingleImageUpload',
|
||||
props: {
|
||||
value: String
|
||||
},
|
||||
computed: {
|
||||
imageUrl() {
|
||||
return this.value
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -36,6 +40,11 @@ export default {
|
||||
dataObj: { token: '', key: '' }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
imageUrl() {
|
||||
return this.value
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rmImage() {
|
||||
this.emitInput('')
|
||||
@@ -43,7 +52,7 @@ export default {
|
||||
emitInput(val) {
|
||||
this.$emit('input', val)
|
||||
},
|
||||
handleImageScucess() {
|
||||
handleImageSuccess() {
|
||||
this.emitInput(this.tempUrl)
|
||||
},
|
||||
beforeUpload() {
|
||||
|
@@ -1,32 +1,36 @@
|
||||
<template>
|
||||
<div class="singleImageUpload2 upload-container">
|
||||
<el-upload class="image-uploader" :data="dataObj" drag :multiple="false" :show-file-list="false" action="https://httpbin.org/post"
|
||||
:on-success="handleImageScucess">
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">Drag或<em>点击上传</em></div>
|
||||
</el-upload>
|
||||
<div v-show="imageUrl.length>0" class="image-preview">
|
||||
<div class="image-preview-wrapper" v-show="imageUrl.length>1">
|
||||
<img :src="imageUrl">
|
||||
<div class="image-preview-action">
|
||||
<i @click="rmImage" class="el-icon-delete"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="singleImageUpload2 upload-container">
|
||||
<el-upload
|
||||
:data="dataObj"
|
||||
:multiple="false"
|
||||
:show-file-list="false"
|
||||
:on-success="handleImageSuccess"
|
||||
class="image-uploader"
|
||||
drag
|
||||
action="https://httpbin.org/post">
|
||||
<i class="el-icon-upload"/>
|
||||
<div class="el-upload__text">Drag或<em>点击上传</em></div>
|
||||
</el-upload>
|
||||
<div v-show="imageUrl.length>0" class="image-preview">
|
||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
||||
<img :src="imageUrl">
|
||||
<div class="image-preview-action">
|
||||
<i class="el-icon-delete" @click="rmImage"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from '@/api/qiniu'
|
||||
|
||||
export default {
|
||||
name: 'singleImageUpload2',
|
||||
name: 'SingleImageUpload2',
|
||||
props: {
|
||||
value: String
|
||||
},
|
||||
computed: {
|
||||
imageUrl() {
|
||||
return this.value
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -35,6 +39,11 @@ export default {
|
||||
dataObj: { token: '', key: '' }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
imageUrl() {
|
||||
return this.value
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rmImage() {
|
||||
this.emitInput('')
|
||||
@@ -42,7 +51,7 @@ export default {
|
||||
emitInput(val) {
|
||||
this.$emit('input', val)
|
||||
},
|
||||
handleImageScucess() {
|
||||
handleImageSuccess() {
|
||||
this.emitInput(this.tempUrl)
|
||||
},
|
||||
beforeUpload() {
|
||||
@@ -66,53 +75,53 @@ export default {
|
||||
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
.upload-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
.image-uploader {
|
||||
height: 100%;
|
||||
}
|
||||
.image-preview {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
border: 1px dashed #d9d9d9;
|
||||
.image-preview-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.image-preview-action {
|
||||
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);
|
||||
transition: opacity .3s;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
line-height: 200px;
|
||||
.el-icon-delete {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.image-preview-action {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
.image-uploader {
|
||||
height: 100%;
|
||||
}
|
||||
.image-preview {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
border: 1px dashed #d9d9d9;
|
||||
.image-preview-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.image-preview-action {
|
||||
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);
|
||||
transition: opacity .3s;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
line-height: 200px;
|
||||
.el-icon-delete {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.image-preview-action {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,40 +1,44 @@
|
||||
<template>
|
||||
<div class="upload-container">
|
||||
<el-upload class="image-uploader" :data="dataObj" drag :multiple="false" :show-file-list="false" action="https://httpbin.org/post"
|
||||
:on-success="handleImageScucess">
|
||||
<i class="el-icon-upload"></i>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
</el-upload>
|
||||
<div class="image-preview image-app-preview">
|
||||
<div class="image-preview-wrapper" v-show="imageUrl.length>1">
|
||||
<img :src="imageUrl">
|
||||
<div class="image-preview-action">
|
||||
<i @click="rmImage" class="el-icon-delete"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="image-preview">
|
||||
<div class="image-preview-wrapper" v-show="imageUrl.length>1">
|
||||
<img :src="imageUrl">
|
||||
<div class="image-preview-action">
|
||||
<i @click="rmImage" class="el-icon-delete"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upload-container">
|
||||
<el-upload
|
||||
:data="dataObj"
|
||||
:multiple="false"
|
||||
:show-file-list="false"
|
||||
:on-success="handleImageSuccess"
|
||||
class="image-uploader"
|
||||
drag
|
||||
action="https://httpbin.org/post">
|
||||
<i class="el-icon-upload"/>
|
||||
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
|
||||
</el-upload>
|
||||
<div class="image-preview image-app-preview">
|
||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
||||
<img :src="imageUrl">
|
||||
<div class="image-preview-action">
|
||||
<i class="el-icon-delete" @click="rmImage"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="image-preview">
|
||||
<div v-show="imageUrl.length>1" class="image-preview-wrapper">
|
||||
<img :src="imageUrl">
|
||||
<div class="image-preview-action">
|
||||
<i class="el-icon-delete" @click="rmImage"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from '@/api/qiniu'
|
||||
|
||||
export default {
|
||||
name: 'singleImageUpload',
|
||||
name: 'SingleImageUpload3',
|
||||
props: {
|
||||
value: String
|
||||
},
|
||||
computed: {
|
||||
imageUrl() {
|
||||
return this.value
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -43,6 +47,11 @@ export default {
|
||||
dataObj: { token: '', key: '' }
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
imageUrl() {
|
||||
return this.value
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rmImage() {
|
||||
this.emitInput('')
|
||||
@@ -50,7 +59,7 @@ export default {
|
||||
emitInput(val) {
|
||||
this.$emit('input', val)
|
||||
},
|
||||
handleImageScucess(file) {
|
||||
handleImageSuccess(file) {
|
||||
this.emitInput(file.files.file)
|
||||
},
|
||||
beforeUpload() {
|
||||
@@ -76,70 +85,70 @@ export default {
|
||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||
@import "src/styles/mixin.scss";
|
||||
.upload-container {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
@include clearfix;
|
||||
.image-uploader {
|
||||
width: 35%;
|
||||
float: left;
|
||||
}
|
||||
.image-preview {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
position: relative;
|
||||
border: 1px dashed #d9d9d9;
|
||||
float: left;
|
||||
margin-left: 50px;
|
||||
.image-preview-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.image-preview-action {
|
||||
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);
|
||||
transition: opacity .3s;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
line-height: 200px;
|
||||
.el-icon-delete {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.image-preview-action {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.image-app-preview {
|
||||
width: 320px;
|
||||
height: 180px;
|
||||
position: relative;
|
||||
border: 1px dashed #d9d9d9;
|
||||
float: left;
|
||||
margin-left: 50px;
|
||||
.app-fake-conver {
|
||||
height: 44px;
|
||||
position: absolute;
|
||||
width: 100%; // background: rgba(0, 0, 0, .1);
|
||||
text-align: center;
|
||||
line-height: 64px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
width: 100%;
|
||||
position: relative;
|
||||
@include clearfix;
|
||||
.image-uploader {
|
||||
width: 35%;
|
||||
float: left;
|
||||
}
|
||||
.image-preview {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
position: relative;
|
||||
border: 1px dashed #d9d9d9;
|
||||
float: left;
|
||||
margin-left: 50px;
|
||||
.image-preview-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.image-preview-action {
|
||||
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);
|
||||
transition: opacity .3s;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
line-height: 200px;
|
||||
.el-icon-delete {
|
||||
font-size: 36px;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
.image-preview-action {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.image-app-preview {
|
||||
width: 320px;
|
||||
height: 180px;
|
||||
position: relative;
|
||||
border: 1px dashed #d9d9d9;
|
||||
float: left;
|
||||
margin-left: 50px;
|
||||
.app-fake-conver {
|
||||
height: 44px;
|
||||
position: absolute;
|
||||
width: 100%; // background: rgba(0, 0, 0, .1);
|
||||
text-align: center;
|
||||
line-height: 64px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<input id="excel-upload-input" type="file" accept=".xlsx, .xls" class="c-hide" @change="handkeFileChange">
|
||||
<div id="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover">
|
||||
<input ref="excel-upload-input" class="excel-upload-input" type="file" accept=".xlsx, .xls" @change="handleClick">
|
||||
<div class="drop" @drop="handleDrop" @dragover="handleDragover" @dragenter="handleDragover">
|
||||
Drop excel file here or
|
||||
<el-button style="margin-left:16px;" size="mini" type="primary" @click="handleUpload">browse</el-button>
|
||||
<el-button :loading="loading" style="margin-left:16px;" size="mini" type="primary" @click="handleUpload">Browse</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -12,6 +12,10 @@
|
||||
import XLSX from 'xlsx'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
beforeUpload: Function, // eslint-disable-line
|
||||
onSuccess: Function// eslint-disable-line
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
@@ -22,21 +26,27 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
generateDate({ header, results }) {
|
||||
generateData({ header, results }) {
|
||||
this.excelData.header = header
|
||||
this.excelData.results = results
|
||||
this.$emit('on-selected-file', this.excelData)
|
||||
this.onSuccess && this.onSuccess(this.excelData)
|
||||
},
|
||||
handleDrop(e) {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
if (this.loading) return
|
||||
const files = e.dataTransfer.files
|
||||
if (files.length !== 1) {
|
||||
this.$message.error('Only support uploading one file!')
|
||||
return
|
||||
}
|
||||
const itemFile = files[0] // only use files[0]
|
||||
this.readerData(itemFile)
|
||||
const rawFile = files[0] // only use files[0]
|
||||
|
||||
if (!this.isExcel(rawFile)) {
|
||||
this.$message.error('Only supports upload .xlsx, .xls, .csv suffix files')
|
||||
return false
|
||||
}
|
||||
this.upload(rawFile)
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
},
|
||||
@@ -46,28 +56,46 @@ export default {
|
||||
e.dataTransfer.dropEffect = 'copy'
|
||||
},
|
||||
handleUpload() {
|
||||
document.getElementById('excel-upload-input').click()
|
||||
this.$refs['excel-upload-input'].click()
|
||||
},
|
||||
handkeFileChange(e) {
|
||||
handleClick(e) {
|
||||
const files = e.target.files
|
||||
const itemFile = files[0] // only use files[0]
|
||||
this.readerData(itemFile)
|
||||
const rawFile = files[0] // only use files[0]
|
||||
if (!rawFile) return
|
||||
this.upload(rawFile)
|
||||
},
|
||||
readerData(itemFile) {
|
||||
const reader = new FileReader()
|
||||
reader.onload = e => {
|
||||
const data = e.target.result
|
||||
const fixedData = this.fixdata(data)
|
||||
const workbook = XLSX.read(btoa(fixedData), { type: 'base64' })
|
||||
const firstSheetName = workbook.SheetNames[0]
|
||||
const worksheet = workbook.Sheets[firstSheetName]
|
||||
const header = this.get_header_row(worksheet)
|
||||
const results = XLSX.utils.sheet_to_json(worksheet)
|
||||
this.generateDate({ header, results })
|
||||
upload(rawFile) {
|
||||
this.$refs['excel-upload-input'].value = null // fix can't select the same excel
|
||||
|
||||
if (!this.beforeUpload) {
|
||||
this.readerData(rawFile)
|
||||
return
|
||||
}
|
||||
const before = this.beforeUpload(rawFile)
|
||||
if (before) {
|
||||
this.readerData(rawFile)
|
||||
}
|
||||
reader.readAsArrayBuffer(itemFile)
|
||||
},
|
||||
fixdata(data) {
|
||||
readerData(rawFile) {
|
||||
this.loading = true
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
reader.onload = e => {
|
||||
const data = e.target.result
|
||||
const fixedData = this.fixData(data)
|
||||
const workbook = XLSX.read(btoa(fixedData), { type: 'base64' })
|
||||
const firstSheetName = workbook.SheetNames[0]
|
||||
const worksheet = workbook.Sheets[firstSheetName]
|
||||
const header = this.getHeaderRow(worksheet)
|
||||
const results = XLSX.utils.sheet_to_json(worksheet)
|
||||
this.generateData({ header, results })
|
||||
this.loading = false
|
||||
resolve()
|
||||
}
|
||||
reader.readAsArrayBuffer(rawFile)
|
||||
})
|
||||
},
|
||||
fixData(data) {
|
||||
let o = ''
|
||||
let l = 0
|
||||
const w = 10240
|
||||
@@ -75,29 +103,34 @@ export default {
|
||||
o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w)))
|
||||
return o
|
||||
},
|
||||
get_header_row(sheet) {
|
||||
getHeaderRow(sheet) {
|
||||
const headers = []
|
||||
const range = XLSX.utils.decode_range(sheet['!ref'])
|
||||
let C
|
||||
const R = range.s.r /* start in the first row */
|
||||
const R = range.s.r
|
||||
/* start in the first row */
|
||||
for (C = range.s.c; C <= range.e.c; ++C) { /* walk every column in the range */
|
||||
var cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })] /* find the cell in the first row */
|
||||
var hdr = 'UNKNOWN ' + C // <-- replace with your desired default
|
||||
const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
|
||||
/* find the cell in the first row */
|
||||
let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
|
||||
if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
|
||||
headers.push(hdr)
|
||||
}
|
||||
return headers
|
||||
},
|
||||
isExcel(file) {
|
||||
return /\.(xlsx|xls|csv)$/.test(file.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#excel-upload-input{
|
||||
.excel-upload-input{
|
||||
display: none;
|
||||
z-index: -9999;
|
||||
}
|
||||
#drop{
|
||||
.drop{
|
||||
border: 2px dashed #bbb;
|
||||
width: 600px;
|
||||
height: 160px;
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// Inspired by https://github.com/Inndy/vue-clipboard2
|
||||
const Clipboard = require('clipboard')
|
||||
if (!Clipboard) {
|
||||
throw new Error('you shold npm install `clipboard` --save at first ')
|
||||
throw new Error('you should npm install `clipboard` --save at first ')
|
||||
}
|
||||
|
||||
export default {
|
||||
|
77
src/directive/el-dragDialog/drag.js
Normal file
@@ -0,0 +1,77 @@
|
||||
export default{
|
||||
bind(el, binding, vnode) {
|
||||
const dialogHeaderEl = el.querySelector('.el-dialog__header')
|
||||
const dragDom = el.querySelector('.el-dialog')
|
||||
dialogHeaderEl.style.cssText += ';cursor:move;'
|
||||
dragDom.style.cssText += ';top:0px;'
|
||||
|
||||
// 获取原有属性 ie dom元素.currentStyle 火狐谷歌 window.getComputedStyle(dom元素, null);
|
||||
const getStyle = (function() {
|
||||
if (window.document.currentStyle) {
|
||||
return (dom, attr) => dom.currentStyle[attr]
|
||||
} else {
|
||||
return (dom, attr) => getComputedStyle(dom, false)[attr]
|
||||
}
|
||||
})()
|
||||
|
||||
dialogHeaderEl.onmousedown = (e) => {
|
||||
// 鼠标按下,计算当前元素距离可视区的距离
|
||||
const disX = e.clientX - dialogHeaderEl.offsetLeft
|
||||
const disY = e.clientY - dialogHeaderEl.offsetTop
|
||||
|
||||
const dragDomWidth = dragDom.offsetWidth
|
||||
const dragDomHeight = dragDom.offsetHeight
|
||||
|
||||
const screenWidth = document.body.clientWidth
|
||||
const screenHeight = document.body.clientHeight
|
||||
|
||||
const minDragDomLeft = dragDom.offsetLeft
|
||||
const maxDragDomLeft = screenWidth - dragDom.offsetLeft - dragDomWidth
|
||||
|
||||
const minDragDomTop = dragDom.offsetTop
|
||||
const maxDragDomTop = screenHeight - dragDom.offsetTop - dragDomHeight
|
||||
|
||||
// 获取到的值带px 正则匹配替换
|
||||
let styL = getStyle(dragDom, 'left')
|
||||
let styT = getStyle(dragDom, 'top')
|
||||
|
||||
if (styL.includes('%')) {
|
||||
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
|
||||
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
|
||||
} else {
|
||||
styL = +styL.replace(/\px/g, '')
|
||||
styT = +styT.replace(/\px/g, '')
|
||||
}
|
||||
|
||||
document.onmousemove = function(e) {
|
||||
// 通过事件委托,计算移动的距离
|
||||
let left = e.clientX - disX
|
||||
let top = e.clientY - disY
|
||||
|
||||
// 边界处理
|
||||
if (-(left) > minDragDomLeft) {
|
||||
left = -minDragDomLeft
|
||||
} else if (left > maxDragDomLeft) {
|
||||
left = maxDragDomLeft
|
||||
}
|
||||
|
||||
if (-(top) > minDragDomTop) {
|
||||
top = -minDragDomTop
|
||||
} else if (top > maxDragDomTop) {
|
||||
top = maxDragDomTop
|
||||
}
|
||||
|
||||
// 移动当前元素
|
||||
dragDom.style.cssText += `;left:${left + styL}px;top:${top + styT}px;`
|
||||
|
||||
// emit onDrag event
|
||||
vnode.child.$emit('dragDialog')
|
||||
}
|
||||
|
||||
document.onmouseup = function(e) {
|
||||
document.onmousemove = null
|
||||
document.onmouseup = null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
13
src/directive/el-dragDialog/index.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import drag from './drag'
|
||||
|
||||
const install = function(Vue) {
|
||||
Vue.directive('el-drag-dialog', drag)
|
||||
}
|
||||
|
||||
if (window.Vue) {
|
||||
window['el-drag-dialog'] = drag
|
||||
Vue.use(install); // eslint-disable-line
|
||||
}
|
||||
|
||||
drag.install = install
|
||||
export default drag
|
13
src/directive/permission/index.js
Normal file
@@ -0,0 +1,13 @@
|
||||
import permission from './permission'
|
||||
|
||||
const install = function(Vue) {
|
||||
Vue.directive('permission', permission)
|
||||
}
|
||||
|
||||
if (window.Vue) {
|
||||
window['permission'] = permission
|
||||
Vue.use(install); // eslint-disable-line
|
||||
}
|
||||
|
||||
permission.install = install
|
||||
export default permission
|
23
src/directive/permission/permission.js
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
import store from '@/store'
|
||||
|
||||
export default{
|
||||
inserted(el, binding, vnode) {
|
||||
const { value } = binding
|
||||
const roles = store.getters && store.getters.roles
|
||||
|
||||
if (value && value instanceof Array && value.length > 0) {
|
||||
const permissionRoles = value
|
||||
|
||||
const hasPermission = roles.some(role => {
|
||||
return permissionRoles.includes(role)
|
||||
})
|
||||
|
||||
if (!hasPermission) {
|
||||
el.parentNode && el.parentNode.removeChild(el)
|
||||
}
|
||||
} else {
|
||||
throw new Error(`need roles! Like v-permission="['admin','editor']"`)
|
||||
}
|
||||
}
|
||||
}
|
@@ -6,7 +6,7 @@ export default{
|
||||
const customOpts = Object.assign({}, binding.value)
|
||||
const opts = Object.assign({
|
||||
ele: el, // 波纹作用元素
|
||||
type: 'hit', // hit点击位置扩散center中心点扩展
|
||||
type: 'hit', // hit 点击位置扩散 center中心点扩展
|
||||
color: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
|
||||
}, customOpts)
|
||||
const target = opts.ele
|
||||
@@ -29,8 +29,8 @@ export default{
|
||||
ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'
|
||||
break
|
||||
default:
|
||||
ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px'
|
||||
ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px'
|
||||
ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.documentElement.scrollTop || document.body.scrollTop) + 'px'
|
||||
ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.documentElement.scrollLeft || document.body.scrollLeft) + 'px'
|
||||
}
|
||||
ripple.style.backgroundColor = opts.color
|
||||
ripple.className = 'waves-ripple z-active'
|
||||
|
@@ -2,20 +2,18 @@ import Vue from 'vue'
|
||||
import store from './store'
|
||||
|
||||
// you can set only in production env show the error-log
|
||||
// if (process.env.NODE_ENV === 'production') {
|
||||
|
||||
Vue.config.errorHandler = function(err, vm, info, a) {
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
Vue.config.errorHandler = function(err, vm, info, a) {
|
||||
// Don't ask me why I use Vue.nextTick, it just a hack.
|
||||
// detail see https://forum.vuejs.org/t/dispatch-in-vue-config-errorhandler-has-some-problem/23500
|
||||
Vue.nextTick(() => {
|
||||
store.dispatch('addErrorLog', {
|
||||
err,
|
||||
vm,
|
||||
info,
|
||||
url: window.location.href
|
||||
Vue.nextTick(() => {
|
||||
store.dispatch('addErrorLog', {
|
||||
err,
|
||||
vm,
|
||||
info,
|
||||
url: window.location.href
|
||||
})
|
||||
console.error(err, info)
|
||||
})
|
||||
console.error(err, info)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
|
@@ -1,3 +1,6 @@
|
||||
// set function parseTime,formatTime to filter
|
||||
export { parseTime, formatTime } from '@/utils'
|
||||
|
||||
function pluralize(time, label) {
|
||||
if (time === 1) {
|
||||
return time + label
|
||||
@@ -16,67 +19,8 @@ export function timeAgo(time) {
|
||||
}
|
||||
}
|
||||
|
||||
export function parseTime(time, cFormat) {
|
||||
if (arguments.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
if ((time + '').length === 10) {
|
||||
time = +time * 1000
|
||||
}
|
||||
|
||||
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
|
||||
let date
|
||||
if (typeof time === 'object') {
|
||||
date = time
|
||||
} else {
|
||||
date = new Date(parseInt(time))
|
||||
}
|
||||
const formatObj = {
|
||||
y: date.getFullYear(),
|
||||
m: date.getMonth() + 1,
|
||||
d: date.getDate(),
|
||||
h: date.getHours(),
|
||||
i: date.getMinutes(),
|
||||
s: date.getSeconds(),
|
||||
a: date.getDay()
|
||||
}
|
||||
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
|
||||
let value = formatObj[key]
|
||||
if (key === 'a') return ['一', '二', '三', '四', '五', '六', '日'][value - 1]
|
||||
if (result.length > 0 && value < 10) {
|
||||
value = '0' + value
|
||||
}
|
||||
return value || 0
|
||||
})
|
||||
return time_str
|
||||
}
|
||||
|
||||
export function formatTime(time, option) {
|
||||
time = +time * 1000
|
||||
const d = new Date(time)
|
||||
const now = Date.now()
|
||||
|
||||
const diff = (now - d) / 1000
|
||||
|
||||
if (diff < 30) {
|
||||
return '刚刚'
|
||||
} else if (diff < 3600) { // less 1 hour
|
||||
return Math.ceil(diff / 60) + '分钟前'
|
||||
} else if (diff < 3600 * 24) {
|
||||
return Math.ceil(diff / 3600) + '小时前'
|
||||
} else if (diff < 3600 * 24 * 2) {
|
||||
return '1天前'
|
||||
}
|
||||
if (option) {
|
||||
return parseTime(time, option)
|
||||
} else {
|
||||
return d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分'
|
||||
}
|
||||
}
|
||||
|
||||
/* 数字 格式化*/
|
||||
export function nFormatter(num, digits) {
|
||||
export function numberFormatter(num, digits) {
|
||||
const si = [
|
||||
{ value: 1E18, symbol: 'E' },
|
||||
{ value: 1E15, symbol: 'P' },
|
||||
@@ -93,12 +37,6 @@ export function nFormatter(num, digits) {
|
||||
return num.toString()
|
||||
}
|
||||
|
||||
export function html2Text(val) {
|
||||
const div = document.createElement('div')
|
||||
div.innerHTML = val
|
||||
return div.textContent || div.innerText
|
||||
}
|
||||
|
||||
export function toThousandslsFilter(num) {
|
||||
export function toThousandFilter(num) {
|
||||
return (+num || 0).toString().replace(/^-?\d+/g, m => m.replace(/(?=(?!\b)(\d{3})+$)/g, ','))
|
||||
}
|
||||
|
@@ -1,12 +1,9 @@
|
||||
import Vue from 'vue'
|
||||
import SvgIcon from '@/components/SvgIcon'// svg组件
|
||||
import generateIconsView from '@/views/svg-icons/generateIconsView.js'// just for @/views/icons , you can delete it
|
||||
|
||||
// register globally
|
||||
Vue.component('svg-icon', SvgIcon)
|
||||
|
||||
const requireAll = requireContext => requireContext.keys().map(requireContext)
|
||||
const req = require.context('./svg', false, /\.svg$/)
|
||||
const iconMap = requireAll(req)
|
||||
|
||||
generateIconsView.generate(iconMap) // just for @/views/icons , you can delete it
|
||||
const requireAll = requireContext => requireContext.keys().map(requireContext)
|
||||
requireAll(req)
|
||||
|
@@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1503994850540" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10206" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M931.6 585.6l0 79c28.6-60.2 44.8-127.4 44.8-198.4C976.4 211 769.4 4 514.2 4S52 211 52 466.2c0 3.2 0.2 6.4 0.2 9.6l166-206 96.4 0L171.8 485.6l46.4 0 0-54.8 99.2-154.6 0 209.4 0 100 0 82.4-99.2 0 0-82.4L67.6 585.6c43 161 170.6 287.4 332.4 328.6-10.4 26.2-40.6 89.4-90.8 100.6-62.2 14 168.8 3.4 333.6-104.6 126.6-36.6 230.8-125.8 287.4-242.2l-97.6 0 0-82.4-166.2 0 0-87.2 0-12.8L666.4 476l166.2-206.2 94 0-140.4 215.8 46.4 0 0-59 99.2-154 0 213.2L931.8 585.6zM366.2 608c-4.8-11.2-7.2-23.2-7.2-36L359 357.6c0-12.8 2.4-24.8 7.2-36 4.8-11.2 11.4-21 19.6-29.2 8.2-8.2 18-14.8 29.2-19.6 11.2-4.8 23.2-7.2 36-7.2l81.6 0c12.8 0 24.8 2.4 36 7.2 11 4.8 20.6 11.2 28.8 19.2l-88.6 129.4 0-23c0-4.8-1.6-8.8-4.8-12-3.2-3.2-7.2-4.8-12-4.8-4.8 0-8.8 1.6-12 4.8-3.2 3.2-4.8 7.2-4.8 12l0 72L372.6 620C370.2 616.2 368 612.2 366.2 608zM624.4 572c0 12.8-2.4 24.8-7.2 36-4.8 11.2-11.4 21-19.6 29.2-8.2 8.2-18 14.8-29.2 19.6-11.2 4.8-23.2 7.2-36 7.2l-81.6 0c-12.8 0-24.8-2.4-36-7.2-11.2-4.8-21-11.4-29.2-19.6-3.6-3.6-7-7.8-10-12l99.2-144.6 0 50.6c0 4.8 1.6 8.8 4.8 12 3.2 3.2 7.2 4.8 12 4.8 4.8 0 8.8-1.6 12-4.8 3.2-3.2 4.8-7.2 4.8-12l0-99.6 92.6-135.2c6.6 7.4 12 15.8 16 25.2 4.8 11.2 7.2 23.2 7.2 36L624.2 572z" p-id="10207"></path></svg>
|
||||
<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>
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.4 KiB |
@@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1503994864347" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10314" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M969.142857 548.571429q0 14.848-10.861714 25.709714t-25.709714 10.861714l-128 0q0 97.718857-38.290286 165.705143l118.857143 119.442286q10.861714 10.861714 10.861714 25.709714t-10.861714 25.709714q-10.276571 10.861714-25.709714 10.861714t-25.709714-10.861714l-113.152-112.566857q-2.852571 2.852571-8.557714 7.424t-23.990857 16.274286-37.156571 20.845714-46.848 16.566857-55.442286 7.424l0-512-73.142857 0 0 512q-29.147429 0-58.002286-7.716571t-49.700571-18.870857-37.705143-22.272-24.868571-18.578286l-8.557714-8.009143-104.557714 118.272q-11.446857 11.995429-27.428571 11.995429-13.714286 0-24.576-9.142857-10.861714-10.276571-11.702857-25.417143t8.850286-26.587429l115.419429-129.718857q-33.133714-65.133714-33.133714-156.562286l-128 0q-14.848 0-25.709714-10.861714t-10.861714-25.709714 10.861714-25.709714 25.709714-10.861714l128 0 0-168.009143-98.852571-98.852571q-10.861714-10.861714-10.861714-25.709714t10.861714-25.709714 25.709714-10.861714 25.709714 10.861714l98.852571 98.852571 482.304 0 98.852571-98.852571q10.861714-10.861714 25.709714-10.861714t25.709714 10.861714 10.861714 25.709714-10.861714 25.709714l-98.852571 98.852571 0 168.009143 128 0q14.848 0 25.709714 10.861714t10.861714 25.709714zM694.857143 219.428571l-365.714286 0q0-75.995429 53.430857-129.426286t129.426286-53.430857 129.426286 53.430857 53.430857 129.426286z" p-id="10315"></path></svg>
|
||||
<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>
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1503994873331" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10422" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M64 448 320 448 320 960 64 960 64 448 64 448ZM704 256 960 256 960 960 704 960 704 256 704 256ZM384 64 640 64 640 960 384 960 384 64 384 64Z" p-id="10423"></path></svg>
|
||||
<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>
|
Before Width: | Height: | Size: 552 B After Width: | Height: | Size: 179 B |
@@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1506419860538" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4662" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M438.857143 950.857143l512 0 0-365.714286-237.714286 0q-22.820571 0-38.838857-16.018286t-16.018286-38.838857l0-237.714286-219.428571 0 0 658.285714zM585.142857 128l0-36.571429q0-7.460571-5.412571-12.873143t-12.873143-5.412571l-402.285714 0q-7.460571 0-12.873143 5.412571t-5.412571 12.873143l0 36.571429q0 7.460571 5.412571 12.873143t12.873143 5.412571l402.285714 0q7.460571 0 12.873143-5.412571t5.412571-12.873143zM731.428571 512l170.861714 0-170.861714-170.861714 0 170.861714zM1024 585.142857l0 384q0 22.820571-16.018286 38.838857t-38.838857 16.018286l-548.571429 0q-22.820571 0-38.838857-16.018286t-16.018286-38.838857l0-91.428571-310.857143 0q-22.820571 0-38.838857-16.018286t-16.018286-38.838857l0-768q0-22.820571 16.018286-38.838857t38.838857-16.018286l621.714286 0q22.820571 0 38.838857 16.018286t16.018286 38.838857l0 187.465143q11.995429 7.460571 20.553143 16.018286l233.179429 233.179429q16.018286 16.018286 27.428571 43.446857t11.410286 50.322286z" p-id="4663"></path></svg>
|
||||
<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>
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 971 B |
@@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1506329916765" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1661" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M64 64 448 64 448 448 64 448 64 64ZM64 576 448 576 448 960 64 960 64 576ZM576 576 960 576 960 960 576 960 576 576ZM768 448C874.038669 448 960 362.038672 960 256 960 149.961328 874.038669 64 768 64 661.961328 64 576 149.961328 576 256 576 362.038672 661.961328 448 768 448Z" p-id="1662"></path></svg>
|
||||
<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>
|
Before Width: | Height: | Size: 683 B After Width: | Height: | Size: 319 B |
@@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1509611822979" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10379" xmlns:xlink="http://www.w3.org/1999/xlink" width="32" height="32"><defs><style type="text/css"></style></defs><path d="M219.428571 658.285714q0-30.285714-21.428571-51.714285T146.285714 585.142857t-51.714285 21.428572T73.142857 658.285714t21.428572 51.714286T146.285714 731.428571t51.714286-21.428571T219.428571 658.285714z m109.714286-256q0-30.285714-21.428571-51.714285T256 329.142857t-51.714286 21.428572T182.857143 402.285714t21.428571 51.714286T256 475.428571t51.714286-21.428571T329.142857 402.285714z m244.571429 274.857143l57.714285-218.285714q3.428571-14.857143-4.285714-27.714286T605.142857 414.285714t-27.428571 3.714286-17.142857 22.571429l-57.714286 218.285714q-34.285714 2.857143-61.142857 24.857143t-36 56.285714q-11.428571 44 11.428571 83.428571t66.857143 50.857143 83.428571-11.428571 50.857143-66.857143q9.142857-34.285714-3.428571-66.857143t-41.142857-52z m377.142857-18.857143q0-30.285714-21.428572-51.714285T877.714286 585.142857t-51.714286 21.428572-21.428571 51.714285 21.428571 51.714286 51.714286 21.428571 51.714285-21.428571 21.428572-51.714286z m-365.714286-365.714285q0-30.285714-21.428571-51.714286T512 219.428571t-51.714286 21.428572T438.857143 292.571429t21.428571 51.714285T512 365.714286t51.714286-21.428572T585.142857 292.571429z m256 109.714285q0-30.285714-21.428571-51.714285T768 329.142857t-51.714286 21.428572T694.857143 402.285714t21.428571 51.714286T768 475.428571t51.714286-21.428571T841.142857 402.285714z m182.857143 256q0 149.142857-80.571429 276-10.857143 16.571429-30.857142 16.571429H111.428571q-20 0-30.857142-16.571429Q0 808 0 658.285714q0-104 40.571429-198.857143t109.142857-163.428571 163.428571-109.142857 198.857143-40.571429 198.857143 40.571429 163.428571 109.142857 109.142857 163.428571 40.571429 198.857143z" p-id="10380"></path></svg>
|
||||
<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>
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.3 KiB |
@@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1510826638494" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1669" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M743.253333 144.184889H374.499556v734.378667H743.253333a92.017778 92.017778 0 0 0 92.16-91.818667V235.975111a91.989333 91.989333 0 0 0-92.16-91.790222z m-0.398222 293.888c0.398222 20.48-1.507556 26.794667-9.756444 26.794667-3.612444 0.597333-9.415111-1.621333-17.863111-8.874667-12.657778-8.931556-21.504-16.753778-29.155556-21.617778-6.798222-5.888-17.550222-5.205333-24.291556 0-8.874667 4.949333-21.532444 15.872-28.814222 21.617778-8.988444 7.907556-15.018667 8.874667-17.180444 8.874667-8.618667 0-10.837333-7.424-10.496-26.794667l-0.312889-223.601778c0-21.162667 8.561778-24.376889 17.265778-24.376889h103.708444c10.552889 0 17.294222 4.835556 17.294222 24.376889l-0.398222 223.601778zM190.122667 235.975111V786.773333a92.046222 92.046222 0 0 0 92.188444 91.818667h46.08V144.184889h-46.08a92.017778 92.017778 0 0 0-92.188444 91.790222z" fill="" p-id="1670"></path></svg>
|
||||
<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>
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 418 B |
@@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1503994190757" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9007" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M574.957891 267.016403 511.503696 267.016403l204.64896 0L511.212054 63.654762l-203.361641 203.361641L449.041086 267.016403l0 189.662641L258.687714 456.679044l0 125.916804L449.041086 582.595848l0 190.354396 125.916804 0L574.957891 582.595848l188.874695 0L763.832586 456.679044 574.957891 456.679044 574.957891 267.016403zM511.25401 960.345238l189.620685-187.394994L323.125305 772.950244 511.25401 960.345238zM71.291696 518.891967l187.394994 189.620685L258.68669 330.762239 71.291696 518.891967zM763.832586 330.762239l0 377.74939 188.874695-189.620685L763.832586 330.762239z" p-id="9008"></path></svg>
|
||||
<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>
|
Before Width: | Height: | Size: 983 B After Width: | Height: | Size: 356 B |
1
src/icons/svg/edit.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><g><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"/></g></svg>
|
After Width: | Height: | Size: 825 B |
@@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1503994210967" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9120" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M513 583.8l448.5-448.5c-11.6-4.7-24.3-7.3-37.5-7.3L100 128c-12.7 0-24.9 2.4-36.1 6.7L513 583.8z" p-id="9121"></path><path d="M513 674.3 14.6 175.9C5.3 191.1 0 208.9 0 228l0 568c0 55.2 44.8 100 100 100l824 0c55.2 0 100-44.8 100-100l0-568c0-18.5-5.1-35.9-13.9-50.8L513 674.3z" p-id="9122"></path></svg>
|
||||
<svg width="128" height="96" xmlns="http://www.w3.org/2000/svg"><g><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"/></g></svg>
|
Before Width: | Height: | Size: 684 B After Width: | Height: | Size: 354 B |
@@ -1 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1503994811583" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9878" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><defs><style type="text/css"></style></defs><path d="M770.56 460.8l250.88 0C998.4 220.16 803.84 25.6 563.2 2.56l0 250.88C668.16 273.92 750.08 355.84 770.56 460.8L770.56 460.8zM770.56 460.8" p-id="9879"></path><path d="M460.8 253.44 460.8 2.56C220.16 25.6 25.6 220.16 2.56 460.8l250.88 0C273.92 355.84 355.84 273.92 460.8 253.44L460.8 253.44zM460.8 253.44" p-id="9880"></path><path d="M563.2 770.56l0 250.88c243.2-23.04 435.2-217.6 460.8-460.8l-250.88 0C750.08 668.16 668.16 750.08 563.2 770.56L563.2 770.56zM563.2 770.56" p-id="9881"></path><path d="M253.44 563.2 2.56 563.2c23.04 243.2 217.6 435.2 460.8 460.8l0-250.88C355.84 750.08 273.92 668.16 253.44 563.2L253.44 563.2zM253.44 563.2" p-id="9882"></path></svg>
|
||||
<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>
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 497 B |