Files
property-manager-side/wuye-manager-uniapp/components/tabs/tabs.vue
2026-05-09 17:10:50 +08:00

112 lines
2.3 KiB
Vue

<template>
<view class="tabs_box">
<view
v-for="(item, index) in tabs"
:key="index"
@tap="handleTabs(item)"
class="tabs_items"
:class="{
active: item.value === currentActiveValue,
line: showBottomLine && item.value === currentActiveValue
}"
>
{{ item.label }}
</view>
</view>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
// 标签项类型
interface TabItem {
label: string
value: string | number
}
// Props 类型定义
interface Props {
tabslist?: any[]
showBottomLine?: boolean
// 配置:传入字段名
options?: {
label: string
value: string
}
activeValue?: string | number
}
// 定义 Props
const props = withDefaults(defineProps<Props>(), {
tabslist: () => [],
showBottomLine: true,
options: () => ({ label: 'name', value: 'value' }),
activeValue: null
})
// ======================
// 格式化 tabs 数据(核心)
// ======================
const tabs = computed<TabItem[]>(() => {
const { tabslist, options } = props
if (!tabslist || tabslist.length === 0) return []
return tabslist.map(item => ({
label: item[options.label],
value: item[options.value]
}))
})
// ======================
// 当前激活值(响应式)
// ======================
const currentActiveValue = ref<string | number>(props.activeValue ?? tabs.value[0]?.value ?? '')
// 事件
const emit = defineEmits<{
update: [value: string | number]
}>()
// 点击切换
const handleTabs = (item: TabItem) => {
currentActiveValue.value = item.value
emit('update', item.value)
}
</script>
<style lang="scss" scoped>
.tabs_box {
height: 60rpx;
line-height: 60rpx;
width: 100%;
display: flex;
align-items: center;
overflow-y: hidden;
overflow-x: auto;
.tabs_items {
flex-shrink: 0;
margin-right: 60rpx;
font-size: 28rpx;
color: #222222;
position: relative;
&.active {
color: #4d5dfa;
&.line {
&::after {
content: '';
display: block;
width: 100%;
height: 8rpx;
background: linear-gradient(180deg, #4d5dfa 0%, #bac0fa 100%);
border-radius: 4rpx;
position: absolute;
left: 0;
bottom: 0;
}
}
}
}
}
</style>