Merge branch 'feat/personnel_channel' into dev/1.0
This commit is contained in:
@@ -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);
|
||||
}
|
||||
Reference in New Issue
Block a user