Files
lucky_shop/components/hover-nav/hover-nav.vue
2026-01-13 15:57:35 +08:00

341 lines
8.8 KiB
Vue
Raw 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 ? '400rpx' : '320rpx' }, customContainerStyle]">
<!-- 切换语言按钮 -->
<button
class="btn-item"
v-if="fixBtnShow && isLanguageSwitchEnabled"
@click="toggleLanguage()"
:style="[{ backgroundSize: '100% 100%' }, customButtonStyle]"
>
<text :style="customTextStyle">{{ currentLangDisplayName }}</text>
</button>
<!-- AI 智能助手 客服按钮根据 enableAIChat 决定 -->
<template v-if="fixBtnShow">
<!-- 优先显示 AI 助手如果启用 -->
<view
v-if="enableAIChat"
class="btn-item"
@click="openAIChat"
:style="{ backgroundImage: aiAgentimg ? `url(${aiAgentimg})` : '', backgroundSize: '100% 100%' }"
>
<text class="ai-icon" v-if="!aiAgentimg">🤖</text>
<view v-if="unreadCount > 0" class="unread-badge">
<text class="badge-text">{{ unreadCount > 99 ? '99+' : unreadCount }}</text>
</view>
</view>
<!-- 否则显示客服按钮 -->
<template v-else>
<!-- #ifdef MP-WEIXIN -->
<button
class="btn-item"
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 -->
<!-- #ifndef MP-WEIXIN -->
<button
class="btn-item"
hoverClass="none"
@click="openKefuSelectPopup"
:style="[{ backgroundImage: kefuimg ? `url(${kefuimg})` : '', backgroundSize: '100% 100%' }, customButtonStyle]"
>
<text class="icox icox-kefu" v-if="!kefuimg"></text>
<!-- <view>首页</view> -->
</button>
<!-- #endif -->
<view class="btn-item" v-if="fixBtnShow" @click="call()"
:style="[{ backgroundImage: 'url(' + (phoneimg ? phoneimg : '') + ')', backgroundSize: '100% 100%' }, customButtonStyle]">
<text class="iconfont icon-dianhua" v-if="!phoneimg"></text>
</view>
<!-- <view class="btn-item icon-xiala" v-if="fixBtnShow" @click="fixBtnShow ? (fixBtnShow = false) : (fixBtnShow = true)">
<text class="iconfont icon-unfold"></text>
</view>
<view class="btn-item switch" v-else :class="{ show: fixBtnShow }"
@click="fixBtnShow ? (fixBtnShow = false) : (fixBtnShow = true)">
<view class="">快捷</view>
<view>导航</view>
</view> -->
</view>
</template>
<script>
import { mapGetters } from 'vuex' // 去掉mapMutations直接用$store.commit
import { createCustomerService } from '@/common/js/customer-service.js';
export default {
name: 'hover-nav',
props: {
need: {
type: Boolean,
default: false
}
},
data() {
return {
pageCount: 0,
fixBtnShow: true,
tel: '',
kefuimg: '',
phoneimg: '',
shopInfo: null, // 店铺信息对象
// --- 语言切换相关 ---
currentLangIndex: 0, // 当前选中的语言索引
langIndexMap: {}, // 语言索引到语言值的映射
isLanguageSwitchEnabled: false, // 是否启用语言切换
// --- 其他 ---
};
},
created() {
// 初始化语言设置
this.initLanguage();
this.kefuimg = this.$util.getDefaultImage().kefu
this.phoneimg = this.$util.getDefaultImage().phone
this.pageCount = getCurrentPages().length;
// 从店铺信息中获取相关信息
uni.getStorage({
key: 'shopInfo',
success: (e) => {
console.log(`获取到的shopInfo:${JSON.stringify(e.data)}`)
this.shopInfo = e.data;
// 从店铺信息中获取手机号
this.tel = e.data.mobile
// 从店铺信息中获取是否启用语言切换
this.isLanguageSwitchEnabled = e.data.ischina;
}
})
},
computed: {
currentLangDisplayName() {
// 语言切换按钮显示名称当前语言为中文时显示EN否则显示CN
// 根据 langIndexMap 获取当前语言值
const lang = this.langIndexMap[this.currentLangIndex];
return lang == 'zh-cn' ? 'EN' : 'CN';
},
};
// 获取容器的自定义样式
customContainerStyle() {
// 只返回非空的样式属性,确保不覆盖原有的默认样式
return this.shopInfo?.floatingButton?.container || {};
data() {
return {
pageCount: 0,
fixBtnShow: true,
tel: '',
kefuimg: '',
phoneimg: '',
customerService: null,
buttonConfig: null,
kefuList: [
{ 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
}; },
// 获取按钮的自定义样式
customButtonStyle() {
// 只返回非空的样式属性,确保不覆盖原有的默认样式
return this.shopInfo?.floatingButton?.button || {};
},
// 获取文本的自定义样式
customTextStyle() {
// 只返回非空的样式属性,确保不覆盖原有的默认样式
return this.shopInfo?.floatingButton?.text || {};
}
},
methods: {
initLanguage() {
// 初始化语言列表
this.langList = this.$langConfig.list();
// 初始化语言索引映射
for (let i = 0; i < this.langList.length; i++) {
this.langIndexMap[i] = this.langList[i].value;
}
// 获取存储的语言设置
const savedLang = uni.getStorageSync('lang');
if (savedLang) {
for (let i = 0; i < this.langList.length; i++) {
if (this.langList[i].value == savedLang) {
this.currentLangIndex = i;
break;
}
}
} else {
this.currentLangIndex = 0;
}
},
//拨打电话
call() {
uni.makePhoneCall({
phoneNumber: this.tel + ''
})
},
toggleLanguage() {
// 切换语言索引
this.currentLangIndex = this.currentLangIndex == 0 ? 1 : 0;
const targetLang = this.langIndexMap[this.currentLangIndex];
// 获取当前页面路由
let currentRoute = this.$util.getCurrentRoute().path;
// 切换语言并重新加载当前页面
this.$langConfig.change(targetLang, currentRoute);
}
}
};
</script>
// 打开客服选择弹窗
openKefuSelectPopup() {
const kefuNames = this.kefuList.map(item => item.name);
wx.showActionSheet({
itemList: kefuNames,
success: (res) => {
this.selectedKefu = this.kefuList[res.tapIndex];
this.reinitCustomerService(this.selectedKefu);
this.handleSelectedKefu();
}
});
},
// 重新初始化客服实例
reinitCustomerService(kefu) {
this.customerService = createCustomerService(this, kefu);
this.buttonConfig = this.customerService.getButtonConfig();
},
}
// 执行选中的客服逻辑
handleSelectedKefu() {
const kefu = this.selectedKefu;
if (!kefu) return;
if (kefu.isOfficial) {
wx.openCustomerServiceConversation({ sessionFrom: 'weapp', showMessageCard: true });
} else if (kefu.id === 'custom-kefu') {
this.customerService.handleCustomerClick();
} else if (kefu.id === 'qyweixin-kefu') {
this.customerService.handleQyWeixinKefuClick();
}
},
// 打开AI聊天修复setAiUnreadCount的核心
openAIChat() {
if (this.enableAIChat) {
// 直接用$store.commit调用Vuex mutation绕过映射问题
this.$store.commit('setAiUnreadCount', 0);
}
this.$util.redirectTo('/pages_tool/ai-chat/index')
}
}
};
</script>
}
//悬浮按钮
.fixed-box {
position: fixed;
right: 0rpx;
bottom: 240rpx;
// #ifdef H5
bottom: 320rpx;
// #endif
z-index: 10;
border-radius: 120rpx;
padding: 20rpx 0;
display: flex;
justify-content: center;
flex-direction: column;
width: 100rpx;
box-sizing: border-box;
transition: 0.3s;
overflow: hidden;
.btn-item {
display: flex;
justify-content: center;
text-align: center;
flex-direction: column;
line-height: 1;
margin: 14rpx 0;
transition: 0.1s;
background: var(--hover-nav-bg-color);
color: var(--hover-nav-text-color);
border-radius: 40rpx;
width: 80rpx;
height: 80rpx;
padding: 0;
overflow: hidden;
text {
font-size: 28rpx;
}
.iconfont,
.icox {
font-size: 36rpx;
font-weight: bold;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
margin: 14rpx 0;
background: #fff;
border-radius: 50rpx;
width: 80rpx;
height: 80rpx;
padding: 0;
position: relative;
text {
font-size: 36rpx;
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 {
font-size: 40rpx;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
}
}
}
</style>