新增管理台,管理轮播图功能
This commit is contained in:
@@ -0,0 +1,396 @@
|
||||
"use strict";
|
||||
const common_vendor = require("../../../common/vendor.js");
|
||||
const _sfc_main = {
|
||||
name: "fui-vtabs",
|
||||
emits: ["click", "change", "scrolltolower"],
|
||||
props: {
|
||||
vtabs: {
|
||||
type: Array,
|
||||
default() {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
nameKey: {
|
||||
type: String,
|
||||
default: "name"
|
||||
},
|
||||
badgeKey: {
|
||||
type: String,
|
||||
default: "badge"
|
||||
},
|
||||
iconKey: {
|
||||
type: String,
|
||||
default: "icon"
|
||||
},
|
||||
activeIconKey: {
|
||||
type: String,
|
||||
default: "activeIcon"
|
||||
},
|
||||
width: {
|
||||
type: [Number, String],
|
||||
default: "0"
|
||||
},
|
||||
height: {
|
||||
type: [Number, String],
|
||||
default: "0"
|
||||
},
|
||||
tabWidth: {
|
||||
type: [Number, String],
|
||||
default: 220
|
||||
},
|
||||
tabHeight: {
|
||||
type: [Number, String],
|
||||
default: 110
|
||||
},
|
||||
size: {
|
||||
type: [Number, String],
|
||||
default: 26
|
||||
},
|
||||
activeSize: {
|
||||
type: [Number, String],
|
||||
default: 26
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: "#333333"
|
||||
},
|
||||
activeColor: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
fontWeight: {
|
||||
type: [Number, String],
|
||||
default: "normal"
|
||||
},
|
||||
activeFontWeight: {
|
||||
type: [Number, String],
|
||||
default: "normal"
|
||||
},
|
||||
background: {
|
||||
type: String,
|
||||
default: "#eeeeee"
|
||||
},
|
||||
activeBgColor: {
|
||||
type: String,
|
||||
default: "#ffffff"
|
||||
},
|
||||
isBorder: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
borderColor: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
activeTab: {
|
||||
type: [Number, String],
|
||||
default: 0
|
||||
},
|
||||
animation: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
badgeColor: {
|
||||
type: String,
|
||||
default: "#fff"
|
||||
},
|
||||
badgeBackground: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
isDot: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//是否联动,为false时content只需展示对应索引数据
|
||||
linkage: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
vtabs: this
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
getActiveColor() {
|
||||
let color = this.activeColor;
|
||||
return color;
|
||||
},
|
||||
getBorderColor() {
|
||||
let color = this.borderColor;
|
||||
return color;
|
||||
},
|
||||
getBadgeBackground() {
|
||||
let color = this.badgeBackground;
|
||||
return color;
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
vals: [],
|
||||
scrollInto: "",
|
||||
current: 0,
|
||||
contentScrollTop: 0,
|
||||
// contentScrollInto: '',
|
||||
heightRecords: [],
|
||||
contentHeight: {},
|
||||
vtabsW: "320px",
|
||||
vtabsH: "600px",
|
||||
isTap: false
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
vtabs(vals) {
|
||||
this.initData(vals);
|
||||
},
|
||||
activeTab(newVal, oldVal) {
|
||||
if (this.linkage) {
|
||||
this.setDefaultTab(newVal);
|
||||
} else {
|
||||
this.switchTab(newVal, true);
|
||||
}
|
||||
},
|
||||
current(val) {
|
||||
this.scrollTabBar(val);
|
||||
},
|
||||
height(val) {
|
||||
this.setHeight(val);
|
||||
},
|
||||
width(val) {
|
||||
this.setWidth(val);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.children = [];
|
||||
this.setWidth(this.width);
|
||||
this.setHeight(this.height);
|
||||
this.calcHeightTimer = null;
|
||||
this.scrollTimer = null;
|
||||
this.initData(this.vtabs);
|
||||
},
|
||||
methods: {
|
||||
setWidth(width) {
|
||||
let res = common_vendor.index.getSystemInfoSync();
|
||||
if (width == 0 || width == "0px" || width == "0rpx") {
|
||||
this.vtabsW = res.windowWidth + "px";
|
||||
} else {
|
||||
this.vtabsW = width;
|
||||
}
|
||||
},
|
||||
setHeight(height) {
|
||||
let res = common_vendor.index.getSystemInfoSync();
|
||||
if (height == 0 || height == "0px" || height == "0rpx") {
|
||||
this.vtabsH = res.windowHeight + "px";
|
||||
} else {
|
||||
this.vtabsH = height;
|
||||
}
|
||||
},
|
||||
setDefaultTab(index, idx = 0) {
|
||||
let len = this.vtabs.length;
|
||||
if (this.heightRecords.length === len && len > 0) {
|
||||
this.switchTab(index, true);
|
||||
} else {
|
||||
if (idx >= 100)
|
||||
return;
|
||||
idx++;
|
||||
setTimeout(() => {
|
||||
this.setDefaultTab(index, idx);
|
||||
}, 250);
|
||||
}
|
||||
},
|
||||
initData(vals) {
|
||||
if (vals && vals.length > 0) {
|
||||
if (typeof vals[0] !== "object") {
|
||||
const key = this.nameKey || "name";
|
||||
vals = vals.map((item) => {
|
||||
return {
|
||||
[key]: item
|
||||
};
|
||||
});
|
||||
}
|
||||
this.vals = vals;
|
||||
this.$nextTick(() => {
|
||||
if (this.linkage) {
|
||||
setTimeout(() => {
|
||||
this.setDefaultTab(this.activeTab);
|
||||
}, 50);
|
||||
} else {
|
||||
this.switchTab(this.activeTab, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
scrollTabBar(index) {
|
||||
let len = this.vtabs.length;
|
||||
if (len === 0)
|
||||
return;
|
||||
index = index < 6 ? 0 : index - 5;
|
||||
if (index >= len)
|
||||
index = len - 1;
|
||||
this.scrollInto = `fui_vtabs_bar_${index}`;
|
||||
},
|
||||
switchTab(index, init) {
|
||||
index = Number(index);
|
||||
const item = {
|
||||
...this.vals[index]
|
||||
};
|
||||
if (item.disable)
|
||||
return;
|
||||
if (this.linkage) {
|
||||
this.contentScrollTop = this.heightRecords[this.current - 1] || 0;
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.current = index;
|
||||
this.contentScrollTop = this.heightRecords[index - 1] || 0;
|
||||
}, 50);
|
||||
});
|
||||
} else {
|
||||
this.current = index;
|
||||
}
|
||||
if (!init) {
|
||||
this.isTap = true;
|
||||
this.$emit("click", {
|
||||
index,
|
||||
...item
|
||||
});
|
||||
}
|
||||
},
|
||||
calcHeight() {
|
||||
let len = this.vtabs.length;
|
||||
let _heightRecords = [];
|
||||
let temp = 0;
|
||||
for (let i = 0; i < len; i++) {
|
||||
_heightRecords[i] = temp + (this.contentHeight[i] || 0);
|
||||
temp = _heightRecords[i];
|
||||
}
|
||||
this.heightRecords = _heightRecords;
|
||||
},
|
||||
contentScroll(e) {
|
||||
if (!this.linkage)
|
||||
return;
|
||||
if (this.isTap) {
|
||||
if (this.scrollTimer) {
|
||||
clearTimeout(this.scrollTimer);
|
||||
}
|
||||
this.scrollTimer = setTimeout(() => {
|
||||
this.isTap = false;
|
||||
}, 50);
|
||||
return;
|
||||
}
|
||||
let _heightRecords = this.heightRecords;
|
||||
if (_heightRecords.length === 0)
|
||||
return;
|
||||
let len = this.vtabs.length;
|
||||
let scrollTop = e.detail.scrollTop + (len - 1) * 0.19;
|
||||
let index = 0;
|
||||
if (scrollTop >= _heightRecords[0]) {
|
||||
for (let i = 1; i < len; i++) {
|
||||
if (scrollTop >= _heightRecords[i - 1] && scrollTop < _heightRecords[i]) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (index != this.current) {
|
||||
const item = {
|
||||
...this.vals[index]
|
||||
};
|
||||
this.$emit("change", {
|
||||
index,
|
||||
...item
|
||||
});
|
||||
this.current = index;
|
||||
}
|
||||
},
|
||||
getCalcHeight(height, index) {
|
||||
this.contentHeight[index] = height;
|
||||
if (this.calcHeightTimer) {
|
||||
clearTimeout(this.calcHeightTimer);
|
||||
}
|
||||
this.calcHeightTimer = setTimeout(() => {
|
||||
this.calcHeight();
|
||||
}, 150);
|
||||
},
|
||||
uninstall(tabIndex, target) {
|
||||
this.children.forEach((item, index) => {
|
||||
if (item === target) {
|
||||
this.children.splice(index, 1);
|
||||
}
|
||||
});
|
||||
delete this.contentHeight[tabIndex];
|
||||
this.calcHeight();
|
||||
},
|
||||
//重置列表高度信息
|
||||
reset() {
|
||||
if (this.linkage) {
|
||||
this.children.forEach((item, index) => {
|
||||
item.calcHeight((height) => {
|
||||
this.getCalcHeight(height, Number(item.tabIndex));
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
onScrolltolower(e) {
|
||||
if (!this.linkage) {
|
||||
this.$emit("scrolltolower", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
|
||||
return {
|
||||
a: common_vendor.f($data.vals, (item, index, i0) => {
|
||||
return common_vendor.e({
|
||||
a: item[$props.iconKey]
|
||||
}, item[$props.iconKey] ? {
|
||||
b: (item.iconWidth || 40) + "rpx",
|
||||
c: (item.iconHeight || 40) + "rpx",
|
||||
d: $data.current === index && item[$props.activeIconKey] ? item[$props.activeIconKey] : item[$props.iconKey]
|
||||
} : {}, {
|
||||
e: common_vendor.t(item[$props.nameKey]),
|
||||
f: item[$props.badgeKey]
|
||||
}, item[$props.badgeKey] ? {
|
||||
g: common_vendor.t($props.isDot ? "" : item[$props.badgeKey]),
|
||||
h: !$options.getBadgeBackground ? 1 : "",
|
||||
i: $props.isDot ? 1 : "",
|
||||
j: !$props.isDot ? 1 : "",
|
||||
k: $props.badgeColor,
|
||||
l: $options.getBadgeBackground
|
||||
} : {}, {
|
||||
m: !$options.getActiveColor && $data.current === index ? 1 : "",
|
||||
n: ($data.current === index ? $props.activeSize : $props.size) + "rpx",
|
||||
o: $data.current === index ? $options.getActiveColor : $props.color,
|
||||
p: $data.current === index ? $props.activeFontWeight : $props.fontWeight,
|
||||
q: !item.disable ? 1 : "",
|
||||
r: item.disable ? 1 : "",
|
||||
s: !$options.getBorderColor && $data.current === index && $props.isBorder ? 1 : "",
|
||||
t: "fui_vtabs_bar_" + index,
|
||||
v: index,
|
||||
w: $data.current === index ? $props.activeBgColor : $props.background,
|
||||
x: $data.current === index && $props.isBorder ? $options.getBorderColor : "transparent",
|
||||
y: common_vendor.o(($event) => $options.switchTab(index), index)
|
||||
});
|
||||
}),
|
||||
b: $props.isBorder ? 1 : "",
|
||||
c: $props.tabWidth + "rpx",
|
||||
d: $props.tabHeight + "rpx",
|
||||
e: $props.tabWidth + "rpx",
|
||||
f: $props.tabWidth + "rpx",
|
||||
g: $data.vtabsH,
|
||||
h: $data.scrollInto,
|
||||
i: $data.isTap,
|
||||
j: $props.tabWidth + "rpx",
|
||||
k: $props.background,
|
||||
l: $data.vtabsH,
|
||||
m: $data.contentScrollTop,
|
||||
n: $props.animation,
|
||||
o: common_vendor.o((...args) => $options.contentScroll && $options.contentScroll(...args)),
|
||||
p: common_vendor.o((...args) => $options.onScrolltolower && $options.onScrolltolower(...args)),
|
||||
q: $data.vtabsW,
|
||||
r: $data.vtabsH
|
||||
};
|
||||
}
|
||||
const Component = /* @__PURE__ */ common_vendor._export_sfc(_sfc_main, [["render", _sfc_render], ["__scopeId", "data-v-d30634da"]]);
|
||||
wx.createComponent(Component);
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
<view style="{{'width:' + q + ';' + ('height:' + r) + ';' + virtualHostStyle}}" class="{{['fui-vtabs__wrap', 'data-v-d30634da', virtualHostClass]}}"><view class="data-v-d30634da" style="{{'width:' + j + ';' + ('background:' + k)}}"><scroll-view show-scrollbar="{{false}}" class="fui-vtabs__scroll-bar data-v-d30634da" style="{{'width:' + f + ';' + ('height:' + g)}}" scroll-y scroll-into-view="{{h}}" scroll-with-animation="{{i}}"><view class="fui-vtabs__item__wrap data-v-d30634da" style="{{'width:' + e}}"><view wx:for="{{a}}" wx:for-item="item" wx:key="v" class="{{['fui-vtabs__item', 'data-v-d30634da', b && 'fui-vtabs__left-border', item.q && 'fui-vtabs__item-hover', item.r && 'fui-vtabs__item-disable', item.s && 'fui-vtabs__border-color']}}" id="{{item.t}}" style="{{'background:' + item.w + ';' + ('border-left-color:' + item.x) + ';' + ('width:' + c) + ';' + ('height:' + d)}}" bindtap="{{item.y}}"><image wx:if="{{item.a}}" class="fui-vtabs__icon data-v-d30634da" style="{{'width:' + item.b + ';' + ('height:' + item.c)}}" src="{{item.d}}"></image><view class="{{['fui-vtabs__text', 'data-v-d30634da', item.m && 'fui-vtabs__selected-color']}}" style="{{'font-size:' + item.n + ';' + ('color:' + item.o) + ';' + ('font-weight:' + item.p)}}">{{item.e}}<text wx:if="{{item.f}}" class="{{['data-v-d30634da', item.h && 'fui-vtabs__badge-color', item.i && 'fui-vtabs__badge-dot', item.j && 'fui-vtabs__badge']}}" style="{{'color:' + item.k + ';' + ('background:' + item.l)}}">{{item.g}}</text></view></view></view></scroll-view></view><scroll-view show-scrollbar="{{false}}" scroll-y="{{true}}" style="{{'height:' + l}}" class="fui-vtabs__content-wrap data-v-d30634da" scroll-top="{{m}}" scroll-with-animation="{{n}}" bindscroll="{{o}}" bindscrolltolower="{{p}}"><view class="fui-vtabs__content data-v-d30634da"><slot></slot></view></scroll-view></view>
|
||||
@@ -0,0 +1,116 @@
|
||||
|
||||
.fui-vtabs__wrap.data-v-d30634da {
|
||||
|
||||
display: flex;
|
||||
|
||||
flex-direction: row;
|
||||
}
|
||||
.fui-vtabs__scroll-bar.data-v-d30634da {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.fui-vtabs__item__wrap.data-v-d30634da {
|
||||
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
.fui-vtabs__item.data-v-d30634da {
|
||||
padding: 0 20rpx;
|
||||
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
|
||||
flex-direction: row;
|
||||
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
}
|
||||
.fui-vtabs__icon.data-v-d30634da {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
.fui-vtabs__item-hover.data-v-d30634da {
|
||||
}
|
||||
.fui-vtabs__item-disable.data-v-d30634da {
|
||||
opacity: .5;
|
||||
}
|
||||
.fui-vtabs__left-border.data-v-d30634da {
|
||||
border-left-width: 8rpx;
|
||||
border-left-style: solid;
|
||||
}
|
||||
.fui-vtabs__text.data-v-d30634da {
|
||||
|
||||
display: block;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
position: relative;
|
||||
}
|
||||
.fui-vtabs__badge.data-v-d30634da {
|
||||
height: 36rpx;
|
||||
padding: 0 12rpx;
|
||||
color: #FFFFFF;
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
border-radius: 100px;
|
||||
|
||||
min-width: 36rpx !important;
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: absolute;
|
||||
right: -32rpx;
|
||||
top: -18rpx;
|
||||
transform: scale(0.9);
|
||||
z-index: 10;
|
||||
}
|
||||
.fui-vtabs__badge-dot.data-v-d30634da {
|
||||
height: 8px !important;
|
||||
width: 8px !important;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
display: inline-block;
|
||||
|
||||
|
||||
border-radius: 50%;
|
||||
|
||||
position: absolute;
|
||||
right: -6px;
|
||||
top: -3px;
|
||||
z-index: 10;
|
||||
}
|
||||
.fui-vtabs__content-wrap.data-v-d30634da {
|
||||
flex: 1;
|
||||
}
|
||||
.fui-vtabs__content.data-v-d30634da {
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.fui-vtabs__selected-color.data-v-d30634da {
|
||||
color: var(--fui-color-primary, #465CFF) !important;
|
||||
}
|
||||
.fui-vtabs__border-color.data-v-d30634da {
|
||||
border-left-color: var(--fui-color-primary, #465CFF) !important;
|
||||
}
|
||||
.fui-vtabs__badge-color.data-v-d30634da {
|
||||
background: var(--fui-color-danger, #FF2B2B) !important;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user