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