feat: 为标签组件添加悬停动画和对齐选项
This commit is contained in:
@@ -68,9 +68,9 @@
|
||||
<!-- 标签导航 -->
|
||||
<view class="tab-nav" :style="tabNavStyle">
|
||||
<view v-for="(tab, idx) in mergedValue.tabs" :key="tab.id || idx" class="tab-item"
|
||||
:class="{ active: activeTab === idx }"
|
||||
:style="[tabItemStyle, activeTab === idx ? tabItemActiveStyle : {}]" @tap="switchTab(idx)">
|
||||
<text class="tab-text" :style="[tabTextStyle, activeTab === idx ? tabTextActiveStyle : {}]">
|
||||
:class="[{ active: activeTab === idx }, { 'hover-animation': mergedValue.animation }]"
|
||||
:style="[tabItemStyle, activeTab === idx ? tabItemActiveStyle : {}, tabItemHoverStyle]" @tap="switchTab(idx)">
|
||||
<text class="tab-text" :style="[tabTextStyle, activeTab === idx ? tabTextActiveStyle : {}, mergedValue.animation ? tabTextHoverStyle : {}]">
|
||||
{{ getTabTitle(tab.title) }}
|
||||
</text>
|
||||
</view>
|
||||
@@ -83,9 +83,9 @@
|
||||
<!-- 左侧标签导航 -->
|
||||
<view class="tab-nav tab-nav-vertical" :style="tabNavStyle">
|
||||
<view v-for="(tab, idx) in mergedValue.tabs" :key="tab.id || idx" class="tab-item tab-item-vertical"
|
||||
:class="{ active: activeTab === idx }"
|
||||
:style="[tabItemStyle, activeTab === idx ? tabItemActiveStyle : {}]" @tap="switchTab(idx)">
|
||||
<text class="tab-text" :style="[tabTextStyle, activeTab === idx ? tabTextActiveStyle : {}]">
|
||||
:class="[{ active: activeTab === idx }, { 'hover-animation': mergedValue.animation }]"
|
||||
:style="[tabItemStyle, activeTab === idx ? tabItemActiveStyle : {}, tabItemHoverStyle]" @tap="switchTab(idx)">
|
||||
<text class="tab-text" :style="[tabTextStyle, activeTab === idx ? tabTextActiveStyle : {}, mergedValue.animation ? tabTextHoverStyle : {}]">
|
||||
{{ getTabTitle(tab.title) }}
|
||||
</text>
|
||||
</view>
|
||||
@@ -147,9 +147,9 @@
|
||||
<!-- 右侧标签导航 -->
|
||||
<view class="tab-nav tab-nav-vertical" :style="tabNavStyle">
|
||||
<view v-for="(tab, idx) in mergedValue.tabs" :key="tab.id || idx" class="tab-item tab-item-vertical"
|
||||
:class="{ active: activeTab === idx }"
|
||||
:style="[tabItemStyle, activeTab === idx ? tabItemActiveStyle : {}]" @tap="switchTab(idx)">
|
||||
<text class="tab-text" :style="[tabTextStyle, activeTab === idx ? tabTextActiveStyle : {}]">
|
||||
:class="[{ active: activeTab === idx }, { 'hover-animation': mergedValue.animation }]"
|
||||
:style="[tabItemStyle, activeTab === idx ? tabItemActiveStyle : {}, tabItemHoverStyle]" @tap="switchTab(idx)">
|
||||
<text class="tab-text" :style="[tabTextStyle, activeTab === idx ? tabTextActiveStyle : {}, mergedValue.animation ? tabTextHoverStyle : {}]">
|
||||
{{ getTabTitle(tab.title) }}
|
||||
</text>
|
||||
</view>
|
||||
@@ -233,7 +233,8 @@ export default {
|
||||
showIndicator: true,
|
||||
activeTabIndex: 0,
|
||||
tabStyle: 'default',
|
||||
tabPosition: 'top'
|
||||
tabPosition: 'top',
|
||||
animation: true
|
||||
};
|
||||
|
||||
// 导航栏样式
|
||||
@@ -241,15 +242,19 @@ export default {
|
||||
tabHeight: 24,
|
||||
tabBgColor: '#ffffff',
|
||||
tabPadding: '0',
|
||||
tabGap: 10
|
||||
tabGap: 10,
|
||||
navAlign: 'start'
|
||||
};
|
||||
|
||||
// 标签项样式
|
||||
const tabItemConfig = {
|
||||
tabGap: 10,
|
||||
fontSize: 14,
|
||||
fontWeight: 400,
|
||||
activeColor: '#339af0',
|
||||
inactiveColor: '#6c757d'
|
||||
inactiveColor: '#6c757d',
|
||||
hoverColor: '#3b82f6',
|
||||
activeFontWeight: 500
|
||||
};
|
||||
|
||||
// 卡片样式
|
||||
@@ -278,7 +283,8 @@ export default {
|
||||
const indicatorConfig = {
|
||||
indicatorColor: '#339af0',
|
||||
indicatorHeight: 2,
|
||||
indicatorWidth: '100%'
|
||||
indicatorWidth: '100%',
|
||||
indicatorBorderRadius: '1px'
|
||||
};
|
||||
|
||||
// 内容区域样式
|
||||
@@ -310,8 +316,10 @@ export default {
|
||||
nav: {},
|
||||
tabItem: {},
|
||||
tabItemActive: {},
|
||||
tabItemHover: {},
|
||||
tabText: {},
|
||||
tabTextActive: {},
|
||||
tabTextHover: {},
|
||||
indicator: {},
|
||||
content: {},
|
||||
panel: {},
|
||||
@@ -383,8 +391,26 @@ export default {
|
||||
// 对于水平布局(顶部和底部),设置固定高度
|
||||
if (this.mergedValue.tabPosition === 'top' || this.mergedValue.tabPosition === 'bottom') {
|
||||
style.height = this.formatStyleValue(this.mergedValue.tabHeight, 24);
|
||||
// 应用对齐方式
|
||||
if (this.mergedValue.navAlign === 'start') {
|
||||
style.justifyContent = 'flex-start';
|
||||
} else if (this.mergedValue.navAlign === 'center') {
|
||||
style.justifyContent = 'center';
|
||||
} else if (this.mergedValue.navAlign === 'end') {
|
||||
style.justifyContent = 'flex-end';
|
||||
}
|
||||
}
|
||||
// 对于垂直布局(左侧和右侧),不设置固定高度,让它自适应内容
|
||||
else {
|
||||
// 垂直布局应用对齐方式
|
||||
if (this.mergedValue.navAlign === 'start') {
|
||||
style.alignItems = 'flex-start';
|
||||
} else if (this.mergedValue.navAlign === 'center') {
|
||||
style.alignItems = 'center';
|
||||
} else if (this.mergedValue.navAlign === 'end') {
|
||||
style.alignItems = 'flex-end';
|
||||
}
|
||||
}
|
||||
|
||||
// 应用导航栏边框样式
|
||||
if (this.mergedValue.showNavBorder) {
|
||||
@@ -434,6 +460,7 @@ export default {
|
||||
tabTextStyle() {
|
||||
return {
|
||||
fontSize: this.formatStyleValue(this.mergedValue.fontSize, 14),
|
||||
fontWeight: this.mergedValue.fontWeight || 400,
|
||||
color: this.mergedValue.inactiveColor,
|
||||
...this.mergedValue.customStyles.tabText
|
||||
};
|
||||
@@ -443,10 +470,26 @@ export default {
|
||||
tabTextActiveStyle() {
|
||||
return {
|
||||
color: this.mergedValue.activeColor,
|
||||
fontWeight: this.mergedValue.activeFontWeight || 500,
|
||||
...this.mergedValue.customStyles.tabTextActive
|
||||
};
|
||||
},
|
||||
|
||||
// 标签项悬停样式
|
||||
tabItemHoverStyle() {
|
||||
return {
|
||||
...this.mergedValue.customStyles.tabItemHover
|
||||
};
|
||||
},
|
||||
|
||||
// 标签文本悬停样式
|
||||
tabTextHoverStyle() {
|
||||
return {
|
||||
color: this.mergedValue.hoverColor || '#3b82f6',
|
||||
...this.mergedValue.customStyles.tabTextHover
|
||||
};
|
||||
},
|
||||
|
||||
// 指示器样式(与后端版本一致)
|
||||
indicatorStyle() {
|
||||
// 计算高度,考虑不同样式
|
||||
@@ -986,7 +1029,6 @@ export default {
|
||||
padding: 0px 20px 0px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
@@ -997,6 +1039,16 @@ export default {
|
||||
color: var(--active-color, #339af0);
|
||||
}
|
||||
|
||||
// 悬停动画效果
|
||||
&.hover-animation {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
&:hover {
|
||||
color: var(--hover-color, #3b82f6);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
}
|
||||
|
||||
// 减少动画效果(针对偏好减少动画的用户)
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
transition: none;
|
||||
@@ -1015,7 +1067,6 @@ export default {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: inherit;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
// ===== 标签指示器样式 =====
|
||||
@@ -1027,6 +1078,9 @@ export default {
|
||||
bottom: 0;
|
||||
left: 16px;
|
||||
right: 16px;
|
||||
|
||||
// 支持圆角
|
||||
border-radius: var(--indicator-border-radius, 1px);
|
||||
}
|
||||
|
||||
// 垂直指示器(用于左右布局)
|
||||
@@ -1122,7 +1176,6 @@ export default {
|
||||
border-radius: 16px;
|
||||
margin: 0 5px;
|
||||
padding: 0 10px;
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
color: var(--card-text-color, #6c757d);
|
||||
@@ -1130,10 +1183,14 @@ export default {
|
||||
height: auto;
|
||||
padding: 8px 16px;
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
|
||||
transform: translateY(-1px);
|
||||
background-color: #f8f9fa;
|
||||
&.hover-animation {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
|
||||
transform: translateY(-1px);
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
@@ -1142,7 +1199,7 @@ export default {
|
||||
box-shadow: 0 2px 10px rgba(51, 154, 240, 0.4);
|
||||
transform: translateY(-1px);
|
||||
|
||||
&:hover {
|
||||
&.hover-animation:hover {
|
||||
background-color: var(--card-active-hover-bg-color, #228be6);
|
||||
color: var(--card-active-hover-text-color, #ffffff);
|
||||
box-shadow: 0 3px 12px rgba(51, 154, 240, 0.45);
|
||||
@@ -1162,16 +1219,19 @@ export default {
|
||||
margin: 5px 10px;
|
||||
padding: 12px 16px;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
border-bottom: none;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
color: var(--card-text-color, #6c757d);
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
|
||||
transform: translateX(-2px);
|
||||
background-color: #f8f9fa;
|
||||
&.hover-animation {
|
||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.18);
|
||||
transform: translateX(-2px);
|
||||
background-color: #f8f9fa;
|
||||
}
|
||||
}
|
||||
|
||||
&.active {
|
||||
@@ -1180,7 +1240,7 @@ export default {
|
||||
box-shadow: 0 2px 10px rgba(51, 154, 240, 0.4);
|
||||
transform: translateX(-2px);
|
||||
|
||||
&:hover {
|
||||
&.hover-animation:hover {
|
||||
background-color: #228be6;
|
||||
box-shadow: 0 3px 12px rgba(51, 154, 240, 0.45);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user