fs-number-box.vue 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. <template>
  2. <view class="fs-number-box" :class="{'fs-number-box-round': round}">
  3. <view
  4. class="fs-number-box-item fs-number-box-left"
  5. @click="minus">
  6. <fs-icon type="icon-minus" size="32rpx" :color="minusDisabled ? '#c8c9cc' : ''"></fs-icon>
  7. </view>
  8. <input
  9. class="fs-number-box-item fs-number-box-middle"
  10. type="number"
  11. :value="modelValue"
  12. @blur="handleChange"
  13. :disabled="disableInput"
  14. />
  15. <view
  16. class="fs-number-box-item fs-number-box-right"
  17. @click="add">
  18. <fs-icon type="icon-plus" size="32rpx" :color="addDisabled ? '#c8c9cc' : ''"></fs-icon>
  19. </view>
  20. </view>
  21. </template>
  22. <script>
  23. export default {
  24. name: 'fs-number-box',
  25. }
  26. </script>
  27. <script setup>
  28. import { ref, watch, computed } from 'vue'
  29. const props = defineProps({
  30. modelValue: {
  31. type: Number,
  32. default: 1
  33. },
  34. min: {
  35. type: Number,
  36. default: 1
  37. },
  38. max: {
  39. type: Number,
  40. default: Number.MAX_SAFE_INTEGER
  41. },
  42. step: {
  43. type: Number,
  44. default: 1
  45. },
  46. round: Boolean,
  47. disableInput: Boolean,
  48. })
  49. const emits = defineEmits(['update:modelValue','change'])
  50. let initValue = ref(props.modelValue)
  51. watch(() => props.modelValue, val => {
  52. initValue.value = val
  53. })
  54. watch(initValue, val => {
  55. emits('update:modelValue', val)
  56. emits('change', val)
  57. })
  58. const add = () => {
  59. initValue.value += Number(props.step)
  60. if (initValue.value > props.max) {
  61. initValue.value = props.max
  62. }
  63. }
  64. const minus = () => {
  65. initValue.value -= Number(props.step)
  66. if (initValue.value < props.min) {
  67. initValue.value = props.min
  68. }
  69. }
  70. const handleChange = e => {
  71. initValue.value = Number(e.detail.value) || props.min
  72. if (initValue.value < props.min) {
  73. initValue.value = props.min
  74. } else if (initValue.value > props.max) {
  75. initValue.value = props.max
  76. }
  77. }
  78. const minusDisabled = computed(() => initValue.value === props.min)
  79. const addDisabled = computed(() => initValue.value === props.max)
  80. </script>
  81. <style lang="scss" scoped>
  82. .fs-number-box{
  83. display: inline-flex;
  84. border: 2rpx solid var(--border-color);
  85. height: 60rpx;
  86. background-color: #fff;
  87. &-round{
  88. border-radius: 30rpx;
  89. }
  90. &-item{
  91. display: flex;
  92. height: 100%;
  93. justify-content: center;
  94. align-items: center;
  95. }
  96. &-left,
  97. &-right{
  98. width: 60rpx;
  99. }
  100. &-middle{
  101. box-sizing: border-box;
  102. width: 80rpx;
  103. border-left: 2rpx solid var(--border-color);
  104. border-right: 2rpx solid var(--border-color);
  105. padding: 10rpx;
  106. text-align: center;
  107. }
  108. }
  109. </style>