'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 端口号
VITE_PORT = 9000
VITE_PORT = 10000
# open 运行 npm run dev 时自动打开浏览器
VITE_OPEN = false

View File

@ -2,4 +2,5 @@ declare const React: string;
declare module '*.json';
declare module '*.png';
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"
const dynamicRoutes = [
export const dynamicRoutes = [
{
path: '/',
component: () => import('/@/views/layout/index.vue'),
@ -11,185 +11,187 @@ const dynamicRoutes = [
isHide: false,
icon: 'iconfont icon-shouye'
},
children: [{
path: '/home',
component: () => import('/@/views/home/index.vue'),
meta: {
title: '首页',
isLink: '',
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-'
}
children: [
{
path: '/home',
component: () => import('/@/views/home/index.vue'),
meta: {
title: '首页',
isLink: '',
isHide: false,
icon: 'iconfont icon-shouye'
}
]
}
]
},
{
path: '/system',
component: () => import('/@/views/layout/index.vue'),
redirect: '/system/menu',
meta: {
title: '系统设置',
isLink: '',
isHide: false,
icon: 'iconfont icon-xitongshezhi'
},
{
path: '/limits',
component: () => import('/@/views/docs/index.vue'),
redirect: '/limits/frontEnd',
meta: {
title: '权限管理',
isLink: '',
isHide: false,
icon: 'iconfont icon-quanxian'
children: [
{
path: '/system/menu',
component: () => import('/@/views/system/menu/index.vue'),
meta: {
title: '菜单管理',
isLink: '',
isHide: false,
icon: 'iconfont icon-caidan'
}
},
children: [
{
path: '/limits/frontEnd',
component: () => import('/@/views/docs/index.vue'),
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: '/system/user',
component: () => import('/@/views/system/user/index.vue'),
meta: {
title: '用户管理',
isLink: '',
isHide: false,
icon: 'iconfont icon-icon-'
}
}
]
},
{
path: '/limits',
component: () => import('/@/views/docs/index.vue'),
redirect: '/limits/frontEnd',
meta: {
title: '权限管理',
isLink: '',
isHide: false,
icon: 'iconfont icon-quanxian'
},
children: [
{
path: '/limits/frontEnd',
component: () => import('/@/views/docs/index.vue'),
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'),
meta: {
title: '页面',
isLink: '',
isHide: false,
icon: 'iconfont icon-fuzhiyemian'
}
},
{
path: '/components',
component: () => import('/@/views/docs copy 1/index.vue'),
meta: {
title: '组件',
isLink: '',
isHide: false,
icon: 'iconfont icon-zujian'
}
},
{
path: '/chart',
component: () => import('/@/views/docs copy 1/index.vue'),
meta: {
title: '大数据图表',
isLink: '',
isHide: false,
icon: 'iconfont icon-ico_shuju'
}
},
{
path: '/docs1',
component: () => import('/@/views/docs copy 1/index.vue'),
meta: {
title: '个人中心',
isLink: '',
isHide: false,
icon: 'iconfont icon-gerenzhongxin'
}
},
{
path: '/docs2',
component: () => import('/@/views/docs copy 2/index.vue'),
meta: {
title: '工具类集合',
isLink: '',
isHide: false,
icon: 'iconfont icon-gongju'
}
},
{
path: '/docs3',
component: () => import('/@/views/docs copy 3/index.vue'),
meta: {
title: '外链',
isLink: '',
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'
}
}]
]
},
{
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'),
meta: {
title: '页面',
isLink: '',
isHide: false,
icon: 'iconfont icon-fuzhiyemian'
}
},
{
path: '/components',
component: () => import('/@/views/docs copy 1/index.vue'),
meta: {
title: '组件',
isLink: '',
isHide: false,
icon: 'iconfont icon-zujian'
}
},
{
path: '/chart',
component: () => import('/@/views/docs copy 1/index.vue'),
meta: {
title: '大数据图表',
isLink: '',
isHide: false,
icon: 'iconfont icon-ico_shuju'
}
},
{
path: '/docs1',
component: () => import('/@/views/docs copy 1/index.vue'),
meta: {
title: '个人中心',
isLink: '',
isHide: false,
icon: 'iconfont icon-gerenzhongxin'
}
},
{
path: '/docs2',
component: () => import('/@/views/docs copy 2/index.vue'),
meta: {
title: '工具类集合',
isLink: '',
isHide: false,
icon: 'iconfont icon-gongju'
}
},
{
path: '/docs3',
component: () => import('/@/views/docs copy 3/index.vue'),
meta: {
title: '外链',
isLink: '',
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',
component: () => import('/@/views/login/index.vue'),

View File

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

View File

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

View File

@ -16,3 +16,29 @@
-webkit-line-clamp: $line;
-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
const urlArr = ["//at.alicdn.com/t/font_2298093_0pyjdtieuwp.css"]
const urlArr = ["//at.alicdn.com/t/font_2298093_anmim41evr5.css"]
// 动态设置字体图标
export function setIconfont() {

View File

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

View File

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

View File

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