'admin-21.01.20:处理路由、页面切换动画'

This commit is contained in:
lyt 2021-01-20 18:52:41 +08:00
parent 889645769b
commit e633bb7df6
14 changed files with 413 additions and 299 deletions

View File

@ -1,5 +1,5 @@
# port 端口号 # port 端口号
VITE_PORT = 9000 VITE_PORT = 10000
# open 运行 npm run dev 时自动打开浏览器 # open 运行 npm run dev 时自动打开浏览器
VITE_OPEN = false VITE_OPEN = false

View File

@ -3,3 +3,4 @@ declare module '*.json';
declare module '*.png'; declare module '*.png';
declare module '*.jpg'; declare module '*.jpg';
declare module '*.scss'; declare module '*.scss';
declare module '*.ts';

View File

@ -1,6 +1,6 @@
import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router" import { createRouter, createWebHashHistory, RouteRecordRaw } from "vue-router"
const dynamicRoutes = [ export const dynamicRoutes = [
{ {
path: '/', path: '/',
component: () => import('/@/views/layout/index.vue'), component: () => import('/@/views/layout/index.vue'),
@ -11,185 +11,187 @@ const dynamicRoutes = [
isHide: false, isHide: false,
icon: 'iconfont icon-shouye' icon: 'iconfont icon-shouye'
}, },
children: [{ children: [
path: '/home', {
component: () => import('/@/views/home/index.vue'), path: '/home',
meta: { component: () => import('/@/views/home/index.vue'),
title: '首页', meta: {
isLink: '', title: '首页',
isHide: false, isLink: '',
icon: 'iconfont icon-shouye' isHide: false,
} icon: 'iconfont icon-shouye'
},
{
path: '/system',
component: () => import('/@/views/docs/index.vue'),
redirect: '/system/menu',
meta: {
title: '系统设置',
isLink: '',
isHide: false,
icon: 'iconfont icon-xitongshezhi'
},
children: [
{
path: '/system/menu',
component: () => import('/@/views/docs/index.vue'),
meta: {
title: '菜单管理',
isLink: '',
isHide: false,
icon: 'iconfont icon-caidan'
}
},
{
path: '/system/user',
component: () => import('/@/views/docs/index.vue'),
meta: {
title: '用户管理',
isLink: '',
isHide: false,
icon: 'iconfont icon-icon-'
}
} }
] }
]
},
{
path: '/system',
component: () => import('/@/views/layout/index.vue'),
redirect: '/system/menu',
meta: {
title: '系统设置',
isLink: '',
isHide: false,
icon: 'iconfont icon-xitongshezhi'
}, },
{ children: [
path: '/limits', {
component: () => import('/@/views/docs/index.vue'), path: '/system/menu',
redirect: '/limits/frontEnd', component: () => import('/@/views/system/menu/index.vue'),
meta: { meta: {
title: '权限管理', title: '菜单管理',
isLink: '', isLink: '',
isHide: false, isHide: false,
icon: 'iconfont icon-quanxian' icon: 'iconfont icon-caidan'
}
}, },
children: [ {
{ path: '/system/user',
path: '/limits/frontEnd', component: () => import('/@/views/system/user/index.vue'),
component: () => import('/@/views/docs/index.vue'), meta: {
redirect: '/limits/frontEnd/page', title: '用户管理',
meta: { isLink: '',
title: '前端控制', isHide: false,
isLink: '', icon: 'iconfont icon-icon-'
isHide: false }
}, }
children: [ ]
{ },
path: '/limits/frontEnd/page', {
component: () => import('/@/views/docs/index.vue'), path: '/limits',
meta: { component: () => import('/@/views/docs/index.vue'),
title: '页面权限', redirect: '/limits/frontEnd',
isLink: '', meta: {
isHide: false title: '权限管理',
} isLink: '',
}, isHide: false,
{ icon: 'iconfont icon-quanxian'
path: '/limits/frontEnd/btn', },
component: () => import('/@/views/docs/index.vue'), children: [
meta: { {
title: '按钮权限', path: '/limits/frontEnd',
isLink: '', component: () => import('/@/views/docs/index.vue'),
isHide: false redirect: '/limits/frontEnd/page',
} meta: {
title: '前端控制',
isLink: '',
isHide: false
},
children: [
{
path: '/limits/frontEnd/page',
component: () => import('/@/views/docs/index.vue'),
meta: {
title: '页面权限',
isLink: '',
isHide: false
}
},
{
path: '/limits/frontEnd/btn',
component: () => import('/@/views/docs/index.vue'),
meta: {
title: '按钮权限',
isLink: '',
isHide: false
} }
]
},
{
path: '/limits/backEnd',
component: () => import('/@/views/docs/index.vue'),
meta: {
title: '后端控制',
isLink: '',
isHide: false
} }
]
},
{
path: '/limits/backEnd',
component: () => import('/@/views/docs/index.vue'),
meta: {
title: '后端控制',
isLink: '',
isHide: false
} }
]
},
{
path: '/fun',
component: () => import('/@/views/docs copy 1/index.vue'),
meta: {
title: '功能',
isLink: '',
isHide: false,
icon: 'iconfont icon-crew_feature'
} }
}, ]
{ },
path: '/pages', {
component: () => import('/@/views/docs copy 1/index.vue'), path: '/fun',
meta: { component: () => import('/@/views/docs copy 1/index.vue'),
title: '页面', meta: {
isLink: '', title: '功能',
isHide: false, isLink: '',
icon: 'iconfont icon-fuzhiyemian' isHide: false,
} icon: 'iconfont icon-crew_feature'
}, }
{ },
path: '/components', {
component: () => import('/@/views/docs copy 1/index.vue'), path: '/pages',
meta: { component: () => import('/@/views/docs copy 1/index.vue'),
title: '组件', meta: {
isLink: '', title: '页面',
isHide: false, isLink: '',
icon: 'iconfont icon-zujian' isHide: false,
} icon: 'iconfont icon-fuzhiyemian'
}, }
{ },
path: '/chart', {
component: () => import('/@/views/docs copy 1/index.vue'), path: '/components',
meta: { component: () => import('/@/views/docs copy 1/index.vue'),
title: '大数据图表', meta: {
isLink: '', title: '组件',
isHide: false, isLink: '',
icon: 'iconfont icon-ico_shuju' isHide: false,
} icon: 'iconfont icon-zujian'
}, }
{ },
path: '/docs1', {
component: () => import('/@/views/docs copy 1/index.vue'), path: '/chart',
meta: { component: () => import('/@/views/docs copy 1/index.vue'),
title: '个人中心', meta: {
isLink: '', title: '大数据图表',
isHide: false, isLink: '',
icon: 'iconfont icon-gerenzhongxin' isHide: false,
} icon: 'iconfont icon-ico_shuju'
}, }
{ },
path: '/docs2', {
component: () => import('/@/views/docs copy 2/index.vue'), path: '/docs1',
meta: { component: () => import('/@/views/docs copy 1/index.vue'),
title: '工具类集合', meta: {
isLink: '', title: '个人中心',
isHide: false, isLink: '',
icon: 'iconfont icon-gongju' isHide: false,
} icon: 'iconfont icon-gerenzhongxin'
}, }
{ },
path: '/docs3', {
component: () => import('/@/views/docs copy 3/index.vue'), path: '/docs2',
meta: { component: () => import('/@/views/docs copy 2/index.vue'),
title: '外链', meta: {
isLink: '', title: '工具类集合',
isHide: false, isLink: '',
icon: 'iconfont icon-caozuo-wailian' isHide: false,
} icon: 'iconfont icon-gongju'
}, }
{ },
path: '/iframe', {
component: () => import('/@/views/docs copy 3/index.vue'), path: '/docs3',
meta: { component: () => import('/@/views/docs copy 3/index.vue'),
title: '内嵌 iframe', meta: {
isLink: '', title: '外链',
isHide: false, isLink: '',
icon: 'iconfont icon-neiqianshujuchucun' isHide: false,
} icon: 'iconfont icon-caozuo-wailian'
}] }
},
{
path: '/iframe',
component: () => import('/@/views/docs copy 3/index.vue'),
meta: {
title: '内嵌 iframe',
isLink: '',
isHide: false,
icon: 'iconfont icon-neiqianshujuchucun'
}
} }
] ]
const staticRoutes: Array<RouteRecordRaw> = [ export const staticRoutes: Array<RouteRecordRaw> = [
{ {
path: '/login', path: '/login',
component: () => import('/@/views/login/index.vue'), component: () => import('/@/views/login/index.vue'),

View File

@ -1,6 +1,7 @@
import { InjectionKey } from 'vue' import { InjectionKey } from 'vue'
import { createStore, useStore as baseUseStore, Store } from 'vuex' import { createStore, useStore as baseUseStore, Store } from 'vuex'
import themeConfig from '../utils/themeConfig' import themeConfig from '/@/utils/themeConfig.ts'
import { dynamicRoutes } from '/@/router/index.ts'
export interface RootStateTypes { export interface RootStateTypes {
themeConfig: { themeConfig: {
isDrawer: boolean, isDrawer: boolean,
@ -40,23 +41,31 @@ export interface RootStateTypes {
animation: string, animation: string,
columnsAsideStyle: string, columnsAsideStyle: string,
layout: string layout: string
} },
routes: Array<object>
} }
export const key: InjectionKey<Store<RootStateTypes>> = Symbol() export const key: InjectionKey<Store<RootStateTypes>> = Symbol()
export const store = createStore<RootStateTypes>({ export const store = createStore<RootStateTypes>({
state: { state: {
themeConfig themeConfig,
routes: []
}, },
mutations: { mutations: {
getThemeConfig(state: any, data: object) { getThemeConfig(state: any, data: object) {
state.themeConfig = Object.assign({}, data) state.themeConfig = Object.assign({}, data)
},
getRoutes(state: any, data: Array<object>) {
state.routes = data
} }
}, },
actions: { actions: {
setThemeConfig({ commit }, data: object) { setThemeConfig({ commit }, data: object) {
commit('getThemeConfig', data) commit('getThemeConfig', data)
},
async setRoutes({ commit }) {
commit('getRoutes', dynamicRoutes)
} }
} }
}) })

View File

@ -37,15 +37,16 @@
------------------------------- */ ------------------------------- */
.breadcrumb-enter-active, .breadcrumb-enter-active,
.breadcrumb-leave-active { .breadcrumb-leave-active {
will-change: transform; transition: all 0.3s;
transition: all 0.3s ease;
position: absolute;
opacity: 0;
} }
.breadcrumb-enter-from, .breadcrumb-enter-from,
.breadcrumb-leave-to { .breadcrumb-leave-active {
opacity: 0;
transform: translateX(20px); transform: translateX(20px);
} }
.breadcrumb-leave-active {
position: absolute;
}
/* logo 过渡动画 /* logo 过渡动画
------------------------------- */ ------------------------------- */

View File

@ -16,3 +16,29 @@
-webkit-line-clamp: $line; -webkit-line-clamp: $line;
-webkit-box-orient: vertical; -webkit-box-orient: vertical;
} }
/* 滚动条(页面未使用) div 中使用
------------------------------- */
// .test {
// @include scrollBar;
// }
@mixin scrollBar {
// 滚动条凹槽的颜色还可以设置边框属性
&::-webkit-scrollbar-track-piece {
background-color: #f8f8f8;
}
// 滚动条的宽度
&::-webkit-scrollbar {
width: 9px;
height: 9px;
}
// 滚动条的设置
&::-webkit-scrollbar-thumb {
background-color: #dddddd;
background-clip: padding-box;
min-height: 28px;
}
&::-webkit-scrollbar-thumb:hover {
background-color: #bbb;
}
}

View File

@ -1,5 +1,5 @@
// 字体图标 url // 字体图标 url
const urlArr = ["//at.alicdn.com/t/font_2298093_0pyjdtieuwp.css"] const urlArr = ["//at.alicdn.com/t/font_2298093_anmim41evr5.css"]
// 动态设置字体图标 // 动态设置字体图标
export function setIconfont() { export function setIconfont() {

View File

@ -1,89 +1,101 @@
<template> <template>
home <div>
<p>home</p> <el-input v-model="val"></el-input>
<p>home</p> home
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home</p> <p>home</p>
<p>home123123</p> <p>home</p>
<p>home</p>
<p>home123123</p>
</div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { toRefs, reactive } from "vue";
export default { export default {
name: "home", name: "home",
setup() {
const state = reactive({
val: "",
});
return {
...toRefs(state),
};
},
}; };
</script> </script>

View File

@ -17,7 +17,6 @@ import {
ref, ref,
onBeforeMount, onBeforeMount,
} from "vue"; } from "vue";
import { useRouter } from "vue-router";
import { useStore } from "/@/store/index.ts"; import { useStore } from "/@/store/index.ts";
import Logo from "/@/views/layout/logo/index.vue"; import Logo from "/@/views/layout/logo/index.vue";
import Vertical from "/@/views/layout/navMenu/vertical.vue"; import Vertical from "/@/views/layout/navMenu/vertical.vue";
@ -26,20 +25,14 @@ export default {
components: { Logo, Vertical }, components: { Logo, Vertical },
setup() { setup() {
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const router = useRouter();
const store = useStore(); const store = useStore();
const state = reactive({ const state = reactive({
menuList: [], menuList: [],
}); });
// // // //
const setFilterRoutes = () => { const setFilterRoutes = () => {
const routesList = router.getRoutes(); store.dispatch("setRoutes");
routesList.map((route) => { state.menuList = filterRoutesFun(store.state.routes);
if (route.path === "/") {
state.menuList = filterRoutesFun(route.children);
console.log(filterRoutesFun(route.children));
}
});
}; };
// //
const filterRoutesFun = (arr: Array<object>) => { const filterRoutesFun = (arr: Array<object>) => {

View File

@ -2,15 +2,7 @@
<el-main> <el-main>
<el-scrollbar class="layout-scrollbar" ref="layoutScrollbarRef" <el-scrollbar class="layout-scrollbar" ref="layoutScrollbarRef"
:style="{minHeight: `calc(100vh - ${headerHeight}`}"> :style="{minHeight: `calc(100vh - ${headerHeight}`}">
<router-view v-slot="{ Component }"> <LayoutParentView />
<transition :name="setTransitionName" mode="out-in">
<div :key="key">
<keep-alive>
<component :is="Component" />
</keep-alive>
</div>
</transition>
</router-view>
<Footer v-if="getThemeConfig.isFooter" /> <Footer v-if="getThemeConfig.isFooter" />
</el-scrollbar> </el-scrollbar>
</el-main> </el-main>
@ -25,36 +17,22 @@ import {
getCurrentInstance, getCurrentInstance,
watch, watch,
} from "vue"; } from "vue";
import { useRoute } from "vue-router";
import { useStore } from "/@/store/index.ts"; import { useStore } from "/@/store/index.ts";
import LayoutParentView from "/@/views/layout/routerView/parent.vue";
import Footer from "/@/views/layout/footer/index.vue"; import Footer from "/@/views/layout/footer/index.vue";
export default defineComponent({ export default defineComponent({
name: "layoutMain", name: "layoutMain",
components: { Footer }, components: { LayoutParentView, Footer },
setup() { setup() {
const { proxy } = getCurrentInstance(); const { proxy } = getCurrentInstance();
const store = useStore(); const store = useStore();
const route = useRoute();
const state = reactive({ const state = reactive({
transitionName: "slide-right",
headerHeight: "84px", headerHeight: "84px",
}); });
//
const setTransitionName = computed(() => {
let { animation } = store.state.themeConfig;
if (animation === "slideRight")
return (state.transitionName = "slide-right");
else if (animation === "slideLeft")
return (state.transitionName = "slide-left");
else if (animation === "opacitys")
return (state.transitionName = "opacitys");
});
// //
const getThemeConfig = computed(() => { const getThemeConfig = computed(() => {
return store.state.themeConfig; return store.state.themeConfig;
}); });
// key
const key = computed(() => route.path);
// themeConfig el-scrollbar // themeConfig el-scrollbar
watch(store.state.themeConfig, (val) => { watch(store.state.themeConfig, (val) => {
state.headerHeight = val.isTagsview ? "84px" : "50px"; state.headerHeight = val.isTagsview ? "84px" : "50px";
@ -65,8 +43,6 @@ export default defineComponent({
}); });
return { return {
getThemeConfig, getThemeConfig,
setTransitionName,
key,
...toRefs(state), ...toRefs(state),
}; };
}, },

View File

@ -0,0 +1,61 @@
<template>
<router-view v-slot="{ Component }" :key="Math.random()">
<transition :name="setTransitionName" mode="out-in">
<keep-alive>
<component :is="Component" />
</keep-alive>
</transition>
</router-view>
</template>
<script lang="ts">
import {
computed,
defineComponent,
toRefs,
reactive,
getCurrentInstance,
watch,
} from "vue";
import { useStore } from "/@/store/index.ts";
export default defineComponent({
name: "layoutParentView",
setup() {
const { proxy } = getCurrentInstance();
const store = useStore();
const state = reactive({
transitionName: "slide-right",
headerHeight: "84px",
});
//
const setTransitionName = computed(() => {
let { animation } = store.state.themeConfig;
if (animation === "slideRight")
return (state.transitionName = "slide-right");
else if (animation === "slideLeft")
return (state.transitionName = "slide-left");
else if (animation === "opacitys")
return (state.transitionName = "opacitys");
});
//
const getThemeConfig = computed(() => {
return store.state.themeConfig;
});
// themeConfig el-scrollbar
watch(store.state.themeConfig, (val) => {
state.headerHeight = val.isTagsview ? "84px" : "50px";
if (val.isFixedHeaderChange !== val.isFixedHeader) {
if (!proxy.$refs.layoutScrollbarRef) return false;
proxy.$refs.layoutScrollbarRef.update();
}
});
return {
getThemeConfig,
setTransitionName,
...toRefs(state),
};
},
});
</script>

View File

@ -0,0 +1,21 @@
<template>
<div>
systemMenu
<el-input v-model="val"></el-input>
</div>
</template>
<script lang="ts">
import { toRefs, reactive } from "vue";
export default {
name: "systemMenu",
setup() {
const state = reactive({
val: "",
});
return {
...toRefs(state),
};
},
};
</script>

View File

@ -0,0 +1,12 @@
<template>
<div>
systemUser
</div>
</template>
<script lang="ts">
export default {
name: "systemUser",
setup() {},
};
</script>

View File

@ -7,7 +7,7 @@ const pathResolve = (dir: string): any => {
} }
const alias: Record<string, string> = { const alias: Record<string, string> = {
'/@/': pathResolve('src'), '/@/': pathResolve('src')
} }
const { VITE_PORT, VITE_PUBLIC_PATH, VITE_OPEN } = loadEnv() const { VITE_PORT, VITE_PUBLIC_PATH, VITE_OPEN } = loadEnv()