uni-number-box.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. <template>
  2. <view class="uni-numbox">
  3. <view class="uni-numbox__minus" :class="{'uni-numbox--disabled': disableSubtract||disabled}" @click="_calcValue('subtract')">-</view>
  4. <input class="uni-numbox__value" type="number" :disabled="disabled" :value="inputValue" @blur="_onBlur">
  5. <view class="uni-numbox__plus" :class="{'uni-numbox--disabled': disableAdd||disabled}" @click="_calcValue('add')">+</view>
  6. </view>
  7. </template>
  8. <script>
  9. export default {
  10. name: 'uni-number-box',
  11. props: {
  12. rowData:{
  13. type: Object,
  14. default:function(){
  15. return {}
  16. }
  17. },
  18. value: {
  19. type: Number,
  20. default: 1
  21. },
  22. min: {
  23. type: Number,
  24. default: 0
  25. },
  26. max: {
  27. type: Number,
  28. default: 100
  29. },
  30. step: {
  31. type: Number,
  32. default: 1
  33. },
  34. disabled: {
  35. type: Boolean,
  36. default: false
  37. }
  38. },
  39. data() {
  40. return {
  41. inputValue: this.value
  42. }
  43. },
  44. computed: {
  45. disableSubtract() {
  46. return this.inputValue <= this.min
  47. },
  48. disableAdd() {
  49. return this.inputValue >= this.max
  50. }
  51. },
  52. watch: {
  53. value(val) {
  54. this.inputValue = val;
  55. },
  56. inputValue(val,old) {
  57. this.$emit('change', {oldval:old,newval:val,rowData:this.rowData});
  58. }
  59. },
  60. methods: {
  61. _calcValue(type) {
  62. if (this.disabled) {
  63. return
  64. }
  65. const scale = this._getDecimalScale()
  66. let value = this.inputValue * scale
  67. let step = this.step * scale
  68. if (type === 'subtract') {
  69. value -= step
  70. } else if (type === 'add') {
  71. value += step
  72. }
  73. if (value < this.min || value > this.max) {
  74. return
  75. }
  76. this.inputValue = value / scale;
  77. },
  78. _getDecimalScale() {
  79. let scale = 1
  80. // 浮点型
  81. if (~~this.step !== this.step) {
  82. scale = Math.pow(10, (this.step + '').split('.')[1].length)
  83. }
  84. return scale
  85. },
  86. _onBlur(event) {
  87. let value = event.detail.value
  88. if (!value) {
  89. this.inputValue = 0
  90. return
  91. }
  92. value = +value;
  93. if (value > this.max) {
  94. value = this.max
  95. } else if (value < this.min) {
  96. value = this.min
  97. }
  98. this.inputValue = value
  99. }
  100. }
  101. }
  102. </script>
  103. <style lang="scss">
  104. $numbox-btn-width:70upx;
  105. $numbox-input-width:80upx;
  106. $numbox-height:70upx;
  107. $uni-font-size-xxl:40upx;
  108. $uni-text-color:#666666;
  109. $uni-border-color:#dadada;
  110. .uni-numbox {
  111. display: inline-flex;
  112. flex-direction: row;
  113. justify-content: flex-start;
  114. height: $numbox-height;
  115. position: relative;
  116. &:after {
  117. content: '';
  118. position: absolute;
  119. transform-origin: center;
  120. box-sizing: border-box;
  121. pointer-events: none;
  122. top: -50%;
  123. left: -50%;
  124. right: -50%;
  125. bottom: -50%;
  126. border-radius: $uni-border-radius-lg;
  127. transform: scale(.5);
  128. }
  129. &__minus,
  130. &__plus {
  131. margin: 0;
  132. // background-color: $uni-bg-color-grey;
  133. background-color: #fff;
  134. width: $numbox-btn-width;
  135. font-size: $uni-font-size-xxl;
  136. height: 100%;
  137. line-height: $numbox-height;
  138. text-align: center;
  139. color: $uni-text-color;
  140. position: relative;
  141. border-radius: 100%;
  142. border: 1px solid $uni-border-color;
  143. }
  144. &__value {
  145. position: relative;
  146. // background-color: $uni-bg-color;
  147. background-color: #fff;
  148. width: $numbox-input-width;
  149. height: 100%;
  150. text-align: center;
  151. &:after {
  152. content: '';
  153. position: absolute;
  154. transform-origin: center;
  155. box-sizing: border-box;
  156. pointer-events: none;
  157. top: -50%;
  158. left: -50%;
  159. right: -50%;
  160. bottom: -50%;
  161. transform: scale(.5);
  162. }
  163. }
  164. &--disabled {
  165. color: $uni-text-color-disable;
  166. }
  167. }
  168. </style>