From 66d2c8d8c97e19fdbd969f97dd3d6a28f27c415f Mon Sep 17 00:00:00 2001
From: quanyawei <401863037@qq.com>
Date: Wed, 01 Nov 2023 16:07:03 +0800
Subject: [PATCH] fix:小程序分享功能和秒级数据

---
 uni_modules/uview-ui/components/u-tabs/u-tabs.vue |  354 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 354 insertions(+), 0 deletions(-)

diff --git a/uni_modules/uview-ui/components/u-tabs/u-tabs.vue b/uni_modules/uview-ui/components/u-tabs/u-tabs.vue
new file mode 100644
index 0000000..9c54cc1
--- /dev/null
+++ b/uni_modules/uview-ui/components/u-tabs/u-tabs.vue
@@ -0,0 +1,354 @@
+<template>
+	<view class="u-tabs">
+		<view class="u-tabs__wrapper">
+			<slot name="left" />
+			<view class="u-tabs__wrapper__scroll-view-wrapper">
+				<scroll-view
+					:scroll-x="scrollable"
+					:scroll-left="scrollLeft"
+					scroll-with-animation
+					class="u-tabs__wrapper__scroll-view"
+					:show-scrollbar="false"
+					ref="u-tabs__wrapper__scroll-view"
+				>
+					<view
+						class="u-tabs__wrapper__nav"
+						ref="u-tabs__wrapper__nav"
+					>
+						<view
+							class="u-tabs__wrapper__nav__item"
+							v-for="(item, index) in list"
+							:key="index"
+							@tap="clickHandler(item, index)"
+							:ref="`u-tabs__wrapper__nav__item-${index}`"
+							:style="[$u.addStyle(itemStyle), {flex: scrollable ? '' : 1}]"
+							:class="[`u-tabs__wrapper__nav__item-${index}`, item.disabled && 'u-tabs__wrapper__nav__item--disabled']"
+						>
+							<text
+								:class="[item.disabled && 'u-tabs__wrapper__nav__item__text--disabled']"
+								class="u-tabs__wrapper__nav__item__text"
+								:style="[textStyle(index)]"
+							>{{ item[keyName] }}</text>
+							<u-badge
+								:show="!!(item.badge && (item.badge.show || item.badge.isDot || item.badge.value))"
+								:isDot="item.badge && item.badge.isDot || propsBadge.isDot"
+								:value="item.badge && item.badge.value || propsBadge.value"
+								:max="item.badge && item.badge.max || propsBadge.max"
+								:type="item.badge && item.badge.type || propsBadge.type"
+								:showZero="item.badge && item.badge.showZero || propsBadge.showZero"
+								:bgColor="item.badge && item.badge.bgColor || propsBadge.bgColor"
+								:color="item.badge && item.badge.color || propsBadge.color"
+								:shape="item.badge && item.badge.shape || propsBadge.shape"
+								:numberType="item.badge && item.badge.numberType || propsBadge.numberType"
+								:inverted="item.badge && item.badge.inverted || propsBadge.inverted"
+								customStyle="margin-left: 4px;"
+							></u-badge>
+						</view>
+						<!-- #ifdef APP-NVUE -->
+						<view
+							class="u-tabs__wrapper__nav__line"
+							ref="u-tabs__wrapper__nav__line"
+							:style="[{
+									width: $u.addUnit(lineWidth),
+									height: $u.addUnit(lineHeight),
+									background: lineColor,
+									backgroundSize: lineBgSize,
+								}]"
+						>
+							<!-- #endif -->
+							<!-- #ifndef APP-NVUE -->
+							<view
+								class="u-tabs__wrapper__nav__line"
+								ref="u-tabs__wrapper__nav__line"
+								:style="[{
+										width: $u.addUnit(lineWidth),
+										transform: `translate(${lineOffsetLeft}px)`,
+										transitionDuration: `${firstTime ? 0 : duration}ms`,
+										height: $u.addUnit(lineHeight),
+										background: lineColor,
+										backgroundSize: lineBgSize,
+									}]"
+							>
+								<!-- #endif -->
+							</view>
+						</view>
+				</scroll-view>
+			</view>
+			<slot name="right" />
+		</view>
+	</view>
+</template>
+
+<script>
+	// #ifdef APP-NVUE
+	const animation = uni.requireNativePlugin('animation')
+	const dom = uni.requireNativePlugin('dom')
+	// #endif
+	import props from './props.js';
+	/**
+	 * Tabs ������
+	 * @description tabs��������������������������������������������������������������������������������������������������������������� ���������������������������������������������������������������tab������������������������������������������
+	 * @tutorial https://www.uviewui.com/components/tabs.html
+	 * @property {String | Number}	duration			������������������������������������������������������ 200 ���
+	 * @property {String | Number}	swierWidth			swiper������������������ '750rpx' ���
+	 * @property {String}	keyName	 ���`list`��������������������������������������� 'name' ���
+	 * @event {Function(index)} change ��������������������� index: ������������������tab������������0������
+	 * @event {Function(index)} click ��������������������� index: ������������������tab������������0������
+	 * @example <u-tabs :list="list" :is-scroll="false" :current="current" @change="change"></u-tabs>
+	 */
+	export default {
+		name: 'u-tabs',
+		mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
+		data() {
+			return {
+				firstTime: true,
+				scrollLeft: 0,
+				scrollViewWidth: 0,
+				lineOffsetLeft: 0,
+				tabsRect: {
+					left: 0
+				},
+				innerCurrent: 0,
+				moving: false,
+			}
+		},
+		watch: {
+			current: {
+				immediate: true,
+				handler (newValue, oldValue) {
+					// ������������������������������������������������
+					if (newValue !== this.innerCurrent) {
+						this.innerCurrent = newValue
+						this.$nextTick(() => {
+							this.resize()
+						})
+					}
+				}
+			},
+			// list������������������������list������������
+			list() {
+				this.$nextTick(() => {
+					this.resize()
+				})
+			}
+		},
+		computed: {
+			textStyle() {
+				return index => {
+					const style = {}
+					// ������������������������������
+					const customeStyle = index === this.innerCurrent ? uni.$u.addStyle(this.activeStyle) : uni.$u
+						.addStyle(
+							this.inactiveStyle)
+					// ���������������������������������������������������������������������������������������nvue���������������style���������������!import���������������������������
+					if (this.list[index].disabled) {
+						style.color = '#c8c9cc'
+					}
+					return uni.$u.deepMerge(customeStyle, style)
+				}
+			},
+			propsBadge() {
+				return uni.$u.props.badge
+			}
+		},
+		async mounted() {
+			this.init()
+		},
+		methods: {
+			setLineLeft() {
+				const tabItem = this.list[this.innerCurrent];
+				if (!tabItem) {
+					return;
+				}
+				// ������������������������������
+				let lineOffsetLeft = this.list
+					.slice(0, this.innerCurrent)
+					.reduce((total, curr) => total + curr.rect.width, 0);
+                // ������������������������px���������
+				const lineWidth = uni.$u.getPx(this.lineWidth);
+				this.lineOffsetLeft = lineOffsetLeft + (tabItem.rect.width - lineWidth) / 2
+				// #ifdef APP-NVUE
+				// ������������������������������������������
+				this.animation(this.lineOffsetLeft, this.firstTime ? 0 : parseInt(this.duration))
+				// #endif
+
+				// ���������������������������������������������������������������������������������������tab item���������
+				// ������������������������������������������nvue���������������������style���������������������������������������������������������������false(������������������������)
+				if (this.firstTime) {
+					setTimeout(() => {
+						this.firstTime = false
+					}, 10);
+				}
+			},
+			// nvue������������������������
+			animation(x, duration = 0) {
+				// #ifdef APP-NVUE
+				const ref = this.$refs['u-tabs__wrapper__nav__line']
+				animation.transition(ref, {
+					styles: {
+						transform: `translateX(${x}px)`
+					},
+					duration
+				})
+				// #endif
+			},
+			// ���������������������
+			clickHandler(item, index) {
+				// ���������������������disabled���������������click������������������������������change���������������������������������������
+				this.$emit('click', {
+					...item,
+					index
+				})
+				// ������disabled���������������
+				if (item.disabled) return
+				this.innerCurrent = index
+				this.resize()
+				this.$emit('change', {
+					...item,
+					index
+				})
+			},
+			init() {
+				uni.$u.sleep().then(() => {
+					this.resize()
+				})
+			},
+			setScrollLeft() {
+				// ������������tab���������������������tab���������width���left(������������������������������������������������)���������
+				const tabRect = this.list[this.innerCurrent]
+				// ������������������item������������������
+				const offsetLeft = this.list
+					.slice(0, this.innerCurrent)
+					.reduce((total, curr) => {
+						return total + curr.rect.width
+					}, 0)
+				// ���������������������
+				const windowWidth = uni.$u.sys().windowWidth
+				// ������������tabs-item������������������������������������������scroll-view���������
+				let scrollLeft = offsetLeft - (this.tabsRect.width - tabRect.rect.width) / 2 - (windowWidth - this.tabsRect
+					.right) / 2 + this.tabsRect.left / 2
+				// ������������������������������scrollLeft���������������������scroll-view������������tabs���������������
+				scrollLeft = Math.min(scrollLeft, this.scrollViewWidth - this.tabsRect.width)
+				this.scrollLeft = Math.max(0, scrollLeft)
+			},
+			// ���������������������������
+			resize() {
+				// ���������������list���������������
+				if(this.list.length === 0) {
+					return
+				}
+				Promise.all([this.getTabsRect(), this.getAllItemRect()]).then(([tabsRect, itemRect = []]) => {
+					this.tabsRect = tabsRect
+					this.scrollViewWidth = 0
+					itemRect.map((item, index) => {
+						// ������scroll-view������������������
+						this.scrollViewWidth += item.width
+						// ���������������������item������������X���������
+						this.list[index].rect = item
+					})
+					// ���������tabs���������������������������������������
+					this.setLineLeft()
+					this.setScrollLeft()
+				})
+			},
+			// ���������������������������
+			getTabsRect() {
+				return new Promise(resolve => {
+					this.queryRect('u-tabs__wrapper__scroll-view').then(size => resolve(size))
+				})
+			},
+			// ���������������������������
+			getAllItemRect() {
+				return new Promise(resolve => {
+					const promiseAllArr = this.list.map((item, index) => this.queryRect(
+						`u-tabs__wrapper__nav__item-${index}`, true))
+					Promise.all(promiseAllArr).then(sizes => resolve(sizes))
+				})
+			},
+			// ���������������������������
+			queryRect(el, item) {
+				// #ifndef APP-NVUE
+				// $uGetRect���uView���������������������������������������������������������https://www.uviewui.com/js/getRect.html
+				// ���������������������this.$uGetRect���������������uni.$u.getRect������������������������������������
+				return new Promise(resolve => {
+					this.$uGetRect(`.${el}`).then(size => {
+						resolve(size)
+					})
+				})
+				// #endif
+
+				// #ifdef APP-NVUE
+				// nvue������������dom������������������������
+				// ������������promise���������������������������������������then������
+				return new Promise(resolve => {
+					dom.getComponentRect(item ? this.$refs[el][0] : this.$refs[el], res => {
+						resolve(res.size)
+					})
+				})
+				// #endif
+			},
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	@import "../../libs/css/components.scss";
+
+	.u-tabs {
+
+		&__wrapper {
+			@include flex;
+			align-items: center;
+
+			&__scroll-view-wrapper {
+				flex: 1;
+				/* #ifndef APP-NVUE */
+				overflow: auto hidden;
+				/* #endif */
+			}
+
+			&__scroll-view {
+				@include flex;
+				flex: 1;
+			}
+
+			&__nav {
+				@include flex;
+				position: relative;
+
+				&__item {
+					padding: 0 11px;
+					@include flex;
+					align-items: center;
+					justify-content: center;
+
+					&--disabled {
+						/* #ifndef APP-NVUE */
+						cursor: not-allowed;
+						/* #endif */
+					}
+
+					&__text {
+						font-size: 15px;
+						color: $u-content-color;
+
+						&--disabled {
+							color: $u-disabled-color !important;
+						}
+					}
+				}
+
+				&__line {
+					height: 3px;
+					background: $u-primary;
+					width: 30px;
+					position: absolute;
+					bottom: 2px;
+					border-radius: 100px;
+					transition-property: transform;
+					transition-duration: 300ms;
+				}
+			}
+		}
+	}
+</style>

--
Gitblit v1.8.0