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-number-box/u-number-box.vue | 363 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 363 insertions(+), 0 deletions(-) diff --git a/uview-ui/components/u-number-box/u-number-box.vue b/uview-ui/components/u-number-box/u-number-box.vue new file mode 100644 index 0000000..54a679e --- /dev/null +++ b/uview-ui/components/u-number-box/u-number-box.vue @@ -0,0 +1,363 @@ +<template> + <view class="u-numberbox"> + <view class="u-icon-minus" @touchstart.stop.prevent="btnTouchStart('minus')" @touchend.stop.prevent="clearTimer" :class="{ 'u-icon-disabled': disabled || inputVal <= min }" + :style="{ + background: bgColor, + height: inputHeight + 'rpx', + color: color + }"> + <u-icon name="minus" :size="size"></u-icon> + </view> + <input :disabled="disabledInput || disabled" :cursor-spacing="getCursorSpacing" :class="{ 'u-input-disabled': disabled }" + v-model="inputVal" class="u-number-input" @blur="onBlur" @focus="onFocus" + type="number" :style="{ + color: color, + fontSize: size + 'rpx', + background: bgColor, + height: inputHeight + 'rpx', + width: inputWidth + 'rpx' + }" /> + <view class="u-icon-plus" @touchstart.stop.prevent="btnTouchStart('plus')" @touchend.stop.prevent="clearTimer" :class="{ 'u-icon-disabled': disabled || inputVal >= max }" + :style="{ + background: bgColor, + height: inputHeight + 'rpx', + color: color + }"> + <u-icon name="plus" :size="size"></u-icon> + </view> + </view> +</template> + +<script> + /** + * numberBox 姝ヨ繘鍣� + * @description 璇ョ粍浠朵竴鑸敤浜庡晢鍩庤喘鐗╅�夋嫨鐗╁搧鏁伴噺鐨勫満鏅�傛敞鎰忥細璇ヨ緭鍏ユ鍙兘杈撳叆澶т簬鎴栫瓑浜�0鐨勬暣鏁帮紝涓嶆敮鎸佸皬鏁拌緭鍏� + * @tutorial https://www.uviewui.com/components/numberBox.html + * @property {Number} value 杈撳叆妗嗗垵濮嬪�硷紙榛樿1锛� + * @property {String} bg-color 杈撳叆妗嗗拰鎸夐挳鐨勮儗鏅鑹诧紙榛樿#F2F3F5锛� + * @property {Number} min 鐢ㄦ埛鍙緭鍏ョ殑鏈�灏忓�硷紙榛樿0锛� + * @property {Number} max 鐢ㄦ埛鍙緭鍏ョ殑鏈�澶у�硷紙榛樿99999锛� + * @property {Number} step 姝ラ暱锛屾瘡娆″姞鎴栧噺鐨勫�硷紙榛樿1锛� + * @property {Boolean} disabled 鏄惁绂佺敤鎿嶄綔锛岀鐢ㄥ悗鏃犳硶鍔犲噺鎴栨墜鍔ㄤ慨鏀硅緭鍏ユ鐨勫�硷紙榛樿false锛� + * @property {Boolean} disabled-input 鏄惁绂佹杈撳叆妗嗘墜鍔ㄨ緭鍏ュ�硷紙榛樿false锛� + * @property {Boolean} positive-integer 鏄惁鍙兘杈撳叆姝f暣鏁帮紙榛樿true锛� + * @property {String | Number} size 杈撳叆妗嗘枃瀛楀拰鎸夐挳瀛椾綋澶у皬锛屽崟浣峳px锛堥粯璁�26锛� + * @property {String} color 杈撳叆妗嗘枃瀛楀拰鍔犲噺鎸夐挳鍥炬爣鐨勯鑹诧紙榛樿#323233锛� + * @property {String | Number} input-width 杈撳叆妗嗗搴︼紝鍗曚綅rpx锛堥粯璁�80锛� + * @property {String | Number} input-height 杈撳叆妗嗗拰鎸夐挳鐨勯珮搴︼紝鍗曚綅rpx锛堥粯璁�50锛� + * @property {String | Number} index 浜嬩欢鍥炶皟鏃剁敤浠ュ尯鍒嗗綋鍓嶅彂鐢熷彉鍖栫殑鏄摢涓緭鍏ユ + * @property {Boolean} long-press 鏄惁寮�鍚暱鎸夎繛缁�掑鎴栭�掑噺(榛樿true) + * @property {String | Number} press-time 寮�鍚暱鎸夎Е鍙戝悗锛屾瘡瑙﹀彂涓�娆¢渶瑕佸涔咃紝鍗曚綅ms(榛樿250) + * @property {String | Number} cursor-spacing 鎸囧畾鍏夋爣浜庨敭鐩樼殑璺濈锛岄伩鍏嶉敭鐩橀伄鎸¤緭鍏ユ锛屽崟浣峳px锛堥粯璁�200锛� + * @event {Function} change 杈撳叆妗嗗唴瀹瑰彂鐢熷彉鍖栨椂瑙﹀彂锛屽璞″舰寮� + * @event {Function} blur 杈撳叆妗嗗け鍘荤劍鐐规椂瑙﹀彂锛屽璞″舰寮� + * @event {Function} minus 鐐瑰嚮鍑忓皯鎸夐挳鏃惰Е鍙�(鎸夐挳鍙偣鍑绘儏鍐典笅)锛屽璞″舰寮� + * @event {Function} plus 鐐瑰嚮澧炲姞鎸夐挳鏃惰Е鍙�(鎸夐挳鍙偣鍑绘儏鍐典笅)锛屽璞″舰寮� + * @example <u-number-box :min="1" :max="100"></u-number-box> + */ + export default { + name: "u-number-box", + props: { + // 棰勬樉绀虹殑鏁板瓧 + value: { + type: Number, + default: 1 + }, + // 鑳屾櫙棰滆壊 + bgColor: { + type: String, + default: '#F2F3F5' + }, + // 鏈�灏忓�� + min: { + type: Number, + default: 0 + }, + // 鏈�澶у�� + max: { + type: Number, + default: 99999 + }, + // 姝ヨ繘鍊硷紝姣忔鍔犳垨鍑忕殑鍊� + step: { + type: Number, + default: 1 + }, + // 鏄惁绂佺敤鍔犲噺鎿嶄綔 + disabled: { + type: Boolean, + default: false + }, + // input鐨勫瓧浣撳ぇ灏忥紝鍗曚綅rpx + size: { + type: [Number, String], + default: 26 + }, + // 鍔犲噺鍥炬爣鐨勯鑹� + color: { + type: String, + default: '#323233' + }, + // input瀹藉害锛屽崟浣峳px + inputWidth: { + type: [Number, String], + default: 80 + }, + // input楂樺害锛屽崟浣峳px + inputHeight: { + type: [Number, String], + default: 50 + }, + // index绱㈠紩锛岀敤浜庡垪琛ㄤ腑浣跨敤锛岃鐢ㄦ埛鐭ラ亾鏄摢涓猲umberbox鍙戠敓浜嗗彉鍖栵紝涓�鑸娇鐢╢or寰幆鍑烘潵鐨刬ndex鍊煎嵆鍙� + index: { + type: [Number, String], + default: '' + }, + // 鏄惁绂佺敤杈撳叆妗嗭紝涓巇isabled浣滅敤浜庤緭鍏ユ鏃讹紝涓篛R鐨勫叧绯伙紝鍗虫兂瑕佺鐢ㄨ緭鍏ユ锛屽張鍙互鍔犲噺鐨勮瘽 + // 璁剧疆disabled涓篺alse锛宒isabledInput涓簍rue鍗冲彲 + disabledInput: { + type: Boolean, + default: false + }, + // 杈撳叆妗嗕簬閿洏涔嬮棿鐨勮窛绂� + cursorSpacing: { + type: [Number, String], + default: 100 + }, + // 鏄惁寮�鍚暱鎸夎繛缁�掑鎴栭�掑噺 + longPress: { + type: Boolean, + default: true + }, + // 寮�鍚暱鎸夎Е鍙戝悗锛屾瘡瑙﹀彂涓�娆¢渶瑕佸涔� + pressTime: { + type: [Number, String], + default: 250 + }, + // 鏄惁鍙兘杈撳叆澶т簬鎴栫瓑浜�0鐨勬暣鏁�(姝f暣鏁�) + positiveInteger: { + type: Boolean, + default: true + } + }, + watch: { + value(v1, v2) { + // 鍙湁value鐨勬敼鍙樻槸鏉ヨ嚜澶栭儴鐨勬椂鍊欙紝鎵嶅幓鍚屾inputVal鐨勫�硷紝鍚﹀垯浼氶�犳垚寰幆閿欒 + if(!this.changeFromInner) { + this.inputVal = v1; + // 鍥犱负inputVal鍙樺寲鍚庯紝浼氳Е鍙憈his.handleChange()锛屽湪鍏朵腑changeFromInner浼氬啀娆¤璁剧疆涓簍rue锛� + // 閫犳垚澶栭潰淇敼鍊硷紝涔熷鑷磋璁や负鏄唴閮ㄤ慨鏀圭殑娣蜂贡锛岃繖閲岃繘琛宼his.$nextTick寤舵椂锛屼繚璇佸湪杩愯鍛ㄦ湡鐨勬渶鍚庡 + // 灏哻hangeFromInner璁剧疆涓篺alse + this.$nextTick(function(){ + this.changeFromInner = false; + }) + } + }, + inputVal(v1, v2) { + // 涓轰簡璁╃敤鎴疯兘澶熷垹闄ゆ墍鏈夎緭鍏ュ�硷紝閲嶆柊杈撳叆鍐呭锛屽垹闄ゆ墍鏈夊�煎悗锛屽唴瀹逛负绌哄瓧绗︿覆 + if (v1 == '') return; + let value = 0; + // 棣栧厛鍒ゆ柇鏄惁鏁板�硷紝骞朵笖鍦╩in鍜宮ax涔嬮棿锛屽鏋滀笉鏄紝浣跨敤鍘熸潵鍊� + let tmp = this.$u.test.number(v1); + if (tmp && v1 >= this.min && v1 <= this.max) value = v1; + else value = v2; + // 鍒ゆ柇鏄惁鍙兘杈撳叆澶т簬绛変簬0鐨勬暣鏁� + if(this.positiveInteger) { + // 灏忎簬0锛屾垨鑰呭甫鏈夊皬鏁扮偣锛� + if(v1 < 0 || String(v1).indexOf('.') !== -1) { + value = v2; + // 鍙屽悜缁戝畾input鐨勫�硷紝蹇呴』瑕佷娇鐢�$nextTick淇敼鏄剧ず鐨勫�� + this.$nextTick(() => { + this.inputVal = v2; + }) + } + } + // 鍙戝嚭change浜嬩欢 + this.handleChange(value, 'change'); + } + }, + data() { + return { + inputVal: 1, // 杈撳叆妗嗕腑鐨勫�硷紝涓嶈兘鐩存帴浣跨敤props涓殑value锛屽洜涓哄簲璇ユ敼鍙榩rops鐨勭姸鎬� + timer: null, // 鐢ㄤ綔闀挎寜鐨勫畾鏃跺櫒 + changeFromInner: false, // 鍊煎彂鐢熷彉鍖栵紝鏄潵鑷唴閮ㄨ繕鏄閮� + innerChangeTimer: null, // 鍐呴儴瀹氭椂鍣� + }; + }, + created() { + this.inputVal = Number(this.value); + }, + computed: { + getCursorSpacing() { + // 鍏堝皢鍊艰浆涓簆x鍗曚綅锛屽啀杞负鏁板�� + return Number(uni.upx2px(this.cursorSpacing)); + } + }, + methods: { + // 鐐瑰嚮閫�鏍奸敭 + btnTouchStart(callback) { + // 鍏堟墽琛屼竴閬嶆柟娉曪紝鍚﹀垯浼氶�犳垚鏉惧紑鎵嬫椂锛屽氨鎵ц浜哻learTimer锛屽鑷存棤娉曞疄鐜板姛鑳� + this[callback](); + // 濡傛灉娌″紑鍚暱鎸夊姛鑳斤紝鐩存帴杩斿洖 + if (!this.longPress) return; + clearInterval(this.timer); //鍐嶆娓呯┖瀹氭椂鍣紝闃叉閲嶅娉ㄥ唽瀹氭椂鍣� + this.timer = null; + this.timer = setInterval(() => { + // 鎵ц鍔犳垨鍑忓嚱鏁� + this[callback](); + }, this.pressTime); + }, + clearTimer() { + this.$nextTick(() => { + clearInterval(this.timer); + this.timer = null; + }) + }, + minus() { + this.computeVal('minus'); + }, + plus() { + this.computeVal('plus'); + }, + // 涓轰簡淇濊瘉灏忔暟鐩稿姞鍑忓嚭鐜扮簿搴︽孩鍑虹殑闂 + calcPlus(num1, num2) { + let baseNum, baseNum1, baseNum2; + try { + baseNum1 = num1.toString().split('.')[1].length; + } catch (e) { + baseNum1 = 0; + } + try { + baseNum2 = num2.toString().split('.')[1].length; + } catch (e) { + baseNum2 = 0; + } + baseNum = Math.pow(10, Math.max(baseNum1, baseNum2)); + let precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2; //绮惧害 + return ((num1 * baseNum + num2 * baseNum) / baseNum).toFixed(precision); + }, + // 涓轰簡淇濊瘉灏忔暟鐩稿姞鍑忓嚭鐜扮簿搴︽孩鍑虹殑闂 + calcMinus(num1, num2) { + let baseNum, baseNum1, baseNum2; + try { + baseNum1 = num1.toString().split('.')[1].length; + } catch (e) { + baseNum1 = 0; + } + try { + baseNum2 = num2.toString().split('.')[1].length; + } catch (e) { + baseNum2 = 0; + } + baseNum = Math.pow(10, Math.max(baseNum1, baseNum2)); + let precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2; + return ((num1 * baseNum - num2 * baseNum) / baseNum).toFixed(precision); + }, + computeVal(type) { + uni.hideKeyboard(); + if (this.disabled) return; + let value = 0; + // 鍑� + if (type === 'minus') { + value = this.calcMinus(this.inputVal, this.step); + } else if (type === 'plus') { + value = this.calcPlus(this.inputVal, this.step); + } + // 鍒ゆ柇鏄惁灏忎簬鏈�灏忓�煎拰澶т簬鏈�澶у�� + if (value < this.min || value > this.max) { + return; + } + this.inputVal = value; + this.handleChange(value, type); + }, + // 澶勭悊鐢ㄦ埛鎵嬪姩杈撳叆鐨勬儏鍐� + onBlur(event) { + let val = 0; + let value = event.detail.value; + // 濡傛灉涓洪潪0-9鏁板瓧缁勬垚锛屾垨鑰呭叾绗竴浣嶆暟鍊间负0锛岀洿鎺ヨ鍏剁瓑浜巑in鍊� + // 杩欓噷涓嶇洿鎺ュ垽鏂槸鍚︽鏁存暟锛屾槸鍥犱负鐢ㄦ埛浼犻�掔殑props min鍊煎彲鑳戒负0 + if (!/(^\d+$)/.test(value) || value[0] == 0) val = this.min; + val = +value; + if (val > this.max) { + val = this.max; + } else if (val < this.min) { + val = this.min; + } + this.$nextTick(() => { + this.inputVal = val; + }) + this.handleChange(val, 'blur'); + }, + // 杈撳叆妗嗚幏寰楃劍鐐逛簨浠� + onFocus() { + this.$emit('focus'); + }, + handleChange(value, type) { + if (this.disabled) return; + // 娓呴櫎瀹氭椂鍣紝閬垮厤閫犳垚娣蜂贡 + if(this.innerChangeTimer) { + clearTimeout(this.innerChangeTimer); + this.innerChangeTimer = null; + } + // 鍙戝嚭input浜嬩欢锛屼慨鏀归�氳繃v-model缁戝畾鐨勫�硷紝杈惧埌鍙屽悜缁戝畾鐨勬晥鏋� + this.changeFromInner = true; + // 涓�瀹氭椂闂村唴锛屾竻闄hangeFromInner鏍囪锛屽惁鍒欏唴閮ㄥ�兼敼鍙樺悗 + // 澶栭儴閫氳繃绋嬪簭淇敼value鍊硷紝灏嗕細鏃犳晥 + this.innerChangeTimer = setTimeout(() => { + this.changeFromInner = false; + }, 150); + this.$emit('input', Number(value)); + this.$emit(type, { + // 杞负Number绫诲瀷 + value: Number(value), + index: this.index + }) + } + } + }; +</script> + +<style lang="scss" scoped> + @import "../../libs/css/style.components.scss"; + + .u-numberbox { + display: inline-flex; + align-items: center; + } + + .u-number-input { + position: relative; + text-align: center; + padding: 0; + margin: 0 6rpx; + @include vue-flex; + align-items: center; + justify-content: center; + } + + .u-icon-plus, + .u-icon-minus { + width: 60rpx; + @include vue-flex; + justify-content: center; + align-items: center; + } + + .u-icon-plus { + border-radius: 0 8rpx 8rpx 0; + } + + .u-icon-minus { + border-radius: 8rpx 0 0 8rpx; + } + + .u-icon-disabled { + color: #c8c9cc !important; + background: #f7f8fa !important; + } + + .u-input-disabled { + color: #c8c9cc !important; + background-color: #f2f3f5 !important; + } +</style> -- Gitblit v1.9.3