rk
2025-09-28 2304d7b140c5c5b4bf3a83f9ced8bff37d20c42e
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
<template>
    <view>
        <view class="skidway" id="skidway"
         :style="{ 
             borderRadius: round.show ? round.style : '',
             height: height + 'rpx',
             border: border.show ? border.style : ''}">
            <view :style="{ width:moveWidth + sliderWidth + 'px', borderRadius: round.show ? round.style : '' }" class="end-status skidway-style">
                <slot name="isFinished">
                    <view style="height: 100%;background-color: #65B58A; color: #fff; display: flex; justify-content: center;align-items: center;">
                            滑动成功
                    </view>
                </slot>
            </view>
            <view class="skidway-style" :style="{borderRadius: round.show ? round.style : ''}">
                <slot name="init">
                    <view style="background-color: #DEE1E6; color: #000; height: 100%; display: flex; justify-content: center;align-items: center;">右滑解锁</view>
                </slot>
            </view>
            <view
             :style="{
                 left:moveWidth +'px',
                 borderRadius: round.show ? round.style : '',
                 width: sliderSize + 'rpx',
                 height: sliderSize + 'rpx'}"
             @touchstart="slideStart"
             @touchmove="slideMove"
             @touchend="slideEnd"
             id="slider"
             class="slider">
                <view v-if="!finishFlag" style="height: 100%; width: 100%;">
                    <slot name="begin">
                        <view style="background-color: #E5673B; height: 100%; display: flex; justify-content: center; align-items: center; color: #fff;">
                            开始
                        </view>
                    </slot>
                </view>
                <view v-else style="height: 100%; width: 100%;" v-show="isShowEnd">
                    <slot name="end">
                        <view style="background-color: #1BA035; height: 100%; display: flex; justify-content: center; align-items: center; color: #fff;">
                            结束
                        </view>
                    </slot>
                </view>
            </view>
        </view>
    </view>
</template>
 
<script>
    export default {
        props: {
            height: {
                type: Number,
                default: 80,
            },
            sliderSize: {
                type: Number,
                default: 80
            },
            round: {
                type: Object,
                default: function () {
                    return { show: false, style: '1rpx solid #C8C9CC' }
                }
            },
            border: {
                type: Object,
                default: function () {
                    return { show: false, style: '1rpx solid #C8C9CC' }
                }
            },
            isShowEndSlider: {
                type: Boolean,
                default: true,
            },
        },
        data() {
            return {
                initX: 0,  // 触发屏幕时的初始位置
                moveWidth: 0,  // 滑动的距离
                skidwayWidth: 0,  // 滑道长度
                sliderWidth: 0, // 滑块长度
                finishFlag: false, // 滑动是否完成
                isMove:true, // 是否可滑动
                isShowEnd: this.isShowEndSlider  // 是否显示结束滑块
            }
        },
        mounted() {
            const elemt = uni.createSelectorQuery().in(this)
            elemt.select('#skidway').boundingClientRect((data) => {
                this.skidwayWidth = data.width;
            }).exec()
            elemt.select('#slider').boundingClientRect((data) => {
                this.sliderWidth = data.width;
            }).exec()
            console.log('触发', this.skidwayWidth, this.sliderWidth);
        },
        methods: {
            slideStart(e) {
                this.initX = e.touches[0].clientX;  // 距离屏幕左侧的距离
                this.isMove = true;  // 允许滑动
            },
            slideReset() {
                this.finishFlag = false;
                this.moveWidth = 0;
            },
            slideFinish() {
                this.isMove = false;
                this.finishFlag = true;
                this.$emit('slideFinish', { status: 'success', resetFunc: this.slideReset });
            },
            slideMove(e) {
                if(!this.isMove) return;
                if (this.moveWidth >= (this.skidwayWidth - this.sliderWidth)) {
                    this.moveWidth = this.skidwayWidth - this.sliderWidth
                    this.slideFinish()
                } else {
                    let width = e.touches[0].clientX - this.initX;
                    if (width<=0) {  // 如果滑动的位置到初始位置的距离小于0,则回到原位
                        width = 0
                    }
                    this.moveWidth = width;
                }
            },
            slideEnd(e) {  // 触摸结束判断滑动是否完成,未完成则回到原位
                if(!this.finishFlag){
                    this.slideReset();
                }
            }
        },
    }
</script>
 
<style lang="scss" scoped>
    .skidway {    
        display: flex;
        align-items: center;
        position: relative;
        .slider {
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            overflow: auto;
            z-index: 2;
        }
        .skidway-style {
            width: 100%;
            height: 100%;
            overflow: auto;
            position: absolute;
            left: 0;
            top: 0;
        }
        .end-status {
            z-index: 1;
        }
    }
</style>