From f26f29d84e0a68831a6af14dab3eec5500496d2e Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期三, 28 五月 2025 16:48:52 +0800
Subject: [PATCH] 初始化项目

---
 uview-ui/components/u-dropdown/u-dropdown.vue |  298 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 298 insertions(+), 0 deletions(-)

diff --git a/uview-ui/components/u-dropdown/u-dropdown.vue b/uview-ui/components/u-dropdown/u-dropdown.vue
new file mode 100644
index 0000000..a665cc8
--- /dev/null
+++ b/uview-ui/components/u-dropdown/u-dropdown.vue
@@ -0,0 +1,298 @@
+<template>
+	<view class="u-dropdown">
+		<view class="u-dropdown__menu" :style="{
+			height: $u.addUnit(height)
+		}" :class="{
+			'u-border-bottom': borderBottom
+		}">
+			<view class="u-dropdown__menu__item" v-for="(item, index) in menuList" :key="index" @tap.stop="menuClick(index)">
+				<view class="u-flex">
+					<text class="u-dropdown__menu__item__text" :style="{
+						color: item.disabled ? '#c0c4cc' : (index === current || highlightIndex == index) ? activeColor : inactiveColor,
+						fontSize: $u.addUnit(titleSize)
+					}">{{item.title}}</text>
+					<view class="u-dropdown__menu__item__arrow" :class="{
+						'u-dropdown__menu__item__arrow--rotate': index === current
+					}">
+						<u-icon :custom-style="{display: 'flex'}" :name="menuIcon" :size="$u.addUnit(menuIconSize)" :color="index === current || highlightIndex == index ? activeColor : '#c0c4cc'"></u-icon>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="u-dropdown__content" :style="[contentStyle, {
+			transition: `opacity ${duration / 1000}s linear`,
+			top: $u.addUnit(height),
+			height: contentHeight + 'px'
+		}]"
+		 @tap="maskClick" @touchmove.stop.prevent>
+			<view @tap.stop.prevent class="u-dropdown__content__popup" :style="[popupStyle]">
+				<slot></slot>
+			</view>
+			<view class="u-dropdown__content__mask"></view>
+		</view>
+	</view>
+</template>
+
+<script>
+	/**
+	 * dropdown 涓嬫媺鑿滃崟
+	 * @description 璇ョ粍浠朵竴鑸敤浜庡悜涓嬪睍寮�鑿滃崟锛屽悓鏃跺彲鍒囨崲澶氫釜閫夐」鍗$殑鍦烘櫙
+	 * @tutorial http://uviewui.com/components/dropdown.html
+	 * @property {String} active-color 鏍囬鍜岄�夐」鍗¢�変腑鐨勯鑹诧紙榛樿#497bff锛�
+	 * @property {String} inactive-color 鏍囬鍜岄�夐」鍗℃湭閫変腑鐨勯鑹诧紙榛樿#606266锛�
+	 * @property {Boolean} close-on-click-mask 鐐瑰嚮閬僵鏄惁鍏抽棴鑿滃崟锛堥粯璁rue锛�
+	 * @property {Boolean} close-on-click-self 鐐瑰嚮褰撳墠婵�娲婚」鏍囬鏄惁鍏抽棴鑿滃崟锛堥粯璁rue锛�
+	 * @property {String | Number} duration 閫夐」鍗″睍寮�鍜屾敹璧风殑杩囨浮鏃堕棿锛屽崟浣峬s锛堥粯璁�300锛�
+	 * @property {String | Number} height 鏍囬鑿滃崟鐨勯珮搴︼紝鍗曚綅浠绘剰锛堥粯璁�80锛�
+	 * @property {String | Number} border-radius 鑿滃崟灞曞紑鍐呭涓嬫柟鐨勫渾瑙掑�硷紝鍗曚綅浠绘剰锛堥粯璁�0锛�
+	 * @property {Boolean} border-bottom 鏍囬鑿滃崟鏄惁鏄剧ず涓嬭竟妗嗭紙榛樿false锛�
+	 * @property {String | Number} title-size 鏍囬鐨勫瓧浣撳ぇ灏忥紝鍗曚綅浠绘剰锛屾暟鍊奸粯璁や负rpx鍗曚綅锛堥粯璁�28锛�
+	 * @event {Function} open 涓嬫媺鑿滃崟琚墦寮�鏃惰Е鍙�
+	 * @event {Function} close 涓嬫媺鑿滃崟琚叧闂椂瑙﹀彂
+	 * @example <u-dropdown></u-dropdown>
+	 */
+	export default {
+		name: 'u-dropdown',
+		props: {
+			// 鑿滃崟鏍囬鍜岄�夐」鐨勬縺娲绘�侀鑹�
+			activeColor: {
+				type: String,
+				default: '#497bff'
+			},
+			// 鑿滃崟鏍囬鍜岄�夐」鐨勬湭婵�娲绘�侀鑹�
+			inactiveColor: {
+				type: String,
+				default: '#606266'
+			},
+			// 鐐瑰嚮閬僵鏄惁鍏抽棴鑿滃崟
+			closeOnClickMask: {
+				type: Boolean,
+				default: true
+			},
+			// 鐐瑰嚮褰撳墠婵�娲婚」鏍囬鏄惁鍏抽棴鑿滃崟
+			closeOnClickSelf: {
+				type: Boolean,
+				default: true
+			},
+			// 杩囨浮鏃堕棿
+			duration: {
+				type: [Number, String],
+				default: 300
+			},
+			// 鏍囬鑿滃崟鐨勯珮搴︼紝鍗曚綅浠绘剰锛屾暟鍊奸粯璁や负rpx鍗曚綅
+			height: {
+				type: [Number, String],
+				default: 80
+			},
+			// 鏄惁鏄剧ず涓嬭竟妗�
+			borderBottom: {
+				type: Boolean,
+				default: false
+			},
+			// 鏍囬鐨勫瓧浣撳ぇ灏�
+			titleSize: {
+				type: [Number, String],
+				default: 28
+			},
+			// 涓嬫媺鍑烘潵鐨勫唴瀹归儴鍒嗙殑鍦嗚鍊�
+			borderRadius: {
+				type: [Number, String],
+				default: 0
+			},
+			// 鑿滃崟鍙充晶鐨刬con鍥炬爣
+			menuIcon: {
+				type: String,
+				default: 'arrow-down'
+			},
+			// 鑿滃崟鍙充晶鍥炬爣鐨勫ぇ灏�
+			menuIconSize: {
+				type: [Number, String],
+				default: 26
+			}
+		},
+		data() {
+			return {
+				showDropdown: true, // 鏄惁鎵撳紑涓嬫潵鑿滃崟,
+				menuList: [], // 鏄剧ず鐨勮彍鍗�
+				active: false, // 涓嬫媺鑿滃崟鐨勭姸鎬�
+				// 褰撳墠鏄鍑犱釜鑿滃崟澶勪簬婵�娲荤姸鎬侊紝灏忕▼搴忎腑姝ゅ涓嶈兘鍐欐垚false鎴栬��""锛屽惁鍒欏悗缁皢current璧嬪�间负0锛�
+				// 鏃犺兘鐨凾X娌℃湁浣跨敤===鑰屾槸浣跨敤==鍒ゆ柇锛屽鑷寸▼搴忚涓哄墠鍚庝簩鑰呮病鏈夊彉鍖栵紝浠庤�屼笉浼氳Е鍙戣鍥炬洿鏂�
+				current: 99999,
+				// 澶栧眰鍐呭鐨勬牱寮忥紝鍒濆鏃跺浜庡簳灞傦紝涓旈�忔槑
+				contentStyle: {
+					zIndex: -1,
+					opacity: 0
+				},
+				// 璁╂煇涓彍鍗曚繚鎸侀珮浜殑鐘舵��
+				highlightIndex: 99999,
+				contentHeight: 0
+			}
+		},
+		computed: {
+			// 涓嬫媺鍑烘潵閮ㄥ垎鐨勬牱寮�
+			popupStyle() {
+				let style = {};
+				// 杩涜Y杞翠綅绉伙紝灞曞紑鐘舵�佹椂锛屾仮澶嶅師浣嶃�傛敹榻愮姸鎬佹椂锛屽線涓婁綅绉�100%锛岃繘琛岄殣钘�
+				style.transform = `translateY(${this.active ? 0 : '-100%'})`
+				style['transition-duration'] = this.duration / 1000 + 's';
+				style.borderRadius = `0 0 ${this.$u.addUnit(this.borderRadius)} ${this.$u.addUnit(this.borderRadius)}`;
+				return style;
+			}
+		},
+		created() {
+			// 寮曠敤鎵�鏈夊瓙缁勪欢(u-dropdown-item)鐨則his锛屼笉鑳藉湪data涓0鏄庡彉閲忥紝鍚﹀垯鍦ㄥ井淇″皬绋嬪簭浼氶�犳垚寰幆寮曠敤鑰屾姤閿�
+			this.children = [];
+		},
+		mounted() {
+			this.getContentHeight();
+		},
+		methods: {
+			init() {
+				// 褰撴煇涓瓙缁勪欢鍐呭鍙樺寲鏃讹紝瑙﹀彂鐖剁粍浠剁殑init锛岀埗缁勪欢鍐嶈姣忎竴涓瓙缁勪欢閲嶆柊鍒濆鍖栦竴閬�
+				// 浠ヤ繚璇佹暟鎹殑姝g‘鎬�
+				this.menuList = [];
+				this.children.map(child => {
+					child.init();
+				})
+			},
+			// 鐐瑰嚮鑿滃崟
+			menuClick(index) {
+				// 鍒ゆ柇鏄惁琚鐢�
+				if (this.menuList[index].disabled) return;
+				// 濡傛灉鐐瑰嚮鏃剁殑绱㈠紩鍜屽綋鍓嶆縺娲婚」绱㈠紩鐩稿悓锛屾剰鍛崇潃鐐瑰嚮浜嗘縺娲婚」锛岄渶瑕佹敹璧蜂笅鎷夎彍鍗�
+				if (index === this.current && this.closeOnClickSelf) {
+					this.close();
+					// 绛夊姩鐢荤粨鏉熷悗锛屽啀绉婚櫎涓嬫媺鑿滃崟涓殑鍐呭锛屽惁鍒欑洿鎺ョЩ闄わ紝涔熷氨娌℃湁涓嬫媺鑿滃崟鏀惰捣鐨勬晥鏋滀簡
+					setTimeout(() => {
+						this.children[index].active = false;
+					}, this.duration)
+					return;
+				}
+				this.open(index);
+			},
+			// 鎵撳紑涓嬫媺鑿滃崟
+			open(index) {
+				// 閲嶇疆楂樹寒绱㈠紩锛屽惁鍒欎細閫犳垚澶氫釜鑿滃崟鍚屾椂楂樹寒
+				// this.highlightIndex = 9999;
+				// 灞曞紑鏃讹紝璁剧疆涓嬫媺鍐呭鐨勬牱寮�
+				this.contentStyle = {
+					zIndex: 11,
+				}
+				// 鏍囪灞曞紑鐘舵�佷互鍙婂綋鍓嶅睍寮�椤圭殑绱㈠紩
+				this.active = true;
+				this.current = index;
+				// 鍘嗛亶鎵�鏈夌殑瀛愬厓绱狅紝灏嗙储寮曞尮閰嶇殑椤规爣璁颁负婵�娲荤姸鎬侊紝鍥犱负瀛愬厓绱犳槸閫氳繃v-if鎺у埗鍒囨崲鐨�
+				// 涔嬫墍浠ヤ笉鏄洜display: none锛屾槸鍥犱负nvue娌℃湁display杩欎釜灞炴��
+				this.children.map((val, idx) => {
+					val.active = index == idx ? true : false;
+				})
+				this.$emit('open', this.current);
+			},
+			// 璁剧疆涓嬫媺鑿滃崟澶勪簬鏀惰捣鐘舵��
+			close() {
+				this.$emit('close', this.current);
+				// 璁剧疆涓烘敹璧风姸鎬侊紝鍚屾椂current褰掍綅锛岃缃负绌哄瓧绗︿覆
+				this.active = false;
+				this.current = 99999;
+				// 涓嬫媺鍐呭鐨勬牱寮忚繘琛岃皟鏁达紝涓嶉�忔槑搴﹁缃负0
+				this.contentStyle = {
+					zIndex: -1,
+					opacity: 0
+				}
+			},
+			// 鐐瑰嚮閬僵
+			maskClick() {
+				// 濡傛灉涓嶅厑璁哥偣鍑婚伄缃╋紝鐩存帴杩斿洖
+				if (!this.closeOnClickMask) return;
+				this.close();
+			},
+			// 澶栭儴鎵嬪姩璁剧疆鏌愪釜鑿滃崟楂樹寒
+			highlight(index = undefined) {
+				this.highlightIndex = index !== undefined ? index : 99999;
+			},
+			// 鑾峰彇涓嬫媺鑿滃崟鍐呭鐨勯珮搴�
+			getContentHeight() {
+				// 杩欓噷鐨勫師鐞嗕负锛屽洜涓篸ropdown缁勪欢鏄浉瀵瑰畾浣嶇殑锛屽畠鐨勪笅鎷夊嚭鏉ョ殑鍐呭锛屽繀椤荤粰瀹氫竴涓珮搴�
+				// 鎵嶈兘璁╅伄缃╁崰婊¤彍鍗曚竴涓嬶紝鐩村埌灞忓箷搴曢儴鐨勯珮搴�
+				// this.$u.sys()涓簎View灏佽鐨勮幏鍙栬澶囦俊鎭殑鏂规硶
+				let windowHeight = this.$u.sys().windowHeight;
+				this.$uGetRect('.u-dropdown__menu').then(res => {
+					// 杩欓噷鑾峰彇鐨勬槸dropdown鐨勫昂瀵革紝鍦℉5涓婏紝uniapp鑾峰彇灏哄鏄湁bug鐨�(浠ュ墠鎻愬嚭淇杩囷紝鍚庢潵鍙堝嚭鐜颁簡姝ug锛岀洰鍓峢x2.8.11鐗堟湰)
+					// H5绔痓ug琛ㄧ幇涓哄厓绱犲昂瀵哥殑top鍊间负瀵艰埅鏍忓簳閮ㄥ埌鍒板厓绱犵殑涓婅竟娌跨殑璺濈锛屼絾鏄厓绱犵殑bottom鍊肩‘鏄鑸爮椤堕儴鍒板厓绱犲簳閮ㄧ殑璺濈
+					// 浜岃�呮槸浜掔浉鐭涚浘鐨勶紝鏈川鍘熷洜鏄疕5绔鑸爮闈炲師鐢燂紝uni鐨勫紑鍙戣�呭ぇ鎰忛�犳垚
+					// 杩欓噷鍙栬彍鍗曟爮鐨刡otton鍊煎悎鐞嗙殑锛屼笉鑳界敤res.top锛屽惁鍒欓〉闈細閫犳垚婊氬姩
+					this.contentHeight = windowHeight - res.bottom;
+				})
+			}
+		}
+	}
+</script>
+
+<style scoped lang="scss">
+	@import "../../libs/css/style.components.scss";
+
+	.u-dropdown {
+		flex: 1;
+		width: 100%;
+		position: relative;
+
+		&__menu {
+			@include vue-flex;
+			position: relative;
+			z-index: 11;
+			height: 80rpx;
+
+			&__item {
+				flex: 1;
+				@include vue-flex;
+				justify-content: center;
+				align-items: center;
+
+				&__text {
+					font-size: 28rpx;
+					color: $u-content-color;
+				}
+
+				&__arrow {
+					margin-left: 6rpx;
+					transition: transform .3s;
+					align-items: center;
+					@include vue-flex;
+
+					&--rotate {
+						transform: rotate(180deg);
+					}
+				}
+			}
+		}
+
+		&__content {
+			position: absolute;
+			z-index: 8;
+			width: 100%;
+			left: 0px;
+			bottom: 0;
+			overflow: hidden;
+			
+
+			&__mask {
+				position: absolute;
+				z-index: 9;
+				background: rgba(0, 0, 0, .3);
+				width: 100%;
+				left: 0;
+				top: 0;
+				bottom: 0;
+			}
+
+			&__popup {
+				position: relative;
+				z-index: 10;
+				transition: all 0.3s;
+				transform: translate3D(0, -100%, 0);
+				overflow: hidden;
+			}
+		}
+
+	}
+</style>

--
Gitblit v1.9.3