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-field/u-field.vue |  384 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 384 insertions(+), 0 deletions(-)

diff --git a/uview-ui/components/u-field/u-field.vue b/uview-ui/components/u-field/u-field.vue
new file mode 100644
index 0000000..b562798
--- /dev/null
+++ b/uview-ui/components/u-field/u-field.vue
@@ -0,0 +1,384 @@
+<template>
+	<view class="u-field" :class="{'u-border-top': borderTop, 'u-border-bottom': borderBottom }">
+		<view class="u-field-inner" :class="[type == 'textarea' ? 'u-textarea-inner' : '', 'u-label-postion-' + labelPosition]">
+			<view class="u-label" :class="[required ? 'u-required' : '']" :style="{
+				justifyContent: justifyContent, 
+				flex: labelPosition == 'left' ? `0 0 ${labelWidth}rpx` : '1'
+			}">
+				<view class="u-icon-wrap" v-if="icon">
+					<u-icon size="32" :custom-style="iconStyle" :name="icon" :color="iconColor" class="u-icon"></u-icon>
+				</view>
+				<slot name="icon"></slot>
+				<text class="u-label-text" :class="[this.$slots.icon || icon ? 'u-label-left-gap' : '']">{{ label }}</text>
+			</view>
+			<view class="fild-body">
+				<view class="u-flex-1 u-flex" :style="[inputWrapStyle]">
+					<textarea v-if="type == 'textarea'" class="u-flex-1 u-textarea-class" :style="[fieldStyle]" :value="value"
+					 :placeholder="placeholder" :placeholderStyle="placeholderStyle" :disabled="disabled" :maxlength="inputMaxlength"
+					 :focus="focus" :autoHeight="autoHeight" :fixed="fixed" @input="onInput" @blur="onBlur" @focus="onFocus" @confirm="onConfirm"
+					 @tap="fieldClick" />
+					<input
+						v-else
+						:style="[fieldStyle]"
+						:type="type"
+						class="u-flex-1 u-field__input-wrap"
+						:value="value"
+						:password="password || this.type === 'password'"
+						:placeholder="placeholder"
+						:placeholderStyle="placeholderStyle"
+						:disabled="disabled"
+						:maxlength="inputMaxlength"
+						:focus="focus"
+						:confirmType="confirmType"
+						@focus="onFocus"
+						@blur="onBlur"
+						@input="onInput"
+						@confirm="onConfirm"
+						@tap="fieldClick"
+					/>
+				</view>
+				<u-icon :size="clearSize" v-if="clearable && value != '' && focused" name="close-circle-fill" color="#c0c4cc" class="u-clear-icon" @click="onClear"/>
+				<view class="u-button-wrap"><slot name="right" /></view>
+				<u-icon v-if="rightIcon" @click="rightIconClick" :name="rightIcon" color="#c0c4cc" :style="[rightIconStyle]" size="26" class="u-arror-right" />
+			</view>
+		</view>
+		<view v-if="errorMessage !== false && errorMessage != ''" class="u-error-message" :style="{
+			paddingLeft: labelWidth + 'rpx'
+		}">{{ errorMessage }}</view>
+	</view>
+</template>
+
+<script>
+/**
+ * field 杈撳叆妗�
+ * @description 鍊熷姪姝ょ粍浠讹紝鍙互瀹炵幇琛ㄥ崟鐨勮緭鍏ワ紝 鏈�"text"鍜�"textarea"绫诲瀷鐨勶紝姝ゅ锛屽�熷姪uView鐨刾icker鍜宎ctionSheet缁勪欢鍙互蹇�熷疄鐜颁笂鎷夎彍鍗曪紝鏃堕棿锛屽湴鍖洪�夋嫨绛夛紝 涓鸿〃鍗曡В鍐虫柟妗堢殑鍒╁櫒銆�
+ * @tutorial https://www.uviewui.com/components/field.html
+ * @property {String} type 杈撳叆妗嗙殑绫诲瀷锛堥粯璁ext锛�
+ * @property {String} icon label宸﹁竟鐨勫浘鏍囷紝闄恥View鐨勫浘鏍囧悕绉�
+ * @property {Object} icon-style 宸﹁竟鍥炬爣鐨勬牱寮忥紝瀵硅薄褰㈠紡
+ * @property {Boolean} right-icon 杈撳叆妗嗗彸杈圭殑鍥炬爣鍚嶇О锛岄檺uView鐨勫浘鏍囧悕绉帮紙榛樿false锛�
+ * @property {Boolean} required 鏄惁蹇呭~锛屽乏杈规偍鏄剧ず绾㈣壊"*"鍙凤紙榛樿false锛�
+ * @property {String} label 杈撳叆妗嗗乏杈圭殑鏂囧瓧鎻愮ず
+ * @property {Boolean} password 鏄惁瀵嗙爜杈撳叆鏂瑰紡(鐢ㄧ偣鏇挎崲鏂囧瓧)锛宼ype涓簍ext鏃舵湁鏁堬紙榛樿false锛�
+ * @property {Boolean} clearable 鏄惁鏄剧ず鍙充晶娓呯┖鍐呭鐨勫浘鏍囨帶浠�(杈撳叆妗嗘湁鍐呭锛屼笖鑾峰緱鐒︾偣鏃舵墠鏄剧ず)锛岀偣鍑诲彲娓呯┖杈撳叆妗嗗唴瀹癸紙榛樿true锛�
+ * @property {Number String} label-width label鐨勫搴︼紝鍗曚綅rpx锛堥粯璁�130锛�
+ * @property {String} label-align label鐨勬枃瀛楀榻愭柟寮忥紙榛樿left锛�
+ * @property {Object} field-style 鑷畾涔夎緭鍏ユ鐨勬牱寮忥紝瀵硅薄褰㈠紡
+ * @property {Number | String} clear-size 娓呴櫎鍥炬爣鐨勫ぇ灏忥紝鍗曚綅rpx锛堥粯璁�30锛�
+ * @property {String} input-align 杈撳叆妗嗗唴瀹瑰榻愭柟寮忥紙榛樿left锛�
+ * @property {Boolean} border-bottom 鏄惁鏄剧ずfield鐨勪笅杈规锛堥粯璁rue锛�
+ * @property {Boolean} border-top 鏄惁鏄剧ずfield鐨勪笂杈规锛堥粯璁alse锛�
+ * @property {String} icon-color 宸﹁竟閫氳繃icon閰嶇疆鐨勫浘鏍囩殑棰滆壊锛堥粯璁�#606266锛�
+ * @property {Boolean} auto-height 鏄惁鑷姩澧為珮杈撳叆鍖哄煙锛宼ype涓簍extarea鏃舵湁鏁堬紙榛樿true锛�
+ * @property {String Boolean} error-message 鏄剧ず鐨勯敊璇彁绀哄唴瀹癸紝濡傛灉涓虹┖瀛楃涓叉垨鑰協alse锛屽垯涓嶆樉绀洪敊璇俊鎭�
+ * @property {String} placeholder 杈撳叆妗嗙殑鎻愮ず鏂囧瓧
+ * @property {String} placeholder-style placeholder鐨勬牱寮�(鍐呰仈鏍峰紡锛屽瓧绗︿覆)锛屽"color: #ddd"
+ * @property {Boolean} focus 鏄惁鑷姩鑾峰緱鐒︾偣锛堥粯璁alse锛�
+ * @property {Boolean} fixed 濡傛灉type涓簍extarea锛屼笖鍦ㄤ竴涓�"position:fixed"鐨勫尯鍩燂紝闇�瑕佹寚鏄庝负true锛堥粯璁alse锛�
+ * @property {Boolean} disabled 鏄惁涓嶅彲杈撳叆锛堥粯璁alse锛�
+ * @property {Number String} maxlength 鏈�澶ц緭鍏ラ暱搴︼紝璁剧疆涓� -1 鐨勬椂鍊欎笉闄愬埗鏈�澶ч暱搴︼紙榛樿140锛�
+ * @property {String} confirm-type 璁剧疆閿洏鍙充笅瑙掓寜閽殑鏂囧瓧锛屼粎鍦╰ype="text"鏃剁敓鏁堬紙榛樿done锛�
+ * @event {Function} input 杈撳叆妗嗗唴瀹瑰彂鐢熷彉鍖栨椂瑙﹀彂
+ * @event {Function} focus 杈撳叆妗嗚幏寰楃劍鐐规椂瑙﹀彂
+ * @event {Function} blur 杈撳叆妗嗗け鍘荤劍鐐规椂瑙﹀彂
+ * @event {Function} confirm 鐐瑰嚮瀹屾垚鎸夐挳鏃惰Е鍙�
+ * @event {Function} right-icon-click 閫氳繃right-icon鐢熸垚鐨勫浘鏍囪鐐瑰嚮鏃惰Е鍙�
+ * @event {Function} click 杈撳叆妗嗚鐐瑰嚮鎴栬�呴�氳繃right-icon鐢熸垚鐨勫浘鏍囪鐐瑰嚮鏃惰Е鍙戯紝杩欐牱璁捐鏄�冭檻鍒颁紶閫掑彸杈圭殑鍥炬爣锛屼竴鑸兘涓洪渶瑕佸脊鍑�"picker"绛夋搷浣滄椂鐨勫満鏅紝鐐瑰嚮鍊掍笁瑙掑浘鏍囷紝鐞嗗簲鍙戝嚭姝や簨浠讹紝瑙佷笂鏂硅鏄�
+ * @example <u-field v-model="mobile" label="鎵嬫満鍙�" required :error-message="errorMessage"></u-field>
+ */
+export default {
+	name:"u-field",
+	props: {
+		icon: String,
+		rightIcon: String,
+		// arrowDirection: {
+		// 	type: String,
+		// 	default: 'right'
+		// },
+		required: Boolean,
+		label: String,
+		password: Boolean,
+		clearable: {
+			type: Boolean,
+			default: true
+		},
+		// 宸﹁竟鏍囬鐨勫搴﹀崟浣峳px
+		labelWidth: {
+			type: [Number, String],
+			default: 130
+		},
+		// 瀵归綈鏂瑰紡锛宭eft|center|right
+		labelAlign: {
+			type: String,
+			default: 'left'
+		},
+		inputAlign: {
+			type: String,
+			default: 'left'
+		},
+		iconColor: {
+			type: String,
+			default: '#606266'
+		},
+		autoHeight: {
+			type: Boolean,
+			default: true
+		},
+		errorMessage: {
+			type: [String, Boolean],
+			default: ''
+		},
+		placeholder: String,
+		placeholderStyle: String,
+		focus: Boolean,
+		fixed: Boolean,
+		value: [Number, String],
+		type: {
+			type: String,
+			default: 'text'
+		},
+		disabled: {
+			type: Boolean,
+			default: false
+		},
+		maxlength: {
+			type: [Number, String],
+			default: 140
+		},
+		confirmType: {
+			type: String,
+			default: 'done'
+		},
+		// lable鐨勪綅缃紝鍙�変负 left-宸﹁竟锛宼op-涓婅竟
+		labelPosition: {
+			type: String,
+			default: 'left'
+		},
+		// 杈撳叆妗嗙殑鑷畾涔夋牱寮�
+		fieldStyle: {
+			type: Object,
+			default() {
+				return {}
+			}
+		},
+		// 娓呴櫎鎸夐挳鐨勫ぇ灏�
+		clearSize: {
+			type: [Number, String],
+			default: 30
+		},
+		// lable宸﹁竟鐨勫浘鏍囨牱寮忥紝瀵硅薄褰㈠紡
+		iconStyle: {
+			type: Object,
+			default() {
+				return {}
+			}
+		},
+		// 鏄惁鏄剧ず涓婅竟妗�
+		borderTop: {
+			type: Boolean,
+			default: false
+		},
+		// 鏄惁鏄剧ず涓嬭竟妗�
+		borderBottom: {
+			type: Boolean,
+			default: true
+		},
+		// 鏄惁鑷姩鍘婚櫎涓ょ鐨勭┖鏍�
+		trim: {
+			type: Boolean,
+			default: true
+		}
+	},
+	data() {
+		return {
+			focused: false,
+			itemIndex: 0,
+		};
+	},
+	computed: {
+		inputWrapStyle() {
+			let style = {};
+			style.textAlign = this.inputAlign;
+			// 鍒ゆ柇lable鐨勪綅缃紝濡傛灉鏄痩eft鐨勮瘽锛岃input宸﹁竟涓よ竟鏈夐棿闅�
+			if(this.labelPosition == 'left') {
+				style.margin = `0 8rpx`;
+			} else {
+				// 濡傛灉lable鏄痶op鐨勶紝input鐨勫乏杈瑰氨娌″繀瑕佹湁闂撮殭浜�
+				style.marginRight = `8rpx`;
+			}
+			return style;
+		},
+		rightIconStyle() {
+			let style = {};
+			if (this.arrowDirection == 'top') style.transform = 'roate(-90deg)';
+			if (this.arrowDirection == 'bottom') style.transform = 'roate(90deg)';
+			else style.transform = 'roate(0deg)';
+			return style;
+		},
+		labelStyle() {
+			let style = {};
+			if(this.labelAlign == 'left') style.justifyContent = 'flext-start';
+			if(this.labelAlign == 'center') style.justifyContent = 'center';
+			if(this.labelAlign == 'right') style.justifyContent = 'flext-end';
+			return style;
+		},
+		// uni涓嶆敮鎸佸湪computed涓啓style.justifyContent = 'center'鐨勫舰寮忥紝鏁呯敤姝ゆ柟娉�
+		justifyContent() {
+			if(this.labelAlign == 'left') return 'flex-start';
+			if(this.labelAlign == 'center') return 'center';
+			if(this.labelAlign == 'right') return 'flex-end';
+		},
+		// 鍥犱负uniapp鐨刬nput缁勪欢鐨刴axlength缁勪欢蹇呴』瑕佹暟鍊硷紝杩欓噷杞负鏁板�硷紝缁欑敤鎴峰彲浠ヤ紶鍏ュ瓧绗︿覆鏁板��
+		inputMaxlength() {
+			return Number(this.maxlength)
+		},
+		// label鐨勪綅缃�
+		fieldInnerStyle() {
+			let style = {};
+			if(this.labelPosition == 'left') {
+				style.flexDirection = 'row';
+			} else {
+				style.flexDirection = 'column';
+			}
+			
+			return style;
+		}
+	},
+	methods: {
+		onInput(event) {
+			let value = event.detail.value;
+			// 鍒ゆ柇鏄惁鍘婚櫎绌烘牸
+			if(this.trim) value = this.$u.trim(value);
+			this.$emit('input', value);
+		},
+		onFocus(event) {
+			this.focused = true;
+			this.$emit('focus', event);
+		},
+		onBlur(event) {
+			// 鏈�寮�濮嬩娇鐢ㄧ殑鏄洃鍚浘鏍嘆touchstart浜嬩欢锛岃嚜浠巋x2.8.4鍚庯紝姝ゆ柟娉曞湪寰俊灏忕▼搴忓嚭閿�
+			// 杩欓噷鏀逛负鐩戝惉鐐瑰嚮浜嬩欢锛屾墜鐐瑰嚮娓呴櫎鍥炬爣鏃讹紝鍚屾椂涔熷彂鐢熶簡@blur浜嬩欢锛屽鑷村浘鏍囨秷澶辫�屾棤娉曠偣鍑伙紝杩欓噷鍋氫竴涓欢鏃�
+			setTimeout(() => {
+				this.focused = false;
+			}, 100)
+			this.$emit('blur', event);
+		},
+		onConfirm(e) {
+			this.$emit('confirm', e.detail.value);
+		},
+		onClear(event) {
+			this.$emit('input', '');
+		},
+		rightIconClick() {
+			this.$emit('right-icon-click');
+			this.$emit('click');
+		},
+		fieldClick() {
+			this.$emit('click');
+		}
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+@import "../../libs/css/style.components.scss";
+	
+.u-field {
+	font-size: 28rpx;
+	padding: 20rpx 28rpx;
+	text-align: left;
+	position: relative;
+	color: $u-main-color;
+}
+
+.u-field-inner {
+	@include vue-flex;
+	align-items: center;
+}
+
+.u-textarea-inner {
+	align-items: flex-start;
+}
+
+.u-textarea-class {
+	min-height: 96rpx;
+	width: auto;
+	font-size: 28rpx;
+}
+
+.fild-body {
+	@include vue-flex;
+	flex: 1;
+	align-items: center;
+}
+
+.u-arror-right {
+	margin-left: 8rpx;
+}
+
+.u-label-text {
+	/* #ifndef APP-NVUE */
+	display: inline-flex;		
+	/* #endif */
+}
+
+.u-label-left-gap {
+	margin-left: 6rpx;
+}
+
+.u-label-postion-top {
+	flex-direction: column;
+	align-items: flex-start;
+}
+
+.u-label {
+	width: 130rpx;
+	flex: 1 1 130rpx;
+	text-align: left;
+	position: relative;
+	@include vue-flex;
+	align-items: center;
+}
+
+.u-required::before {
+	content: '*';
+	position: absolute;
+	left: -16rpx;
+	font-size: 14px;
+	color: $u-type-error;
+	height: 9px;
+	line-height: 1;
+}
+
+.u-field__input-wrap {
+	position: relative;
+	overflow: hidden;
+	font-size: 28rpx;
+	height: 48rpx;
+	flex: 1;
+	width: auto;
+}
+
+.u-clear-icon {
+	@include vue-flex;
+	align-items: center;
+}
+
+.u-error-message {
+	color: $u-type-error;
+	font-size: 26rpx;
+	text-align: left;
+}
+
+.placeholder-style {
+	color: rgb(150, 151, 153);
+}
+
+.u-input-class {
+	font-size: 28rpx;
+}
+
+.u-button-wrap {
+	margin-left: 8rpx;
+}
+</style>

--
Gitblit v1.9.3