'admin-21.01.05:新增按钮权限控制界面及逻辑、处理登录用户信息等'

This commit is contained in:
lyt-Top 2021-02-05 01:15:37 +08:00
parent 097f87317f
commit 25a3cb777e
12 changed files with 306 additions and 71 deletions

View File

@ -2,6 +2,7 @@ import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { store, key } from './store'
import { authDirective } from '/@/utils/authDirective.ts'
import ElementPlus from 'element-plus'
import 'element-plus/lib/theme-chalk/index.css'
@ -12,3 +13,5 @@ import mitt from "mitt"
const app = createApp(App)
app.use(router).use(store, key).use(ElementPlus, { locale: lang }).mount('#app')
app.config.globalProperties.mittBus = mitt()
authDirective(app)

View File

@ -517,14 +517,14 @@ export function formatTwoStageRoutes(arr: any) {
// 缓存多级嵌套数组处理后的一维数组(tagsView、菜单搜索中使用未过滤隐藏的(isHide))
export function setCacheTagsViewRoutes() {
// 先处理有权限的路由,否则 tagsView、菜单搜索中无权限的路由也将显示
let authsRoutes = setFilterMenuFun(dynamicRoutes, store.state.auths)
let authsRoutes = setFilterMenuFun(dynamicRoutes, store.state.userInfos.authPageList)
// 添加到 vuex setTagsViewRoutes 中
store.dispatch('setTagsViewRoutes', formatTwoStageRoutes(formatFlatteningRoutes(authsRoutes))[0].children)
}
// 获取当前用户的权限去比对路由表,用于左侧菜单/横向菜单的显示
export function setFilterMenu() {
store.dispatch("setRoutes", setFilterMenuFun(dynamicRoutes[0].children, store.state.auths))
store.dispatch("setRoutes", setFilterMenuFun(dynamicRoutes[0].children, store.state.userInfos.authPageList))
}
// 判断路由 auth 中是否包含当前登录用户权限字段
@ -551,7 +551,7 @@ export function setFilterRoute() {
let filterRoute: any = []
formatTwoStageRoutes(formatFlatteningRoutes(dynamicRoutes))[0].children.map((route: any) => {
route.meta.auth.map((metaAuth: any) => {
store.state.auths.map((auth: any) => {
store.state.userInfos.authPageList.map((auth: any) => {
if (metaAuth === auth) filterRoute.push({ ...route })
})
})
@ -585,7 +585,6 @@ export function resetRoute() {
export function initAllFun() {
const token = getSession('token')
if (!token) return false
store.dispatch('setAuths')
store.dispatch('setUserInfos')
setAddRoute() // 添加动态路由
setFilterMenu() // 过滤权限菜单

View File

@ -45,9 +45,8 @@ export interface RootStateTypes {
layout: string
},
routes: Array<object>,
caches: Array<string>,
keepAliveNames: Array<string>,
tagsViewRoutes: Array<object>,
auths: Array<string>,
userInfos: object
}
@ -57,9 +56,8 @@ export const store = createStore<RootStateTypes>({
state: {
themeConfig,
routes: [],
caches: [],
keepAliveNames: [],
tagsViewRoutes: [],
auths: [],
userInfos: {}
},
mutations: {
@ -73,16 +71,12 @@ export const store = createStore<RootStateTypes>({
},
// 设置缓存name字段
getCacheKeepAlive(state: any, data: Array<string>) {
state.caches = data
state.keepAliveNames = data
},
// 设置 TagsView 路由
getTagsViewRoutes(state: any, data: Array<string>) {
state.tagsViewRoutes = data
},
// 设置权限
getAuths(state: any, data: Array<string>) {
state.auths = data
},
// 设置用户信息
getUserInfos(state: any, data: object) {
state.userInfos = data
@ -105,15 +99,6 @@ export const store = createStore<RootStateTypes>({
async setTagsViewRoutes({ commit }, data: Array<string>) {
commit('getTagsViewRoutes', data)
},
// 设置权限
async setAuths({ commit }, data: Array<string>) {
// 模拟权限,实际项目中,请通过直接走接口获取权限标识
if (data && data.length > 0) {
commit('getAuths', data)
} else {
if (getSession('userInfo')) commit('getAuths', getSession('userInfo').authList)
}
},
// 设置用户信息
async setUserInfos({ commit }, data: object) {
if (data) {

View File

@ -0,0 +1,42 @@
import type { App } from 'vue'
import { store } from "/@/store/index.ts";
// 判断两数组是否相同
export function judementSameArr(news: Array<string>, old: Array<string>) {
let count = 0
const leng = old.length
for (let i in old) {
for (let j in news) {
if (old[i] === news[j]) count++
}
}
return count === leng ? true : false
}
export function authDirective(app: App) {
// 单个权限验证v-auth="xxx"
app.directive('auth', {
mounted(el, binding) {
if (!store.state.userInfos.authBtnList.some((v: any) => v === binding.value)) el.parentNode.removeChild(el)
}
})
// 多个权限验证满足一个则显示v-auths="[xxx,xxx]"
app.directive('auths', {
mounted(el, binding) {
let flag = false
store.state.userInfos.authBtnList.map((val: any) => {
binding.value.map((v: any) => {
if (val === v) flag = true
})
})
if (!flag) el.parentNode.removeChild(el)
}
})
// 多个权限验证全部满足则显示v-auth-all="[xxx,xxx]"
app.directive('auth-all', {
mounted(el, binding) {
const flag = judementSameArr(binding.value, store.state.userInfos.authBtnList)
if (!flag) el.parentNode.removeChild(el)
}
})
}

View File

@ -0,0 +1,35 @@
import { store } from "/@/store/index.ts";
// 判断两数组是否相同
export function judementSameArr(news: Array<string>, old: Array<string>) {
let count = 0
const leng = old.length
for (let i in old) {
for (let j in news) {
if (old[i] === news[j]) count++
}
}
return count === leng ? true : false
}
// 单个权限验证
export function auth(value: string) {
return store.state.userInfos.authBtnList.some((v: any) => v === value)
}
// 多个权限验证,满足一个则为 true
export function auths(value: Array<string>) {
let flag = false
store.state.userInfos.authBtnList.map((val: any) => {
value.map((v: any) => {
if (val === v) flag = true
})
})
return flag
}
// 多个权限验证,全部满足则为 true
export function authAll(value: Array<string>) {
return judementSameArr(value, store.state.userInfos.authBtnList)
}

View File

@ -1,5 +1,5 @@
<template>
<div v-if="getUserAuthList">
<div v-if="getUserAuthBtnList">
<slot />
</div>
</template>
@ -18,11 +18,11 @@ export default {
setup(props) {
const store = useStore();
// vuex
const getUserAuthList = computed(() => {
return store.state.auths.some((v) => v === props.value);
const getUserAuthBtnList = computed(() => {
return store.state.userInfos.authBtnList.some((v) => v === props.value);
});
return {
getUserAuthList,
getUserAuthBtnList,
};
},
};

View File

@ -1,6 +1,5 @@
<template>
{{getUserAuthList}}
<div v-if="getUserAuthList">
<div v-if="getUserAuthBtnList">
<slot />
</div>
</template>
@ -18,13 +17,23 @@ export default {
},
setup(props) {
const store = useStore();
console.log(store.state);
//
const judementSameArr = (news, old) => {
let count = 0;
const leng = old.length;
for (let i in old) {
for (let j in news) {
if (old[i] === news[j]) count++;
}
}
return count === leng ? true : false;
};
// vuex
const getUserAuthList = computed(() => {
return false;
const getUserAuthBtnList = computed(() => {
return judementSameArr(props.value, store.state.userInfos.authBtnList);
});
return {
getUserAuthList,
getUserAuthBtnList,
};
},
};

View File

@ -1,5 +1,5 @@
<template>
<div v-if="getUserAuthList">
<div v-if="getUserAuthBtnList">
<slot />
</div>
</template>
@ -18,9 +18,9 @@ export default {
setup(props) {
const store = useStore();
// vuex
const getUserAuthList = computed(() => {
const getUserAuthBtnList = computed(() => {
let flag = false;
store.state.auths.map((val) => {
store.state.userInfos.authBtnList.map((val) => {
props.value.map((v) => {
if (val === v) flag = true;
});
@ -28,7 +28,7 @@ export default {
return flag;
});
return {
getUserAuthList,
getUserAuthBtnList,
};
},
};

View File

@ -2,7 +2,7 @@
<div class="h100">
<router-view v-slot="{ Component }">
<transition :name="setTransitionName" mode="out-in">
<keep-alive :include="getCaches">
<keep-alive :include="getKeepAliveNames">
<component :is="Component" :key="refreshRouterViewKey" class="w100" />
</keep-alive>
</transition>
@ -50,8 +50,8 @@ export default defineComponent({
return store.state.themeConfig;
});
// (name)
const getCaches = computed(() => {
return store.state.caches;
const getKeepAliveNames = computed(() => {
return store.state.keepAliveNames;
});
//
onBeforeMount(() => {
@ -69,7 +69,7 @@ export default defineComponent({
});
return {
getThemeConfig,
getCaches,
getKeepAliveNames,
setTransitionName,
...toRefs(state),
};

View File

@ -1,6 +1,7 @@
<template>
<div>
<LimitsFrontEndPage />
<!-- 演示1组件方式 -->
<el-card shadow="hover" header="演示1组件方式" class="mt15">
<el-row class="mb10" style="color:#808080;">单个权限验证:value="xxx"</el-row>
<div class="flex-warp">
@ -36,7 +37,8 @@
</div>
</Auth>
</div>
<el-row class="mb10 mt10" style="color:#808080;">多个权限验证有满足一个则显示:value="[xxx,xxx]"</el-row>
<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">
@ -70,6 +72,7 @@
</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']">
@ -80,43 +83,174 @@
</div>
</div>
</AuthAll>
<div class="flex-warp-item">
<AuthAll :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>
</AuthAll>
<AuthAll :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>
</AuthAll>
<AuthAll :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>
</AuthAll>
</div>
</el-card>
<!-- 演示2指令方式 -->
<el-card shadow="hover" header="演示2指令方式页面初始化时执行" class="mt15">
<el-row class="mb10" style="color:#808080;">单个权限验证v-auth="xxx"</el-row>
<div class="flex-warp">
<div class="flex-warp-item" v-auth="'btn.add'">
<div class="flex-warp-item-box">
<el-button type="primary" size="small" icon="el-icon-document-add">新增
</el-button>
</div>
</div>
<div class="flex-warp-item" v-auth="'btn.edit'">
<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" v-auth="'btn.del'">
<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" v-auth="'btn.link'">
<div class="flex-warp-item-box">
<el-button type="success" size="small" icon="el-icon-link">跳转
</el-button>
</div>
</div>
</div>
<el-row class="mb10 mt10" style="color:#808080;">多个权限验证满足一个则显示v-auths="[xxx,xxx]"</el-row>
<div class="flex-warp">
<div class="flex-warp-item" v-auths="['btn.addsss','btn.edit','btn.delsss','btn.linksss']">
<div class="flex-warp-item-box">
<el-button type="primary" size="small" icon="el-icon-document-add">新增
</el-button>
</div>
</div>
<div class="flex-warp-item" v-auths="['btn.add','btn.edit','btn.del','btn.link']">
<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" v-auths="['btn.add','btn.edit','btn.del','btn.link']">
<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" v-auths="['btn.add','btn.edit','btn.del','btn.link']">
<div class="flex-warp-item-box">
<el-button type="success" size="small" icon="el-icon-link">跳转
</el-button>
</div>
</div>
</div>
<el-row class="mb10 mt10" style="color:#808080;">多个权限验证全部满足则显示v-auth-all="[xxx,xxx]"</el-row>
<div class="flex-warp">
<div class="flex-warp-item" v-auth-all="['btn.add','btn.edit','btn.del','btn.link']">
<div class="flex-warp-item-box">
<el-button type="primary" size="small" icon="el-icon-document-add">新增
</el-button>
</div>
</div>
<div class="flex-warp-item" v-auth-all="['btn.add','btn.edit','btn.del','btn.link']">
<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" v-auth-all="['btn.add','btn.edit','btn.del','btn.link']">
<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" v-auth-all="['btn.add','btn.edit','btn.del','btn.link']">
<div class="flex-warp-item-box">
<el-button type="success" size="small" icon="el-icon-link">跳转
</el-button>
</div>
</div>
</div>
</el-card>
<!-- 演示3函数方式 -->
<el-card shadow="hover" header="演示3函数方式点击按钮查看有无权限用于判断" class="mt15">
<el-row class="mb10" style="color:#808080;">auth('xxx')auths(['xxx','xxx'])authAll(['xxx','xxx'])</el-row>
<div class="flex-warp">
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="primary" size="small" icon="el-icon-document-add" @click="onAuthClick">新增
</el-button>
</div>
</div>
<div class="flex-warp-item">
<div class="flex-warp-item-box">
<el-button type="info" size="small" icon="el-icon-edit-outline" @click="onAuthsClick">编辑</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" @click="onAuthAllClick">删除
</el-button>
</div>
</div>
</div>
</el-card>
</div>
</template>
<script lang="ts">
import { toRefs, reactive } from "vue";
import { ElMessage } from "element-plus";
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";
import { auth, auths, authAll } from "/@/utils/authFunction.ts";
export default {
name: "limitsFrontEndBtn",
components: { LimitsFrontEndPage, Auth, Auths, AuthAll },
setup() {
const state = reactive({
val: "",
});
//
const onAuthClick = () => {
if (!auth("btn.add")) ElMessage.error("抱歉,您没有权限!");
else ElMessage.success("恭喜,您有权限!");
};
// true
const onAuthsClick = () => {
if (!auths(["btn.add", "btn.edit", "btn.del", "btn.link"]))
ElMessage.error("抱歉,您没有权限!");
else ElMessage.success("恭喜,您有权限!");
};
// true
const onAuthAllClick = () => {
if (!authAll(["btn.add", "btn.edit", "btn.del", "btn.link"]))
ElMessage.error("抱歉,您没有权限!");
else ElMessage.success("恭喜,您有权限!");
};
return {
...toRefs(state),
onAuthClick,
onAuthsClick,
onAuthAllClick,
};
},
};

View File

@ -1,9 +1,11 @@
<template>
<div>
<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">
请在切换方法 `onRadioChange` 最后面添加刷新代码 `window.location.reload()` 请注意按钮权限页面中的演示2指令模式演示3函数模式
切换用户时无法动态演示想要动态演示请按 `F5` 或者添加 `window.location.reload()`" type="warning" :closable="false"></el-alert>
<el-alert :title="`当前用户页面权限:[${getAuthPageList}],当前用户按钮权限:[${getAuthBtnList}]`" 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>
<el-radio-button label="test"></el-radio-button>
@ -32,13 +34,17 @@ export default {
val: "",
userAuth: "",
});
//
const getAuthList = computed(() => {
return store.state.auths;
//
const getAuthPageList = computed(() => {
return store.state.userInfos.authPageList;
});
//
const getAuthBtnList = computed(() => {
return store.state.userInfos.authBtnList;
});
//
const initUserAuth = () => {
state.userAuth = store.state.auths[0];
state.userAuth = store.state.userInfos.authPageList[0];
};
//
const initAllFun = () => {
@ -50,16 +56,27 @@ export default {
const onRadioChange = () => {
resetRoute();
let defaultAuthPageList: Array<string> = [];
let adminAuthList: Array<string> = [
"admin",
let defaultAuthBtnList: Array<string> = [];
// admin meta.auth
let adminAuthPageList: Array<string> = ["admin"];
// admin
let adminAuthBtnList: Array<string> = [
"btn.add",
"btn.del",
"btn.edit",
"btn.link",
];
let testAuthList: Array<string> = ["test", "btn.add", "btn.link"];
if (state.userAuth === "admin") defaultAuthPageList = adminAuthList;
else defaultAuthPageList = testAuthList;
// test meta.auth
let testAuthPageList: Array<string> = ["test"];
// test
let testAuthBtnList: Array<string> = ["btn.add", "btn.link"];
if (state.userAuth === "admin") {
defaultAuthPageList = adminAuthPageList;
defaultAuthBtnList = adminAuthBtnList;
} else {
defaultAuthPageList = testAuthPageList;
defaultAuthBtnList = testAuthBtnList;
}
const userInfos = {
userName: state.userAuth,
photo:
@ -71,7 +88,6 @@ export default {
authBtnList: defaultAuthBtnList,
};
setSession("userInfo", userInfos);
// store.dispatch("setAuths", defaultAuthPageList); // (vuex)
store.dispatch("setUserInfos", userInfos); // (vuex)
initAllFun(); //
};
@ -80,7 +96,8 @@ export default {
initUserAuth();
});
return {
getAuthList,
getAuthPageList,
getAuthBtnList,
onRadioChange,
...toRefs(state),
};

View File

@ -68,17 +68,28 @@ export default defineComponent({
//
const onSignIn = () => {
let currentTimeInfo = currentTime.value;
let defaultAuthList: Array<string> = [];
let adminAuthList: Array<string> = [
"admin",
let defaultAuthPageList: Array<string> = [];
let defaultAuthBtnList: Array<string> = [];
// admin meta.auth
let adminAuthPageList: Array<string> = ["admin"];
// admin
let adminAuthBtnList: Array<string> = [
"btn.add",
"btn.del",
"btn.edit",
"btn.link",
];
let testAuthList: Array<string> = ["test", "btn.add", "btn.link"];
if (state.ruleForm.userName === "admin") defaultAuthList = adminAuthList;
else defaultAuthList = testAuthList;
// test meta.auth
let testAuthPageList: Array<string> = ["test"];
// test
let testAuthBtnList: Array<string> = ["btn.add", "btn.link"];
if (state.ruleForm.userName === "admin") {
defaultAuthPageList = adminAuthPageList;
defaultAuthBtnList = adminAuthBtnList;
} else {
defaultAuthPageList = testAuthPageList;
defaultAuthBtnList = testAuthBtnList;
}
const userInfos = {
userName: state.ruleForm.userName,
photo:
@ -86,11 +97,11 @@ export default defineComponent({
? "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("token", Math.random().toString(36).substr(0));
setSession("userInfo", userInfos);
store.dispatch("setAuths", defaultAuthList); // (vuex)
store.dispatch("setUserInfos", userInfos); // (vuex)
initAllFun(); //
router.push("/");