chore:替了hover
This commit is contained in:
@@ -42,6 +42,6 @@ const localDevConfig = ({
|
|||||||
uniacid: 2,
|
uniacid: 2,
|
||||||
domain: 'http://localhost:8050/',
|
domain: 'http://localhost:8050/',
|
||||||
},
|
},
|
||||||
})['2811']; // 选择要使用的环境配置
|
})['1']; // 选择要使用的环境配置
|
||||||
|
|
||||||
export default localDevConfig;
|
export default localDevConfig;
|
||||||
@@ -1,43 +1,57 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- 悬浮按钮 -->
|
<view v-if="pageCount == 1 || need" class="fixed-box"
|
||||||
<view v-if="pageCount == 1 || need" class="fixed-box" :style="[customContainerStyle, {
|
:style="[customContainerStyle, {
|
||||||
height: fixBtnShow ? '400rpx' : '320rpx',
|
height: containerHeight,
|
||||||
backgroundImage: bgUrl ? `url(${bgUrl})` : '',
|
backgroundImage: bgUrl ? `url( $ {bgUrl})` : '',
|
||||||
backgroundSize: 'cover'
|
backgroundSize: 'cover'
|
||||||
}]">
|
}]">
|
||||||
|
|
||||||
|
<!-- ✅ 统一客服入口(根据后台配置自动适配 AI / 企业微信 / 第三方等) -->
|
||||||
|
<!-- 微信官方客服需要使用 button open-type="contact" -->
|
||||||
|
<button
|
||||||
|
v-if="fixBtnShow && isWeappOfficialKefu"
|
||||||
|
class="btn-item common-bg"
|
||||||
|
open-type="contact"
|
||||||
|
:style="{ backgroundImage: currentKefuImg ? `url( $ {currentKefuImg})` : '', backgroundSize: '100% 100%' }"
|
||||||
|
>
|
||||||
|
<text class="ai-icon" v-if="!currentKefuImg">🤖</text>
|
||||||
|
</button>
|
||||||
|
<!-- 其他类型客服使用普通 view -->
|
||||||
|
<view
|
||||||
|
v-else-if="fixBtnShow"
|
||||||
|
class="btn-item common-bg"
|
||||||
|
@click="handleUnifiedKefuClick"
|
||||||
|
:style="{ backgroundImage: currentKefuImg ? `url( $ {currentKefuImg})` : '', backgroundSize: '100% 100%' }"
|
||||||
|
>
|
||||||
|
<text class="ai-icon" v-if="!currentKefuImg">🤖</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- ✅ 新增:小程序系统客服按钮(当附加设置开启时显示) -->
|
||||||
|
<button
|
||||||
|
v-if="fixBtnShow && showWeappSystemKefu"
|
||||||
|
class="btn-item common-bg"
|
||||||
|
open-type="contact"
|
||||||
|
:style="{ backgroundImage: currentKefuImg ? `url( $ {currentKefuImg})` : '', backgroundSize: '100% 100%' }"
|
||||||
|
>
|
||||||
|
<text class="ai-icon" v-if="!currentKefuImg">💬</text>
|
||||||
|
</button>
|
||||||
|
|
||||||
<!-- 中英文切换按钮 -->
|
<!-- 中英文切换按钮 -->
|
||||||
<view v-if="isLanguageSwitchEnabled && fixBtnShow" class="btn-item common-bg" @click="toggleLanguage">
|
<view
|
||||||
|
v-if="isLanguageSwitchEnabled && fixBtnShow"
|
||||||
|
class="btn-item common-bg"
|
||||||
|
@click="toggleLanguage"
|
||||||
|
>
|
||||||
<text>{{ currentLangDisplayName }}</text>
|
<text>{{ currentLangDisplayName }}</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- AI 智能助手 -->
|
|
||||||
<view v-if="fixBtnShow && enableAIChat" class="btn-item common-bg" @click="openAIChat"
|
|
||||||
:style="{ backgroundImage: aiAgentimg ? `url(${aiAgentimg})` : '', backgroundSize: '100% 100%' }">
|
|
||||||
<text class="ai-icon" v-if="!aiAgentimg">🤖</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 微信小程序客服按钮 -->
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<button class="btn-item common-bg" hoverClass="none" openType="contact" sessionFrom="weapp" showMessageCard="true"
|
|
||||||
:style="[{ backgroundImage: kefuimg ? `url(${kefuimg})` : '', backgroundSize: '100% 100%' }, customButtonStyle]">
|
|
||||||
<text class="icox icox-kefu" v-if="!kefuimg"></text>
|
|
||||||
</button>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<!-- 普通客服(仅当未启用 AI 时显示) -->
|
|
||||||
<!-- #ifdef H5 -->
|
|
||||||
<template v-if="fixBtnShow">
|
|
||||||
<button class="btn-item common-bg" hoverClass="none" @click="openCustomerSelectPopup"
|
|
||||||
:style="[{ backgroundImage: kefuimg ? `url(${kefuimg})` : '', backgroundSize: '100% 100%' }, customButtonStyle]">
|
|
||||||
<text class="icox icox-kefu" v-if="!kefuimg"></text>
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<!-- 电话按钮(始终显示) -->
|
<!-- 电话按钮(始终显示) -->
|
||||||
<view v-if="fixBtnShow" class="btn-item common-bg" @click="call()"
|
<view
|
||||||
:style="[{ backgroundImage: phoneimg ? `url(${phoneimg})` : '', backgroundSize: '100% 100%' }, customButtonStyle]">
|
v-if="fixBtnShow"
|
||||||
|
class="btn-item common-bg"
|
||||||
|
@click="call()"
|
||||||
|
:style="[{ backgroundImage: phoneimg ? `url( $ {phoneimg})` : '', backgroundSize: '100% 100%' }, customButtonStyle]"
|
||||||
|
>
|
||||||
<text class="iconfont icon-dianhua" v-if="!phoneimg"></text>
|
<text class="iconfont icon-dianhua" v-if="!phoneimg"></text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -56,16 +70,18 @@ export default {
|
|||||||
return {
|
return {
|
||||||
pageCount: 0,
|
pageCount: 0,
|
||||||
fixBtnShow: true,
|
fixBtnShow: true,
|
||||||
|
|
||||||
shopInfo: null,
|
shopInfo: null,
|
||||||
currentLangIndex: 0,
|
currentLangIndex: 0,
|
||||||
langIndexMap: {},
|
langIndexMap: {},
|
||||||
|
kefuList: [
|
||||||
customerService: null,
|
{ id: 'weixin-official', name: '微信官方客服', isOfficial: true, type: 'weapp' },
|
||||||
|
{ id: 'custom-kefu', name: '自定义在线客服', isOfficial: false, type: 'custom' },
|
||||||
|
{ id: 'qyweixin-kefu', name: '企业微信客服', isOfficial: false, type: 'qyweixin' }
|
||||||
|
],
|
||||||
|
selectedKefu: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
// 安全读取 shopInfo 中的字段,避免 undefined 报错
|
|
||||||
bgUrl() {
|
bgUrl() {
|
||||||
return this.shopInfo?.bgUrl || '';
|
return this.shopInfo?.bgUrl || '';
|
||||||
},
|
},
|
||||||
@@ -73,10 +89,10 @@ export default {
|
|||||||
return this.shopInfo?.aiAgentimg || '';
|
return this.shopInfo?.aiAgentimg || '';
|
||||||
},
|
},
|
||||||
kefuimg() {
|
kefuimg() {
|
||||||
return this.shopInfo?.kefuimg || this.$util.getDefaultImage().kefu;
|
return this.shopInfo?.kefuimg || this. $util.getDefaultImage().kefu;
|
||||||
},
|
},
|
||||||
phoneimg() {
|
phoneimg() {
|
||||||
return this.shopInfo?.phoneimg || this.$util.getDefaultImage().phone;
|
return this.shopInfo?.phoneimg || this. $util.getDefaultImage().phone;
|
||||||
},
|
},
|
||||||
tel() {
|
tel() {
|
||||||
return this.shopInfo?.mobile || '';
|
return this.shopInfo?.mobile || '';
|
||||||
@@ -84,9 +100,6 @@ export default {
|
|||||||
isLanguageSwitchEnabled() {
|
isLanguageSwitchEnabled() {
|
||||||
return !!this.shopInfo?.ischina;
|
return !!this.shopInfo?.ischina;
|
||||||
},
|
},
|
||||||
enableAIChat() {
|
|
||||||
return !!this.shopInfo?.enableAIChat;
|
|
||||||
},
|
|
||||||
currentLangDisplayName() {
|
currentLangDisplayName() {
|
||||||
const lang = this.langIndexMap[this.currentLangIndex];
|
const lang = this.langIndexMap[this.currentLangIndex];
|
||||||
return lang === 'zh-cn' ? 'EN' : 'CN';
|
return lang === 'zh-cn' ? 'EN' : 'CN';
|
||||||
@@ -96,30 +109,87 @@ export default {
|
|||||||
},
|
},
|
||||||
customButtonStyle() {
|
customButtonStyle() {
|
||||||
return this.shopInfo?.floatingButton?.button || {};
|
return this.shopInfo?.floatingButton?.button || {};
|
||||||
|
},
|
||||||
|
unreadCount() {
|
||||||
|
return this. $store.state.aiUnreadCount || 0;
|
||||||
|
},
|
||||||
|
|
||||||
|
// ✅ 新增:根据当前客服类型动态返回图标
|
||||||
|
currentKefuImg() {
|
||||||
|
if (!this.shopInfo) return '';
|
||||||
|
|
||||||
|
const customerService = createCustomerService(this);
|
||||||
|
const config = customerService.getPlatformConfig();
|
||||||
|
|
||||||
|
if (config?.type === 'aikefu') {
|
||||||
|
return this.aiAgentimg;
|
||||||
|
} else if (config?.type === 'wxwork' || config?.type === 'qyweixin') {
|
||||||
|
// 企业微信客服专用图标
|
||||||
|
return this.aiAgentimg;
|
||||||
|
}
|
||||||
|
// 默认客服图标
|
||||||
|
return this.kefuimg;
|
||||||
|
},
|
||||||
|
// ✅ 新增:判断是否为微信官方客服
|
||||||
|
isWeappOfficialKefu() {
|
||||||
|
if (!this.shopInfo) return false;
|
||||||
|
const customerService = createCustomerService(this);
|
||||||
|
const config = customerService.getPlatformConfig();
|
||||||
|
return config?.type === 'weapp';
|
||||||
|
},
|
||||||
|
// ✅ 新增:判断是否需要同时显示小程序系统客服
|
||||||
|
showWeappSystemKefu() {
|
||||||
|
if (!this.shopInfo) return false;
|
||||||
|
const customerService = createCustomerService(this);
|
||||||
|
const config = customerService.getPlatformConfig();
|
||||||
|
// 检查附加设置是否开启了同时显示小程序系统客服,且当前客服类型不是小程序系统客服
|
||||||
|
return (config?.show_system_service === true || config?.show_system_service === '1') && config?.type !== 'weapp';
|
||||||
|
},
|
||||||
|
//根据显示的按钮数量动态计算容器高度
|
||||||
|
containerHeight() {
|
||||||
|
if (!this.fixBtnShow) return '320rpx';
|
||||||
|
|
||||||
|
let buttonCount = 1;
|
||||||
|
if (this.isLanguageSwitchEnabled) buttonCount++;
|
||||||
|
if (this.showWeappSystemKefu) buttonCount++;
|
||||||
|
buttonCount++;
|
||||||
|
const totalRpx = 94 * buttonCount - 14;
|
||||||
|
const pxValue = Math.round(totalRpx * 0.5);
|
||||||
|
|
||||||
|
return ` $ {pxValue}px`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
shopInfo: {
|
||||||
|
handler(newVal) {
|
||||||
|
// 可在此添加额外逻辑(如埋点、通知等),当前无需操作
|
||||||
|
},
|
||||||
|
immediate: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.customerService = createCustomerService(this);
|
|
||||||
this.initLanguage();
|
this.initLanguage();
|
||||||
|
this.pageCount = getCurrentPages().length;
|
||||||
|
|
||||||
uni.getStorage({
|
uni.getStorage({
|
||||||
key: 'shopInfo',
|
key: 'shopInfo',
|
||||||
success: (e) => {
|
success: (e) => {
|
||||||
|
console.log('【调试】当前 shopInfo:', e.data);
|
||||||
this.shopInfo = e.data;
|
this.shopInfo = e.data;
|
||||||
|
},
|
||||||
|
fail: () => {
|
||||||
|
console.warn('未获取到 shopInfo,使用默认设置');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
/**
|
|
||||||
* 初始化多语言配置
|
|
||||||
*/
|
|
||||||
initLanguage() {
|
initLanguage() {
|
||||||
this.langList = this.$langConfig.list();
|
this.langList = this. $langConfig.list();
|
||||||
this.langIndexMap = {};
|
this.langIndexMap = {};
|
||||||
for (let i = 0; i < this.langList.length; i++) {
|
for (let i = 0; i < this.langList.length; i++) {
|
||||||
this.langIndexMap[i] = this.langList[i].value;
|
this.langIndexMap[i] = this.langList[i].value;
|
||||||
}
|
}
|
||||||
const savedLang = this.$langConfig.getCurrentLocale();
|
const savedLang = uni.getStorageSync('lang');
|
||||||
if (savedLang) {
|
if (savedLang) {
|
||||||
for (let i = 0; i < this.langList.length; i++) {
|
for (let i = 0; i < this.langList.length; i++) {
|
||||||
if (this.langList[i].value === savedLang) {
|
if (this.langList[i].value === savedLang) {
|
||||||
@@ -131,43 +201,118 @@ export default {
|
|||||||
this.currentLangIndex = 0;
|
this.currentLangIndex = 0;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* 电话联系客服
|
|
||||||
*/
|
|
||||||
call() {
|
call() {
|
||||||
this.customerService.makePhoneCall(this.tel);
|
if (this.tel) {
|
||||||
|
uni.makePhoneCall({ phoneNumber: this.tel + '' });
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: '暂无联系电话', icon: 'none' });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* 切换中英文语言,并刷新当前页面(保留所有参数)
|
|
||||||
*/
|
|
||||||
toggleLanguage() {
|
toggleLanguage() {
|
||||||
this.currentLangIndex = this.currentLangIndex === 0 ? 1 : 0;
|
this.currentLangIndex = this.currentLangIndex === 0 ? 1 : 0;
|
||||||
const targetLang = this.langIndexMap[this.currentLangIndex];
|
const targetLang = this.langIndexMap[this.currentLangIndex];
|
||||||
|
this. $langConfig.change(targetLang);
|
||||||
|
|
||||||
// 调用语言切换逻辑(设置 storage + 清空缓存)
|
if (uni.getSystemInfoSync().platform === 'browser') {
|
||||||
this.$langConfig.change(targetLang);
|
setTimeout(() => {
|
||||||
|
window.location.reload();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// ✅ 核心方法:统一客服入口
|
||||||
* 打开 AI 智能助手
|
handleUnifiedKefuClick() {
|
||||||
*/
|
const customerService = createCustomerService(this);
|
||||||
openAIChat() {
|
const validation = customerService.validateConfig();
|
||||||
this.$util.redirectTo(this.$util.AI_CHAT_PAGE_URL);
|
|
||||||
|
console.log('【客服配置验证】', validation);
|
||||||
|
|
||||||
|
if (!validation.isValid) {
|
||||||
|
console.error('客服配置无效:', validation.errors);
|
||||||
|
uni.showToast({ title: '客服暂不可用', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (validation.warnings.length > 0) {
|
||||||
|
console.warn('客服配置警告:', validation.warnings);
|
||||||
|
}
|
||||||
|
|
||||||
|
const platformConfig = customerService.getPlatformConfig();
|
||||||
|
console.log('【当前客服配置】', platformConfig);
|
||||||
|
|
||||||
|
// 检查企业微信配置
|
||||||
|
if (platformConfig.type === 'wxwork') {
|
||||||
|
const wxworkConfig = customerService.getWxworkConfig();
|
||||||
|
console.log('【企业微信配置】', wxworkConfig);
|
||||||
|
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
if (!wxworkConfig?.enable || !wxworkConfig?.contact_url) {
|
||||||
|
console.warn('企业微信配置不完整,使用原生客服');
|
||||||
|
uni.showToast({ title: '企业微信配置不完整', icon: 'none' });
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef H5
|
||||||
|
if (!wxworkConfig?.contact_url && !platformConfig.wxwork_url) {
|
||||||
|
console.error('企业微信链接未配置');
|
||||||
|
uni.showToast({ title: '企业微信链接未配置', icon: 'none' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// 直接调用统一处理方法,由 CustomerService 内部根据配置路由
|
||||||
|
try {
|
||||||
|
customerService.handleCustomerClick({
|
||||||
|
sendMessageTitle: '来自悬浮按钮的咨询',
|
||||||
|
sendMessagePath: '/pages/index/index'
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error('客服处理失败:', error);
|
||||||
|
uni.showToast({ title: '打开客服失败', icon: 'none' });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
// 以下方法保留用于 actionSheet(如仍需手动选择)
|
||||||
* 打开客服选择对话框
|
openKefuSelectPopup() {
|
||||||
*/
|
const kefuNames = this.kefuList.map(item => item.name);
|
||||||
openCustomerSelectPopup() {
|
uni.showActionSheet({
|
||||||
this.customerService.openCustomerSelectPopupDialog();
|
itemList: kefuNames,
|
||||||
|
success: (res) => {
|
||||||
|
this.selectedKefu = this.kefuList[res.tapIndex];
|
||||||
|
const cs = createCustomerService(this, this.selectedKefu);
|
||||||
|
if (this.selectedKefu.isOfficial) {
|
||||||
|
uni.openCustomerServiceConversation({
|
||||||
|
sessionFrom: 'weapp',
|
||||||
|
showMessageCard: true
|
||||||
|
});
|
||||||
|
} else if (this.selectedKefu.id === 'qyweixin-kefu') {
|
||||||
|
// 处理企业微信客服
|
||||||
|
if (uni.getSystemInfoSync().platform === 'wechat') {
|
||||||
|
// 小程序端:跳转到企业微信客服
|
||||||
|
uni.navigateTo({
|
||||||
|
url: '/pages_tool/qyweixin-kefu/index'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// H5端:跳转到企业微信链接
|
||||||
|
const qyweixinUrl = this.shopInfo.qyweixinUrl; // 后端返回的企业微信链接
|
||||||
|
if (qyweixinUrl) {
|
||||||
|
window.location.href = qyweixinUrl;
|
||||||
|
} else {
|
||||||
|
uni.showToast({ title: '企业微信客服未配置', icon: 'none' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cs.handleCustomerClick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style scoped>
|
||||||
.fixed-box {
|
.fixed-box {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 0rpx;
|
right: 0rpx;
|
||||||
@@ -188,27 +333,16 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.btn-item {
|
.btn-item {
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
text-align: center;
|
|
||||||
flex-direction: column;
|
|
||||||
line-height: 1;
|
|
||||||
margin: 14rpx 0;
|
|
||||||
transition: 0.1s;
|
|
||||||
color: var(--hover-nav-text-color);
|
|
||||||
border-radius: 40rpx;
|
|
||||||
width: 80rpx;
|
width: 80rpx;
|
||||||
height: 80rpx;
|
height: 80rpx;
|
||||||
padding: 0;
|
background: #fff;
|
||||||
overflow: hidden;
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 14rpx 0;
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 定义共同的背景颜色 */
|
|
||||||
.common-bg {
|
|
||||||
background-color: var(--hover-nav-bg-color);
|
|
||||||
/* 使用变量以保持一致性 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-item text {
|
.btn-item text {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
}
|
}
|
||||||
@@ -223,6 +357,7 @@ export default {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 14rpx 0;
|
margin: 14rpx 0;
|
||||||
|
background: #fff;
|
||||||
border-radius: 50rpx;
|
border-radius: 50rpx;
|
||||||
width: 80rpx;
|
width: 80rpx;
|
||||||
height: 80rpx;
|
height: 80rpx;
|
||||||
@@ -236,7 +371,21 @@ export default {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.unread-badge {
|
||||||
|
position: absolute;
|
||||||
|
top: -5rpx;
|
||||||
|
right: -5rpx;
|
||||||
|
background-color: #ff4544;
|
||||||
|
color: white;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
min-width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
font-size: 20rpx;
|
||||||
|
line-height: 30rpx;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0 8rpx;
|
||||||
|
box-shadow: 0 2rpx 10rpx rgba(255, 69, 68, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
.ai-icon {
|
.ai-icon {
|
||||||
font-size: 40rpx;
|
font-size: 40rpx;
|
||||||
|
|||||||
Reference in New Issue
Block a user