1
0
mirror of https://github.com/PanJiaChen/vue-element-admin.git synced 2025-04-05 19:41:51 +08:00

Compare commits

...

144 Commits

Author SHA1 Message Date
花裤衩
6858a9ad67 docs: update sponsor 2024-10-24 19:25:43 +08:00
花裤衩
0caa975ee2 docs: update sponsor image src 2022-04-11 11:32:06 +08:00
花裤衩
cd3f726749 docs: update sponsor 2022-04-11 10:30:57 +08:00
花裤衩
7ddfe81749 docs: update 2021-12-07 18:55:16 +08:00
花裤衩
805965e8f2 docs: update sponsor 2021-12-07 18:54:03 +08:00
花裤衩
e680b8fa7b docs: update sponsor 2021-12-07 18:26:52 +08:00
花裤衩
0e61e6d82d docs: update readme 2021-11-19 15:18:26 +08:00
花裤衩
33a93a12b4 feat: add new sponsored 2020-12-04 13:50:23 +08:00
花裤衩
1bc2e5c198 docs: add coupon 2020-09-08 10:01:50 +08:00
花裤衩
9cc3fa732a perf: refine documentation button css 2020-09-07 21:45:28 +08:00
花裤衩
44e23d00ca docs: add vue-java-admin-dashboard-spring 2020-09-07 21:37:44 +08:00
花裤衩
8fd08c9167 docs: remove gitads 2020-08-30 22:57:38 +08:00
花裤衩
5e7113935c docs: add GitAds 2020-07-27 10:08:38 +08:00
Kerollos Magdy
46e11caafc
typo: replace Css with CSS (#3323) 2020-07-20 18:13:01 +08:00
dyz
ea60478304
perf[permission.js]: remove useless code (#3301) 2020-07-05 13:12:46 +08:00
crayymumu
fe22b3cd94
perf[Tinymce]: remove useless code (#3295) 2020-07-01 13:50:18 +08:00
花裤衩
7c06214190
perf[chore]: remove preserveWhitespace config (#3280) 2020-06-24 10:17:57 +08:00
花裤衩
73a9ab0379
fix[chore]: do not preload runtime.js (#3279) 2020-06-23 21:12:44 +08:00
花裤衩
585391228e [release] 4.4.0 2020-06-21 21:39:37 +08:00
Dihak
ae2aa61880
bump: update to vue-cli@4 (#3028) 2020-06-21 21:25:55 +08:00
花裤衩
f6d8204b0b [release] 4.3.1 2020-06-18 21:01:02 +08:00
花裤衩
435db380d3 fix some typos 2020-06-15 17:18:55 +08:00
qige2016
6d88db5c73
fix[plop]: set trim => trim() (#3254)
notEmpty
2020-06-15 12:00:17 +08:00
花裤衩
1c943509f9 chore: update element-ui to 2.13.2 2020-06-12 10:18:05 +08:00
花裤衩
4e7665c072
fix[v-permission]: support dynamic set roles (#3251) 2020-06-11 21:02:18 +08:00
花裤衩
a87218e266 perf: lint code 2020-06-11 20:51:10 +08:00
Silentdoer
7702b3d809
perf: remove unused showdown
Co-authored-by: 花裤衩 <panfree23@gmail.com>
2020-06-11 20:24:17 +08:00
MaYuanhai
a50180f653
fix[utils]: param2Obj bug when url params includes ==(#3100) 2020-06-11 20:18:23 +08:00
Cat73
fc68f56d13
feat[Menu]: menu icon support el-icon(#3048) 2020-06-11 13:57:41 +08:00
花裤衩
d3bd933a8e
refactor: change mock files to commonjs (#3246) 2020-06-11 11:40:53 +08:00
花裤衩
0bf61aac53 chore: turn on the preload 2020-06-10 21:47:50 +08:00
花裤衩
2ef49493c3 docs: fix wrong link 2020-06-09 10:51:27 +08:00
花裤衩
f14805d0cd [release] 4.3.0 2020-06-08 21:35:01 +08:00
花裤衩
c5abe7532c perf: change >>> ::v-deep 2020-06-08 20:42:55 +08:00
Cat73
534cd5bc26
chore: change node-sass to dart-sass (#3040) 2020-06-08 20:41:46 +08:00
花裤衩
f1feb2a86d [release] 4.2.2 2020-06-08 19:38:55 +08:00
Edwin Betancourt
0ae5079b2a
docs: Improve read me files and changes in Spanish. (#3234) 2020-06-05 13:32:15 +08:00
Nickbing Lao
6f80263b42
fix[css]: min btn width (#3164) 2020-05-08 11:43:39 +08:00
cooper
5890499077
fix[parseTime]: fixed when pass null (#3038) 2020-05-05 13:21:51 +08:00
AiMe1991
29b4ff636b
perf: when tags-view scroll close the right-menu 2020-05-05 12:55:22 +08:00
花裤衩
e692876c28 docs: add tips 2020-05-05 11:06:51 +08:00
garethx
6dacb783b2
feat: add option to try project on CodeSandbox (#2976) 2020-05-04 23:05:29 +08:00
Phạm Ngọc Hòa
a2784dd6ef
perf: change default element-ui language to english (#2741) 2020-05-04 21:51:21 +08:00
花裤衩
fc26c3106f
fix: compatibility with vetur (#1700) 2020-05-04 21:30:58 +08:00
ntnyq
9580c43a8e
fix[element-variables]: missing space in element-variables (#3144) 2020-04-28 18:26:34 +08:00
Aisen
1b8f726529
perf[Tinymce]: editor try to keep these URLs intact (#3141) 2020-04-28 10:10:58 +08:00
花裤衩
d4405464ce
fix: use vue-cli default source-map (#3097)
cheap-module-eval-source-map
2020-04-22 10:31:46 +08:00
Alex S
9d8c7edf91
fixed typo (#3091) 2020-04-04 15:53:26 +08:00
花裤衩
6eccffeb2f
fix: svg support old broswer (#3085) 2020-03-28 11:16:41 +08:00
花裤衩
f7a9d21109
Update README.zh-CN.md 2020-03-27 12:32:30 +08:00
花裤衩
993a6c72e8 docs: add smallsticker 2020-03-27 11:57:40 +08:00
echofly
9e0435ac85
perf: format component names as PascalCase (#3074)
format: component names should be PascalCase
2020-03-24 10:17:18 +08:00
Aisen60
776f10e197
fix:fixed parseTime bug in ie and safari(#3066)
* /src/utils/index.js parseTime 添加IE浏览器(版本10以下,包括版本10)兼容。

* perf: update

Co-authored-by: aisen60 <aisen60@qq.com>
Co-authored-by: 花裤衩 <panfree23@gmail.com>
2020-03-20 21:24:31 +08:00
echofly
c2a5a15956
fix[profile/UserCard]: fixed wrong key name (#3056)
roles => role
2020-03-18 19:22:38 +08:00
花裤衩
a45e64fcb2 perf: change script-loader to dependencies 2020-02-12 10:01:27 +08:00
Shota Aratono
fec25fedba
docs: improve Japanese translation (#2970) 2020-02-05 09:51:43 +08:00
RoBlues
d6816c547d
perf[Mock]: set responseFake to mock-server.js(#2966)
* modify 把mock/index.js中与mock-server相关的代码转移到mock-server.js中去,实现两则功能分割
2020-02-02 19:39:40 +08:00
李小斐
6850312e89 fix: fixed redirect path regex (#2933) 2020-01-11 10:25:59 +08:00
花裤衩
d634e2ae2f fix: fixed require mock bug in production 2020-01-09 20:24:48 +08:00
花裤衩
b57f2008bd bump: update element-ui version 2020-01-09 17:36:49 +08:00
花裤衩
c9affcf2ad
fix: fixed mock server (#2929)
* init

* refine

* update
2020-01-09 17:21:36 +08:00
花裤衩
fbad7f481b
fix[Charts]: fix charts resize in keep-alive bug (#2922)
* fix[Charts]: fix charts resize in keep-alive bug

* refine
2020-01-09 16:49:57 +08:00
RussXD
088f64eecc perf: optimize checkCapslock method (#2635)
* optimize checkCapslock method

* update

Co-authored-by: 花裤衩 <panfree23@gmail.com>
2020-01-08 12:12:10 +08:00
AndyLZC/AndyLZC.github.io
55b1bbac99 perf[complex-table]:refine code (#2825)
* 解决无法删除列表的bug;优化代码;

* perf: refine

Co-authored-by: 花裤衩 <panfree23@gmail.com>
2020-01-07 22:30:07 +08:00
Kaitian Xie
fd5a2e8da2 perf[Menu]: remove unused menu-wrapper (#2903) 2020-01-06 22:34:14 +08:00
任羽飞
a0b39d5043 perf: import mockXHR only in production (#2910)
* 自动排除mock

生产环境,使用webpack的条件编译自动排除mock数据

* perf: refine

Co-authored-by: 花裤衩 <panfree23@gmail.com>
2020-01-06 22:22:37 +08:00
4f563a7bfe fix[Logout]: click blank area of ​​dropDown able to logout (#2896)
Fixed clicking blank area of ​​drop-down unable to log out
2019-12-31 14:14:34 +08:00
花裤衩
262c0ba08e perf[documentation]: refine css 2019-12-15 20:17:59 +08:00
flitrue
594fc58d0c fix[icons]:fixed eslint 1 error and 2 warnings (#2835) 2019-12-12 15:16:03 +08:00
monkeycf
65d8c451e8 feat: plop new generate store (#2805) 2019-12-04 10:34:23 +08:00
xuanzai
e1554fdbd0 perf[views/icons]: use grid (#2803) 2019-12-01 15:48:30 +08:00
Phạm Ngọc Hòa
53803d067d perf: format pdf download (#2791) 2019-11-27 10:06:28 +08:00
花裤衩
25dddbbce8
update 'MarkdownEditor' components name (#2743) 2019-11-12 17:25:12 +08:00
Phạm Ngọc Hòa
683f68b838 format: space in user card (#2744) 2019-11-12 17:24:30 +08:00
bbigcd
44203f88a7
update 'MarkdownEditor' components name 2019-11-12 12:08:45 +08:00
Phạm Ngọc Hòa
d5c013a48c perf: text i18n (#2739) 2019-11-11 19:39:59 +08:00
Phạm Ngọc Hòa
b11acb2171 perf: complex table (#2732)
Move ont format `{row}`
2019-11-08 11:26:53 +08:00
Phạm Ngọc Hòa
b2dd7caee6 perf: format drag table (#2733)
move one format `{row}`
2019-11-08 11:25:42 +08:00
Phạm Ngọc Hòa
a4fa1199ba perf: format inline edit table (#2725)
move one format `{row}`
2019-11-07 13:37:05 +08:00
Phạm Ngọc Hòa
6a194d1b4f perf: format dropdown menu code (#2720) 2019-11-05 14:26:24 +08:00
花裤衩
6739ab543b style: fix el-date-picker css style 2019-10-25 19:45:21 +08:00
BradyBromley
6a214f0eac docs: improved README.md (#2656) 2019-10-14 10:25:30 +08:00
花裤衩
5273e02259 docs: add job ad 2019-10-12 17:51:26 +08:00
花裤衩
b51590b982
fix[TagsView]: fixed click.middle can close affixed tag bug (#2649) 2019-10-11 13:37:01 +08:00
MaYuanhai
12b44f5d4b perf[SvgIcon]: change xlink:href to href(#2645)
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/xlink:href
2019-10-10 11:35:48 +08:00
花裤衩
197948dc44
fix[TagsView]: fixed toLastView bug (#2634) 2019-10-08 21:20:34 +08:00
花裤衩
b4cdf528ba
fix[logout]: empty tagsview when logout (#2632) 2019-10-08 20:38:19 +08:00
花裤衩
f266713daf fix[tagsView]: fixed DEL_OTHERS_CACHED_VIEWS bug 2019-10-08 18:20:11 +08:00
monkeycf
0343988f3d perf[tagsView]: pref DEL_CACHED_VIEW and DEL_OTHERS_CACHED_VIEWS function (#2626) 2019-10-08 18:15:22 +08:00
monkeycf
9c723c6618 perf[utils.js]: perf parseTime function (#2625) 2019-10-08 17:54:47 +08:00
花裤衩
e3cbf4ad90 fix[example]: fixed create.vue cache error
https://github.com/PanJiaChen/vue-element-admin/issues/2608
2019-09-30 16:38:18 +08:00
花裤衩
8235011665 fix: fixed numberFormatter bug
https://github.com/PanJiaChen/vue-element-admin/issues/2568
2019-09-30 15:06:42 +08:00
MaYuanhai
0e9ce78b8a refactor[ImageCropper]: fix lint error (#2365) 2019-09-30 13:56:56 +08:00
Serge
3a08b6e471 perf: optimize import file-saver way(#2347) 2019-09-30 13:14:55 +08:00
Francis
4d2d52ef03 perf: VS Code support webpack alias file jump (#2609) 2019-09-27 13:45:49 +08:00
MaYuanhai
1336b92c2f fix[Dashboard]: fixed debounce bug (#2586) (#2597)
To fixed https://github.com/PanJiaChen/vue-element-admin/issues/2586
2019-09-26 10:34:31 +08:00
花裤衩
c7c815eef0 docs: add awesome-project 2019-09-22 18:40:28 +08:00
Baskerville*
ee287d8314 fix: typos (#2532)
Role Nmae => Role Name
2019-08-29 10:23:45 +08:00
花裤衩
12c8d85873 fix: fixed missing icons 2019-08-27 20:57:51 +08:00
why
46cc375d0d fix[complex-table]: form header sort icon is out of sync (#2382) 2019-07-16 17:12:26 +08:00
Pan
c8039a5ce3 chore: allow dynamic set port 2019-07-04 16:41:44 +08:00
itsccn
1909018dbd bump: update @vue/cli-plugin-eslint version (#2327)
FIx  cannot find module '.../node_modules/eslint/lib/api.js/package.json' bug,see https://github.com/vuejs/vue-cli/issues/4231.
2019-07-04 14:38:31 +08:00
Pan
018c20a3f6 bump: update axios for security vulnerability 2019-06-30 16:07:54 +08:00
MaYuanhai
ef167ff064 perf[clipboard.js]: remove redundant code (#2307) 2019-06-30 11:09:19 +08:00
TinaryTree
35adfcef3f docs: fix typo README.zh-CN.md (#2283)
修改错别字
2019-06-27 23:15:48 +08:00
MaYuanhai
d3a2b6b34e perf[PanThumb]: Replace the image tag with background-image to prevent the stretching (#2202) 2019-06-06 17:46:00 +08:00
肖敏
4bd8f7f670 fix: input attribute autocomplete error (#2191) 2019-06-02 16:08:23 +08:00
Jessynt
8e9f2e1479 docs: fix typo (#2170) 2019-05-28 16:18:25 +08:00
MaYuanhai
a0793dbeab fix[ImageCropper]: removeEventListener when destroyed(#2169) 2019-05-28 15:10:37 +08:00
Pan
9538d1b766 perf: default not set withCredentials 2019-05-28 11:09:00 +08:00
Pan
054ed40e07 [release] 4.2.1 2019-05-27 16:25:37 +08:00
Serge
ac8c12c82d perf[request.js]: refine error reject (#2160) 2019-05-27 16:24:47 +08:00
花裤衩
e8837d161e
feat: add tab url demo (#2114) 2019-05-27 15:48:45 +08:00
花裤衩
f891202706
fix[Tinymce]: fixed bug when init multiple tinymces at the same time (#2152) 2019-05-27 15:35:07 +08:00
花裤衩
e28701cde4
perf[Tinymce]: add language option (#2159) 2019-05-27 15:04:34 +08:00
bpzhang
5b943d71e9 chore: add autoprefixer to devDependencies 2019-05-27 15:04:04 +08:00
Pan
2584dcce16 update github ISSUE_TEMPLATE 2019-05-27 10:37:00 +08:00
花裤衩
6a322c9def
chore: set localhost => 127.0.0.1 (#2142) 2019-05-26 17:12:36 +08:00
花裤衩
ab1922ef14
Create FUNDING.yml 2019-05-24 10:02:27 +08:00
花裤衩
13c1ecf25c
fix[Chart]: fixed chart bug in keep-alive (#2119) 2019-05-23 11:27:10 +08:00
Pan
8ce250a44e perf[Style]: refine example css 2019-05-23 10:18:50 +08:00
Pan
2f5c2eebcd [release] 4.2.0 2019-05-21 10:53:49 +08:00
花裤衩
6770963672
perf[Tinymce]: dynamic import tinymce(#2102) 2019-05-21 10:50:10 +08:00
Pan
131b9b9eff refactor[chore]: generate postcss.config.js instead of .postcssrc.js
consistent with vue-cli
2019-05-20 13:16:08 +08:00
花裤衩
cd30d25459
perf[Login]: support other query (#2013) 2019-05-20 11:21:07 +08:00
Yamel Senih
d0fcbbaa28 perf[store]: add support to sub-modules (#2047) 2019-05-20 11:10:30 +08:00
花裤衩
40431fdfc8
perf[Breadcrumb]: do not update breadcrumbs when go to redirect page (#2086) 2019-05-20 11:04:51 +08:00
花裤衩
1e598e9684
fix: fixed change roles bug (#2072) 2019-05-20 11:04:17 +08:00
花裤衩
be3dfac13b
feat[SvgIcon]: support import svg from url (#2052) 2019-05-20 11:03:29 +08:00
liugq
4f620c4a0d perf[RightPanel]: tidy css (#2101) 2019-05-17 15:51:08 +08:00
Pan
36060d5daf perf[Exapme]: set page title according to article id 2019-05-17 10:20:42 +08:00
Yamel Senih
a0b2014e85 docs[es]: add some translation(#2080) 2019-05-15 09:33:36 +08:00
Yamel Senih
dbfcc9dc19 docs: add support to readme for Spanish (#2070) 2019-05-14 11:04:03 +08:00
Pan
45edf7b048 fix[redirect]: fix redirect bug in vue-devtool again 2019-05-13 17:32:53 +08:00
Pan
2096ae1b6e perf[Tinymce]: update tinymce cdn version 2019-05-13 10:02:03 +08:00
花裤衩
27df997915
fix[redirect]: fix redirect bug in vue-devtools (#2066) 2019-05-12 14:01:04 +08:00
toruksmakto
3a4543478f feat[ErrorLog]: add a clear button in ErrorLog component (#2065) 2019-05-12 12:00:00 +08:00
花裤衩
7b0d527bf9
perf[style]: refine dashboard style in mobile (#2060) 2019-05-10 18:39:05 +08:00
Pan
0b8baeb14d fix[sidebar.css]: remove redundant css 2019-05-10 18:29:50 +08:00
Pan
4ef0782189 chore: use mockjs in production environment 2019-05-10 14:47:57 +08:00
Pan
0bf339b6db doc: add new article 2019-05-09 12:47:28 +08:00
Pan
013f4fd91b perf[Style]: refine fixed-header style when open el-dialog 2019-05-08 18:10:41 +08:00
Pan
2364fecbdd Revert "perf: optimize page scrolling when setting fixedHeader"
This reverts commit e8e6c7e79c2488779090f00efc5f1bbfcb04bd5b.
2019-05-08 17:50:26 +08:00
花裤衩
7e8a6a4759
perf[Profile]: adapt the profile page to the mobile (#2020) 2019-05-07 14:08:28 +08:00
107 changed files with 2608 additions and 1550 deletions

View File

@ -3,12 +3,3 @@ ENV = 'development'
# base api
VUE_APP_BASE_API = '/dev-api'
# vue-cli uses the VUE_CLI_BABEL_TRANSPILE_MODULES environment variable,
# to control whether the babel-plugin-dynamic-import-node plugin is enabled.
# It only does one thing by converting all import() to require().
# This configuration can significantly increase the speed of hot updates,
# when you have a large number of pages.
# Detail: https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/babel-preset-app/index.js
VUE_CLI_BABEL_TRANSPILE_MODULES = true

4
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,4 @@
# These are supported funding model platforms
patreon: panjiachen
custom: https://panjiachen.github.io/vue-element-admin-site/donate

View File

@ -12,3 +12,24 @@ about: Asking questions about use
Before asking a question, please make sure that you have tried your best to solve this problem.
If it's a code-related issue, please don't just take screenshots. Please provide an online demo to save each other's time.
-->
#### Steps to reproduce问题复现步骤
<!--
1. [xxx]
2. [xxx]
3. [xxxx]
-->
#### Screenshot or Gif截图或动态图
#### Link to minimal reproduction最小可在线还原demo
<!--
Please only use Codepen, JSFiddle, CodeSandbox or a github repo
-->
#### Other relevant information格外信息
- Your OS:
- Node.js version:
- vue-element-admin version:

View File

@ -1,8 +0,0 @@
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {}
}
}

228
README.es.md Normal file
View File

@ -0,0 +1,228 @@
<p align="center">
<img width="320" src="https://wpimg.wallstcn.com/ecc53a42-d79b-42e2-8852-5126b810a4c8.svg">
</p>
<p align="center">
<a href="https://github.com/vuejs/vue">
<img src="https://img.shields.io/badge/vue-2.6.10-brightgreen.svg" alt="vue">
</a>
<a href="https://github.com/ElemeFE/element">
<img src="https://img.shields.io/badge/element--ui-2.7.0-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="Estado de Construcción">
</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="Licencia">
</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="Liberación Github">
</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="Donación">
</a>
</p>
Español | [English](./README.md) | [简体中文](./README.zh-CN.md) | [日本語](./README.ja.md)
## Introducción
[vue-element-admin](https://panjiachen.github.io/vue-element-admin) es una interfáz de administración preparada para producción. Está basada en [vue](https://github.com/vuejs/vue) y usa [element-ui](https://github.com/ElemeFE/element) como conjunto de herramientas de interfáz de usuario.
Vue Element Admin es una solución práctica basada en la nueva plataforma de desarrollo de vue, construida con soporte a i18 para el manejo de múltiples lenguajes, plantillas estándares para aplicaciones de negocio y un conjunto de asombrosas características. Esta herramienta ayuda a construir largas y complejas Aplicacones de una sola página (SPA). Creo que lo que necesites hacer, este proyecto te ayudará.
- [Vista Prévia de la Aplicación](https://panjiachen.github.io/vue-element-admin)
- [Documentación](https://panjiachen.github.io/vue-element-admin-site/)
- [Canal de Gitter](https://gitter.im/vue-element-admin/discuss)
- [Para Donaciones](https://panjiachen.github.io/vue-element-admin-site/donate/)
- [Enlace de Wiki](https://github.com/PanJiaChen/vue-element-admin/wiki)
- [Canal de Gitee](https://panjiachen.gitee.io/vue-element-admin/)
- Plantilla base recomendada para usar: [vue-admin-template](https://github.com/PanJiaChen/vue-admin-template)
- Aplicación de Escritorio: [electron-vue-admin](https://github.com/PanJiaChen/electron-vue-admin)
- Plantilla de Typescript: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (Créditos: [@Armour](https://github.com/Armour))
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
**Después de la versión `v4.1.0+`, la rama por defecto master no tendrá soporte para i18n. Por favor utilice la rama [i18n](https://github.com/PanJiaChen/vue-element-admin/tree/i18n), los cambios serán incluidos en la rama master**
**la versión actual es `v4.0+` construida con `vue-cli`. Si encuentra algún problema, por favor coloque un [issue](https://github.com/PanJiaChen/vue-element-admin/issues/new). Si desea usar la versión anterior, puede cambiar de rama a [tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0), no relacionado con `vue-cli`**
**Este proyecto no está soportado para versiones antigüas de navegadores (ej. IE).**
## Preparación
Necesita instalar [node](https://nodejs.org/) y [git](https://git-scm.com/) localmente. El proyecto es basado en [ES2015+](https://es6.ruanyifeng.com/), [vue](https://cn.vuejs.org/index.html), [vuex](https://vuex.vuejs.org/zh-cn/), [vue-router](https://router.vuejs.org/zh-cn/), [vue-cli](https://github.com/vuejs/vue-cli) , [axios](https://github.com/axios/axios) and [element-ui](https://github.com/ElemeFE/element), toda la solicitud de datos simulada se realiza a través de [Mock.js](https://github.com/nuysoft/Mock).
Entendiendo y aprendiendo esto pudiera ayudarle con su proyecto.
[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/PanJiaChen/vue-element-admin/tree/CodeSandbox)
<p align="center">
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
</p>
## Patrocinantes
Sea un patrocinante y coloque su logo en nuestro LEEME en GitHub con un enlace directo a su sitio web. [[Se un Patrocinante]](https://www.patreon.com/panjiachen)
### Akveo
<a href="https://store.akveo.com/products/vue-java-admin-dashboard-spring?utm_campaign=akveo_store-Vue-Vue_demo%2Fgithub&utm_source=vue_admin&utm_medium=referral&utm_content=github_banner"><img width="500px" src="https://raw.githubusercontent.com/PanJiaChen/vue-element-admin-site/master/docs/.vuepress/public/images/vue-java-banner.png" /></a><p>Get Java backend for Vue admin with 20% discount for 39$ use coupon code SWB0RAZPZR1M
</p>
### Flatlogic
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
## Características
```
- Iniciar / Cerrar Sesión
- Permisos de Autenticación
- Página de Permisos
- Directivas de permisos
- Página de configuración de permisos
- Autenticación por dos pasos
- Construcción Multi-entorno
- Desarrollo (dev)
- sit
- Escenario de pruebas (stage),
- Producción (prod)
- Características Globales
- I18n
- Temas dinámicos
- Menu lateral dinámico (soporte a rutas multi-nivel)
- Barra de rutas dinámica
- Tags-view (Pestañas de página, Soporta operación de clic derecho)
- Svg Sprite
- Datos de simulación con Mock
- Pantalla completa
- Menu lateral responsivo
- Editor
- Editor de Texto Enriquecido
- Editor Markdown
- Editor JSON
- Excel
- Exportación a Excel
- Carga de Excel
- Visualización de Excel
- Exportación como ZIP
- Tabla
- Tabla Dinámica
- Tabla con Arrastrar y Soltar
- Tabla de edición en línea
- Páginas de Error
- 401
- 404
- Componentes
- Carga de Avatar
- Botón para subir al inicio
- Arrastrar y Soltar (Diaglogo)
- Arrastrar y Soltar (Seleccionar)
- Arrastrar y Soltar (Kanban)
- Arrastrar y Soltar (Lista)
- Panel de división
- Componente para soltar archivos
- Adhesión de objetos
- Contador hasta
- Ejemplo Avanzado
- Registro de Errores
- Tablero de indicadores
- Página de Guías
- ECharts (Gráficos)
- Portapapeles
- Convertidor de Markdown a HTML
```
## Iniciando
```bash
# clone el proyecto
git clone https://github.com/PanJiaChen/vue-element-admin.git
# vaya al directorio clonado
cd vue-element-admin
# instale las dependencias
npm install
# corra el proyecto como desarrollador
npm run dev
```
Automáticamente se abrirá el siguiente enlace en su navegador http://localhost:9527
## Construcción
```bash
# Construcción para entornos de prueba
npm run build:stage
# Construcción para entornos de producción
npm run build:prod
```
## Avanzado
```bash
# Vista previa con efectos de entorno
npm run preview
# Vista previa con efectos + análisis de recursos estáticos
npm run preview -- --report
# Chequeo de formato de código
npm run lint
# Chequeo de formato de código y auto-corrección
npm run lint -- --fix
```
Vaya a [Documentación](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) para mayor información
## Registro de Cambios
Los cambios detallados por cada liberación se encuentran en [notas de liberación](https://github.com/PanJiaChen/vue-element-admin/releases).
## Demostración en línea
[Vista Prévia de la Aplicación](https://panjiachen.github.io/vue-element-admin)
## Donación
Si este proyecto es de mucha ayuda para ti, puedes comprarle al autor un vaso de jugo :tropical_drink:
![Donar](https://wpimg.wallstcn.com/bd273f0d-83a0-4ef2-92e1-9ac8ed3746b9.png)
[dona por Paypal](https://www.paypal.me/panfree23)
[Comprame un Café](https://www.buymeacoffee.com/Pan)
## Navegadores Soportados
Navegadores modernos e Internet Explorer 10+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
| --------- | --------- | --------- | --------- |
| IE10, IE11, Edge | últimas 2 versiones | últimas 2 versiones | últimas 2 versiones |
## Licencia
[MIT](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
Copyright (c) 2017-presente PanJiaChen

View File

@ -26,11 +26,11 @@
</a>
</p>
日本語 | [English](./README.md) | [简体中文](./README.zh-CN.md)
日本語 | [English](./README.md) | [简体中文](./README.zh-CN.md) | [Spanish](./README.es.md)
## 概要
[vue-element-admin](https://panjiachen.github.io/vue-element-admin) は管理画面のフロントエンドのインタフェース[vue](https://github.com/vuejs/vue) と [element-ui](https://github.com/ElemeFE/element)を使っています。i18nの多言語対応、可変ルート、権限、典型的なビジネスアプリテンプレートであり、豊富なコンポーネントを提供しています素早くビジネス用の管理画面の現型を構築に役立ちます。
[vue-element-admin](https://panjiachen.github.io/vue-element-admin) は管理画面のフロントエンドのインタフェースで、[vue](https://github.com/vuejs/vue) と [element-ui](https://github.com/ElemeFE/element)を使っています。i18nの多言語対応、可変ルート、権限、典型的なビジネスアプリテンプレートであり、豊富なコンポーネントを提供しています素早くビジネス用の管理画面の現型を構築に役立ちます。
- [デモページ](https://panjiachen.github.io/vue-element-admin)
@ -44,21 +44,24 @@
- おすすめシンプルテンプレート: [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))
- Typescriptバージョン: [vue-typescript-admin-template](https://github.com/Armour/vue-typescript-admin-template) (感謝: [@Armour](https://github.com/Armour))
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
**After the `v4.1.0+` version, the default master branch will not support i18n. Please use [i18n Branch](https://github.com/PanJiaChen/vue-element-admin/tree/i18n), it will keep up with the master update**
**バージョン`v4.1.0+`以降について、デフォルトのmasterブランチではi18nをサポートしていません。masterブランチと共にアップデートされる[i18n Branch](https://github.com/PanJiaChen/vue-element-admin/tree/i18n)を使用してください。 **
**現在のバージョン `v4.0+``vue-cli` で構築バグ報告は[issue](https://github.com/PanJiaChen/vue-element-admin/issues/new)のissueでお願いします。旧バージョン[tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0)もあります。`vue-cli`に依存しないです。**
**現在のバージョン `v4.0+``vue-cli` で構築していて、バグ報告は[issue](https://github.com/PanJiaChen/vue-element-admin/issues/new)のissueでお願いします。旧バージョン[tag/3.11.0](https://github.com/PanJiaChen/vue-element-admin/tree/tag/3.11.0)もあります。こちらは`vue-cli`に依存しないです。**
**低いバージョンのブラウザはサーポートしないです(例えば 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/) 、[vue-cli](https://github.com/vuejs/vue-cli) 、[axios](https://github.com/axios/axios) [element-ui](https://github.com/ElemeFE/element)で開発しています。Requestは[Mock.js](https://github.com/nuysoft/Mock)のモックデータを使っています。
ローカル環境に [node](http://nodejs.org/) と [git](https://git-scm.com/)インストールが必要です。[ES2015+](http://es6.ruanyifeng.com/)、[vue](https://cn.vuejs.org/index.html)、[vuex](https://vuex.vuejs.org/zh-cn/)、[vue-router](https://router.vuejs.org/zh-cn/) 、[vue-cli](https://github.com/vuejs/vue-cli) 、[axios](https://github.com/axios/axios) [element-ui](https://github.com/ElemeFE/element)で開発しています。Requestは[Mock.js](https://github.com/nuysoft/Mock)のモックデータを使っています。
**バグ修正や新規機能追加のissue と pull requestは大歓迎です。**
<p align="center">
[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/PanJiaChen/vue-element-admin/tree/CodeSandbox)
<p align="center">
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
</p>
@ -66,6 +69,12 @@
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
### Akveo
<a href="https://store.akveo.com/products/vue-java-admin-dashboard-spring?utm_campaign=akveo_store-Vue-Vue_demo%2Fgithub&utm_source=vue_admin&utm_medium=referral&utm_content=github_banner"><img width="500px" src="https://raw.githubusercontent.com/PanJiaChen/vue-element-admin-site/master/docs/.vuepress/public/images/vue-java-banner.png" /></a><p>Get Java backend for Vue admin with 20% discount for 39$ use coupon code SWB0RAZPZR1M
</p>
### Flatlogic
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
## 機能一覧
@ -80,15 +89,18 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
- 外部IDでログイン
- 複数環境デプロイ
- dev sit stage prod
- dev
- sit
- stage
- prod
- 共通機能
- 多言語切替
- テーマ切替
- サイトメニュー(ルートから生成)
- Breadcrumb Navigation
- Tag Navigation
- Svg Sprite Icon
- パンくずリストナビゲーション
- タブナビゲーション
- Svg Sprite アイコン
- ローカル/バックエンド モック データ
- Screenfull
@ -103,33 +115,33 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
- リード
- Zip
- Table
- Dynamic Table
- Drag And Drop Table
- Inline Edit Table
- テーブル
- ダイナミックテーブル
- ドラッグアンドドロップテーブル
- インラインエディットテーブル
- Error Page
- エラーページ
- 401
- 404
- コンポーネント
- Avatar Upload
- Back To Top
- Drag Dialog
- Drag Select
- Drag Kanban
- Drag List
- SplitPane
- アバターアップロード
- トップに戻る
- ドラッグダイアログ
- ドラッグ選択
- ドラッグKanban
- ドラッグリスト
- ペインの分割
- Dropzone
- Sticky
- スティッキー
- CountTo
- Advanced Example
- Error Log
- Dashboard
- Guide Page
- 高度なサンプル
- エラーログ
- ダッシュボード
- ガイドページ
- ECharts
- Clipboard
- クリップボード
- Markdown to html
```
@ -149,7 +161,7 @@ npm install
npm run dev
```
This will automatically open http://localhost:9527
http://localhost:9527 が自動的に開きます。
## Build
@ -177,11 +189,11 @@ npm run lint
npm run lint -- --fix
```
Refer to [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) for more information
詳細は [Documentation](https://panjiachen.github.io/vue-element-admin-site/guide/essentials/deploy.html) を参照してください。
## Changelog
Detailed changes for each release are documented in the [release notes](https://github.com/PanJiaChen/vue-element-admin/releases).
各リリースの詳細は [release notes](https://github.com/PanJiaChen/vue-element-admin/releases) にあります。
## Online Demo
@ -203,7 +215,7 @@ Modern browsers and Internet Explorer 10+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
| --------- | --------- | --------- | --------- |
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
| IE10, IE11, Edge | last 2 versions | last 2 versions | last 2 versions |
## License

View File

@ -26,13 +26,28 @@
</a>
</p>
English | [简体中文](./README.zh-CN.md) | [日本語](./README.ja.md)
English | [简体中文](./README.zh-CN.md) | [日本語](./README.ja.md) | [Spanish](./README.es.md)
<!-- <p align="center">
<b>SPONSORED BY</b>
</p>
<table align="center" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td align="center" valign="middle">
<a href="" title="" target="_blank" style="padding-right: 20px;">
<img height="200px" style="padding-right: 20px;" src="" title="variantForm">
</a>
</td>
</tr>
</tbody>
</table>-->
## Introduction
[vue-element-admin](https://panjiachen.github.io/vue-element-admin) is a production-ready front-end solution for admin interfaces. It based on [vue](https://github.com/vuejs/vue) and use the UI Toolkit [element-ui](https://github.com/ElemeFE/element).
[vue-element-admin](https://panjiachen.github.io/vue-element-admin) is a production-ready front-end solution for admin interfaces. It is based on [vue](https://github.com/vuejs/vue) and uses the UI Toolkit [element-ui](https://github.com/ElemeFE/element).
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.
[vue-element-admin](https://panjiachen.github.io/vue-element-admin) is based on the newest development stack of vue and it has a built-in i18n solution, typical templates for enterprise applications, and lots of awesome features. It helps you build large and complex Single-Page Applications. I believe whatever your needs are, this project will help you.
- [Preview](https://panjiachen.github.io/vue-element-admin)
@ -49,6 +64,7 @@ It is a magical vue admin based on the newest development stack of vue, built-in
- 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))
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
**After the `v4.1.0+` version, the default master branch will not support i18n. Please use [i18n Branch](https://github.com/PanJiaChen/vue-element-admin/tree/i18n), it will keep up with the master update**
@ -61,7 +77,9 @@ It is a magical vue admin based on the newest development stack of vue, built-in
You need to install [node](https://nodejs.org/) and [git](https://git-scm.com/) locally. The project is based on [ES2015+](https://es6.ruanyifeng.com/), [vue](https://cn.vuejs.org/index.html), [vuex](https://vuex.vuejs.org/zh-cn/), [vue-router](https://router.vuejs.org/zh-cn/), [vue-cli](https://github.com/vuejs/vue-cli) , [axios](https://github.com/axios/axios) and [element-ui](https://github.com/ElemeFE/element), all request data is simulated using [Mock.js](https://github.com/nuysoft/Mock).
Understanding and learning this knowledge in advance will greatly help the use of this project.
<p align="center">
[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/PanJiaChen/vue-element-admin/tree/CodeSandbox)
<p align="center">
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
</p>
@ -69,6 +87,12 @@ Understanding and learning this knowledge in advance will greatly help the use o
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
### Akveo
<a href="https://store.akveo.com/products/vue-java-admin-dashboard-spring?utm_campaign=akveo_store-Vue-Vue_demo%2Fgithub&utm_source=vue_admin&utm_medium=referral&utm_content=github_banner"><img width="500px" src="https://raw.githubusercontent.com/PanJiaChen/vue-element-admin-site/master/docs/.vuepress/public/images/vue-java-banner.png" /></a><p>Get Java backend for Vue admin with 20% discount for 39$ use coupon code SWB0RAZPZR1M
</p>
### Flatlogic
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
## Features
@ -83,7 +107,10 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
- Two-step login
- Multi-environment build
- dev sit stage prod
- Develop (dev)
- sit
- Stage Test (stage)
- Production (prod)
- Global Features
- I18n
@ -207,7 +234,7 @@ Modern browsers and Internet Explorer 10+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
| --------- | --------- | --------- | --------- |
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
| IE10, IE11, Edge | last 2 versions | last 2 versions | last 2 versions |
## License

View File

@ -26,7 +26,22 @@
</a>
</p>
简体中文 | [English](./README.md)
简体中文 | [English](./README.md) | [日本語](./README.ja.md) | [Spanish](./README.es.md)
<!-- <p align="center">
<b>SPONSORED BY</b>
</p>
<table align="center" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td align="center" valign="middle">
<a href="" title="" target="_blank" style="padding-right: 20px;">
<img height="200px" style="padding-right: 20px;" src="" title="variantForm">
</a>
</td>
</tr>
</tbody>
</table>-->
## 简介
@ -49,6 +64,7 @@
- 基础模板建议使用: [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))
- [awesome-project](https://github.com/PanJiaChen/vue-element-admin/issues/2312)
**`v4.1.0+`版本之后默认 master 分支将不支持国际化,有需要的请使用[i18n](https://github.com/PanJiaChen/vue-element-admin/tree/i18n)分支,它会和 master 保持同步更新**
@ -68,6 +84,7 @@
- [手摸手,带你用 vue 撸后台 系列二(登录权限篇)](https://juejin.im/post/591aa14f570c35006961acac)
- [手摸手,带你用 vue 撸后台 系列三 (实战篇)](https://juejin.im/post/593121aa0ce4630057f70d35)
- [手摸手,带你用 vue 撸后台 系列四(vueAdmin 一个极简的后台基础模板)](https://juejin.im/post/595b4d776fb9a06bbe7dba56)
- [手摸手带你用vue撸后台 系列五(v4.0新版本)](https://juejin.im/post/5c92ff94f265da6128275a85)
- [手摸手,带你封装一个 vue component](https://segmentfault.com/a/1190000009090836)
- [手摸手,带你优雅的使用 icon](https://juejin.im/post/59bb864b5188257e7a427c09)
- [手摸手,带你用合理的姿势使用 webpack4](https://juejin.im/post/5b56909a518825195f499806)
@ -75,7 +92,9 @@
**如有问题请先看上述使用文档和文章,若不能满足,欢迎 issue 和 pr**
<p align="center">
[![Edit on CodeSandbox](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/github/PanJiaChen/vue-element-admin/tree/CodeSandbox)
<p align="center">
<img width="900" src="https://wpimg.wallstcn.com/a5894c1b-f6af-456e-82df-1151da0839bf.png">
</p>
@ -83,8 +102,14 @@
Become a sponsor and get your logo on our README on GitHub with a link to your site. [[Become a sponsor]](https://www.patreon.com/panjiachen)
### Akveo
<a href="https://store.akveo.com/products/vue-java-admin-dashboard-spring?utm_campaign=akveo_store-Vue-Vue_demo%2Fgithub&utm_source=vue_admin&utm_medium=referral&utm_content=github_banner"><img width="500px" src="https://raw.githubusercontent.com/PanJiaChen/vue-element-admin-site/master/docs/.vuepress/public/images/vue-java-banner.png" /></a><p>Java 后端整合可以使用优惠码SWB0RAZPZR1M获得20%的价格优化</p>
### Flatlogic
<a href="https://flatlogic.com/admin-dashboards?from=vue-element-admin"><img width="150px" src="https://wpimg.wallstcn.com/9c0b719b-5551-4c1e-b776-63994632d94a.png" /></a><p>Admin Dashboard Templates made with Vue, React and Angular.</p>
## 功能
```
@ -97,7 +122,10 @@ Become a sponsor and get your logo on our README on GitHub with a link to your s
- 二步登录
- 多环境发布
- dev sit stage prod
- dev
- sit
- stage
- prod
- 全局功能
- 国际化多语言
@ -163,7 +191,7 @@ cd vue-element-admin
# 安装依赖
npm install
# 建议不要直接使用 cnpm 安装以来,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
npm install --registry=https://registry.npm.taobao.org
# 启动服务
@ -219,13 +247,17 @@ Detailed changes for each release are documented in the [release notes](https://
[Buy me a coffee](https://www.buymeacoffee.com/Pan)
## 购买贴纸
你也可以通过 购买[官方授权的贴纸](https://smallsticker.com/product/vue-element-admin) 的方式来支持 vue-element-admin - 每售出一张贴纸,本项目将获得 2 元的捐赠。
## Browsers support
Modern browsers and Internet Explorer 10+.
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](https://godban.github.io/browsers-support-badges/)</br>Safari |
| --------- | --------- | --------- | --------- |
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions
| IE10, IE11, Edge | last 2 versions | last 2 versions | last 2 versions |
## License

View File

@ -1,5 +1,14 @@
module.exports = {
presets: [
'@vue/app'
]
// https://github.com/vuejs/vue-cli/tree/master/packages/@vue/babel-preset-app
'@vue/cli-plugin-babel/preset'
],
'env': {
'development': {
// babel-plugin-dynamic-import-node plugin only does one thing by converting all import() to require().
// This plugin can significantly increase the speed of hot updates, when you have a large number of pages.
// https://panjiachen.github.io/vue-element-admin-site/guide/advanced/lazy-loading.html
'plugins': ['dynamic-import-node']
}
}
}

9
jsconfig.json Normal file
View File

@ -0,0 +1,9 @@
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
},
"exclude": ["node_modules", "dist"]
}

View File

@ -1,4 +1,4 @@
import Mock from 'mockjs'
const Mock = require('mockjs')
const List = []
const count = 100
@ -18,7 +18,7 @@ for (let i = 0; i < count; i++) {
forecast: '@float(0, 100, 2, 2)',
importance: '@integer(1, 3)',
'type|1': ['CN', 'US', 'JP', 'EU'],
'status|1': ['published', 'draft', 'deleted'],
'status|1': ['published', 'draft'],
display_time: '@datetime',
comment_disabled: true,
pageviews: '@integer(300, 5000)',
@ -27,9 +27,9 @@ for (let i = 0; i < count; i++) {
}))
}
export default [
module.exports = [
{
url: '/article/list',
url: '/vue-element-admin/article/list',
type: 'get',
response: config => {
const { importance, type, title, page = 1, limit = 20, sort } = config.query
@ -58,7 +58,7 @@ export default [
},
{
url: '/article/detail',
url: '/vue-element-admin/article/detail',
type: 'get',
response: config => {
const { id } = config.query
@ -74,7 +74,7 @@ export default [
},
{
url: '/article/pv',
url: '/vue-element-admin/article/pv',
type: 'get',
response: _ => {
return {
@ -92,7 +92,7 @@ export default [
},
{
url: '/article/create',
url: '/vue-element-admin/article/create',
type: 'post',
response: _ => {
return {
@ -103,7 +103,7 @@ export default [
},
{
url: '/article/update',
url: '/vue-element-admin/article/update',
type: 'post',
response: _ => {
return {

View File

@ -1,10 +1,10 @@
import Mock from 'mockjs'
import { param2Obj } from '../src/utils'
const Mock = require('mockjs')
const { param2Obj } = require('./utils')
import user from './user'
import role from './role'
import article from './article'
import search from './remote-search'
const user = require('./user')
const role = require('./role')
const article = require('./article')
const search = require('./remote-search')
const mocks = [
...user,
@ -16,7 +16,7 @@ const mocks = [
// for front mock
// please use it cautiously, it will redefine XMLHttpRequest,
// which will cause many of your third-party libraries to be invalidated(like progress event).
export function mockXHR() {
function mockXHR() {
// mock patch
// https://github.com/nuysoft/Mock/issues/300
Mock.XHR.prototype.proxy_send = Mock.XHR.prototype.send
@ -54,17 +54,7 @@ export function mockXHR() {
}
}
// for mock server
const responseFake = (url, type, respond) => {
return {
url: new RegExp(`/mock${url}`),
type: type || 'get',
response(req, res) {
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
}
}
module.exports = {
mocks,
mockXHR
}
export default mocks.map(route => {
return responseFake(route.url, route.type, route.response)
})

View File

@ -2,17 +2,21 @@ const chokidar = require('chokidar')
const bodyParser = require('body-parser')
const chalk = require('chalk')
const path = require('path')
const Mock = require('mockjs')
const mockDir = path.join(process.cwd(), 'mock')
function registerRoutes(app) {
let mockLastIndex
const { default: mocks } = require('./index.js')
for (const mock of mocks) {
const { mocks } = require('./index.js')
const mocksForServer = mocks.map(route => {
return responseFake(route.url, route.type, route.response)
})
for (const mock of mocksForServer) {
app[mock.type](mock.url, mock.response)
mockLastIndex = app._router.stack.length
}
const mockRoutesLength = Object.keys(mocks).length
const mockRoutesLength = Object.keys(mocksForServer).length
return {
mockRoutesLength: mockRoutesLength,
mockStartIndex: mockLastIndex - mockRoutesLength
@ -27,10 +31,19 @@ function unregisterRoutes() {
})
}
module.exports = app => {
// es6 polyfill
require('@babel/register')
// for mock server
const responseFake = (url, type, respond) => {
return {
url: new RegExp(`${process.env.VUE_APP_BASE_API}${url}`),
type: type || 'get',
response(req, res) {
console.log('request invoke:' + req.path)
res.json(Mock.mock(respond instanceof Function ? respond(req, res) : respond))
}
}
}
module.exports = app => {
// parse app.body
// https://expressjs.com/en/4x/api.html#req.body
app.use(bodyParser.json())

View File

@ -1,4 +1,4 @@
import Mock from 'mockjs'
const Mock = require('mockjs')
const NameList = []
const count = 100
@ -10,10 +10,10 @@ for (let i = 0; i < count; i++) {
}
NameList.push({ name: 'mock-Pan' })
export default [
module.exports = [
// username search
{
url: '/search/user',
url: '/vue-element-admin/search/user',
type: 'get',
response: config => {
const { name } = config.query
@ -30,7 +30,7 @@ export default [
// transaction list
{
url: '/transaction/list',
url: '/vue-element-admin/transaction/list',
type: 'get',
response: _ => {
return {

View File

@ -1,6 +1,6 @@
import Mock from 'mockjs'
import { deepClone } from '../../src/utils/index.js'
import { asyncRoutes, constantRoutes } from './routes.js'
const Mock = require('mockjs')
const { deepClone } = require('../utils')
const { asyncRoutes, constantRoutes } = require('./routes.js')
const routes = deepClone([...constantRoutes, ...asyncRoutes])
@ -35,10 +35,10 @@ const roles = [
}
]
export default [
module.exports = [
// mock get all routes form server
{
url: '/routes',
url: '/vue-element-admin/routes',
type: 'get',
response: _ => {
return {
@ -50,7 +50,7 @@ export default [
// mock get all roles form server
{
url: '/roles',
url: '/vue-element-admin/roles',
type: 'get',
response: _ => {
return {
@ -62,7 +62,7 @@ export default [
// add role
{
url: '/role',
url: '/vue-element-admin/role',
type: 'post',
response: {
code: 20000,
@ -74,7 +74,7 @@ export default [
// update role
{
url: '/role/[A-Za-z0-9]',
url: '/vue-element-admin/role/[A-Za-z0-9]',
type: 'put',
response: {
code: 20000,
@ -86,7 +86,7 @@ export default [
// delete role
{
url: '/role/[A-Za-z0-9]',
url: '/vue-element-admin/role/[A-Za-z0-9]',
type: 'delete',
response: {
code: 20000,

View File

@ -1,6 +1,6 @@
// Just a mock data
export const constantRoutes = [
const constantRoutes = [
{
path: '/redirect',
component: 'layout/Layout',
@ -72,7 +72,7 @@ export const constantRoutes = [
}
]
export const asyncRoutes = [
const asyncRoutes = [
{
path: '/permission',
component: 'layout/Layout',
@ -523,3 +523,8 @@ export const asyncRoutes = [
{ path: '*', redirect: '/404', hidden: true }
]
module.exports = {
constantRoutes,
asyncRoutes
}

View File

@ -23,10 +23,10 @@ const users = {
}
}
export default [
module.exports = [
// user login
{
url: '/user/login',
url: '/vue-element-admin/user/login',
type: 'post',
response: config => {
const { username } = config.body
@ -49,7 +49,7 @@ export default [
// get user info
{
url: '/user/info\.*',
url: '/vue-element-admin/user/info\.*',
type: 'get',
response: config => {
const { token } = config.query
@ -72,7 +72,7 @@ export default [
// user logout
{
url: '/user/logout',
url: '/vue-element-admin/user/logout',
type: 'post',
response: _ => {
return {

48
mock/utils.js Normal file
View File

@ -0,0 +1,48 @@
/**
* @param {string} url
* @returns {Object}
*/
function param2Obj(url) {
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
if (!search) {
return {}
}
const obj = {}
const searchArr = search.split('&')
searchArr.forEach(v => {
const index = v.indexOf('=')
if (index !== -1) {
const name = v.substring(0, index)
const val = v.substring(index + 1, v.length)
obj[name] = val
}
})
return obj
}
/**
* This is just a simple version of deep copy
* Has a lot of edge cases bug
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
* @param {Object} source
* @returns {Object}
*/
function deepClone(source) {
if (!source && typeof source !== 'object') {
throw new Error('error arguments', 'deepClone')
}
const targetObj = source.constructor === Array ? [] : {}
Object.keys(source).forEach(keys => {
if (source[keys] && typeof source[keys] === 'object') {
targetObj[keys] = deepClone(source[keys])
} else {
targetObj[keys] = source[keys]
}
})
return targetObj
}
module.exports = {
param2Obj,
deepClone
}

View File

@ -1,55 +1,28 @@
{
"name": "vue-element-admin",
"version": "4.1.0",
"version": "4.4.0",
"description": "A magical vue admin. An out-of-box UI solution for enterprise applications. Newest development stack of vue. Lots of awesome features",
"author": "Pan <panfree23@gmail.com>",
"license": "MIT",
"scripts": {
"dev": "vue-cli-service serve",
"lint": "eslint --ext .js,.vue src",
"build:prod": "vue-cli-service build",
"build:stage": "vue-cli-service build --mode staging",
"preview": "node build/index.js --preview",
"lint": "eslint --ext .js,.vue src",
"test:unit": "jest --clearCache && vue-cli-service test:unit",
"test:ci": "npm run lint && npm run test:unit",
"new": "plop",
"svgo": "svgo -f src/icons/svg --config=src/icons/svgo.yml",
"new": "plop"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
},
"keywords": [
"vue",
"admin",
"dashboard",
"element-ui",
"boilerplate",
"admin-template",
"management-system"
],
"repository": {
"type": "git",
"url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
},
"bugs": {
"url": "https://github.com/PanJiaChen/vue-element-admin/issues"
"test:unit": "jest --clearCache && vue-cli-service test:unit",
"test:ci": "npm run lint && npm run test:unit"
},
"dependencies": {
"axios": "0.18.0",
"axios": "0.18.1",
"clipboard": "2.0.4",
"codemirror": "5.45.0",
"core-js": "3.6.5",
"driver.js": "0.9.5",
"dropzone": "5.5.1",
"echarts": "4.2.1",
"element-ui": "2.7.0",
"element-ui": "2.13.2",
"file-saver": "2.0.1",
"fuse.js": "3.4.4",
"js-cookie": "2.2.0",
@ -59,7 +32,7 @@
"nprogress": "0.2.0",
"path-to-regexp": "2.4.0",
"screenfull": "4.2.0",
"showdown": "1.9.0",
"script-loader": "0.7.2",
"sortablejs": "1.8.4",
"tui-editor": "1.3.3",
"vue": "2.6.10",
@ -71,43 +44,68 @@
"xlsx": "0.14.1"
},
"devDependencies": {
"@babel/core": "7.0.0",
"@babel/register": "7.0.0",
"@vue/cli-plugin-babel": "3.5.3",
"@vue/cli-plugin-eslint": "3.5.1",
"@vue/cli-plugin-unit-jest": "3.5.3",
"@vue/cli-service": "3.5.3",
"@vue/cli-plugin-babel": "4.4.4",
"@vue/cli-plugin-eslint": "4.4.4",
"@vue/cli-plugin-unit-jest": "4.4.4",
"@vue/cli-service": "4.4.4",
"@vue/test-utils": "1.0.0-beta.29",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "10.0.1",
"autoprefixer": "9.5.1",
"babel-eslint": "10.1.0",
"babel-jest": "23.6.0",
"babel-plugin-dynamic-import-node": "2.3.3",
"chalk": "2.4.2",
"chokidar": "2.1.5",
"connect": "3.6.6",
"eslint": "5.15.3",
"eslint-plugin-vue": "5.2.2",
"eslint": "6.7.2",
"eslint-plugin-vue": "6.2.2",
"html-webpack-plugin": "3.2.0",
"husky": "1.3.1",
"lint-staged": "8.1.5",
"mockjs": "1.0.1-beta3",
"node-sass": "^4.9.0",
"plop": "2.3.0",
"runjs": "^4.3.2",
"sass-loader": "^7.1.0",
"runjs": "4.3.2",
"sass": "1.26.2",
"sass-loader": "8.0.2",
"script-ext-html-webpack-plugin": "2.1.3",
"script-loader": "0.7.2",
"serve-static": "^1.13.2",
"serve-static": "1.13.2",
"svg-sprite-loader": "4.1.3",
"svgo": "1.2.0",
"vue-template-compiler": "2.6.10"
},
"browserslist": [
"> 1%",
"last 2 versions"
],
"bugs": {
"url": "https://github.com/PanJiaChen/vue-element-admin/issues"
},
"engines": {
"node": ">=8.9",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
"keywords": [
"vue",
"admin",
"dashboard",
"element-ui",
"boilerplate",
"admin-template",
"management-system"
],
"license": "MIT",
"lint-staged": {
"src/**/*.{js,vue}": [
"eslint --fix",
"git add"
]
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"repository": {
"type": "git",
"url": "git+https://github.com/PanJiaChen/vue-element-admin.git"
}
}

View File

@ -0,0 +1,16 @@
{{#if state}}
const state = {}
{{/if}}
{{#if mutations}}
const mutations = {}
{{/if}}
{{#if actions}}
const actions = {}
{{/if}}
export default {
namespaced: true,
{{options}}
}

View File

@ -0,0 +1,62 @@
const { notEmpty } = require('../utils.js')
module.exports = {
description: 'generate store',
prompts: [{
type: 'input',
name: 'name',
message: 'store name please',
validate: notEmpty('name')
},
{
type: 'checkbox',
name: 'blocks',
message: 'Blocks:',
choices: [{
name: 'state',
value: 'state',
checked: true
},
{
name: 'mutations',
value: 'mutations',
checked: true
},
{
name: 'actions',
value: 'actions',
checked: true
}
],
validate(value) {
if (!value.includes('state') || !value.includes('mutations')) {
return 'store require at least state and mutations'
}
return true
}
}
],
actions(data) {
const name = '{{name}}'
const { blocks } = data
const options = ['state', 'mutations']
const joinFlag = `,
`
if (blocks.length === 3) {
options.push('actions')
}
const actions = [{
type: 'add',
path: `src/store/modules/${name}.js`,
templateFile: 'plop-templates/store/index.hbs',
data: {
options: options.join(joinFlag),
state: blocks.includes('state'),
mutations: blocks.includes('mutations'),
actions: blocks.includes('actions')
}
}]
return actions
}
}

View File

@ -1,9 +1,2 @@
exports.notEmpty = name => {
return v => {
if (!v || v.trim === '') {
return `${name} is required`
} else {
return true
}
}
}
exports.notEmpty = name => v =>
!v || v.trim() === '' ? `${name} is required` : true

View File

@ -1,7 +1,9 @@
const viewGenerator = require('./plop-templates/view/prompt')
const componentGenerator = require('./plop-templates/component/prompt')
const storeGenerator = require('./plop-templates/store/prompt.js')
module.exports = function(plop) {
plop.setGenerator('view', viewGenerator)
plop.setGenerator('component', componentGenerator)
plop.setGenerator('store', storeGenerator)
}

5
postcss.config.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {}
}
}

View File

@ -9,10 +9,6 @@
<title><%= webpackConfig.name %></title>
</head>
<body>
<!-- import cdn js -->
<% for(var js of htmlWebpackPlugin.options.cdn.js) { %>
<script src="<%=js%>"></script>
<% } %>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>

View File

@ -2,7 +2,7 @@ import request from '@/utils/request'
export function fetchList(query) {
return request({
url: '/article/list',
url: '/vue-element-admin/article/list',
method: 'get',
params: query
})
@ -10,7 +10,7 @@ export function fetchList(query) {
export function fetchArticle(id) {
return request({
url: '/article/detail',
url: '/vue-element-admin/article/detail',
method: 'get',
params: { id }
})
@ -18,7 +18,7 @@ export function fetchArticle(id) {
export function fetchPv(pv) {
return request({
url: '/article/pv',
url: '/vue-element-admin/article/pv',
method: 'get',
params: { pv }
})
@ -26,7 +26,7 @@ export function fetchPv(pv) {
export function createArticle(data) {
return request({
url: '/article/create',
url: '/vue-element-admin/article/create',
method: 'post',
data
})
@ -34,7 +34,7 @@ export function createArticle(data) {
export function updateArticle(data) {
return request({
url: '/article/update',
url: '/vue-element-admin/article/update',
method: 'post',
data
})

View File

@ -2,7 +2,7 @@ import request from '@/utils/request'
export function searchUser(name) {
return request({
url: '/search/user',
url: '/vue-element-admin/search/user',
method: 'get',
params: { name }
})
@ -10,7 +10,7 @@ export function searchUser(name) {
export function transactionList(query) {
return request({
url: '/transaction/list',
url: '/vue-element-admin/transaction/list',
method: 'get',
params: query
})

View File

@ -2,21 +2,21 @@ import request from '@/utils/request'
export function getRoutes() {
return request({
url: '/routes',
url: '/vue-element-admin/routes',
method: 'get'
})
}
export function getRoles() {
return request({
url: '/roles',
url: '/vue-element-admin/roles',
method: 'get'
})
}
export function addRole(data) {
return request({
url: '/role',
url: '/vue-element-admin/role',
method: 'post',
data
})
@ -24,7 +24,7 @@ export function addRole(data) {
export function updateRole(id, data) {
return request({
url: `/role/${id}`,
url: `/vue-element-admin/role/${id}`,
method: 'put',
data
})
@ -32,7 +32,7 @@ export function updateRole(id, data) {
export function deleteRole(id) {
return request({
url: `/role/${id}`,
url: `/vue-element-admin/role/${id}`,
method: 'delete'
})
}

View File

@ -2,7 +2,7 @@ import request from '@/utils/request'
export function login(data) {
return request({
url: '/user/login',
url: '/vue-element-admin/user/login',
method: 'post',
data
})
@ -10,7 +10,7 @@ export function login(data) {
export function getInfo(token) {
return request({
url: '/user/info',
url: '/vue-element-admin/user/info',
method: 'get',
params: { token }
})
@ -18,7 +18,7 @@ export function getInfo(token) {
export function logout() {
return request({
url: '/user/logout',
url: '/vue-element-admin/user/logout',
method: 'post'
})
}

View File

@ -19,7 +19,11 @@ export default {
}
},
watch: {
$route() {
$route(route) {
// if you go to the redirect page, do not update the breadcrumbs
if (route.path.startsWith('/redirect/')) {
return
}
this.getBreadcrumb()
}
},

View File

@ -3,32 +3,54 @@ import { debounce } from '@/utils'
export default {
data() {
return {
$_sidebarElm: null
$_sidebarElm: null,
$_resizeHandler: null
}
},
mounted() {
this.__resizeHandler = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHandler)
this.initListener()
},
activated() {
if (!this.$_resizeHandler) {
// avoid duplication init
this.initListener()
}
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
// when keep-alive chart activated, auto resize
this.resize()
},
beforeDestroy() {
window.removeEventListener('resize', this.__resizeHandler)
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
this.destroyListener()
},
deactivated() {
this.destroyListener()
},
methods: {
// use $_ for mixins properties
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
$_sidebarResizeHandler(e) {
if (e.propertyName === 'width') {
this.__resizeHandler()
this.$_resizeHandler()
}
},
initListener() {
this.$_resizeHandler = debounce(() => {
this.resize()
}, 100)
window.addEventListener('resize', this.$_resizeHandler)
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
},
destroyListener() {
window.removeEventListener('resize', this.$_resizeHandler)
this.$_resizeHandler = null
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
},
resize() {
const { chart } = this
chart && chart.resize()
}
}
}

View File

@ -48,14 +48,18 @@ export default {
}
</script>
<style scoped>
.drag-select >>> .sortable-ghost {
opacity: .8;
color: #fff!important;
background: #42b983!important;
}
<style lang="scss" scoped>
.drag-select {
::v-deep {
.sortable-ghost {
opacity: .8;
color: #fff !important;
background: #42b983 !important;
}
.drag-select >>> .el-tag {
cursor: pointer;
.el-tag {
cursor: pointer;
}
}
}
</style>

View File

@ -6,7 +6,11 @@
</el-button>
</el-badge>
<el-dialog :visible.sync="dialogTableVisible" title="Error Log" width="80%" append-to-body>
<el-dialog :visible.sync="dialogTableVisible" width="80%" append-to-body>
<div slot="title">
<span style="padding-right: 10px;">Error Log</span>
<el-button size="mini" type="primary" icon="el-icon-delete" @click="clearAll">Clear All</el-button>
</div>
<el-table :data="errorLogs" border>
<el-table-column label="Message">
<template slot-scope="{row}">
@ -54,6 +58,12 @@ export default {
errorLogs() {
return this.$store.getters.errorLogs
}
},
methods: {
clearAll() {
this.dialogTableVisible = false
this.$store.dispatch('errorLog/clearErrorLog')
}
}
}
</script>

View File

@ -159,7 +159,7 @@ export default {
display: inline-block;
vertical-align: middle;
/deep/ .el-input__inner {
::v-deep .el-input__inner {
border-radius: 0;
border: 0;
padding-left: 0;

File diff suppressed because it is too large Load Diff

View File

@ -54,19 +54,24 @@ export default {
}
</script>
<style scoped>
.json-editor{
<style lang="scss" scoped>
.json-editor {
height: 100%;
position: relative;
}
.json-editor >>> .CodeMirror {
height: auto;
min-height: 300px;
}
.json-editor >>> .CodeMirror-scroll{
min-height: 300px;
}
.json-editor >>> .cm-s-rubyblue span.cm-string {
color: #F08047;
::v-deep {
.CodeMirror {
height: auto;
min-height: 300px;
}
.CodeMirror-scroll {
min-height: 300px;
}
.cm-s-rubyblue span.cm-string {
color: #F08047;
}
}
}
</style>

View File

@ -9,7 +9,7 @@
:placeholder="fillPlaceHolder"
:readonly="readonly"
:disabled="disabled"
:autoComplete="autoComplete"
:autocomplete="autoComplete"
:required="required"
type="email"
class="material-input"
@ -24,7 +24,7 @@
:placeholder="fillPlaceHolder"
:readonly="readonly"
:disabled="disabled"
:autoComplete="autoComplete"
:autocomplete="autoComplete"
:required="required"
type="url"
class="material-input"
@ -40,7 +40,7 @@
:step="step"
:readonly="readonly"
:disabled="disabled"
:autoComplete="autoComplete"
:autocomplete="autoComplete"
:max="max"
:min="min"
:minlength="minlength"
@ -59,7 +59,7 @@
:placeholder="fillPlaceHolder"
:readonly="readonly"
:disabled="disabled"
:autoComplete="autoComplete"
:autocomplete="autoComplete"
:max="max"
:min="min"
:required="required"
@ -76,7 +76,7 @@
:placeholder="fillPlaceHolder"
:readonly="readonly"
:disabled="disabled"
:autoComplete="autoComplete"
:autocomplete="autoComplete"
:required="required"
type="tel"
class="material-input"
@ -91,7 +91,7 @@
:placeholder="fillPlaceHolder"
:readonly="readonly"
:disabled="disabled"
:autoComplete="autoComplete"
:autocomplete="autoComplete"
:minlength="minlength"
:maxlength="maxlength"
:required="required"

View File

@ -12,7 +12,7 @@ import Editor from 'tui-editor'
import defaultOptions from './default-options'
export default {
name: 'MarddownEditor',
name: 'MarkdownEditor',
props: {
value: {
type: String,

View File

@ -5,7 +5,8 @@
<slot />
</div>
</div>
<img :src="image" class="pan-thumb">
<!-- eslint-disable-next-line -->
<div :style="{backgroundImage: `url(${image})`}" class="pan-thumb"></div>
</div>
</template>
@ -52,7 +53,8 @@ export default {
.pan-thumb {
width: 100%;
height: 100%;
background-size: 100%;
background-position: center center;
background-size: cover;
border-radius: 50%;
overflow: hidden;
position: absolute;
@ -60,7 +62,7 @@ export default {
transition: all 0.3s ease-in-out;
}
.pan-thumb:after {
/* .pan-thumb:after {
content: '';
width: 8px;
height: 8px;
@ -71,7 +73,7 @@ export default {
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;

View File

@ -86,32 +86,27 @@ export default {
<style lang="scss" scoped>
.rightPanel-background {
position: fixed;
top: 0;
left: 0;
opacity: 0;
transition: opacity .3s cubic-bezier(.7, .3, .1, 1);
background: rgba(0, 0, 0, .2);
width: 0;
height: 0;
top: 0;
left: 0;
position: fixed;
z-index: -1;
}
.rightPanel {
background: #fff;
z-index: 3000;
position: fixed;
height: 100vh;
width: 100%;
max-width: 260px;
top: 0px;
left: 0px;
height: 100vh;
position: fixed;
top: 0;
right: 0;
box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, .05);
transition: all .25s cubic-bezier(.7, .3, .1, 1);
transform: translate(100%);
background: #fff;
z-index: 40000;
left: auto;
right: 0px;
}
.show {
@ -130,20 +125,18 @@ export default {
}
.handle-button {
position: absolute;
left: -48px;
border-radius: 6px 0 0 6px !important;
width: 48px;
height: 48px;
pointer-events: auto;
z-index: 0;
cursor: pointer;
pointer-events: auto;
font-size: 24px;
position: absolute;
left: -48px;
text-align: center;
font-size: 24px;
border-radius: 6px 0 0 6px !important;
z-index: 0;
pointer-events: auto;
cursor: pointer;
color: #fff;
line-height: 48px;
i {
font-size: 24px;
line-height: 48px;

View File

@ -38,12 +38,13 @@ export default {
</script>
<style lang="scss" >
$n: 8; //items.length
$n: 9; //items.length
$t: .1s;
.share-dropdown-menu {
width: 250px;
position: relative;
z-index: 1;
height: auto!important;
&-title {
width: 100%;
display: block;
@ -65,10 +66,12 @@ $t: .1s;
position: absolute;
width: 100%;
background: #e0e0e0;
color: #000;
line-height: 60px;
height: 60px;
cursor: pointer;
font-size: 20px;
font-size: 18px;
overflow: hidden;
opacity: 1;
transition: transform 0.28s ease;
&:hover {
@ -90,7 +93,7 @@ $t: .1s;
.share-dropdown-menu-item {
@for $i from 1 through $n {
&:nth-of-type(#{$i}) {
transition-delay: ($n - $i)*$t;
transition-delay: ($n - $i)*$t;
transform: translate3d(0, ($i - 1)*60px, 0);
}
}

View File

@ -1,10 +1,14 @@
<template>
<svg :class="svgClass" aria-hidden="true" v-on="$listeners">
<div v-if="isExternal" :style="styleExternalIcon" class="svg-external-icon svg-icon" v-on="$listeners" />
<svg v-else :class="svgClass" aria-hidden="true" v-on="$listeners">
<use :xlink:href="iconName" />
</svg>
</template>
<script>
// doc: https://panjiachen.github.io/vue-element-admin-site/feature/component/svg-icon.html#usage
import { isExternal } from '@/utils/validate'
export default {
name: 'SvgIcon',
props: {
@ -18,6 +22,9 @@ export default {
}
},
computed: {
isExternal() {
return isExternal(this.iconClass)
},
iconName() {
return `#icon-${this.iconClass}`
},
@ -27,6 +34,12 @@ export default {
} else {
return 'svg-icon'
}
},
styleExternalIcon() {
return {
mask: `url(${this.iconClass}) no-repeat 50% 50%`,
'-webkit-mask': `url(${this.iconClass}) no-repeat 50% 50%`
}
}
}
}
@ -40,4 +53,10 @@ export default {
fill: currentColor;
overflow: hidden;
}
.svg-external-icon {
background-color: currentColor;
mask-size: cover!important;
display: inline-block;
}
</style>

View File

@ -104,7 +104,7 @@ export default {
<style lang="scss" scoped>
.editor-slide-upload {
margin-bottom: 20px;
/deep/ .el-upload--picture-card {
::v-deep .el-upload--picture-card {
width: 100%;
}
}

View File

@ -0,0 +1,59 @@
let callbacks = []
function loadedTinymce() {
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2144
// check is successfully downloaded script
return window.tinymce
}
const dynamicLoadScript = (src, callback) => {
const existingScript = document.getElementById(src)
const cb = callback || function() {}
if (!existingScript) {
const script = document.createElement('script')
script.src = src // src url for the third-party library being loaded.
script.id = src
document.body.appendChild(script)
callbacks.push(cb)
const onEnd = 'onload' in script ? stdOnEnd : ieOnEnd
onEnd(script)
}
if (existingScript && cb) {
if (loadedTinymce()) {
cb(null, existingScript)
} else {
callbacks.push(cb)
}
}
function stdOnEnd(script) {
script.onload = function() {
// this.onload = null here is necessary
// because even IE9 works not like others
this.onerror = this.onload = null
for (const cb of callbacks) {
cb(null, script)
}
callbacks = null
}
script.onerror = function() {
this.onerror = this.onload = null
cb(new Error('Failed to load ' + src), script)
}
}
function ieOnEnd(script) {
script.onreadystatechange = function() {
if (this.readyState !== 'complete' && this.readyState !== 'loaded') return
this.onreadystatechange = null
for (const cb of callbacks) {
cb(null, script) // there is no way to catch loading errors in IE8
}
callbacks = null
}
}
}
export default dynamicLoadScript

View File

@ -15,6 +15,10 @@
import editorImage from './components/EditorImage'
import plugins from './plugins'
import toolbar from './toolbar'
import load from './dynamicLoadScript'
// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
const tinymceCDN = 'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js'
export default {
name: 'Tinymce',
@ -60,7 +64,9 @@ export default {
fullscreen: false,
languageTypeList: {
'en': 'en',
'zh': 'zh_CN'
'zh': 'zh_CN',
'es': 'es_MX',
'ja': 'ja'
}
}
},
@ -82,10 +88,12 @@ export default {
}
},
mounted() {
this.initTinymce()
this.init()
},
activated() {
this.initTinymce()
if (window.tinymce) {
this.initTinymce()
}
},
deactivated() {
this.destroyTinymce()
@ -94,10 +102,21 @@ export default {
this.destroyTinymce()
},
methods: {
init() {
// dynamic load tinymce from cdn
load(tinymceCDN, (err) => {
if (err) {
this.$message.error(err.message)
return
}
this.initTinymce()
})
},
initTinymce() {
const _this = this
window.tinymce.init({
selector: `#${this.tinymceId}`,
language: this.languageTypeList['en'],
height: this.height,
body_class: 'panel-body ',
object_resizing: false,
@ -128,7 +147,11 @@ export default {
editor.on('FullscreenStateChanged', (e) => {
_this.fullscreen = e.state
})
}
},
// it will try to keep these URLs intact
// https://www.tiny.cloud/docs-3x/reference/configuration/Configuration3x@convert_urls/
// https://stackoverflow.com/questions/5196205/disable-tinymce-absolute-to-relative-url-conversions
convert_urls: false
//
// images_dataimg_filter(img) {
// setTimeout(() => {
@ -181,37 +204,43 @@ export default {
window.tinymce.get(this.tinymceId).getContent()
},
imageSuccessCBK(arr) {
const _this = this
arr.forEach(v => {
window.tinymce.get(_this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`)
})
arr.forEach(v => window.tinymce.get(this.tinymceId).insertContent(`<img class="wscnph" src="${v.url}" >`))
}
}
}
</script>
<style scoped>
<style lang="scss" scoped>
.tinymce-container {
position: relative;
line-height: normal;
}
.tinymce-container>>>.mce-fullscreen {
z-index: 10000;
.tinymce-container {
::v-deep {
.mce-fullscreen {
z-index: 10000;
}
}
}
.tinymce-textarea {
visibility: hidden;
z-index: -1;
}
.editor-custom-btn-container {
position: absolute;
right: 4px;
top: 4px;
/*z-index: 2005;*/
}
.fullscreen .editor-custom-btn-container {
z-index: 10000;
position: fixed;
}
.editor-upload-btn {
display: inline-block;
}

View File

@ -1,11 +1,11 @@
import store from '@/store'
export default {
inserted(el, binding, vnode) {
const { value } = binding
const roles = store.getters && store.getters.roles
function checkPermission(el, binding) {
const { value } = binding
const roles = store.getters && store.getters.roles
if (value && value instanceof Array && value.length > 0) {
if (value && value instanceof Array) {
if (value.length > 0) {
const permissionRoles = value
const hasPermission = roles.some(role => {
@ -15,8 +15,17 @@ export default {
if (!hasPermission) {
el.parentNode && el.parentNode.removeChild(el)
}
} else {
throw new Error(`need roles! Like v-permission="['admin','editor']"`)
}
} else {
throw new Error(`need roles! Like v-permission="['admin','editor']"`)
}
}
export default {
inserted(el, binding) {
checkPermission(el, binding)
},
update(el, binding) {
checkPermission(el, binding)
}
}

View File

@ -45,7 +45,7 @@ export function numberFormatter(num, digits) {
]
for (let i = 0; i < si.length; i++) {
if (num >= si[i].value) {
return (num / si[i].value + 0.1).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
return (num / si[i].value).toFixed(digits).replace(/\.0+$|(\.[0-9]*[1-9])0+$/, '$1') + si[i].symbol
}
}
return num.toString()

View File

@ -16,7 +16,7 @@ export default {
return this.$store.state.tagsView.cachedViews
},
key() {
return this.$route.fullPath
return this.$route.path
}
}
}
@ -33,8 +33,6 @@ export default {
.fixed-header+.app-main {
padding-top: 50px;
height: 100vh;
overflow: auto;
}
.hasTagsView {
@ -49,3 +47,11 @@ export default {
}
</style>
<style lang="scss">
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
.fixed-header {
padding-right: 15px;
}
}
</style>

View File

@ -36,8 +36,8 @@
<a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
<el-dropdown-item>Docs</el-dropdown-item>
</a>
<el-dropdown-item divided>
<span style="display:block;" @click="logout">Log Out</span>
<el-dropdown-item divided @click.native="logout">
<span style="display:block;">Log Out</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>

View File

@ -17,7 +17,11 @@ export default {
const vnodes = []
if (icon) {
vnodes.push(<svg-icon icon-class={icon}/>)
if (icon.includes('el-icon')) {
vnodes.push(<i class={[icon, 'sub-el-icon']} />)
} else {
vnodes.push(<svg-icon icon-class={icon}/>)
}
}
if (title) {
@ -27,3 +31,11 @@ export default {
}
}
</script>
<style scoped>
.sub-el-icon {
color: currentColor;
width: 1em;
height: 1em;
}
</style>

View File

@ -1,7 +1,5 @@
<template>
<!-- eslint-disable vue/require-component-is -->
<component v-bind="linkProps(to)">
<component :is="type" v-bind="linkProps(to)">
<slot />
</component>
</template>
@ -16,19 +14,28 @@ export default {
required: true
}
},
computed: {
isExternal() {
return isExternal(this.to)
},
type() {
if (this.isExternal) {
return 'a'
}
return 'router-link'
}
},
methods: {
linkProps(url) {
if (isExternal(url)) {
linkProps(to) {
if (this.isExternal) {
return {
is: 'a',
href: url,
href: to,
target: '_blank',
rel: 'noopener'
}
}
return {
is: 'router-link',
to: url
to: to
}
}
}

View File

@ -1,5 +1,5 @@
<template>
<div v-if="!item.hidden" class="menu-wrapper">
<div v-if="!item.hidden">
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<app-link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">

View File

@ -19,12 +19,21 @@ export default {
return this.$refs.scrollContainer.$refs.wrap
}
},
mounted() {
this.scrollWrapper.addEventListener('scroll', this.emitScroll, true)
},
beforeDestroy() {
this.scrollWrapper.removeEventListener('scroll', this.emitScroll)
},
methods: {
handleScroll(e) {
const eventDelta = e.wheelDelta || -e.deltaY * 40
const $scrollWrapper = this.scrollWrapper
$scrollWrapper.scrollLeft = $scrollWrapper.scrollLeft + eventDelta / 4
},
emitScroll() {
this.$emit('scroll')
},
moveToTarget(currentTag) {
const $container = this.$refs.scrollContainer.$el
const $containerWidth = $container.offsetWidth
@ -73,7 +82,7 @@ export default {
position: relative;
overflow: hidden;
width: 100%;
/deep/ {
::v-deep {
.el-scrollbar__bar {
bottom: 0px;
}

View File

@ -1,6 +1,6 @@
<template>
<div id="tags-view-container" class="tags-view-container">
<scroll-pane ref="scrollPane" class="tags-view-wrapper">
<scroll-pane ref="scrollPane" class="tags-view-wrapper" @scroll="handleScroll">
<router-link
v-for="tag in visitedViews"
ref="tag"
@ -9,16 +9,16 @@
:to="{ path: tag.path, query: tag.query, fullPath: tag.fullPath }"
tag="span"
class="tags-view-item"
@click.middle.native="closeSelectedTag(tag)"
@click.middle.native="!isAffix(tag)?closeSelectedTag(tag):''"
@contextmenu.prevent.native="openMenu(tag,$event)"
>
{{ tag.title }}
<span v-if="!tag.meta.affix" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
<span v-if="!isAffix(tag)" class="el-icon-close" @click.prevent.stop="closeSelectedTag(tag)" />
</router-link>
</scroll-pane>
<ul v-show="visible" :style="{left:left+'px',top:top+'px'}" class="contextmenu">
<li @click="refreshSelectedTag(selectedTag)">Refresh</li>
<li v-if="!(selectedTag.meta&&selectedTag.meta.affix)" @click="closeSelectedTag(selectedTag)">Close</li>
<li v-if="!isAffix(selectedTag)" @click="closeSelectedTag(selectedTag)">Close</li>
<li @click="closeOthersTags">Close Others</li>
<li @click="closeAllTags(selectedTag)">Close All</li>
</ul>
@ -69,6 +69,9 @@ export default {
isActive(route) {
return route.path === this.$route.path
},
isAffix(tag) {
return tag.meta && tag.meta.affix
},
filterAffixTags(routes, basePath = '/') {
let tags = []
routes.forEach(route => {
@ -155,7 +158,7 @@ export default {
toLastView(visitedViews, view) {
const latestView = visitedViews.slice(-1)[0]
if (latestView) {
this.$router.push(latestView)
this.$router.push(latestView.fullPath)
} else {
// now the default is to redirect to the home page if there is no tags-view,
// you can adjust it according to your needs.
@ -186,6 +189,9 @@ export default {
},
closeMenu() {
this.visible = false
},
handleScroll() {
this.closeMenu()
}
}
}

View File

@ -6,6 +6,7 @@ import 'normalize.css/normalize.css' // a modern alternative to CSS resets
import Element from 'element-ui'
import './styles/element-variables.scss'
import enLang from 'element-ui/lib/locale/lang/en'// 如果使用中文语言包请默认支持,无需额外引入,请删除该依赖
import '@/styles/index.scss' // global css
@ -21,15 +22,20 @@ import * as filters from './filters' // global filters
/**
* If you don't want to use mock-server
* you want to use mockjs for request interception
* you can execute:
* you want to use MockJs for mock api
* you can execute: mockXHR()
*
* import { mockXHR } from '../mock'
* mockXHR()
* Currently MockJs will be used in the production environment,
* please remove it before going online ! ! !
*/
if (process.env.NODE_ENV === 'production') {
const { mockXHR } = require('../mock')
mockXHR()
}
Vue.use(Element, {
size: Cookies.get('size') || 'medium' // set element-ui default size
size: Cookies.get('size') || 'medium', // set element-ui default size
locale: enLang // 如果使用中文,无需设置,请删除
})
// register global utility filters

View File

@ -24,7 +24,7 @@ router.beforeEach(async(to, from, next) => {
if (to.path === '/login') {
// if is logged in, redirect to the home page
next({ path: '/' })
NProgress.done()
NProgress.done() // hack: https://github.com/PanJiaChen/vue-element-admin/pull/2939
} else {
// determine whether the user has obtained his permission roles through getInfo
const hasRoles = store.getters.roles && store.getters.roles.length > 0

View File

@ -25,7 +25,7 @@ import nestedRouter from './modules/nested'
* meta : {
roles: ['admin','editor'] control the page roles (you can set multiple roles)
title: 'title' the name show in sidebar and breadcrumb (recommend set)
icon: 'svg-name' the icon show in the sidebar
icon: 'svg-name'/'el-icon-x' the icon show in the sidebar
noCache: true if set true, the page will no be cached(default is false)
affix: true if set true, the tag will affix in the tags-view
breadcrumb: false if set false, the item will hidden in breadcrumb(default is true)
@ -45,7 +45,7 @@ export const constantRoutes = [
hidden: true,
children: [
{
path: '/redirect/:path*',
path: '/redirect/:path(.*)',
component: () => import('@/views/redirect/index')
}
]
@ -197,7 +197,7 @@ export const asyncRoutes = [
name: 'Example',
meta: {
title: 'Example',
icon: 'example'
icon: 'el-icon-s-help'
},
children: [
{

View File

@ -5,7 +5,7 @@ import getters from './getters'
Vue.use(Vuex)
// https://webpack.js.org/guides/dependency-management/#requirecontext
const modulesFiles = require.context('./modules', false, /\.js$/)
const modulesFiles = require.context('./modules', true, /\.js$/)
// you do not need `import app from './modules/app'`
// it will auto require all vuex module from modules file

View File

@ -5,12 +5,18 @@ const state = {
const mutations = {
ADD_ERROR_LOG: (state, log) => {
state.logs.push(log)
},
CLEAR_ERROR_LOG: (state) => {
state.logs.splice(0)
}
}
const actions = {
addErrorLog({ commit }, log) {
commit('ADD_ERROR_LOG', log)
},
clearErrorLog({ commit }) {
commit('CLEAR_ERROR_LOG')
}
}

View File

@ -13,6 +13,7 @@ const state = {
const mutations = {
CHANGE_SETTING: (state, { key, value }) => {
// eslint-disable-next-line no-prototype-builtins
if (state.hasOwnProperty(key)) {
state[key] = value
}

View File

@ -28,13 +28,8 @@ const mutations = {
}
},
DEL_CACHED_VIEW: (state, view) => {
for (const i of state.cachedViews) {
if (i === view.name) {
const index = state.cachedViews.indexOf(i)
state.cachedViews.splice(index, 1)
break
}
}
const index = state.cachedViews.indexOf(view.name)
index > -1 && state.cachedViews.splice(index, 1)
},
DEL_OTHERS_VISITED_VIEWS: (state, view) => {
@ -43,12 +38,12 @@ const mutations = {
})
},
DEL_OTHERS_CACHED_VIEWS: (state, view) => {
for (const i of state.cachedViews) {
if (i === view.name) {
const index = state.cachedViews.indexOf(i)
state.cachedViews = state.cachedViews.slice(index, index + 1)
break
}
const index = state.cachedViews.indexOf(view.name)
if (index > -1) {
state.cachedViews = state.cachedViews.slice(index, index + 1)
} else {
// if index = -1, there is no cached tags
state.cachedViews = []
}
},

View File

@ -73,13 +73,18 @@ const actions = {
},
// user logout
logout({ commit, state }) {
logout({ commit, state, dispatch }) {
return new Promise((resolve, reject) => {
logout(state.token).then(() => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
resetRouter()
// reset visited views and cached views
// to fixed https://github.com/PanJiaChen/vue-element-admin/issues/2485
dispatch('tagsView/delAllViews', null, { root: true })
resolve()
}).catch(error => {
reject(error)
@ -98,25 +103,23 @@ const actions = {
},
// dynamically modify permissions
changeRoles({ commit, dispatch }, role) {
return new Promise(async resolve => {
const token = role + '-token'
async changeRoles({ commit, dispatch }, role) {
const token = role + '-token'
commit('SET_TOKEN', token)
setToken(token)
commit('SET_TOKEN', token)
setToken(token)
const { roles } = await dispatch('getInfo')
const { roles } = await dispatch('getInfo')
resetRouter()
resetRouter()
// generate accessible routes map based on roles
const accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })
// generate accessible routes map based on roles
const accessRoutes = await dispatch('permission/generateRoutes', roles, { root: true })
// dynamically add accessible routes
router.addRoutes(accessRoutes)
// dynamically add accessible routes
router.addRoutes(accessRoutes)
resolve()
})
// reset visited views and cached views
dispatch('tagsView/delAllViews', null, { root: true })
}
}

View File

@ -31,7 +31,7 @@
.fixed-width {
.el-button--mini {
padding: 7px 10px;
width: 60px;
min-width: 60px;
}
}
@ -77,3 +77,8 @@
.el-range-editor.el-input__inner {
display: inline-flex !important;
}
// to fix el-date-picker css style
.el-range-separator {
box-sizing: content-box;
}

View File

@ -6,7 +6,7 @@
/* theme color */
$--color-primary: #1890ff;
$--color-success: #13ce66;
$--color-warning: #FFBA00;
$--color-warning: #ffba00;
$--color-danger: #ff4949;
// $--color-info: #1E1E1E;
@ -17,10 +17,10 @@ $--button-font-weight: 400;
$--border-color-light: #dfe4ed;
$--border-color-lighter: #e6ebf5;
$--table-border:1px solid#dfe6ec;
$--table-border: 1px solid #dfe6ec;
/* icon font path, required */
$--font-path: '~element-ui/lib/theme-chalk/fonts';
$--font-path: "~element-ui/lib/theme-chalk/fonts";
@import "~element-ui/packages/theme-chalk/src/index";

View File

@ -57,6 +57,11 @@
margin-right: 16px;
}
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
.el-menu {
border: none;
height: 100%;
@ -95,10 +100,6 @@
margin-left: 54px;
}
.svg-icon {
margin-right: 0px;
}
.submenu-title-noDropdown {
padding: 0 !important;
position: relative;
@ -109,6 +110,10 @@
.svg-icon {
margin-left: 20px;
}
.sub-el-icon {
margin-left: 19px;
}
}
}
@ -122,6 +127,10 @@
margin-left: 20px;
}
.sub-el-icon {
margin-left: 19px;
}
.el-submenu__icon-arrow {
display: none;
}
@ -182,6 +191,10 @@
.svg-icon {
margin-right: 16px;
}
.sub-el-icon {
margin-right: 12px;
margin-left: -2px;
}
}
.nest-menu .el-submenu>.el-submenu__title,

View File

@ -22,14 +22,10 @@ export default function handleClipboard(text, event) {
})
clipboard.on('success', () => {
clipboardSuccess()
clipboard.off('error')
clipboard.off('success')
clipboard.destroy()
})
clipboard.on('error', () => {
clipboardError()
clipboard.off('error')
clipboard.off('success')
clipboard.destroy()
})
clipboard.onClick(event)

View File

@ -6,10 +6,10 @@
* Parse the time to string
* @param {(Object|string|number)} time
* @param {string} cFormat
* @returns {string}
* @returns {string | null}
*/
export function parseTime(time, cFormat) {
if (arguments.length === 0) {
if (arguments.length === 0 || !time) {
return null
}
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
@ -17,9 +17,17 @@ export function parseTime(time, cFormat) {
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
if ((typeof time === 'string')) {
if ((/^[0-9]+$/.test(time))) {
// support "1548221490638"
time = parseInt(time)
} else {
// support safari
// https://stackoverflow.com/questions/4310953/invalid-date-in-safari
time = time.replace(new RegExp(/-/gm), '/')
}
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
@ -34,14 +42,11 @@ export function parseTime(time, cFormat) {
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]
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
const value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
return value.toString().padStart(2, '0')
})
return time_str
}
@ -157,19 +162,21 @@ export function param(json) {
* @returns {Object}
*/
export function param2Obj(url) {
const search = url.split('?')[1]
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
if (!search) {
return {}
}
return JSON.parse(
'{"' +
decodeURIComponent(search)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"')
.replace(/\+/g, ' ') +
'"}'
)
const obj = {}
const searchArr = search.split('&')
searchArr.forEach(v => {
const index = v.indexOf('=')
if (index !== -1) {
const name = v.substring(0, index)
const val = v.substring(index + 1, v.length)
obj[name] = val
}
})
return obj
}
/**

View File

@ -13,11 +13,7 @@ export default function checkPermission(value) {
const hasPermission = roles.some(role => {
return permissionRoles.includes(role)
})
if (!hasPermission) {
return false
}
return true
return hasPermission
} else {
console.error(`need roles! Like v-permission="['admin','editor']"`)
return false

View File

@ -6,7 +6,7 @@ import { getToken } from '@/utils/auth'
// create an axios instance
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
withCredentials: true, // send cookies when cross-domain requests
// withCredentials: true, // send cookies when cross-domain requests
timeout: 5000 // request timeout
})
@ -48,7 +48,7 @@ service.interceptors.response.use(
// if the custom code is not 20000, it is judged as an error.
if (res.code !== 20000) {
Message({
message: res.message || 'error',
message: res.message || 'Error',
type: 'error',
duration: 5 * 1000
})
@ -66,7 +66,7 @@ service.interceptors.response.use(
})
})
}
return Promise.reject(res.message || 'error')
return Promise.reject(new Error(res.message || 'Error'))
} else {
return res
}

View File

@ -1,5 +1,5 @@
/* eslint-disable */
require('script-loader!file-saver');
import { saveAs } from 'file-saver'
import XLSX from 'xlsx'
function generateArray(table) {
@ -151,14 +151,14 @@ export function export_json_to_excel({
filename,
merges = [],
autoWidth = true,
bookType= 'xlsx'
bookType = 'xlsx'
} = {}) {
/* original data */
filename = filename || 'excel-list'
data = [...data]
data.unshift(header);
for (let i = multiHeader.length-1; i > -1; i--) {
for (let i = multiHeader.length - 1; i > -1; i--) {
data.unshift(multiHeader[i])
}

View File

@ -1,5 +1,5 @@
/* eslint-disable */
require('script-loader!file-saver');
import { saveAs } from 'file-saver'
import JSZip from 'jszip'
export function export_txt_to_zip(th, jsonData, txtName, zipName) {

View File

@ -3,13 +3,13 @@
<el-tabs v-model="activeName">
<el-tab-pane label="use clipboard directly" name="directly">
<el-input v-model="inputData" placeholder="Please input" style="width:400px;max-width:100%;" />
<el-button type="primary" icon="document" @click="handleCopy(inputData,$event)">
<el-button type="primary" icon="el-icon-document" @click="handleCopy(inputData,$event)">
copy
</el-button>
</el-tab-pane>
<el-tab-pane label="use clipboard by v-directive" name="v-directive">
<el-input v-model="inputData" placeholder="Please input" style="width:400px;max-width:100%;" />
<el-button v-clipboard:copy="inputData" v-clipboard:success="clipboardSuccess" type="primary" icon="document">
<el-button v-clipboard:copy="inputData" v-clipboard:success="clipboardSuccess" type="primary" icon="el-icon-document">
copy
</el-button>
</el-tab-pane>

View File

@ -7,7 +7,7 @@
<pan-thumb :image="image" />
<el-button type="primary" icon="upload" style="position: absolute;bottom: 15px;margin-left: 40px;" @click="imagecropperShow=true">
<el-button type="primary" icon="el-icon-upload" style="position: absolute;bottom: 15px;margin-left: 40px;" @click="imagecropperShow=true">
Change Avatar
</el-button>

View File

@ -49,7 +49,7 @@
<div style="height:100px;">
<el-form :model="demo" :rules="demoRules">
<el-form-item prop="title">
<md-input v-model="demo.title" icon="search" name="title" placeholder="输入标题">
<md-input v-model="demo.title" icon="el-icon-search" name="title" placeholder="输入标题">
标题
</md-input>
</el-form-item>
@ -149,6 +149,7 @@ export default {
{ title: '登录权限篇', href: 'https://juejin.im/post/591aa14f570c35006961acac' },
{ title: '实战篇', href: 'https://juejin.im/post/593121aa0ce4630057f70d35' },
{ title: 'vue-admin-template 篇', href: 'https://juejin.im/post/595b4d776fb9a06bbe7dba56' },
{ title: 'v4.0 篇', href: 'https://juejin.im/post/5c92ff94f265da6128275a85' },
{ title: '优雅的使用 icon', href: 'https://juejin.im/post/59bb864b5188257e7a427c09' }
]
}

View File

@ -2,7 +2,7 @@
<div class="components-container">
<aside>
Rich text is a core feature of the management backend, but at the same time it is a place with lots of pits. In the process of selecting rich texts, I also took a lot of detours. The common rich texts on the market have been basically used, and I finally chose Tinymce. See the more detailed rich text comparison and introduction.
<a target="_blank" class="link-type" href="https://panjiachen.github.io/vue-element-admin-site/component/rich-editor.html">Documentation</a>
<a target="_blank" class="link-type" href="https://panjiachen.github.io/vue-element-admin-site/feature/component/rich-editor.html">Documentation</a>
</aside>
<div>
<tinymce v-model="content" :height="300" />

View File

@ -5,11 +5,12 @@
<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import { debounce } from '@/utils'
import resize from './mixins/resize'
const animationDuration = 6000
export default {
mixins: [resize],
props: {
className: {
type: String,
@ -30,19 +31,14 @@ export default {
}
},
mounted() {
this.initChart()
this.__resizeHandler = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHandler)
this.$nextTick(() => {
this.initChart()
})
},
beforeDestroy() {
if (!this.chart) {
return
}
window.removeEventListener('resize', this.__resizeHandler)
this.chart.dispose()
this.chart = null
},

View File

@ -15,7 +15,7 @@
<el-progress :percentage="18" />
</div>
<div class="progress-item">
<span>Css</span>
<span>CSS</span>
<el-progress :percentage="12" />
</div>
<div class="progress-item">
@ -101,7 +101,7 @@ export default {
background-color: #fff;
margin: auto;
box-shadow: none!important;
/deep/ .pan-info {
::v-deep .pan-info {
box-shadow: none!important;
}
}

View File

@ -5,9 +5,10 @@
<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import { debounce } from '@/utils'
import resize from './mixins/resize'
export default {
mixins: [resize],
props: {
className: {
type: String,
@ -32,8 +33,7 @@ export default {
},
data() {
return {
chart: null,
sidebarElm: null
chart: null
}
},
watch: {
@ -45,38 +45,21 @@ export default {
}
},
mounted() {
this.initChart()
if (this.autoResize) {
this.__resizeHandler = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHandler)
}
//
this.sidebarElm = document.getElementsByClassName('sidebar-container')[0]
this.sidebarElm && this.sidebarElm.addEventListener('transitionend', this.sidebarResizeHandler)
this.$nextTick(() => {
this.initChart()
})
},
beforeDestroy() {
if (!this.chart) {
return
}
if (this.autoResize) {
window.removeEventListener('resize', this.__resizeHandler)
}
this.sidebarElm && this.sidebarElm.removeEventListener('transitionend', this.sidebarResizeHandler)
this.chart.dispose()
this.chart = null
},
methods: {
sidebarResizeHandler(e) {
if (e.propertyName === 'width') {
this.__resizeHandler()
}
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
this.setOptions(this.chartData)
},
setOptions({ expectedData, actualData } = {}) {
this.chart.setOption({
@ -146,10 +129,6 @@ export default {
animationEasing: 'quadraticOut'
}]
})
},
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
this.setOptions(this.chartData)
}
}
}

View File

@ -73,9 +73,11 @@ export default {
<style lang="scss" scoped>
.panel-group {
margin-top: 18px;
.card-panel-col{
.card-panel-col {
margin-bottom: 32px;
}
.card-panel {
height: 108px;
cursor: pointer;
@ -86,35 +88,45 @@ export default {
background: #fff;
box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
border-color: rgba(0, 0, 0, .05);
&:hover {
.card-panel-icon-wrapper {
color: #fff;
}
.icon-people {
background: #40c9c6;
background: #40c9c6;
}
.icon-message {
background: #36a3f7;
}
.icon-money {
background: #f4516c;
}
.icon-shopping {
background: #34bfa3
}
}
.icon-people {
color: #40c9c6;
}
.icon-message {
color: #36a3f7;
}
.icon-money {
color: #f4516c;
}
.icon-shopping {
color: #34bfa3
}
.card-panel-icon-wrapper {
float: left;
margin: 14px 0 0 14px;
@ -122,25 +134,48 @@ export default {
transition: all 0.38s ease-out;
border-radius: 6px;
}
.card-panel-icon {
float: left;
font-size: 48px;
}
.card-panel-description {
float: right;
font-weight: bold;
margin: 26px;
margin-left: 0px;
.card-panel-text {
line-height: 18px;
color: rgba(0, 0, 0, 0.45);
font-size: 16px;
margin-bottom: 12px;
}
.card-panel-num {
font-size: 20px;
}
}
}
}
@media (max-width:550px) {
.card-panel-description {
display: none;
}
.card-panel-icon-wrapper {
float: none !important;
width: 100%;
height: 100%;
margin: 0 !important;
.svg-icon {
display: block;
margin: 14px auto !important;
float: none !important;
}
}
}
</style>

View File

@ -5,9 +5,10 @@
<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import { debounce } from '@/utils'
import resize from './mixins/resize'
export default {
mixins: [resize],
props: {
className: {
type: String,
@ -28,19 +29,14 @@ export default {
}
},
mounted() {
this.initChart()
this.__resizeHandler = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHandler)
this.$nextTick(() => {
this.initChart()
})
},
beforeDestroy() {
if (!this.chart) {
return
}
window.removeEventListener('resize', this.__resizeHandler)
this.chart.dispose()
this.chart = null
},
@ -58,7 +54,6 @@ export default {
bottom: '10',
data: ['Industries', 'Technology', 'Forex', 'Gold', 'Forecasts']
},
calculable: true,
series: [
{
name: 'WEEKLY WRITE ARTICLES',

View File

@ -5,11 +5,12 @@
<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import { debounce } from '@/utils'
import resize from './mixins/resize'
const animationDuration = 3000
export default {
mixins: [resize],
props: {
className: {
type: String,
@ -30,19 +31,14 @@ export default {
}
},
mounted() {
this.initChart()
this.__resizeHandler = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
window.addEventListener('resize', this.__resizeHandler)
this.$nextTick(() => {
this.initChart()
})
},
beforeDestroy() {
if (!this.chart) {
return
}
window.removeEventListener('resize', this.__resizeHandler)
this.chart.dispose()
this.chart = null
},
@ -74,7 +70,7 @@ export default {
indicator: [
{ name: 'Sales', max: 10000 },
{ name: 'Administration', max: 20000 },
{ name: 'Information Techology', max: 20000 },
{ name: 'Information Technology', max: 20000 },
{ name: 'Customer Support', max: 20000 },
{ name: 'Development', max: 20000 },
{ name: 'Marketing', max: 20000 }

View File

@ -0,0 +1,55 @@
import { debounce } from '@/utils'
export default {
data() {
return {
$_sidebarElm: null,
$_resizeHandler: null
}
},
mounted() {
this.$_resizeHandler = debounce(() => {
if (this.chart) {
this.chart.resize()
}
}, 100)
this.$_initResizeEvent()
this.$_initSidebarResizeEvent()
},
beforeDestroy() {
this.$_destroyResizeEvent()
this.$_destroySidebarResizeEvent()
},
// to fixed bug when cached by keep-alive
// https://github.com/PanJiaChen/vue-element-admin/issues/2116
activated() {
this.$_initResizeEvent()
this.$_initSidebarResizeEvent()
},
deactivated() {
this.$_destroyResizeEvent()
this.$_destroySidebarResizeEvent()
},
methods: {
// use $_ for mixins properties
// https://vuejs.org/v2/style-guide/index.html#Private-property-names-essential
$_initResizeEvent() {
window.addEventListener('resize', this.$_resizeHandler)
},
$_destroyResizeEvent() {
window.removeEventListener('resize', this.$_resizeHandler)
},
$_sidebarResizeHandler(e) {
if (e.propertyName === 'width') {
this.$_resizeHandler()
}
},
$_initSidebarResizeEvent() {
this.$_sidebarElm = document.getElementsByClassName('sidebar-container')[0]
this.$_sidebarElm && this.$_sidebarElm.addEventListener('transitionend', this.$_sidebarResizeHandler)
},
$_destroySidebarResizeEvent() {
this.$_sidebarElm && this.$_sidebarElm.removeEventListener('transitionend', this.$_sidebarResizeHandler)
}
}
}

View File

@ -115,4 +115,10 @@ export default {
margin-bottom: 32px;
}
}
@media (max-width:1024px) {
.chart-wrapper {
padding: 8px;
}
}
</style>

View File

@ -1,21 +1,11 @@
<template>
<div class="app-container documentation-container">
<a
class="document-btn"
target="_blank"
href="https://panjiachen.github.io/vue-element-admin-site/"
>Documentation</a>
<a
class="document-btn"
target="_blank"
href="https://github.com/PanJiaChen/vue-element-admin/"
>Github Repository</a>
<a
class="document-btn"
target="_blank"
href="https://panjiachen.gitee.io/vue-element-admin-site/zh/"
>国内文档</a>
<dropdown-menu :items="articleList" style="float:left;margin-left:50px;" title="系列文章" />
<a class="document-btn" target="_blank" href="https://store.akveo.com/products/vue-java-admin-dashboard-spring?utm_campaign=akveo_store-Vue-Vue_demo%2Fgithub&utm_source=vue_admin&utm_medium=referral&utm_content=demo_English_button">Java backend integration</a>
<a class="document-btn" target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/">Documentation</a>
<a class="document-btn" target="_blank" href="https://github.com/PanJiaChen/vue-element-admin/">Github Repository</a>
<a class="document-btn" target="_blank" href="https://panjiachen.gitee.io/vue-element-admin-site/zh/">国内文档</a>
<dropdown-menu class="document-btn" :items="articleList" title="系列文章" />
<a class="document-btn" target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/zh/job/">内推招聘</a>
</div>
</template>
@ -32,6 +22,7 @@ export default {
{ title: '登录权限篇', href: 'https://juejin.im/post/591aa14f570c35006961acac' },
{ title: '实战篇', href: 'https://juejin.im/post/593121aa0ce4630057f70d35' },
{ title: 'vue-admin-template 篇', href: 'https://juejin.im/post/595b4d776fb9a06bbe7dba56' },
{ title: 'v4.0 篇', href: 'https://juejin.im/post/5c92ff94f265da6128275a85' },
{ title: '自行封装 component', href: 'https://segmentfault.com/a/1190000009090836' },
{ title: '优雅的使用 icon', href: 'https://juejin.im/post/59bb864b5188257e7a427c09' },
{ title: 'webpack4', href: 'https://juejin.im/post/59bb864b5188257e7a427c09' },
@ -45,15 +36,19 @@ export default {
<style lang="scss" scoped>
.documentation-container {
margin: 50px;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
.document-btn {
float: left;
margin-left: 50px;
flex-shrink: 0;
display: block;
cursor: pointer;
background: black;
color: white;
height: 60px;
width: 200px;
padding: 0 16px;
margin: 16px;
line-height: 60px;
font-size: 20px;
text-align: center;

View File

@ -1,6 +1,6 @@
<template>
<div class="errPage-container">
<el-button icon="arrow-left" class="pan-back-btn" @click="back">
<el-button icon="el-icon-arrow-left" class="pan-back-btn" @click="back">
返回
</el-button>
<el-row>

View File

@ -7,7 +7,7 @@
<PlatformDropdown v-model="postForm.platforms" />
<SourceUrlDropdown v-model="postForm.source_uri" />
<el-button v-loading="loading" style="margin-left: 10px;" type="success" @click="submitForm">
Publush
Publish
</el-button>
<el-button v-loading="loading" type="warning" @click="draftForm">
Draft
@ -36,7 +36,7 @@
</el-col>
<el-col :span="10">
<el-form-item label-width="120px" label="Publush Time:" class="postInfo-container-item">
<el-form-item label-width="120px" label="Publish Time:" class="postInfo-container-item">
<el-date-picker v-model="displayTime" type="datetime" format="yyyy-MM-dd HH:mm:ss" placeholder="Select date and time" />
</el-form-item>
</el-col>
@ -49,7 +49,7 @@
:colors="['#99A9BF', '#F7BA2A', '#FF9900']"
:low-threshold="1"
:high-threshold="3"
style="margin-top:8px;"
style="display:inline-block"
/>
</el-form-item>
</el-col>
@ -170,8 +170,6 @@ export default {
if (this.isEdit) {
const id = this.$route.params && this.$route.params.id
this.fetchData(id)
} else {
this.postForm = Object.assign({}, defaultForm)
}
// Why need to make a copy of this.$route here?
@ -183,12 +181,16 @@ export default {
fetchData(id) {
fetchArticle(id).then(response => {
this.postForm = response.data
// Just for test
// just for test
this.postForm.title += ` Article Id:${this.postForm.id}`
this.postForm.content_short += ` Article Id:${this.postForm.id}`
// Set tagsview title
// set tagsview title
this.setTagsViewTitle()
// set page title
this.setPageTitle()
}).catch(err => {
console.log(err)
})
@ -198,6 +200,10 @@ export default {
const route = Object.assign({}, this.tempRoute, { title: `${title}-${this.postForm.id}` })
this.$store.dispatch('tagsView/updateVisitedView', route)
},
setPageTitle() {
const title = 'Edit Article'
document.title = `${title} - ${this.postForm.id}`
},
submitForm() {
console.log(this.postForm)
this.$refs.postForm.validate(valid => {
@ -271,7 +277,7 @@ export default {
}
}
.article-textarea /deep/ {
.article-textarea ::v-deep {
textarea {
padding-right: 40px;
resize: none;

View File

@ -6,7 +6,7 @@
import ArticleDetail from './components/ArticleDetail'
export default {
name: 'CreateForm',
name: 'CreateArticle',
components: { ArticleDetail }
}
</script>

View File

@ -5,7 +5,7 @@
<FilenameOption v-model="filename" />
<AutoWidthOption v-model="autoWidth" />
<BookTypeOption v-model="bookType" />
<el-button :loading="downloadLoading" style="margin:0 0 20px 20px;" type="primary" icon="document" @click="handleDownload">
<el-button :loading="downloadLoading" style="margin:0 0 20px 20px;" type="primary" icon="el-icon-document" @click="handleDownload">
Export Excel
</el-button>
<a href="https://panjiachen.github.io/vue-element-admin-site/feature/component/excel.html" target="_blank" style="margin-left:15px;">
@ -13,7 +13,7 @@
</a>
</div>
<el-table v-loading="listLoading" :data="list" element-loading-text="拼命加载中" border fit highlight-current-row>
<el-table v-loading="listLoading" :data="list" element-loading-text="Loading..." border fit highlight-current-row>
<el-table-column align="center" label="Id" width="95">
<template slot-scope="scope">
{{ scope.$index }}

View File

@ -1,7 +1,7 @@
<template>
<div class="app-container">
<el-button :loading="downloadLoading" style="margin-bottom:20px" type="primary" icon="document" @click="handleDownload">Export</el-button>
<el-button :loading="downloadLoading" style="margin-bottom:20px" type="primary" icon="el-icon-document" @click="handleDownload">Export</el-button>
<el-table
ref="multipleTable"
@ -71,21 +71,21 @@ export default {
},
handleDownload() {
this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => {
const multiHeader = [['Id', 'Main Information', '', '', 'Date']]
const header = ['', 'Title', 'Author', 'Readings', '']
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
const list = this.list
const data = this.formatJson(filterVal, list)
const merges = ['A1:A2', 'B1:D1', 'E1:E2']
excel.export_json_to_excel({
multiHeader,
header,
merges,
data
})
this.downloadLoading = false
import('@/vendor/Export2Excel').then(excel => {
const multiHeader = [['Id', 'Main Information', '', '', 'Date']]
const header = ['', 'Title', 'Author', 'Readings', '']
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
const list = this.list
const data = this.formatJson(filterVal, list)
const merges = ['A1:A2', 'B1:D1', 'E1:E2']
excel.export_json_to_excel({
multiHeader,
header,
merges,
data
})
this.downloadLoading = false
})
},
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => {

View File

@ -1,7 +1,7 @@
<template>
<div class="app-container">
<el-input v-model="filename" placeholder="Please enter the file name (default excel-list)" style="width:350px;" prefix-icon="el-icon-document" />
<el-button :loading="downloadLoading" style="margin-bottom:20px" type="primary" icon="document" @click="handleDownload">
<el-button :loading="downloadLoading" style="margin-bottom:20px" type="primary" icon="el-icon-document" @click="handleDownload">
Export Selected Items
</el-button>
<a href="https://panjiachen.github.io/vue-element-admin-site/feature/component/excel.html" target="_blank" style="margin-left:15px;">

View File

@ -1,74 +1,3 @@
const elementIcons = [
'info',
'error',
'success',
'warning',
'question',
'back',
'arrow-left',
'arrow-down',
'arrow-right',
'arrow-up',
'caret-left',
'caret-bottom',
'caret-top',
'caret-right',
'd-arrow-left',
'd-arrow-right',
'minus',
'plus',
'remove',
'circle-plus',
'remove-outline',
'circle-plus-outline',
'close',
'check',
'circle-close',
'circle-check',
'circle-close-outline',
'circle-check-outline',
'zoom-out',
'zoom-in',
'd-caret',
'sort',
'sort-down',
'sort-up',
'tickets',
'document',
'goods',
'sold-out',
'news',
'message',
'date',
'printer',
'time',
'bell',
'mobile-phone',
'service',
'view',
'menu',
'more',
'more-outline',
'star-on',
'star-off',
'location',
'location-outline',
'phone',
'phone-outline',
'picture',
'picture-outline',
'delete',
'search',
'edit',
'edit-outline',
'rank',
'refresh',
'share',
'setting',
'upload',
'upload2',
'download',
'loading'
]
const elementIcons = ['platform-eleme', 'eleme', 'delete-solid', 'delete', 's-tools', 'setting', 'user-solid', 'user', 'phone', 'phone-outline', 'more', 'more-outline', 'star-on', 'star-off', 's-goods', 'goods', 'warning', 'warning-outline', 'question', 'info', 'remove', 'circle-plus', 'success', 'error', 'zoom-in', 'zoom-out', 'remove-outline', 'circle-plus-outline', 'circle-check', 'circle-close', 's-help', 'help', 'minus', 'plus', 'check', 'close', 'picture', 'picture-outline', 'picture-outline-round', 'upload', 'upload2', 'download', 'camera-solid', 'camera', 'video-camera-solid', 'video-camera', 'message-solid', 'bell', 's-cooperation', 's-order', 's-platform', 's-fold', 's-unfold', 's-operation', 's-promotion', 's-home', 's-release', 's-ticket', 's-management', 's-open', 's-shop', 's-marketing', 's-flag', 's-comment', 's-finance', 's-claim', 's-custom', 's-opportunity', 's-data', 's-check', 's-grid', 'menu', 'share', 'd-caret', 'caret-left', 'caret-right', 'caret-bottom', 'caret-top', 'bottom-left', 'bottom-right', 'back', 'right', 'bottom', 'top', 'top-left', 'top-right', 'arrow-left', 'arrow-right', 'arrow-down', 'arrow-up', 'd-arrow-left', 'd-arrow-right', 'video-pause', 'video-play', 'refresh', 'refresh-right', 'refresh-left', 'finished', 'sort', 'sort-up', 'sort-down', 'rank', 'loading', 'view', 'c-scale-to-original', 'date', 'edit', 'edit-outline', 'folder', 'folder-opened', 'folder-add', 'folder-remove', 'folder-delete', 'folder-checked', 'tickets', 'document-remove', 'document-delete', 'document-copy', 'document-checked', 'document', 'document-add', 'printer', 'paperclip', 'takeaway-box', 'search', 'monitor', 'attract', 'mobile', 'scissors', 'umbrella', 'headset', 'brush', 'mouse', 'coordinate', 'magic-stick', 'reading', 'data-line', 'data-board', 'pie-chart', 'data-analysis', 'collection-tag', 'film', 'suitcase', 'suitcase-1', 'receiving', 'collection', 'files', 'notebook-1', 'notebook-2', 'toilet-paper', 'office-building', 'school', 'table-lamp', 'house', 'no-smoking', 'smoking', 'shopping-cart-full', 'shopping-cart-1', 'shopping-cart-2', 'shopping-bag-1', 'shopping-bag-2', 'sold-out', 'sell', 'present', 'box', 'bank-card', 'money', 'coin', 'wallet', 'discount', 'price-tag', 'news', 'guide', 'male', 'female', 'thumb', 'cpu', 'link', 'connection', 'open', 'turn-off', 'set-up', 'chat-round', 'chat-line-round', 'chat-square', 'chat-dot-round', 'chat-dot-square', 'chat-line-square', 'message', 'postcard', 'position', 'turn-off-microphone', 'microphone', 'close-notification', 'bangzhu', 'time', 'odometer', 'crop', 'aim', 'switch-button', 'full-screen', 'copy-document', 'mic', 'stopwatch', 'medal-1', 'medal', 'trophy', 'trophy-1', 'first-aid-kit', 'discover', 'place', 'location', 'location-outline', 'location-information', 'add-location', 'delete-location', 'map-location', 'alarm-clock', 'timer', 'watch-1', 'watch', 'lock', 'unlock', 'key', 'service', 'mobile-phone', 'bicycle', 'truck', 'ship', 'basketball', 'football', 'soccer', 'baseball', 'wind-power', 'light-rain', 'lightning', 'heavy-rain', 'sunrise', 'sunrise-1', 'sunset', 'sunny', 'cloudy', 'partly-cloudy', 'cloudy-and-sunny', 'moon', 'moon-night', 'dish', 'dish-1', 'food', 'chicken', 'fork-spoon', 'knife-fork', 'burger', 'tableware', 'sugar', 'dessert', 'ice-cream', 'hot-water', 'water-cup', 'coffee-cup', 'cold-drink', 'goblet', 'goblet-full', 'goblet-square', 'goblet-square-full', 'refrigerator', 'grape', 'watermelon', 'cherry', 'apple', 'pear', 'orange', 'coffee', 'ice-tea', 'ice-drink', 'milk-tea', 'potato-strips', 'lollipop', 'ice-cream-square', 'ice-cream-round']
export default elementIcons

View File

@ -6,29 +6,33 @@
</aside>
<el-tabs type="border-card">
<el-tab-pane label="Icons">
<div v-for="item of svgIcons" :key="item" @click="handleClipboard(generateIconCode(item),$event)">
<el-tooltip placement="top">
<div slot="content">
{{ generateIconCode(item) }}
</div>
<div class="icon-item">
<svg-icon :icon-class="item" class-name="disabled" />
<span>{{ item }}</span>
</div>
</el-tooltip>
<div class="grid">
<div v-for="item of svgIcons" :key="item" @click="handleClipboard(generateIconCode(item),$event)">
<el-tooltip placement="top">
<div slot="content">
{{ generateIconCode(item) }}
</div>
<div class="icon-item">
<svg-icon :icon-class="item" class-name="disabled" />
<span>{{ item }}</span>
</div>
</el-tooltip>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="Element-UI Icons">
<div v-for="item of elementIcons" :key="item" @click="handleClipboard(generateElementIconCode(item),$event)">
<el-tooltip placement="top">
<div slot="content">
{{ generateElementIconCode(item) }}
</div>
<div class="icon-item">
<i :class="'el-icon-' + item" />
<span>{{ item }}</span>
</div>
</el-tooltip>
<div class="grid">
<div v-for="item of elementIcons" :key="item" @click="handleClipboard(generateElementIconCode(item),$event)">
<el-tooltip placement="top">
<div slot="content">
{{ generateElementIconCode(item) }}
</div>
<div class="icon-item">
<i :class="'el-icon-' + item" />
<span>{{ item }}</span>
</div>
</el-tooltip>
</div>
</div>
</el-tab-pane>
</el-tabs>
@ -67,6 +71,12 @@ export default {
margin: 10px 20px 0;
overflow: hidden;
.grid {
position: relative;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
}
.icon-item {
margin: 20px;
height: 85px;

View File

@ -1,6 +1,6 @@
<template>
<div class="login-container">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" autocomplete="on" label-position="left">
<div class="title-container">
<h3 class="title">Login Form</h3>
@ -17,7 +17,7 @@
name="username"
type="text"
tabindex="1"
auto-complete="on"
autocomplete="on"
/>
</el-form-item>
@ -34,7 +34,7 @@
placeholder="Password"
name="password"
tabindex="2"
auto-complete="on"
autocomplete="on"
@keyup.native="checkCapslock"
@blur="capsTooltip = false"
@keyup.enter.native="handleLogin"
@ -108,13 +108,18 @@ export default {
capsTooltip: false,
loading: false,
showDialog: false,
redirect: undefined
redirect: undefined,
otherQuery: {}
}
},
watch: {
$route: {
handler: function(route) {
this.redirect = route.query && route.query.redirect
const query = route.query
if (query) {
this.redirect = query.redirect
this.otherQuery = this.getOtherQuery(query)
}
},
immediate: true
}
@ -133,17 +138,9 @@ export default {
// window.removeEventListener('storage', this.afterQRScan)
},
methods: {
checkCapslock({ shiftKey, key } = {}) {
if (key && key.length === 1) {
if (shiftKey && (key >= 'a' && key <= 'z') || !shiftKey && (key >= 'A' && key <= 'Z')) {
this.capsTooltip = true
} else {
this.capsTooltip = false
}
}
if (key === 'CapsLock' && this.capsTooltip === true) {
this.capsTooltip = false
}
checkCapslock(e) {
const { key } = e
this.capsTooltip = key && key.length === 1 && (key >= 'A' && key <= 'Z')
},
showPwd() {
if (this.passwordType === 'password') {
@ -161,7 +158,7 @@ export default {
this.loading = true
this.$store.dispatch('user/login', this.loginForm)
.then(() => {
this.$router.push({ path: this.redirect || '/' })
this.$router.push({ path: this.redirect || '/', query: this.otherQuery })
this.loading = false
})
.catch(() => {
@ -172,6 +169,14 @@ export default {
return false
}
})
},
getOtherQuery(query) {
return Object.keys(query).reduce((acc, cur) => {
if (cur !== 'redirect') {
acc[cur] = query[cur]
}
return acc
}, {})
}
// afterQRScan() {
// if (e.key === 'x-admin-oauth-code') {

View File

@ -26,17 +26,17 @@ export default {
},
methods: {
fetchData() {
import('./content.js').then(data => {
const { title } = data.default
document.title = title
this.article = data.default
setTimeout(() => {
this.fullscreenLoading = false
this.$nextTick(() => {
window.print()
})
}, 3000)
})
import('./content.js').then(data => {
const { title } = data.default
document.title = title
this.article = data.default
setTimeout(() => {
this.fullscreenLoading = false
this.$nextTick(() => {
window.print()
})
}, 3000)
})
}
}
}

View File

@ -91,7 +91,7 @@ export default {
<style lang="scss" scoped>
.app-container {
/deep/ .permission-alert {
::v-deep .permission-alert {
width: 320px;
margin-top: 15px;
background-color: #f0f9eb;
@ -100,10 +100,10 @@ export default {
border-radius: 4px;
display: inline-block;
}
/deep/ .permission-sourceCode {
::v-deep .permission-sourceCode {
margin-left: 15px;
}
/deep/ .permission-tag {
::v-deep .permission-tag {
background-color: #ecf5ff;
}
}

View File

@ -228,7 +228,7 @@ export default {
dangerouslyUseHTMLString: true,
message: `
<div>Role Key: ${key}</div>
<div>Role Nmae: ${name}</div>
<div>Role Name: ${name}</div>
<div>Description: ${description}</div>
`,
type: 'success'

View File

@ -1,5 +1,5 @@
<template>
<el-card>
<el-card style="margin-bottom:20px;">
<div slot="header" class="clearfix">
<span>About me</span>
</div>
@ -65,7 +65,7 @@ export default {
name: '',
email: '',
avatar: '',
roles: ''
role: ''
}
}
}
@ -74,61 +74,61 @@ export default {
</script>
<style lang="scss" scoped>
.box-center {
margin: 0 auto;
display: table;
}
.box-center {
margin: 0 auto;
display: table;
}
.text-muted {
color: #777;
}
.text-muted {
color: #777;
}
.user-profile {
.user-name {
font-weight: bold;
}
.user-profile {
.user-name {
font-weight: bold;
}
.box-center {
padding-top: 10px;
}
.box-center {
padding-top: 10px;
}
.user-role {
padding-top: 10px;
font-weight: 400;
font-size: 14px;
}
.user-role {
padding-top: 10px;
font-weight: 400;
font-size: 14px;
}
.box-social {
padding-top: 30px;
.box-social {
padding-top: 30px;
.el-table {
border-top: 1px solid #dfe6ec;
}
}
.el-table {
border-top: 1px solid #dfe6ec;
}
}
.user-follow {
padding-top: 20px;
}
}
.user-follow {
padding-top: 20px;
}
}
.user-bio {
margin-top: 20px;
color: #606266;
.user-bio {
margin-top: 20px;
color: #606266;
span {
padding-left: 4px;
}
span {
padding-left: 4px;
}
.user-bio-section {
font-size: 14px;
padding: 15px 0;
.user-bio-section {
font-size: 14px;
padding: 15px 0;
.user-bio-section-header {
border-bottom: 1px solid #dfe6ec;
padding-bottom: 10px;
margin-bottom: 10px;
font-weight: bold;
}
}
}
.user-bio-section-header {
border-bottom: 1px solid #dfe6ec;
padding-bottom: 10px;
margin-bottom: 10px;
font-weight: bold;
}
}
}
</style>

View File

@ -3,11 +3,11 @@
<div v-if="user">
<el-row :gutter="20">
<el-col :span="6">
<el-col :span="6" :xs="24">
<user-card :user="user" />
</el-col>
<el-col :span="18">
<el-col :span="18" :xs="24">
<el-card>
<el-tabs v-model="activeTab">
<el-tab-pane label="Activity" name="activity">

View File

@ -1,6 +1,6 @@
<script>
export default {
beforeCreate() {
created() {
const { params, query } = this.$route
const { path } = params
this.$router.replace({ path: '/' + path, query })

View File

@ -13,11 +13,11 @@
</template>
<script>
import tabPane from './components/TabPane'
import TabPane from './components/TabPane'
export default {
name: 'Tab',
components: { tabPane },
components: { TabPane },
data() {
return {
tabMapOptions: [
@ -30,6 +30,18 @@ export default {
createdTimes: 0
}
},
watch: {
activeName(val) {
this.$router.push(`${this.$route.path}?tab=${val}`)
}
},
created() {
// init the default selected tab
const tab = this.$route.query.tab
if (tab) {
this.activeName = tab
}
},
methods: {
showCreatedTimes() {
this.createdTimes = this.createdTimes + 1

Some files were not shown because too many files have changed in this diff Show More