@@ -28,7 +28,7 @@
import draggable from 'vuedraggable'
export default {
- name: 'twoDndList',
+ name: 'DndList',
components: { draggable },
computed: {
filterList2() {
@@ -97,7 +97,7 @@ export default {
diff --git a/src/components/Hamburger/index.vue b/src/components/Hamburger/index.vue
index 6ec90362..fb6aeacd 100644
--- a/src/components/Hamburger/index.vue
+++ b/src/components/Hamburger/index.vue
@@ -1,15 +1,15 @@
-
+
diff --git a/src/components/ImageCropper/index.vue b/src/components/ImageCropper/index.vue
index 1e5c28b2..3e09d0a9 100644
--- a/src/components/ImageCropper/index.vue
+++ b/src/components/ImageCropper/index.vue
@@ -105,7 +105,7 @@
diff --git a/src/components/ScrollBar/index.vue b/src/components/ScrollBar/index.vue
new file mode 100644
index 00000000..5c8d21cd
--- /dev/null
+++ b/src/components/ScrollBar/index.vue
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
diff --git a/src/components/ScrollPane/index.vue b/src/components/ScrollPane/index.vue
new file mode 100644
index 00000000..a786ec32
--- /dev/null
+++ b/src/components/ScrollPane/index.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
diff --git a/src/components/Share/dropdownMenu.vue b/src/components/Share/dropdownMenu.vue
new file mode 100644
index 00000000..13cab547
--- /dev/null
+++ b/src/components/Share/dropdownMenu.vue
@@ -0,0 +1,97 @@
+
+
+
+
+
+
+
diff --git a/src/components/SplitPane/Pane.vue b/src/components/SplitPane/Pane.vue
deleted file mode 100644
index d13d1286..00000000
--- a/src/components/SplitPane/Pane.vue
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/src/components/SplitPane/Resizer.vue b/src/components/SplitPane/Resizer.vue
deleted file mode 100644
index 07b6fb3b..00000000
--- a/src/components/SplitPane/Resizer.vue
+++ /dev/null
@@ -1,72 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/components/SplitPane/index.vue b/src/components/SplitPane/index.vue
deleted file mode 100644
index 477405b6..00000000
--- a/src/components/SplitPane/index.vue
+++ /dev/null
@@ -1,111 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/components/SvgIcon/index.vue b/src/components/SvgIcon/index.vue
new file mode 100644
index 00000000..e331a27e
--- /dev/null
+++ b/src/components/SvgIcon/index.vue
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
diff --git a/src/components/TextHoverEffect/Mallki.vue b/src/components/TextHoverEffect/Mallki.vue
new file mode 100644
index 00000000..7e975dc8
--- /dev/null
+++ b/src/components/TextHoverEffect/Mallki.vue
@@ -0,0 +1,113 @@
+
+
+ {{text}}
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ThemePicker/index.vue b/src/components/ThemePicker/index.vue
new file mode 100644
index 00000000..25766330
--- /dev/null
+++ b/src/components/ThemePicker/index.vue
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
diff --git a/src/components/Tinymce/components/editorImage.vue b/src/components/Tinymce/components/editorImage.vue
index f390c134..b0347cf8 100644
--- a/src/components/Tinymce/components/editorImage.vue
+++ b/src/components/Tinymce/components/editorImage.vue
@@ -1,25 +1,18 @@
-
- 上传图片
-
-
-
- 点击上传
-
- 取 消
- 确 定
-
-
+
+ 上传图片
+
+
+
+ 点击上传
+
+ 取 消
+ 确 定
+
+
+
diff --git a/src/directive/sticky.js b/src/directive/sticky.js
index d7da0891..bc234660 100644
--- a/src/directive/sticky.js
+++ b/src/directive/sticky.js
@@ -10,12 +10,12 @@ vueSticky.install = Vue => {
elStyle.position = '-webkit-sticky'
elStyle.position = 'sticky'
- // if the browser support css sticky(Currently Safari, Firefox and Chrome Canary)
- // if (~elStyle.position.indexOf('sticky')) {
- // elStyle.top = `${stickyTop}px`;
- // elStyle.zIndex = zIndex;
- // return
- // }
+ // if the browser support css sticky(Currently Safari, Firefox and Chrome Canary)
+ // if (~elStyle.position.indexOf('sticky')) {
+ // elStyle.top = `${stickyTop}px`;
+ // elStyle.zIndex = zIndex;
+ // return
+ // }
const elHeight = el.getBoundingClientRect().height
const elWidth = el.getBoundingClientRect().width
elStyle.cssText = `top: ${stickyTop}px; z-index: ${zIndex}`
diff --git a/src/filters/index.js b/src/filters/index.js
index 15334cb9..285a314b 100644
--- a/src/filters/index.js
+++ b/src/filters/index.js
@@ -4,6 +4,7 @@ function pluralize(time, label) {
}
return time + label + 's'
}
+
export function timeAgo(time) {
const between = Date.now() / 1000 - Number(time)
if (between < 3600) {
@@ -77,12 +78,12 @@ export function formatTime(time, option) {
/* 数字 格式化*/
export function nFormatter(num, digits) {
const si = [
- { value: 1E18, symbol: 'E' },
- { value: 1E15, symbol: 'P' },
- { value: 1E12, symbol: 'T' },
- { value: 1E9, symbol: 'G' },
- { value: 1E6, symbol: 'M' },
- { value: 1E3, symbol: 'k' }
+ { value: 1E18, symbol: 'E' },
+ { value: 1E15, symbol: 'P' },
+ { value: 1E12, symbol: 'T' },
+ { value: 1E9, symbol: 'G' },
+ { value: 1E6, symbol: 'M' },
+ { value: 1E3, symbol: 'k' }
]
for (let i = 0; i < si.length; i++) {
if (num >= si[i].value) {
diff --git a/src/icons/index.js b/src/icons/index.js
index c8e36b9b..2d689240 100644
--- a/src/icons/index.js
+++ b/src/icons/index.js
@@ -1,12 +1,12 @@
import Vue from 'vue'
-import IconSvg from '@/components/Icon-svg'// svg组件
-import generateIconsView from '@/views/svg-icons/generateIconsView.js'// just for views/icons , you can delete it
-// register globally
+import SvgIcon from '@/components/SvgIcon'// svg组件
+import generateIconsView from '@/views/svg-icons/generateIconsView.js'// just for @/views/icons , you can delete it
-Vue.component('icon-svg', IconSvg)
+// register globally
+Vue.component('svg-icon', SvgIcon)
const requireAll = requireContext => requireContext.keys().map(requireContext)
const req = require.context('./svg', false, /\.svg$/)
const iconMap = requireAll(req)
-generateIconsView.generate(iconMap) // just for views/icons , you can delete it
+generateIconsView.generate(iconMap) // just for @/views/icons , you can delete it
diff --git a/src/icons/svg/dashboard.svg b/src/icons/svg/dashboard.svg
new file mode 100644
index 00000000..bee42507
--- /dev/null
+++ b/src/icons/svg/dashboard.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/documentation.svg b/src/icons/svg/documentation.svg
new file mode 100644
index 00000000..caf68ddb
--- /dev/null
+++ b/src/icons/svg/documentation.svg
@@ -0,0 +1 @@
+
diff --git a/src/icons/svg/international.svg b/src/icons/svg/international.svg
new file mode 100644
index 00000000..6912767d
--- /dev/null
+++ b/src/icons/svg/international.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/language.svg b/src/icons/svg/language.svg
new file mode 100644
index 00000000..2baf7431
--- /dev/null
+++ b/src/icons/svg/language.svg
@@ -0,0 +1 @@
+
diff --git a/src/icons/svg/message.svg b/src/icons/svg/message.svg
new file mode 100644
index 00000000..d807b002
--- /dev/null
+++ b/src/icons/svg/message.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/money.svg b/src/icons/svg/money.svg
new file mode 100644
index 00000000..d4fcb9ca
--- /dev/null
+++ b/src/icons/svg/money.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/peoples.svg b/src/icons/svg/peoples.svg
new file mode 100644
index 00000000..2dccfcc0
--- /dev/null
+++ b/src/icons/svg/peoples.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/icons/svg/shoppingCard.svg b/src/icons/svg/shoppingCard.svg
new file mode 100644
index 00000000..cdebbdb4
--- /dev/null
+++ b/src/icons/svg/shoppingCard.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/lang/en.js b/src/lang/en.js
new file mode 100644
index 00000000..3986a2e5
--- /dev/null
+++ b/src/lang/en.js
@@ -0,0 +1,48 @@
+export default {
+ route: {
+ dashboard: 'Dashboard',
+ introduction: 'Introduction',
+ documentation: 'Documentation',
+ permission: 'Permission',
+ icons: 'Icons',
+ components: 'Components',
+ componentIndex: 'Introduction',
+ tinymce: 'Tinymce',
+ markdown: 'Markdown',
+ jsonEditor: 'JSON Editor',
+ dndList: 'Dnd List',
+ splitPane: 'SplitPane',
+ avatarUpload: 'Avatar Upload',
+ dropzone: 'Dropzone',
+ sticky: 'Sticky',
+ countTo: 'CountTo',
+ componentMixin: 'Mixin',
+ backToTop: 'BackToTop',
+ charts: 'Charts',
+ keyboardChart: 'Keyboard Chart',
+ lineChart: 'Line chart',
+ mixChart: 'Mix Chart',
+ example: 'Example',
+ Table: 'Table',
+ dynamicTable: 'Dynamic Table',
+ dragTable: 'Drag Table',
+ inlineEditTable: 'Inline Edit',
+ complexTable: 'Complex Table',
+ tab: 'Tab',
+ form: 'Form',
+ createForm: 'Create Form',
+ editForm: 'Edit Form',
+ errorPages: 'Error Pages',
+ page401: '401',
+ page404: '404',
+ errorLog: 'Error Log',
+ excel: 'Excel',
+ exportExcel: 'Export Excel',
+ selectExcel: 'Export Selected',
+ uploadExcel: 'Upload Excel',
+ exportZip: 'Zip',
+ theme: 'Theme',
+ clipboardDemo: 'Clipboard',
+ i18n: 'I18n'
+ }
+}
diff --git a/src/lang/index.js b/src/lang/index.js
new file mode 100644
index 00000000..12b9cacb
--- /dev/null
+++ b/src/lang/index.js
@@ -0,0 +1,27 @@
+import Vue from 'vue'
+import VueI18n from 'vue-i18n'
+import Cookies from 'js-cookie'
+import elementEnLocale from 'element-ui/lib/locale/lang/en' // element-ui lang
+import elementZhLocale from 'element-ui/lib/locale/lang/zh-CN'// element-ui lang
+import enLocale from './en'
+import zhLocale from './zh'
+
+Vue.use(VueI18n)
+
+const messages = {
+ en: {
+ ...enLocale,
+ ...elementEnLocale
+ },
+ zh: {
+ ...zhLocale,
+ ...elementZhLocale
+ }
+}
+
+const i18n = new VueI18n({
+ locale: Cookies.get('language') || 'zh', // set locale
+ messages // set locale messages
+})
+
+export default i18n
diff --git a/src/lang/zh.js b/src/lang/zh.js
new file mode 100644
index 00000000..e44d0cf0
--- /dev/null
+++ b/src/lang/zh.js
@@ -0,0 +1,48 @@
+export default {
+ route: {
+ dashboard: '首页',
+ introduction: '简述',
+ documentation: '文档',
+ permission: '权限测试页',
+ icons: '图标',
+ components: '组件',
+ componentIndex: '介绍',
+ tinymce: '富文本编辑器',
+ markdown: 'Markdown',
+ jsonEditor: 'JSON编辑器',
+ dndList: '列表拖拽',
+ splitPane: 'Splitpane',
+ avatarUpload: '头像上传',
+ dropzone: 'Dropzone',
+ sticky: 'Sticky',
+ countTo: 'CountTo',
+ componentMixin: '小组件',
+ backToTop: '返回顶部',
+ charts: '图表',
+ keyboardChart: '键盘图表',
+ lineChart: '折线图',
+ mixChart: '混合图表',
+ example: '综合实例',
+ Table: 'Table',
+ dynamicTable: '动态table',
+ dragTable: '拖拽table',
+ inlineEditTable: 'table内编辑',
+ complexTable: '综合table',
+ tab: 'Tab',
+ form: '表单',
+ createForm: '创建表单',
+ editForm: '编辑表单',
+ errorPages: '错误页面',
+ page401: '401',
+ page404: '404',
+ errorLog: '错误日志',
+ excel: 'excel',
+ exportExcel: 'export excel',
+ selectExcel: 'export selected',
+ uploadExcel: 'upload excel',
+ exportZip: 'zip',
+ theme: '换肤',
+ clipboardDemo: 'clipboard',
+ i18n: '国际化'
+ }
+}
diff --git a/src/main.js b/src/main.js
index 121aef26..1a63658e 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,6 +1,7 @@
import Vue from 'vue'
-import ElementUI from 'element-ui'
-import 'element-ui/lib/theme-default/index.css'
+import Element from 'element-ui'
+import 'element-ui/lib/theme-chalk/index.css'
+import i18n from './lang' // 国际化
import App from './App'
import router from './router'
import store from './store'
@@ -8,9 +9,11 @@ import * as filters from './filters' // 全局filter
import './icons' // icon
import './errorLog'// error log
import './permission' // 权限
-import './mock' // 该项目所有请求使用mockjs模拟
+import './mock' // 该项目所有请求使用mockjs模拟
-Vue.use(ElementUI)
+Vue.use(Element, {
+ i18n: (key, value) => i18n.t(key, value)
+})
// register global utility filters.
Object.keys(filters).forEach(key => {
@@ -23,6 +26,7 @@ new Vue({
el: '#app',
router,
store,
+ i18n,
template: '
',
components: { App }
})
diff --git a/src/mock/article.js b/src/mock/article.js
index f6ed1751..a42030ed 100644
--- a/src/mock/article.js
+++ b/src/mock/article.js
@@ -50,7 +50,7 @@ export default {
author: { key: 'mockPan' },
source_name: '原创作者',
category_item: [{ key: 'global', name: '全球' }],
- comment_disabled: false,
+ comment_disabled: true,
content: '
我是测试数据我是测试数据
"',
content_short: '我是测试数据',
display_time: +new Date(),
@@ -59,6 +59,6 @@ export default {
source_uri: 'https://github.com/PanJiaChen/vue-element-admin',
status: 'published',
tags: [],
- title: ''
+ title: 'vue-element-admin'
})
}
diff --git a/src/mock/index.js b/src/mock/index.js
index 15cea12b..c2fbb7f0 100644
--- a/src/mock/index.js
+++ b/src/mock/index.js
@@ -2,6 +2,7 @@ import Mock from 'mockjs'
import loginAPI from './login'
import articleAPI from './article'
import remoteSearchAPI from './remoteSearch'
+import transactionAPI from './transaction'
Mock.setup({
timeout: '350-600'
@@ -20,4 +21,7 @@ Mock.mock(/\/article\/pv/, 'get', articleAPI.getPv)
// 搜索相关
Mock.mock(/\/search\/user/, 'get', remoteSearchAPI.searchUser)
+// 账单相关
+Mock.mock(/\/transaction\/list/, 'get', transactionAPI.getList)
+
export default Mock
diff --git a/src/mock/login.js b/src/mock/login.js
index 5b00b503..8693ef98 100644
--- a/src/mock/login.js
+++ b/src/mock/login.js
@@ -14,13 +14,6 @@ const userMap = {
introduction: '我是编辑',
avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
name: 'Normal Editor'
- },
- developer: {
- role: ['develop'],
- token: 'develop',
- introduction: '我是开发',
- avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
- name: '工程师小王'
}
}
diff --git a/src/mock/transaction.js b/src/mock/transaction.js
new file mode 100644
index 00000000..a17517e4
--- /dev/null
+++ b/src/mock/transaction.js
@@ -0,0 +1,23 @@
+import Mock from 'mockjs'
+
+const List = []
+const count = 20
+
+for (let i = 0; i < count; i++) {
+ List.push(Mock.mock({
+ order_no: '@guid()',
+ timestamp: +Mock.Random.date('T'),
+ username: '@name()',
+ price: '@float(1000, 15000, 0, 2)',
+ 'status|1': ['success', 'pending']
+ }))
+}
+
+export default {
+ getList: () => {
+ return {
+ total: List.length,
+ items: List
+ }
+ }
+}
diff --git a/src/permission.js b/src/permission.js
index 2fcc4c9c..77c88e11 100644
--- a/src/permission.js
+++ b/src/permission.js
@@ -12,8 +12,8 @@ function hasPermission(roles, permissionRoles) {
return roles.some(role => permissionRoles.indexOf(role) >= 0)
}
-// register global progress.
const whiteList = ['/login', '/authredirect']// 不重定向白名单
+
router.beforeEach((to, from, next) => {
NProgress.start() // 开启Progress
if (getToken()) { // 判断是否有token
diff --git a/src/router/_import_development.js b/src/router/_import_development.js
index b0f53d2c..7c8b5e6b 100644
--- a/src/router/_import_development.js
+++ b/src/router/_import_development.js
@@ -1 +1 @@
-module.exports = file => require('@/views/' + file + '.vue').default // vue-loader at least v13.0.0+
+module.exports = file => require('@/views/' + file + '.vue').default // vue-loader at least v13.0.0+
diff --git a/src/router/index.js b/src/router/index.js
index f94f479b..26c47f4a 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -1,40 +1,51 @@
import Vue from 'vue'
import Router from 'vue-router'
const _import = require('./_import_' + process.env.NODE_ENV)
-// in development env not use Lazy Loading,because Lazy Loading too many pages will cause webpack hot update too slow.so only in production use Lazy Loading
+// in development-env not use lazy-loading, because lazy-loading too many pages will cause webpack hot update too slow. so only in production use lazy-loading;
+// detail: https://panjiachen.github.io/vue-element-admin-site/#/lazy-loading
Vue.use(Router)
-/* layout */
+/* Layout */
import Layout from '../views/layout/Layout'
/**
-* icon : the icon show in the sidebar
-* hidden : if `hidden:true` will not show in the sidebar
-* redirect : if `redirect:noredirect` will no redirct in the levelbar
-* noDropdown : if `noDropdown:true` will has no submenu
-* meta : { role: ['admin'] } will control the page role
+* hidden: true if `hidden:true` will not show in the sidebar(default is false)
+* redirect: noredirect if `redirect:noredirect` will no redirct in the breadcrumb
+* name:'router-name' the name is used by
(must set!!!)
+* meta : {
+ role: ['admin','editor'] will control the page role (you can set multiple roles)
+ title: 'title' the name show in submenu and breadcrumb (recommend set)
+ icon: 'svg-name' the icon show in the sidebar,
+ noCache: true if fasle ,the page will no be cached(default is false)
+ }
**/
export const constantRouterMap = [
- { path: '/login', component: _import('login/index'), hidden: true },
- { path: '/authredirect', component: _import('login/authredirect'), hidden: true },
- { path: '/404', component: _import('errorPage/404'), hidden: true },
- { path: '/401', component: _import('errorPage/401'), hidden: true },
+ { path: '/login', component: _import('login/index'), hidden: true },
+ { path: '/authredirect', component: _import('login/authredirect'), hidden: true },
+ { path: '/404', component: _import('errorPage/404'), hidden: true },
+ { path: '/401', component: _import('errorPage/401'), hidden: true },
{
- path: '/',
+ path: '',
component: Layout,
- redirect: '/dashboard',
- name: '首页',
- hidden: true,
- children: [{ path: 'dashboard', component: _import('dashboard/index') }]
+ redirect: 'dashboard',
+ children: [{
+ path: 'dashboard',
+ component: _import('dashboard/index'),
+ name: 'dashboard',
+ meta: { title: 'dashboard', icon: 'dashboard', noCache: true }
+ }]
},
{
- path: '/introduction',
+ path: '/documentation',
component: Layout,
- redirect: '/introduction/index',
- icon: 'people',
- noDropdown: true,
- children: [{ path: 'index', component: _import('introduction/index'), name: '简述' }]
+ redirect: '/documentation/index',
+ children: [{
+ path: 'index',
+ component: _import('documentation/index'),
+ name: 'documentation',
+ meta: { title: 'documentation', icon: 'documentation', noCache: true }
+ }]
}
]
@@ -49,137 +60,178 @@ export const asyncRouterMap = [
path: '/permission',
component: Layout,
redirect: '/permission/index',
- name: '权限测试',
- icon: 'lock',
meta: { role: ['admin'] },
- noDropdown: true,
- children: [{ path: 'index', component: _import('permission/index'), name: '权限测试页', meta: { role: ['admin'] }}]
+ children: [{
+ path: 'index',
+ component: _import('permission/index'),
+ name: 'permission',
+ meta: {
+ title: 'permission',
+ icon: 'lock',
+ role: ['admin']
+ }
+ }]
},
+
{
path: '/icon',
component: Layout,
- icon: 'icon',
- noDropdown: true,
- children: [{ path: 'index', component: _import('svg-icons/index'), name: 'icons' }]
+ children: [{
+ path: 'index',
+ component: _import('svg-icons/index'),
+ name: 'icons',
+ meta: { title: 'icons', icon: 'icon', noCache: true }
+ }]
},
+
{
path: '/components',
component: Layout,
- redirect: '/components/index',
- name: '组件',
- icon: 'component',
+ redirect: 'noredirect',
+ name: 'component-demo',
+ meta: {
+ title: 'components',
+ icon: 'component'
+ },
children: [
- { path: 'index', component: _import('components/index'), name: '介绍 ' },
- { path: 'tinymce', component: _import('components/tinymce'), name: '富文本编辑器' },
- { path: 'markdown', component: _import('components/markdown'), name: 'Markdown' },
- { path: 'jsoneditor', component: _import('components/jsonEditor'), name: 'JSON编辑器' },
- { path: 'dndlist', component: _import('components/dndList'), name: '列表拖拽' },
- { path: 'splitpane', component: _import('components/splitpane'), name: 'SplitPane' },
- { path: 'avatarupload', component: _import('components/avatarUpload'), name: '头像上传' },
- { path: 'dropzone', component: _import('components/dropzone'), name: 'Dropzone' },
- { path: 'sticky', component: _import('components/sticky'), name: 'Sticky' },
- { path: 'countto', component: _import('components/countTo'), name: 'CountTo' },
- { path: 'mixin', component: _import('components/mixin'), name: '小组件' },
- { path: 'backtotop', component: _import('components/backToTop'), name: '返回顶部' }
+ { path: 'tinymce', component: _import('components-demo/tinymce'), name: 'tinymce-demo', meta: { title: 'tinymce' }},
+ { path: 'markdown', component: _import('components-demo/markdown'), name: 'markdown-demo', meta: { title: 'markdown' }},
+ { path: 'json-editor', component: _import('components-demo/jsonEditor'), name: 'jsonEditor-demo', meta: { title: 'jsonEditor' }},
+ { path: 'dnd-list', component: _import('components-demo/dndList'), name: 'dndList-demo', meta: { title: 'dndList' }},
+ { path: 'splitpane', component: _import('components-demo/splitpane'), name: 'splitpane-demo', meta: { title: 'splitPane' }},
+ { path: 'avatar-upload', component: _import('components-demo/avatarUpload'), name: 'avatarUpload-demo', meta: { title: 'avatarUpload' }},
+ { path: 'dropzone', component: _import('components-demo/dropzone'), name: 'dropzone-demo', meta: { title: 'dropzone' }},
+ { path: 'sticky', component: _import('components-demo/sticky'), name: 'sticky-demo', meta: { title: 'sticky' }},
+ { path: 'count-to', component: _import('components-demo/countTo'), name: 'countTo-demo', meta: { title: 'countTo' }},
+ { path: 'mixin', component: _import('components-demo/mixin'), name: 'componentMixin-demo', meta: { title: 'componentMixin' }},
+ { path: 'back-to-top', component: _import('components-demo/backToTop'), name: 'backToTop-demo', meta: { title: 'backToTop' }}
]
},
+
{
path: '/charts',
component: Layout,
- redirect: '/charts/index',
- name: '图表',
- icon: 'chart',
+ redirect: 'noredirect',
+ name: 'charts',
+ meta: {
+ title: 'charts',
+ icon: 'chart'
+ },
children: [
- { path: 'index', component: _import('charts/index'), name: '介绍' },
- { path: 'keyboard', component: _import('charts/keyboard'), name: '键盘图表' },
- { path: 'keyboard2', component: _import('charts/keyboard2'), name: '键盘图表2' },
- { path: 'line', component: _import('charts/line'), name: '折线图' },
- { path: 'mixchart', component: _import('charts/mixChart'), name: '混合图表' }
+ { path: 'keyboard', component: _import('charts/keyboard'), name: 'keyboardChart', meta: { title: 'keyboardChart', noCache: true }},
+ { path: 'line', component: _import('charts/line'), name: 'lineChart', meta: { title: 'lineChart', noCache: true }},
+ { path: 'mixchart', component: _import('charts/mixChart'), name: 'mixChart', meta: { title: 'mixChart', noCache: true }}
]
},
+
{
path: '/example',
component: Layout,
- redirect: 'noredirect',
- name: '综合实例',
- icon: 'example',
+ redirect: '/example/table/complex-table',
+ name: 'example',
+ meta: {
+ title: 'example',
+ icon: 'example'
+ },
children: [
{
path: '/example/table',
component: _import('example/table/index'),
- redirect: '/example/table/table',
+ redirect: '/example/table/complex-table',
name: 'Table',
- icon: 'table',
+ meta: {
+ title: 'Table',
+ icon: 'table'
+ },
children: [
- { path: 'dynamictable', component: _import('example/table/dynamicTable/index'), name: '动态table' },
- { path: 'dragtable', component: _import('example/table/dragTable'), name: '拖拽table' },
- { path: 'inline_edit_table', component: _import('example/table/inlineEditTable'), name: 'table内编辑' },
- { path: 'table', component: _import('example/table/table'), name: '综合table' }
+ { path: 'dynamic-table', component: _import('example/table/dynamicTable/index'), name: 'dynamicTable', meta: { title: 'dynamicTable' }},
+ { path: 'drag-table', component: _import('example/table/dragTable'), name: 'dragTable', meta: { title: 'dragTable' }},
+ { path: 'inline-edit-table', component: _import('example/table/inlineEditTable'), name: 'inlineEditTable', meta: { title: 'inlineEditTable' }},
+ { path: 'complex-table', component: _import('example/table/complexTable'), name: 'complexTable', meta: { title: 'complexTable' }}
]
},
- { path: 'form/edit', icon: 'form', component: _import('example/form'), name: '编辑Form', meta: { isEdit: true }},
- { path: 'form/create', icon: 'form', component: _import('example/form'), name: '创建Form' },
- { path: 'tab/index', icon: 'tab', component: _import('example/tab/index'), name: 'Tab' }
+ { path: 'tab/index', icon: 'tab', component: _import('example/tab/index'), name: 'tab', meta: { title: 'tab' }}
]
},
+
+ {
+ path: '/form',
+ component: Layout,
+ redirect: 'noredirect',
+ name: 'form',
+ meta: {
+ title: 'form',
+ icon: 'form'
+ },
+ children: [
+ { path: 'create-form', component: _import('form/create'), name: 'createForm', meta: { title: 'createForm', icon: 'table' }},
+ { path: 'edit-form', component: _import('form/edit'), name: 'editForm', meta: { title: 'editForm', icon: 'table' }}
+ ]
+ },
+
{
path: '/error',
component: Layout,
redirect: 'noredirect',
- name: '错误页面',
- icon: '404',
+ name: 'errorPages',
+ meta: {
+ title: 'errorPages',
+ icon: '404'
+ },
children: [
- { path: '401', component: _import('errorPage/401'), name: '401' },
- { path: '404', component: _import('errorPage/404'), name: '404' }
+ { path: '401', component: _import('errorPage/401'), name: 'page401', meta: { title: 'page401', noCache: true }},
+ { path: '404', component: _import('errorPage/404'), name: 'page404', meta: { title: 'page404', noCache: true }}
]
},
+
{
- path: '/errlog',
+ path: '/error-log',
component: Layout,
redirect: 'noredirect',
- name: 'errlog',
- icon: 'bug',
- noDropdown: true,
- children: [{ path: 'log', component: _import('errlog/index'), name: '错误日志' }]
+ children: [{ path: 'log', component: _import('errorLog/index'), name: 'errorLog', meta: { title: 'errorLog', icon: 'bug' }}]
},
+
{
path: '/excel',
component: Layout,
- redirect: '/excel/download',
+ redirect: '/excel/export-excel',
name: 'excel',
- icon: 'excel',
+ meta: {
+ title: 'excel',
+ icon: 'excel'
+ },
children: [
- { path: 'download', component: _import('excel/index'), name: 'export excel' },
- { path: 'download2', component: _import('excel/selectExcel'), name: 'export selected' },
- { path: 'upload', component: _import('excel/uploadExcel'), name: 'upload excel' }
+ { path: 'export-excel', component: _import('excel/exportExcel'), name: 'exportExcel', meta: { title: 'exportExcel' }},
+ { path: 'export-selected-excel', component: _import('excel/selectExcel'), name: 'selectExcel', meta: { title: 'selectExcel' }},
+ { path: 'upload-excel', component: _import('excel/uploadExcel'), name: 'uploadExcel', meta: { title: 'uploadExcel' }}
]
},
+
{
path: '/zip',
component: Layout,
redirect: '/zip/download',
- name: 'zip',
- icon: 'zip',
- children: [
- { path: 'download', component: _import('zip/index'), name: 'export zip' }
- ]
+ children: [{ path: 'download', component: _import('zip/index'), name: 'exportZip', meta: { title: 'exportZip', icon: 'zip' }}]
},
+
{
path: '/theme',
component: Layout,
redirect: 'noredirect',
- name: 'theme',
- icon: 'theme',
- noDropdown: true,
- children: [{ path: 'index', component: _import('theme/index'), name: '换肤' }]
+ children: [{ path: 'index', component: _import('theme/index'), name: 'theme', meta: { title: 'theme', icon: 'theme' }}]
},
+
{
path: '/clipboard',
component: Layout,
redirect: 'noredirect',
- icon: 'clipboard',
- noDropdown: true,
- children: [{ path: 'index', component: _import('clipboard/index'), name: 'clipboard' }]
+ children: [{ path: 'index', component: _import('clipboard/index'), name: 'clipboardDemo', meta: { title: 'clipboardDemo', icon: 'clipboard' }}]
+ },
+
+ {
+ path: '/i18n',
+ component: Layout,
+ children: [{ path: 'index', component: _import('i18n-demo/index'), name: 'i18n', meta: { title: 'i18n', icon: 'international' }}]
},
{ path: '*', redirect: '/404', hidden: true }
diff --git a/src/store/getters.js b/src/store/getters.js
index 6d4c72d0..4acc4bbe 100644
--- a/src/store/getters.js
+++ b/src/store/getters.js
@@ -1,6 +1,8 @@
const getters = {
sidebar: state => state.app.sidebar,
+ language: state => state.app.language,
visitedViews: state => state.app.visitedViews,
+ cachedViews: state => state.app.cachedViews,
token: state => state.user.token,
avatar: state => state.user.avatar,
name: state => state.user.name,
diff --git a/src/store/modules/app.js b/src/store/modules/app.js
index 95cdf5f1..21b4de01 100644
--- a/src/store/modules/app.js
+++ b/src/store/modules/app.js
@@ -5,7 +5,9 @@ const app = {
sidebar: {
opened: !+Cookies.get('sidebarStatus')
},
- visitedViews: []
+ language: Cookies.get('language') || 'zh',
+ visitedViews: [],
+ cachedViews: []
},
mutations: {
TOGGLE_SIDEBAR: state => {
@@ -16,25 +18,44 @@ const app = {
}
state.sidebar.opened = !state.sidebar.opened
},
+ SET_LANGUAGE: (state, language) => {
+ state.language = language
+ Cookies.set('language', language)
+ },
ADD_VISITED_VIEWS: (state, view) => {
if (state.visitedViews.some(v => v.path === view.path)) return
- state.visitedViews.push({ name: view.name, path: view.path })
+ state.visitedViews.push({
+ name: view.name,
+ path: view.path,
+ title: view.meta.title || 'no-name'
+ })
+ if (!view.meta.noCache) {
+ state.cachedViews.push(view.name)
+ }
},
DEL_VISITED_VIEWS: (state, view) => {
- let index
for (const [i, v] of state.visitedViews.entries()) {
if (v.path === view.path) {
- index = i
+ state.visitedViews.splice(i, 1)
+ break
+ }
+ }
+ for (const i of state.cachedViews) {
+ if (i === view.name) {
+ const index = state.cachedViews.indexOf(i)
+ state.cachedViews.splice(index, 1)
break
}
}
- state.visitedViews.splice(index, 1)
}
},
actions: {
- ToggleSideBar({ commit }) {
+ toggleSideBar({ commit }) {
commit('TOGGLE_SIDEBAR')
},
+ setLanguage({ commit }, language) {
+ commit('SET_LANGUAGE', language)
+ },
addVisitedViews({ commit }, view) {
commit('ADD_VISITED_VIEWS', view)
},
diff --git a/src/store/modules/user.js b/src/store/modules/user.js
index 0ac425e1..8cf6d18a 100644
--- a/src/store/modules/user.js
+++ b/src/store/modules/user.js
@@ -50,8 +50,8 @@ const user = {
return new Promise((resolve, reject) => {
loginByUsername(username, userInfo.password).then(response => {
const data = response.data
- setToken(response.data.token)
commit('SET_TOKEN', data.token)
+ setToken(response.data.token)
resolve()
}).catch(error => {
reject(error)
diff --git a/src/styles/btn.scss b/src/styles/btn.scss
index 39b42dee..f3f75c16 100644
--- a/src/styles/btn.scss
+++ b/src/styles/btn.scss
@@ -1,11 +1,4 @@
-$blue:#324157;
-$light-blue:#3A71A8;
-$red:#C03639;
-$pink: #E65D6E;
-$green: #30B08F;
-$tiffany: #4AB7BD;
-$yellow:#FEC171;
-$panGreen: #30B08F;
+@import './variables.scss';
@mixin colorBtn($color) {
background: $color;
diff --git a/src/styles/element-ui.scss b/src/styles/element-ui.scss
index 3b005d07..9ca1bb0f 100644
--- a/src/styles/element-ui.scss
+++ b/src/styles/element-ui.scss
@@ -1,22 +1,4 @@
//覆盖一些element-ui样式
- .block-checkbox {
- display: block;
- }
-
- .operation-container {
- .cell {
- padding: 10px !important;
- }
- .el-button {
- &:nth-child(3) {
- margin-top: 10px;
- margin-left: 0px;
- }
- &:nth-child(4) {
- margin-top: 10px;
- }
- }
- }
.el-upload {
input[type="file"] {
@@ -30,7 +12,7 @@
.cell {
.el-tag {
- margin-right: 8px;
+ margin-right: 0px;
}
}
diff --git a/src/styles/index.scss b/src/styles/index.scss
index 9090126f..45bbe204 100644
--- a/src/styles/index.scss
+++ b/src/styles/index.scss
@@ -1,8 +1,12 @@
+@import './variables.scss';
@import './mixin.scss';
-@import './btn.scss';
+@import './transition.scss';
@import './element-ui.scss';
@import './sidebar.scss';
+@import './btn.scss';
+
body {
+ height: 100%;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
@@ -14,9 +18,14 @@ label {
}
html {
+ height: 100%;
box-sizing: border-box;
}
+#app{
+ height: 100%;
+}
+
*,
*:before,
*:after {
@@ -44,6 +53,10 @@ a:hover {
text-decoration: none;
}
+div:focus{
+ outline: none;
+ }
+
.fr {
float: right;
}
@@ -72,6 +85,17 @@ a:hover {
display: block;
}
+.clearfix {
+ &:after {
+ visibility: hidden;
+ display: block;
+ font-size: 0;
+ content: " ";
+ clear: both;
+ height: 0;
+ }
+}
+
code {
background: #eef1f6;
padding: 15px 10px;
@@ -87,14 +111,17 @@ code {
}
}
-.fade-enter-active,
-.fade-leave-active {
- transition: all .2s ease
-}
-
-.fade-enter,
-.fade-leave-active {
- opacity: 0;
+.warn-content{
+ background: rgba(66,185,131,.1);
+ border-radius: 2px;
+ padding: 16px;
+ padding: 1rem;
+ line-height: 1.6rem;
+ word-spacing: .05rem;
+ a{
+ color: #42b983;
+ font-weight: 600;
+ }
}
//main-container全局样式
@@ -119,14 +146,6 @@ code {
text-align: center
}
-.svg-icon {
- width: 1em;
- height: 1em;
- vertical-align: -0.15em;
- fill: currentColor;
- overflow: hidden;
-}
-
.sub-navbar {
height: 50px;
line-height: 50px;
@@ -157,57 +176,6 @@ code {
}
}
-.publishedTag,
-.draftTag,
-.deletedTag {
- color: #fff;
- background-color: $panGreen;
- line-height: 1;
- text-align: center;
- margin: 0;
- padding: 8px 12px;
- font-size: 14px;
- border-radius: 4px;
- position: absolute;
- left: 20px;
- top: 10px;
-}
-
-.draftTag {
- background-color: $yellow;
-}
-
-.deletedTag {
- background-color: $red;
-}
-
-.input-label {
- font-size: 14px;
- color: #48576a;
- line-height: 1;
- padding: 11px 5px 11px 0;
-}
-
-.clearfix {
- &:after {
- visibility: hidden;
- display: block;
- font-size: 0;
- content: " ";
- clear: both;
- height: 0;
- }
-}
-
-.no-marginLeft {
- .el-checkbox {
- margin: 0 20px 15px 0;
- }
- .el-checkbox+.el-checkbox {
- margin-left: 0px;
- }
-}
-
.filter-container {
padding-bottom: 10px;
.filter-item {
@@ -225,48 +193,3 @@ code {
.multiselect--active {
z-index: 1000 !important;
}
-
-//refine simplemde
-.simplemde-container {
- .editor-toolbar.fullscreen,
- .CodeMirror-fullscreen {
- z-index: 1003;
- }
-}
-
-//暂时性解决diolag 问题 https://github.com/ElemeFE/element/issues/2461
-.el-dialog {
- transform: none;
- left: 0;
- position: relative;
- margin: 0 auto;
-}
-
-//github-corner
-.github-corner:hover .octo-arm {
- animation: octocat-wave 560ms ease-in-out
-}
-
-@keyframes octocat-wave {
- 0%,
- 100% {
- transform: rotate(0)
- }
- 20%,
- 60% {
- transform: rotate(-25deg)
- }
- 40%,
- 80% {
- transform: rotate(10deg)
- }
-}
-
-@media (max-width:500px) {
- .github-corner:hover .octo-arm {
- animation: none
- }
- .github-corner .octo-arm {
- animation: octocat-wave 560ms ease-in-out
- }
-}
diff --git a/src/styles/sidebar.scss b/src/styles/sidebar.scss
index a41a033e..2fed2b1d 100644
--- a/src/styles/sidebar.scss
+++ b/src/styles/sidebar.scss
@@ -1,77 +1,100 @@
-// 侧边栏
-.sidebar-container>.el-menu {
- width: 100%!important;
- min-height: 100%;
-}
-
-.sidebar-container .svg-icon {
- margin-right: 16px;
-}
-
-.hideSidebar .el-submenu>.el-submenu__title,
-.hideSidebar .submenu-title-noDropdown {
- padding-left: 10px!important;
-}
-
-.hideSidebar .submenu-title-noDropdown span,
-.hideSidebar .el-submenu>.el-submenu__title>span {
- height: 0;
- width: 0;
- overflow: hidden;
- visibility: hidden;
- display: inline-block;
-}
-
-.hideSidebar .nest-menu .el-submenu__title {
- text-align: initial!important;
- padding-left: 20px!important;
- span {
- height: auto;
- width: auto;
- visibility: visible;
- display: inline;
- }
- .el-submenu__icon-arrow {
- display: block!important;
- }
-}
-
-.hideSidebar .menu-wrapper>.el-menu-item,
-.hideSidebar .submenu-title-noDropdown,
-.hideSidebar .menu-wrapper>.el-submenu .el-submenu__title {
- text-align: center;
-}
-
-.hideSidebar .el-menu-item .el-submenu__icon-arrow,
-.hideSidebar .el-submenu .el-submenu__title .el-submenu__icon-arrow {
- display: none;
-}
-
-.hideSidebar .submenu-title-noDropdown {
- position: relative;
- span {
- transition: opacity .3s cubic-bezier(.55, 0, .1, 1);
- opacity: 0;
- }
- &:hover {
- span {
- display: block;
- border-radius: 3px;
- z-index: 1002;
- width: 140px;
- height: 56px;
- visibility: visible;
- position: absolute;
- right: -145px;
- text-align: left;
- text-indent: 20px;
- top: 0px;
- background-color: #1f2d3d;
- opacity: 1;
+#app {
+ // 主体区域
+ .main-container {
+ min-height: 100%;
+ transition: margin-left 0.28s;
+ margin-left: 180px;
+ } // 侧边栏
+ .sidebar-container {
+ transition: width 0.28s;
+ width: 180px!important;
+ height: 100%;
+ position: fixed;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1001;
+ a {
+ display: inline-block;
+ width: 100%;
+ }
+ .svg-icon {
+ margin-right: 16px;
+ }
+ .el-menu {
+ border: none;
+ width: 100%;
}
}
-}
-
-.el-submenu .el-menu-item {
- min-width: 180px!important;
+ .hideSidebar {
+ .sidebar-container,.sidebar-container .el-menu {
+ width: 36px!important;
+ // overflow: inherit;
+ }
+ .main-container {
+ margin-left: 36px;
+ }
+ }
+ .hideSidebar {
+ .submenu-title-noDropdown {
+ padding-left: 10px!important;
+ position: relative;
+ span {
+ height: 0;
+ width: 0;
+ overflow: hidden;
+ visibility: hidden;
+ transition: opacity .3s cubic-bezier(.55, 0, .1, 1);
+ opacity: 0;
+ display: inline-block;
+ }
+ &:hover {
+ span {
+ display: block;
+ border-radius: 3px;
+ z-index: 1002;
+ width: 140px;
+ height: 56px;
+ visibility: visible;
+ position: absolute;
+ right: -145px;
+ text-align: left;
+ text-indent: 20px;
+ top: 0px;
+ background-color: $subMenuBg!important;
+ opacity: 1;
+ }
+ }
+ }
+ .el-submenu {
+ &>.el-submenu__title {
+ padding-left: 10px!important;
+ &>span {
+ display: none;
+ }
+ .el-submenu__icon-arrow {
+ display: none;
+ }
+ }
+ .nest-menu {
+ .el-submenu__icon-arrow {
+ display: block!important;
+ }
+ span {
+ display: inline-block!important;
+ }
+ }
+ }
+ }
+ .nest-menu .el-submenu>.el-submenu__title,
+ .el-submenu .el-menu-item {
+ min-width: 180px!important;
+ background-color: $subMenuBg!important;
+ &:hover {
+ background-color: $menuHover!important;
+ }
+ }
+ .el-menu--collapse .el-menu .el-submenu{
+ min-width: 180px!important;
+ }
}
diff --git a/src/styles/transition.scss b/src/styles/transition.scss
new file mode 100644
index 00000000..85c03286
--- /dev/null
+++ b/src/styles/transition.scss
@@ -0,0 +1,33 @@
+//globl transition css
+
+/*fade*/
+.fade-enter-active,
+.fade-leave-active {
+ transition: opacity 0.28s;
+}
+
+.fade-enter,
+.fade-leave-active {
+ opacity: 0;
+}
+
+/*fade*/
+.breadcrumb-enter-active,
+.breadcrumb-leave-active {
+ transition: all .5s;
+}
+
+.breadcrumb-enter,
+.breadcrumb-leave-active {
+ opacity: 0;
+ transform: translateX(20px);
+}
+
+.breadcrumb-move {
+ transition: all .5s;
+}
+
+.breadcrumb-leave-active {
+ position: absolute;
+}
+
diff --git a/src/styles/variables.scss b/src/styles/variables.scss
new file mode 100644
index 00000000..acc77a82
--- /dev/null
+++ b/src/styles/variables.scss
@@ -0,0 +1,13 @@
+$blue:#324157;
+$light-blue:#3A71A8;
+$red:#C03639;
+$pink: #E65D6E;
+$green: #30B08F;
+$tiffany: #4AB7BD;
+$yellow:#FEC171;
+$panGreen: #30B08F;
+
+//sidebar
+$menuBg:#304156;
+$subMenuBg:#1f2d3d;
+$menuHover:#001528;
diff --git a/src/utils/clipboard.js b/src/utils/clipboard.js
index 882b1251..25295900 100644
--- a/src/utils/clipboard.js
+++ b/src/utils/clipboard.js
@@ -1,5 +1,5 @@
-import Clipboard from 'clipboard'
import Vue from 'vue'
+import Clipboard from 'clipboard'
function clipboardSuccess() {
Vue.prototype.$message({
diff --git a/src/utils/index.js b/src/utils/index.js
index 7707a3e0..ee74ce57 100644
--- a/src/utils/index.js
+++ b/src/utils/index.js
@@ -2,266 +2,273 @@
* Created by jiachenpan on 16/11/18.
*/
- export function parseTime(time, cFormat) {
- if (arguments.length === 0) {
- return null
- }
- const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
- let date
- if (typeof time === 'object') {
- date = time
- } else {
- if (('' + time).length === 10) time = parseInt(time) * 1000
- date = new Date(time)
- }
- const formatObj = {
- y: date.getFullYear(),
- m: date.getMonth() + 1,
- d: date.getDate(),
- h: date.getHours(),
- i: date.getMinutes(),
- s: date.getSeconds(),
- a: date.getDay()
- }
- const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
- let value = formatObj[key]
- if (key === 'a') return ['一', '二', '三', '四', '五', '六', '日'][value - 1]
- if (result.length > 0 && value < 10) {
- value = '0' + value
- }
- return value || 0
- })
- return time_str
- }
+export function parseTime(time, cFormat) {
+ if (arguments.length === 0) {
+ return null
+ }
+ const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}'
+ let date
+ if (typeof time === 'object') {
+ date = time
+ } else {
+ if (('' + time).length === 10) time = parseInt(time) * 1000
+ date = new Date(time)
+ }
+ const formatObj = {
+ y: date.getFullYear(),
+ m: date.getMonth() + 1,
+ d: date.getDate(),
+ h: date.getHours(),
+ i: date.getMinutes(),
+ s: date.getSeconds(),
+ a: date.getDay()
+ }
+ const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
+ let value = formatObj[key]
+ if (key === 'a') return ['一', '二', '三', '四', '五', '六', '日'][value - 1]
+ if (result.length > 0 && value < 10) {
+ value = '0' + value
+ }
+ return value || 0
+ })
+ return time_str
+}
- export function formatTime(time, option) {
- time = +time * 1000
- const d = new Date(time)
- const now = Date.now()
+export function formatTime(time, option) {
+ time = +time * 1000
+ const d = new Date(time)
+ const now = Date.now()
- const diff = (now - d) / 1000
+ const diff = (now - d) / 1000
- if (diff < 30) {
- return '刚刚'
- } else if (diff < 3600) { // less 1 hour
- return Math.ceil(diff / 60) + '分钟前'
- } else if (diff < 3600 * 24) {
- return Math.ceil(diff / 3600) + '小时前'
- } else if (diff < 3600 * 24 * 2) {
- return '1天前'
- }
- if (option) {
- return parseTime(time, option)
- } else {
- return d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分'
- }
- }
+ if (diff < 30) {
+ return '刚刚'
+ } else if (diff < 3600) { // less 1 hour
+ return Math.ceil(diff / 60) + '分钟前'
+ } else if (diff < 3600 * 24) {
+ return Math.ceil(diff / 3600) + '小时前'
+ } else if (diff < 3600 * 24 * 2) {
+ return '1天前'
+ }
+ if (option) {
+ return parseTime(time, option)
+ } else {
+ return d.getMonth() + 1 + '月' + d.getDate() + '日' + d.getHours() + '时' + d.getMinutes() + '分'
+ }
+}
// 格式化时间
- export function getQueryObject(url) {
- url = url == null ? window.location.href : url
- const search = url.substring(url.lastIndexOf('?') + 1)
- const obj = {}
- const reg = /([^?&=]+)=([^?&=]*)/g
- search.replace(reg, (rs, $1, $2) => {
- const name = decodeURIComponent($1)
- let val = decodeURIComponent($2)
- val = String(val)
- obj[name] = val
- return rs
- })
- return obj
- }
+export function getQueryObject(url) {
+ url = url == null ? window.location.href : url
+ const search = url.substring(url.lastIndexOf('?') + 1)
+ const obj = {}
+ const reg = /([^?&=]+)=([^?&=]*)/g
+ search.replace(reg, (rs, $1, $2) => {
+ const name = decodeURIComponent($1)
+ let val = decodeURIComponent($2)
+ val = String(val)
+ obj[name] = val
+ return rs
+ })
+ return obj
+}
/**
*get getByteLen
* @param {Sting} val input value
* @returns {number} output value
*/
- export function getByteLen(val) {
- let len = 0
- for (let i = 0; i < val.length; i++) {
- if (val[i].match(/[^\x00-\xff]/ig) != null) {
- len += 1
- } else { len += 0.5 }
- }
- return Math.floor(len)
- }
+export function getByteLen(val) {
+ let len = 0
+ for (let i = 0; i < val.length; i++) {
+ if (val[i].match(/[^\x00-\xff]/ig) != null) {
+ len += 1
+ } else { len += 0.5 }
+ }
+ return Math.floor(len)
+}
- export function cleanArray(actual) {
- const newArray = []
- for (let i = 0; i < actual.length; i++) {
- if (actual[i]) {
- newArray.push(actual[i])
- }
- }
- return newArray
- }
+export function cleanArray(actual) {
+ const newArray = []
+ for (let i = 0; i < actual.length; i++) {
+ if (actual[i]) {
+ newArray.push(actual[i])
+ }
+ }
+ return newArray
+}
- export function param(json) {
- if (!json) return ''
- return cleanArray(Object.keys(json).map(key => {
- if (json[key] === undefined) return ''
- return encodeURIComponent(key) + '=' +
+export function param(json) {
+ if (!json) return ''
+ return cleanArray(Object.keys(json).map(key => {
+ if (json[key] === undefined) return ''
+ return encodeURIComponent(key) + '=' +
encodeURIComponent(json[key])
- })).join('&')
- }
+ })).join('&')
+}
- export function param2Obj(url) {
- const search = url.split('?')[1]
- if (!search) {
- return {}
- }
- return JSON.parse('{"' + decodeURIComponent(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}')
- }
+export function param2Obj(url) {
+ const search = url.split('?')[1]
+ if (!search) {
+ return {}
+ }
+ return JSON.parse('{"' + decodeURIComponent(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}')
+}
- export function html2Text(val) {
- const div = document.createElement('div')
- div.innerHTML = val
- return div.textContent || div.innerText
- }
+export function html2Text(val) {
+ const div = document.createElement('div')
+ div.innerHTML = val
+ return div.textContent || div.innerText
+}
- export function objectMerge(target, source) {
- /* Merges two objects,
+export function objectMerge(target, source) {
+ /* Merges two objects,
giving the last one precedence */
- if (typeof target !== 'object') {
- target = {}
- }
- if (Array.isArray(source)) {
- return source.slice()
- }
- for (const property in source) {
- if (source.hasOwnProperty(property)) {
- const sourceProperty = source[property]
- if (typeof sourceProperty === 'object') {
- target[property] = objectMerge(target[property], sourceProperty)
- continue
- }
- target[property] = sourceProperty
- }
- }
- return target
- }
+ if (typeof target !== 'object') {
+ target = {}
+ }
+ if (Array.isArray(source)) {
+ return source.slice()
+ }
+ for (const property in source) {
+ if (source.hasOwnProperty(property)) {
+ const sourceProperty = source[property]
+ if (typeof sourceProperty === 'object') {
+ target[property] = objectMerge(target[property], sourceProperty)
+ continue
+ }
+ target[property] = sourceProperty
+ }
+ }
+ return target
+}
- export function scrollTo(element, to, duration) {
- if (duration <= 0) return
- const difference = to - element.scrollTop
- const perTick = difference / duration * 10
- setTimeout(() => {
- console.log(new Date())
- element.scrollTop = element.scrollTop + perTick
- if (element.scrollTop === to) return
- scrollTo(element, to, duration - 10)
- }, 10)
- }
+export function scrollTo(element, to, duration) {
+ if (duration <= 0) return
+ const difference = to - element.scrollTop
+ const perTick = difference / duration * 10
+ setTimeout(() => {
+ console.log(new Date())
+ element.scrollTop = element.scrollTop + perTick
+ if (element.scrollTop === to) return
+ scrollTo(element, to, duration - 10)
+ }, 10)
+}
- export function toggleClass(element, className) {
- if (!element || !className) {
- return
- }
- let classString = element.className
- const nameIndex = classString.indexOf(className)
- if (nameIndex === -1) {
- classString += '' + className
- } else {
- classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length)
- }
- element.className = classString
- }
+export function toggleClass(element, className) {
+ if (!element || !className) {
+ return
+ }
+ let classString = element.className
+ const nameIndex = classString.indexOf(className)
+ if (nameIndex === -1) {
+ classString += '' + className
+ } else {
+ classString = classString.substr(0, nameIndex) + classString.substr(nameIndex + className.length)
+ }
+ element.className = classString
+}
- export const pickerOptions = [
- {
- text: '今天',
- onClick(picker) {
- const end = new Date()
- const start = new Date(new Date().toDateString())
- end.setTime(start.getTime())
- picker.$emit('pick', [start, end])
- }
- }, {
- text: '最近一周',
- onClick(picker) {
- const end = new Date(new Date().toDateString())
- const start = new Date()
- start.setTime(end.getTime() - 3600 * 1000 * 24 * 7)
- picker.$emit('pick', [start, end])
- }
- }, {
- text: '最近一个月',
- onClick(picker) {
- const end = new Date(new Date().toDateString())
- const start = new Date()
- start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
- picker.$emit('pick', [start, end])
- }
- }, {
- text: '最近三个月',
- onClick(picker) {
- const end = new Date(new Date().toDateString())
- const start = new Date()
- start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
- picker.$emit('pick', [start, end])
- }
- }]
+export const pickerOptions = [
+ {
+ text: '今天',
+ onClick(picker) {
+ const end = new Date()
+ const start = new Date(new Date().toDateString())
+ end.setTime(start.getTime())
+ picker.$emit('pick', [start, end])
+ }
+ }, {
+ text: '最近一周',
+ onClick(picker) {
+ const end = new Date(new Date().toDateString())
+ const start = new Date()
+ start.setTime(end.getTime() - 3600 * 1000 * 24 * 7)
+ picker.$emit('pick', [start, end])
+ }
+ }, {
+ text: '最近一个月',
+ onClick(picker) {
+ const end = new Date(new Date().toDateString())
+ const start = new Date()
+ start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
+ picker.$emit('pick', [start, end])
+ }
+ }, {
+ text: '最近三个月',
+ onClick(picker) {
+ const end = new Date(new Date().toDateString())
+ const start = new Date()
+ start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
+ picker.$emit('pick', [start, end])
+ }
+ }]
- export function getTime(type) {
- if (type === 'start') {
- return new Date().getTime() - 3600 * 1000 * 24 * 90
- } else {
- return new Date(new Date().toDateString())
- }
- }
+export function getTime(type) {
+ if (type === 'start') {
+ return new Date().getTime() - 3600 * 1000 * 24 * 90
+ } else {
+ return new Date(new Date().toDateString())
+ }
+}
- export function debounce(func, wait, immediate) {
- let timeout, args, context, timestamp, result
+export function debounce(func, wait, immediate) {
+ let timeout, args, context, timestamp, result
- const later = function() {
+ const later = function() {
// 据上一次触发时间间隔
- const last = +new Date() - timestamp
+ const last = +new Date() - timestamp
// 上次被包装函数被调用时间间隔last小于设定时间间隔wait
- if (last < wait && last > 0) {
- timeout = setTimeout(later, wait - last)
- } else {
- timeout = null
+ if (last < wait && last > 0) {
+ timeout = setTimeout(later, wait - last)
+ } else {
+ timeout = null
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
- if (!immediate) {
- result = func.apply(context, args)
- if (!timeout) context = args = null
- }
- }
- }
+ if (!immediate) {
+ result = func.apply(context, args)
+ if (!timeout) context = args = null
+ }
+ }
+ }
- return function(...args) {
- context = this
- timestamp = +new Date()
- const callNow = immediate && !timeout
+ return function(...args) {
+ context = this
+ timestamp = +new Date()
+ const callNow = immediate && !timeout
// 如果延时不存在,重新设定延时
- if (!timeout) timeout = setTimeout(later, wait)
- if (callNow) {
- result = func.apply(context, args)
- context = args = null
- }
+ if (!timeout) timeout = setTimeout(later, wait)
+ if (callNow) {
+ result = func.apply(context, args)
+ context = args = null
+ }
- return result
- }
- }
+ return result
+ }
+}
- export function deepClone(source) {
- if (!source && typeof source !== 'object') {
- throw new Error('error arguments', 'shallowClone')
- }
- const targetObj = source.constructor === Array ? [] : {}
- for (const keys in source) {
- if (source.hasOwnProperty(keys)) {
- if (source[keys] && typeof source[keys] === 'object') {
- targetObj[keys] = source[keys].constructor === Array ? [] : {}
- targetObj[keys] = deepClone(source[keys])
- } else {
- targetObj[keys] = source[keys]
- }
- }
- }
- return targetObj
- }
+export function deepClone(source) {
+ if (!source && typeof source !== 'object') {
+ throw new Error('error arguments', 'shallowClone')
+ }
+ const targetObj = source.constructor === Array ? [] : {}
+ for (const keys in source) {
+ if (source.hasOwnProperty(keys)) {
+ if (source[keys] && typeof source[keys] === 'object') {
+ targetObj[keys] = source[keys].constructor === Array ? [] : {}
+ targetObj[keys] = deepClone(source[keys])
+ } else {
+ targetObj[keys] = source[keys]
+ }
+ }
+ }
+ return targetObj
+}
+
+// get dependencies verison from package.json by webpack.DefinePlugin
+export function getVersion(name) {
+ import('../../package').then(p => {
+ return p.dependencies[name]
+ })
+}
diff --git a/src/utils/openWindow.js b/src/utils/openWindow.js
index 2c542913..b63dfbb4 100644
--- a/src/utils/openWindow.js
+++ b/src/utils/openWindow.js
@@ -7,7 +7,7 @@
*/
export default function openWindow(url, title, w, h) {
- // Fixes dual-screen position Most browsers Firefox
+ // Fixes dual-screen position Most browsers Firefox
const dualScreenLeft = window.screenLeft !== undefined ? window.screenLeft : screen.left
const dualScreenTop = window.screenTop !== undefined ? window.screenTop : screen.top
diff --git a/src/utils/fetch.js b/src/utils/request.js
similarity index 54%
rename from src/utils/fetch.js
rename to src/utils/request.js
index 4e193863..ee007f1f 100644
--- a/src/utils/fetch.js
+++ b/src/utils/request.js
@@ -6,7 +6,7 @@ import { getToken } from '@/utils/auth'
// 创建axios实例
const service = axios.create({
baseURL: process.env.BASE_API, // api的base_url
- timeout: 5000 // 请求超时时间
+ timeout: 5000 // 请求超时时间
})
// request拦截器
@@ -29,29 +29,29 @@ service.interceptors.response.use(
* 下面的注释为通过response自定义code来标示请求状态,当code返回如下情况为权限有问题,登出并返回到登录页
* 如通过xmlhttprequest 状态码标识 逻辑可写在下面error中
*/
-// const res = response.data;
-// if (res.code !== 20000) {
-// Message({
-// message: res.message,
-// type: 'error',
-// duration: 5 * 1000
-// });
-// // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
-// if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
-// MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
-// confirmButtonText: '重新登录',
-// cancelButtonText: '取消',
-// type: 'warning'
-// }).then(() => {
-// store.dispatch('FedLogOut').then(() => {
-// location.reload();// 为了重新实例化vue-router对象 避免bug
-// });
-// })
-// }
-// return Promise.reject('error');
-// } else {
-// return response.data;
-// }
+ // const res = response.data;
+ // if (res.code !== 20000) {
+ // Message({
+ // message: res.message,
+ // type: 'error',
+ // duration: 5 * 1000
+ // });
+ // // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
+ // if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
+ // MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
+ // confirmButtonText: '重新登录',
+ // cancelButtonText: '取消',
+ // type: 'warning'
+ // }).then(() => {
+ // store.dispatch('FedLogOut').then(() => {
+ // location.reload();// 为了重新实例化vue-router对象 避免bug
+ // });
+ // })
+ // }
+ // return Promise.reject('error');
+ // } else {
+ // return response.data;
+ // }
error => {
console.log('err' + error)// for debug
Message({
@@ -60,7 +60,6 @@ service.interceptors.response.use(
duration: 5 * 1000
})
return Promise.reject(error)
- }
-)
+ })
export default service
diff --git a/src/utils/validate.js b/src/utils/validate.js
index 834a8dd9..5bdd1b43 100644
--- a/src/utils/validate.js
+++ b/src/utils/validate.js
@@ -31,3 +31,13 @@ export function validatAlphabets(str) {
return reg.test(str)
}
+/**
+ * validate email
+ * @param email
+ * @returns {boolean}
+ */
+export function validateEmail(email) {
+ const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
+ return re.test(email)
+}
+
diff --git a/src/vendor/Export2Excel.js b/src/vendor/Export2Excel.js
index 4370da36..f7765e9a 100644
--- a/src/vendor/Export2Excel.js
+++ b/src/vendor/Export2Excel.js
@@ -155,6 +155,6 @@ export function export_json_to_excel(th, jsonData, defaultTitle) {
wb.Sheets[ws_name] = ws;
var wbout = XLSX.write(wb, {bookType: 'xlsx', bookSST: false, type: 'binary'});
- var title = defaultTitle || '列表'
+ var title = defaultTitle || 'excel-list'
saveAs(new Blob([s2ab(wbout)], {type: "application/octet-stream"}), title + ".xlsx")
}
diff --git a/src/vendor/Export2Zip.js b/src/vendor/Export2Zip.js
index 599eda18..6e11dc83 100644
--- a/src/vendor/Export2Zip.js
+++ b/src/vendor/Export2Zip.js
@@ -4,8 +4,8 @@ import JSZip from 'jszip'
export function export_txt_to_zip(th, jsonData, txtName, zipName) {
const zip = new JSZip()
- const txt_name = txtName || '文本'
- const zip_name = zipName || '压缩包'
+ const txt_name = txtName || 'file'
+ const zip_name = zipName || 'file'
const data = jsonData
let txtData = `${th}\r\n`
data.forEach((row) => {
diff --git a/src/views/charts/index.vue b/src/views/charts/index.vue
deleted file mode 100644
index d824b3cc..00000000
--- a/src/views/charts/index.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
- 这里的所有的图表都基于ECharts,实例代码来源 gallery
其实ECharts封装的很好了,用vue封装是很简单的事情,建议大家自己来封装。相关教程
-
-
-
diff --git a/src/views/charts/keyboard.vue b/src/views/charts/keyboard.vue
index bfc4db82..4001811e 100644
--- a/src/views/charts/keyboard.vue
+++ b/src/views/charts/keyboard.vue
@@ -1,16 +1,17 @@
diff --git a/src/views/charts/keyboard2.vue b/src/views/charts/keyboard2.vue
deleted file mode 100644
index b7b53c20..00000000
--- a/src/views/charts/keyboard2.vue
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
-
-
-
-
diff --git a/src/views/charts/line.vue b/src/views/charts/line.vue
index 63b73a39..6d62e52f 100644
--- a/src/views/charts/line.vue
+++ b/src/views/charts/line.vue
@@ -1,16 +1,17 @@
diff --git a/src/views/charts/mixChart.vue b/src/views/charts/mixChart.vue
index 647c1ec6..387e2e18 100644
--- a/src/views/charts/mixChart.vue
+++ b/src/views/charts/mixChart.vue
@@ -1,16 +1,17 @@
diff --git a/src/views/clipboard/index.vue b/src/views/clipboard/index.vue
index b0281abc..dfc4a98c 100644
--- a/src/views/clipboard/index.vue
+++ b/src/views/clipboard/index.vue
@@ -15,9 +15,10 @@
+
+
diff --git a/src/views/components-demo/mixin.vue b/src/views/components-demo/mixin.vue
new file mode 100644
index 00000000..e6a29b40
--- /dev/null
+++ b/src/views/components-demo/mixin.vue
@@ -0,0 +1,153 @@
+
+
+
+
+
+ Buttons
+
+
+
+ Components
+
+
+ Charts
+
+
+ Excel
+
+
+ Table
+
+
+ Form
+
+
+ Theme
+
+
+
+
+
+
+
+
+
+ Material Design 的input
+
+
+
+
+ 标题
+
+
+
+
+
+
+
+
+
+ 图片hover效果
+
+
+
+ vue-element-admin
+
+
+
+
+
+
+
+
+ 水波纹 waves v-directive
+
+
+ 水波纹效果
+
+
+
+
+
+
+
+ hover text
+
+
+
+
+
+
+
+
+
+
+
+
+ Share
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/components-demo/splitpane.vue b/src/views/components-demo/splitpane.vue
new file mode 100644
index 00000000..fa3f14a4
--- /dev/null
+++ b/src/views/components-demo/splitpane.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+
diff --git a/src/views/components/sticky.vue b/src/views/components-demo/sticky.vue
similarity index 95%
rename from src/views/components/sticky.vue
rename to src/views/components-demo/sticky.vue
index f6cf3daa..014d71fa 100644
--- a/src/views/components/sticky.vue
+++ b/src/views/components-demo/sticky.vue
@@ -97,6 +97,7 @@
import Sticky from '@/components/Sticky'
export default {
+ name: 'sticky-demo',
components: { Sticky },
data() {
return {
@@ -104,9 +105,9 @@ export default {
url: '',
platforms: ['a-platform'],
platformsOptions: [
- { key: 'a-platform', name: '平台A' },
- { key: 'b-platform', name: '平台B' },
- { key: 'c-platform', name: '平台C' }
+ { key: 'a-platform', name: '平台A' },
+ { key: 'b-platform', name: '平台B' },
+ { key: 'c-platform', name: '平台C' }
],
pickerOptions: {
disabledDate(time) {
diff --git a/src/views/components/tinymce.vue b/src/views/components-demo/tinymce.vue
similarity index 65%
rename from src/views/components/tinymce.vue
rename to src/views/components-demo/tinymce.vue
index a442599e..d8a85c3b 100644
--- a/src/views/components/tinymce.vue
+++ b/src/views/components-demo/tinymce.vue
@@ -1,10 +1,12 @@
-
公司做的后台主要是一个cms系统,公司也是以自媒体为核心的,所以富文本是后台很核心的功能。在选择富文本的过程中也走了不少的弯路,市面上常见的富文本都基本用过了,最终选择了Tinymce 相关文章 官网
+
公司做的后台主要是一个cms系统,公司也是以自媒体为核心的,所以富文本是后台很核心的功能。在选择富文本的过程中也走了不少的弯路,市面上常见的富文本都基本用过了,最终选择了Tinymce
+ 文档介绍
+
-
+
-
+
@@ -12,6 +14,7 @@
import Tinymce from '@/components/Tinymce'
export default {
+ name: 'tinymce-demo',
components: { Tinymce },
data() {
return {
diff --git a/src/views/components/index.vue b/src/views/components/index.vue
deleted file mode 100644
index 661c4835..00000000
--- a/src/views/components/index.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
这里暂时列出了自己在项目中用到的组件和一些自己封装的组件,如有补充可以提 issue
- 我个人崇尚自己封装组件,因为很多组件会和业务后高度的耦合,而且第三方封装的组件灵活性可控性都不高,如有需要可以看楼主之前写过的一篇文章
-
-
-
diff --git a/src/views/components/markdown.vue b/src/views/components/markdown.vue
deleted file mode 100644
index c50752cb..00000000
--- a/src/views/components/markdown.vue
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/views/components/mixin.vue b/src/views/components/mixin.vue
deleted file mode 100644
index 5f450c91..00000000
--- a/src/views/components/mixin.vue
+++ /dev/null
@@ -1,66 +0,0 @@
-
-
-
-
-
- 标题
-
-
- Material Design 的input
-
-
-
-
- 上海花裤衩
-
-
图片hover效果
-
-
-
- 水波纹效果
- 水波纹 v-directive
-
-
-
-
-
-
-
diff --git a/src/views/components/splitpane.vue b/src/views/components/splitpane.vue
deleted file mode 100644
index d60d4040..00000000
--- a/src/views/components/splitpane.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/views/dashboard/admin/barChart.vue b/src/views/dashboard/admin/components/BarChart.vue
similarity index 80%
rename from src/views/dashboard/admin/barChart.vue
rename to src/views/dashboard/admin/components/BarChart.vue
index a09bd8d9..78e71a93 100644
--- a/src/views/dashboard/admin/barChart.vue
+++ b/src/views/dashboard/admin/components/BarChart.vue
@@ -5,8 +5,10 @@
+
+
+
diff --git a/src/views/dashboard/admin/lineChart.vue b/src/views/dashboard/admin/components/LineChart.vue
similarity index 69%
rename from src/views/dashboard/admin/lineChart.vue
rename to src/views/dashboard/admin/components/LineChart.vue
index 59aa61e6..df96887b 100644
--- a/src/views/dashboard/admin/lineChart.vue
+++ b/src/views/dashboard/admin/components/LineChart.vue
@@ -24,6 +24,9 @@ export default {
autoResize: {
type: Boolean,
default: true
+ },
+ chartData: {
+ type: Object
}
},
data() {
@@ -60,62 +63,87 @@ export default {
this.chart.dispose()
this.chart = null
},
+ watch: {
+ chartData: {
+ deep: true,
+ handler(val) {
+ this.setOptions(val)
+ }
+ }
+ },
methods: {
- initChart() {
- this.chart = echarts.init(this.$el, 'macarons')
-
+ setOptions({ expectedData, actualData } = {}) {
this.chart.setOption({
xAxis: {
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
- boundaryGap: false
+ boundaryGap: false,
+ axisTick: {
+ show: false
+ }
},
grid: {
left: 10,
right: 10,
bottom: 20,
+ top: 30,
containLabel: true
},
-
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross'
+ },
+ padding: [5, 10]
+ },
+ yAxis: {
+ axisTick: {
+ show: false
}
},
- yAxis: {},
- series: [{
- name: 'visitors',
- itemStyle: {
- normal: {
- areaStyle: {}
- }
- },
- smooth: true,
- type: 'line',
- data: [100, 120, 161, 134, 105, 160, 165],
- animationDuration: 2600,
- animationEasing: 'cubicInOut'
+ legend: {
+ data: ['expected', 'actual']
},
- {
- name: 'buyers',
- smooth: true,
- type: 'line',
- itemStyle: {
+ series: [{
+ name: 'expected', itemStyle: {
normal: {
- color: 'rgba(2, 197, 233, 0.2)',
+ color: '#FF005A',
lineStyle: {
- color: 'rgba(2, 197, 233, 0.2)'
- },
- areaStyle: {
- color: 'rgba(99,194,255, 0.6)'
+ color: '#FF005A',
+ width: 2
}
}
},
- data: [120, 82, 91, 154, 162, 140, 130],
- animationDuration: 2000,
+ smooth: true,
+ type: 'line',
+ data: expectedData,
+ animationDuration: 2800,
+ animationEasing: 'cubicInOut'
+ },
+ {
+ name: 'actual',
+ smooth: true,
+ type: 'line',
+ itemStyle: {
+ normal: {
+ color: '#3888fa',
+ lineStyle: {
+ color: '#3888fa',
+ width: 2
+ },
+ areaStyle: {
+ color: '#f3f8ff'
+ }
+ }
+ },
+ data: actualData,
+ animationDuration: 2800,
animationEasing: 'quadraticOut'
}]
})
+ },
+ initChart() {
+ this.chart = echarts.init(this.$el, 'macarons')
+ this.setOptions(this.chartData)
}
}
}
diff --git a/src/views/dashboard/admin/components/PanelGroup.vue b/src/views/dashboard/admin/components/PanelGroup.vue
new file mode 100644
index 00000000..54e797fc
--- /dev/null
+++ b/src/views/dashboard/admin/components/PanelGroup.vue
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/views/dashboard/admin/pieChart.vue b/src/views/dashboard/admin/components/PieChart.vue
similarity index 62%
rename from src/views/dashboard/admin/pieChart.vue
rename to src/views/dashboard/admin/components/PieChart.vue
index 6384e1de..36a11227 100644
--- a/src/views/dashboard/admin/pieChart.vue
+++ b/src/views/dashboard/admin/components/PieChart.vue
@@ -5,6 +5,7 @@
diff --git a/src/components/TodoList/Todo.vue b/src/views/dashboard/admin/components/TodoList/Todo.vue
similarity index 100%
rename from src/components/TodoList/Todo.vue
rename to src/views/dashboard/admin/components/TodoList/Todo.vue
diff --git a/src/components/TodoList/index.scss b/src/views/dashboard/admin/components/TodoList/index.scss
similarity index 98%
rename from src/components/TodoList/index.scss
rename to src/views/dashboard/admin/components/TodoList/index.scss
index 8ed13d73..f004e6aa 100644
--- a/src/components/TodoList/index.scss
+++ b/src/views/dashboard/admin/components/TodoList/index.scss
@@ -4,10 +4,13 @@
color: #4d4d4d;
min-width: 230px;
max-width: 550px;
- margin: 40PX auto 0;
+ margin: 0 auto ;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-weight: 300;
+ background: #fff;
+ z-index: 1;
+ position: relative;
button {
margin: 0;
padding: 0;
@@ -81,7 +84,7 @@
-moz-osx-font-smoothing: grayscale;
}
.new-todo {
- padding: 16px 16px 16px 60px;
+ padding: 10px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
diff --git a/src/components/TodoList/index.vue b/src/views/dashboard/admin/components/TodoList/index.vue
similarity index 83%
rename from src/components/TodoList/index.vue
rename to src/views/dashboard/admin/components/TodoList/index.vue
index 8ce6af46..34f0241d 100644
--- a/src/components/TodoList/index.vue
+++ b/src/views/dashboard/admin/components/TodoList/index.vue
@@ -2,7 +2,7 @@
@@ -24,9 +24,9 @@
{{ key | capitalize }}
-
@@ -43,7 +43,12 @@ const filters = {
const defalutList = [
{ text: 'star this repository', done: false },
{ text: 'fork this repository', done: false },
- { text: 'follow author', done: false }
+ { text: 'follow author', done: false },
+ { text: 'vue-element-admin', done: true },
+ { text: 'vue', done: true },
+ { text: 'element-ui', done: true },
+ { text: 'axios', done: true },
+ { text: 'webpack', done: true }
]
export default {
components: { Todo },
@@ -51,7 +56,8 @@ export default {
return {
visibility: 'all',
filters,
- todos: JSON.parse(window.localStorage.getItem(STORAGE_KEY)) || defalutList
+ // todos: JSON.parse(window.localStorage.getItem(STORAGE_KEY)) || defalutList
+ todos: defalutList
}
},
computed: {
diff --git a/src/views/dashboard/admin/components/TransactionTable.vue b/src/views/dashboard/admin/components/TransactionTable.vue
new file mode 100644
index 00000000..35a65153
--- /dev/null
+++ b/src/views/dashboard/admin/components/TransactionTable.vue
@@ -0,0 +1,55 @@
+
+
+
+
+ {{scope.row.order_no}}
+
+
+
+
+ ¥{{scope.row.price | toThousandslsFilter}}
+
+
+
+
+ {{scope.row.status}}
+
+
+
+
+
+
+
diff --git a/src/views/dashboard/admin/index.vue b/src/views/dashboard/admin/index.vue
index ad657137..95c9cd6b 100644
--- a/src/views/dashboard/admin/index.vue
+++ b/src/views/dashboard/admin/index.vue
@@ -1,131 +1,109 @@
-
-
-
-
- Components
-
-
- Charts
-
-
- Excel
-
-
- Table
-
-
- Form
-
-
- Theme
-
-
+
+
-
-
-
-
- {{name}}
-
-
- 文章
-
-
-
-
- 浏览量
-
-
-
-
+
-
-
-
+
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/src/views/dashboard/editor/index.vue b/src/views/dashboard/editor/index.vue
index 07f30ee6..531c8067 100644
--- a/src/views/dashboard/editor/index.vue
+++ b/src/views/dashboard/editor/index.vue
@@ -4,14 +4,14 @@
你的权限:
{{item}}
-
+
{{name}}
- 普通编辑dashboard
+ 普通编辑dashboard