chore:后台页面管理编辑-平台入驻核心权益-新增Tab页,前端运行出来可以正常滑动,Tab页正常显示
This commit is contained in:
@@ -210,7 +210,7 @@ const localDevConfig = ({
|
||||
// })['2724']; // 生物菌肥
|
||||
// })['2811']; // 选择要使用的环境配置
|
||||
// })['local-11']; // 选择要使用的环境配置
|
||||
})['5g-351']; // 本地
|
||||
})['2482']; // 本地
|
||||
// })['local-2']; // 本地
|
||||
// })['local-11']; // 本地
|
||||
// })['1-test']; // test
|
||||
|
||||
@@ -5,15 +5,18 @@
|
||||
<!-- 顶部标签位置:标签导航 + 指示器 + 内容区域 -->
|
||||
<template v-if="mergedValue.tabPosition === 'top'">
|
||||
<!-- 标签导航 -->
|
||||
<view class="tab-nav" :style="[tabNavStyle]">
|
||||
<view v-for="(tab, idx) in mergedValue.tabs" :key="getTabKey(tab, 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 : {}]">
|
||||
{{ getTabTitle(tab.title) }}
|
||||
</text>
|
||||
<scroll-view class="tab-nav" :style="[tabNavStyle]" scroll-x
|
||||
:scroll-into-view="scrollIntoId" :scroll-with-animation="true">
|
||||
<view class="tab-nav-inner" :style="[tabNavInnerStyle]">
|
||||
<view v-for="(tab, idx) in mergedValue.tabs" :key="getTabKey(tab, idx)" class="tab-item"
|
||||
:class="{ active: activeTab === idx }" :id="getNavItemId(idx)"
|
||||
:style="[tabItemStyle, activeTab === idx ? tabItemActiveStyle : {}]" @tap="switchTab(idx)">
|
||||
<text class="tab-text" :style="[tabTextStyle, activeTab === idx ? tabTextActiveStyle : {}]">
|
||||
{{ getTabTitle(tab.title) }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 指示器 -->
|
||||
<view v-if="mergedValue.showIndicator" class="tab-indicator" :style="[
|
||||
@@ -74,30 +77,36 @@
|
||||
]"></view>
|
||||
|
||||
<!-- 标签导航 -->
|
||||
<view class="tab-nav" :style="[tabNavStyle]">
|
||||
<view v-for="(tab, idx) in mergedValue.tabs" :key="getTabKey(tab, idx)" class="tab-item"
|
||||
: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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 左侧标签位置:标签导航 + 指示器 + 内容区域 (水平布局) -->
|
||||
<template v-else-if="mergedValue.tabPosition === 'left'">
|
||||
<view class="tab-layout-horizontal">
|
||||
<!-- 左侧标签导航 -->
|
||||
<view class="tab-nav tab-nav-vertical" :style="[tabNavStyle]">
|
||||
<view v-for="(tab, idx) in mergedValue.tabs" :key="getTabKey(tab, idx)" class="tab-item tab-item-vertical"
|
||||
<scroll-view class="tab-nav" :style="[tabNavStyle]" scroll-x
|
||||
:scroll-into-view="scrollIntoId" :scroll-with-animation="true">
|
||||
<view class="tab-nav-inner" :style="[tabNavInnerStyle]">
|
||||
<view v-for="(tab, idx) in mergedValue.tabs" :key="getTabKey(tab, idx)" class="tab-item"
|
||||
:class="[{ active: activeTab === idx }, { 'hover-animation': mergedValue.animation }]"
|
||||
:id="getNavItemId(idx)"
|
||||
: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>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<!-- 左侧标签位置:标签导航 + 指示器 + 内容区域 (水平布局) -->
|
||||
<template v-else-if="mergedValue.tabPosition === 'left'">
|
||||
<view class="tab-layout-horizontal">
|
||||
<!-- 左侧标签导航 -->
|
||||
<scroll-view class="tab-nav tab-nav-vertical" :style="[tabNavStyle]" scroll-y
|
||||
:scroll-into-view="scrollIntoId" :scroll-with-animation="true">
|
||||
<view v-for="(tab, idx) in mergedValue.tabs" :key="getTabKey(tab, idx)" class="tab-item tab-item-vertical"
|
||||
:class="[{ active: activeTab === idx }, { 'hover-animation': mergedValue.animation }]"
|
||||
:id="getNavItemId(idx)"
|
||||
: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>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 左侧指示器 -->
|
||||
<view v-if="mergedValue.showIndicator" class="tab-indicator tab-indicator-vertical" :style="[
|
||||
@@ -161,15 +170,17 @@
|
||||
]"></view>
|
||||
|
||||
<!-- 右侧标签导航 -->
|
||||
<view class="tab-nav tab-nav-vertical" :style="[tabNavStyle]">
|
||||
<scroll-view class="tab-nav tab-nav-vertical" :style="[tabNavStyle]" scroll-y
|
||||
:scroll-into-view="scrollIntoId" :scroll-with-animation="true">
|
||||
<view v-for="(tab, idx) in mergedValue.tabs" :key="getTabKey(tab, idx)" class="tab-item tab-item-vertical"
|
||||
:class="[{ active: activeTab === idx }, { 'hover-animation': mergedValue.animation }]"
|
||||
:id="getNavItemId(idx)"
|
||||
: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>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
@@ -208,6 +219,7 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
activeTab: this.value?.activeTabIndex ?? 0, // 设置当前激活的标签索引
|
||||
scrollIntoId: '', // scroll-view 滚动定位的导航项 id
|
||||
indicatorVars: { // 指示器CSS变量
|
||||
top: '',
|
||||
left: '',
|
||||
@@ -229,6 +241,8 @@ export default {
|
||||
// 初始化指示器位置
|
||||
this.$nextTick(() => {
|
||||
this.updateIndicatorPosition();
|
||||
// 初始化时将激活标签滚动到可视区域
|
||||
this.syncScrollIntoId();
|
||||
});
|
||||
},
|
||||
|
||||
@@ -417,14 +431,6 @@ 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 {
|
||||
@@ -451,6 +457,24 @@ export default {
|
||||
return style;
|
||||
},
|
||||
|
||||
// 导航栏内层容器样式(与后端版本一致)
|
||||
tabNavInnerStyle() {
|
||||
let style = {};
|
||||
|
||||
// 仅水平布局(顶部和底部)应用对齐方式
|
||||
if (this.mergedValue.tabPosition === 'top' || this.mergedValue.tabPosition === 'bottom') {
|
||||
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';
|
||||
}
|
||||
}
|
||||
|
||||
return style;
|
||||
},
|
||||
|
||||
// 标签项样式(与后端版本一致)
|
||||
tabItemStyle() {
|
||||
let style = {
|
||||
@@ -601,9 +625,10 @@ export default {
|
||||
|
||||
// 监听器
|
||||
watch: {
|
||||
// 监听激活标签变化,更新指示器
|
||||
// 监听激活标签变化,更新指示器并滚动导航
|
||||
activeTab: {
|
||||
handler() {
|
||||
this.syncScrollIntoId();
|
||||
this.$nextTick(() => {
|
||||
this.updateIndicatorPosition();
|
||||
});
|
||||
@@ -724,6 +749,16 @@ export default {
|
||||
getTabKey(tab, idx) {
|
||||
return `tab-${tab?.id ?? idx}`;
|
||||
},
|
||||
// 获取导航项的 DOM id(用于 scroll-view 的 scroll-into-view 定位)
|
||||
getNavItemId(idx) {
|
||||
return `tab-nav-item-${idx}`;
|
||||
},
|
||||
// 将当前激活标签滚动到导航栏可视区域
|
||||
syncScrollIntoId() {
|
||||
this.$nextTick(() => {
|
||||
this.scrollIntoId = this.getNavItemId(this.activeTab);
|
||||
});
|
||||
},
|
||||
// 更新指示器位置(与后端版本一致)
|
||||
updateIndicatorPosition() {
|
||||
this.$nextTick(() => {
|
||||
@@ -1034,8 +1069,6 @@ export default {
|
||||
|
||||
// ===== 标签导航栏样式 =====
|
||||
.tab-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 5px 0;
|
||||
border-bottom: 1px solid #e0e0e0;
|
||||
overflow-x: auto;
|
||||
@@ -1049,6 +1082,16 @@ export default {
|
||||
}
|
||||
}
|
||||
|
||||
// 导航栏内层容器:使用 inline-flex 让内容自然撑开宽度,保证小程序 scroll-view 可横向滚动
|
||||
.tab-nav-inner {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
width: max-content;
|
||||
min-width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// 垂直导航栏
|
||||
.tab-nav-vertical {
|
||||
flex-direction: column;
|
||||
@@ -1068,6 +1111,7 @@ export default {
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
user-select: none;
|
||||
flex-shrink: 0; // 防止标签在 scroll-view 内被压缩,保证可完整展示并横向滑动
|
||||
|
||||
&.active {
|
||||
color: var(--active-color, #339af0);
|
||||
|
||||
Reference in New Issue
Block a user