'admin-21.02.04:处理菜单权限、优化部分界面用户体验等'

This commit is contained in:
lyt-Top 2021-02-04 08:37:20 +08:00
parent 741ce08183
commit 9586a55808
18 changed files with 157 additions and 113 deletions

View File

@ -7,7 +7,7 @@
},
"dependencies": {
"clipboard": "^2.0.6",
"element-plus": "^1.0.2-beta.30",
"element-plus": "^1.0.2-beta.31",
"mitt": "^2.1.0",
"nprogress": "^0.2.0",
"screenfull": "^5.1.0",

View File

@ -165,20 +165,6 @@ export const dynamicRoutes = [
isIframe: false,
auth: ['admin', 'test']
}
},
{
path: '/limits/backEnd/btn',
name: 'limitsBackEndEndBtn',
component: () => import('/@/views/limits/backEnd/btn/index.vue'),
meta: {
title: '按钮权限',
isLink: '',
isHide: false,
isKeepAlive: true,
isAffix: false,
isIframe: false,
auth: ['admin', 'test']
}
}
]
}
@ -190,7 +176,7 @@ export const dynamicRoutes = [
component: () => import('/@/views/layout/routerView/parent.vue'),
redirect: '/menu/menu1',
meta: {
title: '路由嵌套',
title: '菜单嵌套',
isLink: '',
isHide: false,
isKeepAlive: true,
@ -600,6 +586,7 @@ export function initAllFun() {
const token = getSession('token')
if (!token) return false
store.dispatch('setAuths')
store.dispatch('setUserInfos')
setAddRoute() // 添加动态路由
setFilterMenu() // 过滤权限菜单
setCacheTagsViewRoutes() // 添加 keepAlive 缓存

View File

@ -47,7 +47,8 @@ export interface RootStateTypes {
routes: Array<object>,
caches: Array<string>,
tagsViewRoutes: Array<object>,
auths: Array<string>
auths: Array<string>,
userInfos: object
}
export const key: InjectionKey<Store<RootStateTypes>> = Symbol()
@ -58,7 +59,8 @@ export const store = createStore<RootStateTypes>({
routes: [],
caches: [],
tagsViewRoutes: [],
auths: []
auths: [],
userInfos: {}
},
mutations: {
// 设置布局配置
@ -80,7 +82,11 @@ export const store = createStore<RootStateTypes>({
// 设置权限
getAuths(state: any, data: Array<string>) {
state.auths = data
}
},
// 设置用户信息
getUserInfos(state: any, data: object) {
state.userInfos = data
},
},
actions: {
// 设置布局配置
@ -102,15 +108,19 @@ export const store = createStore<RootStateTypes>({
// 设置权限
async setAuths({ commit }, data: Array<string>) {
// 模拟权限,实际项目中,请通过直接走接口获取权限标识
let authList: Array<string> = []
if (getSession('defaultAuthList')) {
authList = getSession('defaultAuthList')
if (data && data.length > 0) {
commit('getAuths', data)
} else {
let defaultAuthList: Array<string> = ['admin', 'btn.add', 'btn.del', 'btn.edit']
if (data && data.length > 0) authList = data
else authList = defaultAuthList
if (getSession('userInfo')) commit('getAuths', getSession('userInfo').authList)
}
},
// 设置用户信息
async setUserInfos({ commit }, data: object) {
if (data) {
commit('getUserInfos', data)
} else {
if (getSession('userInfo')) commit('getUserInfos', getSession('userInfo'))
}
commit('getAuths', authList)
},
}
})

View File

@ -60,7 +60,7 @@ $--color-danger-light-8: mix($--color-whites, $--color-danger, 80%) !default;
$--color-danger-light-9: mix($--color-whites, $--color-danger, 90%) !default;
$--bg-topBar: #ffffff;
$--bg-menuBar: #545c64;
$--bg-columnsMenuBar: #4276ab;
$--bg-columnsMenuBar: #545c64;
$--bg-topBarColor: #606266;
$--bg-menuBarColor: #eaeaea;
$--bg-columnsMenuBarColor: #e6e6e6;

View File

@ -8,7 +8,7 @@ export default {
danger: "#f56c6c",
topBar: "#ffffff",
menuBar: "#545c64",
columnsMenuBar: '#4276ab',
columnsMenuBar: '#545c64',
topBarColor: "#606266",
menuBarColor: "#eaeaea",
columnsMenuBarColor: '#e6e6e6',

View File

@ -105,6 +105,11 @@ export default {
proxy.$refs.layoutAsideScrollbarRef.update();
}
});
//
watch(store.state, (val) => {
if (val.routes.length === state.menuList.length) return false;
setFilterRoutes();
});
//
onBeforeMount(() => {
initMenuFixed(document.body.clientWidth);

View File

@ -162,24 +162,24 @@
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15"
:style="{opacity:getThemeConfig.layout === 'transverse' ? 0.5 : 1}">
<div class="layout-breadcrumb-seting-bar-flex-label">面包屑 Breadcrumb</div>
<div class="layout-breadcrumb-seting-bar-flex-label">开启 Breadcrumb</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isBreadcrumb" :disabled="getThemeConfig.layout === 'transverse'"
@change="onIsBreadcrumbChange"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">开启 Tagsview</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isTagsview" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">开启 Breadcrumb 图标</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isBreadcrumbIcon" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">开启 Tagsview</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isTagsview" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">开启 Tagsview 图标</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
@ -573,7 +573,7 @@ export default defineComponent({
} else {
getThemeConfig.value.isShowLogo = false;
getThemeConfig.value.isBreadcrumb = true;
getThemeConfig.value.isCollapse = true;
getThemeConfig.value.isCollapse = false;
getThemeConfig.value.isTagsview = true;
getThemeConfig.value.isClassicSplitMenu = false;
getThemeConfig.value.menuBar = "#545c64";

View File

@ -20,9 +20,8 @@
:title="isScreenfull ? '开全屏' : '关全屏'" :class="!isScreenfull?'icon-fullscreen':'icon-tuichuquanping'"></i></div>
<el-dropdown :show-timeout="70" :hide-timeout="50" @command="onHandleCommandClick">
<span class="layout-navbars-breadcrumb-user-link">
<img src="https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg"
class="layout-navbars-breadcrumb-user-link-photo mr5" />
{{userInfo.userName === '' ? 'test' : userInfo.userName}}
<img :src="getUserInfos.photo" class="layout-navbars-breadcrumb-user-link-photo mr5" />
{{getUserInfos.userName === '' ? 'test' : getUserInfos.userName}}
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<template #dropdown>
@ -48,7 +47,6 @@ import {
toRefs,
toRef,
ref,
onMounted,
} from "vue";
import { useRouter } from "vue-router";
import { ElMessageBox, ElMessage } from "element-plus";
@ -69,7 +67,6 @@ export default {
const state = reactive({
isScreenfull: false,
isShowUserNewsPopover: false,
userInfo: {},
});
//
const setFlexAutoStyle = computed(() => {
@ -80,6 +77,10 @@ export default {
)
return { flex: 1 };
});
// vuex
const getUserInfos = computed(() => {
return store.state.userInfos;
});
//
const onScreenfullClick = () => {
if (!screenfull.isEnabled) {
@ -140,24 +141,15 @@ export default {
const onUserNewsPopoverClick = () => {
state.isShowUserNewsPopover = !state.isShowUserNewsPopover;
};
// sessionStorage
const initUserInfo = () => {
if (!getSession("userInfo")) return false;
state.userInfo = getSession("userInfo");
};
//
onMounted(() => {
initUserInfo();
});
return {
setFlexAutoStyle,
getUserInfos,
onLayoutSetingClick,
onHandleCommandClick,
onScreenfullClick,
onSearchClick,
onUserNewsPopoverClick,
searchRef,
initUserInfo,
...toRefs(state),
};
},

View File

@ -35,10 +35,11 @@ import {
onBeforeMount,
onUnmounted,
getCurrentInstance,
watch,
} from "vue";
import { useRoute, useRouter, onBeforeRouteUpdate } from "vue-router";
import { useStore } from "/@/store/index.ts";
import { setSession, getSession } from "/@/utils/storage.ts";
import { setSession, getSession, removeSession } from "/@/utils/storage.ts";
import Sortable from "sortablejs";
import Contextmenu from "/@/views/layout/navBars/tagsView/contextmenu.vue";
import Scroll from "/@/views/layout/navBars/tagsView/scroll.vue";
@ -55,13 +56,11 @@ export default {
const router = useRouter();
const state = reactive({
routePath: route.path,
dropdown: {
x: "",
y: "",
},
dropdown: { x: "", y: "" },
tagsRefsIndex: 0,
tagsViewList: [],
sortable: "",
tagsViewRoutesList: [],
});
// tagsView
const setTagsStyle = computed(() => {
@ -80,6 +79,13 @@ export default {
const addBrowserSetSession = (tagsViewList: Array<object>) => {
setSession("tagsViewList", tagsViewList);
};
// vuex tagsViewRoutes
const getTagsViewRoutes = () => {
state.tagsViewList = [];
removeSession("tagsViewList");
state.tagsViewRoutesList = store.state.tagsViewRoutes;
initTagsView();
};
// vuex isAffix
const initTagsView = () => {
if (
@ -88,7 +94,7 @@ export default {
) {
state.tagsViewList = getSession("tagsViewList");
} else {
store.state.tagsViewRoutes.map((v) => {
state.tagsViewRoutesList.map((v) => {
if (v.meta.isAffix && !v.meta.isHide)
state.tagsViewList.push({ ...v });
});
@ -102,7 +108,7 @@ export default {
// 1 tagsViewisHide tagsView
const addTagsView = (path: string) => {
if (state.tagsViewList.some((v) => v.path === path)) return false;
const item = store.state.tagsViewRoutes.find((v) => v.path === path);
const item = state.tagsViewRoutesList.find((v) => v.path === path);
if (item.meta.isLink && !item.meta.isIframe) return false;
if (!item.meta.isHide) state.tagsViewList.push({ ...item });
addBrowserSetSession(state.tagsViewList);
@ -128,7 +134,7 @@ export default {
// 4 tagsViewisAffix
const closeOtherTagsView = (path: string) => {
state.tagsViewList = [];
store.state.tagsViewRoutes.map((v) => {
state.tagsViewRoutesList.map((v) => {
if (v.meta.isAffix && !v.meta.isHide) state.tagsViewList.push({ ...v });
});
addTagsView(path);
@ -136,7 +142,7 @@ export default {
// 5 tagsViewisAffix
const closeAllTagsView = (path: string) => {
state.tagsViewList = [];
store.state.tagsViewRoutes.map((v) => {
state.tagsViewRoutesList.map((v) => {
if (v.meta.isAffix && !v.meta.isHide) {
state.tagsViewList.push({ ...v });
if (state.tagsViewList.some((v) => v.path === path))
@ -221,7 +227,13 @@ export default {
});
}
};
//
// tagsView
watch(store.state, (val) => {
if (val.tagsViewRoutes.length === state.tagsViewRoutesList.length)
return false;
getTagsViewRoutes();
});
//
onBeforeMount(() => {
// 0 1 2 3
proxy.mittBus.on("onCurrentContextmenuClick", (data: object) => {
@ -239,14 +251,15 @@ export default {
// /
proxy.mittBus.off("openOrCloseSortable");
});
//
//
onBeforeUpdate(() => {
tagsRefs.value = [];
});
//
onMounted(() => {
// vuex tagsViewRoutes
getTagsViewRoutes();
initSortable();
initTagsView();
});
//
onBeforeRouteUpdate((to) => {
@ -258,6 +271,7 @@ export default {
return {
isActive,
onContextmenu,
getTagsViewRoutes,
onTagsClick,
tagsRefs,
contextmenuRef,

View File

@ -22,11 +22,7 @@ import {
onUnmounted,
nextTick,
} from "vue";
import {
useRoute,
useRouter,
onBeforeRouteUpdate,
} from "vue-router";
import { useRoute, useRouter } from "vue-router";
import { useStore } from "/@/store/index.ts";
export default defineComponent({
name: "layoutParentView",
@ -37,7 +33,7 @@ export default defineComponent({
const store = useStore();
const state = reactive({
transitionName: "slide-right",
refreshRouterViewKey: route.path,
refreshRouterViewKey: null,
});
//
const setTransitionName = computed(() => {
@ -57,10 +53,6 @@ export default defineComponent({
const getCaches = computed(() => {
return store.state.caches;
});
//
onBeforeRouteUpdate((to) => {
state.refreshRouterViewKey = to.path;
});
//
onBeforeMount(() => {
proxy.mittBus.on("onTagsViewRefreshRouterView", (path: string) => {

View File

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

View File

@ -1,19 +1,83 @@
<template>
<div>
limitsFrontEndPage
<el-input v-model="val"></el-input>
<el-alert :title="`当前用户权限:[${getAuthList}]`" type="success" :closable="false"></el-alert>
<el-card shadow="hover" header="切换用户演示,前端控制不同用户显示不同页面权限" class="mt15">
<el-radio-group v-model="userAuth" size="small" @change="onRadioChange">
<el-radio-button label="admin"></el-radio-button>
<el-radio-button label="test"></el-radio-button>
</el-radio-group>
</el-card>
</div>
</template>
<script lang="ts">
import { toRefs, reactive } from "vue";
import { toRefs, reactive, computed, onMounted } from "vue";
import { useRouter } from "vue-router";
import { useStore } from "/@/store/index.ts";
import {
resetRoute,
setAddRoute,
setFilterMenu,
setCacheTagsViewRoutes,
} from "/@/router/index.ts";
import { setSession } from "/@/utils/storage.ts";
export default {
name: "limitsFrontEndPage",
setup() {
const store = useStore();
const router = useRouter();
const state = reactive({
val: "",
userAuth: "",
});
//
const getAuthList = computed(() => {
return store.state.auths;
});
//
const initUserAuth = () => {
state.userAuth = store.state.auths[0];
};
//
const initAllFun = () => {
setAddRoute();
setFilterMenu();
setCacheTagsViewRoutes();
};
//
const onRadioChange = () => {
resetRoute();
let defaultAuthList: Array<string> = [];
let adminAuthList: Array<string> = [
"admin",
"btn.add",
"btn.del",
"btn.edit",
];
let testAuthList: Array<string> = ["test", "btn.add"];
if (state.userAuth === "admin") defaultAuthList = adminAuthList;
else defaultAuthList = testAuthList;
const userInfos = {
userName: state.userAuth,
photo:
state.userAuth === "admin"
? "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg"
: "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=317673774,2961727727&fm=26&gp=0.jpg",
time: new Date().getTime(),
authList: defaultAuthList,
};
setSession("userInfo", userInfos);
store.dispatch("setAuths", defaultAuthList); // (vuex)
store.dispatch("setUserInfos", userInfos); // (vuex)
initAllFun(); //
};
//
onMounted(() => {
initUserAuth();
});
return {
getAuthList,
onRadioChange,
...toRefs(state),
};
},

View File

@ -78,14 +78,20 @@ export default defineComponent({
let testAuthList: Array<string> = ["test", "btn.add"];
if (state.ruleForm.userName === "admin") defaultAuthList = adminAuthList;
else defaultAuthList = testAuthList;
store.dispatch("setAuths", defaultAuthList);
initAllFun();
setSession("defaultAuthList", defaultAuthList);
setSession("token", Math.random().toString(36).substr(0));
setSession("userInfo", {
const userInfos = {
userName: state.ruleForm.userName,
photo:
state.ruleForm.userName === "admin"
? "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg"
: "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=317673774,2961727727&fm=26&gp=0.jpg",
time: new Date().getTime(),
});
authList: defaultAuthList,
};
setSession("token", Math.random().toString(36).substr(0));
setSession("userInfo", userInfos);
store.dispatch("setAuths", defaultAuthList); // (vuex)
store.dispatch("setUserInfos", userInfos); // (vuex)
initAllFun(); //
router.push("/");
setTimeout(() => {
ElMessage.success(`${currentTimeInfo},欢迎回来!`);

View File

@ -1,7 +1,6 @@
<template>
<div>
menu11
<el-input v-model="val"></el-input>
<el-input v-model="val" placeholder="menu11请输入内容测试路由缓存"></el-input>
</div>
</template>

View File

@ -1,7 +1,6 @@
<template>
<div>
menu121
<el-input v-model="val"></el-input>
<el-input v-model="val" placeholder="menu121请输入内容测试路由缓存"></el-input>
</div>
</template>

View File

@ -1,7 +1,6 @@
<template>
<div>
menu122
<el-input v-model="val"></el-input>
<el-input v-model="val" placeholder="menu122请输入内容测试路由缓存"></el-input>
</div>
</template>

View File

@ -1,7 +1,6 @@
<template>
<div>
menu13
<el-input v-model="val"></el-input>
<el-input v-model="val" placeholder="menu13请输入内容测试路由缓存"></el-input>
</div>
</template>

View File

@ -1,7 +1,6 @@
<template>
<div>
menu2
<el-input v-model="val"></el-input>
<el-input v-model="val" placeholder="menu2请输入内容测试路由缓存"></el-input>
</div>
</template>