@lavida/vue-element-admin-template 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +15 -0
- package/template/.editorconfig +14 -0
- package/template/.env.development +5 -0
- package/template/.env.production +6 -0
- package/template/.env.staging +8 -0
- package/template/.eslintignore +4 -0
- package/template/.eslintrc.js +198 -0
- package/template/.travis.yml +5 -0
- package/template/LICENSE +21 -0
- package/template/README.es.md +222 -0
- package/template/README.ja.md +218 -0
- package/template/README.md +222 -0
- package/template/README.zh-CN.md +245 -0
- package/template/babel.config.js +14 -0
- package/template/build/index.js +35 -0
- package/template/jest.config.js +24 -0
- package/template/jsconfig.json +9 -0
- package/template/mock/article.js +116 -0
- package/template/mock/index.js +60 -0
- package/template/mock/mock-server.js +81 -0
- package/template/mock/remote-search.js +51 -0
- package/template/mock/role/index.js +98 -0
- package/template/mock/role/routes.js +530 -0
- package/template/mock/user.js +84 -0
- package/template/mock/utils.js +48 -0
- package/template/package.json +111 -0
- package/template/plop-templates/component/index.hbs +26 -0
- package/template/plop-templates/component/prompt.js +55 -0
- package/template/plop-templates/store/index.hbs +16 -0
- package/template/plop-templates/store/prompt.js +62 -0
- package/template/plop-templates/utils.js +2 -0
- package/template/plop-templates/view/index.hbs +26 -0
- package/template/plop-templates/view/prompt.js +55 -0
- package/template/plopfile.js +9 -0
- package/template/postcss.config.js +5 -0
- package/template/public/favicon.ico +0 -0
- package/template/public/index.html +15 -0
- package/template/src/App.vue +11 -0
- package/template/src/api/article.js +41 -0
- package/template/src/api/qiniu.js +8 -0
- package/template/src/api/remote-search.js +17 -0
- package/template/src/api/role.js +38 -0
- package/template/src/api/user.js +24 -0
- package/template/src/assets/401_images/401.gif +0 -0
- package/template/src/assets/404_images/404.png +0 -0
- package/template/src/assets/404_images/404_cloud.png +0 -0
- package/template/src/assets/custom-theme/fonts/element-icons.ttf +0 -0
- package/template/src/assets/custom-theme/fonts/element-icons.woff +0 -0
- package/template/src/assets/custom-theme/index.css +1 -0
- package/template/src/components/BackToTop/index.vue +111 -0
- package/template/src/components/Breadcrumb/index.vue +82 -0
- package/template/src/components/Charts/Keyboard.vue +155 -0
- package/template/src/components/Charts/LineMarker.vue +227 -0
- package/template/src/components/Charts/MixChart.vue +271 -0
- package/template/src/components/Charts/mixins/resize.js +56 -0
- package/template/src/components/DndList/index.vue +166 -0
- package/template/src/components/DragSelect/index.vue +65 -0
- package/template/src/components/Dropzone/index.vue +297 -0
- package/template/src/components/ErrorLog/index.vue +78 -0
- package/template/src/components/GithubCorner/index.vue +54 -0
- package/template/src/components/Hamburger/index.vue +44 -0
- package/template/src/components/HeaderSearch/index.vue +180 -0
- package/template/src/components/ImageCropper/index.vue +1779 -0
- package/template/src/components/ImageCropper/utils/data2blob.js +19 -0
- package/template/src/components/ImageCropper/utils/effectRipple.js +39 -0
- package/template/src/components/ImageCropper/utils/language.js +232 -0
- package/template/src/components/ImageCropper/utils/mimes.js +7 -0
- package/template/src/components/JsonEditor/index.vue +77 -0
- package/template/src/components/Kanban/index.vue +99 -0
- package/template/src/components/MDinput/index.vue +360 -0
- package/template/src/components/MarkdownEditor/default-options.js +31 -0
- package/template/src/components/MarkdownEditor/index.vue +118 -0
- package/template/src/components/Pagination/index.vue +101 -0
- package/template/src/components/PanThumb/index.vue +142 -0
- package/template/src/components/RightPanel/index.vue +145 -0
- package/template/src/components/Screenfull/index.vue +60 -0
- package/template/src/components/Share/DropdownMenu.vue +103 -0
- package/template/src/components/SizeSelect/index.vue +57 -0
- package/template/src/components/Sticky/index.vue +91 -0
- package/template/src/components/SvgIcon/index.vue +62 -0
- package/template/src/components/TextHoverEffect/Mallki.vue +113 -0
- package/template/src/components/ThemePicker/index.vue +175 -0
- package/template/src/components/Tinymce/components/EditorImage.vue +111 -0
- package/template/src/components/Tinymce/dynamicLoadScript.js +59 -0
- package/template/src/components/Tinymce/index.vue +250 -0
- package/template/src/components/Tinymce/plugins.js +7 -0
- package/template/src/components/Tinymce/toolbar.js +6 -0
- package/template/src/components/Upload/SingleImage.vue +134 -0
- package/template/src/components/Upload/SingleImage2.vue +130 -0
- package/template/src/components/Upload/SingleImage3.vue +157 -0
- package/template/src/components/UploadExcel/index.vue +138 -0
- package/template/src/directive/clipboard/clipboard.js +49 -0
- package/template/src/directive/clipboard/index.js +13 -0
- package/template/src/directive/el-drag-dialog/drag.js +77 -0
- package/template/src/directive/el-drag-dialog/index.js +13 -0
- package/template/src/directive/el-table/adaptive.js +41 -0
- package/template/src/directive/el-table/index.js +13 -0
- package/template/src/directive/permission/index.js +13 -0
- package/template/src/directive/permission/permission.js +31 -0
- package/template/src/directive/sticky.js +91 -0
- package/template/src/directive/waves/index.js +13 -0
- package/template/src/directive/waves/waves.css +26 -0
- package/template/src/directive/waves/waves.js +72 -0
- package/template/src/filters/index.js +68 -0
- package/template/src/icons/index.js +9 -0
- package/template/src/icons/svg/404.svg +1 -0
- package/template/src/icons/svg/bug.svg +1 -0
- package/template/src/icons/svg/chart.svg +1 -0
- package/template/src/icons/svg/clipboard.svg +1 -0
- package/template/src/icons/svg/component.svg +1 -0
- package/template/src/icons/svg/dashboard.svg +1 -0
- package/template/src/icons/svg/documentation.svg +1 -0
- package/template/src/icons/svg/drag.svg +1 -0
- package/template/src/icons/svg/edit.svg +1 -0
- package/template/src/icons/svg/education.svg +1 -0
- package/template/src/icons/svg/email.svg +1 -0
- package/template/src/icons/svg/example.svg +1 -0
- package/template/src/icons/svg/excel.svg +1 -0
- package/template/src/icons/svg/exit-fullscreen.svg +1 -0
- package/template/src/icons/svg/eye-open.svg +1 -0
- package/template/src/icons/svg/eye.svg +1 -0
- package/template/src/icons/svg/form.svg +1 -0
- package/template/src/icons/svg/fullscreen.svg +1 -0
- package/template/src/icons/svg/guide.svg +1 -0
- package/template/src/icons/svg/icon.svg +1 -0
- package/template/src/icons/svg/international.svg +1 -0
- package/template/src/icons/svg/language.svg +1 -0
- package/template/src/icons/svg/link.svg +1 -0
- package/template/src/icons/svg/list.svg +1 -0
- package/template/src/icons/svg/lock.svg +1 -0
- package/template/src/icons/svg/message.svg +1 -0
- package/template/src/icons/svg/money.svg +1 -0
- package/template/src/icons/svg/nested.svg +1 -0
- package/template/src/icons/svg/password.svg +1 -0
- package/template/src/icons/svg/pdf.svg +1 -0
- package/template/src/icons/svg/people.svg +1 -0
- package/template/src/icons/svg/peoples.svg +1 -0
- package/template/src/icons/svg/qq.svg +1 -0
- package/template/src/icons/svg/search.svg +1 -0
- package/template/src/icons/svg/shopping.svg +1 -0
- package/template/src/icons/svg/size.svg +1 -0
- package/template/src/icons/svg/skill.svg +1 -0
- package/template/src/icons/svg/star.svg +1 -0
- package/template/src/icons/svg/tab.svg +1 -0
- package/template/src/icons/svg/table.svg +1 -0
- package/template/src/icons/svg/theme.svg +1 -0
- package/template/src/icons/svg/tree-table.svg +1 -0
- package/template/src/icons/svg/tree.svg +1 -0
- package/template/src/icons/svg/user.svg +1 -0
- package/template/src/icons/svg/wechat.svg +1 -0
- package/template/src/icons/svg/zip.svg +1 -0
- package/template/src/icons/svgo.yml +22 -0
- package/template/src/layout/components/AppMain.vue +57 -0
- package/template/src/layout/components/Navbar.vue +167 -0
- package/template/src/layout/components/Settings/index.vue +108 -0
- package/template/src/layout/components/Sidebar/FixiOSBug.js +26 -0
- package/template/src/layout/components/Sidebar/Item.vue +41 -0
- package/template/src/layout/components/Sidebar/Link.vue +43 -0
- package/template/src/layout/components/Sidebar/Logo.vue +82 -0
- package/template/src/layout/components/Sidebar/SidebarItem.vue +95 -0
- package/template/src/layout/components/Sidebar/index.vue +54 -0
- package/template/src/layout/components/TagsView/ScrollPane.vue +94 -0
- package/template/src/layout/components/TagsView/index.vue +292 -0
- package/template/src/layout/components/index.js +5 -0
- package/template/src/layout/index.vue +102 -0
- package/template/src/layout/mixin/ResizeHandler.js +45 -0
- package/template/src/main.js +53 -0
- package/template/src/permission.js +74 -0
- package/template/src/router/index.js +404 -0
- package/template/src/router/modules/charts.js +36 -0
- package/template/src/router/modules/components.js +102 -0
- package/template/src/router/modules/nested.js +66 -0
- package/template/src/router/modules/table.js +41 -0
- package/template/src/settings.js +35 -0
- package/template/src/store/getters.js +15 -0
- package/template/src/store/index.js +25 -0
- package/template/src/store/modules/app.js +56 -0
- package/template/src/store/modules/errorLog.js +28 -0
- package/template/src/store/modules/permission.js +69 -0
- package/template/src/store/modules/settings.js +35 -0
- package/template/src/store/modules/tagsView.js +160 -0
- package/template/src/store/modules/user.js +131 -0
- package/template/src/styles/btn.scss +99 -0
- package/template/src/styles/element-ui.scss +84 -0
- package/template/src/styles/element-variables.scss +31 -0
- package/template/src/styles/index.scss +191 -0
- package/template/src/styles/mixin.scss +66 -0
- package/template/src/styles/sidebar.scss +226 -0
- package/template/src/styles/transition.scss +48 -0
- package/template/src/styles/variables.scss +35 -0
- package/template/src/utils/auth.js +15 -0
- package/template/src/utils/clipboard.js +32 -0
- package/template/src/utils/error-log.js +35 -0
- package/template/src/utils/get-page-title.js +10 -0
- package/template/src/utils/index.js +357 -0
- package/template/src/utils/open-window.js +25 -0
- package/template/src/utils/permission.js +25 -0
- package/template/src/utils/request.js +85 -0
- package/template/src/utils/scroll-to.js +58 -0
- package/template/src/utils/validate.js +87 -0
- package/template/src/vendor/Export2Excel.js +220 -0
- package/template/src/vendor/Export2Zip.js +24 -0
- package/template/src/views/charts/keyboard.vue +23 -0
- package/template/src/views/charts/line.vue +23 -0
- package/template/src/views/charts/mix-chart.vue +23 -0
- package/template/src/views/clipboard/index.vue +49 -0
- package/template/src/views/components-demo/avatar-upload.vue +61 -0
- package/template/src/views/components-demo/back-to-top.vue +154 -0
- package/template/src/views/components-demo/count-to.vue +218 -0
- package/template/src/views/components-demo/dnd-list.vue +39 -0
- package/template/src/views/components-demo/drag-dialog.vue +61 -0
- package/template/src/views/components-demo/drag-kanban.vue +66 -0
- package/template/src/views/components-demo/drag-select.vue +43 -0
- package/template/src/views/components-demo/dropzone.vue +31 -0
- package/template/src/views/components-demo/json-editor.vue +36 -0
- package/template/src/views/components-demo/markdown.vue +101 -0
- package/template/src/views/components-demo/mixin.vue +169 -0
- package/template/src/views/components-demo/split-pane.vue +67 -0
- package/template/src/views/components-demo/sticky.vue +135 -0
- package/template/src/views/components-demo/tinymce.vue +36 -0
- package/template/src/views/dashboard/admin/components/BarChart.vue +102 -0
- package/template/src/views/dashboard/admin/components/BoxCard.vue +118 -0
- package/template/src/views/dashboard/admin/components/LineChart.vue +135 -0
- package/template/src/views/dashboard/admin/components/PanelGroup.vue +181 -0
- package/template/src/views/dashboard/admin/components/PieChart.vue +79 -0
- package/template/src/views/dashboard/admin/components/RaddarChart.vue +116 -0
- package/template/src/views/dashboard/admin/components/TodoList/Todo.vue +81 -0
- package/template/src/views/dashboard/admin/components/TodoList/index.scss +320 -0
- package/template/src/views/dashboard/admin/components/TodoList/index.vue +127 -0
- package/template/src/views/dashboard/admin/components/TransactionTable.vue +55 -0
- package/template/src/views/dashboard/admin/components/mixins/resize.js +55 -0
- package/template/src/views/dashboard/admin/index.vue +124 -0
- package/template/src/views/dashboard/editor/index.vue +74 -0
- package/template/src/views/dashboard/index.vue +31 -0
- package/template/src/views/documentation/index.vue +56 -0
- package/template/src/views/error-log/components/ErrorTestA.vue +13 -0
- package/template/src/views/error-log/components/ErrorTestB.vue +11 -0
- package/template/src/views/error-log/index.vue +32 -0
- package/template/src/views/error-page/401.vue +99 -0
- package/template/src/views/error-page/404.vue +228 -0
- package/template/src/views/example/components/ArticleDetail.vue +289 -0
- package/template/src/views/example/components/Dropdown/Comment.vue +41 -0
- package/template/src/views/example/components/Dropdown/Platform.vue +46 -0
- package/template/src/views/example/components/Dropdown/SourceUrl.vue +38 -0
- package/template/src/views/example/components/Dropdown/index.js +3 -0
- package/template/src/views/example/components/Warning.vue +13 -0
- package/template/src/views/example/create.vue +13 -0
- package/template/src/views/example/edit.vue +13 -0
- package/template/src/views/example/list.vue +112 -0
- package/template/src/views/excel/components/AutoWidthOption.vue +34 -0
- package/template/src/views/excel/components/BookTypeOption.vue +39 -0
- package/template/src/views/excel/components/FilenameOption.vue +27 -0
- package/template/src/views/excel/export-excel.vue +116 -0
- package/template/src/views/excel/merge-header.vue +101 -0
- package/template/src/views/excel/select-excel.vue +107 -0
- package/template/src/views/excel/upload-excel.vue +42 -0
- package/template/src/views/guide/index.vue +36 -0
- package/template/src/views/guide/steps.js +53 -0
- package/template/src/views/icons/element-icons.js +3 -0
- package/template/src/views/icons/index.vue +101 -0
- package/template/src/views/icons/svg-icons.js +10 -0
- package/template/src/views/login/auth-redirect.vue +15 -0
- package/template/src/views/login/components/SocialSignin.vue +72 -0
- package/template/src/views/login/index.vue +324 -0
- package/template/src/views/nested/menu1/index.vue +7 -0
- package/template/src/views/nested/menu1/menu1-1/index.vue +7 -0
- package/template/src/views/nested/menu1/menu1-2/index.vue +7 -0
- package/template/src/views/nested/menu1/menu1-2/menu1-2-1/index.vue +5 -0
- package/template/src/views/nested/menu1/menu1-2/menu1-2-2/index.vue +5 -0
- package/template/src/views/nested/menu1/menu1-3/index.vue +5 -0
- package/template/src/views/nested/menu2/index.vue +5 -0
- package/template/src/views/pdf/content.js +58 -0
- package/template/src/views/pdf/download.vue +201 -0
- package/template/src/views/pdf/index.vue +13 -0
- package/template/src/views/permission/components/SwitchRoles.vue +32 -0
- package/template/src/views/permission/directive.vue +111 -0
- package/template/src/views/permission/page.vue +19 -0
- package/template/src/views/permission/role.vue +270 -0
- package/template/src/views/profile/components/Account.vue +38 -0
- package/template/src/views/profile/components/Activity.vue +185 -0
- package/template/src/views/profile/components/Timeline.vue +43 -0
- package/template/src/views/profile/components/UserCard.vue +134 -0
- package/template/src/views/profile/index.vue +68 -0
- package/template/src/views/qiniu/upload.vue +41 -0
- package/template/src/views/redirect/index.vue +12 -0
- package/template/src/views/tab/components/TabPane.vue +103 -0
- package/template/src/views/tab/index.vue +57 -0
- package/template/src/views/table/complex-table.vue +379 -0
- package/template/src/views/table/drag-table.vue +153 -0
- package/template/src/views/table/dynamic-table/components/FixedThead.vue +62 -0
- package/template/src/views/table/dynamic-table/components/UnfixedThead.vue +50 -0
- package/template/src/views/table/dynamic-table/index.vue +24 -0
- package/template/src/views/table/inline-edit-table.vue +149 -0
- package/template/src/views/theme/index.vue +120 -0
- package/template/src/views/zip/index.vue +77 -0
- package/template/tests/unit/.eslintrc.js +5 -0
- package/template/tests/unit/components/Hamburger.spec.js +18 -0
- package/template/tests/unit/components/SvgIcon.spec.js +22 -0
- package/template/tests/unit/utils/formatTime.spec.js +29 -0
- package/template/tests/unit/utils/param2Obj.spec.js +14 -0
- package/template/tests/unit/utils/parseTime.spec.js +37 -0
- package/template/tests/unit/utils/validate.spec.js +28 -0
- package/template/vue.config.js +125 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// global transition css
|
|
2
|
+
|
|
3
|
+
/* fade */
|
|
4
|
+
.fade-enter-active,
|
|
5
|
+
.fade-leave-active {
|
|
6
|
+
transition: opacity 0.28s;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.fade-enter,
|
|
10
|
+
.fade-leave-active {
|
|
11
|
+
opacity: 0;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/* fade-transform */
|
|
15
|
+
.fade-transform-leave-active,
|
|
16
|
+
.fade-transform-enter-active {
|
|
17
|
+
transition: all .5s;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.fade-transform-enter {
|
|
21
|
+
opacity: 0;
|
|
22
|
+
transform: translateX(-30px);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.fade-transform-leave-to {
|
|
26
|
+
opacity: 0;
|
|
27
|
+
transform: translateX(30px);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* breadcrumb transition */
|
|
31
|
+
.breadcrumb-enter-active,
|
|
32
|
+
.breadcrumb-leave-active {
|
|
33
|
+
transition: all .5s;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.breadcrumb-enter,
|
|
37
|
+
.breadcrumb-leave-active {
|
|
38
|
+
opacity: 0;
|
|
39
|
+
transform: translateX(20px);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.breadcrumb-move {
|
|
43
|
+
transition: all .5s;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.breadcrumb-leave-active {
|
|
47
|
+
position: absolute;
|
|
48
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// base color
|
|
2
|
+
$blue:#324157;
|
|
3
|
+
$light-blue:#3A71A8;
|
|
4
|
+
$red:#C03639;
|
|
5
|
+
$pink: #E65D6E;
|
|
6
|
+
$green: #30B08F;
|
|
7
|
+
$tiffany: #4AB7BD;
|
|
8
|
+
$yellow:#FEC171;
|
|
9
|
+
$panGreen: #30B08F;
|
|
10
|
+
|
|
11
|
+
// sidebar
|
|
12
|
+
$menuText:#bfcbd9;
|
|
13
|
+
$menuActiveText:#409EFF;
|
|
14
|
+
$subMenuActiveText:#f4f4f5; // https://github.com/ElemeFE/element/issues/12951
|
|
15
|
+
|
|
16
|
+
$menuBg:#304156;
|
|
17
|
+
$menuHover:#263445;
|
|
18
|
+
|
|
19
|
+
$subMenuBg:#1f2d3d;
|
|
20
|
+
$subMenuHover:#001528;
|
|
21
|
+
|
|
22
|
+
$sideBarWidth: 210px;
|
|
23
|
+
|
|
24
|
+
// the :export directive is the magic sauce for webpack
|
|
25
|
+
// https://www.bluematador.com/blog/how-to-share-variables-between-js-and-sass
|
|
26
|
+
:export {
|
|
27
|
+
menuText: $menuText;
|
|
28
|
+
menuActiveText: $menuActiveText;
|
|
29
|
+
subMenuActiveText: $subMenuActiveText;
|
|
30
|
+
menuBg: $menuBg;
|
|
31
|
+
menuHover: $menuHover;
|
|
32
|
+
subMenuBg: $subMenuBg;
|
|
33
|
+
subMenuHover: $subMenuHover;
|
|
34
|
+
sideBarWidth: $sideBarWidth;
|
|
35
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import Cookies from 'js-cookie'
|
|
2
|
+
|
|
3
|
+
const TokenKey = 'Admin-Token'
|
|
4
|
+
|
|
5
|
+
export function getToken() {
|
|
6
|
+
return Cookies.get(TokenKey)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function setToken(token) {
|
|
10
|
+
return Cookies.set(TokenKey, token)
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function removeToken() {
|
|
14
|
+
return Cookies.remove(TokenKey)
|
|
15
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import Vue from 'vue'
|
|
2
|
+
import Clipboard from 'clipboard'
|
|
3
|
+
|
|
4
|
+
function clipboardSuccess() {
|
|
5
|
+
Vue.prototype.$message({
|
|
6
|
+
message: 'Copy successfully',
|
|
7
|
+
type: 'success',
|
|
8
|
+
duration: 1500
|
|
9
|
+
})
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function clipboardError() {
|
|
13
|
+
Vue.prototype.$message({
|
|
14
|
+
message: 'Copy failed',
|
|
15
|
+
type: 'error'
|
|
16
|
+
})
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default function handleClipboard(text, event) {
|
|
20
|
+
const clipboard = new Clipboard(event.target, {
|
|
21
|
+
text: () => text
|
|
22
|
+
})
|
|
23
|
+
clipboard.on('success', () => {
|
|
24
|
+
clipboardSuccess()
|
|
25
|
+
clipboard.destroy()
|
|
26
|
+
})
|
|
27
|
+
clipboard.on('error', () => {
|
|
28
|
+
clipboardError()
|
|
29
|
+
clipboard.destroy()
|
|
30
|
+
})
|
|
31
|
+
clipboard.onClick(event)
|
|
32
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import Vue from 'vue'
|
|
2
|
+
import store from '@/store'
|
|
3
|
+
import { isString, isArray } from '@/utils/validate'
|
|
4
|
+
import settings from '@/settings'
|
|
5
|
+
|
|
6
|
+
// you can set in settings.js
|
|
7
|
+
// errorLog:'production' | ['production', 'development']
|
|
8
|
+
const { errorLog: needErrorLog } = settings
|
|
9
|
+
|
|
10
|
+
function checkNeed() {
|
|
11
|
+
const env = process.env.NODE_ENV
|
|
12
|
+
if (isString(needErrorLog)) {
|
|
13
|
+
return env === needErrorLog
|
|
14
|
+
}
|
|
15
|
+
if (isArray(needErrorLog)) {
|
|
16
|
+
return needErrorLog.includes(env)
|
|
17
|
+
}
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (checkNeed()) {
|
|
22
|
+
Vue.config.errorHandler = function(err, vm, info, a) {
|
|
23
|
+
// Don't ask me why I use Vue.nextTick, it just a hack.
|
|
24
|
+
// detail see https://forum.vuejs.org/t/dispatch-in-vue-config-errorhandler-has-some-problem/23500
|
|
25
|
+
Vue.nextTick(() => {
|
|
26
|
+
store.dispatch('errorLog/addErrorLog', {
|
|
27
|
+
err,
|
|
28
|
+
vm,
|
|
29
|
+
info,
|
|
30
|
+
url: window.location.href
|
|
31
|
+
})
|
|
32
|
+
console.error(err, info)
|
|
33
|
+
})
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Created by PanJiaChen on 16/11/18.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Parse the time to string
|
|
7
|
+
* @param {(Object|string|number)} time
|
|
8
|
+
* @param {string} cFormat
|
|
9
|
+
* @returns {string | null}
|
|
10
|
+
*/
|
|
11
|
+
export function parseTime(time, cFormat) {
|
|
12
|
+
if (arguments.length === 0 || !time) {
|
|
13
|
+
return null
|
|
14
|
+
}
|
|
15
|
+
const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
|
|
16
|
+
let date
|
|
17
|
+
if (typeof time === 'object') {
|
|
18
|
+
date = time
|
|
19
|
+
} else {
|
|
20
|
+
if ((typeof time === 'string')) {
|
|
21
|
+
if ((/^[0-9]+$/.test(time))) {
|
|
22
|
+
// support "1548221490638"
|
|
23
|
+
time = parseInt(time)
|
|
24
|
+
} else {
|
|
25
|
+
// support safari
|
|
26
|
+
// https://stackoverflow.com/questions/4310953/invalid-date-in-safari
|
|
27
|
+
time = time.replace(new RegExp(/-/gm), '/')
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if ((typeof time === 'number') && (time.toString().length === 10)) {
|
|
32
|
+
time = time * 1000
|
|
33
|
+
}
|
|
34
|
+
date = new Date(time)
|
|
35
|
+
}
|
|
36
|
+
const formatObj = {
|
|
37
|
+
y: date.getFullYear(),
|
|
38
|
+
m: date.getMonth() + 1,
|
|
39
|
+
d: date.getDate(),
|
|
40
|
+
h: date.getHours(),
|
|
41
|
+
i: date.getMinutes(),
|
|
42
|
+
s: date.getSeconds(),
|
|
43
|
+
a: date.getDay()
|
|
44
|
+
}
|
|
45
|
+
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
|
|
46
|
+
const value = formatObj[key]
|
|
47
|
+
// Note: getDay() returns 0 on Sunday
|
|
48
|
+
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
|
|
49
|
+
return value.toString().padStart(2, '0')
|
|
50
|
+
})
|
|
51
|
+
return time_str
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {number} time
|
|
56
|
+
* @param {string} option
|
|
57
|
+
* @returns {string}
|
|
58
|
+
*/
|
|
59
|
+
export function formatTime(time, option) {
|
|
60
|
+
if (('' + time).length === 10) {
|
|
61
|
+
time = parseInt(time) * 1000
|
|
62
|
+
} else {
|
|
63
|
+
time = +time
|
|
64
|
+
}
|
|
65
|
+
const d = new Date(time)
|
|
66
|
+
const now = Date.now()
|
|
67
|
+
|
|
68
|
+
const diff = (now - d) / 1000
|
|
69
|
+
|
|
70
|
+
if (diff < 30) {
|
|
71
|
+
return '刚刚'
|
|
72
|
+
} else if (diff < 3600) {
|
|
73
|
+
// less 1 hour
|
|
74
|
+
return Math.ceil(diff / 60) + '分钟前'
|
|
75
|
+
} else if (diff < 3600 * 24) {
|
|
76
|
+
return Math.ceil(diff / 3600) + '小时前'
|
|
77
|
+
} else if (diff < 3600 * 24 * 2) {
|
|
78
|
+
return '1天前'
|
|
79
|
+
}
|
|
80
|
+
if (option) {
|
|
81
|
+
return parseTime(time, option)
|
|
82
|
+
} else {
|
|
83
|
+
return (
|
|
84
|
+
d.getMonth() +
|
|
85
|
+
1 +
|
|
86
|
+
'月' +
|
|
87
|
+
d.getDate() +
|
|
88
|
+
'日' +
|
|
89
|
+
d.getHours() +
|
|
90
|
+
'时' +
|
|
91
|
+
d.getMinutes() +
|
|
92
|
+
'分'
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {string} url
|
|
99
|
+
* @returns {Object}
|
|
100
|
+
*/
|
|
101
|
+
export function getQueryObject(url) {
|
|
102
|
+
url = url == null ? window.location.href : url
|
|
103
|
+
const search = url.substring(url.lastIndexOf('?') + 1)
|
|
104
|
+
const obj = {}
|
|
105
|
+
const reg = /([^?&=]+)=([^?&=]*)/g
|
|
106
|
+
search.replace(reg, (rs, $1, $2) => {
|
|
107
|
+
const name = decodeURIComponent($1)
|
|
108
|
+
let val = decodeURIComponent($2)
|
|
109
|
+
val = String(val)
|
|
110
|
+
obj[name] = val
|
|
111
|
+
return rs
|
|
112
|
+
})
|
|
113
|
+
return obj
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* @param {string} input value
|
|
118
|
+
* @returns {number} output value
|
|
119
|
+
*/
|
|
120
|
+
export function byteLength(str) {
|
|
121
|
+
// returns the byte length of an utf8 string
|
|
122
|
+
let s = str.length
|
|
123
|
+
for (var i = str.length - 1; i >= 0; i--) {
|
|
124
|
+
const code = str.charCodeAt(i)
|
|
125
|
+
if (code > 0x7f && code <= 0x7ff) s++
|
|
126
|
+
else if (code > 0x7ff && code <= 0xffff) s += 2
|
|
127
|
+
if (code >= 0xDC00 && code <= 0xDFFF) i--
|
|
128
|
+
}
|
|
129
|
+
return s
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* @param {Array} actual
|
|
134
|
+
* @returns {Array}
|
|
135
|
+
*/
|
|
136
|
+
export function cleanArray(actual) {
|
|
137
|
+
const newArray = []
|
|
138
|
+
for (let i = 0; i < actual.length; i++) {
|
|
139
|
+
if (actual[i]) {
|
|
140
|
+
newArray.push(actual[i])
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return newArray
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @param {Object} json
|
|
148
|
+
* @returns {Array}
|
|
149
|
+
*/
|
|
150
|
+
export function param(json) {
|
|
151
|
+
if (!json) return ''
|
|
152
|
+
return cleanArray(
|
|
153
|
+
Object.keys(json).map(key => {
|
|
154
|
+
if (json[key] === undefined) return ''
|
|
155
|
+
return encodeURIComponent(key) + '=' + encodeURIComponent(json[key])
|
|
156
|
+
})
|
|
157
|
+
).join('&')
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @param {string} url
|
|
162
|
+
* @returns {Object}
|
|
163
|
+
*/
|
|
164
|
+
export function param2Obj(url) {
|
|
165
|
+
const search = decodeURIComponent(url.split('?')[1]).replace(/\+/g, ' ')
|
|
166
|
+
if (!search) {
|
|
167
|
+
return {}
|
|
168
|
+
}
|
|
169
|
+
const obj = {}
|
|
170
|
+
const searchArr = search.split('&')
|
|
171
|
+
searchArr.forEach(v => {
|
|
172
|
+
const index = v.indexOf('=')
|
|
173
|
+
if (index !== -1) {
|
|
174
|
+
const name = v.substring(0, index)
|
|
175
|
+
const val = v.substring(index + 1, v.length)
|
|
176
|
+
obj[name] = val
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
return obj
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* @param {string} val
|
|
184
|
+
* @returns {string}
|
|
185
|
+
*/
|
|
186
|
+
export function html2Text(val) {
|
|
187
|
+
const div = document.createElement('div')
|
|
188
|
+
div.innerHTML = val
|
|
189
|
+
return div.textContent || div.innerText
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Merges two objects, giving the last one precedence
|
|
194
|
+
* @param {Object} target
|
|
195
|
+
* @param {(Object|Array)} source
|
|
196
|
+
* @returns {Object}
|
|
197
|
+
*/
|
|
198
|
+
export function objectMerge(target, source) {
|
|
199
|
+
if (typeof target !== 'object') {
|
|
200
|
+
target = {}
|
|
201
|
+
}
|
|
202
|
+
if (Array.isArray(source)) {
|
|
203
|
+
return source.slice()
|
|
204
|
+
}
|
|
205
|
+
Object.keys(source).forEach(property => {
|
|
206
|
+
const sourceProperty = source[property]
|
|
207
|
+
if (typeof sourceProperty === 'object') {
|
|
208
|
+
target[property] = objectMerge(target[property], sourceProperty)
|
|
209
|
+
} else {
|
|
210
|
+
target[property] = sourceProperty
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
return target
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* @param {HTMLElement} element
|
|
218
|
+
* @param {string} className
|
|
219
|
+
*/
|
|
220
|
+
export function toggleClass(element, className) {
|
|
221
|
+
if (!element || !className) {
|
|
222
|
+
return
|
|
223
|
+
}
|
|
224
|
+
let classString = element.className
|
|
225
|
+
const nameIndex = classString.indexOf(className)
|
|
226
|
+
if (nameIndex === -1) {
|
|
227
|
+
classString += '' + className
|
|
228
|
+
} else {
|
|
229
|
+
classString =
|
|
230
|
+
classString.substr(0, nameIndex) +
|
|
231
|
+
classString.substr(nameIndex + className.length)
|
|
232
|
+
}
|
|
233
|
+
element.className = classString
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* @param {string} type
|
|
238
|
+
* @returns {Date}
|
|
239
|
+
*/
|
|
240
|
+
export function getTime(type) {
|
|
241
|
+
if (type === 'start') {
|
|
242
|
+
return new Date().getTime() - 3600 * 1000 * 24 * 90
|
|
243
|
+
} else {
|
|
244
|
+
return new Date(new Date().toDateString())
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* @param {Function} func
|
|
250
|
+
* @param {number} wait
|
|
251
|
+
* @param {boolean} immediate
|
|
252
|
+
* @return {*}
|
|
253
|
+
*/
|
|
254
|
+
export function debounce(func, wait, immediate) {
|
|
255
|
+
let timeout, args, context, timestamp, result
|
|
256
|
+
|
|
257
|
+
const later = function() {
|
|
258
|
+
// 据上一次触发时间间隔
|
|
259
|
+
const last = +new Date() - timestamp
|
|
260
|
+
|
|
261
|
+
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
|
|
262
|
+
if (last < wait && last > 0) {
|
|
263
|
+
timeout = setTimeout(later, wait - last)
|
|
264
|
+
} else {
|
|
265
|
+
timeout = null
|
|
266
|
+
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
|
|
267
|
+
if (!immediate) {
|
|
268
|
+
result = func.apply(context, args)
|
|
269
|
+
if (!timeout) context = args = null
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return function(...args) {
|
|
275
|
+
context = this
|
|
276
|
+
timestamp = +new Date()
|
|
277
|
+
const callNow = immediate && !timeout
|
|
278
|
+
// 如果延时不存在,重新设定延时
|
|
279
|
+
if (!timeout) timeout = setTimeout(later, wait)
|
|
280
|
+
if (callNow) {
|
|
281
|
+
result = func.apply(context, args)
|
|
282
|
+
context = args = null
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return result
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* This is just a simple version of deep copy
|
|
291
|
+
* Has a lot of edge cases bug
|
|
292
|
+
* If you want to use a perfect deep copy, use lodash's _.cloneDeep
|
|
293
|
+
* @param {Object} source
|
|
294
|
+
* @returns {Object}
|
|
295
|
+
*/
|
|
296
|
+
export function deepClone(source) {
|
|
297
|
+
if (!source && typeof source !== 'object') {
|
|
298
|
+
throw new Error('error arguments', 'deepClone')
|
|
299
|
+
}
|
|
300
|
+
const targetObj = source.constructor === Array ? [] : {}
|
|
301
|
+
Object.keys(source).forEach(keys => {
|
|
302
|
+
if (source[keys] && typeof source[keys] === 'object') {
|
|
303
|
+
targetObj[keys] = deepClone(source[keys])
|
|
304
|
+
} else {
|
|
305
|
+
targetObj[keys] = source[keys]
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
return targetObj
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/**
|
|
312
|
+
* @param {Array} arr
|
|
313
|
+
* @returns {Array}
|
|
314
|
+
*/
|
|
315
|
+
export function uniqueArr(arr) {
|
|
316
|
+
return Array.from(new Set(arr))
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* @returns {string}
|
|
321
|
+
*/
|
|
322
|
+
export function createUniqueString() {
|
|
323
|
+
const timestamp = +new Date() + ''
|
|
324
|
+
const randomNum = parseInt((1 + Math.random()) * 65536) + ''
|
|
325
|
+
return (+(randomNum + timestamp)).toString(32)
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Check if an element has a class
|
|
330
|
+
* @param {HTMLElement} elm
|
|
331
|
+
* @param {string} cls
|
|
332
|
+
* @returns {boolean}
|
|
333
|
+
*/
|
|
334
|
+
export function hasClass(ele, cls) {
|
|
335
|
+
return !!ele.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'))
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Add class to element
|
|
340
|
+
* @param {HTMLElement} elm
|
|
341
|
+
* @param {string} cls
|
|
342
|
+
*/
|
|
343
|
+
export function addClass(ele, cls) {
|
|
344
|
+
if (!hasClass(ele, cls)) ele.className += ' ' + cls
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Remove class from element
|
|
349
|
+
* @param {HTMLElement} elm
|
|
350
|
+
* @param {string} cls
|
|
351
|
+
*/
|
|
352
|
+
export function removeClass(ele, cls) {
|
|
353
|
+
if (hasClass(ele, cls)) {
|
|
354
|
+
const reg = new RegExp('(\\s|^)' + cls + '(\\s|$)')
|
|
355
|
+
ele.className = ele.className.replace(reg, ' ')
|
|
356
|
+
}
|
|
357
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*Created by PanJiaChen on 16/11/29.
|
|
3
|
+
* @param {Sting} url
|
|
4
|
+
* @param {Sting} title
|
|
5
|
+
* @param {Number} w
|
|
6
|
+
* @param {Number} h
|
|
7
|
+
*/
|
|
8
|
+
export default function openWindow(url, title, w, h) {
|
|
9
|
+
// Fixes dual-screen position Most browsers Firefox
|
|
10
|
+
const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left
|
|
11
|
+
const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top
|
|
12
|
+
|
|
13
|
+
const width = window.innerWidth ? window.innerWidth : document.documentElement.clientWidth ? document.documentElement.clientWidth : screen.width
|
|
14
|
+
const height = window.innerHeight ? window.innerHeight : document.documentElement.clientHeight ? document.documentElement.clientHeight : screen.height
|
|
15
|
+
|
|
16
|
+
const left = ((width / 2) - (w / 2)) + dualScreenLeft
|
|
17
|
+
const top = ((height / 2) - (h / 2)) + dualScreenTop
|
|
18
|
+
const newWindow = window.open(url, title, 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=yes, copyhistory=no, width=' + w + ', height=' + h + ', top=' + top + ', left=' + left)
|
|
19
|
+
|
|
20
|
+
// Puts focus on the newWindow
|
|
21
|
+
if (window.focus) {
|
|
22
|
+
newWindow.focus()
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import store from '@/store'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {Array} value
|
|
5
|
+
* @returns {Boolean}
|
|
6
|
+
* @example see @/views/permission/directive.vue
|
|
7
|
+
*/
|
|
8
|
+
export default function checkPermission(value) {
|
|
9
|
+
if (value && value instanceof Array && value.length > 0) {
|
|
10
|
+
const roles = store.getters && store.getters.roles
|
|
11
|
+
const permissionRoles = value
|
|
12
|
+
|
|
13
|
+
const hasPermission = roles.some(role => {
|
|
14
|
+
return permissionRoles.includes(role)
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
if (!hasPermission) {
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
return true
|
|
21
|
+
} else {
|
|
22
|
+
console.error(`need roles! Like v-permission="['admin','editor']"`)
|
|
23
|
+
return false
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import axios from 'axios'
|
|
2
|
+
import { MessageBox, Message } from 'element-ui'
|
|
3
|
+
import store from '@/store'
|
|
4
|
+
import { getToken } from '@/utils/auth'
|
|
5
|
+
|
|
6
|
+
// create an axios instance
|
|
7
|
+
const service = axios.create({
|
|
8
|
+
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
|
|
9
|
+
// withCredentials: true, // send cookies when cross-domain requests
|
|
10
|
+
timeout: 5000 // request timeout
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
// request interceptor
|
|
14
|
+
service.interceptors.request.use(
|
|
15
|
+
config => {
|
|
16
|
+
// do something before request is sent
|
|
17
|
+
|
|
18
|
+
if (store.getters.token) {
|
|
19
|
+
// let each request carry token
|
|
20
|
+
// ['X-Token'] is a custom headers key
|
|
21
|
+
// please modify it according to the actual situation
|
|
22
|
+
config.headers['X-Token'] = getToken()
|
|
23
|
+
}
|
|
24
|
+
return config
|
|
25
|
+
},
|
|
26
|
+
error => {
|
|
27
|
+
// do something with request error
|
|
28
|
+
console.log(error) // for debug
|
|
29
|
+
return Promise.reject(error)
|
|
30
|
+
}
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
// response interceptor
|
|
34
|
+
service.interceptors.response.use(
|
|
35
|
+
/**
|
|
36
|
+
* If you want to get http information such as headers or status
|
|
37
|
+
* Please return response => response
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Determine the request status by custom code
|
|
42
|
+
* Here is just an example
|
|
43
|
+
* You can also judge the status by HTTP Status Code
|
|
44
|
+
*/
|
|
45
|
+
response => {
|
|
46
|
+
const res = response.data
|
|
47
|
+
|
|
48
|
+
// if the custom code is not 20000, it is judged as an error.
|
|
49
|
+
if (res.code !== 20000) {
|
|
50
|
+
Message({
|
|
51
|
+
message: res.message || 'Error',
|
|
52
|
+
type: 'error',
|
|
53
|
+
duration: 5 * 1000
|
|
54
|
+
})
|
|
55
|
+
|
|
56
|
+
// 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
|
|
57
|
+
if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
|
|
58
|
+
// to re-login
|
|
59
|
+
MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
|
|
60
|
+
confirmButtonText: 'Re-Login',
|
|
61
|
+
cancelButtonText: 'Cancel',
|
|
62
|
+
type: 'warning'
|
|
63
|
+
}).then(() => {
|
|
64
|
+
store.dispatch('user/resetToken').then(() => {
|
|
65
|
+
location.reload()
|
|
66
|
+
})
|
|
67
|
+
})
|
|
68
|
+
}
|
|
69
|
+
return Promise.reject(new Error(res.message || 'Error'))
|
|
70
|
+
} else {
|
|
71
|
+
return res
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
error => {
|
|
75
|
+
console.log('err' + error) // for debug
|
|
76
|
+
Message({
|
|
77
|
+
message: error.message,
|
|
78
|
+
type: 'error',
|
|
79
|
+
duration: 5 * 1000
|
|
80
|
+
})
|
|
81
|
+
return Promise.reject(error)
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
export default service
|