'admin-21.02.04:处理分栏布局菜单高亮、编写用户按钮权限组件'
This commit is contained in:
parent
9586a55808
commit
097f87317f
29
vue-admin-wonderful-next/src/views/components/auth/auth.vue
Normal file
29
vue-admin-wonderful-next/src/views/components/auth/auth.vue
Normal file
@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<div v-if="getUserAuthList">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: String,
|
||||
default: () => "",
|
||||
},
|
||||
},
|
||||
nane: "auth",
|
||||
setup(props) {
|
||||
const store = useStore();
|
||||
// 获取 vuex 中的用户权限
|
||||
const getUserAuthList = computed(() => {
|
||||
return store.state.auths.some((v) => v === props.value);
|
||||
});
|
||||
return {
|
||||
getUserAuthList,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
@ -0,0 +1,31 @@
|
||||
<template>
|
||||
{{getUserAuthList}}
|
||||
<div v-if="getUserAuthList">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
export default {
|
||||
nane: "authAll",
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const store = useStore();
|
||||
console.log(store.state);
|
||||
// 获取 vuex 中的用户权限
|
||||
const getUserAuthList = computed(() => {
|
||||
return false;
|
||||
});
|
||||
return {
|
||||
getUserAuthList,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
35
vue-admin-wonderful-next/src/views/components/auth/auths.vue
Normal file
35
vue-admin-wonderful-next/src/views/components/auth/auths.vue
Normal file
@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div v-if="getUserAuthList">
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
nane: "auths",
|
||||
setup(props) {
|
||||
const store = useStore();
|
||||
// 获取 vuex 中的用户权限
|
||||
const getUserAuthList = computed(() => {
|
||||
let flag = false;
|
||||
store.state.auths.map((val) => {
|
||||
props.value.map((v) => {
|
||||
if (val === v) flag = true;
|
||||
});
|
||||
});
|
||||
return flag;
|
||||
});
|
||||
return {
|
||||
getUserAuthList,
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
@ -1,21 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
componentsIndex
|
||||
<el-input v-model="val"></el-input>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive } from "vue";
|
||||
export default {
|
||||
name: "componentsIndex",
|
||||
setup() {
|
||||
const state = reactive({
|
||||
val: "",
|
||||
});
|
||||
return {
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
@ -108,6 +108,8 @@ export default {
|
||||
// 监听路由的变化,动态赋值给菜单中
|
||||
watch(store.state, (val) => {
|
||||
if (val.routes.length === state.menuList.length) return false;
|
||||
let { layout, isClassicSplitMenu } = val.themeConfig;
|
||||
if (layout === "classic" && isClassicSplitMenu) return false;
|
||||
setFilterRoutes();
|
||||
});
|
||||
// 页面加载前
|
||||
@ -119,8 +121,10 @@ export default {
|
||||
});
|
||||
proxy.mittBus.on("setSendClassicChildren", (res) => {
|
||||
let { layout, isClassicSplitMenu } = store.state.themeConfig;
|
||||
if (layout === "classic" && isClassicSplitMenu)
|
||||
if (layout === "classic" && isClassicSplitMenu) {
|
||||
state.menuList = [];
|
||||
state.menuList = res.children;
|
||||
}
|
||||
});
|
||||
proxy.mittBus.on("getBreadcrumbIndexSetFilterRoutes", () => {
|
||||
setFilterRoutes();
|
||||
|
@ -35,6 +35,7 @@ import {
|
||||
onMounted,
|
||||
nextTick,
|
||||
getCurrentInstance,
|
||||
watch,
|
||||
} from "vue";
|
||||
import { useRoute, useRouter, onBeforeRouteUpdate } from "vue-router";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
@ -51,6 +52,7 @@ export default {
|
||||
columnsAsideList: [],
|
||||
liIndex: 0,
|
||||
difference: 0,
|
||||
routeSplit: [],
|
||||
});
|
||||
// 设置高亮样式
|
||||
const setColumnsAsideStyle = computed(() => {
|
||||
@ -64,7 +66,7 @@ export default {
|
||||
return "layout-columns-card-active";
|
||||
});
|
||||
// 设置菜单高亮位置移动
|
||||
const setColumnsAsideMove = (v: Object, k: number) => {
|
||||
const setColumnsAsideMove = (k: number) => {
|
||||
state.liIndex = k;
|
||||
columnsAsideActiveRef.value.style.top = `${
|
||||
columnsAsideOffsetTopRefs.value[k].offsetTop + state.difference
|
||||
@ -72,22 +74,22 @@ export default {
|
||||
};
|
||||
// 菜单高亮点击事件
|
||||
const onColumnsAsideMenuClick = (v: Object, k: number) => {
|
||||
setColumnsAsideMove(v, k);
|
||||
setColumnsAsideMove(k);
|
||||
let { path, redirect } = v;
|
||||
if (redirect) router.push(redirect);
|
||||
else router.push(path);
|
||||
};
|
||||
// 设置高亮动态位置
|
||||
const onColumnsAsideDown = (v: Object, k: number) => {
|
||||
const onColumnsAsideDown = (k: number) => {
|
||||
nextTick(() => {
|
||||
setColumnsAsideMove(v, k);
|
||||
setColumnsAsideMove(k);
|
||||
});
|
||||
};
|
||||
// 设置/过滤路由(非静态路由/是否显示在菜单中)
|
||||
const setFilterRoutes = () => {
|
||||
state.columnsAsideList = filterRoutesFun(store.state.routes);
|
||||
const resData = setSendChildren(route.path);
|
||||
onColumnsAsideDown(resData.item[0], resData.item[0].k);
|
||||
onColumnsAsideDown(resData.item[0].k);
|
||||
proxy.mittBus.emit("setSendColumnsChildren", resData);
|
||||
};
|
||||
// 传送当前子级数据到菜单中
|
||||
@ -114,12 +116,31 @@ export default {
|
||||
return item;
|
||||
});
|
||||
};
|
||||
// tagsView 点击时,根据路由查找下标 columnsAsideList,实现左侧菜单高亮
|
||||
const setColumnsMenuHighlight = (path) => {
|
||||
state.routeSplit = path.split("/");
|
||||
state.routeSplit.shift();
|
||||
const routeFirst = `/${state.routeSplit[0]}`;
|
||||
const currentSplitRoute = state.columnsAsideList.find(
|
||||
(v) => v.path === routeFirst
|
||||
);
|
||||
// 延迟拿值,防止取不到
|
||||
setTimeout(() => {
|
||||
onColumnsAsideDown(currentSplitRoute.k);
|
||||
}, 0);
|
||||
};
|
||||
// 监听路由的变化,动态赋值给菜单中
|
||||
watch(store.state, (val) => {
|
||||
if (val.routes.length === state.columnsAsideList.length) return false;
|
||||
setFilterRoutes();
|
||||
});
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
setFilterRoutes();
|
||||
});
|
||||
// 路由更新时
|
||||
onBeforeRouteUpdate((to) => {
|
||||
setColumnsMenuHighlight(to.path);
|
||||
proxy.mittBus.emit("setSendColumnsChildren", setSendChildren(to.path));
|
||||
});
|
||||
return {
|
||||
|
@ -15,8 +15,9 @@ import {
|
||||
onMounted,
|
||||
onUnmounted,
|
||||
getCurrentInstance,
|
||||
watch,
|
||||
} from "vue";
|
||||
import { useRoute, onBeforeRouteUpdate } from "vue-router";
|
||||
import { useRoute } from "vue-router";
|
||||
import { useStore } from "/@/store/index.ts";
|
||||
import Breadcrumb from "/@/views/layout/navBars/breadcrumb/breadcrumb.vue";
|
||||
import User from "/@/views/layout/navBars/breadcrumb/user.vue";
|
||||
@ -95,6 +96,11 @@ export default {
|
||||
});
|
||||
return currentData;
|
||||
};
|
||||
// 监听路由的变化,动态赋值给菜单中
|
||||
watch(store.state, (val) => {
|
||||
if (val.routes.length === state.menuList.length) return false;
|
||||
setFilterRoutes();
|
||||
});
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
setFilterRoutes();
|
||||
@ -106,13 +112,6 @@ export default {
|
||||
onUnmounted(() => {
|
||||
proxy.mittBus.off("getBreadcrumbIndexSetFilterRoutes");
|
||||
});
|
||||
// 路由更新时
|
||||
onBeforeRouteUpdate((to) => {
|
||||
proxy.mittBus.emit(
|
||||
"setSendClassicChildren",
|
||||
setSendClassicChildren(to.path)
|
||||
);
|
||||
});
|
||||
return {
|
||||
getThemeConfig,
|
||||
setIsShowLogo,
|
||||
|
@ -81,6 +81,7 @@ export default {
|
||||
};
|
||||
// 获取 vuex 中的 tagsViewRoutes 列表
|
||||
const getTagsViewRoutes = () => {
|
||||
state.routePath = route.path;
|
||||
state.tagsViewList = [];
|
||||
removeSession("tagsViewList");
|
||||
state.tagsViewRoutesList = store.state.tagsViewRoutes;
|
||||
@ -185,6 +186,7 @@ export default {
|
||||
};
|
||||
// 当前的 tagsView 项点击时
|
||||
const onTagsClick = (v: object, k: number) => {
|
||||
state.routePath = v.path;
|
||||
state.tagsRefsIndex = k;
|
||||
router.push(v.path);
|
||||
};
|
||||
|
@ -1,7 +1,8 @@
|
||||
<template>
|
||||
<div class="el-menu-horizontal-warp">
|
||||
<el-scrollbar @wheel.native.prevent="onElMenuHorizontalScroll" ref="elMenuHorizontalScrollRef">
|
||||
<el-menu router :default-active="defaultActive" background-color="transparent" mode="horizontal">
|
||||
<el-menu router :default-active="defaultActive" background-color="transparent" mode="horizontal"
|
||||
@select="onHorizontalSelect">
|
||||
<template v-for="val in menuList">
|
||||
<el-submenu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
|
||||
<template #title>
|
||||
@ -90,6 +91,37 @@ export default defineComponent({
|
||||
state.defaultActive = path;
|
||||
}
|
||||
};
|
||||
// 路由过滤递归函数
|
||||
const filterRoutesFun = (arr: Array<object>) => {
|
||||
return arr
|
||||
.filter((item) => !item.meta.isHide)
|
||||
.map((item) => {
|
||||
item = Object.assign({}, item);
|
||||
if (item.children) item.children = filterRoutesFun(item.children);
|
||||
return item;
|
||||
});
|
||||
};
|
||||
// 传送当前子级数据到菜单中
|
||||
const setSendClassicChildren = (path: string) => {
|
||||
const currentPathSplit = path.split("/");
|
||||
let currentData: object = {};
|
||||
filterRoutesFun(store.state.routes).map((v, k) => {
|
||||
if (v.path === `/${currentPathSplit[1]}`) {
|
||||
v["k"] = k;
|
||||
currentData["item"] = [{ ...v }];
|
||||
currentData["children"] = [{ ...v }];
|
||||
if (v.children) currentData["children"] = v.children;
|
||||
}
|
||||
});
|
||||
return currentData;
|
||||
};
|
||||
// 菜单激活回调
|
||||
const onHorizontalSelect = (path) => {
|
||||
proxy.mittBus.emit(
|
||||
"setSendClassicChildren",
|
||||
setSendClassicChildren(path)
|
||||
);
|
||||
};
|
||||
// 页面加载时
|
||||
onMounted(() => {
|
||||
initElMenuOffsetLeft();
|
||||
@ -103,6 +135,7 @@ export default defineComponent({
|
||||
return {
|
||||
menuList,
|
||||
onElMenuHorizontalScroll,
|
||||
onHorizontalSelect,
|
||||
...toRefs(state),
|
||||
};
|
||||
},
|
||||
|
@ -39,6 +39,7 @@ export default defineComponent({
|
||||
nextTick(() => {
|
||||
state.iframeLoading = true;
|
||||
const iframe = document.getElementById("iframe");
|
||||
if (!iframe) return false;
|
||||
iframe.onload = () => {
|
||||
state.iframeLoading = false;
|
||||
};
|
||||
@ -59,7 +60,9 @@ export default defineComponent({
|
||||
});
|
||||
// 页面卸载时
|
||||
onUnmounted(() => {
|
||||
proxy.mittBus.off("onTagsViewRefreshRouterView");
|
||||
proxy.mittBus.off("onTagsViewRefreshRouterView", () => {
|
||||
console.log(1111);
|
||||
});
|
||||
});
|
||||
return {
|
||||
...toRefs(state),
|
||||
|
@ -57,9 +57,9 @@ export default defineComponent({
|
||||
onBeforeMount(() => {
|
||||
proxy.mittBus.on("onTagsViewRefreshRouterView", (path: string) => {
|
||||
if (route.path !== path) return false;
|
||||
state.refreshRouterViewKey = Math.random();
|
||||
state.refreshRouterViewKey = route.path;
|
||||
nextTick(() => {
|
||||
state.refreshRouterViewKey = path;
|
||||
state.refreshRouterViewKey = null;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -1,14 +1,116 @@
|
||||
<template>
|
||||
<div>
|
||||
limitsFrontEndBtn
|
||||
<el-input v-model="val"></el-input>
|
||||
<LimitsFrontEndPage />
|
||||
<el-card shadow="hover" header="演示1:组件方式" class="mt15">
|
||||
<el-row class="mb10" style="color:#808080;">单个权限验证(:value="xxx"):</el-row>
|
||||
<div class="flex-warp">
|
||||
<Auth :value="'btn.add'">
|
||||
<div class="flex-warp-item">
|
||||
<div class="flex-warp-item-box">
|
||||
<el-button type="primary" size="small" icon="el-icon-document-add">新增
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</Auth>
|
||||
<Auth :value="'btn.edit'">
|
||||
<div class="flex-warp-item">
|
||||
<div class="flex-warp-item-box">
|
||||
<el-button type="info" size="small" icon="el-icon-edit-outline">编辑</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</Auth>
|
||||
<Auth :value="'btn.del'">
|
||||
<div class="flex-warp-item">
|
||||
<div class="flex-warp-item-box">
|
||||
<el-button type="danger" size="small" icon="el-icon-delete">删除
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</Auth>
|
||||
<Auth :value="'btn.link'">
|
||||
<div class="flex-warp-item">
|
||||
<div class="flex-warp-item-box">
|
||||
<el-button type="success" size="small" icon="el-icon-link">跳转
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</Auth>
|
||||
</div>
|
||||
<el-row class="mb10 mt10" style="color:#808080;">多个权限验证,有满足一个则显示(:value="[xxx,xxx]"):</el-row>
|
||||
<div class="flex-warp">
|
||||
<Auths :value="['btn.addsss','btn.edit','btn.delsss','btn.linksss']">
|
||||
<div class="flex-warp-item">
|
||||
<div class="flex-warp-item-box">
|
||||
<el-button type="primary" size="small" icon="el-icon-document-add">新增
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</Auths>
|
||||
<Auths :value="['btn.add','btn.edit','btn.del','btn.link']">
|
||||
<div class="flex-warp-item">
|
||||
<div class="flex-warp-item-box">
|
||||
<el-button type="info" size="small" icon="el-icon-edit-outline">编辑</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</Auths>
|
||||
<Auths :value="['btn.add','btn.edit','btn.del','btn.link']">
|
||||
<div class="flex-warp-item">
|
||||
<div class="flex-warp-item-box">
|
||||
<el-button type="danger" size="small" icon="el-icon-delete">删除
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</Auths>
|
||||
<Auths :value="['btn.add','btn.edit','btn.del','btn.link']">
|
||||
<div class="flex-warp-item">
|
||||
<div class="flex-warp-item-box">
|
||||
<el-button type="success" size="small" icon="el-icon-link">跳转
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</Auths>
|
||||
</div>
|
||||
<el-row class="mb10 mt10" style="color:#808080;">多个权限验证,全部满足则显示(:value="[xxx,xxx]"):</el-row>
|
||||
<div class="flex-warp">
|
||||
<AuthAll :value="['btn.add','btn.edit','btn.del','btn.link']">
|
||||
<div class="flex-warp-item">
|
||||
<div class="flex-warp-item-box">
|
||||
<el-button type="primary" size="small" icon="el-icon-document-add">新增
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</AuthAll>
|
||||
<div class="flex-warp-item">
|
||||
<div class="flex-warp-item-box">
|
||||
<el-button type="info" size="small" icon="el-icon-edit-outline">编辑</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-warp-item">
|
||||
<div class="flex-warp-item-box">
|
||||
<el-button type="danger" size="small" icon="el-icon-delete">删除
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-warp-item">
|
||||
<div class="flex-warp-item-box">
|
||||
<el-button type="success" size="small" icon="el-icon-link">跳转
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { toRefs, reactive } from "vue";
|
||||
import LimitsFrontEndPage from "/@/views/limits/frontEnd/page/index.vue";
|
||||
import Auth from "/@/views/components/auth/auth.vue";
|
||||
import Auths from "/@/views/components/auth/auths.vue";
|
||||
import AuthAll from "/@/views/components/auth/authAll.vue";
|
||||
export default {
|
||||
name: "limitsFrontEndBtn",
|
||||
components: { LimitsFrontEndPage, Auth, Auths, AuthAll },
|
||||
setup() {
|
||||
const state = reactive({
|
||||
val: "",
|
||||
@ -18,4 +120,20 @@ export default {
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.flex-warp {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-content: flex-start;
|
||||
margin: 0 -5px;
|
||||
.flex-warp-item {
|
||||
padding: 5px;
|
||||
.flex-warp-item-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,6 +1,8 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-alert :title="`当前用户权限:[${getAuthList}]`" type="success" :closable="false"></el-alert>
|
||||
<el-alert title="温馨提示:此权限页面代码及效果只作为演示使用,若出现不可逆转的bug,请尝试 `F5` 刷新页面。若实际项目中非要实现此用户权限切换功能,
|
||||
请在切换方法 `onRadioChange` 最后面添加刷新代码 `window.location.reload()`。" type="warning" :closable="false"></el-alert>
|
||||
<el-alert :title="`当前用户权限:[${getAuthList}]`" type="success" :closable="false" class="mt15"></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>
|
||||
@ -47,16 +49,17 @@ export default {
|
||||
// 用户权限改变时
|
||||
const onRadioChange = () => {
|
||||
resetRoute();
|
||||
let defaultAuthList: Array<string> = [];
|
||||
let defaultAuthPageList: Array<string> = [];
|
||||
let adminAuthList: Array<string> = [
|
||||
"admin",
|
||||
"btn.add",
|
||||
"btn.del",
|
||||
"btn.edit",
|
||||
"btn.link",
|
||||
];
|
||||
let testAuthList: Array<string> = ["test", "btn.add"];
|
||||
if (state.userAuth === "admin") defaultAuthList = adminAuthList;
|
||||
else defaultAuthList = testAuthList;
|
||||
let testAuthList: Array<string> = ["test", "btn.add", "btn.link"];
|
||||
if (state.userAuth === "admin") defaultAuthPageList = adminAuthList;
|
||||
else defaultAuthPageList = testAuthList;
|
||||
const userInfos = {
|
||||
userName: state.userAuth,
|
||||
photo:
|
||||
@ -64,10 +67,11 @@ export default {
|
||||
? "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,
|
||||
authPageList: defaultAuthPageList,
|
||||
authBtnList: defaultAuthBtnList,
|
||||
};
|
||||
setSession("userInfo", userInfos);
|
||||
store.dispatch("setAuths", defaultAuthList); // 请注意执行顺序(存储用户权限到vuex)
|
||||
// store.dispatch("setAuths", defaultAuthPageList); // 请注意执行顺序(存储用户权限到vuex)
|
||||
store.dispatch("setUserInfos", userInfos); // 请注意执行顺序(存储用户信息vuex)
|
||||
initAllFun(); // 请注意执行顺序
|
||||
};
|
||||
|
@ -74,8 +74,9 @@ export default defineComponent({
|
||||
"btn.add",
|
||||
"btn.del",
|
||||
"btn.edit",
|
||||
"btn.link",
|
||||
];
|
||||
let testAuthList: Array<string> = ["test", "btn.add"];
|
||||
let testAuthList: Array<string> = ["test", "btn.add", "btn.link"];
|
||||
if (state.ruleForm.userName === "admin") defaultAuthList = adminAuthList;
|
||||
else defaultAuthList = testAuthList;
|
||||
const userInfos = {
|
||||
|
Loading…
Reference in New Issue
Block a user