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