Files
lucky_shop/components/hover-nav/hover-nav.vue

279 lines
7.0 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view v-if="pageCount == 1 || need" class="fixed-box" :style="{ height: fixBtnShow ? (isH5 ? '180rpx' : '330rpx') : '120rpx' }">
<!-- 统一的客服耳机按钮H5和小程序共用 -->
<!-- #ifdef MP-WEIXIN -->
<button
class="btn-item"
v-if="fixBtnShow"
hoverClass="none"
:open-type="weappOfficialService ? 'contact' : ''"
@click="handleWeappCustomerClick"
:style="{ backgroundImage: 'url(' + (kefuimg ? kefuimg : '') + ')', backgroundSize: '100% 100%' }"
>
<text class="icox icox-kefu" v-if="!kefuimg"></text>
<view v-if="unreadCount > 0 && isDifyService" class="unread-badge">
<text class="badge-text">{{ unreadCount > 99 ? '99+' : unreadCount }}</text>
</view>
</button>
<!-- #endif -->
<!-- #ifdef H5 -->
<button
class="btn-item"
v-if="fixBtnShow"
hoverClass="none"
@click="handleCustomerService"
:style="{ backgroundImage: 'url(' + (kefuimg ? kefuimg : '') + ')', backgroundSize: '100% 100%' }"
>
<text class="icox icox-kefu" v-if="!kefuimg"></text>
<view v-if="unreadCount > 0 && isDifyService" class="unread-badge">
<text class="badge-text">{{ unreadCount > 99 ? '99+' : unreadCount }}</text>
</view>
</button>
<!-- #endif -->
<view
class="btn-item"
v-if="fixBtnShow"
@click="call()"
:style="{ backgroundImage: 'url(' + (phoneimg ? phoneimg : '') + ')', backgroundSize: '100% 100%' }"
>
<text class="iconfont icon-dianhua" v-if="!phoneimg"></text>
</view>
</view>
</template>
<script>
import { createCustomerService } from '@/common/js/customer-service.js';
import { mapGetters, mapMutations } from 'vuex';
export default {
name: 'hover-nav',
props: {
need: {
type: Boolean,
default: false
}
},
data() {
return {
pageCount: 0,
fixBtnShow: true,
tel: '',
kefuimg: '',
phoneimg: '',
customerService: null,
buttonConfig: null,
isH5: false,
platformConfig: null,
latestConfig: null,
weappOfficialService: false // 微信小程序是否使用官方客服
};
},
created() {
// 1. 判断平台类型
// #ifdef H5
this.isH5 = true;
// #endif
// #ifdef MP-WEIXIN
this.isH5 = false;
// #endif
// 2. 初始化资源
this.kefuimg = this.$util.getDefaultImage().kefu;
this.phoneimg = this.$util.getDefaultImage().phone;
this.pageCount = getCurrentPages().length;
// 3. 获取店铺电话
this.getShopTel();
// 4. 首次加载获取最新配置(小程序强制请求最新配置,避免缓存)
this.getLatestConfig(true).then(config => {
this.latestConfig = config;
this.initCustomerService(config);
this.initWeappServiceType();
});
},
computed: {
...mapGetters([
'globalAIKefuConfig',
'aiUnreadCount'
]),
isDifyService() {
const serviceType = this.platformConfig?.type || '';
return serviceType === 'aikefu';
},
aiAgentimg() {
return this.globalAIKefuConfig?.icon || this.$util.getDefaultImage().aiAgent || '';
},
unreadCount() {
return this.aiUnreadCount;
}
},
methods: {
...mapMutations([
'setAiUnreadCount'
]),
/**
* 修复:微信小程序客服点击事件(直接触发客服逻辑)
*/
handleWeappCustomerClick() {
if (!this.weappOfficialService) {
// 直接调用客服处理逻辑
this.handleCustomerService();
}
},
/**
* 修复:获取最新配置(支持强制刷新,解决小程序缓存问题)
*/
async getLatestConfig(forceRefresh = false) {
return new Promise((resolve) => {
// H5/小程序强制请求最新配置,避免缓存
this.$api.sendRequest({
url: '/api/site/getServicerConfig',
header: {
'Cache-Control': 'no-cache, no-store, must-revalidate',
'Pragma': 'no-cache',
'Expires': '0'
},
data: { t: new Date().getTime() },
success: (res) => {
const config = res.code === 0 ? res.data : this.$store.state.servicerConfig || {};
this.$store.commit('UPDATE_SERVICER_CONFIG', config);
resolve(config);
},
fail: () => resolve(this.$store.state.servicerConfig || {})
});
});
},
/**
* 初始化客服服务(确保实例正确创建)
*/
initCustomerService(config = null) {
// 强制重新创建客服实例
this.customerService = null;
this.customerService = createCustomerService(this, config || this.latestConfig);
this.platformConfig = this.customerService.refreshConfig(config || this.latestConfig);
this.buttonConfig = this.customerService.getButtonConfig();
},
/**
* 微信小程序:初始化服务类型(修复判断逻辑)
*/
initWeappServiceType() {
// #ifdef MP-WEIXIN
this.weappOfficialService = this.buttonConfig?.openType === 'contact' && !this.isDifyService;
// #endif
},
/**
* 获取店铺电话
*/
getShopTel() {
uni.getStorage({
key: 'shopInfo',
success: (e) => {
if (e.data && e.data.mobile && /^1[3-9]\d{9}$/.test(e.data.mobile)) {
this.tel = e.data.mobile;
}
}
});
},
/**
* 拨打电话
*/
call() {
if (!this.tel || !/^1[3-9]\d{9}$/.test(this.tel)) {
uni.showToast({ title: '暂无有效联系电话', icon: 'none' });
return;
}
uni.makePhoneCall({
phoneNumber: this.tel,
fail: (err) => {
if (err.errMsg !== 'makePhoneCall:fail cancel') {
uni.showToast({ title: '拨号失败,请稍后重试', icon: 'none' });
}
}
});
},
/**
* 客服点击逻辑(修复:确保小程序端正确执行)
*/
async handleCustomerService() {
uni.showLoading({ title: '加载中...', mask: true });
try {
// 再次获取最新配置确保是dify模式
const newConfig = await this.getLatestConfig(true);
this.initCustomerService(newConfig);
// 强制触发客服点击
if (this.customerService) {
this.customerService.handleCustomerClick();
}
} catch (e) {
uni.showToast({ title: '操作失败', icon: 'none' });
} finally {
uni.hideLoading();
}
}
}
};
</script>
<style scoped>
/* 样式保持不变 */
.fixed-box {
position: fixed;
right: 20rpx;
bottom: 200rpx;
z-index: 9999;
display: flex;
flex-direction: column;
align-items: center;
gap: 14rpx;
}
.btn-item {
width: 88rpx !important;
height: 88rpx !important;
border-radius: 50% !important;
background-color: #ffffff !important;
background-size: 60% 60% !important;
background-position: center !important;
background-repeat: no-repeat !important;
border: none !important;
padding: 0 !important;
margin: 0 !important;
display: flex !important;
justify-content: center !important;
align-items: center !important;
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
}
.btn-item::after {
border: none !important;
}
.unread-badge {
position: absolute;
top: -5rpx;
right: -5rpx;
background: #ff4544;
color: #fff;
border-radius: 20rpx;
min-width: 30rpx;
height: 30rpx;
line-height: 30rpx;
text-align: center;
font-size: 10rpx;
padding: 0 8rpx;
box-shadow: 0 2rpx 10rpx rgba(255, 73, 72, 0.3);
z-index: 1;
}
/* #ifdef MP-WEIXIN */
.unread-badge {
font-size: 20rpx;
}
/* #endif */
.ai-icon {
font-size: 40rpx;
}
</style>