pan-mini/unpackage/dist/dev/mp-weixin/components/smart-tabs/smart-tabs.js

249 lines
7.0 KiB
JavaScript

"use strict";
const common_vendor = require("../../common/vendor.js");
const _sfc_main = {
name: "SmartTabs",
props: {
// 是否支持滚动
scrollEnable: {
type: Boolean,
required: false,
default: false
},
// 选项卡配置
tabs: {
type: Array,
required: true,
default: () => []
},
// 初始选中的索引
initialIndex: {
type: Number,
default: 0
},
// 动画时长
duration: {
type: Number,
default: 300
},
// 是否显示徽章
showBadge: {
type: Boolean,
default: true
},
// 激活状态颜色
activeColor: {
type: String,
default: "#007AFF"
},
// 非激活状态颜色
inactiveColor: {
type: String,
default: "#333"
},
// 最小项宽度(用于平铺模式)
minItemWidth: {
type: Number,
default: 120
// rpx
}
},
data() {
return {
currentIndex: this.initialIndex,
scrollLeft: 0,
tabWidths: [],
containerWidth: 0,
activeTabId: `tab_${this.initialIndex}`,
canScrollLeft: false,
canScrollRight: false
};
},
mounted() {
this.$nextTick(() => {
this.calculateLayout();
});
},
methods: {
// 计算布局
calculateLayout() {
this.getContainerWidth().then(() => {
this.calculateTabPositions().then(() => {
this.checkScrollability();
this.scrollToCurrentTab();
});
});
},
// 获取容器宽度
getContainerWidth() {
return new Promise((resolve) => {
const query = common_vendor.index.createSelectorQuery().in(this);
query.select(".tabs-header").boundingClientRect();
query.exec((res) => {
if (res && res[0]) {
this.containerWidth = res[0].width;
}
resolve();
});
});
},
// 计算选项卡位置
calculateTabPositions() {
return new Promise((resolve) => {
const query = common_vendor.index.createSelectorQuery().in(this);
this.tabs.forEach((_, index) => {
query.select(`#tab_${index}`).boundingClientRect();
});
query.exec((res) => {
this.tabWidths = res.map((item) => item ? item.width : 0);
resolve();
});
});
},
// 检查是否需要滚动
checkScrollability() {
this.checkScrollState();
},
// 检查滚动状态
checkScrollState() {
if (!this.$props.scrollEnable) {
this.canScrollLeft = false;
this.canScrollRight = false;
return;
}
this.canScrollLeft = this.scrollLeft > 0;
const totalWidth = this.tabWidths.reduce((sum, width) => sum + width, 0);
this.canScrollRight = this.scrollLeft < totalWidth - this.containerWidth;
},
// 滚动到当前选项卡
scrollToCurrentTab() {
if (this.tabWidths.length === 0 || !this.$props.scrollEnable)
return;
let totalWidth = 0;
for (let i = 0; i < this.currentIndex; i++) {
totalWidth += this.tabWidths[i];
}
const currentTabWidth = this.tabWidths[this.currentIndex];
const scrollLeft = totalWidth - (this.containerWidth - currentTabWidth) / 2;
this.scrollLeft = scrollLeft;
this.activeTabId = `tab_${this.currentIndex}`;
this.checkScrollState();
},
// 处理滚动事件
handleScroll(e) {
this.scrollLeft = e.detail.scrollLeft;
this.checkScrollState();
},
// 处理选项卡点击
handleTabClick(index) {
if (this.currentIndex !== index) {
this.currentIndex = index;
this.scrollToCurrentTab();
this.$emit("change", index);
}
},
// 处理滑动切换
handleSwiperChange(e) {
const index = e.detail.current;
if (this.currentIndex !== index) {
this.currentIndex = index;
this.scrollToCurrentTab();
this.$emit("change", index);
}
},
// 获取选项卡样式
getTabStyle(index) {
const isActive = this.currentIndex === index;
const style = {
color: isActive ? this.activeColor : this.inactiveColor,
fontWeight: isActive ? "bold" : "normal",
width: this.scrollEnable ? "auto" : `${100 / this.tabs.length}%`
};
if (!this.$props.scrollEnable) {
style.flex = "1";
style.minWidth = "0";
style.textAlign = "center";
}
return style;
},
getScrollViewStyle() {
console.log("aaa", this.$props.scrollEnable);
const isActive = this.$props.scrollEnable;
const style = {
"--scroll-content-display": isActive ? "block" : "flex"
};
console.log("aaa", this.$props.scrollEnable);
return style;
},
// 切换到指定选项卡
switchTo(index) {
if (index >= 0 && index < this.tabs.length && index !== this.currentIndex) {
this.currentIndex = index;
this.scrollToCurrentTab();
this.$emit("change", index);
}
},
// 向左滚动
scrollLeftByStep() {
this.scrollLeft = Math.max(0, this.scrollLeft - 100);
this.checkScrollState();
},
// 向右滚动
scrollRightByStep() {
const totalWidth = this.tabWidths.reduce((sum, width) => sum + width, 0);
const maxScroll = totalWidth - this.containerWidth;
this.scrollLeft = Math.min(maxScroll, this.scrollLeft + 100);
this.checkScrollState();
}
},
watch: {
initialIndex(newVal) {
if (newVal !== this.currentIndex) {
this.currentIndex = newVal;
this.scrollToCurrentTab();
}
},
tabs() {
this.$nextTick(() => {
this.calculateLayout();
});
}
}
};
const __injectCSSVars__ = () => {
common_vendor.useCssVars((_ctx) => ({
"71c614aa": _ctx.activeColor
}));
};
const __setup__ = _sfc_main.setup;
_sfc_main.setup = __setup__ ? (props, ctx) => {
__injectCSSVars__();
return __setup__(props, ctx);
} : __injectCSSVars__;
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
return {
a: common_vendor.f($props.tabs, (tab, index, i0) => {
return common_vendor.e({
a: common_vendor.t(tab.label),
b: $props.showBadge && tab.badge
}, $props.showBadge && tab.badge ? {
c: common_vendor.t(tab.badge > 99 ? "99+" : tab.badge)
} : {}, {
d: index,
e: `tab_${index}`,
f: $data.currentIndex === index ? 1 : "",
g: common_vendor.s($options.getTabStyle(index)),
h: common_vendor.o(($event) => $options.handleTabClick(index), index)
});
}),
b: $props.scrollEnable,
c: $data.scrollLeft,
d: $props.scrollEnable,
e: $data.activeTabId,
f: common_vendor.s($options.getScrollViewStyle()),
g: common_vendor.o((...args) => $options.handleScroll && $options.handleScroll(...args)),
h: common_vendor.s(_ctx.__cssVars())
};
}
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-f67213a1"]]);
wx.createComponent(Component);