This commit is contained in:
lijianyou
2025-09-30 15:00:32 +08:00
parent 1b262f06b8
commit b4e759cf69
202 changed files with 22035 additions and 0 deletions
+128
View File
@@ -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;
+6
View File
@@ -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;
} */
+10
View File
@@ -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>
+32
View File
@@ -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;
+2
View File
@@ -0,0 +1,2 @@
export { useAuthStore, default as AuthPlugin } from './auth/auth-plugin';
export { default as IconfontPlugin } from './iconfont';