feat:vue-elemet-admin升级改造
This commit is contained in:
parent
0ec8710e6f
commit
e983182fdb
|
|
@ -10,6 +10,7 @@
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.24.0",
|
||||||
"element-plus": "^1.2.0-beta.3",
|
"element-plus": "^1.2.0-beta.3",
|
||||||
"path-to-regexp": "^6.2.0",
|
"path-to-regexp": "^6.2.0",
|
||||||
|
"screenfull": "^6.0.0",
|
||||||
"vue": "^3.2.16",
|
"vue": "^3.2.16",
|
||||||
"vue-router": "^4.0.12",
|
"vue-router": "^4.0.12",
|
||||||
"vuex": "^4.0.2"
|
"vuex": "^4.0.2"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
<template>
|
||||||
|
<div id="screenfull">
|
||||||
|
<div
|
||||||
|
v-if="isFullscreen"
|
||||||
|
@click="click"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="icon"
|
||||||
|
aria-hidden="true"
|
||||||
|
font-size="40px"
|
||||||
|
>
|
||||||
|
<use xlink:href="#iconshiliangzhinengduixiang1" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
@click="click"
|
||||||
|
v-else
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="icon"
|
||||||
|
aria-hidden="true"
|
||||||
|
font-size="40px"
|
||||||
|
>
|
||||||
|
<use xlink:href="#iconshiliangzhinengduixiang1" />
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import screenfull from 'screenfull'
|
||||||
|
import { ElMessage } from 'element-plus'
|
||||||
|
import {defineComponent,onBeforeUnmount,onMounted,reactive,toRefs} from "vue";
|
||||||
|
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
|
||||||
|
setup(){
|
||||||
|
const state =reactive({
|
||||||
|
isFullscreen: false,
|
||||||
|
click:()=>{
|
||||||
|
if (!screenfull.isEnabled) {
|
||||||
|
ElMessage({
|
||||||
|
message: 'you browser can not work',
|
||||||
|
type: 'warning'
|
||||||
|
})
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
screenfull.toggle()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const change=()=>{
|
||||||
|
if(screenfull.isEnabled){
|
||||||
|
this.isFullscreen = screenfull.isFullscreen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
if (screenfull.isEnabled) {
|
||||||
|
screenfull.on('change', change)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
if (screenfull.isEnabled) {
|
||||||
|
screenfull.off('change', change)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
...toRefs(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.screenfull-svg {
|
||||||
|
display: inline-block;
|
||||||
|
cursor: pointer;
|
||||||
|
fill: #5a5e66;;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
vertical-align: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,23 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<section class="app-main">
|
<section class="app-main">
|
||||||
<transition name="fade-transform" mode="out-in">
|
<router-view v-slot="{ Component }">
|
||||||
<router-view :key="key"/>
|
<transition name="router-fade" mode="out-in">
|
||||||
</transition>
|
<keep-alive :include="cachedViews()">
|
||||||
|
<component :is="Component" :key="key"/>
|
||||||
|
</keep-alive>
|
||||||
|
</transition>
|
||||||
|
</router-view>
|
||||||
</section>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
|
|
||||||
import {useRoute} from "vue-router";
|
<script lang="ts">
|
||||||
import {defineComponent} from "vue";
|
import {defineComponent} from "vue";
|
||||||
|
import {useStore} from '@/store'
|
||||||
|
import {useRoute} from "vue-router";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
setup() {
|
setup() {
|
||||||
|
const store = useStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const cachedViews = () => {
|
||||||
|
return store.state.tagsView.cachedViews
|
||||||
|
}
|
||||||
const key = () => {
|
const key = () => {
|
||||||
return route.path
|
return route.path
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
cachedViews,
|
||||||
key
|
key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,33 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="navbar">
|
<div class="navbar">
|
||||||
<hamburger :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar"/>
|
<hamburger id="hamburger-container" :is-active="sidebar.opened" class="hamburger-container" @toggleClick="toggleSideBar" />
|
||||||
|
|
||||||
<breadcrumb class="breadcrumb-container"/>
|
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" />
|
||||||
|
|
||||||
<div class="right-menu">
|
<div class="right-menu">
|
||||||
<el-dropdown class="avatar-container" trigger="click">
|
<template v-if="device!=='mobile'">
|
||||||
|
<!-- <search id="header-search" class="right-menu-item" />
|
||||||
|
|
||||||
|
<error-log class="errLog-container right-menu-item hover-effect" />-->
|
||||||
|
|
||||||
|
<screenfull id="screenfull" class="right-menu-item hover-effect" />
|
||||||
|
|
||||||
|
<!-- <el-tooltip content="Global Size" effect="dark" placement="bottom">
|
||||||
|
<size-select id="size-select" class="right-menu-item hover-effect" />
|
||||||
|
</el-tooltip>-->
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
|
||||||
<div class="avatar-wrapper">
|
<div class="avatar-wrapper">
|
||||||
<img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar">
|
<img :src="avatar+'?imageView2/1/w/80/h/80'" class="user-avatar">
|
||||||
<i class="el-icon-caret-bottom"/>
|
<i class="el-icon-caret-bottom" />
|
||||||
</div>
|
</div>
|
||||||
<el-dropdown-menu slot="dropdown" class="user-dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
<router-link to="/">
|
<router-link to="/">
|
||||||
<el-dropdown-item>
|
<el-dropdown-item>Dashboard</el-dropdown-item>
|
||||||
Home
|
|
||||||
</el-dropdown-item>
|
|
||||||
</router-link>
|
</router-link>
|
||||||
<a target="_blank" href="https://github.com/PanJiaChen/vue-admin-template/">
|
<a target="_blank" href="https://github.com/PanJiaChen/vue-element-admin/">
|
||||||
<el-dropdown-item>Github</el-dropdown-item>
|
<el-dropdown-item>Github</el-dropdown-item>
|
||||||
</a>
|
</a>
|
||||||
<a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
|
<a target="_blank" href="https://panjiachen.github.io/vue-element-admin-site/#/">
|
||||||
|
|
@ -30,18 +41,19 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {reactive,computed,toRefs} from "vue";
|
import {reactive,computed,toRefs} from "vue";
|
||||||
import {useStore} from "@/store";
|
import {useStore} from "@/store";
|
||||||
import {useRoute,useRouter} from "vue-router"
|
import {useRoute,useRouter} from "vue-router"
|
||||||
import Breadcrumb from '@/components/Breadcrumb/index.vue'
|
import Breadcrumb from '@/components/Breadcrumb/index.vue'
|
||||||
import Hamburger from '@/components/Hamburger/index.vue'
|
import Hamburger from '@/components/Hamburger/index.vue'
|
||||||
|
import Screenfull from '@/components/screenfull/index.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
Breadcrumb,
|
Breadcrumb,
|
||||||
Hamburger
|
Hamburger,
|
||||||
|
Screenfull
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@
|
||||||
<script>
|
<script>
|
||||||
import {computed, defineComponent} from "vue";
|
import {computed, defineComponent} from "vue";
|
||||||
import SidebarItem from './SidebarItem.vue'
|
import SidebarItem from './SidebarItem.vue'
|
||||||
import SidebarLogo from './Logo.vue'
|
import Logo from './Logo.vue'
|
||||||
import variables from '@styles/variables.scss'
|
import variables from '@styles/variables.scss'
|
||||||
import {useStore} from '@/store'
|
import {useStore} from '@/store'
|
||||||
import {useRoute} from 'vue-router'
|
import {useRoute} from 'vue-router'
|
||||||
|
|
@ -31,7 +31,7 @@ import {useRoute} from 'vue-router'
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
components: {
|
components: {
|
||||||
SidebarItem,
|
SidebarItem,
|
||||||
SidebarLogo
|
Logo
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
|
|
@ -39,6 +39,9 @@ export default defineComponent({
|
||||||
const sidebar = computed(() => {
|
const sidebar = computed(() => {
|
||||||
return store.state.app.sidebar
|
return store.state.app.sidebar
|
||||||
})
|
})
|
||||||
|
const routes = computed(() => {
|
||||||
|
return store.state.permission.routes
|
||||||
|
})
|
||||||
const showLogo = computed(() => {
|
const showLogo = computed(() => {
|
||||||
return store.state.settings.sidebarLogo
|
return store.state.settings.sidebarLogo
|
||||||
})
|
})
|
||||||
|
|
@ -56,7 +59,7 @@ export default defineComponent({
|
||||||
|
|
||||||
return {
|
return {
|
||||||
sidebar,
|
sidebar,
|
||||||
route,
|
routes,
|
||||||
showLogo,
|
showLogo,
|
||||||
variables,
|
variables,
|
||||||
activeMenu,
|
activeMenu,
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,9 @@ export default defineComponent({
|
||||||
const instance = getCurrentInstance()
|
const instance = getCurrentInstance()
|
||||||
const currentRoute = useRoute()
|
const currentRoute = useRoute()
|
||||||
const scrollPaneRef = ref(null)
|
const scrollPaneRef = ref(null)
|
||||||
const {ctx} = instance
|
const {ctx} = instance as any
|
||||||
|
|
||||||
const toLastView=(visitedViews,view)=>{
|
const toLastView=(visitedViews:TagView[],view:TagView)=>{
|
||||||
const latestView = visitedViews.slice(-1)[0]
|
const latestView = visitedViews.slice(-1)[0]
|
||||||
if (latestView && latestView.fullPath) {
|
if (latestView && latestView.fullPath) {
|
||||||
router.push(latestView.fullPath)
|
router.push(latestView.fullPath)
|
||||||
|
|
@ -70,12 +70,12 @@ export default defineComponent({
|
||||||
visible: false,
|
visible: false,
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
selectedTag: {},
|
selectedTag: {} as TagView,
|
||||||
affixTags: [],
|
affixTags: [] as TagView[],
|
||||||
isActive: (route) => {
|
isActive: (route:TagView) => {
|
||||||
return route.path === currentRoute.path
|
return route.path === currentRoute.path
|
||||||
},
|
},
|
||||||
isAffix: (tag) => {
|
isAffix: (tag:TagView) => {
|
||||||
return tag.meta && tag.meta.affix
|
return tag.meta && tag.meta.affix
|
||||||
},
|
},
|
||||||
refreshSelectedTag: (view: TagView) => {
|
refreshSelectedTag: (view: TagView) => {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="classObj" class="app-wrapper">
|
<div :class="classObj" class="app-wrapper">
|
||||||
<div v-if="device==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
|
<div v-if="classObj.mobile==='mobile'&&sidebar.opened" class="drawer-bg" @click="handleClickOutside"/>
|
||||||
<sidebar class="sidebar-container"/>
|
<sidebar class="sidebar-container"/>
|
||||||
<div :class="{hasTagsView:needTagsView}" class="main-container">
|
<div :class="{hasTagsView:needTagsView}" class="main-container">
|
||||||
<div :class="{'fixed-header':fixedHeader}">
|
<div :class="{'fixed-header':fixedHeader}">
|
||||||
|
|
@ -8,20 +8,23 @@
|
||||||
<tags-view v-if="needTagsView"/>
|
<tags-view v-if="needTagsView"/>
|
||||||
</div>
|
</div>
|
||||||
<app-main/>
|
<app-main/>
|
||||||
|
<!--
|
||||||
<right-panel v-if="showSettings">
|
<right-panel v-if="showSettings">
|
||||||
<settings/>
|
<settings/>
|
||||||
</right-panel>
|
</right-panel>
|
||||||
|
-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {computed, defineComponent, onBeforeMount, onBeforeUnmount, onMounted, reactive, toRefs} from "vue";
|
import {computed, defineComponent, onBeforeMount, onBeforeUnmount, onMounted, reactive, toRefs, watch} from "vue";
|
||||||
import {AppMain,Navbar, Settings,Sidebar,TagsView } from './components'
|
import {AppMain, Navbar, Settings, Sidebar, TagsView} from './components/index.ts'
|
||||||
import resize from './mixin/ResizeHandler'
|
|
||||||
import {useStore} from "@store";
|
import {useStore} from "@store";
|
||||||
|
import {useRoute} from "vue-router";
|
||||||
|
const {body} = document
|
||||||
|
const WIDTH = 992
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Layout',
|
name: 'Layout',
|
||||||
|
|
@ -34,14 +37,50 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const {
|
|
||||||
sidebar,
|
const device = computed(() => {
|
||||||
device,
|
return store.state.app.device
|
||||||
resizeMounted,
|
})
|
||||||
addEventListenerOnResize,
|
|
||||||
removeEventListenerResize,
|
const sidebar = computed(() => {
|
||||||
watchRouter
|
return store.state.app.sidebar
|
||||||
} = resize()
|
})
|
||||||
|
|
||||||
|
const isMobile = () => {
|
||||||
|
const rect = body.getBoundingClientRect()
|
||||||
|
return rect.width - 1 < WIDTH
|
||||||
|
}
|
||||||
|
|
||||||
|
const resizeHandler = () => {
|
||||||
|
if (!document.hidden) {
|
||||||
|
store.dispatch('app/toggleDevice', isMobile() ? 'mobile' : 'desktop')
|
||||||
|
if (isMobile()) {
|
||||||
|
store.dispatch('app/closeSideBar', {withoutAnimation: true})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const resizeMounted = () => {
|
||||||
|
if (isMobile()) {
|
||||||
|
store.dispatch('app/toggleDevice', 'mobile')
|
||||||
|
store.dispatch('app/closeSideBar', {withoutAnimation: true})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const addEventListenerOnResize = () => {
|
||||||
|
window.addEventListener('resize', resizeHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
const removeEventListenerResize = () => {
|
||||||
|
window.removeEventListener('resize', resizeHandler)
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentRoute = useRoute()
|
||||||
|
const watchRouter = watch(() => currentRoute.name, () => {
|
||||||
|
if (store.state.app.device === 'mobile' && store.state.app.sidebar.opened) {
|
||||||
|
store.dispatch('app/closeSideBar', false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
handleClickOutside: () => {
|
handleClickOutside: () => {
|
||||||
|
|
@ -57,33 +96,33 @@ export default defineComponent({
|
||||||
mobile: device === 'mobile'
|
mobile: device === 'mobile'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const showSettings=computed(()=>{
|
const showSettings = computed(() => {
|
||||||
return store.state.settings.showSettings
|
return store.state.settings.showSettings
|
||||||
})
|
})
|
||||||
|
|
||||||
const needTagsView=computed(()=>{
|
const needTagsView = computed(() => {
|
||||||
return store.state.settings.tagsView
|
return store.state.settings.tagsView
|
||||||
})
|
})
|
||||||
|
|
||||||
const fixedHeader=computed(()=>{
|
const fixedHeader = computed(() => {
|
||||||
return store.state.settings.fixedHeader
|
return store.state.settings.fixedHeader
|
||||||
})
|
})
|
||||||
|
|
||||||
watchRouter()
|
watchRouter()
|
||||||
|
|
||||||
onBeforeMount(()=>{
|
onBeforeMount(() => {
|
||||||
addEventListenerOnResize()
|
addEventListenerOnResize()
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(()=>{
|
onMounted(() => {
|
||||||
resizeMounted()
|
resizeMounted()
|
||||||
})
|
})
|
||||||
|
|
||||||
onBeforeUnmount(()=>{
|
onBeforeUnmount(() => {
|
||||||
removeEventListenerResize()
|
removeEventListenerResize()
|
||||||
})
|
})
|
||||||
|
|
||||||
return{
|
return {
|
||||||
classObj,
|
classObj,
|
||||||
sidebar,
|
sidebar,
|
||||||
showSettings,
|
showSettings,
|
||||||
|
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
import {useStore} from '@/store'
|
|
||||||
import {computed, watch} from "vue";
|
|
||||||
import { useRoute } from 'vue-router'
|
|
||||||
const store = useStore()
|
|
||||||
|
|
||||||
const {body} = document
|
|
||||||
const WIDTH = 992 // refer to Bootstrap's responsive design
|
|
||||||
|
|
||||||
|
|
||||||
export default function () {
|
|
||||||
const device = computed(() => {
|
|
||||||
return store.state.app.device
|
|
||||||
})
|
|
||||||
|
|
||||||
const sidebar = computed(() => {
|
|
||||||
return store.state.app.sidebar
|
|
||||||
})
|
|
||||||
|
|
||||||
const isMobile = () => {
|
|
||||||
const rect = body.getBoundingClientRect()
|
|
||||||
return rect.width - 1 < WIDTH
|
|
||||||
}
|
|
||||||
|
|
||||||
const resizeHandler = () => {
|
|
||||||
if (!document.hidden) {
|
|
||||||
store.dispatch('app/toggleDevice', isMobile() ? 'mobile' : 'desktop')
|
|
||||||
if (isMobile()) {
|
|
||||||
store.dispatch('app/closeSideBar', {withoutAnimation: true})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const resizeMounted = () => {
|
|
||||||
if(isMobile()){
|
|
||||||
store.dispatch('app/toggleDevice', 'mobile')
|
|
||||||
store.dispatch('app/closeSideBar', {withoutAnimation: true})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const addEventListenerOnResize = () => {
|
|
||||||
window.addEventListener('resize', resizeHandler)
|
|
||||||
}
|
|
||||||
|
|
||||||
const removeEventListenerResize = () => {
|
|
||||||
window.removeEventListener('resize', resizeHandler)
|
|
||||||
}
|
|
||||||
|
|
||||||
const currentRoute = useRoute()
|
|
||||||
const watchRouter = watch(() => currentRoute.name, () => {
|
|
||||||
if (store.state.app.device === 'mobile' && store.state.app.sidebar.opened) {
|
|
||||||
store.dispatch('app/closeSideBar', false)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
device,
|
|
||||||
sidebar,
|
|
||||||
resizeMounted,
|
|
||||||
addEventListenerOnResize,
|
|
||||||
removeEventListenerResize,
|
|
||||||
watchRouter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue