zetan-cli-dev-template-vue-element-admin 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/package.json +8 -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 +228 -0
- package/template/README.ja.md +224 -0
- package/template/README.md +250 -0
- package/template/README.zh-CN.md +273 -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 +247 -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 +21 -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 +57 -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 +124 -0
@@ -0,0 +1,149 @@
|
|
1
|
+
<template>
|
2
|
+
<div class="app-container">
|
3
|
+
<el-table v-loading="listLoading" :data="list" border fit highlight-current-row style="width: 100%">
|
4
|
+
<el-table-column align="center" label="ID" width="80">
|
5
|
+
<template slot-scope="{row}">
|
6
|
+
<span>{{ row.id }}</span>
|
7
|
+
</template>
|
8
|
+
</el-table-column>
|
9
|
+
|
10
|
+
<el-table-column width="180px" align="center" label="Date">
|
11
|
+
<template slot-scope="{row}">
|
12
|
+
<span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
|
13
|
+
</template>
|
14
|
+
</el-table-column>
|
15
|
+
|
16
|
+
<el-table-column width="120px" align="center" label="Author">
|
17
|
+
<template slot-scope="{row}">
|
18
|
+
<span>{{ row.author }}</span>
|
19
|
+
</template>
|
20
|
+
</el-table-column>
|
21
|
+
|
22
|
+
<el-table-column width="100px" label="Importance">
|
23
|
+
<template slot-scope="{row}">
|
24
|
+
<svg-icon v-for="n in + row.importance" :key="n" icon-class="star" class="meta-item__icon" />
|
25
|
+
</template>
|
26
|
+
</el-table-column>
|
27
|
+
|
28
|
+
<el-table-column class-name="status-col" label="Status" width="110">
|
29
|
+
<template slot-scope="{row}">
|
30
|
+
<el-tag :type="row.status | statusFilter">
|
31
|
+
{{ row.status }}
|
32
|
+
</el-tag>
|
33
|
+
</template>
|
34
|
+
</el-table-column>
|
35
|
+
|
36
|
+
<el-table-column min-width="300px" label="Title">
|
37
|
+
<template slot-scope="{row}">
|
38
|
+
<template v-if="row.edit">
|
39
|
+
<el-input v-model="row.title" class="edit-input" size="small" />
|
40
|
+
<el-button
|
41
|
+
class="cancel-btn"
|
42
|
+
size="small"
|
43
|
+
icon="el-icon-refresh"
|
44
|
+
type="warning"
|
45
|
+
@click="cancelEdit(row)"
|
46
|
+
>
|
47
|
+
cancel
|
48
|
+
</el-button>
|
49
|
+
</template>
|
50
|
+
<span v-else>{{ row.title }}</span>
|
51
|
+
</template>
|
52
|
+
</el-table-column>
|
53
|
+
|
54
|
+
<el-table-column align="center" label="Actions" width="120">
|
55
|
+
<template slot-scope="{row}">
|
56
|
+
<el-button
|
57
|
+
v-if="row.edit"
|
58
|
+
type="success"
|
59
|
+
size="small"
|
60
|
+
icon="el-icon-circle-check-outline"
|
61
|
+
@click="confirmEdit(row)"
|
62
|
+
>
|
63
|
+
Ok
|
64
|
+
</el-button>
|
65
|
+
<el-button
|
66
|
+
v-else
|
67
|
+
type="primary"
|
68
|
+
size="small"
|
69
|
+
icon="el-icon-edit"
|
70
|
+
@click="row.edit=!row.edit"
|
71
|
+
>
|
72
|
+
Edit
|
73
|
+
</el-button>
|
74
|
+
</template>
|
75
|
+
</el-table-column>
|
76
|
+
</el-table>
|
77
|
+
</div>
|
78
|
+
</template>
|
79
|
+
|
80
|
+
<script>
|
81
|
+
import { fetchList } from '@/api/article'
|
82
|
+
|
83
|
+
export default {
|
84
|
+
name: 'InlineEditTable',
|
85
|
+
filters: {
|
86
|
+
statusFilter(status) {
|
87
|
+
const statusMap = {
|
88
|
+
published: 'success',
|
89
|
+
draft: 'info',
|
90
|
+
deleted: 'danger'
|
91
|
+
}
|
92
|
+
return statusMap[status]
|
93
|
+
}
|
94
|
+
},
|
95
|
+
data() {
|
96
|
+
return {
|
97
|
+
list: null,
|
98
|
+
listLoading: true,
|
99
|
+
listQuery: {
|
100
|
+
page: 1,
|
101
|
+
limit: 10
|
102
|
+
}
|
103
|
+
}
|
104
|
+
},
|
105
|
+
created() {
|
106
|
+
this.getList()
|
107
|
+
},
|
108
|
+
methods: {
|
109
|
+
async getList() {
|
110
|
+
this.listLoading = true
|
111
|
+
const { data } = await fetchList(this.listQuery)
|
112
|
+
const items = data.items
|
113
|
+
this.list = items.map(v => {
|
114
|
+
this.$set(v, 'edit', false) // https://vuejs.org/v2/guide/reactivity.html
|
115
|
+
v.originalTitle = v.title // will be used when user click the cancel botton
|
116
|
+
return v
|
117
|
+
})
|
118
|
+
this.listLoading = false
|
119
|
+
},
|
120
|
+
cancelEdit(row) {
|
121
|
+
row.title = row.originalTitle
|
122
|
+
row.edit = false
|
123
|
+
this.$message({
|
124
|
+
message: 'The title has been restored to the original value',
|
125
|
+
type: 'warning'
|
126
|
+
})
|
127
|
+
},
|
128
|
+
confirmEdit(row) {
|
129
|
+
row.edit = false
|
130
|
+
row.originalTitle = row.title
|
131
|
+
this.$message({
|
132
|
+
message: 'The title has been edited',
|
133
|
+
type: 'success'
|
134
|
+
})
|
135
|
+
}
|
136
|
+
}
|
137
|
+
}
|
138
|
+
</script>
|
139
|
+
|
140
|
+
<style scoped>
|
141
|
+
.edit-input {
|
142
|
+
padding-right: 100px;
|
143
|
+
}
|
144
|
+
.cancel-btn {
|
145
|
+
position: absolute;
|
146
|
+
right: 15px;
|
147
|
+
top: 10px;
|
148
|
+
}
|
149
|
+
</style>
|
@@ -0,0 +1,120 @@
|
|
1
|
+
<template>
|
2
|
+
<div class="app-container">
|
3
|
+
<el-card class="box-card">
|
4
|
+
<div slot="header">
|
5
|
+
<a class="link-type link-title" target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/guide/advanced/theme.html">
|
6
|
+
Theme documentation
|
7
|
+
</a>
|
8
|
+
</div>
|
9
|
+
<div class="box-item">
|
10
|
+
<span class="field-label">Change Theme : </span>
|
11
|
+
<el-switch v-model="theme" />
|
12
|
+
<aside style="margin-top:15px;">
|
13
|
+
Tips: It is different from the theme-pick on the navbar is two different skinning methods, each with different application scenarios. Refer to the documentation for details.
|
14
|
+
</aside>
|
15
|
+
</div>
|
16
|
+
</el-card>
|
17
|
+
|
18
|
+
<div class="block">
|
19
|
+
<el-button type="primary">
|
20
|
+
Primary
|
21
|
+
</el-button>
|
22
|
+
<el-button type="success">
|
23
|
+
Success
|
24
|
+
</el-button>
|
25
|
+
<el-button type="info">
|
26
|
+
Info
|
27
|
+
</el-button>
|
28
|
+
<el-button type="warning">
|
29
|
+
Warning
|
30
|
+
</el-button>
|
31
|
+
<el-button type="danger">
|
32
|
+
Danger
|
33
|
+
</el-button>
|
34
|
+
</div>
|
35
|
+
|
36
|
+
<div class="block">
|
37
|
+
<el-button type="primary" icon="el-icon-edit" />
|
38
|
+
<el-button type="primary" icon="el-icon-share" />
|
39
|
+
<el-button type="primary" icon="el-icon-delete" />
|
40
|
+
<el-button type="primary" icon="el-icon-search">
|
41
|
+
Search
|
42
|
+
</el-button>
|
43
|
+
<el-button type="primary">
|
44
|
+
Upload
|
45
|
+
<i class="el-icon-upload el-icon-right" />
|
46
|
+
</el-button>
|
47
|
+
</div>
|
48
|
+
|
49
|
+
<div class="block">
|
50
|
+
<el-tag v-for="tag in tags" :key="tag.type" :type="tag.type" class="tag-item">
|
51
|
+
{{ tag.name }}
|
52
|
+
</el-tag>
|
53
|
+
</div>
|
54
|
+
|
55
|
+
<div class="block">
|
56
|
+
<el-radio-group v-model="radio">
|
57
|
+
<el-radio :label="3">
|
58
|
+
Option A
|
59
|
+
</el-radio>
|
60
|
+
<el-radio :label="6">
|
61
|
+
Option B
|
62
|
+
</el-radio>
|
63
|
+
<el-radio :label="9">
|
64
|
+
Option C
|
65
|
+
</el-radio>
|
66
|
+
</el-radio-group>
|
67
|
+
</div>
|
68
|
+
|
69
|
+
<div class="block">
|
70
|
+
<el-slider v-model="slideValue" />
|
71
|
+
</div>
|
72
|
+
</div>
|
73
|
+
</template>
|
74
|
+
|
75
|
+
<script>
|
76
|
+
import { toggleClass } from '@/utils'
|
77
|
+
import '@/assets/custom-theme/index.css' // the theme changed version element-ui css
|
78
|
+
|
79
|
+
export default {
|
80
|
+
name: 'Theme',
|
81
|
+
data() {
|
82
|
+
return {
|
83
|
+
theme: false,
|
84
|
+
tags: [
|
85
|
+
{ name: 'Tag One', type: '' },
|
86
|
+
{ name: 'Tag Two', type: 'info' },
|
87
|
+
{ name: 'Tag Three', type: 'success' },
|
88
|
+
{ name: 'Tag Four', type: 'warning' },
|
89
|
+
{ name: 'Tag Five', type: 'danger' }
|
90
|
+
],
|
91
|
+
slideValue: 50,
|
92
|
+
radio: 3
|
93
|
+
}
|
94
|
+
},
|
95
|
+
watch: {
|
96
|
+
theme() {
|
97
|
+
toggleClass(document.body, 'custom-theme')
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}
|
101
|
+
</script>
|
102
|
+
|
103
|
+
<style scoped>
|
104
|
+
.field-label{
|
105
|
+
vertical-align: middle;
|
106
|
+
}
|
107
|
+
.box-card {
|
108
|
+
width: 400px;
|
109
|
+
max-width: 100%;
|
110
|
+
margin: 20px auto;
|
111
|
+
}
|
112
|
+
|
113
|
+
.block {
|
114
|
+
padding: 30px 24px;
|
115
|
+
}
|
116
|
+
|
117
|
+
.tag-item {
|
118
|
+
margin-right: 15px;
|
119
|
+
}
|
120
|
+
</style>
|
@@ -0,0 +1,77 @@
|
|
1
|
+
<template>
|
2
|
+
<div class="app-container">
|
3
|
+
<el-input v-model="filename" placeholder="Please enter the file name (default file)" style="width:300px;" prefix-icon="el-icon-document" />
|
4
|
+
<el-button :loading="downloadLoading" style="margin-bottom:20px;" type="primary" icon="el-icon-document" @click="handleDownload">
|
5
|
+
Export Zip
|
6
|
+
</el-button>
|
7
|
+
<el-table v-loading="listLoading" :data="list" element-loading-text="拼命加载中" border fit highlight-current-row>
|
8
|
+
<el-table-column align="center" label="ID" width="95">
|
9
|
+
<template slot-scope="scope">
|
10
|
+
{{ scope.$index }}
|
11
|
+
</template>
|
12
|
+
</el-table-column>
|
13
|
+
<el-table-column label="Title">
|
14
|
+
<template slot-scope="scope">
|
15
|
+
{{ scope.row.title }}
|
16
|
+
</template>
|
17
|
+
</el-table-column>
|
18
|
+
<el-table-column label="Author" width="95" align="center">
|
19
|
+
<template slot-scope="scope">
|
20
|
+
<el-tag>{{ scope.row.author }}</el-tag>
|
21
|
+
</template>
|
22
|
+
</el-table-column>
|
23
|
+
<el-table-column label="Readings" width="115" align="center">
|
24
|
+
<template slot-scope="scope">
|
25
|
+
{{ scope.row.pageviews }}
|
26
|
+
</template>
|
27
|
+
</el-table-column>
|
28
|
+
<el-table-column align="center" label="Date" width="220">
|
29
|
+
<template slot-scope="scope">
|
30
|
+
<i class="el-icon-time" />
|
31
|
+
<span>{{ scope.row.display_time }}</span>
|
32
|
+
</template>
|
33
|
+
</el-table-column>
|
34
|
+
</el-table>
|
35
|
+
</div>
|
36
|
+
</template>
|
37
|
+
|
38
|
+
<script>
|
39
|
+
import { fetchList } from '@/api/article'
|
40
|
+
|
41
|
+
export default {
|
42
|
+
name: 'ExportZip',
|
43
|
+
data() {
|
44
|
+
return {
|
45
|
+
list: null,
|
46
|
+
listLoading: true,
|
47
|
+
downloadLoading: false,
|
48
|
+
filename: ''
|
49
|
+
}
|
50
|
+
},
|
51
|
+
created() {
|
52
|
+
this.fetchData()
|
53
|
+
},
|
54
|
+
methods: {
|
55
|
+
async fetchData() {
|
56
|
+
this.listLoading = true
|
57
|
+
const { data } = await fetchList()
|
58
|
+
this.list = data.items
|
59
|
+
this.listLoading = false
|
60
|
+
},
|
61
|
+
handleDownload() {
|
62
|
+
this.downloadLoading = true
|
63
|
+
import('@/vendor/Export2Zip').then(zip => {
|
64
|
+
const tHeader = ['Id', 'Title', 'Author', 'Readings', 'Date']
|
65
|
+
const filterVal = ['id', 'title', 'author', 'pageviews', 'display_time']
|
66
|
+
const list = this.list
|
67
|
+
const data = this.formatJson(filterVal, list)
|
68
|
+
zip.export_txt_to_zip(tHeader, data, this.filename, this.filename)
|
69
|
+
this.downloadLoading = false
|
70
|
+
})
|
71
|
+
},
|
72
|
+
formatJson(filterVal, jsonData) {
|
73
|
+
return jsonData.map(v => filterVal.map(j => v[j]))
|
74
|
+
}
|
75
|
+
}
|
76
|
+
}
|
77
|
+
</script>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { shallowMount } from '@vue/test-utils'
|
2
|
+
import Hamburger from '@/components/Hamburger/index.vue'
|
3
|
+
describe('Hamburger.vue', () => {
|
4
|
+
it('toggle click', () => {
|
5
|
+
const wrapper = shallowMount(Hamburger)
|
6
|
+
const mockFn = jest.fn()
|
7
|
+
wrapper.vm.$on('toggleClick', mockFn)
|
8
|
+
wrapper.find('.hamburger').trigger('click')
|
9
|
+
expect(mockFn).toBeCalled()
|
10
|
+
})
|
11
|
+
it('prop isActive', () => {
|
12
|
+
const wrapper = shallowMount(Hamburger)
|
13
|
+
wrapper.setProps({ isActive: true })
|
14
|
+
expect(wrapper.contains('.is-active')).toBe(true)
|
15
|
+
wrapper.setProps({ isActive: false })
|
16
|
+
expect(wrapper.contains('.is-active')).toBe(false)
|
17
|
+
})
|
18
|
+
})
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import { shallowMount } from '@vue/test-utils'
|
2
|
+
import SvgIcon from '@/components/SvgIcon/index.vue'
|
3
|
+
describe('SvgIcon.vue', () => {
|
4
|
+
it('iconClass', () => {
|
5
|
+
const wrapper = shallowMount(SvgIcon, {
|
6
|
+
propsData: {
|
7
|
+
iconClass: 'test'
|
8
|
+
}
|
9
|
+
})
|
10
|
+
expect(wrapper.find('use').attributes().href).toBe('#icon-test')
|
11
|
+
})
|
12
|
+
it('className', () => {
|
13
|
+
const wrapper = shallowMount(SvgIcon, {
|
14
|
+
propsData: {
|
15
|
+
iconClass: 'test'
|
16
|
+
}
|
17
|
+
})
|
18
|
+
expect(wrapper.classes().length).toBe(1)
|
19
|
+
wrapper.setProps({ className: 'test' })
|
20
|
+
expect(wrapper.classes().includes('test')).toBe(true)
|
21
|
+
})
|
22
|
+
})
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import { formatTime } from '@/utils/index.js'
|
2
|
+
describe('Utils:formatTime', () => {
|
3
|
+
const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01"
|
4
|
+
const retrofit = 5 * 1000
|
5
|
+
|
6
|
+
it('ten digits timestamp', () => {
|
7
|
+
expect(formatTime((d / 1000).toFixed(0))).toBe('7月13日17时54分')
|
8
|
+
})
|
9
|
+
it('test now', () => {
|
10
|
+
expect(formatTime(+new Date() - 1)).toBe('刚刚')
|
11
|
+
})
|
12
|
+
it('less two minute', () => {
|
13
|
+
expect(formatTime(+new Date() - 60 * 2 * 1000 + retrofit)).toBe('2分钟前')
|
14
|
+
})
|
15
|
+
it('less two hour', () => {
|
16
|
+
expect(formatTime(+new Date() - 60 * 60 * 2 * 1000 + retrofit)).toBe('2小时前')
|
17
|
+
})
|
18
|
+
it('less one day', () => {
|
19
|
+
expect(formatTime(+new Date() - 60 * 60 * 24 * 1 * 1000)).toBe('1天前')
|
20
|
+
})
|
21
|
+
it('more than one day', () => {
|
22
|
+
expect(formatTime(d)).toBe('7月13日17时54分')
|
23
|
+
})
|
24
|
+
it('format', () => {
|
25
|
+
expect(formatTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54')
|
26
|
+
expect(formatTime(d, '{y}-{m}-{d}')).toBe('2018-07-13')
|
27
|
+
expect(formatTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54')
|
28
|
+
})
|
29
|
+
})
|
@@ -0,0 +1,14 @@
|
|
1
|
+
import { param2Obj } from '@/utils/index.js'
|
2
|
+
describe('Utils:param2Obj', () => {
|
3
|
+
const url = 'https://github.com/PanJiaChen/vue-element-admin?name=bill&age=29&sex=1&field=dGVzdA==&key=%E6%B5%8B%E8%AF%95'
|
4
|
+
|
5
|
+
it('param2Obj test', () => {
|
6
|
+
expect(param2Obj(url)).toEqual({
|
7
|
+
name: 'bill',
|
8
|
+
age: '29',
|
9
|
+
sex: '1',
|
10
|
+
field: window.btoa('test'),
|
11
|
+
key: '测试'
|
12
|
+
})
|
13
|
+
})
|
14
|
+
})
|
@@ -0,0 +1,37 @@
|
|
1
|
+
import { parseTime } from '@/utils/index.js'
|
2
|
+
|
3
|
+
describe('Utils:parseTime', () => {
|
4
|
+
const d = new Date('2018-07-13 17:54:01') // "2018-07-13 17:54:01"
|
5
|
+
it('timestamp', () => {
|
6
|
+
expect(parseTime(d)).toBe('2018-07-13 17:54:01')
|
7
|
+
})
|
8
|
+
|
9
|
+
it('timestamp string', () => {
|
10
|
+
expect(parseTime((d + ''))).toBe('2018-07-13 17:54:01')
|
11
|
+
})
|
12
|
+
|
13
|
+
it('ten digits timestamp', () => {
|
14
|
+
expect(parseTime((d / 1000).toFixed(0))).toBe('2018-07-13 17:54:01')
|
15
|
+
})
|
16
|
+
it('new Date', () => {
|
17
|
+
expect(parseTime(new Date(d))).toBe('2018-07-13 17:54:01')
|
18
|
+
})
|
19
|
+
it('format', () => {
|
20
|
+
expect(parseTime(d, '{y}-{m}-{d} {h}:{i}')).toBe('2018-07-13 17:54')
|
21
|
+
expect(parseTime(d, '{y}-{m}-{d}')).toBe('2018-07-13')
|
22
|
+
expect(parseTime(d, '{y}/{m}/{d} {h}-{i}')).toBe('2018/07/13 17-54')
|
23
|
+
})
|
24
|
+
it('get the day of the week', () => {
|
25
|
+
expect(parseTime(d, '{a}')).toBe('五') // 星期五
|
26
|
+
})
|
27
|
+
it('get the day of the week', () => {
|
28
|
+
expect(parseTime(+d + 1000 * 60 * 60 * 24 * 2, '{a}')).toBe('日') // 星期日
|
29
|
+
})
|
30
|
+
it('empty argument', () => {
|
31
|
+
expect(parseTime()).toBeNull()
|
32
|
+
})
|
33
|
+
|
34
|
+
it('null', () => {
|
35
|
+
expect(parseTime(null)).toBeNull()
|
36
|
+
})
|
37
|
+
})
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import { validUsername, validURL, validLowerCase, validUpperCase, validAlphabets } from '@/utils/validate.js'
|
2
|
+
describe('Utils:validate', () => {
|
3
|
+
it('validUsername', () => {
|
4
|
+
expect(validUsername('admin')).toBe(true)
|
5
|
+
expect(validUsername('editor')).toBe(true)
|
6
|
+
expect(validUsername('xxxx')).toBe(false)
|
7
|
+
})
|
8
|
+
it('validURL', () => {
|
9
|
+
expect(validURL('https://github.com/PanJiaChen/vue-element-admin')).toBe(true)
|
10
|
+
expect(validURL('http://github.com/PanJiaChen/vue-element-admin')).toBe(true)
|
11
|
+
expect(validURL('github.com/PanJiaChen/vue-element-admin')).toBe(false)
|
12
|
+
})
|
13
|
+
it('validLowerCase', () => {
|
14
|
+
expect(validLowerCase('abc')).toBe(true)
|
15
|
+
expect(validLowerCase('Abc')).toBe(false)
|
16
|
+
expect(validLowerCase('123abc')).toBe(false)
|
17
|
+
})
|
18
|
+
it('validUpperCase', () => {
|
19
|
+
expect(validUpperCase('ABC')).toBe(true)
|
20
|
+
expect(validUpperCase('Abc')).toBe(false)
|
21
|
+
expect(validUpperCase('123ABC')).toBe(false)
|
22
|
+
})
|
23
|
+
it('validAlphabets', () => {
|
24
|
+
expect(validAlphabets('ABC')).toBe(true)
|
25
|
+
expect(validAlphabets('Abc')).toBe(true)
|
26
|
+
expect(validAlphabets('123aBC')).toBe(false)
|
27
|
+
})
|
28
|
+
})
|
@@ -0,0 +1,124 @@
|
|
1
|
+
'use strict'
|
2
|
+
const path = require('path')
|
3
|
+
const defaultSettings = require('./src/settings.js')
|
4
|
+
|
5
|
+
function resolve(dir) {
|
6
|
+
return path.join(__dirname, dir)
|
7
|
+
}
|
8
|
+
|
9
|
+
const name = defaultSettings.title || 'vue Element Admin' // page title
|
10
|
+
|
11
|
+
// If your port is set to 80,
|
12
|
+
// use administrator privileges to execute the command line.
|
13
|
+
// For example, Mac: sudo npm run
|
14
|
+
// You can change the port by the following method:
|
15
|
+
// port = 9527 npm run dev OR npm run dev --port = 9527
|
16
|
+
const port = process.env.port || process.env.npm_config_port || 9527 // dev port
|
17
|
+
|
18
|
+
// All configuration item explanations can be find in https://cli.vuejs.org/config/
|
19
|
+
module.exports = {
|
20
|
+
/**
|
21
|
+
* You will need to set publicPath if you plan to deploy your site under a sub path,
|
22
|
+
* for example GitHub Pages. If you plan to deploy your site to https://foo.github.io/bar/,
|
23
|
+
* then publicPath should be set to "/bar/".
|
24
|
+
* In most cases please use '/' !!!
|
25
|
+
* Detail: https://cli.vuejs.org/config/#publicpath
|
26
|
+
*/
|
27
|
+
publicPath: '/',
|
28
|
+
outputDir: 'dist',
|
29
|
+
assetsDir: 'static',
|
30
|
+
lintOnSave: process.env.NODE_ENV === 'development',
|
31
|
+
productionSourceMap: false,
|
32
|
+
devServer: {
|
33
|
+
port: port,
|
34
|
+
open: true,
|
35
|
+
overlay: {
|
36
|
+
warnings: false,
|
37
|
+
errors: true
|
38
|
+
},
|
39
|
+
before: require('./mock/mock-server.js')
|
40
|
+
},
|
41
|
+
configureWebpack: {
|
42
|
+
// provide the app's title in webpack's name field, so that
|
43
|
+
// it can be accessed in index.html to inject the correct title.
|
44
|
+
name: name,
|
45
|
+
resolve: {
|
46
|
+
alias: {
|
47
|
+
'@': resolve('src')
|
48
|
+
}
|
49
|
+
}
|
50
|
+
},
|
51
|
+
chainWebpack(config) {
|
52
|
+
// it can improve the speed of the first screen, it is recommended to turn on preload
|
53
|
+
// it can improve the speed of the first screen, it is recommended to turn on preload
|
54
|
+
config.plugin('preload').tap(() => [
|
55
|
+
{
|
56
|
+
rel: 'preload',
|
57
|
+
// to ignore runtime.js
|
58
|
+
// https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/cli-service/lib/config/app.js#L171
|
59
|
+
fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
|
60
|
+
include: 'initial'
|
61
|
+
}
|
62
|
+
])
|
63
|
+
|
64
|
+
// when there are many pages, it will cause too many meaningless requests
|
65
|
+
config.plugins.delete('prefetch')
|
66
|
+
|
67
|
+
// set svg-sprite-loader
|
68
|
+
config.module
|
69
|
+
.rule('svg')
|
70
|
+
.exclude.add(resolve('src/icons'))
|
71
|
+
.end()
|
72
|
+
config.module
|
73
|
+
.rule('icons')
|
74
|
+
.test(/\.svg$/)
|
75
|
+
.include.add(resolve('src/icons'))
|
76
|
+
.end()
|
77
|
+
.use('svg-sprite-loader')
|
78
|
+
.loader('svg-sprite-loader')
|
79
|
+
.options({
|
80
|
+
symbolId: 'icon-[name]'
|
81
|
+
})
|
82
|
+
.end()
|
83
|
+
|
84
|
+
config
|
85
|
+
.when(process.env.NODE_ENV !== 'development',
|
86
|
+
config => {
|
87
|
+
config
|
88
|
+
.plugin('ScriptExtHtmlWebpackPlugin')
|
89
|
+
.after('html')
|
90
|
+
.use('script-ext-html-webpack-plugin', [{
|
91
|
+
// `runtime` must same as runtimeChunk name. default is `runtime`
|
92
|
+
inline: /runtime\..*\.js$/
|
93
|
+
}])
|
94
|
+
.end()
|
95
|
+
config
|
96
|
+
.optimization.splitChunks({
|
97
|
+
chunks: 'all',
|
98
|
+
cacheGroups: {
|
99
|
+
libs: {
|
100
|
+
name: 'chunk-libs',
|
101
|
+
test: /[\\/]node_modules[\\/]/,
|
102
|
+
priority: 10,
|
103
|
+
chunks: 'initial' // only package third parties that are initially dependent
|
104
|
+
},
|
105
|
+
elementUI: {
|
106
|
+
name: 'chunk-elementUI', // split elementUI into a single package
|
107
|
+
priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
|
108
|
+
test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
|
109
|
+
},
|
110
|
+
commons: {
|
111
|
+
name: 'chunk-commons',
|
112
|
+
test: resolve('src/components'), // can customize your rules
|
113
|
+
minChunks: 3, // minimum common number
|
114
|
+
priority: 5,
|
115
|
+
reuseExistingChunk: true
|
116
|
+
}
|
117
|
+
}
|
118
|
+
})
|
119
|
+
// https:// webpack.js.org/configuration/optimization/#optimizationruntimechunk
|
120
|
+
config.optimization.runtimeChunk('single')
|
121
|
+
}
|
122
|
+
)
|
123
|
+
}
|
124
|
+
}
|