Compare commits
10 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f5563b4eed | ||
|
0c80fba84c | ||
|
4d3bbae183 | ||
|
b6d97f1806 | ||
|
a68413cb8f | ||
|
f9aaaa9091 | ||
|
85492f148f | ||
|
b7ca786751 | ||
|
c32bd73b42 | ||
|
3aacd3cccd |
5
.travis.yml
Executable file
5
.travis.yml
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
language: node_js
|
||||||
|
node_js: stable
|
||||||
|
script: npm run test
|
||||||
|
notifications:
|
||||||
|
email: false
|
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
[](https://github.com/vuejs/vue)
|
[](https://github.com/vuejs/vue)
|
||||||
[](https://github.com/ElemeFE/element)
|
[](https://github.com/ElemeFE/element)
|
||||||
|
[](https://travis-ci.org/PanJiaChen/vue-element-admin)
|
||||||
[](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
|
[](https://github.com/PanJiaChen/vue-element-admin/blob/master/LICENSE)
|
||||||
[]()
|
[]()
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@
|
|||||||
- 动态面包屑
|
- 动态面包屑
|
||||||
- 国际化多语言
|
- 国际化多语言
|
||||||
- 多种动态换肤
|
- 多种动态换肤
|
||||||
- 快捷导航(标签页)
|
- 快捷导航(标签页 支持右键操作)
|
||||||
- 富文本编辑器
|
- 富文本编辑器
|
||||||
- Markdown编辑器
|
- Markdown编辑器
|
||||||
- JSON编辑器
|
- JSON编辑器
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "vue-element-admin",
|
"name": "vue-element-admin",
|
||||||
"version": "3.2.0",
|
"version": "3.3.0",
|
||||||
"description": "A Vue.js admin",
|
"description": "A Vue.js admin",
|
||||||
"author": "Pan <panfree23@gmail.com>",
|
"author": "Pan <panfree23@gmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -10,7 +10,8 @@
|
|||||||
"build:prod": "cross-env NODE_ENV=production env_config=prod node build/build.js",
|
"build:prod": "cross-env NODE_ENV=production env_config=prod node build/build.js",
|
||||||
"build:sit": "cross-env NODE_ENV=production env_config=sit node build/build.js",
|
"build:sit": "cross-env NODE_ENV=production env_config=sit node build/build.js",
|
||||||
"build:sit-preview": "cross-env NODE_ENV=production env_config=sit npm_config_preview=true npm_config_report=true node build/build.js",
|
"build:sit-preview": "cross-env NODE_ENV=production env_config=sit npm_config_preview=true npm_config_report=true node build/build.js",
|
||||||
"lint": "eslint --ext .js,.vue src"
|
"lint": "eslint --ext .js,.vue src",
|
||||||
|
"test": "npm run lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "0.17.1",
|
"axios": "0.17.1",
|
||||||
|
@@ -1,56 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<el-badge :is-dot="true" style="line-height: 30px;" @click.native="dialogTableVisible=true">
|
|
||||||
<el-button size="small" type="primary">
|
|
||||||
<svg t="1492682037685" class="bug-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1863"
|
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64">
|
|
||||||
<path d="M969.142857 548.571429q0 14.848-10.861714 25.709714t-25.709714 10.861714l-128 0q0 97.718857-38.290286 165.705143l118.857143 119.442286q10.861714 10.861714 10.861714 25.709714t-10.861714 25.709714q-10.276571 10.861714-25.709714 10.861714t-25.709714-10.861714l-113.152-112.566857q-2.852571 2.852571-8.557714 7.424t-23.990857 16.274286-37.156571 20.845714-46.848 16.566857-55.442286 7.424l0-512-73.142857 0 0 512q-29.147429 0-58.002286-7.716571t-49.700571-18.870857-37.705143-22.272-24.868571-18.578286l-8.557714-8.009143-104.557714 118.272q-11.446857 11.995429-27.428571 11.995429-13.714286 0-24.576-9.142857-10.861714-10.276571-11.702857-25.417143t8.850286-26.587429l115.419429-129.718857q-33.133714-65.133714-33.133714-156.562286l-128 0q-14.848 0-25.709714-10.861714t-10.861714-25.709714 10.861714-25.709714 25.709714-10.861714l128 0 0-168.009143-98.852571-98.852571q-10.861714-10.861714-10.861714-25.709714t10.861714-25.709714 25.709714-10.861714 25.709714 10.861714l98.852571 98.852571 482.304 0 98.852571-98.852571q10.861714-10.861714 25.709714-10.861714t25.709714 10.861714 10.861714 25.709714-10.861714 25.709714l-98.852571 98.852571 0 168.009143 128 0q14.848 0 25.709714 10.861714t10.861714 25.709714zM694.857143 219.428571l-365.714286 0q0-75.995429 53.430857-129.426286t129.426286-53.430857 129.426286 53.430857 53.430857 129.426286z"
|
|
||||||
p-id="1864"></path>
|
|
||||||
</svg>
|
|
||||||
</el-button>
|
|
||||||
</el-badge>
|
|
||||||
<el-dialog title="bug日志" :visible.sync="dialogTableVisible">
|
|
||||||
<el-table :data="logsList">
|
|
||||||
<el-table-column label="message">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<div>msg:{{ scope.row.err.message }}</div>
|
|
||||||
<br/>
|
|
||||||
<div>url: {{scope.row.url}}</div>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="stack">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
{{ scope.row.err.stack}}
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
|
|
||||||
</el-table>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'errLog',
|
|
||||||
props: {
|
|
||||||
logsList: {
|
|
||||||
type: Array
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
dialogTableVisible: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.bug-svg {
|
|
||||||
width: 1em;
|
|
||||||
height: 1em;
|
|
||||||
vertical-align: -0.15em;
|
|
||||||
fill: currentColor;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
</style>
|
|
77
src/components/ErrorLog/index.vue
Normal file
77
src/components/ErrorLog/index.vue
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-badge :is-dot="true" style="line-height: 30px;" @click.native="dialogTableVisible=true">
|
||||||
|
<el-button size="small" type="danger" class="bug-btn">
|
||||||
|
<svg t="1492682037685" class="bug-svg" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1863"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink" width="128" height="128">
|
||||||
|
<path d="M969.142857 548.571429q0 14.848-10.861714 25.709714t-25.709714 10.861714l-128 0q0 97.718857-38.290286 165.705143l118.857143 119.442286q10.861714 10.861714 10.861714 25.709714t-10.861714 25.709714q-10.276571 10.861714-25.709714 10.861714t-25.709714-10.861714l-113.152-112.566857q-2.852571 2.852571-8.557714 7.424t-23.990857 16.274286-37.156571 20.845714-46.848 16.566857-55.442286 7.424l0-512-73.142857 0 0 512q-29.147429 0-58.002286-7.716571t-49.700571-18.870857-37.705143-22.272-24.868571-18.578286l-8.557714-8.009143-104.557714 118.272q-11.446857 11.995429-27.428571 11.995429-13.714286 0-24.576-9.142857-10.861714-10.276571-11.702857-25.417143t8.850286-26.587429l115.419429-129.718857q-33.133714-65.133714-33.133714-156.562286l-128 0q-14.848 0-25.709714-10.861714t-10.861714-25.709714 10.861714-25.709714 25.709714-10.861714l128 0 0-168.009143-98.852571-98.852571q-10.861714-10.861714-10.861714-25.709714t10.861714-25.709714 25.709714-10.861714 25.709714 10.861714l98.852571 98.852571 482.304 0 98.852571-98.852571q10.861714-10.861714 25.709714-10.861714t25.709714 10.861714 10.861714 25.709714-10.861714 25.709714l-98.852571 98.852571 0 168.009143 128 0q14.848 0 25.709714 10.861714t10.861714 25.709714zM694.857143 219.428571l-365.714286 0q0-75.995429 53.430857-129.426286t129.426286-53.430857 129.426286 53.430857 53.430857 129.426286z"
|
||||||
|
p-id="1864"></path>
|
||||||
|
</svg>
|
||||||
|
</el-button>
|
||||||
|
</el-badge>
|
||||||
|
|
||||||
|
<el-dialog title="Error Log" :visible.sync="dialogTableVisible" width="80%">
|
||||||
|
<el-table :data="logsList" border>
|
||||||
|
<el-table-column label="Message">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div>
|
||||||
|
<span class="message-title">Msg:</span>
|
||||||
|
<el-tag type="danger">{{ scope.row.err.message }}</el-tag>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<div>
|
||||||
|
<span class="message-title" style="padding-right: 10px;">Info: </span>
|
||||||
|
<el-tag type="warning">{{scope.row.vm.$vnode.tag}} error in {{scope.row.info}}</el-tag>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<div>
|
||||||
|
<span class="message-title" style="padding-right: 16px;">Url: </span>
|
||||||
|
<el-tag type="success">{{scope.row.url}}</el-tag>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="Stack">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ scope.row.err.stack}}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'errorLog',
|
||||||
|
props: {
|
||||||
|
logsList: {
|
||||||
|
type: Array
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dialogTableVisible: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.bug-btn.el-button--small {
|
||||||
|
padding: 9px 10px;
|
||||||
|
}
|
||||||
|
.bug-svg {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
vertical-align: -0.15em;
|
||||||
|
fill: currentColor;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.message-title {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #333;
|
||||||
|
font-weight: bold;
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="scroll-container" ref="scrollContainer" @mousewheel="handleScroll">
|
<div class="scroll-container" ref="scrollContainer" @wheel.prevent="handleScroll" >
|
||||||
<div class="scroll-wrapper" ref="scrollWrapper" :style="{top: top + 'px'}">
|
<div class="scroll-wrapper" ref="scrollWrapper" :style="{top: top + 'px'}">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
const delta = 15
|
const delta = 15
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'scrollBar',
|
name: 'scrollBar',
|
||||||
data() {
|
data() {
|
||||||
@@ -17,19 +18,19 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleScroll(e) {
|
handleScroll(e) {
|
||||||
e.preventDefault()
|
const eventDelta = e.wheelDelta || -e.deltaY * 3
|
||||||
const $container = this.$refs.scrollContainer
|
const $container = this.$refs.scrollContainer
|
||||||
const $containerHeight = $container.offsetHeight
|
const $containerHeight = $container.offsetHeight
|
||||||
const $wrapper = this.$refs.scrollWrapper
|
const $wrapper = this.$refs.scrollWrapper
|
||||||
const $wrapperHeight = $wrapper.offsetHeight
|
const $wrapperHeight = $wrapper.offsetHeight
|
||||||
if (e.wheelDelta > 0) {
|
if (eventDelta > 0) {
|
||||||
this.top = Math.min(0, this.top + e.wheelDelta)
|
this.top = Math.min(0, this.top + eventDelta)
|
||||||
} else {
|
} else {
|
||||||
if ($containerHeight - delta < $wrapperHeight) {
|
if ($containerHeight - delta < $wrapperHeight) {
|
||||||
if (this.top < -($wrapperHeight - $containerHeight + delta)) {
|
if (this.top < -($wrapperHeight - $containerHeight + delta)) {
|
||||||
this.top = this.top
|
this.top = this.top
|
||||||
} else {
|
} else {
|
||||||
this.top = Math.max(this.top + e.wheelDelta, $containerHeight - $wrapperHeight - delta)
|
this.top = Math.max(this.top + eventDelta, $containerHeight - $wrapperHeight - delta)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.top = 0
|
this.top = 0
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="scroll-container" ref="scrollContainer" @mousewheel="handleScroll">
|
<div class="scroll-container" ref="scrollContainer" @wheel.prevent="handleScroll">
|
||||||
<div class="scroll-wrapper" ref="scrollWrapper" :style="{left: left + 'px'}">
|
<div class="scroll-wrapper" ref="scrollWrapper" :style="{left: left + 'px'}">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
@@ -18,20 +18,20 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleScroll(e) {
|
handleScroll(e) {
|
||||||
e.preventDefault()
|
const eventDelta = e.wheelDelta || -e.deltaY * 3
|
||||||
const $container = this.$refs.scrollContainer
|
const $container = this.$refs.scrollContainer
|
||||||
const $containerWidth = $container.offsetWidth
|
const $containerWidth = $container.offsetWidth
|
||||||
const $wrapper = this.$refs.scrollWrapper
|
const $wrapper = this.$refs.scrollWrapper
|
||||||
const $wrapperWidth = $wrapper.offsetWidth
|
const $wrapperWidth = $wrapper.offsetWidth
|
||||||
|
|
||||||
if (e.wheelDelta > 0) {
|
if (eventDelta > 0) {
|
||||||
this.left = Math.min(0, this.left + e.wheelDelta)
|
this.left = Math.min(0, this.left + eventDelta)
|
||||||
} else {
|
} else {
|
||||||
if ($containerWidth - padding < $wrapperWidth) {
|
if ($containerWidth - padding < $wrapperWidth) {
|
||||||
if (this.left < -($wrapperWidth - $containerWidth + padding)) {
|
if (this.left < -($wrapperWidth - $containerWidth + padding)) {
|
||||||
this.left = this.left
|
this.left = this.left
|
||||||
} else {
|
} else {
|
||||||
this.left = Math.max(this.left + e.wheelDelta, $containerWidth - $wrapperWidth - padding)
|
this.left = Math.max(this.left + eventDelta, $containerWidth - $wrapperWidth - padding)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.left = 0
|
this.left = 0
|
||||||
@@ -64,6 +64,7 @@ export default {
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
width: 100%;
|
||||||
.scroll-wrapper {
|
.scroll-wrapper {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
@@ -1,14 +1,17 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import errLog from '@/store/errLog'
|
import store from './store'
|
||||||
|
|
||||||
// 生产环境错误日志
|
// 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) {
|
Vue.config.errorHandler = function(err, vm, info, a) {
|
||||||
console.log(err, window.location.href)
|
Vue.nextTick(() => {
|
||||||
errLog.pushLog({
|
store.dispatch('addErrorLog', {
|
||||||
err,
|
err,
|
||||||
url: window.location.href,
|
vm,
|
||||||
vm
|
info,
|
||||||
|
url: window.location.href
|
||||||
})
|
})
|
||||||
}
|
console.error(err, info)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
const errLog = {
|
|
||||||
state: {
|
|
||||||
errLog: []
|
|
||||||
},
|
|
||||||
pushLog(log) {
|
|
||||||
this.state.errLog.unshift(log)
|
|
||||||
},
|
|
||||||
clearLog() {
|
|
||||||
this.state.errLog = []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default errLog
|
|
@@ -11,6 +11,7 @@ const getters = {
|
|||||||
roles: state => state.user.roles,
|
roles: state => state.user.roles,
|
||||||
setting: state => state.user.setting,
|
setting: state => state.user.setting,
|
||||||
permission_routers: state => state.permission.routers,
|
permission_routers: state => state.permission.routers,
|
||||||
addRouters: state => state.permission.addRouters
|
addRouters: state => state.permission.addRouters,
|
||||||
|
errorLogs: state => state.errorLog.logs
|
||||||
}
|
}
|
||||||
export default getters
|
export default getters
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import Vuex from 'vuex'
|
import Vuex from 'vuex'
|
||||||
import app from './modules/app'
|
import app from './modules/app'
|
||||||
|
import errorLog from './modules/errorLog'
|
||||||
import permission from './modules/permission'
|
import permission from './modules/permission'
|
||||||
import tagsView from './modules/tagsView'
|
import tagsView from './modules/tagsView'
|
||||||
import user from './modules/user'
|
import user from './modules/user'
|
||||||
@@ -11,6 +12,7 @@ Vue.use(Vuex)
|
|||||||
const store = new Vuex.Store({
|
const store = new Vuex.Store({
|
||||||
modules: {
|
modules: {
|
||||||
app,
|
app,
|
||||||
|
errorLog,
|
||||||
permission,
|
permission,
|
||||||
tagsView,
|
tagsView,
|
||||||
user
|
user
|
||||||
|
17
src/store/modules/errorLog.js
Normal file
17
src/store/modules/errorLog.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
const errorLog = {
|
||||||
|
state: {
|
||||||
|
logs: []
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
ADD_ERROR_LOG: (state, log) => {
|
||||||
|
state.logs.push(log)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
addErrorLog({ commit }, log) {
|
||||||
|
commit('ADD_ERROR_LOG', log)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default errorLog
|
@@ -29,6 +29,25 @@ const tagsView = {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
DEL_OTHERS_VIEWS: (state, view) => {
|
||||||
|
for (const [i, v] of state.visitedViews.entries()) {
|
||||||
|
if (v.path === view.path) {
|
||||||
|
state.visitedViews = state.visitedViews.slice(i, i + 1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const i of state.cachedViews) {
|
||||||
|
if (i === view.name) {
|
||||||
|
const index = state.cachedViews.indexOf(i)
|
||||||
|
state.cachedViews = state.cachedViews.slice(index, i + 1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DEL_ALL_VIEWS: (state) => {
|
||||||
|
state.visitedViews = []
|
||||||
|
state.cachedViews = []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
@@ -40,6 +59,18 @@ const tagsView = {
|
|||||||
commit('DEL_VISITED_VIEWS', view)
|
commit('DEL_VISITED_VIEWS', view)
|
||||||
resolve([...state.visitedViews])
|
resolve([...state.visitedViews])
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
delOthersViews({ commit, state }, view) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
commit('DEL_OTHERS_VIEWS', view)
|
||||||
|
resolve([...state.visitedViews])
|
||||||
|
})
|
||||||
|
},
|
||||||
|
delAllViews({ commit, state }) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
commit('DEL_ALL_VIEWS')
|
||||||
|
resolve([...state.visitedViews])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -5,3 +5,9 @@
|
|||||||
<!--error code-->
|
<!--error code-->
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'errorTestA'
|
||||||
|
}
|
||||||
|
</script>
|
11
src/views/errorLog/errorTestB.vue
Normal file
11
src/views/errorLog/errorTestB.vue
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
<template>
|
||||||
|
<div></div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
created() {
|
||||||
|
this.b = b // eslint-disable-line
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
@@ -1,21 +1,26 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="errPage-container">
|
<div class="errPage-container">
|
||||||
<err-code></err-code>
|
<errorA></errorA>
|
||||||
|
<errorB></errorB>
|
||||||
|
|
||||||
<h3>请点击右上角bug小图表</h3>
|
<h3>请点击右上角bug小图表</h3>
|
||||||
<code>
|
<code>
|
||||||
现在的管理后台基本都是spa的形式了,它增强了用户体验,但同时也会增加页面出问题的可能性,可能一个小小的疏忽就导致整个页面的死锁。好在Vue官网提供了一个方法来捕获处理异常
|
现在的管理后台基本都是spa的形式了,它增强了用户体验,但同时也会增加页面出问题的可能性,可能一个小小的疏忽就导致整个页面的死锁。好在 Vue 官网提供了一个方法来捕获处理异常.
|
||||||
|
<a target="_blank" class="link-type" href="https://panjiachen.github.io/vue-element-admin-site/#/error?id=%e4%bb%a3%e7%a0%81">文档介绍</a>
|
||||||
</code>
|
</code>
|
||||||
<a href="#"><img src='http://panjiachen.github.io/images/errHandler.png'></a>
|
<a href="#">
|
||||||
|
<img src='https://wpimg.wallstcn.com/360e4842-4db5-42d0-b078-f9a84a825546.gif'>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import errCode from './errcode'
|
import errorA from './errorTestA'
|
||||||
|
import errorB from './errorTestB'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'errorLog',
|
name: 'errorLog',
|
||||||
components: { errCode }
|
components: { errorA, errorB }
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@@ -5,8 +5,7 @@
|
|||||||
<breadcrumb class="breadcrumb-container"></breadcrumb>
|
<breadcrumb class="breadcrumb-container"></breadcrumb>
|
||||||
|
|
||||||
<div class="right-menu">
|
<div class="right-menu">
|
||||||
|
<error-log v-if="errorLogs.length>0" class="errLog-container right-menu-item" :logsList="errorLogs"></error-log>
|
||||||
<error-log v-if="log.length>0" class="errLog-container right-menu-item" :logsList="log"></error-log>
|
|
||||||
|
|
||||||
<el-tooltip effect="dark" content="全屏" placement="bottom">
|
<el-tooltip effect="dark" content="全屏" placement="bottom">
|
||||||
<screenfull class="screenfull right-menu-item"></screenfull>
|
<screenfull class="screenfull right-menu-item"></screenfull>
|
||||||
@@ -57,8 +56,7 @@ import Breadcrumb from '@/components/Breadcrumb'
|
|||||||
import Hamburger from '@/components/Hamburger'
|
import Hamburger from '@/components/Hamburger'
|
||||||
import ThemePicker from '@/components/ThemePicker'
|
import ThemePicker from '@/components/ThemePicker'
|
||||||
import Screenfull from '@/components/Screenfull'
|
import Screenfull from '@/components/Screenfull'
|
||||||
import ErrorLog from '@/components/ErrLog'
|
import ErrorLog from '@/components/ErrorLog'
|
||||||
import errLogStore from 'store/errLog'
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
@@ -68,17 +66,13 @@ export default {
|
|||||||
ErrorLog,
|
ErrorLog,
|
||||||
Screenfull
|
Screenfull
|
||||||
},
|
},
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
log: errLogStore.state.errLog
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters([
|
...mapGetters([
|
||||||
'sidebar',
|
'sidebar',
|
||||||
'name',
|
'name',
|
||||||
'avatar',
|
'avatar',
|
||||||
'language'
|
'language',
|
||||||
|
'errorLogs'
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
@@ -1,10 +1,17 @@
|
|||||||
<template>
|
<template>
|
||||||
<scroll-pane class='tags-view-container' ref='scrollPane'>
|
<div class="tags-view-container">
|
||||||
<router-link ref='tag' class="tags-view-item" :class="isActive(tag)?'active':''" v-for="tag in Array.from(visitedViews)" :to="tag.path":key="tag.path">
|
<scroll-pane class='tags-view-wrapper' ref='scrollPane'>
|
||||||
{{generateTitle(tag.title)}}
|
<router-link ref='tag' class="tags-view-item" :class="isActive(tag)?'active':''" v-for="tag in Array.from(visitedViews)" :to="tag.path" :key="tag.path" @contextmenu.prevent.native="openMenu(tag,$event)">
|
||||||
<span class='el-icon-close' @click='closeViewTags(tag,$event)'></span>
|
{{generateTitle(tag.title)}}
|
||||||
</router-link>
|
<span class='el-icon-close' @click.prevent.stop='closeSelectedTag(tag)'></span>
|
||||||
</scroll-pane>
|
</router-link>
|
||||||
|
</scroll-pane>
|
||||||
|
<ul class='contextmenu' v-show="visible" :style="{left:left+'px',top:top+'px'}">
|
||||||
|
<li @click="closeSelectedTag(selectedTag)">Close</li>
|
||||||
|
<li @click="closeOthersTags">Close Others</li>
|
||||||
|
<li @click="closeAllTags">Close All</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -13,35 +20,46 @@ import { generateTitle } from '@/utils/i18n'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { ScrollPane },
|
components: { ScrollPane },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
selectedTag: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
visitedViews() {
|
visitedViews() {
|
||||||
return this.$store.state.tagsView.visitedViews
|
return this.$store.state.tagsView.visitedViews
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
$route() {
|
||||||
|
this.addViewTags()
|
||||||
|
this.moveToCurrentTag()
|
||||||
|
},
|
||||||
|
visible(value) {
|
||||||
|
if (value) {
|
||||||
|
window.addEventListener('click', this.closeMenu)
|
||||||
|
} else {
|
||||||
|
window.removeEventListener('click', this.closeMenu)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.addViewTags()
|
this.addViewTags()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
generateTitle,
|
generateTitle, // generateTitle by vue-i18n
|
||||||
closeViewTags(view, $event) {
|
|
||||||
this.$store.dispatch('delVisitedViews', view).then((views) => {
|
|
||||||
if (this.isActive(view)) {
|
|
||||||
const latestView = views.slice(-1)[0]
|
|
||||||
if (latestView) {
|
|
||||||
this.$router.push(latestView.path)
|
|
||||||
} else {
|
|
||||||
this.$router.push('/')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
$event.preventDefault()
|
|
||||||
},
|
|
||||||
generateRoute() {
|
generateRoute() {
|
||||||
if (this.$route.name) {
|
if (this.$route.name) {
|
||||||
return this.$route
|
return this.$route
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
|
isActive(route) {
|
||||||
|
return route.path === this.$route.path || route.name === this.$route.name
|
||||||
|
},
|
||||||
addViewTags() {
|
addViewTags() {
|
||||||
const route = this.generateRoute()
|
const route = this.generateRoute()
|
||||||
if (!route) {
|
if (!route) {
|
||||||
@@ -49,9 +67,6 @@ export default {
|
|||||||
}
|
}
|
||||||
this.$store.dispatch('addVisitedViews', route)
|
this.$store.dispatch('addVisitedViews', route)
|
||||||
},
|
},
|
||||||
isActive(route) {
|
|
||||||
return route.path === this.$route.path || route.name === this.$route.name
|
|
||||||
},
|
|
||||||
moveToCurrentTag() {
|
moveToCurrentTag() {
|
||||||
const tags = this.$refs.tag
|
const tags = this.$refs.tag
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
@@ -62,12 +77,35 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
},
|
closeSelectedTag(view) {
|
||||||
watch: {
|
this.$store.dispatch('delVisitedViews', view).then((views) => {
|
||||||
$route() {
|
if (this.isActive(view)) {
|
||||||
this.addViewTags()
|
const latestView = views.slice(-1)[0]
|
||||||
this.moveToCurrentTag()
|
if (latestView) {
|
||||||
|
this.$router.push(latestView.path)
|
||||||
|
} else {
|
||||||
|
this.$router.push('/')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
closeOthersTags() {
|
||||||
|
this.$router.push(this.selectedTag.path)
|
||||||
|
this.$store.dispatch('delOthersViews', this.selectedTag)
|
||||||
|
},
|
||||||
|
closeAllTags() {
|
||||||
|
this.$store.dispatch('delAllViews')
|
||||||
|
this.$router.push('/')
|
||||||
|
},
|
||||||
|
openMenu(tag, e) {
|
||||||
|
this.visible = true
|
||||||
|
this.selectedTag = tag
|
||||||
|
this.left = e.clientX
|
||||||
|
this.top = e.clientY
|
||||||
|
},
|
||||||
|
closeMenu() {
|
||||||
|
this.visible = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,38 +113,61 @@ export default {
|
|||||||
|
|
||||||
<style rel="stylesheet/scss" lang="scss" scoped>
|
<style rel="stylesheet/scss" lang="scss" scoped>
|
||||||
.tags-view-container {
|
.tags-view-container {
|
||||||
background: #fff;
|
.tags-view-wrapper {
|
||||||
height: 34px;
|
|
||||||
border-bottom: 1px solid #d8dce5;
|
|
||||||
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
|
|
||||||
.tags-view-item {
|
|
||||||
display: inline-block;
|
|
||||||
position: relative;
|
|
||||||
height: 26px;
|
|
||||||
line-height: 26px;
|
|
||||||
border: 1px solid #d8dce5;
|
|
||||||
color: #495060;
|
|
||||||
background: #fff;
|
background: #fff;
|
||||||
padding: 0 8px;
|
height: 34px;
|
||||||
font-size: 12px;
|
border-bottom: 1px solid #d8dce5;
|
||||||
margin-left: 5px;
|
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
|
||||||
margin-top: 4px;
|
.tags-view-item {
|
||||||
&:first-of-type {
|
display: inline-block;
|
||||||
margin-left: 15px;
|
position: relative;
|
||||||
|
height: 26px;
|
||||||
|
line-height: 26px;
|
||||||
|
border: 1px solid #d8dce5;
|
||||||
|
color: #495060;
|
||||||
|
background: #fff;
|
||||||
|
padding: 0 8px;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-top: 4px;
|
||||||
|
&:first-of-type {
|
||||||
|
margin-left: 15px;
|
||||||
|
}
|
||||||
|
&.active {
|
||||||
|
background-color: #42b983;
|
||||||
|
color: #fff;
|
||||||
|
border-color: #42b983;
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
background: #fff;
|
||||||
|
display: inline-block;
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 50%;
|
||||||
|
position: relative;
|
||||||
|
margin-right: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.active {
|
}
|
||||||
background-color: #42b983;
|
.contextmenu {
|
||||||
color: #fff;
|
margin: 0;
|
||||||
border-color: #42b983;
|
background: #fff;
|
||||||
&::before {
|
z-index: 2;
|
||||||
content: '';
|
position: absolute;
|
||||||
background: #fff;
|
list-style-type: none;
|
||||||
display: inline-block;
|
padding: 5px 0;
|
||||||
width: 8px;
|
border-radius: 4px;
|
||||||
height: 8px;
|
font-size: 12px;
|
||||||
border-radius: 50%;
|
font-weight: 400;
|
||||||
position: relative;
|
color: #333;
|
||||||
margin-right: 2px;
|
box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, .3);
|
||||||
|
li {
|
||||||
|
margin: 0;
|
||||||
|
padding: 7px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
background: #eee;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -114,7 +175,8 @@ export default {
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style rel="stylesheet/scss" lang="scss">
|
<style rel="stylesheet/scss" lang="scss">
|
||||||
.tags-view-container {
|
//reset element css of el-icon-close
|
||||||
|
.tags-view-wrapper {
|
||||||
.tags-view-item {
|
.tags-view-item {
|
||||||
.el-icon-close {
|
.el-icon-close {
|
||||||
width: 16px;
|
width: 16px;
|
||||||
|
Reference in New Issue
Block a user