Files
YGChatCS/src/components/AiTabSwitch/index.vue
2026-04-24 16:56:56 +08:00

148 lines
4.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="ai-tab-wrapper">
<view class="tab-container">
<view class="tab-item is-left" :class="{ 'active': modelValue === 0 }" @tap="handleSwitch(0)">
<view class="tab-content">
<text class="tab-text">探索发现</text>
</view>
</view>
<view class="tab-item is-right" :class="{ 'active': modelValue === 1 }" @tap="handleSwitch(1)">
<view class="tab-content">
<text class="tab-text">AI伴游</text>
<view v-if="showDot" class="status-dot"></view>
</view>
</view>
</view>
</view>
</template>
<script setup>
const props = defineProps({
modelValue: { type: Number, default: 0 },
showDot: { type: Boolean, default: true }
});
const emit = defineEmits(['update:modelValue', 'change']);
const handleSwitch = (i) => {
emit('update:modelValue', i);
emit('change', i);
};
</script>
<style scoped>
.ai-tab-wrapper {
width: 100%;
background-color: #61D68B;
}
.tab-container {
position: relative;
width: 100%;
height: 48px;
display: flex;
overflow: hidden;
/* 基础容器不做裁切,交给内部 Item */
}
.tab-item {
position: relative;
flex: 1;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
/* 选中态提升层级,压住对方的交汇线 */
.tab-item.active {
z-index: 10;
}
.tab-content {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
/* 未选中样式:半透明渐变 */
background: rgba(0, 0, 0, 0.05);
transition: background 0.3s;
}
.tab-item.active .tab-content {
/* 选中样式:纯白 */
background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #F0F8F3 75.52%);
}
.tab-text {
font-size: 15px;
color: rgba(255, 255, 255, 0.95);
z-index: 20;
}
.tab-item.active .tab-text {
color: #2E312F;
font-weight: bold;
}
/* ------------------- 核心:异形路径优化 ------------------- */
/* 路径逻辑:
1. H 指令缩短,让出更多空间给交汇处。
2. C 指令(贝塞尔曲线)的终点设在高度 48 的位置,确保底部平齐不留空隙。
3. 通过 margin-right/left 让两个形状在中心高度24px处重叠。
*/
.is-left {
margin-right: -14px;
/* 减小重叠宽度,使形状更精巧 */
}
.is-left .tab-content {
/* 路径:左侧顶满 -> 顶部直线 -> 在中间开始向下弯曲 -> 底部平齐拉回 */
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='3 0 180 48' preserveAspectRatio='none'%3E%3Cpath d='M0,0 H140 C155,0 160,12 165,24 C170,36 175,48 185,48 H0 V0 Z' fill='black'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='3 0 180 48' preserveAspectRatio='none'%3E%3Cpath d='M0,0 H140 C155,0 160,12 165,24 C170,36 175,48 185,48 H0 V0 Z' fill='black'/%3E%3C/svg%3E");
-webkit-mask-size: 100% 100%;
}
.is-right {
margin-left: -14px;
}
.is-right .tab-content {
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 48' preserveAspectRatio='none'%3E%3Cpath d='M180,0 H40 C25,0 20,12 15,24 C10,36 5,48 -5,48 H180 V0 Z' fill='black'/%3E%3C/svg%3E");
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 48' preserveAspectRatio='none'%3E%3Cpath d='M180,0 H40 C25,0 20,12 15,24 C10,36 5,48 -5,48 H180 V0 Z' fill='black'/%3E%3C/svg%3E");
-webkit-mask-size: 100% 100%;
}
/* ------------------- 选中态的渐变边框 ------------------- */
.tab-item.active::after {
content: "";
position: absolute;
inset: 0;
z-index: 15;
pointer-events: none;
/* 360deg 渐变 */
background: linear-gradient(0deg, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%);
}
.is-left.active::after {
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='3 0 180 48' preserveAspectRatio='none'%3E%3Cpath d='M0.5,47.5 V0.5 H140 C155,0.5 160,12.5 165,24.5 C170,36.5 175,47.5 184.5,47.5' fill='none' stroke='black' stroke-width='1.2'/%3E%3C/svg%3E");
}
.is-right.active::after {
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 48' preserveAspectRatio='none'%3E%3Cpath d='M179.5,47.5 V0.5 H40 C25,0.5 20,12.5 15,24.5 C10,36.5 5,47.5 -4.5,47.5' fill='none' stroke='black' stroke-width='1.2'/%3E%3C/svg%3E");
}
.status-dot {
width: 7px;
height: 7px;
background-color: #26D46C;
border-radius: 50%;
margin-left: 5px;
transform: translateY(-8px);
}
</style>