57 lines
1.4 KiB
Vue
57 lines
1.4 KiB
Vue
<script lang="ts" setup>
|
|
/**
|
|
* VIP 权限显隐全局组件
|
|
* 用法:
|
|
* <VipGate code="medical_record">有权限才渲染</VipGate>
|
|
* <VipGate :code="VIP_FEATURE.AI_PRESCRIPTION" :vip="receptionVip">...</VipGate>
|
|
* 接诊/复诊务必传 :vip="履约诊所vip",不要只靠登录态
|
|
*/
|
|
import { computed } from 'vue';
|
|
|
|
import {
|
|
hasVipPermission,
|
|
levelAtLeast,
|
|
type StoreVipInfo,
|
|
} from '#/utils/vip';
|
|
|
|
const props = withDefaults(
|
|
defineProps<{
|
|
/** 权限码(与 xk_vip_feature.code / 等级 permissions 对齐) */
|
|
code?: string;
|
|
/** 最低等级编码 */
|
|
minLevel?: string;
|
|
/**
|
|
* 指定 VIP 来源(挂号履约诊所);不传则用登录态 userInfo.vip
|
|
*/
|
|
vip?: StoreVipInfo | string[] | null;
|
|
/** 无权限时是否渲染 fallback 插槽(默认不渲染) */
|
|
fallback?: boolean;
|
|
}>(),
|
|
{
|
|
code: '',
|
|
minLevel: '',
|
|
fallback: false,
|
|
},
|
|
);
|
|
|
|
const allowed = computed(() => {
|
|
if (props.code) {
|
|
// 传了 :vip 则按履约诊所判;未传则回落登录态
|
|
if (props.vip !== undefined) {
|
|
return hasVipPermission(props.code, props.vip);
|
|
}
|
|
return hasVipPermission(props.code);
|
|
}
|
|
if (props.minLevel) {
|
|
const vipObj = Array.isArray(props.vip) ? null : (props.vip ?? null);
|
|
return levelAtLeast(props.minLevel, vipObj);
|
|
}
|
|
return true;
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<slot v-if="allowed" />
|
|
<slot v-else-if="fallback" name="fallback" />
|
|
</template>
|