From d1448cb0ef10f358bb7bddb4e1ec268515e0b787 Mon Sep 17 00:00:00 2001 From: gaoluyang <2820782392@qq.com> Date: 星期二, 15 七月 2025 11:46:57 +0800 Subject: [PATCH] 项目初始化 --- uni_modules/uview-ui/components/u-number-box/u-number-box.vue | 416 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 416 insertions(+), 0 deletions(-) diff --git a/uni_modules/uview-ui/components/u-number-box/u-number-box.vue b/uni_modules/uview-ui/components/u-number-box/u-number-box.vue new file mode 100644 index 0000000..69211c5 --- /dev/null +++ b/uni_modules/uview-ui/components/u-number-box/u-number-box.vue @@ -0,0 +1,416 @@ +<template> + <view class="u-number-box"> + <view + class="u-number-box__slot" + @tap.stop="clickHandler('minus')" + @touchstart="onTouchStart('minus')" + @touchend.stop="clearTimeout" + v-if="showMinus && $slots.minus" + > + <slot name="minus" /> + </view> + <view + v-else-if="showMinus" + class="u-number-box__minus" + @tap.stop="clickHandler('minus')" + @touchstart="onTouchStart('minus')" + @touchend.stop="clearTimeout" + hover-class="u-number-box__minus--hover" + hover-stay-time="150" + :class="{ 'u-number-box__minus--disabled': isDisabled('minus') }" + :style="[buttonStyle('minus')]" + > + <u-icon + name="minus" + :color="isDisabled('minus') ? '#c8c9cc' : '#323233'" + size="15" + bold + :customStyle="iconStyle" + ></u-icon> + </view> + + <slot name="input"> + <input + :disabled="disabledInput || disabled" + :cursor-spacing="getCursorSpacing" + :class="{ 'u-number-box__input--disabled': disabled || disabledInput }" + v-model="currentValue" + class="u-number-box__input" + @blur="onBlur" + @focus="onFocus" + @input="onInput" + type="number" + :style="[inputStyle]" + /> + </slot> + <view + class="u-number-box__slot" + @tap.stop="clickHandler('plus')" + @touchstart="onTouchStart('plus')" + @touchend.stop="clearTimeout" + v-if="showPlus && $slots.plus" + > + <slot name="plus" /> + </view> + <view + v-else-if="showPlus" + class="u-number-box__plus" + @tap.stop="clickHandler('plus')" + @touchstart="onTouchStart('plus')" + @touchend.stop="clearTimeout" + hover-class="u-number-box__plus--hover" + hover-stay-time="150" + :class="{ 'u-number-box__minus--disabled': isDisabled('plus') }" + :style="[buttonStyle('plus')]" + > + <u-icon + name="plus" + :color="isDisabled('plus') ? '#c8c9cc' : '#323233'" + size="15" + bold + :customStyle="iconStyle" + ></u-icon> + </view> + </view> +</template> + +<script> + import props from './props.js'; + /** + * numberBox 姝ヨ繘鍣� + * @description 璇ョ粍浠朵竴鑸敤浜庡晢鍩庤喘鐗╅�夋嫨鐗╁搧鏁伴噺鐨勫満鏅�� + * @tutorial https://uviewui.com/components/numberBox.html + * @property {String | Number} name 姝ヨ繘鍣ㄦ爣璇嗙锛屽湪change鍥炶皟杩斿洖 + * @property {String | Number} value 鐢ㄤ簬鍙屽悜缁戝畾鐨勫�硷紝鍒濆鍖栨椂璁剧疆璁句负榛樿min鍊�(鏈�灏忓��) 锛堥粯璁� 0 锛� + * @property {String | Number} min 鏈�灏忓�� 锛堥粯璁� 1 锛� + * @property {String | Number} max 鏈�澶у�� 锛堥粯璁� Number.MAX_SAFE_INTEGER 锛� + * @property {String | Number} step 鍔犲噺鐨勬闀匡紝鍙负灏忔暟 锛堥粯璁� 1 锛� + * @property {Boolean} integer 鏄惁鍙厑璁歌緭鍏ユ暣鏁� 锛堥粯璁� false 锛� + * @property {Boolean} disabled 鏄惁绂佺敤锛屽寘鎷緭鍏ユ锛屽姞鍑忔寜閽� 锛堥粯璁� false 锛� + * @property {Boolean} disabledInput 鏄惁绂佺敤杈撳叆妗� 锛堥粯璁� false 锛� + * @property {Boolean} asyncChange 鏄惁寮�鍚紓姝ュ彉鏇达紝寮�鍚悗闇�瑕佹墜鍔ㄦ帶鍒惰緭鍏ュ�� 锛堥粯璁� false 锛� + * @property {String | Number} inputWidth 杈撳叆妗嗗搴︼紝鍗曚綅涓簆x 锛堥粯璁� 35 锛� + * @property {Boolean} showMinus 鏄惁鏄剧ず鍑忓皯鎸夐挳 锛堥粯璁� true 锛� + * @property {Boolean} showPlus 鏄惁鏄剧ず澧炲姞鎸夐挳 锛堥粯璁� true 锛� + * @property {String | Number} decimalLength 鏄剧ず鐨勫皬鏁颁綅鏁� + * @property {Boolean} longPress 鏄惁寮�鍚暱鎸夊姞鍑忔墜鍔� 锛堥粯璁� true 锛� + * @property {String} color 杈撳叆妗嗘枃瀛楀拰鍔犲噺鎸夐挳鍥炬爣鐨勯鑹� 锛堥粯璁� '#323233' 锛� + * @property {String | Number} buttonSize 鎸夐挳澶у皬锛屽楂樼瓑浜庢鍊硷紝鍗曚綅px锛岃緭鍏ユ楂樺害鍜屾鍊间繚鎸佷竴鑷� 锛堥粯璁� 30 锛� + * @property {String} bgColor 杈撳叆妗嗗拰鎸夐挳鐨勮儗鏅鑹� 锛堥粯璁� '#EBECEE' 锛� + * @property {String | Number} cursorSpacing 鎸囧畾鍏夋爣浜庨敭鐩樼殑璺濈锛岄伩鍏嶉敭鐩橀伄鎸¤緭鍏ユ锛屽崟浣峱x 锛堥粯璁� 100 锛� + * @property {Boolean} disablePlus 鏄惁绂佺敤澧炲姞鎸夐挳 锛堥粯璁� false 锛� + * @property {Boolean} disableMinus 鏄惁绂佺敤鍑忓皯鎸夐挳 锛堥粯璁� false 锛� + * @property {Object 锝� String} iconStyle 鍔犲噺鎸夐挳鍥炬爣鐨勬牱寮� + * + * @event {Function} onFocus 杈撳叆妗嗘椿鍔ㄧ劍鐐� + * @event {Function} onBlur 杈撳叆妗嗗け鍘荤劍鐐� + * @event {Function} onInput 杈撳叆妗嗗�煎彂鐢熷彉鍖� + * @event {Function} onChange + * @example <u-number-box v-model="value" @change="valChange"></u-number-box> + */ + export default { + name: 'u-number-box', + mixins: [uni.$u.mpMixin, uni.$u.mixin, props], + data() { + return { + // 杈撳叆妗嗗疄闄呮搷浣滅殑鍊� + currentValue: '', + // 瀹氭椂鍣� + longPressTimer: null + } + }, + watch: { + // 澶氫釜鍊间箣闂达紝鍙涓�涓�煎彂鐢熷彉鍖栵紝閮借閲嶆柊妫�鏌heck()鍑芥暟 + watchChange(n) { + this.check() + }, + // 鐩戝惉v-mode鐨勫彉鍖栵紝閲嶆柊鍒濆鍖栧唴閮ㄧ殑鍊� + value(n) { + if (n !== this.currentValue) { + this.currentValue = this.format(this.value) + } + } + }, + computed: { + getCursorSpacing() { + // 鍒ゆ柇浼犲叆鐨勫崟浣嶏紝濡傛灉涓簆x鍗曚綅锛岄渶瑕佽浆鎴恜x + return uni.$u.getPx(this.cursorSpacing) + }, + // 鎸夐挳鐨勬牱寮� + buttonStyle() { + return (type) => { + const style = { + backgroundColor: this.bgColor, + height: uni.$u.addUnit(this.buttonSize), + color: this.color + } + if (this.isDisabled(type)) { + style.backgroundColor = '#f7f8fa' + } + return style + } + }, + // 杈撳叆妗嗙殑鏍峰紡 + inputStyle() { + const disabled = this.disabled || this.disabledInput + const style = { + color: this.color, + backgroundColor: this.bgColor, + height: uni.$u.addUnit(this.buttonSize), + width: uni.$u.addUnit(this.inputWidth) + } + return style + }, + // 鐢ㄤ簬鐩戝惉澶氫釜鍊煎彂鐢熷彉鍖� + watchChange() { + return [this.integer, this.decimalLength, this.min, this.max] + }, + isDisabled() { + return (type) => { + if (type === 'plus') { + // 鍦ㄧ偣鍑诲鍔犳寜閽儏鍐典笅锛屽垽鏂暣浣撶殑disabled锛屾槸鍚﹀崟鐙鐢ㄥ鍔犳寜閽紝浠ュ強褰撳墠鍊兼槸鍚﹀ぇ浜庢渶澶х殑鍏佽鍊� + return ( + this.disabled || + this.disablePlus || + this.currentValue >= this.max + ) + } + // 鐐瑰嚮鍑忓皯鎸夐挳鍚岀悊 + return ( + this.disabled || + this.disableMinus || + this.currentValue <= this.min + ) + } + }, + }, + mounted() { + this.init() + }, + methods: { + init() { + this.currentValue = this.format(this.value) + }, + // 鏍煎紡鍖栨暣鐞嗘暟鎹紝闄愬埗鑼冨洿 + format(value) { + value = this.filter(value) + // 濡傛灉涓虹┖瀛楃涓诧紝閭d箞璁剧疆涓�0锛屽悓鏃跺皢鍊艰浆涓篘umber绫诲瀷 + value = value === '' ? 0 : +value + // 瀵规瘮鏈�澶ф渶灏忓�硷紝鍙栧湪min鍜宮ax涔嬮棿鐨勫�� + value = Math.max(Math.min(this.max, value), this.min) + // 濡傛灉璁惧畾浜嗘渶澶х殑灏忔暟浣嶆暟锛屼娇鐢╰oFixed鍘昏繘琛屾牸寮忓寲 + if (this.decimalLength !== null) { + value = value.toFixed(this.decimalLength) + } + return value + }, + // 杩囨护闈炴硶鐨勫瓧绗� + filter(value) { + // 鍙厑璁�0-9涔嬮棿鐨勬暟瀛楋紝"."涓哄皬鏁扮偣锛�"-"涓鸿礋鏁版椂鍊欎娇鐢� + value = String(value).replace(/[^0-9.-]/g, '') + // 濡傛灉鍙厑璁歌緭鍏ユ暣鏁帮紝鍒欒繃婊ゆ帀灏忔暟鐐瑰悗鐨勯儴鍒� + if (this.integer && value.indexOf('.') !== -1) { + value = value.split('.')[0] + } + return value; + }, + check() { + // 鏍煎紡鍖栦簡涔嬪悗锛屽鏋滃墠鍚庣殑鍊间笉鐩哥瓑锛岄偅涔堣缃负鏍煎紡鍖栧悗鐨勫�� + const val = this.format(this.currentValue); + if (val !== this.currentValue) { + this.currentValue = val + } + }, + // 鍒ゆ柇鏄惁鍑轰簬绂佹鎿嶄綔鐘舵�� + // isDisabled(type) { + // if (type === 'plus') { + // // 鍦ㄧ偣鍑诲鍔犳寜閽儏鍐典笅锛屽垽鏂暣浣撶殑disabled锛屾槸鍚﹀崟鐙鐢ㄥ鍔犳寜閽紝浠ュ強褰撳墠鍊兼槸鍚﹀ぇ浜庢渶澶х殑鍏佽鍊� + // return ( + // this.disabled || + // this.disablePlus || + // this.currentValue >= this.max + // ) + // } + // // 鐐瑰嚮鍑忓皯鎸夐挳鍚岀悊 + // return ( + // this.disabled || + // this.disableMinus || + // this.currentValue <= this.min + // ) + // }, + // 杈撳叆妗嗘椿鍔ㄧ劍鐐� + onFocus(event) { + this.$emit('focus', { + ...event.detail, + name: this.name, + }) + }, + // 杈撳叆妗嗗け鍘荤劍鐐� + onBlur(event) { + // 瀵硅緭鍏ュ�艰繘琛屾牸寮忓寲 + const value = this.format(event.detail.value) + // 鍙戝嚭blur浜嬩欢 + this.$emit( + 'blur',{ + ...event.detail, + name: this.name, + } + ) + }, + // 杈撳叆妗嗗�煎彂鐢熷彉鍖� + onInput(e) { + const { + value = '' + } = e.detail || {} + // 涓虹┖杩斿洖 + if (value === '') return + let formatted = this.filter(value) + // 鏈�澶у厑璁哥殑灏忔暟闀垮害 + if (this.decimalLength !== null && formatted.indexOf('.') !== -1) { + const pair = formatted.split('.'); + formatted = `${pair[0]}.${pair[1].slice(0, this.decimalLength)}` + } + formatted = this.format(formatted) + this.emitChange(formatted); + }, + // 鍙戝嚭change浜嬩欢 + emitChange(value) { + // 濡傛灉寮�鍚簡寮傛鍙樻洿鍊硷紝鍒欎笉淇敼鍐呴儴鐨勫�硷紝闇�瑕佺敤鎴锋墜鍔ㄥ湪澶栭儴閫氳繃v-model鍙樻洿 + if (!this.asyncChange) { + this.$nextTick(() => { + this.$emit('input', value) + this.currentValue = value + this.$forceUpdate() + }) + } + this.$emit('change', { + value, + name: this.name, + }); + }, + onChange() { + const { + type + } = this + if (this.isDisabled(type)) { + return this.$emit('overlimit', type) + } + const diff = type === 'minus' ? -this.step : +this.step + const value = this.format(this.add(+this.currentValue, diff)) + this.emitChange(value) + this.$emit(type) + }, + // 瀵瑰�兼墿澶у悗杩涜鍥涜垗浜斿叆锛屽啀闄や互鎵╁ぇ鍥犲瓙锛岄伩鍏嶅嚭鐜版诞鐐规暟鎿嶄綔鐨勭簿搴﹂棶棰� + add(num1, num2) { + const cardinal = Math.pow(10, 10); + return Math.round((num1 + num2) * cardinal) / cardinal + }, + // 鐐瑰嚮鍔犲噺鎸夐挳 + clickHandler(type) { + this.type = type + this.onChange() + }, + longPressStep() { + // 姣忛殧涓�娈垫椂闂达紝閲嶆柊璋冪敤longPressStep鏂规硶锛屽疄鐜伴暱鎸夊姞鍑� + this.clearTimeout() + this.longPressTimer = setTimeout(() => { + this.onChange() + this.longPressStep() + }, 250); + }, + onTouchStart(type) { + if (!this.longPress) return + this.clearTimeout() + this.type = type + // 涓�瀹氭椂闂村悗锛岄粯璁よ揪鍒伴暱鎸夌姸鎬� + this.longPressTimer = setTimeout(() => { + this.onChange() + this.longPressStep() + }, 600) + }, + // 瑙︽懜缁撴潫锛屾竻闄ゅ畾鏃跺櫒锛屽仠姝㈤暱鎸夊姞鍑� + onTouchEnd() { + if (!this.longPress) return + this.clearTimeout() + }, + // 娓呴櫎瀹氭椂鍣� + clearTimeout() { + clearTimeout(this.longPressTimer) + this.longPressTimer = null + } + } + } +</script> + +<style lang="scss" scoped> + @import '../../libs/css/components.scss'; + + $u-numberBox-hover-bgColor: #E6E6E6 !default; + $u-numberBox-disabled-color: #c8c9cc !default; + $u-numberBox-disabled-bgColor: #f7f8fa !default; + $u-numberBox-plus-radius: 4px !default; + $u-numberBox-minus-radius: 4px !default; + $u-numberBox-input-text-align: center !default; + $u-numberBox-input-font-size: 15px !default; + $u-numberBox-input-padding: 0 !default; + $u-numberBox-input-margin: 0 2px !default; + $u-numberBox-input-disabled-color: #c8c9cc !default; + $u-numberBox-input-disabled-bgColor: #f2f3f5 !default; + + .u-number-box { + @include flex(row); + align-items: center; + + &__slot { + /* #ifndef APP-NVUE */ + touch-action: none; + /* #endif */ + } + + &__plus, + &__minus { + width: 35px; + @include flex; + justify-content: center; + align-items: center; + /* #ifndef APP-NVUE */ + touch-action: none; + /* #endif */ + + &--hover { + background-color: $u-numberBox-hover-bgColor !important; + } + + &--disabled { + color: $u-numberBox-disabled-color; + background-color: $u-numberBox-disabled-bgColor; + } + } + + &__plus { + border-top-right-radius: $u-numberBox-plus-radius; + border-bottom-right-radius: $u-numberBox-plus-radius; + } + + &__minus { + border-top-left-radius: $u-numberBox-minus-radius; + border-bottom-left-radius: $u-numberBox-minus-radius; + } + + &__input { + position: relative; + text-align: $u-numberBox-input-text-align; + font-size: $u-numberBox-input-font-size; + padding: $u-numberBox-input-padding; + margin: $u-numberBox-input-margin; + @include flex; + align-items: center; + justify-content: center; + + &--disabled { + color: $u-numberBox-input-disabled-color; + background-color: $u-numberBox-input-disabled-bgColor; + } + } + } +</style> -- Gitblit v1.9.3