Merge branch 'feat/personnel_channel' into dev/1.0

This commit is contained in:
2026-01-16 10:16:40 +08:00
parent 2896817435
commit dd4176998b
11 changed files with 571 additions and 591 deletions

View File

@@ -2,13 +2,68 @@
* 客服统一处理服务
* 整合各种客服方式,提供统一的调用接口
*/
export class CustomerService {
constructor(vueInstance, externalConfig = null) {
class CustomerService {
constructor(vueInstance, externalConfig = {}) {
if (!vueInstance.$lang) {
throw new Error('CustomerService 必须在 Vue 实例中初始化');
}
this.vm = vueInstance;
this.externalConfig = externalConfig; // 外部传入的最新配置(优先级最高)
this.latestPlatformConfig = null;
}
getSupoortKeFuList() {
if (!this.vm) return [];
const vm = this.vm;
return [
{
id: 'weixin-official',
name: vm.$lang('customer.weChatKefu'),
isOfficial: true,
type: 'weapp'
},
{
id: 'custom-kefu',
name: vm.$lang('customer.systemKefu'),
isOfficial: false
},
{
id: 'qyweixin-kefu',
name: vm.$lang('customer.weChatWorkKefu'),
isOfficial: false
},
]
}
/**
* 打开客服选择弹窗
*/
openCustomerSelectPopupDialog() {
const kefu_list = this.getSupoortKeFuList();
const kefuNames = kefu_list.map(item => item.name);
uni.showActionSheet({
itemList: kefuNames,
success: (res) => {
const kefu = kefu_list[res.tapIndex];
this.externalConfig = kefu ?? this.externalConfig ?? {};
if (kefu.isOfficial) {
uni.openCustomerServiceConversation({
sessionFrom: 'weapp',
showMessageCard: true
});
} else if (kefu.id === 'custom-kefu') {
this.handleCustomerClick();
} else if (kefu.id === 'qyweixin-kefu') {
this.handleQyWeixinKefuClick();
}
}
});
}
/**
* 强制刷新配置(支持传入外部配置)
* @param {Object} externalConfig 外部最新配置
@@ -82,7 +137,7 @@ export class CustomerService {
validateConfig() {
const config = this.getPlatformConfig();
const wxworkConfig = this.getWxworkConfig();
const result = {
isValid: true,
errors: [],
@@ -122,35 +177,11 @@ export class CustomerService {
}
/**
* 跳转到Dify客服页面
* 跳转到AI客服页面
*/
openDifyService() {
try {
if (this.vm.setAiUnreadCount) {
this.vm.setAiUnreadCount(0);
}
// 强制跳转,忽略框架层的封装
uni.redirectTo({
url: '/pages_tool/ai-chat/index',
fail: (err) => {
// 兜底使用window.location跳转H5
// #ifdef H5
window.location.href = '/pages_tool/ai-chat/index';
// #endif
console.error('跳转Dify客服失败:', err);
uni.showToast({
title: '跳转客服失败',
icon: 'none'
});
}
});
} catch (e) {
console.error('跳转Dify客服异常:', e);
uni.showToast({
title: '跳转客服失败',
icon: 'none'
});
}
openAIKeFuService() {
const vm = this.vm;
vm.$util.redirectTo(vm.$util.AI_CHAT_PAGE_URL);
}
/**
@@ -170,7 +201,7 @@ export class CustomerService {
}
const config = this.getPlatformConfig();
const { niushop = {}, sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options;
const { niushop = {}, sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options || {};
if (config.type === 'none') {
this.showNoServicePopup();
@@ -180,7 +211,7 @@ export class CustomerService {
// 核心分支根据最新的type处理
switch (config.type) {
case 'aikefu':
this.openDifyService();
this.openAIKeFuService();
break;
case 'wxwork':
this.openWxworkService(false, config, options);
@@ -211,7 +242,7 @@ export class CustomerService {
openWxworkService(useOriginalService = false, servicerConfig = null, options = {}) {
const config = servicerConfig || this.getPlatformConfig();
const wxworkConfig = this.getWxworkConfig();
const { sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options;
const { sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options || {};
// #ifdef MP-WEIXIN
if (wxworkConfig?.enable && wxworkConfig?.contact_url && !useOriginalService) {
@@ -292,7 +323,7 @@ export class CustomerService {
* @param {Object} options 选项参数
*/
handleCustomWeappService(config, options = {}) {
const { sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options;
const { sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options || {};
if (config.customServiceUrl) {
let url = config.customServiceUrl;
@@ -300,11 +331,11 @@ export class CustomerService {
if (sendMessageTitle) params.push(`title=${encodeURIComponent(sendMessageTitle)}`);
if (sendMessagePath) params.push(`path=${encodeURIComponent(sendMessagePath)}`);
if (sendMessageImg) params.push(`img=${encodeURIComponent(sendMessageImg)}`);
if (params.length > 0) {
url += (url.includes('?') ? '&' : '?') + params.join('&');
}
uni.navigateTo({
url: url,
fail: (err) => {
@@ -328,7 +359,7 @@ export class CustomerService {
// #ifdef H5
window.open(config.thirdPartyServiceUrl, '_blank');
// #endif
// #ifdef MP-WEIXIN
if (config.thirdPartyMiniAppId) {
wx.navigateToMiniProgram({
@@ -381,7 +412,7 @@ export class CustomerService {
console.log('支付宝小程序客服', config);
switch (config.type) {
case 'aikefu':
this.openDifyService();
this.openAIKeFuService();
break;
case 'third':
this.openThirdService(config);
@@ -395,26 +426,29 @@ export class CustomerService {
/**
* 拨打电话
*/
makePhoneCall() {
this.vm.$api.sendRequest({
url: '/api/site/shopcontact',
success: res => {
if (res.code === 0 && res.data?.mobile) {
makePhoneCall(mobileNumber) {
if (mobileNumber) {
return uni.makePhoneCall({
phoneNumber: mobileNumber
});
}
// 从缓存中获取电话信息
uni.getStorage({
key: 'shopInfo',
success: (res) => {
const shopInfo = res.data;
const mobile = shopInfo?.mobile ?? '';
if (mobile) {
uni.makePhoneCall({
phoneNumber: res.data.mobile
});
phoneNumber: mobile
});
} else {
uni.showToast({
title: '暂无客服电话',
icon: 'none'
});
});
}
},
fail: () => {
uni.showToast({
title: '获取客服电话失败',
icon: 'none'
});
}
});
}
@@ -424,8 +458,8 @@ export class CustomerService {
*/
showNoServicePopup() {
const siteInfo = this.vm.$store.state.siteInfo || {};
const message = siteInfo?.site_tel
? `请联系客服,客服电话是${siteInfo.site_tel}`
const message = siteInfo?.site_tel
? `请联系客服,客服电话是${siteInfo.site_tel}`
: '抱歉,商家暂无客服,请线下联系';
uni.showModal({
@@ -506,6 +540,6 @@ export class CustomerService {
* @param {Object} externalConfig 外部最新配置
* @returns {CustomerService} 客服服务实例
*/
export function createCustomerService(vueInstance, externalConfig = null) {
export function createCustomerService(vueInstance, externalConfig = {}) {
return new CustomerService(vueInstance, externalConfig);
}