init
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
import { defineStore } from 'pinia';
|
||||
import { Plugin } from 'vue';
|
||||
import './auth.css';
|
||||
import { alert } from 'stepin';
|
||||
export type AuthKey = string | number;
|
||||
|
||||
export interface AuthState {
|
||||
authorities: AuthKey[];
|
||||
}
|
||||
|
||||
export type AuthActions = {
|
||||
setAuthorities: (authorities: AuthKey[]) => void;
|
||||
hasAuthority: (authority: AuthKey) => boolean;
|
||||
useAuth: <T extends Function>(key: AuthKey, func: T) => T;
|
||||
};
|
||||
|
||||
export const useAuthStore = defineStore<string, AuthState, {}, AuthActions>('auth', {
|
||||
state() {
|
||||
return {
|
||||
authorities: [],
|
||||
};
|
||||
},
|
||||
actions: {
|
||||
setAuthorities(authorities) {
|
||||
this.authorities = authorities;
|
||||
},
|
||||
hasAuthority(authority) {
|
||||
return this.authorities.indexOf(authority) !== -1;
|
||||
},
|
||||
/**
|
||||
* 给函数添加 权限校验
|
||||
* @param key
|
||||
* @param func
|
||||
* @returns
|
||||
*/
|
||||
useAuth<T extends Function>(key: AuthKey, func: T): T {
|
||||
const _this = this;
|
||||
return function t() {
|
||||
if (!_this.hasAuthority(key)) {
|
||||
alert.error(msgFormatter(key));
|
||||
} else {
|
||||
return func.apply(undefined, arguments);
|
||||
}
|
||||
} as unknown as T;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* 给函数添加 权限校验
|
||||
* @param key
|
||||
* @param func
|
||||
* @returns
|
||||
*/
|
||||
export function useAuth<T extends Function>(key: AuthKey, func: T): T {
|
||||
return function t() {
|
||||
const authStore = useAuthStore();
|
||||
if (!authStore.hasAuthority(key)) {
|
||||
alert.error(msgFormatter(key));
|
||||
} else {
|
||||
return func.apply(undefined, arguments);
|
||||
}
|
||||
} as unknown as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件配置
|
||||
*/
|
||||
export interface AuthPluginConfig {
|
||||
disableClass?: string;
|
||||
action?: 'hide' | 'disable';
|
||||
formatter?: (access: string) => string;
|
||||
[key: string | number]: any;
|
||||
}
|
||||
|
||||
function msgFormatter(access: AuthKey) {
|
||||
return `对不起,您没有 \`${access}\` 权限`;
|
||||
}
|
||||
|
||||
interface Operator {
|
||||
reject: (el: HTMLElement, access: string, config: AuthPluginConfig) => void;
|
||||
access: (el: HTMLElement, access: string, config: AuthPluginConfig) => void;
|
||||
}
|
||||
|
||||
const operators = {
|
||||
hide: {
|
||||
reject: (el: HTMLElement, access: string, config: AuthPluginConfig) => {
|
||||
el.setAttribute('_display', el.style.display);
|
||||
el.style.display = 'none';
|
||||
},
|
||||
access: (el: HTMLElement, access: string, config: AuthPluginConfig) => {
|
||||
if (el.hasAttribute('_display')) {
|
||||
el.style.display = el.getAttribute('_display');
|
||||
}
|
||||
el.removeAttribute('_display');
|
||||
},
|
||||
},
|
||||
disable: {
|
||||
reject: (el: HTMLElement, access: string, config: AuthPluginConfig) => {
|
||||
el.classList.add(config.disableClass!);
|
||||
el.setAttribute('disabled', '');
|
||||
el.setAttribute('title', config.formatter!(access));
|
||||
},
|
||||
access: (el: HTMLElement, access: string, config: AuthPluginConfig) => {
|
||||
el.classList.remove(config.disableClass!);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const AuthPlugin: Plugin = {
|
||||
install(app, { disableClass = 'auth-disable', action = 'disable', formatter = msgFormatter }: AuthPluginConfig = {}) {
|
||||
app.directive('auth', (el: HTMLElement, { value, arg: access, modifiers }, vnode) => {
|
||||
const { disable, hide } = modifiers;
|
||||
const _action = hide ? 'hide' : disable ? 'disable' : undefined;
|
||||
const authConfig = { disableClass, formatter, action: _action ?? action } as AuthPluginConfig;
|
||||
const operator: Operator = operators[authConfig.action!];
|
||||
|
||||
const authorStore = useAuthStore();
|
||||
if (!authorStore.hasAuthority(access!)) {
|
||||
operator.reject(el, access!, authConfig);
|
||||
} else {
|
||||
operator.access(el, access!, authConfig);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export default AuthPlugin;
|
||||
@@ -0,0 +1,6 @@
|
||||
#stepin-app .auth-disable {
|
||||
@apply bg-disabled text-disabled relative cursor-not-allowed border-disabled rounded-sm border border-solid;
|
||||
}
|
||||
/* *[disabled] {
|
||||
@apply bg-disabled text-disabled relative cursor-not-allowed border-disabled rounded-sm border border-solid;
|
||||
} */
|
||||
@@ -0,0 +1,10 @@
|
||||
<script lang="ts" setup>
|
||||
defineProps({ name: String });
|
||||
</script>
|
||||
<template>
|
||||
<span role="img" style="line-height: 1">
|
||||
<svg fill="currentColor" style="vertical-align: top" width="1em" height="1em" aria-hidden="true">
|
||||
<use :xlink:href="`#${name}`"></use>
|
||||
</svg>
|
||||
</span>
|
||||
</template>
|
||||
@@ -0,0 +1,32 @@
|
||||
import { Plugin } from 'vue';
|
||||
import IconFont from './IconFont.vue';
|
||||
|
||||
function createScriptUrlElements(scriptUrls: string[]) {
|
||||
scriptUrls.forEach((url) => {
|
||||
if (url.length > 0) {
|
||||
const script = document.createElement('script');
|
||||
script.setAttribute('src', url);
|
||||
script.setAttribute('data-namespace', url);
|
||||
document.body.appendChild(script);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const IconFontPlugin: Plugin = {
|
||||
install(app, options: { url: string | string[] }) {
|
||||
if (
|
||||
typeof document !== 'undefined' &&
|
||||
typeof window !== 'undefined' &&
|
||||
typeof document.createElement === 'function'
|
||||
) {
|
||||
if (Array.isArray(options.url)) {
|
||||
createScriptUrlElements(options.url.reverse());
|
||||
} else {
|
||||
createScriptUrlElements([options.url]);
|
||||
}
|
||||
}
|
||||
app.component('IconFont', IconFont);
|
||||
},
|
||||
};
|
||||
|
||||
export default IconFontPlugin;
|
||||
@@ -0,0 +1,2 @@
|
||||
export { useAuthStore, default as AuthPlugin } from './auth/auth-plugin';
|
||||
export { default as IconfontPlugin } from './iconfont';
|
||||
Reference in New Issue
Block a user