🍊 feat(Web): 新增 badgeTabs 组件(带徽标的选项卡)

- 创建 badgeTabs 组件,用于展示带有徽标的标签页
- 组件支持自定义数据、最大徽标数、徽标偏移量等属性
- 实现了响应式数据更新和事件发射功能
- 优化了隐藏零徽标和权限控制的逻辑
This commit is contained in:
喵你个汪呀 2025-08-22 12:27:23 +08:00
parent 90da6d08b5
commit 4edc2d81dc

View File

@ -0,0 +1,113 @@
<script setup lang="ts">
import { PropType, reactive, watch } from 'vue';
import { number } from 'echarts';
import { auth } from '/@/utils/authFunction';
const emit = defineEmits(['update:modelValue', 'change']);
type BadgeTabsItem = {
label: string; //
value: string; //
count?: number; //
visible?: boolean; //
disabled?: boolean; //
};
/**
* 组件属性定义
*/
const props = defineProps({
/**
* 绑定值
* @type {string|number|boolean}
* @required
* @example
* <BadgeTabs v-model="state.active" :data="[
* { label: '履约中', value: 10, count: state.total?.ly ?? 0 },
* { label: '解约申请', value: 20, count: state.total?.jysq ?? 0 },
* { label: '解约审核', value: 21, count: state.total?.jysh ?? 0, visible: auth('jtysqyQyd/approve') },
* { label: '已解约', value: 22, count: state.total?.yjy ?? 0 },
* { label: '已超期', value: 11, count: state.total?.ycq ?? 0 },
* { label: '已失效', value: 199, count: state.total?.ysx ?? 0 },
* ]" @@change="handleQuery(true)">
* <el-table ref="tableRef" :data="state.tableData">
* <el-table-column label="序号" width="50"></el-table-column>
* <el-table-column label="合同编号"></el-table-column>
* </el-table>
* </BadgeTabs>
*/
modelValue: {
type: [String, Number, Boolean],
required: true,
},
/**
* 字典编码用于从字典中获取数据
* @type {string}
* @required
* @default []
* @example []
*/
data: {
type: Array as PropType<BadgeTabsItem[]>,
required: true,
default: [],
},
/**
* badge 最大值
* @type {number}
* @default 99
* @example 99
*/
max: {
type: Number,
default: 99,
},
/**
* badge 的偏移量
* @type [int, int]
* @default [5, -2]
* @example [5, -2]
*/
offset: {
type: Array as PropType<[int, int]>,
default: [5, -2],
},
/**
* 隐藏小于等于0的badge
* @type {boolean}
* @default true
* @example true
*/
hideZero: {
type: Boolean,
default: true,
},
});
const state = reactive({
active: props.modelValue,
data: props.data,
});
watch(() => state.active, (newValue) => {
emit('update:modelValue', newValue);
emit('change', newValue, state.data);
}, { immediate: true })
watch(() => props.data, (newValue) => {
state.data = newValue ?? [];
console.log(state.data);
}, { immediate: true })
</script>
<template>
<el-tabs v-model="state.active" class="ml5 mt5" v-bind="$attrs">
<el-tab-pane v-for="(item, index) in state.data" :key="index" :label="item.label" :name="item.value" :disabled="item.disabled" v-show="item.visible === undefined || item.visible">
<template #label v-if="(props.hideZero && item.count || !props.hideZero)">
<el-badge :value="item.count ?? 0" :max="props.max" :offset="props.offset">{{ item.label }}</el-badge>
</template>
</el-tab-pane>
<slot></slot>
</el-tabs>
</template>
<style scoped lang="scss">
</style>