Merge branch 'master' into deploy
This commit is contained in:
commit
1cfcd49fe2
|
@ -18,6 +18,12 @@
|
||||||
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
|
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
|
||||||
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
|
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
|
||||||
</a>
|
</a>
|
||||||
|
<a href="https://gitter.im/vue-element-admin/discuss">
|
||||||
|
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="gitter">
|
||||||
|
</a>
|
||||||
|
<a href="https://panjiachen.github.io/vue-element-admin-site/donate">
|
||||||
|
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
English | [简体中文](./README.zh-CN.md)
|
English | [简体中文](./README.zh-CN.md)
|
||||||
|
|
|
@ -18,6 +18,12 @@
|
||||||
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
|
<a href="https://github.com/PanJiaChen/vue-element-admin/releases">
|
||||||
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
|
<img src="https://img.shields.io/github/release/PanJiaChen/vue-element-admin.svg" alt="GitHub release">
|
||||||
</a>
|
</a>
|
||||||
|
<a href="https://gitter.im/vue-element-admin/discuss">
|
||||||
|
<img src="https://badges.gitter.im/Join%20Chat.svg" alt="gitter">
|
||||||
|
</a>
|
||||||
|
<a href="https://panjiachen.gitee.io/vue-element-admin-site/zh/donate">
|
||||||
|
<img src="https://img.shields.io/badge/%24-donate-ff69b4.svg" alt="donate">
|
||||||
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
简体中文 | [English](./README.md)
|
简体中文 | [English](./README.md)
|
||||||
|
|
|
@ -57,7 +57,6 @@
|
||||||
"vue": "2.5.17",
|
"vue": "2.5.17",
|
||||||
"vue-count-to": "1.0.13",
|
"vue-count-to": "1.0.13",
|
||||||
"vue-i18n": "7.3.2",
|
"vue-i18n": "7.3.2",
|
||||||
"vue-multiselect": "2.1.0",
|
|
||||||
"vue-router": "3.0.1",
|
"vue-router": "3.0.1",
|
||||||
"vue-splitpane": "1.0.2",
|
"vue-splitpane": "1.0.2",
|
||||||
"vuedraggable": "^2.16.0",
|
"vuedraggable": "^2.16.0",
|
||||||
|
|
|
@ -45,7 +45,8 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
visible: false,
|
visible: false,
|
||||||
interval: null
|
interval: null,
|
||||||
|
isMoving: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -62,13 +63,16 @@ export default {
|
||||||
this.visible = window.pageYOffset > this.visibilityHeight
|
this.visible = window.pageYOffset > this.visibilityHeight
|
||||||
},
|
},
|
||||||
backToTop() {
|
backToTop() {
|
||||||
|
if (this.isMoving) return
|
||||||
const start = window.pageYOffset
|
const start = window.pageYOffset
|
||||||
let i = 0
|
let i = 0
|
||||||
|
this.isMoving = true
|
||||||
this.interval = setInterval(() => {
|
this.interval = setInterval(() => {
|
||||||
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
|
const next = Math.floor(this.easeInOutQuad(10 * i, start, -start, 500))
|
||||||
if (next <= this.backPosition) {
|
if (next <= this.backPosition) {
|
||||||
window.scrollTo(0, this.backPosition)
|
window.scrollTo(0, this.backPosition)
|
||||||
clearInterval(this.interval)
|
clearInterval(this.interval)
|
||||||
|
this.isMoving = false
|
||||||
} else {
|
} else {
|
||||||
window.scrollTo(0, next)
|
window.scrollTo(0, next)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ export default {
|
||||||
this.$i18n.locale = lang
|
this.$i18n.locale = lang
|
||||||
this.$store.dispatch('setLanguage', lang)
|
this.$store.dispatch('setLanguage', lang)
|
||||||
this.$message({
|
this.$message({
|
||||||
message: 'switch language success',
|
message: 'Switch Language Success',
|
||||||
type: 'success'
|
type: 'success'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
<template>
|
||||||
|
<el-dropdown trigger="click" @command="handleSetSize">
|
||||||
|
<div>
|
||||||
|
<svg-icon class-name="size-icon" icon-class="size" />
|
||||||
|
</div>
|
||||||
|
<el-dropdown-menu slot="dropdown">
|
||||||
|
<el-dropdown-item :disabled="size==='medium'" command="medium">Medium</el-dropdown-item>
|
||||||
|
<el-dropdown-item :disabled="size==='small'" command="small">Small</el-dropdown-item>
|
||||||
|
<el-dropdown-item :disabled="size==='mini'" command="mini">Mini</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
size() {
|
||||||
|
return this.$store.getters.size
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleSetSize(size) {
|
||||||
|
this.$ELEMENT.size = size
|
||||||
|
this.$store.dispatch('setSize', size)
|
||||||
|
this.refreshView()
|
||||||
|
this.$message({
|
||||||
|
message: 'Switch Size Success',
|
||||||
|
type: 'success'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
refreshView() {
|
||||||
|
// In order to make the cached page re-rendered
|
||||||
|
const visitedViews = [...this.$store.getters.visitedViews].map(i => {
|
||||||
|
i.meta.noCache = true
|
||||||
|
return i
|
||||||
|
})
|
||||||
|
|
||||||
|
this.$store.dispatch('delAllViews', this.$route).then(() => {
|
||||||
|
console.log(visitedViews)
|
||||||
|
for (const i of visitedViews) {
|
||||||
|
this.$store.dispatch('addVisitedViews', i)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const { path } = this.$route
|
||||||
|
|
||||||
|
this.$router.replace({
|
||||||
|
path: '/redirect' + path
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.size-icon {
|
||||||
|
font-size: 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
vertical-align: -4px!important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
@ -46,7 +46,16 @@ export default {
|
||||||
hasChange: false,
|
hasChange: false,
|
||||||
hasInit: false,
|
hasInit: false,
|
||||||
tinymceId: this.id,
|
tinymceId: this.id,
|
||||||
fullscreen: false
|
fullscreen: false,
|
||||||
|
languageTypeList: {
|
||||||
|
'en': 'en',
|
||||||
|
'zh': 'zh_CN'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
language() {
|
||||||
|
return this.languageTypeList[this.$store.getters.language]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
@ -55,6 +64,10 @@ export default {
|
||||||
this.$nextTick(() =>
|
this.$nextTick(() =>
|
||||||
window.tinymce.get(this.tinymceId).setContent(val || ''))
|
window.tinymce.get(this.tinymceId).setContent(val || ''))
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
language() {
|
||||||
|
this.destroyTinymce()
|
||||||
|
this.$nextTick(() => this.initTinymce())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
@ -73,6 +86,7 @@ export default {
|
||||||
initTinymce() {
|
initTinymce() {
|
||||||
const _this = this
|
const _this = this
|
||||||
window.tinymce.init({
|
window.tinymce.init({
|
||||||
|
language: this.language,
|
||||||
selector: `#${this.tinymceId}`,
|
selector: `#${this.tinymceId}`,
|
||||||
height: this.height,
|
height: this.height,
|
||||||
body_class: 'panel-body ',
|
body_class: 'panel-body ',
|
||||||
|
|
|
@ -2,20 +2,18 @@ import Vue from 'vue'
|
||||||
import store from './store'
|
import store from './store'
|
||||||
|
|
||||||
// you can set only in production env show the error-log
|
// you can set only in production env show the error-log
|
||||||
// if (process.env.NODE_ENV === 'production') {
|
if (process.env.NODE_ENV === 'production') {
|
||||||
|
Vue.config.errorHandler = function(err, vm, info, a) {
|
||||||
Vue.config.errorHandler = function(err, vm, info, a) {
|
|
||||||
// Don't ask me why I use Vue.nextTick, it just a hack.
|
// Don't ask me why I use Vue.nextTick, it just a hack.
|
||||||
// detail see https://forum.vuejs.org/t/dispatch-in-vue-config-errorhandler-has-some-problem/23500
|
// detail see https://forum.vuejs.org/t/dispatch-in-vue-config-errorhandler-has-some-problem/23500
|
||||||
Vue.nextTick(() => {
|
Vue.nextTick(() => {
|
||||||
store.dispatch('addErrorLog', {
|
store.dispatch('addErrorLog', {
|
||||||
err,
|
err,
|
||||||
vm,
|
vm,
|
||||||
info,
|
info,
|
||||||
url: window.location.href
|
url: window.location.href
|
||||||
|
})
|
||||||
|
console.error(err, info)
|
||||||
})
|
})
|
||||||
console.error(err, info)
|
}
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1534846208920" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2941" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M912 1008.512H15.488V112h448.256v96H111.488v704.512H816V560.256h96z" p-id="2942"></path><path d="M918.208 37.888l67.904 67.904L545.984 545.92 478.08 478.08z" p-id="2943"></path><path d="M1007.168 310.656h-96V112h-208V16h304z" p-id="2944"></path></svg>
|
After Width: | Height: | Size: 637 B |
|
@ -0,0 +1,2 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1535513021233" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="13539" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css">@font-face { font-family: rbicon; src: url("chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2") format("woff2"); font-weight: normal; font-style: normal; }
|
||||||
|
</style></defs><path d="M64 512l384 0 0 128-128 0 0 384-128 0 0-384-128 0zM960 256l-251.74016 0 0 768-136.4992 0 0-768-251.74016 0 0-128 640 0z" p-id="13540"></path></svg>
|
After Width: | Height: | Size: 711 B |
|
@ -60,14 +60,16 @@ export default {
|
||||||
exportZip: 'Export Zip',
|
exportZip: 'Export Zip',
|
||||||
theme: 'Theme',
|
theme: 'Theme',
|
||||||
clipboardDemo: 'Clipboard',
|
clipboardDemo: 'Clipboard',
|
||||||
i18n: 'I18n'
|
i18n: 'I18n',
|
||||||
|
externalLink: 'External Link'
|
||||||
},
|
},
|
||||||
navbar: {
|
navbar: {
|
||||||
logOut: 'Log Out',
|
logOut: 'Log Out',
|
||||||
dashboard: 'Dashboard',
|
dashboard: 'Dashboard',
|
||||||
github: 'Github',
|
github: 'Github',
|
||||||
screenfull: 'screenfull',
|
screenfull: 'Screenfull',
|
||||||
theme: 'theme'
|
theme: 'Theme',
|
||||||
|
size: 'Global Size'
|
||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
title: 'Login Form',
|
title: 'Login Form',
|
||||||
|
|
|
@ -60,14 +60,16 @@ export default {
|
||||||
exportZip: 'Export Zip',
|
exportZip: 'Export Zip',
|
||||||
theme: '换肤',
|
theme: '换肤',
|
||||||
clipboardDemo: 'Clipboard',
|
clipboardDemo: 'Clipboard',
|
||||||
i18n: '国际化'
|
i18n: '国际化',
|
||||||
|
externalLink: '外链'
|
||||||
},
|
},
|
||||||
navbar: {
|
navbar: {
|
||||||
logOut: '退出登录',
|
logOut: '退出登录',
|
||||||
dashboard: '首页',
|
dashboard: '首页',
|
||||||
github: '项目地址',
|
github: '项目地址',
|
||||||
screenfull: '全屏',
|
screenfull: '全屏',
|
||||||
theme: '换肤'
|
theme: '换肤',
|
||||||
|
size: '布局大小'
|
||||||
},
|
},
|
||||||
login: {
|
login: {
|
||||||
title: '系统登录',
|
title: '系统登录',
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
import Cookies from 'js-cookie'
|
||||||
|
|
||||||
import 'normalize.css/normalize.css' // A modern alternative to CSS resets
|
import 'normalize.css/normalize.css' // A modern alternative to CSS resets
|
||||||
|
|
||||||
import Element from 'element-ui'
|
import Element from 'element-ui'
|
||||||
|
@ -20,7 +22,7 @@ import './mock' // simulation data
|
||||||
import * as filters from './filters' // global filters
|
import * as filters from './filters' // global filters
|
||||||
|
|
||||||
Vue.use(Element, {
|
Vue.use(Element, {
|
||||||
size: 'medium', // set element-ui default size
|
size: Cookies.get('size') || 'medium', // set element-ui default size
|
||||||
i18n: (key, value) => i18n.t(key, value)
|
i18n: (key, value) => i18n.t(key, value)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,17 @@ import nestedRouter from './modules/nested'
|
||||||
}
|
}
|
||||||
**/
|
**/
|
||||||
export const constantRouterMap = [
|
export const constantRouterMap = [
|
||||||
|
{
|
||||||
|
path: '/redirect',
|
||||||
|
component: Layout,
|
||||||
|
hidden: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '/redirect/:path*',
|
||||||
|
component: () => import('@/views/redirect/index')
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
component: () => import('@/views/login/index'),
|
component: () => import('@/views/login/index'),
|
||||||
|
@ -322,5 +333,16 @@ export const asyncRouterMap = [
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
path: 'external-link',
|
||||||
|
component: Layout,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'https://github.com/PanJiaChen/vue-element-admin',
|
||||||
|
meta: { title: 'externalLink', icon: 'link' }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
{ path: '*', redirect: '/404', hidden: true }
|
{ path: '*', redirect: '/404', hidden: true }
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const getters = {
|
const getters = {
|
||||||
sidebar: state => state.app.sidebar,
|
sidebar: state => state.app.sidebar,
|
||||||
language: state => state.app.language,
|
language: state => state.app.language,
|
||||||
|
size: state => state.app.size,
|
||||||
device: state => state.app.device,
|
device: state => state.app.device,
|
||||||
visitedViews: state => state.tagsView.visitedViews,
|
visitedViews: state => state.tagsView.visitedViews,
|
||||||
cachedViews: state => state.tagsView.cachedViews,
|
cachedViews: state => state.tagsView.cachedViews,
|
||||||
|
|
|
@ -7,7 +7,8 @@ const app = {
|
||||||
withoutAnimation: false
|
withoutAnimation: false
|
||||||
},
|
},
|
||||||
device: 'desktop',
|
device: 'desktop',
|
||||||
language: Cookies.get('language') || 'en'
|
language: Cookies.get('language') || 'en',
|
||||||
|
size: Cookies.get('size') || 'medium'
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
TOGGLE_SIDEBAR: state => {
|
TOGGLE_SIDEBAR: state => {
|
||||||
|
@ -30,6 +31,10 @@ const app = {
|
||||||
SET_LANGUAGE: (state, language) => {
|
SET_LANGUAGE: (state, language) => {
|
||||||
state.language = language
|
state.language = language
|
||||||
Cookies.set('language', language)
|
Cookies.set('language', language)
|
||||||
|
},
|
||||||
|
SET_SIZE: (state, size) => {
|
||||||
|
state.size = size
|
||||||
|
Cookies.set('size', size)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
@ -44,6 +49,9 @@ const app = {
|
||||||
},
|
},
|
||||||
setLanguage({ commit }, language) {
|
setLanguage({ commit }, language) {
|
||||||
commit('SET_LANGUAGE', language)
|
commit('SET_LANGUAGE', language)
|
||||||
|
},
|
||||||
|
setSize({ commit }, size) {
|
||||||
|
commit('SET_SIZE', size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,8 @@ export function parseTime(time, cFormat) {
|
||||||
}
|
}
|
||||||
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
|
const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
|
||||||
let value = formatObj[key]
|
let value = formatObj[key]
|
||||||
if (key === 'a') { return ['一', '二', '三', '四', '五', '六', '日'][value - 1] }
|
// Note: getDay() returns 0 on Sunday
|
||||||
|
if (key === 'a') { return ['日', '一', '二', '三', '四', '五', '六'][value ] }
|
||||||
if (result.length > 0 && value < 10) {
|
if (result.length > 0 && value < 10) {
|
||||||
value = '0' + value
|
value = '0' + value
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,8 +77,6 @@
|
||||||
import Tinymce from '@/components/Tinymce'
|
import Tinymce from '@/components/Tinymce'
|
||||||
import Upload from '@/components/Upload/singleImage3'
|
import Upload from '@/components/Upload/singleImage3'
|
||||||
import MDinput from '@/components/MDinput'
|
import MDinput from '@/components/MDinput'
|
||||||
import Multiselect from 'vue-multiselect'// 使用的一个多选框组件,element-ui的select不能满足所有需求
|
|
||||||
import 'vue-multiselect/dist/vue-multiselect.min.css'// 多选框组件css
|
|
||||||
import Sticky from '@/components/Sticky' // 粘性header组件
|
import Sticky from '@/components/Sticky' // 粘性header组件
|
||||||
import { validateURL } from '@/utils/validate'
|
import { validateURL } from '@/utils/validate'
|
||||||
import { fetchArticle } from '@/api/article'
|
import { fetchArticle } from '@/api/article'
|
||||||
|
@ -102,7 +100,7 @@ const defaultForm = {
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ArticleDetail',
|
name: 'ArticleDetail',
|
||||||
components: { Tinymce, MDinput, Upload, Multiselect, Sticky, Warning, CommentDropdown, PlatformDropdown, SourceUrlDropdown },
|
components: { Tinymce, MDinput, Upload, Sticky, Warning, CommentDropdown, PlatformDropdown, SourceUrlDropdown },
|
||||||
props: {
|
props: {
|
||||||
isEdit: {
|
isEdit: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
<screenfull class="screenfull right-menu-item"/>
|
<screenfull class="screenfull right-menu-item"/>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
|
|
||||||
|
<el-tooltip :content="$t('navbar.size')" effect="dark" placement="bottom">
|
||||||
|
<size-select class="international right-menu-item"/>
|
||||||
|
</el-tooltip>
|
||||||
|
|
||||||
<lang-select class="international right-menu-item"/>
|
<lang-select class="international right-menu-item"/>
|
||||||
|
|
||||||
<el-tooltip :content="$t('navbar.theme')" effect="dark" placement="bottom">
|
<el-tooltip :content="$t('navbar.theme')" effect="dark" placement="bottom">
|
||||||
|
@ -48,6 +52,7 @@ import Breadcrumb from '@/components/Breadcrumb'
|
||||||
import Hamburger from '@/components/Hamburger'
|
import Hamburger from '@/components/Hamburger'
|
||||||
import ErrorLog from '@/components/ErrorLog'
|
import ErrorLog from '@/components/ErrorLog'
|
||||||
import Screenfull from '@/components/Screenfull'
|
import Screenfull from '@/components/Screenfull'
|
||||||
|
import SizeSelect from '@/components/SizeSelect'
|
||||||
import LangSelect from '@/components/LangSelect'
|
import LangSelect from '@/components/LangSelect'
|
||||||
import ThemePicker from '@/components/ThemePicker'
|
import ThemePicker from '@/components/ThemePicker'
|
||||||
|
|
||||||
|
@ -57,6 +62,7 @@ export default {
|
||||||
Hamburger,
|
Hamburger,
|
||||||
ErrorLog,
|
ErrorLog,
|
||||||
Screenfull,
|
Screenfull,
|
||||||
|
SizeSelect,
|
||||||
LangSelect,
|
LangSelect,
|
||||||
ThemePicker
|
ThemePicker
|
||||||
},
|
},
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'MenuItem',
|
||||||
|
functional: true,
|
||||||
|
props: {
|
||||||
|
icon: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
render(h, context) {
|
||||||
|
const { icon, title } = context.props
|
||||||
|
const vnodes = []
|
||||||
|
|
||||||
|
if (icon) {
|
||||||
|
vnodes.push(<svg-icon icon-class={icon}/>)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (title) {
|
||||||
|
vnodes.push(<span slot='title'>{(title)}</span>)
|
||||||
|
}
|
||||||
|
return vnodes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -1,28 +1,27 @@
|
||||||
<template>
|
<template>
|
||||||
<div v-if="!item.hidden&&item.children" class="menu-wrapper">
|
<div v-if="!item.hidden&&item.children" class="menu-wrapper">
|
||||||
|
|
||||||
<router-link v-if="hasOneShowingChild(item.children) && !onlyOneChild.children&&!item.alwaysShow" :to="resolvePath(onlyOneChild.path)">
|
<template v-if="hasOneShowingChild(item.children) && !onlyOneChild.children&&!item.alwaysShow">
|
||||||
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
|
<a :href="onlyOneChild.path" target="_blank" @click="clickLink(onlyOneChild.path,$event)">
|
||||||
<svg-icon v-if="onlyOneChild.meta&&onlyOneChild.meta.icon" :icon-class="onlyOneChild.meta.icon"/>
|
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}">
|
||||||
<span v-if="onlyOneChild.meta&&onlyOneChild.meta.title" slot="title">{{ generateTitle(onlyOneChild.meta.title) }}</span>
|
<item v-if="onlyOneChild.meta" :icon="onlyOneChild.meta.icon" :title="generateTitle(onlyOneChild.meta.title)" />
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</router-link>
|
</a>
|
||||||
|
</template>
|
||||||
|
|
||||||
<el-submenu v-else :index="item.name||item.path">
|
<el-submenu v-else :index="item.name||item.path">
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<svg-icon v-if="item.meta&&item.meta.icon" :icon-class="item.meta.icon"/>
|
<item v-if="item.meta" :icon="item.meta.icon" :title="generateTitle(item.meta.title)" />
|
||||||
<span v-if="item.meta&&item.meta.title" slot="title">{{ generateTitle(item.meta.title) }}</span>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-for="child in item.children" v-if="!child.hidden">
|
<template v-for="child in item.children" v-if="!child.hidden">
|
||||||
<sidebar-item v-if="child.children&&child.children.length>0" :is-nest="true" :item="child" :key="child.path" :base-path="resolvePath(child.path)" class="nest-menu"/>
|
<sidebar-item v-if="child.children&&child.children.length>0" :is-nest="true" :item="child" :key="child.path" :base-path="resolvePath(child.path)" class="nest-menu"/>
|
||||||
|
|
||||||
<router-link v-else :to="resolvePath(child.path)" :key="child.name">
|
<a v-else :href="child.path" :key="child.name" target="_blank" @click="clickLink(child.path,$event)">
|
||||||
<el-menu-item :index="resolvePath(child.path)">
|
<el-menu-item :index="resolvePath(child.path)">
|
||||||
<svg-icon v-if="child.meta&&child.meta.icon" :icon-class="child.meta.icon"/>
|
<item v-if="child.meta" :icon="child.meta.icon" :title="generateTitle(child.meta.title)" />
|
||||||
<span v-if="child.meta&&child.meta.title" slot="title">{{ generateTitle(child.meta.title) }}</span>
|
|
||||||
</el-menu-item>
|
</el-menu-item>
|
||||||
</router-link>
|
</a>
|
||||||
</template>
|
</template>
|
||||||
</el-submenu>
|
</el-submenu>
|
||||||
|
|
||||||
|
@ -32,9 +31,12 @@
|
||||||
<script>
|
<script>
|
||||||
import path from 'path'
|
import path from 'path'
|
||||||
import { generateTitle } from '@/utils/i18n'
|
import { generateTitle } from '@/utils/i18n'
|
||||||
|
import { validateURL } from '@/utils/validate'
|
||||||
|
import Item from './Item'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'SidebarItem',
|
name: 'SidebarItem',
|
||||||
|
components: { Item },
|
||||||
props: {
|
props: {
|
||||||
// route object
|
// route object
|
||||||
item: {
|
item: {
|
||||||
|
@ -71,11 +73,20 @@ export default {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
resolvePath(...paths) {
|
resolvePath(routePath) {
|
||||||
return path.resolve(this.basePath, ...paths)
|
return path.resolve(this.basePath, routePath)
|
||||||
|
},
|
||||||
|
isExternalLink(routePath) {
|
||||||
|
return validateURL(routePath)
|
||||||
|
},
|
||||||
|
clickLink(routePath, e) {
|
||||||
|
if (!this.isExternalLink(routePath)) {
|
||||||
|
e.preventDefault()
|
||||||
|
const path = this.resolvePath(routePath)
|
||||||
|
this.$router.push(path)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
generateTitle
|
generateTitle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
beforeCreate() {
|
||||||
|
const path = this.$route.params.path
|
||||||
|
this.$router.replace('/' + path)
|
||||||
|
},
|
||||||
|
render: function(h) {
|
||||||
|
return h() // avoid warning message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
Loading…
Reference in New Issue