微信小程序悬浮客服

1.html:

<movable-area class="movableArea">

<movable-view class="movableView" direction="all" inertia x="{{x}}" y="{{y}}" bindchange="touchChange" bindtouchend="touchEnd">

<view class="dock-service-wrap {{pin?\'active\':\'\'}} {{isTouch?\'round\':\'\'}}">

<view class="mi-flex mi-align-items-center">

<mi-icon src="/images/kefu.png" width="90rpx" bindtap="handlePin" />

<navigator wx:if="{{!user.id}}" url="/pages/login/login">

<view class="dock-service-tips">

<text>HI\n</text>

<text>我是您的顾问,有任何问题\n随时都可以联系我。</text>

</view>

</navigator>

<button wx:else class="btn-contact" session-from="sobot|{{user.nickname}}|{{user.avatar_url}}||transfer_action={{transferAction}}" open-type="contact">

<view class="dock-service-tips">

<text>HI,{{user.nickname}}\n</text>

<text>我是您的顾问,有任何问题\n随时都可以联系我。</text>

</view>

</button>

<mi-icon class="dock-service-dock" src="/images/icon_arrow_right@2x.png" width="28rpx" bindtap="handleDock" />

</view>

</view>

</movable-view>

</movable-area>

2.css:

.movableArea {

position: fixed;

top: 0;

width: 100vw;

height: 100vh;

pointer-events: none;

z-index: 100;

}

.movableView {

pointer-events: auto;

width: 120rpx;

height: 120rpx;

}

.dock-service-wrap {

padding: 15rpx;

width: 132rpx;

max-height: 148rpx;

background-color: rgba(0, 0, 0, 0.7);

border-radius: 150rpx 0 0 150rpx;

overflow: hidden;

transition: border-radius 100ms ease-in-out;

}

.dock-service-wrap.active {

width: 480rpx;

}

.dock-service-wrap.round {

width: 120rpx;

border-radius: 150rpx

}

.dock-service-wrap.active .dock-service-tips {

display: block;

}

.dock-service-wrap.active .dock-service-dock {

display: block;

}

.dock-service-tips {

display: none;

margin-left: 16rpx;

color: #fff;

font-size: 24rpx;

line-height: 30rpx;

text-align: left;

}

.dock-service-dock {

margin-left: 16rpx;

display: none;

}

3.js:

import {

getUser

} from "./../../core/user.js";

Component({

options: {

styleIsolation: "apply-shared"

},

/**

* 组件的属性列表

*/

properties: {

y: {

type: Number,

value: 0,

},

},

/**

* 组件的初始数据

*/

data: {

user: {},

transferAction: "[{\'actionType\':\'to_group\',\'deciId\':\'b3d80dcbba164dffa8edf2a95feb9bf2\',\'optionId\':\'4\'}]",

initX: wx.getSystemInfoSync().safeArea.width,

x: wx.getSystemInfoSync().safeArea.width,

pin: false,

isTouch: false,

},

lifetimes: {

attached: function () {

this.setData({

user: getUser(),

});

},

ready: function () {

this.createSelectorQuery().select(".dock-service-wrap").fields({

size: true

}, res => {

this.setData({

initX: wx.getSystemInfoSync().safeArea.width - res.width,

x: wx.getSystemInfoSync().safeArea.width - res.width

});

}).exec();

}

},

pageLifetimes: {

show: function () {

this.setData({

user: getUser(),

});

// console.log(this.data.user);

}

},

/**

* 组件的方法列表

*/

methods: {

touchChange(event) {

let {

x,

y,

source

} = event.detail;

if (source === "touch") {

this.setData({

isTouch: true,

pin: false

});

} else if (x === this.data.initX) {

this.setData({

pin: false,

isTouch: false

});

}

},

touchEnd(event) {

// 只有拖动的时候才会去改变y坐标

// 其它因素触发该事件不会改变y坐标

if (this.data.isTouch === false) {

return;

}

let y = event.changedTouches[0].clientY;

this.setData({

x: this.data.initX,

y: y,

});

},

handlePin() {

// 如果拖动还未结束,点击无效

if (this.data.isTouch === true) {

return;

}

if (this.data.pin === false) {

this.setData({

pin: true,

});

this.createSelectorQuery().select(".dock-service-wrap").fields({

size: true

}, res => {

this.setData({

x: wx.getSystemInfoSync().safeArea.width - res.width

});

}).exec();

} else {

this.handleDock();

}

},

handleDock() {

this.setData({

x: this.data.initX,

});

}

}

})