'admin-21.02.04:处理分栏布局菜单高亮、编写用户按钮权限组件'

This commit is contained in:
lyt 2021-02-04 18:13:03 +08:00
parent 9586a55808
commit 097f87317f
14 changed files with 309 additions and 50 deletions

View 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>

View File

@ -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>

View 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>

View File

@ -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>

View File

@ -108,6 +108,8 @@ export default {
// //
watch(store.state, (val) => { watch(store.state, (val) => {
if (val.routes.length === state.menuList.length) return false; if (val.routes.length === state.menuList.length) return false;
let { layout, isClassicSplitMenu } = val.themeConfig;
if (layout === "classic" && isClassicSplitMenu) return false;
setFilterRoutes(); setFilterRoutes();
}); });
// //
@ -119,8 +121,10 @@ export default {
}); });
proxy.mittBus.on("setSendClassicChildren", (res) => { proxy.mittBus.on("setSendClassicChildren", (res) => {
let { layout, isClassicSplitMenu } = store.state.themeConfig; let { layout, isClassicSplitMenu } = store.state.themeConfig;
if (layout === "classic" && isClassicSplitMenu) if (layout === "classic" && isClassicSplitMenu) {
state.menuList = [];
state.menuList = res.children; state.menuList = res.children;
}
}); });
proxy.mittBus.on("getBreadcrumbIndexSetFilterRoutes", () => { proxy.mittBus.on("getBreadcrumbIndexSetFilterRoutes", () => {
setFilterRoutes(); setFilterRoutes();

View File

@ -35,6 +35,7 @@ import {
onMounted, onMounted,
nextTick, nextTick,
getCurrentInstance, getCurrentInstance,
watch,
} from "vue"; } from "vue";
import { useRoute, useRouter, onBeforeRouteUpdate } from "vue-router"; import { useRoute, useRouter, onBeforeRouteUpdate } from "vue-router";
import { useStore } from "/@/store/index.ts"; import { useStore } from "/@/store/index.ts";
@ -51,6 +52,7 @@ export default {
columnsAsideList: [], columnsAsideList: [],
liIndex: 0, liIndex: 0,
difference: 0, difference: 0,
routeSplit: [],
}); });
// //
const setColumnsAsideStyle = computed(() => { const setColumnsAsideStyle = computed(() => {
@ -64,7 +66,7 @@ export default {
return "layout-columns-card-active"; return "layout-columns-card-active";
}); });
// //
const setColumnsAsideMove = (v: Object, k: number) => { const setColumnsAsideMove = (k: number) => {
state.liIndex = k; state.liIndex = k;
columnsAsideActiveRef.value.style.top = `${ columnsAsideActiveRef.value.style.top = `${
columnsAsideOffsetTopRefs.value[k].offsetTop + state.difference columnsAsideOffsetTopRefs.value[k].offsetTop + state.difference
@ -72,22 +74,22 @@ export default {
}; };
// //
const onColumnsAsideMenuClick = (v: Object, k: number) => { const onColumnsAsideMenuClick = (v: Object, k: number) => {
setColumnsAsideMove(v, k); setColumnsAsideMove(k);
let { path, redirect } = v; let { path, redirect } = v;
if (redirect) router.push(redirect); if (redirect) router.push(redirect);
else router.push(path); else router.push(path);
}; };
// //
const onColumnsAsideDown = (v: Object, k: number) => { const onColumnsAsideDown = (k: number) => {
nextTick(() => { nextTick(() => {
setColumnsAsideMove(v, k); setColumnsAsideMove(k);
}); });
}; };
// // // //
const setFilterRoutes = () => { const setFilterRoutes = () => {
state.columnsAsideList = filterRoutesFun(store.state.routes); state.columnsAsideList = filterRoutesFun(store.state.routes);
const resData = setSendChildren(route.path); const resData = setSendChildren(route.path);
onColumnsAsideDown(resData.item[0], resData.item[0].k); onColumnsAsideDown(resData.item[0].k);
proxy.mittBus.emit("setSendColumnsChildren", resData); proxy.mittBus.emit("setSendColumnsChildren", resData);
}; };
// //
@ -114,12 +116,31 @@ export default {
return item; 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(() => { onMounted(() => {
setFilterRoutes(); setFilterRoutes();
}); });
// //
onBeforeRouteUpdate((to) => { onBeforeRouteUpdate((to) => {
setColumnsMenuHighlight(to.path);
proxy.mittBus.emit("setSendColumnsChildren", setSendChildren(to.path)); proxy.mittBus.emit("setSendColumnsChildren", setSendChildren(to.path));
}); });
return { return {

View File

@ -15,8 +15,9 @@ import {
onMounted, onMounted,
onUnmounted, onUnmounted,
getCurrentInstance, getCurrentInstance,
watch,
} from "vue"; } from "vue";
import { useRoute, onBeforeRouteUpdate } from "vue-router"; import { useRoute } from "vue-router";
import { useStore } from "/@/store/index.ts"; import { useStore } from "/@/store/index.ts";
import Breadcrumb from "/@/views/layout/navBars/breadcrumb/breadcrumb.vue"; import Breadcrumb from "/@/views/layout/navBars/breadcrumb/breadcrumb.vue";
import User from "/@/views/layout/navBars/breadcrumb/user.vue"; import User from "/@/views/layout/navBars/breadcrumb/user.vue";
@ -95,6 +96,11 @@ export default {
}); });
return currentData; return currentData;
}; };
//
watch(store.state, (val) => {
if (val.routes.length === state.menuList.length) return false;
setFilterRoutes();
});
// //
onMounted(() => { onMounted(() => {
setFilterRoutes(); setFilterRoutes();
@ -106,13 +112,6 @@ export default {
onUnmounted(() => { onUnmounted(() => {
proxy.mittBus.off("getBreadcrumbIndexSetFilterRoutes"); proxy.mittBus.off("getBreadcrumbIndexSetFilterRoutes");
}); });
//
onBeforeRouteUpdate((to) => {
proxy.mittBus.emit(
"setSendClassicChildren",
setSendClassicChildren(to.path)
);
});
return { return {
getThemeConfig, getThemeConfig,
setIsShowLogo, setIsShowLogo,

View File

@ -81,6 +81,7 @@ export default {
}; };
// vuex tagsViewRoutes // vuex tagsViewRoutes
const getTagsViewRoutes = () => { const getTagsViewRoutes = () => {
state.routePath = route.path;
state.tagsViewList = []; state.tagsViewList = [];
removeSession("tagsViewList"); removeSession("tagsViewList");
state.tagsViewRoutesList = store.state.tagsViewRoutes; state.tagsViewRoutesList = store.state.tagsViewRoutes;
@ -185,6 +186,7 @@ export default {
}; };
// tagsView // tagsView
const onTagsClick = (v: object, k: number) => { const onTagsClick = (v: object, k: number) => {
state.routePath = v.path;
state.tagsRefsIndex = k; state.tagsRefsIndex = k;
router.push(v.path); router.push(v.path);
}; };

View File

@ -1,7 +1,8 @@
<template> <template>
<div class="el-menu-horizontal-warp"> <div class="el-menu-horizontal-warp">
<el-scrollbar @wheel.native.prevent="onElMenuHorizontalScroll" ref="elMenuHorizontalScrollRef"> <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"> <template v-for="val in menuList">
<el-submenu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path"> <el-submenu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
<template #title> <template #title>
@ -90,6 +91,37 @@ export default defineComponent({
state.defaultActive = path; 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(() => { onMounted(() => {
initElMenuOffsetLeft(); initElMenuOffsetLeft();
@ -103,6 +135,7 @@ export default defineComponent({
return { return {
menuList, menuList,
onElMenuHorizontalScroll, onElMenuHorizontalScroll,
onHorizontalSelect,
...toRefs(state), ...toRefs(state),
}; };
}, },

View File

@ -39,6 +39,7 @@ export default defineComponent({
nextTick(() => { nextTick(() => {
state.iframeLoading = true; state.iframeLoading = true;
const iframe = document.getElementById("iframe"); const iframe = document.getElementById("iframe");
if (!iframe) return false;
iframe.onload = () => { iframe.onload = () => {
state.iframeLoading = false; state.iframeLoading = false;
}; };
@ -59,7 +60,9 @@ export default defineComponent({
}); });
// //
onUnmounted(() => { onUnmounted(() => {
proxy.mittBus.off("onTagsViewRefreshRouterView"); proxy.mittBus.off("onTagsViewRefreshRouterView", () => {
console.log(1111);
});
}); });
return { return {
...toRefs(state), ...toRefs(state),

View File

@ -57,9 +57,9 @@ export default defineComponent({
onBeforeMount(() => { onBeforeMount(() => {
proxy.mittBus.on("onTagsViewRefreshRouterView", (path: string) => { proxy.mittBus.on("onTagsViewRefreshRouterView", (path: string) => {
if (route.path !== path) return false; if (route.path !== path) return false;
state.refreshRouterViewKey = Math.random(); state.refreshRouterViewKey = route.path;
nextTick(() => { nextTick(() => {
state.refreshRouterViewKey = path; state.refreshRouterViewKey = null;
}); });
}); });
}); });

View File

@ -1,14 +1,116 @@
<template> <template>
<div> <div>
limitsFrontEndBtn <LimitsFrontEndPage />
<el-input v-model="val"></el-input> <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> </div>
</template> </template>
<script lang="ts"> <script lang="ts">
import { toRefs, reactive } from "vue"; 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 { export default {
name: "limitsFrontEndBtn", name: "limitsFrontEndBtn",
components: { LimitsFrontEndPage, Auth, Auths, AuthAll },
setup() { setup() {
const state = reactive({ const state = reactive({
val: "", val: "",
@ -19,3 +121,19 @@ 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>

View File

@ -1,6 +1,8 @@
<template> <template>
<div> <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-card shadow="hover" header="切换用户演示,前端控制不同用户显示不同页面权限" class="mt15">
<el-radio-group v-model="userAuth" size="small" @change="onRadioChange"> <el-radio-group v-model="userAuth" size="small" @change="onRadioChange">
<el-radio-button label="admin"></el-radio-button> <el-radio-button label="admin"></el-radio-button>
@ -47,16 +49,17 @@ export default {
// //
const onRadioChange = () => { const onRadioChange = () => {
resetRoute(); resetRoute();
let defaultAuthList: Array<string> = []; let defaultAuthPageList: Array<string> = [];
let adminAuthList: Array<string> = [ let adminAuthList: Array<string> = [
"admin", "admin",
"btn.add", "btn.add",
"btn.del", "btn.del",
"btn.edit", "btn.edit",
"btn.link",
]; ];
let testAuthList: Array<string> = ["test", "btn.add"]; let testAuthList: Array<string> = ["test", "btn.add", "btn.link"];
if (state.userAuth === "admin") defaultAuthList = adminAuthList; if (state.userAuth === "admin") defaultAuthPageList = adminAuthList;
else defaultAuthList = testAuthList; else defaultAuthPageList = testAuthList;
const userInfos = { const userInfos = {
userName: state.userAuth, userName: state.userAuth,
photo: photo:
@ -64,10 +67,11 @@ export default {
? "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1813762643,1914315241&fm=26&gp=0.jpg" ? "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", : "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=317673774,2961727727&fm=26&gp=0.jpg",
time: new Date().getTime(), time: new Date().getTime(),
authList: defaultAuthList, authPageList: defaultAuthPageList,
authBtnList: defaultAuthBtnList,
}; };
setSession("userInfo", userInfos); setSession("userInfo", userInfos);
store.dispatch("setAuths", defaultAuthList); // (vuex) // store.dispatch("setAuths", defaultAuthPageList); // (vuex)
store.dispatch("setUserInfos", userInfos); // (vuex) store.dispatch("setUserInfos", userInfos); // (vuex)
initAllFun(); // initAllFun(); //
}; };

View File

@ -74,8 +74,9 @@ export default defineComponent({
"btn.add", "btn.add",
"btn.del", "btn.del",
"btn.edit", "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; if (state.ruleForm.userName === "admin") defaultAuthList = adminAuthList;
else defaultAuthList = testAuthList; else defaultAuthList = testAuthList;
const userInfos = { const userInfos = {